diff --git a/database.py b/database.py index e03499c..eb5f723 100644 --- a/database.py +++ b/database.py @@ -4,6 +4,7 @@ import waitress import os import datetime import cleanup +import sys SCROBBLES = [] # Format: tuple(track_ref,timestamp,saved) @@ -114,7 +115,18 @@ def post_scrobble(): (artists,title) = cleanup.fullclean(artists,title) time = int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp()) + ## this is necessary for localhost testing + response.set_header("Access-Control-Allow-Origin","*") + createScrobble(artists,title,time) + + return "" + +@route("/flush") +def abouttoshutdown(): + flush() + print("Database saved to disk.") + #sys.exit() # Starts the server def runserver(DATABASE_PORT): diff --git a/scrobbler-vivaldi-plex/background.js b/scrobbler-vivaldi-plex/background.js new file mode 100644 index 0000000..43f368f --- /dev/null +++ b/scrobbler-vivaldi-plex/background.js @@ -0,0 +1,133 @@ + + +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) { + chrome.tabs.get(tabId,party) +} + +function onTabRemoved() { + +} + +function onTabChanged(activeInfo) { +} + + +function party(tab) { + + var patterns = [ + "https://app.plex.tv", + "http://app.plex.tv", + "https://plex.", + "http://plex." + ]; + + importantPage = false + + for (var i=0;i 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 stopPlayback() { + 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 scrobble(artist,title) { + artiststring = encodeURIComponent(artist) + titlestring = encodeURIComponent(title) + var xhttp = new XMLHttpRequest(); + xhttp.open("GET","http://localhost:12345/db/newscrobble?artist=" + artiststring + "&title=" + titlestring,true); + xhttp.send() +} + +/// i have to add content scripts to the specific tab and then send messages to the extension diff --git a/scrobbler-vivaldi-plex/contentScript.js b/scrobbler-vivaldi-plex/contentScript.js new file mode 100644 index 0000000..a9fb50a --- /dev/null +++ b/scrobbler-vivaldi-plex/contentScript.js @@ -0,0 +1,42 @@ +//activeLibrary = document.querySelector("[data-qa-id*=sidebarLibrariesList]").querySelector("[class*=Link-isSelected]") + +//currentArtist = "" +//currentTitle = "" +//alreadyPlayed = 0 +//maxLength = 0 +//lastUpdate = 0 + + + +bar = document.querySelector("div[class*=PlayerControls]") +if (bar == null) { + console.log("Nothing playing right now!") + chrome.runtime.sendMessage({type:"stopPlayback"}) + exit() +} + +metadata = bar.querySelector("div[class*=PlayerControlsMetadata-container]") + +title = metadata.querySelector("a[class*=MetadataPosterTitle-singleLineTitle]").getAttribute("title") +artist = metadata.querySelector("span[class*=MetadataPosterTitle-title] > a:nth-child(1)").getAttribute("title") +duration = metadata.querySelector("[data-qa-id=mediaDuration]").innerHTML.split("/")[1] +durationSeconds = parseInt(duration.split(":")[0]) * 60 + parseInt(duration.split(":")[1]) + +control = bar.querySelector("div[class*=PlayerControls-buttonGroupCenter] > button:nth-child(2)").getAttribute("title") +if (control == "Play") { + console.log("Not playing right now") + chrome.runtime.sendMessage({type:"stopPlayback"}) + //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/scrobbler-vivaldi-plex/icon128.png b/scrobbler-vivaldi-plex/icon128.png new file mode 100644 index 0000000..949d7af Binary files /dev/null and b/scrobbler-vivaldi-plex/icon128.png differ diff --git a/scrobbler-vivaldi-plex/icon256.png b/scrobbler-vivaldi-plex/icon256.png new file mode 100644 index 0000000..9911120 Binary files /dev/null and b/scrobbler-vivaldi-plex/icon256.png differ diff --git a/scrobbler-vivaldi-plex/icon48.png b/scrobbler-vivaldi-plex/icon48.png new file mode 100644 index 0000000..c2da2d6 Binary files /dev/null and b/scrobbler-vivaldi-plex/icon48.png differ diff --git a/scrobbler-vivaldi-plex/manifest.json b/scrobbler-vivaldi-plex/manifest.json new file mode 100644 index 0000000..b217284 --- /dev/null +++ b/scrobbler-vivaldi-plex/manifest.json @@ -0,0 +1,48 @@ +{ + "name": "Plexoja", + "version": "0.1", + "description": "Scrobbles tracks from Plex Web to your Maloja server", + "manifest_version": 2, + "permissions": ["activeTab", "declarativeContent","tabs","http://app.plex.tv/*"], + "background": + { + "scripts": + [ + "background.js" + ] + }, + "content_scripts": + [ + { + "matches": + [ + "http://app.plex.tv/*", + "https://app.plex.tv/*" + ], + "include_globs": + [ + "http://plex.*", + "https://plex.*" + ], + "js": + [ + "contentScript.js" + ] + } + + ], + + "browser_action": + { + "default_icon": + { + "128":"icon128.png", + "48":"icon48.png" + } + }, + "icons": + { + "128":"icon128.png", + "48":"icon48.png" + } +} diff --git a/server.py b/server.py index be4d100..55bd736 100755 --- a/server.py +++ b/server.py @@ -1,7 +1,5 @@ from bottle import route, run, template, static_file, request, response -#import os from importlib.machinery import SourceFileLoader -#from serverutil import log, db_remove, createVideoFile import _thread import waitress import urllib.request @@ -11,18 +9,6 @@ import urllib.parse MAIN_PORT = 12345 DATABASE_PORT = 12349 -#@route("//") -#@route("//") -#@route("//") -#@route("//") -#@route("//") -#@route("//") -#@route("//") -#@route("/") -def static(pth): - - return static_file(pth,root="") - @route("") @route("/") @@ -42,13 +28,25 @@ def database(pth): keystring += urllib.parse.quote(k) + "=" + urllib.parse.quote(keys[k]) + "&" contents = urllib.request.urlopen("http://localhost:" + str(DATABASE_PORT) + "/" + pth + keystring).read() response.content_type = "application/json" + response.set_header("Access-Control-Allow-Origin","*") #print("Returning " + "http://localhost:" + str(DATABASE_PORT) + "/" + pth) return contents +@route("/exit") +def shutdown(): + urllib.request.urlopen("http://localhost:" + str(DATABASE_PORT) + "/flush") + print("Server shutting down...") + sys.exit() + + +@route("/") +def static(pth): + + return static_file(pth,root="") -## other programs to always run with the server +## start database server _thread.start_new_thread(SourceFileLoader("database","database.py").load_module().runserver,(DATABASE_PORT,)) run(host='0.0.0.0', port=MAIN_PORT, server='waitress')