diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 429abab3..42bd73d6 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -50,15 +50,15 @@ from pyrogram.api.errors import ( from pyrogram.client.handlers import DisconnectHandler from pyrogram.client.handlers.handler import Handler from pyrogram.client.methods.password.utils import compute_check -from pyrogram.client.session_storage import BaseSessionConfig from pyrogram.crypto import AES from pyrogram.session import Auth, Session from .dispatcher import Dispatcher from .ext import utils, Syncer, BaseClient from .methods import Methods -from .session_storage import SessionDoesNotExist -from .session_storage.json_session_storage import JsonSessionStorage -from .session_storage.string_session_storage import StringSessionStorage +from .session_storage import ( + SessionDoesNotExist, SessionStorage, MemorySessionStorage, JsonSessionStorage, + StringSessionStorage +) log = logging.getLogger(__name__) @@ -183,7 +183,7 @@ class Client(Methods, BaseClient): """ def __init__(self, - session_name: Union[str, BaseSessionConfig], + session_name: Union[str, SessionStorage], api_id: Union[int, str] = None, api_hash: str = None, app_version: str = None, @@ -209,14 +209,16 @@ class Client(Methods, BaseClient): takeout: bool = None): if isinstance(session_name, str): - if session_name.startswith(':'): + if session_name == ':memory:': + session_storage = MemorySessionStorage(self) + elif session_name.startswith(':'): session_storage = StringSessionStorage(self, session_name) else: session_storage = JsonSessionStorage(self, session_name) - elif isinstance(session_name, BaseSessionConfig): - session_storage = session_name.session_storage_cls(self, session_name) + elif isinstance(session_name, SessionStorage): + session_storage = session_name else: - raise RuntimeError('Wrong session_name passed, expected str or BaseSessionConfig subclass') + raise RuntimeError('Wrong session_name passed, expected str or SessionConfig subclass') super().__init__(session_storage) @@ -230,7 +232,7 @@ class Client(Methods, BaseClient): self.ipv6 = ipv6 # TODO: Make code consistent, use underscore for private/protected fields self._proxy = proxy - self.test_mode = test_mode + self.session_storage.test_mode = test_mode self.phone_number = phone_number self.phone_code = phone_code self.password = password @@ -282,10 +284,10 @@ class Client(Methods, BaseClient): raise ConnectionError("Client has already been started") if isinstance(self.session_storage, JsonSessionStorage): - if self.BOT_TOKEN_RE.match(self.session_storage.session_data): - self.is_bot = True - self.bot_token = self.session_storage.session_data - self.session_storage.session_data = self.session_storage.session_data.split(":")[0] + if self.BOT_TOKEN_RE.match(self.session_storage._session_name): + self.session_storage.is_bot = True + self.bot_token = self.session_storage._session_name + self.session_storage._session_name = self.session_storage._session_name.split(":")[0] warnings.warn('\nYou are using a bot token as session name.\n' 'It will be deprecated in next update, please use session file name to load ' 'existing sessions and bot_token argument to create new sessions.', @@ -297,33 +299,33 @@ class Client(Methods, BaseClient): self.session = Session( self, - self.dc_id, - self.auth_key + self.session_storage.dc_id, + self.session_storage.auth_key ) self.session.start() self.is_started = True try: - if self.user_id is None: + if self.session_storage.user_id is None: if self.bot_token is None: self.authorize_user() else: - self.is_bot = True + self.session_storage.is_bot = True self.authorize_bot() self.save_session() - if not self.is_bot: + if not self.session_storage.is_bot: if self.takeout: self.takeout_id = self.send(functions.account.InitTakeoutSession()).id log.warning("Takeout session {} initiated".format(self.takeout_id)) now = time.time() - if abs(now - self.date) > Client.OFFLINE_SLEEP: - self.peers_by_username.clear() - self.peers_by_phone.clear() + if abs(now - self.session_storage.date) > Client.OFFLINE_SLEEP: + self.session_storage.peers_by_username.clear() + self.session_storage.peers_by_phone.clear() self.get_initial_dialogs() self.get_contacts() @@ -512,19 +514,20 @@ class Client(Methods, BaseClient): except UserMigrate as e: self.session.stop() - self.dc_id = e.x - self.auth_key = Auth(self.dc_id, self.test_mode, self.ipv6, self._proxy).create() + self.session_storage.dc_id = e.x + self.session_storage.auth_key = Auth(self.session_storage.dc_id, self.session_storage.test_mode, + self.ipv6, self._proxy).create() self.session = Session( self, - self.dc_id, - self.auth_key + self.session_storage.dc_id, + self.session_storage.auth_key ) self.session.start() self.authorize_bot() else: - self.user_id = r.user.id + self.session_storage.user_id = r.user.id print("Logged in successfully as @{}".format(r.user.username)) @@ -564,19 +567,19 @@ class Client(Methods, BaseClient): except (PhoneMigrate, NetworkMigrate) as e: self.session.stop() - self.dc_id = e.x + self.session_storage.dc_id = e.x - self.auth_key = Auth( - self.dc_id, - self.test_mode, + self.session_storage.auth_key = Auth( + self.session_storage.dc_id, + self.session_storage.test_mode, self.ipv6, self._proxy ).create() self.session = Session( self, - self.dc_id, - self.auth_key + self.session_storage.dc_id, + self.session_storage.auth_key ) self.session.start() @@ -752,7 +755,7 @@ class Client(Methods, BaseClient): assert self.send(functions.help.AcceptTermsOfService(terms_of_service.id)) self.password = None - self.user_id = r.user.id + self.session_storage.user_id = r.user.id print("Logged in successfully as {}".format(r.user.first_name)) @@ -776,13 +779,13 @@ class Client(Methods, BaseClient): access_hash=access_hash ) - self.peers_by_id[user_id] = input_peer + self.session_storage.peers_by_id[user_id] = input_peer if username is not None: - self.peers_by_username[username.lower()] = input_peer + self.session_storage.peers_by_username[username.lower()] = input_peer if phone is not None: - self.peers_by_phone[phone] = input_peer + self.session_storage.peers_by_phone[phone] = input_peer if isinstance(entity, (types.Chat, types.ChatForbidden)): chat_id = entity.id @@ -792,7 +795,7 @@ class Client(Methods, BaseClient): chat_id=chat_id ) - self.peers_by_id[peer_id] = input_peer + self.session_storage.peers_by_id[peer_id] = input_peer if isinstance(entity, (types.Channel, types.ChannelForbidden)): channel_id = entity.id @@ -810,10 +813,10 @@ class Client(Methods, BaseClient): access_hash=access_hash ) - self.peers_by_id[peer_id] = input_peer + self.session_storage.peers_by_id[peer_id] = input_peer if username is not None: - self.peers_by_username[username.lower()] = input_peer + self.session_storage.peers_by_username[username.lower()] = input_peer def download_worker(self): name = threading.current_thread().name @@ -1127,10 +1130,11 @@ class Client(Methods, BaseClient): def load_session(self): try: - self.session_storage.load_session() + self.session_storage.load() except SessionDoesNotExist: log.info('Could not load session "{}", initiate new one'.format(self.session_name)) - self.auth_key = Auth(self.dc_id, self.test_mode, self.ipv6, self._proxy).create() + self.session_storage.auth_key = Auth(self.session_storage.dc_id, self.session_storage.test_mode, + self.ipv6, self._proxy).create() def load_plugins(self): if self.plugins.get("enabled", False): @@ -1237,7 +1241,7 @@ class Client(Methods, BaseClient): log.warning('No plugin loaded from "{}"'.format(root)) def save_session(self): - self.session_storage.save_session() + self.session_storage.save() def get_initial_dialogs_chunk(self, offset_date: int = 0): @@ -1257,7 +1261,7 @@ class Client(Methods, BaseClient): log.warning("get_dialogs flood: waiting {} seconds".format(e.x)) time.sleep(e.x) else: - log.info("Total peers: {}".format(len(self.peers_by_id))) + log.info("Total peers: {}".format(len(self.session_storage.peers_by_id))) return r def get_initial_dialogs(self): @@ -1293,7 +1297,7 @@ class Client(Methods, BaseClient): ``KeyError`` in case the peer doesn't exist in the internal database. """ try: - return self.peers_by_id[peer_id] + return self.session_storage.peers_by_id[peer_id] except KeyError: if type(peer_id) is str: if peer_id in ("self", "me"): @@ -1304,17 +1308,17 @@ class Client(Methods, BaseClient): try: int(peer_id) except ValueError: - if peer_id not in self.peers_by_username: + if peer_id not in self.session_storage.peers_by_username: self.send( functions.contacts.ResolveUsername( username=peer_id ) ) - return self.peers_by_username[peer_id] + return self.session_storage.peers_by_username[peer_id] else: try: - return self.peers_by_phone[peer_id] + return self.session_storage.peers_by_phone[peer_id] except KeyError: raise PeerIdInvalid @@ -1341,7 +1345,7 @@ class Client(Methods, BaseClient): ) try: - return self.peers_by_id[peer_id] + return self.session_storage.peers_by_id[peer_id] except KeyError: raise PeerIdInvalid @@ -1411,7 +1415,7 @@ class Client(Methods, BaseClient): file_id = file_id or self.rnd_id() md5_sum = md5() if not is_big and not is_missing_part else None - session = Session(self, self.dc_id, self.auth_key, is_media=True) + session = Session(self, self.session_storage.dc_id, self.session_storage.auth_key, is_media=True) session.start() try: @@ -1492,7 +1496,7 @@ class Client(Methods, BaseClient): session = self.media_sessions.get(dc_id, None) if session is None: - if dc_id != self.dc_id: + if dc_id != self.session_storage.dc_id: exported_auth = self.send( functions.auth.ExportAuthorization( dc_id=dc_id @@ -1502,7 +1506,7 @@ class Client(Methods, BaseClient): session = Session( self, dc_id, - Auth(dc_id, self.test_mode, self.ipv6, self._proxy).create(), + Auth(dc_id, self.session_storage.test_mode, self.ipv6, self._proxy).create(), is_media=True ) @@ -1520,7 +1524,7 @@ class Client(Methods, BaseClient): session = Session( self, dc_id, - self.auth_key, + self.session_storage.auth_key, is_media=True ) @@ -1588,7 +1592,7 @@ class Client(Methods, BaseClient): cdn_session = Session( self, r.dc_id, - Auth(r.dc_id, self.test_mode, self.ipv6, self._proxy).create(), + Auth(r.dc_id, self.session_storage.test_mode, self.ipv6, self._proxy).create(), is_media=True, is_cdn=True ) diff --git a/pyrogram/client/ext/base_client.py b/pyrogram/client/ext/base_client.py index 3f40865f..732a600f 100644 --- a/pyrogram/client/ext/base_client.py +++ b/pyrogram/client/ext/base_client.py @@ -24,10 +24,10 @@ from threading import Lock from pyrogram import __version__ from ..style import Markdown, HTML from ...session.internals import MsgId -from ..session_storage import SessionStorageMixin, BaseSessionStorage +from ..session_storage import SessionStorage -class BaseClient(SessionStorageMixin): +class BaseClient: class StopTransmission(StopIteration): pass @@ -68,14 +68,14 @@ class BaseClient(SessionStorageMixin): 13: "video_note" } - def __init__(self, session_storage: BaseSessionStorage): + def __init__(self, session_storage: SessionStorage): self.session_storage = session_storage self.rnd_id = MsgId self.channels_pts = {} - self.markdown = Markdown(self.peers_by_id) - self.html = HTML(self.peers_by_id) + self.markdown = Markdown(self.session_storage.peers_by_id) + self.html = HTML(self.session_storage.peers_by_id) self.session = None self.media_sessions = {} diff --git a/pyrogram/client/ext/syncer.py b/pyrogram/client/ext/syncer.py index 70955624..e13212be 100644 --- a/pyrogram/client/ext/syncer.py +++ b/pyrogram/client/ext/syncer.py @@ -81,9 +81,9 @@ class Syncer: @classmethod def sync(cls, client): - client.date = int(time.time()) + client.session_storage.date = int(time.time()) try: - client.session_storage.save_session(sync=True) + client.session_storage.save(sync=True) except Exception as e: log.critical(e, exc_info=True) else: diff --git a/pyrogram/client/methods/contacts/get_contacts.py b/pyrogram/client/methods/contacts/get_contacts.py index 29b7e176..35b24592 100644 --- a/pyrogram/client/methods/contacts/get_contacts.py +++ b/pyrogram/client/methods/contacts/get_contacts.py @@ -44,5 +44,5 @@ class GetContacts(BaseClient): log.warning("get_contacts flood: waiting {} seconds".format(e.x)) time.sleep(e.x) else: - log.info("Total contacts: {}".format(len(self.peers_by_phone))) + log.info("Total contacts: {}".format(len(self.session_storage.peers_by_phone))) return [pyrogram.User._parse(self, user) for user in contacts.users] diff --git a/pyrogram/client/session_storage/__init__.py b/pyrogram/client/session_storage/__init__.py index 611ec9b7..ad2d8900 100644 --- a/pyrogram/client/session_storage/__init__.py +++ b/pyrogram/client/session_storage/__init__.py @@ -16,5 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from .session_storage_mixin import SessionStorageMixin -from .base_session_storage import BaseSessionStorage, BaseSessionConfig, SessionDoesNotExist +from .abstract import SessionStorage, SessionDoesNotExist +from .memory import MemorySessionStorage +from .json import JsonSessionStorage +from .string import StringSessionStorage diff --git a/pyrogram/client/session_storage/session_storage_mixin.py b/pyrogram/client/session_storage/abstract.py similarity index 50% rename from pyrogram/client/session_storage/session_storage_mixin.py rename to pyrogram/client/session_storage/abstract.py index 7d783ca7..e8f4441e 100644 --- a/pyrogram/client/session_storage/session_storage_mixin.py +++ b/pyrogram/client/session_storage/abstract.py @@ -16,66 +16,103 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from typing import Dict +import abc +from typing import Type + +import pyrogram -class SessionStorageMixin: +class SessionDoesNotExist(Exception): + pass + + +class SessionStorage(abc.ABC): + def __init__(self, client: 'pyrogram.client.BaseClient'): + self._client = client + + @abc.abstractmethod + def load(self): + ... + + @abc.abstractmethod + def save(self, sync=False): + ... + + @abc.abstractmethod + def sync_cleanup(self): + ... + @property - def dc_id(self) -> int: - return self.session_storage.dc_id + @abc.abstractmethod + def dc_id(self): + ... @dc_id.setter + @abc.abstractmethod def dc_id(self, val): - self.session_storage.dc_id = val + ... @property - def test_mode(self) -> bool: - return self.session_storage.test_mode + @abc.abstractmethod + def test_mode(self): + ... @test_mode.setter + @abc.abstractmethod def test_mode(self, val): - self.session_storage.test_mode = val + ... @property - def auth_key(self) -> bytes: - return self.session_storage.auth_key + @abc.abstractmethod + def auth_key(self): + ... @auth_key.setter + @abc.abstractmethod def auth_key(self, val): - self.session_storage.auth_key = val + ... @property + @abc.abstractmethod def user_id(self): - return self.session_storage.user_id + ... @user_id.setter - def user_id(self, val) -> int: - self.session_storage.user_id = val + @abc.abstractmethod + def user_id(self, val): + ... @property - def date(self) -> int: - return self.session_storage.date + @abc.abstractmethod + def date(self): + ... @date.setter + @abc.abstractmethod def date(self, val): - self.session_storage.date = val + ... @property + @abc.abstractmethod def is_bot(self): - return self.session_storage.is_bot + ... @is_bot.setter - def is_bot(self, val) -> int: - self.session_storage.is_bot = val + @abc.abstractmethod + def is_bot(self, val): + ... @property - def peers_by_id(self) -> Dict[str, int]: - return self.session_storage.peers_by_id + @abc.abstractmethod + def peers_by_id(self): + ... @property - def peers_by_username(self) -> Dict[str, int]: - return self.session_storage.peers_by_username + @abc.abstractmethod + def peers_by_username(self): + ... @property - def peers_by_phone(self) -> Dict[str, int]: - return self.session_storage.peers_by_phone + @abc.abstractmethod + def peers_by_phone(self): + ... diff --git a/pyrogram/client/session_storage/base_session_storage.py b/pyrogram/client/session_storage/base_session_storage.py deleted file mode 100644 index 92473956..00000000 --- a/pyrogram/client/session_storage/base_session_storage.py +++ /dev/null @@ -1,60 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-2019 Dan Tès -# -# This file is part of Pyrogram. -# -# Pyrogram is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pyrogram is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Pyrogram. If not, see . - -import abc -from typing import Type - -import pyrogram - - -class SessionDoesNotExist(Exception): - pass - - -class BaseSessionStorage(abc.ABC): - def __init__(self, client: 'pyrogram.client.BaseClient', session_data): - self.client = client - self.session_data = session_data - self.dc_id = 1 - self.test_mode = None - self.auth_key = None - self.user_id = None - self.date = 0 - self.is_bot = False - self.peers_by_id = {} - self.peers_by_username = {} - self.peers_by_phone = {} - - @abc.abstractmethod - def load_session(self): - ... - - @abc.abstractmethod - def save_session(self, sync=False): - ... - - @abc.abstractmethod - def sync_cleanup(self): - ... - - -class BaseSessionConfig(abc.ABC): - @property - @abc.abstractmethod - def session_storage_cls(self) -> Type[BaseSessionStorage]: - ... diff --git a/pyrogram/client/session_storage/json_session_storage.py b/pyrogram/client/session_storage/json.py similarity index 58% rename from pyrogram/client/session_storage/json_session_storage.py rename to pyrogram/client/session_storage/json.py index 1e1e0ca4..170089a4 100644 --- a/pyrogram/client/session_storage/json_session_storage.py +++ b/pyrogram/client/session_storage/json.py @@ -22,21 +22,26 @@ import logging import os import shutil +import pyrogram from ..ext import utils -from . import BaseSessionStorage, SessionDoesNotExist +from . import MemorySessionStorage, SessionDoesNotExist log = logging.getLogger(__name__) -class JsonSessionStorage(BaseSessionStorage): +class JsonSessionStorage(MemorySessionStorage): + def __init__(self, client: 'pyrogram.client.ext.BaseClient', session_name: str): + super(JsonSessionStorage, self).__init__(client) + self._session_name = session_name + def _get_file_name(self, name: str): if not name.endswith('.session'): name += '.session' - return os.path.join(self.client.workdir, name) + return os.path.join(self._client.workdir, name) - def load_session(self): - file_path = self._get_file_name(self.session_data) + def load(self): + file_path = self._get_file_name(self._session_name) log.info('Loading JSON session from {}'.format(file_path)) try: @@ -45,59 +50,59 @@ class JsonSessionStorage(BaseSessionStorage): except FileNotFoundError: raise SessionDoesNotExist() - self.dc_id = s["dc_id"] - self.test_mode = s["test_mode"] - self.auth_key = base64.b64decode("".join(s["auth_key"])) # join split key - self.user_id = s["user_id"] - self.date = s.get("date", 0) - self.is_bot = s.get('is_bot', self.client.is_bot) + self._dc_id = s["dc_id"] + self._test_mode = s["test_mode"] + self._auth_key = base64.b64decode("".join(s["auth_key"])) # join split key + self._user_id = s["user_id"] + self._date = s.get("date", 0) + self._is_bot = s.get('is_bot', self._is_bot) for k, v in s.get("peers_by_id", {}).items(): - self.peers_by_id[int(k)] = utils.get_input_peer(int(k), v) + self._peers_by_id[int(k)] = utils.get_input_peer(int(k), v) for k, v in s.get("peers_by_username", {}).items(): - peer = self.peers_by_id.get(v, None) + peer = self._peers_by_id.get(v, None) if peer: - self.peers_by_username[k] = peer + self._peers_by_username[k] = peer for k, v in s.get("peers_by_phone", {}).items(): - peer = self.peers_by_id.get(v, None) + peer = self._peers_by_id.get(v, None) if peer: - self.peers_by_phone[k] = peer + self._peers_by_phone[k] = peer - def save_session(self, sync=False): - file_path = self._get_file_name(self.session_data) + def save(self, sync=False): + file_path = self._get_file_name(self._session_name) if sync: file_path += '.tmp' log.info('Saving JSON session to {}, sync={}'.format(file_path, sync)) - auth_key = base64.b64encode(self.auth_key).decode() + auth_key = base64.b64encode(self._auth_key).decode() auth_key = [auth_key[i: i + 43] for i in range(0, len(auth_key), 43)] # split key in lines of 43 chars - os.makedirs(self.client.workdir, exist_ok=True) + os.makedirs(self._client.workdir, exist_ok=True) data = { - 'dc_id': self.dc_id, - 'test_mode': self.test_mode, + 'dc_id': self._dc_id, + 'test_mode': self._test_mode, 'auth_key': auth_key, - 'user_id': self.user_id, - 'date': self.date, - 'is_bot': self.is_bot, + 'user_id': self._user_id, + 'date': self._date, + 'is_bot': self._is_bot, 'peers_by_id': { k: getattr(v, "access_hash", None) - for k, v in self.peers_by_id.copy().items() + for k, v in self._peers_by_id.copy().items() }, 'peers_by_username': { k: utils.get_peer_id(v) - for k, v in self.peers_by_username.copy().items() + for k, v in self._peers_by_username.copy().items() }, 'peers_by_phone': { k: utils.get_peer_id(v) - for k, v in self.peers_by_phone.copy().items() + for k, v in self._peers_by_phone.copy().items() } } @@ -109,10 +114,10 @@ class JsonSessionStorage(BaseSessionStorage): # execution won't be here if an error has occurred earlier if sync: - shutil.move(file_path, self._get_file_name(self.session_data)) + shutil.move(file_path, self._get_file_name(self._session_name)) def sync_cleanup(self): try: - os.remove(self._get_file_name(self.session_data) + '.tmp') + os.remove(self._get_file_name(self._session_name) + '.tmp') except OSError: pass diff --git a/pyrogram/client/session_storage/memory.py b/pyrogram/client/session_storage/memory.py new file mode 100644 index 00000000..f456f8eb --- /dev/null +++ b/pyrogram/client/session_storage/memory.py @@ -0,0 +1,85 @@ +import pyrogram +from . import SessionStorage, SessionDoesNotExist + + +class MemorySessionStorage(SessionStorage): + def __init__(self, client: 'pyrogram.client.ext.BaseClient'): + super(MemorySessionStorage, self).__init__(client) + self._dc_id = 1 + self._test_mode = None + self._auth_key = None + self._user_id = None + self._date = 0 + self._is_bot = False + self._peers_by_id = {} + self._peers_by_username = {} + self._peers_by_phone = {} + + def load(self): + raise SessionDoesNotExist() + + def save(self, sync=False): + pass + + def sync_cleanup(self): + pass + + @property + def dc_id(self): + return self._dc_id + + @dc_id.setter + def dc_id(self, val): + self._dc_id = val + + @property + def test_mode(self): + return self._test_mode + + @test_mode.setter + def test_mode(self, val): + self._test_mode = val + + @property + def auth_key(self): + return self._auth_key + + @auth_key.setter + def auth_key(self, val): + self._auth_key = val + + @property + def user_id(self): + return self._user_id + + @user_id.setter + def user_id(self, val): + self._user_id = val + + @property + def date(self): + return self._date + + @date.setter + def date(self, val): + self._date = val + + @property + def is_bot(self): + return self._is_bot + + @is_bot.setter + def is_bot(self, val): + self._is_bot = val + + @property + def peers_by_id(self): + return self._peers_by_id + + @property + def peers_by_username(self): + return self._peers_by_username + + @property + def peers_by_phone(self): + return self._peers_by_phone diff --git a/pyrogram/client/session_storage/string_session_storage.py b/pyrogram/client/session_storage/string.py similarity index 62% rename from pyrogram/client/session_storage/string_session_storage.py rename to pyrogram/client/session_storage/string.py index 5b1a8cc1..f8ec740a 100644 --- a/pyrogram/client/session_storage/string_session_storage.py +++ b/pyrogram/client/session_storage/string.py @@ -2,10 +2,11 @@ import base64 import binascii import struct -from . import BaseSessionStorage, SessionDoesNotExist +import pyrogram +from . import MemorySessionStorage, SessionDoesNotExist -class StringSessionStorage(BaseSessionStorage): +class StringSessionStorage(MemorySessionStorage): """ Packs session data as following (forcing little-endian byte order): Char dc_id (1 byte, unsigned) @@ -18,22 +19,26 @@ class StringSessionStorage(BaseSessionStorage): """ PACK_FORMAT = '