today_spend_query.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. """Read-only Tencent daily spend summaries for Feishu commands."""
  2. from __future__ import annotations
  3. import logging
  4. from datetime import datetime
  5. from typing import Any
  6. from operator_commands import (
  7. SCOPE_ACCOUNTS,
  8. SCOPE_ALL,
  9. SCOPE_AUTOMATION,
  10. ParsedCommand,
  11. )
  12. from storage import load_all_spend_accounts, load_automation_spend_accounts
  13. from tencent_client import TencentClient
  14. logger = logging.getLogger("tencent_realtime_control.today_spend")
  15. def _select_accounts(parsed: ParsedCommand) -> tuple[str, list[int]]:
  16. all_accounts = {
  17. int(row["account_id"]) for row in load_all_spend_accounts()
  18. }
  19. if parsed.scope_type == SCOPE_ALL:
  20. return "全部账户", sorted(all_accounts)
  21. if parsed.scope_type == SCOPE_AUTOMATION:
  22. automation_ids = {
  23. int(row["account_id"]) for row in load_automation_spend_accounts()
  24. }
  25. return "自动化账户", sorted(automation_ids & set(all_accounts))
  26. if parsed.scope_type == SCOPE_ACCOUNTS:
  27. missing = [value for value in parsed.account_ids if value not in all_accounts]
  28. if missing:
  29. raise ValueError(f"账户不在启用白名单: {missing}")
  30. return "指定账户", list(parsed.account_ids)
  31. raise ValueError(f"不支持的今日消耗查询范围: {parsed.scope_type}")
  32. def query_today_spend(
  33. parsed: ParsedCommand,
  34. *,
  35. now: datetime,
  36. tencent: TencentClient | None = None,
  37. ) -> dict[str, Any]:
  38. scope_label, account_ids = _select_accounts(parsed)
  39. if not account_ids:
  40. raise ValueError(f"{scope_label}范围内没有可查询账户")
  41. results: list[dict[str, int]] = []
  42. failed_account_ids: list[int] = []
  43. client = tencent or TencentClient()
  44. for account_id in account_ids:
  45. try:
  46. results.append(
  47. client.get_today_account_metrics(account_id, now.date())
  48. )
  49. except Exception:
  50. failed_account_ids.append(account_id)
  51. logger.exception("Today spend query failed account=%s", account_id)
  52. return {
  53. "scope_label": scope_label,
  54. "data_date": now.date(),
  55. "queried_at": now,
  56. "account_count": len(account_ids),
  57. "successful_account_count": len(results),
  58. "failed_account_count": len(failed_account_ids),
  59. "spending_account_count": sum(
  60. 1 for row in results if int(row.get("cost_fen") or 0) > 0
  61. ),
  62. "cost_fen": sum(int(row.get("cost_fen") or 0) for row in results),
  63. "impressions": sum(int(row.get("impressions") or 0) for row in results),
  64. "clicks": sum(int(row.get("clicks") or 0) for row in results),
  65. "conversions": sum(int(row.get("conversions") or 0) for row in results),
  66. "complete": not failed_account_ids,
  67. "failed_account_ids": failed_account_ids,
  68. }