@@ -178,30 +178,42 @@ def _setup_discord_bot_token(cls) -> None:
178178 cls ._settings ["DISCORD_BOT_TOKEN" ] = raw_discord_bot_token
179179
180180 @classmethod
181- def _setup_discord_log_channel_webhook_url (cls ) -> None :
181+ def _setup_discord_log_channel_webhook (cls ) -> "Logger" :
182182 raw_discord_log_channel_webhook_url : str = os .getenv (
183- "DISCORD_LOG_CHANNEL_WEBHOOK_URL" ,
184- "" ,
183+ "DISCORD_LOG_CHANNEL_WEBHOOK_URL" , ""
185184 )
186185
187- DISCORD_LOG_CHANNEL_WEBHOOK_URL_IS_VALID : Final [bool ] = bool (
188- not raw_discord_log_channel_webhook_url
189- or (
190- validators .url (raw_discord_log_channel_webhook_url )
191- and raw_discord_log_channel_webhook_url .startswith (
192- "https://discord.com/api/webhooks/" ,
193- )
194- ),
195- )
196- if not DISCORD_LOG_CHANNEL_WEBHOOK_URL_IS_VALID :
186+ if raw_discord_log_channel_webhook_url and (
187+ not validators .url (raw_discord_log_channel_webhook_url )
188+ or not raw_discord_log_channel_webhook_url .startswith (
189+ "https://discord.com/api/webhooks/"
190+ )
191+ ):
197192 INVALID_DISCORD_LOG_CHANNEL_WEBHOOK_URL_MESSAGE : Final [str ] = (
198193 "DISCORD_LOG_CHANNEL_WEBHOOK_URL must be a valid webhook URL "
199194 "that points to a discord channel where logs should be displayed."
200195 )
201196 raise ImproperlyConfiguredError (INVALID_DISCORD_LOG_CHANNEL_WEBHOOK_URL_MESSAGE )
202197
198+ webhook_config_logger : Logger = logging .getLogger ("_temp_webhook_config" )
199+
200+ if raw_discord_log_channel_webhook_url :
201+ discord_logging_handler : logging .Handler = DiscordHandler (
202+ service_name = "TeX-Bot" , webhook_url = raw_discord_log_channel_webhook_url
203+ )
204+
205+ discord_logging_handler .setLevel (logging .WARNING )
206+
207+ discord_logging_handler .setFormatter (
208+ logging .Formatter ("{levelname} | {message}" , style = "{" )
209+ )
210+
211+ webhook_config_logger .addHandler (discord_logging_handler )
212+
203213 cls ._settings ["DISCORD_LOG_CHANNEL_WEBHOOK_URL" ] = raw_discord_log_channel_webhook_url
204214
215+ return webhook_config_logger
216+
205217 @classmethod
206218 def _setup_discord_logging_channel (cls ) -> None :
207219 if cls ._settings ["DISCORD_LOG_CHANNEL_WEBHOOK_URL" ]:
@@ -230,7 +242,6 @@ def _setup_discord_guild_id(cls) -> None:
230242 "DISCORD_GUILD_ID must be a valid Discord guild ID "
231243 "(see https://docs.pycord.dev/en/stable/api/abcs.html#discord.abc.Snowflake.id)."
232244 )
233- logger .error (INVALID_DISCORD_GUILD_ID_MESSAGE )
234245 raise ImproperlyConfiguredError (INVALID_DISCORD_GUILD_ID_MESSAGE )
235246
236247 cls ._settings ["_DISCORD_MAIN_GUILD_ID" ] = int (raw_discord_guild_id ) # type: ignore[arg-type]
@@ -247,7 +258,6 @@ def _setup_group_full_name(cls) -> None:
247258 INVALID_GROUP_FULL_NAME : Final [str ] = (
248259 "GROUP_NAME must not contain any invalid characters."
249260 )
250- logger .error (INVALID_GROUP_FULL_NAME )
251261 raise ImproperlyConfiguredError (INVALID_GROUP_FULL_NAME )
252262 cls ._settings ["_GROUP_FULL_NAME" ] = raw_group_full_name
253263
@@ -263,7 +273,6 @@ def _setup_group_short_name(cls) -> None:
263273 INVALID_GROUP_SHORT_NAME : Final [str ] = (
264274 "GROUP_SHORT_NAME must not contain any invalid characters."
265275 )
266- logger .error (INVALID_GROUP_SHORT_NAME )
267276 raise ImproperlyConfiguredError (INVALID_GROUP_SHORT_NAME )
268277 cls ._settings ["_GROUP_SHORT_NAME" ] = raw_group_short_name
269278
@@ -278,7 +287,6 @@ def _setup_purchase_membership_url(cls) -> None:
278287 INVALID_PURCHASE_MEMBERSHIP_URL_MESSAGE : Final [str ] = (
279288 "PURCHASE_MEMBERSHIP_URL must be a valid URL."
280289 )
281- logger .error (INVALID_PURCHASE_MEMBERSHIP_URL_MESSAGE )
282290 raise ImproperlyConfiguredError (INVALID_PURCHASE_MEMBERSHIP_URL_MESSAGE )
283291
284292 cls ._settings ["PURCHASE_MEMBERSHIP_URL" ] = raw_purchase_membership_url
@@ -294,7 +302,6 @@ def _setup_membership_perks_url(cls) -> None:
294302 INVALID_MEMBERSHIP_PERKS_URL_MESSAGE : Final [str ] = (
295303 "MEMBERSHIP_PERKS_URL must be a valid URL."
296304 )
297- logger .error (INVALID_MEMBERSHIP_PERKS_URL_MESSAGE )
298305 raise ImproperlyConfiguredError (INVALID_MEMBERSHIP_PERKS_URL_MESSAGE )
299306
300307 cls ._settings ["MEMBERSHIP_PERKS_URL" ] = raw_membership_perks_url
@@ -311,7 +318,6 @@ def _setup_ping_command_easter_egg_probability(cls) -> None:
311318 os .getenv ("PING_COMMAND_EASTER_EGG_PROBABILITY" , "0.01" ),
312319 )
313320 except ValueError as e :
314- logger .error (INVALID_PING_COMMAND_EASTER_EGG_PROBABILITY_MESSAGE ) # noqa: TRY400
315321 raise (
316322 ImproperlyConfiguredError (INVALID_PING_COMMAND_EASTER_EGG_PROBABILITY_MESSAGE )
317323 ) from e
@@ -343,7 +349,6 @@ def _get_messages_dict(cls, raw_messages_file_path: str | None) -> Mapping[str,
343349 MESSAGES_FILE_PATH_DOES_NOT_EXIST_MESSAGE : Final [str ] = (
344350 "MESSAGES_FILE_PATH must be a path to a file that exists."
345351 )
346- logger .error (MESSAGES_FILE_PATH_DOES_NOT_EXIST_MESSAGE )
347352 raise ImproperlyConfiguredError (MESSAGES_FILE_PATH_DOES_NOT_EXIST_MESSAGE )
348353
349354 messages_file : IO [str ]
@@ -352,11 +357,9 @@ def _get_messages_dict(cls, raw_messages_file_path: str | None) -> Mapping[str,
352357 try :
353358 messages_dict : object = json .load (messages_file )
354359 except json .JSONDecodeError as e :
355- logger .error (JSON_DECODING_ERROR_MESSAGE ) # noqa: TRY400
356360 raise ImproperlyConfiguredError (JSON_DECODING_ERROR_MESSAGE ) from e
357361
358362 if not isinstance (messages_dict , Mapping ):
359- logger .error (JSON_DECODING_ERROR_MESSAGE )
360363 raise ImproperlyConfiguredError (JSON_DECODING_ERROR_MESSAGE )
361364
362365 return messages_dict
@@ -375,7 +378,6 @@ def _setup_welcome_messages(cls) -> None:
375378 and messages_dict ["welcome_messages" ],
376379 )
377380 if not WELCOME_MESSAGES_KEY_IS_VALID :
378- logger .error ("Unable to locate welcome messages." )
379381 raise MessagesJSONFileValueError (
380382 dict_key = "welcome_messages" ,
381383 invalid_value = messages_dict ["welcome_messages" ],
@@ -396,7 +398,6 @@ def _setup_roles_messages(cls) -> None:
396398 messages_dict ["roles_messages" ], Iterable
397399 ) and bool (messages_dict ["roles_messages" ])
398400 if not ROLES_MESSAGES_KEY_IS_VALID :
399- logger .error ("Unable to locate role messages." )
400401 raise MessagesJSONFileValueError (
401402 dict_key = "roles_messages" ,
402403 invalid_value = messages_dict ["roles_messages" ],
@@ -415,7 +416,6 @@ def _setup_organisation_id(cls) -> None:
415416 INVALID_ORGANISATION_ID_MESSAGE : Final [str ] = (
416417 "ORGANISATION_ID must be an integer 4 to 5 digits long."
417418 )
418- logger .error (INVALID_ORGANISATION_ID_MESSAGE )
419419 raise ImproperlyConfiguredError (message = INVALID_ORGANISATION_ID_MESSAGE )
420420
421421 cls ._settings ["ORGANISATION_ID" ] = raw_organisation_id
@@ -434,7 +434,6 @@ def _setup_members_list_auth_session_cookie(cls) -> None:
434434 INVALID_MEMBERS_LIST_AUTH_SESSION_COOKIE_MESSAGE : Final [str ] = (
435435 "MEMBERS_LIST_URL_SESSION_COOKIE must be a valid .ASPXAUTH cookie."
436436 )
437- logger .error (INVALID_MEMBERS_LIST_AUTH_SESSION_COOKIE_MESSAGE )
438437 raise ImproperlyConfiguredError (INVALID_MEMBERS_LIST_AUTH_SESSION_COOKIE_MESSAGE )
439438
440439 cls ._settings ["MEMBERS_LIST_AUTH_SESSION_COOKIE" ] = (
@@ -451,7 +450,6 @@ def _setup_send_introduction_reminders(cls) -> None:
451450 INVALID_SEND_INTRODUCTION_REMINDERS_MESSAGE : Final [str ] = (
452451 'SEND_INTRODUCTION_REMINDERS must be one of: "Once", "Interval" or "False".'
453452 )
454- logger .error (INVALID_SEND_INTRODUCTION_REMINDERS_MESSAGE )
455453 raise ImproperlyConfiguredError (INVALID_SEND_INTRODUCTION_REMINDERS_MESSAGE )
456454
457455 if raw_send_introduction_reminders in TRUE_VALUES :
@@ -484,7 +482,6 @@ def _setup_send_introduction_reminders_delay(cls) -> None:
484482 "SEND_INTRODUCTION_REMINDERS_DELAY must contain the delay "
485483 "in any combination of seconds, minutes, hours, days or weeks."
486484 )
487- logger .error (INVALID_SEND_INTRODUCTION_REMINDERS_DELAY_MESSAGE )
488485 raise ImproperlyConfiguredError (
489486 INVALID_SEND_INTRODUCTION_REMINDERS_DELAY_MESSAGE ,
490487 )
@@ -502,7 +499,6 @@ def _setup_send_introduction_reminders_delay(cls) -> None:
502499 "SEND_INTRODUCTION_REMINDERS_DELAY must be longer than or equal to 1 day "
503500 "(in any allowed format)."
504501 )
505- logger .error (TOO_SMALL_SEND_INTRODUCTION_REMINDERS_DELAY_MESSAGE )
506502 raise ImproperlyConfiguredError (
507503 TOO_SMALL_SEND_INTRODUCTION_REMINDERS_DELAY_MESSAGE ,
508504 )
@@ -518,7 +514,6 @@ def _setup_send_introduction_reminders_interval(cls) -> None:
518514 "Invalid setup order: SEND_INTRODUCTION_REMINDERS must be set up "
519515 "before SEND_INTRODUCTION_REMINDERS_INTERVAL can be set up."
520516 )
521- logger .error (INVALID_SETUP_ORDER_MESSAGE )
522517 raise RuntimeError (INVALID_SETUP_ORDER_MESSAGE )
523518
524519 raw_send_introduction_reminders_interval : re .Match [str ] | None = re .fullmatch (
@@ -536,7 +531,6 @@ def _setup_send_introduction_reminders_interval(cls) -> None:
536531 "SEND_INTRODUCTION_REMINDERS_INTERVAL must contain the interval "
537532 "in any combination of seconds, minutes or hours."
538533 )
539- logger .error (INVALID_SEND_INTRODUCTION_REMINDERS_INTERVAL_MESSAGE )
540534 raise ImproperlyConfiguredError (
541535 INVALID_SEND_INTRODUCTION_REMINDERS_INTERVAL_MESSAGE ,
542536 )
@@ -561,7 +555,6 @@ def _setup_send_get_roles_reminders(cls) -> None:
561555 INVALID_SEND_GET_ROLES_REMINDERS_MESSAGE : Final [str ] = (
562556 "SEND_GET_ROLES_REMINDERS must be a boolean value."
563557 )
564- logger .error (INVALID_SEND_GET_ROLES_REMINDERS_MESSAGE )
565558 raise ImproperlyConfiguredError (INVALID_SEND_GET_ROLES_REMINDERS_MESSAGE )
566559
567560 cls ._settings ["SEND_GET_ROLES_REMINDERS" ] = raw_send_get_roles_reminders in TRUE_VALUES
@@ -588,7 +581,6 @@ def _setup_send_get_roles_reminders_delay(cls) -> None:
588581 "SEND_GET_ROLES_REMINDERS_DELAY must contain the delay "
589582 "in any combination of seconds, minutes, hours, days or weeks."
590583 )
591- logger .error (INVALID_SEND_GET_ROLES_REMINDERS_DELAY_MESSAGE )
592584 raise ImproperlyConfiguredError (
593585 INVALID_SEND_GET_ROLES_REMINDERS_DELAY_MESSAGE ,
594586 )
@@ -606,7 +598,6 @@ def _setup_send_get_roles_reminders_delay(cls) -> None:
606598 "SEND_SEND_GET_ROLES_REMINDERS_DELAY "
607599 "must be longer than or equal to 1 day (in any allowed format)."
608600 )
609- logger .error (TOO_SMALL_SEND_GET_ROLES_REMINDERS_DELAY_MESSAGE )
610601 raise ImproperlyConfiguredError (
611602 TOO_SMALL_SEND_GET_ROLES_REMINDERS_DELAY_MESSAGE ,
612603 )
@@ -622,7 +613,6 @@ def _setup_advanced_send_get_roles_reminders_interval(cls) -> None:
622613 "Invalid setup order: SEND_GET_ROLES_REMINDERS must be set up "
623614 "before ADVANCED_SEND_GET_ROLES_REMINDERS_INTERVAL can be set up."
624615 )
625- logger .error (INVALID_SETUP_ORDER_MESSAGE )
626616 raise RuntimeError (INVALID_SETUP_ORDER_MESSAGE )
627617
628618 raw_advanced_send_get_roles_reminders_interval : re .Match [str ] | None = re .fullmatch (
@@ -642,7 +632,6 @@ def _setup_advanced_send_get_roles_reminders_interval(cls) -> None:
642632 "ADVANCED_SEND_GET_ROLES_REMINDERS_INTERVAL must contain the interval "
643633 "in any combination of seconds, minutes or hours."
644634 )
645- logger .error (INVALID_ADVANCED_SEND_GET_ROLES_REMINDERS_INTERVAL_MESSAGE )
646635 raise ImproperlyConfiguredError (
647636 INVALID_ADVANCED_SEND_GET_ROLES_REMINDERS_INTERVAL_MESSAGE ,
648637 )
@@ -668,7 +657,6 @@ def _setup_statistics_days(cls) -> None:
668657 INVALID_STATISTICS_DAYS_MESSAGE : Final [str ] = (
669658 "STATISTICS_DAYS must contain the statistics period in days."
670659 )
671- logger .error (INVALID_STATISTICS_DAYS_MESSAGE ) # noqa: TRY400
672660 raise ImproperlyConfiguredError (INVALID_STATISTICS_DAYS_MESSAGE ) from e
673661
674662 cls ._settings ["STATISTICS_DAYS" ] = timedelta (days = raw_statistics_days )
@@ -698,7 +686,6 @@ def _setup_moderation_document_url(cls) -> None:
698686 MODERATION_DOCUMENT_URL_MESSAGE : Final [str ] = (
699687 "MODERATION_DOCUMENT_URL must be a valid URL."
700688 )
701- logger .error (MODERATION_DOCUMENT_URL_MESSAGE )
702689 raise ImproperlyConfiguredError (MODERATION_DOCUMENT_URL_MESSAGE )
703690
704691 cls ._settings ["MODERATION_DOCUMENT_URL" ] = raw_moderation_document_url
@@ -714,7 +701,6 @@ def _setup_strike_performed_manually_warning_location(cls) -> None:
714701 "MANUAL_MODERATION_WARNING_MESSAGE_LOCATION must be a valid name "
715702 "of a channel in your group's Discord guild."
716703 )
717- logger .error (STRIKE_PERFORMED_MANUALLY_WARNING_LOCATION_MESSAGE )
718704 raise ImproperlyConfiguredError (STRIKE_PERFORMED_MANUALLY_WARNING_LOCATION_MESSAGE )
719705
720706 cls ._settings ["STRIKE_PERFORMED_MANUALLY_WARNING_LOCATION" ] = (
@@ -751,31 +737,36 @@ def _setup_env_variables(cls) -> None:
751737
752738 dotenv .load_dotenv ()
753739
754- cls ._setup_logging ()
755- cls ._setup_discord_bot_token ()
756- cls ._setup_discord_log_channel_webhook_url ()
757- cls ._setup_discord_logging_channel ()
758- cls ._setup_discord_guild_id ()
759- cls ._setup_group_full_name ()
760- cls ._setup_group_short_name ()
761- cls ._setup_ping_command_easter_egg_probability ()
762- cls ._setup_welcome_messages ()
763- cls ._setup_roles_messages ()
764- cls ._setup_organisation_id ()
765- cls ._setup_members_list_auth_session_cookie ()
766- cls ._setup_membership_perks_url ()
767- cls ._setup_purchase_membership_url ()
768- cls ._setup_send_introduction_reminders ()
769- cls ._setup_send_introduction_reminders_delay ()
770- cls ._setup_send_introduction_reminders_interval ()
771- cls ._setup_send_get_roles_reminders ()
772- cls ._setup_send_get_roles_reminders_delay ()
773- cls ._setup_advanced_send_get_roles_reminders_interval ()
774- cls ._setup_statistics_days ()
775- cls ._setup_statistics_roles ()
776- cls ._setup_moderation_document_url ()
777- cls ._setup_strike_performed_manually_warning_location ()
778- cls ._setup_auto_add_committee_to_threads ()
740+ webhook_config_logger : Logger = cls ._setup_discord_log_channel_webhook ()
741+
742+ try :
743+ cls ._setup_logging ()
744+ cls ._setup_discord_bot_token ()
745+ cls ._setup_discord_logging_channel ()
746+ cls ._setup_discord_guild_id ()
747+ cls ._setup_group_full_name ()
748+ cls ._setup_group_short_name ()
749+ cls ._setup_ping_command_easter_egg_probability ()
750+ cls ._setup_welcome_messages ()
751+ cls ._setup_roles_messages ()
752+ cls ._setup_organisation_id ()
753+ cls ._setup_members_list_auth_session_cookie ()
754+ cls ._setup_membership_perks_url ()
755+ cls ._setup_purchase_membership_url ()
756+ cls ._setup_send_introduction_reminders ()
757+ cls ._setup_send_introduction_reminders_delay ()
758+ cls ._setup_send_introduction_reminders_interval ()
759+ cls ._setup_send_get_roles_reminders ()
760+ cls ._setup_send_get_roles_reminders_delay ()
761+ cls ._setup_advanced_send_get_roles_reminders_interval ()
762+ cls ._setup_statistics_days ()
763+ cls ._setup_statistics_roles ()
764+ cls ._setup_moderation_document_url ()
765+ cls ._setup_strike_performed_manually_warning_location ()
766+ cls ._setup_auto_add_committee_to_threads ()
767+ except ImproperlyConfiguredError as improper_config_error :
768+ webhook_config_logger .error (improper_config_error .message ) # noqa: TRY400
769+ raise improper_config_error from improper_config_error
779770
780771 cls ._is_env_variables_setup = True
781772
0 commit comments