OSDN Git Service

MisskeyClient.CreatePostメソッドを実装
authorKimura Youichi <kim.upsilon@bucyou.net>
Mon, 27 May 2024 22:32:42 +0000 (07:32 +0900)
committerKimura Youichi <kim.upsilon@bucyou.net>
Mon, 10 Jun 2024 15:20:56 +0000 (00:20 +0900)
OpenTween.Tests/Api/Misskey/NoteCreateRequestTest.cs [new file with mode: 0644]
OpenTween/Api/Misskey/NoteCreateRequest.cs [new file with mode: 0644]
OpenTween/SocialProtocol/Misskey/MisskeyClient.cs

diff --git a/OpenTween.Tests/Api/Misskey/NoteCreateRequestTest.cs b/OpenTween.Tests/Api/Misskey/NoteCreateRequestTest.cs
new file mode 100644 (file)
index 0000000..d020c8a
--- /dev/null
@@ -0,0 +1,63 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2024 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// 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 <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Threading.Tasks;
+using Moq;
+using OpenTween.Connection;
+using Xunit;
+
+namespace OpenTween.Api.Misskey
+{
+    public class NoteCreateRequestTest
+    {
+        [Fact]
+        public async Task Send_Test()
+        {
+            var response = TestUtils.CreateApiResponse(new MisskeyNote());
+
+            var mock = new Mock<IApiConnection>();
+            mock.Setup(x =>
+                    x.SendAsync(It.IsAny<IHttpRequest>())
+                )
+                .Callback<IHttpRequest>(x =>
+                {
+                    var request = Assert.IsType<PostJsonRequest>(x);
+                    Assert.Equal(new("notes/create", UriKind.Relative), request.RequestUri);
+                    Assert.Equal(
+                        """{"replyId":"aaaaa","text":"tetete","visibility":"public"}""",
+                        request.JsonString
+                    );
+                })
+                .ReturnsAsync(response);
+
+            var request = new NoteCreateRequest
+            {
+                Text = "tetete",
+                Visibility = "public",
+                ReplyId = new("aaaaa"),
+            };
+            await request.Send(mock.Object);
+
+            mock.VerifyAll();
+        }
+    }
+}
diff --git a/OpenTween/Api/Misskey/NoteCreateRequest.cs b/OpenTween/Api/Misskey/NoteCreateRequest.cs
new file mode 100644 (file)
index 0000000..858e660
--- /dev/null
@@ -0,0 +1,90 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2024 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// 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 <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#nullable enable
+
+using System;
+using System.Runtime.Serialization;
+using System.Threading.Tasks;
+using OpenTween.Connection;
+using OpenTween.SocialProtocol.Misskey;
+
+namespace OpenTween.Api.Misskey
+{
+    public class NoteCreateRequest
+    {
+        public string? Text { get; set; }
+
+        public string? Visibility { get; set; }
+
+        public MisskeyNoteId? ReplyId { get; set; }
+
+        public MisskeyNoteId? RenoteId { get; set; }
+
+        public async Task<MisskeyNote> Send(IApiConnection apiConnection)
+        {
+            var request = new PostJsonRequest
+            {
+                RequestUri = new("notes/create", UriKind.Relative),
+                JsonString = this.CreateRequestJson(),
+            };
+
+            using var response = await apiConnection.SendAsync(request)
+                .ConfigureAwait(false);
+
+            var responseBody = await response.ReadAsJson<ResponseBody>()
+                .ConfigureAwait(false);
+
+            return responseBody.CreatedNote;
+        }
+
+        [DataContract]
+        private record RequestBody(
+            [property: DataMember(Name = "text", EmitDefaultValue = false)]
+            string? Text,
+            [property: DataMember(Name = "visibility", EmitDefaultValue = false)]
+            string? Visibility,
+            [property: DataMember(Name = "replyId", EmitDefaultValue = false)]
+            string? ReplyId,
+            [property: DataMember(Name = "renoteId", EmitDefaultValue = false)]
+            string? RenoteId
+        );
+
+        [DataContract]
+        private class ResponseBody
+        {
+            [DataMember(Name = "createdNote")]
+            public MisskeyNote CreatedNote { get; set; } = new();
+        }
+
+        private string CreateRequestJson()
+        {
+            var body = new RequestBody(
+                Text: this.Text,
+                Visibility: this.Visibility,
+                ReplyId: this.ReplyId?.Id,
+                RenoteId: this.RenoteId?.Id
+            );
+
+            return JsonUtils.SerializeJsonByDataContract(body);
+        }
+    }
+}
index 460a1a2..af84224 100644 (file)
@@ -30,6 +30,8 @@ namespace OpenTween.SocialProtocol.Misskey
 {
     public class MisskeyClient : ISocialProtocolClient
     {
+        public static int MaxNoteTextLength { get; } = 3_000;
+
         private readonly MisskeyAccount account;
         private readonly MisskeyPostFactory postFactory = new();
 
@@ -96,11 +98,29 @@ namespace OpenTween.SocialProtocol.Misskey
         public Task<PostClass[]> GetRelatedPosts(PostClass targetPost, bool firstLoad)
             => throw this.CreateException();
 
-        public Task<PostClass?> CreatePost(PostStatusParams postParams)
-            => throw this.CreateException();
+        public async Task<PostClass?> CreatePost(PostStatusParams postParams)
+        {
+            if (postParams.Text.StartsWith("D "))
+                throw this.CreateException(); // DM の送信は非対応
+
+            var request = new NoteCreateRequest
+            {
+                Text = postParams.Text,
+                ReplyId = postParams.InReplyTo is { } replyTo
+                    ? this.AssertMisskeyNoteId(replyTo.StatusId)
+                    : null,
+            };
+
+            var note = await request.Send(this.account.Connection)
+                .ConfigureAwait(false);
+
+            var post = this.CreatePostFromNote(note, firstLoad: false);
+
+            return post;
+        }
 
         public int GetTextLengthRemain(PostStatusParams postParams)
-            => 0;
+            => MaxNoteTextLength - postParams.Text.ToCodepoints().Count();
 
         public Task DeletePost(PostId postId)
             => throw this.CreateException();