临时提交
This commit is contained in:
16
Entity/AnchorModel.py
Normal file
16
Entity/AnchorModel.py
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
# 主播模型
|
||||
class AnchorModel:
|
||||
def __init__(self, anchorId= "", country= ""):
|
||||
# 主播ID
|
||||
self.anchorId = anchorId
|
||||
# 主播国家
|
||||
self.country = country
|
||||
|
||||
# 字典转模型
|
||||
@classmethod
|
||||
def dictToModel(cls, d):
|
||||
model = AnchorModel()
|
||||
model.anchorId = d.get('anchorId', "")
|
||||
model.country = d.get('country', "")
|
||||
return model
|
||||
@@ -1,4 +1,24 @@
|
||||
# Tik Tok app bundle id
|
||||
import threading
|
||||
from typing import Dict, Any
|
||||
|
||||
from Entity.AnchorModel import AnchorModel
|
||||
|
||||
tikTokApp = "com.zhiliaoapp.musically"
|
||||
# wda apple bundle id
|
||||
WdaAppBundleId = "com.vv.wda.xctrunner"
|
||||
# 全局主播列表
|
||||
anchorList: list[AnchorModel] = []
|
||||
# 线程锁
|
||||
anchorListLock = threading.Lock()
|
||||
|
||||
# 安全删除数据
|
||||
def removeModelFromAnchorList(model: AnchorModel):
|
||||
with anchorListLock:
|
||||
anchorList.remove(model)
|
||||
|
||||
# 添加数据
|
||||
def addModelToAnchorList(models: list[Dict[str, Any]]):
|
||||
with anchorListLock:
|
||||
for dic in models:
|
||||
obj = AnchorModel.dictToModel(dic)
|
||||
anchorList.append(obj)
|
||||
@@ -2,14 +2,20 @@ import json
|
||||
import os
|
||||
import socket
|
||||
import threading
|
||||
import warnings
|
||||
from queue import Queue
|
||||
from typing import Any, Dict
|
||||
|
||||
import tidevice
|
||||
import wda
|
||||
from flask import Flask, request
|
||||
from flask_cors import CORS
|
||||
from Entity.ResultData import ResultData
|
||||
from Utils.ControlUtils import ControlUtils
|
||||
from Utils.ThreadManager import ThreadManager
|
||||
from script.ScriptManager import ScriptManager
|
||||
from Entity.AnchorModel import AnchorModel
|
||||
from Entity.Variables import anchorList, addModelToAnchorList
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(app)
|
||||
@@ -81,21 +87,8 @@ def deviceList():
|
||||
def deviceAppList():
|
||||
param = request.get_json()
|
||||
udid = param["udid"]
|
||||
t = tidevice.Device(udid)
|
||||
|
||||
# 获取已安装的应用列表
|
||||
apps = []
|
||||
for app in t.installation.iter_installed():
|
||||
apps.append({
|
||||
"name": app.get("CFBundleDisplayName", "Unknown"),
|
||||
"bundleId": app.get("CFBundleIdentifier", "Unknown"),
|
||||
"version": app.get("CFBundleShortVersionString", "Unknown"),
|
||||
"path": app.get("Path", "Unknown")
|
||||
})
|
||||
|
||||
# 筛选非系统级应用(过滤掉以 com.apple 开头的系统应用)
|
||||
non_system_apps = [app for app in apps if not app["bundleId"].startswith("com.apple")]
|
||||
return ResultData(data=non_system_apps).toJson()
|
||||
apps = ControlUtils.getDeviceAppList(udid)
|
||||
return ResultData(data=apps).toJson()
|
||||
|
||||
# 打开指定app
|
||||
@app.route('/launchApp', methods=['POST'])
|
||||
@@ -188,12 +181,36 @@ def stopScript():
|
||||
ThreadManager.stop(udid)
|
||||
return ResultData(data="").toJson()
|
||||
|
||||
# AI聊天
|
||||
@app.route('/aiChat', methods=['POST'])
|
||||
def aiChat():
|
||||
body = request.get_json()
|
||||
udid = body.get("udid")
|
||||
|
||||
# 传递主播数据
|
||||
@app.route('/passAnchorData', methods=['POST'])
|
||||
def passAnchorData():
|
||||
data: Dict[str, Any] = request.get_json()
|
||||
# 设备列表
|
||||
idList = data.get("deviceList", [])
|
||||
# 主播列表
|
||||
acList = data.get("anchorList", [])
|
||||
# 是否需要回复
|
||||
needReply = data.get("needReply", False)
|
||||
# 添加主播数据
|
||||
addModelToAnchorList(acList)
|
||||
# 启动线程,执行脚本
|
||||
for udid in idList:
|
||||
manager = ScriptManager()
|
||||
event = threading.Event()
|
||||
# 启动脚本
|
||||
thread = threading.Thread(target=manager.greetNewFollowers, args=(udid, needReply, event))
|
||||
thread.start()
|
||||
# 添加到线程管理
|
||||
ThreadManager.add(udid, thread, event)
|
||||
return ResultData(data="").toJson()
|
||||
|
||||
# 添加临时数据
|
||||
@app.route("/addTempAnchorData", methods=['POST'])
|
||||
def addTempAnchorData():
|
||||
data = request.get_json()
|
||||
addModelToAnchorList(data)
|
||||
return ResultData(data="").toJson()
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run("0.0.0.0", port=5000, debug=True, use_reloader=False)
|
||||
|
||||
@@ -4,10 +4,8 @@ import re
|
||||
import cv2
|
||||
import numpy as np
|
||||
import wda
|
||||
|
||||
from Utils.LogManager import LogManager
|
||||
|
||||
|
||||
# 工具类
|
||||
class AiUtils(object):
|
||||
|
||||
@@ -225,3 +223,4 @@ class AiUtils(object):
|
||||
print(e)
|
||||
return None
|
||||
|
||||
# AiUtils.screenshot()
|
||||
@@ -1,3 +1,4 @@
|
||||
import tidevice
|
||||
from wda import Client
|
||||
|
||||
from Entity.Variables import tikTokApp
|
||||
@@ -7,13 +8,47 @@ from Utils.LogManager import LogManager
|
||||
# 页面控制工具类
|
||||
class ControlUtils(object):
|
||||
|
||||
# 获取设备上的app列表
|
||||
@classmethod
|
||||
def getDeviceAppList(self, udid):
|
||||
device = tidevice.Device(udid)
|
||||
# 获取已安装的应用列表
|
||||
apps = []
|
||||
for app in device.installation.iter_installed():
|
||||
apps.append({
|
||||
"name": app.get("CFBundleDisplayName", "Unknown"),
|
||||
"bundleId": app.get("CFBundleIdentifier", "Unknown"),
|
||||
"version": app.get("CFBundleShortVersionString", "Unknown"),
|
||||
"path": app.get("Path", "Unknown")
|
||||
})
|
||||
|
||||
# 筛选非系统级应用(过滤掉以 com.apple 开头的系统应用)
|
||||
noSystemApps = [app for app in apps if not app["bundleId"].startswith("com.apple")]
|
||||
return noSystemApps
|
||||
|
||||
# 打开Tik Tok
|
||||
@classmethod
|
||||
def openTikTok(cls, session: Client):
|
||||
def openTikTok(cls, session: Client, udid):
|
||||
apps = cls.getDeviceAppList(udid)
|
||||
tk = ""
|
||||
for app in apps:
|
||||
if app.get("name", "") == "TikTok":
|
||||
tk = app.get("bundleId", "")
|
||||
|
||||
currentApp = session.app_current()
|
||||
if currentApp != tikTokApp:
|
||||
if currentApp != tk:
|
||||
session.app_start(tikTokApp)
|
||||
|
||||
# 关闭Tik Tok
|
||||
@classmethod
|
||||
def closeTikTok(cls, session: Client, udid):
|
||||
apps = cls.getDeviceAppList(udid)
|
||||
tk = ""
|
||||
for app in apps:
|
||||
if app.get("name", "") == "TikTok":
|
||||
tk = app.get("bundleId", "")
|
||||
session.app_stop(tk)
|
||||
|
||||
# 返回
|
||||
@classmethod
|
||||
def clickBack(cls, session: Client):
|
||||
@@ -63,5 +98,16 @@ class ControlUtils(object):
|
||||
# return False
|
||||
|
||||
|
||||
# 点击搜索
|
||||
@classmethod
|
||||
def clickSearch(cls, session: Client):
|
||||
obj = session.xpath("//*[@name='搜索']")
|
||||
try:
|
||||
if obj.label == "搜索":
|
||||
return obj
|
||||
else:
|
||||
return None
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return None
|
||||
|
||||
# ControlUtils.backAction("eca000fcb6f55d7ed9b4c524055214c26a7de7aa")
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 1.8 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 7.3 KiB |
BIN
screenshot.png
Normal file
BIN
screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
@@ -1,10 +1,13 @@
|
||||
import random
|
||||
import threading
|
||||
import time
|
||||
from enum import Enum
|
||||
import wda
|
||||
import os
|
||||
from Utils.AiUtils import AiUtils
|
||||
from Utils.ControlUtils import ControlUtils
|
||||
from Utils.LogManager import LogManager
|
||||
from Entity.Variables import anchorList, removeModelFromAnchorList
|
||||
|
||||
|
||||
# 脚本管理类
|
||||
@@ -28,10 +31,14 @@ class ScriptManager():
|
||||
def growAccount(self, udid, event):
|
||||
client = wda.USBClient(udid)
|
||||
session = client.session()
|
||||
session.appium_settings({"snapshotMaxDepth": 15})
|
||||
session.appium_settings({"snapshotMaxDepth": 0})
|
||||
|
||||
# 检测当前打开的是否是Tik Tok。如果不是就打开
|
||||
ControlUtils.openTikTok(session)
|
||||
# 先关闭Tik Tok
|
||||
ControlUtils.closeTikTok(session, udid)
|
||||
time.sleep(1)
|
||||
|
||||
# 重新打开Tik Tok
|
||||
ControlUtils.openTikTok(session, udid)
|
||||
time.sleep(3)
|
||||
|
||||
# 创建udid名称的目录
|
||||
@@ -93,6 +100,86 @@ class ScriptManager():
|
||||
print(f"发生异常:{e}")
|
||||
client.swipe_up()
|
||||
|
||||
|
||||
# 观看直播
|
||||
def viewLive(self):
|
||||
pass
|
||||
|
||||
# 关注打招呼
|
||||
def greetNewFollowers(self, udid, needReply, event):
|
||||
client = wda.USBClient(udid)
|
||||
session = client.session()
|
||||
session.appium_settings({"snapshotMaxDepth": 15})
|
||||
|
||||
# 先关闭Tik Tok
|
||||
ControlUtils.closeTikTok(session, udid)
|
||||
time.sleep(1)
|
||||
|
||||
# 重新打开Tik Tok
|
||||
ControlUtils.openTikTok(session, udid)
|
||||
time.sleep(3)
|
||||
|
||||
# 点击搜索按钮
|
||||
searchButton = ControlUtils.clickSearch(session)
|
||||
if searchButton is not None:
|
||||
searchButton.click()
|
||||
else:
|
||||
print("没找到搜索按钮")
|
||||
return
|
||||
|
||||
# 搜索框
|
||||
input = session.xpath('//XCUIElementTypeSearchField')
|
||||
|
||||
# 获取一个主播
|
||||
anchor = anchorList[0]
|
||||
aid = anchor.anchorId
|
||||
|
||||
# 如果找到了输入框,就点击并且输入内容
|
||||
if input.exists:
|
||||
input.click()
|
||||
time.sleep(1)
|
||||
input.set_text(aid + "\n")
|
||||
|
||||
# 切换UI查找深度
|
||||
session.appium_settings({"snapshotMaxDepth": 25})
|
||||
|
||||
# 点击进入主播首页
|
||||
session.xpath(
|
||||
'(//XCUIElementTypeCollectionView[@name="TTKSearchCollectionComponent"]'
|
||||
'//XCUIElementTypeCell'
|
||||
'//XCUIElementTypeButton[following-sibling::XCUIElementTypeButton[@name="关注" or @label="关注"]])[1]'
|
||||
).get(timeout=5).tap()
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
# 向上划一点
|
||||
r = client.swipe_up()
|
||||
print(r)
|
||||
|
||||
# 分析页面节点
|
||||
# print(session.source())
|
||||
|
||||
# 观看主播视频
|
||||
def viewAnchorVideo():
|
||||
pass
|
||||
|
||||
viewAnchorVideo()
|
||||
else:
|
||||
pass
|
||||
# 功能待完善
|
||||
|
||||
|
||||
|
||||
# while not event.is_set() and len(anchorList) > 0:
|
||||
# anchor = anchorList[0]
|
||||
# aid = anchor.anchorId
|
||||
#
|
||||
# ControlUtils.clickSearch(session, udid)
|
||||
#
|
||||
# # 删除数据
|
||||
# removeModelFromAnchorList(anchor)
|
||||
# print(len(anchorList))
|
||||
|
||||
# manager = ScriptManager()
|
||||
# manager.growAccount("eca000fcb6f55d7ed9b4c524055214c26a7de7aa")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user