Skip to content

Commit 0c4666c

Browse files
committed
Add Client.safe_disptach
1 parent 2c4b479 commit 0c4666c

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

twitchio/client.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,71 @@ def dispatch(self, event: str, payload: Any | None = None) -> None:
266266
task.add_done_callback(waits.discard)
267267
waits.add(task)
268268

269+
def safe_dispatch(self, name: str, *, payload: Any | None = None) -> None:
270+
"""Method to dispatch a custom :ref:`_Event`.
271+
272+
When an event is dispatched all listeners listening to the event, coroutine functions defined on the
273+
:class:`~twitchio.Client` with the same name, and :meth:`~twitchio.Client.wait_for` waiting for the event will be
274+
triggered.
275+
276+
Internally the :class:`~twitchio.Client` uses a method similar to this, however to avoid conflicts with built-in events
277+
it is not documented and you should use this method instead when needing a custom event dispatched.
278+
279+
This method avoids conflicts with internal events by prefixing the name of the event with ``event_safe_``;
280+
specifically in this case ``_safe_`` is added between the ``event_`` prefix and the name of the event.
281+
282+
All events in TwitchIO, including custom ones, must take between ``0`` or ``1`` arguments only. If ``None`` is
283+
passed to the payload parameter (default), the event will be dispatched with no arguments attached. Otherwise you can
284+
provide one parameter ``payload`` which (ideally) is a class containing all the information and methods needed in
285+
your event. Keep in mind that events expect consistency; E.g. If your event takes a payload argument it should
286+
**always** take a payload argument and vice versa. If designing an ``ext`` for TwitchIO this also will be inline
287+
with how end-users will expect events to work.
288+
289+
.. note::
290+
291+
If you intend on using this in a custom ``ext`` for example; consider also adding a small prefix to the name to
292+
identify your extension from others.
293+
294+
.. warning::
295+
296+
Overriding this method is highly discouraged. Any changes made to the safe name of the event may have hard to
297+
track and unwanted side effects. TwitchIO uses events internally and any changes to these dispatched events
298+
internally by users may also lead to consequences such as being rate limted or banned by Twitch, banned by
299+
broadcasters or; memory, CPU, network and other performance issues.
300+
301+
Parameters
302+
----------
303+
name: str
304+
The name of the event you wish to dispatch. Remember the name of the event will be prefixed with ``event_safe_``.
305+
payload: Any | None
306+
The payload object dispatched to all your listeners. Defaults to ``None`` which would pass ``0`` arguments to all
307+
listeners.
308+
309+
Example
310+
-------
311+
312+
.. code:: python3
313+
314+
class CoolPayload:
315+
316+
def __init__(self, number: int) -> None:
317+
self.number = number
318+
319+
320+
class CoolComponent(commands.Component):
321+
322+
@commands.Component.listener()
323+
async def event_safe_cool(self, payload: CoolPayload) -> None:
324+
print(f"Received 'cool' event with number: {payload.number}")
325+
326+
327+
# Somewhere...
328+
payload = CoolPayload(number=9)
329+
client.safe_dispatch("cool", payload)
330+
"""
331+
name_ = f"safe_{name}"
332+
self.dispatch(name_, payload)
333+
269334
async def setup_hook(self) -> None:
270335
"""
271336
Method called after :meth:`~.login` has been called but before the client is ready.

0 commit comments

Comments
 (0)