# coding=utf-8
"""
推送记录管理模块
管理推送记录,支持每日只推送一次和时间窗口控制
通过 storage_backend 统一存储,支持本地 SQLite 和远程云存储
"""
from datetime import datetime
from typing import Callable, Optional, Any
import pytz
class PushRecordManager:
"""
推送记录管理器
通过 storage_backend 统一管理推送记录:
- 本地环境:使用 LocalStorageBackend,数据存储在本地 SQLite
- GitHub Actions:使用 RemoteStorageBackend,数据存储在云端
这样 once_per_day 功能在 GitHub Actions 上也能正常工作。
"""
def __init__(
self,
storage_backend: Any,
get_time_func: Optional[Callable[[], datetime]] = None,
):
"""
初始化推送记录管理器
Args:
storage_backend: 存储后端实例(LocalStorageBackend 或 RemoteStorageBackend)
get_time_func: 获取当前时间的函数(应使用配置的时区)
"""
self.storage_backend = storage_backend
self.get_time = get_time_func or self._default_get_time
print(f"[推送记录] 使用 {storage_backend.backend_name} 存储后端")
def _default_get_time(self) -> datetime:
"""默认时间获取函数(UTC+8)"""
return datetime.now(pytz.timezone("Asia/Shanghai"))
def has_pushed_today(self) -> bool:
"""
检查今天是否已经推送过
Returns:
是否已推送
"""
return self.storage_backend.has_pushed_today()
def record_push(self, report_type: str) -> bool:
"""
记录推送
Args:
report_type: 报告类型
Returns:
是否记录成功
"""
return self.storage_backend.record_push(report_type)
def is_in_time_range(self, start_time: str, end_time: str) -> bool:
"""
检查当前时间是否在指定时间范围内
Args:
start_time: 开始时间(格式:HH:MM)
end_time: 结束时间(格式:HH:MM)
Returns:
是否在时间范围内
"""
now = self.get_time()
current_time = now.strftime("%H:%M")
def normalize_time(time_str: str) -> str:
"""将时间字符串标准化为 HH:MM 格式"""
try:
parts = time_str.strip().split(":")
if len(parts) != 2:
raise ValueError(f"时间格式错误: {time_str}")
hour = int(parts[0])
minute = int(parts[1])
if not (0 <= hour <= 23 and 0 <= minute <= 59):
raise ValueError(f"时间范围错误: {time_str}")
return f"{hour:02d}:{minute:02d}"
except Exception as e:
print(f"时间格式化错误 '{time_str}': {e}")
return time_str
normalized_start = normalize_time(start_time)
normalized_end = normalize_time(end_time)
normalized_current = normalize_time(current_time)
result = normalized_start <= normalized_current <= normalized_end
if not result:
print(f"时间窗口判断:当前 {normalized_current},窗口 {normalized_start}-{normalized_end}")
return result