ok-script 2.0.6__tar.gz → 2.0.7b1__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.
Files changed (360) hide show
  1. {ok_script-2.0.6/ok_script.egg-info → ok_script-2.0.7b1}/PKG-INFO +1 -1
  2. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/__init__.py +46 -6
  3. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/notification/manager.py +13 -1
  4. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/notification/providers.py +72 -0
  5. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/MainWindow.py +10 -2
  6. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/en_US.qm +0 -0
  7. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/en_US.ts +72 -0
  8. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/es_ES.qm +0 -0
  9. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/es_ES.ts +72 -0
  10. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/ja_JP.qm +0 -0
  11. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/ja_JP.ts +72 -0
  12. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/ko_KR.qm +0 -0
  13. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/ko_KR.ts +72 -0
  14. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/zh_CN.qm +0 -0
  15. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/zh_CN.ts +72 -0
  16. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/zh_TW.qm +0 -0
  17. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/zh_TW.ts +72 -0
  18. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/resources.py +5154 -4703
  19. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/ScheduleTaskTab.py +49 -17
  20. ok_script-2.0.7b1/ok/ui/qt/tasks/schedule_index_sync.py +587 -0
  21. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/web/app.py +30 -2
  22. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/GlobalConfig.py +32 -0
  23. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/process.py +15 -1
  24. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/windows_schedule.py +134 -17
  25. {ok_script-2.0.6 → ok_script-2.0.7b1/ok_script.egg-info}/PKG-INFO +1 -1
  26. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok_script.egg-info/SOURCES.txt +5 -1
  27. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_notifications.py +84 -2
  28. ok_script-2.0.7b1/tests/test_schedule_startup.py +117 -0
  29. ok_script-2.0.7b1/tests/test_schedule_task_index_sync.py +657 -0
  30. ok_script-2.0.7b1/tests/test_windows_schedule_target_parse.py +99 -0
  31. {ok_script-2.0.6 → ok_script-2.0.7b1}/LICENSE.txt +0 -0
  32. {ok_script-2.0.6 → ok_script-2.0.7b1}/MANIFEST.in +0 -0
  33. {ok_script-2.0.6 → ok_script-2.0.7b1}/README.md +0 -0
  34. {ok_script-2.0.6 → ok_script-2.0.7b1}/diagnostics/qq_trace.py +0 -0
  35. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/__main__.py +0 -0
  36. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/alas/__init__.py +0 -0
  37. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/alas/emulator_base.py +0 -0
  38. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/alas/emulator_windows.py +0 -0
  39. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/alas/platform_windows.py +0 -0
  40. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/alas/utils.py +0 -0
  41. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/capture/__init__.py +0 -0
  42. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/capture/adb/__init__.py +0 -0
  43. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/capture/adb/deep.py +0 -0
  44. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/capture/adb/minitouch.py +0 -0
  45. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/capture/adb/nemu_ipc.py +0 -0
  46. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/capture/adb/nemu_utils.py +0 -0
  47. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/capture/adb/pool.py +0 -0
  48. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/capture/adb/timer.py +0 -0
  49. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/capture/adb/util.py +0 -0
  50. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/capture/windows/__init__.py +0 -0
  51. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/capture/windows/d3d11.py +0 -0
  52. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/capture/windows/dump.py +0 -0
  53. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/cli.py +0 -0
  54. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/__init__.py +0 -0
  55. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/config_schema.py +0 -0
  56. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/downloads.py +0 -0
  57. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/events.py +0 -0
  58. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/icons.py +0 -0
  59. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/notifications.py +0 -0
  60. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/screenshot.py +0 -0
  61. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/script_editing.py +0 -0
  62. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/script_packager.py +0 -0
  63. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/script_templates.py +0 -0
  64. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/start_controller.py +0 -0
  65. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/task_manager.py +0 -0
  66. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/template_store.py +0 -0
  67. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/translation.py +0 -0
  68. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/core/ui_config.py +0 -0
  69. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/DeviceManager.py +0 -0
  70. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/__init__.py +0 -0
  71. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture.py +0 -0
  72. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture_methods/__init__.py +0 -0
  73. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture_methods/adb.py +0 -0
  74. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture_methods/base.py +0 -0
  75. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture_methods/bitblt.py +0 -0
  76. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture_methods/bitblt_utils.py +0 -0
  77. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture_methods/browser.py +0 -0
  78. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture_methods/desktop_duplication.py +0 -0
  79. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture_methods/hwnd_window.py +0 -0
  80. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture_methods/image.py +0 -0
  81. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture_methods/nemu_ipc.py +0 -0
  82. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture_methods/types.py +0 -0
  83. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture_methods/update.py +0 -0
  84. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/capture_methods/windows_graphics.py +0 -0
  85. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/interaction.py +0 -0
  86. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/interaction_methods/__init__.py +0 -0
  87. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/interaction_methods/adb.py +0 -0
  88. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/interaction_methods/base.py +0 -0
  89. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/interaction_methods/browser.py +0 -0
  90. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/interaction_methods/do_nothing.py +0 -0
  91. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/interaction_methods/foreground_post_message.py +0 -0
  92. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/interaction_methods/genshin.py +0 -0
  93. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/interaction_methods/keys.py +0 -0
  94. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/interaction_methods/post_message.py +0 -0
  95. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/interaction_methods/pydirect.py +0 -0
  96. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/interaction_methods/pynput.py +0 -0
  97. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/interaction_methods/swipe.py +0 -0
  98. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/device/intercation.py +0 -0
  99. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/feature/Box.py +0 -0
  100. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/feature/Feature.py +0 -0
  101. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/feature/FeatureSet.py +0 -0
  102. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/feature/__init__.py +0 -0
  103. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/gui/__init__.py +0 -0
  104. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/gui/util/pyappify_startup.py +0 -0
  105. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/notification/__init__.py +0 -0
  106. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/notification/messenger_images.py +0 -0
  107. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/notification/pipeline.py +0 -0
  108. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/notification/ppocr.py +0 -0
  109. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/notification/system.py +0 -0
  110. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/notification/windows_messenger.py +0 -0
  111. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ocr/__init__.py +0 -0
  112. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ocr/download_paddle_model.py +0 -0
  113. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
  114. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
  115. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
  116. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
  117. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
  118. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
  119. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
  120. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
  121. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
  122. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Media/__init__.py +0 -0
  123. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
  124. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Security/__init__.py +0 -0
  125. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
  126. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/Storage/__init__.py +0 -0
  127. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/UI/ViewManagement/__init__.py +0 -0
  128. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/UI/__init__.py +0 -0
  129. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/Windows/__init__.py +0 -0
  130. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/__init__.py +0 -0
  131. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/delegate.py +0 -0
  132. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/export.py +0 -0
  133. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/idldsl.py +0 -0
  134. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/inspectable.py +0 -0
  135. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/roapi.py +0 -0
  136. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/types.py +0 -0
  137. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/rotypes/winstring.py +0 -0
  138. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/task/DiagnosisTask.py +0 -0
  139. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/task/TaskExecutor.py +0 -0
  140. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/task/__init__.py +0 -0
  141. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/task/exceptions.py +0 -0
  142. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/task/task.py +0 -0
  143. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/task/web.py +0 -0
  144. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/test/OKTestRunner.py +0 -0
  145. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/test/RunTests.py +0 -0
  146. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/test/TaskTestCase.py +0 -0
  147. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/test/__init__.py +0 -0
  148. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/third_party/__init__.py +0 -0
  149. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/third_party/paperclip.py +0 -0
  150. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/__init__.py +0 -0
  151. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/overlay/__init__.py +0 -0
  152. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/overlay/win32_gdi.py +0 -0
  153. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/Communicate.py +0 -0
  154. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/MessageWindow.py +0 -0
  155. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/StartController.py +0 -0
  156. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/TabTitles.py +0 -0
  157. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/__init__.py +0 -0
  158. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/about/AboutTab.py +0 -0
  159. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/about/HttpTextEdit.py +0 -0
  160. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/about/LinksBar.py +0 -0
  161. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/about/ProjectCard.py +0 -0
  162. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/about/UpdateCard.py +0 -0
  163. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/about/VersionCard.py +0 -0
  164. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/about/__init__.py +0 -0
  165. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/common/OKIcon.py +0 -0
  166. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/common/__init__.py +0 -0
  167. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/common/accent_color.py +0 -0
  168. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/common/config.py +0 -0
  169. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/common/design_system.py +0 -0
  170. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/common/icons.py +0 -0
  171. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/common/style_sheet.py +0 -0
  172. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/debug/DebugTab.py +0 -0
  173. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/debug/OverlayWidget.py +0 -0
  174. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/debug/RunCodeTab.py +0 -0
  175. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/debug/Screenshot.py +0 -0
  176. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/debug/__init__.py +0 -0
  177. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/events.py +0 -0
  178. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/GettextTranslator.py +0 -0
  179. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/__init__.py +0 -0
  180. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/path.py +0 -0
  181. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/i18n/update.py +0 -0
  182. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/overlay/OverlayWindow.py +0 -0
  183. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/overlay/__init__.py +0 -0
  184. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/__init__.py +0 -0
  185. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/dark/card.qss +0 -0
  186. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/dark/discord.svg +0 -0
  187. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/dark/heart.svg +0 -0
  188. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/dark/message_window.qss +0 -0
  189. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/dark/setting_interface.qss +0 -0
  190. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/dark/status_bar.qss +0 -0
  191. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/dark/stop.svg +0 -0
  192. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/dark/tab.qss +0 -0
  193. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/light/card.qss +0 -0
  194. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/light/discord.svg +0 -0
  195. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/light/heart.svg +0 -0
  196. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/light/message_window.qss +0 -0
  197. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/light/setting_interface.qss +0 -0
  198. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/light/status_bar.qss +0 -0
  199. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/light/stop.svg +0 -0
  200. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qss/light/tab.qss +0 -0
  201. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/qt.qrc +0 -0
  202. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/settings/GlobalConfigCard.py +0 -0
  203. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/settings/GlobalConfigTab.py +0 -0
  204. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/settings/SettingTab.py +0 -0
  205. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/settings/__init__.py +0 -0
  206. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/start/LogWindow.py +0 -0
  207. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/start/SelectCaptureListView.py +0 -0
  208. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/start/SelectInteractionListView.py +0 -0
  209. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/start/StartCard.py +0 -0
  210. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/start/StartTab.py +0 -0
  211. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/start/__init__.py +0 -0
  212. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/ConfigCard.py +0 -0
  213. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/ConfigItemFactory.py +0 -0
  214. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/ConfigLabelAndWidget.py +0 -0
  215. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/EditTaskTab.py +0 -0
  216. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/LabelAndButtons.py +0 -0
  217. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/LabelAndDoubleSpinBox.py +0 -0
  218. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/LabelAndDropDown.py +0 -0
  219. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/LabelAndFileSelector.py +0 -0
  220. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/LabelAndGlobal.py +0 -0
  221. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/LabelAndLineEdit.py +0 -0
  222. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/LabelAndList.py +0 -0
  223. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/LabelAndMultiSelection.py +0 -0
  224. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/LabelAndSpinBox.py +0 -0
  225. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/LabelAndSwitchButton.py +0 -0
  226. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/LabelAndTextEdit.py +0 -0
  227. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/LabelAndWidget.py +0 -0
  228. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/MarkUpWindow.py +0 -0
  229. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/ModifyListDialog.py +0 -0
  230. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/ModifyListItem.py +0 -0
  231. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/OneTimeTaskTab.py +0 -0
  232. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/PythonHighlighter.py +0 -0
  233. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/RecordScript.py +0 -0
  234. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/ScriptPackager.py +0 -0
  235. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/StartButton.py +0 -0
  236. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/TaskCard.py +0 -0
  237. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/TaskManger.py +0 -0
  238. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/TaskOpButton.py +0 -0
  239. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/TaskTab.py +0 -0
  240. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/TemplateFactory.py +0 -0
  241. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/TemplateTab.py +0 -0
  242. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/TooltipTableWidget.py +0 -0
  243. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/TriggerTaskTab.py +0 -0
  244. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/tasks/__init__.py +0 -0
  245. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/util/Alert.py +0 -0
  246. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/util/InitWorker.py +0 -0
  247. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/util/__init__.py +0 -0
  248. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/util/app.py +0 -0
  249. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/util/download.py +0 -0
  250. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/util/pip_util.py +0 -0
  251. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/util/pyappify_startup.py +0 -0
  252. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/util/touch_scroll.py +0 -0
  253. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/util/windows_thumbnail.py +0 -0
  254. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/BaseLoading.py +0 -0
  255. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/BaseWindow.py +0 -0
  256. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/Card.py +0 -0
  257. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/CustomTab.py +0 -0
  258. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/EmptyCard.py +0 -0
  259. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/ExpandCardLayout.py +0 -0
  260. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/FlowLayout.py +0 -0
  261. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/FramelessDialog.py +0 -0
  262. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/ImageWidget.py +0 -0
  263. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/ListTableWidgetItem.py +0 -0
  264. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/NumericTableWidgetItem.py +0 -0
  265. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/OkCompactSpinBox.py +0 -0
  266. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/SortingTableWidgetItem.py +0 -0
  267. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/StartLoadingDialog.py +0 -0
  268. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/StatusBar.py +0 -0
  269. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/Tab.py +0 -0
  270. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/TabWidget.py +0 -0
  271. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/UpdateConfigWidgetItem.py +0 -0
  272. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/WidgetWithVLabel.py +0 -0
  273. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/YesNonWidgetItem.py +0 -0
  274. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/qt/widget/__init__.py +0 -0
  275. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/web/__init__.py +0 -0
  276. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/web/requirements.py +0 -0
  277. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/web/server.py +0 -0
  278. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/web/static/app.js +0 -0
  279. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/web/static/chunk-fluent.js +0 -0
  280. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/web/static/chunk-react.js +0 -0
  281. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/web/static/index.css +0 -0
  282. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/ui/web/static/index.html +0 -0
  283. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/update/__init__.py +0 -0
  284. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/update/copy_ok_folder.py +0 -0
  285. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/update/inline_ok_requirements.py +0 -0
  286. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/Analytics.py +0 -0
  287. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/__init__.py +0 -0
  288. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/blur.py +0 -0
  289. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/clazz.py +0 -0
  290. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/collection.py +0 -0
  291. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/color.py +0 -0
  292. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/config.py +0 -0
  293. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/explorer.py +0 -0
  294. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/file.py +0 -0
  295. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/gpu_driver_settings.py +0 -0
  296. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/handler.py +0 -0
  297. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/i18n.py +0 -0
  298. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/logger.py +0 -0
  299. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/partial_sync_repo.py +0 -0
  300. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/print_hwnd.py +0 -0
  301. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok/util/window.py +0 -0
  302. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok_script.egg-info/dependency_links.txt +0 -0
  303. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok_script.egg-info/entry_points.txt +0 -0
  304. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok_script.egg-info/not-zip-safe +0 -0
  305. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok_script.egg-info/requires.txt +0 -0
  306. {ok_script-2.0.6 → ok_script-2.0.7b1}/ok_script.egg-info/top_level.txt +0 -0
  307. {ok_script-2.0.6 → ok_script-2.0.7b1}/pyproject.toml +0 -0
  308. {ok_script-2.0.6 → ok_script-2.0.7b1}/scripts/generate_web_i18n.py +0 -0
  309. {ok_script-2.0.6 → ok_script-2.0.7b1}/setup.cfg +0 -0
  310. {ok_script-2.0.6 → ok_script-2.0.7b1}/setup.py +0 -0
  311. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_accent_color.py +0 -0
  312. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_app.py +0 -0
  313. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_base_interaction.py +0 -0
  314. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_blur.py +0 -0
  315. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_box.py +0 -0
  316. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_capture_update.py +0 -0
  317. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_cli.py +0 -0
  318. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_config_card.py +0 -0
  319. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_core_events.py +0 -0
  320. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_core_ui_services.py +0 -0
  321. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_device_manager.py +0 -0
  322. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_expand_card_layout.py +0 -0
  323. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_explorer.py +0 -0
  324. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_global_config.py +0 -0
  325. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_gpu_driver_settings.py +0 -0
  326. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_handler.py +0 -0
  327. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_headless_imports.py +0 -0
  328. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_inline_ok_requirements.py +0 -0
  329. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_logger.py +0 -0
  330. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_main_window_notifications.py +0 -0
  331. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_main_window_startup_tab.py +0 -0
  332. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_main_window_system_theme.py +0 -0
  333. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_missing_frame.py +0 -0
  334. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_navigation_state.py +0 -0
  335. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_nemu_ipc_capture.py +0 -0
  336. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_ok_mutex.py +0 -0
  337. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_overlay_custom_draw.py +0 -0
  338. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_package_metadata.py +0 -0
  339. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_process.py +0 -0
  340. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_process_mutex.py +0 -0
  341. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_pyappify_startup_update.py +0 -0
  342. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_qt_events.py +0 -0
  343. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_qt_legacy_imports.py +0 -0
  344. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_qt_page_layout.py +0 -0
  345. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_runtime_startup.py +0 -0
  346. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_start_controller.py +0 -0
  347. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_start_tab_overlay.py +0 -0
  348. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_task_executor_queue.py +0 -0
  349. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_task_ui.py +0 -0
  350. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_template_tab.py +0 -0
  351. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_touch_scroll.py +0 -0
  352. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_translation_fallback.py +0 -0
  353. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_ui_config.py +0 -0
  354. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_web_app.py +0 -0
  355. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_web_i18n.py +0 -0
  356. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_web_server.py +0 -0
  357. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_web_task_tabs.py +0 -0
  358. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_web_ui_pages.py +0 -0
  359. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_web_ui_tasks.py +0 -0
  360. {ok_script-2.0.6 → ok_script-2.0.7b1}/tests/test_windows_graphics_capture.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ok-script
