"""数据存储模块 - JSON文件读写""" import json import re from datetime import date, datetime, timedelta from pathlib import Path from typing import Dict, List, Optional from src.config import get_timezone from src.markdown_utils import dump_frontmatter, parse_frontmatter def get_fetch_file(d: date = None, data_dir: str = "news-data") -> str: """获取fetch文件路径 (使用配置时区)""" if d is None: d = datetime.now(get_timezone()).date() return f"{data_dir}/fetch-{d.isoformat()}.json" def get_push_file(push_time: datetime = None, data_dir: str = "news-data") -> str: """生成push文件路径""" if push_time is None: push_time = datetime.now(get_timezone()) time_str = push_time.strftime("%Y-%m-%d-%H-%M-%S") return f"{data_dir}/push-{time_str}.md" def get_notify_file(d: date = None, data_dir: str = "news-data") -> str: """获取notify文件路径 (使用配置时区)""" if d is None: d = datetime.now(get_timezone()).date() return f"{data_dir}/notify-{d.isoformat()}.md" def save_notify_file( filepath: str, content: str, metadata: Dict = None, ): """保存即时推送文件(Markdown格式),同一天的内容追加到同一文件""" path = Path(filepath) path.parent.mkdir(parents=True, exist_ok=True) notify_time = datetime.now(get_timezone()).isoformat() if metadata: frontmatter_dict = metadata.copy() else: frontmatter_dict = {"pushTime": notify_time} frontmatter = dump_frontmatter(frontmatter_dict) new_content = f"---\n{frontmatter}---\n\n{content}\n\n------\n" with open(path, "a", encoding="utf-8") as f: f.write(new_content) _SECTION_RE_CACHE: Dict[str, re.Pattern] = {} def _section_re(section: str) -> re.Pattern: """获取/缓存 sentinel 正则。section 名做转义,允许字母数字下划线""" if section not in _SECTION_RE_CACHE: s = re.escape(section) pattern = ( rf"(.*?)" ) _SECTION_RE_CACHE[section] = re.compile(pattern, flags=re.DOTALL) return _SECTION_RE_CACHE[section] def extract_section(push_md: str, section: str) -> str: """从 push 文件内容中切出 之间的 markdown。 向后兼容: - 新文件(带 sentinel): 返回 sentinel 边界内的原文(不去边界空行) - 老文件(无 sentinel) 且 section == 'rss': 返回整个 push_md - 老文件(无 sentinel) 且 section != 'rss': 返回空字符串 - sentinel 残缺(只有 BEGIN 没有 END): 返回空字符串 """ match = _section_re(section).search(push_md) if match: return match.group(1) # 老文件兜底:rss 段视为整个 body has_any_sentinel = "\n{body}\n" ) return "\n\n".join(parts)