OSDN Git Service

OAuth2Sessionを使用したAPIアクセスに対応
authorKimura Youichi <kim.upsilon@bucyou.net>
Sun, 22 Jan 2023 10:53:30 +0000 (19:53 +0900)
committerKimura Youichi <kim.upsilon@bucyou.net>
Sun, 22 Jan 2023 11:19:40 +0000 (20:19 +0900)
OpenTween/AppendSettingDialog.cs
OpenTween/ApplicationSettings.cs
OpenTween/AuthTypeSelectDialog.cs
OpenTween/Connection/Networking.cs
OpenTween/Connection/TwitterApiConnection.cs
OpenTween/Connection/TwitterAppToken.cs
OpenTween/Connection/TwitterComCookieHandler.cs [new file with mode: 0644]
OpenTween/Setting/SettingCommon.cs

index e0377ab..fa4cc1e 100644 (file)
@@ -185,9 +185,28 @@ namespace OpenTween
                     if (appToken == null)
                         return;
 
-                    var newAccount = await this.PinAuth(appToken);
-                    if (newAccount == null)
-                        return;
+                    UserAccount newAccount;
+                    if (appToken.AuthType == APIAuthType.TwitterComCookie)
+                    {
+                        newAccount = new()
+                        {
+                            TwitterAuthType = appToken.AuthType,
+                            TwitterComCookie = appToken.TwitterComCookie,
+                        };
+
+                        using var twitterApi = new TwitterApi();
+                        twitterApi.Initialize(appToken, "", "", 0L, "");
+                        var twitterUser = await twitterApi.AccountVerifyCredentials();
+                        newAccount.UserId = twitterUser.Id;
+                        newAccount.Username = twitterUser.ScreenName;
+                    }
+                    else
+                    {
+                        var account = await this.PinAuth(appToken);
+                        if (account == null)
+                            return;
+                        newAccount = account;
+                    }
 
                     var authUserCombo = this.BasedPanel.AuthUserCombo;
 
index d7c7a46..8d3522e 100644 (file)
@@ -127,6 +127,11 @@ namespace OpenTween
         /// </summary>
         public static readonly ApiKey TwitterConsumerSecret = ApiKey.Create("%e%p93BdDzlwbYIC5Ych/47OQ==%xYZTCYaBxzS4An3o7Qcigjp9QMtu5vi5iEAW/sNgoOoAUyuHJRPP3Ovs20ZV2fAYKxUDiu76dxLfObwI7QjSRA==%YEruRDAQdbJzO+y6kn7+U/uIyIyNra/8Ulo+L6KJcWA=");
 
+        /// <summary>
+        /// <see cref="OpenTween.Connection.TwitterComCookieHandler"/> で使用する Bearer token
+        /// </summary>
+        public static readonly ApiKey TwitterComBearerToken = ApiKey.Create("%e%D2/mWPJwkdhuxnXCCnPiAw==%mAH3yTqmvpdf7Zukmlan0yXhUoAuVTo0fBjOsI3RXwP3/NpS2V4/UmcwGy6aZPEl05wDrL9e1BCKdfbB4+cvQUasEGWU1RRW4KsLyzFMX+nqnvP6cgl2Oa7ek0KDT5xShl+gnOCq03dWBPY0uKrLZA==%5+REZK8MSrAzlMM4C6oph/rIJje8YqSDPOiHFiSOyh4=");
+
         // =====================================================================
         // Foursquare
         // https://developer.foursquare.com/ から取得できます。
index 50b2efa..a23767e 100644 (file)
@@ -53,6 +53,14 @@ namespace OpenTween
                     OAuth1ConsumerSecret = ApiKey.Create(this.OAuth1ConsumerSecretTextBox.Text),
                 };
             }
