Skip to content

Commit b954c0f

Browse files
committed
Merge branch 'develop' into release
2 parents 39cbe2a + db3cde3 commit b954c0f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2546
-136
lines changed

CHANGELOG.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
更新履歴
22

3+
==== Ver 3.13.0(2024/01/27)
4+
* NEW: Cookie使用時のReplyタブの更新に対応(/statuses/mentions_timeline.json 廃止に伴う対応)
5+
* NEW: Cookie使用時のFavoritesタブの更新に対応
6+
* NEW: Cookie使用時のFav追加・削除に対応
7+
* NEW: ステータスバーに各タブの更新回数(起動時からの回数)の表示を追加
8+
* NEW: 設定画面の更新間隔ページに24時間分の取得回数目安の表示を追加
9+
* CHG: 更新間隔の初期設定を変更
10+
* FIX: Cookie使用時にツイート検索の言語指定が効かない不具合を修正
11+
* FIX: ツイート検索のキーワードを後から変更すると検索結果が表示されない不具合を修正
12+
* FIX: Cookie使用時にステータスバーにRecentタブのレートリミットが表示されない不具合を修正
13+
* FIX: 取得したツイートの中身が空だった場合のエラー処理を改善
14+
* FIX: タイムラインの取得結果にレートリミットに関するメッセージが含まれていた場合はエラーとして扱う
15+
316
==== Ver 3.12.0(2024/01/20)
417
* NEW: graphqlエンドポイントを使用したホームタイムラインの取得に対応
518

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// OpenTween - Client of Twitter
2+
// Copyright (c) 2024 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3+
// All rights reserved.
4+
//
5+
// This file is part of OpenTween.
6+
//
7+
// This program is free software; you can redistribute it and/or modify it
8+
// under the terms of the GNU General Public License as published by the Free
9+
// Software Foundation; either version 3 of the License, or (at your option)
10+
// any later version.
11+
//
12+
// This program is distributed in the hope that it will be useful, but
13+
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14+
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
// for more details.
16+
//
17+
// You should have received a copy of the GNU General Public License along
18+
// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19+
// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20+
// Boston, MA 02110-1301, USA.
21+
22+
using System.Threading.Tasks;
23+
using Moq;
24+
using OpenTween.Connection;
25+
using Xunit;
26+
27+
namespace OpenTween.Api.GraphQL
28+
{
29+
public class FavoriteTweetRequestTest
30+
{
31+
[Fact]
32+
public async Task Send_Test()
33+
{
34+
using var apiResponse = await TestUtils.CreateApiResponse("Resources/Responses/FavoriteTweet.json");
35+
36+
var mock = new Mock<IApiConnection>();
37+
mock.Setup(x =>
38+
x.SendAsync(It.IsAny<IHttpRequest>())
39+
)
40+
.Callback<IHttpRequest>(x =>
41+
{
42+
var request = Assert.IsType<PostJsonRequest>(x);
43+
Assert.Equal(new("https://twitter.com/i/api/graphql/lI07N6Otwv1PhnEgXILM7A/FavoriteTweet"), request.RequestUri);
44+
Assert.Equal("""{"variables":{"tweet_id":"12345"},"queryId":"lI07N6Otwv1PhnEgXILM7A"}""", request.JsonString);
45+
})
46+
.ReturnsAsync(apiResponse);
47+
48+
var request = new FavoriteTweetRequest
49+
{
50+
TweetId = new("12345"),
51+
};
52+
53+
await request.Send(mock.Object);
54+
55+
mock.VerifyAll();
56+
}
57+
58+
[Fact]
59+
public async Task Send_AlreadyFavoritedTest()
60+
{
61+
using var apiResponse = await TestUtils.CreateApiResponse("Resources/Responses/FavoriteTweet_AlreadyFavorited.json");
62+
63+
var mock = new Mock<IApiConnection>();
64+
mock.Setup(x => x.SendAsync(It.IsAny<IHttpRequest>()))
65+
.ReturnsAsync(apiResponse);
66+
67+
var request = new FavoriteTweetRequest
68+
{
69+
TweetId = new("12345"),
70+
};
71+
72+
// 重複によるエラーレスポンスが返っているが例外を発生させない
73+
await request.Send(mock.Object);
74+
75+
mock.VerifyAll();
76+
}
77+
}
78+
}

OpenTween.Tests/Api/GraphQL/HomeLatestTimelineRequestTest.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
using System.Threading.Tasks;
2323
using Moq;
24+
using OpenTween.Api.DataModel;
2425
using OpenTween.Connection;
2526
using Xunit;
2627

@@ -92,5 +93,32 @@ public async Task Send_RequestCursor_Test()
9293
await request.Send(mock.Object);
9394
mock.VerifyAll();
9495
}
96+
97+
[Fact]
98+
public async Task Send_RateLimitTest()
99+
{
100+
using var apiResponse = await TestUtils.CreateApiResponse("Resources/Responses/HomeLatestTimeline_RateLimit.json");
101+
102+
var mock = new Mock<IApiConnection>();
103+
mock.Setup(x =>
104+
x.SendAsync(It.IsAny<IHttpRequest>())
105+
)
106+
.Callback<IHttpRequest>(x =>
107+
{
108+
var request = Assert.IsType<GetRequest>(x);
109+
Assert.Equal(new("https://twitter.com/i/api/graphql/lAKISuk_McyDUlhS2Zmv4A/HomeLatestTimeline"), request.RequestUri);
110+
})
111+
.ReturnsAsync(apiResponse);
112+
113+
var request = new HomeLatestTimelineRequest();
114+
115+
var ex = await Assert.ThrowsAsync<TwitterApiException>(
116+
() => request.Send(mock.Object)
117+
);
118+
var errorItem = Assert.Single(ex.Errors);
119+
Assert.Equal(TwitterErrorCode.RateLimit, errorItem.Code);
120+
121+
mock.VerifyAll();
122+
}
95123
}
96124
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// OpenTween - Client of Twitter
2+
// Copyright (c) 2024 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3+
// All rights reserved.
4+
//
5+
// This file is part of OpenTween.
6+
//
7+
// This program is free software; you can redistribute it and/or modify it
8+
// under the terms of the GNU General Public License as published by the Free
9+
// Software Foundation; either version 3 of the License, or (at your option)
10+
// any later version.
11+
//
12+
// This program is distributed in the hope that it will be useful, but
13+
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14+
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
// for more details.
16+
//
17+
// You should have received a copy of the GNU General Public License along
18+
// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19+
// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20+
// Boston, MA 02110-1301, USA.
21+
22+
using System.Threading.Tasks;
23+
using Moq;
24+
using OpenTween.Connection;
25+
using Xunit;
26+
27+
namespace OpenTween.Api.GraphQL
28+
{
29+
public class LikesRequestTest
30+
{
31+
[Fact]
32+
public async Task Send_Test()
33+
{
34+
using var apiResponse = await TestUtils.CreateApiResponse("Resources/Responses/Likes.json");
35+
36+
var mock = new Mock<IApiConnection>();
37+
mock.Setup(x =>
38+
x.SendAsync(It.IsAny<IHttpRequest>())
39+
)
40+
.Callback<IHttpRequest>(x =>
41+
{
42+
var request = Assert.IsType<GetRequest>(x);
43+
Assert.Equal(new("https://twitter.com/i/api/graphql/G_zHbTiwSqLm0TAK_3sNWQ/Likes"), request.RequestUri);
44+
var query = request.Query!;
45+
Assert.Equal(2, query.Count);
46+
Assert.Equal("""{"userId":"12345","count":20,"includePromotedContent":false,"withClientEventToken":false,"withBirdwatchNotes":false,"withVoice":true,"withV2Timeline":true}""", query["variables"]);
47+
Assert.True(query.ContainsKey("features"));
48+
Assert.Equal("Likes", request.EndpointName);
49+
})
50+
.ReturnsAsync(apiResponse);
51+
52+
var request = new LikesRequest
53+
{
54+
UserId = "12345",
55+
Count = 20,
56+
};
57+
58+
var response = await request.Send(mock.Object);
59+
Assert.Single(response.Tweets);
60+
Assert.Equal("DAAHCgABGEs2Ve9AAAELAAIAAAATMTc4OTA3OTU2MDM5NDcxNTMyMggAAwAAAAEAAA", response.CursorTop);
61+
Assert.Equal("DAAHCgABGEs2Ve8___8LAAIAAAATMTc4OTA3OTU2MDM5NDcxNTMyMggAAwAAAAIAAA", response.CursorBottom);
62+
63+
mock.VerifyAll();
64+
}
65+
66+
[Fact]
67+
public async Task Send_RequestCursor_Test()
68+
{
69+
using var apiResponse = await TestUtils.CreateApiResponse("Resources/Responses/Likes.json");
70+
71+
var mock = new Mock<IApiConnection>();
72+
mock.Setup(x =>
73+
x.SendAsync(It.IsAny<IHttpRequest>())
74+
)
75+
.Callback<IHttpRequest>(x =>
76+
{
77+
var request = Assert.IsType<GetRequest>(x);
78+
Assert.Equal(new("https://twitter.com/i/api/graphql/G_zHbTiwSqLm0TAK_3sNWQ/Likes"), request.RequestUri);
79+
var query = request.Query!;
80+
Assert.Equal("""{"userId":"12345","count":20,"includePromotedContent":false,"withClientEventToken":false,"withBirdwatchNotes":false,"withVoice":true,"withV2Timeline":true,"cursor":"aaa"}""", query["variables"]);
81+
})
82+
.ReturnsAsync(apiResponse);
83+
84+
var request = new LikesRequest
85+
{
86+
UserId = "12345",
87+
Count = 20,
88+
Cursor = "aaa",
89+
};
90+
91+
await request.Send(mock.Object);
92+
mock.VerifyAll();
93+
}
94+
}
95+
}

OpenTween.Tests/Api/GraphQL/TimelineTweetTest.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,24 @@ public void ToStatus_TweetTombstone_Test()
188188
var rootElm = this.LoadResponseDocument("TimelineTweet_TweetTombstone.json");
189189
var timelineTweet = new TimelineTweet(rootElm);
190190

191-
Assert.True(timelineTweet.IsTombstone);
191+
Assert.False(timelineTweet.IsAvailable);
192192
var ex = Assert.Throws<WebApiException>(
193193
() => timelineTweet.ToTwitterStatus()
194194
);
195195
Assert.Equal("This Post is from a suspended account. Learn more", ex.Message);
196196
}
197+
198+
[Fact]
199+
public void ToStatus_EmptyTweet_Test()
200+
{
201+
var rootElm = this.LoadResponseDocument("TimelineTweet_EmptyTweet.json");
202+
var timelineTweet = new TimelineTweet(rootElm);
203+
204+
Assert.False(timelineTweet.IsAvailable);
205+
var ex = Assert.Throws<WebApiException>(
206+
() => timelineTweet.ToTwitterStatus()
207+
);
208+
Assert.Equal("Tweet is not available", ex.Message);
209+
}
197210
}
198211
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// OpenTween - Client of Twitter
2+
// Copyright (c) 2024 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3+
// All rights reserved.
4+
//
5+
// This file is part of OpenTween.
6+
//
7+
// This program is free software; you can redistribute it and/or modify it
8+
// under the terms of the GNU General Public License as published by the Free
9+
// Software Foundation; either version 3 of the License, or (at your option)
10+
// any later version.
11+
//
12+
// This program is distributed in the hope that it will be useful, but
13+
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14+
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
// for more details.
16+
//
17+
// You should have received a copy of the GNU General Public License along
18+
// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19+
// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20+
// Boston, MA 02110-1301, USA.
21+
22+
using System.Threading.Tasks;
23+
using Moq;
24+
using OpenTween.Connection;
25+
using Xunit;
26+
27+
namespace OpenTween.Api.GraphQL
28+
{
29+
public class UnfavoriteTweetRequestTest
30+
{
31+
[Fact]
32+
public async Task Send_Test()
33+
{
34+
using var apiResponse = await TestUtils.CreateApiResponse("Resources/Responses/UnfavoriteTweet.json");
35+
36+
var mock = new Mock<IApiConnection>();
37+
mock.Setup(x =>
38+
x.SendAsync(It.IsAny<IHttpRequest>())
39+
)
40+
.Callback<IHttpRequest>(x =>
41+
{
42+
var request = Assert.IsType<PostJsonRequest>(x);
43+
Assert.Equal(new("https://twitter.com/i/api/graphql/ZYKSe-w7KEslx3JhSIk5LA/UnfavoriteTweet"), request.RequestUri);
44+
Assert.Equal("""{"variables":{"tweet_id":"12345"},"queryId":"ZYKSe-w7KEslx3JhSIk5LA"}""", request.JsonString);
45+
})
46+
.ReturnsAsync(apiResponse);
47+
48+
var request = new UnfavoriteTweetRequest
49+
{
50+
TweetId = new("12345"),
51+
};
52+
53+
await request.Send(mock.Object);
54+
55+
mock.VerifyAll();
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)