20250904-初步功能已完成
This commit is contained in:
2
.idea/iOSAI.iml
generated
2
.idea/iOSAI.iml
generated
@@ -4,7 +4,7 @@
|
|||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.12 (IOS-AI)" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.12" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -3,5 +3,5 @@
|
|||||||
<component name="Black">
|
<component name="Black">
|
||||||
<option name="sdkName" value="Python 3.12" />
|
<option name="sdkName" value="Python 3.12" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (IOS-AI)" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
||||||
156
.idea/workspace.xml
generated
156
.idea/workspace.xml
generated
@@ -4,7 +4,10 @@
|
|||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="eceeff5e-51c1-459c-a911-d21ec090a423" name="Changes" comment="20250918-新增主播库功能" />
|
<list default="true" id="eceeff5e-51c1-459c-a911-d21ec090a423" name="Changes" comment="20250904-初步功能已完成">
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/Module/DeviceInfo.py" beforeDir="false" afterPath="$PROJECT_DIR$/Module/DeviceInfo.py" afterDir="false" />
|
||||||
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
@@ -34,9 +37,6 @@
|
|||||||
<component name="HighlightingSettingsPerFile">
|
<component name="HighlightingSettingsPerFile">
|
||||||
<setting file="file://$PROJECT_DIR$/build.bat" root0="SKIP_INSPECTION" />
|
<setting file="file://$PROJECT_DIR$/build.bat" root0="SKIP_INSPECTION" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PerforceDirect.Settings">
|
|
||||||
<option name="CHARSET" value="无" />
|
|
||||||
</component>
|
|
||||||
<component name="ProjectColorInfo">{
|
<component name="ProjectColorInfo">{
|
||||||
"customColor": "",
|
"customColor": "",
|
||||||
"associatedIndex": 5
|
"associatedIndex": 5
|
||||||
@@ -49,50 +49,44 @@
|
|||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent"><![CDATA[{
|
<component name="PropertiesComponent">{
|
||||||
"keyToString": {
|
"keyToString": {
|
||||||
"ASKED_ADD_EXTERNAL_FILES": "true",
|
"ASKED_ADD_EXTERNAL_FILES": "true",
|
||||||
"ASKED_MARK_IGNORED_FILES_AS_EXCLUDED": "true",
|
"ASKED_MARK_IGNORED_FILES_AS_EXCLUDED": "true",
|
||||||
"Python.12.executor": "Run",
|
"Python.12.executor": "Run",
|
||||||
"Python.123 (1).executor": "Run",
|
"Python.123.executor": "Run",
|
||||||
"Python.123.executor": "Run",
|
"Python.Main.executor": "Run",
|
||||||
"Python.Main.executor": "Run",
|
"Python.Test.executor": "Run",
|
||||||
"Python.Test.executor": "Run",
|
"Python.test.executor": "Run",
|
||||||
"Python.test (1).executor": "Run",
|
"Python.tidevice_entry.executor": "Run",
|
||||||
"Python.test (2).executor": "Run",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
"Python.test.executor": "Run",
|
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||||
"Python.tidevice_entry.executor": "Run",
|
"RunOnceActivity.git.unshallow": "true",
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
"git-widget-placeholder": "main",
|
||||||
"RunOnceActivity.git.unshallow": "true",
|
"javascript.nodejs.core.library.configured.version": "20.17.0",
|
||||||
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
"javascript.nodejs.core.library.typings.version": "20.17.58",
|
||||||
"git-widget-placeholder": "main",
|
"last_opened_file_path": "C:/Users/zhangkai/Desktop/20250916ios/iOSAI/resources",
|
||||||
"javascript.nodejs.core.library.configured.version": "20.17.0",
|
"node.js.detected.package.eslint": "true",
|
||||||
"javascript.nodejs.core.library.typings.version": "20.17.58",
|
"node.js.detected.package.tslint": "true",
|
||||||
"last_opened_file_path": "C:/Users/zhangkai/Desktop/20250916ios/iOSAI/Utils",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
"node.js.detected.package.eslint": "true",
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
"node.js.detected.package.tslint": "true",
|
"nodejs_package_manager_path": "npm",
|
||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"settings.editor.selected.configurable": "preferences.editor.code.editing",
|
||||||
"node.js.selected.package.tslint": "(autodetect)",
|
"vue.rearranger.settings.migration": "true"
|
||||||
"nodejs_package_manager_path": "npm",
|
|
||||||
"settings.editor.selected.configurable": "preferences.editor.code.editing",
|
|
||||||
"vue.rearranger.settings.migration": "true"
|
|
||||||
}
|
}
|
||||||
}]]></component>
|
}</component>
|
||||||
<component name="RecentsManager">
|
<component name="RecentsManager">
|
||||||
<key name="CopyFile.RECENT_KEYS">
|
<key name="CopyFile.RECENT_KEYS">
|
||||||
<recent name="C:\Users\zhangkai\Desktop\20250916ios\iOSAI\Utils" />
|
|
||||||
<recent name="C:\Users\zhangkai\Desktop\20250916ios\iOSAI\script" />
|
|
||||||
<recent name="C:\Users\zhangkai\Desktop\20250916ios\iOSAI\resources" />
|
<recent name="C:\Users\zhangkai\Desktop\20250916ios\iOSAI\resources" />
|
||||||
</key>
|
</key>
|
||||||
<key name="MoveFile.RECENT_KEYS">
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
<recent name="C:\Users\zhangkai\Desktop\20250916ios\iOSAI\script" />
|
|
||||||
<recent name="E:\Code\python\iOSAI\resources" />
|
<recent name="E:\Code\python\iOSAI\resources" />
|
||||||
<recent name="E:\Code\python\iOSAI" />
|
<recent name="E:\Code\python\iOSAI" />
|
||||||
</key>
|
</key>
|
||||||
</component>
|
</component>
|
||||||
<component name="RunManager" selected="Python.Main">
|
<component name="RunManager" selected="Python.Main">
|
||||||
<configuration name="123 (1)" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
<configuration name="12" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||||
<module name="iOSAI" />
|
<module name="iOSAI" />
|
||||||
<option name="ENV_FILES" value="" />
|
<option name="ENV_FILES" value="" />
|
||||||
<option name="INTERPRETER_OPTIONS" value="" />
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
@@ -101,12 +95,12 @@
|
|||||||
<env name="PYTHONUNBUFFERED" value="1" />
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
</envs>
|
</envs>
|
||||||
<option name="SDK_HOME" value="" />
|
<option name="SDK_HOME" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/script" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
<option name="IS_MODULE_SDK" value="true" />
|
<option name="IS_MODULE_SDK" value="true" />
|
||||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/script/123.py" />
|
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/12.py" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||||
<option name="EMULATE_TERMINAL" value="false" />
|
<option name="EMULATE_TERMINAL" value="false" />
|
||||||
@@ -129,7 +123,7 @@
|
|||||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||||
<option name="SCRIPT_NAME" value="C:\Users\zhangkai\Desktop\20250916ios\iOSAI\script\123.py" />
|
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/123.py" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||||
<option name="EMULATE_TERMINAL" value="false" />
|
<option name="EMULATE_TERMINAL" value="false" />
|
||||||
@@ -161,7 +155,7 @@
|
|||||||
<option name="INPUT_FILE" value="" />
|
<option name="INPUT_FILE" value="" />
|
||||||
<method v="2" />
|
<method v="2" />
|
||||||
</configuration>
|
</configuration>
|
||||||
<configuration name="test (1)" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
<configuration name="Test" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||||
<module name="iOSAI" />
|
<module name="iOSAI" />
|
||||||
<option name="ENV_FILES" value="" />
|
<option name="ENV_FILES" value="" />
|
||||||
<option name="INTERPRETER_OPTIONS" value="" />
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
@@ -170,35 +164,12 @@
|
|||||||
<env name="PYTHONUNBUFFERED" value="1" />
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
</envs>
|
</envs>
|
||||||
<option name="SDK_HOME" value="" />
|
<option name="SDK_HOME" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/Utils" />
|
||||||
<option name="IS_MODULE_SDK" value="true" />
|
<option name="IS_MODULE_SDK" value="true" />
|
||||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/test.py" />
|
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/Utils/Test.py" />
|
||||||
<option name="PARAMETERS" value="" />
|
|
||||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
|
||||||
<option name="EMULATE_TERMINAL" value="false" />
|
|
||||||
<option name="MODULE_MODE" value="false" />
|
|
||||||
<option name="REDIRECT_INPUT" value="false" />
|
|
||||||
<option name="INPUT_FILE" value="" />
|
|
||||||
<method v="2" />
|
|
||||||
</configuration>
|
|
||||||
<configuration name="test (2)" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
|
||||||
<module name="iOSAI" />
|
|
||||||
<option name="ENV_FILES" value="" />
|
|
||||||
<option name="INTERPRETER_OPTIONS" value="" />
|
|
||||||
<option name="PARENT_ENVS" value="true" />
|
|
||||||
<envs>
|
|
||||||
<env name="PYTHONUNBUFFERED" value="1" />
|
|
||||||
</envs>
|
|
||||||
<option name="SDK_HOME" value="" />
|
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/script" />
|
|
||||||
<option name="IS_MODULE_SDK" value="true" />
|
|
||||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
|
||||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
|
||||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
|
||||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/script/test.py" />
|
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||||
<option name="EMULATE_TERMINAL" value="false" />
|
<option name="EMULATE_TERMINAL" value="false" />
|
||||||
@@ -232,19 +203,17 @@
|
|||||||
</configuration>
|
</configuration>
|
||||||
<recent_temporary>
|
<recent_temporary>
|
||||||
<list>
|
<list>
|
||||||
<item itemvalue="Python.123 (1)" />
|
|
||||||
<item itemvalue="Python.123" />
|
|
||||||
<item itemvalue="Python.test (1)" />
|
|
||||||
<item itemvalue="Python.test (2)" />
|
|
||||||
<item itemvalue="Python.test" />
|
<item itemvalue="Python.test" />
|
||||||
|
<item itemvalue="Python.123" />
|
||||||
|
<item itemvalue="Python.Test" />
|
||||||
|
<item itemvalue="Python.12" />
|
||||||
</list>
|
</list>
|
||||||
</recent_temporary>
|
</recent_temporary>
|
||||||
</component>
|
</component>
|
||||||
<component name="SharedIndexes">
|
<component name="SharedIndexes">
|
||||||
<attachedChunks>
|
<attachedChunks>
|
||||||
<set>
|
<set>
|
||||||
<option value="bundled-js-predefined-1d06a55b98c1-0b3e54e931b4-JavaScript-PY-241.18034.82" />
|
<option value="bundled-python-sdk-ce6832f46686-7b97d883f26b-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-252.25557.178" />
|
||||||
<option value="bundled-python-sdk-975db3bf15a3-2767605e8bc2-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-241.18034.82" />
|
|
||||||
</set>
|
</set>
|
||||||
</attachedChunks>
|
</attachedChunks>
|
||||||
</component>
|
</component>
|
||||||
@@ -310,10 +279,6 @@
|
|||||||
<workItem from="1757506636968" duration="5910000" />
|
<workItem from="1757506636968" duration="5910000" />
|
||||||
<workItem from="1757567423145" duration="16668000" />
|
<workItem from="1757567423145" duration="16668000" />
|
||||||
<workItem from="1757998910052" duration="3676000" />
|
<workItem from="1757998910052" duration="3676000" />
|
||||||
<workItem from="1758122148569" duration="213000" />
|
|
||||||
<workItem from="1758171936953" duration="7319000" />
|
|
||||||
<workItem from="1758180127232" duration="653000" />
|
|
||||||
<workItem from="1758182513694" duration="19233000" />
|
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00001" summary="ai 开始测试">
|
<task id="LOCAL-00001" summary="ai 开始测试">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
@@ -355,31 +320,7 @@
|
|||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1757587781103</updated>
|
<updated>1757587781103</updated>
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00006" summary="20250904-初步功能已完成">
|
<option name="localTasksCounter" value="6" />
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1758121742405</created>
|
|
||||||
<option name="number" value="00006" />
|
|
||||||
<option name="presentableId" value="LOCAL-00006" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1758121742405</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00007" summary="20250918-新增主播库功能">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1758197707496</created>
|
|
||||||
<option name="number" value="00007" />
|
|
||||||
<option name="presentableId" value="LOCAL-00007" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1758197707496</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00008" summary="20250918-新增主播库功能">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1758202317131</created>
|
|
||||||
<option name="number" value="00008" />
|
|
||||||
<option name="presentableId" value="LOCAL-00008" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1758202317131</updated>
|
|
||||||
</task>
|
|
||||||
<option name="localTasksCounter" value="9" />
|
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
@@ -403,25 +344,22 @@
|
|||||||
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
|
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
|
||||||
<MESSAGE value="ai 开始测试" />
|
<MESSAGE value="ai 开始测试" />
|
||||||
<MESSAGE value="20250904-初步功能已完成" />
|
<MESSAGE value="20250904-初步功能已完成" />
|
||||||
<MESSAGE value="20250918-新增主播库功能" />
|
<option name="LAST_COMMIT_MESSAGE" value="20250904-初步功能已完成" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="20250918-新增主播库功能" />
|
|
||||||
</component>
|
</component>
|
||||||
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$LogManager.coverage" NAME="LogManager 覆盖结果" MODIFIED="1756711414832" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/Utils" />
|
<SUITE FILE_PATH="coverage/iOSAI$LogManager.coverage" NAME="LogManager 覆盖结果" MODIFIED="1756711414832" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/Utils" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$FlaskService.coverage" NAME="FlaskService 覆盖结果" MODIFIED="1756730187792" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/Module" />
|
<SUITE FILE_PATH="coverage/iOSAI$FlaskService.coverage" NAME="FlaskService 覆盖结果" MODIFIED="1756730187792" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/Module" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$test.coverage" NAME="test 覆盖结果" MODIFIED="1758183945062" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/Utils" />
|
<SUITE FILE_PATH="coverage/iOSAI$test.coverage" NAME="test 覆盖结果" MODIFIED="1756467664420" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$windows_run.coverage" NAME="windows_run Coverage Results" MODIFIED="1756473558532" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/script" />
|
<SUITE FILE_PATH="coverage/iOSAI$windows_run.coverage" NAME="windows_run Coverage Results" MODIFIED="1756473558532" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/script" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$1352.coverage" NAME="1352 覆盖结果" MODIFIED="1757662777051" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
<SUITE FILE_PATH="coverage/iOSAI$1352.coverage" NAME="1352 覆盖结果" MODIFIED="1757662777051" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$mac_wda_agent.coverage" NAME="mac_wda_agent Coverage Results" MODIFIED="1756473148639" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/script" />
|
<SUITE FILE_PATH="coverage/iOSAI$mac_wda_agent.coverage" NAME="mac_wda_agent Coverage Results" MODIFIED="1756473148639" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/script" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$123456.coverage" NAME="123456 覆盖结果" MODIFIED="1757672582575" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
<SUITE FILE_PATH="coverage/iOSAI$123456.coverage" NAME="123456 覆盖结果" MODIFIED="1757672582575" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$2111.coverage" NAME="2111 覆盖结果" MODIFIED="1757330714370" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
<SUITE FILE_PATH="coverage/iOSAI$2111.coverage" NAME="2111 覆盖结果" MODIFIED="1757330714370" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$456.coverage" NAME="456 覆盖结果" MODIFIED="1757654671631" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
<SUITE FILE_PATH="coverage/iOSAI$456.coverage" NAME="456 覆盖结果" MODIFIED="1757654671631" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$123__1_.coverage" NAME="123 (1) 覆盖结果" MODIFIED="1758201139058" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/script" />
|
<SUITE FILE_PATH="coverage/iOSAI$123__1_.coverage" NAME="123 (1) 覆盖结果" MODIFIED="1756897091135" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$test__1_.coverage" NAME="test (1) 覆盖结果" MODIFIED="1758193027385" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$tidevice_entry.coverage" NAME="tidevice_entry 覆盖结果" MODIFIED="1757061969626" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
<SUITE FILE_PATH="coverage/iOSAI$tidevice_entry.coverage" NAME="tidevice_entry 覆盖结果" MODIFIED="1757061969626" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$ScriptManager.coverage" NAME="ScriptManager 覆盖结果" MODIFIED="1756896057801" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/script" />
|
<SUITE FILE_PATH="coverage/iOSAI$ScriptManager.coverage" NAME="ScriptManager 覆盖结果" MODIFIED="1756896057801" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/script" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$Main.coverage" NAME="Main 覆盖结果" MODIFIED="1758201539285" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
|
<SUITE FILE_PATH="coverage/iOSAI$Main.coverage" NAME="Main 覆盖结果" MODIFIED="1758120400301" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$123.coverage" NAME="123 覆盖结果" MODIFIED="1758200468014" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
<SUITE FILE_PATH="coverage/iOSAI$123.coverage" NAME="123 覆盖结果" MODIFIED="1758115088356" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||||
<SUITE FILE_PATH="coverage/iOSAI$test__2_.coverage" NAME="test (2) 覆盖结果" MODIFIED="1758192701951" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/script" />
|
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -2,15 +2,15 @@ import json
|
|||||||
|
|
||||||
# 返回数据模型
|
# 返回数据模型
|
||||||
class ResultData(object):
|
class ResultData(object):
|
||||||
def __init__(self, code=200, data=None, massage="获取成功"):
|
def __init__(self, code=200, data=None, message="获取成功"):
|
||||||
super(ResultData, self).__init__()
|
super(ResultData, self).__init__()
|
||||||
self.code = code
|
self.code = code
|
||||||
self.data = data
|
self.data = data
|
||||||
self.massage = massage
|
self.message = message
|
||||||
|
|
||||||
def toJson(self):
|
def toJson(self):
|
||||||
return json.dumps({
|
return json.dumps({
|
||||||
"code": self.code,
|
"code": self.code,
|
||||||
"data": self.data,
|
"data": self.data,
|
||||||
"massage": self.massage
|
"message": self.message
|
||||||
}, ensure_ascii=False) # ensure_ascii=False 确保中文不会被转义
|
}, ensure_ascii=False) # ensure_ascii=False 确保中文不会被转义
|
||||||
@@ -4,12 +4,12 @@ import signal
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||||
|
|
||||||
import wda
|
|
||||||
import threading
|
|
||||||
import subprocess
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Dict, Optional
|
from typing import List, Dict, Optional
|
||||||
|
import threading
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
import wda
|
||||||
from tidevice import Usbmux, ConnectionType
|
from tidevice import Usbmux, ConnectionType
|
||||||
from tidevice._device import BaseDevice
|
from tidevice._device import BaseDevice
|
||||||
from Entity.DeviceModel import DeviceModel
|
from Entity.DeviceModel import DeviceModel
|
||||||
@@ -23,10 +23,8 @@ class Deviceinfo(object):
|
|||||||
"""设备生命周期管理:以 deviceModelList 为唯一真理源"""
|
"""设备生命周期管理:以 deviceModelList 为唯一真理源"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
...
|
# ✅ 连接线程池(最大 6 并发)
|
||||||
# ✅ 新增:连接线程池(最大 6 并发)
|
|
||||||
self._connect_pool = ThreadPoolExecutor(max_workers=6)
|
self._connect_pool = ThreadPoolExecutor(max_workers=6)
|
||||||
...
|
|
||||||
|
|
||||||
if os.name == "nt":
|
if os.name == "nt":
|
||||||
self._si = subprocess.STARTUPINFO()
|
self._si = subprocess.STARTUPINFO()
|
||||||
@@ -44,11 +42,14 @@ class Deviceinfo(object):
|
|||||||
|
|
||||||
self._lock = threading.Lock()
|
self._lock = threading.Lock()
|
||||||
self._model_index: Dict[str, DeviceModel] = {} # udid -> model
|
self._model_index: Dict[str, DeviceModel] = {} # udid -> model
|
||||||
# ✅ 1. 失踪时间戳记录(替代原来的 miss_count)
|
# ✅ 失踪时间戳记录(替代原来的 miss_count)
|
||||||
self._last_seen: Dict[str, float] = {}
|
self._last_seen: Dict[str, float] = {}
|
||||||
self._port_pool: List[int] = []
|
self._port_pool: List[int] = []
|
||||||
self._port_in_use: set[int] = set()
|
self._port_in_use: set[int] = set()
|
||||||
|
|
||||||
|
# ✅ 新增:全局 iproxy 进程注册表 udid -> Popen
|
||||||
|
self._iproxy_registry: Dict[str, subprocess.Popen] = {}
|
||||||
|
|
||||||
# region iproxy 初始化(原逻辑不变)
|
# region iproxy 初始化(原逻辑不变)
|
||||||
try:
|
try:
|
||||||
self.iproxy_path = self._iproxy_path()
|
self.iproxy_path = self._iproxy_path()
|
||||||
@@ -76,6 +77,9 @@ class Deviceinfo(object):
|
|||||||
args = [str(self.iproxy_path), "-u", udid, str(local_port), str(remote_port)]
|
args = [str(self.iproxy_path), "-u", udid, str(local_port), str(remote_port)]
|
||||||
p = subprocess.Popen(args, **self._popen_kwargs)
|
p = subprocess.Popen(args, **self._popen_kwargs)
|
||||||
|
|
||||||
|
# ✅ 注册到全局表
|
||||||
|
self._iproxy_registry[udid] = p
|
||||||
|
|
||||||
def _pipe_to_log(name: str, stream):
|
def _pipe_to_log(name: str, stream):
|
||||||
try:
|
try:
|
||||||
for line in iter(stream.readline, ''):
|
for line in iter(stream.readline, ''):
|
||||||
@@ -127,6 +131,13 @@ class Deviceinfo(object):
|
|||||||
for udid in need_remove:
|
for udid in need_remove:
|
||||||
self._remove_model(udid)
|
self._remove_model(udid)
|
||||||
|
|
||||||
|
# ✅ 实时清理孤儿 iproxy(原 10 秒改为每次循环)
|
||||||
|
self._cleanup_orphan_iproxy()
|
||||||
|
|
||||||
|
# ✅ 设备全空时核平所有 iproxy
|
||||||
|
if not self.deviceModelList:
|
||||||
|
self._kill_all_iproxy()
|
||||||
|
|
||||||
# 2. 发现新设备 → 并发连接
|
# 2. 发现新设备 → 并发连接
|
||||||
with self._lock:
|
with self._lock:
|
||||||
new_udids = [d.udid for d in lists
|
new_udids = [d.udid for d in lists
|
||||||
@@ -146,7 +157,7 @@ class Deviceinfo(object):
|
|||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# ✅ 3. USB 层枚举 SN(跨平台)
|
# ✅ USB 层枚举 SN(跨平台)
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
def _usb_enumerate_sn(self) -> set[str]:
|
def _usb_enumerate_sn(self) -> set[str]:
|
||||||
try:
|
try:
|
||||||
@@ -155,7 +166,32 @@ class Deviceinfo(object):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return set()
|
return set()
|
||||||
|
|
||||||
# ===================== 以下代码与原文件完全一致 =====================
|
# ----------------------------------------------------------
|
||||||
|
# ✅ 清理孤儿 iproxy
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
def _cleanup_orphan_iproxy(self):
|
||||||
|
live_udids = set(self._model_index.keys())
|
||||||
|
for udid, proc in list(self._iproxy_registry.items()):
|
||||||
|
if udid not in live_udids:
|
||||||
|
LogManager.warning(f"发现孤儿 iproxy 进程,UDID 不在线:{udid},正在清理")
|
||||||
|
self._terminate_proc(proc)
|
||||||
|
self._iproxy_registry.pop(udid, None)
|
||||||
|
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# ✅ 核平所有 iproxy(Windows / macOS 通用)
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
def _kill_all_iproxy(self):
|
||||||
|
try:
|
||||||
|
if os.name == "nt":
|
||||||
|
subprocess.run(["taskkill", "/F", "/IM", "iproxy.exe"], check=False)
|
||||||
|
else:
|
||||||
|
subprocess.run(["pkill", "-f", "iproxy"], check=False)
|
||||||
|
self._iproxy_registry.clear()
|
||||||
|
LogManager.info("已强制清理所有 iproxy 进程")
|
||||||
|
except Exception as e:
|
||||||
|
LogManager.warning(f"强制清理 iproxy 失败:{e}")
|
||||||
|
|
||||||
|
# -------------------- 以下代码与原文件完全一致 --------------------
|
||||||
def _wda_health_checker(self):
|
def _wda_health_checker(self):
|
||||||
while True:
|
while True:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
@@ -229,6 +265,11 @@ class Deviceinfo(object):
|
|||||||
print(f"【删】待杀进程数 count={len(to_kill)} udid={udid}")
|
print(f"【删】待杀进程数 count={len(to_kill)} udid={udid}")
|
||||||
LogManager.method_info(f"【删】待杀进程数 count={len(to_kill)} udid={udid}", method="device_count")
|
LogManager.method_info(f"【删】待杀进程数 count={len(to_kill)} udid={udid}", method="device_count")
|
||||||
|
|
||||||
|
# ✅ 先清理注册表中的 iproxy
|
||||||
|
iproxy_proc = self._iproxy_registry.pop(udid, None)
|
||||||
|
if iproxy_proc:
|
||||||
|
self._terminate_proc(iproxy_proc)
|
||||||
|
|
||||||
for idx, item in enumerate(to_kill, 1):
|
for idx, item in enumerate(to_kill, 1):
|
||||||
print(f"【删】杀进程 {idx}/{len(to_kill)} pid={item.get('target').pid} udid={udid}")
|
print(f"【删】杀进程 {idx}/{len(to_kill)} pid={item.get('target').pid} udid={udid}")
|
||||||
LogManager.method_info(f"【删】杀进程 {idx}/{len(to_kill)} pid={item.get('target').pid} udid={udid}", method="device_count")
|
LogManager.method_info(f"【删】杀进程 {idx}/{len(to_kill)} pid={item.get('target').pid} udid={udid}", method="device_count")
|
||||||
@@ -335,13 +376,14 @@ class Deviceinfo(object):
|
|||||||
if not self._spawn_iproxy:
|
if not self._spawn_iproxy:
|
||||||
LogManager.error("iproxy 启动器未就绪", udid)
|
LogManager.error("iproxy 启动器未就绪", udid)
|
||||||
return None
|
return None
|
||||||
while self._port_in_use and self._is_port_open(port):
|
for attempt in range(5):
|
||||||
|
if not self._is_port_open(port):
|
||||||
|
break
|
||||||
|
LogManager.warning(f"端口 {port} 仍被占用,第 {attempt+1} 次重试释放", udid)
|
||||||
pid = self._get_pid_by_port(port)
|
pid = self._get_pid_by_port(port)
|
||||||
if pid and pid != os.getpid():
|
if pid and pid != os.getpid():
|
||||||
LogManager.warning(f"端口 {port} 仍被 PID {pid} 占用,尝试释放", udid)
|
|
||||||
self._kill_pid_gracefully(pid)
|
self._kill_pid_gracefully(pid)
|
||||||
else:
|
time.sleep(0.2)
|
||||||
break
|
|
||||||
try:
|
try:
|
||||||
p = self._spawn_iproxy(udid, port, 9100)
|
p = self._spawn_iproxy(udid, port, 9100)
|
||||||
self._port_in_use.add(port)
|
self._port_in_use.add(port)
|
||||||
|
|||||||
@@ -244,8 +244,8 @@ def growAccount():
|
|||||||
thread = threading.Thread(target=manager.growAccount, args=(udid, event))
|
thread = threading.Thread(target=manager.growAccount, args=(udid, event))
|
||||||
thread.start()
|
thread.start()
|
||||||
# 添加到线程管理
|
# 添加到线程管理
|
||||||
ThreadManager.add(udid, thread, event)
|
code , msg = ThreadManager.add(udid, thread, event)
|
||||||
return ResultData(data="").toJson()
|
return ResultData(data="", code=code, message= msg).toJson()
|
||||||
|
|
||||||
|
|
||||||
# 观看直播
|
# 观看直播
|
||||||
@@ -269,7 +269,7 @@ def stopScript():
|
|||||||
udid = body.get("udid")
|
udid = body.get("udid")
|
||||||
LogManager.method_info(f"接口收到 /stopScript udid={udid}", method="task")
|
LogManager.method_info(f"接口收到 /stopScript udid={udid}", method="task")
|
||||||
code, msg = ThreadManager.stop(udid)
|
code, msg = ThreadManager.stop(udid)
|
||||||
return ResultData(code=code, data="", massage=msg).toJson()
|
return ResultData(code=code, data="", message=msg).toJson()
|
||||||
|
|
||||||
|
|
||||||
# 关注打招呼
|
# 关注打招呼
|
||||||
@@ -305,6 +305,7 @@ def passAnchorData():
|
|||||||
return ResultData(data="").toJson()
|
return ResultData(data="").toJson()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LogManager.error(e)
|
LogManager.error(e)
|
||||||
|
return ResultData(data="", code=1001).toJson()
|
||||||
|
|
||||||
|
|
||||||
# 获取私信数据
|
# 获取私信数据
|
||||||
@@ -325,7 +326,7 @@ def addTempAnchorData():
|
|||||||
"""
|
"""
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
if not data:
|
if not data:
|
||||||
return ResultData(code=400, massage="请求数据为空").toJson()
|
return ResultData(code=400, message="请求数据为空").toJson()
|
||||||
# 追加到 JSON 文件
|
# 追加到 JSON 文件
|
||||||
AiUtils.save_aclist_flat_append(data, "log/acList.json")
|
AiUtils.save_aclist_flat_append(data, "log/acList.json")
|
||||||
return ResultData(data="ok").toJson()
|
return ResultData(data="ok").toJson()
|
||||||
@@ -359,7 +360,7 @@ def getChatTextInfo():
|
|||||||
'text': 'Unable to retrieve chat messages on the current screen. Please navigate to the TikTok chat page and try again!!!'
|
'text': 'Unable to retrieve chat messages on the current screen. Please navigate to the TikTok chat page and try again!!!'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
return ResultData(data=data, massage="解析失败").toJson()
|
return ResultData(data=data, message="解析失败").toJson()
|
||||||
|
|
||||||
|
|
||||||
# 监控消息
|
# 监控消息
|
||||||
@@ -386,7 +387,7 @@ def upLoadLogLogs():
|
|||||||
if ok:
|
if ok:
|
||||||
return ResultData(data="日志上传成功").toJson()
|
return ResultData(data="日志上传成功").toJson()
|
||||||
else:
|
else:
|
||||||
return ResultData(data="", massage="日志上传失败").toJson()
|
return ResultData(data="", message="日志上传失败").toJson()
|
||||||
|
|
||||||
|
|
||||||
# 获取当前的主播列表数据
|
# 获取当前的主播列表数据
|
||||||
@@ -517,8 +518,8 @@ def update_last_message():
|
|||||||
multi=False # 只改第一条匹配的
|
multi=False # 只改第一条匹配的
|
||||||
)
|
)
|
||||||
if updated_count > 0:
|
if updated_count > 0:
|
||||||
return ResultData(data=updated_count, massage="修改成功").toJson()
|
return ResultData(data=updated_count, message="修改成功").toJson()
|
||||||
return ResultData(data=updated_count, massage="修改失败").toJson()
|
return ResultData(data=updated_count, message="修改失败").toJson()
|
||||||
|
|
||||||
|
|
||||||
@app.route("/delete_last_message", methods=['POST'])
|
@app.route("/delete_last_message", methods=['POST'])
|
||||||
@@ -534,8 +535,8 @@ def delete_last_message():
|
|||||||
multi=False # 只改第一条匹配的
|
multi=False # 只改第一条匹配的
|
||||||
)
|
)
|
||||||
if updated_count > 0:
|
if updated_count > 0:
|
||||||
return ResultData(data=updated_count, massage="修改成功").toJson()
|
return ResultData(data=updated_count, message="修改成功").toJson()
|
||||||
return ResultData(data=updated_count, massage="修改失败").toJson()
|
return ResultData(data=updated_count, message="修改失败").toJson()
|
||||||
|
|
||||||
|
|
||||||
# @app.route("/killWda", methods=['POST'])
|
# @app.route("/killWda", methods=['POST'])
|
||||||
|
|||||||
@@ -105,7 +105,6 @@ class FlaskSubprocessManager:
|
|||||||
|
|
||||||
# 守护线程:把子进程 stdout → LogManager.info/system
|
# 守护线程:把子进程 stdout → LogManager.info/system
|
||||||
threading.Thread(target=self._flush_stdout, daemon=True).start()
|
threading.Thread(target=self._flush_stdout, daemon=True).start()
|
||||||
|
|
||||||
LogManager.info(f"Flask 子进程已启动,PID={self.process.pid},端口={self.comm_port}", udid="system")
|
LogManager.info(f"Flask 子进程已启动,PID={self.process.pid},端口={self.comm_port}", udid="system")
|
||||||
|
|
||||||
if not self._wait_port_open(timeout=10):
|
if not self._wait_port_open(timeout=10):
|
||||||
@@ -122,6 +121,8 @@ class FlaskSubprocessManager:
|
|||||||
for line in iter(self.process.stdout.readline, ""):
|
for line in iter(self.process.stdout.readline, ""):
|
||||||
if line:
|
if line:
|
||||||
LogManager.info(line.rstrip(), udid="system")
|
LogManager.info(line.rstrip(), udid="system")
|
||||||
|
# 同时输出到控制台
|
||||||
|
print(line.rstrip()) # 打印到主进程的控制台
|
||||||
self.process.stdout.close()
|
self.process.stdout.close()
|
||||||
|
|
||||||
# ---------- 发送 ----------
|
# ---------- 发送 ----------
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from Module.DeviceInfo import Deviceinfo
|
from Module.DeviceInfo import Deviceinfo
|
||||||
from Module.FlaskSubprocessManager import FlaskSubprocessManager
|
from Module.FlaskSubprocessManager import FlaskSubprocessManager
|
||||||
from Utils.DevDiskImageDeployer import DevDiskImageDeployer
|
from Utils.DevDiskImageDeployer import DevDiskImageDeployer
|
||||||
from Utils.LogManager import LogManager
|
|
||||||
|
|
||||||
|
|
||||||
# 确定 exe 或 py 文件所在目录
|
# 确定 exe 或 py 文件所在目录
|
||||||
BASE = Path(getattr(sys, 'frozen', False) and sys.executable or __file__).resolve().parent
|
BASE = Path(getattr(sys, 'frozen', False) and sys.executable or __file__).resolve().parent
|
||||||
|
|||||||
BIN
SupportFiles/14.0.zip
Normal file
BIN
SupportFiles/14.0.zip
Normal file
Binary file not shown.
BIN
SupportFiles/14.1.zip
Normal file
BIN
SupportFiles/14.1.zip
Normal file
Binary file not shown.
BIN
SupportFiles/14.2.zip
Normal file
BIN
SupportFiles/14.2.zip
Normal file
Binary file not shown.
BIN
SupportFiles/14.3.zip
Normal file
BIN
SupportFiles/14.3.zip
Normal file
Binary file not shown.
BIN
SupportFiles/14.4.zip
Normal file
BIN
SupportFiles/14.4.zip
Normal file
Binary file not shown.
BIN
SupportFiles/14.5.zip
Normal file
BIN
SupportFiles/14.5.zip
Normal file
Binary file not shown.
BIN
SupportFiles/14.6.zip
Normal file
BIN
SupportFiles/14.6.zip
Normal file
Binary file not shown.
BIN
SupportFiles/14.7.zip
Normal file
BIN
SupportFiles/14.7.zip
Normal file
Binary file not shown.
BIN
SupportFiles/14.8.zip
Normal file
BIN
SupportFiles/14.8.zip
Normal file
Binary file not shown.
BIN
SupportFiles/15.0.zip
Normal file
BIN
SupportFiles/15.0.zip
Normal file
Binary file not shown.
BIN
SupportFiles/15.1.zip
Normal file
BIN
SupportFiles/15.1.zip
Normal file
Binary file not shown.
BIN
SupportFiles/15.2.zip
Normal file
BIN
SupportFiles/15.2.zip
Normal file
Binary file not shown.
BIN
SupportFiles/15.3.zip
Normal file
BIN
SupportFiles/15.3.zip
Normal file
Binary file not shown.
BIN
SupportFiles/15.4.zip
Normal file
BIN
SupportFiles/15.4.zip
Normal file
Binary file not shown.
BIN
SupportFiles/15.5.zip
Normal file
BIN
SupportFiles/15.5.zip
Normal file
Binary file not shown.
BIN
SupportFiles/15.6.zip
Normal file
BIN
SupportFiles/15.6.zip
Normal file
Binary file not shown.
BIN
SupportFiles/15.7.zip
Normal file
BIN
SupportFiles/15.7.zip
Normal file
Binary file not shown.
BIN
SupportFiles/15.8.zip
Normal file
BIN
SupportFiles/15.8.zip
Normal file
Binary file not shown.
BIN
SupportFiles/16.0.zip
Normal file
BIN
SupportFiles/16.0.zip
Normal file
Binary file not shown.
BIN
SupportFiles/16.1.zip
Normal file
BIN
SupportFiles/16.1.zip
Normal file
Binary file not shown.
BIN
SupportFiles/16.2.zip
Normal file
BIN
SupportFiles/16.2.zip
Normal file
Binary file not shown.
BIN
SupportFiles/16.3.zip
Normal file
BIN
SupportFiles/16.3.zip
Normal file
Binary file not shown.
BIN
SupportFiles/16.4.zip
Normal file
BIN
SupportFiles/16.4.zip
Normal file
Binary file not shown.
BIN
SupportFiles/16.5.zip
Normal file
BIN
SupportFiles/16.5.zip
Normal file
Binary file not shown.
BIN
SupportFiles/16.6.zip
Normal file
BIN
SupportFiles/16.6.zip
Normal file
Binary file not shown.
BIN
SupportFiles/16.7.zip
Normal file
BIN
SupportFiles/16.7.zip
Normal file
Binary file not shown.
@@ -79,7 +79,6 @@ class ControlUtils(object):
|
|||||||
"//Window[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]").exists:
|
"//Window[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]").exists:
|
||||||
back = session.xpath(
|
back = session.xpath(
|
||||||
"//Window[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]")
|
"//Window[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]")
|
||||||
|
|
||||||
if back.exists:
|
if back.exists:
|
||||||
back.click()
|
back.click()
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -28,43 +28,6 @@ def _force_utf8_everywhere():
|
|||||||
|
|
||||||
# _force_utf8_everywhere()
|
# _force_utf8_everywhere()
|
||||||
|
|
||||||
|
|
||||||
# ========= 全局:强制 UTF-8 + 关闭缓冲(运行期立刻生效) =========
|
|
||||||
def _force_utf8_everywhere():
|
|
||||||
os.environ.setdefault("PYTHONUTF8", "1")
|
|
||||||
# 等价于 -u:让 stdout/stderr 无缓冲
|
|
||||||
os.environ.setdefault("PYTHONUNBUFFERED", "1")
|
|
||||||
os.environ.setdefault("PYTHONIOENCODING", "utf-8")
|
|
||||||
|
|
||||||
# 若是 3.7+,优先用 reconfigure 实时改流
|
|
||||||
try:
|
|
||||||
if hasattr(sys.stdout, "reconfigure"):
|
|
||||||
sys.stdout.reconfigure(encoding="utf-8", errors="replace",
|
|
||||||
line_buffering=True, write_through=True)
|
|
||||||
elif getattr(sys.stdout, "buffer", None):
|
|
||||||
# 退路:重新包一层,启用行缓冲 + 直写
|
|
||||||
sys.stdout = io.TextIOWrapper(
|
|
||||||
sys.stdout.buffer, encoding="utf-8",
|
|
||||||
errors="replace", line_buffering=True
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
if hasattr(sys.stderr, "reconfigure"):
|
|
||||||
sys.stderr.reconfigure(encoding="utf-8", errors="replace",
|
|
||||||
line_buffering=True, write_through=True)
|
|
||||||
elif getattr(sys.stderr, "buffer", None):
|
|
||||||
sys.stderr = io.TextIOWrapper(
|
|
||||||
sys.stderr.buffer, encoding="utf-8",
|
|
||||||
errors="replace", line_buffering=True
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# ===========================================================
|
|
||||||
|
|
||||||
|
|
||||||
class LogManager:
|
class LogManager:
|
||||||
"""
|
"""
|
||||||
设备级与“设备+方法”级日志管理:
|
设备级与“设备+方法”级日志管理:
|
||||||
|
|||||||
@@ -1,126 +1,77 @@
|
|||||||
import os
|
|
||||||
import signal
|
|
||||||
import sys
|
|
||||||
import threading
|
import threading
|
||||||
import time
|
from typing import Dict, Tuple
|
||||||
import psutil
|
|
||||||
import subprocess
|
|
||||||
from pathlib import Path
|
|
||||||
from threading import Event, Thread
|
|
||||||
from typing import Dict, Optional
|
|
||||||
|
|
||||||
from Utils.LogManager import LogManager
|
from Utils.LogManager import LogManager
|
||||||
|
|
||||||
|
|
||||||
class ThreadManager:
|
class ThreadManager:
|
||||||
"""
|
_tasks: Dict[str, Dict] = {}
|
||||||
对调用方完全透明:
|
|
||||||
add(udid, thread_obj, stop_event) 保持原签名
|
|
||||||
stop(udid) 保持原签名
|
|
||||||
但内部把 thread_obj 当成“壳”,真正拉起的是子进程。
|
|
||||||
"""
|
|
||||||
_pool: Dict[str, psutil.Process] = {}
|
|
||||||
_lock = threading.Lock()
|
_lock = threading.Lock()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add(cls, udid: str, dummy_thread, dummy_event: Event) -> None:
|
def add(cls, udid: str, thread: threading.Thread, event: threading.Event) -> Tuple[int, str]:
|
||||||
LogManager.method_info(f"【1】入口 udid={udid} 长度={len(udid)}", method="task")
|
"""
|
||||||
if udid in cls._pool:
|
添加一个线程到线程管理器。
|
||||||
LogManager.method_warning(f"{udid} 仍在运行,先强制清理旧任务", method="task")
|
:param udid: 设备的唯一标识符
|
||||||
cls.stop(udid)
|
:param thread: 线程对象
|
||||||
LogManager.method_info(f"【2】判断旧任务后 udid={udid} 长度={len(udid)}", method="task")
|
:param event: 用于控制线程退出的 Event 对象
|
||||||
port = cls._find_free_port()
|
:return: 状态码和信息
|
||||||
LogManager.method_info(f"【3】找端口后 udid={udid} 长度={len(udid)}", method="task")
|
"""
|
||||||
proc = cls._start_worker_process(udid, port)
|
with cls._lock:
|
||||||
LogManager.method_info(f"【4】子进程启动后 udid={udid} 长度={len(udid)}", method="task")
|
if udid in cls._tasks and cls._tasks[udid].get("running", False):
|
||||||
cls._pool[udid] = proc
|
LogManager.method_info(f"任务添加失败:设备 {udid} 已存在运行中的任务", method="task")
|
||||||
LogManager.method_info(f"【5】已写入字典,udid={udid} 长度={len(udid)}", method="task")
|
return 400, f"该设备中已存在任务 {udid}"
|
||||||
|
|
||||||
|
# 如果任务已经存在但已停止,清理旧任务记录
|
||||||
|
if udid in cls._tasks and not cls._tasks[udid].get("running", False):
|
||||||
|
LogManager.method_info(f"清理设备 {udid} 的旧任务记录", method="task")
|
||||||
|
del cls._tasks[udid]
|
||||||
|
|
||||||
|
# 添加新任务记录
|
||||||
|
cls._tasks[udid] = {
|
||||||
|
"thread": thread,
|
||||||
|
"event": event,
|
||||||
|
"running": True
|
||||||
|
}
|
||||||
|
LogManager.method_info(f"设备 {udid} 开始任务成功", method="task")
|
||||||
|
return 200, f"创建任务成功 {udid}"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def stop(cls, udid: str) -> tuple[int, str]:
|
def stop(cls, udid: str) -> Tuple[int, str]:
|
||||||
with cls._lock: # 类级锁
|
|
||||||
proc = cls._pool.get(udid) # 1. 只读,不删
|
|
||||||
if proc is None:
|
|
||||||
return 1001, f"无此任务 {udid}"
|
|
||||||
|
|
||||||
try:
|
|
||||||
proc.terminate()
|
|
||||||
gone, alive = psutil.wait_procs([proc], timeout=3)
|
|
||||||
if alive:
|
|
||||||
for p in alive:
|
|
||||||
for child in p.children(recursive=True):
|
|
||||||
child.kill()
|
|
||||||
p.kill()
|
|
||||||
psutil.wait_procs(alive, timeout=2)
|
|
||||||
|
|
||||||
# 正常退出
|
|
||||||
cls._pool.pop(udid)
|
|
||||||
LogManager.method_info("任务停止成功", method="task")
|
|
||||||
return 200, f"停止线程成功 {udid}"
|
|
||||||
|
|
||||||
except psutil.NoSuchProcess: # 精准捕获
|
|
||||||
cls._pool.pop(udid)
|
|
||||||
LogManager.method_info("进程已自然退出", method="task")
|
|
||||||
return 200, f"进程已退出 {udid}"
|
|
||||||
|
|
||||||
except Exception as e: # 真正的异常
|
|
||||||
LogManager.method_error(f"停止异常: {e}", method="task")
|
|
||||||
return 1002, f"停止异常 {udid}"
|
|
||||||
|
|
||||||
# ------------------------------------------------------
|
|
||||||
# 以下全是内部工具,外部无需调用
|
|
||||||
# ------------------------------------------------------
|
|
||||||
@staticmethod
|
|
||||||
def _find_free_port(start: int = 50000) -> int:
|
|
||||||
"""找个随机空闲端口,给子进程当通信口(可选)"""
|
|
||||||
import socket
|
|
||||||
for p in range(start, start + 1000):
|
|
||||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
||||||
if s.connect_ex(("127.0.0.1", p)) != 0:
|
|
||||||
return p
|
|
||||||
raise RuntimeError("无可用端口")
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _start_worker_process(udid: str, port: int) -> psutil.Process:
|
|
||||||
"""
|
"""
|
||||||
真正拉起子进程:
|
停止指定设备的线程。
|
||||||
打包环境:exe --udid=xxx
|
:param udid: 设备的唯一标识符
|
||||||
源码环境:python -m Module.Worker --udid=xxx
|
:return: 状态码和信息
|
||||||
"""
|
"""
|
||||||
exe_path = Path(sys.executable).resolve()
|
with cls._lock:
|
||||||
is_frozen = exe_path.suffix.lower() == ".exe" and exe_path.exists()
|
if udid not in cls._tasks or not cls._tasks[udid].get("running", False):
|
||||||
|
LogManager.method_info(f"任务停止失败:设备 {udid} 没有执行相关任务", method="task")
|
||||||
|
return 400, f"当前设备没有执行相关任务 {udid}"
|
||||||
|
|
||||||
if is_frozen:
|
task = cls._tasks[udid]
|
||||||
# 打包后
|
event = task["event"]
|
||||||
cmd = [str(exe_path), "--role=worker", f"--udid={udid}", f"--port={port}"]
|
thread = task["thread"]
|
||||||
cwd = str(exe_path.parent)
|
|
||||||
else:
|
|
||||||
# 源码运行
|
|
||||||
cmd = [sys.executable, "-u", "-m", "Module.Worker", f"--udid={udid}", f"--port={port}"]
|
|
||||||
cwd = str(Path(__file__).resolve().parent.parent)
|
|
||||||
|
|
||||||
# 核心:CREATE_NO_WINDOW + 独立会话,父进程死也不影响
|
LogManager.method_info(f"设备 {udid} 的任务正在停止", method="task")
|
||||||
creation_flags = 0x08000000 if os.name == "nt" else 0
|
|
||||||
proc = subprocess.Popen(
|
|
||||||
cmd,
|
|
||||||
stdin=subprocess.DEVNULL,
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.STDOUT,
|
|
||||||
text=True,
|
|
||||||
encoding="utf-8",
|
|
||||||
errors="replace",
|
|
||||||
bufsize=1,
|
|
||||||
cwd=cwd,
|
|
||||||
start_new_session=True, # 独立进程组
|
|
||||||
creationflags=creation_flags
|
|
||||||
)
|
|
||||||
# 守护线程:把子进程 stdout 实时打到日志
|
|
||||||
Thread(target=lambda: ThreadManager._log_stdout(proc, udid), daemon=True).start()
|
|
||||||
return psutil.Process(proc.pid)
|
|
||||||
|
|
||||||
@staticmethod
|
# 设置停止标志位
|
||||||
def _log_stdout(proc: subprocess.Popen, udid: str):
|
event.set()
|
||||||
for line in iter(proc.stdout.readline, ""):
|
|
||||||
if line:
|
# 等待线程结束
|
||||||
LogManager.info(line.rstrip(), udid)
|
thread.join(timeout=5) # 可设置超时时间,避免阻塞
|
||||||
proc.stdout.close()
|
|
||||||
|
# 清理任务记录
|
||||||
|
del cls._tasks[udid] # 删除任务记录
|
||||||
|
LogManager.method_info(f"设备 {udid} 的任务停止成功", method="task")
|
||||||
|
return 200, f"当前任务停止成功 {udid}"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def is_task_running(cls, udid: str) -> bool:
|
||||||
|
"""
|
||||||
|
检查任务是否正在运行。
|
||||||
|
:param udid: 设备的唯一标识符
|
||||||
|
:return: True 表示任务正在运行,False 表示没有任务运行
|
||||||
|
"""
|
||||||
|
with cls._lock:
|
||||||
|
is_running = cls._tasks.get(udid, {}).get("running", False)
|
||||||
|
LogManager.method_info(f"检查设备 {udid} 的任务状态:{'运行中' if is_running else '未运行'}", method="task")
|
||||||
|
return is_running
|
||||||
|
|||||||
@@ -60,8 +60,6 @@ class ScriptManager():
|
|||||||
# 设置手机的节点深度为15,判断该页面是否正确
|
# 设置手机的节点深度为15,判断该页面是否正确
|
||||||
session.appium_settings({"snapshotMaxDepth": 15})
|
session.appium_settings({"snapshotMaxDepth": 15})
|
||||||
|
|
||||||
# 判断当前页面上是否有推荐按钮
|
|
||||||
|
|
||||||
el = session.xpath(
|
el = session.xpath(
|
||||||
'//XCUIElementTypeButton[@name="top_tabs_recomend" or @name="推荐" or @label="推荐"]'
|
'//XCUIElementTypeButton[@name="top_tabs_recomend" or @name="推荐" or @label="推荐"]'
|
||||||
)
|
)
|
||||||
@@ -274,7 +272,6 @@ class ScriptManager():
|
|||||||
retries = 0
|
retries = 0
|
||||||
while not event.is_set():
|
while not event.is_set():
|
||||||
try:
|
try:
|
||||||
|
|
||||||
self.greetNewFollowers(udid, needReply, event)
|
self.greetNewFollowers(udid, needReply, event)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -294,13 +291,11 @@ class ScriptManager():
|
|||||||
LogManager.method_info(f"是否要自动回复消息:{needReply}", "关注打招呼", udid)
|
LogManager.method_info(f"是否要自动回复消息:{needReply}", "关注打招呼", udid)
|
||||||
|
|
||||||
# 先关闭Tik Tok
|
# 先关闭Tik Tok
|
||||||
|
|
||||||
ControlUtils.closeTikTok(session, udid)
|
ControlUtils.closeTikTok(session, udid)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
# 重新打开Tik Tok
|
# 重新打开Tik Tok
|
||||||
ControlUtils.openTikTok(session, udid)
|
ControlUtils.openTikTok(session, udid)
|
||||||
|
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
LogManager.method_info(f"重启tiktok", "关注打招呼", udid)
|
LogManager.method_info(f"重启tiktok", "关注打招呼", udid)
|
||||||
# 设置查找深度
|
# 设置查找深度
|
||||||
@@ -374,6 +369,7 @@ class ScriptManager():
|
|||||||
input.set_text(f"{aid or '暂无数据'}\n")
|
input.set_text(f"{aid or '暂无数据'}\n")
|
||||||
|
|
||||||
# 定位 "关注" 按钮 通过关注按钮的位置点击主播首页
|
# 定位 "关注" 按钮 通过关注按钮的位置点击主播首页
|
||||||
|
|
||||||
session.appium_settings({"snapshotMaxDepth": 25})
|
session.appium_settings({"snapshotMaxDepth": 25})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -606,7 +602,6 @@ class ScriptManager():
|
|||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
continue # 重新进入 while 循环,调用 monitorMessages
|
continue # 重新进入 while 循环,调用 monitorMessages
|
||||||
|
|
||||||
|
|
||||||
# 检查未读消息并回复
|
# 检查未读消息并回复
|
||||||
def monitorMessages(self, session, udid):
|
def monitorMessages(self, session, udid):
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user