@fraqjs/fraq 0.9.1 → 0.10.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 +12 -1
- package/dist/index.mjs +168 -153
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -5522,9 +5522,19 @@ interface RawPattern<P extends Pattern> {
|
|
|
5522
5522
|
pattern: P;
|
|
5523
5523
|
execute: Executor<P>;
|
|
5524
5524
|
}
|
|
5525
|
+
interface SessionReplyOptions {
|
|
5526
|
+
withQuote?: boolean;
|
|
5527
|
+
withMention?: boolean;
|
|
5528
|
+
}
|
|
5525
5529
|
interface Session {
|
|
5526
5530
|
raw: IncomingMessage;
|
|
5527
|
-
reply(
|
|
5531
|
+
reply(
|
|
5532
|
+
textOrSegments: string | OutgoingSegment_ZodInput[],
|
|
5533
|
+
options?: SessionReplyOptions,
|
|
5534
|
+
): Promise<{
|
|
5535
|
+
messageSeq: number;
|
|
5536
|
+
}>;
|
|
5537
|
+
reaction(type: 'face' | 'emoji', reactionId: string): Promise<void>;
|
|
5528
5538
|
}
|
|
5529
5539
|
declare class CommandBuilder<P extends Pattern = {}, S = Command<P>> {
|
|
5530
5540
|
readonly name: string;
|
|
@@ -5846,6 +5856,7 @@ export {
|
|
|
5846
5856
|
ServiceClass,
|
|
5847
5857
|
Session,
|
|
5848
5858
|
SessionPredicate,
|
|
5859
|
+
SessionReplyOptions,
|
|
5849
5860
|
TypeInstruction,
|
|
5850
5861
|
combineLogHandlers,
|
|
5851
5862
|
createMilkyClient,
|
package/dist/index.mjs
CHANGED
|
@@ -64,6 +64,138 @@ function createMilkyClient(...params) {
|
|
|
64
64
|
} });
|
|
65
65
|
}
|
|
66
66
|
//#endregion
|
|
67
|
+
//#region src/protocol/segment.ts
|
|
68
|
+
function msg(strings, ...values) {
|
|
69
|
+
let buffer = "";
|
|
70
|
+
const segments = [];
|
|
71
|
+
for (let i = 0; i < strings.length; i++) {
|
|
72
|
+
buffer += strings[i];
|
|
73
|
+
if (i < values.length) {
|
|
74
|
+
const value = values[i];
|
|
75
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") buffer += value.toString();
|
|
76
|
+
else {
|
|
77
|
+
if (buffer) {
|
|
78
|
+
segments.push({
|
|
79
|
+
type: "text",
|
|
80
|
+
data: { text: buffer }
|
|
81
|
+
});
|
|
82
|
+
buffer = "";
|
|
83
|
+
}
|
|
84
|
+
segments.push(value);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (buffer) segments.push({
|
|
89
|
+
type: "text",
|
|
90
|
+
data: { text: buffer }
|
|
91
|
+
});
|
|
92
|
+
return trimBoundaryTextSegments(segments);
|
|
93
|
+
}
|
|
94
|
+
function isTextSegment(segment) {
|
|
95
|
+
return segment.type === "text";
|
|
96
|
+
}
|
|
97
|
+
function withText(segment, text) {
|
|
98
|
+
return {
|
|
99
|
+
...segment,
|
|
100
|
+
data: {
|
|
101
|
+
...segment.data,
|
|
102
|
+
text
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function trimBoundaryTextSegments(segments) {
|
|
107
|
+
const result = [...segments];
|
|
108
|
+
const first = result[0];
|
|
109
|
+
if (first && isTextSegment(first)) {
|
|
110
|
+
const text = first.data.text.trimStart();
|
|
111
|
+
if (text) result[0] = withText(first, text);
|
|
112
|
+
else result.shift();
|
|
113
|
+
}
|
|
114
|
+
const lastIndex = result.length - 1;
|
|
115
|
+
const last = result[lastIndex];
|
|
116
|
+
if (last && isTextSegment(last)) {
|
|
117
|
+
const text = last.data.text.trimEnd();
|
|
118
|
+
if (text) result[lastIndex] = withText(last, text);
|
|
119
|
+
else result.pop();
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
let seg;
|
|
124
|
+
(function(_seg) {
|
|
125
|
+
function mention(userId) {
|
|
126
|
+
return {
|
|
127
|
+
type: "mention",
|
|
128
|
+
data: { user_id: userId }
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
_seg.mention = mention;
|
|
132
|
+
function mentionAll() {
|
|
133
|
+
return {
|
|
134
|
+
type: "mention_all",
|
|
135
|
+
data: {}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
_seg.mentionAll = mentionAll;
|
|
139
|
+
function face(faceId, options) {
|
|
140
|
+
return {
|
|
141
|
+
type: "face",
|
|
142
|
+
data: {
|
|
143
|
+
face_id: faceId.toString(),
|
|
144
|
+
is_large: options?.isLarge ?? false
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
_seg.face = face;
|
|
149
|
+
function reply(messageSeq) {
|
|
150
|
+
return {
|
|
151
|
+
type: "reply",
|
|
152
|
+
data: { message_seq: messageSeq }
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
_seg.reply = reply;
|
|
156
|
+
function image(uri, options) {
|
|
157
|
+
return {
|
|
158
|
+
type: "image",
|
|
159
|
+
data: {
|
|
160
|
+
uri,
|
|
161
|
+
sub_type: options?.subType,
|
|
162
|
+
summary: options?.summary
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
_seg.image = image;
|
|
167
|
+
function record(uri) {
|
|
168
|
+
return {
|
|
169
|
+
type: "record",
|
|
170
|
+
data: { uri }
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
_seg.record = record;
|
|
174
|
+
function video(uri, options) {
|
|
175
|
+
return {
|
|
176
|
+
type: "video",
|
|
177
|
+
data: {
|
|
178
|
+
uri,
|
|
179
|
+
thumb_uri: options?.thumbUri
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
_seg.video = video;
|
|
184
|
+
function forward(messages, options) {
|
|
185
|
+
return {
|
|
186
|
+
type: "forward",
|
|
187
|
+
data: {
|
|
188
|
+
messages,
|
|
189
|
+
title: options?.title,
|
|
190
|
+
preview: options?.preview,
|
|
191
|
+
summary: options?.summary,
|
|
192
|
+
prompt: options?.prompt
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
_seg.forward = forward;
|
|
197
|
+
})(seg || (seg = {}));
|
|
198
|
+
//#endregion
|
|
67
199
|
//#region src/routing/command.ts
|
|
68
200
|
var CommandBuilder = class {
|
|
69
201
|
name;
|
|
@@ -592,25 +724,40 @@ and implement the dispose method to clean up resources when the context stops.
|
|
|
592
724
|
createSession(message) {
|
|
593
725
|
return {
|
|
594
726
|
raw: message,
|
|
595
|
-
reply: async (
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
727
|
+
reply: async (textOrSegments, options) => {
|
|
728
|
+
const actualSegments = [];
|
|
729
|
+
if (typeof textOrSegments === "string") actualSegments.push({
|
|
730
|
+
type: "text",
|
|
731
|
+
data: { text: textOrSegments }
|
|
732
|
+
});
|
|
733
|
+
else actualSegments.push(...textOrSegments);
|
|
734
|
+
if (options?.withMention && message.message_scene === "group") actualSegments.unshift(seg.mention(message.sender_id));
|
|
735
|
+
if (options?.withQuote) actualSegments.unshift(seg.reply(message.message_seq));
|
|
736
|
+
switch (message.message_scene) {
|
|
737
|
+
case "friend": {
|
|
738
|
+
const { message_seq } = await this.client.send_private_message({
|
|
739
|
+
user_id: message.peer_id,
|
|
740
|
+
message: actualSegments
|
|
741
|
+
});
|
|
742
|
+
return { messageSeq: message_seq };
|
|
743
|
+
}
|
|
744
|
+
case "group": {
|
|
745
|
+
const { message_seq } = await this.client.send_group_message({
|
|
746
|
+
group_id: message.peer_id,
|
|
747
|
+
message: actualSegments
|
|
748
|
+
});
|
|
749
|
+
return { messageSeq: message_seq };
|
|
610
750
|
}
|
|
611
|
-
} catch (error) {
|
|
612
|
-
this.logger.error(`Error sending reply (source msg: scene=${message.message_scene} peer=${message.peer_id} sender=${message.sender_id} seq=${message.message_seq})`, error);
|
|
613
751
|
}
|
|
752
|
+
return { messageSeq: 0 };
|
|
753
|
+
},
|
|
754
|
+
reaction: async (type, reactionId) => {
|
|
755
|
+
if (message.message_scene === "group") await this.client.send_group_message_reaction({
|
|
756
|
+
group_id: message.peer_id,
|
|
757
|
+
message_seq: message.message_seq,
|
|
758
|
+
reaction_type: type,
|
|
759
|
+
reaction: reactionId
|
|
760
|
+
});
|
|
614
761
|
}
|
|
615
762
|
};
|
|
616
763
|
}
|
|
@@ -726,15 +873,15 @@ and implement the dispose method to clean up resources when the context stops.
|
|
|
726
873
|
for (const installedPlugin of sortedPlugins) {
|
|
727
874
|
const { plugin, args } = installedPlugin;
|
|
728
875
|
const providedBeforeApply = new Set(this.services.keys());
|
|
729
|
-
let
|
|
876
|
+
let applyingMessage = `Applying plugin ${plugin.name}`;
|
|
730
877
|
const requiredServices = [];
|
|
731
878
|
const providedServices = [];
|
|
732
879
|
if (plugin.requires) for (const service of plugin.requires) requiredServices.push(service.name);
|
|
733
880
|
if (plugin.optionalRequires) for (const service of plugin.optionalRequires) requiredServices.push(`${service.name}?`);
|
|
734
881
|
if (plugin.provides) for (const service of plugin.provides) providedServices.push(service.name);
|
|
735
|
-
if (requiredServices.length > 0)
|
|
736
|
-
if (providedServices.length > 0)
|
|
737
|
-
this.logger.
|
|
882
|
+
if (requiredServices.length > 0) applyingMessage += `, requires: [${requiredServices.join(", ")}]`;
|
|
883
|
+
if (providedServices.length > 0) applyingMessage += `, provides: [${providedServices.join(", ")}]`;
|
|
884
|
+
this.logger.info(applyingMessage);
|
|
738
885
|
await plugin.apply(this.getPluginContext(installedPlugin), ...args);
|
|
739
886
|
for (const service of plugin.provides ?? []) if (!this.services.has(service) || providedBeforeApply.has(service)) throw new Error(`${plugin.name} declares service ${service.name} but did not provide it.`);
|
|
740
887
|
}
|
|
@@ -1063,138 +1210,6 @@ function definePlugin(plugin) {
|
|
|
1063
1210
|
return plugin;
|
|
1064
1211
|
}
|
|
1065
1212
|
//#endregion
|
|
1066
|
-
//#region src/protocol/segment.ts
|
|
1067
|
-
function msg(strings, ...values) {
|
|
1068
|
-
let buffer = "";
|
|
1069
|
-
const segments = [];
|
|
1070
|
-
for (let i = 0; i < strings.length; i++) {
|
|
1071
|
-
buffer += strings[i];
|
|
1072
|
-
if (i < values.length) {
|
|
1073
|
-
const value = values[i];
|
|
1074
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") buffer += value.toString();
|
|
1075
|
-
else {
|
|
1076
|
-
if (buffer) {
|
|
1077
|
-
segments.push({
|
|
1078
|
-
type: "text",
|
|
1079
|
-
data: { text: buffer }
|
|
1080
|
-
});
|
|
1081
|
-
buffer = "";
|
|
1082
|
-
}
|
|
1083
|
-
segments.push(value);
|
|
1084
|
-
}
|
|
1085
|
-
}
|
|
1086
|
-
}
|
|
1087
|
-
if (buffer) segments.push({
|
|
1088
|
-
type: "text",
|
|
1089
|
-
data: { text: buffer }
|
|
1090
|
-
});
|
|
1091
|
-
return trimBoundaryTextSegments(segments);
|
|
1092
|
-
}
|
|
1093
|
-
function isTextSegment(segment) {
|
|
1094
|
-
return segment.type === "text";
|
|
1095
|
-
}
|
|
1096
|
-
function withText(segment, text) {
|
|
1097
|
-
return {
|
|
1098
|
-
...segment,
|
|
1099
|
-
data: {
|
|
1100
|
-
...segment.data,
|
|
1101
|
-
text
|
|
1102
|
-
}
|
|
1103
|
-
};
|
|
1104
|
-
}
|
|
1105
|
-
function trimBoundaryTextSegments(segments) {
|
|
1106
|
-
const result = [...segments];
|
|
1107
|
-
const first = result[0];
|
|
1108
|
-
if (first && isTextSegment(first)) {
|
|
1109
|
-
const text = first.data.text.trimStart();
|
|
1110
|
-
if (text) result[0] = withText(first, text);
|
|
1111
|
-
else result.shift();
|
|
1112
|
-
}
|
|
1113
|
-
const lastIndex = result.length - 1;
|
|
1114
|
-
const last = result[lastIndex];
|
|
1115
|
-
if (last && isTextSegment(last)) {
|
|
1116
|
-
const text = last.data.text.trimEnd();
|
|
1117
|
-
if (text) result[lastIndex] = withText(last, text);
|
|
1118
|
-
else result.pop();
|
|
1119
|
-
}
|
|
1120
|
-
return result;
|
|
1121
|
-
}
|
|
1122
|
-
let seg;
|
|
1123
|
-
(function(_seg) {
|
|
1124
|
-
function mention(userId) {
|
|
1125
|
-
return {
|
|
1126
|
-
type: "mention",
|
|
1127
|
-
data: { user_id: userId }
|
|
1128
|
-
};
|
|
1129
|
-
}
|
|
1130
|
-
_seg.mention = mention;
|
|
1131
|
-
function mentionAll() {
|
|
1132
|
-
return {
|
|
1133
|
-
type: "mention_all",
|
|
1134
|
-
data: {}
|
|
1135
|
-
};
|
|
1136
|
-
}
|
|
1137
|
-
_seg.mentionAll = mentionAll;
|
|
1138
|
-
function face(faceId, options) {
|
|
1139
|
-
return {
|
|
1140
|
-
type: "face",
|
|
1141
|
-
data: {
|
|
1142
|
-
face_id: faceId.toString(),
|
|
1143
|
-
is_large: options?.isLarge ?? false
|
|
1144
|
-
}
|
|
1145
|
-
};
|
|
1146
|
-
}
|
|
1147
|
-
_seg.face = face;
|
|
1148
|
-
function reply(messageSeq) {
|
|
1149
|
-
return {
|
|
1150
|
-
type: "reply",
|
|
1151
|
-
data: { message_seq: messageSeq }
|
|
1152
|
-
};
|
|
1153
|
-
}
|
|
1154
|
-
_seg.reply = reply;
|
|
1155
|
-
function image(uri, options) {
|
|
1156
|
-
return {
|
|
1157
|
-
type: "image",
|
|
1158
|
-
data: {
|
|
1159
|
-
uri,
|
|
1160
|
-
sub_type: options?.subType,
|
|
1161
|
-
summary: options?.summary
|
|
1162
|
-
}
|
|
1163
|
-
};
|
|
1164
|
-
}
|
|
1165
|
-
_seg.image = image;
|
|
1166
|
-
function record(uri) {
|
|
1167
|
-
return {
|
|
1168
|
-
type: "record",
|
|
1169
|
-
data: { uri }
|
|
1170
|
-
};
|
|
1171
|
-
}
|
|
1172
|
-
_seg.record = record;
|
|
1173
|
-
function video(uri, options) {
|
|
1174
|
-
return {
|
|
1175
|
-
type: "video",
|
|
1176
|
-
data: {
|
|
1177
|
-
uri,
|
|
1178
|
-
thumb_uri: options?.thumbUri
|
|
1179
|
-
}
|
|
1180
|
-
};
|
|
1181
|
-
}
|
|
1182
|
-
_seg.video = video;
|
|
1183
|
-
function forward(messages, options) {
|
|
1184
|
-
return {
|
|
1185
|
-
type: "forward",
|
|
1186
|
-
data: {
|
|
1187
|
-
messages,
|
|
1188
|
-
title: options?.title,
|
|
1189
|
-
preview: options?.preview,
|
|
1190
|
-
summary: options?.summary,
|
|
1191
|
-
prompt: options?.prompt
|
|
1192
|
-
}
|
|
1193
|
-
};
|
|
1194
|
-
}
|
|
1195
|
-
_seg.forward = forward;
|
|
1196
|
-
})(seg || (seg = {}));
|
|
1197
|
-
//#endregion
|
|
1198
1213
|
//#region src/protocol/types.ts
|
|
1199
1214
|
const milkyVersion = "1.3";
|
|
1200
1215
|
const milkyPackageVersion = "1.3.0-rc.1";
|