summaryrefslogtreecommitdiff
path: root/poezio/core
diff options
context:
space:
mode:
Diffstat (limited to 'poezio/core')
-rw-r--r--poezio/core/commands.py137
-rw-r--r--poezio/core/completions.py9
-rw-r--r--poezio/core/core.py27
-rw-r--r--poezio/core/handlers.py8
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