[patch] DY-token检测逻辑修改 修改本地打包环境路径锁定
This commit is contained in:
@@ -1022,22 +1022,20 @@ class DouYinMessageHandler:
|
||||
try:
|
||||
message = blackboxprotobuf.decode_message(content)[0]
|
||||
|
||||
# 🔥 优化:只记录有效消息类型,过滤无用日志
|
||||
# 首先检查是否是心跳响应(优先处理,减少不必要的解析)
|
||||
if "5" in message:
|
||||
kv_pairs = message["5"]
|
||||
if isinstance(kv_pairs, list):
|
||||
for pair in kv_pairs:
|
||||
if isinstance(pair, dict) and pair.get("1") == b"code" and pair.get("2") == b"0":
|
||||
self._log("💓 心跳响应正常", "DEBUG")
|
||||
return
|
||||
# 解析二进制数据
|
||||
decoded_message_readable = self.decode_binary_data(message)
|
||||
print(f"\n📨 收到消息: {decoded_message_readable}")
|
||||
|
||||
# 解析用户Token(静默处理)
|
||||
user, token = self.code_parse(message=message)
|
||||
if user and token:
|
||||
receiver_id = int(user.split(":")[0])
|
||||
self._init_user_info(receiver_id, token)
|
||||
self._log(f"✅ 获取到用户Token: 用户ID={receiver_id}", "DEBUG")
|
||||
|
||||
print(f"✅ 获取到用户Token: 用户ID={receiver_id}")
|
||||
|
||||
# 获取消息类型
|
||||
msg_type = message.get('1')
|
||||
print(f"📋 消息类型: {msg_type}")
|
||||
|
||||
# 获取内部消息结构
|
||||
inner_msg = message.get('8', {})
|
||||
@@ -1046,37 +1044,48 @@ class DouYinMessageHandler:
|
||||
if isinstance(inner_msg, bytes):
|
||||
try:
|
||||
inner_msg = blackboxprotobuf.decode_message(inner_msg)[0]
|
||||
except Exception:
|
||||
# 无法解析的消息静默忽略
|
||||
print(f"🔄 解析内部消息字节成功")
|
||||
except Exception as e:
|
||||
print(f"⚠️ 无法解析内部消息字节: {e}")
|
||||
return
|
||||
|
||||
if not inner_msg or not isinstance(inner_msg, dict):
|
||||
# 消息结构不完整,静默忽略
|
||||
print("⚠️ 消息结构不完整")
|
||||
return
|
||||
|
||||
# 获取内部消息类型
|
||||
inner_type = inner_msg.get('1')
|
||||
inner_data = inner_msg.get('6', {})
|
||||
|
||||
# 🔥 只处理和记录有意义的消息类型
|
||||
# 首先检查是否是心跳响应
|
||||
if "5" in message:
|
||||
kv_pairs = message["5"]
|
||||
if isinstance(kv_pairs, list):
|
||||
for pair in kv_pairs:
|
||||
if isinstance(pair, dict) and pair.get("1") == b"code" and pair.get("2") == b"0":
|
||||
self._log("💓 心跳响应正常", "DEBUG")
|
||||
return
|
||||
print(f"📋 内部消息类型: {inner_type}")
|
||||
print(f"📋 内部消息数据键: {list(inner_data.keys()) if isinstance(inner_data, dict) else type(inner_data)}")
|
||||
|
||||
# 处理不同类型的消息
|
||||
if inner_type == 610: # Token消息
|
||||
self._log("🔑 处理Token消息", "DEBUG")
|
||||
print("🔑 处理Token消息")
|
||||
self._handle_token_message(inner_data)
|
||||
|
||||
elif inner_type == 500: # 聊天消息(真正的用户消息)
|
||||
# 🔥 只有聊天消息才打印详细日志
|
||||
decoded_message_readable = self.decode_binary_data(message)
|
||||
self._log(f"💬 收到用户消息: {decoded_message_readable}", "INFO")
|
||||
elif inner_type == 500: # 聊天消息
|
||||
print("💬 处理聊天消息")
|
||||
self._handle_chat_message(inner_data, message)
|
||||
|
||||
elif inner_type == 200: # 心跳消息
|
||||
self._log("💓 收到心跳消息", "DEBUG")
|
||||
print("💓 收到心跳消息")
|
||||
|
||||
# 🔥 其他未知消息类型静默忽略,不打印日志
|
||||
else:
|
||||
print(f"❓ 未知内部消息类型: {inner_type}")
|
||||
|
||||
except Exception as e:
|
||||
# 只记录真正的错误,忽略解析失败
|
||||
self._log(f"❌ 处理消息时出错: {e}", "ERROR")
|
||||
print(f"❌ 解析消息时出错: {e}")
|
||||
traceback.print_exc()
|
||||
|
||||
async def _process_pending_message(self, sender_id, message_content):
|
||||
"""处理待发送的消息"""
|
||||
@@ -1286,6 +1295,8 @@ class DouYinMessageHandler:
|
||||
def _extract_message_text(self, msg_content):
|
||||
"""从消息内容中提取文本和图片URL"""
|
||||
try:
|
||||
print("🔍 开始提取消息内容...")
|
||||
|
||||
# 初始化返回结果
|
||||
result = {
|
||||
'text': None,
|
||||
@@ -1300,22 +1311,27 @@ class DouYinMessageHandler:
|
||||
# 方法1: 处理文本消息(从'8'字段获取)
|
||||
text_content = msg_content.get('8')
|
||||
if text_content:
|
||||
print(f"📄 检测到文本内容")
|
||||
if isinstance(text_content, bytes):
|
||||
try:
|
||||
decoded = text_content.decode('utf-8')
|
||||
result['text'] = decoded
|
||||
self._log(f"✅ UTF-8解码成功: {decoded}", "SUCCESS")
|
||||
except UnicodeDecodeError:
|
||||
try:
|
||||
decoded = text_content.decode('gbk')
|
||||
result['text'] = decoded
|
||||
self._log(f"✅ GBK解码成功: {decoded}", "SUCCESS")
|
||||
except:
|
||||
pass
|
||||
self._log("⚠️ 无法解码文本内容", "DEBUG")
|
||||
elif isinstance(text_content, str):
|
||||
result['text'] = text_content
|
||||
self._log(f"✅ 直接使用文本内容: {text_content}")
|
||||
|
||||
# 方法2: 统一处理'9'字段中的数据(包括文本和图片、消息、视频
|
||||
meta_data = msg_content.get('9', [])
|
||||
if meta_data:
|
||||
print(f"🔍 检测到消息元数据")
|
||||
for item in meta_data:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
@@ -1328,13 +1344,17 @@ class DouYinMessageHandler:
|
||||
# 处理所有类型的URL
|
||||
if key == 'avatar_uri':
|
||||
result['avatar'] = value
|
||||
self._log(f"✅ 找到头像URL: {value}", "SUCCESS")
|
||||
elif key == 'imageUrl':
|
||||
result['image_url'] = value
|
||||
self._log(f"✅ 找到图片URL: {value}", "SUCCESS")
|
||||
elif key == 'thumbnailUrl':
|
||||
result['thumbnail_url'] = value
|
||||
self._log(f"✅ 找到缩略图URL: {value}", "SUCCESS")
|
||||
elif key == 'goods_id':
|
||||
goods_id = value
|
||||
result['goods_id'] = goods_id
|
||||
self._log(f"✅ 找到商品ID: {goods_id}", "SUCCESS")
|
||||
elif key == 'msg_render_model':
|
||||
try:
|
||||
video_info = json.loads(value)
|
||||
@@ -1344,17 +1364,22 @@ class DouYinMessageHandler:
|
||||
viedo_url = render_body.get('coverURL')
|
||||
viedo_vid = render_body.get('vid')
|
||||
if viedo_vid and viedo_url:
|
||||
self._log(f"✅ 找到视频原始vid: {viedo_vid}", "SUCCESS")
|
||||
|
||||
# 解析获取视频播放地址
|
||||
play_url = self.parse_video(viedo_vid)
|
||||
if play_url:
|
||||
result['video_url'] = play_url
|
||||
else:
|
||||
# 如果解析失败,使用备用封面图片作为地址
|
||||
# 如果解析失败 在打印对应的日志后 使用备用封面图片作为地址
|
||||
if '\\u0026' in viedo_url:
|
||||
viedo_url = viedo_url.replace('\\u0026', '&')
|
||||
result['video_url'] = viedo_url
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
self._log("⚠️ 使用视频封面作为备选", "WARNING")
|
||||
else:
|
||||
self._log("⚠️ 未找到视频核心id 可能出现新的数据存放地址", "DEBUG")
|
||||
except json.JSONDecodeError as e:
|
||||
self._log(f"解析视频信息失败: {e}", "ERROR")
|
||||
elif key == 'sku_order_id':
|
||||
# 取到了对应的订单号 id
|
||||
order_id = value
|
||||
@@ -1367,6 +1392,7 @@ class DouYinMessageHandler:
|
||||
# 方法3: 兼容处理旧的'9-1'字段(如果存在)
|
||||
image_data = msg_content.get('9-1', []) # 如果没有拿到这个arrayList那么就不需要在对里面的数据进行解析了
|
||||
if image_data != []:
|
||||
print(f"📸 检测到旧的图片数据格式", "DEBUG")
|
||||
for item in image_data:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
@@ -1378,13 +1404,17 @@ class DouYinMessageHandler:
|
||||
|
||||
if key == 'avatar_uri' and not result['avatar']:
|
||||
result['avatar'] = value
|
||||
self._log(f"✅ 找到头像URL: {value}", "SUCCESS")
|
||||
elif key == 'imageUrl' and not result['image_url']:
|
||||
result['image_url'] = value
|
||||
self._log(f"✅ 找到图片URL: {value}", "SUCCESS")
|
||||
elif key == 'thumbnailUrl' and not result['thumbnail_url']:
|
||||
result['thumbnail_url'] = value
|
||||
self._log(f"✅ 找到缩略图URL: {value}", "SUCCESS")
|
||||
elif key == 'goods_id':
|
||||
goods_id = value
|
||||
result['goods_id'] = goods_id
|
||||
self._log(f"✅ 找到商品ID: {goods_id}", "SUCCESS")
|
||||
elif key == 'msg_render_model':
|
||||
try:
|
||||
video_info = json.loads(value)
|
||||
@@ -1394,22 +1424,42 @@ class DouYinMessageHandler:
|
||||
viedo_url = render_body.get('coverURL')
|
||||
viedo_vid = render_body.get('vid')
|
||||
if viedo_vid and viedo_url:
|
||||
self._log(f"✅ 找到视频原始vid: {viedo_vid}", "SUCCESS")
|
||||
|
||||
# 解析获取视频播放地址
|
||||
play_url = self.parse_video(viedo_vid)
|
||||
if play_url:
|
||||
result['video_url'] = play_url
|
||||
else:
|
||||
# 如果解析失败,使用备用封面图片作为地址
|
||||
# 如果解析失败 在打印对应的日志后 使用备用封面图片作为地址
|
||||
if '\\u0026' in viedo_url:
|
||||
viedo_url = viedo_url.replace('\\u0026', '&')
|
||||
result['video_url'] = viedo_url
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
self._log("⚠️ 使用视频封面作为备选", "WARNING")
|
||||
else:
|
||||
self._log("⚠️ 未找到视频核心id 可能出现新的数据存放地址", "DEBUG")
|
||||
except json.JSONDecodeError as e:
|
||||
self._log(f"解析视频信息失败: {e}", "ERROR")
|
||||
elif key == 'sku_order_id':
|
||||
# 取到了对应的订单号 id
|
||||
order_id = value
|
||||
result['order_id'] = order_id
|
||||
|
||||
# 如果都没找到内容,打印调试信息
|
||||
if not any(result.values()):
|
||||
print("🔍 未找到有效内容,打印所有字段:")
|
||||
for key, value in msg_content.items():
|
||||
if isinstance(value, bytes):
|
||||
try:
|
||||
decoded = value.decode('utf-8', errors='ignore')
|
||||
print(f" {key}: {decoded[:100]}...")
|
||||
except:
|
||||
print(f" {key}: [无法解码的字节数据,长度: {len(value)}]")
|
||||
elif isinstance(value, list):
|
||||
print(f" {key}: [列表数据,长度: {len(value)}]")
|
||||
else:
|
||||
print(f" {key}: {value}")
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
@@ -1428,6 +1478,8 @@ class DouYinMessageHandler:
|
||||
def _handle_chat_message(self, message, msg_type):
|
||||
"""处理聊天消息 - 修改版本,支持多种消息类型"""
|
||||
try:
|
||||
self._log(f"🔍 开始解析{message} 消息结构", "DEBUG")
|
||||
|
||||
msg_500 = message.get('500', {})
|
||||
if not msg_500:
|
||||
return
|
||||
@@ -1440,21 +1492,28 @@ class DouYinMessageHandler:
|
||||
inner_msg_type = msg_content.get("6", 0)
|
||||
sender_id = msg_content.get("7", 0)
|
||||
|
||||
self._log(f"📊 内部消息类型: {inner_msg_type}, 发送者ID: {sender_id}", "DEBUG")
|
||||
|
||||
print("会不会到这里来呢")
|
||||
|
||||
# 处理不同类型的消息
|
||||
if inner_msg_type == 1000 and sender_id and sender_id != int(self.cookie['PIGEON_CID']):
|
||||
# 用户文本消息 - 处理AI回复
|
||||
self._log(f"✅ 检测到用户消息 (类型1000),发送者: {sender_id}", "INFO")
|
||||
self._log("✅ 检测到1000状态的有效消息", "INFO")
|
||||
self._handle_user_text_message(msg_content, sender_id)
|
||||
|
||||
elif inner_msg_type == 50002 and sender_id and sender_id != int(self.cookie['PIGEON_CID']):
|
||||
# 系统消息 - 触发token请求
|
||||
self._log(f"✅ 检测到系统消息 (类型50002),发送者: {sender_id}", "DEBUG")
|
||||
self._log("✅ 检测到50002类型的系统消息", "INFO")
|
||||
self._handle_system_message(msg_content, sender_id)
|
||||
|
||||
# 🔥 其他消息类型静默忽略
|
||||
else:
|
||||
# 忽略其他消息
|
||||
self._log(f"🔍 忽略消息类型: {inner_msg_type}", "DEBUG")
|
||||
|
||||
except Exception as e:
|
||||
self._log(f"❌ 处理聊天消息失败: {e}", "ERROR")
|
||||
self._log(f"❌ 错误详情: {traceback.format_exc()}", "DEBUG")
|
||||
|
||||
def _handle_user_text_message(self, msg_content, sender_id):
|
||||
"""处理用户文本消息"""
|
||||
|
||||
@@ -1,57 +1,63 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
生产环境打包脚本 - 自动禁用日志功能
|
||||
Production build script - Automatically disable logging functionality
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
# Ensure script runs in correct directory
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
os.chdir(SCRIPT_DIR)
|
||||
print(f"Working directory: {SCRIPT_DIR}")
|
||||
|
||||
def disable_logging():
|
||||
"""自动禁用所有日志功能"""
|
||||
"""Disable all logging functionality"""
|
||||
print("Disabling logging functionality...")
|
||||
|
||||
# 备份原文件
|
||||
# Backup original files
|
||||
files_to_backup = ['main.py', 'exe_file_logger.py']
|
||||
for file_name in files_to_backup:
|
||||
if os.path.exists(file_name):
|
||||
shutil.copy(file_name, f'{file_name}.backup')
|
||||
print(f"Backed up {file_name}")
|
||||
|
||||
# 1. 修改 main.py - 注释掉日志初始化
|
||||
# 1. Modify main.py - comment out logging initialization
|
||||
if os.path.exists('main.py'):
|
||||
with open('main.py', 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# 注释掉日志相关的导入和初始化
|
||||
# Comment out logging related imports and initialization
|
||||
content = content.replace(
|
||||
'from exe_file_logger import setup_file_logging, log_to_file',
|
||||
'# from exe_file_logger import setup_file_logging, log_to_file # 生产环境禁用'
|
||||
'# from exe_file_logger import setup_file_logging, log_to_file # Production disabled'
|
||||
).replace(
|
||||
'setup_file_logging()',
|
||||
'# setup_file_logging() # 生产环境禁用'
|
||||
'# setup_file_logging() # Production disabled'
|
||||
).replace(
|
||||
'print("文件日志系统已在main.py中初始化")',
|
||||
'# print("文件日志系统已在main.py中初始化") # 生产环境禁用'
|
||||
'# print("文件日志系统已在main.py中初始化") # Production disabled'
|
||||
)
|
||||
|
||||
with open('main.py', 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
print("Disabled logging in main.py")
|
||||
|
||||
# 2. 修改 exe_file_logger.py - 让所有函数变成空操作
|
||||
# 2. Modify exe_file_logger.py - make all functions no-op
|
||||
if os.path.exists('exe_file_logger.py'):
|
||||
with open('exe_file_logger.py', 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# 将 setup_file_logging 函数替换为空函数
|
||||
# Replace setup_file_logging function with empty function
|
||||
content = content.replace(
|
||||
'def setup_file_logging():',
|
||||
'def setup_file_logging():\n """生产环境 - 禁用文件日志"""\n return None\n\ndef setup_file_logging_original():'
|
||||
'def setup_file_logging():\n """Production - Logging disabled"""\n return None\n\ndef setup_file_logging_original():'
|
||||
).replace(
|
||||
'def log_to_file(message):',
|
||||
'def log_to_file(message):\n """生产环境 - 禁用文件日志"""\n pass\n\ndef log_to_file_original(message):'
|
||||
'def log_to_file(message):\n """Production - Logging disabled"""\n pass\n\ndef log_to_file_original(message):'
|
||||
)
|
||||
|
||||
with open('exe_file_logger.py', 'w', encoding='utf-8') as f:
|
||||
@@ -61,37 +67,54 @@ def disable_logging():
|
||||
print("All logging functionality disabled")
|
||||
|
||||
def restore_logging():
|
||||
"""恢复日志功能"""
|
||||
"""Restore logging functionality"""
|
||||
print("Restoring development configuration...")
|
||||
files_to_restore = ['main.py', 'exe_file_logger.py']
|
||||
restored_count = 0
|
||||
|
||||
for file_name in files_to_restore:
|
||||
backup_file = f'{file_name}.backup'
|
||||
if os.path.exists(backup_file):
|
||||
shutil.copy(backup_file, file_name)
|
||||
os.remove(backup_file)
|
||||
print(f"Restored {file_name}")
|
||||
print("All files restored to development configuration")
|
||||
try:
|
||||
if os.path.exists(backup_file):
|
||||
# Ensure target file is writable
|
||||
if os.path.exists(file_name):
|
||||
os.chmod(file_name, 0o666)
|
||||
|
||||
shutil.copy(backup_file, file_name)
|
||||
os.remove(backup_file)
|
||||
print(f"[OK] Restored {file_name}")
|
||||
restored_count += 1
|
||||
else:
|
||||
print(f"[WARN] Backup file not found: {backup_file}")
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Failed to restore {file_name}: {e}")
|
||||
|
||||
if restored_count == len(files_to_restore):
|
||||
print("[OK] All files restored to development configuration")
|
||||
else:
|
||||
print(f"[WARN] Restored {restored_count}/{len(files_to_restore)} files")
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
"""Main function"""
|
||||
print("Production Build Tool (No Logging Version)")
|
||||
print("=" * 60)
|
||||
|
||||
try:
|
||||
# 1. 禁用日志功能
|
||||
# 1. Disable logging functionality
|
||||
disable_logging()
|
||||
|
||||
# 2. 执行打包
|
||||
# 2. Execute build
|
||||
print("\nStarting build...")
|
||||
result = subprocess.run(['python', 'quick_build.py'], capture_output=False)
|
||||
|
||||
if result.returncode == 0:
|
||||
# 验证最终输出(quick_build.py 已统一输出到 MultiPlatformGUI)
|
||||
# Verify output (quick_build.py outputs to MultiPlatformGUI)
|
||||
if os.path.exists('dist/MultiPlatformGUI'):
|
||||
print("\nProduction build completed successfully!")
|
||||
print("Output directory: dist/MultiPlatformGUI/")
|
||||
print("All logging disabled - client will not generate log files")
|
||||
|
||||
# 验证关键文件
|
||||
# Verify key files
|
||||
exe_path = 'dist/MultiPlatformGUI/main.exe'
|
||||
if os.path.exists(exe_path):
|
||||
size = os.path.getsize(exe_path) / 1024 / 1024 # MB
|
||||
@@ -107,8 +130,8 @@ def main():
|
||||
print(f"ERROR: Build process error: {e}")
|
||||
|
||||
finally:
|
||||
# 3. 恢复日志功能(用于开发)
|
||||
print("\nRestoring development configuration...")
|
||||
# 3. Restore logging functionality (for development)
|
||||
print()
|
||||
restore_logging()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
|
||||
Reference in New Issue
Block a user