3
- Version: 2.0.6
3
+ Version: 2.0.7b1
4
4
  Summary: Automation with Computer Vision for Python
5
5
  Author-email: ok-oldking <firedcto@gmail.com>
6
6
  License: ok-script License
@@ -361,7 +361,9 @@ class App(_OverlayConfigMixin):
361
361
  if ok_tr := QCoreApplication.translate("app", key):
362
362
  if ok_tr != key:
363
363
  return ok_tr
364
- if self.to_translate is not None:
364
+ # 纯数字配置值(如 self.tr("100"))不是需要翻译的文案,收集前过滤掉,
365
+ # 避免污染 .po 翻译目录(生成一堆无意义的纯数字 msgid)。
366
+ if self.to_translate is not None and not (isinstance(key, str) and key.strip().isdigit()):
365
367
  self.to_translate.add(key)
366
368
  if self.po_translation is None:
367
369
  locale_name = self.locale.name()
@@ -746,8 +748,10 @@ class OK:
746
748
  )
747
749
  use_gui = (ui_config is not None and ui_config["type"] == "qt"
748
750
  and not self.args.get('headless', False))
749
- if not use_gui and self.args.get('task', 0) > 0:
750
- self.run_task(self.args.get('task'), exit_after=self.args.get('exit', False))
751
+ task_arg = self.args.get('task', 0)
752
+ has_task = bool(task_arg) if isinstance(task_arg, str) else task_arg > 0
753
+ if not use_gui and has_task:
754
+ self.run_task(task_arg, exit_after=self.args.get('exit', False))
751
755
  return
