account_stats.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #!/usr/bin/env python3
  2. import sqlite3
  3. import sys
  4. from pathlib import Path
  5. from datetime import datetime
  6. # --- 配置 ---
  7. BASE_DIR = Path(__file__).resolve().parent.parent
  8. DB_PATH = BASE_DIR / "data.sqlite3"
  9. # --- 配置结束 ---
  10. def get_db_connection():
  11. """建立并返回数据库连接,如果数据库不存在则退出。"""
  12. if not DB_PATH.exists():
  13. print(f"错误: 数据库文件未找到: {DB_PATH}", file=sys.stderr)
  14. sys.exit(1)
  15. try:
  16. conn = sqlite3.connect(DB_PATH)
  17. conn.row_factory = sqlite3.Row
  18. return conn
  19. except sqlite3.Error as e:
  20. print(f"数据库连接错误: {e}", file=sys.stderr)
  21. sys.exit(1)
  22. def check_table_and_columns(conn: sqlite3.Connection):
  23. """检查 'accounts' 表和必要的列是否存在。"""
  24. try:
  25. cursor = conn.execute("PRAGMA table_info(accounts)")
  26. columns = [row['name'] for row in cursor.fetchall()]
  27. if not columns:
  28. print("错误: 'accounts' 表不存在。", file=sys.stderr)
  29. sys.exit(1)
  30. required_cols = ['id', 'label', 'enabled', 'success_count', 'error_count', 'last_refresh_status', 'last_refresh_time']
  31. missing_cols = [col for col in required_cols if col not in columns]
  32. if missing_cols:
  33. print(f"错误: 'accounts' 表缺少以下列: {', '.join(missing_cols)}", file=sys.stderr)
  34. sys.exit(1)
  35. except sqlite3.Error as e:
  36. print(f"检查表结构时出错: {e}", file=sys.stderr)
  37. sys.exit(1)
  38. def gather_stats():
  39. """连接数据库,查询并打印全面的账户统计信息。"""
  40. conn = get_db_connection()
  41. check_table_and_columns(conn)
  42. try:
  43. accounts = conn.execute("SELECT * FROM accounts ORDER BY created_at DESC").fetchall()
  44. except sqlite3.Error as e:
  45. print(f"查询账户时出错: {e}", file=sys.stderr)
  46. conn.close()
  47. sys.exit(1)
  48. total_accounts = len(accounts)
  49. if total_accounts == 0:
  50. print("数据库中没有找到任何账户。")
  51. conn.close()
  52. return
  53. # --- 汇总统计 ---
  54. enabled_accounts = [acc for acc in accounts if acc['enabled'] == 1]
  55. disabled_accounts = [acc for acc in accounts if acc['enabled'] == 0]
  56. refresh_failed_accounts = [acc for acc in accounts if acc['last_refresh_status'] == 'failed']
  57. never_used_accounts = [acc for acc in accounts if acc['success_count'] == 0]
  58. error_accounts = [acc for acc in accounts if acc['error_count'] > 0]
  59. total_success_count = sum(acc['success_count'] for acc in accounts)
  60. print("--- 账户统计摘要 ---")
  61. print(f"总账户数: {total_accounts}")
  62. print(f" - 启用中: {len(enabled_accounts)}")
  63. print(f" - 已禁用: {len(disabled_accounts)}")
  64. print("-" * 20)
  65. print(f"Token刷新失败数: {len(refresh_failed_accounts)}")
  66. print(f"从未使用过的账户数: {len(never_used_accounts)}")
  67. print(f"有错误记录的账户数: {len(error_accounts)}")
  68. print(f"所有账户总成功调用次数: {total_success_count}")
  69. print("-" * 20)
  70. # --- 详细列表 ---
  71. print("\n--- 账户详细列表 ---")
  72. header = "| {:<8s} | {:<6s} | {:<15s} | {:<5s} | {:<5s} | {:<12s} | {:<20s} |".format(
  73. "状态", "启用", "标签 (Label)", "成功", "错误", "刷新状态", "最后刷新时间"
  74. )
  75. print(header)
  76. print("-" * len(header))
  77. for acc in accounts:
  78. # 状态 emoji
  79. status_icon = "✅" if acc['enabled'] else "❌"
  80. if acc['last_refresh_status'] == 'failed':
  81. status_icon = "⚠️"
  82. # 格式化输出
  83. enabled_str = "是" if acc['enabled'] else "否"
  84. label = acc['label'] if acc['label'] else "(无)"
  85. # 截断过长的标签
  86. if len(label) > 15:
  87. label = label[:12] + "..."
  88. last_refresh_time = acc['last_refresh_time'] if acc['last_refresh_time'] else "从未"
  89. print("| {:<10s} | {:<8s} | {:<15s} | {:<5d} | {:<5d} | {:<12s} | {:<20s} |".format(
  90. status_icon,
  91. enabled_str,
  92. label,
  93. acc['success_count'],
  94. acc['error_count'],
  95. acc['last_refresh_status'],
  96. last_refresh_time
  97. ))
  98. print("-" * len(header))
  99. conn.close()
  100. def main():
  101. """脚本主入口"""
  102. gather_stats()
  103. sys.exit(0)
  104. if __name__ == "__main__":
  105. main()