Skip to content

Commit a004824

Browse files
Add notification for Linux
1 parent 51e1c21 commit a004824

File tree

4 files changed

+144
-24
lines changed

4 files changed

+144
-24
lines changed

README.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,25 @@ The mouse support also has been programmed. You can scroll the chatbox and the s
173173
"emoji": true,
174174
"markdown": true,
175175
"pictures": true,
176-
"browser": ""
176+
"browser": "",
177+
"notification": ""
177178
}
178179
}
179180
```
180-
* `browser`: Config your preferable browser to open the link, when ever you focus on chat box text which contains external link (http/https), press enter key, the link will be opened. Valid [value](https://docs.python.org/2/library/webbrowser.html#webbrowser.get). Example you can config `"browser": "chrome"`
181+
* `browser`: Config your preferable browser to open the link, when ever you focus on chat box text which contains external link (http/https), press enter key, the link will be opened. Valid [value](https://docs.python.org/2/library/webbrowser.html#webbrowser.get). Example you can config `"browser": "chrome"`
182+
* `notification`: How do you want to receive notification. `all` receive all; `none` disable notification, `mentioned` Only mentioned and direct message
183+
184+
#### Notification
185+
186+
Supported:
187+
* Linux
188+
* Macos >= 10.10 use [terminal-notifier](https://github.com/julienXX/terminal-notifier), you can install your custom terminal-notifier or using default binary in pync package
189+
190+
To test your notification availability, trigger below command, if you can see notification you can use this feature
191+
192+
```bash
193+
python sclack/notification.py
194+
```
181195

182196
## Tested Terminals
183197

@@ -219,7 +233,5 @@ Contributions are very welcome, and there is a lot of work to do! You can...
219233
![](./resources/example_4.png)
220234
![](./resources/example_5.png)
221235
![](./resources/example_6.png)
222-
![](./resources/example_7.png)
223-
![](./resources/example_8.png)
224236

225237
<p align="center">Made with :rage: by <a href="https://github.com/haskellcamargo">@haskellcamargo</a></p>

app.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from sclack.quick_switcher import QuickSwitcher
2626
from sclack.store import Store
2727
from sclack.themes import themes
28+
from sclack.notification import TerminalNotifier
2829

2930
from sclack.widgets.set_snooze import SetSnoozeWidget
3031
from sclack.utils.channel import is_dm, is_group, is_channel
@@ -119,7 +120,7 @@ def should_notify_me(self, message_obj):
119120
:return:
120121
"""
121122
# You send message, don't need notification
122-
if self.config['features']['notification'] in ['', 'none'] or message_obj['user'] == self.store.state.auth['user_id']:
123+
if self.config['features']['notification'] in ['', 'none'] or message_obj.get('user') == self.store.state.auth['user_id']:
123124
return False
124125

125126
if self.config['features']['notification'] == 'all':
@@ -438,7 +439,9 @@ def notification_messages(self, messages):
438439
"""
439440
for message in messages:
440441
if self.should_notify_me(message):
441-
self.send_notification(message, MarkdownText(message['text']))
442+
loop.create_task(
443+
self.send_notification(message, MarkdownText(message['text']))
444+
)
442445

443446
def render_message(self, message, channel_id=None):
444447
is_app = False
@@ -491,7 +494,6 @@ def render_message(self, message, channel_id=None):
491494
return None
492495

493496
user_id = user['id']
494-
# TODO
495497
user_name = user['profile']['display_name'] or user.get('name')
496498
color = user.get('color')
497499
if message.get('file'):
@@ -504,7 +506,6 @@ def render_message(self, message, channel_id=None):
504506
return None
505507

506508
user_id = user['id']
507-
# TODO
508509
user_name = user['profile']['display_name'] or user.get('name')
509510
color = user.get('color')
510511

@@ -622,25 +623,25 @@ def render_messages(self, messages, channel_id=None):
622623
elif date_text is not None:
623624
_messages.append(TextDivider(('history_date', date_text), 'center'))
624625

625-
message = self.render_message(message, channel_id)
626+
message = self.render_message(raw_message, channel_id)
626627

627628
if message is not None:
628629
_messages.append(message)
629630

630631
return _messages
631632

633+
@asyncio.coroutine
632634
def send_notification(self, raw_message, markdown_text):
633635
"""
634-
Only MacOS
635-
@TODO Linux libnotify and Windows
636+
Only MacOS and Linux
637+
@TODO Windows
636638
:param raw_message:
637639
:param markdown_text:
638640
:return:
639641
"""
640642
user = self.store.find_user_by_id(raw_message.get('user'))
641643
sender_name = self.store.get_user_display_name(user)
642644

643-
# TODO Checking bot
644645
if raw_message.get('channel')[0] == 'D':
645646
notification_title = 'New message in {}'.format(
646647
self.store.state.auth['team']
@@ -651,19 +652,20 @@ def send_notification(self, raw_message, markdown_text):
651652
self.store.get_channel_name(raw_message.get('channel')),
652653
)
653654

654-
sub_title = sender_name
655655

656-
if platform.system() == 'Darwin':
657-
# Macos
658-
import pync
659-
pync.notify(
660-
markdown_text.render_text(),
661-
title=notification_title,
662-
subtitle=sub_title,
663-
appIcon='./resources/slack_icon.png'
656+
icon_path = os.path.realpath(
657+
os.path.join(
658+
os.path.dirname(__file__),
659+
'resources/slack_icon.png'
664660
)
665-
else:
666-
pass
661+
)
662+
TerminalNotifier().notify(
663+
str(markdown_text),
664+
title=notification_title,
665+
subtitle=sender_name,
666+
appIcon=icon_path,
667+
sound='default'
668+
)
667669

668670
def handle_mark_read(self, data):
669671
"""

sclack/markdown.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,5 @@ def render_emoji(result):
7474
self._result.append(('message', self.decode_buffer()))
7575
return self._result
7676

77-
def render_text(self):
77+
def __str__(self):
7878
return urwid.Text(self.markup).text

sclack/notification.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Notification wrapper
2+
3+
import os
4+
import platform
5+
import subprocess
6+
import sys
7+
8+
9+
class TerminalNotifier(object):
10+
def __init__(self, wait=False):
11+
self.wait = wait
12+
13+
def notify(self, message, **kwargs):
14+
if platform.system() == 'Darwin':
15+
import pync
16+
pync.notify(message, **kwargs)
17+
elif platform.system() == 'Linux':
18+
new_kwargs = {}
19+
mappings = {
20+
'group': 'category',
21+
'appIcon': 'icon',
22+
'title': 'title',
23+
'subtitle': 'subtitle',
24+
}
25+
26+
for origin_attr, new_attr in mappings.items():
27+
if kwargs.get(origin_attr):
28+
new_kwargs[new_attr] = kwargs.get(origin_attr)
29+
30+
if kwargs.get('subtitle'):
31+
if new_kwargs.get('title'):
32+
title = '{} by '.format(new_kwargs['title'])
33+
else:
34+
title = ''
35+
36+
new_kwargs['title'] = '{}{}'.format(title, kwargs.get('subtitle'))
37+
38+
pync = LinuxTerminalNotifier(wait=self.wait)
39+
pync.notify(message, **new_kwargs)
40+
else:
41+
# M$ Windows
42+
pass
43+
44+
45+
class LinuxTerminalNotifier(object):
46+
def __init__(self, wait=False):
47+
"""
48+
Raises an exception if not supported on the current platform or
49+
if terminal-notifier was not found.
50+
"""
51+
self._wait = wait
52+
proc = subprocess.Popen(["which", "notify-send"], stdout=subprocess.PIPE)
53+
env_bin_path = proc.communicate()[0].strip()
54+
55+
if env_bin_path and os.path.exists(env_bin_path):
56+
self.bin_path = os.path.realpath(env_bin_path)
57+
58+
if not os.path.exists(self.bin_path):
59+
raise Exception("Notifier is not defined")
60+
61+
def notify(self, message, **kwargs):
62+
if sys.version_info < (3,):
63+
message = message.encode('utf-8')
64+
65+
self._wait = kwargs.pop('wait', False)
66+
args = []
67+
68+
if kwargs.get('icon'):
69+
args += ['--icon', kwargs['icon']]
70+
71+
if kwargs.get('title'):
72+
args += [kwargs['title'], message]
73+
else:
74+
args += [message]
75+
76+
return self.execute(args)
77+
78+
def execute(self, args):
79+
args = [str(arg) for arg in args]
80+
81+
output = subprocess.Popen([self.bin_path, ] + args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
82+
83+
if self._wait:
84+
output.wait()
85+
86+
if output.returncode:
87+
raise Exception("Some error during subprocess call.")
88+
89+
return output
90+
91+
92+
if __name__ == '__main__':
93+
"""
94+
Test your notification availability
95+
"""
96+
TerminalNotifier().notify(
97+
'Your notification message is here',
98+
title='Sclack notification',
99+
appIcon=os.path.realpath(
100+
os.path.join(
101+
os.path.dirname(__file__),
102+
'..',
103+
'resources/slack_icon.png'
104+
)
105+
)
106+
)

0 commit comments

Comments
 (0)