diff --git a/FeedlySharp/Extensions/JsonExtensions.cs b/FeedlySharp/Extensions/JsonExtensions.cs index 1a2e9a4..bf66c7a 100644 --- a/FeedlySharp/Extensions/JsonExtensions.cs +++ b/FeedlySharp/Extensions/JsonExtensions.cs @@ -43,7 +43,7 @@ namespace FeedlySharp.Extensions public override bool CanConvert(Type objectType) { - return objectType == typeof(TimeSpan); + return objectType == typeof(TimeSpan) || objectType == typeof(TimeSpan?); } } @@ -57,12 +57,12 @@ namespace FeedlySharp.Extensions DateTime epoc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); var delta = date.Subtract(epoc); - writer.WriteValue((int)Math.Truncate(delta.TotalSeconds)); + writer.WriteValue((int)Math.Truncate(delta.TotalMilliseconds)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - if (reader.Value.ToString() == "0") + if (reader.Value.ToString() == "0" || reader.Value == null) { return null; } @@ -72,7 +72,12 @@ namespace FeedlySharp.Extensions return null; } - return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(Convert.ToDouble(reader.Value)); + return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(Convert.ToDouble(reader.Value)); + } + + public override bool CanConvert(Type objectType) + { + return objectType == typeof(DateTime) || objectType == typeof(DateTime?); } } diff --git a/FeedlySharp/FeedlyClient.User.cs b/FeedlySharp/FeedlyClient.User.cs new file mode 100644 index 0000000..338f5d7 --- /dev/null +++ b/FeedlySharp/FeedlyClient.User.cs @@ -0,0 +1,24 @@ +using FeedlySharp.Models; +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace FeedlySharp +{ + public partial class FeedlyClient + { + public async Task GetUser(CancellationToken cancellationToken = default(CancellationToken)) + { + return await Client.AuthRequest(HttpMethod.Get, "v3/profile", null, cancellationToken); + } + + + public async Task UpdateUser(Dictionary parameters, CancellationToken cancellationToken = default(CancellationToken)) + { + return await Client.AuthRequest(HttpMethod.Post, "v3/profile", parameters, cancellationToken); + } + } +} diff --git a/FeedlySharp/FeedlyClient.cs b/FeedlySharp/FeedlyClient.cs index 8ad9e82..dac943b 100644 --- a/FeedlySharp/FeedlyClient.cs +++ b/FeedlySharp/FeedlyClient.cs @@ -18,6 +18,8 @@ namespace FeedlySharp private string CloudUri { get { return GetCloudUri(Environment); } } + private string AccessToken { get; set; } + private FeedlyHttpClient Client { get; set; } @@ -36,6 +38,13 @@ namespace FeedlySharp } + public void Activate(string accessToken) + { + AccessToken = accessToken; + Client.AccessToken = accessToken; + } + + private string GetCloudUri(CloudEnvironment environment) { return String.Format("https://{0}.feedly.com", environment == CloudEnvironment.Production ? "cloud" : "sandbox"); @@ -46,11 +55,11 @@ namespace FeedlySharp { Client.Dispose(); } + } - public enum CloudEnvironment - { - Production, - Sandbox - } + public enum CloudEnvironment + { + Production, + Sandbox } } diff --git a/FeedlySharp/FeedlyHttpClient.cs b/FeedlySharp/FeedlyHttpClient.cs index ddb621a..682de88 100644 --- a/FeedlySharp/FeedlyHttpClient.cs +++ b/FeedlySharp/FeedlyHttpClient.cs @@ -15,6 +15,9 @@ namespace FeedlySharp { internal class FeedlyHttpClient : HttpClient { + public string AccessToken { get; set; } + + public FeedlyHttpClient(Uri baseUri) : base() { BaseAddress = baseUri; @@ -22,19 +25,39 @@ namespace FeedlySharp } - public async Task Request(HttpMethod method, string requestUri, Dictionary parameters, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() + public async Task AuthRequest(HttpMethod method, string requestUri, Dictionary parameters = null, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() + { + if (String.IsNullOrEmpty(AccessToken)) + { + throw new FeedlySharpException("This request requires an access token."); + } + + return await Request(method, requestUri, parameters, cancellationToken, new Dictionary() + { + { "Authorization", String.Format("OAuth {0}", AccessToken) } + }); + } + + + public async Task Request(HttpMethod method, string requestUri, Dictionary parameters = null, CancellationToken cancellationToken = default(CancellationToken), Dictionary headers = null) where T : class, new() { HttpRequestMessage request = new HttpRequestMessage(method, requestUri); HttpResponseMessage response = null; string responseString = null; - if (parameters == null) - { - parameters = new Dictionary(); - } - // content of the request - request.Content = new FormUrlEncodedContent(parameters); + if (parameters != null) + { + request.Content = new FormUrlEncodedContent(parameters); + } + // additional headers + if (headers != null) + { + foreach (KeyValuePair header in headers) + { + request.Headers.Add(header.Key, header.Value); + } + } // make async request try @@ -93,6 +116,7 @@ namespace FeedlySharp { new BoolConverter(), new UnixDateTimeConverter(), + new TimeSpanConverter(), new NullableIntConverter(), new UriConverter() } diff --git a/FeedlySharp/FeedlySharp.csproj b/FeedlySharp/FeedlySharp.csproj index 7577423..5b1cdb8 100644 --- a/FeedlySharp/FeedlySharp.csproj +++ b/FeedlySharp/FeedlySharp.csproj @@ -38,8 +38,10 @@ + + diff --git a/FeedlySharp/Models/FeedlyUser.cs b/FeedlySharp/Models/FeedlyUser.cs new file mode 100644 index 0000000..bd7aca1 --- /dev/null +++ b/FeedlySharp/Models/FeedlyUser.cs @@ -0,0 +1,109 @@ +using Newtonsoft.Json; +using System; + +namespace FeedlySharp.Models +{ + [JsonObject] + public class FeedlyUser + { + public string Id { get; set; } + + public string Email { get; set; } + + public string GivenName { get; set; } + + public string FamilyName { get; set; } + + public string FullName { get; set; } + + public Uri Picture { get; set; } + + public Gender Gender { get; set; } + + public string Locale { get; set; } + + [JsonProperty("google")] + public string OAuthGoogleId { get; set; } + + [JsonProperty("reader")] + public string OAuthGoogleReaderId { get; set; } + + [JsonProperty("twitterUserId")] + public string OAuthTwitterId { get; set; } + + [JsonProperty("facebookUserId")] + public string OAuthFacebookId { get; set; } + + [JsonProperty("wordPressId")] + public string OAuthWordpressId { get; set; } + + [JsonProperty("windowsLiveId")] + public string OAuthMicrosoftId { get; set; } + + public string Wave { get; set; } + + public string Client { get; set; } + + [JsonProperty("source")] + public string ClientSource { get; set; } + + [JsonProperty("created")] + public DateTime? CreationDate { get; set; } + + [JsonProperty("product")] + public ProProduct ProProduct { get; set; } + + [JsonProperty("productExpiration")] + public TimeSpan? ProExpiration { get; set; } + + [JsonProperty("subscriptionStatus")] + public ProStatus ProStatus { get; set; } + + [JsonProperty("evernoteConnected")] + public bool IsEvernoteConnected { get; set; } + + [JsonProperty("pocketConnected")] + public bool IsPocketConnected { get; set; } + + [JsonProperty("dropboxConnected")] + public bool IsDropboxConnected { get; set; } + + [JsonProperty("facebookConnected")] + public bool IsFacebookConnected { get; set; } + + [JsonProperty("twitterConnected")] + public bool IsTwitterConnected { get; set; } + + [JsonProperty("windowsLiveConnected")] + public bool IsMicrosoftConnected { get; set; } + + [JsonProperty("wordPressConnected")] + public bool IsWordpressConnected { get; set; } + } + + public enum Gender + { + Unknown, + Male, + Female + } + + public enum ProProduct + { + None, + FeedlyProMonthly, + FeedlyProYearly, + FeedlyProLifetime + } + + public enum ProStatus + { + None, + Active, + PastDue, + Canceled, + Unpaid, + Deleted, + Expired + } +} diff --git a/FeedlySharp/Models/Responses.cs b/FeedlySharp/Models/Responses.cs index 3179d1c..df5e234 100644 --- a/FeedlySharp/Models/Responses.cs +++ b/FeedlySharp/Models/Responses.cs @@ -25,7 +25,6 @@ namespace FeedlySharp.Models public string AccessToken { get; set; } [JsonProperty("expires_in")] - [JsonConverter(typeof(TimeSpanConverter))] public TimeSpan ExpiresIn { get; set; } [JsonProperty("refresh_token")]