Preparing to update filter system

- Filters are asynchronous from now on
- Filters are provided with the AsyncClient from now on
This commit is contained in:
2026-09-09 01:03:51 +03:00
parent 5fd87879ca
commit 7d6230881b
3 changed files with 14 additions and 10 deletions

View File

@@ -51,7 +51,7 @@ class Callbacks:
for callback_info in self._filters: for callback_info in self._filters:
if not isinstance(callback_info, self._FilterBasedCallback): if not isinstance(callback_info, self._FilterBasedCallback):
continue continue
if not callback_info.filter(room, event): if not await callback_info.filter(room, event, self._client):
continue continue
event_data = RoomEventData( event_data = RoomEventData(
room=room, room=room,

View File

@@ -1,6 +1,7 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
import logging import logging
from nio import AsyncClient
from nio import MatrixRoom, Event from nio import MatrixRoom, Event
class BaseEventFilter(ABC): class BaseEventFilter(ABC):
@@ -59,14 +60,16 @@ class BaseEventFilter(ABC):
pass pass
@abstractmethod @abstractmethod
def __call__(self, room: MatrixRoom, event: Event) -> bool: async def __call__(self, room: MatrixRoom, event: Event, client: AsyncClient) -> bool:
"""This abstract method must be redefined in derived classes so that """This abstract method must be redefined in derived classes so that
the filter operates according to its description. This method must the filter operates according to its description. This method must
not raise exceptions. In case of exception it should log it using not raise exceptions. In case of exception it should log it using
`self._logger` and return False `self._logger` and return False
Args: Args:
room - room the event has happened in
event - the event to check againts this filter event - the event to check againts this filter
client - the client
Returns: Returns:
True if the event satisfies this filter True if the event satisfies this filter
@@ -123,8 +126,8 @@ class CompoundEventFilter(BaseEventFilter):
expression = f"~{reprs[0]}" expression = f"~{reprs[0]}"
return f"({expression})" return f"({expression})"
def __call__(self, room: MatrixRoom, event: Event) -> bool: async def __call__(self, room: MatrixRoom, event: Event, client: AsyncClient) -> bool:
evaluated = [arg(room, event) for arg in self._arguments] evaluated = [await arg(room, event, client) for arg in self._arguments]
if self._operator == self.OPERATOR_AND: if self._operator == self.OPERATOR_AND:
return all(evaluated) return all(evaluated)
elif self._operator == self.OPERATOR_OR: elif self._operator == self.OPERATOR_OR:

View File

@@ -1,5 +1,6 @@
from .base import BaseEventFilter from .base import BaseEventFilter
from nio import AsyncClient
from nio import MatrixRoom, Event from nio import MatrixRoom, Event
class TextFilter(BaseEventFilter): class TextFilter(BaseEventFilter):
@@ -13,7 +14,7 @@ class TextFilter(BaseEventFilter):
def __repr__(self): def __repr__(self):
return "TextFilter()" return "TextFilter()"
def __call__(self, room: MatrixRoom, event: Event) -> bool: async def __call__(self, room: MatrixRoom, event: Event, client: AsyncClient) -> bool:
return hasattr(event, "body") and type(event.body) is str # type: ignore return hasattr(event, "body") and type(event.body) is str # type: ignore
class FormattedTextFilter(BaseEventFilter): class FormattedTextFilter(BaseEventFilter):
@@ -27,7 +28,7 @@ class FormattedTextFilter(BaseEventFilter):
def __repr__(self): def __repr__(self):
return "FormattedTextFilter()" return "FormattedTextFilter()"
def __call__(self, room: MatrixRoom, event: Event) -> bool: async def __call__(self, room: MatrixRoom, event: Event, client: AsyncClient) -> bool:
return hasattr(event, "formatted_body") and type(event.formatted_body) is str # type: ignore return hasattr(event, "formatted_body") and type(event.formatted_body) is str # type: ignore
class TextContainsFilter(BaseEventFilter): class TextContainsFilter(BaseEventFilter):
@@ -49,7 +50,7 @@ class TextContainsFilter(BaseEventFilter):
def __repr__(self): def __repr__(self):
return f"TextContainsFilter({repr(self._needle)}, any_case={repr(self._any_case)})" return f"TextContainsFilter({repr(self._needle)}, any_case={repr(self._any_case)})"
def __call__(self, room: MatrixRoom, event: Event) -> bool: async def __call__(self, room: MatrixRoom, event: Event, client: AsyncClient) -> bool:
try: try:
body = event.body.lower() if self._any_case else event.body # type: ignore body = event.body.lower() if self._any_case else event.body # type: ignore
for n in self._needle: for n in self._needle:
@@ -78,7 +79,7 @@ class TextStartsWithFilter(BaseEventFilter):
def __repr__(self): def __repr__(self):
return f"TextStartsWithFilter({repr(self._substring)}, any_case={repr(self._any_case)})" return f"TextStartsWithFilter({repr(self._substring)}, any_case={repr(self._any_case)})"
def __call__(self, room: MatrixRoom, event: Event) -> bool: async def __call__(self, room: MatrixRoom, event: Event, client: AsyncClient) -> bool:
try: try:
body = event.body.lower() if self._any_case else event.body # type: ignore body = event.body.lower() if self._any_case else event.body # type: ignore
for s in self._substring: for s in self._substring:
@@ -107,7 +108,7 @@ class TextEndsWithFilter(BaseEventFilter):
def __repr__(self): def __repr__(self):
return f"TextEndsWithFilter({repr(self._substring)}, any_case={repr(self._any_case)})" return f"TextEndsWithFilter({repr(self._substring)}, any_case={repr(self._any_case)})"
def __call__(self, room: MatrixRoom, event: Event) -> bool: async def __call__(self, room: MatrixRoom, event: Event, client: AsyncClient) -> bool:
try: try:
body = event.body.lower() if self._any_case else event.body # type: ignore body = event.body.lower() if self._any_case else event.body # type: ignore
for s in self._substring: for s in self._substring:
@@ -144,7 +145,7 @@ class TextCommandFilter(BaseEventFilter):
def __repr__(self): def __repr__(self):
return f"TextCommandFilter({repr(self._verbs)}, {repr(self._min_args)}, {repr(self._max_args)}, {repr(self._prefix)})" return f"TextCommandFilter({repr(self._verbs)}, {repr(self._min_args)}, {repr(self._max_args)}, {repr(self._prefix)})"
def __call__(self, room: MatrixRoom, event: Event) -> bool: async def __call__(self, room: MatrixRoom, event: Event, client: AsyncClient) -> bool:
try: try:
parts = [p.strip() for p in event.body.split() if p.strip()] # type: ignore parts = [p.strip() for p in event.body.split() if p.strip()] # type: ignore
args_count = len(parts) - 1 args_count = len(parts) - 1