diff --git a/src/LinqToTwitter6/LinqToTwitter.Tests/BlocksTests/BlocksCommandsTests.cs b/src/LinqToTwitter6/LinqToTwitter.Tests/BlocksTests/BlocksCommandsTests.cs index 116f89fe..bfc0b74e 100644 --- a/src/LinqToTwitter6/LinqToTwitter.Tests/BlocksTests/BlocksCommandsTests.cs +++ b/src/LinqToTwitter6/LinqToTwitter.Tests/BlocksTests/BlocksCommandsTests.cs @@ -55,7 +55,7 @@ public async Task CreateBlockAsync_Handles_Response() const bool SkipStatus = true; var ctx = InitializeTwitterContext(); - User actual = await ctx.CreateBlockAsync(Id, null, SkipStatus); + User actual = await ctx.BlockUserAsync(Id, null, SkipStatus); Assert.AreEqual("LINQ to Tweeter Test", actual.Name); } @@ -67,7 +67,7 @@ public async Task CreateBlockAsync_WithRawResult_Succeeds() const bool SkipStatus = true; var ctx = InitializeTwitterContext(); - await ctx.CreateBlockAsync(Id, null, SkipStatus); + await ctx.BlockUserAsync(Id, null, SkipStatus); Assert.AreEqual(BlocksUserJson, ctx.RawResult); } @@ -79,7 +79,7 @@ public async Task CreateBlockAsync_Builds_Url() const bool SkipStatus = true; var ctx = InitializeTwitterContext(); - await ctx.CreateBlockAsync(Id, null, SkipStatus); + await ctx.BlockUserAsync(Id, null, SkipStatus); execMock.Verify(exec => exec.PostFormUrlEncodedToTwitterAsync( @@ -96,7 +96,7 @@ public async Task CreateBlockAsync_Throws_On_Null_UserID_And_ScreenName() var ctx = InitializeTwitterContext(); var ex = await L2TAssert.Throws( - async () => await ctx.CreateBlockAsync(0, null, true)); + async () => await ctx.BlockUserAsync(0, null, true)); Assert.AreEqual("UserIDOrScreenName", ex.ParamName); } @@ -108,7 +108,7 @@ public async Task DestroyBlockAsync_Handles_Response() const bool SkipStatus = true; var ctx = InitializeTwitterContext(); - User actual = await ctx.DestroyBlockAsync(Id, null, SkipStatus); + User actual = await ctx.UnblockUserAsync(Id, null, SkipStatus); Assert.AreEqual("LINQ to Tweeter Test", actual.Name); } @@ -120,7 +120,7 @@ public async Task DestroyBlockAsync_WithRawResult_Succeeds() const bool SkipStatus = true; var ctx = InitializeTwitterContext(); - await ctx.DestroyBlockAsync(Id, null, SkipStatus); + await ctx.UnblockUserAsync(Id, null, SkipStatus); Assert.AreEqual(BlocksUserJson, ctx.RawResult); } @@ -132,7 +132,7 @@ public async Task DestroyBlockAsync_Builds_Url() const bool SkipStatus = true; var ctx = InitializeTwitterContext(); - await ctx.DestroyBlockAsync(Id, null, SkipStatus); + await ctx.UnblockUserAsync(Id, null, SkipStatus); execMock.Verify(exec => exec.PostFormUrlEncodedToTwitterAsync( @@ -149,7 +149,7 @@ public async Task DestroyBlockAsync_Throws_On_No_ID_Or_ScreenName() var ctx = InitializeTwitterContext(); var ex = await L2TAssert.Throws( - async () => await ctx.DestroyBlockAsync(0, null, true)); + async () => await ctx.UnblockUserAsync(0, null, true)); Assert.AreEqual("UserIDOrScreenName", ex.ParamName); } diff --git a/src/LinqToTwitter6/LinqToTwitter/Blocks/BlockingResponse.cs b/src/LinqToTwitter6/LinqToTwitter/Blocks/BlockingResponse.cs new file mode 100644 index 00000000..720ecd41 --- /dev/null +++ b/src/LinqToTwitter6/LinqToTwitter/Blocks/BlockingResponse.cs @@ -0,0 +1,11 @@ +using System; +using System.Text.Json.Serialization; + +namespace LinqToTwitter +{ + public class BlockingResponse + { + [JsonPropertyName("data")] + public BlockingResponseData? Data { get; init; } + } +} diff --git a/src/LinqToTwitter6/LinqToTwitter/Blocks/BlockingResponseData.cs b/src/LinqToTwitter6/LinqToTwitter/Blocks/BlockingResponseData.cs new file mode 100644 index 00000000..c7b9ba98 --- /dev/null +++ b/src/LinqToTwitter6/LinqToTwitter/Blocks/BlockingResponseData.cs @@ -0,0 +1,10 @@ +using System.Text.Json.Serialization; + +namespace LinqToTwitter +{ + public record BlockingResponseData + { + [JsonPropertyName("blocking")] + public bool Blocking { get; set; } + } +} diff --git a/src/LinqToTwitter6/LinqToTwitter/Blocks/TwitterContextBlockCommands.cs b/src/LinqToTwitter6/LinqToTwitter/Blocks/TwitterContextBlockCommands.cs index 4370fc5e..5222cdd2 100644 --- a/src/LinqToTwitter6/LinqToTwitter/Blocks/TwitterContextBlockCommands.cs +++ b/src/LinqToTwitter6/LinqToTwitter/Blocks/TwitterContextBlockCommands.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Net.Http; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -10,95 +10,69 @@ namespace LinqToTwitter public partial class TwitterContext { /// - /// Blocks a user. + /// Block a user. /// - /// ID of user to block - /// Screen name of user to block - /// Don't include status + /// Following user ID + /// Followed user ID + /// Allows request cancellation /// User that was unblocked - public async Task CreateBlockAsync(ulong userID, string screenName, bool skipStatus) + public async Task BlockUserAsync(string sourceUserID, string targetUserID, CancellationToken cancelToken = default(CancellationToken)) { - return await CreateBlockAsync(userID, screenName, true, skipStatus).ConfigureAwait(false); - } - - /// - /// Blocks a user. - /// - /// ID of user to block - /// Screen name of user to block - /// Set to false to not include entities (default: true) - /// Don't include status - /// User that was unblocked - public async Task CreateBlockAsync(ulong userID, string screenName, bool includeEntities, bool skipStatus, CancellationToken cancelToken = default(CancellationToken)) - { - if (userID <= 0 && string.IsNullOrWhiteSpace(screenName)) - throw new ArgumentException("Either userID or screenName are required parameters.", "UserIDOrScreenName"); + _ = sourceUserID ?? throw new ArgumentException($"{nameof(sourceUserID)} is a required parameter.", nameof(sourceUserID)); + _ = targetUserID ?? throw new ArgumentException($"{nameof(targetUserID)} is a required parameter.", nameof(targetUserID)); - var blocksUrl = BaseUrl + "blocks/create.json"; + var url = $"{BaseUrl}users/{sourceUserID}/blocking"; var reqProc = new BlocksRequestProcessor(); + var postData = new Dictionary(); + var postObj = new TwitterUserTargetID() { TargetUserID = targetUserID.ToString() }; + RawResult = - await TwitterExecutor.PostFormUrlEncodedToTwitterAsync( + await TwitterExecutor.SendJsonToTwitterAsync( HttpMethod.Post.ToString(), - blocksUrl, - new Dictionary - { - { "user_id", userID <= 0 ? null : userID.ToString() }, - { "screen_name", screenName }, - { "include_entities", includeEntities.ToString().ToLower() }, - { "skip_status", skipStatus.ToString().ToLower() } - }, + url, + postData, + postObj, cancelToken) - .ConfigureAwait(false); + .ConfigureAwait(false); - return reqProc.ProcessActionResult(RawResult, UserAction.SingleUser); - } + BlockingResponse? result = JsonSerializer.Deserialize(RawResult); - /// - /// Unblocks a user. - /// - /// ID of user to block - /// Screen name of user to block - /// Don't include status - /// User that was unblocked - public async Task DestroyBlockAsync(ulong userID, string screenName, bool skipStatus, CancellationToken cancelToken = default(CancellationToken)) - { - return await DestroyBlockAsync(userID, screenName, true, skipStatus, cancelToken).ConfigureAwait(false); + return result; } /// - /// Unblocks a user. + /// Unblock a user. /// - /// ID of user to block - /// Screen name of user to block - /// Set to false to not include entities (default: true) - /// Don't include status + /// Following user ID + /// Followed user ID + /// Allows request cancellation /// User that was unblocked - public async Task DestroyBlockAsync(ulong userID, string screenName, bool includeEntities, bool skipStatus, CancellationToken cancelToken = default(CancellationToken)) + public async Task UnblockUserAsync(string sourceUserID, string targetUserID, CancellationToken cancelToken = default(CancellationToken)) { - if (userID <= 0 && string.IsNullOrWhiteSpace(screenName)) - throw new ArgumentException("Either userID or screenName are required parameters.", "UserIDOrScreenName"); + _ = sourceUserID ?? throw new ArgumentException($"{nameof(sourceUserID)} is a required parameter.", nameof(sourceUserID)); + _ = targetUserID ?? throw new ArgumentException($"{nameof(targetUserID)} is a required parameter.", nameof(targetUserID)); - var blocksUrl = BaseUrl + "blocks/destroy.json"; + var url = $"{BaseUrl}users/{sourceUserID}/blocking/{targetUserID}"; var reqProc = new BlocksRequestProcessor(); + var postData = new Dictionary(); + var postObj = new TwitterUserTargetID() { TargetUserID = targetUserID.ToString() }; + RawResult = - await TwitterExecutor.PostFormUrlEncodedToTwitterAsync( - HttpMethod.Post.ToString(), - blocksUrl, - new Dictionary - { - { "user_id", userID <= 0 ? null : userID.ToString() }, - { "screen_name", screenName }, - { "include_entities", includeEntities.ToString().ToLower() }, - { "skip_status", skipStatus.ToString().ToLower() } - }, + await TwitterExecutor.SendJsonToTwitterAsync( + HttpMethod.Delete.ToString(), + url, + postData, + postObj, cancelToken) - .ConfigureAwait(false); + .ConfigureAwait(false); + + BlockingResponse? result = JsonSerializer.Deserialize(RawResult); - return reqProc.ProcessActionResult(RawResult, UserAction.SingleUser); + return result; } } } diff --git a/src/LinqToTwitter6/LinqToTwitter/User/TwitterContextUserCommands.cs b/src/LinqToTwitter6/LinqToTwitter/User/TwitterContextUserCommands.cs index 58ca9e45..48a72092 100644 --- a/src/LinqToTwitter6/LinqToTwitter/User/TwitterContextUserCommands.cs +++ b/src/LinqToTwitter6/LinqToTwitter/User/TwitterContextUserCommands.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Net.Http; using System.Text.Json; using System.Threading;