Inlcude account for message deduplication

It was not possible to write with 2 different accounts into the
same MUC
This commit is contained in:
Philipp Hörist 2018-01-25 00:46:32 +01:00
parent 90bc646b09
commit 4c545be737
3 changed files with 40 additions and 20 deletions

View File

@ -1061,6 +1061,7 @@ class MamMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.nick = None self.nick = None
def generate(self): def generate(self):
account = self.conn.name
archive_jid = self.stanza.getFrom() archive_jid = self.stanza.getFrom()
own_jid = self.conn.get_own_jid() own_jid = self.conn.get_own_jid()
if archive_jid and not archive_jid.bareMatch(own_jid): if archive_jid and not archive_jid.bareMatch(own_jid):
@ -1076,7 +1077,8 @@ class MamMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.unique_id, origin_id = self.get_unique_id() self.unique_id, origin_id = self.get_unique_id()
# Check for duplicates # Check for duplicates
if app.logger.find_stanza_id(own_jid.getStripped(), if app.logger.find_stanza_id(account,
own_jid.getStripped(),
self.unique_id, origin_id): self.unique_id, origin_id):
return return
@ -1151,6 +1153,7 @@ class MamGcMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.kind = KindConstant.GC_MSG self.kind = KindConstant.GC_MSG
def generate(self): def generate(self):
account = self.conn.name
self.msg_ = self.forwarded.getTag('message', protocol=True) self.msg_ = self.forwarded.getTag('message', protocol=True)
if self.msg_.getType() != 'groupchat': if self.msg_.getType() != 'groupchat':
@ -1161,7 +1164,9 @@ class MamGcMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.unique_id = self.get_stanza_id(self.result, query=True) self.unique_id = self.get_stanza_id(self.result, query=True)
# Check for duplicates # Check for duplicates
if app.logger.find_stanza_id(self.room_jid, self.unique_id, if app.logger.find_stanza_id(account,
self.room_jid,
self.unique_id,
groupchat=True): groupchat=True):
return return
@ -1285,7 +1290,8 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
# Check groupchat messages for duplicates, # Check groupchat messages for duplicates,
# We do this because of MUC History messages # We do this because of MUC History messages
if self.stanza.getType() == 'groupchat': if self.stanza.getType() == 'groupchat':
if app.logger.find_stanza_id(self.stanza.getFrom().getStripped(), if app.logger.find_stanza_id(account,
self.stanza.getFrom().getStripped(),
self.unique_id, self.unique_id,
groupchat=True): groupchat=True):
return return

View File

@ -1057,10 +1057,12 @@ class Logger:
self.con.executescript(sql) self.con.executescript(sql)
self._timeout_commit() self._timeout_commit()
def search_for_duplicate(self, jid, timestamp, msg): def search_for_duplicate(self, account, jid, timestamp, msg):
""" """
Check if a message is already in the `logs` table Check if a message is already in the `logs` table
:param account: The account
:param jid: The jid as string :param jid: The jid as string
:param timestamp: The timestamp in UTC epoch :param timestamp: The timestamp in UTC epoch
@ -1072,27 +1074,31 @@ class Logger:
start_time = timestamp - 10 start_time = timestamp - 10
end_time = timestamp + 10 end_time = timestamp + 10
account_id = self.get_account_id(account)
log.debug('start: %s, end: %s, jid: %s, message: %s', log.debug('start: %s, end: %s, jid: %s, message: %s',
start_time, end_time, jid, msg) start_time, end_time, jid, msg)
sql = ''' sql = '''
SELECT * FROM logs SELECT * FROM logs
NATURAL JOIN jids WHERE jid = ? AND message = ? NATURAL JOIN jids WHERE jid = ? AND message = ? AND account_id = ?
AND time BETWEEN ? AND ? AND time BETWEEN ? AND ?
''' '''
result = self.con.execute(sql, (jid, msg, start_time, end_time)).fetchone() result = self.con.execute(
sql, (jid, msg, account_id, start_time, end_time)).fetchone()
if result is not None: if result is not None:
log.debug('Message already in DB') log.debug('Message already in DB')
return True return True
return False return False
def find_stanza_id(self, archive_jid, stanza_id, origin_id=None, def find_stanza_id(self, account, archive_jid, stanza_id, origin_id=None,
groupchat=False): groupchat=False):
""" """
Checks if a stanza-id is already in the `logs` table Checks if a stanza-id is already in the `logs` table
:param account: The account
:param archive_jid: The jid of the archive the stanza-id belongs to :param archive_jid: The jid of the archive the stanza-id belongs to
:param stanza_id: The stanza-id :param stanza_id: The stanza-id
@ -1113,22 +1119,30 @@ class Logger:
return False return False
archive_id = self.get_jid_id(archive_jid) archive_id = self.get_jid_id(archive_jid)
if groupchat: account_id = self.get_account_id(account)
column = 'jid_id'
else:
column = 'account_id'
if groupchat:
# Stanza ID is only unique within a specific archive.
# So a Stanza ID could be repeated in different MUCs, so we
# filter also for the archive JID
sql = ''' sql = '''
SELECT stanza_id FROM logs SELECT stanza_id FROM logs
WHERE stanza_id IN ({values}) AND {archive} = ? LIMIT 1 WHERE stanza_id IN ({values})
'''.format(values=', '.join('?' * len(ids)), AND jid_id = ? AND account_id = ? LIMIT 1
archive=column) '''.format(values=', '.join('?' * len(ids)))
result = self.con.execute(
result = self.con.execute(sql, tuple(ids) + (archive_id,)).fetchone() sql, tuple(ids) + (archive_id, account_id)).fetchone()
else:
sql = '''
SELECT stanza_id FROM logs
WHERE stanza_id IN ({values}) AND account_id = ? LIMIT 1
'''.format(values=', '.join('?' * len(ids)))
result = self.con.execute(
sql, tuple(ids) + (account_id,)).fetchone()
if result is not None: if result is not None:
log.info('Found duplicated message, stanza-id: %s, origin-id: %s', log.info('Found duplicated message, stanza-id: %s, origin-id: %s, '
stanza_id, origin_id) 'archive-jid: %s, account: %s', stanza_id, origin_id, archive_id, account_id)
return True return True
return False return False

View File

@ -203,7 +203,7 @@ class ConnectionArchive313:
# if self.archiving_namespace != nbxmpp.NS_MAM_2: # if self.archiving_namespace != nbxmpp.NS_MAM_2:
# Fallback duplicate search without stanza-id # Fallback duplicate search without stanza-id
duplicate = app.logger.search_for_duplicate( duplicate = app.logger.search_for_duplicate(
obj.with_, obj.timestamp, obj.msgtxt) self.name, obj.with_, obj.timestamp, obj.msgtxt)
if duplicate: if duplicate:
# dont propagate the event further # dont propagate the event further
return True return True