// Connection.cs // // Copyright (C) 2009 Amr Hassan // // 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 3 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, see . // using System; namespace Lastfm.Scrobbling { /// /// A connection to the Last.fm scrobbling service. Can be used individually for scrobbling /// or through a object. /// public class Connection { public string ClientID {get; private set;} private string SessionID {get; set;} private Uri SubmissionURL {get; set;} private Uri NowplayingURL {get; set;} private RequestParameters handshakeParameters; private bool firstHandshakeDone {get; set;} public Connection(string clientID, string clientVersion, string username, Lastfm.Services.Session authenticatedSession) { RequestParameters p = new RequestParameters(); p["hs"] = "true"; p["p"] = "1.2.1"; p["c"] = clientID; p["v"] = clientVersion; p["u"] = username; string timestamp = Utilities.DateTimeToUTCTimestamp(DateTime.Now).ToString(); p["t"] = timestamp; p["api_key"] = authenticatedSession.APIKey; p["sk"] = authenticatedSession.SessionKey; p["a"] = Utilities.md5(authenticatedSession.APISecret + timestamp); this.handshakeParameters = p; ClientID = clientID; } public Connection(string clientID, string clientVersion, string username, string md5Password) { RequestParameters p = new RequestParameters(); p["hs"] = "true"; p["p"] = "1.2.1"; p["c"] = clientID; p["v"] = clientVersion; p["u"] = username; string timestamp = Utilities.DateTimeToUTCTimestamp(DateTime.Now).ToString(); p["t"] = timestamp; p["a"] = Utilities.md5(md5Password + timestamp); this.handshakeParameters = p; ClientID = clientID; } /// /// A handshake is performed at the beginning to retrieve the /// SessionID, SubmissionURL and NowplayingURL and also everytime the server /// reports that the SessionID is invalid. /// private void doHandshake() { Request request = new Request(new Uri("http://post.audioscrobbler.com:80/"), handshakeParameters); string[] response = request.execute().Split('\n'); SessionID = response[1]; NowplayingURL = new Uri(response[2]); SubmissionURL = new Uri(response[3]); } /// /// Performs the initial handshake. Can be ignored, a handshake /// will be performed whenever necessary. /// public void Initialize() { if (!firstHandshakeDone) { doHandshake(); firstHandshakeDone = true; } } /// /// Send the now playing notification. /// /// /// A /// public void ReportNowplaying(NowplayingTrack track) { Initialize(); RequestParameters p = new RequestParameters(); p["s"] = SessionID; p["a"] = track.Artist; p["t"] = track.Title; p["b"] = track.Album; if (track.Duration.TotalSeconds == 0) p["l"] = ""; else p["l"] = track.Duration.TotalSeconds.ToString(); if (track.Number == 0) p["n"] = ""; else p["n"] = track.Number.ToString(); p["m"] = track.MBID; Request request = new Request(this.NowplayingURL, p); // A BadSessionException occurs when another client has made a handshake // with this user's credentials, should redo a handshake and pass this // exception quietly. try { request.execute(); } catch (BadSessionException) { this.doHandshake(); this.ReportNowplaying(track); } } /// /// Public scrobble function. Scrobbles a PlayedTrack object. /// /// /// A /// public void Scrobble(Entry track) { RequestParameters np = new RequestParameters(); RequestParameters p = track.getParameters(); foreach(string key in p.Keys) np[key + "[0]"] = p[key]; // This scrobbles the collection of parameters no matter what they belong to. this.Scrobble(np); } /// /// The internal scrobble function, scrobbles pure request parameters. /// Could be for more than one track, as specified by Last.fm, but they recommend that /// only one track should be submitted at a time. /// /// /// A /// internal void Scrobble(RequestParameters parameters) { Initialize(); parameters["s"] = SessionID; Request request = new Request(this.SubmissionURL, parameters); // A BadSessionException occurs when another client has made a handshake // with this user's credentials, should redo a handshake and pass this // exception quietly. try { request.execute(); } catch (BadSessionException) { this.doHandshake(); this.Scrobble(parameters); } } } }