kotonebot 0.5.0__py3-none-any.whl → 0.7.0__py3-none-any.whl

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 (107) hide show
  1. kotonebot/__init__.py +39 -39
  2. kotonebot/backend/bot.py +312 -312
  3. kotonebot/backend/color.py +525 -525
  4. kotonebot/backend/context/__init__.py +3 -3
  5. kotonebot/backend/context/context.py +1002 -1002
  6. kotonebot/backend/context/task_action.py +183 -183
  7. kotonebot/backend/core.py +86 -129
  8. kotonebot/backend/debug/entry.py +89 -89
  9. kotonebot/backend/debug/mock.py +78 -78
  10. kotonebot/backend/debug/server.py +222 -222
  11. kotonebot/backend/debug/vars.py +351 -351
  12. kotonebot/backend/dispatch.py +227 -227
  13. kotonebot/backend/flow_controller.py +196 -196
  14. kotonebot/backend/image.py +36 -5
  15. kotonebot/backend/loop.py +222 -208
  16. kotonebot/backend/ocr.py +535 -535
  17. kotonebot/backend/preprocessor.py +103 -103
  18. kotonebot/client/__init__.py +9 -9
  19. kotonebot/client/device.py +369 -529
  20. kotonebot/client/fast_screenshot.py +377 -377
  21. kotonebot/client/host/__init__.py +43 -43
  22. kotonebot/client/host/adb_common.py +101 -107
  23. kotonebot/client/host/custom.py +118 -118
  24. kotonebot/client/host/leidian_host.py +196 -196
  25. kotonebot/client/host/mumu12_host.py +353 -353
  26. kotonebot/client/host/protocol.py +214 -214
  27. kotonebot/client/host/windows_common.py +73 -58
  28. kotonebot/client/implements/__init__.py +65 -70
  29. kotonebot/client/implements/adb.py +89 -89
  30. kotonebot/client/implements/nemu_ipc/__init__.py +11 -11
  31. kotonebot/client/implements/nemu_ipc/external_renderer_ipc.py +284 -284
  32. kotonebot/client/implements/nemu_ipc/nemu_ipc.py +327 -327
  33. kotonebot/client/implements/remote_windows.py +188 -188
  34. kotonebot/client/implements/uiautomator2.py +85 -85
  35. kotonebot/client/implements/windows/__init__.py +1 -0
  36. kotonebot/client/implements/windows/print_window.py +133 -0
  37. kotonebot/client/implements/windows/send_message.py +324 -0
  38. kotonebot/client/implements/{windows.py → windows/windows.py} +175 -176
  39. kotonebot/client/protocol.py +69 -69
  40. kotonebot/client/registration.py +24 -24
  41. kotonebot/client/scaler.py +467 -0
  42. kotonebot/config/base_config.py +103 -96
  43. kotonebot/config/config.py +61 -0
  44. kotonebot/config/manager.py +36 -36
  45. kotonebot/core/__init__.py +13 -0
  46. kotonebot/core/entities/base.py +182 -0
  47. kotonebot/core/entities/compound.py +75 -0
  48. kotonebot/core/entities/ocr.py +117 -0
  49. kotonebot/core/entities/template_match.py +198 -0
  50. kotonebot/devtools/__init__.py +42 -0
  51. kotonebot/devtools/cli/__init__.py +6 -0
  52. kotonebot/devtools/cli/main.py +53 -0
  53. kotonebot/{tools → devtools}/mirror.py +354 -354
  54. kotonebot/devtools/project/project.py +41 -0
  55. kotonebot/devtools/project/scanner.py +202 -0
  56. kotonebot/devtools/project/schema.py +99 -0
  57. kotonebot/devtools/resgen/__init__.py +42 -0
  58. kotonebot/devtools/resgen/codegen.py +331 -0
  59. kotonebot/devtools/resgen/core.py +94 -0
  60. kotonebot/devtools/resgen/parsers.py +360 -0
  61. kotonebot/devtools/resgen/utils.py +158 -0
  62. kotonebot/devtools/resgen/validation.py +115 -0
  63. kotonebot/devtools/web/dist/assets/bootstrap-icons-BOrJxbIo.woff +0 -0
  64. kotonebot/devtools/web/dist/assets/bootstrap-icons-BtvjY1KL.woff2 +0 -0
  65. kotonebot/devtools/web/dist/assets/ext-language_tools-CD021WJ2.js +2577 -0
  66. kotonebot/devtools/web/dist/assets/index-B_m5f2LF.js +2836 -0
  67. kotonebot/devtools/web/dist/assets/index-BlEDyGGa.css +9 -0
  68. kotonebot/devtools/web/dist/assets/language-client-C9muzqaq.js +128 -0
  69. kotonebot/devtools/web/dist/assets/mode-python-CtHp76XS.js +476 -0
  70. kotonebot/devtools/web/dist/icons/symbol-class.svg +3 -0
  71. kotonebot/devtools/web/dist/icons/symbol-file.svg +3 -0
  72. kotonebot/devtools/web/dist/icons/symbol-method.svg +3 -0
  73. kotonebot/devtools/web/dist/index.html +25 -0
  74. kotonebot/devtools/web/server/__init__.py +0 -0
  75. kotonebot/devtools/web/server/rest_api.py +217 -0
  76. kotonebot/devtools/web/server/server.py +85 -0
  77. kotonebot/errors.py +76 -76
  78. kotonebot/interop/win/__init__.py +13 -9
  79. kotonebot/interop/win/_mouse.py +310 -310
  80. kotonebot/interop/win/message_box.py +313 -313
  81. kotonebot/interop/win/reg.py +37 -37
  82. kotonebot/interop/win/shake_mouse.py +224 -0
  83. kotonebot/interop/win/shortcut.py +43 -43
  84. kotonebot/interop/win/task_dialog.py +513 -513
  85. kotonebot/interop/win/window.py +89 -0
  86. kotonebot/logging/__init__.py +2 -2
  87. kotonebot/logging/log.py +17 -17
  88. kotonebot/primitives/__init__.py +19 -17
  89. kotonebot/primitives/geometry.py +1067 -862
  90. kotonebot/primitives/visual.py +143 -63
  91. kotonebot/ui/file_host/sensio.py +36 -36
  92. kotonebot/ui/file_host/tmp_send.py +54 -54
  93. kotonebot/ui/pushkit/__init__.py +3 -3
  94. kotonebot/ui/pushkit/image_host.py +88 -88
  95. kotonebot/ui/pushkit/protocol.py +13 -13
  96. kotonebot/ui/pushkit/wxpusher.py +54 -54
  97. kotonebot/ui/user.py +148 -148
  98. kotonebot/util.py +436 -436
  99. {kotonebot-0.5.0.dist-info → kotonebot-0.7.0.dist-info}/METADATA +84 -82
  100. kotonebot-0.7.0.dist-info/RECORD +109 -0
  101. {kotonebot-0.5.0.dist-info → kotonebot-0.7.0.dist-info}/WHEEL +1 -1
  102. kotonebot-0.7.0.dist-info/entry_points.txt +2 -0
  103. {kotonebot-0.5.0.dist-info → kotonebot-0.7.0.dist-info}/licenses/LICENSE +673 -673
  104. kotonebot/client/implements/adb_raw.py +0 -163
  105. kotonebot-0.5.0.dist-info/RECORD +0 -71
  106. /kotonebot/{tools → devtools/project}/__init__.py +0 -0
  107. {kotonebot-0.5.0.dist-info → kotonebot-0.7.0.dist-info}/top_level.txt +0 -0
