1+ import traceback
12from abc import ABC
3+ from typing import Any
4+
25import yaml
36
47import discord
58from utils .database import database
6- from discord import Interaction
9+ from . import embed_factory as ef
10+ from discord import Interaction , ApplicationContext , DiscordException
711
812
913class AdvContext (discord .ApplicationContext ):
@@ -29,12 +33,85 @@ class AdvContext(discord.ApplicationContext):
2933class SurveyWolf (discord .Bot , ABC ):
3034 def __init__ (self , description = None , * args , ** options ):
3135 super ().__init__ (description = description , * args , ** options )
36+ self ._did_on_ready = False
3237
3338 with open ("config.yaml" ) as stream :
3439 config = yaml .safe_load (stream )
3540
36- self .ERROR_LOGGING_WEBHOOK = config ["error_logging_webhook" ]
37- self .SERVER_JOIN_LEAVE_WEBHOOK = config ["server_join_leave_webhook" ]
41+ self ._raw_config = config
42+ self .config = self ._raw_config .copy ()
43+
44+ async def on_ready (self ):
45+ if self ._did_on_ready :
46+ return
47+ self ._did_on_ready = True
48+ # Do Some Additional Processing On Some Config Items
49+ self .config .update (
50+ {
51+ "error_logging_webhook" : await self ._create_webhook (self .config ["error_logging_webhook" ]),
52+ "server_join_leave_webhook" : await self ._create_webhook (self .config ["server_join_leave_webhook" ]),
53+ }
54+ )
55+
56+ async def _create_webhook (self , url : str ) -> discord .Webhook | None :
57+ if url == "None" :
58+ return None
59+
60+ try :
61+ return await self .fetch_webhook (discord .Webhook .from_url (url , session = self .http ._HTTPClient__session ).id )
62+ except discord .NotFound :
63+ return None
64+
65+ def update_config (self , key : str , value , raw = None ) -> None :
66+ """
67+ Updates the config with the key and value. Updates the config file with the raw value
68+ :param key: The Config Key
69+ :param value: The Value The Bot Should Retrieve
70+ :param raw: The Value That Should Be Stored In The Config File. Defaults To `value`
71+ """
72+ if raw is None :
73+ raw = value
74+
75+ self ._raw_config [key ] = raw
76+ with open ("config.yaml" , "w" ) as stream :
77+ yaml .safe_dump (self ._raw_config , stream )
78+ self .config [key ] = value
3879
3980 async def get_application_context (self , interaction : Interaction , cls = None ) -> discord .ApplicationContext :
4081 return await super ().get_application_context (interaction , cls = cls or AdvContext )
82+
83+ @staticmethod
84+ def _split_text (text : str , max_length : int , newline : bool = False ) -> list [str ]:
85+ texts = []
86+ while len (text ) > max_length :
87+ if newline :
88+ try :
89+ ind = text [:max_length ].rindex ("\n " )
90+ except ValueError :
91+ # No newline was found so fall back to character count
92+ ind = max_length
93+ else :
94+ ind = max_length
95+
96+ texts .append (text [:ind ])
97+ # The +1 is to remove the newline character
98+ text = text [ind + 1 :]
99+ texts .append (text )
100+ return texts
101+
102+ async def on_application_command_error (self , ctx : ApplicationContext , exception : DiscordException ) -> None :
103+ if (w := self .config ["error_logging_webhook" ]) is not None :
104+ text = f"Error In { ctx .command .qualified_name } Guild ID: { ctx .guild_id } Channel ID: { ctx .channel_id } \n "
105+ text += "" .join (traceback .format_exception (type (exception ), exception , exception .__traceback__ ))
106+ for i in self ._split_text (text , 1990 , newline = True ):
107+ await w .send (f"```py\n { i } \n ```" )
108+ await ctx .respond (embed = await ef .error ("An Error Occurred" ))
109+ raise exception
110+
111+ async def on_error (self , event_method : str , * args : Any , ** kwargs : Any ) -> None :
112+ if (w := self .config ["error_logging_webhook" ]) is not None :
113+ text = "Error In " + event_method + "\n "
114+ text += traceback .format_exc ()
115+ for i in self ._split_text (text , 1990 , newline = True ):
116+ await w .send (f"```py\n { i } \n ```" )
117+ traceback .print_exc ()
0 commit comments