diff --git a/app/core/config.py b/app/core/config.py index bf27932..0044957 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -169,6 +169,13 @@ class Settings(BaseSettings): # 进程内自动兑换 worker 的检查间隔(秒):每隔这么久醒一次,跨过北京 0 点就跑一轮。 # 默认 600s=10min,即 0 点后最多 10 分钟内兑完(客户端文案已注明「可能存在延迟」)。 AUTO_EXCHANGE_CHECK_INTERVAL_SEC: int = 600 + # === 15 天不活跃清零(app.core.inactivity_reset_worker)=== + INACTIVITY_RESET_ENABLED: bool = False # 总闸,默认关;灰度验证后再开 + INACTIVITY_RESET_DAYS: int = 15 # 不活跃阈值(天),第 (N+1) 日 0 点清 + INACTIVITY_WARN_DAYS_BEFORE: str = "7,2" # 清零前几天各推一次;""=不推。逗号分隔 + INACTIVITY_RESET_RUN_HOUR: int = 3 # 北京时间每日执行点(0-23) + INACTIVITY_NOTIFY_CHANNEL: str = "log" # log(占位) / jpush / sms + INACTIVITY_RESET_CHECK_INTERVAL_SEC: int = 1800 # worker 唤醒间隔(秒) # 免确认收款授权(用户授权免确认模式)的授权结果回调地址,必须公网可访问 HTTPS、不带参数。 # 发起授权 / 首单顺带授权时作为 authorization_notify_url 传给微信。一期不处理回调内容 # (授权状态靠 query 查询兜底),但微信要求该字段非空,故启用免确认前必须配置;留空时免确认相关接口返回未配置。 @@ -189,6 +196,19 @@ class Settings(BaseSettings): """免确认收款授权可用 = 微信支付凭证齐全 + 授权回调地址已配。""" return bool(self.wxpay_configured and self.WXPAY_AUTH_NOTIFY_URL) + @property + def inactivity_warn_stages(self) -> list[int]: + """解析 INACTIVITY_WARN_DAYS_BEFORE → 降序去重的提前天数列表。 + 丢弃非数字 / <=0 / >=RESET_DAYS 的项(空串 → 空列表 = 不推)。""" + out: list[int] = [] + for part in (self.INACTIVITY_WARN_DAYS_BEFORE or "").split(","): + part = part.strip() + if part.isdigit(): + v = int(part) + if 0 < v < self.INACTIVITY_RESET_DAYS and v not in out: + out.append(v) + return sorted(out, reverse=True) + # ===== 穿山甲激励视频(服务端发奖回调)===== # 看完激励视频后穿山甲服务器回调本服务发金币(S2S,客户端被破解也刷不到)。 # 穿山甲后台配置的"奖励校验密钥"(m-key),验签用。每个 GroMore 广告位 m-key 不同(后台各自 diff --git a/tests/test_inactivity_reset.py b/tests/test_inactivity_reset.py index 9a49d14..881c3ea 100644 --- a/tests/test_inactivity_reset.py +++ b/tests/test_inactivity_reset.py @@ -107,3 +107,13 @@ def test_last_active_expr_takes_max_of_baseline_and_events() -> None: finally: db.rollback() db.close() + + +def test_inactivity_warn_stages_parsing() -> None: + from app.core.config import Settings + s = Settings(INACTIVITY_WARN_DAYS_BEFORE="7,2", INACTIVITY_RESET_DAYS=15) + assert s.inactivity_warn_stages == [7, 2] # 降序去重 + s2 = Settings(INACTIVITY_WARN_DAYS_BEFORE="", INACTIVITY_RESET_DAYS=15) + 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)