summaryrefslogtreecommitdiff
path: root/beinc_server.py
diff options
context:
space:
mode:
authorSimeon Simeonov2014-05-07 22:28:48 +0200
committerSimeon Simeonov2014-05-07 22:28:48 +0200
commit60f47b04174d016cc86c6e06fdaf0794c3d14216 (patch)
treeb8137a37b8e4b81202db5943b509652c7f9564b5 /beinc_server.py
parent833ddeb822493f6ab2abd6f193b4c0bc8ea76854 (diff)
Git server / generic client and weechat client completed
Diffstat (limited to 'beinc_server.py')
-rwxr-xr-xbeinc_server.py148
1 files changed, 77 insertions, 71 deletions
diff --git a/beinc_server.py b/beinc_server.py
index 8687da3..d4dd3c3 100755
--- a/beinc_server.py
+++ b/beinc_server.py
@@ -1,18 +1,42 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2# -*- coding: utf-8 -*- 2# -*- coding: utf-8 -*-
3 3
4# Blackmore's Enhanced IRC-Notification Collection (BEINC) v1.0
5# Copyright (C) 2013-2014 Simeon Simeonov
6
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
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
4import argparse 21import argparse
22import errno
5import getpass 23import getpass
6import json 24import json
7import os 25import os
26import random
8import sys 27import sys
9 28
10import cherrypy 29import cherrypy
11 30
31try:
32 import pynotify
33except ImportError as e:
34 pynotify = None
35
12 36
13__author__ = 'Simeon Simeonov' 37__author__ = 'Simeon Simeonov'
14__version__ = '1.0-beta' 38__version__ = '1.0'
15__license__ = "GPL3" 39__license__ = 'GPL3'
16 40
17 41
18BEINC_OSD_TYPE_NONE = 0 42BEINC_OSD_TYPE_NONE = 0
@@ -33,40 +57,35 @@ class BEINCInstance(object):
33 self.__osd_type = BEINC_OSD_TYPE_NONE 57 self.__osd_type = BEINC_OSD_TYPE_NONE
34 self.__osd_notification = None 58 self.__osd_notification = None
35 59
36 try: 60 self.__name = instance_dict.get('name')
37 self.__name = instance_dict['name'] 61 self.__password = instance_dict.get('password', '')
38 self.__password = instance_dict['password'] 62 self.__queue_size = int(instance_dict.get('queue_size', 3))
39 self.__queue_size = int(instance_dict['queue_size'])
40
41 except Exception as e:
42 sys.stderr.write(
43 'Instance processing error {0}:\n{1}\n'.format(self.__name,
44 e))
45 sys.exit(1)
46 63
47 if instance_dict['osd_system'].lower() == 'pynotify': 64 if instance_dict['osd_system'].lower() == 'pynotify':
65 self.__queue_size = 0 # disable queueing
48 if not pynotify: 66 if not pynotify:
49 sys.stderr.write( 67 sys.stderr.write(
50 'This server does not possess pynotify capability\n') 68 'This server does not possess pynotify capability\n')
51 sys.stderr.write( 69 sys.stderr.write(
52 'Remove the instance {0}'.format(self.__name)) 70 'Remove the instance {0}'.format(self.__name))
53 sys.stderr.write("or define it with 'osd_system': 'none'\n") 71 sys.stderr.write("or define it with 'osd_system': 'none'\n")
54 sys.exit(1) 72 sys.exit(errno.EPERM)
55 73
56 try: 74 try:
57 self.__osd_notification = pynotify.Notification(' ') 75 self.__osd_notification = pynotify.Notification(' ')
58 self.__osd_notification.set_timeout( 76 self.__osd_notification.set_timeout(
59 instance_dict['osd_timeout']) 77 int(instance_dict.get('osd_timeout', 5000)))
60 self.__osd_notification.set_property( 78 self.__osd_notification.set_property(
61 'app_name', 79 'app_name',
62 '{0} {1}'.format(sys.argv[0], __version__)) 80 '{0} {1}'.format(sys.argv[0], __version__))
63 except Exception as e: 81 except Exception as e:
64 sys.stderr.write( 82 sys.stderr.write(
65 'Unable to set up a notification object for {0} ({1})\n') 83 'Unable to set up a notification object for {0} ({1})\n')
66 sys.exit(1) 84 sys.exit(errno.EPERM)
67 85
68 self.__osd_type = BEINC_OSD_TYPE_PYNOTIFY 86 self.__osd_type = BEINC_OSD_TYPE_PYNOTIFY
69 87
88
70 @property 89 @property
71 def name(self): 90 def name(self):
72 """ 91 """
@@ -129,34 +148,25 @@ def beinc_instance_login(method):
129 """ 148 """
130 decorator for checking login credentials 149 decorator for checking login credentials
131 """ 150 """
132 from functools import wraps
133 151
134 @wraps(method) 152 def wrapper(self, *args, **kwargs):
135 def tmp_func(self, *args, **kwargs):
136 153
137 if not args: 154 if not args:
138 raise cherrypy.HTTPError(400) 155 raise cherrypy.HTTPError(status = 404)
139
140 print('args: {0}'.format(args))
141 print('kwargs: {0}'.format(kwargs))
142 print(cherrypy.request.config)
143 print('args[0]: {0} ({1})'.format(args[0], str(type(args[0]))))
144 print('instances: {0}'.format(str(self.__instances)))
145 156
146 try: 157 try:
147 instance = self.__instances[args[0]] 158 instance = self.instances[args[0]]
148 except Exception as e: 159 except Exception as e:
149 sys.stderr.write('Wrong instance or password: {0}\n'.format(e)) 160 raise cherrypy.HTTPError(status = 401,
150 raise cherrypy.HTTPError('403 Forbidden', 161 message = 'Wrong instance or password')
151 'Wrong instance or password')
152 162
153 if not instance.password_match(kwargs.get('password')): 163 if not instance.password_match(kwargs.get('password')):
154 raise cherrypy.HTTPError('403 Forbidden', 164 raise cherrypy.HTTPError(status = 401,
155 'Wrong instance or password') 165 message = 'Wrong instance or password')
156 166
157 return method(self, *args, **kwargs) 167 return method(self, *args, **kwargs)
158 168
159 return tmp_func 169 return wrapper
160 170
161 171
162class WebNotifyServer(object): 172class WebNotifyServer(object):
@@ -167,15 +177,32 @@ class WebNotifyServer(object):
167 self.__config = config 177 self.__config = config
168 self.__instances = dict() 178 self.__instances = dict()
169 179
180 # initialize pynotify if the module exists and if needed
181 if pynotify:
182 for instance in self.__config['server']['instances']:
183 # check if we have at least one instance that uses pynotify
184 # before initializing it
185 if instance.get('osd_system', '').lower() == 'pynotify':
186 if not pynotify.init('BEINC Notify'):
187 sys.stderr.write('pynotify.init failed! Exiting...\n')
188 sys.exit(1)
189 break
170 try: 190 try:
171 for instance in self.__config['server']['instances']: 191 for instance in self.__config['server']['instances']:
172 self.__instances[instance['name']] = BEINCInstance(instance) 192 self.__instances[instance['name']] = BEINCInstance(instance)
173 print('Instance "{0}" added'.format(instance['name'])) 193 print('Instance "{0}" added'.format(instance['name']))
174 194
175 except Exception as e: 195 except Exception as e:
176 sys.stderr.write('Unable to initialize queues: {0}\n'.format(e)) 196 sys.stderr.write('Unable to create instance "{0}": {1}\n'.format(
197 instance['name'],
198 e))
177 sys.exit(1) 199 sys.exit(1)
178 200
201
202 @property
203 def instances(self):
204 return self.__instances
205
179 @cherrypy.expose 206 @cherrypy.expose
180 def index(self): 207 def index(self):
181 """ 208 """
@@ -190,33 +217,14 @@ class WebNotifyServer(object):
190 """ 217 """
191 return 'default' 218 return 'default'
192 219
220
193 @cherrypy.expose 221 @cherrypy.expose
222 @beinc_instance_login
194 def push(self, *args, **kwargs): 223 def push(self, *args, **kwargs):
195 print('push called')
196
197 if not args:
198 raise cherrypy.HTTPError(400)
199
200 # print('args: {0}'.format(args))
201 # print('kwargs: {0}'.format(unicode(kwargs)))
202 # print(cherrypy.request.config)
203 # print('args[0]: {0} ({1})'.format(args[0], str(type(args[0]))))
204 # print('instances: {0}'.format(str(self.__instances)))
205
206 try:
207 instance = self.__instances[args[0]]
208 except Exception as e:
209 sys.stderr.write('Wrong instance or password\n')
210 #print('DEBUG: {0}'.format(e))
211 raise cherrypy.HTTPError('403 Forbidden',
212 'Wrong instance or password')
213 224
214 if not instance.password_match(kwargs.get('password')): 225 instance = self.__instances[args[0]]
215 sys.stderr.write('Wrong instance or password\n')
216 raise cherrypy.HTTPError('403 Forbidden',
217 'Wrong instance or password')
218 226
219# instance = self.__instances[args[0]] 227 print('**kwargs: {0}'.format(str(kwargs)))
220 title = kwargs.get('title', '') 228 title = kwargs.get('title', '')
221 message = kwargs.get('message', '') 229 message = kwargs.get('message', '')
222 try: 230 try:
@@ -229,12 +237,19 @@ class WebNotifyServer(object):
229 e)) 237 e))
230 raise cherrypy.HTTPError(500, 'Unable to send message') 238 raise cherrypy.HTTPError(500, 'Unable to send message')
231 239
240
232 @cherrypy.expose 241 @cherrypy.expose
233 @beinc_instance_login 242 @beinc_instance_login
234 def pull(self, *args, **kwargs): 243 def pull(self, *args, **kwargs):
235 244
236 instance = self.__instances(args[0]) 245 instance = self.__instances[args[0]]
237 return 'OK' 246 if not instance.queueable:
247 raise cherrypy.HTTPError(
248 status = 405,
249 message = 'BEINC instance "{0}" does not support queuing'.format(
250 instance.name))
251
252 return instance.get_queue()
238 253
239 254
240def main(): 255def main():
@@ -283,7 +298,7 @@ def main():
283 except Exception as e: 298 except Exception as e:
284 sys.stderr.write('Unable to parse {0}: {1}'.format(args.config_file, 299 sys.stderr.write('Unable to parse {0}: {1}'.format(args.config_file,
285 e)) 300 e))
286 sys.exit(1) 301 sys.exit(errno.EIO)
287 302
288 cherrypy.config.update({ 303 cherrypy.config.update({
289 'server.socket_host': args.hostname, 304 'server.socket_host': args.hostname,
@@ -292,20 +307,11 @@ def main():
292 'server.ssl_certificate': config_dict['server']['general']['ssl_certificate'], 307 'server.ssl_certificate': config_dict['server']['general']['ssl_certificate'],
293 'server.ssl_private_key': config_dict['server']['general']['ssl_private_key'], 308 'server.ssl_private_key': config_dict['server']['general']['ssl_private_key'],
294 'tools.encode.on': True, 309 'tools.encode.on': True,
295 'tools.encode.encoding': 'utf-8' 310 'tools.encode.encoding': 'utf-8',
311 'tools.log_tracebacks.on': False,
312 'request.show_tracebacks': False
296 }) 313 })
297 314
298 global pynotify
299 try:
300 import pynotify
301 if not pynotify.init('BEINC Notify'):
302 sys.stderr.write('pynotify.init failed! Exiting...\n')
303 sys.exit(1)
304 except Exception as e:
305 sys.stderr.write(
306 'Notice: pynotify support unavailable ({0})\n'.format(e))
307 pynotify = False
308
309 try: 315 try:
310 cherrypy.quickstart(WebNotifyServer(config_dict)) 316 cherrypy.quickstart(WebNotifyServer(config_dict))
311 317