mirror of
https://github.com/beetbox/beets.git
synced 2025-12-10 02:22:25 +01:00
Merge pull request #4842 from arsaboo/deezer
Import additional fields from Deezer and add function to update rank
This commit is contained in:
commit
b19b961035
3 changed files with 71 additions and 3 deletions
|
|
@ -16,19 +16,28 @@
|
|||
"""
|
||||
|
||||
import collections
|
||||
import time
|
||||
|
||||
import unidecode
|
||||
import requests
|
||||
import unidecode
|
||||
|
||||
from beets import ui
|
||||
from beets.autotag import AlbumInfo, TrackInfo
|
||||
from beets.plugins import MetadataSourcePlugin, BeetsPlugin
|
||||
from beets.dbcore import types
|
||||
from beets.library import DateType
|
||||
from beets.plugins import BeetsPlugin, MetadataSourcePlugin
|
||||
from beets.util.id_extractors import deezer_id_regex
|
||||
|
||||
|
||||
class DeezerPlugin(MetadataSourcePlugin, BeetsPlugin):
|
||||
data_source = 'Deezer'
|
||||
|
||||
item_types = {
|
||||
'deezer_track_rank': types.INTEGER,
|
||||
'deezer_track_id': types.INTEGER,
|
||||
'deezer_updated': DateType(),
|
||||
}
|
||||
|
||||
# Base URLs for the Deezer API
|
||||
# Documentation: https://developers.deezer.com/api/
|
||||
search_url = 'https://api.deezer.com/search/'
|
||||
|
|
@ -40,6 +49,19 @@ class DeezerPlugin(MetadataSourcePlugin, BeetsPlugin):
|
|||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def commands(self):
|
||||
"""Add beet UI commands to interact with Deezer."""
|
||||
deezer_update_cmd = ui.Subcommand(
|
||||
'deezerupdate', help=f'Update {self.data_source} rank')
|
||||
|
||||
def func(lib, opts, args):
|
||||
items = lib.items(ui.decargs(args))
|
||||
self.deezerupdate(items, ui.should_write())
|
||||
|
||||
deezer_update_cmd.func = func
|
||||
|
||||
return [deezer_update_cmd]
|
||||
|
||||
def album_for_id(self, album_id):
|
||||
"""Fetch an album by its Deezer ID or URL and return an
|
||||
AlbumInfo object or None if the album is not found.
|
||||
|
|
@ -54,7 +76,15 @@ class DeezerPlugin(MetadataSourcePlugin, BeetsPlugin):
|
|||
return None
|
||||
|
||||
album_data = requests.get(self.album_url + deezer_id).json()
|
||||
artist, artist_id = self.get_artist(album_data['contributors'])
|
||||
if 'error' in album_data:
|
||||
self._log.debug(f"Error fetching album {album_id}: "
|
||||
f"{album_data['error']['message']}")
|
||||
return None
|
||||
contributors = album_data.get('contributors')
|
||||
if contributors is not None:
|
||||
artist, artist_id = self.get_artist(contributors)
|
||||
else:
|
||||
artist, artist_id = None, None
|
||||
|
||||
release_date = album_data['release_date']
|
||||
date_parts = [int(part) for part in release_date.split('-')]
|
||||
|
|
@ -113,6 +143,7 @@ class DeezerPlugin(MetadataSourcePlugin, BeetsPlugin):
|
|||
mediums=max(medium_totals.keys()),
|
||||
data_source=self.data_source,
|
||||
data_url=album_data['link'],
|
||||
cover_art_url=album_data.get('cover_xl'),
|
||||
)
|
||||
|
||||
def _get_track(self, track_data):
|
||||
|
|
@ -129,14 +160,18 @@ class DeezerPlugin(MetadataSourcePlugin, BeetsPlugin):
|
|||
return TrackInfo(
|
||||
title=track_data['title'],
|
||||
track_id=track_data['id'],
|
||||
deezer_track_id=track_data['id'],
|
||||
isrc=track_data.get('isrc'),
|
||||
artist=artist,
|
||||
artist_id=artist_id,
|
||||
length=track_data['duration'],
|
||||
index=track_data.get('track_position'),
|
||||
medium=track_data.get('disk_number'),
|
||||
deezer_track_rank=track_data.get('rank'),
|
||||
medium_index=track_data.get('track_position'),
|
||||
data_source=self.data_source,
|
||||
data_url=track_data['link'],
|
||||
deezer_updated=time.time(),
|
||||
)
|
||||
|
||||
def track_for_id(self, track_id=None, track_data=None):
|
||||
|
|
@ -157,6 +192,10 @@ class DeezerPlugin(MetadataSourcePlugin, BeetsPlugin):
|
|||
if deezer_id is None:
|
||||
return None
|
||||
track_data = requests.get(self.track_url + deezer_id).json()
|
||||
if 'error' in track_data:
|
||||
self._log.debug(f"Error fetching track {track_id}: "
|
||||
f"{track_data['error']['message']}")
|
||||
return None
|
||||
track = self._get_track(track_data)
|
||||
|
||||
# Get album's tracks to set `track.index` (position on the entire
|
||||
|
|
@ -232,3 +271,27 @@ class DeezerPlugin(MetadataSourcePlugin, BeetsPlugin):
|
|||
query,
|
||||
)
|
||||
return response_data
|
||||
|
||||
def deezerupdate(self, items, write):
|
||||
"""Obtain rank information from Deezer."""
|
||||
for index, item in enumerate(items, start=1):
|
||||
self._log.info('Processing {}/{} tracks - {} ',
|
||||
index, len(items), item)
|
||||
try:
|
||||
deezer_track_id = item.deezer_track_id
|
||||
except AttributeError:
|
||||
self._log.debug('No deezer_track_id present for: {}', item)
|
||||
continue
|
||||
try:
|
||||
rank = requests.get(
|
||||
f"{self.track_url}{deezer_track_id}").json().get('rank')
|
||||
self._log.debug('Deezer track: {} has {} rank',
|
||||
deezer_track_id, rank)
|
||||
except Exception as e:
|
||||
self._log.debug('Invalid Deezer track_id: {}', e)
|
||||
continue
|
||||
item.deezer_track_rank = int(rank)
|
||||
item.store()
|
||||
item.deezer_updated = time.time()
|
||||
if write:
|
||||
item.try_write()
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ for Python 3.6).
|
|||
|
||||
New features:
|
||||
|
||||
* :doc:`/plugins/deezer`: Import rank and other attributes from Deezer during import and add a function to update the rank of existing items.
|
||||
:bug:`4841`
|
||||
* resolve transl-tracklisting relations for pseudo releases and merge data with the actual release
|
||||
:bug:`654`
|
||||
* Fetchart: Use the right field (`spotify_album_id`) to obtain the Spotify album id
|
||||
|
|
@ -95,6 +97,7 @@ New features:
|
|||
|
||||
Bug fixes:
|
||||
|
||||
* :doc:`/plugins/deezer`: Fixed the error where Deezer plugin would crash if non-Deezer id is passed during import.
|
||||
* :doc:`/plugins/fetchart`: Fix fetching from Cover Art Archive when the
|
||||
`maxwidth` option is set to one of the supported Cover Art Archive widths.
|
||||
* :doc:`/plugins/discogs`: Fix "Discogs plugin replacing Feat. or Ft. with
|
||||
|
|
|
|||
|
|
@ -23,3 +23,5 @@ Configuration
|
|||
-------------
|
||||
|
||||
This plugin can be configured like other metadata source plugins as described in :ref:`metadata-source-plugin-configuration`.
|
||||
|
||||
The ``deezer`` plugin provides an additional command ``deezerupdate`` to update the ``rank`` information from Deezer. The ``rank`` (ranges from 0 to 1M) is a global indicator of a song's popularity on Deezer that is updated daily based on streams. The higher the ``rank``, the more popular the track is.
|
||||
|
|
|
|||
Loading…
Reference in a new issue