Skip to content

Commit 7f50f96

Browse files
Add notification for Linux
1 parent 01be5a8 commit 7f50f96

File tree

4 files changed

+143
-23
lines changed

4 files changed

+143
-23
lines changed

README.md

+16-4
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,25 @@ The mouse support also has been programmed. You can scroll the chatbox and the s
160160
"emoji": true,
161161
"markdown": true,
162162
"pictures": true,
163-
"browser": ""
163+
"browser": "",
164+
"notification": ""
164165
}
165166
}
166167
```
167-
* `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"`
168+
* `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"`
169+
* `notification`: How do you want to receive notification. `all` receive all; `none` disable notification, `mentioned` Only mentioned and direct message
170+
171+
#### Notification
172+
173+
Supported:
174+
* Linux
175+
* 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
176+
177+
To test your notification availability, trigger below command, if you can see notification you can use this feature
178+
179+
```bash
180+
python sclack/notification.py
181+
```
168182

169183
## Tested Terminals
170184

@@ -206,7 +220,5 @@ Contributions are very welcome, and there is a lot of work to do! You can...
206220
![](./resources/example_4.png)
207221
![](./resources/example_5.png)
208222
![](./resources/example_6.png)
209-
![](./resources/example_7.png)
210-
![](./resources/example_8.png)
211223

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

app.py

+20-18
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from sclack.quick_switcher import QuickSwitcher
2424
from sclack.store import Store
2525
from sclack.themes import themes
26+
from sclack.notification import TerminalNotifier
2627

2728
loop = asyncio.get_event_loop()
2829

@@ -110,7 +111,7 @@ def should_notify_me(self, message_obj):
110111
:return:
111112
"""
112113
# You send message, don't need notification
113-
if self.config['features']['notification'] in ['', 'none'] or message_obj['user'] == self.store.state.auth['user_id']:
114+
if self.config['features']['notification'] in ['', 'none'] or message_obj.get('user') == self.store.state.auth['user_id']:
114115
return False
115116

116117
if self.config['features']['notification'] == 'all':
@@ -373,7 +374,9 @@ def notification_messages(self, messages):
373374
"""
374375
for message in messages:
375376
if self.should_notify_me(message):
376-
self.send_notification(message, MarkdownText(message['text']))
377+
loop.create_task(
378+
self.send_notification(message, MarkdownText(message['text']))
379+
)
377380

378381
def render_message(self, message):
379382
is_app = False
@@ -424,7 +427,6 @@ def render_message(self, message):
424427
return None
425428

426429
user_id = user['id']
427-
# TODO
428430
user_name = user['profile']['display_name'] or user.get('name')
429431
color = user.get('color')
430432
if message.get('file'):
@@ -437,7 +439,6 @@ def render_message(self, message):
437439
return None
438440

439441
user_id = user['id']
440-
# TODO
441442
user_name = user['profile']['display_name'] or user.get('name')
442443
color = user.get('color')
443444

@@ -554,18 +555,18 @@ def render_messages(self, messages):
554555

555556
return _messages
556557

558+
@asyncio.coroutine
557559
def send_notification(self, raw_message, markdown_text):
558560
"""
559-
Only MacOS
560-
@TODO Linux libnotify and Windows
561+
Only MacOS and Linux
562+
@TODO Windows
561563
:param raw_message:
562564
:param markdown_text:
563565
:return:
564566
"""
565567
user = self.store.find_user_by_id(raw_message.get('user'))
566568
sender_name = self.store.get_user_display_name(user)
567569

568-
# TODO Checking bot
569570
if raw_message.get('channel')[0] == 'D':
570571
notification_title = 'New message in {}'.format(
571572
self.store.state.auth['team']
@@ -576,19 +577,20 @@ def send_notification(self, raw_message, markdown_text):
576577
self.store.get_channel_name(raw_message.get('channel')),
577578
)
578579

579-
sub_title = sender_name
580580

581-
if platform.system() == 'Darwin':
582-
# Macos
583-
import pync
584-
pync.notify(
585-
markdown_text.render_text(),
586-
title=notification_title,
587-
subtitle=sub_title,
588-
appIcon='./resources/slack_icon.png'
581+
icon_path = os.path.realpath(
582+
os.path.join(
583+
os.path.dirname(__file__),
584+
'resources/slack_icon.png'
589585
)
590-
else:
591-
pass
586+
)
587+
TerminalNotifier().notify(
588+
str(markdown_text),
589+
title=notification_title,
590+
subtitle=sender_name,
591+
appIcon=icon_path,
592+
sound='default'
593+
)
592594

593595
@asyncio.coroutine
594596
def _go_to_channel(self, channel_id):

sclack/markdown.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,5 @@ def render_emoji(result):
7373
self._result.append(('message', self.decode_buffer()))
7474
return self._result
7575

76-
def render_text(self):
76+
def __str__(self):
7777
return urwid.Text(self.markup).text

sclack/notification.py

+106
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)