752
756
  if use_gui:
753
757
  if not self.init_error:
@@ -789,11 +793,18 @@ class OK:
789
793
  from ok.core.events import communicate
790
794
  from ok.util.GlobalConfig import basic_options
791
795
 
792
- task_number = self.args.get('task', 0)
796
+ task_arg = self.args.get('task', 0)
793
797
  app = self.headless_app if self.should_init_task_manager_headless() else self.app
794
798
  app.initialize_overlay()
795
799
  communicate.start_success.emit()
796
- if task_number > 0:
800
+ if task_arg:
801
+ if isinstance(task_arg, str):
802
+ # -t 传任务名/类名:解析为当前 onetime_tasks 中的任务实例再启动
803
+ start_task = self.get_onetime_task(task_arg)
804
+ logger.info(f'start runtime with task name {task_arg}')
805
+ app.start_controller.start(start_task, exit_after=self.args.get('exit', False))
806
+ return True
807
+ task_number = task_arg
797
808
  logger.info(f'start runtime with task param {task_number - 1} {self.args.get("exit", False)}')
798
809
  app.start_controller.start(task_number - 1, exit_after=self.args.get('exit', False))
799
810
  elif self.global_config.get_config(basic_options).get('Auto Start Game When App Starts'):
@@ -867,9 +878,38 @@ class OK:
867
878
 
