diff --git a/.idea/iOSAI.iml b/.idea/iOSAI.iml
index df5cbff..f571432 100644
--- a/.idea/iOSAI.iml
+++ b/.idea/iOSAI.iml
@@ -2,7 +2,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index c27b771..db8786c 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,5 +3,5 @@
-
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index cd899f8..33c043d 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,12 +4,11 @@
-
-
+
+
+
-
-
@@ -49,27 +48,27 @@
- {
- "keyToString": {
- "ASKED_ADD_EXTERNAL_FILES": "true",
- "Python.123.executor": "Run",
- "Python.Main.executor": "Run",
- "Python.tidevice_entry.executor": "Run",
- "RunOnceActivity.ShowReadmeOnStart": "true",
- "SHARE_PROJECT_CONFIGURATION_FILES": "true",
- "git-widget-placeholder": "main",
- "javascript.nodejs.core.library.configured.version": "20.17.0",
- "javascript.nodejs.core.library.typings.version": "20.17.58",
- "last_opened_file_path": "F:/company code/AI item/20250820/iOSAI",
- "node.js.detected.package.eslint": "true",
- "node.js.detected.package.tslint": "true",
- "node.js.selected.package.eslint": "(autodetect)",
- "node.js.selected.package.tslint": "(autodetect)",
- "nodejs_package_manager_path": "npm",
- "settings.editor.selected.configurable": "vcs.Git",
- "vue.rearranger.settings.migration": "true"
+
+}]]>
@@ -181,9 +180,8 @@
-
-
-
+
+
@@ -193,15 +191,7 @@
1756303135240
-
-
- 1756985736631
-
-
-
- 1756985736631
-
-
+
@@ -224,19 +214,18 @@
-
-
+
-
-
-
-
-
+
+
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/Entity/AnchorModel.py b/Entity/AnchorModel.py
index 4d27505..8731735 100644
--- a/Entity/AnchorModel.py
+++ b/Entity/AnchorModel.py
@@ -14,3 +14,8 @@ class AnchorModel:
model.anchorId = d.get('anchorId', "")
model.country = d.get('country', "")
return model
+
+ # 模型转字典
+ @classmethod
+ def modelToDict(cls, model):
+ return {"anchorId": model.anchorId, "country": model.country}
diff --git a/Entity/Variables.py b/Entity/Variables.py
index f499be5..b8d9506 100644
--- a/Entity/Variables.py
+++ b/Entity/Variables.py
@@ -2,6 +2,7 @@ import threading
from typing import Dict, Any
from Entity.AnchorModel import AnchorModel
+
# wda apple bundle id
WdaAppBundleId = "com.yolozsAgent.wda.xctrunner"
diff --git a/Module/DeviceInfo.py b/Module/DeviceInfo.py
index 8232e56..2834562 100644
--- a/Module/DeviceInfo.py
+++ b/Module/DeviceInfo.py
@@ -10,7 +10,7 @@ import subprocess
from pathlib import Path
from typing import List, Dict, Optional
-from tidevice import Usbmux
+from tidevice import Usbmux, ConnectionType
from Entity.DeviceModel import DeviceModel
from Entity.Variables import WdaAppBundleId
from Module.FlaskSubprocessManager import FlaskSubprocessManager
@@ -110,13 +110,15 @@ class Deviceinfo(object):
continue
# 新接入设备
for device in lists:
- if (device not in self.deviceArray) and (len(self.deviceArray) < self.maxDeviceCount):
+ # usb设备,并且为新设备。并且大于总限制数量
+ if device.conn_type == ConnectionType.USB and (device not in self.deviceArray) and (len(self.deviceArray) < self.maxDeviceCount):
self.screenProxy += 1
try:
self.connectDevice(device.udid)
self.deviceArray.append(device)
except Exception as e:
LogManager.error(f"连接设备失败 {device.udid}: {e}", device.udid)
+
# 拔出设备处理
self._removeDisconnected(lists)
time.sleep(1)
@@ -126,9 +128,9 @@ class Deviceinfo(object):
# ----------------------------
def connectDevice(self, identifier: str):
# 1) 连接 WDA(USBClient -> 设备 8100)
-
try:
d = wda.USBClient(identifier, 8100)
+
LogManager.info("启动 WDA 成功", identifier)
except Exception as e:
LogManager.error(f"启动 WDA 失败,请检查手机是否已信任、WDA 是否正常。错误: {e}", identifier)
diff --git a/Module/FlaskService.py b/Module/FlaskService.py
index c464536..c860da5 100644
--- a/Module/FlaskService.py
+++ b/Module/FlaskService.py
@@ -2,13 +2,12 @@ import json
import os
import socket
import threading
-import warnings
from queue import Queue
from typing import Any, Dict
+
+from Entity.AnchorModel import AnchorModel
from Utils.AiUtils import AiUtils
from Utils.LogManager import LogManager
-from Utils.Requester import Requester
-
import tidevice
import wda
from flask import Flask, request
@@ -17,8 +16,8 @@ from Entity.ResultData import ResultData
from Utils.ControlUtils import ControlUtils
from Utils.ThreadManager import ThreadManager
from script.ScriptManager import ScriptManager
-from Entity.Variables import anchorList, addModelToAnchorList,prologueList
-
+from Entity.Variables import anchorList, addModelToAnchorList, prologueList, removeModelFromAnchorList
+import Entity.Variables as ev
app = Flask(__name__)
CORS(app)
@@ -81,17 +80,17 @@ def start_socket_listener():
listener_thread = threading.Thread(target=start_socket_listener, daemon=True)
listener_thread.start()
-
-@app.route('/passToken', methods=['POST'])
-def passToken():
- try:
- data = request.get_json()
- token = data['token']
- Requester.requestPrologue(token)
- return ResultData(data="").toJson()
- except Exception as e:
- print(e)
- return ResultData(data="").toJson()
+# 传递token,暂时用不到了
+# @app.route('/passToken', methods=['POST'])
+# def passToken():
+# try:
+# data = request.get_json()
+# token = data['token']
+# Requester.requestPrologue(token)
+# return ResultData(data="").toJson()
+# except Exception as e:
+# print(e)
+# return ResultData(data="").toJson()
# 获取设备列表
@@ -245,6 +244,11 @@ def passAnchorData():
acList = data.get("anchorList", [])
# 是否需要回复
needReply = data.get("needReply", True)
+
+ # 获取打招呼数据
+ ev.prologueList = data.get("prologueList", [])
+
+
# 添加主播数据
addModelToAnchorList(acList)
# 启动线程,执行脚本
@@ -252,13 +256,17 @@ def passAnchorData():
manager = ScriptManager()
event = threading.Event()
# 启动脚本
- # thread = threading.Thread(target=manager.greetNewFollowers, args=(udid, needReply, event))
thread = threading.Thread(target=manager.safe_greetNewFollowers, args=(udid, needReply, event))
thread.start()
# 添加到线程管理
ThreadManager.add(udid, thread, event)
return ResultData(data="").toJson()
+# 获取私信数据
+@app.route("/getPrologueList", methods=['GET'])
+def getPrologueList():
+ print(ev.prologueList)
+ return ResultData(data=ev.prologueList).toJson()
# 添加临时数据
@app.route("/addTempAnchorData", methods=['POST'])
@@ -277,7 +285,6 @@ def getChatTextInfo():
session = client.session()
xml = session.source()
try:
- print(xml)
result = AiUtils.extract_messages_from_xml(xml)
print(result)
return ResultData(data=result).toJson()
@@ -312,24 +319,34 @@ def monitorMessages():
@app.route("/setLoginInfo", methods=['POST'])
-def upLoadLogFile():
+def upLoadLogLogs():
data = request.get_json() # 解析 JSON
token = data.get("token")
userId = data.get("userId")
tenantId = data.get("tenantId")
ok = LogManager.upload_all_logs("http://47.79.98.113:8101/api/log/upload", token, userId, tenantId)
-
if ok:
return ResultData(data="日志上传成功").toJson()
else:
return ResultData(data="", msg="日志上传失败").toJson()
-# @app.route("/", methods=['POST'])
-# def upLoadLogFile():
-# datas = request.get_json() # 解析 JSON
-# # 先清空打招呼语
-# prologueList.clear()
-# # 添加新的打招呼语句
-# for data in datas:
-# prologueList.append(data)
+# 获取当前的主播列表数据
+@app.route("/anchorList", methods=['POST'])
+def queryAnchorList():
+ data = []
+ for model in anchorList:
+ data.append(AnchorModel.modelToDict(model))
+ return ResultData(data=data).toJson()
+# 删除主播
+@app.route("/deleteAnchorWithIds", methods=['POST'])
+def deleteAnchorWithIds():
+ ls: list[dict] = request.get_json()
+ for dic in ls:
+ for model in anchorList:
+ if dic.get("anchorId") == model.anchorId:
+ removeModelFromAnchorList(model)
+ return ResultData(data="").toJson()
+
+if __name__ == '__main__':
+ app.run("0.0.0.0", port=5000, debug=True, use_reloader=False)
diff --git a/Module/Main.py b/Module/Main.py
index 837b0d1..c86317d 100644
--- a/Module/Main.py
+++ b/Module/Main.py
@@ -7,6 +7,7 @@ from Module.FlaskSubprocessManager import FlaskSubprocessManager
from Utils.DevDiskImageDeployer import DevDiskImageDeployer
from Utils.LogManager import LogManager
+
# 确定 exe 或 py 文件所在目录
BASE = Path(getattr(sys, 'frozen', False) and sys.executable or __file__).resolve().parent
LOG_DIR = BASE / "log"
@@ -25,8 +26,10 @@ if "--role=flask" in sys.argv:
_run_flask_role()
sys.exit(0)
+
# 项目入口
if __name__ == "__main__":
+
# 添加iOS开发包到电脑上
deployer = DevDiskImageDeployer(verbose=True)
deployer.deploy_all()
diff --git a/Utils/AiUtils.py b/Utils/AiUtils.py
index 1550cf5..9574bda 100644
--- a/Utils/AiUtils.py
+++ b/Utils/AiUtils.py
@@ -459,3 +459,18 @@ class AiUtils(object):
return t
return ""
+
+ # 检查字符串中是否包含中文
+ @classmethod
+ def contains_chinese(cls, text):
+ """
+ 判断字符串中是否包含中文字符。
+ 参数:
+ text (str): 要检测的字符串。
+
+ 返回:
+ bool: 如果字符串中包含中文,返回 True;否则返回 False。
+ """
+ # 使用正则表达式匹配中文字符
+ pattern = re.compile(r'[\u4e00-\u9fff]')
+ return bool(pattern.search(text))
diff --git a/Utils/LogManager.py b/Utils/LogManager.py
index afb11f3..cbb1b00 100644
--- a/Utils/LogManager.py
+++ b/Utils/LogManager.py
@@ -1,85 +1,4 @@
-# import logging
-# import os
-# import sys
-# import shutil
-# from pathlib import Path
-#
-#
-# class LogManager:
-# # 运行根目录:打包后取 exe 目录;源码运行取项目目录
-# if getattr(sys, "frozen", False):
-# projectRoot = os.path.dirname(sys.executable)
-# else:
-# projectRoot = os.path.dirname(os.path.dirname(__file__))
-#
-# logDir = os.path.join(projectRoot, "log")
-# _loggers = {}
-#
-# @classmethod
-# def _setupLogger(cls, udid, name, logName, level=logging.INFO):
-# """创建或获取 logger,并绑定到文件"""
-# deviceLogDir = os.path.join(cls.logDir, udid)
-# os.makedirs(deviceLogDir, exist_ok=True)
-# logFile = os.path.join(deviceLogDir, logName)
-#
-# logger_name = f"{udid}_{name}"
-# logger = logging.getLogger(logger_name)
-# logger.setLevel(level)
-#
-# # 避免重复添加 handler
-# if not any(
-# isinstance(h, logging.FileHandler) and h.baseFilename == os.path.abspath(logFile)
-# for h in logger.handlers
-# ):
-# fileHandler = logging.FileHandler(logFile, mode="a", encoding="utf-8")
-# formatter = logging.Formatter(
-# "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
-# datefmt="%Y-%m-%d %H:%M:%S"
-# )
-# fileHandler.setFormatter(formatter)
-# logger.addHandler(fileHandler)
-#
-# return logger
-#
-# @classmethod
-# def info(cls, text, udid="system"):
-# cls._setupLogger(udid, "infoLogger", "info.log", level=logging.INFO).info(f"[{udid}] {text}")
-#
-# @classmethod
-# def warning(cls, text, udid="system"):
-# cls._setupLogger(udid, "warningLogger", "warning.log", level=logging.WARNING).warning(f"[{udid}] {text}")
-#
-# @classmethod
-# def error(cls, text, udid="system"):
-# cls._setupLogger(udid, "errorLogger", "error.log", level=logging.ERROR).error(f"[{udid}] {text}")
-#
-# # 清空日志
-# @classmethod
-# def clearLogs(cls):
-# """启动时清空 log 目录下所有文件"""
-# print("开始清空日志...")
-#
-# # 关闭所有 handler
-# for name, logger in logging.Logger.manager.loggerDict.items():
-# if isinstance(logger, logging.Logger):
-# for handler in logger.handlers[:]:
-# try:
-# handler.close()
-# except Exception:
-# pass
-# logger.removeHandler(handler)
-#
-# # 仅删除目录里的所有文件和子目录
-# log_path = Path(cls.logDir)
-# if log_path.exists():
-# for item in log_path.iterdir():
-# if item.is_file():
-# item.unlink()
-# elif item.is_dir():
-# import shutil
-# shutil.rmtree(item)
-#
-# print("日志清空完成")
+
import datetime
import io
import logging
@@ -89,11 +8,8 @@ import sys
import shutil
import zipfile
from pathlib import Path
-
import requests
-import Entity.Variables
-
class LogManager:
# 运行根目录:打包后取 exe 目录;源码运行取项目目录
@@ -235,7 +151,6 @@ class LogManager:
@classmethod
def clearLogs(cls):
"""启动时清空 log 目录下所有文件"""
- print("开始清空日志...")
# 关闭所有 handler
for name, logger in logging.Logger.manager.loggerDict.items():
@@ -258,13 +173,11 @@ class LogManager:
# 清缓存
cls._method_loggers.clear()
- print("日志清空完成")
@classmethod
def upload_all_logs(cls, server_url, token, userId, tenantId):
log_path = Path(cls.logDir)
if not log_path.exists():
- print("[upload_all_logs] 日志目录不存在")
return False
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
@@ -286,20 +199,9 @@ class LogManager:
files = {
"file": (filename, io.BytesIO(zip_bytes), "application/zip")
}
- print(
- f"[upload_all_logs] "
- f"server={server_url} (type={type(server_url)}) "
- f"tenantId={tenantId} (type={type(tenantId)}) "
- f"userId={userId} (type={type(userId)}) "
- f"token={token} (type={type(token)})"
- )
- print("开始上传")
# 3) 上传
resp = requests.post(server_url, headers=headers, data=data, files=files)
- print(resp.text)
- print("上传结束")
-
if resp.json()['data']:
return True
return False
diff --git a/build-tidevice.bat b/build-tidevice.bat
index cb175bb..52df5ee 100644
--- a/build-tidevice.bat
+++ b/build-tidevice.bat
@@ -4,6 +4,6 @@ pyinstaller -F -n tidevice ^
--hidden-import=tidevice._usbmux ^
--hidden-import=tidevice._wdaproxy ^
--collect-all tidevice ^
- -c ^
+ --noconsole ^
--add-data="C:\Users\milk\AppData\Local\Programs\Python\Python312\Lib\site-packages\tidevice;tidevice" ^
- tidevice_entry.py
\ No newline at end of file
+ tidevice_entry.py
diff --git a/build.bat b/build.bat
index 2bdf314..98699cd 100644
--- a/build.bat
+++ b/build.bat
@@ -1,17 +1,11 @@
-@echo off
-python -m nuitka Module\Main.py ^
+python -m nuitka Module/Main.py ^
--standalone ^
--msvc=latest ^
--windows-console-mode=disable ^
--remove-output ^
--output-dir=out ^
--output-filename=IOSAI ^
- --include-package=Module,Utils,Entity,script,tidevice ^
- --include-module=tidevice.__main__ ^
- --include-module=tidevice._proto ^
- --include-module=tidevice._instruments ^
- --include-module=tidevice._usbmux ^
- --include-module=tidevice._wdaproxy ^
+ --include-package=Module,Utils,Entity,script ^
--include-module=flask ^
--include-module=flask_cors ^
--include-module=jinja2 ^
@@ -27,5 +21,4 @@ python -m nuitka Module\Main.py ^
--include-data-dir="E:/Code/python/iOSAI/SupportFiles=SupportFiles" ^
--include-data-dir="E:/Code/python/iOSAI/resources=resources" ^
--include-data-files="E:/Code/python/iOSAI/resources/iproxy/*=resources/iproxy/" ^
- --windows-icon-from-ico=resources/icon.ico
-pause
\ No newline at end of file
+ --windows-icon-from-ico=resources/icon.ico
\ No newline at end of file
diff --git a/resources/iproxy/tidevice.exe b/resources/iproxy/tidevice.exe
index 466c364..fdd3048 100644
Binary files a/resources/iproxy/tidevice.exe and b/resources/iproxy/tidevice.exe differ