diff options
| author | Simeon Simeonov | 2022-09-10 10:27:18 +0200 |
|---|---|---|
| committer | Simeon Simeonov | 2022-09-10 10:27:18 +0200 |
| commit | 003cd12be734b05d7281579d3d377f79425531fa (patch) | |
| tree | edac9e287a9d8a38b97df2c1722bfc732bc781d3 | |
| parent | 1dab5dbd8da35d7c7f9f44915fe5be7f7b1e5b79 (diff) | |
Remove obsolete code and use black alike code styling
| -rwxr-xr-x | beinc_generic_client.py | 86 | ||||
| -rwxr-xr-x | beinc_pull.py | 110 | ||||
| -rwxr-xr-x | beinc_server.py | 156 | ||||
| -rw-r--r-- | beinc_weechat.py | 286 |
4 files changed, 376 insertions, 262 deletions
diff --git a/beinc_generic_client.py b/beinc_generic_client.py index ca3847a..af1e74f 100755 --- a/beinc_generic_client.py +++ b/beinc_generic_client.py | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | # -*- coding: utf-8 -*- | 2 | # -*- coding: utf-8 -*- |
| 3 | 3 | ||
| 4 | # Blackmore's Enhanced IRC-Notification Collection (BEINC) v4.0 | 4 | # Blackmore's Enhanced IRC-Notification Collection (BEINC) v4.0 |
| 5 | # Copyright (C) 2013-2020 Simeon Simeonov | 5 | # Copyright (C) 2013-2022 Simeon Simeonov |
| 6 | 6 | ||
| 7 | # This program is free software: you can redistribute it and/or modify | 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 | 8 | # it under the terms of the GNU General Public License as published by |
| @@ -29,9 +29,8 @@ import sys | |||
| 29 | import urllib.parse | 29 | import urllib.parse |
| 30 | import urllib.request | 30 | import urllib.request |
| 31 | 31 | ||
| 32 | |||
| 33 | __author__ = 'Simeon Simeonov' | 32 | __author__ = 'Simeon Simeonov' |
| 34 | __version__ = '4.1' | 33 | __version__ = '4.2' |
| 35 | __license__ = 'GPL3' | 34 | __license__ = 'GPL3' |
| 36 | 35 | ||
| 37 | 36 | ||
| @@ -58,7 +57,7 @@ def fetch_password(args_password): | |||
| 58 | sys.exit(errno.EACCES) | 57 | sys.exit(errno.EACCES) |
| 59 | elif os.path.isfile(args_password): | 58 | elif os.path.isfile(args_password): |
| 60 | try: | 59 | try: |
| 61 | with io.open(args_password, 'r') as fp: | 60 | with io.open(args_password, 'r', encoding='utf-8') as fp: |
| 62 | passwd = fp.readline() | 61 | passwd = fp.readline() |
| 63 | if passwd.strip(): | 62 | if passwd.strip(): |
| 64 | return passwd.strip() | 63 | return passwd.strip() |
| @@ -86,10 +85,12 @@ def pull_notifications(ssl_context, args): | |||
| 86 | data=urllib.parse.urlencode( | 85 | data=urllib.parse.urlencode( |
| 87 | ( | 86 | ( |
| 88 | ('resource_name', args.rname), | 87 | ('resource_name', args.rname), |
| 89 | ('password', args.password) | 88 | ('password', args.password), |
| 90 | )).encode('utf-8'), | 89 | ) |
| 90 | ).encode('utf-8'), | ||
| 91 | timeout=args.socket_timeout, | 91 | timeout=args.socket_timeout, |
| 92 | context=ssl_context) | 92 | context=ssl_context, |
| 93 | ) | ||
| 93 | response_dict = json.loads(response.read().decode('utf-8')) | 94 | response_dict = json.loads(response.read().decode('utf-8')) |
| 94 | if response.code != 200: | 95 | if response.code != 200: |
| 95 | raise socket.error(response_dict.get('message', '')) | 96 | raise socket.error(response_dict.get('message', '')) |
| @@ -113,10 +114,12 @@ def push_notification(ssl_context, args): | |||
| 113 | ('resource_name', args.rname), | 114 | ('resource_name', args.rname), |
| 114 | ('password', args.password), | 115 | ('password', args.password), |
| 115 | ('title', args.title), | 116 | ('title', args.title), |
| 116 | ('message', args.message) | 117 | ('message', args.message), |
| 117 | )).encode('utf-8'), | 118 | ) |
| 119 | ).encode('utf-8'), | ||
| 118 | timeout=args.socket_timeout, | 120 | timeout=args.socket_timeout, |
| 119 | context=ssl_context) | 121 | context=ssl_context, |
| 122 | ) | ||
| 120 | response_dict = json.loads(response.read().decode('utf-8')) | 123 | response_dict = json.loads(response.read().decode('utf-8')) |
| 121 | if response.code != 200: | 124 | if response.code != 200: |
| 122 | raise socket.error(response_dict.get('message', '')) | 125 | raise socket.error(response_dict.get('message', '')) |
| @@ -125,91 +128,112 @@ def push_notification(ssl_context, args): | |||
| 125 | def main(inargs=None): | 128 | def main(inargs=None): |
| 126 | """main entry""" | 129 | """main entry""" |
| 127 | parser = argparse.ArgumentParser( | 130 | parser = argparse.ArgumentParser( |
| 128 | description='The following options are available') | 131 | description='The following options are available' |
| 132 | ) | ||
| 129 | parser.add_argument( | 133 | parser.add_argument( |
| 130 | 'url', | 134 | 'url', |
| 131 | metavar='URL', | 135 | metavar='URL', |
| 132 | type=str, | 136 | type=str, |
| 133 | help='BEINC server destination URL') | 137 | help='BEINC server destination URL', |
| 138 | ) | ||
| 134 | parser.add_argument( | 139 | parser.add_argument( |
| 135 | '-c', '--cert-file', | 140 | '-c', |
| 141 | '--cert-file', | ||
| 136 | metavar='FILE', | 142 | metavar='FILE', |
| 137 | type=str, | 143 | type=str, |
| 138 | dest='cert', | 144 | dest='cert', |
| 139 | default='', | 145 | default='', |
| 140 | help='CA-cert to check the server-cert against' | 146 | help='CA-cert to check the server-cert against' |
| 141 | '(default: Check disabled)') | 147 | '(default: Check disabled)', |
| 148 | ) | ||
| 142 | parser.add_argument( | 149 | parser.add_argument( |
| 143 | '--ciphers', | 150 | '--ciphers', |
| 144 | metavar='CIPHERS', | 151 | metavar='CIPHERS', |
| 145 | type=str, | 152 | type=str, |
| 146 | dest='ciphers', | 153 | dest='ciphers', |
| 147 | default='', | 154 | default='', |
| 148 | help='Preferred ciphers list (default: auto)') | 155 | help='Preferred ciphers list (default: auto)', |
| 156 | ) | ||
| 149 | parser.add_argument( | 157 | parser.add_argument( |
| 150 | '--disable-hostname-check', | 158 | '--disable-hostname-check', |
| 151 | action='store_true', | 159 | action='store_true', |
| 152 | dest='disable_hostname_check', | 160 | dest='disable_hostname_check', |
| 153 | default=False, | 161 | default=False, |
| 154 | help='Do not check whether server cert matches server hostname') | 162 | help='Do not check whether server cert matches server hostname', |
| 163 | ) | ||
| 155 | parser.add_argument( | 164 | parser.add_argument( |
| 156 | '-m', '--message', | 165 | '-m', |
| 166 | '--message', | ||
| 157 | metavar='MESSAGE', | 167 | metavar='MESSAGE', |
| 158 | type=str, | 168 | type=str, |
| 159 | dest='message', | 169 | dest='message', |
| 160 | default='BEINC message', | 170 | default='BEINC message', |
| 161 | help='BEINC message (default: "BEINC message")') | 171 | help='BEINC message (default: "BEINC message")', |
| 172 | ) | ||
| 162 | parser.add_argument( | 173 | parser.add_argument( |
| 163 | '-n', '--resource-name', | 174 | '-n', |
| 175 | '--resource-name', | ||
| 164 | metavar='NAME', | 176 | metavar='NAME', |
| 165 | type=str, | 177 | type=str, |
| 166 | dest='rname', | 178 | dest='rname', |
| 167 | required=True, | 179 | required=True, |
| 168 | help='The name of the BEINC-resource on the remote server') | 180 | help='The name of the BEINC-resource on the remote server', |
| 181 | ) | ||
| 169 | parser.add_argument( | 182 | parser.add_argument( |
| 170 | '-p', '--password', | 183 | '-p', |
| 184 | '--password', | ||
| 171 | metavar='PASSWORD[FILE]', | 185 | metavar='PASSWORD[FILE]', |
| 172 | type=str, | 186 | type=str, |
| 173 | dest='password', | 187 | dest='password', |
| 174 | default='', | 188 | default='', |
| 175 | help='BEINC taget-password / text-file containing the target password' | 189 | help='BEINC taget-password / text-file containing the target password' |
| 176 | ' (default & recommended: prompt for passwd)') | 190 | ' (default & recommended: prompt for passwd)', |
| 191 | ) | ||
| 177 | parser.add_argument( | 192 | parser.add_argument( |
| 178 | '--pull', | 193 | '--pull', |
| 179 | action='store_true', | 194 | action='store_true', |
| 180 | dest='pull', | 195 | dest='pull', |
| 181 | default=False, | 196 | default=False, |
| 182 | help='Perform a pull operation (default: push)') | 197 | help='Perform a pull operation (default: push)', |
| 198 | ) | ||
| 183 | parser.add_argument( | 199 | parser.add_argument( |
| 184 | '-T', '--socket-timeout', | 200 | '-T', |
| 201 | '--socket-timeout', | ||
| 185 | metavar='SECONDS', | 202 | metavar='SECONDS', |
| 186 | type=int, | 203 | type=int, |
| 187 | dest='socket_timeout', | 204 | dest='socket_timeout', |
| 188 | default=3, | 205 | default=3, |
| 189 | help='Socket timeout in seconds (0=Python default) (default: 3)') | 206 | help='Socket timeout in seconds (0=Python default) (default: 3)', |
| 207 | ) | ||
| 190 | parser.add_argument( | 208 | parser.add_argument( |
| 191 | '-t', '--title', | 209 | '-t', |
| 210 | '--title', | ||
| 192 | metavar='TITLE', | 211 | metavar='TITLE', |
| 193 | type=str, | 212 | type=str, |
| 194 | dest='title', | 213 | dest='title', |
| 195 | default='BEINC title', | 214 | default='BEINC title', |
| 196 | help='BEINC title (default: "BEINC title"') | 215 | help='BEINC title (default: "BEINC title"', |
| 216 | ) | ||
| 197 | parser.add_argument( | 217 | parser.add_argument( |
| 198 | '-v', '--version', | 218 | '-v', |
| 219 | '--version', | ||
| 199 | action='version', | 220 | action='version', |
| 200 | version=f'%(prog)s {__version__}', | 221 | version=f'%(prog)s {__version__}', |
| 201 | help='display program-version and exit') | 222 | help='display program-version and exit', |
| 223 | ) | ||
| 202 | args = parser.parse_args(inargs) | 224 | args = parser.parse_args(inargs) |
| 203 | if args.socket_timeout: | 225 | if args.socket_timeout: |
| 204 | socket.setdefaulttimeout(args.socket_timeout) | 226 | socket.setdefaulttimeout(args.socket_timeout) |
| 205 | args.password = fetch_password(args.password) | 227 | args.password = fetch_password(args.password) |
| 206 | try: | 228 | try: |
| 207 | context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) | 229 | context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) |
| 208 | context.verify_mode = ssl.CERT_NONE | ||
| 209 | if args.cert: | 230 | if args.cert: |
| 210 | context.verify_mode = ssl.CERT_REQUIRED | 231 | context.verify_mode = ssl.CERT_REQUIRED |
| 211 | context.load_verify_locations(cafile=os.path.expanduser(args.cert)) | 232 | context.load_verify_locations(cafile=os.path.expanduser(args.cert)) |
| 212 | context.check_hostname = bool(not args.disable_hostname_check) | 233 | context.check_hostname = bool(not args.disable_hostname_check) |
| 234 | else: | ||
| 235 | context.check_hostname = False | ||
| 236 | context.verify_mode = ssl.CERT_NONE | ||
| 213 | if args.ciphers: | 237 | if args.ciphers: |
| 214 | context.set_ciphers(args.ciphers) | 238 | context.set_ciphers(args.ciphers) |
| 215 | if args.pull: | 239 | if args.pull: |
diff --git a/beinc_pull.py b/beinc_pull.py index c99cde8..67b6e63 100755 --- a/beinc_pull.py +++ b/beinc_pull.py | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | # -*- coding: utf-8 -*- | 2 | # -*- coding: utf-8 -*- |
| 3 | 3 | ||
| 4 | # Blackmore's Enhanced IRC-Notification Collection (BEINC) v4.0 | 4 | # Blackmore's Enhanced IRC-Notification Collection (BEINC) v4.0 |
| 5 | # Copyright (C) 2013-2020 Simeon Simeonov | 5 | # Copyright (C) 2013-2022 Simeon Simeonov |
| 6 | 6 | ||
| 7 | # This program is free software: you can redistribute it and/or modify | 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 | 8 | # it under the terms of the GNU General Public License as published by |
| @@ -38,7 +38,7 @@ except ImportError: | |||
| 38 | 38 | ||
| 39 | 39 | ||
| 40 | __author__ = 'Simeon Simeonov' | 40 | __author__ = 'Simeon Simeonov' |
| 41 | __version__ = '4.1' | 41 | __version__ = '4.2' |
| 42 | __license__ = 'GPL3' | 42 | __license__ = 'GPL3' |
| 43 | 43 | ||
| 44 | 44 | ||
| @@ -65,7 +65,7 @@ def fetch_password(args_password): | |||
| 65 | sys.exit(errno.EACCES) | 65 | sys.exit(errno.EACCES) |
| 66 | elif os.path.isfile(args_password): | 66 | elif os.path.isfile(args_password): |
| 67 | try: | 67 | try: |
| 68 | with io.open(args_password, 'r') as fp: | 68 | with io.open(args_password, 'r', encoding='utf-8') as fp: |
| 69 | passwd = fp.readline() | 69 | passwd = fp.readline() |
| 70 | if passwd.strip(): | 70 | if passwd.strip(): |
| 71 | return passwd.strip() | 71 | return passwd.strip() |
| @@ -93,11 +93,14 @@ def display_notification(args, title, message): | |||
| 93 | raise Exception( | 93 | raise Exception( |
| 94 | 'Could not load "pynotify".' | 94 | 'Could not load "pynotify".' |
| 95 | 'Please install "pynotify" or use a different osd-system!' | 95 | 'Please install "pynotify" or use a different osd-system!' |
| 96 | 'Terminating...') | 96 | 'Terminating...' |
| 97 | ) | ||
| 97 | if not pynotify.init('BEINC Notify'): | 98 | if not pynotify.init('BEINC Notify'): |
| 98 | raise Exception('There was a problem with libnotify') | 99 | raise Exception('There was a problem with libnotify') |
| 99 | notification_obj = pynotify.Notification(summary=title, | 100 | notification_obj = pynotify.Notification( |
| 100 | message=message) | 101 | summary=title, |
| 102 | message=message, | ||
| 103 | ) | ||
| 101 | notification_obj.timeout = 1000 * args.osd_timeout | 104 | notification_obj.timeout = 1000 * args.osd_timeout |
| 102 | notification_obj.set_category('im.received') | 105 | notification_obj.set_category('im.received') |
| 103 | notification_obj.show() | 106 | notification_obj.show() |
| @@ -116,35 +119,37 @@ def pull_notifications(scheduler, args): | |||
| 116 | :type args: argparse.Namespace | 119 | :type args: argparse.Namespace |
| 117 | """ | 120 | """ |
| 118 | try: | 121 | try: |
| 119 | context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) | 122 | context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) |
| 120 | context.verify_mode = ssl.CERT_NONE | ||
| 121 | if args.cert: | 123 | if args.cert: |
| 122 | context.verify_mode = ssl.CERT_REQUIRED | 124 | context.verify_mode = ssl.CERT_REQUIRED |
| 123 | context.load_verify_locations(cafile=os.path.expanduser(args.cert)) | 125 | context.load_verify_locations(cafile=os.path.expanduser(args.cert)) |
| 124 | context.check_hostname = bool(not args.disable_hostname_check) | 126 | context.check_hostname = bool(not args.disable_hostname_check) |
| 127 | else: | ||
| 128 | context.check_hostname = False | ||
| 129 | context.verify_mode = ssl.CERT_NONE | ||
| 125 | if args.ciphers: | 130 | if args.ciphers: |
| 126 | context.set_ciphers(args.ciphers) | 131 | context.set_ciphers(args.ciphers) |
| 127 | response = urllib.request.urlopen( | 132 | response = urllib.request.urlopen( |
| 128 | args.url, | 133 | args.url, |
| 129 | data=urllib.parse.urlencode( | 134 | data=urllib.parse.urlencode( |
| 130 | ( | 135 | (('resource_name', args.rname), ('password', args.password)) |
| 131 | ('resource_name', args.rname), | 136 | ).encode('utf-8'), |
| 132 | ('password', args.password) | ||
| 133 | )).encode('utf-8'), | ||
| 134 | timeout=args.socket_timeout, | 137 | timeout=args.socket_timeout, |
| 135 | context=context) | 138 | context=context, |
| 139 | ) | ||
| 136 | response_dict = json.loads(response.read().decode('utf-8')) | 140 | response_dict = json.loads(response.read().decode('utf-8')) |
| 137 | if response.code != 200: | 141 | if response.code != 200: |
| 138 | raise socket.error(response_dict.get('message', '')) | 142 | raise socket.error(response_dict.get('message', '')) |
| 139 | for entry in response_dict['data']['messages']: | 143 | for entry in response_dict['data']['messages']: |
| 140 | display_notification(args, | 144 | display_notification( |
| 141 | entry.get('title', ''), | 145 | args, |
| 142 | entry.get('message', '')) | 146 | entry.get('title', ''), |
| 147 | entry.get('message', ''), | ||
| 148 | ) | ||
| 143 | response.close() | 149 | response.close() |
| 144 | scheduler.enter(args.frequency, | 150 | scheduler.enter( |
| 145 | 1, | 151 | args.frequency, 1, pull_notifications, (scheduler, args) |
| 146 | pull_notifications, | 152 | ) |
| 147 | (scheduler, args)) | ||
| 148 | except ssl.SSLError as e: | 153 | except ssl.SSLError as e: |
| 149 | eprint(f'BEINC SSL/TLS error: {e}') | 154 | eprint(f'BEINC SSL/TLS error: {e}') |
| 150 | sys.exit(errno.EPERM) | 155 | sys.exit(errno.EPERM) |
| @@ -159,88 +164,105 @@ def pull_notifications(scheduler, args): | |||
| 159 | def main(inargs=None): | 164 | def main(inargs=None): |
| 160 | """main entry""" | 165 | """main entry""" |
| 161 | parser = argparse.ArgumentParser( | 166 | parser = argparse.ArgumentParser( |
| 162 | description='The following options are available') | 167 | description='The following options are available' |
| 168 | ) | ||
| 163 | parser.add_argument( | 169 | parser.add_argument( |
| 164 | 'url', | 170 | 'url', |
| 165 | metavar='URL', | 171 | metavar='URL', |
| 166 | type=str, | 172 | type=str, |
| 167 | help='BEINC server destination URL') | 173 | help='BEINC server destination URL', |
| 174 | ) | ||
| 168 | parser.add_argument( | 175 | parser.add_argument( |
| 169 | '-c', '--cert-file', | 176 | '-c', |
| 177 | '--cert-file', | ||
| 170 | metavar='FILE', | 178 | metavar='FILE', |
| 171 | type=str, | 179 | type=str, |
| 172 | dest='cert', | 180 | dest='cert', |
| 173 | default='', | 181 | default='', |
| 174 | help='CA-cert to check the server-cert against ' | 182 | help='CA-cert to check the server-cert against ' |
| 175 | '(default: Check disabled)') | 183 | '(default: Check disabled)', |
| 184 | ) | ||
| 176 | parser.add_argument( | 185 | parser.add_argument( |
| 177 | '--ciphers', | 186 | '--ciphers', |
| 178 | metavar='CIPHERS', | 187 | metavar='CIPHERS', |
| 179 | type=str, | 188 | type=str, |
| 180 | dest='ciphers', | 189 | dest='ciphers', |
| 181 | default='', | 190 | default='', |
| 182 | help='Preferred ciphers list (default: auto)') | 191 | help='Preferred ciphers list (default: auto)', |
| 192 | ) | ||
| 183 | parser.add_argument( | 193 | parser.add_argument( |
| 184 | '--disable-hostname-check', | 194 | '--disable-hostname-check', |
| 185 | action='store_true', | 195 | action='store_true', |
| 186 | dest='disable_hostname_check', | 196 | dest='disable_hostname_check', |
| 187 | default=False, | 197 | default=False, |
| 188 | help='Do not check whether server cert matches server hostname') | 198 | help='Do not check whether server cert matches server hostname', |
| 199 | ) | ||
| 189 | parser.add_argument( | 200 | parser.add_argument( |
| 190 | '-f', '--frequency', | 201 | '-f', |
| 202 | '--frequency', | ||
| 191 | metavar='SECONDS', | 203 | metavar='SECONDS', |
| 192 | type=int, | 204 | type=int, |
| 193 | dest='frequency', | 205 | dest='frequency', |
| 194 | default=10, | 206 | default=10, |
| 195 | help='Pulling frequency in seconds (default: 10)') | 207 | help='Pulling frequency in seconds (default: 10)', |
| 208 | ) | ||
| 196 | parser.add_argument( | 209 | parser.add_argument( |
| 197 | '-n', '--resource-name', | 210 | '-n', |
| 211 | '--resource-name', | ||
| 198 | metavar='NAME', | 212 | metavar='NAME', |
| 199 | type=str, | 213 | type=str, |
| 200 | dest='rname', | 214 | dest='rname', |
| 201 | required=True, | 215 | required=True, |
| 202 | help='The name of the BEINC-resource on the remote server') | 216 | help='The name of the BEINC-resource on the remote server', |
| 217 | ) | ||
| 203 | parser.add_argument( | 218 | parser.add_argument( |
| 204 | '-o', '--osd-system', | 219 | '-o', |
| 220 | '--osd-system', | ||
| 205 | metavar='SYSTEM', | 221 | metavar='SYSTEM', |
| 206 | type=str, | 222 | type=str, |
| 207 | dest='osd_sys', | 223 | dest='osd_sys', |
| 208 | default='pynotify', | 224 | default='pynotify', |
| 209 | help='BEINC osd-system: "pynotify" (default)') | 225 | help='BEINC osd-system: "pynotify" (default)', |
| 226 | ) | ||
| 210 | parser.add_argument( | 227 | parser.add_argument( |
| 211 | '-p', '--password', | 228 | '-p', |
| 229 | '--password', | ||
| 212 | metavar='PASSWORD[FILE]', | 230 | metavar='PASSWORD[FILE]', |
| 213 | type=str, | 231 | type=str, |
| 214 | dest='password', | 232 | dest='password', |
| 215 | default='', | 233 | default='', |
| 216 | help='BEINC taget-password / text-file containing the target password' | 234 | help='BEINC taget-password / text-file containing the target password' |
| 217 | ' (default & recommended: prompt for passwd)') | 235 | ' (default & recommended: prompt for passwd)', |
| 236 | ) | ||
| 218 | parser.add_argument( | 237 | parser.add_argument( |
| 219 | '-T', '--socket-timeout', | 238 | '-T', |
| 239 | '--socket-timeout', | ||
| 220 | metavar='SECONDS', | 240 | metavar='SECONDS', |
| 221 | type=int, | 241 | type=int, |
| 222 | dest='socket_timeout', | 242 | dest='socket_timeout', |
| 223 | default=3, | 243 | default=3, |
| 224 | help='Socket timeout in seconds (0=Python default) (default: 3)') | 244 | help='Socket timeout in seconds (0=Python default) (default: 3)', |
| 245 | ) | ||
| 225 | parser.add_argument( | 246 | parser.add_argument( |
| 226 | '-t', '--osd-timeout', | 247 | '-t', |
| 248 | '--osd-timeout', | ||
| 227 | metavar='SECONDS', | 249 | metavar='SECONDS', |
| 228 | type=int, | 250 | type=int, |
| 229 | dest='osd_timeout', | 251 | dest='osd_timeout', |
| 230 | default=5, | 252 | default=5, |
| 231 | help='OSD timeout (default: 5)') | 253 | help='OSD timeout (default: 5)', |
| 254 | ) | ||
| 232 | parser.add_argument( | 255 | parser.add_argument( |
| 233 | '-v', '--version', | 256 | '-v', |
| 257 | '--version', | ||
| 234 | action='version', | 258 | action='version', |
| 235 | version=f'%(prog)s {__version__}', | 259 | version=f'%(prog)s {__version__}', |
| 236 | help='display program-version and exit') | 260 | help='display program-version and exit', |
| 261 | ) | ||
| 237 | args = parser.parse_args(inargs) | 262 | args = parser.parse_args(inargs) |
| 238 | args.password = fetch_password(args.password) | 263 | args.password = fetch_password(args.password) |
| 239 | scheduler = sched.scheduler(time.time, time.sleep) | 264 | scheduler = sched.scheduler(time.time, time.sleep) |
| 240 | scheduler.enter(args.frequency, | 265 | scheduler.enter(args.frequency, 1, pull_notifications, (scheduler, args)) |
| 241 | 1, | ||
| 242 | pull_notifications, | ||
| 243 | (scheduler, args)) | ||
| 244 | scheduler.run() | 266 | scheduler.run() |
| 245 | 267 | ||
| 246 | 268 | ||
diff --git a/beinc_server.py b/beinc_server.py index 8957e73..77aa35e 100755 --- a/beinc_server.py +++ b/beinc_server.py | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | # -*- coding: utf-8 -*- | 2 | # -*- coding: utf-8 -*- |
| 3 | 3 | ||
| 4 | # Blackmore's Enhanced IRC-Notification Collection (BEINC) v4.0 | 4 | # Blackmore's Enhanced IRC-Notification Collection (BEINC) v4.0 |
| 5 | # Copyright (C) 2013-2020 Simeon Simeonov | 5 | # Copyright (C) 2013-2022 Simeon Simeonov |
| 6 | 6 | ||
| 7 | # This program is free software: you can redistribute it and/or modify | 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 | 8 | # it under the terms of the GNU General Public License as published by |
| @@ -21,15 +21,15 @@ | |||
| 21 | import argparse | 21 | import argparse |
| 22 | import cgi | 22 | import cgi |
| 23 | import errno | 23 | import errno |
| 24 | import io | ||
| 24 | import json | 25 | import json |
| 25 | import logging | 26 | import logging |
| 26 | import os | 27 | import os |
| 27 | import ssl | 28 | import ssl |
| 28 | import sys | 29 | import sys |
| 29 | |||
| 30 | from functools import wraps | 30 | from functools import wraps |
| 31 | from logging.config import fileConfig | ||
| 32 | from http.server import BaseHTTPRequestHandler, HTTPServer | 31 | from http.server import BaseHTTPRequestHandler, HTTPServer |
| 32 | from logging.config import fileConfig | ||
| 33 | 33 | ||
| 34 | try: | 34 | try: |
| 35 | import notify2 as pynotify | 35 | import notify2 as pynotify |
| @@ -38,7 +38,7 @@ except ImportError: | |||
| 38 | 38 | ||
| 39 | 39 | ||
| 40 | __author__ = 'Simeon Simeonov' | 40 | __author__ = 'Simeon Simeonov' |
| 41 | __version__ = '4.1' | 41 | __version__ = '4.2' |
| 42 | __license__ = 'GPL3' | 42 | __license__ = 'GPL3' |
| 43 | 43 | ||
| 44 | 44 | ||
| @@ -71,6 +71,7 @@ def eprint(*arg, **kwargs): | |||
| 71 | 71 | ||
| 72 | def beinc_login_required(method): | 72 | def beinc_login_required(method): |
| 73 | """Decorator for checking login credentials""" | 73 | """Decorator for checking login credentials""" |
| 74 | |||
| 74 | @wraps(method) | 75 | @wraps(method) |
| 75 | def wrapper(self, data, *arg, **kwargs): | 76 | def wrapper(self, data, *arg, **kwargs): |
| 76 | if data.get('resource_name') is None: | 77 | if data.get('resource_name') is None: |
| @@ -84,6 +85,7 @@ def beinc_login_required(method): | |||
| 84 | if not instance.password_match(data.get('password')): | 85 | if not instance.password_match(data.get('password')): |
| 85 | raise BEINCError401('Wrong instance or password') | 86 | raise BEINCError401('Wrong instance or password') |
| 86 | return method(self, data, *arg, **kwargs) | 87 | return method(self, data, *arg, **kwargs) |
| 88 | |||
| 87 | return wrapper | 89 | return wrapper |
| 88 | 90 | ||
| 89 | 91 | ||
| @@ -105,19 +107,24 @@ class BEINCInstance: | |||
| 105 | self._queue_size = 0 # disable queueing | 107 | self._queue_size = 0 # disable queueing |
| 106 | if pynotify is None: | 108 | if pynotify is None: |
| 107 | eprint('This server does not possess pynotify capability') | 109 | eprint('This server does not possess pynotify capability') |
| 108 | eprint(f'Remove the instance {self._name} or define it with ' | 110 | eprint( |
| 109 | f'"osd_system": "none" or other ' | 111 | f'Remove the instance {self._name} or define it with ' |
| 110 | f'available backend') | 112 | f'"osd_system": "none" or other ' |
| 113 | f'available backend' | ||
| 114 | ) | ||
| 111 | sys.exit(errno.EPERM) | 115 | sys.exit(errno.EPERM) |
| 112 | try: | 116 | try: |
| 113 | self._osd_notification = pynotify.Notification(' ') | 117 | self._osd_notification = pynotify.Notification(' ') |
| 114 | self._osd_notification.timeout = 1000 * int( | 118 | self._osd_notification.timeout = 1000 * int( |
| 115 | instance_dict.get('osd_timeout', 5)) | 119 | instance_dict.get('osd_timeout', 5) |
| 120 | ) | ||
| 116 | self._osd_notification.set_category('im.received') | 121 | self._osd_notification.set_category('im.received') |
| 117 | self._osd_type = BEINC_OSD_TYPE_PYNOTIFY | 122 | self._osd_type = BEINC_OSD_TYPE_PYNOTIFY |
| 118 | except Exception as e: | 123 | except Exception as e: |
| 119 | eprint(f'Unable to set up a pynotify notification object ' | 124 | eprint( |
| 120 | f'for "{self._name}" ({e})') | 125 | f'Unable to set up a pynotify notification object ' |
| 126 | f'for "{self._name}" ({e})' | ||
| 127 | ) | ||
| 121 | sys.exit(errno.EPERM) | 128 | sys.exit(errno.EPERM) |
| 122 | 129 | ||
| 123 | @property | 130 | @property |
| @@ -195,6 +202,7 @@ class BEINCInstance: | |||
| 195 | 202 | ||
| 196 | class BEINCCustomHandler(BaseHTTPRequestHandler): | 203 | class BEINCCustomHandler(BaseHTTPRequestHandler): |
| 197 | """Custom handler""" | 204 | """Custom handler""" |
| 205 | |||
| 198 | def do_POST(self): | 206 | def do_POST(self): |
| 199 | """Handle POST requests""" | 207 | """Handle POST requests""" |
| 200 | if self.path.strip('/') not in ('beinc/push', 'beinc/pull'): | 208 | if self.path.strip('/') not in ('beinc/push', 'beinc/pull'): |
| @@ -203,14 +211,18 @@ class BEINCCustomHandler(BaseHTTPRequestHandler): | |||
| 203 | form = cgi.FieldStorage( | 211 | form = cgi.FieldStorage( |
| 204 | fp=self.rfile, | 212 | fp=self.rfile, |
| 205 | headers=self.headers, | 213 | headers=self.headers, |
| 206 | environ={'REQUEST_METHOD': 'POST', | 214 | environ={ |
| 207 | 'CONTENT_TYPE': self.headers['Content-Type']}) | 215 | 'REQUEST_METHOD': 'POST', |
| 216 | 'CONTENT_TYPE': self.headers['Content-Type'], | ||
| 217 | }, | ||
| 218 | ) | ||
| 208 | # extract all known fields | 219 | # extract all known fields |
| 209 | POST_data = dict( | 220 | POST_data = dict( |
| 210 | resource_name=form.getvalue('resource_name'), | 221 | resource_name=form.getvalue('resource_name'), |
| 211 | password=form.getvalue('password'), | 222 | password=form.getvalue('password'), |
| 212 | title=form.getvalue('title', ''), | 223 | title=form.getvalue('title', ''), |
| 213 | message=form.getvalue('message', '')) | 224 | message=form.getvalue('message', ''), |
| 225 | ) | ||
| 214 | try: | 226 | try: |
| 215 | result = {} | 227 | result = {} |
| 216 | if self.path.strip('/') == 'beinc/push': | 228 | if self.path.strip('/') == 'beinc/push': |
| @@ -249,10 +261,11 @@ class BEINCCustomHandler(BaseHTTPRequestHandler): | |||
| 249 | instance = self.server.instances[data.get('resource_name')] | 261 | instance = self.server.instances[data.get('resource_name')] |
| 250 | try: | 262 | try: |
| 251 | if not instance.queueable: | 263 | if not instance.queueable: |
| 252 | raise BEINCError405( | 264 | raise BEINCError405('This instance does not support queuing') |
| 253 | 'This instance does not support queuing') | 265 | return { |
| 254 | return {'message': 'OK. Fetched.', | 266 | 'message': 'OK. Fetched.', |
| 255 | 'data': {'messages': instance.get_queue()}} | 267 | 'data': {'messages': instance.get_queue()}, |
| 268 | } | ||
| 256 | except Exception as e: | 269 | except Exception as e: |
| 257 | self._generate_json_error(500, str(e)) | 270 | self._generate_json_error(500, str(e)) |
| 258 | 271 | ||
| @@ -270,9 +283,9 @@ class BEINCCustomHandler(BaseHTTPRequestHandler): | |||
| 270 | self.send_header('Content-type', 'application/json; charset=utf-8') | 283 | self.send_header('Content-type', 'application/json; charset=utf-8') |
| 271 | self.end_headers() | 284 | self.end_headers() |
| 272 | msg = {'code': code, 'message': message, 'data': {}} | 285 | msg = {'code': code, 'message': message, 'data': {}} |
| 273 | self.wfile.write(json.dumps(msg, | 286 | self.wfile.write( |
| 274 | sort_keys=True, | 287 | json.dumps(msg, sort_keys=True, indent=4).encode('utf-8') |
| 275 | indent=4).encode('utf-8')) | 288 | ) |
| 276 | 289 | ||
| 277 | def _render_to_JSON_response(self, context): | 290 | def _render_to_JSON_response(self, context): |
| 278 | """ | 291 | """ |
| @@ -284,13 +297,14 @@ class BEINCCustomHandler(BaseHTTPRequestHandler): | |||
| 284 | self.send_response(200) | 297 | self.send_response(200) |
| 285 | self.send_header('Content-type', 'application/json; charset=utf-8') | 298 | self.send_header('Content-type', 'application/json; charset=utf-8') |
| 286 | self.end_headers() | 299 | self.end_headers() |
| 287 | self.wfile.write(json.dumps(response, | 300 | self.wfile.write( |
| 288 | sort_keys=True, | 301 | json.dumps(response, sort_keys=True, indent=4).encode('utf-8') |
| 289 | indent=4).encode('utf-8')) | 302 | ) |
| 290 | 303 | ||
| 291 | 304 | ||
| 292 | class BEINCNotifyServer(HTTPServer): | 305 | class BEINCNotifyServer(HTTPServer): |
| 293 | """BEINCNotifyServer class""" | 306 | """BEINCNotifyServer class""" |
| 307 | |||
| 294 | def __init__(self, *arg, **kwargs): | 308 | def __init__(self, *arg, **kwargs): |
| 295 | """Default constructor""" | 309 | """Default constructor""" |
| 296 | super().__init__(*arg, **kwargs) | 310 | super().__init__(*arg, **kwargs) |
| @@ -319,9 +333,7 @@ class BEINCNotifyServer(HTTPServer): | |||
| 319 | self._instances[instance['name']] = BEINCInstance(instance) | 333 | self._instances[instance['name']] = BEINCInstance(instance) |
| 320 | logger.info('Instance %s added', instance['name']) | 334 | logger.info('Instance %s added', instance['name']) |
| 321 | except Exception as e: | 335 | except Exception as e: |
| 322 | eprint('Unable to create instance "{0}": {1}'.format( | 336 | eprint(f"Unable to create instance \"{instance['name']}\": {e}") |
| 323 | instance['name'], | ||
| 324 | e)) | ||
| 325 | sys.exit(1) | 337 | sys.exit(1) |
| 326 | 338 | ||
| 327 | @property | 339 | @property |
| @@ -334,51 +346,66 @@ class BEINCNotifyServer(HTTPServer): | |||
| 334 | 346 | ||
| 335 | if __name__ == '__main__': | 347 | if __name__ == '__main__': |
| 336 | parser = argparse.ArgumentParser( | 348 | parser = argparse.ArgumentParser( |
| 337 | description='The following options are available') | 349 | description='The following options are available' |
| 350 | ) | ||
| 338 | parser.add_argument( | 351 | parser.add_argument( |
| 339 | '-H', '--hostname', | 352 | '-H', |
| 353 | '--hostname', | ||
| 340 | metavar='HOSTNAME', | 354 | metavar='HOSTNAME', |
| 341 | type=str, | 355 | type=str, |
| 342 | dest='hostname', | 356 | dest='hostname', |
| 343 | default='127.0.0.1', | 357 | default='127.0.0.1', |
| 344 | help='BEINC server IP / hostname (default: 127.0.0.1)') | 358 | help='BEINC server IP / hostname (default: 127.0.0.1)', |
| 359 | ) | ||
| 345 | parser.add_argument( | 360 | parser.add_argument( |
| 346 | '-L', '--logger-name', | 361 | '-L', |
| 362 | '--logger-name', | ||
| 347 | metavar='NAME', | 363 | metavar='NAME', |
| 348 | type=str, | 364 | type=str, |
| 349 | dest='logger_name', | 365 | dest='logger_name', |
| 350 | default='', | 366 | default='', |
| 351 | help="BEINC logger name (default: 'beinc')") | 367 | help="BEINC logger name (default: 'beinc')", |
| 368 | ) | ||
| 352 | parser.add_argument( | 369 | parser.add_argument( |
| 353 | '-l', '--logger-config', | 370 | '-l', |
| 371 | '--logger-config', | ||
| 354 | metavar='CONFIG', | 372 | metavar='CONFIG', |
| 355 | type=str, | 373 | type=str, |
| 356 | dest='logger_config', | 374 | dest='logger_config', |
| 357 | default=os.path.expanduser('~/.beinc_server_logger.ini'), | 375 | default=os.path.expanduser('~/.beinc_server_logger.ini'), |
| 358 | help=('BEINC logger config (.ini) ' | 376 | help=( |
| 359 | '(default: ~/.beinc_server_logger.ini)')) | 377 | 'BEINC logger config (.ini) ' |
| 378 | '(default: ~/.beinc_server_logger.ini)' | ||
| 379 | ), | ||
| 380 | ) | ||
| 360 | parser.add_argument( | 381 | parser.add_argument( |
| 361 | '-p', '--port', | 382 | '-p', |
| 383 | '--port', | ||
| 362 | metavar='PORT', | 384 | metavar='PORT', |
| 363 | type=int, | 385 | type=int, |
| 364 | dest='port', | 386 | dest='port', |
| 365 | default=9998, | 387 | default=9998, |
| 366 | help='BEINC server port (default: 9998)') | 388 | help='BEINC server port (default: 9998)', |
| 389 | ) | ||
| 367 | parser.add_argument( | 390 | parser.add_argument( |
| 368 | '-f', '--config-file', | 391 | '-f', |
| 392 | '--config-file', | ||
| 369 | metavar='FILE', | 393 | metavar='FILE', |
| 370 | type=str, | 394 | type=str, |
| 371 | default=os.path.expanduser('~/.beinc_server.json'), | 395 | default=os.path.expanduser('~/.beinc_server.json'), |
| 372 | dest='config_file', | 396 | dest='config_file', |
| 373 | help='BEINC config file (default: ~/.beinc_server.json)') | 397 | help='BEINC config file (default: ~/.beinc_server.json)', |
| 398 | ) | ||
| 374 | parser.add_argument( | 399 | parser.add_argument( |
| 375 | '-v', '--version', | 400 | '-v', |
| 401 | '--version', | ||
| 376 | action='version', | 402 | action='version', |
| 377 | version=f'%(prog)s {__version__}', | 403 | version=f'%(prog)s {__version__}', |
| 378 | help='Display program-version and exit') | 404 | help='Display program-version and exit', |
| 405 | ) | ||
| 379 | args = parser.parse_args() | 406 | args = parser.parse_args() |
| 380 | try: | 407 | try: |
| 381 | with open(args.config_file, 'r') as fp: | 408 | with io.open(args.config_file, 'r', encoding='utf-8') as fp: |
| 382 | config_dict = json.load(fp) | 409 | config_dict = json.load(fp) |
| 383 | except Exception as e: | 410 | except Exception as e: |
| 384 | eprint(f'Unable to parse {args.config_file}: {e}') | 411 | eprint(f'Unable to parse {args.config_file}: {e}') |
| @@ -390,35 +417,42 @@ if __name__ == '__main__': | |||
| 390 | else: | 417 | else: |
| 391 | logging.basicConfig( | 418 | logging.basicConfig( |
| 392 | format='%(asctime)s - %(levelname)s - %(message)s', | 419 | format='%(asctime)s - %(levelname)s - %(message)s', |
| 393 | level=logging.DEBUG) | 420 | level=logging.DEBUG, |
| 421 | ) | ||
| 394 | logger = logging.getLogger('beinc') | 422 | logger = logging.getLogger('beinc') |
| 395 | logger.info('BEINC starting. Loading config...') | 423 | logger.info('BEINC starting. Loading config...') |
| 396 | if config_dict.get('config_version') != BEINC_CURRENT_CONFIG_VERSION: | 424 | if config_dict.get('config_version') != BEINC_CURRENT_CONFIG_VERSION: |
| 397 | eprint( | 425 | eprint( |
| 398 | 'WARNING: The version of the config-file: {0} ({1}) ' | 426 | f'WARNING: The version of the config-file: {args.config_file} ' |
| 399 | 'does not correspond to the latest version supported ' | 427 | f'({config_dict.get("config_version", "Not set")}) does not ' |
| 400 | 'by this program ({2})\nCheck beinc_config_sample.json ' | 428 | 'correspond to the latest version supported by this program ' |
| 401 | 'for the newest features!'.format( | 429 | f'({BEINC_CURRENT_CONFIG_VERSION})\n' |
| 402 | args.config_file, | 430 | 'Check beinc_config_sample.json for the newest features!' |
| 403 | config_dict.get('config_version', 'Not set'), | 431 | ) |
| 404 | BEINC_CURRENT_CONFIG_VERSION)) | ||
| 405 | ssl_certificate = config_dict['server']['general'].get( | 432 | ssl_certificate = config_dict['server']['general'].get( |
| 406 | 'ssl_certificate') | 433 | 'ssl_certificate' |
| 434 | ) | ||
| 407 | ssl_private_key = config_dict['server']['general'].get( | 435 | ssl_private_key = config_dict['server']['general'].get( |
| 408 | 'ssl_private_key') | 436 | 'ssl_private_key' |
| 437 | ) | ||
| 409 | ssl_acceptable_ciphers_str = config_dict['server']['general'].get( | 438 | ssl_acceptable_ciphers_str = config_dict['server']['general'].get( |
| 410 | 'ssl_ciphers') | 439 | 'ssl_ciphers' |
| 411 | beinc_server = BEINCNotifyServer((args.hostname, args.port), | 440 | ) |
| 412 | BEINCCustomHandler) | 441 | beinc_server = BEINCNotifyServer( |
| 442 | (args.hostname, args.port), | ||
| 443 | BEINCCustomHandler, | ||
| 444 | ) | ||
| 413 | beinc_server.set_config(config_dict) | 445 | beinc_server.set_config(config_dict) |
| 414 | if ssl_certificate and ssl_private_key: | 446 | if ssl_certificate and ssl_private_key: |
| 415 | beinc_server.socket = ssl.wrap_socket( | 447 | context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) |
| 416 | beinc_server.socket, | 448 | context.load_cert_chain( |
| 417 | keyfile=ssl_private_key, | 449 | certfile=ssl_certificate, keyfile=ssl_private_key |
| 418 | certfile=ssl_certificate, | 450 | ) |
| 419 | server_side=True, | 451 | if ssl_acceptable_ciphers_str is not None: |
| 420 | ssl_version=ssl.PROTOCOL_TLSv1_2, | 452 | context.set_ciphers(ssl_acceptable_ciphers_str) |
| 421 | ciphers=ssl_acceptable_ciphers_str) | 453 | beinc_server.socket = context.wrap_socket( |
| 454 | beinc_server.socket, server_side=True | ||
| 455 | ) | ||
| 422 | logger.info('Done!') | 456 | logger.info('Done!') |
| 423 | beinc_server.serve_forever() | 457 | beinc_server.serve_forever() |
| 424 | except KeyboardInterrupt: | 458 | except KeyboardInterrupt: |
diff --git a/beinc_weechat.py b/beinc_weechat.py index 75af86a..2288b74 100644 --- a/beinc_weechat.py +++ b/beinc_weechat.py | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
| 2 | 2 | ||
| 3 | # Blackmore's Enhanced IRC-Notification Collection (BEINC) v4.0 | 3 | # Blackmore's Enhanced IRC-Notification Collection (BEINC) v4.0 |
| 4 | # Copyright (C) 2013-2020 Simeon Simeonov | 4 | # Copyright (C) 2013-2022 Simeon Simeonov |
| 5 | 5 | ||
| 6 | # This program is free software: you can redistribute it and/or modify | 6 | # This program is free software: you can redistribute it and/or modify |
| 7 | # it under the terms of the GNU General Public License as published by | 7 | # it under the terms of the GNU General Public License as published by |
| @@ -17,6 +17,7 @@ | |||
| 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | """BEINC client for Weechat""" | 18 | """BEINC client for Weechat""" |
| 19 | import datetime | 19 | import datetime |
| 20 | import io | ||
| 20 | import json | 21 | import json |
| 21 | import os | 22 | import os |
| 22 | import socket | 23 | import socket |
| @@ -26,9 +27,8 @@ import urllib.request | |||
| 26 | 27 | ||
| 27 | import weechat | 28 | import weechat |
| 28 | 29 | ||
| 29 | |||
| 30 | __author__ = 'Simeon Simeonov' | 30 | __author__ = 'Simeon Simeonov' |
| 31 | __version__ = '4.1' | 31 | __version__ = '4.2' |
| 32 | __license__ = 'GPL3' | 32 | __license__ = 'GPL3' |
| 33 | 33 | ||
| 34 | 34 | ||
| @@ -61,38 +61,46 @@ class WeechatTarget: | |||
| 61 | if self._url == '': | 61 | if self._url == '': |
| 62 | raise Exception('"target_url" not defined for target') | 62 | raise Exception('"target_url" not defined for target') |
| 63 | self._password = target_dict.get('target_password', '') | 63 | self._password = target_dict.get('target_password', '') |
| 64 | self._pm_title_template = target_dict.get('pm_title_template', | 64 | self._pm_title_template = target_dict.get( |
| 65 | '%s @ %S') | 65 | 'pm_title_template', '%s @ %S' |
| 66 | self._pm_message_template = target_dict.get('pm_message_template', | 66 | ) |
| 67 | '%m') | 67 | self._pm_message_template = target_dict.get( |
| 68 | self._cm_title_template = target_dict.get('cm_title_template', | 68 | 'pm_message_template', '%m' |
| 69 | '%c @ %S') | 69 | ) |
| 70 | self._cm_message_template = target_dict.get('cm_message_template', | 70 | self._cm_title_template = target_dict.get( |
| 71 | '%s -> %m') | 71 | 'cm_title_template', '%c @ %S' |
| 72 | self._nm_title_template = target_dict.get('nm_title_template', | 72 | ) |
| 73 | '%c @ %S') | 73 | self._cm_message_template = target_dict.get( |
| 74 | self._nm_message_template = target_dict.get('nm_message_template', | 74 | 'cm_message_template', '%s -> %m' |
| 75 | '%s -> %m') | 75 | ) |
| 76 | self._nm_title_template = target_dict.get( | ||
| 77 | 'nm_title_template', '%c @ %S' | ||
| 78 | ) | ||
| 79 | self._nm_message_template = target_dict.get( | ||
| 80 | 'nm_message_template', '%s -> %m' | ||
| 81 | ) | ||
| 76 | self._chans = set(target_dict.get('channel_list', [])) | 82 | self._chans = set(target_dict.get('channel_list', [])) |
| 77 | self._nicks = set(target_dict.get('nick_list', [])) | 83 | self._nicks = set(target_dict.get('nick_list', [])) |
| 78 | self._chan_messages_policy = int(target_dict.get( | 84 | self._chan_messages_policy = int( |
| 79 | 'channel_messages_policy', | 85 | target_dict.get('channel_messages_policy', BEINC_POLICY_LIST_ONLY) |
| 80 | BEINC_POLICY_LIST_ONLY)) | 86 | ) |
| 81 | self._priv_messages_policy = int(target_dict.get( | 87 | self._priv_messages_policy = int( |
| 82 | 'private_messages_policy', | 88 | target_dict.get('private_messages_policy', BEINC_POLICY_ALL) |
| 83 | BEINC_POLICY_ALL)) | 89 | ) |
| 84 | self._notifications_policy = int(target_dict.get( | 90 | self._notifications_policy = int( |
| 85 | 'notifications_policy', | 91 | target_dict.get('notifications_policy', BEINC_POLICY_ALL) |
| 86 | BEINC_POLICY_ALL)) | 92 | ) |
| 87 | self._cert_file = target_dict.get('target_cert_file') | 93 | self._cert_file = target_dict.get('target_cert_file') |
| 88 | self._timestamp_format = target_dict.get('target_timestamp_format', | 94 | self._timestamp_format = target_dict.get( |
| 89 | '%H:%M:%S') | 95 | 'target_timestamp_format', '%H:%M:%S' |
| 96 | ) | ||
| 90 | self._debug = bool(target_dict.get('debug', False)) | 97 | self._debug = bool(target_dict.get('debug', False)) |
| 91 | self._enabled = bool(target_dict.get('enabled', True)) | 98 | self._enabled = bool(target_dict.get('enabled', True)) |
| 92 | self._socket_timeout = int(target_dict.get('socket_timeout', 3)) | 99 | self._socket_timeout = int(target_dict.get('socket_timeout', 3)) |
| 93 | self._ssl_ciphers = target_dict.get('ssl_ciphers', '') | 100 | self._ssl_ciphers = target_dict.get('ssl_ciphers', '') |
| 94 | self._disable_hostname_check = bool( | 101 | self._disable_hostname_check = bool( |
| 95 | target_dict.get('disable-hostname-check', False)) | 102 | target_dict.get('disable-hostname-check', False) |
| 103 | ) | ||
| 96 | self._ssl_version = target_dict.get('ssl_version', 'auto') | 104 | self._ssl_version = target_dict.get('ssl_version', 'auto') |
| 97 | self._last_message = None # datetime.datetime instance | 105 | self._last_message = None # datetime.datetime instance |
| 98 | self._context = None | 106 | self._context = None |
| @@ -143,26 +151,22 @@ class WeechatTarget: | |||
| 143 | last_message = 'never' | 151 | last_message = 'never' |
| 144 | if self._last_message is not None: | 152 | if self._last_message is not None: |
| 145 | last_message = self._last_message.strftime('%Y-%m-%d %H:%M:%S') | 153 | last_message = self._last_message.strftime('%Y-%m-%d %H:%M:%S') |
| 146 | return ('name: {0}\nurl: {1}\nenabled: {2}\nchannel_list: {3}\n' | 154 | return ( |
| 147 | 'nick_list: {4}\nchannel_messages_policy: {5}\n' | 155 | f'name: {self._name}\nurl: {self._url}\n' |
| 148 | 'private_messages_policy: {6}\nnotifications_policy: {7}\n' | 156 | f"enabled: {'yes' if self._enabled else 'no'}\n" |
| 149 | 'last message: {8}\nsocket timeout: {9}\nssl-version: {10}\n' | 157 | f"channel_list: {', '.join(self._chans)}\n" |
| 150 | 'ciphers: {11}\ndisable hostname check: {12}\n' | 158 | f"nick_list: {', '.join(self._nicks)}\n" |
| 151 | 'debug: {13}\n\n'.format( | 159 | f'channel_messages_policy: {self._chan_messages_policy}\n' |
| 152 | self._name, | 160 | f'private_messages_policy: {self._priv_messages_policy}\n' |
| 153 | self._url, | 161 | f'notifications_policy: {self._notifications_policy}\n' |
| 154 | 'yes' if self._enabled else 'no', | 162 | f'last message: {last_message}\n' |
| 155 | ', '.join(self._chans), | 163 | f'socket timeout: {self._socket_timeout}\n' |
| 156 | ', '.join(self._nicks), | 164 | f'ssl-version: {self._ssl_version}\n' |
| 157 | self._chan_messages_policy, | 165 | f"ciphers: {self._ssl_ciphers or 'auto'}\n" |
| 158 | self._priv_messages_policy, | 166 | "disable hostname check: " |
| 159 | self._notifications_policy, | 167 | f"{'yes' if self._disable_hostname_check else 'no'}\n" |
| 160 | last_message, | 168 | f"debug: {'yes' if self._debug else 'no'}\n\n" |
| 161 | self._socket_timeout, | 169 | ) |
| 162 | self._ssl_version, | ||
| 163 | self._ssl_ciphers or 'auto', | ||
| 164 | 'yes' if self._disable_hostname_check else 'no', | ||
| 165 | 'yes' if self._debug else 'no')) | ||
| 166 | 170 | ||
| 167 | def send_private_message_notification(self, values): | 171 | def send_private_message_notification(self, values): |
| 168 | """ | 172 | """ |
| @@ -172,20 +176,22 @@ class WeechatTarget: | |||
| 172 | :type value: dict | 176 | :type value: dict |
| 173 | """ | 177 | """ |
| 174 | try: | 178 | try: |
| 175 | title = self._fetch_formatted_str(self._pm_title_template, | 179 | title = self._fetch_formatted_str(self._pm_title_template, values) |
| 176 | values) | ||
| 177 | message = self._fetch_formatted_str( | 180 | message = self._fetch_formatted_str( |
| 178 | self._pm_message_template, | 181 | self._pm_message_template, |
| 179 | values) | 182 | values, |
| 183 | ) | ||
| 180 | if not self._send_beinc_message(title, message) and self._debug: | 184 | if not self._send_beinc_message(title, message) and self._debug: |
| 181 | beinc_prnt( | 185 | beinc_prnt( |
| 182 | f'BEINC DEBUG: send_private_message_notification-ERROR ' | 186 | f'BEINC DEBUG: send_private_message_notification-ERROR ' |
| 183 | f'for "{self._name}": _send_beinc_message -> False') | 187 | f'for "{self._name}": _send_beinc_message -> False' |
| 188 | ) | ||
| 184 | except Exception as e: | 189 | except Exception as e: |
| 185 | if self._debug: | 190 | if self._debug: |
| 186 | beinc_prnt( | 191 | beinc_prnt( |
| 187 | f'BEINC DEBUG: send_private_message_notification-ERROR ' | 192 | f'BEINC DEBUG: send_private_message_notification-ERROR ' |
| 188 | f'for "{self._name}": {e}') | 193 | f'for "{self._name}": {e}' |
| 194 | ) | ||
| 189 | 195 | ||
| 190 | def send_channel_message_notification(self, values): | 196 | def send_channel_message_notification(self, values): |
| 191 | """ | 197 | """ |
| @@ -195,19 +201,21 @@ class WeechatTarget: | |||
| 195 | :type value: dict | 201 | :type value: dict |
| 196 | """ | 202 | """ |
| 197 | try: | 203 | try: |
| 198 | title = self._fetch_formatted_str(self._cm_title_template, | 204 | title = self._fetch_formatted_str(self._cm_title_template, values) |
| 199 | values) | 205 | message = self._fetch_formatted_str( |
| 200 | message = self._fetch_formatted_str(self._cm_message_template, | 206 | self._cm_message_template, values |
| 201 | values) | 207 | ) |
| 202 | if not self._send_beinc_message(title, message) and self._debug: | 208 | if not self._send_beinc_message(title, message) and self._debug: |
| 203 | beinc_prnt( | 209 | beinc_prnt( |
| 204 | f'BEINC DEBUG: send_channel_message_notification-ERROR ' | 210 | f'BEINC DEBUG: send_channel_message_notification-ERROR ' |
| 205 | f'for "{self._name}": _send_beinc_message -> False') | 211 | f'for "{self._name}": _send_beinc_message -> False' |
| 212 | ) | ||
| 206 | except Exception as e: | 213 | except Exception as e: |
| 207 | if self._debug: | 214 | if self._debug: |
| 208 | beinc_prnt( | 215 | beinc_prnt( |
| 209 | f'BEINC DEBUG: send_channel_message_notification-ERROR ' | 216 | f'BEINC DEBUG: send_channel_message_notification-ERROR ' |
| 210 | f'for "{self._name}": {e}') | 217 | f'for "{self._name}": {e}' |
| 218 | ) | ||
| 211 | 219 | ||
| 212 | def send_notify_message_notification(self, values): | 220 | def send_notify_message_notification(self, values): |
| 213 | """ | 221 | """ |
| @@ -217,19 +225,21 @@ class WeechatTarget: | |||
| 217 | :type value: dict | 225 | :type value: dict |
| 218 | """ | 226 | """ |
| 219 | try: | 227 | try: |
| 220 | title = self._fetch_formatted_str(self._nm_title_template, | 228 | title = self._fetch_formatted_str(self._nm_title_template, values) |
| 221 | values) | 229 | message = self._fetch_formatted_str( |
| 222 | message = self._fetch_formatted_str(self._nm_message_template, | 230 | self._nm_message_template, values |
| 223 | values) | 231 | ) |
| 224 | if not self._send_beinc_message(title, message) and self._debug: | 232 | if not self._send_beinc_message(title, message) and self._debug: |
| 225 | beinc_prnt( | 233 | beinc_prnt( |
| 226 | f'BEINC DEBUG: send_notify_message_notification-ERROR ' | 234 | f'BEINC DEBUG: send_notify_message_notification-ERROR ' |
| 227 | f'for "{self._name}": _send_beinc_message -> False') | 235 | f'for "{self._name}": _send_beinc_message -> False' |
| 236 | ) | ||
| 228 | except Exception as e: | 237 | except Exception as e: |
| 229 | if self._debug: | 238 | if self._debug: |
| 230 | beinc_prnt( | 239 | beinc_prnt( |
| 231 | f'BEINC DEBUG: send_notify_message_notification-ERROR ' | 240 | f'BEINC DEBUG: send_notify_message_notification-ERROR ' |
| 232 | f'for "{self._name}": {e}') | 241 | f'for "{self._name}": {e}' |
| 242 | ) | ||
| 233 | 243 | ||
| 234 | def send_broadcast_notification(self, message): | 244 | def send_broadcast_notification(self, message): |
| 235 | """ | 245 | """ |
| @@ -244,26 +254,30 @@ class WeechatTarget: | |||
| 244 | if not self._send_beinc_message(title, message) and self._debug: | 254 | if not self._send_beinc_message(title, message) and self._debug: |
| 245 | beinc_prnt( | 255 | beinc_prnt( |
| 246 | f'BEINC DEBUG: send_broadcast_notification-ERROR ' | 256 | f'BEINC DEBUG: send_broadcast_notification-ERROR ' |
| 247 | f'for "{self._name}": _send_beinc_message -> False') | 257 | f'for "{self._name}": _send_beinc_message -> False' |
| 258 | ) | ||
| 248 | except Exception as e: | 259 | except Exception as e: |
| 249 | if self._debug: | 260 | if self._debug: |
| 250 | beinc_prnt( | 261 | beinc_prnt( |
| 251 | f'BEINC DEBUG: send_broadcast_notification-ERROR ' | 262 | f'BEINC DEBUG: send_broadcast_notification-ERROR ' |
| 252 | f'for "{self._name}": {e}') | 263 | f'for "{self._name}": {e}' |
| 264 | ) | ||
| 253 | 265 | ||
| 254 | def _context_setup(self): | 266 | def _context_setup(self): |
| 255 | """Sets up the SSL context""" | 267 | """Sets up the SSL context""" |
| 256 | if self._context is not None: | 268 | if self._context is not None: |
| 257 | return True | 269 | return True |
| 258 | try: | 270 | try: |
| 259 | context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) | 271 | context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) |
| 260 | context.verify_mode = ssl.CERT_NONE | ||
| 261 | if self._cert_file: | 272 | if self._cert_file: |
| 262 | context.verify_mode = ssl.CERT_REQUIRED | 273 | context.verify_mode = ssl.CERT_REQUIRED |
| 263 | context.load_verify_locations(cafile=os.path.expanduser( | 274 | context.load_verify_locations( |
| 264 | self._cert_file)) | 275 | cafile=os.path.expanduser(self._cert_file) |
| 265 | context.check_hostname = bool( | 276 | ) |
| 266 | not self._disable_hostname_check) | 277 | context.check_hostname = bool(not self._disable_hostname_check) |
| 278 | else: | ||
| 279 | context.check_hostname = False | ||
| 280 | context.verify_mode = ssl.CERT_NONE | ||
| 267 | if self._ssl_ciphers and self._ssl_ciphers != 'auto': | 281 | if self._ssl_ciphers and self._ssl_ciphers != 'auto': |
| 268 | context.set_ciphers(self._ssl_ciphers) | 282 | context.set_ciphers(self._ssl_ciphers) |
| 269 | self._context = context | 283 | self._context = context |
| @@ -292,13 +306,15 @@ class WeechatTarget: | |||
| 292 | :rtype: str | 306 | :rtype: str |
| 293 | """ | 307 | """ |
| 294 | timestamp = datetime.datetime.now().strftime(self._timestamp_format) | 308 | timestamp = datetime.datetime.now().strftime(self._timestamp_format) |
| 295 | replacements = {'%S': values['server'], | 309 | replacements = { |
| 296 | '%s': values['source_nick'], | 310 | '%S': values['server'], |
| 297 | '%c': values['channel'], | 311 | '%s': values['source_nick'], |
| 298 | '%m': values['message'], | 312 | '%c': values['channel'], |
| 299 | '%t': timestamp, | 313 | '%m': values['message'], |
| 300 | '%p': 'BEINC', | 314 | '%t': timestamp, |
| 301 | '%n': values['own_nick']} | 315 | '%p': 'BEINC', |
| 316 | '%n': values['own_nick'], | ||
| 317 | } | ||
| 302 | for key, value in replacements.items(): | 318 | for key, value in replacements.items(): |
| 303 | template = template.replace(key, value) | 319 | template = template.replace(key, value) |
| 304 | return template | 320 | return template |
| @@ -327,16 +343,20 @@ class WeechatTarget: | |||
| 327 | ('resource_name', self._name), | 343 | ('resource_name', self._name), |
| 328 | ('password', self._password), | 344 | ('password', self._password), |
| 329 | ('title', title), | 345 | ('title', title), |
| 330 | ('message', message) | 346 | ('message', message), |
| 331 | )).encode('utf-8'), | 347 | ) |
| 348 | ).encode('utf-8'), | ||
| 332 | timeout=self._socket_timeout, | 349 | timeout=self._socket_timeout, |
| 333 | context=self._context) | 350 | context=self._context, |
| 351 | ) | ||
| 334 | response_dict = json.loads(response.read().decode('utf-8')) | 352 | response_dict = json.loads(response.read().decode('utf-8')) |
| 335 | if response.code != 200: | 353 | if response.code != 200: |
| 336 | raise socket.error(response_dict.get('message', '')) | 354 | raise socket.error(response_dict.get('message', '')) |
| 337 | if self._debug: | 355 | if self._debug: |
| 338 | beinc_prnt('BEINC DEBUG: Server responded: {0}'.format( | 356 | beinc_prnt( |
| 339 | response_dict.get('message'))) | 357 | "BEINC DEBUG: Server responded: " |
| 358 | f"{response_dict.get('message')}" | ||
| 359 | ) | ||
| 340 | self._last_message = datetime.datetime.now() | 360 | self._last_message = datetime.datetime.now() |
| 341 | return True | 361 | return True |
| 342 | except ssl.SSLError as e: | 362 | except ssl.SSLError as e: |
| @@ -378,7 +398,7 @@ def beinc_cmd_target_handler(cmd_tokens): | |||
| 378 | if cmd_tokens[0] == 'list': | 398 | if cmd_tokens[0] == 'list': |
| 379 | beinc_prnt('--- Globals ---') | 399 | beinc_prnt('--- Globals ---') |
| 380 | for key, value in global_values.items(): | 400 | for key, value in global_values.items(): |
| 381 | beinc_prnt('{key} -> {value}'.format(key=key, value=str(value))) | 401 | beinc_prnt(f'{key} -> {str(value)}') |
| 382 | beinc_prnt('--- Targets ---') | 402 | beinc_prnt('--- Targets ---') |
| 383 | for target in target_list: | 403 | for target in target_list: |
| 384 | beinc_prnt(str(target)) | 404 | beinc_prnt(str(target)) |
| @@ -430,8 +450,10 @@ def beinc_command(data, buffer_obj, args): | |||
| 430 | elif cmd_tokens[0] == 'target': | 450 | elif cmd_tokens[0] == 'target': |
| 431 | return beinc_cmd_target_handler(cmd_tokens[1:]) | 451 | return beinc_cmd_target_handler(cmd_tokens[1:]) |
| 432 | else: | 452 | else: |
| 433 | beinc_prnt('syntax: /beinc < on | off | reload |' | 453 | beinc_prnt( |
| 434 | ' broadcast <text> | target <action> >') | 454 | 'syntax: /beinc < on | off | reload |' |
| 455 | ' broadcast <text> | target <action> >' | ||
| 456 | ) | ||
| 435 | return weechat.WEECHAT_RC_OK | 457 | return weechat.WEECHAT_RC_OK |
| 436 | 458 | ||
| 437 | 459 | ||
| @@ -439,8 +461,9 @@ def beinc_privmsg_handler(data, signal, signal_data): | |||
| 439 | """Callback function the *PRIVMSG* IRC messages hooked by Weechat""" | 461 | """Callback function the *PRIVMSG* IRC messages hooked by Weechat""" |
| 440 | if not enabled: | 462 | if not enabled: |
| 441 | return weechat.WEECHAT_RC_OK | 463 | return weechat.WEECHAT_RC_OK |
| 442 | prvmsg_dict = weechat.info_get_hashtable('irc_message_parse', | 464 | prvmsg_dict = weechat.info_get_hashtable( |
| 443 | {'message': signal_data}) | 465 | 'irc_message_parse', {'message': signal_data} |
| 466 | ) | ||
| 444 | # packing the privmsg handler values | 467 | # packing the privmsg handler values |
| 445 | ph_values = {} | 468 | ph_values = {} |
| 446 | ph_values['server'] = signal.split(',')[0] | 469 | ph_values['server'] = signal.split(',')[0] |
| @@ -448,7 +471,8 @@ def beinc_privmsg_handler(data, signal, signal_data): | |||
| 448 | ph_values['channel'] = prvmsg_dict['arguments'].split(':')[0].strip() | 471 | ph_values['channel'] = prvmsg_dict['arguments'].split(':')[0].strip() |
| 449 | ph_values['source_nick'] = prvmsg_dict['nick'] | 472 | ph_values['source_nick'] = prvmsg_dict['nick'] |
| 450 | ph_values['message'] = ':'.join( | 473 | ph_values['message'] = ':'.join( |
| 451 | prvmsg_dict['arguments'].split(':')[1:]).strip() | 474 | prvmsg_dict['arguments'].split(':')[1:] |
| 475 | ).strip() | ||
| 452 | if ph_values['channel'] == ph_values['own_nick']: | 476 | if ph_values['channel'] == ph_values['own_nick']: |
| 453 | # priv messages are handled here | 477 | # priv messages are handled here |
| 454 | if not global_values['global_private_messages_policy']: | 478 | if not global_values['global_private_messages_policy']: |
| @@ -458,10 +482,10 @@ def beinc_privmsg_handler(data, signal, signal_data): | |||
| 458 | continue | 482 | continue |
| 459 | p_messages_policy = target.private_messages_policy | 483 | p_messages_policy = target.private_messages_policy |
| 460 | if p_messages_policy == BEINC_POLICY_ALL or ( | 484 | if p_messages_policy == BEINC_POLICY_ALL or ( |
| 461 | p_messages_policy == BEINC_POLICY_LIST_ONLY and | 485 | p_messages_policy == BEINC_POLICY_LIST_ONLY |
| 462 | '{0}.{1}'.format( | 486 | and f"{ph_values['server']}.{ph_values['source_nick'].lower()}" |
| 463 | ph_values['server'], | 487 | in target.nicks |
| 464 | ph_values['source_nick'].lower()) in target.nicks): | 488 | ): |
| 465 | target.send_private_message_notification(ph_values) | 489 | target.send_private_message_notification(ph_values) |
| 466 | elif ph_values['own_nick'].lower() in ph_values['message'].lower(): | 490 | elif ph_values['own_nick'].lower() in ph_values['message'].lower(): |
| 467 | # notify messages are handled here | 491 | # notify messages are handled here |
| @@ -471,10 +495,9 @@ def beinc_privmsg_handler(data, signal, signal_data): | |||
| 471 | if not target.enabled: | 495 | if not target.enabled: |
| 472 | continue | 496 | continue |
| 473 | if target.notifications_policy == BEINC_POLICY_ALL or ( | 497 | if target.notifications_policy == BEINC_POLICY_ALL or ( |
| 474 | target.notifications_policy == BEINC_POLICY_LIST_ONLY and | 498 | target.notifications_policy == BEINC_POLICY_LIST_ONLY |
| 475 | '{0}.{1}'.format( | 499 | and f"{ph_values['server']}.{ph_values['channel'].lower()}" |
| 476 | ph_values['server'], | 500 | in target.chans |
| 477 | ph_values['channel'].lower()) in target.chans | ||
| 478 | ): | 501 | ): |
| 479 | target.send_notify_message_notification(ph_values) | 502 | target.send_notify_message_notification(ph_values) |
| 480 | elif global_values['global_channel_messages_policy']: | 503 | elif global_values['global_channel_messages_policy']: |
| @@ -486,10 +509,10 @@ def beinc_privmsg_handler(data, signal, signal_data): | |||
| 486 | continue | 509 | continue |
| 487 | c_messages_policy = target.channel_messages_policy | 510 | c_messages_policy = target.channel_messages_policy |
| 488 | if c_messages_policy == BEINC_POLICY_ALL or ( | 511 | if c_messages_policy == BEINC_POLICY_ALL or ( |
| 489 | c_messages_policy == BEINC_POLICY_LIST_ONLY and | 512 | c_messages_policy == BEINC_POLICY_LIST_ONLY |
| 490 | '{0}.{1}'.format( | 513 | and f"{ph_values['server']}.{ph_values['channel'].lower()}" |
| 491 | ph_values['server'], | 514 | in target.chans |
| 492 | ph_values['channel'].lower()) in target.chans): | 515 | ): |
| 493 | target.send_channel_message_notification(ph_values) | 516 | target.send_channel_message_notification(ph_values) |
| 494 | return weechat.WEECHAT_RC_OK | 517 | return weechat.WEECHAT_RC_OK |
| 495 | 518 | ||
| @@ -517,24 +540,28 @@ def beinc_init(): | |||
| 517 | try: | 540 | try: |
| 518 | beinc_config_file_str = os.path.join( | 541 | beinc_config_file_str = os.path.join( |
| 519 | weechat.info_get('weechat_dir', ''), | 542 | weechat.info_get('weechat_dir', ''), |
| 520 | 'beinc_weechat.json') | 543 | 'beinc_weechat.json', |
| 544 | ) | ||
| 521 | beinc_prnt(f'Parsing {beinc_config_file_str}...') | 545 | beinc_prnt(f'Parsing {beinc_config_file_str}...') |
| 522 | custom_error = 'load error' | 546 | custom_error = 'load error' |
| 523 | with open(beinc_config_file_str, 'r') as fp: | 547 | with io.open(beinc_config_file_str, 'r', encoding='utf-8') as fp: |
| 524 | config_dict = json.load(fp) | 548 | config_dict = json.load(fp) |
| 525 | custom_error = 'target parse error' | 549 | custom_error = 'target parse error' |
| 526 | global_values['use_current_buffer'] = bool( | 550 | global_values['use_current_buffer'] = bool( |
| 527 | config_dict['irc_client'].get( | 551 | config_dict['irc_client'].get('use_current_buffer', False) |
| 528 | 'use_current_buffer', False)) | 552 | ) |
| 529 | if config_dict.get('config_version', | 553 | if ( |
| 530 | 0) != BEINC_CURRENT_CONFIG_VERSION: | 554 | config_dict.get('config_version', 0) |
| 531 | beinc_prnt('WARNING: The version of the config-file: {0} ({1}) ' | 555 | != BEINC_CURRENT_CONFIG_VERSION |
| 532 | 'does not correspond to the latest version supported ' | 556 | ): |
| 533 | 'by this program ({2})\nCheck beinc_config_sample.json ' | 557 | beinc_prnt( |
| 534 | 'for the newest features!'.format( | 558 | "WARNING: The version of the config-file: " |
| 535 | beinc_config_file_str, | 559 | f"{beinc_config_file_str} " |
| 536 | config_dict.get('config_version', 0), | 560 | f"({config_dict.get('config_version', 0)}) " |
| 537 | BEINC_CURRENT_CONFIG_VERSION)) | 561 | "does not correspond to the latest version supported " |
| 562 | f"by this program ({BEINC_CURRENT_CONFIG_VERSION})\n" | ||
| 563 | "Check beinc_config_sample.json for the newest features!" | ||
| 564 | ) | ||
| 538 | for target in config_dict['irc_client']['targets']: | 565 | for target in config_dict['irc_client']['targets']: |
| 539 | try: | 566 | try: |
| 540 | new_target = WeechatTarget(target) | 567 | new_target = WeechatTarget(target) |
| @@ -551,8 +578,10 @@ def beinc_init(): | |||
| 551 | beinc_prnt(f'BEINC target "{new_target.name}" added') | 578 | beinc_prnt(f'BEINC target "{new_target.name}" added') |
| 552 | beinc_prnt('Done!') | 579 | beinc_prnt('Done!') |
| 553 | except Exception as e: | 580 | except Exception as e: |
| 554 | beinc_prnt(f'ERROR: unable to parse {beinc_config_file_str}: ' | 581 | beinc_prnt( |
| 555 | f'{custom_error} - {e}\nBEINC is now disabled') | 582 | f'ERROR: unable to parse {beinc_config_file_str}: ' |
| 583 | f'{custom_error} - {e}\nBEINC is now disabled' | ||
| 584 | ) | ||
| 556 | enabled = False | 585 | enabled = False |
| 557 | # do not return error / exit the script | 586 | # do not return error / exit the script |
| 558 | # in order to give a smoother opportunity to fix a 'broken' config | 587 | # in order to give a smoother opportunity to fix a 'broken' config |
| @@ -567,19 +596,24 @@ weechat.register( | |||
| 567 | __license__, | 596 | __license__, |
| 568 | 'Blackmore\'s Extended IRC Notification Collection (Weechat Client)', | 597 | 'Blackmore\'s Extended IRC Notification Collection (Weechat Client)', |
| 569 | '', | 598 | '', |
| 570 | '') | 599 | '', |
| 600 | ) | ||
| 571 | version = weechat.info_get('version_number', '') or 0 | 601 | version = weechat.info_get('version_number', '') or 0 |
| 572 | if int(version) < 0x00040000: | 602 | if int(version) < 0x00040000: |
| 573 | weechat.prnt('', 'WeeChat version >= 0.4.0 is required to run beinc') | 603 | weechat.prnt('', 'WeeChat version >= 0.4.0 is required to run beinc') |
| 574 | else: | 604 | else: |
| 575 | weechat.hook_command('beinc', | 605 | weechat.hook_command( |
| 576 | 'BEINC command', ('< broadcast <message> | on | off |' | 606 | 'beinc', |
| 577 | ' reload | target <action> >'), | 607 | 'BEINC command', |
| 578 | ('Available target actions:\n' | 608 | '< broadcast <message> | on | off | reload | target <action> >', |
| 579 | 'disable <target name>\nenable <target name>\nlist'), | 609 | ( |
| 580 | 'None', | 610 | 'Available target actions:\n' |
| 581 | 'beinc_command', | 611 | 'disable <target name>\nenable <target name>\nlist' |
| 582 | '') | 612 | ), |
| 613 | 'None', | ||
| 614 | 'beinc_command', | ||
| 615 | '', | ||
| 616 | ) | ||
| 583 | weechat.hook_signal('*,irc_in2_privmsg', 'beinc_privmsg_handler', '') | 617 | weechat.hook_signal('*,irc_in2_privmsg', 'beinc_privmsg_handler', '') |
| 584 | beinc_init() | 618 | beinc_init() |
| 585 | weechat.prnt('', 'beinc initiated!') | 619 | weechat.prnt('', 'beinc initiated!') |
