Philipp Hörist pushed to branch master at gajim / gajim
Commits: 9bb4c42a by lovetox at 2020-03-28T23:07:36+01:00 MAM: Use nbxmpp methods
- - - - - f92842d7 by lovetox at 2020-03-28T23:07:44+01:00 MAM: Remove mam:1 support
- - - - - d7c0852f by lovetox at 2020-03-28T23:07:44+01:00 MUC: Only depend on MAM for history
- - - - -
9 changed files:
- gajim/application.py - gajim/common/logger.py - gajim/common/modules/mam.py - gajim/common/modules/message.py - gajim/common/modules/muc.py - gajim/gtk/groupchat_info.py - gajim/gtk/history_sync.py - gajim/gtk/mam_preferences.py - gajim/gtk/server_info.py
Changes:
===================================== gajim/application.py ===================================== @@ -593,7 +593,7 @@ class GajimApplication(Gtk.Application): if event.feature == nbxmpp.NS_VCARD: action = '%s-profile' % event.account self.lookup_action(action).set_enabled(True) - elif event.feature in (nbxmpp.NS_MAM_1, nbxmpp.NS_MAM_2): + elif event.feature == nbxmpp.NS_MAM_2: action = '%s-archive' % event.account self.lookup_action(action).set_enabled(True) elif event.feature == nbxmpp.NS_PRIVACY:
===================================== gajim/common/logger.py ===================================== @@ -1333,42 +1333,6 @@ class Logger: return True return False
- @timeit - def search_for_duplicate(self, account, jid, timestamp, msg): - """ - Check if a message is already in the `logs` table - - :param account: The account - - :param jid: The jid as string - - :param timestamp: The timestamp in UTC epoch - - :param msg: The message text - """ - - # Add 10 seconds around the timestamp - start_time = timestamp - 30 - end_time = timestamp + 30 - - account_id = self.get_account_id(account) - log.debug('start: %s, end: %s, jid: %s, message: %s', - start_time, end_time, jid, msg) - - sql = ''' - SELECT * FROM logs - NATURAL JOIN jids WHERE jid = ? AND message = ? AND account_id = ? - AND time BETWEEN ? AND ? - ''' - - result = self._con.execute( - sql, (jid, msg, account_id, start_time, end_time)).fetchone() - - if result is not None: - log.debug('Message already in DB') - return True - return False - @timeit def find_stanza_id(self, account, archive_jid, stanza_id, origin_id=None, groupchat=False): @@ -1679,6 +1643,23 @@ class Logger: log.info('Set message archive info: %s %s', jid, kwargs) self._timeout_commit()
+ @timeit + def reset_archive_infos(self, jid): + """ + Set archive infos + + :param jid: The jid of the archive + + """ + jid_id = self.get_jid_id(jid) + sql = '''UPDATE last_archive_message + SET last_mam_id = NULL, oldest_mam_timestamp = NULL, + last_muc_timestamp = NULL + WHERE jid_id = ?''' + self._con.execute(sql, (jid_id,)) + log.info('Reset message archive info: %s', jid) + self._timeout_commit() + @timeit def _fill_disco_info_cache(self): sql = '''SELECT disco_info as "disco_info [disco_info]",
===================================== gajim/common/modules/mam.py ===================================== @@ -15,10 +15,12 @@ # XEP-0313: Message Archive Management
import time -from datetime import datetime, timedelta +from datetime import datetime +from datetime import timedelta
import nbxmpp from nbxmpp.util import generate_id +from nbxmpp.util import is_error_result from nbxmpp.structs import StanzaHandler
from gajim.common import app @@ -36,6 +38,14 @@ from gajim.common.modules.base import BaseModule
class MAM(BaseModule): + + _nbxmpp_extends = 'MAM' + _nbxmpp_methods = [ + 'request_preferences', + 'set_preferences', + 'make_query', + ] + def __init__(self, con): BaseModule.__init__(self, con)
@@ -49,33 +59,30 @@ class MAM(BaseModule): ]
self.available = False - self.archiving_namespace = None self._mam_query_ids = {}
# Holds archive jids where catch up was successful self._catch_up_finished = []
def pass_disco(self, info): - if nbxmpp.NS_MAM_2 in info.features: - self.archiving_namespace = nbxmpp.NS_MAM_2 - elif nbxmpp.NS_MAM_1 in info.features: - self.archiving_namespace = nbxmpp.NS_MAM_1 - else: + if nbxmpp.NS_MAM_2 not in info.features: return
self.available = True - self._log.info('Discovered MAM %s: %s', - self.archiving_namespace, info.jid) + self._log.info('Discovered MAM: %s', info.jid)
app.nec.push_incoming_event( NetworkEvent('feature-discovered', account=self._account, - feature=self.archiving_namespace)) + feature=nbxmpp.NS_MAM_2))
def reset_state(self): self._mam_query_ids.clear() self._catch_up_finished.clear()
+ def _remove_query_id(self, jid): + self._mam_query_ids.pop(jid, None) + def is_catch_up_finished(self, jid): return jid in self._catch_up_finished
@@ -112,27 +119,26 @@ class MAM(BaseModule):
if properties.type.is_groupchat: archive_jid = properties.jid.getBare() + timestamp = properties.timestamp + disco_info = app.logger.get_last_disco_info(archive_jid) if disco_info is None: # This is the case on MUC creation # After MUC configuration we receive a configuration change # message before we had the chance to disco the new MUC return - namespace = disco_info.mam_namespace - timestamp = properties.timestamp - if namespace is None: - # MUC History - app.logger.set_archive_infos( - archive_jid, - last_muc_timestamp=timestamp) + + if disco_info.mam_namespace != nbxmpp.NS_MAM_2: return
else: + if not self.available: + return + archive_jid = self._con.get_own_jid().getBare() - namespace = self.archiving_namespace timestamp = None
- if properties.stanza_id is None or namespace != nbxmpp.NS_MAM_2: + if properties.stanza_id is None: return
if not archive_jid == properties.stanza_id.by: @@ -179,16 +185,15 @@ class MAM(BaseModule):
stanza_id, message_id = self._get_unique_id(properties)
- if properties.mam.is_ver_2: - # Search only with stanza-id for duplicates on mam:2 - if app.logger.find_stanza_id(self._account, - str(properties.mam.archive), - stanza_id, - message_id, - groupchat=is_groupchat): - self._log.info('Found duplicate with stanza-id: %s, ' - 'message-id: %s', stanza_id, message_id) - raise nbxmpp.NodeProcessed + # Search for duplicates + if app.logger.find_stanza_id(self._account, + str(properties.mam.archive), + stanza_id, + message_id, + groupchat=is_groupchat): + self._log.info('Found duplicate with stanza-id: %s, ' + 'message-id: %s', stanza_id, message_id) + raise nbxmpp.NodeProcessed
additional_data = AdditionalDataDict() if properties.has_user_delay: @@ -223,12 +228,6 @@ class MAM(BaseModule): return stanza_id = message_id
- if properties.mam.namespace == nbxmpp.NS_MAM_1: - if app.logger.search_for_duplicate( - self._account, with_, properties.mam.timestamp, msgtxt): - self._log.info('Found duplicate with fallback for mam:1') - return - app.logger.insert_into_logs(self._account, with_, properties.mam.timestamp, @@ -253,7 +252,7 @@ class MAM(BaseModule): )
def _is_valid_request(self, properties): - valid_id = self._mam_query_ids.get(str(properties.mam.archive), None) + valid_id = self._mam_query_ids.get(properties.mam.archive, None) return valid_id == properties.mam.query_id
def _get_query_id(self, jid): @@ -261,59 +260,8 @@ class MAM(BaseModule): self._mam_query_ids[jid] = query_id return query_id
- def _parse_iq(self, stanza): - if not nbxmpp.isResultNode(stanza): - self._log.error('Error on MAM query: %s', stanza.getError()) - raise InvalidMamIQ - - fin = stanza.getTag('fin') - if fin is None: - self._log.error('Malformed MAM query result received: %s', stanza) - raise InvalidMamIQ - - set_ = fin.getTag('set', namespace=nbxmpp.NS_RSM) - if set_ is None: - self._log.error( - 'Malformed MAM query result received (no "set" Node): %s', - stanza) - raise InvalidMamIQ - return fin, set_ - - def _get_from_jid(self, stanza): - jid = stanza.getFrom() - if jid is None: - # No from means, iq from our own archive - jid = self._con.get_own_jid().getStripped() - else: - jid = jid.getStripped() - return jid - - def request_archive_count(self, start_date, end_date): - jid = self._con.get_own_jid().getStripped() - self._log.info('Request archive count from: %s', jid) - query_id = self._get_query_id(jid) - query = self._get_archive_query( - query_id, start=start_date, end=end_date, max_=0) - self._con.connection.SendAndCallForResponse( - query, self._received_count, {'query_id': query_id}) - return query_id - - def _received_count(self, _nbxmpp_client, stanza, query_id): - try: - _, set_ = self._parse_iq(stanza) - except InvalidMamIQ: - return - - jid = self._get_from_jid(stanza) - self._mam_query_ids.pop(jid) - - count = set_.getTagData('count') - self._log.info('Received archive count: %s', count) - app.nec.push_incoming_event(ArchivingCountReceived( - None, query_id=query_id, count=count)) - def request_archive_on_signin(self): - own_jid = self._con.get_own_jid().getStripped() + own_jid = self._con.get_own_jid().getBare()
if own_jid in self._mam_query_ids: self._log.warning('MAM request for %s already running', own_jid) @@ -331,49 +279,53 @@ class MAM(BaseModule): app.config.del_per('accounts', self._account, 'last_mam_id')
start_date = None - query_id = self._get_query_id(own_jid) + queryid = self._get_query_id(own_jid) if mam_id: self._log.info('MAM query after: %s', mam_id) - query = self._get_archive_query(query_id, after=mam_id) + else: # First Start, we request the last week start_date = datetime.utcnow() - timedelta(days=7) self._log.info('First start: query archive start: %s', start_date) - query = self._get_archive_query(query_id, start=start_date) + + self._nbxmpp('MAM').make_query(own_jid, + queryid, + after=mam_id, + start=start_date, + callback=self._result_finished, + user_data={'queryid': queryid, + 'start': start_date, + 'groupchat': False})
if own_jid in self._catch_up_finished: self._catch_up_finished.remove(own_jid) - self._send_archive_query(query, query_id, start_date)
def request_archive_on_muc_join(self, jid): archive = app.logger.get_archive_infos(jid) threshold = get_sync_threshold(jid, archive) self._log.info('Threshold for %s: %s', jid, threshold) - query_id = self._get_query_id(jid) + + mam_id = None start_date = None if archive is None or archive.last_mam_id is None: - # First Start, we dont request history - # Depending on what a MUC saves, there could be thousands - # of Messages even in just one day. + # First join start_date = datetime.utcnow() - timedelta(days=1) self._log.info('First join: query archive %s from: %s', jid, start_date) - query = self._get_archive_query( - query_id, jid=jid, start=start_date)
elif threshold == SyncThreshold.NO_THRESHOLD: # Not our first join and no threshold set + + mam_id = archive.last_mam_id self._log.info('Request from archive: %s, after mam-id %s', jid, archive.last_mam_id) - query = self._get_archive_query( - query_id, jid=jid, after=archive.last_mam_id)
else: # Not our first join, check how much time elapsed since our # last join and check against threshold last_timestamp = archive.last_muc_timestamp if last_timestamp is None: - self._log.info('No last muc timestamp found ( mam:1? )') + self._log.info('No last muc timestamp found') last_timestamp = 0
last = datetime.utcfromtimestamp(float(last_timestamp)) @@ -383,242 +335,138 @@ class MAM(BaseModule): self._log.info('Too much time elapsed since last join, ' 'request from: %s, threshold: %s', start_date, threshold) - query = self._get_archive_query( - query_id, jid=jid, start=start_date) + else: # Request from last mam-id + mam_id = archive.last_mam_id self._log.info('Request from archive %s after %s:', jid, archive.last_mam_id) - query = self._get_archive_query( - query_id, jid=jid, after=archive.last_mam_id)
if jid in self._catch_up_finished: self._catch_up_finished.remove(jid) - self._send_archive_query(query, query_id, start_date, groupchat=True) - - def _send_archive_query(self, query, query_id, start_date=None, - groupchat=False): - self._con.connection.SendAndCallForResponse( - query, self._result_finished, {'query_id': query_id, - 'start_date': start_date, - 'groupchat': groupchat}) - - def _result_finished(self, _nbxmpp_client, stanza, query_id, - start_date, groupchat): - try: - fin, set_ = self._parse_iq(stanza) - except InvalidMamIQ: - return
- jid = self._get_from_jid(stanza) + queryid = self._get_query_id(jid) + self._nbxmpp('MAM').make_query(jid, + queryid, + after=mam_id, + start=start_date, + callback=self._result_finished, + user_data={'queryid': queryid, + 'start': start_date, + 'groupchat': True}) + + def _result_finished(self, result, user_data): + queryid, start_date, groupchat = user_data.values() + self._remove_query_id(result.jid) + + if is_error_result(result): + if result.condition == 'item-not-found': + app.logger.reset_archive_infos(result.jid) + if groupchat: + self.request_archive_on_muc_join(result.jid) + else: + self.request_archive_on_signin() + return
- last = set_.getTagData('last') - if last is None: - self._log.info('End of MAM query, no items retrieved') - self._catch_up_finished.append(jid) - self._mam_query_ids.pop(jid) + if result.rsm.last is None: + self._log.info('MAM catchup finished: %s', result.jid) + self._catch_up_finished.append(result.jid) return
- complete = fin.getAttr('complete') - if complete != 'true': - app.logger.set_archive_infos(jid, last_mam_id=last) - self._mam_query_ids.pop(jid) - query_id = self._get_query_id(jid) - query = self._get_archive_query(query_id, jid=jid, after=last) - self._send_archive_query(query, query_id, groupchat=groupchat) + if not result.complete: + app.logger.set_archive_infos(result.jid, + last_mam_id=result.rsm.last) + queryid = self._get_query_id(result.jid) + + self._nbxmpp('MAM').make_query(result.jid, + queryid, + after=result.rsm.last, + callback=self._result_finished, + user_data={'queryid': queryid, + 'start': None, + 'groupchat': groupchat}) + else: - self._mam_query_ids.pop(jid) - app.logger.set_archive_infos( - jid, last_mam_id=last, last_muc_timestamp=time.time()) + app.logger.set_archive_infos(result.jid, + last_mam_id=result.rsm.last, + last_muc_timestamp=time.time()) + if start_date is not None and not groupchat: # Record the earliest timestamp we request from # the account archive. For the account archive we only # set start_date at the very first request. app.logger.set_archive_infos( - jid, oldest_mam_timestamp=start_date.timestamp()) + result.jid, + oldest_mam_timestamp=start_date.timestamp()) + + self._catch_up_finished.append(result.jid) + self._log.info('End of MAM query, last mam id: %s', + result.rsm.last)
- self._catch_up_finished.append(jid) - self._log.info('End of MAM query, last mam id: %s', last) + def request_archive_interval(self, + start_date, + end_date, + after=None, + queryid=None):
- def request_archive_interval(self, start_date, end_date, after=None, - query_id=None): - jid = self._con.get_own_jid().getStripped() if after is None: - self._log.info('Request intervall from %s to %s from %s', - start_date, end_date, jid) + self._log.info('Request interval from %s to %s', + start_date, end_date) else: - self._log.info('Query page after %s from %s', after, jid) - if query_id is None: - query_id = self._get_query_id(jid) - self._mam_query_ids[jid] = query_id - query = self._get_archive_query(query_id, start=start_date, - end=end_date, after=after, max_=30) - - self._con.connection.SendAndCallForResponse( - query, self._intervall_result, {'query_id': query_id, - 'start_date': start_date, - 'end_date': end_date}) - return query_id - - def _intervall_result(self, _nbxmpp_client, stanza, query_id, - start_date, end_date): - try: - fin, set_ = self._parse_iq(stanza) - except InvalidMamIQ: + self._log.info('Query page after %s', after) + + jid = self._con.get_own_jid().getBare() + if queryid is None: + queryid = self._get_query_id(jid) + self._mam_query_ids[jid] = queryid + + self._nbxmpp('MAM').make_query(jid, + queryid, + after=after, + start=start_date, + end=end_date, + callback=self._on_interval_result, + user_data={'queryid': queryid, + 'start_date': start_date, + 'end_date': end_date}) + return queryid + + def _on_interval_result(self, result, user_data): + queryid, start_date, end_date = user_data.values() + self._remove_query_id(result.jid) + + if is_error_result(result): return
- jid = self._get_from_jid(stanza) - self._mam_query_ids.pop(jid) if start_date: timestamp = start_date.timestamp() else: timestamp = ArchiveState.ALL
- last = set_.getTagData('last') - if last is None: - app.nec.push_incoming_event(ArchivingIntervalFinished( - None, query_id=query_id)) - app.logger.set_archive_infos( - jid, oldest_mam_timestamp=timestamp) + if result.rsm.last is None: + app.nec.push_incoming_event(NetworkEvent( + 'archiving-interval-finished', + account=self._account, + query_id=queryid)) + + app.logger.set_archive_infos(result.jid, + oldest_mam_timestamp=timestamp) self._log.info('End of MAM request, no items retrieved') return
- complete = fin.getAttr('complete') - if complete != 'true': - self.request_archive_interval(start_date, end_date, last, query_id) + if not result.complete: + self.request_archive_interval(start_date, + end_date, + result.rsm.last, + queryid) else: self._log.info('Request finished') - app.logger.set_archive_infos( - jid, oldest_mam_timestamp=timestamp) - app.nec.push_incoming_event(ArchivingIntervalFinished( - None, query_id=query_id)) - - def _get_archive_query(self, query_id, jid=None, start=None, end=None, - with_=None, after=None, max_=70): - # Muc archive query? - disco_info = app.logger.get_last_disco_info(jid) - if disco_info is None: - # Query to our own archive - namespace = self.archiving_namespace - else: - namespace = disco_info.mam_namespace - - iq = nbxmpp.Iq('set', to=jid) - query = iq.addChild('query', namespace=namespace) - form = query.addChild(node=nbxmpp.DataForm(typ='submit')) - field = nbxmpp.DataField(typ='hidden', - name='FORM_TYPE', - value=namespace) - form.addChild(node=field) - if start: - field = nbxmpp.DataField( - typ='text-single', - name='start', - value=start.strftime('%Y-%m-%dT%H:%M:%SZ')) - form.addChild(node=field) - if end: - field = nbxmpp.DataField(typ='text-single', - name='end', - value=end.strftime('%Y-%m-%dT%H:%M:%SZ')) - form.addChild(node=field) - if with_: - field = nbxmpp.DataField(typ='jid-single', - name='with', - value=with_) - form.addChild(node=field) - - set_ = query.setTag('set', namespace=nbxmpp.NS_RSM) - set_.setTagData('max', max_) - if after: - set_.setTagData('after', after) - query.setAttr('queryid', query_id) - return iq - - def request_mam_preferences(self): - self._log.info('Request MAM preferences') - iq = nbxmpp.Iq('get', self.archiving_namespace) - iq.setQuery('prefs') - self._con.connection.SendAndCallForResponse( - iq, self._preferences_received) - - def _preferences_received(self, _nbxmpp_client, stanza): - if not nbxmpp.isResultNode(stanza): - self._log.info('Error: %s', stanza.getError()) - app.nec.push_incoming_event(MAMPreferenceError( - None, conn=self._con, error=stanza.getError())) - return - - self._log.info('Received MAM preferences') - prefs = stanza.getTag('prefs', namespace=self.archiving_namespace) - if prefs is None: - self._log.error('Malformed stanza (no prefs node): %s', stanza) - return - - rules = [] - default = prefs.getAttr('default') - for item in prefs.getTag('always').getTags('jid'): - rules.append((item.getData(), 'Always')) - - for item in prefs.getTag('never').getTags('jid'): - rules.append((item.getData(), 'Never')) - - app.nec.push_incoming_event(MAMPreferenceReceived( - None, conn=self._con, rules=rules, default=default)) - - def set_mam_preferences(self, rules, default): - iq = nbxmpp.Iq(typ='set') - prefs = iq.addChild(name='prefs', - namespace=self.archiving_namespace, - attrs={'default': default}) - always = prefs.addChild(name='always') - never = prefs.addChild(name='never') - for item in rules: - jid, archive = item - if archive: - always.addChild(name='jid').setData(jid) - else: - never.addChild(name='jid').setData(jid) - - self._con.connection.SendAndCallForResponse( - iq, self._preferences_saved) - - def _preferences_saved(self, _nbxmpp_client, stanza): - if not nbxmpp.isResultNode(stanza): - self._log.info('Error: %s', stanza.getError()) - app.nec.push_incoming_event(MAMPreferenceError( - None, conn=self._con, error=stanza.getError())) - else: - self._log.info('Preferences saved') - app.nec.push_incoming_event( - MAMPreferenceSaved(None, conn=self._con)) - - -class MAMPreferenceError(NetworkIncomingEvent): - name = 'mam-prefs-error' - - -class MAMPreferenceReceived(NetworkIncomingEvent): - name = 'mam-prefs-received' - - -class MAMPreferenceSaved(NetworkIncomingEvent): - name = 'mam-prefs-saved' - - -class ArchivingCountReceived(NetworkIncomingEvent): - name = 'archiving-count-received' - - -class ArchivingIntervalFinished(NetworkIncomingEvent): - name = 'archiving-interval-finished' - - -class ArchivingErrorReceived(NetworkIncomingEvent): - name = 'archiving-error-received' - - -class InvalidMamIQ(Exception): - pass + app.logger.set_archive_infos(result.jid, + oldest_mam_timestamp=timestamp) + app.nec.push_incoming_event(NetworkEvent( + 'archiving-interval-finished', + account=self._account, + query_id=queryid))
def get_instance(*args, **kwargs):
===================================== gajim/common/modules/message.py ===================================== @@ -266,15 +266,16 @@ class Message(BaseModule): if properties.type.is_groupchat: disco_info = app.logger.get_last_disco_info( properties.jid.getBare()) - namespace = disco_info.mam_namespace + + if disco_info.mam_namespace != nbxmpp.NS_MAM_2: + return None, None + archive = properties.jid else: - namespace = self._con.get_module('MAM').archiving_namespace - archive = self._con.get_own_jid() + if not self._con.get_module('MAM').available: + return None, None
- if namespace != nbxmpp.NS_MAM_2: - # Only mam:2 ensures valid stanza-id - return None, None + archive = self._con.get_own_jid()
if archive.bareMatch(properties.stanza_id.by): return properties.stanza_id.id, None
===================================== gajim/common/modules/muc.py ===================================== @@ -17,9 +17,6 @@
import time import logging -from datetime import datetime -from datetime import timedelta -from datetime import timezone
import nbxmpp from nbxmpp.const import InviteType @@ -35,10 +32,8 @@ from gajim.common import helpers from gajim.common import ged from gajim.common.const import KindConstant from gajim.common.const import MUCJoinedState -from gajim.common.const import SyncThreshold from gajim.common.helpers import AdditionalDataDict from gajim.common.helpers import get_default_muc_config -from gajim.common.helpers import get_sync_threshold from gajim.common.helpers import to_user_string from gajim.common.helpers import event_filter from gajim.common import idle @@ -185,7 +180,7 @@ class MUC(BaseModule): status=self._con.status_message)
muc_x = presence.setTag(nbxmpp.NS_MUC + ' x') - self._add_history_query(muc_x, str(muc_data.jid)) + muc_x.setTag('history', {'maxchars': '0'})
if muc_data.password is not None: muc_x.setTagData('password', muc_data.password) @@ -340,32 +335,6 @@ class MUC(BaseModule): show=self._con.status, status=self._con.status_message)
- def _add_history_query(self, muc_x, room_jid): - disco_info = app.logger.get_last_disco_info(room_jid) - if disco_info.has_mam: - # The room is MAM capable dont get MUC History - muc_x.setTag('history', {'maxchars': '0'}) - else: - # Request MUC History (not MAM) - archive = app.logger.get_archive_infos(room_jid) - threshold = get_sync_threshold(room_jid, archive) - - since_epoch = 0 - if archive is not None and archive.last_muc_timestamp is not None: - since_epoch = float(archive.last_muc_timestamp) - - since_date = datetime.fromtimestamp(since_epoch, timezone.utc) - if threshold != SyncThreshold.NO_THRESHOLD: - now = datetime.now(timezone.utc) - threshold_date = now - timedelta(days=threshold) - since_date = max(threshold_date, since_date) - - date_string = since_date.strftime('%Y-%m-%dT%H:%M:%SZ') - muc_x.setTag('history', {'since': date_string}) - self._log.info('Request MUC history since: %s (%s)', - date_string, since_date.timestamp()) - self._log.info('Threshold for %s: %s', room_jid, threshold) - def _on_error_presence(self, _con, _stanza, properties): room_jid = properties.jid.getBare() muc_data = self._manager.get(room_jid)
===================================== gajim/gtk/groupchat_info.py ===================================== @@ -18,7 +18,6 @@ from gi.repository import Gdk from gi.repository import GLib from gi.repository import Gtk
-from nbxmpp.protocol import NS_MAM_1 from nbxmpp.protocol import NS_MAM_2
from gajim.common import app @@ -206,8 +205,7 @@ class GroupChatInfoScrolled(Gtk.ScrolledWindow): grid.remove_row(row) features = list(features)
- has_mam = NS_MAM_2 in features or NS_MAM_1 in features - if has_mam: + if NS_MAM_2 in features: features.append('mam')
row = 10
===================================== gajim/gtk/history_sync.py ===================================== @@ -19,6 +19,8 @@ from datetime import datetime, timedelta from gi.repository import Gtk from gi.repository import GLib
+from nbxmpp.util import is_error_result + from gajim.common import app from gajim.common import ged from gajim.common.i18n import _ @@ -139,18 +141,25 @@ class HistorySyncAssistant(Gtk.Assistant, EventHelper): log.info('Start: %s', self.start) log.info('End: %s', self.end)
- self.query_id = self.con.get_module('MAM').request_archive_count( - self.start, self.end) + jid = self.con.get_own_jid().getBare()
- def _received_count(self, event): - if event.query_id != self.query_id: + self.con.get_module('MAM').make_query(jid, + start=self.start, + end=self.end, + max_=0, + callback=self._received_count) + + + def _received_count(self, result): + if is_error_result(result): return
- if event.count is not None: - self.download_history.count = int(event.count) + if result.rsm.count is not None: + self.download_history.count = int(result.rsm.count) self.query_id = self.con.get_module('MAM').request_archive_interval( self.start, self.end)
+ @event_filter(['account']) def _received_finished(self, event): if event.query_id != self.query_id: return
===================================== gajim/gtk/mam_preferences.py ===================================== @@ -17,12 +17,14 @@ import logging from gi.repository import Gtk from gi.repository import Gdk
+from nbxmpp.util import is_error_result + from gajim.common import app -from gajim.common import ged from gajim.common.i18n import _
from gajim.gtk.util import get_builder from gajim.gtk.util import EventHelper +from gajim.gtk.util import ensure_not_destroyed from gajim.gtk.dialogs import DialogButton from gajim.gtk.dialogs import NewConfirmationDialog from gajim.gtk.dialogs import InformationDialog @@ -43,6 +45,7 @@ class MamPreferences(Gtk.ApplicationWindow, EventHelper):
self.account = account self._con = app.connections[account] + self._destroyed = False
self._ui = get_builder('mam_preferences.ui') self.add(self._ui.get_object('mam_box')) @@ -50,33 +53,40 @@ class MamPreferences(Gtk.ApplicationWindow, EventHelper): self._spinner = Gtk.Spinner() self._ui.overlay.add_overlay(self._spinner)
- self.register_events([ - ('mam-prefs-received', ged.GUI1, self._mam_prefs_received), - ('mam-prefs-saved', ged.GUI1, self._mam_prefs_saved), - ('mam-prefs-error', ged.GUI1, self._mam_prefs_error), - ]) - self._set_mam_box_state(False) + self.connect('destroy', self._on_destroy) self._ui.connect_signals(self) self.show_all()
self._activate_spinner()
- self._con.get_module('MAM').request_mam_preferences() + self._con.get_module('MAM').request_preferences( + callback=self._mam_prefs_received)
- def _mam_prefs_received(self, obj): - if obj.conn.name != self.account: + def _on_destroy(self, *args): + self._destroyed = True + + @ensure_not_destroyed + def _mam_prefs_received(self, result): + if is_error_result(result): + self._on_error(result.get_text()) return + self._disable_spinner() self._set_mam_box_state(True)
- self._ui.default_combo.set_active_id(obj.default) + self._ui.default_combo.set_active_id(result.default) self._ui.preferences_store.clear() - for item in obj.rules: - self._ui.preferences_store.append(item) + for jid in result.always: + self._ui.preferences_store.append((str(jid), 'Always'))
- def _mam_prefs_saved(self, obj): - if obj.conn.name != self.account: + for jid in result.never: + self._ui.preferences_store.append((str(jid), 'Never')) + + @ensure_not_destroyed + def _mam_prefs_saved(self, result): + if is_error_result(result): + self._on_error(result.get_text()) return
self._disable_spinner() @@ -91,18 +101,11 @@ class MamPreferences(Gtk.ApplicationWindow, EventHelper): [DialogButton.make('OK', callback=_on_ok)]).show()
- def _mam_prefs_error(self, obj=None): - if obj and obj.conn.name != self.account: - return - + def _on_error(self, error): self._disable_spinner()
- if not obj: - msg = _('No response from the Server') - else: - msg = _('Error received: {}').format(obj.error_msg) - - InformationDialog(_('Archiving Preferences Error'), msg) + InformationDialog(_('Archiving Preferences Error'), + _('Error received: {}').format(error))
self._set_mam_box_state(True)
@@ -130,11 +133,17 @@ class MamPreferences(Gtk.ApplicationWindow, EventHelper): def _on_save(self, _button): self._activate_spinner() self._set_mam_box_state(False) - items = [] + always = [] + never = [] default = self._ui.default_combo.get_active_id() for item in self._ui.preferences_store: - items.append((item[0].lower(), item[1])) - self._con.get_module('MAM').set_mam_preferences(items, default) + jid, type_ = item + if type_ == 'Always': + always.append(jid) + else: + never.append(jid) + self._con.get_module('MAM').set_preferences( + default, always, never, callback=self._mam_prefs_saved)
def _activate_spinner(self): self._spinner.show()
===================================== gajim/gtk/server_info.py ===================================== @@ -288,8 +288,7 @@ class ServerInfo(Gtk.ApplicationWindow, EventHelper): con.get_module('Carbons').supported, nbxmpp.NS_CARBONS), Feature('XEP-0313: Message Archive Management', - con.get_module('MAM').available, - con.get_module('MAM').archiving_namespace), + con.get_module('MAM').available), Feature('XEP-0363: HTTP File Upload', con.get_module('HTTPUpload').available, http_upload_info),
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/df2f93c08603a48079d87bbd12aa51e9...