summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimeon Simeonov2014-04-29 20:37:32 +0200
committerSimeon Simeonov2014-04-29 20:37:32 +0200
commit833ddeb822493f6ab2abd6f193b4c0bc8ea76854 (patch)
treef7f9b55595be52aa8ff29be04428f70a000f780e
parent504c118c5535d3e2e1c943e9ae354b1048604be3 (diff)
Overall design finished
-rw-r--r--beinc_server.json80
-rwxr-xr-xbeinc_server.py6
-rw-r--r--beinc_weechat.py340
3 files changed, 330 insertions, 96 deletions
diff --git a/beinc_server.json b/beinc_server.json
index 0bdcc8a..2824dea 100644
--- a/beinc_server.json
+++ b/beinc_server.json
@@ -1,42 +1,48 @@
1{ 1{
2 "server": { 2 "server": {
3 "general": { 3 "general": {
4 "ssl_module": "pyopenssl", 4 "ssl_module": "pyopenssl",
5 "ssl_private_key": "key.pem", 5 "ssl_private_key": "key.pem",
6 "ssl_certificate": "cert.crt" 6 "ssl_certificate": "cert.crt"
7 }, 7 },
8 8
9 "instances": [ 9 "instances": [
10 { 10 {
11 "name": "test", 11 "name": "test",
12 "password": "changeme", 12 "password": "changeme",
13 "osd_system": "pynotify", 13 "osd_system": "pynotify",
14 "osd_timeout": 5000, 14 "osd_timeout": 5000,
15 "queue_size": 4 15 "queue_size": 4
16 } 16 }
17 ] 17 ]
18 }, 18 },
19 19
20 "irc_client": { 20 "irc_client": {
21 "targets": [ 21 "targets": [
22 { 22 {
23 "name": "weechat_main", 23 "name": "weechat_main",
24 "target_url": "", 24 "target_url": "",
25 "target_password": "changeme", 25 "target_password": "changeme",
26 "title_template": "", 26 "target_cert_file": "",
27 "message_template": "", 27 "target_timestamp_format": "%H:%M:%S",
28 "channel_list": ["RedpillLinpro.#python", 28 "pm_title_template": "",
29 "Exile.#hin", 29 "pm_message_template": "",
30 "RedpillLinpro.#adult", 30 "cm_title_template": "",
31 "Exile.#pichove"], 31 "cm_message_template": "",
32 "nick_list": "", 32 "nm_title_template": "",
33 "channel_messages_policy": 0, 33 "nm_message_template": "",
34 "private_messages_policy": 0, 34 "channel_list": ["RedpillLinpro.#python",
35 "notifications_policy": 0 35 "Exile.#hin",
36 } 36 "RedpillLinpro.#adult",
37 ] 37 "Exile.#pichove"],
38 }, 38 "nick_list": ["Exile.Blackmore"],
39 39 "channel_messages_policy": 0,
40 "config_version": 1 40 "private_messages_policy": 0,
41 "notifications_policy": 0
42 }
43 ]
44 },
41 45
46 "config_version": 1
47
42} 48}
diff --git a/beinc_server.py b/beinc_server.py
index 300c954..8687da3 100755
--- a/beinc_server.py
+++ b/beinc_server.py
@@ -206,12 +206,13 @@ class WebNotifyServer(object):
206 try: 206 try:
207 instance = self.__instances[args[0]] 207 instance = self.__instances[args[0]]
208 except Exception as e: 208 except Exception as e:
209 sys.stderr.write('Wrong instance or password: {0}\n'.format(e)) 209 sys.stderr.write('Wrong instance or password\n')
210 #print('DEBUG: {0}'.format(e))
210 raise cherrypy.HTTPError('403 Forbidden', 211 raise cherrypy.HTTPError('403 Forbidden',
211 'Wrong instance or password') 212 'Wrong instance or password')
212 213
213 if not instance.password_match(kwargs.get('password')): 214 if not instance.password_match(kwargs.get('password')):
214 sys.stderr.write('Wrong instance or password: {0}\n'.format(e)) 215 sys.stderr.write('Wrong instance or password\n')
215 raise cherrypy.HTTPError('403 Forbidden', 216 raise cherrypy.HTTPError('403 Forbidden',
216 'Wrong instance or password') 217 'Wrong instance or password')
217 218
@@ -282,6 +283,7 @@ def main():
282 except Exception as e: 283 except Exception as e:
283 sys.stderr.write('Unable to parse {0}: {1}'.format(args.config_file, 284 sys.stderr.write('Unable to parse {0}: {1}'.format(args.config_file,
284 e)) 285 e))
286 sys.exit(1)
285 287
286 cherrypy.config.update({ 288 cherrypy.config.update({
287 'server.socket_host': args.hostname, 289 'server.socket_host': args.hostname,
diff --git a/beinc_weechat.py b/beinc_weechat.py
index 4abf6f1..689f450 100644
--- a/beinc_weechat.py
+++ b/beinc_weechat.py
@@ -1,14 +1,62 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2# -*- coding: utf-8 -*- 2# -*- coding: utf-8 -*-
3 3
4import datetime
5import httplib
4import json 6import json
5import os 7import os
8import random
6import socket 9import socket
10import ssl
7import sys 11import sys
12import urllib
13import urllib2
8 14
9import weechat 15import weechat
10 16
11enabled = True 17enabled = True
18global_values = dict()
19
20# few constants #
21BEINC_POLICY_NONE = 0
22BEINC_POLICY_ALL = 1
23BEINC_POLICY_LIST_ONLY = 2
24
25
26
27class ValidHTTPSConnection(httplib.HTTPConnection):
28 """
29 """
30
31 default_port = httplib.HTTPS_PORT
32
33 def __init__(self, cert_file, *args, **kwargs):
34 httplib.HTTPConnection.__init__(self, *args, **kwargs)
35 self.__cert_file = cert_file
36
37
38 def connect(self):
39 sock = socket.create_connection((self.host, self.port),
40 self.timeout, self.source_address)
41 if self._tunnel_host:
42 self.sock = sock
43 self._tunnel()
44 self.sock = ssl.wrap_socket(sock,
45 ca_certs=self.__cert_file,
46 cert_reqs=ssl.CERT_REQUIRED)
47
48
49
50class ValidHTTPSHandler(urllib2.HTTPSHandler):
51
52 def __init__(self, cert_file, *args, **kwargs):
53 urllib2.HTTPSHandler.__init__(self, *args, **kwargs)
54 self.__cert_file = cert_file
55
56 def https_open(self, req):
57 return self.do_open(ValidHTTPSConnection(self.__cert_file), req)
58
59
12 60
13class WeechatTarget(object): 61class WeechatTarget(object):
14 """ 62 """
@@ -18,80 +66,223 @@ class WeechatTarget(object):
18 """ 66 """
19 target_dict: the config-dictionary node that represents this instance 67 target_dict: the config-dictionary node that represents this instance
20 """ 68 """
69 self.__name = target_dict.get(
70 'name',
71 ''.join([chr(random.randrange(97, 123)) for x in range(4)]))
72 self.__url = target_dict.get('target_url')
73 self.__password = target_dict.get('target_password')
74
75 self.__pm_title_template = target_dict.get('pm_title_template',
76 '%s @ %S')
77 self.__pm_message_template = target_dict.get('pm_message_template',
78 '%m')
79
80 self.__cm_title_template = target_dict.get('cm_title_template',
81 '%c @ %S')
82 self.__cm_message_template = target_dict.get('cm_message_template',
83 '%s -> %m')
84
85 self.__nm_title_template = target_dict.get('nm_title_template',
86 '%c @ %S')
87 self.__nm_message_template = target_dict.get('nm_message_template',
88 '%s -> %m')
89
90 self.__chans = set(target_dict.get('channel_list', list()))
91 self.__nicks = set(target_dict.get('nick_list', list()))
92 self.__chan_messages_policy = int(target_dict.get(
93 'channel_messages_policy',
94 BEINC_POLICY_LIST_ONLY))
95 self.__priv_messages_policy = int(target_dict.get(
96 'private_messages_policy',
97 BEINC_POLICY_ALL))
98 self.__notifications_policy = int(target_dict.get(
99 'notifications_policy',
100 BEINC_POLICY_ALL))
101 self.__cert_file = target_dict.get('target_cert_file')
102 self.__timestamp_format = target_dict.get('target_timestamp_format',
103 '%H:%M:%S')
104
105
106 @property
107 def name(self):
108 """
109 """
110 return self.__name
111
112
113 @property
114 def chans(self):
115 """
116 """
117 return self.__chans
118
119
120 @property
121 def nicks(self):
122 """
123 """
124 return self.__nicks
125
126
127 @property
128 def channel_messages_policy(self):
129 """
130 """
131 return self.__chan_messages_policy
132
133
134 @property
135 def private_messages_policy(self):
136 """
137 """
138 return self.__priv_messages_policy
139
140
141 @property
142 def notifications_policy(self):
143 """
144 """
145 return self.__notifications_policy
146
147
148 def __repr__(self):
149 """
150 """
151
152 return 'name: {0}\nurl: {1}\nchannel_list: {2}\nnick_list: {3}'\
153 'channel_messages_policy: {4}\nprivate_messages_policy: {5}'\
154 'notifications_policy: {6}'.format(self.__name,
155 self.__url,
156 ', '.join(self.__chans),
157 ', '.join(self.__nicks),
158 self.__chan_message_policy,
159 self.__priv_message_policy,
160 self.__notifications_policy)
161
162
163 def send_private_message_notification(self, message, values):
164 """
165 """
166 pass
167
168
169 def send_channel_message_notification(self, message, values):
170 """
171 """
172 pass
21 173
22 self.__name = target_dict['name']
23 self.__url = target_dict['target_url']
24 self.__password = target_dict['target_password']
25 self.__title_template = target_dict['title_template']
26 self.__message_template = target_dict['message_template']
27 self.__failed = False
28 174
175 def send_notify_message_notification(self, message, values):
176 """
177 """
178 pass
179
180
181 def __fetch_formatted_str(self, template, values):
182 """
183 """
184 replacements = {'%S': values['server'],
185 '%s': values['source_nick'],
186 '%c': values['channel'],
187 '%m': values['message'],
188 '%t': values['timestamp'],
189 '%p': 'BEINC',
190 '%n': values['own_nick']}
191 for key, value in replacements.items():
192 template = template.replace(key, value)
193 return template
29 194
30 195
196 def __send_beinc_message(self, data):
197 """
198 the function implements the BEINC "protocol" by generating a simple
199 HTTP request
200 """
31 201
32def bosd_send_xosd_message(message):
33 for conn in connections:
34 try: 202 try:
35 #weechat.prnt("", message) 203 req = urllib2.Request(self.__url, data)
36 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 204 opener = urllib2.build_opener(ValidHTTPSHandler)
37 s.connect((conn['sbosdd_ip'], conn['sbosdd_port'])) 205
38 s.send(message) 206 response = opener.open(req)
39 s.close() 207 res_code = response.code
40 except: 208 response.close()
41 continue 209 if res_code == 200:
210 return True
211 except Exception as e:
212 weechat.prnt(weechat.current_buffer(),
213 'DEBUG: send_beinc_message-ERROR: {0}'.format(e))
214 return False
42 215
43 return True
44 216
45 217
46def bosd_command(data, buffer, args): 218def beinc_send_message(message):
219 weechat.prnt(weechat.current_buffer(), 'beinc message: {0}'.format(message))
220
221
222def beinc_command(data, buffer, args):
47 global enabled 223 global enabled
48 if args == 'on': 224 if args == 'on':
49 enabled = True 225 enabled = True
50 weechat.prnt(weechat.current_buffer(), 'bosd on') 226 weechat.prnt(weechat.current_buffer(), 'beinc on')
51 elif args == 'off': 227 elif args == 'off':
52 enabled = False 228 enabled = False
53 weechat.prnt(weechat.current_buffer(), 'bosd off') 229 weechat.prnt(weechat.current_buffer(), 'beinc off')
54 elif args == 'reload': 230 elif args == 'reload':
55 weechat.prnt(weechat.current_buffer(), '{0} reloaded') 231 beinc_config_file_str = os.path.join(
232 weechat.info_get('weechat_dir', ''),
233 'beinc.json')
234 weechat.prnt(weechat.current_buffer(), '{0} reloaded'.format(
235 beinc_config_file_str))
56 else: 236 else:
57 bosd_send_xosd_message(args) 237 beinc_send_message(args)
58 238
59 return weechat.WEECHAT_RC_OK 239 return weechat.WEECHAT_RC_OK
60 240
61 241
62def bosd_privmsg_handler(data, signal, signal_data): 242def beinc_privmsg_handler(data, signal, signal_data):
63 if not enabled: 243 if not enabled:
64 return weechat.WEECHAT_RC_OK 244 return weechat.WEECHAT_RC_OK
65 245
66 prvmsg_dict = weechat.info_get_hashtable("irc_message_parse", 246 prvmsg_dict = weechat.info_get_hashtable('irc_message_parse',
67 { "message": signal_data }) 247 {'message': signal_data })
68 248
249 # packing the privmsg handler values
250 ph_values = dict()
251 ph_values['server'] = signal.split(',')[0]
252 ph_values['own_nick'] = weechat.info_get('irc_nick', server)
253 ph_values['channel'] = prvmsg_dict['arguments'].split(':')[0].strip()
254 ph_values['source_nick'] = prvmsg_dict['nick']
255 ph_values['message'] = ':'.join(
256 prvmsg_dict['arguments'].split(':')[1:]).strip()
257 ph_values['timestamp'] = datetime.datetime.now().strftime(
258 self.__timestamp_format)
69 259
70 server = signal.split(",")[0] 260 if ph_values['channel'] == ph_values['own_nick']:
71 261 # priv messages are handled here
72 # channel = signal_data.split(":")[-1] 262 if not global_values['global_channel_messages_policy']:
73 # my_nick = weechat.info_get("irc_nick_from_host", signal_data) 263 return weechat.WEECHAT_RC_OK
74
75 my_nick = weechat.info_get("irc_nick", server)
76 channel = prvmsg_dict['arguments'].split(":")[0].strip()
77 nick = prvmsg_dict['nick']
78 message = ':'.join(prvmsg_dict['arguments'].split(':')[1:]).strip()
79
80 if (my_nick.lower() in message.lower()) or ('{0}.{1}'.format(server,channel.lower()) in notify_channels):
81 template_msg = '{0} @ {1} - {2}: {3}'.format(channel,
82 server,
83 nick,
84 message)
85 bosd_send_xosd_message(template_msg)
86 264
87 if my_nick.lower() in channel.lower(): 265 for target in target_list:
88 template_msg = '{0} @ {1}: {2}'.format(nick, server, message) 266 if target.private_messages_policy == 1 or (
89 bosd_send_xosd_message(template_msg) 267 target.private_messages_policy == 2 \
268 and '{0}.{1}'.format(
269 ph_values['server'],
270 ph_values['source_nick'].lower()) in target.nicks):
271 weechat.prnt(weechat.current_buffer(),
272 'DEBUG: priv message - {0}'.format(
273 ph_values['message']))
90 274
91 # weechat.prnt("", 275 elif privmsg_handler_values['own_nick'].lower() in ph_values['message'].lower():
92 # 'DEBUG: my_nick - {0}, server - {1}, channel - {2}'.format(my_nick, 276 # notify messages are handled here
93 # server, 277 weechat.prnt(weechat.current_buffer(),
94 # channel)) 278 'DEBUG: notify message - {0}'.format(ph_values['message']))
279 if not global_values['global_notifications_policy']:
280 return weechat.WEECHAT_RC_OK
281
282 elif global_values['global_channel_messages_policy']:
283 # chan messages are handled here
284 weechat.prnt(weechat.current_buffer(),
285 'DEBUG: chan message - {0}'.format(ph_values['message']))
95 286
96 return weechat.WEECHAT_RC_OK 287 return weechat.WEECHAT_RC_OK
97 288
@@ -100,13 +291,20 @@ def beinc_init():
100 291
101 global enabled 292 global enabled
102 global target_list 293 global target_list
294 global global_values
103 295
296 global_values['global_chans'] = set()
297 global_values['global_nicks'] = set()
104 custom_error = '' 298 custom_error = ''
105 299
300 global_values['global_channel_messages_policy'] = False
301 global_values['global_private_messages_policy'] = False
302 global_values['global_notifications_policy'] = False
303
106 try: 304 try:
107 beinc_config_file_str = os.path.join(weechat.info_get('weechat_dir', 305 beinc_config_file_str = os.path.join(
108 ''), 306 weechat.info_get('weechat_dir', ''),
109 'beinc.json') 307 'beinc.json')
110 weechat.prnt('', 'Parsing {0}...'.format(beinc_config_file_str)) 308 weechat.prnt('', 'Parsing {0}...'.format(beinc_config_file_str))
111 309
112 custom_error = 'load error' 310 custom_error = 'load error'
@@ -118,8 +316,22 @@ def beinc_init():
118 316
119 custom_error = 'target parse error' 317 custom_error = 'target parse error'
120 for target in config_dict['irc_client']['targets']: 318 for target in config_dict['irc_client']['targets']:
121 new_target = WeechatTarget(target) 319 try:
320 new_target = WeechatTarget(target)
321 except Exception as e:
322 weechat.prnt('', 'Unable to add target: {0}'.format(e))
323 continue
324 global_values['global_chans'].update(new_target.chans)
325 global_values['global_nicks'].update(new_target.nicks)
326 if new_target.channel_messages_policy:
327 global_values['global_channel_messages_policy'] = True
328 if new_target.private_messages_policy:
329 global_values['global_private_messages_policy'] = True
330 if new_target.notifications_policy:
331 global_values['global_notifications_policy'] = True
332
122 target_list.append(new_target) 333 target_list.append(new_target)
334 weechat.prnt('', 'BEINC target {0} added'.format(new_target.name))
123 335
124 weechat.prnt('', 'Done!!!') 336 weechat.prnt('', 'Done!!!')
125 337
@@ -135,10 +347,24 @@ def beinc_init():
135 return weechat.WEECHAT_RC_OK 347 return weechat.WEECHAT_RC_OK
136 348
137 349
138weechat.register('beinc_weechat', 'Simeon Simeonov', '1.0', 'GPL3', 'Blackmore\'s Extended IRC Notification Collection (Weechat Client)', '', '')
139weechat.hook_command('beinc', 'beinc on off toggle', '<on | off | reload>', 'description...', 'None', 'beinc_command', '')
140weechat.hook_signal('*,irc_in2_privmsg', 'beinc_privmsg_handler', '')
141
142beinc_init()
143 350
144weechat.prnt('', 'beinc initiated!') 351weechat.register('beinc_weechat',
352 'Simeon Simeonov',
353 '1.0',
354 'GPL3',
355 'Blackmore\'s Extended IRC Notification Collection (Weechat Client)',
356 '',
357 '')
358version = weechat.info_get('version_number', '') or 0
359if int(version) < 0x00040000:
360 weechat.prnt('', 'WeeChat version >= 0.4.0 is required to run beinc')
361else:
362 weechat.hook_command('beinc',
363 'beinc on off toggle', '<on | off | reload>',
364 'description...',
365 'None',
366 'beinc_command',
367 '')
368 weechat.hook_signal('*,irc_in2_privmsg', 'beinc_privmsg_handler', '')
369 beinc_init()
370 weechat.prnt('', 'beinc initiated!')