diff --git a/backend/src/controllers/videos.controller.ts b/backend/src/controllers/videos.controller.ts index 3f84f0d..a6e3e2c 100644 --- a/backend/src/controllers/videos.controller.ts +++ b/backend/src/controllers/videos.controller.ts @@ -17,7 +17,7 @@ export async function getAllVideos(req: AuthRequest, res: Response) { console.log('[CONTROLLER] pageNum:', pageNum, 'limitNum:', limitNum, 'offset:', offset); // Build query - let whereClause = '1=1'; + let whereClause = 'v.duration_seconds >= 600'; const args: any[] = []; if (channelId) { diff --git a/backend/src/db/migrate.ts b/backend/src/db/migrate.ts index 6b63512..93a43be 100644 --- a/backend/src/db/migrate.ts +++ b/backend/src/db/migrate.ts @@ -1,4 +1,5 @@ import { db } from '../config/database.js'; +import { isoDurationToSeconds } from '../utils/duration.js'; const migrations = [ { @@ -96,6 +97,44 @@ const migrations = [ await db.execute(`INSERT OR IGNORE INTO settings (key, value) VALUES ('initial_setup_complete', 'false')`); await db.execute(`INSERT OR IGNORE INTO settings (key, value) VALUES ('refresh_in_progress', 'false')`); } + }, + { + id: 2, + name: 'add_duration_seconds', + up: async () => { + const columnCheck = await db.execute(` + SELECT 1 FROM pragma_table_info('videos_cache') + WHERE name = 'duration_seconds' + `); + + if (!columnCheck.rows.length) { + await db.execute(` + ALTER TABLE videos_cache + ADD COLUMN duration_seconds INTEGER DEFAULT 0 + `); + } + + const videos = await db.execute(` + SELECT id, duration + FROM videos_cache + `); + + for (const row of videos.rows) { + const duration = row.duration as string | null; + const seconds = duration ? isoDurationToSeconds(duration) : 0; + await db.execute({ + sql: `UPDATE videos_cache + SET duration_seconds = ? + WHERE id = ?`, + args: [seconds, row.id] + }); + } + + await db.execute(` + CREATE INDEX IF NOT EXISTS idx_videos_duration_seconds + ON videos_cache(duration_seconds) + `); + } } ]; diff --git a/backend/src/services/cache.service.ts b/backend/src/services/cache.service.ts index 414aa8a..c0e05b1 100644 --- a/backend/src/services/cache.service.ts +++ b/backend/src/services/cache.service.ts @@ -1,5 +1,6 @@ import { db, getSetting, setSetting } from '../config/database.js'; import { fetchChannelVideos } from './youtube.service.js'; +import { isoDurationToSeconds } from '../utils/duration.js'; export async function isRefreshInProgress(): Promise { const value = await getSetting('refresh_in_progress'); @@ -38,15 +39,16 @@ async function updateVideoCache(channelId: string, videos: any[]) { // Insert new videos for (const video of videos) { + const durationSeconds = isoDurationToSeconds(video.duration); await db.execute({ sql: `INSERT INTO videos_cache (id, channel_id, title, description, thumbnail_url, - published_at, view_count, like_count, duration) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, + published_at, view_count, like_count, duration, duration_seconds) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, args: [ video.id, channelId, video.title, video.description, video.thumbnailUrl, video.publishedAt, video.viewCount, - video.likeCount, video.duration + video.likeCount, video.duration, durationSeconds ] }); } diff --git a/backend/src/utils/duration.ts b/backend/src/utils/duration.ts new file mode 100644 index 0000000..bf17f8a --- /dev/null +++ b/backend/src/utils/duration.ts @@ -0,0 +1,18 @@ +export function isoDurationToSeconds(isoDuration: string): number { + if (!isoDuration) { + return 0; + } + + const match = isoDuration.match(/PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?/); + if (!match) { + return 0; + } + + const hours = parseInt(match[1] || '0', 10); + const minutes = parseInt(match[2] || '0', 10); + const seconds = parseInt(match[3] || '0', 10); + + return hours * 3600 + minutes * 60 + seconds; +} + +