push_manager.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. # coding=utf-8
  2. """
  3. 推送记录管理模块
  4. 管理推送记录,支持每日只推送一次和时间窗口控制
  5. 通过 storage_backend 统一存储,支持本地 SQLite 和远程云存储
  6. """
  7. from datetime import datetime
  8. from typing import Callable, Optional, Any
  9. import pytz
  10. class PushRecordManager:
  11. """
  12. 推送记录管理器
  13. 通过 storage_backend 统一管理推送记录:
  14. - 本地环境:使用 LocalStorageBackend,数据存储在本地 SQLite
  15. - GitHub Actions:使用 RemoteStorageBackend,数据存储在云端
  16. 这样 once_per_day 功能在 GitHub Actions 上也能正常工作。
  17. """
  18. def __init__(
  19. self,
  20. storage_backend: Any,
  21. get_time_func: Optional[Callable[[], datetime]] = None,
  22. ):
  23. """
  24. 初始化推送记录管理器
  25. Args:
  26. storage_backend: 存储后端实例(LocalStorageBackend 或 RemoteStorageBackend)
  27. get_time_func: 获取当前时间的函数(应使用配置的时区)
  28. """
  29. self.storage_backend = storage_backend
  30. self.get_time = get_time_func or self._default_get_time
  31. print(f"[推送记录] 使用 {storage_backend.backend_name} 存储后端")
  32. def _default_get_time(self) -> datetime:
  33. """默认时间获取函数(UTC+8)"""
  34. return datetime.now(pytz.timezone("Asia/Shanghai"))
  35. def has_pushed_today(self) -> bool:
  36. """
  37. 检查今天是否已经推送过
  38. Returns:
  39. 是否已推送
  40. """
  41. return self.storage_backend.has_pushed_today()
  42. def record_push(self, report_type: str) -> bool:
  43. """
  44. 记录推送
  45. Args:
  46. report_type: 报告类型
  47. Returns:
  48. 是否记录成功
  49. """
  50. return self.storage_backend.record_push(report_type)
  51. def is_in_time_range(self, start_time: str, end_time: str) -> bool:
  52. """
  53. 检查当前时间是否在指定时间范围内
  54. Args:
  55. start_time: 开始时间(格式:HH:MM)
  56. end_time: 结束时间(格式:HH:MM)
  57. Returns:
  58. 是否在时间范围内
  59. """
  60. now = self.get_time()
  61. current_time = now.strftime("%H:%M")
  62. def normalize_time(time_str: str) -> str:
  63. """将时间字符串标准化为 HH:MM 格式"""
  64. try:
  65. parts = time_str.strip().split(":")
  66. if len(parts) != 2:
  67. raise ValueError(f"时间格式错误: {time_str}")
  68. hour = int(parts[0])
  69. minute = int(parts[1])
  70. if not (0 <= hour <= 23 and 0 <= minute <= 59):
  71. raise ValueError(f"时间范围错误: {time_str}")
  72. return f"{hour:02d}:{minute:02d}"
  73. except Exception as e:
  74. print(f"时间格式化错误 '{time_str}': {e}")
  75. return time_str
  76. normalized_start = normalize_time(start_time)
  77. normalized_end = normalize_time(end_time)
  78. normalized_current = normalize_time(current_time)
  79. result = normalized_start <= normalized_current <= normalized_end
  80. if not result:
  81. print(f"时间窗口判断:当前 {normalized_current},窗口 {normalized_start}-{normalized_end}")
  82. return result