sondt99/ctf-bot

GitHub: sondt99/ctf-bot

一款面向 CTF 团队的 Discord 机器人,集成赛事管理、挑战追踪、实时记分牌轮询和消息统计,一站式解决比赛协作的组织难题。

Stars: 1 | Forks: 0

# Discord CTF Bot 一个用于组织 Capture The Flag 比赛的 Discord bot。它集成了 CTFtime 来获取赛事信息,为每个赛事创建专属分类和频道,通过线程跟踪各项挑战,并对 CTFd 和 rCTF 平台的实时记分牌进行轮询。 ## 文档 - [架构](docs/architecture.md) — 组件概述与数据流 - [数据库](docs/database.md) — schema、表、迁移和 repository API - [开发](docs/development.md) — 本地设置、测试与类型检查 - [部署](docs/deployment.md) — Docker、systemd 与环境变量参考 ## 功能 - **CTFtime 集成** — 通过分页浏览并加入即将举行的 CTF 赛事 - **挑战管理** — 为每个挑战创建线程,批量导入 CTFd 挑战,跟踪已解决/开放状态 - **实时记分牌** — 定期轮询,并针对 CTFd 和 rCTF 的变化发送通知 - **消息统计** — 用户排行榜、活跃度分析以及历史数据回填 - **多赛事支持** — 同时运行多个 CTF,每个赛事都有各自的分类 - **基于角色的权限控制** — `@ctf` 角色的成员可以将挑战标记为已解决;管理员命令仅限管理员使用 - **审计日志** — 自动创建私有的 `BOT` 分类,包含命令日志和手动数据库备份 ## 要求 - Python 3.11+ - 带有[所需 intents](#permissions) 的 Discord bot token ## 设置 ``` # 1. 克隆并配置 cp .env.example .env # 编辑 .env 并设置 DISCORD_TOKEN # 2. 安装依赖 pip install -r requirements.txt # 3. 运行 bot python -m bot.main ``` ## Docker 部署 ``` # 1. 复制并编辑 env 文件 cp .env.example .env # 编辑 .env:设置 DISCORD_TOKEN,可选 FERNET_KEY 等 # 2. 启动 bot docker compose up -d # 3. 查看日志 docker compose logs -f bot # 4. 升级(在 git pull 之后) docker compose build --pull && docker compose up -d ``` SQLite 数据库存储在一个命名的 Docker volume (`bot_data`) 中,因此它会在重启和容器升级后保留。 ## 环境变量 | 变量 | 必需 | 默认值 | 描述 | |---|---|---|---| | `DISCORD_TOKEN` | 是 | — | Discord bot token | | `DATABASE_PATH` | 否 | `ctf_bot.db` | SQLite 数据库文件的路径 | | `SCOREBOARD_POLL_SECONDS` | 否 | `30` | 记分牌轮询间隔(秒) | | `SCOREBOARD_TOP_N` | 否 | `10` | 记分牌更新中显示的队伍数量 | | `SCOREBOARD_TEAM_NAME` | 否 | — | 你的队伍名称(用于记分牌跟踪) | | `TIMEZONE` | 否 | `UTC+7` | 赛事显示的时区 — IANA 名称 (`Asia/Ho_Chi_Minh`) 或偏移量 (`UTC+7`) | | `CTF_REMOVE_PASSWORD` | 否 | — | `/ctf remove` 所需的密码 | | `DISCORD_GUILD_ID` | 否 | — | Guild ID,用于实现更快的斜杠命令同步 | | `FERNET_KEY` | 否 | — | 用于对静态认证 token 进行加密的 Fernet key(使用 `python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"` 生成) | ## 命令 ### CTF 赛事 | 命令 | 描述 | 权限 | |---|---|---| | `/ctf upcoming [limit]` | 浏览 CTFtime 上即将举行的 CTF | 所有人 | | `/ctf running [limit]` | 列出 CTFtime 上当前活跃的 CTF | 所有人 | | `/ctf archive [limit] [days]` | 列出最近结束的 CTF(默认:过去 30 天) | 所有人 | | `/ctf join ` | 为赛事创建分类和频道(自动创建 `@ctf` 角色) | 管理员 | | `/ctf list` | 列出已加入的 CTF 及其 event ID | 所有人 | | `/ctf progress [event_id]` | 显示挑战进度及各分类详情 | 所有人 | | `/ctf export [event_id] [format]` | 将挑战数据导出为 JSON 或 CSV | 所有人 | | `/ctf hidden [event_id]` | 向非管理员隐藏 CTF 分类 | 管理员 | | `/ctf remove [event_id] password` | 删除 CTF 分类及所有相关数据 | 管理员 | ### 挑战 | 命令 | 描述 | 权限 | |---|---|---| | `/challenge ` | 为挑战创建一个线程(必须在 topic 频道中执行) | 所有人 | | `/challenge-fetch [auth_token]` | 获取 CTFd 挑战,将 CTFd 分类映射到 topic 频道,创建缺失的线程,并仅在描述/文件更改时刷新 CTFd embed | 管理员 | | `/done [solver2] ...` | 将挑战标记为已解决并重命名线程 | 管理员 / `@ctf` 角色 | | `/challenges [event_id]` | 列出所有挑战及其状态和线程链接 | 所有人 | | `/remove-challenge` | 取消跟踪当前挑战(保留线程) | 管理员 | ### 记分牌 | 命令 | 描述 | 权限 | |---|---|---| | `/scoreboard [auth_token] [team] [event_id]` | 配置记分牌轮询(`CTFd` 或 `rCTF`) | 管理员 | | `/scoreboard_list` | 显示活跃的记分牌配置 | 所有人 | | `/scoreboard_remove ` | 移除记分牌配置 | 管理员 | ### 统计 | 命令 | 描述 | 权限 | |---|---|---| | `/stats leaderboard [limit] [channel]` | 按消息数排名的顶级用户 | 所有人 | | `/stats user ` | 用户个人的消息统计、排名和活跃频道 | 所有人 | | `/stats sync [limit] [channel]` | 将历史消息回填到统计中 | 管理员 | ## 工作流 ``` 1. /ctf join → Bot creates category with topic channels 2. /challenge-fetch [token] → Bot asks how to map CTFd categories, then imports into topic threads 3. Or go to a topic channel and run /challenge for manual threads 4. Work on the challenge in the thread 5. /done @solver → Mark solved, thread renamed to [DONE] 6. /challenges → Overview with clickable thread links ``` ## 加入时创建的频道 每个 CTF 赛事都会获得一个以该赛事命名的 Discord 分类,其中包含: ``` account — read-only info channel general — general discussion rev — reverse engineering pwn — binary exploitation web — web challenges crypto — cryptography for — forensics misc — miscellaneous scoreboard — live scoreboard updates ``` ## BOT 管理员分类 在启动时,bot 会创建一个仅管理员可见的私有 `BOT` 分类: - **#log** — 命令使用日志 - **#backup** — 由 `/backup` 创建的数据库上传 ## 权限 该 bot 需要以下 Discord 权限: | 权限 | 原因 | |---|---| | Manage Channels | 创建分类、频道和线程 | | Create Public Threads | 挑战线程 | | Read Message History | `/stats sync` 数据回填 | | Send Messages | 创建线程及回复 | | Embed Links | 所有 bot 回复均使用 embed | | Manage Roles | (可选)如果你希望 bot 管理 `@ctf` 角色 | **所需 intents**(在 Discord Developer Portal 中启用): - Server Members - Message Content(如果将来使用前缀命令) ## 注意事项 - 必须在服务器中手动创建 `@ctf` 角色,`/done` 权限才能生效。 - `/challenge-fetch` 每次运行时都会询问分类映射,因此在赛事中途添加的新的 CTFd 分类可以在导入前进行路由。 - 现有的 CTFd 挑战线程仅在描述或文件链接发生更改时才会更新;仅分数/解答数量的变化将被忽略。标记为 `/done` 的线程不会被更新。 - `/challenge-fetch` 接受完整的 CTFd URL (`http://localhost:8000`) 或仅主机的 URL (`localhost:8000`)。 - 消息统计仅跟踪 bot 部署后发送的消息,除非你运行 `/stats sync`。 - rCTF 的记分牌轮询直接使用公共 API — 不需要浏览器依赖。 - 该 bot 使用 SQLite。在生产环境中使用时,请确保数据库文件位于持久化的 volume 中。
标签:Discord, Docker, Python, 团队协作, 安全防御评估, 无后门, 请求拦截, 逆向工具