diff options
author | mathieui <mathieui@mathieui.net> | 2021-06-22 23:16:42 +0200 |
---|---|---|
committer | mathieui <mathieui@mathieui.net> | 2021-06-22 23:26:49 +0200 |
commit | 2b76f72e4d58eb540aa19173a050142f5199ff81 (patch) | |
tree | ccca7dbf36c20e980e3a69c0028af264702c75f6 /poezio/tabs | |
parent | 3035f4ed4d5ef5d581c7f224833392526bfd1bc5 (diff) | |
download | poezio-2b76f72e4d58eb540aa19173a050142f5199ff81.tar.gz poezio-2b76f72e4d58eb540aa19173a050142f5199ff81.tar.bz2 poezio-2b76f72e4d58eb540aa19173a050142f5199ff81.tar.xz poezio-2b76f72e4d58eb540aa19173a050142f5199ff81.zip |
Fix the message doubling situation
Add an "initial" parameter for onetoonetabs, and delay the reception of
the message until the sync is done (and possibly ignore the message if
it is fetched by the sync).
Fixes #3542
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: |