Files
server-core/scripts/db/set_sms_config.py
T

105 lines
4.3 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""短信生态配置写入脚本(迁移自 PineSoundServer .env)。
把阿里云凭据/签名/区域与 PineSound 短信模板(仅本项目需要的 T1 登录)写入
system_configs 表:
- sms.provider -> aliyun
- sms.aliyun -> 凭据/签名/区域(与 PineSoundServer .env 完全一致:
ACCESS_KEY_ID / ACCESS_KEY_SECRET / REGION_ID=cn-qingdao /
SIGN_NAME=派音人工智能)
- sms.template.login -> SMS_510980133PineSound T1 登录验证码,变量 code)
- sms.template.register -> SMS_510980133(本项目注册=手机号登录一体,复用 T1)
PineSound 其余模板(修改密码/绑定手机/找回密码/注销/充值/内测)本项目当前业务
未使用,不迁移;notification / order_status / appointment 场景 PineSound 无匹配
模板,保持留空(stub 打印,不阻断业务)。
用法:
python scripts/db/set_sms_config.py # 实际执行
python scripts/db/set_sms_config.py --dry-run # 只预览不写库
"""
from __future__ import annotations
import argparse
import asyncio
from pathlib import Path
from dotenv import load_dotenv
load_dotenv(Path(__file__).resolve().parent.parent.parent / ".env")
from sqlalchemy import text # noqa: E402
from app.infrastructure.db import AsyncSessionLocal # noqa: E402
from app.infrastructure.repositories import utcnow_iso # noqa: E402
# 与 PineSoundServer .env 完全一致的阿里云短信配置
ALIYUN_CONFIG = {
"access_key_id": "LTAI5t6ZU2Nf8qbGpEpn7bzN",
"access_key_secret": "lnNkxiXvNVsCPdc7hVZSXz6goOz8YJ",
"sign_name": "派音人工智能",
"region_id": "cn-qingdao",
"endpoint": "dysmsapi.aliyuncs.com",
}
# key -> (value, description);幂等覆盖:已存在的键也更新为 PineSound 配置。
SMS_CONFIGS: list[tuple[str, str, str]] = [
("sms.provider", "aliyun", "短信 providerstub|aliyun"),
("sms.aliyun",
__import__("json").dumps(ALIYUN_CONFIG, ensure_ascii=False),
"阿里云短信总配置(与 PineSoundServer .env 一致)"),
("sms.template.login",
'{"template_id":"SMS_510980133","variables":["code"]}',
"登录验证码模板(PineSound T1:验证码 code,5分钟有效,请勿泄露)"),
("sms.template.register",
'{"template_id":"SMS_510980133","variables":["code"]}',
"注册验证码模板(本项目注册=手机号登录一体,复用 T1)"),
("sms.template.notification",
'{"template_id":"","variables":[]}',
"通知提醒模板(PineSound 无匹配模板,暂留空)"),
("sms.template.order_status",
'{"template_id":"","variables":["order_no","status"]}',
"订单状态变动模板(PineSound 无匹配模板,暂留空)"),
("sms.template.appointment",
'{"template_id":"","variables":["service_name","schedule_at","contact"]}',
"服务预约模板(PineSound 无匹配模板,暂留空)"),
]
async def main(dry_run: bool) -> int:
now = utcnow_iso()
async with AsyncSessionLocal() as session:
for key, value, description in SMS_CONFIGS:
exists = (
await session.execute(
text("SELECT `key` FROM system_configs WHERE `key` = :k"),
{"k": key},
)
).scalar_one_or_none()
if exists:
sql = text(
"UPDATE system_configs SET `value` = :v, description = :d, "
"updated_at = :now WHERE `key` = :k"
)
else:
sql = text(
"INSERT INTO system_configs (`key`, `value`, `description`, "
"updated_at) VALUES (:k, :v, :d, :now)"
)
if dry_run:
print(f"[dry-run] {'UPDATE' if exists else 'INSERT'} {key} = {value}")
continue
await session.execute(sql, {"k": key, "v": value, "d": description, "now": now})
if not dry_run:
await session.commit()
return 0
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="写入短信生态配置(PineSound 迁移)")
parser.add_argument("--dry-run", action="store_true", help="只预览不写库")
args = parser.parse_args()
raise SystemExit(asyncio.run(main(args.dry_run)))