annotate sat/plugins/plugin_exp_pubsub_hook.py @ 3728:b15644cae50d

component AP gateway: JID/node ⟺ AP outbox conversion: - convert a combination of JID and optional pubsub node to AP actor handle (see `getJIDAndNode` for details) and vice versa - the gateway now provides a Pubsub service - retrieve pubsub node and convert it to AP collection, AP pagination is converted to RSM - do the opposite: convert AP collection to pubsub and handle RSM request. Due to ActivityStream collection pagination limitations, some RSM request produce inefficient requests, but caching should be used most of the time in the future and avoid the problem. - set specific name to HTTP Server - new `local_only` setting (`True` by default) to indicate if the gateway can request or not XMPP Pubsub nodes from other servers - disco info now specifies important features such as Pubsub RSM, and nodes metadata ticket 363
author Goffi <goffi@goffi.org>
date Tue, 25 Jan 2022 17:54:06 +0100
parents be6d91572633
children 524856bd7b19
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
1 #!/usr/bin/env python3
3137
559a625a236b fixed shebangs
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
2
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
3
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 # SAT plugin for Pubsub Hooks
3479
be6d91572633 date update
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
5 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
6
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # This program is free software: you can redistribute it and/or modify
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # it under the terms of the GNU Affero General Public License as published by
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # the Free Software Foundation, either version 3 of the License, or
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
10 # (at your option) any later version.
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
11
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # This program is distributed in the hope that it will be useful,
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
15 # GNU Affero General Public License for more details.
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
16
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # You should have received a copy of the GNU Affero General Public License
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
19
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
20 from sat.core.i18n import _
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
21 from sat.core.constants import Const as C
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
22 from sat.core import exceptions
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
23 from sat.core.log import getLogger
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
24 from sat.memory import persistent
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
25 from twisted.words.protocols.jabber import jid
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
26 from twisted.internet import defer
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
27
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
28 log = getLogger(__name__)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
29
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
30 NS_PUBSUB_HOOK = "PUBSUB_HOOK"
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
31
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 PLUGIN_INFO = {
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 C.PI_NAME: "PubSub Hook",
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
34 C.PI_IMPORT_NAME: NS_PUBSUB_HOOK,
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 C.PI_TYPE: "EXP",
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
36 C.PI_PROTOCOLS: [],
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
37 C.PI_DEPENDENCIES: ["XEP-0060"],
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
38 C.PI_MAIN: "PubsubHook",
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
39 C.PI_HANDLER: "no",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
40 C.PI_DESCRIPTION: _(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
41 """Experimental plugin to launch on action on Pubsub notifications"""
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
42 ),
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
43 }
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
44
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
45 #  python module
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
46 HOOK_TYPE_PYTHON = "python"
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 # python file path
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
48 HOOK_TYPE_PYTHON_FILE = "python_file"
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 # python code directly
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
50 HOOK_TYPE_PYTHON_CODE = "python_code"
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
51 HOOK_TYPES = (HOOK_TYPE_PYTHON, HOOK_TYPE_PYTHON_FILE, HOOK_TYPE_PYTHON_CODE)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
52
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
53
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
54 class PubsubHook(object):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
55 def __init__(self, host):
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
56 log.info(_("PubSub Hook initialization"))
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
57 self.host = host
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
58 self.node_hooks = {} # keep track of the number of hooks per node (for all profiles)
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
59 host.bridge.addMethod(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
60 "psHookAdd", ".plugin", in_sign="ssssbs", out_sign="", method=self._addHook
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
61 )
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
62 host.bridge.addMethod(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
63 "psHookRemove",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
64 ".plugin",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
65 in_sign="sssss",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
66 out_sign="i",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
67 method=self._removeHook,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
68 )
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
69 host.bridge.addMethod(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
70 "psHookList",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
71 ".plugin",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
72 in_sign="s",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
73 out_sign="aa{ss}",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
74 method=self._listHooks,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
75 )
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
76
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
77 @defer.inlineCallbacks
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
78 def profileConnected(self, client):
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
79 hooks = client._hooks = persistent.PersistentBinaryDict(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
80 NS_PUBSUB_HOOK, client.profile
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
81 )
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
82 client._hooks_temporary = {}
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
83 yield hooks.load()
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
84 for node in hooks:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
85 self._installNodeManager(client, node)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
86
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
87 def profileDisconnected(self, client):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
88 for node in client._hooks:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
89 self._removeNodeManager(client, node)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
90
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
91 def _installNodeManager(self, client, node):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
92 if node in self.node_hooks:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
93 log.debug(_("node manager already set for {node}").format(node=node))
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
94 self.node_hooks[node] += 1
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
95 else:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
96 # first hook on this node
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
97 self.host.plugins["XEP-0060"].addManagedNode(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
98 node, items_cb=self._itemsReceived
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
99 )
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
100 self.node_hooks[node] = 0
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
101 log.info(_("node manager installed on {node}").format(node=node))
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
102
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
103 def _removeNodeManager(self, client, node):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
104 try:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
105 self.node_hooks[node] -= 1
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
106 except KeyError:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
107 log.error(_("trying to remove a {node} without hook").format(node=node))
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
108 else:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
109 if self.node_hooks[node] == 0:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
110 del self.node_hooks[node]
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
111 self.host.plugins["XEP-0060"].removeManagedNode(node, self._itemsReceived)
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
112 log.debug(_("hook removed"))
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
113 else:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
114 log.debug(_("node still needed for an other hook"))
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
115
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
116 def installHook(self, client, service, node, hook_type, hook_arg, persistent):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
117 if hook_type not in HOOK_TYPES:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
118 raise exceptions.DataError(
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
119 _("{hook_type} is not handled").format(hook_type=hook_type)
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
120 )
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
121 if hook_type != HOOK_TYPE_PYTHON_FILE:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
122 raise NotImplementedError(
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
123 _("{hook_type} hook type not implemented yet").format(
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
124 hook_type=hook_type
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
125 )
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
126 )
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
127 self._installNodeManager(client, node)
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
128 hook_data = {"service": service, "type": hook_type, "arg": hook_arg}
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
129
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
130 if persistent:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
131 hooks_list = client._hooks.setdefault(node, [])
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
132 hooks_list.append(hook_data)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
133 client._hooks.force(node)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
134 else:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
135 hooks_list = client._hooks_temporary.setdefault(node, [])
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
136 hooks_list.append(hook_data)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
137
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
138 log.info(
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
139 _("{persistent} hook installed on {node} for {profile}").format(
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
140 persistent=_("persistent") if persistent else _("temporary"),
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
141 node=node,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
142 profile=client.profile,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
143 )
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
144 )
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
145
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
146 def _itemsReceived(self, client, itemsEvent):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
147 node = itemsEvent.nodeIdentifier
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
148 for hooks in (client._hooks, client._hooks_temporary):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
149 if node not in hooks:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
150 continue
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
151 hooks_list = hooks[node]
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
152 for hook_data in hooks_list[:]:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
153 if hook_data["service"] != itemsEvent.sender.userhostJID():
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
154 continue
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
155 try:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
156 callback = hook_data["callback"]
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
157 except KeyError:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
158 # first time we get this hook, we create the callback
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
159 hook_type = hook_data["type"]
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
160 try:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
161 if hook_type == HOOK_TYPE_PYTHON_FILE:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
162 hook_globals = {}
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
163 exec(compile(open(hook_data["arg"], "rb").read(), hook_data["arg"], 'exec'), hook_globals)
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
164 callback = hook_globals["hook"]
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
165 else:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
166 raise NotImplementedError(
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
167 _("{hook_type} hook type not implemented yet").format(
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
168 hook_type=hook_type
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
169 )
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
170 )
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
171 except Exception as e:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
172 log.warning(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
173 _(
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
174 "Can't load Pubsub hook at node {node}, it will be removed: {reason}"
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
175 ).format(node=node, reason=e)
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
176 )
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
177 hooks_list.remove(hook_data)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
178 continue
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
179
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
180 for item in itemsEvent.items:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
181 try:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
182 callback(self.host, client, item)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
183 except Exception as e:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
184 log.warning(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
185 _(
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
186 "Error while running Pubsub hook for node {node}: {msg}"
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
187 ).format(node=node, msg=e)
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
188 )
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
189
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
190 def _addHook(self, service, node, hook_type, hook_arg, persistent, profile):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
191 client = self.host.getClient(profile)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
192 service = jid.JID(service) if service else client.jid.userhostJID()
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
193 return self.addHook(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
194 client,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
195 service,
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
196 str(node),
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
197 str(hook_type),
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
198 str(hook_arg),
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
199 persistent,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
200 )
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
201
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
202 def addHook(self, client, service, node, hook_type, hook_arg, persistent):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
203 r"""Add a hook which will be triggered on a pubsub notification
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
204
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
205 @param service(jid.JID): service of the node
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
206 @param node(unicode): Pubsub node
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
207 @param hook_type(unicode): type of the hook, one of:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
208 - HOOK_TYPE_PYTHON: a python module (must be in path)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
209 module must have a "hook" method which will be called
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
210 - HOOK_TYPE_PYTHON_FILE: a python file
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
211 file must have a "hook" method which will be called
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
212 - HOOK_TYPE_PYTHON_CODE: direct python code
2444
30278ea1ca7c plugin XEP-0060: added node watching methods to bridge:
Goffi <goffi@goffi.org>
parents: 2307
diff changeset
213 /!\ Python hooks will be executed in SàT context,
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
214 with host, client and item as arguments, it means that:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
215 - they can do whatever they wants, so don't run untrusted hooks
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
216 - they MUST NOT BLOCK, they are run in Twisted async environment and blocking would block whole SàT process
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
217 - item are domish.Element
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
218 @param hook_arg(unicode): argument of the hook, depending on the hook_type
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
219 can be a module path, file path, python code
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
220 """
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
221 assert service is not None
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
222 return self.installHook(client, service, node, hook_type, hook_arg, persistent)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
223
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
224 def _removeHook(self, service, node, hook_type, hook_arg, profile):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
225 client = self.host.getClient(profile)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
226 service = jid.JID(service) if service else client.jid.userhostJID()
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
227 return self.removeHook(client, service, node, hook_type or None, hook_arg or None)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
228
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
229 def removeHook(self, client, service, node, hook_type=None, hook_arg=None):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
230 """Remove a persistent or temporaty root
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
231
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
232 @param service(jid.JID): service of the node
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
233 @param node(unicode): Pubsub node
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
234 @param hook_type(unicode, None): same as for [addHook]
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
235 match all if None
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
236 @param hook_arg(unicode, None): same as for [addHook]
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
237 match all if None
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
238 @return(int): number of hooks removed
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
239 """
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
240 removed = 0
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
241 for hooks in (client._hooks, client._hooks_temporary):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
242 if node in hooks:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
243 for hook_data in hooks[node]:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
244 if (
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
245 service != hook_data["service"]
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
246 or hook_type is not None
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
247 and hook_type != hook_data["type"]
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
248 or hook_arg is not None
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
249 and hook_arg != hook_data["arg"]
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
250 ):
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
251 continue
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
252 hooks[node].remove(hook_data)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
253 removed += 1
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
254 if not hooks[node]:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
255 #  no more hooks, we can remove the node
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
256 del hooks[node]
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
257 self._removeNodeManager(client, node)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
258 else:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
259 if hooks == client._hooks:
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
260 hooks.force(node)
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
261 return removed
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
262
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
263 def _listHooks(self, profile):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
264 hooks_list = self.listHooks(self.host.getClient(profile))
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
265 for hook in hooks_list:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
266 hook["service"] = hook["service"].full()
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
267 hook["persistent"] = C.boolConst(hook["persistent"])
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
268 return hooks_list
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
269
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
270 def listHooks(self, client):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
271 """return list of registered hooks"""
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
272 hooks_list = []
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
273 for hooks in (client._hooks, client._hooks_temporary):
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
274 persistent = hooks is client._hooks
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
275 for node, hooks_data in hooks.items():
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
276 for hook_data in hooks_data:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
277 hooks_list.append(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
278 {
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
279 "service": hook_data["service"],
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
280 "node": node,
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
281 "type": hook_data["type"],
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
282 "arg": hook_data["arg"],
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
283 "persistent": persistent,
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
284 }
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
285 )
2307
8fa7edd0da24 plugin Pubsub Hook: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
286 return hooks_list