diff options
-rw-r--r-- | src/tabs/muctab.py | 510 |
1 files changed, 355 insertions, 155 deletions
diff --git a/src/tabs/muctab.py b/src/tabs/muctab.py index 157b28d9..ceda58a5 100644 --- a/src/tabs/muctab.py +++ b/src/tabs/muctab.py @@ -96,22 +96,27 @@ class MucTab(ChatTab): completion=self.completion_unignore) self.register_command('kick', self.command_kick, usage=_('<nick> [reason]'), - desc=_('Kick the user with the specified nickname. You also can give an optional reason.'), + desc=_('Kick the user with the specified nickname.' + ' You also can give an optional reason.'), shortdesc=_('Kick someone.'), completion=self.completion_quoted) self.register_command('ban', self.command_ban, usage=_('<nick> [reason]'), - desc=_('Ban the user with the specified nickname. You also can give an optional reason.'), + desc=_('Ban the user with the specified nickname.' + ' You also can give an optional reason.'), shortdesc='Ban someone', completion=self.completion_quoted) self.register_command('role', 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.'), + 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) self.register_command('affiliation', self.command_affiliation, usage=_('<nick or jid> <affiliation>'), - desc=_('Set the affiliation of an user. Affiliations can be: outcast, none, member, admin, owner.'), + 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) self.register_command('topic', self.command_topic, @@ -121,16 +126,22 @@ class MucTab(ChatTab): completion=self.completion_topic) self.register_command('query', self.command_query, usage=_('<nick> [message]'), - desc=_('Query: 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.'), + 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 an user.'), completion=self.completion_quoted) self.register_command('part', self.command_part, usage=_('[message]'), - desc=_('Disconnect from a room. You can specify an optional message.'), + desc=_('Disconnect from a room. You can' + ' specify an optional message.'), shortdesc=_('Leave the room.')) self.register_command('close', 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.'), + desc=_('Disconnect from a room and close the tab.' + ' You can specify an optional message if ' + 'you are still connected.'), shortdesc=_('Close the tab.')) self.register_command('nick', self.command_nick, usage=_('<nickname>'), @@ -152,7 +163,9 @@ class MucTab(ChatTab): shortdesc=_('Leave and re-join the room.')) self.register_command('info', self.command_info, usage=_('<nickname>'), - desc=_('Display some information about the user in the MUC: its/his/her role, affiliation, status and status message.'), + 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) self.register_command('configure', self.command_configure, @@ -160,11 +173,13 @@ class MucTab(ChatTab): shortdesc=_('Configure the room.')) self.register_command('version', 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).'), + 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) self.register_command('names', self.command_names, - desc=_('Get the list of the users in the room, and the list of the people assuming the different roles.'), + desc=_('Get the users in the room with their roles.'), shortdesc=_('List the users.')) self.register_command('invite', self.command_invite, desc=_('Invite a contact to this room'), @@ -211,23 +226,32 @@ class MucTab(ChatTab): def completion_version(self, the_input): """Completion for /version""" compare_users = lambda x: x.last_talked - userlist = [user.nick for user in sorted(self.users, key=compare_users, reverse=True)\ - if user.nick != self.own_nick] - comp = sorted(reduce(lambda x, y: x + [i.jid for i in y], - (roster[jid].resources for jid in roster.jids() if len(roster[jid])), - [])) + userlist = [] + for user in sorted(self.users, key=compare_users, reverse=True): + if user.nick != self.own_nick: + userlist.append(user.nick) + comp = [] + for jid in (jid for jid in roster.jids() if len(roster[jid])): + for resource in roster[jid].resources: + comp.append(resource.jid) + comp.sort() userlist.extend(comp) - return the_input.new_completion(userlist, 1, quotify=False) + + return the_input.auto_completion(userlist, quotify=False) def completion_info(self, the_input): """Completion for /info""" compare_users = lambda x: x.last_talked - userlist = [user.nick for user in sorted(self.users, key=compare_users, reverse=True)] + userlist = [] + for user in sorted(self.users, key=compare_users, reverse=True): + userlist.append(user.nick) return the_input.auto_completion(userlist, quotify=False) def completion_nick(self, the_input): """Completion for /nick""" - nicks = [os.environ.get('USER'), config.get('default_nick', ''), self.core.get_bookmark_nickname(self.get_name())] + nicks = [os.environ.get('USER'), + config.get('default_nick', ''), + self.core.get_bookmark_nickname(self.get_name())] nicks = [i for i in nicks if i] return the_input.auto_completion(nicks, '', quotify=False) @@ -254,7 +278,8 @@ class MucTab(ChatTab): return the_input.new_completion(userlist, 1, '', quotify=True) elif n == 2: possible_roles = ['none', 'visitor', 'participant', 'moderator'] - return the_input.new_completion(possible_roles, 2, '', quotify=True) + return the_input.new_completion(possible_roles, 2, '', + quotify=True) def completion_affiliation(self, the_input): """Completion for /affiliation""" @@ -269,8 +294,10 @@ class MucTab(ChatTab): userlist.extend(jidlist) return the_input.new_completion(userlist, 1, '', quotify=True) elif n == 2: - possible_affiliations = ['none', 'member', 'admin', 'owner', 'outcast'] - return the_input.new_completion(possible_affiliations, 2, '', quotify=True) + possible_affiliations = ['none', 'member', 'admin', + 'owner', 'outcast'] + return the_input.new_completion(possible_affiliations, 2, '', + quotify=True) def command_invite(self, args): """/invite <jid> [reason]""" @@ -307,12 +334,19 @@ class MucTab(ChatTab): return self.core.command_help('info') user = self.get_user_by_name(arg) if not user: - return self.core.information("Unknown user: %s" % arg) + return self.core.information(_("Unknown user: %s") % arg) theme = get_theme() - info = '\x19%s}%s\x19o%s: show: \x19%s}%s\x19o, affiliation: \x19%s}%s\x19o, role: \x19%s}%s\x19o%s' % ( + if user.jid: + user_jid = ' (\x19%s}%s\x19o)' % ( + dump_tuple(theme.COLOR_MUC_JID), + user.jid) + else: + user_jid = '' + info = _('\x19%s}%s\x19o%s: show: \x19%s}%s\x19o, affiliation:' + ' \x19%s}%s\x19o, role: \x19%s}%s\x19o%s') % ( dump_tuple(user.color), arg, - (' (\x19%s}%s\x19o)' % (dump_tuple(theme.COLOR_MUC_JID), user.jid)) if user.jid != '' else '', + user_jid, dump_tuple(theme.color_show(user.show)), user.show or 'Available', dump_tuple(theme.color_role(user.role)), @@ -323,9 +357,14 @@ class MucTab(ChatTab): self.core.information(info, 'Info') def command_configure(self, arg): + """ + /configure + """ form = fixes.get_room_form(self.core.xmpp, self.get_name()) if not form: - self.core.information('Could not retrieve the configuration form', 'Error') + self.core.information( + _('Could not retrieve the configuration form'), + _('Error')) return self.core.open_new_form(form, self.cancel_config, self.send_config) @@ -381,8 +420,11 @@ class MucTab(ChatTab): """ def callback(res): if not res: - return self.core.information('Could not get the software version from %s' % (jid,), 'Warning') - version = '%s is running %s version %s on %s' % (jid, + return self.core.information(_('Could not get the software ' + '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')) @@ -405,11 +447,14 @@ class MucTab(ChatTab): return self.core.command_help('nick') nick = arg if not self.joined: - return self.core.information('/nick only works in joined rooms', 'Info') + return self.core.information(_('/nick only works in joined rooms'), + _('Info')) current_status = self.core.get_status() if not safeJID(self.get_name() + '/' + nick): return self.core.information('Invalid nick', 'Info') - muc.change_nick(self.core, self.name, nick, current_status.message, current_status.show) + muc.change_nick(self.core, self.name, nick, + current_status.message, + current_status.show) def command_part(self, arg): """ @@ -423,7 +468,7 @@ class MucTab(ChatTab): spec_col = dump_tuple(get_theme().COLOR_QUIT_CHAR) if config.get_by_tabname('display_user_color_in_join_part', True, - self.general_jid, True): + self.general_jid, True): color = dump_tuple(get_theme().COLOR_OWN_NICK) else: color = 3 @@ -477,7 +522,8 @@ class MucTab(ChatTab): r = self.core.open_private_window(self.name, user.nick) if r and len(args) > 1: msg = args[1] - self.core.current_tab().command_say(xhtml.convert_simple_to_full_colors(msg)) + self.core.current_tab().command_say( + xhtml.convert_simple_to_full_colors(msg)) if not r: self.core.information(_("Cannot find user: %s" % nick), 'Error') @@ -486,8 +532,10 @@ class MucTab(ChatTab): /topic [new topic] """ if not arg.strip(): - self._text_buffer.add_message(_("\x19%s}The subject of the room is: %s") % - (dump_tuple(get_theme().COLOR_INFORMATION_TEXT), self.topic)) + self._text_buffer.add_message( + _("\x19%s}The subject of the room is: %s") % + dump_tuple(get_theme().COLOR_INFORMATION_TEXT, + self.topic)) self.refresh() return subject = arg @@ -514,7 +562,8 @@ class MucTab(ChatTab): users = self.users[:] users.sort(key=lambda x: x.nick.lower()) for user in users: - color = aff.get(user.affiliation, get_theme().CHAR_AFFILIATION_NONE) + color = aff.get(user.affiliation, + get_theme().CHAR_AFFILIATION_NONE) if user.role == 'visitor': visitors.append((user, color)) elif user.role == 'participant': @@ -526,17 +575,21 @@ class MucTab(ChatTab): buff = ['Users: %s \n' % len(self.users)] for moderator in moderators: - buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % (color_moderator, - moderator[1], dump_tuple(moderator[0].color), moderator[0].nick)) + buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % ( + color_moderator, moderator[1], + dump_tuple(moderator[0].color), moderator[0].nick)) for participant in participants: - buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % (color_participant, - participant[1], dump_tuple(participant[0].color), participant[0].nick)) + buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % ( + color_participant, participant[1], + dump_tuple(participant[0].color), participant[0].nick)) for visitor in visitors: - buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % (color_visitor, - visitor[1], dump_tuple(visitor[0].color), visitor[0].nick)) + buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % ( + color_visitor, visitor[1], + dump_tuple(visitor[0].color), visitor[0].nick)) for other in others: - buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % (color_other, - other[1], dump_tuple(other[0].color), other[0].nick)) + buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % ( + color_other, other[1], + dump_tuple(other[0].color), other[0].nick)) buff.append('\n') message = ' '.join(buff) @@ -552,8 +605,11 @@ class MucTab(ChatTab): """Nick completion, but with quotes""" if the_input.get_argument_position(quoted=True) == 1: compare_users = lambda x: x.last_talked - word_list = [user.nick for user in sorted(self.users, key=compare_users, reverse=True)\ - if user.nick != self.own_nick] + word_list = [] + for user in sorted(self.users, key=compare_users, reverse=True): + if user.nick != self.own_nick: + word_list.append(user.nick) + return the_input.new_completion(word_list, 1, quotify=True) def command_kick(self, arg): @@ -587,9 +643,13 @@ class MucTab(ChatTab): nick = args[0] if nick in [user.nick for user in self.users]: - res = muc.set_user_affiliation(self.core.xmpp, self.get_name(), 'outcast', nick=nick, callback=callback, reason=msg) + res = muc.set_user_affiliation(self.core.xmpp, self.get_name(), + 'outcast', nick=nick, + callback=callback, reason=msg) else: - res = muc.set_user_affiliation(self.core.xmpp, self.get_name(), 'outcast', jid=safeJID(nick), callback=callback, reason=msg) + res = muc.set_user_affiliation(self.core.xmpp, self.get_name(), + 'outcast', jid=safeJID(nick), + callback=callback, reason=msg) if not res: self.core.information('Could not ban user', 'Error') @@ -616,7 +676,8 @@ class MucTab(ChatTab): return if not safeJID(self.get_name() + '/' + nick): return self.core('Invalid nick', 'Info') - muc.set_user_role(self.core.xmpp, self.get_name(), nick, reason, role, callback=callback) + muc.set_user_role(self.core.xmpp, self.get_name(), nick, reason, role, + callback=callback) def command_affiliation(self, arg): """ @@ -638,11 +699,15 @@ class MucTab(ChatTab): self.core.command_help('affiliation') return if nick in [user.nick for user in self.users]: - res = muc.set_user_affiliation(self.core.xmpp, self.get_name(), affiliation, nick=nick, callback=callback) + res = muc.set_user_affiliation(self.core.xmpp, self.get_name(), + affiliation, nick=nick, + callback=callback) else: - res = muc.set_user_affiliation(self.core.xmpp, self.get_name(), affiliation, jid=safeJID(nick), callback=callback) + res = muc.set_user_affiliation(self.core.xmpp, self.get_name(), + affiliation, jid=safeJID(nick), + callback=callback) if not res: - self.core.information('Could not set affiliation', 'Error') + self.core.information(_('Could not set affiliation'), _('Error')) def command_say(self, line, correct=False): """ @@ -666,7 +731,8 @@ class MucTab(ChatTab): msg.enable('html') msg['html']['body'] = xhtml.poezio_colors_to_html(msg['body']) msg['body'] = xhtml.clean_text(msg['body']) - if config.get_by_tabname('send_chat_states', True, self.general_jid, True) and self.remote_wants_chatstates is not False: + if (config.get_by_tabname('send_chat_states', True, self.general_jid, + True) and self.remote_wants_chatstates is not False): msg['chat_state'] = needed if correct: msg['replace']['id'] = self.last_sent_message['id'] @@ -723,7 +789,8 @@ class MucTab(ChatTab): def completion_unignore(self, the_input): if the_input.get_argument_position() == 1: - return the_input.new_completion([user.nick for user in self.ignores], 1, '', quotify=False) + users = [user.nick for user in self.ignores] + return the_input.auto_completion(users, quotify=False) def resize(self): """ @@ -736,12 +803,23 @@ class MucTab(ChatTab): 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, (self.width//10)*9+1) + 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.topic_win.resize(1, self.width, 0, 0) - self.v_separator.resize(self.height-2 - 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.v_separator.resize(self.height - 2 - 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.text_win.rebuild_everything(self._text_buffer) - self.info_header.resize(1, self.width, self.height-2-self.core.information_win_size - Tab.tab_win_height(), 0) + self.info_header.resize(1, self.width, + self.height - 2 + - self.core.information_win_size + - Tab.tab_win_height(), + 0) self.input.resize(1, self.width, self.height-1, 0) def refresh(self): @@ -763,7 +841,10 @@ class MucTab(ChatTab): self.key_func[key]() return False self.input.do_command(key, raw=raw) - empty_after = self.input.get_text() == '' or (self.input.get_text().startswith('/') and not self.input.get_text().startswith('//')) + empty_after = self.input.get_text() == '' + 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 @@ -774,19 +855,30 @@ class MucTab(ChatTab): if self.complete_commands(self.input): return - # If we are not completing a command or a command's argument, complete a nick + # If we are not completing a command or a command argument, + # complete a nick compare_users = lambda x: x.last_talked - word_list = [user.nick for user in sorted(self.users, key=compare_users, reverse=True)\ - if user.nick != self.own_nick] - after = config.get('after_completion', ',')+" " + word_list = [] + for user in sorted(self.users, key=compare_users, reverse=True): + if user.nick != self.own_nick: + word_list.append(user.nick) + 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): + 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): add_after = after else: - add_after = '' if not config.get('add_space_after_completion', True) else ' ' + if not config.get('add_space_after_completion', True): + add_after = '' + else: + add_after = ' ' self.input.auto_completion(word_list, add_after, quotify=False) - empty_after = self.input.get_text() == '' or (self.input.get_text().startswith('/') and not self.input.get_text().startswith('//')) + empty_after = self.input.get_text() == '' + 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 get_name(self): @@ -810,16 +902,19 @@ class MucTab(ChatTab): self.state = 'disconnected' self.text_win.remove_line_separator() self.text_win.add_line_separator(self._text_buffer) - if config.get_by_tabname('send_chat_states', True, self.general_jid, True) and not self.input.get_text(): + if config.get_by_tabname('send_chat_states', True, + self.general_jid, True) and not self.input.get_text(): self.send_chat_state('inactive') self.check_scrolled() def on_gain_focus(self): self.state = 'current' - if self.text_win.built_lines and self.text_win.built_lines[-1] is None and not config.get('show_useless_separator', False): + if (self.text_win.built_lines and self.text_win.built_lines[-1] is None + and not config.get('show_useless_separator', False)): self.text_win.remove_line_separator() curses.curs_set(1) - if self.joined and config.get_by_tabname('send_chat_states', True, self.general_jid, True) and not self.input.get_text(): + if self.joined and config.get_by_tabname('send_chat_states', True, + self.general_jid, True) and not self.input.get_text(): self.send_chat_state('active') def on_info_win_size_changed(self): @@ -829,14 +924,27 @@ class MucTab(ChatTab): 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, (self.width//10)*9+1) - 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.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.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 handle_presence(self, presence): from_nick = presence['from'].resource from_room = presence['from'].bare - status_codes = set([s.attrib['code'] for s in presence.findall('{%s}x/{%s}status' % (NS_MUC_USER, NS_MUC_USER))]) + xpath = '{%s}x/{%s}status' % (NS_MUC_USER, NS_MUC_USER) + status_codes = set() + for status_code in presence.findall(xpath): + status_codes.add(status_code.attrib['code']) + # Check if it's not an error presence. if presence['type'] == 'error': return self.core.room_error(presence, from_room) @@ -848,8 +956,10 @@ class MucTab(ChatTab): typ = presence['type'] if not self.joined: # user in the room BEFORE us. # ignore redondant presence message, see bug #1509 - if from_nick not in [user.nick for user in self.users] and typ != "unavailable": - new_user = User(from_nick, affiliation, show, status, role, jid) + if (from_nick not in [user.nick for user in self.users] + and typ != "unavailable"): + new_user = User(from_nick, affiliation, show, + status, role, jid) self.users.append(new_user) self.core.events.trigger('muc_join', presence, self) if '110' in status_codes or self.own_nick == from_nick: @@ -863,12 +973,13 @@ class MucTab(ChatTab): self._state = 'normal' elif self != self.core.current_tab(): self._state = 'joined' - if self.core.current_tab() == self and self.core.status.show not in ('xa', 'away'): + if (self.core.current_tab() is self + and self.core.status.show not in ('xa', 'away')): self.send_chat_state('active') new_user.color = get_theme().COLOR_OWN_NICK - if config.get_by_tabname('display_user_color_in_join_part', True, - self.general_jid, True): + if config.get_by_tabname('display_user_color_in_join_part', + True, self.general_jid, True): color = dump_tuple(new_user.color) else: color = 3 @@ -893,21 +1004,21 @@ class MucTab(ChatTab): self.add_message( _('\x19%(info_col)s}Info: The room ' 'has been created') % - {'info_col': info_col }, + {'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}, + {'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}, + {'info_col': info_col, + 'warn_col': warn_col}, typ=0) if self.core.current_tab() is not self: self.refresh_tab_win() @@ -924,19 +1035,22 @@ class MucTab(ChatTab): # New user if not user: self.core.events.trigger('muc_join', presence, self) - self.on_user_join(from_nick, affiliation, show, status, role, jid) + self.on_user_join(from_nick, affiliation, show, status, role, + jid) # nick change elif change_nick: self.core.events.trigger('muc_nickchange', presence, self) 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, from_nick, status) + self.core.on_user_left_private_conversation(from_room, + from_nick, status) self.on_user_banned(presence, user, from_nick) # kick elif kick: self.core.events.trigger('muc_kick', presence, self) - self.core.on_user_left_private_conversation(from_room, from_nick, status) + self.core.on_user_left_private_conversation(from_room, + from_nick, status) self.on_user_kicked(presence, user, from_nick) elif shutdown: self.core.events.trigger('muc_shutdown', presence, self) @@ -946,10 +1060,12 @@ 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) if self.core.current_tab() is self: self.text_win.refresh() self.user_win.refresh(self.users) @@ -982,7 +1098,8 @@ class MucTab(ChatTab): user = User(from_nick, affiliation, show, status, role, jid) self.users.append(user) - hide_exit_join = config.get_by_tabname('hide_exit_join', -1, self.general_jid, True) + hide_exit_join = config.get_by_tabname('hide_exit_join', -1, + self.general_jid, True) if hide_exit_join != 0: if config.get_by_tabname('display_user_color_in_join_part', True, self.general_jid, True): @@ -1014,17 +1131,25 @@ class MucTab(ChatTab): 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.find('{%s}x/{%s}item' % (NS_MUC_USER, NS_MUC_USER)).attrib['nick'] + new_nick = presence.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 self.core.on_muc_own_nickchange(self) user.change_nick(new_nick) - color = dump_tuple(user.color) if config.get_by_tabname('display_user_color_in_join_part', True, self.general_jid, True) else 3 - 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': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}, - typ=2) + + if config.get_by_tabname('display_user_color_in_join_part', True, + self.general_jid, True): + color = dump_tuple(user.color) + 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) # rename the private tabs if needed self.core.rename_private_tabs(self.name, from_nick, new_nick) @@ -1033,49 +1158,68 @@ class MucTab(ChatTab): When someone is banned from a muc """ self.users.remove(user) - by = presence.find('{%s}x/{%s}item/{%s}actor' % (NS_MUC_USER, NS_MUC_USER, NS_MUC_USER)) - reason = presence.find('{%s}x/{%s}item/{%s}reason' % (NS_MUC_USER, NS_MUC_USER, NS_MUC_USER)) + by = presence.find('{%s}x/{%s}item/{%s}actor' % + (NS_MUC_USER, NS_MUC_USER, NS_MUC_USER)) + reason = presence.find('{%s}x/{%s}item/{%s}reason' % + (NS_MUC_USER, NS_MUC_USER, NS_MUC_USER)) by = by.attrib['jid'] if by is not None else None + + 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 by: - kick_msg = _('\x191}%(spec)s \x193}You\x19%(info_col)s} have been banned by \x194}%(by)s') % { - 'spec': get_theme().CHAR_KICK, 'by':by, - 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} + 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} else: - kick_msg = _('\x191}%(spec)s \x193}You\x19%(info_col)s} have been banned.') % { - 'spec': get_theme().CHAR_KICK, - 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} + kick_msg = _('\x191}%(spec)s \x193}You\x19' + '%(info_col)s} have been banned.') % { + 'spec': char_kick, 'info_col': info_col} self.core.disable_private_tabs(self.name, reason=kick_msg) self.disconnect() self.refresh_tab_win() self.core.current_tab().input.refresh() self.core.doupdate() - if config.get_by_tabname('autorejoin', False, self.general_jid, True): - delay = config.get_by_tabname('autorejoin_delay', "5", self.general_jid, True) + if config.get_by_tabname('autorejoin', False, + self.general_jid, True): + delay = config.get_by_tabname('autorejoin_delay', '5', + self.general_jid, True) delay = common.parse_str_to_secs(delay) 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)) + delay, + muc.join_groupchat, + self.core, + self.name, + self.own_nick)) else: - color = dump_tuple(user.color) if config.get_by_tabname('display_user_color_in_join_part', True, self.general_jid, True) else 3 + if config.get_by_tabname('display_user_color_in_join_part', + True, self.general_jid, True): + color = dump_tuple(user.color) + else: + color = 3 + if by: - kick_msg = _('\x191}%(spec)s \x19%(color)s}%(nick)s\x19%(info_col)s} has been banned by \x194}%(by)s') % { - 'spec':get_theme().CHAR_KICK, 'nick':from_nick, 'color':color, 'by':by, - 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} + 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} else: - kick_msg = _('\x191}%(spec)s \x19%(color)s}%(nick)s\x19%(info_col)s} has been banned') % { - 'spec':get_theme().CHAR_KICK, 'nick':from_nick, 'color':color, - 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} + 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} 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': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} + kick_msg += _('\x19%(info_col)s} Reason: \x196}' + '%(reason)s\x19%(info_col)s}') % { + 'reason': reason.text, 'info_col': info_col} self.add_message(kick_msg, typ=2) def on_user_kicked(self, presence, user, from_nick): @@ -1083,26 +1227,37 @@ class MucTab(ChatTab): When someone is kicked from a muc """ self.users.remove(user) - actor_elem = presence.find('{%s}x/{%s}item/{%s}actor' % (NS_MUC_USER, NS_MUC_USER, NS_MUC_USER)) - reason = presence.find('{%s}x/{%s}item/{%s}reason' % (NS_MUC_USER, NS_MUC_USER, NS_MUC_USER)) + actor_elem = presence.find('{%s}x/{%s}item/{%s}actor' % + (NS_MUC_USER, NS_MUC_USER, NS_MUC_USER)) + reason = presence.find('{%s}x/{%s}item/{%s}reason' % + (NS_MUC_USER, NS_MUC_USER, NS_MUC_USER)) by = None + info_col = dump_tuple(get_theme().COLOR_INFORMATION_TEXT) + 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 by: - kick_msg = _('\x191}%(spec)s \x193}You\x19%(info_col)s} have been kicked by \x193}%(by)s') % { - 'spec': get_theme().CHAR_KICK, 'by':by, - 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} + 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} else: - kick_msg = _('\x191}%(spec)s \x193}You\x19%(info_col)s} have been kicked.') % {'spec':get_theme().CHAR_KICK, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} + kick_msg = _('\x191}%(spec)s \x193}You\x19%(info_col)s}' + ' have been kicked.') % { + 'spec': char_kick, + 'info_col': info_col} self.core.disable_private_tabs(self.name, reason=kick_msg) self.disconnect() self.refresh_tab_win() self.core.current_tab().input.refresh() self.core.doupdate() # try to auto-rejoin - if config.get_by_tabname('autorejoin', False, self.general_jid, True): - delay = config.get_by_tabname('autorejoin_delay', "5", self.general_jid, True) + if config.get_by_tabname('autorejoin', False, + self.general_jid, True): + delay = config.get_by_tabname('autorejoin_delay', "5", + self.general_jid, True) delay = common.parse_str_to_secs(delay) if delay <= 0: muc.join_groupchat(self.core, self.name, self.own_nick) @@ -1114,13 +1269,26 @@ class MucTab(ChatTab): self.name, self.own_nick)) else: - color = dump_tuple(user.color) if config.get_by_tabname('display_user_color_in_join_part', True, self.general_jid, True) else 3 + if config.get_by_tabname('display_user_color_in_join_part', True, + self.general_jid, True): + color = dump_tuple(user.color) + else: + color = 3 if by: - kick_msg = _('\x191}%(spec)s \x19%(color)s}%(nick)s\x19%(info_col)s} has been kicked by \x193}%(by)s') % {'spec': get_theme().CHAR_KICK, 'nick':from_nick, 'color':color, 'by':by, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} + 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} else: - kick_msg = _('\x191}%(spec)s \x19%(color)s}%(nick)s\x19%(info_col)s} has been kicked') % {'spec': get_theme().CHAR_KICK, 'nick':from_nick, 'color':color, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} + 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} if reason is not None and reason.text: - kick_msg += _('\x19%(info_col)s} Reason: \x196}%(reason)s') % {'reason': reason.text, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} + kick_msg += _('\x19%(info_col)s} Reason: \x196}' + '%(reason)s') % { + '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): @@ -1129,12 +1297,16 @@ class MucTab(ChatTab): """ self.users.remove(user) if self.own_nick == user.nick: - # We are now out of the room. Happens with some buggy (? not sure) servers + # We are now out of the room. + # Happens with some buggy (? not sure) servers self.disconnect() self.core.disable_private_tabs(from_room) self.refresh_tab_win() - hide_exit_join = max(config.get_by_tabname('hide_exit_join', -1, self.general_jid, True), -1) + hide_exit_join = max(config.get_by_tabname('hide_exit_join', -1, + self.general_jid, True), + -1) + if hide_exit_join == -1 or user.has_talked_since(hide_exit_join): if config.get_by_tabname('display_user_color_in_join_part', True, self.general_jid, True): @@ -1146,7 +1318,8 @@ class MucTab(ChatTab): if not jid.full: leave_msg = _('\x19%(color_spec)s}%(spec)s \x19%(color)s}' - '%(nick)s\x19%(info_col)s} has left the chatroom') % { + '%(nick)s\x19%(info_col)s} has left the ' + 'chatroom') % { 'nick':from_nick, 'color':color, 'spec':get_theme().CHAR_QUIT, 'info_col': info_col, @@ -1155,7 +1328,8 @@ class MucTab(ChatTab): 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 chatroom') % { + '%(jid)s\x19%(info_col)s}) has left the ' + 'chatroom') % { 'spec':get_theme().CHAR_QUIT, 'nick':from_nick, 'color':color, 'jid':jid.full, 'info_col': info_col, @@ -1164,9 +1338,11 @@ class MucTab(ChatTab): 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, from_nick, status) + self.core.on_user_left_private_conversation(from_room, from_nick, + 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 """ @@ -1187,8 +1363,9 @@ class MucTab(ChatTab): 'nick': from_nick, 'color': color, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} if show not in SHOW_NAME: - self.core.information(_("%s from room %s sent an invalid show: %s") %\ - (from_nick, from_room, show), "Warning") + self.core.information(_("%s from room %s sent an invalid show: %s") + % (from_nick, from_room, show), + _("Warning")) if affiliation != user.affiliation: msg += _('affiliation: %s, ') % affiliation display_message = True @@ -1209,7 +1386,8 @@ class MucTab(ChatTab): if not display_message: return msg = msg[:-2] # remove the last ", " - hide_status_change = config.get_by_tabname('hide_status_change', -1, self.general_jid, True) + hide_status_change = config.get_by_tabname('hide_status_change', -1, + self.general_jid, True) if hide_status_change < -1: hide_status_change = -1 if ((hide_status_change == -1 or \ @@ -1225,7 +1403,9 @@ 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), msg) + self.core.on_user_changed_status_in_private('%s/%s' % + (from_room, from_nick), + msg) # finally, effectively change the user status user.update(affiliation, show, status, role) @@ -1250,9 +1430,10 @@ 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') + self.core.information(_('Unable to write in the log file'), + _('Error')) def do_highlight(self, txt, time, nickname): """ @@ -1266,7 +1447,9 @@ class MucTab(ChatTab): self.state = 'highlight' highlighted = True else: - highlight_words = config.get_by_tabname('highlight_on', '', self.general_jid, True).split(':') + highlight_words = config.get_by_tabname('highlight_on', '', + self.general_jid, + True).split(':') for word in highlight_words: if word and word.lower() in txt.lower(): if self.state != 'current': @@ -1276,7 +1459,8 @@ class MucTab(ChatTab): if highlighted: beep_on = config.get('beep_on', 'highlight private').split() if 'highlight' in beep_on and 'message' not in beep_on: - if not config.get_by_tabname('disable_beep', False, self.name, False): + if not config.get_by_tabname('disable_beep', False, + self.name, False): curses.beep() return highlighted @@ -1297,33 +1481,49 @@ class MucTab(ChatTab): Return True if the message highlighted us. False otherwise. """ self.log_message(txt, nickname, time=time, typ=kwargs.get('typ', 1)) - args = {key: value for key, value in kwargs.items() if key not in ('typ', 'forced_user')} - user = self.get_user_by_name(nickname) if nickname is not None else None + args = dict() + for key, value in kwargs.items(): + if key not in ('typ', 'forced_user'): + args[key] = value + if nickname is not None: + user = self.get_user_by_name(nickname) + else: + user = None + if user: user.set_last_talked(datetime.now()) args['user'] = user if not user and kwargs.get('forced_user'): 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', True, self.get_name()): + + 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', + True, self.get_name())): self.state = 'message' if time: - txt = '\x19%(info_col)s}%(txt)s' % {'txt':txt, 'info_col': dump_tuple(get_theme().COLOR_LOG_MSG)} + txt = '\x19%(info_col)s}%(txt)s' % { + 'txt': txt, + 'info_col': dump_tuple(get_theme().COLOR_LOG_MSG)} elif (not nickname or time) and not txt.startswith('/me '): - txt = '\x19%(info_col)s}%(txt)s' % {'txt':txt, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} + txt = '\x19%(info_col)s}%(txt)s' % { + '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) - 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) self.core.refresh_window() |