feat(priority): group priority changed notifications by target group and fetch remote account details

This commit is contained in:
liumangmang
2026-07-01 09:00:29 +08:00
parent 6065e824e3
commit fe40fcd4c9
3 changed files with 246 additions and 10 deletions
+67 -6
View File
@@ -239,16 +239,34 @@ def build_rate_priority_map(db: Session, upstream_ids: set[int]) -> dict[str, in
return {key: rate_to_priority[rate] for key, rate in group_rates.items()}
def _priority_result(row, new_priority: int | None, status: str, message: str) -> dict:
"""构建统一的优先级同步结果 dict。"""
def _priority_result(
row,
new_priority: int | None,
status: str,
message: str,
account_name: str | None = None,
old_priority: Any = None,
source_rate: float | None = None,
) -> dict:
"""构建统一的优先级同步结果 dict,支持丰富的展示和后向兼容性。"""
tg_id = row.imported_target_group_id or row.group_id
tg_name = row.imported_target_group_name or tg_id
return {
# 兼容旧字段
"account_id": row.imported_account_id,
"group_id": row.group_id,
"upstream_id": row.upstream_id,
"old_priority": None,
"old_priority": old_priority,
"new_priority": new_priority,
"status": status,
"message": message,
# 新增增强型字段
"target_group_id": tg_id,
"target_group_name": tg_name,
"account_name": account_name or row.imported_account_id,
"source_group_id": row.group_id,
"source_group_name": row.group_name or row.group_id,
"source_rate": source_rate,
}
@@ -529,12 +547,32 @@ def sync_account_priorities_for_upstream(
auth_config=json.loads(website.auth_config_json or "{}"),
timeout=float(website.timeout_seconds),
) as client:
# 尽量拉取目标网站账号列表以获取账号名称和旧 priority,失败不阻断
account_info_map: dict[str, dict[str, Any]] = {}
try:
remote_accounts = client.list_accounts() or []
for acc in remote_accounts:
acc_id = _extract_id(acc)
if acc_id:
account_info_map[str(acc_id)] = {
"name": acc.get("name") or acc.get("account_name") or str(acc_id),
"priority": acc.get("priority"),
}
except Exception as e:
logger.warning("failed to fetch remote accounts for website %s: %s", wid, e)
for comp_rows in competitive_buckets.values():
for row in comp_rows:
account_id = row.imported_account_id
new_priority = priority_assignment.get(account_id)
if new_priority is None:
continue
acc_info = account_info_map.get(str(account_id)) or {}
acc_name = acc_info.get("name") or str(account_id)
old_prio = acc_info.get("priority")
src_rate = raw_rate_map.get(f"{row.upstream_id}:{row.group_id}")
try:
client.update_account(account_id, {"priority": new_priority})
logger.info(
@@ -544,7 +582,15 @@ def sync_account_priorities_for_upstream(
row.imported_target_group_id or row.group_id, new_priority,
)
site_results.append(
_priority_result(row, new_priority, "success", f"优先级已更新为 {new_priority}")
_priority_result(
row,
new_priority,
"success",
f"优先级已更新为 {new_priority}",
account_name=acc_name,
old_priority=old_prio,
source_rate=src_rate,
)
)
except Exception as exc:
logger.warning(
@@ -552,14 +598,29 @@ def sync_account_priorities_for_upstream(
account_id, wid, exc,
)
site_results.append(
_priority_result(row, new_priority, "failed", str(exc))
_priority_result(
row,
new_priority,
"failed",
str(exc),
account_name=acc_name,
old_priority=old_prio,
source_rate=src_rate,
)
)
except Exception as exc:
logger.warning("failed to connect website %s for account priority sync: %s", wid, exc)
for comp_rows in competitive_buckets.values():
for row in comp_rows:
src_rate = raw_rate_map.get(f"{row.upstream_id}:{row.group_id}")
site_results.append(
_priority_result(row, None, "failed", f"连接网站失败: {exc}")
_priority_result(
row,
None,
"failed",
f"连接网站失败: {exc}",
source_rate=src_rate,
)
)
# 只发送有实际成功/失败的通知(不包含单账号跳过项)
+34 -4
View File
@@ -79,11 +79,41 @@ def format_dingtalk_priority_changed(
f"- **摘要**{success} 更新 / {failed} 失败 / {skipped} 跳过",
"",
]
# 按目标分组聚合
from collections import defaultdict
groups = defaultdict(list)
for u in updates:
emoji = {"success": "", "failed": "", "skipped": "⏭️"}.get(u.get("status", ""), "")
gid = u.get("group_id", "?")
priority = u.get("new_priority", "")
lines.append(f"{emoji} `{gid}` → priority={priority}")
tg_name = u.get("target_group_name") or u.get("target_group_id") or u.get("group_id") or "未知目标分组"
groups[tg_name].append(u)
for tg_name, items in groups.items():
lines.append(f"目标分组:{tg_name}")
for u in items:
emoji = {"success": "", "failed": "", "skipped": "⏭️"}.get(u.get("status", ""), "")
acc_name = u.get("account_name") or u.get("account_id") or "未知账号"
acc_id = u.get("account_id") or "未知ID"
old_p = u.get("old_priority")
old_p_str = "未知" if old_p in (None, "", "未知") else str(old_p)
new_p = u.get("new_priority")
new_p_str = "未知" if new_p in (None, "", "未知") else str(new_p)
src_group = u.get("source_group_name") or u.get("source_group_id") or "未知来源"
rate = u.get("source_rate")
rate_str = str(rate) if rate is not None else ""
line = f"- {emoji} {acc_name}(账号ID {acc_id}):old={old_p_str} → new={new_p_str},来源分组={src_group},倍率={rate_str}"
if u.get("status") == "failed" and u.get("message"):
line += f",原因={u.get('message')}"
lines.append(line)
lines.append("")
while lines and not lines[-1]:
lines.pop()
return {
"msgtype": "markdown",
"markdown": {