From 0632920a6ffa55923af31439e890a6a59efb4a32 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 10 Mar 2021 02:19:11 +0000 Subject: [PATCH 1/5] fix: upgrade @cliqz/adblocker-electron from 1.20.0 to 1.20.1 Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.20.0 to 1.20.1. See this package in npm: See this project in Snyk: https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr --- package.json | 2 +- yarn.lock | 62 ++++++++++++++++++++++++++-------------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index f5524a37..d5eb1933 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "npm": "Please use yarn and not npm" }, "dependencies": { - "@cliqz/adblocker-electron": "^1.20.0", + "@cliqz/adblocker-electron": "^1.20.1", "@ffmpeg/core": "^0.8.5", "@ffmpeg/ffmpeg": "^0.9.7", "YoutubeNonStop": "git://github.com/lawfx/YoutubeNonStop.git#v0.8.1", diff --git a/yarn.lock b/yarn.lock index f4ac5ed3..b5fe1e94 100644 --- a/yarn.lock +++ b/yarn.lock @@ -282,45 +282,45 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@cliqz/adblocker-content@^1.20.0": - version "1.20.0" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker-content/-/adblocker-content-1.20.0.tgz#fcfa2845a577ba8d9af282afbae2fc437b3f1c70" - integrity sha512-KcokmK2B+tAnVMi7nGHgzXUVf78wAODG1Uk+K3tBPf9VAo3mwldYZ472uTj6LUfZv5oeTwe4PwfmPWXWZy3Eew== +"@cliqz/adblocker-content@^1.20.3": + version "1.20.3" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker-content/-/adblocker-content-1.20.3.tgz#198c8719cd62ef3c67a5c98e7a54336b7812ed86" + integrity sha512-aCBTiIiNgVbmDIQyUcsn0j3n+umvs0DuVlL6dccPE3qfeFxT4whUvMwjxUS2/dIBfJK9A1LywmvVke2eSPw9wg== dependencies: - "@cliqz/adblocker-extended-selectors" "^1.20.0" + "@cliqz/adblocker-extended-selectors" "^1.20.3" -"@cliqz/adblocker-electron-preload@^1.20.0": - version "1.20.0" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron-preload/-/adblocker-electron-preload-1.20.0.tgz#997b694fbb1b1206e04b1fd570690234cc7ef630" - integrity sha512-brNQFjIoGTMClmFphtoK0EnjOlbqfxr6sA3CrOZiHfG0e07Id5GoU95re8+s8xA+/nd1GrJl/k5/b4aks+S9Gw== +"@cliqz/adblocker-electron-preload@^1.20.3": + version "1.20.3" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron-preload/-/adblocker-electron-preload-1.20.3.tgz#17dff446ad742cb6e68a4572e7a75cff1fa33f95" + integrity sha512-fWAFEGj+F0VOUKZd2FqWLuguXmGzkRQz5wTCqasvndX4HSe0P8Pd2666pWK9RJW1dLJE7U61mQfTbYqlUFVTMA== dependencies: - "@cliqz/adblocker-content" "^1.20.0" + "@cliqz/adblocker-content" "^1.20.3" -"@cliqz/adblocker-electron@^1.20.0": - version "1.20.0" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron/-/adblocker-electron-1.20.0.tgz#bacfb9feaf1d3dab339b992e3defa111a4b5ed3c" - integrity sha512-zD881g+YxxO4BM6NB5qZtSevg9Cj7QtlCJ4tkcKZnD9MDQsNXQVIFFEWwqhd00kLkTUS0+jT0px9b81cigAPNg== +"@cliqz/adblocker-electron@^1.20.1": + version "1.20.3" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron/-/adblocker-electron-1.20.3.tgz#f2b4bf5dddf90f64251c46f89238526dc0037384" + integrity sha512-ZcEl3W7R/aoUA0IPIMtvdn7gVE6O9+rDQ9OllIH/s/gVeElXZsgPEtpPMSuoJWbi9d2mlr8yo3UFvkV3u7c4gw== dependencies: - "@cliqz/adblocker" "^1.20.0" - "@cliqz/adblocker-electron-preload" "^1.20.0" + "@cliqz/adblocker" "^1.20.3" + "@cliqz/adblocker-electron-preload" "^1.20.3" tldts-experimental "^5.6.21" -"@cliqz/adblocker-extended-selectors@^1.20.0": - version "1.20.0" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker-extended-selectors/-/adblocker-extended-selectors-1.20.0.tgz#95ede657b670f627b39f92d85a97093cecee6ffe" - integrity sha512-dnBPIngGe1eDWvYX49eP2yyCE2AY1QD5E+8SaXW6lslnjS0GQnkcXCAkkGR2am4Qdk78HAiWTXL65Zt9hdkupA== +"@cliqz/adblocker-extended-selectors@^1.20.3": + version "1.20.3" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker-extended-selectors/-/adblocker-extended-selectors-1.20.3.tgz#a817915948ec4e64c8b878a80a71d911ea0412c8" + integrity sha512-Xsrqg4qgpNVx80UJrAz/nS8jcbgCTIGvir0MrjoXrw0GheqRxsgE540XXP9JA7QlifLNVEOO44DpHvhUmISkQw== -"@cliqz/adblocker@^1.20.0": - version "1.20.0" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker/-/adblocker-1.20.0.tgz#514746e9ee72fcd886f1e2e1aaf13b28fc63f232" - integrity sha512-lkEj0Pj1ikwMURrvoFv0YnLfaXFuJI+jexI7zdh4fDmlwRppzDDgOhPXgCczoAlYacJk5x2mf7pan6JybRD9Kw== +"@cliqz/adblocker@^1.20.3": + version "1.20.3" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker/-/adblocker-1.20.3.tgz#4e8d03ed03c476f7b4388d25f910b1b9e0b15cc9" + integrity sha512-Dqj8fJ399kFsFQ53uW0ajA5jH5VJ5ppawOjtoV2s+7NILj1ydvw40jTrr3l/ObMvxaAGaDUj2Euo4beg3/EtRQ== dependencies: - "@cliqz/adblocker-content" "^1.20.0" - "@cliqz/adblocker-extended-selectors" "^1.20.0" + "@cliqz/adblocker-content" "^1.20.3" + "@cliqz/adblocker-extended-selectors" "^1.20.3" "@remusao/guess-url-type" "^1.1.2" "@remusao/small" "^1.1.2" "@remusao/smaz" "^1.7.1" - "@types/chrome" "^0.0.128" + "@types/chrome" "^0.0.133" "@types/firefox-webext-browser" "^82.0.0" tldts-experimental "^5.6.21" @@ -1014,10 +1014,10 @@ "@types/node" "*" "@types/responselike" "*" -"@types/chrome@^0.0.128": - version "0.0.128" - resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.128.tgz#5dbd8b2539a367353fbe4386f119b510105f8b6a" - integrity sha512-eGc599TDtersMBW1cSnExHm0IHrXrO5xdk6Sa2Dq30ED+hR1rpT1ez0NNcCgvGO52nmktGfyvd3Uyquzv3LL4g== +"@types/chrome@^0.0.133": + version "0.0.133" + resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.133.tgz#9e1d55441584ba2d5274ca84db36427da9c5dc6e" + integrity sha512-G8uIUdaCTBILprQvQXBWGXZxjAWbkCkFQit17cdH3zYQEwU8f/etNl8+M7e8MRz9Xj8daHaVpysneMZMx8/ldQ== dependencies: "@types/filesystem" "*" "@types/har-format" "*" From 2fb4cbcf0239fac52b4b933a4aa73c99a90313d0 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Wed, 24 Mar 2021 19:38:45 +0200 Subject: [PATCH 2/5] move icons to 'assets' folder --- .../taskbar-mediacontrol/{ => assets}/backward.png | Bin .../taskbar-mediacontrol/{ => assets}/forward.png | Bin plugins/taskbar-mediacontrol/{ => assets}/pause.png | Bin plugins/taskbar-mediacontrol/{ => assets}/play.png | Bin plugins/taskbar-mediacontrol/back.js | 4 ++-- 5 files changed, 2 insertions(+), 2 deletions(-) rename plugins/taskbar-mediacontrol/{ => assets}/backward.png (100%) rename plugins/taskbar-mediacontrol/{ => assets}/forward.png (100%) rename plugins/taskbar-mediacontrol/{ => assets}/pause.png (100%) rename plugins/taskbar-mediacontrol/{ => assets}/play.png (100%) diff --git a/plugins/taskbar-mediacontrol/backward.png b/plugins/taskbar-mediacontrol/assets/backward.png similarity index 100% rename from plugins/taskbar-mediacontrol/backward.png rename to plugins/taskbar-mediacontrol/assets/backward.png diff --git a/plugins/taskbar-mediacontrol/forward.png b/plugins/taskbar-mediacontrol/assets/forward.png similarity index 100% rename from plugins/taskbar-mediacontrol/forward.png rename to plugins/taskbar-mediacontrol/assets/forward.png diff --git a/plugins/taskbar-mediacontrol/pause.png b/plugins/taskbar-mediacontrol/assets/pause.png similarity index 100% rename from plugins/taskbar-mediacontrol/pause.png rename to plugins/taskbar-mediacontrol/assets/pause.png diff --git a/plugins/taskbar-mediacontrol/play.png b/plugins/taskbar-mediacontrol/assets/play.png similarity index 100% rename from plugins/taskbar-mediacontrol/play.png rename to plugins/taskbar-mediacontrol/assets/play.png diff --git a/plugins/taskbar-mediacontrol/back.js b/plugins/taskbar-mediacontrol/back.js index 64ad6815..b4d7dd3c 100644 --- a/plugins/taskbar-mediacontrol/back.js +++ b/plugins/taskbar-mediacontrol/back.js @@ -53,6 +53,6 @@ module.exports = win => { }; // Util -function get(address) { - return path.join(__dirname, address); +function get(file) { + return path.join(__dirname,"assets", file); } From 9a95f435ad34f55534951e3d2e9f6a03472c8169 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Thu, 25 Mar 2021 01:02:42 +0200 Subject: [PATCH 3/5] merge source (#2) * Added Discord timeout * Add getOptions in plugin util * Mutex in ffmpeg conversion (only supports one command at a time) * Add menu customization in plugin system * Add ytpl package (playlist info) * Handle ffmpeg metadata flags when metadata is not present * Only use artist in file name if present * Export sendError method * Handle image not present in metadata util * Add downloader utils (getFolder and default menu label) * Pass (optional) existing metadata and subfolder in mp3 converter * Add listener to download playlist * Add custom menu in downloader plugin ("download playlist" item) * nit: fix main CSS style * Only set the "enable" item in menu if plugin not enabled * Navigation plugin: inject HTML once CSS is loaded Co-authored-by: Sem Visscher Co-authored-by: TC --- config/defaults.js | 4 ++ config/plugins.js | 5 ++ menu.js | 48 ++++++++++---- package.json | 4 +- plugins/discord/back.js | 10 ++- plugins/downloader/back.js | 25 ++++---- plugins/downloader/menu.js | 63 +++++++++++++++++++ plugins/downloader/utils.js | 4 ++ plugins/downloader/youtube-dl.js | 87 +++++++++++++++++++------- plugins/navigation/back.js | 5 +- plugins/navigation/front.js | 20 +++--- plugins/navigation/templates/back.html | 2 +- plugins/utils.js | 9 ++- yarn.lock | 21 ++++++- youtube-music.css | 2 +- 15 files changed, 248 insertions(+), 61 deletions(-) create mode 100644 plugins/downloader/menu.js create mode 100644 plugins/downloader/utils.js diff --git a/config/defaults.js b/config/defaults.js index 6238e114..855b1964 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -35,6 +35,10 @@ const defaultConfig = { ffmpegArgs: [], // e.g. ["-b:a", "192k"] for an audio bitrate of 192kb/s downloadFolder: undefined, // Custom download folder (absolute path) }, + discord: { + activityTimoutEnabled: true, // if enabled, the discord rich presence gets cleared when music paused after the time specified below + activityTimoutTime: 10 * 60 * 1000 // 10 minutes + }, }, }; diff --git a/config/plugins.js b/config/plugins.js index 03962c3d..7a73335c 100644 --- a/config/plugins.js +++ b/config/plugins.js @@ -24,6 +24,10 @@ function setOptions(plugin, options) { }); } +function getOptions(plugin) { + return store.get("plugins")[plugin]; +} + function enable(plugin) { setOptions(plugin, { enabled: true }); } @@ -38,4 +42,5 @@ module.exports = { enable, disable, setOptions, + getOptions, }; diff --git a/menu.js b/menu.js index 661929ca..91bb073d 100644 --- a/menu.js +++ b/menu.js @@ -1,26 +1,50 @@ +const { existsSync } = require("fs"); +const path = require("path"); + const { app, Menu } = require("electron"); const is = require("electron-is"); const { getAllPlugins } = require("./plugins/utils"); const config = require("./config"); +const pluginEnabledMenu = (plugin, label = "") => ({ + label: label || plugin, + type: "checkbox", + checked: config.plugins.isEnabled(plugin), + click: (item) => { + if (item.checked) { + config.plugins.enable(plugin); + } else { + config.plugins.disable(plugin); + } + }, +}); + const mainMenuTemplate = (win) => [ { label: "Plugins", submenu: [ ...getAllPlugins().map((plugin) => { - return { - label: plugin, - type: "checkbox", - checked: config.plugins.isEnabled(plugin), - click: (item) => { - if (item.checked) { - config.plugins.enable(plugin); - } else { - config.plugins.disable(plugin); - } - }, - }; + const pluginPath = path.join(__dirname, "plugins", plugin, "menu.js"); + + if (!config.plugins.isEnabled(plugin)) { + return pluginEnabledMenu(plugin); + } + + if (existsSync(pluginPath)) { + const getPluginMenu = require(pluginPath); + return { + label: plugin, + submenu: [ + pluginEnabledMenu(plugin, "Enabled"), + ...getPluginMenu(win, config.plugins.getOptions(plugin), () => + module.exports.setApplicationMenu(win) + ), + ], + }; + } + + return pluginEnabledMenu(plugin); }), { type: "separator" }, { diff --git a/package.json b/package.json index f5524a37..5e7af40b 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "@ffmpeg/core": "^0.8.5", "@ffmpeg/ffmpeg": "^0.9.7", "YoutubeNonStop": "git://github.com/lawfx/YoutubeNonStop.git#v0.8.1", + "async-mutex": "^0.3.1", "browser-id3-writer": "^4.4.0", "discord-rpc": "^3.2.0", "downloads-folder": "^3.0.1", @@ -77,7 +78,8 @@ "electron-updater": "^4.3.6", "filenamify": "^4.2.0", "node-fetch": "^2.6.1", - "ytdl-core": "^4.4.5" + "ytdl-core": "^4.4.5", + "ytpl": "^2.0.5" }, "devDependencies": { "electron": "^11.2.3", diff --git a/plugins/discord/back.js b/plugins/discord/back.js index 3e4ab629..0ebcc624 100644 --- a/plugins/discord/back.js +++ b/plugins/discord/back.js @@ -9,7 +9,9 @@ const rpc = new Discord.Client({ // Application ID registered by @semvis123 const clientId = "790655993809338398"; -module.exports = (win) => { +let clearActivity; + +module.exports = (win, {activityTimoutEnabled, activityTimoutTime}) => { const registerCallback = getSongInfo(win); // If the page is ready, register the callback @@ -29,7 +31,13 @@ module.exports = (win) => { // Add an idle icon to show that the song is paused activityInfo.smallImageKey = "idle"; activityInfo.smallImageText = "idle/paused"; + // Set start the timer so the activity gets cleared after a while if enabled + if (activityTimoutEnabled) + clearActivity = setTimeout(()=>rpc.clearActivity(), activityTimoutTime||10,000); + } else { + // stop the clear activity timout + clearTimeout(clearActivity); // Add the start and end time of the song const songStartTime = Date.now() - songInfo.elapsedSeconds * 1000; activityInfo.startTimestamp = songStartTime; diff --git a/plugins/downloader/back.js b/plugins/downloader/back.js index a5a49958..a1d2ff80 100644 --- a/plugins/downloader/back.js +++ b/plugins/downloader/back.js @@ -45,19 +45,21 @@ function handle(win) { let fileBuffer = songBuffer; try { - const coverBuffer = metadata.image.toPNG(); const writer = new ID3Writer(songBuffer); + if (metadata.image) { + const coverBuffer = metadata.image.toPNG(); - // Create the metadata tags - writer - .setFrame("TIT2", metadata.title) - .setFrame("TPE1", [metadata.artist]) - .setFrame("APIC", { - type: 3, - data: coverBuffer, - description: "", - }); - writer.addTag(); + // Create the metadata tags + writer + .setFrame("TIT2", metadata.title) + .setFrame("TPE1", [metadata.artist]) + .setFrame("APIC", { + type: 3, + data: coverBuffer, + description: "", + }); + writer.addTag(); + } fileBuffer = Buffer.from(writer.arrayBuffer); } catch (error) { sendError(win, error); @@ -70,3 +72,4 @@ function handle(win) { } module.exports = handle; +module.exports.sendError = sendError; diff --git a/plugins/downloader/menu.js b/plugins/downloader/menu.js new file mode 100644 index 00000000..4eda01a5 --- /dev/null +++ b/plugins/downloader/menu.js @@ -0,0 +1,63 @@ +const { existsSync, mkdirSync } = require("fs"); +const { join } = require("path"); +const { URL } = require("url"); + +const { ipcMain } = require("electron"); +const is = require("electron-is"); +const ytpl = require("ytpl"); + +const { sendError } = require("./back"); +const { defaultMenuDownloadLabel, getFolder } = require("./utils"); + +let downloadLabel = defaultMenuDownloadLabel; + +module.exports = (win, options, refreshMenu) => [ + { + label: downloadLabel, + click: async () => { + const currentURL = win.webContents.getURL(); + const playlistID = new URL(currentURL).searchParams.get("list"); + if (!playlistID) { + sendError(win, new Error("No playlist ID found")); + return; + } + + const playlist = await ytpl(playlistID); + 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 }); + + ipcMain.on("downloader-feedback", (_, feedback) => { + downloadLabel = feedback; + refreshMenu(); + }); + + downloadLabel = `Downloading "${playlistTitle}"`; + refreshMenu(); + + if (is.dev()) { + console.log( + `Downloading playlist "${playlistTitle}" (${playlist.items.length} songs)` + ); + } + + playlist.items.slice(0, options.playlistMaxItems).forEach((song) => { + win.webContents.send( + "downloader-download-playlist", + song, + playlistTitle, + options + ); + }); + }, + }, +]; diff --git a/plugins/downloader/utils.js b/plugins/downloader/utils.js new file mode 100644 index 00000000..3e0727cb --- /dev/null +++ b/plugins/downloader/utils.js @@ -0,0 +1,4 @@ +const downloadsFolder = require("downloads-folder"); + +module.exports.getFolder = (customFolder) => customFolder || downloadsFolder(); +module.exports.defaultMenuDownloadLabel = "Download playlist"; diff --git a/plugins/downloader/youtube-dl.js b/plugins/downloader/youtube-dl.js index 3541391f..65907e2b 100644 --- a/plugins/downloader/youtube-dl.js +++ b/plugins/downloader/youtube-dl.js @@ -1,7 +1,8 @@ const { randomBytes } = require("crypto"); +const { writeFileSync } = require("fs"); const { join } = require("path"); -const downloadsFolder = require("downloads-folder"); +const Mutex = require("async-mutex").Mutex; const { ipcRenderer } = require("electron"); const is = require("electron-is"); const filenamify = require("filenamify"); @@ -12,8 +13,9 @@ const filenamify = require("filenamify"); const FFmpeg = require("@ffmpeg/ffmpeg/dist/ffmpeg.min"); const ytdl = require("ytdl-core"); -const { triggerActionSync } = require("../utils"); +const { triggerAction, triggerActionSync } = require("../utils"); const { ACTIONS, CHANNEL } = require("./actions.js"); +const { defaultMenuDownloadLabel, getFolder } = require("./utils"); const { createFFmpeg } = FFmpeg; const ffmpeg = createFFmpeg({ @@ -21,13 +23,16 @@ const ffmpeg = createFFmpeg({ logger: () => {}, // console.log, progress: () => {}, // console.log, }); +const ffmpegMutex = new Mutex(); const downloadVideoToMP3 = ( videoUrl, sendFeedback, sendError, reinit, - options + options, + metadata = undefined, + subfolder = "" ) => { sendFeedback("Downloading…"); @@ -66,9 +71,18 @@ const downloadVideoToMP3 = ( } }) .on("error", sendError) - .on("end", () => { + .on("end", async () => { const buffer = Buffer.concat(chunks); - toMP3(videoName, buffer, sendFeedback, sendError, reinit, options); + await toMP3( + videoName, + buffer, + sendFeedback, + sendError, + reinit, + options, + metadata, + subfolder + ); }); }; @@ -78,10 +92,13 @@ const toMP3 = async ( sendFeedback, sendError, reinit, - options + options, + existingMetadata = undefined, + subfolder = "" ) => { const safeVideoName = randomBytes(32).toString("hex"); const extension = options.extension || "mp3"; + const releaseFFmpegMutex = await ffmpegMutex.acquire(); try { if (!ffmpeg.isLoaded()) { @@ -93,7 +110,7 @@ const toMP3 = async ( ffmpeg.FS("writeFile", safeVideoName, buffer); sendFeedback("Converting…"); - const metadata = getMetadata(); + const metadata = existingMetadata || getMetadata(); await ffmpeg.run( "-i", safeVideoName, @@ -102,24 +119,31 @@ const toMP3 = async ( safeVideoName + "." + extension ); - const folder = options.downloadFolder || downloadsFolder(); + const folder = getFolder(options.downloadFolder); const name = metadata - ? `${metadata.artist} - ${metadata.title}` + ? `${metadata.artist ? `${metadata.artist} - ` : ""}${metadata.title}` : videoName; const filename = filenamify(name + "." + extension, { replacement: "_", }); - // Add the metadata - sendFeedback("Adding metadata…"); - ipcRenderer.send( - "add-metadata", - join(folder, filename), - ffmpeg.FS("readFile", safeVideoName + "." + extension) - ); - ipcRenderer.once("add-metadata-done", reinit); + const filePath = join(folder, subfolder, filename); + const fileBuffer = ffmpeg.FS("readFile", safeVideoName + "." + extension); + + if (existingMetadata) { + writeFileSync(filePath, fileBuffer); + reinit(); + } else { + // Add the metadata + sendFeedback("Adding metadata…"); + ipcRenderer.send("add-metadata", filePath, fileBuffer); + ipcRenderer.once("add-metadata-done", reinit); + sendFeedback("Finished converting", metadata); + } } catch (e) { sendError(e); + } finally { + releaseFFmpegMutex(); } }; @@ -133,13 +157,34 @@ const getFFmpegMetadataArgs = (metadata) => { } return [ - "-metadata", - `title=${metadata.title}`, - "-metadata", - `artist=${metadata.artist}`, + ...(metadata.title ? ["-metadata", `title=${metadata.title}`] : []), + ...(metadata.artist ? ["-metadata", `artist=${metadata.artist}`] : []), ]; }; module.exports = { downloadVideoToMP3, }; + +ipcRenderer.on( + "downloader-download-playlist", + (_, songMetadata, playlistFolder, options) => { + const reinit = () => + ipcRenderer.send("downloader-feedback", defaultMenuDownloadLabel); + + downloadVideoToMP3( + songMetadata.url, + (feedback) => { + ipcRenderer.send("downloader-feedback", feedback); + }, + (error) => { + triggerAction(CHANNEL, ACTIONS.ERROR, error); + reinit(); + }, + reinit, + options, + songMetadata, + playlistFolder + ); + } +); diff --git a/plugins/navigation/back.js b/plugins/navigation/back.js index 6d0d0a2a..4c3e00dc 100644 --- a/plugins/navigation/back.js +++ b/plugins/navigation/back.js @@ -4,7 +4,10 @@ const { injectCSS, listenAction } = require("../utils"); const { ACTIONS, CHANNEL } = require("./actions.js"); function handle(win) { - injectCSS(win.webContents, path.join(__dirname, "style.css")); + injectCSS(win.webContents, path.join(__dirname, "style.css"), () => { + win.webContents.send("navigation-css-ready"); + }); + listenAction(CHANNEL, (event, action) => { switch (action) { case ACTIONS.NEXT: diff --git a/plugins/navigation/front.js b/plugins/navigation/front.js index 92bc1325..d89c9891 100644 --- a/plugins/navigation/front.js +++ b/plugins/navigation/front.js @@ -1,15 +1,19 @@ +const { ipcRenderer } = require("electron"); + const { ElementFromFile, templatePath } = require("../utils"); function run() { - const forwardButton = ElementFromFile( - templatePath(__dirname, "forward.html") - ); - const backButton = ElementFromFile(templatePath(__dirname, "back.html")); - const menu = document.querySelector("ytmusic-pivot-bar-renderer"); + ipcRenderer.on("navigation-css-ready", () => { + const forwardButton = ElementFromFile( + templatePath(__dirname, "forward.html") + ); + const backButton = ElementFromFile(templatePath(__dirname, "back.html")); + const menu = document.querySelector("ytmusic-pivot-bar-renderer"); - if (menu) { - menu.prepend(backButton, forwardButton); - } + if (menu) { + menu.prepend(backButton, forwardButton); + } + }); } module.exports = run; diff --git a/plugins/navigation/templates/back.html b/plugins/navigation/templates/back.html index 2a675163..b872ada5 100644 --- a/plugins/navigation/templates/back.html +++ b/plugins/navigation/templates/back.html @@ -20,7 +20,7 @@ preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" - style="pointer-events: none; display: block; width: 100%; height: 100%;" + style="pointer-events: none; display: block; width: 100%; height: 100%" > { }); }; -module.exports.injectCSS = (webContents, filepath) => { - webContents.on("did-finish-load", () => { - webContents.insertCSS(fs.readFileSync(filepath, "utf8")); +module.exports.injectCSS = (webContents, filepath, cb = undefined) => { + webContents.on("did-finish-load", async () => { + await webContents.insertCSS(fs.readFileSync(filepath, "utf8")); + if (cb) { + cb(); + } }); }; diff --git a/yarn.lock b/yarn.lock index f4ac5ed3..f1a14d40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1661,6 +1661,13 @@ async-exit-hook@^2.0.1: resolved "https://registry.yarnpkg.com/async-exit-hook/-/async-exit-hook-2.0.1.tgz#8bd8b024b0ec9b1c01cccb9af9db29bd717dfaf3" integrity sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw== +async-mutex@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.3.1.tgz#7033af665f1c7cebed8b878267a43ba9e77c5f67" + integrity sha512-vRfQwcqBnJTLzVQo72Sf7KIUbcSUP5hNchx6udI1U6LuPQpfePgdjJzlCe76yFZ8pxlLjn9lwcl/Ya0TSOv0Tw== + dependencies: + tslib "^2.1.0" + async@0.9.x: version "0.9.2" resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" @@ -6147,7 +6154,7 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -miniget@^4.0.0: +miniget@^4.0.0, miniget@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/miniget/-/miniget-4.2.0.tgz#0004e95536b192d95a7d09f4435d67b9285481d0" integrity sha512-IzTOaNgBw/qEpzkPTE7X2cUVXQfSKbG8w52Emi93zb+Zya2ZFrbmavpixzebuDJD9Ku4ecbaFlC7Y1cEESzQtQ== @@ -8362,6 +8369,11 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" + integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== + tsutils@^3.17.1: version "3.20.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.20.0.tgz#ea03ea45462e146b53d70ce0893de453ff24f698" @@ -9065,6 +9077,13 @@ ytdl-core@^4.4.5: miniget "^4.0.0" sax "^1.1.3" +ytpl@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/ytpl/-/ytpl-2.0.5.tgz#c56900bccaf96e289304de647bc861121f61223e" + integrity sha512-8hc+f3pijaogj1yoZTCGImMDS4x0ogFPDsx1PefNQ+2EAhJMm1K4brcYT9zpJhPi9SXh+O103pEIHDw3+dAhxA== + dependencies: + miniget "^4.1.0" + zip-stream@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.0.4.tgz#3a8f100b73afaa7d1ae9338d910b321dec77ff3a" diff --git a/youtube-music.css b/youtube-music.css index d9c7b3ec..fe5eb326 100644 --- a/youtube-music.css +++ b/youtube-music.css @@ -5,7 +5,7 @@ /* Allow window dragging */ ytmusic-nav-bar { -webkit-user-select: none; - -webkit-app-region : drag; + -webkit-app-region: drag; } iron-icon, From 88cd1651c3ce5f7ac571ec3e4bb5f740c2468487 Mon Sep 17 00:00:00 2001 From: TC Date: Thu, 25 Mar 2021 22:15:39 +0100 Subject: [PATCH 4/5] Clean metadata + apply pngcrush on images in taskbar plugin --- .../taskbar-mediacontrol/assets/backward.png | Bin 570 -> 269 bytes plugins/taskbar-mediacontrol/assets/forward.png | Bin 545 -> 250 bytes plugins/taskbar-mediacontrol/assets/pause.png | Bin 300 -> 192 bytes plugins/taskbar-mediacontrol/assets/play.png | Bin 468 -> 265 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/plugins/taskbar-mediacontrol/assets/backward.png b/plugins/taskbar-mediacontrol/assets/backward.png index 3f1a27f89aeec3b9acc06844d69e15d053d6c733..2dd278eb7bf3823282bb8a872289a06ec407c685 100644 GIT binary patch delta 252 zcmV zM+`X(6o3GR{|p=GX@EY%PKI*~T;v%b!Z3s34^aJo1`E;+U}Y#^cn{W0mI0m&H{hB{ zHb9+WD~e{44B%(zWB7%kok#DRS1I!ps5TzNb0a6SL8U7Ki9m9Y#NQrb{44~KxR0u?>L?aav5>=8i zRWcJ*vNIJ56siMzCV_|S*E^l&Yo9;Xs0005ENkl|ED{nHOn(xIg~3uE6ESz%k_;rdpX6ndg{=XSEKPD1FR%;iv2J31-W(R5k7GECC4bAC6F`zZxQPC# za=Qvh(vLyxoqz5{_*0000`=0!R~?uT!iyD61B7sAM$G^roESMEge_eMgkmQP8U_gA%G3cN92htt zeArMJAcO~V>IMkm%-8`T?CCooyjjyWKnOR=KLYX!>Jim9sz#EntcFRAvs@@@rKzQ= j*18Cm!bY18R}t@DH=MI>j#b@000000NkvXXu0mjf$mw8{ delta 531 zcmV+u0_^?z0igtt8Gi-<0047(dh`GQ00eVFNmK|32nc)#WQYI&010qNS#tmY0UH1S z0UH60_fF*i000?uMObuGZ)S9NVRB^vcXxL#X>MzCV_|S*E^l&Yo9;Xs0004=Nkl47{>A6g)|}Y5lLg}g2Y#1Af|Q{Dj&$<4&?k7i8>D7bFn8Li6X+r>l6Znv1 zBuQVd1sc}lD&8hJ+=f8IHatl3ILV$i1R4(Fb&~5zHn$-Ft8p4{u&E7!f6@zqAGm?N z`1I$?HC+yWg0odM4oT*1=$60~&Q;aJ#Wt?=2)^Jvc7Oj*I4jpc;WjQ*)yz^3u7tod zoT;jpog7}y2&Qqos)jlZr?UpWVHBfP^|jOBP6h5^q^hQu8@yD3S7zrtwo<_ji`{`4 zoWg-_g!A_XzT+CMRMqEh1TQ4;9Fus5;i~%B&ERA-~8Gi%-007x@vVQ;o00Lr5M??VshmXv^0001aNkleBm(?k>4qtx%udVbbttF`#6()BOG6AHc@ z+;e7~z=LUDHvM#N2=-!N5@=vxQD9)?Z~!tLST?Bd&G{$rAoAk<1CL&GSI&&B|1)Ra d*Ln4#4B3%BtD>vZ(t*xq@O1TaS?83{1OUm&Zdw2U diff --git a/plugins/taskbar-mediacontrol/assets/play.png b/plugins/taskbar-mediacontrol/assets/play.png index 27d9ad1535ff0de4af3363f9195012d45dbef306..7a2cfa50efb0d0d9ed263c56378584da47c031e2 100644 GIT binary patch delta 248 zcmV6ZAg>fh%*W=>@|tfjBdv=y3?dfvzVIE1I4_8JSUW z1meW_cSh0(#GZ~P5DV&_AaG$y*%63@5d}vew(omn6NGyU<~%{5{bzys1S^TwH=2cH ym9o`LRy&&m#TseWP>mSt_F}PDo4s7E^?n0#l`g}0%v{m{0000oc5!lIL8@MUQTpt6Hc~)EjR8I( zuK)l42Qmi`G_G4^1hihOB*-tAfr*)gl}$)QR8~t{N6*&VHy}DWBe$S<^3)kScJ1D~ z@8Fdix9+@s|KazaoHN@pfV%oUT^vI!dY4|d6gp%e;1bAq?9K0eQp{|B-q$-YX(&b8 zCp-#Q&AcM(^g^~f=OW+M%V!whZH_W{VEjCgcSb$q(|ysL)BZf$>G_BuFPO1Fifh50 z(nkz(uT}USSP3$;?_-F&ZNj%8V(TLYy_F1~+8B=gXR>zE(>%Y$_2jCjo1g5~H4w7o k%q@Mh)gsDPcm0+Byqg_j_7?w&HUNdEr>mdKI;Vst01fbf5dZ)H From fe8f048571b3386117880b85adab9c43704d9b56 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Fri, 26 Mar 2021 04:07:45 +0300 Subject: [PATCH 5/5] add Download Folder Chooser --- plugins/downloader/menu.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugins/downloader/menu.js b/plugins/downloader/menu.js index 4eda01a5..14419e0c 100644 --- a/plugins/downloader/menu.js +++ b/plugins/downloader/menu.js @@ -9,6 +9,8 @@ const ytpl = require("ytpl"); const { sendError } = require("./back"); const { defaultMenuDownloadLabel, getFolder } = require("./utils"); +const { setOptions } = require('../../config/plugins') +const { dialog } = require('electron'); let downloadLabel = defaultMenuDownloadLabel; module.exports = (win, options, refreshMenu) => [ @@ -60,4 +62,17 @@ module.exports = (win, options, refreshMenu) => [ }); }, }, + { + label: 'Choose download folder:', + click: () => { + let result = dialog.showOpenDialogSync({ + properties: ['openDirectory', 'createDirectory'], + defaultPath: Array.isArray(options.downloadFolder) ? options.downloadFolder[0] : undefined, + }) + if(result) { + options.downloadFolder = result + setOptions("downloader", options) + } //else = user pressed cancel + } + }, ];