diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index 7ff7cc438..2430c9463 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -636,8 +636,7 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.get_id() self.is_gc = False # is it a GC presence ? sigTag = None - ns_muc_user_x = None - avatar_sha = None + self.avatar_sha = None # XEP-0172 User Nickname self.user_nick = self.iq_obj.getTagData('nick') or '' self.contact_nickname = None @@ -653,12 +652,10 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): namespace = x.getNamespace() if namespace.startswith(xmpp.NS_MUC): self.is_gc = True - if namespace == xmpp.NS_MUC_USER and x.getTag('destroy'): - ns_muc_user_x = x elif namespace == xmpp.NS_SIGNED: sigTag = x elif namespace == xmpp.NS_VCARD_UPDATE: - avatar_sha = x.getTagData('photo') + self.avatar_sha = x.getTagData('photo') self.contact_nickname = x.getTagData('nickname') elif namespace == xmpp.NS_DELAY and not self.timestamp: # XEP-0091 @@ -703,133 +700,12 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.jid, self.keyID) if self.is_gc: - if self.ptype == 'error': - errcon = self.iq_obj.getError() - errmsg = self.iq_obj.getErrorMsg() - errcode = self.iq_obj.getErrorCode() - - gc_control = gajim.interface.msg_win_mgr.get_gc_control( - self.jid, self.conn.name) - - # If gc_control is missing - it may be minimized. Try to get it - # from there. If it's not there - then it's missing anyway and - # will remain set to None. - if gc_control is None: - minimized = gajim.interface.minimized_controls[ - self.conn.name] - gc_control = minimized.get(self.jid) - - if errcode == '502': - # Internal Timeout: - self.show = 'error' - self.status = errmsg - return True - elif errcode == '503': - if gc_control is None or gc_control.autorejoin is None: - # maximum user number reached - self.conn.dispatch('GC_ERROR', (gc_control, - _('Unable to join group chat'), - _('Maximum number of users for %s has been ' - 'reached') % self.jid)) - elif (errcode == '401') or (errcon == 'not-authorized'): - # password required to join - self.conn.dispatch('GC_PASSWORD_REQUIRED', (self.jid, - self.resource)) - elif (errcode == '403') or (errcon == 'forbidden'): - # we are banned - self.conn.dispatch('GC_ERROR', (gc_control, - _('Unable to join group chat'), - _('You are banned from group chat %s.') % self.jid)) - elif (errcode == '404') or (errcon in ('item-not-found', - 'remote-server-not-found')): - if gc_control is None or gc_control.autorejoin is None: - # group chat does not exist - self.conn.dispatch('GC_ERROR', (gc_control, - _('Unable to join group chat'), - _('Group chat %s does not exist.') % self.jid)) - elif (errcode == '405') or (errcon == 'not-allowed'): - self.conn.dispatch('GC_ERROR', (gc_control, - _('Unable to join group chat'), - _('Group chat creation is restricted.'))) - elif (errcode == '406') or (errcon == 'not-acceptable'): - self.conn.dispatch('GC_ERROR', (gc_control, - _('Unable to join group chat'), - _('Your registered nickname must be used in group chat ' - '%s.') % self.jid)) - elif (errcode == '407') or (errcon == 'registration-required'): - self.conn.dispatch('GC_ERROR', (gc_control, - _('Unable to join group chat'), - _('You are not in the members list in groupchat %s.') %\ - self.jid)) - elif (errcode == '409') or (errcon == 'conflict'): - # nick conflict - self.conn.dispatch('ASK_NEW_NICK', (self.jid,)) - else: # print in the window the error - self.conn.dispatch('ERROR_ANSWER', ('', self.jid, - errmsg, errcode)) - elif not self.ptype or self.ptype == 'unavailable': - if gajim.config.get('log_contact_status_changes') and \ - gajim.config.should_log(self.conn.name, self.jid): - gc_c = gajim.contacts.get_gc_contact(self.conn.name, - self.jid, self.resource) - st = self.status or '' - if gc_c: - jid = gc_c.jid - else: - jid = self.iq_obj.getJid() - if jid: - # we know real jid, save it in db - st += ' (%s)' % jid - try: - gajim.logger.write('gcstatus', self.fjid, st, self.show) - except exceptions.PysqliteOperationalError, e: - self.conn.dispatch('DB_ERROR', (_('Disk Write Error'), - str(e))) - except exceptions.DatabaseMalformed: - pritext = _('Database Error') - sectext = _('The database file (%s) cannot be read. ' - 'Try to repair it (see ' - 'http://trac.gajim.org/wiki/DatabaseBackup) or ' - 'remove it (all history will be lost).') % \ - LOG_DB_PATH - self.conn.dispatch('DB_ERROR', (pritext, sectext)) - if avatar_sha == '': - # contact has no avatar - puny_nick = helpers.sanitize_filename(self.resource) - gajim.interface.remove_avatar_files(self.jid, puny_nick) - # NOTE: if it's a gc presence, don't ask vcard here. - # We may ask it to real jid in gui part. - if ns_muc_user_x: - # Room has been destroyed. see - # http://www.xmpp.org/extensions/xep-0045.html#destroyroom - reason = _('Room has been destroyed') - destroy = ns_muc_user_x.getTag('destroy') - r = destroy.getTagData('reason') - if r: - reason += ' (%s)' % r - if destroy.getAttr('jid'): - try: - jid = helpers.parse_jid(destroy.getAttr('jid')) - reason += '\n' + \ - _('You can join this room instead: %s') % jid - except common.helpers.InvalidFormat: - pass - statusCode = ['destroyed'] - else: - reason = self.iq_obj.getReason() - statusCode = self.iq_obj.getStatusCode() - role = self.iq_obj.getRole() - affiliation = self.iq_obj.getAffiliation() - prs_jid = self.iq_obj.getJid() - actor = self.iq_obj.getActor() - new_nick = self.iq_obj.getNewNick() - self.conn.dispatch('GC_NOTIFY', (self.jid, self.show, - self.status, self.resource, role, affiliation, prs_jid, - reason, actor, statusCode, new_nick, avatar_sha)) + gajim.nec.push_incoming_event(GcPresenceReceivedEvent(None, + conn=self.conn, iq_obj=self.iq_obj, presence_obj=self)) return if self.ptype == 'subscribe': - log.debug('subscribe request from %s' % self.jfid) + log.debug('subscribe request from %s' % self.fjid) if self.fjid.find('@') <= 0 and self.fjid in \ self.conn.agent_registrations: self.conn.agent_registrations[self.fjid]['sub_received'] = True @@ -929,7 +805,7 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): sess.terminate() del self.conn.sessions[jid][sess.thread_id] - if avatar_sha is not None and self.ptype != 'error': + if self.avatar_sha is not None and self.ptype != 'error': if self.jid not in self.conn.vcard_shas: cached_vcard = self.conn.get_cached_vcard(self.jid) if cached_vcard and 'PHOTO' in cached_vcard and \ @@ -938,7 +814,7 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): cached_vcard['PHOTO']['SHA'] else: self.conn.vcard_shas[self.jid] = '' - if avatar_sha != self.conn.vcard_shas[self.jid]: + if self.avatar_sha != self.conn.vcard_shas[self.jid]: # avatar has been updated self.conn.request_vcard(self.jid) @@ -964,3 +840,96 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.conn.dispatch('STATUS', self.show) elif self.jid in jid_list: return True + +class GcPresenceReceivedEvent(nec.NetworkIncomingEvent): + name = 'gc-presence-received' + base_network_events = [] + + def get_gc_control(self): + self.gc_control = gajim.interface.msg_win_mgr.get_gc_control( + self.room_jid, self.conn.name) + + # If gc_control is missing - it may be minimized. Try to get it + # from there. If it's not there - then it's missing anyway and + # will remain set to None. + if not self.gc_control: + minimized = gajim.interface.minimized_controls[self.conn.name] + self.gc_control = minimized.get(self.room_jid) + + def generate(self): + self.ptype = self.presence_obj.ptype + self.fjid = self.presence_obj.fjid + self.room_jid = self.presence_obj.jid + self.nick = self.presence_obj.resource + self.show = self.presence_obj.show + self.status = self.presence_obj.status + self.avatar_sha = self.presence_obj.avatar_sha + self.errcon = self.iq_obj.getError() + self.errmsg = self.iq_obj.getErrorMsg() + self.errcode = self.iq_obj.getErrorCode() + self.get_gc_control() + self.gc_contact = gajim.contacts.get_gc_contact(self.conn.name, + self.room_jid, self.nick) + + if self.ptype == 'error': + return True + + if self.ptype and self.ptype != 'unavailable': + return + if gajim.config.get('log_contact_status_changes') and \ + gajim.config.should_log(self.conn.name, self.room_jid): + if self.gc_contact: + jid = self.gc_contact.jid + else: + jid = self.iq_obj.getJid() + if jid: + # we know real jid, save it in db + self.status += ' (%s)' % jid + try: + gajim.logger.write('gcstatus', self.fjid, self.status, + self.show) + except exceptions.PysqliteOperationalError, e: + self.conn.dispatch('DB_ERROR', (_('Disk Write Error'), + str(e))) + except exceptions.DatabaseMalformed: + pritext = _('Database Error') + sectext = _('The database file (%s) cannot be read. ' + 'Try to repair it (see ' + 'http://trac.gajim.org/wiki/DatabaseBackup) or ' + 'remove it (all history will be lost).') % \ + LOG_DB_PATH + self.conn.dispatch('DB_ERROR', (pritext, sectext)) + if self.avatar_sha == '': + # contact has no avatar + puny_nick = helpers.sanitize_filename(self.nick) + gajim.interface.remove_avatar_files(self.room_jid, puny_nick) + # NOTE: if it's a gc presence, don't ask vcard here. + # We may ask it to real jid in gui part. + self.status_code = [] + ns_muc_user_x = self.iq_obj.getTag('x', namespace=xmpp.NS_MUC_USER) + if ns_muc_user_x: + # Room has been destroyed. see + # http://www.xmpp.org/extensions/xep-0045.html#destroyroom + self.reason = _('Room has been destroyed') + destroy = ns_muc_user_x.getTag('destroy') + if destroy: + r = destroy.getTagData('reason') + if r: + self.reason += ' (%s)' % r + if destroy.getAttr('jid'): + try: + jid = helpers.parse_jid(destroy.getAttr('jid')) + self.reason += '\n' + \ + _('You can join this room instead: %s') % jid + except common.helpers.InvalidFormat: + pass + self.status_code = ['destroyed'] + else: + self.reason = self.iq_obj.getReason() + self.status_code = self.iq_obj.getStatusCode() + self.role = self.iq_obj.getRole() + self.affiliation = self.iq_obj.getAffiliation() + self.real_jid = self.iq_obj.getJid() + self.actor = self.iq_obj.getActor() + self.new_nick = self.iq_obj.getNewNick() + return True diff --git a/src/groupchat_control.py b/src/groupchat_control.py index 4fd329d1d..f5295bb27 100644 --- a/src/groupchat_control.py +++ b/src/groupchat_control.py @@ -45,6 +45,7 @@ import dataforms_widget from common import gajim from common import helpers from common import dataforms +from common import ged from chat_control import ChatControl from chat_control import ChatControlBase @@ -388,9 +389,11 @@ class GroupchatControl(ChatControlBase): self.list_treeview.set_expander_column(column) self.setup_seclabel(self.xml.get_object('label_selector')) - + self.form_widget = None + gajim.ged.register_event_handler('gc-presence-received', ged.GUI1, + self._nec_gc_presence_received) gajim.gc_connected[self.account][self.room_jid] = False # disable win, we are not connected yet ChatControlBase.got_disconnected(self) @@ -1243,81 +1246,81 @@ class GroupchatControl(ChatControlBase): for role in ('visitor', 'participant', 'moderator'): self.draw_role(role) - def chg_contact_status(self, nick, show, status, role, affiliation, jid, - reason, actor, statusCode, new_nick, avatar_sha, tim=None): - """ - When an occupant changes his or her status - """ - if show == 'invisible': + def _nec_gc_presence_received(self, obj): + if obj.room_jid != self.room_jid: + return + if obj.ptype == 'error': return + role = obj.role if not role: role = 'visitor' + + affiliation = obj.affiliation if not affiliation: affiliation = 'none' - fake_jid = self.room_jid + '/' + nick + newly_created = False - nick_jid = nick + nick_jid = obj.nick # Set to true if role or affiliation have changed right_changed = False - if jid: + if obj.real_jid: # delete ressource - simple_jid = gajim.get_jid_without_resource(jid) + simple_jid = gajim.get_jid_without_resource(obj.real_jid) nick_jid += ' (%s)' % simple_jid - # statusCode + # status_code # http://www.xmpp.org/extensions/xep-0045.html#registrar-statuscodes-\ # init - if statusCode: - if '100' in statusCode: + if obj.status_code: + if '100' in obj.status_code: # Can be a message (see handle_event_gc_config_change in # gajim.py) - self.print_conversation(\ + self.print_conversation( _('Any occupant is allowed to see your full JID')) - if '170' in statusCode: + if '170' in obj.status_code: # Can be a message (see handle_event_gc_config_change in # gajim.py) self.print_conversation(_('Room logging is enabled')) - if '201' in statusCode: + if '201' in obj.status_code: self.print_conversation(_('A new room has been created')) - if '210' in statusCode: + if '210' in obj.status_code: self.print_conversation(\ _('The server has assigned or modified your roomnick')) - if show in ('offline', 'error'): - if statusCode: - if '307' in statusCode: - if actor is None: # do not print 'kicked by None' + if obj.show in ('offline', 'error'): + if obj.status_code: + if '307' in obj.status_code: + if obj.actor is None: # do not print 'kicked by None' s = _('%(nick)s has been kicked: %(reason)s') % { - 'nick': nick, - 'reason': reason } + 'nick': obj.nick, 'reason': obj.reason} else: s = _('%(nick)s has been kicked by %(who)s: ' - '%(reason)s') % {'nick': nick, 'who': actor, - 'reason': reason } - self.print_conversation(s, 'info', tim=tim, graphics=False) - if nick == self.nick and not gajim.config.get( + '%(reason)s') % {'nick': obj.nick, 'who': obj.actor, + 'reason': obj.reason} + self.print_conversation(s, 'info', graphics=False) + if obj.nick == self.nick and not gajim.config.get( 'muc_autorejoin_on_kick'): self.autorejoin = False - elif '301' in statusCode: - if actor is None: # do not print 'banned by None' + elif '301' in obj.status_code: + if obj.actor is None: # do not print 'banned by None' s = _('%(nick)s has been banned: %(reason)s') % { - 'nick': nick, 'reason': reason } + 'nick': obj.nick, 'reason': obj.reason} else: s = _('%(nick)s has been banned by %(who)s: ' - '%(reason)s') % { 'nick': nick, 'who': actor, - 'reason': reason } - self.print_conversation(s, 'info', tim=tim, graphics=False) - if nick == self.nick: + '%(reason)s') % {'nick': obj.nick, 'who': obj.actor, + 'reason': obj.reason} + self.print_conversation(s, 'info', graphics=False) + if obj.nick == self.nick: self.autorejoin = False - elif '303' in statusCode: # Someone changed his or her nick - if new_nick == self.new_nick or nick == self.nick: + elif '303' in obj.status_code: # Someone changed his or her nick + if obj.new_nick == self.new_nick or obj.nick == self.nick: # We changed our nick - self.nick = new_nick + self.nick = obj.new_nick self.new_nick = '' - s = _('You are now known as %s') % new_nick + s = _('You are now known as %s') % self.nick # Stop all E2E sessions nick_list = gajim.contacts.get_nick_list(self.account, self.room_jid) @@ -1334,24 +1337,24 @@ class GroupchatControl(ChatControlBase): ctrl.no_autonegotiation = False else: s = _('%(nick)s is now known as %(new_nick)s') % { - 'nick': nick, 'new_nick': new_nick} + 'nick': obj.nick, 'new_nick': obj.new_nick} # We add new nick to muc roster here, so we don't see # that "new_nick has joined the room" when he just changed # nick. # add_contact_to_roster will be called a second time # after that, but that doesn't hurt - self.add_contact_to_roster(new_nick, show, role, - affiliation, status, jid) - if nick in self.attention_list: - self.attention_list.remove(nick) + self.add_contact_to_roster(obj.new_nick, obj.show, role, + affiliation, obj.status, obj.real_jid) + if obj.nick in self.attention_list: + self.attention_list.remove(obj.nick) # keep nickname color - if nick in self.gc_custom_colors: - self.gc_custom_colors[new_nick] = \ - self.gc_custom_colors[nick] + if obj.nick in self.gc_custom_colors: + self.gc_custom_colors[obj.new_nick] = \ + self.gc_custom_colors[obj.nick] # rename vcard / avatar puny_jid = helpers.sanitize_filename(self.room_jid) - puny_nick = helpers.sanitize_filename(nick) - puny_new_nick = helpers.sanitize_filename(new_nick) + puny_nick = helpers.sanitize_filename(obj.nick) + puny_new_nick = helpers.sanitize_filename(obj.new_nick) old_path = os.path.join(gajim.VCARD_PATH, puny_jid, puny_nick) new_path = os.path.join(gajim.VCARD_PATH, puny_jid, @@ -1373,39 +1376,39 @@ class GroupchatControl(ChatControlBase): # will also remove 'TEST' os.remove(files[old_file]) os.rename(old_file, files[old_file]) - self.print_conversation(s, 'info', tim=tim, graphics=False) - elif '321' in statusCode: + self.print_conversation(s, 'info', graphics=False) + elif '321' in obj.status_code: s = _('%(nick)s has been removed from the room ' - '(%(reason)s)') % { 'nick': nick, + '(%(reason)s)') % { 'nick': obj.nick, 'reason': _('affiliation changed') } - self.print_conversation(s, 'info', tim=tim, graphics=False) - elif '322' in statusCode: + self.print_conversation(s, 'info', graphics=False) + elif '322' in obj.status_code: s = _('%(nick)s has been removed from the room ' - '(%(reason)s)') % { 'nick': nick, + '(%(reason)s)') % { 'nick': obj.nick, 'reason': _('room configuration changed to ' 'members-only') } - self.print_conversation(s, 'info', tim=tim, graphics=False) - elif '332' in statusCode: + self.print_conversation(s, 'info', graphics=False) + elif '332' in obj.status_code: s = _('%(nick)s has been removed from the room ' - '(%(reason)s)') % {'nick': nick, + '(%(reason)s)') % {'nick': obj.nick, 'reason': _('system shutdown') } - self.print_conversation(s, 'info', tim=tim, graphics=False) + self.print_conversation(s, 'info', graphics=False) # Room has been destroyed. - elif 'destroyed' in statusCode: + elif 'destroyed' in obj.status_code: self.autorejoin = False - self.print_conversation(reason, 'info', tim, graphics=False) + self.print_conversation(reason, 'info', graphics=False) - if len(gajim.events.get_events(self.account, jid=fake_jid, + if len(gajim.events.get_events(self.account, jid=obj.fjid, types=['pm'])) == 0: - self.remove_contact(nick) + self.remove_contact(obj.nick) self.draw_all_roles() else: c = gajim.contacts.get_gc_contact(self.account, self.room_jid, - nick) - c.show = show - c.status = status - if nick == self.nick and (not statusCode or \ - '303' not in statusCode): # We became offline + obj.nick) + c.show = obj.show + c.status = obj.status + if obj.nick == self.nick and (not obj.status_code or \ + '303' not in obj.status_code): # We became offline self.got_disconnected() contact = gajim.contacts.\ get_contact_with_highest_priority(self.account, @@ -1416,27 +1419,27 @@ class GroupchatControl(ChatControlBase): if self.parent_win: self.parent_win.redraw_tab(self) else: - iter_ = self.get_contact_iter(nick) + iter_ = self.get_contact_iter(obj.nick) if not iter_: - if '210' in statusCode: + if '210' in obj.status_code: # Server changed our nick - self.nick = nick - s = _('You are now known as %s') % nick - self.print_conversation(s, 'info', tim=tim, graphics=False) - iter_ = self.add_contact_to_roster(nick, show, role, - affiliation, status, jid) + self.nick = obj.nick + s = _('You are now known as %s') % obj.nick + self.print_conversation(s, 'info', graphics=False) + iter_ = self.add_contact_to_roster(obj.nick, obj.show, role, + affiliation, obj.status, obj.real_jid) newly_created = True self.draw_all_roles() - if statusCode and '201' in statusCode: + if obj.status_code and '201' in obj.status_code: # We just created the room gajim.connections[self.account].request_gc_config( self.room_jid) else: gc_c = gajim.contacts.get_gc_contact(self.account, - self.room_jid, nick) + self.room_jid, obj.nick) if not gc_c: log.error('%s has an iter, but no gc_contact instance' % \ - nick) + obj.nick) return # Re-get vcard if avatar has changed # We do that here because we may request it to the real JID if @@ -1445,71 +1448,72 @@ class GroupchatControl(ChatControlBase): if gc_c and gc_c.jid: real_jid = gc_c.jid else: - real_jid = fake_jid - if fake_jid in con.vcard_shas: - if avatar_sha != con.vcard_shas[fake_jid]: + real_jid = obj.fjid + if obj.fjid in obj.conn.vcard_shas: + if obj.avatar_sha != obj.conn.vcard_shas[obj.fjid]: server = gajim.get_server_from_jid(self.room_jid) if not server.startswith('irc'): - con.request_vcard(real_jid, fake_jid) + obj.conn.request_vcard(real_jid, obj.fjid) else: - cached_vcard = con.get_cached_vcard(fake_jid, True) + cached_vcard = obj.conn.get_cached_vcard(obj.fjid, True) if cached_vcard and 'PHOTO' in cached_vcard and \ 'SHA' in cached_vcard['PHOTO']: cached_sha = cached_vcard['PHOTO']['SHA'] else: cached_sha = '' - if cached_sha != avatar_sha: + if cached_sha != obj.avatar_sha: # avatar has been updated # sha in mem will be updated later server = gajim.get_server_from_jid(self.room_jid) if not server.startswith('irc'): - con.request_vcard(real_jid, fake_jid) + obj.conn.request_vcard(real_jid, obj.fjid) else: # save sha in mem NOW - con.vcard_shas[fake_jid] = avatar_sha + obj.conn.vcard_shas[obj.fjid] = obj.avatar_sha actual_affiliation = gc_c.affiliation if affiliation != actual_affiliation: - if actor: + if obj.actor: st = _('** Affiliation of %(nick)s has been set to ' '%(affiliation)s by %(actor)s') % {'nick': nick_jid, - 'affiliation': affiliation, 'actor': actor} + 'affiliation': affiliation, 'actor': obj.actor} else: st = _('** Affiliation of %(nick)s has been set to ' '%(affiliation)s') % {'nick': nick_jid, 'affiliation': affiliation} - if reason: - st += ' (%s)' % reason - self.print_conversation(st, tim=tim, graphics=False) + if obj.reason: + st += ' (%s)' % obj.reason + self.print_conversation(st, graphics=False) right_changed = True - actual_role = self.get_role(nick) + actual_role = self.get_role(obj.nick) if role != actual_role: - self.remove_contact(nick) - self.add_contact_to_roster(nick, show, role, affiliation, - status, jid) + self.remove_contact(obj.nick) + self.add_contact_to_roster(obj.nick, obj.show, role, + affiliation, obj.status, obj.real_jid) self.draw_role(actual_role) self.draw_role(role) - if actor: + if obj.actor: st = _('** Role of %(nick)s has been set to %(role)s ' 'by %(actor)s') % {'nick': nick_jid, 'role': role, - 'actor': actor} + 'actor': obj.actor} else: st = _('** Role of %(nick)s has been set to ' '%(role)s') % {'nick': nick_jid, 'role': role} - if reason: - st += ' (%s)' % reason - self.print_conversation(st, tim=tim, graphics=False) + if obj.reason: + st += ' (%s)' % obj.reason + self.print_conversation(st, graphics=False) right_changed = True else: - if gc_c.show == show and gc_c.status == status and \ + if gc_c.show == obj.show and gc_c.status == obj.status and \ gc_c.affiliation == affiliation: # no change return - gc_c.show = show + gc_c.show = obj.show gc_c.affiliation = affiliation - gc_c.status = status - self.draw_contact(nick) - if (time.time() - self.room_creation) > 30 and nick != self.nick and \ - (not statusCode or '303' not in statusCode) and not right_changed: + gc_c.status = obj.status + self.draw_contact(obj.nick) + if (time.time() - self.room_creation) > 30 and obj.nick != self.nick \ + and (not obj.status_code or '303' not in obj.status_code) and not \ + right_changed: st = '' print_status = None for bookmark in gajim.connections[self.account].bookmarks: @@ -1518,24 +1522,24 @@ class GroupchatControl(ChatControlBase): break if not print_status: print_status = gajim.config.get('print_status_in_muc') - if show == 'offline': - if nick in self.attention_list: - self.attention_list.remove(nick) - if show == 'offline' and print_status in ('all', 'in_and_out') and \ - (not statusCode or '307' not in statusCode): + if obj.show == 'offline': + if obj.nick in self.attention_list: + self.attention_list.remove(obj.nick) + if obj.show == 'offline' and print_status in ('all', 'in_and_out') \ + and (not obj.status_code or '307' not in obj.status_code): st = _('%s has left') % nick_jid - if reason: - st += ' [%s]' % reason + if obj.reason: + st += ' [%s]' % obj.reason else: if newly_created and print_status in ('all', 'in_and_out'): st = _('%s has joined the group chat') % nick_jid elif print_status == 'all': st = _('%(nick)s is now %(status)s') % {'nick': nick_jid, - 'status': helpers.get_uf_show(show)} + 'status': helpers.get_uf_show(obj.show)} if st: - if status: - st += ' (' + status + ')' - self.print_conversation(st, tim=tim, graphics=False) + if obj.status: + st += ' (' + obj.status + ')' + self.print_conversation(st, graphics=False) def add_contact_to_roster(self, nick, show, role, affiliation, status, jid=''): @@ -1673,7 +1677,7 @@ class GroupchatControl(ChatControlBase): del win._controls[self.account][self.contact.jid] def shutdown(self, status='offline'): - # PluginSystem: calling shutdown of super class (ChatControlBase) + # PluginSystem: calling shutdown of super class (ChatControlBase) # to let it remove it's GUI extension points super(GroupchatControl, self).shutdown() diff --git a/src/gui_interface.py b/src/gui_interface.py index a60ce0b22..f4d0199d8 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -133,9 +133,7 @@ class Interface: #('INFORMATION', account, (title_text, section_text)) dialogs.InformationDialog(data[0], data[1]) - def handle_event_ask_new_nick(self, account, data): - #('ASK_NEW_NICK', account, (room_jid,)) - room_jid = data[0] + def handle_ask_new_nick(self, account, room_jid): title = _('Unable to join group chat') prompt = _('Your desired nickname in group chat %s is in use or ' 'registered by another occupant.\nPlease specify another nickname ' @@ -284,6 +282,79 @@ class Interface: profile_window.ProfileWindow(account) gajim.connections[account].request_vcard(jid) + def handle_gc_error(self, gc_control, pritext, sectext): + if gc_control and obj.gc_control.autorejoin is not None: + if gc_control.error_dialog: + gc_control.error_dialog.destroy() + def on_close(dummy): + gc_control.error_dialog.destroy() + gc_control.error_dialog = None + gc_control.error_dialog = dialogs.ErrorDialog(pritext, sectext, + on_response_ok=on_close, on_response_cancel=on_close) + else: + dialogs.ErrorDialog(pritext, sectext) + + def handle_gc_password_required(self, account, room_jid, nick): + def on_ok(text): + gajim.connections[account].join_gc(nick, room_jid, text) + gajim.gc_passwords[room_jid] = text + + def on_cancel(): + # get and destroy window + if room_jid in gajim.interface.minimized_controls[account]: + self.roster.on_disconnect(None, room_jid, account) + else: + win = self.msg_win_mgr.get_window(room_jid, account) + ctrl = self.msg_win_mgr.get_gc_control(room_jid, account) + win.remove_tab(ctrl, 3) + + dlg = dialogs.InputDialog(_('Password Required'), + _('A Password is required to join the room %s. Please type it.') % \ + room_jid, is_modal=False, ok_handler=on_ok, + cancel_handler=on_cancel) + dlg.input_entry.set_visibility(False) + + def handle_event_gc_presence(self, obj): + gc_control = obj.gc_control + if obj.ptype == 'error': + if obj.errcode == '503': + # maximum user number reached + self.handle_gc_error(gc_control, + _('Unable to join group chat'), + _('Maximum number of users for %s has been reached') % \ + obj.room_jid) + elif (obj.errcode == '401') or (obj.errcon == 'not-authorized'): + # password required to join + self.handle_gc_password_required(obj.conn.name, obj.room_jid, + obj.nick) + elif (obj.errcode == '403') or (obj.errcon == 'forbidden'): + # we are banned + self.handle_gc_error(gc_control, _('Unable to join group chat'), + _('You are banned from group chat %s.') % obj.room_jid) + elif (obj.errcode == '404') or (obj.errcon in ('item-not-found', + 'remote-server-not-found')): + # group chat does not exist + self.handle_gc_error(gc_control, _('Unable to join group chat'), + _('Group chat %s does not exist.') % obj.room_jid) + elif (obj.errcode == '405') or (obj.errcon == 'not-allowed'): + self.handle_gc_error(gc_control, _('Unable to join group chat'), + _('Group chat creation is restricted.')) + elif (obj.errcode == '406') or (obj.errcon == 'not-acceptable'): + self.handle_gc_error(gc_control, _('Unable to join group chat'), + _('Your registered nickname must be used in group chat ' + '%s.') % obj.room_jid) + elif (obj.errcode == '407') or (obj.errcon == \ + 'registration-required'): + self.handle_gc_error(gc_control, _('Unable to join group chat'), + _('You are not in the members list in groupchat %s.') % \ + obj.room_jid) + elif (obj.errcode == '409') or (obj.errcon == 'conflict'): + self.handle_ask_new_nick(obj.conn.name, obj.room_jid) + elif gc_control: + gc_control.print_conversation('Error %s: %s' % (obj.errcode, + obj.errmsg)) + return + def handle_event_presence(self, obj): # 'NOTIFY' (account, (jid, status, status message, resource, # priority, # keyID, timestamp, contact_nickname)) @@ -883,30 +954,6 @@ class Interface: self.instances[account]['gc_config'][obj.jid].\ affiliation_list_received(obj.users_dict) - def handle_event_gc_password_required(self, account, array): - #('GC_PASSWORD_REQUIRED', account, (room_jid, nick)) - room_jid = array[0] - nick = array[1] - - def on_ok(text): - gajim.connections[account].join_gc(nick, room_jid, text) - gajim.gc_passwords[room_jid] = text - - def on_cancel(): - # get and destroy window - if room_jid in gajim.interface.minimized_controls[account]: - self.roster.on_disconnect(None, room_jid, account) - else: - win = self.msg_win_mgr.get_window(room_jid, account) - ctrl = self.msg_win_mgr.get_gc_control(room_jid, account) - win.remove_tab(ctrl, 3) - - dlg = dialogs.InputDialog(_('Password Required'), - _('A Password is required to join the room %s. Please type it.') % \ - room_jid, is_modal=False, ok_handler=on_ok, - cancel_handler=on_cancel) - dlg.input_entry.set_visibility(False) - def handle_event_gc_invitation(self, account, array): #('GC_INVITATION', (room_jid, jid_from, reason, password, is_continued)) jid = gajim.get_jid_without_resource(array[1]) @@ -925,20 +972,6 @@ class Interface: notify.popup(event_type, jid, account, 'gc-invitation', path, event_type, room_jid) - def handle_event_gc_error(self, account, data): - #('ERROR', account, (gc_control, title_text, section_text)) - gc_control, pritext, sectext = data - if gc_control: - if gc_control.error_dialog: - gc_control.error_dialog.destroy() - def on_close(dummy): - gc_control.error_dialog.destroy() - gc_control.error_dialog = None - gc_control.error_dialog = dialogs.ErrorDialog(pritext, sectext, - on_response_ok=on_close, on_response_cancel=on_close) - else: - dialogs.ErrorDialog(pritext, sectext) - def forget_gpg_passphrase(self, keyid): if keyid in self.gpg_passphrase: del self.gpg_passphrase[keyid] @@ -1893,8 +1926,6 @@ class Interface: 'GC_SUBJECT': [self.handle_event_gc_subject], 'GC_CONFIG_CHANGE': [self.handle_event_gc_config_change], 'GC_INVITATION': [self.handle_event_gc_invitation], - 'GC_PASSWORD_REQUIRED': [self.handle_event_gc_password_required], - 'GC_ERROR': [self.handle_event_gc_error], 'BAD_PASSPHRASE': [self.handle_event_bad_passphrase], 'CON_TYPE': [self.handle_event_con_type], 'CONNECTION_LOST': [self.handle_event_connection_lost], @@ -1905,7 +1936,6 @@ class Interface: 'STANZA_SENT': [self.handle_event_stanza_sent], 'VCARD_PUBLISHED': [self.handle_event_vcard_published], 'VCARD_NOT_PUBLISHED': [self.handle_event_vcard_not_published], - 'ASK_NEW_NICK': [self.handle_event_ask_new_nick], 'SIGNED_IN': [self.handle_event_signed_in], 'METACONTACTS': [self.handle_event_metacontacts], 'ATOM_ENTRY': [self.handle_atom_entry], @@ -1944,6 +1974,7 @@ class Interface: 'ARCHIVING_ERROR': [self.handle_event_archiving_error], 'bookmarks-received': [self.handle_event_bookmarks], 'error-received': [self.handle_event_error_answer], + 'gc-presence-received': [self.handle_event_gc_presence], 'gmail-notify': [self.handle_event_gmail_notify], 'http-auth-received': [self.handle_event_http_auth], 'last-result-received': [self.handle_event_last_status_time], @@ -2707,7 +2738,7 @@ class Interface: def get_fg_color(self, fmt='hex'): def format_gdkcolor (c): if fmt == 'tex': - return ' '.join([str(s) for s in + return ' '.join([str(s) for s in ('rgb', c.red_float, c.green_float, c.blue_float)]) elif fmt == 'hex': return str(c)