internal: move and split muc message handling
This commit is contained in:
parent
1f95f25a87
commit
cf3d06fb0a
2 changed files with 138 additions and 95 deletions
|
@ -478,7 +478,7 @@ class HandlerCore:
|
||||||
else:
|
else:
|
||||||
contact.name = ''
|
contact.name = ''
|
||||||
|
|
||||||
async def on_groupchat_message(self, message: Message):
|
async def on_groupchat_message(self, message: Message) -> None:
|
||||||
"""
|
"""
|
||||||
Triggered whenever a message is received from a multi-user chat room.
|
Triggered whenever a message is received from a multi-user chat room.
|
||||||
"""
|
"""
|
||||||
|
@ -495,99 +495,8 @@ class HandlerCore:
|
||||||
muc.leave_groupchat(
|
muc.leave_groupchat(
|
||||||
self.core.xmpp, room_from, self.core.own_nick, msg='')
|
self.core.xmpp, room_from, self.core.own_nick, msg='')
|
||||||
return
|
return
|
||||||
|
valid_message = await tab.handle_message(message)
|
||||||
nick_from = message['mucnick']
|
if valid_message and 'message' in config.getstr('beep_on').split():
|
||||||
user = tab.get_user_by_name(nick_from)
|
|
||||||
if user and user in tab.ignores:
|
|
||||||
return
|
|
||||||
|
|
||||||
await self.core.events.trigger_async('muc_msg', message, tab)
|
|
||||||
use_xhtml = config.get_by_tabname('enable_xhtml_im', room_from)
|
|
||||||
tmp_dir = get_image_cache()
|
|
||||||
body = xhtml.get_body_from_message_stanza(
|
|
||||||
message, use_xhtml=use_xhtml, extract_images_to=tmp_dir)
|
|
||||||
|
|
||||||
# TODO: #3314. Is this a MUC reflection?
|
|
||||||
# Is this an encrypted message? Is so ignore.
|
|
||||||
# It is not possible in the OMEMO case to decrypt these messages
|
|
||||||
# since we don't encrypt for our own device (something something
|
|
||||||
# forward secrecy), but even for non-FS encryption schemes anyway
|
|
||||||
# messages shouldn't have changed after a round-trip to the room.
|
|
||||||
# Otherwire replace the matching message we sent.
|
|
||||||
|
|
||||||
if not body:
|
|
||||||
return
|
|
||||||
|
|
||||||
old_state = tab.state
|
|
||||||
delayed, date = common.find_delayed_tag(message)
|
|
||||||
is_history = not tab.joined and delayed
|
|
||||||
|
|
||||||
replaced = False
|
|
||||||
if message.xml.find('{urn:xmpp:message-correct:0}replace') is not None:
|
|
||||||
replaced_id = message['replace']['id']
|
|
||||||
if replaced_id != '' and config.get_by_tabname(
|
|
||||||
'group_corrections', message['from'].bare):
|
|
||||||
try:
|
|
||||||
delayed_date = date or datetime.now()
|
|
||||||
if tab.modify_message(
|
|
||||||
body,
|
|
||||||
replaced_id,
|
|
||||||
message['id'],
|
|
||||||
time=delayed_date,
|
|
||||||
delayed=delayed,
|
|
||||||
nickname=nick_from,
|
|
||||||
user=user):
|
|
||||||
await self.core.events.trigger_async('highlight', message, tab)
|
|
||||||
replaced = True
|
|
||||||
except CorrectionError:
|
|
||||||
log.debug('Unable to correct a message', exc_info=True)
|
|
||||||
|
|
||||||
if not replaced:
|
|
||||||
ui_msg: Union[InfoMessage, PMessage]
|
|
||||||
# Messages coming from MUC barejid (Server maintenance, IRC mode
|
|
||||||
# changes from biboumi, etc.) are displayed as info messages.
|
|
||||||
highlight = False
|
|
||||||
if message['from'].resource:
|
|
||||||
highlight = tab.message_is_highlight(body, nick_from, is_history)
|
|
||||||
ui_msg = PMessage(
|
|
||||||
txt=body,
|
|
||||||
time=date,
|
|
||||||
nickname=nick_from,
|
|
||||||
history=is_history,
|
|
||||||
delayed=delayed,
|
|
||||||
identifier=message['id'],
|
|
||||||
jid=message['from'],
|
|
||||||
user=user,
|
|
||||||
highlight=highlight,
|
|
||||||
)
|
|
||||||
typ = 1
|
|
||||||
else:
|
|
||||||
ui_msg = InfoMessage(
|
|
||||||
txt=body,
|
|
||||||
time=date,
|
|
||||||
identifier=message['id'],
|
|
||||||
)
|
|
||||||
typ = 2
|
|
||||||
tab.add_message(ui_msg)
|
|
||||||
if highlight:
|
|
||||||
await self.core.events.trigger_async('highlight', message, tab)
|
|
||||||
|
|
||||||
if message['from'].resource == tab.own_nick:
|
|
||||||
tab.set_last_sent_message(message, correct=replaced)
|
|
||||||
|
|
||||||
if tab is self.core.tabs.current_tab:
|
|
||||||
tab.text_win.refresh()
|
|
||||||
tab.info_header.refresh(tab, tab.text_win, user=tab.own_user)
|
|
||||||
tab.input.refresh()
|
|
||||||
self.core.doupdate()
|
|
||||||
elif tab.state != old_state:
|
|
||||||
self.core.refresh_tab_win()
|
|
||||||
current = self.core.tabs.current_tab
|
|
||||||
if hasattr(current, 'input') and current.input:
|
|
||||||
current.input.refresh()
|
|
||||||
self.core.doupdate()
|
|
||||||
|
|
||||||
if 'message' in config.getstr('beep_on').split():
|
|
||||||
if (not config.get_by_tabname('disable_beep', room_from)
|
if (not config.get_by_tabname('disable_beep', room_from)
|
||||||
and self.core.own_nick != message['from'].resource):
|
and self.core.own_nick != message['from'].resource):
|
||||||
curses.beep()
|
curses.beep()
|
||||||
|
|
|
@ -18,6 +18,7 @@ import random
|
||||||
import re
|
import re
|
||||||
import functools
|
import functools
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import (
|
from typing import (
|
||||||
cast,
|
cast,
|
||||||
|
@ -44,12 +45,13 @@ from poezio import timed_events
|
||||||
from poezio import windows
|
from poezio import windows
|
||||||
from poezio import xhtml
|
from poezio import xhtml
|
||||||
from poezio.common import to_utc
|
from poezio.common import to_utc
|
||||||
from poezio.config import config
|
from poezio.config import config, get_image_cache
|
||||||
from poezio.core.structs import Command
|
from poezio.core.structs import Command
|
||||||
from poezio.decorators import refresh_wrapper, command_args_parser
|
from poezio.decorators import refresh_wrapper, command_args_parser
|
||||||
from poezio.logger import logger
|
from poezio.logger import logger
|
||||||
from poezio.log_loader import LogLoader, MAMFiller
|
from poezio.log_loader import LogLoader, MAMFiller
|
||||||
from poezio.roster import roster
|
from poezio.roster import roster
|
||||||
|
from poezio.text_buffer import CorrectionError
|
||||||
from poezio.theming import get_theme, dump_tuple
|
from poezio.theming import get_theme, dump_tuple
|
||||||
from poezio.user import User
|
from poezio.user import User
|
||||||
from poezio.core.structs import Completion, Status
|
from poezio.core.structs import Completion, Status
|
||||||
|
@ -73,6 +75,18 @@ NS_MUC_USER = 'http://jabber.org/protocol/muc#user'
|
||||||
COMPARE_USERS_LAST_TALKED = lambda x: x.last_talked
|
COMPARE_USERS_LAST_TALKED = lambda x: x.last_talked
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MessageData:
|
||||||
|
message: SMessage
|
||||||
|
delayed: bool
|
||||||
|
date: Optional[datetime]
|
||||||
|
nick: str
|
||||||
|
user: Optional[User]
|
||||||
|
room_from: str
|
||||||
|
body: str
|
||||||
|
is_history: bool
|
||||||
|
|
||||||
|
|
||||||
class MucTab(ChatTab):
|
class MucTab(ChatTab):
|
||||||
"""
|
"""
|
||||||
The tab containing a multi-user-chat room.
|
The tab containing a multi-user-chat room.
|
||||||
|
@ -482,6 +496,126 @@ class MucTab(ChatTab):
|
||||||
self.general_jid) and not self.input.get_text():
|
self.general_jid) and not self.input.get_text():
|
||||||
self.send_chat_state('active')
|
self.send_chat_state('active')
|
||||||
|
|
||||||
|
async def handle_message(self, message: SMessage) -> bool:
|
||||||
|
"""Parse an incoming message
|
||||||
|
|
||||||
|
Returns False if the message was dropped silently.
|
||||||
|
"""
|
||||||
|
room_from = message['from'].bare
|
||||||
|
nick_from = message['mucnick']
|
||||||
|
user = self.get_user_by_name(nick_from)
|
||||||
|
if user and user in self.ignores:
|
||||||
|
return False
|
||||||
|
|
||||||
|
await self.core.events.trigger_async('muc_msg', message, self)
|
||||||
|
use_xhtml = config.get_by_tabname('enable_xhtml_im', room_from)
|
||||||
|
tmp_dir = get_image_cache()
|
||||||
|
body = xhtml.get_body_from_message_stanza(
|
||||||
|
message, use_xhtml=use_xhtml, extract_images_to=tmp_dir)
|
||||||
|
|
||||||
|
# TODO: #3314. Is this a MUC reflection?
|
||||||
|
# Is this an encrypted message? Is so ignore.
|
||||||
|
# It is not possible in the OMEMO case to decrypt these messages
|
||||||
|
# since we don't encrypt for our own device (something something
|
||||||
|
# forward secrecy), but even for non-FS encryption schemes anyway
|
||||||
|
# messages shouldn't have changed after a round-trip to the room.
|
||||||
|
# Otherwire replace the matching message we sent.
|
||||||
|
if not body:
|
||||||
|
return False
|
||||||
|
|
||||||
|
old_state = self.state
|
||||||
|
delayed, date = common.find_delayed_tag(message)
|
||||||
|
is_history = not self.joined and delayed
|
||||||
|
|
||||||
|
mdata = MessageData(
|
||||||
|
message, delayed, date, nick_from, user, room_from, body,
|
||||||
|
is_history
|
||||||
|
)
|
||||||
|
|
||||||
|
replaced = False
|
||||||
|
if message.xml.find('{urn:xmpp:message-correct:0}replace') is not None:
|
||||||
|
replaced = await self._handle_correction_message(mdata)
|
||||||
|
if not replaced:
|
||||||
|
await self._handle_normal_message(mdata)
|
||||||
|
if mdata.nick == self.own_nick:
|
||||||
|
self.set_last_sent_message(message, correct=replaced)
|
||||||
|
self._refresh_after_message(old_state)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _refresh_after_message(self, old_state: str) -> None:
|
||||||
|
"""Refresh the appropriate UI after a message is received"""
|
||||||
|
if self is self.core.tabs.current_tab:
|
||||||
|
self.refresh()
|
||||||
|
elif self.state != old_state:
|
||||||
|
self.core.refresh_tab_win()
|
||||||
|
current = self.core.tabs.current_tab
|
||||||
|
current.refresh_input()
|
||||||
|
self.core.doupdate()
|
||||||
|
|
||||||
|
async def _handle_correction_message(self, message: MessageData) -> bool:
|
||||||
|
"""Process a correction message.
|
||||||
|
|
||||||
|
Returns true if a message was actually corrected.
|
||||||
|
"""
|
||||||
|
replaced_id = message.message['replace']['id']
|
||||||
|
if replaced_id != '' and config.get_by_tabname(
|
||||||
|
'group_corrections', message.room_from):
|
||||||
|
try:
|
||||||
|
delayed_date = message.date or datetime.now()
|
||||||
|
modify_hl = self.modify_message(
|
||||||
|
message.body,
|
||||||
|
replaced_id,
|
||||||
|
message.message['id'],
|
||||||
|
time=delayed_date,
|
||||||
|
delayed=message.delayed,
|
||||||
|
nickname=message.nick,
|
||||||
|
user=message.user
|
||||||
|
)
|
||||||
|
if modify_hl:
|
||||||
|
await self.core.events.trigger_async(
|
||||||
|
'highlight',
|
||||||
|
message.message,
|
||||||
|
self
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except CorrectionError:
|
||||||
|
log.debug('Unable to correct a message', exc_info=True)
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def _handle_normal_message(self, message: MessageData) -> None:
|
||||||
|
"""
|
||||||
|
Process the non-correction groupchat message.
|
||||||
|
"""
|
||||||
|
ui_msg: Union[InfoMessage, Message]
|
||||||
|
# Messages coming from MUC barejid (Server maintenance, IRC mode
|
||||||
|
# changes from biboumi, etc.) have no nick/resource and are displayed
|
||||||
|
# as info messages.
|
||||||
|
highlight = False
|
||||||
|
if message.nick:
|
||||||
|
highlight = self.message_is_highlight(
|
||||||
|
message.body, message.nick, message.is_history
|
||||||
|
)
|
||||||
|
ui_msg = Message(
|
||||||
|
txt=message.body,
|
||||||
|
time=message.date,
|
||||||
|
nickname=message.nick,
|
||||||
|
history=message.is_history,
|
||||||
|
delayed=message.delayed,
|
||||||
|
identifier=message.message['id'],
|
||||||
|
jid=message.message['from'],
|
||||||
|
user=message.user,
|
||||||
|
highlight=highlight,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
ui_msg = InfoMessage(
|
||||||
|
txt=message.body,
|
||||||
|
time=message.date,
|
||||||
|
identifier=message.message['id'],
|
||||||
|
)
|
||||||
|
self.add_message(ui_msg)
|
||||||
|
if highlight:
|
||||||
|
await self.core.events.trigger_async('highlight', message, self)
|
||||||
|
|
||||||
def handle_presence(self, presence: Presence) -> None:
|
def handle_presence(self, presence: Presence) -> None:
|
||||||
"""Handle MUC presence"""
|
"""Handle MUC presence"""
|
||||||
self.reset_lag()
|
self.reset_lag()
|
||||||
|
|
Loading…
Reference in a new issue