From af099f796fb51fd3b9634b5bd04ed3d9e856e4da Mon Sep 17 00:00:00 2001 From: Kimura Youichi Date: Wed, 24 Jan 2024 11:40:49 +0900 Subject: [PATCH] =?utf8?q?TimelineTweet=E3=81=AE=E4=B8=AD=E8=BA=AB?= =?utf8?q?=E3=81=8C=E7=A9=BA=E3=81=A0=E3=81=A3=E3=81=9F=E5=A0=B4=E5=90=88?= =?utf8?q?=E3=81=AF=E7=84=A1=E8=A6=96=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- CHANGELOG.txt | 1 + OpenTween.Tests/Api/GraphQL/TimelineTweetTest.cs | 15 ++++++++++- .../Responses/TimelineTweet_EmptyTweet.json | 6 +++++ OpenTween/Api/GraphQL/TimelineResponse.cs | 2 +- OpenTween/Api/GraphQL/TimelineTweet.cs | 29 ++++++++++++++-------- 5 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 OpenTween.Tests/Resources/Responses/TimelineTweet_EmptyTweet.json diff --git a/CHANGELOG.txt b/CHANGELOG.txt index b2de0f81..944406f7 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -5,6 +5,7 @@ * FIX: Cookie使用時にツイート検索の言語指定が効かない不具合を修正 * FIX: ツイート検索のキーワードを後から変更すると検索結果が表示されない不具合を修正 * FIX: Cookie使用時にステータスバーにRecentタブのレートリミットが表示されない不具合を修正 + * FIX: 取得したツイートの中身が空だった場合のエラー処理を改善 ==== Ver 3.12.0(2024/01/20) * NEW: graphqlエンドポイントを使用したホームタイムラインの取得に対応 diff --git a/OpenTween.Tests/Api/GraphQL/TimelineTweetTest.cs b/OpenTween.Tests/Api/GraphQL/TimelineTweetTest.cs index f1958321..a4ccdac9 100644 --- a/OpenTween.Tests/Api/GraphQL/TimelineTweetTest.cs +++ b/OpenTween.Tests/Api/GraphQL/TimelineTweetTest.cs @@ -188,11 +188,24 @@ namespace OpenTween.Api.GraphQL var rootElm = this.LoadResponseDocument("TimelineTweet_TweetTombstone.json"); var timelineTweet = new TimelineTweet(rootElm); - Assert.True(timelineTweet.IsTombstone); + Assert.False(timelineTweet.IsAvailable); var ex = Assert.Throws( () => timelineTweet.ToTwitterStatus() ); Assert.Equal("This Post is from a suspended account. Learn more", ex.Message); } + + [Fact] + public void ToStatus_EmptyTweet_Test() + { + var rootElm = this.LoadResponseDocument("TimelineTweet_EmptyTweet.json"); + var timelineTweet = new TimelineTweet(rootElm); + + Assert.False(timelineTweet.IsAvailable); + var ex = Assert.Throws( + () => timelineTweet.ToTwitterStatus() + ); + Assert.Equal("Tweet is not available", ex.Message); + } } } diff --git a/OpenTween.Tests/Resources/Responses/TimelineTweet_EmptyTweet.json b/OpenTween.Tests/Resources/Responses/TimelineTweet_EmptyTweet.json new file mode 100644 index 00000000..70b98651 --- /dev/null +++ b/OpenTween.Tests/Resources/Responses/TimelineTweet_EmptyTweet.json @@ -0,0 +1,6 @@ +{ + "itemType": "TimelineTweet", + "__typename": "TimelineTweet", + "tweet_results": {}, + "tweetDisplayType": "Tweet" +} diff --git a/OpenTween/Api/GraphQL/TimelineResponse.cs b/OpenTween/Api/GraphQL/TimelineResponse.cs index 052ea610..a2729df0 100644 --- a/OpenTween/Api/GraphQL/TimelineResponse.cs +++ b/OpenTween/Api/GraphQL/TimelineResponse.cs @@ -34,7 +34,7 @@ namespace OpenTween.Api.GraphQL { public TwitterStatus[] ToTwitterStatuses() => this.Tweets - .Where(x => !x.IsTombstone) + .Where(x => x.IsAvailable) .Select(x => x.ToTwitterStatus()) .ToArray(); } diff --git a/OpenTween/Api/GraphQL/TimelineTweet.cs b/OpenTween/Api/GraphQL/TimelineTweet.cs index af7b1764..e8140341 100644 --- a/OpenTween/Api/GraphQL/TimelineTweet.cs +++ b/OpenTween/Api/GraphQL/TimelineTweet.cs @@ -23,6 +23,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -38,10 +39,10 @@ namespace OpenTween.Api.GraphQL public XElement Element { get; } - public bool IsTombstone - => this.tombstoneElm != null; + public bool IsAvailable + => this.resultElm != null && !this.IsTombstoneResult(this.resultElm); - private readonly XElement? tombstoneElm; + private readonly XElement? resultElm; public TimelineTweet(XElement element) { @@ -50,19 +51,22 @@ namespace OpenTween.Api.GraphQL throw new ArgumentException($"Invalid itemType: {typeName}", nameof(element)); this.Element = element; - this.tombstoneElm = this.TryGetTombstoneElm(); + this.resultElm = this.TryGetResultElm(); } - private XElement? TryGetTombstoneElm() - => this.Element.XPathSelectElement("tweet_results/result[__typename[text()='TweetTombstone']]"); + private XElement? TryGetResultElm() + => this.Element.XPathSelectElement("tweet_results/result"); + + private bool IsTombstoneResult([NotNullWhen(true)]XElement? resultElm) + => resultElm?.Element("__typename")?.Value == "TweetTombstone"; public TwitterStatus ToTwitterStatus() { - this.ThrowIfTweetIsTombstone(); + this.ThrowIfTweetIsNotAvailable(); try { - var resultElm = this.Element.Element("tweet_results")?.Element("result") ?? throw CreateParseError(); + var resultElm = this.resultElm ?? throw CreateParseError(); var status = TimelineTweet.ParseTweetUnion(resultElm); if (this.Element.Element("promotedMetadata") != null) @@ -78,12 +82,15 @@ namespace OpenTween.Api.GraphQL } } - public void ThrowIfTweetIsTombstone() + public void ThrowIfTweetIsNotAvailable() { - if (this.tombstoneElm == null) + if (this.IsAvailable) return; - var tombstoneText = this.tombstoneElm.XPathSelectElement("tombstone/text/text")?.Value; + string? tombstoneText = null; + if (this.IsTombstoneResult(this.resultElm)) + tombstoneText = this.resultElm.XPathSelectElement("tombstone/text/text")?.Value; + var message = tombstoneText ?? "Tweet is not available"; var json = JsonUtils.JsonXmlToString(this.Element); -- 2.11.0