source: python/implugin.py @ 600e09c

Last change on this file since 600e09c 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
Line 
1#!/usr/bin/python
2
3import bjsonrpc
4from bjsonrpc.handlers import BaseHandler
5
6import re
7import socket
8
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.
12# (Currently login/-out, buddy_msg.)
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
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
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):
42        # Protocol name to be used in the BitlBee CLI, etc.
43        NAME = "rpc-test"
44
45        # See account.h (TODO: Add constants.)
46        ACCOUNT_FLAGS = 0
47       
48        # Supported away states. If your protocol supports a specific set of
49        # away states, put them in a list in this variable.
50        AWAY_STATES = None
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 = {}
67       
68        # Filled in during initialisation:
69        # Version number as a three-tuple, so 3.2 becomes (3, 2, 0).
70        bitlbee_version = None
71        # Full version string
72        bitlbee_version_str = None
73        # Will become an RpcForwarder object to call into BitlBee
74        bee = None
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)
85                self.bitlbee_version = make_version_tuple(bee["version"])
86                self.bitlbee_version_str = bee["version_str"]
87
88                return {
89                        "name": self.NAME,
90                        "method_list": list(set(dir(self)) & set(SUPPORTED_FUNCTIONS)),
91                        "account_flags": self.ACCOUNT_FLAGS,
92                        "away_state_list": self.AWAY_STATES,
93                        "settings": self.SETTINGS,
94                }
95
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:
105                        return
106                func(key, value)
107       
108        def setting(self, key):
109                return self._settings_values[key]
110
111
112def RunPlugin(plugin, debug=False):
113        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
114        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
115        sock.bind("/tmp/rpcplugins/%s.sock" % plugin.NAME)
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.