diff options
Diffstat (limited to 'poezio/core')
-rw-r--r-- | poezio/core/commands.py | 137 | ||||
-rw-r--r-- | poezio/core/completions.py | 9 | ||||
-rw-r--r-- | poezio/core/core.py | 27 | ||||
-rw-r--r-- | poezio/core/handlers.py | 8 |
4 files changed, 140 insertions, 41 deletions
diff --git a/poezio/core/commands.py b/poezio/core/commands.py index 4dbb5611..05e7421b 100644 --- a/poezio/core/commands.py +++ b/poezio/core/commands.py @@ -8,6 +8,7 @@ log = logging.getLogger(__name__) import asyncio from xml.etree import cElementTree as ET +from typing import List, Optional, Tuple from slixmpp import JID, InvalidJID from slixmpp.exceptions import XMPPError @@ -23,6 +24,8 @@ from poezio.bookmarks import Bookmark from poezio.common import safeJID from poezio.config import config, DEFAULT_CONFIG, options as config_opts from poezio import multiuserchat as muc +from poezio.contact import Contact +from poezio import windows from poezio.plugin import PluginConfig from poezio.roster import roster from poezio.theming import dump_tuple, get_theme @@ -133,7 +136,7 @@ class CommandCore: current.send_chat_state('inactive') for tab in self.core.tabs: if isinstance(tab, tabs.MucTab) and tab.joined: - muc.change_show(self.core.xmpp, tab.name, tab.own_nick, show, + muc.change_show(self.core.xmpp, tab.jid, tab.own_nick, show, msg) if hasattr(tab, 'directed_presence'): del tab.directed_presence @@ -151,7 +154,7 @@ class CommandCore: jid, ptype, status = args[0], args[1], args[2] if jid == '.' and isinstance(self.core.tabs.current_tab, tabs.ChatTab): - jid = self.core.tabs.current_tab.name + jid = self.core.tabs.current_tab.jid if ptype == 'available': ptype = None try: @@ -258,7 +261,7 @@ class CommandCore: self.core.refresh_window() @command_args_parser.quoted(0, 1) - def list(self, args): + def list(self, args: List[str]) -> None: """ /list [server] Opens a MucListTab containing the list of the room in the specified server @@ -266,12 +269,18 @@ class CommandCore: if args is None: return self.help('list') elif args: - jid = safeJID(args[0]) + try: + jid = JID(args[0]) + except InvalidJID: + return self.core.information('Invalid server %r' % jid, 'Error') else: if not isinstance(self.core.tabs.current_tab, tabs.MucTab): return self.core.information('Please provide a server', 'Error') - jid = safeJID(self.core.tabs.current_tab.name) + jid = self.core.tabs.current_tab.jid + if jid is None or not jid.domain: + return None + jid = JID(jid.domain) list_tab = tabs.MucListTab(self.core, jid) self.core.add_tab(list_tab, True) cb = list_tab.on_muc_list_item_received @@ -297,20 +306,23 @@ class CommandCore: tab = self.core.tabs.current_tab if not isinstance(tab, (tabs.MucTab, tabs.PrivateTab)): return (None, None) - room = safeJID(tab.name).bare + room = tab.jid.bare nick = tab.own_nick return (room, nick) - def _parse_join_jid(self, jid_string): + def _parse_join_jid(self, jid_string: str) -> Tuple[Optional[str], Optional[str]]: # we try to join a server directly - if jid_string.startswith('@'): - server_root = True - info = safeJID(jid_string[1:]) - else: - info = safeJID(jid_string) - server_root = False + try: + if jid_string.startswith('@'): + server_root = True + info = JID(jid_string[1:]) + else: + info = JID(jid_string) + server_root = False + except InvalidJID: + return (None, None) - set_nick = '' + set_nick = '' # type: Optional[str] if len(jid_string) > 1 and jid_string.startswith('/'): set_nick = jid_string[1:] elif info.resource: @@ -322,7 +334,7 @@ class CommandCore: if not isinstance(tab, tabs.MucTab): room, set_nick = (None, None) else: - room = tab.name + room = tab.jid.bare if not set_nick: set_nick = tab.own_nick else: @@ -332,10 +344,8 @@ class CommandCore: # check if the current room's name has a server if room.find('@') == -1 and not server_root: tab = self.core.tabs.current_tab - if isinstance(tab, tabs.MucTab): - if tab.name.find('@') != -1: - domain = safeJID(tab.name).domain - room += '@%s' % domain + if isinstance(tab, tabs.MucTab) and tab.domain: + room += '@%s' % tab.domain return (room, set_nick) @command_args_parser.quoted(0, 2) @@ -425,7 +435,7 @@ class CommandCore: nick = None if not jid: tab = self.core.tabs.current_tab - roomname = tab.name + roomname = tab.jid.bare if tab.joined and tab.own_nick != self.core.own_nick: nick = tab.own_nick if password is None and tab.password is not None: @@ -439,7 +449,7 @@ class CommandCore: tab = self.core.tabs.current_tab if not isinstance(tab, tabs.MucTab): return - roomname = tab.name + roomname = tab.jid.bare bookmark = self.core.bookmarks[roomname] if bookmark is None: bookmark = Bookmark(roomname) @@ -458,9 +468,9 @@ class CommandCore: def _add_wildcard_bookmarks(self, method): new_bookmarks = [] for tab in self.core.get_tabs(tabs.MucTab): - bookmark = self.core.bookmarks[tab.name] + bookmark = self.core.bookmarks[tab.jid.bare] if not bookmark: - bookmark = Bookmark(tab.name, autojoin=True, method=method) + bookmark = Bookmark(tab.jid.bare, autojoin=True, method=method) new_bookmarks.append(bookmark) else: bookmark.method = method @@ -497,8 +507,8 @@ class CommandCore: if not args: tab = self.core.tabs.current_tab - if isinstance(tab, tabs.MucTab) and self.core.bookmarks[tab.name]: - self.core.bookmarks.remove(tab.name) + if isinstance(tab, tabs.MucTab) and self.core.bookmarks[tab.jid.bare]: + self.core.bookmarks.remove(tab.jid.bare) self.core.bookmarks.save(self.core.xmpp, callback=cb) else: self.core.information('No bookmark to remove', 'Info') @@ -509,6 +519,71 @@ class CommandCore: else: self.core.information('No bookmark to remove', 'Info') + @command_args_parser.quoted(0, 1) + def command_accept(self, args): + """ + Accept a JID. Authorize it AND subscribe to it + """ + if not args: + tab = self.core.tabs.current_tab + RosterInfoTab = tabs.RosterInfoTab + if not isinstance(tab, RosterInfoTab): + return self.core.information('No JID specified', 'Error') + else: + item = tab.selected_row + if isinstance(item, Contact): + jid = item.bare_jid + else: + return self.core.information('No subscription to accept', 'Warning') + else: + jid = safeJID(args[0]).bare + nodepart = safeJID(jid).user + jid = safeJID(jid) + # crappy transports putting resources inside the node part + if '\\2f' in nodepart: + jid.user = nodepart.split('\\2f')[0] + contact = roster[jid] + if contact is None: + return self.core.information('No subscription to accept', 'Warning') + contact.pending_in = False + roster.modified() + self.core.xmpp.send_presence(pto=jid, ptype='subscribed') + self.core.xmpp.client_roster.send_last_presence() + if contact.subscription in ('from', + 'none') and not contact.pending_out: + self.core.xmpp.send_presence( + pto=jid, ptype='subscribe', pnick=self.core.own_nick) + self.core.information('%s is now authorized' % jid, 'Roster') + + @command_args_parser.quoted(1) + def command_add(self, args): + """ + Add the specified JID to the roster, and automatically + accept the reverse subscription + """ + if args is None: + tab = self.core.tabs.current_tab + ConversationTab = tabs.ConversationTab + if isinstance(tab, ConversationTab): + jid = tab.general_jid + if jid in roster and roster[jid].subscription in ('to', 'both'): + return self.core.information('Already subscribed.', 'Roster') + roster.add(jid) + roster.modified() + return self.core.information('%s was added to the roster' % jid, 'Roster') + else: + return self.core.information('No JID specified', 'Error') + jid = safeJID(safeJID(args[0]).bare) + if not str(jid): + self.core.information( + 'The provided JID (%s) is not valid' % (args[0], ), 'Error') + return + if jid in roster and roster[jid].subscription in ('to', 'both'): + return self.core.information('Already subscribed.', 'Roster') + roster.add(jid) + roster.modified() + self.core.information('%s was added to the roster' % jid, 'Roster') + @command_args_parser.ignored def command_reconnect(self): """ @@ -536,7 +611,8 @@ class CommandCore: theme.COLOR_INFORMATION_TEXT), }) for option_name, option_value in section.items(): - if 'password' in option_name and 'eval_password' not in option_name: + if isinstance(option_name, str) and \ + 'password' in option_name and 'eval_password' not in option_name: option_value = '********' lines.append( '%s\x19%s}=\x19o%s' % @@ -546,7 +622,8 @@ class CommandCore: elif len(args) == 1: option = args[0] value = config.get(option) - if 'password' in option and 'eval_password' not in option and value is not None: + if isinstance(option, str) and \ + 'password' in option and 'eval_password' not in option and value is not None: value = '********' if value is None and '=' in option: args = option.split('=', 1) @@ -595,7 +672,7 @@ class CommandCore: info = plugin_config.set_and_save(option, value, section) else: if args[0] == '.': - name = safeJID(self.core.tabs.current_tab.name).bare + name = self.core.tabs.current_tab.jid.bare if not name: self.core.information( 'Invalid tab to use the "." argument.', 'Error') @@ -663,11 +740,11 @@ class CommandCore: message = args[1] else: if isinstance(tab, tabs.MucTab): - domain = safeJID(tab.name).domain + domain = tab.jid.domain else: return self.core.information("No server specified", "Error") for tab in self.core.get_tabs(tabs.MucTab): - if JID(tab.name).domain == domain: + if tab.jid.domain == domain: tab.leave_room(message) tab.join() diff --git a/poezio/core/completions.py b/poezio/core/completions.py index 87bb2d47..84de77ca 100644 --- a/poezio/core/completions.py +++ b/poezio/core/completions.py @@ -161,8 +161,8 @@ class CompletionCore: muc_serv_list = [] for tab in self.core.get_tabs( tabs.MucTab): # TODO, also from an history - if tab.name not in muc_serv_list: - muc_serv_list.append(safeJID(tab.name).server) + if tab.jid.server not in muc_serv_list: + muc_serv_list.append(tab.jid.server) if muc_serv_list: return Completion( the_input.new_completion, muc_serv_list, 1, quotify=False) @@ -284,7 +284,7 @@ class CompletionCore: rooms = [] for tab in self.core.get_tabs(tabs.MucTab): if tab.joined: - rooms.append(tab.name) + rooms.append(tab.jid.bare) rooms.sort() return Completion( the_input.new_completion, rooms, n, '', quotify=True) @@ -346,8 +346,7 @@ class CompletionCore: """Completion for /server_cycle""" serv_list = set() for tab in self.core.get_tabs(tabs.MucTab): - serv = safeJID(tab.name).server - serv_list.add(serv) + serv_list.add(tab.jid.server) return Completion(the_input.new_completion, sorted(serv_list), 1, ' ') def set(self, the_input): diff --git a/poezio/core/core.py b/poezio/core/core.py index 6f840dc2..26543add 100644 --- a/poezio/core/core.py +++ b/poezio/core/core.py @@ -19,7 +19,7 @@ from typing import Callable, Dict, List, Optional, Set, Tuple, Type from xml.etree import cElementTree as ET from functools import partial -from slixmpp import JID +from slixmpp import JID, InvalidJID from slixmpp.util import FileSystemPerJidCache from slixmpp.xmlstream.handler import Callback from slixmpp.exceptions import IqError, IqTimeout @@ -936,7 +936,15 @@ class Core: nick = self.own_nick localpart = uuid.uuid4().hex - room = '{!s}@{!s}'.format(localpart, default_muc) + room_str = '{!s}@{!s}'.format(localpart, default_muc) + try: + room = JID(room_str) + except InvalidJID: + self.information( + 'The generated XMPP address is invalid: {!s}'.format(room_str), + 'Error' + ) + return None self.open_new_room(room, nick).join() iq = self._impromptu_room_form(room) @@ -1758,6 +1766,21 @@ class Core: shortdesc="Bookmark a room online.", completion=self.completion.bookmark) self.register_command( + 'accept', + self.command.command_accept, + usage='[jid]', + desc='Allow the provided JID (or the selected contact ' + 'in your roster), to see your presence.', + shortdesc='Allow a user your presence.',) + self.register_command( + 'add', + self.command.command_add, + usage='<jid>', + desc='Add the specified JID to your roster, ask them to' + ' allow you to see his presence, and allow them to' + ' see your presence.', + shortdesc='Add a user to your roster.') + self.register_command( 'reconnect', self.command.command_reconnect, usage="[reconnect]", diff --git a/poezio/core/handlers.py b/poezio/core/handlers.py index 614cabe4..c17f3761 100644 --- a/poezio/core/handlers.py +++ b/poezio/core/handlers.py @@ -235,7 +235,7 @@ class HandlerCore: # Differentiate both type of messages, and call the appropriate handler. jid_from = message['from'] for tab in self.core.get_tabs(tabs.MucTab): - if tab.name == jid_from.bare: + if tab.jid.bare == jid_from.bare: if jid_from.resource: self.on_groupchat_private_message(message, sent=False) return @@ -247,7 +247,7 @@ class HandlerCore: """ jid_from = message['from'] for tab in self.core.get_tabs(tabs.MucTab): - if tab.name == jid_from.bare: + if tab.jid.bare == jid_from.bare: if jid_from.full == jid_from.bare: self.core.room_error(message, jid_from.bare) else: @@ -1408,12 +1408,12 @@ class HandlerCore: jid_from = message['from'] self.core.information('%s requests your attention!' % jid_from, 'Info') for tab in self.core.tabs: - if tab.name == jid_from: + if tab.jid == jid_from: tab.state = 'attention' self.core.refresh_tab_win() return for tab in self.core.tabs: - if tab.name == jid_from.bare: + if tab.jid.bare == jid_from.bare: tab.state = 'attention' self.core.refresh_tab_win() return |