@@ -1,163 +0,0 @@
1
- import os
2
- import time
3
- import subprocess
4
- import struct
5
- from threading import Thread, Lock
6
- from functools import cached_property
7
- from typing_extensions import override
8
-
9
- import cv2
10
- import numpy as np
11
- from cv2.typing import MatLike
12
- try:
13
- from adbutils._utils import adb_path
14
- from adbutils._device import AdbDevice as AdbUtilsDevice
15
- except ImportError as _e:
16
- from kotonebot.errors import MissingDependencyError
17
- raise MissingDependencyError(_e, 'android')
18
-
19
- from .adb import AdbImpl
20
- from kotonebot import logging
21
-
22
- logger = logging.getLogger(__name__)
23
-
24
- WAIT_TIMEOUT = 10
25
- MAX_RETRY_COUNT = 5
26
- SCRIPT: str = """#!/bin/sh
27
- while true; do
28
- screencap
29
- sleep 0.3
30
- done
31
- """
32
-
33
- class AdbRawImpl(AdbImpl):
34
- def __init__(self, adb_connection: AdbUtilsDevice):
35
- super().__init__(adb_connection)
36
- self.__worker: Thread | None = None
37
- self.__process: subprocess.Popen | None = None
38
- self.__data: MatLike | None = None
39
- self.__retry_count = 0
40
- self.__lock = Lock()
41
- self.__stopping = False
42
-
43
- def __cleanup_worker(self) -> None:
44
- if self.__process:
45
- try:
46
- self.__process.kill()
47
- except:
48
- pass
49
- self.__process = None
50
- if self.__worker:
51
- try:
52
- self.__worker.join()
53
- except:
54
- pass
55
- self.__worker = None
56
- self.__data = None
57
-
58
- def __start_worker(self) -> None:
59
- self.__stopping = True
60
- self.__cleanup_worker()
61
- self.__stopping = False
62
- self.__worker = Thread(target=self.__worker_thread_with_retry, daemon=True)
63
- self.__worker.start()
64
-
65
- def __worker_thread_with_retry(self) -> None:
66
- try:
67
- self.__worker_thread()
68
- except Exception as e:
69
- logger.error(f"Worker thread failed: {e}")
70
- with self.__lock:
71
- self.__retry_count += 1
72
- raise
73
-
74
- def __worker_thread(self) -> None:
75
- with open('screenshot.sh', 'w', encoding='utf-8', newline='\n') as f:
76
- f.write(SCRIPT)
77
- self.adb.push('screenshot.sh', '/data/local/tmp/screenshot.sh')
78
- self.adb.shell(f'chmod 755 /data/local/tmp/screenshot.sh')
79
- os.remove('screenshot.sh')
80
-
81
- cmd = fr'{adb_path()} -s {self.adb.serial} exec-out "sh /data/local/tmp/screenshot.sh"'
82
- self.__process = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
83
-
84
- while not self.__stopping and self.__process.poll() is None:
85
- if self.__process.stdout is None:
86
- logger.error("Failed to get stdout from process")
87
- continue
88
-
89
- # 解析 header
90
- # https://stackoverflow.com/questions/22034959/what-format-does-adb-screencap-sdcard-screenshot-raw-produce-without-p-f
91
- if self.__api_level >= 26:
92
- metadata = self.__process.stdout.read(16)
93
- w, h, p, c = struct.unpack('<IIII', metadata)
94
- # w=width, h=height, p=pixel_format, c=color_space
95
- # 详见:https://android.googlesource.com/platform/frameworks/base/+/26a2b97dbe48ee45e9ae70110714048f2f360f97/cmds/screencap/screencap.cpp#209
96
- else:
97
- metadata = self.__process.stdout.read(12)
98
- w, h, p = struct.unpack('<III', metadata)
99
- if p == 1: # PixelFormat.RGBA_8888
100
- channel = 4
101
- else:
102
- raise ValueError(f"Unsupported pixel format: {p}")
103
- data_size = w * h * channel
104
-
105
- if (data_size < 100 * 100 * 4) or (data_size > 3000 * 3000 * 4):
106
- raise ValueError(f"Invaild data_size: {w}x{h}.")
107
-
108
- # 读取图像数据
109
- # logger.verbose(f"receiving image data: {w}x{h} {data_size} bytes")
110
- image_data = self.__process.stdout.read(data_size)
111
- if not isinstance(image_data, bytes) or len(image_data) != data_size:
112
- logger.error(f"Failed to read image data, expected {data_size} bytes but got {len(image_data) if isinstance(image_data, bytes) else 'non-bytes'}")
113
- raise RuntimeError("Failed to read image data")
114
-
115
- np_data = np.frombuffer(image_data, np.uint8)
116
- np_data = np_data.reshape(h, w, channel)
117
- self.__data = cv2.cvtColor(np_data, cv2.COLOR_RGBA2BGR)
118
-
119
- @cached_property
120
- def __api_level(self) -> int:
121
- try:
122
- output = self.adb.shell("getprop ro.build.version.sdk")
123
- assert isinstance(output, str)
124
- return int(output.strip())
125
- except Exception as e:
126
- logger.error(f"Failed to get API level: {e}")
127
- return 0
128
-
129
- @override
130
- def screenshot(self) -> MatLike:
131
- with self.__lock:
132
- if self.__retry_count >= MAX_RETRY_COUNT:
133
- raise RuntimeError(f"Maximum retry count ({MAX_RETRY_COUNT}) exceeded")
134
-
135
- if not self.__worker or (self.__worker and not self.__worker.is_alive()):
136
- self.__start_worker()
137
-
138
- start_time = time.time()
139
- while self.__data is None:
140
- time.sleep(0.01)
141
- if time.time() - start_time > WAIT_TIMEOUT:
142
- logger.warning("Screenshot timeout, cleaning up and restarting worker...")
143
- with self.__lock:
144
- if self.__retry_count < MAX_RETRY_COUNT:
145
- self.__start_worker()
146
- start_time = time.time() # 重置超时计时器
147
- continue
148
- else:
149
- raise RuntimeError(f"Maximum retry count ({MAX_RETRY_COUNT}) exceeded")
150
-
151
- # 检查 worker 是否还活着
152
- if self.__worker and not self.__worker.is_alive():
153
- with self.__lock:
154
- if self.__retry_count < MAX_RETRY_COUNT:
155
- logger.warning("Worker thread died, restarting...")
156
- self.__start_worker()
157
- else:
158
- raise RuntimeError(f"Maximum retry count ({MAX_RETRY_COUNT}) exceeded")
159
-
160
- logger.verbose(f"adb raw screenshot wait time: {time.time() - start_time:.4f}s")
161
- data = self.__data
162
- self.__data = None
163
- return data
@@ -1,71 +0,0 @@
1
- kotonebot/__init__.py,sha256=1xO-UaCDhT9sAdfKWV3KUwtvws-ONqI7QCTRnYsV48E,597
2
- kotonebot/errors.py,sha256=biNgoJdU1RUxs3RwqKqbdvt2aXsZmkr_wpPjpxUrmS0,2503
3
- kotonebot/util.py,sha256=Tiiwgxbj2YYeqFJtebafZlRfcK970bHBItn5SxUR9pA,13934
4
- kotonebot/backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- kotonebot/backend/bot.py,sha256=kmqWjxSXLHAbPXyKozBZv3s3sY6YSmkXDsIbq7QOWOE,11558
6
- kotonebot/backend/color.py,sha256=kmDtYaWkofbg9QtdWpbMu41a-jorabcffFmtIu9gDR0,19600
7
- kotonebot/backend/core.py,sha256=NAhveckuZLhu356WjpOUQOFXFjcLi5LwoV44IxbBeXY,3897
8
- kotonebot/backend/dispatch.py,sha256=4IzA7pfyH4VFkoA5TLvHLZn_Is7MV9-wx78uVxMe1YQ,7196
9
- kotonebot/backend/flow_controller.py,sha256=fNbZHiFVGkFoC0-MvLTJDKrEjtjDXfrJ7L9vYbTdnIU,6032
10
- kotonebot/backend/image.py,sha256=jXYGVXa9K1zBCJBG1Btsf2AG5XI9A0DMy5uYy6KOusk,28111
11
- kotonebot/backend/loop.py,sha256=e4STYQ6sbUp53xcYJXyhz4vOyEzXds1MKR0xebqU228,6638
12
- kotonebot/backend/ocr.py,sha256=kgnPWnB-Sbl7pAM6_RSaq0NrhlmArL7wzB574TIURMw,17844
13
- kotonebot/backend/preprocessor.py,sha256=ce2J70I4vbiyOly61KVPkfmsJf8Oeuj23Vnmbz_eCGk,3320
14
- kotonebot/backend/context/__init__.py,sha256=TR8WdJt92k62HskPFyfuubyIWXcnJpT_ItGKH1daevY,165
15
- kotonebot/backend/context/context.py,sha256=R91knq7Ry5MSWaFhOj3HIF13u8bomOOsGk59yPOG4aw,33780
16
- kotonebot/backend/context/task_action.py,sha256=HZeYzKFbC3mgOQ1g3rodwhYCncImhqM5FenbKHNsHnc,6261
17
- kotonebot/backend/debug/__init__.py,sha256=pcSpwzU2YwGrogOoHmsI035nkA_-kDLfm-lfBxHuQ-c,43
18
- kotonebot/backend/debug/entry.py,sha256=Ohf42wPs0C6P5ZGEyAJiol0h531Lss6pKhATJMBnl0w,2744
19
- kotonebot/backend/debug/mock.py,sha256=Owm86oYtKnlSfgwqb3n5undlshJjdgNTkFl7D33zWSQ,2040
20
- kotonebot/backend/debug/server.py,sha256=-xZRDy6BSExQi2Zcx_HjuQ8TYviQB_776kPtt16Nooc,7295
21
- kotonebot/backend/debug/vars.py,sha256=_Zj7s4CikU2XU3xKsKeLYhKmImH-vB9xwXYviuproZQ,10561
22
- kotonebot/client/__init__.py,sha256=VlseblhIlmDtNehlxLjbaaSKiXGZSVZSs_RlS7VeKcw,183
23
- kotonebot/client/device.py,sha256=83h2hqNjAyqpPfCnMGXmQMlHfyoVlwiYRP1TgyyEWTA,20828
24
- kotonebot/client/fast_screenshot.py,sha256=v_57ZkEKOv98S0y8FHs_n4de5-k5neSiBJU4CEXDEd4,13270
25
- kotonebot/client/protocol.py,sha256=H9SKCSVPuORn63GuSycFnRV4CMWAfqtEWXZF9YAjY7w,2231
26
- kotonebot/client/registration.py,sha256=xHaCUDNOtA3o8enmSRAVsb1hVoSuv1GstyeM8MgONQM,824
27
- kotonebot/client/host/__init__.py,sha256=1bWuQSObozMVF0JqtvtAm_Fn-A1MsEDaJHCMw42FbAY,1537
28
- kotonebot/client/host/adb_common.py,sha256=OOu1ik3VzoCx1DdGKQPnebByxkAUtBiBp5f6EkBl8eg,3790
29
- kotonebot/client/host/custom.py,sha256=dy49_-ZBosUoSM92CzaEJ7eEHkoooR4VFehDNnIoc98,4104
30
- kotonebot/client/host/leidian_host.py,sha256=ydRJpyArD0F1bDNFcxp0w3ryIOGSfwv9_fzm-IfRg1I,7353
31
- kotonebot/client/host/mumu12_host.py,sha256=lbLsSZJtyEYIyX2iFOVmBCBBMOEYIg1W8gj_5F-nqtU,13911
32
- kotonebot/client/host/protocol.py,sha256=N5kRm_IVubsQQlAOkZvAHPrREbSaSnVYrLqyz9U8inc,7959
33
- kotonebot/client/host/windows_common.py,sha256=kxCSachnMIyZEavl-0-MAwADTd0lqbZmgrUyvgjImXo,2373
34
- kotonebot/client/implements/__init__.py,sha256=b9eaN16EdWPPu1WERA2HysWI1YHPYU9jtQ2wuAA8BvU,2205
35
- kotonebot/client/implements/adb.py,sha256=nMGAIDlKTy9v2SKU3q5XSuE78b9M-wqEQPwN98eLtOU,3199
36
- kotonebot/client/implements/adb_raw.py,sha256=QkYCeLnVHevc6q4qyxW34Y4MTSrhxS9_d7qfBW-QgBI,6292
37
- kotonebot/client/implements/remote_windows.py,sha256=OhgpEcmTYhAsedqPY419BcJTlMvJW0ssJ8nHQjdlEuU,6568
38
- kotonebot/client/implements/uiautomator2.py,sha256=BN1XRZi9LYZrvM9JKpPgs2F1PgXTsLWLzDhkRl-t2nw,2637
39
- kotonebot/client/implements/windows.py,sha256=FduISikRDi72paLs5xpKcohXsC4HkM36AInp8j4Be10,6713
40
- kotonebot/client/implements/nemu_ipc/__init__.py,sha256=9Q7ovvO4qf3sQTHAUTHHuUOgijmd6B8OTKSsdQkYrG0,310
41
- kotonebot/client/implements/nemu_ipc/external_renderer_ipc.py,sha256=TEz7DykLLa30Rb5r5JGt2Odus_OJw4X2HYfiNGsvOyQ,10359
42
- kotonebot/client/implements/nemu_ipc/nemu_ipc.py,sha256=SV6JRShJ_z_f5tzh-0wRn6fhsrjmbsZKBl65j9CmGas,11755
43
- kotonebot/config/__init__.py,sha256=-jATUOdrpUrBRT9RiTRQho2-2zeet50qQggsVMVpqNE,35
44
- kotonebot/config/base_config.py,sha256=BwC3XWc78r8FhBsHhcSBlW2sjhomy5EhRksMDNRuuvA,3342
45
- kotonebot/config/manager.py,sha256=Ybfv92yhM_l2kKKEw1VsKTYxundALlurSpZge7XIDxA,1025
46
- kotonebot/interop/win/__init__.py,sha256=e6Pps5u7z88PabVFG8Vg11RHw3toCSa3GjuihgUcXtc,169
47
- kotonebot/interop/win/_mouse.py,sha256=cMeIA3SaxTJYRfPC1a7M1dkzw-pa2Ctg7pxKAUZdtLI,10131
48
- kotonebot/interop/win/message_box.py,sha256=YiT_CFS9SPCJjAXwrzHktHJ5elCLzmE83sUnPAC9s4o,8322
49
- kotonebot/interop/win/reg.py,sha256=jWf-px_-iK4oJOqu5x955zHQGVDEcunNvuAPXt_DqvY,1310
50
- kotonebot/interop/win/shortcut.py,sha256=ftt0ieKGWDgcozn63URUFBa5x5U8vdrRkUdt_7BnVcc,1721
51
- kotonebot/interop/win/task_dialog.py,sha256=KO8yCelqcoP4K6Jgw18IsXnM5FK1wTCvZ6y-lWsOyx8,19678
52
- kotonebot/logging/__init__.py,sha256=bpRRM3l35XLeFkD7Yxkh1DfzM5FTsfNl7pPjn0E9dW4,140
53
- kotonebot/logging/log.py,sha256=e3Nr8viVSc3wIkPaLQBDRpWbc6nzpwtTmCUPIqSGDaE,538
54
- kotonebot/primitives/__init__.py,sha256=V5NybWHUCIcIe_7m2_5tw_SRCLK7RnBVSUCjCO0QYZU,338
55
- kotonebot/primitives/geometry.py,sha256=qhgms19KIVabyu9nZOphNw1E0q4F-t_pj9vbTiB9ZU4,25749
56
- kotonebot/primitives/visual.py,sha256=eJyNKGynDJO_aI2b8zFcIGaYH7da9n5ICe0mwMpIe8Q,1965
57
- kotonebot/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
- kotonebot/tools/mirror.py,sha256=FnElklO_fKZtzKi72tnRCIuY0veQSU5jLfKv7_tObt0,13466
59
- kotonebot/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
- kotonebot/ui/user.py,sha256=RnswuO4EgFf2eTuOAcnfK9vcrW5F5hEjFyD-3fi5RXY,4337
61
- kotonebot/ui/file_host/sensio.py,sha256=G6L4NqZT6T7wWF9_ZVuH9exa-W9qJ2OaLoB5mxGP_LY,878
62
- kotonebot/ui/file_host/tmp_send.py,sha256=am7dLjbU9eb-7d1HBRp1eBI5ycWeeJamB3DlLELGna8,1748
63
- kotonebot/ui/pushkit/__init__.py,sha256=icm_WYjlfbFhbxxdnKadn-gzYfm1XguTsiiZauqyN0E,70
64
- kotonebot/ui/pushkit/image_host.py,sha256=7miupmjSZP_6krAcF9TxB0Ae7ZJf9OJljrytEaT3MzY,2503
65
- kotonebot/ui/pushkit/protocol.py,sha256=h_1YICkrvviEiZYLAJ1QMnizXMWvqQnIrUY7zIyNWFQ,253
66
- kotonebot/ui/pushkit/wxpusher.py,sha256=qqEmg17wJmHOt6EtKdfInaX22erkMgzkULt6T0pk1Ho,1696
67
- kotonebot-0.5.0.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
68
- kotonebot-0.5.0.dist-info/METADATA,sha256=_Py_jZ16jYDtksdTSVRGHKL8OkXe8XVPQHszN40570E,3154
69
- kotonebot-0.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
70
- kotonebot-0.5.0.dist-info/top_level.txt,sha256=QUWAZdbBndoojkrs6RcNytLAn7a0ns4YNF4tLx2Nc4s,10
71
- kotonebot-0.5.0.dist-info/RECORD,,
File without changes