44
44
from logging import Logger
45
45
46
46
from beets .importer import ImportTask
47
- from beets .library import Item
47
+ from beets .library import Item , Library
48
48
49
49
from ._typing import (
50
50
GeniusAPI ,
@@ -950,7 +950,6 @@ def translator(self) -> Translator | None:
950
950
951
951
def __init__ (self ):
952
952
super ().__init__ ()
953
- self .import_stages = [self .imported ]
954
953
self .config .add (
955
954
{
956
955
"auto" : True ,
@@ -969,6 +968,7 @@ def __init__(self):
969
968
"fallback" : None ,
970
969
"force" : False ,
971
970
"local" : False ,
971
+ "print" : False ,
972
972
"synced" : False ,
973
973
# Musixmatch is disabled by default as they are currently blocking
974
974
# requests with the beets user agent.
@@ -982,14 +982,16 @@ def __init__(self):
982
982
self .config ["google_engine_ID" ].redact = True
983
983
self .config ["genius_api_key" ].redact = True
984
984
985
+ if self .config ["auto" ]:
986
+ self .import_stages = [self .imported ]
987
+
985
988
def commands (self ):
986
989
cmd = ui .Subcommand ("lyrics" , help = "fetch song lyrics" )
987
990
cmd .parser .add_option (
988
991
"-p" ,
989
992
"--print" ,
990
- dest = "printlyr" ,
991
993
action = "store_true" ,
992
- default = False ,
994
+ default = self . config [ "print" ]. get () ,
993
995
help = "print lyrics to console" ,
994
996
)
995
997
cmd .parser .add_option (
@@ -1004,34 +1006,27 @@ def commands(self):
1004
1006
cmd .parser .add_option (
1005
1007
"-f" ,
1006
1008
"--force" ,
1007
- dest = "force_refetch" ,
1008
1009
action = "store_true" ,
1009
- default = False ,
1010
+ default = self . config [ "force" ]. get () ,
1010
1011
help = "always re-download lyrics" ,
1011
1012
)
1012
1013
cmd .parser .add_option (
1013
1014
"-l" ,
1014
1015
"--local" ,
1015
- dest = "local_only" ,
1016
1016
action = "store_true" ,
1017
- default = False ,
1017
+ default = self . config [ "local" ]. get () ,
1018
1018
help = "do not fetch missing lyrics" ,
1019
1019
)
1020
1020
1021
- def func (lib , opts , args ):
1021
+ def func (lib : Library , opts , args ) -> None :
1022
1022
# The "write to files" option corresponds to the
1023
1023
# import_write config value.
1024
- items = list (lib .items (ui .decargs (args )))
1024
+ self .config .set (vars (opts ))
1025
+ items = list (lib .items (args ))
1025
1026
for item in items :
1026
- if not opts .local_only and not self .config ["local" ]:
1027
- self .fetch_item_lyrics (
1028
- item ,
1029
- ui .should_write (),
1030
- opts .force_refetch or self .config ["force" ],
1031
- )
1032
- if item .lyrics :
1033
- if opts .printlyr :
1034
- ui .print_ (item .lyrics )
1027
+ self .add_item_lyrics (item , ui .should_write ())
1028
+ if item .lyrics and opts .print :
1029
+ ui .print_ (item .lyrics )
1035
1030
1036
1031
if opts .rest_directory and (
1037
1032
items := [i for i in items if i .lyrics ]
@@ -1043,32 +1038,34 @@ def func(lib, opts, args):
1043
1038
1044
1039
def imported (self , _ , task : ImportTask ) -> None :
1045
1040
"""Import hook for fetching lyrics automatically."""
1046
- if self .config ["auto" ]:
1047
- for item in task .imported_items ():
1048
- self .fetch_item_lyrics (item , False , self .config ["force" ])
1041
+ for item in task .imported_items ():
1042
+ self .add_item_lyrics (item , False )
1043
+
1044
+ def find_lyrics (self , item : Item ) -> str :
1045
+ album , length = item .album , round (item .length )
1046
+ matches = (
1047
+ [
1048
+ lyrics
1049
+ for t in titles
1050
+ if (lyrics := self .get_lyrics (a , t , album , length ))
1051
+ ]
1052
+ for a , titles in search_pairs (item )
1053
+ )
1049
1054
1050
- def fetch_item_lyrics (self , item : Item , write : bool , force : bool ) -> None :
1055
+ return "\n \n ---\n \n " .join (next (filter (None , matches ), []))
1056
+
1057
+ def add_item_lyrics (self , item : Item , write : bool ) -> None :
1051
1058
"""Fetch and store lyrics for a single item. If ``write``, then the
1052
1059
lyrics will also be written to the file itself.
1053
1060
"""
1054
- # Skip if the item already has lyrics.
1055
- if not force and item .lyrics :
1056
- self .info ("🔵 Lyrics already present: {}" , item )
1061
+ if self .config ["local" ]:
1057
1062
return
1058
1063
1059
- lyrics_matches = []
1060
- album , length = item .album , round (item .length )
1061
- for artist , titles in search_pairs (item ):
1062
- lyrics_matches = [
1063
- self .get_lyrics (artist , title , album , length )
1064
- for title in titles
1065
- ]
1066
- if any (lyrics_matches ):
1067
- break
1068
-
1069
- lyrics = "\n \n ---\n \n " .join (filter (None , lyrics_matches ))
1064
+ if not self .config ["force" ] and item .lyrics :
1065
+ self .info ("🔵 Lyrics already present: {}" , item )
1066
+ return
1070
1067
1071
- if lyrics :
1068
+ if lyrics := self . find_lyrics ( item ) :
1072
1069
self .info ("🟢 Found lyrics: {0}" , item )
1073
1070
if translator := self .translator :
1074
1071
initial_lyrics = lyrics
0 commit comments