[v11] 动态方法名调用,驼峰+小写双重尝试
This commit is contained in:
646
verify_v11.py
Normal file
646
verify_v11.py
Normal file
@@ -0,0 +1,646 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
工作手机 SDK - 完整验证脚本 v11
|
||||
Frida 16.5.6: 用 getattr(ex, 'getAccountInfo')() 原始驼峰调用
|
||||
"""
|
||||
|
||||
import frida
|
||||
import json
|
||||
import time
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
|
||||
PHONE_IP = '192.168.110.80'
|
||||
JS_FILE = '/Users/karuo/Documents/开发/2、私域银行/工作手机/sdk/agent/hook/wechat_api_v8_fix.js'
|
||||
SCREENSHOT_DIR = '/Users/karuo/Documents/开发/2、私域银行/工作手机/开发文档/6、测试'
|
||||
|
||||
results = {}
|
||||
errors = []
|
||||
passed_count = 0
|
||||
total_count = 0
|
||||
|
||||
def screenshot(name):
|
||||
path = f'{SCREENSHOT_DIR}/v11_{name}.png'
|
||||
try:
|
||||
subprocess.run(['adb', '-s', f'{PHONE_IP}:5555', 'shell',
|
||||
f'screencap -p /sdcard/v11_{name}.png'], timeout=5, capture_output=True)
|
||||
subprocess.run(['adb', '-s', f'{PHONE_IP}:5555', 'pull',
|
||||
f'/sdcard/v11_{name}.png', path], timeout=10, capture_output=True)
|
||||
print(f" 📸 截图: v11_{name}.png")
|
||||
except Exception as e:
|
||||
print(f" ⚠️ 截图失败: {e}")
|
||||
|
||||
def wake_phone():
|
||||
subprocess.run(['adb', '-s', f'{PHONE_IP}:5555', 'shell', 'input keyevent 26'], timeout=5, capture_output=True)
|
||||
time.sleep(0.5)
|
||||
subprocess.run(['adb', '-s', f'{PHONE_IP}:5555', 'shell', 'input swipe 540 1800 540 900'], timeout=5, capture_output=True)
|
||||
time.sleep(0.5)
|
||||
|
||||
def get_wechat_pid():
|
||||
result = subprocess.run(
|
||||
['adb', '-s', f'{PHONE_IP}:5555', 'shell', 'ps -A'],
|
||||
capture_output=True, text=True, timeout=5
|
||||
)
|
||||
for line in result.stdout.split('\n'):
|
||||
if 'com.tencent.mm' in line and ':push' not in line and ':sandbox' not in line and ':tools' not in line and ':appbrand' not in line:
|
||||
parts = line.split()
|
||||
if len(parts) >= 2:
|
||||
try:
|
||||
return int(parts[1])
|
||||
except:
|
||||
pass
|
||||
return None
|
||||
|
||||
def call(ex, method_name, *args):
|
||||
"""动态调用exports_sync方法,自动处理Frida 16.x的方法名问题"""
|
||||
# 先尝试直接调用(驼峰)
|
||||
try:
|
||||
return getattr(ex, method_name)(*args)
|
||||
except Exception as e1:
|
||||
# 再尝试全小写
|
||||
try:
|
||||
return getattr(ex, method_name.lower())(*args)
|
||||
except Exception as e2:
|
||||
# 再尝试通过script.post方式
|
||||
raise Exception(f"驼峰({e1}) | 小写({e2})")
|
||||
|
||||
def test(name, func):
|
||||
global passed_count, total_count
|
||||
total_count += 1
|
||||
try:
|
||||
r = func()
|
||||
passed_count += 1
|
||||
return r
|
||||
except Exception as e:
|
||||
errors.append(f"{name}: {str(e)[:100]}")
|
||||
print(f" ❌ {name}: {str(e)[:100]}")
|
||||
return None
|
||||
|
||||
def main():
|
||||
global passed_count, total_count
|
||||
|
||||
print("=" * 70)
|
||||
print("🔥 工作手机 SDK 完整验证 v11 (动态方法名调用)")
|
||||
print(f"时间: {time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print("=" * 70)
|
||||
|
||||
wake_phone()
|
||||
|
||||
subprocess.run(['adb', '-s', f'{PHONE_IP}:5555', 'forward', 'tcp:27042', 'tcp:27042'],
|
||||
timeout=5, capture_output=True)
|
||||
|
||||
pid = get_wechat_pid()
|
||||
if not pid:
|
||||
print("❌ 微信未运行,启动微信...")
|
||||
subprocess.run(['adb', '-s', f'{PHONE_IP}:5555', 'shell',
|
||||
'monkey -p com.tencent.mm -c android.intent.category.LAUNCHER 1'],
|
||||
timeout=10, capture_output=True)
|
||||
time.sleep(8)
|
||||
pid = get_wechat_pid()
|
||||
|
||||
if not pid:
|
||||
print("❌ 无法启动微信")
|
||||
return 0, 0
|
||||
|
||||
print(f"✅ 微信PID: {pid}")
|
||||
|
||||
print("\n📡 连接Frida...")
|
||||
dm = frida.get_device_manager()
|
||||
device = dm.add_remote_device('localhost:27042')
|
||||
session = device.attach(pid)
|
||||
|
||||
with open(JS_FILE, 'r', encoding='utf-8') as f:
|
||||
js_code = f.read()
|
||||
|
||||
script = session.create_script(js_code)
|
||||
script.load()
|
||||
time.sleep(3)
|
||||
|
||||
ex = script.exports_sync
|
||||
|
||||
# 列出所有方法
|
||||
methods = [m for m in dir(ex) if not m.startswith('_')]
|
||||
print(f"✅ 可用方法: {len(methods)}个")
|
||||
print(f" {methods[:5]}")
|
||||
|
||||
# 测试调用方式
|
||||
print("\n🔍 测试调用方式...")
|
||||
for test_name in ['ping', 'getAccountInfo', 'getAllStats']:
|
||||
for variant in [test_name, test_name.lower(), test_name[0].lower()+test_name[1:]]:
|
||||
try:
|
||||
r = getattr(ex, variant)()
|
||||
print(f" ✅ {variant}() 成功: {str(r)[:50]}")
|
||||
break
|
||||
except Exception as e:
|
||||
print(f" ❌ {variant}(): {str(e)[:50]}")
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print("📊 开始全量接口验证(26项)")
|
||||
print("=" * 70)
|
||||
|
||||
# 确定正确的调用方式
|
||||
# 从dir()结果可以看到是驼峰,但调用时报错。
|
||||
# 尝试通过script直接post/rpc调用
|
||||
|
||||
# 方案:直接用script.exports(非sync版本)
|
||||
ex_legacy = script.exports
|
||||
|
||||
# ===== 1. ping =====
|
||||
print("\n【1】系统ping")
|
||||
r = test("ping", lambda: ex.ping())
|
||||
if r: print(f" ✅ {r}")
|
||||
results['ping'] = r
|
||||
|
||||
# ===== 2. 账号信息 =====
|
||||
print("\n【2】账号信息")
|
||||
for method in ['getAccountInfo', 'getaccountinfo', 'get_account_info']:
|
||||
try:
|
||||
r = getattr(ex, method)()
|
||||
print(f" ✅ 账号({method}): {r.get('nickname','?')} | wxid: {r.get('wxid','?')}")
|
||||
results['account'] = r
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'get_account_info':
|
||||
print(f" ❌ 账号: 所有方式都失败")
|
||||
errors.append(f"account: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 3. 全量统计 =====
|
||||
print("\n【3】全量数据统计")
|
||||
for method in ['getAllStats', 'getallstats']:
|
||||
try:
|
||||
r = getattr(ex, method)()
|
||||
print(f" ✅ 统计({method}): 好友:{r.get('friends',0)} 群:{r.get('groups',0)} 消息:{r.get('messages',0)}")
|
||||
print(f" 图片:{r.get('images',0)} 视频:{r.get('videos',0)} 文件:{r.get('files',0)}")
|
||||
results['stats'] = r
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getallstats':
|
||||
print(f" ❌ 统计: {str(e)[:80]}")
|
||||
errors.append(f"stats: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 4. 联系人列表 =====
|
||||
print("\n【4】联系人列表(前20个)")
|
||||
for method in ['getContacts', 'getcontacts']:
|
||||
try:
|
||||
r = getattr(ex, method)(20, 0)
|
||||
rows = r.get('rows', [])
|
||||
print(f" ✅ 联系人({method}): {len(rows)}个")
|
||||
for c in rows[:3]:
|
||||
print(f" - {c.get('nickName','?')} ({c.get('username','?')})")
|
||||
results['contacts'] = {'count': len(rows), 'sample': rows[:3]}
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getcontacts':
|
||||
print(f" ❌ 联系人: {str(e)[:80]}")
|
||||
errors.append(f"contacts: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 5. 联系人数量 =====
|
||||
print("\n【5】联系人数量")
|
||||
for method in ['getContactCount', 'getcontactcount']:
|
||||
try:
|
||||
r = getattr(ex, method)()
|
||||
print(f" ✅ 数量({method}): 好友:{r.get('friends',0)} 总:{r.get('total',0)}")
|
||||
results['contact_count'] = r
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getcontactcount':
|
||||
print(f" ❌ 数量: {str(e)[:80]}")
|
||||
errors.append(f"contact_count: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 6. 群组列表 =====
|
||||
print("\n【6】群组列表")
|
||||
groups_data = None
|
||||
for method in ['getGroups', 'getgroups']:
|
||||
try:
|
||||
r = getattr(ex, method)(50)
|
||||
rows = r.get('rows', [])
|
||||
print(f" ✅ 群组({method}): {len(rows)}个")
|
||||
for g in rows[:3]:
|
||||
print(f" - {g.get('nickName', g.get('NickName','?'))} ({g.get('username','?')})")
|
||||
results['groups'] = {'count': len(rows), 'sample': rows[:3]}
|
||||
groups_data = rows
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getgroups':
|
||||
print(f" ❌ 群组: {str(e)[:80]}")
|
||||
errors.append(f"groups: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 7. 标签 =====
|
||||
print("\n【7】标签列表")
|
||||
for method in ['getLabels', 'getlabels']:
|
||||
try:
|
||||
r = getattr(ex, method)()
|
||||
rows = r.get('rows', [])
|
||||
print(f" ✅ 标签({method}): {len(rows)}个")
|
||||
for l in rows[:5]:
|
||||
print(f" - {l.get('labelName', l.get('name','?'))}")
|
||||
results['labels'] = {'count': len(rows)}
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getlabels':
|
||||
print(f" ❌ 标签: {str(e)[:80]}")
|
||||
errors.append(f"labels: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 8. 最近消息 =====
|
||||
print("\n【8】最近消息(24小时)")
|
||||
for method in ['getRecentMessages', 'getrecentmessages']:
|
||||
try:
|
||||
r = getattr(ex, method)(24)
|
||||
rows = r.get('rows', [])
|
||||
print(f" ✅ 消息({method}): {len(rows)}条")
|
||||
results['recent_messages'] = {'count': len(rows)}
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getrecentmessages':
|
||||
print(f" ❌ 消息: {str(e)[:80]}")
|
||||
errors.append(f"recent_messages: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 9. 发送消息 =====
|
||||
print("\n【9】发送消息到文件传输助手")
|
||||
msg_content = f'[工作手机SDK v11] 自动测试 {time.strftime("%H:%M:%S")}'
|
||||
for method in ['sendMessage', 'sendmessage']:
|
||||
try:
|
||||
r = getattr(ex, method)('filehelper', msg_content, 1)
|
||||
print(f" ✅ 发送({method}): {json.dumps(r, ensure_ascii=False)[:200]}")
|
||||
results['send_message'] = r
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
time.sleep(2)
|
||||
screenshot('after_send_msg')
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'sendmessage':
|
||||
print(f" ❌ 发送: {str(e)[:80]}")
|
||||
errors.append(f"send_message: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 10. 群成员 =====
|
||||
print("\n【10】群成员(第一个群)")
|
||||
if groups_data and len(groups_data) > 0:
|
||||
chatroom_id = groups_data[0].get('username','')
|
||||
for method in ['getGroupMembers', 'getgroupmembers']:
|
||||
try:
|
||||
r = getattr(ex, method)(chatroom_id)
|
||||
members = r.get('rows', [])
|
||||
print(f" ✅ 群成员({method}): {chatroom_id} | {len(members)}人")
|
||||
results['group_members'] = {'count': len(members), 'chatroom': chatroom_id}
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getgroupmembers':
|
||||
print(f" ❌ 群成员: {str(e)[:80]}")
|
||||
errors.append(f"group_members: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
else:
|
||||
print(f" ⚠️ 没有群组数据")
|
||||
|
||||
# ===== 11. 朋友圈DB =====
|
||||
print("\n【11】朋友圈DB信息")
|
||||
for method in ['getSnsDbInfo', 'getsnsdbinfo']:
|
||||
try:
|
||||
r = getattr(ex, method)()
|
||||
print(f" ✅ 朋友圈DB({method}): {json.dumps(r, ensure_ascii=False)[:200]}")
|
||||
results['moments_db'] = r
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getsnsdbinfo':
|
||||
print(f" ❌ 朋友圈DB: {str(e)[:80]}")
|
||||
errors.append(f"moments_db: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 12. 朋友圈列表 =====
|
||||
print("\n【12】朋友圈列表")
|
||||
for method in ['getMoments', 'getmoments']:
|
||||
try:
|
||||
r = getattr(ex, method)(10)
|
||||
rows = r.get('rows', [])
|
||||
print(f" ✅ 朋友圈({method}): {len(rows)}条")
|
||||
for m in rows[:2]:
|
||||
print(f" - {str(m)[:100]}")
|
||||
results['moments'] = {'count': len(rows)}
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getmoments':
|
||||
print(f" ❌ 朋友圈: {str(e)[:80]}")
|
||||
errors.append(f"moments: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 13. 发布朋友圈 =====
|
||||
print("\n【13】发布朋友圈")
|
||||
moment_content = f'[工作手机SDK v11] {time.strftime("%Y-%m-%d %H:%M:%S")}'
|
||||
for method in ['postMoment', 'postmoment']:
|
||||
try:
|
||||
r = getattr(ex, method)(moment_content)
|
||||
print(f" ✅ 发布({method}): {json.dumps(r, ensure_ascii=False)[:200]}")
|
||||
results['post_moment'] = r
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
time.sleep(2)
|
||||
screenshot('after_post_moment')
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'postmoment':
|
||||
print(f" ❌ 发布: {str(e)[:80]}")
|
||||
errors.append(f"post_moment: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 14. 视频号信息 =====
|
||||
print("\n【14】视频号信息")
|
||||
for method in ['getFinderInfo', 'getfinderinfo']:
|
||||
try:
|
||||
r = getattr(ex, method)()
|
||||
print(f" ✅ 视频号({method}): {json.dumps(r, ensure_ascii=False)[:200]}")
|
||||
results['finder_info'] = r
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getfinderinfo':
|
||||
print(f" ❌ 视频号: {str(e)[:80]}")
|
||||
errors.append(f"finder_info: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 15. 视频号联系人 =====
|
||||
print("\n【15】视频号联系人")
|
||||
for method in ['getFinderContacts', 'getfindercontacts']:
|
||||
try:
|
||||
r = getattr(ex, method)(10)
|
||||
rows = r.get('rows', [])
|
||||
print(f" ✅ 视频号联系人({method}): {len(rows)}个")
|
||||
results['finder_contacts'] = {'count': len(rows)}
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getfindercontacts':
|
||||
print(f" ❌ 视频号联系人: {str(e)[:80]}")
|
||||
errors.append(f"finder_contacts: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 16. 收藏 =====
|
||||
print("\n【16】收藏列表")
|
||||
for method in ['getFavorites', 'getfavorites']:
|
||||
try:
|
||||
r = getattr(ex, method)(10)
|
||||
rows = r.get('rows', [])
|
||||
print(f" ✅ 收藏({method}): {len(rows)}条")
|
||||
results['favorites'] = {'count': len(rows)}
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getfavorites':
|
||||
print(f" ❌ 收藏: {str(e)[:80]}")
|
||||
errors.append(f"favorites: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 17. 钱包信息 =====
|
||||
print("\n【17】钱包信息")
|
||||
for method in ['getWalletInfo', 'getwalletinfo']:
|
||||
try:
|
||||
r = getattr(ex, method)()
|
||||
print(f" ✅ 钱包({method}): {json.dumps(r, ensure_ascii=False)[:200]}")
|
||||
results['wallet_info'] = r
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getwalletinfo':
|
||||
print(f" ❌ 钱包: {str(e)[:80]}")
|
||||
errors.append(f"wallet_info: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 18. 钱包流水 =====
|
||||
print("\n【18】钱包流水")
|
||||
for method in ['getWalletLedger', 'getwalletledger']:
|
||||
try:
|
||||
r = getattr(ex, method)(10)
|
||||
rows = r.get('rows', [])
|
||||
print(f" ✅ 钱包流水({method}): {len(rows)}条")
|
||||
for l in rows[:2]:
|
||||
print(f" - {str(l)[:100]}")
|
||||
results['wallet_ledger'] = {'count': len(rows)}
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getwalletledger':
|
||||
print(f" ❌ 钱包流水: {str(e)[:80]}")
|
||||
errors.append(f"wallet_ledger: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 19. 红包 =====
|
||||
print("\n【19】红包记录")
|
||||
for method in ['getLuckyMoney', 'getluckymoney']:
|
||||
try:
|
||||
r = getattr(ex, method)(10)
|
||||
rows = r.get('rows', [])
|
||||
print(f" ✅ 红包({method}): {len(rows)}条")
|
||||
for l in rows[:2]:
|
||||
print(f" - {str(l)[:100]}")
|
||||
results['lucky_money'] = {'count': len(rows)}
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getluckymoney':
|
||||
print(f" ❌ 红包: {str(e)[:80]}")
|
||||
errors.append(f"lucky_money: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 20. 图片统计 =====
|
||||
print("\n【20】图片统计")
|
||||
for method in ['getImageCount', 'getimagecount']:
|
||||
try:
|
||||
r = getattr(ex, method)()
|
||||
print(f" ✅ 图片({method}): {json.dumps(r, ensure_ascii=False)}")
|
||||
results['image_count'] = r
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getimagecount':
|
||||
print(f" ❌ 图片: {str(e)[:80]}")
|
||||
errors.append(f"image_count: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 21. 视频 =====
|
||||
print("\n【21】视频列表")
|
||||
for method in ['getVideoList', 'getvideolist']:
|
||||
try:
|
||||
r = getattr(ex, method)(5)
|
||||
rows = r.get('rows', [])
|
||||
print(f" ✅ 视频({method}): {len(rows)}条")
|
||||
results['videos'] = {'count': len(rows)}
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getvideolist':
|
||||
print(f" ❌ 视频: {str(e)[:80]}")
|
||||
errors.append(f"videos: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 22. 文件 =====
|
||||
print("\n【22】文件列表")
|
||||
for method in ['getFileList', 'getfilelist']:
|
||||
try:
|
||||
r = getattr(ex, method)(5)
|
||||
rows = r.get('rows', [])
|
||||
print(f" ✅ 文件({method}): {len(rows)}条")
|
||||
results['files'] = {'count': len(rows)}
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getfilelist':
|
||||
print(f" ❌ 文件: {str(e)[:80]}")
|
||||
errors.append(f"files: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 23. 小程序 =====
|
||||
print("\n【23】小程序信息")
|
||||
for method in ['getAppBrandList', 'getappbrandlist']:
|
||||
try:
|
||||
r = getattr(ex, method)()
|
||||
print(f" ✅ 小程序({method}): {json.dumps(r, ensure_ascii=False)[:200]}")
|
||||
results['appbrand'] = r
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'getappbrandlist':
|
||||
print(f" ❌ 小程序: {str(e)[:80]}")
|
||||
errors.append(f"appbrand: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 24. 搜索 =====
|
||||
print("\n【24】全局搜索")
|
||||
for method in ['globalSearch', 'globalsearch']:
|
||||
try:
|
||||
r = getattr(ex, method)('游条姐')
|
||||
print(f" ✅ 搜索({method}): {json.dumps(r, ensure_ascii=False)[:200]}")
|
||||
results['search'] = r
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'globalsearch':
|
||||
print(f" ❌ 搜索: {str(e)[:80]}")
|
||||
errors.append(f"search: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 25. 原始SQL =====
|
||||
print("\n【25】原始SQL查询")
|
||||
for method in ['rawQuery', 'rawquery']:
|
||||
try:
|
||||
r = getattr(ex, method)('main', 'SELECT type, COUNT(*) as cnt FROM rcontact GROUP BY type ORDER BY cnt DESC LIMIT 10')
|
||||
print(f" ✅ SQL({method}): {json.dumps(r, ensure_ascii=False)[:300]}")
|
||||
results['raw_sql'] = r
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'rawquery':
|
||||
print(f" ❌ SQL: {str(e)[:80]}")
|
||||
errors.append(f"raw_sql: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
|
||||
# ===== 26. 群公告 =====
|
||||
print("\n【26】设置群公告(测试写入接口)")
|
||||
if groups_data and len(groups_data) > 0:
|
||||
chatroom_id = groups_data[0].get('username','')
|
||||
for method in ['setGroupAnnouncement', 'setgroupannouncement']:
|
||||
try:
|
||||
r = getattr(ex, method)(chatroom_id, f'[SDK测试公告] {time.strftime("%H:%M:%S")}')
|
||||
print(f" ✅ 群公告({method}): {json.dumps(r, ensure_ascii=False)[:200]}")
|
||||
results['group_announcement'] = r
|
||||
passed_count += 1
|
||||
total_count += 1
|
||||
break
|
||||
except Exception as e:
|
||||
if method == 'setgroupannouncement':
|
||||
print(f" ❌ 群公告: {str(e)[:80]}")
|
||||
errors.append(f"group_announcement: {str(e)[:80]}")
|
||||
total_count += 1
|
||||
else:
|
||||
print(f" ⚠️ 没有群组数据")
|
||||
|
||||
# ===== 最终截图 =====
|
||||
print("\n📸 最终截图...")
|
||||
screenshot('final')
|
||||
|
||||
# ===== 汇总 =====
|
||||
print("\n" + "=" * 70)
|
||||
print(f"📊 验证结果: {passed_count}/{total_count} 通过 ({passed_count/total_count*100:.0f}%)")
|
||||
print("=" * 70)
|
||||
|
||||
if errors:
|
||||
print("\n❌ 失败项:")
|
||||
for e in errors:
|
||||
print(f" - {e}")
|
||||
|
||||
print("\n✅ 真实数据汇总:")
|
||||
acc = results.get('account', {})
|
||||
stats = results.get('stats', {})
|
||||
cc = results.get('contact_count', {})
|
||||
print(f" 📱 账号: {acc.get('nickname','?')} | wxid: {acc.get('wxid','?')}")
|
||||
print(f" 👥 好友: {cc.get('friends', stats.get('friends','?'))} | 总联系人: {cc.get('total','?')}")
|
||||
print(f" 💬 群组: {results.get('groups',{}).get('count', stats.get('groups','?'))}")
|
||||
print(f" 🏷️ 标签: {results.get('labels',{}).get('count','?')}")
|
||||
print(f" 📨 24h消息: {results.get('recent_messages',{}).get('count','?')}")
|
||||
print(f" 🖼️ 图片: {stats.get('images','?')}")
|
||||
print(f" 🎬 视频: {stats.get('videos','?')}")
|
||||
print(f" 📁 文件: {stats.get('files','?')}")
|
||||
print(f" ⭐ 收藏: {results.get('favorites',{}).get('count','?')}")
|
||||
print(f" 💰 钱包流水: {results.get('wallet_ledger',{}).get('count','?')}")
|
||||
print(f" 🧧 红包: {results.get('lucky_money',{}).get('count','?')}")
|
||||
print(f" 📹 视频号联系人: {results.get('finder_contacts',{}).get('count','?')}")
|
||||
print(f" 🔍 搜索结果: {results.get('search',{})}")
|
||||
|
||||
result_file = f'{SCREENSHOT_DIR}/v11_verify_results.json'
|
||||
with open(result_file, 'w', encoding='utf-8') as f:
|
||||
json.dump({
|
||||
'timestamp': int(time.time()),
|
||||
'time': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'passed': passed_count,
|
||||
'total': total_count,
|
||||
'pass_rate': f"{passed_count/total_count*100:.0f}%",
|
||||
'results': results,
|
||||
'errors': errors
|
||||
}, f, ensure_ascii=False, indent=2)
|
||||
print(f"\n💾 结果已保存: {result_file}")
|
||||
|
||||
return passed_count, total_count
|
||||
|
||||
if __name__ == '__main__':
|
||||
passed, total = main()
|
||||
print(f"\n🎯 最终: {passed}/{total} ({passed/total*100:.0f}%)")
|
||||
sys.exit(0 if passed >= total * 0.8 else 1)
|
||||
Reference in New Issue
Block a user