| import json
|
| import threading
|
| from datetime import datetime
|
| import pytz
|
| import config
|
| import api_client
|
|
|
| accounts_data = {}
|
| data_lock = threading.Lock()
|
| shanghai_tz = pytz.timezone(config.SHANGHAI_TZ_STR)
|
|
|
| def parse_accounts():
|
| global accounts_data
|
| if not config.ACCOUNTS_JSON:
|
| print("错误: ACCOUNTS 环境变量未设置。")
|
| return False
|
| try:
|
| accounts_list = json.loads(config.ACCOUNTS_JSON)
|
| if not isinstance(accounts_list, list):
|
| print("错误: ACCOUNTS 环境变量必须是一个 JSON 数组。")
|
| return False
|
|
|
| temp_accounts_data = {}
|
| for acc in accounts_list:
|
| if isinstance(acc, dict) and "email" in acc and "password" in acc:
|
| temp_accounts_data[acc["email"]] = {
|
| "password": acc["password"],
|
| "token": None,
|
| "profile": None,
|
| "last_login_success": None,
|
| "last_profile_success": None,
|
| "last_login_attempt": None,
|
| "last_profile_attempt": None,
|
| "login_error": None,
|
| "profile_error": None,
|
| "cards_info": None,
|
| "last_card_info_success": None,
|
| "last_card_info_attempt": None,
|
| "card_info_error": None,
|
| }
|
| else:
|
| print(f"警告: ACCOUNTS 中的条目格式不正确: {acc}")
|
|
|
| with data_lock:
|
| accounts_data = temp_accounts_data
|
| print(f"成功加载 {len(accounts_data)} 个账户。")
|
| return True
|
| except json.JSONDecodeError:
|
| print("错误: ACCOUNTS 环境变量不是有效的 JSON 格式。")
|
| return False
|
|
|
| def login_and_store_token(email):
|
| global accounts_data
|
| with data_lock:
|
| account_info = accounts_data.get(email)
|
| if not account_info:
|
| print(f"错误: 账户 {email} 未找到。")
|
| return
|
|
|
| password = account_info["password"]
|
| print(f"[{datetime.now(shanghai_tz)}] 尝试为账户 {email} 登录...")
|
|
|
| token, error = api_client.api_login(email, password)
|
|
|
| with data_lock:
|
| accounts_data[email]["last_login_attempt"] = datetime.now(shanghai_tz)
|
| if token:
|
| accounts_data[email]["token"] = token
|
| accounts_data[email]["last_login_success"] = True
|
| accounts_data[email]["login_error"] = None
|
| print(f"[{datetime.now(shanghai_tz)}] 账户 {email} 登录成功。")
|
| else:
|
| accounts_data[email]["token"] = None
|
| accounts_data[email]["last_login_success"] = False
|
| accounts_data[email]["login_error"] = error
|
| print(f"[{datetime.now(shanghai_tz)}] 账户 {email} 登录失败: {error}")
|
|
|
| def fetch_and_store_profile(email):
|
| global accounts_data
|
| with data_lock:
|
| account_info = accounts_data.get(email)
|
| if not account_info:
|
| print(f"错误: 账户 {email} 未找到 (fetch_and_store_profile)。")
|
| return
|
| token = account_info.get("token")
|
|
|
| if not token:
|
| print(f"[{datetime.now(shanghai_tz)}] 账户 {email} 没有有效的 token,跳过获取 Profile。")
|
| with data_lock:
|
| accounts_data[email]["last_profile_attempt"] = datetime.now(shanghai_tz)
|
| accounts_data[email]["last_profile_success"] = False
|
| accounts_data[email]["profile_error"] = "无有效 Token"
|
| accounts_data[email]["profile"] = None
|
| accounts_data[email]["last_card_info_attempt"] = datetime.now(shanghai_tz)
|
| accounts_data[email]["cards_info"] = None
|
| accounts_data[email]["last_card_info_success"] = False
|
| accounts_data[email]["card_info_error"] = "因 Token 为空未尝试"
|
| return
|
|
|
| print(f"[{datetime.now(shanghai_tz)}] 尝试为账户 {email} 获取 Profile...")
|
| profile, error = api_client.get_api_profile(email, token)
|
|
|
| profile_fetch_successful_this_attempt = False
|
| with data_lock:
|
| accounts_data[email]["last_profile_attempt"] = datetime.now(shanghai_tz)
|
| if profile:
|
| accounts_data[email]["profile"] = profile
|
| accounts_data[email]["last_profile_success"] = True
|
| accounts_data[email]["profile_error"] = None
|
| profile_fetch_successful_this_attempt = True
|
| print(f"[{datetime.now(shanghai_tz)}] 账户 {email} 获取 Profile 成功。")
|
| else:
|
| accounts_data[email]["profile"] = None
|
| accounts_data[email]["last_profile_success"] = False
|
| accounts_data[email]["profile_error"] = error
|
| print(f"[{datetime.now(shanghai_tz)}] 账户 {email} 获取 Profile 失败: {error}")
|
| if error and ("token" in error.lower() or "auth" in error.lower() or "登录" in error.lower()):
|
| print(f"[{datetime.now(shanghai_tz)}] 账户 {email} 获取 Profile 失败,疑似 Token 失效,将尝试重新登录。")
|
| accounts_data[email]["token"] = None
|
| accounts_data[email]["last_card_info_attempt"] = datetime.now(shanghai_tz)
|
| accounts_data[email]["cards_info"] = None
|
| accounts_data[email]["last_card_info_success"] = False
|
| accounts_data[email]["card_info_error"] = "因 Profile 获取失败未尝试"
|
| return
|
|
|
| if profile_fetch_successful_this_attempt:
|
| current_token_for_cards = None
|
| with data_lock:
|
| if email in accounts_data:
|
| current_token_for_cards = accounts_data[email].get("token")
|
| else:
|
| print(f"[{datetime.now(shanghai_tz)}] 账户 {email} 在获取卡片信息前数据结构异常,跳过。")
|
| return
|
|
|
|
|
| if not current_token_for_cards:
|
| print(f"[{datetime.now(shanghai_tz)}] 账户 {email} 在获取卡片信息前发现 Token 已失效或被清除,跳过。")
|
| with data_lock:
|
| if email in accounts_data:
|
| accounts_data[email]["last_card_info_attempt"] = datetime.now(shanghai_tz)
|
| accounts_data[email]["cards_info"] = None
|
| accounts_data[email]["last_card_info_success"] = False
|
| accounts_data[email]["card_info_error"] = "因 Token 失效未尝试"
|
| return
|
|
|
| print(f"[{datetime.now(shanghai_tz)}] Profile 获取成功,继续为账户 {email} 获取卡片信息...")
|
| cards_info, card_error = api_client.get_api_card_info(email, current_token_for_cards)
|
|
|
| with data_lock:
|
| if email in accounts_data:
|
| accounts_data[email]["last_card_info_attempt"] = datetime.now(shanghai_tz)
|
| if cards_info:
|
| accounts_data[email]["cards_info"] = cards_info
|
| accounts_data[email]["last_card_info_success"] = True
|
| accounts_data[email]["card_info_error"] = None
|
| print(f"[{datetime.now(shanghai_tz)}] 账户 {email} 获取卡片信息成功。")
|
| elif card_error:
|
| accounts_data[email]["cards_info"] = None
|
| accounts_data[email]["last_card_info_success"] = False
|
| accounts_data[email]["card_info_error"] = card_error
|
| print(f"[{datetime.now(shanghai_tz)}] 账户 {email} 获取卡片信息失败: {card_error}")
|
| else:
|
| accounts_data[email]["cards_info"] = None
|
| accounts_data[email]["last_card_info_success"] = True
|
| accounts_data[email]["card_info_error"] = None
|
| print(f"[{datetime.now(shanghai_tz)}] 账户 {email} 获取卡片信息成功,但无卡片数据。")
|
|
|
| def get_accounts_data_for_display():
|
| with data_lock:
|
| display_data = {}
|
| for email, data in accounts_data.items():
|
| display_data[email] = {
|
| "profile": data.get("profile"),
|
| "last_login_success": data.get("last_login_success"),
|
| "last_profile_success": data.get("last_profile_success"),
|
| "last_login_attempt": data.get("last_login_attempt").isoformat() if data.get("last_login_attempt") else None,
|
| "last_profile_attempt": data.get("last_profile_attempt").isoformat() if data.get("last_profile_attempt") else None,
|
| "login_error": data.get("login_error"),
|
| "profile_error": data.get("profile_error"),
|
| "token_present": bool(data.get("token")),
|
| "cards_info": data.get("cards_info"),
|
| "last_card_info_success": data.get("last_card_info_success"),
|
| "last_card_info_attempt": data.get("last_card_info_attempt").isoformat() if data.get("last_card_info_attempt") else None,
|
| "card_info_error": data.get("card_info_error")
|
| }
|
| return display_data
|
|
|
| def get_all_account_emails():
|
| with data_lock:
|
| return list(accounts_data.keys())
|
|
|
| def get_accounts_from_config():
|
| if not config.ACCOUNTS_JSON:
|
| print("错误: ACCOUNTS 环境变量未设置 (get_accounts_from_config)。")
|
| return []
|
| try:
|
| accounts_list = json.loads(config.ACCOUNTS_JSON)
|
| if not isinstance(accounts_list, list):
|
| print("错误: ACCOUNTS 环境变量必须是一个 JSON 数组 (get_accounts_from_config)。")
|
| return []
|
|
|
| valid_accounts = []
|
| for acc in accounts_list:
|
| if isinstance(acc, dict) and "email" in acc and "password" in acc:
|
| valid_accounts.append({"email": acc["email"], "password": acc["password"]})
|
| else:
|
| print(f"警告: ACCOUNTS 中的条目格式不正确,已跳过: {acc} (get_accounts_from_config)")
|
| return valid_accounts
|
| except json.JSONDecodeError:
|
| print("错误: ACCOUNTS 环境变量不是有效的 JSON 格式 (get_accounts_from_config)。")
|
| return [] |