From b43c97bf6ed9af79b47fdbfe6ea23fdb3ca3b160 Mon Sep 17 00:00:00 2001 From: Kimura Youichi Date: Sun, 10 Dec 2023 22:03:16 +0900 Subject: [PATCH] =?utf8?q?ITwitterCredential=E3=81=A8=E3=82=A2=E3=82=AF?= =?utf8?q?=E3=82=BB=E3=82=B9=E6=89=8B=E6=AE=B5=E3=81=94=E3=81=A8=E3=81=AE?= =?utf8?q?=E5=85=B7=E8=B1=A1=E3=82=AF=E3=83=A9=E3=82=B9=E3=82=92=E8=BF=BD?= =?utf8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- OpenTween.Tests/Api/TwitterApiTest.cs | 10 +- .../Connection/TwitterApiConnectionTest.cs | 26 ++--- .../Connection/TwitterCredentialCookieTest.cs | 47 +++++++++ .../Connection/TwitterCredentialOAuth1Test.cs | 51 ++++++++++ OpenTween.Tests/TweenMainTest.cs | 8 +- OpenTween/Api/TwitterApi.cs | 8 +- OpenTween/AppendSettingDialog.cs | 4 +- OpenTween/ApplicationEvents.cs | 4 +- OpenTween/Connection/ITwitterCredential.cs | 34 +++++++ OpenTween/Connection/TwitterApiConnection.cs | 113 ++++++++------------- OpenTween/Connection/TwitterCredentialCookie.cs | 38 +++++++ OpenTween/Connection/TwitterCredentialNone.cs | 36 +++++++ OpenTween/Connection/TwitterCredentialOAuth1.cs | 52 ++++++++++ OpenTween/Setting/SettingCommon.cs | 14 +++ OpenTween/Tween.cs | 4 +- OpenTween/Twitter.cs | 9 +- 16 files changed, 349 insertions(+), 109 deletions(-) create mode 100644 OpenTween.Tests/Connection/TwitterCredentialCookieTest.cs create mode 100644 OpenTween.Tests/Connection/TwitterCredentialOAuth1Test.cs create mode 100644 OpenTween/Connection/ITwitterCredential.cs create mode 100644 OpenTween/Connection/TwitterCredentialCookie.cs create mode 100644 OpenTween/Connection/TwitterCredentialNone.cs create mode 100644 OpenTween/Connection/TwitterCredentialOAuth1.cs diff --git a/OpenTween.Tests/Api/TwitterApiTest.cs b/OpenTween.Tests/Api/TwitterApiTest.cs index d74088b2..bac959bb 100644 --- a/OpenTween.Tests/Api/TwitterApiTest.cs +++ b/OpenTween.Tests/Api/TwitterApiTest.cs @@ -59,8 +59,9 @@ namespace OpenTween.Api Assert.IsType(twitterApi.ApiConnection); var apiConnection = (TwitterApiConnection)twitterApi.ApiConnection!; - Assert.Equal("*** AccessToken ***", apiConnection.AccessToken); - Assert.Equal("*** AccessSecret ***", apiConnection.AccessSecret); + var credential = Assert.IsType(apiConnection.Credential); + Assert.Equal("*** AccessToken ***", credential.Token); + Assert.Equal("*** AccessSecret ***", credential.TokenSecret); Assert.Equal(100L, twitterApi.CurrentUserId); Assert.Equal("hogehoge", twitterApi.CurrentScreenName); @@ -74,8 +75,9 @@ namespace OpenTween.Api Assert.IsType(twitterApi.ApiConnection); apiConnection = (TwitterApiConnection)twitterApi.ApiConnection!; - Assert.Equal("*** AccessToken2 ***", apiConnection.AccessToken); - Assert.Equal("*** AccessSecret2 ***", apiConnection.AccessSecret); + credential = Assert.IsType(apiConnection.Credential); + Assert.Equal("*** AccessToken2 ***", credential.Token); + Assert.Equal("*** AccessSecret2 ***", credential.TokenSecret); Assert.Equal(200L, twitterApi.CurrentUserId); Assert.Equal("foobar", twitterApi.CurrentScreenName); diff --git a/OpenTween.Tests/Connection/TwitterApiConnectionTest.cs b/OpenTween.Tests/Connection/TwitterApiConnectionTest.cs index 1c7b53cd..c646f07b 100644 --- a/OpenTween.Tests/Connection/TwitterApiConnectionTest.cs +++ b/OpenTween.Tests/Connection/TwitterApiConnectionTest.cs @@ -57,7 +57,7 @@ namespace OpenTween.Connection { using var mockHandler = new HttpMessageHandlerMock(); using var http = new HttpClient(mockHandler); - using var apiConnection = new TwitterApiConnection(ApiKey.Create(""), ApiKey.Create(""), "", ""); + using var apiConnection = new TwitterApiConnection(); apiConnection.Http = http; mockHandler.Enqueue(x => @@ -95,7 +95,7 @@ namespace OpenTween.Connection { using var mockHandler = new HttpMessageHandlerMock(); using var http = new HttpClient(mockHandler); - using var apiConnection = new TwitterApiConnection(ApiKey.Create(""), ApiKey.Create(""), "", ""); + using var apiConnection = new TwitterApiConnection(); apiConnection.Http = http; mockHandler.Enqueue(x => @@ -132,7 +132,7 @@ namespace OpenTween.Connection { using var mockHandler = new HttpMessageHandlerMock(); using var http = new HttpClient(mockHandler); - using var apiConnection = new TwitterApiConnection(ApiKey.Create(""), ApiKey.Create(""), "", ""); + using var apiConnection = new TwitterApiConnection(); apiConnection.Http = http; mockHandler.Enqueue(x => @@ -175,7 +175,7 @@ namespace OpenTween.Connection { using var mockHandler = new HttpMessageHandlerMock(); using var http = new HttpClient(mockHandler); - using var apiConnection = new TwitterApiConnection(ApiKey.Create(""), ApiKey.Create(""), "", ""); + using var apiConnection = new TwitterApiConnection(); apiConnection.Http = http; mockHandler.Enqueue(x => @@ -219,7 +219,7 @@ namespace OpenTween.Connection { using var mockHandler = new HttpMessageHandlerMock(); using var http = new HttpClient(mockHandler); - using var apiConnection = new TwitterApiConnection(ApiKey.Create(""), ApiKey.Create(""), "", ""); + using var apiConnection = new TwitterApiConnection(); apiConnection.Http = http; mockHandler.Enqueue(x => @@ -251,7 +251,7 @@ namespace OpenTween.Connection { using var mockHandler = new HttpMessageHandlerMock(); using var http = new HttpClient(mockHandler); - using var apiConnection = new TwitterApiConnection(ApiKey.Create(""), ApiKey.Create(""), "", ""); + using var apiConnection = new TwitterApiConnection(); apiConnection.Http = http; mockHandler.Enqueue(x => @@ -285,7 +285,7 @@ namespace OpenTween.Connection { using var mockHandler = new HttpMessageHandlerMock(); using var http = new HttpClient(mockHandler); - using var apiConnection = new TwitterApiConnection(ApiKey.Create(""), ApiKey.Create(""), "", ""); + using var apiConnection = new TwitterApiConnection(); using var image = TestUtils.CreateDummyImage(); apiConnection.Http = http; @@ -331,7 +331,7 @@ namespace OpenTween.Connection { using var mockHandler = new HttpMessageHandlerMock(); using var http = new HttpClient(mockHandler); - using var apiConnection = new TwitterApiConnection(ApiKey.Create(""), ApiKey.Create(""), "", ""); + using var apiConnection = new TwitterApiConnection(); apiConnection.Http = http; mockHandler.Enqueue(async x => @@ -371,7 +371,7 @@ namespace OpenTween.Connection { using var mockHandler = new HttpMessageHandlerMock(); using var http = new HttpClient(mockHandler); - using var apiConnection = new TwitterApiConnection(ApiKey.Create(""), ApiKey.Create(""), "", ""); + using var apiConnection = new TwitterApiConnection(); apiConnection.HttpUpload = http; using var image = TestUtils.CreateDummyImage(); @@ -441,7 +441,7 @@ namespace OpenTween.Connection { using var mockHandler = new HttpMessageHandlerMock(); using var http = new HttpClient(mockHandler); - using var apiConnection = new TwitterApiConnection(ApiKey.Create(""), ApiKey.Create(""), "", ""); + using var apiConnection = new TwitterApiConnection(); apiConnection.HttpUpload = http; mockHandler.Enqueue(async x => @@ -486,7 +486,7 @@ namespace OpenTween.Connection { using var mockHandler = new HttpMessageHandlerMock(); using var http = new HttpClient(mockHandler); - using var apiConnection = new TwitterApiConnection(ApiKey.Create(""), ApiKey.Create(""), "", ""); + using var apiConnection = new TwitterApiConnection(); apiConnection.Http = http; mockHandler.Enqueue(async x => @@ -520,7 +520,7 @@ namespace OpenTween.Connection { using var mockHandler = new HttpMessageHandlerMock(); using var http = new HttpClient(mockHandler); - using var apiConnection = new TwitterApiConnection(ApiKey.Create(""), ApiKey.Create(""), "", ""); + using var apiConnection = new TwitterApiConnection(); apiConnection.Http = http; mockHandler.Enqueue(async x => @@ -555,7 +555,7 @@ namespace OpenTween.Connection { using var mockHandler = new HttpMessageHandlerMock(); using var http = new HttpClient(mockHandler); - using var apiConnection = new TwitterApiConnection(ApiKey.Create(""), ApiKey.Create(""), "", ""); + using var apiConnection = new TwitterApiConnection(); apiConnection.Http = http; mockHandler.Enqueue(x => diff --git a/OpenTween.Tests/Connection/TwitterCredentialCookieTest.cs b/OpenTween.Tests/Connection/TwitterCredentialCookieTest.cs new file mode 100644 index 00000000..938b8f55 --- /dev/null +++ b/OpenTween.Tests/Connection/TwitterCredentialCookieTest.cs @@ -0,0 +1,47 @@ +// 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.Net.Http; +using Xunit; + +namespace OpenTween.Connection +{ + public class TwitterCredentialCookieTest + { + [Fact] + public void CreateHttpHandler_Test() + { + var appToken = new TwitterAppToken + { + AuthType = APIAuthType.TwitterComCookie, + TwitterComCookie = "aaa=bbb", + }; + var credential = new TwitterCredentialCookie(appToken); + + using var innerHandler = new HttpClientHandler(); + using var handler = credential.CreateHttpHandler(innerHandler); + + var cookieHandler = Assert.IsType(handler); + Assert.Equal("aaa=bbb", cookieHandler.RawCookie); + Assert.Same(innerHandler, cookieHandler.InnerHandler); + } + } +} diff --git a/OpenTween.Tests/Connection/TwitterCredentialOAuth1Test.cs b/OpenTween.Tests/Connection/TwitterCredentialOAuth1Test.cs new file mode 100644 index 00000000..5ede503b --- /dev/null +++ b/OpenTween.Tests/Connection/TwitterCredentialOAuth1Test.cs @@ -0,0 +1,51 @@ +// 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.Net.Http; +using Xunit; + +namespace OpenTween.Connection +{ + public class TwitterCredentialOAuth1Test + { + [Fact] + public void CreateHttpHandler_Test() + { + var appToken = new TwitterAppToken + { + AuthType = APIAuthType.OAuth1, + OAuth1CustomConsumerKey = ApiKey.Create("consumer_key"), + OAuth1CustomConsumerSecret = ApiKey.Create("consumer_secret"), + }; + var credential = new TwitterCredentialOAuth1(appToken, "access_token", "access_secret"); + + using var innerHandler = new HttpClientHandler(); + using var handler = credential.CreateHttpHandler(innerHandler); + + var oauthHandler = Assert.IsType(handler); + Assert.Equal("consumer_key", oauthHandler.ConsumerKey.Value); + Assert.Equal("consumer_secret", oauthHandler.ConsumerSecret.Value); + Assert.Equal("access_token", oauthHandler.AccessToken); + Assert.Equal("access_secret", oauthHandler.AccessSecret); + Assert.Same(innerHandler, oauthHandler.InnerHandler); + } + } +} diff --git a/OpenTween.Tests/TweenMainTest.cs b/OpenTween.Tests/TweenMainTest.cs index 37a1ac2f..87dfbec7 100644 --- a/OpenTween.Tests/TweenMainTest.cs +++ b/OpenTween.Tests/TweenMainTest.cs @@ -48,13 +48,7 @@ namespace OpenTween using var imageCache = new ImageCache(); using var iconAssets = new IconAssetsManager(); var thumbnailGenerator = new ThumbnailGenerator(new(autoupdate: false)); - var twitterAppToken = new TwitterAppToken - { - AuthType = APIAuthType.OAuth1, - OAuth1CustomConsumerKey = ApiKey.Create("aaa"), - OAuth1CustomConsumerSecret = ApiKey.Create("bbb"), - }; - twitter.Initialize(twitterAppToken, "", "", "", 0L); + twitter.Initialize(new TwitterCredentialNone(), "", 0L); using var tweenMain = new TweenMain(settings, tabinfo, twitter, imageCache, iconAssets, thumbnailGenerator); } diff --git a/OpenTween/Api/TwitterApi.cs b/OpenTween/Api/TwitterApi.cs index abce7633..bc97384d 100644 --- a/OpenTween/Api/TwitterApi.cs +++ b/OpenTween/Api/TwitterApi.cs @@ -62,13 +62,13 @@ namespace OpenTween.Api } public void Initialize(string accessToken, string accessSecret, long userId, string screenName) - => this.Initialize(this.AppToken, accessToken, accessSecret, userId, screenName); + => this.Initialize(new TwitterCredentialOAuth1(this.AppToken, accessToken, accessSecret), userId, screenName); - public void Initialize(TwitterAppToken appToken, string accessToken, string accessSecret, long userId, string screenName) + public void Initialize(ITwitterCredential credential, long userId, string screenName) { - this.AppToken = appToken; + this.AppToken = credential.AppToken; - var newInstance = new TwitterApiConnection(this.AppToken, accessToken, accessSecret); + var newInstance = new TwitterApiConnection(credential); var oldInstance = Interlocked.Exchange(ref this.ApiConnection, newInstance); oldInstance?.Dispose(); diff --git a/OpenTween/AppendSettingDialog.cs b/OpenTween/AppendSettingDialog.cs index 0803eb48..703cd51c 100644 --- a/OpenTween/AppendSettingDialog.cs +++ b/OpenTween/AppendSettingDialog.cs @@ -195,7 +195,7 @@ namespace OpenTween }; using var twitterApi = new TwitterApi(); - twitterApi.Initialize(appToken, "", "", 0L, ""); + twitterApi.Initialize(new TwitterCredentialCookie(appToken), 0L, ""); var twitterUser = await twitterApi.AccountVerifyCredentials(); newAccount.UserId = twitterUser.Id; newAccount.Username = twitterUser.ScreenName; @@ -294,7 +294,7 @@ namespace OpenTween if (MyCommon.IsNullOrEmpty(pin)) return null; // キャンセルされた場合 - var accessTokenResponse = await TwitterApiConnection.GetAccessTokenAsync(appToken, requestToken, pin); + var accessTokenResponse = await TwitterApiConnection.GetAccessTokenAsync(requestToken, pin); return new UserAccount { diff --git a/OpenTween/ApplicationEvents.cs b/OpenTween/ApplicationEvents.cs index 539639cc..04d5a694 100644 --- a/OpenTween/ApplicationEvents.cs +++ b/OpenTween/ApplicationEvents.cs @@ -143,9 +143,9 @@ namespace OpenTween { var account = settings.Common.SelectedAccount; if (account != null) - tw.Initialize(account.GetTwitterAppToken(), account.Token, account.TokenSecret, account.Username, account.UserId); + tw.Initialize(account.GetTwitterCredential(), account.Username, account.UserId); else - tw.Initialize(TwitterAppToken.GetDefault(), "", "", "", 0L); + tw.Initialize(new TwitterCredentialNone(), "", 0L); tw.RestrictFavCheck = settings.Common.RestrictFavCheck; tw.ReadOwnPost = settings.Common.ReadOwnPost; diff --git a/OpenTween/Connection/ITwitterCredential.cs b/OpenTween/Connection/ITwitterCredential.cs new file mode 100644 index 00000000..87f5a8dc --- /dev/null +++ b/OpenTween/Connection/ITwitterCredential.cs @@ -0,0 +1,34 @@ +// 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.Net.Http; + +namespace OpenTween.Connection +{ + public interface ITwitterCredential + { + TwitterAppToken AppToken { get; } + + HttpMessageHandler CreateHttpHandler(HttpMessageHandler innerHandler); + } +} diff --git a/OpenTween/Connection/TwitterApiConnection.cs b/OpenTween/Connection/TwitterApiConnection.cs index 35a8e0b9..bfcc99b0 100644 --- a/OpenTween/Connection/TwitterApiConnection.cs +++ b/OpenTween/Connection/TwitterApiConnection.cs @@ -52,35 +52,20 @@ namespace OpenTween.Connection public bool IsDisposed { get; private set; } = false; - public string AccessToken { get; } - - public string AccessSecret { get; } - internal HttpClient Http; internal HttpClient HttpUpload; internal HttpClient HttpStreaming; - private readonly TwitterAppToken appToken; + internal ITwitterCredential Credential { get; } - public TwitterApiConnection(ApiKey consumerKey, ApiKey consumerSecret, string accessToken, string accessSecret) - : this( - new() - { - AuthType = APIAuthType.OAuth1, - OAuth1CustomConsumerKey = consumerKey, - OAuth1CustomConsumerSecret = consumerSecret, - }, - accessToken, - accessSecret - ) + public TwitterApiConnection() + : this(new TwitterCredentialNone()) { } - public TwitterApiConnection(TwitterAppToken appToken, string accessToken, string accessSecret) + public TwitterApiConnection(ITwitterCredential credential) { - this.appToken = appToken; - this.AccessToken = accessToken; - this.AccessSecret = accessSecret; + this.Credential = credential; this.InitializeHttpClients(); Networking.WebProxyChanged += this.Networking_WebProxyChanged; @@ -89,12 +74,12 @@ namespace OpenTween.Connection [MemberNotNull(nameof(Http), nameof(HttpUpload), nameof(HttpStreaming))] private void InitializeHttpClients() { - this.Http = InitializeHttpClient(this.appToken, this.AccessToken, this.AccessSecret); + this.Http = InitializeHttpClient(this.Credential); - this.HttpUpload = InitializeHttpClient(this.appToken, this.AccessToken, this.AccessSecret); + this.HttpUpload = InitializeHttpClient(this.Credential); this.HttpUpload.Timeout = Networking.UploadImageTimeout; - this.HttpStreaming = InitializeHttpClient(this.appToken, this.AccessToken, this.AccessSecret, disableGzip: true); + this.HttpStreaming = InitializeHttpClient(this.Credential, disableGzip: true); this.HttpStreaming.Timeout = Timeout.InfiniteTimeSpan; } @@ -500,14 +485,29 @@ namespace OpenTween.Connection { var uri = new Uri(RestApiBase, authServiceProvider); - return OAuthEchoHandler.CreateHandler( - innerHandler, - uri, - this.appToken.OAuth1ConsumerKey, - this.appToken.OAuth1ConsumerSecret, - this.AccessToken, - this.AccessSecret, - realm); + if (this.Credential is TwitterCredentialOAuth1 oauthCredential) + { + return OAuthEchoHandler.CreateHandler( + innerHandler, + uri, + oauthCredential.AppToken.OAuth1ConsumerKey, + oauthCredential.AppToken.OAuth1ConsumerSecret, + oauthCredential.Token, + oauthCredential.TokenSecret, + realm); + } + else + { + // MobipictureApi クラス向けの暫定対応 + return OAuthEchoHandler.CreateHandler( + innerHandler, + uri, + ApiKey.Create(""), + ApiKey.Create(""), + "", + "", + realm); + } } public void Dispose() @@ -538,19 +538,20 @@ namespace OpenTween.Connection private void Networking_WebProxyChanged(object sender, EventArgs e) => this.InitializeHttpClients(); - public static async Task<(string Token, string TokenSecret)> GetRequestTokenAsync(TwitterAppToken appToken) + public static async Task GetRequestTokenAsync(TwitterAppToken appToken) { + var emptyCredential = new TwitterCredentialOAuth1(appToken, "", ""); var param = new Dictionary { ["oauth_callback"] = "oob", }; - var response = await GetOAuthTokenAsync(new Uri("https://api.twitter.com/oauth/request_token"), param, appToken, oauthToken: null) + var response = await GetOAuthTokenAsync(new Uri("https://api.twitter.com/oauth/request_token"), param, emptyCredential) .ConfigureAwait(false); - return (response["oauth_token"], response["oauth_token_secret"]); + return new(appToken, response["oauth_token"], response["oauth_token_secret"]); } - public static Uri GetAuthorizeUri((string Token, string TokenSecret) requestToken, string? screenName = null) + public static Uri GetAuthorizeUri(TwitterCredentialOAuth1 requestToken, string? screenName = null) { var param = new Dictionary { @@ -563,13 +564,13 @@ namespace OpenTween.Connection return new Uri("https://api.twitter.com/oauth/authorize?" + MyCommon.BuildQueryString(param)); } - public static async Task> GetAccessTokenAsync(TwitterAppToken appToken, (string Token, string TokenSecret) requestToken, string verifier) + public static async Task> GetAccessTokenAsync(TwitterCredentialOAuth1 credential, string verifier) { var param = new Dictionary { ["oauth_verifier"] = verifier, }; - var response = await GetOAuthTokenAsync(new Uri("https://api.twitter.com/oauth/access_token"), param, appToken, requestToken) + var response = await GetOAuthTokenAsync(new Uri("https://api.twitter.com/oauth/access_token"), param, credential) .ConfigureAwait(false); return response; @@ -578,14 +579,10 @@ namespace OpenTween.Connection private static async Task> GetOAuthTokenAsync( Uri uri, IDictionary param, - TwitterAppToken appToken, - (string Token, string TokenSecret)? oauthToken) + TwitterCredentialOAuth1 credential + ) { - HttpClient authorizeClient; - if (oauthToken != null) - authorizeClient = InitializeHttpClient(appToken.OAuth1ConsumerKey, appToken.OAuth1ConsumerSecret, oauthToken.Value.Token, oauthToken.Value.TokenSecret); - else - authorizeClient = InitializeHttpClient(appToken.OAuth1ConsumerKey, appToken.OAuth1ConsumerSecret, "", ""); + using var authorizeClient = InitializeHttpClient(credential); var requestUri = new Uri(uri, "?" + MyCommon.BuildQueryString(param)); @@ -617,24 +614,7 @@ namespace OpenTween.Connection } } - private static HttpClient InitializeHttpClient(ApiKey consumerKey, ApiKey consumerSecret, string accessToken, string accessSecret, bool disableGzip = false) - { - var builder = Networking.CreateHttpClientBuilder(); - - builder.SetupHttpClientHandler(x => - { - x.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache); - - if (disableGzip) - x.AutomaticDecompression = DecompressionMethods.None; - }); - - builder.AddHandler(x => new OAuthHandler(x, consumerKey, consumerSecret, accessToken, accessSecret)); - - return builder.Build(); - } - - private static HttpClient InitializeHttpClient(TwitterAppToken appToken, string accessToken, string accessSecret, bool disableGzip = false) + private static HttpClient InitializeHttpClient(ITwitterCredential credential, bool disableGzip = false) { var builder = Networking.CreateHttpClientBuilder(); @@ -646,14 +626,7 @@ namespace OpenTween.Connection x.AutomaticDecompression = DecompressionMethods.None; }); - builder.AddHandler(x => appToken.AuthType switch - { - APIAuthType.OAuth1 - => new OAuthHandler(x, appToken.OAuth1ConsumerKey, appToken.OAuth1ConsumerSecret, accessToken, accessSecret), - APIAuthType.TwitterComCookie - => new TwitterComCookieHandler(x, appToken.TwitterComCookie), - _ => throw new NotImplementedException(), - }); + builder.AddHandler(x => credential.CreateHttpHandler(x)); return builder.Build(); } diff --git a/OpenTween/Connection/TwitterCredentialCookie.cs b/OpenTween/Connection/TwitterCredentialCookie.cs new file mode 100644 index 00000000..14452e09 --- /dev/null +++ b/OpenTween/Connection/TwitterCredentialCookie.cs @@ -0,0 +1,38 @@ +// 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.Net.Http; + +namespace OpenTween.Connection +{ + public class TwitterCredentialCookie : ITwitterCredential + { + public TwitterAppToken AppToken { get; } + + public TwitterCredentialCookie(TwitterAppToken appToken) + => this.AppToken = appToken; + + public HttpMessageHandler CreateHttpHandler(HttpMessageHandler innerHandler) + => new TwitterComCookieHandler(innerHandler, this.AppToken.TwitterComCookie); + } +} diff --git a/OpenTween/Connection/TwitterCredentialNone.cs b/OpenTween/Connection/TwitterCredentialNone.cs new file mode 100644 index 00000000..67d1c86b --- /dev/null +++ b/OpenTween/Connection/TwitterCredentialNone.cs @@ -0,0 +1,36 @@ +// 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.Net.Http; + +namespace OpenTween.Connection +{ + public class TwitterCredentialNone : ITwitterCredential + { + public TwitterAppToken AppToken + => TwitterAppToken.GetDefault(); + + public HttpMessageHandler CreateHttpHandler(HttpMessageHandler innerHandler) + => innerHandler; + } +} diff --git a/OpenTween/Connection/TwitterCredentialOAuth1.cs b/OpenTween/Connection/TwitterCredentialOAuth1.cs new file mode 100644 index 00000000..298ace00 --- /dev/null +++ b/OpenTween/Connection/TwitterCredentialOAuth1.cs @@ -0,0 +1,52 @@ +// 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.Net.Http; + +namespace OpenTween.Connection +{ + public class TwitterCredentialOAuth1 : ITwitterCredential + { + public TwitterAppToken AppToken { get; } + + public string Token { get; } + + public string TokenSecret { get; } + + public TwitterCredentialOAuth1(TwitterAppToken appToken, string accessToken, string accessSecret) + { + this.AppToken = appToken; + this.Token = accessToken; + this.TokenSecret = accessSecret; + } + + public HttpMessageHandler CreateHttpHandler(HttpMessageHandler innerHandler) + => new OAuthHandler( + innerHandler, + this.AppToken.OAuth1ConsumerKey, + this.AppToken.OAuth1ConsumerSecret, + this.Token, + this.TokenSecret + ); + } +} diff --git a/OpenTween/Setting/SettingCommon.cs b/OpenTween/Setting/SettingCommon.cs index 3e9f6568..5d9f3ad7 100644 --- a/OpenTween/Setting/SettingCommon.cs +++ b/OpenTween/Setting/SettingCommon.cs @@ -398,6 +398,20 @@ namespace OpenTween }; } + public ITwitterCredential GetTwitterCredential() + { + var appToken = this.GetTwitterAppToken(); + + return appToken.AuthType switch + { + APIAuthType.OAuth1 + => new TwitterCredentialOAuth1(appToken, this.TwitterOAuth1ConsumerKey, this.TwitterOAuth1ConsumerSecret), + APIAuthType.TwitterComCookie + => new TwitterCredentialCookie(appToken), + _ => new TwitterCredentialNone(), + }; + } + private string Encrypt(string password) { if (MyCommon.IsNullOrEmpty(password)) password = ""; diff --git a/OpenTween/Tween.cs b/OpenTween/Tween.cs index 63e29883..0dc35687 100644 --- a/OpenTween/Tween.cs +++ b/OpenTween/Tween.cs @@ -2555,9 +2555,9 @@ namespace OpenTween var account = this.settings.Common.SelectedAccount; if (account != null) - this.tw.Initialize(account.GetTwitterAppToken(), account.Token, account.TokenSecret, account.Username, account.UserId); + this.tw.Initialize(account.GetTwitterCredential(), account.Username, account.UserId); else - this.tw.Initialize(TwitterAppToken.GetDefault(), "", "", "", 0L); + this.tw.Initialize(new TwitterCredentialNone(), "", 0L); this.tw.RestrictFavCheck = this.settings.Common.RestrictFavCheck; this.tw.ReadOwnPost = this.settings.Common.ReadOwnPost; diff --git a/OpenTween/Twitter.cs b/OpenTween/Twitter.cs index f100a887..48be5ba9 100644 --- a/OpenTween/Twitter.cs +++ b/OpenTween/Twitter.cs @@ -228,15 +228,14 @@ namespace OpenTween this.Api.Initialize(token, tokenSecret, userId, username); } - public void Initialize(TwitterAppToken appToken, string token, string tokenSecret, string username, long userId) + public void Initialize(ITwitterCredential credential, string username, long userId) { // OAuth認証 - if (MyCommon.IsNullOrEmpty(token) || MyCommon.IsNullOrEmpty(tokenSecret) || MyCommon.IsNullOrEmpty(username)) - { + if (credential is TwitterCredentialNone) Twitter.AccountState = MyCommon.ACCOUNT_STATE.Invalid; - } + this.ResetApiStatus(); - this.Api.Initialize(appToken, token, tokenSecret, userId, username); + this.Api.Initialize(credential, userId, username); } public async Task PostStatus(PostStatusParams param) -- 2.11.0