feat(models): mounts/media_items/playback_progress/danmaku_cache
This commit is contained in:
parent
3143a9c7d0
commit
f94aabe8a5
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { sql } from "drizzle-orm";
|
||||||
|
import { integer, sqliteTable, text, uniqueIndex } from "drizzle-orm/sqlite-core";
|
||||||
|
|
||||||
|
export const danmakuCache = sqliteTable(
|
||||||
|
"danmaku_cache",
|
||||||
|
{
|
||||||
|
id: text("id")
|
||||||
|
.primaryKey()
|
||||||
|
.$defaultFn(() => crypto.randomUUID()),
|
||||||
|
matchKey: text("match_key").notNull(),
|
||||||
|
payload: text("payload").notNull(),
|
||||||
|
source: text("source").notNull().default("open-network"),
|
||||||
|
expiresAt: integer("expires_at", { mode: "timestamp" }),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp" })
|
||||||
|
.notNull()
|
||||||
|
.default(sql`(unixepoch())`),
|
||||||
|
},
|
||||||
|
(t) => [uniqueIndex("danmaku_match_key_uq").on(t.matchKey)],
|
||||||
|
);
|
||||||
|
export type DanmakuCacheRow = typeof danmakuCache.$inferSelect;
|
||||||
|
|
@ -5,3 +5,11 @@ export { sessions } from "./sessions.js";
|
||||||
export type { Session, NewSession } from "./sessions.js";
|
export type { Session, NewSession } from "./sessions.js";
|
||||||
export { passwordResets } from "./password-resets.js";
|
export { passwordResets } from "./password-resets.js";
|
||||||
export type { PasswordReset, NewPasswordReset } from "./password-resets.js";
|
export type { PasswordReset, NewPasswordReset } from "./password-resets.js";
|
||||||
|
export { mounts } from "./mounts.js";
|
||||||
|
export type { Mount, NewMount } from "./mounts.js";
|
||||||
|
export { mediaItems } from "./media-items.js";
|
||||||
|
export type { MediaItem, NewMediaItem } from "./media-items.js";
|
||||||
|
export { playbackProgress } from "./playback-progress.js";
|
||||||
|
export type { PlaybackProgress } from "./playback-progress.js";
|
||||||
|
export { danmakuCache } from "./danmaku-cache.js";
|
||||||
|
export type { DanmakuCacheRow } from "./danmaku-cache.js";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { sql } from "drizzle-orm";
|
||||||
|
import { integer, sqliteTable, text, uniqueIndex } from "drizzle-orm/sqlite-core";
|
||||||
|
import { users } from "./users.js";
|
||||||
|
import { mounts } from "./mounts.js";
|
||||||
|
|
||||||
|
export const mediaItems = sqliteTable(
|
||||||
|
"media_items",
|
||||||
|
{
|
||||||
|
id: text("id")
|
||||||
|
.primaryKey()
|
||||||
|
.$defaultFn(() => crypto.randomUUID()),
|
||||||
|
userId: text("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => users.id, { onDelete: "cascade" }),
|
||||||
|
mountId: text("mount_id").references(() => mounts.id, { onDelete: "set null" }),
|
||||||
|
path: text("path").notNull(),
|
||||||
|
rawName: text("raw_name").notNull(),
|
||||||
|
title: text("title").notNull(),
|
||||||
|
size: integer("size").notNull().default(0),
|
||||||
|
mime: text("mime"),
|
||||||
|
bangumiId: integer("bangumi_id"),
|
||||||
|
epNumber: integer("ep_number"),
|
||||||
|
scrapeStatus: text("scrape_status").notNull().default("pending"),
|
||||||
|
scrapedAt: integer("scraped_at", { mode: "timestamp" }),
|
||||||
|
posterUrl: text("poster_url"),
|
||||||
|
matchedHash: text("matched_hash"),
|
||||||
|
scannedAt: integer("scanned_at", { mode: "timestamp" })
|
||||||
|
.notNull()
|
||||||
|
.default(sql`(unixepoch())`),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
||||||
|
.notNull()
|
||||||
|
.default(sql`(unixepoch())`),
|
||||||
|
},
|
||||||
|
(t) => [uniqueIndex("media_user_path_uq").on(t.userId, t.path)],
|
||||||
|
);
|
||||||
|
export type MediaItem = typeof mediaItems.$inferSelect;
|
||||||
|
export type NewMediaItem = typeof mediaItems.$inferInsert;
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { sql } from "drizzle-orm";
|
||||||
|
import { integer, sqliteTable, text, uniqueIndex } from "drizzle-orm/sqlite-core";
|
||||||
|
import { users } from "./users.js";
|
||||||
|
|
||||||
|
export const mounts = sqliteTable(
|
||||||
|
"mounts",
|
||||||
|
{
|
||||||
|
id: text("id")
|
||||||
|
.primaryKey()
|
||||||
|
.$defaultFn(() => crypto.randomUUID()),
|
||||||
|
userId: text("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => users.id, { onDelete: "cascade" }),
|
||||||
|
name: text("name").notNull(),
|
||||||
|
type: text("type").notNull().default("webdav"),
|
||||||
|
baseUrl: text("base_url").notNull(),
|
||||||
|
username: text("username"),
|
||||||
|
/** AES-GCM 密文(base64),永不回传前端 */
|
||||||
|
secretEnc: text("secret_enc").notNull().default(""),
|
||||||
|
rootPath: text("root_path").notNull().default("/"),
|
||||||
|
enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp" })
|
||||||
|
.notNull()
|
||||||
|
.default(sql`(unixepoch())`),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
||||||
|
.notNull()
|
||||||
|
.default(sql`(unixepoch())`),
|
||||||
|
},
|
||||||
|
(t) => [uniqueIndex("mounts_user_name_uq").on(t.userId, t.name)],
|
||||||
|
);
|
||||||
|
export type Mount = typeof mounts.$inferSelect;
|
||||||
|
export type NewMount = typeof mounts.$inferInsert;
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { sql } from "drizzle-orm";
|
||||||
|
import { integer, sqliteTable, text, uniqueIndex } from "drizzle-orm/sqlite-core";
|
||||||
|
import { users } from "./users.js";
|
||||||
|
import { mediaItems } from "./media-items.js";
|
||||||
|
|
||||||
|
export const playbackProgress = sqliteTable(
|
||||||
|
"playback_progress",
|
||||||
|
{
|
||||||
|
id: text("id")
|
||||||
|
.primaryKey()
|
||||||
|
.$defaultFn(() => crypto.randomUUID()),
|
||||||
|
userId: text("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => users.id, { onDelete: "cascade" }),
|
||||||
|
mediaItemId: text("media_item_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => mediaItems.id, { onDelete: "cascade" }),
|
||||||
|
positionMs: integer("position_ms").notNull().default(0),
|
||||||
|
durationMs: integer("duration_ms").notNull().default(0),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
||||||
|
.notNull()
|
||||||
|
.default(sql`(unixepoch())`),
|
||||||
|
},
|
||||||
|
(t) => [uniqueIndex("progress_user_media_uq").on(t.userId, t.mediaItemId)],
|
||||||
|
);
|
||||||
|
export type PlaybackProgress = typeof playbackProgress.$inferSelect;
|
||||||
Loading…
Reference in New Issue