mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-10 10:11:46 +00:00
allow downloading playlists from popup menu
This commit is contained in:
@ -14,87 +14,21 @@ let downloadLabel = defaultMenuDownloadLabel;
|
||||
let playingPlaylistId = undefined;
|
||||
let callbackIsRegistered = false;
|
||||
|
||||
const INVALID_PLAYLIST_MODIFIER = 'RDAMPLPL';
|
||||
|
||||
module.exports = (win, options) => {
|
||||
if (!callbackIsRegistered) {
|
||||
ipcMain.on("video-src-changed", async (_, data) => {
|
||||
playingPlaylistId = JSON.parse(data)?.videoDetails?.playlistId;
|
||||
});
|
||||
ipcMain.on("download-playlist-request", async (_event, url) => downloadPlaylist(url, win, options));
|
||||
callbackIsRegistered = true;
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
label: downloadLabel,
|
||||
click: async () => {
|
||||
const currentPagePlaylistId = new URL(win.webContents.getURL()).searchParams.get("list");
|
||||
const playlistId = currentPagePlaylistId || playingPlaylistId;
|
||||
if (!playlistId) {
|
||||
sendError(win, new Error("No playlist ID found"));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`trying to get playlist ID: '${playlistId}'`);
|
||||
let playlist;
|
||||
try {
|
||||
playlist = await ytpl(playlistId, {
|
||||
limit: options.playlistMaxItems || Infinity,
|
||||
});
|
||||
} catch (e) {
|
||||
sendError(win, e);
|
||||
return;
|
||||
}
|
||||
const playlistTitle = playlist.title;
|
||||
|
||||
const folder = getFolder(options.downloadFolder);
|
||||
const playlistFolder = join(folder, playlistTitle);
|
||||
if (existsSync(playlistFolder)) {
|
||||
sendError(
|
||||
win,
|
||||
new Error(`The folder ${playlistFolder} already exists`)
|
||||
);
|
||||
return;
|
||||
}
|
||||
mkdirSync(playlistFolder, { recursive: true });
|
||||
|
||||
dialog.showMessageBox({
|
||||
type: "info",
|
||||
buttons: ["OK"],
|
||||
title: "Started Download",
|
||||
message: `Downloading Playlist "${playlistTitle}"`,
|
||||
detail: `(${playlist.items.length} songs)`,
|
||||
});
|
||||
|
||||
if (is.dev()) {
|
||||
console.log(
|
||||
`Downloading playlist "${playlistTitle}" (${playlist.items.length} songs)`
|
||||
);
|
||||
}
|
||||
|
||||
const steps = 1 / playlist.items.length;
|
||||
let progress = 0;
|
||||
|
||||
win.setProgressBar(2); // starts with indefinite bar
|
||||
|
||||
let dirWatcher = chokidar.watch(playlistFolder);
|
||||
dirWatcher.on('add', () => {
|
||||
progress += steps;
|
||||
if (progress >= 0.9999) {
|
||||
win.setProgressBar(-1); // close progress bar
|
||||
dirWatcher.close().then(() => dirWatcher = null);
|
||||
} else {
|
||||
win.setProgressBar(progress);
|
||||
}
|
||||
});
|
||||
|
||||
playlist.items.forEach((song) => {
|
||||
win.webContents.send(
|
||||
"downloader-download-playlist",
|
||||
song.url,
|
||||
playlistTitle,
|
||||
options
|
||||
);
|
||||
});
|
||||
},
|
||||
click: () => downloadPlaylist(undefined, win, options)
|
||||
},
|
||||
{
|
||||
label: "Choose download folder",
|
||||
@ -123,3 +57,87 @@ module.exports = (win, options) => {
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
async function downloadPlaylist(url, win, options) {
|
||||
const getPlaylistID = aURL => {
|
||||
const result = aURL?.searchParams.get("list") || aURL?.searchParams.get("playlist");
|
||||
return (!result || result.startsWith(INVALID_PLAYLIST_MODIFIER)) ? undefined : result;
|
||||
};
|
||||
if (url) {
|
||||
try {
|
||||
url = new URL(url);
|
||||
} catch {
|
||||
url = undefined;
|
||||
};
|
||||
}
|
||||
const playlistId = getPlaylistID(url)
|
||||
|| getPlaylistID(new URL(win.webContents.getURL()))
|
||||
|| playingPlaylistId;
|
||||
|
||||
if (!playlistId) {
|
||||
sendError(win, new Error("No playlist ID found"));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`trying to get playlist ID: '${playlistId}'`);
|
||||
let playlist;
|
||||
try {
|
||||
playlist = await ytpl(playlistId, {
|
||||
limit: options.playlistMaxItems || Infinity,
|
||||
});
|
||||
} catch (e) {
|
||||
sendError(win, e);
|
||||
return;
|
||||
}
|
||||
const playlistTitle = playlist.title;
|
||||
|
||||
const folder = getFolder(options.downloadFolder);
|
||||
const playlistFolder = join(folder, playlistTitle);
|
||||
if (existsSync(playlistFolder)) {
|
||||
sendError(
|
||||
win,
|
||||
new Error(`The folder ${playlistFolder} already exists`)
|
||||
);
|
||||
return;
|
||||
}
|
||||
mkdirSync(playlistFolder, { recursive: true });
|
||||
|
||||
dialog.showMessageBox({
|
||||
type: "info",
|
||||
buttons: ["OK"],
|
||||
title: "Started Download",
|
||||
message: `Downloading Playlist "${playlistTitle}"`,
|
||||
detail: `(${playlist.items.length} songs)`,
|
||||
});
|
||||
|
||||
if (is.dev()) {
|
||||
console.log(
|
||||
`Downloading playlist "${playlistTitle}" - ${playlist.items.length} songs (${playlistId})`
|
||||
);
|
||||
}
|
||||
|
||||
const steps = 1 / playlist.items.length;
|
||||
let progress = 0;
|
||||
|
||||
win.setProgressBar(2); // starts with indefinite bar
|
||||
|
||||
let dirWatcher = chokidar.watch(playlistFolder);
|
||||
dirWatcher.on('add', () => {
|
||||
progress += steps;
|
||||
if (progress >= 0.9999) {
|
||||
win.setProgressBar(-1); // close progress bar
|
||||
dirWatcher.close().then(() => dirWatcher = null);
|
||||
} else {
|
||||
win.setProgressBar(progress);
|
||||
}
|
||||
});
|
||||
|
||||
playlist.items.forEach((song) => {
|
||||
win.webContents.send(
|
||||
"downloader-download-playlist",
|
||||
song.url,
|
||||
playlistTitle,
|
||||
options
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user