summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbeinc_generic_client.py158
-rw-r--r--beinc_server.json25
-rwxr-xr-xbeinc_server.py148
-rw-r--r--beinc_weechat.py327
-rw-r--r--bosd.py101
-rw-r--r--bpynotify_orm.py32
-rwxr-xr-xsocket_server.py77
-rwxr-xr-xweb_server.py47
-rwxr-xr-xweechat_notify.py49
-rwxr-xr-xweechat_notify_server.py116
10 files changed, 507 insertions, 573 deletions
diff --git a/beinc_generic_client.py b/beinc_generic_client.py
new file mode 100755
index 0000000..6cffc84
--- /dev/null
+++ b/beinc_generic_client.py
@@ -0,0 +1,158 @@
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# Blackmore's Enhanced IRC-Notification Collection (BEINC) v1.0
5# Copyright (C) 2013-2014 Simeon Simeonov
6
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
21import argparse
22import errno
23import getpass
24import httplib
25import socket
26import ssl
27import sys
28import urllib
29import urllib2
30
31
32__author__ = 'Simeon Simeonov'
33__version__ = '1.0'
34__license__ = 'GPL3'
35
36
37class ValidHTTPSConnection(httplib.HTTPConnection):
38 """
39 Implements a simple CERT verification functionality
40 """
41
42 default_port = httplib.HTTPS_PORT
43
44 def __init__(self, *args, **kwargs):
45 httplib.HTTPConnection.__init__(self, *args, **kwargs)
46
47 def connect(self):
48 sock = socket.create_connection((self.host, self.port),
49 self.timeout, self.source_address)
50 if self._tunnel_host:
51 self.sock = sock
52 self._tunnel()
53 self.sock = ssl.wrap_socket(sock,
54 ca_certs=global_beinc_cert_file,
55 cert_reqs=ssl.CERT_REQUIRED)
56
57
58
59class ValidHTTPSHandler(urllib2.HTTPSHandler):
60 """
61 Implements a simple CERT verification functionality
62 """
63
64 def https_open(self, req):
65 return self.do_open(ValidHTTPSConnection, req)
66
67
68
69def action_push(args):
70 """
71 """
72 try:
73 post_values = {'title': args.title,
74 'message': args.message,
75 'password': args.password}
76 data = urllib.urlencode(post_values)
77 req = urllib2.Request(args.url, data)
78 if args.cert: # check for cert validity
79 global global_beinc_cert_file # ugly hack
80 global_beinc_cert_file = args.cert
81 opener = urllib2.build_opener(ValidHTTPSHandler)
82 response = opener.open(req)
83 else: # ... or don't
84 response = urllib2.urlopen(req)
85 res_code = response.code
86 if res_code == 200:
87 print('Server responded: OK')
88 else:
89 print('Server responded: {0}'.format(res_code))
90 print('Body:\n{0}'.format(response.read()))
91 response.close()
92 except urllib2.HTTPError as e:
93 sys.stderr.write('BEINC-server error ({0} - {1})\n'.format(e.code, e.reason))
94 except Exception as e:
95 sys.stderr.write('BEINC generic client error: {0}\n'.format(e))
96 sys.exit(errno.EPERM)
97
98
99def main():
100
101 parser = argparse.ArgumentParser(
102 description='The following options are available')
103
104 parser.add_argument('url',
105 metavar='URL',
106 type=str,
107 #dest='url',
108 #required=True,
109 help='Destination URL')
110
111 parser.add_argument('-c', '--cert-file',
112 metavar='FILE',
113 type=str,
114 dest='cert',
115 default='',
116 help='BEINC CA-cert to check the server-cert against')
117
118 parser.add_argument('-m', '--message',
119 metavar='MESSAGE',
120 type=str,
121 dest='message',
122 default='BEINC message',
123 help='BEINC message')
124
125 parser.add_argument('-p', '--password',
126 metavar='PASSWORD',
127 type=str,
128 dest='password',
129 default='',
130 help='Password')
131
132 parser.add_argument('-t', '--title',
133 metavar='TITLE',
134 type=str,
135 dest='title',
136 default='BEINC title',
137 help='BEINC title')
138
139 parser.add_argument('-v', '--version',
140 action='version',
141 version='%(prog)s {0}'.format(__version__),
142 help='display program-version and exit')
143
144 args = parser.parse_args()
145
146 if not args.password:
147 try:
148 args.password = getpass.getpass()
149 except Exception as e:
150 sys.stderr.write('Prompt terminated\n')
151 sys.exit(errno.EACCES)
152
153 action_push(args)
154 sys.exit(0)
155
156
157if __name__ == '__main__':
158 main()
diff --git a/beinc_server.json b/beinc_server.json
index 2824dea..46674ed 100644
--- a/beinc_server.json
+++ b/beinc_server.json
@@ -18,27 +18,30 @@
18 }, 18 },
19 19
20 "irc_client": { 20 "irc_client": {
21 "use_current_buffer": 0,
21 "targets": [ 22 "targets": [
22 { 23 {
23 "name": "weechat_main", 24 "name": "weechat_main",
24 "target_url": "", 25 "target_url": "https://10.0.0.2:9898/push/secondtest",
25 "target_password": "changeme", 26 "target_password": "changeme",
26 "target_cert_file": "", 27 "target_cert_file": "",
27 "target_timestamp_format": "%H:%M:%S", 28 "target_timestamp_format": "%H:%M:%S",
28 "pm_title_template": "", 29 "pm_title_template": "%s @ %S",
29 "pm_message_template": "", 30 "pm_message_template": "%m",
30 "cm_title_template": "", 31 "cm_title_template": "%c @ %S",
31 "cm_message_template": "", 32 "cm_message_template": "%s -> %m",
32 "nm_title_template": "", 33 "nm_title_template": "%c @ %S",
33 "nm_message_template": "", 34 "nm_message_template": "%s -> %m",
34 "channel_list": ["RedpillLinpro.#python", 35 "channel_list": ["RedpillLinpro.#python",
35 "Exile.#hin", 36 "Exile.#test",
36 "RedpillLinpro.#adult", 37 "RedpillLinpro.#adult",
37 "Exile.#pichove"], 38 "Exile.#pichove"],
38 "nick_list": ["Exile.Blackmore"], 39 "nick_list": ["Exile.Blackmore"],
39 "channel_messages_policy": 0, 40 "channel_messages_policy": 2,
40 "private_messages_policy": 0, 41 "private_messages_policy": 1,
41 "notifications_policy": 0 42 "notifications_policy": 1,
43 "debug": 1,
44 "enabled": 1
42 } 45 }
43 ] 46 ]
44 }, 47 },
diff --git a/beinc_server.py b/beinc_server.py
index 8687da3..d4dd3c3 100755
--- a/beinc_server.py
+++ b/beinc_server.py
@@ -1,18 +1,42 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2# -*- coding: utf-8 -*- 2# -*- coding: utf-8 -*-
3 3
4# Blackmore's Enhanced IRC-Notification Collection (BEINC) v1.0
5# Copyright (C) 2013-2014 Simeon Simeonov
6
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
4import argparse 21import argparse
22import errno
5import getpass 23import getpass
6import json 24import json
7import os 25import os
26import random
8import sys 27import sys
9 28
10import cherrypy 29import cherrypy
11 30
31try:
32 import pynotify
33except ImportError as e:
34 pynotify = None
35
12 36
13__author__ = 'Simeon Simeonov' 37__author__ = 'Simeon Simeonov'
14__version__ = '1.0-beta' 38__version__ = '1.0'
15__license__ = "GPL3" 39__license__ = 'GPL3'
16 40
17 41
18BEINC_OSD_TYPE_NONE = 0 42BEINC_OSD_TYPE_NONE = 0
@@ -33,40 +57,35 @@ class BEINCInstance(object):
33 self.__osd_type = BEINC_OSD_TYPE_NONE 57 self.__osd_type = BEINC_OSD_TYPE_NONE
34 self.__osd_notification = None 58 self.__osd_notification = None
35 59
36 try: 60 self.__name = instance_dict.get('name')
37 self.__name = instance_dict['name'] 61 self.__password = instance_dict.get('password', '')
38 self.__password = instance_dict['password'] 62 self.__queue_size = int(instance_dict.get('queue_size', 3))
39 self.__queue_size = int(instance_dict['queue_size'])
40
41 except Exception as e:
42 sys.stderr.write(
43 'Instance processing error {0}:\n{1}\n'.format(self.__name,
44 e))
45 sys.exit(1)
46 63
47 if instance_dict['osd_system'].lower() == 'pynotify': 64 if instance_dict['osd_system'].lower() == 'pynotify':
65 self.__queue_size = 0 # disable queueing
48 if not pynotify: 66 if not pynotify:
49 sys.stderr.write( 67 sys.stderr.write(
50 'This server does not possess pynotify capability\n') 68 'This server does not possess pynotify capability\n')
51 sys.stderr.write( 69 sys.stderr.write(
52 'Remove the instance {0}'.format(self.__name)) 70 'Remove the instance {0}'.format(self.__name))
53 sys.stderr.write("or define it with 'osd_system': 'none'\n") 71 sys.stderr.write("or define it with 'osd_system': 'none'\n")
54 sys.exit(1) 72 sys.exit(errno.EPERM)
55 73
56 try: 74 try:
57 self.__osd_notification = pynotify.Notification(' ') 75 self.__osd_notification = pynotify.Notification(' ')
58 self.__osd_notification.set_timeout( 76 self.__osd_notification.set_timeout(
59 instance_dict['osd_timeout']) 77 int(instance_dict.get('osd_timeout', 5000)))
60 self.__osd_notification.set_property( 78 self.__osd_notification.set_property(
61 'app_name', 79 'app_name',
62 '{0} {1}'.format(sys.argv[0], __version__)) 80 '{0} {1}'.format(sys.argv[0], __version__))
63 except Exception as e: 81 except Exception as e:
64 sys.stderr.write( 82 sys.stderr.write(
65 'Unable to set up a notification object for {0} ({1})\n') 83 'Unable to set up a notification object for {0} ({1})\n')
66 sys.exit(1) 84 sys.exit(errno.EPERM)
67 85
68 self.__osd_type = BEINC_OSD_TYPE_PYNOTIFY 86 self.__osd_type = BEINC_OSD_TYPE_PYNOTIFY
69 87
88
70 @property 89 @property
71 def name(self): 90 def name(self):
72 """ 91 """
@@ -129,34 +148,25 @@ def beinc_instance_login(method):
129 """ 148 """
130 decorator for checking login credentials 149 decorator for checking login credentials
131 """ 150 """
132 from functools import wraps
133 151
134 @wraps(method) 152 def wrapper(self, *args, **kwargs):
135 def tmp_func(self, *args, **kwargs):
136 153
137 if not args: 154 if not args:
138 raise cherrypy.HTTPError(400) 155 raise cherrypy.HTTPError(status = 404)
139
140 print('args: {0}'.format(args))
141 print('kwargs: {0}'.format(kwargs))
142 print(cherrypy.request.config)
143 print('args[0]: {0} ({1})'.format(args[0], str(type(args[0]))))
144 print('instances: {0}'.format(str(self.__instances)))
145 156
146 try: 157 try:
147 instance = self.__instances[args[0]] 158 instance = self.instances[args[0]]
148 except Exception as e: 159 except Exception as e:
149 sys.stderr.write('Wrong instance or password: {0}\n'.format(e)) 160 raise cherrypy.HTTPError(status = 401,
150 raise cherrypy.HTTPError('403 Forbidden', 161 message = 'Wrong instance or password')
151 'Wrong instance or password')
152 162
153 if not instance.password_match(kwargs.get('password')): 163 if not instance.password_match(kwargs.get('password')):
154 raise cherrypy.HTTPError('403 Forbidden', 164 raise cherrypy.HTTPError(status = 401,
155 'Wrong instance or password') 165 message = 'Wrong instance or password')
156 166
157 return method(self, *args, **kwargs) 167 return method(self, *args, **kwargs)
158 168
159 return tmp_func 169 return wrapper
160 170
161 171
162class WebNotifyServer(object): 172class WebNotifyServer(object):
@@ -167,15 +177,32 @@ class WebNotifyServer(object):
167 self.__config = config 177 self.__config = config
168 self.__instances = dict() 178 self.__instances = dict()
169 179
180 # initialize pynotify if the module exists and if needed
181 if pynotify:
182 for instance in self.__config['server']['instances']:
183 # check if we have at least one instance that uses pynotify
184 # before initializing it
185 if instance.get('osd_system', '').lower() == 'pynotify':
186 if not pynotify.init('BEINC Notify'):
187 sys.stderr.write('pynotify.init failed! Exiting...\n')
188 sys.exit(1)
189 break
170 try: 190 try:
171 for instance in self.__config['server']['instances']: 191 for instance in self.__config['server']['instances']:
172 self.__instances[instance['name']] = BEINCInstance(instance) 192 self.__instances[instance['name']] = BEINCInstance(instance)
173 print('Instance "{0}" added'.format(instance['name'])) 193 print('Instance "{0}" added'.format(instance['name']))
174 194
175 except Exception as e: 195 except Exception as e:
176 sys.stderr.write('Unable to initialize queues: {0}\n'.format(e)) 196 sys.stderr.write('Unable to create instance "{0}": {1}\n'.format(
197 instance['name'],
198 e))
177 sys.exit(1) 199 sys.exit(1)
178 200
201
202 @property
203 def instances(self):
204 return self.__instances
205
179 @cherrypy.expose 206 @cherrypy.expose
180 def index(self): 207 def index(self):
181 """ 208 """
@@ -190,33 +217,14 @@ class WebNotifyServer(object):
190 """ 217 """
191 return 'default' 218 return 'default'
192 219
220
193 @cherrypy.expose 221 @cherrypy.expose
222 @beinc_instance_login
194 def push(self, *args, **kwargs): 223 def push(self, *args, **kwargs):
195 print('push called')
196
197 if not args:
198 raise cherrypy.HTTPError(400)
199
200 # print('args: {0}'.format(args))
201 # print('kwargs: {0}'.format(unicode(kwargs)))
202 # print(cherrypy.request.config)
203 # print('args[0]: {0} ({1})'.format(args[0], str(type(args[0]))))
204 # print('instances: {0}'.format(str(self.__instances)))
205
206 try:
207 instance = self.__instances[args[0]]
208 except Exception as e:
209 sys.stderr.write('Wrong instance or password\n')
210 #print('DEBUG: {0}'.format(e))
211 raise cherrypy.HTTPError('403 Forbidden',
212 'Wrong instance or password')
213 224
214 if not instance.password_match(kwargs.get('password')): 225 instance = self.__instances[args[0]]
215 sys.stderr.write('Wrong instance or password\n')
216 raise cherrypy.HTTPError('403 Forbidden',
217 'Wrong instance or password')
218 226
219# instance = self.__instances[args[0]] 227 print('**kwargs: {0}'.format(str(kwargs)))
220 title = kwargs.get('title', '') 228 title = kwargs.get('title', '')
221 message = kwargs.get('message', '') 229 message = kwargs.get('message', '')
222 try: 230 try:
@@ -229,12 +237,19 @@ class WebNotifyServer(object):
229 e)) 237 e))
230 raise cherrypy.HTTPError(500, 'Unable to send message') 238 raise cherrypy.HTTPError(500, 'Unable to send message')
231 239
240
232 @cherrypy.expose 241 @cherrypy.expose
233 @beinc_instance_login 242 @beinc_instance_login
234 def pull(self, *args, **kwargs): 243 def pull(self, *args, **kwargs):
235 244
236 instance = self.__instances(args[0]) 245 instance = self.__instances[args[0]]
237 return 'OK' 246 if not instance.queueable:
247 raise cherrypy.HTTPError(
248 status = 405,
249 message = 'BEINC instance "{0}" does not support queuing'.format(
250 instance.name))
251
252 return instance.get_queue()
238 253
239 254
240def main(): 255def main():
@@ -283,7 +298,7 @@ def main():
283 except Exception as e: 298 except Exception as e:
284 sys.stderr.write('Unable to parse {0}: {1}'.format(args.config_file, 299 sys.stderr.write('Unable to parse {0}: {1}'.format(args.config_file,
285 e)) 300 e))
286 sys.exit(1) 301 sys.exit(errno.EIO)
287 302
288 cherrypy.config.update({ 303 cherrypy.config.update({
289 'server.socket_host': args.hostname, 304 'server.socket_host': args.hostname,
@@ -292,20 +307,11 @@ def main():
292 'server.ssl_certificate': config_dict['server']['general']['ssl_certificate'], 307 'server.ssl_certificate': config_dict['server']['general']['ssl_certificate'],
293 'server.ssl_private_key': config_dict['server']['general']['ssl_private_key'], 308 'server.ssl_private_key': config_dict['server']['general']['ssl_private_key'],
294 'tools.encode.on': True, 309 'tools.encode.on': True,
295 'tools.encode.encoding': 'utf-8' 310 'tools.encode.encoding': 'utf-8',
311 'tools.log_tracebacks.on': False,
312 'request.show_tracebacks': False
296 }) 313 })
297 314
298 global pynotify
299 try:
300 import pynotify
301 if not pynotify.init('BEINC Notify'):
302 sys.stderr.write('pynotify.init failed! Exiting...\n')
303 sys.exit(1)
304 except Exception as e:
305 sys.stderr.write(
306 'Notice: pynotify support unavailable ({0})\n'.format(e))
307 pynotify = False
308
309 try: 315 try:
310 cherrypy.quickstart(WebNotifyServer(config_dict)) 316 cherrypy.quickstart(WebNotifyServer(config_dict))
311 317
diff --git a/beinc_weechat.py b/beinc_weechat.py
index 689f450..8b4392f 100644
--- a/beinc_weechat.py
+++ b/beinc_weechat.py
@@ -1,6 +1,23 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2# -*- coding: utf-8 -*- 2# -*- coding: utf-8 -*-
3 3
4# Blackmore's Enhanced IRC-Notification Collection (BEINC) v1.0
5# Copyright (C) 2013-2014 Simeon Simeonov
6
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
4import datetime 21import datetime
5import httplib 22import httplib
6import json 23import json
@@ -14,6 +31,12 @@ import urllib2
14 31
15import weechat 32import weechat
16 33
34
35__author__ = 'Simeon Simeonov'
36__version__ = '1.0'
37__license__ = 'GPL3'
38
39
17enabled = True 40enabled = True
18global_values = dict() 41global_values = dict()
19 42
@@ -26,14 +49,13 @@ BEINC_POLICY_LIST_ONLY = 2
26 49
27class ValidHTTPSConnection(httplib.HTTPConnection): 50class ValidHTTPSConnection(httplib.HTTPConnection):
28 """ 51 """
52 Implements a simple CERT verification functionality
29 """ 53 """
30 54
31 default_port = httplib.HTTPS_PORT 55 default_port = httplib.HTTPS_PORT
32 56
33 def __init__(self, cert_file, *args, **kwargs): 57 def __init__(self, *args, **kwargs):
34 httplib.HTTPConnection.__init__(self, *args, **kwargs) 58 httplib.HTTPConnection.__init__(self, *args, **kwargs)
35 self.__cert_file = cert_file
36
37 59
38 def connect(self): 60 def connect(self):
39 sock = socket.create_connection((self.host, self.port), 61 sock = socket.create_connection((self.host, self.port),
@@ -42,19 +64,18 @@ class ValidHTTPSConnection(httplib.HTTPConnection):
42 self.sock = sock 64 self.sock = sock
43 self._tunnel() 65 self._tunnel()
44 self.sock = ssl.wrap_socket(sock, 66 self.sock = ssl.wrap_socket(sock,
45 ca_certs=self.__cert_file, 67 ca_certs=global_beinc_cert_file,
46 cert_reqs=ssl.CERT_REQUIRED) 68 cert_reqs=ssl.CERT_REQUIRED)
47 69
48 70
49 71
50class ValidHTTPSHandler(urllib2.HTTPSHandler): 72class ValidHTTPSHandler(urllib2.HTTPSHandler):
51 73 """
52 def __init__(self, cert_file, *args, **kwargs): 74 Implements a simple CERT verification functionality
53 urllib2.HTTPSHandler.__init__(self, *args, **kwargs) 75 """
54 self.__cert_file = cert_file
55 76
56 def https_open(self, req): 77 def https_open(self, req):
57 return self.do_open(ValidHTTPSConnection(self.__cert_file), req) 78 return self.do_open(ValidHTTPSConnection, req)
58 79
59 80
60 81
@@ -101,6 +122,8 @@ class WeechatTarget(object):
101 self.__cert_file = target_dict.get('target_cert_file') 122 self.__cert_file = target_dict.get('target_cert_file')
102 self.__timestamp_format = target_dict.get('target_timestamp_format', 123 self.__timestamp_format = target_dict.get('target_timestamp_format',
103 '%H:%M:%S') 124 '%H:%M:%S')
125 self.__debug = bool(target_dict.get('debug', False))
126 self.__enabled = bool(target_dict.get('enabled', True))
104 127
105 128
106 @property 129 @property
@@ -144,48 +167,117 @@ class WeechatTarget(object):
144 """ 167 """
145 return self.__notifications_policy 168 return self.__notifications_policy
146 169
147 170
171 @property
172 def enabled(self):
173 """
174 """
175 return self.__enabled
176
177 @enabled.setter
178 def enabled(self, value):
179 """
180 """
181 self.__enabled = value
182
183
148 def __repr__(self): 184 def __repr__(self):
149 """ 185 """
150 """ 186 """
151 187 return 'name: {0}\nurl: {1}\nchannel_list: {2}\nnick_list: {3}\n'\
152 return 'name: {0}\nurl: {1}\nchannel_list: {2}\nnick_list: {3}'\ 188 'channel_messages_policy: {4}\nprivate_messages_policy: {5}\n'\
153 'channel_messages_policy: {4}\nprivate_messages_policy: {5}'\ 189 'notifications_policy: {6}\nenabled: {7}\n\n'.format(
154 'notifications_policy: {6}'.format(self.__name, 190 self.__name,
155 self.__url, 191 self.__url,
156 ', '.join(self.__chans), 192 ', '.join(self.__chans),
157 ', '.join(self.__nicks), 193 ', '.join(self.__nicks),
158 self.__chan_message_policy, 194 self.__chan_messages_policy,
159 self.__priv_message_policy, 195 self.__priv_messages_policy,
160 self.__notifications_policy) 196 self.__notifications_policy,
197 'yes' if self.__enabled else 'no')
161 198
162 199
163 def send_private_message_notification(self, message, values): 200 def send_private_message_notification(self, values):
164 """ 201 """
165 """ 202 """
166 pass 203 try:
204 title_str = self.__fetch_formatted_str(self.__pm_title_template,
205 values)
206 message_str = self.__fetch_formatted_str(self.__pm_message_template,
207 values)
208 post_values = {'title': title_str,
209 'message': message_str,
210 'password': self.__password}
211 data = urllib.urlencode(post_values)
212 if self.__send_beinc_message(data) and self.__debug:
213 beinc_prnt(
214 'BEINC DEBUG: send_private_message_notification-ERROR '
215 'for "{0}": __send_beinc_message -> False'.format(
216 self.__name))
217 except Exception as e:
218 if self.__debug:
219 beinc_prnt(
220 'BEINC DEBUG: send_private_message_notification-ERROR '
221 'for "{0}": {1}'.format(self.__name, e))
167 222
168 223
169 def send_channel_message_notification(self, message, values): 224 def send_channel_message_notification(self, values):
170 """ 225 """
171 """ 226 """
172 pass 227 try:
228 title_str = self.__fetch_formatted_str(self.__cm_title_template,
229 values)
230 message_str = self.__fetch_formatted_str(self.__cm_message_template,
231 values)
232 post_values = {'title': title_str,
233 'message': message_str,
234 'password': self.__password}
235 data = urllib.urlencode(post_values)
236 if self.__send_beinc_message(data) and self.__debug:
237 beinc_prnt(
238 'BEINC DEBUG: send_channel_message_notification-ERROR '
239 'for "{0}": __send_beinc_message -> False'.format(
240 self.__name))
241 except Exception as e:
242 if self.__debug:
243 beinc_prnt(
244 'BEINC DEBUG: send_channel_message_notification-ERROR '
245 'for "{0}": {1}'.format(self.__name, e))
173 246
174 247
175 def send_notify_message_notification(self, message, values): 248 def send_notify_message_notification(self, values):
176 """ 249 """
177 """ 250 """
178 pass 251 try:
252 title_str = self.__fetch_formatted_str(self.__nm_title_template,
253 values)
254 message_str = self.__fetch_formatted_str(self.__nm_message_template,
255 values)
256 post_values = {'title': title_str,
257 'message': message_str,
258 'password': self.__password}
259 data = urllib.urlencode(post_values)
260 if self.__send_beinc_message(data) and self.__debug:
261 beinc_prnt(
262 'BEINC DEBUG: send_notify_message_notification-ERROR '
263 'for "{0}": __send_beinc_message -> False'.format(
264 self.__name))
265 except Exception as e:
266 if self.__debug:
267 beinc_prnt(
268 'BEINC DEBUG: send_notify_message_notification-ERROR '
269 'for "{0}": {1}'.format(self.__name, e))
179 270
180 271
181 def __fetch_formatted_str(self, template, values): 272 def __fetch_formatted_str(self, template, values):
182 """ 273 """
183 """ 274 """
275 timestamp = datetime.datetime.now().strftime(self.__timestamp_format)
184 replacements = {'%S': values['server'], 276 replacements = {'%S': values['server'],
185 '%s': values['source_nick'], 277 '%s': values['source_nick'],
186 '%c': values['channel'], 278 '%c': values['channel'],
187 '%m': values['message'], 279 '%m': values['message'],
188 '%t': values['timestamp'], 280 '%t': timestamp,
189 '%p': 'BEINC', 281 '%p': 'BEINC',
190 '%n': values['own_nick']} 282 '%n': values['own_nick']}
191 for key, value in replacements.items(): 283 for key, value in replacements.items():
@@ -201,40 +293,100 @@ class WeechatTarget(object):
201 293
202 try: 294 try:
203 req = urllib2.Request(self.__url, data) 295 req = urllib2.Request(self.__url, data)
204 opener = urllib2.build_opener(ValidHTTPSHandler) 296
205 297 if self.__cert_file:
206 response = opener.open(req) 298 opener = urllib2.build_opener(ValidHTTPSHandler)
299 response = opener.open(req)
300 else:
301 response = urllib2.urlopen(req)
207 res_code = response.code 302 res_code = response.code
208 response.close() 303 response.close()
209 if res_code == 200: 304 if res_code == 200:
210 return True 305 return True
211 except Exception as e: 306 except urllib2.HTTPError as e:
212 weechat.prnt(weechat.current_buffer(), 307 if self.__debug:
213 'DEBUG: send_beinc_message-ERROR: {0}'.format(e)) 308 beinc_prnt(
309 'BEINC DEBUG: send_beinc_message-ERROR for "{0}": {1} ->'
310 ' ({2} - {3})'.format(self.__name, e.url, e.code, e.reason))
311 # all other exception should be handled by the caller
214 return False 312 return False
215 313
216 314
217 315
218def beinc_send_message(message): 316def beinc_prnt(message_str):
219 weechat.prnt(weechat.current_buffer(), 'beinc message: {0}'.format(message)) 317 """
318 wrapper around weechat.prnt
319 """
320 if global_values['use_current_buffer']:
321 weechat.prnt(weechat.current_buffer(), message_str)
322 else:
323 weechat.prnt('', message_str)
324
220 325
326def beinc_cmd_target_handler(cmd_tokens):
327 """
328 handles: '/beinc target' command actions
329 """
330 if not cmd_tokens or cmd_tokens[0] not in ['list', 'enable', 'disable']:
331 beinc_prnt('beinc target [ list | enable <name> | disable <name> ]')
332 return weechat.WEECHAT_RC_OK
221 333
222def beinc_command(data, buffer, args): 334 if cmd_tokens[0] == 'list':
335 beinc_prnt('--- Targets ---')
336 for target in target_list:
337 beinc_prnt(str(target))
338 beinc_prnt('---------------')
339 elif cmd_tokens[0] == 'enable':
340 if not cmd_tokens[1:]:
341 beinc_prnt('missing a name-argument')
342 return weechat.WEECHAT_RC_OK
343 name = ' '.join(cmd_tokens[1:])
344 for target in target_list:
345 if target.name == name:
346 target.enabled = True
347 beinc_prnt('target "{0}" enabled'.format(name))
348 break
349 else:
350 beinc_prnt('no matching target for "{0}"'.format(name))
351 elif cmd_tokens[0] == 'disable':
352 if not cmd_tokens[1:]:
353 beinc_prnt('missing a name-argument')
354 return weechat.WEECHAT_RC_OK
355 name = ' '.join(cmd_tokens[1:])
356 for target in target_list:
357 if target.name == name:
358 target.enabled = False
359 beinc_prnt('target "{0}" disabled'.format(name))
360 break
361 else:
362 beinc_prnt('no matching target for "{0}"'.format(name))
363
364 return weechat.WEECHAT_RC_OK
365
366
367def beinc_command(data, buffer_obj, args):
223 global enabled 368 global enabled
369 cmd_tokens = args.split()
370
371 if not cmd_tokens:
372 return weechat.WEECHAT_RC_OK
373
224 if args == 'on': 374 if args == 'on':
225 enabled = True 375 enabled = True
226 weechat.prnt(weechat.current_buffer(), 'beinc on') 376 beinc_prnt('BEINC on')
227 elif args == 'off': 377 elif args == 'off':
228 enabled = False 378 enabled = False
229 weechat.prnt(weechat.current_buffer(), 'beinc off') 379 beinc_prnt('BEINC off')
230 elif args == 'reload': 380 elif args == 'reload':
231 beinc_config_file_str = os.path.join( 381 beinc_prnt('Reloading BEINC...')
232 weechat.info_get('weechat_dir', ''), 382 beinc_init()
233 'beinc.json') 383 elif cmd_tokens[0] == 'target':
234 weechat.prnt(weechat.current_buffer(), '{0} reloaded'.format( 384 return beinc_cmd_target_handler(cmd_tokens[1:])
235 beinc_config_file_str))
236 else: 385 else:
237 beinc_send_message(args) 386 beinc_prnt('data: {0}, cmd_tokens: {1}, args: {2}'.format(
387 str(data),
388 str(cmd_tokens),
389 str(args)))
238 390
239 return weechat.WEECHAT_RC_OK 391 return weechat.WEECHAT_RC_OK
240 392
@@ -249,40 +401,74 @@ def beinc_privmsg_handler(data, signal, signal_data):
249 # packing the privmsg handler values 401 # packing the privmsg handler values
250 ph_values = dict() 402 ph_values = dict()
251 ph_values['server'] = signal.split(',')[0] 403 ph_values['server'] = signal.split(',')[0]
252 ph_values['own_nick'] = weechat.info_get('irc_nick', server) 404 ph_values['own_nick'] = weechat.info_get('irc_nick', ph_values['server'])
253 ph_values['channel'] = prvmsg_dict['arguments'].split(':')[0].strip() 405 ph_values['channel'] = prvmsg_dict['arguments'].split(':')[0].strip()
254 ph_values['source_nick'] = prvmsg_dict['nick'] 406 ph_values['source_nick'] = prvmsg_dict['nick']
255 ph_values['message'] = ':'.join( 407 ph_values['message'] = ':'.join(
256 prvmsg_dict['arguments'].split(':')[1:]).strip() 408 prvmsg_dict['arguments'].split(':')[1:]).strip()
257 ph_values['timestamp'] = datetime.datetime.now().strftime(
258 self.__timestamp_format)
259 409
260 if ph_values['channel'] == ph_values['own_nick']: 410 if ph_values['channel'] == ph_values['own_nick']:
261 # priv messages are handled here 411 # priv messages are handled here
262 if not global_values['global_channel_messages_policy']: 412 if not global_values['global_private_messages_policy']:
413 return weechat.WEECHAT_RC_OK
414
415 if global_values['global_private_messages_policy'] == BEINC_POLICY_LIST_ONLY \
416 and '{0}.{1}'.format(
417 ph_values['server'],
418 ph_values['source_nick'].lower()) not in global_values['global_nicks']:
263 return weechat.WEECHAT_RC_OK 419 return weechat.WEECHAT_RC_OK
264 420
265 for target in target_list: 421 for target in target_list:
266 if target.private_messages_policy == 1 or ( 422 if not target.enabled:
267 target.private_messages_policy == 2 \ 423 continue
424 if target.private_messages_policy == BEINC_POLICY_ALL or (
425 target.private_messages_policy == BEINC_POLICY_LIST_ONLY \
268 and '{0}.{1}'.format( 426 and '{0}.{1}'.format(
269 ph_values['server'], 427 ph_values['server'],
270 ph_values['source_nick'].lower()) in target.nicks): 428 ph_values['source_nick'].lower()) in target.nicks):
271 weechat.prnt(weechat.current_buffer(), 429 target.send_private_message_notification(ph_values)
272 'DEBUG: priv message - {0}'.format(
273 ph_values['message']))
274 430
275 elif privmsg_handler_values['own_nick'].lower() in ph_values['message'].lower(): 431 elif ph_values['own_nick'].lower() in ph_values['message'].lower():
276 # notify messages are handled here 432 # notify messages are handled here
277 weechat.prnt(weechat.current_buffer(),
278 'DEBUG: notify message - {0}'.format(ph_values['message']))
279 if not global_values['global_notifications_policy']: 433 if not global_values['global_notifications_policy']:
280 return weechat.WEECHAT_RC_OK 434 return weechat.WEECHAT_RC_OK
281 435
436 if global_values['global_notifications_policy'] == BEINC_POLICY_LIST_ONLY \
437 and '{0}.{1}'.format(
438 ph_values['server'],
439 ph_values['channel'].lower()) not in global_values['global_chans']:
440 return weechat.WEECHAT_RC_OK
441
442 for target in target_list:
443 if not target.enabled:
444 continue
445 if target.notifications_policy == BEINC_POLICY_ALL or (
446 target.notifications_policy == BEINC_POLICY_LIST_ONLY \
447 and '{0}.{1}'.format(
448 ph_values['server'],
449 ph_values['channel'].lower()) in target.chans):
450 target.send_notify_message_notification(ph_values)
451
282 elif global_values['global_channel_messages_policy']: 452 elif global_values['global_channel_messages_policy']:
283 # chan messages are handled here 453 # chan messages are handled here
284 weechat.prnt(weechat.current_buffer(), 454 if not global_values['global_notifications_policy']:
285 'DEBUG: chan message - {0}'.format(ph_values['message'])) 455 return weechat.WEECHAT_RC_OK
456
457 if global_values['global_channel_messages_policy'] == BEINC_POLICY_LIST_ONLY \
458 and '{0}.{1}'.format(
459 ph_values['server'],
460 ph_values['channel'].lower()) not in global_values['global_chans']:
461 return weechat.WEECHAT_RC_OK
462
463 for target in target_list:
464 if not target.enabled:
465 continue
466 if target.channel_messages_policy == BEINC_POLICY_ALL or (
467 target.channel_messages_policy == BEINC_POLICY_LIST_ONLY \
468 and '{0}.{1}'.format(
469 ph_values['server'],
470 ph_values['channel'].lower()) in target.chans):
471 target.send_channel_message_notification(ph_values)
286 472
287 return weechat.WEECHAT_RC_OK 473 return weechat.WEECHAT_RC_OK
288 474
@@ -293,33 +479,36 @@ def beinc_init():
293 global target_list 479 global target_list
294 global global_values 480 global global_values
295 481
482 # global chans/nicks sets are used to speed up the filtering
483 global_values = dict()
296 global_values['global_chans'] = set() 484 global_values['global_chans'] = set()
297 global_values['global_nicks'] = set() 485 global_values['global_nicks'] = set()
298 custom_error = '' 486 target_list = list()
299 487
488 custom_error = ''
300 global_values['global_channel_messages_policy'] = False 489 global_values['global_channel_messages_policy'] = False
301 global_values['global_private_messages_policy'] = False 490 global_values['global_private_messages_policy'] = False
302 global_values['global_notifications_policy'] = False 491 global_values['global_notifications_policy'] = False
303 492 global_values['use_current_buffer'] = False
493
304 try: 494 try:
305 beinc_config_file_str = os.path.join( 495 beinc_config_file_str = os.path.join(
306 weechat.info_get('weechat_dir', ''), 496 weechat.info_get('weechat_dir', ''),
307 'beinc.json') 497 'beinc.json')
308 weechat.prnt('', 'Parsing {0}...'.format(beinc_config_file_str)) 498 beinc_prnt('Parsing {0}...'.format(beinc_config_file_str))
309 499
310 custom_error = 'load error' 500 custom_error = 'load error'
311 with open(beinc_config_file_str, 'r') as fp: 501 with open(beinc_config_file_str, 'r') as fp:
312 config_dict = json.load(fp) 502 config_dict = json.load(fp)
313 503
314 # clear the target-list
315 target_list = []
316
317 custom_error = 'target parse error' 504 custom_error = 'target parse error'
505 global_values['use_current_buffer'] = bool(config_dict['irc_client'].get(
506 'use_current_buffer', False))
318 for target in config_dict['irc_client']['targets']: 507 for target in config_dict['irc_client']['targets']:
319 try: 508 try:
320 new_target = WeechatTarget(target) 509 new_target = WeechatTarget(target)
321 except Exception as e: 510 except Exception as e:
322 weechat.prnt('', 'Unable to add target: {0}'.format(e)) 511 beinc_prnt('Unable to add target: {0}'.format(e))
323 continue 512 continue
324 global_values['global_chans'].update(new_target.chans) 513 global_values['global_chans'].update(new_target.chans)
325 global_values['global_nicks'].update(new_target.nicks) 514 global_values['global_nicks'].update(new_target.nicks)
@@ -331,12 +520,12 @@ def beinc_init():
331 global_values['global_notifications_policy'] = True 520 global_values['global_notifications_policy'] = True
332 521
333 target_list.append(new_target) 522 target_list.append(new_target)
334 weechat.prnt('', 'BEINC target {0} added'.format(new_target.name)) 523 beinc_prnt('BEINC target "{0}" added'.format(new_target.name))
335 524
336 weechat.prnt('', 'Done!!!') 525 beinc_prnt('Done!')
337 526
338 except Exception as e: 527 except Exception as e:
339 weechat.prnt('', 'ERROR: unable to parse {0}: {1} - {2}'.format( 528 beinc_prnt('ERROR: unable to parse {0}: {1} - {2}'.format(
340 beinc_config_file_str, custom_error, e)) 529 beinc_config_file_str, custom_error, e))
341 enabled = False 530 enabled = False
342 531
diff --git a/bosd.py b/bosd.py
deleted file mode 100644
index d678754..0000000
--- a/bosd.py
+++ /dev/null
@@ -1,101 +0,0 @@
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import urllib
5import urllib2
6
7import weechat
8
9#### CONFIG ####
10enabled = True
11
12notify_channels = [
13 "RedpillLinpro.#python",
14 "Exile.#hin",
15 "RedpillLinpro.#adult",
16 "Exile.#pichove"
17 ]
18
19connections = [ {'bosd_url': 'https://127.0.0.1:9999/npush/',
20 'bosd_password': '1234'},
21
22# {'bosd_url': 'https://pichove.org:9999/npush/',
23# 'bosd_port': 9999,
24# 'bosd_password': 'foo'},
25 ]
26################
27
28__VERSION__ = '2.0'
29
30def bosd_send_message(header='', message=''):
31 for conn in connections:
32 try:
33 conn['nheader'] = header # notification header
34 conn['nmessage'] = message # notification message
35
36 data = urllib.urlencode(conn)
37
38 req = urllib2.Request(url, data)
39 urllib2.urlopen(req)
40 #weechat.prnt("", message)
41 except:
42 continue
43
44 return True
45
46
47def bosd_command(data, buffer, args):
48 global enabled
49 if args == 'on':
50 enabled = True
51 weechat.prnt(weechat.current_buffer(), "bosd on")
52 elif args == 'off':
53 enabled = False
54 weechat.prnt(weechat.current_buffer(), "bosd off")
55 else:
56 bosd_send_message('BOSD generic', args)
57
58 return weechat.WEECHAT_RC_OK
59
60
61def bosd_privmsg_handler(data, signal, signal_data):
62 if not enabled:
63 return weechat.WEECHAT_RC_OK
64
65 prvmsg_dict = weechat.info_get_hashtable("irc_message_parse",
66 { "message": signal_data })
67
68
69 server = signal.split(",")[0]
70
71 # channel = signal_data.split(":")[-1]
72 # my_nick = weechat.info_get("irc_nick_from_host", signal_data)
73
74 my_nick = weechat.info_get("irc_nick", server)
75 channel = prvmsg_dict['arguments'].split(":")[0].strip()
76 nick = prvmsg_dict['nick']
77 message = ':'.join(prvmsg_dict['arguments'].split(':')[1:]).strip()
78
79 if (my_nick in message) or ('{0}.{1}'.format(server,channel) in notify_channels):
80 template_msg = '{0} @ {1} - {2}: {3}'.format(channel,
81 server,
82 nick,
83 message)
84 bosd_send_xosd_message(template_msg)
85
86 if my_nick in channel:
87 template_msg = '{0} @ {1}: {2}'.format(nick, server, message)
88 bosd_send_xosd_message(template_msg)
89
90 #my_str = "%s - %s - %s - %s" % (my_nick, server, channel, message)
91 #weechat.prnt("", my_str)
92
93 return weechat.WEECHAT_RC_OK
94
95
96
97weechat.register('bosd', 'Simeon Simeonov', '1.0', 'GPL3', 'Socket notification script', "", "")
98weechat.hook_command("bosd", "bosd on off toggle", "<on | off>", "description...", "None", "bosd_command", "")
99weechat.hook_signal("*,irc_in2_privmsg", "bosd_privmsg_handler", "")
100
101weechat.prnt("", "bosd initiated!")
diff --git a/bpynotify_orm.py b/bpynotify_orm.py
deleted file mode 100644
index 0540d0a..0000000
--- a/bpynotify_orm.py
+++ /dev/null
@@ -1,32 +0,0 @@
1# -*- coding: utf-8 -*-
2
3import datetime
4
5from sqlalchemy import schema, types
6from sqlalchemy.orm import mapper
7
8metadata = schema.MetaData()
9
10notification_entry_table = schema.Table('notification_entries', metadata,
11 schema.Column('id', types.Integer, primary_key=True),
12 schema.Column('timestamp', types.DateTime),
13 schema.Column('message', types.Unicode(), default = u'Empty message'),
14 schema.Column('viewed', types.Boolean, default=False)
15 )
16
17
18
19class NotificationEntry(object):
20
21 def __init__(self, message):
22
23 self.timestamp = datetime.datetime.now()
24 self.message = message
25
26
27 def __repr__(self):
28
29 return message
30
31
32mapper(NotificationEntry, notification_entry_table)
diff --git a/socket_server.py b/socket_server.py
deleted file mode 100755
index c68e500..0000000
--- a/socket_server.py
+++ /dev/null
@@ -1,77 +0,0 @@
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import SocketServer
5import os
6import sys
7
8from sqlalchemy import create_engine
9from sqlalchemy.orm import sessionmaker
10
11from bpynotify_orm import NotificationEntry, notification_entry_table
12
13
14class CustomSocketServer(SocketServer.TCPServer):
15
16 def __init__(self, server_address, RequestHandlerClass, session):
17 #super(CustomSocketServer, self).__init__(server_address,
18 # RequestHandlerClass)
19 SocketServer.TCPServer.__init__(self,
20 server_address,
21 RequestHandlerClass)
22 self.session = session
23
24
25class MyTCPHandler(SocketServer.StreamRequestHandler):
26 """
27 The RequestHandler class for our server.
28
29 It is instantiated once per connection to the server, and must
30 override the handle() method to implement communication to the
31 client.
32 """
33
34 def handle(self):
35
36 self.data = self.rfile.readline().decode('utf8').strip()
37 #print(self.data)
38 entry = NotificationEntry(self.data)
39 self.server.session.add(entry)
40 self.server.session.commit()
41
42
43def main():
44
45 HOST, PORT = "localhost", 9997
46
47 if len(sys.argv) == 2 and sys.argv[1] == '-d':
48 try:
49 pid = os.fork()
50 if pid > 0:
51 sys.exit(0)
52 except Exception as e:
53 sys.stderr.write("Unable to daemonize. Fork error: {0}".format(e))
54 sys.exit(1)
55
56 try:
57
58 engine = create_engine('sqlite:///notifications.db')
59 Session = sessionmaker(bind=engine) # bound session
60 session = Session()
61
62 server = CustomSocketServer((HOST, PORT), MyTCPHandler, session)
63
64 # clean all previous entries #
65 notification_entry_table.delete(bind=engine).execute()
66
67 server.serve_forever()
68
69 except Exception as e:
70 sys.stderr.write("Server error: {0}".format(e))
71 sys.exit(1)
72
73 sys.exit(0)
74
75
76if __name__ == "__main__":
77 main()
diff --git a/web_server.py b/web_server.py
deleted file mode 100755
index cec8c38..0000000
--- a/web_server.py
+++ /dev/null
@@ -1,47 +0,0 @@
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import sys
5
6import cherrypy
7
8class WebNotifyServer(object):
9
10 def __init__(self):
11 self.counter = 0
12
13 @cherrypy.expose
14 def notifications(self, **kwargs):
15 self.counter += 1
16 print(str(kwargs))
17 print(self.counter)
18 return ("called")
19
20
21 @cherrypy.expose
22 def other(self, **kwargs):
23 self.counter += 1
24 print(str(kwargs))
25 print(self.counter)
26 return ("called")
27
28
29def main():
30
31 cherrypy.config.update({
32 'server.socket_host': '10.0.0.4',
33 'server.socket_port': 40003,
34 })
35
36 try:
37 cherrypy.quickstart(WebNotifyServer())
38
39 except Exception as e:
40 sys.stderr.write("WebServer error: {0}".format(e))
41 sys.exit(1)
42
43 sys.exit(0)
44
45
46if __name__ == "__main__":
47 main()
diff --git a/weechat_notify.py b/weechat_notify.py
deleted file mode 100755
index 897f26d..0000000
--- a/weechat_notify.py
+++ /dev/null
@@ -1,49 +0,0 @@
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import json
5import urllib2
6import sched
7import sys
8import time
9
10import pynotify
11
12POLLING_FREQUENCY = 10
13NOTIFICATION_URL = 'https://simeon.simeonov.no:40004/notifications/'
14TIMEOUT_SEC = 3
15
16
17def poll_notifications(scheduler):
18 """
19 """
20 try:
21 req = urllib2.Request(NOTIFICATION_URL)
22 response = urllib2.urlopen(req)
23 response_str = response.read()
24
25 entries = json.loads(response_str)
26 for entry in entries:
27 n = pynotify.Notification('IRC', entry, 'dialog-information')
28 n.set_timeout(TIMEOUT_SEC)
29 n.show()
30
31 except Exception as e:
32 sys.stderr.write("Client error: {0}".format(e))
33 sys.exit(1)
34
35 scheduler.enter(POLLING_FREQUENCY, 1, poll_notifications, (scheduler,))
36
37
38def main():
39
40 if not pynotify.init("Weechat Notify"):
41 sys.stderr.write("There was a problem with libnotify")
42 sys.exit(1)
43
44 sc = sched.scheduler(time.time, time.sleep)
45 sc.enter(POLLING_FREQUENCY, 1, poll_notifications, (sc,))
46 sc.run()
47
48if __name__ == '__main__':
49 main()
diff --git a/weechat_notify_server.py b/weechat_notify_server.py
deleted file mode 100755
index 35d4f42..0000000
--- a/weechat_notify_server.py
+++ /dev/null
@@ -1,116 +0,0 @@
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import json
5import SocketServer
6import os
7import sys
8
9from multiprocessing import Process, Queue
10
11import cherrypy
12
13import settings
14
15
16class CustomSocketServer(SocketServer.TCPServer):
17
18 def __init__(self, server_address, RequestHandlerClass, queue):
19 SocketServer.TCPServer.__init__(self,
20 server_address,
21 RequestHandlerClass)
22 self.queue = queue
23
24
25class MyTCPHandler(SocketServer.StreamRequestHandler):
26 """
27 The RequestHandler class for our server.
28
29 It is instantiated once per connection to the server, and must
30 override the handle() method to implement communication to the
31 client.
32 """
33
34 def handle(self):
35
36 data = self.rfile.readline().strip()
37
38 if self.server.queue.qsize() > 3:
39 self.server.queue.get()
40
41 self.server.queue.put(data)
42 #print(self.data)
43
44
45class WebNotifyServer(object):
46
47 def __init__(self, queue):
48 self.queue = queue
49
50 @cherrypy.expose
51 def notifications(self):
52
53 entry_list = list()
54
55 while not self.queue.empty():
56 entry_list.append(self.queue.get(False))
57
58 #print (json.dumps(entry_list, sort_keys=True, indent=4))
59 return json.dumps(entry_list)
60
61
62def socket_server(queue):
63
64 try:
65 server = CustomSocketServer((settings.SOCKET_SERVER_HOST,
66 settings.SOCKET_SERVER_PORT),
67 MyTCPHandler,
68 queue)
69 server.serve_forever()
70
71 except Exception as e:
72 sys.stderr.write("SocketServer error: {0}".format(e))
73 sys.exit(1)
74
75 sys.exit(0)
76
77
78
79def web_server(queue):
80
81 cherrypy.config.update({
82 'server.socket_host': settings.WEB_SERVER_HOST,
83 'server.socket_port': settings.WEB_SERVER_PORT,
84 'server.ssl_module': 'pyopenssl',
85 'server.ssl_certificate': settings.WEB_SERVER_CERT,
86 'server.ssl_private_key': settings.WEB_SERVER_KEY,
87 })
88
89 try:
90
91 cherrypy.quickstart(WebNotifyServer(queue))
92
93 except Exception as e:
94 sys.stderr.write("WebServer error: {0}".format(e))
95 sys.exit(1)
96
97 sys.exit(0)
98
99
100def main():
101
102 q = Queue()
103
104 socket_server_process = Process(target=socket_server, args=(q,))
105 web_server_process = Process(target=web_server, args=(q,))
106
107 web_server_process.start()
108 socket_server_process.start()
109
110 socket_server_process.join()
111 web_server_process.join()
112
113 sys.exit(0)
114
115if __name__ == "__main__":
116 main()