/* This software is in the public domain, furnished "as is", without technical support, and with no warranty, express or implied, as to its usefulness for any purpose. */ #include #include struct MyCoreApp : QCoreApplication { Q_OBJECT public: MyCoreApp( int& argc, char**& argv ) : QCoreApplication( argc, argv ) {} private slots: void onWsError( lastfm::ws::Error e ) { // QNetworkReply will invoke this slot on application level errors // mostly this is only stuff like Ws::InvalidSessionKey and // Ws::InvalidApiKey qWarning() << e; } }; int main( int argc, char** argv ) { MyCoreApp app( argc, argv ); // this is used to generate the UserAgent for webservice requests // please set it to something sensible in your application app.setApplicationName( "liblastfm" ); ////// you'll need to fill these in for this demo to work lastfm::ws::Username = lastfm::ws::ApiKey = lastfm::ws::SharedSecret = QString password = ////// Usually you never have to construct an Last.fm WS API call manually // eg. Track.getTopTags() just returns a QNetworkReply* but authentication is // different. // We're using getMobileSession here as we're a console app, but you // should use getToken if you can as the user will be presented with a // route that feels my trustworthy to them than entering their password // into some random app they just downloaded... ;) QMap params; params["method"] = "auth.getMobileSession"; params["username"] = lastfm::ws::Username; params["authToken"] = lastfm::md5( (lastfm::ws::Username + lastfm::md5( password.toUtf8() )).toUtf8() ); QNetworkReply* reply = lastfm::ws::post( params ); // never do this when an event loop is running it's a real HACK QEventLoop loop; loop.connect( reply, SIGNAL(finished()), SLOT(quit()) ); loop.exec(); try { ////// Usually there is a convenience function to decode the output from // ws calls too, but again, authentication is different. We think you // need to handle it yourselves :P Also conveniently it means you // can learn more about what our webservices return, eg. this service // will return an XML document like this: // // // // mxcl // d580d57f32848f5dcf574d1ce18d78b2 // 1 // // // // If status is not "ok" then this function throws lastfm::XmlQuery const lfm = lastfm::ws::parse( reply ); // replace username; because eg. perhaps the user typed their // username with the wrong case lastfm::ws::Username = lfm["session"]["name"].text(); // we now have a session key, you should save this, forever! Really. // DO NOT AUTHENTICATE EVERY TIME THE APP STARTS! You only have to do // this once. Or again if the user deletes your key on the site. If // that happens you'll get notification to your onWsError() function, // see above. lastfm::ws::SessionKey = lfm["session"]["key"].text(); qDebug() << "sk:" << lastfm::ws::SessionKey; ////// because the SessionKey is now set, the AuthenticatedUser class will // work. And we can call authenticated calls QNetworkReply* reply = lastfm::AuthenticatedUser().getRecommendedArtists(); // again, you shouldn't do this.. ;) QEventLoop loop; loop.connect( reply, SIGNAL(finished()), SLOT(quit()) ); loop.exec(); // yay, a list rec'd artists to stderr :) qDebug() << lastfm::Artist::list( reply ); } catch (std::runtime_error& e) { // lastfm::ws::parse() can throw lastfm::ws::ParseError, this // exception derives std::runtime_error qWarning() << e.what(); return 1; } } #include "demo2.moc"