Skip to content

Commit 8e5c8ee

Browse files
Merge pull request #93 from duynguyenhoang/feature/get_permalink
Get permalink and put it into chat input
2 parents 577dec7 + 43243f0 commit 8e5c8ee

File tree

9 files changed

+166
-135
lines changed

9 files changed

+166
-135
lines changed

README.md

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -103,24 +103,30 @@ You can use <kbd>ctrl k</kbd> (or your custom shortcut) to navigate in your DMs
103103

104104
You can use <kbd>ctrl d</kbd> (or your custom shortcut) to set snooze time.
105105

106+
### Get permalink
107+
108+
Focus on message and press <kbd>r</kbd> (or your custom shortcut) to get permalink (Quote message) and it will be put into your chat box.
109+
106110
### Default keybindings
107111
```json
108112
{
109-
"keymap": {
110-
"cursor_down": "j",
111-
"cursor_left": "h",
112-
"cursor_right":"l",
113-
"cursor_up": "k",
114-
"delete_message": "d",
115-
"edit_message": "e",
116-
"go_to_chatbox": "c",
117-
"go_to_profile": "p",
118-
"go_to_sidebar": "esc",
119-
"open_quick_switcher": "ctrl k",
120-
"quit_application": "q",
121-
"set_edit_topic_mode": "t",
122-
"set_insert_mode": "i",
123-
"yank_message": "y"
113+
"keymap": {
114+
"cursor_down": "j",
115+
"cursor_left": "h",
116+
"cursor_right": "l",
117+
"cursor_up": "k",
118+
"delete_message": "d",
119+
"edit_message": "e",
120+
"go_to_chatbox": "c",
121+
"go_to_profile": "p",
122+
"go_to_sidebar": "esc",
123+
"open_quick_switcher": "ctrl k",
124+
"quit_application": "q",
125+
"set_edit_topic_mode": "t",
126+
"set_insert_mode": "i",
127+
"yank_message": "y",
128+
"get_permalink": "r",
129+
"set_snooze": "ctrl d"
124130
}
125131
}
126132
```

app.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
import urwid
1313
from datetime import datetime
1414
from sclack.components import Attachment, Channel, ChannelHeader, ChatBox, Dm
15-
from sclack.components import Indicators, MarkdownText, Message, MessageBox
15+
from sclack.components import Indicators, MarkdownText, MessageBox
16+
from sclack.component.message import Message
1617
from sclack.components import NewMessagesDivider, Profile, ProfileSideBar
1718
from sclack.components import Reaction, SideBar, TextDivider
1819
from sclack.components import User, Workspaces
@@ -314,6 +315,16 @@ def edit_message(self, widget, user_id, ts, original_text):
314315
self.chatbox.message_box.text = original_text
315316
widget.set_edit_mode()
316317

318+
def get_permalink(self, widget, channel_id, ts):
319+
try:
320+
permalink = self.store.get_permalink(channel_id, ts)
321+
if permalink and permalink.get('permalink'):
322+
text = permalink.get('permalink')
323+
self.set_insert_mode()
324+
self.chatbox.message_box.text = text
325+
except:
326+
pass
327+
317328
def delete_message(self, widget, user_id, ts):
318329
if self.store.state.auth['user_id'] == user_id:
319330
if self.store.delete_message(self.store.state.channel['id'], ts)['ok']:
@@ -487,6 +498,7 @@ def render_message(self, message, channel_id=None):
487498
self.lazy_load_images(files, message)
488499

489500
urwid.connect_signal(message, 'edit_message', self.edit_message)
501+
urwid.connect_signal(message, 'get_permalink', self.get_permalink)
490502
urwid.connect_signal(message, 'go_to_profile', self.go_to_profile)
491503
urwid.connect_signal(message, 'go_to_sidebar', self.go_to_sidebar)
492504
urwid.connect_signal(message, 'delete_message', self.delete_message)

