diff options
| author | Simeon Simeonov | 2014-04-29 20:37:32 +0200 |
|---|---|---|
| committer | Simeon Simeonov | 2014-04-29 20:37:32 +0200 |
| commit | 833ddeb822493f6ab2abd6f193b4c0bc8ea76854 (patch) | |
| tree | f7f9b55595be52aa8ff29be04428f70a000f780e /beinc_weechat.py | |
| parent | 504c118c5535d3e2e1c943e9ae354b1048604be3 (diff) | |
Overall design finished
Diffstat (limited to 'beinc_weechat.py')
| -rw-r--r-- | beinc_weechat.py | 340 |
1 files changed, 283 insertions, 57 deletions
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 | ||
| 4 | import datetime | ||
| 5 | import httplib | ||
| 4 | import json | 6 | import json |
| 5 | import os | 7 | import os |
| 8 | import random | ||
| 6 | import socket | 9 | import socket |
| 10 | import ssl | ||
| 7 | import sys | 11 | import sys |
| 12 | import urllib | ||
| 13 | import urllib2 | ||
| 8 | 14 | ||
| 9 | import weechat | 15 | import weechat |
| 10 | 16 | ||
| 11 | enabled = True | 17 | enabled = True |
| 18 | global_values = dict() | ||
| 19 | |||
| 20 | # few constants # | ||
| 21 | BEINC_POLICY_NONE = 0 | ||
| 22 | BEINC_POLICY_ALL = 1 | ||
| 23 | BEINC_POLICY_LIST_ONLY = 2 | ||
| 24 | |||
| 25 | |||
| 26 | |||
| 27 | class 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 | |||
| 50 | class 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 | ||
| 13 | class WeechatTarget(object): | 61 | class 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 | ||
| 32 | def 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 | ||
| 46 | def bosd_command(data, buffer, args): | 218 | def beinc_send_message(message): |
| 219 | weechat.prnt(weechat.current_buffer(), 'beinc message: {0}'.format(message)) | ||
| 220 | |||
| 221 | |||
| 222 | def 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 | ||
| 62 | def bosd_privmsg_handler(data, signal, signal_data): | 242 | def 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 | ||
| 138 | weechat.register('beinc_weechat', 'Simeon Simeonov', '1.0', 'GPL3', 'Blackmore\'s Extended IRC Notification Collection (Weechat Client)', '', '') | ||
| 139 | weechat.hook_command('beinc', 'beinc on off toggle', '<on | off | reload>', 'description...', 'None', 'beinc_command', '') | ||
| 140 | weechat.hook_signal('*,irc_in2_privmsg', 'beinc_privmsg_handler', '') | ||
| 141 | |||
| 142 | beinc_init() | ||
| 143 | 350 | ||
| 144 | weechat.prnt('', 'beinc initiated!') | 351 | weechat.register('beinc_weechat', |
| 352 | 'Simeon Simeonov', | ||
| 353 | '1.0', | ||
| 354 | 'GPL3', | ||
| 355 | 'Blackmore\'s Extended IRC Notification Collection (Weechat Client)', | ||
| 356 | '', | ||
| 357 | '') | ||
| 358 | version = weechat.info_get('version_number', '') or 0 | ||
| 359 | if int(version) < 0x00040000: | ||
| 360 | weechat.prnt('', 'WeeChat version >= 0.4.0 is required to run beinc') | ||
| 361 | else: | ||
| 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!') | ||
