-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
123 lines (102 loc) · 3.56 KB
/
Copy pathmain.py
File metadata and controls
123 lines (102 loc) · 3.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
from __future__ import annotations
import asyncio
import logging
import os
import discord
from discord import app_commands
from dotenv import load_dotenv
import generate
import parse
import scheduler
from commands import (
analyze as analyze_cmd,
bands as bands_cmd,
directory as directory_cmd,
help as help_cmd,
knowledgeharden as knowledgeharden_cmd,
rubric as rubric_cmd,
schedule as schedule_cmd,
session as session_cmd,
stats as stats_cmd,
sweep as sweep_cmd,
transcript as transcript_cmd,
)
load_dotenv()
logging.basicConfig(
level=os.environ.get("LOG_LEVEL", "INFO"),
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)
log = logging.getLogger("fortifai")
intents = discord.Intents.default()
intents.message_content = True
intents.guilds = True
intents.dm_messages = True
bot = discord.Client(intents=intents)
tree = app_commands.CommandTree(bot)
# --- extracted command modules --------------------------------------------
transcript_cmd.register(tree)
analyze_cmd.register(tree)
stats_cmd.register(tree)
session_cmd.register(tree)
help_cmd.register(tree)
rubric_cmd.register(tree)
bands_cmd.register(tree)
directory_cmd.register(tree)
schedule_cmd.register(tree)
sweep_cmd.register(tree)
knowledgeharden_cmd.register(tree, bot)
# --- lifecycle -------------------------------------------------------------
@bot.event
async def on_ready():
log.info("logged in as %s (%s)", bot.user, bot.user.id if bot.user else "?")
parse.ensure_runtime_dirs()
parse.seed_meta_if_empty()
industries = generate.list_industries()
log.info("industries available: %s", industries or "(none)")
for industry in industries:
if not parse.grader_available(industry):
log.warning(
"templates/%s/grader_question.md is missing or empty — grading unavailable for this industry.",
industry,
)
scheduler.start(asyncio.get_running_loop(), schedule_cmd.make_on_schedule_fire(bot))
# Slash command sync. Global syncs propagate over up to ~1 hour, which
# makes development frustrating when a parameter list changes. If
# DEV_GUILD_ID is set, we copy the global tree into that guild and sync
# there too — guild-scoped commands appear immediately.
dev_guild_id = os.environ.get("DEV_GUILD_ID", "").strip()
try:
synced_global = await tree.sync()
log.info(
"synced %d global slash commands: %s",
len(synced_global),
", ".join(sorted(c.name for c in synced_global)),
)
if dev_guild_id:
try:
guild = discord.Object(id=int(dev_guild_id))
except ValueError:
log.warning("DEV_GUILD_ID=%r is not a valid integer; skipping guild sync", dev_guild_id)
else:
tree.copy_global_to(guild=guild)
synced_guild = await tree.sync(guild=guild)
log.info(
"synced %d slash commands to guild %s (instant): %s",
len(synced_guild),
dev_guild_id,
", ".join(sorted(c.name for c in synced_guild)),
)
except discord.HTTPException as e:
log.error("command sync failed: %s", e)
@bot.event
async def on_disconnect():
log.info("bot disconnected")
def main() -> None:
token = os.environ.get("DISCORD_BOT_TOKEN")
if not token:
raise SystemExit("DISCORD_BOT_TOKEN is not set.")
parse.ensure_runtime_dirs()
parse.seed_meta_if_empty()
bot.run(token)
if __name__ == "__main__":
main()