feat(welfare): 可插拔不活跃预警通知器 + LogNotifier 占位
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
"""不活跃预警通知器(可插拔)。
|
||||
|
||||
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, invite_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, invite_cash_cents: int,
|
||||
stage: int, days_until_reset: int) -> str:
|
||||
logger.warning(
|
||||
"[inactivity-warn] user=%s coin=%s cash_cents=%s invite_cash_cents=%s "
|
||||
"stage=T-%s days_until_reset=%s",
|
||||
user_id, coin, cash_cents, invite_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()
|
||||
@@ -117,3 +117,13 @@ def test_inactivity_warn_stages_parsing() -> None:
|
||||
assert s2.inactivity_warn_stages == [] # 空=不推
|
||||
s3 = Settings(INACTIVITY_WARN_DAYS_BEFORE="2,20,7,2", INACTIVITY_RESET_DAYS=15)
|
||||
assert s3.inactivity_warn_stages == [7, 2] # 去重 + 丢弃 >=RESET_DAYS(20)
|
||||
|
||||
|
||||
def test_log_notifier_returns_placeholder(caplog) -> None:
|
||||
from app.integrations.notifier import LogNotifier, get_notifier
|
||||
n = get_notifier("log")
|
||||
assert isinstance(n, LogNotifier) and n.channel == "log"
|
||||
status = n.warn(user_id=1, coin=10, cash_cents=20, invite_cash_cents=30, stage=7, days_until_reset=8)
|
||||
assert status == "placeholder"
|
||||
# 未实现通道回退 LogNotifier(占位)
|
||||
assert get_notifier("jpush").channel == "log"
|
||||
|
||||
Reference in New Issue
Block a user