Mercurial > libervia-backend
comparison libervia/backend/plugins/plugin_exp_parrot.py @ 4071:4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 02 Jun 2023 11:49:51 +0200 |
parents | sat/plugins/plugin_exp_parrot.py@c23cad65ae99 |
children | 0d7bb4df2343 |
comparison
equal
deleted
inserted
replaced
4070:d10748475025 | 4071:4b842c1fb686 |
---|---|
1 #!/usr/bin/env python3 | |
2 | |
3 | |
4 # SAT plugin for parrot mode (experimental) | |
5 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) | |
6 | |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 from libervia.backend.core.i18n import _ | |
21 from libervia.backend.core.constants import Const as C | |
22 from libervia.backend.core.log import getLogger | |
23 | |
24 log = getLogger(__name__) | |
25 from twisted.words.protocols.jabber import jid | |
26 | |
27 from libervia.backend.core.exceptions import UnknownEntityError | |
28 | |
29 # from sat.tools import trigger | |
30 | |
31 PLUGIN_INFO = { | |
32 C.PI_NAME: "Parrot Plugin", | |
33 C.PI_IMPORT_NAME: "EXP-PARROT", | |
34 C.PI_TYPE: "EXP", | |
35 C.PI_PROTOCOLS: [], | |
36 C.PI_DEPENDENCIES: ["XEP-0045"], | |
37 C.PI_RECOMMENDATIONS: [C.TEXT_CMDS], | |
38 C.PI_MAIN: "Exp_Parrot", | |
39 C.PI_HANDLER: "no", | |
40 C.PI_DESCRIPTION: _( | |
41 """Implementation of parrot mode (repeat messages between 2 entities)""" | |
42 ), | |
43 } | |
44 | |
45 | |
46 class Exp_Parrot(object): | |
47 """Parrot mode plugin: repeat messages from one entity or MUC room to another one""" | |
48 | |
49 # XXX: This plugin can be potentially dangerous if we don't trust entities linked | |
50 # this is specially true if we have other triggers. | |
51 # send_message_trigger avoid other triggers execution, it's deactivated to allow | |
52 # /unparrot command in text commands plugin. | |
53 # FIXME: potentially unsecure, specially with e2e encryption | |
54 | |
55 def __init__(self, host): | |
56 log.info(_("Plugin Parrot initialization")) | |
57 self.host = host | |
58 host.trigger.add("message_received", self.message_received_trigger, priority=100) | |
59 # host.trigger.add("sendMessage", self.send_message_trigger, priority=100) | |
60 try: | |
61 self.host.plugins[C.TEXT_CMDS].register_text_commands(self) | |
62 except KeyError: | |
63 log.info(_("Text commands not available")) | |
64 | |
65 # def send_message_trigger(self, client, mess_data, treatments): | |
66 # """ Deactivate other triggers if recipient is in parrot links """ | |
67 # try: | |
68 # _links = client.parrot_links | |
69 # except AttributeError: | |
70 # return True | |
71 # | |
72 # if mess_data['to'].userhostJID() in _links.values(): | |
73 # log.debug("Parrot link detected, skipping other triggers") | |
74 # raise trigger.SkipOtherTriggers | |
75 | |
76 def message_received_trigger(self, client, message_elt, post_treat): | |
77 """ Check if source is linked and repeat message, else do nothing """ | |
78 # TODO: many things are not repeated (subject, thread, etc) | |
79 from_jid = message_elt["from"] | |
80 | |
81 try: | |
82 _links = client.parrot_links | |
83 except AttributeError: | |
84 return True | |
85 | |
86 if not from_jid.userhostJID() in _links: | |
87 return True | |
88 | |
89 message = {} | |
90 for e in message_elt.elements(C.NS_CLIENT, "body"): | |
91 body = str(e) | |
92 lang = e.getAttribute("lang") or "" | |
93 | |
94 try: | |
95 entity_type = self.host.memory.entity_data_get( | |
96 client, from_jid, [C.ENTITY_TYPE])[C.ENTITY_TYPE] | |
97 except (UnknownEntityError, KeyError): | |
98 entity_type = "contact" | |
99 if entity_type == C.ENTITY_TYPE_MUC: | |
100 src_txt = from_jid.resource | |
101 if src_txt == self.host.plugins["XEP-0045"].get_room_nick( | |
102 client, from_jid.userhostJID() | |
103 ): | |
104 # we won't repeat our own messages | |
105 return True | |
106 else: | |
107 src_txt = from_jid.user | |
108 message[lang] = "[{}] {}".format(src_txt, body) | |
109 | |
110 linked = _links[from_jid.userhostJID()] | |
111 | |
112 client.sendMessage( | |
113 jid.JID(str(linked)), message, None, "auto", no_trigger=True | |
114 ) | |
115 | |
116 return True | |
117 | |
118 def add_parrot(self, client, source_jid, dest_jid): | |
119 """Add a parrot link from one entity to another one | |
120 | |
121 @param source_jid: entity from who messages will be repeated | |
122 @param dest_jid: entity where the messages will be repeated | |
123 """ | |
124 try: | |
125 _links = client.parrot_links | |
126 except AttributeError: | |
127 _links = client.parrot_links = {} | |
128 | |
129 _links[source_jid.userhostJID()] = dest_jid | |
130 log.info( | |
131 "Parrot mode: %s will be repeated to %s" | |
132 % (source_jid.userhost(), str(dest_jid)) | |
133 ) | |
134 | |
135 def remove_parrot(self, client, source_jid): | |
136 """Remove parrot link | |
137 | |
138 @param source_jid: this entity will no more be repeated | |
139 """ | |
140 try: | |
141 del client.parrot_links[source_jid.userhostJID()] | |
142 except (AttributeError, KeyError): | |
143 pass | |
144 | |
145 def cmd_parrot(self, client, mess_data): | |
146 """activate Parrot mode between 2 entities, in both directions.""" | |
147 log.debug("Catched parrot command") | |
148 txt_cmd = self.host.plugins[C.TEXT_CMDS] | |
149 | |
150 try: | |
151 link_left_jid = jid.JID(mess_data["unparsed"].strip()) | |
152 if not link_left_jid.user or not link_left_jid.host: | |
153 raise jid.InvalidFormat | |
154 except (RuntimeError, jid.InvalidFormat, AttributeError): | |
155 txt_cmd.feed_back( | |
156 client, "Can't activate Parrot mode for invalid jid", mess_data | |
157 ) | |
158 return False | |
159 | |
160 link_right_jid = mess_data["to"] | |
161 | |
162 self.add_parrot(client, link_left_jid, link_right_jid) | |
163 self.add_parrot(client, link_right_jid, link_left_jid) | |
164 | |
165 txt_cmd.feed_back( | |
166 client, | |
167 "Parrot mode activated for {}".format(str(link_left_jid)), | |
168 mess_data, | |
169 ) | |
170 | |
171 return False | |
172 | |
173 def cmd_unparrot(self, client, mess_data): | |
174 """remove Parrot mode between 2 entities, in both directions.""" | |
175 log.debug("Catched unparrot command") | |
176 txt_cmd = self.host.plugins[C.TEXT_CMDS] | |
177 | |
178 try: | |
179 link_left_jid = jid.JID(mess_data["unparsed"].strip()) | |
180 if not link_left_jid.user or not link_left_jid.host: | |
181 raise jid.InvalidFormat | |
182 except jid.InvalidFormat: | |
183 txt_cmd.feed_back( | |
184 client, "Can't deactivate Parrot mode for invalid jid", mess_data | |
185 ) | |
186 return False | |
187 | |
188 link_right_jid = mess_data["to"] | |
189 | |
190 self.remove_parrot(client, link_left_jid) | |
191 self.remove_parrot(client, link_right_jid) | |
192 | |
193 txt_cmd.feed_back( | |
194 client, | |
195 "Parrot mode deactivated for {} and {}".format( | |
196 str(link_left_jid), str(link_right_jid) | |
197 ), | |
198 mess_data, | |
199 ) | |
200 | |
201 return False |