config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"set_edit_topic_mode": "t",
1717
"set_insert_mode": "i",
1818
"yank_message": "y",
19+
"get_permalink": "r",
1920
"set_snooze": "ctrl d"
2021
},
2122
"sidebar": {

sclack/component/message.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import re
2+
3+
import urwid
4+
import pyperclip
5+
import webbrowser
6+
from sclack.store import Store
7+
from sclack.component.time import Time
8+
9+
10+
class Message(urwid.AttrMap):
11+
__metaclass__ = urwid.MetaSignals
12+
signals = [
13+
'delete_message',
14+
'edit_message',
15+
'get_permalink',
16+
'go_to_profile',
17+
'go_to_sidebar',
18+
'quit_application',
19+
'set_insert_mode',
20+
'mark_read',
21+
]
22+
23+
def __init__(self, ts, channel_id, user, text, indicators, reactions=(), attachments=()):
24+
self.ts = ts
25+
self.channel_id = channel_id
26+
self.user_id = user.id
27+
self.markdown_text = text
28+
self.original_text = text.original_text
29+
self.text_widget = urwid.WidgetPlaceholder(text)
30+
main_column = [urwid.Columns([('pack', user), self.text_widget])]
31+
main_column.extend(attachments)
32+
self._file_index = len(main_column)
33+
if reactions:
34+
main_column.append(urwid.Columns([
35+
('pack', reaction) for reaction in reactions
36+
]))
37+
self.main_column = urwid.Pile(main_column)
38+
columns = [
39+
('fixed', 7, Time(ts)),
40+
self.main_column,
41+
('fixed', indicators.size, indicators)
42+
]
43+
self.contents = urwid.Columns(columns)
44+
super(Message, self).__init__(self.contents, None, {
45+
None: 'active_message',
46+
'message': 'active_message'
47+
})
48+
49+
def keypress(self, size, key):
50+
keymap = Store.instance.config['keymap']
51+
52+
if key == keymap['delete_message']:
53+
urwid.emit_signal(self, 'delete_message', self, self.user_id, self.ts)
54+
return True
55+
elif key == keymap['edit_message']:
56+
urwid.emit_signal(self, 'edit_message', self, self.user_id, self.ts, self.original_text)
57+
return True
58+
elif key == keymap['go_to_profile']:
59+
urwid.emit_signal(self, 'go_to_profile', self.user_id)
60+
return True
61+
elif key == keymap['go_to_sidebar'] or key == keymap['cursor_left']:
62+
urwid.emit_signal(self, 'go_to_sidebar')
63+
return True
64+
elif key == keymap['quit_application']:
65+
urwid.emit_signal(self, 'quit_application')
66+
return True
67+
elif key == keymap['set_insert_mode']:
68+
urwid.emit_signal(self, 'set_insert_mode')
69+
return True
70+
elif key == keymap['yank_message']:
71+
try:
72+
pyperclip.copy(self.original_text)
73+
except pyperclip.PyperclipException:
74+
pass
75+
return True
76+
elif key == keymap['get_permalink']:
77+
# FIXME
78+
urwid.emit_signal(self, 'get_permalink', self, self.channel_id, self.ts)
79+
elif key == 'enter':
80+
browser_name = Store.instance.config['features']['browser']
81+
82+
for item in self.markdown_text.markup:
83+
type, value = item
84+
85+
if type == 'link' and re.compile(r'^https?://').search(value):
86+
browser_instance = webbrowser if browser_name == '' else webbrowser.get(browser_name)
87+
browser_instance.open(value, new=2)
88+
break
89+
90+
return super(Message, self).keypress(size, key)
91+
92+
def set_text(self, text):
93+
self.text_widget.original_widget = text
94+
95+
def set_edit_mode(self):
96+
self.set_attr_map({
97+
None: 'editing_message',
98+
'message': 'editing_message'
99+
})
100+
101+
def unset_edit_mode(self):
102+
self.set_attr_map({
103+
None: None,
104+
'message': None
105+
})
106+
107+
def selectable(self):
108+
return True
109+
110+
@property
111+
def file(self):
112+
return None
113+
114+
@file.setter
115+
def file(self, file):
116+
self.main_column.contents.insert(self._file_index, (file, ('pack', 1)))

sclack/component/time.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from datetime import datetime
2+
3+
import urwid
4+
5+
6+
class Time(urwid.Text):
7+
def __init__(self, timestamp):
8+
time = datetime.fromtimestamp(float(timestamp)).strftime('%H:%M')
9+
super(Time, self).__init__(('datetime', ' {} '.format(time)))

sclack/components.py

Lines changed: 0 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -517,110 +517,6 @@ def __init__(self, is_edited=False, is_starred=False):
517517
super(Indicators, self).__init__(indicators)
518518

519519

520-
class Message(urwid.AttrMap):
521-
__metaclass__ = urwid.MetaSignals
522-
signals = [
523-
'delete_message',
524-
'edit_message',
525-
'go_to_profile',
526-
'go_to_sidebar',
527-
'quit_application',
528-
'set_insert_mode',
529-
'mark_read',
530-
]
531-
532-
def __init__(self, ts, channel_id, user, text, indicators, reactions=(), attachments=()):
533-
self.ts = ts
534-
self.channel_id = channel_id
535-
self.user_id = user.id
536-
self.markdown_text = text
537-
self.original_text = text.original_text
538-
self.text_widget = urwid.WidgetPlaceholder(text)
539-
main_column = [urwid.Columns([('pack', user), self.text_widget])]
540-
main_column.extend(attachments)
541-
self._file_index = len(main_column)
542-
if reactions:
543-
main_column.append(urwid.Columns([
544-
('pack', reaction) for reaction in reactions
545-
]))
546-
self.main_column = urwid.Pile(main_column)
547-
columns = [
548-
('fixed', 7, Time(ts)),
549-
self.main_column,
550-
('fixed', indicators.size, indicators)
551-
]
552-
self.contents = urwid.Columns(columns)
553-
super(Message, self).__init__(self.contents, None, {
554-
None: 'active_message',
555-
'message': 'active_message'
556-
})
557-
558-
def keypress(self, size, key):
559-
keymap = Store.instance.config['keymap']
560-
561-
if key == keymap['delete_message']:
562-
urwid.emit_signal(self, 'delete_message', self, self.user_id, self.ts)
563-
return True
564-
elif key == keymap['edit_message']:
565-
urwid.emit_signal(self, 'edit_message', self, self.user_id, self.ts, self.original_text)
566-
return True
567-
elif key == keymap['go_to_profile']:
568-
urwid.emit_signal(self, 'go_to_profile', self.user_id)
569-
return True
570-
elif key == keymap['go_to_sidebar'] or key == keymap['cursor_left']:
571-
urwid.emit_signal(self, 'go_to_sidebar')
572-
return True
573-
elif key == keymap['quit_application']:
574-
urwid.emit_signal(self, 'quit_application')
575-
return True
576-
elif key == keymap['set_insert_mode']:
577-
urwid.emit_signal(self, 'set_insert_mode')
578-
return True
579-
elif key == keymap['yank_message']:
580-
try:
581-
pyperclip.copy(self.original_text)
582-
except pyperclip.PyperclipException:
583-
pass
584-
return True
585-
elif key == 'enter':
586-
browser_name = Store.instance.config['features']['browser']
587-
588-
for item in self.markdown_text.markup:
589-
type, value = item
590-
591-
if type == 'link' and re.compile(r'^https?://').search(value):
592-
browser_instance = webbrowser if browser_name == '' else webbrowser.get(browser_name)
593-
browser_instance.open(value, new=2)
594-
break
595-
596-
return super(Message, self).keypress(size, key)
597-
598-
def set_text(self, text):
599-
self.text_widget.original_widget = text
600-
601-
def set_edit_mode(self):
602-
self.set_attr_map({
603-
None: 'editing_message',
604-
'message': 'editing_message'
605-
})
606-
607-
def unset_edit_mode(self):
608-
self.set_attr_map({
609-
None: None,
610-
'message': None
611-
})
612-
613-
def selectable(self):
614-
return True
615-
616-
@property
617-
def file(self):
618-
return None
619-
620-
@file.setter
621-
def file(self, file):
622-
self.main_column.contents.insert(self._file_index, (file, ('pack', 1)))
623-
624520
class MessageBox(urwid.AttrMap):
625521
def __init__(self, user, typing=None, is_read_only=False):
626522
self.read_only_widget = urwid.Text('You have no power here!', align='center')
@@ -971,12 +867,6 @@ def __init__(self, text='', align='left', char='─'):
971867
]
972868
super(TextDivider, self).__init__(body)
973869

