fix(federation): generate thumbnails for downloaded federated attachments

After the file worker downloads a federated attachment, generate a
thumbnail using the same sharp pipeline as local uploads. This ensures
federated images use bandwidth-efficient thumbnails in chat view
instead of serving the full-size image.

Also fixes processCreateEvent to not copy the source instance's
thumbnailFilename (which doesn't exist locally).
This commit is contained in:
Jannis Braun
2026-03-26 06:46:14 +01:00
parent 4ed9b30ce9
commit 086195aa7c
@@ -7,6 +7,7 @@ import { buildFederationHeaders } from './federationAuth.js';
import { generateSnowflake } from './snowflake.js';
import { getDmMessageWithUser } from '../routes/dm.js';
import { connectionManager } from '../ws/handler.js';
import { generateThumbnail } from './thumbnail.js';
import type { FederationRelayRequest, FederationRelayResponse, FederationRelayEvent } from '@backspace/shared';
import fs from 'node:fs';
import path from 'node:path';
@@ -444,12 +445,21 @@ async function processFileQueueEntry(
return;
}
// Generate thumbnail for images (same as local upload flow)
let thumbnailFilename: string | null = null;
try {
thumbnailFilename = await generateThumbnail(localPath, entry.mimetype, config.uploadDir);
} catch {
// Non-fatal — full image will be used instead
}
// Update the existing attachment row (created by processCreateEvent with
// sourceUrl as interim filename) to point to the local file
const updated = db.update(schema.attachments)
.set({
filename: localFilename,
size: stat.size,
thumbnailFilename,
})
.where(
and(
@@ -471,6 +481,7 @@ async function processFileQueueEntry(
originalName: entry.originalName,
mimetype: entry.mimetype,
size: stat.size,
thumbnailFilename,
sourceUrl: entry.sourceUrl,
createdAt: now,
})