diff --git a/custom_components/spotcast/__init__.py b/custom_components/spotcast/__init__.py index f0b9a8c6..71d5273f 100644 --- a/custom_components/spotcast/__init__.py +++ b/custom_components/spotcast/__init__.py @@ -63,6 +63,7 @@ get_spotify_media_player, is_empty_str, is_valid_uri, + url_to_spotify_uri, ) from .spotcast_controller import SpotcastController @@ -243,6 +244,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 e9e4ca0e..42aee5fb 100644 --- a/custom_components/spotcast/helpers.py +++ b/custom_components/spotcast/helpers.py @@ -2,6 +2,9 @@ import asyncio import logging +import requests +import urllib.parse +import difflib import random import time from functools import partial, wraps @@ -434,6 +437,26 @@ def get_random_playlist_from_category( 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