mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 17:46:06 +00:00
feat: enable S3 video uploads and update related configurations
- Added support for self-hosted S3 video uploads with new environment variables: OPENFRAME_ENABLE_S3_VIDEO_UPLOADS and OPENFRAME_MAX_VIDEO_UPLOAD_BYTES. - Updated .env.example and .env.docker.example to reflect new configuration options. - Enhanced Content Security Policy to include origins for S3-compatible storage. - Updated dependencies for AWS SDK to support new features. - Refactored upload logic to accommodate both Bunny and S3 upload providers. - Updated documentation to clarify the usage of direct uploads and S3 configurations. - Closes #11
This commit is contained in:
@@ -10,7 +10,7 @@ import { logError } from '@/lib/logger';
|
||||
|
||||
const UNATTACHED_UPLOAD_TTL_MS = 15 * 60 * 1000;
|
||||
const CHUNK_SIZE = 500;
|
||||
const PREFIXES = ['images/', 'voice/'] as const;
|
||||
const PREFIXES = ['images/', 'voice/', 'videos/'] as const;
|
||||
|
||||
type CleanupCandidate = {
|
||||
key: string;
|
||||
@@ -33,6 +33,10 @@ function keyToProxyUrl(key: string): string | null {
|
||||
const filename = key.slice('voice/'.length);
|
||||
return filename ? `/api/upload/audio/${filename}` : null;
|
||||
}
|
||||
if (key.startsWith('videos/')) {
|
||||
const filename = key.slice('videos/'.length);
|
||||
return filename ? `/api/upload/video/${filename}` : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -93,31 +97,38 @@ async function findReferencedUrls(urls: string[]): Promise<Set<string>> {
|
||||
).userFeedbackScreenshot;
|
||||
|
||||
for (const group of chunk(urls, CHUNK_SIZE)) {
|
||||
const [commentRows, feedbackRows, feedbackAttachmentRows, assetRows] = await Promise.all([
|
||||
db.comment.findMany({
|
||||
where: {
|
||||
OR: [{ voiceUrl: { in: group } }, { imageUrl: { in: group } }],
|
||||
},
|
||||
select: {
|
||||
voiceUrl: true,
|
||||
imageUrl: true,
|
||||
},
|
||||
}),
|
||||
db.userFeedback.findMany({
|
||||
where: { screenshotUrl: { in: group } },
|
||||
select: { screenshotUrl: true },
|
||||
}),
|
||||
userFeedbackScreenshotDelegate
|
||||
? userFeedbackScreenshotDelegate.findMany({
|
||||
where: { url: { in: group } },
|
||||
select: { url: true },
|
||||
})
|
||||
: Promise.resolve([] as Array<{ url: string }>),
|
||||
db.videoAsset.findMany({
|
||||
where: { sourceUrl: { in: group } },
|
||||
select: { sourceUrl: true },
|
||||
}),
|
||||
]);
|
||||
const [commentRows, feedbackRows, feedbackAttachmentRows, assetRows, versionRows] =
|
||||
await Promise.all([
|
||||
db.comment.findMany({
|
||||
where: {
|
||||
OR: [{ voiceUrl: { in: group } }, { imageUrl: { in: group } }],
|
||||
},
|
||||
select: {
|
||||
voiceUrl: true,
|
||||
imageUrl: true,
|
||||
},
|
||||
}),
|
||||
db.userFeedback.findMany({
|
||||
where: { screenshotUrl: { in: group } },
|
||||
select: { screenshotUrl: true },
|
||||
}),
|
||||
userFeedbackScreenshotDelegate
|
||||
? userFeedbackScreenshotDelegate.findMany({
|
||||
where: { url: { in: group } },
|
||||
select: { url: true },
|
||||
})
|
||||
: Promise.resolve([] as Array<{ url: string }>),
|
||||
db.videoAsset.findMany({
|
||||
where: { sourceUrl: { in: group } },
|
||||
select: { sourceUrl: true },
|
||||
}),
|
||||
db.videoVersion.findMany({
|
||||
where: {
|
||||
OR: [{ originalUrl: { in: group } }, { thumbnailUrl: { in: group } }],
|
||||
},
|
||||
select: { originalUrl: true, thumbnailUrl: true },
|
||||
}),
|
||||
]);
|
||||
|
||||
for (const row of commentRows) {
|
||||
if (row.voiceUrl) referenced.add(row.voiceUrl);
|
||||
@@ -132,6 +143,10 @@ async function findReferencedUrls(urls: string[]): Promise<Set<string>> {
|
||||
for (const row of assetRows) {
|
||||
if (row.sourceUrl) referenced.add(row.sourceUrl);
|
||||
}
|
||||
for (const row of versionRows) {
|
||||
if (row.originalUrl) referenced.add(row.originalUrl);
|
||||
if (row.thumbnailUrl) referenced.add(row.thumbnailUrl);
|
||||
}
|
||||
}
|
||||
|
||||
return referenced;
|
||||
|
||||
Reference in New Issue
Block a user