summaryrefslogtreecommitdiff
path: root/beinc_pull.py
diff options
context:
space:
mode:
Diffstat (limited to 'beinc_pull.py')
-rwxr-xr-xbeinc_pull.py110
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):
159def main(inargs=None): 164def 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