375 lines
13 KiB
Python
Executable File
375 lines
13 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Cookie应急处理脚本
|
|
当Cookie失效时,提供详细的恢复指南
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
from datetime import datetime
|
|
import subprocess
|
|
|
|
class CookieEmergencyHandler:
|
|
"""Cookie应急处理器"""
|
|
|
|
def __init__(self):
|
|
self.cookie_file = os.path.expanduser("~/.xiaohongshu-cli/cookies.json")
|
|
self.qqbot = None
|
|
|
|
# 尝试导入QQBot
|
|
try:
|
|
from qqbot_integration import QQBotIntegration
|
|
self.qqbot = QQBotIntegration()
|
|
except:
|
|
print("⚠️ QQBot集成不可用")
|
|
|
|
def diagnose_cookie_issue(self):
|
|
"""诊断Cookie问题"""
|
|
print("🔍 诊断Cookie问题...")
|
|
|
|
issues = []
|
|
|
|
# 1. 检查文件是否存在
|
|
if not os.path.exists(self.cookie_file):
|
|
issues.append({
|
|
'type': 'FILE_MISSING',
|
|
'severity': 'CRITICAL',
|
|
'message': 'Cookie文件不存在',
|
|
'solution': '需要重新获取Cookie'
|
|
})
|
|
return issues
|
|
|
|
# 2. 检查文件权限
|
|
if not os.access(self.cookie_file, os.R_OK):
|
|
issues.append({
|
|
'type': 'PERMISSION_DENIED',
|
|
'severity': 'HIGH',
|
|
'message': 'Cookie文件不可读',
|
|
'solution': '检查文件权限: chmod 644 ~/.xiaohongshu-cli/cookies.json'
|
|
})
|
|
|
|
# 3. 检查文件内容
|
|
try:
|
|
with open(self.cookie_file, 'r', encoding='utf-8') as f:
|
|
cookies = json.load(f)
|
|
|
|
if not isinstance(cookies, dict):
|
|
issues.append({
|
|
'type': 'INVALID_FORMAT',
|
|
'severity': 'HIGH',
|
|
'message': 'Cookie文件格式错误',
|
|
'solution': 'Cookie文件应该是JSON字典格式'
|
|
})
|
|
elif len(cookies) == 0:
|
|
issues.append({
|
|
'type': 'EMPTY_COOKIE',
|
|
'severity': 'HIGH',
|
|
'message': 'Cookie文件为空',
|
|
'solution': '需要重新获取Cookie'
|
|
})
|
|
else:
|
|
print(f"✅ Cookie文件格式正确,包含 {len(cookies)} 个Cookie")
|
|
|
|
# 检查关键Cookie
|
|
key_cookies = ['a1', 'webId', 'web_session', 'x-user-id-creator.xiaohongshu.com']
|
|
missing_keys = []
|
|
|
|
for key in key_cookies:
|
|
if key not in cookies:
|
|
missing_keys.append(key)
|
|
|
|
if missing_keys:
|
|
issues.append({
|
|
'type': 'MISSING_KEY_COOKIES',
|
|
'severity': 'HIGH',
|
|
'message': f'缺少关键Cookie: {", ".join(missing_keys)}',
|
|
'solution': '这些Cookie对于登录至关重要,需要重新获取'
|
|
})
|
|
|
|
except json.JSONDecodeError as e:
|
|
issues.append({
|
|
'type': 'JSON_PARSE_ERROR',
|
|
'severity': 'HIGH',
|
|
'message': f'JSON解析错误: {str(e)}',
|
|
'solution': 'Cookie文件损坏,需要重新获取'
|
|
})
|
|
except Exception as e:
|
|
issues.append({
|
|
'type': 'UNKNOWN_ERROR',
|
|
'severity': 'HIGH',
|
|
'message': f'读取Cookie文件时出错: {str(e)}',
|
|
'solution': '检查文件完整性'
|
|
})
|
|
|
|
# 4. 测试Cookie有效性
|
|
try:
|
|
result = subprocess.run(
|
|
['xhs', 'status', '--json'],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=10
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
issues.append({
|
|
'type': 'XHS_COMMAND_FAILED',
|
|
'severity': 'HIGH',
|
|
'message': f'xhs命令执行失败: {result.stderr[:100]}',
|
|
'solution': '检查xhs-cli安装和配置'
|
|
})
|
|
else:
|
|
data = json.loads(result.stdout)
|
|
if not data.get('ok') or not data.get('data', {}).get('authenticated'):
|
|
issues.append({
|
|
'type': 'COOKIE_INVALID',
|
|
'severity': 'CRITICAL',
|
|
'message': 'Cookie无效或已过期',
|
|
'solution': '需要重新登录小红书获取新Cookie'
|
|
})
|
|
else:
|
|
print(f"✅ Cookie验证通过,用户: {data['data']['user'].get('nickname')}")
|
|
|
|
except subprocess.TimeoutExpired:
|
|
issues.append({
|
|
'type': 'CHECK_TIMEOUT',
|
|
'severity': 'MEDIUM',
|
|
'message': 'Cookie检查超时',
|
|
'solution': '网络问题或xhs-cli响应慢'
|
|
})
|
|
except Exception as e:
|
|
issues.append({
|
|
'type': 'CHECK_ERROR',
|
|
'severity': 'HIGH',
|
|
'message': f'Cookie检查出错: {str(e)}',
|
|
'solution': '检查系统配置'
|
|
})
|
|
|
|
return issues
|
|
|
|
def generate_recovery_guide(self, issues):
|
|
"""生成恢复指南"""
|
|
print("\n📋 生成恢复指南...")
|
|
|
|
guide = "🔧 小红书Cookie恢复指南\n"
|
|
guide += "=" * 50 + "\n\n"
|
|
guide += f"⏰ 生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
|
|
|
|
# 问题摘要
|
|
critical_count = sum(1 for issue in issues if issue['severity'] == 'CRITICAL')
|
|
high_count = sum(1 for issue in issues if issue['severity'] == 'HIGH')
|
|
|
|
guide += f"📊 问题摘要:\n"
|
|
guide += f" 严重问题: {critical_count} 个\n"
|
|
guide += f" 高级问题: {high_count} 个\n"
|
|
guide += f" 总问题数: {len(issues)} 个\n\n"
|
|
|
|
# 详细问题
|
|
guide += "🔍 详细问题:\n"
|
|
for i, issue in enumerate(issues, 1):
|
|
emoji = "🔴" if issue['severity'] in ['CRITICAL', 'HIGH'] else "🟡"
|
|
guide += f"{emoji} 问题 {i}: {issue['type']}\n"
|
|
guide += f" 严重性: {issue['severity']}\n"
|
|
guide += f" 描述: {issue['message']}\n"
|
|
guide += f" 解决方案: {issue['solution']}\n\n"
|
|
|
|
# 恢复步骤
|
|
guide += "🚀 恢复步骤:\n"
|
|
guide += "1. 重新登录小红书\n"
|
|
guide += " - 打开小红书网页版 (https://www.xiaohongshu.com)\n"
|
|
guide += " - 使用账号密码登录\n"
|
|
guide += " - 确保登录状态正常\n\n"
|
|
|
|
guide += "2. 导出Cookie\n"
|
|
guide += " - 安装EditThisCookie浏览器插件\n"
|
|
guide += " - 在小红书页面点击插件图标\n"
|
|
guide += " - 点击'导出'按钮,保存为cookies.txt\n\n"
|
|
|
|
guide += "3. 导入新Cookie\n"
|
|
guide += " cd ~/.nanobot/workspace/skills/xiaohongshu_integration\n"
|
|
guide += " python3 cookie_manager.py import /path/to/cookies.txt --type editthis\n\n"
|
|
|
|
guide += "4. 验证Cookie\n"
|
|
guide += " python3 cookie_manager.py check\n"
|
|
guide += " python3 xiaohongshu_publisher.py check\n\n"
|
|
|
|
guide += "5. 测试发布\n"
|
|
guide += " python3 xiaohongshu_publisher.py test\n\n"
|
|
|
|
# 快速命令
|
|
guide += "⚡ 快速命令:\n"
|
|
guide += " # 诊断问题\n"
|
|
guide += " python3 cookie_emergency_handler.py diagnose\n\n"
|
|
guide += " # 导入Cookie\n"
|
|
guide += " python3 cookie_manager.py import cookies.txt\n\n"
|
|
guide += " # 检查状态\n"
|
|
guide += " python3 cookie_manager.py check\n\n"
|
|
|
|
# 文件位置
|
|
guide += "📁 文件位置:\n"
|
|
guide += " Cookie文件: ~/.xiaohongshu-cli/cookies.json\n"
|
|
guide += " 备份目录: ~/.xiaohongshu-cli/backups/\n"
|
|
guide += " 技能目录: ~/.nanobot/workspace/skills/xiaohongshu_integration/\n"
|
|
|
|
return guide
|
|
|
|
def send_emergency_alert(self, issues):
|
|
"""发送紧急告警"""
|
|
if not self.qqbot:
|
|
print("❌ QQBot不可用,无法发送紧急告警")
|
|
return False
|
|
|
|
print("🔔 发送紧急告警到QQBot...")
|
|
|
|
# 生成告警消息
|
|
critical_issues = [i for i in issues if i['severity'] in ['CRITICAL', 'HIGH']]
|
|
|
|
if not critical_issues:
|
|
print("✅ 无严重问题,无需发送紧急告警")
|
|
return True
|
|
|
|
alert_message = f"发现 {len(critical_issues)} 个严重Cookie问题,需要立即处理!"
|
|
|
|
# 构建详细信息
|
|
cookie_info = {
|
|
'问题数量': f'{len(critical_issues)} 个严重问题',
|
|
'最严重问题': critical_issues[0]['type'],
|
|
'生成时间': datetime.now().strftime('%H:%M:%S'),
|
|
'状态': '需要立即处理'
|
|
}
|
|
|
|
# 发送告警
|
|
return self.qqbot.send_cookie_alert('COOKIE_EXPIRED', alert_message, cookie_info)
|
|
|
|
def create_backup(self):
|
|
"""创建Cookie备份"""
|
|
print("💾 创建Cookie备份...")
|
|
|
|
if not os.path.exists(self.cookie_file):
|
|
print("❌ Cookie文件不存在,无法备份")
|
|
return False
|
|
|
|
try:
|
|
# 使用cookie_manager备份
|
|
from cookie_manager import XiaohongshuCookieManager
|
|
manager = XiaohongshuCookieManager()
|
|
backup_file = manager.backup_current_cookies()
|
|
|
|
if backup_file:
|
|
print(f"✅ Cookie备份成功: {backup_file}")
|
|
return backup_file
|
|
else:
|
|
print("❌ Cookie备份失败")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"❌ 备份失败: {e}")
|
|
|
|
# 手动备份
|
|
backup_dir = os.path.expanduser("~/.xiaohongshu-cli/emergency_backup")
|
|
os.makedirs(backup_dir, exist_ok=True)
|
|
|
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
backup_file = os.path.join(backup_dir, f"cookies_emergency_{timestamp}.json")
|
|
|
|
import shutil
|
|
shutil.copy2(self.cookie_file, backup_file)
|
|
|
|
print(f"✅ 手动备份成功: {backup_file}")
|
|
return backup_file
|
|
|
|
def emergency_recovery(self):
|
|
"""应急恢复流程"""
|
|
print("🚨 执行应急恢复流程...")
|
|
|
|
# 1. 诊断问题
|
|
issues = self.diagnose_cookie_issue()
|
|
|
|
# 2. 创建备份
|
|
backup_file = self.create_backup()
|
|
|
|
# 3. 生成恢复指南
|
|
guide = self.generate_recovery_guide(issues)
|
|
|
|
# 4. 保存指南到文件
|
|
guide_file = f"/tmp/xiaohongshu_recovery_guide_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
|
|
with open(guide_file, 'w', encoding='utf-8') as f:
|
|
f.write(guide)
|
|
|
|
print(f"✅ 恢复指南已保存: {guide_file}")
|
|
|
|
# 5. 发送紧急告警
|
|
if issues:
|
|
self.send_emergency_alert(issues)
|
|
|
|
# 6. 显示指南
|
|
print("\n" + "=" * 70)
|
|
print("应急恢复指南")
|
|
print("=" * 70)
|
|
print(guide[:500] + "...")
|
|
print(f"\n完整指南: {guide_file}")
|
|
|
|
return guide_file
|
|
|
|
def main():
|
|
"""主函数"""
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(description='Cookie应急处理器')
|
|
subparsers = parser.add_subparsers(dest='command', help='命令')
|
|
|
|
# diagnose命令
|
|
subparsers.add_parser('diagnose', help='诊断Cookie问题')
|
|
|
|
# recover命令
|
|
subparsers.add_parser('recover', help='执行应急恢复')
|
|
|
|
# backup命令
|
|
subparsers.add_parser('backup', help='创建Cookie备份')
|
|
|
|
# guide命令
|
|
subparsers.add_parser('guide', help='生成恢复指南')
|
|
|
|
args = parser.parse_args()
|
|
|
|
handler = CookieEmergencyHandler()
|
|
|
|
if args.command == 'diagnose':
|
|
issues = handler.diagnose_cookie_issue()
|
|
if issues:
|
|
print(f"🔍 发现 {len(issues)} 个问题:")
|
|
for issue in issues:
|
|
print(f" {issue['severity']}: {issue['type']} - {issue['message']}")
|
|
else:
|
|
print("✅ 未发现问题,Cookie状态正常")
|
|
|
|
elif args.command == 'recover':
|
|
handler.emergency_recovery()
|
|
|
|
elif args.command == 'backup':
|
|
handler.create_backup()
|
|
|
|
elif args.command == 'guide':
|
|
# 模拟一些问题
|
|
test_issues = [
|
|
{
|
|
'type': 'COOKIE_EXPIRED',
|
|
'severity': 'CRITICAL',
|
|
'message': 'Cookie已过期',
|
|
'solution': '重新登录获取新Cookie'
|
|
},
|
|
{
|
|
'type': 'MISSING_KEY_COOKIES',
|
|
'severity': 'HIGH',
|
|
'message': '缺少关键Cookie: a1, webId',
|
|
'solution': '需要完整的Cookie集合'
|
|
}
|
|
]
|
|
guide = handler.generate_recovery_guide(test_issues)
|
|
print(guide)
|
|
|
|
else:
|
|
parser.print_help()
|
|
|
|
if __name__ == "__main__":
|
|
main() |