Philipp Hörist pushed to branch master at gajim / gajim

Commits:

23 changed files:

Changes:

  • gajim/application.py
    ... ... @@ -56,6 +56,7 @@ from gajim.common import logger
    56 56
     from gajim.common.i18n import _
    
    57 57
     from gajim.common.contacts import LegacyContactsAPI
    
    58 58
     from gajim.common.task_manager import TaskManager
    
    59
    +from gajim.common.storage.cache import CacheStorage
    
    59 60
     
    
    60 61
     
    
    61 62
     class GajimApplication(Gtk.Application):
    
    ... ... @@ -182,6 +183,8 @@ class GajimApplication(Gtk.Application):
    182 183
             app.print_version()
    
    183 184
             app.detect_dependencies()
    
    184 185
             configpaths.create_paths()
    
    186
    +        app.storage.cache = CacheStorage()
    
    187
    +        app.storage.cache.init()
    
    185 188
             try:
    
    186 189
                 app.logger = logger.Logger()
    
    187 190
                 app.contacts = LegacyContactsAPI()
    

  • gajim/common/app.py
    ... ... @@ -71,6 +71,12 @@ plugin_manager = None # Plugins Manager
    71 71
     
    
    72 72
     logger = cast(LoggerT, None)
    
    73 73
     
    
    74
    +class Storage:
    
    75
    +    def __init__(self):
    
    76
    +        self.cache = None
    
    77
    +
    
    78
    +storage = Storage()
    
    79
    +
    
    74 80
     css_config = None
    
    75 81
     
    
    76 82
     transport_type = {}  # type: Dict[str, str]
    

  • gajim/common/contacts.py
    ... ... @@ -143,7 +143,7 @@ class CommonContact(XMPPEntity):
    143 143
                 # return caps for a contact that has no resources left.
    
    144 144
                 return False
    
    145 145
     
    
    146
    -        disco_info = app.logger.get_last_disco_info(self.get_full_jid())
    
    146
    +        disco_info = app.storage.cache.get_last_disco_info(self.get_full_jid())
    
    147 147
             if disco_info is None:
    
    148 148
                 return False
    
    149 149
     
    
    ... ... @@ -151,7 +151,7 @@ class CommonContact(XMPPEntity):
    151 151
     
    
    152 152
         @property
    
    153 153
         def uses_phone(self):
    
    154
    -        disco_info = app.logger.get_last_disco_info(self.get_full_jid())
    
    154
    +        disco_info = app.storage.cache.get_last_disco_info(self.get_full_jid())
    
    155 155
             if disco_info is None:
    
    156 156
                 return False
    
    157 157
     
    
    ... ... @@ -271,7 +271,7 @@ class Contact(CommonContact):
    271 271
             if not self.is_groupchat:
    
    272 272
                 raise ValueError
    
    273 273
     
    
    274
    -        disco_info = app.logger.get_last_disco_info(self.jid)
    
    274
    +        disco_info = app.storage.cache.get_last_disco_info(self.jid)
    
    275 275
     
    
    276 276
             context = 'public'
    
    277 277
             if disco_info is not None and disco_info.muc_is_members_only:
    

  • gajim/common/helpers.py
    ... ... @@ -898,7 +898,7 @@ def call_counter(func):
    898 898
         return helper
    
    899 899
     
    
    900 900
     def get_sync_threshold(jid, archive_info):
    
    901
    -    disco_info = app.logger.get_last_disco_info(jid)
    
    901
    +    disco_info = app.storage.cache.get_last_disco_info(jid)
    
    902 902
         if archive_info is None or archive_info.sync_threshold is None:
    
    903 903
             if disco_info is not None and disco_info.muc_is_members_only:
    
    904 904
                 threshold = app.settings.get('private_room_sync_threshold')
    
    ... ... @@ -1231,7 +1231,7 @@ def get_groupchat_name(con, jid):
    1231 1231
         if name:
    
    1232 1232
             return name
    
    1233 1233
     
    
    1234
    -    disco_info = app.logger.get_last_disco_info(jid)
    
    1234
    +    disco_info = app.storage.cache.get_last_disco_info(jid)
    
    1235 1235
         if disco_info is not None:
    
    1236 1236
             if disco_info.muc_name:
    
    1237 1237
                 return disco_info.muc_name
    

  • gajim/common/logger.py
    ... ... @@ -28,7 +28,6 @@ This module allows to access the on-disk database of logs
    28 28
     import os
    
    29 29
     import sys
    
    30 30
     import time
    
    31
    -import math
    
    32 31
     import datetime
    
    33 32
     import calendar
    
    34 33
     import json
    
    ... ... @@ -38,20 +37,16 @@ from collections import namedtuple
    38 37
     
    
    39 38
     from gi.repository import GLib
    
    40 39
     
    
    41
    -from nbxmpp.protocol import Iq
    
    42
    -from nbxmpp.protocol import JID
    
    43
    -from nbxmpp.structs import DiscoInfo
    
    44
    -from nbxmpp.structs import CommonError
    
    45
    -from nbxmpp.modules.discovery import parse_disco_info
    
    46
    -
    
    47 40
     from gajim.common import exceptions
    
    48 41
     from gajim.common import app
    
    49 42
     from gajim.common import configpaths
    
    50 43
     from gajim.common.helpers import AdditionalDataDict
    
    51 44
     from gajim.common.i18n import _
    
    52
    -from gajim.common.const import (
    
    53
    -    JIDConstant, KindConstant, ShowConstant, TypeConstant,
    
    54
    -    SubscriptionConstant)
    
    45
    +from gajim.common.const import ShowConstant
    
    46
    +from gajim.common.const import KindConstant
    
    47
    +from gajim.common.const import JIDConstant
    
    48
    +
    
    49
    +from gajim.common.storage.base import timeit
    
    55 50
     
    
    56 51
     
    
    57 52
     LOGS_SQL_STATEMENT = '''
    
    ... ... @@ -97,113 +92,23 @@ LOGS_SQL_STATEMENT = '''
    97 92
         PRAGMA user_version=5;
    
    98 93
         '''
    
    99 94
     
    
    100
    -CACHE_SQL_STATEMENT = '''
    
    101
    -    CREATE TABLE transports_cache (
    
    102
    -            transport TEXT UNIQUE,
    
    103
    -            type INTEGER
    
    104
    -    );
    
    105
    -    CREATE TABLE caps_cache (
    
    106
    -            hash_method TEXT,
    
    107
    -            hash TEXT,
    
    108
    -            data TEXT,
    
    109
    -            last_seen INTEGER
    
    110
    -    );
    
    111
    -    CREATE TABLE last_seen_disco_info(
    
    112
    -            jid TEXT PRIMARY KEY UNIQUE,
    
    113
    -            disco_info TEXT,
    
    114
    -            last_seen INTEGER
    
    115
    -    );
    
    116
    -    CREATE TABLE roster_entry(
    
    117
    -            account_jid_id INTEGER,
    
    118
    -            jid_id INTEGER,
    
    119
    -            name TEXT,
    
    120
    -            subscription INTEGER,
    
    121
    -            ask BOOLEAN,
    
    122
    -            avatar_sha TEXT,
    
    123
    -            PRIMARY KEY (account_jid_id, jid_id)
    
    124
    -    );
    
    125
    -    CREATE TABLE roster_group(
    
    126
    -            account_jid_id INTEGER,
    
    127
    -            jid_id INTEGER,
    
    128
    -            group_name TEXT,
    
    129
    -            PRIMARY KEY (account_jid_id, jid_id, group_name)
    
    130
    -    );
    
    131
    -    CREATE TABLE muc_avatars(
    
    132
    -            jid TEXT PRIMARY KEY UNIQUE,
    
    133
    -            avatar_sha TEXT
    
    134
    -    );
    
    135
    -    PRAGMA user_version=5;
    
    136
    -    '''
    
    137 95
     
    
    138 96
     log = logging.getLogger('gajim.c.logger')
    
    139 97
     
    
    140 98
     
    
    141
    -def timeit(func):
    
    142
    -    def func_wrapper(self, *args, **kwargs):
    
    143
    -        start = time.time()
    
    144
    -        result = func(self, *args, **kwargs)
    
    145
    -        exec_time = (time.time() - start) * 1e3
    
    146
    -        level = 30 if exec_time > 50 else 10
    
    147
    -        log.log(level, 'Execution time for %s: %s ms',
    
    148
    -                func.__name__, math.ceil(exec_time))
    
    149
    -        return result
    
    150
    -    return func_wrapper
    
    151
    -
    
    152
    -def _convert_disco_info(disco_info):
    
    153
    -    return parse_disco_info(Iq(node=disco_info))
    
    154
    -
    
    155
    -def _adapt_disco_info(disco_info):
    
    156
    -    return str(disco_info.stanza)
    
    157
    -
    
    158
    -def _convert_common_error(common_error):
    
    159
    -    return CommonError.from_string(common_error)
    
    160
    -
    
    161
    -def _adapt_common_error(common_error):
    
    162
    -    return common_error.serialize()
    
    163
    -
    
    164
    -def _convert_marker(marker):
    
    165
    -    return 'received' if marker == 0 else 'displayed'
    
    166
    -
    
    167
    -def _jid_adapter(jid):
    
    168
    -    return str(jid)
    
    169
    -
    
    170
    -def _jid_converter(jid):
    
    171
    -    return JID.from_string(jid.decode())
    
    172
    -
    
    173
    -
    
    174
    -sqlite.register_converter('jid', _jid_converter)
    
    175
    -sqlite.register_adapter(JID, _jid_adapter)
    
    176
    -
    
    177
    -sqlite.register_converter('disco_info', _convert_disco_info)
    
    178
    -sqlite.register_adapter(DiscoInfo, _adapt_disco_info)
    
    179
    -
    
    180
    -sqlite.register_converter('common_error', _convert_common_error)
    
    181
    -sqlite.register_adapter(CommonError, _adapt_common_error)
    
    182
    -
    
    183
    -sqlite.register_converter('marker', _convert_marker)
    
    184
    -
    
    185
    -
    
    186 99
     class Logger:
    
    187 100
         def __init__(self):
    
    101
    +        self._log = log
    
    188 102
             self._jid_ids = {}
    
    189 103
             self._jid_ids_reversed = {}
    
    190 104
             self._con = None
    
    191 105
             self._commit_timout_id = None
    
    192 106
             self._log_db_path = configpaths.get('LOG_DB')
    
    193
    -        self._cache_db_path = configpaths.get('CACHE_DB')
    
    194
    -
    
    195
    -        self._entity_caps_cache = {}
    
    196
    -        self._disco_info_cache = {}
    
    197
    -        self._muc_avatar_sha_cache = {}
    
    198 107
     
    
    199 108
             self._create_databases()
    
    200 109
             self._migrate_databases()
    
    201 110
             self._connect_databases()
    
    202 111
             self._get_jid_ids_from_db()
    
    203
    -        self._fill_disco_info_cache()
    
    204
    -        self._fill_muc_avatar_sha_cache()
    
    205
    -        self._clean_caps_table()
    
    206
    -        self._load_caps_data()
    
    207 112
     
    
    208 113
         def _create_databases(self):
    
    209 114
             if os.path.isdir(self._log_db_path):
    
    ... ... @@ -211,19 +116,9 @@ class Logger:
    211 116
                           self._log_db_path)
    
    212 117
                 sys.exit()
    
    213 118
     
    
    214
    -        if os.path.isdir(self._cache_db_path):
    
    215
    -            log.error(_('%s is a directory but should be a file'),
    
    216
    -                      self._cache_db_path)
    
    217
    -            sys.exit()
    
    218
    -
    
    219 119
             if not os.path.exists(self._log_db_path):
    
    220
    -            if os.path.exists(self._cache_db_path):
    
    221
    -                os.remove(self._cache_db_path)
    
    222 120
                 self._create(LOGS_SQL_STATEMENT, self._log_db_path)
    
    223 121
     
    
    224
    -        if not os.path.exists(self._cache_db_path):
    
    225
    -            self._create(CACHE_SQL_STATEMENT, self._cache_db_path)
    
    226
    -
    
    227 122
         @staticmethod
    
    228 123
         def _connect(*args, **kwargs):
    
    229 124
             con = sqlite.connect(*args, **kwargs)
    
    ... ... @@ -257,10 +152,6 @@ class Logger:
    257 152
                 con = self._connect(self._log_db_path)
    
    258 153
                 self._migrate_logs(con)
    
    259 154
                 con.close()
    
    260
    -
    
    261
    -            con = self._connect(self._cache_db_path)
    
    262
    -            self._migrate_cache(con)
    
    263
    -            con.close()
    
    264 155
             except Exception:
    
    265 156
                 log.exception('Error')
    
    266 157
                 sys.exit()
    
    ... ... @@ -318,50 +209,6 @@ class Logger:
    318 209
                 ]
    
    319 210
                 self._execute_multiple(con, statements)
    
    320 211
     
    
    321
    -    @timeit
    
    322
    -    def _migrate_cache(self, con):
    
    323
    -        if self._get_user_version(con) == 0:
    
    324
    -            # All migrations from 0.16.9 until 1.0.0
    
    325
    -            statements = [
    
    326
    -                'ALTER TABLE roster_entry ADD COLUMN "avatar_sha" TEXT',
    
    327
    -                'PRAGMA user_version=1'
    
    328
    -                ]
    
    329
    -            self._execute_multiple(con, statements)
    
    330
    -
    
    331
    -        if self._get_user_version(con) < 2:
    
    332
    -            statements = [
    
    333
    -                'DROP TABLE IF EXISTS caps_cache',
    
    334
    -                'CREATE TABLE caps_cache (hash_method TEXT, hash TEXT, data TEXT, last_seen INTEGER)',
    
    335
    -                'PRAGMA user_version=2'
    
    336
    -                ]
    
    337
    -            self._execute_multiple(con, statements)
    
    338
    -
    
    339
    -        if self._get_user_version(con) < 3:
    
    340
    -            statements = [
    
    341
    -                '''CREATE TABLE last_seen_disco_info(
    
    342
    -                    jid TEXT PRIMARY KEY UNIQUE,
    
    343
    -                    disco_info TEXT,
    
    344
    -                    last_seen INTEGER)''',
    
    345
    -                'PRAGMA user_version=3'
    
    346
    -                ]
    
    347
    -            self._execute_multiple(con, statements)
    
    348
    -
    
    349
    -        if self._get_user_version(con) < 4:
    
    350
    -            statements = [
    
    351
    -                '''CREATE TABLE muc_avatars(
    
    352
    -                   jid TEXT PRIMARY KEY UNIQUE,
    
    353
    -                   avatar_sha TEXT)''',
    
    354
    -                'PRAGMA user_version=4'
    
    355
    -                ]
    
    356
    -            self._execute_multiple(con, statements)
    
    357
    -
    
    358
    -        if self._get_user_version(con) < 5:
    
    359
    -            statements = [
    
    360
    -                'DELETE FROM caps_cache',
    
    361
    -                'PRAGMA user_version=5'
    
    362
    -                ]
    
    363
    -            self._execute_multiple(con, statements)
    
    364
    -
    
    365 212
         @staticmethod
    
    366 213
         def _execute_multiple(con, statements):
    
    367 214
             """
    
    ... ... @@ -416,13 +263,6 @@ class Logger:
    416 263
             self._con.create_function("get_timeout", 0, self._get_timeout)
    
    417 264
     
    
    418 265
             self._set_synchronous(False)
    
    419
    -        try:
    
    420
    -            self._con.execute("ATTACH DATABASE '%s' AS cache" %
    
    421
    -                              self._cache_db_path.replace("'", "''"))
    
    422
    -        except Exception:
    
    423
    -            log.exception('Error')
    
    424
    -            self._con.close()
    
    425
    -            sys.exit()
    
    426 266
     
    
    427 267
         @timeit
    
    428 268
         def _set_synchronous(self, sync):
    
    ... ... @@ -594,99 +434,6 @@ class Logger:
    594 434
             # it's a RFC violation .... but we should not crash
    
    595 435
             return None
    
    596 436
     
    
    597
    -    def convert_human_transport_type_to_db_api_values(self, type_):
    
    598
    -        """
    
    599
    -        Convert from string style to constant ints for db
    
    600
    -        """
    
    601
    -        if type_ == 'aim':
    
    602
    -            return TypeConstant.AIM
    
    603
    -        if type_ == 'gadu-gadu':
    
    604
    -            return TypeConstant.GG
    
    605
    -        if type_ == 'http-ws':
    
    606
    -            return TypeConstant.HTTP_WS
    
    607
    -        if type_ == 'icq':
    
    608
    -            return TypeConstant.ICQ
    
    609
    -        if type_ == 'msn':
    
    610
    -            return TypeConstant.MSN
    
    611
    -        if type_ == 'qq':
    
    612
    -            return TypeConstant.QQ
    
    613
    -        if type_ == 'sms':
    
    614
    -            return TypeConstant.SMS
    
    615
    -        if type_ == 'smtp':
    
    616
    -            return TypeConstant.SMTP
    
    617
    -        if type_ in ('tlen', 'x-tlen'):
    
    618
    -            return TypeConstant.TLEN
    
    619
    -        if type_ == 'newmail':
    
    620
    -            return TypeConstant.NEWMAIL
    
    621
    -        if type_ == 'rss':
    
    622
    -            return TypeConstant.RSS
    
    623
    -        if type_ == 'weather':
    
    624
    -            return TypeConstant.WEATHER
    
    625
    -        if type_ == 'mrim':
    
    626
    -            return TypeConstant.MRIM
    
    627
    -        if type_ == 'jabber':
    
    628
    -            return TypeConstant.NO_TRANSPORT
    
    629
    -        return None
    
    630
    -
    
    631
    -    def convert_api_values_to_human_transport_type(self, type_id):
    
    632
    -        """
    
    633
    -        Convert from constant ints for db to string style
    
    634
    -        """
    
    635
    -        if type_id == TypeConstant.AIM:
    
    636
    -            return 'aim'
    
    637
    -        if type_id == TypeConstant.GG:
    
    638
    -            return 'gadu-gadu'
    
    639
    -        if type_id == TypeConstant.HTTP_WS:
    
    640
    -            return 'http-ws'
    
    641
    -        if type_id == TypeConstant.ICQ:
    
    642
    -            return 'icq'
    
    643
    -        if type_id == TypeConstant.MSN:
    
    644
    -            return 'msn'
    
    645
    -        if type_id == TypeConstant.QQ:
    
    646
    -            return 'qq'
    
    647
    -        if type_id == TypeConstant.SMS:
    
    648
    -            return 'sms'
    
    649
    -        if type_id == TypeConstant.SMTP:
    
    650
    -            return 'smtp'
    
    651
    -        if type_id == TypeConstant.TLEN:
    
    652
    -            return 'tlen'
    
    653
    -        if type_id == TypeConstant.NEWMAIL:
    
    654
    -            return 'newmail'
    
    655
    -        if type_id == TypeConstant.RSS:
    
    656
    -            return 'rss'
    
    657
    -        if type_id == TypeConstant.WEATHER:
    
    658
    -            return 'weather'
    
    659
    -        if type_id == TypeConstant.MRIM:
    
    660
    -            return 'mrim'
    
    661
    -        if type_id == TypeConstant.NO_TRANSPORT:
    
    662
    -            return 'jabber'
    
    663
    -
    
    664
    -    def convert_xmpp_sub(self, sub):
    
    665
    -        """
    
    666
    -        Convert from string style to constant ints for db
    
    667
    -        """
    
    668
    -        if sub == 'none':
    
    669
    -            return SubscriptionConstant.NONE
    
    670
    -        if sub == 'to':
    
    671
    -            return SubscriptionConstant.TO
    
    672
    -        if sub == 'from':
    
    673
    -            return SubscriptionConstant.FROM
    
    674
    -        if sub == 'both':
    
    675
    -            return SubscriptionConstant.BOTH
    
    676
    -
    
    677
    -    def convert_db_sub(self, sub):
    
    678
    -        """
    
    679
    -        Convert from constant ints for db to string style
    
    680
    -        """
    
    681
    -        if sub == SubscriptionConstant.NONE:
    
    682
    -            return 'none'
    
    683
    -        if sub == SubscriptionConstant.TO:
    
    684
    -            return 'to'
    
    685
    -        if sub == SubscriptionConstant.FROM:
    
    686
    -            return 'from'
    
    687
    -        if sub == SubscriptionConstant.BOTH:
    
    688
    -            return 'both'
    
    689
    -
    
    690 437
         @timeit
    
    691 438
         def insert_unread_events(self, message_id, jid_id):
    
    692 439
             """
    
    ... ... @@ -1043,246 +790,6 @@ class Logger:
    1043 790
             return self._con.execute(
    
    1044 791
                 sql, tuple(jids) + (start, end)).fetchone()
    
    1045 792
     
    
    1046
    -    @timeit
    
    1047
    -    def save_transport_type(self, jid, type_):
    
    1048
    -        """
    
    1049
    -        Save the type of the transport in DB
    
    1050
    -        """
    
    1051
    -        type_id = self.convert_human_transport_type_to_db_api_values(type_)
    
    1052
    -        if not type_id:
    
    1053
    -            # unknown type
    
    1054
    -            return
    
    1055
    -        result = self._con.execute(
    
    1056
    -            'SELECT type from transports_cache WHERE transport = "%s"' % jid).fetchone()
    
    1057
    -        if result:
    
    1058
    -            if result.type == type_id:
    
    1059
    -                return
    
    1060
    -            sql = 'UPDATE transports_cache SET type = %d WHERE transport = "%s"' %\
    
    1061
    -                    (type_id, jid)
    
    1062
    -            self.simple_commit(sql)
    
    1063
    -            return
    
    1064
    -        sql = 'INSERT INTO transports_cache (transport, type) VALUES (?, ?)'
    
    1065
    -        self._con.execute(sql, (jid, type_id))
    
    1066
    -        self._timeout_commit()
    
    1067
    -
    
    1068
    -    @timeit
    
    1069
    -    def get_transports_type(self):
    
    1070
    -        """
    
    1071
    -        Return all the type of the transports in DB
    
    1072
    -        """
    
    1073
    -        results = self._con.execute('SELECT * from transports_cache').fetchall()
    
    1074
    -        if not results:
    
    1075
    -            return {}
    
    1076
    -        answer = {}
    
    1077
    -        for result in results:
    
    1078
    -            answer[result.transport] = self.convert_api_values_to_human_transport_type(
    
    1079
    -                    result.type)
    
    1080
    -        return answer
    
    1081
    -
    
    1082
    -    @timeit
    
    1083
    -    def _load_caps_data(self):
    
    1084
    -        '''
    
    1085
    -        Load caps cache data
    
    1086
    -        '''
    
    1087
    -        rows = self._con.execute(
    
    1088
    -            'SELECT hash_method, hash, data as "data [disco_info]" '
    
    1089
    -            'FROM caps_cache')
    
    1090
    -
    
    1091
    -        for row in rows:
    
    1092
    -            self._entity_caps_cache[(row.hash_method, row.hash)] = row.data
    
    1093
    -
    
    1094
    -    @timeit
    
    1095
    -    def add_caps_entry(self, jid, hash_method, hash_, caps_data):
    
    1096
    -        self._entity_caps_cache[(hash_method, hash_)] = caps_data
    
    1097
    -
    
    1098
    -        self._disco_info_cache[jid] = caps_data
    
    1099
    -
    
    1100
    -        self._con.execute('''
    
    1101
    -                INSERT INTO caps_cache (hash_method, hash, data, last_seen)
    
    1102
    -                VALUES (?, ?, ?, ?)
    
    1103
    -                ''', (hash_method, hash_, caps_data, int(time.time())))
    
    1104
    -        self._timeout_commit()
    
    1105
    -
    
    1106
    -    def get_caps_entry(self, hash_method, hash_):
    
    1107
    -        return self._entity_caps_cache.get((hash_method, hash_))
    
    1108
    -
    
    1109
    -    @timeit
    
    1110
    -    def update_caps_time(self, method, hash_):
    
    1111
    -        sql = '''UPDATE caps_cache SET last_seen = ?
    
    1112
    -                 WHERE hash_method = ? and hash = ?'''
    
    1113
    -        self._con.execute(sql, (int(time.time()), method, hash_))
    
    1114
    -        self._timeout_commit()
    
    1115
    -
    
    1116
    -    @timeit
    
    1117
    -    def _clean_caps_table(self):
    
    1118
    -        """
    
    1119
    -        Remove caps which was not seen for 3 months
    
    1120
    -        """
    
    1121
    -        timestamp = int(time.time()) - 3 * 30 * 24 * 3600
    
    1122
    -        self._con.execute('DELETE FROM caps_cache WHERE last_seen < ?',
    
    1123
    -                          (timestamp,))
    
    1124
    -        self._timeout_commit()
    
    1125
    -
    
    1126
    -    @timeit
    
    1127
    -    def replace_roster(self, account_name, roster_version, roster):
    
    1128
    -        """
    
    1129
    -        Replace current roster in DB by a new one
    
    1130
    -
    
    1131
    -        accout_name is the name of the account to change.
    
    1132
    -        roster_version is the version of the new roster.
    
    1133
    -        roster is the new version.
    
    1134
    -        """
    
    1135
    -        # First we must reset roster_version value to ensure that the server
    
    1136
    -        # sends back all the roster at the next connection if the replacement
    
    1137
    -        # didn't work properly.
    
    1138
    -        app.settings.set_account_setting(account_name, 'roster_version', '')
    
    1139
    -
    
    1140
    -        account_jid = app.get_jid_from_account(account_name)
    
    1141
    -        # Execute get_jid_id() because this ensures on new accounts that the
    
    1142
    -        # jid_id will be created
    
    1143
    -        self.get_jid_id(account_jid, type_=JIDConstant.NORMAL_TYPE)
    
    1144
    -
    
    1145
    -        # Delete old roster
    
    1146
    -        self.remove_roster(account_jid)
    
    1147
    -
    
    1148
    -        # Fill roster tables with the new roster
    
    1149
    -        for jid in roster:
    
    1150
    -            self.add_or_update_contact(account_jid, jid, roster[jid]['name'],
    
    1151
    -                roster[jid]['subscription'], roster[jid]['ask'],
    
    1152
    -                roster[jid]['groups'], commit=False)
    
    1153
    -        self._timeout_commit()
    
    1154
    -
    
    1155
    -        # At this point, we are sure the replacement works properly so we can
    
    1156
    -        # set the new roster_version value.
    
    1157
    -        app.settings.set_account_setting(account_name,
    
    1158
    -                                         'roster_version',
    
    1159
    -                                         roster_version)
    
    1160
    -
    
    1161
    -    @timeit
    
    1162
    -    def del_contact(self, account_jid, jid):
    
    1163
    -        """
    
    1164
    -        Remove jid from account_jid roster
    
    1165
    -        """
    
    1166
    -        try:
    
    1167
    -            account_jid_id = self.get_jid_id(account_jid)
    
    1168
    -            jid_id = self.get_jid_id(jid)
    
    1169
    -        except exceptions.PysqliteOperationalError as e:
    
    1170
    -            raise exceptions.PysqliteOperationalError(str(e))
    
    1171
    -        self._con.execute(
    
    1172
    -                'DELETE FROM roster_group WHERE account_jid_id=? AND jid_id=?',
    
    1173
    -                (account_jid_id, jid_id))
    
    1174
    -        self._con.execute(
    
    1175
    -                'DELETE FROM roster_entry WHERE account_jid_id=? AND jid_id=?',
    
    1176
    -                (account_jid_id, jid_id))
    
    1177
    -        self._timeout_commit()
    
    1178
    -
    
    1179
    -    @timeit
    
    1180
    -    def add_or_update_contact(self, account_jid, jid, name, sub, ask, groups,
    
    1181
    -                              commit=True):
    
    1182
    -        """
    
    1183
    -        Add or update a contact from account_jid roster
    
    1184
    -        """
    
    1185
    -        if sub == 'remove':
    
    1186
    -            self.del_contact(account_jid, jid)
    
    1187
    -            return
    
    1188
    -
    
    1189
    -        try:
    
    1190
    -            account_jid_id = self.get_jid_id(account_jid)
    
    1191
    -            jid_id = self.get_jid_id(jid, type_=JIDConstant.NORMAL_TYPE)
    
    1192
    -        except exceptions.PysqliteOperationalError as error:
    
    1193
    -            raise exceptions.PysqliteOperationalError(str(error))
    
    1194
    -
    
    1195
    -        # Update groups information
    
    1196
    -        # First we delete all previous groups information
    
    1197
    -        sql = 'DELETE FROM roster_group WHERE account_jid_id=? AND jid_id=?'
    
    1198
    -        self._con.execute(sql, (account_jid_id, jid_id))
    
    1199
    -        # Then we add all new groups information
    
    1200
    -        sql = '''INSERT INTO roster_group (account_jid_id, jid_id, group_name)
    
    1201
    -                 VALUES (?, ?, ?)'''
    
    1202
    -        for group in groups:
    
    1203
    -            self._con.execute(sql, (account_jid_id, jid_id, group))
    
    1204
    -
    
    1205
    -        if name is None:
    
    1206
    -            name = ''
    
    1207
    -
    
    1208
    -        sql = '''REPLACE INTO roster_entry
    
    1209
    -                 (account_jid_id, jid_id, name, subscription, ask)
    
    1210
    -                 VALUES(?, ?, ?, ?, ?)'''
    
    1211
    -        self._con.execute(sql, (account_jid_id,
    
    1212
    -                                jid_id,
    
    1213
    -                                name,
    
    1214
    -                                self.convert_xmpp_sub(sub),
    
    1215
    -                                bool(ask)))
    
    1216
    -        if commit:
    
    1217
    -            self._timeout_commit()
    
    1218
    -
    
    1219
    -    @timeit
    
    1220
    -    def get_roster(self, account_jid):
    
    1221
    -        """
    
    1222
    -        Return the accound_jid roster in NonBlockingRoster format
    
    1223
    -        """
    
    1224
    -        data = {}
    
    1225
    -        account_jid_id = self.get_jid_id(account_jid, type_=JIDConstant.NORMAL_TYPE)
    
    1226
    -
    
    1227
    -        # First we fill data with roster_entry information
    
    1228
    -        rows = self._con.execute('''
    
    1229
    -                SELECT j.jid, re.jid_id, re.name, re.subscription, re.ask, re.avatar_sha
    
    1230
    -                FROM roster_entry re, jids j
    
    1231
    -                WHERE re.account_jid_id=? AND j.jid_id=re.jid_id''', (account_jid_id,))
    
    1232
    -        for row in rows:
    
    1233
    -            #jid, jid_id, name, subscription, ask
    
    1234
    -            jid = row.jid
    
    1235
    -            name = row.name
    
    1236
    -            data[jid] = {}
    
    1237
    -            data[jid]['avatar_sha'] = row.avatar_sha
    
    1238
    -            if name:
    
    1239
    -                data[jid]['name'] = name
    
    1240
    -            else:
    
    1241
    -                data[jid]['name'] = None
    
    1242
    -            data[jid]['subscription'] = self.convert_db_sub(row.subscription)
    
    1243
    -            data[jid]['groups'] = []
    
    1244
    -            data[jid]['resources'] = {}
    
    1245
    -            if row.ask:
    
    1246
    -                data[jid]['ask'] = 'subscribe'
    
    1247
    -            else:
    
    1248
    -                data[jid]['ask'] = None
    
    1249
    -            data[jid]['id'] = row.jid_id
    
    1250
    -
    
    1251
    -        # Then we add group for roster entries
    
    1252
    -        for jid in data:
    
    1253
    -            rows = self._con.execute('''
    
    1254
    -                    SELECT group_name FROM roster_group
    
    1255
    -                    WHERE account_jid_id=? AND jid_id=?''',
    
    1256
    -                    (account_jid_id, data[jid]['id']))
    
    1257
    -            for row in rows:
    
    1258
    -                group_name = row.group_name
    
    1259
    -                data[jid]['groups'].append(group_name)
    
    1260
    -            del data[jid]['id']
    
    1261
    -
    
    1262
    -        return data
    
    1263
    -
    
    1264
    -    @timeit
    
    1265
    -    def remove_roster(self, account_jid):
    
    1266
    -        """
    
    1267
    -        Remove the roster of an account
    
    1268
    -
    
    1269
    -        :param account_jid:     The jid of the account
    
    1270
    -        """
    
    1271
    -        try:
    
    1272
    -            jid_id = self.get_jid_id(account_jid)
    
    1273
    -        except ValueError:
    
    1274
    -            # This happens if the JID never made it to the Database
    
    1275
    -            # because the account was never connected
    
    1276
    -            return
    
    1277
    -
    
    1278
    -        sql = '''
    
    1279
    -            DELETE FROM roster_entry WHERE account_jid_id = {jid_id};
    
    1280
    -            DELETE FROM roster_group WHERE account_jid_id = {jid_id};
    
    1281
    -            '''.format(jid_id=jid_id)
    
    1282
    -
    
    1283
    -        self._con.executescript(sql)
    
    1284
    -        self._timeout_commit()
    
    1285
    -
    
    1286 793
         @timeit
    
    1287 794
         def deduplicate_muc_message(self, account, jid, resource,
    
    1288 795
                                     timestamp, message_id):
    
    ... ... @@ -1519,71 +1026,6 @@ class Logger:
    1519 1026
             self._con.execute(sql, (state, account_id, jid_id, message_id))
    
    1520 1027
             self._timeout_commit()
    
    1521 1028
     
    
    1522
    -    @timeit
    
    1523
    -    def _fill_muc_avatar_sha_cache(self):
    
    1524
    -        sql = '''SELECT jid, avatar_sha FROM muc_avatars'''
    
    1525
    -        rows = self._con.execute(sql).fetchall()
    
    1526
    -        for row in rows:
    
    1527
    -            self._muc_avatar_sha_cache[row.jid] = row.avatar_sha
    
    1528
    -        log.info('%d Avatar SHA entries loaded', len(rows))
    
    1529
    -
    
    1530
    -    @timeit
    
    1531
    -    def set_avatar_sha(self, account_jid, jid, sha=None):
    
    1532
    -        """
    
    1533
    -        Set the avatar sha of a jid on an account
    
    1534
    -
    
    1535
    -        :param account_jid: The jid of the account
    
    1536
    -
    
    1537
    -        :param jid:         The jid that belongs to the avatar
    
    1538
    -
    
    1539
    -        :param sha:         The sha of the avatar
    
    1540
    -
    
    1541
    -        """
    
    1542
    -
    
    1543
    -        account_jid_id = self.get_jid_id(account_jid)
    
    1544
    -        jid_id = self.get_jid_id(jid, type_=JIDConstant.NORMAL_TYPE)
    
    1545
    -
    
    1546
    -        sql = '''
    
    1547
    -            UPDATE roster_entry SET avatar_sha = ?
    
    1548
    -            WHERE account_jid_id = ? AND jid_id = ?
    
    1549
    -            '''
    
    1550
    -        self._con.execute(sql, (sha, account_jid_id, jid_id))
    
    1551
    -        self._timeout_commit()
    
    1552
    -
    
    1553
    -    @timeit
    
    1554
    -    def set_muc_avatar_sha(self, jid, sha=None):
    
    1555
    -        """
    
    1556
    -        Set the avatar sha of a MUC
    
    1557
    -
    
    1558
    -        :param jid:         The MUC jid that belongs to the avatar
    
    1559
    -
    
    1560
    -        :param sha:         The sha of the avatar
    
    1561
    -
    
    1562
    -        """
    
    1563
    -
    
    1564
    -        sql = '''INSERT INTO muc_avatars (jid, avatar_sha)
    
    1565
    -                 VALUES (?, ?)'''
    
    1566
    -
    
    1567
    -        try:
    
    1568
    -            self._con.execute(sql, (jid, sha))
    
    1569
    -        except sqlite.IntegrityError:
    
    1570
    -            sql = 'UPDATE muc_avatars SET avatar_sha = ? WHERE jid = ?'
    
    1571
    -            self._con.execute(sql, (sha, jid))
    
    1572
    -
    
    1573
    -        self._muc_avatar_sha_cache[jid] = sha
    
    1574
    -
    
    1575
    -        self._timeout_commit()
    
    1576
    -
    
    1577
    -    def get_muc_avatar_sha(self, jid):
    
    1578
    -        """
    
    1579
    -        Get the avatar sha of a MUC
    
    1580
    -
    
    1581
    -        :param jid:         The MUC jid that belongs to the avatar
    
    1582
    -
    
    1583
    -        """
    
    1584
    -
    
    1585
    -        return self._muc_avatar_sha_cache.get(jid)
    
    1586
    -
    
    1587 1029
         @timeit
    
    1588 1030
         def get_archive_infos(self, jid):
    
    1589 1031
             """
    
    ... ... @@ -1657,66 +1099,3 @@ class Logger:
    1657 1099
             self._con.execute(sql, (jid_id,))
    
    1658 1100
             log.info('Reset message archive info: %s', jid)
    
    1659 1101
             self._timeout_commit()
    1660
    -
    
    1661
    -    @timeit
    
    1662
    -    def _fill_disco_info_cache(self):
    
    1663
    -        sql = '''SELECT disco_info as "disco_info [disco_info]",
    
    1664
    -                 jid, last_seen FROM
    
    1665
    -                 last_seen_disco_info'''
    
    1666
    -        rows = self._con.execute(sql).fetchall()
    
    1667
    -        for row in rows:
    
    1668
    -            disco_info = row.disco_info._replace(timestamp=row.last_seen)
    
    1669
    -            self._disco_info_cache[row.jid] = disco_info
    
    1670
    -        log.info('%d DiscoInfo entries loaded', len(rows))
    
    1671
    -
    
    1672
    -    def get_last_disco_info(self, jid, max_age=0):
    
    1673
    -        """
    
    1674
    -        Get last disco info from jid
    
    1675
    -
    
    1676
    -        :param jid:         The jid
    
    1677
    -
    
    1678
    -        :param max_age:     max age in seconds of the DiscoInfo record
    
    1679
    -
    
    1680
    -        """
    
    1681
    -
    
    1682
    -        disco_info = self._disco_info_cache.get(jid)
    
    1683
    -        if disco_info is not None:
    
    1684
    -            max_timestamp = time.time() - max_age if max_age else 0
    
    1685
    -            if max_timestamp > disco_info.timestamp:
    
    1686
    -                return None
    
    1687
    -        return disco_info
    
    1688
    -
    
    1689
    -    @timeit
    
    1690
    -    def set_last_disco_info(self, jid, disco_info, cache_only=False):
    
    1691
    -        """
    
    1692
    -        Get last disco info from jid
    
    1693
    -
    
    1694
    -        :param jid:          The jid
    
    1695
    -
    
    1696
    -        :param disco_info:   A DiscoInfo object
    
    1697
    -
    
    1698
    -        """
    
    1699
    -
    
    1700
    -        log.info('Save disco info from %s', jid)
    
    1701
    -
    
    1702
    -        if cache_only:
    
    1703
    -            self._disco_info_cache[jid] = disco_info
    
    1704
    -            return
    
    1705
    -
    
    1706
    -        disco_exists = self.get_last_disco_info(jid) is not None
    
    1707
    -        if disco_exists:
    
    1708
    -            sql = '''UPDATE last_seen_disco_info SET
    
    1709
    -                     disco_info = ?, last_seen = ?
    
    1710
    -                     WHERE jid = ?'''
    
    1711
    -
    
    1712
    -            self._con.execute(sql, (disco_info, disco_info.timestamp, str(jid)))
    
    1713
    -
    
    1714
    -        else:
    
    1715
    -            sql = '''INSERT INTO last_seen_disco_info
    
    1716
    -                     (jid, disco_info, last_seen)
    
    1717
    -                     VALUES (?, ?, ?)'''
    
    1718
    -
    
    1719
    -            self._con.execute(sql, (str(jid), disco_info, disco_info.timestamp))
    
    1720
    -
    
    1721
    -        self._disco_info_cache[jid] = disco_info
    
    1722
    -        self._timeout_commit()

  • gajim/common/modules/caps.py
    ... ... @@ -101,14 +101,14 @@ class Caps(BaseModule):
    101 101
     
    
    102 102
             self._log.info('Received %s', task.entity)
    
    103 103
     
    
    104
    -        disco_info = app.logger.get_caps_entry(task.entity.method,
    
    105
    -                                               task.entity.hash)
    
    104
    +        disco_info = app.storage.cache.get_caps_entry(task.entity.method,
    
    105
    +                                                      task.entity.hash)
    
    106 106
             if disco_info is None:
    
    107 107
                 self._queue_task(task)
    
    108 108
                 return
    
    109 109
     
    
    110 110
             jid = str(properties.jid)
    
    111
    -        app.logger.set_last_disco_info(jid, disco_info, cache_only=True)
    
    111
    +        app.storage.cache.set_last_disco_info(jid, disco_info, cache_only=True)
    
    112 112
             app.nec.push_incoming_event(
    
    113 113
                 NetworkEvent('caps-update',
    
    114 114
                              account=self._account,
    
    ... ... @@ -143,7 +143,7 @@ class Caps(BaseModule):
    143 143
                                   disco_info.jid, error)
    
    144 144
                 return
    
    145 145
     
    
    146
    -        app.logger.add_caps_entry(
    
    146
    +        app.storage.cache.add_caps_entry(
    
    147 147
                 str(disco_info.jid),
    
    148 148
                 task.entity.method,
    
    149 149
                 disco_info.get_caps_hash(),
    

  • gajim/common/modules/discovery.py
    ... ... @@ -153,7 +153,6 @@ class Discovery(BaseModule):
    153 153
                 jid = str(info.jid)
    
    154 154
                 if jid not in app.transport_type:
    
    155 155
                     app.transport_type[jid] = identity.type
    
    156
    -            app.logger.save_transport_type(jid, identity.type)
    
    157 156
     
    
    158 157
                 if identity.type in self._con.available_transports:
    
    159 158
                     self._con.available_transports[identity.type].append(jid)
    
    ... ... @@ -200,7 +199,7 @@ class Discovery(BaseModule):
    200 199
         def _muc_info_received(self, result, callback=None):
    
    201 200
             self._log.info('MUC info received: %s', result.jid)
    
    202 201
             if not is_error_result(result):
    
    203
    -            app.logger.set_last_disco_info(result.jid, result)
    
    202
    +            app.storage.cache.set_last_disco_info(result.jid, result)
    
    204 203
                 self._con.get_module('VCardAvatars').muc_disco_info_update(result)
    
    205 204
                 app.nec.push_incoming_event(NetworkEvent(
    
    206 205
                     'muc-disco-update',
    

  • gajim/common/modules/mam.py
    ... ... @@ -122,7 +122,7 @@ class MAM(BaseModule):
    122 122
                 archive_jid = properties.jid.bare
    
    123 123
                 timestamp = properties.timestamp
    
    124 124
     
    
    125
    -            disco_info = app.logger.get_last_disco_info(archive_jid)
    
    125
    +            disco_info = app.storage.cache.get_last_disco_info(archive_jid)
    
    126 126
                 if disco_info is None:
    
    127 127
                     # This is the case on MUC creation
    
    128 128
                     # After MUC configuration we receive a configuration change
    

  • gajim/common/modules/message.py
    ... ... @@ -253,7 +253,7 @@ class Message(BaseModule):
    253 253
                     message_id=event.properties.id)
    
    254 254
     
    
    255 255
         def _check_for_mam_compliance(self, room_jid, stanza_id):
    
    256
    -        disco_info = app.logger.get_last_disco_info(room_jid)
    
    256
    +        disco_info = app.storage.cache.get_last_disco_info(room_jid)
    
    257 257
             if stanza_id is None and disco_info.mam_namespace == Namespace.MAM_2:
    
    258 258
                 self._log.warning('%s announces mam:2 without stanza-id', room_jid)
    
    259 259
     
    
    ... ... @@ -266,7 +266,7 @@ class Message(BaseModule):
    266 266
                 return None, None
    
    267 267
     
    
    268 268
             if properties.type.is_groupchat:
    
    269
    -            disco_info = app.logger.get_last_disco_info(
    
    269
    +            disco_info = app.storage.cache.get_last_disco_info(
    
    270 270
                     properties.jid.bare)
    
    271 271
     
    
    272 272
                 if disco_info.mam_namespace != Namespace.MAM_2:
    

  • gajim/common/modules/muc.py
    ... ... @@ -141,7 +141,8 @@ class MUC(BaseModule):
    141 141
     
    
    142 142
             self._manager.add(muc_data)
    
    143 143
     
    
    144
    -        disco_info = app.logger.get_last_disco_info(muc_data.jid, max_age=60)
    
    144
    +        disco_info = app.storage.cache.get_last_disco_info(muc_data.jid,
    
    145
    +                                                           max_age=60)
    
    145 146
             if disco_info is None:
    
    146 147
                 self._con.get_module('Discovery').disco_muc(
    
    147 148
                     muc_data.jid,
    

  • gajim/common/modules/roster.py
    ... ... @@ -45,8 +45,7 @@ class Roster(BaseModule):
    45 45
     
    
    46 46
         def load_roster(self):
    
    47 47
             self._log.info('Load from database')
    
    48
    -        account_jid = self._con.get_own_jid().bare
    
    49
    -        data = app.logger.get_roster(account_jid)
    
    48
    +        data = app.storage.cache.load_roster(self._account)
    
    50 49
             if data:
    
    51 50
                 self.set_raw(data)
    
    52 51
                 for jid, item in self._data.items():
    
    ... ... @@ -71,6 +70,9 @@ class Roster(BaseModule):
    71 70
                 roster=self._data.copy(),
    
    72 71
                 received_from_server=False))
    
    73 72
     
    
    73
    +    def _store_roster(self):
    
    74
    +        app.storage.cache.store_roster(self._account, self._data)
    
    75
    +
    
    74 76
         def request_roster(self):
    
    75 77
             version = None
    
    76 78
             features = self._con.connection.features
    
    ... ... @@ -99,7 +101,10 @@ class Roster(BaseModule):
    99 101
                     version = self._parse_roster(stanza)
    
    100 102
     
    
    101 103
                     self._log.info('New version: %s', version)
    
    102
    -                app.logger.replace_roster(self._account, version, self._data)
    
    104
    +                self._store_roster()
    
    105
    +                app.settings.set_account_setting(self._account,
    
    106
    +                                                 'roster_version',
    
    107
    +                                                 version)
    
    103 108
     
    
    104 109
                     received_from_server = True
    
    105 110
     
    
    ... ... @@ -135,10 +140,8 @@ class Roster(BaseModule):
    135 140
                     ask=attrs['ask'],
    
    136 141
                     groups=attrs['groups'],
    
    137 142
                     avatar_sha=None))
    
    138
    -            account_jid = self._con.get_own_jid().bare
    
    139
    -            app.logger.add_or_update_contact(
    
    140
    -                account_jid, item.jid, attrs['name'],
    
    141
    -                attrs['subscription'], attrs['ask'], attrs['groups'])
    
    143
    +
    
    144
    +            self._store_roster()
    
    142 145
     
    
    143 146
             self._log.info('New version: %s', version)
    
    144 147
             app.settings.set_account_setting(self._account,
    
    ... ... @@ -238,13 +241,8 @@ class Roster(BaseModule):
    238 241
                                'subscription':
    
    239 242
                                'none',
    
    240 243
                                'groups': ['Not in contact list']}
    
    241
    -        account_jid = self._con.get_own_jid().bare
    
    242
    -        app.logger.add_or_update_contact(
    
    243
    -            account_jid, jid,
    
    244
    -            self._data[jid]['name'],
    
    245
    -            self._data[jid]['subscription'],
    
    246
    -            self._data[jid]['ask'],
    
    247
    -            self._data[jid]['groups'])
    
    244
    +
    
    245
    +        self._store_roster()
    
    248 246
     
    
    249 247
         def _get_item_data(self, jid, dataname):
    
    250 248
             """
    
    ... ... @@ -369,6 +367,13 @@ class Roster(BaseModule):
    369 367
                 'avatar_sha': None
    
    370 368
             }
    
    371 369
     
    
    370
    +    def set_avatar_sha(self, jid, sha):
    
    371
    +        if jid not in self._data:
    
    372
    +            return
    
    373
    +
    
    374
    +        self._data[jid]['avatar_sha'] = sha
    
    375
    +        self._store_roster()
    
    376
    +
    
    372 377
     
    
    373 378
     def get_instance(*args, **kwargs):
    
    374 379
         return Roster(*args, **kwargs), 'Roster'

  • gajim/common/modules/user_avatar.py
    ... ... @@ -40,13 +40,12 @@ class UserAvatar(BaseModule):
    40 40
     
    
    41 41
             data = properties.pubsub_event.data
    
    42 42
             jid = str(properties.jid)
    
    43
    -        own_jid = self._con.get_own_jid().bare
    
    44 43
     
    
    45 44
             if data is None:
    
    46 45
                 # Remove avatar
    
    47 46
                 self._log.info('Remove: %s', jid)
    
    48 47
                 app.contacts.set_avatar(self._account, jid, None)
    
    49
    -            app.logger.set_avatar_sha(own_jid, jid, None)
    
    48
    +            self._con.get_module('Roster').set_avatar_sha(jid, None)
    
    50 49
                 app.interface.update_avatar(self._account, jid)
    
    51 50
             else:
    
    52 51
                 if properties.is_self_message:
    
    ... ... @@ -76,8 +75,8 @@ class UserAvatar(BaseModule):
    76 75
                                                  'avatar_sha',
    
    77 76
                                                  result.sha)
    
    78 77
             else:
    
    79
    -            own_jid = self._con.get_own_jid().bare
    
    80
    -            app.logger.set_avatar_sha(own_jid, str(result.jid), result.sha)
    
    78
    +            self._con.get_module('Roster').set_avatar_sha(str(result.jid),
    
    79
    +                                                          result.sha)
    
    81 80
     
    
    82 81
             app.contacts.set_avatar(self._account, str(result.jid), result.sha)
    
    83 82
             app.interface.update_avatar(self._account, str(result.jid))
    

  • gajim/common/modules/vcard_avatars.py
    ... ... @@ -132,7 +132,6 @@ class VCardAvatars(BaseModule):
    132 132
                                  room)
    
    133 133
     
    
    134 134
         def _process_update(self, jid, state, avatar_sha, room):
    
    135
    -        acc_jid = self._con.get_own_jid().bare
    
    136 135
             if state == AvatarState.EMPTY:
    
    137 136
                 # Empty <photo/> tag, means no avatar is advertised
    
    138 137
                 self._log.info('%s has no avatar published', jid)
    
    ... ... @@ -142,9 +141,9 @@ class VCardAvatars(BaseModule):
    142 141
                 app.contacts.set_avatar(self._account, jid, None)
    
    143 142
     
    
    144 143
                 if room:
    
    145
    -                app.logger.set_muc_avatar_sha(jid, None)
    
    144
    +                app.storage.cache.set_muc_avatar_sha(jid, None)
    
    146 145
                 else:
    
    147
    -                app.logger.set_avatar_sha(acc_jid, jid, None)
    
    146
    +                self._con.get_module('Roster').set_avatar_sha(jid, None)
    
    148 147
                 app.interface.update_avatar(self._account, jid, room_avatar=room)
    
    149 148
             else:
    
    150 149
                 self._log.info('Update: %s %s', jid, avatar_sha)
    
    ... ... @@ -158,9 +157,10 @@ class VCardAvatars(BaseModule):
    158 157
                     # Check if the avatar is already in storage
    
    159 158
                     self._log.info('Found avatar in storage')
    
    160 159
                     if room:
    
    161
    -                    app.logger.set_muc_avatar_sha(jid, avatar_sha)
    
    160
    +                    app.storage.cache.set_muc_avatar_sha(jid, avatar_sha)
    
    162 161
                     else:
    
    163
    -                    app.logger.set_avatar_sha(acc_jid, jid, avatar_sha)
    
    162
    +                    self._con.get_module('Roster').set_avatar_sha(jid,
    
    163
    +                                                                  avatar_sha)
    
    164 164
                     app.contacts.set_avatar(self._account, jid, avatar_sha)
    
    165 165
                     app.interface.update_avatar(
    
    166 166
                         self._account, jid, room_avatar=room)
    

  • gajim/common/modules/vcard_temp.py
    ... ... @@ -266,7 +266,7 @@ class VCardTemp(BaseModule):
    266 266
             app.interface.save_avatar(photo_decoded)
    
    267 267
     
    
    268 268
             self._log.info('Received: %s %s', jid, avatar_sha)
    
    269
    -        app.logger.set_muc_avatar_sha(jid, avatar_sha)
    
    269
    +        app.storage.cache.set_muc_avatar_sha(jid, avatar_sha)
    
    270 270
             app.contacts.set_avatar(self._account, jid, avatar_sha)
    
    271 271
             app.interface.update_avatar(self._account, jid, room_avatar=True)
    
    272 272
     
    
    ... ... @@ -292,8 +292,7 @@ class VCardTemp(BaseModule):
    292 292
                     app.interface.update_avatar(contact=contact)
    
    293 293
             else:
    
    294 294
                 self._log.info('Received: %s %s', jid, avatar_sha)
    
    295
    -            own_jid = self._con.get_own_jid().bare
    
    296
    -            app.logger.set_avatar_sha(own_jid, jid, avatar_sha)
    
    295
    +            self._con.get_module('Roster').set_avatar_sha(jid, avatar_sha)
    
    297 296
                 app.contacts.set_avatar(self._account, jid, avatar_sha)
    
    298 297
                 app.interface.update_avatar(self._account, jid)
    
    299 298
     
    

  • gajim/common/storage/__init__.py

  • gajim/common/storage/base.py
    1
    +# This file is part of Gajim.
    
    2
    +#
    
    3
    +# Gajim is free software; you can redistribute it and/or modify
    
    4
    +# it under the terms of the GNU General Public License as published
    
    5
    +# by the Free Software Foundation; version 3 only.
    
    6
    +#
    
    7
    +# Gajim is distributed in the hope that it will be useful,
    
    8
    +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    9
    +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    
    10
    +# GNU General Public License for more details.
    
    11
    +#
    
    12
    +# You should have received a copy of the GNU General Public License
    
    13
    +# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
    
    14
    +
    
    15
    +import sys
    
    16
    +import math
    
    17
    +import time
    
    18
    +import sqlite3
    
    19
    +
    
    20
    +from gi.repository import GLib
    
    21
    +
    
    22
    +from nbxmpp.protocol import Iq
    
    23
    +from nbxmpp.protocol import JID
    
    24
    +from nbxmpp.structs import DiscoInfo
    
    25
    +from nbxmpp.structs import CommonError
    
    26
    +from nbxmpp.modules.discovery import parse_disco_info
    
    27
    +
    
    28
    +
    
    29
    +def timeit(func):
    
    30
    +    def func_wrapper(self, *args, **kwargs):
    
    31
    +        start = time.time()
    
    32
    +        result = func(self, *args, **kwargs)
    
    33
    +        exec_time = (time.time() - start) * 1e3
    
    34
    +        level = 30 if exec_time > 50 else 10
    
    35
    +        self._log.log(level,
    
    36
    +                      'Execution time for %s: %s ms',
    
    37
    +                      func.__name__,
    
    38
    +                      math.ceil(exec_time))
    
    39
    +        return result
    
    40
    +    return func_wrapper
    
    41
    +
    
    42
    +
    
    43
    +def _convert_common_error(common_error):
    
    44
    +    return CommonError.from_string(common_error)
    
    45
    +
    
    46
    +def _adapt_common_error(common_error):
    
    47
    +    return common_error.serialize()
    
    48
    +
    
    49
    +sqlite3.register_converter('common_error', _convert_common_error)
    
    50
    +sqlite3.register_adapter(CommonError, _adapt_common_error)
    
    51
    +
    
    52
    +def _convert_marker(marker):
    
    53
    +    return 'received' if marker == 0 else 'displayed'
    
    54
    +
    
    55
    +sqlite3.register_converter('marker', _convert_marker)
    
    56
    +
    
    57
    +def _jid_adapter(jid):
    
    58
    +    return str(jid)
    
    59
    +
    
    60
    +def _jid_converter(jid):
    
    61
    +    return JID.from_string(jid.decode())
    
    62
    +
    
    63
    +sqlite3.register_converter('jid', _jid_converter)
    
    64
    +sqlite3.register_adapter(JID, _jid_adapter)
    
    65
    +
    
    66
    +def _convert_disco_info(disco_info):
    
    67
    +    return parse_disco_info(Iq(node=disco_info))
    
    68
    +
    
    69
    +def _adapt_disco_info(disco_info):
    
    70
    +    return str(disco_info.stanza)
    
    71
    +
    
    72
    +sqlite3.register_converter('disco_info', _convert_disco_info)
    
    73
    +sqlite3.register_adapter(DiscoInfo, _adapt_disco_info)
    
    74
    +
    
    75
    +
    
    76
    +class SqliteStorage:
    
    77
    +    '''
    
    78
    +    Base Storage Class
    
    79
    +    '''
    
    80
    +
    
    81
    +    def __init__(self,
    
    82
    +                 log,
    
    83
    +                 path,
    
    84
    +                 create_statement,
    
    85
    +                 commit_delay=500):
    
    86
    +
    
    87
    +        self._log = log
    
    88
    +        self._path = path
    
    89
    +        self._create_statement = create_statement
    
    90
    +        self._commit_delay = commit_delay
    
    91
    +        self._con = None
    
    92
    +        self._commit_source_id = None
    
    93
    +
    
    94
    +    def init(self, **kwargs):
    
    95
    +        if self._path.exists():
    
    96
    +            if not self._path.is_file():
    
    97
    +                sys.exit('%s must be a file', self._path)
    
    98
    +            self._con = self._connect(**kwargs)
    
    99
    +
    
    100
    +        else:
    
    101
    +            self._con = self._create_storage(**kwargs)
    
    102
    +
    
    103
    +        self._migrate_storage()
    
    104
    +
    
    105
    +    def _set_journal_mode(self, mode):
    
    106
    +        self._con.execute(f'PRAGMA journal_mode={mode}')
    
    107
    +
    
    108
    +    def _set_synchronous(self, mode):
    
    109
    +        self._con.execute(f'PRAGMA synchronous={mode}')
    
    110
    +
    
    111
    +    @property
    
    112
    +    def user_version(self) -> int:
    
    113
    +        return self._con.execute('PRAGMA user_version').fetchone()[0]
    
    114
    +
    
    115
    +    def _connect(self, **kwargs):
    
    116
    +        return sqlite3.connect(self._path, **kwargs)
    
    117
    +
    
    118
    +    def _create_storage(self, **kwargs):
    
    119
    +        self._log.info('Creating %s', self._path)
    
    120
    +        con = self._connect(**kwargs)
    
    121
    +        self._path.chmod(0o600)
    
    122
    +
    
    123
    +        try:
    
    124
    +            con.executescript(self._create_statement)
    
    125
    +        except Exception:
    
    126
    +            self._log.exception('Error')
    
    127
    +            con.close()
    
    128
    +            self._path.unlink()
    
    129
    +            sys.exit('Failed creating storage')
    
    130
    +
    
    131
    +        con.commit()
    
    132
    +        return con
    
    133
    +
    
    134
    +    def _reinit_storage(self):
    
    135
    +        if self._con is not None:
    
    136
    +            self._con.close()
    
    137
    +        self._path.unlink()
    
    138
    +        self.init()
    
    139
    +
    
    140
    +    def _migrate_storage(self):
    
    141
    +        try:
    
    142
    +            self._migrate()
    
    143
    +        except Exception:
    
    144
    +            self._con.close()
    
    145
    +            self._log.exception('Error')
    
    146
    +            sys.exit()
    
    147
    +
    
    148
    +    def _migrate(self):
    
    149
    +        raise NotImplementedError
    
    150
    +
    
    151
    +    def _execute_multiple(self, statements):
    
    152
    +        """
    
    153
    +        Execute multiple statements with the option to fail on duplicates
    
    154
    +        but still continue
    
    155
    +        """
    
    156
    +        for sql in statements:
    
    157
    +            try:
    
    158
    +                self._con.execute(sql)
    
    159
    +                self._con.commit()
    
    160
    +            except sqlite3.OperationalError as error:
    
    161
    +                if str(error).startswith('duplicate column name:'):
    
    162
    +                    self._log.info(error)
    
    163
    +                else:
    
    164
    +                    self._con.close()
    
    165
    +                    self._log.exception('Error')
    
    166
    +                    sys.exit()
    
    167
    +
    
    168
    +    @timeit
    
    169
    +    def _commit(self):
    
    170
    +        self._commit_source_id = None
    
    171
    +        self._con.commit()
    
    172
    +        return False
    
    173
    +
    
    174
    +    def _delayed_commit(self):
    
    175
    +        if self._commit_source_id is not None:
    
    176
    +            return
    
    177
    +
    
    178
    +        self._commit_source_id = GLib.timeout_add(self._commit_delay,
    
    179
    +                                                  self._commit)

  • gajim/common/storage/cache.py
    1
    +# This file is part of Gajim.
    
    2
    +#
    
    3
    +# Gajim is free software; you can redistribute it and/or modify
    
    4
    +# it under the terms of the GNU General Public License as published
    
    5
    +# by the Free Software Foundation; version 3 only.
    
    6
    +#
    
    7
    +# Gajim is distributed in the hope that it will be useful,
    
    8
    +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    9
    +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    
    10
    +# GNU General Public License for more details.
    
    11
    +#
    
    12
    +# You should have received a copy of the GNU General Public License
    
    13
    +# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
    
    14
    +
    
    15
    +import json
    
    16
    +import time
    
    17
    +import sqlite3
    
    18
    +import logging
    
    19
    +from pathlib import Path
    
    20
    +from collections import namedtuple
    
    21
    +
    
    22
    +from gajim.common import configpaths
    
    23
    +from gajim.common.storage.base import SqliteStorage
    
    24
    +from gajim.common.storage.base import timeit
    
    25
    +
    
    26
    +
    
    27
    +CURRENT_USER_VERSION = 6
    
    28
    +
    
    29
    +CACHE_SQL_STATEMENT = '''
    
    30
    +    CREATE TABLE caps_cache (
    
    31
    +            hash_method TEXT,
    
    32
    +            hash TEXT,
    
    33
    +            data TEXT,
    
    34
    +            last_seen INTEGER
    
    35
    +    );
    
    36
    +    CREATE TABLE last_seen_disco_info(
    
    37
    +            jid TEXT PRIMARY KEY UNIQUE,
    
    38
    +            disco_info TEXT,
    
    39
    +            last_seen INTEGER
    
    40
    +    );
    
    41
    +    CREATE TABLE roster(
    
    42
    +            account TEXT PRIMARY KEY UNIQUE,
    
    43
    +            roster TEXT
    
    44
    +    );
    
    45
    +    CREATE TABLE muc_avatars(
    
    46
    +            jid TEXT PRIMARY KEY UNIQUE,
    
    47
    +            avatar_sha TEXT
    
    48
    +    );
    
    49
    +    PRAGMA user_version=%s;
    
    50
    +    ''' % CURRENT_USER_VERSION
    
    51
    +
    
    52
    +log = logging.getLogger('gajim.c.storage.cache')
    
    53
    +
    
    54
    +
    
    55
    +class CacheStorage(SqliteStorage):
    
    56
    +    def __init__(self):
    
    57
    +        SqliteStorage.__init__(self,
    
    58
    +                               log,
    
    59
    +                               Path(configpaths.get('CACHE_DB')),
    
    60
    +                               CACHE_SQL_STATEMENT)
    
    61
    +
    
    62
    +        self._entity_caps_cache = {}
    
    63
    +        self._disco_info_cache = {}
    
    64
    +        self._muc_avatar_sha_cache = {}
    
    65
    +
    
    66
    +    def init(self, **kwargs):
    
    67
    +        SqliteStorage.init(self,
    
    68
    +                           detect_types=sqlite3.PARSE_COLNAMES)
    
    69
    +        self._set_journal_mode('WAL')
    
    70
    +        self._con.row_factory = self._namedtuple_factory
    
    71
    +
    
    72
    +        self._fill_disco_info_cache()
    
    73
    +        self._fill_muc_avatar_sha_cache()
    
    74
    +        self._clean_caps_table()
    
    75
    +        self._load_caps_data()
    
    76
    +
    
    77
    +    @staticmethod
    
    78
    +    def _namedtuple_factory(cursor, row):
    
    79
    +        fields = [col[0] for col in cursor.description]
    
    80
    +        Row = namedtuple("Row", fields)
    
    81
    +        return Row(*row)
    
    82
    +
    
    83
    +    def _migrate(self):
    
    84
    +        user_version = self.user_version
    
    85
    +        if user_version > CURRENT_USER_VERSION:
    
    86
    +            # Gajim was downgraded, reinit the storage
    
    87
    +            self._reinit_storage()
    
    88
    +            return
    
    89
    +
    
    90
    +        if user_version < 6:
    
    91
    +            self._reinit_storage()
    
    92
    +
    
    93
    +    @timeit
    
    94
    +    def _load_caps_data(self):
    
    95
    +        rows = self._con.execute(
    
    96
    +            'SELECT hash_method, hash, data as "data [disco_info]" '
    
    97
    +            'FROM caps_cache')
    
    98
    +
    
    99
    +        for row in rows:
    
    100
    +            self._entity_caps_cache[(row.hash_method, row.hash)] = row.data
    
    101
    +
    
    102
    +    @timeit
    
    103
    +    def add_caps_entry(self, jid, hash_method, hash_, caps_data):
    
    104
    +        self._entity_caps_cache[(hash_method, hash_)] = caps_data
    
    105
    +
    
    106
    +        self._disco_info_cache[jid] = caps_data
    
    107
    +
    
    108
    +        self._con.execute('''
    
    109
    +            INSERT INTO caps_cache (hash_method, hash, data, last_seen)
    
    110
    +            VALUES (?, ?, ?, ?)
    
    111
    +            ''', (hash_method, hash_, caps_data, int(time.time())))
    
    112
    +        self._delayed_commit()
    
    113
    +
    
    114
    +    def get_caps_entry(self, hash_method, hash_):
    
    115
    +        return self._entity_caps_cache.get((hash_method, hash_))
    
    116
    +
    
    117
    +    @timeit
    
    118
    +    def update_caps_time(self, method, hash_):
    
    119
    +        sql = '''UPDATE caps_cache SET last_seen = ?
    
    120
    +                 WHERE hash_method = ? and hash = ?'''
    
    121
    +        self._con.execute(sql, (int(time.time()), method, hash_))
    
    122
    +        self._delayed_commit()
    
    123
    +
    
    124
    +    @timeit
    
    125
    +    def _clean_caps_table(self):
    
    126
    +        """
    
    127
    +        Remove caps which was not seen for 3 months
    
    128
    +        """
    
    129
    +        timestamp = int(time.time()) - 3 * 30 * 24 * 3600
    
    130
    +        self._con.execute('DELETE FROM caps_cache WHERE last_seen < ?',
    
    131
    +                          (timestamp,))
    
    132
    +        self._delayed_commit()
    
    133
    +
    
    134
    +    @timeit
    
    135
    +    def _fill_disco_info_cache(self):
    
    136
    +        sql = '''SELECT disco_info as "disco_info [disco_info]",
    
    137
    +                 jid, last_seen FROM
    
    138
    +                 last_seen_disco_info'''
    
    139
    +        rows = self._con.execute(sql).fetchall()
    
    140
    +        for row in rows:
    
    141
    +            disco_info = row.disco_info._replace(timestamp=row.last_seen)
    
    142
    +            self._disco_info_cache[row.jid] = disco_info
    
    143
    +        log.info('%d DiscoInfo entries loaded', len(rows))
    
    144
    +
    
    145
    +    def get_last_disco_info(self, jid, max_age=0):
    
    146
    +        """
    
    147
    +        Get last disco info from jid
    
    148
    +
    
    149
    +        :param jid:         The jid
    
    150
    +
    
    151
    +        :param max_age:     max age in seconds of the DiscoInfo record
    
    152
    +
    
    153
    +        """
    
    154
    +
    
    155
    +        disco_info = self._disco_info_cache.get(jid)
    
    156
    +        if disco_info is not None:
    
    157
    +            max_timestamp = time.time() - max_age if max_age else 0
    
    158
    +            if max_timestamp > disco_info.timestamp:
    
    159
    +                return None
    
    160
    +        return disco_info
    
    161
    +
    
    162
    +    @timeit
    
    163
    +    def set_last_disco_info(self, jid, disco_info, cache_only=False):
    
    164
    +        """
    
    165
    +        Get last disco info from jid
    
    166
    +
    
    167
    +        :param jid:          The jid
    
    168
    +
    
    169
    +        :param disco_info:   A DiscoInfo object
    
    170
    +
    
    171
    +        """
    
    172
    +
    
    173
    +        log.info('Save disco info from %s', jid)
    
    174
    +
    
    175
    +        if cache_only:
    
    176
    +            self._disco_info_cache[jid] = disco_info
    
    177
    +            return
    
    178
    +
    
    179
    +        disco_exists = self.get_last_disco_info(jid) is not None
    
    180
    +        if disco_exists:
    
    181
    +            sql = '''UPDATE last_seen_disco_info SET
    
    182
    +                     disco_info = ?, last_seen = ?
    
    183
    +                     WHERE jid = ?'''
    
    184
    +
    
    185
    +            self._con.execute(sql, (disco_info, disco_info.timestamp, str(jid)))
    
    186
    +
    
    187
    +        else:
    
    188
    +            sql = '''INSERT INTO last_seen_disco_info
    
    189
    +                     (jid, disco_info, last_seen)
    
    190
    +                     VALUES (?, ?, ?)'''
    
    191
    +
    
    192
    +            self._con.execute(sql, (str(jid), disco_info, disco_info.timestamp))
    
    193
    +
    
    194
    +        self._disco_info_cache[jid] = disco_info
    
    195
    +        self._delayed_commit()
    
    196
    +
    
    197
    +    @timeit
    
    198
    +    def store_roster(self, account, roster):
    
    199
    +        serialized = json.dumps(roster)
    
    200
    +
    
    201
    +        insert_sql = 'INSERT INTO roster(account, roster) VALUES(?, ?)'
    
    202
    +        update_sql = 'UPDATE roster SET roster = ? WHERE account = ?'
    
    203
    +
    
    204
    +        try:
    
    205
    +            self._con.execute(insert_sql, (account, serialized))
    
    206
    +        except sqlite3.IntegrityError:
    
    207
    +            self._con.execute(update_sql, (serialized, account))
    
    208
    +
    
    209
    +        self._delayed_commit()
    
    210
    +
    
    211
    +    @timeit
    
    212
    +    def load_roster(self, account):
    
    213
    +        select_sql = 'SELECT roster FROM roster WHERE account = ?'
    
    214
    +        result = self._con.execute(select_sql, (account,)).fetchone()
    
    215
    +        if result is None:
    
    216
    +            return None
    
    217
    +        return json.loads(result.roster)
    
    218
    +
    
    219
    +    @timeit
    
    220
    +    def remove_roster(self, account):
    
    221
    +        delete_sql = 'DELETE FROM roster WHERE account = ?'
    
    222
    +        self._con.execute(delete_sql, (account,))
    
    223
    +        self._commit()
    
    224
    +
    
    225
    +    @timeit
    
    226
    +    def _fill_muc_avatar_sha_cache(self):
    
    227
    +        sql = '''SELECT jid, avatar_sha FROM muc_avatars'''
    
    228
    +        rows = self._con.execute(sql).fetchall()
    
    229
    +        for row in rows:
    
    230
    +            self._muc_avatar_sha_cache[row.jid] = row.avatar_sha
    
    231
    +        log.info('%d Avatar SHA entries loaded', len(rows))
    
    232
    +
    
    233
    +    @timeit
    
    234
    +    def set_muc_avatar_sha(self, jid, sha=None):
    
    235
    +        """
    
    236
    +        Set the avatar sha of a MUC
    
    237
    +
    
    238
    +        :param jid:         The MUC jid that belongs to the avatar
    
    239
    +
    
    240
    +        :param sha:         The sha of the avatar
    
    241
    +
    
    242
    +        """
    
    243
    +
    
    244
    +        sql = '''INSERT INTO muc_avatars (jid, avatar_sha)
    
    245
    +                 VALUES (?, ?)'''
    
    246
    +
    
    247
    +        try:
    
    248
    +            self._con.execute(sql, (jid, sha))
    
    249
    +        except sqlite3.IntegrityError:
    
    250
    +            sql = 'UPDATE muc_avatars SET avatar_sha = ? WHERE jid = ?'
    
    251
    +            self._con.execute(sql, (sha, jid))
    
    252
    +
    
    253
    +        self._muc_avatar_sha_cache[jid] = sha
    
    254
    +
    
    255
    +        self._delayed_commit()
    
    256
    +
    
    257
    +    def get_muc_avatar_sha(self, jid):
    
    258
    +        """
    
    259
    +        Get the avatar sha of a MUC
    
    260
    +
    
    261
    +        :param jid:         The MUC jid that belongs to the avatar
    
    262
    +
    
    263
    +        """
    
    264
    +
    
    265
    +        return self._muc_avatar_sha_cache.get(jid)

  • gajim/groupchat_control.py
    ... ... @@ -266,7 +266,7 @@ class GroupchatControl(ChatControlBase):
    266 266
     
    
    267 267
         @property
    
    268 268
         def disco_info(self):
    
    269
    -        return app.logger.get_last_disco_info(self.contact.jid)
    
    269
    +        return app.storage.cache.get_last_disco_info(self.contact.jid)
    
    270 270
     
    
    271 271
         def add_actions(self):
    
    272 272
             super().add_actions()
    

  • gajim/gtk/avatar.py
    ... ... @@ -239,7 +239,7 @@ class AvatarStorage(metaclass=Singleton):
    239 239
             if surface is not None:
    
    240 240
                 return surface
    
    241 241
     
    
    242
    -        avatar_sha = app.logger.get_muc_avatar_sha(jid)
    
    242
    +        avatar_sha = app.storage.cache.get_muc_avatar_sha(jid)
    
    243 243
             if avatar_sha is not None:
    
    244 244
                 surface = self.surface_from_filename(avatar_sha, size, scale)
    
    245 245
                 if surface is None:
    

  • gajim/gtk/groupchat_config.py
    ... ... @@ -52,7 +52,7 @@ class GroupchatConfig(Gtk.ApplicationWindow):
    52 52
                 self._ui.add_button.set_sensitive(True)
    
    53 53
                 self._ui.add_button.set_tooltip_text('')
    
    54 54
     
    
    55
    -        disco_info = app.logger.get_last_disco_info(self.jid)
    
    55
    +        disco_info = app.storage.cache.get_last_disco_info(self.jid)
    
    56 56
             visible = disco_info.supports(Namespace.REGISTER)
    
    57 57
             self._ui.reserved_name_column.set_visible(visible)
    
    58 58
             self._ui.info_button.set_sensitive(False)
    

  • gajim/gtk/tooltips.py
    ... ... @@ -357,7 +357,7 @@ class RosterTooltip(StatusTable):
    357 357
     
    
    358 358
             else:  # only one resource
    
    359 359
                 if contact.is_groupchat:
    
    360
    -                disco_info = app.logger.get_last_disco_info(contact.jid)
    
    360
    +                disco_info = app.storage.cache.get_last_disco_info(contact.jid)
    
    361 361
                     if disco_info is not None:
    
    362 362
                         description = disco_info.muc_description
    
    363 363
                         if description:
    

  • gajim/gui_interface.py
    ... ... @@ -1321,7 +1321,7 @@ class Interface:
    1321 1321
     
    
    1322 1322
         def create_groupchat_control(self, account, room_jid, muc_data,
    
    1323 1323
                                      minimize=False):
    
    1324
    -        avatar_sha = app.logger.get_muc_avatar_sha(room_jid)
    
    1324
    +        avatar_sha = app.storage.cache.get_muc_avatar_sha(room_jid)
    
    1325 1325
             contact = app.contacts.create_contact(jid=room_jid,
    
    1326 1326
                                                   account=account,
    
    1327 1327
                                                   groups=[_('Group chats')],
    
    ... ... @@ -1653,7 +1653,7 @@ class Interface:
    1653 1653
             if app.settings.get_account_setting(account, 'active'):
    
    1654 1654
                 self.disable_account(account)
    
    1655 1655
     
    
    1656
    -        app.logger.remove_roster(app.get_jid_from_account(account))
    
    1656
    +        app.storage.cache.remove_roster(account)
    
    1657 1657
             # Delete password must be before del_per() because it calls set_per()
    
    1658 1658
             # which would recreate the account with defaults values if not found
    
    1659 1659
             passwords.delete_password(account)
    
    ... ... @@ -2103,9 +2103,6 @@ class Interface:
    2103 2103
     
    
    2104 2104
             self.make_regexps()
    
    2105 2105
     
    
    2106
    -        # get transports type from DB
    
    2107
    -        app.transport_type = app.logger.get_transports_type()
    
    2108
    -
    
    2109 2106
             self.last_ftwindow_update = 0
    
    2110 2107
     
    
    2111 2108
             self._network_monitor = Gio.NetworkMonitor.get_default()
    

  • gajim/roster_window.py
    ... ... @@ -1155,7 +1155,7 @@ class RosterWindow:
    1155 1155
                 status_span = '\n<span size="small" style="italic" ' \
    
    1156 1156
                               'alpha="70%">{}</span>'
    
    1157 1157
                 if contact.is_groupchat:
    
    1158
    -                disco_info = app.logger.get_last_disco_info(contact.jid)
    
    1158
    +                disco_info = app.storage.cache.get_last_disco_info(contact.jid)
    
    1159 1159
                     if disco_info is not None:
    
    1160 1160
                         description = disco_info.muc_description
    
    1161 1161
                         if description: