From 5232e94e331faf2176bbee5de7cdff65b43e592d Mon Sep 17 00:00:00 2001 From: Kimura Youichi Date: Wed, 5 Jul 2023 00:54:53 +0900 Subject: [PATCH] =?UTF-8?q?graphql=E3=82=A8=E3=83=B3=E3=83=89=E3=83=9D?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=83=88=E3=82=92=E4=BD=BF=E7=94=A8=E3=81=97?= =?UTF-8?q?=E3=81=9F=E3=83=AA=E3=82=B9=E3=83=88=E3=81=AE=E3=82=BF=E3=82=A4?= =?UTF-8?q?=E3=83=A0=E3=83=A9=E3=82=A4=E3=83=B3=E5=8F=96=E5=BE=97=E3=81=AB?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ListLatestTweetsTimelineRequestTest.cs | 66 + .../Api/GraphQL/TimelineTweetTest.cs | 114 ++ OpenTween.Tests/OpenTween.Tests.csproj | 15 + ...ListLatestTweetsTimeline_Conversation.json | 1282 +++++++++++++++++ .../ListLatestTweetsTimeline_SimpleTweet.json | 179 +++ .../TimelineTweet_RetweetedTweet.json | 1227 ++++++++++++++++ .../Responses/TimelineTweet_SimpleTweet.json | 120 ++ .../TimelineTweet_TweetWithMedia.json | 530 +++++++ .../ListLatestTweetsTimelineRequest.cs | 90 ++ OpenTween/Api/GraphQL/TimelineTweet.cs | 143 ++ OpenTween/Resources/ChangeLog.txt | 1 + OpenTween/Twitter.cs | 13 +- 12 files changed, 3779 insertions(+), 1 deletion(-) create mode 100644 OpenTween.Tests/Api/GraphQL/ListLatestTweetsTimelineRequestTest.cs create mode 100644 OpenTween.Tests/Api/GraphQL/TimelineTweetTest.cs create mode 100644 OpenTween.Tests/Resources/Responses/ListLatestTweetsTimeline_Conversation.json create mode 100644 OpenTween.Tests/Resources/Responses/ListLatestTweetsTimeline_SimpleTweet.json create mode 100644 OpenTween.Tests/Resources/Responses/TimelineTweet_RetweetedTweet.json create mode 100644 OpenTween.Tests/Resources/Responses/TimelineTweet_SimpleTweet.json create mode 100644 OpenTween.Tests/Resources/Responses/TimelineTweet_TweetWithMedia.json create mode 100644 OpenTween/Api/GraphQL/ListLatestTweetsTimelineRequest.cs create mode 100644 OpenTween/Api/GraphQL/TimelineTweet.cs diff --git a/OpenTween.Tests/Api/GraphQL/ListLatestTweetsTimelineRequestTest.cs b/OpenTween.Tests/Api/GraphQL/ListLatestTweetsTimelineRequestTest.cs new file mode 100644 index 000000000..c53b27b97 --- /dev/null +++ b/OpenTween.Tests/Api/GraphQL/ListLatestTweetsTimelineRequestTest.cs @@ -0,0 +1,66 @@ +// OpenTween - Client of Twitter +// Copyright (c) 2023 kim_upsilon (@kim_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 , or write to +// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +// Boston, MA 02110-1301, USA. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Moq; +using OpenTween.Api.TwitterV2; +using OpenTween.Connection; +using Xunit; + +namespace OpenTween.Api.GraphQL +{ + public class ListLatestTweetsTimelineRequestTest + { + [Fact] + public async Task Send_Test() + { + using var responseStream = File.OpenRead("Resources/Responses/ListLatestTweetsTimeline_SimpleTweet.json"); + + var mock = new Mock(); + mock.Setup(x => + x.GetStreamAsync(It.IsAny(), It.IsAny>()) + ) + .Callback>((url, param) => + { + Assert.Equal(new("https://twitter.com/i/api/graphql/6ClPnsuzQJ1p7-g32GQw9Q/ListLatestTweetsTimeline"), url); + Assert.Equal(2, param.Count); + Assert.Equal("""{"listId":"1675863884757110790","count":20}""", param["variables"]); + Assert.True(param.ContainsKey("features")); + }) + .ReturnsAsync(responseStream); + + var request = new ListLatestTweetsTimelineRequest(listId: "1675863884757110790") + { + Count = 20, + }; + + var tweets = await request.Send(mock.Object).ConfigureAwait(false); + Assert.Single(tweets); + + mock.VerifyAll(); + } + } +} diff --git a/OpenTween.Tests/Api/GraphQL/TimelineTweetTest.cs b/OpenTween.Tests/Api/GraphQL/TimelineTweetTest.cs new file mode 100644 index 000000000..b16e97158 --- /dev/null +++ b/OpenTween.Tests/Api/GraphQL/TimelineTweetTest.cs @@ -0,0 +1,114 @@ +// OpenTween - Client of Twitter +// Copyright (c) 2023 kim_upsilon (@kim_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 , or write to +// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +// Boston, MA 02110-1301, USA. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Json; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Linq; +using OpenTween.Models; +using Xunit; + +namespace OpenTween.Api.GraphQL +{ + public class TimelineTweetTest + { + private XElement LoadResponseDocument(string filename) + { + using var stream = File.OpenRead($"Resources/Responses/{filename}"); + using var jsonReader = JsonReaderWriterFactory.CreateJsonReader(stream, XmlDictionaryReaderQuotas.Max); + return XElement.Load(jsonReader); + } + + private TabInformations CreateTabInfo() + { + var tabinfo = new TabInformations(); + tabinfo.AddDefaultTabs(); + return tabinfo; + } + + [Fact] + public void ExtractTimelineTweets_Single_Test() + { + var rootElm = this.LoadResponseDocument("ListLatestTweetsTimeline_SimpleTweet.json"); + var timelineTweets = TimelineTweet.ExtractTimelineTweets(rootElm); + Assert.Single(timelineTweets); + } + + [Fact] + public void ExtractTimelineTweets_Conversation_Test() + { + var rootElm = this.LoadResponseDocument("ListLatestTweetsTimeline_Conversation.json"); + var timelineTweets = TimelineTweet.ExtractTimelineTweets(rootElm); + Assert.Equal(3, timelineTweets.Length); + } + + [Fact] + public void ToStatus_WithTwitterPostFactory_SimpleTweet_Test() + { + var rootElm = this.LoadResponseDocument("TimelineTweet_SimpleTweet.json"); + var timelineTweet = new TimelineTweet(rootElm); + var status = timelineTweet.ToTwitterStatus(); + var postFactory = new TwitterPostFactory(this.CreateTabInfo()); + var post = postFactory.CreateFromStatus(status, selfUserId: 1L, new HashSet()); + + Assert.Equal("1613784711020826626", post.StatusId.Id); + Assert.Equal(40480664L, post.UserId); + } + + [Fact] + public void ToStatus_WithTwitterPostFactory_TweetWithMedia_Test() + { + var rootElm = this.LoadResponseDocument("TimelineTweet_TweetWithMedia.json"); + var timelineTweet = new TimelineTweet(rootElm); + var status = timelineTweet.ToTwitterStatus(); + var postFactory = new TwitterPostFactory(this.CreateTabInfo()); + var post = postFactory.CreateFromStatus(status, selfUserId: 1L, new HashSet()); + + Assert.Equal("1614587968567783424", post.StatusId.Id); + Assert.Equal(40480664L, post.UserId); + Assert.Equal(2, post.Media.Count); + Assert.Equal("https://pbs.twimg.com/media/FmgrJiEaAAEU42G.png", post.Media[0].Url); + Assert.Equal("OpenTweenで @opentween のツイート一覧を表示しているスクショ", post.Media[0].AltText); + Assert.Equal("https://pbs.twimg.com/media/FmgrJiXaMAEu873.jpg", post.Media[1].Url); + Assert.Equal("OpenTweenの新しい画像投稿画面を動かしている様子のスクショ", post.Media[1].AltText); + } + + [Fact] + public void ToStatus_WithTwitterPostFactory_RetweetedTweet_Test() + { + var rootElm = this.LoadResponseDocument("TimelineTweet_RetweetedTweet.json"); + var timelineTweet = new TimelineTweet(rootElm); + var status = timelineTweet.ToTwitterStatus(); + var postFactory = new TwitterPostFactory(this.CreateTabInfo()); + var post = postFactory.CreateFromStatus(status, selfUserId: 1L, new HashSet()); + + Assert.Equal("1617128268548964354", post.StatusId.Id); + Assert.Equal(40480664L, post.RetweetedByUserId); + Assert.Equal("1617126084138659840", post.RetweetedId!.Id); + Assert.Equal(514241801L, post.UserId); + } + } +} diff --git a/OpenTween.Tests/OpenTween.Tests.csproj b/OpenTween.Tests/OpenTween.Tests.csproj index a143b1727..f1722591e 100644 --- a/OpenTween.Tests/OpenTween.Tests.csproj +++ b/OpenTween.Tests/OpenTween.Tests.csproj @@ -52,5 +52,20 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + diff --git a/OpenTween.Tests/Resources/Responses/ListLatestTweetsTimeline_Conversation.json b/OpenTween.Tests/Resources/Responses/ListLatestTweetsTimeline_Conversation.json new file mode 100644 index 000000000..e5e844ca3 --- /dev/null +++ b/OpenTween.Tests/Resources/Responses/ListLatestTweetsTimeline_Conversation.json @@ -0,0 +1,1282 @@ +{ + "data": { + "list": { + "tweets_timeline": { + "timeline": { + "instructions": [ + { + "type": "TimelineAddEntries", + "entries": [ + { + "entryId": "list-conversation-1675866022877331462", + "sortIndex": "1675866022877331450", + "content": { + "entryType": "TimelineTimelineModule", + "__typename": "TimelineTimelineModule", + "items": [ + { + "entryId": "list-conversation-1675866022877331462-tweet-1616184396092178433", + "item": { + "itemContent": { + "itemType": "TimelineTweet", + "__typename": "TimelineTweet", + "tweet_results": { + "result": { + "__typename": "Tweet", + "rest_id": "1616184396092178433", + "core": { + "user_results": { + "result": { + "__typename": "User", + "id": "VXNlcjo0MDQ4MDY2NA==", + "rest_id": "40480664", + "affiliates_highlighted_label": {}, + "has_graduated_access": true, + "is_blue_verified": false, + "profile_image_shape": "Circle", + "legacy": { + "followed_by": true, + "following": true, + "can_dm": true, + "can_media_tag": true, + "created_at": "Sat May 16 15:20:01 +0000 2009", + "default_profile": false, + "default_profile_image": false, + "description": "OpenTween Project 言い出しっぺ", + "entities": { + "description": { + "urls": [] + }, + "url": { + "urls": [ + { + "display_url": "m.upsilo.net/@upsilon", + "expanded_url": "https://m.upsilo.net/@upsilon", + "url": "https://t.co/vNMmyHHOQD", + "indices": [ + 0, + 23 + ] + } + ] + } + }, + "fast_followers_count": 0, + "favourites_count": 216272, + "followers_count": 1301, + "friends_count": 917, + "has_custom_timelines": false, + "is_translator": false, + "listed_count": 92, + "location": "Funabashi, Chiba, Japan", + "media_count": 1040, + "name": "upsilon", + "normal_followers_count": 1301, + "pinned_tweet_ids_str": [], + "possibly_sensitive": false, + "profile_banner_url": "https://pbs.twimg.com/profile_banners/40480664/1349188016", + "profile_image_url_https": "https://pbs.twimg.com/profile_images/719076434/____normal.png", + "profile_interstitial_type": "", + "screen_name": "kim_upsilon", + "statuses_count": 10096, + "translator_type": "regular", + "url": "https://t.co/vNMmyHHOQD", + "verified": false, + "want_retweets": true, + "withheld_in_countries": [] + } + } + } + }, + "edit_control": { + "edit_tweet_ids": [ + "1616184396092178433" + ], + "editable_until_msecs": "1674165161000", + "is_edit_eligible": false, + "edits_remaining": "5" + }, + "edit_perspective": { + "favorited": false, + "retweeted": false + }, + "is_translatable": true, + "views": { + "count": "1244", + "state": "EnabledWithCount" + }, + "source": "OpenTween (dev)", + "quoted_status_result": { + "result": { + "__typename": "Tweet", + "rest_id": "1616182499641819136", + "core": { + "user_results": { + "result": { + "__typename": "User", + "id": "VXNlcjo1MTQyNDE4MDE=", + "rest_id": "514241801", + "affiliates_highlighted_label": {}, + "has_graduated_access": false, + "is_blue_verified": false, + "profile_image_shape": "Circle", + "legacy": { + "can_dm": true, + "can_media_tag": false, + "created_at": "Sun Mar 04 11:33:45 +0000 2012", + "default_profile": false, + "default_profile_image": false, + "description": "Windows 用 Twitter クライアント OpenTween のアカウントです。", + "entities": { + "description": { + "urls": [] + }, + "url": { + "urls": [ + { + "display_url": "opentween.org", + "expanded_url": "https://www.opentween.org/", + "url": "https://t.co/An6OJeC28u", + "indices": [ + 0, + 23 + ] + } + ] + } + }, + "fast_followers_count": 0, + "favourites_count": 0, + "followers_count": 301, + "friends_count": 1, + "has_custom_timelines": false, + "is_translator": false, + "listed_count": 14, + "location": "", + "media_count": 0, + "name": "OpenTween", + "normal_followers_count": 301, + "pinned_tweet_ids_str": [ + "1617124615347908609" + ], + "possibly_sensitive": false, + "profile_image_url_https": "https://pbs.twimg.com/profile_images/661168792488153088/-UAFci6G_normal.png", + "profile_interstitial_type": "", + "screen_name": "opentween", + "statuses_count": 31, + "translator_type": "none", + "url": "https://t.co/An6OJeC28u", + "verified": false, + "want_retweets": false, + "withheld_in_countries": [] + } + } + } + }, + "card": { + "rest_id": "https://t.co/LvEPrVETIQ", + "legacy": { + "binding_values": [ + { + "key": "photo_image_full_size_large", + "value": { + "image_value": { + "height": 419, + "width": 800, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=jpg&name=800x419" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image", + "value": { + "image_value": { + "height": 200, + "width": 400, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=jpg&name=400x400" + }, + "type": "IMAGE" + } + }, + { + "key": "description", + "value": { + "string_value": "==== Ver 3.2.0(2023/01/20) NEW: 複数枚の画像を添付する際にリスト上で画像を確認できるようになりました CHG: アカウント追加時の認可関連のエラーメッセージがより詳細になるように変更", + "type": "STRING" + } + }, + { + "key": "domain", + "value": { + "string_value": "github.com", + "type": "STRING" + } + }, + { + "key": "thumbnail_image_large", + "value": { + "image_value": { + "height": 300, + "width": 600, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=jpg&name=600x600" + }, + "type": "IMAGE" + } + }, + { + "key": "summary_photo_image_small", + "value": { + "image_value": { + "height": 202, + "width": 386, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=jpg&name=386x202" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image_original", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=jpg&name=orig" + }, + "type": "IMAGE" + } + }, + { + "key": "site", + "value": { + "scribe_key": "publisher_id", + "type": "USER", + "user_value": { + "id_str": "13334762", + "path": [] + } + } + }, + { + "key": "photo_image_full_size_small", + "value": { + "image_value": { + "height": 202, + "width": 386, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=jpg&name=386x202" + }, + "type": "IMAGE" + } + }, + { + "key": "summary_photo_image_large", + "value": { + "image_value": { + "height": 419, + "width": 800, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=jpg&name=800x419" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image_small", + "value": { + "image_value": { + "height": 72, + "width": 144, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=jpg&name=144x144" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image_x_large", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=png&name=2048x2048_2_exp" + }, + "type": "IMAGE" + } + }, + { + "key": "photo_image_full_size_original", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=jpg&name=orig" + }, + "type": "IMAGE" + } + }, + { + "key": "photo_image_full_size_alt_text", + "value": { + "string_value": "==== Ver 3.2.0(2023/01/20) NEW: 複数枚の画像を添付する際にリスト上で画像を確認できるようになりました CHG: アカウント追加時の認可関連のエラーメッセージがより詳細になるように変更", + "type": "STRING" + } + }, + { + "key": "vanity_url", + "value": { + "scribe_key": "vanity_url", + "string_value": "github.com", + "type": "STRING" + } + }, + { + "key": "photo_image_full_size", + "value": { + "image_value": { + "height": 314, + "width": 600, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=jpg&name=600x314" + }, + "type": "IMAGE" + } + }, + { + "key": "summary_photo_image_alt_text", + "value": { + "string_value": "==== Ver 3.2.0(2023/01/20) NEW: 複数枚の画像を添付する際にリスト上で画像を確認できるようになりました CHG: アカウント追加時の認可関連のエラーメッセージがより詳細になるように変更", + "type": "STRING" + } + }, + { + "key": "thumbnail_image_color", + "value": { + "image_color_value": { + "palette": [ + { + "rgb": { + "blue": 255, + "green": 255, + "red": 255 + }, + "percentage": 91.56 + }, + { + "rgb": { + "blue": 1, + "green": 135, + "red": 23 + }, + "percentage": 3.12 + }, + { + "rgb": { + "blue": 105, + "green": 184, + "red": 118 + }, + "percentage": 1.56 + }, + { + "rgb": { + "blue": 40, + "green": 55, + "red": 50 + }, + "percentage": 0.98 + }, + { + "rgb": { + "blue": 152, + "green": 247, + "red": 255 + }, + "percentage": 0.37 + } + ] + }, + "type": "IMAGE_COLOR" + } + }, + { + "key": "title", + "value": { + "string_value": "Release OpenTween v3.2.0 · opentween/OpenTween", + "type": "STRING" + } + }, + { + "key": "summary_photo_image_color", + "value": { + "image_color_value": { + "palette": [ + { + "rgb": { + "blue": 255, + "green": 255, + "red": 255 + }, + "percentage": 91.56 + }, + { + "rgb": { + "blue": 1, + "green": 135, + "red": 23 + }, + "percentage": 3.12 + }, + { + "rgb": { + "blue": 105, + "green": 184, + "red": 118 + }, + "percentage": 1.56 + }, + { + "rgb": { + "blue": 40, + "green": 55, + "red": 50 + }, + "percentage": 0.98 + }, + { + "rgb": { + "blue": 152, + "green": 247, + "red": 255 + }, + "percentage": 0.37 + } + ] + }, + "type": "IMAGE_COLOR" + } + }, + { + "key": "summary_photo_image_x_large", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=png&name=2048x2048_2_exp" + }, + "type": "IMAGE" + } + }, + { + "key": "summary_photo_image", + "value": { + "image_value": { + "height": 314, + "width": 600, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=jpg&name=600x314" + }, + "type": "IMAGE" + } + }, + { + "key": "photo_image_full_size_color", + "value": { + "image_color_value": { + "palette": [ + { + "rgb": { + "blue": 255, + "green": 255, + "red": 255 + }, + "percentage": 91.56 + }, + { + "rgb": { + "blue": 1, + "green": 135, + "red": 23 + }, + "percentage": 3.12 + }, + { + "rgb": { + "blue": 105, + "green": 184, + "red": 118 + }, + "percentage": 1.56 + }, + { + "rgb": { + "blue": 40, + "green": 55, + "red": 50 + }, + "percentage": 0.98 + }, + { + "rgb": { + "blue": 152, + "green": 247, + "red": 255 + }, + "percentage": 0.37 + } + ] + }, + "type": "IMAGE_COLOR" + } + }, + { + "key": "photo_image_full_size_x_large", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=png&name=2048x2048_2_exp" + }, + "type": "IMAGE" + } + }, + { + "key": "card_url", + "value": { + "scribe_key": "card_url", + "string_value": "https://t.co/LvEPrVETIQ", + "type": "STRING" + } + }, + { + "key": "summary_photo_image_original", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1674655953424207872/tp2h8UWj?format=jpg&name=orig" + }, + "type": "IMAGE" + } + } + ], + "card_platform": { + "platform": { + "audience": { + "name": "production" + }, + "device": { + "name": "Swift", + "version": "12" + } + } + }, + "name": "summary_large_image", + "url": "https://t.co/LvEPrVETIQ", + "user_refs_results": [ + { + "result": { + "__typename": "User", + "id": "VXNlcjoxMzMzNDc2Mg==", + "rest_id": "13334762", + "affiliates_highlighted_label": {}, + "has_graduated_access": true, + "is_blue_verified": true, + "profile_image_shape": "Square", + "legacy": { + "can_dm": false, + "can_media_tag": true, + "created_at": "Mon Feb 11 04:41:50 +0000 2008", + "default_profile": false, + "default_profile_image": false, + "description": "The AI-powered developer platform to build, scale, and deliver secure software.", + "entities": { + "description": { + "urls": [] + }, + "url": { + "urls": [ + { + "display_url": "github.com", + "expanded_url": "http://github.com", + "url": "https://t.co/bbJgfyzcJR", + "indices": [ + 0, + 23 + ] + } + ] + } + }, + "fast_followers_count": 0, + "favourites_count": 8055, + "followers_count": 2511440, + "friends_count": 334, + "has_custom_timelines": true, + "is_translator": false, + "listed_count": 18239, + "location": "San Francisco, CA", + "media_count": 2063, + "name": "GitHub", + "normal_followers_count": 2511440, + "pinned_tweet_ids_str": [], + "possibly_sensitive": false, + "profile_banner_url": "https://pbs.twimg.com/profile_banners/13334762/1680541755", + "profile_image_url_https": "https://pbs.twimg.com/profile_images/1633247750010830848/8zfRrYjA_normal.png", + "profile_interstitial_type": "", + "screen_name": "github", + "statuses_count": 8343, + "translator_type": "none", + "url": "https://t.co/bbJgfyzcJR", + "verified": false, + "verified_type": "Business", + "want_retweets": false, + "withheld_in_countries": [] + } + } + } + ] + } + }, + "unified_card": { + "card_fetch_state": "NoCard" + }, + "edit_control": { + "edit_tweet_ids": [ + "1616182499641819136" + ], + "editable_until_msecs": "1674164709000", + "is_edit_eligible": true, + "edits_remaining": "5" + }, + "edit_perspective": { + "favorited": false, + "retweeted": false + }, + "is_translatable": true, + "views": { + "count": "7527", + "state": "EnabledWithCount" + }, + "source": "OpenTween", + "legacy": { + "bookmark_count": 1, + "bookmarked": false, + "created_at": "Thu Jan 19 21:15:09 +0000 2023", + "conversation_id_str": "1616182499641819136", + "display_text_range": [ + 0, + 74 + ], + "entities": { + "user_mentions": [], + "urls": [ + { + "display_url": "osdn.net/projects/opent…", + "expanded_url": "https://osdn.net/projects/opentween/releases/78187", + "url": "https://t.co/8lcm1hhdfS", + "indices": [ + 27, + 50 + ] + }, + { + "display_url": "github.com/opentween/Open…", + "expanded_url": "https://github.com/opentween/OpenTween/releases/tag/OpenTween_v3.2.0", + "url": "https://t.co/LvEPrVETIQ", + "indices": [ + 51, + 74 + ] + } + ], + "hashtags": [ + { + "indices": [ + 0, + 10 + ], + "text": "OpenTween" + } + ], + "symbols": [] + }, + "favorite_count": 20, + "favorited": false, + "full_text": "#OpenTween v3.2.0 リリースしました\nhttps://t.co/8lcm1hhdfS\nhttps://t.co/LvEPrVETIQ", + "is_quote_status": false, + "lang": "ja", + "possibly_sensitive": false, + "possibly_sensitive_editable": true, + "quote_count": 3, + "reply_count": 3, + "retweet_count": 22, + "retweeted": false, + "user_id_str": "514241801", + "id_str": "1616182499641819136" + } + } + }, + "legacy": { + "bookmark_count": 0, + "bookmarked": false, + "created_at": "Thu Jan 19 21:22:41 +0000 2023", + "conversation_id_str": "1616184396092178433", + "display_text_range": [ + 0, + 60 + ], + "entities": { + "user_mentions": [], + "urls": [ + { + "display_url": "twitter.com/opentween/stat…", + "expanded_url": "https://twitter.com/opentween/status/1616182499641819136", + "url": "https://t.co/bzvF5kDXeE", + "indices": [ + 37, + 60 + ] + } + ], + "hashtags": [ + { + "indices": [ + 26, + 36 + ], + "text": "OpenTween" + } + ], + "symbols": [] + }, + "favorite_count": 5, + "favorited": false, + "full_text": "画像を添付する時の画面が見やすくなりました(主観) #OpenTween\nhttps://t.co/bzvF5kDXeE", + "is_quote_status": true, + "lang": "ja", + "possibly_sensitive": false, + "possibly_sensitive_editable": true, + "quote_count": 0, + "quoted_status_id_str": "1616182499641819136", + "quoted_status_permalink": { + "url": "https://t.co/bzvF5kDXeE", + "expanded": "https://twitter.com/opentween/status/1616182499641819136", + "display": "twitter.com/opentween/stat…" + }, + "reply_count": 1, + "retweet_count": 1, + "retweeted": false, + "user_id_str": "40480664", + "id_str": "1616184396092178433" + } + } + }, + "tweetDisplayType": "Tweet" + }, + "clientEventInfo": { + "component": "suggest_organic_list_tweet", + "element": "tweet", + "details": { + "timelinesDetails": { + "injectionType": "OrganicListTweet" + } + } + } + } + }, + { + "entryId": "list-conversation-1675866022877331462-tweet-1616185165583351809", + "item": { + "itemContent": { + "itemType": "TimelineTweet", + "__typename": "TimelineTweet", + "tweet_results": { + "result": { + "__typename": "Tweet", + "rest_id": "1616185165583351809", + "core": { + "user_results": { + "result": { + "__typename": "User", + "id": "VXNlcjo0MDQ4MDY2NA==", + "rest_id": "40480664", + "affiliates_highlighted_label": {}, + "has_graduated_access": true, + "is_blue_verified": false, + "profile_image_shape": "Circle", + "legacy": { + "followed_by": true, + "following": true, + "can_dm": true, + "can_media_tag": true, + "created_at": "Sat May 16 15:20:01 +0000 2009", + "default_profile": false, + "default_profile_image": false, + "description": "OpenTween Project 言い出しっぺ", + "entities": { + "description": { + "urls": [] + }, + "url": { + "urls": [ + { + "display_url": "m.upsilo.net/@upsilon", + "expanded_url": "https://m.upsilo.net/@upsilon", + "url": "https://t.co/vNMmyHHOQD", + "indices": [ + 0, + 23 + ] + } + ] + } + }, + "fast_followers_count": 0, + "favourites_count": 216272, + "followers_count": 1301, + "friends_count": 917, + "has_custom_timelines": false, + "is_translator": false, + "listed_count": 92, + "location": "Funabashi, Chiba, Japan", + "media_count": 1040, + "name": "upsilon", + "normal_followers_count": 1301, + "pinned_tweet_ids_str": [], + "possibly_sensitive": false, + "profile_banner_url": "https://pbs.twimg.com/profile_banners/40480664/1349188016", + "profile_image_url_https": "https://pbs.twimg.com/profile_images/719076434/____normal.png", + "profile_interstitial_type": "", + "screen_name": "kim_upsilon", + "statuses_count": 10096, + "translator_type": "regular", + "url": "https://t.co/vNMmyHHOQD", + "verified": false, + "want_retweets": true, + "withheld_in_countries": [] + } + } + } + }, + "edit_control": { + "edit_tweet_ids": [ + "1616185165583351809" + ], + "editable_until_msecs": "1674165345000", + "is_edit_eligible": false, + "edits_remaining": "5" + }, + "edit_perspective": { + "favorited": false, + "retweeted": false + }, + "is_translatable": true, + "views": { + "count": "653", + "state": "EnabledWithCount" + }, + "source": "OpenTween (dev)", + "legacy": { + "bookmark_count": 0, + "bookmarked": false, + "created_at": "Thu Jan 19 21:25:45 +0000 2023", + "conversation_id_str": "1616184396092178433", + "display_text_range": [ + 0, + 47 + ], + "entities": { + "user_mentions": [], + "urls": [], + "hashtags": [], + "symbols": [] + }, + "favorite_count": 0, + "favorited": false, + "full_text": "あとで細かい使い勝手の調整はするつもり。画像の順番を入れ替えたりとか、途中の画像を消したりとか", + "in_reply_to_screen_name": "kim_upsilon", + "in_reply_to_status_id_str": "1616184396092178433", + "in_reply_to_user_id_str": "40480664", + "is_quote_status": false, + "lang": "ja", + "quote_count": 0, + "reply_count": 1, + "retweet_count": 0, + "retweeted": false, + "user_id_str": "40480664", + "id_str": "1616185165583351809" + } + } + }, + "tweetDisplayType": "Tweet" + }, + "clientEventInfo": { + "component": "suggest_organic_list_tweet", + "element": "tweet", + "details": { + "timelinesDetails": { + "injectionType": "OrganicListTweet" + } + } + } + } + }, + { + "entryId": "list-conversation-1675866022877331462-tweet-1616193114699628545", + "item": { + "itemContent": { + "itemType": "TimelineTweet", + "__typename": "TimelineTweet", + "tweet_results": { + "result": { + "__typename": "Tweet", + "rest_id": "1616193114699628545", + "core": { + "user_results": { + "result": { + "__typename": "User", + "id": "VXNlcjo0MDQ4MDY2NA==", + "rest_id": "40480664", + "affiliates_highlighted_label": {}, + "has_graduated_access": true, + "is_blue_verified": false, + "profile_image_shape": "Circle", + "legacy": { + "followed_by": true, + "following": true, + "can_dm": true, + "can_media_tag": true, + "created_at": "Sat May 16 15:20:01 +0000 2009", + "default_profile": false, + "default_profile_image": false, + "description": "OpenTween Project 言い出しっぺ", + "entities": { + "description": { + "urls": [] + }, + "url": { + "urls": [ + { + "display_url": "m.upsilo.net/@upsilon", + "expanded_url": "https://m.upsilo.net/@upsilon", + "url": "https://t.co/vNMmyHHOQD", + "indices": [ + 0, + 23 + ] + } + ] + } + }, + "fast_followers_count": 0, + "favourites_count": 216272, + "followers_count": 1301, + "friends_count": 917, + "has_custom_timelines": false, + "is_translator": false, + "listed_count": 92, + "location": "Funabashi, Chiba, Japan", + "media_count": 1040, + "name": "upsilon", + "normal_followers_count": 1301, + "pinned_tweet_ids_str": [], + "possibly_sensitive": false, + "profile_banner_url": "https://pbs.twimg.com/profile_banners/40480664/1349188016", + "profile_image_url_https": "https://pbs.twimg.com/profile_images/719076434/____normal.png", + "profile_interstitial_type": "", + "screen_name": "kim_upsilon", + "statuses_count": 10096, + "translator_type": "regular", + "url": "https://t.co/vNMmyHHOQD", + "verified": false, + "want_retweets": true, + "withheld_in_countries": [] + } + } + } + }, + "card": { + "rest_id": "https://t.co/p8rFeE4bV8", + "legacy": { + "binding_values": [ + { + "key": "thumbnail_image", + "value": { + "image_value": { + "height": 144, + "width": 144, + "url": "https://pbs.twimg.com/card_img/1675000140871143425/jnI1-BdH?format=jpg&name=144x144_2" + }, + "type": "IMAGE" + } + }, + { + "key": "domain", + "value": { + "string_value": "github.com", + "type": "STRING" + } + }, + { + "key": "thumbnail_image_large", + "value": { + "image_value": { + "height": 420, + "width": 420, + "url": "https://pbs.twimg.com/card_img/1675000140871143425/jnI1-BdH?format=jpg&name=420x420_2" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image_original", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675000140871143425/jnI1-BdH?format=jpg&name=orig" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image_small", + "value": { + "image_value": { + "height": 100, + "width": 100, + "url": "https://pbs.twimg.com/card_img/1675000140871143425/jnI1-BdH?format=jpg&name=100x100_2" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image_x_large", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675000140871143425/jnI1-BdH?format=png&name=2048x2048_2_exp" + }, + "type": "IMAGE" + } + }, + { + "key": "vanity_url", + "value": { + "scribe_key": "vanity_url", + "string_value": "github.com", + "type": "STRING" + } + }, + { + "key": "thumbnail_image_color", + "value": { + "image_color_value": { + "palette": [ + { + "rgb": { + "blue": 255, + "green": 255, + "red": 255 + }, + "percentage": 88.31 + }, + { + "rgb": { + "blue": 124, + "green": 119, + "red": 115 + }, + "percentage": 6.63 + }, + { + "rgb": { + "blue": 1, + "green": 135, + "red": 23 + }, + "percentage": 3.15 + }, + { + "rgb": { + "blue": 105, + "green": 184, + "red": 118 + }, + "percentage": 1.71 + }, + { + "rgb": { + "blue": 211, + "green": 208, + "red": 243 + }, + "percentage": 0.15 + } + ] + }, + "type": "IMAGE_COLOR" + } + }, + { + "key": "title", + "value": { + "string_value": "添付画像に同一の画像を続けて追加すると表示中の画像が破棄される不具合を修正 by upsilon · Pull Request #189 · opentween/OpenTween", + "type": "STRING" + } + }, + { + "key": "card_url", + "value": { + "scribe_key": "card_url", + "string_value": "https://t.co/p8rFeE4bV8", + "type": "STRING" + } + } + ], + "card_platform": { + "platform": { + "audience": { + "name": "production" + }, + "device": { + "name": "Swift", + "version": "12" + } + } + }, + "name": "summary", + "url": "https://t.co/p8rFeE4bV8", + "user_refs_results": [] + } + }, + "unified_card": { + "card_fetch_state": "NoCard" + }, + "edit_control": { + "edit_tweet_ids": [ + "1616193114699628545" + ], + "editable_until_msecs": "1674167240000", + "is_edit_eligible": false, + "edits_remaining": "5" + }, + "edit_perspective": { + "favorited": false, + "retweeted": false + }, + "is_translatable": true, + "views": { + "count": "924", + "state": "EnabledWithCount" + }, + "source": "OpenTween (dev)", + "legacy": { + "bookmark_count": 0, + "bookmarked": false, + "created_at": "Thu Jan 19 21:57:20 +0000 2023", + "conversation_id_str": "1616184396092178433", + "display_text_range": [ + 0, + 144 + ], + "entities": { + "user_mentions": [], + "urls": [ + { + "display_url": "github.com/opentween/Open…", + "expanded_url": "https://github.com/opentween/OpenTween/pull/189", + "url": "https://t.co/p8rFeE4bV8", + "indices": [ + 121, + 144 + ] + } + ], + "hashtags": [], + "symbols": [] + }, + "favorite_count": 12, + "favorited": false, + "full_text": "リリースした直後にデバッグ能力が500倍になるのやめたい\n\n添付画像に同一の画像を続けて追加すると表示中の画像が破棄される不具合を修正 by upsilon · Pull Request #189 · opentween/OpenTween https://t.co/p8rFeE4bV8", + "in_reply_to_screen_name": "kim_upsilon", + "in_reply_to_status_id_str": "1616185165583351809", + "in_reply_to_user_id_str": "40480664", + "is_quote_status": false, + "lang": "ja", + "possibly_sensitive": false, + "possibly_sensitive_editable": true, + "quote_count": 0, + "reply_count": 0, + "retweet_count": 1, + "retweeted": false, + "user_id_str": "40480664", + "id_str": "1616193114699628545" + } + } + }, + "tweetDisplayType": "Tweet" + }, + "clientEventInfo": { + "component": "suggest_organic_list_tweet", + "element": "tweet", + "details": { + "timelinesDetails": { + "injectionType": "OrganicListTweet" + } + } + } + } + } + ], + "metadata": { + "conversationMetadata": { + "allTweetIds": [ + "1616184396092178433", + "1616185165583351809", + "1616193114699628545" + ], + "enableDeduplication": true + } + }, + "displayType": "VerticalConversation", + "clientEventInfo": { + "component": "suggest_organic_list_tweet", + "details": { + "timelinesDetails": { + "injectionType": "OrganicListTweet" + } + } + } + } + }, + { + "entryId": "cursor-top-1675866022877331457", + "sortIndex": "1675866022877331457", + "content": { + "entryType": "TimelineTimelineCursor", + "__typename": "TimelineTimelineCursor", + "value": "DAABCgABF0HfRMjAJxEKAAIWes8rE1oQAAgAAwAAAAEAAA", + "cursorType": "Top" + } + }, + { + "entryId": "cursor-bottom-1675866022877331382", + "sortIndex": "1675866022877331382", + "content": { + "entryType": "TimelineTimelineCursor", + "__typename": "TimelineTimelineCursor", + "value": "DAABCgABF0HfRMi__7QKAAIVAxUYmFWQAwgAAwAAAAIAAA", + "cursorType": "Bottom" + } + } + ] + } + ], + "metadata": { + "scribeConfig": { + "page": "list_tweets" + } + } + } + } + } + } +} diff --git a/OpenTween.Tests/Resources/Responses/ListLatestTweetsTimeline_SimpleTweet.json b/OpenTween.Tests/Resources/Responses/ListLatestTweetsTimeline_SimpleTweet.json new file mode 100644 index 000000000..58bdd2804 --- /dev/null +++ b/OpenTween.Tests/Resources/Responses/ListLatestTweetsTimeline_SimpleTweet.json @@ -0,0 +1,179 @@ +{ + "data": { + "list": { + "tweets_timeline": { + "timeline": { + "instructions": [ + { + "type": "TimelineAddEntries", + "entries": [ + { + "entryId": "tweet-1613784711020826626", + "sortIndex": "1675866022877331438", + "content": { + "entryType": "TimelineTimelineItem", + "__typename": "TimelineTimelineItem", + "itemContent": { + "itemType": "TimelineTweet", + "__typename": "TimelineTweet", + "tweet_results": { + "result": { + "__typename": "Tweet", + "rest_id": "1613784711020826626", + "core": { + "user_results": { + "result": { + "__typename": "User", + "id": "VXNlcjo0MDQ4MDY2NA==", + "rest_id": "40480664", + "affiliates_highlighted_label": {}, + "has_graduated_access": true, + "is_blue_verified": false, + "profile_image_shape": "Circle", + "legacy": { + "followed_by": true, + "following": true, + "can_dm": true, + "can_media_tag": true, + "created_at": "Sat May 16 15:20:01 +0000 2009", + "default_profile": false, + "default_profile_image": false, + "description": "OpenTween Project 言い出しっぺ", + "entities": { + "description": { + "urls": [] + }, + "url": { + "urls": [ + { + "display_url": "m.upsilo.net/@upsilon", + "expanded_url": "https://m.upsilo.net/@upsilon", + "url": "https://t.co/vNMmyHHOQD", + "indices": [ + 0, + 23 + ] + } + ] + } + }, + "fast_followers_count": 0, + "favourites_count": 216272, + "followers_count": 1301, + "friends_count": 917, + "has_custom_timelines": false, + "is_translator": false, + "listed_count": 92, + "location": "Funabashi, Chiba, Japan", + "media_count": 1040, + "name": "upsilon", + "normal_followers_count": 1301, + "pinned_tweet_ids_str": [], + "possibly_sensitive": false, + "profile_banner_url": "https://pbs.twimg.com/profile_banners/40480664/1349188016", + "profile_image_url_https": "https://pbs.twimg.com/profile_images/719076434/____normal.png", + "profile_interstitial_type": "", + "screen_name": "kim_upsilon", + "statuses_count": 10096, + "translator_type": "regular", + "url": "https://t.co/vNMmyHHOQD", + "verified": false, + "want_retweets": true, + "withheld_in_countries": [] + } + } + } + }, + "edit_control": { + "edit_tweet_ids": [ + "1613784711020826626" + ], + "editable_until_msecs": "1673593032000", + "is_edit_eligible": true, + "edits_remaining": "5" + }, + "edit_perspective": { + "favorited": false, + "retweeted": false + }, + "is_translatable": true, + "views": { + "count": "403", + "state": "EnabledWithCount" + }, + "source": "OpenTween (dev)", + "legacy": { + "bookmark_count": 1, + "bookmarked": false, + "created_at": "Fri Jan 13 06:27:12 +0000 2023", + "conversation_id_str": "1613784711020826626", + "display_text_range": [ + 0, + 20 + ], + "entities": { + "user_mentions": [], + "urls": [], + "hashtags": [], + "symbols": [] + }, + "favorite_count": 6, + "favorited": false, + "full_text": "この数年おきに来るAPI凍結騒動は何なの", + "is_quote_status": false, + "lang": "ja", + "quote_count": 0, + "reply_count": 0, + "retweet_count": 0, + "retweeted": false, + "user_id_str": "40480664", + "id_str": "1613784711020826626" + } + } + }, + "tweetDisplayType": "Tweet" + }, + "clientEventInfo": { + "component": "suggest_organic_list_tweet", + "element": "tweet", + "details": { + "timelinesDetails": { + "injectionType": "OrganicListTweet" + } + } + } + } + }, + { + "entryId": "cursor-top-1675866022877331457", + "sortIndex": "1675866022877331457", + "content": { + "entryType": "TimelineTimelineCursor", + "__typename": "TimelineTimelineCursor", + "value": "DAABCgABF0HfRMjAJxEKAAIWes8rE1oQAAgAAwAAAAEAAA", + "cursorType": "Top" + } + }, + { + "entryId": "cursor-bottom-1675866022877331382", + "sortIndex": "1675866022877331382", + "content": { + "entryType": "TimelineTimelineCursor", + "__typename": "TimelineTimelineCursor", + "value": "DAABCgABF0HfRMi__7QKAAIVAxUYmFWQAwgAAwAAAAIAAA", + "cursorType": "Bottom" + } + } + ] + } + ], + "metadata": { + "scribeConfig": { + "page": "list_tweets" + } + } + } + } + } + } +} diff --git a/OpenTween.Tests/Resources/Responses/TimelineTweet_RetweetedTweet.json b/OpenTween.Tests/Resources/Responses/TimelineTweet_RetweetedTweet.json new file mode 100644 index 000000000..6204d25e8 --- /dev/null +++ b/OpenTween.Tests/Resources/Responses/TimelineTweet_RetweetedTweet.json @@ -0,0 +1,1227 @@ +{ + "itemType": "TimelineTweet", + "__typename": "TimelineTweet", + "tweet_results": { + "result": { + "__typename": "Tweet", + "rest_id": "1617128268548964354", + "core": { + "user_results": { + "result": { + "__typename": "User", + "id": "VXNlcjo0MDQ4MDY2NA==", + "rest_id": "40480664", + "affiliates_highlighted_label": {}, + "has_graduated_access": true, + "is_blue_verified": false, + "profile_image_shape": "Circle", + "legacy": { + "followed_by": true, + "following": true, + "can_dm": true, + "can_media_tag": true, + "created_at": "Sat May 16 15:20:01 +0000 2009", + "default_profile": false, + "default_profile_image": false, + "description": "OpenTween Project 言い出しっぺ", + "entities": { + "description": { + "urls": [] + }, + "url": { + "urls": [ + { + "display_url": "m.upsilo.net/@upsilon", + "expanded_url": "https://m.upsilo.net/@upsilon", + "url": "https://t.co/vNMmyHHOQD", + "indices": [ + 0, + 23 + ] + } + ] + } + }, + "fast_followers_count": 0, + "favourites_count": 216272, + "followers_count": 1301, + "friends_count": 917, + "has_custom_timelines": false, + "is_translator": false, + "listed_count": 92, + "location": "Funabashi, Chiba, Japan", + "media_count": 1040, + "name": "upsilon", + "normal_followers_count": 1301, + "pinned_tweet_ids_str": [], + "possibly_sensitive": false, + "profile_banner_url": "https://pbs.twimg.com/profile_banners/40480664/1349188016", + "profile_image_url_https": "https://pbs.twimg.com/profile_images/719076434/____normal.png", + "profile_interstitial_type": "", + "screen_name": "kim_upsilon", + "statuses_count": 10096, + "translator_type": "regular", + "url": "https://t.co/vNMmyHHOQD", + "verified": false, + "want_retweets": true, + "withheld_in_countries": [] + } + } + } + }, + "card": { + "rest_id": "https://t.co/HPLtWszxIr", + "legacy": { + "binding_values": [ + { + "key": "photo_image_full_size_large", + "value": { + "image_value": { + "height": 419, + "width": 800, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=800x419" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image", + "value": { + "image_value": { + "height": 200, + "width": 400, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=400x400" + }, + "type": "IMAGE" + } + }, + { + "key": "description", + "value": { + "string_value": "==== Ver 3.3.0(2023/01/22) NEW: アカウント追加時にAPIキーを指定可能になりました CHG: API v2 の使用を設定状態に関わらず無効化しました FIX: 同一の画像を複数枚添付する時にプレビュー画像の表示がエラーになる不具合を修正", + "type": "STRING" + } + }, + { + "key": "domain", + "value": { + "string_value": "github.com", + "type": "STRING" + } + }, + { + "key": "thumbnail_image_large", + "value": { + "image_value": { + "height": 300, + "width": 600, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=600x600" + }, + "type": "IMAGE" + } + }, + { + "key": "summary_photo_image_small", + "value": { + "image_value": { + "height": 202, + "width": 386, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=386x202" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image_original", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=orig" + }, + "type": "IMAGE" + } + }, + { + "key": "site", + "value": { + "scribe_key": "publisher_id", + "type": "USER", + "user_value": { + "id_str": "13334762", + "path": [] + } + } + }, + { + "key": "photo_image_full_size_small", + "value": { + "image_value": { + "height": 202, + "width": 386, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=386x202" + }, + "type": "IMAGE" + } + }, + { + "key": "summary_photo_image_large", + "value": { + "image_value": { + "height": 419, + "width": 800, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=800x419" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image_small", + "value": { + "image_value": { + "height": 72, + "width": 144, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=144x144" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image_x_large", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=png&name=2048x2048_2_exp" + }, + "type": "IMAGE" + } + }, + { + "key": "photo_image_full_size_original", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=orig" + }, + "type": "IMAGE" + } + }, + { + "key": "photo_image_full_size_alt_text", + "value": { + "string_value": "==== Ver 3.3.0(2023/01/22) NEW: アカウント追加時にAPIキーを指定可能になりました CHG: API v2 の使用を設定状態に関わらず無効化しました FIX: 同一の画像を複数枚添付する時にプレビュー画像の表示がエラーになる不具合を修正", + "type": "STRING" + } + }, + { + "key": "vanity_url", + "value": { + "scribe_key": "vanity_url", + "string_value": "github.com", + "type": "STRING" + } + }, + { + "key": "photo_image_full_size", + "value": { + "image_value": { + "height": 314, + "width": 600, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=600x314" + }, + "type": "IMAGE" + } + }, + { + "key": "summary_photo_image_alt_text", + "value": { + "string_value": "==== Ver 3.3.0(2023/01/22) NEW: アカウント追加時にAPIキーを指定可能になりました CHG: API v2 の使用を設定状態に関わらず無効化しました FIX: 同一の画像を複数枚添付する時にプレビュー画像の表示がエラーになる不具合を修正", + "type": "STRING" + } + }, + { + "key": "thumbnail_image_color", + "value": { + "image_color_value": { + "palette": [ + { + "rgb": { + "blue": 255, + "green": 255, + "red": 255 + }, + "percentage": 91.56 + }, + { + "rgb": { + "blue": 1, + "green": 135, + "red": 23 + }, + "percentage": 3.12 + }, + { + "rgb": { + "blue": 105, + "green": 184, + "red": 118 + }, + "percentage": 1.56 + }, + { + "rgb": { + "blue": 36, + "green": 37, + "red": 39 + }, + "percentage": 0.96 + }, + { + "rgb": { + "blue": 152, + "green": 247, + "red": 255 + }, + "percentage": 0.37 + } + ] + }, + "type": "IMAGE_COLOR" + } + }, + { + "key": "title", + "value": { + "string_value": "Release OpenTween v3.3.0 · opentween/OpenTween", + "type": "STRING" + } + }, + { + "key": "summary_photo_image_color", + "value": { + "image_color_value": { + "palette": [ + { + "rgb": { + "blue": 255, + "green": 255, + "red": 255 + }, + "percentage": 91.56 + }, + { + "rgb": { + "blue": 1, + "green": 135, + "red": 23 + }, + "percentage": 3.12 + }, + { + "rgb": { + "blue": 105, + "green": 184, + "red": 118 + }, + "percentage": 1.56 + }, + { + "rgb": { + "blue": 36, + "green": 37, + "red": 39 + }, + "percentage": 0.96 + }, + { + "rgb": { + "blue": 152, + "green": 247, + "red": 255 + }, + "percentage": 0.37 + } + ] + }, + "type": "IMAGE_COLOR" + } + }, + { + "key": "summary_photo_image_x_large", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=png&name=2048x2048_2_exp" + }, + "type": "IMAGE" + } + }, + { + "key": "summary_photo_image", + "value": { + "image_value": { + "height": 314, + "width": 600, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=600x314" + }, + "type": "IMAGE" + } + }, + { + "key": "photo_image_full_size_color", + "value": { + "image_color_value": { + "palette": [ + { + "rgb": { + "blue": 255, + "green": 255, + "red": 255 + }, + "percentage": 91.56 + }, + { + "rgb": { + "blue": 1, + "green": 135, + "red": 23 + }, + "percentage": 3.12 + }, + { + "rgb": { + "blue": 105, + "green": 184, + "red": 118 + }, + "percentage": 1.56 + }, + { + "rgb": { + "blue": 36, + "green": 37, + "red": 39 + }, + "percentage": 0.96 + }, + { + "rgb": { + "blue": 152, + "green": 247, + "red": 255 + }, + "percentage": 0.37 + } + ] + }, + "type": "IMAGE_COLOR" + } + }, + { + "key": "photo_image_full_size_x_large", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=png&name=2048x2048_2_exp" + }, + "type": "IMAGE" + } + }, + { + "key": "card_url", + "value": { + "scribe_key": "card_url", + "string_value": "https://t.co/HPLtWszxIr", + "type": "STRING" + } + }, + { + "key": "summary_photo_image_original", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=orig" + }, + "type": "IMAGE" + } + } + ], + "card_platform": { + "platform": { + "audience": { + "name": "production" + }, + "device": { + "name": "Swift", + "version": "12" + } + } + }, + "name": "summary_large_image", + "url": "https://t.co/HPLtWszxIr", + "user_refs_results": [ + { + "result": { + "__typename": "User", + "id": "VXNlcjoxMzMzNDc2Mg==", + "rest_id": "13334762", + "affiliates_highlighted_label": {}, + "has_graduated_access": true, + "is_blue_verified": true, + "profile_image_shape": "Square", + "legacy": { + "can_dm": false, + "can_media_tag": true, + "created_at": "Mon Feb 11 04:41:50 +0000 2008", + "default_profile": false, + "default_profile_image": false, + "description": "The AI-powered developer platform to build, scale, and deliver secure software.", + "entities": { + "description": { + "urls": [] + }, + "url": { + "urls": [ + { + "display_url": "github.com", + "expanded_url": "http://github.com", + "url": "https://t.co/bbJgfyzcJR", + "indices": [ + 0, + 23 + ] + } + ] + } + }, + "fast_followers_count": 0, + "favourites_count": 8055, + "followers_count": 2511440, + "friends_count": 334, + "has_custom_timelines": true, + "is_translator": false, + "listed_count": 18239, + "location": "San Francisco, CA", + "media_count": 2063, + "name": "GitHub", + "normal_followers_count": 2511440, + "pinned_tweet_ids_str": [], + "possibly_sensitive": false, + "profile_banner_url": "https://pbs.twimg.com/profile_banners/13334762/1680541755", + "profile_image_url_https": "https://pbs.twimg.com/profile_images/1633247750010830848/8zfRrYjA_normal.png", + "profile_interstitial_type": "", + "screen_name": "github", + "statuses_count": 8343, + "translator_type": "none", + "url": "https://t.co/bbJgfyzcJR", + "verified": false, + "verified_type": "Business", + "want_retweets": false, + "withheld_in_countries": [] + } + } + } + ] + } + }, + "unified_card": { + "card_fetch_state": "NoCard" + }, + "edit_control": { + "edit_tweet_ids": [ + "1617128268548964354" + ], + "editable_until_msecs": "1674390198669", + "is_edit_eligible": false, + "edits_remaining": "5" + }, + "edit_perspective": { + "favorited": false, + "retweeted": false + }, + "is_translatable": true, + "views": { + "state": "Enabled" + }, + "source": "OpenTween (dev)", + "legacy": { + "bookmark_count": 0, + "bookmarked": false, + "created_at": "Sun Jan 22 11:53:18 +0000 2023", + "conversation_id_str": "1617128268548964354", + "display_text_range": [ + 0, + 89 + ], + "entities": { + "user_mentions": [ + { + "id_str": "514241801", + "name": "OpenTween", + "screen_name": "opentween", + "indices": [ + 3, + 13 + ] + } + ], + "urls": [ + { + "display_url": "osdn.net/projects/opent…", + "expanded_url": "https://osdn.net/projects/opentween/releases/78197", + "url": "https://t.co/nQja6BhnU6", + "indices": [ + 42, + 65 + ] + }, + { + "display_url": "github.com/opentween/Open…", + "expanded_url": "https://github.com/opentween/OpenTween/releases/tag/OpenTween_v3.3.0", + "url": "https://t.co/HPLtWszxIr", + "indices": [ + 66, + 89 + ] + } + ], + "hashtags": [ + { + "indices": [ + 15, + 25 + ], + "text": "OpenTween" + } + ], + "symbols": [] + }, + "favorite_count": 0, + "favorited": false, + "full_text": "RT @opentween: #OpenTween v3.3.0 リリースしました\nhttps://t.co/nQja6BhnU6\nhttps://t.co/HPLtWszxIr", + "is_quote_status": false, + "lang": "ja", + "possibly_sensitive": false, + "possibly_sensitive_editable": true, + "quote_count": 0, + "reply_count": 0, + "retweet_count": 254, + "retweeted": false, + "user_id_str": "40480664", + "id_str": "1617128268548964354", + "retweeted_status_result": { + "result": { + "__typename": "Tweet", + "rest_id": "1617126084138659840", + "core": { + "user_results": { + "result": { + "__typename": "User", + "id": "VXNlcjo1MTQyNDE4MDE=", + "rest_id": "514241801", + "affiliates_highlighted_label": {}, + "has_graduated_access": false, + "is_blue_verified": false, + "profile_image_shape": "Circle", + "legacy": { + "can_dm": true, + "can_media_tag": false, + "created_at": "Sun Mar 04 11:33:45 +0000 2012", + "default_profile": false, + "default_profile_image": false, + "description": "Windows 用 Twitter クライアント OpenTween のアカウントです。", + "entities": { + "description": { + "urls": [] + }, + "url": { + "urls": [ + { + "display_url": "opentween.org", + "expanded_url": "https://www.opentween.org/", + "url": "https://t.co/An6OJeC28u", + "indices": [ + 0, + 23 + ] + } + ] + } + }, + "fast_followers_count": 0, + "favourites_count": 0, + "followers_count": 301, + "friends_count": 1, + "has_custom_timelines": false, + "is_translator": false, + "listed_count": 14, + "location": "", + "media_count": 0, + "name": "OpenTween", + "normal_followers_count": 301, + "pinned_tweet_ids_str": [ + "1617124615347908609" + ], + "possibly_sensitive": false, + "profile_image_url_https": "https://pbs.twimg.com/profile_images/661168792488153088/-UAFci6G_normal.png", + "profile_interstitial_type": "", + "screen_name": "opentween", + "statuses_count": 31, + "translator_type": "none", + "url": "https://t.co/An6OJeC28u", + "verified": false, + "want_retweets": false, + "withheld_in_countries": [] + } + } + } + }, + "card": { + "rest_id": "https://t.co/HPLtWszxIr", + "legacy": { + "binding_values": [ + { + "key": "photo_image_full_size_large", + "value": { + "image_value": { + "height": 419, + "width": 800, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=800x419" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image", + "value": { + "image_value": { + "height": 200, + "width": 400, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=400x400" + }, + "type": "IMAGE" + } + }, + { + "key": "description", + "value": { + "string_value": "==== Ver 3.3.0(2023/01/22) NEW: アカウント追加時にAPIキーを指定可能になりました CHG: API v2 の使用を設定状態に関わらず無効化しました FIX: 同一の画像を複数枚添付する時にプレビュー画像の表示がエラーになる不具合を修正", + "type": "STRING" + } + }, + { + "key": "domain", + "value": { + "string_value": "github.com", + "type": "STRING" + } + }, + { + "key": "thumbnail_image_large", + "value": { + "image_value": { + "height": 300, + "width": 600, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=600x600" + }, + "type": "IMAGE" + } + }, + { + "key": "summary_photo_image_small", + "value": { + "image_value": { + "height": 202, + "width": 386, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=386x202" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image_original", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=orig" + }, + "type": "IMAGE" + } + }, + { + "key": "site", + "value": { + "scribe_key": "publisher_id", + "type": "USER", + "user_value": { + "id_str": "13334762", + "path": [] + } + } + }, + { + "key": "photo_image_full_size_small", + "value": { + "image_value": { + "height": 202, + "width": 386, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=386x202" + }, + "type": "IMAGE" + } + }, + { + "key": "summary_photo_image_large", + "value": { + "image_value": { + "height": 419, + "width": 800, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=800x419" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image_small", + "value": { + "image_value": { + "height": 72, + "width": 144, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=144x144" + }, + "type": "IMAGE" + } + }, + { + "key": "thumbnail_image_x_large", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=png&name=2048x2048_2_exp" + }, + "type": "IMAGE" + } + }, + { + "key": "photo_image_full_size_original", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=orig" + }, + "type": "IMAGE" + } + }, + { + "key": "photo_image_full_size_alt_text", + "value": { + "string_value": "==== Ver 3.3.0(2023/01/22) NEW: アカウント追加時にAPIキーを指定可能になりました CHG: API v2 の使用を設定状態に関わらず無効化しました FIX: 同一の画像を複数枚添付する時にプレビュー画像の表示がエラーになる不具合を修正", + "type": "STRING" + } + }, + { + "key": "vanity_url", + "value": { + "scribe_key": "vanity_url", + "string_value": "github.com", + "type": "STRING" + } + }, + { + "key": "photo_image_full_size", + "value": { + "image_value": { + "height": 314, + "width": 600, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=600x314" + }, + "type": "IMAGE" + } + }, + { + "key": "summary_photo_image_alt_text", + "value": { + "string_value": "==== Ver 3.3.0(2023/01/22) NEW: アカウント追加時にAPIキーを指定可能になりました CHG: API v2 の使用を設定状態に関わらず無効化しました FIX: 同一の画像を複数枚添付する時にプレビュー画像の表示がエラーになる不具合を修正", + "type": "STRING" + } + }, + { + "key": "thumbnail_image_color", + "value": { + "image_color_value": { + "palette": [ + { + "rgb": { + "blue": 255, + "green": 255, + "red": 255 + }, + "percentage": 91.56 + }, + { + "rgb": { + "blue": 1, + "green": 135, + "red": 23 + }, + "percentage": 3.12 + }, + { + "rgb": { + "blue": 105, + "green": 184, + "red": 118 + }, + "percentage": 1.56 + }, + { + "rgb": { + "blue": 36, + "green": 37, + "red": 39 + }, + "percentage": 0.96 + }, + { + "rgb": { + "blue": 152, + "green": 247, + "red": 255 + }, + "percentage": 0.37 + } + ] + }, + "type": "IMAGE_COLOR" + } + }, + { + "key": "title", + "value": { + "string_value": "Release OpenTween v3.3.0 · opentween/OpenTween", + "type": "STRING" + } + }, + { + "key": "summary_photo_image_color", + "value": { + "image_color_value": { + "palette": [ + { + "rgb": { + "blue": 255, + "green": 255, + "red": 255 + }, + "percentage": 91.56 + }, + { + "rgb": { + "blue": 1, + "green": 135, + "red": 23 + }, + "percentage": 3.12 + }, + { + "rgb": { + "blue": 105, + "green": 184, + "red": 118 + }, + "percentage": 1.56 + }, + { + "rgb": { + "blue": 36, + "green": 37, + "red": 39 + }, + "percentage": 0.96 + }, + { + "rgb": { + "blue": 152, + "green": 247, + "red": 255 + }, + "percentage": 0.37 + } + ] + }, + "type": "IMAGE_COLOR" + } + }, + { + "key": "summary_photo_image_x_large", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=png&name=2048x2048_2_exp" + }, + "type": "IMAGE" + } + }, + { + "key": "summary_photo_image", + "value": { + "image_value": { + "height": 314, + "width": 600, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=600x314" + }, + "type": "IMAGE" + } + }, + { + "key": "photo_image_full_size_color", + "value": { + "image_color_value": { + "palette": [ + { + "rgb": { + "blue": 255, + "green": 255, + "red": 255 + }, + "percentage": 91.56 + }, + { + "rgb": { + "blue": 1, + "green": 135, + "red": 23 + }, + "percentage": 3.12 + }, + { + "rgb": { + "blue": 105, + "green": 184, + "red": 118 + }, + "percentage": 1.56 + }, + { + "rgb": { + "blue": 36, + "green": 37, + "red": 39 + }, + "percentage": 0.96 + }, + { + "rgb": { + "blue": 152, + "green": 247, + "red": 255 + }, + "percentage": 0.37 + } + ] + }, + "type": "IMAGE_COLOR" + } + }, + { + "key": "photo_image_full_size_x_large", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=png&name=2048x2048_2_exp" + }, + "type": "IMAGE" + } + }, + { + "key": "card_url", + "value": { + "scribe_key": "card_url", + "string_value": "https://t.co/HPLtWszxIr", + "type": "STRING" + } + }, + { + "key": "summary_photo_image_original", + "value": { + "image_value": { + "height": 600, + "width": 1200, + "url": "https://pbs.twimg.com/card_img/1675573204138758145/wECzotsL?format=jpg&name=orig" + }, + "type": "IMAGE" + } + } + ], + "card_platform": { + "platform": { + "audience": { + "name": "production" + }, + "device": { + "name": "Swift", + "version": "12" + } + } + }, + "name": "summary_large_image", + "url": "https://t.co/HPLtWszxIr", + "user_refs_results": [ + { + "result": { + "__typename": "User", + "id": "VXNlcjoxMzMzNDc2Mg==", + "rest_id": "13334762", + "affiliates_highlighted_label": {}, + "has_graduated_access": true, + "is_blue_verified": true, + "profile_image_shape": "Square", + "legacy": { + "can_dm": false, + "can_media_tag": true, + "created_at": "Mon Feb 11 04:41:50 +0000 2008", + "default_profile": false, + "default_profile_image": false, + "description": "The AI-powered developer platform to build, scale, and deliver secure software.", + "entities": { + "description": { + "urls": [] + }, + "url": { + "urls": [ + { + "display_url": "github.com", + "expanded_url": "http://github.com", + "url": "https://t.co/bbJgfyzcJR", + "indices": [ + 0, + 23 + ] + } + ] + } + }, + "fast_followers_count": 0, + "favourites_count": 8055, + "followers_count": 2511440, + "friends_count": 334, + "has_custom_timelines": true, + "is_translator": false, + "listed_count": 18239, + "location": "San Francisco, CA", + "media_count": 2063, + "name": "GitHub", + "normal_followers_count": 2511440, + "pinned_tweet_ids_str": [], + "possibly_sensitive": false, + "profile_banner_url": "https://pbs.twimg.com/profile_banners/13334762/1680541755", + "profile_image_url_https": "https://pbs.twimg.com/profile_images/1633247750010830848/8zfRrYjA_normal.png", + "profile_interstitial_type": "", + "screen_name": "github", + "statuses_count": 8343, + "translator_type": "none", + "url": "https://t.co/bbJgfyzcJR", + "verified": false, + "verified_type": "Business", + "want_retweets": false, + "withheld_in_countries": [] + } + } + } + ] + } + }, + "unified_card": { + "card_fetch_state": "NoCard" + }, + "edit_control": { + "edit_tweet_ids": [ + "1617126084138659840" + ], + "editable_until_msecs": "1674389677000", + "is_edit_eligible": true, + "edits_remaining": "5" + }, + "edit_perspective": { + "favorited": false, + "retweeted": false + }, + "is_translatable": true, + "views": { + "count": "51826", + "state": "EnabledWithCount" + }, + "source": "OpenTween (dev)", + "legacy": { + "bookmark_count": 24, + "bookmarked": false, + "created_at": "Sun Jan 22 11:44:37 +0000 2023", + "conversation_id_str": "1617126084138659840", + "display_text_range": [ + 0, + 74 + ], + "entities": { + "user_mentions": [], + "urls": [ + { + "display_url": "osdn.net/projects/opent…", + "expanded_url": "https://osdn.net/projects/opentween/releases/78197", + "url": "https://t.co/nQja6BhnU6", + "indices": [ + 27, + 50 + ] + }, + { + "display_url": "github.com/opentween/Open…", + "expanded_url": "https://github.com/opentween/OpenTween/releases/tag/OpenTween_v3.3.0", + "url": "https://t.co/HPLtWszxIr", + "indices": [ + 51, + 74 + ] + } + ], + "hashtags": [ + { + "indices": [ + 0, + 10 + ], + "text": "OpenTween" + } + ], + "symbols": [] + }, + "favorite_count": 168, + "favorited": false, + "full_text": "#OpenTween v3.3.0 リリースしました\nhttps://t.co/nQja6BhnU6\nhttps://t.co/HPLtWszxIr", + "is_quote_status": false, + "lang": "ja", + "possibly_sensitive": false, + "possibly_sensitive_editable": true, + "quote_count": 17, + "reply_count": 1, + "retweet_count": 254, + "retweeted": false, + "user_id_str": "514241801", + "id_str": "1617126084138659840" + } + } + } + } + } + }, + "tweetDisplayType": "Tweet" +} diff --git a/OpenTween.Tests/Resources/Responses/TimelineTweet_SimpleTweet.json b/OpenTween.Tests/Resources/Responses/TimelineTweet_SimpleTweet.json new file mode 100644 index 000000000..399ea23fa --- /dev/null +++ b/OpenTween.Tests/Resources/Responses/TimelineTweet_SimpleTweet.json @@ -0,0 +1,120 @@ +{ + "itemType": "TimelineTweet", + "__typename": "TimelineTweet", + "tweet_results": { + "result": { + "__typename": "Tweet", + "rest_id": "1613784711020826626", + "core": { + "user_results": { + "result": { + "__typename": "User", + "id": "VXNlcjo0MDQ4MDY2NA==", + "rest_id": "40480664", + "affiliates_highlighted_label": {}, + "has_graduated_access": true, + "is_blue_verified": false, + "profile_image_shape": "Circle", + "legacy": { + "followed_by": true, + "following": true, + "can_dm": true, + "can_media_tag": true, + "created_at": "Sat May 16 15:20:01 +0000 2009", + "default_profile": false, + "default_profile_image": false, + "description": "OpenTween Project 言い出しっぺ", + "entities": { + "description": { + "urls": [] + }, + "url": { + "urls": [ + { + "display_url": "m.upsilo.net/@upsilon", + "expanded_url": "https://m.upsilo.net/@upsilon", + "url": "https://t.co/vNMmyHHOQD", + "indices": [ + 0, + 23 + ] + } + ] + } + }, + "fast_followers_count": 0, + "favourites_count": 216272, + "followers_count": 1301, + "friends_count": 917, + "has_custom_timelines": false, + "is_translator": false, + "listed_count": 92, + "location": "Funabashi, Chiba, Japan", + "media_count": 1040, + "name": "upsilon", + "normal_followers_count": 1301, + "pinned_tweet_ids_str": [], + "possibly_sensitive": false, + "profile_banner_url": "https://pbs.twimg.com/profile_banners/40480664/1349188016", + "profile_image_url_https": "https://pbs.twimg.com/profile_images/719076434/____normal.png", + "profile_interstitial_type": "", + "screen_name": "kim_upsilon", + "statuses_count": 10096, + "translator_type": "regular", + "url": "https://t.co/vNMmyHHOQD", + "verified": false, + "want_retweets": true, + "withheld_in_countries": [] + } + } + } + }, + "edit_control": { + "edit_tweet_ids": [ + "1613784711020826626" + ], + "editable_until_msecs": "1673593032000", + "is_edit_eligible": true, + "edits_remaining": "5" + }, + "edit_perspective": { + "favorited": false, + "retweeted": false + }, + "is_translatable": true, + "views": { + "count": "403", + "state": "EnabledWithCount" + }, + "source": "OpenTween (dev)", + "legacy": { + "bookmark_count": 1, + "bookmarked": false, + "created_at": "Fri Jan 13 06:27:12 +0000 2023", + "conversation_id_str": "1613784711020826626", + "display_text_range": [ + 0, + 20 + ], + "entities": { + "user_mentions": [], + "urls": [], + "hashtags": [], + "symbols": [] + }, + "favorite_count": 6, + "favorited": false, + "full_text": "この数年おきに来るAPI凍結騒動は何なの", + "is_quote_status": false, + "lang": "ja", + "quote_count": 0, + "reply_count": 0, + "retweet_count": 0, + "retweeted": false, + "user_id_str": "40480664", + "id_str": "1613784711020826626" + } + } + }, + "tweetDisplayType": "Tweet" +} diff --git a/OpenTween.Tests/Resources/Responses/TimelineTweet_TweetWithMedia.json b/OpenTween.Tests/Resources/Responses/TimelineTweet_TweetWithMedia.json new file mode 100644 index 000000000..0c3273936 --- /dev/null +++ b/OpenTween.Tests/Resources/Responses/TimelineTweet_TweetWithMedia.json @@ -0,0 +1,530 @@ +{ + "itemType": "TimelineTweet", + "__typename": "TimelineTweet", + "tweet_results": { + "result": { + "__typename": "Tweet", + "rest_id": "1614587968567783424", + "core": { + "user_results": { + "result": { + "__typename": "User", + "id": "VXNlcjo0MDQ4MDY2NA==", + "rest_id": "40480664", + "affiliates_highlighted_label": {}, + "has_graduated_access": true, + "is_blue_verified": false, + "profile_image_shape": "Circle", + "legacy": { + "followed_by": true, + "following": true, + "can_dm": true, + "can_media_tag": true, + "created_at": "Sat May 16 15:20:01 +0000 2009", + "default_profile": false, + "default_profile_image": false, + "description": "OpenTween Project 言い出しっぺ", + "entities": { + "description": { + "urls": [] + }, + "url": { + "urls": [ + { + "display_url": "m.upsilo.net/@upsilon", + "expanded_url": "https://m.upsilo.net/@upsilon", + "url": "https://t.co/vNMmyHHOQD", + "indices": [ + 0, + 23 + ] + } + ] + } + }, + "fast_followers_count": 0, + "favourites_count": 216272, + "followers_count": 1301, + "friends_count": 917, + "has_custom_timelines": false, + "is_translator": false, + "listed_count": 92, + "location": "Funabashi, Chiba, Japan", + "media_count": 1040, + "name": "upsilon", + "normal_followers_count": 1301, + "pinned_tweet_ids_str": [], + "possibly_sensitive": false, + "profile_banner_url": "https://pbs.twimg.com/profile_banners/40480664/1349188016", + "profile_image_url_https": "https://pbs.twimg.com/profile_images/719076434/____normal.png", + "profile_interstitial_type": "", + "screen_name": "kim_upsilon", + "statuses_count": 10096, + "translator_type": "regular", + "url": "https://t.co/vNMmyHHOQD", + "verified": false, + "want_retweets": true, + "withheld_in_countries": [] + } + } + } + }, + "edit_control": { + "edit_tweet_ids": [ + "1614587968567783424" + ], + "editable_until_msecs": "1673784543000", + "is_edit_eligible": true, + "edits_remaining": "5" + }, + "edit_perspective": { + "favorited": false, + "retweeted": false + }, + "is_translatable": true, + "views": { + "count": "513", + "state": "EnabledWithCount" + }, + "source": "OpenTween (dev)", + "legacy": { + "bookmark_count": 0, + "bookmarked": false, + "created_at": "Sun Jan 15 11:39:03 +0000 2023", + "conversation_id_str": "1614587968567783424", + "display_text_range": [ + 0, + 3 + ], + "entities": { + "media": [ + { + "display_url": "pic.twitter.com/nMKqMc02ps", + "expanded_url": "https://twitter.com/kim_upsilon/status/1614587968567783424/photo/1", + "id_str": "1614587909176426497", + "indices": [ + 4, + 27 + ], + "media_url_https": "https://pbs.twimg.com/media/FmgrJiEaAAEU42G.png", + "type": "photo", + "url": "https://t.co/nMKqMc02ps", + "features": { + "large": { + "faces": [] + }, + "medium": { + "faces": [] + }, + "small": { + "faces": [] + }, + "orig": { + "faces": [] + } + }, + "sizes": { + "large": { + "h": 736, + "w": 1170, + "resize": "fit" + }, + "medium": { + "h": 736, + "w": 1170, + "resize": "fit" + }, + "small": { + "h": 428, + "w": 680, + "resize": "fit" + }, + "thumb": { + "h": 150, + "w": 150, + "resize": "crop" + } + }, + "original_info": { + "height": 736, + "width": 1170, + "focus_rects": [ + { + "x": 0, + "y": 0, + "w": 1170, + "h": 655 + }, + { + "x": 0, + "y": 0, + "w": 736, + "h": 736 + }, + { + "x": 0, + "y": 0, + "w": 646, + "h": 736 + }, + { + "x": 20, + "y": 0, + "w": 368, + "h": 736 + }, + { + "x": 0, + "y": 0, + "w": 1170, + "h": 736 + } + ] + } + }, + { + "display_url": "pic.twitter.com/nMKqMc02ps", + "expanded_url": "https://twitter.com/kim_upsilon/status/1614587968567783424/photo/1", + "id_str": "1614587909256130561", + "indices": [ + 4, + 27 + ], + "media_url_https": "https://pbs.twimg.com/media/FmgrJiXaMAEu873.jpg", + "type": "photo", + "url": "https://t.co/nMKqMc02ps", + "features": { + "large": { + "faces": [ + { + "x": 1432, + "y": 192, + "h": 104, + "w": 104 + } + ] + }, + "medium": { + "faces": [ + { + "x": 1010, + "y": 135, + "h": 73, + "w": 73 + } + ] + }, + "small": { + "faces": [ + { + "x": 572, + "y": 76, + "h": 41, + "w": 41 + } + ] + }, + "orig": { + "faces": [ + { + "x": 1432, + "y": 192, + "h": 104, + "w": 104 + } + ] + } + }, + "sizes": { + "large": { + "h": 1195, + "w": 1700, + "resize": "fit" + }, + "medium": { + "h": 844, + "w": 1200, + "resize": "fit" + }, + "small": { + "h": 478, + "w": 680, + "resize": "fit" + }, + "thumb": { + "h": 150, + "w": 150, + "resize": "crop" + } + }, + "original_info": { + "height": 1195, + "width": 1700, + "focus_rects": [ + { + "x": 0, + "y": 0, + "w": 1700, + "h": 952 + }, + { + "x": 380, + "y": 0, + "w": 1195, + "h": 1195 + }, + { + "x": 453, + "y": 0, + "w": 1048, + "h": 1195 + }, + { + "x": 678, + "y": 0, + "w": 598, + "h": 1195 + }, + { + "x": 0, + "y": 0, + "w": 1700, + "h": 1195 + } + ] + } + } + ], + "user_mentions": [], + "urls": [], + "hashtags": [], + "symbols": [] + }, + "extended_entities": { + "media": [ + { + "display_url": "pic.twitter.com/nMKqMc02ps", + "expanded_url": "https://twitter.com/kim_upsilon/status/1614587968567783424/photo/1", + "ext_alt_text": "OpenTweenで @opentween のツイート一覧を表示しているスクショ", + "id_str": "1614587909176426497", + "indices": [ + 4, + 27 + ], + "media_key": "3_1614587909176426497", + "media_url_https": "https://pbs.twimg.com/media/FmgrJiEaAAEU42G.png", + "type": "photo", + "url": "https://t.co/nMKqMc02ps", + "ext_media_availability": { + "status": "Available" + }, + "features": { + "large": { + "faces": [] + }, + "medium": { + "faces": [] + }, + "small": { + "faces": [] + }, + "orig": { + "faces": [] + } + }, + "sizes": { + "large": { + "h": 736, + "w": 1170, + "resize": "fit" + }, + "medium": { + "h": 736, + "w": 1170, + "resize": "fit" + }, + "small": { + "h": 428, + "w": 680, + "resize": "fit" + }, + "thumb": { + "h": 150, + "w": 150, + "resize": "crop" + } + }, + "original_info": { + "height": 736, + "width": 1170, + "focus_rects": [ + { + "x": 0, + "y": 0, + "w": 1170, + "h": 655 + }, + { + "x": 0, + "y": 0, + "w": 736, + "h": 736 + }, + { + "x": 0, + "y": 0, + "w": 646, + "h": 736 + }, + { + "x": 20, + "y": 0, + "w": 368, + "h": 736 + }, + { + "x": 0, + "y": 0, + "w": 1170, + "h": 736 + } + ] + } + }, + { + "display_url": "pic.twitter.com/nMKqMc02ps", + "expanded_url": "https://twitter.com/kim_upsilon/status/1614587968567783424/photo/1", + "ext_alt_text": "OpenTweenの新しい画像投稿画面を動かしている様子のスクショ", + "id_str": "1614587909256130561", + "indices": [ + 4, + 27 + ], + "media_key": "3_1614587909256130561", + "media_url_https": "https://pbs.twimg.com/media/FmgrJiXaMAEu873.jpg", + "type": "photo", + "url": "https://t.co/nMKqMc02ps", + "ext_media_availability": { + "status": "Available" + }, + "features": { + "large": { + "faces": [ + { + "x": 1432, + "y": 192, + "h": 104, + "w": 104 + } + ] + }, + "medium": { + "faces": [ + { + "x": 1010, + "y": 135, + "h": 73, + "w": 73 + } + ] + }, + "small": { + "faces": [ + { + "x": 572, + "y": 76, + "h": 41, + "w": 41 + } + ] + }, + "orig": { + "faces": [ + { + "x": 1432, + "y": 192, + "h": 104, + "w": 104 + } + ] + } + }, + "sizes": { + "large": { + "h": 1195, + "w": 1700, + "resize": "fit" + }, + "medium": { + "h": 844, + "w": 1200, + "resize": "fit" + }, + "small": { + "h": 478, + "w": 680, + "resize": "fit" + }, + "thumb": { + "h": 150, + "w": 150, + "resize": "crop" + } + }, + "original_info": { + "height": 1195, + "width": 1700, + "focus_rects": [ + { + "x": 0, + "y": 0, + "w": 1700, + "h": 952 + }, + { + "x": 380, + "y": 0, + "w": 1195, + "h": 1195 + }, + { + "x": 453, + "y": 0, + "w": 1048, + "h": 1195 + }, + { + "x": 678, + "y": 0, + "w": 598, + "h": 1195 + }, + { + "x": 0, + "y": 0, + "w": 1700, + "h": 1195 + } + ] + } + } + ] + }, + "favorite_count": 4, + "favorited": false, + "full_text": "てすと https://t.co/nMKqMc02ps", + "is_quote_status": false, + "lang": "ja", + "possibly_sensitive": false, + "possibly_sensitive_editable": true, + "quote_count": 0, + "reply_count": 0, + "retweet_count": 0, + "retweeted": false, + "user_id_str": "40480664", + "id_str": "1614587968567783424" + } + } + }, + "tweetDisplayType": "Tweet" +} diff --git a/OpenTween/Api/GraphQL/ListLatestTweetsTimelineRequest.cs b/OpenTween/Api/GraphQL/ListLatestTweetsTimelineRequest.cs new file mode 100644 index 000000000..ce8532b32 --- /dev/null +++ b/OpenTween/Api/GraphQL/ListLatestTweetsTimelineRequest.cs @@ -0,0 +1,90 @@ +// OpenTween - Client of Twitter +// Copyright (c) 2023 kim_upsilon (@kim_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 , or write to +// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +// Boston, MA 02110-1301, USA. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization.Json; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Linq; +using OpenTween.Connection; + +namespace OpenTween.Api.GraphQL +{ + public class ListLatestTweetsTimelineRequest + { + private static readonly Uri EndpointUri = new("https://twitter.com/i/api/graphql/6ClPnsuzQJ1p7-g32GQw9Q/ListLatestTweetsTimeline"); + + public string ListId { get; set; } + + public int Count { get; set; } = 20; + + public ListLatestTweetsTimelineRequest(string listId) + => this.ListId = listId; + + public Dictionary CreateParameters() + { + return new() + { + ["variables"] = "{" + + $@"""listId"":""{JsonUtils.EscapeJsonString(this.ListId)}""," + + $@"""count"":{this.Count}" + + "}", + ["features"] = "{" + + @"""rweb_lists_timeline_redesign_enabled"":true," + + @"""responsive_web_graphql_exclude_directive_enabled"":true," + + @"""verified_phone_label_enabled"":false," + + @"""creator_subscriptions_tweet_preview_api_enabled"":true," + + @"""responsive_web_graphql_timeline_navigation_enabled"":true," + + @"""responsive_web_graphql_skip_user_profile_image_extensions_enabled"":false," + + @"""tweetypie_unmention_optimization_enabled"":true," + + @"""responsive_web_edit_tweet_api_enabled"":true," + + @"""graphql_is_translatable_rweb_tweet_is_translatable_enabled"":true," + + @"""view_counts_everywhere_api_enabled"":true," + + @"""longform_notetweets_consumption_enabled"":true," + + @"""responsive_web_twitter_article_tweet_consumption_enabled"":false," + + @"""tweet_awards_web_tipping_enabled"":false," + + @"""freedom_of_speech_not_reach_fetch_enabled"":true," + + @"""standardized_nudges_misinfo"":true," + + @"""tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled"":true," + + @"""longform_notetweets_rich_text_read_enabled"":true," + + @"""longform_notetweets_inline_media_enabled"":true," + + @"""responsive_web_media_download_video_enabled"":false," + + @"""responsive_web_enhance_cards_enabled"":false" + + "}", + }; + } + + public async Task Send(IApiConnection apiConnection) + { + var param = this.CreateParameters(); + using var stream = await apiConnection.GetStreamAsync(EndpointUri, param); + using var jsonReader = JsonReaderWriterFactory.CreateJsonReader(stream, XmlDictionaryReaderQuotas.Max); + var xElm = XElement.Load(jsonReader); + + return TimelineTweet.ExtractTimelineTweets(xElm); + } + } +} diff --git a/OpenTween/Api/GraphQL/TimelineTweet.cs b/OpenTween/Api/GraphQL/TimelineTweet.cs new file mode 100644 index 000000000..62949ef87 --- /dev/null +++ b/OpenTween/Api/GraphQL/TimelineTweet.cs @@ -0,0 +1,143 @@ +// OpenTween - Client of Twitter +// Copyright (c) 2023 kim_upsilon (@kim_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 , or write to +// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +// Boston, MA 02110-1301, USA. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; +using System.Xml.XPath; +using OpenTween.Api.DataModel; + +namespace OpenTween.Api.GraphQL +{ + public class TimelineTweet + { + public const string TypeName = nameof(TimelineTweet); + + public XElement Element { get; } + + public TimelineTweet(XElement element) + { + var typeName = element.Element("itemType")?.Value; + if (typeName != TypeName) + throw new ArgumentException($"Invalid itemType: {typeName}", nameof(element)); + + this.Element = element; + } + + public TwitterStatus ToTwitterStatus() + { + var tweetElm = this.Element.Element("tweet_results")?.Element("result") ?? throw CreateParseError(); + return this.ParseTweet(tweetElm); + } + + private TwitterStatus ParseTweet(XElement tweetElm) + { + var tweetLegacyElm = tweetElm.Element("legacy") ?? throw CreateParseError(); + var userElm = tweetElm.Element("core")?.Element("user_results")?.Element("result") ?? throw CreateParseError(); + var userLegacyElm = userElm.Element("legacy") ?? throw CreateParseError(); + var retweetedTweetElm = tweetLegacyElm.Element("retweeted_status_result")?.Element("result"); + + static string GetText(XElement elm, string name) + => elm.Element(name)?.Value ?? throw CreateParseError(); + + static string? GetTextOrNull(XElement elm, string name) + => elm.Element(name)?.Value; + + return new() + { + IdStr = GetText(tweetElm, "rest_id"), + Source = GetText(tweetElm, "source"), + CreatedAt = GetText(tweetLegacyElm, "created_at"), + FullText = GetText(tweetLegacyElm, "full_text"), + InReplyToScreenName = GetTextOrNull(tweetLegacyElm, "in_reply_to_screen_name"), + InReplyToStatusIdStr = GetTextOrNull(tweetLegacyElm, "in_reply_to_status_id_str"), + InReplyToUserId = GetTextOrNull(tweetLegacyElm, "in_reply_to_user_id_str") is string userId ? long.Parse(userId) : null, + Favorited = GetTextOrNull(tweetLegacyElm, "favorited") is string favorited ? favorited == "true" : null, + Entities = new() + { + UserMentions = tweetLegacyElm.XPathSelectElements("entities/user_mentions/item") + .Select(x => new TwitterEntityMention() + { + Indices = x.XPathSelectElements("indices/item").Select(x => int.Parse(x.Value)).ToArray(), + ScreenName = GetText(x, "screen_name"), + }) + .ToArray(), + Urls = tweetLegacyElm.XPathSelectElements("entities/urls/item") + .Select(x => new TwitterEntityUrl() + { + Indices = x.XPathSelectElements("indices/item").Select(x => int.Parse(x.Value)).ToArray(), + DisplayUrl = GetText(x, "display_url"), + ExpandedUrl = GetText(x, "expanded_url"), + Url = GetText(x, "url"), + }) + .ToArray(), + Hashtags = tweetLegacyElm.XPathSelectElements("entities/hashtags/item") + .Select(x => new TwitterEntityHashtag() + { + Indices = x.XPathSelectElements("indices/item").Select(x => int.Parse(x.Value)).ToArray(), + Text = GetText(x, "text"), + }) + .ToArray(), + }, + ExtendedEntities = new() + { + Media = tweetLegacyElm.XPathSelectElements("extended_entities/media/item") + .Select(x => new TwitterEntityMedia() + { + Indices = x.XPathSelectElements("indices/item").Select(x => int.Parse(x.Value)).ToArray(), + DisplayUrl = GetText(x, "display_url"), + ExpandedUrl = GetText(x, "expanded_url"), + Url = GetText(x, "url"), + MediaUrlHttps = GetText(x, "media_url_https"), + Type = GetText(x, "type"), + AltText = GetTextOrNull(x, "ext_alt_text"), + }) + .ToArray(), + }, + User = new() + { + Id = long.Parse(GetText(userElm, "rest_id")), + IdStr = GetText(userElm, "rest_id"), + Name = GetText(userLegacyElm, "name"), + ProfileImageUrlHttps = GetText(userLegacyElm, "profile_image_url_https"), + ScreenName = GetText(userLegacyElm, "screen_name"), + Protected = GetTextOrNull(userLegacyElm, "protected") == "true", + }, + RetweetedStatus = retweetedTweetElm != null ? this.ParseTweet(retweetedTweetElm) : null, + }; + } + + private static Exception CreateParseError() + => throw new WebApiException("Parse error on TimelineTweet"); + + public static TimelineTweet[] ExtractTimelineTweets(XElement element) + { + return element.XPathSelectElements($"//itemContent[itemType[text()='{TypeName}']][tweetDisplayType[text()='Tweet']]") + .Select(x => new TimelineTweet(x)) + .ToArray(); + } + } +} diff --git a/OpenTween/Resources/ChangeLog.txt b/OpenTween/Resources/ChangeLog.txt index 0bcd68584..12349dc16 100644 --- a/OpenTween/Resources/ChangeLog.txt +++ b/OpenTween/Resources/ChangeLog.txt @@ -1,6 +1,7 @@ 更新履歴 ==== Unreleased + * NEW: Cookie使用時にgraphqlエンドポイントを使用したリストのタイムライン取得に対応 * FIX: 「このタブの発言をクリア」で参照されなくなった発言分のメモリが開放されない場合がある不具合を修正 ==== Ver 3.5.0(2023/06/16) diff --git a/OpenTween/Twitter.cs b/OpenTween/Twitter.cs index 3d43e8904..0b463f58b 100644 --- a/OpenTween/Twitter.cs +++ b/OpenTween/Twitter.cs @@ -43,6 +43,7 @@ using System.Windows.Forms; using OpenTween.Api; using OpenTween.Api.DataModel; +using OpenTween.Api.GraphQL; using OpenTween.Api.TwitterV2; using OpenTween.Connection; using OpenTween.Models; @@ -746,7 +747,17 @@ public async Task GetListStatus(bool read, ListTimelineTabModel tab, bool more, var count = GetApiResultCount(MyCommon.WORKERTYPE.List, more, startup); TwitterStatus[] statuses; - if (more) + if (this.Api.AppToken.AuthType == APIAuthType.TwitterComCookie) + { + var request = new ListLatestTweetsTimelineRequest(tab.ListInfo.Id.ToString()) + { + Count = count, + }; + var timelineTweets = await request.Send(this.Api.Connection) + .ConfigureAwait(false); + statuses = timelineTweets.Select(x => x.ToTwitterStatus()).ToArray(); + } + else if (more) { statuses = await this.Api.ListsStatuses(tab.ListInfo.Id, count, maxId: tab.OldestId, includeRTs: SettingManager.Instance.Common.IsListsIncludeRts) .ConfigureAwait(false);