forked from karpathy/ulogme
-
Notifications
You must be signed in to change notification settings - Fork 14
/
notify.py
executable file
·211 lines (180 loc) · 9.03 KB
/
notify.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#!/usr/bin/env python3
# -*- coding: utf8 -*-
# notify.py for https://github.com/Naereen/uLogMe/
# MIT Licensed, https://lbesson.mit-license.org/
#
"""
Defines one useful function notify() to (try to) send a desktop notification.
"""
from __future__ import print_function # Python 2 compatibility
from __future__ import absolute_import # Python 2 compatibility
from webbrowser import open as openTab
from os import getcwd
from os.path import exists, join
from glob import glob
from random import choice
from subprocess import Popen
# WARNING Unused callback function for the notifications
def open_the_ulogme_page(notification, label, args=("localhost", 8124)):
""" Open the http://{}:{}/ URL in a new tab of your favorite browser. """
print("notify.notify(): open_the_ulogme_page callback function ...")
print("open_the_ulogme_page(): notification = {}, label = {}, args = {} ...".format(notification, label, args))
IP, PORT = args
ulogme_url = "http://{}:{}/".format(IP, PORT)
print("notify.notify(): Calling 'open(ulogme_url, new=2, autoraise=True)' ...")
return openTab(ulogme_url, new=2, autoraise=True)
# Constants for the program
PROGRAM_NAME = "uLogMe server (ulogme_serve.py)"
ICON_PATH = join("..", "scripts", "icons", "pikachu.png")
ICON_PATHS = glob(join("..", "scripts", "icons", "*.png"))
def choose_icon(random=True):
""" Choose a random icon. """
if random:
iconpath = choice(ICON_PATHS)
else:
iconpath = ICON_PATH
# print("iconpath =", iconpath) # DEBUG
return iconpath
# Define the icon loaded function
try:
from gi import require_version
require_version('GdkPixbuf', '2.0')
from gi.repository import GdkPixbuf
def load_icon(random=True):
""" Load and open a random icon. """
iconpath = choose_icon(random=random)
# Loading the icon...
if exists(iconpath):
# Use GdkPixbuf to create the proper image type
iconpng = GdkPixbuf.Pixbuf.new_from_file(iconpath)
else:
iconpng = None
# print("iconpng =", iconpng) # DEBUG
return iconpng
except ImportError:
print("\nError, gi.repository.GdkPixbuf seems to not be available, so notification icons will not be available ...")
print("On Ubuntu, if you want notification icons to work, install the 'python-gobject' and 'libnotify-bin' packages.")
print("(For more details, cf. 'http://www.devdungeon.com/content/desktop-notifications-python-libnotify')")
def load_icon(random=True):
print("Fake icon, random = {}.".format(random)) # DEBUG
return None
# Trying to import gi.repository.Notify
has_Notify = False
try:
from gi import require_version
require_version('Notify', '0.7')
from gi.repository import Notify
# One time initialization of libnotify
Notify.init(PROGRAM_NAME)
has_Notify = True
except ImportError:
print("\nError, gi.repository.Notify seems to not be available, so notification will not be available ...")
print("On Ubuntu, if you want notifications to work, install the 'python-gobject' and 'libnotify-bin' packages.")
print("(For more details, cf. 'http://www.devdungeon.com/content/desktop-notifications-python-libnotify')")
# Define the first notify function, with gi.repository.Notify
def notify_gi(body, summary=PROGRAM_NAME,
icon="random", addCallback=False,
IP="localhost", PORT=8124, # FIXED use this in ulogme_serve.py
timeout=5 # In seconds
):
"""
Send a notification, with gi.repository.Notify.
- icon can be "dialog-information", "dialog-warn", "dialog-error". By default it is set to the 'pikachu.png' image
"""
try:
# Trying to fix a bug:
# g-dbus-error-quark: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name :1.5124 was not provided by any .service files (2)
Notify.init(PROGRAM_NAME)
# Cf. http://www.devdungeon.com/content/desktop-notifications-python-libnotify
# Create the notification object
if icon and icon != "random":
notification = Notify.Notification.new(
summary, # Title of the notification
body, # Optional content of the notification
icon # WARNING Should not indicate it here
)
else:
notification = Notify.Notification.new(
summary, # Title of the notification
body # Optional content of the notification
)
if icon == "random":
# Add a Pikachu icom to the notification
# Why Pikachu? ALWAYS PIKACHU! http://www.lsv.ens-cachan.fr/~picaro/
iconpng = load_icon(random=True)
if iconpng is not None:
# Use the GdkPixbuf image
notification.set_icon_from_pixbuf(iconpng)
notification.set_image_from_pixbuf(iconpng)
# Lowest urgency (LOW, NORMAL or CRITICAL)
notification.set_urgency(Notify.Urgency.LOW)
# add duration, lower than 10 seconds (5 second is enough).
notification.set_timeout(timeout * 1000)
# DONE add a callback that open the browser tab/page on uLogMe when clicked on it
# The notification will have a button that says "View uLogMe page".
if addCallback:
notification.add_action(
"action_click",
"View uLogMe page",
open_the_ulogme_page,
(IP, PORT) # Arguments given to open_the_ulogme_page
)
# Actually show the notification on screen
notification.show()
return 0
# Ugly! XXX Catches too general exception
except Exception as e:
print("\nnotify.notify(): Error, notify.notify() failed, with this exception")
print(e)
return -1
# Define the second notify function, with a subprocess call to 'notify-send'
def notify_cli(body, summary=PROGRAM_NAME,
icon="random", addCallback=False,
IP="localhost", PORT=8124, # XXX unused here, notify-send does not accept callback functions
timeout=5 # In seconds
):
"""
Send a notification, with a subprocess call to 'notify-send'.
"""
if addCallback:
print("Warning: addCallback = True but notify-send does not accept callback functions (for IP = {}, PORT = {}).".format(IP, PORT)) # DEBUG
try:
print("notify.notify(): Trying to use the command line program 'notify-send' ...")
if icon == "random":
icon = join(getcwd(), choose_icon(random=True))
if icon:
Popen(["notify-send", "--expire-time=%s" % (timeout * 1000), "--icon=%s" % (icon), summary, body])
print("notify.notify(): A notification have been sent, with summary = '%s', body = '%s', expire-time='%s' and icon='%s'." % (summary, body, timeout * 1000, icon))
else:
Popen(["notify-send", "--expire-time=%s" % (timeout * 1000), summary, body])
print("notify.notify(): A notification have been sent, with summary = '%s', body = '%s' and expire-time='%s'." % (summary, body, timeout * 1000))
return 0
# Ugly! XXX Catches too general exception
except Exception as e:
print("\nnotify.notify(): notify-send : not-found ! Returned exception is %s." % e)
return -1
# Define the unified notify.notify() function
def notify(body, summary=PROGRAM_NAME,
icon="random", addCallback=False,
IP="localhost", PORT=8124, # FIXED use this in ulogme_serve.py
timeout=5 # In seconds
):
# print("Notification: '{}', from '{}' with icon '{}'.".format(body, summary, icon)) # DEBUG
if not has_Notify:
print("notify.notify(): Warning, desktop notification from Python seems to not be available ...")
return notify_cli(body, summary=summary, icon=icon, IP=IP, PORT=PORT, timeout=timeout, addCallback=addCallback)
try:
return_code = notify_gi(body, summary=summary, icon=icon, IP=IP, PORT=PORT, timeout=timeout, addCallback=addCallback)
if return_code < 0:
return_code = notify_cli(body, summary=summary, icon=icon, IP=IP, PORT=PORT, timeout=timeout, addCallback=addCallback)
except Exception:
return_code = notify_cli(body, summary=summary, icon=icon, IP=IP, PORT=PORT, timeout=timeout, addCallback=addCallback)
return return_code
if __name__ == "__main__":
# notify_gi("Test body Test body Test body ! From 'notify_gi(...)', with icon=terminal ...", icon="terminal")
# notify_gi("Test body Test body Test body ! From 'notify_gi(...)', with random Pokémon icon ...")
# notify_cli("Test body Test body Test body ! From 'notify_cli(...)', with icon=terminal ...", icon="terminal")
# notify_cli("Test body Test body Test body ! From 'notify_cli(...)', with random Pokémon icon ...")
notify("Test body Test body Test body ! From 'notify(...)', with icon=terminal ...", icon="terminal")
notify("Test body Test body Test body ! From 'notify(...)', with no icon ...", icon=None)
notify("Test body Test body Test body ! From 'notify(...)', with random Pokémon icon ...")