From 0743034de0443e889ec11d7ea83727ff4fb96599 Mon Sep 17 00:00:00 2001 From: TC Date: Tue, 12 Jan 2021 21:17:08 +0100 Subject: [PATCH] Split providers in 2 --- providers/song-controls.js | 18 ++++++ providers/song-info.js | 114 ++++++++++++++++++++++++++++++++++ providers/song-info/back.js | 120 ------------------------------------ 3 files changed, 132 insertions(+), 120 deletions(-) create mode 100644 providers/song-controls.js create mode 100644 providers/song-info.js delete mode 100644 providers/song-info/back.js diff --git a/providers/song-controls.js b/providers/song-controls.js new file mode 100644 index 0000000000..20946a38cd --- /dev/null +++ b/providers/song-controls.js @@ -0,0 +1,18 @@ +// This is used for to control the songs +const pressKey = (window, key) => { + window.webContents.sendInputEvent({ + type: "keydown", + keyCode: key, + }); +}; + +module.exports = (win) => { + return { + previous: () => pressKey(win, "k"), + next: () => pressKey(win, "j"), + playPause: () => pressKey(win, "space"), + like: () => pressKey(win, "_"), + dislike: () => pressKey(win, "+"), + search: () => pressKey(win, "/"), + }; +}; diff --git a/providers/song-info.js b/providers/song-info.js new file mode 100644 index 0000000000..1c3333e092 --- /dev/null +++ b/providers/song-info.js @@ -0,0 +1,114 @@ +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; diff --git a/providers/song-info/back.js b/providers/song-info/back.js deleted file mode 100644 index c7c78a19a0..0000000000 --- a/providers/song-info/back.js +++ /dev/null @@ -1,120 +0,0 @@ -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'; - -// This is used for to control the songs -const presskey = (window, key) => { - window.webContents.sendInputEvent({ - type: 'keydown', - keyCode: key - }); -}; - -// 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('-'); -}; - -// This variable will be filled with the callbacks once they register -const callbacks = []; - -module.exports = win => { - // Fill songInfo with empty values - global.songInfo = { - title: '', - artist: '', - views: '', - likes: '', - imageSrc: '', - image: null, - isPaused: true - }; - // The song control functions - global.songControls = { - previous: () => presskey(win, 'k'), - next: () => presskey(win, 'j'), - pause: () => presskey(win, 'space'), - like: () => presskey(win, '_'), - dislike: () => presskey(win, '+') - }; - - // This function will allow plugins to register callback that will be triggered when data changes - global.songInfo.onNewData = callback => { - callbacks.push(callback); - }; - - win.on('page-title-updated', async () => { - // Save the old title temporarily - const oldTitle = global.songInfo.title; - // Get and set the new data - global.songInfo.title = await getTitle(win); - global.songInfo.isPaused = await getPausedStatus(win); - - // If title changed then we do need to update other info - if (oldTitle !== global.songInfo.title) { - const subInfo = await getSubInfo(win); - global.songInfo.artist = subInfo[0]; - global.songInfo.views = subInfo[1]; - global.songInfo.likes = subInfo[2]; - global.songInfo.imageSrc = await getImageSrc(win); - global.songInfo.image = await getImage(global.songInfo.imageSrc); - } - - // Trigger the callbacks - callbacks.forEach(c => { - c(global.songInfo); - }); - }); -};