diff --git a/src/lastfm_service.cpp b/src/lastfm_service.cpp new file mode 100644 index 00000000..f678573a --- /dev/null +++ b/src/lastfm_service.cpp @@ -0,0 +1,175 @@ +/*************************************************************************** + * Copyright (C) 2008-2010 by Andrzej Rybczak * + * electricityispower@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "lastfm_service.h" + +#ifdef HAVE_CURL_CURL_H + +#include "conv.h" +#include "curl_handle.h" +#include "settings.h" + +const char *LastfmService::baseURL = "http://ws.audioscrobbler.com/2.0/?api_key=d94e5b6e26469a2d1ffae8ef20131b79&method="; + +const char *LastfmService::msgParseFailed = "Fetched data could not be parsed"; + +LastfmService::Result LastfmService::fetch(Args &args) +{ + Result result; + + std::string url = baseURL; + url += methodName(); + for (Args::const_iterator it = args.begin(); it != args.end(); ++it) + { + url += "&"; + url += it->first; + url += "="; + url += Curl::escape(it->second); + } + + std::string data; + CURLcode code = Curl::perform(data, url); + + if (code != CURLE_OK) + { + result.second = curl_easy_strerror(code); + return result; + } + + if (actionFailed(data)) + { + StripHtmlTags(data); + result.second = data; + return result; + } + + if (!parse(data)) + { + // if relevant part of data was not found and one of arguments + // was language, try to fetch it again without that parameter. + // otherwise just report failure. + Args::iterator lang = args.find("lang"); + if (lang != args.end()) + { + args.erase(lang); + return fetch(args); + } + else + { + // parse should change data to error msg, if it fails + result.second = data; + return result; + } + } + + result.first = true; + result.second = data; + return result; +} + +bool LastfmService::actionFailed(const std::string &data) +{ + return data.find("status=\"failed\"") != std::string::npos; +} + +void LastfmService::postProcess(std::string &data) +{ + StripHtmlTags(data); + Trim(data); +} + +/***********************************************************************/ + +bool ArtistInfo::checkArgs(const Args &args) +{ + return args.find("artist") != args.end(); +} + +void ArtistInfo::colorizeOutput(NCurses::Scrollpad &w) +{ + w.SetFormatting(fmtBold, U("\n\nSimilar artists:\n"), fmtBoldEnd, false); + w.SetFormatting(Config.color2, U("\n * "), clEnd, true); + // below is used so format won't be removed using RemoveFormatting() by accident. + w.ForgetFormatting(); +} + +bool ArtistInfo::parse(std::string &data) +{ + size_t a, b; + bool parse_failed = false; + + if ((a = data.find("")) != std::string::npos) + { + a += static_strlen(""); + if ((b = data.find("")) == std::string::npos) + parse_failed = true; + } + else + parse_failed = true; + + if (parse_failed) + { + data = msgParseFailed; + return false; + } + + if (a == b) + { + data = "No description available for this artist."; + return false; + } + + std::vector< std::pair > similars; + for (size_t i = data.find(""), j, k = data.find(""), l; + i != std::string::npos; i = data.find("", i), k = data.find("", k)) + { + j = data.find("", i); + i += static_strlen(""); + + l = data.find("", k); + k += static_strlen(""); + + similars.push_back(std::make_pair(data.substr(i, j-i), data.substr(k, l-k))); + StripHtmlTags(similars.back().first); + } + + a += static_strlen(""); + data = data.substr(a, b-a); + + postProcess(data); + + data += "\n\nSimilar artists:\n"; + for (size_t i = 1; i < similars.size(); ++i) + { + data += "\n * "; + data += similars[i].first; + data += " ("; + data += similars[i].second; + data += ")"; + } + data += "\n\n"; + data += similars.front().second; + + return true; +} + +#endif + diff --git a/src/lastfm_service.h b/src/lastfm_service.h new file mode 100644 index 00000000..2258d33a --- /dev/null +++ b/src/lastfm_service.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (C) 2008-2010 by Andrzej Rybczak * + * electricityispower@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef _LASTFM_SERVICE_H +#define _LASTFM_SERVICE_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_CURL_CURL_H + +#include +#include + +#include "scrollpad.h" + +struct LastfmService +{ + typedef std::map Args; + typedef std::pair Result; + + virtual const char *name() = 0; + virtual Result fetch(Args &args); + + virtual bool checkArgs(const Args &args) = 0; + virtual void colorizeOutput(NCurses::Scrollpad &w) = 0; + + protected: + virtual bool actionFailed(const std::string &data); + + virtual bool parse(std::string &data) = 0; + virtual void postProcess(std::string &data); + + virtual const char *methodName() = 0; + + static const char *baseURL; + static const char *msgParseFailed; +}; + +struct ArtistInfo : public LastfmService +{ + virtual const char *name() { return "Artist info"; } + + virtual bool checkArgs(const Args &args); + virtual void colorizeOutput(NCurses::Scrollpad &w); + + protected: + virtual bool parse(std::string &data); + + virtual const char *methodName() { return "artist.getinfo"; } +}; + +#endif // HAVE_CURL_CURL_H + +#endif \ No newline at end of file