From b5c58f842a44dbb2c54de37384895144fd0c95d5 Mon Sep 17 00:00:00 2001 From: Ching L Date: Mon, 17 Mar 2025 13:49:45 +0800 Subject: [PATCH] chore: Remove draw_result.py as it is no longer needed for match result visualization --- draw_result.py | 110 ------------------------------------------ project-info.md | 125 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 110 deletions(-) delete mode 100644 draw_result.py create mode 100644 project-info.md diff --git a/draw_result.py b/draw_result.py deleted file mode 100644 index 2498a61..0000000 --- a/draw_result.py +++ /dev/null @@ -1,110 +0,0 @@ -from PIL import Image, ImageDraw, ImageFont - -icon_width = 256 -icon_height = 144 -banner_height = 70 - -# 创建空白画布 -width = icon_width * 5 -height = icon_height * 2 * 5 + banner_height -background_color = (255, 255, 255) -image = Image.new("RGB", (width, height), background_color) -draw = ImageDraw.Draw(image) - -# 定义字体和颜色 -font_color = (0, 0, 0) -font = ImageFont.truetype("arial.ttf", 34) - -# 定义玩家信息的位置 -player_info_x = 0 -player_info_y = banner_height -player_info_2_x = player_info_x + icon_width -player_info_2_x_end = int(player_info_2_x + icon_width * 1.5) -lv_height = int(icon_height / 2) - -# 添加天辉标题 -radiant_color = "#66bb6a" -draw.rectangle([0, 0, player_info_2_x_end, 70], fill=radiant_color) -draw.text((20, 20), "天辉", font=font, fill=font_color) - -# 添加玩家信息 -for i in range(5): - # 左侧等级信息 - draw.rectangle([player_info_x, player_info_y, player_info_2_x, player_info_y + lv_height], fill="#808080") - draw.text((player_info_x + 10, player_info_y + 10), "LV. 25", font=font, fill=font_color) - - # 左侧头像信息 - icon = Image.open("hero_img/muerta.png") - # icon = icon.resize((144, 256)) - image.paste(icon, (player_info_x, player_info_y+lv_height)) - - # 左侧KDA信息 - draw.rectangle([player_info_x, player_info_y+lv_height+icon_height, player_info_2_x, player_info_y+lv_height+icon_height+lv_height], fill="#808080") - draw.text((player_info_x + 10, player_info_y+lv_height+icon_height + 20), "10/0/10", font=font, fill=font_color) - - # 右侧玩家名称 - draw.rectangle([player_info_2_x, player_info_y, player_info_2_x_end, player_info_y + lv_height], fill="#808080") - draw.text((player_info_2_x, player_info_y + 20), "muerta", font=font, fill=font_color) - - # 右侧金钱信息 - draw.rectangle([player_info_2_x, player_info_y + lv_height, player_info_2_x_end, player_info_y + lv_height+lv_height], fill="#808080") - draw.text((player_info_2_x, player_info_y + lv_height + 20), "金钱:10000", font=font, fill=font_color) - - # 右侧伤害信息 - draw.rectangle([player_info_2_x, player_info_y + lv_height*2, player_info_2_x_end, player_info_y + lv_height*3], fill="#808080") - draw.text((player_info_2_x, player_info_y + lv_height*2 +20), "伤害:23456", font=font, fill=font_color) - - # 右侧段位信息 - draw.rectangle([player_info_2_x, player_info_y + lv_height*3, player_info_2_x_end, player_info_y + lv_height*4], fill="#808080") - draw.text((player_info_2_x, player_info_y + lv_height*3 +20), "中军 3", font=font, fill=font_color) - - player_info_y += lv_height * 2 + icon_height - -# 添加夜魇标题 -dire_color = "#f44336" -draw.rectangle([player_info_2_x_end, 0, width, 70], fill=dire_color) -draw.text((player_info_2_x_end + 20,20), "夜魇", font=font, fill=(255, 255, 255)) - -player_info_x = int(width / 2) -player_info_y = 70 -player_info_2_x = player_info_x + icon_width -player_info_2_x_end = player_info_2_x + icon_width * 1.5 -lv_height = 72 - - -# 添加玩家信息 -for i in range(5): - # 左侧等级信息 - draw.rectangle([player_info_x, player_info_y, player_info_2_x, player_info_y + lv_height], fill="#808080") - draw.text((player_info_x + 10, player_info_y + 10), "LV. 25", font=font, fill=font_color) - - # 左侧头像信息 - icon = Image.open("hero_img/muerta.png") - # icon = icon.resize((144, 256)) - image.paste(icon, (player_info_x, player_info_y+lv_height)) - - # 左侧KDA信息 - draw.rectangle([player_info_x, player_info_y+lv_height+icon_height, player_info_2_x, player_info_y+lv_height+icon_height+lv_height], fill="#808080") - draw.text((player_info_x + 10, player_info_y+lv_height+icon_height + 20), "10/0/10", font=font, fill=font_color) - - # 右侧玩家名称 - draw.rectangle([player_info_2_x, player_info_y, player_info_2_x_end, player_info_y + lv_height], fill="#808080") - draw.text((player_info_2_x, player_info_y + 20), "muerta", font=font, fill=font_color) - - # 右侧金钱信息 - draw.rectangle([player_info_2_x, player_info_y + lv_height, player_info_2_x_end, player_info_y + lv_height+lv_height], fill="#808080") - draw.text((player_info_2_x, player_info_y + lv_height + 20), "金钱:10000", font=font, fill=font_color) - - # 右侧伤害信息 - draw.rectangle([player_info_2_x, player_info_y + lv_height*2, player_info_2_x_end, player_info_y + lv_height*3], fill="#808080") - draw.text((player_info_2_x, player_info_y + lv_height*2 +20), "伤害:23456", font=font, fill=font_color) - - # 右侧段位信息 - draw.rectangle([player_info_2_x, player_info_y + lv_height*3, player_info_2_x_end, player_info_y + lv_height*4], fill="#808080") - draw.text((player_info_2_x, player_info_y + lv_height*3 +20), "中军 3", font=font, fill=font_color) - - player_info_y += lv_height * 2 + icon_height - - -# 保存图片 -image.save("dota_match_result.png") diff --git a/project-info.md b/project-info.md new file mode 100644 index 0000000..c6f74b6 --- /dev/null +++ b/project-info.md @@ -0,0 +1,125 @@ +# DotaBot 项目文档 + +## 项目概述 + +DotaBot 是一个 Discord 机器人,用于跟踪 Dota 2 玩家的比赛数据并在 Discord 频道中分享这些信息。它可以监控指定玩家的最近比赛,生成比赛报告图片,并通知连胜/连败等特殊事件。 + +## 项目架构 + +### 核心组件 + +1. **Discord Bot**: 基于 py-cord 库实现的 Discord 机器人 +2. **Dota 2 API 集成**: 使用 OpenDota API 获取比赛数据 +3. **数据库**: 使用 Peewee ORM 管理本地数据 +4. **图片生成**: 使用 Playwright 和 Jinja2 生成比赛报告图片 +5. **图片存储**: 使用 Cloudflare R2 存储生成的图片 + +### 文件结构 + +``` +├── discord_bot.py # Discord 机器人主程序 +├── dota.py # Dota 2 数据处理和模型定义 +├── image_generator.py # 图片生成模块 +├── utils.py # 工具函数 +├── matches.py # 比赛数据处理 +├── heroes.json # 英雄数据 +├── templates/ # HTML 模板目录 +│ ├── match_report.html # 比赛报告模板 +│ └── recent_matches.html # 最近比赛模板 +├── env.ini # 配置文件 +└── dotabot.log # 日志文件 +``` + +## 依赖关系 +``` +project-info.md +discord_bot.py +├── dota.py +│ ├── utils.py +│ └── image_generator.py +└── utils.py +image_generator.py +├── utils.py +├── templates/match_report.html +└── templates/recent_matches.html +dota.py +├── utils.py +└── image_generator.py +``` + + + +## 功能模块 + +### 1. Discord Bot (discord_bot.py) + +Discord 机器人的主程序,负责与 Discord 交互,包括: +- 定时任务获取最新比赛数据 +- 处理用户命令 +- 发送比赛报告和通知 + +主要命令: +- `/recent_matches [name] [match_count]`: 获取指定玩家的最近比赛 +- `/list_friends`: 列出所有已添加的好友 +- `/add_friend [steam_id] [name]`: 添加新好友 +- `/mod_friend [steam_id] [name]`: 修改好友信息 +- `/activate_friend [steam_id]`: 启用好友 +- `/deactivate_friend [steam_id]`: 禁用好友 + +### 2. Dota 数据处理 (dota.py) + +处理 Dota 2 比赛数据,定义数据模型,包括: +- `Match`: 比赛数据模型 +- `Friend`: 好友数据模型 +- 比赛数据序列化 +- 连胜/连败检测 + +主要功能: +- `get_friends_recent_matches()`: 获取所有好友的最近比赛 +- `serialize_match_for_discord()`: 将比赛数据格式化为 Discord 消息 +- `check_streaks()`: 检查连胜/连败情况 + +### 3. 图片生成 (image_generator.py) + +使用 Playwright 和 Jinja2 生成比赛报告图片,包括: +- `ImageGenerator` 类:负责生成比赛报告和最近比赛图片 +- 使用 HTML 模板渲染比赛数据 +- 使用 Playwright 将 HTML 转换为图片 +- 上传图片到 Cloudflare R2 存储 + +主要方法: +- `generate_match_report()`: 生成单场比赛报告图片 +- `generate_recent_matches_image()`: 生成最近比赛汇总图片 + +### 4. 工具函数 (utils.py) + +提供各种辅助功能,包括: +- 时间格式转换 +- 英雄名称中英文转换 +- 数字格式化 +- 图片上传到 Cloudflare R2 +- 日志记录 + +主要函数: +- `convert_seconds_to_hms()`: 将秒数转换为时分秒 +- `get_hero_chinese_name()`: 获取英雄的中文名称 +- `upload_image()`: 上传图片到 Cloudflare R2 +- `get_ranking()`: 获取天梯段位名称 + +## 数据流 + +1. **定时任务流程**: + - Discord Bot 定时调用 `get_friends_recent_matches()` + - 获取所有活跃好友的最新比赛 + - 对于新比赛,调用 `serialize_match_for_discord()` 格式化数据 + - 调用 `ImageGenerator.generate_match_report()` 生成比赛报告图片 + - 发送格式化的比赛数据和图片到 Discord 频道 + +2. **用户命令流程**: + - 用户发送命令 (如 `/recent_matches`) + - Discord Bot 处理命令并调用相应函数 + - 对于 `/recent_matches`,调用 `Friend.serialize_recent_matches_for_discord()` + - 调用 `ImageGenerator.generate_recent_matches_image()` 生成图片 + - 发送结果到 Discord + +