diff options
Diffstat (limited to 'beinc_pull.py')
| -rwxr-xr-x | beinc_pull.py | 110 |
1 files changed, 66 insertions, 44 deletions
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 | ||
