Skip to content

Commit

Permalink
feat: Metadata.inh
Browse files Browse the repository at this point in the history
  • Loading branch information
RF-Tar-Railt committed Jan 13, 2024
1 parent 6eefc77 commit 554444e
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 70 deletions.
24 changes: 24 additions & 0 deletions avilla/core/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
from avilla.core.selector import Selector
from avilla.core.service import AvillaService
from avilla.core.utilles import identity
from avilla.core.event import MetadataModified
from avilla.standard.core.request import RequestEvent
from avilla.standard.core.activity import ActivityEvent

if TYPE_CHECKING:
from graia.broadcast import Decorator, Dispatchable, Namespace, T_Dispatcher
Expand Down Expand Up @@ -131,6 +134,27 @@ def event_record(self, event: AvillaEvent | AvillaLifecycleEvent):
if type(event) in self.custom_event_recorder:
self.custom_event_recorder[type(event)](event)

elif isinstance(event, RequestEvent):
logger.info(
f"[{context.account.info.protocol.__class__.__name__.replace('Protocol', '')} "
f"{context.account.route['account']}]: "
f"Request {event.request.request_type or event.request.id} "
f"from {client} in {scene}"
)
elif isinstance(event, ActivityEvent):
logger.info(
f"[{context.account.info.protocol.__class__.__name__.replace('Protocol', '')} "
f"{context.account.route['account']}]: "
f"Activity {event.id}: {event.activity}"
f"from {client} in {scene}"
)
elif isinstance(event, MetadataModified):
logger.info(
f"[{context.account.info.protocol.__class__.__name__.replace('Protocol', '')} "
f"{context.account.route['account']}]: "
f"Metadata {event.route} Modified: {event.details}"
f"from {client} in {scene}"
)
elif isinstance(event, MessageReceived):
logger.info(
f"[{context.account.info.protocol.__class__.__name__.replace('Protocol', '')} "
Expand Down
26 changes: 17 additions & 9 deletions avilla/core/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ async def catch(interface: DispatcherInterface[AvillaEvent]):
if isclass(interface.annotation) and issubclass(interface.annotation, BaseAccount):
return interface.event.context.account

if interface.name == "client":
if interface.name == "client" and interface.annotation is Selector:
return interface.event.context.client

if interface.name == "scene":
if interface.name == "scene" and interface.annotation is Selector:
return interface.event.context.scene

if interface.name == "endpoint":
if interface.name == "endpoint" and interface.annotation is Selector:
return interface.event.context.endpoint

@staticmethod
Expand Down Expand Up @@ -113,22 +113,30 @@ class ModifyDetail:
current: Any = None
previous: Any = None

def __repr__(self):
if self.type == "set":
return f"Set to {self.current!r}"
if self.type == "clear":
return f"Clear from {self.previous!r}"
if self.type == "update":
return f"Update from {self.previous!r} to {self.current!r}"
return "..."


@dataclass
class MetadataModified(AvillaEvent):
endpoint: Selector
route: type[Metadata] | MetadataRoute[Unpack[tuple[Any, ...]], Metadata]
details: dict[FieldReference, ModifyDetail]
details: dict[Any, ModifyDetail]
operator: Selector | None = None
scene: Selector | None = None

class Dispatcher(AvillaEvent.Dispatcher):
@staticmethod
async def catch(interface: DispatcherInterface["MetadataModified"]):
if interface.name == "route":
return interface.event.route
if interface.name == "details":
return interface.event.details
if interface.name == "operator":
return Force(interface.event.operator)
if interface.annotation is dict:
return interface.event.details
if interface.is_annotated and interface.annotated_origin is ModifyDetail:
return interface.event.details.get(interface.annotated_metadata[0])
return await AvillaEvent.Dispatcher.catch(interface)
89 changes: 65 additions & 24 deletions avilla/core/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

from contextvars import ContextVar
from dataclasses import dataclass, field
from types import FunctionType
from typing import Any, Callable, Generic, TypeVar, Union, overload, cast
from typing import Any, Generic, TypeVar, Union, overload, TYPE_CHECKING
from weakref import WeakKeyDictionary

from typing_extensions import Self, TypeVarTuple, Unpack
Expand Down Expand Up @@ -66,9 +65,14 @@ def __init_subclass__(cls) -> None:
METACELL_PARAMS_CTX[cls] = ContextVar(f"$MetadataParam${cls.__module__}::{cls.__qualname__}", default=None)
super().__init_subclass__()

@classmethod
def inh(cls: type[_MetadataT1], operator: Callable[[_MetadataT1], T]) -> FieldReference[_MetadataT1, T]:
return FieldReference(cls, operator)
if TYPE_CHECKING:
@classmethod
def inh(cls: type[_MetadataT1]) -> _MetadataT1:
...
else:
@classmethod
def inh(cls: type[_MetadataT1]) -> FieldReference[_MetadataT1]:
return FieldReference(cls)

@classmethod
def get_params(cls) -> dict[str, Any] | None:
Expand Down Expand Up @@ -129,38 +133,75 @@ def clear_params(self) -> None:
for cell in self.cells:
cell.clear_params()

@property
def _(self: MetadataRoute[Unpack[tuple[Any, ...]], _MetadataT1]):
@_GetItemAgent
def wrapper(operator: Callable[[_MetadataT1], T]) -> FieldReference[_MetadataT1, T]:
return FieldReference(self, operator)

return wrapper
if TYPE_CHECKING:
@property
def inh(self: MetadataRoute[Unpack[tuple[Any, ...]], _MetadataT1]) -> _MetadataT1:
...
else:
@property
def inh(self: MetadataRoute[Unpack[tuple[Any, ...]], _MetadataT1]) -> RouteFieldReference[_MetadataT1]:
return RouteFieldReference(self)

def has_params(self) -> bool:
return any(cell.has_params() for cell in self.cells)


class FieldReference(Generic[_MetadataT1, T]):
define: type[_MetadataT1] | MetadataRoute[Unpack[tuple[Any, ...]], _MetadataT1]
class FieldReference(Generic[_MetadataT1]):
def __init__(self, define: type[_MetadataT1]) -> None:
self.__define = define
self.__steps: list[str] = []

def __hash__(self):
return hash(self.__define) + hash(".".join(self.__steps)) + hash("FieldReference")

def __eq__(self, other):
return isinstance(other, FieldReference) and self.__hash__() == other.__hash__()

def __repr__(self) -> str:
return f"{self.__define.__name__}.{'.'.join(self.__steps)}"

def __getattr__(self, item: str) -> Self:
self.__steps.append(item)
return self

def __call__(self, *args: Any, **kwargs: Any) -> Self:
prev = self.__steps[-1]
self.__steps[-1] = f"{prev}({', '.join(repr(arg) for arg in args)}, {', '.join(f'{key}={repr(value)}' for key, value in kwargs.items())})"
return self

def __getitem__(self, item: Any) -> Self:
prev = self.__steps[-1]
self.__steps[-1] = f"{prev}[{repr(item)}]"
return self

def __init__(
self,
define: type[_MetadataT1] | MetadataRoute[Unpack[tuple[Any, ...]], _MetadataT1],
operator: Callable[[_MetadataT1], T]
) -> None:

self.define = define
self.operator = cast(FunctionType, operator)
class RouteFieldReference(Generic[_MetadataT1]):
def __init__(self, define: MetadataRoute[Unpack[tuple[Any, ...]], _MetadataT1]) -> None:
self.__define = define
self.__steps: list[str] = []

def __hash__(self):
return hash(self.define) + hash(self.operator.__code__) + hash("FieldReference")
return hash(self.__define) + hash(".".join(self.__steps)) + hash("RouteFieldReference")

def __eq__(self, other):
return isinstance(other, FieldReference) and self.__hash__() == other.__hash__()
return isinstance(other, RouteFieldReference) and self.__hash__() == other.__hash__()

def __repr__(self) -> str:
return f"FieldReference[{self.define.__repr__()}]"
return f"{self.__define.__repr__()}.{'.'.join(self.__steps)}"

def __getattr__(self, item: str) -> Self:
self.__steps.append(item)
return self

def __call__(self, *args: Any, **kwargs: Any) -> Self:
prev = self.__steps[-1]
self.__steps[-1] = f"{prev}({', '.join(repr(arg) for arg in args)}, {', '.join(f'{key}={repr(value)}' for key, value in kwargs.items())})"
return self

def __getitem__(self, item: Any) -> Self:
prev = self.__steps[-1]
self.__steps[-1] = f"{prev}[{repr(item)}]"
return self


Route = Union[type[Metadata], MetadataRoute]
4 changes: 2 additions & 2 deletions avilla/elizabeth/perform/event/friend.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ async def friend_input_status_changed(self, raw_event: dict):
friend,
InputtingStatus,
{
InputtingStatus.inh(lambda x: x.value): ModifyDetail(
InputtingStatus.inh().value: ModifyDetail(
"update", raw_event["inputting"], not raw_event["inputting"]
)
},
Expand Down Expand Up @@ -68,7 +68,7 @@ async def friend_nick_changed(self, raw_event: dict):
context,
friend,
Nick,
{Nick.inh(lambda x: x.name): ModifyDetail("update", raw_event["to"], raw_event["from"])},
{Nick.inh().name: ModifyDetail("update", raw_event["to"], raw_event["from"])},
operator=friend,
scene=friend,
)
18 changes: 9 additions & 9 deletions avilla/elizabeth/perform/event/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ async def bot_group_permission_change(self, raw_event: dict):
group.member(account_route["account"]),
Privilege,
{
Privilege.inh(lambda x: x.available): ModifyDetail("update", available, not available),
Privilege.inh(lambda x: x.effective): ModifyDetail("update", available, not available),
Privilege.inh().available: ModifyDetail("update", available, not available),
Privilege.inh().effective: ModifyDetail("update", available, not available),
},
operator=operator,
scene=group,
Expand Down Expand Up @@ -112,8 +112,8 @@ async def bot_mute(self, raw_event: dict):
group.member(account_route["account"]),
MuteInfo,
{
MuteInfo.inh(lambda x: x.muted): ModifyDetail("update", True, False),
MuteInfo.inh(lambda x: x.duration): ModifyDetail(
MuteInfo.inh().muted: ModifyDetail("update", True, False),
MuteInfo.inh().duration: ModifyDetail(
"set", timedelta(seconds=raw_event["durationSeconds"]), None
),
},
Expand Down Expand Up @@ -164,8 +164,8 @@ async def bot_unmute(self, raw_event: dict):
group.member(account_route["account"]),
MuteInfo,
{
MuteInfo.inh(lambda x: x.muted): ModifyDetail("update", False, True),
MuteInfo.inh(lambda x: x.duration): ModifyDetail("clear", timedelta(seconds=0)),
MuteInfo.inh().muted: ModifyDetail("update", False, True),
MuteInfo.inh().duration: ModifyDetail("clear", timedelta(seconds=0)),
},
operator=operator,
scene=group,
Expand Down Expand Up @@ -213,7 +213,7 @@ async def group_name_change(self, raw_event: dict):
context,
group,
Summary,
{Summary.inh(lambda x: x.name): ModifyDetail("update", raw_event["current"], raw_event["origin"])},
{Summary.inh().name: ModifyDetail("update", raw_event["current"], raw_event["origin"])},
operator=operator or group.member(account_route["account"]),
scene=group,
)
Expand Down Expand Up @@ -261,7 +261,7 @@ async def group_mute_all(self, raw_event: dict):
group,
MuteInfo,
{
MuteInfo.inh(lambda x: x.muted): ModifyDetail("update", raw_event["current"], raw_event["origin"]),
MuteInfo.inh().muted: ModifyDetail("update", raw_event["current"], raw_event["origin"]),
},
operator=operator or group.member(account_route["account"]), # bot self if no operator
scene=group,
Expand Down Expand Up @@ -310,7 +310,7 @@ async def group_entrance_announcement_change(self, raw_event: dict):
group,
Announcement,
{
Announcement.inh(lambda x: x.content): ModifyDetail(
Announcement.inh().content: ModifyDetail(
"update", raw_event["current"], raw_event["origin"]
),
},
Expand Down
20 changes: 11 additions & 9 deletions avilla/elizabeth/perform/event/member.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ async def member_card_change(self, raw_event: dict):
context,
member,
Nick,
{Nick.inh(lambda x: x.nickname): ModifyDetail("update", raw_event["current"], raw_event["origin"])},
{
Nick.inh().nickname: ModifyDetail("update", raw_event["current"], raw_event["origin"])
},
operator=operator or group.member(account_route["account"]),
scene=group,
)
Expand Down Expand Up @@ -142,7 +144,7 @@ async def member_special_title_change(self, raw_event: dict):
context,
member,
Nick,
{Nick.inh(lambda x: x.badge): ModifyDetail("update", raw_event["current"], raw_event["origin"])},
{Nick.inh().badge: ModifyDetail("update", raw_event["current"], raw_event["origin"])},
operator=operator,
scene=group,
)
Expand Down Expand Up @@ -210,8 +212,8 @@ async def member_permission_change(self, raw_event: dict):
member,
Privilege,
{
Privilege.inh(lambda x: x.available): ModifyDetail("update", available, not available),
Privilege.inh(lambda x: x.effective): ModifyDetail("update", available, not available),
Privilege.inh().available: ModifyDetail("update", available, not available),
Privilege.inh().effective: ModifyDetail("update", available, not available),
},
operator=operator,
scene=group,
Expand Down Expand Up @@ -276,8 +278,8 @@ async def member_mute(self, raw_event: dict):
member,
MuteInfo,
{
MuteInfo.inh(lambda x: x.muted): ModifyDetail("update", True, False),
MuteInfo.inh(lambda x: x.duration): ModifyDetail(
MuteInfo.inh().muted: ModifyDetail("update", True, False),
MuteInfo.inh().duration: ModifyDetail(
"set", timedelta(seconds=raw_event["durationSeconds"]), None
),
},
Expand Down Expand Up @@ -344,8 +346,8 @@ async def member_unmute(self, raw_event: dict):
member,
MuteInfo,
{
MuteInfo.inh(lambda x: x.muted): ModifyDetail("update", False, True),
MuteInfo.inh(lambda x: x.duration): ModifyDetail("set", timedelta(seconds=0)),
MuteInfo.inh().muted: ModifyDetail("update", False, True),
MuteInfo.inh().duration: ModifyDetail("set", timedelta(seconds=0)),
},
operator=operator or group.member(account_route["account"]),
scene=group,
Expand Down Expand Up @@ -394,7 +396,7 @@ async def member_honor_change(self, raw_event: dict):
member,
Honor,
{
Honor.inh(lambda x: x.name): (
Honor.inh().name: (
ModifyDetail("set", raw_event["honor"], None)
if raw_event["action"] == "achieve"
else ModifyDetail("clear", None, raw_event["honor"])
Expand Down
Loading

0 comments on commit 554444e

Please sign in to comment.