+            else if (this.UseTwitterComCookieRadioButton.Checked)
+            {
+                result = new()
+                {
+                    AuthType = APIAuthType.TwitterComCookie,
+                    TwitterComCookie = this.TwitterComCookieTextBox.Text,
+                };
+            }
             else
             {
                 return;
index cd7db98..b75013c 100644 (file)
@@ -141,6 +141,7 @@ namespace OpenTween.Connection
         {
             var handler = new WebRequestHandler
             {
+                UseCookies = false,
                 AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
             };
 
index 3d57005..21d664c 100644 (file)
@@ -594,6 +594,8 @@ namespace OpenTween.Connection
             {
                 APIAuthType.OAuth1
                     => new OAuthHandler(innerHandler, appToken.OAuth1ConsumerKey, appToken.OAuth1ConsumerSecret, accessToken, accessSecret),
+                APIAuthType.TwitterComCookie
+                    => new TwitterComCookieHandler(innerHandler, appToken.TwitterComCookie),
                 _ => throw new NotImplementedException(),
             };
 
index c37a6a0..b762ab7 100644 (file)
@@ -38,6 +38,8 @@ namespace OpenTween.Connection
 
         public ApiKey OAuth1ConsumerSecret { get; set; } = ApiKey.Create("");
 
+        public string TwitterComCookie { get; set; } = "";
+
         public static TwitterAppToken GetDefault()
         {
             return new()
diff --git a/OpenTween/Connection/TwitterComCookieHandler.cs b/OpenTween/Connection/TwitterComCookieHandler.cs
new file mode 100644 (file)
index 0000000..9f33052
--- /dev/null
@@ -0,0 +1,81 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2023 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#nullable enable
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace OpenTween.Connection
+{
+    public class TwitterComCookieHandler : DelegatingHandler
+    {
+        public string RawCookie { get; private set; } = "";
+
+        public string CsrfToken { get; private set; } = "";
+
+        public string AuthToken { get; private set; } = "";
+
+        public TwitterComCookieHandler(HttpMessageHandler innerHandler, string rawCookie)
+            : base(innerHandler)
+        {
+            this.SetCookie(rawCookie);
+        }
+
+        public void SetCookie(string rawCookie)
+        {
+            this.RawCookie = rawCookie;
+
+            var pairs = rawCookie.Split(';')
+                .Select(x => x.Trim().Split(new[] { '=' }, 2))
+                .Where(x => x.Length == 2)
+                .Select(x => new KeyValuePair<string, string>(x[0], x[1]));
+
+            string? GetValue(string key)
+                => pairs.Where(x => x.Key == key).Select(x => x.Value).FirstOrDefault();
+
+            this.CsrfToken = GetValue("ct0") ?? "";
+            this.AuthToken = GetValue("auth_token") ?? "";
+        }
+
+        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+        {
+            if (!MyCommon.IsNullOrEmpty(this.RawCookie))
+            {
+                request.Headers.Add("x-twitter-auth-type", "OAuth2Session");
+                request.Headers.Add("x-csrf-token", this.CsrfToken);
+                request.Headers.Add("cookie", this.GenerateCookieValue());
+                request.Headers.Authorization = new("Bearer", ApplicationSettings.TwitterComBearerToken.Value);
+            }
+
+            return await base.SendAsync(request, cancellationToken)
+                .ConfigureAwait(false);
+        }
+
+        private string GenerateCookieValue()
+            => $"ct0={this.CsrfToken}; auth_token={this.AuthToken}";
+    }
+}
index ffee8b4..ed6ae8e 100644 (file)
@@ -366,6 +366,15 @@ namespace OpenTween
             set => this.TwitterOAuth1ConsumerSecret = this.Decrypt(value);
         }
 
+        [XmlIgnore]
+        public string TwitterComCookie { get; set; } = "";
+
+        public string TwitterComCookieEncrypted
+        {
+            get => this.Encrypt(this.TwitterComCookie);
+            set => this.TwitterComCookie = this.Decrypt(value);
+        }
+
         public string Token = "";
 
         [XmlIgnore]
@@ -384,6 +393,7 @@ namespace OpenTween
                 AuthType = this.TwitterAuthType,
                 OAuth1ConsumerKey = ApiKey.Create(this.TwitterOAuth1ConsumerKey),
                 OAuth1ConsumerSecret = ApiKey.Create(this.TwitterOAuth1ConsumerSecret),
+                TwitterComCookie = this.TwitterComCookie,
             };
         }
 
@@ -431,5 +441,6 @@ namespace OpenTween
     public enum APIAuthType
     {
         OAuth1,
+        TwitterComCookie,
     }
 }
\ No newline at end of file