From dac61bd4ccef8329f516336056201d2299ece909 Mon Sep 17 00:00:00 2001 From: Casey Callendrello Date: Thu, 23 Feb 2023 21:33:17 +0100 Subject: [PATCH] handle spotify web URLs as well This automatically converts spotify web URLs (e.g. https://open.spotify.com/track/XXX) to spotify URIs. Signed-off-by: Casey Callendrello --- custom_components/spotcast/__init__.py | 9 +++++++++ custom_components/spotcast/helpers.py | 22 +++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/custom_components/spotcast/__init__.py b/custom_components/spotcast/__init__.py index 9d33b7a8..55475dfb 100644 --- a/custom_components/spotcast/__init__.py +++ b/custom_components/spotcast/__init__.py @@ -56,6 +56,7 @@ get_random_playlist_from_category, get_search_results, is_valid_uri, + url_to_spotify_uri, ) from .spotcast_controller import SpotcastController @@ -229,6 +230,14 @@ def start_casting(call: ha_core.ServiceCall): # remove ? from badly formatted URI uri = uri.split("?")[0] + if uri.startswith("http"): + try: + u = url_to_spotify_uri(uri) + _LOGGER.debug("converted web URL %s to spotify URI %s", uri, u) + uri = u + except ValueError: + _LOGGER.error("invalid web URL provided, could not convert to spotify URI: %s", uri) + if not is_valid_uri(uri): _LOGGER.error("Invalid URI provided, aborting casting") return diff --git a/custom_components/spotcast/helpers.py b/custom_components/spotcast/helpers.py index 7895fefd..cc50bb6b 100644 --- a/custom_components/spotcast/helpers.py +++ b/custom_components/spotcast/helpers.py @@ -3,7 +3,7 @@ import asyncio import logging import requests -import urllib +import urllib.parse import difflib import random from functools import partial, wraps @@ -171,6 +171,26 @@ def get_random_playlist_from_category(spotify_client:spotipy.Spotify, category:s return chosen['uri'] + +def url_to_spotify_uri(url: str) -> str: + """ + Convert a spotify web url (e.g. https://open.spotify.com/track/XXXX) to + a spotify-style URI (spotify:track:XXXX). Returns None on error. + """ + + o: urllib.parse.ParseResult + # will raise ValueError if URL is invalid + o = urllib.parse.urlparse(url) + + if o.hostname != "open.spotify.com": + raise ValueError('Spotify URLs must have a hostname of "open.spotify.com"') + + path = o.path.split("/") + if len(path) != 3: + raise ValueError('Spotify URLs must be of the form "https://open.spotify.com//"') + + return f'spotify:{path[1]}:{path[2]}' + def is_valid_uri(uri: str) -> bool: # list of possible types