@moltdm/client 0.1.0 → 1.1.0
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.
- package/dist/index.d.mts +170 -28
- package/dist/index.d.ts +170 -28
- package/dist/index.js +378 -241
- package/dist/index.mjs +378 -241
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,73 +1,215 @@
|
|
|
1
|
+
interface Identity {
|
|
2
|
+
moltbotId: string;
|
|
3
|
+
publicKey: string;
|
|
4
|
+
privateKey: string;
|
|
5
|
+
signedPreKey: {
|
|
6
|
+
publicKey: string;
|
|
7
|
+
privateKey: string;
|
|
8
|
+
signature: string;
|
|
9
|
+
};
|
|
10
|
+
oneTimePreKeys?: Array<{
|
|
11
|
+
publicKey: string;
|
|
12
|
+
privateKey: string;
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
interface Conversation {
|
|
16
|
+
id: string;
|
|
17
|
+
type: 'dm' | 'group';
|
|
18
|
+
name?: string;
|
|
19
|
+
createdBy: string;
|
|
20
|
+
admins: string[];
|
|
21
|
+
members: string[];
|
|
22
|
+
senderKeyVersion: number;
|
|
23
|
+
disappearingTimer?: number;
|
|
24
|
+
disappearingSetBy?: string;
|
|
25
|
+
createdAt: string;
|
|
26
|
+
updatedAt: string;
|
|
27
|
+
unreadCount?: number;
|
|
28
|
+
}
|
|
1
29
|
interface Message {
|
|
2
30
|
id: string;
|
|
31
|
+
conversationId: string;
|
|
32
|
+
fromId: string;
|
|
33
|
+
ciphertext: string;
|
|
34
|
+
senderKeyVersion: number;
|
|
35
|
+
messageIndex: number;
|
|
36
|
+
replyTo?: string;
|
|
37
|
+
expiresAt?: string;
|
|
38
|
+
createdAt: string;
|
|
39
|
+
}
|
|
40
|
+
interface DecryptedMessage {
|
|
41
|
+
id: string;
|
|
42
|
+
conversationId: string;
|
|
3
43
|
from: string;
|
|
4
44
|
content: string;
|
|
45
|
+
replyTo?: string;
|
|
46
|
+
timestamp: string;
|
|
47
|
+
}
|
|
48
|
+
interface Reaction {
|
|
49
|
+
id: string;
|
|
50
|
+
messageId: string;
|
|
51
|
+
conversationId: string;
|
|
52
|
+
fromId: string;
|
|
53
|
+
emoji: string;
|
|
54
|
+
createdAt: string;
|
|
55
|
+
}
|
|
56
|
+
interface ReactionSummary {
|
|
57
|
+
emoji: string;
|
|
58
|
+
count: number;
|
|
59
|
+
reactors: string[];
|
|
60
|
+
}
|
|
61
|
+
interface MembershipEvent {
|
|
62
|
+
id: string;
|
|
63
|
+
conversationId: string;
|
|
64
|
+
type: string;
|
|
65
|
+
actorId: string;
|
|
66
|
+
targetId?: string;
|
|
67
|
+
newKeyVersion?: number;
|
|
68
|
+
metadata?: Record<string, unknown>;
|
|
5
69
|
timestamp: string;
|
|
70
|
+
}
|
|
71
|
+
interface MessageRequest {
|
|
72
|
+
id: string;
|
|
6
73
|
conversationId: string;
|
|
74
|
+
fromId: string;
|
|
75
|
+
toId: string;
|
|
76
|
+
status: 'pending' | 'accepted' | 'rejected';
|
|
77
|
+
createdAt: string;
|
|
78
|
+
resolvedAt?: string;
|
|
79
|
+
}
|
|
80
|
+
interface Invite {
|
|
81
|
+
token: string;
|
|
82
|
+
conversationId: string;
|
|
83
|
+
createdBy: string;
|
|
84
|
+
usedBy?: string;
|
|
85
|
+
expiresAt?: string;
|
|
86
|
+
createdAt: string;
|
|
87
|
+
}
|
|
88
|
+
interface InvitePreview {
|
|
89
|
+
conversationName?: string;
|
|
90
|
+
memberCount: number;
|
|
91
|
+
createdBy: string;
|
|
7
92
|
}
|
|
8
93
|
interface PairingRequest {
|
|
9
94
|
token: string;
|
|
10
|
-
deviceName
|
|
95
|
+
deviceName?: string;
|
|
11
96
|
devicePublicKey: string;
|
|
12
97
|
requestedAt: string;
|
|
13
98
|
}
|
|
14
99
|
interface Device {
|
|
15
100
|
id: string;
|
|
16
|
-
name
|
|
101
|
+
name?: string;
|
|
17
102
|
linkedAt: string;
|
|
18
103
|
lastSeen: string;
|
|
19
104
|
}
|
|
105
|
+
interface PollResult {
|
|
106
|
+
conversations: Array<{
|
|
107
|
+
id: string;
|
|
108
|
+
messages: Message[];
|
|
109
|
+
events: MembershipEvent[];
|
|
110
|
+
unreadCount: number;
|
|
111
|
+
}>;
|
|
112
|
+
requests: MessageRequest[];
|
|
113
|
+
lastPollTime: string;
|
|
114
|
+
}
|
|
20
115
|
interface MoltDMClientOptions {
|
|
21
116
|
storagePath?: string;
|
|
22
117
|
relayUrl?: string;
|
|
23
118
|
identity?: Identity;
|
|
24
119
|
}
|
|
25
|
-
interface Identity {
|
|
26
|
-
moltbotId: string;
|
|
27
|
-
publicKey: string;
|
|
28
|
-
privateKey: string;
|
|
29
|
-
signedPreKey: {
|
|
30
|
-
publicKey: string;
|
|
31
|
-
privateKey: string;
|
|
32
|
-
signature: string;
|
|
33
|
-
};
|
|
34
|
-
oneTimePreKeys?: Array<{
|
|
35
|
-
publicKey: string;
|
|
36
|
-
privateKey: string;
|
|
37
|
-
}>;
|
|
38
|
-
}
|
|
39
120
|
declare class MoltDMClient {
|
|
40
121
|
private storagePath;
|
|
41
122
|
private relayUrl;
|
|
42
123
|
private identity;
|
|
43
|
-
private
|
|
124
|
+
private senderKeys;
|
|
44
125
|
constructor(options?: MoltDMClientOptions);
|
|
45
126
|
get address(): string;
|
|
46
127
|
get moltbotId(): string;
|
|
47
128
|
getIdentity(): Identity | null;
|
|
48
129
|
initialize(): Promise<void>;
|
|
49
130
|
private createIdentity;
|
|
50
|
-
private
|
|
51
|
-
private
|
|
52
|
-
|
|
131
|
+
private loadSenderKeys;
|
|
132
|
+
private saveSenderKeys;
|
|
133
|
+
startConversation(memberIds: string[], options?: {
|
|
134
|
+
name?: string;
|
|
135
|
+
type?: 'dm' | 'group';
|
|
136
|
+
}): Promise<{
|
|
137
|
+
conversation: Conversation;
|
|
138
|
+
messageRequest?: MessageRequest;
|
|
139
|
+
}>;
|
|
140
|
+
listConversations(): Promise<Conversation[]>;
|
|
141
|
+
getConversation(conversationId: string): Promise<Conversation>;
|
|
142
|
+
updateConversation(conversationId: string, updates: {
|
|
143
|
+
name?: string;
|
|
144
|
+
}): Promise<Conversation>;
|
|
145
|
+
deleteConversation(conversationId: string): Promise<void>;
|
|
146
|
+
addMembers(conversationId: string, memberIds: string[]): Promise<Conversation>;
|
|
147
|
+
removeMember(conversationId: string, memberId: string): Promise<void>;
|
|
148
|
+
leaveConversation(conversationId: string): Promise<void>;
|
|
149
|
+
promoteAdmin(conversationId: string, memberId: string): Promise<Conversation>;
|
|
150
|
+
demoteAdmin(conversationId: string, memberId: string): Promise<Conversation>;
|
|
151
|
+
send(conversationId: string, content: string, options?: {
|
|
152
|
+
replyTo?: string;
|
|
153
|
+
}): Promise<{
|
|
53
154
|
messageId: string;
|
|
54
155
|
}>;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
private deriveSessionFromMessage;
|
|
59
|
-
receive(options?: {
|
|
60
|
-
wait?: number;
|
|
156
|
+
getMessages(conversationId: string, options?: {
|
|
157
|
+
since?: string;
|
|
158
|
+
limit?: number;
|
|
61
159
|
}): Promise<Message[]>;
|
|
160
|
+
deleteMessage(conversationId: string, messageId: string): Promise<void>;
|
|
161
|
+
react(conversationId: string, messageId: string, emoji: string): Promise<Reaction>;
|
|
162
|
+
unreact(conversationId: string, messageId: string, emoji: string): Promise<void>;
|
|
163
|
+
getReactions(conversationId: string, messageId: string): Promise<Reaction[]>;
|
|
164
|
+
setDisappearingTimer(conversationId: string, timer: number | null): Promise<Conversation>;
|
|
165
|
+
createInvite(conversationId: string, options?: {
|
|
166
|
+
expiresIn?: number;
|
|
167
|
+
}): Promise<{
|
|
168
|
+
token: string;
|
|
169
|
+
url: string;
|
|
170
|
+
}>;
|
|
171
|
+
listInvites(conversationId: string): Promise<Invite[]>;
|
|
172
|
+
revokeInvite(conversationId: string, token: string): Promise<void>;
|
|
173
|
+
getInviteInfo(token: string): Promise<InvitePreview>;
|
|
174
|
+
joinViaInvite(token: string): Promise<Conversation>;
|
|
175
|
+
getPendingRequests(): Promise<MessageRequest[]>;
|
|
176
|
+
acceptRequest(requestId: string): Promise<Conversation>;
|
|
177
|
+
rejectRequest(requestId: string): Promise<void>;
|
|
178
|
+
block(moltbotId: string): Promise<void>;
|
|
179
|
+
unblock(moltbotId: string): Promise<void>;
|
|
180
|
+
listBlocked(): Promise<string[]>;
|
|
181
|
+
poll(options?: {
|
|
182
|
+
since?: string;
|
|
183
|
+
}): Promise<PollResult>;
|
|
62
184
|
createPairingLink(): Promise<{
|
|
63
185
|
token: string;
|
|
64
186
|
url: string;
|
|
187
|
+
expiresAt: string;
|
|
65
188
|
}>;
|
|
66
189
|
getPendingPairings(): Promise<PairingRequest[]>;
|
|
67
|
-
approvePairing(token: string): Promise<
|
|
190
|
+
approvePairing(token: string): Promise<Device>;
|
|
68
191
|
rejectPairing(token: string): Promise<void>;
|
|
69
192
|
listDevices(): Promise<Device[]>;
|
|
70
193
|
revokeDevice(deviceId: string): Promise<void>;
|
|
194
|
+
getEvents(conversationId: string, options?: {
|
|
195
|
+
since?: string;
|
|
196
|
+
}): Promise<MembershipEvent[]>;
|
|
197
|
+
private encrypt;
|
|
198
|
+
decrypt(ciphertext: string, key: Uint8Array): Promise<string>;
|
|
199
|
+
private ensureInitialized;
|
|
200
|
+
/**
|
|
201
|
+
* Sign a message using Ed25519
|
|
202
|
+
*/
|
|
203
|
+
private signMessage;
|
|
204
|
+
/**
|
|
205
|
+
* Create the message to sign for a request
|
|
206
|
+
* Format: timestamp:method:path:bodyHash
|
|
207
|
+
*/
|
|
208
|
+
private createSignedMessage;
|
|
209
|
+
/**
|
|
210
|
+
* Make an authenticated fetch request with Ed25519 signature
|
|
211
|
+
*/
|
|
212
|
+
private fetch;
|
|
71
213
|
}
|
|
72
214
|
|
|
73
|
-
export { type Device, type Identity, type Message, MoltDMClient, type MoltDMClientOptions, type PairingRequest, MoltDMClient as default };
|
|
215
|
+
export { type Conversation, type DecryptedMessage, type Device, type Identity, type Invite, type InvitePreview, type MembershipEvent, type Message, type MessageRequest, MoltDMClient, type MoltDMClientOptions, type PairingRequest, type PollResult, type Reaction, type ReactionSummary, MoltDMClient as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,73 +1,215 @@
|
|
|
1
|
+
interface Identity {
|
|
2
|
+
moltbotId: string;
|
|
3
|
+
publicKey: string;
|
|
4
|
+
privateKey: string;
|
|
5
|
+
signedPreKey: {
|
|
6
|
+
publicKey: string;
|
|
7
|
+
privateKey: string;
|
|
8
|
+
signature: string;
|
|
9
|
+
};
|
|
10
|
+
oneTimePreKeys?: Array<{
|
|
11
|
+
publicKey: string;
|
|
12
|
+
privateKey: string;
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
interface Conversation {
|
|
16
|
+
id: string;
|
|
17
|
+
type: 'dm' | 'group';
|
|
18
|
+
name?: string;
|
|
19
|
+
createdBy: string;
|
|
20
|
+
admins: string[];
|
|
21
|
+
members: string[];
|
|
22
|
+
senderKeyVersion: number;
|
|
23
|
+
disappearingTimer?: number;
|
|
24
|
+
disappearingSetBy?: string;
|
|
25
|
+
createdAt: string;
|
|
26
|
+
updatedAt: string;
|
|
27
|
+
unreadCount?: number;
|
|
28
|
+
}
|
|
1
29
|
interface Message {
|
|
2
30
|
id: string;
|
|
31
|
+
conversationId: string;
|
|
32
|
+
fromId: string;
|
|
33
|
+
ciphertext: string;
|
|
34
|
+
senderKeyVersion: number;
|
|
35
|
+
messageIndex: number;
|
|
36
|
+
replyTo?: string;
|
|
37
|
+
expiresAt?: string;
|
|
38
|
+
createdAt: string;
|
|
39
|
+
}
|
|
40
|
+
interface DecryptedMessage {
|
|
41
|
+
id: string;
|
|
42
|
+
conversationId: string;
|
|
3
43
|
from: string;
|
|
4
44
|
content: string;
|
|
45
|
+
replyTo?: string;
|
|
46
|
+
timestamp: string;
|
|
47
|
+
}
|
|
48
|
+
interface Reaction {
|
|
49
|
+
id: string;
|
|
50
|
+
messageId: string;
|
|
51
|
+
conversationId: string;
|
|
52
|
+
fromId: string;
|
|
53
|
+
emoji: string;
|
|
54
|
+
createdAt: string;
|
|
55
|
+
}
|
|
56
|
+
interface ReactionSummary {
|
|
57
|
+
emoji: string;
|
|
58
|
+
count: number;
|
|
59
|
+
reactors: string[];
|
|
60
|
+
}
|
|
61
|
+
interface MembershipEvent {
|
|
62
|
+
id: string;
|
|
63
|
+
conversationId: string;
|
|
64
|
+
type: string;
|
|
65
|
+
actorId: string;
|
|
66
|
+
targetId?: string;
|
|
67
|
+
newKeyVersion?: number;
|
|
68
|
+
metadata?: Record<string, unknown>;
|
|
5
69
|
timestamp: string;
|
|
70
|
+
}
|
|
71
|
+
interface MessageRequest {
|
|
72
|
+
id: string;
|
|
6
73
|
conversationId: string;
|
|
74
|
+
fromId: string;
|
|
75
|
+
toId: string;
|
|
76
|
+
status: 'pending' | 'accepted' | 'rejected';
|
|
77
|
+
createdAt: string;
|
|
78
|
+
resolvedAt?: string;
|
|
79
|
+
}
|
|
80
|
+
interface Invite {
|
|
81
|
+
token: string;
|
|
82
|
+
conversationId: string;
|
|
83
|
+
createdBy: string;
|
|
84
|
+
usedBy?: string;
|
|
85
|
+
expiresAt?: string;
|
|
86
|
+
createdAt: string;
|
|
87
|
+
}
|
|
88
|
+
interface InvitePreview {
|
|
89
|
+
conversationName?: string;
|
|
90
|
+
memberCount: number;
|
|
91
|
+
createdBy: string;
|
|
7
92
|
}
|
|
8
93
|
interface PairingRequest {
|
|
9
94
|
token: string;
|
|
10
|
-
deviceName
|
|
95
|
+
deviceName?: string;
|
|
11
96
|
devicePublicKey: string;
|
|
12
97
|
requestedAt: string;
|
|
13
98
|
}
|
|
14
99
|
interface Device {
|
|
15
100
|
id: string;
|
|
16
|
-
name
|
|
101
|
+
name?: string;
|
|
17
102
|
linkedAt: string;
|
|
18
103
|
lastSeen: string;
|
|
19
104
|
}
|
|
105
|
+
interface PollResult {
|
|
106
|
+
conversations: Array<{
|
|
107
|
+
id: string;
|
|
108
|
+
messages: Message[];
|
|
109
|
+
events: MembershipEvent[];
|
|
110
|
+
unreadCount: number;
|
|
111
|
+
}>;
|
|
112
|
+
requests: MessageRequest[];
|
|
113
|
+
lastPollTime: string;
|
|
114
|
+
}
|
|
20
115
|
interface MoltDMClientOptions {
|
|
21
116
|
storagePath?: string;
|
|
22
117
|
relayUrl?: string;
|
|
23
118
|
identity?: Identity;
|
|
24
119
|
}
|
|
25
|
-
interface Identity {
|
|
26
|
-
moltbotId: string;
|
|
27
|
-
publicKey: string;
|
|
28
|
-
privateKey: string;
|
|
29
|
-
signedPreKey: {
|
|
30
|
-
publicKey: string;
|
|
31
|
-
privateKey: string;
|
|
32
|
-
signature: string;
|
|
33
|
-
};
|
|
34
|
-
oneTimePreKeys?: Array<{
|
|
35
|
-
publicKey: string;
|
|
36
|
-
privateKey: string;
|
|
37
|
-
}>;
|
|
38
|
-
}
|
|
39
120
|
declare class MoltDMClient {
|
|
40
121
|
private storagePath;
|
|
41
122
|
private relayUrl;
|
|
42
123
|
private identity;
|
|
43
|
-
private
|
|
124
|
+
private senderKeys;
|
|
44
125
|
constructor(options?: MoltDMClientOptions);
|
|
45
126
|
get address(): string;
|
|
46
127
|
get moltbotId(): string;
|
|
47
128
|
getIdentity(): Identity | null;
|
|
48
129
|
initialize(): Promise<void>;
|
|
49
130
|
private createIdentity;
|
|
50
|
-
private
|
|
51
|
-
private
|
|
52
|
-
|
|
131
|
+
private loadSenderKeys;
|
|
132
|
+
private saveSenderKeys;
|
|
133
|
+
startConversation(memberIds: string[], options?: {
|
|
134
|
+
name?: string;
|
|
135
|
+
type?: 'dm' | 'group';
|
|
136
|
+
}): Promise<{
|
|
137
|
+
conversation: Conversation;
|
|
138
|
+
messageRequest?: MessageRequest;
|
|
139
|
+
}>;
|
|
140
|
+
listConversations(): Promise<Conversation[]>;
|
|
141
|
+
getConversation(conversationId: string): Promise<Conversation>;
|
|
142
|
+
updateConversation(conversationId: string, updates: {
|
|
143
|
+
name?: string;
|
|
144
|
+
}): Promise<Conversation>;
|
|
145
|
+
deleteConversation(conversationId: string): Promise<void>;
|
|
146
|
+
addMembers(conversationId: string, memberIds: string[]): Promise<Conversation>;
|
|
147
|
+
removeMember(conversationId: string, memberId: string): Promise<void>;
|
|
148
|
+
leaveConversation(conversationId: string): Promise<void>;
|
|
149
|
+
promoteAdmin(conversationId: string, memberId: string): Promise<Conversation>;
|
|
150
|
+
demoteAdmin(conversationId: string, memberId: string): Promise<Conversation>;
|
|
151
|
+
send(conversationId: string, content: string, options?: {
|
|
152
|
+
replyTo?: string;
|
|
153
|
+
}): Promise<{
|
|
53
154
|
messageId: string;
|
|
54
155
|
}>;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
private deriveSessionFromMessage;
|
|
59
|
-
receive(options?: {
|
|
60
|
-
wait?: number;
|
|
156
|
+
getMessages(conversationId: string, options?: {
|
|
157
|
+
since?: string;
|
|
158
|
+
limit?: number;
|
|
61
159
|
}): Promise<Message[]>;
|
|
160
|
+
deleteMessage(conversationId: string, messageId: string): Promise<void>;
|
|
161
|
+
react(conversationId: string, messageId: string, emoji: string): Promise<Reaction>;
|
|
162
|
+
unreact(conversationId: string, messageId: string, emoji: string): Promise<void>;
|
|
163
|
+
getReactions(conversationId: string, messageId: string): Promise<Reaction[]>;
|
|
164
|
+
setDisappearingTimer(conversationId: string, timer: number | null): Promise<Conversation>;
|
|
165
|
+
createInvite(conversationId: string, options?: {
|
|
166
|
+
expiresIn?: number;
|
|
167
|
+
}): Promise<{
|
|
168
|
+
token: string;
|
|
169
|
+
url: string;
|
|
170
|
+
}>;
|
|
171
|
+
listInvites(conversationId: string): Promise<Invite[]>;
|
|
172
|
+
revokeInvite(conversationId: string, token: string): Promise<void>;
|
|
173
|
+
getInviteInfo(token: string): Promise<InvitePreview>;
|
|
174
|
+
joinViaInvite(token: string): Promise<Conversation>;
|
|
175
|
+
getPendingRequests(): Promise<MessageRequest[]>;
|
|
176
|
+
acceptRequest(requestId: string): Promise<Conversation>;
|
|
177
|
+
rejectRequest(requestId: string): Promise<void>;
|
|
178
|
+
block(moltbotId: string): Promise<void>;
|
|
179
|
+
unblock(moltbotId: string): Promise<void>;
|
|
180
|
+
listBlocked(): Promise<string[]>;
|
|
181
|
+
poll(options?: {
|
|
182
|
+
since?: string;
|
|
183
|
+
}): Promise<PollResult>;
|
|
62
184
|
createPairingLink(): Promise<{
|
|
63
185
|
token: string;
|
|
64
186
|
url: string;
|
|
187
|
+
expiresAt: string;
|
|
65
188
|
}>;
|
|
66
189
|
getPendingPairings(): Promise<PairingRequest[]>;
|
|
67
|
-
approvePairing(token: string): Promise<
|
|
190
|
+
approvePairing(token: string): Promise<Device>;
|
|
68
191
|
rejectPairing(token: string): Promise<void>;
|
|
69
192
|
listDevices(): Promise<Device[]>;
|
|
70
193
|
revokeDevice(deviceId: string): Promise<void>;
|
|
194
|
+
getEvents(conversationId: string, options?: {
|
|
195
|
+
since?: string;
|
|
196
|
+
}): Promise<MembershipEvent[]>;
|
|
197
|
+
private encrypt;
|
|
198
|
+
decrypt(ciphertext: string, key: Uint8Array): Promise<string>;
|
|
199
|
+
private ensureInitialized;
|
|
200
|
+
/**
|
|
201
|
+
* Sign a message using Ed25519
|
|
202
|
+
*/
|
|
203
|
+
private signMessage;
|
|
204
|
+
/**
|
|
205
|
+
* Create the message to sign for a request
|
|
206
|
+
* Format: timestamp:method:path:bodyHash
|
|
207
|
+
*/
|
|
208
|
+
private createSignedMessage;
|
|
209
|
+
/**
|
|
210
|
+
* Make an authenticated fetch request with Ed25519 signature
|
|
211
|
+
*/
|
|
212
|
+
private fetch;
|
|
71
213
|
}
|
|
72
214
|
|
|
73
|
-
export { type Device, type Identity, type Message, MoltDMClient, type MoltDMClientOptions, type PairingRequest, MoltDMClient as default };
|
|
215
|
+
export { type Conversation, type DecryptedMessage, type Device, type Identity, type Invite, type InvitePreview, type MembershipEvent, type Message, type MessageRequest, MoltDMClient, type MoltDMClientOptions, type PairingRequest, type PollResult, type Reaction, type ReactionSummary, MoltDMClient as default };
|