nickoala / telepot

Python framework for Telegram Bot API
MIT License
2.43k stars 474 forks source link

Schedule event in others event space #376

Open giovanni5 opened 6 years ago

giovanni5 commented 6 years ago

hi, it is possible to do something like this:

def schedule_event_for_all(when, data_tuple):
    for delegate in active_delegates:
        delegate.scheduler.event_at(when, data_tuple)

how to obtain the active_delegates list? or

def schedule_event_for_all(when, data_tuple):
    for source in sources:
        bot.scheduler.event_at(when, {'_event': {'source': source, 'data': data_tuple}})

in my example ad admin wants to schedule an event for all delegates.

nickoala commented 6 years ago

In effect, you are requiring a way to retrieve the list of all active *Handler objects.

This line in the file __init__.py indicates that there is a field self._delegate_records in DelegatorBot holding all the active delegates. To be precise, self._delegate_records is a list of tuples; each tuple's third element is a dictionary whose keys are delegate's ID and whose values are delegates. Unfortunately, those delegates in the dictionary are not *Handler objects you want to get at. Those delegates are actually threads (or tasks in async version) wrapping around *Handler objects. There is no way to retrieve *Handler objects from delegates.

For what you want to achieve, however, I think of another approach. The way telepot delivers messages and events is by broadcasting all messages and events to all *Handler objects, and lets each *Handler filter for what they want to hear. All *Handlers have a listener object which performs the filtering. Normally, the listener is configured to listen out for those messages and events aimed at its parent *Handler only. For example, this line configures it to listen for chat messages with a certain chat id; this line configures it to listen for events with a certain event space and source id; this line configures it to listen for chat messages with a certain flavor and a certain from id. You tell a listener what to capture by giving it a message pattern or a predicate function. Here is the reference.

To achieve a broadcast (i.e. sending an event to all delegates), you can configure the listeners to be less specific. For example, you can design your broadcast event to have the form:

{'_broadcast': { ... }}

and configure your listener as:

self.listener.capture([lambda msg: flavor(msg) == '_broadcast'])

Then, when you use bot.scheduler to schedule such an event, all delegates should receive it, if all goes well.

Mind you, I haven't actually done such a thing. But it should be feasible within telepot's design. Any unintended consequences? I can't think of any, but can't say for sure. Like I said, I haven't done such a thing :blush: Good luck.

giovanni5 commented 6 years ago

The way telepot delivers messages and events is by broadcasting all messages and events to all Handler objects, and lets each Handler filter for what they want to hear.

so my schedule_event_for_all is a waste of resources. Thank you very much, your solution is cleaner and works fine.