diff --git a/FeedlySharp/FeedlyClient.Tags.cs b/FeedlySharp/FeedlyClient.Tags.cs new file mode 100644 index 0000000..ce7b6a3 --- /dev/null +++ b/FeedlySharp/FeedlyClient.Tags.cs @@ -0,0 +1,59 @@ +using FeedlySharp.Models; +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.Linq; + +namespace FeedlySharp +{ + public partial class FeedlyClient + { + public async Task> GetTags(CancellationToken cancellationToken = default(CancellationToken)) + { + return await Client.AuthRequest>(HttpMethod.Get, "v3/tags", null, cancellationToken); + } + + + public async Task UpdateTags(string entryId, string[] tags, CancellationToken cancellationToken = default(CancellationToken)) + { + string tagsString = String.Join(",", tags.Select(x => ValueToResource("tag", x))); + await Client.AuthRequest(HttpMethod.Put, String.Format("v3/tags/{0}", tagsString), new { entryId = entryId }, cancellationToken); + return true; + } + + + public async Task UpdateTags(string[] entryIds, string[] tags, CancellationToken cancellationToken = default(CancellationToken)) + { + string tagsString = String.Join(",", tags.Select(x => ValueToResource("tag", x))); + await Client.AuthRequest(HttpMethod.Put, String.Format("v3/tags/{0}", tagsString), new { entryIds = entryIds }, cancellationToken); + return true; + } + + + public async Task RenameTag(string oldTag, string newTag, CancellationToken cancellationToken = default(CancellationToken)) + { + await Client.AuthRequest(HttpMethod.Post, String.Format("v3/tags/{0}", ValueToResource("tag", oldTag)), new { label = newTag }, cancellationToken); + return true; + } + + + public async Task RemoveTags(string[] entryIds, string[] tags, CancellationToken cancellationToken = default(CancellationToken)) + { + string tagsString = String.Join(",", tags.Select(x => ValueToResource("tag", x))); + string entryIdsString = String.Join(",", entryIds.Select(x => WebUtility.UrlEncode(x))); + await Client.AuthRequest(HttpMethod.Delete, String.Format("v3/tags/{0}/{1}", tagsString, entryIdsString), null, cancellationToken); + return true; + } + + + public async Task RemoveTags(string[] tags, CancellationToken cancellationToken = default(CancellationToken)) + { + string tagsString = String.Join(",", tags.Select(x => ValueToResource("tag", x))); + await Client.AuthRequest(HttpMethod.Delete, String.Format("v3/tags/{0}", tagsString), null, cancellationToken); + return true; + } + } +} diff --git a/FeedlySharp/FeedlyClient.cs b/FeedlySharp/FeedlyClient.cs index dac943b..79964cc 100644 --- a/FeedlySharp/FeedlyClient.cs +++ b/FeedlySharp/FeedlyClient.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Text; using System.Threading.Tasks; @@ -20,6 +21,8 @@ namespace FeedlySharp private string AccessToken { get; set; } + private string UserId { get; set; } + private FeedlyHttpClient Client { get; set; } @@ -38,9 +41,10 @@ namespace FeedlySharp } - public void Activate(string accessToken) + public void Activate(string accessToken, string userId) { AccessToken = accessToken; + UserId = userId; Client.AccessToken = accessToken; } @@ -50,6 +54,11 @@ namespace FeedlySharp return String.Format("https://{0}.feedly.com", environment == CloudEnvironment.Production ? "cloud" : "sandbox"); } + private string ValueToResource(string key, string value) + { + return WebUtility.UrlEncode(String.Format("user/{0}/{1}/{2}", UserId, key, value)); + } + public void Dispose() { diff --git a/FeedlySharp/FeedlyHttpClient.cs b/FeedlySharp/FeedlyHttpClient.cs index 913cde3..4bab7ed 100644 --- a/FeedlySharp/FeedlyHttpClient.cs +++ b/FeedlySharp/FeedlyHttpClient.cs @@ -32,14 +32,28 @@ namespace FeedlySharp throw new FeedlySharpException("This request requires an access token."); } - return await Request(method, requestUri, parameters, cancellationToken, new Dictionary() + return await Request(method, requestUri, parameters, null, 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() + public async Task AuthRequest(HttpMethod method, string requestUri, dynamic body = 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, null, body, cancellationToken, new Dictionary() + { + { "Authorization", String.Format("OAuth {0}", AccessToken) } + }); + } + + + public async Task Request(HttpMethod method, string requestUri, Dictionary parameters = null, dynamic body = null, CancellationToken cancellationToken = default(CancellationToken), Dictionary headers = null) where T : class, new() { HttpRequestMessage request = new HttpRequestMessage(method, requestUri); HttpResponseMessage response = null; @@ -58,6 +72,11 @@ namespace FeedlySharp request.Headers.Add(header.Key, header.Value); } } + // body + if (body != null) + { + request.Content = new StringContent(JsonConvert.SerializeObject(body)); + } // make async request try diff --git a/FeedlySharp/FeedlySharp.csproj b/FeedlySharp/FeedlySharp.csproj index c843f7d..afcafaf 100644 --- a/FeedlySharp/FeedlySharp.csproj +++ b/FeedlySharp/FeedlySharp.csproj @@ -36,6 +36,7 @@ + @@ -43,6 +44,7 @@ + diff --git a/FeedlySharp/Models/FeedlyTag.cs b/FeedlySharp/Models/FeedlyTag.cs new file mode 100644 index 0000000..7f82ce3 --- /dev/null +++ b/FeedlySharp/Models/FeedlyTag.cs @@ -0,0 +1,14 @@ +using Newtonsoft.Json; +using System; + +namespace FeedlySharp.Models +{ + public class FeedlyTag + { + public string Id { get; set; } + + public string Label { get; set; } + + public bool IsGlobal { get; set; } + } +}