server/database/entities/Attachment.ts

121 lines
4.2 KiB
TypeScript
Raw Normal View History

2024-04-07 07:30:49 +02:00
import type { Config } from "config-manager";
import type { InferSelectModel } from "drizzle-orm";
import type * as Lysand from "lysand-types";
import { MediaBackendType } from "media-manager";
import { db } from "~drizzle/db";
import { attachment } from "~drizzle/schema";
2024-04-14 12:53:21 +02:00
import type { AsyncAttachment as APIAsyncAttachment } from "~types/mastodon/async_attachment";
import type { Attachment as APIAttachment } from "~types/mastodon/attachment";
export type Attachment = InferSelectModel<typeof attachment>;
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: attachment.url,
remote_url: attachment.remoteUrl,
preview_url: 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,
): Lysand.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: Lysand.ContentFormat,
): Promise<InferSelectModel<typeof attachment>> => {
const key = Object.keys(attachmentToConvert)[0];
const value = attachmentToConvert[key];
const result = await db
.insert(attachment)
.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
};