mirror of
https://github.com/beetbox/beets.git
synced 2026-01-10 09:58:45 +01:00
Merge pull request #4854 from JOJ0/discogs_single_album_refactor
Support providing album information on singleton imports via Discogs
This commit is contained in:
commit
c03bd26e3a
7 changed files with 86 additions and 4 deletions
|
|
@ -212,6 +212,7 @@ class TrackInfo(AttrDict):
|
|||
bpm: Optional[str] = None,
|
||||
initial_key: Optional[str] = None,
|
||||
genre: Optional[str] = None,
|
||||
album: Optional[str] = None,
|
||||
**kwargs,
|
||||
):
|
||||
self.title = title
|
||||
|
|
@ -241,6 +242,7 @@ class TrackInfo(AttrDict):
|
|||
self.bpm = bpm
|
||||
self.initial_key = initial_key
|
||||
self.genre = genre
|
||||
self.album = album
|
||||
self.update(kwargs)
|
||||
|
||||
# As above, work around a bug in python-musicbrainz-ngs.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import:
|
|||
bell: no
|
||||
set_fields: {}
|
||||
ignored_alias_types: []
|
||||
singleton_album_disambig: yes
|
||||
|
||||
clutter: ["Thumbs.DB", ".DS_Store"]
|
||||
ignore: [".*", "*~", "System Volume Information", "lost+found"]
|
||||
|
|
|
|||
|
|
@ -215,6 +215,15 @@ def disambig_string(info):
|
|||
if info.albumstatus == 'Pseudo-Release':
|
||||
disambig.append(info.albumstatus)
|
||||
|
||||
if isinstance(info, hooks.TrackInfo):
|
||||
if info.index:
|
||||
disambig.append("Index {}".format(str(info.index)))
|
||||
if info.track_alt:
|
||||
disambig.append("Track {}".format(info.track_alt))
|
||||
if (config['import']['singleton_album_disambig'].get()
|
||||
and info.get('album')):
|
||||
disambig.append("[{}]".format(info.album))
|
||||
|
||||
if disambig:
|
||||
return ', '.join(disambig)
|
||||
|
||||
|
|
@ -444,18 +453,28 @@ def show_item_change(item, match):
|
|||
"""
|
||||
cur_artist, new_artist = item.artist, match.info.artist
|
||||
cur_title, new_title = item.title, match.info.title
|
||||
cur_album = item.album if item.album else ""
|
||||
new_album = match.info.album if match.info.album else ""
|
||||
|
||||
if cur_artist != new_artist or cur_title != new_title:
|
||||
if (cur_artist != new_artist or cur_title != new_title
|
||||
or cur_album != new_album):
|
||||
cur_artist, new_artist = ui.colordiff(cur_artist, new_artist)
|
||||
cur_title, new_title = ui.colordiff(cur_title, new_title)
|
||||
cur_album, new_album = ui.colordiff(cur_album, new_album)
|
||||
|
||||
print_("Correcting track tags from:")
|
||||
print_(f" {cur_artist} - {cur_title}")
|
||||
if cur_album:
|
||||
print_(f" Album: {cur_album}")
|
||||
print_("To:")
|
||||
print_(f" {new_artist} - {new_title}")
|
||||
if new_album:
|
||||
print_(f" Album: {new_album}")
|
||||
|
||||
else:
|
||||
print_(f"Tagging track: {cur_artist} - {cur_title}")
|
||||
if cur_album:
|
||||
print_(f" Album: {new_album}")
|
||||
|
||||
# Data URL.
|
||||
if match.info.data_url:
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ python3-discogs-client library.
|
|||
import beets.ui
|
||||
from beets import config
|
||||
from beets.util.id_extractors import extract_discogs_id_regex
|
||||
from beets.autotag.hooks import AlbumInfo, TrackInfo
|
||||
from beets.autotag.hooks import AlbumInfo, TrackInfo, string_dist
|
||||
from beets.plugins import MetadataSourcePlugin, BeetsPlugin, get_distance
|
||||
import confuse
|
||||
from discogs_client import __version__ as dc_string
|
||||
|
|
@ -196,6 +196,40 @@ class DiscogsPlugin(BeetsPlugin):
|
|||
self._log.debug('Connection error in album search', exc_info=True)
|
||||
return []
|
||||
|
||||
def get_track_from_album_by_title(self, album_info, title,
|
||||
dist_threshold=0.3):
|
||||
def compare_func(track_info):
|
||||
track_title = getattr(track_info, "title", None)
|
||||
dist = string_dist(track_title, title)
|
||||
return (track_title and dist < dist_threshold)
|
||||
return self.get_track_from_album(album_info, compare_func)
|
||||
|
||||
def get_track_from_album(self, album_info, compare_func):
|
||||
"""Return the first track of the release where `compare_func` returns
|
||||
true.
|
||||
|
||||
:return: TrackInfo object.
|
||||
:rtype: beets.autotag.hooks.TrackInfo
|
||||
"""
|
||||
if not album_info:
|
||||
return None
|
||||
|
||||
for track_info in album_info.tracks:
|
||||
# check for matching position
|
||||
if not compare_func(track_info):
|
||||
continue
|
||||
|
||||
# attach artist info if not provided
|
||||
if not track_info['artist']:
|
||||
track_info['artist'] = album_info.artist
|
||||
track_info['artist_id'] = album_info.artist_id
|
||||
# attach album info
|
||||
track_info['album'] = album_info.album
|
||||
|
||||
return track_info
|
||||
|
||||
return None
|
||||
|
||||
def item_candidates(self, item, artist, title):
|
||||
"""Returns a list of TrackInfo objects for Search API results
|
||||
matching ``title`` and ``artist``.
|
||||
|
|
@ -214,6 +248,7 @@ class DiscogsPlugin(BeetsPlugin):
|
|||
if not artist and not title:
|
||||
self._log.debug('Skipping Discogs query. File missing artist and '
|
||||
'title tags.')
|
||||
return
|
||||
|
||||
query = f'{artist} {title}'
|
||||
try:
|
||||
|
|
@ -230,7 +265,11 @@ class DiscogsPlugin(BeetsPlugin):
|
|||
candidates = []
|
||||
for album_cur in albums:
|
||||
self._log.debug(u'searching within album {0}', album_cur.album)
|
||||
candidates += album_cur.tracks
|
||||
track_result = self.get_track_from_album_by_title(
|
||||
album_cur, item['title']
|
||||
)
|
||||
if track_result:
|
||||
candidates.append(track_result)
|
||||
# first 10 results, don't overwhelm with options
|
||||
return candidates[:10]
|
||||
|
||||
|
|
@ -276,7 +315,7 @@ class DiscogsPlugin(BeetsPlugin):
|
|||
query = re.sub(r'(?u)\W+', ' ', query)
|
||||
# Strip medium information from query, Things like "CD1" and "disk 1"
|
||||
# can also negate an otherwise positive result.
|
||||
query = re.sub(r'(?i)\b(CD|disc)\s*\d+', '', query)
|
||||
query = re.sub(r'(?i)\b(CD|disc|vinyl)\s*\d+', '', query)
|
||||
|
||||
try:
|
||||
releases = self.discogs_client.search(query,
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@ New features:
|
|||
:bug:`4373`
|
||||
* Fetch the ``release_group_title`` field from MusicBrainz.
|
||||
:bug: `4809`
|
||||
* :doc:`plugins/discogs`: Add support for applying album information on
|
||||
singleton imports.
|
||||
:bug: `4716`
|
||||
|
||||
Bug fixes:
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@ Discogs Plugin
|
|||
The ``discogs`` plugin extends the autotagger's search capabilities to
|
||||
include matches from the `Discogs`_ database.
|
||||
|
||||
Files can be imported as albums or as singletons. Since `Discogs`_ matches are
|
||||
always based on `Discogs`_ releases, the album tag is written even to
|
||||
singletons. This enhances the importers results when reimporting as (full or
|
||||
partial) albums later on.
|
||||
|
||||
.. _Discogs: https://discogs.com
|
||||
|
||||
Installation
|
||||
|
|
|
|||
|
|
@ -760,6 +760,19 @@ Fields are persisted to the media files of each track.
|
|||
|
||||
Default: ``{}`` (empty).
|
||||
|
||||
.. _singleton_album_disambig:
|
||||
|
||||
singleton_album_disambig
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
During singleton imports and if the metadata source provides it, album names
|
||||
are appended to the disambiguation string of matching track candidates. For
|
||||
example: ``The Artist - The Title (Discogs, Index 3, Track B1, [The Album]``.
|
||||
This feature is currently supported by the :doc:`/plugins/discogs` and the
|
||||
:doc:`/plugins/spotify`.
|
||||
|
||||
Default: ``yes``.
|
||||
|
||||
.. _musicbrainz-config:
|
||||
|
||||
MusicBrainz Options
|
||||
|
|
|
|||
Loading…
Reference in a new issue