server/database/entities/Attachment.ts

122 lines
4.4 KiB
TypeScript
Raw Normal View History

import { proxyUrl } from "@/response";
import type { EntityValidator } from "@lysand-org/federation";
2024-04-07 07:30:49 +02:00
import type { Config } from "config-manager";
import type { InferSelectModel } from "drizzle-orm";
import { MediaBackendType } from "media-manager";
import { db } from "~/drizzle/db";
import { Attachments } from "~/drizzle/schema";
import type { AsyncAttachment as APIAsyncAttachment } from "~/types/mastodon/async_attachment";
import type { Attachment as APIAttachment } from "~/types/mastodon/attachment";
export type Attachment = InferSelectModel<typeof Attachments>;
2023-11-22 01:56:58 +01:00
export const attachmentToAPI = (
2024-04-07 07:30:49 +02:00
attachment: Attachment,
2023-11-22 01:56:58 +01:00
): APIAsyncAttachment | APIAttachment => {
2024-04-07 07:30:49 +02:00
let type = "unknown";
2023-11-22 01:56:58 +01:00
if (attachment.mimeType.startsWith("image/")) {
2024-04-07 07:30:49 +02:00
type = "image";
} else if (attachment.mimeType.startsWith("video/")) {
2024-04-07 07:30:49 +02:00
type = "video";
} else if (attachment.mimeType.startsWith("audio/")) {
2024-04-07 07:30:49 +02:00
type = "audio";
}
2023-11-22 01:56:58 +01:00
2024-04-07 07:30:49 +02:00
return {
id: attachment.id,
type: type as "image" | "video" | "audio" | "unknown",
url: proxyUrl(attachment.url) ?? "",
remote_url: proxyUrl(attachment.remoteUrl),
preview_url: proxyUrl(attachment.thumbnailUrl || attachment.url),
2024-04-07 07:30:49 +02:00
text_url: null,
meta: {
width: attachment.width || undefined,
height: attachment.height || undefined,
fps: attachment.fps || undefined,
size:
attachment.width && attachment.height
? `${attachment.width}x${attachment.height}`
: undefined,
duration: attachment.duration || undefined,
length: attachment.size?.toString() || undefined,
aspect:
attachment.width && attachment.height
? attachment.width / attachment.height
: undefined,
original: {
width: attachment.width || undefined,
height: attachment.height || undefined,
size:
attachment.width && attachment.height
? `${attachment.width}x${attachment.height}`
: undefined,
aspect:
attachment.width && attachment.height
? attachment.width / attachment.height
: undefined,
},
// Idk whether size or length is the right value
},
description: attachment.description,
blurhash: attachment.blurhash,
};
2023-11-22 01:56:58 +01:00
};
export const attachmentToLysand = (
attachment: Attachment,
): typeof EntityValidator.$ContentFormat => {
return {
[attachment.mimeType]: {
content: attachment.url,
blurhash: attachment.blurhash ?? undefined,
description: attachment.description ?? undefined,
duration: attachment.duration ?? undefined,
fps: attachment.fps ?? undefined,
height: attachment.height ?? undefined,
size: attachment.size ?? undefined,
hash: attachment.sha256
? {
sha256: attachment.sha256,
}
: undefined,
width: attachment.width ?? undefined,
},
};
};
export const attachmentFromLysand = async (
attachmentToConvert: typeof EntityValidator.$ContentFormat,
): Promise<InferSelectModel<typeof Attachments>> => {
const key = Object.keys(attachmentToConvert)[0];
const value = attachmentToConvert[key];
const result = await db
.insert(Attachments)
.values({
mimeType: key,
url: value.content,
description: value.description || undefined,
duration: value.duration || undefined,
fps: value.fps || undefined,
height: value.height || undefined,
size: value.size || undefined,
width: value.width || undefined,
sha256: value.hash?.sha256 || undefined,
blurhash: value.blurhash || undefined,
})
.returning();
return result[0];
};
2024-04-07 07:30:49 +02:00
export const getUrl = (name: string, config: Config) => {
if (config.media.backend === MediaBackendType.LOCAL) {
2024-04-08 05:28:18 +02:00
return new URL(`/media/${name}`, config.http.base_url).toString();
2024-04-07 07:30:49 +02:00
}
if (config.media.backend === MediaBackendType.S3) {
2024-04-08 05:28:18 +02:00
return new URL(`/${name}`, config.s3.public_url).toString();
2024-04-07 07:30:49 +02:00
}
return "";
2023-11-22 01:56:58 +01:00
};