lib.itmens/catalog/sites/spotify.py

152 lines
4.8 KiB
Python
Raw Normal View History

2022-12-08 15:45:37 +00:00
"""
Spotify
"""
import datetime
import logging
import time
import dateparser
import requests
2022-12-08 15:45:37 +00:00
from django.conf import settings
2022-12-08 15:45:37 +00:00
from catalog.common import *
from catalog.models import *
from catalog.music.utils import upc_to_gtin_13
2022-12-08 15:45:37 +00:00
from .douban import *
2022-12-08 15:45:37 +00:00
_logger = logging.getLogger(__name__)
spotify_token = None
spotify_token_expire_time = time.time()
2022-12-15 17:29:35 -05:00
@SiteManager.register
2022-12-08 15:45:37 +00:00
class Spotify(AbstractSite):
2022-12-16 01:08:10 -05:00
SITE_NAME = SiteName.Spotify
2022-12-08 15:45:37 +00:00
ID_TYPE = IdType.Spotify_Album
2023-08-14 14:01:54 -04:00
URL_PATTERNS = [
r"^\w+://open\.spotify\.com/album/([a-zA-Z0-9]+).*",
r"^\w+://open\.spotify\.com/[\w-]+/album/([a-zA-Z0-9]+).*",
]
2022-12-29 23:57:02 -05:00
WIKI_PROPERTY_ID = "?"
2022-12-08 15:45:37 +00:00
DEFAULT_MODEL = Album
@classmethod
def id_to_url(cls, id_value):
2022-12-08 15:45:37 +00:00
return f"https://open.spotify.com/album/{id_value}"
def scrape(self):
api_url = f"https://api.spotify.com/v1/albums/{self.id_value}"
2022-12-29 23:57:02 -05:00
headers = {"Authorization": f"Bearer {get_spotify_token()}"}
2022-12-08 15:45:37 +00:00
res_data = BasicDownloader(api_url, headers=headers).download().json()
artist = []
2022-12-29 23:57:02 -05:00
for artist_dict in res_data["artists"]:
artist.append(artist_dict["name"])
2022-12-08 15:45:37 +00:00
2022-12-29 23:57:02 -05:00
title = res_data["name"]
2022-12-08 15:45:37 +00:00
genre = res_data.get("genres", [])
2022-12-08 15:45:37 +00:00
company = []
2022-12-29 23:57:02 -05:00
for com in res_data["copyrights"]:
company.append(com["text"])
2022-12-08 15:45:37 +00:00
duration = 0
track_list = []
track_urls = []
2022-12-29 23:57:02 -05:00
for track in res_data["tracks"]["items"]:
track_urls.append(track["external_urls"]["spotify"])
duration += track["duration_ms"]
if res_data["tracks"]["items"][-1]["disc_number"] > 1:
2022-12-08 15:45:37 +00:00
# more than one disc
2022-12-29 23:57:02 -05:00
track_list.append(
str(track["disc_number"])
+ "-"
+ str(track["track_number"])
+ ". "
+ track["name"]
)
2022-12-08 15:45:37 +00:00
else:
2022-12-29 23:57:02 -05:00
track_list.append(str(track["track_number"]) + ". " + track["name"])
track_list = "\n".join(track_list)
2023-08-11 11:55:42 -04:00
dt = dateparser.parse(res_data["release_date"])
release_date = dt.strftime("%Y-%m-%d") if dt else None
2022-12-08 15:45:37 +00:00
gtin = None
2022-12-29 23:57:02 -05:00
if res_data["external_ids"].get("upc"):
gtin = upc_to_gtin_13(res_data["external_ids"].get("upc"))
2022-12-29 23:57:02 -05:00
if res_data["external_ids"].get("ean"):
gtin = upc_to_gtin_13(res_data["external_ids"].get("ean"))
2022-12-08 18:08:05 +00:00
isrc = None
2022-12-29 23:57:02 -05:00
if res_data["external_ids"].get("isrc"):
isrc = res_data["external_ids"].get("isrc")
pd = ResourceContent(
metadata={
"title": title,
"artist": artist,
"genre": genre,
"track_list": track_list,
"release_date": release_date,
"duration": duration,
"company": company,
"brief": None,
"cover_image_url": res_data["images"][0]["url"],
}
)
2022-12-08 15:45:37 +00:00
if gtin:
pd.lookup_ids[IdType.GTIN] = gtin
2022-12-08 18:08:05 +00:00
if isrc:
pd.lookup_ids[IdType.ISRC] = isrc
2022-12-08 15:45:37 +00:00
if pd.metadata["cover_image_url"]:
imgdl = BasicImageDownloader(pd.metadata["cover_image_url"], self.url)
try:
pd.cover_image = imgdl.download().content
pd.cover_image_extention = imgdl.extention
except Exception:
2022-12-29 23:57:02 -05:00
_logger.debug(
f'failed to download cover for {self.url} from {pd.metadata["cover_image_url"]}'
)
2022-12-08 15:45:37 +00:00
return pd
def get_spotify_token():
global spotify_token, spotify_token_expire_time
2022-12-08 16:59:03 +00:00
if get_mock_mode():
2022-12-29 23:57:02 -05:00
return "mocked"
2022-12-08 15:45:37 +00:00
if spotify_token is None or is_spotify_token_expired():
invoke_spotify_token()
return spotify_token
2022-12-16 01:08:10 -05:00
2022-12-08 15:45:37 +00:00
def is_spotify_token_expired():
global spotify_token_expire_time
return True if spotify_token_expire_time <= time.time() else False
def invoke_spotify_token():
global spotify_token, spotify_token_expire_time
r = requests.post(
"https://accounts.spotify.com/api/token",
2022-12-29 23:57:02 -05:00
data={"grant_type": "client_credentials"},
headers={"Authorization": f"Basic {settings.SPOTIFY_CREDENTIAL}"},
2022-12-08 15:45:37 +00:00
)
data = r.json()
if r.status_code == 401:
# token expired, try one more time
# this maybe caused by external operations,
# for example debugging using a http client
r = requests.post(
"https://accounts.spotify.com/api/token",
2022-12-29 23:57:02 -05:00
data={"grant_type": "client_credentials"},
headers={"Authorization": f"Basic {settings.SPOTIFY_CREDENTIAL}"},
2022-12-08 15:45:37 +00:00
)
data = r.json()
elif r.status_code != 200:
raise Exception(f"Request to spotify API fails. Reason: {r.reason}")
# minus 2 for execution time error
2022-12-29 23:57:02 -05:00
spotify_token_expire_time = int(data["expires_in"]) + time.time() - 2
spotify_token = data["access_token"]