⭐AI-driven public opinion & trend monitor with multi-platform aggregation, RSS, and smart alerts.🎯 告别信息过载,你的 AI 舆情监控助手与热点筛选工具!聚合多平台热点 + RSS 订阅,支持关键词精准筛选。AI 智能筛选新闻 + AI 翻译 + AI 分析简报直推手机,也支持接入 MCP 架构,赋能 AI 自然语言对话分析、情感洞察与趋势预测等。支持 Docker ,数据本地/云端自持。集成微信/飞书/钉钉/Telegram/邮件/ntfy/bark/slack 等渠道智能推送。
This report presents the forensic synthetic code analysis of sansan0/TrendRadar, a Python project with 60,535 GitHub stars. SynthScan v2.0 examined 57,917 lines of code across 110 source files, recording 1072 pattern matches distributed across 14 syntactic categories. The overall adjusted score of 37.0 places this repository in the Strong AI signal band.
The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).
This chart maps the temporal evolution of the adjusted synthetic code score across successive scan runs. An upward trajectory indicates ongoing incorporation of AI-generated code or expanding LLM-assisted scaffolding; a stable or declining trajectory may reflect active human refactoring, code removal, or the adoption of stricter authorship policies. The dashed secondary line (right axis) independently tracks total raw pattern hit count, which can diverge from the normalised score when codebase size changes significantly between scans.
Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.
This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.
The scanner identified 1072 distinct pattern matches across 14 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | config/config.en.yaml | 1 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| MEDIUM⚡ | config/config.en.yaml | 4 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| MEDIUM⚡ | config/config.en.yaml | 10 | # =============================================================== | COMMENT |
| MEDIUM⚡ | config/config.en.yaml | 12 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 24 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 41 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 47 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 64 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 106 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 113 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 153 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 155 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 175 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 177 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 190 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 192 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 220 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 224 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 254 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 262 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 308 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 310 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 352 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 354 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 409 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 411 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 436 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 440 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 456 | # =============================================================== | COMMENT |
| MEDIUM | config/config.en.yaml | 458 | # =============================================================== | COMMENT |
| MEDIUM⚡ | config/ai_translation_prompt.txt | 1 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| MEDIUM⚡ | config/ai_translation_prompt.txt | 4 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| MEDIUM⚡ | config/ai_translation_prompt.txt | 12 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| MEDIUM | config/ai_interests.txt | 1 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| MEDIUM | config/ai_interests.txt | 4 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| MEDIUM | config/ai_analysis_prompt.txt | 1 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| MEDIUM | config/ai_analysis_prompt.txt | 4 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| MEDIUM | config/ai_analysis_prompt.txt | 21 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| MEDIUM⚡ | config/config.yaml | 1 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| MEDIUM⚡ | config/config.yaml | 4 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| MEDIUM⚡ | config/config.yaml | 10 | # =============================================================== | COMMENT |
| MEDIUM⚡ | config/config.yaml | 12 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 24 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 41 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 47 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 63 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 105 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 112 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 152 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 154 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 174 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 176 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 189 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 191 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 219 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 223 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 253 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 261 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 307 | # =============================================================== | COMMENT |
| MEDIUM | config/config.yaml | 309 | # =============================================================== | COMMENT |
| 228 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH⚡ | trendradar/report/html.py | 2379 | var timer = null; | CODE |
| HIGH⚡ | trendradar/report/html.py | 2386 | item.style.display = (!query || title.toLowerCase().indexOf(query) !== -1) ? '' : 'none'; | CODE |
| HIGH⚡ | trendradar/report/html.py | 2390 | item.style.display = (!query || title.toLowerCase().indexOf(query) !== -1) ? '' : 'none'; | CODE |
| HIGH⚡ | trendradar/report/html.py | 2867 | lines.push('# ' + (headerTitle ? headerTitle.textContent.trim() : 'TrendRadar')); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2868 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2876 | if (label && value) { | CODE |
| HIGH⚡ | trendradar/report/html.py | 2877 | lines.push('- **' + label.textContent.trim() + '**: ' + value.textContent.trim()); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2880 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2899 | if (rank && rank.textContent.trim() && rank.textContent.trim() !== '?') meta.push('#' + rank.textCon | CODE |
| HIGH⚡ | trendradar/report/html.py | 2899 | if (rank && rank.textContent.trim() && rank.textContent.trim() !== '?') meta.push('#' + rank.textCon | CODE |
| HIGH⚡ | trendradar/report/html.py | 2901 | if (source) meta.push(source.textContent.trim()); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2903 | if (keyword) meta.push(keyword.textContent.trim()); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2905 | if (time) meta.push(time.textContent.trim()); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2907 | if (count) meta.push(count.textContent.trim()); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2922 | lines.push('## 热点新闻'); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2923 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2928 | lines.push('### ' + wordName.textContent.trim() + (wordCount ? ' (' + wordCount.textContent. | CODE |
| HIGH⚡ | trendradar/report/html.py | 2929 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2934 | if (line) lines.push(line); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2936 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2944 | lines.push('## ' + (newTitle ? newTitle.textContent.trim() : '本次新增热点')); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2945 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2950 | lines.push('### ' + srcTitle.textContent.trim()); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2951 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2956 | if (line) lines.push(line); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2958 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2966 | lines.push('## ' + (rssSectionTitle ? rssSectionTitle.textContent.trim() : 'RSS 订阅更新')); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2967 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2973 | lines.push('### ' + feedName.textContent.trim() + (feedCount ? ' (' + feedCount.textContent. | CODE |
| HIGH⚡ | trendradar/report/html.py | 2974 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2984 | if (time) meta.push(time.textContent.trim()); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2986 | if (author) meta.push(author.textContent.trim()); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2991 | lines.push(line); | CODE |
| HIGH⚡ | trendradar/report/html.py | 2993 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3003 | lines.push('## AI 分析'); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3004 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3005 | lines.push('> ' + aiError.textContent.trim()); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3006 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3011 | lines.push('## ' + (aiTitle ? aiTitle.textContent.trim() : 'AI 热点分析')); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3012 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3018 | lines.push('### ' + blockTitle.textContent.trim()); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3019 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3022 | lines.push(blockContent.textContent.trim()); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3023 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3033 | lines.push('## ' + (standaloneTitle ? standaloneTitle.textContent.trim() : '独立展示区')); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3034 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3040 | lines.push('### ' + name.textContent.trim() + (cnt ? ' (' + cnt.textContent.trim() + ')' : ' | CODE |
| HIGH⚡ | trendradar/report/html.py | 3041 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3046 | if (line) lines.push(line); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3048 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3057 | lines.push('## 抓取异常'); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3058 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3060 | lines.push('- ' + item.textContent.trim()); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3062 | lines.push(''); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3067 | lines.push('---'); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3068 | lines.push('*Generated by TrendRadar*'); | CODE |
| HIGH⚡ | trendradar/report/html.py | 3087 | var savedMode = null; | CODE |
| HIGH⚡ | trendradar/report/html.py | 3089 | if (savedMode === '1' || (savedMode === null && window.innerWidth > 768)) { | CODE |
| HIGH⚡ | trendradar/report/html.py | 3096 | var savedDark = null; | CODE |
| HIGH | trendradar/report/html.py | 2299 | var tabBar = wrapper ? wrapper.querySelector('.tab-bar') : null; | CODE |
| 22 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | trendradar/core/frequency.py | 99 | 加载频率词配置 配置文件格式说明: - 每个词组由空行分隔 - [GLOBAL_FILTER] 区域定义全局过滤词 - [WORD_GROUPS] 区域定义词组(默认) 词组语法: | STRING |
| HIGH | trendradar/core/config.py | 12 | 解析多账号配置,返回账号列表 Args: config_value: 配置值字符串,多个账号用分隔符分隔 separator: 分隔符,默认为 ; Returns: | STRING |
| HIGH | trendradar/core/config.py | 45 | 验证配对配置的数量是否一致 对于需要多个配置项配对的渠道(如 Telegram 的 token 和 chat_id), 验证所有配置项的账号数量是否一致。 Args: configs: | STRING |
| HIGH | trendradar/core/config.py | 102 | 限制账号数量 当配置的账号数量超过最大限制时,只使用前 N 个账号, 并输出警告信息。 Args: accounts: 账号列表 max_count: 最大账号数量 | STRING |
| HIGH | trendradar/core/config.py | 129 | 安全获取指定索引的账号值 当索引超出范围或账号值为空时,返回默认值。 Args: accounts: 账号列表 index: 索引 default: 默认值 | STRING |
| HIGH | trendradar/core/loader.py | 525 | 加载配置文件 Args: config_path: 配置文件路径,默认从环境变量 CONFIG_PATH 获取或使用 config/config.yaml Returns: 包含 | STRING |
| HIGH | trendradar/utils/url.py | 39 | 标准化 URL,去除动态参数 用于数据库去重,确保同一条新闻的不同 URL 变体能被正确识别为同一条。 处理规则: 1. 去除平台特定的动态参数(如微博的 band_rank) 2. 去除通用追 | STRING |
| HIGH | trendradar/ai/client.py | 47 | 调用 AI 模型进行对话 Args: messages: 消息列表,格式: [{"role": "system/user/assistant", "content": "..."} | STRING |
| HIGH | mcp_server/server.py | 122 | 【推荐优先调用】将自然语言日期表达式解析为标准日期范围 **为什么需要这个工具?** 用户经常使用"本周"、"最近7天"等自然语言表达日期,但 AI 模型自己计算日期 可能导致不一致的结果。此工具在服务器 | STRING |
| HIGH | mcp_server/server.py | 225 | 获取热点话题统计 Args: top_n: 返回TOP N话题,默认10 mode: 时间模式 - "daily": 当日累计数据统计 - | STRING |
| HIGH | mcp_server/server.py | 261 | 获取最新的 RSS 订阅数据(支持多日查询) RSS 数据与热榜新闻分开存储,按时间流展示,适合获取特定来源的最新内容。 Args: feeds: RSS 源 ID 列表,如 ['hacker- | STRING |
| HIGH | mcp_server/server.py | 295 | 搜索 RSS 数据 在 RSS 订阅数据中搜索包含指定关键词的文章。 Args: keyword: 搜索关键词(必需) feeds: RSS 源 ID 列表,如 ['hacker | STRING |
| HIGH | mcp_server/server.py | 398 | 统一话题趋势分析工具 - 整合多种趋势分析模式 建议:使用自然语言日期时,先调用 resolve_date_range 获取精确日期范围。 Args: topic: 话题关键词(必需) | STRING |
| HIGH | mcp_server/server.py | 447 | 统一数据洞察分析工具 - 整合多种数据分析模式 Args: insight_type: 洞察类型,可选值: - "platform_compare": 平台对比分析(对比不同平台对 | STRING |
| HIGH | mcp_server/server.py | 492 | 分析新闻的情感倾向和热度趋势 建议:使用自然语言日期时,先调用 resolve_date_range 获取精确日期范围。 Args: topic: 话题关键词(可选) platf | STRING |
| HIGH | mcp_server/server.py | 532 | 查找与指定新闻标题相关的其他新闻(支持当天和历史数据) Args: reference_title: 参考新闻标题(完整或部分) date_range: 日期范围(可选) | STRING |
| HIGH | mcp_server/server.py | 599 | 跨平台新闻聚合 - 对相似新闻进行去重合并 将不同平台报道的同一事件合并为一条聚合新闻,显示跨平台覆盖情况和综合热度。 Args: date_range: 日期范围,不指定则查询今天 | STRING |
| HIGH | mcp_server/server.py | 639 | 时期对比分析 - 比较两个时间段的新闻数据 对比不同时期的热点话题、平台活跃度、新闻数量等维度。 **使用场景:** - 对比本周和上周的热点变化 - 分析某个话题在两个时期的热度差异 | STRING |
| HIGH | mcp_server/server.py | 705 | 统一搜索接口,支持多种搜索模式,可同时搜索热榜和RSS 建议:使用自然语言日期时,先调用 resolve_date_range 获取精确日期范围。 Args: query: 搜索关键词或内容片段 | STRING |
| HIGH | mcp_server/server.py | 794 | 检查版本更新(同时检查 TrendRadar 和 MCP Server) 比较本地版本与 GitHub 远程版本,判断是否需要更新。 Args: proxy_url: 可选的代理URL,用于访问 | STRING |
| HIGH | mcp_server/server.py | 820 | 手动触发一次爬取任务(可选持久化) Args: platforms: 平台ID列表,如 ['zhihu', 'weibo'],不指定则使用所有平台 save_to_local: 是否保存到 | STRING |
| HIGH | mcp_server/server.py | 849 | 从远程存储拉取数据到本地 用于 MCP Server 等场景:爬虫存到远程云存储(如 Cloudflare R2), MCP Server 拉取到本地进行分析查询。 Args: days | STRING |
| HIGH | mcp_server/server.py | 905 | 列出本地/远程可用的日期范围 查看本地和远程存储中有哪些日期的数据可用。 Args: source: 数据来源 - "local": 仅本地 - | STRING |
| HIGH | mcp_server/server.py | 935 | 读取指定 URL 的文章内容,返回 LLM 友好的 Markdown 格式 通过 Jina AI Reader 将网页转换为干净的 Markdown,自动去除广告、导航栏等噪音内容。 适合用于:阅读新闻正文、获取 | STRING |
| HIGH | mcp_server/server.py | 975 | 批量读取多篇文章内容(最多 5 篇,间隔 5 秒) 逐篇请求文章内容,每篇之间自动间隔 5 秒以遵守速率限制。 **典型使用流程:** 1. 先用 search_news(include_url=Tru | STRING |
| HIGH | mcp_server/server.py | 1014 | 获取通知渠道的格式化策略指南 返回各渠道支持的 Markdown 特性、格式限制和最佳格式化提示词。 在调用 send_notification 之前使用此工具,可以了解目标渠道的格式要求, 从而生成最佳 | STRING |
| HIGH | mcp_server/server.py | 1077 | 向已配置的通知渠道发送消息 接受 markdown 格式内容,内部自动适配各渠道的格式要求和限制: - 飞书:Markdown 卡片消息(支持 **粗体**、<font color>彩色文本、[链接](url)、 | STRING |
| HIGH | mcp_server/tools/search_tools.py | 43 | 统一新闻搜索工具 - 整合多种搜索模式,支持同时搜索热榜和RSS Args: query: 查询内容(必需)- 关键词、内容片段或实体名称 search_m | STRING |
| HIGH | mcp_server/tools/analytics.py | 119 | 统一数据洞察分析工具 - 整合多种数据分析模式 Args: insight_type: 洞察类型,可选值: - "platform_compare" | STRING |
| HIGH | mcp_server/tools/analytics.py | 272 | 热度趋势分析 - 追踪特定话题的热度变化趋势 Args: topic: 话题关键词 date_range: 日期范围(可选) | STRING |
| HIGH | mcp_server/tools/analytics.py | 430 | 平台对比分析 - 对比不同平台对同一话题的关注度 Args: topic: 话题关键词(可选,不指定则对比整体活跃度) date_range: 日期范围,格 | STRING |
| HIGH | mcp_server/tools/analytics.py | 554 | 关键词共现分析 - 分析哪些关键词经常同时出现 Args: min_frequency: 最小共现频次 top_n: 返回TOP N关键词对 | STRING |
| HIGH | mcp_server/tools/analytics.py | 666 | 情感倾向分析 - 生成用于 AI 情感分析的结构化提示词 本工具收集新闻数据并生成优化的 AI 提示词,你可以将其发送给 AI 进行深度情感分析。 Args: t | STRING |
| HIGH | mcp_server/tools/analytics.py | 944 | 相似新闻查找 - 基于标题相似度查找相关新闻 Args: reference_title: 参考标题 threshold: 相似度阈值(0-1之间) | STRING |
| HIGH | mcp_server/tools/analytics.py | 1059 | 实体识别搜索 - 搜索包含特定人物/地点/机构的新闻 Args: entity: 实体名称 entity_type: 实体类型(person/locatio | STRING |
| HIGH | mcp_server/tools/analytics.py | 1188 | 每日/每周摘要生成器 - 自动生成热点摘要报告 Args: report_type: 报告类型(daily/weekly) date_range: 自定义日 | STRING |
| HIGH | mcp_server/tools/analytics.py | 1367 | 平台活跃度统计 - 统计各平台的发布频率和活跃时间段 Args: date_range: 日期范围(可选) Returns: 平台活跃度统 | STRING |
| HIGH | mcp_server/tools/analytics.py | 1495 | 话题生命周期分析 - 追踪话题从出现到消失的完整周期 Args: topic: 话题关键词 date_range: 日期范围(可选) | STRING |
| HIGH | mcp_server/tools/analytics.py | 1653 | 异常热度检测 - 自动识别突然爆火的话题 Args: threshold: 热度突增倍数阈值 time_window: 检测时间窗口(小时) | STRING |
| HIGH | mcp_server/tools/analytics.py | 1792 | 话题预测 - 基于历史数据预测未来可能的热点 Args: lookahead_hours: 预测未来多少小时 confidence_threshold: 置 | STRING |
| HIGH | mcp_server/utils/validators.py | 22 | 将字符串解析为列表 支持格式: - JSON 数组: '["zhihu", "weibo"]' - Python 列表字符串: "['zhihu', 'weibo']" - 逗号分隔: "zhih | STRING |
| HIGH | mcp_server/utils/validators.py | 74 | 将字符串解析为整数 Args: value: 字符串值 param_name: 参数名(用于错误消息) Returns: 解析后的整数 Raises: | STRING |
| HIGH | mcp_server/utils/validators.py | 106 | 将字符串解析为浮点数 Args: value: 字符串值 param_name: 参数名(用于错误消息) Returns: 解析后的浮点数 Raises | STRING |
| HIGH | mcp_server/utils/validators.py | 197 | 验证平台列表 Args: platforms: 平台ID列表或字符串,None表示使用 config.yaml 中配置的所有平台 支持多种格式: | STRING |
| HIGH | mcp_server/utils/validators.py | 258 | 验证数量限制参数 Args: limit: 限制数量(整数或字符串) default: 默认值 max_limit: 最大限制 Returns: | STRING |
| HIGH | mcp_server/utils/validators.py | 295 | 验证日期格式 Args: date_str: 日期字符串 (YYYY-MM-DD) Returns: datetime对象 Raises: Invali | STRING |
| HIGH | mcp_server/utils/validators.py | 317 | 规范化 date_range 参数 某些 MCP 客户端(特别是 HTTP 方式)会将 JSON 对象序列化为字符串传入。 此函数尝试将 JSON 字符串解析为 dict,如果不是 JSON 格式则保持原样。 | STRING |
| HIGH | mcp_server/utils/validators.py | 364 | 验证日期范围 Args: date_range: 日期范围,支持多种格式: - dict: {"start": "YYYY-MM-DD", "end": "YYYY-MM-DD"} | STRING |
| HIGH | mcp_server/utils/validators.py | 483 | 验证关键词 Args: keyword: 搜索关键词 Returns: 处理后的关键词 Raises: InvalidParameterError: 关 | STRING |
| HIGH | mcp_server/utils/validators.py | 516 | 验证TOP N参数 Args: top_n: TOP N数量(整数或字符串) default: 默认值 Returns: 验证后的值 Raises: | STRING |
| HIGH | mcp_server/utils/validators.py | 533 | 验证模式参数 Args: mode: 模式字符串 valid_modes: 有效模式列表 default: 默认模式 Returns: 验证后的模 | STRING |
| HIGH | mcp_server/utils/validators.py | 563 | 验证配置节参数 Args: section: 配置节名称 Returns: 验证后的配置节 Raises: InvalidParameterError: | STRING |
| HIGH | mcp_server/utils/validators.py | 586 | 验证阈值参数(浮点数) Args: threshold: 阈值(浮点数、整数或字符串) default: 默认值 min_value: 最小值 max_va | STRING |
| HIGH | mcp_server/utils/validators.py | 633 | 验证并解析日期查询字符串 Args: date_query: 日期查询字符串 allow_future: 是否允许未来日期 max_days_ago: 允许查询的最大天数 | STRING |
| HIGH | mcp_server/utils/date_parser.py | 93 | 解析日期查询字符串 支持的格式: - 相对日期(中文):今天、昨天、前天、大前天、N天前 - 相对日期(英文):today、yesterday、N days ago | STRING |
| HIGH | mcp_server/utils/date_parser.py | 279 | 将日期格式化为文件夹名称 Args: date: datetime对象 Returns: 文件夹名称,格式: YYYY-MM-DD | STRING |
| HIGH | mcp_server/utils/date_parser.py | 332 | 将自然语言日期表达式解析为标准日期范围 这是专门为 MCP 工具设计的方法,用于在服务器端解析日期表达式, 避免 AI 模型自己计算日期导致的不一致问题。 Args: | STRING |
| HIGH | mcp_server/services/data_service.py | 52 | 获取最新一批爬取的新闻数据 Args: platforms: 平台ID列表,None表示所有平台 limit: 返回条数限制 inc | STRING |
| HIGH | mcp_server/services/data_service.py | 127 | 按指定日期获取新闻 Args: target_date: 目标日期 platforms: 平台ID列表,None表示所有平台 lim | STRING |
| HIGH | mcp_server/services/data_service.py | 207 | 按关键词搜索新闻 Args: keyword: 搜索关键词 date_range: 日期范围 (start_date, end_date) | STRING |
| 8 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | docker/manage.py | 452 | def _is_expected_webserver_process(pid: int) -> bool: | CODE |
| LOW⚡ | docker/manage.py | 460 | def _terminate_webserver_process(pid: int, require_expected: bool = True) -> bool: | CODE |
| LOW | docs/assets/script.js | 474 | function saveFrequencyToLocalStorage() { | CODE |
| LOW | docs/assets/script.js | 478 | function saveTimelineToLocalStorage() { | CODE |
| LOW | docs/assets/script.js | 2637 | function parseDisplayRegionsFromYaml() { | CODE |
| LOW | docs/assets/script.js | 2744 | function updateDisplayRegionsInYaml(regions) { | CODE |
| LOW | docs/assets/script.js | 3142 | function parseStandaloneConfigFromYaml() { | CODE |
| LOW | docs/assets/script.js | 3221 | function updateStandaloneConfigInYaml(type, list) { | CODE |
| LOW | docs/assets/script.js | 3364 | function showVersionComparisonModal(fileName, currentVersion, latestVersion) { | CODE |
| LOW | docs/assets/script.js | 4647 | function applyTimelineEditorChanges(editor, lines) { | CODE |
| LOW | docs/assets/script.js | 4703 | function updateTimelineSectionField(presetName, field, value) { | CODE |
| LOW | docs/assets/script.js | 4887 | function scrollTimelineEditorToPreset(presetName) { | CODE |
| LOW | docs/assets/script.js | 5603 | function removePeriodFromDayPlanInLines(lines, sectionInfo, planKey, periodKey) { | CODE |
| LOW | trendradar/context.py | 465 | def create_notification_dispatcher(self) -> NotificationDispatcher: | CODE |
| LOW | trendradar/context.py | 518 | def convert_ai_filter_to_report_data( | CODE |
| LOW⚡ | trendradar/__main__.py | 109 | def _detect_docker_environment(self) -> bool: | CODE |
| LOW⚡ | trendradar/__main__.py | 136 | def _set_update_info_from_config(self) -> None: | CODE |
| LOW | trendradar/__main__.py | 158 | def _has_notification_configured(self) -> bool: | CODE |
| LOW | trendradar/__main__.py | 199 | def _prepare_ai_analysis_data( | CODE |
| LOW | trendradar/__main__.py | 482 | def _prepare_current_title_info(self, results: Dict, time_info: str) -> Dict: | CODE |
| LOW | trendradar/__main__.py | 792 | def _send_notification_if_needed( | CODE |
| LOW | trendradar/__main__.py | 925 | def _initialize_and_check_config(self) -> bool: | CODE |
| LOW | trendradar/__main__.py | 1090 | def _process_rss_data_by_mode(self, rss_data) -> Tuple[Optional[List[Dict]], Optional[List[Dict]], Optional[List[Dic | CODE |
| LOW | trendradar/__main__.py | 1263 | def _convert_rss_items_to_list(self, items_dict: Dict, id_to_name: Dict) -> List[Dict]: | CODE |
| LOW | trendradar/__main__.py | 1359 | def _generate_rss_html_report(self, rss_items: list, feeds_info: dict) -> str: | CODE |
| LOW | trendradar/core/config.py | 11 | def parse_multi_account_config(config_value: str, separator: str = ";") -> List[str]: | CODE |
| LOW | trendradar/core/analyzer.py | 712 | def convert_keyword_stats_to_platform_stats( | CODE |
| LOW | trendradar/core/loader.py | 86 | def _load_notification_config(config_data: Dict) -> Dict: | CODE |
| LOW | trendradar/core/loader.py | 295 | def _load_ai_translation_config(config_data: Dict) -> Dict: | CODE |
| LOW | trendradar/core/loader.py | 442 | def _print_notification_sources(config: Dict) -> None: | CODE |
| LOW | trendradar/core/data.py | 15 | def read_all_today_titles_from_storage( | CODE |
| LOW | trendradar/core/data.py | 113 | def detect_latest_new_titles_from_storage( | CODE |
| LOW | trendradar/notification/formatters.py | 72 | def convert_markdown_to_mrkdwn(content: str) -> str: | CODE |
| LOW | trendradar/notification/renderer.py | 287 | def _render_rss_section_feishu(rss_items: list, separator: str = "---") -> str: | CODE |
| LOW | trendradar/notification/renderer.py | 330 | def _render_rss_section_markdown(rss_items: list) -> str: | CODE |
| LOW | trendradar/notification/batch.py | 34 | def get_max_batch_header_size(format_type: str) -> int: | CODE |
| LOW | trendradar/notification/batch.py | 73 | def truncate_at_line_boundary(text: str, max_bytes: int) -> str: | CODE |
| LOW | trendradar/notification/batch.py | 95 | def truncate_preserving_footer(content: str, max_bytes: int) -> str: | CODE |
| LOW | trendradar/notification/splitter.py | 135 | def split_content_into_batches( | CODE |
| LOW | trendradar/notification/splitter.py | 617 | def process_new_titles_section(current_batch, current_batch_has_content, batches, add_separator=True): | CODE |
| LOW | trendradar/notification/splitter.py | 845 | def process_standalone_section_wrapper(current_batch, current_batch_has_content, batches, add_separator=True): | CODE |
| LOW | trendradar/notification/splitter.py | 856 | def process_rss_stats_wrapper(current_batch, current_batch_has_content, batches, add_separator=True): | CODE |
| LOW | trendradar/notification/splitter.py | 995 | def _process_rss_stats_section( | CODE |
| LOW | trendradar/notification/splitter.py | 1226 | def _process_rss_new_titles_section( | CODE |
| LOW | trendradar/notification/splitter.py | 1474 | def _process_standalone_section( | CODE |
| LOW | trendradar/notification/splitter.py | 1701 | def _format_standalone_platform_item(item: Dict, index: int, format_type: str, rank_threshold: int = 10) -> str: | CODE |
| LOW | trendradar/notification/splitter.py | 1807 | def _format_standalone_rss_item( | CODE |
| LOW⚡ | trendradar/storage/remote.py | 489 | def get_active_ai_filter_tags(self, date=None, interests_file="ai_interests.txt"): | CODE |
| LOW⚡ | trendradar/storage/remote.py | 495 | def get_latest_ai_filter_tag_version(self, date=None): | CODE |
| LOW⚡ | trendradar/storage/remote.py | 498 | def deprecate_all_ai_filter_tags(self, date=None, interests_file="ai_interests.txt"): | CODE |
| LOW⚡ | trendradar/storage/remote.py | 516 | def get_active_ai_filter_results(self, date=None, interests_file="ai_interests.txt"): | CODE |
| LOW⚡ | trendradar/storage/remote.py | 519 | def deprecate_specific_ai_filter_tags(self, tag_ids, date=None): | CODE |
| LOW⚡ | trendradar/storage/remote.py | 525 | def update_ai_filter_tags_hash(self, interests_file, new_hash, date=None): | CODE |
| LOW⚡ | trendradar/storage/remote.py | 531 | def update_ai_filter_tag_descriptions(self, tag_updates, date=None, interests_file="ai_interests.txt"): | CODE |
| LOW⚡ | trendradar/storage/remote.py | 537 | def update_ai_filter_tag_priorities(self, tag_priorities, date=None, interests_file="ai_interests.txt"): | CODE |
| LOW | trendradar/storage/remote.py | 558 | def clear_unmatched_analyzed_news(self, date=None, interests_file="ai_interests.txt"): | CODE |
| LOW⚡ | trendradar/storage/local.py | 234 | def get_active_ai_filter_tags(self, date=None, interests_file="ai_interests.txt"): | CODE |
| LOW⚡ | trendradar/storage/local.py | 240 | def get_latest_ai_filter_tag_version(self, date=None): | CODE |
| LOW⚡ | trendradar/storage/local.py | 243 | def deprecate_all_ai_filter_tags(self, date=None, interests_file="ai_interests.txt"): | CODE |
| LOW⚡ | trendradar/storage/local.py | 252 | def get_active_ai_filter_results(self, date=None, interests_file="ai_interests.txt"): | CODE |
| 78 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | docker/manage.py | 448 | except Exception: | CODE |
| LOW | docker/manage.py | 32 | except Exception as e: | CODE |
| LOW | docker/manage.py | 113 | except Exception as e: | CODE |
| LOW | docker/manage.py | 135 | except Exception as e: | CODE |
| LOW | docker/manage.py | 180 | except Exception: | CODE |
| LOW | docker/manage.py | 222 | except Exception as e: | CODE |
| LOW | docker/manage.py | 316 | except Exception as e: | CODE |
| LOW | docker/manage.py | 411 | except Exception as e: | CODE |
| LOW | docker/manage.py | 435 | except Exception as e: | CODE |
| LOW | docker/manage.py | 507 | except Exception: | CODE |
| LOW | docker/manage.py | 512 | except Exception: | CODE |
| LOW | docker/manage.py | 527 | except Exception: | CODE |
| LOW | docker/manage.py | 554 | except Exception as e: | CODE |
| LOW | docker/manage.py | 590 | except Exception as e: | CODE |
| LOW | docker/manage.py | 608 | except Exception as e: | CODE |
| LOW | docker/manage.py | 613 | except Exception: | CODE |
| LOW | docker/manage.py | 641 | except Exception as e: | CODE |
| LOW | docker/manage.py | 726 | except Exception as e: | STRING |
| LOW⚡ | trendradar/__main__.py | 119 | except Exception: | CODE |
| LOW | trendradar/__main__.py | 151 | except Exception as e: | CODE |
| LOW | trendradar/__main__.py | 298 | except Exception as e: | CODE |
| LOW | trendradar/__main__.py | 429 | except Exception as e: | CODE |
| LOW | trendradar/__main__.py | 478 | except Exception as e: | CODE |
| LOW | trendradar/__main__.py | 1086 | except Exception as e: | CODE |
| LOW | trendradar/__main__.py | 1385 | except Exception as e: | CODE |
| LOW | trendradar/__main__.py | 1630 | except Exception as e: | CODE |
| LOW | trendradar/__main__.py | 1708 | except Exception as e: | STRING |
| LOW | trendradar/core/cdn.py | 69 | except Exception as e: | CODE |
| LOW | trendradar/core/cdn.py | 86 | except Exception: | CODE |
| LOW | trendradar/core/data.py | 78 | except Exception as e: | CODE |
| LOW | trendradar/core/data.py | 193 | except Exception as e: | CODE |
| LOW | trendradar/notification/senders.py | 221 | except Exception as e: | CODE |
| LOW | trendradar/notification/senders.py | 337 | except Exception as e: | CODE |
| LOW | trendradar/notification/senders.py | 464 | except Exception as e: | CODE |
| LOW | trendradar/notification/senders.py | 579 | except Exception as e: | CODE |
| LOW | trendradar/notification/senders.py | 740 | except Exception as e: | STRING |
| LOW | trendradar/notification/senders.py | 923 | except Exception as e: | STRING |
| LOW | trendradar/notification/senders.py | 1085 | except Exception as e: | STRING |
| LOW | trendradar/notification/senders.py | 1197 | except Exception as e: | STRING |
| LOW | trendradar/notification/senders.py | 1321 | except Exception as e: | STRING |
| LOW | trendradar/crawler/fetcher.py | 139 | except Exception as e: | CODE |
| LOW | trendradar/crawler/fetcher.py | 225 | except Exception as e: | CODE |
| LOW | trendradar/crawler/rss/fetcher.py | 149 | except Exception as e: | CODE |
| LOW | trendradar/utils/time.py | 164 | except Exception: | CODE |
| LOW | trendradar/utils/time.py | 237 | except Exception: | CODE |
| LOW | trendradar/utils/time.py | 285 | except Exception: | CODE |
| LOW | trendradar/utils/url.py | 126 | except Exception: | CODE |
| LOW⚡ | trendradar/storage/remote.py | 638 | except Exception as e: | CODE |
| LOW⚡ | trendradar/storage/remote.py | 765 | except Exception: | CODE |
| LOW | trendradar/storage/remote.py | 203 | except Exception as e: | CODE |
| LOW | trendradar/storage/remote.py | 251 | except Exception as e: | CODE |
| LOW | trendradar/storage/remote.py | 319 | except Exception as e: | CODE |
| LOW | trendradar/storage/remote.py | 616 | except Exception as e: | CODE |
| LOW | trendradar/storage/remote.py | 658 | except Exception as e: | CODE |
| LOW | trendradar/storage/remote.py | 671 | except Exception as e: | CODE |
| LOW | trendradar/storage/remote.py | 725 | except Exception: | CODE |
| LOW | trendradar/storage/remote.py | 743 | except Exception as e: | CODE |
| LOW | trendradar/storage/remote.py | 754 | except Exception as e: | CODE |
| LOW | trendradar/storage/remote.py | 825 | except Exception as e: | CODE |
| LOW | trendradar/storage/remote.py | 857 | except Exception as e: | CODE |
| 119 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | trendradar/__init__.py | 10 | CODE | |
| LOW | trendradar/context.py | 12 | CODE | |
| LOW | trendradar/context.py | 12 | CODE | |
| LOW | trendradar/core/__init__.py | 6 | CODE | |
| LOW | trendradar/core/__init__.py | 6 | CODE | |
| LOW | trendradar/core/__init__.py | 6 | CODE | |
| LOW | trendradar/core/__init__.py | 6 | CODE | |
| LOW | trendradar/core/__init__.py | 12 | CODE | |
| LOW | trendradar/core/__init__.py | 13 | CODE | |
| LOW | trendradar/core/__init__.py | 13 | CODE | |
| LOW | trendradar/core/__init__.py | 14 | CODE | |
| LOW | trendradar/core/__init__.py | 14 | CODE | |
| LOW | trendradar/core/__init__.py | 15 | CODE | |
| LOW | trendradar/core/__init__.py | 15 | CODE | |
| LOW | trendradar/core/__init__.py | 15 | CODE | |
| LOW | trendradar/core/__init__.py | 15 | CODE | |
| LOW | trendradar/core/__init__.py | 21 | CODE | |
| LOW | trendradar/core/__init__.py | 21 | CODE | |
| LOW | trendradar/core/__init__.py | 21 | CODE | |
| LOW | trendradar/core/__init__.py | 21 | CODE | |
| LOW | trendradar/notification/dispatcher.py | 13 | CODE | |
| LOW | trendradar/notification/dispatcher.py | 40 | CODE | |
| LOW | trendradar/notification/__init__.py | 19 | CODE | |
| LOW | trendradar/notification/__init__.py | 19 | CODE | |
| LOW | trendradar/notification/__init__.py | 23 | CODE | |
| LOW | trendradar/notification/__init__.py | 23 | CODE | |
| LOW | trendradar/notification/__init__.py | 23 | CODE | |
| LOW | trendradar/notification/__init__.py | 23 | CODE | |
| LOW | trendradar/notification/__init__.py | 29 | CODE | |
| LOW | trendradar/notification/__init__.py | 29 | CODE | |
| LOW | trendradar/notification/__init__.py | 33 | CODE | |
| LOW | trendradar/notification/__init__.py | 33 | CODE | |
| LOW | trendradar/notification/__init__.py | 37 | CODE | |
| LOW | trendradar/notification/__init__.py | 37 | CODE | |
| LOW | trendradar/notification/__init__.py | 37 | CODE | |
| LOW | trendradar/notification/__init__.py | 37 | CODE | |
| LOW | trendradar/notification/__init__.py | 37 | CODE | |
| LOW | trendradar/notification/__init__.py | 37 | CODE | |
| LOW | trendradar/notification/__init__.py | 37 | CODE | |
| LOW | trendradar/notification/__init__.py | 37 | CODE | |
| LOW | trendradar/notification/__init__.py | 37 | CODE | |
| LOW | trendradar/notification/__init__.py | 48 | CODE | |
| LOW | trendradar/crawler/__init__.py | 6 | CODE | |
| LOW | trendradar/crawler/rss/__init__.py | 8 | CODE | |
| LOW | trendradar/crawler/rss/__init__.py | 9 | CODE | |
| LOW | trendradar/crawler/rss/__init__.py | 9 | CODE | |
| LOW | trendradar/crawler/rss/fetcher.py | 17 | CODE | |
| LOW | trendradar/utils/__init__.py | 6 | CODE | |
| LOW | trendradar/utils/__init__.py | 6 | CODE | |
| LOW | trendradar/utils/__init__.py | 6 | CODE | |
| LOW | trendradar/utils/__init__.py | 6 | CODE | |
| LOW | trendradar/utils/__init__.py | 6 | CODE | |
| LOW | trendradar/utils/__init__.py | 13 | CODE | |
| LOW | trendradar/storage/__init__.py | 11 | CODE | |
| LOW | trendradar/storage/__init__.py | 11 | CODE | |
| LOW | trendradar/storage/__init__.py | 11 | CODE | |
| LOW | trendradar/storage/__init__.py | 11 | CODE | |
| LOW | trendradar/storage/__init__.py | 11 | CODE | |
| LOW | trendradar/storage/__init__.py | 11 | CODE | |
| LOW | trendradar/storage/__init__.py | 19 | CODE | |
| 31 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docker/manage.py | 36 | CODE | |
| LOW | docker/manage.py | 117 | CODE | |
| LOW | docker/manage.py | 322 | CODE | |
| LOW | trendradar/__main__.py | 199 | CODE | |
| LOW | trendradar/__main__.py | 305 | CODE | |
| LOW | trendradar/__main__.py | 502 | CODE | |
| LOW | trendradar/__main__.py | 792 | CODE | |
| LOW | trendradar/__main__.py | 988 | CODE | |
| LOW | trendradar/__main__.py | 1263 | CODE | |
| LOW | trendradar/__main__.py | 1335 | CODE | |
| LOW | trendradar/core/frequency.py | 96 | CODE | |
| LOW | trendradar/core/analyzer.py | 93 | CODE | |
| LOW | trendradar/core/analyzer.py | 494 | CODE | |
| LOW | trendradar/core/scheduler.py | 363 | CODE | |
| LOW | trendradar/core/data.py | 113 | CODE | |
| LOW | trendradar/notification/dispatcher.py | 73 | CODE | |
| LOW | trendradar/notification/dispatcher.py | 750 | CODE | |
| LOW | trendradar/notification/renderer.py | 18 | CODE | |
| LOW | trendradar/notification/renderer.py | 150 | CODE | |
| LOW | trendradar/notification/splitter.py | 135 | CODE | |
| LOW | trendradar/notification/splitter.py | 995 | CODE | |
| LOW | trendradar/notification/splitter.py | 1226 | CODE | |
| LOW | trendradar/notification/splitter.py | 1474 | CODE | |
| LOW | trendradar/notification/splitter.py | 1701 | CODE | |
| LOW | trendradar/notification/splitter.py | 1807 | CODE | |
| LOW | trendradar/notification/splitter.py | 376 | CODE | |
| LOW | trendradar/notification/splitter.py | 617 | CODE | |
| LOW | trendradar/notification/splitter.py | 791 | CODE | |
| LOW | trendradar/notification/senders.py | 96 | CODE | |
| LOW | trendradar/notification/senders.py | 230 | CODE | |
| LOW | trendradar/notification/senders.py | 346 | CODE | |
| LOW | trendradar/notification/senders.py | 473 | CODE | |
| LOW | trendradar/notification/senders.py | 588 | CODE | |
| LOW | trendradar/notification/senders.py | 747 | CODE | |
| LOW | trendradar/notification/senders.py | 938 | CODE | |
| LOW | trendradar/notification/senders.py | 1100 | CODE | |
| LOW | trendradar/notification/senders.py | 1206 | CODE | |
| LOW | trendradar/crawler/fetcher.py | 153 | CODE | |
| LOW | trendradar/crawler/rss/fetcher.py | 200 | CODE | |
| LOW | trendradar/utils/time.py | 96 | CODE | |
| LOW | trendradar/utils/time.py | 175 | CODE | |
| LOW | trendradar/utils/time.py | 242 | CODE | |
| LOW | trendradar/storage/remote.py | 574 | CODE | |
| LOW | trendradar/storage/remote.py | 680 | CODE | |
| LOW | trendradar/storage/remote.py | 773 | CODE | |
| LOW | trendradar/storage/remote.py | 831 | CODE | |
| LOW | trendradar/storage/local.py | 289 | CODE | |
| LOW | trendradar/storage/local.py | 395 | CODE | |
| LOW | trendradar/storage/sqlite_mixin.py | 119 | CODE | |
| LOW | trendradar/storage/sqlite_mixin.py | 343 | CODE | |
| LOW | trendradar/storage/sqlite_mixin.py | 482 | CODE | |
| LOW | trendradar/storage/sqlite_mixin.py | 620 | CODE | |
| LOW | trendradar/storage/sqlite_mixin.py | 818 | CODE | |
| LOW | trendradar/storage/sqlite_mixin.py | 1044 | CODE | |
| LOW | trendradar/storage/sqlite_mixin.py | 1581 | CODE | |
| LOW | trendradar/storage/base.py | 230 | CODE | |
| LOW | trendradar/ai/analyzer.py | 255 | CODE | |
| LOW | trendradar/ai/analyzer.py | 470 | CODE | |
| LOW | trendradar/ai/filter.py | 119 | CODE | |
| LOW | trendradar/ai/filter.py | 386 | CODE | |
| 50 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | config/config.en.yaml | 1 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| LOW | config/config.en.yaml | 21 | show_version_update: true # Show version-update prompt (true=show, false=hide) | COMMENT |
| LOW | config/config.en.yaml | 41 | # =============================================================== | COMMENT |
| LOW | config/config.en.yaml | 141 | - id: "yahoo-finance" | COMMENT |
| LOW | config/config.en.yaml | 361 | # - gemini/gemini-2.5-flash (Google Gemini) | COMMENT |
| LOW | config/config.en.yaml | 381 | # Step 2 — prefix the model with "openai/" | COMMENT |
| LOW | config/ai_translation_prompt.txt | 1 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| LOW | config/ai_analysis_prompt.txt | 1 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| LOW | config/config.yaml | 1 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| LOW | config/config.yaml | 21 | show_version_update: true # 是否显示版本更新提示(true=显示, false=隐藏) | COMMENT |
| LOW | config/config.yaml | 41 | # =============================================================== | COMMENT |
| LOW | config/config.yaml | 141 | name: "雅虎财经" | COMMENT |
| LOW | config/config.yaml | 361 | # - anthropic/claude-sonnet-4-20250514 (Anthropic) | COMMENT |
| LOW | config/config.yaml | 381 | # | COMMENT |
| LOW | config/timeline.en.yaml | 1 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| LOW | config/timeline.en.yaml | 21 | # | COMMENT |
| LOW | config/timeline.en.yaml | 41 | # Call an AI model to deeply analyze the collected news (optional; needs an API key) | COMMENT |
| LOW | config/timeline.en.yaml | 61 | # | COMMENT |
| LOW | config/timeline.en.yaml | 81 | # | COMMENT |
| LOW | config/timeline.en.yaml | 101 | # | COMMENT |
| LOW | config/timeline.en.yaml | 361 | # | COMMENT |
| LOW | config/timeline.en.yaml | 381 | # Fields not written inside a block also fall back to the default. | COMMENT |
| LOW | config/timeline.en.yaml | 401 | COMMENT | |
| LOW | config/timeline.en.yaml | 421 | COMMENT | |
| LOW | config/timeline.en.yaml | 441 | # A period can also set this to override | COMMENT |
| LOW | config/timeline.en.yaml | 541 | # | COMMENT |
| LOW | config/frequency_words.en.txt | 1 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| LOW | config/frequency_words.en.txt | 21 | # Global Filter | COMMENT |
| LOW | config/frequency_words.en.txt | 41 | # | COMMENT |
| LOW | config/frequency_words.en.txt | 61 | # ┌─────────────────────────────────────────────────────────────┐ | COMMENT |
| LOW | config/frequency_words.en.txt | 81 | # 3. Name the group (recommended) | COMMENT |
| LOW | config/frequency_words.en.txt | 101 | # | COMMENT |
| LOW | config/frequency_words.en.txt | 121 | # [Apple Inc.] | COMMENT |
| LOW | config/frequency_words.en.txt | 141 | # ──────────────────── | COMMENT |
| LOW | config/timeline.yaml | 1 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| LOW | config/timeline.yaml | 21 | # | COMMENT |
| LOW | config/timeline.yaml | 41 | # 调用 AI 大模型对采集到的新闻进行深度分析(可选,需配置 API Key) | COMMENT |
| LOW | config/timeline.yaml | 61 | # | COMMENT |
| LOW | config/timeline.yaml | 81 | # ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ | COMMENT |
| LOW | config/timeline.yaml | 101 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| LOW | config/timeline.yaml | 361 | # | COMMENT |
| LOW | config/timeline.yaml | 381 | # | COMMENT |
| LOW | config/timeline.yaml | 401 | # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | COMMENT |
| LOW | config/timeline.yaml | 421 | COMMENT | |
| LOW | config/timeline.yaml | 441 | # 例如晚间汇总用 AI 筛选: | COMMENT |
| LOW | config/timeline.yaml | 541 | # 什么是「冲突」? | COMMENT |
| LOW | config/frequency_words.txt | 1 | # ═══════════════════════════════════════════════════════════════ | COMMENT |
| LOW | config/frequency_words.txt | 21 | # 全局过滤区 | COMMENT |
| LOW | config/frequency_words.txt | 41 | # | COMMENT |
| LOW | config/frequency_words.txt | 61 | # ┌─────────────────────────────────────────────────────────────┐ | COMMENT |
| LOW | config/frequency_words.txt | 81 | # 3. 给词组起个名字(推荐) | COMMENT |
| LOW | config/frequency_words.txt | 101 | # | COMMENT |
| LOW | config/frequency_words.txt | 121 | # [苹果公司] | COMMENT |
| LOW | config/frequency_words.txt | 141 | # ──────────────────── | COMMENT |
| LOW | docs/assets/style.css | 1 | /* 编辑器区域滚动条 */ | COMMENT |
| LOW | .github/workflows/crawler.yml | 1 | name: Get Hot News | COMMENT |
| LOW | .github/workflows/crawler.yml | 21 | # 🙏 珍惜资源 / Respect shared resources: | COMMENT |
| LOW | .github/workflows/crawler.yml | 101 | # Critical for load balancing. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | trendradar/context.py | 308 | CODE | |
| LOW | trendradar/context.py | 405 | CODE | |
| LOW | trendradar/__main__.py | 652 | CODE | |
| LOW | trendradar/__main__.py | 792 | CODE | |
| LOW | trendradar/core/analyzer.py | 93 | CODE | |
| LOW | trendradar/notification/dispatcher.py | 248 | CODE | |
| LOW | trendradar/notification/splitter.py | 135 | CODE | |
| LOW | trendradar/notification/senders.py | 96 | CODE | |
| LOW | trendradar/notification/senders.py | 230 | CODE | |
| LOW | trendradar/notification/senders.py | 346 | CODE | |
| LOW | trendradar/notification/senders.py | 473 | CODE | |
| LOW | trendradar/notification/senders.py | 747 | CODE | |
| LOW | trendradar/notification/senders.py | 938 | CODE | |
| LOW | trendradar/notification/senders.py | 1100 | CODE | |
| LOW | trendradar/notification/senders.py | 1206 | CODE | |
| LOW | trendradar/storage/manager.py | 372 | CODE | |
| LOW | trendradar/storage/manager.py | 30 | CODE | |
| LOW | trendradar/ai/formatter.py | 65 | CODE | |
| LOW | trendradar/report/html.py | 16 | CODE | |
| LOW | trendradar/report/generator.py | 142 | CODE | |
| LOW | mcp_server/server.py | 693 | CODE | |
| LOW | mcp_server/tools/search_tools.py | 30 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | README-EN.md | 1746 | ### Step 1: Create Slack App | COMMENT |
| LOW | README-EN.md | 1760 | ### Step 2: Enable Incoming Webhooks | COMMENT |
| LOW | README-EN.md | 1770 | ### Step 3: Generate Webhook URL | COMMENT |
| LOW | README-EN.md | 1785 | ### Step 4: Copy and Save Webhook URL | COMMENT |
| LOW⚡ | README-EN.md | 2368 | # Step 1: Start with broad keywords for testing | COMMENT |
| LOW⚡ | README-EN.md | 2373 | # Step 2: After finding mismatches, add required words | COMMENT |
| LOW⚡ | README-EN.md | 2379 | # Step 3: After finding noise, add filter words | COMMENT |
| LOW⚡ | config/timeline.en.yaml | 368 | # Step 1: Define "blocks" (periods) | COMMENT |
| LOW⚡ | config/timeline.en.yaml | 372 | # Step 2: Assemble "a day's plan" (day_plans) | COMMENT |
| LOW⚡ | config/timeline.en.yaml | 376 | # Step 3: Assign "which plan each day uses" (week_map) | COMMENT |
| LOW⚡ | config/timeline.en.yaml | 450 | # Step 1: Define blocks (periods) | COMMENT |
| LOW⚡ | config/timeline.en.yaml | 511 | # Step 2: Assemble blocks into day plans | COMMENT |
| LOW⚡ | config/timeline.en.yaml | 525 | # Step 3: Assign which day plan each day uses | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | trendradar/core/scheduler.py | 0 | 检查指定时间段的某个 action 是否已执行 args: date_str: 日期字符串 yyyy-mm-dd period_key: 时间段 key action: 动作类型 (analyze / push) returns: 是否已执 | STRING |
| HIGH | trendradar/storage/sqlite_mixin.py | 0 | 检查指定时间段的某个 action 是否已执行 args: date_str: 日期字符串 yyyy-mm-dd period_key: 时间段 key action: 动作类型 (analyze / push) returns: 是否已执 | STRING |
| HIGH | trendradar/storage/base.py | 0 | 检查指定时间段的某个 action 是否已执行 args: date_str: 日期字符串 yyyy-mm-dd period_key: 时间段 key action: 动作类型 (analyze / push) returns: 是否已执 | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | trendradar/__init__.py | 13 | __all__ = ["AppContext", "__version__"] | CODE |
| LOW⚡ | trendradar/__main__.py | 126 | def _setup_proxy(self) -> None: | CODE |
| LOW⚡ | trendradar/__main__.py | 136 | def _set_update_info_from_config(self) -> None: | CODE |
| LOW | trendradar/core/__init__.py | 28 | __all__ = [ | CODE |
| LOW | trendradar/core/cdn.py | 16 | logger = logging.getLogger(__name__) | CODE |
| LOW | trendradar/notification/__init__.py | 50 | __all__ = [ | CODE |
| LOW | trendradar/crawler/__init__.py | 8 | __all__ = ["DataFetcher"] | CODE |
| LOW | trendradar/crawler/rss/__init__.py | 11 | __all__ = ["RSSParser", "RSSFetcher", "RSSFeedConfig"] | CODE |
| LOW | trendradar/utils/__init__.py | 15 | __all__ = [ | CODE |
| LOW | trendradar/storage/__init__.py | 31 | __all__ = [ | CODE |
| LOW | trendradar/ai/__init__.py | 21 | __all__ = [ | CODE |
| LOW | trendradar/report/__init__.py | 28 | __all__ = [ | CODE |
| LOW | trendradar/commands/__init__.py | 13 | __all__ = [ | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | config/timeline.en.yaml | 368 | # Step 1: Define "blocks" (periods) | COMMENT |
| LOW⚡ | config/timeline.en.yaml | 372 | # Step 2: Assemble "a day's plan" (day_plans) | COMMENT |
| LOW⚡ | config/timeline.en.yaml | 376 | # Step 3: Assign "which plan each day uses" (week_map) | COMMENT |
| LOW⚡ | config/timeline.en.yaml | 450 | # Step 1: Define blocks (periods) | COMMENT |
| LOW⚡ | config/timeline.en.yaml | 511 | # Step 2: Assemble blocks into day plans | COMMENT |
| LOW⚡ | config/timeline.en.yaml | 525 | # Step 3: Assign which day plan each day uses | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | README-EN.md | 2705 | └── docker-compose.yml # Docker Compose orchestration file | CODE |