-
Notifications
You must be signed in to change notification settings - Fork 602
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
132 additions
and
120 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, "/"), | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
This file was deleted.
Oops, something went wrong.