diff --git a/plugins/downloader/youtube-dl.js b/plugins/downloader/youtube-dl.js index f0f47cecf1..906fc35cdc 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 0000000000..302425d3bf --- /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 0000000000..e1354d26fb --- /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 0000000000..7807a81440 --- /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/providers/song-info.js b/providers/song-info.js index 08eaf9448e..0ef0f86897 100644 --- a/providers/song-info.js +++ b/providers/song-info.js @@ -55,8 +55,9 @@ const songInfo = { const handleData = async (responseText, win) => { let data = JSON.parse(responseText); - songInfo.title = data?.videoDetails?.title; - songInfo.artist = await getArtist(win) || cleanupArtistName(data?.videoDetails?.author); + songInfo.title = cleanupName(data?.videoDetails?.title); + songInfo.artist = + (await getArtist(win)) || cleanupName(data?.videoDetails?.author); songInfo.views = data?.videoDetails?.viewCount; songInfo.imageSrc = data?.videoDetails?.thumbnail?.thumbnails?.pop()?.url; songInfo.songDuration = data?.videoDetails?.lengthSeconds; @@ -98,8 +99,15 @@ const registerProvider = (win) => { }); }; -const suffixesToRemove = [' - Topic', 'VEVO']; -function cleanupArtistName(artist) { +const suffixesToRemove = [ + " - Topic", + "VEVO", + " (Performance Video)", + " (Official Music Video)", + " (Official Video)", + " (Clip officiel)", +]; +function cleanupName(artist) { if (!artist) { return artist; } @@ -114,4 +122,4 @@ function cleanupArtistName(artist) { module.exports = registerCallback; module.exports.setupSongInfo = registerProvider; module.exports.getImage = getImage; -module.exports.cleanupArtistName = cleanupArtistName; +module.exports.cleanupName = cleanupName;