868
879
  def find_task_by_name(self, tasks, task):
869
880
  normalized_task = task.lower()
881
+
882
+ # 1) 若传入的是"模块路径.类名"形式(含点,如 src.tasks.onetime.DailyTask),
883
+ # 优先按完整标识精确匹配(唯一、不随名称变化)。
884
+ if "." in task:
885
+ full_matches = [
886
+ candidate for candidate in tasks
887
+ if f"{candidate.__class__.__module__}.{candidate.__class__.__name__}".lower() == normalized_task
888
+ ]
889
+ if len(full_matches) == 1:
890
+ return full_matches[0]
891
+ if len(full_matches) > 1:
892
+ names = ', '.join(candidate.__class__.__name__ for candidate in full_matches)
893
+ raise ValueError(f'Multiple tasks matched "{task}": {names}')
894
+
895
+ # 2) 模块路径+类名精确匹配失败(项目重构/模块移动/目录重命名等):
896
+ # 回退到按类名匹配当前任务;若命中,说明是同一任务类、只是模块路径变了。
897
+ class_name = task.rsplit(".", 1)[-1]
898
+ class_matches = [
899
+ candidate for candidate in tasks
900
+ if candidate.__class__.__name__.lower() == class_name.lower()
901
+ ]
902
+ if len(class_matches) == 1:
903
+ return class_matches[0]
904
+ if len(class_matches) > 1:
905
+ names = ', '.join(candidate.__class__.__name__ for candidate in class_matches)
906
+ raise ValueError(f'Multiple tasks matched "{task}": {names}')
907
+
908
+ # 3) 非模块路径形式(或模块路径与类名都未命中):按 name / 类名精确匹配
870
909
  exact_matches = [
871
910
  candidate for candidate in tasks
872
- if candidate.name.lower() == normalized_task or candidate.__class__.__name__.lower() == normalized_task
911
+ if candidate.name.lower() == normalized_task
912
+ or candidate.__class__.__name__.lower() == normalized_task
873
913
  ]
874
914
  if len(exact_matches) == 1:
875
915
  return exact_matches[0]
@@ -1,7 +1,8 @@
1
1
  from ok.notification.pipeline import NotificationPipeline
2
2
  from ok.notification.ppocr import NotificationPPOCR
3
3
  from ok.notification.providers import (
4
- DiscordProvider, QQBotProvider, TelegramBotProvider, WeComWebhookProvider)
4
+ DiscordProvider, QQBotProvider, SmtpProvider, TelegramBotProvider,
5
+ WeComWebhookProvider)
5
6
  from ok.notification.windows_messenger import MessengerAutomation
