This commit is contained in:
theliu
2026-04-26 20:05:33 +08:00
commit 5ff0c575a1
21 changed files with 2507 additions and 0 deletions
+114
View File
@@ -0,0 +1,114 @@
import hashlib
import requests
from flask import session, redirect, url_for, request
from functools import wraps
LOGIN_URL = "https://api.infi.cn/board/user/nc/accountLogin"
USER_API = "https://api.infi.cn/bsg/user/getMyInfo"
def infi_login(account, password):
"""使用英飞API登录"""
try:
login_data = {
"account": account,
"passwd": hashlib.md5(password.encode()).hexdigest(),
"loginOriginType": 1
}
login_response = requests.post(
LOGIN_URL,
json=login_data,
headers={"Content-Type": "application/json"},
timeout=10
)
print(f"[debug] infi_login: LOGIN_URL status={login_response.status_code}")
print(f"[debug] infi_login: LOGIN_URL body={login_response.text[:1000]}")
if login_response.status_code != 200:
return None, f"API请求失败,HTTP {login_response.status_code}"
try:
data = login_response.json()
except ValueError:
print("[debug] infi_login: 无法解析登录响应为 JSON", login_response.text[:1000])
return None, "无法解析登录响应为 JSON"
# 兼容不同的返回格式:优先从 obj.token 拿 token,其次尝试顶层 token 或 obj 为字符串的情况
token = None
if isinstance(data, dict):
obj = data.get('obj')
if isinstance(obj, dict) and obj.get('token'):
token = obj.get('token')
elif isinstance(obj, str) and obj:
token = obj
elif data.get('token'):
token = data.get('token')
if not token:
# 如果存在 code/msg,把它们返回以便排查
code = data.get('code') if isinstance(data, dict) else None
msg = data.get('msg') if isinstance(data, dict) else None
detail = f" code={code}" if code is not None else ""
print(f"[debug] infi_login: 未找到 token,响应 data={data}")
if msg:
return None, f"登录失败: {msg}{detail}"
return None, f"登录失败:未在响应中找到 token。响应: {data}"
# 获取用户信息
user_response = requests.post(
USER_API,
headers={
"access-token": token,
"Origin": "https://infi.cn",
"Content-Type": "application/json"
},
timeout=10
)
print(f"[debug] infi_login: USER_API status={user_response.status_code}")
print(f"[debug] infi_login: USER_API body={user_response.text[:1000]}")
if user_response.status_code != 200:
body = user_response.text[:1000]
return None, f"获取用户信息失败,HTTP {user_response.status_code} 响应: {body}"
try:
user_data = user_response.json()
except ValueError:
print("[debug] infi_login: 无法解析用户信息响应为 JSON", user_response.text[:1000])
return None, "无法解析用户信息响应为 JSON"
# 兼容不同返回格式:服务端有时使用 code==0 表示成功
if isinstance(user_data, dict) and user_data.get('code') is not None and user_data.get('code') not in (0, 200):
print(f"[debug] infi_login: user_data indicates failure: {user_data}")
return None, f"获取用户信息失败: {user_data.get('msg', '')} 响应: {user_data}"
user_obj = None
if isinstance(user_data, dict):
user_obj = user_data.get('obj') or user_data
return {
'token': token,
'user_info': user_obj
}, None
except Exception as e:
# 针对网络/DNS 解析类错误返回更有帮助的提示
msg = str(e)
if 'NameResolutionError' in msg or 'Failed to resolve' in msg or 'Max retries exceeded' in msg:
return None, (
"网络错误:无法解析 api.infi.cn(DNS)。请检查网络连接、DNS 或代理设置。"
" 可尝试命令:\n 1) `nslookup api.infi.cn`\n 2) `ping api.infi.cn`\n"
" 或切换网络/使用 VPN、设置正确的 `HTTP(S)_PROXY` 环境变量。"
)
return None, f"登录异常: {msg}"
def login_required(f):
"""登录装饰器"""
@wraps(f)
def decorated_function(*args, **kwargs):
if 'user_account' not in session:
return redirect(url_for('login'))
return f(*args, **kwargs)
return decorated_function