diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 67feb14a..ccd5e1ea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: - name: Setup NodeJS uses: actions/setup-node@v1 with: - node-version: "12.x" + node-version: "14.x" - name: Get yarn cache directory path id: yarn-cache-dir-path diff --git a/package.json b/package.json index a2db61fa..acacb3b7 100644 --- a/package.json +++ b/package.json @@ -60,11 +60,11 @@ "release:win": "yarn run clean && electron-builder --win -p always" }, "engines": { - "node": ">=12.20", + "node": ">=14.0.0", "npm": "Please use yarn and not npm" }, "dependencies": { - "@cliqz/adblocker-electron": "^1.22.1", + "@cliqz/adblocker-electron": "^1.22.3", "@ffmpeg/core": "^0.10.0", "@ffmpeg/ffmpeg": "^0.10.0", "YoutubeNonStop": "git://github.com/lawfx/YoutubeNonStop.git#v0.9.0", @@ -82,6 +82,7 @@ "electron-updater": "^4.3.10", "filenamify": "^4.3.0", "md5": "^2.3.0", + "mpris-service": "^2.1.2", "node-fetch": "^2.6.1", "node-notifier": "^9.0.1", "ytdl-core": "^4.9.1", diff --git a/plugins/discord/back.js b/plugins/discord/back.js index c6faadd7..a2eef1f5 100644 --- a/plugins/discord/back.js +++ b/plugins/discord/back.js @@ -29,6 +29,9 @@ module.exports = (win, {activityTimoutEnabled, activityTimoutTime}) => { songInfo.uploadDate, songInfo.views.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + " views" ].join(' || '), + buttons: [ + { label: "Listen Along", url: songInfo.url }, + ] }; if (songInfo.isPaused) { diff --git a/plugins/downloader/style.css b/plugins/downloader/style.css index 8119fc5e..6f29fc6b 100644 --- a/plugins/downloader/style.css +++ b/plugins/downloader/style.css @@ -6,8 +6,16 @@ cursor: pointer; } +.menu-item > .yt-simple-endpoint:hover { + background-color: var(--ytmusic-menu-item-hover-background-color); +} + .menu-icon { flex: var(--ytmusic-menu-item-icon_-_flex); margin: var(--ytmusic-menu-item-icon_-_margin); fill: var(--ytmusic-menu-item-icon_-_fill); + stroke: var(--iron-icon-stroke-color, none); + width: var(--iron-icon-width, 24px); + height: var(--iron-icon-height, 24px); + animation: var(--iron-icon_-_animation); } diff --git a/plugins/downloader/templates/download.html b/plugins/downloader/templates/download.html index d4f455d0..ede5ec02 100644 --- a/plugins/downloader/templates/download.html +++ b/plugins/downloader/templates/download.html @@ -1,5 +1,5 @@ diff --git a/plugins/downloader/youtube-dl.js b/plugins/downloader/youtube-dl.js index f0f47cec..906fc35c 100644 --- a/plugins/downloader/youtube-dl.js +++ b/plugins/downloader/youtube-dl.js @@ -15,7 +15,7 @@ const ytdl = require("ytdl-core"); const { triggerAction, triggerActionSync } = require("../utils"); const { ACTIONS, CHANNEL } = require("./actions.js"); const { getFolder, urlToJPG } = require("./utils"); -const { cleanupArtistName } = require("../../providers/song-info"); +const { cleanupName } = require("../../providers/song-info"); const { createFFmpeg } = FFmpeg; const ffmpeg = createFFmpeg({ @@ -40,7 +40,10 @@ const downloadVideoToMP3 = async ( const { videoDetails } = await ytdl.getInfo(videoUrl); const thumbnails = videoDetails?.thumbnails; metadata = { - artist: videoDetails?.media?.artist || cleanupArtistName(videoDetails?.author?.name) || "", + artist: + videoDetails?.media?.artist || + cleanupName(videoDetails?.author?.name) || + "", title: videoDetails?.media?.song || videoDetails?.title || "", imageSrcYTPL: thumbnails ? urlToJPG(thumbnails[thumbnails.length - 1].url, videoDetails?.videoId) diff --git a/plugins/lyrics-genius/back.js b/plugins/lyrics-genius/back.js new file mode 100644 index 00000000..302425d3 --- /dev/null +++ b/plugins/lyrics-genius/back.js @@ -0,0 +1,52 @@ +const { join } = require("path"); + +const { ipcMain } = require("electron"); +const is = require("electron-is"); +const fetch = require("node-fetch"); + +const { cleanupName } = require("../../providers/song-info"); +const { injectCSS } = require("../utils"); + +module.exports = async (win) => { + injectCSS(win.webContents, join(__dirname, "style.css")); + + ipcMain.on("search-genius-lyrics", async (event, extractedSongInfo) => { + const metadata = JSON.parse(extractedSongInfo); + const queryString = `${cleanupName(metadata.artist)} ${cleanupName( + metadata.title + )}`; + + let response = await fetch( + `https://genius.com/api/search/multi?per_page=5&q=${encodeURI( + queryString + )}` + ); + if (!response.ok) { + event.returnValue = null; + return; + } + + const info = await response.json(); + let url = ""; + try { + url = info.response.sections.filter( + (section) => section.type === "song" + )[0].hits[0].result.url; + } catch { + event.returnValue = null; + return; + } + + if (is.dev()) { + console.log("Fetching lyrics from Genius:", url); + } + + response = await fetch(url); + if (!response.ok) { + event.returnValue = null; + return; + } + + event.returnValue = await response.text(); + }); +}; diff --git a/plugins/lyrics-genius/front.js b/plugins/lyrics-genius/front.js new file mode 100644 index 00000000..e1354d26 --- /dev/null +++ b/plugins/lyrics-genius/front.js @@ -0,0 +1,65 @@ +const { ipcRenderer } = require("electron"); + +module.exports = () => { + ipcRenderer.on("update-song-info", (_, extractedSongInfo) => { + const lyricsTab = document.querySelector('tp-yt-paper-tab[tabindex="-1"]'); + + // Check if disabled + if (!lyricsTab || !lyricsTab.hasAttribute("disabled")) { + return; + } + + const html = ipcRenderer.sendSync( + "search-genius-lyrics", + extractedSongInfo + ); + if (!html) { + return; + } + + const wrapper = document.createElement("div"); + wrapper.innerHTML = html; + const lyricsSelector1 = wrapper.querySelector(".lyrics"); + const lyricsSelector2 = wrapper.querySelector( + '[class^="Lyrics__Container"]' + ); + const lyrics = lyricsSelector1 + ? lyricsSelector1.innerHTML + : lyricsSelector2 + ? lyricsSelector2.innerHTML + : null; + if (!lyrics) { + return; + } + + lyricsTab.removeAttribute("disabled"); + lyricsTab.removeAttribute("aria-disabled"); + document.querySelector("tp-yt-paper-tab").onclick = () => { + lyricsTab.removeAttribute("disabled"); + lyricsTab.removeAttribute("aria-disabled"); + }; + + lyricsTab.onclick = () => { + const tabContainer = document.querySelector("ytmusic-tab-renderer"); + console.log("tabContainer", tabContainer); + const observer = new MutationObserver((_, observer) => { + const lyricsContainer = document.querySelector( + '[page-type="MUSIC_PAGE_TYPE_TRACK_LYRICS"] > ytmusic-message-renderer' + ); + if (lyricsContainer) { + lyricsContainer.innerHTML = `
+ ${lyrics} + + Source : Genius +
`; + observer.disconnect(); + } + }); + observer.observe(tabContainer, { + attributes: true, + childList: true, + subtree: true, + }); + }; + }); +}; diff --git a/plugins/lyrics-genius/style.css b/plugins/lyrics-genius/style.css new file mode 100644 index 00000000..7807a814 --- /dev/null +++ b/plugins/lyrics-genius/style.css @@ -0,0 +1,7 @@ +/* Disable links in Genius lyrics */ +.genius-lyrics a { + color: var(--ytmusic-text-primary); + display: inline-block; + pointer-events: none; + text-decoration: none; +} diff --git a/plugins/playback-speed/templates/slider.html b/plugins/playback-speed/templates/slider.html index 67ced7a4..85865af0 100644 --- a/plugins/playback-speed/templates/slider.html +++ b/plugins/playback-speed/templates/slider.html @@ -1,79 +1,87 @@