new event for groupchat presences

This commit is contained in:
Yann Leboulanger 2010-09-28 15:13:51 +02:00
parent 8d218ab0d0
commit 69a1eee8e6
3 changed files with 298 additions and 294 deletions

View file

@ -636,8 +636,7 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.get_id() self.get_id()
self.is_gc = False # is it a GC presence ? self.is_gc = False # is it a GC presence ?
sigTag = None sigTag = None
ns_muc_user_x = None self.avatar_sha = None
avatar_sha = None
# XEP-0172 User Nickname # XEP-0172 User Nickname
self.user_nick = self.iq_obj.getTagData('nick') or '' self.user_nick = self.iq_obj.getTagData('nick') or ''
self.contact_nickname = None self.contact_nickname = None
@ -653,12 +652,10 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
namespace = x.getNamespace() namespace = x.getNamespace()
if namespace.startswith(xmpp.NS_MUC): if namespace.startswith(xmpp.NS_MUC):
self.is_gc = True self.is_gc = True
if namespace == xmpp.NS_MUC_USER and x.getTag('destroy'):
ns_muc_user_x = x
elif namespace == xmpp.NS_SIGNED: elif namespace == xmpp.NS_SIGNED:
sigTag = x sigTag = x
elif namespace == xmpp.NS_VCARD_UPDATE: elif namespace == xmpp.NS_VCARD_UPDATE:
avatar_sha = x.getTagData('photo') self.avatar_sha = x.getTagData('photo')
self.contact_nickname = x.getTagData('nickname') self.contact_nickname = x.getTagData('nickname')
elif namespace == xmpp.NS_DELAY and not self.timestamp: elif namespace == xmpp.NS_DELAY and not self.timestamp:
# XEP-0091 # XEP-0091
@ -703,133 +700,12 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.jid, self.keyID) self.jid, self.keyID)
if self.is_gc: if self.is_gc:
if self.ptype == 'error': gajim.nec.push_incoming_event(GcPresenceReceivedEvent(None,
errcon = self.iq_obj.getError() conn=self.conn, iq_obj=self.iq_obj, presence_obj=self))
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))
return return
if self.ptype == 'subscribe': 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 \ if self.fjid.find('@') <= 0 and self.fjid in \
self.conn.agent_registrations: self.conn.agent_registrations:
self.conn.agent_registrations[self.fjid]['sub_received'] = True self.conn.agent_registrations[self.fjid]['sub_received'] = True
@ -929,7 +805,7 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
sess.terminate() sess.terminate()
del self.conn.sessions[jid][sess.thread_id] 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: if self.jid not in self.conn.vcard_shas:
cached_vcard = self.conn.get_cached_vcard(self.jid) cached_vcard = self.conn.get_cached_vcard(self.jid)
if cached_vcard and 'PHOTO' in cached_vcard and \ if cached_vcard and 'PHOTO' in cached_vcard and \
@ -938,7 +814,7 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
cached_vcard['PHOTO']['SHA'] cached_vcard['PHOTO']['SHA']
else: else:
self.conn.vcard_shas[self.jid] = '' 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 # avatar has been updated
self.conn.request_vcard(self.jid) self.conn.request_vcard(self.jid)
@ -964,3 +840,96 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.conn.dispatch('STATUS', self.show) self.conn.dispatch('STATUS', self.show)
elif self.jid in jid_list: elif self.jid in jid_list:
return True 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

View file