6
7
  from ok.util.GlobalConfig import (
7
8
  DISCORD_NOTIFICATION_ENABLED, DISCORD_WEBHOOK, NOTIFICATION_OPTION_NAME,
@@ -10,6 +11,9 @@ from ok.util.GlobalConfig import (
10
11
  QQ_BOT_APP_ID, QQ_BOT_CHANNEL_ID, QQ_BOT_NOTIFICATION_ENABLED,
11
12
  QQ_BOT_TOKEN, TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID,
12
13
  TELEGRAM_NOTIFICATION_ENABLED, WECOM_NOTIFICATION_ENABLED, WECOM_WEBHOOK,
14
+ SMTP_DEFAULT_RECIPIENT, SMTP_DEFAULT_SENDER, SMTP_HOST,
15
+ SMTP_NOTIFICATION_ENABLED, SMTP_PASSWORD, SMTP_PORT, SMTP_USE_TLS,
16
+ SMTP_USERNAME,
13
17
  )
14
18
  from ok.util.logger import Logger
15
19
 
@@ -46,6 +50,7 @@ class NotificationManager:
46
50
  self.config.get(TELEGRAM_NOTIFICATION_ENABLED),
47
51
  self.config.get(WECOM_NOTIFICATION_ENABLED),
48
52
  self.config.get(QQ_BOT_NOTIFICATION_ENABLED),
53
+ self.config.get(SMTP_NOTIFICATION_ENABLED),
49
54
  ))
50
55
 
51
56
  def submit(self, title, message, images=None):
@@ -89,6 +94,13 @@ class NotificationManager:
89
94
  self._safe_send('QQ Bot', QQBotProvider().send,
90
95
  self.config.get(QQ_BOT_APP_ID), self.config.get(QQ_BOT_TOKEN),
91
96
  self.config.get(QQ_BOT_CHANNEL_ID), title, message, images)
97
+ if self.config.get(SMTP_NOTIFICATION_ENABLED):
98
+ self._safe_send('SMTP', SmtpProvider(
99
+ self.config.get(SMTP_HOST), self.config.get(SMTP_PORT),
100
+ self.config.get(SMTP_USERNAME), self.config.get(SMTP_PASSWORD),
101
+ self.config.get(SMTP_USE_TLS), self.config.get(SMTP_DEFAULT_SENDER),
102
+ self.config.get(SMTP_DEFAULT_RECIPIENT)).send,
103
+ None, title, message, images)
92
104
  if self.pipeline.stop_event.is_set():
93
105
  return False
94
106
  if self.config.get(QQ_NOTIFICATION_ENABLED):
@@ -1,6 +1,9 @@
1
1
  import io
2
2
  import hashlib
3
3
  import base64
4
+ import smtplib
5
+ import ssl
6
+ from email.message import EmailMessage
4
7
 
5
8
  import cv2
6
9
  import requests
@@ -160,3 +163,72 @@ class QQBotProvider:
160
163
  except Exception as e:
161
164
  logger.error('QQ Bot notification failed', e)
162
165
  return False
166
+
167
+
168
+ class SmtpProvider:
169
+ """SMTP email notification provider using Python stdlib."""
170
+
171
+ def __init__(self, host, port, username, password, use_tls,
172
+ default_sender, default_recipient):
173
+ self.host = str(host or '').strip()
174
+ self.port = int(port or 587)
175
+ self.username = str(username or '').strip()
176
+ self.password = str(password or '').strip()
177
+ self.use_tls = bool(use_tls)
178
+ self.default_sender = str(default_sender or '').strip()
179
+ self.default_recipient = str(default_recipient or '').strip()
180
+
181
+ def send(self, webhook, title, message, images, sender=None, sender_icon=None):
182
+ # webhook and sender_icon are ignored for SMTP.
183
+ if not self.host or not self.default_sender or not self.default_recipient:
184
+ logger.warning('SMTP notification enabled but host/sender/recipient not configured')
185
+ return False
186
+
187
+ msg = EmailMessage()
188
+ msg['Subject'] = str(title or 'ok-script Notification')
189
+ msg['From'] = str(sender or self.default_sender)
190
+ msg['To'] = self.default_recipient
191
+ msg.set_content(str(message or ''))
192
+ self._attach_images(msg, images)
193
+
194
+ # Secure default context (TLS 1.2+, certificate verification on).
195
+ # NOSONAR: SonarPython flags create_default_context() as S4423 false positive.
196
+ context = ssl.create_default_context() # NOSONAR
197
+ try:
198
+ self._deliver(msg, context)
199
+ return True
200
+ except smtplib.SMTPAuthenticationError as e:
201
+ logger.error('SMTP authentication failed', e)
202
+ return False
203
+ except smtplib.SMTPConnectError as e:
204
+ logger.error('SMTP connection failed', e)
205
+ return False
206
+ except Exception as e:
207
+ logger.error('SMTP notification failed', e)
208
+ return False
209
+
210
+ def _deliver(self, msg, context):
211
+ """Connect to the SMTP server and send the message."""
212
+ if self.use_tls and self.port == 465:
213
+ server = smtplib.SMTP_SSL(self.host, self.port, timeout=30, context=context)
214
+ else:
215
+ server = smtplib.SMTP(self.host, self.port, timeout=30)
216
+ with server:
217
+ server.ehlo()
218
+ if self.use_tls and self.port != 465:
219
+ server.starttls(context=context)
220
+ server.ehlo()
221
+ if self.username:
222
+ server.login(self.username, self.password)
223
+ server.send_message(msg)
224
+
225
+ def _attach_images(self, msg, images):
226
+ """Attach notification images to the message, skipping frames that fail to encode."""
227
+ for index, frame in enumerate(images or []):
228
+ try:
229
+ msg.add_attachment(
230
+ _png_bytes(frame),
231
+ maintype='image', subtype='png',
232
+ filename=f'notification_{index + 1}.png')
233
+ except Exception as e:
234
+ logger.error('SMTP attachment encoding failed', e)
@@ -203,8 +203,16 @@ class MainWindow(FluentWindow):
203
203
  self.update_imported_tabs()
204
204
  communicate.task_list_updated.connect(self.update_imported_tabs)
205
205
 
206
- # 添加计划任务Tab
207
- any_support_schedule = any(task.support_schedule_task for task in visible_onetime_tasks)
206
+ # Resolve this launch from local metadata; Windows migration runs in
207
+ # ScheduleTaskTab's worker so COM cannot block window construction.
208
+ try:
209
+ from ok.ui.qt.tasks.schedule_index_sync import resolve_current_schedule_task
210
+ resolve_current_schedule_task()
211
+ except Exception:
212
+ logger.exception("schedule task index sync failed in __init__")
213
+
214
+ # 添加计划任务Tab(不要求任务 visible,未显示在 GUI 的任务也可计划调度)
215
+ any_support_schedule = any(task.support_schedule_task for task in self.executor.onetime_tasks)
208
216
  if any_support_schedule:
