This commit is contained in:
mzl
2026-01-12 16:37:46 +08:00
parent 2398942043
commit 3e8f2acbd1
2 changed files with 181 additions and 26 deletions
+7
View File
@@ -0,0 +1,7 @@
{
"permissions": {
"allow": [
"Bash(docker compose build:*)"
]
}
}
+174 -26
View File
@@ -6,7 +6,7 @@ import asyncio
import json
import os
import subprocess
from datetime import datetime
from datetime import datetime, timedelta
from typing import Dict, List, Optional
from fastapi import FastAPI, HTTPException, BackgroundTasks
from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse
@@ -455,41 +455,189 @@ async def generate_qrcode():
}
@app.get("/api/check-login-status")
async def check_login_status():
"""检查小红书登录状态(直接验证)"""
try:
# 如果浏览器可用,直接使用浏览器验证
if hasattr(app_state, 'browser') and app_state.browser:
try:
page = await app_state.browser.new_page()
await page.goto("https://www.xiaohongshu.com/", timeout=10000)
await asyncio.sleep(2)
# 获取页面cookies
cookies = await page.context.cookies()
page.close()
# 检查是否有小红书相关的session cookie
web_session = None
for cookie in cookies:
if 'web_session' in cookie.get('name', '').lower():
web_session = cookie
break
if web_session and web_session.get('value'):
return {
"success": True,
"message": "已登录小红书",
"logged_in": True
}
else:
return {
"success": False,
"message": "未找到登录状态,请先登录"
}
except Exception as e:
pass
# 如果浏览器不可用,尝试访问登录页面检查
try:
# 使用 requests 作为备选方案
import asyncio
import aiohttp
async with aiohttp.ClientSession() as session:
async with session.get("https://www.xiaohongshu.com/") as response:
if response.status == 200:
# 检查响应中是否有登录相关内容
content = await response.text()
# 如果页面包含登录标识,说明未登录
if any(keyword in content for keyword in ['登录', 'login', 'signin']):
return {
"success": False,
"message": "未找到登录状态,请先登录"
}
# 尝试获取cookies
cookies = session.cookie_jar
if cookies:
return {
"success": True,
"message": "已登录小红书",
"logged_in": True
}
except Exception as e:
# 如果 aiohttp 不可用,跳过此检查
pass
return {
"success": False,
"message": "未找到登录状态,请先登录"
}
except Exception as e:
return {
"success": False,
"message": f"检查登录状态失败: {str(e)}"
}
@app.post("/api/login/verify")
async def verify_login():
"""验证登录状态"""
try:
# 优先检查浏览器的实际登录状态
if hasattr(app_state, 'browser') and app_state.browser:
try:
# 创建新页面检查登录状态
page = await app_state.browser.new_page()
# 访问小红书主页
await page.goto("https://www.xiaohongshu.com/", timeout=10000)
# 等待页面加载
await asyncio.sleep(2)
# 检查页面标题
title = await page.title()
# 如果页面包含"登录"字样,说明未登录
if "登录" in title or "login" in title.lower():
await page.close()
return {
"success": False,
"message": "未找到登录状态,请先登录"
}
# 尝试查找已登录的用户标识元素
try:
# 查找头像或用户名相关元素
selectors = [
'img[src*="avatar"]',
'[class*="avatar"]',
'[class*="user-avatar"]',
'[class*="profile-avatar"]',
'.user-name',
'[class*="username"]'
]
for selector in selectors:
elements = await page.query_selector_all(selector)
if elements:
await page.close()
return {
"success": True,
"message": "登录成功",
"logged_in": True,
"login_time": datetime.now().isoformat(),
"expire_time": (datetime.now() + timedelta(hours=24)).isoformat(),
"expire_in_hours": 24
}
except:
pass
await page.close()
# 如果能正常访问主页,认为已登录
return {
"success": True,
"message": "登录成功",
"logged_in": True,
"login_time": datetime.now().isoformat(),
"expire_time": (datetime.now() + timedelta(hours=24)).isoformat(),
"expire_in_hours": 24
}
except Exception as e:
# 如果浏览器访问失败,回退到本地文件检查
pass
# 检查本地登录状态文件(兼容处理)
auth_file = os.path.join(config.DATA_DIR, "auth_state.json")
if not os.path.exists(auth_file):
if os.path.exists(auth_file):
with open(auth_file, 'r', encoding='utf-8') as f:
auth_data = json.load(f)
# 检查登录是否过期
login_time = auth_data.get("login_time")
expire_time = auth_data.get("expire_time")
current_time = datetime.now().isoformat()
if expire_time and current_time > expire_time:
# 登录已过期,清除状态
os.remove(auth_file)
return {
"success": False,
"message": "登录已过期,请重新登录"
}
return {
"success": False,
"message": "未找到登录状态,请先登录"
}
with open(auth_file, 'r', encoding='utf-8') as f:
auth_data = json.load(f)
# 检查登录是否过期
login_time = auth_data.get("login_time")
expire_time = auth_data.get("expire_time")
current_time = datetime.now().isoformat()
if expire_time and current_time > expire_time:
# 登录已过期,清除状态
os.remove(auth_file)
return {
"success": False,
"message": "登录已过期,请重新登录"
"success": True,
"message": "登录成功",
"logged_in": True,
"login_time": login_time,
"expire_time": expire_time,
"expire_in_hours": 24
}
return {
"success": True,
"message": "登录成功",
"logged_in": True,
"login_time": login_time,
"expire_time": expire_time,
"expire_in_hours": 24
"success": False,
"message": "未找到登录状态,请先登录"
}
except Exception as e: