Determine delay timestamp correctly
- Check the from attr on the delay node to determine if its a user timestamp or from the server - Dont use user timestamp for sorting - Record the user timestamp in additional data so its saved to the database Fixes #9444
This commit is contained in:
		
							parent
							
								
									b2ecc14cae
								
							
						
					
					
						commit
						6c2df54132
					
				
					 4 changed files with 108 additions and 21 deletions
				
			
		| 
						 | 
					@ -130,12 +130,13 @@ class MAM:
 | 
				
			||||||
            raise nbxmpp.NodeProcessed
 | 
					            raise nbxmpp.NodeProcessed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Timestamp parsing
 | 
					        # Timestamp parsing
 | 
				
			||||||
        timestamp = parse_delay(forwarded)
 | 
					        # Most servers dont set the 'from' attr, so we cant check for it
 | 
				
			||||||
        if timestamp is None:
 | 
					        delay_timestamp = parse_delay(forwarded)
 | 
				
			||||||
 | 
					        if delay_timestamp is None:
 | 
				
			||||||
 | 
					            log.warning('No timestamp on MAM message')
 | 
				
			||||||
 | 
					            log.warning(stanza)
 | 
				
			||||||
            raise nbxmpp.NodeProcessed
 | 
					            raise nbxmpp.NodeProcessed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        user_timestamp = parse_delay(message)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Fix for self messaging
 | 
					        # Fix for self messaging
 | 
				
			||||||
        if not groupchat:
 | 
					        if not groupchat:
 | 
				
			||||||
            to = message.getTo()
 | 
					            to = message.getTo()
 | 
				
			||||||
