Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Max Erenberg
2020-09-01 02:10:59 -04:00
100 changed files with 4777 additions and 2374 deletions

View File

@ -3,7 +3,7 @@ import pathlib
from mopidy import config, ext
__version__ = "3.51.0"
__version__ = "3.52.4"
logger = logging.getLogger(__name__)

View File

@ -38,6 +38,10 @@ class IrisCore(pykka.ThreadingActor):
"seed_tracks": [],
"results": [],
}
data = {
"commands": [],
"pinned": [],
}
ioloop = None
@classmethod
@ -55,8 +59,9 @@ class IrisCore(pykka.ThreadingActor):
def start(self):
logger.info("Starting Iris " + Extension.version)
# Load our commands from file
self.commands = self.load_from_file("commands")
# Load our commands and pinned items from file
self.data["commands"] = self.load_from_file("commands")
self.data["pinned"] = self.load_from_file("pinned")
##
# Mopidy is shutting down
@ -79,7 +84,10 @@ class IrisCore(pykka.ThreadingActor):
f.close()
return content
except Exception:
return {}
if name == "pinned":
return []
else:
return {}
##
# Save dict object to disk
@ -654,6 +662,7 @@ class IrisCore(pykka.ThreadingActor):
return response
async def load_more_tracks(self, *args, **kwargs):
logger.info("Loading more radio tracks from Spotify")
try:
await self.get_spotify_token()
spotify_token = self.spotify_token
@ -702,7 +711,7 @@ class IrisCore(pykka.ThreadingActor):
except (urllib.error.HTTPError, urllib.error.URLError) as e:
error = json.loads(e.read())
error = {
error_response = {
"message": "Could not fetch Spotify recommendations: "
+ error["error_description"]
}
@ -710,10 +719,10 @@ class IrisCore(pykka.ThreadingActor):
"Could not fetch Spotify recommendations: "
+ error["error_description"]
)
logger.debug(error)
logger.debug(error_response)
return False
def check_for_radio_update(self):
async def check_for_radio_update(self):
tracklistLength = self.core.tracklist.get_length().get()
if tracklistLength < 3 and self.radio["enabled"] == 1:
@ -723,7 +732,7 @@ class IrisCore(pykka.ThreadingActor):
# We've run out of pre-fetched tracks, so we need to get more
# recommendations
if len(uris) < 3:
uris = self.load_more_tracks()
uris = await self.load_more_tracks()
# Remove the next batch, and update our results
self.radio["results"] = uris[3:]
@ -822,49 +831,70 @@ class IrisCore(pykka.ThreadingActor):
self.queue_metadata = cleaned_queue_metadata
##
# Commands
# Server-side data assets
#
# These are stored locally for all users to access
# These functions are used internally to store data locally for all users to access
##
def get_commands(self, *args, **kwargs):
def get_data(self, name, *args, **kwargs):
callback = kwargs.get("callback", False)
response = {"commands": self.commands}
response = {name: self.data[name]}
if callback:
callback(response)
else:
return response
def set_commands(self, *args, **kwargs):
def set_data(self, name, *args, **kwargs):
callback = kwargs.get("callback", False)
data = kwargs.get("data", {})
# Update our temporary variable
self.commands = data["commands"]
self.data[name] = data[name]
# Save the new commands to file storage
self.save_to_file(self.commands, "commands")
self.save_to_file(self.data[name], name)
self.broadcast(
data={
"method": "commands_changed",
"params": {"commands": self.commands},
"method": f"{name}_changed",
"params": {name: self.data[name]},
}
)
response = {"message": "Commands saved"}
response = {"message": f"Saved {name}"}
if callback:
callback(response)
else:
return response
##
# Pinned assets
##
def get_pinned(self, *args, **kwargs):
return self.get_data("pinned", *args, **kwargs)
def set_pinned(self, *args, **kwargs):
return self.set_data("pinned", *args, **kwargs)
##
# Commands
##
def get_commands(self, *args, **kwargs):
return self.get_data("commands", *args, **kwargs)
def set_commands(self, *args, **kwargs):
return self.set_data("commands", *args, **kwargs)
async def run_command(self, *args, **kwargs):
callback = kwargs.get("callback", False)
data = kwargs.get("data", {})
error = False
if str(data["id"]) not in self.commands:
if str(data["id"]) not in self.data["commands"]:
error = {
"message": "Command failed",
"description": "Could not find command by ID "
@ -873,7 +903,7 @@ class IrisCore(pykka.ThreadingActor):
+ '"',
}
else:
command = self.commands[str(data["id"])]
command = self.data["commands"][str(data["id"])]
if "method" not in command:
error = {
"message": "Command failed",
@ -991,14 +1021,24 @@ class IrisCore(pykka.ThreadingActor):
async def refresh_spotify_token(self, *args, **kwargs):
callback = kwargs.get("callback", None)
# Use client_id and client_secret from config
# This was introduced in Mopidy-Spotify 3.1.0
url = "https://auth.mopidy.com/spotify/token"
data = {
"client_id": self.config["spotify"]["client_id"],
"client_secret": self.config["spotify"]["client_secret"],
"grant_type": "client_credentials",
}
try:
# Use client_id and client_secret from config
# This was introduced in Mopidy-Spotify 3.1.0
url = "https://auth.mopidy.com/spotify/token"
data = {
"client_id": self.config["spotify"]["client_id"],
"client_secret": self.config["spotify"]["client_secret"],
"grant_type": "client_credentials",
}
except (Exception):
error = {
"message": "Could not refresh Spotify token: invalid configuration"
}
if callback:
callback(False, error)
else:
return error
try:
http_client = tornado.httpclient.AsyncHTTPClient()
@ -1027,7 +1067,7 @@ class IrisCore(pykka.ThreadingActor):
except (urllib.error.HTTPError, urllib.error.URLError) as e:
error = json.loads(e.read())
error = {
"message": "Could not refresh token: "
"message": "Could not refresh Spotify token: "
+ error["error_description"]
}
@ -1098,12 +1138,11 @@ class IrisCore(pykka.ThreadingActor):
except (urllib.error.HTTPError, urllib.error.URLError) as e:
error = json.loads(e.read())
error = {
"message": "Could not fetch Spotify recommendations: "
"message": "Could not fetch Genius lyrics: "
+ error["error_description"]
}
logger.error(
"Could not fetch Spotify recommendations: "
+ error["error_description"]
"Could not fetch Genius lyrics: " + error["error_description"]
)
logger.debug(error)
return error

View File

@ -23,7 +23,13 @@ class IrisFrontend(pykka.ThreadingActor, CoreListener):
iris.stop()
def track_playback_ended(self, tl_track, time_position):
iris.ioloop.add_callback(functools.partial(iris.check_for_radio_update))
if iris.ioloop:
iris.ioloop.add_callback(
functools.partial(iris.check_for_radio_update)
)
def tracklist_changed(self):
iris.ioloop.add_callback(functools.partial(iris.clean_queue_metadata))
if iris.ioloop:
iris.ioloop.add_callback(
functools.partial(iris.clean_queue_metadata)
)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View File

@ -106,8 +106,8 @@
// Release details
// These are automatically injected to built HTML
var build = "1597898076";
var version = "3.51.0";
var build = "1598940390";
var version = "3.52.4";
// Construct the script tag
var js = document.createElement("script");

View File

@ -1,5 +1,5 @@
{
"manifest_version": "3.51.0",
"manifest_version": "3.52.4",
"short_name": "Iris",
"name": "Iris",
"icons": [