91 Commits

Author SHA1 Message Date
Šarūnas Nejus
fb9de7a619 lyrics: fix musica parsing 2026-06-03 15:42:19 +01:00
Benjamin Stevenson
fc8217f576 merge: resolve changelog and poetry.lock conflicts with master 2026-05-21 19:50:06 -04:00
Benjamin Stevenson
85d5509baa fix: keep LRC in USLT, simplify synced_lyrics write path, fix poetry.lock 2026-05-21 19:48:37 -04:00
Sebastian Mohr
adfb73b66d Run ruff format 2026-05-20 16:53:06 +02:00
Eyüp Can Akman
88be3023bb lyrics: handle apostrophes in musixmatch slug
The musixmatch URL slug builder did not replace curly apostrophes
(U+2018, U+2019) before applying the whitespace-to-dash rule, so titles
like "If They're Shooting at You" produced a slug with the raw quote
preserved and the lookup failed.

Add a REPLACEMENTS entry that maps both curly quote codepoints to a
dash before the rest of the substitutions run.
2026-04-28 17:27:28 +03:00
Benjamin Stevenson
d20c9169c4 fix: ruff line length 2026-04-24 16:43:59 -04:00
Benjamin Stevenson
c9b1baee24 fix: keep LRC in DB, pass plain text to USLT via tags, bump mediafile to 0.17.0 2026-04-24 16:41:37 -04:00
Benjamin Stevenson
edb1934fc9 fix: ruff formatting and lint errors 2026-04-22 18:14:31 -04:00
Benjamin Stevenson
78d9f89dbd Use mediafile synced_lyrics field instead of _write_sylt_to_id3 2026-04-22 18:11:01 -04:00
Benjamin Stevenson
26759b9c6e Address review: use XXX lang code, log save errors 2026-04-22 13:58:10 -04:00
Benjamin Stevenson
dc0a0bf4b3 Fix formatting: resolve changelog merge conflict and remove extra blank line 2026-04-21 17:30:07 -04:00
Benjamin Stevenson
fc769e9a79 lyrics: write synced LRC lyrics to SYLT ID3 frame
When the lyrics plugin writes LRC-formatted (timestamped) lyrics to an
ID3-tagged audio file, store the timing data in the SYLT (synchronized
lyrics) frame and plain text in USLT, rather than writing raw LRC text
verbatim to USLT.

Fixes #6541
2026-04-21 17:22:15 -04:00
Šarūnas Nejus
163b94d464 lyrics: add keep_synced option to not overwrite synced lyrics 2026-04-17 09:19:15 +01:00
kelamg
989fc665c9 Improve test 2026-03-22 01:46:50 +00:00
kelamg
b3bcb78349 Fix indentation 2026-03-22 01:46:50 +00:00
jochem
55b6fbe77d copied more generic implementation from snejus, and updated the tests and docs accordingly 2026-03-22 01:46:50 +00:00
kelamg
9a735df125 Fix formatting 2026-03-22 01:46:50 +00:00
kelamg
ec4def9e91 Refactor exclusion tests to pytest 2026-03-22 01:46:50 +00:00
jochem
2f9ee89b2a Added feature to exclude albums/songs during importing when auto is enabled, as requested in issue #3523. Also added corresponding tests and documentation. 2026-03-22 01:46:50 +00:00
Šarūnas Nejus
a7325e7483 Skip langdetect-dependent tests when package is not installed
Add a `requires_import` pytest marker and `is_importable` fixture to
conditionally skip or adjust assertions based on whether optional
dependencies are available. Apply this to `langdetect`-dependent
language detection tests in lyrics and migration test suites.
2026-03-08 08:19:55 +00:00
Šarūnas Nejus
05a822dd5c Move Lyrics class under beets.util as it is used by migrations 2026-03-06 10:57:08 +00:00
Šarūnas Nejus
7d30efa82c Migrate lyrics metadata to flex fields on library open
- Add `LyricsMetadataInFlexFieldsMigration` to extract legacy source
  URLs and language metadata from lyrics text into flex attributes
- Add `Lyrics.from_legacy_text` to parse legacy lyrics format
- Move `with_row_factory` context manager up to base `Migration` class
- Rename `migrate_table` to `migrate_model` and pass model class
  instead of table name string. This is so that the migration can access
  both `_table` and `_flex_table` attributes.
- Make `langdetect` import optional in `Lyrics.__post_init__`: users may
  not have have the dependency installed, and we do not want the
  migration to fail because of that.
- Move `BACKEND_BY_NAME` to module level for use outside plugin class
2026-03-06 10:57:08 +00:00
Šarūnas Nejus
7df14e1877 Fix timestamp format in translation/synced lyrics test 2026-03-06 10:57:08 +00:00
Šarūnas Nejus
38708ae592 Refactor lyrics handling to use structured Lyrics object
* Introduce a `Lyrics` dataclass to carry text, source URL, and language
  metadata through fetch, translation, and storage paths.
* Return `Lyrics` from backends and plugin lookup methods instead of raw
  tuples/strings.
* Store backend name in `lyrics_source` derived from fetched URL root
  domain.
* Simplify translator flow to operate on `Lyrics`, reuse line splitting,
  append translations in-place, and record translation language
  metadata.
