maapy 0.1.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.
- maapy/__init__.py +93 -0
- maapy/_callback/__init__.py +9 -0
- maapy/_callback/common.py +47 -0
- maapy/_callback/global_taskchain.py +282 -0
- maapy/_callback/parser.py +851 -0
- maapy/_callback/payloads.py +392 -0
- maapy/_callback/subtask.py +70 -0
- maapy/_callback/subtask_roguelike.py +164 -0
- maapy/_callback/subtask_structured.py +491 -0
- maapy/_ffi.py +129 -0
- maapy/_json.py +38 -0
- maapy/_loader.py +77 -0
- maapy/_lowlevel.py +238 -0
- maapy/callback.py +314 -0
- maapy/client.py +843 -0
- maapy/connection.py +50 -0
- maapy/constants.py +325 -0
- maapy/events/__init__.py +295 -0
- maapy/events/_base.py +26 -0
- maapy/events/global_events.py +195 -0
- maapy/events/rules.py +380 -0
- maapy/events/subtask_events.py +654 -0
- maapy/events/taskchain_events.py +40 -0
- maapy/exceptions.py +38 -0
- maapy/game_data.py +119 -0
- maapy/instance.py +274 -0
- maapy/py.typed +0 -0
- maapy/tasks/__init__.py +55 -0
- maapy/tasks/_base.py +130 -0
- maapy/tasks/award.py +20 -0
- maapy/tasks/closedown.py +21 -0
- maapy/tasks/copilot.py +106 -0
- maapy/tasks/custom.py +110 -0
- maapy/tasks/debug.py +14 -0
- maapy/tasks/depot.py +14 -0
- maapy/tasks/fight.py +52 -0
- maapy/tasks/infrast.py +35 -0
- maapy/tasks/mall.py +23 -0
- maapy/tasks/operbox.py +14 -0
- maapy/tasks/reclamation.py +21 -0
- maapy/tasks/recruit.py +82 -0
- maapy/tasks/roguelike.py +58 -0
- maapy/tasks/startup.py +23 -0
- maapy/utils/__init__.py +1 -0
- maapy/utils/image.py +27 -0
- maapy-0.1.0.dist-info/METADATA +24 -0
- maapy-0.1.0.dist-info/RECORD +49 -0
- maapy-0.1.0.dist-info/WHEEL +4 -0
- maapy-0.1.0.dist-info/licenses/LICENSE +8 -0
maapy/__init__.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""maapy——基于 CFFI 的 MaaCore.dll Python 绑定。
|
|
2
|
+
|
|
3
|
+
使用方式:
|
|
4
|
+
from maapy import MaaClient
|
|
5
|
+
from maapy.tasks import FightTask, StartUpTask
|
|
6
|
+
from maapy.events import StageDropsEvent, ConnectionEvent
|
|
7
|
+
|
|
8
|
+
MaaClient.load(core_dir="F:/maa")
|
|
9
|
+
client = MaaClient()
|
|
10
|
+
client.connect("127.0.0.1:5555")
|
|
11
|
+
task = client.append(FightTask(stage="1-7", times=10), tag="farm")
|
|
12
|
+
client.start()
|
|
13
|
+
task.wait()
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from .client import MaaClient, TaskHandle, TaskResult, TaskStatus
|
|
17
|
+
from .connection import (
|
|
18
|
+
ConnectionExtras,
|
|
19
|
+
LDPlayerConnectionExtras,
|
|
20
|
+
MuMuConnectionExtras,
|
|
21
|
+
)
|
|
22
|
+
from .constants import (
|
|
23
|
+
AsstMsg,
|
|
24
|
+
AsstTaskType,
|
|
25
|
+
ClientType,
|
|
26
|
+
ConnectionWhat,
|
|
27
|
+
Facility,
|
|
28
|
+
InstanceOptionKey,
|
|
29
|
+
ReclamationTheme,
|
|
30
|
+
RoguelikeTheme,
|
|
31
|
+
Server,
|
|
32
|
+
StaticOptionKey,
|
|
33
|
+
SubTaskWhat,
|
|
34
|
+
Win32InputMethod,
|
|
35
|
+
Win32ScreencapMethod,
|
|
36
|
+
)
|
|
37
|
+
from .events import (
|
|
38
|
+
AllTasksCompletedEvent,
|
|
39
|
+
AsyncCallInfoEvent,
|
|
40
|
+
CallbackErrorEvent,
|
|
41
|
+
ConnectionEvent,
|
|
42
|
+
E,
|
|
43
|
+
AppendTask,
|
|
44
|
+
CancelAndAppend,
|
|
45
|
+
CancelTask,
|
|
46
|
+
Continue,
|
|
47
|
+
StageDropsEvent,
|
|
48
|
+
StopCore,
|
|
49
|
+
TaskChainCompletedEvent,
|
|
50
|
+
TaskChainErrorEvent,
|
|
51
|
+
TaskChainStartEvent,
|
|
52
|
+
UpdateParams,
|
|
53
|
+
)
|
|
54
|
+
from .exceptions import (
|
|
55
|
+
MaaCallbackError,
|
|
56
|
+
MaaConnectionError,
|
|
57
|
+
MaaDataError,
|
|
58
|
+
MaaError,
|
|
59
|
+
MaaLoadError,
|
|
60
|
+
MaaTaskError,
|
|
61
|
+
MaaValidationError,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
__all__ = [
|
|
65
|
+
"MaaClient",
|
|
66
|
+
"TaskHandle",
|
|
67
|
+
"TaskResult",
|
|
68
|
+
"TaskStatus",
|
|
69
|
+
"ConnectionExtras",
|
|
70
|
+
"MuMuConnectionExtras",
|
|
71
|
+
"LDPlayerConnectionExtras",
|
|
72
|
+
"AsstMsg",
|
|
73
|
+
"AsstTaskType",
|
|
74
|
+
"StaticOptionKey",
|
|
75
|
+
"InstanceOptionKey",
|
|
76
|
+
"Win32ScreencapMethod",
|
|
77
|
+
"Win32InputMethod",
|
|
78
|
+
"MaaError",
|
|
79
|
+
"MaaLoadError",
|
|
80
|
+
"MaaConnectionError",
|
|
81
|
+
"MaaTaskError",
|
|
82
|
+
"MaaValidationError",
|
|
83
|
+
"MaaDataError",
|
|
84
|
+
"MaaCallbackError",
|
|
85
|
+
"CallbackErrorEvent",
|
|
86
|
+
"E",
|
|
87
|
+
"Continue",
|
|
88
|
+
"StopCore",
|
|
89
|
+
"CancelTask",
|
|
90
|
+
"AppendTask",
|
|
91
|
+
"CancelAndAppend",
|
|
92
|
+
"UpdateParams",
|
|
93
|
+
]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""回调解析共用的辅助函数和类型别名"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Callable, TypeAlias, TypedDict, TypeVar
|
|
6
|
+
|
|
7
|
+
import msgspec
|
|
8
|
+
|
|
9
|
+
from .._json import JsonDict, as_json_dict
|
|
10
|
+
from ..constants import AsstMsg
|
|
11
|
+
from ..events._base import Event
|
|
12
|
+
|
|
13
|
+
_MsgParser: TypeAlias = Callable[[AsstMsg, JsonDict], Event]
|
|
14
|
+
_EventFactory: TypeAlias = Callable[..., Event]
|
|
15
|
+
_SubTaskExtraParser: TypeAlias = Callable[..., Event]
|
|
16
|
+
_T = TypeVar("_T")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class _SubtaskEventKwargs(TypedDict):
|
|
20
|
+
msg: int
|
|
21
|
+
uuid: str
|
|
22
|
+
subtask: str
|
|
23
|
+
class_name: str
|
|
24
|
+
taskchain: str
|
|
25
|
+
taskid: int
|
|
26
|
+
what: str
|
|
27
|
+
why: str
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _decode_struct(value: object, model: type[_T], field_name: str) -> _T:
|
|
31
|
+
try:
|
|
32
|
+
data = as_json_dict(value)
|
|
33
|
+
except msgspec.ValidationError as exc:
|
|
34
|
+
raise msgspec.ValidationError(f"{field_name}: {exc}") from exc
|
|
35
|
+
try:
|
|
36
|
+
return msgspec.convert(data, type=model)
|
|
37
|
+
except msgspec.ValidationError as exc:
|
|
38
|
+
raise msgspec.ValidationError(f"{field_name}: {exc}") from exc
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
__all__ = [
|
|
42
|
+
"_EventFactory",
|
|
43
|
+
"_MsgParser",
|
|
44
|
+
"_SubTaskExtraParser",
|
|
45
|
+
"_SubtaskEventKwargs",
|
|
46
|
+
"_decode_struct",
|
|
47
|
+
]
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
"""全局和任务链回调的解析逻辑"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import msgspec
|
|
6
|
+
|
|
7
|
+
from .._json import JsonDict
|
|
8
|
+
from ..constants import AsstMsg
|
|
9
|
+
from ..events._base import Event
|
|
10
|
+
from ..events.global_events import (
|
|
11
|
+
AllTasksCompletedEvent,
|
|
12
|
+
AsyncCallInfoEvent,
|
|
13
|
+
AttachWindowAsyncCallInfoEvent,
|
|
14
|
+
CallbackErrorEvent,
|
|
15
|
+
ClickAsyncCallInfoEvent,
|
|
16
|
+
ConnectAsyncCallInfoEvent,
|
|
17
|
+
ConnectFailedConnectionEvent,
|
|
18
|
+
ConnectedConnectionEvent,
|
|
19
|
+
ConnectionEvent,
|
|
20
|
+
DestroyedEvent,
|
|
21
|
+
DisconnectConnectionEvent,
|
|
22
|
+
FastestWayToScreencapConnectionEvent,
|
|
23
|
+
InitFailedEvent,
|
|
24
|
+
InternalErrorEvent,
|
|
25
|
+
ReconnectedConnectionEvent,
|
|
26
|
+
ReconnectingConnectionEvent,
|
|
27
|
+
ReportRequestEvent,
|
|
28
|
+
ResolutionErrorConnectionEvent,
|
|
29
|
+
ResolutionGotConnectionEvent,
|
|
30
|
+
ResolutionInfoConnectionEvent,
|
|
31
|
+
ScreencapAsyncCallInfoEvent,
|
|
32
|
+
ScreencapCostConnectionEvent,
|
|
33
|
+
ScreencapFailedConnectionEvent,
|
|
34
|
+
ScreencapMethodAlternative,
|
|
35
|
+
TouchModeNotAvailableConnectionEvent,
|
|
36
|
+
UnknownAsyncCallInfoEvent,
|
|
37
|
+
UnsupportedPlayToolsConnectionEvent,
|
|
38
|
+
UnsupportedResolutionConnectionEvent,
|
|
39
|
+
UuidGotConnectionEvent,
|
|
40
|
+
)
|
|
41
|
+
from ..events.taskchain_events import RoutingRestartTaskChainEvent, TaskChainExtraInfoEvent
|
|
42
|
+
from .common import _EventFactory, _MsgParser, _decode_struct
|
|
43
|
+
from .payloads import (
|
|
44
|
+
AllTasksCompletedPayload,
|
|
45
|
+
AsyncCallInfoPayload,
|
|
46
|
+
ConnectionInfoPayload,
|
|
47
|
+
InitFailedPayload,
|
|
48
|
+
ReportRequestPayload,
|
|
49
|
+
ScreencapAlternativePayload,
|
|
50
|
+
TaskChainPayload,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class GlobalTaskchainParsingMixin:
|
|
55
|
+
"""集中处理全局事件和任务链事件的 JSON 解析"""
|
|
56
|
+
|
|
57
|
+
_msg_dispatch: dict[AsstMsg, _MsgParser]
|
|
58
|
+
_taskchain_event_classes: dict[AsstMsg, _EventFactory]
|
|
59
|
+
|
|
60
|
+
def _parse_and_route(self, msg: int, data: JsonDict) -> Event | None:
|
|
61
|
+
try:
|
|
62
|
+
msg_id = AsstMsg(msg)
|
|
63
|
+
except ValueError:
|
|
64
|
+
raise msgspec.ValidationError(f"unknown callback msg: {msg}") from None
|
|
65
|
+
parser = self._msg_dispatch.get(msg_id)
|
|
66
|
+
if parser is not None:
|
|
67
|
+
return parser(msg_id, data)
|
|
68
|
+
raise msgspec.ValidationError(f"unhandled callback msg: {msg_id.name}") from None
|
|
69
|
+
|
|
70
|
+
def _callback_error(self, msg: int, source: str, exc: BaseException) -> CallbackErrorEvent:
|
|
71
|
+
return CallbackErrorEvent(
|
|
72
|
+
msg=msg,
|
|
73
|
+
uuid="",
|
|
74
|
+
source=source,
|
|
75
|
+
error=f"{type(exc).__name__}: {exc}",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
def _parse_internal_error(self, msg_id: AsstMsg, data: JsonDict) -> Event:
|
|
79
|
+
del data
|
|
80
|
+
return InternalErrorEvent(msg=int(msg_id), uuid="")
|
|
81
|
+
|
|
82
|
+
def _parse_init_failed(self, msg_id: AsstMsg, data: JsonDict) -> Event:
|
|
83
|
+
payload = _decode_struct(data, InitFailedPayload, "callback")
|
|
84
|
+
return InitFailedEvent(
|
|
85
|
+
msg=int(msg_id),
|
|
86
|
+
uuid="",
|
|
87
|
+
what=payload.what,
|
|
88
|
+
why=payload.why,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
def _parse_connection_info(self, msg_id: AsstMsg, data: JsonDict) -> Event:
|
|
92
|
+
payload = _decode_struct(data, ConnectionInfoPayload, "callback")
|
|
93
|
+
details = payload.details
|
|
94
|
+
what = payload.what
|
|
95
|
+
common_kwargs = {
|
|
96
|
+
"msg": int(msg_id),
|
|
97
|
+
"uuid": payload.uuid,
|
|
98
|
+
"what": what,
|
|
99
|
+
"why": payload.why,
|
|
100
|
+
"connected": what in ("Connected", "UuidGot"),
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if what == "ConnectFailed":
|
|
104
|
+
return ConnectFailedConnectionEvent(
|
|
105
|
+
**common_kwargs,
|
|
106
|
+
adb=details.adb,
|
|
107
|
+
address=details.address,
|
|
108
|
+
config=details.config,
|
|
109
|
+
adb_output=details.adb_output,
|
|
110
|
+
)
|
|
111
|
+
if what == "Connected":
|
|
112
|
+
return ConnectedConnectionEvent(
|
|
113
|
+
**common_kwargs,
|
|
114
|
+
adb=details.adb,
|
|
115
|
+
address=details.address,
|
|
116
|
+
config=details.config,
|
|
117
|
+
)
|
|
118
|
+
if what == "UuidGot":
|
|
119
|
+
return UuidGotConnectionEvent(
|
|
120
|
+
**common_kwargs,
|
|
121
|
+
adb=details.adb,
|
|
122
|
+
address=details.address,
|
|
123
|
+
config=details.config,
|
|
124
|
+
device_uuid=details.uuid,
|
|
125
|
+
)
|
|
126
|
+
if what == "UnsupportedResolution":
|
|
127
|
+
return UnsupportedResolutionConnectionEvent(
|
|
128
|
+
**common_kwargs,
|
|
129
|
+
width=details.width or payload.width,
|
|
130
|
+
height=details.height or payload.height,
|
|
131
|
+
)
|
|
132
|
+
if what == "ResolutionInfo":
|
|
133
|
+
return ResolutionInfoConnectionEvent(
|
|
134
|
+
**common_kwargs,
|
|
135
|
+
width=details.width or payload.width,
|
|
136
|
+
height=details.height or payload.height,
|
|
137
|
+
)
|
|
138
|
+
if what == "ResolutionGot":
|
|
139
|
+
return ResolutionGotConnectionEvent(
|
|
140
|
+
**common_kwargs,
|
|
141
|
+
adb=details.adb,
|
|
142
|
+
address=details.address,
|
|
143
|
+
config=details.config,
|
|
144
|
+
width=details.width or payload.width,
|
|
145
|
+
height=details.height or payload.height,
|
|
146
|
+
)
|
|
147
|
+
if what == "ResolutionError":
|
|
148
|
+
return ResolutionErrorConnectionEvent(
|
|
149
|
+
**common_kwargs,
|
|
150
|
+
adb=details.adb,
|
|
151
|
+
address=details.address,
|
|
152
|
+
config=details.config,
|
|
153
|
+
width=details.width or payload.width,
|
|
154
|
+
height=details.height or payload.height,
|
|
155
|
+
)
|
|
156
|
+
if what == "Reconnecting":
|
|
157
|
+
return ReconnectingConnectionEvent(
|
|
158
|
+
**common_kwargs,
|
|
159
|
+
reconnect=details.reconnect,
|
|
160
|
+
cmd=details.cmd,
|
|
161
|
+
times=details.times,
|
|
162
|
+
)
|
|
163
|
+
if what == "Reconnected":
|
|
164
|
+
return ReconnectedConnectionEvent(
|
|
165
|
+
**common_kwargs,
|
|
166
|
+
reconnect=details.reconnect,
|
|
167
|
+
cmd=details.cmd,
|
|
168
|
+
times=details.times,
|
|
169
|
+
)
|
|
170
|
+
if what == "Disconnect":
|
|
171
|
+
return DisconnectConnectionEvent(
|
|
172
|
+
**common_kwargs,
|
|
173
|
+
reconnect=details.reconnect,
|
|
174
|
+
cmd=details.cmd,
|
|
175
|
+
times=details.times,
|
|
176
|
+
)
|
|
177
|
+
if what == "ScreencapFailed":
|
|
178
|
+
return ScreencapFailedConnectionEvent(**common_kwargs)
|
|
179
|
+
if what == "TouchModeNotAvailable":
|
|
180
|
+
return TouchModeNotAvailableConnectionEvent(
|
|
181
|
+
**common_kwargs,
|
|
182
|
+
adb=details.adb,
|
|
183
|
+
address=details.address,
|
|
184
|
+
config=details.config,
|
|
185
|
+
)
|
|
186
|
+
if what == "FastestWayToScreencap":
|
|
187
|
+
return FastestWayToScreencapConnectionEvent(
|
|
188
|
+
**common_kwargs,
|
|
189
|
+
method=details.method,
|
|
190
|
+
cost=details.cost,
|
|
191
|
+
alternatives=[_screencap_alternative(item) for item in details.alternatives],
|
|
192
|
+
)
|
|
193
|
+
if what == "ScreencapCost":
|
|
194
|
+
return ScreencapCostConnectionEvent(
|
|
195
|
+
**common_kwargs,
|
|
196
|
+
min_cost=details.min_cost,
|
|
197
|
+
max_cost=details.max_cost,
|
|
198
|
+
avg_cost=details.avg_cost,
|
|
199
|
+
fault_times=details.fault_times,
|
|
200
|
+
)
|
|
201
|
+
if what == "UnsupportedPlayTools":
|
|
202
|
+
return UnsupportedPlayToolsConnectionEvent(**common_kwargs)
|
|
203
|
+
raise msgspec.ValidationError(f"unknown ConnectionInfo what: {what}") from None
|
|
204
|
+
|
|
205
|
+
def _parse_all_tasks_completed(self, msg_id: AsstMsg, data: JsonDict) -> Event:
|
|
206
|
+
payload = _decode_struct(data, AllTasksCompletedPayload, "callback")
|
|
207
|
+
return AllTasksCompletedEvent(
|
|
208
|
+
msg=int(msg_id),
|
|
209
|
+
uuid=payload.uuid,
|
|
210
|
+
taskchain=payload.taskchain,
|
|
211
|
+
finished_tasks=list(payload.finished_tasks),
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
def _parse_async_call_info(self, msg_id: AsstMsg, data: JsonDict) -> Event:
|
|
215
|
+
payload = _decode_struct(data, AsyncCallInfoPayload, "callback")
|
|
216
|
+
common_kwargs = {
|
|
217
|
+
"msg": int(msg_id),
|
|
218
|
+
"uuid": payload.uuid,
|
|
219
|
+
"what": payload.what,
|
|
220
|
+
"async_call_id": payload.async_call_id,
|
|
221
|
+
"ret": payload.details.ret,
|
|
222
|
+
"cost": payload.details.cost,
|
|
223
|
+
}
|
|
224
|
+
what = payload.what
|
|
225
|
+
if what == "Connect":
|
|
226
|
+
return ConnectAsyncCallInfoEvent(**common_kwargs)
|
|
227
|
+
if what == "AttachWindow":
|
|
228
|
+
return AttachWindowAsyncCallInfoEvent(**common_kwargs)
|
|
229
|
+
if what == "Click":
|
|
230
|
+
return ClickAsyncCallInfoEvent(**common_kwargs)
|
|
231
|
+
if what == "Screencap":
|
|
232
|
+
return ScreencapAsyncCallInfoEvent(**common_kwargs)
|
|
233
|
+
if what == "Unknown":
|
|
234
|
+
return UnknownAsyncCallInfoEvent(**common_kwargs)
|
|
235
|
+
raise msgspec.ValidationError(f"unknown AsyncCallInfo what: {what}") from None
|
|
236
|
+
|
|
237
|
+
def _parse_destroyed(self, msg_id: AsstMsg, data: JsonDict) -> Event:
|
|
238
|
+
payload = _decode_struct(data, TaskChainPayload, "callback")
|
|
239
|
+
return DestroyedEvent(msg=int(msg_id), uuid=payload.uuid)
|
|
240
|
+
|
|
241
|
+
def _parse_report_request(self, msg_id: AsstMsg, data: JsonDict) -> Event:
|
|
242
|
+
payload = _decode_struct(data, ReportRequestPayload, "callback")
|
|
243
|
+
return ReportRequestEvent(
|
|
244
|
+
msg=int(msg_id),
|
|
245
|
+
uuid=payload.uuid,
|
|
246
|
+
url=payload.url,
|
|
247
|
+
headers=dict(payload.headers),
|
|
248
|
+
body=payload.body,
|
|
249
|
+
subtask=payload.subtask,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
def _parse_taskchain(self, msg_id: AsstMsg, data: JsonDict) -> Event:
|
|
253
|
+
payload = _decode_struct(data, TaskChainPayload, "callback")
|
|
254
|
+
if msg_id == AsstMsg.TASK_CHAIN_EXTRA_INFO:
|
|
255
|
+
common_kwargs = {
|
|
256
|
+
"msg": int(msg_id),
|
|
257
|
+
"uuid": payload.uuid,
|
|
258
|
+
"taskchain": payload.taskchain,
|
|
259
|
+
"taskid": payload.taskid,
|
|
260
|
+
"what": payload.what,
|
|
261
|
+
"why": payload.why,
|
|
262
|
+
}
|
|
263
|
+
if payload.what == "RoutingRestart":
|
|
264
|
+
return RoutingRestartTaskChainEvent(
|
|
265
|
+
**common_kwargs,
|
|
266
|
+
node_cost=payload.node_cost,
|
|
267
|
+
)
|
|
268
|
+
return TaskChainExtraInfoEvent(**common_kwargs)
|
|
269
|
+
|
|
270
|
+
event_class = self._taskchain_event_classes.get(msg_id)
|
|
271
|
+
if event_class is None:
|
|
272
|
+
raise msgspec.ValidationError(f"unhandled taskchain msg: {msg_id.name}")
|
|
273
|
+
return event_class(
|
|
274
|
+
msg=int(msg_id),
|
|
275
|
+
uuid=payload.uuid,
|
|
276
|
+
taskchain=payload.taskchain,
|
|
277
|
+
taskid=payload.taskid,
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def _screencap_alternative(item: ScreencapAlternativePayload) -> ScreencapMethodAlternative:
|
|
282
|
+
return ScreencapMethodAlternative(method=item.method, cost=item.cost)
|