diff options
Diffstat (limited to 'poezio/tabs')
-rw-r--r-- | poezio/tabs/basetabs.py | 17 | ||||
-rw-r--r-- | poezio/tabs/conversationtab.py | 88 | ||||
-rw-r--r-- | poezio/tabs/privatetab.py | 66 |
3 files changed, 156 insertions, 15 deletions
diff --git a/poezio/tabs/basetabs.py b/poezio/tabs/basetabs.py index 43ab237f..f52122a5 100644 --- a/poezio/tabs/basetabs.py +++ b/poezio/tabs/basetabs.py @@ -999,7 +999,7 @@ class ChatTab(Tab): class OneToOneTab(ChatTab): - def __init__(self, core, jid): + def __init__(self, core, jid, initial=None): ChatTab.__init__(self, core, jid) self.__status = Status("", "") @@ -1018,18 +1018,29 @@ class OneToOneTab(ChatTab): shortdesc='Request the attention.', desc='Attention: Request the attention of the contact. Can also ' 'send a message along with the attention.') - self.init_logs() + self.init_logs(initial=initial) - def init_logs(self) -> None: + def init_logs(self, initial=None) -> None: use_log = config.get_by_tabname('use_log', self.jid) mam_sync = config.get_by_tabname('mam_sync', self.jid) if use_log and mam_sync: limit = config.get_by_tabname('mam_sync_limit', self.jid) self.mam_filler = MAMFiller(logger, self, limit) + + async def fallback_no_mam(): + await self.mam_filler.done.wait() + if self.mam_filler.result == 0: + self.handle_message(initial) + asyncio.ensure_future(fallback_no_mam()) + elif use_log and initial: + self.handle_message(initial, display=False) asyncio.ensure_future( LogLoader(logger, self, use_log).tab_open() ) + def handle_message(self, msg: SMessage, display: bool = True): + pass + def remote_user_color(self): return dump_tuple(get_theme().COLOR_REMOTE_USER) diff --git a/poezio/tabs/conversationtab.py b/poezio/tabs/conversationtab.py index 78faf49a..eb6e97b5 100644 --- a/poezio/tabs/conversationtab.py +++ b/poezio/tabs/conversationtab.py @@ -13,22 +13,25 @@ There are two different instances of a ConversationTab: """ import curses import logging +from datetime import datetime from typing import Dict, Callable -from slixmpp import JID, InvalidJID +from slixmpp import JID, InvalidJID, Message as SMessage from poezio.tabs.basetabs import OneToOneTab, Tab from poezio import common +from poezio import tabs from poezio import windows from poezio import xhtml -from poezio.config import config +from poezio.config import config, get_image_cache from poezio.core.structs import Command from poezio.decorators import refresh_wrapper from poezio.roster import roster from poezio.theming import get_theme, dump_tuple from poezio.decorators import command_args_parser -from poezio.ui.types import InfoMessage +from poezio.ui.types import InfoMessage, Message +from poezio.text_buffer import CorrectionError log = logging.getLogger(__name__) @@ -43,8 +46,8 @@ class ConversationTab(OneToOneTab): additional_information: Dict[str, Callable[[str], str]] = {} message_type = 'chat' - def __init__(self, core, jid): - OneToOneTab.__init__(self, core, jid) + def __init__(self, core, jid, initial=None): + OneToOneTab.__init__(self, core, jid, initial=initial) self.nick = None self.nick_sent = False self.state = 'normal' @@ -102,6 +105,71 @@ class ConversationTab(OneToOneTab): def completion(self): self.complete_commands(self.input) + def handle_message(self, message: SMessage, display: bool = True): + """Handle a received message. + + The message can come from us (carbon copy). + """ + use_xhtml = config.get_by_tabname( + 'enable_xhtml_im', + message['from'].bare + ) + tmp_dir = get_image_cache() + # normal message, we are the recipient + if message['to'].bare == self.core.xmpp.boundjid.bare: + conv_jid = message['from'] + jid = conv_jid + color = get_theme().COLOR_REMOTE_USER + self.last_remote_message = datetime.now() + remote_nick = self.get_nick() + # we wrote the message (happens with carbons) + elif message['from'].bare == self.core.xmpp.boundjid.bare: + conv_jid = message['to'] + jid = self.core.xmpp.boundjid + color = get_theme().COLOR_OWN_NICK + remote_nick = self.core.own_nick + # we are not part of that message, drop it + else: + return + + self.core.events.trigger('conversation_msg', message, self) + + if not message['body']: + return + body = xhtml.get_body_from_message_stanza( + message, use_xhtml=use_xhtml, extract_images_to=tmp_dir) + delayed, date = common.find_delayed_tag(message) + + replaced = False + if message.get_plugin('replace', check=True): + replaced_id = message['replace']['id'] + if replaced_id and config.get_by_tabname('group_corrections', + conv_jid.bare): + try: + replaced = self.modify_message( + body, + replaced_id, + message['id'], + time=date, + jid=jid, + nickname=remote_nick) + except CorrectionError: + log.debug('Unable to correct the message: %s', message) + if not replaced: + msg = Message( + txt=body, + time=date, + nickname=remote_nick, + nick_color=color, + history=delayed, + identifier=message['id'], + jid=jid, + ) + if display: + self.add_message(msg) + else: + self.log_message(msg) + @refresh_wrapper.always @command_args_parser.raw def command_say(self, line: str, attention: bool = False, correct: bool = False): @@ -396,9 +464,9 @@ class DynamicConversationTab(ConversationTab): plugin_commands: Dict[str, Command] = {} plugin_keys: Dict[str, Callable] = {} - def __init__(self, core, jid, resource=None): + def __init__(self, core, jid, initial=None): self.locked_resource = None - ConversationTab.__init__(self, core, jid) + ConversationTab.__init__(self, core, jid, initial=initial) self.jid.resource = None self.info_header = windows.DynamicConversationInfoWin() self.register_command( @@ -466,15 +534,15 @@ class StaticConversationTab(ConversationTab): plugin_commands: Dict[str, Command] = {} plugin_keys: Dict[str, Callable] = {} - def __init__(self, core, jid): - ConversationTab.__init__(self, core, jid) + def __init__(self, core, jid, initial=None): + ConversationTab.__init__(self, core, jid, initial=initial) assert jid.resource self.info_header = windows.ConversationInfoWin() self.resize() self.update_commands() self.update_keys() - def init_logs(self) -> None: + def init_logs(self, initial=None) -> None: # Disable local logs becauseā¦ pass diff --git a/poezio/tabs/privatetab.py b/poezio/tabs/privatetab.py index daf81733..439ab5f8 100644 --- a/poezio/tabs/privatetab.py +++ b/poezio/tabs/privatetab.py @@ -12,19 +12,23 @@ the ConversationTab (such as tab-completion on nicks from the room). """ import curses import logging +from datetime import datetime from typing import Dict, Callable from slixmpp import JID +from slixmpp.stanza import Message as SMessage from poezio.tabs import OneToOneTab, MucTab, Tab +from poezio import common from poezio import windows from poezio import xhtml -from poezio.config import config +from poezio.config import config, get_image_cache from poezio.core.structs import Command from poezio.decorators import refresh_wrapper from poezio.theming import get_theme, dump_tuple from poezio.decorators import command_args_parser +from poezio.text_buffer import CorrectionError from poezio.ui.types import ( Message, PersistentInfoMessage, @@ -42,7 +46,7 @@ class PrivateTab(OneToOneTab): message_type = 'chat' additional_information: Dict[str, Callable[[str], str]] = {} - def __init__(self, core, jid, nick): + def __init__(self, core, jid, nick, initial=None): OneToOneTab.__init__(self, core, jid) self.own_nick = nick self.info_header = windows.PrivateInfoWin() @@ -137,6 +141,64 @@ class PrivateTab(OneToOneTab): and not self.input.get_text().startswith('//')) self.send_composing_chat_state(empty_after) + def handle_message(self, message: SMessage, display: bool = True): + sent = message['from'].bare == self.core.xmpp.boundjid.bare + jid = message['to'] if sent else message['from'] + with_nick = jid.resource + sender_nick = with_nick + if sent: + sender_nick = (self.own_nick or self.core.own_nick) + room_from = jid.bare + use_xhtml = config.get_by_tabname( + 'enable_xhtml_im', + jid.bare + ) + tmp_dir = get_image_cache() + if not sent: + self.core.events.trigger('private_msg', message, self) + body = xhtml.get_body_from_message_stanza( + message, use_xhtml=use_xhtml, extract_images_to=tmp_dir) + if not body or not self: + return + delayed, date = common.find_delayed_tag(message) + replaced = False + user = self.parent_muc.get_user_by_name(with_nick) + if message.get_plugin('replace', check=True): + replaced_id = message['replace']['id'] + if replaced_id != '' and config.get_by_tabname( + 'group_corrections', room_from): + try: + self.modify_message( + body, + replaced_id, + message['id'], + user=user, + time=date, + jid=message['from'], + nickname=sender_nick) + replaced = True + except CorrectionError: + log.debug('Unable to correct a message', exc_info=True) + if not replaced: + msg = Message( + txt=body, + time=date, + history=delayed, + nickname=sender_nick, + nick_color=get_theme().COLOR_OWN_NICK if sent else None, + user=user, + identifier=message['id'], + jid=message['from'], + ) + if display: + self.add_message(msg) + else: + self.log_message(msg) + if sent: + self.set_last_sent_message(message, correct=replaced) + else: + self.last_remote_message = datetime.now() + @refresh_wrapper.always @command_args_parser.raw def command_say(self, line: str, attention: bool = False, correct: bool = False) -> None: |