NAME

LyricFinder - Fetch song lyrics from several internet lyric sites.

AUTHOR

This module is Copyright (c) 2020 by

Jim Turner, <turnerjw784 at yahoo.com>

All rights reserved.

This library is free software; you can redistribute it and/or modify it under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file.

NOTE: This is a "derived work" of Lyrics::Fetcher family of modules, by (c) David Precious (davidp at preshweb.co.uk) (CPAN Id: BIGPRESH), as fair use legal under the terms of, subject to, and licensed in terms compatable and compliant with those modules. Many thanks to David for laying the groundwork for this module!

SYNOPSIS

    #!/usr/bin/perl

    use LyricFinder;

    # create a new finder object:
    my $finder = new LyricFinder();

    # fetch lyrics for a song from a specific site (https://www.azlyrics.com):
    print $finder->fetch('Pink Floyd','Echoes','AZLyrics');

    # if you omit the site, automatically tries all available
    # sites in random order:
    print $finder->fetch('Oasis', 'Cast No Shadow');

    # or you can pass an arrayref of sites you want used in order:
    print $finder->fetch('Oasis', 'Whatever', [qw(Genius AZLyrics)]);

    # To find out which site modules are available:
    my @fetchers = $finder->sources();

    # To fetch the source (site) name and base url:
    print "(Lyrics courtesy: ".$finder->source().")\n";
    print "site url:  ".$finder->site().")\n";

    # To show what sites we had to search for these lyrics:
    print "..Tried sites:  ".$finder->tried().".\n";

    # To do caching:
    $finder->cache('/tmp/lyrics');
    #-or-
    my $localfinder = new LyricFinder(-cache => '/tmp/lyrics');

    #-or- to only fetch lyrics from our cache:
    my $local_lyrics = $localfinder->fetch('Oasis', 'Cast No Shadow', 'Cache');
    if ($local_lyrics) {
        print "..Lyrics from disk:\n\n$local_lyrics\n";
    } else {
        print "..No local lyrics found for 'Cast No Shadow', by Oasis.\n";
    }

DESCRIPTION

LyricFinder accepts an artist name and song title, searches supported lyrics sites for song lyrics, and, if found, returns them as a string.

The supported and currently-installed modules are: LyricFinder::ApiLyricsOvh (for searching api.lyrics.ovh), LyricFinder::AZLyrics (www.azlyrics.com), LyricFinder::Genius (genius.com), LyricFinder::Letras (www.letras.mus.br), and LyricFinder::Musixmatch (www.musixmatch.com). There is a special module for storing and / or fetching lyrics (.lrc) files already stored locally, called LyricFinder::Cache.

This module is derived from the (older) Lyrics::Fetcher collection of modules by (c) 2007-2020 David Precious, but currently (as of December, 2020) supports more lyric sites (5) and bundles all the supported site modules together here (simply install this one module). We have reworked the "Cache" module to cache lyrics files by artist and song title on disk in the user's desired location. LyricFinder is also truly object-oriented making interaction with the user-facing methods and data easier and more streamlined.

NOTE: This module is used completely independent of any of those modules, but the code is derived from them, as allowed by and the license and credits are included here, as required by their open-source license. It is capable of being used as a drop-in replacement, but some function names and other code changes will be needed.

We've also added methods to easily change the "user-agent" passed to the lyrics sites, as needed/desired by the user programatically.

We've also changed the default to search the supported sites randomly, instead of in the same fixed alphabetical order by module name ("load-balancing" the searches to all the sites). This is helpful when using LyricFinder as a plugin for streaming media players, such as the author's very own "Fauxdacious Media Player" that frequently stream internet radio stations, which can impose a "hit" on the lyrics sites each time the song title changes. This reduces the odds of a user's IP-address possibly being banned by a lyrics site for "too-frequent scraping / usage"! NOTE: If you want to prevent the usage of one or more of the specific sites, simply delete or rename that site's submodule file. If you want to use one or more specific sites, or enforce a specific search order, you can call the fetch() method with a third argument consisting of the site module name, ie. "Musixmatch", or reference to an array of site module names, ie. [Genius, AZLyrics]. If you specify "Cache" as the single module name (and provide a "-cache" directory containing lyrics files on your hard drive), LyricFinder will only search that directory for lyrics, and not the internet. Otherwise, specifying a "-cache" directory will cause LyricFinder to first look in your cache directory for matching lyrics first, and only search any of the lyrics sites if not found, then will cache the lyrics found on the internet to a new lyric file in your lyrics directory eleminating re-searching the web when you play the same song again later and reducing internet bandwidth usage!

