Skip to content

Commit

Permalink
feat(Chat): added option to set a handler for when a command executio…
Browse files Browse the repository at this point in the history
…n if blocked by the middleware
  • Loading branch information
Teekeks committed Aug 31, 2023
1 parent 6fe6468 commit 510c7de
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
6 changes: 6 additions & 0 deletions twitchAPI/chat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,8 @@ def __init__(self,
self._command_middleware: List['BaseCommandMiddleware'] = []
self._command_specific_middleware: Dict[str, List['BaseCommandMiddleware']] = {}
self._task_callback = partial(done_task_callback, self.logger)
self.default_command_execution_blocked_handler: Optional[Callable[[ChatCommand], Awaitable[None]]] = None
"""The default handler to be called should a command execution be blocked by a middleware that has no specific handler set."""

def __await__(self):
t = asyncio.create_task(self._get_username())
Expand Down Expand Up @@ -1105,6 +1107,10 @@ async def _handle_msg(self, parsed: dict):
async def _can_execute_command(_com: ChatCommand, _name: str) -> bool:
for mid in self._command_middleware + self._command_specific_middleware.get(_name, []):
if not await mid.can_execute(command):
if mid.execute_blocked_handler is not None:
await mid.execute_blocked_handler(_com)
elif self.default_command_execution_blocked_handler is not None:
await self.default_command_execution_blocked_handler(_com)
return False
return True

Expand Down
21 changes: 18 additions & 3 deletions twitchAPI/chat/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"""
from abc import ABC, abstractmethod
from typing import Optional, List, TYPE_CHECKING
from typing import Optional, List, TYPE_CHECKING, Callable, Awaitable

if TYPE_CHECKING:
from . import ChatCommand
Expand All @@ -21,6 +21,9 @@
class BaseCommandMiddleware(ABC):
"""The base for chat command middleware, extend from this when implementing your own"""

execute_blocked_handler: Optional[Callable[[ChatCommand], Awaitable[None]]] = None
"""If set, this handler will be called should :const:`twitchAPI.chat.middleware.BaseCommandMiddleware.can_execute()` fail."""

@abstractmethod
async def can_execute(self, command: 'ChatCommand') -> bool:
"""
Expand All @@ -35,11 +38,14 @@ class ChannelRestriction(BaseCommandMiddleware):

def __init__(self,
allowed_channel: Optional[List[str]] = None,
denied_channel: Optional[List[str]] = None):
denied_channel: Optional[List[str]] = None,
execute_blocked_handler: Optional[Callable[[ChatCommand], Awaitable[None]]] = None):
"""
:param allowed_channel: if provided, the command can only be used in channels on this list
:param denied_channel: if provided, the command can't be used in channels on this list
:param execute_blocked_handler: optional specific handler for when the execution is blocked
"""
self.execute_blocked_handler = execute_blocked_handler
self.allowed = allowed_channel if allowed_channel is not None else []
self.denied = denied_channel if denied_channel is not None else []

Expand All @@ -55,11 +61,14 @@ class UserRestriction(BaseCommandMiddleware):

def __init__(self,
allowed_users: Optional[List[str]] = None,
denied_users: Optional[List[str]] = None):
denied_users: Optional[List[str]] = None,
execute_blocked_handler: Optional[Callable[[ChatCommand], Awaitable[None]]] = None):
"""
:param allowed_users: if provided, the command can only be used by one of the provided users
:param denied_users: if provided, the command can not be used by any of the provided users
:param execute_blocked_handler: optional specific handler for when the execution is blocked
"""
self.execute_blocked_handler = execute_blocked_handler
self.allowed = allowed_users if allowed_users is not None else []
self.denied = denied_users if denied_users is not None else []

Expand All @@ -73,5 +82,11 @@ async def can_execute(self, command: 'ChatCommand') -> bool:
class StreamerOnly(BaseCommandMiddleware):
"""Restricts the use of commands to only the streamer in their channel"""

def __int__(self, execute_blocked_handler: Optional[Callable[[ChatCommand], Awaitable[None]]] = None):
"""
:param execute_blocked_handler: optional specific handler for when the execution is blocked
"""
self.execute_blocked_handler = execute_blocked_handler

async def can_execute(self, command: 'ChatCommand') -> bool:
return command.room.name == command.user.name

0 comments on commit 510c7de

Please sign in to comment.