source: python/implugin.py @ 2b4402f

Last change on this file since 2b4402f was 600e09c, checked in by Wilmer van der Gaast <wilmer@…>, at 2015-05-14T16:38:00Z

Rough split of NewsBlur plugin from implugin base. Includes some plumbing
for caching setting values inside the plugin.

  • Property mode set to 100755
File size: 3.4 KB
RevLine 
[f3af614]1#!/usr/bin/python
2
3import bjsonrpc
4from bjsonrpc.handlers import BaseHandler
5
6import re
7import socket
[2533d10]8
[f3af614]9# List of functions an IM plugin can export. This library will indicate to
10# BitlBee which functions are actually implemented so omitted features
11# will be disabled, but note that some/many functions are simply mandatory.
[f8feb8a]12# (Currently login/-out, buddy_msg.)
[f3af614]13SUPPORTED_FUNCTIONS = [
14        'login', 'keepalive', 'logout', 'buddy_msg', 'set_away',
15        'send_typing', 'add_buddy', 'remove_buddy', 'add_permit',
16        'add_deny', 'rem_permit', 'rem_deny', 'get_info', 'chat_invite',
17        'chat_kick', 'chat_leave', 'chat_msg', 'chat_with', 'chat_join',
18        'chat_topic'
19]
20
[b20014b]21def make_version_tuple(hex):
22        """Convert the BitlBee binary-encoded version number into something
23        more "Pythonic". Could use distutils.version instead but its main
24        benefit appears to be string parsing which here is not that useful."""
25
26        return (hex >> 16, (hex >> 8) & 0xff, hex & 0xff)
27
[f3af614]28class RpcForwarder(object):
29        """Tiny object that forwards RPCs from local Python code to BitlBee
30        with a marginally nicer syntax. This layer could eventually be
31        used to add basic parameter checking though I don't think that should
32        be done here."""
33       
34        def __init__(self, methods, target):
35                for m in methods:
36                        # imc(b)_ prefix is not useful here, chop it.
37                        # (Maybe do this in BitlBee already as well.)
38                        newname = re.sub("^imcb?_", "", m)
39                        self.__setattr__(newname, target.__getattr__(m))
40
41class BitlBeeIMPlugin(BaseHandler):
[c5a7b8d]42        # Protocol name to be used in the BitlBee CLI, etc.
[f3af614]43        NAME = "rpc-test"
[c5a7b8d]44
45        # See account.h (TODO: Add constants.)
[e9face7]46        ACCOUNT_FLAGS = 0
[c5a7b8d]47       
48        # Supported away states. If your protocol supports a specific set of
49        # away states, put them in a list in this variable.
[2533d10]50        AWAY_STATES = None
[600e09c]51
52        SETTINGS = {
53                "oauth": {
54                        "default": False,
55                        "type": "bool",
56                },
57                "test": {
58                        "default": 123,
59                        "type": "int",
60                },
61                "stringetje": {
62                        "default": "testje",
63                        "flags": 0x04,
64                }
65        }
66        _settings_values = {}
[f3af614]67       
68        # Filled in during initialisation:
[b20014b]69        # Version number as a three-tuple, so 3.2 becomes (3, 2, 0).
[f3af614]70        bitlbee_version = None
71        # Full version string
72        bitlbee_version_str = None
[c5a7b8d]73        # Will become an RpcForwarder object to call into BitlBee
74        bee = None
[f3af614]75       
76        @classmethod
77        def _factory(cls, *args, **kwargs):
78                def handler_factory(connection):
79                        handler = cls(connection, *args, **kwargs)
80                        return handler
81                return handler_factory
82       
83        def init(self, bee):
84                self.bee = RpcForwarder(bee["method_list"], self._conn.call)
[b20014b]85                self.bitlbee_version = make_version_tuple(bee["version"])
[f3af614]86                self.bitlbee_version_str = bee["version_str"]
[2533d10]87
[f3af614]88                return {
89                        "name": self.NAME,
90                        "method_list": list(set(dir(self)) & set(SUPPORTED_FUNCTIONS)),
[c5a7b8d]91                        "account_flags": self.ACCOUNT_FLAGS,
92                        "away_state_list": self.AWAY_STATES,
[600e09c]93                        "settings": self.SETTINGS,
[f3af614]94                }
95
[600e09c]96        def login(self, account):
97                for key, value in account.get("settings", {}).iteritems():
98                        self.set_set(key, value)
99
100        def set_set(self, key, value):
101                self._settings_values[key] = value
102                try:
103                        func = self.__getattribute__("set_set_%s" % key)
104                except AttributeError:
[e9face7]105                        return
[600e09c]106                func(key, value)
107       
108        def setting(self, key):
109                return self._settings_values[key]
[e9face7]110
[f3af614]111
[600e09c]112def RunPlugin(plugin, debug=False):
[f3af614]113        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
114        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
[600e09c]115        sock.bind("/tmp/rpcplugins/%s.sock" % plugin.NAME)
[f3af614]116        sock.listen(3)
117       
118        srv = bjsonrpc.server.Server(sock, plugin._factory())
119       
120        srv.debug_socket(debug)
121        srv.serve()
Note: See TracBrowser for help on using the repository browser.