Skip to content

Commit

Permalink
Refactor skip options, add more meta tags
Browse files Browse the repository at this point in the history
  • Loading branch information
infojunkie committed May 26, 2024
1 parent a52e974 commit de25102
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 31 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "discogs-tag"
version = "0.2.0"
version = "0.3.0"
description = "A rudimentary audio tagger based on Discogs metadata."
authors = ["infojunkie <[email protected]>"]
readme = "README.md"
Expand Down
83 changes: 63 additions & 20 deletions src/discogs_tag/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,27 @@
from functools import reduce
from discogs_tag import __NAME__, __VERSION__

SKIP_KEYS = [
'artist',
'composer',
'title',
'position',
'date',
'subtrack',
'album',
'genre',
'albumartist'
]

def tag(
release,
dir='./',
dry=False,
ignore=False,
skip_artist=False,
skip_title=False,
skip_composer=False,
skip_position=False,
skip_year=False,
skip_subtrack=False
skip=None
):
"""Tag the audio files with the given Discogs release."""
options = locals()
options = parse_options(locals())
request = urllib.request.Request(f'https://api.discogs.com/releases/{release}', headers = {
'User-Agent': f'{__NAME__} {__VERSION__}'
})
Expand All @@ -40,19 +47,17 @@ def copy(
dir='./',
dry=False,
ignore=False,
skip_artist=False,
skip_title=False,
skip_composer=False,
skip_position=False,
skip_year=False,
skip_subtrack=False
skip=None
):
"""Copy the audio tags from source to destination folders."""
options = locals()
options = parse_options(locals())
src_files = sorted(
glob.glob(os.path.join(glob.escape(src), '**', '*.flac'), recursive=True) +
glob.glob(os.path.join(glob.escape(src), '**', '*.mp3'), recursive=True)
)
if not src_files:
raise Exception(f'No source files found at {src}. Aborting.')

dst_files = sorted(
glob.glob(os.path.join(glob.escape(dir), '**', '*.flac'), recursive=True) +
glob.glob(os.path.join(glob.escape(dir), '**', '*.mp3'), recursive=True)
Expand All @@ -70,20 +75,30 @@ def safe_position(audio, n):
return audio['tracknumber'][0].split('/')[0].lstrip('0')
except:
return str(n)
def safe_year(audio):
try:
return int(audio['date'][0].split('-')[0])
except:
return None

tracklist = []
for n, file in enumerate(files):
audio = mutagen.File(file, easy=True)
tracklist.append({
'type_': 'track',
'position': safe_position(audio, n+1),
'artists': [{
'anv': audio['artist'][0]
}],
'title': audio['title'][0],
'year': audio['date'][0],
'artists': [{ 'anv': artist } for artist in audio.get('artist', [])],
'title': audio.get('title', [''])[0],
'extraartists': [{
'role': 'Written-By',
'anv': composer
} for composer in audio.get('composer', [])]
})
return {
'artists': [{ 'anv': artist } for artist in audio.get('albumartist', [])],
'title': audio.get('album', [''])[0],
'year': safe_year(audio),
'genres': audio.get('genre', []),
'tracklist': sorted(tracklist, key=lambda track: int(track['position']))
}

Expand Down Expand Up @@ -122,6 +137,14 @@ def reduce_track(tracks, track):
if not options['dry']:
print(f'Processed {len(files)} audio files.')

def parse_options(options):
for skip in SKIP_KEYS:
options['skip_' + skip] = False
if options['skip'] is not None:
for skip in options['skip'].lower():
options['skip_' + skip] = True
return options

def merge_metadata(release, track, audio, options):
def artist_name(artist):
name = None
Expand All @@ -143,6 +166,26 @@ def artist_name(artist):
if artists:
audio['artist'] = ', '.join(artists)

if not options['skip_albumartist']:
artists = []
if 'artists' in release:
artists += [artist_name(artist) for artist in release['artists']]
if artists:
audio['albumartist'] = ', '.join(artists)

if not options['skip_genre']:
genres = []
if 'genres' in release:
genres += [genre for genre in release['genres']]
if 'styles' in release:
genres += [genre for genre in release['styles']]
if genres:
audio['genre'] = ', '.join(genres)

if not options['skip_album']:
if 'title' in release:
audio['album'] = release['title']

if not options['skip_composer']:
composers = [artist_name(composer) for composer in filter(lambda a: a['role'].casefold() == 'Written-By'.casefold(), track['extraartists'])] if 'extraartists' in track else None
if composers:
Expand All @@ -154,7 +197,7 @@ def artist_name(artist):
if len(positions) > 1:
audio['discnumber'] = positions[0]

if not options['skip_year']:
if not options['skip_date']:
if 'year' in release and release['year']:
audio['date'] = str(release['year'])

Expand Down
14 changes: 4 additions & 10 deletions tests/test_discogs_tag.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from discogs_tag.cli import merge_metadata, apply_metadata
from discogs_tag.cli import merge_metadata, apply_metadata, parse_options
import pytest
import json

Expand All @@ -24,13 +24,7 @@ def test_merge_metadata():
'role': 'Written-By',
'name': 'Composer'
}]
}, audio, {
'skip_artist': False,
'skip_composer': False,
'skip_title': False,
'skip_position': False,
'skip_year': False
})
}, audio, parse_options({ 'skip': None }))
assert audio['title'] == 'Title'
assert audio['artist'] == 'Artist 1, Artist 2, Artist 3, Guitarist'
assert audio['discnumber'] == '1'
Expand All @@ -44,7 +38,7 @@ def test_apply_metadata():

# Test that files must match API results.
with pytest.raises(Exception) as error:
apply_metadata(data, [], { 'dry': False, 'ignore': False, 'skip_subtrack': False })
apply_metadata(data, [], parse_options({ 'dry': False, 'ignore': False, 'skip': None }))
assert "Expecting 28 files" in str(error.value)

def test_count_subtracks():
Expand All @@ -53,5 +47,5 @@ def test_count_subtracks():

# Test that files must match API results.
with pytest.raises(Exception) as error:
apply_metadata(data, [], { 'dry': False, 'ignore': False, 'skip_subtrack': False })
apply_metadata(data, [], parse_options({ 'dry': False, 'ignore': False, 'skip': None }))
assert "Expecting 18 files" in str(error.value)

0 comments on commit de25102

Please sign in to comment.