feat(douyu): 和平小店绑定功能(生成绑定二维码/查询绑定信息)
- activity_client: xpd_bind_qr(roleParam 签发 livelink 绑定链接, 微信扫码进小程序绑定) + xpd_bind_info(bindInfo 查询绑定状态/角色/平台), gameRole 非 dict 边界防护 - runner/service: 注册 get_xpd_bind_qr / query_xpd_bind_info 任务, 回写 xpd_game_name / xpd_bind_status - router: get_xpd_bind_qr 的 url 加入列表接口保留白名单(二维码展示) - 前端: 和平小店面板新增两个按钮, 二维码列支持 get_xpd_bind_qr 展示/放大
This commit is contained in:
@@ -190,7 +190,7 @@ def _sanitize_task_result(result: dict | None, task_type: str, *, include_detail
|
||||
if "limited_goods" in data:
|
||||
data["limited_goods"] = _slim_limited_goods(data.get("limited_goods"))
|
||||
|
||||
if task_type not in {"get_bind_qr", "prepare_esports_bind", "get_esports_bind_qr"}:
|
||||
if task_type not in {"get_bind_qr", "prepare_esports_bind", "get_esports_bind_qr", "get_xpd_bind_qr"}:
|
||||
data.pop("url", None)
|
||||
if task_type not in {"create_elite_qr", "create_esports_qr", "create_gold_qr"}:
|
||||
data.pop("pay_url", None)
|
||||
|
||||
@@ -1076,6 +1076,57 @@ class DouyuBatchRunner:
|
||||
{"role": role, "area_id": area_id},
|
||||
)
|
||||
|
||||
def _execute_get_xpd_bind_qr(
|
||||
self,
|
||||
db: Session,
|
||||
task: DouyuTask,
|
||||
account: Account,
|
||||
cookie: str,
|
||||
config: dict,
|
||||
):
|
||||
"""生成和平小店绑定二维码(微信扫码在小程序内绑定角色)。"""
|
||||
client = self._client(cookie)
|
||||
act_alias = str(config.get("xpd_act_alias") or "").strip()
|
||||
if not act_alias:
|
||||
self._mark_task(db, task, "failed", "请先配置小店活动代号 actAlias")
|
||||
return
|
||||
result = client.xpd_bind_qr(act_alias=act_alias)
|
||||
account.xpd_bind_status = "xpd_bind_qr_ready"
|
||||
account.updated_at = datetime.now(timezone.utc)
|
||||
db.commit()
|
||||
self._mark_task(db, task, "success", "小店绑定二维码已生成", result)
|
||||
|
||||
def _execute_query_xpd_bind_info(
|
||||
self,
|
||||
db: Session,
|
||||
task: DouyuTask,
|
||||
account: Account,
|
||||
cookie: str,
|
||||
config: dict,
|
||||
):
|
||||
"""查询和平小店绑定信息(bindInfo)。"""
|
||||
client = self._client(cookie)
|
||||
act_alias = str(config.get("xpd_act_alias") or "").strip()
|
||||
if not act_alias:
|
||||
self._mark_task(db, task, "failed", "请先配置小店活动代号 actAlias")
|
||||
return
|
||||
result = client.xpd_bind_info(act_alias=act_alias)
|
||||
role_name = str(result.get("role_name") or "")
|
||||
if role_name:
|
||||
account.xpd_game_name = role_name
|
||||
account.xpd_bind_status = "xpd_bound" if result.get("bind_role") else "xpd_not_bound"
|
||||
account.updated_at = datetime.now(timezone.utc)
|
||||
db.commit()
|
||||
status = "已绑定" if result.get("bind_role") else "未绑定"
|
||||
text = str(result.get("role_name") or result.get("nick") or "-")
|
||||
self._mark_task(
|
||||
db,
|
||||
task,
|
||||
"success",
|
||||
f"小店绑定: {status} ({text})",
|
||||
result,
|
||||
)
|
||||
|
||||
def _execute_refresh_xpd_goods(
|
||||
self,
|
||||
db: Session,
|
||||
@@ -2443,6 +2494,8 @@ class DouyuBatchRunner:
|
||||
"query_gold_balance": self._execute_query_gold_balance,
|
||||
"query_exchange_records": self._execute_query_exchange_records,
|
||||
"prefetch_csrf_token": self._execute_prefetch_csrf_token,
|
||||
"get_xpd_bind_qr": self._execute_get_xpd_bind_qr,
|
||||
"query_xpd_bind_info": self._execute_query_xpd_bind_info,
|
||||
"query_xpd_role": self._execute_query_xpd_role,
|
||||
"refresh_xpd_goods": self._execute_refresh_xpd_goods,
|
||||
"query_xpd_balance": self._execute_query_xpd_balance,
|
||||
|
||||
@@ -38,6 +38,8 @@ SUPPORTED_DOUYU_TASK_TYPES = {
|
||||
"refresh_goods": "刷新商品列表",
|
||||
"query_exchange_records": "一键查询兑换记录",
|
||||
"prefetch_csrf_token": "一键获取兑换 CSRF Token",
|
||||
"get_xpd_bind_qr": "生成小店绑定二维码",
|
||||
"query_xpd_bind_info": "查询小店绑定信息",
|
||||
"query_xpd_role": "查询小店绑定角色",
|
||||
"refresh_xpd_goods": "刷新小店商品列表",
|
||||
"query_xpd_balance": "查询小店点券余额",
|
||||
|
||||
@@ -84,6 +84,8 @@ const ESPORTS_QUICK_ACTIONS = [
|
||||
];
|
||||
|
||||
const PEACE_QUICK_ACTIONS = [
|
||||
{ key: 'get_xpd_bind_qr', icon: <QrcodeOutlined /> },
|
||||
{ key: 'query_xpd_bind_info', icon: <SearchOutlined /> },
|
||||
{ key: 'query_xpd_role', icon: <SearchOutlined /> },
|
||||
{ key: 'refresh_xpd_goods', icon: <ReloadOutlined /> },
|
||||
{ key: 'query_xpd_balance', icon: <SearchOutlined /> },
|
||||
@@ -122,6 +124,8 @@ const ESPORTS_TASK_TYPES = new Set([
|
||||
'donate_esports_firework_gift',
|
||||
]);
|
||||
const PEACE_TASK_TYPES = new Set([
|
||||
'get_xpd_bind_qr',
|
||||
'query_xpd_bind_info',
|
||||
'query_xpd_role',
|
||||
'refresh_xpd_goods',
|
||||
'query_xpd_balance',
|
||||
@@ -149,6 +153,7 @@ function resultFlag(result: Record<string, unknown> | null | undefined, key: str
|
||||
function taskQrUrl(task: DouyuTaskItem | null | undefined): string {
|
||||
if (!task) return '';
|
||||
if (task.task_type === 'get_bind_qr') return resultText(task.result, 'url');
|
||||
if (task.task_type === 'get_xpd_bind_qr') return resultText(task.result, 'url');
|
||||
if (['create_elite_qr', 'create_esports_qr', 'create_gold_qr'].includes(task.task_type)) {
|
||||
return resultText(task.result, 'pay_url');
|
||||
}
|
||||
@@ -1323,6 +1328,7 @@ export default function DouyuTasksPage({ handbook }: { handbook: HandbookKind })
|
||||
if (!task) return;
|
||||
if (hasBindQrcode(task)) openQrTask(task);
|
||||
else if (hasPaymentQrcode(task)) openPayTask(task);
|
||||
else if (task.task_type === 'get_xpd_bind_qr') openQrTask(task);
|
||||
else openEsportsBindTask(task);
|
||||
};
|
||||
return (
|
||||
@@ -1442,6 +1448,8 @@ export default function DouyuTasksPage({ handbook }: { handbook: HandbookKind })
|
||||
<span>小店查询</span>
|
||||
</div>
|
||||
<Space direction="vertical" style={{ width: '100%' }} size={6}>
|
||||
{renderActionButton('get_xpd_bind_qr', 'primary')}
|
||||
{renderActionButton('query_xpd_bind_info', 'primary')}
|
||||
{renderActionButton('query_xpd_role', 'primary')}
|
||||
{renderActionButton('query_xpd_balance', 'primary')}
|
||||
{renderActionButton('refresh_xpd_goods')}
|
||||
|
||||
Reference in New Issue
Block a user