209
217
  from ok.ui.qt.tasks.ScheduleTaskTab import ScheduleTaskTab
210
218
  self.schedule_tab = ScheduleTaskTab(config=self.config)
@@ -1638,6 +1638,78 @@
1638
1638
  <source>Requires the local WeChat client window to be open and running</source>
1639
1639
  <translation>Requires the local WeChat client window to be open and running</translation>
1640
1640
  </message>
1641
+ <message>
1642
+ <source>SMTP Notification</source>
1643
+ <translation>SMTP Notification</translation>
1644
+ </message>
1645
+ <message>
1646
+ <source>SMTP Host</source>
1647
+ <translation>SMTP Host</translation>
1648
+ </message>
1649
+ <message>
1650
+ <source>SMTP Port</source>
1651
+ <translation>SMTP Port</translation>
1652
+ </message>
1653
+ <message>
1654
+ <source>SMTP Username</source>
1655
+ <translation>SMTP Username</translation>
1656
+ </message>
1657
+ <message>
1658
+ <source>SMTP Password</source>
1659
+ <translation>SMTP Password</translation>
1660
+ </message>
1661
+ <message>
1662
+ <source>SMTP Use TLS</source>
1663
+ <translation>SMTP Use TLS</translation>
1664
+ </message>
1665
+ <message>
1666
+ <source>SMTP Default Sender</source>
1667
+ <translation>SMTP Default Sender</translation>
1668
+ </message>
1669
+ <message>
1670
+ <source>SMTP Default Recipient</source>
1671
+ <translation>SMTP Default Recipient</translation>
1672
+ </message>
1673
+ <message>
1674
+ <source>Send notifications through an SMTP email server</source>
1675
+ <translation>Send notifications through an SMTP email server</translation>
1676
+ </message>
1677
+ <message>
1678
+ <source>SMTP server address (e.g. smtp.qq.com)</source>
1679
+ <translation>SMTP server address (e.g. smtp.qq.com)</translation>
1680
+ </message>
1681
+ <message>
1682
+ <source>SMTP server port (587 for STARTTLS)</source>
1683
+ <translation>SMTP server port (587 for STARTTLS)</translation>
1684
+ </message>
1685
+ <message>
1686
+ <source>Username for SMTP authentication (your own email address)</source>
1687
+ <translation>Username for SMTP authentication (your own email address)</translation>
1688
+ </message>
1689
+ <message>
1690
+ <source>Get an authorization code from your email settings</source>
1691
+ <translation>Get an authorization code from your email settings</translation>
1692
+ </message>
1693
+ <message>
1694
+ <source>Use STARTTLS encryption (recommended for port 587)</source>
1695
+ <translation>Use STARTTLS encryption (recommended for port 587)</translation>
1696
+ </message>
1697
+ <message>
1698
+ <source>Sender email address</source>
1699
+ <translation>Sender email address</translation>
1700
+ </message>
1701
+ <message>
1702
+ <source>Recipient email address(es), comma-separated</source>
1703
+ <translation>Recipient email address(es), comma-separated</translation>
1704
+ </message>
1705
+ <message>
1706
+ <source>SMTP server port (587 or 465)</source>
1707
+ <translation>SMTP server port (587 or 465)</translation>
1708
+ </message>
1709
+ <message>
1710
+ <source>Enable TLS encryption (STARTTLS for 587, SMTPS for 465)</source>
1711
+ <translation>Enable TLS encryption (STARTTLS for 587, SMTPS for 465)</translation>
1712
+ </message>
1641
1713
  </context>
1642
1714
  <context>
1643
1715
  <name>ScheduleTaskTable</name>
@@ -1636,6 +1636,78 @@
1636
1636
  <source>Requires the local WeChat client window to be open and running</source>
1637
1637
  <translation>Requiere que la ventana del cliente local de WeChat esté abierta y en ejecución</translation>
1638
1638
  </message>
1639
+ <message>
1640
+ <source>SMTP Notification</source>
1641
+ <translation>Notificación por SMTP</translation>
1642
+ </message>
1643
+ <message>
1644
+ <source>SMTP Host</source>
1645
+ <translation>Servidor SMTP</translation>
1646
+ </message>
1647
+ <message>
1648
+ <source>SMTP Port</source>
1649
+ <translation>Puerto SMTP</translation>
1650
+ </message>
1651
+ <message>
1652
+ <source>SMTP Username</source>
1653
+ <translation>Nombre de usuario</translation>
1654
+ </message>
1655
+ <message>
1656
+ <source>SMTP Password</source>
1657
+ <translation>Contraseña</translation>
1658
+ </message>
1659
+ <message>
1660
+ <source>SMTP Use TLS</source>
1661
+ <translation>Cifrado</translation>
1662
+ </message>
1663
+ <message>
1664
+ <source>SMTP Default Sender</source>
1665
+ <translation>Remitente</translation>
1666
+ </message>
1667
+ <message>
1668
+ <source>SMTP Default Recipient</source>
1669
+ <translation>Destinatario</translation>
1670
+ </message>
1671
+ <message>
1672
+ <source>Send notifications through an SMTP email server</source>
1673
+ <translation>Enviar notificaciones a través de un servidor de correo SMTP</translation>
1674
+ </message>
1675
+ <message>
1676
+ <source>SMTP server address (e.g. smtp.qq.com)</source>
1677
+ <translation>Dirección del servidor SMTP (p. ej., smtp.qq.com)</translation>
1678
+ </message>
1679
+ <message>
1680
+ <source>SMTP server port (587 for STARTTLS)</source>
1681
+ <translation>Puerto del servidor SMTP (587 para STARTTLS)</translation>
1682
+ </message>
1683
+ <message>
1684
+ <source>Username for SMTP authentication (your own email address)</source>
1685
+ <translation>Nombre de usuario para autenticación (introduce tu propia dirección de correo)</translation>
1686
+ </message>
1687
+ <message>
1688
+ <source>Get an authorization code from your email settings</source>
1689
+ <translation>Obtén un código de autorización en la configuración de tu correo</translation>
1690
+ </message>
1691
+ <message>
1692
+ <source>Use STARTTLS encryption (recommended for port 587)</source>
1693
+ <translation>Usar cifrado STARTTLS (recomendado para el puerto 587)</translation>
1694
+ </message>
1695
+ <message>
1696
+ <source>Sender email address</source>
1697
+ <translation>Dirección de correo del remitente</translation>
1698
+ </message>
1699
+ <message>
1700
+ <source>Recipient email address(es), comma-separated</source>
1701
+ <translation>Dirección de correo del destinatario (varias separadas por comas)</translation>
1702
+ </message>
1703
+ <message>
1704
+ <source>SMTP server port (587 or 465)</source>
1705
+ <translation>Puerto del servidor SMTP (587 o 465)</translation>
1706
+ </message>
1707
+ <message>
1708
+ <source>Enable TLS encryption (STARTTLS for 587, SMTPS for 465)</source>
1709
+ <translation>Habilitar cifrado TLS (STARTTLS en el puerto 587, SMTPS en el 465)</translation>
1710
+ </message>
1639
1711
  </context>
