Add support for fetching lyrics from jah-lyrics.com and plyrics.com
This commit is contained in:
1
NEWS
1
NEWS
@@ -23,6 +23,7 @@ ncmpcpp-0.8 (????-??-??)
|
||||
* Fixed fetching artist info in language other than English.
|
||||
* Added test that checks if lyrics fetchers work (available via command line parameter --test-lyrics-fetchers).
|
||||
* Fixed fetching lyrics from justsomelyrics.com.
|
||||
* Added support for fetching lyrics from jah-lyrics.com and plyrics.com.
|
||||
|
||||
ncmpcpp-0.7.7 (2016-10-31)
|
||||
* Fixed compilation on 32bit platforms.
|
||||
|
||||
@@ -360,7 +360,7 @@
|
||||
#
|
||||
#lines_scrolled = 2
|
||||
#
|
||||
#lyrics_fetchers = lyricwiki, azlyrics, genius, sing365, lyricsmania, metrolyrics, justsomelyrics, tekstowo, internet
|
||||
#lyrics_fetchers = lyricwiki, azlyrics, genius, sing365, lyricsmania, metrolyrics, justsomelyrics, jahlyrics, plyrics, tekstowo, internet
|
||||
#
|
||||
#follow_now_playing_lyrics = no
|
||||
#
|
||||
|
||||
@@ -139,25 +139,27 @@ bool configure(int argc, char **argv)
|
||||
|
||||
if (vm.count("test-lyrics-fetchers"))
|
||||
{
|
||||
std::vector<std::string> fetcher_names = {
|
||||
"lyricwiki",
|
||||
"azlyrics",
|
||||
"genius",
|
||||
"sing365",
|
||||
"lyricsmania",
|
||||
"metrolyrics",
|
||||
"justsomelyrics",
|
||||
"tekstowo",
|
||||
std::vector<std::tuple<std::string, std::string, std::string>> fetcher_data = {
|
||||
std::make_tuple("lyricwiki", "rihanna", "umbrella"),
|
||||
std::make_tuple("azlyrics", "rihanna", "umbrella"),
|
||||
std::make_tuple("genius", "rihanna", "umbrella"),
|
||||
std::make_tuple("sing365", "rihanna", "umbrella"),
|
||||
std::make_tuple("lyricsmania", "rihanna", "umbrella"),
|
||||
std::make_tuple("metrolyrics", "rihanna", "umbrella"),
|
||||
std::make_tuple("justsomelyrics", "rihanna", "umbrella"),
|
||||
std::make_tuple("jahlyrics", "sean kingston", "dry your eyes"),
|
||||
std::make_tuple("plyrics", "offspring", "genocide"),
|
||||
std::make_tuple("tekstowo", "rihanna", "umbrella"),
|
||||
};
|
||||
for (auto &name : fetcher_names)
|
||||
for (auto &data : fetcher_data)
|
||||
{
|
||||
auto fetcher = boost::lexical_cast<LyricsFetcher_>(name);
|
||||
auto fetcher = boost::lexical_cast<LyricsFetcher_>(std::get<0>(data));
|
||||
std::cout << std::setw(20)
|
||||
<< std::left
|
||||
<< fetcher->name()
|
||||
<< " : "
|
||||
<< std::flush;
|
||||
auto result = fetcher->fetch("rihanna", "umbrella");
|
||||
auto result = fetcher->fetch(std::get<1>(data), std::get<2>(data));
|
||||
std::cout << (result.first ? "ok" : "failed")
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
@@ -52,6 +52,10 @@ std::istream &operator>>(std::istream &is, LyricsFetcher_ &fetcher)
|
||||
fetcher = std::make_unique<MetrolyricsFetcher>();
|
||||
else if (s == "justsomelyrics")
|
||||
fetcher = std::make_unique<JustSomeLyricsFetcher>();
|
||||
else if (s == "jahlyrics")
|
||||
fetcher = std::make_unique<JahLyricsFetcher>();
|
||||
else if (s == "plyrics")
|
||||
fetcher = std::make_unique<PLyricsFetcher>();
|
||||
else if (s == "tekstowo")
|
||||
fetcher = std::make_unique<TekstowoFetcher>();
|
||||
else if (s == "internet")
|
||||
@@ -63,14 +67,15 @@ std::istream &operator>>(std::istream &is, LyricsFetcher_ &fetcher)
|
||||
|
||||
const char LyricsFetcher::msgNotFound[] = "Not found";
|
||||
|
||||
LyricsFetcher::Result LyricsFetcher::fetch(const std::string &artist, const std::string &title)
|
||||
LyricsFetcher::Result LyricsFetcher::fetch(const std::string &artist,
|
||||
const std::string &title)
|
||||
{
|
||||
Result result;
|
||||
result.first = false;
|
||||
|
||||
std::string url = urlTemplate();
|
||||
boost::replace_all(url, "%artist%", artist);
|
||||
boost::replace_all(url, "%title%", title);
|
||||
boost::replace_all(url, "%artist%", Curl::escape(artist));
|
||||
boost::replace_all(url, "%title%", Curl::escape(title));
|
||||
|
||||
std::string data;
|
||||
CURLcode code = Curl::perform(data, url);
|
||||
@@ -106,7 +111,8 @@ LyricsFetcher::Result LyricsFetcher::fetch(const std::string &artist, const std:
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> LyricsFetcher::getContent(const char *regex_, const std::string &data)
|
||||
std::vector<std::string> LyricsFetcher::getContent(const char *regex_,
|
||||
const std::string &data)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
boost::regex rx(regex_);
|
||||
@@ -135,7 +141,8 @@ void LyricsFetcher::postProcess(std::string &data) const
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
LyricsFetcher::Result LyricwikiFetcher::fetch(const std::string &artist, const std::string &title)
|
||||
LyricsFetcher::Result LyricwikiFetcher::fetch(const std::string &artist,
|
||||
const std::string &title)
|
||||
{
|
||||
LyricsFetcher::Result result = LyricsFetcher::fetch(artist, title);
|
||||
if (result.first == true)
|
||||
@@ -194,16 +201,17 @@ bool LyricwikiFetcher::notLyrics(const std::string &data) const
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
LyricsFetcher::Result GoogleLyricsFetcher::fetch(const std::string &artist, const std::string &title)
|
||||
LyricsFetcher::Result GoogleLyricsFetcher::fetch(const std::string &artist,
|
||||
const std::string &title)
|
||||
{
|
||||
Result result;
|
||||
result.first = false;
|
||||
|
||||
std::string search_str = artist;
|
||||
std::string search_str = Curl::escape(artist);
|
||||
search_str += "+";
|
||||
search_str += title;
|
||||
search_str += Curl::escape(title);
|
||||
search_str += "+%2B";
|
||||
search_str += siteKeyword();
|
||||
search_str += Curl::escape(siteKeyword());
|
||||
|
||||
std::string google_url = "http://www.google.com/search?hl=en&ie=UTF-8&oe=UTF-8&q=";
|
||||
google_url += search_str;
|
||||
@@ -217,9 +225,9 @@ LyricsFetcher::Result GoogleLyricsFetcher::fetch(const std::string &artist, cons
|
||||
result.second = curl_easy_strerror(code);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
auto urls = getContent("<A HREF=\"(.*?)\">here</A>", data);
|
||||
|
||||
|
||||
if (urls.empty() || !isURLOk(urls[0]))
|
||||
{
|
||||
result.second = msgNotFound;
|
||||
@@ -247,7 +255,8 @@ bool MetrolyricsFetcher::isURLOk(const std::string &url)
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
LyricsFetcher::Result InternetLyricsFetcher::fetch(const std::string &artist, const std::string &title)
|
||||
LyricsFetcher::Result InternetLyricsFetcher::fetch(const std::string &artist,
|
||||
const std::string &title)
|
||||
{
|
||||
GoogleLyricsFetcher::fetch(artist, title);
|
||||
LyricsFetcher::Result result;
|
||||
|
||||
@@ -131,6 +131,22 @@ protected:
|
||||
virtual const char *regex() const override { return "<lyrics.*?>(.*?)</lyrics>"; }
|
||||
};
|
||||
|
||||
struct JahLyricsFetcher : public GoogleLyricsFetcher
|
||||
{
|
||||
virtual const char *name() const override { return "jah-lyrics.com"; }
|
||||
|
||||
protected:
|
||||
virtual const char *regex() const override { return "<div class=\"song-header\">.*?</div>(.*?)<p class=\"disclaimer\">"; }
|
||||
};
|
||||
|
||||
struct PLyricsFetcher : public GoogleLyricsFetcher
|
||||
{
|
||||
virtual const char *name() const override { return "plyrics.com"; }
|
||||
|
||||
protected:
|
||||
virtual const char *regex() const override { return "<!-- start of lyrics -->(.*?)<!-- end of lyrics -->"; }
|
||||
};
|
||||
|
||||
struct TekstowoFetcher : public GoogleLyricsFetcher
|
||||
{
|
||||
virtual const char *name() const override { return "tekstowo.pl"; }
|
||||
|
||||
@@ -124,8 +124,8 @@ boost::optional<std::string> downloadLyrics(
|
||||
std::shared_ptr<std::atomic<bool>> download_stopper,
|
||||
LyricsFetcher *current_fetcher)
|
||||
{
|
||||
std::string s_artist = Curl::escape(s.getArtist());
|
||||
std::string s_title = Curl::escape(s.getTitle());
|
||||
std::string s_artist = s.getArtist();
|
||||
std::string s_title = s.getTitle();
|
||||
// If artist or title is empty, use filename. This should give reasonable
|
||||
// results for google search based lyrics fetchers.
|
||||
if (s_artist.empty() || s_title.empty())
|
||||
@@ -137,7 +137,6 @@ boost::optional<std::string> downloadLyrics(
|
||||
size_t dot = s_title.rfind('.');
|
||||
if (dot != std::string::npos)
|
||||
s_title.resize(dot);
|
||||
s_title = Curl::escape(s_title);
|
||||
}
|
||||
|
||||
auto fetch_lyrics = [&](auto &fetcher_) {
|
||||
|
||||
@@ -389,7 +389,7 @@ bool Configuration::read(const std::vector<std::string> &config_paths, bool igno
|
||||
p.add("cyclic_scrolling", &use_cyclic_scrolling, "no", yes_no);
|
||||
p.add("lines_scrolled", &lines_scrolled, "2");
|
||||
p.add("lyrics_fetchers", &lyrics_fetchers,
|
||||
"lyricwiki, azlyrics, genius, sing365, lyricsmania, metrolyrics, justsomelyrics, tekstowo, internet",
|
||||
"lyricwiki, azlyrics, genius, sing365, lyricsmania, metrolyrics, justsomelyrics, jahlyrics, plyrics, tekstowo, internet",
|
||||
list_of<LyricsFetcher_>);
|
||||
p.add("follow_now_playing_lyrics", &now_playing_lyrics, "no", yes_no);
|
||||
p.add("fetch_lyrics_for_current_song_in_background", &fetch_lyrics_in_background,
|
||||
|
||||
Reference in New Issue
Block a user