77
88from db import GroupMessage
99
10- E = TypeVar ('E' , bound = "Element" )
10+ E = TypeVar ("E" , bound = "Element" )
1111
1212
1313class ElementRegistry :
14+ """
15+ A registry for managing and decoding elements based on their IDs.
16+
17+ Attributes:
18+ _decoders (defaultdict): A dictionary mapping element IDs to their corresponding decoder classes.
19+
20+ Methods:
21+ register(elem_id: int) -> callable:
22+ A class method that registers a decoder class for a given element ID.
23+
24+ decode(data) -> E:
25+ A class method that decodes the given data using the registered decoder class for the element ID.
26+ """
27+
1428 _decoders = defaultdict (lambda : UnsupportedElement )
1529
1630 @classmethod
1731 def register (cls , elem_id : int ) -> callable :
32+ """
33+ Registers a class as a decoder for a specific element ID.
34+
35+ This method is intended to be used as a decorator to register a class
36+ that can decode messages of a specific type identified by `elem_id`.
37+
38+ Args:
39+ elem_id (int): The element ID to register the class for.
40+
41+ Example:
42+ @ElementRegistry.register(elem_id=10)
43+ class SomeElement(Element):
44+ @classmethod
45+ def decode(cls, data):
46+ return SomeElement()
47+ """
48+
1849 def decorator (element_class : Type [E ]) -> Type [E ]:
1950 cls ._decoders [elem_id ] = element_class
2051 return element_class
@@ -23,35 +54,83 @@ def decorator(element_class: Type[E]) -> Type[E]:
2354
2455 @classmethod
2556 def decode (cls , data ) -> E :
57+ """
58+ Decodes the given data using the appropriate decoder.
59+
60+ Args:
61+ data (dict): The data to decode.
62+
63+ Returns:
64+ E: The decoded element if successful.
65+ UnsupportedElement: If decoding fails due to a ValueError.
66+ """
2667 try :
2768 return cls ._decoders [data .get ("45002" )].decode (data )
2869 except ValueError :
2970 return UnsupportedElement (data = None )
3071
3172
3273class Element (ABC , BaseModel ):
74+ """
75+ Abstract base class for elements, inheriting from ABC and BaseModel.
76+
77+ Methods:
78+ decode(cls, data) -> E:
79+ Decodes the given data into an instance of the element.
80+ Must be implemented by subclasses.
81+
82+ __str__(self):
83+ Returns a string representation of the element.
84+ Must be implemented by subclasses.
85+ """
3386 ...
3487
3588 @classmethod
3689 @abstractmethod
3790 def decode (cls , data ) -> E :
91+ """
92+ Abstract method to decode the given data into an instance of the element.
93+
94+ Args:
95+ data: The data to be decoded.
96+
97+ Returns:
98+ An instance of type E.
99+
100+ Raises:
101+ NotImplementedError: This method is not yet implemented.
102+ """
38103 raise NotImplementedError
39104
40105 @abstractmethod
41106 def __str__ (self ):
107+ """
108+ Return a string representation of the object.
109+ This method should be overridden by subclasses to provide a meaningful
110+ string representation of the object. If not implemented, it raises a
111+ NotImplementedError.
112+
113+ Returns:
114+ str: A string representation of the object.
115+
116+ Raises:
117+ NotImplementedError: If the method is not overridden by a subclass.
118+ """
119+
42120 raise NotImplementedError
43121
44122
45123class UnsupportedElement (Element ):
46- """ data is None when error raised in parsing, is dict when no parse function found """
124+ """data is None when error raised in parsing, is dict when no parse function found"""
125+
47126 data : dict | None
48127
49128 @classmethod
50129 def decode (cls , data ):
51130 return UnsupportedElement (data = data )
52131
53132 def __str__ (self ):
54- return "不支持的消息"
133+ return "[ 不支持的消息] "
55134
56135
57136@ElementRegistry .register (elem_id = 1 )
@@ -104,31 +183,30 @@ class FileElement(Element):
104183 hash : str | None
105184 path : str | None
106185
107-
108186 @classmethod
109187 def decode (cls , data ):
110188 return FileElement (
111- hash = hash .hex () if isinstance (hash := data .get ("45406" ), bytes ) else None ,
112- path = path .decode () if isinstance (path := data .get ("45954" ), bytes ) else None ,
189+ hash = hash .hex () if isinstance (hash := data .get ("45406" ), bytes ) else None ,
190+ path = (
191+ path .decode () if isinstance (path := data .get ("45954" ), bytes ) else None
192+ ),
113193 )
114194
115195 def __str__ (self ):
116196 return "[文件]"
117-
197+
118198
119199@ElementRegistry .register (elem_id = 4 )
120200class AudioElement (Element ):
121201 filename : str
122202 hash : str | None
123203
124-
125204 @classmethod
126205 def decode (cls , data ):
127206 return AudioElement (
128207 filename = data .get ("45402" ),
129- hash = hash .hex () if isinstance (hash := data .get ("45406" ), bytes ) else None ,
208+ hash = hash .hex () if isinstance (hash := data .get ("45406" ), bytes ) else None ,
130209 )
131-
132210
133211 def __str__ (self ):
134212 return "[语音消息]"
@@ -139,14 +217,12 @@ class VideoElement(Element):
139217 filename : str | None
140218 hash : str | None
141219
142-
143220 @classmethod
144221 def decode (cls , data ):
145222 return VideoElement (
146223 filename = data .get ("40402" ),
147- hash = hash .hex () if isinstance (hash := data .get ("45406" ), bytes ) else None
224+ hash = hash .hex () if isinstance (hash := data .get ("45406" ), bytes ) else None ,
148225 )
149-
150226
151227 def __str__ (self ):
152228 return "[视频消息]"
@@ -172,16 +248,18 @@ class Reply(Element):
172248 source_sender_uin : str | None
173249 source_sender_qq : int | None
174250 source_time : int | None
175- source_content : ' Message'
251+ source_content : " Message"
176252
177253 @classmethod
178254 def decode (cls , data ):
179255 return Reply (
180256 source_seq = data .get ("47402" ),
181- source_sender_uin = sender_uin if isinstance (sender_uin := data .get ("40020" ), str ) else None ,
257+ source_sender_uin = (
258+ sender_uin if isinstance (sender_uin := data .get ("40020" ), str ) else None
259+ ),
182260 source_sender_qq = data .get ("47403" ),
183261 source_time = data .get ("47404" ),
184- source_content = Message .from_reply (data .get ("47423" ))
262+ source_content = Message .from_reply (data .get ("47423" )),
185263 )
186264
187265 def __str__ (self ):
@@ -214,22 +292,23 @@ class WithdrawNotifyElement(SystemNotificationElement):
214292 @classmethod
215293 def system_decode (cls , data ):
216294 return WithdrawNotifyElement (
217- sender = sender if isinstance (sender := data .get ("47705" ), str ) else None ,
218- withdrawer = withdrawer if isinstance (withdrawer := data .get ("47716" ), str ) else None ,
219- suffix = suffix if (suffix := data .get ("47713" )) else None ,
295+ sender = sender if isinstance (sender := data .get ("47705" ), str ) else None ,
296+ withdrawer = (
297+ withdrawer if isinstance (withdrawer := data .get ("47716" ), str ) else None
298+ ),
299+ suffix = suffix if (suffix := data .get ("47713" )) else None ,
220300 )
221301
222302 def __str__ (self ):
223303 return "撤回了一条消息"
224-
304+
225305
226306@ElementRegistry .register (elem_id = 9 )
227307class RedPackElement (Element ):
228308 greet : str
229309 alt : str
230310 skin_type : str | None
231311
232-
233312 @classmethod
234313 def decode (cls , data ):
235314 desc = data .get ("48403" )
@@ -241,9 +320,13 @@ def decode(cls, data):
241320 return RedPackElement (
242321 greet = desc .get ("48443" ),
243322 alt = desc .get ("48448" ),
244- skin_type = skin_type if isinstance (skin_type := data .get ("48421" ).get ("5" ), str ) else None ,
323+ skin_type = (
324+ skin_type
325+ if isinstance (skin_type := data .get ("48421" ).get ("5" ), str )
326+ else None
327+ ),
245328 )
246-
329+
247330 def __str__ (self ):
248331 return self .alt
249332
@@ -254,9 +337,7 @@ class AppElement(Element):
254337
255338 @classmethod
256339 def decode (cls , data ):
257- return AppElement (
258- data = data .get ("47901" ).decode ()
259- )
340+ return AppElement (data = data .get ("47901" ).decode ())
260341
261342 def __str__ (self ):
262343 return "[应用消息]"
@@ -323,21 +404,19 @@ def decode(cls, data):
323404
324405 def __str__ (self ):
325406 return "[Bot卡片]"
326-
407+
327408
328409@ElementRegistry .register (elem_id = 21 )
329410class CallNotifyElement (Element ):
330411 alt_1 : str
331412 alt_2 : str
332413
333-
334414 @classmethod
335415 def decode (cls , data ):
336416 return CallNotifyElement (
337417 alt_1 = data .get ("48153" ),
338418 alt_2 = data .get ("48157" ),
339419 )
340-
341420
342421 def __str__ (self ):
343422 return self .alt_1
@@ -346,10 +425,10 @@ def __str__(self):
346425class Message (BaseModel ):
347426 ID : int | None
348427 seq : int | None
349- elements : List [' Element' ]
428+ elements : List [" Element" ]
350429
351430 @classmethod
352- def from_db (cls , dbo : GroupMessage ) -> ' Message' :
431+ def from_db (cls , dbo : GroupMessage ) -> " Message" :
353432 if dbo .message_body is None :
354433 elements = []
355434 else :
@@ -366,7 +445,7 @@ def from_db(cls, dbo: GroupMessage) -> 'Message':
366445 )
367446
368447 @classmethod
369- def from_reply (cls , embed ) -> ' Message' :
448+ def from_reply (cls , embed ) -> " Message" :
370449 if embed is None :
371450 embed = []
372451 if isinstance (embed , dict ):
0 commit comments