候选池按独立事件拉取,白名单过滤低质源,同事件与 tech 主题去重后按展示上限打包。 Co-authored-by: Cursor <cursoragent@cursor.com>
135 lines
4.6 KiB
Python
135 lines
4.6 KiB
Python
"""AI 时讯 deep-research 解析与企微格式。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from daily.format_wecom import _ai_news_lines, replace_wecom_news_sections
|
|
from daily.news.research import (
|
|
parse_research_response,
|
|
research_pool_limit,
|
|
research_tech_pool_limit,
|
|
)
|
|
|
|
|
|
class TestAiNewsResearchPool(unittest.TestCase):
|
|
def test_pool_defaults_above_display(self):
|
|
self.assertEqual(research_pool_limit(10), 20)
|
|
self.assertEqual(research_tech_pool_limit(5), 10)
|
|
|
|
def test_pool_env_override(self):
|
|
import os
|
|
from unittest import mock
|
|
|
|
with mock.patch.dict(os.environ, {"DAILY_AI_NEWS_RESEARCH_POOL": "24"}, clear=False):
|
|
self.assertEqual(research_pool_limit(10), 24)
|
|
|
|
|
|
class TestAiNewsResearchParse(unittest.TestCase):
|
|
def test_parse_items(self):
|
|
raw = """
|
|
{
|
|
"items": [
|
|
{
|
|
"title": "Apple sues OpenAI",
|
|
"link": "https://techcrunch.com/2026/07/10/apple/",
|
|
"source_name": "TechCrunch",
|
|
"desc_short": "苹果起诉 OpenAI 涉嫌窃取商业机密",
|
|
"published_fmt": "07-11 05:00"
|
|
}
|
|
]
|
|
}
|
|
"""
|
|
items, tech = parse_research_response(raw, limit=10)
|
|
self.assertEqual(len(items), 1)
|
|
self.assertEqual(items[0]["source_name"], "TechCrunch")
|
|
self.assertIn("苹果", items[0]["desc_short"])
|
|
self.assertEqual(tech, [])
|
|
|
|
def test_dedupe_links(self):
|
|
raw = """{"items": [
|
|
{"title": "A", "link": "https://example.com/a", "source_name": "Ex", "desc_short": "一"},
|
|
{"title": "B", "link": "https://example.com/a", "source_name": "Ex", "desc_short": "二"}
|
|
]}"""
|
|
items, _ = parse_research_response(raw, limit=10)
|
|
self.assertEqual(len(items), 1)
|
|
|
|
def test_parse_tech_items(self):
|
|
raw = """{"items": [
|
|
{"title": "A", "link": "https://example.com/a", "source_name": "Ex", "desc_short": "一"}
|
|
], "tech_items": [
|
|
{"title": "B", "link": "https://example.com/b", "source_name": "Ex", "desc_short": "二"}
|
|
]}"""
|
|
items, tech = parse_research_response(raw, limit=10, tech_limit=5)
|
|
self.assertEqual(len(items), 1)
|
|
self.assertEqual(len(tech), 1)
|
|
self.assertEqual(tech[0]["title"], "B")
|
|
|
|
|
|
class TestMergedWecomNews(unittest.TestCase):
|
|
def test_merged_block_format(self):
|
|
items = [
|
|
{
|
|
"title": "Apple sues OpenAI",
|
|
"link": "https://techcrunch.com/x",
|
|
"source_name": "TechCrunch",
|
|
"desc_short": "苹果起诉 OpenAI",
|
|
"published_fmt": "07-11 05:00",
|
|
}
|
|
]
|
|
lines = _ai_news_lines(items, merged=True)
|
|
self.assertIn("TechCrunch - Apple sues OpenAI", lines[0])
|
|
self.assertIn("— 苹果起诉 OpenAI", lines[0])
|
|
self.assertNotIn("07-11", lines[0])
|
|
|
|
def test_merged_with_tech_block(self):
|
|
md = """📰 **早报**
|
|
|
|
📈 **Skills Trending Top 1**
|
|
1. skill
|
|
"""
|
|
main = [
|
|
{"title": "Main", "link": "https://example.com/m", "source_name": "Src", "desc_short": "主条", "published_fmt": "07-11"}
|
|
]
|
|
tech = [
|
|
{"title": "Tech", "link": "https://example.com/t", "source_name": "Src2", "desc_short": "技术条", "published_fmt": "07-12"}
|
|
]
|
|
out = replace_wecom_news_sections(md, ai_news=main, tech_ai_news=tech, merged=True)
|
|
self.assertIn("📰 **AI 时讯精选 Top 2**", out)
|
|
self.assertNotIn("技术类时讯", out)
|
|
self.assertNotIn("🔧", out)
|
|
self.assertNotIn("07-11", out)
|
|
self.assertNotIn("07-12", out)
|
|
self.assertIn("2. [Src2 - Tech]", out)
|
|
|
|
def test_replace_merged_removes_split_blocks(self):
|
|
md = """📰 **早报**
|
|
|
|
🌍 **国际 AI 时讯 Top 1**
|
|
1. [old](https://example.com/old) · `X`
|
|
|
|
🇨🇳 **国内 AI 时讯 Top 1**
|
|
1. [old2](https://example.com/old2) · `Y`
|
|
|
|
📈 **Skills Trending Top 1**
|
|
1. skill
|
|
"""
|
|
items = [
|
|
{
|
|
"title": "New story",
|
|
"link": "https://example.com/new",
|
|
"source_name": "Fortune",
|
|
"desc_short": "新故事",
|
|
"published_fmt": "",
|
|
}
|
|
]
|
|
out = replace_wecom_news_sections(md, ai_news=items, merged=True)
|
|
self.assertIn("📰 **AI 时讯精选 Top 1**", out)
|
|
self.assertNotIn("国际 AI 时讯", out)
|
|
self.assertNotIn("国内 AI 时讯", out)
|
|
self.assertIn("📈 **Skills Trending Top 1**", out)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|