mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-11 10:31:47 +00:00
115 lines
3.1 KiB
JavaScript
115 lines
3.1 KiB
JavaScript
const { nativeImage } = require("electron");
|
|
|
|
const fetch = require("node-fetch");
|
|
|
|
// This selects the song title
|
|
const titleSelector = ".title.style-scope.ytmusic-player-bar";
|
|
|
|
// This selects the song image
|
|
const imageSelector =
|
|
"#layout > ytmusic-player-bar > div.middle-controls.style-scope.ytmusic-player-bar > img";
|
|
|
|
// This selects the song subinfo, this includes artist, views, likes
|
|
const subInfoSelector =
|
|
"#layout > ytmusic-player-bar > div.middle-controls.style-scope.ytmusic-player-bar > div.content-info-wrapper.style-scope.ytmusic-player-bar > span";
|
|
|
|
// Grab the title using the selector
|
|
const getTitle = (win) => {
|
|
return win.webContents
|
|
.executeJavaScript(
|
|
"document.querySelector('" + titleSelector + "').innerText"
|
|
)
|
|
.catch((error) => {
|
|
console.log(error);
|
|
});
|
|
};
|
|
|
|
// Grab the image src using the selector
|
|
const getImageSrc = (win) => {
|
|
return win.webContents
|
|
.executeJavaScript("document.querySelector('" + imageSelector + "').src")
|
|
.catch((error) => {
|
|
console.log(error);
|
|
});
|
|
};
|
|
|
|
// Grab the subinfo using the selector
|
|
const getSubInfo = async (win) => {
|
|
// Get innerText of subinfo element
|
|
const subInfoString = await win.webContents.executeJavaScript(
|
|
'document.querySelector("' + subInfoSelector + '").innerText'
|
|
);
|
|
|
|
// Split and clean the string
|
|
const splittedSubInfo = subInfoString.replaceAll("\n", "").split(" • ");
|
|
|
|
// Make sure we always return 3 elements in the aray
|
|
const subInfo = [];
|
|
for (let i = 0; i < 3; i++) {
|
|
// Fill array with empty string if not defined
|
|
subInfo.push(splittedSubInfo[i] || "");
|
|
}
|
|
|
|
return subInfo;
|
|
};
|
|
|
|
// Grab the native image using the src
|
|
const getImage = async (src) => {
|
|
const result = await fetch(src);
|
|
const buffer = await result.buffer();
|
|
return nativeImage.createFromBuffer(buffer);
|
|
};
|
|
|
|
const getPausedStatus = async (win) => {
|
|
const title = await win.webContents.executeJavaScript("document.title");
|
|
return !title.includes("-");
|
|
};
|
|
|
|
// Fill songInfo with empty values
|
|
const songInfo = {
|
|
title: "",
|
|
artist: "",
|
|
views: "",
|
|
likes: "",
|
|
imageSrc: "",
|
|
image: null,
|
|
isPaused: true,
|
|
};
|
|
|
|
const registerProvider = (win) => {
|
|
// This variable will be filled with the callbacks once they register
|
|
const callbacks = [];
|
|
|
|
// This function will allow plugins to register callback that will be triggered when data changes
|
|
const registerCallback = (callback) => {
|
|
callbacks.push(callback);
|
|
};
|
|
|
|
win.on("page-title-updated", async () => {
|
|
// Save the old title temporarily
|
|
const oldTitle = songInfo.title;
|
|
// Get and set the new data
|
|
songInfo.title = await getTitle(win);
|
|
songInfo.isPaused = await getPausedStatus(win);
|
|
|
|
// If title changed then we do need to update other info
|
|
if (oldTitle !== songInfo.title) {
|
|
const subInfo = await getSubInfo(win);
|
|
songInfo.artist = subInfo[0];
|
|
songInfo.views = subInfo[1];
|
|
songInfo.likes = subInfo[2];
|
|
songInfo.imageSrc = await getImageSrc(win);
|
|
songInfo.image = await getImage(songInfo.imageSrc);
|
|
}
|
|
|
|
// Trigger the callbacks
|
|
callbacks.forEach((c) => {
|
|
c(songInfo);
|
|
});
|
|
});
|
|
|
|
return registerCallback;
|
|
};
|
|
|
|
module.exports = registerProvider;
|