临时提交

This commit is contained in:
zw
2025-08-14 14:30:36 +08:00
parent 4c2bf5d8f2
commit f3fe7a661f
4 changed files with 67 additions and 36 deletions

View File

@@ -5,6 +5,8 @@ import threading
import warnings
from queue import Queue
from typing import Any, Dict
from Utils.AiUtils import AiUtils
from Utils.Requester import Requester
import tidevice
import wda
@@ -72,6 +74,11 @@ listener_thread.start()
def passToken():
data = request.get_json()
accountToken = data['token']
print(accountToken)
Requester.requestComments()
return ResultData(data="").toJson()
# 获取设备列表
@@ -230,5 +237,16 @@ def addTempAnchorData():
addModelToAnchorList(data)
return ResultData(data="").toJson()
# 获取当前屏幕上的聊天信息
@app.route("/getChatTextInfo", methods=['POST'])
def getChatTextInfo():
data = request.get_json()
udid = data.get("udid")
client = wda.USBClient(udid)
session = client.session()
xml = session.source()
result = AiUtils.extract_messages_from_xml(xml)
return ResultData(data=result).toJson()
if __name__ == '__main__':
app.run("0.0.0.0", port=5000, debug=True, use_reloader=False)

View File

@@ -286,39 +286,59 @@ class AiUtils(object):
@classmethod
def extract_messages_from_xml(cls, xml: str):
"""
输入 WDA 的页面 XML输出按时间顺序的消息列表
每项形如:
{'type': 'time', 'text': '昨天 下午8:48'}
{'type': 'msg', 'dir': 'in'|'out', 'text': 'hello'}
仅返回当前屏幕中“可见的”聊天内容(含时间分隔)
"""
from lxml import etree
root = etree.fromstring(xml.encode("utf-8"))
items = []
# 屏幕宽度(用于右对齐判断)
# 屏幕宽度
app = root.xpath('/XCUIElementTypeApplication')
screen_w = cls.parse_float(app[0], 'width', 414.0) if app else 414.0
# 1) 时间分隔
# 找 Table 的可见范围
table = root.xpath('//XCUIElementTypeTable')
if table:
table = table[0]
table_top = cls.parse_float(table, 'y', 0.0)
table_h = cls.parse_float(table, 'height', 0.0)
table_bottom = table_top + table_h
else:
table_top, table_bottom = 0.0, cls.parse_float(app[0], 'height', 736.0) if app else 736.0
def in_view(el) -> bool:
"""元素在聊天区内并且可见"""
if el.get('visible') != 'true':
return False
y = cls.parse_float(el, 'y', -1e9)
h = cls.parse_float(el, 'height', 0.0)
by = y + h
return not (by <= table_top or y >= table_bottom)
# 时间分隔
for t in root.xpath('//XCUIElementTypeStaticText[contains(@traits, "Header")]'):
txt = t.get('label') or t.get('name') or t.get('value') or ''
y = cls.parse_float(t, 'y')
if txt.strip():
items.append({'type': 'time', 'text': txt.strip(), 'y': y})
# 2) 消息气泡
msg_nodes = root.xpath(
'//XCUIElementTypeTable//XCUIElementTypeCell'
'//XCUIElementTypeOther[@name or @label]'
)
if not in_view(t):
continue
txt = (t.get('label') or t.get('name') or t.get('value') or '').strip()
if txt:
items.append({'type': 'time', 'text': txt, 'y': cls.parse_float(t, 'y')})
# 消息气泡
EXCLUDES = {'Heart', 'Lol', 'ThumbsUp', '分享发布内容', '视频贴纸标签页', '双击发送表情'}
msg_nodes = table.xpath(
'.//XCUIElementTypeCell[@visible="true"]'
'//XCUIElementTypeOther[@visible="true" and (@name or @label) and not(ancestor::XCUIElementTypeCollectionView)]'
) if table is not None else []
for o in msg_nodes:
text = (o.get('label') or o.get('name') or '').strip()
if not text or text in EXCLUDES:
continue
if not in_view(o):
continue
# 拿到所在 Cell(用来找头像按钮)
# 所在 Cell
cell = o.getparent()
while cell is not None and cell.get('type') != 'XCUIElementTypeCell':
cell = cell.getparent()
@@ -329,29 +349,20 @@ class AiUtils(object):
right_edge = x + w
direction = None
# 2.1 依据同 Cell 内“图片头像”的位置判定(优先,最稳)
# 头像位置判定
if cell is not None:
avatar_btns = cell.xpath('.//XCUIElementTypeButton[@name="图片头像" or @label="图片头像"]')
avatar_btns = cell.xpath(
'.//XCUIElementTypeButton[@visible="true" and (@name="图片头像" or @label="图片头像")]')
if avatar_btns:
ax = cls.parse_float(avatar_btns[0], 'x')
# 头像在左侧 → 对方;头像在右侧 → 自己
if ax < screen_w / 2:
direction = 'in'
else:
direction = 'out'
# 2.2 退化规则:看是否右对齐
direction = 'in' if ax < (screen_w / 2) else 'out'
# 右对齐兜底
if direction is None:
# 离右边 <= 20px 视为右对齐(自己发的)
if right_edge > screen_w - 20:
direction = 'out'
else:
direction = 'in'
direction = 'out' if right_edge > (screen_w - 20) else 'in'
items.append({'type': 'msg', 'dir': direction, 'text': text, 'y': y})
# 3) 按 y 排序并清理
# 排序 & 清理
items.sort(key=lambda i: i['y'])
for it in items:
it.pop('y', None)

View File

@@ -8,6 +8,7 @@ BaseUrl = "http://192.168.1.174:8101/api/common/"
class Requester():
comment = "comment"
prologue = "prologue"
@classmethod
def requestComments(cls):
headers = {

View File

@@ -317,10 +317,9 @@ class ScriptManager():
if chatInput.exists:
print("找到输入框了, 准备发送一条打招呼消息")
# 准备打招呼的文案
# text = random.choice(prologueList)
text = "你好"
text = random.choice(prologueList)
# 翻译成主播国家的语言
msg = Requester.translation(text, "法国")
msg = Requester.translation(text, anchorCountry)
# 准备发送一条信息
chatInput.click()
time.sleep(2)
@@ -329,6 +328,8 @@ class ScriptManager():
time.sleep(1)
else:
print("无法发送信息")
LogManager.error(f"给主播{anchor.anchorId} 发送消息失败", udid)
# 接着下一个主播
removeModelFromAnchorList(anchor)
goBack(4)