diff sat/plugins/plugin_xep_0045.py @ 3028:ab2696e34d29

Python 3 port: /!\ this is a huge commit /!\ starting from this commit, SàT is needs Python 3.6+ /!\ SàT maybe be instable or some feature may not work anymore, this will improve with time This patch port backend, bridge and frontends to Python 3. Roughly this has been done this way: - 2to3 tools has been applied (with python 3.7) - all references to python2 have been replaced with python3 (notably shebangs) - fixed files not handled by 2to3 (notably the shell script) - several manual fixes - fixed issues reported by Python 3 that where not handled in Python 2 - replaced "async" with "async_" when needed (it's a reserved word from Python 3.7) - replaced zope's "implements" with @implementer decorator - temporary hack to handle data pickled in database, as str or bytes may be returned, to be checked later - fixed hash comparison for password - removed some code which is not needed anymore with Python 3 - deactivated some code which needs to be checked (notably certificate validation) - tested with jp, fixed reported issues until some basic commands worked - ported Primitivus (after porting dependencies like urwid satext) - more manual fixes
author Goffi <goffi@goffi.org>
date Tue, 13 Aug 2019 19:08:41 +0200
parents 7b8d40b17451
children 730bbed77a89
line wrap: on
line diff
--- a/sat/plugins/plugin_xep_0045.py	Wed Jul 31 11:31:22 2019 +0200
+++ b/sat/plugins/plugin_xep_0045.py	Tue Aug 13 19:08:41 2019 +0200
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 # SAT plugin for managing xep-0045
@@ -34,7 +34,7 @@
 from wokkel import muc, disco, iwokkel
 from sat.tools import xml_tools
 
-from zope.interface import implements
+from zope.interface import implementer
 
 # XXX: mam and rsm come from sat_tmp.wokkel
 from wokkel import rsm
@@ -47,7 +47,7 @@
     C.PI_TYPE: "XEP",
     C.PI_PROTOCOLS: ["XEP-0045"],
     C.PI_DEPENDENCIES: ["XEP-0359"],
-    C.PI_RECOMMENDATIONS: [C.TEXT_CMDS, u"XEP-0313"],
+    C.PI_RECOMMENDATIONS: [C.TEXT_CMDS, "XEP-0313"],
     C.PI_MAIN: "XEP_0045",
     C.PI_HANDLER: "yes",
     C.PI_DESCRIPTION: _("""Implementation of Multi-User Chat""")
@@ -62,13 +62,13 @@
 ROOM_STATE_SELF_PRESENCE = "self-presence"
 ROOM_STATE_LIVE = "live"
 ROOM_STATES = (ROOM_STATE_OCCUPANTS, ROOM_STATE_SELF_PRESENCE, ROOM_STATE_LIVE)
-HISTORY_LEGACY = u"legacy"
-HISTORY_MAM = u"mam"
+HISTORY_LEGACY = "legacy"
+HISTORY_MAM = "mam"
 
 
-CONFIG_SECTION = u'plugin muc'
+CONFIG_SECTION = 'plugin muc'
 
-default_conf = {"default_muc": u'sat@chat.jabberfr.org'}
+default_conf = {"default_muc": 'sat@chat.jabberfr.org'}
 
 
 class AlreadyJoined(exceptions.ConflictError):
@@ -86,17 +86,17 @@
         log.info(_("Plugin XEP_0045 initialization"))
         self.host = host
         self._sessions = memory.Sessions()
-        host.bridge.addMethod("mucJoin", ".plugin", in_sign='ssa{ss}s', out_sign='(bsa{sa{ss}}sss)', method=self._join, async=True)  # return same arguments as mucRoomJoined + a boolean set to True is the room was already joined (first argument)
+        host.bridge.addMethod("mucJoin", ".plugin", in_sign='ssa{ss}s', out_sign='(bsa{sa{ss}}sss)', method=self._join, async_=True)  # return same arguments as mucRoomJoined + a boolean set to True is the room was already joined (first argument)
         host.bridge.addMethod("mucNick", ".plugin", in_sign='sss', out_sign='', method=self._nick)
         host.bridge.addMethod("mucNickGet", ".plugin", in_sign='ss', out_sign='s', method=self._getRoomNick)
-        host.bridge.addMethod("mucLeave", ".plugin", in_sign='ss', out_sign='', method=self._leave, async=True)
+        host.bridge.addMethod("mucLeave", ".plugin", in_sign='ss', out_sign='', method=self._leave, async_=True)
         host.bridge.addMethod("mucOccupantsGet", ".plugin", in_sign='ss', out_sign='a{sa{ss}}', method=self._getRoomOccupants)
         host.bridge.addMethod("mucSubject", ".plugin", in_sign='sss', out_sign='', method=self._subject)
         host.bridge.addMethod("mucGetRoomsJoined", ".plugin", in_sign='s', out_sign='a(sa{sa{ss}}ss)', method=self._getRoomsJoined)
         host.bridge.addMethod("mucGetUniqueRoomName", ".plugin", in_sign='ss', out_sign='s', method=self._getUniqueName)
-        host.bridge.addMethod("mucConfigureRoom", ".plugin", in_sign='ss', out_sign='s', method=self._configureRoom, async=True)
+        host.bridge.addMethod("mucConfigureRoom", ".plugin", in_sign='ss', out_sign='s', method=self._configureRoom, async_=True)
         host.bridge.addMethod("mucGetDefaultService", ".plugin", in_sign='', out_sign='s', method=self.getDefaultMUC)
-        host.bridge.addMethod("mucGetService", ".plugin", in_sign='ss', out_sign='s', method=self._getMUCService, async=True)
+        host.bridge.addMethod("mucGetService", ".plugin", in_sign='ss', out_sign='s', method=self._getMUCService, async_=True)
         host.bridge.addSignal("mucRoomJoined", ".plugin", signature='sa{sa{ss}}sss')  # args: room_jid, occupants, user_nick, subject, profile
         host.bridge.addSignal("mucRoomLeft", ".plugin", signature='ss')  # args: room_jid, profile
         host.bridge.addSignal("mucRoomUserChangedNick", ".plugin", signature='ssss')  # args: room_jid, old_nick, new_nick, profile
@@ -107,13 +107,13 @@
         try:
             self.text_cmds = self.host.plugins[C.TEXT_CMDS]
         except KeyError:
-            log.info(_(u"Text commands not available"))
+            log.info(_("Text commands not available"))
         else:
             self.text_cmds.registerTextCommands(self)
             self.text_cmds.addWhoIsCb(self._whois, 100)
 
-        self._mam = self.host.plugins.get(u"XEP-0313")
-        self._si = self.host.plugins[u"XEP-0359"]
+        self._mam = self.host.plugins.get("XEP-0313")
+        self._si = self.host.plugins["XEP-0359"]
 
         host.trigger.add("presence_available", self.presenceTrigger)
         host.trigger.add("presence_received", self.presenceReceivedTrigger)
@@ -127,15 +127,15 @@
 
     def _message_parseTrigger(self, client, message_elt, data):
         """Add stanza-id from the room if present"""
-        if message_elt.getAttribute(u"type") != C.MESS_TYPE_GROUPCHAT:
+        if message_elt.getAttribute("type") != C.MESS_TYPE_GROUPCHAT:
             return True
 
         # stanza_id will not be filled by parseMessage because the emitter
         # is the room and not our server, so we have to parse it here
-        room_jid = data[u"from"].userhostJID()
+        room_jid = data["from"].userhostJID()
         stanza_id = self._si.getStanzaId(message_elt, room_jid)
         if stanza_id:
-            data[u"extra"][u"stanza_id"] = stanza_id
+            data["extra"]["stanza_id"] = stanza_id
 
     def messageReceivedTrigger(self, client, message_elt, post_treat):
         if message_elt.getAttribute("type") == C.MESS_TYPE_GROUPCHAT:
@@ -152,15 +152,15 @@
                         # but an expected case.
                         # On the other hand, with legacy history, it's not normal.
                         log.warning(_(
-                            u"Received non delayed message in a room before its "
-                            u"initialisation: state={state}, msg={msg}").format(
+                            "Received non delayed message in a room before its "
+                            "initialisation: state={state}, msg={msg}").format(
                         state=room.state,
                         msg=message_elt.toXml()))
                     room._cache.append(message_elt)
                     return False
             else:
-                log.warning(u"Received groupchat message for a room which has not been "
-                            u"joined, ignoring it: {}".format(message_elt.toXml()))
+                log.warning("Received groupchat message for a room which has not been "
+                            "joined, ignoring it: {}".format(message_elt.toXml()))
                 return False
         return True
 
@@ -173,7 +173,7 @@
         try:
             return client._muc_client.joined_rooms[room_jid]
         except KeyError:
-            raise exceptions.NotFound(_(u"This room has not been joined"))
+            raise exceptions.NotFound(_("This room has not been joined"))
 
     def checkRoomJoined(self, client, room_jid):
         """Check that given room has been joined in current session
@@ -181,7 +181,7 @@
         @param room_jid (JID): room JID
         """
         if room_jid not in client._muc_client.joined_rooms:
-            raise exceptions.NotFound(_(u"This room has not been joined"))
+            raise exceptions.NotFound(_("This room has not been joined"))
 
     def isJoinedRoom(self, client, room_jid):
         """Tell if a jid is a known and joined room
@@ -213,8 +213,8 @@
     def _passwordUICb(self, data, client, room_jid, nick):
         """Called when the user has given room password (or cancelled)"""
         if C.bool(data.get(C.XMLUI_DATA_CANCELLED, "false")):
-            log.info(u"room join for {} is cancelled".format(room_jid.userhost()))
-            raise failure.Failure(exceptions.CancelError(D_(u"Room joining cancelled by user")))
+            log.info("room join for {} is cancelled".format(room_jid.userhost()))
+            raise failure.Failure(exceptions.CancelError(D_("Room joining cancelled by user")))
         password = data[xml_tools.formEscape('password')]
         return client._muc_client.join(room_jid, nick, password).addCallbacks(self._joinCb, self._joinEb, (client, room_jid, nick), errbackArgs=(client, room_jid, nick, password))
 
@@ -234,10 +234,10 @@
             # FIXME: the current behaviour is to create an instant room
             # and send the signal only when the room is unlocked
             # a proper configuration management should be done
-            log.debug(_(u"room locked !"))
+            log.debug(_("room locked !"))
             d = client._muc_client.configure(room.roomJID, {})
             d.addErrback(self.host.logErrback,
-                         msg=_(u'Error while configuring the room: {failure_}'))
+                         msg=_('Error while configuring the room: {failure_}'))
         return room.fully_joined
 
     def _joinEb(self, failure, client, room_jid, nick, password):
@@ -253,7 +253,7 @@
                 return client._muc_client.join(room_jid, nick, password).addCallbacks(self._joinCb, self._joinEb, (client, room_jid, nick), errbackArgs=(client, room_jid, nick, password))
             elif condition == 'not-allowed':
                 # room is restricted, we need a password
-                password_ui = xml_tools.XMLUI("form", title=D_(u'Room {} is restricted').format(room_jid.userhost()), submit_id='')
+                password_ui = xml_tools.XMLUI("form", title=D_('Room {} is restricted').format(room_jid.userhost()), submit_id='')
                 password_ui.addText(D_("This room is restricted, please enter the password"))
                 password_ui.addPassword('password')
                 d = xml_tools.deferXMLUI(self.host, password_ui, profile=client.profile)
@@ -262,16 +262,16 @@
 
             msg_suffix = ' with condition "{}"'.format(failure.value.condition)
 
-        mess = D_(u"Error while joining the room {room}{suffix}".format(
+        mess = D_("Error while joining the room {room}{suffix}".format(
             room = room_jid.userhost(), suffix = msg_suffix))
         log.error(mess)
-        xmlui = xml_tools.note(mess, D_(u"Group chat error"), level=C.XMLUI_DATA_LVL_ERROR)
+        xmlui = xml_tools.note(mess, D_("Group chat error"), level=C.XMLUI_DATA_LVL_ERROR)
         self.host.actionNew({'xmlui': xmlui.toXml()}, profile=client.profile)
 
     @staticmethod
     def _getOccupants(room):
         """Get occupants of a room in a form suitable for bridge"""
-        return {u.nick: {k:unicode(getattr(u,k) or '') for k in OCCUPANT_KEYS} for u in room.roster.values()}
+        return {u.nick: {k:str(getattr(u,k) or '') for k in OCCUPANT_KEYS} for u in list(room.roster.values())}
 
     def _getRoomOccupants(self, room_jid_s, profile_key):
         client = self.host.getClient(profile_key)
@@ -289,7 +289,7 @@
     def getRoomsJoined(self, client):
         """Return rooms where user is"""
         result = []
-        for room in client._muc_client.joined_rooms.values():
+        for room in list(client._muc_client.joined_rooms.values()):
             if room.state == ROOM_STATE_LIVE:
                 result.append((room.roomJID.userhost(), self._getOccupants(room), room.nick, room.subject))
         return result
@@ -330,7 +330,7 @@
 
         def xmluiReceived(xmlui):
             if not xmlui:
-                msg = D_(u"No configuration available for this room")
+                msg = D_("No configuration available for this room")
                 return {"xmlui": xml_tools.note(msg).toXml()}
             return {"xmlui": xmlui.toXml()}
         return self.configureRoom(client, room_jid).addCallback(xmluiReceived)
@@ -385,7 +385,7 @@
     def _getMUCService(self, jid_=None, profile=C.PROF_KEY_NONE):
         client = self.host.getClient(profile)
         d = self.getMUCService(client, jid_ or None)
-        d.addCallback(lambda service_jid: service_jid.full() if service_jid is not None else u'')
+        d.addCallback(lambda service_jid: service_jid.full() if service_jid is not None else '')
         return d
 
     @defer.inlineCallbacks
@@ -426,18 +426,18 @@
         @return: jid.JID (unique room bare JID)
         """
         # TODO: we should use #RFC-0045 10.1.4 when available here
-        room_name = unicode(uuid.uuid4())
+        room_name = str(uuid.uuid4())
         if muc_service is None:
             try:
                 muc_service = client.muc_service
             except AttributeError:
-                raise exceptions.NotReady(u"Main server MUC service has not been checked yet")
+                raise exceptions.NotReady("Main server MUC service has not been checked yet")
             if muc_service is None:
                 log.warning(_("No MUC service found on main server"))
                 raise exceptions.FeatureNotFound
 
         muc_service = muc_service.userhost()
-        return jid.JID(u"{}@{}".format(room_name, muc_service))
+        return jid.JID("{}@{}".format(room_name, muc_service))
 
     def getDefaultMUC(self):
         """Return the default MUC.
@@ -462,9 +462,9 @@
             try:
                 room_jid = jid.JID(room_jid_s)
             except (RuntimeError, jid.InvalidFormat, AttributeError):
-                return defer.fail(jid.InvalidFormat(_(u"Invalid room identifier: {room_id}'. Please give a room short or full identifier like 'room' or 'room@{muc_service}'.").format(
+                return defer.fail(jid.InvalidFormat(_("Invalid room identifier: {room_id}'. Please give a room short or full identifier like 'room' or 'room@{muc_service}'.").format(
                     room_id=room_jid_s,
-                    muc_service=unicode(muc_service))))
+                    muc_service=str(muc_service))))
             if not room_jid.user:
                 room_jid.user, room_jid.host = room_jid.host, muc_service
         else:
@@ -482,10 +482,10 @@
             options = {}
         if room_jid in client._muc_client.joined_rooms:
             room = client._muc_client.joined_rooms[room_jid]
-            log.info(_(u'{profile} is already in room {room_jid}').format(
+            log.info(_('{profile} is already in room {room_jid}').format(
                 profile=client.profile, room_jid = room_jid.userhost()))
             return defer.fail(AlreadyJoined(room))
-        log.info(_(u"[{profile}] is joining room {room} with nick {nick}").format(
+        log.info(_("[{profile}] is joining room {room} with nick {nick}").format(
             profile=client.profile, room=room_jid.userhost(), nick=nick))
 
         password = options.get("password")
@@ -504,7 +504,7 @@
             This list can be used directly (unpacked) with self.join
         """
         args_list = []
-        for room in client._muc_client.joined_rooms.values():
+        for room in list(client._muc_client.joined_rooms.values()):
             client._muc_client._removeRoom(room.roomJID)
             args_list.append((client, room.roomJID, room.nick))
         return args_list
@@ -642,16 +642,16 @@
             nick = options[0]
             assert self.isNickInRoom(client, mess_data["to"], nick)
         except (IndexError, AssertionError):
-            feedback = _(u"You must provide a member's nick to kick.")
+            feedback = _("You must provide a member's nick to kick.")
             self.text_cmds.feedBack(client, feedback, mess_data)
             return False
 
         d = self.kick(client, nick, mess_data["to"], {} if len(options) == 1 else {'reason': options[1]})
 
         def cb(__):
-            feedback_msg = _(u'You have kicked {}').format(nick)
+            feedback_msg = _('You have kicked {}').format(nick)
             if len(options) > 1:
-                feedback_msg += _(u' for the following reason: {}').format(options[1])
+                feedback_msg += _(' for the following reason: {}').format(options[1])
             self.text_cmds.feedBack(client, feedback_msg, mess_data)
             return True
         d.addCallback(cb)
@@ -671,16 +671,16 @@
             assert(entity_jid.user)
             assert(entity_jid.host)
         except (RuntimeError, jid.InvalidFormat, AttributeError, IndexError, AssertionError):
-            feedback = _(u"You must provide a valid JID to ban, like in '/ban contact@example.net'")
+            feedback = _("You must provide a valid JID to ban, like in '/ban contact@example.net'")
             self.text_cmds.feedBack(client, feedback, mess_data)
             return False
 
         d = self.ban(client, entity_jid, mess_data["to"], {} if len(options) == 1 else {'reason': options[1]})
 
         def cb(__):
-            feedback_msg = _(u'You have banned {}').format(entity_jid)
+            feedback_msg = _('You have banned {}').format(entity_jid)
             if len(options) > 1:
-                feedback_msg += _(u' for the following reason: {}').format(options[1])
+                feedback_msg += _(' for the following reason: {}').format(options[1])
             self.text_cmds.feedBack(client, feedback_msg, mess_data)
             return True
         d.addCallback(cb)
@@ -704,20 +704,20 @@
             assert(entity_jid.user)
             assert(entity_jid.host)
         except (RuntimeError, jid.InvalidFormat, AttributeError, IndexError, AssertionError):
-            feedback = _(u"You must provide a valid JID to affiliate, like in '/affiliate contact@example.net member'")
+            feedback = _("You must provide a valid JID to affiliate, like in '/affiliate contact@example.net member'")
             self.text_cmds.feedBack(client, feedback, mess_data)
             return False
 
         affiliation = options[1] if len(options) > 1 else 'none'
         if affiliation not in AFFILIATIONS:
-            feedback = _(u"You must provide a valid affiliation: %s") % ' '.join(AFFILIATIONS)
+            feedback = _("You must provide a valid affiliation: %s") % ' '.join(AFFILIATIONS)
             self.text_cmds.feedBack(client, feedback, mess_data)
             return False
 
         d = self.affiliate(client, entity_jid, mess_data["to"], {'affiliation': affiliation})
 
         def cb(__):
-            feedback_msg = _(u'New affiliation for %(entity)s: %(affiliation)s').format(entity=entity_jid, affiliation=affiliation)
+            feedback_msg = _('New affiliation for %(entity)s: %(affiliation)s').format(entity=entity_jid, affiliation=affiliation)
             self.text_cmds.feedBack(client, feedback_msg, mess_data)
             return True
         d.addCallback(cb)
@@ -763,11 +763,11 @@
             elif client.muc_service is not None:
                 service = client.muc_service
             else:
-                msg = D_(u"No known default MUC service".format(unparsed))
+                msg = D_("No known default MUC service".format(unparsed))
                 self.text_cmds.feedBack(client, msg, mess_data)
                 return False
         except jid.InvalidFormat:
-            msg = D_(u"{} is not a valid JID!".format(unparsed))
+            msg = D_("{} is not a valid JID!".format(unparsed))
             self.text_cmds.feedBack(client, msg, mess_data)
             return False
         d = self.host.getDiscoItems(client, service)
@@ -801,7 +801,7 @@
         # FIXME: should we add a privacy parameters in settings to activate before
         #        broadcasting the presence to all MUC rooms ?
         muc_client = client._muc_client
-        for room_jid, room in muc_client.joined_rooms.iteritems():
+        for room_jid, room in muc_client.joined_rooms.items():
             elt = xml_tools.elementCopy(presence_elt)
             elt['to'] = room_jid.userhost() + '/' + room.nick
             client.presence.send(elt)
@@ -816,15 +816,15 @@
         return True
 
 
+@implementer(iwokkel.IDisco)
 class SatMUCClient(muc.MUCClient):
-    implements(iwokkel.IDisco)
 
     def __init__(self, plugin_parent):
         self.plugin_parent = plugin_parent
         muc.MUCClient.__init__(self)
         self._changing_nicks = set()  # used to keep trace of who is changing nick,
                                       # and to discard userJoinedRoom signal in this case
-        print "init SatMUCClient OK"
+        print("init SatMUCClient OK")
 
     @property
     def joined_rooms(self):
@@ -861,8 +861,8 @@
         expected_state = ROOM_STATES[new_state_idx-1]
         if room.state != expected_state:
             log.error(_(
-                u"room {room} is not in expected state: room is in state {current_state} "
-                u"while we were expecting {expected_state}").format(
+                "room {room} is not in expected state: room is in state {current_state} "
+                "while we were expecting {expected_state}").format(
                 room=room.roomJID.userhost(),
                 current_state=room.state,
                 expected_state=expected_state))
@@ -919,19 +919,19 @@
             limit=1,
             between=False,
             filters={
-                u'types': C.MESS_TYPE_GROUPCHAT,
-                u'last_stanza_id': True},
+                'types': C.MESS_TYPE_GROUPCHAT,
+                'last_stanza_id': True},
             profile=client.profile)
         if last_mess:
