ok-script 0.0.49__tar.gz → 0.0.50__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ok-script might be problematic. Click here for more details.
- {ok-script-0.0.49 → ok-script-0.0.50}/PKG-INFO +2 -1
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/adb/DeviceManager.py +3 -4
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/App.py +6 -2
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/Communicate.py +2 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/MainWindow.py +3 -3
- ok-script-0.0.50/ok/gui/about/AboutTab.py +135 -0
- ok-script-0.0.50/ok/gui/about/VersionCard.py +40 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/start/SelectCaptureListView.py +5 -7
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/widget/Tab.py +7 -3
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/task/TaskExecutor.py +8 -2
- ok-script-0.0.50/ok/update/Updater.py +251 -0
- ok-script-0.0.50/ok/update/gen_md5.py +23 -0
- ok-script-0.0.50/ok/util/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/util/path.py +46 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok_script.egg-info/PKG-INFO +2 -1
- {ok-script-0.0.49 → ok-script-0.0.50}/ok_script.egg-info/SOURCES.txt +7 -1
- {ok-script-0.0.49 → ok-script-0.0.50}/ok_script.egg-info/requires.txt +1 -0
- ok-script-0.0.50/ok_script.egg-info/top_level.txt +2 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/setup.py +3 -2
- ok-script-0.0.50/tests/__init__.py +3 -0
- ok-script-0.0.50/tests/test_updater.py +25 -0
- ok-script-0.0.49/ok/gui/about/AboutTab.py +0 -24
- ok-script-0.0.49/ok_script.egg-info/top_level.txt +0 -1
- {ok-script-0.0.49 → ok-script-0.0.50}/README.md +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/OK.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/BaseCaptureMethod.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/HwndWindow.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/adb/ADBCaptureMethod.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/adb/WindowsCaptureFactory.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/adb/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/adb/bin/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/adb/targets.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/adb/vbox.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/windows/BaseWindowsCaptureMethod.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/windows/BitBltCaptureMethod.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/windows/DesktopDuplicationCaptureMethod.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/windows/WindowsGraphicsCaptureMethod.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/windows/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/windows/d3d11.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/windows/dump.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/windows/utils.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/capture/windows/window.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/color/Color.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/color/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/config/Config.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/config/InfoDict.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/config/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/feature/Box.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/feature/Feature.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/feature/FeatureSet.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/feature/FindFeature.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/feature/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/MessageWindow.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/TabTitles.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/about/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/common/OKIcon.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/common/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/common/config.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/common/style_sheet.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/debug/AspectRatioWidget.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/debug/DebugTab.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/debug/FrameWidget.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/debug/InfoWidget.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/debug/LoggerWidget.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/debug/Screenshot.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/debug/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/i18n/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/i18n/path.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/i18n/update.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/icon/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/icon/icon.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/overlay/OverlayWindow.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/overlay/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/qss/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/resources.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/settings/SettingTab.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/settings/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/start/SelectHwndWindow.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/start/StartCard.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/start/StartTab.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/start/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/ConfigItemFactory.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/ConfigLabelAndWidget.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/LabelAndDoubleSpinBox.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/LabelAndDropDown.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/LabelAndLineEdit.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/LabelAndList.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/LabelAndSpinBox.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/LabelAndSwitchButton.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/LabelAndWidget.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/ModifyListDialog.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/ModifyListItem.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/OneTimeTaskTab.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/StartButton.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/TaskCard.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/TaskOpButton.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/TooltipTableWidget.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/TriggerTaskTab.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/tasks/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/util/Alert.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/util/InitWorker.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/util/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/widget/Card.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/widget/FramelessDialog.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/widget/ListTableWidgetItem.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/widget/NumericTableWidgetItem.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/widget/StatusBar.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/widget/TabWidget.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/widget/UpdateConfigWidgetItem.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/widget/YesNonWidgetItem.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/gui/widget/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/interaction/ADBInteraction.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/interaction/BaseInteraction.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/interaction/Win32Interaction.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/interaction/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/logging/Logger.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/logging/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/ocr/OCR.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/ocr/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Media/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Security/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/Storage/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/Windows/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/delegate.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/export.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/idldsl.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/inspectable.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/roapi.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/types.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/rotypes/winstring.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/save/BlackBarProcessor.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/save/PostProcessor.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/save/SaveByInterval.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/save/SaveByKeyPress.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/save/SaveMethodBase.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/save/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/scene/FeatureScene.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/scene/Scene.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/scene/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/stats/StreamStats.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/stats/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/task/BaseTask.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/task/ExecutorOperation.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/task/OneTimeTask.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/task/TriggerTask.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/task/__init__.py +0 -0
- {ok-script-0.0.49/ok/util → ok-script-0.0.50/ok/update}/__init__.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/util/exit_event.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/util/json.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/util/list.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/util/thread.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/util/win32_process.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok/util/yaml.py +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/ok_script.egg-info/dependency_links.txt +0 -0
- {ok-script-0.0.49 → ok-script-0.0.50}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ok-script
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.50
|
|
4
4
|
Summary: Automation with Computer Vision for Python
|
|
5
5
|
Home-page: https://github.com/ok-oldking/ok-script
|
|
6
6
|
Author: ok-oldking
|
|
@@ -21,6 +21,7 @@ Requires-Dist: PySide6-Fluent-Widgets>=1.5.6
|
|
|
21
21
|
Requires-Dist: psutil>=5.9.8
|
|
22
22
|
Requires-Dist: opencv-python>=4.9.0.80
|
|
23
23
|
Requires-Dist: ok-d3dshot>=0.1.5
|
|
24
|
+
Requires-Dist: py7zr>=0.21.0
|
|
24
25
|
|
|
25
26
|
# ok-script
|
|
26
27
|
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import threading
|
|
2
2
|
|
|
3
3
|
import win32gui
|
|
4
|
-
from adbutils import AdbError
|
|
5
4
|
|
|
6
5
|
from ok.capture.HwndWindow import HwndWindow, find_hwnd_by_title_and_exe
|
|
7
6
|
from ok.capture.adb.ADBCaptureMethod import ADBCaptureMethod, do_screencap
|
|
8
7
|
from ok.capture.adb.WindowsCaptureFactory import update_capture_method
|
|
9
|
-
from ok.capture.adb.vbox import installed_emulator
|
|
10
8
|
from ok.capture.windows.window import get_window_bounds
|
|
11
9
|
from ok.config.Config import Config
|
|
12
10
|
from ok.gui.Communicate import communicate
|
|
@@ -36,8 +34,7 @@ class DeviceManager:
|
|
|
36
34
|
"DeviceManager")
|
|
37
35
|
self.thread = None
|
|
38
36
|
self.capture_method = None
|
|
39
|
-
self.
|
|
40
|
-
self.start()
|
|
37
|
+
self.refresh()
|
|
41
38
|
|
|
42
39
|
def refresh(self):
|
|
43
40
|
if self.thread is None or not self.thread.is_alive():
|
|
@@ -121,6 +118,7 @@ class DeviceManager:
|
|
|
121
118
|
return
|
|
122
119
|
if not fast:
|
|
123
120
|
self.connect_all()
|
|
121
|
+
from ok.capture.adb.vbox import installed_emulator
|
|
124
122
|
installed_emulators = [] if fast else installed_emulator()
|
|
125
123
|
for device in self.adb.list():
|
|
126
124
|
logger.debug(f'adb.list() {device}')
|
|
@@ -295,6 +293,7 @@ class DeviceManager:
|
|
|
295
293
|
def shell(self, *args, **kwargs):
|
|
296
294
|
device = self.device
|
|
297
295
|
if device is not None:
|
|
296
|
+
from adbutils import AdbError
|
|
298
297
|
try:
|
|
299
298
|
return device.shell(*args, **kwargs)
|
|
300
299
|
except AdbError as e:
|
|
@@ -13,6 +13,7 @@ from ok.gui.MessageWindow import MessageWindow
|
|
|
13
13
|
from ok.gui.i18n.path import i18n_path
|
|
14
14
|
from ok.gui.overlay.OverlayWindow import OverlayWindow
|
|
15
15
|
from ok.logging.Logger import get_logger
|
|
16
|
+
from ok.update.Updater import Updater
|
|
16
17
|
|
|
17
18
|
logger = get_logger(__name__)
|
|
18
19
|
|
|
@@ -32,6 +33,8 @@ class App:
|
|
|
32
33
|
self.app.setAttribute(Qt.AA_DontCreateNativeWidgetSiblings)
|
|
33
34
|
qconfig.theme = Theme.AUTO
|
|
34
35
|
|
|
36
|
+
self.updater = Updater(self.config, exit_event)
|
|
37
|
+
|
|
35
38
|
self.about = self.config.get('about')
|
|
36
39
|
self.title = self.config.get('gui_title')
|
|
37
40
|
self.version = self.config.get('version')
|
|
@@ -75,8 +78,9 @@ class App:
|
|
|
75
78
|
self.show_message_window(title, content)
|
|
76
79
|
|
|
77
80
|
def show_main_window(self):
|
|
78
|
-
self.main_window = MainWindow(self.icon, self.
|
|
79
|
-
|
|
81
|
+
self.main_window = MainWindow(self.icon, self.title, self.version, self.overlay, self.about,
|
|
82
|
+
exit_event=self.exit_event)
|
|
83
|
+
# Set the window title here
|
|
80
84
|
self.main_window.setWindowIcon(self.icon)
|
|
81
85
|
if self.overlay and ok.gui.device_manager.hwnd is not None:
|
|
82
86
|
self.overlay_window = OverlayWindow(ok.gui.device_manager.hwnd)
|
|
@@ -20,6 +20,8 @@ class Communicate(QObject):
|
|
|
20
20
|
config_validation: Signal = Signal(str)
|
|
21
21
|
tab = Signal(str)
|
|
22
22
|
capture_error = Signal()
|
|
23
|
+
check_update = Signal()
|
|
24
|
+
download_update = Signal(float, str, str, bool)
|
|
23
25
|
|
|
24
26
|
def emit_draw_box(self, key: str = None, boxes=None, color=None, frame=None):
|
|
25
27
|
self.draw_box.emit(key, boxes, color, frame)
|
|
@@ -20,7 +20,7 @@ class Communicate(QObject):
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class MainWindow(MSFluentWindow):
|
|
23
|
-
def __init__(self, icon, debug=False, about=None, exit_event=None):
|
|
23
|
+
def __init__(self, icon, title, version, debug=False, about=None, exit_event=None):
|
|
24
24
|
super().__init__()
|
|
25
25
|
self.exit_event = exit_event
|
|
26
26
|
self.start_tab = StartTab()
|
|
@@ -42,11 +42,11 @@ class MainWindow(MSFluentWindow):
|
|
|
42
42
|
# self.addSubInterface(debug_tab, FluentIcon.COMMAND_PROMPT, self.tr('Debug'))
|
|
43
43
|
# ... Add other tabs similarly
|
|
44
44
|
if about:
|
|
45
|
-
about_tab = AboutTab(about)
|
|
45
|
+
about_tab = AboutTab(icon, title, version, about)
|
|
46
46
|
self.addSubInterface(about_tab, FluentIcon.QUESTION, self.tr('About'),
|
|
47
47
|
position=NavigationItemPosition.BOTTOM)
|
|
48
48
|
# Styling the tabs and content if needed, for example:
|
|
49
|
-
self.setWindowTitle(
|
|
49
|
+
self.setWindowTitle(f'{title} {version}')
|
|
50
50
|
|
|
51
51
|
communicate.executor_paused.connect(self.executor_paused)
|
|
52
52
|
communicate.tab.connect(self.navigate_tab)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
from PySide6.QtCore import Qt
|
|
2
|
+
from PySide6.QtWidgets import QHBoxLayout, QLabel
|
|
3
|
+
from qfluentwidgets import TextEdit, PushButton, InfoBar, InfoBarPosition, ProgressBar
|
|
4
|
+
|
|
5
|
+
import ok.gui
|
|
6
|
+
from ok.capture.windows.dump import dump_threads
|
|
7
|
+
from ok.gui.Communicate import communicate
|
|
8
|
+
from ok.gui.about.VersionCard import VersionCard
|
|
9
|
+
from ok.gui.widget.Tab import Tab
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AboutTab(Tab):
|
|
13
|
+
def __init__(self, icon, title, version, about):
|
|
14
|
+
super().__init__()
|
|
15
|
+
self.version_card = VersionCard(icon, title, version, self)
|
|
16
|
+
# Create a QTextEdit instance
|
|
17
|
+
self.addWidget(self.version_card, align=Qt.AlignCenter)
|
|
18
|
+
if ok.gui.app.updater.enabled():
|
|
19
|
+
self.update_hbox = QHBoxLayout()
|
|
20
|
+
self.update_hbox.addStretch()
|
|
21
|
+
self.check_update_button = PushButton(self.tr("Check for updates"))
|
|
22
|
+
self.check_update_button.clicked.connect(self.check_update)
|
|
23
|
+
self.update_hbox.addWidget(self.check_update_button)
|
|
24
|
+
self.download_latest_button = PushButton()
|
|
25
|
+
self.download_latest_button.clicked.connect(self.download_latest)
|
|
26
|
+
|
|
27
|
+
self.update_hbox.addWidget(self.download_latest_button)
|
|
28
|
+
self.download_stable_button = PushButton(self.tr("Download stable version {version}").format(version=1))
|
|
29
|
+
self.download_stable_button.clicked.connect(self.download_stable)
|
|
30
|
+
|
|
31
|
+
self.update_hbox.addWidget(self.download_stable_button)
|
|
32
|
+
|
|
33
|
+
self.download_bar = ProgressBar(self)
|
|
34
|
+
self.download_bar.setFixedWidth(200)
|
|
35
|
+
self.update_hbox.addWidget(self.download_bar)
|
|
36
|
+
|
|
37
|
+
self.downloading_text = QLabel()
|
|
38
|
+
self.update_hbox.addWidget(self.downloading_text)
|
|
39
|
+
|
|
40
|
+
self.update_hbox.addStretch()
|
|
41
|
+
self.addLayout(self.update_hbox)
|
|
42
|
+
communicate.download_update.connect(self.download_update)
|
|
43
|
+
communicate.check_update.connect(self.update_update)
|
|
44
|
+
self.update_update_buttons(0)
|
|
45
|
+
text_edit = TextEdit()
|
|
46
|
+
text_edit.setHtml(about)
|
|
47
|
+
text_edit.setReadOnly(True)
|
|
48
|
+
|
|
49
|
+
# Set the layout on the widget
|
|
50
|
+
self.addWidget(text_edit)
|
|
51
|
+
if ok.gui.ok.debug:
|
|
52
|
+
dump_button = PushButton(self.tr("Dump Threads(HotKey:Ctrl+Alt+D)"))
|
|
53
|
+
dump_button.clicked.connect(dump_threads)
|
|
54
|
+
self.addWidget(dump_button)
|
|
55
|
+
|
|
56
|
+
def update_update_buttons(self, percent, progress=""):
|
|
57
|
+
if ok.gui.app.updater.latest_release and not ok.gui.app.updater.downloading:
|
|
58
|
+
self.download_latest_button.setText(self.tr("Download latest version {version} ({size})").format(
|
|
59
|
+
version=ok.gui.app.updater.latest_release.get('version'),
|
|
60
|
+
size=ok.gui.app.updater.latest_release.get('readable_size')))
|
|
61
|
+
self.download_latest_button.show()
|
|
62
|
+
else:
|
|
63
|
+
self.download_latest_button.hide()
|
|
64
|
+
if ok.gui.app.updater.stable_release and not ok.gui.app.updater.downloading:
|
|
65
|
+
self.download_stable_button.setText(self.tr("Download stable version {version} ({size})").format(
|
|
66
|
+
version=ok.gui.app.updater.stable_release.get('version'),
|
|
67
|
+
size=ok.gui.app.updater.stable_release.get('readable_size')))
|
|
68
|
+
self.download_stable_button.show()
|
|
69
|
+
else:
|
|
70
|
+
self.download_stable_button.hide()
|
|
71
|
+
if ok.gui.app.updater.downloading:
|
|
72
|
+
self.downloading_text.show()
|
|
73
|
+
self.downloading_text.setText(
|
|
74
|
+
self.tr('Downloading {progress} {percent}%').format(progress=progress, percent=format(percent, '.1f')))
|
|
75
|
+
self.download_bar.show()
|
|
76
|
+
self.download_bar.setValue(percent)
|
|
77
|
+
else:
|
|
78
|
+
self.downloading_text.hide()
|
|
79
|
+
self.download_bar.hide()
|
|
80
|
+
|
|
81
|
+
def download_update(self, percent, progress, done, error):
|
|
82
|
+
message = ""
|
|
83
|
+
if done:
|
|
84
|
+
if error:
|
|
85
|
+
bar = InfoBar.error
|
|
86
|
+
title = self.tr('Download Error:')
|
|
87
|
+
message = error
|
|
88
|
+
else:
|
|
89
|
+
bar = InfoBar.info
|
|
90
|
+
title = self.tr('Download Complete!')
|
|
91
|
+
bar(
|
|
92
|
+
title=title,
|
|
93
|
+
content=message,
|
|
94
|
+
orient=Qt.Horizontal,
|
|
95
|
+
isClosable=True,
|
|
96
|
+
position=InfoBarPosition.TOP,
|
|
97
|
+
duration=5000, # won't disappear automatically
|
|
98
|
+
parent=self
|
|
99
|
+
)
|
|
100
|
+
self.update_update_buttons(percent, progress)
|
|
101
|
+
|
|
102
|
+
def download_latest(self):
|
|
103
|
+
ok.gui.app.updater.async_run(lambda: ok.gui.app.updater.download(ok.gui.app.updater.latest_release))
|
|
104
|
+
|
|
105
|
+
def download_stable(self):
|
|
106
|
+
ok.gui.app.updater.async_run(lambda: ok.gui.app.updater.download(ok.gui.app.updater.stable_release))
|
|
107
|
+
|
|
108
|
+
def update_update(self):
|
|
109
|
+
self.check_update_button.setText(
|
|
110
|
+
self.tr("Check for update"))
|
|
111
|
+
self.check_update_button.setEnabled(True)
|
|
112
|
+
if ok.gui.app.updater.latest_release or ok.gui.app.updater.stable_release:
|
|
113
|
+
bar = InfoBar.info
|
|
114
|
+
message = self.tr('Found new version!')
|
|
115
|
+
elif ok.gui.app.updater.error:
|
|
116
|
+
bar = InfoBar.error
|
|
117
|
+
message = self.tr('Found new version!')
|
|
118
|
+
else:
|
|
119
|
+
bar = InfoBar.info
|
|
120
|
+
message = self.tr("This is the newest version!")
|
|
121
|
+
bar(
|
|
122
|
+
title="",
|
|
123
|
+
content=message,
|
|
124
|
+
orient=Qt.Horizontal,
|
|
125
|
+
isClosable=True,
|
|
126
|
+
position=InfoBarPosition.TOP,
|
|
127
|
+
duration=5000, # won't disappear automatically
|
|
128
|
+
parent=self
|
|
129
|
+
)
|
|
130
|
+
self.update_update_buttons(0)
|
|
131
|
+
|
|
132
|
+
def check_update(self):
|
|
133
|
+
ok.gui.app.updater.async_run(lambda: ok.gui.app.updater.check_for_updates())
|
|
134
|
+
self.check_update_button.setText(self.tr("Checking for updates"))
|
|
135
|
+
self.check_update_button.setEnabled(False)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from PySide6.QtCore import Qt
|
|
2
|
+
from PySide6.QtWidgets import QLabel, QHBoxLayout, QVBoxLayout
|
|
3
|
+
from qfluentwidgets import IconWidget, TextWrap, CardWidget
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class VersionCard(CardWidget):
|
|
7
|
+
""" Sample card """
|
|
8
|
+
|
|
9
|
+
def __init__(self, icon, title, version, parent=None):
|
|
10
|
+
super().__init__(parent=parent)
|
|
11
|
+
|
|
12
|
+
self.iconWidget = IconWidget(icon, self)
|
|
13
|
+
self.titleLabel = QLabel(title, self)
|
|
14
|
+
self.contentLabel = QLabel(TextWrap.wrap(version, 45, False)[0], self)
|
|
15
|
+
|
|
16
|
+
self.hBoxLayout = QHBoxLayout(self)
|
|
17
|
+
self.vBoxLayout = QVBoxLayout()
|
|
18
|
+
|
|
19
|
+
self.setFixedSize(360, 90)
|
|
20
|
+
self.iconWidget.setFixedSize(48, 48)
|
|
21
|
+
|
|
22
|
+
self.hBoxLayout.setSpacing(28)
|
|
23
|
+
self.hBoxLayout.setContentsMargins(20, 0, 0, 0)
|
|
24
|
+
self.vBoxLayout.setSpacing(2)
|
|
25
|
+
self.vBoxLayout.setContentsMargins(0, 0, 0, 0)
|
|
26
|
+
self.vBoxLayout.setAlignment(Qt.AlignVCenter)
|
|
27
|
+
|
|
28
|
+
self.hBoxLayout.setAlignment(Qt.AlignVCenter)
|
|
29
|
+
self.hBoxLayout.addWidget(self.iconWidget)
|
|
30
|
+
self.hBoxLayout.addLayout(self.vBoxLayout)
|
|
31
|
+
self.vBoxLayout.addStretch(1)
|
|
32
|
+
self.vBoxLayout.addWidget(self.titleLabel)
|
|
33
|
+
self.vBoxLayout.addWidget(self.contentLabel)
|
|
34
|
+
self.vBoxLayout.addStretch(1)
|
|
35
|
+
|
|
36
|
+
self.titleLabel.setObjectName('titleLabel')
|
|
37
|
+
self.contentLabel.setObjectName('contentLabel')
|
|
38
|
+
|
|
39
|
+
def mouseReleaseEvent(self, e):
|
|
40
|
+
super().mouseReleaseEvent(e)
|
|
@@ -9,20 +9,18 @@ class SelectCaptureListView(ListWidget):
|
|
|
9
9
|
|
|
10
10
|
def update_for_device(self, device, hwnd, capture):
|
|
11
11
|
if self.count() == 0:
|
|
12
|
-
item = QListWidgetItem(self.tr(f"Game Window
|
|
13
|
-
|
|
14
|
-
# Add the QListWidgetItem to the QListWidget
|
|
12
|
+
item = QListWidgetItem(self.tr(f"Game Window"))
|
|
15
13
|
self.addItem(item)
|
|
16
|
-
tips = hwnd or
|
|
14
|
+
tips = hwnd or ""
|
|
17
15
|
if device == "windows":
|
|
18
16
|
title = self.tr("Game Window")
|
|
19
17
|
if self.count() == 2:
|
|
20
18
|
self.takeItem(1)
|
|
21
19
|
else:
|
|
22
|
-
title = self.tr("Emulator Window")
|
|
20
|
+
title = self.tr("Emulator Window(Supports Background, Fast, Low Latency)")
|
|
23
21
|
if self.count() == 1:
|
|
24
|
-
item = QListWidgetItem(self.tr("ADB
|
|
22
|
+
item = QListWidgetItem(self.tr("ADB(Supports Background, Slow, High Compatibility, High Latency)"))
|
|
25
23
|
self.addItem(item)
|
|
26
|
-
self.item(0).setText(f"{title}
|
|
24
|
+
self.item(0).setText(f"{title} - {tips}")
|
|
27
25
|
selected = 0 if capture == "windows" else 1
|
|
28
26
|
self.setCurrentRow(selected)
|
|
@@ -29,9 +29,13 @@ class Tab(ScrollArea):
|
|
|
29
29
|
|
|
30
30
|
def addCard(self, title, widget, stretch=0, parent=None):
|
|
31
31
|
container = Card(title, widget)
|
|
32
|
-
self.
|
|
32
|
+
self.addWidget(container, stretch)
|
|
33
33
|
return container
|
|
34
34
|
|
|
35
|
-
def addWidget(self, widget, stretch=0):
|
|
36
|
-
self.vBoxLayout.addWidget(widget, stretch,
|
|
35
|
+
def addWidget(self, widget, stretch=0, align=Qt.AlignTop):
|
|
36
|
+
self.vBoxLayout.addWidget(widget, stretch, align)
|
|
37
37
|
return widget
|
|
38
|
+
|
|
39
|
+
def addLayout(self, layout, stretch=0):
|
|
40
|
+
self.vBoxLayout.addLayout(layout, stretch)
|
|
41
|
+
return layout
|
|
@@ -3,6 +3,7 @@ import time
|
|
|
3
3
|
import traceback
|
|
4
4
|
|
|
5
5
|
from ok.capture.BaseCaptureMethod import CaptureException
|
|
6
|
+
from ok.capture.adb.ADBCaptureMethod import ADBCaptureMethod
|
|
6
7
|
from ok.capture.adb.DeviceManager import DeviceManager
|
|
7
8
|
from ok.gui.Communicate import communicate
|
|
8
9
|
from ok.logging.Logger import get_logger
|
|
@@ -73,6 +74,7 @@ class TaskExecutor:
|
|
|
73
74
|
return self._frame
|
|
74
75
|
|
|
75
76
|
def supports_screen_ratio(self, supported_ratio):
|
|
77
|
+
frame = self.method.get_frame() if not isinstance(self.method, ADBCaptureMethod) else None
|
|
76
78
|
if supported_ratio is None:
|
|
77
79
|
return True, None
|
|
78
80
|
width = self.method.width
|
|
@@ -88,9 +90,13 @@ class TaskExecutor:
|
|
|
88
90
|
|
|
89
91
|
# Calculate the difference between the actual and supported ratios
|
|
90
92
|
difference = abs(actual_ratio - supported_ratio)
|
|
91
|
-
|
|
93
|
+
support = difference <= 0.01 * supported_ratio
|
|
94
|
+
if not support:
|
|
95
|
+
logger.error(f'resolution error {width}x{height} {frame is None}')
|
|
96
|
+
if not support and frame:
|
|
97
|
+
communicate.screenshot.emit(frame, "resolution_error")
|
|
92
98
|
# Check if the difference is within 1%
|
|
93
|
-
return
|
|
99
|
+
return support, f"{width}x{height}"
|
|
94
100
|
|
|
95
101
|
def can_capture(self):
|
|
96
102
|
return self.method is not None and self.interaction is not None and self.interaction.should_capture()
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import os
|
|
3
|
+
import queue
|
|
4
|
+
import threading
|
|
5
|
+
import zipfile
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
|
|
8
|
+
import py7zr
|
|
9
|
+
import requests
|
|
10
|
+
|
|
11
|
+
from ok.gui.Communicate import communicate
|
|
12
|
+
from ok.logging.Logger import get_logger
|
|
13
|
+
from ok.util.path import get_path_relative_to_exe, ensure_dir, dir_checksum, find_folder_with_file
|
|
14
|
+
|
|
15
|
+
logger = get_logger(__name__)
|
|
16
|
+
|
|
17
|
+
updater_bat = r'''@echo off
|
|
18
|
+
set "source_folder=%~1"
|
|
19
|
+
set "target_folder=%~2"
|
|
20
|
+
|
|
21
|
+
for /R "%source_folder%" %%F in (*) do (
|
|
22
|
+
if exist "%target_folder%\%%~nxF" (
|
|
23
|
+
echo Deleting "%target_folder%\%%~nxF"
|
|
24
|
+
del /F /Q "%target_folder%\%%~nxF"
|
|
25
|
+
)
|
|
26
|
+
echo Copying "%%F"
|
|
27
|
+
copy /Y "%%F" "%target_folder%\%%~nxF"
|
|
28
|
+
)
|
|
29
|
+
'''
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Updater:
|
|
33
|
+
def __init__(self, app_config, exit_event):
|
|
34
|
+
self.config = app_config.get('update')
|
|
35
|
+
self.version = app_config.get('version')
|
|
36
|
+
self.debug = app_config.get('debug')
|
|
37
|
+
self.latest_release = None
|
|
38
|
+
self.stable_release = None
|
|
39
|
+
self.error = None
|
|
40
|
+
self.downloading = False
|
|
41
|
+
if self.config is None:
|
|
42
|
+
return
|
|
43
|
+
self.update_url = self.config.get('releases_url')
|
|
44
|
+
self.proxy_url = self.config.get('proxy_url')
|
|
45
|
+
self.use_proxy = self.config.get('use_proxy')
|
|
46
|
+
self.update_dir = get_path_relative_to_exe('updates')
|
|
47
|
+
self.exit_event = exit_event
|
|
48
|
+
self.task_queue = queue.Queue()
|
|
49
|
+
self.exit_event.bind_queue(self.task_queue)
|
|
50
|
+
t = threading.Thread(target=self._run_tasks, name='run_tasks')
|
|
51
|
+
t.start()
|
|
52
|
+
|
|
53
|
+
def _run_tasks(self):
|
|
54
|
+
while True and not self.exit_event.is_set():
|
|
55
|
+
task = self.task_queue.get()
|
|
56
|
+
if task is None:
|
|
57
|
+
logger.debug("Task queue get is None quit")
|
|
58
|
+
break
|
|
59
|
+
task()
|
|
60
|
+
self.task_queue.task_done()
|
|
61
|
+
|
|
62
|
+
def get_url(self, url):
|
|
63
|
+
if self.use_proxy:
|
|
64
|
+
url = self.proxy_url + url
|
|
65
|
+
logger.info(f'get_url: {url}')
|
|
66
|
+
return url
|
|
67
|
+
|
|
68
|
+
def check_for_updates(self):
|
|
69
|
+
try:
|
|
70
|
+
# Send GET request to the API endpoint
|
|
71
|
+
response = requests.get(self.get_url(self.update_url))
|
|
72
|
+
|
|
73
|
+
# Raise an exception if the request was unsuccessful
|
|
74
|
+
response.raise_for_status()
|
|
75
|
+
|
|
76
|
+
# Parse the JSON response to a dictionary
|
|
77
|
+
releases = response.json()
|
|
78
|
+
|
|
79
|
+
# Extract useful information from each release
|
|
80
|
+
self.latest_release = None
|
|
81
|
+
self.stable_release = None
|
|
82
|
+
self.error = None
|
|
83
|
+
for release in releases:
|
|
84
|
+
release = self.parse_data(release)
|
|
85
|
+
|
|
86
|
+
if not release.get('draft') and is_newer_version(self.version, release.get('version')):
|
|
87
|
+
if self.latest_release is None:
|
|
88
|
+
self.latest_release = release
|
|
89
|
+
if not release.get('prerelease') and self.stable_release is None:
|
|
90
|
+
self.stable_release = release
|
|
91
|
+
|
|
92
|
+
if self.latest_release and self.stable_release:
|
|
93
|
+
break
|
|
94
|
+
|
|
95
|
+
if self.latest_release == self.stable_release:
|
|
96
|
+
self.latest_release = None
|
|
97
|
+
|
|
98
|
+
except Exception as e:
|
|
99
|
+
print(f"HTTP error occurred: {e}")
|
|
100
|
+
communicate.check_update.emit()
|
|
101
|
+
|
|
102
|
+
def async_run(self, task):
|
|
103
|
+
self.task_queue.put(task)
|
|
104
|
+
|
|
105
|
+
def download(self, release):
|
|
106
|
+
try:
|
|
107
|
+
ensure_dir(self.update_dir)
|
|
108
|
+
file = os.path.join(self.update_dir, release.get('version') + '.' + release.get('type'))
|
|
109
|
+
downloaded = 0
|
|
110
|
+
size = release.get('size')
|
|
111
|
+
if os.path.exists(file):
|
|
112
|
+
downloaded = os.path.getsize(file)
|
|
113
|
+
if downloaded == size:
|
|
114
|
+
logger.info(f'File {file} already downloaded')
|
|
115
|
+
self.extract(file)
|
|
116
|
+
return
|
|
117
|
+
elif downloaded > size:
|
|
118
|
+
logger.warning(f'File {file} already downloaded greater than target')
|
|
119
|
+
os.remove(file)
|
|
120
|
+
downloaded = 0
|
|
121
|
+
|
|
122
|
+
headers = {'Range': f'bytes={downloaded}-'}
|
|
123
|
+
response = requests.get(self.get_url(release.get('url')), headers=headers, stream=True)
|
|
124
|
+
response.raise_for_status()
|
|
125
|
+
logger.info(f'download update to: {file} downloaded {convert_size(downloaded)}')
|
|
126
|
+
self.downloading = True
|
|
127
|
+
communicate.download_update.emit(0, "", False, None)
|
|
128
|
+
with open(file, 'ab') as f:
|
|
129
|
+
for chunk in response.iter_content(chunk_size=1024): # 1 KB chunks
|
|
130
|
+
if self.exit_event.is_set():
|
|
131
|
+
return
|
|
132
|
+
if chunk:
|
|
133
|
+
downloaded += len(chunk)
|
|
134
|
+
percent = downloaded / size * 100
|
|
135
|
+
# Every 1%
|
|
136
|
+
communicate.download_update.emit(percent,
|
|
137
|
+
convert_size(downloaded) + '/' + convert_size(size), False,
|
|
138
|
+
None
|
|
139
|
+
)
|
|
140
|
+
f.write(chunk) # Write chunk to file
|
|
141
|
+
self.downloading = False
|
|
142
|
+
logger.info(f'download success: {file}')
|
|
143
|
+
self.extract(file)
|
|
144
|
+
return
|
|
145
|
+
except Exception as e:
|
|
146
|
+
logger.error('download error occurred', e)
|
|
147
|
+
communicate.download_update.emit(0, "", True, e.args[0])
|
|
148
|
+
|
|
149
|
+
def extract(self, file):
|
|
150
|
+
communicate.download_update.emit(100, "Extracting", False, None)
|
|
151
|
+
folder, extension = file.rsplit('.', 1)
|
|
152
|
+
ensure_dir(folder)
|
|
153
|
+
if extension == '7z':
|
|
154
|
+
with py7zr.SevenZipFile(file, mode='r') as z:
|
|
155
|
+
z.extractall(folder)
|
|
156
|
+
elif extension == 'zip':
|
|
157
|
+
with zipfile.ZipFile(file, 'r') as z:
|
|
158
|
+
z.extractall(folder)
|
|
159
|
+
|
|
160
|
+
updater_root_folder = find_folder_with_file(folder, 'md5.txt')
|
|
161
|
+
|
|
162
|
+
if updater_root_folder is None:
|
|
163
|
+
logger.error('check_package_error no md5.txt found')
|
|
164
|
+
self.check_package_error()
|
|
165
|
+
return
|
|
166
|
+
correct_md5_file = os.path.join(updater_root_folder, 'md5.txt')
|
|
167
|
+
try:
|
|
168
|
+
with open(correct_md5_file, 'r') as file:
|
|
169
|
+
# Read the content of the file
|
|
170
|
+
correct_md5 = file.read()
|
|
171
|
+
except Exception as e:
|
|
172
|
+
logger.error(f'check_package_error md5.txt not found {correct_md5_file}', e)
|
|
173
|
+
self.check_package_error()
|
|
174
|
+
return
|
|
175
|
+
|
|
176
|
+
md5 = dir_checksum(updater_root_folder, ['md5.txt'])
|
|
177
|
+
if md5 != correct_md5:
|
|
178
|
+
logger.error(f'check_package_error md5.txt mismatch {correct_md5_file} != {md5}')
|
|
179
|
+
self.check_package_error()
|
|
180
|
+
return
|
|
181
|
+
logger.info(f'extract {file} md5: {md5}')
|
|
182
|
+
|
|
183
|
+
# Open the file in write mode ('w')
|
|
184
|
+
try:
|
|
185
|
+
with open(get_path_relative_to_exe('update.bat'), 'w') as file:
|
|
186
|
+
# Write a string to the file
|
|
187
|
+
file.write(updater_bat)
|
|
188
|
+
logger.info('write update .bat')
|
|
189
|
+
except Exception as e:
|
|
190
|
+
logger.error(f'write updater_bat error', e)
|
|
191
|
+
self.check_package_error()
|
|
192
|
+
return
|
|
193
|
+
|
|
194
|
+
# Now, 'Hello, World!' is written to 'filename.txt'
|
|
195
|
+
|
|
196
|
+
communicate.download_update.emit(100, "", True, None)
|
|
197
|
+
|
|
198
|
+
def check_package_error(self):
|
|
199
|
+
# clear_folder(self.update_dir)
|
|
200
|
+
communicate.download_update.emit(100, "", True, "Update Package CheckSum Error!")
|
|
201
|
+
|
|
202
|
+
def enabled(self):
|
|
203
|
+
return self.config is not None
|
|
204
|
+
|
|
205
|
+
def parse_data(self, release):
|
|
206
|
+
version = release.get('tag_name')
|
|
207
|
+
time = datetime.strptime(release.get('published_at'), "%Y-%m-%dT%H:%M:%SZ").strftime('%Y-%m-%d %H:%M:%S')
|
|
208
|
+
target_asset = None
|
|
209
|
+
for asset in release.get('assets'):
|
|
210
|
+
asset = {
|
|
211
|
+
'name': asset.get('name'),
|
|
212
|
+
'url': asset.get('browser_download_url'),
|
|
213
|
+
'size': asset.get('size'),
|
|
214
|
+
'readable_size': convert_size(asset.get('size'))
|
|
215
|
+
}
|
|
216
|
+
asset['type'] = asset['url'].rsplit('.', 1)[1]
|
|
217
|
+
url = asset.get('url')
|
|
218
|
+
if version in url:
|
|
219
|
+
if 'debug' in url and self.debug:
|
|
220
|
+
target_asset = asset
|
|
221
|
+
elif 'release' in url and not self.debug:
|
|
222
|
+
target_asset = asset
|
|
223
|
+
if not target_asset:
|
|
224
|
+
raise ValueError(f'No asset found for version: {version}')
|
|
225
|
+
release = {
|
|
226
|
+
'version': version,
|
|
227
|
+
'notes': release.get('body'),
|
|
228
|
+
'time': time,
|
|
229
|
+
'draft': release.get('draft'),
|
|
230
|
+
'prerelease': release.get('prerelease'),
|
|
231
|
+
}
|
|
232
|
+
release.update(target_asset)
|
|
233
|
+
return release
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def is_newer_version(base_version, target_version):
|
|
237
|
+
base_version = list(map(int, base_version[1:].split('.')))
|
|
238
|
+
target_version = list(map(int, target_version[1:].split('.')))
|
|
239
|
+
|
|
240
|
+
# Compare the versions
|
|
241
|
+
return base_version < target_version
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def convert_size(size_bytes):
|
|
245
|
+
if size_bytes == 0:
|
|
246
|
+
return "0B"
|
|
247
|
+
size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
|
|
248
|
+
i = int(math.floor(math.log(size_bytes, 1024)))
|
|
249
|
+
p = math.pow(1024, i)
|
|
250
|
+
s = round(size_bytes / p, 2)
|
|
251
|
+
return f"{s} {size_name[i]}"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import os.path
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
from ok.util.path import dir_checksum
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def write_checksum_to_file(folder_path):
|
|
8
|
+
# Call the dir_checksum function
|
|
9
|
+
checksum = dir_checksum(folder_path)
|
|
10
|
+
|
|
11
|
+
# Write the checksum to a file named 'md5.txt' in the same folder
|
|
12
|
+
file = os.path.join(folder_path, 'md5.txt')
|
|
13
|
+
with open(file, 'w') as file:
|
|
14
|
+
file.write(checksum)
|
|
15
|
+
print(f'write checksum {checksum} to {file}')
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
if __name__ == "__main__":
|
|
19
|
+
# Get the folder path from the command line arguments
|
|
20
|
+
folder_path = sys.argv[1]
|
|
21
|
+
|
|
22
|
+
# Call the function
|
|
23
|
+
write_checksum_to_file(folder_path)
|
|
File without changes
|