mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-01-25 00:34:19 +03:00
Simplify event resolving logic
Although this commit introduces a race condition since an event may only be half-resolved. A lock is thus needed, but it depends on an event-loop to which we don't have access in the class-level.
This commit is contained in:
parent
9f237cc928
commit
d474458136
|
@ -270,8 +270,6 @@ class TelegramBaseClient(abc.ABC):
|
|||
|
||||
# Some further state for subclasses
|
||||
self._event_builders = []
|
||||
self._events_pending_resolve = []
|
||||
self._event_resolve_lock = asyncio.Lock()
|
||||
self._conversations = {}
|
||||
|
||||
# Default parse mode
|
||||
|
|
|
@ -89,7 +89,7 @@ class UpdateMethods(UserMethods):
|
|||
elif not event:
|
||||
event = events.Raw()
|
||||
|
||||
self._events_pending_resolve.append(event)
|
||||
self._loop.create_task(event.resolve(self))
|
||||
self._event_builders.append((event, callback))
|
||||
|
||||
def remove_event_handler(self, callback, event=None):
|
||||
|
@ -249,17 +249,6 @@ class UpdateMethods(UserMethods):
|
|||
self._dispatching_updates_queue.clear()
|
||||
|
||||
async def _dispatch_update(self, update):
|
||||
if self._events_pending_resolve:
|
||||
if self._event_resolve_lock.locked():
|
||||
async with self._event_resolve_lock:
|
||||
pass
|
||||
else:
|
||||
async with self._event_resolve_lock:
|
||||
for event in self._events_pending_resolve:
|
||||
await event.resolve(self)
|
||||
|
||||
self._events_pending_resolve.clear()
|
||||
|
||||
built = EventBuilderDict(self, update)
|
||||
if self._conversations:
|
||||
for conv in self._conversations.values():
|
||||
|
@ -274,7 +263,15 @@ class UpdateMethods(UserMethods):
|
|||
|
||||
for builder, callback in self._event_builders:
|
||||
event = built[type(builder)]
|
||||
if not event or not builder.filter(event):
|
||||
if not event:
|
||||
continue
|
||||
|
||||
# TODO Lock until it's resolved; the task for resolving
|
||||
# was already created when adding the event handler.
|
||||
if not builder.resolved:
|
||||
await builder.resolve()
|
||||
|
||||
if not builder.filter(event):
|
||||
continue
|
||||
|
||||
try:
|
||||
|
|
|
@ -57,7 +57,7 @@ class EventBuilder(abc.ABC):
|
|||
def __init__(self, chats=None, blacklist_chats=False):
|
||||
self.chats = chats
|
||||
self.blacklist_chats = blacklist_chats
|
||||
self._self_id = None
|
||||
self.resolved = False
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
|
@ -66,9 +66,11 @@ class EventBuilder(abc.ABC):
|
|||
|
||||
async def resolve(self, client):
|
||||
"""Helper method to allow event builders to be resolved before usage"""
|
||||
self.chats = await _into_id_set(client, self.chats)
|
||||
if not EventBuilder.self_id:
|
||||
EventBuilder.self_id = await client.get_peer_id('me')
|
||||
if not self.resolved:
|
||||
self.resolved = True
|
||||
self.chats = await _into_id_set(client, self.chats)
|
||||
if not EventBuilder.self_id:
|
||||
EventBuilder.self_id = await client.get_peer_id('me')
|
||||
|
||||
def filter(self, event):
|
||||
"""
|
||||
|
|
|
@ -71,8 +71,9 @@ class NewMessage(EventBuilder):
|
|||
))
|
||||
|
||||
async def resolve(self, client):
|
||||
await super().resolve(client)
|
||||
self.from_users = await _into_id_set(client, self.from_users)
|
||||
if not self.resolved:
|
||||
await super().resolve(client)
|
||||
self.from_users = await _into_id_set(client, self.from_users)
|
||||
|
||||
@classmethod
|
||||
def build(cls, update):
|
||||
|
|
|
@ -27,7 +27,7 @@ class Raw(EventBuilder):
|
|||
self.types = tuple(types)
|
||||
|
||||
async def resolve(self, client):
|
||||
pass
|
||||
self.resolved = True
|
||||
|
||||
@classmethod
|
||||
def build(cls, update):
|
||||
|
|
|
@ -260,6 +260,8 @@ class Conversation(ChatGetter):
|
|||
if isinstance(event, type):
|
||||
event = event()
|
||||
|
||||
await event.resolve()
|
||||
|
||||
counter = Conversation._custom_counter
|
||||
Conversation._custom_counter += 1
|
||||
|
||||
|
@ -270,22 +272,17 @@ class Conversation(ChatGetter):
|
|||
finally:
|
||||
del self._custom[counter]
|
||||
|
||||
self._custom[counter] = (event, future, False)
|
||||
self._custom[counter] = (event, future)
|
||||
return await result()
|
||||
|
||||
async def _check_custom(self, built):
|
||||
# TODO This code is quite much a copy paste of registering events
|
||||
# in the client, resolving them and setting the client; perhaps
|
||||
# there is a better way?
|
||||
for i, (ev, fut, resolved) in self._custom.items():
|
||||
for i, (ev, fut) in self._custom.items():
|
||||
ev_type = type(ev)
|
||||
if built[ev_type]:
|
||||
if not resolved:
|
||||
await ev.resolve(self._client)
|
||||
self._custom[i] = (ev, fut, True)
|
||||
|
||||
if ev.filter(built[ev_type]):
|
||||
fut.set_result(built[ev_type])
|
||||
if built[ev_type] and ev.filter(built[ev_type]):
|
||||
fut.set_result(built[ev_type])
|
||||
|
||||
def _on_new_message(self, response):
|
||||
response = response.message
|
||||
|
|
Loading…
Reference in New Issue
Block a user