From 60f47b04174d016cc86c6e06fdaf0794c3d14216 Mon Sep 17 00:00:00 2001
From: Simeon Simeonov
Date: Wed, 7 May 2014 22:28:48 +0200
Subject: Git server / generic client and weechat client completed
---
beinc_generic_client.py | 158 ++++++++++++++++++++++
beinc_server.json | 25 ++--
beinc_server.py | 148 +++++++++++----------
beinc_weechat.py | 331 +++++++++++++++++++++++++++++++++++++----------
bosd.py | 101 ---------------
bpynotify_orm.py | 32 -----
socket_server.py | 77 -----------
web_server.py | 47 -------
weechat_notify.py | 49 -------
weechat_notify_server.py | 116 -----------------
10 files changed, 509 insertions(+), 575 deletions(-)
create mode 100755 beinc_generic_client.py
delete mode 100644 bosd.py
delete mode 100644 bpynotify_orm.py
delete mode 100755 socket_server.py
delete mode 100755 web_server.py
delete mode 100755 weechat_notify.py
delete mode 100755 weechat_notify_server.py
diff --git a/beinc_generic_client.py b/beinc_generic_client.py
new file mode 100755
index 0000000..6cffc84
--- /dev/null
+++ b/beinc_generic_client.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Blackmore's Enhanced IRC-Notification Collection (BEINC) v1.0
+# Copyright (C) 2013-2014 Simeon Simeonov
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
+import argparse
+import errno
+import getpass
+import httplib
+import socket
+import ssl
+import sys
+import urllib
+import urllib2
+
+
+__author__ = 'Simeon Simeonov'
+__version__ = '1.0'
+__license__ = 'GPL3'
+
+
+class ValidHTTPSConnection(httplib.HTTPConnection):
+ """
+ Implements a simple CERT verification functionality
+ """
+
+ default_port = httplib.HTTPS_PORT
+
+ def __init__(self, *args, **kwargs):
+ httplib.HTTPConnection.__init__(self, *args, **kwargs)
+
+ def connect(self):
+ sock = socket.create_connection((self.host, self.port),
+ self.timeout, self.source_address)
+ if self._tunnel_host:
+ self.sock = sock
+ self._tunnel()
+ self.sock = ssl.wrap_socket(sock,
+ ca_certs=global_beinc_cert_file,
+ cert_reqs=ssl.CERT_REQUIRED)
+
+
+
+class ValidHTTPSHandler(urllib2.HTTPSHandler):
+ """
+ Implements a simple CERT verification functionality
+ """
+
+ def https_open(self, req):
+ return self.do_open(ValidHTTPSConnection, req)
+
+
+
+def action_push(args):
+ """
+ """
+ try:
+ post_values = {'title': args.title,
+ 'message': args.message,
+ 'password': args.password}
+ data = urllib.urlencode(post_values)
+ req = urllib2.Request(args.url, data)
+ if args.cert: # check for cert validity
+ global global_beinc_cert_file # ugly hack
+ global_beinc_cert_file = args.cert
+ opener = urllib2.build_opener(ValidHTTPSHandler)
+ response = opener.open(req)
+ else: # ... or don't
+ response = urllib2.urlopen(req)
+ res_code = response.code
+ if res_code == 200:
+ print('Server responded: OK')
+ else:
+ print('Server responded: {0}'.format(res_code))
+ print('Body:\n{0}'.format(response.read()))
+ response.close()
+ except urllib2.HTTPError as e:
+ sys.stderr.write('BEINC-server error ({0} - {1})\n'.format(e.code, e.reason))
+ except Exception as e:
+ sys.stderr.write('BEINC generic client error: {0}\n'.format(e))
+ sys.exit(errno.EPERM)
+
+
+def main():
+
+ parser = argparse.ArgumentParser(
+ description='The following options are available')
+
+ parser.add_argument('url',
+ metavar='URL',
+ type=str,
+ #dest='url',
+ #required=True,
+ help='Destination URL')
+
+ parser.add_argument('-c', '--cert-file',
+ metavar='FILE',
+ type=str,
+ dest='cert',
+ default='',
+ help='BEINC CA-cert to check the server-cert against')
+
+ parser.add_argument('-m', '--message',
+ metavar='MESSAGE',
+ type=str,
+ dest='message',
+ default='BEINC message',
+ help='BEINC message')
+
+ parser.add_argument('-p', '--password',
+ metavar='PASSWORD',
+ type=str,
+ dest='password',
+ default='',
+ help='Password')
+
+ parser.add_argument('-t', '--title',
+ metavar='TITLE',
+ type=str,
+ dest='title',
+ default='BEINC title',
+ help='BEINC title')
+
+ parser.add_argument('-v', '--version',
+ action='version',
+ version='%(prog)s {0}'.format(__version__),
+ help='display program-version and exit')
+
+ args = parser.parse_args()
+
+ if not args.password:
+ try:
+ args.password = getpass.getpass()
+ except Exception as e:
+ sys.stderr.write('Prompt terminated\n')
+ sys.exit(errno.EACCES)
+
+ action_push(args)
+ sys.exit(0)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/beinc_server.json b/beinc_server.json
index 2824dea..46674ed 100644
--- a/beinc_server.json
+++ b/beinc_server.json
@@ -18,27 +18,30 @@
},
"irc_client": {
+ "use_current_buffer": 0,
"targets": [
{
"name": "weechat_main",
- "target_url": "",
+ "target_url": "https://10.0.0.2:9898/push/secondtest",
"target_password": "changeme",
"target_cert_file": "",
"target_timestamp_format": "%H:%M:%S",
- "pm_title_template": "",
- "pm_message_template": "",
- "cm_title_template": "",
- "cm_message_template": "",
- "nm_title_template": "",
- "nm_message_template": "",
+ "pm_title_template": "%s @ %S",
+ "pm_message_template": "%m",
+ "cm_title_template": "%c @ %S",
+ "cm_message_template": "%s -> %m",
+ "nm_title_template": "%c @ %S",
+ "nm_message_template": "%s -> %m",
"channel_list": ["RedpillLinpro.#python",
- "Exile.#hin",
+ "Exile.#test",
"RedpillLinpro.#adult",
"Exile.#pichove"],
"nick_list": ["Exile.Blackmore"],
- "channel_messages_policy": 0,
- "private_messages_policy": 0,
- "notifications_policy": 0
+ "channel_messages_policy": 2,
+ "private_messages_policy": 1,
+ "notifications_policy": 1,
+ "debug": 1,
+ "enabled": 1
}
]
},
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 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+# Blackmore's Enhanced IRC-Notification Collection (BEINC) v1.0
+# Copyright (C) 2013-2014 Simeon Simeonov
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
import argparse
+import errno
import getpass
import json
import os
+import random
import sys
import cherrypy
+try:
+ import pynotify
+except ImportError as e:
+ pynotify = None
+
__author__ = 'Simeon Simeonov'
-__version__ = '1.0-beta'
-__license__ = "GPL3"
+__version__ = '1.0'
+__license__ = 'GPL3'
BEINC_OSD_TYPE_NONE = 0
@@ -33,40 +57,35 @@ class BEINCInstance(object):
self.__osd_type = BEINC_OSD_TYPE_NONE
self.__osd_notification = None
- try:
- self.__name = instance_dict['name']
- self.__password = instance_dict['password']
- self.__queue_size = int(instance_dict['queue_size'])
-
- except Exception as e:
- sys.stderr.write(
- 'Instance processing error {0}:\n{1}\n'.format(self.__name,
- e))
- sys.exit(1)
+ self.__name = instance_dict.get('name')
+ self.__password = instance_dict.get('password', '')
+ self.__queue_size = int(instance_dict.get('queue_size', 3))
if instance_dict['osd_system'].lower() == 'pynotify':
+ self.__queue_size = 0 # disable queueing
if not pynotify:
sys.stderr.write(
'This server does not possess pynotify capability\n')
sys.stderr.write(
'Remove the instance {0}'.format(self.__name))
sys.stderr.write("or define it with 'osd_system': 'none'\n")
- sys.exit(1)
+ sys.exit(errno.EPERM)
try:
self.__osd_notification = pynotify.Notification(' ')
self.__osd_notification.set_timeout(
- instance_dict['osd_timeout'])
+ int(instance_dict.get('osd_timeout', 5000)))
self.__osd_notification.set_property(
'app_name',
'{0} {1}'.format(sys.argv[0], __version__))
except Exception as e:
sys.stderr.write(
'Unable to set up a notification object for {0} ({1})\n')
- sys.exit(1)
+ sys.exit(errno.EPERM)
self.__osd_type = BEINC_OSD_TYPE_PYNOTIFY
+
@property
def name(self):
"""
@@ -129,34 +148,25 @@ def beinc_instance_login(method):
"""
decorator for checking login credentials
"""
- from functools import wraps
- @wraps(method)
- def tmp_func(self, *args, **kwargs):
+ def wrapper(self, *args, **kwargs):
if not args:
- raise cherrypy.HTTPError(400)
-
- print('args: {0}'.format(args))
- print('kwargs: {0}'.format(kwargs))
- print(cherrypy.request.config)
- print('args[0]: {0} ({1})'.format(args[0], str(type(args[0]))))
- print('instances: {0}'.format(str(self.__instances)))
+ raise cherrypy.HTTPError(status = 404)
try:
- instance = self.__instances[args[0]]
+ instance = self.instances[args[0]]
except Exception as e:
- sys.stderr.write('Wrong instance or password: {0}\n'.format(e))
- raise cherrypy.HTTPError('403 Forbidden',
- 'Wrong instance or password')
+ raise cherrypy.HTTPError(status = 401,
+ message = 'Wrong instance or password')
if not instance.password_match(kwargs.get('password')):
- raise cherrypy.HTTPError('403 Forbidden',
- 'Wrong instance or password')
+ raise cherrypy.HTTPError(status = 401,
+ message = 'Wrong instance or password')
return method(self, *args, **kwargs)
- return tmp_func
+ return wrapper
class WebNotifyServer(object):
@@ -167,15 +177,32 @@ class WebNotifyServer(object):
self.__config = config
self.__instances = dict()
+ # initialize pynotify if the module exists and if needed
+ if pynotify:
+ for instance in self.__config['server']['instances']:
+ # check if we have at least one instance that uses pynotify
+ # before initializing it
+ if instance.get('osd_system', '').lower() == 'pynotify':
+ if not pynotify.init('BEINC Notify'):
+ sys.stderr.write('pynotify.init failed! Exiting...\n')
+ sys.exit(1)
+ break
try:
for instance in self.__config['server']['instances']:
self.__instances[instance['name']] = BEINCInstance(instance)
print('Instance "{0}" added'.format(instance['name']))
except Exception as e:
- sys.stderr.write('Unable to initialize queues: {0}\n'.format(e))
+ sys.stderr.write('Unable to create instance "{0}": {1}\n'.format(
+ instance['name'],
+ e))
sys.exit(1)
+
+ @property
+ def instances(self):
+ return self.__instances
+
@cherrypy.expose
def index(self):
"""
@@ -190,33 +217,14 @@ class WebNotifyServer(object):
"""
return 'default'
+
@cherrypy.expose
+ @beinc_instance_login
def push(self, *args, **kwargs):
- print('push called')
-
- if not args:
- raise cherrypy.HTTPError(400)
-
- # print('args: {0}'.format(args))
- # print('kwargs: {0}'.format(unicode(kwargs)))
- # print(cherrypy.request.config)
- # print('args[0]: {0} ({1})'.format(args[0], str(type(args[0]))))
- # print('instances: {0}'.format(str(self.__instances)))
-
- try:
- instance = self.__instances[args[0]]
- except Exception as e:
- sys.stderr.write('Wrong instance or password\n')
- #print('DEBUG: {0}'.format(e))
- raise cherrypy.HTTPError('403 Forbidden',
- 'Wrong instance or password')
- if not instance.password_match(kwargs.get('password')):
- sys.stderr.write('Wrong instance or password\n')
- raise cherrypy.HTTPError('403 Forbidden',
- 'Wrong instance or password')
+ instance = self.__instances[args[0]]
-# instance = self.__instances[args[0]]
+ print('**kwargs: {0}'.format(str(kwargs)))
title = kwargs.get('title', '')
message = kwargs.get('message', '')
try:
@@ -229,12 +237,19 @@ class WebNotifyServer(object):
e))
raise cherrypy.HTTPError(500, 'Unable to send message')
+
@cherrypy.expose
@beinc_instance_login
def pull(self, *args, **kwargs):
- instance = self.__instances(args[0])
- return 'OK'
+ instance = self.__instances[args[0]]
+ if not instance.queueable:
+ raise cherrypy.HTTPError(
+ status = 405,
+ message = 'BEINC instance "{0}" does not support queuing'.format(
+ instance.name))
+
+ return instance.get_queue()
def main():
@@ -283,7 +298,7 @@ def main():
except Exception as e:
sys.stderr.write('Unable to parse {0}: {1}'.format(args.config_file,
e))
- sys.exit(1)
+ sys.exit(errno.EIO)
cherrypy.config.update({
'server.socket_host': args.hostname,
@@ -292,20 +307,11 @@ def main():
'server.ssl_certificate': config_dict['server']['general']['ssl_certificate'],
'server.ssl_private_key': config_dict['server']['general']['ssl_private_key'],
'tools.encode.on': True,
- 'tools.encode.encoding': 'utf-8'
+ 'tools.encode.encoding': 'utf-8',
+ 'tools.log_tracebacks.on': False,
+ 'request.show_tracebacks': False
})
- global pynotify
- try:
- import pynotify
- if not pynotify.init('BEINC Notify'):
- sys.stderr.write('pynotify.init failed! Exiting...\n')
- sys.exit(1)
- except Exception as e:
- sys.stderr.write(
- 'Notice: pynotify support unavailable ({0})\n'.format(e))
- pynotify = False
-
try:
cherrypy.quickstart(WebNotifyServer(config_dict))
diff --git a/beinc_weechat.py b/beinc_weechat.py
index 689f450..8b4392f 100644
--- a/beinc_weechat.py
+++ b/beinc_weechat.py
@@ -1,6 +1,23 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+# Blackmore's Enhanced IRC-Notification Collection (BEINC) v1.0
+# Copyright (C) 2013-2014 Simeon Simeonov
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
import datetime
import httplib
import json
@@ -14,6 +31,12 @@ import urllib2
import weechat
+
+__author__ = 'Simeon Simeonov'
+__version__ = '1.0'
+__license__ = 'GPL3'
+
+
enabled = True
global_values = dict()
@@ -26,14 +49,13 @@ BEINC_POLICY_LIST_ONLY = 2
class ValidHTTPSConnection(httplib.HTTPConnection):
"""
+ Implements a simple CERT verification functionality
"""
default_port = httplib.HTTPS_PORT
- def __init__(self, cert_file, *args, **kwargs):
+ def __init__(self, *args, **kwargs):
httplib.HTTPConnection.__init__(self, *args, **kwargs)
- self.__cert_file = cert_file
-
def connect(self):
sock = socket.create_connection((self.host, self.port),
@@ -42,19 +64,18 @@ class ValidHTTPSConnection(httplib.HTTPConnection):
self.sock = sock
self._tunnel()
self.sock = ssl.wrap_socket(sock,
- ca_certs=self.__cert_file,
+ ca_certs=global_beinc_cert_file,
cert_reqs=ssl.CERT_REQUIRED)
class ValidHTTPSHandler(urllib2.HTTPSHandler):
-
- def __init__(self, cert_file, *args, **kwargs):
- urllib2.HTTPSHandler.__init__(self, *args, **kwargs)
- self.__cert_file = cert_file
+ """
+ Implements a simple CERT verification functionality
+ """
def https_open(self, req):
- return self.do_open(ValidHTTPSConnection(self.__cert_file), req)
+ return self.do_open(ValidHTTPSConnection, req)
@@ -101,6 +122,8 @@ class WeechatTarget(object):
self.__cert_file = target_dict.get('target_cert_file')
self.__timestamp_format = target_dict.get('target_timestamp_format',
'%H:%M:%S')
+ self.__debug = bool(target_dict.get('debug', False))
+ self.__enabled = bool(target_dict.get('enabled', True))
@property
@@ -144,48 +167,117 @@ class WeechatTarget(object):
"""
return self.__notifications_policy
-
+
+ @property
+ def enabled(self):
+ """
+ """
+ return self.__enabled
+
+ @enabled.setter
+ def enabled(self, value):
+ """
+ """
+ self.__enabled = value
+
+
def __repr__(self):
"""
"""
-
- return 'name: {0}\nurl: {1}\nchannel_list: {2}\nnick_list: {3}'\
- 'channel_messages_policy: {4}\nprivate_messages_policy: {5}'\
- 'notifications_policy: {6}'.format(self.__name,
- self.__url,
- ', '.join(self.__chans),
- ', '.join(self.__nicks),
- self.__chan_message_policy,
- self.__priv_message_policy,
- self.__notifications_policy)
-
-
- def send_private_message_notification(self, message, values):
+ return 'name: {0}\nurl: {1}\nchannel_list: {2}\nnick_list: {3}\n'\
+ 'channel_messages_policy: {4}\nprivate_messages_policy: {5}\n'\
+ 'notifications_policy: {6}\nenabled: {7}\n\n'.format(
+ self.__name,
+ self.__url,
+ ', '.join(self.__chans),
+ ', '.join(self.__nicks),
+ self.__chan_messages_policy,
+ self.__priv_messages_policy,
+ self.__notifications_policy,
+ 'yes' if self.__enabled else 'no')
+
+
+ def send_private_message_notification(self, values):
"""
"""
- pass
+ try:
+ title_str = self.__fetch_formatted_str(self.__pm_title_template,
+ values)
+ message_str = self.__fetch_formatted_str(self.__pm_message_template,
+ values)
+ post_values = {'title': title_str,
+ 'message': message_str,
+ 'password': self.__password}
+ data = urllib.urlencode(post_values)
+ if self.__send_beinc_message(data) and self.__debug:
+ beinc_prnt(
+ 'BEINC DEBUG: send_private_message_notification-ERROR '
+ 'for "{0}": __send_beinc_message -> False'.format(
+ self.__name))
+ except Exception as e:
+ if self.__debug:
+ beinc_prnt(
+ 'BEINC DEBUG: send_private_message_notification-ERROR '
+ 'for "{0}": {1}'.format(self.__name, e))
- def send_channel_message_notification(self, message, values):
+ def send_channel_message_notification(self, values):
"""
"""
- pass
+ try:
+ title_str = self.__fetch_formatted_str(self.__cm_title_template,
+ values)
+ message_str = self.__fetch_formatted_str(self.__cm_message_template,
+ values)
+ post_values = {'title': title_str,
+ 'message': message_str,
+ 'password': self.__password}
+ data = urllib.urlencode(post_values)
+ if self.__send_beinc_message(data) and self.__debug:
+ beinc_prnt(
+ 'BEINC DEBUG: send_channel_message_notification-ERROR '
+ 'for "{0}": __send_beinc_message -> False'.format(
+ self.__name))
+ except Exception as e:
+ if self.__debug:
+ beinc_prnt(
+ 'BEINC DEBUG: send_channel_message_notification-ERROR '
+ 'for "{0}": {1}'.format(self.__name, e))
-
- def send_notify_message_notification(self, message, values):
+
+ def send_notify_message_notification(self, values):
"""
"""
- pass
+ try:
+ title_str = self.__fetch_formatted_str(self.__nm_title_template,
+ values)
+ message_str = self.__fetch_formatted_str(self.__nm_message_template,
+ values)
+ post_values = {'title': title_str,
+ 'message': message_str,
+ 'password': self.__password}
+ data = urllib.urlencode(post_values)
+ if self.__send_beinc_message(data) and self.__debug:
+ beinc_prnt(
+ 'BEINC DEBUG: send_notify_message_notification-ERROR '
+ 'for "{0}": __send_beinc_message -> False'.format(
+ self.__name))
+ except Exception as e:
+ if self.__debug:
+ beinc_prnt(
+ 'BEINC DEBUG: send_notify_message_notification-ERROR '
+ 'for "{0}": {1}'.format(self.__name, e))
def __fetch_formatted_str(self, template, values):
"""
"""
+ timestamp = datetime.datetime.now().strftime(self.__timestamp_format)
replacements = {'%S': values['server'],
'%s': values['source_nick'],
'%c': values['channel'],
'%m': values['message'],
- '%t': values['timestamp'],
+ '%t': timestamp,
'%p': 'BEINC',
'%n': values['own_nick']}
for key, value in replacements.items():
@@ -201,40 +293,100 @@ class WeechatTarget(object):
try:
req = urllib2.Request(self.__url, data)
- opener = urllib2.build_opener(ValidHTTPSHandler)
-
- response = opener.open(req)
+
+ if self.__cert_file:
+ opener = urllib2.build_opener(ValidHTTPSHandler)
+ response = opener.open(req)
+ else:
+ response = urllib2.urlopen(req)
res_code = response.code
response.close()
if res_code == 200:
return True
- except Exception as e:
- weechat.prnt(weechat.current_buffer(),
- 'DEBUG: send_beinc_message-ERROR: {0}'.format(e))
+ except urllib2.HTTPError as e:
+ if self.__debug:
+ beinc_prnt(
+ 'BEINC DEBUG: send_beinc_message-ERROR for "{0}": {1} ->'
+ ' ({2} - {3})'.format(self.__name, e.url, e.code, e.reason))
+ # all other exception should be handled by the caller
return False
-def beinc_send_message(message):
- weechat.prnt(weechat.current_buffer(), 'beinc message: {0}'.format(message))
+def beinc_prnt(message_str):
+ """
+ wrapper around weechat.prnt
+ """
+ if global_values['use_current_buffer']:
+ weechat.prnt(weechat.current_buffer(), message_str)
+ else:
+ weechat.prnt('', message_str)
+
+def beinc_cmd_target_handler(cmd_tokens):
+ """
+ handles: '/beinc target' command actions
+ """
+ if not cmd_tokens or cmd_tokens[0] not in ['list', 'enable', 'disable']:
+ beinc_prnt('beinc target [ list | enable | disable ]')
+ return weechat.WEECHAT_RC_OK
-def beinc_command(data, buffer, args):
+ if cmd_tokens[0] == 'list':
+ beinc_prnt('--- Targets ---')
+ for target in target_list:
+ beinc_prnt(str(target))
+ beinc_prnt('---------------')
+ elif cmd_tokens[0] == 'enable':
+ if not cmd_tokens[1:]:
+ beinc_prnt('missing a name-argument')
+ return weechat.WEECHAT_RC_OK
+ name = ' '.join(cmd_tokens[1:])
+ for target in target_list:
+ if target.name == name:
+ target.enabled = True
+ beinc_prnt('target "{0}" enabled'.format(name))
+ break
+ else:
+ beinc_prnt('no matching target for "{0}"'.format(name))
+ elif cmd_tokens[0] == 'disable':
+ if not cmd_tokens[1:]:
+ beinc_prnt('missing a name-argument')
+ return weechat.WEECHAT_RC_OK
+ name = ' '.join(cmd_tokens[1:])
+ for target in target_list:
+ if target.name == name:
+ target.enabled = False
+ beinc_prnt('target "{0}" disabled'.format(name))
+ break
+ else:
+ beinc_prnt('no matching target for "{0}"'.format(name))
+
+ return weechat.WEECHAT_RC_OK
+
+
+def beinc_command(data, buffer_obj, args):
global enabled
+ cmd_tokens = args.split()
+
+ if not cmd_tokens:
+ return weechat.WEECHAT_RC_OK
+
if args == 'on':
enabled = True
- weechat.prnt(weechat.current_buffer(), 'beinc on')
+ beinc_prnt('BEINC on')
elif args == 'off':
enabled = False
- weechat.prnt(weechat.current_buffer(), 'beinc off')
+ beinc_prnt('BEINC off')
elif args == 'reload':
- beinc_config_file_str = os.path.join(
- weechat.info_get('weechat_dir', ''),
- 'beinc.json')
- weechat.prnt(weechat.current_buffer(), '{0} reloaded'.format(
- beinc_config_file_str))
+ beinc_prnt('Reloading BEINC...')
+ beinc_init()
+ elif cmd_tokens[0] == 'target':
+ return beinc_cmd_target_handler(cmd_tokens[1:])
else:
- beinc_send_message(args)
+ beinc_prnt('data: {0}, cmd_tokens: {1}, args: {2}'.format(
+ str(data),
+ str(cmd_tokens),
+ str(args)))
return weechat.WEECHAT_RC_OK
@@ -249,40 +401,74 @@ def beinc_privmsg_handler(data, signal, signal_data):
# packing the privmsg handler values
ph_values = dict()
ph_values['server'] = signal.split(',')[0]
- ph_values['own_nick'] = weechat.info_get('irc_nick', server)
+ ph_values['own_nick'] = weechat.info_get('irc_nick', ph_values['server'])
ph_values['channel'] = prvmsg_dict['arguments'].split(':')[0].strip()
ph_values['source_nick'] = prvmsg_dict['nick']
ph_values['message'] = ':'.join(
prvmsg_dict['arguments'].split(':')[1:]).strip()
- ph_values['timestamp'] = datetime.datetime.now().strftime(
- self.__timestamp_format)
if ph_values['channel'] == ph_values['own_nick']:
# priv messages are handled here
- if not global_values['global_channel_messages_policy']:
+ if not global_values['global_private_messages_policy']:
+ return weechat.WEECHAT_RC_OK
+
+ if global_values['global_private_messages_policy'] == BEINC_POLICY_LIST_ONLY \
+ and '{0}.{1}'.format(
+ ph_values['server'],
+ ph_values['source_nick'].lower()) not in global_values['global_nicks']:
return weechat.WEECHAT_RC_OK
for target in target_list:
- if target.private_messages_policy == 1 or (
- target.private_messages_policy == 2 \
+ if not target.enabled:
+ continue
+ if target.private_messages_policy == BEINC_POLICY_ALL or (
+ target.private_messages_policy == BEINC_POLICY_LIST_ONLY \
and '{0}.{1}'.format(
ph_values['server'],
ph_values['source_nick'].lower()) in target.nicks):
- weechat.prnt(weechat.current_buffer(),
- 'DEBUG: priv message - {0}'.format(
- ph_values['message']))
+ target.send_private_message_notification(ph_values)
- elif privmsg_handler_values['own_nick'].lower() in ph_values['message'].lower():
+ elif ph_values['own_nick'].lower() in ph_values['message'].lower():
# notify messages are handled here
- weechat.prnt(weechat.current_buffer(),
- 'DEBUG: notify message - {0}'.format(ph_values['message']))
if not global_values['global_notifications_policy']:
return weechat.WEECHAT_RC_OK
+ if global_values['global_notifications_policy'] == BEINC_POLICY_LIST_ONLY \
+ and '{0}.{1}'.format(
+ ph_values['server'],
+ ph_values['channel'].lower()) not in global_values['global_chans']:
+ return weechat.WEECHAT_RC_OK
+
+ for target in target_list:
+ if not target.enabled:
+ continue
+ if target.notifications_policy == BEINC_POLICY_ALL or (
+ target.notifications_policy == BEINC_POLICY_LIST_ONLY \
+ and '{0}.{1}'.format(
+ ph_values['server'],
+ ph_values['channel'].lower()) in target.chans):
+ target.send_notify_message_notification(ph_values)
+
elif global_values['global_channel_messages_policy']:
# chan messages are handled here
- weechat.prnt(weechat.current_buffer(),
- 'DEBUG: chan message - {0}'.format(ph_values['message']))
+ if not global_values['global_notifications_policy']:
+ return weechat.WEECHAT_RC_OK
+
+ if global_values['global_channel_messages_policy'] == BEINC_POLICY_LIST_ONLY \
+ and '{0}.{1}'.format(
+ ph_values['server'],
+ ph_values['channel'].lower()) not in global_values['global_chans']:
+ return weechat.WEECHAT_RC_OK
+
+ for target in target_list:
+ if not target.enabled:
+ continue
+ if target.channel_messages_policy == BEINC_POLICY_ALL or (
+ target.channel_messages_policy == BEINC_POLICY_LIST_ONLY \
+ and '{0}.{1}'.format(
+ ph_values['server'],
+ ph_values['channel'].lower()) in target.chans):
+ target.send_channel_message_notification(ph_values)
return weechat.WEECHAT_RC_OK
@@ -293,33 +479,36 @@ def beinc_init():
global target_list
global global_values
+ # global chans/nicks sets are used to speed up the filtering
+ global_values = dict()
global_values['global_chans'] = set()
global_values['global_nicks'] = set()
- custom_error = ''
+ target_list = list()
+ custom_error = ''
global_values['global_channel_messages_policy'] = False
global_values['global_private_messages_policy'] = False
global_values['global_notifications_policy'] = False
-
+ global_values['use_current_buffer'] = False
+
try:
beinc_config_file_str = os.path.join(
weechat.info_get('weechat_dir', ''),
'beinc.json')
- weechat.prnt('', 'Parsing {0}...'.format(beinc_config_file_str))
+ beinc_prnt('Parsing {0}...'.format(beinc_config_file_str))
custom_error = 'load error'
with open(beinc_config_file_str, 'r') as fp:
config_dict = json.load(fp)
- # clear the target-list
- target_list = []
-
custom_error = 'target parse error'
+ global_values['use_current_buffer'] = bool(config_dict['irc_client'].get(
+ 'use_current_buffer', False))
for target in config_dict['irc_client']['targets']:
try:
new_target = WeechatTarget(target)
except Exception as e:
- weechat.prnt('', 'Unable to add target: {0}'.format(e))
+ beinc_prnt('Unable to add target: {0}'.format(e))
continue
global_values['global_chans'].update(new_target.chans)
global_values['global_nicks'].update(new_target.nicks)
@@ -331,12 +520,12 @@ def beinc_init():
global_values['global_notifications_policy'] = True
target_list.append(new_target)
- weechat.prnt('', 'BEINC target {0} added'.format(new_target.name))
+ beinc_prnt('BEINC target "{0}" added'.format(new_target.name))
- weechat.prnt('', 'Done!!!')
+ beinc_prnt('Done!')
except Exception as e:
- weechat.prnt('', 'ERROR: unable to parse {0}: {1} - {2}'.format(
+ beinc_prnt('ERROR: unable to parse {0}: {1} - {2}'.format(
beinc_config_file_str, custom_error, e))
enabled = False
diff --git a/bosd.py b/bosd.py
deleted file mode 100644
index d678754..0000000
--- a/bosd.py
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import urllib
-import urllib2
-
-import weechat
-
-#### CONFIG ####
-enabled = True
-
-notify_channels = [
- "RedpillLinpro.#python",
- "Exile.#hin",
- "RedpillLinpro.#adult",
- "Exile.#pichove"
- ]
-
-connections = [ {'bosd_url': 'https://127.0.0.1:9999/npush/',
- 'bosd_password': '1234'},
-
-# {'bosd_url': 'https://pichove.org:9999/npush/',
-# 'bosd_port': 9999,
-# 'bosd_password': 'foo'},
- ]
-################
-
-__VERSION__ = '2.0'
-
-def bosd_send_message(header='', message=''):
- for conn in connections:
- try:
- conn['nheader'] = header # notification header
- conn['nmessage'] = message # notification message
-
- data = urllib.urlencode(conn)
-
- req = urllib2.Request(url, data)
- urllib2.urlopen(req)
- #weechat.prnt("", message)
- except:
- continue
-
- return True
-
-
-def bosd_command(data, buffer, args):
- global enabled
- if args == 'on':
- enabled = True
- weechat.prnt(weechat.current_buffer(), "bosd on")
- elif args == 'off':
- enabled = False
- weechat.prnt(weechat.current_buffer(), "bosd off")
- else:
- bosd_send_message('BOSD generic', args)
-
- return weechat.WEECHAT_RC_OK
-
-
-def bosd_privmsg_handler(data, signal, signal_data):
- if not enabled:
- return weechat.WEECHAT_RC_OK
-
- prvmsg_dict = weechat.info_get_hashtable("irc_message_parse",
- { "message": signal_data })
-
-
- server = signal.split(",")[0]
-
- # channel = signal_data.split(":")[-1]
- # my_nick = weechat.info_get("irc_nick_from_host", signal_data)
-
- my_nick = weechat.info_get("irc_nick", server)
- channel = prvmsg_dict['arguments'].split(":")[0].strip()
- nick = prvmsg_dict['nick']
- message = ':'.join(prvmsg_dict['arguments'].split(':')[1:]).strip()
-
- if (my_nick in message) or ('{0}.{1}'.format(server,channel) in notify_channels):
- template_msg = '{0} @ {1} - {2}: {3}'.format(channel,
- server,
- nick,
- message)
- bosd_send_xosd_message(template_msg)
-
- if my_nick in channel:
- template_msg = '{0} @ {1}: {2}'.format(nick, server, message)
- bosd_send_xosd_message(template_msg)
-
- #my_str = "%s - %s - %s - %s" % (my_nick, server, channel, message)
- #weechat.prnt("", my_str)
-
- return weechat.WEECHAT_RC_OK
-
-
-
-weechat.register('bosd', 'Simeon Simeonov', '1.0', 'GPL3', 'Socket notification script', "", "")
-weechat.hook_command("bosd", "bosd on off toggle", "", "description...", "None", "bosd_command", "")
-weechat.hook_signal("*,irc_in2_privmsg", "bosd_privmsg_handler", "")
-
-weechat.prnt("", "bosd initiated!")
diff --git a/bpynotify_orm.py b/bpynotify_orm.py
deleted file mode 100644
index 0540d0a..0000000
--- a/bpynotify_orm.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import datetime
-
-from sqlalchemy import schema, types
-from sqlalchemy.orm import mapper
-
-metadata = schema.MetaData()
-
-notification_entry_table = schema.Table('notification_entries', metadata,
- schema.Column('id', types.Integer, primary_key=True),
- schema.Column('timestamp', types.DateTime),
- schema.Column('message', types.Unicode(), default = u'Empty message'),
- schema.Column('viewed', types.Boolean, default=False)
- )
-
-
-
-class NotificationEntry(object):
-
- def __init__(self, message):
-
- self.timestamp = datetime.datetime.now()
- self.message = message
-
-
- def __repr__(self):
-
- return message
-
-
-mapper(NotificationEntry, notification_entry_table)
diff --git a/socket_server.py b/socket_server.py
deleted file mode 100755
index c68e500..0000000
--- a/socket_server.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import SocketServer
-import os
-import sys
-
-from sqlalchemy import create_engine
-from sqlalchemy.orm import sessionmaker
-
-from bpynotify_orm import NotificationEntry, notification_entry_table
-
-
-class CustomSocketServer(SocketServer.TCPServer):
-
- def __init__(self, server_address, RequestHandlerClass, session):
- #super(CustomSocketServer, self).__init__(server_address,
- # RequestHandlerClass)
- SocketServer.TCPServer.__init__(self,
- server_address,
- RequestHandlerClass)
- self.session = session
-
-
-class MyTCPHandler(SocketServer.StreamRequestHandler):
- """
- The RequestHandler class for our server.
-
- It is instantiated once per connection to the server, and must
- override the handle() method to implement communication to the
- client.
- """
-
- def handle(self):
-
- self.data = self.rfile.readline().decode('utf8').strip()
- #print(self.data)
- entry = NotificationEntry(self.data)
- self.server.session.add(entry)
- self.server.session.commit()
-
-
-def main():
-
- HOST, PORT = "localhost", 9997
-
- if len(sys.argv) == 2 and sys.argv[1] == '-d':
- try:
- pid = os.fork()
- if pid > 0:
- sys.exit(0)
- except Exception as e:
- sys.stderr.write("Unable to daemonize. Fork error: {0}".format(e))
- sys.exit(1)
-
- try:
-
- engine = create_engine('sqlite:///notifications.db')
- Session = sessionmaker(bind=engine) # bound session
- session = Session()
-
- server = CustomSocketServer((HOST, PORT), MyTCPHandler, session)
-
- # clean all previous entries #
- notification_entry_table.delete(bind=engine).execute()
-
- server.serve_forever()
-
- except Exception as e:
- sys.stderr.write("Server error: {0}".format(e))
- sys.exit(1)
-
- sys.exit(0)
-
-
-if __name__ == "__main__":
- main()
diff --git a/web_server.py b/web_server.py
deleted file mode 100755
index cec8c38..0000000
--- a/web_server.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import sys
-
-import cherrypy
-
-class WebNotifyServer(object):
-
- def __init__(self):
- self.counter = 0
-
- @cherrypy.expose
- def notifications(self, **kwargs):
- self.counter += 1
- print(str(kwargs))
- print(self.counter)
- return ("called")
-
-
- @cherrypy.expose
- def other(self, **kwargs):
- self.counter += 1
- print(str(kwargs))
- print(self.counter)
- return ("called")
-
-
-def main():
-
- cherrypy.config.update({
- 'server.socket_host': '10.0.0.4',
- 'server.socket_port': 40003,
- })
-
- try:
- cherrypy.quickstart(WebNotifyServer())
-
- except Exception as e:
- sys.stderr.write("WebServer error: {0}".format(e))
- sys.exit(1)
-
- sys.exit(0)
-
-
-if __name__ == "__main__":
- main()
diff --git a/weechat_notify.py b/weechat_notify.py
deleted file mode 100755
index 897f26d..0000000
--- a/weechat_notify.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import json
-import urllib2
-import sched
-import sys
-import time
-
-import pynotify
-
-POLLING_FREQUENCY = 10
-NOTIFICATION_URL = 'https://simeon.simeonov.no:40004/notifications/'
-TIMEOUT_SEC = 3
-
-
-def poll_notifications(scheduler):
- """
- """
- try:
- req = urllib2.Request(NOTIFICATION_URL)
- response = urllib2.urlopen(req)
- response_str = response.read()
-
- entries = json.loads(response_str)
- for entry in entries:
- n = pynotify.Notification('IRC', entry, 'dialog-information')
- n.set_timeout(TIMEOUT_SEC)
- n.show()
-
- except Exception as e:
- sys.stderr.write("Client error: {0}".format(e))
- sys.exit(1)
-
- scheduler.enter(POLLING_FREQUENCY, 1, poll_notifications, (scheduler,))
-
-
-def main():
-
- if not pynotify.init("Weechat Notify"):
- sys.stderr.write("There was a problem with libnotify")
- sys.exit(1)
-
- sc = sched.scheduler(time.time, time.sleep)
- sc.enter(POLLING_FREQUENCY, 1, poll_notifications, (sc,))
- sc.run()
-
-if __name__ == '__main__':
- main()
diff --git a/weechat_notify_server.py b/weechat_notify_server.py
deleted file mode 100755
index 35d4f42..0000000
--- a/weechat_notify_server.py
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import json
-import SocketServer
-import os
-import sys
-
-from multiprocessing import Process, Queue
-
-import cherrypy
-
-import settings
-
-
-class CustomSocketServer(SocketServer.TCPServer):
-
- def __init__(self, server_address, RequestHandlerClass, queue):
- SocketServer.TCPServer.__init__(self,
- server_address,
- RequestHandlerClass)
- self.queue = queue
-
-
-class MyTCPHandler(SocketServer.StreamRequestHandler):
- """
- The RequestHandler class for our server.
-
- It is instantiated once per connection to the server, and must
- override the handle() method to implement communication to the
- client.
- """
-
- def handle(self):
-
- data = self.rfile.readline().strip()
-
- if self.server.queue.qsize() > 3:
- self.server.queue.get()
-
- self.server.queue.put(data)
- #print(self.data)
-
-
-class WebNotifyServer(object):
-
- def __init__(self, queue):
- self.queue = queue
-
- @cherrypy.expose
- def notifications(self):
-
- entry_list = list()
-
- while not self.queue.empty():
- entry_list.append(self.queue.get(False))
-
- #print (json.dumps(entry_list, sort_keys=True, indent=4))
- return json.dumps(entry_list)
-
-
-def socket_server(queue):
-
- try:
- server = CustomSocketServer((settings.SOCKET_SERVER_HOST,
- settings.SOCKET_SERVER_PORT),
- MyTCPHandler,
- queue)
- server.serve_forever()
-
- except Exception as e:
- sys.stderr.write("SocketServer error: {0}".format(e))
- sys.exit(1)
-
- sys.exit(0)
-
-
-
-def web_server(queue):
-
- cherrypy.config.update({
- 'server.socket_host': settings.WEB_SERVER_HOST,
- 'server.socket_port': settings.WEB_SERVER_PORT,
- 'server.ssl_module': 'pyopenssl',
- 'server.ssl_certificate': settings.WEB_SERVER_CERT,
- 'server.ssl_private_key': settings.WEB_SERVER_KEY,
- })
-
- try:
-
- cherrypy.quickstart(WebNotifyServer(queue))
-
- except Exception as e:
- sys.stderr.write("WebServer error: {0}".format(e))
- sys.exit(1)
-
- sys.exit(0)
-
-
-def main():
-
- q = Queue()
-
- socket_server_process = Process(target=socket_server, args=(q,))
- web_server_process = Process(target=web_server, args=(q,))
-
- web_server_process.start()
- socket_server_process.start()
-
- socket_server_process.join()
- web_server_process.join()
-
- sys.exit(0)
-
-if __name__ == "__main__":
- main()
--
cgit v1.3