974-
975-
class Time(urwid.Text):
976-
def __init__(self, timestamp):
977-
time = datetime.fromtimestamp(float(timestamp)).strftime('%H:%M')
978-
super(Time, self).__init__(('datetime', ' {} '.format(time)))
979-
980870
def shorten_hex(color):
981871
if color.startswith('#'):
982872
color = color[1:]

sclack/quick_switcher.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
import time
33
import unicodedata
44
from .store import Store
5-
6-
7-
def get_icon(name):
8-
return Store.instance.config['icons'][name]
5+
from sclack.components import get_icon
96

107

118
def remove_diacritic(input):

sclack/store.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ def mark_read(self, channel_id, ts):
129129
elif self.is_dm(channel_id):
130130
return self.slack.api_call('im.mark', channel=channel_id, ts=ts)
131131

132+
def get_permalink(self, channel_id, ts):
133+
# https://api.slack.com/methods/chat.getPermalink
134+
return self.slack.api_call('chat.getPermalink', channel=channel_id, message_ts=ts)
135+
132136
def set_snooze(self, snoozed_time):
133137
return self.slack.api_call('dnd.setSnooze', num_minutes=snoozed_time)
134138

sclack/widgets/set_snooze.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
import urwid
2-
from sclack.store import Store
3-
4-
5-
def get_icon(name):
6-
return Store.instance.config['icons'][name]
2+
from sclack.components import get_icon
73

84

95
class SetSnoozeWidgetItem(urwid.AttrMap):

0 commit comments

Comments
 (0)