Remove PackedChat

In favour of using the session entity type consistently.
This commit is contained in:
Lonami Exo
2022-02-08 11:31:24 +01:00
parent 07faa53c5a
commit 9b4808a558
8 changed files with 86 additions and 74 deletions

View File

@@ -64,15 +64,15 @@ class Session(ABC):
Get the `Entity` with matching ``ty`` and ``id``.
The following groups of ``ty`` should be treated to be equivalent, that is, for a given
``ty`` and ``id``, if the ``ty`` is in a given group, a matching ``access_hash`` with
that ``id`` from within any ``ty`` in that group should be returned.
``ty`` and ``id``, if the ``ty`` is in a given group, a matching ``hash`` with that ``id``
from within any ``ty`` in that group should be returned.
* `EntityType.USER` and `EntityType.BOT`.
* `EntityType.GROUP`.
* `EntityType.CHANNEL`, `EntityType.MEGAGROUP` and `EntityType.GIGAGROUP`.
For example, if a ``ty`` representing a bot is stored but the asking ``ty`` is a user,
the corresponding ``access_hash`` should still be returned.
the corresponding ``hash`` should still be returned.
You may use ``EntityType.canonical`` to find out the canonical type.

View File

@@ -34,12 +34,12 @@ class MemorySession(Session):
return list(self.channel_states.values())
async def insert_entities(self, entities: List[Entity]):
self.entities.update((e.id, (e.ty, e.access_hash)) for e in entities)
self.entities.update((e.id, (e.ty, e.hash)) for e in entities)
async def get_entity(self, ty: Optional[int], id: int) -> Optional[Entity]:
try:
ty, access_hash = self.entities[id]
return Entity(ty, id, access_hash)
ty, hash = self.entities[id]
return Entity(ty, id, hash)
except KeyError:
return None

View File

@@ -127,7 +127,7 @@ class SQLiteSession(Session):
limit 1
''')
c.execute('''
insert into entity (id, access_hash, ty)
insert into entity (id, hash, ty)
select
case
when id < -1000000000000 then -(id + 1000000000000)
@@ -173,7 +173,7 @@ class SQLiteSession(Session):
)''',
'''entity (
id integer primary key,
access_hash integer not null,
hash integer not null,
ty integer not null
)''',
)
@@ -245,13 +245,13 @@ class SQLiteSession(Session):
try:
c.executemany(
'insert or replace into entity values (?,?,?)',
[(e.id, e.access_hash, e.ty) for e in entities]
[(e.id, e.hash, e.ty) for e in entities]
)
finally:
c.close()
async def get_entity(self, ty: Optional[int], id: int) -> Optional[Entity]:
row = self._execute('select ty, id, access_hash from entity where id = ?', id)
row = self._execute('select ty, id, hash from entity where id = ?', id)
return Entity(*row) if row else None
async def save(self):

View File

@@ -105,12 +105,74 @@ class Entity:
"""
Stores the information needed to use a certain user, chat or channel with the API.
* ty: 8-bit number indicating the type of the entity.
* ty: 8-bit number indicating the type of the entity (of type `EntityType`).
* id: 64-bit number uniquely identifying the entity among those of the same type.
* access_hash: 64-bit number needed to use this entity with the API.
* hash: 64-bit signed number needed to use this entity with the API.
The string representation of this class is considered to be stable, for as long as
Telegram doesn't need to add more fields to the entities. It can also be converted
to bytes with ``bytes(entity)``, for a more compact representation.
"""
__slots__ = ('ty', 'id', 'access_hash')
__slots__ = ('ty', 'id', 'hash')
ty: EntityType
id: int
access_hash: int
hash: int
@property
def is_user(self):
"""
``True`` if the entity is either a user or a bot.
"""
return self.ty in (EntityType.USER, EntityType.BOT)
@property
def is_group(self):
"""
``True`` if the entity is a small group chat or `megagroup`_.
.. _megagroup: https://telegram.org/blog/supergroups5k
"""
return self.ty in (EntityType.GROUP, EntityType.MEGAGROUP)
@property
def is_channel(self):
"""
``True`` if the entity is a broadcast channel or `broadcast group`_.
.. _broadcast group: https://telegram.org/blog/autodelete-inv2#groups-with-unlimited-members
"""
return self.ty in (EntityType.CHANNEL, EntityType.GIGAGROUP)
@classmethod
def from_str(cls, string: str):
"""
Convert the string into an `Entity`.
"""
try:
ty, id, hash = string.split('.')
ty, id, hash = ord(ty), int(id), int(hash)
except AttributeError:
raise TypeError(f'expected str, got {string!r}') from None
except (TypeError, ValueError):
raise ValueError(f'malformed entity str (must be T.id.hash), got {string!r}') from None
return cls(EntityType(ty), id, hash)
@classmethod
def from_bytes(cls, blob):
"""
Convert the bytes into an `Entity`.
"""
try:
ty, id, hash = struct.unpack('<Bqq', blob)
except struct.error:
raise ValueError(f'malformed entity data, got {string!r}') from None
return cls(EntityType(ty), id, hash)
def __str__(self):
return f'{chr(self.ty)}.{self.id}.{self.hash}'
def __bytes__(self):
return struct.pack('<Bqq', self.ty, self.id, self.hash)