-            stanza_id = last_mess[0][-1][u'stanza_id']
+            stanza_id = last_mess[0][-1]['stanza_id']
             rsm_req = rsm.RSMRequest(max_=100, after=stanza_id)
             no_loop=False
         else:
-            log.info(u"We have no MAM archive for room {room_jid}.".format(
+            log.info("We have no MAM archive for room {room_jid}.".format(
                 room_jid=room_jid))
             # we don't want the whole archive if we have no archive yet
             # as it can be huge
-            rsm_req = rsm.RSMRequest(max_=50, before=u'')
+            rsm_req = rsm.RSMRequest(max_=50, before='')
             no_loop=True
 
         mam_req = mam.MAMRequest(rsm_=rsm_req)
@@ -941,7 +941,7 @@
             mam_data = yield self._mam.getArchives(client, mam_req,
                                                    service=room_jid)
             elt_list, rsm_response, mam_response = mam_data
-            complete = True if no_loop else mam_response[u"complete"]
+            complete = True if no_loop else mam_response["complete"]
             # we update MAM request for next iteration
             mam_req.rsm.after = rsm_response.last
 
@@ -956,11 +956,11 @@
                             client, mess_elt, mam_req, service=room_jid)
                     except exceptions.DataError:
                         continue
-                    if fwd_message_elt.getAttribute(u"to"):
+                    if fwd_message_elt.getAttribute("to"):
                         log.warning(
-                            u'Forwarded message element has a "to" attribute while it is '
-                            u'forbidden by specifications')
-                    fwd_message_elt[u"to"] = client.jid.full()
+                            'Forwarded message element has a "to" attribute while it is '
+                            'forbidden by specifications')
+                    fwd_message_elt["to"] = client.jid.full()
                     mess_data = client.messageProt.parseMessage(fwd_message_elt)
                     # we attache parsed message data to element, to avoid parsing
                     # again in _addToHistory
