mirror of
https://github.com/ZhuLinsen/daily_stock_analysis
synced 2026-09-20 10:53:33 +08:00
fix: support legacy Discord channel env alias and align docs (#659)
This commit is contained in:
@@ -234,6 +234,7 @@ AGENT_SKILLS=bull_trend,ma_golden_cross,volume_breakout,shrink_pullback
|
||||
# 3. 获取频道 ID:Discord 开启开发者模式 -> 右键频道 -> 复制 ID
|
||||
# DISCORD_BOT_TOKEN=
|
||||
# DISCORD_MAIN_CHANNEL_ID=
|
||||
# DISCORD_CHANNEL_ID= # 兼容旧变量名,推荐改用 DISCORD_MAIN_CHANNEL_ID
|
||||
#
|
||||
# 【方式九】Server酱3 配置(国内推送服务,支持微信推送)
|
||||
# 注册Server酱3账号并获取SendKey https://sc3.ft07.com/
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
[](https://github.com/features/actions)
|
||||
[](https://hub.docker.com/)
|
||||
|
||||
> 🤖 基于 AI 大模型的 A股/港股/美股自选股智能分析系统,每日自动分析并推送「决策仪表盘」到企业微信/飞书/Telegram/邮箱
|
||||
> 🤖 基于 AI 大模型的 A股/港股/美股自选股智能分析系统,每日自动分析并推送「决策仪表盘」到企业微信/飞书/Telegram/Discord/邮箱
|
||||
|
||||
[**功能特性**](#-功能特性) · [**快速开始**](#-快速开始) · [**推送效果**](#-推送效果) · [**完整指南**](docs/full-guide.md) · [**常见问题**](docs/FAQ.md) · [**更新日志**](docs/CHANGELOG.md)
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
| 历史记录 | 批量管理 | 支持多选、全选及批量删除历史分析记录,优化管理效率与 UI/UX 体验 |
|
||||
| 回测 | AI 回测验证 | 自动评估历史分析准确率,方向胜率、止盈止损命中率 |
|
||||
| **Agent 问股** | **策略对话** | **多轮策略问答,支持均线金叉/缠论/波浪等 11 种内置策略,Web/Bot/API 全链路** |
|
||||
| 推送 | 多渠道通知 | 企业微信、飞书、Telegram、钉钉、邮件、Pushover |
|
||||
| 推送 | 多渠道通知 | 企业微信、飞书、Telegram、Discord、钉钉、邮件、Pushover |
|
||||
| 自动化 | 定时运行 | GitHub Actions 定时执行,无需服务器 |
|
||||
|
||||
> 历史报告详情会优先展示 AI 返回的原始「狙击点位」文本,避免区间价、条件说明等复杂内容在历史回看时被压缩成单个数字。
|
||||
@@ -115,6 +115,9 @@
|
||||
| `TELEGRAM_BOT_TOKEN` | Telegram Bot Token(@BotFather 获取) | 可选 |
|
||||
| `TELEGRAM_CHAT_ID` | Telegram Chat ID | 可选 |
|
||||
| `TELEGRAM_MESSAGE_THREAD_ID` | Telegram Topic ID (用于发送到子话题) | 可选 |
|
||||
| `DISCORD_WEBHOOK_URL` | Discord Webhook URL | 可选 |
|
||||
| `DISCORD_BOT_TOKEN` | Discord Bot Token(与 Webhook 二选一) | 可选 |
|
||||
| `DISCORD_MAIN_CHANNEL_ID` | Discord Channel ID(使用 Bot 时需要) | 可选 |
|
||||
| `EMAIL_SENDER` | 发件人邮箱(如 `xxx@qq.com`) | 可选 |
|
||||
| `EMAIL_PASSWORD` | 邮箱授权码(非登录密码) | 可选 |
|
||||
| `EMAIL_RECEIVERS` | 收件人邮箱(多个用逗号分隔,留空则发给自己) | 可选 |
|
||||
|
||||
@@ -41,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- 📖 **.env.example** — added `AGENT_ARCH` and `AGENT_NL_ROUTING` configuration documentation
|
||||
|
||||
### Fixed
|
||||
- 🎮 **Discord channel env compatibility** — runtime now accepts legacy `DISCORD_CHANNEL_ID` as a fallback for `DISCORD_MAIN_CHANNEL_ID`, and the docs/examples now use the same variable name as the actual workflow/config implementation
|
||||
- 🐛 **Session secret rotation on Windows** — use atomic replace so auth toggles invalidate existing sessions even when `.session_secret` already exists
|
||||
- 🐛 **Auth toggle atomicity** — persist `ADMIN_AUTH_ENABLED` before rotating session secret; on rotation failure, roll back to the previous auth state
|
||||
- 🔧 **LLM runtime selection guardrails** — YAML 模式下渠道编辑器不再覆盖 `LITELLM_MODEL` / fallback / Vision;系统配置校验补上全部渠道禁用后的运行时来源检查,并修复 `vertexai/...` 这类协议别名模型被重复加前缀的问题
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
| `TELEGRAM_MESSAGE_THREAD_ID` | Telegram Topic ID (用於發送到子話題) | 可選 |
|
||||
| `DISCORD_WEBHOOK_URL` | Discord Webhook URL | 可選 |
|
||||
| `DISCORD_BOT_TOKEN` | Discord Bot Token(與 Webhook 二選一) | 可選 |
|
||||
| `DISCORD_CHANNEL_ID` | Discord Channel ID(使用 Bot 時需要) | 可選 |
|
||||
| `DISCORD_MAIN_CHANNEL_ID` | Discord Channel ID(使用 Bot 時需要) | 可選 |
|
||||
| `EMAIL_SENDER` | 發件人郵箱(如 `xxx@qq.com`) | 可選 |
|
||||
| `EMAIL_PASSWORD` | 郵箱授權碼(非登錄密碼) | 可選 |
|
||||
| `EMAIL_RECEIVERS` | 收件人郵箱(多個用逗號分隔,留空則發給自己) | 可選 |
|
||||
|
||||
@@ -97,7 +97,7 @@ Go to your forked repo → `Settings` → `Secrets and variables` → `Actions`
|
||||
| `TELEGRAM_MESSAGE_THREAD_ID` | Telegram Topic ID (For sending to topics) | Optional |
|
||||
| `DISCORD_WEBHOOK_URL` | Discord Webhook URL | Optional |
|
||||
| `DISCORD_BOT_TOKEN` | Discord Bot Token (choose one with Webhook) | Optional |
|
||||
| `DISCORD_CHANNEL_ID` | Discord Channel ID (required when using Bot) | Optional |
|
||||
| `DISCORD_MAIN_CHANNEL_ID` | Discord Channel ID (required when using Bot) | Optional |
|
||||
| `EMAIL_SENDER` | Sender email (e.g., `xxx@qq.com`) | Optional |
|
||||
| `EMAIL_PASSWORD` | Email authorization code (not login password) | Optional |
|
||||
| `EMAIL_RECEIVERS` | Receiver emails (comma-separated, leave empty to send to yourself) | Optional |
|
||||
@@ -256,7 +256,7 @@ DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/xxx/yyy
|
||||
Bot:
|
||||
```bash
|
||||
DISCORD_BOT_TOKEN=your_bot_token
|
||||
DISCORD_CHANNEL_ID=your_channel_id
|
||||
DISCORD_MAIN_CHANNEL_ID=your_channel_id
|
||||
```
|
||||
|
||||
### 3. Email
|
||||
|
||||
@@ -75,7 +75,7 @@ daily_stock_analysis/
|
||||
| `TELEGRAM_MESSAGE_THREAD_ID` | Telegram Topic ID (用于发送到子话题) | 可选 |
|
||||
| `DISCORD_WEBHOOK_URL` | Discord Webhook URL([创建方法](https://support.discord.com/hc/en-us/articles/228383668)) | 可选 |
|
||||
| `DISCORD_BOT_TOKEN` | Discord Bot Token(与 Webhook 二选一) | 可选 |
|
||||
| `DISCORD_CHANNEL_ID` | Discord Channel ID(使用 Bot 时需要) | 可选 |
|
||||
| `DISCORD_MAIN_CHANNEL_ID` | Discord Channel ID(使用 Bot 时需要) | 可选 |
|
||||
| `EMAIL_SENDER` | 发件人邮箱(如 `xxx@qq.com`) | 可选 |
|
||||
| `EMAIL_PASSWORD` | 邮箱授权码(非登录密码) | 可选 |
|
||||
| `EMAIL_RECEIVERS` | 收件人邮箱(多个用逗号分隔,留空则发给自己) | 可选 |
|
||||
@@ -189,7 +189,7 @@ daily_stock_analysis/
|
||||
| `TELEGRAM_MESSAGE_THREAD_ID` | Telegram Topic ID | 可选 |
|
||||
| `DISCORD_WEBHOOK_URL` | Discord Webhook URL | 可选 |
|
||||
| `DISCORD_BOT_TOKEN` | Discord Bot Token(与 Webhook 二选一) | 可选 |
|
||||
| `DISCORD_CHANNEL_ID` | Discord Channel ID(使用 Bot 时需要) | 可选 |
|
||||
| `DISCORD_MAIN_CHANNEL_ID` | Discord Channel ID(使用 Bot 时需要) | 可选 |
|
||||
| `DISCORD_MAX_WORDS` | Discord 最大字数限制(默认 免费服务器限制2000) | 可选 |
|
||||
| `EMAIL_SENDER` | 发件人邮箱 | 可选 |
|
||||
| `EMAIL_PASSWORD` | 邮箱授权码(非登录密码) | 可选 |
|
||||
@@ -586,7 +586,7 @@ DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/xxx/yyy
|
||||
|
||||
```bash
|
||||
DISCORD_BOT_TOKEN=your_bot_token
|
||||
DISCORD_CHANNEL_ID=your_channel_id
|
||||
DISCORD_MAIN_CHANNEL_ID=your_channel_id
|
||||
```
|
||||
|
||||
### Pushover(iOS/Android 推送)
|
||||
|
||||
@@ -75,7 +75,7 @@ Go to your forked repo → `Settings` → `Secrets and variables` → `Actions`
|
||||
| `TELEGRAM_MESSAGE_THREAD_ID` | Telegram Topic ID (for sending to topics) | Optional |
|
||||
| `DISCORD_WEBHOOK_URL` | Discord Webhook URL ([How to create](https://support.discord.com/hc/en-us/articles/228383668)) | Optional |
|
||||
| `DISCORD_BOT_TOKEN` | Discord Bot Token (choose one with Webhook) | Optional |
|
||||
| `DISCORD_CHANNEL_ID` | Discord Channel ID (required when using Bot) | Optional |
|
||||
| `DISCORD_MAIN_CHANNEL_ID` | Discord Channel ID (required when using Bot) | Optional |
|
||||
| `EMAIL_SENDER` | Sender email (e.g., `xxx@qq.com`) | Optional |
|
||||
| `EMAIL_PASSWORD` | Email authorization code (not login password) | Optional |
|
||||
| `EMAIL_RECEIVERS` | Receiver emails (comma-separated, leave empty to send to self) | Optional |
|
||||
@@ -175,7 +175,7 @@ Default schedule: Every weekday at **18:00 (Beijing Time)** automatic execution.
|
||||
| `TELEGRAM_MESSAGE_THREAD_ID` | Telegram Topic ID | Optional |
|
||||
| `DISCORD_WEBHOOK_URL` | Discord Webhook URL | Optional |
|
||||
| `DISCORD_BOT_TOKEN` | Discord Bot Token (choose one with Webhook) | Optional |
|
||||
| `DISCORD_CHANNEL_ID` | Discord Channel ID (required when using Bot) | Optional |
|
||||
| `DISCORD_MAIN_CHANNEL_ID` | Discord Channel ID (required when using Bot) | Optional |
|
||||
| `DISCORD_MAX_WORDS` | Discord Word Limit (default 2000 for un-upgraded servers) | Optional |
|
||||
| `EMAIL_SENDER` | Sender email | Optional |
|
||||
| `EMAIL_PASSWORD` | Email authorization code (not login password) | Optional |
|
||||
@@ -460,7 +460,7 @@ DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/xxx/yyy
|
||||
|
||||
```bash
|
||||
DISCORD_BOT_TOKEN=your_bot_token
|
||||
DISCORD_CHANNEL_ID=your_channel_id
|
||||
DISCORD_MAIN_CHANNEL_ID=your_channel_id
|
||||
```
|
||||
|
||||
### Pushover (iOS/Android Push)
|
||||
|
||||
@@ -920,7 +920,10 @@ class Config:
|
||||
custom_webhook_bearer_token=os.getenv('CUSTOM_WEBHOOK_BEARER_TOKEN'),
|
||||
webhook_verify_ssl=os.getenv('WEBHOOK_VERIFY_SSL', 'true').lower() == 'true',
|
||||
discord_bot_token=os.getenv('DISCORD_BOT_TOKEN'),
|
||||
discord_main_channel_id=os.getenv('DISCORD_MAIN_CHANNEL_ID'),
|
||||
discord_main_channel_id=(
|
||||
os.getenv('DISCORD_MAIN_CHANNEL_ID')
|
||||
or os.getenv('DISCORD_CHANNEL_ID')
|
||||
),
|
||||
discord_webhook_url=os.getenv('DISCORD_WEBHOOK_URL'),
|
||||
astrbot_url=os.getenv('ASTRBOT_URL'),
|
||||
astrbot_token=os.getenv('ASTRBOT_TOKEN'),
|
||||
|
||||
@@ -360,6 +360,52 @@ class TestVisionKeyValidation:
|
||||
assert not any(i.field == "VISION_MODEL" for i in issues)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Env alias compatibility
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestEnvAliasCompatibility:
|
||||
@patch("src.config.setup_env")
|
||||
@patch.object(Config, "_parse_litellm_yaml", return_value=[])
|
||||
def test_discord_channel_id_legacy_alias_is_still_loaded(
|
||||
self,
|
||||
_mock_parse_yaml,
|
||||
_mock_setup_env,
|
||||
):
|
||||
with patch.dict(
|
||||
"os.environ",
|
||||
{
|
||||
"DISCORD_BOT_TOKEN": "token",
|
||||
"DISCORD_CHANNEL_ID": "legacy-channel",
|
||||
},
|
||||
clear=True,
|
||||
):
|
||||
config = Config._load_from_env()
|
||||
|
||||
assert config.discord_bot_token == "token"
|
||||
assert config.discord_main_channel_id == "legacy-channel"
|
||||
|
||||
@patch("src.config.setup_env")
|
||||
@patch.object(Config, "_parse_litellm_yaml", return_value=[])
|
||||
def test_discord_main_channel_id_takes_precedence_over_legacy_alias(
|
||||
self,
|
||||
_mock_parse_yaml,
|
||||
_mock_setup_env,
|
||||
):
|
||||
with patch.dict(
|
||||
"os.environ",
|
||||
{
|
||||
"DISCORD_BOT_TOKEN": "token",
|
||||
"DISCORD_CHANNEL_ID": "legacy-channel",
|
||||
"DISCORD_MAIN_CHANNEL_ID": "main-channel",
|
||||
},
|
||||
clear=True,
|
||||
):
|
||||
config = Config._load_from_env()
|
||||
|
||||
assert config.discord_main_channel_id == "main-channel"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# validate() backward compatibility
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user