修复一些问题
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -24,6 +24,8 @@ var/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
out/
|
||||
Main.build/
|
||||
Main.dist/
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
@@ -128,4 +130,5 @@ dmypy.json
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
*.bat
|
||||
build-tidevice.bat
|
||||
build.bat
|
||||
36
.idea/workspace.xml
generated
36
.idea/workspace.xml
generated
@@ -5,37 +5,12 @@
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="eceeff5e-51c1-459c-a911-d21ec090a423" name="Changes" comment="20250904-初步功能已完成">
|
||||
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Module/Main.py" beforeDir="false" afterPath="$PROJECT_DIR$/Module/Main.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevice_id.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevice_id.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicebackup.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicebackup.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicebackup2.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicebackup2.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicebtlogger.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicebtlogger.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicecrashreport.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicecrashreport.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicedate.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicedate.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicedebug.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicedebug.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicedebugserverproxy.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicedebugserverproxy.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicedevmodectl.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicedevmodectl.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicediagnostics.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicediagnostics.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/ideviceenterrecovery.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/ideviceenterrecovery.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/ideviceimagemounter.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/ideviceimagemounter.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/ideviceinfo.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/ideviceinfo.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicename.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicename.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicenotificationproxy.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicenotificationproxy.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicepair.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicepair.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/ideviceprovision.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/ideviceprovision.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicerestore.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicerestore.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicescreenshot.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicescreenshot.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicesetlocation.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicesetlocation.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/idevicesyslog.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/idevicesyslog.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/inetcat.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/inetcat.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/irecovery.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/irecovery.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/libcrypto-3.dll" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/libcrypto-3.dll" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/libcurl.dll" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/libcurl.dll" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/libssl-3.dll" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/libssl-3.dll" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/plistutil.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/plistutil.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/readline.dll" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/readline.dll" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/iproxy/tidevice.exe" beforeDir="false" afterPath="$PROJECT_DIR$/resources/iproxy/tidevice.exe" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Module/FlaskService.py" beforeDir="false" afterPath="$PROJECT_DIR$/Module/FlaskService.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Utils/AiUtils.py" beforeDir="false" afterPath="$PROJECT_DIR$/Utils/AiUtils.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Utils/ThreadManager.py" beforeDir="false" afterPath="$PROJECT_DIR$/Utils/ThreadManager.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/script/ScriptManager.py" beforeDir="false" afterPath="$PROJECT_DIR$/script/ScriptManager.py" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@@ -102,6 +77,7 @@
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"settings.editor.selected.configurable": "preferences.editor.code.editing",
|
||||
"two.files.diff.last.used.file": "E:/share/iOSAI/Module/FlaskService.py",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}</component>
|
||||
|
||||
@@ -393,9 +393,12 @@ def upLoadLogLogs():
|
||||
# 获取当前的主播列表数据
|
||||
@app.route("/anchorList", methods=['POST'])
|
||||
def queryAnchorList():
|
||||
file_path = "log/acList.json"
|
||||
# 项目根目录(当前文件在 infos 下,回退两层到根目录)
|
||||
root_dir = Path(__file__).resolve().parent.parent
|
||||
file_path = root_dir / "log" / "acList.json"
|
||||
|
||||
data = []
|
||||
if Path(file_path).exists():
|
||||
if file_path.exists():
|
||||
try:
|
||||
with open(file_path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
@@ -421,14 +424,14 @@ def updateAnchorList():
|
||||
new_status = 1 if state else 0
|
||||
|
||||
# 用工具类解析路径,避免 cwd 影响
|
||||
file_path = AiUtils._resolve_path("Module/log/acList.json")
|
||||
file_path = AiUtils._resolve_path("log/acList.json")
|
||||
|
||||
# 加载 JSON
|
||||
try:
|
||||
doc = json.loads(file_path.read_text(encoding="utf-8-sig"))
|
||||
except Exception as e:
|
||||
LogManager.error(f"[updateAnchorList] 读取失败: {e}")
|
||||
return ResultData(code=500, massage=f"读取失败: {e}").toJson()
|
||||
return ResultData(code=1001, message=f"暂无数据").toJson()
|
||||
|
||||
# 定位 anchorList
|
||||
if isinstance(doc, list):
|
||||
@@ -438,7 +441,7 @@ def updateAnchorList():
|
||||
acList = doc["anchorList"]
|
||||
wrapper = doc
|
||||
else:
|
||||
return ResultData(code=500, massage="文件格式不合法").toJson()
|
||||
return ResultData(code=500, message="文件格式不合法").toJson()
|
||||
|
||||
# 遍历并更新
|
||||
updated = 0
|
||||
@@ -454,19 +457,12 @@ def updateAnchorList():
|
||||
file_path.write_text(json.dumps(to_write, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
except Exception as e:
|
||||
LogManager.error(f"[updateAnchorList] 写入失败: {e}")
|
||||
return ResultData(code=500, massage=f"写入失败: {e}").toJson()
|
||||
return ResultData(code=500, message=f"写入失败: {e}").toJson()
|
||||
|
||||
if updated:
|
||||
return ResultData(data=updated, massage=f"已更新 {updated} 条记录").toJson()
|
||||
return ResultData(data=updated, message=f"已更新 {updated} 条记录").toJson()
|
||||
else:
|
||||
return ResultData(data=0, massage="未找到符合条件的记录").toJson()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return ResultData(data=0, message="未找到符合条件的记录").toJson()
|
||||
|
||||
|
||||
# 删除主播
|
||||
@@ -538,6 +534,12 @@ def delete_last_message():
|
||||
return ResultData(data=updated_count, message="修改成功").toJson()
|
||||
return ResultData(data=updated_count, message="修改失败").toJson()
|
||||
|
||||
#的停止所有任务
|
||||
@app.route("/stopAllTask", methods=['POST'])
|
||||
def stopAllTask():
|
||||
idList = request.get_json()
|
||||
code, data , msg = ThreadManager.batch_stop(idList)
|
||||
return ResultData(code, data, msg).toJson()
|
||||
|
||||
# @app.route("/killWda", methods=['POST'])
|
||||
# def killWda():
|
||||
|
||||
Binary file not shown.
@@ -686,15 +686,16 @@ class AiUtils(object):
|
||||
def save_aclist_flat_append(cls, acList, filename="log/acList.json"):
|
||||
"""
|
||||
将 anchor 对象数组平铺追加到 JSON 文件(数组)中。
|
||||
期望 acList 形如:
|
||||
[
|
||||
{"anchorId": "ldn327_", "country": ""},
|
||||
{"anchorId": "tianliang30", "country": ""}
|
||||
]
|
||||
文件固定写到 项目根目录/log/acList.json
|
||||
"""
|
||||
|
||||
# 找到当前文件所在目录,回退到项目根目录
|
||||
root_dir = Path(__file__).resolve().parent.parent # 根据实际层级调整
|
||||
log_dir = root_dir
|
||||
log_dir.mkdir(parents=True, exist_ok=True) # 确保 log 目录存在
|
||||
|
||||
file_path = log_dir / filename
|
||||
|
||||
file_path = Path(filename)
|
||||
data = cls._read_json_list(file_path)
|
||||
|
||||
# 规范化输入,确保都是 {anchorId, country}
|
||||
@@ -705,30 +706,12 @@ class AiUtils(object):
|
||||
|
||||
data.extend(to_add)
|
||||
cls._write_json_list(file_path, data)
|
||||
LogManager.method_info(f"写入的路径是:{file_path}", "写入数据")
|
||||
LogManager.info(f"[acList] 已追加 {len(to_add)} 条,当前总数={len(data)} -> {file_path}")
|
||||
|
||||
# -------- 弹出(取一个删一个) --------
|
||||
# @classmethod
|
||||
# def pop_aclist_first(cls, filename="log/acList.json"):
|
||||
# """
|
||||
# 从 JSON 数组中取出第一个 anchor 对象,并删除它;为空或文件不存在返回 None。
|
||||
# 返回形如:{"anchorId": "...", "country": "..."}
|
||||
# """
|
||||
# file_path = Path(filename)
|
||||
# data = cls._read_json_list(file_path)
|
||||
# if not data:
|
||||
# return None
|
||||
#
|
||||
# first = data.pop(0)
|
||||
# # 兜底保证结构
|
||||
# norm = cls._normalize_anchor_items(first)
|
||||
# first = norm[0] if norm else None
|
||||
#
|
||||
# cls._write_json_list(file_path, data)
|
||||
# return first
|
||||
|
||||
@classmethod
|
||||
def pop_aclist_first(cls, filename="Module/log/acList.json", mode="pop"):
|
||||
def pop_aclist_first(cls, filename="log/acList.json", mode="pop"):
|
||||
"""
|
||||
从 JSON 数组/对象(anchorList)中取出第一个 anchor 对象。
|
||||
- mode="pop" : 取出并删除
|
||||
@@ -867,12 +850,16 @@ class AiUtils(object):
|
||||
@classmethod
|
||||
def delete_anchors_by_ids(cls, ids: list[str], filename="log/acList.json") -> int:
|
||||
"""
|
||||
根据 anchorId 列表从 JSON 文件中删除匹配的 anchor。
|
||||
根据 anchorId 列表从根目录/log/acList.json 中删除匹配的 anchor。
|
||||
返回删除数量。
|
||||
"""
|
||||
file_path = Path(filename)
|
||||
# 确保路径固定在根目录下的 log 文件夹
|
||||
root_dir = Path(__file__).resolve().parent.parent
|
||||
file_path = root_dir / "log" / filename
|
||||
|
||||
if not file_path.exists():
|
||||
return 0
|
||||
|
||||
try:
|
||||
with open(file_path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
@@ -881,15 +868,19 @@ class AiUtils(object):
|
||||
except Exception as e:
|
||||
LogManager.error(f"[delete_anchors_by_ids] 读取失败: {e}")
|
||||
return 0
|
||||
|
||||
before = len(data)
|
||||
# 保留不在 ids 里的对象
|
||||
data = [d for d in data if isinstance(d, dict) and d.get("anchorId") not in ids]
|
||||
deleted = before - len(data)
|
||||
|
||||
try:
|
||||
file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(file_path, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
except Exception as e:
|
||||
LogManager.error(f"[delete_anchors_by_ids] 写入失败: {e}")
|
||||
|
||||
return deleted
|
||||
|
||||
# -------- 查看第一个(取出但不删除) --------
|
||||
@@ -903,7 +894,7 @@ class AiUtils(object):
|
||||
return (base / p).resolve()
|
||||
|
||||
@classmethod
|
||||
def peek_aclist_first(cls, filename="Module/log/acList.json"):
|
||||
def peek_aclist_first(cls, filename="log/acList.json"):
|
||||
file_path = cls._resolve_path(filename)
|
||||
if not file_path.exists():
|
||||
print(f"[peek] 文件不存在: {file_path}")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import threading
|
||||
from typing import Dict, Tuple
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
from typing import Dict, Tuple, List
|
||||
from Utils.LogManager import LogManager
|
||||
|
||||
|
||||
@@ -64,6 +65,37 @@ class ThreadManager:
|
||||
LogManager.method_info(f"设备 {udid} 的任务停止成功", method="task")
|
||||
return 200, f"当前任务停止成功 {udid}"
|
||||
|
||||
@classmethod
|
||||
def batch_stop(cls, udids: List[str]) -> Tuple[int, List[str], str]:
|
||||
"""
|
||||
批量停止任务,使用多线程并发执行。
|
||||
:param udids: 待停止的设备唯一标识列表
|
||||
:return: (code, fail_list, msg)
|
||||
code=200 全部成功,fail_list=[]
|
||||
code=1001 部分/全部失败,fail_list 为失败描述字符串列表
|
||||
"""
|
||||
if not udids:
|
||||
return 200, [], "无设备需要停止"
|
||||
|
||||
fail_list: List[str] = []
|
||||
|
||||
with ThreadPoolExecutor(max_workers=min(32, len(udids))) as executor:
|
||||
future_map = {executor.submit(cls.stop, udid): udid for udid in udids}
|
||||
|
||||
for future in as_completed(future_map):
|
||||
udid = future_map[future]
|
||||
try:
|
||||
code, reason = future.result()
|
||||
if code != 200:
|
||||
fail_list.append(f"设备{udid}停止失败:{reason}")
|
||||
except Exception as exc:
|
||||
fail_list.append(f"设备{udid}停止异常:{exc}")
|
||||
|
||||
if fail_list:
|
||||
return 1001, fail_list, "停止失败"
|
||||
return 200, [], "全部设备停止成功"
|
||||
|
||||
|
||||
@classmethod
|
||||
def is_task_running(cls, udid: str) -> bool:
|
||||
"""
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -244,7 +244,7 @@ class ScriptManager():
|
||||
session.double_tap(x, y)
|
||||
|
||||
print("--------------------------------------------")
|
||||
time.sleep(random.randint(180, 300))
|
||||
time.sleep(random.randint(300, 600))
|
||||
session.swipe_up()
|
||||
|
||||
# 正常退出(外部 event 触发)
|
||||
@@ -320,11 +320,16 @@ class ScriptManager():
|
||||
# 循环条件。1、 循环关闭 2、 数据处理完毕
|
||||
while not event.is_set():
|
||||
|
||||
# 获取一个主播,
|
||||
LogManager.method_info(f"开始获取数据", "关注打招呼", udid)
|
||||
# 获取一个主播,
|
||||
result = AiUtils.peek_aclist_first()
|
||||
state = result.get("state",0)
|
||||
LogManager.method_info(f"数据是:{result}", "关注打招呼", udid)
|
||||
|
||||
state = result.get("state", 0)
|
||||
if not state:
|
||||
LogManager.method_info(f"当前主播的状态是:{state} 不通行,取出数据移到列表尾部 继续下一个", "关注打招呼", udid)
|
||||
LogManager.method_info(f"当前主播的状态是:{state} 不通行,取出数据移到列表尾部 继续下一个", "关注打招呼",
|
||||
udid)
|
||||
AiUtils.pop_aclist_first(mode="move")
|
||||
continue
|
||||
|
||||
@@ -337,7 +342,7 @@ class ScriptManager():
|
||||
time.sleep(30)
|
||||
continue
|
||||
|
||||
aid = anchor["anchorId"]
|
||||
aid = anchor.get("anchorId", "")
|
||||
anchorCountry = anchor.get("country", "")
|
||||
|
||||
LogManager.method_info(f"主播的数据,用户名:{aid},国家:{anchorCountry}", "关注打招呼", udid)
|
||||
|
||||
Binary file not shown.
@@ -1,45 +0,0 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
from PyInstaller.utils.hooks import collect_all
|
||||
|
||||
datas = [('C:\\Users\\milk\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\tidevice', 'tidevice')]
|
||||
binaries = []
|
||||
hiddenimports = ['tidevice._proto', 'tidevice._instruments', 'tidevice._usbmux', 'tidevice._wdaproxy']
|
||||
tmp_ret = collect_all('tidevice')
|
||||
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['tidevice_entry.py'],
|
||||
pathex=[],
|
||||
binaries=binaries,
|
||||
datas=datas,
|
||||
hiddenimports=hiddenimports,
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
noarchive=False,
|
||||
optimize=0,
|
||||
)
|
||||
pyz = PYZ(a.pure)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.datas,
|
||||
[],
|
||||
name='tidevice',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=False,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
Reference in New Issue
Block a user