| 
						 | 
					@ -180,8 +181,7 @@ class MAM:
 | 
				
			||||||
            {'conn': self._con,
 | 
					            {'conn': self._con,
 | 
				
			||||||
             'additional_data': {},
 | 
					             'additional_data': {},
 | 
				
			||||||
             'encrypted': False,
 | 
					             'encrypted': False,
 | 
				
			||||||
             'timestamp': timestamp,
 | 
					             'timestamp': delay_timestamp,
 | 
				
			||||||
             'user_timestamp': user_timestamp,
 | 
					 | 
				
			||||||
             'self_message': self_message,
 | 
					             'self_message': self_message,
 | 
				
			||||||
             'groupchat': groupchat,
 | 
					             'groupchat': groupchat,
 | 
				
			||||||
             'muc_pm': muc_pm,
 | 
					             'muc_pm': muc_pm,
 | 
				
			||||||
| 
						 | 
					@ -248,7 +248,12 @@ class MAM:
 | 
				
			||||||
            # For example Chatstates, Receipts, Chatmarkers
 | 
					            # For example Chatstates, Receipts, Chatmarkers
 | 
				
			||||||
            log.debug(event.message.getProperties())
 | 
					            log.debug(event.message.getProperties())
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
        log.debug(event.msgtxt)
 | 
					
 | 
				
			||||||
 | 
					        user_timestamp = parse_delay(event.stanza)
 | 
				
			||||||
 | 
					        if user_timestamp is not None:
 | 
				
			||||||
 | 
					            # Record it as a user timestamp
 | 
				
			||||||
 | 
					            event.additional_data.set_value(
 | 
				
			||||||
 | 
					                'gajim', 'user_timestamp', user_timestamp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        event.correct_id = parse_correction(event.message)
 | 
					        event.correct_id = parse_correction(event.message)
 | 
				
			||||||
        parse_oob(event.message, event.additional_data)
 | 
					        parse_oob(event.message, event.additional_data)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -223,15 +223,40 @@ class Message:
 | 
				
			||||||
        except nbxmpp.NodeProcessed:
 | 
					        except nbxmpp.NodeProcessed:
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        timestamp, delayed = parse_delay(event.stanza), True
 | 
					        subject = event.stanza.getSubject()
 | 
				
			||||||
        if timestamp is None:
 | 
					        groupchat = event.mtype == 'groupchat'
 | 
				
			||||||
 | 
					        muc_subject = subject and groupchat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Determine timestamps
 | 
				
			||||||
 | 
					        if groupchat:
 | 
				
			||||||
 | 
					            delay_entity_jid = event.jid
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            delay_entity_jid = self._con.get_own_jid().getDomain()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if muc_subject:
 | 
				
			||||||
 | 
					            # MUC Subjects can have a delay timestamp
 | 
				
			||||||
 | 
					            # to indicate when the user has set the subject,
 | 
				
			||||||
 | 
					            # the 'from' attr on these delays is the MUC server
 | 
				
			||||||
 | 
					            # but we treat it as user timestamp
 | 
				
			||||||
            timestamp = time.time()
 | 
					            timestamp = time.time()
 | 
				
			||||||
            delayed = False
 | 
					            user_timestamp = parse_delay(event.stanza, from_=delay_entity_jid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            timestamp = parse_delay(event.stanza, from_=delay_entity_jid)
 | 
				
			||||||
 | 
					            if timestamp is None:
 | 
				
			||||||
 | 
					                timestamp = time.time()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            user_timestamp = parse_delay(event.stanza,
 | 
				
			||||||
 | 
					                                         not_from=[delay_entity_jid])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if user_timestamp is not None:
 | 
				
			||||||
 | 
					            event.additional_data.set_value(
 | 
				
			||||||
 | 
					                'gajim', 'user_timestamp', user_timestamp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        event_attr = {
 | 
					        event_attr = {
 | 
				
			||||||
            'popup': False,
 | 
					            'popup': False,
 | 
				
			||||||
            'msg_log_id': None,
 | 
					            'msg_log_id': None,
 | 
				
			||||||
            'subject': event.stanza.getSubject(),
 | 
					            'subject': subject,
 | 
				
			||||||
            'displaymarking': parse_securitylabel(event.stanza),
 | 
					            'displaymarking': parse_securitylabel(event.stanza),
 | 
				
			||||||
            'attention': parse_attention(event.stanza),
 | 
					            'attention': parse_attention(event.stanza),
 | 
				
			||||||
            'correct_id': parse_correction(event.stanza),
 | 
					            'correct_id': parse_correction(event.stanza),
 | 
				
			||||||
| 
						 | 
					@ -239,7 +264,7 @@ class Message:
 | 
				
			||||||
            'form_node': parse_form(event.stanza),
 | 
					            'form_node': parse_form(event.stanza),
 | 
				
			||||||
            'xhtml': parse_xhtml(event.stanza),
 | 
					            'xhtml': parse_xhtml(event.stanza),
 | 
				
			||||||
            'timestamp': timestamp,
 | 
					            'timestamp': timestamp,
 | 
				
			||||||
            'delayed': delayed,
 | 
					            'delayed': user_timestamp is not None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        parse_oob(event.stanza, event.additional_data)
 | 
					        parse_oob(event.stanza, event.additional_data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -257,7 +282,7 @@ class Message:
 | 
				
			||||||
                    event.session, event.fjid, timestamp)
 | 
					                    event.session, event.fjid, timestamp)
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if event.mtype == 'groupchat':
 | 
					        if groupchat:
 | 
				
			||||||
            app.nec.push_incoming_event(GcMessageReceivedEvent(
 | 
					            app.nec.push_incoming_event(GcMessageReceivedEvent(
 | 
				
			||||||
                None,
 | 
					                None,
 | 
				
			||||||
                conn=self._con,
 | 
					                conn=self._con,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,18 +65,45 @@ def parse_eme(stanza):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# XEP-0203: Delayed Delivery
 | 
					# XEP-0203: Delayed Delivery
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def parse_delay(stanza, epoch=True, convert='utc'):
 | 
					def parse_delay(stanza, epoch=True, convert='utc', from_=None, not_from=None):
 | 
				
			||||||
    timestamp = None
 | 
					    '''
 | 
				
			||||||
    delay = stanza.getTagAttr(
 | 
					    Returns the first valid delay timestamp that matches
 | 
				
			||||||
        'delay', 'stamp', namespace=nbxmpp.NS_DELAY2)
 | 
					
 | 
				
			||||||
    if delay is not None:
 | 
					    :param epoch:      Returns the timestamp as epoch
 | 
				
			||||||
        timestamp = parse_datetime(delay, check_utc=True,
 | 
					
 | 
				
			||||||
 | 
					    :param convert:    Converts the timestamp to either utc or local
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :param from_:      Matches only delays that have the according
 | 
				
			||||||
 | 
					                       from attr set
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :param not_from:   Matches only delays that have the according
 | 
				
			||||||
 | 
					                       from attr not set
 | 
				
			||||||
 | 
					    '''
 | 
				
			||||||
 | 
					    delays = stanza.getTags('delay', namespace=nbxmpp.NS_DELAY2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for delay in delays:
 | 
				
			||||||
 | 
					        stamp = delay.getAttr('stamp')
 | 
				
			||||||
 | 
					        if stamp is None:
 | 
				
			||||||
 | 
					            log.warning('Invalid timestamp received: %s', stamp)
 | 
				
			||||||
 | 
					            log.warning(stanza)
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        delay_from = delay.getAttr('from')
 | 
				
			||||||
 | 
					        if from_ is not None:
 | 
				
			||||||
 | 
					            if delay_from != from_:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					        if not_from is not None:
 | 
				
			||||||
 | 
					            if delay_from in not_from:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        timestamp = parse_datetime(stamp, check_utc=True,
 | 
				
			||||||
                                   epoch=epoch, convert=convert)
 | 
					                                   epoch=epoch, convert=convert)
 | 
				
			||||||
        if timestamp is None:
 | 
					        if timestamp is None:
 | 
				
			||||||
            log.warning('Invalid timestamp received: %s', delay)
 | 
					            log.warning('Invalid timestamp received: %s', stamp)
 | 
				
			||||||
            log.warning(stanza)
 | 
					            log.warning(stanza)
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return timestamp
 | 
					        return timestamp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# XEP-0066: Out of Band Data
 | 
					# XEP-0066: Out of Band Data
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										30
									
								
								test/no_gui/unit/test_helpers.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								test/no_gui/unit/test_helpers.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,30 @@
 | 
				
			||||||
 | 
					import unittest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import nbxmpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from gajim.common.modules.misc import parse_delay
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestHelpers(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_parse_delay(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        node = """
 | 
				
			||||||
 | 
					        <message>
 | 
				
			||||||
 | 
					            <delay xmlns='urn:xmpp:delay' from='capulet.com' stamp='2002-09-10T23:08:25Z' />
 | 
				
			||||||
 | 
					            <delay xmlns='urn:xmpp:delay' from='romeo.com' stamp='2010-09-10T23:08:25Z' />
 | 
				
			||||||
 | 
					            <delay xmlns='urn:xmpp:delay' stamp='2015-09-10T23:08:25Z' />
 | 
				
			||||||
 | 
					        </message>
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        message = nbxmpp.Node(node=node)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        timestamp = parse_delay(message)
 | 
				
			||||||
 | 
					        self.assertEqual(timestamp, 1031699305.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        timestamp = parse_delay(message, from_='capulet.com')
 | 
				
			||||||
 | 
					        self.assertEqual(timestamp, 1031699305.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        timestamp = parse_delay(message, from_='romeo.com')
 | 
				
			||||||
 | 
					        self.assertEqual(timestamp, 1284160105.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        timestamp = parse_delay(message, not_from=['romeo.com'])
 | 
				
			||||||
 | 
					        self.assertEqual(timestamp, 1031699305.0)
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue