diff --git a/scrobbler-vivaldi-plex/icon128.png b/scrobbler-vivaldi-plex/icon128.png deleted file mode 100644 index 042e50d..0000000 Binary files a/scrobbler-vivaldi-plex/icon128.png and /dev/null differ diff --git a/scrobbler-vivaldi-plex/icon256.png b/scrobbler-vivaldi-plex/icon256.png deleted file mode 100644 index 8a25766..0000000 Binary files a/scrobbler-vivaldi-plex/icon256.png and /dev/null differ diff --git a/scrobbler-vivaldi-plex/icon48.png b/scrobbler-vivaldi-plex/icon48.png deleted file mode 100644 index f21e770..0000000 Binary files a/scrobbler-vivaldi-plex/icon48.png and /dev/null differ diff --git a/scrobblers/.gitignore b/scrobblers/.gitignore new file mode 100644 index 0000000..01b9fd9 --- /dev/null +++ b/scrobblers/.gitignore @@ -0,0 +1 @@ +*.xcf diff --git a/scrobbler-vivaldi-plex/background.js b/scrobblers/chromium-plex/background.js similarity index 100% rename from scrobbler-vivaldi-plex/background.js rename to scrobblers/chromium-plex/background.js diff --git a/scrobbler-vivaldi-plex/contentScript.js b/scrobblers/chromium-plex/contentScript.js similarity index 100% rename from scrobbler-vivaldi-plex/contentScript.js rename to scrobblers/chromium-plex/contentScript.js diff --git a/scrobblers/chromium-plex/icon128.png b/scrobblers/chromium-plex/icon128.png new file mode 100644 index 0000000..23abc0b Binary files /dev/null and b/scrobblers/chromium-plex/icon128.png differ diff --git a/scrobblers/chromium-plex/icon256.png b/scrobblers/chromium-plex/icon256.png new file mode 100644 index 0000000..754a0c1 Binary files /dev/null and b/scrobblers/chromium-plex/icon256.png differ diff --git a/scrobblers/chromium-plex/icon48.png b/scrobblers/chromium-plex/icon48.png new file mode 100644 index 0000000..5cb2120 Binary files /dev/null and b/scrobblers/chromium-plex/icon48.png differ diff --git a/scrobbler-vivaldi-plex/manifest.json b/scrobblers/chromium-plex/manifest.json similarity index 100% rename from scrobbler-vivaldi-plex/manifest.json rename to scrobblers/chromium-plex/manifest.json diff --git a/scrobbler-vivaldi-plex/settings.html b/scrobblers/chromium-plex/settings.html similarity index 100% rename from scrobbler-vivaldi-plex/settings.html rename to scrobblers/chromium-plex/settings.html diff --git a/scrobbler-vivaldi-plex/settings.js b/scrobblers/chromium-plex/settings.js similarity index 100% rename from scrobbler-vivaldi-plex/settings.js rename to scrobblers/chromium-plex/settings.js diff --git a/scrobblers/chromium-youtubemusic/background.js b/scrobblers/chromium-youtubemusic/background.js new file mode 100644 index 0000000..b8c6b27 --- /dev/null +++ b/scrobblers/chromium-youtubemusic/background.js @@ -0,0 +1,231 @@ + + +chrome.tabs.onUpdated.addListener(onTabUpdated); +chrome.tabs.onRemoved.addListener(onTabRemoved); +chrome.tabs.onActivated.addListener(onTabChanged); +chrome.runtime.onMessage.addListener(onPlaybackUpdate); + +function onTabUpdated(tabId, changeInfo, tab) { + console.log("Update") + chrome.tabs.get(tabId,party) +} + +function onTabRemoved() { + +} + +function onTabChanged(activeInfo) { +} + + +function party(tab) { + + var patterns = [ + "https://music.youtube.com", + "http://music.youtube.com" + ]; + + importantPage = false + + for (var i=0;i currentLength) { + alreadyPlayed = alreadyPlayed - currentLength + scrobble(currentArtist,currentTitle,currentLength) + } + + setUpdate() + currentlyPlaying = true + + } + + // CASE 2: New track is being played + else if (artist != currentArtist || title != currentTitle) { + + //first inform ourselves that the previous track has now been stopped for good + stopPlayback(artist,title) + //then initialize new playback + console.log("New track") + setUpdate() + alreadyPlayed = 0 + currentTitle = title + currentArtist = artist + currentLength = seconds + console.log(artist + " - " + title + " is playing!") + currentlyPlaying = true + } +} + +// the artist and title arguments are not attributes of the track being stopped, but of the track active now +// they are here to recognize whether the playback has been paused or completely ended / replaced +function stopPlayback(artist,title) { + + //CASE 1: Playback just paused OR CASE 2: Playback ended + if (currentlyPlaying) { + d = setUpdate() + alreadyPlayed = alreadyPlayed + d + console.log(d + " seconds played since last update, " + alreadyPlayed + " seconds played overall") + } + + + // Already played full song + while (alreadyPlayed > currentLength) { + alreadyPlayed = alreadyPlayed - currentLength + scrobble(currentArtist,currentTitle,currentLength) + } + + currentlyPlaying = false + + + + //ONLY CASE 2: Playback ended + if (artist != currentArtist || title != currentTitle) { + if (alreadyPlayed > currentLength / 2) { + scrobble(currentArtist,currentTitle,alreadyPlayed) + alreadyPlayed = 0 + } + } +} + + +// One problem here: Closing the player while it's paused does not cause an event, so the track will only be scrobbled the next time we play something. +// Also potentially problematic: Pausing a track and just leaving it should probably trigger a scrobble after some time because we can assume the user just stopped listening but didn't bother to press the X +// We could simply check for scrobblability when the track is paused, but this would remove the ability to send listening time with the scrobble + + +function ostopPlayback(artist,title) { + currentlyPlaying = false + console.log("Playback stopped!") + d = new Date() + t = Math.floor(d.getTime()/1000) + delta = t - lastUpdate + console.log("Since the last update, " + delta + " seconds of music have been played") + alreadyPlayed = alreadyPlayed + delta + console.log(alreadyPlayed + " seconds of this track have been played overall") + if ((alreadyPlayed > currentLength/2) && !alreadyScrobbled) { + console.log("Enough to scrobble: " + currentArtist + " - " + currentTitle) + scrobble(currentArtist,currentTitle) + alreadyScrobbled = true + } +} + +function ostartPlayback(artist,title,seconds) { + + console.log("Playback started!") + if (artist == currentArtist && title == currentTitle && !currentlyPlaying) { + console.log("Still previous track!") + while (alreadyPlayed > currentLength) { + console.log("This song is being played several times in a row!") + if (!alreadyScrobbled) { + scrobble(currentArtist,currentTitle) + //alreadyScrobbled = true + } + alreadyPlayed = alreadyPlayed - currentLength + alreadyScrobbled = false + + } + d = new Date() + t = Math.floor(d.getTime()/1000) + lastUpdate = t + currentlyPlaying = true + } + else if (artist != currentArtist || title != currentTitle) { + console.log("New track!") + if (currentlyPlaying) { + console.log("We were playing another track before, so let's check if we should scrobble that.") + d = new Date() + t = Math.floor(d.getTime()/1000) + delta = t - lastUpdate + console.log("Since the last update, " + delta + " seconds of music have been played") + alreadyPlayed = alreadyPlayed + delta + + } + + console.log("The previous track was played for " + alreadyPlayed + " seconds, that's " + Math.floor(alreadyPlayed/currentLength * 100) + "% of its length.") + if (alreadyPlayed > currentLength/2 && !alreadyScrobbled) { + console.log("Enough to scrobble: " + currentArtist + " - " + currentTitle) + scrobble(currentArtist,currentTitle) + + } + else if (alreadyScrobbled) { + console.log("We already scrobbled this track tho.") + alreadyScrobbled = false + } + + + console.log("But now, new track!") + d = new Date() + t = Math.floor(d.getTime()/1000) + lastUpdate = t + alreadyPlayed = 0 + currentTitle = title + currentArtist = artist + currentLength = seconds + console.log(artist + " - " + title + " is playing!") + currentlyPlaying = true + } +} + + + +function scrobble(artist,title,seconds) { + console.log("Scrobbling " + artist + " - " + title + "; " + seconds + " seconds playtime") + artiststring = encodeURIComponent(artist) + titlestring = encodeURIComponent(title) + chrome.storage.local.get("apikey",function(result) { + APIKEY = result["apikey"] + chrome.storage.local.get("serverurl",function(result) { + URL = result["serverurl"] + var xhttp = new XMLHttpRequest(); + xhttp.open("POST",URL + "/db/newscrobble",true); + xhttp.send("artist=" + artiststring + "&title=" + titlestring + "&duration=" + seconds + "&key=" + APIKEY) + }); + }); + + +} + +function setUpdate() { + d = new Date() + t = Math.floor(d.getTime()/1000) + delta = t - lastUpdate + lastUpdate = t + return delta +} diff --git a/scrobblers/chromium-youtubemusic/contentScript.js b/scrobblers/chromium-youtubemusic/contentScript.js new file mode 100644 index 0000000..b4e9a68 --- /dev/null +++ b/scrobblers/chromium-youtubemusic/contentScript.js @@ -0,0 +1,40 @@ +bar = document.querySelector("ytmusic-player-bar") +if (bar == null) { + console.log("Nothing playing right now!") + chrome.runtime.sendMessage({type:"stopPlayback",artist:"",title:""}) + exit() +} + +metadata = bar.querySelector("div[class*=middle-controls] > div[class*=content-info-wrapper]") + +ctrl = bar.querySelector("div[class*=left-controls]") + +title = metadata.querySelector("yt-formatted-string[class*=title]").getAttribute("title") +artist = metadata.querySelector("span > span[class*=subtitle] > yt-formatted-string > a:nth-child(1)").innerHTML +duration = ctrl.querySelector("[class*=time-info]").innerHTML.split("/")[1] +if (duration.split(":").length == 2) { + durationSeconds = parseInt(duration.split(":")[0]) * 60 + parseInt(duration.split(":")[1]) +} +else { + durationSeconds = parseInt(duration.split(":")[0]) * 60 * 60 + parseInt(duration.split(":")[1]) * 60 + parseInt(duration.split(":")[2]) +} + + +control = ctrl.querySelector("div > paper-icon-button[class*=play-pause-button]").getAttribute("title") +if (control == "Play") { + console.log("Not playing right now") + chrome.runtime.sendMessage({type:"stopPlayback",artist:artist,title:title}) + //stopPlayback() +} +else if (control == "Pause") { + console.log("Playing " + artist + " - " + title) + chrome.runtime.sendMessage({type:"startPlayback",artist:artist,title:title,duration:durationSeconds}) + //startPlayback(artist,title,durationSeconds) +} + + + + + + + diff --git a/scrobblers/chromium-youtubemusic/icon128.png b/scrobblers/chromium-youtubemusic/icon128.png new file mode 100644 index 0000000..df0435d Binary files /dev/null and b/scrobblers/chromium-youtubemusic/icon128.png differ diff --git a/scrobblers/chromium-youtubemusic/icon256.png b/scrobblers/chromium-youtubemusic/icon256.png new file mode 100644 index 0000000..0462c28 Binary files /dev/null and b/scrobblers/chromium-youtubemusic/icon256.png differ diff --git a/scrobblers/chromium-youtubemusic/icon48.png b/scrobblers/chromium-youtubemusic/icon48.png new file mode 100644 index 0000000..e8749e3 Binary files /dev/null and b/scrobblers/chromium-youtubemusic/icon48.png differ diff --git a/scrobblers/chromium-youtubemusic/manifest.json b/scrobblers/chromium-youtubemusic/manifest.json new file mode 100644 index 0000000..075b54c --- /dev/null +++ b/scrobblers/chromium-youtubemusic/manifest.json @@ -0,0 +1,31 @@ +{ + "name": "Youtoja", + "version": "0.1", + "description": "Scrobbles tracks from YouTube Music to your Maloja server", + "manifest_version": 2, + "permissions": ["activeTab", "declarativeContent","tabs","storage","http://music.youtube.com/*","https://music.youtube.com/*"], + "background": + { + "scripts": + [ + "background.js" + ] + }, + + + "browser_action": + { + "default_icon": + { + "128":"icon128.png", + "48":"icon48.png" + }, + "default_popup": "settings.html", + "default_title": "Settings" + }, + "icons": + { + "128":"icon128.png", + "48":"icon48.png" + } +} diff --git a/scrobblers/chromium-youtubemusic/settings.html b/scrobblers/chromium-youtubemusic/settings.html new file mode 100644 index 0000000..b9d83b2 --- /dev/null +++ b/scrobblers/chromium-youtubemusic/settings.html @@ -0,0 +1,18 @@ + + + + + Wat + + + + +
+ Server:
+ +

+ API key:
+ +
+ + diff --git a/scrobblers/chromium-youtubemusic/settings.js b/scrobblers/chromium-youtubemusic/settings.js new file mode 100644 index 0000000..ac403e2 --- /dev/null +++ b/scrobblers/chromium-youtubemusic/settings.js @@ -0,0 +1,77 @@ + +document.addEventListener("DOMContentLoaded",function() { + document.getElementById("serverurl").addEventListener("input",updateServer); + document.getElementById("apikey").addEventListener("input",updateAPIKey); + + document.getElementById("serverurl").addEventListener("change",checkServer); + document.getElementById("apikey").addEventListener("change",checkServer); + + + chrome.storage.local.get({"serverurl":"http://localhost:42010"},function(result) { + document.getElementById("serverurl").value = result["serverurl"] + checkServer() + }); + chrome.storage.local.get({"apikey":"BlackPinkInYourArea"},function(result) { + document.getElementById("apikey").value = result["apikey"] + checkServer() + }); + + + +}); + + + +function updateServer() { + + text = document.getElementById("serverurl").value + + + chrome.storage.local.set({"serverurl":text}) +} + +function updateAPIKey() { + text = document.getElementById("apikey").value + chrome.storage.local.set({"apikey":text}) +} + +function checkServer() { + url = document.getElementById("serverurl").value + "/db/test?key=" + document.getElementById("apikey").value + + var xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = createCheckmarks; + try { + xhttp.open("GET",url,true); + xhttp.send(); + } + catch (e) { + //document.getElementById("checkmark_url").innerHTML = "❌" + //document.getElementById("checkmark_key").innerHTML = "❌" + document.getElementById("serverurl").style.backgroundColor = "red" + document.getElementById("apikey").style.backgroundColor = "red" + } + +} + +function createCheckmarks() { + if (this.readyState == 4) { + if ((this.status == 204) || (this.status == 205)) { + //document.getElementById("checkmark_url").innerHTML = "✔️" + //document.getElementById("checkmark_key").innerHTML = "✔️" + document.getElementById("serverurl").style.backgroundColor = "lawngreen" + document.getElementById("apikey").style.backgroundColor = "lawngreen" + } + else if (this.status == 403) { + //document.getElementById("checkmark_url").innerHTML = "✔️" + //document.getElementById("checkmark_key").innerHTML = "❌" + document.getElementById("serverurl").style.backgroundColor = "lawngreen" + document.getElementById("apikey").style.backgroundColor = "red" + } + else { + //document.getElementById("checkmark_url").innerHTML = "❌" + //document.getElementById("checkmark_key").innerHTML = "❌" + document.getElementById("serverurl").style.backgroundColor = "red" + document.getElementById("apikey").style.backgroundColor = "red" + } + } +}