@ -45,6 +45,7 @@ import dataforms_widget
from common import gajim from common import gajim
from common import helpers from common import helpers
from common import dataforms from common import dataforms
from common import ged
from chat_control import ChatControl from chat_control import ChatControl
from chat_control import ChatControlBase from chat_control import ChatControlBase
@ -388,9 +389,11 @@ class GroupchatControl(ChatControlBase):
self.list_treeview.set_expander_column(column) self.list_treeview.set_expander_column(column)
self.setup_seclabel(self.xml.get_object('label_selector')) self.setup_seclabel(self.xml.get_object('label_selector'))
self.form_widget = None 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 gajim.gc_connected[self.account][self.room_jid] = False
# disable win, we are not connected yet # disable win, we are not connected yet
ChatControlBase.got_disconnected(self) ChatControlBase.got_disconnected(self)
@ -1243,81 +1246,81 @@ class GroupchatControl(ChatControlBase):
for role in ('visitor', 'participant', 'moderator'): for role in ('visitor', 'participant', 'moderator'):
self.draw_role(role) self.draw_role(role)
def chg_contact_status(self, nick, show, status, role, affiliation, jid, def _nec_gc_presence_received(self, obj):
reason, actor, statusCode, new_nick, avatar_sha, tim=None): if obj.room_jid != self.room_jid:
""" return
When an occupant changes his or her status if obj.ptype == 'error':
"""
if show == 'invisible':
return return
role = obj.role
if not role: if not role:
role = 'visitor' role = 'visitor'
affiliation = obj.affiliation
if not affiliation: if not affiliation:
affiliation = 'none' affiliation = 'none'
fake_jid = self.room_jid + '/' + nick
newly_created = False newly_created = False
nick_jid = nick nick_jid = obj.nick
# Set to true if role or affiliation have changed # Set to true if role or affiliation have changed
right_changed = False right_changed = False
if jid: if obj.real_jid:
# delete ressource # 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 nick_jid += ' (%s)' % simple_jid
# statusCode # status_code
# http://www.xmpp.org/extensions/xep-0045.html#registrar-statuscodes-\ # http://www.xmpp.org/extensions/xep-0045.html#registrar-statuscodes-\
# init # init
if statusCode: if obj.status_code:
if '100' in statusCode: if '100' in obj.status_code:
# Can be a message (see handle_event_gc_config_change in # Can be a message (see handle_event_gc_config_change in
# gajim.py) # gajim.py)
self.print_conversation(\ self.print_conversation(
_('Any occupant is allowed to see your full JID')) _('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 # Can be a message (see handle_event_gc_config_change in
# gajim.py) # gajim.py)
self.print_conversation(_('Room logging is enabled')) 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')) self.print_conversation(_('A new room has been created'))
if '210' in statusCode: if '210' in obj.status_code:
self.print_conversation(\ self.print_conversation(\
_('The server has assigned or modified your roomnick')) _('The server has assigned or modified your roomnick'))
if show in ('offline', 'error'): if obj.show in ('offline', 'error'):
if statusCode: if obj.status_code:
if '307' in statusCode: if '307' in obj.status_code:
if actor is None: # do not print 'kicked by None' if obj.actor is None: # do not print 'kicked by None'
s = _('%(nick)s has been kicked: %(reason)s') % { s = _('%(nick)s has been kicked: %(reason)s') % {
'nick': nick, 'nick': obj.nick, 'reason': obj.reason}
'reason': reason }
else: else:
s = _('%(nick)s has been kicked by %(who)s: ' s = _('%(nick)s has been kicked by %(who)s: '
'%(reason)s') % {'nick': nick, 'who': actor, '%(reason)s') % {'nick': obj.nick, 'who': obj.actor,
'reason': reason } 'reason': obj.reason}
self.print_conversation(s, 'info', tim=tim, graphics=False) self.print_conversation(s, 'info', graphics=False)
if nick == self.nick and not gajim.config.get( if obj.nick == self.nick and not gajim.config.get(
'muc_autorejoin_on_kick'): 'muc_autorejoin_on_kick'):
self.autorejoin = False self.autorejoin = False
elif '301' in statusCode: elif '301' in obj.status_code:
if actor is None: # do not print 'banned by None' if obj.actor is None: # do not print 'banned by None'
s = _('%(nick)s has been banned: %(reason)s') % { s = _('%(nick)s has been banned: %(reason)s') % {
'nick': nick, 'reason': reason } 'nick': obj.nick, 'reason': obj.reason}
else: else:
s = _('%(nick)s has been banned by %(who)s: ' s = _('%(nick)s has been banned by %(who)s: '
'%(reason)s') % { 'nick': nick, 'who': actor, '%(reason)s') % {'nick': obj.nick, 'who': obj.actor,
'reason': reason } 'reason': obj.reason}
self.print_conversation(s, 'info', tim=tim, graphics=False) self.print_conversation(s, 'info', graphics=False)
if nick == self.nick: if obj.nick == self.nick:
self.autorejoin = False self.autorejoin = False
elif '303' in statusCode: # Someone changed his or her nick elif '303' in obj.status_code: # Someone changed his or her nick
if new_nick == self.new_nick or nick == self.nick: if obj.new_nick == self.new_nick or obj.nick == self.nick:
# We changed our nick # We changed our nick
self.nick = new_nick self.nick = obj.new_nick
self.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 # Stop all E2E sessions
nick_list = gajim.contacts.get_nick_list(self.account, nick_list = gajim.contacts.get_nick_list(self.account,
self.room_jid) self.room_jid)
@ -1334,24 +1337,24 @@ class GroupchatControl(ChatControlBase):
ctrl.no_autonegotiation = False ctrl.no_autonegotiation = False
else: else:
s = _('%(nick)s is now known as %(new_nick)s') % { 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 # We add new nick to muc roster here, so we don't see
# that "new_nick has joined the room" when he just changed # that "new_nick has joined the room" when he just changed
# nick. # nick.
# add_contact_to_roster will be called a second time # add_contact_to_roster will be called a second time
# after that, but that doesn't hurt # after that, but that doesn't hurt
self.add_contact_to_roster(new_nick, show, role, self.add_contact_to_roster(obj.new_nick, obj.show, role,
affiliation, status, jid) affiliation, obj.status, obj.real_jid)
if nick in self.attention_list: if obj.nick in self.attention_list:
self.attention_list.remove(nick) self.attention_list.remove(obj.nick)
# keep nickname color # keep nickname color
if nick in self.gc_custom_colors: if obj.nick in self.gc_custom_colors:
self.gc_custom_colors[new_nick] = \ self.gc_custom_colors[obj.new_nick] = \
self.gc_custom_colors[nick] self.gc_custom_colors[obj.nick]
# rename vcard / avatar # rename vcard / avatar
puny_jid = helpers.sanitize_filename(self.room_jid) puny_jid = helpers.sanitize_filename(self.room_jid)
puny_nick = helpers.sanitize_filename(nick) puny_nick = helpers.sanitize_filename(obj.nick)
puny_new_nick = helpers.sanitize_filename(new_nick) puny_new_nick = helpers.sanitize_filename(obj.new_nick)
old_path = os.path.join(gajim.VCARD_PATH, puny_jid, old_path = os.path.join(gajim.VCARD_PATH, puny_jid,
puny_nick) puny_nick)
new_path = os.path.join(gajim.VCARD_PATH, puny_jid, new_path = os.path.join(gajim.VCARD_PATH, puny_jid,
@ -1373,39 +1376,39 @@ class GroupchatControl(ChatControlBase):
# will also remove 'TEST' # will also remove 'TEST'
os.remove(files[old_file]) os.remove(files[old_file])
os.rename(old_file, files[old_file]) os.rename(old_file, files[old_file])
self.print_conversation(s, 'info', tim=tim, graphics=False) self.print_conversation(s, 'info', graphics=False)
elif '321' in statusCode: elif '321' in obj.status_code:
s = _('%(nick)s has been removed from the room ' s = _('%(nick)s has been removed from the room '
'(%(reason)s)') % { 'nick': nick, '(%(reason)s)') % { 'nick': obj.nick,
'reason': _('affiliation changed') } 'reason': _('affiliation changed') }
self.print_conversation(s, 'info', tim=tim, graphics=False) self.print_conversation(s, 'info', graphics=False)
elif '322' in statusCode: elif '322' in obj.status_code:
s = _('%(nick)s has been removed from the room ' s = _('%(nick)s has been removed from the room '
'(%(reason)s)') % { 'nick': nick, '(%(reason)s)') % { 'nick': obj.nick,
'reason': _('room configuration changed to ' 'reason': _('room configuration changed to '
'members-only') } 'members-only') }
self.print_conversation(s, 'info', tim=tim, graphics=False) self.print_conversation(s, 'info', graphics=False)
elif '332' in statusCode: elif '332' in obj.status_code:
s = _('%(nick)s has been removed from the room ' s = _('%(nick)s has been removed from the room '
'(%(reason)s)') % {'nick': nick, '(%(reason)s)') % {'nick': obj.nick,
'reason': _('system shutdown') } 'reason': _('system shutdown') }
self.print_conversation(s, 'info', tim=tim, graphics=False) self.print_conversation(s, 'info', graphics=False)
# Room has been destroyed. # Room has been destroyed.
elif 'destroyed' in statusCode: elif 'destroyed' in obj.status_code:
self.autorejoin = False 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: types=['pm'])) == 0:
self.remove_contact(nick) self.remove_contact(obj.nick)
self.draw_all_roles() self.draw_all_roles()
else: else:
c = gajim.contacts.get_gc_contact(self.account, self.room_jid, c = gajim.contacts.get_gc_contact(self.account, self.room_jid,
nick) obj.nick)
c.show = show c.show = obj.show
c.status = status c.status = obj.status
if nick == self.nick and (not statusCode or \ if obj.nick == self.nick and (not obj.status_code or \
'303' not in statusCode): # We became offline '303' not in obj.status_code): # We became offline
self.got_disconnected() self.got_disconnected()
contact = gajim.contacts.\ contact = gajim.contacts.\
get_contact_with_highest_priority(self.account, get_contact_with_highest_priority(self.account,
@ -1416,27 +1419,27 @@ class GroupchatControl(ChatControlBase):
if self.parent_win: if self.parent_win:
self.parent_win.redraw_tab(self) self.parent_win.redraw_tab(self)
else: else:
iter_ = self.get_contact_iter(nick) iter_ = self.get_contact_iter(obj.nick)
if not iter_: if not iter_:
if '210' in statusCode: if '210' in obj.status_code:
# Server changed our nick # Server changed our nick
self.nick = nick self.nick = obj.nick
s = _('You are now known as %s') % nick s = _('You are now known as %s') % obj.nick
self.print_conversation(s, 'info', tim=tim, graphics=False) self.print_conversation(s, 'info', graphics=False)
iter_ = self.add_contact_to_roster(nick, show, role, iter_ = self.add_contact_to_roster(obj.nick, obj.show, role,
affiliation, status, jid) affiliation, obj.status, obj.real_jid)
newly_created = True newly_created = True
self.draw_all_roles() 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 # We just created the room
gajim.connections[self.account].request_gc_config( gajim.connections[self.account].request_gc_config(
self.room_jid) self.room_jid)
else: else:
gc_c = gajim.contacts.get_gc_contact(self.account, gc_c = gajim.contacts.get_gc_contact(self.account,
self.room_jid, nick) self.room_jid, obj.nick)
if not gc_c: if not gc_c:
log.error('%s has an iter, but no gc_contact instance' % \ log.error('%s has an iter, but no gc_contact instance' % \
nick) obj.nick)
return return
# Re-get vcard if avatar has changed # Re-get vcard if avatar has changed
# We do that here because we may request it to the real JID if # 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: if gc_c and gc_c.jid:
real_jid = gc_c.jid real_jid = gc_c.jid
else: else:
real_jid = fake_jid real_jid = obj.fjid
if fake_jid in con.vcard_shas: if obj.fjid in obj.conn.vcard_shas:
if avatar_sha != con.vcard_shas[fake_jid]: if obj.avatar_sha != obj.conn.vcard_shas[obj.fjid]:
server = gajim.get_server_from_jid(self.room_jid) server = gajim.get_server_from_jid(self.room_jid)
if not server.startswith('irc'): if not server.startswith('irc'):
con.request_vcard(real_jid, fake_jid) obj.conn.request_vcard(real_jid, obj.fjid)
else: 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 \ if cached_vcard and 'PHOTO' in cached_vcard and \
'SHA' in cached_vcard['PHOTO']: 'SHA' in cached_vcard['PHOTO']:
cached_sha = cached_vcard['PHOTO']['SHA'] cached_sha = cached_vcard['PHOTO']['SHA']
else: else:
cached_sha = '' cached_sha = ''
if cached_sha != avatar_sha: if cached_sha != obj.avatar_sha:
# avatar has been updated # avatar has been updated
# sha in mem will be updated later # sha in mem will be updated later
server = gajim.get_server_from_jid(self.room_jid) server = gajim.get_server_from_jid(self.room_jid)
if not server.startswith('irc'): if not server.startswith('irc'):
con.request_vcard(real_jid, fake_jid) obj.conn.request_vcard(real_jid, obj.fjid)
else: else:
# save sha in mem NOW # 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 actual_affiliation = gc_c.affiliation
if affiliation != actual_affiliation: if affiliation != actual_affiliation:
if actor: if obj.actor:
st = _('** Affiliation of %(nick)s has been set to ' st = _('** Affiliation of %(nick)s has been set to '
'%(affiliation)s by %(actor)s') % {'nick': nick_jid, '%(affiliation)s by %(actor)s') % {'nick': nick_jid,
'affiliation': affiliation, 'actor': actor} 'affiliation': affiliation, 'actor': obj.actor}
else: else:
st = _('** Affiliation of %(nick)s has been set to ' st = _('** Affiliation of %(nick)s has been set to '
'%(affiliation)s') % {'nick': nick_jid, '%(affiliation)s') % {'nick': nick_jid,
'affiliation': affiliation} 'affiliation': affiliation}
if reason: if obj.reason:
st += ' (%s)' % reason st += ' (%s)' % obj.reason
self.print_conversation(st, tim=tim, graphics=False) self.print_conversation(st, graphics=False)
right_changed = True right_changed = True
actual_role = self.get_role(nick) actual_role = self.get_role(obj.nick)
if role != actual_role: if role != actual_role:
self.remove_contact(nick) self.remove_contact(obj.nick)
self.add_contact_to_roster(nick, show, role, affiliation, self.add_contact_to_roster(obj.nick, obj.show, role,
status, jid) affiliation, obj.status, obj.real_jid)
self.draw_role(actual_role) self.draw_role(actual_role)
self.draw_role(role) self.draw_role(role)
if actor: if obj.actor:
st = _('** Role of %(nick)s has been set to %(role)s ' st = _('** Role of %(nick)s has been set to %(role)s '
'by %(actor)s') % {'nick': nick_jid, 'role': role, 'by %(actor)s') % {'nick': nick_jid, 'role': role,
'actor': actor} 'actor': obj.actor}
else: else:
st = _('** Role of %(nick)s has been set to ' st = _('** Role of %(nick)s has been set to '
'%(role)s') % {'nick': nick_jid, 'role': role} '%(role)s') % {'nick': nick_jid, 'role': role}
if reason: if obj.reason:
st += ' (%s)' % reason st += ' (%s)' % obj.reason
self.print_conversation(st, tim=tim, graphics=False) self.print_conversation(st, graphics=False)
right_changed = True right_changed = True
else: 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 gc_c.affiliation == affiliation: # no change
return return
gc_c.show = show gc_c.show = obj.show
gc_c.affiliation = affiliation gc_c.affiliation = affiliation
gc_c.status = status gc_c.status = obj.status
self.draw_contact(nick) self.draw_contact(obj.nick)
if (time.time() - self.room_creation) > 30 and nick != self.nick and \ if (time.time() - self.room_creation) > 30 and obj.nick != self.nick \
(not statusCode or '303' not in statusCode) and not right_changed: and (not obj.status_code or '303' not in obj.status_code) and not \
right_changed:
st = '' st = ''
print_status = None print_status = None
for bookmark in gajim.connections[self.account].bookmarks: for bookmark in gajim.connections[self.account].bookmarks:
@ -1518,24 +1522,24 @@ class GroupchatControl(ChatControlBase):
break break
if not print_status: if not print_status:
print_status = gajim.config.get('print_status_in_muc') print_status = gajim.config.get('print_status_in_muc')
if show == 'offline': if obj.show == 'offline':
if nick in self.attention_list: if obj.nick in self.attention_list:
self.attention_list.remove(nick) self.attention_list.remove(obj.nick)
if show == 'offline' and print_status in ('all', 'in_and_out') and \ if obj.show == 'offline' and print_status in ('all', 'in_and_out') \
(not statusCode or '307' not in statusCode): and (not obj.status_code or '307' not in obj.status_code):
st = _('%s has left') % nick_jid st = _('%s has left') % nick_jid
if reason: if obj.reason:
st += ' [%s]' % reason st += ' [%s]' % obj.reason
else: else:
if newly_created and print_status in ('all', 'in_and_out'): if newly_created and print_status in ('all', 'in_and_out'):
st = _('%s has joined the group chat') % nick_jid st = _('%s has joined the group chat') % nick_jid
elif print_status == 'all': elif print_status == 'all':
st = _('%(nick)s is now %(status)s') % {'nick': nick_jid, 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 st:
if status: if obj.status:
st += ' (' + status + ')' st += ' (' + obj.status + ')'
self.print_conversation(st, tim=tim, graphics=False) self.print_conversation(st, graphics=False)
def add_contact_to_roster(self, nick, show, role, affiliation, status, def add_contact_to_roster(self, nick, show, role, affiliation, status,
jid=''): jid=''):
@ -1673,7 +1677,7 @@ class GroupchatControl(ChatControlBase):
del win._controls[self.account][self.contact.jid] del win._controls[self.account][self.contact.jid]
def shutdown(self, status='offline'): 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 # to let it remove it's GUI extension points
super(GroupchatControl, self).shutdown() super(GroupchatControl, self).shutdown()

View file

@ -133,9 +133,7 @@ class Interface:
#('INFORMATION', account, (title_text, section_text)) #('INFORMATION', account, (title_text, section_text))
dialogs.InformationDialog(data[0], data[1]) dialogs.InformationDialog(data[0], data[1])
def handle_event_ask_new_nick(self, account, data): def handle_ask_new_nick(self, account, room_jid):
#('ASK_NEW_NICK', account, (room_jid,))
room_jid = data[0]
title = _('Unable to join group chat') title = _('Unable to join group chat')
prompt = _('Your desired nickname in group chat %s is in use or ' prompt = _('Your desired nickname in group chat %s is in use or '
'registered by another occupant.\nPlease specify another nickname ' 'registered by another occupant.\nPlease specify another nickname '
@ -284,6 +282,79 @@ class Interface:
profile_window.ProfileWindow(account) profile_window.ProfileWindow(account)
gajim.connections[account].request_vcard(jid) 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): def handle_event_presence(self, obj):
# 'NOTIFY' (account, (jid, status, status message, resource, # 'NOTIFY' (account, (jid, status, status message, resource,
# priority, # keyID, timestamp, contact_nickname)) # priority, # keyID, timestamp, contact_nickname))
@ -883,30 +954,6 @@ class Interface:
self.instances[account]['gc_config'][obj.jid].\ self.instances[account]['gc_config'][obj.jid].\
affiliation_list_received(obj.users_dict) 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): def handle_event_gc_invitation(self, account, array):
#('GC_INVITATION', (room_jid, jid_from, reason, password, is_continued)) #('GC_INVITATION', (room_jid, jid_from, reason, password, is_continued))
jid = gajim.get_jid_without_resource(array[1]) jid = gajim.get_jid_without_resource(array[1])
@ -925,20 +972,6 @@ class Interface:
notify.popup(event_type, jid, account, 'gc-invitation', path, notify.popup(event_type, jid, account, 'gc-invitation', path,
event_type, room_jid) 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): def forget_gpg_passphrase(self, keyid):
if keyid in self.gpg_passphrase: if keyid in self.gpg_passphrase:
del self.gpg_passphrase[keyid] del self.gpg_passphrase[keyid]
@ -1893,8 +1926,6 @@ class Interface:
'GC_SUBJECT': [self.handle_event_gc_subject], 'GC_SUBJECT': [self.handle_event_gc_subject],
'GC_CONFIG_CHANGE': [self.handle_event_gc_config_change], 'GC_CONFIG_CHANGE': [self.handle_event_gc_config_change],
'GC_INVITATION': [self.handle_event_gc_invitation], '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], 'BAD_PASSPHRASE': [self.handle_event_bad_passphrase],
'CON_TYPE': [self.handle_event_con_type], 'CON_TYPE': [self.handle_event_con_type],
'CONNECTION_LOST': [self.handle_event_connection_lost], 'CONNECTION_LOST': [self.handle_event_connection_lost],
@ -1905,7 +1936,6 @@ class Interface:
'STANZA_SENT': [self.handle_event_stanza_sent], 'STANZA_SENT': [self.handle_event_stanza_sent],
'VCARD_PUBLISHED': [self.handle_event_vcard_published], 'VCARD_PUBLISHED': [self.handle_event_vcard_published],
'VCARD_NOT_PUBLISHED': [self.handle_event_vcard_not_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], 'SIGNED_IN': [self.handle_event_signed_in],
'METACONTACTS': [self.handle_event_metacontacts], 'METACONTACTS': [self.handle_event_metacontacts],
'ATOM_ENTRY': [self.handle_atom_entry], 'ATOM_ENTRY': [self.handle_atom_entry],
@ -1944,6 +1974,7 @@ class Interface:
'ARCHIVING_ERROR': [self.handle_event_archiving_error], 'ARCHIVING_ERROR': [self.handle_event_archiving_error],
'bookmarks-received': [self.handle_event_bookmarks], 'bookmarks-received': [self.handle_event_bookmarks],
'error-received': [self.handle_event_error_answer], 'error-received': [self.handle_event_error_answer],
'gc-presence-received': [self.handle_event_gc_presence],
'gmail-notify': [self.handle_event_gmail_notify], 'gmail-notify': [self.handle_event_gmail_notify],
'http-auth-received': [self.handle_event_http_auth], 'http-auth-received': [self.handle_event_http_auth],
'last-result-received': [self.handle_event_last_status_time], 'last-result-received': [self.handle_event_last_status_time],
@ -2707,7 +2738,7 @@ class Interface:
def get_fg_color(self, fmt='hex'): def get_fg_color(self, fmt='hex'):
def format_gdkcolor (c): def format_gdkcolor (c):
if fmt == 'tex': 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)]) ('rgb', c.red_float, c.green_float, c.blue_float)])
elif fmt == 'hex': elif fmt == 'hex':
return str(c) return str(c)