mirror of
https://github.com/Alexander-D-Karpov/akarpov
synced 2025-07-15 01:22:17 +03:00
added external service for meta retrieve
This commit is contained in:
parent
f320fa2d62
commit
1b9b1d2bb5
76
akarpov/music/services/external.py
Normal file
76
akarpov/music/services/external.py
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import requests
|
||||||
|
from typing import Optional, Dict, Any
|
||||||
|
import structlog
|
||||||
|
from django.conf import settings
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ExternalServiceClient:
|
||||||
|
def __init__(self):
|
||||||
|
self.base_url = getattr(settings, 'MUSIC_EXTERNAL_SERVICE_URL', None)
|
||||||
|
|
||||||
|
def _make_request(self, endpoint: str, params: Dict = None, **kwargs) -> Optional[Dict]:
|
||||||
|
if not self.base_url:
|
||||||
|
return None
|
||||||
|
|
||||||
|
url = f"{self.base_url.rstrip('/')}/{endpoint.lstrip('/')}"
|
||||||
|
try:
|
||||||
|
response = requests.post(url, params=params, **kwargs)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
logger.error(
|
||||||
|
"External service request failed",
|
||||||
|
error=str(e),
|
||||||
|
endpoint=endpoint,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_spotify_info(self, track_name: str) -> Optional[Dict[str, Any]]:
|
||||||
|
return self._make_request(
|
||||||
|
"/spotify/search",
|
||||||
|
params={"query": track_name}
|
||||||
|
)
|
||||||
|
|
||||||
|
def translate_text(self, text: str, source_lang: str = "auto", target_lang: str = "en") -> Optional[str]:
|
||||||
|
response = self._make_request(
|
||||||
|
"/translation/translate",
|
||||||
|
json={
|
||||||
|
"text": text,
|
||||||
|
"source_lang": source_lang,
|
||||||
|
"target_lang": target_lang
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return response.get("translated_text") if response else None
|
||||||
|
|
||||||
|
|
||||||
|
def external_service_fallback(fallback_func):
|
||||||
|
"""Decorator to try external service first, then fall back to local implementation"""
|
||||||
|
|
||||||
|
@wraps(fallback_func)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
if not hasattr(settings, 'MUSIC_EXTERNAL_SERVICE_URL') or not settings.MUSIC_EXTERNAL_SERVICE_URL:
|
||||||
|
return fallback_func(*args, **kwargs)
|
||||||
|
|
||||||
|
client = ExternalServiceClient()
|
||||||
|
try:
|
||||||
|
if fallback_func.__name__ == "get_spotify_info":
|
||||||
|
result = client.get_spotify_info(args[1]) # args[1] is track_name
|
||||||
|
elif fallback_func.__name__ == "safe_translate":
|
||||||
|
result = client.translate_text(args[0]) # args[0] is text
|
||||||
|
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(
|
||||||
|
"External service failed, falling back to local implementation",
|
||||||
|
error=str(e),
|
||||||
|
function=fallback_func.__name__
|
||||||
|
)
|
||||||
|
|
||||||
|
return fallback_func(*args, **kwargs)
|
||||||
|
|
||||||
|
return wrapper
|
|
@ -4,6 +4,11 @@
|
||||||
import requests
|
import requests
|
||||||
import spotipy
|
import spotipy
|
||||||
|
|
||||||
|
from akarpov.music.services.external import (
|
||||||
|
ExternalServiceClient,
|
||||||
|
external_service_fallback,
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from deep_translator import GoogleTranslator
|
from deep_translator import GoogleTranslator
|
||||||
except requests.exceptions.JSONDecodeError:
|
except requests.exceptions.JSONDecodeError:
|
||||||
|
@ -76,6 +81,7 @@ def spotify_search(name: str, session: spotipy.Spotify, search_type="track"):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
@external_service_fallback
|
||||||
def get_spotify_info(name: str, session: spotipy.Spotify) -> dict:
|
def get_spotify_info(name: str, session: spotipy.Spotify) -> dict:
|
||||||
info = {
|
info = {
|
||||||
"album_name": "",
|
"album_name": "",
|
||||||
|
@ -379,29 +385,43 @@ def save_author_image(author, image_path):
|
||||||
print(f"Error saving author image: {str(e)}")
|
print(f"Error saving author image: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
def safe_translate(text):
|
@external_service_fallback
|
||||||
|
def safe_translate(text: str) -> str:
|
||||||
try:
|
try:
|
||||||
translated = GoogleTranslator(source="auto", target="en").translate(text)
|
translated = GoogleTranslator(source="auto", target="en").translate(text)
|
||||||
return slugify(translated)
|
return slugify(translated)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error translating text: {str(e)}")
|
print(f"Translation failed: {str(e)}")
|
||||||
return slugify(text)
|
return slugify(text)
|
||||||
|
|
||||||
|
|
||||||
def search_all_platforms(track_name: str) -> dict:
|
def search_all_platforms(track_name: str) -> dict:
|
||||||
print(track_name)
|
print(track_name)
|
||||||
# session = spotipy.Spotify(
|
|
||||||
# auth_manager=spotipy.SpotifyClientCredentials(
|
if settings.MUSIC_EXTERNAL_SERVICE_URL:
|
||||||
# client_id=settings.MUSIC_SPOTIFY_ID,
|
# Use external service if configured
|
||||||
# client_secret=settings.MUSIC_SPOTIFY_SECRET,
|
client = ExternalServiceClient()
|
||||||
# )
|
spotify_info = client.get_spotify_info(track_name) or {}
|
||||||
# )
|
else:
|
||||||
# spotify_info = get_spotify_info(track_name, session)
|
# Local implementation fallback
|
||||||
spotify_info = {} # TODO: add proxy for info retrieve
|
try:
|
||||||
|
session = spotipy.Spotify(
|
||||||
|
auth_manager=SpotifyClientCredentials(
|
||||||
|
client_id=settings.MUSIC_SPOTIFY_ID,
|
||||||
|
client_secret=settings.MUSIC_SPOTIFY_SECRET,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
spotify_info = get_spotify_info(track_name, session)
|
||||||
|
except Exception as e:
|
||||||
|
print("Local Spotify implementation failed", error=str(e))
|
||||||
|
spotify_info = {}
|
||||||
|
|
||||||
yandex_info = search_yandex(track_name)
|
yandex_info = search_yandex(track_name)
|
||||||
|
|
||||||
if "album_image_path" in spotify_info and "album_image_path" in yandex_info:
|
if "album_image_path" in spotify_info and "album_image_path" in yandex_info:
|
||||||
os.remove(yandex_info["album_image_path"])
|
os.remove(yandex_info["album_image_path"])
|
||||||
|
|
||||||
|
# Combine artist information
|
||||||
combined_artists = set()
|
combined_artists = set()
|
||||||
for artist in spotify_info.get("artists", []) + yandex_info.get("artists", []):
|
for artist in spotify_info.get("artists", []) + yandex_info.get("artists", []):
|
||||||
normalized_artist = normalize_text(artist)
|
normalized_artist = normalize_text(artist)
|
||||||
|
@ -410,12 +430,13 @@ def search_all_platforms(track_name: str) -> dict:
|
||||||
for existing_artist in combined_artists
|
for existing_artist in combined_artists
|
||||||
):
|
):
|
||||||
combined_artists.add(normalized_artist)
|
combined_artists.add(normalized_artist)
|
||||||
genre = spotify_info.get("genre") or yandex_info.get("genre")
|
|
||||||
if type(genre) is list:
|
|
||||||
genre = sorted(genre, key=lambda x: len(x))
|
|
||||||
genre = genre[0]
|
|
||||||
|
|
||||||
track_info = {
|
# Process genre information
|
||||||
|
genre = spotify_info.get("genre") or yandex_info.get("genre")
|
||||||
|
if isinstance(genre, list) and genre:
|
||||||
|
genre = sorted(genre, key=len)[0]
|
||||||
|
|
||||||
|
return {
|
||||||
"album_name": spotify_info.get("album_name")
|
"album_name": spotify_info.get("album_name")
|
||||||
or yandex_info.get("album_name", ""),
|
or yandex_info.get("album_name", ""),
|
||||||
"release": spotify_info.get("release") or yandex_info.get("release", ""),
|
"release": spotify_info.get("release") or yandex_info.get("release", ""),
|
||||||
|
@ -425,5 +446,3 @@ def search_all_platforms(track_name: str) -> dict:
|
||||||
"album_image": spotify_info.get("album_image_path")
|
"album_image": spotify_info.get("album_image_path")
|
||||||
or yandex_info.get("album_image_path", None),
|
or yandex_info.get("album_image_path", None),
|
||||||
}
|
}
|
||||||
|
|
||||||
return track_info
|
|
||||||
|
|
|
@ -715,6 +715,9 @@
|
||||||
LAST_FM_API_KEY = env("LAST_FM_API_KET", default="")
|
LAST_FM_API_KEY = env("LAST_FM_API_KET", default="")
|
||||||
LAST_FM_SECRET = env("LAST_FM_SECRET", default="")
|
LAST_FM_SECRET = env("LAST_FM_SECRET", default="")
|
||||||
|
|
||||||
|
# EXTERNAL
|
||||||
|
MUSIC_EXTERNAL_SERVICE_URL = env("MUSIC_EXTERNAL_SERVICE_URL", default="")
|
||||||
|
|
||||||
# ROBOTS
|
# ROBOTS
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
ROBOTS_USE_SITEMAP = True
|
ROBOTS_USE_SITEMAP = True
|
||||||
|
|
Loading…
Reference in New Issue
Block a user