40c99afd92
- 清零改两桶(金币 + 折算现金);邀请奖励金物理隔离、不清(产品红线),仅快照入审计 - 预警编排 select_warn_candidates / run_warn_once / run_once(分档 + streak 去重); notifier.warn 去掉 invite 参数(邀请金不清、不预警) - 预警逐用户 try/except 隔离 + run_once 保证预警故障绝不阻塞清零(接真推送前必备) - 每日 worker inactivity_reset_worker(文件锁 + 北京日守卫 + RUN_HOUR 门槛 + 总闸默认关) + main.py lifespan 接线 - admin 最近活跃口径改用共享 activity(移除 last_login_at、纳入 home_view 占位) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
44 lines
1.6 KiB
Python
44 lines
1.6 KiB
Python
"""不活跃预警通知器(可插拔)。
|
|
|
|
v1 仅日志占位(LogNotifier):现状无真实推送能力(极光只用于一键登录解密 + 设备心跳告警,
|
|
心跳 worker 也只打印),先把清零主流程 + 审计做扎实。后续实现同协议的 JPushNotifier /
|
|
SmsNotifier 即可替换,worker/repo 不改。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Protocol
|
|
|
|
logger = logging.getLogger("shagua.inactivity")
|
|
|
|
|
|
class InactivityNotifier(Protocol):
|
|
channel: str
|
|
|
|
def warn(self, *, user_id: int, coin: int, cash_cents: int,
|
|
stage: int, days_until_reset: int) -> str:
|
|
"""发预警(只涉及会被清的金币 + 折算现金;邀请现金不清、不预警)。
|
|
返回状态:'sent' / 'failed' / 'placeholder'。"""
|
|
...
|
|
|
|
|
|
class LogNotifier:
|
|
"""占位实现:只打印,不真推。参照 heartbeat_monitor_worker「本期先不接推送」先例。"""
|
|
|
|
channel = "log"
|
|
|
|
def warn(self, *, user_id: int, coin: int, cash_cents: int,
|
|
stage: int, days_until_reset: int) -> str:
|
|
logger.warning(
|
|
"[inactivity-warn] user=%s coin=%s cash_cents=%s stage=T-%s days_until_reset=%s",
|
|
user_id, coin, cash_cents, stage, days_until_reset,
|
|
)
|
|
return "placeholder"
|
|
|
|
|
|
def get_notifier(channel: str) -> InactivityNotifier:
|
|
"""按配置返回通知器。未实现的通道(jpush/sms)暂回退 LogNotifier 占位。"""
|
|
# 后续:if channel == "jpush": return JPushNotifier()
|
|
# if channel == "sms": return SmsNotifier()
|
|
return LogNotifier()
|