using PocketSharp.Models; using RestSharp; using RestSharp.Contrib; using System; using System.Collections.Generic; using System.Net; namespace PocketSharp { /// /// PocketClient /// public partial class PocketClient { /// /// REST client used for the API communication /// protected readonly RestClient _restClient; /// /// The base URL for the Pocket API /// protected static Uri baseUri = new Uri("https://getpocket.com/v3/"); /// /// The authentification URL /// protected string authentificationUri = "https://getpocket.com/auth/authorize?request_token={0}&redirect_uri={1}"; /// /// callback URL for API calls /// protected string CallbackUri { get; set; } /// /// Accessor for the Pocket API key /// see: http://getpocket.com/developer /// public string ConsumerKey { get; set; } /// /// Returns all associated data from the last request /// public IRestResponse LastRequestData { get; private set; } /// /// Code retrieved on authentification /// public string RequestCode { get; set; } /// /// Code retrieved on authentification-success /// public string AccessCode { get; set; } /// /// Initializes a new instance of the class. /// /// The API key /// Provide an access code if the user is already authenticated /// The callback URL is called by Pocket after authentication public PocketClient(string consumerKey, string accessCode = null, string callbackUri = null) { // assign public properties ConsumerKey = consumerKey; // assign access code if submitted if (accessCode != null) { AccessCode = accessCode.ToString(); } // assign callback uri if submitted if (callbackUri != null) { CallbackUri = HttpUtility.UrlEncode(callbackUri.ToString()); } // initialize REST client _restClient = new RestClient(baseUri.ToString()); // add default parameters to each request _restClient.AddDefaultParameter("consumer_key", ConsumerKey); // Pocket needs this specific Accept header :-S _restClient.AddDefaultHeader("Accept", "*/*"); // defines the response format (according to the Pocket docs) _restClient.AddDefaultHeader("X-Accept", "application/json"); // custom JSON deserializer (ServiceStack.Text) _restClient.AddHandler("application/json", new JsonDeserializer()); // add custom deserialization lambdas JsonDeserializer.AddCustomDeserialization(); } /// /// Makes a HTTP REST request to the API /// /// The request. /// protected string Request(RestRequest request) { IRestResponse response = _restClient.Execute(request); LastRequestData = response; ValidateResponse(response); return response.Content; } /// /// Makes a typed HTTP REST request to the API /// /// /// The request. /// protected T Request(RestRequest request) where T : new() { IRestResponse response = _restClient.Execute(request); LastRequestData = response; ValidateResponse(response); return response.Data; } /// /// Fetches a typed resource /// /// /// Requested method (path after /v3/) /// Additional POST parameters /// if set to true [require auth]. /// /// No access token available. Use authentification first. protected T Get(string method, List parameters = null, bool requireAuth = false) where T : class, new() { if (requireAuth && AccessCode == null) { throw new APIException("No access token available. Use authentification first."); } // every single Pocket API endpoint requires HTTP POST data var request = new RestRequest(method, Method.POST); // add access token (necessary for all requests except authentification) if (AccessCode != null) { request.AddParameter("access_token", AccessCode); } // enumeration for params if (parameters != null) { parameters.ForEach(delegate(Parameter param) { request.AddParameter(param); }); } // do the request return Request(request); } /// /// Puts an action /// /// The action parameter. /// protected bool PutSendAction(ActionParameter actionParameter) { ModifyParameters parameters = new ModifyParameters() { Actions = new List() { actionParameter } }; return Get("send", parameters.Convert(), true).Status; } /// /// Validates the response. /// /// The response. /// /// /// Error retrieving response /// protected void ValidateResponse(IRestResponse response) { if (response.StatusCode != HttpStatusCode.OK) { // get pocket error headers Parameter error = response.Headers[1]; Parameter errorCode = response.Headers[2]; string exceptionString = response.Content; bool isPocketError = error.Name == "X-Error"; // update message to include pocket response data if (isPocketError) { exceptionString = exceptionString + "\nPocketResponse: (" + errorCode.Value + ") " + error.Value; } // create exception APIException exception = new APIException(exceptionString, response.ErrorException); if (isPocketError) { // add custom pocket fields exception.PocketError = error.Value.ToString(); exception.PocketErrorCode = Convert.ToInt32(errorCode.Value); // add to generic exception data exception.Data.Add(error.Name, error.Value); exception.Data.Add(errorCode.Name, errorCode.Value); } throw exception; } else if (response.ErrorException != null) { throw new APIException("Error retrieving response", response.ErrorException); } } } }