Mercurial > libervia-backend
comparison sat/plugins/plugin_xep_0045.py @ 4037:524856bd7b19
massive refactoring to switch from camelCase to snake_case:
historically, Libervia (SàT before) was using camelCase as allowed by PEP8 when using a
pre-PEP8 code, to use the same coding style as in Twisted.
However, snake_case is more readable and it's better to follow PEP8 best practices, so it
has been decided to move on full snake_case. Because Libervia has a huge codebase, this
ended with a ugly mix of camelCase and snake_case.
To fix that, this patch does a big refactoring by renaming every function and method
(including bridge) that are not coming from Twisted or Wokkel, to use fully snake_case.
This is a massive change, and may result in some bugs.
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 08 Apr 2023 13:54:42 +0200 |
parents | 32d714a8ea51 |
children | c23cad65ae99 |
comparison
equal
deleted
inserted
replaced
4036:c4464d7ae97b | 4037:524856bd7b19 |
---|---|
85 | 85 |
86 def __init__(self, host): | 86 def __init__(self, host): |
87 log.info(_("Plugin XEP_0045 initialization")) | 87 log.info(_("Plugin XEP_0045 initialization")) |
88 self.host = host | 88 self.host = host |
89 self._sessions = memory.Sessions() | 89 self._sessions = memory.Sessions() |
90 # return same arguments as mucRoomJoined + a boolean set to True is the room was | 90 # return same arguments as muc_room_joined + a boolean set to True is the room was |
91 # already joined (first argument) | 91 # already joined (first argument) |
92 host.bridge.addMethod( | 92 host.bridge.add_method( |
93 "mucJoin", ".plugin", in_sign='ssa{ss}s', out_sign='(bsa{sa{ss}}ssass)', | 93 "muc_join", ".plugin", in_sign='ssa{ss}s', out_sign='(bsa{sa{ss}}ssass)', |
94 method=self._join, async_=True) | 94 method=self._join, async_=True) |
95 host.bridge.addMethod( | 95 host.bridge.add_method( |
96 "mucNick", ".plugin", in_sign='sss', out_sign='', method=self._nick) | 96 "muc_nick", ".plugin", in_sign='sss', out_sign='', method=self._nick) |
97 host.bridge.addMethod( | 97 host.bridge.add_method( |
98 "mucNickGet", ".plugin", in_sign='ss', out_sign='s', method=self._getRoomNick) | 98 "muc_nick_get", ".plugin", in_sign='ss', out_sign='s', method=self._get_room_nick) |
99 host.bridge.addMethod( | 99 host.bridge.add_method( |
100 "mucLeave", ".plugin", in_sign='ss', out_sign='', method=self._leave, | 100 "muc_leave", ".plugin", in_sign='ss', out_sign='', method=self._leave, |
101 async_=True) | 101 async_=True) |
102 host.bridge.addMethod( | 102 host.bridge.add_method( |
103 "mucOccupantsGet", ".plugin", in_sign='ss', out_sign='a{sa{ss}}', | 103 "muc_occupants_get", ".plugin", in_sign='ss', out_sign='a{sa{ss}}', |
104 method=self._getRoomOccupants) | 104 method=self._get_room_occupants) |
105 host.bridge.addMethod( | 105 host.bridge.add_method( |
106 "mucSubject", ".plugin", in_sign='sss', out_sign='', method=self._subject) | 106 "muc_subject", ".plugin", in_sign='sss', out_sign='', method=self._subject) |
107 host.bridge.addMethod( | 107 host.bridge.add_method( |
108 "mucGetRoomsJoined", ".plugin", in_sign='s', out_sign='a(sa{sa{ss}}ssas)', | 108 "muc_get_rooms_joined", ".plugin", in_sign='s', out_sign='a(sa{sa{ss}}ssas)', |
109 method=self._getRoomsJoined) | 109 method=self._get_rooms_joined) |
110 host.bridge.addMethod( | 110 host.bridge.add_method( |
111 "mucGetUniqueRoomName", ".plugin", in_sign='ss', out_sign='s', | 111 "muc_get_unique_room_name", ".plugin", in_sign='ss', out_sign='s', |
112 method=self._getUniqueName) | 112 method=self._get_unique_name) |
113 host.bridge.addMethod( | 113 host.bridge.add_method( |
114 "mucConfigureRoom", ".plugin", in_sign='ss', out_sign='s', | 114 "muc_configure_room", ".plugin", in_sign='ss', out_sign='s', |
115 method=self._configureRoom, async_=True) | 115 method=self._configure_room, async_=True) |
116 host.bridge.addMethod( | 116 host.bridge.add_method( |
117 "mucGetDefaultService", ".plugin", in_sign='', out_sign='s', | 117 "muc_get_default_service", ".plugin", in_sign='', out_sign='s', |
118 method=self.getDefaultMUC) | 118 method=self.get_default_muc) |
119 host.bridge.addMethod( | 119 host.bridge.add_method( |
120 "mucGetService", ".plugin", in_sign='ss', out_sign='s', | 120 "muc_get_service", ".plugin", in_sign='ss', out_sign='s', |
121 method=self._getMUCService, async_=True) | 121 method=self._get_muc_service, async_=True) |
122 # called when a room will be joined but must be locked until join is received | 122 # called when a room will be joined but must be locked until join is received |
123 # (room is prepared, history is getting retrieved) | 123 # (room is prepared, history is getting retrieved) |
124 # args: room_jid, profile | 124 # args: room_jid, profile |
125 host.bridge.addSignal( | 125 host.bridge.add_signal( |
126 "mucRoomPrepareJoin", ".plugin", signature='ss') | 126 "muc_room_prepare_join", ".plugin", signature='ss') |
127 # args: room_jid, occupants, user_nick, subject, profile | 127 # args: room_jid, occupants, user_nick, subject, profile |
128 host.bridge.addSignal( | 128 host.bridge.add_signal( |
129 "mucRoomJoined", ".plugin", signature='sa{sa{ss}}ssass') | 129 "muc_room_joined", ".plugin", signature='sa{sa{ss}}ssass') |
130 # args: room_jid, profile | 130 # args: room_jid, profile |
131 host.bridge.addSignal( | 131 host.bridge.add_signal( |
132 "mucRoomLeft", ".plugin", signature='ss') | 132 "muc_room_left", ".plugin", signature='ss') |
133 # args: room_jid, old_nick, new_nick, profile | 133 # args: room_jid, old_nick, new_nick, profile |
134 host.bridge.addSignal( | 134 host.bridge.add_signal( |
135 "mucRoomUserChangedNick", ".plugin", signature='ssss') | 135 "muc_room_user_changed_nick", ".plugin", signature='ssss') |
136 # args: room_jid, subject, profile | 136 # args: room_jid, subject, profile |
137 host.bridge.addSignal( | 137 host.bridge.add_signal( |
138 "mucRoomNewSubject", ".plugin", signature='sss') | 138 "muc_room_new_subject", ".plugin", signature='sss') |
139 self.__submit_conf_id = host.registerCallback( | 139 self.__submit_conf_id = host.register_callback( |
140 self._submitConfiguration, with_data=True) | 140 self._submit_configuration, with_data=True) |
141 self._room_join_id = host.registerCallback(self._UIRoomJoinCb, with_data=True) | 141 self._room_join_id = host.register_callback(self._ui_room_join_cb, with_data=True) |
142 host.importMenu( | 142 host.import_menu( |
143 (D_("MUC"), D_("configure")), self._configureRoomMenu, security_limit=0, | 143 (D_("MUC"), D_("configure")), self._configure_room_menu, security_limit=0, |
144 help_string=D_("Configure Multi-User Chat room"), type_=C.MENU_ROOM) | 144 help_string=D_("Configure Multi-User Chat room"), type_=C.MENU_ROOM) |
145 try: | 145 try: |
146 self.text_cmds = self.host.plugins[C.TEXT_CMDS] | 146 self.text_cmds = self.host.plugins[C.TEXT_CMDS] |
147 except KeyError: | 147 except KeyError: |
148 log.info(_("Text commands not available")) | 148 log.info(_("Text commands not available")) |
149 else: | 149 else: |
150 self.text_cmds.registerTextCommands(self) | 150 self.text_cmds.register_text_commands(self) |
151 self.text_cmds.addWhoIsCb(self._whois, 100) | 151 self.text_cmds.add_who_is_cb(self._whois, 100) |
152 | 152 |
153 self._mam = self.host.plugins.get("XEP-0313") | 153 self._mam = self.host.plugins.get("XEP-0313") |
154 self._si = self.host.plugins["XEP-0359"] | 154 self._si = self.host.plugins["XEP-0359"] |
155 | 155 |
156 host.trigger.add("presence_available", self.presenceTrigger) | 156 host.trigger.add("presence_available", self.presence_trigger) |
157 host.trigger.add("presence_received", self.presenceReceivedTrigger) | 157 host.trigger.add("presence_received", self.presence_received_trigger) |
158 host.trigger.add("messageReceived", self.messageReceivedTrigger, priority=1000000) | 158 host.trigger.add("messageReceived", self.message_received_trigger, priority=1000000) |
159 host.trigger.add("message_parse", self._message_parseTrigger) | 159 host.trigger.add("message_parse", self._message_parse_trigger) |
160 | 160 |
161 async def profileConnected(self, client): | 161 async def profile_connected(self, client): |
162 client.muc_service = await self.get_MUC_service(client) | 162 client.muc_service = await self.get_muc_service(client) |
163 | 163 |
164 def _message_parseTrigger(self, client, message_elt, data): | 164 def _message_parse_trigger(self, client, message_elt, data): |
165 """Add stanza-id from the room if present""" | 165 """Add stanza-id from the room if present""" |
166 if message_elt.getAttribute("type") != C.MESS_TYPE_GROUPCHAT: | 166 if message_elt.getAttribute("type") != C.MESS_TYPE_GROUPCHAT: |
167 return True | 167 return True |
168 | 168 |
169 # stanza_id will not be filled by parseMessage because the emitter | 169 # stanza_id will not be filled by parse_message because the emitter |
170 # is the room and not our server, so we have to parse it here | 170 # is the room and not our server, so we have to parse it here |
171 room_jid = data["from"].userhostJID() | 171 room_jid = data["from"].userhostJID() |
172 stanza_id = self._si.getStanzaId(message_elt, room_jid) | 172 stanza_id = self._si.get_stanza_id(message_elt, room_jid) |
173 if stanza_id: | 173 if stanza_id: |
174 data["extra"]["stanza_id"] = stanza_id | 174 data["extra"]["stanza_id"] = stanza_id |
175 | 175 |
176 def messageReceivedTrigger(self, client, message_elt, post_treat): | 176 def message_received_trigger(self, client, message_elt, post_treat): |
177 if message_elt.getAttribute("type") == C.MESS_TYPE_GROUPCHAT: | 177 if message_elt.getAttribute("type") == C.MESS_TYPE_GROUPCHAT: |
178 if message_elt.subject or message_elt.delay: | 178 if message_elt.subject or message_elt.delay: |
179 return False | 179 return False |
180 from_jid = jid.JID(message_elt['from']) | 180 from_jid = jid.JID(message_elt['from']) |
181 room_jid = from_jid.userhostJID() | 181 room_jid = from_jid.userhostJID() |
198 log.warning("Received groupchat message for a room which has not been " | 198 log.warning("Received groupchat message for a room which has not been " |
199 "joined, ignoring it: {}".format(message_elt.toXml())) | 199 "joined, ignoring it: {}".format(message_elt.toXml())) |
200 return False | 200 return False |
201 return True | 201 return True |
202 | 202 |
203 def getRoom(self, client: SatXMPPEntity, room_jid: jid.JID) -> muc.Room: | 203 def get_room(self, client: SatXMPPEntity, room_jid: jid.JID) -> muc.Room: |
204 """Retrieve Room instance from its jid | 204 """Retrieve Room instance from its jid |
205 | 205 |
206 @param room_jid: jid of the room | 206 @param room_jid: jid of the room |
207 @raise exceptions.NotFound: the room has not been joined | 207 @raise exceptions.NotFound: the room has not been joined |
208 """ | 208 """ |
209 try: | 209 try: |
210 return client._muc_client.joined_rooms[room_jid] | 210 return client._muc_client.joined_rooms[room_jid] |
211 except KeyError: | 211 except KeyError: |
212 raise exceptions.NotFound(_("This room has not been joined")) | 212 raise exceptions.NotFound(_("This room has not been joined")) |
213 | 213 |
214 def checkRoomJoined(self, client, room_jid): | 214 def check_room_joined(self, client, room_jid): |
215 """Check that given room has been joined in current session | 215 """Check that given room has been joined in current session |
216 | 216 |
217 @param room_jid (JID): room JID | 217 @param room_jid (JID): room JID |
218 """ | 218 """ |
219 if room_jid not in client._muc_client.joined_rooms: | 219 if room_jid not in client._muc_client.joined_rooms: |
220 raise exceptions.NotFound(_("This room has not been joined")) | 220 raise exceptions.NotFound(_("This room has not been joined")) |
221 | 221 |
222 def isJoinedRoom(self, client: SatXMPPEntity, room_jid: jid.JID) -> bool: | 222 def is_joined_room(self, client: SatXMPPEntity, room_jid: jid.JID) -> bool: |
223 """Tell if a jid is a known and joined room | 223 """Tell if a jid is a known and joined room |
224 | 224 |
225 @room_jid: jid of the room | 225 @room_jid: jid of the room |
226 """ | 226 """ |
227 try: | 227 try: |
228 self.checkRoomJoined(client, room_jid) | 228 self.check_room_joined(client, room_jid) |
229 except exceptions.NotFound: | 229 except exceptions.NotFound: |
230 return False | 230 return False |
231 else: | 231 else: |
232 return True | 232 return True |
233 | 233 |
234 def isRoom(self, client, entity_jid): | 234 def is_room(self, client, entity_jid): |
235 """Tell if a jid is a joined MUC | 235 """Tell if a jid is a joined MUC |
236 | 236 |
237 similar to isJoinedRoom but returns a boolean | 237 similar to is_joined_room but returns a boolean |
238 @param entity_jid(jid.JID): full or bare jid of the entity check | 238 @param entity_jid(jid.JID): full or bare jid of the entity check |
239 @return (bool): True if the bare jid of the entity is a room jid | 239 @return (bool): True if the bare jid of the entity is a room jid |
240 """ | 240 """ |
241 try: | 241 try: |
242 self.checkRoomJoined(client, entity_jid.userhostJID()) | 242 self.check_room_joined(client, entity_jid.userhostJID()) |
243 except exceptions.NotFound: | 243 except exceptions.NotFound: |
244 return False | 244 return False |
245 else: | 245 else: |
246 return True | 246 return True |
247 | 247 |
248 def getBareOrFull(self, client, peer_jid): | 248 def get_bare_or_full(self, client, peer_jid): |
249 """use full jid if peer_jid is an occupant of a room, bare jid else | 249 """use full jid if peer_jid is an occupant of a room, bare jid else |
250 | 250 |
251 @param peer_jid(jid.JID): entity to test | 251 @param peer_jid(jid.JID): entity to test |
252 @return (jid.JID): bare or full jid | 252 @return (jid.JID): bare or full jid |
253 """ | 253 """ |
254 if peer_jid.resource: | 254 if peer_jid.resource: |
255 if not self.isRoom(client, peer_jid): | 255 if not self.is_room(client, peer_jid): |
256 return peer_jid.userhostJID() | 256 return peer_jid.userhostJID() |
257 return peer_jid | 257 return peer_jid |
258 | 258 |
259 def _getRoomJoinedArgs(self, room, profile): | 259 def _get_room_joined_args(self, room, profile): |
260 return [ | 260 return [ |
261 room.roomJID.userhost(), | 261 room.roomJID.userhost(), |
262 XEP_0045._getOccupants(room), | 262 XEP_0045._get_occupants(room), |
263 room.nick, | 263 room.nick, |
264 room.subject, | 264 room.subject, |
265 [s.name for s in room.statuses], | 265 [s.name for s in room.statuses], |
266 profile | 266 profile |
267 ] | 267 ] |
268 | 268 |
269 def _UIRoomJoinCb(self, data, profile): | 269 def _ui_room_join_cb(self, data, profile): |
270 room_jid = jid.JID(data['index']) | 270 room_jid = jid.JID(data['index']) |
271 client = self.host.getClient(profile) | 271 client = self.host.get_client(profile) |
272 self.join(client, room_jid) | 272 self.join(client, room_jid) |
273 return {} | 273 return {} |
274 | 274 |
275 def _passwordUICb(self, data, client, room_jid, nick): | 275 def _password_ui_cb(self, data, client, room_jid, nick): |
276 """Called when the user has given room password (or cancelled)""" | 276 """Called when the user has given room password (or cancelled)""" |
277 if C.bool(data.get(C.XMLUI_DATA_CANCELLED, "false")): | 277 if C.bool(data.get(C.XMLUI_DATA_CANCELLED, "false")): |
278 log.info("room join for {} is cancelled".format(room_jid.userhost())) | 278 log.info("room join for {} is cancelled".format(room_jid.userhost())) |
279 raise failure.Failure(exceptions.CancelError(D_("Room joining cancelled by user"))) | 279 raise failure.Failure(exceptions.CancelError(D_("Room joining cancelled by user"))) |
280 password = data[xml_tools.formEscape('password')] | 280 password = data[xml_tools.form_escape('password')] |
281 return client._muc_client.join(room_jid, nick, password).addCallbacks(self._joinCb, self._joinEb, (client, room_jid, nick), errbackArgs=(client, room_jid, nick, password)) | 281 return client._muc_client.join(room_jid, nick, password).addCallbacks(self._join_cb, self._join_eb, (client, room_jid, nick), errbackArgs=(client, room_jid, nick, password)) |
282 | 282 |
283 def _showListUI(self, items, client, service): | 283 def _show_list_ui(self, items, client, service): |
284 xmlui = xml_tools.XMLUI(title=D_('Rooms in {}'.format(service.full()))) | 284 xmlui = xml_tools.XMLUI(title=D_('Rooms in {}'.format(service.full()))) |
285 adv_list = xmlui.changeContainer('advanced_list', columns=1, selectable='single', callback_id=self._room_join_id) | 285 adv_list = xmlui.change_container('advanced_list', columns=1, selectable='single', callback_id=self._room_join_id) |
286 items = sorted(items, key=lambda i: i.name.lower()) | 286 items = sorted(items, key=lambda i: i.name.lower()) |
287 for item in items: | 287 for item in items: |
288 adv_list.setRowIndex(item.entity.full()) | 288 adv_list.set_row_index(item.entity.full()) |
289 xmlui.addText(item.name) | 289 xmlui.addText(item.name) |
290 adv_list.end() | 290 adv_list.end() |
291 self.host.actionNew({'xmlui': xmlui.toXml()}, profile=client.profile) | 291 self.host.action_new({'xmlui': xmlui.toXml()}, profile=client.profile) |
292 | 292 |
293 def _joinCb(self, room, client, room_jid, nick): | 293 def _join_cb(self, room, client, room_jid, nick): |
294 """Called when the user is in the requested room""" | 294 """Called when the user is in the requested room""" |
295 if room.locked: | 295 if room.locked: |
296 # FIXME: the current behaviour is to create an instant room | 296 # FIXME: the current behaviour is to create an instant room |
297 # and send the signal only when the room is unlocked | 297 # and send the signal only when the room is unlocked |
298 # a proper configuration management should be done | 298 # a proper configuration management should be done |
299 log.debug(_("room locked !")) | 299 log.debug(_("room locked !")) |
300 d = client._muc_client.configure(room.roomJID, {}) | 300 d = client._muc_client.configure(room.roomJID, {}) |
301 d.addErrback(self.host.logErrback, | 301 d.addErrback(self.host.log_errback, |
302 msg=_('Error while configuring the room: {failure_}')) | 302 msg=_('Error while configuring the room: {failure_}')) |
303 return room.fully_joined | 303 return room.fully_joined |
304 | 304 |
305 def _joinEb(self, failure_, client, room_jid, nick, password): | 305 def _join_eb(self, failure_, client, room_jid, nick, password): |
306 """Called when something is going wrong when joining the room""" | 306 """Called when something is going wrong when joining the room""" |
307 try: | 307 try: |
308 condition = failure_.value.condition | 308 condition = failure_.value.condition |
309 except AttributeError: | 309 except AttributeError: |
310 msg_suffix = f': {failure_}' | 310 msg_suffix = f': {failure_}' |
311 else: | 311 else: |
312 if condition == 'conflict': | 312 if condition == 'conflict': |
313 # we have a nickname conflict, we try again with "_" suffixed to current nickname | 313 # we have a nickname conflict, we try again with "_" suffixed to current nickname |
314 nick += '_' | 314 nick += '_' |
315 return client._muc_client.join(room_jid, nick, password).addCallbacks(self._joinCb, self._joinEb, (client, room_jid, nick), errbackArgs=(client, room_jid, nick, password)) | 315 return client._muc_client.join(room_jid, nick, password).addCallbacks(self._join_cb, self._join_eb, (client, room_jid, nick), errbackArgs=(client, room_jid, nick, password)) |
316 elif condition == 'not-allowed': | 316 elif condition == 'not-allowed': |
317 # room is restricted, we need a password | 317 # room is restricted, we need a password |
318 password_ui = xml_tools.XMLUI("form", title=D_('Room {} is restricted').format(room_jid.userhost()), submit_id='') | 318 password_ui = xml_tools.XMLUI("form", title=D_('Room {} is restricted').format(room_jid.userhost()), submit_id='') |
319 password_ui.addText(D_("This room is restricted, please enter the password")) | 319 password_ui.addText(D_("This room is restricted, please enter the password")) |
320 password_ui.addPassword('password') | 320 password_ui.addPassword('password') |
321 d = xml_tools.deferXMLUI(self.host, password_ui, profile=client.profile) | 321 d = xml_tools.defer_xmlui(self.host, password_ui, profile=client.profile) |
322 d.addCallback(self._passwordUICb, client, room_jid, nick) | 322 d.addCallback(self._password_ui_cb, client, room_jid, nick) |
323 return d | 323 return d |
324 | 324 |
325 msg_suffix = ' with condition "{}"'.format(failure_.value.condition) | 325 msg_suffix = ' with condition "{}"'.format(failure_.value.condition) |
326 | 326 |
327 mess = D_("Error while joining the room {room}{suffix}".format( | 327 mess = D_("Error while joining the room {room}{suffix}".format( |
328 room = room_jid.userhost(), suffix = msg_suffix)) | 328 room = room_jid.userhost(), suffix = msg_suffix)) |
329 log.warning(mess) | 329 log.warning(mess) |
330 xmlui = xml_tools.note(mess, D_("Group chat error"), level=C.XMLUI_DATA_LVL_ERROR) | 330 xmlui = xml_tools.note(mess, D_("Group chat error"), level=C.XMLUI_DATA_LVL_ERROR) |
331 self.host.actionNew({'xmlui': xmlui.toXml()}, profile=client.profile) | 331 self.host.action_new({'xmlui': xmlui.toXml()}, profile=client.profile) |
332 | 332 |
333 @staticmethod | 333 @staticmethod |
334 def _getOccupants(room): | 334 def _get_occupants(room): |
335 """Get occupants of a room in a form suitable for bridge""" | 335 """Get occupants of a room in a form suitable for bridge""" |
336 return {u.nick: {k:str(getattr(u,k) or '') for k in OCCUPANT_KEYS} for u in list(room.roster.values())} | 336 return {u.nick: {k:str(getattr(u,k) or '') for k in OCCUPANT_KEYS} for u in list(room.roster.values())} |
337 | 337 |
338 def _getRoomOccupants(self, room_jid_s, profile_key): | 338 def _get_room_occupants(self, room_jid_s, profile_key): |
339 client = self.host.getClient(profile_key) | 339 client = self.host.get_client(profile_key) |
340 room_jid = jid.JID(room_jid_s) | 340 room_jid = jid.JID(room_jid_s) |
341 return self.getRoomOccupants(client, room_jid) | 341 return self.get_room_occupants(client, room_jid) |
342 | 342 |
343 def getRoomOccupants(self, client, room_jid): | 343 def get_room_occupants(self, client, room_jid): |
344 room = self.getRoom(client, room_jid) | 344 room = self.get_room(client, room_jid) |
345 return self._getOccupants(room) | 345 return self._get_occupants(room) |
346 | 346 |
347 def _getRoomsJoined(self, profile_key=C.PROF_KEY_NONE): | 347 def _get_rooms_joined(self, profile_key=C.PROF_KEY_NONE): |
348 client = self.host.getClient(profile_key) | 348 client = self.host.get_client(profile_key) |
349 return self.getRoomsJoined(client) | 349 return self.get_rooms_joined(client) |
350 | 350 |
351 def getRoomsJoined(self, client): | 351 def get_rooms_joined(self, client): |
352 """Return rooms where user is""" | 352 """Return rooms where user is""" |
353 result = [] | 353 result = [] |
354 for room in list(client._muc_client.joined_rooms.values()): | 354 for room in list(client._muc_client.joined_rooms.values()): |
355 if room.state == ROOM_STATE_LIVE: | 355 if room.state == ROOM_STATE_LIVE: |
356 result.append( | 356 result.append( |
357 (room.roomJID.userhost(), | 357 (room.roomJID.userhost(), |
358 self._getOccupants(room), | 358 self._get_occupants(room), |
359 room.nick, | 359 room.nick, |
360 room.subject, | 360 room.subject, |
361 [s.name for s in room.statuses], | 361 [s.name for s in room.statuses], |
362 ) | 362 ) |
363 ) | 363 ) |
364 return result | 364 return result |
365 | 365 |
366 def _getRoomNick(self, room_jid_s, profile_key=C.PROF_KEY_NONE): | 366 def _get_room_nick(self, room_jid_s, profile_key=C.PROF_KEY_NONE): |
367 client = self.host.getClient(profile_key) | 367 client = self.host.get_client(profile_key) |
368 return self.getRoomNick(client, jid.JID(room_jid_s)) | 368 return self.get_room_nick(client, jid.JID(room_jid_s)) |
369 | 369 |
370 def getRoomNick(self, client, room_jid): | 370 def get_room_nick(self, client, room_jid): |
371 """return nick used in room by user | 371 """return nick used in room by user |
372 | 372 |
373 @param room_jid (jid.JID): JID of the room | 373 @param room_jid (jid.JID): JID of the room |
374 @profile_key: profile | 374 @profile_key: profile |
375 @return: nick or empty string in case of error | 375 @return: nick or empty string in case of error |
376 @raise exceptions.Notfound: use has not joined the room | 376 @raise exceptions.Notfound: use has not joined the room |
377 """ | 377 """ |
378 self.checkRoomJoined(client, room_jid) | 378 self.check_room_joined(client, room_jid) |
379 return client._muc_client.joined_rooms[room_jid].nick | 379 return client._muc_client.joined_rooms[room_jid].nick |
380 | 380 |
381 def _configureRoom(self, room_jid_s, profile_key=C.PROF_KEY_NONE): | 381 def _configure_room(self, room_jid_s, profile_key=C.PROF_KEY_NONE): |
382 client = self.host.getClient(profile_key) | 382 client = self.host.get_client(profile_key) |
383 d = self.configureRoom(client, jid.JID(room_jid_s)) | 383 d = self.configure_room(client, jid.JID(room_jid_s)) |
384 d.addCallback(lambda xmlui: xmlui.toXml()) | 384 d.addCallback(lambda xmlui: xmlui.toXml()) |
385 return d | 385 return d |
386 | 386 |
387 def _configureRoomMenu(self, menu_data, profile): | 387 def _configure_room_menu(self, menu_data, profile): |
388 """Return room configuration form | 388 """Return room configuration form |
389 | 389 |
390 @param menu_data: %(menu_data)s | 390 @param menu_data: %(menu_data)s |
391 @param profile: %(doc_profile)s | 391 @param profile: %(doc_profile)s |
392 """ | 392 """ |
393 client = self.host.getClient(profile) | 393 client = self.host.get_client(profile) |
394 try: | 394 try: |
395 room_jid = jid.JID(menu_data['room_jid']) | 395 room_jid = jid.JID(menu_data['room_jid']) |
396 except KeyError: | 396 except KeyError: |
397 log.error(_("room_jid key is not present !")) | 397 log.error(_("room_jid key is not present !")) |
398 return defer.fail(exceptions.DataError) | 398 return defer.fail(exceptions.DataError) |
399 | 399 |
400 def xmluiReceived(xmlui): | 400 def xmlui_received(xmlui): |
401 if not xmlui: | 401 if not xmlui: |
402 msg = D_("No configuration available for this room") | 402 msg = D_("No configuration available for this room") |
403 return {"xmlui": xml_tools.note(msg).toXml()} | 403 return {"xmlui": xml_tools.note(msg).toXml()} |
404 return {"xmlui": xmlui.toXml()} | 404 return {"xmlui": xmlui.toXml()} |
405 return self.configureRoom(client, room_jid).addCallback(xmluiReceived) | 405 return self.configure_room(client, room_jid).addCallback(xmlui_received) |
406 | 406 |
407 def configureRoom(self, client, room_jid): | 407 def configure_room(self, client, room_jid): |
408 """return the room configuration form | 408 """return the room configuration form |
409 | 409 |
410 @param room: jid of the room to configure | 410 @param room: jid of the room to configure |
411 @return: configuration form as XMLUI | 411 @return: configuration form as XMLUI |
412 """ | 412 """ |
413 self.checkRoomJoined(client, room_jid) | 413 self.check_room_joined(client, room_jid) |
414 | 414 |
415 def config2XMLUI(result): | 415 def config_2_xmlui(result): |
416 if not result: | 416 if not result: |
417 return "" | 417 return "" |
418 session_id, session_data = self._sessions.newSession(profile=client.profile) | 418 session_id, session_data = self._sessions.new_session(profile=client.profile) |
419 session_data["room_jid"] = room_jid | 419 session_data["room_jid"] = room_jid |
420 xmlui = xml_tools.dataForm2XMLUI(result, submit_id=self.__submit_conf_id) | 420 xmlui = xml_tools.data_form_2_xmlui(result, submit_id=self.__submit_conf_id) |
421 xmlui.session_id = session_id | 421 xmlui.session_id = session_id |
422 return xmlui | 422 return xmlui |
423 | 423 |
424 d = client._muc_client.getConfiguration(room_jid) | 424 d = client._muc_client.getConfiguration(room_jid) |
425 d.addCallback(config2XMLUI) | 425 d.addCallback(config_2_xmlui) |
426 return d | 426 return d |
427 | 427 |
428 def _submitConfiguration(self, raw_data, profile): | 428 def _submit_configuration(self, raw_data, profile): |
429 cancelled = C.bool(raw_data.get("cancelled", C.BOOL_FALSE)) | 429 cancelled = C.bool(raw_data.get("cancelled", C.BOOL_FALSE)) |
430 if cancelled: | 430 if cancelled: |
431 return defer.succeed({}) | 431 return defer.succeed({}) |
432 client = self.host.getClient(profile) | 432 client = self.host.get_client(profile) |
433 try: | 433 try: |
434 session_data = self._sessions.profileGet(raw_data["session_id"], profile) | 434 session_data = self._sessions.profile_get(raw_data["session_id"], profile) |
435 except KeyError: | 435 except KeyError: |
436 log.warning(D_("Session ID doesn't exist, session has probably expired.")) | 436 log.warning(D_("Session ID doesn't exist, session has probably expired.")) |
437 _dialog = xml_tools.XMLUI('popup', title=D_('Room configuration failed')) | 437 _dialog = xml_tools.XMLUI('popup', title=D_('Room configuration failed')) |
438 _dialog.addText(D_("Session ID doesn't exist, session has probably expired.")) | 438 _dialog.addText(D_("Session ID doesn't exist, session has probably expired.")) |
439 return defer.succeed({'xmlui': _dialog.toXml()}) | 439 return defer.succeed({'xmlui': _dialog.toXml()}) |
440 | 440 |
441 data = xml_tools.XMLUIResult2DataFormResult(raw_data) | 441 data = xml_tools.xmlui_result_2_data_form_result(raw_data) |
442 d = client._muc_client.configure(session_data['room_jid'], data) | 442 d = client._muc_client.configure(session_data['room_jid'], data) |
443 _dialog = xml_tools.XMLUI('popup', title=D_('Room configuration succeed')) | 443 _dialog = xml_tools.XMLUI('popup', title=D_('Room configuration succeed')) |
444 _dialog.addText(D_("The new settings have been saved.")) | 444 _dialog.addText(D_("The new settings have been saved.")) |
445 d.addCallback(lambda ignore: {'xmlui': _dialog.toXml()}) | 445 d.addCallback(lambda ignore: {'xmlui': _dialog.toXml()}) |
446 del self._sessions[raw_data["session_id"]] | 446 del self._sessions[raw_data["session_id"]] |
447 return d | 447 return d |
448 | 448 |
449 def isNickInRoom(self, client, room_jid, nick): | 449 def is_nick_in_room(self, client, room_jid, nick): |
450 """Tell if a nick is currently present in a room""" | 450 """Tell if a nick is currently present in a room""" |
451 self.checkRoomJoined(client, room_jid) | 451 self.check_room_joined(client, room_jid) |
452 return client._muc_client.joined_rooms[room_jid].inRoster(muc.User(nick)) | 452 return client._muc_client.joined_rooms[room_jid].inRoster(muc.User(nick)) |
453 | 453 |
454 def _getMUCService(self, jid_=None, profile=C.PROF_KEY_NONE): | 454 def _get_muc_service(self, jid_=None, profile=C.PROF_KEY_NONE): |
455 client = self.host.getClient(profile) | 455 client = self.host.get_client(profile) |
456 d = defer.ensureDeferred(self.get_MUC_service(client, jid_ or None)) | 456 d = defer.ensureDeferred(self.get_muc_service(client, jid_ or None)) |
457 d.addCallback(lambda service_jid: service_jid.full() if service_jid is not None else '') | 457 d.addCallback(lambda service_jid: service_jid.full() if service_jid is not None else '') |
458 return d | 458 return d |
459 | 459 |
460 async def get_MUC_service( | 460 async def get_muc_service( |
461 self, | 461 self, |
462 client: SatXMPPEntity, | 462 client: SatXMPPEntity, |
463 jid_: Optional[jid.JID] = None) -> Optional[jid.JID]: | 463 jid_: Optional[jid.JID] = None) -> Optional[jid.JID]: |
464 """Return first found MUC service of an entity | 464 """Return first found MUC service of an entity |
465 | 465 |
472 except AttributeError: | 472 except AttributeError: |
473 pass | 473 pass |
474 else: | 474 else: |
475 # we have a cached value, we return it | 475 # we have a cached value, we return it |
476 return muc_service | 476 return muc_service |
477 services = await self.host.findServiceEntities(client, "conference", "text", jid_) | 477 services = await self.host.find_service_entities(client, "conference", "text", jid_) |
478 for service in services: | 478 for service in services: |
479 if ".irc." not in service.userhost(): | 479 if ".irc." not in service.userhost(): |
480 # FIXME: | 480 # FIXME: |
481 # This ugly hack is here to avoid an issue with openfire: the IRC gateway | 481 # This ugly hack is here to avoid an issue with openfire: the IRC gateway |
482 # use "conference/text" identity (instead of "conference/irc") | 482 # use "conference/text" identity (instead of "conference/irc") |
484 break | 484 break |
485 else: | 485 else: |
486 muc_service = None | 486 muc_service = None |
487 return muc_service | 487 return muc_service |
488 | 488 |
489 def _getUniqueName(self, muc_service="", profile_key=C.PROF_KEY_NONE): | 489 def _get_unique_name(self, muc_service="", profile_key=C.PROF_KEY_NONE): |
490 client = self.host.getClient(profile_key) | 490 client = self.host.get_client(profile_key) |
491 return self.getUniqueName(client, muc_service or None).full() | 491 return self.get_unique_name(client, muc_service or None).full() |
492 | 492 |
493 def getUniqueName(self, client, muc_service=None): | 493 def get_unique_name(self, client, muc_service=None): |
494 """Return unique name for a room, avoiding collision | 494 """Return unique name for a room, avoiding collision |
495 | 495 |
496 @param muc_service (jid.JID) : leave empty string to use the default service | 496 @param muc_service (jid.JID) : leave empty string to use the default service |
497 @return: jid.JID (unique room bare JID) | 497 @return: jid.JID (unique room bare JID) |
498 """ | 498 """ |
508 raise exceptions.FeatureNotFound | 508 raise exceptions.FeatureNotFound |
509 | 509 |
510 muc_service = muc_service.userhost() | 510 muc_service = muc_service.userhost() |
511 return jid.JID("{}@{}".format(room_name, muc_service)) | 511 return jid.JID("{}@{}".format(room_name, muc_service)) |
512 | 512 |
513 def getDefaultMUC(self): | 513 def get_default_muc(self): |
514 """Return the default MUC. | 514 """Return the default MUC. |
515 | 515 |
516 @return: unicode | 516 @return: unicode |
517 """ | 517 """ |
518 return self.host.memory.getConfig(CONFIG_SECTION, 'default_muc', default_conf['default_muc']) | 518 return self.host.memory.config_get(CONFIG_SECTION, 'default_muc', default_conf['default_muc']) |
519 | 519 |
520 def _join_eb(self, failure_, client): | 520 def _join_eb(self, failure_, client): |
521 failure_.trap(AlreadyJoined) | 521 failure_.trap(AlreadyJoined) |
522 room = failure_.value.room | 522 room = failure_.value.room |
523 return [True] + self._getRoomJoinedArgs(room, client.profile) | 523 return [True] + self._get_room_joined_args(room, client.profile) |
524 | 524 |
525 def _join(self, room_jid_s, nick, options, profile_key=C.PROF_KEY_NONE): | 525 def _join(self, room_jid_s, nick, options, profile_key=C.PROF_KEY_NONE): |
526 """join method used by bridge | 526 """join method used by bridge |
527 | 527 |
528 @return (tuple): already_joined boolean + room joined arguments (see [_getRoomJoinedArgs]) | 528 @return (tuple): already_joined boolean + room joined arguments (see [_get_room_joined_args]) |
529 """ | 529 """ |
530 client = self.host.getClient(profile_key) | 530 client = self.host.get_client(profile_key) |
531 if room_jid_s: | 531 if room_jid_s: |
532 muc_service = client.muc_service | 532 muc_service = client.muc_service |
533 try: | 533 try: |
534 room_jid = jid.JID(room_jid_s) | 534 room_jid = jid.JID(room_jid_s) |
535 except (RuntimeError, jid.InvalidFormat, AttributeError): | 535 except (RuntimeError, jid.InvalidFormat, AttributeError): |
537 room_id=room_jid_s, | 537 room_id=room_jid_s, |
538 muc_service=str(muc_service)))) | 538 muc_service=str(muc_service)))) |
539 if not room_jid.user: | 539 if not room_jid.user: |
540 room_jid.user, room_jid.host = room_jid.host, muc_service | 540 room_jid.user, room_jid.host = room_jid.host, muc_service |
541 else: | 541 else: |
542 room_jid = self.getUniqueName(profile_key=client.profile) | 542 room_jid = self.get_unique_name(profile_key=client.profile) |
543 # TODO: error management + signal in bridge | 543 # TODO: error management + signal in bridge |
544 d = self.join(client, room_jid, nick, options or None) | 544 d = self.join(client, room_jid, nick, options or None) |
545 d.addCallback(lambda room: [False] + self._getRoomJoinedArgs(room, client.profile)) | 545 d.addCallback(lambda room: [False] + self._get_room_joined_args(room, client.profile)) |
546 d.addErrback(self._join_eb, client) | 546 d.addErrback(self._join_eb, client) |
547 return d | 547 return d |
548 | 548 |
549 async def join( | 549 async def join( |
550 self, | 550 self, |
562 log.info(_('{profile} is already in room {room_jid}').format( | 562 log.info(_('{profile} is already in room {room_jid}').format( |
563 profile=client.profile, room_jid = room_jid.userhost())) | 563 profile=client.profile, room_jid = room_jid.userhost())) |
564 raise AlreadyJoined(room) | 564 raise AlreadyJoined(room) |
565 log.info(_("[{profile}] is joining room {room} with nick {nick}").format( | 565 log.info(_("[{profile}] is joining room {room} with nick {nick}").format( |
566 profile=client.profile, room=room_jid.userhost(), nick=nick)) | 566 profile=client.profile, room=room_jid.userhost(), nick=nick)) |
567 self.host.bridge.mucRoomPrepareJoin(room_jid.userhost(), client.profile) | 567 self.host.bridge.muc_room_prepare_join(room_jid.userhost(), client.profile) |
568 | 568 |
569 password = options.get("password") | 569 password = options.get("password") |
570 | 570 |
571 try: | 571 try: |
572 room = await client._muc_client.join(room_jid, nick, password) | 572 room = await client._muc_client.join(room_jid, nick, password) |
573 except Exception as e: | 573 except Exception as e: |
574 room = await utils.asDeferred( | 574 room = await utils.as_deferred( |
575 self._joinEb(failure.Failure(e), client, room_jid, nick, password) | 575 self._join_eb(failure.Failure(e), client, room_jid, nick, password) |
576 ) | 576 ) |
577 else: | 577 else: |
578 await defer.ensureDeferred( | 578 await defer.ensureDeferred( |
579 self._joinCb(room, client, room_jid, nick) | 579 self._join_cb(room, client, room_jid, nick) |
580 ) | 580 ) |
581 return room | 581 return room |
582 | 582 |
583 def popRooms(self, client): | 583 def pop_rooms(self, client): |
584 """Remove rooms and return data needed to re-join them | 584 """Remove rooms and return data needed to re-join them |
585 | 585 |
586 This methods is to be called before a hot reconnection | 586 This methods is to be called before a hot reconnection |
587 @return (list[(jid.JID, unicode)]): arguments needed to re-join the rooms | 587 @return (list[(jid.JID, unicode)]): arguments needed to re-join the rooms |
588 This list can be used directly (unpacked) with self.join | 588 This list can be used directly (unpacked) with self.join |
592 client._muc_client._removeRoom(room.roomJID) | 592 client._muc_client._removeRoom(room.roomJID) |
593 args_list.append((client, room.roomJID, room.nick)) | 593 args_list.append((client, room.roomJID, room.nick)) |
594 return args_list | 594 return args_list |
595 | 595 |
596 def _nick(self, room_jid_s, nick, profile_key=C.PROF_KEY_NONE): | 596 def _nick(self, room_jid_s, nick, profile_key=C.PROF_KEY_NONE): |
597 client = self.host.getClient(profile_key) | 597 client = self.host.get_client(profile_key) |
598 return self.nick(client, jid.JID(room_jid_s), nick) | 598 return self.nick(client, jid.JID(room_jid_s), nick) |
599 | 599 |
600 def nick(self, client, room_jid, nick): | 600 def nick(self, client, room_jid, nick): |
601 """Change nickname in a room""" | 601 """Change nickname in a room""" |
602 self.checkRoomJoined(client, room_jid) | 602 self.check_room_joined(client, room_jid) |
603 return client._muc_client.nick(room_jid, nick) | 603 return client._muc_client.nick(room_jid, nick) |
604 | 604 |
605 def _leave(self, room_jid, profile_key): | 605 def _leave(self, room_jid, profile_key): |
606 client = self.host.getClient(profile_key) | 606 client = self.host.get_client(profile_key) |
607 return self.leave(client, jid.JID(room_jid)) | 607 return self.leave(client, jid.JID(room_jid)) |
608 | 608 |
609 def leave(self, client, room_jid): | 609 def leave(self, client, room_jid): |
610 self.checkRoomJoined(client, room_jid) | 610 self.check_room_joined(client, room_jid) |
611 return client._muc_client.leave(room_jid) | 611 return client._muc_client.leave(room_jid) |
612 | 612 |
613 def _subject(self, room_jid_s, new_subject, profile_key): | 613 def _subject(self, room_jid_s, new_subject, profile_key): |
614 client = self.host.getClient(profile_key) | 614 client = self.host.get_client(profile_key) |
615 return self.subject(client, jid.JID(room_jid_s), new_subject) | 615 return self.subject(client, jid.JID(room_jid_s), new_subject) |
616 | 616 |
617 def subject(self, client, room_jid, subject): | 617 def subject(self, client, room_jid, subject): |
618 self.checkRoomJoined(client, room_jid) | 618 self.check_room_joined(client, room_jid) |
619 return client._muc_client.subject(room_jid, subject) | 619 return client._muc_client.subject(room_jid, subject) |
620 | 620 |
621 def getHandler(self, client): | 621 def get_handler(self, client): |
622 # create a MUC client and associate it with profile' session | 622 # create a MUC client and associate it with profile' session |
623 muc_client = client._muc_client = LiberviaMUCClient(self) | 623 muc_client = client._muc_client = LiberviaMUCClient(self) |
624 return muc_client | 624 return muc_client |
625 | 625 |
626 def kick(self, client, nick, room_jid, options=None): | 626 def kick(self, client, nick, room_jid, options=None): |
630 @param room_jid_s (JID): jid of the room | 630 @param room_jid_s (JID): jid of the room |
631 @param options (dict): attribute with extra info (reason, password) as in #XEP-0045 | 631 @param options (dict): attribute with extra info (reason, password) as in #XEP-0045 |
632 """ | 632 """ |
633 if options is None: | 633 if options is None: |
634 options = {} | 634 options = {} |
635 self.checkRoomJoined(client, room_jid) | 635 self.check_room_joined(client, room_jid) |
636 return client._muc_client.kick(room_jid, nick, reason=options.get('reason', None)) | 636 return client._muc_client.kick(room_jid, nick, reason=options.get('reason', None)) |
637 | 637 |
638 def ban(self, client, entity_jid, room_jid, options=None): | 638 def ban(self, client, entity_jid, room_jid, options=None): |
639 """Ban an entity from the room | 639 """Ban an entity from the room |
640 | 640 |
641 @param entity_jid (JID): bare jid of the entity to be banned | 641 @param entity_jid (JID): bare jid of the entity to be banned |
642 @param room_jid (JID): jid of the room | 642 @param room_jid (JID): jid of the room |
643 @param options: attribute with extra info (reason, password) as in #XEP-0045 | 643 @param options: attribute with extra info (reason, password) as in #XEP-0045 |
644 """ | 644 """ |
645 self.checkRoomJoined(client, room_jid) | 645 self.check_room_joined(client, room_jid) |
646 if options is None: | 646 if options is None: |
647 options = {} | 647 options = {} |
648 assert not entity_jid.resource | 648 assert not entity_jid.resource |
649 assert not room_jid.resource | 649 assert not room_jid.resource |
650 return client._muc_client.ban(room_jid, entity_jid, reason=options.get('reason', None)) | 650 return client._muc_client.ban(room_jid, entity_jid, reason=options.get('reason', None)) |
654 | 654 |
655 @param entity_jid (JID): bare jid of the entity | 655 @param entity_jid (JID): bare jid of the entity |
656 @param room_jid_s (JID): jid of the room | 656 @param room_jid_s (JID): jid of the room |
657 @param options: attribute with extra info (reason, nick) as in #XEP-0045 | 657 @param options: attribute with extra info (reason, nick) as in #XEP-0045 |
658 """ | 658 """ |
659 self.checkRoomJoined(client, room_jid) | 659 self.check_room_joined(client, room_jid) |
660 assert not entity_jid.resource | 660 assert not entity_jid.resource |
661 assert not room_jid.resource | 661 assert not room_jid.resource |
662 assert 'affiliation' in options | 662 assert 'affiliation' in options |
663 # TODO: handles reason and nick | 663 # TODO: handles reason and nick |
664 return client._muc_client.modifyAffiliationList(room_jid, [entity_jid], options['affiliation']) | 664 return client._muc_client.modifyAffiliationList(room_jid, [entity_jid], options['affiliation']) |
684 @command (all): JID | 684 @command (all): JID |
685 - JID: room to join (on the same service if full jid is not specified) | 685 - JID: room to join (on the same service if full jid is not specified) |
686 """ | 686 """ |
687 room_raw = mess_data["unparsed"].strip() | 687 room_raw = mess_data["unparsed"].strip() |
688 if room_raw: | 688 if room_raw: |
689 if self.isJoinedRoom(client, mess_data["to"]): | 689 if self.is_joined_room(client, mess_data["to"]): |
690 # we use the same service as the one from the room where the command has | 690 # we use the same service as the one from the room where the command has |
691 # been entered if full jid is not entered | 691 # been entered if full jid is not entered |
692 muc_service = mess_data["to"].host | 692 muc_service = mess_data["to"].host |
693 nick = self.getRoomNick(client, mess_data["to"]) or client.jid.user | 693 nick = self.get_room_nick(client, mess_data["to"]) or client.jid.user |
694 else: | 694 else: |
695 # the command has been entered in a one2one conversation, so we use | 695 # the command has been entered in a one2one conversation, so we use |
696 # our server MUC service as default service | 696 # our server MUC service as default service |
697 muc_service = client.muc_service or "" | 697 muc_service = client.muc_service or "" |
698 nick = client.jid.user | 698 nick = client.jid.user |
699 room_jid = self.text_cmds.getRoomJID(room_raw, muc_service) | 699 room_jid = self.text_cmds.get_room_jid(room_raw, muc_service) |
700 self.join(client, room_jid, nick, {}) | 700 self.join(client, room_jid, nick, {}) |
701 | 701 |
702 return False | 702 return False |
703 | 703 |
704 def cmd_leave(self, client, mess_data): | 704 def cmd_leave(self, client, mess_data): |
707 @command (group): [ROOM_JID] | 707 @command (group): [ROOM_JID] |
708 - ROOM_JID: jid of the room to live (current room if not specified) | 708 - ROOM_JID: jid of the room to live (current room if not specified) |
709 """ | 709 """ |
710 room_raw = mess_data["unparsed"].strip() | 710 room_raw = mess_data["unparsed"].strip() |
711 if room_raw: | 711 if room_raw: |
712 room = self.text_cmds.getRoomJID(room_raw, mess_data["to"].host) | 712 room = self.text_cmds.get_room_jid(room_raw, mess_data["to"].host) |
713 else: | 713 else: |
714 room = mess_data["to"] | 714 room = mess_data["to"] |
715 | 715 |
716 self.leave(client, room) | 716 self.leave(client, room) |
717 | 717 |
732 - ROOM_NICK: the nick of the person to kick | 732 - ROOM_NICK: the nick of the person to kick |
733 """ | 733 """ |
734 options = mess_data["unparsed"].strip().split() | 734 options = mess_data["unparsed"].strip().split() |
735 try: | 735 try: |
736 nick = options[0] | 736 nick = options[0] |
737 assert self.isNickInRoom(client, mess_data["to"], nick) | 737 assert self.is_nick_in_room(client, mess_data["to"], nick) |
738 except (IndexError, AssertionError): | 738 except (IndexError, AssertionError): |
739 feedback = _("You must provide a member's nick to kick.") | 739 feedback = _("You must provide a member's nick to kick.") |
740 self.text_cmds.feedBack(client, feedback, mess_data) | 740 self.text_cmds.feed_back(client, feedback, mess_data) |
741 return False | 741 return False |
742 | 742 |
743 reason = ' '.join(options[1:]) if len(options) > 1 else None | 743 reason = ' '.join(options[1:]) if len(options) > 1 else None |
744 | 744 |
745 d = self.kick(client, nick, mess_data["to"], {"reason": reason}) | 745 d = self.kick(client, nick, mess_data["to"], {"reason": reason}) |
748 feedback_msg = _('You have kicked {}').format(nick) | 748 feedback_msg = _('You have kicked {}').format(nick) |
749 if reason is not None: | 749 if reason is not None: |
750 feedback_msg += _(' for the following reason: {reason}').format( | 750 feedback_msg += _(' for the following reason: {reason}').format( |
751 reason=reason | 751 reason=reason |
752 ) | 752 ) |
753 self.text_cmds.feedBack(client, feedback_msg, mess_data) | 753 self.text_cmds.feed_back(client, feedback_msg, mess_data) |
754 return True | 754 return True |
755 d.addCallback(cb) | 755 d.addCallback(cb) |
756 return d | 756 return d |
757 | 757 |
758 def cmd_ban(self, client, mess_data): | 758 def cmd_ban(self, client, mess_data): |
771 except (RuntimeError, jid.InvalidFormat, AttributeError, IndexError, | 771 except (RuntimeError, jid.InvalidFormat, AttributeError, IndexError, |
772 AssertionError): | 772 AssertionError): |
773 feedback = _( | 773 feedback = _( |
774 "You must provide a valid JID to ban, like in '/ban contact@example.net'" | 774 "You must provide a valid JID to ban, like in '/ban contact@example.net'" |
775 ) | 775 ) |
776 self.text_cmds.feedBack(client, feedback, mess_data) | 776 self.text_cmds.feed_back(client, feedback, mess_data) |
777 return False | 777 return False |
778 | 778 |
779 reason = ' '.join(options[1:]) if len(options) > 1 else None | 779 reason = ' '.join(options[1:]) if len(options) > 1 else None |
780 | 780 |
781 d = self.ban(client, entity_jid, mess_data["to"], {"reason": reason}) | 781 d = self.ban(client, entity_jid, mess_data["to"], {"reason": reason}) |
784 feedback_msg = _('You have banned {}').format(entity_jid) | 784 feedback_msg = _('You have banned {}').format(entity_jid) |
785 if reason is not None: | 785 if reason is not None: |
786 feedback_msg += _(' for the following reason: {reason}').format( | 786 feedback_msg += _(' for the following reason: {reason}').format( |
787 reason=reason | 787 reason=reason |
788 ) | 788 ) |
789 self.text_cmds.feedBack(client, feedback_msg, mess_data) | 789 self.text_cmds.feed_back(client, feedback_msg, mess_data) |
790 return True | 790 return True |
791 d.addCallback(cb) | 791 d.addCallback(cb) |
792 return d | 792 return d |
793 | 793 |
794 def cmd_affiliate(self, client, mess_data): | 794 def cmd_affiliate(self, client, mess_data): |
808 entity_jid = jid.JID(jid_s).userhostJID() | 808 entity_jid = jid.JID(jid_s).userhostJID() |
809 assert(entity_jid.user) | 809 assert(entity_jid.user) |
810 assert(entity_jid.host) | 810 assert(entity_jid.host) |
811 except (RuntimeError, jid.InvalidFormat, AttributeError, IndexError, AssertionError): | 811 except (RuntimeError, jid.InvalidFormat, AttributeError, IndexError, AssertionError): |
812 feedback = _("You must provide a valid JID to affiliate, like in '/affiliate contact@example.net member'") | 812 feedback = _("You must provide a valid JID to affiliate, like in '/affiliate contact@example.net member'") |
813 self.text_cmds.feedBack(client, feedback, mess_data) | 813 self.text_cmds.feed_back(client, feedback, mess_data) |
814 return False | 814 return False |
815 | 815 |
816 affiliation = options[1] if len(options) > 1 else 'none' | 816 affiliation = options[1] if len(options) > 1 else 'none' |
817 if affiliation not in AFFILIATIONS: | 817 if affiliation not in AFFILIATIONS: |
818 feedback = _("You must provide a valid affiliation: %s") % ' '.join(AFFILIATIONS) | 818 feedback = _("You must provide a valid affiliation: %s") % ' '.join(AFFILIATIONS) |
819 self.text_cmds.feedBack(client, feedback, mess_data) | 819 self.text_cmds.feed_back(client, feedback, mess_data) |
820 return False | 820 return False |
821 | 821 |
822 d = self.affiliate(client, entity_jid, mess_data["to"], {'affiliation': affiliation}) | 822 d = self.affiliate(client, entity_jid, mess_data["to"], {'affiliation': affiliation}) |
823 | 823 |
824 def cb(__): | 824 def cb(__): |
825 feedback_msg = _('New affiliation for {entity}: {affiliation}').format( | 825 feedback_msg = _('New affiliation for {entity}: {affiliation}').format( |
826 entity=entity_jid, affiliation=affiliation) | 826 entity=entity_jid, affiliation=affiliation) |
827 self.text_cmds.feedBack(client, feedback_msg, mess_data) | 827 self.text_cmds.feed_back(client, feedback_msg, mess_data) |
828 return True | 828 return True |
829 d.addCallback(cb) | 829 d.addCallback(cb) |
830 return d | 830 return d |
831 | 831 |
832 def cmd_title(self, client, mess_data): | 832 def cmd_title(self, client, mess_data): |
869 elif client.muc_service is not None: | 869 elif client.muc_service is not None: |
870 service = client.muc_service | 870 service = client.muc_service |
871 else: | 871 else: |
872 msg = D_("No known default MUC service {unparsed}").format( | 872 msg = D_("No known default MUC service {unparsed}").format( |
873 unparsed=unparsed) | 873 unparsed=unparsed) |
874 self.text_cmds.feedBack(client, msg, mess_data) | 874 self.text_cmds.feed_back(client, msg, mess_data) |
875 return False | 875 return False |
876 except jid.InvalidFormat: | 876 except jid.InvalidFormat: |
877 msg = D_("{} is not a valid JID!".format(unparsed)) | 877 msg = D_("{} is not a valid JID!".format(unparsed)) |
878 self.text_cmds.feedBack(client, msg, mess_data) | 878 self.text_cmds.feed_back(client, msg, mess_data) |
879 return False | 879 return False |
880 d = self.host.getDiscoItems(client, service) | 880 d = self.host.getDiscoItems(client, service) |
881 d.addCallback(self._showListUI, client, service) | 881 d.addCallback(self._show_list_ui, client, service) |
882 | 882 |
883 return False | 883 return False |
884 | 884 |
885 def _whois(self, client, whois_msg, mess_data, target_jid): | 885 def _whois(self, client, whois_msg, mess_data, target_jid): |
886 """ Add MUC user information to whois """ | 886 """ Add MUC user information to whois """ |
902 if user.status: | 902 if user.status: |
903 whois_msg.append(_("Status: %s") % user.status) | 903 whois_msg.append(_("Status: %s") % user.status) |
904 if user.show: | 904 if user.show: |
905 whois_msg.append(_("Show: %s") % user.show) | 905 whois_msg.append(_("Show: %s") % user.show) |
906 | 906 |
907 def presenceTrigger(self, presence_elt, client): | 907 def presence_trigger(self, presence_elt, client): |
908 # FIXME: should we add a privacy parameters in settings to activate before | 908 # FIXME: should we add a privacy parameters in settings to activate before |
909 # broadcasting the presence to all MUC rooms ? | 909 # broadcasting the presence to all MUC rooms ? |
910 muc_client = client._muc_client | 910 muc_client = client._muc_client |
911 for room_jid, room in muc_client.joined_rooms.items(): | 911 for room_jid, room in muc_client.joined_rooms.items(): |
912 elt = xml_tools.elementCopy(presence_elt) | 912 elt = xml_tools.element_copy(presence_elt) |
913 elt['to'] = room_jid.userhost() + '/' + room.nick | 913 elt['to'] = room_jid.userhost() + '/' + room.nick |
914 client.presence.send(elt) | 914 client.presence.send(elt) |
915 return True | 915 return True |
916 | 916 |
917 def presenceReceivedTrigger(self, client, entity, show, priority, statuses): | 917 def presence_received_trigger(self, client, entity, show, priority, statuses): |
918 entity_bare = entity.userhostJID() | 918 entity_bare = entity.userhostJID() |
919 muc_client = client._muc_client | 919 muc_client = client._muc_client |
920 if entity_bare in muc_client.joined_rooms: | 920 if entity_bare in muc_client.joined_rooms: |
921 # presence is already handled in (un)availableReceived | 921 # presence is already handled in (un)availableReceived |
922 return False | 922 return False |
951 | 951 |
952 @property | 952 @property |
953 def _si(self): | 953 def _si(self): |
954 return self.plugin_parent._si | 954 return self.plugin_parent._si |
955 | 955 |
956 def changeRoomState(self, room, new_state): | 956 def change_room_state(self, room, new_state): |
957 """Check that room is in expected state, and change it | 957 """Check that room is in expected state, and change it |
958 | 958 |
959 @param new_state: one of ROOM_STATE_* | 959 @param new_state: one of ROOM_STATE_* |
960 """ | 960 """ |
961 new_state_idx = ROOM_STATES.index(new_state) | 961 new_state_idx = ROOM_STATES.index(new_state) |
993 room_jid: jid.JID, | 993 room_jid: jid.JID, |
994 nick: str, | 994 nick: str, |
995 password: Optional[str] | 995 password: Optional[str] |
996 ) -> muc.Room: | 996 ) -> muc.Room: |
997 """Join room an retrieve history with legacy method""" | 997 """Join room an retrieve history with legacy method""" |
998 mess_data_list = await self.host.memory.historyGet( | 998 mess_data_list = await self.host.memory.history_get( |
999 room_jid, | 999 room_jid, |
1000 client.jid.userhostJID(), | 1000 client.jid.userhostJID(), |
1001 limit=1, | 1001 limit=1, |
1002 between=True, | 1002 between=True, |
1003 profile=client.profile | 1003 profile=client.profile |
1016 room._history_type = HISTORY_LEGACY | 1016 room._history_type = HISTORY_LEGACY |
1017 room._history_d = defer.Deferred() | 1017 room._history_d = defer.Deferred() |
1018 room._history_d.callback(None) | 1018 room._history_d.callback(None) |
1019 return room | 1019 return room |
1020 | 1020 |
1021 async def _get_MAM_history( | 1021 async def _get_mam_history( |
1022 self, | 1022 self, |
1023 client: SatXMPPEntity, | 1023 client: SatXMPPEntity, |
1024 room: muc.Room, | 1024 room: muc.Room, |
1025 room_jid: jid.JID | 1025 room_jid: jid.JID |
1026 ) -> None: | 1026 ) -> None: |
1028 history_d = room._history_d = defer.Deferred() | 1028 history_d = room._history_d = defer.Deferred() |
1029 # we trigger now the deferred so all callback are processed as soon as possible | 1029 # we trigger now the deferred so all callback are processed as soon as possible |
1030 # and in order | 1030 # and in order |
1031 history_d.callback(None) | 1031 history_d.callback(None) |
1032 | 1032 |
1033 last_mess = await self.host.memory.historyGet( | 1033 last_mess = await self.host.memory.history_get( |
1034 room_jid, | 1034 room_jid, |
1035 None, | 1035 None, |
1036 limit=1, | 1036 limit=1, |
1037 between=False, | 1037 between=False, |
1038 filters={ | 1038 filters={ |
1054 mam_req = mam.MAMRequest(rsm_=rsm_req) | 1054 mam_req = mam.MAMRequest(rsm_=rsm_req) |
1055 complete = False | 1055 complete = False |
1056 count = 0 | 1056 count = 0 |
1057 while not complete: | 1057 while not complete: |
1058 try: | 1058 try: |
1059 mam_data = await self._mam.getArchives(client, mam_req, | 1059 mam_data = await self._mam.get_archives(client, mam_req, |
1060 service=room_jid) | 1060 service=room_jid) |
1061 except xmpp_error.StanzaError as e: | 1061 except xmpp_error.StanzaError as e: |
1062 if last_mess and e.condition == 'item-not-found': | 1062 if last_mess and e.condition == 'item-not-found': |
1063 log.info( | 1063 log.info( |
1064 f"requested item (with id {stanza_id!r}) can't be found in " | 1064 f"requested item (with id {stanza_id!r}) can't be found in " |
1081 else: | 1081 else: |
1082 count += len(elt_list) | 1082 count += len(elt_list) |
1083 | 1083 |
1084 for mess_elt in elt_list: | 1084 for mess_elt in elt_list: |
1085 try: | 1085 try: |
1086 fwd_message_elt = self._mam.getMessageFromResult( | 1086 fwd_message_elt = self._mam.get_message_from_result( |
1087 client, mess_elt, mam_req, service=room_jid) | 1087 client, mess_elt, mam_req, service=room_jid) |
1088 except exceptions.DataError: | 1088 except exceptions.DataError: |
1089 continue | 1089 continue |
1090 if fwd_message_elt.getAttribute("to"): | 1090 if fwd_message_elt.getAttribute("to"): |
1091 log.warning( | 1091 log.warning( |
1092 'Forwarded message element has a "to" attribute while it is ' | 1092 'Forwarded message element has a "to" attribute while it is ' |
1093 'forbidden by specifications') | 1093 'forbidden by specifications') |
1094 fwd_message_elt["to"] = client.jid.full() | 1094 fwd_message_elt["to"] = client.jid.full() |
1095 try: | 1095 try: |
1096 mess_data = client.messageProt.parseMessage(fwd_message_elt) | 1096 mess_data = client.messageProt.parse_message(fwd_message_elt) |
1097 except Exception as e: | 1097 except Exception as e: |
1098 log.error( | 1098 log.error( |
1099 f"Can't parse message, ignoring it: {e}\n" | 1099 f"Can't parse message, ignoring it: {e}\n" |
1100 f"{fwd_message_elt.toXml()}" | 1100 f"{fwd_message_elt.toXml()}" |
1101 ) | 1101 ) |
1102 continue | 1102 continue |
1103 # we attache parsed message data to element, to avoid parsing | 1103 # we attache parsed message data to element, to avoid parsing |
1104 # again in _addToHistory | 1104 # again in _add_to_history |
1105 fwd_message_elt._mess_data = mess_data | 1105 fwd_message_elt._mess_data = mess_data |
1106 # and we inject to MUC workflow | 1106 # and we inject to MUC workflow |
1107 client._muc_client._onGroupChat(fwd_message_elt) | 1107 client._muc_client._onGroupChat(fwd_message_elt) |
1108 | 1108 |
1109 if not count: | 1109 if not count: |
1116 .format(num_mess=count, room_jid=room_jid)) | 1116 .format(num_mess=count, room_jid=room_jid)) |
1117 | 1117 |
1118 # for legacy history, the following steps are done in receivedSubject but for MAM | 1118 # for legacy history, the following steps are done in receivedSubject but for MAM |
1119 # the order is different (we have to join then get MAM archive, so subject | 1119 # the order is different (we have to join then get MAM archive, so subject |
1120 # is received before archive), so we change state and add the callbacks here. | 1120 # is received before archive), so we change state and add the callbacks here. |
1121 self.changeRoomState(room, ROOM_STATE_LIVE) | 1121 self.change_room_state(room, ROOM_STATE_LIVE) |
1122 history_d.addCallbacks(self._historyCb, self._historyEb, [room], | 1122 history_d.addCallbacks(self._history_cb, self._history_eb, [room], |
1123 errbackArgs=[room]) | 1123 errbackArgs=[room]) |
1124 | 1124 |
1125 # we wait for all callbacks to be processed | 1125 # we wait for all callbacks to be processed |
1126 await history_d | 1126 await history_d |
1127 | 1127 |
1128 async def _join_MAM( | 1128 async def _join_mam( |
1129 self, | 1129 self, |
1130 client: SatXMPPEntity, | 1130 client: SatXMPPEntity, |
1131 room_jid: jid.JID, | 1131 room_jid: jid.JID, |
1132 nick: str, | 1132 nick: str, |
1133 password: Optional[str] | 1133 password: Optional[str] |
1138 room_jid, nick, muc.HistoryOptions(maxStanzas=0), password=password | 1138 room_jid, nick, muc.HistoryOptions(maxStanzas=0), password=password |
1139 ) | 1139 ) |
1140 room._history_type = HISTORY_MAM | 1140 room._history_type = HISTORY_MAM |
1141 # MAM history retrieval can be very long, and doesn't need to be sync, so we don't | 1141 # MAM history retrieval can be very long, and doesn't need to be sync, so we don't |
1142 # wait for it | 1142 # wait for it |
1143 defer.ensureDeferred(self._get_MAM_history(client, room, room_jid)) | 1143 defer.ensureDeferred(self._get_mam_history(client, room, room_jid)) |
1144 room.fully_joined.callback(room) | 1144 room.fully_joined.callback(room) |
1145 | 1145 |
1146 return room | 1146 return room |
1147 | 1147 |
1148 async def join(self, room_jid, nick, password=None): | 1148 async def join(self, room_jid, nick, password=None): |
1149 room_service = jid.JID(room_jid.host) | 1149 room_service = jid.JID(room_jid.host) |
1150 has_mam = await self.host.hasFeature(self.client, mam.NS_MAM, room_service) | 1150 has_mam = await self.host.hasFeature(self.client, mam.NS_MAM, room_service) |
1151 if not self._mam or not has_mam: | 1151 if not self._mam or not has_mam: |
1152 return await self._join_legacy(self.client, room_jid, nick, password) | 1152 return await self._join_legacy(self.client, room_jid, nick, password) |
1153 else: | 1153 else: |
1154 return await self._join_MAM(self.client, room_jid, nick, password) | 1154 return await self._join_mam(self.client, room_jid, nick, password) |
1155 | 1155 |
1156 ## presence/roster ## | 1156 ## presence/roster ## |
1157 | 1157 |
1158 def availableReceived(self, presence): | 1158 def availableReceived(self, presence): |
1159 """ | 1159 """ |
1211 | 1211 |
1212 room.removeUser(user) | 1212 room.removeUser(user) |
1213 | 1213 |
1214 if muc.STATUS_CODE.NEW_NICK in presence.mucStatuses: | 1214 if muc.STATUS_CODE.NEW_NICK in presence.mucStatuses: |
1215 self._changing_nicks.add(presence.nick) | 1215 self._changing_nicks.add(presence.nick) |
1216 self.userChangedNick(room, user, presence.nick) | 1216 self.user_changed_nick(room, user, presence.nick) |
1217 else: | 1217 else: |
1218 self._changing_nicks.discard(presence.nick) | 1218 self._changing_nicks.discard(presence.nick) |
1219 self.userLeftRoom(room, user) | 1219 self.userLeftRoom(room, user) |
1220 | 1220 |
1221 def userJoinedRoom(self, room, user): | 1221 def userJoinedRoom(self, room, user): |
1222 if user.nick == room.nick: | 1222 if user.nick == room.nick: |
1223 # we have received our own nick, | 1223 # we have received our own nick, |
1224 # this mean that the full room roster was received | 1224 # this mean that the full room roster was received |
1225 self.changeRoomState(room, ROOM_STATE_SELF_PRESENCE) | 1225 self.change_room_state(room, ROOM_STATE_SELF_PRESENCE) |
1226 log.debug("room {room} joined with nick {nick}".format( | 1226 log.debug("room {room} joined with nick {nick}".format( |
1227 room=room.occupantJID.userhost(), nick=user.nick)) | 1227 room=room.occupantJID.userhost(), nick=user.nick)) |
1228 # we set type so we don't have to use a deferred | 1228 # we set type so we don't have to use a deferred |
1229 # with disco to check entity type | 1229 # with disco to check entity type |
1230 self.host.memory.updateEntityData( | 1230 self.host.memory.update_entity_data( |
1231 self.client, room.roomJID, C.ENTITY_TYPE, C.ENTITY_TYPE_MUC | 1231 self.client, room.roomJID, C.ENTITY_TYPE, C.ENTITY_TYPE_MUC |
1232 ) | 1232 ) |
1233 elif room.state not in (ROOM_STATE_OCCUPANTS, ROOM_STATE_LIVE): | 1233 elif room.state not in (ROOM_STATE_OCCUPANTS, ROOM_STATE_LIVE): |
1234 log.warning( | 1234 log.warning( |
1235 "Received user presence data in a room before its initialisation " | 1235 "Received user presence data in a room before its initialisation " |
1270 "timestamp": time.time(), | 1270 "timestamp": time.time(), |
1271 } | 1271 } |
1272 # FIXME: we disable presence in history as it's taking a lot of space | 1272 # FIXME: we disable presence in history as it's taking a lot of space |
1273 # while not indispensable. In the future an option may allow | 1273 # while not indispensable. In the future an option may allow |
1274 # to re-enable it | 1274 # to re-enable it |
1275 # self.client.messageAddToHistory(mess_data) | 1275 # self.client.message_add_to_history(mess_data) |
1276 self.client.messageSendToBridge(mess_data) | 1276 self.client.message_send_to_bridge(mess_data) |
1277 | 1277 |
1278 | 1278 |
1279 def userLeftRoom(self, room, user): | 1279 def userLeftRoom(self, room, user): |
1280 if not self.host.trigger.point("MUC user left", room, user, self.client.profile): | 1280 if not self.host.trigger.point("MUC user left", room, user, self.client.profile): |
1281 return | 1281 return |
1282 if user.nick == room.nick: | 1282 if user.nick == room.nick: |
1283 # we left the room | 1283 # we left the room |
1284 room_jid_s = room.roomJID.userhost() | 1284 room_jid_s = room.roomJID.userhost() |
1285 log.info(_("Room ({room}) left ({profile})").format( | 1285 log.info(_("Room ({room}) left ({profile})").format( |
1286 room = room_jid_s, profile = self.client.profile)) | 1286 room = room_jid_s, profile = self.client.profile)) |
1287 self.host.memory.delEntityCache(room.roomJID, profile_key=self.client.profile) | 1287 self.host.memory.del_entity_cache(room.roomJID, profile_key=self.client.profile) |
1288 self.host.bridge.mucRoomLeft(room.roomJID.userhost(), self.client.profile) | 1288 self.host.bridge.muc_room_left(room.roomJID.userhost(), self.client.profile) |
1289 elif room.state != ROOM_STATE_LIVE: | 1289 elif room.state != ROOM_STATE_LIVE: |
1290 log.warning("Received user presence data in a room before its initialisation (current state: {state})," | 1290 log.warning("Received user presence data in a room before its initialisation (current state: {state})," |
1291 "this is not standard! Ignoring it: {room} ({nick})".format( | 1291 "this is not standard! Ignoring it: {room} ({nick})".format( |
1292 state=room.state, | 1292 state=room.state, |
1293 room=room.roomJID.userhost(), | 1293 room=room.roomJID.userhost(), |
1313 "type": C.MESS_TYPE_INFO, | 1313 "type": C.MESS_TYPE_INFO, |
1314 "extra": extra, | 1314 "extra": extra, |
1315 "timestamp": time.time(), | 1315 "timestamp": time.time(), |
1316 } | 1316 } |
1317 # FIXME: disable history, see userJoinRoom comment | 1317 # FIXME: disable history, see userJoinRoom comment |
1318 # self.client.messageAddToHistory(mess_data) | 1318 # self.client.message_add_to_history(mess_data) |
1319 self.client.messageSendToBridge(mess_data) | 1319 self.client.message_send_to_bridge(mess_data) |
1320 | 1320 |
1321 def userChangedNick(self, room, user, new_nick): | 1321 def user_changed_nick(self, room, user, new_nick): |
1322 self.host.bridge.mucRoomUserChangedNick(room.roomJID.userhost(), user.nick, new_nick, self.client.profile) | 1322 self.host.bridge.muc_room_user_changed_nick(room.roomJID.userhost(), user.nick, new_nick, self.client.profile) |
1323 | 1323 |
1324 def userUpdatedStatus(self, room, user, show, status): | 1324 def userUpdatedStatus(self, room, user, show, status): |
1325 entity = jid.JID(tuple=(room.roomJID.user, room.roomJID.host, user.nick)) | 1325 entity = jid.JID(tuple=(room.roomJID.user, room.roomJID.host, user.nick)) |
1326 if hasattr(room, "_cache_presence"): | 1326 if hasattr(room, "_cache_presence"): |
1327 # room has a cache for presence, meaning it has not been fully | 1327 # room has a cache for presence, meaning it has not been fully |
1335 "show": show, | 1335 "show": show, |
1336 "status": status, | 1336 "status": status, |
1337 } | 1337 } |
1338 return | 1338 return |
1339 statuses = {C.PRESENCE_STATUSES_DEFAULT: status or ''} | 1339 statuses = {C.PRESENCE_STATUSES_DEFAULT: status or ''} |
1340 self.host.bridge.presenceUpdate( | 1340 self.host.bridge.presence_update( |
1341 entity.full(), show or '', 0, statuses, self.client.profile) | 1341 entity.full(), show or '', 0, statuses, self.client.profile) |
1342 | 1342 |
1343 ## messages ## | 1343 ## messages ## |
1344 | 1344 |
1345 def receivedGroupChat(self, room, user, body): | 1345 def receivedGroupChat(self, room, user, body): |
1346 log.debug('receivedGroupChat: room=%s user=%s body=%s' % (room.roomJID.full(), user, body)) | 1346 log.debug('receivedGroupChat: room=%s user=%s body=%s' % (room.roomJID.full(), user, body)) |
1347 | 1347 |
1348 def _addToHistory(self, __, user, message): | 1348 def _add_to_history(self, __, user, message): |
1349 try: | 1349 try: |
1350 # message can be already parsed (with MAM), in this case mess_data | 1350 # message can be already parsed (with MAM), in this case mess_data |
1351 # it attached to the element | 1351 # it attached to the element |
1352 mess_data = message.element._mess_data | 1352 mess_data = message.element._mess_data |
1353 except AttributeError: | 1353 except AttributeError: |
1354 mess_data = self.client.messageProt.parseMessage(message.element) | 1354 mess_data = self.client.messageProt.parse_message(message.element) |
1355 if mess_data['message'] or mess_data['subject']: | 1355 if mess_data['message'] or mess_data['subject']: |
1356 return defer.ensureDeferred( | 1356 return defer.ensureDeferred( |
1357 self.host.memory.addToHistory(self.client, mess_data) | 1357 self.host.memory.add_to_history(self.client, mess_data) |
1358 ) | 1358 ) |
1359 else: | 1359 else: |
1360 return defer.succeed(None) | 1360 return defer.succeed(None) |
1361 | 1361 |
1362 def _addToHistoryEb(self, failure): | 1362 def _add_to_history_eb(self, failure): |
1363 failure.trap(exceptions.CancelError) | 1363 failure.trap(exceptions.CancelError) |
1364 | 1364 |
1365 def receivedHistory(self, room, user, message): | 1365 def receivedHistory(self, room, user, message): |
1366 """Called when history (backlog) message are received | 1366 """Called when history (backlog) message are received |
1367 | 1367 |
1384 log.warning(_("storing the unexpected message anyway, to avoid loss")) | 1384 log.warning(_("storing the unexpected message anyway, to avoid loss")) |
1385 # we have to restore URI which are stripped by wokkel parsing | 1385 # we have to restore URI which are stripped by wokkel parsing |
1386 for c in message.element.elements(): | 1386 for c in message.element.elements(): |
1387 if c.uri is None: | 1387 if c.uri is None: |
1388 c.uri = C.NS_CLIENT | 1388 c.uri = C.NS_CLIENT |
1389 mess_data = self.client.messageProt.parseMessage(message.element) | 1389 mess_data = self.client.messageProt.parse_message(message.element) |
1390 message.element._mess_data = mess_data | 1390 message.element._mess_data = mess_data |
1391 self._addToHistory(None, user, message) | 1391 self._add_to_history(None, user, message) |
1392 if mess_data['message'] or mess_data['subject']: | 1392 if mess_data['message'] or mess_data['subject']: |
1393 self.host.bridge.messageNew( | 1393 self.host.bridge.message_new( |
1394 *self.client.messageGetBridgeArgs(mess_data), | 1394 *self.client.message_get_bridge_args(mess_data), |
1395 profile=self.client.profile | 1395 profile=self.client.profile |
1396 ) | 1396 ) |
1397 return | 1397 return |
1398 room._history_d.addCallback(self._addToHistory, user, message) | 1398 room._history_d.addCallback(self._add_to_history, user, message) |
1399 room._history_d.addErrback(self._addToHistoryEb) | 1399 room._history_d.addErrback(self._add_to_history_eb) |
1400 | 1400 |
1401 ## subject ## | 1401 ## subject ## |
1402 | 1402 |
1403 def groupChatReceived(self, message): | 1403 def groupChatReceived(self, message): |
1404 """ | 1404 """ |
1424 self.receivedHistory(room, user, message) | 1424 self.receivedHistory(room, user, message) |
1425 | 1425 |
1426 def subject(self, room, subject): | 1426 def subject(self, room, subject): |
1427 return muc.MUCClientProtocol.subject(self, room, subject) | 1427 return muc.MUCClientProtocol.subject(self, room, subject) |
1428 | 1428 |
1429 def _historyCb(self, __, room): | 1429 def _history_cb(self, __, room): |
1430 """Called when history have been written to database and subject is received | 1430 """Called when history have been written to database and subject is received |
1431 | 1431 |
1432 this method will finish joining by: | 1432 this method will finish joining by: |
1433 - sending message to bridge | 1433 - sending message to bridge |
1434 - calling fully_joined deferred (for legacy history) | 1434 - calling fully_joined deferred (for legacy history) |
1435 - sending stanza put in cache | 1435 - sending stanza put in cache |
1436 - cleaning variables not needed anymore | 1436 - cleaning variables not needed anymore |
1437 """ | 1437 """ |
1438 args = self.plugin_parent._getRoomJoinedArgs(room, self.client.profile) | 1438 args = self.plugin_parent._get_room_joined_args(room, self.client.profile) |
1439 self.host.bridge.mucRoomJoined(*args) | 1439 self.host.bridge.muc_room_joined(*args) |
1440 if room._history_type == HISTORY_LEGACY: | 1440 if room._history_type == HISTORY_LEGACY: |
1441 room.fully_joined.callback(room) | 1441 room.fully_joined.callback(room) |
1442 del room._history_d | 1442 del room._history_d |
1443 del room._history_type | 1443 del room._history_type |
1444 cache = room._cache | 1444 cache = room._cache |
1447 del room._cache_presence | 1447 del room._cache_presence |
1448 for elem in cache: | 1448 for elem in cache: |
1449 self.client.xmlstream.dispatch(elem) | 1449 self.client.xmlstream.dispatch(elem) |
1450 for presence_data in cache_presence.values(): | 1450 for presence_data in cache_presence.values(): |
1451 if not presence_data['show'] and not presence_data['status']: | 1451 if not presence_data['show'] and not presence_data['status']: |
1452 # occupants are already sent in mucRoomJoined, so if we don't have | 1452 # occupants are already sent in muc_room_joined, so if we don't have |
1453 # extra information like show or statuses, we can discard the signal | 1453 # extra information like show or statuses, we can discard the signal |
1454 continue | 1454 continue |
1455 else: | 1455 else: |
1456 self.userUpdatedStatus(**presence_data) | 1456 self.userUpdatedStatus(**presence_data) |
1457 | 1457 |
1458 def _historyEb(self, failure_, room): | 1458 def _history_eb(self, failure_, room): |
1459 log.error("Error while managing history: {}".format(failure_)) | 1459 log.error("Error while managing history: {}".format(failure_)) |
1460 self._historyCb(None, room) | 1460 self._history_cb(None, room) |
1461 | 1461 |
1462 def receivedSubject(self, room, user, subject): | 1462 def receivedSubject(self, room, user, subject): |
1463 # when subject is received, we know that we have whole roster and history | 1463 # when subject is received, we know that we have whole roster and history |
1464 # cf. http://xmpp.org/extensions/xep-0045.html#enter-subject | 1464 # cf. http://xmpp.org/extensions/xep-0045.html#enter-subject |
1465 room.subject = subject # FIXME: subject doesn't handle xml:lang | 1465 room.subject = subject # FIXME: subject doesn't handle xml:lang |
1466 if room.state != ROOM_STATE_LIVE: | 1466 if room.state != ROOM_STATE_LIVE: |
1467 if room._history_type == HISTORY_LEGACY: | 1467 if room._history_type == HISTORY_LEGACY: |
1468 self.changeRoomState(room, ROOM_STATE_LIVE) | 1468 self.change_room_state(room, ROOM_STATE_LIVE) |
1469 room._history_d.addCallbacks(self._historyCb, self._historyEb, [room], errbackArgs=[room]) | 1469 room._history_d.addCallbacks(self._history_cb, self._history_eb, [room], errbackArgs=[room]) |
1470 else: | 1470 else: |
1471 # the subject has been changed | 1471 # the subject has been changed |
1472 log.debug(_("New subject for room ({room_id}): {subject}").format(room_id = room.roomJID.full(), subject = subject)) | 1472 log.debug(_("New subject for room ({room_id}): {subject}").format(room_id = room.roomJID.full(), subject = subject)) |
1473 self.host.bridge.mucRoomNewSubject(room.roomJID.userhost(), subject, self.client.profile) | 1473 self.host.bridge.muc_room_new_subject(room.roomJID.userhost(), subject, self.client.profile) |
1474 | 1474 |
1475 ## disco ## | 1475 ## disco ## |
1476 | 1476 |
1477 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): | 1477 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): |
1478 return [disco.DiscoFeature(NS_MUC)] | 1478 return [disco.DiscoFeature(NS_MUC)] |