@@ -969,12 +969,12 @@
                     client._muc_client._onGroupChat(fwd_message_elt)
 
         if not count:
-            log.info(_(u"No message received while offline in {room_jid}".format(
+            log.info(_("No message received while offline in {room_jid}".format(
                 room_jid=room_jid)))
         else:
             log.info(
-                _(u"We have received {num_mess} message(s) in {room_jid} while "
-                  u"offline.")
+                _("We have received {num_mess} message(s) in {room_jid} while "
+                  "offline.")
                 .format(num_mess=count, room_jid=room_jid))
 
         # for legacy history, the following steps are done in receivedSubject but for MAM
@@ -1017,7 +1017,7 @@
         if user is None:
             nick = presence.sender.resource
             if not nick:
-                log.warning(_(u"missing nick in presence: {xml}").format(
+                log.warning(_("missing nick in presence: {xml}").format(
                     xml = presence.toElement().toXml()))
                 return
             user = muc.User(nick, presence.entity)
@@ -1061,7 +1061,7 @@
             # we have received our own nick,
             # this mean that the full room roster was received
             self.changeRoomState(room, ROOM_STATE_SELF_PRESENCE)
-            log.debug(u"room {room} joined with nick {nick}".format(
+            log.debug("room {room} joined with nick {nick}".format(
                 room=room.occupantJID.userhost(), nick=user.nick))
             # we set type so we don't have to use a deferred
             # with disco to check entity type
@@ -1070,9 +1070,9 @@
                 profile_key=self.client.profile)
         elif room.state not in (ROOM_STATE_OCCUPANTS, ROOM_STATE_LIVE):
             log.warning(
-                u"Received user presence data in a room before its initialisation "
-                u"(current state: {state}),"
-                u"this is not standard! Ignoring it: {room} ({nick})".format(
+                "Received user presence data in a room before its initialisation "
+                "(current state: {state}),"
+                "this is not standard! Ignoring it: {room} ({nick})".format(
                     state=room.state,
                     room=room.roomJID.userhost(),
                     nick=user.nick))
@@ -1084,7 +1084,7 @@
                 self._changing_nicks.remove(user.nick)
             except KeyError:
                 # this is a new user
-                log.debug(_(u"user {nick} has joined room {room_id}").format(
+                log.debug(_("user {nick} has joined room {room_id}").format(
                     nick=user.nick, room_id=room.occupantJID.userhost()))
                 if not self.host.trigger.point(
                         "MUC user joined", room, user, self.client.profile):
@@ -1100,8 +1100,8 @@
                 mess_data = {  # dict is similar to the one used in client.onMessage
                     "from": room.roomJID,
                     "to": self.client.jid,
-                    "uid": unicode(uuid.uuid4()),
-                    "message": {'': D_(u"=> {} has joined the room").format(user.nick)},
+                    "uid": str(uuid.uuid4()),
+                    "message": {'': D_("=> {} has joined the room").format(user.nick)},
                     "subject": {},
                     "type": C.MESS_TYPE_INFO,
                     "extra": extra,
@@ -1120,12 +1120,12 @@
         if user.nick == room.nick:
             # we left the room
             room_jid_s = room.roomJID.userhost()
-            log.info(_(u"Room ({room}) left ({profile})").format(
+            log.info(_("Room ({room}) left ({profile})").format(
                 room = room_jid_s, profile = self.client.profile))
             self.host.memory.delEntityCache(room.roomJID, profile_key=self.client.profile)
             self.host.bridge.mucRoomLeft(room.roomJID.userhost(), self.client.profile)
         elif room.state != ROOM_STATE_LIVE:
-            log.warning(u"Received user presence data in a room before its initialisation (current state: {state}),"
+            log.warning("Received user presence data in a room before its initialisation (current state: {state}),"
                 "this is not standard! Ignoring it: {room} ({nick})".format(
                 state=room.state,
                 room=room.roomJID.userhost(),
@@ -1134,7 +1134,7 @@
         else:
             if not room.fully_joined.called:
                 return
-            log.debug(_(u"user {nick} left room {room_id}").format(nick=user.nick, room_id=room.occupantJID.userhost()))
+            log.debug(_("user {nick} left room {room_id}").format(nick=user.nick, room_id=room.occupantJID.userhost()))
             extra = {'info_type': ROOM_USER_LEFT,
                      'user_affiliation': user.affiliation,
                      'user_role': user.role,
@@ -1145,8 +1145,8 @@
             mess_data = {  # dict is similar to the one used in client.onMessage
                 "from": room.roomJID,
                 "to": self.client.jid,
-                "uid": unicode(uuid.uuid4()),
-                "message": {'': D_(u"<= {} has left the room").format(user.nick)},
+                "uid": str(uuid.uuid4()),
+                "message": {'': D_("<= {} has left the room").format(user.nick)},
                 "subject": {},
                 "type": C.MESS_TYPE_INFO,
                 "extra": extra,
@@ -1181,7 +1181,7 @@
     ## messages ##
 
     def receivedGroupChat(self, room, user, body):
-        log.debug(u'receivedGroupChat: room=%s user=%s body=%s' % (room.roomJID.full(), user, body))
+        log.debug('receivedGroupChat: room=%s user=%s body=%s' % (room.roomJID.full(), user, body))
 
     def _addToHistory(self, __, user, message):
         try:
@@ -1190,7 +1190,7 @@
             mess_data = message.element._mess_data
         except AttributeError:
             mess_data = self.client.messageProt.parseMessage(message.element)
-        if mess_data[u'message'] or mess_data[u'subject']:
+        if mess_data['message'] or mess_data['subject']:
             return self.host.memory.addToHistory(self.client, mess_data)
         else:
             return defer.succeed(None)
@@ -1210,14 +1210,14 @@
         """
         if room.state != ROOM_STATE_SELF_PRESENCE:
             log.warning(_(
-                u"received history in unexpected state in room {room} (state: "
-                u"{state})").format(room = room.roomJID.userhost(),
+                "received history in unexpected state in room {room} (state: "
+                "{state})").format(room = room.roomJID.userhost(),
                                     state = room.state))
             if not hasattr(room, "_history_d"):
                 # XXX: this hack is due to buggy behaviour seen in the wild because of the
                 #      "mod_delay" prosody module being activated. This module add an
                 #      unexpected <delay> elements which break our workflow.
-                log.warning(_(u"storing the unexpected message anyway, to avoid loss"))
+                log.warning(_("storing the unexpected message anyway, to avoid loss"))
                 # we have to restore URI which are stripped by wokkel parsing
                 for c in message.element.elements():
                     if c.uri is None:
@@ -1225,7 +1225,7 @@
                 mess_data = self.client.messageProt.parseMessage(message.element)
                 message.element._mess_data = mess_data
                 self._addToHistory(None, user, message)
-                if mess_data[u'message'] or mess_data[u'subject']:
+                if mess_data['message'] or mess_data['subject']:
                     self.host.bridge.messageNew(
                         *self.client.messageGetBridgeArgs(mess_data),
                         profile=self.client.profile
@@ -1248,7 +1248,7 @@
         room, user = self._getRoomUser(message)
 
         if room is None:
-            log.warning(u"No room found for message: {message}"
+            log.warning("No room found for message: {message}"
                         .format(message=message.toElement().toXml()))
             return
 
@@ -1282,8 +1282,8 @@
         del room._cache_presence
         for elem in cache:
             self.client.xmlstream.dispatch(elem)
-        for presence_data in cache_presence.itervalues():
-            if not presence_data[u'show'] and not presence_data[u'status']:
+        for presence_data in cache_presence.values():
+            if not presence_data['show'] and not presence_data['status']:
                 # occupants are already sent in mucRoomJoined, so if we don't have
                 # extra information like show or statuses, we can discard the signal
                 continue
@@ -1291,7 +1291,7 @@
                 self.userUpdatedStatus(**presence_data)
 
     def _historyEb(self, failure_, room):
-        log.error(u"Error while managing history: {}".format(failure_))
+        log.error("Error while managing history: {}".format(failure_))
         self._historyCb(None, room)
 
     def receivedSubject(self, room, user, subject):
@@ -1304,7 +1304,7 @@
                 room._history_d.addCallbacks(self._historyCb, self._historyEb, [room], errbackArgs=[room])
         else:
             # the subject has been changed
-            log.debug(_(u"New subject for room ({room_id}): {subject}").format(room_id = room.roomJID.full(), subject = subject))
+            log.debug(_("New subject for room ({room_id}): {subject}").format(room_id = room.roomJID.full(), subject = subject))
             self.host.bridge.mucRoomNewSubject(room.roomJID.userhost(), subject, self.client.profile)
 
     ## disco ##