add related links
artist links to feed page (/feed/:ID) release links to feed xml (release description)
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
import re
|
||||
import musicbrainzngs
|
||||
import logging
|
||||
from .config import config
|
||||
from datetime import datetime
|
||||
from email.utils import formatdate
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def init_musicbrainz():
|
||||
app_name = config.MB_APP_NAME
|
||||
version = config.MB_VERSION
|
||||
contact = config.MB_CONTACT
|
||||
|
||||
logger.debug(f"Initializing MusicBrainz API with user agent: {app_name}/{version} ( {contact} )")
|
||||
musicbrainzngs.set_useragent(app_name, version, contact)
|
||||
|
||||
def search_artists(query):
|
||||
logger.debug(f"Searching for artists with query: '{query}'")
|
||||
try:
|
||||
result = musicbrainzngs.search_artists(query=query, limit=10)
|
||||
artists = []
|
||||
if 'artist-list' in result:
|
||||
for artist in result['artist-list']:
|
||||
artists.append({
|
||||
'id': artist['id'],
|
||||
'name': artist['name'],
|
||||
'disambiguation': artist.get('disambiguation', '')
|
||||
})
|
||||
logger.debug(f"Found {len(artists)} artists for query: '{query}'")
|
||||
return artists
|
||||
except musicbrainzngs.MusicBrainzError as e:
|
||||
logger.error(f"MusicBrainz API error while searching for '{query}': {e}")
|
||||
return []
|
||||
|
||||
def _parse_release_date(release_date_str, release_title):
|
||||
"""Parse a release date string which can be YYYY, YYYY-MM, or YYYY-MM-DD."""
|
||||
if not release_date_str:
|
||||
return None, None
|
||||
|
||||
date_formats = ['%Y-%m-%d', '%Y-%m', '%Y']
|
||||
dt = None
|
||||
for fmt in date_formats:
|
||||
try:
|
||||
dt = datetime.strptime(release_date_str, fmt)
|
||||
if fmt == '%Y-%m':
|
||||
dt = dt.replace(day=1)
|
||||
elif fmt == '%Y':
|
||||
dt = dt.replace(month=1, day=1)
|
||||
break # Found a valid format
|
||||
except (ValueError, TypeError):
|
||||
continue
|
||||
|
||||
if dt:
|
||||
return dt, formatdate(dt.timestamp())
|
||||
|
||||
logger.warning(f"Could not parse date format '{release_date_str}' for release '{release_title}'")
|
||||
return None, None
|
||||
|
||||
def _process_release(release, artist_id):
|
||||
"""Process a single release from the MusicBrainz API response."""
|
||||
release_date = release.get('date', 'Unknown')
|
||||
_, pub_date = _parse_release_date(release_date, release['title'])
|
||||
|
||||
links = {}
|
||||
if 'url-relation-list' in release:
|
||||
links = get_artist_relation_links(release['url-relation-list'])
|
||||
|
||||
return {
|
||||
'artist': {
|
||||
'name': config.get_artist_name(artist_id),
|
||||
'id': artist_id,
|
||||
},
|
||||
'hasCoverArt': release.get('cover-art-archive', {}).get('artwork') == 'true',
|
||||
'id': release['id'],
|
||||
'title': release['title'],
|
||||
'date': release_date,
|
||||
'pub_date': pub_date,
|
||||
'release-group': release.get('release-group', {}),
|
||||
'links': links,
|
||||
}
|
||||
def get_artist_meta_by_id(artist_id):
|
||||
"""get additional meta data about an artist"""
|
||||
meta = {
|
||||
'links': {}
|
||||
}
|
||||
try:
|
||||
logger.debug(f"Fetching artist {artist_id} meta data")
|
||||
# Fetch artist data including URL relations
|
||||
result = musicbrainzngs.get_artist_by_id(artist_id, includes=["url-rels"])
|
||||
artist_data = result.get('artist', {})
|
||||
|
||||
if 'url-relation-list' in artist_data:
|
||||
meta['links'] = get_artist_relation_links(artist_data['url-relation-list'])
|
||||
else:
|
||||
meta['links'] = None
|
||||
|
||||
return meta
|
||||
|
||||
except musicbrainzngs.WebServiceError as exc:
|
||||
logger.error(f"Error fetching artist {artist_id} meta data from MusicBrainz: {exc}")
|
||||
|
||||
return meta
|
||||
|
||||
def get_artist_relation_links(relationlist):
|
||||
"""Parse and extract named links from a MusicBrainz URL relation list."""
|
||||
links = {}
|
||||
for rel in relationlist:
|
||||
target = rel.get('target')
|
||||
if not target:
|
||||
continue
|
||||
if re.match(r'^https://.*imdb\.com', target):
|
||||
links['IMDb'] = target
|
||||
elif re.match(r'^https://music\.apple\.com', target):
|
||||
links['apple'] = target
|
||||
elif re.match(r'^https://music\.amazon\.com', target):
|
||||
links['amazon'] = target
|
||||
elif re.match(r'^https://open\.spotify\.com', target):
|
||||
links['spotify'] = target
|
||||
elif re.match(r'^https://.*qobuz\.com', target):
|
||||
links['qobuz'] = target
|
||||
elif re.match(r'^https://.*deezer\.com', target):
|
||||
links['deezer'] = target
|
||||
elif re.match(r'^https://.*beatport\.com', target):
|
||||
links['beatport'] = target
|
||||
return links
|
||||
|
||||
def get_artist_releases(artist_id):
|
||||
"""Fetch releases for a given artist ID from MusicBrainz."""
|
||||
artist_name = config.get_artist_name(artist_id)
|
||||
logger.debug(f"Fetching releases for artist {artist_name} ({artist_id})")
|
||||
try:
|
||||
result = musicbrainzngs.browse_releases(
|
||||
artist=artist_id,
|
||||
release_type=['album'],
|
||||
includes=['release-groups', 'url-rels']
|
||||
)
|
||||
|
||||
releases = []
|
||||
if 'release-list' in result:
|
||||
releases = [_process_release(r, artist_id) for r in result['release-list']]
|
||||
|
||||
logger.debug(f"Found {len(releases)} releases for artist {artist_name} ({artist_id})")
|
||||
return releases
|
||||
except musicbrainzngs.MusicBrainzError as e:
|
||||
logger.error(f"MusicBrainz API error while fetching releases for artist '{artist_id}': {e}")
|
||||
return []
|
||||
Reference in New Issue
Block a user