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.

   This module is derived from the (older0 Lyrics::Fetcher collection of
   modules by (c) 2007-2020 David Precious, but currently (as of December,
   2020) supports more lyric sites (4), bundles all the supported site
   modules together here (simply install this one module), has 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 a few 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 sever 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"). 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. 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"*.

           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"*, and -debug => *integer*.
           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.

       site-module-name => { *"-option"* => *value* [, *"-option"* =>
       *value* ... ] }
           Specifies these same 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.

           Default: none (no site-specific options)

   [ *$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*])
       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.

       "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, 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->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

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>)

   *   RT: CPAN's request tracker (report bugs here)

       <http://rt.cpan.org/NoAuth/Bugs.html?Dist=LyricFinder>

   *   CPAN Ratings

       <http://cpanratings.perl.org/d/LyricFinder>

   *   Search CPAN

       <http://search.cpan.org/dist/LyricFinder/>

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 <[email protected]>. Copyright
   2003 Zachary P. Landau <[email protected]>