mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-15 17:30:13 +08:00
fix(dashboard): resolve chat attachment 401 (#7569)
* fix(dashboard): resolve chat attachment 401 by restoring axios blob URL fetch * chore: cache blob URL promises to prevent duplicate requests and memory leaks
This commit is contained in:
@@ -86,6 +86,7 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
const messagesBySession = reactive<Record<string, ChatRecord[]>>({});
|
||||
const loadedSessions = reactive<Record<string, boolean>>({});
|
||||
const activeConnections = reactive<Record<string, ActiveConnection>>({});
|
||||
const attachmentBlobCache = new Map<string, Promise<string>>();
|
||||
const sessionProjects = reactive<Record<string, ChatSessionProject | null>>(
|
||||
{},
|
||||
);
|
||||
@@ -98,6 +99,10 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
cleanupConnections();
|
||||
for (const promise of attachmentBlobCache.values()) {
|
||||
promise.then((url) => URL.revokeObjectURL(url)).catch(() => {});
|
||||
}
|
||||
attachmentBlobCache.clear();
|
||||
});
|
||||
|
||||
function isSessionRunning(sessionId: string) {
|
||||
@@ -129,6 +134,47 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
return !isUserMessage(msg) && msgIndex === activeMessages.value.length - 1;
|
||||
}
|
||||
|
||||
async function resolvePartMedia(part: MessagePart): Promise<void> {
|
||||
if (part.embedded_url) return;
|
||||
let url: string;
|
||||
let cacheKey: string;
|
||||
if (part.attachment_id) {
|
||||
cacheKey = `att:${part.attachment_id}`;
|
||||
url = `/api/chat/get_attachment?attachment_id=${encodeURIComponent(part.attachment_id)}`;
|
||||
} else if (part.filename) {
|
||||
cacheKey = `file:${part.filename}`;
|
||||
url = `/api/chat/get_file?filename=${encodeURIComponent(part.filename)}`;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
let promise = attachmentBlobCache.get(cacheKey);
|
||||
if (!promise) {
|
||||
promise = axios
|
||||
.get(url, { responseType: "blob" })
|
||||
.then((resp) => URL.createObjectURL(resp.data));
|
||||
attachmentBlobCache.set(cacheKey, promise);
|
||||
}
|
||||
try {
|
||||
part.embedded_url = await promise;
|
||||
} catch (e) {
|
||||
attachmentBlobCache.delete(cacheKey);
|
||||
console.error("Failed to resolve media:", cacheKey, e);
|
||||
}
|
||||
}
|
||||
|
||||
async function resolveRecordMedia(records: ChatRecord[]) {
|
||||
const mediaTypes = ["image", "record", "video"];
|
||||
const tasks: Promise<void>[] = [];
|
||||
for (const record of records) {
|
||||
for (const part of record.content?.message || []) {
|
||||
if (mediaTypes.includes(part.type) && !part.embedded_url && (part.attachment_id || part.filename)) {
|
||||
tasks.push(resolvePartMedia(part));
|
||||
}
|
||||
}
|
||||
}
|
||||
await Promise.all(tasks);
|
||||
}
|
||||
|
||||
async function loadSessionMessages(sessionId: string) {
|
||||
if (!sessionId) return;
|
||||
loadingMessages.value = true;
|
||||
@@ -138,7 +184,9 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
});
|
||||
const payload = response.data?.data || {};
|
||||
const history = payload.history || [];
|
||||
messagesBySession[sessionId] = history.map(normalizeHistoryRecord);
|
||||
const records = history.map(normalizeHistoryRecord);
|
||||
await resolveRecordMedia(records);
|
||||
messagesBySession[sessionId] = records;
|
||||
sessionProjects[sessionId] = normalizeSessionProject(payload.project);
|
||||
loadedSessions[sessionId] = true;
|
||||
} catch (error) {
|
||||
@@ -438,7 +486,14 @@ export function useMessages(options: UseMessagesOptions) {
|
||||
.replace("[FILE]", "")
|
||||
.replace("[VIDEO]", "")
|
||||
.split("|", 1)[0];
|
||||
messageContent(botRecord).message.push({ type: msgType, filename });
|
||||
const mediaPart: MessagePart = { type: msgType, filename };
|
||||
if (msgType !== "file") {
|
||||
resolvePartMedia(mediaPart).then(() => {
|
||||
messageContent(botRecord).message.push(mediaPart);
|
||||
});
|
||||
} else {
|
||||
messageContent(botRecord).message.push(mediaPart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user