77from types import TracebackType
88from typing import Any , Final , cast
99
10- from dotenv import load_dotenv
10+ import dotenv
1111from httpx import Client , HTTPStatusError , Response
1212
13+ log = logging .getLogger ("botstrap" ) # note this instance will not have the .trace level
14+
15+ # TODO: Remove once better error handling for constants.py is in place.
16+ if (dotenv .dotenv_values ().get ("BOT_TOKEN" ) or os .getenv ("BOT_TOKEN" )) is None :
17+ msg = (
18+ "Couldn't find the `BOT_TOKEN` environment variable. "
19+ "Make sure to add it to your `.env` file like this: `BOT_TOKEN=value_of_your_bot_token`"
20+ )
21+ log .fatal (msg )
22+ sys .exit (1 )
23+
1324# Filter out the send typing monkeypatch logs from bot core when we import to get constants
1425logging .getLogger ("pydis_core" ).setLevel (logging .WARNING )
1526
27+ # As a side effect, this also configures our logging styles
1628from bot .constants import ( # noqa: E402
29+ Bot as BotConstants ,
30+ Guild as GuildConstants ,
1731 Webhooks ,
1832 _Categories , # pyright: ignore[reportPrivateUsage]
1933 _Channels , # pyright: ignore[reportPrivateUsage]
2034 _Emojis , # pyright: ignore[reportPrivateUsage]
2135 _Roles , # pyright: ignore[reportPrivateUsage]
2236)
23- from bot .log import get_logger # noqa: E402
2437
25- load_dotenv ()
26- log = get_logger ( "botstrap" )
27- # Silence noisy httpcore logger
28- get_logger ( "httpcore" ). setLevel ( "INFO" )
38+ # Silence noisy loggers
39+ logging . getLogger ( "httpx" ). setLevel ( logging . WARNING )
40+ logging . getLogger ( " httpcore" ). setLevel ( logging . WARNING )
41+
2942
3043ENV_FILE = Path (".env.server" )
31- BOT_TOKEN = os .getenv ("BOT_TOKEN" , None )
32- GUILD_ID = os .getenv ("GUILD_ID" , None )
3344
3445COMMUNITY_FEATURE = "COMMUNITY"
3546PYTHON_HELP_CHANNEL_NAME = "python_help"
4051GUILD_FORUM_TYPE = 15
4152EMOJI_REGEX = re .compile (r"<:(\w+):(\d+)>" )
4253
43- if not BOT_TOKEN :
44- message = (
45- "Couldn't find the `BOT_TOKEN` environment variable. "
46- "Make sure to add it to your `.env` file like this: `BOT_TOKEN=value_of_your_bot_token`"
47- )
48- log .warning (message )
49- raise ValueError (message )
50-
51- if not GUILD_ID :
52- message = (
54+ if GuildConstants .id == type (GuildConstants ).model_fields ["id" ].default :
55+ msg = (
5356 "Couldn't find the `GUILD_ID` environment variable. "
5457 "Make sure to add it to your `.env` file like this: `GUILD_ID=value_of_your_discord_server_id`"
5558 )
56- log .warning ( message )
57- raise ValueError ( message )
59+ log .error ( msg )
60+ sys . exit ( 1 )
5861
5962
6063class SilencedDict (dict [str , Any ]):
@@ -86,10 +89,10 @@ class DiscordClient(Client):
8689
8790 CDN_BASE_URL : Final [str ] = "https://cdn.discordapp.com"
8891
89- def __init__ (self , guild_id : int | str ):
92+ def __init__ (self , * , guild_id : int | str , bot_token : str ):
9093 super ().__init__ (
9194 base_url = "https://discord.com/api/v10" ,
92- headers = {"Authorization" : f"Bot { BOT_TOKEN } " },
95+ headers = {"Authorization" : f"Bot { bot_token } " },
9396 event_hooks = {"response" : [self ._raise_for_status ]},
9497 )
9598 self .guild_id = guild_id
@@ -284,8 +287,15 @@ def clone_emoji(self, *, new_name: str, original_emoji_id: str | int) -> str:
284287class BotStrapper :
285288 """Bootstrap the bot configuration for a given guild."""
286289
287- def __init__ (self , guild_id : int | str , env_file : Path ):
288- self .client = DiscordClient (guild_id = guild_id )
290+ def __init__ (
291+ self ,
292+ * ,
293+ guild_id : int | str ,
294+ env_file : Path ,
295+ bot_token : str ,
296+ ):
297+ self .guild_id = guild_id
298+ self .client = DiscordClient (guild_id = guild_id , bot_token = bot_token )
289299 self .env_file = env_file
290300
291301 def __enter__ (self ):
@@ -310,12 +320,12 @@ def check_guild_membership(self) -> None:
310320 """Check the bot is in the required guild."""
311321 if not self .client .check_if_in_guild ():
312322 client_id = self .client .app_info ["id" ]
313- log .error ("The bot is not a member of the configured guild with ID %s." , GUILD_ID )
323+ log .error ("The bot is not a member of the configured guild with ID %s." , self . guild_id )
314324 log .warning (
315325 "Please invite with the following URL and rerun this script: "
316326 "https://discord.com/oauth2/authorize?client_id=%s&guild_id=%s&scope=bot+applications.commands&permissions=8" ,
317327 client_id ,
318- GUILD_ID ,
328+ self . guild_id ,
319329 )
320330 raise BotstrapError ("Bot is not a member of the configured guild." )
321331
@@ -463,7 +473,7 @@ def run(self) -> None:
463473
464474
465475if __name__ == "__main__" :
466- botstrap = BotStrapper (guild_id = GUILD_ID , env_file = ENV_FILE )
476+ botstrap = BotStrapper (guild_id = GuildConstants . id , env_file = ENV_FILE , bot_token = BotConstants . token )
467477 with botstrap :
468478 botstrap .run ()
469479 log .info ("Botstrap completed successfully. Configuration has been written to %s" , ENV_FILE )
0 commit comments