2026-03-06 10:57:08 +00:00
Šarūnas Nejus
c239275193 Do not split orig/trans if they are not different 2026-03-05 15:36:59 +00:00
Šarūnas Nejus
cd95c15a0b Add a test to show duplicate translations we have right now 2026-03-05 15:36:59 +00:00
Šarūnas Nejus
82bfc03494 Preserve synced lyrics when fetched result is plain text
When lyrics.synced is enabled, avoid replacing existing synced lyrics with
newly fetched unsynced lyrics, even with force enabled.

Allow replacement when the new lyrics are also synced, or when synced mode
is disabled.
2026-03-05 15:36:59 +00:00
Šarūnas Nejus
24ca6abcfe lyrics: validate synced lyrics duration 2026-03-05 15:34:32 +00:00
Šarūnas Nejus
c52656fb0a Enable RUF rules 2026-01-13 20:55:40 +00:00
Šarūnas Nejus
b964d8b7eb Configure future-annotations 2026-01-13 20:55:40 +00:00
Ben Stolovitz
2f98f11d57 fix local langdetect test failures
avoid linter error

avoid other linter error

fix format

changing deps (no lock!)

poetry lock?

lint & format

attempt 2 at poetry lock

crlf -> lf line endings

changelog!
2025-05-31 18:56:21 -04:00
Šarūnas Nejus
b713d72612 translations: use a more distinctive separator
I found that the translator would sometimes replace the pipe character
with another symbol (maybe it got confused thinking the character is
part of the text?).

Added spaces around the pipe to make it more clear that it's definitely
the separator.
2025-02-20 03:47:04 +00:00
Šarūnas Nejus
43032f7bc7 translations: make sure we do not re-translate 2025-02-20 03:47:04 +00:00
Šarūnas Nejus
7893766e4c Improve flags structure and add tests 2025-02-20 03:47:04 +00:00
Šarūnas Nejus
c95156adcd Refactor writing rest files 2025-02-20 03:47:04 +00:00
Šarūnas Nejus
d7201062a8 Resurrect translation functionality 2025-02-20 03:47:04 +00:00
Sebastian Mohr
ed92f9b997 Do not skip tests in ci.
The return type of the stage decorator should in theory be `T|None`
but the return of task types is not consistent in its usage. Would need
some bigger changes for which I'm not ready at the moment.
2025-02-03 11:37:33 +01:00
Sebastian Mohr
04aa1b8ddb Added last missing typehints in importer and fixed some typehint issues
in util. Also run poe format
2025-02-01 15:52:11 +01:00
Sebastian Mohr
c81a2c9b18 Using 3.9 unions instead of new 3.10 style unions for typehints 2025-02-01 13:25:25 +01:00
Šarūnas Nejus
7389f241f4 Do not search for Various Artists, split titles by ' / ' 2025-01-27 10:56:53 +00:00
Šarūnas Nejus
734bcc28a8 Append source to the lyrics 2025-01-27 10:56:53 +00:00
Šarūnas Nejus
bdc564a573 Tidy up handling of backends 2025-01-27 10:56:53 +00:00
Šarūnas Nejus
70554640e5 Create Html class for cleaning up the html text
Additionally, improve HTML pre-processing:

* Ensure a new line between blocks of lyrics text from letras.mus.br.
* Parse a missing last block of lyrics text from lacocinelle.net.
* Parse a missing last block of lyrics text from paroles.net.
* Fix encoding issues with AZLyrics by setting response encoding to
  None, allowing `requests` to handle it.
2025-01-27 10:56:52 +00:00
Šarūnas Nejus
c5c4138d66 Google: Refactor and improve
* Type the response data that Google Custom Search API return.
* Exclude some 'letras.mus.br' pages that do not contain lyric.
* Exclude results from Musixmatch as we cannot access their pages.
* Improve parsing of the URL title:
  - Handle long URL titles that get truncated (end with ellipsis) for
    long searches
  - Remove domains starting with 'www'
  - Parse the title AND the artist. Previously this would only parse the
    title, and fetch lyrics even when the artist did not match.
* Remove now redundant credits cleanup and checks for valid lyrics.
2025-01-27 10:56:52 +00:00
Šarūnas Nejus
12c5eaae5e Unite Genius, Tekstowo and Google backends under the same interface 2025-01-27 10:56:52 +00:00
Šarūnas Nejus
745c5eb9f0 Genius: refactor and simplify 2025-01-27 10:56:52 +00:00
Šarūnas Nejus
f94d2767f9 Use a single slug implementation
Tidy up 'Google.is_page_candidate' method and remove 'Google.sluggify'
method which was a duplicate of 'slug'.

Since 'GeniusFetchTest' only tested whether the artist name is cleaned
up (the rest of the functionality is patched), remove it and move its
test cases to the 'test_slug' test.
2025-01-27 08:50:50 +00:00
Šarūnas Nejus
dd9f178fff Do not try to strip cruft from the parsed lyrics text.
Having removed it I fuond that only the Genius lyrics changed: it had en
extra new line. Thus I defined a function 'collapse_newlines' which now
gets called for the Genius lyrics.
2025-01-27 08:50:50 +00:00
Šarūnas Nejus
7c2fb31136 Leave a single chef in the kitchen 2025-01-27 08:50:50 +00:00
Šarūnas Nejus
cb29605bfd Include class name in the log messages 2025-01-27 08:50:50 +00:00