Philipp Hörist pushed to branch master at gajim / gajim
Commits: 6ae3bb31 by lovetox at 2022-09-03T10:01:28+00:00 refactor: Contacts: Remove convenience method
- - - - - af02c6bd by lovetox at 2022-09-03T10:01:28+00:00 fix: Better validate message corrections
- Refactor message processing code - Introduce 5 minute message correction limit
- - - - -
7 changed files:
- gajim/common/const.py - gajim/common/modules/contacts.py - gajim/common/modules/mam.py - gajim/common/modules/message.py - gajim/common/modules/util.py - gajim/common/storage/archive.py - gajim/gtk/chat_list_stack.py
Changes:
===================================== gajim/common/const.py ===================================== @@ -36,6 +36,8 @@ STOP_EVENT = True PROPAGATE_EVENT = False
+MAX_MESSAGE_CORRECTION_DELAY = 300 +
class EncryptionData(NamedTuple): additional_data: Any = None
===================================== gajim/common/modules/contacts.py ===================================== @@ -222,15 +222,6 @@ def get_bare_contact(self, jid: Union[str, JID]) -> Union[BareContact, ''' return self._contacts[jid]
- def get_group_chat_contact(self, - jid: Union[str, JID] - ) -> Union[BareContact, - ResourceContact, - GroupchatContact, - GroupchatParticipant]: - - return self.get_contact(jid, groupchat=True) - def get_contacts_with_domain(self, domain: str ) -> list[Union[BareContact,
===================================== gajim/common/modules/mam.py ===================================== @@ -43,7 +43,6 @@ from gajim.common.events import ArchivingIntervalFinished from gajim.common.events import FeatureDiscovered from gajim.common.events import MamMessageReceived -from gajim.common.events import MessageUpdated from gajim.common.events import RawMamMessageReceived from gajim.common.const import ArchiveState, ClientState from gajim.common.const import KindConstant @@ -51,7 +50,7 @@ from gajim.common.helpers import AdditionalDataDict from gajim.common.helpers import get_retraction_text from gajim.common.modules.misc import parse_oob -from gajim.common.modules.misc import parse_correction +from gajim.common.modules.util import check_if_message_correction from gajim.common.modules.util import get_eme_message from gajim.common.modules.util import as_task from gajim.common.modules.base import BaseModule @@ -311,21 +310,12 @@ def _mam_message_received(self, 'kind': kind, }
- correct_id = parse_correction(properties) - if correct_id is not None: - nickname = properties.muc_nickname or properties.nickname - app.ged.raise_event(MessageUpdated(account=self._account, - jid=jid, - msgtxt=properties.body, - nickname=nickname, - properties=properties, - correct_id=correct_id)) - app.storage.archive.store_message_correction( - self._account, - jid, - correct_id, - properties.body, - properties.type.is_groupchat) + if check_if_message_correction(properties, + self._account, + properties.jid, + properties.body, + kind, + self._log): return
app.storage.archive.insert_into_logs(
===================================== gajim/common/modules/message.py ===================================== @@ -32,13 +32,12 @@ from gajim.common.events import GcMessageReceived from gajim.common.events import MessageError from gajim.common.events import MessageReceived -from gajim.common.events import MessageUpdated from gajim.common.events import RawMessageReceived from gajim.common.helpers import AdditionalDataDict from gajim.common.const import KindConstant from gajim.common.modules.base import BaseModule +from gajim.common.modules.util import check_if_message_correction from gajim.common.modules.util import get_eme_message -from gajim.common.modules.misc import parse_correction from gajim.common.modules.misc import parse_oob from gajim.common.modules.misc import parse_xhtml from gajim.common.structs import OutgoingMessage @@ -190,23 +189,19 @@ def _message_received(self, 'properties': properties, }
- correct_id = parse_correction(properties) - if correct_id is not None: - nickname = properties.muc_nickname or properties.nickname - event = MessageUpdated(account=self._account, - jid=event_attr['jid'], - msgtxt=msgtxt, - nickname=nickname, - properties=properties, - correct_id=correct_id) - - app.storage.archive.store_message_correction( - self._account, - jid, - correct_id, - msgtxt, - properties.type.is_groupchat) - app.ged.raise_event(event) + if type_.is_groupchat: + kind = KindConstant.GC_MSG + elif properties.is_sent_carbon: + kind = KindConstant.CHAT_MSG_SENT + else: + kind = KindConstant.CHAT_MSG_RECV + + if check_if_message_correction(properties, + self._account, + from_, + msgtxt, + kind, + self._log): return
if type_.is_groupchat: @@ -224,10 +219,6 @@ def _message_received(self,
app.ged.raise_event(MessageReceived(**event_attr))
- log_type = KindConstant.CHAT_MSG_RECV - if properties.is_sent_carbon: - log_type = KindConstant.CHAT_MSG_SENT - if not msgtxt: return
@@ -235,7 +226,7 @@ def _message_received(self, self._account, fjid if properties.is_muc_pm else jid, properties.timestamp, - log_type, + kind, message=msgtxt, subject=properties.subject, additional_data=additional_data, @@ -399,12 +390,13 @@ def log_message(self, message: OutgoingMessage) -> None: return
if message.correct_id is not None: - app.storage.archive.store_message_correction( + app.storage.archive.try_message_correction( self._account, message.jid, - message.correct_id, + None, message.message, - message.is_groupchat) + message.correct_id, + KindConstant.CHAT_MSG_SENT) return
app.storage.archive.insert_into_logs(
===================================== gajim/common/modules/util.py ===================================== @@ -19,19 +19,25 @@ from typing import Any from typing import Union
+import logging from logging import LoggerAdapter from functools import wraps from functools import partial
import nbxmpp +from nbxmpp.protocol import JID from nbxmpp.protocol import Message from nbxmpp.structs import EMEData from nbxmpp.structs import MessageProperties +from nbxmpp.const import MessageType from nbxmpp.task import Task
from gajim.common import app from gajim.common import types from gajim.common.const import EME_MESSAGES +from gajim.common.const import KindConstant +from gajim.common.events import MessageUpdated +from gajim.common.modules.misc import parse_correction
def from_xs_boolean(value: Union[str, bool]) -> bool: @@ -115,3 +121,57 @@ def func_wrapper(self, *args, callback=None, user_data=None, **kwargs): task_.start() return task_ return func_wrapper + + +def check_if_message_correction(properties: MessageProperties, + account: str, + jid: JID, + msgtxt: str, + kind: KindConstant, + logger: LoggerAdapter[logging.Logger]) -> bool: + + correct_id = parse_correction(properties) + if correct_id is None: + return False + + if properties.type not in (MessageType.GROUPCHAT, MessageType.CHAT): + logger.warning('Ignore correction with message type: %s', + properties.type) + return False + + nickname = None + if properties.type.is_groupchat: + if jid.is_bare: + logger.warning( + 'Ignore correction from bare groupchat jid: %s', jid) + return False + + nickname = jid.resource + jid = jid.new_as_bare() + + elif not properties.is_muc_pm: + jid = jid.new_as_bare() + + successful = app.storage.archive.try_message_correction( + account, + jid, + nickname, + msgtxt, + correct_id, + kind) + + if not successful: + logger.info('Message correction not successful') + return False + + nickname = properties.muc_nickname or properties.nickname + + event = MessageUpdated(account=account, + jid=jid, + msgtxt=msgtxt, + nickname=nickname, + properties=properties, + correct_id=correct_id) + + app.ged.raise_event(event) + return True
===================================== gajim/common/storage/archive.py ===================================== @@ -42,6 +42,7 @@ from gajim.common import app from gajim.common import configpaths from gajim.common.helpers import AdditionalDataDict +from gajim.common.const import MAX_MESSAGE_CORRECTION_DELAY from gajim.common.const import ShowConstant from gajim.common.const import KindConstant from gajim.common.const import JIDConstant @@ -991,7 +992,7 @@ def get_last_correctable_message(self, ''' jids = [jid] account_id = self.get_account_id(account) - min_time = time.time() - 5 * 60 + min_time = time.time() - MAX_MESSAGE_CORRECTION_DELAY
sql = ''' SELECT contact_name, time, kind, message, stanza_id, message_id, @@ -1008,29 +1009,57 @@ def get_last_correctable_message(self, tuple(jids) + (message_id, min_time)).fetchone()
@timeit - def store_message_correction(self, - account: str, - jid: JID, - correct_id: str, - corrected_text: str, - is_groupchat: bool) -> None: - type_ = JIDConstant.NORMAL_TYPE - if is_groupchat: - type_ = JIDConstant.ROOM_TYPE + def try_message_correction(self, + account: str, + jid: JID, + nickname: Optional[str], + corrected_text: str, + correct_id: str, + kind: KindConstant) -> bool: + + '''Try to correct a message + + :param jid: This can be a full jid or bare jid. A full jid only if the + message is a MUC PM, otherwise a bare jid needs to be + passed. `nickname` should only be passed if the message + is a group chat message. + '''
- jid_id = self.get_jid_id(str(jid), type_=type_) account_id = self.get_account_id(account) - sql = ''' - SELECT log_line_id, message, additional_data - FROM logs - WHERE +jid_id = ? - AND account_id = ? - AND message_id = ? - ''' - row = self._con.execute( - sql, (jid_id, account_id, correct_id)).fetchone() - if row is None: - return + max_timestamp = time.time() - MAX_MESSAGE_CORRECTION_DELAY + + self._log.debug( + 'Check if message is correctable, parameters: %s %s %s %s %s', + jid, account_id, nickname, correct_id, max_timestamp) + + sql = '''SELECT log_line_id, message, additional_data + FROM logs + NATURAL JOIN jids jid_id + WHERE +jid = ? + AND account_id = ? + AND contact_name IS ? + AND message_id = ? + AND kind = ? + AND time > ? + ''' + + rows = self._con.execute(sql, (jid, + account_id, + nickname, + correct_id, + kind, + max_timestamp + )).fetchall() + + if not rows: + self._log.debug('No correctable messages found') + return False + + if len(rows) != 1: + self._log.warning('More than one correctable message found') + return False + + row = rows[0]
if row.additional_data is None: additional_data = AdditionalDataDict() @@ -1052,6 +1081,8 @@ def store_message_correction(self, self._con.execute( sql, (corrected_text, serialized_dict, row.log_line_id))
+ return True + @timeit def update_additional_data(self, account: str,
===================================== gajim/gtk/chat_list_stack.py ===================================== @@ -283,7 +283,7 @@ def _remove() -> None: return
client = app.get_client(account) - contact = client.get_module('Contacts').get_group_chat_contact(jid) + contact = client.get_module('Contacts').get_contact(jid, groupchat=True)
if contact.is_not_joined: _remove()
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/c74d8f0e2c916dc7117c65e097569de0...