satori-python-adapter-milky 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.
- .mina/adapter_milky.toml +29 -0
- satori/adapters/milky/__init__.py +4 -0
- satori/adapters/milky/api.py +311 -0
- satori/adapters/milky/events/__init__.py +7 -0
- satori/adapters/milky/events/base.py +19 -0
- satori/adapters/milky/events/group.py +74 -0
- satori/adapters/milky/events/message.py +80 -0
- satori/adapters/milky/events/request.py +92 -0
- satori/adapters/milky/main.py +247 -0
- satori/adapters/milky/message.py +233 -0
- satori/adapters/milky/utils.py +77 -0
- satori/adapters/milky/webhook.py +230 -0
- satori_python_adapter_milky-0.1.0.dist-info/METADATA +151 -0
- satori_python_adapter_milky-0.1.0.dist-info/RECORD +16 -0
- satori_python_adapter_milky-0.1.0.dist-info/WHEEL +4 -0
- satori_python_adapter_milky-0.1.0.dist-info/licenses/LICENSE +21 -0
.mina/adapter_milky.toml
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
includes = ["src/satori/adapters/milky"]
|
|
2
|
+
raw-dependencies = ["satori-python-server >= 0.17.2"]
|
|
3
|
+
|
|
4
|
+
[project]
|
|
5
|
+
name = "satori-python-adapter-milky"
|
|
6
|
+
version = "0.1.0"
|
|
7
|
+
authors = [
|
|
8
|
+
{name = "RF-Tar-Railt", email = "rf_tar_railt@qq.com"}
|
|
9
|
+
]
|
|
10
|
+
dependencies = []
|
|
11
|
+
description = "Satori Protocol SDK for python, adapter for Milky"
|
|
12
|
+
license = {text = "MIT"}
|
|
13
|
+
readme = "README.md"
|
|
14
|
+
requires-python = ">=3.10,<4.0"
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Typing :: Typed",
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3.8",
|
|
20
|
+
"Programming Language :: Python :: 3.9",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Operating System :: OS Independent",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
homepage = "https://github.com/RF-Tar-Railt/satori-python"
|
|
29
|
+
repository = "https://github.com/RF-Tar-Railt/satori-python"
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
|
|
5
|
+
from satori import Api
|
|
6
|
+
from satori.model import Channel, ChannelType, Login, PageDequeResult, PageResult
|
|
7
|
+
from satori.server import Adapter, Request
|
|
8
|
+
from satori.server.route import (
|
|
9
|
+
ApproveParam,
|
|
10
|
+
ChannelListParam,
|
|
11
|
+
ChannelMuteParam,
|
|
12
|
+
ChannelParam,
|
|
13
|
+
ChannelUpdateParam,
|
|
14
|
+
FriendListParam,
|
|
15
|
+
GuildGetParam,
|
|
16
|
+
GuildListParam,
|
|
17
|
+
GuildMemberGetParam,
|
|
18
|
+
GuildMemberKickParam,
|
|
19
|
+
GuildMemberMuteParam,
|
|
20
|
+
GuildXXXListParam,
|
|
21
|
+
MessageListParam,
|
|
22
|
+
MessageOpParam,
|
|
23
|
+
MessageParam,
|
|
24
|
+
ReactionCreateParam,
|
|
25
|
+
ReactionDeleteParam,
|
|
26
|
+
UserChannelCreateParam,
|
|
27
|
+
UserGetParam,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
from .message import MilkyMessageEncoder, decode_message
|
|
31
|
+
from .utils import (
|
|
32
|
+
MilkyNetwork,
|
|
33
|
+
decode_friend,
|
|
34
|
+
decode_group_channel,
|
|
35
|
+
decode_guild,
|
|
36
|
+
decode_member,
|
|
37
|
+
decode_private_channel,
|
|
38
|
+
decode_user_profile,
|
|
39
|
+
get_scene_and_peer,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def apply(
|
|
44
|
+
adapter: Adapter,
|
|
45
|
+
net_getter: Callable[[str], MilkyNetwork],
|
|
46
|
+
login_getter: Callable[[str], Login],
|
|
47
|
+
):
|
|
48
|
+
@adapter.route(Api.LOGIN_GET)
|
|
49
|
+
async def login_get(request: Request):
|
|
50
|
+
return login_getter(request.self_id)
|
|
51
|
+
|
|
52
|
+
@adapter.route(Api.MESSAGE_CREATE)
|
|
53
|
+
async def message_create(request: Request[MessageParam]):
|
|
54
|
+
net = net_getter(request.self_id)
|
|
55
|
+
login = login_getter(request.self_id)
|
|
56
|
+
encoder = MilkyMessageEncoder(login, net, request.params["channel_id"])
|
|
57
|
+
return await encoder.send(request.params["content"])
|
|
58
|
+
|
|
59
|
+
@adapter.route(Api.MESSAGE_GET)
|
|
60
|
+
async def message_get(request: Request[MessageOpParam]):
|
|
61
|
+
net = net_getter(request.self_id)
|
|
62
|
+
scene, peer_id = get_scene_and_peer(request.params["channel_id"])
|
|
63
|
+
result = await net.call_api(
|
|
64
|
+
"get_message",
|
|
65
|
+
{
|
|
66
|
+
"message_scene": scene,
|
|
67
|
+
"peer_id": peer_id,
|
|
68
|
+
"message_seq": int(request.params["message_id"]),
|
|
69
|
+
},
|
|
70
|
+
)
|
|
71
|
+
if not result or "message" not in result:
|
|
72
|
+
raise RuntimeError("Failed to get message")
|
|
73
|
+
return await decode_message(net, result["message"])
|
|
74
|
+
|
|
75
|
+
@adapter.route(Api.MESSAGE_DELETE)
|
|
76
|
+
async def message_delete(request: Request[MessageOpParam]):
|
|
77
|
+
net = net_getter(request.self_id)
|
|
78
|
+
scene, peer_id = get_scene_and_peer(request.params["channel_id"])
|
|
79
|
+
message_seq = int(request.params["message_id"])
|
|
80
|
+
if scene == "group":
|
|
81
|
+
await net.call_api("recall_group_message", {"group_id": peer_id, "message_seq": message_seq})
|
|
82
|
+
else:
|
|
83
|
+
await net.call_api("recall_private_message", {"user_id": peer_id, "message_seq": message_seq})
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
@adapter.route(Api.MESSAGE_LIST)
|
|
87
|
+
async def message_list(request: Request[MessageListParam]):
|
|
88
|
+
net = net_getter(request.self_id)
|
|
89
|
+
params = request.params
|
|
90
|
+
direction = params.get("direction", "before")
|
|
91
|
+
if direction != "before":
|
|
92
|
+
raise RuntimeError("Milky adapter only supports direction='before'")
|
|
93
|
+
scene, peer_id = get_scene_and_peer(params["channel_id"])
|
|
94
|
+
result = await net.call_api(
|
|
95
|
+
"get_history_messages",
|
|
96
|
+
{
|
|
97
|
+
"message_scene": scene,
|
|
98
|
+
"peer_id": peer_id,
|
|
99
|
+
"start_message_seq": int(params["next"]) if params.get("next") else None, # type: ignore
|
|
100
|
+
"limit": params.get("limit"),
|
|
101
|
+
},
|
|
102
|
+
)
|
|
103
|
+
if not result:
|
|
104
|
+
return PageDequeResult([])
|
|
105
|
+
messages = [await decode_message(net, item) for item in result.get("messages", [])]
|
|
106
|
+
next_seq = result.get("next_message_seq")
|
|
107
|
+
return PageDequeResult(messages, str(next_seq) if next_seq is not None else None)
|
|
108
|
+
|
|
109
|
+
@adapter.route(Api.CHANNEL_GET)
|
|
110
|
+
async def channel_get(request: Request[ChannelParam]):
|
|
111
|
+
net = net_getter(request.self_id)
|
|
112
|
+
channel_id = request.params["channel_id"]
|
|
113
|
+
scene, peer_id = get_scene_and_peer(channel_id)
|
|
114
|
+
if scene == "group":
|
|
115
|
+
result = await net.call_api("get_group_info", {"group_id": peer_id})
|
|
116
|
+
if not result:
|
|
117
|
+
raise RuntimeError("Failed to get group info")
|
|
118
|
+
return decode_group_channel(result["group"])
|
|
119
|
+
profile = await net.call_api("get_user_profile", {"user_id": peer_id})
|
|
120
|
+
if not profile:
|
|
121
|
+
raise RuntimeError("Failed to get user profile")
|
|
122
|
+
return decode_private_channel(profile, channel_id)
|
|
123
|
+
|
|
124
|
+
@adapter.route(Api.CHANNEL_LIST)
|
|
125
|
+
async def channel_list(request: Request[ChannelListParam]):
|
|
126
|
+
net = net_getter(request.self_id)
|
|
127
|
+
guild_id = int(request.params["guild_id"])
|
|
128
|
+
result = await net.call_api("get_group_info", {"group_id": guild_id})
|
|
129
|
+
if not result:
|
|
130
|
+
raise RuntimeError("Failed to get group info")
|
|
131
|
+
channel = decode_group_channel(result["group"])
|
|
132
|
+
return PageResult([channel])
|
|
133
|
+
|
|
134
|
+
@adapter.route(Api.USER_CHANNEL_CREATE)
|
|
135
|
+
async def user_channel_create(request: Request[UserChannelCreateParam]):
|
|
136
|
+
return Channel(f"private:{request.params['user_id']}", ChannelType.DIRECT)
|
|
137
|
+
|
|
138
|
+
@adapter.route(Api.CHANNEL_UPDATE)
|
|
139
|
+
async def channel_update(request: Request[ChannelUpdateParam]):
|
|
140
|
+
net = net_getter(request.self_id)
|
|
141
|
+
data = request.params["data"]
|
|
142
|
+
channel_id = request.params["channel_id"]
|
|
143
|
+
scene, peer_id = get_scene_and_peer(channel_id)
|
|
144
|
+
if scene != "group":
|
|
145
|
+
raise RuntimeError("Only group channels support update")
|
|
146
|
+
if "name" in data:
|
|
147
|
+
await net.call_api("set_group_name", {"group_id": peer_id, "new_group_name": data["name"]})
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
@adapter.route(Api.CHANNEL_MUTE)
|
|
151
|
+
async def channel_mute(request: Request[ChannelMuteParam]):
|
|
152
|
+
net = net_getter(request.self_id)
|
|
153
|
+
scene, peer_id = get_scene_and_peer(request.params["channel_id"])
|
|
154
|
+
if scene != "group":
|
|
155
|
+
raise RuntimeError("Only group channels support mute")
|
|
156
|
+
await net.call_api(
|
|
157
|
+
"set_group_whole_mute",
|
|
158
|
+
{"group_id": peer_id, "is_mute": request.params["duration"] > 0},
|
|
159
|
+
)
|
|
160
|
+
return
|
|
161
|
+
|
|
162
|
+
@adapter.route(Api.GUILD_GET)
|
|
163
|
+
async def guild_get(request: Request[GuildGetParam]):
|
|
164
|
+
net = net_getter(request.self_id)
|
|
165
|
+
guild_id = int(request.params["guild_id"])
|
|
166
|
+
result = await net.call_api("get_group_info", {"group_id": guild_id})
|
|
167
|
+
if not result:
|
|
168
|
+
raise RuntimeError("Failed to get group info")
|
|
169
|
+
return decode_guild(result["group"])
|
|
170
|
+
|
|
171
|
+
@adapter.route(Api.GUILD_LIST)
|
|
172
|
+
async def guild_list(request: Request[GuildListParam]):
|
|
173
|
+
net = net_getter(request.self_id)
|
|
174
|
+
result = await net.call_api("get_group_list", {})
|
|
175
|
+
groups = [decode_guild(item) for item in result.get("groups", [])] if result else []
|
|
176
|
+
return PageResult(groups)
|
|
177
|
+
|
|
178
|
+
@adapter.route(Api.GUILD_MEMBER_GET)
|
|
179
|
+
async def guild_member_get(request: Request[GuildMemberGetParam]):
|
|
180
|
+
net = net_getter(request.self_id)
|
|
181
|
+
result = await net.call_api(
|
|
182
|
+
"get_group_member_info",
|
|
183
|
+
{"group_id": int(request.params["guild_id"]), "user_id": int(request.params["user_id"])},
|
|
184
|
+
)
|
|
185
|
+
if not result:
|
|
186
|
+
raise RuntimeError("Failed to get group member")
|
|
187
|
+
return decode_member(result["member"])
|
|
188
|
+
|
|
189
|
+
@adapter.route(Api.GUILD_MEMBER_LIST)
|
|
190
|
+
async def guild_member_list(request: Request[GuildXXXListParam]):
|
|
191
|
+
net = net_getter(request.self_id)
|
|
192
|
+
result = await net.call_api("get_group_member_list", {"group_id": int(request.params["guild_id"])})
|
|
193
|
+
members = [decode_member(item) for item in result.get("members", [])] if result else []
|
|
194
|
+
return PageResult(members)
|
|
195
|
+
|
|
196
|
+
@adapter.route(Api.GUILD_MEMBER_KICK)
|
|
197
|
+
async def guild_member_kick(request: Request[GuildMemberKickParam]):
|
|
198
|
+
net = net_getter(request.self_id)
|
|
199
|
+
await net.call_api(
|
|
200
|
+
"kick_group_member",
|
|
201
|
+
{
|
|
202
|
+
"group_id": int(request.params["guild_id"]),
|
|
203
|
+
"user_id": int(request.params["user_id"]),
|
|
204
|
+
"reject_add_request": request.params.get("permanent", False),
|
|
205
|
+
},
|
|
206
|
+
)
|
|
207
|
+
return
|
|
208
|
+
|
|
209
|
+
@adapter.route(Api.GUILD_MEMBER_MUTE)
|
|
210
|
+
async def guild_member_mute(request: Request[GuildMemberMuteParam]):
|
|
211
|
+
net = net_getter(request.self_id)
|
|
212
|
+
await net.call_api(
|
|
213
|
+
"set_group_member_mute",
|
|
214
|
+
{
|
|
215
|
+
"group_id": int(request.params["guild_id"]),
|
|
216
|
+
"user_id": int(request.params["user_id"]),
|
|
217
|
+
"duration": int(request.params["duration"]),
|
|
218
|
+
},
|
|
219
|
+
)
|
|
220
|
+
return
|
|
221
|
+
|
|
222
|
+
@adapter.route(Api.GUILD_MEMBER_APPROVE)
|
|
223
|
+
async def guild_member_approve(request: Request[ApproveParam]):
|
|
224
|
+
net = net_getter(request.self_id)
|
|
225
|
+
message_id = request.params["message_id"]
|
|
226
|
+
notification_seq, notification_type, group_id, is_filtered = message_id.split("|")
|
|
227
|
+
params = {
|
|
228
|
+
"notification_seq": int(notification_seq),
|
|
229
|
+
"notification_type": notification_type,
|
|
230
|
+
"group_id": int(group_id),
|
|
231
|
+
"is_filtered": bool(int(is_filtered)),
|
|
232
|
+
}
|
|
233
|
+
if request.params["approve"]:
|
|
234
|
+
await net.call_api("accept_group_request", params)
|
|
235
|
+
else:
|
|
236
|
+
params["reason"] = request.params.get("comment")
|
|
237
|
+
await net.call_api("reject_group_request", params)
|
|
238
|
+
return
|
|
239
|
+
|
|
240
|
+
@adapter.route(Api.GUILD_APPROVE)
|
|
241
|
+
async def guild_approve(request: Request[ApproveParam]):
|
|
242
|
+
net = net_getter(request.self_id)
|
|
243
|
+
group_id, invitation_seq = request.params["message_id"].split("|")
|
|
244
|
+
payload = {"group_id": int(group_id), "invitation_seq": int(invitation_seq)}
|
|
245
|
+
if request.params["approve"]:
|
|
246
|
+
await net.call_api("accept_group_invitation", payload)
|
|
247
|
+
else:
|
|
248
|
+
await net.call_api("reject_group_invitation", payload)
|
|
249
|
+
return
|
|
250
|
+
|
|
251
|
+
@adapter.route(Api.REACTION_CREATE)
|
|
252
|
+
async def reaction_create(request: Request[ReactionCreateParam]):
|
|
253
|
+
net = net_getter(request.self_id)
|
|
254
|
+
scene, peer_id = get_scene_and_peer(request.params["channel_id"])
|
|
255
|
+
if scene != "group":
|
|
256
|
+
raise RuntimeError("Reactions only supported in group channels")
|
|
257
|
+
await net.call_api(
|
|
258
|
+
"send_group_message_reaction",
|
|
259
|
+
{
|
|
260
|
+
"group_id": peer_id,
|
|
261
|
+
"message_seq": int(request.params["message_id"]),
|
|
262
|
+
"reaction": request.params["emoji"],
|
|
263
|
+
"is_add": True,
|
|
264
|
+
},
|
|
265
|
+
)
|
|
266
|
+
return
|
|
267
|
+
|
|
268
|
+
@adapter.route(Api.REACTION_DELETE)
|
|
269
|
+
async def reaction_delete(request: Request[ReactionDeleteParam]):
|
|
270
|
+
net = net_getter(request.self_id)
|
|
271
|
+
scene, peer_id = get_scene_and_peer(request.params["channel_id"])
|
|
272
|
+
if scene != "group":
|
|
273
|
+
raise RuntimeError("Reactions only supported in group channels")
|
|
274
|
+
await net.call_api(
|
|
275
|
+
"send_group_message_reaction",
|
|
276
|
+
{
|
|
277
|
+
"group_id": peer_id,
|
|
278
|
+
"message_seq": int(request.params["message_id"]),
|
|
279
|
+
"reaction": request.params["emoji"],
|
|
280
|
+
"is_add": False,
|
|
281
|
+
},
|
|
282
|
+
)
|
|
283
|
+
return
|
|
284
|
+
|
|
285
|
+
@adapter.route(Api.USER_GET)
|
|
286
|
+
async def user_get(request: Request[UserGetParam]):
|
|
287
|
+
net = net_getter(request.self_id)
|
|
288
|
+
user_id = request.params["user_id"]
|
|
289
|
+
profile = await net.call_api("get_user_profile", {"user_id": int(user_id)})
|
|
290
|
+
if not profile:
|
|
291
|
+
raise RuntimeError("Failed to get user profile")
|
|
292
|
+
return decode_user_profile(profile, user_id)
|
|
293
|
+
|
|
294
|
+
@adapter.route(Api.FRIEND_LIST)
|
|
295
|
+
async def friend_list(request: Request[FriendListParam]):
|
|
296
|
+
net = net_getter(request.self_id)
|
|
297
|
+
result = await net.call_api("get_friend_list", {})
|
|
298
|
+
friends = [decode_friend(item) for item in result.get("friends", [])] if result else []
|
|
299
|
+
return PageResult(friends)
|
|
300
|
+
|
|
301
|
+
@adapter.route(Api.FRIEND_APPROVE)
|
|
302
|
+
async def friend_approve(request: Request[ApproveParam]):
|
|
303
|
+
net = net_getter(request.self_id)
|
|
304
|
+
initiator_uid, is_filtered = request.params["message_id"].split("|")
|
|
305
|
+
payload = {"initiator_uid": initiator_uid, "is_filtered": bool(int(is_filtered))}
|
|
306
|
+
if request.params["approve"]:
|
|
307
|
+
await net.call_api("accept_friend_request", payload)
|
|
308
|
+
else:
|
|
309
|
+
payload["reason"] = request.params.get("comment")
|
|
310
|
+
await net.call_api("reject_friend_request", payload)
|
|
311
|
+
return
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# import event handlers to register them
|
|
2
|
+
from . import group as group # noqa: F401
|
|
3
|
+
from . import message as message # noqa: F401
|
|
4
|
+
from . import request as request # noqa: F401
|
|
5
|
+
from .base import event_handlers, register_event
|
|
6
|
+
|
|
7
|
+
__all__ = ["event_handlers", "register_event"]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Awaitable, Callable
|
|
4
|
+
|
|
5
|
+
from satori.model import Event, Login
|
|
6
|
+
|
|
7
|
+
from ..utils import MilkyNetwork
|
|
8
|
+
|
|
9
|
+
EventHandler = Callable[[Login, MilkyNetwork, dict], Awaitable[Event | None]]
|
|
10
|
+
|
|
11
|
+
event_handlers: dict[str, EventHandler] = {}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def register_event(event_type: str):
|
|
15
|
+
def decorator(func: EventHandler):
|
|
16
|
+
event_handlers[event_type] = func
|
|
17
|
+
return func
|
|
18
|
+
|
|
19
|
+
return decorator
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
|
|
5
|
+
from satori import EventType
|
|
6
|
+
from satori.model import Channel, ChannelType, Event, Guild, Member, User
|
|
7
|
+
|
|
8
|
+
from ..utils import group_avatar, user_avatar
|
|
9
|
+
from .base import register_event
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@register_event("group_member_increase")
|
|
13
|
+
async def group_member_increase(login, net, raw):
|
|
14
|
+
data = raw["data"]
|
|
15
|
+
guild_id = str(data["group_id"])
|
|
16
|
+
guild = Guild(guild_id, avatar=group_avatar(guild_id))
|
|
17
|
+
channel = Channel(guild_id, ChannelType.TEXT)
|
|
18
|
+
user = User(str(data["user_id"]), avatar=user_avatar(data["user_id"]))
|
|
19
|
+
member = Member(user, avatar=user.avatar)
|
|
20
|
+
operator = None
|
|
21
|
+
if data.get("operator_id"):
|
|
22
|
+
operator = User(str(data["operator_id"]), avatar=user_avatar(data["operator_id"]))
|
|
23
|
+
return Event(
|
|
24
|
+
EventType.GUILD_MEMBER_ADDED,
|
|
25
|
+
datetime.fromtimestamp(raw["time"]),
|
|
26
|
+
login,
|
|
27
|
+
guild=guild,
|
|
28
|
+
channel=channel,
|
|
29
|
+
user=user,
|
|
30
|
+
member=member,
|
|
31
|
+
operator=operator,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@register_event("group_member_decrease")
|
|
36
|
+
async def group_member_decrease(login, net, raw):
|
|
37
|
+
data = raw["data"]
|
|
38
|
+
guild_id = str(data["group_id"])
|
|
39
|
+
guild = Guild(guild_id, avatar=group_avatar(guild_id))
|
|
40
|
+
channel = Channel(guild_id, ChannelType.TEXT)
|
|
41
|
+
user = User(str(data["user_id"]), avatar=user_avatar(data["user_id"]))
|
|
42
|
+
member = Member(user, avatar=user.avatar)
|
|
43
|
+
operator = None
|
|
44
|
+
if data.get("operator_id"):
|
|
45
|
+
operator = User(str(data["operator_id"]), avatar=user_avatar(data["operator_id"]))
|
|
46
|
+
return Event(
|
|
47
|
+
EventType.GUILD_MEMBER_REMOVED,
|
|
48
|
+
datetime.fromtimestamp(raw["time"]),
|
|
49
|
+
login,
|
|
50
|
+
guild=guild,
|
|
51
|
+
channel=channel,
|
|
52
|
+
user=user,
|
|
53
|
+
member=member,
|
|
54
|
+
operator=operator,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@register_event("group_name_change")
|
|
59
|
+
async def group_name_change(login, net, raw):
|
|
60
|
+
data = raw["data"]
|
|
61
|
+
guild_id = str(data["group_id"])
|
|
62
|
+
guild = Guild(guild_id, name=data.get("new_group_name"), avatar=group_avatar(guild_id))
|
|
63
|
+
channel = Channel(guild_id, ChannelType.TEXT, name=data.get("new_group_name"))
|
|
64
|
+
operator = None
|
|
65
|
+
if data.get("operator_id"):
|
|
66
|
+
operator = User(str(data["operator_id"]), avatar=user_avatar(data["operator_id"]))
|
|
67
|
+
return Event(
|
|
68
|
+
EventType.GUILD_UPDATED,
|
|
69
|
+
datetime.fromtimestamp(raw["time"]),
|
|
70
|
+
login,
|
|
71
|
+
guild=guild,
|
|
72
|
+
channel=channel,
|
|
73
|
+
operator=operator,
|
|
74
|
+
)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
|
|
5
|
+
from satori import EventType
|
|
6
|
+
from satori.model import Channel, ChannelType, Event, Guild, MessageObject, User
|
|
7
|
+
|
|
8
|
+
from ..message import decode_message
|
|
9
|
+
from ..utils import group_avatar, user_avatar
|
|
10
|
+
from .base import register_event
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@register_event("message_receive")
|
|
14
|
+
async def message_receive(login, net, raw):
|
|
15
|
+
message = await decode_message(net, raw["data"])
|
|
16
|
+
return Event(
|
|
17
|
+
EventType.MESSAGE_CREATED,
|
|
18
|
+
datetime.fromtimestamp(raw["time"]),
|
|
19
|
+
login,
|
|
20
|
+
channel=message.channel,
|
|
21
|
+
guild=message.guild,
|
|
22
|
+
member=message.member,
|
|
23
|
+
user=message.user,
|
|
24
|
+
message=message,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@register_event("message_recall")
|
|
29
|
+
async def message_recall(login, net, raw):
|
|
30
|
+
data = raw["data"]
|
|
31
|
+
scene = data["message_scene"]
|
|
32
|
+
peer_id = str(data["peer_id"])
|
|
33
|
+
if scene == "group":
|
|
34
|
+
channel = Channel(peer_id, ChannelType.TEXT)
|
|
35
|
+
guild = Guild(peer_id, avatar=group_avatar(peer_id))
|
|
36
|
+
elif scene == "temp":
|
|
37
|
+
channel = Channel(f"private:temp_{peer_id}", ChannelType.DIRECT)
|
|
38
|
+
guild = None
|
|
39
|
+
else:
|
|
40
|
+
channel = Channel(f"private:{peer_id}", ChannelType.DIRECT)
|
|
41
|
+
guild = None
|
|
42
|
+
user = User(str(data["sender_id"]), avatar=user_avatar(data["sender_id"]))
|
|
43
|
+
operator = User(str(data["operator_id"]), avatar=user_avatar(data["operator_id"]))
|
|
44
|
+
message = MessageObject(str(data["message_seq"]), "", channel=channel, guild=guild, user=user)
|
|
45
|
+
return Event(
|
|
46
|
+
EventType.MESSAGE_DELETED,
|
|
47
|
+
datetime.fromtimestamp(raw["time"]),
|
|
48
|
+
login,
|
|
49
|
+
channel=channel,
|
|
50
|
+
guild=guild,
|
|
51
|
+
user=user,
|
|
52
|
+
operator=operator,
|
|
53
|
+
message=message,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@register_event("group_message_reaction")
|
|
58
|
+
async def group_message_reaction(login, net, raw):
|
|
59
|
+
data = raw["data"]
|
|
60
|
+
guild_id = str(data["group_id"])
|
|
61
|
+
guild = Guild(guild_id, avatar=group_avatar(guild_id))
|
|
62
|
+
channel = Channel(guild_id, ChannelType.TEXT)
|
|
63
|
+
user = User(str(data["user_id"]), avatar=user_avatar(data["user_id"]))
|
|
64
|
+
face_id = data["face_id"]
|
|
65
|
+
message = MessageObject(
|
|
66
|
+
str(data["message_seq"]), f"<milky:face id='{face_id}'>", channel=channel, guild=guild, user=user
|
|
67
|
+
)
|
|
68
|
+
if data["is_add"]:
|
|
69
|
+
event_type = EventType.REACTION_ADDED
|
|
70
|
+
else:
|
|
71
|
+
event_type = EventType.REACTION_REMOVED
|
|
72
|
+
return Event(
|
|
73
|
+
event_type,
|
|
74
|
+
datetime.fromtimestamp(raw["time"]),
|
|
75
|
+
login,
|
|
76
|
+
channel=channel,
|
|
77
|
+
guild=guild,
|
|
78
|
+
user=user,
|
|
79
|
+
message=message,
|
|
80
|
+
)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
|
|
5
|
+
from satori import EventType
|
|
6
|
+
from satori.model import Channel, ChannelType, Event, Guild, Member, MessageObject, User
|
|
7
|
+
|
|
8
|
+
from ..utils import group_avatar, user_avatar
|
|
9
|
+
from .base import register_event
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@register_event("friend_request")
|
|
13
|
+
async def friend_request(login, net, raw):
|
|
14
|
+
data = raw["data"]
|
|
15
|
+
user = User(str(data["initiator_id"]), avatar=user_avatar(data["initiator_id"]))
|
|
16
|
+
channel = Channel(f"private:{user.id}", ChannelType.DIRECT)
|
|
17
|
+
message_id = f"{data['initiator_uid']}|{1 if data.get('is_filtered') else 0}"
|
|
18
|
+
message = MessageObject(message_id, data.get("comment", ""))
|
|
19
|
+
return Event(
|
|
20
|
+
EventType.FRIEND_REQUEST,
|
|
21
|
+
datetime.fromtimestamp(raw["time"]),
|
|
22
|
+
login,
|
|
23
|
+
user=user,
|
|
24
|
+
channel=channel,
|
|
25
|
+
message=message,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@register_event("group_join_request")
|
|
30
|
+
async def group_join_request(login, net, raw):
|
|
31
|
+
data = raw["data"]
|
|
32
|
+
guild_id = str(data["group_id"])
|
|
33
|
+
guild = Guild(guild_id, avatar=group_avatar(guild_id))
|
|
34
|
+
channel = Channel(guild_id)
|
|
35
|
+
user = User(str(data["initiator_id"]), avatar=user_avatar(data["initiator_id"]))
|
|
36
|
+
member = Member(user, avatar=user_avatar(data["initiator_id"]))
|
|
37
|
+
message_id = f"{data['notification_seq']}|join_request|{guild_id}|{1 if data.get('is_filtered') else 0}"
|
|
38
|
+
message = MessageObject(message_id, data.get("comment", ""))
|
|
39
|
+
return Event(
|
|
40
|
+
EventType.GUILD_MEMBER_REQUEST,
|
|
41
|
+
datetime.fromtimestamp(raw["time"]),
|
|
42
|
+
login,
|
|
43
|
+
guild=guild,
|
|
44
|
+
channel=channel,
|
|
45
|
+
user=user,
|
|
46
|
+
member=member,
|
|
47
|
+
message=message,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@register_event("group_invited_join_request")
|
|
52
|
+
async def group_invited_join_request(login, net, raw):
|
|
53
|
+
data = raw["data"]
|
|
54
|
+
guild_id = str(data["group_id"])
|
|
55
|
+
guild = Guild(guild_id, avatar=group_avatar(guild_id))
|
|
56
|
+
channel = Channel(guild_id)
|
|
57
|
+
user = User(str(data["target_user_id"]), avatar=user_avatar(data["target_user_id"]))
|
|
58
|
+
member = Member(user, avatar=user.avatar)
|
|
59
|
+
message_id = f"{data['notification_seq']}|invited_join_request|{guild_id}|0"
|
|
60
|
+
message = MessageObject(message_id, "")
|
|
61
|
+
operator = User(str(data["initiator_id"]), avatar=user_avatar(data["initiator_id"]))
|
|
62
|
+
return Event(
|
|
63
|
+
EventType.GUILD_MEMBER_REQUEST,
|
|
64
|
+
datetime.fromtimestamp(raw["time"]),
|
|
65
|
+
login,
|
|
66
|
+
guild=guild,
|
|
67
|
+
channel=channel,
|
|
68
|
+
user=user,
|
|
69
|
+
member=member,
|
|
70
|
+
operator=operator,
|
|
71
|
+
message=message,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@register_event("group_invitation")
|
|
76
|
+
async def group_invitation(login, net, raw):
|
|
77
|
+
data = raw["data"]
|
|
78
|
+
guild_id = str(data["group_id"])
|
|
79
|
+
guild = Guild(guild_id, avatar=group_avatar(guild_id))
|
|
80
|
+
channel = Channel(guild_id)
|
|
81
|
+
user = User(str(data["initiator_id"]), avatar=user_avatar(data["initiator_id"]))
|
|
82
|
+
message_id = f"{guild_id}|{data['invitation_seq']}"
|
|
83
|
+
message = MessageObject(message_id, "")
|
|
84
|
+
return Event(
|
|
85
|
+
EventType.GUILD_REQUEST,
|
|
86
|
+
datetime.fromtimestamp(raw["time"]),
|
|
87
|
+
login,
|
|
88
|
+
guild=guild,
|
|
89
|
+
channel=channel,
|
|
90
|
+
user=user,
|
|
91
|
+
message=message,
|
|
92
|
+
)
|