|
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 [] |