Content
<div align="center" id="trendradar">
<a href="https://github.com/sansan0/TrendRadar" title="TrendRadar">
<img src="/_image/banner.webp" alt="TrendRadar Banner" width="80%">
</a>
Fastest <strong>30 seconds</strong> deployment of hot spot assistant - goodbye ineffective brushing, only see the news information you really care about
<a href="https://trendshift.io/repositories/14726" target="_blank"><img src="https://trendshift.io/api/badge/repositories/14726" alt="sansan0%2FTrendRadar | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
[](https://github.com/sansan0/TrendRadar/stargazers)
[](https://github.com/sansan0/TrendRadar/network/members)
[](LICENSE)
[](https://github.com/sansan0/TrendRadar)
[](https://github.com/sansan0/TrendRadar)
[](https://hub.docker.com/r/wantcat/trendradar)
[](https://hub.docker.com/r/wantcat/trendradar-mcp)
[](https://github.com/sansan0/TrendRadar)
[](https://github.com/sansan0/TrendRadar)
[](https://work.weixin.qq.com/)
[](https://weixin.qq.com/)
[](https://telegram.org/)
[](#)
[](https://www.feishu.cn/)
[](#)
[](https://github.com/binwiederhier/ntfy)
[](https://github.com/Finb/Bark)
[](https://slack.com/)
[](#)
[](https://github.com/sansan0/TrendRadar)
[](https://sansan0.github.io/TrendRadar)
[](https://hub.docker.com/r/wantcat/trendradar)
[](https://modelcontextprotocol.io/)
[](#)
[](#)
</div>
<div align="center">
**English** | **[English](README-EN.md)**
</div>
> This project aims to be lightweight and easy to deploy
<br>
## 📑 Quick Navigation
> 💡 **Click the link below** to quickly jump to the corresponding section. It is recommended to start with "**Quick Start**" for deployment, and for detailed customization, please refer to "**Configuration Details**".
<div align="center">
| | | |
|:---:|:---:|:---:|
| [🚀 **Quick Start**](#-quick-start) | [AI Intelligent Analysis](#-ai-intelligent-analysis) | [⚙️ **Configuration Details**](#configuration-details) |
| [Docker Deployment](#6-docker-deployment) | [MCP Client](#-mcp-client) | [📝 **Update Log**](#-update-log) |
| [🎯 **Core Features**](#-core-features) | [☕ **Support Projects**](#-support-projects) | [📚 **Project Related**](#-project-related) |
</div>
<br>
- Thanks to the audience who **starred** the project, **fork** as you wish, **star** as I wish, and having both 😍 is the best support for open source spirit.
<details>
<summary>👉 Click to expand: <strong>Acknowledgment List</strong> (Angel Round Honor List 🔥73+🔥 people)</summary>
### Early Supporters Acknowledgment
> 💡 **Special Note**:
>
> 1. **About the list**: The table below records the supporters during the early stages (angel round) of the project. Due to manual statistics being cumbersome and prone to errors, **there might be omissions or incomplete records. If there are any oversights, they are unintentional and we appreciate your understanding**.
> 2. **Future Plans**: In order to dedicate limited energy to code and functional iterations, **as of now, this list will no longer be manually maintained**.
>
> Regardless of whether your name is listed, every bit of support you provided has been the foundation for TrendRadar to reach where it is today. 🙏
### Infrastructure Support
Thanks to **GitHub** for providing free infrastructure, which is the primary reason this project can be **one-click forked** and run conveniently.
### Data Support
This project uses the API from the [newsnow](https://github.com/ourongxing/newsnow) project to obtain multi-platform data, and we extend special thanks to the author for providing the service.
After contact, the author expressed no concerns about server pressure, but this is based on their goodwill and trust. Please:
- **Go to the [newsnow project](https://github.com/ourongxing/newsnow) and star it for support**
- When deploying with Docker, please reasonably control the push frequency and avoid overfishing.
### Promotion Assistance
> Thanks to the following platforms and individuals for their recommendations (in chronological order)
- [Minor Software](https://mp.weixin.qq.com/s/fvutkJ_NPUelSW9OGK39aA) - Open-source software recommendation platform
- [LinuxDo Community](https://linux.do/) - A gathering place for tech enthusiasts
- [Ruanyf Weekly](https://github.com/ruanyf/weekly) - A influential weekly in the tech circle
### Audience Support
> Thanks to **those who have financially supported** us. Your generosity has transformed into snacks and drinks beside our keyboards, accompanying every iteration of the project.
>
> **Regarding the return of "One Yuan Appreciation"**:
> With the release of version 5.0.0, the project has entered a new phase. To support the growing API costs and caffeine consumption, the "One Yuan Appreciation" channel has been reopened. Every intention you have will be converted into tokens and motivation in the world of code. 🚀 [Go to support](#-support-the-project)
| Donor | Amount | Date | Remarks |
| :-------------------------: | :----: | :----: | :-----------------------: |
| D*5 | 1.8 * 3 | 2025.11.24 | |
| *鬼 | 1 | 2025.11.17 | |
| *超 | 10 | 2025.11.17 | |
| R*w | 10 | 2025.11.17 | This agent is awesome, brother |
| J*o | 1 | 2025.11.17 | Thanks for open-sourcing, wishing you success |
| *晨 | 8.88 | 2025.11.16 | The project is great, I'm studying and learning |
| *海 | 1 | 2025.11.15 | |
| *德 | 1.99 | 2025.11.15 | |
| *疏 | 8.8 | 2025.11.14 | Thanks for open-sourcing, the project is great, supporting |
| M*e | 10 | 2025.11.14 | Open-sourcing is not easy, thanks for your hard work |
| **柯 | 1 | 2025.11.14 | |
| *云 | 88 | 2025.11.13 | Good project, thanks for open-sourcing |
| *W | 6 | 2025.11.13 | |
| *凯 | 1 | 2025.11.13 | |
| 对*. | 1 | 2025.11.13 | Thanks for your TrendRadar |
| s*y | 1 | 2025.11.13 | |
| **翔 | 10 | 2025.11.13 | Good project, it's a pity to meet you late, thanks for open-sourcing! |
| *韦 | 9.9 | 2025.11.13 | TrendRadar is awesome, please have a cup of coffee~ |
| h*p | 5 | 2025.11.12 | Supporting China's open-source power, come on! |
| c*r | 6 | 2025.11.12 | |
| a*n | 5 | 2025.11.12 | |
| 。*c | 1 | 2025.11.12 | Thanks for sharing |
| *记 | 1 | 2025.11.11 | |
| *主 | 1 | 2025.11.10 | |
| *了 | 10 | 2025.11.09 | |
| *杰 | 5 | 2025.11.08 | |
| *点 | 8.80 | 2025.11.07 | It's not easy to develop, supporting一下。 |
| Q*Q | 6.66 | 2025.11.07 | Thanks for open-sourcing! |
| C*e | 1 | 2025.11.05 | |
| Peter Fan | 20 | 2025.10.29 | |
| M*n | 1 | 2025.10.27 | Thanks for open-sourcing |
| *许 | 8.88 | 2025.10.23 | Teacher, I'm a newbie, I've been playing around for a few days and still can't get it, seeking guidance |
| Eason | 1 | 2025.10.22 | I haven't figured it out yet, but you're doing a good thing |
| P*n | 1 | 2025.10.20 | |
| *杰 | 1 | 2025.10.19 | |
| *徐 | 1 | 2025.10.18 | |
| *志 | 1 | 2025.10.17 | |
| *😀 | 10 | 2025.10.16 | Appreciate |
| **杰 | 10 | 2025.10.16 | |
| *啸 | 10 | 2025.10.16 | |
| *纪 | 5 | 2025.10.14 | TrendRadar |
| J*d | 1 | 2025.10.14 | Thanks for your tool, it's fun... |
| *H | 1 | 2025.10.14 | |
| 那*O | 10 | 2025.10.13 | |
| *圆 | 1 | 2025.10.13 | |
| P*g | 6 | 2025.10.13 | |
| Ocean | 20 | 2025.10.12 | ...it's really great!!!even for a newbie like me... |
| **培 | 5.2 | 2025.10.2 | github-yzyf1312:open-source forever |
| *椿 | 3 | 2025.9.23 | Keep going, it's great |
| *🍍 | 10 | 2025.9.21 | |
| E*f | 1 | 2025.9.20 | |
| *记 | 1 | 2025.9.20 | |
| z*u | 2 | 2025.9.19 | |
| **昊 | 5 | 2025.9.17 | |
| *号 | 1 | 2025.9.15 | |
| T*T | 2 | 2025.9.15 | Appreciate |
| *家 | 10 | 2025.9.10 | |
| *X | 1.11 | 2025.9.3 | |
| *飙 | 20 | 2025.8.31 | From old童, thanks |
| *下 | 1 | 2025.8.30 | |
| 2*D | 88 | 2025.8.13 下午 | |
| 2*D | 1 | 2025.8.13 上午 | |
| S*o | 1 | 2025.8.05 | Supporting一下 |
| *侠 | 10 | 2025.8.04 | |
| x*x | 2 | 2025.8.03 | trendRadar great project appreciate |
| *远 | 1 | 2025.8.01 | |
| *邪 | 5 | 2025.8.01 | |
| *梦 | 0.1 | 2025.7.30 | |
| **龙 | 10 | 2025.7.29 | Supporting一下 |
</details>
<br>
## 🪄 Sponsors
<div align="center">
> **Position available**
>
> Interested in sponsoring? Trigger the auto-reply in the WeChat public account to get my contact information
</div>
<br>
<a name="-support-the-project"></a>
### ❤️ Appreciate if you like it
> If TrendRadar has helped you capture value, consider contributing to its continued evolution
>
> Any amount is welcome, and even 1 yuan is an encouragement for open-source. Feel free to leave a message when appreciating (´▽`ʃ♡ƪ)
<div align="center">
| WeChat Appreciation | Alipay Appreciation |
|:---:|:---:|
| <img src="https://cdn-1258574687.cos.ap-shanghai.myqcloud.com/img/%2F2025%2F07%2F17%2F2ae0a88d98079f7e876c2b4dc85233c6-9e8025.JPG" width="240" alt="WeChat Appreciation"> | <img src="https://cdn-1258574687.cos.ap-shanghai.myqcloud.com/img/%2F2025%2F07%2F17%2F1ed4f20ab8e35be51f8e84c94e6e239b4-fe4947.JPG" width="240" alt="Alipay Appreciation"> |
</div>
### 🤝 Secondary development and citation
If you use or draw inspiration from this project's ideas or core code in your project, **you are very welcome** to mention the source and attach a link to this repository in your README or documentation.
This will help with the project's continued maintenance and community development, and we appreciate your respect and support! ❤️
### 💬 Communication and feedback
- **GitHub Issues**: Suitable for specific technical issues. Please provide complete information (screenshots, error logs, etc.) to help locate the issue quickly.
- **Public account communication**: It's recommended to communicate in the comment section of relevant articles. If you need to ask questions in the background, **liking/recommending** the article is the best "knock on the door," and I can feel your intention (´▽`ʃ♡ƪ).
- **QQ group communication**: Follow the public account and reply with "**交流群**" to join. Whether you're an AI newbie or a hardcore developer, you can ask technical questions or share experiences. The group focuses on mutual assistance and inspiration, and please look at the group announcement before joining; when asking questions, describe the issue clearly and attach screenshots, and group friends will help when they're available 🤝
> **Friendly reminder**:
> This project is open-source sharing, not a commercial product. Treating the author as a friend rather than customer service will make communication more efficient!
<div align="center">
|Public Account|
|:---:|
| <img src="_image/weixin.png" width="500" title="硅基茶水间"/> |
</div>
<br>
## 📝 Update Log
> **📌 View the latest updates**: **[Original repository update log](https://github.com/sansan0/TrendRadar?tab=readme-ov-file#-更新日志)** :
- **Tips**: It's recommended to view the [historical updates] to understand the specific [functional content]
### 2026/06/19 - v6.10.0
- **AI translation batch processing**: Automatically batch requests for large title translations to avoid translation failures due to exceeding limits
- **Module splitting and refactoring**: Split context.py and __main__.py, and independently develop the AI screening pipeline into the filter_pipeline module for clearer responsibilities and easier maintenance
- **Fix Feishu source label display**: Fix the issue where Feishu card source labels and AI independent source points were not displayed due to being swallowed by CommonMark
### 2026/02/09 - mcp-v4.0.0
- **🔥 AI message direct push to all channels**: Let AI-written content be pushed to 9 channels like Feishu, DingTalk, Telegram, and email with one click, and Markdown automatically adapts to each platform's format without worrying about format differences
- **Add formatting strategy guide**: Add the get_channel_format_guide tool to tell AI which formats each channel supports and what limitations there are, making generated content better formatted
- **Intelligent batch sending**: Automatically split super-long messages into chunks according to each channel's byte limit (Feishu 30KB, DingTalk 20KB, etc.), with configurations read from config.yaml
- **Fix channel misdetection**: ntfy no longer reports "configured" due to default address
- **Code reuse optimization**: Batch processing functions directly reuse the core modules of trendradar without duplicating code
<details>
<summary>👉 Click to expand: <strong>Historical updates</strong></summary>
### 2026/06/02 - v6.9.0
- **Hotlist domain security verification**: Add the expected_domain configuration item to verify the domain legitimacy of returned data links, and discard data and warn if it doesn't match
- **Custom hotlist API address**: Support self-deployed newsnow and configure api_url to use your own data source
### 2026/05/23 - v6.8.0
- **HTML report comprehensive enhancement**: Add report metadata display (generation time, data source, version number), dark mode automatic adaptation, tab bar interaction optimization, trend arrow visualization, and significantly improved browser reading experience
- **Version check CDN multi-source fallback**: The version check interface supports automatic fallback from GitHub → jsDelivr → Cloudflare and other multiple CDN sources, ensuring stable acquisition even in domestic network environments
- **Display area switch takes effect**: HTML reports and emails now correctly respect the display.regions.ai_analysis and display.regions.standalone switches, and do not render if closed
- **Export button fix**: Fix the issue where the export button dropdown menu icon disappears after clicking
- **Markdown export fix**: Fix the issue where HTML report Markdown export had incorrect JS line breaks
### 2026/05/15 - v6.7.0
- **Markdown export**: Add Markdown format to the report export dropdown menu, generating structured text with links for easy LLM secondary processing and cross-platform sharing ([#1121](https://github.com/sansan0/TrendRadar/issues/1121))
- **RSS guid deduplication**: Add a guid field to RSS storage, changing the deduplication priority to guid > url to solve the issue of duplicate entry due to URL changes
- **Empty title protection**: Add empty title protection logic throughout the parser, rendering layer, and translation backfill to ensure normal display of title-less entries
- **Translation quality enhancement**: Require translation prompts to retain numbered order, and empty translation results no longer overwrite original titles
### 2026/03/28 - v6.6.0
- **HTML report browser enhancement**: Automatically switch to a wide-screen layout when opening a report in a browser, with keyword grouping and independent display areas supporting quick tab switching, real-time filtering of news titles in the search box, and original narrow-screen layout displayed in email clients
- **Dark mode**: One-click switch to a dark theme, automatically remembering preferences, suitable for nighttime reading
- **One-click news copy**: Hover over the news serial number to copy the title and link for easy sharing
- **Export optimization**: Merge screenshot and segmented screenshot into a dropdown export button, automatically restoring a clean layout for screenshots
- **Shortcut system**: Support 'W' for wide-screen switching, 'D' for dark mode, '/' for search, and '?' for viewing shortcut prompts
- **Reading progress bar**: Display real-time reading progress at the top of the page
### 2026/03/12 - v6.5.0
- **AI intelligent screening system**: No need to manually set keywords! Write your concerns in ai_interests.txt, and AI will automatically extract tags and score each piece of news, pushing only content that's truly relevant to you. If AI screening encounters issues, it will automatically switch back to keyword matching, ensuring uninterrupted pushing
- **Different screening methods and focus directions supported for each time period**: Each time period in the Timeline can now independently set what method to use for screening and what type of news to focus on. For example: use "tech keywords" to quickly filter in the morning and switch to "financial AI interest description" for in-depth screening in the evening - using the same system but looking at different content at different times
- **AI analysis range independent of push**: The data range of AI analysis can be different from the pushed content. For example, push only new messages (to avoid repetitive disturbance) but analyze all news for the day (to see the complete trend). Each time period can also independently set the AI analysis mode
- **AI screening intelligent saving**: Already analyzed news will not consume duplicate tokens; after changing interest descriptions, AI automatically judges the change amplitude - small changes only update affected tags, and large changes re-classify everything
- **Multi-file configuration and tag isolation**: Custom keyword files are placed in config/custom/keyword/, AI interest files are placed in config/custom/ai/, and tags generated by different files are independent and do not interfere with each other
- **AI translation precise control**: Can control whether hotlist, RSS, and independent display areas are translated, and areas that are not enabled for display automatically skip token consumption
- **Remote storage batch upload**: Multiple write operations are accumulated and submitted to the cloud at once to reduce API calls
- **Maximum display limit per keyword/tag**: Control the maximum number of news pieces displayed per grouping through max_news_per_keyword to prevent a single hot topic from occupying the entire push
- **Intelligent detection of time period conflicts**: If two time periods have overlapping times, the system automatically reports an error and prompts modification to avoid unexpected behavior due to configuration conflicts
- Fix several bugs
### 2026/02/09 - v6.0.0
> **Breaking Change**: Configuration file upgrade (config.yaml 2.0.0), old `push_window` and `analysis_window` configurations are no longer compatible, please refer to the new config.yaml migration
- **Unified Scheduling System**: Added `timeline.yaml`, use a single configuration to control "when to collect / push / AI analyze"
- **5 Preset Templates**: `always_on` (24/7, default), `morning_evening` (morning and evening summary), `office_hours` (office hours), `night_owl` (night owl), `custom` (custom); also supports adding custom templates under `presets:`, as long as the key is not repeated, and then fill in your template name in config.yaml
- **Flexible Time Period Configuration**: supports workday/weekend differences,跨午夜时间段, per-period once deduplication
- **Visual Configuration Editor**:
- Added `timeline.yaml` editing tab, parallel to config.yaml / frequency_words.txt
- Preset mode card selection: click to switch, automatically synchronize config.yaml's `schedule.preset`
- Weekly view timeline: 7 days × 24 hours horizontal bar, use color to distinguish push/analysis/collect status
- Interactive controls: switches, drop-down boxes, time selectors, modify in real-time and synchronize to left YAML
- Weekly mapping drop-down selection: dynamically fill in according to daily plan, drag and drop to complete scheduling configuration
- **AI Prompt Stability Optimization** (ai_analysis_prompt.txt v2.0.0):
- Format specification independent description: extract line breaks/tags/serial numbers/prohibited items from JSON value, as an independent chapter
- JSON template simplification: field description shortened to one sentence + word limit, reduce AI output format confusion
- Remove Markdown format in system prompt, consistent with "禁止 Markdown" instruction
- All JSON fields declared as optional, lack of any field will not error, enhance fault tolerance
- **New Independent Display Area AI Summary** (`ai_analysis.include_standalone`):
- New independent switch, after enabling, AI generates core summary for each standalone source
- AI analysis and push display decoupling: no need to enable push display in independent display area, AI can also independently analyze complete hot list data
- Supports hot list platform and RSS source, including ranking/time/trace data
- Trace analysis and `include_rank_timeline` linkage: when enabled, use trace data to do in-depth trend analysis, when closed, based on ranking to make simple judgment
- New `standalone_summaries` JSON field (independent source quick view), all push channels have been adapted to render
### 2026/01/28 - v5.5.0
> Same as mcp functionality, I didn't create a new repository for this small tool, it's pure front-end, so I'll put it together
- Add trendradar's visual configuration editor
### 2026/02/02 - mcp-v3.2.0
- **New read_article tool**: read single article content (Markdown format) through Jina AI Reader
- **New read_articles_batch tool**: batch read multiple articles (up to 5, automatic speed limit)
- **Recommended workflow**: `search_news(query="keyword", include_url=True)` → `read_article(url=...)` read content
- **Documentation update**: README-MCP-FAQ.md and README-MCP-FAQ-EN.md add Q19-Q20 article reading related instructions
### 2026/01/10 - mcp-v3.0.0~v3.1.5
- **Breaking Change**: all tool return values unified to `{success, summary, data, error}` structure
- **Asynchronous consistency**: all 21 tool functions use `asyncio.to_thread()` to package synchronous calls
- **MCP Resources**: add 4 resources (platforms, rss-feeds, available-dates, keywords)
- **RSS enhancement**: `get_latest_rss` supports multi-day query (days parameter),跨日期 URL deduplication
- **Regular expression fix**: `get_trending_topics` supports `/pattern/` regular expression syntax and `display_name`
- **Cache optimization**: add `make_cache_key()` function, parameter sorting + MD5 hash to ensure consistency
- **New check_version tool**: supports checking TrendRadar and MCP Server version updates at the same time
### 2026/01/23 - v5.4.0
- Add independent control function of AI analysis mode, optional follow_report | daily | current | incremental
- Add AI analysis time window control, support custom operation segment and daily frequency limit
- Add configuration file version management function
- Fix several bugs
### 2026/01/19 - v5.3.0
> **Major refactoring: AI module migration to LiteLLM**
- **Unified AI interface**: use LiteLLM instead of manual implementation, support 100+ AI providers
- **Simplified configuration**: remove `provider` field, use `model: "provider/model_name"` format
- **New features**: automatic retry (`num_retries`), backup model (`fallback_models`)
- **Configuration change**:
- `ai.provider` → remove (merged into model)
- `ai.base_url` → `ai.api_base`
- `AI_PROVIDER` environment variable → remove
- `AI_BASE_URL` environment variable → `AI_API_BASE`
- **Model format example**:
- DeepSeek: `deepseek/deepseek-chat`
- OpenAI: `openai/gpt-4o`
- Gemini: `gemini/gemini-2.5-flash`
- Anthropic: `anthropic/claude-3-5-sonnet`
### 2026/01/17 - v5.2.0
> Mainly see config.yaml description
**🌐 AI Translation Function**
- **Multi-language translation**: support translating push content into any language
- **Batch translation**: intelligent batch processing, reduce API call times
- **Custom prompt words**: support custom translation style
**🔧 Configuration Architecture Optimization**
- **AI model configuration independence**: analysis and translation share model configuration
- **Regional switch unification**: unified management of regional display
- **Regional sorting customization**: support custom display order of each region
**✨ AI Analysis Enhancement**
- **AI analysis embedded HTML**: analysis results directly embedded in HTML report, email notification directly use
- **Rich-style AI block**: gradient blue background card layout, clear separation of each analysis dimension
- **Ranking timeline support**: AI can obtain precise ranking of each news at each crawl time point
- **Sector reorganization (7→4)**: integrate into core hotspot situation, public opinion trend controversy, abnormal and weak signal, and research strategy suggestions
**🔧 Multi-model Adaptation**
- **General parameter pass-through**: support passing arbitrary advanced parameters to API
- **Gemini adaptation**: native parameter support, built-in security strategy relaxation
**🐛 Bug Fix**
- Fix several known issues, improve system stability
### 2026/01/10 - v5.0.0
> **Development episode**:
> Tribute to the one that accompanied me for more than two years, but after recharging, it popped up `"This organization has been disabled"`
**✨ Push Content "Five Major Sections" Refactor**
This update refactors the push message into five major sections:
1. **📊 Hot List News**: full network hotspot aggregation accurately screened according to your keywords.
2. **📰 RSS Subscription**: your personalized subscription source content, support grouping by keyword.
3. **🆕 Newly Added**: real-time capture of new hotspots since the last run (with 🆕 mark).
4. **📋 Independent Display Area**: complete hot list or RSS source display of specified platform, **completely不受关键词过滤限制**.
5. **✨ AI Analysis Section**: in-depth insights driven by AI, including trend overview, heat trend and **extremely important** emotional tendency analysis.
**✨ AI Intelligent Analysis Push Function**
- **AI analysis integration**: use large AI model to deeply analyze push content, automatically generate hotspot trend overview, keyword heat analysis, cross-platform association, potential impact assessment, etc.
- **Emotional tendency analysis**: add in-depth emotional recognition, accurately capture positive/negative, controversy or concern emotions of public opinion
- **Multi-AI provider support**: support DeepSeek (default, high cost-performance), OpenAI, Google Gemini and any OpenAI compatible interface
- **Two push modes**: `only_analysis` (only AI analysis), `both` (both push)
- **Custom prompt words**: customize AI analysis role and output format through `config/ai_analysis_prompt.txt` file
- **Multi-dimensional data analysis**: AI can analyze ranking changes, heat duration, cross-platform performance, trend prediction, etc.
**📋 Independent Display Area Function**
- **Complete hot list display**: complete hot list of specified platform separately displayed,不受关键词过滤影响
- **RSS independent display**: RSS source content can be completely displayed, suitable for content-less subscription sources
- **Flexible configuration**: support configuration display platform list, RSS source list, maximum display number
**📊 Push Experience Refactor**
- **排版升级**: redesign and unify statistical header of each channel, strengthen block organization, message hierarchy clear at a glance
- **Configuration simplification**: optimize configuration logic of Feishu and other notification channels, easier to use
- **Heat trend arrow**: add 🔺(up), 🔻(down), ➖(stable) trend mark, intuitively display heat change
- **General Webhook**: support custom Webhook URL and JSON template, easily adapt to Discord, Matrix, IFTTT and other platforms
**🔧 Configuration Optimization**
- **Frequency word configuration enhancement**: add `[group alias]` syntax, support `#` comment line, configuration clearer (thanks to [@songge8](https://github.com/sansan0/TrendRadar/issues/752) proposed suggestion)
- **Environment variable support**: AI analysis related configuration support environment variable coverage (`AI_API_KEY`, `AI_PROVIDER`, etc.)
> 💡 See detailed configuration tutorial in [让 AI 帮我分析热点](#12-让-ai-帮我分析热点)
### 2026/01/02 - v4.7.0
- **Fix RSS HTML display**: fix RSS data format mismatch causing rendering issue, now correctly display according to keyword grouping
- **Add regular expression syntax**: keyword configuration supports `/pattern/` regular expression syntax, solve English substring mis-matching problem (e.g., `ai` matches `training`) [📖 View syntax details](#关键词基础语法)
- **Add display name syntax**: use `=> remark` to give complex regular expression a good name, push message display clearer (e.g., `/\bai\b/ => AI-related`)
- **No regular expression?** README adds AI-generated regular expression guide, tell ChatGPT/Gemini/DeepSeek what you want to match, let AI help you write
### 2025/12/30 - mcp-v2.0.0
- **Architecture adjustment**: remove TXT support, unify use SQLite database
- **RSS query**: add `get_latest_rss`, `search_rss`, `get_rss_feeds_status`
- **Unified search**: `search_news` supports `include_rss` parameter to search hot list and RSS at the same time
### 2026/01/01 - v4.6.0
- **Fix RSS HTML display**: merge RSS content into hot list HTML page, display according to source grouping
- **Add display_mode configuration**: support `keyword` (group by keyword) and `platform` (group by platform) two display modes
### 2025/12/30 - v4.5.0
- **RSS subscription source support**: add RSS/Atom crawl, group by keyword statistics (consistent with hot list format)
- **Storage structure refactoring**: flatten directory structure `output/{type}/{date}.db`
- **Unified sorting configuration**: `sort_by_position_first` affects both hot list and RSS
- **Configuration structure refactoring**: `config.yaml` reorganize into 7 logical groups (app, report, notification, storage, platforms, rss, advanced), configuration path clearer
### 2025/12/26 - mcp-v1.2.0
**MCP module update - optimize toolset, add aggregation comparison function, merge redundant tools:**
- Add `aggregate_news` tool - cross-platform news deduplication aggregation
- Add `compare_periods` tool - period comparison analysis (week-on-week/month-on-month)
- Merge `find_similar_news` + `search_related_news_history` → `find_related_news`
- Enhance `get_trending_topics` - add `auto_extract` mode to automatically extract hotspots
- Fix several bugs
- Synchronously update README-MCP-FAQ.md Chinese and English version (Q1-Q18)
### 2025/12/20 - v4.0.3
- Add URL standardization function to solve duplicate push problem caused by dynamic parameters (e.g., `band_rank`) on platforms like Weibo
- Fix incremental mode detection logic to correctly identify historical titles
### 2025/12/17 - v4.0.1
- StorageManager adds push record proxy method
- S3 client switched to virtual-hosted style to improve compatibility (support Tencent Cloud COS and other services)
### 2025/12/13 - mcp-v1.1.0
**MCP module update:**
- Adapt to v4.0.0, also compatible with v3.x data
- Add storage synchronization tool: `sync_from_remote`, `get_storage_status`, `list_available_dates`
### 2025/12/13 - v4.0.0
**🎉 Major update: comprehensive refactoring of storage and core architecture**
- **Multi-storage backend support**: introduce new storage module, support local SQLite and remote cloud storage (S3 compatible protocol, e.g., Cloudflare R2), adapt to GitHub Actions, Docker and local environment.
- **Database structure optimization**: refactor SQLite database table structure to improve data efficiency and query ability.
- **Core code modularization**: split main program logic into multiple modules of trendradar package, significantly improve code maintainability.
- **Enhanced function**: realize date format standardization, data retention strategy, time zone configuration support, time display optimization, and fix remote storage data persistence problem to ensure accuracy of data merging.
- **Cleanup and compatibility**: remove most historical compatibility code, unify data storage and reading method.
### 2025/12/03 - v3.5.0
**🎉 Core function enhancement**
1. **Multi-account push support**
- All push channels (Feishu, Dingding, Enterprise WeChat, Telegram, ntfy, Bark, Slack) support multi-account configuration
- Use semicolon `;` to separate multiple accounts, e.g., `FEISHU_WEBHOOK_URL=url1;url2`
- Automatically verify and pair configuration (e.g., Telegram's token and chat_id) quantity consistency
2. **Push area configuration**
- Customize display order of each area through `display.region_order` (v5.2.0 replaces original `reverse_content_order`)
- Control whether each area is displayed through `display.regions` (hot list, new hotspot, RSS, independent display area, AI analysis)
3. **Global filter keyword**
- Add `[GLOBAL_FILTER]` area mark, support global filtering of unwanted content
- Applicable scenarios: filter advertisements, marketing, low-quality content, etc.
**🐳 Docker double-path HTML generation optimization**
- **Problem fix**: solve the problem that `index.html` cannot be synchronized to the host in Docker environment
- **Double-path generation**: generate today's summary HTML in two locations
- `index.html` (project root directory): for GitHub Pages access
- `output/index.html`: through Docker Volume mount, host can directly access
- **Compatibility**: ensure that Docker, GitHub Actions, and local running environment can access web report
**🐳 Docker MCP image support**
- Add independent MCP service image `wantcat/trendradar-mcp`
- Support Docker deployment of AI analysis function, provide service through HTTP interface (port 3333)
- Dual-container architecture: news push service and MCP service run independently, can be expanded and restarted separately
- See [Docker deployment - MCP service](#6-docker-部署)
**🌐 Web server support**
- Add built-in web server, support access to generated report through browser
- Control start/stop through `manage.py` command: `docker exec -it trendradar python manage.py start_webserver`
- Access address: `http://localhost:8080` (port configurable)
- Security features: static file service, directory restriction, local access
- Support automatic start and manual control two modes
**📖 Documentation optimization**
- Add [How to display push content?](#7-推送内容怎么显示) chapter: customize push style and content
- Add [When will I be pushed?](#8-什么时候给我推送) chapter: set push time period
- Add [How often to run?](#9-多久运行一次) chapter: set automatic running frequency
- Add [Push to multiple groups/devices](#10-推送到多个群设备) chapter: push to multiple receivers at the same time
- Optimize each configuration section: unified addition of "configuration location" description
- Simplify quick start configuration description: three core files at a glance
- Optimize [Docker deployment](#6-docker-部署) chapter: add image description, recommend git clone deployment, reorganize deployment method
**🔧 Upgrade instructions**:
- **GitHub Fork user**: update `main.py`, `config/config.yaml` (add multi-account push support, no need to modify existing configuration)
- **Multi-account push**: new feature, default not enabled, existing single-account configuration remains unaffected
### 2025/11/28 - mcp-v1.0.3
**MCP module update:**
- Add date parsing tool resolve_date_range, solve AI model date inconsistency problem
- Support natural language date expression parsing (this week, recent 7 days, last month, etc.)
- Tool total increased from 13 to 14
### 2025/11/28 - v3.4.1
**🔧 Format optimization**
1. **Bark push enhancement**
- Bark now supports Markdown rendering
- Enable native Markdown format: bold, link, list, code block, etc.
- Remove pure text conversion, fully utilize Bark's native rendering capability
2. **Slack format precise**
- Use dedicated mrkdwn format to process batch content
- Improve byte size estimation accuracy (avoid message exceeding limit)
- Optimize link format: `<url|text>` and bold syntax: `*text*`
3. **Performance improvement**
- Format conversion completed during batch processing, avoid secondary processing
- Accurately estimate message size, reduce send failure rate
**🔧 Upgrade instructions**:
- **GitHub Fork user**: update `main.py`, `config.yaml`
### 2025/11/25 - v3.4.0
**🎉 Newly Added Slack Push Support**
1. **Team Collaboration Push Channel**
- Supports Slack Incoming Webhooks (a popular team collaboration tool globally)
- Centralized message management, suitable for team-shared hot news
- Supports mrkdwn format (bold, links, etc.)
2. **Multiple Deployment Methods**
- GitHub Actions: Configure `SLACK_WEBHOOK_URL` Secret
- Docker: Environment variable `SLACK_WEBHOOK_URL`
- Local Run: `config/config.yaml` configuration file
> 📖 **Detailed Configuration Tutorial**: [Quick Start - Slack Push](#-quick-start)
- Optimized setup-windows.bat and setup-windows-en.bat for a smoother MCP installation experience
**🔧 Upgrade Instructions**:
- **GitHub Fork Users**: Update `main.py`, `config/config.yaml`, `.github/workflows/crawler.yml`
### 2025/11/24 - v3.3.0
**🎉 Newly Added Bark Push Support**
1. **iOS Exclusive Push Channel**
- Supports Bark push (based on APNs, iOS platform)
- Free, open-source, efficient, and ad-free
- Supports official servers and self-built servers
2. **Multiple Deployment Methods**
- GitHub Actions: Configure `BARK_URL` Secret
- Docker: Environment variable `BARK_URL`
- Local Run: `config/config.yaml` configuration file
> 📖 **Detailed Configuration Tutorial**: [Quick Start - Bark Push](#-quick-start)
**🐛 Bug Fixes**
- Fixed the issue where `ntfy_server_url` configuration in `config.yaml` did not take effect ([#345](https://github.com/sansan0/TrendRadar/issues/345))
**🔧 Upgrade Instructions**:
- **GitHub Fork Users**: Update `main.py`, `config/config.yaml`, `.github/workflows/crawler.yml`
### 2025/11/23 - v3.2.0
**🎯 Newly Added Advanced Customization Features**
1. **Keyword Sorting Priority Configuration**
- Supports two sorting strategies: heat priority vs. configuration order priority
- Meets different usage scenarios: hot spot tracking or personalized attention
2. **Precise Control over Display Quantity**
- Global configuration: uniformly limits the display quantity of all keywords
- Individual configuration: use `@number` syntax to set a limit for specific keywords
- Effectively controls push length and highlights key content
> 📖 **Detailed Configuration Tutorial**: [Keyword Configuration - Advanced Configuration](#keyword-advanced-configuration)
**🔧 Upgrade Instructions**:
- **GitHub Fork Users**: Update `main.py`, `config/config.yaml`
### 2025/11/18 - mcp-v1.0.2
**MCP Module Update:**
- Optimized the query for today's news to prevent incorrect returns of past dates
### 2025/11/22 - v3.1.1
- **Fixed Data Exception Leading to Crash**: Solved the `'float' object has no attribute 'lower'` error encountered by some users in the GitHub Actions environment
- Added a dual protection mechanism: filters invalid titles (None, float, empty string) at the data acquisition stage and adds type checks at function call sites
- Enhanced system stability to ensure normal operation even when data sources return abnormal formats
**Upgrade Instructions** (GitHub Fork Users):
- Must update: `main.py`
- Recommended to use minor version upgrade method: copy and replace the above files
### 2025/11/20 - v3.1.0
- **Newly Added Personal WeChat Push Support**: Enterprise WeChat applications can push to personal WeChat without installing the Enterprise WeChat APP
- Supports two message formats: `markdown` (Enterprise WeChat group robot) and `text` (personal WeChat application)
- Added `WEWORK_MSG_TYPE` environment variable configuration, supporting GitHub Actions, Docker, docker compose, and other deployment methods
- `text` mode automatically clears Markdown syntax, providing pure text push effects
- See the "Personal WeChat Push" configuration instructions in the Quick Start
**Upgrade Instructions** (GitHub Fork Users):
- Must update: `main.py`, `config/config.yaml`
- Optional update: `.github/workflows/crawler.yml` (if using GitHub Actions deployment)
- Recommended to use minor version upgrade method: copy and replace the above files
### 2025/11/12 - v3.0.5
- Fixed email sending SSL/TLS port configuration logic error
- Optimized email service providers (QQ/163/126) to use port 465 (SSL) by default
- **Added Docker Environment Variable Support**: core configuration items (`enable_crawler`, `report_mode`, `push_window`, etc.) support overriding through environment variables, solving the issue of NAS users' configuration file modifications not taking effect (see [🐳 Docker Deployment](#-docker-deployment) chapter)
### 2025/10/26 - mcp-v1.0.1
**MCP Module Update:**
- Fixed date query parameter passing error
- Unified time parameter format for all tools
### 2025/10/31 - v3.0.4
- Solved the error caused by Feishu pushing content that was too long, implementing batch pushing
### 2025/10/23 - v3.0.3
- Expanded ntfy error message display range
### 2025/10/21 - v3.0.2
- Fixed ntfy push encoding issue
### 2025/10/20 - v3.0.0
**Major Update - AI Analysis Function Launched** ✨
- **Core Features**:
- Added AI analysis server based on MCP (Model Context Protocol)
- Supports 17 intelligent analysis tools: basic query, intelligent retrieval, advanced analysis, RSS query, system management
- Natural language interaction: query and analyze news data through dialogue
- Multi-client support: Claude Desktop, Cherry Studio, Cursor, Cline, etc.
- **Analysis Capabilities**:
- Topic trend analysis (heat tracking, life cycle, hot spot detection, trend prediction)
- Data insights (platform comparison, activity statistics, keyword co-occurrence)
- Sentiment analysis, similar news lookup, intelligent summary generation
- Historical related news retrieval, multi-mode search
- **Update Tips**:
- This is an independent AI analysis function, not affecting existing push functions
- Can be used selectively, no need to upgrade existing deployments
### 2025/10/15 - v2.4.4
- **Update Content**:
- Fixed ntfy push encoding issue + 1
- Fixed push time window judgment problem
- **Update Tips**:
- Recommended to use 【minor version upgrade】
### 2025/10/10 - v2.4.3
> Thanks to [nidaye996](https://github.com/sansan0/TrendRadar/issues/98) for discovering experience issues
- **Update Content**:
- Refactored "silent push mode" to "push time window control", enhancing functional understanding
- Clarified push time window as an optional additional feature, can be used with three push modes
- Improved comments and documentation descriptions for clearer functional positioning
- **Update Tips**:
- This is just a refactoring, no need to upgrade
### 2025/10/8 - v2.4.2
- **Update Content**:
- Fixed ntfy push encoding issue
- Fixed configuration file missing issue
- Optimized ntfy push effect
- Added GitHub page image segment export function
- **Update Tips**:
- Recommended to use 【major version update】
### 2025/10/2 - v2.4.0
**Added Ntfy Push Notification**
- **Core Features**:
- Supports ntfy.sh public service and self-hosted server
- **Usage Scenarios**:
- Suitable for users pursuing privacy (supports self-hosting)
- Cross-platform push (iOS, Android, Desktop, Web)
- No need to register an account (public server)
- Open-source and free (MIT protocol)
- **Update Tips**:
- Recommended to use 【major version update】
### 2025/09/26 - v2.3.2
- Corrected email notification configuration check being missed ([#88](https://github.com/sansan0/TrendRadar/issues/88))
**Fix Description**:
- Solved the issue where even with correct email notification configuration, the system still prompts "no webhook configured"
### 2025/09/22 - v2.3.1
- **Added Email Push Function**, supports sending hot news reports to email
- **Intelligent SMTP Identification**: automatically identifies 10+ email service providers' configurations, including Gmail, QQ Email, Outlook, and more
- **HTML Format**: email content uses the same HTML format as the web version, beautifully formatted and mobile-friendly
- **Batch Sending Support**: supports multiple recipients, separated by commas, for simultaneous sending to multiple people
- **Custom SMTP**: allows custom SMTP server and port configuration
- Fixed Docker build network connection issue
**Usage Instructions**:
- Applicable scenarios: suitable for users needing email archiving, team sharing, and timed reports
- Supported email services: Gmail, QQ Email, Outlook/Hotmail, 163/126 Email, Sina Email, Sohu Email, etc.
**Update Tips**:
- This update includes significant changes; for a smooth upgrade, use 【major version update】
### 2025/09/17 - v2.2.0
- Added one-click save news image function, making it easy to share concerned hotspots
**Usage Instructions**:
- Applicable scenarios: when you enable the web version functionality (GitHub Pages)
- Usage method: open the webpage link on a mobile or computer, click the "Save as Image" button at the top of the page
- Actual effect: the system automatically creates a beautiful image of the current news report, saving it to your mobile photo album or computer desktop
- Sharing convenience: you can directly share the image with friends, post it on your moments, or share it to your work group, allowing others to see the important information you've discovered
### 2025/09/13 - v2.1.2
- Solved the DingTalk push capacity limit causing news push failure (adopted batch pushing)
### 2025/09/04 - v2.1.1
- Fixed Docker running issue on certain architectures
- Officially released the official Docker image wantcat/trendradar, supporting multiple architectures
- Optimized Docker deployment process, no need for local build for quick usage
### 2025/08/30 - v2.1.0
**Core Improvements**:
- **Push Logic Optimization**: changed from "pushing every execution" to "controllable pushing within a time window"
- **Time Window Control**: allows setting push time range, avoiding disturbances during non-working hours
- **Push Frequency Options**: supports single or multiple pushes within a time segment
**Update Tips**:
- This feature is disabled by default; needs manual enabling in config.yaml
- Upgrade requires updating main.py and config.yaml simultaneously
### 2025/08/27 - v2.0.4
- This version is not for fixing issues but for an important reminder
- Please properly keep webhooks secure, do not expose them publicly
- If you deployed this project on GitHub using fork, fill webhooks in GitHub Secret, not in config.yaml
- If you have exposed webhooks or filled them in config.yaml, consider deleting and regenerating
### 2025/08/06 - v2.0.3
- Optimized GitHub page web version effect for better mobile usage
### 2025/07/28 - v2.0.2
- Code refactoring
- Solved the issue of version number easily being missed during modification
### 2025/07/27 - v2.0.1
**Fixed Issues**:
1. Docker shell script execution exception due to CRLF line endings
2. Logic issue when frequency_words.txt is empty, causing news sending to be empty
- Fixed: when frequency_words.txt is empty, it will **push all news**, but limited by message push size restrictions, consider adjustments:
- Solution 1: disable mobile push, choose GitHub Pages deployment (best for obtaining complete information, reordering hotspots by **custom search algorithm**)
- Solution 2: reduce push platforms, prioritize **WeChat** or **Telegram**, which have batch push functions (due to limited push capacity, batch pushing affects experience, but ensures complete information)
- Solution 3: combine with Solution 2, mode selection current or incremental can effectively reduce one-time push content
### 2025/07/17 - v2.0.0
**Major Refactor**:
- Configuration management refactor: all configurations now managed through `config/config.yaml` file (main.py not split for ease of copying and upgrading)
- Runtime mode upgrade: supports three modes - `daily` (daily summary), `current` (current rankings), `incremental` (incremental monitoring)
- Docker support: complete Docker deployment scheme, supporting containerized operation
**Configuration File Description**:
- `config/config.yaml` - main configuration file (application settings, crawler configuration, notification configuration, platform configuration, etc.)
- `config/frequency_words.txt` - keyword configuration (monitoring vocabulary settings)
### 2025/07/09 - v1.4.1
**New Feature**: added incremental push (configured with FOCUS_NEW_ONLY at the beginning of main.py), focusing on new topics rather than sustained heat, only sending notifications when new content is available.
**Fixed Issues**: occasional formatting anomalies due to special symbols in news content.
### 2025/06/23 - v1.3.0
WeChat and Telegram push message have length limits, so I implemented splitting and pushing. See documentation for [WeChat](https://developer.work.weixin.qq.com/document/path/91770) and [Telegram](https://core.telegram.org/bots/api)
### 2025/06/21 - v1.2.1
Before this version, old versions not only required main.py to be copied and replaced, but crawler.yml also needed to be copied and replaced
https://github.com/sansan0/TrendRadar/blob/master/.github/workflows/crawler.yml
### 2025/06/19 - v1.2.0
> Thanks to claude research for organizing platform APIs, allowing quick completion of platform adaptations (though code has more redundancy~
1. Supports Telegram, WeChat, and DingTalk push channels, supporting multi-channel configuration and simultaneous push
### 2025/06/18 - v1.1.0
> **200 stars⭐**, continue to help everyone~ Recent encouragement data from my public account shows many people have seen and shared recommendations; I see specific account encouragement data, many became angel wheel old powder (I play public account for over a year, though registered seven or eight years ago, haha, early to get on the car, late to get off)
1. Important update: added weights, news you see now are hottest and most concerned at the top
2. Updated documentation usage; recent updates include many features, and previous documentation was simple (see below ⚙️ frequency_words.txt complete tutorial)
### 2025/06/16 - v1.0.0
1. Added a new version update prompt for the project, default on; to turn off, change "FEISHU_SHOW_VERSION_UPDATE": True in main.py to False
### 2025/06/13+14
1. Removed compatibility code; previous fork students directly copying code will show exceptions on that day (will return to normal the next day)
2. feishu and html bottom add a new news display
### 2025/06/09
**100 stars⭐**, write a small function for everyone to help~
frequency_words.txt file added a 【must-have word】function using + sign
1. Must-have word syntax:
Tang Seng or Zhu Bajie must appear in the title together to be included in push news
```
+Tang Seng
+Zhu Bajie
```
2. Higher filter priority:
If the filter word matches Tang Seng chanting, even if the must-have word list includes Tang Seng, it will not be displayed
```
+Tang Seng
!Tang Seng Chanting
```
### 2025/06/02
1. **Webpage** and **Feishu messages** support direct mobile jump to detailed news
2. Optimized display effect + 1
### 2025/05/26
1. Feishu message display effect optimization
<table>
<tr>
<td align="center">
Before optimization<br>
<img src="_image/before.jpg" alt="Feishu message interface - before optimization" width="400"/>
</td>
<td align="center">
After optimization<br>
<img src="_image/after.jpg" alt="Feishu message interface - after optimization" width="400"/>
</td>
</tr>
</table>
</details>
<br>
## ✨ Core Function
### **Global Hotspot Aggregation**
- Zhihu
- Douyin
- Bilibili hot search
- Wall Street Journal
- Tieba
- Baidu hot search
- Cai Lian She Hot
- Pengpai News
- Phoenix.com
- Today’s Headlines
- Weibo
Default monitoring of 11 mainstream platforms; you can also add extra platforms
> 💡 Detailed configuration tutorial see [Configuration Details - Platform Configuration](#1-platform-configuration)
### **RSS Feed Support** (v4.5.0 added)
Supports RSS/Atom feed source capture, grouped by keywords (consistent with hot list format):
- **Unified format**: RSS and hot list use the same keyword matching and display format
- **Simple configuration**: directly add RSS source in `config.yaml`
- **Merge push**: hot list and RSS merged into one message push
- **Freshness filter**: automatically filter old articles exceeding specified days, avoid duplicate push. Supports global default days and single-source independent settings
> 💡 RSS uses the same `frequency_words.txt` for keyword filtering
### **Visual Configuration Editor**
Provides web-based graphical configuration interface, no need to manually edit YAML files, all configuration items can be modified and exported through the form.
👉 **Online Experience**: [https://sansan0.github.io/TrendRadar/](https://sansan0.github.io/TrendRadar/)
<img src="/_image/editor.png" alt="Visual configuration editor" width="80%">
### **Smart Push Strategy**
**Three Push Modes**:
| Mode | Applicable Scenario | Push Characteristics |
|------|---------|---------|
| **Daily Summary** (daily) | Enterprise Managers / Ordinary Users | Push all matching news of the day (including previously pushed) on time |
| **Current Hot List** (current) | Self-Media People / Content Creators | Push current hot list matching news on time (continuously on the list appear every time) |
| **Incremental Monitoring** (incremental) | Investors / Traders | Only push new content, zero repetition |
> 💡 **Quick Selection Guide:**
> - Don't want to see duplicate news → Use `incremental` (Incremental Monitoring)
> - Want to see the complete hot list trend → Use `current` (Current Hot List)
> - Need a daily summary report → Use `daily` (Daily Summary)
>
> See detailed comparison and configuration tutorial in [Configuration Details - Push Mode Detailed Explanation](#3-push-mode-detailed-explanation)
**Additional Features** (optional):
| Feature | Description | Default |
|------|------|------|
| **Scheduling System** | Arrange from Monday to Sunday: assign different time periods, push modes, and AI analysis strategies for each day. **Each time period can independently set filtering methods (keywords/AI) and focus directions**, to see different types of news at different times. Built-in 5 presets (always_on / morning_evening / office_hours / night_owl / custom), also customizable. Support workday/weekend differentiation,跨午夜时段, per-period去重, time period conflict detection (v6.0.0 + v6.5.0) | morning_evening |
| **Content Order Configuration** | Adjust the display order of each area (hot list, new hot spots, RSS, independent display area, AI analysis) through `display.region_order`; control whether each area is displayed through `display.regions` (v5.2.0) | See configuration file |
| **Display Mode Switching** | `keyword`=grouped by keywords, `platform`=grouped by platform (added in v4.6.0) | keyword |
> 💡 See detailed configuration tutorial in [How is the push content displayed?](#7-how-is-the-push-content-displayed) and [When will I be pushed?](#8-when-will-i-be-pushed)
### **Precise Content Filtering**
Set personal keywords (e.g., AI, BYD, education policy), only push relevant hot spots, and filter out irrelevant information
> 💡 **Basic Configuration Tutorial**: [Keyword Configuration - Basic Syntax](#keyword-basic-syntax)
>
> 💡 **Advanced Configuration Tutorial**: [Keyword Configuration - Advanced Configuration](#keyword-advanced-configuration)
>
> 💡 You can also not filter and push all hot spots completely (leave `frequency_words.txt` empty)
### **AI Intelligent News Screening** (added in v6.5.0)
Use natural language to describe your interests, and AI automatically classify news, replacing traditional keyword matching
- **Natural Language Interest Description**: Write down your focus directions in `ai_interests.txt` in daily language, no need to learn keyword syntax
- **Two-Stage Intelligent Processing**: AI extracts structured tags from interest descriptions and then classifies news into tags and scores in batches
- **Score Threshold Control**: Precisely control the push quality through `ai_filter.min_score`, only push high relevance news
- **Automatic Fallback Guarantee**: Automatically fallback to keyword matching when AI screening fails, ensuring uninterrupted push
- **Intelligent Tag Update**: AI automatically evaluates the change amplitude when interests change and decides incremental or full reclassification
- **Flexible Switching**: `filter.method` supports `keyword` (default) and `ai` modes, Timeline can cover by time period
- **Personalized by Time Period**: Different time periods can use different keyword files or AI interest descriptions. For example, use "technology thesaurus" for quick filtering in the morning and switch to "financial interest" for AI deep screening in the evening
```yaml
# config.yaml quick enable example
filter:
method: ai # keyword (default) | ai
ai_filter:
min_score: 6 # minimum score threshold for push (1-10)
```
> 💡 AI screening and AI analysis/translation share model configuration, just configure `ai.api_key` once
### **Hot Spot Trend Analysis**
Track news heat changes in real-time, letting you not only know "what's on the hot search" but also understand "how hot spots evolve"
- **Time Axis Tracking**: Record the complete time span of each news from first appearance to last appearance
- **Heat Change**: Statistics of news ranking changes and appearance frequency in different time periods
- **New Detection**: Real-time identify new hot spots and mark with🆕 to remind at the first time
- **Sustainability Analysis**: Distinguish one-time hot spots and continuously fermented deep news
- **Cross-Platform Comparison**: Compare the ranking performance of the same news on different platforms and see the difference in media attention
> 💡 See push format description in [Message Style Description](#5-what-does-my-message-look-like)
### **Personalized Hot Spot Algorithm**
No longer be led by algorithms of various platforms, TrendRadar will reorganize the whole network's hot search
> 💡 Three ratios can be adjusted, see [Configuration Details - Hot Spot Weight Adjustment](#4-hot-spot-weight-adjustment)
### **Multi-Channel and Multi-Account Push**
Support **WeChat** (+ WeChat push solution), **Feishu**, **DingTalk**, **Telegram**, **Email**, **ntfy**, **Bark**, **Slack**, **Universal Webhook** (can connect to Discord, IFTTT, etc.), messages directly to mobile phones and email
> 💡 See detailed configuration tutorial in [Push to Multiple Groups/Devices](#10-push-to-multiple-groups-devices)
### **AI Multi-Language Translation** (added in v5.2.0)
Translate push content into any language, breaking language barriers, whether reading domestic hot spots or subscribing to overseas information through RSS
- **One-Click Translation**: Set `ai_translation.enabled: true` and target language in `config.yaml`
- **Multi-Language Support**: Support English, Korean, Japanese, French, and any other language
- **Intelligent Batch Processing**: Automatically batch translate to reduce API call times and save cost
- **Custom Style**: Customize translation style and terminology through `ai_translation_prompt.txt`
- **Shared Model Configuration**: Share model settings with AI analysis function using `ai` configuration section
```yaml
# config.yaml quick enable example
ai_translation:
enabled: true
language: "English" # target language
```
> 💡 Translation function and AI analysis function share model configuration, just configure `ai.api_key` once
**RSS Source Reference**: Here are some RSS subscription source collections that can be used as needed
- [awesome-tech-rss](https://github.com/tuan3w/awesome-tech-rss) - Technology, entrepreneurship, programming blogs, and media
- [awesome-rss-feeds](https://github.com/plenaryapp/awesome-rss-feeds) - Mainstream news media RSS collections from various countries
> ⚠️ Some overseas media content may involve sensitive topics, and AI models may refuse to translate. It is recommended to screen subscription sources according to actual needs
### **HTML Report Browser Enhancement** (added in v6.6.0)
Open the pushed HTML report in a browser and automatically unlock enhanced experience (email clients are not affected):
- **Wide-Screen Mode**: Desktop automatically switch to 1200px wide-screen layout, fully utilizing screen space
- **Tab Quick Switch**: Keyword grouping and independent display areas both support Tab navigation, goodbye to long page scrolling
- **Dark Mode**: One-click switch to dark theme, automatically remember preferences
- **Real-Time Search**: Press `/` to bring up the search box and filter news titles in real-time
- **One-Click Copy**: Hover over news serial number to copy title and link
- **Shortcut Keys**: `W` wide-screen, `D` dark, `/` search, `?` view all shortcut keys
> 💡 All enhanced functions are based on progressive enhancement, and email clients still display the original 600px layout, with zero regression
### **Flexible Storage Architecture** (major update in v4.0.0)
**Multi-Storage Backend Support**:
- **Remote Cloud Storage**: GitHub Actions environment default, support S3 compatible protocol (R2/OSS/COS, etc.), data stored in the cloud, not polluting the repository
- **Local SQLite Database**: Docker/local environment default, data completely controllable
- **Automatic Backend Selection**: Intelligent switch storage method according to running environment
> 💡 See detailed explanation in [Where is data stored?](#11-where-is-data-stored)
### **Multi-Endpoint Deployment**
- **GitHub Actions**: Timed automatic crawling + remote cloud storage (need to sign in for renewal)
- **Docker Deployment**: Support multi-architecture containerized operation, data local storage
- **Local Operation**: Windows/Mac/Linux direct operation
### **AI Analysis and Push** (added in v5.0.0)
Use AI large model to conduct in-depth analysis of push content, automatically generate hot spot insight reports
- **Intelligent Analysis**: Automatically analyze hot spot trends, keyword heat, cross-platform association, and potential impact
- **Multi-Provider**: Based on LiteLLM unified interface, support 100+ AI providers (DeepSeek, OpenAI, Gemini, Anthropic, local Ollama, etc.), also support backup model automatic switching
- **Independent Analysis Mode**: AI analysis range can be different from push - push only send new messages (avoid disturbance), but AI can analyze all news of the day (see complete trend)
- **Flexible Push**: Optional only original content, only AI analysis, or both
- **Custom Prompt Words**: Customize analysis angle through `config/ai_analysis_prompt.txt`
> 💡 See detailed configuration tutorial in [Let AI help me analyze hot spots](#12-let-ai-help-me-analyze-hot-spots)
### **Independent Display Area** (added in v5.0.0)
Provide complete hot list display for specified platforms, not affected by keyword filtering
- **Complete Hot List**: Complete display of hot list for specified platforms, suitable for users who want to see complete rankings
- **RSS Independent Display**: RSS source content can be completely displayed, not limited by keywords
- **AI Deep Analysis**: Can independently enable AI trend analysis for complete hot list, no need to display in push
- **Flexible Configuration**: Support configuration display platform, RSS source, maximum number of articles
> 💡 See detailed configuration tutorial in [How is the push content displayed? - Independent Display Area](#7-how-is-the-push-content-displayed)
### **AI Intelligent Analysis** (added in v3.0.0)
AI dialogue analysis system based on MCP (Model Context Protocol) protocol, letting you deeply dig news data with natural language
> **💡 Usage Tips**: AI function needs local news data support
> - Project comes with test data, can immediately experience function
> - It is recommended to deploy and run the project yourself to obtain more real-time data
>
> See [AI Intelligent Analysis](#-ai-intelligent-analysis)
### **Web Deployment**
Run and generate `index.html` in the root directory, which is a complete news report page
> **Deployment Method**: Click **Use this template** to create a repository and deploy to Cloudflare Pages or GitHub Pages and other static hosting platforms
>
> **💡 Tips**: Enable GitHub Pages to obtain online access address, go to repository Settings → Pages to enable. [Effect Preview](https://sansan0.github.io/TrendRadar/)
>
> ⚠️ Original GitHub Actions automatic storage function has been discontinued (this solution once caused GitHub server load too high, affecting platform stability)
### **Reduce APP Dependence**
From "being bound by algorithm recommendation" to "actively obtaining information you want"
**Suitable for**: Investors, self-media people, enterprise public relations, ordinary users concerned about current events
**Typical Scenarios**: Stock investment monitoring, brand public opinion tracking, industry dynamic attention, life information acquisition
| Web Effect (Email Push Effect) | Feishu Push Effect | AI Analysis Push Effect |
|:---:|:---:|:---:|
|  |  |  |
<br>
## 🚀 Quick Start
> **Reminder**: It is recommended to **[view the latest official documentation](https://github.com/sansan0/TrendRadar?tab=readme-ov-file)** to ensure configuration steps are the latest.
### Please select a deployment method suitable for you
#### 🅰️ Option 1: Docker Deployment (recommended 🔥)
* **Features**: More stable than GitHub Actions, data stored locally (no need to configure cloud storage)
* **Applicable**: Those with their own servers, NAS, or long-running computers
* **Note**: You need to read and understand the basic configuration process below, then jump to the Docker tutorial for deployment.
#### 🅱️ Option 2: GitHub Actions Deployment (this section ⬇️)
* **Features**: Serverless, data stored in **remote cloud storage** (recommended configuration)
* **Applicable**: Users without servers, using GitHub free resources
* **Note**: Need to configure cloud storage for a complete experience and regular sign-in for renewal
### 1️⃣ Step 1: Get Project Code
Click the green **[Use this template]** button in the top right corner of this repository → Select "Create a new repository".
> ⚠️ Reminder:
> - Subsequent documentation mentions "Fork" can be understood as "Use this template"
> - Using Fork may cause operation exceptions, see [Issue #606](https://github.com/sansan0/TrendRadar/issues/606)
<br>
### 2️⃣ Step 2: Set up GitHub Secrets
In your forked repository, go to `Settings` > `Secrets and variables` > `Actions` > `New repository secret`
**📌 Important Notes (please read carefully):**
- **One Name corresponds to one Secret**: For each configuration item, click the "New repository secret" button once and fill in a pair of "Name" and "Secret".
- **You won't see the value after saving**: For security reasons, when you re-edit after saving, you can only see the Name (name), but not the content of the Secret (value).
- **Do not create your own names**: The Name (name) of the Secret must **strictly use** the names listed below (such as `WEWORK_WEBHOOK_URL`, `FEISHU_WEBHOOK_URL`, etc.), and cannot be modified or created casually, otherwise the system will not be able to identify it.
- **Multiple platforms can be configured at the same time**: The system will send notifications to all configured platforms.
**Configuration Example:**
<img src="_image/secrets.png" alt="GitHub Secrets Configuration Example"/>
As shown in the figure above, each line is a configuration item:
- **Name**: Must use the fixed names listed in the expanded content below (such as `WEWORK_WEBHOOK_URL`).
- **Secret**: Fill in the actual content you obtained from the corresponding platform (such as Webhook address, Token, etc.).
<br>
<details>
<summary>👉 Click to expand: <strong>WeChat Work Robot</strong> (easiest and quickest configuration)</summary>
<br>
**GitHub Secret Configuration (⚠️ Name must be consistent):**
- **Name**: `WEWORK_WEBHOOK_URL` (please copy and paste this name, don't type it yourself)
- **Secret**: Your WeChat Work robot Webhook address
<br>
**Robot Setting Steps:**
#### Mobile Settings:
1. Open WeChat Work App → Enter the target internal group chat
2. Click the "…" button in the upper right corner → Select "Message Push"
3. Click "Add" → Enter "TrendRadar"
4. Copy the Webhook address, click Save, and copy the content to configure to the GitHub Secret above
#### PC Settings are similar
</details>
<details>
<summary>👉 Click to expand: <strong>Personal WeChat Push</strong> (based on WeChat Work application, push to personal WeChat)</summary>
<br>
> Since this solution is based on the plug-in mechanism of WeChat Work, the push style is plain text (without markdown format), but it can be directly pushed to personal WeChat without installing WeChat Work App.
**GitHub Secret Configuration (⚠️ Name must be consistent):**
- **Name**: `WEWORK_WEBHOOK_URL` (please copy and paste this name, don't type it yourself)
- **Secret**: Your WeChat Work application Webhook address
- **Name**: `WEWORK_MSG_TYPE` (please copy and paste this name, don't type it yourself)
- **Secret**: `text`
<br>
**Setting Steps:**
1. Complete the WeChat Work robot Webhook settings above
2. Add `WEWORK_MSG_TYPE` Secret, set the value to `text`
3. Follow the picture operation to associate personal WeChat
4. After configuration, the WeChat Work App on the mobile phone can be deleted
<img src="_image/wework.png" title="Personal WeChat Push Configuration"/>
**Note**:
- Use the same Webhook address as the WeChat Work robot
- The difference is the message format: `text` is plain text, `markdown` is rich text (default)
- The plain text format will automatically remove all markdown syntax (bold, link, etc.)
</details>
<details>
<summary>👉 Click to expand: <strong>Feishu Robot</strong> (message display is relatively friendly)</summary>
<br>
> **Note**: The original 'Feishu Robot Assistant (BotBuilder)' will be discontinued on June 30, 2026, please use the **group custom robot** method below. The existing BotBuilder webhook address will be invalid and need to be reconfigured.
If **AI analysis** is enabled, Feishu push may have a delay of several minutes (about 5% probability), which is speculated to be the platform's compliance audit for AI-generated content.
**GitHub Secret Configuration (⚠️ Name must be consistent):**
- **Name**: `FEISHU_WEBHOOK_URL` (please copy and paste this name, don't type it yourself)
- **Secret**: Your Feishu custom robot Webhook address (format: `https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxx`)
**Configuration Steps:**
1. Enter the target group, click the **More** button in the upper right corner of the group, and click **Settings**.

2. On the right **Settings** interface, click **Group Robot**.

3. On the **Group Robot** interface, click **Add Robot**.
4. In the **Add Robot** dialog box, find and click **Custom Robot**.

5. Set the custom robot's avatar, name (such as "TrendRadar Hotspot Monitoring"), and description, and click **Add**.

6. Get the custom robot's **webhook address**, and click **Complete**.
> ⚠️ Please keep this webhook address properly, do not publish it on GitHub, blogs, or other publicly accessible websites, to avoid address leakage and malicious calls to send spam messages.

7. Configure the copied Webhook address to `FEISHU_WEBHOOK_URL` in GitHub Secrets.
> 💡 After configuration, you can click the robot picture on the right side of the group name to enter the custom robot details page and manage configuration information.
>
> 📖 Official documentation: [Custom Robot Usage Guide](https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot)
</details>
<details>
<summary>👉 Click to expand: <strong>DingTalk Robot</strong></summary>
<br>
**GitHub Secret Configuration (⚠️ Name must be consistent):**
- **Name**: `DINGTALK_WEBHOOK_URL` (please copy and paste this name, don't type it yourself)
- **Secret**: Your DingTalk robot Webhook address
<br>
**Robot Setting Steps:**
1. **Create a robot (only PC side supports)**:
- Open DingTalk PC client, enter the target group chat
- Click the group settings icon (⚙️) → flip down to find "Robot" and click on it
- Select "Add Robot" → "Custom"
2. **Configure the robot**:
- Set the robot name
- **Security settings**:
- **Custom keywords**: Set "hotspot"
3. **Complete settings**:
- Check the service terms agreement → click "Complete"
- Copy the obtained Webhook URL
- Configure the URL to `DINGTALK_WEBHOOK_URL` in GitHub Secrets
**Note**: Mobile devices can only receive messages, not create new robots.
</details>
<details>
<summary>👉 Click to expand: <strong>Telegram Bot</strong></summary>
<br>
**GitHub Secret Configuration (⚠️ Name must be consistent):**
- **Name**: `TELEGRAM_BOT_TOKEN` (please copy and paste this name, don't type it yourself)
- **Secret**: Your Telegram Bot Token
- **Name**: `TELEGRAM_CHAT_ID` (please copy and paste this name, don't type it yourself)
- **Secret**: Your Telegram Chat ID
**Note**: Telegram needs to configure **two** Secrets, please click the "New repository secret" button twice to add them separately
<br>
**Robot Setting Steps:**
1. **Create a robot**:
- Search for `@BotFather` in Telegram (pay attention to case, with a blue badge, about 37849827 monthly users, which is the official one, some imitation official accounts to identify)
- Send `/newbot` command to create a new robot
- Set the robot name (must end with "bot", it is easy to encounter duplicate names, so you have to think of different names)
- Get the Bot Token (format like: `123456789:AAHfiqksKZ8WmR2zSjiQ7_v4TMAKdiHm9T0`)
2. **Get Chat ID**:
**Method 1: Get through official API**:
- Send a message to your robot
- Visit: `https://api.telegram.org/bot<your Bot Token>/getUpdates`
- Find the number in `"chat":{"id":number}` in the returned JSON
**Method 2: Use third-party tools**:
- Search for `@userinfobot` and send `/start`
- Get your user ID as Chat ID
3. **Configure to GitHub**:
- `TELEGRAM_BOT_TOKEN`: Fill in the Bot Token obtained in step 1
- `TELEGRAM_CHAT_ID`: Fill in the Chat ID obtained in step 2
</details>
<details>
<summary>👉 Click to expand: <strong>Email Push</strong> (support all mainstream email)</summary>
<br>
- Precautions: To prevent the email mass mailing function from being **abused**, the current mass mailing is that all recipients can see each other's email addresses.
- If you have not configured the email sending experience below, it is not recommended to try.
> ⚠️ **Important configuration dependency**: Email push requires HTML report files. Please ensure that `storage.formats.html` is set to `true` in `config/config.yaml`:
> ```yaml
> storage:
> formats:
> sqlite: true
> txt: false
> html: true # Must be enabled, otherwise email push will fail
> ```
> If set to `false`, email push will report an error: `Error: HTML file does not exist or is not provided: None`
<br>
**GitHub Secret Configuration (⚠️ Name must be consistent):**
- **Name**: `EMAIL_FROM` (please copy and paste this name, don't type it yourself)
- **Secret**: Sender email address
- **Name**: `EMAIL_PASSWORD` (please copy and paste this name, don't type it yourself)
- **Secret**: Email password or authorization code
- **Name**: `EMAIL_TO` (please copy and paste this name, don't type it yourself)
- **Secret**: Recipient email address (multiple recipients separated by English commas, can also be the same as EMAIL_FROM, send to yourself)
- **Name**: `EMAIL_SMTP_SERVER` (optional configuration, please copy and paste this name)
- **Secret**: SMTP server address (can be left blank, the system will automatically identify)
- **Name**: `EMAIL_SMTP_PORT` (optional configuration, please copy and paste this name)
- **Secret**: SMTP port (can be left blank, the system will automatically identify)
**Note**: Email push requires at least **3 required** Secrets (EMAIL_FROM, EMAIL_PASSWORD, EMAIL_TO), the last two are optional configurations
<br>
**Supported email service providers** (automatically identify SMTP configuration):
| Email Service Provider | Domain | SMTP Server | Port | Encryption method |
|-----------|------|------------|------|------------------|
| **Gmail** | gmail.com | smtp.gmail.com | 587 | TLS |
| **QQ Mail** | qq.com | smtp.qq.com | 465 | SSL |
| **Outlook** | outlook.com | smtp-mail.outlook.com | 587 | TLS |
| **Hotmail** | hotmail.com | smtp-mail.outlook.com | 587 | TLS |
| **Live** | live.com | smtp-mail.outlook.com | 587 | TLS |
| **163 Mail** | 163.com | smtp.163.com | 465 | SSL |
| **126 Mail** | 126.com | smtp.126.com | 465 | SSL |
| **Sina Mail** | sina.com | smtp.sina.com | 465 | SSL |
| **Sohu Mail** | sohu.com | smtp.sohu.com | 465 | SSL |
| **Tiany翼 Mail** | 189.cn | smtp.189.cn | 465 | SSL |
| **Aliyun Mail** | aliyun.com | smtp.aliyun.com | 465 | TLS |
| **Yandex Mail** | yandex.com | smtp.yandex.com | 465 | TLS |
| **iCloud Mail** | icloud.com | smtp.mail.me.com | 587 | SSL |
> **Automatic identification**: When using the above email, no need to manually configure `EMAIL_SMTP_SERVER` and `EMAIL_SMTP_PORT`, the system will automatically identify.
>
> **Feedback note**:
> - If you test other email successfully, welcome to open [Issues](https://github.com/sansan0/TrendRadar/issues) to inform, I will add it to the support list
> - If the above email configuration is incorrect or cannot be used, please open [Issues](https://github.com/sansan0/TrendRadar/issues) to feedback and help improve the project
>
> **Special thanks**:
> - Thanks to [@DYZYD](https://github.com/DYZYD) contribute Tiany翼 Mail (189.cn) configuration and complete self-issuing and receiving test ([#291](https://github.com/sansan0/TrendRadar/issues/291))
> - Thanks to [@longzhenren](https://github.com/longzhenren) contribute Aliyun Mail (aliyun.com) configuration and complete test ([#344](https://github.com/sansan0/TrendRadar/issues/344))
> - Thanks to [@ACANX](https://github.com/ACANX) contribute Yandex Mail (yandex.com) configuration and complete test ([#663](https://github.com/sansan0/TrendRadar/issues/663))
> - Thanks to [@Sleepy-Tianhao](https://github.com/Sleepy-Tianhao) contribute iCloud Mail (icloud.com) configuration and complete test ([#728](https://github.com/sansan0/TrendRadar/issues/728))
**Common email settings**:
#### QQ Mail:
1. Log in QQ Mail web version → Settings → Account
2. Enable POP3/SMTP service
3. Generate authorization code (16 letters)
4. `EMAIL_PASSWORD` fill in authorization code, not QQ password
#### Gmail:
1. Enable two-step verification
2. Generate application-specific password
3. `EMAIL_PASSWORD` fill in application-specific password
#### 163/126 Mail:
1. Log in web version → Settings → POP3/SMTP/IMAP
2. Enable SMTP service
3. Set client authorization code
4. `EMAIL_PASSWORD` fill in authorization code
<br>
**Advanced configuration**:
If automatic identification fails, you can manually configure SMTP:
- `EMAIL_SMTP_SERVER`: such as smtp.gmail.com
- `EMAIL_SMTP_PORT`: such as 587 (TLS) or 465 (SSL)
<br>
**If there are multiple recipients (note English commas separator)**:
- EMAIL_TO="user1@example.com,user2@example.com,user3@example.com"
</details>
<details>
<summary>👉 Click to expand: <strong>ntfy push</strong> (open source and free, support self-hosted)</summary>
<br>
**Two usage methods**:
### Method 1: Free use (recommended for novices) 🆓
**Features**:
- ✅ No need to register an account, use immediately
- ✅ 250 messages per day (enough for 90% users)
- ✅ Topic name is "password" (need to choose a name that is not easy to guess)
- ⚠️ Messages are not encrypted, not suitable for sensitive information, but suitable for our non-sensitive information of this project
**Quick start**:
1. **Download ntfy app**:
- Android: [Google Play](https://play.google.com/store/apps/details?id=io.heckel.ntfy) / [F-Droid](https://f-droid.org/en/packages/io.heckel.ntfy/)
- iOS: [App Store](https://apps.apple.com/us/app/ntfy/id1625396347)
- Desktop: Visit [ntfy.sh](https://ntfy.sh)
**Subscribe Topic** (choose a hard-to-guess name):
```
Suggested format: trendradar-{your initials}-{random number}
No Chinese characters allowed
✅ Good example: trendradar-zs-8492
❌ Bad example: news, alerts (too easy to guess)
```
3. **Configure GitHub Secret (⚠️ Name must match exactly)**:
- **Name**: `NTFY_TOPIC` (copy and paste this name)
- **Secret**: fill in the topic name you just subscribed
- **Name**: `NTFY_SERVER_URL` (optional, copy and paste this name)
- **Secret**: leave blank (default is ntfy.sh)
- **Name**: `NTFY_TOKEN` (optional, copy and paste this name)
- **Secret**: leave blank
**Note**: ntfy requires at least 1 required Secret (NTFY_TOPIC), the other two are optional
4. **Test**:
```bash
curl -d "Test message" ntfy.sh/your_topic_name
```
### Method 2: Self-Hosted (Complete Privacy Control) 🔒
**Suitable for**: Those with servers, pursuing complete privacy, and having strong technical skills
**Advantages**:
- ✅ Completely open-source (Apache 2.0 + GPLv2)
- ✅ Data completely under your control
- ✅ No limitations
- ✅ Zero cost
**One-click Docker deployment**:
```bash
docker run -d \
--name ntfy \
-p 80 \
-v /var/cache/ntfy:/var/cache/ntfy \
binwiederhier/ntfy \
--cache-file /var/cache/ntfy/cache.db ```
**Configure TrendRadar**:
```yaml
N_SERVER_URL: https://ntfy.yourdomain.com
NTFY_TOPIC: trendradar-alerts # Simple name available for self-hosted
NTFY_TOKEN: tk_your_token # Optional: enable access control
```
**Subscribe in the app**:
- Click "Use another server"
- Enter your server address
- Enter the topic name
- (Optional) Enter login credentials
---
**Frequently Asked Questions:**
<details>
<summary><strong>Q1: Is the free version sufficient?</strong></summary>
250 messages per day are enough for most users. With a 30-minute crawl interval, that's about 48 pushes per day, which is more than enough.
</details>
<details>
<summary><strong>Q2: Is the topic name really secure?</strong></summary>
If you choose a random, long enough name (like `trendradar-zs-8492-news`), brute-force attacks are almost impossible:
- ntfy has strict rate limiting (1 request per second)
- 64 character choices (A-Z, a-z, 0-9, _, -)
- 10-character random string has 64^10 possibilities (takes years to crack)
</details>
---
**Recommendations:**
| User type | Recommended solution | Reason |
|---------|---------|------|
| Ordinary users | Method 1 (free) | Simple and quick, sufficient |
| Technical users | Method 2 (self-hosted) | Complete control, no limitations |
| High-frequency users | Method 3 (paid) | Check the official website information |
**Related links:**
- [ntfy official documentation](https://tfy.sh/)
- [Self-hosted tutorial](https://docs.ntfy.sh/install/)
- [GitHub repository](https://github.com/binwiederhier/ntfy)
</details>
<details>
<summary>👉 Click to expand: <strong>Bark Push</strong> (iOS exclusive, simple and efficient)</summary>
<br>
**GitHub Secret configuration (⚠️ Name must match exactly)**:
- **Name**: `BARK_URL` (copy and paste this name)
Secret**: your Bark
<br>
**Bark introduction:**
Bark is a free and open-source push tool for iOS, characterized by simplicity, speed, and no adsUsage:**
### Method Use the official server (recommended for beginners) 1. **Download Bark App**:
- iOS: [App Store](https://apps.apple.com/app/bark-手机发推送/id1403753865)
2. push URL**:
- Open Bark App
- Copy the push URL displayed on the homepage (format like: `api.day.app/your_device_key`)
- Configure the URL to `BARK_URL` in GitHub Secrets
### Method 2: Self-hosted server (complete privacy control🔒
**Suitable for**: Those with servers, pursuing complete privacy, and having strong**One-click Docker ```bash
docker run -d \
bark-server \
-p 8080:808 finab/bark-server
```
**Configure TrendRadar**:
```yaml
ARK_URL: http-server-ip:8080_key
**Notes:**
- ✅ Bark uses APNs push, with a maximum message size of 4KB
- ✅ Supports automatic batching, no need to long messages
- ✅ Push format is plain text (automatically removes Markdown syntax)
- ⚠️ Only supports iOSRelated links:**
- [Bark official website](bark.day.app/)
-ark GitHub repositorygithub.com/Finark)
- [ Server self-hosted tutorial](https://github.com/Finb/bark-server)
</details>
<details>
<summary>👉 Click to expand: <strong>Slack Push</strong></summary>
<br>
**GitHub Secret configuration (⚠️ Name must match exactly)**:
- **Name**: `SLACKOK_URL` ( paste this name)
**: your Slack Incoming Webhook URL
<brSlack introduction:**
Slack is collaboration tool, and Webhooks can push messages to Slack channels.
**Setup Step 1: Create Slack App
1. Slack API page**:
- Open https://api.slack.com/apps?new_app=1
- If not logged in, log in to your Slack workspace
2. **Choose creation method**:
- Click **"From scratch"**
3. **Fill in app information**:
- **App Name**: fill in the app name (e.g., `TrendRadar` or `Hot News Monitor`)
- **Workspace**: select your workspace from the dropdown list
- Click **"Create App"**
### Step 2: Enable Incoming Webhooks
1. **Navigate to Incoming Webhooks**:
- Find and click **"Incoming Webhooks"** in the left menu
2. **Enable feature**:
- Find **"Activate Incoming Webhooks"** switch
- Toggle the switch from `OFF` to `ON`
- The page will refresh to display new configuration options
### Step 3: Generate Webhook URL. **Add new**:
- Scroll to the bottom of the page
- Click **"Add New Webhook to Workspace"**
**Select target channel**:
- An authorization page will
- Select the channel to receive messages from the dropdown list (e.g., `#hot-news`)
- If you want to select a private channel, you must the channel
3. **Authorize app**:
**"Allow"** to complete authorization
- The system will automatically jump back to the configuration page
### Step Copy and save Webhook URL
1. generated URL**:
- In the "Webhook URLs for Your Workspace" section
- You will see the generated Web
- Format like: `https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX`
2. **Copy URL**:
- Click the **"Copy"** button next to the URL
- Or manually select and copy the URL
3. **Configure to TrendRadar**:
- **GitHub Actions**: add URL to `SLACK_WEBHOOK_URL` in GitHub Secrets
- **Local testing**: fill in `slack_webhook_url` in `config/config.yaml`
**Docker deployment**: add URL to `SLACK_WEBHOOK_URL` variable in `docker/.env`
---
**Notes:**
- ✅ Supports Markdown format (automatically converted to Slack mrkdwn)
- ✅ Supports automatic batching (4KB per batch)
- ✅ Suitable for team collaboration, centralized message management
- ⚠️ Webhook URL contains secret key, do not expose
**Message format preview:**
```
*[Part 1/2]*
📊 *Hot word statistics*
🔥 *[1/3] AI ChatGPT* : 2 messages
1. [Baidu Hot Search] 🆕 ChatGPT-5 officially released]* - 09:1 time)
2. [Tout AI chip concept stocks surge]* - [08 ~ 10: (3 times)
links:**
-coming Webhooks](https://api/messaging/web- [Slack API app://api.sl/apps)
</details<summary> to <strong>Generic Webhook Push</ (supports Discord, Matrix, IFTTT, etc.)</summary>
<br>
Hub Secret configuration (⚠️ Name must match exactly- **Name**: `HOOK_URLcopy and paste this- **Secret**:hook URL
-**: `GENERIC_WEBHO (optional, paste this name)
Secret**: JSON template string, supports `{title}`}` placeholders
<br>
**Generic Webhook introduction Webhook supports any platform HTTP POST requests but not limited to:
- **Discord**: push to channels via Webhook
- **Matrix**: bridge push via
- **IF trigger automation processes
-hosted services**: services that support
**Configuration example configuration
1. **Get Webhook URL**:
- Go to Discord server settings → Integrations → Webhooks
- Create a new Webhook and copy the URL
2. **Configure template**:
```json
{"content": "{content}"}
```
3. **GitHub Secret configuration**:
- `GENERIC_WEBHOOK_URL`: Discord Webhook URL
- `GENERIC_WEBHOOK_TEMPLATE`: `{"content": "{content}"}`
### Custom template
The template supports two placeholders:
- `{title}` - message title
- `{content}` - message content
**Template example:**
```json
# Default format (leave blank)
{"title": "{title}", "content": "{content}"}
# Discord format
{"content": "{content}"}
# Custom format
{"text": "{content}", "username": "TrendRadar"}
```
---
**Notes:**
- ✅ Supports Markdown format (consistent with WeChat format)
- ✅ Supports automatic batching
- ✅ Supports multi-account configuration (use `;` to separate)
- ⚠️ Template must be valid JSON
- ⚠️ Different platforms have different requirements for message format, please refer to the target platform documentation
</details>
<br>
### Step 3: Manually test news push
> ⚠️ Reminder:
> - Complete steps 1-2, then test immediately! Test successfully before adjusting configurations (step 4)
> - Please enter your own project, not this one!
**How to find your Actions page**:
- **Method 1**: Open your forked project homepage, click the **Actions** tab at the top
- **Method 2**: Directly access `https://github.com/your_username/TrendRadar/actions`
**Example comparison**:
- ❌ Author's project: `https://github.com/sansanTrendRadar/actions`
- ✅ Your project: `github.com/yourTrendRadar/actions`
steps**:
1. project's Actions page
Find **"Get Hot** (must be these exact words), click and then click"Run workflow"** button on the right
If you don't see this, refer to [#109://github.com/s0/TrendRadar) to solve. Within 3 message will be pushed platform
<br>
> ⚠️ Reminder - Don't test too triggering GitHub
> - After workflow, refresh the browser page to see the new run record
<br>
### Step 4: Configuration instructions (optional)
Default configurations are already usable. If you need personalized adjustments, understand the following files:
| File | Function |
|------|------|
| `config/config.yaml` | Main configuration file: push mode, time window, platform list, hot word weight, etc. |
| `config/frequency_words.txt` | Keyword file: set concerned vocabulary, filter push content |
| `config/ai_analysis_prompt.txt` | AI prompt template: customize AI analyst role and analysis dimensions |
| `.github/workflows/crawler.yml` | Execution frequency: control how often to run (⚠️ modify with caution) |
👉 **Detailed configuration tutorial**: [Configuration explanation](#configuration-explanation)
<br>
### 5️⃣ Step 5: Remote Cloud Storage & Check-in Configuration
**v4.0.0 Important Change**: Introduced an 'activity detection' mechanism, GitHub Actions require periodic check-ins to maintain operation.
- **Operation Cycle**: Valid for **7 days**, services will automatically suspend after countdown.
- **Renewal Method**: Manually trigger "Check In" workflow on Actions page to reset 7-day validity.
- **Operation Path**: `Actions` → `Check In` → `Run workflow`
- **Design Philosophy**:
- If you forget to check in for 7 days, perhaps this information is not essential for you. Timely suspension helps you detach from the information flow and gives your brain a breather.
- GitHub Actions are valuable public computing resources. The check-in mechanism aims to avoid idle computing power and ensure resources are allocated to active and needed users. Thanks for your understanding and support.
---
**About Remote Cloud Storage Configuration (choose based on deployment method):**
- **GitHub Actions Users**:
- **Current Status**: Actions run in a new environment each time, no file saving. If cloud storage is not configured, the project will run in **lightweight mode** (no incremental push, no history tracking).
- **Recommendation**: Configure remote cloud storage for a complete experience.
- **Docker / Local Users**:
- **Current Status**: Data is saved on the local hard drive by default.
- **Recommendation**: Cloud storage is optional and can be used for off-site backup.
<details>
<summary>👉 Click to expand: <strong>Remote Cloud Storage Configuration Tutorial (using Cloudflare R2 as an example)</strong></summary>
<br>
**⚠️ Prerequisites (important):**
According to Cloudflare platform rules, enabling R2 requires binding a payment method.
* **Purpose**: Only for identity verification (Verify Only), **no charges incurred**.
* **Payment**: Supports dual-currency credit cards or PayPal in China.
* **Usage**: R2's free quota (10GB storage/month) is sufficient for daily operation, no need to worry about payment.
---
**GitHub Secret Configuration (need to add 4 items):**
| Name(Name) | Secret(value)description |
|-------------|-----------------|
| `S3_BUCKET_NAME` | Bucket name (e.g., `trendradar-data`) |
| `S3_ACCESS_KEY_ID` | Access key ID (Access Key ID) |
| `S3_SECRET_ACCESS_KEY` | Access key (Secret Access Key) |
| `S3_ENDPOINT_URL` | S3 API endpoint (e.g., R2: `https://<account-id>.r2.cloudflarestorage.com`) |
**Optional Configuration:**
| Name(Name) | Secret(value)description |
|-------------|-----------------|
| `S3_REGION` | Region (default `auto`, some service providers may require specification) |
> 💡 **More storage configuration options**: See [Where is the data saved?](#11-数据保存在哪里)
<br>
**Detailed operation steps (obtaining credentials):**
1. **Enter R2 Overview**:
- Log in to [Cloudflare Dashboard](https://dash.cloudflare.com/).
- Find and click `R2 object storage` in the left sidebar.
2. **Create a bucket**:
- Click `Overview`.
- Click `Create bucket` in the top right corner.
- Enter a name (e.g., `trendradar-data`) and click `Create bucket`.
3. **Create an API token**:
- Go back to the **Overview** page.
- Click `Manage` in the bottom right corner to find and click `Manage R2 API Tokens`.
- You will see `S3 API`: `https://<account-id>.r2.cloudflarestorage.com` (this is S3_ENDPOINT_URL).
- Click `Create Account API token`.
- **⚠️ Key settings**:
- **Token name**: Fill in as needed (e.g., `github-action-write`).
- **Permissions**: Choose `Admin Read & Write`.
- **Specify bucket**: For security, select `For specified buckets only` and choose your bucket (e.g., `trendradar-data`).
- Click `Create API token`, **immediately copy** the displayed `Access Key ID` and `Secret Access Key` (only shown once!).
</details>
<br>
### 6️⃣ Step 6: Enable AI Analysis Push
This is a core feature of v5.0.0, allowing AI to summarize and analyze news for you, recommended for trying.
**Configuration method:**
Add to GitHub Secrets (or `.env` / `config.yaml`):
- `AI_API_KEY`: Your API Key (supports DeepSeek, OpenAI, etc.)
- `AI_PROVIDER`: Service provider name (e.g., `deepseek`, `openai`)
That's it, no complex deployment needed; you'll see intelligent analysis reports on the next push.
<br>
### 7️⃣ Step 7: 🎉 Deployment Successful!
Congratulations! You can now start enjoying the efficient information flow brought by TrendRadar.
💬 **Join the community**: Welcome to follow the official account "**[硅基茶水间](#-支持项目)**" and share your usage experience and advanced gameplay.
<br>
### 8️⃣ Step 8: Advanced: Choose Your AI Assistant
TrendRadar provides two AI usage methods to meet different needs:
| Feature | ✨ AI Analysis Push | 🧠 AI Intelligent Analysis |
| :--- | :--- | :--- |
| **Mode** | **Passive reception** (daily report) | **Active dialogue** (in-depth research) |
| **Scenario** | "What's happening today?" | "Analyze AI industry changes over the past week" |
| **Deployment** | Simple (fill in Key) | Advanced (require local operation/Docker) |
| **Client** | Mobile | Computer |
👉 **Conclusion**: Start with **AI Analysis Push** for daily needs; if you're a data analyst or need in-depth mining, try **[AI Intelligent Analysis](#-ai-智能分析)**.
<br>
<a name="配置详解"></a>
## ⚙️ Configuration Details
> **📖 Reminder**: This section provides detailed configuration instructions, recommended to complete the [Quick Start](#-快速开始) basic configuration and then review detailed options as needed.
### 1. Which platforms do I want to watch?
<details id="自定义监控平台">
<summary>👉 Click to expand: <strong>Select information sources</strong></summary>
<br>
**Configuration location:** `config/config.yaml` `platforms` section
This project's data sources come from [newsnow](https://github.com/ourongxing/newsnow). You can click on the [website](https://newsnow.busiyi.world/), click [More], and see if there are any platforms you want.
Specific additions can be accessed by visiting [project source code](https://github.com/ourongxing/newsnow/tree/main/server/sources), according to the file names inside, modify the `platforms` configuration in `config/config.yaml`:
```yaml
platforms:
enabled: true # Whether to enable hot list platform crawling
sources:
- id: "toutiao"
name: "Toutiao"
- id: "baidu"
name: "Baidu Hot Search"
- id: "wallstreetcn-hot"
name: "Wall Street Insights"
# Add more platforms...
```
> 💡 **Shortcut**: If you can't read the source code, you can copy others' organized [platform configuration summary](https://github.com/sansan0/TrendRadar/issues/95)
> ⚠️ **Note**: It's not that the more platforms, the better. Too many platforms can lead to information overload and reduce user experience.
</details>
### 2. What content am I concerned about?
Tell the robot what you want to see in the `frequency_words.txt` file, and it will help you monitor it. Supports ordinary words, must words, filter words, and other gameplay.
| Syntax type | Symbol | Effect | Example | Matching logic |
|---------|------|------|------|---------|
| **Ordinary words** | None | Basic matching | `Huawei` | Contains any one |
| **Must words** | `+` | Limited scope | `+Mobile` | Must contain simultaneously |
| **Filter words** | `!` | Exclude interference | `!Advertisement` | Contains then directly exclude |
| **Quantity limit** | `@` | Control display quantity | `@10` | Display at most 10 news (added in v3.2.0) |
| **Global filter** | `[GLOBAL_FILTER]` | Global exclusion of specified content | See below | Filter in any case (added in v3.5.0) |
| **Regular expression** | `/pattern/` | Precise matching mode | `/\bai\b/` | Use regular expression matching (added in v4.7.0) |
| **Display name** | `=> Remark` | Custom display text | `/\bai\b/ => AI related` | Push and HTML display remark name (added in v4.7.0) |
#### 2.1 Basic syntax
<a name="关键词基础语法"></a>
<details>
<summary>👉 Click to expand: <strong>Basic syntax tutorial</strong></summary>
<br>
**Configuration location:** `config/frequency_words.txt`
##### 1. **Ordinary keywords** - Basic matching
```txt
Huawei
OPPO
Apple
```
**Effect:** News titles containing any of these words will be captured
##### 2. **Must words** `+Vocabulary` - Limited scope
```txt
Huawei
OPPO
+Mobile
```
**Effect:** Must contain both ordinary words and must words to be captured
##### 3. **Filter words** `!Vocabulary` - Exclude interference
```txt
Apple
Huawei
!Fruit
!Price
```
**Effect:** News containing filter words will be **directly excluded**, even if containing keywords
##### 4. **Quantity limit** `@Number` - Control display quantity (added in v3.2.0)
```txt
Tesla
Musk
@5
```
**Effect:** Limit the maximum number of news articles displayed for the keyword group
**Configuration priority:** `@Number` > Global configuration > Not limited
##### 5. **Global filter** `[GLOBAL_FILTER]` - Global exclusion of specified content (added in v3.5.0)
```txt
[GLOBAL_FILTER]
Advertisement
Promotion
Marketing
Shocking
Title party
[WORD_GROUPS]
Technology
AI
Huawei
Hongmeng
!Car
```
**Effect:** Filter news containing specified words in any case, **highest priority**
**Usage scenarios:**
- Filter low-quality content: Shocking, title party, exposure, etc.
- Filter marketing content: Advertisement, promotion, sponsorship, etc.
- Filter specific topics: Entertainment, gossip (according to needs)
**Filter priority:** Global filter > Word group filter (`!`) > Word group matching
**Area description:**
- `[GLOBAL_FILTER]`: Global filter area, containing words will be filtered in any case
- `[WORD_GROUPS]`: Word group area, maintaining existing syntax (`!`, `+`, `@`)
- If no area is marked, defaults to word group processing (backward compatible)
**Matching example:**
```txt
[GLOBAL_FILTER]
Advertisement
[WORD_GROUPS]
Technology
AI
```
- ❌ "Advertisement: Latest technology product launch" ← Contains global filter word "Advertisement", directly rejected
- ✅ "Technology company releases AI new product" ← Does not contain global filter word, matches "Technology" word group
- ✅ "AI technology breakthrough attracts attention" ← Does not contain global filter word, matches "Technology" word group
**Notes:**
- Global filter words should be used cautiously to avoid excessive filtering leading to omission of valuable content
- It is recommended to control global filter words within 5-15
- For filtering specific words, prioritize using word group filter words (`!` prefix)
##### 6. **Regular expression** `/pattern/` - Precise matching mode (added in v4.7.0)
Ordinary keywords use substring matching, which is convenient in a Chinese environment but may cause mis-matching in an English environment. For example, `ai` will match `training` in `ai`.
Using regular expression syntax `/pattern/` can achieve precise matching:
```txt
/(?<![a-z])ai(?![a-z])/
Artificial intelligence
Machine learning
```
**Effect:** Use regular expressions for matching, supporting all Python regular syntax
**Common regular patterns:**
| Demand | Regular writing | Description |
|------|---------|------|
| English word boundary | `/\bword\b/` | Match independent words, e.g., `/\bai\b/` matches "AI" but not "training" |
| Non-letter before and after | `/(?<![a-z])ai(?![a-z])/` | Looser boundary, suitable for mixed Chinese and English scenarios |
| Start matching | `/^breaking/` | Only match titles starting with "breaking" |
| End matching | `/发布$/` | Only match titles ending with "" |
| Multi-select | `/苹果\|华为\|小米/` | Match any one (note escape `\|`) |
**Matching example:**
```txt
# Configuration
/(?<![a-z])ai(?![a-z])/
Artificial intelligence
```
- ✅ "AI is the future" ← Matches independent "AI"
- ✅ "" ← Matches "ai" with Chinese characters before and after
- ✅ "Artificial intelligence development is rapid" ← Matches "artificial intelligence"
- ❌ "Resistance training is important" ← "ai" in "training" does not match
- ❌ "The maid cleaned the room" ← "ai" in "maid" does not match
**Combination use:**
```txt
# Regular + ordinary words + filter words
/\bai\b/
Artificial intelligence
Machine learning
!Advertisement
```
**Notes:**
- Regular expressions automatically enable case-insensitive matching (`re.IGNORECASE`)
- Supports `/pattern/i` and other JavaScript style writing (flags will be ignored because case-insensitive is enabled by default)
- Invalid regular syntax will be treated as ordinary words
- Regular can be used for ordinary words, must words (`+`), filter words (`!`)
**💡 Can't write regular expressions? Let AI help you generate!**
If you're not familiar with regular expressions, you can directly let ChatGPT / Gemini / DeepSeek help you generate. Just tell AI:
> I need a Python regular expression to match the English word "ai" but not "ai" in "training".
> Please directly provide the regular expression in the format `/pattern/`, no need for additional explanation.
AI will give you a result like: `/(?<![a-zA-Z])ai(?![a-zA-Z])/`
##### 7. **Display name** `=> Remark` - Custom display text (added in v4.7.0)
Regular expressions in push messages and HTML pages may not be friendly. Use the `=> Remark` syntax to set the display name:
```txt
/(?<![a-zA-Z])ai(?![a-zA-Z])/ => AI related
Artificial intelligence
```
**Effect:** Push messages and HTML pages display "AI related" instead of complex regular expressions
**Syntax format:**
```txt
# Regular + display name
/pattern/ => Display name
/pattern/i => Display name # Supports flags writing (flags are ignored)
/pattern/=>Display name # => Spaces on both sides are optional
# Ordinary words + display name
deepseek => DeepSeek dynamics
```
**Matching example:**
```txt
# Configuration
/(?<![a-zA-Z])ai(?![a-zA-Z])/ => AI related
Artificial intelligence
```
| Original configuration | Push/HTML display |
|---------|---------------|
| `/(?<![a-z])ai(?![a-z])/` + `Artificial intelligence` | `(?<![a-z])ai(?![a-z]) Artificial intelligence` |
| `/(?<![a-z])ai(?![a-z])/ => AI related` + `Artificial intelligence` | **`AI related`** |
**Notes:**
- Display name only needs to be written on the first word of the group
- If multiple words in a group have display names, use the first one
- If no display name is set, automatically use all words in the group to concatenate
---
#### 🔗 Word group function - Important role of empty lines
**Core rules:** Use **empty lines** to separate different word groups, each group independently counts
##### Example configuration:
```txt
iPhone
Huawei
OPPO
+Release
A-share
Shanghai stock exchange
Shenzhen stock exchange
+Rise and fall
!Prediction
World Cup
European Cup
Asian Cup
+Match
```
##### Word group explanation and matching effect:
**Group 1 - Mobile new product category:**
- Keywords: iPhone, Huawei, OPPO
- Must words: Release
- Effect: Must contain mobile brand name and "Release"
**Matching example:**
- ✅ "iPhone 15 officially released price announced" ← Has "iPhone" + "Release"
- ✅ "Huawei Mate60 series release live" ← Has "Huawei" + "Release"
- ✅ "OPPO Find X7 release time confirmed" ← Has "OPPO" + "Release"
- ❌ "iPhone sales hit a new high" ← Has "iPhone" but lacks "Release"
**Group 2 - Stock market trend category:**
- Keywords: A-share, Shanghai stock exchange, Shenzhen stock exchange
- Must words: Rise and fall
- Filter words: Prediction
- Effect: Focus on real-time market trends, excluding predictions
**Matching example:**
- ✅ "A-share rose sharply today" ← Has "A-share" + "Rise and fall"
- ✅ "Shanghai stock exchange hit a new high" ← Has "Shanghai stock exchange" + "Rise and fall"
- ❌ "Expert predicts A-share trend" ← Has "A-share" + "Rise and fall" but contains "Prediction"
**Group 3 - Football event category:**
- Keywords: World Cup, European Cup, Asian Cup
- Must words: Match
- Effect: Focus on match-related news
---
#### 📝 Configuration tips
##### 1. **From loose to strict**
```txt
# Step 1: Test with loose keywords
Artificial intelligence
AI
ChatGPT
# Step 2: Add must words to limit scope after finding mismatches
Artificial intelligence
AI
ChatGPT
+Technology
# Step 3: Add filter words to exclude interference after finding interference
Artificial intelligence
AI
ChatGPT
+Technology
!Advertisement
!Training
```
##### 2. **Avoid excessive complexity**
❌ **Not recommended:** A word group contains too many words
```txt
Huawei
OPPO
Apple
Samsung
Vivo
OnePlus
魅族
+Mobile
+Release
+Sales
!Fake
!Repair
!Second-hand
```
✅ **Recommended:** Split into multiple precise word groups
```txt
Huawei
OPPO
+New product
Apple
Samsung
+Release
Mobile
Sales
+Market
```
</details>
#### 2.2 Advanced configuration (added in v3.2.0)
<a name="关键词高级配置"></a>
<details>
<summary>👉 Click to expand: <strong>Advanced configuration tutorial</strong></summary>
<br>
</details>
# Tool List
##### Keyword Sorting Priority
**Configuration Location:** `config/config.yaml`
```yaml
report:
sort_by_position_first: false # Sorting priority configuration
```
| Configuration Value | Sorting Rule | Applicable Scenario |
|--------|---------|---------|
| `false` (Default) | Hotspot count ↓ → Configuration position ↑ | Focus on heat trend |
| `true` | Configuration position ↑ → Hotspot count ↓ | Focus on personal priority |
**Example:** Configuration order A, B, C, hotspot count A (3), B (10), C (5)
- `false`: B (10) → C (5) → A (3)
- `true`: A (3) → B (10) → C (5)
##### Global Display Quantity Limit
```yaml
report:
max_news_per_keyword: 10 # Maximum 10 news per keyword (0 = no limit)
```
**Docker Environment Variables:**
```bash
SORT_BY_POSITION_FIRST=true
MAX_NEWS_PER_KEYWORD=10
```
**Comprehensive Example:**
```yaml
# config.yaml
report:
sort_by_position_first: true # Prioritize by configuration order
max_news_per_keyword: 10 # Global default 10 news per keyword
```
```txt
# frequency_words.txt
Tesla
Musk
@20 # High priority, display 20 news (override global config)
Huawei # Use global config, display 10 news
BYD
@5 # Limit to 5 news
```
**Final Effect:** Display by configuration order: Tesla (20) → Huawei (10) → BYD (5)
</details>
### 3. Which Push Mode to Choose?
<details>
<summary>👉 Click to expand: <strong>Detailed comparison of three push modes</strong></summary>
<br>
**Configuration Location:** `config/config.yaml` under `report.mode`
```yaml
report:
mode: "daily" # Options: "daily" | "incremental" | "current"
```
#### Detailed Comparison Table
| Mode | Applicable Users | Push Timing | Display Content | Typical Use Case |
|------|----------|----------|----------|------------|
| **Daily Summary**<br/>`daily` | 📋 Enterprise managers / ordinary users | Push at regular intervals (default hourly) | All matching news for the day<br/>+ New news area | **Example**: Check all important news for the day at 6 PM<br/>**Characteristics**: See the complete trend for the day, without missing any hotspots<br/>**Reminder**: Includes previously pushed news |
| **Current Rankings**<br/>`current` | 📰 Self-media / content creators | Push at regular intervals (default hourly) | Current rankings matching news<br/>+ New news area | **Example**: Track "what topics are trending now"<br/>**Characteristics**: Understand current heat ranking changes in real-time<br/>**Reminder**: News that consistently ranks will appear multiple times |
| **Incremental Monitoring**<br/>`incremental` | 📈 Investors / traders | Push only with new additions | New matching frequency word news | **Example**: Monitor "Tesla", only notify with new messages<br/>**Characteristics**: Zero repetition, only see first-time appearing news<br/>**Suitable for**: High-frequency monitoring, avoiding information disturbance |
#### Actual Push Effects Example
Assuming you monitor the keyword "Apple", executed hourly:
| Time | `daily` Mode Push | `current` Mode Push | `incremental` Mode Push |
|-----|--------------|----------------|-------------------|
| 10:00 | News A, News B | News A, News B | News A, News B |
| 11:00 | News A, News B, News C | News B, News C, News D | **Only** News C |
| 12:00 | News A, News B, News C | News C, News D, News E | **Only** News D, News E |
**Description**:
- `daily`: Accumulate and display all news for the day (A, B, C are retained)
- `current`: Display current rankings news (ranking changes, News D ranks, News A drops)
- `incremental`: **Only push newly appeared news** (avoid repetitive disturbance)
#### Frequently Asked Questions
> **💡 Encountering this issue?** 👉 "Executed once every hour, the news output at the first execution still appears in the next hour"
> - **Cause**: You might have chosen `daily` (daily summary) or `current` (current rankings) mode
> - **Solution**: Switch to `incremental` (incremental monitoring) mode, only push new content
#### ⚠️ Important Note for Incremental Mode
> **Users who chose `incremental` (incremental monitoring) mode, please note:**
>
> 📌 **Incremental mode only pushes when new matching news is added**
>
> **If you haven't received a push for a long time, it might be because:**
> 1. No new hotspots appeared for your keywords during the current period
> 2. Keyword configuration is too strict or too broad
> 3. Monitored platform quantity is relatively small
>
> **Solutions:**
> - Solution 1: 👉 [Optimize keyword configuration](#2-keyword-configuration) - Adjust keyword precision, add or modify monitoring words
> - Solution 2: Switch push mode - Use `current` or `daily` mode, can receive pushes regularly
> - Solution 3: 👉 [Increase monitored platforms](#1-platform-configuration) - Add more news platforms, expand information sources
</details>
### 4. Adjusting Hotspot Algorithm
<details>
<summary>👉 Click to expand: <strong>Customizing hotspot weights</strong></summary>
<br>
**Configuration Location:** `config/config.yaml` under `advanced.weight`
```yaml
advanced:
weight:
rank: 0.6 # Ranking weight
frequency: 0.3 # Frequency weight
hotness: 0.1 # Hotness weight
```
Current default configuration is balanced
#### Two Core Scenarios
**Pursuing Real-time Hotspots**:
```yaml
advanced:
weight:
rank: 0.8 # Mainly consider ranking
frequency: 0.1 # Less concerned about sustainability
hotness: 0.1
```
**Applicable Users**: Self-media bloggers, marketing personnel, users who want to quickly understand current trending topics
**Pursuing In-depth Topics**:
```yaml
advanced:
weight:
rank: 0.4 # Moderately consider ranking
frequency: 0.5 # Emphasize intra-day sustainability
hotness: 0.1
```
**Applicable Users**: Investors, researchers, news workers, users who need in-depth trend analysis
#### Adjustment Method
1. **Three numbers must add up to 1.0**
2. **Increase the important factor**: If you care about ranking, increase `rank`; if you care about sustainability, increase `frequency`
3. **Suggest adjusting by 0.1-0.2 each time**, observe effects
Core idea: Users pursuing speed and timeliness increase ranking weights, users pursuing depth and stability increase frequency weights.
</details>
### 5. What Do Received Messages Look Like?
<details>
<summary>👉 Click to expand: <strong>Message style preview</strong></summary>
<br>
#### Push Example
📊 Hotspot Vocabulary Statistics
🔥 [1/3] AI ChatGPT : 2 News
1. [Baidu Hot Search] 🆕 ChatGPT-5 Officially Released [**1**] - 09:15 (1 time)
2. [Toutiao] AI Chip Concept Stocks Soar [**3**] - [08:30 ~ 10:45] (3 times)
━━━━━━━━━━━━━━━━━━━
📈 [2/3] BYD Tesla : 2 News
1. [Weibo] 🆕 BYD Monthly Sales Record Broken [**2**] - 10:20 (1 time)
2. [Douyin] Tesla Price Reduction Promotion [**4**] - [07:45 ~ 09:15] (2 times)
━━━━━━━━━━━━━━━━━━━
📌 [3/3] A-share Stock Market : 1 News
1. [Wall Street Insights] A-share Mid-day Review and Analysis [**5**] - [11:30 ~ 12:00] (2 times)
🆕 **Newly Added Hotspot News** (Total 2 News)
**Baidu Hot Search** (1 News):
1. ChatGPT-5 Officially Released [**1**]
**Weibo** (1 News):
1. BYD Monthly Sales Record Broken [**2**]
Update Time: 2025-01-15 12:30:15
#### Message Format Description
| Format Element | Example | Meaning | Description |
| ------------- | --------------------------- | ------------ | --------------------------------------- |
| 🔥📈📌 | 🔥 [1/3] AI ChatGPT | Heat Level | 🔥High heat (≥10 news) 📈Medium heat (5-9 news) 📌Ordinary heat (<5 news) |
| [Serial/Total] | [1/3] | Sorting Position | Current word group ranking among all matching word groups |
| Frequency Word Group | AI ChatGPT | Keyword Group | Configured word group, title must contain the vocabulary |
| : N News | : 2 News | Matching Quantity | Total news matched for the word group |
| [Platform Name] | [Baidu Hot Search] | Source Platform | News platform name |
| 🆕 | 🆕 ChatGPT-5 Officially Released | New Marker | First appearance in this round of hotspots |
| [**Number**] | [**1**] | High Ranking | Ranking ≤ threshold, red and bold display |
| [Number] | [7] | Ordinary Ranking | Ranking > threshold, ordinary display |
| - Time | - 09:15 | First Time | Time when the news was first discovered |
| [Time~Time] | [08:30 ~ 10:45] | Duration | Time range from first appearance to last appearance |
| (N Times) | (3 times) | Appearance Frequency | Total appearances during monitoring |
| **New Area** | 🆕 **Newly Added Hotspot News** | New Topic Summary | Separate display of newly appeared hotspots |
</details>
### 6. Docker Deployment
**Image Description:**
TrendRadar provides two independent Docker images, choose according to needs:
| Image Name | Purpose | Description |
|---------|------|------|
| `wantcat/trendradar` | News push service | Regularly crawl news, push notifications (mandatory) |
| `wantcat/trendradar-mcp` | AI analysis service | MCP protocol support, AI conversation analysis (optional) |
> 💡 **Suggestion**:
> - Only need push function: Deploy `wantcat/trendradar` image only
> - Need AI analysis function: Deploy both images
<details>
<summary>👉 Click to expand: <strong>Complete Docker deployment guide</strong></summary>
<br>
#### Method 1: Using Docker Compose (Recommended)
1. **Create Project Directory and Configuration**:
```bash
# Clone the project to local
git clone https://github.com/sansan0/TrendRadar.git
cd TrendRadar
```
> **Explanation**: The key directory structure required for Docker deployment is as follows:
```
Current Directory/
├── config/
│ ├── config.yaml # Core function configuration (required)
│ ├── frequency_words.txt # Keyword configuration (required)
│ ├── timeline.yaml # Timeline configuration
│ ├── ai_analysis_prompt.txt # AI analysis prompt (optional)
│ ├── ai_translation_prompt.txt # AI translation prompt (optional)
│ ├── ai_interests.txt # AI interest filtering configuration (optional)
│ ├── ai_filter/ # AI filtering related prompts
│ │ ├── prompt.txt
│ │ ├── extract_prompt.txt
│ │ └── update_tags_prompt.txt
│ └── custom/ # User-defined configuration (optional)
│ ├── ai/ # Custom AI prompts
│ └── keyword/ # Custom keyword files
└── docker/
├── .env # Sensitive information + Docker-specific configuration
└── docker-compose.yml # Docker Compose orchestration file
```
2. **Configuration File Instructions**:
**Configuration Division Principle (v4.6.0 optimization)**:
| File | Purpose | Modification Frequency | Description |
|------|------|-------------------------|------|
| `config/config.yaml` | **Core Function Configuration** | Low | Report mode, push settings, storage format, push window, AI analysis switch, platform enablement, etc. |
| `config/frequency_words.txt` | **Keyword Configuration** | High | Set hot words of concern, support grouping, regular expressions, aliases, and other advanced syntax |
| `config/timeline.yaml` | **Timeline Configuration** | Low | Control news timeline display and filtering rules |
| `config/ai_analysis_prompt.txt` | **AI Analysis Prompt** | Medium | Customize AI analysis role definition and output format (v5.0.0+) |
| `config/ai_translation_prompt.txt` | **AI Translation Prompt** | Low | Customize AI translation prompt template |
| `config/ai_interests.txt` | **AI Interest Filtering** | Medium | Define AI-based interest automatic news filtering rules |
| `config/ai_filter/` | **AI Filtering Prompt** | Low | Internal prompt words for AI filtering module (generally no need to modify) |
| `config/custom/` | **User-defined Extension** | As needed | `custom/ai/` for custom AI prompts, `custom/keyword/` for custom keyword files |
| `docker/.env` | **Sensitive Information + Docker-specific Configuration** | Low | Webhook URLs, API Key, S3 key, scheduled task, etc., **not tracked by git** |
> **Division Points**:
> - **Functional Behavior** → Modify `config.yaml` (e.g., enable/disable a platform, adjust push mode)
> - **Content Concern** → Modify `frequency_words.txt` (e.g., add new concern keywords)
> - **AI Output Style** → Modify `ai_analysis_prompt.txt` or `ai_translation_prompt.txt`
> - **Secret and Credential** → Modify `docker/.env` (put sensitive information like API Key, Webhook URL here)
> - **Personalized Extension** → Use `config/custom/` directory to avoid direct modification of default configuration being overwritten by upgrade
> **Configuration Modification Takes Effect**: After modifying `config.yaml`, execute `docker compose up -d` to restart the container to take effect
**⚙️ Environment Variable Override Mechanism (v3.0.5+)**
Environment variables in `.env` file will override corresponding configurations in `config.yaml`:
| Environment Variable | Corresponding Configuration | Example Value | Description |
|---------|---------|-------|------|
| `WEBSERVER_PORT` | - | `8080` | Web server port |
| `FEISHU_WEBHOOK_URL` | `notification.channels.feishu.webhook_url` | `https://...` | Feishu Webhook (multiple accounts separated by `;`) |
| `AI_ANALYSIS_ENABLED` | `ai_analysis.enabled` | `true` / `false` | Whether to enable AI analysis (added in v5.0.0) |
| `AI_API_KEY` | `ai.api_key` | `sk-xxx...` | AI API Key (shared by `ai_analysis` and `ai_translation`) |
| `AI_PROVIDER` | `ai.provider` | `deepseek` / `openai` / `gemini` | AI provider |
| `S3_*` | `storage.remote.*` | - | Remote storage configuration (5 parameters) |
**Configuration Priority**: Environment variable > config.yaml
**Usage**:
- Modify `.env` file and fill in required configurations
- Or add directly in the "environment variable" section of NAS/Synology Docker management interface
- Take effect after restarting the container: `docker compose up -d`
3. **Start Service**:
**Option A: Start All Services (Push + AI Analysis)**
```bash
# Pull the latest image
docker compose pull
# Start all services (trendradar + trendradar-mcp)
docker compose up -d
```
**Option B: Start News Push Service Only**
```bash
# Start trendradar only (timed crawling and pushing)
docker compose pull trendradar
docker compose up -d trendradar
```
**Option C: Start MCP AI Analysis Service Only**
```bash
# Start trendradar-mcp only (provide AI analysis interface)
docker compose pull trendradar-mcp
docker compose up -d trendradar-mcp
```
> **Tips**:
> - Most users only need to start `trendradar` to achieve news push function
> - Only when using ChatGPT/Gemini for AI dialogue analysis, you need to start `trendradar-mcp`
> - Two services are independent and can be flexibly combined according to needs
4. **View Running Status**:
```bash
# View news push service logs
docker logs -f trendradar
# View MCP AI analysis service logs
docker logs -f trendradar-mcp
# View all container status
docker ps | grep trendradar
# Stop specific service
docker compose stop trendradar # Stop push service
docker compose stop trendradar-mcp # Stop MCP service
```
#### Method 2: Local Build (Developer Option)
If you need to customize and modify the code or build your own image:
```bash
# Clone the project
git clone https://github.com/sansan0/TrendRadar.git
cd TrendRadar
# Modify configuration files
vim config/config.yaml
vim config/frequency_words.txt
# Use build version of docker compose
cd docker
cp docker-compose-build.yml docker-compose.yml
```
**Build and Start Service**:
```bash
# Option A: Build and start all services
docker compose build
docker compose up -d
# Option B: Build and start news push service only
docker compose build trendradar
docker compose up -d trendradar
# Option C: Build and start MCP AI analysis service only
docker compose build trendradar-mcp
docker compose up -d trendradar-mcp
```
> **Architecture Parameter Instructions**:
> - Default build `amd64` architecture image (suitable for most x86_64 servers)
> - If you need to build `arm64` architecture (Apple Silicon, Raspberry Pi, etc.), set environment variable:
> ```bash
> export DOCKER_ARCH=arm64
> docker compose build
> ```
#### Image Update
```bash
# Method 1: Manual update (crawler + MCP image)
docker pull wantcat/trendradar:latest
docker pull wantcat/trendradar-mcp:latest
docker compose down
docker compose up -d
# Method 2: Use docker compose to update
docker compose pull
docker compose up -d
```
**Available Images**:
| Image Name | Purpose | Description |
|---------|------|------|
| `wantcat/trendradar` | News push service | Timed crawling news, push notifications |
| `wantcat/trendradar-mcp` | MCP service | AI analysis function (optional) |
#### Service Management Commands
```bash
# View running status
docker exec -it trendradar python manage.py status
# Manually execute a crawler
docker exec -it trendradar python manage.py run
# View real-time logs
docker exec -it trendradar python manage.py logs
# Display current configuration
docker exec -it trendradar python manage.py config
# Display output files
docker exec -it trendradar python manage.py files
# Web server management (for browser access to generated reports)
docker exec -it trendradar python manage.py start_webserver # Start web server
docker exec -it trendradar python manage.py stop_webserver # Stop web server
docker exec -it trendradar python manage.py webserver_status # View web server status
# View help information
docker exec -it trendradar python manage.py help
# Restart container
docker restart trendradar
# Stop container
docker stop trendradar
# Delete container (retain data)
docker rm trendradar
```
> **Web Server Instructions**:
> - Automatically started in cron mode, access `http://localhost:8080` through browser to view the latest report
> - Access historical reports through directory navigation (e.g., `http://localhost:8080/2025-xx-xx/`)
> - Port can be configured in `.env` file with `WEBSERVER_PORT` parameter
> - Manual stop: `docker exec -it trendradar python manage.py stop_webserver`
> - Manual start: `docker exec -it trendradar python manage.py start_webserver`
> - Security tip: Only provides static file access, restricted to `output` directory, bound to local access only
#### Data Persistence
Generated reports and data are saved in the `./output` directory by default, and data will be retained even if the container is restarted or deleted.
**📊 Web Version Report Access Path**:
TrendRadar generated daily summary HTML report will be saved to two locations:
| File Location | Access Method | Applicable Scenario |
|---------|---------|---------|
| `output/index.html` | Direct access on host machine | **Docker deployment** (visible on host machine through Volume mounting) |
| `index.html` | Root directory access | **GitHub Pages** (repository root directory, Pages automatically identified) |
| `output/html/YYYY-MM-DD/daily_summary.html` | Historical report access | All environments (archived by date) |
**Local Access Example**:
```bash
# Method 1: Access through web server (recommended, Docker environment)
# 1. Start web server
docker exec -it trendradar python manage.py start_webserver
# 2. Access in browser
http://localhost:8080 # Access latest report (default index.html)
http://localhost:8080/html/2025-xx-xx/ # Access report for specified date
# Method 2: Open file directly (local environment)
open ./output/index.html # macOS
start ./output/index.html # Windows
xdg-open ./output/index.html # Linux
# Method 3: Access historical archive
open ./output/html/2025-xx-xx/daily_summary.html
```
**Why are there two index.html files?**
- `output/index.html`: Docker Volume mounted to host machine, can be opened directly locally
- `index.html`: GitHub Actions pushed to repository, GitHub Pages automatically deployed
> **Tips**: Two files have the same content, choose either one to access
#### Troubleshooting
```bash
# Check container status
docker inspect trendradar
# View container logs
docker logs --tail 100 trendradar
# Enter container for debugging
docker exec -it trendradar /bin/bash
# Verify configuration file
docker exec -it trendradar ls -la /app/config/
```
#### MCP Service Deployment (AI Analysis Function)
If you need to use AI analysis function, you can deploy an independent MCP service container.
**Architecture Instructions**:
```mermaid
flowchart TB
subgraph trendradar["trendradar"]
A1[Timed crawling news]
A2[Push notifications]
end
subgraph trendradar-mcp["trendradar-mcp"]
B1[127.0.0.1:3333]
B2[AI analysis interface]
end
subgraph shared["Shared Volume"]
C1["config/ (ro)"]
C2["output/ (ro)"]
end
trendradar --> shared
trendradar-mcp --> shared
```
**Quick Start**:
If you have completed deployment according to [Method 1: Using Docker Compose](#method-1-using-docker-compose-recommended), just start MCP service:
```bash
cd TrendRadar/docker
docker compose up -d trendradar-mcp
# View running status
docker ps | grep trendradar-mcp
```
**Start MCP Service Alone** (without using docker compose):
```bash
# Linux/Mac
docker run -d --name trendradar-mcp \
-p 127.0.0.1:3333:3333 \
-v $(pwd)/config:/app/config:ro \
-v $(pwd)/output:/app/output:ro \
-e TZ=Asia/Shanghai \
wantcat/trendradar-mcp:latest
# Windows PowerShell
docker run -d --name trendradar-mcp `
-p 127.0.0.1:3333:3333 `
-v ${PWD}/config:/app/config:ro `
-v ${PWD}/output:/app/output:ro `
-e TZ=Asia/Shanghai `
wantcat/trendradar-mcp:latest
```
> ⚠️ **Attention**: When running alone, ensure that there are `config/` and `output/` folders under the current directory, and they contain configuration files and news data.
**Verify Service**:
```bash
# Check MCP service health status
curl http://127.0.0.1:3333/mcp
```
# Tool List
## Check MCP Service Logs
docker logs -f trendradar-mcp
## Configure in AI Client:
After MCP service starts, configure according to different clients:
### Cherry Studio (Recommended, GUI Configuration):
- Settings → MCP Server → Add
- Type: `streamableHttp`
- URL: `http://127.0.0.1:3333/mcp`
### Claude Desktop / Cline (JSON Configuration):
```json
{
"mcpServers": {
"trendradar": {
"url": "http://127.0.0.1:3333/mcp",
"type": "streamableHttp"
}
}
}
```
> 💡 **Tip**: MCP service only listens to local port (127.0.0.1), ensuring security. If you need remote access, configure a reverse proxy and authentication yourself.
## Push Content Display
### Configuration Location: `config/config.yaml` `report` and `display` sections
```yaml
report:
mode: "daily" # Push mode
display_mode: "keyword" # Display mode (added in v4.6.0)
rank_threshold: 5 # Ranking highlight threshold
sort_by_position_first: false # Sorting priority
max_news_per_keyword: 0 # Maximum news per keyword
display:
region_order: # Region display order (added in v5.2.0)
- new_items # New hotspots region
- hotlist # Hotlist region
- rss # RSS subscription region
- standalone # Independent display area
- ai_analysis # AI analysis region
```
#### Common Configuration Item Description
| What I want to adjust | Which parameter to modify | Default value | Description |
|-------------|-------------|-------|------|
| **Push mode** | `mode` | `daily` | Decides push timing and content, see [Push Mode Details](#3-push-mode-details) |
| **Grouping method** | `display_mode` | `keyword` | `keyword`=group by keyword (e.g., "AI"), `platform`=group by platform (e.g., "Weibo") |
| **Highlight key points** | `rank_threshold` | `5` | News ranking top 5 will be **bolded**, easy to see the hottest ones |
| **Sorting rule** | `sort_by_position_first` | `false` | `false`= hottest ones on top, `true`= your configured words on top |
| **Quantity limit** | `max_news_per_keyword` | `0` | Maximum news per keyword? `0` means no limit |
| **Display order** | `display.region_order` | See above configuration | Adjust list order to control region display position |
#### Grouping Method Comparison (display_mode)
Do you want to see "what news are there under this topic" or "what news are there on this platform"?
| Mode | Grouping method | Title prefix | Applicable scenario |
|------|---------|---------|---------|
| `keyword` (default) | **Group by keyword** | `[Platform name]` | I follow "AI", want to see AI-related news from various platforms |
| `platform` | **Group by platform** | `[Keyword]` | I follow "Weibo", want to see news about my followed keywords on Weibo |
#### Region Display Order (region_order)
By adjusting the `display.region_order` list order, you can control the display position of each region in the push message.
**Default order**: New hotspots → Hotlist → RSS → Independent display area → AI analysis
**Custom example**: Want AI analysis on top?
```yaml
display:
region_order:
- ai_analysis # Move to the first line
- new_items
- hotlist
- rss
- standalone
```
**Note**: A region will only be displayed if it meets two conditions:
1. In `region_order` list
2. Corresponding switch in `display.regions` is `true`
#### Region Switch (regions)
Control whether each region is displayed in the push message:
```yaml
display:
regions:
hotlist: true # Hotlist region (keyword-matched hot news)
new_items: false # New hotspots region (including hotlist new + RSS new)
rss: true # RSS subscription region (keyword-matched RSS content)
standalone: false # Independent display area (complete hotlist/RSS, not subject to keyword filtering)
ai_analysis: true # AI analysis region
```
| Region | Configuration key | Default value | Description |
|------|--------|-------|------|
| **Hotlist** | `hotlist` | `true` | Keyword-matched hot news aggregation |
| **New hotspots** | `new_items` | `false` | Newly appeared hot topics (including hotlist new + RSS new). Note: 🆕 mark in hotlist region is not affected by this switch |
| **RSS** | `rss` | `true` | Keyword-matched RSS subscription content. If closed, skip RSS analysis, but independent display area RSS is not affected |
| **Independent display area** | `standalone` | `false` | Specified platform/RSS complete content display, not subject to keyword filtering |
| **AI analysis** | `ai_analysis` | `true` | AI-generated hotspot analysis summary |
#### Sorting Priority (sort_by_position_first)
Assume you configured keywords: 1. Tesla, 2. BYD.
Actual popularity: BYD (10 articles), Tesla (3 articles).
| Configuration value | Sorting result | Your idea |
|-------|---------|---------|
| `false` (default) | BYD (10 articles) → Tesla (3 articles) | "Who's hot on top" |
| `true` | Tesla (3 articles) → BYD (10 articles) | "My configured order is priority, regardless of popularity" |
#### Independent Display Area (standalone)
**Scenario**: Some platforms (e.g., Zhihu hotlist, HackerNews), I want to **see the complete list**, regardless of whether it matches my keywords.
```yaml
display:
regions:
standalone: true # Display independent display area in push (closing does not affect AI analysis)
standalone:
platforms: ["zhihu", "weibo"] # These platforms' hotlists are displayed completely
rss_feeds: ["hacker-news"] # These RSS sources' content is displayed completely
max_items: 20 # Maximum display items
```
> 💡 **Push display and AI analysis are independent**: `regions.standalone` only controls whether to display independent display area in push. Even if closed, AI will still analyze these platforms' complete data if `include_standalone: true` is configured in AI configuration.
## When to Push?
<details>
<summary>👉 Click to expand: <strong>Set Push Timing (Scheduling System)</strong></summary>
<br>
### Configuration Location: `config/config.yaml` `schedule` section + `config/timeline.yaml`
#### Quick Start
Just select a preset template in `config.yaml`, no need to edit `timeline.yaml`:
```yaml
schedule:
enabled: true
preset: "morning_evening" # Change here
```
#### Optional Preset Templates
| Template name | Description | Push behavior |
|-------|------|---------|
| `morning_evening` | Daily incremental + evening summary (recommended) | Push when new + 19:00-21:00 evening summary |
| `always_on` | Always monitoring | Push when new, no time segment division |
| `office_hours` | Office hours | Three-stage workday (arrival overview → lunch hotspots → end-of-work summary), weekend incremental free push |
| `night_owl` | Night owl | Afternoon overview + deep night full-day summary (22:00-01:00跨 midnight) |
| `custom` | Completely custom | Edit `timeline.yaml` bottom custom section |
#### Completely Custom
If preset templates do not meet requirements, edit `config/timeline.yaml` bottom `custom` section, define time segments, daily plans, and week mappings. See `timeline.yaml` file comments for details.
#### Important Reminder
> ⚠️ **Users upgrading from old versions**:
> - v6.0.0 removed old `notification.push_window` and `ai_analysis.analysis_window` configurations
> - Use new `schedule` + `timeline.yaml` scheduling system
> - Old "push once a day" can be replaced with `morning_evening` preset
> - Old "work hours push" can be replaced with `office_hours` preset
> ⚠️ **GitHub Actions users**:
> - GitHub Actions execution time is unstable, may have ±15 minutes deviation
> - Time segment range suggests leaving at least **2 hours**
> - For precise timing push, recommend using **Docker deployment** on personal server
</details>
## How often to run?
<details>
<summary>👉 Click to expand: <strong>Set Automatic Running Frequency</strong></summary>
<br>
### Configuration Location: `.github/workflows/crawler.yml` `schedule` section
```yaml
on:
schedule:
- cron: "0 * * * *" # Run once an hour
```
#### How to modify running frequency?
GitHub Actions uses "Cron" time format, no need to understand deeply, just copy and replace.
### Configuration Location: `.github/workflows/crawler.yml` file `schedule` section
| What I want... | Copy this line | Description |
|-----------|------------|------|
| **Once an hour** | `- cron: "0 * * * *"` | **Default configuration**, runs at 0 minute |
| **Every 30 minutes** | `- cron: "*/30 * * * *"` | Run every 30 minutes |
| **Daily at 8:00** | `- cron: "0 0 * * *"` | ⚠️ Write `0` because UTC time (0:00) = Beijing time (8:00) |
| **Work hours every half hour** | `- cron: "*/30 0-14 * * *"` | Corresponds to Beijing time 8:00 - 22:00 |
| **Three meals a day** | `- cron: "0 0,6,12 * * *"` | Corresponds to Beijing time 8:00, 14:00, 20:00 |
#### ⚠️ Two important reminders
1. **Time difference**: GitHub server is abroad, using UTC time.
- **Simple arithmetic**: Your desired Beijing time **minus 8 hours** = time to fill.
- *Example: Want it to run at 20:00 Beijing time, set to 12:00*
2. **Don't be too frequent**: Suggest interval not less than 30 minutes.
- GitHub free resources are limited, running too frequently may be restricted by official account.
- Actions start-up has several minutes delay, too precise control is meaningless.
#### Step-by-step modification
1. In your GitHub repository, find `.github/workflows/crawler.yml` file
2. Click right-top ✏️ (Edit) button
3. Find `cron: "..."` line, replace content with above "code"
4. Click right-top green **Commit changes** button save
</details>
## Push to multiple groups/devices
<details>
<summary>👉 Click to expand: <strong>Push to multiple receivers simultaneously</strong></summary>
> ### ⚠️ **Security first**
> **Do not write password/Token in `config.yaml`!**
> If you upload files with passwords to GitHub, the whole world can see.
>
> **Correct approach**:
> - **GitHub Actions users**: Go to Settings -> Secrets to add
> - **Docker users**: Write in `.env` file (this file will not be uploaded)
#### How to push to multiple places?
Simple, use semicolon `;` to separate multiple addresses.
**Example**:
Assume you have two Feishu groups, want to receive push simultaneously:
- Group 1 address: `https://.../webhook/aaa`
- Group 2 address: `https://.../webhook/bbb`
Configure: `https://.../webhook/aaa;https://.../webhook/bbb`
#### Platforms supporting multiple accounts
| Platform | Configuration method | Notes |
|------|---------|----------|
| **Feishu/DingTalk/WeCom** | Use `;` to separate multiple Webhook URLs | Simplest, just connect them |
| **Bark (iOS)** | Use `;` to separate multiple Key URLs | Push to multiple iPhones |
| **Telegram** | Token and ChatID use `;` to separate | ⚠️ **Note order**:<br>Token1 corresponds to ChatID1<br>Token2 corresponds to ChatID2 |
| **ntfy** | Topic and Token use `;` to separate | If a topic does not need a token, leave blank:<br>`token1;;token3` (middle one is blank) |
#### Common configuration examples (GitHub Secrets / .env)
```bash
# Feishu push to 3 groups
FEISHU_WEBHOOK_URL=https://hook1...;https://hook2...;https://hook3...
# DingTalk push to 2 groups
DINGTALK_WEBHOOK_URL=https://oapi...;https://oapi...
# Telegram push to 2 people (note one-to-one correspondence)
TELEGRAM_BOT_TOKEN=tokenA;tokenB
TELEGRAM_CHAT_ID=userA;userB
```
> **Tip**: To prevent abuse, default limit is 3 accounts per platform. If you need more, modify `MAX_ACCOUNTS_PER_CHANNEL` configuration.
</details>
## Where is data stored?
<details id="storage-config">
<summary>👉 Click to expand: <strong>Choose data storage location</strong></summary>
<br>
#### Where will data be stored?
The system will automatically choose the most suitable location for you, you usually don't need to worry:
| Your running environment | Data stored in | Description |
|-------------|-----------|------|
| **Docker / Local run** | **Local hard disk** | Stored in project directory `output/` folder, can be viewed anytime. |
| **GitHub Actions** | **Cloud storage** | Because GitHub Actions will destroy environment after running, a cloud storage (e.g., Cloudflare R2) is required. |
#### How to configure cloud storage? (GitHub Actions users must read)
If you use GitHub Actions, you need a "cloud hard disk" to store data. For example, use Cloudflare R2 (because it has free quota).
**Add these 5 variables in GitHub Secrets**:
| Variable name | What to fill |
|-------|-------|
| `STORAGE_BACKEND` | `remote` |
| `S3_BUCKET_NAME` | Your storage bucket name |
| `S3_ACCESS_KEY_ID` | Your Access Key |
| `S3_SECRET_ACCESS_KEY` | Your Secret Key |
| `S3_ENDPOINT_URL` | Your R2 interface address |
> 💡 **Detailed tutorial**: How to apply for R2? See [Quick Start - Remote Storage Configuration](#-quick-start)
#### How long will data be saved?
By default, we will not automatically delete your data. But if you think data takes up too much space, set "auto-cleanup".
**Configuration location**: `config/config.yaml`
```yaml
storage:
local:
retention_days: 30 # Local data retained for 30 days (0 means permanent)
remote:
retention_days: 30 # Cloud data retained for 30 days
```
#### Push time is not correct? (Timezone setting)
If you are abroad or find push time does not match your local time, modify timezone.
**Configuration location**: `config/config.yaml`
```yaml
app:
timezone: "Asia/Shanghai" # Default is China time
```
- For example, if you are in Los Angeles, change to: `America/Los_Angeles`
- For example, if you are in London, change to: `Europe/London`
</details>
## Let AI help analyze hotspots
<details id="ai-analysis-config">
<summary>👉 Click to expand: <strong>Enable AI intelligent analysis function</strong></summary>
<br>
#### What can AI do for me?
After enabling this function, AI will act like a professional analyst, for each batch of news push:
1. **Automatic reading**: Read all matched hot news
2. **Deep thinking**: Analyze isolated news associations
3. **Write report**: Append a short, profound "insight report" at the end of the push message
**Includes**: Hotspot trend summary, public opinion analysis, cross-platform association analysis, potential impact assessment, etc.
</details>
#### How to Enable AI Analysis?
The simplest way is through environment variable configuration (recommended GitHub Secrets or .env).
**Required Configurations**:
| Variable Name | What to Fill | Description |
|---------------|--------------|--------------|
| `AI_ANALYSIS_ENABLED` | `true` | Enable switch |
| `AI_API_KEY` | `sk-xxxxxx` | Your API Key |
| `AI_MODEL` | `deepseek/deepseek-chat` | Model identifier (format: `provider/model`) |
**Supported AI Providers** (based on LiteLLM, supports 100+ providers):
| Provider | What to Fill for AI_MODEL | Description |
|-----------|--------------------------|--------------|
| **DeepSeek** (recommended) | `deepseek/deepseek-chat` | High cost-effectiveness, suitable for high-frequency analysis |
| **OpenAI** | `openai/gpt-4o`<br>`openai/gpt-4o-mini` | GPT-4o series |
| **Google Gemini** | `gemini/gemini-1.5-flash`<br>`gemini/gemini-1.5-pro` | Gemini series |
| **Custom API** | Any format | Used with `AI_API_BASE` |
> 💡 **New Feature**: Now unified interface based on [LiteLLM](https://github.com/BerriAI/litellm), supports 100+ AI providers, simpler configuration, and improved error handling.
**Optional Configurations**:
| Variable Name | Default Value | Description |
|---------------|---------------|--------------|
| `AI_API_BASE` | (automatic) | Custom API address (e.g., OneAPI, local model) |
| `AI_TEMPERATURE` | `1.0` | Sampling temperature (0-2, higher is more random) |
| `AI_MAX_TOKENS` | `5000` | Maximum generated tokens |
| `AI_TIMEOUT` | `120` | Request timeout (seconds) |
| `AI_NUM_RETRIES` | `2` | Number of retry attempts |
#### Advanced Play: AI Translation
If you follow foreign RSS sources (e.g., Hacker News), AI can help translate content into Chinese for you.
**Configuration Location**: `config/config.yaml`
```yaml
ai_translation:
enabled: true # Enable translation
language: "Chinese" # Translate to what language (Chinese, English, Japanese...)
```
#### Advanced Play: Custom AI Persona
Do you find AI's responses too official? You can modify its prompt to make it fit your preferred style (e.g., "sarcastic commentator", "experienced investment advisor").
- **Edit File**: `config/ai_analysis_prompt.txt`
- **Edit Method**: Open and edit directly, tell AI what analysis style you want.
</details>
<br>
## ✨ AI Intelligent Analysis
TrendRadar v3.0.0 introduces AI analysis based on **MCP (Model Context Protocol)**, allowing you to converse with news data in natural language for in-depth analysis.
### ⚠️ Read Before Use
**Important Note**: AI functionality requires local news data support.
AI analysis is **not** a direct query of real-time network data but analyzes your **locally accumulated news data** (stored in the `output` folder).
#### Instructions for Use:
1. **Project Comes with Test Data**: The `output` directory includes **2025-12-21~2025-12-27** one week's hot list news data for quick AI feature experience.
2. **Query Limitations**:
- ✅ Can only query data within the existing date range (December 21-27, 7 days total).
- ❌ Cannot query real-time news or future dates.
3. **Get Latest Data**:
- Test data is for quick experience; **recommended to deploy the project yourself** to get real-time data.
- Follow [Quick Start](#-quick-start) to deploy and run the project.
- Wait at least 1 day to accumulate news data before querying the latest hot topics.
### 1. Quick Deployment
Cherry Studio provides a GUI configuration interface for 5-minute quick deployment, making complex configurations a one-click installation.
**Graphical Deployment Tutorial**: Updated to my [public WeChat account](#-support-the-project), reply "mcp" for details.
**Detailed Deployment Tutorial**: [README-Cherry-Studio.md](README-Cherry-Studio.md)
**Deployment Mode Description**:
- **STDIO Mode (Recommended)**: Configure once and no need to repeat; graphical deployment tutorial uses this mode as an example.
- **HTTP Mode (Alternative)**: If STDIO mode configuration encounters issues, use HTTP mode. This mode's configuration is similar to STDIO but with a one-line copy-paste content and less prone to errors. The only difference is that the service needs to be manually started each time.
### 2. Learning How to Chat with AI
**Detailed Dialogue Tutorial**: [README-MCP-FAQ.md](README-MCP-FAQ.md)
> 💡 **Tip**: It's not recommended to ask multiple questions at once. If your chosen AI model can't handle sequential calls like in the figure below, consider switching to another model.
<img src="/_image/ai4.png" alt="mcp usage effect diagram" width="600">
<br>
## 🔌 MCP Client
TrendRadar MCP service supports the standard Model Context Protocol (MCP) and can connect to various MCP-supported AI clients for intelligent analysis.
### Supported Clients
**Note**:
- Replace `/path/to/TrendRadar` with your project's actual path.
- Use double backslashes for Windows paths: `C:\\Users\\YourName\\TrendRadar`.
- Remember to restart after saving.
<details>
<summary>👉 Click to expand: <b>Cursor</b></summary>
#### Method 1: HTTP Mode
1. **Start HTTP Service**:
```bash
# Windows
start-http.bat
# Mac/Linux
./start-http.sh
```
2. **Configure Cursor**:
**Project-level Configuration** (recommended):
Create `.cursor/mcp.json` in the project root directory:
```json
{
"mcpServers": {
"trendradar": {
"url": "http://localhost:3333/mcp",
"description": "TrendRadar News Hotspot Aggregation Analysis"
}
}
}
```
**Global Configuration**:
Create `~/.cursor/mcp.json` (with the same content).
3. **Usage Steps**:
- Save the configuration file and restart Cursor.
- Check the connected tools in the "Available Tools" section of the chat interface.
- Start using: `Search today's "AI" related news`.
#### Method 2: STDIO Mode (Recommended)
Create `.cursor/mcp.json`:
```json
{
"mcpServers": {
"trendradar": {
"command": "uv",
"args": [
"--directory",
"/path/to/TrendRadar",
"run",
"python",
"-m",
"mcp_server.server"
]
}
}
}
```
</details>
<details>
<summary>👉 Click to expand: <b>VSCode (Cline/Continue)</b></summary>
#### Cline Configuration
Add to Cline's MCP settings:
**HTTP Mode**:
```json
{
"trendradar": {
"url": "http://localhost:3333/mcp",
"type": "streamableHttp",
"autoApprove": [],
"disabled": false
}
}
```
**STDIO Mode** (recommended):
```json
{
"trendradar": {
"command": "uv",
"args": [
"--directory",
"/path/to/TrendRadar",
"run",
"python",
"-m",
"mcp_server.server"
],
"type": "stdio",
"disabled": false
}
}
```
#### Continue Configuration
Edit `~/.continue/config.json`:
```json
{
"experimental": {
"modelContextProtocolServers": [
{
"transport": {
"type": "stdio",
"command": "uv",
"args": [
"--directory",
"/path/to/TrendRadar",
"run",
"python",
"-m",
"mcp_server.server"
]
}
}
]
}
}
```
**Usage Example**:
```
Analyze the trend of "Tesla" in the last 7 days
Generate today's hot summary report
Search for news related to "Bitcoin" and analyze sentiment
```
</details>
<details>
<summary>👉 Click to expand: <b>MCP Inspector</b> (debugging tool)</summary>
<br>
MCP Inspector is an official debugging tool for testing MCP connections:
#### Usage Steps
1. **Start TrendRadar HTTP Service**:
```bash
# Windows
start-http.bat
# Mac/Linux
./start-http.sh
```
2. **Start MCP Inspector**:
```bash
npx @modelcontextprotocol/inspector
```
3. **Connect in Browser**:
- Visit: `http://localhost:3333/mcp`
- Test "Ping Server" to verify connection
- Check "List Tools" to see if 17 tools are returned:
- Basic Query: get_latest_news, get_news_by_date, get_trending_topics
- Intelligent Search: search_news, find_related_news
- Advanced Analysis: analyze_topic_trend, analyze_data_insights, analyze_sentiment, aggregate_news, compare_periods, generate_summary_report
- RSS Query: get_latest_rss, search_rss, get_rss_feeds_status
- System Management: get_current_config, get_system_status, resolve_date_range
</details>
<details>
<summary>👉 Click to expand: <b>Other MCP-supported Clients</b></summary>
<br>
Any client supporting the Model Context Protocol can connect to TrendRadar:
#### HTTP Mode
**Service Address**: `http://localhost:3333/mcp`
**Basic Configuration Template**:
```json
{
"name": "trendradar",
"url": "http://localhost:3333/mcp",
"type": "http",
"description": "News Hotspot Aggregation Analysis"
}
```
#### STDIO Mode (Recommended)
**Basic Configuration Template**:
```json
{
"name": "trendradar",
"command": "uv",
"args": [
"--directory",
"/path/to/TrendRadar",
"run",
"python",
"-m",
"mcp_server.server"
],
"type": "stdio"
}
```
**Note**:
- Replace `/path/to/TrendRadar` with the actual project path.
- Use backslash escape for Windows paths: `C:\\Users\\...`
- Ensure project dependencies are installed (setup script has been run).
</details>
### Frequently Asked Questions
<details>
<summary>👉 Click to expand: <b>Q1: HTTP Service Fails to Start?</b></summary>
<br>
**Check Steps**:
1. Confirm port 3333 is not occupied:
```bash
# Windows
netstat -ano | findstr :3333
# Mac/Linux
lsof -i :3333
```
2. Check if project dependencies are installed:
```bash
# Run installation script again
# Windows: setup-windows.bat or setup-windows-en.bat
# Mac/Linux: ./setup-mac.sh
```
3. View detailed error logs:
```bash
uv run python -m mcp_server.server --transport http --port 3333
```
4. Try custom port:
```bash
uv run python -m mcp_server.server --transport http --port 33333
```
</details>
<details>
<summary>👉 Click to expand: <b>Q2: Client Cannot Connect to MCP Service?</b></summary>
<br>
**Solutions**:
1. **STDIO Mode**:
- Confirm UV path is correct (run `which uv` or `where uv`).
- Confirm project path is correct and has no Chinese characters.
- Check client error logs.
2. **HTTP Mode**:
- Confirm service is started (visit `http://localhost:3333/mcp`).
- Check firewall settings.
- Try using 127.0.0.1 instead of localhost.
3. **General Check**:
- Restart client application.
- Check MCP service logs.
- Use MCP Inspector to test connection.
</details>
<details>
<summary>👉 Click to expand: <b>Q3: Tool Invocation Fails or Returns Error?</b></summary>
<br>
**Possible Causes**:
1. **Data Does Not Exist**:
- Confirm data has been crawled (output directory exists).
- Check query date range for available data.
- View available dates in the output directory.
2. **Parameter Error**:
- Check date format: `YYYY-MM-DD`.
- Confirm platform ID is correct: `zhihu`, `weibo`, etc.
- View tool documentation for parameter descriptions.
3. **Configuration Issue**:
- Confirm `config/config.yaml` exists.
- Confirm `config/frequency_words.txt` exists.
- Check configuration file format.
</details>
<br>
## 📚 Project Related
> **4 Articles**:
- [Leave a comment at the bottom of this article for easy communication with the project author](https://mp.weixin.qq.com/s/KYEPfTPVzZNWFclZh4am_g)
- [2 months to break 1000 stars, my GitHub project promotion experience](https://mp.weixin.qq.com/s/jzn0vLiQFX408opcfpPPxQ)
- [Notes on running this project in GitHub fork](https://mp.weixin.qq.com/s/C8evK-U7onG1sTTdwdW2zg)
- [How to write public account or news articles based on this project](https://mp.weixin.qq.com/s/8ghyfDAtQZjLrnWTQabYOQ)
>**AI Development**:
- If you have niche needs, you can develop based on my project, even with zero programming experience.
- All my open-source projects use **AI-assisted software** to improve development efficiency, and this tool is open-sourced.
- **Core Function**: Quickly filter project code and feed it to AI; you only need to supplement personal needs.
- **Project Address**: https://github.com/sansan0/ai-code-context-helper
### Other Projects
> 📍 Mao Zedong Footprint Map - Interactive dynamic display of complete trajectory from 1893-1976. Welcome comrades to contribute data.
- https://github.com/sansan0/mao-map
> Bilibili comment area data visualization analysis software
- https://github.com/sansan0/bilibili-comment-analyzer
[](https://www.star-history.com/#sansan0/TrendRadar&Date)
<br>
## 📄 License
GPL-3.0 License
---
<div align="center">
[🔝 Back to Top](#trendradar)
</div>
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available