| blib/lib/LyricFinder/Letras.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 20 | 91 | 21.9 |
| branch | 0 | 30 | 0.0 |
| condition | 0 | 27 | 0.0 |
| subroutine | 7 | 10 | 70.0 |
| pod | 2 | 2 | 100.0 |
| total | 29 | 160 | 18.1 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package LyricFinder::Letras; | ||||||
| 2 | |||||||
| 3 | 1 | 1 | 6 | use strict; | |||
| 1 | 1 | ||||||
| 1 | 24 | ||||||
| 4 | 1 | 1 | 4 | use warnings; | |||
| 1 | 1 | ||||||
| 1 | 19 | ||||||
| 5 | 1 | 1 | 4 | use Carp; | |||
| 1 | 2 | ||||||
| 1 | 40 | ||||||
| 6 | 1 | 1 | 5 | use HTML::Strip; | |||
| 1 | 1 | ||||||
| 1 | 26 | ||||||
| 7 | 1 | 1 | 5 | use parent 'LyricFinder::_Class'; | |||
| 1 | 1 | ||||||
| 1 | 5 | ||||||
| 8 | |||||||
| 9 | our $haveLyricsCache; | ||||||
| 10 | BEGIN { | ||||||
| 11 | 1 | 1 | 69 | $haveLyricsCache = 0; | |||
| 12 | 1 | 1 | 56 | eval "use LyricFinder::Cache; \$haveLyricsCache = 1; 1"; | |||
| 1 | 5 | ||||||
| 1 | 1 | ||||||
| 1 | 25 | ||||||
| 13 | } | ||||||
| 14 | |||||||
| 15 | my $Source = 'Letras'; | ||||||
| 16 | my $Site = 'https://www.letras.mus.br'; | ||||||
| 17 | my $DEBUG = 0; | ||||||
| 18 | |||||||
| 19 | sub new | ||||||
| 20 | { | ||||||
| 21 | 0 | 0 | 1 | my $class = shift; | |||
| 22 | |||||||
| 23 | 0 | my $self = $class->SUPER::new($Source, @_); | |||||
| 24 | 0 | @{$self->{'_fetchers'}} = ($Source); | |||||
| 0 | |||||||
| 25 | 0 | unshift(@{$self->{'_fetchers'}}, 'Cache') if ($haveLyricsCache | |||||
| 26 | 0 | 0 | 0 | && $self->{'-cache'} && $self->{'-cache'} !~ /^\>/); | |||
| 0 | |||||||
| 27 | |||||||
| 28 | 0 | bless $self, $class; #BLESS IT! | |||||
| 29 | |||||||
| 30 | 0 | return $self; | |||||
| 31 | } | ||||||
| 32 | |||||||
| 33 | sub fetch { | ||||||
| 34 | 0 | 0 | 1 | my ($self, $artist_in, $song_in) = @_; | |||
| 35 | |||||||
| 36 | 0 | $self->_debug("Letras::fetch($artist_in, $song_in)!"); | |||||
| 37 | |||||||
| 38 | 0 | 0 | return '' unless ($self->_check_inputs($artist_in, $song_in)); | ||||
| 39 | 0 | 0 | return '' if ($self->{'Error'} ne 'Ok'); | ||||
| 40 | |||||||
| 41 | 0 | my $artist = $artist_in; | |||||
| 42 | 0 | my $song = $song_in; | |||||
| 43 | # first, see if we've got it cached: | ||||||
| 44 | 0 | $self->_debug("i:haveCache=$haveLyricsCache= -cachedir=".$self->{'-cache'}."="); | |||||
| 45 | 0 | 0 | 0 | if ($haveLyricsCache && $self->{'-cache'} && $self->{'-cache'} !~ /^\>/) { | |||
| 0 | |||||||
| 46 | 0 | my $cache = new LyricFinder::Cache(%{$self}); | |||||
| 0 | |||||||
| 47 | 0 | 0 | if ($cache) { | ||||
| 48 | 0 | my $lyrics = $cache->fetch($artist, $song); | |||||
| 49 | 0 | 0 | 0 | if (defined($lyrics) && $lyrics =~ /\w/) { | |||
| 50 | 0 | $self->_debug("..Got lyrics from cache."); | |||||
| 51 | 0 | $self->{'Source'} = 'Cache'; | |||||
| 52 | 0 | $self->{'Site'} = $cache->site(); | |||||
| 53 | 0 | $self->{'Url'} = $cache->url(); | |||||
| 54 | |||||||
| 55 | 0 | return $lyrics; | |||||
| 56 | } | ||||||
| 57 | } | ||||||
| 58 | } | ||||||
| 59 | |||||||
| 60 | 0 | $self->{'Site'} = $Site; | |||||
| 61 | |||||||
| 62 | 0 | $artist = $self->_remove_accents($artist); | |||||
| 63 | 0 | $song = $self->_remove_accents($song); | |||||
| 64 | |||||||
| 65 | # Their URLs look like e.g.: | ||||||
| 66 | # https://www.letras.mus.br/ |
||||||
| 67 | 0 | ($self->{'Url'} = $artist) =~ s#\s*\/\s*# and #; #CONVERT "artist1 / artist2" TO "artist1 and artist2"! | |||||
| 68 | 0 | $song =~ s#\s*\/\s*#\-#g; #FIX SONGS WITH "/" IN THEM! | |||||
| 69 | 0 | $self->{'Url'} .= "/${song}-lyrics"; | |||||
| 70 | 0 | $self->{'Url'} =~ s/\&/and/g; | |||||
| 71 | 0 | $self->{'Url'} =~ s/ +/\-/g; | |||||
| 72 | 0 | $self->{'Url'} = $Site . '/' . $self->{'Url'}; | |||||
| 73 | 0 | $self->{'Url'} =~ tr/A-Z/a-z/; | |||||
| 74 | 0 | $self->{'_confirm_title'} = $song_in; | |||||
| 75 | 0 | $self->{'_confirm_artist'} = $artist_in; | |||||
| 76 | 0 | my $lyrics = $self->_web_fetch($artist, $song); | |||||
| 77 | 0 | 0 | 0 | if ($lyrics && $haveLyricsCache && $self->{'-cache'} && $self->{'-cache'} !~ /^\) { | |||
| 0 | |||||||
| 0 | |||||||
| 78 | 0 | $self->_debug("=== WILL CACHE LYRICS! ==="); | |||||
| 79 | # cache the fetched lyrics, if we can: | ||||||
| 80 | 0 | my $cache = new LyricFinder::Cache(%{$self}); | |||||
| 0 | |||||||
| 81 | 0 | 0 | $cache->save($artist, $song, $lyrics) if ($cache); | ||||
| 82 | } | ||||||
| 83 | 0 | return $lyrics; | |||||
| 84 | } | ||||||
| 85 | |||||||
| 86 | sub _parse { | ||||||
| 87 | 0 | 0 | my $self = shift; | ||||
| 88 | 0 | my $html = shift; | |||||
| 89 | |||||||
| 90 | 0 | $self->_debug("Letras::_parse()!"); | |||||
| 91 | 0 | 0 | if (my ($goodbit) = $html =~ | ||||
| 92 | m{\ (.+?)\<\/div\>}msi) |
||||||
| 93 | { | ||||||
| 94 | 0 | my $hs = HTML::Strip->new(); | |||||
| 95 | |||||||
| 96 | #LETRAS SOMETIMES RETURNS "BEST GUESS" (WRONG) SONG LYRICS IF NOT FOUND, AND WE | ||||||
| 97 | #DON'T WANT THIS, SO WE MUST CONFIRM THAT THE TITLE AND ARTIST MATCH WHAT WE | ||||||
| 98 | #REQUESTED, AND PUNT IF THEY DON'T!: | ||||||
| 99 | 0 | 0 | if ($html =~ m#\ (.+?)\<\/div\>#msi) { |
||||
| 100 | 0 | my $headers = $1; | |||||
| 101 | 0 | 0 | my $title = ($headers =~ m#\(.+?)\<\/h1\>#si) ? $hs->parse($1) : ''; |
||||
| 102 | 0 | $title =~ s/^\s+//; | |||||
| 103 | 0 | $title =~ s/\s+$//; | |||||
| 104 | 0 | 0 | if ($title) { | ||||
| 105 | 0 | 0 | if ($self->{'_confirm_title'} !~ /^${title}$/i) { | ||||
| 106 | 0 | $self->{'Error'} = "e:$Source - Results did not match title ($title)."; | |||||
| 107 | 0 | return ''; | |||||
| 108 | } | ||||||
| 109 | 0 | 0 | my $artist = ($headers =~ m#\(.+?)\<\/h2\>#si) ? $hs->parse($1) : ''; |
||||
| 110 | 0 | $artist =~ s/^\s+//; | |||||
| 111 | 0 | $artist =~ s/\s+$//; | |||||
| 112 | 0 | 0 | 0 | if ($artist && $self->{'_confirm_artist'} !~ /^${artist}$/i) { | |||
| 113 | 0 | $self->{'Error'} = "e:$Source - Results did not match artist ($artist)."; | |||||
| 114 | 0 | return ''; | |||||
| 115 | } | ||||||
| 116 | } | ||||||
| 117 | } | ||||||
| 118 | |||||||
| 119 | 0 | $goodbit =~ s#\<\/?p\>#\r\n#gsi; | |||||
| 120 | 0 | $goodbit =~ s#\ #\r\n#gsi; |
|||||
| 121 | 0 | my $text = $hs->parse($goodbit); | |||||
| 122 | |||||||
| 123 | 0 | return $self->_normalize_lyric_text($self->_html2text($text)); | |||||
| 124 | } else { | ||||||
| 125 | 0 | carp($self->{'Error'} = "e:$Source - Failed to identify lyrics on result page."); | |||||
| 126 | 0 | return ''; | |||||
| 127 | } | ||||||
| 128 | } | ||||||
| 129 | |||||||
| 130 | 1 | ||||||
| 131 | |||||||
| 132 | __END__ |