chore: update Angular cache files and TypeScript build info

This commit is contained in:
2025-09-17 21:27:20 -04:00
parent 3dbfb04b15
commit f3a78b7d7e
12 changed files with 60 additions and 19 deletions
+11 -4
View File
@@ -279,11 +279,17 @@ function ensureTag(userId, name) {
return id;
}
export function likeVideo({ userId, provider, videoId }) {
export function likeVideo({ userId, provider, videoId, title, thumbnail }) {
const tagId = ensureTag(userId, 'like');
// Upsert-like behavior; ignore if exists
db.prepare(`INSERT OR IGNORE INTO video_tags (user_id, provider, video_id, tag_id) VALUES (?, ?, ?, ?)`)
.run(userId, provider, videoId, tagId);
db.prepare(`INSERT OR IGNORE INTO video_tags (user_id, provider, video_id, tag_id, created_at) VALUES (?, ?, ?, ?, ?)`)
.run(userId, provider, videoId, tagId, nowIso());
// Also update the watch_history table with the title and thumbnail
if (title || thumbnail) {
upsertWatchHistory({ userId, provider, videoId, title, thumbnail });
}
return { provider, video_id: videoId };
}
@@ -350,6 +356,7 @@ export function listLikedVideos({ userId, limit = 100, q }) {
SELECT
vt.provider,
vt.video_id,
vt.created_at,
COALESCE(wh.title, '') AS title,
COALESCE(wh.thumbnail, '') AS thumbnail,
wh.last_watched_at AS last_watched_at
@@ -361,7 +368,7 @@ export function listLikedVideos({ userId, limit = 100, q }) {
WHERE vt.user_id = ? AND vt.tag_id = ?
`;
const orderLimit = `
ORDER BY COALESCE(wh.last_watched_at, wh.watched_at) DESC
ORDER BY vt.created_at DESC
LIMIT ?
`;
const query = hasQ
+29 -3
View File
@@ -1058,10 +1058,36 @@ r.get('/user/likes', authMiddleware, (req, res) => {
return res.json(rows);
});
r.post('/user/likes', authMiddleware, (req, res) => {
const { provider, videoId } = req.body || {};
r.post('/user/likes', authMiddleware, async (req, res) => {
let { provider, videoId, title, thumbnail } = req.body || {};
try {
console.log('[POST /user/likes] payload:', {
provider,
videoId,
titlePreview: typeof title === 'string' ? title.slice(0, 80) : title,
hasThumbnail: Boolean(thumbnail)
});
} catch {}
if (!provider || !videoId) return res.status(400).json({ error: 'provider and videoId are required' });
const row = likeVideo({ userId: req.user.id, provider, videoId });
// Server-side enrichment: if title or thumbnail is missing, fetch minimal details via yt-dlp
try {
const needTitle = !(typeof title === 'string' && title.trim().length > 0);
const needThumb = !(typeof thumbnail === 'string' && thumbnail.trim().length > 0);
if (needTitle || needThumb) {
const url = providerUrlFrom(provider, videoId, { instance: req.query.instance, slug: req.query.slug, sourceUrl: req.query.sourceUrl });
try {
const raw = await youtubedl(url, { dumpSingleJson: true, noWarnings: true, noCheckCertificates: true, skipDownload: true });
const meta = (typeof raw === 'string') ? JSON.parse(raw || '{}') : (raw || {});
if (needTitle) title = meta?.title || title || '';
if (needThumb) thumbnail = meta?.thumbnail || (Array.isArray(meta?.thumbnails) && meta.thumbnails.length ? meta.thumbnails[0].url : thumbnail || '');
} catch (e) {
console.warn('[POST /user/likes] details fetch failed, continuing without enrichment:', e?.message || e);
}
}
} catch {}
const row = likeVideo({ userId: req.user.id, provider, videoId, title, thumbnail });
return res.status(201).json(row);
});