playlist skipping
This commit is contained in:
parent
702ef6cb3e
commit
cd4237dcbe
56
init.ts
56
init.ts
|
|
@ -17,6 +17,8 @@ import {
|
||||||
initYtdlp,
|
initYtdlp,
|
||||||
setProgressCallback,
|
setProgressCallback,
|
||||||
setTrackReadyCallback,
|
setTrackReadyCallback,
|
||||||
|
skipSlowQueueItem,
|
||||||
|
getQueuedSlowItems,
|
||||||
type QueueItem,
|
type QueueItem,
|
||||||
} from "./ytdlp";
|
} from "./ytdlp";
|
||||||
|
|
||||||
|
|
@ -206,6 +208,60 @@ export async function init(): Promise<void> {
|
||||||
library.logActivity("scan_updated", { id: track.id, filename: track.filename, title: track.title });
|
library.logActivity("scan_updated", { id: track.id, filename: track.filename, title: track.title });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Prescan slow queue to find tracks already in library
|
||||||
|
function prescanSlowQueue() {
|
||||||
|
const queuedItems = getQueuedSlowItems();
|
||||||
|
if (queuedItems.length === 0) return;
|
||||||
|
|
||||||
|
const tracks = library.getAllTracks();
|
||||||
|
if (tracks.length === 0) return;
|
||||||
|
|
||||||
|
for (const item of queuedItems) {
|
||||||
|
const itemTitle = normalizeForMatch(item.title);
|
||||||
|
|
||||||
|
// Check if any library track matches
|
||||||
|
for (const track of tracks) {
|
||||||
|
const trackTitle = normalizeForMatch(track.title || "");
|
||||||
|
const trackFilename = normalizeForMatch((track.filename || "").replace(/\.[^.]+$/, ""));
|
||||||
|
|
||||||
|
const matches =
|
||||||
|
(trackTitle && trackTitle === itemTitle) ||
|
||||||
|
(trackFilename && trackFilename === itemTitle) ||
|
||||||
|
(trackTitle && itemTitle && trackTitle.includes(itemTitle)) ||
|
||||||
|
(trackTitle && itemTitle && itemTitle.includes(trackTitle)) ||
|
||||||
|
(trackFilename && itemTitle && trackFilename.includes(itemTitle)) ||
|
||||||
|
(trackFilename && itemTitle && itemTitle.includes(trackFilename));
|
||||||
|
|
||||||
|
if (matches) {
|
||||||
|
console.log(`[ytdlp] Prescan: "${item.title}" already exists as "${track.title || track.filename}"`);
|
||||||
|
|
||||||
|
// Skip download and add to playlist
|
||||||
|
const skipped = skipSlowQueueItem(item.id, track.id);
|
||||||
|
if (skipped && skipped.playlistId) {
|
||||||
|
try {
|
||||||
|
addTracksToPlaylist(skipped.playlistId, [track.id]);
|
||||||
|
sendToUser(skipped.userId, {
|
||||||
|
type: "toast",
|
||||||
|
message: `Already in library, added to: ${skipped.playlistName}`,
|
||||||
|
toastType: "info"
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[ytdlp] Failed to add existing track to playlist:`, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run prescan periodically (every 30 seconds)
|
||||||
|
setInterval(prescanSlowQueue, 30000);
|
||||||
|
// Also run once after initial scan completes
|
||||||
|
library.onScanComplete(() => {
|
||||||
|
setTimeout(prescanSlowQueue, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
// Load channels from database
|
// Load channels from database
|
||||||
const savedChannels = loadAllChannels();
|
const savedChannels = loadAllChannels();
|
||||||
let hasDefault = false;
|
let hasDefault = false;
|
||||||
|
|
|
||||||
|
|
@ -760,6 +760,7 @@
|
||||||
else if (res.ok) {
|
else if (res.ok) {
|
||||||
M.showToast("Removed");
|
M.showToast("Removed");
|
||||||
clearSelection();
|
clearSelection();
|
||||||
|
render();
|
||||||
} else {
|
} else {
|
||||||
M.showToast("Failed to remove from queue", "error");
|
M.showToast("Failed to remove from queue", "error");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
30
ytdlp.ts
30
ytdlp.ts
|
|
@ -525,6 +525,36 @@ function notifyProgress(item: QueueItem): void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark a slow queue item as skipped (already in library)
|
||||||
|
export function skipSlowQueueItem(id: string, trackId: string): QueueItem | null {
|
||||||
|
const item = slowQueue.find(i => i.id === id && i.status === "queued");
|
||||||
|
if (!item) return null;
|
||||||
|
|
||||||
|
item.status = "complete";
|
||||||
|
item.progress = 100;
|
||||||
|
item.completedAt = Date.now();
|
||||||
|
item.trackId = trackId;
|
||||||
|
|
||||||
|
// Update database
|
||||||
|
updateSlowQueueItem(id, {
|
||||||
|
status: "complete",
|
||||||
|
progress: 100,
|
||||||
|
completedAt: Math.floor(item.completedAt / 1000)
|
||||||
|
});
|
||||||
|
|
||||||
|
notifyProgress(item);
|
||||||
|
|
||||||
|
// Remove from queue after brief delay
|
||||||
|
setTimeout(() => removeFromQueue(item), 1000);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get queued items from slow queue (for prescan)
|
||||||
|
export function getQueuedSlowItems(): QueueItem[] {
|
||||||
|
return slowQueue.filter(i => i.status === "queued");
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup old completed/failed items
|
// Cleanup old completed/failed items
|
||||||
export function cleanupOldItems(maxAge: number = 3600000): void {
|
export function cleanupOldItems(maxAge: number = 3600000): void {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue