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