In case of problems with fetching lyrics, the error string will be returned by $finder->message(). If all goes well, it will have 'Ok' in it.

The site selection is made by the "method" parameter passed to the fetch() of this module. You can also omit this parameter, in which case all available fetchers will be tried in random order, or you can supply an arrayref of sites you'd like to try in the order you specify.

The value of the "method" parameter (if specified) must be either the "*" part of one of the installed LyricFinder::* fetcher package name, "all", or "random".

If you have another lyrics site that is not supported, please file a feature request via email or the CPAN bug system, or (for faster service), provide a Perl patch module / program source that can extract lyrics from that site and I'll consider it! The easiest way to do this is to take one of the existing submodules, copy it to "LyricFinder::YOURSITE.pm and modify it (and the POD docs) to your specific site's needs, test it with several Artist / Title combinations (see the "SYNOPSIS" code above), and send it to me (That's what I do for new sites)!

INSTALLATION

        To install this module, run the following commands:

        perl Makefile.PL

        make

        make test

        make install

SUBROUTINES/METHODS

new LyricFinder([ options ])

Creates a new finder object for fetching lyrics. The same finder object can be used for multiple fetches from multiple sites, so this normally only needs to be called once.

options is a hash of option/value pairs (ie. "-option" => "value"). If an "-option" is specified with no "value" given, the default value will be 1 ("true"). The currently-supported options are:

-agent => "user-agent string"

Specifies an alternate "user-agent" string sent to the lyric sites when attempting to fetch lyrics. Get / set the desired user-agent (ie. browser name) to pass to the lyrics sites. Some sites are pickey about receiving a user-agent string that corresponds to a valid / supported web-browser to prevent their sites from being "scraped" by programs, such as this.

Default: "Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0".

NOTE: This value will be overridden if $founder->agent("agent") is called! NOTE: See below how to specify a different agent for a specific site module.

-cache => "directory"

Specifies a directory (ie. "/home/user/Music/Lyricsfiles") to be used for disk caching. If specified, this directory will be searched for a matching lyrics (.lrc) file (in this example, "/home/user/Music/LyricsFiles/artist/title.lrc"). If no matching lyrics file is found (and the search module list is not specifically set to "Cache" (and lyrics are found on the internet), then the lyrics will be saved to the directory under "artist/title.lrc".

Default: none (no caching)

An optional dirctional indicator ("<" or ">") can be prepended to the directory to limit caching activity. "<" allows fetching lyrics from the cache directory, but will not cache (write) new lyrics found on the web to the directory. ">" (the opposite) will cache new lyrics but will never attempt to fetch (read) lyrics from the cache directory. These options may be useful if one either simply wants to build a lyrics database but always fetch the latest, or perhaps limit lyrics to a fixed cache but not add to it, or perhaps is using a readonly directory. The default is no indicator which allows both reading and writing.

Directory must be a valid directory, but may be specified as either a path (ie. "/home/user/lyrics") or a URI (ie. "file:///home/user/lyrics") or with a limiting directional indicator, ie. "</home/user/lyrics". It may or may not have a trailing "/" (ie. "/home/user/lyrics/").

NOTE: This value will be overridden if $founder->cache("directory") is called! NOTE: See below how to specify a different agent for a specific site module.

-debug => number

Specifies whether debug information will be displayed (0: no, >0: yes).

Default 0 (no). 1 will display debug info. There is currently only one level of debug verbosity.

-noextra => 0 | 1 (false or true)

Some sites (currently, only Musixmatch) may append some additional information below the lyrics text. If specified or given a true value, this will be suppressed and only the actual song lyrics returned. Default 0 (false) - show any additional site-specific information.

-omit => "site-module[,site-module2...]]

Permits omitting specific sites which are currently installed from being searched (namely when using random or all). For example, to exclude the Musixmatch site, specify: -omit => "Musixmatch", which will cause LyricFinder::Musixmatch to not be considered for lyrics search. Default is for all installed sites (submodules) to be considered. NOTE: The site list can be specified as a comma-separated string OR as an array reference, ie. -omit = [ qw(Musixmatch Genius) ]>.

-site-module-name => { "-option" => value [, "-option" => value ... ] }

Specifies options for a specific site fetcher module. These values will override any of the general option values specified for that specific module or calls to the general agent() method, if it is used to fetch lyrics. Examples would be if one needed to specify a different user-agent for one of the sites, or wished to cache lyrics fetched by sites to specific directories for some reason. By default, top-level options are passed to the various sites, so this should only be needed in special cases.

Example: "-Musixmatch => { -noextra => 1 }"

Default: none (no site-specific options)

NOTE: The "-cache" (cache-directory) option is needed by the main LyricFinder module and the site submodules in order to use the caching feature, so passing "-Cache => {-cache => directory}" will NOT work (the way one might assume)!

[ $current-agent string = ] $finder->agent( [ user-agent string ] )

Set the desired user-agent (ie. browser name) to pass to the lyrics sites. Some sites are pickey about receiving a user-agent string that corresponds to a valid / supported web-browser to prevent their sites from being "scraped" by programs, such as this.

Default: "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"

If no argument is passed, it returns the current GENERAL user-agent string in effect (but a different agent option is specified for a specific module may have been specified and used by THAT module - see new() options above).

NOTE: This will override any -agent option value specified in new()! NOTE: See above how to specify a different user-agent for a specific site module.

[ $current-directory = ] $finder->cache( [ $directory ] )

Specifies a directory (ie. "/home/user/Music/Lyricsfiles") to be used for disk caching. If specified, this directory will be searched for a matching lyrics (.lrc) file (in this example, "/home/user/Music/LyricsFiles/artist/title.lrc"). If no matching lyrics file is found (and the search module list is not specifically set to "Cache" (and lyrics are found on the internet), then the lyrics will be saved to the directory under "artist/title.lrc".

An optional dirctional indicator ("<" or ">") can be prepended to the directory to limit caching activity. "<" allows fetching lyrics from the cache directory, but will not cache (write) new lyrics found on the web to the directory. ">" (the opposite) will cache new lyrics but will never attempt to fetch (read) lyrics from the cache directory. These options may be useful if one either simply wants to build a lyrics database but always fetch the latest, or perhaps limit lyrics to a fixed cache but not add to it, or perhaps is using a readonly directory. The default is no indicator which allows both reading and writing.

Directory must be a valid directory, but may be specified as either a path (ie. "/home/user/lyrics") or a URI (ie. "file:///home/user/lyrics") or with a limiting directional indicator, ie. "</home/user/lyrics". It may or may not have a trailing "/" (ie. "/home/user/lyrics/").

If no argument is passed, it returns the current GENERAL cache directory string in effect (but a different directory option is specified for a specific module may have been specified and used by THAT module - see new() options above).

NOTE: This will override any -cache option value specified in new()!

NOTE: See above how to specify a different directory for a specific site module.

[ $scalar | @array ] = $finder->credits()

Returns either a comma-separated list or an array of names credited by the site with posting the lyrics on the site (if any) or an empty string, if none found. NOTE: The only site that supports this currently is AZLyrics.

$string = $finder->fetch($artist, $title [, $source | \@sources [, $limit]])

Attempt to fetch the lyrics for the given artist and title. A single source site module can be specified as a string ($source) or multiple source modules, ie. [module1, module2...], or "random" or "Cache". Default: "random" (search all available sites in random order until lyrics found or all available sites have been searched). This is the primary method call, and the only one required (besides new()) to be called to obtain lyrics. $limit (if specified) is an integer number to limit the max. number of fetchers to try (normally used with $source = "random") to limit the time needed to search for lyrics (before giving up). If not specified, zero, or higher than the number of installed fetchers, then all available (installed) fetcher submodules (sites) will be tried (until one succefully finds lyrics).

"Cache" is a special value that limits searching to a specified lyrics directory on one's local hard drive. NOTE: It should NOT be included in a list, but used by itself. If a lyrics directory is specified, Cache will automatically be searched first!

If an array reference (a list) of modules are provided, they will be searched in the order they appear in the list.

The currently-installed and supported modules are: ApiLyricsOvh, AZLyrics, Genius, Letras, and Musixmatch (NOTE the "x" in the spelling of "Musixmatch")!

Returns lyrics as a string (includes line-breaks appropriate for the user's operating system), or an empty string, if no lyrics found.

$scalar = $finder->image_url()

Returns a URL for a cover-art image, if one found on the lyrics page. Currently, only the LyricFinder::Genius and LyricFinder::Musixmatch sites contain cover-art images. For the other sites, or if no image is found, an empty string will be returned if this method is called.

$scalar = $finder->message()

Returns the last error string generated, or "Ok" if all's well.

[ $scalar | @array ] = $finder->order()

Returns either a comma-separated list or an array of the site modules tried by the last fetch. This is useful to see what sites are being tried and in what order if random order is being used. Similar to tried(), except all sites being considered are shown.

$scalar = $finder->site()

Returns the actual base URL of the site that successfully fetched the lyrics in the last successful fetch (or an empty string if the fetch failed).

$scalar = $finder->source()

Returns the name of the module that successfully fetched the lyrics in the last successful fetch (or "none" if the fetch failed).

[ $arrayref | @array ] = $finder->sources()

Returns a list of available site modules. Similar to Lyric::Fetcher's available_fetchers() function.

[ $scalar | @array ] = $finder->tried()

Returns either a comma-separated list or an array of the site modules actually tried when fetching lyrics. This is useful to see what sites were actually hit and in what order if random order is being used. Similar to order(), except only sites actually hit are shown (the last one is the one that successfully fetched the lyrics.

$scalar = $finder->url()

Returns the actual URL used to fetch the lyrics from the site (includes the actual formatted search arguments passed to the site). This can be helpful in debugging, etc.

NOTE: If caching is being used and lyrics are found and fetched from the cache directory, site() will return the full filename of the cache file fetched.

$LyricFinder::VERSION

The current version# of LyricFinder

DEPENDENCIES

HTML::Strip, HTTP::Request, LWP::UserAgent, URI::Escape

BUGS

Please report any bugs or feature requests to bug-lyricFinder at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=LyricFinder. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc LyricFinder

SEE ALSO

Fauxdacious media player - (https://wildstar84.wordpress.com/fauxdacious)

LICENSE AND COPYRIGHT

Copyright (c) 2020 Jim Turner.

This program is free software; you can redistribute it and/or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:

http://www.perlfoundation.org/artistic_license_2_0

Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.

If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.

This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.

This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.

Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Original Lyrics::Fetcher::* work:

Copyright (C) 2007-2020 David Precious.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.7 or, at your option, any later version of Perl 5 you may have available.

Legal disclaimer: I have no connection with the owners of www.genius.com. Lyrics fetched by this script may be copyrighted by the authors, it's up to you to determine whether this is the case, and if so, whether you are entitled to request/use those lyrics. You will almost certainly not be allowed to use the lyrics obtained for any commercial purposes.

All comments / suggestions / bug reports gratefully received (ideally use the RT installation at https://rt.cpan.org/ or through the web interface at https://rt.cpan.org/NoAuth/ReportBug.html?Queue=LyricFinder, or mail me direct if you prefer).

Developed on Github at https://github.com/bigpresh/LyricFinder

Previously: Copyright 2003 Sir Reflog <reflog@mail15.com>. Copyright 2003 Zachary P. Landau <kapheine@hypa.net>