openclaw-channel-dmwork 0.3.2 → 0.3.3
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/package.json +1 -1
- package/src/inbound.ts +30 -6
package/package.json
CHANGED
package/src/inbound.ts
CHANGED
|
@@ -126,6 +126,25 @@ async function uploadAndSendMedia(params: {
|
|
|
126
126
|
});
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
/** Guess MIME type from file extension */
|
|
130
|
+
function guessMime(pathOrName?: string, fallback = "application/octet-stream"): string {
|
|
131
|
+
if (!pathOrName) return fallback;
|
|
132
|
+
const ext = pathOrName.split(".").pop()?.toLowerCase() ?? "";
|
|
133
|
+
const map: Record<string, string> = {
|
|
134
|
+
jpg: "image/jpeg", jpeg: "image/jpeg", png: "image/png", gif: "image/gif", webp: "image/webp", svg: "image/svg+xml", bmp: "image/bmp",
|
|
135
|
+
mp3: "audio/mpeg", ogg: "audio/ogg", wav: "audio/wav", m4a: "audio/mp4", aac: "audio/aac", opus: "audio/opus",
|
|
136
|
+
mp4: "video/mp4", mov: "video/quicktime", webm: "video/webm", avi: "video/x-msvideo", mkv: "video/x-matroska",
|
|
137
|
+
pdf: "application/pdf", doc: "application/msword", docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
138
|
+
xls: "application/vnd.ms-excel", xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
139
|
+
ppt: "application/vnd.ms-powerpoint", pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
140
|
+
zip: "application/zip", gz: "application/gzip", tar: "application/x-tar",
|
|
141
|
+
txt: "text/plain", json: "application/json", csv: "text/csv", md: "text/markdown",
|
|
142
|
+
py: "text/x-python", js: "text/javascript", ts: "text/typescript", go: "text/x-go", java: "text/x-java",
|
|
143
|
+
html: "text/html", css: "text/css", xml: "text/xml", yaml: "text/yaml", yml: "text/yaml",
|
|
144
|
+
};
|
|
145
|
+
return map[ext] ?? fallback;
|
|
146
|
+
}
|
|
147
|
+
|
|
129
148
|
interface ResolvedContent {
|
|
130
149
|
text: string;
|
|
131
150
|
mediaUrl?: string;
|
|
@@ -150,23 +169,27 @@ function resolveContent(payload: BotMessage["payload"], apiUrl?: string): Resolv
|
|
|
150
169
|
return { text: payload.content ?? "" };
|
|
151
170
|
case MessageType.Image: {
|
|
152
171
|
const imgUrl = makeFullUrl(payload.url);
|
|
153
|
-
|
|
172
|
+
const imgMime = guessMime(payload.url, "image/jpeg");
|
|
173
|
+
return { text: `[图片]\n${imgUrl ?? ""}`.trim(), mediaUrl: imgUrl, mediaType: imgMime };
|
|
154
174
|
}
|
|
155
175
|
case MessageType.GIF: {
|
|
156
176
|
const gifUrl = makeFullUrl(payload.url);
|
|
157
|
-
return { text: `[GIF]\n${gifUrl ?? ""}`.trim(), mediaUrl: gifUrl, mediaType: "image" };
|
|
177
|
+
return { text: `[GIF]\n${gifUrl ?? ""}`.trim(), mediaUrl: gifUrl, mediaType: "image/gif" };
|
|
158
178
|
}
|
|
159
179
|
case MessageType.Voice: {
|
|
160
180
|
const voiceUrl = makeFullUrl(payload.url);
|
|
161
|
-
|
|
181
|
+
const voiceMime = guessMime(payload.url, "audio/mpeg");
|
|
182
|
+
return { text: `[语音消息]\n${voiceUrl ?? ""}`.trim(), mediaUrl: voiceUrl, mediaType: voiceMime };
|
|
162
183
|
}
|
|
163
184
|
case MessageType.Video: {
|
|
164
185
|
const videoUrl = makeFullUrl(payload.url);
|
|
165
|
-
|
|
186
|
+
const videoMime = guessMime(payload.url, "video/mp4");
|
|
187
|
+
return { text: `[视频]\n${videoUrl ?? ""}`.trim(), mediaUrl: videoUrl, mediaType: videoMime };
|
|
166
188
|
}
|
|
167
189
|
case MessageType.File: {
|
|
168
190
|
const fileUrl = makeFullUrl(payload.url);
|
|
169
|
-
|
|
191
|
+
const fileMime = guessMime(payload.url, payload.name ? guessMime(payload.name, "application/octet-stream") : "application/octet-stream");
|
|
192
|
+
return { text: `[文件: ${payload.name ?? "未知文件"}]\n${fileUrl ?? ""}`.trim(), mediaUrl: fileUrl, mediaType: fileMime };
|
|
170
193
|
}
|
|
171
194
|
case MessageType.Location: {
|
|
172
195
|
const lat = payload.latitude ?? payload.lat;
|
|
@@ -410,7 +433,8 @@ export async function handleInboundMessage(params: {
|
|
|
410
433
|
let rawBody = resolved.text;
|
|
411
434
|
let inboundMediaUrl = resolved.mediaUrl;
|
|
412
435
|
// Inline text file content if possible
|
|
413
|
-
|
|
436
|
+
const isFileMessage = message.payload?.type === MessageType.File;
|
|
437
|
+
if (isFileMessage && resolved.mediaUrl) {
|
|
414
438
|
const fileContent = await resolveFileContent(resolved.mediaUrl, account.config.botToken ?? "");
|
|
415
439
|
if (fileContent) {
|
|
416
440
|
rawBody = `[文件: ${message.payload.name ?? "未知文件"}]\n\n--- 文件内容 ---\n${fileContent}\n--- 文件结束 ---`;
|