1640
1712
  <context>
1641
1713
  <name>ScheduleTaskTable</name>
@@ -1628,6 +1628,78 @@
1628
1628
  <source>Requires the local WeChat client window to be open and running</source>
1629
1629
  <translation>ローカルの WeChat クライアントウィンドウを開いて実行しておく必要があります</translation>
1630
1630
  </message>
1631
+ <message>
1632
+ <source>SMTP Notification</source>
1633
+ <translation>SMTP 通知</translation>
1634
+ </message>
1635
+ <message>
1636
+ <source>SMTP Host</source>
1637
+ <translation>SMTP ホスト</translation>
1638
+ </message>
1639
+ <message>
1640
+ <source>SMTP Port</source>
1641
+ <translation>SMTP ポート</translation>
1642
+ </message>
1643
+ <message>
1644
+ <source>SMTP Username</source>
1645
+ <translation>ユーザー名</translation>
1646
+ </message>
1647
+ <message>
1648
+ <source>SMTP Password</source>
1649
+ <translation>パスワード</translation>
1650
+ </message>
1651
+ <message>
1652
+ <source>SMTP Use TLS</source>
1653
+ <translation>暗号化</translation>
1654
+ </message>
1655
+ <message>
1656
+ <source>SMTP Default Sender</source>
1657
+ <translation>送信者</translation>
1658
+ </message>
1659
+ <message>
1660
+ <source>SMTP Default Recipient</source>
1661
+ <translation>受信者</translation>
1662
+ </message>
1663
+ <message>
1664
+ <source>Send notifications through an SMTP email server</source>
1665
+ <translation>SMTP メールサーバーで通知を送信</translation>
1666
+ </message>
1667
+ <message>
1668
+ <source>SMTP server address (e.g. smtp.qq.com)</source>
1669
+ <translation>SMTP サーバーのアドレス(例: smtp.qq.com)</translation>
1670
+ </message>
1671
+ <message>
1672
+ <source>SMTP server port (587 for STARTTLS)</source>
1673
+ <translation>SMTP サーバーのポート(STARTTLS は 587)</translation>
1674
+ </message>
1675
+ <message>
1676
+ <source>Username for SMTP authentication (your own email address)</source>
1677
+ <translation>認証用ユーザー名(自分のメールアドレスを入力)</translation>
1678
+ </message>
1679
+ <message>
1680
+ <source>Get an authorization code from your email settings</source>
1681
+ <translation>メール設定画面で認可コードを取得してください</translation>
1682
+ </message>
1683
+ <message>
1684
+ <source>Use STARTTLS encryption (recommended for port 587)</source>
1685
+ <translation>STARTTLS 暗号化を使用(ポート 587 に推奨)</translation>
1686
+ </message>
1687
+ <message>
1688
+ <source>Sender email address</source>
1689
+ <translation>送信者のメールアドレス</translation>
1690
+ </message>
1691
+ <message>
1692
+ <source>Recipient email address(es), comma-separated</source>
1693
+ <translation>受信者のメールアドレス(複数の場合はカンマ区切り)</translation>
1694
+ </message>
1695
+ <message>
1696
+ <source>SMTP server port (587 or 465)</source>
1697
+ <translation>SMTP サーバーのポート(587または465)</translation>
1698
+ </message>
1699
+ <message>
1700
+ <source>Enable TLS encryption (STARTTLS for 587, SMTPS for 465)</source>
1701
+ <translation>TLS 暗号化を有効化(ポート 587 は STARTTLS、465 は SMTPS)</translation>
1702
+ </message>
1631
1703
  </context>
1632
1704
  <context>
1633
1705
  <name>ScheduleTaskTable</name>
@@ -1637,6 +1637,78 @@
1637
1637
  <source>Requires the local WeChat client window to be open and running</source>
1638
1638
  <translation>로컬 WeChat 클라이언트 창이 열려 있고 실행 중이어야 합니다</translation>
1639
1639
  </message>
