1- __version__ = "3.2.2 "
1+ __version__ = "3.3.0-dev1 "
22
33import asyncio
44import logging
1919from aiohttp import ClientSession
2020from emoji import UNICODE_EMOJI
2121from motor .motor_asyncio import AsyncIOMotorClient
22+ from pkg_resources import parse_version
2223from pymongo .errors import ConfigurationError
2324
2425try :
3233from core import checks
3334from core .clients import ApiClient , PluginDatabaseClient
3435from core .config import ConfigManager
35- from core .utils import human_join , strtobool , parse_alias
36+ from core .utils import human_join , parse_alias
3637from core .models import PermissionLevel , ModmailLogger , SafeFormatter
3738from core .thread import ThreadManager
3839from core .time import human_timedelta
@@ -70,6 +71,7 @@ def __init__(self):
7071 self ._api = None
7172 self .metadata_loop = None
7273 self .formatter = SafeFormatter ()
74+ self .loaded_cogs = ["cogs.modmail" , "cogs.plugins" , "cogs.utility" ]
7375
7476 self ._connected = asyncio .Event ()
7577 self .start_time = datetime .utcnow ()
@@ -97,17 +99,7 @@ def __init__(self):
9799 sys .exit (0 )
98100
99101 self .plugin_db = PluginDatabaseClient (self )
100-
101- logger .line ()
102- logger .info ("┌┬┐┌─┐┌┬┐┌┬┐┌─┐┬┬" )
103- logger .info ("││││ │ │││││├─┤││" )
104- logger .info ("┴ ┴└─┘─┴┘┴ ┴┴ ┴┴┴─┘" )
105- logger .info ("v%s" , __version__ )
106- logger .info ("Authors: kyb3r, fourjr, Taaku18" )
107- logger .line ()
108-
109- self ._load_extensions ()
110- logger .line ()
102+ self .startup ()
111103
112104 @property
113105 def uptime (self ) -> str :
@@ -123,6 +115,24 @@ def uptime(self) -> str:
123115
124116 return self .formatter .format (fmt , d = days , h = hours , m = minutes , s = seconds )
125117
118+ def startup (self ):
119+ logger .line ()
120+ logger .info ("┌┬┐┌─┐┌┬┐┌┬┐┌─┐┬┬" )
121+ logger .info ("││││ │ │││││├─┤││" )
122+ logger .info ("┴ ┴└─┘─┴┘┴ ┴┴ ┴┴┴─┘" )
123+ logger .info ("v%s" , __version__ )
124+ logger .info ("Authors: kyb3r, fourjr, Taaku18" )
125+ logger .line ()
126+
127+ for cog in self .loaded_cogs :
128+ logger .info ("Loading %s." , cog )
129+ try :
130+ self .load_extension (cog )
131+ logger .info ("Successfully loaded %s." , cog )
132+ except Exception :
133+ logger .exception ("Failed to load %s." , cog )
134+ logger .line ()
135+
126136 def _configure_logging (self ):
127137 level_text = self .config ["log_level" ].upper ()
128138 logging_levels = {
@@ -161,8 +171,8 @@ def _configure_logging(self):
161171 logger .debug ("Successfully configured logging." )
162172
163173 @property
164- def version (self ) -> str :
165- return __version__
174+ def version (self ):
175+ return parse_version ( __version__ )
166176
167177 @property
168178 def session (self ) -> ClientSession :
@@ -179,18 +189,6 @@ def api(self):
179189 async def get_prefix (self , message = None ):
180190 return [self .prefix , f"<@{ self .user .id } > " , f"<@!{ self .user .id } > " ]
181191
182- def _load_extensions (self ):
183- """Adds commands automatically"""
184- for file in os .listdir ("cogs" ):
185- if not file .endswith (".py" ):
186- continue
187- cog = f"cogs.{ file [:- 3 ]} "
188- logger .info ("Loading %s." , cog )
189- try :
190- self .load_extension (cog )
191- except Exception :
192- logger .exception ("Failed to load %s." , cog )
193-
194192 def run (self , * args , ** kwargs ):
195193 try :
196194 self .loop .run_until_complete (self .start (self .token ))
@@ -366,25 +364,21 @@ def blocked_whitelisted_users(self) -> typing.List[str]:
366364 def prefix (self ) -> str :
367365 return str (self .config ["prefix" ])
368366
369- def _parse_color (self , conf_name ):
370- color = self .config [conf_name ]
371- try :
372- return int (color .lstrip ("#" ), base = 16 )
373- except ValueError :
374- logger .error ("Invalid %s provided." , conf_name )
375- return int (self .config .remove (conf_name ).lstrip ("#" ), base = 16 )
376-
377367 @property
378368 def mod_color (self ) -> int :
379- return self ._parse_color ("mod_color" )
369+ return self .config . get ("mod_color" )
380370
381371 @property
382372 def recipient_color (self ) -> int :
383- return self ._parse_color ("recipient_color" )
373+ return self .config . get ("recipient_color" )
384374
385375 @property
386376 def main_color (self ) -> int :
387- return self ._parse_color ("main_color" )
377+ return self .config .get ("main_color" )
378+
379+ @property
380+ def error_color (self ) -> int :
381+ return self .config .get ("error_color" )
388382
389383 def command_perm (self , command_name : str ) -> PermissionLevel :
390384 level = self .config ["override_command_level" ].get (command_name )
@@ -518,7 +512,6 @@ async def on_ready(self):
518512 loop = None ,
519513 )
520514 self .metadata_loop .before_loop (self .before_post_metadata )
521- self .metadata_loop .after_loop (self .after_post_metadata )
522515 self .metadata_loop .start ()
523516
524517 async def convert_emoji (self , name : str ) -> str :
@@ -574,38 +567,14 @@ async def _process_blocked(self, message: discord.Message) -> bool:
574567
575568 now = datetime .utcnow ()
576569
577- account_age = self .config [ "account_age" ]
578- guild_age = self .config [ "guild_age" ]
570+ account_age = self .config . get ( "account_age" )
571+ guild_age = self .config . get ( "guild_age" )
579572
580573 if account_age is None :
581574 account_age = isodate .Duration ()
582575 if guild_age is None :
583576 guild_age = isodate .Duration ()
584577
585- if not isinstance (account_age , isodate .Duration ):
586- try :
587- account_age = isodate .parse_duration (account_age )
588- except isodate .ISO8601Error :
589- logger .warning (
590- "The account age limit needs to be a "
591- "ISO-8601 duration formatted duration string "
592- 'greater than 0 days, not "%s".' ,
593- str (account_age ),
594- )
595- account_age = self .config .remove ("account_age" )
596-
597- if not isinstance (guild_age , isodate .Duration ):
598- try :
599- guild_age = isodate .parse_duration (guild_age )
600- except isodate .ISO8601Error :
601- logger .warning (
602- "The guild join age limit needs to be a "
603- "ISO-8601 duration formatted duration string "
604- 'greater than 0 days, not "%s".' ,
605- str (guild_age ),
606- )
607- guild_age = self .config .remove ("guild_age" )
608-
609578 reason = self .blocked_users .get (str (message .author .id )) or ""
610579 min_guild_age = min_account_age = now
611580
@@ -643,7 +612,7 @@ async def _process_blocked(self, message: discord.Message) -> bool:
643612 title = "Message not sent!" ,
644613 description = f"Your must wait for { delta } "
645614 f"before you can contact me." ,
646- color = discord . Color . red () ,
615+ color = self . error_color ,
647616 )
648617 )
649618
@@ -667,7 +636,7 @@ async def _process_blocked(self, message: discord.Message) -> bool:
667636 title = "Message not sent!" ,
668637 description = f"Your must wait for { delta } "
669638 f"before you can contact me." ,
670- color = discord . Color . red () ,
639+ color = self . error_color ,
671640 )
672641 )
673642
@@ -898,23 +867,15 @@ async def _void(*_args, **_kwargs):
898867 pass
899868
900869 if isinstance (channel , discord .DMChannel ):
901- try :
902- user_typing = strtobool (self .config ["user_typing" ])
903- except ValueError :
904- user_typing = self .config .remove ("user_typing" )
905- if not user_typing :
870+ if not self .config .get ("user_typing" ):
906871 return
907872
908873 thread = await self .threads .find (recipient = user )
909874
910875 if thread :
911876 await thread .channel .trigger_typing ()
912877 else :
913- try :
914- mod_typing = strtobool (self .config ["mod_typing" ])
915- except ValueError :
916- mod_typing = self .config .remove ("mod_typing" )
917- if not mod_typing :
878+ if not self .config .get ("mod_typing" ):
918879 return
919880
920881 thread = await self .threads .find (channel = channel )
@@ -952,15 +913,7 @@ async def on_raw_reaction_add(self, payload):
952913
953914 if isinstance (channel , discord .DMChannel ):
954915 if str (reaction ) == str (close_emoji ): # closing thread
955- try :
956- recipient_thread_close = strtobool (
957- self .config ["recipient_thread_close" ]
958- )
959- except ValueError :
960- recipient_thread_close = self .config .remove (
961- "recipient_thread_close"
962- )
963- if not recipient_thread_close :
916+ if not self .config .get ("recipient_thread_close" ):
964917 return
965918 thread = await self .threads .find (recipient = user )
966919 ts = message .embeds [0 ].timestamp if message .embeds else None
@@ -1018,8 +971,7 @@ async def on_member_remove(self, member):
1018971 thread = await self .threads .find (recipient = member )
1019972 if thread :
1020973 embed = discord .Embed (
1021- description = "The recipient has left the server." ,
1022- color = discord .Color .red (),
974+ description = "The recipient has left the server." , color = self .error_color
1023975 )
1024976 await thread .channel .send (embed = embed )
1025977
@@ -1077,15 +1029,13 @@ async def on_command_error(self, context, exception):
10771029 )
10781030 await context .trigger_typing ()
10791031 await context .send (
1080- embed = discord .Embed (color = discord . Color . red () , description = msg )
1032+ embed = discord .Embed (color = self . error_color , description = msg )
10811033 )
10821034
10831035 elif isinstance (exception , commands .BadArgument ):
10841036 await context .trigger_typing ()
10851037 await context .send (
1086- embed = discord .Embed (
1087- color = discord .Color .red (), description = str (exception )
1088- )
1038+ embed = discord .Embed (color = self .error_color , description = str (exception ))
10891039 )
10901040 elif isinstance (exception , commands .CommandNotFound ):
10911041 logger .warning ("CommandNotFound: %s" , exception )
@@ -1097,7 +1047,7 @@ async def on_command_error(self, context, exception):
10971047 if hasattr (check , "fail_msg" ):
10981048 await context .send (
10991049 embed = discord .Embed (
1100- color = discord . Color . red () , description = check .fail_msg
1050+ color = self . error_color , description = check .fail_msg
11011051 )
11021052 )
11031053 if hasattr (check , "permission_level" ):
@@ -1157,7 +1107,7 @@ async def post_metadata(self):
11571107 "member_count" : len (self .guild .members ),
11581108 "uptime" : (datetime .utcnow () - self .start_time ).total_seconds (),
11591109 "latency" : f"{ self .ws .latency * 1000 :.4f} " ,
1160- "version" : self .version ,
1110+ "version" : str ( self .version ) ,
11611111 "selfhosted" : True ,
11621112 "last_updated" : str (datetime .utcnow ()),
11631113 }
@@ -1172,10 +1122,6 @@ async def before_post_metadata(self):
11721122 if not self .guild :
11731123 self .metadata_loop .cancel ()
11741124
1175- @staticmethod
1176- async def after_post_metadata ():
1177- logger .info ("Metadata loop has been cancelled." )
1178-
11791125
11801126if __name__ == "__main__" :
11811127 try :
0 commit comments