mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-11 10:31:47 +00:00
Merge pull request #387 from th-ch/lyrics-genius-plugin
Plugin to fetch lyrics from Genius
This commit is contained in:
@ -15,7 +15,7 @@ const ytdl = require("ytdl-core");
|
|||||||
const { triggerAction, triggerActionSync } = require("../utils");
|
const { triggerAction, triggerActionSync } = require("../utils");
|
||||||
const { ACTIONS, CHANNEL } = require("./actions.js");
|
const { ACTIONS, CHANNEL } = require("./actions.js");
|
||||||
const { getFolder, urlToJPG } = require("./utils");
|
const { getFolder, urlToJPG } = require("./utils");
|
||||||
const { cleanupArtistName } = require("../../providers/song-info");
|
const { cleanupName } = require("../../providers/song-info");
|
||||||
|
|
||||||
const { createFFmpeg } = FFmpeg;
|
const { createFFmpeg } = FFmpeg;
|
||||||
const ffmpeg = createFFmpeg({
|
const ffmpeg = createFFmpeg({
|
||||||
@ -40,7 +40,10 @@ const downloadVideoToMP3 = async (
|
|||||||
const { videoDetails } = await ytdl.getInfo(videoUrl);
|
const { videoDetails } = await ytdl.getInfo(videoUrl);
|
||||||
const thumbnails = videoDetails?.thumbnails;
|
const thumbnails = videoDetails?.thumbnails;
|
||||||
metadata = {
|
metadata = {
|
||||||
artist: videoDetails?.media?.artist || cleanupArtistName(videoDetails?.author?.name) || "",
|
artist:
|
||||||
|
videoDetails?.media?.artist ||
|
||||||
|
cleanupName(videoDetails?.author?.name) ||
|
||||||
|
"",
|
||||||
title: videoDetails?.media?.song || videoDetails?.title || "",
|
title: videoDetails?.media?.song || videoDetails?.title || "",
|
||||||
imageSrcYTPL: thumbnails ?
|
imageSrcYTPL: thumbnails ?
|
||||||
urlToJPG(thumbnails[thumbnails.length - 1].url, videoDetails?.videoId)
|
urlToJPG(thumbnails[thumbnails.length - 1].url, videoDetails?.videoId)
|
||||||
|
|||||||
52
plugins/lyrics-genius/back.js
Normal file
52
plugins/lyrics-genius/back.js
Normal file
@ -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();
|
||||||
|
});
|
||||||
|
};
|
||||||
65
plugins/lyrics-genius/front.js
Normal file
65
plugins/lyrics-genius/front.js
Normal file
@ -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 = `<div id="contents" class="style-scope ytmusic-section-list-renderer genius-lyrics">
|
||||||
|
${lyrics}
|
||||||
|
|
||||||
|
<yt-formatted-string class="footer style-scope ytmusic-description-shelf-renderer">Source : Genius</yt-formatted-string>
|
||||||
|
</div>`;
|
||||||
|
observer.disconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
observer.observe(tabContainer, {
|
||||||
|
attributes: true,
|
||||||
|
childList: true,
|
||||||
|
subtree: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
7
plugins/lyrics-genius/style.css
Normal file
7
plugins/lyrics-genius/style.css
Normal file
@ -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;
|
||||||
|
}
|
||||||
@ -55,8 +55,9 @@ const songInfo = {
|
|||||||
|
|
||||||
const handleData = async (responseText, win) => {
|
const handleData = async (responseText, win) => {
|
||||||
let data = JSON.parse(responseText);
|
let data = JSON.parse(responseText);
|
||||||
songInfo.title = data?.videoDetails?.title;
|
songInfo.title = cleanupName(data?.videoDetails?.title);
|
||||||
songInfo.artist = await getArtist(win) || cleanupArtistName(data?.videoDetails?.author);
|
songInfo.artist =
|
||||||
|
(await getArtist(win)) || cleanupName(data?.videoDetails?.author);
|
||||||
songInfo.views = data?.videoDetails?.viewCount;
|
songInfo.views = data?.videoDetails?.viewCount;
|
||||||
songInfo.imageSrc = data?.videoDetails?.thumbnail?.thumbnails?.pop()?.url;
|
songInfo.imageSrc = data?.videoDetails?.thumbnail?.thumbnails?.pop()?.url;
|
||||||
songInfo.songDuration = data?.videoDetails?.lengthSeconds;
|
songInfo.songDuration = data?.videoDetails?.lengthSeconds;
|
||||||
@ -98,8 +99,15 @@ const registerProvider = (win) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const suffixesToRemove = [' - Topic', 'VEVO'];
|
const suffixesToRemove = [
|
||||||
function cleanupArtistName(artist) {
|
" - Topic",
|
||||||
|
"VEVO",
|
||||||
|
" (Performance Video)",
|
||||||
|
" (Official Music Video)",
|
||||||
|
" (Official Video)",
|
||||||
|
" (Clip officiel)",
|
||||||
|
];
|
||||||
|
function cleanupName(artist) {
|
||||||
if (!artist) {
|
if (!artist) {
|
||||||
return artist;
|
return artist;
|
||||||
}
|
}
|
||||||
@ -114,4 +122,4 @@ function cleanupArtistName(artist) {
|
|||||||
module.exports = registerCallback;
|
module.exports = registerCallback;
|
||||||
module.exports.setupSongInfo = registerProvider;
|
module.exports.setupSongInfo = registerProvider;
|
||||||
module.exports.getImage = getImage;
|
module.exports.getImage = getImage;
|
||||||
module.exports.cleanupArtistName = cleanupArtistName;
|
module.exports.cleanupName = cleanupName;
|
||||||
|
|||||||
Reference in New Issue
Block a user