2525from .dispatch import Listener
2626from .enums import OpCodeType
2727from .error import GatewayException
28- from .http import HTTPClient
28+ from .http . client import HTTPClient
2929from .models .flags import Intents
3030from .models .misc import MISSING
3131from .models .presence import ClientPresence
3232
3333log = get_logger ("gateway" )
3434
35-
3635__all__ = ("_Heartbeat" , "WebSocketClient" )
3736
3837
@@ -280,7 +279,7 @@ async def wait_until_ready(self):
280279 """Waits for the client to become ready according to the Gateway."""
281280 await self .ready .wait ()
282281
283- def _dispatch_event (self , event : str , data : dict ) -> None :
282+ def _dispatch_event (self , event : str , data : dict ) -> None : # sourcery no-metrics
284283 """
285284 Dispatches an event from the Gateway.
286285
@@ -291,97 +290,88 @@ def _dispatch_event(self, event: str, data: dict) -> None:
291290 """
292291 path : str = "interactions"
293292 path += ".models" if event == "INTERACTION_CREATE" else ".api.models"
294-
295- if event != "TYPING_START" :
296- if event != "INTERACTION_CREATE" :
297- name : str = event .lower ()
298- try :
299- _event_path : list = [section .capitalize () for section in name .split ("_" )]
300- _name : str = (
301- _event_path [0 ] if len (_event_path ) < 3 else "" .join (_event_path [:- 1 ])
302- )
303- __obj : object = getattr (__import__ (path ), _name )
304-
305- if name in {"_create" , "_add" }:
306- data ["_client" ] = self ._http
307-
308- self ._dispatch .dispatch (f"on_{ name } " , __obj (** data )) # noqa
309- except AttributeError as error :
310- log .fatal (f"An error occured dispatching { name } : { error } " )
293+ if event == "INTERACTION_CREATE" :
294+ if not data .get ("type" ):
295+ log .warning (
296+ "Context is being created for the interaction, but no type is specified. Skipping..."
297+ )
311298 else :
312- if not data .get ("type" ):
313- log .warning (
314- "Context is being created for the interaction, but no type is specified. Skipping..."
315- )
316- else :
317- _context = self .__contextualize (data )
318- _name : str = ""
319- __args : list = [_context ]
320- __kwargs : dict = {}
321-
322- if data ["type" ] == InteractionType .APPLICATION_COMMAND :
323- _name = f"command_{ _context .data .name } "
324-
325- if _context .data ._json .get ("options" ):
326- for option in _context .data .options :
327- _type = self .__option_type_context (
328- _context ,
329- (
330- option ["type" ]
331- if isinstance (option , dict )
332- else option .type .value
333- ),
334- )
335- if _type :
336- if isinstance (option , dict ):
337- _type [option ["value" ]]._client = self ._http
338- option .update ({"value" : _type [option ["value" ]]})
339- else :
340- _type [option .value ]._client = self ._http
341- option ._json .update ({"value" : _type [option .value ]})
342- _option = self .__sub_command_context (option , _context )
343- __kwargs .update (_option )
344-
345- self ._dispatch .dispatch ("on_command" , _context )
346- elif data ["type" ] == InteractionType .MESSAGE_COMPONENT :
347- _name = f"component_{ _context .data .custom_id } "
348-
349- if _context .data ._json .get ("values" ):
350- __args .append (_context .data .values )
351-
352- self ._dispatch .dispatch ("on_component" , _context )
353- elif data ["type" ] == InteractionType .APPLICATION_COMMAND_AUTOCOMPLETE :
354- _name = f"autocomplete_{ _context .data .id } "
355-
356- if _context .data ._json .get ("options" ):
357- for option in _context .data .options :
358- __name , _value = self .__sub_command_context (option , _context )
359- _name += f"_{ __name } " if __name else ""
360-
361- if _value :
362- __args .append (_value )
363-
364- self ._dispatch .dispatch ("on_autocomplete" , _context )
365- elif data ["type" ] == InteractionType .MODAL_SUBMIT :
366- _name = f"modal_{ _context .data .custom_id } "
367-
368- if _context .data ._json .get ("components" ):
369- for component in _context .data .components :
370- if component .get ("components" ):
371- __args .append (
372- [_value ["value" ] for _value in component ["components" ]][0 ]
373- )
299+ # sourcery skip: extract-method
300+ _context = self .__contextualize (data )
301+ _name : str = ""
302+ __args : list = [_context ]
303+ __kwargs : dict = {}
304+
305+ if data ["type" ] == InteractionType .APPLICATION_COMMAND :
306+ _name = f"command_{ _context .data .name } "
307+
308+ if _context .data ._json .get ("options" ):
309+ for option in _context .data .options :
310+ _type = self .__option_type_context (
311+ _context ,
312+ (option ["type" ] if isinstance (option , dict ) else option .type .value ),
313+ )
314+ if _type :
315+ if isinstance (option , dict ):
316+ _type [option ["value" ]]._client = self ._http
317+ option .update ({"value" : _type [option ["value" ]]})
374318 else :
375- __args .append (
376- [_value .value for _value in component .components ][0 ]
377- )
378-
379- self ._dispatch .dispatch ("on_modal" , _context )
380-
381- self ._dispatch .dispatch (_name , * __args , ** __kwargs )
382- self ._dispatch .dispatch ("on_interaction" , _context )
383- self ._dispatch .dispatch ("on_interaction_create" , _context )
384-
319+ _type [option .value ]._client = self ._http
320+ option ._json .update ({"value" : _type [option .value ]})
321+ _option = self .__sub_command_context (option , _context )
322+ __kwargs .update (_option )
323+
324+ self ._dispatch .dispatch ("on_command" , _context )
325+ elif data ["type" ] == InteractionType .MESSAGE_COMPONENT :
326+ _name = f"component_{ _context .data .custom_id } "
327+
328+ if _context .data ._json .get ("values" ):
329+ __args .append (_context .data .values )
330+
331+ self ._dispatch .dispatch ("on_component" , _context )
332+ elif data ["type" ] == InteractionType .APPLICATION_COMMAND_AUTOCOMPLETE :
333+ _name = f"autocomplete_{ _context .data .id } "
334+
335+ if _context .data ._json .get ("options" ):
336+ for option in _context .data .options :
337+ __name , _value = self .__sub_command_context (option , _context )
338+ _name += f"_{ __name } " if __name else ""
339+
340+ if _value :
341+ __args .append (_value )
342+
343+ self ._dispatch .dispatch ("on_autocomplete" , _context )
344+ elif data ["type" ] == InteractionType .MODAL_SUBMIT :
345+ _name = f"modal_{ _context .data .custom_id } "
346+
347+ if _context .data ._json .get ("components" ):
348+ for component in _context .data .components :
349+ if component .get ("components" ):
350+ __args .append (
351+ [_value ["value" ] for _value in component ["components" ]][0 ]
352+ )
353+ else :
354+ __args .append ([_value .value for _value in component .components ][0 ])
355+
356+ self ._dispatch .dispatch ("on_modal" , _context )
357+
358+ self ._dispatch .dispatch (_name , * __args , ** __kwargs )
359+ self ._dispatch .dispatch ("on_interaction" , _context )
360+ self ._dispatch .dispatch ("on_interaction_create" , _context )
361+ elif event != "TYPING_START" :
362+ name : str = event .lower ()
363+ try :
364+ _event_path : list = [section .capitalize () for section in name .split ("_" )]
365+ _name : str = _event_path [0 ] if len (_event_path ) < 3 else "" .join (_event_path [:- 1 ])
366+ __obj : object = getattr (__import__ (path ), _name )
367+
368+ # name in {"_create", "_add"} returns False (tested w message_create)
369+ if any (_ in name for _ in {"_create" , "_update" , "_add" , "_remove" , "_delete" }):
370+ data ["_client" ] = self ._http
371+
372+ self ._dispatch .dispatch (f"on_{ name } " , __obj (** data )) # noqa
373+ except AttributeError as error :
374+ log .fatal (f"An error occured dispatching { name } : { error } " )
385375 self ._dispatch .dispatch ("raw_socket_create" , data )
386376
387377 def __contextualize (self , data : dict ) -> object :
@@ -621,3 +611,20 @@ def shard(self) -> Optional[List[Tuple[int]]]:
621611 def presence (self ) -> Optional [ClientPresence ]:
622612 """Returns the current presence."""
623613 return self .__presence
614+
615+ async def _update_presence (self , presence : ClientPresence ) -> None :
616+ """
617+ Sends an ``UPDATE_PRESENCE`` packet to the gateway.
618+
619+ .. note::
620+ There is a ratelimit to using this method (5 per minute).
621+ As there's no gateway ratelimiter yet, breaking this ratelimit
622+ will force your bot to disconnect.
623+
624+ :param presence: The presence to change the bot to on identify.
625+ :type presence: ClientPresence
626+ """
627+ payload : dict = {"op" : OpCodeType .PRESENCE , "d" : presence ._json }
628+ await self ._send_packet (payload )
629+ log .debug (f"UPDATE_PRESENCE: { presence ._json } " )
630+ self .__presence = presence
0 commit comments