diff options
| author | Simeon Simeonov | 2014-08-31 13:28:22 +0200 |
|---|---|---|
| committer | Simeon Simeonov | 2014-08-31 13:28:22 +0200 |
| commit | 472f3d3bf50b352165bc192ce5d0ffa45d81ce00 (patch) | |
| tree | 56d35f027b7939284871a10a57223a768b738f51 | |
| parent | fa1aacfde8679551cebda346a2c45d04204441eb (diff) | |
Version 1.0 completed
| -rw-r--r-- | INSTALL | 97 | ||||
| -rw-r--r-- | README | 46 | ||||
| -rwxr-xr-x | beinc_poller.py | 10 | ||||
| -rwxr-xr-x | beinc_server.py | 10 | ||||
| -rw-r--r-- | beinc_weechat.py | 37 |
5 files changed, 185 insertions, 15 deletions
| @@ -1,3 +1,98 @@ | |||
| 1 | Installation Instructions | 1 | Installation Instructions |
| 2 | --------------------------------------- | 2 | ------------------------- |
| 3 | 3 | ||
| 4 | Refer to README for a basic information about the differents BEINC components | ||
| 5 | and their software requirements! | ||
| 6 | |||
| 7 | |||
| 8 | Installing the dependencies | ||
| 9 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | Gentoo GNU/Linux 2013, 2014 | ||
| 14 | .......................... | ||
| 15 | |||
| 16 | # emerge -va dev-python/pyopenssl dev-python/cherrypy dev-python/notify-python dev-python/pyosd | ||
| 17 | |||
| 18 | |||
| 19 | Ubuntu GNU/Linux | ||
| 20 | ................ | ||
| 21 | |||
| 22 | # apt-get install python-openssl python-cherrypy python-notify2 python-pyosd | ||
| 23 | |||
| 24 | |||
| 25 | FreeBSD 9, 10 | ||
| 26 | ............. | ||
| 27 | |||
| 28 | # cd /usr/ports/security/py-openssl | ||
| 29 | # make install clean | ||
| 30 | |||
| 31 | # cd /usr/ports/www/py-cherrypy | ||
| 32 | # make install clean | ||
| 33 | |||
| 34 | # cd /usr/ports/devel/py-notify | ||
| 35 | # make install clean | ||
| 36 | |||
| 37 | # cd /usr/ports/misc/py-osd | ||
| 38 | # make install clean | ||
| 39 | |||
| 40 | |||
| 41 | Intallation using virtualenv and pip | ||
| 42 | .................................... | ||
| 43 | |||
| 44 | Very often you are not the administrator of the server hosting your BEINC server | ||
| 45 | This is where virtualenv may become handy (provided that it has been installed): | ||
| 46 | $ virtualenv beinc_installation | ||
| 47 | $ cd beinc_installation | ||
| 48 | $ source bin/activate | ||
| 49 | $ pip install cherrypy | ||
| 50 | $ pip install pyopenssl | ||
| 51 | $ cd beinc-<version> | ||
| 52 | $ ./beinc_server.py -h | ||
| 53 | |||
| 54 | |||
| 55 | Installing and setting up BEINC | ||
| 56 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 57 | |||
| 58 | Unpack the latest version of BEINC | ||
| 59 | $ tar zxvf beinc-<version>.tar.gz | ||
| 60 | |||
| 61 | $cd beinc-<version> | ||
| 62 | Read the README file | ||
| 63 | |||
| 64 | You should now have a basic understanding about the different BEINC components | ||
| 65 | and how they interact with each other. | ||
| 66 | beinc_server.py and beinc_weechat.py are using a .json configuration file. | ||
| 67 | Read beinc_config_sample.json.readme where every configuration option is explined. | ||
| 68 | Decide on a use-strategy and place the different components to their locations: | ||
| 69 | |||
| 70 | beinc_server.py: | ||
| 71 | Create a configuration file based on beinc_config_sample.json, defining your instances | ||
| 72 | Start the BEINC server: | ||
| 73 | $ ./beinc_server.py -H 10.0.0.44 -p 9678 | ||
| 74 | The example loads the server listening on 10.0.0.44, port 9678 using the default | ||
| 75 | ~/.beinc_server.json as a configuration file | ||
| 76 | |||
| 77 | beinc_poller.py: | ||
| 78 | $ ./beinc_poller.py -h | ||
| 79 | The example lists all available command options | ||
| 80 | $ ./beinc_poller.py -t 10 -f 7 --cert-file /home/sgs/weechat_cert.crt \ | ||
| 81 | -P /home/sgs/.weechat_beinc_passwd https://10.0.0.44:9678/pull/weechat | ||
| 82 | Starts polling from the instance (target) defined above, | ||
| 83 | defining an OSD timeout of 10 seconds, polling frequency of 7 seconds, | ||
| 84 | checking whether the server's SSL certificate was signed (issued) by /home/sgs/weechat_cert.crt, | ||
| 85 | extracting the target's password from /home/sgs/.weechat_beinc_passwd | ||
| 86 | |||
| 87 | beinc_generic_client.py: | ||
| 88 | $ ./beinc_generic_client.py -h | ||
| 89 | The example lists all available command options | ||
| 90 | |||
| 91 | beinc_weechat.py: | ||
| 92 | Create a configuration file based on beinc_config_sample.json, defining your targets | ||
| 93 | and copy it (or symlink it) to ~/<weechat-dir>/beinc_weechat.json | ||
| 94 | (weechat-dir is usually ~/.weechat) | ||
| 95 | Copy (or symlink) beinc_weechat.py to ~/<weechat-dir>/python/autoload/ | ||
| 96 | Load the script in Weechat by typing: /python load beinc_weechat.py | ||
| 97 | Make sure that all your targets look as they should: /beinc target list | ||
| 98 | Test if your targets are displaying / relaying your messages: /beinc broadcast Test | ||
| @@ -27,6 +27,9 @@ beinc_generic_client.py - a simple client used to push notification messages | |||
| 27 | Why should I use BEINC and what has it done for me lately? | 27 | Why should I use BEINC and what has it done for me lately? |
| 28 | ---------------------------------------------------------- | 28 | ---------------------------------------------------------- |
| 29 | 29 | ||
| 30 | BEINC is a free-software, licensed under the GPL3. It gives you the freedoms | ||
| 31 | of using it, studying it and modifying it. | ||
| 32 | |||
| 30 | BEINC is designed to assist you two common scenarios. | 33 | BEINC is designed to assist you two common scenarios. |
| 31 | As an example we will consider the case of an IRC cliet, although BEINC can be | 34 | As an example we will consider the case of an IRC cliet, although BEINC can be |
| 32 | used by any client that conforms with BEINC's "messaging protocol". | 35 | used by any client that conforms with BEINC's "messaging protocol". |
| @@ -35,9 +38,15 @@ We have the common situation where a user is accessing an IRC client located on | |||
| 35 | a different computer (typically: weechat, irssi, etc. running on a remote server) | 38 | a different computer (typically: weechat, irssi, etc. running on a remote server) |
| 36 | The IRC client receives a private message (or any event that requires the user's | 39 | The IRC client receives a private message (or any event that requires the user's |
| 37 | attention) and the user has to be notified. | 40 | attention) and the user has to be notified. |
| 41 | No matter which of the two scenarios applies to your needs, you should start by | ||
| 42 | - setting up a BEINC client similar to beinc_generic_client.py on the server | ||
| 43 | If you are running weechat >=0.4.0, this version of BEINC comes with | ||
| 44 | a complete weechat BEINC-client: beinc_weechat.py | ||
| 45 | Configure the client to send notifications to the beinc_server.py | ||
| 46 | N.B. Using encryption is important in these days and age. | ||
| 38 | 47 | ||
| 39 | Scenario one: | 48 | Scenario one: |
| 40 | The user's computer can be reached from the server running the IRC client. | 49 | The user's computer can be reached by the server running the IRC client. |
| 41 | If the server (running the IRC client) is able to connect to | 50 | If the server (running the IRC client) is able to connect to |
| 42 | a specified TCP port on the user's computer, this is sufficient for BEINC to | 51 | a specified TCP port on the user's computer, this is sufficient for BEINC to |
| 43 | directly notify the user. Solution: | 52 | directly notify the user. Solution: |
| @@ -45,25 +54,44 @@ directly notify the user. Solution: | |||
| 45 | notification-message should be displayed). Define an unprivileged port for | 54 | notification-message should be displayed). Define an unprivileged port for |
| 46 | beinc_server.py to listen on and enable its OSD capabilities | 55 | beinc_server.py to listen on and enable its OSD capabilities |
| 47 | (through pynotify and/or pyosd) | 56 | (through pynotify and/or pyosd) |
| 48 | - set up a BEINC client similar to beinc_generic_client.py on the server | ||
| 49 | If you are running weechat >=0.4.0, this version of BEINC comes with | ||
| 50 | a complete weechat BEINC-client: beinc_weechat.py | ||
| 51 | Configure the client to send notifications to the beinc_server.py | ||
| 52 | 57 | ||
| 53 | Scenario two: | 58 | Scenario two: |
| 59 | The user's computer can NOT be reached by the server running the IRC client. | ||
| 60 | This scenario is typical for users that are working on computers that can not | ||
| 61 | be reached from outside. | ||
| 62 | Solution: | ||
| 63 | - find a server that can be reached by the server running the IRC client. | ||
| 64 | - set up the beinc_server.py on it. No OSD capabilities are needed (no X11). | ||
| 65 | Define instance(s) for queueing. Define a queue size | ||
| 66 | (how many notifications to store) for each of them. | ||
| 67 | - set up beinc_poller.py on the desktop workstation (the computer where the | ||
| 68 | notification-message should be displayed). | ||
| 69 | beinc_poller.py should be able to access the server running beinc_server.py | ||
| 70 | Polling interval of 5 seconds should be enough for most users. | ||
| 54 | 71 | ||
| 72 | Read beinc_config_sample.json.readme for details on how to setup beinc_server.py | ||
| 73 | and beinc_weechat.py! | ||
| 74 | Use "-h" command line parameter in order to display the available options for | ||
| 75 | beinc_poller.py and beinc_generic_client.py | ||
| 55 | 76 | ||
| 56 | 77 | ||
| 57 | Supported systems & requirements | 78 | Supported systems & requirements |
| 58 | -------------------------------- | 79 | -------------------------------- |
| 59 | Any system running Postfix and Spamassassin. | 80 | Any system running the software required for the selected components. |
| 81 | All components tested on: Gentoo GNU/Linux 2013,2014, | ||
| 82 | Ubuntu GNU/Linux 14.4,13.10, | ||
| 83 | FreeBSD 9.x | ||
| 60 | 84 | ||
| 61 | 85 | ||
| 62 | Requirements: | 86 | Requirements: |
| 63 | All components: Python 2.7.* | 87 | All components: Python 2.7.* |
| 64 | beinc_server.py: cherrypy >= 3.2.0, pyopenssl >= 0.13.0 | 88 | beinc_server.py: cherrypy >= 3.2.0, pyopenssl >= 0.13.0 (opntional (ssl support)), |
| 65 | beinc_weechat.py: | 89 | pynotify >= 0.1 (optional), pyosd >= 0.2 (optional) |
| 66 | beinc_poller.py: | 90 | beinc_weechat.py: Weechat >= 0.4.0 |
| 91 | beinc_poller.py: pynotify >= 0.1 (optional), pyosd >= 0.2 (optional) | ||
| 92 | beinc_generic_client.py: No additional software required | ||
| 93 | |||
| 94 | Read INSTALL for more details about installing the requirements! | ||
| 67 | 95 | ||
| 68 | 96 | ||
| 69 | License | 97 | License |
diff --git a/beinc_poller.py b/beinc_poller.py index 4fbe0e0..a1269c2 100755 --- a/beinc_poller.py +++ b/beinc_poller.py | |||
| @@ -86,6 +86,11 @@ class ValidHTTPSHandler(urllib2.HTTPSHandler): | |||
| 86 | 86 | ||
| 87 | def poll_notifications(scheduler, args, notification_obj): | 87 | def poll_notifications(scheduler, args, notification_obj): |
| 88 | """ | 88 | """ |
| 89 | the core function initiated by the scheduler performing a single poll | ||
| 90 | |||
| 91 | scheduler: scheduler object | ||
| 92 | args: the argparse processed command-line arguments | ||
| 93 | notification_obj: pynotify or pyosd notification object | ||
| 89 | """ | 94 | """ |
| 90 | try: | 95 | try: |
| 91 | post_values = {'password': args.password} | 96 | post_values = {'password': args.password} |
| @@ -193,11 +198,12 @@ def main(): | |||
| 193 | help='BEINC osd-system ("pynotify" or "pyosd") (default: pynotify)') | 198 | help='BEINC osd-system ("pynotify" or "pyosd") (default: pynotify)') |
| 194 | parser.add_argument( | 199 | parser.add_argument( |
| 195 | '-P', '--password', | 200 | '-P', '--password', |
| 196 | metavar='PASSWORD', | 201 | metavar='PASSWORD[FILE]', |
| 197 | type=str, | 202 | type=str, |
| 198 | dest='password', | 203 | dest='password', |
| 199 | default='', | 204 | default='', |
| 200 | help='BEINC taget-password (default & recommended: prompt for passwd)') | 205 | help='BEINC taget-password / text-file containing the target password' |
| 206 | ' (default & recommended: prompt for passwd)') | ||
| 201 | parser.add_argument( | 207 | parser.add_argument( |
| 202 | '-p', '--position', | 208 | '-p', '--position', |
| 203 | metavar='POSITION', | 209 | metavar='POSITION', |
diff --git a/beinc_server.py b/beinc_server.py index 906b303..30c8a95 100755 --- a/beinc_server.py +++ b/beinc_server.py | |||
| @@ -133,14 +133,14 @@ class BEINCInstance(object): | |||
| 133 | @property | 133 | @property |
| 134 | def name(self): | 134 | def name(self): |
| 135 | """ | 135 | """ |
| 136 | name-property for the server instance | 136 | name-property for the server instance (read-only) |
| 137 | """ | 137 | """ |
| 138 | return self.__name | 138 | return self.__name |
| 139 | 139 | ||
| 140 | @property | 140 | @property |
| 141 | def queueable(self): | 141 | def queueable(self): |
| 142 | """ | 142 | """ |
| 143 | True if this instance has a queueing capability | 143 | True if this instance has a queueing capability (read-only) |
| 144 | """ | 144 | """ |
| 145 | return bool(self.__queue_size) | 145 | return bool(self.__queue_size) |
| 146 | 146 | ||
| @@ -216,6 +216,9 @@ def beinc_instance_login(method): | |||
| 216 | 216 | ||
| 217 | 217 | ||
| 218 | class WebNotifyServer(object): | 218 | class WebNotifyServer(object): |
| 219 | """ | ||
| 220 | A class representing the entire server | ||
| 221 | """ | ||
| 219 | 222 | ||
| 220 | def __init__(self, config): | 223 | def __init__(self, config): |
| 221 | """ | 224 | """ |
| @@ -244,6 +247,9 @@ class WebNotifyServer(object): | |||
| 244 | 247 | ||
| 245 | @property | 248 | @property |
| 246 | def instances(self): | 249 | def instances(self): |
| 250 | """ | ||
| 251 | a property that returns the instance list (read-only) | ||
| 252 | """ | ||
| 247 | return self.__instances | 253 | return self.__instances |
| 248 | 254 | ||
| 249 | @cherrypy.expose | 255 | @cherrypy.expose |
diff --git a/beinc_weechat.py b/beinc_weechat.py index 14e6eac..f878c89 100644 --- a/beinc_weechat.py +++ b/beinc_weechat.py | |||
| @@ -79,6 +79,8 @@ class ValidHTTPSHandler(urllib2.HTTPSHandler): | |||
| 79 | 79 | ||
| 80 | class WeechatTarget(object): | 80 | class WeechatTarget(object): |
| 81 | """ | 81 | """ |
| 82 | The target (destination) class | ||
| 83 | Each remote destination is represented as a WeechatTarget object | ||
| 82 | """ | 84 | """ |
| 83 | 85 | ||
| 84 | def __init__(self, target_dict): | 86 | def __init__(self, target_dict): |
| @@ -123,48 +125,56 @@ class WeechatTarget(object): | |||
| 123 | @property | 125 | @property |
| 124 | def name(self): | 126 | def name(self): |
| 125 | """ | 127 | """ |
| 128 | Target name (read-only property) | ||
| 126 | """ | 129 | """ |
| 127 | return self.__name | 130 | return self.__name |
| 128 | 131 | ||
| 129 | @property | 132 | @property |
| 130 | def chans(self): | 133 | def chans(self): |
| 131 | """ | 134 | """ |
| 135 | Target channel list (read-only property) | ||
| 132 | """ | 136 | """ |
| 133 | return self.__chans | 137 | return self.__chans |
| 134 | 138 | ||
| 135 | @property | 139 | @property |
| 136 | def nicks(self): | 140 | def nicks(self): |
| 137 | """ | 141 | """ |
| 142 | Target nick list (read-only property) | ||
| 138 | """ | 143 | """ |
| 139 | return self.__nicks | 144 | return self.__nicks |
| 140 | 145 | ||
| 141 | @property | 146 | @property |
| 142 | def channel_messages_policy(self): | 147 | def channel_messages_policy(self): |
| 143 | """ | 148 | """ |
| 149 | The target's channel messages policy (read-only property) | ||
| 144 | """ | 150 | """ |
| 145 | return self.__chan_messages_policy | 151 | return self.__chan_messages_policy |
| 146 | 152 | ||
| 147 | @property | 153 | @property |
| 148 | def private_messages_policy(self): | 154 | def private_messages_policy(self): |
| 149 | """ | 155 | """ |
| 156 | The target's private messages policy (read-only property) | ||
| 150 | """ | 157 | """ |
| 151 | return self.__priv_messages_policy | 158 | return self.__priv_messages_policy |
| 152 | 159 | ||
| 153 | @property | 160 | @property |
| 154 | def notifications_policy(self): | 161 | def notifications_policy(self): |
| 155 | """ | 162 | """ |
| 163 | The target's notifications policy (read-only property) | ||
| 156 | """ | 164 | """ |
| 157 | return self.__notifications_policy | 165 | return self.__notifications_policy |
| 158 | 166 | ||
| 159 | @property | 167 | @property |
| 160 | def enabled(self): | 168 | def enabled(self): |
| 161 | """ | 169 | """ |
| 170 | The target's enabled status (bool property) | ||
| 162 | """ | 171 | """ |
| 163 | return self.__enabled | 172 | return self.__enabled |
| 164 | 173 | ||
| 165 | @enabled.setter | 174 | @enabled.setter |
| 166 | def enabled(self, value): | 175 | def enabled(self, value): |
| 167 | """ | 176 | """ |
| 177 | The target's enabled status (bool property) | ||
| 168 | """ | 178 | """ |
| 169 | self.__enabled = value | 179 | self.__enabled = value |
| 170 | 180 | ||
| @@ -186,6 +196,9 @@ class WeechatTarget(object): | |||
| 186 | 196 | ||
| 187 | def send_private_message_notification(self, values): | 197 | def send_private_message_notification(self, values): |
| 188 | """ | 198 | """ |
| 199 | sends a private message notification to the represented target | ||
| 200 | |||
| 201 | values: dict pupulated by the irc msg-handler | ||
| 189 | """ | 202 | """ |
| 190 | try: | 203 | try: |
| 191 | title_str = self.__fetch_formatted_str(self.__pm_title_template, | 204 | title_str = self.__fetch_formatted_str(self.__pm_title_template, |
| @@ -210,6 +223,9 @@ class WeechatTarget(object): | |||
| 210 | 223 | ||
| 211 | def send_channel_message_notification(self, values): | 224 | def send_channel_message_notification(self, values): |
| 212 | """ | 225 | """ |
| 226 | sends a channel message notification to the represented target | ||
| 227 | |||
| 228 | values: dict pupulated by the irc msg-handler | ||
| 213 | """ | 229 | """ |
| 214 | try: | 230 | try: |
| 215 | title_str = self.__fetch_formatted_str(self.__cm_title_template, | 231 | title_str = self.__fetch_formatted_str(self.__cm_title_template, |
| @@ -234,6 +250,9 @@ class WeechatTarget(object): | |||
| 234 | 250 | ||
| 235 | def send_notify_message_notification(self, values): | 251 | def send_notify_message_notification(self, values): |
| 236 | """ | 252 | """ |
| 253 | sends a notify message notification to the represented target | ||
| 254 | |||
| 255 | values: dict pupulated by the irc msg-handler | ||
| 237 | """ | 256 | """ |
| 238 | try: | 257 | try: |
| 239 | title_str = self.__fetch_formatted_str(self.__nm_title_template, | 258 | title_str = self.__fetch_formatted_str(self.__nm_title_template, |
| @@ -258,6 +277,10 @@ class WeechatTarget(object): | |||
| 258 | 277 | ||
| 259 | def send_broadcast_notification(self, message): | 278 | def send_broadcast_notification(self, message): |
| 260 | """ | 279 | """ |
| 280 | sends a 'pure' broadcast / test message notification | ||
| 281 | to the represented target | ||
| 282 | |||
| 283 | message: a single message string | ||
| 261 | """ | 284 | """ |
| 262 | try: | 285 | try: |
| 263 | post_values = {'title': 'BEINC broadcast', | 286 | post_values = {'title': 'BEINC broadcast', |
| @@ -277,6 +300,11 @@ class WeechatTarget(object): | |||
| 277 | 300 | ||
| 278 | def __fetch_formatted_str(self, template, values): | 301 | def __fetch_formatted_str(self, template, values): |
| 279 | """ | 302 | """ |
| 303 | returns a formatted string by replacing the defined | ||
| 304 | macros in 'template' the the corresponding values from 'values' | ||
| 305 | |||
| 306 | values: dict | ||
| 307 | template: str | ||
| 280 | """ | 308 | """ |
| 281 | template = unicode(template) | 309 | template = unicode(template) |
| 282 | timestamp = datetime.datetime.now().strftime(self.__timestamp_format) | 310 | timestamp = datetime.datetime.now().strftime(self.__timestamp_format) |
| @@ -384,6 +412,9 @@ def beinc_cmd_target_handler(cmd_tokens): | |||
| 384 | 412 | ||
| 385 | 413 | ||
| 386 | def beinc_command(data, buffer_obj, args): | 414 | def beinc_command(data, buffer_obj, args): |
| 415 | """ | ||
| 416 | Callback function handling the Weechat's /beinc command | ||
| 417 | """ | ||
| 387 | global enabled | 418 | global enabled |
| 388 | cmd_tokens = args.split() | 419 | cmd_tokens = args.split() |
| 389 | if not cmd_tokens: | 420 | if not cmd_tokens: |
| @@ -402,11 +433,15 @@ def beinc_command(data, buffer_obj, args): | |||
| 402 | elif cmd_tokens[0] == 'target': | 433 | elif cmd_tokens[0] == 'target': |
| 403 | return beinc_cmd_target_handler(cmd_tokens[1:]) | 434 | return beinc_cmd_target_handler(cmd_tokens[1:]) |
| 404 | else: | 435 | else: |
| 405 | beinc_prnt('syntax: /beinc < on | off | reload | target <action> >') | 436 | beinc_prnt('syntax: /beinc < on | off | reload |' |
| 437 | ' broadcast <text> | target <action> >') | ||
| 406 | return weechat.WEECHAT_RC_OK | 438 | return weechat.WEECHAT_RC_OK |
| 407 | 439 | ||
| 408 | 440 | ||
| 409 | def beinc_privmsg_handler(data, signal, signal_data): | 441 | def beinc_privmsg_handler(data, signal, signal_data): |
| 442 | """ | ||
| 443 | Callback function the *PRIVMSG* IRC messages hooked by Weechat | ||
| 444 | """ | ||
| 410 | if not enabled: | 445 | if not enabled: |
| 411 | return weechat.WEECHAT_RC_OK | 446 | return weechat.WEECHAT_RC_OK |
| 412 | prvmsg_dict = weechat.info_get_hashtable('irc_message_parse', | 447 | prvmsg_dict = weechat.info_get_hashtable('irc_message_parse', |
