86 lines
2.3 KiB
TypeScript
86 lines
2.3 KiB
TypeScript
import { randomBytes } from "node:crypto";
|
|
import {
|
|
index,
|
|
pgSchema,
|
|
text,
|
|
timestamp,
|
|
} from "drizzle-orm/pg-core";
|
|
import { uuidv7 } from "uuidv7";
|
|
import { users } from "./account";
|
|
import { cdn } from "./form";
|
|
|
|
export const shareSchema = pgSchema("share");
|
|
|
|
export type ShareSource = "web" | "bot";
|
|
|
|
const SHARE_ID_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
|
|
export function createShareId() {
|
|
let id = "";
|
|
while (id.length < 8) {
|
|
for (const value of randomBytes(8)) {
|
|
if (value >= 252) continue;
|
|
id += SHARE_ID_ALPHABET[value % SHARE_ID_ALPHABET.length];
|
|
if (id.length === 8) break;
|
|
}
|
|
}
|
|
return id;
|
|
}
|
|
|
|
export const shareTexts = shareSchema.table(
|
|
"text",
|
|
{
|
|
id: text("id").primaryKey().$defaultFn(createShareId),
|
|
content: text("content").notNull(),
|
|
description: text("description"),
|
|
imageCdnId: text("image_cdn_id").references(() => cdn.id, {
|
|
onDelete: "set null",
|
|
}),
|
|
source: text("source").$type<ShareSource>().notNull(),
|
|
authorId: text("author_id").references(() => users.id, {
|
|
onDelete: "set null",
|
|
}),
|
|
authorDiscordId: text("author_discord_id").notNull(),
|
|
authorName: text("author_name").notNull(),
|
|
authorAvatarUrl: text("author_avatar_url"),
|
|
createdAt: timestamp("created_at", { mode: "date", withTimezone: true })
|
|
.defaultNow()
|
|
.notNull(),
|
|
},
|
|
(share) => [
|
|
index("share_text_author_created_idx").on(
|
|
share.authorDiscordId,
|
|
share.createdAt
|
|
),
|
|
]
|
|
);
|
|
|
|
export const shareComments = shareSchema.table(
|
|
"comment",
|
|
{
|
|
id: text("id")
|
|
.primaryKey()
|
|
.$defaultFn(() => uuidv7()),
|
|
shareId: text("share_id")
|
|
.notNull()
|
|
.references(() => shareTexts.id, { onDelete: "cascade" }),
|
|
body: text("body").notNull(),
|
|
authorId: text("author_id").references(() => users.id, {
|
|
onDelete: "set null",
|
|
}),
|
|
authorDiscordId: text("author_discord_id").notNull(),
|
|
authorName: text("author_name").notNull(),
|
|
authorAvatarUrl: text("author_avatar_url"),
|
|
createdAt: timestamp("created_at", { mode: "date", withTimezone: true })
|
|
.defaultNow()
|
|
.notNull(),
|
|
},
|
|
(comment) => [
|
|
index("share_comment_share_created_id_idx").on(
|
|
comment.shareId,
|
|
comment.createdAt,
|
|
comment.id
|
|
),
|
|
]
|
|
);
|