26
26
from __future__ import annotations
27
27
28
28
import asyncio
29
- from collections .abc import Callable , Coroutine , Iterable
30
- from functools import partial
31
29
import logging
32
30
import struct
33
31
import sys
34
32
import time
33
+ from collections .abc import Callable , Coroutine , Iterable
34
+ from functools import partial
35
35
from typing import TYPE_CHECKING , Any , Generic , TypeVar , overload
36
36
37
37
from discord import utils
44
44
from typing_extensions import ParamSpec
45
45
46
46
from discord import abc
47
+
47
48
from ..voice .client import VoiceClient
48
49
49
- R = TypeVar ('R' )
50
- P = ParamSpec ('P' )
50
+ R = TypeVar ("R" )
51
+ P = ParamSpec ("P" )
51
52
52
53
__all__ = (
53
54
"Sink" ,
54
55
"RawData" ,
55
- ' SinkFilter' ,
56
- ' SinkHandler' ,
56
+ " SinkFilter" ,
57
+ " SinkHandler" ,
57
58
)
58
59
59
60
63
64
CREATE_NO_WINDOW = 0x08000000
64
65
65
66
66
- S = TypeVar ('S' , bound = ' Sink' )
67
+ S = TypeVar ("S" , bound = " Sink" )
67
68
_log = logging .getLogger (__name__ )
68
69
69
70
@@ -76,12 +77,16 @@ class SinkFilter(Generic[S]):
76
77
"""
77
78
78
79
@overload
79
- async def filter_packet (self , sink : S , user : abc .Snowflake , packet : RawData ) -> bool : ...
80
+ async def filter_packet (
81
+ self , sink : S , user : abc .Snowflake , packet : RawData
82
+ ) -> bool : ...
80
83
81
84
@overload
82
85
def filter_packet (self , sink : S , user : abc .Snowflake , packet : RawData ) -> bool : ...
83
86
84
- def filter_packet (self , sink : S , user : abc .Snowflake , packet : RawData ) -> bool | Coroutine [Any , Any , bool ]:
87
+ def filter_packet (
88
+ self , sink : S , user : abc .Snowflake , packet : RawData
89
+ ) -> bool | Coroutine [Any , Any , bool ]:
85
90
"""|maybecoro|
86
91
87
92
This is called automatically everytime a voice packet is received.
@@ -102,15 +107,21 @@ def filter_packet(self, sink: S, user: abc.Snowflake, packet: RawData) -> bool |
102
107
:class:`bool`
103
108
Whether the filter was successful.
104
109
"""
105
- raise NotImplementedError (' subclasses must implement this' )
110
+ raise NotImplementedError (" subclasses must implement this" )
106
111
107
112
@overload
108
- async def filter_speaking_state (self , sink : S , user : abc .Snowflake , before : SpeakingState , after : SpeakingState ) -> bool : ...
113
+ async def filter_speaking_state (
114
+ self , sink : S , user : abc .Snowflake , before : SpeakingState , after : SpeakingState
115
+ ) -> bool : ...
109
116
110
117
@overload
111
- def filter_speaking_state (self , sink : S , user : abc .Snowflake , before : SpeakingState , after : SpeakingState ) -> bool : ...
118
+ def filter_speaking_state (
119
+ self , sink : S , user : abc .Snowflake , before : SpeakingState , after : SpeakingState
120
+ ) -> bool : ...
112
121
113
- def filter_speaking_state (self , sink : S , user : abc .Snowflake , before : SpeakingState , after : SpeakingState ) -> bool | Coroutine [Any , Any , bool ]:
122
+ def filter_speaking_state (
123
+ self , sink : S , user : abc .Snowflake , before : SpeakingState , after : SpeakingState
124
+ ) -> bool | Coroutine [Any , Any , bool ]:
114
125
"""|maybecoro|
115
126
116
127
This is called automatically everytime a speaking state is updated.
@@ -133,11 +144,10 @@ def filter_speaking_state(self, sink: S, user: abc.Snowflake, before: SpeakingSt
133
144
:class:`bool`
134
145
Whether the filter was successful.
135
146
"""
136
- raise NotImplementedError (' subclasses must implement this' )
147
+ raise NotImplementedError (" subclasses must implement this" )
137
148
138
149
def cleanup (self ) -> None :
139
150
"""A function called when the filter is ready for cleanup."""
140
- pass
141
151
142
152
143
153
class SinkHandler (Generic [S ]):
@@ -149,12 +159,16 @@ class SinkHandler(Generic[S]):
149
159
"""
150
160
151
161
@overload
152
- async def handle_packet (self , sink : S , user : abc .Snowflake , packet : RawData ) -> Any : ...
162
+ async def handle_packet (
163
+ self , sink : S , user : abc .Snowflake , packet : RawData
164
+ ) -> Any : ...
153
165
154
166
@overload
155
167
def handle_packet (self , sink : S , user : abc .Snowflake , packet : RawData ) -> Any : ...
156
168
157
- def handle_packet (self , sink : S , user : abc .Snowflake , packet : RawData ) -> Any | Coroutine [Any , Any , Any ]:
169
+ def handle_packet (
170
+ self , sink : S , user : abc .Snowflake , packet : RawData
171
+ ) -> Any | Coroutine [Any , Any , Any ]:
158
172
"""|maybecoro|
159
173
160
174
This is called automatically everytime a voice packet which has successfully passed the filters is received.
@@ -168,15 +182,20 @@ def handle_packet(self, sink: S, user: abc.Snowflake, packet: RawData) -> Any |
168
182
packet: :class:`~.RawData`
169
183
The raw data packet.
170
184
"""
171
- pass
172
185
173
186
@overload
174
- async def handle_speaking_state (self , sink : S , user : abc .Snowflake , before : SpeakingState , after : SpeakingState ) -> Any : ...
187
+ async def handle_speaking_state (
188
+ self , sink : S , user : abc .Snowflake , before : SpeakingState , after : SpeakingState
189
+ ) -> Any : ...
175
190
176
191
@overload
177
- def handle_speaking_state (self , sink : S , user : abc .Snowflake , before : SpeakingState , after : SpeakingState ) -> Any : ...
192
+ def handle_speaking_state (
193
+ self , sink : S , user : abc .Snowflake , before : SpeakingState , after : SpeakingState
194
+ ) -> Any : ...
178
195
179
- def handle_speaking_state (self , sink : S , user : abc .Snowflake , before : SpeakingState , after : SpeakingState ) -> Any | Coroutine [Any , Any , Any ]:
196
+ def handle_speaking_state (
197
+ self , sink : S , user : abc .Snowflake , before : SpeakingState , after : SpeakingState
198
+ ) -> Any | Coroutine [Any , Any , Any ]:
180
199
"""|maybecoro|
181
200
182
201
This is called automatically everytime a speaking state update is received which has successfully passed the filters.
@@ -192,11 +211,9 @@ def handle_speaking_state(self, sink: S, user: abc.Snowflake, before: SpeakingSt
192
211
after: :class:`~discord.SpeakingState`
193
212
The speaking state after the update.
194
213
"""
195
- pass
196
214
197
215
def cleanup (self ) -> None :
198
216
"""A function called when the handler is ready for cleanup."""
199
- pass
200
217
201
218
202
219
class RawData :
@@ -340,10 +357,12 @@ def __init_subclass__(cls) -> None:
340
357
elif isinstance (value , classmethod ):
341
358
value = partial (value .__func__ , cls )
342
359
343
- if not hasattr (value , ' __listener__' ):
360
+ if not hasattr (value , " __listener__" ):
344
361
continue
345
362
346
- event_name = getattr (value , '__listener_name__' , elem ).removeprefix ('on_' )
363
+ event_name = getattr (value , "__listener_name__" , elem ).removeprefix (
364
+ "on_"
365
+ )
347
366
348
367
try :
349
368
listeners [event_name ].append (value )
@@ -364,7 +383,9 @@ def __init__(
364
383
self ._filters : list [SinkFilter ] = filters or []
365
384
self ._handlers : list [SinkHandler ] = handlers or []
366
385
self .__dispatch_set : set [asyncio .Task [Any ]] = set ()
367
- self ._listeners : dict [str , list [Callable [[Iterable [object ]], bool ]]] = self .__listeners__
386
+ self ._listeners : dict [str , list [Callable [[Iterable [object ]], bool ]]] = (
387
+ self .__listeners__
388
+ )
368
389
369
390
@property
370
391
def filtering_mode (self ) -> SinkFilteringMode :
@@ -377,13 +398,15 @@ def filtering_mode(self, value: SinkFilteringMode) -> None:
377
398
elif value is SinkFilteringMode .any :
378
399
self ._filter_strat = any
379
400
else :
380
- raise TypeError (f'expected a FilteringMode enum member, got { value .__class__ .__name__ } ' )
401
+ raise TypeError (
402
+ f"expected a FilteringMode enum member, got { value .__class__ .__name__ } "
403
+ )
381
404
382
405
self .__filtering_mode = value
383
406
384
407
def dispatch (self , event : str , * args : Any , ** kwargs : Any ) -> Any :
385
- _log .debug (' Dispatching sink %s event %s' , self .__class__ .__name__ , event )
386
- method = f' on_{ event } '
408
+ _log .debug (" Dispatching sink %s event %s" , self .__class__ .__name__ , event )
409
+ method = f" on_{ event } "
387
410
388
411
listeners = self .__listeners__ .get (event , [])
389
412
for coro in listeners :
@@ -401,7 +424,7 @@ async def _run_event(
401
424
coro : Callable [..., Coroutine [Any , Any , Any ]],
402
425
event_name : str ,
403
426
* args : Any ,
404
- ** kwargs : Any
427
+ ** kwargs : Any ,
405
428
) -> None :
406
429
try :
407
430
await coro (* args , ** kwargs )
@@ -426,7 +449,9 @@ def _call_voice_packet_handlers(self, user: abc.Snowflake, packet: RawData) -> N
426
449
self .__dispatch_set .add (task )
427
450
task .add_done_callback (self .__dispatch_set .remove )
428
451
429
- def _call_speaking_state_handlers (self , user : abc .Snowflake , before : SpeakingState , after : SpeakingState ) -> None :
452
+ def _call_speaking_state_handlers (
453
+ self , user : abc .Snowflake , before : SpeakingState , after : SpeakingState
454
+ ) -> None :
430
455
for handler in self ._handlers :
431
456
task = asyncio .create_task (
432
457
utils .maybe_coroutine (
@@ -449,13 +474,13 @@ def _schedule_event(
449
474
) -> asyncio .Task :
450
475
wrapped = self ._run_event (coro , event_name , * args , ** kwargs )
451
476
452
- task = asyncio .create_task (wrapped , name = f' sinks: { event_name } ' )
477
+ task = asyncio .create_task (wrapped , name = f" sinks: { event_name } " )
453
478
self .__dispatch_set .add (task )
454
479
task .add_done_callback (self .__dispatch_set .discard )
455
480
return task
456
481
457
482
def __repr__ (self ) -> str :
458
- return f' <{ self .__class__ .__name__ } id={ id (self ):#x} >'
483
+ return f" <{ self .__class__ .__name__ } id={ id (self ):#x} >"
459
484
460
485
def stop (self ) -> None :
461
486
"""Stops this sink's recording.
@@ -499,7 +524,9 @@ def add_filter(self, filter: SinkFilter, /) -> None:
499
524
"""
500
525
501
526
if not isinstance (filter , SinkFilter ):
502
- raise TypeError (f'expected a Filter object, not { filter .__class__ .__name__ } ' )
527
+ raise TypeError (
528
+ f"expected a Filter object, not { filter .__class__ .__name__ } "
529
+ )
503
530
self ._filters .append (filter )
504
531
505
532
def remove_filter (self , filter : SinkFilter , / ) -> None :
@@ -531,7 +558,9 @@ def add_handler(self, handler: SinkHandler, /) -> None:
531
558
"""
532
559
533
560
if not isinstance (handler , SinkHandler ):
534
- raise TypeError (f'expected a Handler object, not { handler .__class__ .__name__ } ' )
561
+ raise TypeError (
562
+ f"expected a Handler object, not { handler .__class__ .__name__ } "
563
+ )
535
564
self ._handlers .append (handler )
536
565
537
566
def remove_handler (self , handler : SinkHandler , / ) -> None :
@@ -549,22 +578,16 @@ def remove_handler(self, handler: SinkHandler, /) -> None:
549
578
pass
550
579
551
580
@staticmethod
552
- def listener (event : str = MISSING ) -> Callable [[Callable [P , Coroutine [Any , Any , R ]]], Callable [P , Coroutine [Any , Any , R ]]]:
581
+ def listener (
582
+ event : str = MISSING ,
583
+ ) -> Callable [
584
+ [Callable [P , Coroutine [Any , Any , R ]]], Callable [P , Coroutine [Any , Any , R ]]
585
+ ]:
553
586
"""Registers a function to be an event listener for this sink.
554
587
555
588
The events must be a :ref:`coroutine <coroutine>`, if not, :exc:`TypeError` is raised; and
556
589
also must be inside a sink class.
557
590
558
- Example
559
- -------
560
-
561
- .. code-block:: python3
562
-
563
- class MySink(Sink):
564
- @Sink.listener()
565
- async def on_member_speaking_state_update(member, ssrc, state):
566
- pass
567
-
568
591
Parameters
569
592
----------
570
593
event: :class:`str`
@@ -574,41 +597,64 @@ async def on_member_speaking_state_update(member, ssrc, state):
574
597
------
575
598
TypeError
576
599
The coroutine passed is not actually a coroutine, or the listener is not in a sink class.
600
+
601
+ Example
602
+ -------
603
+
604
+ .. code-block:: python3
605
+
606
+ class MySink(Sink):
607
+ @Sink.listener()
608
+ async def on_member_speaking_state_update(member, ssrc, state):
609
+ pass
577
610
"""
578
611
579
- def decorator (func : Callable [P , Coroutine [Any , Any , R ]]) -> Callable [P , Coroutine [Any , Any , R ]]:
580
- parts = func .__qualname__ .split ('.' )
612
+ def decorator (
613
+ func : Callable [P , Coroutine [Any , Any , R ]],
614
+ ) -> Callable [P , Coroutine [Any , Any , R ]]:
615
+ parts = func .__qualname__ .split ("." )
581
616
582
617
if not parts or not len (parts ) > 1 :
583
- raise TypeError (' event listeners must be declared in a Sink class' )
618
+ raise TypeError (" event listeners must be declared in a Sink class" )
584
619
585
620
if parts [- 1 ] != func .__name__ :
586
- raise NameError ('qualified name and function name mismatch, this should not happen' )
621
+ raise NameError (
622
+ "qualified name and function name mismatch, this should not happen"
623
+ )
587
624
588
625
if not asyncio .iscoroutinefunction (func ):
589
- raise TypeError (' event listeners must be coroutine functions' )
626
+ raise TypeError (" event listeners must be coroutine functions" )
590
627
591
628
func .__listener__ = True
592
629
if event is not MISSING :
593
630
func .__listener_name__ = event
594
631
return func
632
+
595
633
return decorator
596
634
597
635
async def on_voice_packet_receive (self , user : abc .Snowflake , data : RawData ) -> None :
598
636
pass
599
637
600
- async def on_unfiltered_voice_packet_receive (self , user : abc .Snowflake , data : RawData ) -> None :
638
+ async def on_unfiltered_voice_packet_receive (
639
+ self , user : abc .Snowflake , data : RawData
640
+ ) -> None :
601
641
pass
602
642
603
- async def on_speaking_state_update (self , user : abc .Snowflake , before : SpeakingState , after : SpeakingState ) -> None :
643
+ async def on_speaking_state_update (
644
+ self , user : abc .Snowflake , before : SpeakingState , after : SpeakingState
645
+ ) -> None :
604
646
pass
605
647
606
- async def on_unfiltered_speaking_state_update (self , user : abc .Snowflake , before : SpeakingState , after : SpeakingState ) -> None :
648
+ async def on_unfiltered_speaking_state_update (
649
+ self , user : abc .Snowflake , before : SpeakingState , after : SpeakingState
650
+ ) -> None :
607
651
pass
608
652
609
- async def on_error (self , event : str , exception : Exception , * args : Any , ** kwargs : Any ) -> None :
653
+ async def on_error (
654
+ self , event : str , exception : Exception , * args : Any , ** kwargs : Any
655
+ ) -> None :
610
656
_log .exception (
611
- ' An error ocurred in sink %s while dispatching the event %s' ,
657
+ " An error ocurred in sink %s while dispatching the event %s" ,
612
658
self ,
613
659
event ,
614
660
exc_info = exception ,
0 commit comments