import { sqliteTable, text, integer, real } from 'drizzle-orm/sqlite-core'; import { sql } from 'drizzle-orm'; import { channels } from './channels'; /** Individual content items (videos, audio tracks, livestreams). */ export const contentItems = sqliteTable('content_items', { id: integer('id').primaryKey({ autoIncrement: true }), channelId: integer('channel_id') .references(() => channels.id, { onDelete: 'cascade' }), title: text('title').notNull(), platformContentId: text('platform_content_id').notNull(), url: text('url').notNull(), contentType: text('content_type').notNull(), // 'video' | 'audio' | 'livestream' duration: integer('duration'), // seconds filePath: text('file_path'), fileSize: integer('file_size'), // bytes format: text('format'), // container format e.g. 'mp4', 'webm', 'mp3' qualityMetadata: text('quality_metadata', { mode: 'json' }), // actual quality info post-download status: text('status').notNull().default('monitored'), // monitored|queued|downloading|downloaded|failed|ignored thumbnailUrl: text('thumbnail_url'), publishedAt: text('published_at'), // ISO datetime from platform (nullable) downloadedAt: text('downloaded_at'), // ISO datetime when download completed (nullable) monitored: integer('monitored', { mode: 'boolean' }).notNull().default(true), // per-item monitoring toggle createdAt: text('created_at') .notNull() .default(sql`(datetime('now'))`), updatedAt: text('updated_at') .notNull() .default(sql`(datetime('now'))`), }); /** Format profiles defining preferred download quality/format settings. */ export const formatProfiles = sqliteTable('format_profiles', { id: integer('id').primaryKey({ autoIncrement: true }), name: text('name').notNull(), videoResolution: text('video_resolution'), // e.g. '1080p', '720p', 'best' audioCodec: text('audio_codec'), // e.g. 'opus', 'aac', 'mp3' audioBitrate: text('audio_bitrate'), // e.g. '320k', '192k' containerFormat: text('container_format'), // e.g. 'mp4', 'mkv', 'mp3' isDefault: integer('is_default', { mode: 'boolean' }).notNull().default(false), subtitleLanguages: text('subtitle_languages'), embedSubtitles: integer('embed_subtitles', { mode: 'boolean' }).notNull().default(false), embedChapters: integer('embed_chapters', { mode: 'boolean' }).notNull().default(false), embedThumbnail: integer('embed_thumbnail', { mode: 'boolean' }).notNull().default(false), sponsorBlockRemove: text('sponsor_block_remove'), // comma-separated categories: 'sponsor,selfpromo,interaction,intro,outro,preview,music_offtopic,filler' createdAt: text('created_at') .notNull() .default(sql`(datetime('now'))`), updatedAt: text('updated_at') .notNull() .default(sql`(datetime('now'))`), });