1
0
mirror of https://github.com/clementine-player/Clementine synced 2024-12-18 04:19:55 +01:00

Add an Encyclopaedia Metallum lyrics provider. Fixes issue 3568

This commit is contained in:
Paweł Szymański 2013-12-03 20:21:52 +11:00 committed by David Sansome
parent 5207af6f93
commit 6e8cfc7762
4 changed files with 78 additions and 26 deletions

View File

@ -43,6 +43,14 @@
</exclude> </exclude>
<invalidIndicator value="Page not Found"/> <invalidIndicator value="Page not Found"/>
</provider> </provider>
<provider name="Encyclopaedia Metallum" title="{title Lyrics - {artist}" charset="utf-8" url="http://www.metal-archives.com/search/ajax-advanced/searching/songs/?songTitle={title}&amp;bandName={artist}&amp;ExactBandMatch=1">
<extract>
<item url="http://www.metal-archives.com/release/ajax-view-lyrics/id/{id}"/>
<item begin="id=\&quot;lyricsLink_" end="&quot;"/>
</extract>
<invalidIndicator value="&quot;iTotalRecords&quot;: 0"/>
<invalidIndicator value="lyrics not available"/>
</provider>
<provider name="letras.mus.br" title="" charset="iso-8859-1" url="http://letras.terra.com.br/winamp.php?musica={title}&amp;artista={artist}"> <provider name="letras.mus.br" title="" charset="iso-8859-1" url="http://letras.terra.com.br/winamp.php?musica={title}&amp;artista={artist}">
<urlFormat replace="_@,;&amp;\/&quot;" with="_"/> <urlFormat replace="_@,;&amp;\/&quot;" with="_"/>
<urlFormat replace=" " with="+"/> <urlFormat replace=" " with="+"/>

View File

@ -34,7 +34,8 @@ const int UltimateLyricsProvider::kRedirectLimit = 5;
UltimateLyricsProvider::UltimateLyricsProvider() UltimateLyricsProvider::UltimateLyricsProvider()
: network_(new NetworkAccessManager(this)), : network_(new NetworkAccessManager(this)),
relevance_(0), relevance_(0),
redirect_count_(0) redirect_count_(0),
url_hop_(false)
{ {
} }
@ -64,13 +65,16 @@ void UltimateLyricsProvider::FetchInfo(int id, const Song& metadata) {
void UltimateLyricsProvider::LyricsFetched() { void UltimateLyricsProvider::LyricsFetched() {
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender()); QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
if (!reply) if (!reply) {
url_hop_ = false;
return; return;
}
int id = requests_.take(reply); int id = requests_.take(reply);
reply->deleteLater(); reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
url_hop_ = false;
emit Finished(id); emit Finished(id);
return; return;
} }
@ -79,6 +83,7 @@ void UltimateLyricsProvider::LyricsFetched() {
QVariant redirect_target = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); QVariant redirect_target = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (redirect_target.isValid()) { if (redirect_target.isValid()) {
if (redirect_count_ >= kRedirectLimit) { if (redirect_count_ >= kRedirectLimit) {
url_hop_ = false;
emit Finished(id); emit Finished(id);
return; return;
} }
@ -105,11 +110,13 @@ void UltimateLyricsProvider::LyricsFetched() {
foreach (const QString& indicator, invalid_indicators_) { foreach (const QString& indicator, invalid_indicators_) {
if (original_content.contains(indicator)) { if (original_content.contains(indicator)) {
qLog(Debug) << "Found invalid indicator" << indicator; qLog(Debug) << "Found invalid indicator" << indicator;
url_hop_ = false;
emit Finished(id); emit Finished(id);
return; return;
} }
} }
if (!url_hop_) {
// Apply extract rules // Apply extract rules
foreach (const Rule& rule, extract_rules_) { foreach (const Rule& rule, extract_rules_) {
// Modify the rule for this request's metadata // Modify the rule for this request's metadata
@ -119,18 +126,28 @@ void UltimateLyricsProvider::LyricsFetched() {
} }
QString content = original_content; QString content = original_content;
ApplyExtractRule(rule_copy, &content); if (ApplyExtractRule(rule_copy, &content)) {
qLog(Debug) << "Extract rule" << rule_copy << "matched" << content.length(); url_hop_ = true;
QUrl url(content);
qLog(Debug) << "Next url hop: " << url;
QNetworkReply* reply = network_->get(QNetworkRequest(url));
requests_[reply] = id;
connect(reply, SIGNAL(finished()), SLOT(LyricsFetched()));
return;
}
// Apply exclude rules
foreach (const Rule& rule, exclude_rules_) {
ApplyExcludeRule(rule, &lyrics);
}
if (!content.isEmpty()) { if (!content.isEmpty()) {
lyrics = content; lyrics = content;
break; break;
} }
} }
} else {
// Apply exclude rules lyrics = original_content;
foreach (const Rule& rule, exclude_rules_) {
ApplyExcludeRule(rule, &lyrics);
} }
if (!lyrics.isEmpty()) { if (!lyrics.isEmpty()) {
@ -152,17 +169,40 @@ void UltimateLyricsProvider::LyricsFetched() {
emit InfoReady(id, data); emit InfoReady(id, data);
} }
url_hop_ = false;
emit Finished(id); emit Finished(id);
} }
void UltimateLyricsProvider::ApplyExtractRule(const Rule& rule, QString* content) const { bool UltimateLyricsProvider::ApplyExtractRule(const Rule& rule, QString* content) const {
foreach (const RuleItem& item, rule) { foreach (const RuleItem& item, rule) {
if (item.second.isNull()) { if (item.second.isNull()) {
if (item.first.startsWith("http://") && item.second.isNull()) {
*content = ExtractUrl(*content, rule);
return true;
} else {
*content = ExtractXmlTag(*content, item.first); *content = ExtractXmlTag(*content, item.first);
}
} else { } else {
*content = Extract(*content, item.first, item.second); *content = Extract(*content, item.first, item.second);
} }
} }
return false;
}
QString UltimateLyricsProvider::ExtractUrl(const QString& source, const Rule& rule) {
QString url;
QString id;
foreach(const RuleItem& item, rule) {
if (item.first.startsWith("http://") && item.second.isNull())
url = item.first;
else
id = Extract(source, item.first,item.second);
}
url.replace("{id}", id);
return url;
} }
QString UltimateLyricsProvider::ExtractXmlTag(const QString& source, const QString& tag) { QString UltimateLyricsProvider::ExtractXmlTag(const QString& source, const QString& tag) {

View File

@ -62,9 +62,10 @@ private slots:
void LyricsFetched(); void LyricsFetched();
private: private:
void ApplyExtractRule(const Rule& rule, QString* content) const; bool ApplyExtractRule(const Rule& rule, QString* content) const;
void ApplyExcludeRule(const Rule& rule, QString* content) const; void ApplyExcludeRule(const Rule& rule, QString* content) const;
static QString ExtractUrl(const QString& source, const Rule& rule);
static QString ExtractXmlTag(const QString& source, const QString& tag); static QString ExtractXmlTag(const QString& source, const QString& tag);
static QString Extract(const QString& source, const QString& begin, const QString& end); static QString Extract(const QString& source, const QString& begin, const QString& end);
static QString ExcludeXmlTag(const QString& source, const QString& tag); static QString ExcludeXmlTag(const QString& source, const QString& tag);
@ -93,6 +94,7 @@ private:
Song metadata_; Song metadata_;
int redirect_count_; int redirect_count_;
bool url_hop_;
}; };
#endif // ULTIMATELYRICSPROVIDER_H #endif // ULTIMATELYRICSPROVIDER_H

View File

@ -110,6 +110,8 @@ UltimateLyricsProvider::Rule UltimateLyricsReader::ParseRule(QXmlStreamReader* r
QXmlStreamAttributes attr = reader->attributes(); QXmlStreamAttributes attr = reader->attributes();
if (attr.hasAttribute("tag")) if (attr.hasAttribute("tag"))
ret << UltimateLyricsProvider::RuleItem(attr.value("tag").toString(), QString()); ret << UltimateLyricsProvider::RuleItem(attr.value("tag").toString(), QString());
else if (attr.hasAttribute("url"))
ret << UltimateLyricsProvider::RuleItem(attr.value("url").toString(), QString());
else if (attr.hasAttribute("begin")) else if (attr.hasAttribute("begin"))
ret << UltimateLyricsProvider::RuleItem(attr.value("begin").toString(), ret << UltimateLyricsProvider::RuleItem(attr.value("begin").toString(),
attr.value("end").toString()); attr.value("end").toString());