@@ -107,6 +107,8 @@ def __init__(
107
107
self ._args : list [Any ] = []
108
108
self ._kwargs : dict [str , Any ] = {}
109
109
110
+ self ._prepare_called : bool = False
111
+
110
112
@property
111
113
def message (self ) -> ChatMessage | None :
112
114
"""Property returning the :class:`~twitchio.ChatMessage` that this :class:`~.commands.Context` was
@@ -343,7 +345,10 @@ async def _get_prefix(self) -> None:
343
345
344
346
self ._validate_prefix (potential )
345
347
346
- def _get_command (self ) -> None :
348
+ def _get_command (self , reset : bool = False ) -> None :
349
+ if self ._prepare_called :
350
+ return
351
+
347
352
commands = self ._bot ._commands
348
353
349
354
if isinstance (self ._payload , (ChannelPointsRedemptionAdd , ChannelPointsRedemptionUpdate )):
@@ -361,17 +366,51 @@ def _get_command(self) -> None:
361
366
self ._invoked_with = next_
362
367
command = commands .get (next_ )
363
368
369
+ if reset :
370
+ self ._view .reset ()
371
+
364
372
if not command :
365
373
return
366
374
367
375
self ._command = command
368
376
return
369
377
370
- async def _prepare (self ) -> None :
378
+ async def fetch_command (self ) -> Command [Any , ...] | RewardCommand [Any , ...] | None :
379
+ """|coro|
380
+
381
+ Method which validates the prefix and finds and returns the command that would be invoked or ``None`` if no valid
382
+ command can be found.
383
+
384
+ If no valid ``prefix`` is found this method will always return ``None``.
385
+
386
+ .. note::
387
+
388
+ Unlike :meth:`.prepare` this method resets the state of the internal string-view used to find the ``prefix``,
389
+ ``command`` and ``arguments`` and can be safely used at anytime.
390
+
391
+ .. versionadded:: 3.1
392
+
393
+ Returns
394
+ -------
395
+ :class:`twitchio.ext.commands.Command` | :class:`twitchio.ext.commands.RewardCommand` | None
396
+ The :class:`twitchio.ext.commands.Command` or :class:`twitchio.ext.commands.RewardCommand` if found alongside
397
+ a valid prefix, otherwise ``None``.
398
+ """
399
+ try :
400
+ await self ._prepare (reset = True )
401
+ except PrefixError :
402
+ return
403
+
404
+ return self ._command
405
+
406
+ async def _prepare (self , reset : bool = False ) -> None :
371
407
if isinstance (self ._payload , ChatMessage ):
372
408
await self ._get_prefix ()
373
409
374
- self ._get_command ()
410
+ self ._get_command (reset = reset )
411
+
412
+ if reset is False :
413
+ self ._prepare_called = True
375
414
376
415
async def prepare (self ) -> None :
377
416
"""|coro|
@@ -381,6 +420,10 @@ async def prepare(self) -> None:
381
420
This coroutine is called automatically in :meth:`.invoke` before anything else.
382
421
383
422
Could be overriden to add extra setup before command invocation.
423
+
424
+ .. note::
425
+
426
+ If this method is overriden you should call `await super().prepare()` to ensure correct setup of the context.
384
427
"""
385
428
await self ._prepare ()
386
429
0 commit comments