diff options
Diffstat (limited to 'poezio/tabs/muctab.py')
-rw-r--r-- | poezio/tabs/muctab.py | 1064 |
1 files changed, 617 insertions, 447 deletions
diff --git a/poezio/tabs/muctab.py b/poezio/tabs/muctab.py index 4438e015..94b521ba 100644 --- a/poezio/tabs/muctab.py +++ b/poezio/tabs/muctab.py @@ -34,7 +34,6 @@ from poezio.theming import get_theme, dump_tuple from poezio.user import User from poezio.core.structs import Completion, Status - NS_MUC_USER = 'http://jabber.org/protocol/muc#user' STATUS_XPATH = '{%s}x/{%s}status' % (NS_MUC_USER, NS_MUC_USER) @@ -129,11 +128,14 @@ class MucTab(ChatTab): seconds = delta.seconds + delta.days * 24 * 3600 else: seconds = 0 - muc.join_groupchat(self.core, self.name, self.own_nick, - self.password, - status=status.message, - show=status.show, - seconds=seconds) + muc.join_groupchat( + self.core, + self.name, + self.own_nick, + self.password, + status=status.message, + show=status.show, + seconds=seconds) def leave_room(self, message): if self.joined: @@ -152,8 +154,10 @@ class MucTab(ChatTab): 'You (\x19%(color)s}%(nick)s\x19%(info_col)s})' ' left the room' ' (\x19o%(reason)s\x19%(info_col)s})') % { - 'info_col': info_col, 'reason': message, - 'spec': char_quit, 'color': color, + 'info_col': info_col, + 'reason': message, + 'spec': char_quit, + 'color': color, 'color_spec': spec_col, 'nick': self.own_nick, } @@ -162,60 +166,77 @@ class MucTab(ChatTab): 'You (\x19%(color)s}%(nick)s\x19%(info_col)s})' ' left the room') % { 'info_col': info_col, - 'spec': char_quit, 'color': color, + 'spec': char_quit, + 'color': color, 'color_spec': spec_col, 'nick': self.own_nick, } self.add_message(msg, typ=2) self.disconnect() - muc.leave_groupchat(self.core.xmpp, self.name, self.own_nick, message) + muc.leave_groupchat(self.core.xmpp, self.name, self.own_nick, + message) self.core.disable_private_tabs(self.name, reason=msg) else: - muc.leave_groupchat(self.core.xmpp, self.name, self.own_nick, message) + muc.leave_groupchat(self.core.xmpp, self.name, self.own_nick, + message) def change_affiliation(self, nick_or_jid, affiliation, reason=''): """ Change the affiliation of a nick or JID """ + def callback(iq): if iq['type'] == 'error': - self.core.information("Could not set affiliation '%s' for '%s'." % ( - affiliation, nick_or_jid), "Warning") + self.core.information( + "Could not set affiliation '%s' for '%s'." % + (affiliation, nick_or_jid), "Warning") + if not self.joined: return valid_affiliations = ('outcast', 'none', 'member', 'admin', 'owner') if affiliation not in valid_affiliations: - return self.core.information('The affiliation must be one of ' + ', '.join(valid_affiliations), + return self.core.information('The affiliation must be one of ' + + ', '.join(valid_affiliations), 'Error') if nick_or_jid in [user.nick for user in self.users]: - res = muc.set_user_affiliation(self.core.xmpp, self.name, - affiliation, nick=nick_or_jid, - callback=callback, reason=reason) + res = muc.set_user_affiliation( + self.core.xmpp, + self.name, + affiliation, + nick=nick_or_jid, + callback=callback, + reason=reason) else: - res = muc.set_user_affiliation(self.core.xmpp, self.name, - affiliation, jid=safeJID(nick_or_jid), - callback=callback, reason=reason) + res = muc.set_user_affiliation( + self.core.xmpp, + self.name, + affiliation, + jid=safeJID(nick_or_jid), + callback=callback, + reason=reason) def change_role(self, nick, role, reason=''): """ Change the role of a nick """ + def callback(iq): if iq['type'] == 'error': - self.core.information("Could not set role '%s' for '%s'." % ( - role, nick), "Warning") + self.core.information("Could not set role '%s' for '%s'." % + (role, nick), "Warning") + valid_roles = ('none', 'visitor', 'participant', 'moderator') if not self.joined or role not in valid_roles: - return self.core.information('The role must be one of ' + ', '.join(valid_roles), - 'Error') + return self.core.information( + 'The role must be one of ' + ', '.join(valid_roles), 'Error') if not safeJID(self.name + '/' + nick): return self.core.information('Invalid nick', 'Info') - muc.set_user_role(self.core.xmpp, self.name, nick, reason, role, - callback=callback) + muc.set_user_role( + self.core.xmpp, self.name, nick, reason, role, callback=callback) @refresh_wrapper.conditional def print_info(self, nick): @@ -228,26 +249,24 @@ class MucTab(ChatTab): inf = '\x19' + dump_tuple(theme.COLOR_INFORMATION_TEXT) + '}' if user.jid: user_jid = '%s (\x19%s}%s\x19o%s)' % ( - inf, - dump_tuple(theme.COLOR_MUC_JID), - user.jid, - inf) + inf, dump_tuple(theme.COLOR_MUC_JID), user.jid, inf) else: user_jid = '' info = ('\x19%(user_col)s}%(nick)s\x19o%(jid)s%(info)s: show: ' '\x19%(show_col)s}%(show)s\x19o%(info)s, affiliation: ' '\x19%(role_col)s}%(affiliation)s\x19o%(info)s, role: ' '\x19%(role_col)s}%(role)s\x19o%(status)s') % { - 'user_col': dump_tuple(user.color), - 'nick': nick, - 'jid': user_jid, - 'info': inf, - 'show_col': dump_tuple(theme.color_show(user.show)), - 'show': user.show or 'Available', - 'role_col': dump_tuple(theme.color_role(user.role)), - 'affiliation': user.affiliation or 'None', - 'role': user.role or 'None', - 'status': '\n%s' % user.status if user.status else ''} + 'user_col': dump_tuple(user.color), + 'nick': nick, + 'jid': user_jid, + 'info': inf, + 'show_col': dump_tuple(theme.color_show(user.show)), + 'show': user.show or 'Available', + 'role_col': dump_tuple(theme.color_role(user.role)), + 'affiliation': user.affiliation or 'None', + 'role': user.role or 'None', + 'status': '\n%s' % user.status if user.status else '' + } self.add_message(info, typ=0) return True @@ -266,21 +285,24 @@ class MucTab(ChatTab): user = self.get_user_by_name(self.topic_from) if user: user_text = dump_tuple(user.color) - user_string = '\x19%s}(set by \x19%s}%s\x19%s})' % ( - info_text, user_text, user.nick, info_text) + user_string = '\x19%s}(set by \x19%s}%s\x19%s})' % (info_text, + user_text, + user.nick, + info_text) else: user_string = self.topic_from else: user_string = '' self._text_buffer.add_message( - "\x19%s}The subject of the room is: \x19%s}%s %s" % - (info_text, norm_text, self.topic, user_string)) + "\x19%s}The subject of the room is: \x19%s}%s %s" % + (info_text, norm_text, self.topic, user_string)) @refresh_wrapper.always def recolor(self, random_colors=False): """Recolor the current MUC users""" - deterministic = config.get_by_tabname('deterministic_nick_colors', self.name) + deterministic = config.get_by_tabname('deterministic_nick_colors', + self.name) if deterministic: for user in self.users: if user is self.own_user: @@ -321,14 +343,16 @@ class MucTab(ChatTab): return False if color == 'unset': if config.remove_and_save(nick, 'muc_colors'): - self.core.information('Color for nick %s unset' % (nick), 'Info') + self.core.information('Color for nick %s unset' % (nick), + 'Info') else: if color == 'random': color = random.choice(list(xhtml.colors)) if user: user.change_color(color) config.set_and_save(nick, color, 'muc_colors') - nick_color_aliases = config.get_by_tabname('nick_color_aliases', self.name) + nick_color_aliases = config.get_by_tabname('nick_color_aliases', + self.name) if nick_color_aliases: # if any user in the room has a nick which is an alias of the # nick, update its color @@ -347,9 +371,9 @@ class MucTab(ChatTab): return False self.input.do_command(key, raw=raw) empty_after = self.input.get_text() == '' - empty_after = empty_after or (self.input.get_text().startswith('/') - and not - self.input.get_text().startswith('//')) + empty_after = empty_after or ( + self.input.get_text().startswith('/') + and not self.input.get_text().startswith('//')) self.send_composing_chat_state(empty_after) return False @@ -381,7 +405,8 @@ class MucTab(ChatTab): and not config.get('show_useless_separator')): self.text_win.remove_line_separator() curses.curs_set(1) - if self.joined and config.get_by_tabname('send_chat_states', + if self.joined and config.get_by_tabname( + 'send_chat_states', self.general_jid) and not self.input.get_text(): self.send_chat_state('active') @@ -416,7 +441,8 @@ class MucTab(ChatTab): """ Batch-process all the initial presences """ - deterministic = config.get_by_tabname('deterministic_nick_colors', self.name) + deterministic = config.get_by_tabname('deterministic_nick_colors', + self.name) for stanza in self.presence_buffer: try: @@ -437,10 +463,11 @@ class MucTab(ChatTab): """ Presence received while we are not in the room (before code=110) """ - from_nick, from_room, affiliation, show, status, role, jid, typ = dissect_presence(presence) + from_nick, from_room, affiliation, show, status, role, jid, typ = dissect_presence( + presence) user_color = self.search_for_color(from_nick) - new_user = User(from_nick, affiliation, show, - status, role, jid, deterministic, user_color) + new_user = User(from_nick, affiliation, show, status, role, jid, + deterministic, user_color) self.users.append(new_user) self.core.events.trigger('muc_join', presence, self) if own: @@ -475,44 +502,43 @@ class MucTab(ChatTab): info_col = dump_tuple(get_theme().COLOR_INFORMATION_TEXT) warn_col = dump_tuple(get_theme().COLOR_WARNING_TEXT) spec_col = dump_tuple(get_theme().COLOR_JOIN_CHAR) - enable_message = ( - '\x19%(color_spec)s}%(spec)s\x19%(info_col)s} You ' - '(\x19%(nick_col)s}%(nick)s\x19%(info_col)s}) joined' - ' the room') % { - 'nick': from_nick, - 'spec': get_theme().CHAR_JOIN, - 'color_spec': spec_col, - 'nick_col': color, - 'info_col': info_col, - } + enable_message = ('\x19%(color_spec)s}%(spec)s\x19%(info_col)s} You ' + '(\x19%(nick_col)s}%(nick)s\x19%(info_col)s}) joined' + ' the room') % { + 'nick': from_nick, + 'spec': get_theme().CHAR_JOIN, + 'color_spec': spec_col, + 'nick_col': color, + 'info_col': info_col, + } self.add_message(enable_message, typ=2) self.core.enable_private_tabs(self.name, enable_message) if '201' in status_codes: self.add_message( - '\x19%(info_col)s}Info: The room ' - 'has been created' % - {'info_col': info_col}, + '\x19%(info_col)s}Info: The room ' + 'has been created' % {'info_col': info_col}, typ=0) if '170' in status_codes: self.add_message( - '\x19%(warn_col)s}Warning:\x19%(info_col)s}' - ' This room is publicly logged' % - {'info_col': info_col, - 'warn_col': warn_col}, + '\x19%(warn_col)s}Warning:\x19%(info_col)s}' + ' This room is publicly logged' % + {'info_col': info_col, + 'warn_col': warn_col}, typ=0) if '100' in status_codes: self.add_message( - '\x19%(warn_col)s}Warning:\x19%(info_col)s}' - ' This room is not anonymous.' % - {'info_col': info_col, - 'warn_col': warn_col}, + '\x19%(warn_col)s}Warning:\x19%(info_col)s}' + ' This room is not anonymous.' % + {'info_col': info_col, + 'warn_col': warn_col}, typ=0) def handle_presence_joined(self, presence, status_codes): """ Handle new presences when we are already in the room """ - from_nick, from_room, affiliation, show, status, role, jid, typ = dissect_presence(presence) + from_nick, from_room, affiliation, show, status, role, jid, typ = dissect_presence( + presence) change_nick = '303' in status_codes kick = '307' in status_codes and typ == 'unavailable' ban = '301' in status_codes and typ == 'unavailable' @@ -523,8 +549,8 @@ class MucTab(ChatTab): if not user and typ != "unavailable": user_color = self.search_for_color(from_nick) self.core.events.trigger('muc_join', presence, self) - self.on_user_join(from_nick, affiliation, show, status, role, - jid, user_color) + self.on_user_join(from_nick, affiliation, show, status, role, jid, + user_color) elif user is None: log.error('BUG: User %s in %s is None', from_nick, self.name) return @@ -533,13 +559,13 @@ class MucTab(ChatTab): self.on_user_nick_change(presence, user, from_nick, from_room) elif ban: self.core.events.trigger('muc_ban', presence, self) - self.core.on_user_left_private_conversation(from_room, - user, status) + self.core.on_user_left_private_conversation( + from_room, user, status) self.on_user_banned(presence, user, from_nick) elif kick: self.core.events.trigger('muc_kick', presence, self) - self.core.on_user_left_private_conversation(from_room, - user, status) + self.core.on_user_left_private_conversation( + from_room, user, status) self.on_user_kicked(presence, user, from_nick) elif shutdown: self.core.events.trigger('muc_shutdown', presence, self) @@ -549,38 +575,40 @@ class MucTab(ChatTab): self.on_non_member_kicked() # user quit elif typ == 'unavailable': - self.on_user_leave_groupchat(user, jid, status, - from_nick, from_room) + self.on_user_leave_groupchat(user, jid, status, from_nick, + from_room) # status change else: - self.on_user_change_status(user, from_nick, from_room, - affiliation, role, show, status) + self.on_user_change_status(user, from_nick, from_room, affiliation, + role, show, status) def on_non_member_kicked(self): """We have been kicked because the MUC is members-only""" self.add_message( - '\x19%(info_col)s}You have been kicked because you ' - 'are not a member and the room is now members-only.' % { - 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}, + '\x19%(info_col)s}You have been kicked because you ' + 'are not a member and the room is now members-only.' % + {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}, typ=2) self.disconnect() def on_muc_shutdown(self): """We have been kicked because the MUC service is shutting down""" self.add_message( - '\x19%(info_col)s}You have been kicked because the' - ' MUC service is shutting down.' % { - 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}, + '\x19%(info_col)s}You have been kicked because the' + ' MUC service is shutting down.' % + {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}, typ=2) self.disconnect() - def on_user_join(self, from_nick, affiliation, show, status, role, jid, color): + def on_user_join(self, from_nick, affiliation, show, status, role, jid, + color): """ When a new user joins the groupchat """ - deterministic = config.get_by_tabname('deterministic_nick_colors', self.name) - user = User(from_nick, affiliation, - show, status, role, jid, deterministic, color) + deterministic = config.get_by_tabname('deterministic_nick_colors', + self.name) + user = User(from_nick, affiliation, show, status, role, jid, + deterministic, color) bisect.insort_left(self.users, user) hide_exit_join = config.get_by_tabname('hide_exit_join', self.general_jid) @@ -596,27 +624,30 @@ class MucTab(ChatTab): if not jid.full: msg = ('\x19%(color_spec)s}%(spec)s \x19%(color)s}%(nick)s' '\x19%(info_col)s} joined the room') % { - 'nick': from_nick, 'spec': char_join, - 'color': color, - 'info_col': info_col, - 'color_spec': spec_col, - } + 'nick': from_nick, + 'spec': char_join, + 'color': color, + 'info_col': info_col, + 'color_spec': spec_col, + } else: msg = ('\x19%(color_spec)s}%(spec)s \x19%(color)s}%(nick)s' '\x19%(info_col)s} (\x19%(jid_color)s}%(jid)s\x19' '%(info_col)s}) joined the room') % { - 'spec': char_join, 'nick': from_nick, - 'color':color, 'jid':jid.full, - 'info_col': info_col, - 'jid_color': dump_tuple(get_theme().COLOR_MUC_JID), - 'color_spec': spec_col, - } + 'spec': char_join, + 'nick': from_nick, + 'color': color, + 'jid': jid.full, + 'info_col': info_col, + 'jid_color': dump_tuple(get_theme().COLOR_MUC_JID), + 'color_spec': spec_col, + } self.add_message(msg, typ=2) self.core.on_user_rejoined_private_conversation(self.name, from_nick) def on_user_nick_change(self, presence, user, from_nick, from_room): - new_nick = presence.xml.find('{%s}x/{%s}item' % (NS_MUC_USER, NS_MUC_USER) - ).attrib['nick'] + new_nick = presence.xml.find('{%s}x/{%s}item' % + (NS_MUC_USER, NS_MUC_USER)).attrib['nick'] if user.nick == self.own_nick: self.own_nick = new_nick # also change our nick in all private discussions of this room @@ -624,8 +655,8 @@ class MucTab(ChatTab): else: color = config.get_by_tabname(new_nick, 'muc_colors') if color != '': - deterministic = config.get_by_tabname('deterministic_nick_colors', - self.name) + deterministic = config.get_by_tabname( + 'deterministic_nick_colors', self.name) user.change_color(color, deterministic) user.change_nick(new_nick) self.users.remove(user) @@ -637,11 +668,15 @@ class MucTab(ChatTab): else: color = 3 info_col = dump_tuple(get_theme().COLOR_INFORMATION_TEXT) - self.add_message('\x19%(color)s}%(old)s\x19%(info_col)s} is' - ' now known as \x19%(color)s}%(new)s' % { - 'old':from_nick, 'new':new_nick, - 'color':color, 'info_col': info_col}, - typ=2) + self.add_message( + '\x19%(color)s}%(old)s\x19%(info_col)s} is' + ' now known as \x19%(color)s}%(new)s' % { + 'old': from_nick, + 'new': new_nick, + 'color': color, + 'info_col': info_col + }, + typ=2) # rename the private tabs if needed self.core.rename_private_tabs(self.name, from_nick, user) @@ -662,16 +697,20 @@ class MucTab(ChatTab): info_col = dump_tuple(get_theme().COLOR_INFORMATION_TEXT) char_kick = get_theme().CHAR_KICK - if from_nick == self.own_nick: # we are banned + if from_nick == self.own_nick: # we are banned if by: kick_msg = ('\x191}%(spec)s \x193}You\x19%(info_col)s}' ' have been banned by \x194}%(by)s') % { - 'spec': char_kick, 'by': by, - 'info_col': info_col} + 'spec': char_kick, + 'by': by, + 'info_col': info_col + } else: kick_msg = ('\x191}%(spec)s \x193}You\x19' '%(info_col)s} have been banned.') % { - 'spec': char_kick, 'info_col': info_col} + 'spec': char_kick, + 'info_col': info_col + } self.core.disable_private_tabs(self.name, reason=kick_msg) self.disconnect() self.refresh_tab_win() @@ -684,11 +723,9 @@ class MucTab(ChatTab): if delay <= 0: muc.join_groupchat(self.core, self.name, self.own_nick) else: - self.core.add_timed_event(timed_events.DelayedEvent( - delay, - muc.join_groupchat, - self.core, - self.name, + self.core.add_timed_event( + timed_events.DelayedEvent(delay, muc.join_groupchat, + self.core, self.name, self.own_nick)) else: @@ -702,18 +739,26 @@ class MucTab(ChatTab): kick_msg = ('\x191}%(spec)s \x19%(color)s}' '%(nick)s\x19%(info_col)s} ' 'has been banned by \x194}%(by)s') % { - 'spec': char_kick, 'nick': from_nick, - 'color': color, 'by': by, - 'info_col': info_col} + 'spec': char_kick, + 'nick': from_nick, + 'color': color, + 'by': by, + 'info_col': info_col + } else: kick_msg = ('\x191}%(spec)s \x19%(color)s}%(nick)s' '\x19%(info_col)s} has been banned') % { - 'spec': char_kick, 'nick': from_nick, - 'color': color, 'info_col': info_col} + 'spec': char_kick, + 'nick': from_nick, + 'color': color, + 'info_col': info_col + } if reason is not None and reason.text: kick_msg += ('\x19%(info_col)s} Reason: \x196}' '%(reason)s\x19%(info_col)s}') % { - 'reason': reason.text, 'info_col': info_col} + 'reason': reason.text, + 'info_col': info_col + } self.add_message(kick_msg, typ=2) def on_user_kicked(self, presence, user, from_nick): @@ -730,18 +775,21 @@ class MucTab(ChatTab): char_kick = get_theme().CHAR_KICK if actor_elem is not None: by = actor_elem.get('nick') or actor_elem.get('jid') - if from_nick == self.own_nick: # we are kicked + if from_nick == self.own_nick: # we are kicked if by: kick_msg = ('\x191}%(spec)s \x193}You\x19' '%(info_col)s} have been kicked' ' by \x193}%(by)s') % { - 'spec': char_kick, 'by': by, - 'info_col': info_col} + 'spec': char_kick, + 'by': by, + 'info_col': info_col + } else: kick_msg = ('\x191}%(spec)s \x193}You\x19%(info_col)s}' ' have been kicked.') % { - 'spec': char_kick, - 'info_col': info_col} + 'spec': char_kick, + 'info_col': info_col + } self.core.disable_private_tabs(self.name, reason=kick_msg) self.disconnect() self.refresh_tab_win() @@ -755,12 +803,10 @@ class MucTab(ChatTab): if delay <= 0: muc.join_groupchat(self.core, self.name, self.own_nick) else: - self.core.add_timed_event(timed_events.DelayedEvent( - delay, - muc.join_groupchat, - self.core, - self.name, - self.own_nick)) + self.core.add_timed_event( + timed_events.DelayedEvent(delay, muc.join_groupchat, + self.core, self.name, + self.own_nick)) else: if config.get_by_tabname('display_user_color_in_join_part', self.general_jid): @@ -771,17 +817,26 @@ class MucTab(ChatTab): kick_msg = ('\x191}%(spec)s \x19%(color)s}%(nick)s' '\x19%(info_col)s} has been kicked by ' '\x193}%(by)s') % { - 'spec': char_kick, 'nick':from_nick, - 'color':color, 'by':by, 'info_col': info_col} + 'spec': char_kick, + 'nick': from_nick, + 'color': color, + 'by': by, + 'info_col': info_col + } else: kick_msg = ('\x191}%(spec)s \x19%(color)s}%(nick)s' '\x19%(info_col)s} has been kicked') % { - 'spec': char_kick, 'nick': from_nick, - 'color':color, 'info_col': info_col} + 'spec': char_kick, + 'nick': from_nick, + 'color': color, + 'info_col': info_col + } if reason is not None and reason.text: kick_msg += ('\x19%(info_col)s} Reason: \x196}' '%(reason)s') % { - 'reason': reason.text, 'info_col': info_col} + 'reason': reason.text, + 'info_col': info_col + } self.add_message(kick_msg, typ=2) def on_user_leave_groupchat(self, user, jid, status, from_nick, from_room): @@ -812,35 +867,39 @@ class MucTab(ChatTab): leave_msg = ('\x19%(color_spec)s}%(spec)s \x19%(color)s}' '%(nick)s\x19%(info_col)s} has left the ' 'room') % { - 'nick':from_nick, 'color':color, - 'spec':get_theme().CHAR_QUIT, - 'info_col': info_col, - 'color_spec': spec_col} + 'nick': from_nick, + 'color': color, + 'spec': get_theme().CHAR_QUIT, + 'info_col': info_col, + 'color_spec': spec_col + } else: jid_col = dump_tuple(get_theme().COLOR_MUC_JID) leave_msg = ('\x19%(color_spec)s}%(spec)s \x19%(color)s}' '%(nick)s\x19%(info_col)s} (\x19%(jid_col)s}' '%(jid)s\x19%(info_col)s}) has left the ' 'room') % { - 'spec':get_theme().CHAR_QUIT, - 'nick':from_nick, 'color':color, - 'jid':jid.full, 'info_col': info_col, - 'color_spec': spec_col, - 'jid_col': jid_col} + 'spec': get_theme().CHAR_QUIT, + 'nick': from_nick, + 'color': color, + 'jid': jid.full, + 'info_col': info_col, + 'color_spec': spec_col, + 'jid_col': jid_col + } if status: leave_msg += ' (\x19o%s\x19%s})' % (status, info_col) self.add_message(leave_msg, typ=2) - self.core.on_user_left_private_conversation(from_room, user, - status) + self.core.on_user_left_private_conversation(from_room, user, status) - def on_user_change_status( - self, user, from_nick, from_room, affiliation, role, show, status): + def on_user_change_status(self, user, from_nick, from_room, affiliation, + role, show, status): """ When an user changes her status """ # build the message - display_message = False # flag to know if something significant enough - # to be displayed has changed + display_message = False # flag to know if something significant enough + # to be displayed has changed if config.get_by_tabname('display_user_color_in_join_part', self.general_jid): color = dump_tuple(user.color) @@ -848,12 +907,15 @@ class MucTab(ChatTab): color = 3 if from_nick == self.own_nick: msg = '\x19%(color)s}You\x19%(info_col)s} changed: ' % { - 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT), - 'color': color} + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT), + 'color': color + } else: msg = '\x19%(color)s}%(nick)s\x19%(info_col)s} changed: ' % { - 'nick': from_nick, 'color': color, - 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} + 'nick': from_nick, + 'color': color, + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT) + } if affiliation != user.affiliation: msg += 'affiliation: %s, ' % affiliation display_message = True @@ -873,7 +935,7 @@ class MucTab(ChatTab): display_message = True if not display_message: return - msg = msg[:-2] # remove the last ", " + msg = msg[:-2] # remove the last ", " hide_status_change = config.get_by_tabname('hide_status_change', self.general_jid) if hide_status_change < -1: @@ -891,8 +953,8 @@ class MucTab(ChatTab): role != user.role): # display the message in the room self._text_buffer.add_message(msg) - self.core.on_user_changed_status_in_private('%s/%s' % - (from_room, from_nick), + self.core.on_user_changed_status_in_private('%s/%s' % (from_room, + from_nick), Status(show, status)) self.users.remove(user) # finally, effectively change the user status @@ -922,7 +984,7 @@ class MucTab(ChatTab): Log the messages in the archives, if it needs to be """ - if time is None and self.joined: # don't log the history messages + if time is None and self.joined: # don't log the history messages if not logger.log_message(self.name, nickname, txt, typ=typ): self.core.information('Unable to write in the log file', 'Error') @@ -965,32 +1027,44 @@ class MucTab(ChatTab): args['user'] = kwargs['forced_user'] if (not time and nickname and nickname != self.own_nick - and self.state != 'current'): - if (self.state != 'highlight' and - config.get_by_tabname('notify_messages', self.name)): + and self.state != 'current'): + if (self.state != 'highlight' + and config.get_by_tabname('notify_messages', self.name)): self.state = 'message' if time and not txt.startswith('/me'): txt = '\x19%(info_col)s}%(txt)s' % { - 'txt': txt, - 'info_col': dump_tuple(get_theme().COLOR_LOG_MSG)} + 'txt': txt, + 'info_col': dump_tuple(get_theme().COLOR_LOG_MSG) + } elif not nickname: txt = '\x19%(info_col)s}%(txt)s' % { - 'txt': txt, - 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} - elif not kwargs.get('highlight'): # TODO + 'txt': txt, + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT) + } + elif not kwargs.get('highlight'): # TODO args['highlight'] = self.do_highlight(txt, time, nickname) time = time or datetime.now() self._text_buffer.add_message(txt, time, nickname, **args) return args.get('highlight', False) - def modify_message(self, txt, old_id, new_id, - time=None, nickname=None, user=None, jid=None): + def modify_message(self, + txt, + old_id, + new_id, + time=None, + nickname=None, + user=None, + jid=None): self.log_message(txt, nickname, time=time, typ=1) highlight = self.do_highlight(txt, time, nickname, corrected=True) - message = self._text_buffer.modify_message(txt, old_id, new_id, - highlight=highlight, - time=time, user=user, - jid=jid) + message = self._text_buffer.modify_message( + txt, + old_id, + new_id, + highlight=highlight, + time=time, + user=user, + jid=jid) if message: self.text_win.modify_message(old_id, message) return highlight @@ -1000,11 +1074,13 @@ class MucTab(ChatTab): return [(1, safeJID(self.name).user), (3, self.name)] def enable_self_ping_event(self): - delay = config.get_by_tabname("self_ping_delay", self.general_jid, default=0) - if delay <= 0: # use 0 or some negative value to disable it + delay = config.get_by_tabname( + "self_ping_delay", self.general_jid, default=0) + if delay <= 0: # use 0 or some negative value to disable it return self.disable_self_ping_event() - self.self_ping_event = timed_events.DelayedEvent(delay, self.send_self_ping) + self.self_ping_event = timed_events.DelayedEvent( + delay, self.send_self_ping) self.core.add_timed_event(self.self_ping_event) def disable_self_ping_event(self): @@ -1014,16 +1090,17 @@ class MucTab(ChatTab): def send_self_ping(self): to = self.name + "/" + self.own_nick - self.core.xmpp.plugin['xep_0199'].send_ping(jid=to, - callback=self.on_self_ping_result, - timeout_callback=self.on_self_ping_failed, - timeout=60) + self.core.xmpp.plugin['xep_0199'].send_ping( + jid=to, + callback=self.on_self_ping_result, + timeout_callback=self.on_self_ping_failed, + timeout=60) def on_self_ping_result(self, iq): if iq["type"] == "error" and iq["error"]["condition"] != "feature-not-implemented": self.command_cycle(iq["error"]["text"] or "not in this room") self.core.refresh_window() - else: # Re-send a self-ping in a few seconds + else: # Re-send a self-ping in a few seconds self.enable_self_ping_event() def search_for_color(self, nick): @@ -1035,7 +1112,8 @@ class MucTab(ChatTab): color = config.get_by_tabname(nick, 'muc_colors') if color != '': return color - nick_color_aliases = config.get_by_tabname('nick_color_aliases', self.name) + nick_color_aliases = config.get_by_tabname('nick_color_aliases', + self.name) if nick_color_aliases: nick_alias = re.sub('^_*(.*?)_*$', '\\1', nick) color = config.get_by_tabname(nick_alias, 'muc_colors') @@ -1088,26 +1166,23 @@ class MucTab(ChatTab): tab_win_height = Tab.tab_win_height() info_win_height = self.core.information_win_size - - self.user_win.resize(self.height - 3 - info_win_height - - tab_win_height, - self.width - (self.width // 10) * 9 - 1, - 1, - (self.width // 10) * 9 + 1) - self.v_separator.resize(self.height - 3 - info_win_height - tab_win_height, - 1, 1, 9 * (self.width // 10)) + self.user_win.resize( + self.height - 3 - info_win_height - tab_win_height, self.width - + (self.width // 10) * 9 - 1, 1, (self.width // 10) * 9 + 1) + self.v_separator.resize( + self.height - 3 - info_win_height - tab_win_height, 1, 1, + 9 * (self.width // 10)) self.topic_win.resize(1, self.width, 0, 0) - self.text_win.resize(self.height - 3 - info_win_height - - tab_win_height, - text_width, 1, 0) + self.text_win.resize( + self.height - 3 - info_win_height - tab_win_height, text_width, 1, + 0) self.text_win.rebuild_everything(self._text_buffer) - self.info_header.resize(1, self.width, - self.height - 2 - info_win_height - - tab_win_height, - 0) - self.input.resize(1, self.width, self.height-1, 0) + self.info_header.resize( + 1, self.width, self.height - 2 - info_win_height - tab_win_height, + 0) + self.input.resize(1, self.width, self.height - 1, 0) def refresh(self): if self.need_resize: @@ -1131,40 +1206,40 @@ class MucTab(ChatTab): self.input.refresh() def on_info_win_size_changed(self): - if self.core.information_win_size >= self.height-3: + if self.core.information_win_size >= self.height - 3: return if config.get("hide_user_list"): text_width = self.width else: - text_width = (self.width//10)*9 - self.user_win.resize(self.height - 3 - self.core.information_win_size - - Tab.tab_win_height(), - self.width - (self.width // 10) * 9 - 1, - 1, + text_width = (self.width // 10) * 9 + self.user_win.resize(self.height - 3 - self.core.information_win_size - + Tab.tab_win_height(), + self.width - (self.width // 10) * 9 - 1, 1, (self.width // 10) * 9 + 1) - self.v_separator.resize(self.height - 3 - self.core.information_win_size - Tab.tab_win_height(), - 1, 1, 9 * (self.width // 10)) - self.text_win.resize(self.height - 3 - self.core.information_win_size - - Tab.tab_win_height(), - text_width, 1, 0) - self.info_header.resize(1, self.width, - self.height-2-self.core.information_win_size - - Tab.tab_win_height(), - 0) + self.v_separator.resize( + self.height - 3 - self.core.information_win_size - + Tab.tab_win_height(), 1, 1, 9 * (self.width // 10)) + self.text_win.resize(self.height - 3 - self.core.information_win_size - + Tab.tab_win_height(), text_width, 1, 0) + self.info_header.resize( + 1, self.width, self.height - 2 - self.core.information_win_size - + Tab.tab_win_height(), 0) + def do_highlight(self, txt, time, nickname, corrected=False): """ Set the tab color and returns the nick color """ highlighted = False - if (not time or corrected) and nickname and nickname != self.own_nick and self.joined: + if (not time or corrected + ) and nickname and nickname != self.own_nick and self.joined: if re.search(r'\b' + self.own_nick.lower() + r'\b', txt.lower()): if self.state != 'current': self.state = 'highlight' highlighted = True else: - highlight_words = config.get_by_tabname('highlight_on', - self.general_jid) + highlight_words = config.get_by_tabname( + 'highlight_on', self.general_jid) highlight_words = highlight_words.split(':') for word in highlight_words: if word and word.lower() in txt.lower(): @@ -1205,11 +1280,11 @@ class MucTab(ChatTab): """ /configure """ + def on_form_received(form): if not form: self.core.information( - 'Could not retrieve the configuration form', - 'Error') + 'Could not retrieve the configuration form', 'Error') return self.core.open_new_form(form, self.cancel_config, self.send_config) @@ -1254,17 +1329,18 @@ class MucTab(ChatTab): """ /version <jid or nick> """ + def callback(res): if not res: return self.core.information('Could not get the software ' - 'version from %s' % (jid,), + 'version from %s' % (jid, ), 'Warning') version = '%s is running %s version %s on %s' % ( - jid, - res.get('name') or 'an unknown software', - res.get('version') or 'unknown', - res.get('os') or 'an unknown platform') + jid, res.get('name') or 'an unknown software', + res.get('version') or 'unknown', + res.get('os') or 'an unknown platform') self.core.information(version, 'Info') + if args is None: return self.core.command.help('version') nick = args[0] @@ -1273,8 +1349,7 @@ class MucTab(ChatTab): jid = safeJID(jid + '/' + nick) else: jid = safeJID(nick) - fixes.get_version(self.core.xmpp, jid, - callback=callback) + fixes.get_version(self.core.xmpp, jid, callback=callback) @command_args_parser.quoted(1) def command_nick(self, args): @@ -1290,8 +1365,7 @@ class MucTab(ChatTab): current_status = self.core.get_status() if not safeJID(self.name + '/' + nick): return self.core.information('Invalid nick', 'Info') - muc.change_nick(self.core, self.name, nick, - current_status.message, + muc.change_nick(self.core, self.name, nick, current_status.message, current_status.show) @command_args_parser.quoted(0, 1, ['']) @@ -1323,7 +1397,7 @@ class MucTab(ChatTab): /query <nick> [message] """ if args is None: - return self.core.command.help('query') + return self.core.command.help('query') nick = args[0] r = None for user in self.users: @@ -1332,7 +1406,7 @@ class MucTab(ChatTab): if r and len(args) == 2: msg = args[1] self.core.current_tab().command_say( - xhtml.convert_simple_to_full_colors(msg)) + xhtml.convert_simple_to_full_colors(msg)) if not r: self.core.information("Cannot find user: %s" % nick, 'Error') @@ -1355,11 +1429,11 @@ class MucTab(ChatTab): return aff = { - 'owner': get_theme().CHAR_AFFILIATION_OWNER, - 'admin': get_theme().CHAR_AFFILIATION_ADMIN, - 'member': get_theme().CHAR_AFFILIATION_MEMBER, - 'none': get_theme().CHAR_AFFILIATION_NONE, - } + 'owner': get_theme().CHAR_AFFILIATION_OWNER, + 'admin': get_theme().CHAR_AFFILIATION_ADMIN, + 'member': get_theme().CHAR_AFFILIATION_MEMBER, + 'none': get_theme().CHAR_AFFILIATION_NONE, + } colors = {} colors["visitor"] = dump_tuple(get_theme().COLOR_USER_VISITOR) @@ -1372,8 +1446,9 @@ class MucTab(ChatTab): affiliation = aff.get(user.affiliation, get_theme().CHAR_AFFILIATION_NONE) color = colors.get(user.role, color_other) - buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % ( - color, affiliation, dump_tuple(user.color), user.nick)) + buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % + (color, affiliation, dump_tuple(user.color), + user.nick)) buff.append('\n') message = ' '.join(buff) @@ -1414,6 +1489,7 @@ class MucTab(ChatTab): Changes the role of an user roles can be: none, visitor, participant, moderator """ + def callback(iq): if iq['type'] == 'error': self.core.room_error(iq, self.name) @@ -1431,6 +1507,7 @@ class MucTab(ChatTab): Changes the affiliation of an user affiliations can be: outcast, none, member, admin, owner """ + def callback(iq): if iq['type'] == 'error': self.core.room_error(iq, self.name) @@ -1542,9 +1619,8 @@ class MucTab(ChatTab): after = config.get('after_completion') + ' ' input_pos = self.input.pos if ' ' not in self.input.get_text()[:input_pos] or ( - self.input.last_completion and - self.input.get_text()[:input_pos] == - self.input.last_completion + after): + self.input.last_completion and self.input.get_text() + [:input_pos] == self.input.last_completion + after): add_after = after else: if not config.get('add_space_after_completion'): @@ -1553,9 +1629,9 @@ class MucTab(ChatTab): add_after = ' ' self.input.auto_completion(word_list, add_after, quotify=False) empty_after = self.input.get_text() == '' - empty_after = empty_after or (self.input.get_text().startswith('/') - and not - self.input.get_text().startswith('//')) + empty_after = empty_after or ( + self.input.get_text().startswith('/') + and not self.input.get_text().startswith('//')) self.send_composing_chat_state(empty_after) def completion_version(self, the_input): @@ -1584,15 +1660,18 @@ class MucTab(ChatTab): def completion_nick(self, the_input): """Completion for /nick""" - nicks = [os.environ.get('USER'), - config.get('default_nick'), - self.core.get_bookmark_nickname(self.name)] + nicks = [ + os.environ.get('USER'), + config.get('default_nick'), + self.core.get_bookmark_nickname(self.name) + ] nicks = [i for i in nicks if i] return Completion(the_input.auto_completion, nicks, '', quotify=False) def completion_recolor(self, the_input): if the_input.get_argument_position() == 1: - return Completion(the_input.new_completion, ['random'], 1, '', quotify=False) + return Completion( + the_input.new_completion, ['random'], 1, '', quotify=False) return True def completion_color(self, the_input): @@ -1602,13 +1681,15 @@ class MucTab(ChatTab): userlist = [user.nick for user in self.users] if self.own_nick in userlist: userlist.remove(self.own_nick) - return Completion(the_input.new_completion, userlist, 1, '', quotify=True) + return Completion( + the_input.new_completion, userlist, 1, '', quotify=True) elif n == 2: colors = [i for i in xhtml.colors if i] colors.sort() colors.append('unset') colors.append('random') - return Completion(the_input.new_completion, colors, 2, '', quotify=False) + return Completion( + the_input.new_completion, colors, 2, '', quotify=False) def completion_ignore(self, the_input): """Completion for /ignore""" @@ -1625,11 +1706,12 @@ class MucTab(ChatTab): userlist = [user.nick for user in self.users] if self.own_nick in userlist: userlist.remove(self.own_nick) - return Completion(the_input.new_completion, userlist, 1, '', quotify=True) + return Completion( + the_input.new_completion, userlist, 1, '', quotify=True) elif n == 2: possible_roles = ['none', 'visitor', 'participant', 'moderator'] - return Completion(the_input.new_completion, possible_roles, 2, '', - quotify=True) + return Completion( + the_input.new_completion, possible_roles, 2, '', quotify=True) def completion_affiliation(self, the_input): """Completion for /affiliation""" @@ -1642,22 +1724,30 @@ class MucTab(ChatTab): if self.core.xmpp.boundjid.bare in jidlist: jidlist.remove(self.core.xmpp.boundjid.bare) userlist.extend(jidlist) - return Completion(the_input.new_completion, userlist, 1, '', quotify=True) + return Completion( + the_input.new_completion, userlist, 1, '', quotify=True) elif n == 2: - possible_affiliations = ['none', 'member', 'admin', - 'owner', 'outcast'] - return Completion(the_input.new_completion, possible_affiliations, 2, '', - quotify=True) + possible_affiliations = [ + 'none', 'member', 'admin', 'owner', 'outcast' + ] + return Completion( + the_input.new_completion, + possible_affiliations, + 2, + '', + quotify=True) def completion_invite(self, the_input): """Completion for /invite""" n = the_input.get_argument_position(quoted=True) if n == 1: - return Completion(the_input.new_completion, roster.jids(), 1, quotify=True) + return Completion( + the_input.new_completion, roster.jids(), 1, quotify=True) def completion_topic(self, the_input): if the_input.get_argument_position() == 1: - return Completion(the_input.auto_completion, [self.topic], '', quotify=False) + return Completion( + the_input.auto_completion, [self.topic], '', quotify=False) def completion_quoted(self, the_input): """Nick completion, but with quotes""" @@ -1668,13 +1758,15 @@ class MucTab(ChatTab): if user.nick != self.own_nick: word_list.append(user.nick) - return Completion(the_input.new_completion, word_list, 1, quotify=True) + return Completion( + the_input.new_completion, word_list, 1, quotify=True) def completion_unignore(self, the_input): if the_input.get_argument_position() == 1: users = [user.nick for user in self.ignores] return Completion(the_input.auto_completion, users, quotify=False) + ########################## REGISTER STUFF ############################## def register_keys(self): @@ -1687,183 +1779,261 @@ class MucTab(ChatTab): def register_commands(self): "Register tab-specific commands" - self.register_commands_batch([ - { - 'name': 'ignore', - 'func': self.command_ignore, - 'usage': '<nickname>', - 'desc': 'Ignore a specified nickname.', - 'shortdesc': 'Ignore someone', - 'completion': self.completion_unignore - }, - { - 'name': 'unignore', - 'func': self.command_unignore, - 'usage': '<nickname>', - 'desc': 'Remove the specified nickname from the ignore list.', - 'shortdesc': 'Unignore someone.', - 'completion': self.completion_unignore - }, - { - 'name': 'kick', - 'func': self.command_kick, - 'usage': '<nick> [reason]', - 'desc': ('Kick the user with the specified nickname.' - ' You also can give an optional reason.'), - 'shortdesc': 'Kick someone.', - 'completion': self.completion_quoted - }, - { - 'name': 'ban', - 'func': self.command_ban, - 'usage': '<nick> [reason]', - 'desc': ('Ban the user with the specified nickname.' - ' You also can give an optional reason.'), - 'shortdesc': 'Ban someone', - 'completion': self.completion_quoted - }, - { - 'name': 'role', - 'func': self.command_role, - 'usage': '<nick> <role> [reason]', - 'desc': ('Set the role of an user. Roles can be:' - ' none, visitor, participant, moderator.' - ' You also can give an optional reason.'), - 'shortdesc': 'Set the role of an user.', - 'completion': self.completion_role - }, - { - 'name': 'affiliation', - 'func': self.command_affiliation, - 'usage': '<nick or jid> <affiliation>', - 'desc': ('Set the affiliation of an user. Affiliations can be:' - ' outcast, none, member, admin, owner.'), - 'shortdesc': 'Set the affiliation of an user.', - 'completion': self.completion_affiliation - }, - { - 'name': 'topic', - 'func': self.command_topic, - 'usage': '<subject>', - 'desc': 'Change the subject of the room.', - 'shortdesc': 'Change the subject.', - 'completion': self.completion_topic - }, - { - 'name': 'subject', - 'func': self.command_topic, - 'usage': '<subject>', - 'desc': 'Change the subject of the room.', - 'shortdesc': 'Change the subject.', - 'completion': self.completion_topic - }, - { - 'name': 'query', - 'func': self.command_query, - 'usage': '<nick> [message]', - 'desc': ('Open a private conversation with <nick>. This nick' - ' has to be present in the room you\'re currently in.' - ' If you specified a message after the nickname, it ' - 'will immediately be sent to this user.'), - 'shortdesc': 'Query a user.', - 'completion': self.completion_quoted - }, - { - 'name': 'part', - 'func': self.command_part, - 'usage': '[message]', - 'desc': ('Disconnect from a room. You can' - ' specify an optional message.'), - 'shortdesc': 'Leave the room.' - }, - { - 'name': 'close', - 'func': self.command_close, - 'usage': '[message]', - 'desc': ('Disconnect from a room and close the tab.' - ' You can specify an optional message if ' - 'you are still connected.'), - 'shortdesc': 'Close the tab.' - }, - { - 'name': 'nick', - 'func': self.command_nick, - 'usage': '<nickname>', - 'desc': 'Change your nickname in the current room.', - 'shortdesc': 'Change your nickname.', - 'completion': self.completion_nick - }, - { - 'name':'recolor', - 'func': self.command_recolor, - 'usage': '[random]', - 'desc': ('Re-assign a color to all participants of the' - ' current room, based on the last time they talked.' - ' Use this if the participants currently talking ' - 'have too many identical colors. Use /recolor random' - ' for a non-deterministic result.'), - 'shortdesc': 'Change the nicks colors.', - 'completion': self.completion_recolor - }, - { - 'name': 'color', - 'func': self.command_color, - 'usage': '<nick> <color>', - 'desc': ('Fix a color for a nick. Use "unset" instead of a ' - 'color to remove the attribution'), - 'shortdesc': 'Fix a color for a nick.', - 'completion': self.completion_recolor - }, - { - 'name': 'cycle', - 'func': self.command_cycle, - 'usage': '[message]', - 'desc': 'Leave the current room and rejoin it immediately.', - 'shortdesc': 'Leave and re-join the room.' - }, - { - 'name': 'info', - 'func': self.command_info, - 'usage': '<nickname>', - 'desc': ('Display some information about the user ' - 'in the MUC: its/his/her role, affiliation,' - ' status and status message.'), - 'shortdesc': 'Show an user\'s infos.', - 'completion': self.completion_info - }, - { - 'name': 'configure', - 'func': self.command_configure, - 'desc': 'Configure the current room, through a form.', - 'shortdesc': 'Configure the room.' - }, - { - 'name': 'version', - 'func': self.command_version, - 'usage': '<jid or nick>', - 'desc': ('Get the software version of the given JID' - ' or nick in room (usually its XMPP client' - ' and Operating System).'), - 'shortdesc': 'Get the software version of a jid.', - 'completion': self.completion_version - }, - { - 'name': 'names', - 'func': self.command_names, - 'desc': 'Get the users in the room with their roles.', - 'shortdesc': 'List the users.' - }, - { - 'name': 'invite', - 'func': self.command_invite, - 'desc': 'Invite a contact to this room', - 'usage': '<jid> [reason]', - 'shortdesc': 'Invite a contact to this room', - 'completion': self.completion_invite - } - ]) + self.register_commands_batch([{ + 'name': 'ignore', + 'func': self.command_ignore, + 'usage': '<nickname>', + 'desc': 'Ignore a specified nickname.', + 'shortdesc': 'Ignore someone', + 'completion': self.completion_unignore + }, { + 'name': + 'unignore', + 'func': + self.command_unignore, + 'usage': + '<nickname>', + 'desc': + 'Remove the specified nickname from the ignore list.', + 'shortdesc': + 'Unignore someone.', + 'completion': + self.completion_unignore + }, { + 'name': + 'kick', + 'func': + self.command_kick, + 'usage': + '<nick> [reason]', + 'desc': ('Kick the user with the specified nickname.' + ' You also can give an optional reason.'), + 'shortdesc': + 'Kick someone.', + 'completion': + self.completion_quoted + }, { + 'name': + 'ban', + 'func': + self.command_ban, + 'usage': + '<nick> [reason]', + 'desc': ('Ban the user with the specified nickname.' + ' You also can give an optional reason.'), + 'shortdesc': + 'Ban someone', + 'completion': + self.completion_quoted + }, { + 'name': + 'role', + 'func': + self.command_role, + 'usage': + '<nick> <role> [reason]', + 'desc': ('Set the role of an user. Roles can be:' + ' none, visitor, participant, moderator.' + ' You also can give an optional reason.'), + 'shortdesc': + 'Set the role of an user.', + 'completion': + self.completion_role + }, { + 'name': + 'affiliation', + 'func': + self.command_affiliation, + 'usage': + '<nick or jid> <affiliation>', + 'desc': ('Set the affiliation of an user. Affiliations can be:' + ' outcast, none, member, admin, owner.'), + 'shortdesc': + 'Set the affiliation of an user.', + 'completion': + self.completion_affiliation + }, { + 'name': + 'topic', + 'func': + self.command_topic, + 'usage': + '<subject>', + 'desc': + 'Change the subject of the room.', + 'shortdesc': + 'Change the subject.', + 'completion': + self.completion_topic + }, { + 'name': + 'subject', + 'func': + self.command_topic, + 'usage': + '<subject>', + 'desc': + 'Change the subject of the room.', + 'shortdesc': + 'Change the subject.', + 'completion': + self.completion_topic + }, { + 'name': + 'query', + 'func': + self.command_query, + 'usage': + '<nick> [message]', + 'desc': ('Open a private conversation with <nick>. This nick' + ' has to be present in the room you\'re currently in.' + ' If you specified a message after the nickname, it ' + 'will immediately be sent to this user.'), + 'shortdesc': + 'Query a user.', + 'completion': + self.completion_quoted + }, { + 'name': + 'part', + 'func': + self.command_part, + 'usage': + '[message]', + 'desc': ('Disconnect from a room. You can' + ' specify an optional message.'), + 'shortdesc': + 'Leave the room.' + }, { + 'name': + 'close', + 'func': + self.command_close, + 'usage': + '[message]', + 'desc': ('Disconnect from a room and close the tab.' + ' You can specify an optional message if ' + 'you are still connected.'), + 'shortdesc': + 'Close the tab.' + }, { + 'name': + 'nick', + 'func': + self.command_nick, + 'usage': + '<nickname>', + 'desc': + 'Change your nickname in the current room.', + 'shortdesc': + 'Change your nickname.', + 'completion': + self.completion_nick + }, { + 'name': + 'recolor', + 'func': + self.command_recolor, + 'usage': + '[random]', + 'desc': ('Re-assign a color to all participants of the' + ' current room, based on the last time they talked.' + ' Use this if the participants currently talking ' + 'have too many identical colors. Use /recolor random' + ' for a non-deterministic result.'), + 'shortdesc': + 'Change the nicks colors.', + 'completion': + self.completion_recolor + }, { + 'name': + 'color', + 'func': + self.command_color, + 'usage': + '<nick> <color>', + 'desc': ('Fix a color for a nick. Use "unset" instead of a ' + 'color to remove the attribution'), + 'shortdesc': + 'Fix a color for a nick.', + 'completion': + self.completion_recolor + }, { + 'name': + 'cycle', + 'func': + self.command_cycle, + 'usage': + '[message]', + 'desc': + 'Leave the current room and rejoin it immediately.', + 'shortdesc': + 'Leave and re-join the room.' + }, { + 'name': + 'info', + 'func': + self.command_info, + 'usage': + '<nickname>', + 'desc': ('Display some information about the user ' + 'in the MUC: its/his/her role, affiliation,' + ' status and status message.'), + 'shortdesc': + 'Show an user\'s infos.', + 'completion': + self.completion_info + }, { + 'name': + 'configure', + 'func': + self.command_configure, + 'desc': + 'Configure the current room, through a form.', + 'shortdesc': + 'Configure the room.' + }, { + 'name': + 'version', + 'func': + self.command_version, + 'usage': + '<jid or nick>', + 'desc': ('Get the software version of the given JID' + ' or nick in room (usually its XMPP client' + ' and Operating System).'), + 'shortdesc': + 'Get the software version of a jid.', + 'completion': + self.completion_version + }, { + 'name': + 'names', + 'func': + self.command_names, + 'desc': + 'Get the users in the room with their roles.', + 'shortdesc': + 'List the users.' + }, { + 'name': + 'invite', + 'func': + self.command_invite, + 'desc': + 'Invite a contact to this room', + 'usage': + '<jid> [reason]', + 'shortdesc': + 'Invite a contact to this room', + 'completion': + self.completion_invite + }]) + + +class PresenceError(Exception): + pass -class PresenceError(Exception): pass def dissect_presence(presence): """ |