1299 lines
45 KiB
Markdown
1299 lines
45 KiB
Markdown
# Telegram Media Downloader — 产品需求文档(PRD)
|
||
|
||
**文档版本:** 1.0
|
||
**项目版本:** 2.2.5
|
||
**撰写日期:** 2026-04-06
|
||
**项目地址:** https://github.com/tangyoha/telegram_media_downloader
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
1. [产品概述](#1-产品概述)
|
||
2. [目标用户](#2-目标用户)
|
||
3. [使用场景](#3-使用场景)
|
||
4. [核心功能](#4-核心功能)
|
||
5. [项目架构](#5-项目架构)
|
||
6. [目录结构](#6-目录结构)
|
||
7. [核心模块详解](#7-核心模块详解)
|
||
8. [配置项完整说明](#8-配置项完整说明)
|
||
9. [下载过滤器语法](#9-下载过滤器语法)
|
||
10. [Web 界面 API 接口](#10-web-界面-api-接口)
|
||
11. [数据结构](#11-数据结构)
|
||
12. [下载目录结构](#12-下载目录结构)
|
||
13. [安装与运行](#13-安装与运行)
|
||
14. [依赖说明](#14-依赖说明)
|
||
15. [当前限制与已知问题](#15-当前限制与已知问题)
|
||
16. [优化建议与迭代方向](#16-优化建议与迭代方向)
|
||
|
||
---
|
||
|
||
## 1. 产品概述
|
||
|
||
### 1.1 产品定位
|
||
|
||
Telegram Media Downloader 是一款基于 Python 的 Telegram 媒体批量下载工具。它通过 Telegram 官方 MTProto API(pyrogram 客户端)连接 Telegram,能够从指定频道、群组或私聊中批量下载多种媒体类型(视频、图片、音频、文档、语音等),并提供配套的 Web 可视化管理界面和 Telegram Bot 控制接口。
|
||
|
||
### 1.2 核心价值
|
||
|
||
- **批量高效**:支持对多个频道并发处理,断点续传,不重复下载已有文件。
|
||
- **精细过滤**:通过类 SQL 表达式对消息日期、文件大小、文件名、视频分辨率、标题内容等进行精确筛选。
|
||
- **多端控制**:提供 Web 界面(浏览器访问)和 Telegram Bot 两种控制方式,无需每次修改配置文件。
|
||
- **可扩展存储**:下载完成后可自动上传到 Telegram 指定聊天,或通过 Rclone 上传到 100+ 种云存储(Google Drive、OneDrive、阿里云盘等)。
|
||
- **容器化支持**:完整的 Docker/Docker-Compose 支持,易于部署和隔离运行。
|
||
|
||
### 1.3 版本说明
|
||
|
||
当前版本为 **2.2.5**(见 `utils/__init__.py`)。该版本已经历多次重构,核心下载引擎稳定,Web 界面为近期新增功能,仍处于持续迭代阶段。
|
||
|
||
---
|
||
|
||
## 2. 目标用户
|
||
|
||
| 用户类型 | 使用场景 | 技术门槛 |
|
||
|---------|---------|---------|
|
||
| 内容收藏者 | 批量下载 Telegram 频道的学习资料、影视资源、图片合集 | 低(Web 界面操作) |
|
||
| 内容创作者 | 从特定群组归档历史素材 | 低 |
|
||
| 开发者/研究者 | 数据采集、内容存档 | 中(需配置 API) |
|
||
| 运营人员 | 多频道内容监控、素材备份 | 中 |
|
||
| 服务器管理员 | 无头服务器 + Docker 自动化归档 | 高 |
|
||
|
||
**前提要求:**
|
||
|
||
1. 拥有 Telegram 账号
|
||
2. 在 [my.telegram.org/apps](https://my.telegram.org/apps) 申请个人 API 凭证(免费,约 1 分钟)
|
||
3. 目标频道/群组可访问(公开频道或已加入的私有群组)
|
||
4. 中国大陆用户需配置代理(Telegram 在大陆被屏蔽)
|
||
|
||
---
|
||
|
||
## 3. 使用场景
|
||
|
||
### 场景 A:一次性归档某个频道的历史内容
|
||
|
||
用户希望把某个影视资源 Telegram 频道自 2023 年以来发布的所有 MP4 视频下载到本地。
|
||
|
||
**操作流程:**
|
||
1. 打开 Web 界面,在顶部表单输入频道名(如 `@example_channel`)
|
||
2. 设置开始日期 `2023-01-01`,验证频道有效性
|
||
3. 在 `config.yaml` 中配置 `file_formats.video: [mp4]`(或在界面中设置)
|
||
4. 点击「保存并重启下载」,程序自动遍历频道历史消息,过滤并下载所有 MP4 文件
|
||
5. 下载完成后,文件按 `频道名/年月/` 目录结构整理好
|
||
|
||
---
|
||
|
||
### 场景 B:持续监听新频道更新
|
||
|
||
用户希望每次运行都只下载上次未下载的新内容(增量同步)。
|
||
|
||
**机制:** 每次下载完成后,程序自动把当前最大消息 ID 写入 `config.yaml` 的 `last_read_message_id` 字段,下次运行从该 ID 之后继续,不重复下载。
|
||
|
||
---
|
||
|
||
### 场景 C:通过 Telegram Bot 远程控制
|
||
|
||
用户在服务器上部署程序,配置 `bot_token`,通过向 Bot 发送命令来添加下载任务、查看进度,无需 SSH 进服务器。
|
||
|
||
---
|
||
|
||
### 场景 D:高清视频筛选下载
|
||
|
||
频道中混合了低清和高清视频,用户只想要 1080p 及以上的内容。
|
||
|
||
**配置过滤器:**
|
||
```yaml
|
||
download_filter: media_width >= 1920 and media_height >= 1080
|
||
```
|
||
|
||
---
|
||
|
||
### 场景 E:大文件上传至云盘
|
||
|
||
本地磁盘空间有限,下载后自动通过 Rclone 上传到 Google Drive,并删除本地文件。
|
||
|
||
---
|
||
|
||
## 4. 核心功能
|
||
|
||
### 4.1 媒体批量下载
|
||
|
||
- **支持媒体类型:** audio(音频)、photo(图片)、video(视频)、document(文档/PDF/压缩包等)、voice(语音消息)、video_note(圆形视频消息)、animation(GIF)
|
||
- **文件格式过滤:** 对每种媒体类型可配置允许的格式列表,`all` 表示不限制
|
||
- **并发下载:** 通过 asyncio 队列管理,支持配置最大并发任务数(`max_download_task`)和最大并发传输数(`max_concurrent_transmissions`)
|
||
- **断点续传:** 通过 `last_read_message_id` 记录上次处理到的消息位置,下次启动自动从该位置继续
|
||
- **去重跳过:** 已存在于目标路径且大小一致的文件自动跳过,不重复下载
|
||
- **临时目录机制:** 下载先写入 `temp/` 目录,完成后移动到最终位置,避免半完成文件污染
|
||
|
||
### 4.2 下载过滤器
|
||
|
||
基于 PLY(Python Lex-Yacc)实现的表达式过滤引擎,支持:
|
||
- 按消息日期筛选(最常用)
|
||
- 按文件大小筛选
|
||
- 按视频分辨率筛选
|
||
- 按文件名正则匹配
|
||
- 按消息标题关键字筛选
|
||
- 按视频时长筛选
|
||
- 逻辑组合:`and`、`or`
|
||
|
||
详见 [第9节:下载过滤器语法](#9-下载过滤器语法)。
|
||
|
||
### 4.3 Web 管理界面
|
||
|
||
- **顶部操作栏(横排):** 频道输入+验证、开始/结束日期、保存路径编辑、保存并重启按钮
|
||
- **实时统计头部:** 下载速度、正在下载数、已完成数、已跳过数
|
||
- **当前任务横幅:** 显示正在处理的频道名及当前状态
|
||
- **历史频道网格:** 记录历史使用的频道,点击可快速填入表单
|
||
- **下载进度列表:** 实时展示每个文件的下载进度条、速度
|
||
- **已完成列表:** 展示已完成下载的文件名和大小
|
||
- **暂停/继续控制:** 随时暂停或恢复下载任务
|
||
- **新用户引导向导:** 首次使用时显示 3 步引导(API 凭证获取、代理配置、确认),无需手动编辑配置文件
|
||
|
||
### 4.4 Telegram Bot 控制
|
||
|
||
通过配置 `bot_token` 启用机器人模式:
|
||
- 向 Bot 发送频道链接,Bot 自动添加下载任务
|
||
- 发送命令查看当前下载进度
|
||
- 转发消息给 Bot,Bot 自动下载其中的媒体
|
||
- 权限控制(可限制只有特定用户能使用)
|
||
|
||
### 4.5 云存储上传
|
||
|
||
| 功能 | 说明 |
|
||
|------|------|
|
||
| 上传到 Telegram 聊天 | 下载完成后转发到指定 Telegram 聊天/频道 |
|
||
| Rclone 上传 | 支持所有 Rclone 兼容的云存储(Google Drive、OneDrive、S3、阿里云盘等) |
|
||
| 阿里云盘(Aligo)| 专用适配器,支持阿里云盘 API |
|
||
| 上传前压缩 | 可配置上传前对文件进行 ZIP 压缩 |
|
||
| 上传后删除本地 | 上传成功后自动删除本地文件,节省磁盘空间 |
|
||
|
||
### 4.6 多语言支持
|
||
|
||
支持界面/日志语言:英文(EN)、中文(ZH)、俄文(RU)、乌克兰文(UA),通过 `config.yaml` 中 `language` 字段配置。
|
||
|
||
### 4.7 容器化部署
|
||
|
||
提供完整 Dockerfile 和 docker-compose.yaml,支持:
|
||
- 单命令部署 `docker-compose up -d`
|
||
- 数据卷挂载(配置文件、下载目录)
|
||
- 端口映射(Web 界面)
|
||
|
||
---
|
||
|
||
## 5. 项目架构
|
||
|
||
### 5.1 技术栈
|
||
|
||
| 层级 | 技术 |
|
||
|------|------|
|
||
| Telegram 通信 | pyrogram(自定义 fork,支持最新 TDLib) |
|
||
| 异步框架 | asyncio(Python 原生) |
|
||
| Web 服务 | Flask 2.2.2 + Flask-Login |
|
||
| 配置存储 | YAML(ruamel.yaml 保持格式) |
|
||
| 过滤器引擎 | PLY(Python Lex-Yacc) |
|
||
| 前端 | 原生 HTML/CSS/JS(无框架,深色主题) |
|
||
| 加密 | pycryptodome(AES-128-CBC) |
|
||
| 日志 | loguru + rich |
|
||
| 云存储 | Rclone(子进程调用)、aligo |
|
||
|
||
### 5.2 整体架构图
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ media_downloader.py │
|
||
│ (主进程入口) │
|
||
│ │
|
||
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────┐ │
|
||
│ │ Application │ │ asyncio │ │ Flask Web │ │
|
||
│ │ 配置管理 │ │ 事件循环 │ │ Server │ │
|
||
│ └──────────────┘ └──────┬───────┘ └───────────────┘ │
|
||
│ │ │
|
||
│ ┌────────────────┼──────────────────┐ │
|
||
│ ▼ ▼ ▼ │
|
||
│ ┌─────────────┐ ┌────────────┐ ┌──────────────┐ │
|
||
│ │ 下载主流程 │ │ Worker │ │ Bot 处理 │ │
|
||
│ │ (每个聊天) │ │ 队列处理 │ │ (可选) │ │
|
||
│ └──────┬──────┘ └─────┬──────┘ └──────────────┘ │
|
||
│ │ │ │
|
||
│ ▼ ▼ │
|
||
│ ┌─────────────────────────────────┐ │
|
||
│ │ pyrogram.Client │ │
|
||
│ │ (Telegram MTProto API) │ │
|
||
│ └────────────────┬────────────────┘ │
|
||
└────────────────────┼────────────────────────────────────┘
|
||
│
|
||
┌──────┴──────┐
|
||
│ Telegram │
|
||
│ 服务器 │
|
||
└─────────────┘
|
||
```
|
||
|
||
### 5.3 核心数据流
|
||
|
||
```
|
||
程序启动
|
||
│
|
||
├─ 加载 config.yaml → Application 初始化
|
||
│
|
||
├─ 启动 Flask Web Server(端口 5001)
|
||
│
|
||
├─ 建立 Telegram 连接(pyrogram.Client.start())
|
||
│ └─ 首次运行:提示手机号 + 验证码(终端交互)
|
||
│
|
||
└─ download_all_chat() 主循环
|
||
│
|
||
├─ 对每个 chat(config.yaml 中的 chat 列表):
|
||
│ ├─ get_chat_history_v2() → 逐批获取历史消息(每批 100 条)
|
||
│ ├─ exec_filter() → 应用过滤表达式
|
||
│ ├─ 通过时 → add_download_task() → 压入 asyncio.Queue
|
||
│ └─ 记录 last_read_message_id
|
||
│
|
||
└─ Worker 并发处理队列
|
||
├─ _get_media_meta() → 提取文件名、大小等元数据
|
||
├─ 检查文件是否已存在 → 跳过
|
||
├─ download_media() → 下载到 temp/ 目录
|
||
├─ _check_download_finish() → 校验完整性
|
||
├─ _move_to_download_path() → 移动到最终路径
|
||
├─ [可选] 上传到 Telegram 或云盘
|
||
└─ update_download_status() → 更新 Web 统计数据
|
||
|
||
程序结束
|
||
├─ 等待所有队列任务完成
|
||
├─ 更新 config.yaml 中的 last_read_message_id
|
||
└─ 如 restart_program=True → 重启进程(os.execv)
|
||
```
|
||
|
||
---
|
||
|
||
## 6. 目录结构
|
||
|
||
```
|
||
telegram_media_downloader/
|
||
├── media_downloader.py # 主入口,程序启动和下载编排
|
||
├── config.yaml # 用户配置文件(核心)
|
||
├── requirements.txt # Python 依赖列表
|
||
├── setup.py # 打包配置
|
||
├── Makefile # 快捷命令(install/test/lint)
|
||
├── Dockerfile # Docker 镜像构建文件
|
||
├── docker-compose.yaml # Docker 编排配置
|
||
├── gen_filter_cache.py # 过滤器缓存预生成脚本
|
||
├── README.md # 英文文档
|
||
├── README_CN.md # 中文文档
|
||
├── PRD.md # 本文档
|
||
│
|
||
├── module/ # 核心业务模块
|
||
│ ├── __init__.py
|
||
│ ├── app.py # Application 类、任务节点、配置管理
|
||
│ ├── web.py # Flask Web 服务、所有 HTTP API
|
||
│ ├── bot.py # Telegram Bot 处理逻辑
|
||
│ ├── filter.py # PLY 词法/语法分析过滤引擎
|
||
│ ├── download_stat.py # 下载速度统计、任务进度追踪
|
||
│ ├── get_chat_history_v2.py # 聊天历史异步生成器(优化版)
|
||
│ ├── pyrogram_extension.py # pyrogram 扩展(钩子、进度、上传)
|
||
│ ├── send_media_group_v2.py # 媒体组批量转发
|
||
│ ├── cloud_drive.py # 云盘上传适配器(Rclone/Aligo)
|
||
│ ├── language.py # 多语言翻译字典
|
||
│ ├── parsetab.py # PLY 自动生成的解析表(勿手动修改)
|
||
│ ├── parser.out # PLY 解析调试信息
|
||
│ ├── templates/ # Flask HTML 模板
|
||
│ │ ├── index.html # 主界面(含向导、下载控制)
|
||
│ │ ├── login.html # 登录页面
|
||
│ │ └── control.html # 旧版控制页面(已由 index.html 统一)
|
||
│ └── static/ # Web 静态资源
|
||
│ ├── css/
|
||
│ ├── layui/ # Layui 前端框架(旧版残留)
|
||
│ ├── request/ # JS 请求库
|
||
│ ├── login/ # 登录页样式
|
||
│ └── aes/ # AES 加密 JS 库
|
||
│
|
||
├── utils/ # 通用工具类库
|
||
│ ├── __init__.py # 版本号定义(__version__ = "2.2.5")
|
||
│ ├── crypto.py # AES-128-CBC 加密解密
|
||
│ ├── file_management.py # 文件操作辅助函数
|
||
│ ├── format.py # 字节格式化、日期时间处理、URL 解析
|
||
│ ├── log.py # werkzeug 日志过滤器
|
||
│ ├── meta.py # 元数据打印工具
|
||
│ ├── meta_data.py # MetaData 类(过滤器属性集合)
|
||
│ ├── platform.py # 跨平台(Windows/Linux/macOS)检测
|
||
│ └── updates.py # 版本更新检查
|
||
│
|
||
├── tests/ # 单元测试
|
||
│ ├── test_common.py
|
||
│ ├── test_media_downloader.py
|
||
│ ├── module/
|
||
│ │ └── test_app.py
|
||
│ └── utils/
|
||
│ ├── test_cypto.py
|
||
│ ├── test_filter.py
|
||
│ ├── test_file_management.py
|
||
│ ├── test_format.py
|
||
│ ├── test_log.py
|
||
│ ├── test_meta.py
|
||
│ └── test_updates.py
|
||
│
|
||
└── temp/ # 下载临时目录(运行时自动创建)
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 核心模块详解
|
||
|
||
### 7.1 `media_downloader.py` — 主入口
|
||
|
||
**职责:** 程序生命周期管理、异步任务编排、下载流程控制。
|
||
|
||
| 函数 | 说明 |
|
||
|------|------|
|
||
| `main()` | 程序主入口,创建 pyrogram 客户端,启动 Web/Bot 服务,进入下载主循环 |
|
||
| `run_with_restart()` | 包装 main(),支持程序自动重启(`_app.restart_program = True` 时触发) |
|
||
| `download_all_chat()` | 遍历 config 中所有聊天,依次调用 `download_chat_task` |
|
||
| `download_chat_task()` | 单个聊天的完整下载流程:获取历史 → 过滤 → 入队 |
|
||
| `download_task()` | 处理单条消息的下载:元数据提取 → 去重 → 下载 → 移动 → 上传 |
|
||
| `download_media()` | 调用 pyrogram API 执行实际文件下载,写入 temp/ |
|
||
| `worker()` | asyncio Queue 消费者,循环从队列取任务并调用 `download_task` |
|
||
| `add_download_task()` | 将消息包装为任务节点,压入 asyncio.Queue |
|
||
| `_get_media_meta()` | 从 pyrogram Message 对象提取文件名、大小、扩展名等元数据 |
|
||
| `save_msg_to_file()` | 将纯文本消息保存为 .txt 文件(需配置 `enable_download_txt`) |
|
||
|
||
**重启机制:**
|
||
```python
|
||
# 任意地方设置此标志:
|
||
_app.restart_program = True
|
||
|
||
# run_with_restart() 检测到此标志后执行:
|
||
os.execv(sys.executable, [sys.executable] + sys.argv)
|
||
```
|
||
|
||
---
|
||
|
||
### 7.2 `module/app.py` — 应用配置管理
|
||
|
||
**职责:** 配置文件的读取/写入、任务节点数据结构定义、过滤器执行。
|
||
|
||
#### 核心枚举
|
||
|
||
```python
|
||
class DownloadState(Enum):
|
||
Downloading = 1 # 正在下载
|
||
StopDownload = 2 # 已停止(暂停)
|
||
|
||
class DownloadStatus(Enum):
|
||
SkipDownload = 1 # 已跳过(文件已存在)
|
||
SuccessDownload = 2 # 下载成功
|
||
FailedDownload = 3 # 下载失败
|
||
Downloading = 4 # 下载中
|
||
```
|
||
|
||
#### 核心类
|
||
|
||
**`ChatDownloadConfig`** — 单个聊天的下载配置:
|
||
|
||
| 属性 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `chat_id` | str/int | 聊天标识符 |
|
||
| `last_read_message_id` | int | 最后读取的消息ID(断点续传依据) |
|
||
| `download_filter` | str | 下载过滤表达式 |
|
||
| `ids_to_retry` | list | 失败需重试的消息ID列表 |
|
||
|
||
**`TaskNode`** — 单次下载任务的运行时状态:
|
||
|
||
| 属性 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `chat_id` | str/int | 所属聊天 |
|
||
| `total_task` | int | 本次任务总消息数 |
|
||
| `download_status` | dict | {message_id: DownloadStatus} |
|
||
| `is_running` | bool | 是否正在运行 |
|
||
| `upload_success_count` | int | 上传成功计数 |
|
||
|
||
**`Application`** — 全局应用实例:
|
||
|
||
| 属性 | 说明 |
|
||
|------|------|
|
||
| `config` | 完整的 YAML 配置字典 |
|
||
| `chat_download_config` | {chat_id: ChatDownloadConfig} |
|
||
| `save_path` | 下载根目录路径 |
|
||
| `api_id / api_hash` | Telegram API 凭证 |
|
||
| `media_types` | 要下载的媒体类型列表 |
|
||
| `file_formats` | 各媒体类型的格式白名单 |
|
||
| `file_path_prefix` | 目录结构组件列表 |
|
||
| `file_name_prefix` | 文件名前缀组件列表 |
|
||
| `proxy` | 代理配置字典 |
|
||
| `restart_program` | 重启标志(设为 True 触发重启) |
|
||
| `cloud_drive_config` | 云盘配置 |
|
||
|
||
---
|
||
|
||
### 7.3 `module/web.py` — Web 服务
|
||
|
||
**职责:** Flask HTTP 服务、用户认证、前端 API、配置管理、频道历史。
|
||
|
||
**初始化方式(依赖注入):**
|
||
|
||
```python
|
||
def init_web(app, client, add_download_task_func, download_chat_task_func):
|
||
"""
|
||
由 media_downloader.py 在启动时调用,注入全局依赖:
|
||
- app: Application 实例
|
||
- client: pyrogram.Client 实例
|
||
- add_download_task_func: 添加下载任务的回调
|
||
- download_chat_task_func: 下载聊天任务的回调
|
||
"""
|
||
```
|
||
|
||
**频道历史存储:** 保存在 `module/channel_history.json`,结构如下:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"chat_id": "example_channel",
|
||
"chat_title": "示例频道",
|
||
"chat_type": "CHANNEL",
|
||
"last_used": "2026-04-06T12:00:00"
|
||
}
|
||
]
|
||
```
|
||
|
||
**登录认证:**
|
||
- 密码在 `config.yaml` 的 `web_login_secret` 字段配置(明文,传输时 AES 加密)
|
||
- 未配置 `web_login_secret` 时自动跳过登录(本地开发模式)
|
||
- 使用 Flask-Login 管理会话
|
||
|
||
---
|
||
|
||
### 7.4 `module/filter.py` — 过滤引擎
|
||
|
||
**职责:** 将过滤表达式字符串解析并编译为可执行的过滤函数。
|
||
|
||
**技术实现:** 使用 PLY(Python Lex-Yacc)构建词法分析器和语法分析器,将表达式 AST 转换为 Python 可调用对象。
|
||
|
||
**支持的可过滤属性(`utils/meta_data.py` 中 `MetaData` 类定义):**
|
||
|
||
| 属性名 | 数据类型 | 说明 |
|
||
|--------|---------|------|
|
||
| `message_date` | datetime | 消息发送时间 |
|
||
| `message_id` | int | 消息 ID |
|
||
| `media_file_size` | int | 文件大小(字节) |
|
||
| `media_width` | int | 图片/视频宽度(像素) |
|
||
| `media_height` | int | 图片/视频高度(像素) |
|
||
| `media_file_name` | str | 文件名(含扩展名) |
|
||
| `message_caption` | str | 消息说明文字 |
|
||
| `media_duration` | int | 视频/音频时长(秒) |
|
||
| `sender_id` | int | 发送者用户 ID |
|
||
| `sender_name` | str | 发送者名称 |
|
||
| `reply_to_message_id` | int | 被回复的消息 ID |
|
||
|
||
---
|
||
|
||
### 7.5 `module/download_stat.py` — 下载统计
|
||
|
||
**职责:** 全局下载速度计算、任务进度数据的维护(供 Web API 消费)。
|
||
|
||
**核心全局数据(`_download_result`):**
|
||
|
||
```python
|
||
_download_result: dict = {
|
||
"chat_id_1": {
|
||
message_id_1: {
|
||
"down_byte": 已下载字节数(int),
|
||
"total_size": 文件总字节数(int),
|
||
"file_name": 完整文件路径(str),
|
||
"download_speed": 当前速度(bytes/s,int),
|
||
"start_time": 开始时间戳(float),
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**任务进度数据(`_task_progress`):**
|
||
|
||
```python
|
||
_task_progress: dict = {
|
||
"current_chat": 当前处理的聊天 ID(str),
|
||
"current_chat_title": 当前聊天标题(str),
|
||
"checked_messages": 已检查的消息总数(int),
|
||
"skipped_files": 已跳过的文件数(int),
|
||
"downloading_files": 正在下载的文件数(int),
|
||
"completed_files": 已完成的文件数(int),
|
||
"failed_files": 失败的文件数(int),
|
||
"is_checking": 是否正在扫描消息(bool),
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 7.6 `module/pyrogram_extension.py` — pyrogram 扩展
|
||
|
||
**职责:** 扩展 pyrogram 客户端功能,包括下载进度回调、上传功能、权限检查。
|
||
|
||
**核心功能:**
|
||
|
||
1. **`HookClient`** — 继承 `pyrogram.Client`,支持自定义钩子:
|
||
- `on_download_start` — 下载开始时回调
|
||
- `on_download_progress` — 下载进度更新回调
|
||
- `on_download_finish` — 下载完成回调
|
||
|
||
2. **`record_download_status`** — 装饰器,自动将下载进度写入 `download_stat.py` 的统计数据。
|
||
|
||
3. **上传功能:**
|
||
- `upload_telegram_chat()` — 上传文件到指定 Telegram 聊天
|
||
- 通过 cloud_drive.py 上传到云存储
|
||
|
||
4. **`get_extension(file_id, mime_type)`** — 根据 Telegram 文件 ID 或 MIME 类型推断文件扩展名。
|
||
|
||
5. **`check_user_permission(user_id)`** — 检查用户是否在白名单中(Bot 模式权限控制)。
|
||
|
||
---
|
||
|
||
### 7.7 `module/cloud_drive.py` — 云盘上传
|
||
|
||
**支持适配器:**
|
||
|
||
| 适配器 | 说明 | 配置字段 |
|
||
|--------|------|---------|
|
||
| `rclone` | 通用云存储(100+ 服务) | `upload_adapter: rclone` |
|
||
| `aligo` | 阿里云盘专用 | `upload_adapter: aligo` |
|
||
|
||
**配置示例(config.yaml):**
|
||
|
||
```yaml
|
||
cloud_drive_config:
|
||
enable_upload_file: true
|
||
upload_adapter: rclone # 或 aligo
|
||
remote_dir: "gdrive:/telegram" # Rclone 远程路径
|
||
before_upload_file_zip: false # 上传前是否压缩
|
||
after_upload_file_delete: true # 上传成功后删除本地文件
|
||
```
|
||
|
||
---
|
||
|
||
## 8. 配置项完整说明
|
||
|
||
配置文件路径:`config.yaml`(项目根目录)
|
||
|
||
### 8.1 必填项
|
||
|
||
| 字段 | 类型 | 示例 | 说明 |
|
||
|------|------|------|------|
|
||
| `api_id` | int | `12345678` | Telegram API ID,从 my.telegram.org 获取 |
|
||
| `api_hash` | str | `"abcdef1234..."` | Telegram API Hash,32位字符串 |
|
||
| `chat` | list | 见下方 | 下载目标配置列表 |
|
||
| `save_path` | str | `"/Users/xx/Downloads/tg"` | 文件保存根目录(绝对路径) |
|
||
|
||
### 8.2 聊天配置(`chat` 列表元素)
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `chat_id` | str/int | — | 频道/群组用户名(`@xxx`或`xxx`)或数字 ID |
|
||
| `last_read_message_id` | int | `0` | 上次读取到的消息 ID,断点续传依据,程序自动更新 |
|
||
| `download_filter` | str | 无 | 过滤表达式,见第9节 |
|
||
|
||
### 8.3 媒体类型和格式
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `media_types` | list | `[audio, photo, video, document]` | 要下载的媒体类型 |
|
||
| `file_formats.audio` | list | `[all]` | 允许的音频格式,`all` 不限制 |
|
||
| `file_formats.video` | list | `[all]` | 允许的视频格式 |
|
||
| `file_formats.document` | list | `[all]` | 允许的文档格式 |
|
||
|
||
**有效媒体类型值:** `audio`、`photo`、`video`、`document`、`voice`、`video_note`、`animation`
|
||
|
||
### 8.4 文件路径配置
|
||
|
||
| 字段 | 类型 | 示例 | 说明 |
|
||
|------|------|------|------|
|
||
| `file_path_prefix` | list | `[chat_title, media_datetime]` | 目录层级结构组件,顺序即目录嵌套顺序 |
|
||
| `file_name_prefix` | list | `[message_id]` | 文件名前缀组件 |
|
||
|
||
**`file_path_prefix` 可用值:**
|
||
- `chat_title` — 频道/群组名称
|
||
- `media_datetime` — 媒体发布的年月(格式 `2024_01`)
|
||
- `media_type` — 媒体类型(audio/video/photo/document)
|
||
|
||
**`file_name_prefix` 可用值:**
|
||
- `message_id` — 消息 ID
|
||
- `caption` — 消息说明文字(截断处理)
|
||
- `chat_title` — 聊天标题
|
||
|
||
### 8.5 Web 服务配置
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `web_host` | str | `"127.0.0.1"` | Web 服务绑定地址,服务器部署改为 `"0.0.0.0"` |
|
||
| `web_port` | int | `5000` | Web 服务端口 |
|
||
| `web_login_secret` | str | 无(跳过登录) | Web 界面登录密码,AES 加密传输 |
|
||
|
||
### 8.6 代理配置
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `proxy.scheme` | str | 代理类型:`socks5` 或 `http` |
|
||
| `proxy.hostname` | str | 代理服务器地址,本地代理填 `"127.0.0.1"` |
|
||
| `proxy.port` | int | 代理端口(Clash SOCKS5: 7891,HTTP: 7890;V2Ray: 10808/10809) |
|
||
|
||
**常见代理软件对应配置:**
|
||
|
||
| 代理软件 | SOCKS5 端口 | HTTP 端口 | 推荐配置 |
|
||
|---------|------------|----------|---------|
|
||
| Clash | 7891 | 7890 | `scheme: socks5, port: 7891` |
|
||
| 狗子云(VPN模式) | 无 | 7890 | `scheme: http, port: 7890` |
|
||
| V2Ray | 10808 | 10809 | `scheme: socks5, port: 10808` |
|
||
| Shadowsocks | 1080 | — | `scheme: socks5, port: 1080` |
|
||
|
||
### 8.7 性能配置
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `max_download_task` | int | `5` | 最大并发下载任务数 |
|
||
| `max_concurrent_transmissions` | int | `1` | 单个文件的并发分片传输数 |
|
||
|
||
### 8.8 其他配置
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `language` | str | `"EN"` | 界面语言:`EN`/`ZH`/`RU`/`UA` |
|
||
| `log_level` | str | `"INFO"` | 日志级别:`DEBUG`/`INFO`/`WARNING`/`ERROR` |
|
||
| `enable_download_txt` | bool | `false` | 是否将纯文本消息保存为 .txt 文件 |
|
||
| `hide_file_name` | bool | `false` | Web 界面是否隐藏下载文件名(隐私模式) |
|
||
| `bot_token` | str | 无 | Telegram Bot Token,启用 Bot 模式 |
|
||
| `allowed_user_ids` | list | 无(不限制) | 允许使用 Bot 的用户 ID 白名单 |
|
||
|
||
---
|
||
|
||
## 9. 下载过滤器语法
|
||
|
||
过滤器配置在 `config.yaml` 的 `chat[i].download_filter` 字段中。
|
||
|
||
### 9.1 基本语法
|
||
|
||
```
|
||
<属性名> <操作符> <值> [and/or <条件2>]
|
||
```
|
||
|
||
### 9.2 操作符
|
||
|
||
| 操作符 | 适用类型 | 示例 |
|
||
|--------|---------|------|
|
||
| `>=` | 数字、日期 | `media_file_size >= 1024` |
|
||
| `<=` | 数字、日期 | `message_date <= 2024-12-31 23:59:59` |
|
||
| `>` | 数字、日期 | `media_width > 1920` |
|
||
| `<` | 数字、日期 | `media_duration < 3600` |
|
||
| `==` | 数字、字符串 | `sender_id == 123456` |
|
||
| `!=` | 数字、字符串 | `sender_id != 123456` |
|
||
| `matches` | 字符串 | `media_file_name matches ".*\.mp4$"` |
|
||
| `contains` | 字符串 | `message_caption contains "4K"` |
|
||
|
||
### 9.3 逻辑组合
|
||
|
||
```
|
||
# AND:两个条件都满足
|
||
message_date >= 2024-01-01 00:00:00 and message_date <= 2024-12-31 23:59:59
|
||
|
||
# OR:任一条件满足
|
||
media_file_name matches ".*\.mp4$" or media_file_name matches ".*\.mkv$"
|
||
|
||
# 复合条件
|
||
message_date >= 2024-01-01 00:00:00 and media_file_size >= 10485760
|
||
```
|
||
|
||
### 9.4 完整示例
|
||
|
||
```yaml
|
||
# 示例1:只下载 2024 年的内容
|
||
download_filter: message_date >= 2024-01-01 00:00:00 and message_date <= 2024-12-31 23:59:59
|
||
|
||
# 示例2:只下载大于 10MB 的文件
|
||
download_filter: media_file_size >= 10485760
|
||
|
||
# 示例3:只下载 1080p 及以上的视频
|
||
download_filter: media_width >= 1920 and media_height >= 1080
|
||
|
||
# 示例4:只下载文件名包含特定字符串的文件
|
||
download_filter: media_file_name matches ".*\\.720p.*"
|
||
|
||
# 示例5:只下载标题含关键字的消息
|
||
download_filter: message_caption contains "完整版"
|
||
|
||
# 示例6:下载特定时间段内的大文件视频
|
||
download_filter: message_date >= 2023-06-01 00:00:00 and media_file_size >= 52428800 and media_duration >= 600
|
||
```
|
||
|
||
### 9.5 日期格式规范
|
||
|
||
日期必须使用格式:`YYYY-MM-DD HH:MM:SS`,例如:
|
||
- `2024-01-18 00:00:00`(起始日期,时间设 00:00:00)
|
||
- `2024-12-31 23:59:59`(结束日期,时间设 23:59:59)
|
||
|
||
---
|
||
|
||
## 10. Web 界面 API 接口
|
||
|
||
Base URL:`http://127.0.0.1:5001`(默认,端口可配置)
|
||
|
||
### 10.1 无需认证的接口
|
||
|
||
#### `GET /api/setup_status`
|
||
检测当前配置完成度,用于判断是否需要显示新用户引导向导。
|
||
|
||
**响应:**
|
||
```json
|
||
{
|
||
"has_api_credentials": true, // api_id 和 api_hash 是否已配置且有效
|
||
"has_session": true, // 是否已有 Telegram 登录会话文件
|
||
"has_chat": true, // 是否已配置了至少一个聊天
|
||
"proxy": {
|
||
"scheme": "http",
|
||
"hostname": "127.0.0.1",
|
||
"port": 7890
|
||
},
|
||
"save_path": "/Users/xx/Downloads/tg"
|
||
}
|
||
```
|
||
|
||
#### `POST /api/save_initial_config`
|
||
保存初始配置(新用户引导第3步使用),无需登录。
|
||
|
||
**请求体:**
|
||
```json
|
||
{
|
||
"api_id": 12345678,
|
||
"api_hash": "abcdef...",
|
||
"proxy_enabled": true,
|
||
"proxy_scheme": "http",
|
||
"proxy_hostname": "127.0.0.1",
|
||
"proxy_port": 7890,
|
||
"save_path": "/Users/xx/Downloads/tg"
|
||
}
|
||
```
|
||
|
||
**响应:**
|
||
```json
|
||
{ "success": true, "message": "配置已保存,程序将重启" }
|
||
```
|
||
|
||
#### `GET /get_app_version`
|
||
**响应:** `"2.2.5"`(纯文本)
|
||
|
||
---
|
||
|
||
### 10.2 需要认证的接口
|
||
|
||
所有以下接口在设置了 `web_login_secret` 时需要先登录,否则返回 302 重定向到 `/login`。
|
||
|
||
#### `GET /get_download_status`
|
||
获取实时下载速度和状态。
|
||
|
||
**响应:**
|
||
```json
|
||
{
|
||
"download_speed": "1.23 MB/s",
|
||
"upload_speed": "0.00 B/s",
|
||
"state": "pause" // "pause" = 下载中,"continue" = 已暂停
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### `GET /api/task_progress`
|
||
获取当前任务详细进度。
|
||
|
||
**响应:**
|
||
```json
|
||
{
|
||
"current_chat": "example_channel",
|
||
"current_chat_title": "示例频道",
|
||
"checked_messages": 1234,
|
||
"skipped_files": 567,
|
||
"downloading_files": 3,
|
||
"completed_files": 890,
|
||
"failed_files": 2,
|
||
"is_checking": false
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### `POST /set_download_state?state=pause`
|
||
暂停或继续下载。
|
||
|
||
| state 参数 | 效果 |
|
||
|-----------|------|
|
||
| `pause` | 暂停下载 |
|
||
| `continue` | 继续下载 |
|
||
|
||
**响应:** `"pause"` 或 `"continue"`(纯文本,表示操作后的新状态)
|
||
|
||
---
|
||
|
||
#### `GET /api/get_config`
|
||
获取当前配置信息(供 Web 界面初始化表单)。
|
||
|
||
**响应:**
|
||
```json
|
||
{
|
||
"chat_id": "example_channel",
|
||
"download_filter": "message_date >= 2024-01-01 00:00:00",
|
||
"save_path": "/Users/xx/Downloads/tg"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### `POST /api/validate_chat`
|
||
验证频道/群组是否可访问(连通 Telegram 服务器查询)。
|
||
|
||
**请求体:**
|
||
```json
|
||
{ "chat_id": "example_channel" }
|
||
```
|
||
|
||
**响应(成功):**
|
||
```json
|
||
{
|
||
"valid": true,
|
||
"chat_id": "example_channel",
|
||
"chat_title": "示例频道",
|
||
"chat_type": "CHANNEL" // CHANNEL / SUPERGROUP / GROUP / PRIVATE
|
||
}
|
||
```
|
||
|
||
**响应(失败):**
|
||
```json
|
||
{
|
||
"valid": false,
|
||
"error": "Chat not found"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### `POST /api/save_path`
|
||
修改文件保存路径(立即生效,无需重启)。
|
||
|
||
**请求体:**
|
||
```json
|
||
{ "save_path": "/new/save/path" }
|
||
```
|
||
|
||
**响应:**
|
||
```json
|
||
{ "success": true, "save_path": "/new/save/path" }
|
||
```
|
||
|
||
---
|
||
|
||
#### `POST /api/save_and_restart`
|
||
保存下载配置并重启程序(最常用操作)。
|
||
|
||
**请求体:**
|
||
```json
|
||
{
|
||
"chat_id": "example_channel",
|
||
"start_date": "2024-01-01",
|
||
"end_date": "2024-12-31", // 可为空
|
||
"chat_title": "示例频道",
|
||
"chat_type": "CHANNEL"
|
||
}
|
||
```
|
||
|
||
**响应:**
|
||
```json
|
||
{ "success": true, "message": "配置已保存,程序正在重启" }
|
||
```
|
||
|
||
---
|
||
|
||
#### `POST /api/start_download`
|
||
动态启动下载任务(**不重启程序**,直接将任务加入当前运行队列)。
|
||
|
||
**请求体(同 save_and_restart)**
|
||
|
||
**响应:**
|
||
```json
|
||
{ "success": true, "message": "下载任务已启动" }
|
||
```
|
||
|
||
---
|
||
|
||
#### `GET /api/channel_history`
|
||
获取频道历史记录列表(按最近使用排序)。
|
||
|
||
**响应:**
|
||
```json
|
||
{
|
||
"success": true,
|
||
"history": [
|
||
{
|
||
"chat_id": "example_channel",
|
||
"chat_title": "示例频道",
|
||
"chat_type": "CHANNEL",
|
||
"last_used": "2026-04-06T12:00:00"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### `DELETE /api/channel_history/<chat_id>`
|
||
删除指定频道的历史记录。
|
||
|
||
**响应:** `{ "success": true, "message": "已删除" }`
|
||
|
||
---
|
||
|
||
#### `POST /api/channel_history/clear`
|
||
清空所有频道历史记录。
|
||
|
||
**响应:** `{ "success": true, "message": "已清空" }`
|
||
|
||
---
|
||
|
||
#### `GET /get_download_list?already_down=false`
|
||
获取下载文件列表。
|
||
|
||
| 参数 | 值 | 说明 |
|
||
|-----|-----|------|
|
||
| `already_down` | `false` | 返回正在下载的文件列表 |
|
||
| `already_down` | `true` | 返回已完成下载的文件列表 |
|
||
|
||
**响应(JSON 数组):**
|
||
```json
|
||
[
|
||
{
|
||
"chat": "example_channel",
|
||
"id": "12345",
|
||
"filename": "video.mp4",
|
||
"total_size": "1.23 GB",
|
||
"download_progress": "45.6",
|
||
"download_speed": "2.34 MB/s",
|
||
"save_path": "/Users/xx/Downloads/tg/示例频道/2024_01/video.mp4"
|
||
}
|
||
]
|
||
```
|
||
|
||
---
|
||
|
||
## 11. 数据结构
|
||
|
||
### 11.1 `config.yaml` 完整示例
|
||
|
||
```yaml
|
||
# ── Telegram API 凭证(必填)──
|
||
api_id: 12345678
|
||
api_hash: abcdef1234567890abcdef1234567890
|
||
|
||
# ── 下载目标列表(至少一个)──
|
||
chat:
|
||
- chat_id: example_channel
|
||
last_read_message_id: 0 # 程序运行后自动更新,勿手动修改
|
||
download_filter: message_date >= 2024-01-01 00:00:00
|
||
|
||
# ── 媒体类型 ──
|
||
media_types:
|
||
- audio
|
||
- photo
|
||
- video
|
||
- document
|
||
- voice
|
||
- video_note
|
||
|
||
# ── 文件格式过滤 ──
|
||
file_formats:
|
||
audio:
|
||
- all
|
||
document:
|
||
- all
|
||
video:
|
||
- all
|
||
|
||
# ── 目录/文件名结构 ──
|
||
file_path_prefix:
|
||
- chat_title
|
||
- media_datetime
|
||
|
||
# ── 保存路径(必填)──
|
||
save_path: /Users/username/Downloads/telegram_downloads
|
||
|
||
# ── Web 界面 ──
|
||
web_host: 127.0.0.1
|
||
web_port: 5001
|
||
# web_login_secret: your_password # 注释掉则不需要密码
|
||
|
||
# ── 代理(大陆必填)──
|
||
proxy:
|
||
scheme: http # 或 socks5
|
||
hostname: 127.0.0.1
|
||
port: 7890
|
||
|
||
# ── 可选高级配置 ──
|
||
language: ZH
|
||
max_download_task: 5
|
||
enable_download_txt: false
|
||
|
||
# ── Bot 模式(可选)──
|
||
# bot_token: 1234567890:AAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||
# allowed_user_ids: [123456789]
|
||
|
||
# ── 云盘上传(可选)──
|
||
# cloud_drive_config:
|
||
# enable_upload_file: true
|
||
# upload_adapter: rclone
|
||
# remote_dir: "gdrive:/Telegram"
|
||
# after_upload_file_delete: true
|
||
```
|
||
|
||
### 11.2 `channel_history.json` 结构
|
||
|
||
```json
|
||
[
|
||
{
|
||
"chat_id": "example_channel",
|
||
"chat_title": "示例频道",
|
||
"chat_type": "CHANNEL",
|
||
"last_used": "2026-04-06T12:34:56.789000"
|
||
}
|
||
]
|
||
```
|
||
|
||
---
|
||
|
||
## 12. 下载目录结构
|
||
|
||
下载文件的存储结构由 `file_path_prefix` 和 `file_name_prefix` 两个配置项控制。
|
||
|
||
### 12.1 默认结构(`file_path_prefix: [chat_title, media_datetime]`)
|
||
|
||
```
|
||
save_path/
|
||
├── 示例频道/ ← chat_title
|
||
│ ├── 2024_01/ ← media_datetime (YYYY_MM)
|
||
│ │ ├── 1001 - video_001.mp4 ← message_id - 文件名
|
||
│ │ ├── 1002 - photo_001.jpg
|
||
│ │ └── 1003 - document.pdf
|
||
│ └── 2024_02/
|
||
│ └── ...
|
||
├── 另一个频道/
|
||
│ └── ...
|
||
└── temp/ ← 下载中的临时文件
|
||
└── ...(下载完成后自动清理)
|
||
```
|
||
|
||
### 12.2 按媒体类型分目录(`file_path_prefix: [chat_title, media_type]`)
|
||
|
||
```
|
||
save_path/
|
||
└── 示例频道/
|
||
├── video/
|
||
│ ├── video_001.mp4
|
||
│ └── video_002.mkv
|
||
├── photo/
|
||
│ └── photo_001.jpg
|
||
├── audio/
|
||
└── document/
|
||
```
|
||
|
||
---
|
||
|
||
## 13. 安装与运行
|
||
|
||
### 13.1 环境要求
|
||
|
||
- Python 3.7+
|
||
- 网络可访问 Telegram 服务器(大陆需代理)
|
||
- 已申请 Telegram API 凭证
|
||
|
||
### 13.2 本地安装
|
||
|
||
```bash
|
||
# 克隆仓库
|
||
git clone https://github.com/tangyoha/telegram_media_downloader.git
|
||
cd telegram_media_downloader
|
||
|
||
# 安装依赖
|
||
pip3 install -r requirements.txt
|
||
# 或使用 Makefile
|
||
make install
|
||
|
||
# 编辑配置文件(必须)
|
||
# 填写 api_id, api_hash, save_path, chat(或使用 Web 向导)
|
||
nano config.yaml
|
||
|
||
# 启动
|
||
python3 media_downloader.py
|
||
```
|
||
|
||
### 13.3 首次运行登录流程
|
||
|
||
```
|
||
程序启动
|
||
↓
|
||
提示输入手机号:Enter phone number: +86138...
|
||
↓
|
||
提示输入验证码(Telegram App 内收件箱):Enter OTP: 12345
|
||
↓
|
||
(可能需要)输入两步验证密码:Enter password: ****
|
||
↓
|
||
登录成功,生成 session 文件(项目根目录,*.session)
|
||
↓
|
||
后续运行无需重新登录(session 文件保存登录状态)
|
||
```
|
||
|
||
**注意:** session 文件是登录凭证,请妥善保管,不要提交到代码仓库。
|
||
|
||
### 13.4 Docker 部署
|
||
|
||
```bash
|
||
# 方式一:使用 docker-compose(推荐)
|
||
# 修改 docker-compose.yaml 中的卷挂载路径
|
||
docker-compose up -d
|
||
|
||
# 方式二:手动运行容器
|
||
docker pull tangyoha/telegram_media_downloader:latest
|
||
docker run -d \
|
||
-p 5000:5000 \
|
||
-v $(pwd)/config.yaml:/app/config.yaml \
|
||
-v /your/download/path:/downloads \
|
||
tangyoha/telegram_media_downloader:latest
|
||
```
|
||
|
||
### 13.5 访问 Web 界面
|
||
|
||
启动后访问:`http://localhost:5001`(端口以 config.yaml 中 `web_port` 为准)
|
||
|
||
---
|
||
|
||
## 14. 依赖说明
|
||
|
||
### 14.1 核心依赖
|
||
|
||
| 库 | 版本 | 用途 | 说明 |
|
||
|----|------|------|------|
|
||
| pyrogram | 自定义 fork | Telegram MTProto 客户端 | 使用 tangyoha 的修补版,修复了若干上游问题 |
|
||
| PyTgCrypto | 1.2.6 | Telegram 加密 | pyrogram 的加密加速依赖 |
|
||
| ruamel.yaml | 0.17.21 | YAML 读写 | 保持 YAML 注释和格式,用于写回 config.yaml |
|
||
| PyYAML | 5.3.1 | YAML 解析 | 兼容性保留 |
|
||
| flask | 2.2.2 | Web 框架 | 提供 HTTP 服务和模板渲染 |
|
||
| flask-login | 0.6.2 | 会话认证 | Web 界面登录管理 |
|
||
| Werkzeug | 2.2.2 | WSGI 工具 | Flask 依赖,HTTP 服务底层 |
|
||
| pycryptodome | 3.18.0 | AES 加密 | Web 密码加密传输 |
|
||
| ply | 3.11 | 词法/语法分析 | 下载过滤器表达式引擎 |
|
||
| loguru | 0.6.0 | 日志 | 结构化彩色日志输出 |
|
||
| rich | 12.5.1 | 终端输出 | 彩色进度显示 |
|
||
| requests | 2.32.3 | HTTP 请求 | 版本更新检查 |
|
||
|
||
### 14.2 可选依赖
|
||
|
||
| 库 | 用途 |
|
||
|----|------|
|
||
| rclone | 云存储上传(外部命令,非 Python 包) |
|
||
| aligo | 阿里云盘上传 |
|
||
|
||
---
|
||
|
||
## 15. 当前限制与已知问题
|
||
|
||
### 15.1 功能限制
|
||
|
||
| 限制 | 描述 | 影响 |
|
||
|------|------|------|
|
||
| 终端首次登录 | 首次运行必须在终端手动输入手机号+验证码,不支持纯 Web 引导完成登录 | 服务器无头部署不便 |
|
||
| 无内置调度 | 没有定时任务功能,需借助外部 cron 实现周期性运行 | 无法自动增量同步 |
|
||
| 频道列表硬编码 | config.yaml 中的 chat 列表需手动编辑或通过 Web 界面覆盖,不支持多频道并存管理 | 多频道管理不便 |
|
||
| 单进程架构 | 所有下载在一个进程中,重启会中断当前任务 | 更新配置代价大 |
|
||
| 无下载队列持久化 | 程序重启后,未完成的队列任务丢失 | 中断恢复能力弱 |
|
||
| Web 界面无 HTTPS | Web 服务仅 HTTP,暴露在公网有安全风险 | 服务器部署需额外加固 |
|
||
|
||
### 15.2 已知技术问题
|
||
|
||
| 问题 | 原因 | 临时解决方案 |
|
||
|------|------|------------|
|
||
| 代理配置敏感 | pyrogram 直连 Telegram DC IP,不走系统代理,必须在 config.yaml 中显式配置代理 | 确保代理软件开启了 SOCKS5/HTTP 端口 |
|
||
| Flask 模板缓存 | 非 debug 模式下 Jinja2 不自动重载模板,修改 HTML 后需重启服务 | 重启服务进程 |
|
||
| PLY 解析表文件 | `parsetab.py` 是自动生成的,不应手动修改,但提交到了版本库中 | 保持不修改此文件 |
|
||
| 私有频道下载受限 | 必须以账号身份加入该私有频道才能下载,Bot Token 无法访问普通私有频道 | 用账号加入频道后再配置下载 |
|
||
|
||
### 15.3 性能特性
|
||
|
||
- 历史消息获取速度受 Telegram API 频率限制(大频道可能需要数分钟至数小时扫描)
|
||
- 并发下载数默认 5,可通过 `max_download_task` 调高,但过高可能触发 Telegram 限流
|
||
- 临时文件在 `temp/` 目录,建议 `temp/` 和最终保存路径在同一磁盘分区(避免跨分区移动开销)
|
||
|
||
---
|
||
|
||
## 16. 优化建议与迭代方向
|
||
|
||
### 16.1 高优先级(影响核心体验)
|
||
|
||
#### 1. Web 引导完成 Telegram 登录
|
||
**现状:** 首次登录必须在终端交互完成,对服务器部署和非技术用户极不友好。
|
||
**建议:** 在 Web 向导第4步中,通过轮询 `/api/login_status` 接口感知登录状态,或通过 WebSocket 推送终端输出,在 Web 界面内完成手机号+验证码输入。
|
||
|
||
#### 2. 下载任务持久化
|
||
**现状:** 程序重启后,正在进行的任务从队列消失(只有 `last_read_message_id` 之前的已读记录)。
|
||
**建议:** 将 asyncio Queue 的待处理任务序列化到 SQLite 或 JSON 文件,重启后自动恢复。
|
||
|
||
#### 3. 多频道独立配置管理
|
||
**现状:** `save_and_restart` 接口会覆盖 config.yaml 中的 `chat` 列表为单个频道,不支持同时配置多频道。
|
||
**建议:** Web 界面支持频道列表管理,增删改每个频道的配置,而不是每次覆盖。
|
||
|
||
---
|
||
|
||
### 16.2 中优先级(提升使用效率)
|
||
|
||
#### 4. 内置定时任务(增量同步调度器)
|
||
**建议:** 在 Web 界面添加"定时同步"功能(如每天凌晨 2 点自动运行),内置 APScheduler 或 cron 风格调度,无需依赖外部 cron。
|
||
|
||
#### 5. 下载统计与历史报告
|
||
**建议:** 增加下载历史记录(SQLite 存储),Web 界面展示:
|
||
- 按日期的下载量图表
|
||
- 按频道的下载统计
|
||
- 磁盘空间使用情况
|
||
|
||
#### 6. 实时进度推送(WebSocket)
|
||
**现状:** Web 界面通过轮询(每 2 秒 fetch 一次)获取进度,有延迟且浪费请求。
|
||
**建议:** 改用 WebSocket 或 SSE(Server-Sent Events)推送实时进度,降低延迟和服务器压力。
|
||
|
||
#### 7. 文件去重优化
|
||
**现状:** 通过比较文件路径和大小判断是否已下载。
|
||
**建议:** 增加基于消息 ID 的已下载记录(SQLite),即使文件被移动或重命名,也不会重复下载同一消息。
|
||
|
||
---
|
||
|
||
### 16.3 低优先级(长期演进)
|
||
|
||
#### 8. HTTPS 支持
|
||
**建议:** Web 服务支持 SSL/TLS 配置(提供证书路径配置项),或提供 Nginx 反向代理配置示例,供服务器部署时使用。
|
||
|
||
#### 9. 移动端适配
|
||
**现状:** Web 界面在小屏幕(480px 以下)有布局问题。
|
||
**建议:** 完善响应式布局,优化移动端操作体验(触摸友好的表单控件、大按钮)。
|
||
|
||
#### 10. 过滤器可视化编辑器
|
||
**现状:** 过滤器需手动输入表达式字符串,语法不直观。
|
||
**建议:** Web 界面提供图形化过滤条件构建器(类似 Notion filter),自动生成过滤表达式字符串。
|
||
|
||
#### 11. 多账号支持
|
||
**建议:** 支持配置多个 Telegram 账号(多个 `api_id/api_hash`),不同频道使用不同账号下载,规避单账号频率限制。
|
||
|
||
#### 12. API 文档自动生成
|
||
**建议:** 使用 Flask-RESTX 或 flasgger 为 Web API 生成 Swagger 文档,方便二次开发和集成。
|
||
|
||
---
|
||
|
||
### 16.4 代码质量建议
|
||
|
||
| 类别 | 建议 |
|
||
|------|------|
|
||
| 测试覆盖率 | 补充 web.py API 端点的集成测试,当前测试主要覆盖工具函数 |
|
||
| 类型注解 | 核心函数补充完整的 Python 类型注解(typing),提升 IDE 支持和可读性 |
|
||
| 配置校验 | 启动时对 config.yaml 进行 Schema 校验(使用 pydantic 或 jsonschema),提前发现配置错误 |
|
||
| 错误处理 | media_downloader.py 中部分 except 过于宽泛(`except Exception`),建议细化为具体异常类型 |
|
||
| 日志规范 | 统一使用 loguru,移除部分混用 print 和 logging 的情况 |
|
||
| 文档字符串 | 核心函数(尤其是 web.py 的路由函数)补充 docstring |
|
||
|
||
---
|
||
|
||
*文档结束*
|
||
|
||
> 本文档基于项目版本 2.2.5 编写(2026-04-06)。如项目代码有更新,部分细节可能与实际不符,请以代码为准。
|