1640
+ <message>
1641
+ <source>SMTP Notification</source>
1642
+ <translation>SMTP 알림</translation>
1643
+ </message>
1644
+ <message>
1645
+ <source>SMTP Host</source>
1646
+ <translation>SMTP 호스트</translation>
1647
+ </message>
1648
+ <message>
1649
+ <source>SMTP Port</source>
1650
+ <translation>SMTP 포트</translation>
1651
+ </message>
1652
+ <message>
1653
+ <source>SMTP Username</source>
1654
+ <translation>사용자 이름</translation>
1655
+ </message>
1656
+ <message>
1657
+ <source>SMTP Password</source>
1658
+ <translation>비밀번호</translation>
1659
+ </message>
1660
+ <message>
1661
+ <source>SMTP Use TLS</source>
1662
+ <translation>암호화</translation>
1663
+ </message>
1664
+ <message>
1665
+ <source>SMTP Default Sender</source>
1666
+ <translation>발신자</translation>
1667
+ </message>
1668
+ <message>
1669
+ <source>SMTP Default Recipient</source>
1670
+ <translation>수신자</translation>
1671
+ </message>
1672
+ <message>
1673
+ <source>Send notifications through an SMTP email server</source>
1674
+ <translation>SMTP 메일 서버를 통해 알림 보내기</translation>
1675
+ </message>
1676
+ <message>
1677
+ <source>SMTP server address (e.g. smtp.qq.com)</source>
1678
+ <translation>SMTP 서버 주소 (예: smtp.qq.com)</translation>
1679
+ </message>
1680
+ <message>
1681
+ <source>SMTP server port (587 for STARTTLS)</source>
1682
+ <translation>SMTP 서버 포트 (STARTTLS는 587)</translation>
1683
+ </message>
1684
+ <message>
1685
+ <source>Username for SMTP authentication (your own email address)</source>
1686
+ <translation>인증용 사용자 이름 (자신의 이메일 주소 입력)</translation>
1687
+ </message>
1688
+ <message>
1689
+ <source>Get an authorization code from your email settings</source>
1690
+ <translation>메일 설정 화면에서 인증 코드를 받으세요</translation>
1691
+ </message>
1692
+ <message>
1693
+ <source>Use STARTTLS encryption (recommended for port 587)</source>
1694
+ <translation>STARTTLS 암호화 사용 (587 포트 권장)</translation>
1695
+ </message>
1696
+ <message>
1697
+ <source>Sender email address</source>
1698
+ <translation>발신자 이메일 주소</translation>
1699
+ </message>
1700
+ <message>
1701
+ <source>Recipient email address(es), comma-separated</source>
1702
+ <translation>수신자 이메일 주소 (여러 개는 쉼표로 구분)</translation>
1703
+ </message>
1704
+ <message>
1705
+ <source>SMTP server port (587 or 465)</source>
1706
+ <translation>SMTP 서버 포트 (587 또는 465)</translation>
1707
+ </message>
1708
+ <message>
1709
+ <source>Enable TLS encryption (STARTTLS for 587, SMTPS for 465)</source>
1710
+ <translation>TLS 암호화 활성화 (587 포트는 STARTTLS, 465 포트는 SMTPS)</translation>
1711
+ </message>
1640
1712
  </context>
1641
1713
  <context>
1642
1714
  <name>ScheduleTaskTable</name>
@@ -1634,6 +1634,78 @@
1634
1634
  <source>Requires the local WeChat client window to be open and running</source>
1635
1635
  <translation>需要本地微信客户端窗口保持打开并运行</translation>
1636
1636
  </message>
1637
+ <message>
1638
+ <source>SMTP Notification</source>
1639
+ <translation>SMTP 邮件通知</translation>
1640
+ </message>
1641
+ <message>
1642
+ <source>SMTP Host</source>
1643
+ <translation>SMTP 服务器</translation>
1644
+ </message>
1645
+ <message>
1646
+ <source>SMTP Port</source>
1647
+ <translation>SMTP 端口</translation>
1648
+ </message>
1649
+ <message>
1650
+ <source>SMTP Username</source>
1651
+ <translation>用户名</translation>
1652
+ </message>
1653
+ <message>
1654
+ <source>SMTP Password</source>
1655
+ <translation>密码</translation>
1656
+ </message>
1657
+ <message>
1658
+ <source>SMTP Use TLS</source>
1659
+ <translation>加密</translation>
1660
+ </message>
1661
+ <message>
1662
+ <source>SMTP Default Sender</source>
1663
+ <translation>发件人</translation>
1664
+ </message>
1665
+ <message>
1666
+ <source>SMTP Default Recipient</source>
1667
+ <translation>收件人</translation>
1668
+ </message>
1669
+ <message>
1670
+ <source>Send notifications through an SMTP email server</source>
1671
+ <translation>通过 SMTP 邮件服务器发送通知</translation>
1672
+ </message>
1673
+ <message>
1674
+ <source>SMTP server address (e.g. smtp.qq.com)</source>
1675
+ <translation>SMTP 服务器地址(例如 smtp.qq.com)</translation>
1676
+ </message>
1677
+ <message>
1678
+ <source>SMTP server port (587 for STARTTLS)</source>
1679
+ <translation>SMTP 服务器端口(STARTTLS 使用 587)</translation>
1680
+ </message>
1681
+ <message>
1682
+ <source>Username for SMTP authentication (your own email address)</source>
1683
+ <translation>认证用户名,填入自己的邮箱即可</translation>
1684
+ </message>
1685
+ <message>
1686
+ <source>Get an authorization code from your email settings</source>
1687
+ <translation>在邮箱设置界面获取授权码</translation>
1688
+ </message>
1689
+ <message>
1690
+ <source>Use STARTTLS encryption (recommended for port 587)</source>
1691
+ <translation>使用 STARTTLS 加密(建议 587 端口使用)</translation>
1692
+ </message>
1693
+ <message>
1694
+ <source>Sender email address</source>
1695
+ <translation>发件人邮箱地址</translation>
1696
+ </message>
1697
+ <message>
1698
+ <source>Recipient email address(es), comma-separated</source>
1699
+ <translation>收件人邮箱地址,多个以逗号分隔</translation>
1700
+ </message>
1701
+ <message>
1702
+ <source>SMTP server port (587 or 465)</source>
1703
+ <translation>SMTP 服务器端口(587或465)</translation>
1704
+ </message>
1705
+ <message>
1706
+ <source>Enable TLS encryption (STARTTLS for 587, SMTPS for 465)</source>
1707
+ <translation>启用 TLS 加密(587 端口用 STARTTLS,465 端口用 SMTPS)</translation>
1708
+ </message>
1637
1709
  </context>
1638
1710
  <context>
1639
1711
  <name>ScheduleTaskTable</name>