mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-22 01:16:35 +03:00
Remove StateCache
This commit is contained in:
parent
f4b2fe9540
commit
b5bfe5d9a1
|
@ -608,7 +608,6 @@ class AuthMethods:
|
|||
self._bot = None
|
||||
self._self_input_peer = None
|
||||
self._authorized = False
|
||||
self._state_cache.reset()
|
||||
|
||||
await self.disconnect()
|
||||
await self.session.delete()
|
||||
|
|
|
@ -13,7 +13,6 @@ from ..entitycache import EntityCache
|
|||
from ..extensions import markdown
|
||||
from ..network import MTProtoSender, Connection, ConnectionTcpFull, TcpMTProxy
|
||||
from ..sessions import Session, SQLiteSession, MemorySession
|
||||
from ..statecache import StateCache
|
||||
from ..tl import functions, types
|
||||
from ..tl.alltlobjects import LAYER
|
||||
|
||||
|
@ -412,8 +411,6 @@ class TelegramBaseClient(abc.ABC):
|
|||
|
||||
self._authorized = None # None = unknown, False = no, True = yes
|
||||
|
||||
self._state_cache = StateCache(None, self._log)
|
||||
|
||||
# Some further state for subclasses
|
||||
self._event_builders = []
|
||||
|
||||
|
@ -519,11 +516,6 @@ class TelegramBaseClient(abc.ABC):
|
|||
except OSError:
|
||||
print('Failed to connect')
|
||||
"""
|
||||
# Update state (for catching up after a disconnection)
|
||||
# TODO Get state from channels too
|
||||
self._state_cache = StateCache(
|
||||
await self.session.get_update_state(0), self._log)
|
||||
|
||||
if not await self._sender.connect(self._connection(
|
||||
self.session.server_address,
|
||||
self.session.port,
|
||||
|
@ -644,15 +636,6 @@ class TelegramBaseClient(abc.ABC):
|
|||
await asyncio.wait(self._updates_queue)
|
||||
self._updates_queue.clear()
|
||||
|
||||
pts, date = self._state_cache[None]
|
||||
if pts and date:
|
||||
await self.session.set_update_state(0, types.updates.State(
|
||||
pts=pts,
|
||||
qts=0,
|
||||
date=date,
|
||||
seq=0,
|
||||
unread_count=0
|
||||
))
|
||||
|
||||
await self.session.close()
|
||||
|
||||
|
|
|
@ -1,164 +0,0 @@
|
|||
import inspect
|
||||
|
||||
from .tl import types
|
||||
|
||||
|
||||
# Which updates have the following fields?
|
||||
_has_channel_id = []
|
||||
|
||||
|
||||
# TODO EntityCache does the same. Reuse?
|
||||
def _fill():
|
||||
for name in dir(types):
|
||||
update = getattr(types, name)
|
||||
if getattr(update, 'SUBCLASS_OF_ID', None) == 0x9f89304e:
|
||||
cid = update.CONSTRUCTOR_ID
|
||||
sig = inspect.signature(update.__init__)
|
||||
for param in sig.parameters.values():
|
||||
if param.name == 'channel_id' and param.annotation == int:
|
||||
_has_channel_id.append(cid)
|
||||
|
||||
if not _has_channel_id:
|
||||
raise RuntimeError('FIXME: Did the init signature or updates change?')
|
||||
|
||||
|
||||
# We use a function to avoid cluttering the globals (with name/update/cid/doc)
|
||||
_fill()
|
||||
|
||||
|
||||
class StateCache:
|
||||
"""
|
||||
In-memory update state cache, defaultdict-like behaviour.
|
||||
"""
|
||||
def __init__(self, initial, loggers):
|
||||
# We only care about the pts and the date. By using a tuple which
|
||||
# is lightweight and immutable we can easily copy them around to
|
||||
# each update in case they need to fetch missing entities.
|
||||
self._logger = loggers[__name__]
|
||||
if initial:
|
||||
self._pts_date = initial.pts, initial.date
|
||||
else:
|
||||
self._pts_date = None, None
|
||||
|
||||
def reset(self):
|
||||
self.__dict__.clear()
|
||||
self._pts_date = None, None
|
||||
|
||||
# TODO Call this when receiving responses too...?
|
||||
def update(
|
||||
self,
|
||||
update,
|
||||
*,
|
||||
channel_id=None,
|
||||
has_pts=frozenset(x.CONSTRUCTOR_ID for x in (
|
||||
types.UpdateNewMessage,
|
||||
types.UpdateDeleteMessages,
|
||||
types.UpdateReadHistoryInbox,
|
||||
types.UpdateReadHistoryOutbox,
|
||||
types.UpdateWebPage,
|
||||
types.UpdateReadMessagesContents,
|
||||
types.UpdateEditMessage,
|
||||
types.updates.State,
|
||||
types.updates.DifferenceTooLong,
|
||||
types.UpdateShortMessage,
|
||||
types.UpdateShortChatMessage,
|
||||
types.UpdateShortSentMessage
|
||||
)),
|
||||
has_date=frozenset(x.CONSTRUCTOR_ID for x in (
|
||||
types.UpdateUserPhoto,
|
||||
types.UpdateEncryption,
|
||||
types.UpdateEncryptedMessagesRead,
|
||||
types.UpdateChatParticipantAdd,
|
||||
types.updates.DifferenceEmpty,
|
||||
types.UpdateShortMessage,
|
||||
types.UpdateShortChatMessage,
|
||||
types.UpdateShort,
|
||||
types.UpdatesCombined,
|
||||
types.Updates,
|
||||
types.UpdateShortSentMessage,
|
||||
)),
|
||||
has_channel_pts=frozenset(x.CONSTRUCTOR_ID for x in (
|
||||
types.UpdateChannelTooLong,
|
||||
types.UpdateNewChannelMessage,
|
||||
types.UpdateDeleteChannelMessages,
|
||||
types.UpdateEditChannelMessage,
|
||||
types.UpdateChannelWebPage,
|
||||
types.updates.ChannelDifferenceEmpty,
|
||||
types.updates.ChannelDifferenceTooLong,
|
||||
types.updates.ChannelDifference
|
||||
)),
|
||||
check_only=False
|
||||
):
|
||||
"""
|
||||
Update the state with the given update.
|
||||
"""
|
||||
cid = update.CONSTRUCTOR_ID
|
||||
if check_only:
|
||||
return cid in has_pts or cid in has_date or cid in has_channel_pts
|
||||
|
||||
if cid in has_pts:
|
||||
if cid in has_date:
|
||||
self._pts_date = update.pts, update.date
|
||||
else:
|
||||
self._pts_date = update.pts, self._pts_date[1]
|
||||
elif cid in has_date:
|
||||
self._pts_date = self._pts_date[0], update.date
|
||||
|
||||
if cid in has_channel_pts:
|
||||
if channel_id is None:
|
||||
channel_id = self.get_channel_id(update)
|
||||
|
||||
if channel_id is None:
|
||||
self._logger.info(
|
||||
'Failed to retrieve channel_id from %s', update)
|
||||
else:
|
||||
self.__dict__[channel_id] = update.pts
|
||||
|
||||
def get_channel_id(
|
||||
self,
|
||||
update,
|
||||
has_channel_id=frozenset(_has_channel_id),
|
||||
# Hardcoded because only some with message are for channels
|
||||
has_message=frozenset(x.CONSTRUCTOR_ID for x in (
|
||||
types.UpdateNewChannelMessage,
|
||||
types.UpdateEditChannelMessage
|
||||
))
|
||||
):
|
||||
"""
|
||||
Gets the **unmarked** channel ID from this update, if it has any.
|
||||
|
||||
Fails for ``*difference`` updates, where ``channel_id``
|
||||
is supposedly already known from the outside.
|
||||
"""
|
||||
cid = update.CONSTRUCTOR_ID
|
||||
if cid in has_channel_id:
|
||||
return update.channel_id
|
||||
elif cid in has_message:
|
||||
if update.message.peer_id is None:
|
||||
# Telegram sometimes sends empty messages to give a newer pts:
|
||||
# UpdateNewChannelMessage(message=MessageEmpty(id), pts=pts, pts_count=1)
|
||||
# Not sure why, but it's safe to ignore them.
|
||||
self._logger.debug('Update has None peer_id %s', update)
|
||||
else:
|
||||
return update.message.peer_id.channel_id
|
||||
|
||||
return None
|
||||
|
||||
def __getitem__(self, item):
|
||||
"""
|
||||
If `item` is `None`, returns the default ``(pts, date)``.
|
||||
|
||||
If it's an **unmarked** channel ID, returns its ``pts``.
|
||||
|
||||
If no information is known, ``pts`` will be `None`.
|
||||
"""
|
||||
if item is None:
|
||||
return self._pts_date
|
||||
else:
|
||||
return self.__dict__.get(item)
|
||||
|
||||
def __setitem__(self, where, value):
|
||||
if where is None:
|
||||
self._pts_date = value
|
||||
else:
|
||||
self.__dict__[where] = value
|
Loading…
Reference in New Issue
Block a user