diff options
| -rw-r--r-- | beinc_server.json | 20 | ||||
| -rwxr-xr-x | beinc_server.py | 52 | ||||
| -rw-r--r-- | beinc_weechat.py | 144 | ||||
| -rwxr-xr-x | weechat_notify.py | 3 |
4 files changed, 180 insertions, 39 deletions
diff --git a/beinc_server.json b/beinc_server.json index 8fa042c..0bdcc8a 100644 --- a/beinc_server.json +++ b/beinc_server.json | |||
| @@ -17,7 +17,25 @@ | |||
| 17 | ] | 17 | ] |
| 18 | }, | 18 | }, |
| 19 | 19 | ||
| 20 | "client": {}, | 20 | "irc_client": { |
| 21 | "targets": [ | ||
| 22 | { | ||
| 23 | "name": "weechat_main", | ||
| 24 | "target_url": "", | ||
| 25 | "target_password": "changeme", | ||
| 26 | "title_template": "", | ||
| 27 | "message_template": "", | ||
| 28 | "channel_list": ["RedpillLinpro.#python", | ||
| 29 | "Exile.#hin", | ||
| 30 | "RedpillLinpro.#adult", | ||
| 31 | "Exile.#pichove"], | ||
| 32 | "nick_list": "", | ||
| 33 | "channel_messages_policy": 0, | ||
| 34 | "private_messages_policy": 0, | ||
| 35 | "notifications_policy": 0 | ||
| 36 | } | ||
| 37 | ] | ||
| 38 | }, | ||
| 21 | 39 | ||
| 22 | "config_version": 1 | 40 | "config_version": 1 |
| 23 | 41 | ||
diff --git a/beinc_server.py b/beinc_server.py index da47e22..300c954 100755 --- a/beinc_server.py +++ b/beinc_server.py | |||
| @@ -19,12 +19,11 @@ BEINC_OSD_TYPE_NONE = 0 | |||
| 19 | BEINC_OSD_TYPE_PYNOTIFY = 1 | 19 | BEINC_OSD_TYPE_PYNOTIFY = 1 |
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | |||
| 23 | class BEINCInstance(object): | 22 | class BEINCInstance(object): |
| 24 | """ | 23 | """ |
| 25 | Represents a single server-instance | 24 | Represents a single server-instance |
| 26 | """ | 25 | """ |
| 27 | 26 | ||
| 28 | def __init__(self, instance_dict): | 27 | def __init__(self, instance_dict): |
| 29 | """ | 28 | """ |
| 30 | instance_dict: the config-dictionary node that represents this instance | 29 | instance_dict: the config-dictionary node that represents this instance |
| @@ -38,7 +37,7 @@ class BEINCInstance(object): | |||
| 38 | self.__name = instance_dict['name'] | 37 | self.__name = instance_dict['name'] |
| 39 | self.__password = instance_dict['password'] | 38 | self.__password = instance_dict['password'] |
| 40 | self.__queue_size = int(instance_dict['queue_size']) | 39 | self.__queue_size = int(instance_dict['queue_size']) |
| 41 | 40 | ||
| 42 | except Exception as e: | 41 | except Exception as e: |
| 43 | sys.stderr.write( | 42 | sys.stderr.write( |
| 44 | 'Instance processing error {0}:\n{1}\n'.format(self.__name, | 43 | 'Instance processing error {0}:\n{1}\n'.format(self.__name, |
| @@ -50,7 +49,8 @@ class BEINCInstance(object): | |||
| 50 | sys.stderr.write( | 49 | sys.stderr.write( |
| 51 | 'This server does not possess pynotify capability\n') | 50 | 'This server does not possess pynotify capability\n') |
| 52 | sys.stderr.write( | 51 | sys.stderr.write( |
| 53 | "Remove the instance {0} or define it with 'osd_system': 'none'") | 52 | 'Remove the instance {0}'.format(self.__name)) |
| 53 | sys.stderr.write("or define it with 'osd_system': 'none'\n") | ||
| 54 | sys.exit(1) | 54 | sys.exit(1) |
| 55 | 55 | ||
| 56 | try: | 56 | try: |
| @@ -58,7 +58,7 @@ class BEINCInstance(object): | |||
| 58 | self.__osd_notification.set_timeout( | 58 | self.__osd_notification.set_timeout( |
| 59 | instance_dict['osd_timeout']) | 59 | instance_dict['osd_timeout']) |
| 60 | self.__osd_notification.set_property( | 60 | self.__osd_notification.set_property( |
| 61 | 'app_name', | 61 | 'app_name', |
| 62 | '{0} {1}'.format(sys.argv[0], __version__)) | 62 | '{0} {1}'.format(sys.argv[0], __version__)) |
| 63 | except Exception as e: | 63 | except Exception as e: |
| 64 | sys.stderr.write( | 64 | sys.stderr.write( |
| @@ -67,7 +67,6 @@ class BEINCInstance(object): | |||
| 67 | 67 | ||
| 68 | self.__osd_type = BEINC_OSD_TYPE_PYNOTIFY | 68 | self.__osd_type = BEINC_OSD_TYPE_PYNOTIFY |
| 69 | 69 | ||
| 70 | |||
| 71 | @property | 70 | @property |
| 72 | def name(self): | 71 | def name(self): |
| 73 | """ | 72 | """ |
| @@ -75,7 +74,6 @@ class BEINCInstance(object): | |||
| 75 | """ | 74 | """ |
| 76 | return self.__name | 75 | return self.__name |
| 77 | 76 | ||
| 78 | |||
| 79 | @property | 77 | @property |
| 80 | def queueable(self): | 78 | def queueable(self): |
| 81 | """ | 79 | """ |
| @@ -83,18 +81,13 @@ class BEINCInstance(object): | |||
| 83 | """ | 81 | """ |
| 84 | return bool(self.__queue_size) | 82 | return bool(self.__queue_size) |
| 85 | 83 | ||
| 86 | |||
| 87 | def password_match(self, password): | 84 | def password_match(self, password): |
| 88 | """ | 85 | """ |
| 89 | Returns True if 'passowrd' matches the instance-password, | 86 | Returns True if 'passowrd' matches the instance-password, |
| 90 | otherwise - False | 87 | otherwise - False |
| 91 | """ | 88 | """ |
| 92 | if self.__password == password: | 89 | return True if self.__password == password else False |
| 93 | return True | ||
| 94 | 90 | ||
| 95 | return False | ||
| 96 | |||
| 97 | |||
| 98 | def send_message(self, title, message): | 91 | def send_message(self, title, message): |
| 99 | """ | 92 | """ |
| 100 | Displays or enqueues the message, | 93 | Displays or enqueues the message, |
| @@ -105,7 +98,6 @@ class BEINCInstance(object): | |||
| 105 | else: | 98 | else: |
| 106 | self.__send_message_to_queue(title, message) | 99 | self.__send_message_to_queue(title, message) |
| 107 | 100 | ||
| 108 | |||
| 109 | def get_queue(self): | 101 | def get_queue(self): |
| 110 | """ | 102 | """ |
| 111 | Reruens a json representation of the message queue | 103 | Reruens a json representation of the message queue |
| @@ -114,7 +106,6 @@ class BEINCInstance(object): | |||
| 114 | self.__message_queue = list() | 106 | self.__message_queue = list() |
| 115 | return jstr | 107 | return jstr |
| 116 | 108 | ||
| 117 | |||
| 118 | def __send_pynotify_messaage(self, title, message): | 109 | def __send_pynotify_messaage(self, title, message): |
| 119 | """ | 110 | """ |
| 120 | Displays pynotify message | 111 | Displays pynotify message |
| @@ -123,7 +114,6 @@ class BEINCInstance(object): | |||
| 123 | self.__osd_notification.set_properties(summary=title, body=message) | 114 | self.__osd_notification.set_properties(summary=title, body=message) |
| 124 | self.__osd_notification.show() | 115 | self.__osd_notification.show() |
| 125 | 116 | ||
| 126 | |||
| 127 | def __send_message_to_queue(self, title, message): | 117 | def __send_message_to_queue(self, title, message): |
| 128 | """ | 118 | """ |
| 129 | Enqueues the message | 119 | Enqueues the message |
| @@ -135,7 +125,6 @@ class BEINCInstance(object): | |||
| 135 | self.__message_queue.append({'title': title, 'message': message}) | 125 | self.__message_queue.append({'title': title, 'message': message}) |
| 136 | 126 | ||
| 137 | 127 | ||
| 138 | |||
| 139 | def beinc_instance_login(method): | 128 | def beinc_instance_login(method): |
| 140 | """ | 129 | """ |
| 141 | decorator for checking login credentials | 130 | decorator for checking login credentials |
| @@ -160,20 +149,16 @@ def beinc_instance_login(method): | |||
| 160 | sys.stderr.write('Wrong instance or password: {0}\n'.format(e)) | 149 | sys.stderr.write('Wrong instance or password: {0}\n'.format(e)) |
| 161 | raise cherrypy.HTTPError('403 Forbidden', | 150 | raise cherrypy.HTTPError('403 Forbidden', |
| 162 | 'Wrong instance or password') | 151 | 'Wrong instance or password') |
| 163 | |||
| 164 | print('First') | ||
| 165 | 152 | ||
| 166 | if not instance.password_match(kwargs.get('password')): | 153 | if not instance.password_match(kwargs.get('password')): |
| 167 | raise cherrypy.HTTPError('403 Forbidden', | 154 | raise cherrypy.HTTPError('403 Forbidden', |
| 168 | 'Wrong instance or password') | 155 | 'Wrong instance or password') |
| 169 | 156 | ||
| 170 | print('second') | ||
| 171 | return method(self, *args, **kwargs) | 157 | return method(self, *args, **kwargs) |
| 172 | 158 | ||
| 173 | return tmp_func | 159 | return tmp_func |
| 174 | 160 | ||
| 175 | 161 | ||
| 176 | |||
| 177 | class WebNotifyServer(object): | 162 | class WebNotifyServer(object): |
| 178 | 163 | ||
| 179 | def __init__(self, config): | 164 | def __init__(self, config): |
| @@ -191,7 +176,6 @@ class WebNotifyServer(object): | |||
| 191 | sys.stderr.write('Unable to initialize queues: {0}\n'.format(e)) | 176 | sys.stderr.write('Unable to initialize queues: {0}\n'.format(e)) |
| 192 | sys.exit(1) | 177 | sys.exit(1) |
| 193 | 178 | ||
| 194 | |||
| 195 | @cherrypy.expose | 179 | @cherrypy.expose |
| 196 | def index(self): | 180 | def index(self): |
| 197 | """ | 181 | """ |
| @@ -199,7 +183,6 @@ class WebNotifyServer(object): | |||
| 199 | """ | 183 | """ |
| 200 | return 'index' | 184 | return 'index' |
| 201 | 185 | ||
| 202 | |||
| 203 | @cherrypy.expose | 186 | @cherrypy.expose |
| 204 | def default(self, *args): | 187 | def default(self, *args): |
| 205 | """ | 188 | """ |
| @@ -207,7 +190,6 @@ class WebNotifyServer(object): | |||
| 207 | """ | 190 | """ |
| 208 | return 'default' | 191 | return 'default' |
| 209 | 192 | ||
| 210 | |||
| 211 | @cherrypy.expose | 193 | @cherrypy.expose |
| 212 | def push(self, *args, **kwargs): | 194 | def push(self, *args, **kwargs): |
| 213 | print('push called') | 195 | print('push called') |
| @@ -227,10 +209,10 @@ class WebNotifyServer(object): | |||
| 227 | sys.stderr.write('Wrong instance or password: {0}\n'.format(e)) | 209 | sys.stderr.write('Wrong instance or password: {0}\n'.format(e)) |
| 228 | raise cherrypy.HTTPError('403 Forbidden', | 210 | raise cherrypy.HTTPError('403 Forbidden', |
| 229 | 'Wrong instance or password') | 211 | 'Wrong instance or password') |
| 230 | 212 | ||
| 231 | if not instance.password_match(kwargs.get('password')): | 213 | if not instance.password_match(kwargs.get('password')): |
| 232 | sys.stderr.write('Wrong instance or password: {0}\n'.format(e)) | 214 | sys.stderr.write('Wrong instance or password: {0}\n'.format(e)) |
| 233 | raise cherrypy.HTTPError('403 Forbidden', | 215 | raise cherrypy.HTTPError('403 Forbidden', |
| 234 | 'Wrong instance or password') | 216 | 'Wrong instance or password') |
| 235 | 217 | ||
| 236 | # instance = self.__instances[args[0]] | 218 | # instance = self.__instances[args[0]] |
| @@ -242,11 +224,10 @@ class WebNotifyServer(object): | |||
| 242 | except Exception as e: | 224 | except Exception as e: |
| 243 | sys.stderr.write( | 225 | sys.stderr.write( |
| 244 | 'Unable to handle message in {0}: ({1})\n'.format( | 226 | 'Unable to handle message in {0}: ({1})\n'.format( |
| 245 | instance.name, | 227 | instance.name, |
| 246 | e)) | 228 | e)) |
| 247 | raise cherrypy.HTTPError(500, 'Unable to send message') | 229 | raise cherrypy.HTTPError(500, 'Unable to send message') |
| 248 | 230 | ||
| 249 | |||
| 250 | @cherrypy.expose | 231 | @cherrypy.expose |
| 251 | @beinc_instance_login | 232 | @beinc_instance_login |
| 252 | def pull(self, *args, **kwargs): | 233 | def pull(self, *args, **kwargs): |
| @@ -255,12 +236,11 @@ class WebNotifyServer(object): | |||
| 255 | return 'OK' | 236 | return 'OK' |
| 256 | 237 | ||
| 257 | 238 | ||
| 258 | |||
| 259 | def main(): | 239 | def main(): |
| 260 | 240 | ||
| 261 | parser = argparse.ArgumentParser(description='The following options are available') | 241 | parser = argparse.ArgumentParser( |
| 242 | description='The following options are available') | ||
| 262 | 243 | ||
| 263 | |||
| 264 | parser.add_argument('-d', | 244 | parser.add_argument('-d', |
| 265 | action='store_true', | 245 | action='store_true', |
| 266 | dest='daemonize', | 246 | dest='daemonize', |
| @@ -295,14 +275,13 @@ def main(): | |||
| 295 | 275 | ||
| 296 | args = parser.parse_args() | 276 | args = parser.parse_args() |
| 297 | 277 | ||
| 298 | |||
| 299 | try: | 278 | try: |
| 300 | with open(args.config_file, 'r') as fp: | 279 | with open(args.config_file, 'r') as fp: |
| 301 | config_dict = json.load(fp) | 280 | config_dict = json.load(fp) |
| 302 | 281 | ||
| 303 | except Exception as e: | 282 | except Exception as e: |
| 304 | sys.stderr.write('Unable to parse {0}: {1}'.format(args.config_file, e)) | 283 | sys.stderr.write('Unable to parse {0}: {1}'.format(args.config_file, |
| 305 | 284 | e)) | |
| 306 | 285 | ||
| 307 | cherrypy.config.update({ | 286 | cherrypy.config.update({ |
| 308 | 'server.socket_host': args.hostname, | 287 | 'server.socket_host': args.hostname, |
| @@ -317,7 +296,7 @@ def main(): | |||
| 317 | global pynotify | 296 | global pynotify |
| 318 | try: | 297 | try: |
| 319 | import pynotify | 298 | import pynotify |
| 320 | if not pynotify.init("BEINC Notify"): | 299 | if not pynotify.init('BEINC Notify'): |
| 321 | sys.stderr.write('pynotify.init failed! Exiting...\n') | 300 | sys.stderr.write('pynotify.init failed! Exiting...\n') |
| 322 | sys.exit(1) | 301 | sys.exit(1) |
| 323 | except Exception as e: | 302 | except Exception as e: |
| @@ -337,4 +316,3 @@ def main(): | |||
| 337 | 316 | ||
| 338 | if __name__ == "__main__": | 317 | if __name__ == "__main__": |
| 339 | main() | 318 | main() |
| 340 | |||
diff --git a/beinc_weechat.py b/beinc_weechat.py new file mode 100644 index 0000000..4abf6f1 --- /dev/null +++ b/beinc_weechat.py | |||
| @@ -0,0 +1,144 @@ | |||
| 1 | #!/usr/bin/env python | ||
| 2 | # -*- coding: utf-8 -*- | ||
| 3 | |||
| 4 | import json | ||
| 5 | import os | ||
| 6 | import socket | ||
| 7 | import sys | ||
| 8 | |||
| 9 | import weechat | ||
| 10 | |||
| 11 | enabled = True | ||
| 12 | |||
| 13 | class WeechatTarget(object): | ||
| 14 | """ | ||
| 15 | """ | ||
| 16 | |||
| 17 | def __init__(self, target_dict): | ||
| 18 | """ | ||
| 19 | target_dict: the config-dictionary node that represents this instance | ||
| 20 | """ | ||
| 21 | |||
| 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 | |||
| 29 | |||
| 30 | |||
| 31 | |||
| 32 | def bosd_send_xosd_message(message): | ||
| 33 | for conn in connections: | ||
| 34 | try: | ||
| 35 | #weechat.prnt("", message) | ||
| 36 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
| 37 | s.connect((conn['sbosdd_ip'], conn['sbosdd_port'])) | ||
| 38 | s.send(message) | ||
| 39 | s.close() | ||
| 40 | except: | ||
| 41 | continue | ||
| 42 | |||
| 43 | return True | ||
| 44 | |||
| 45 | |||
| 46 | def bosd_command(data, buffer, args): | ||
| 47 | global enabled | ||
| 48 | if args == 'on': | ||
| 49 | enabled = True | ||
| 50 | weechat.prnt(weechat.current_buffer(), 'bosd on') | ||
| 51 | elif args == 'off': | ||
| 52 | enabled = False | ||
| 53 | weechat.prnt(weechat.current_buffer(), 'bosd off') | ||
| 54 | elif args == 'reload': | ||
| 55 | weechat.prnt(weechat.current_buffer(), '{0} reloaded') | ||
| 56 | else: | ||
| 57 | bosd_send_xosd_message(args) | ||
| 58 | |||
| 59 | return weechat.WEECHAT_RC_OK | ||
| 60 | |||
| 61 | |||
| 62 | def bosd_privmsg_handler(data, signal, signal_data): | ||
| 63 | if not enabled: | ||
| 64 | return weechat.WEECHAT_RC_OK | ||
| 65 | |||
| 66 | prvmsg_dict = weechat.info_get_hashtable("irc_message_parse", | ||
| 67 | { "message": signal_data }) | ||
| 68 | |||
| 69 | |||
| 70 | server = signal.split(",")[0] | ||
| 71 | |||
| 72 | # channel = signal_data.split(":")[-1] | ||
| 73 | # my_nick = weechat.info_get("irc_nick_from_host", signal_data) | ||
| 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 | |||
| 87 | if my_nick.lower() in channel.lower(): | ||
| 88 | template_msg = '{0} @ {1}: {2}'.format(nick, server, message) | ||
| 89 | bosd_send_xosd_message(template_msg) | ||
| 90 | |||
| 91 | # weechat.prnt("", | ||
| 92 | # 'DEBUG: my_nick - {0}, server - {1}, channel - {2}'.format(my_nick, | ||
| 93 | # server, | ||
| 94 | # channel)) | ||
| 95 | |||
| 96 | return weechat.WEECHAT_RC_OK | ||
| 97 | |||
| 98 | |||
| 99 | def beinc_init(): | ||
| 100 | |||
| 101 | global enabled | ||
| 102 | global target_list | ||
| 103 | |||
| 104 | custom_error = '' | ||
| 105 | |||
| 106 | try: | ||
| 107 | beinc_config_file_str = os.path.join(weechat.info_get('weechat_dir', | ||
| 108 | ''), | ||
| 109 | 'beinc.json') | ||
| 110 | weechat.prnt('', 'Parsing {0}...'.format(beinc_config_file_str)) | ||
| 111 | |||
| 112 | custom_error = 'load error' | ||
| 113 | with open(beinc_config_file_str, 'r') as fp: | ||
| 114 | config_dict = json.load(fp) | ||
| 115 | |||
| 116 | # clear the target-list | ||
| 117 | target_list = [] | ||
| 118 | |||
| 119 | custom_error = 'target parse error' | ||
| 120 | for target in config_dict['irc_client']['targets']: | ||
| 121 | new_target = WeechatTarget(target) | ||
| 122 | target_list.append(new_target) | ||
| 123 | |||
| 124 | weechat.prnt('', 'Done!!!') | ||
| 125 | |||
| 126 | except Exception as e: | ||
| 127 | weechat.prnt('', 'ERROR: unable to parse {0}: {1} - {2}'.format( | ||
| 128 | beinc_config_file_str, custom_error, e)) | ||
| 129 | enabled = False | ||
| 130 | |||
| 131 | # do not return error / exit the script | ||
| 132 | # in order to give a smoother opportunity to fix a 'broken' config | ||
| 133 | return weechat.WEECHAT_RC_OK | ||
| 134 | |||
| 135 | return weechat.WEECHAT_RC_OK | ||
| 136 | |||
| 137 | |||
| 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 | |||
| 144 | weechat.prnt('', 'beinc initiated!') | ||
diff --git a/weechat_notify.py b/weechat_notify.py index f070551..897f26d 100755 --- a/weechat_notify.py +++ b/weechat_notify.py | |||
| @@ -13,6 +13,7 @@ POLLING_FREQUENCY = 10 | |||
| 13 | NOTIFICATION_URL = 'https://simeon.simeonov.no:40004/notifications/' | 13 | NOTIFICATION_URL = 'https://simeon.simeonov.no:40004/notifications/' |
| 14 | TIMEOUT_SEC = 3 | 14 | TIMEOUT_SEC = 3 |
| 15 | 15 | ||
| 16 | |||
| 16 | def poll_notifications(scheduler): | 17 | def poll_notifications(scheduler): |
| 17 | """ | 18 | """ |
| 18 | """ | 19 | """ |
| @@ -20,7 +21,7 @@ def poll_notifications(scheduler): | |||
| 20 | req = urllib2.Request(NOTIFICATION_URL) | 21 | req = urllib2.Request(NOTIFICATION_URL) |
| 21 | response = urllib2.urlopen(req) | 22 | response = urllib2.urlopen(req) |
| 22 | response_str = response.read() | 23 | response_str = response.read() |
| 23 | 24 | ||
| 24 | entries = json.loads(response_str) | 25 | entries = json.loads(response_str) |
| 25 | for entry in entries: | 26 | for entry in entries: |
| 26 | n = pynotify.Notification('IRC', entry, 'dialog-information') | 27 | n = pynotify.Notification('IRC', entry, 'dialog-information') |
