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