diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 1df31a34d..451e9a19a 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -4,6 +4,7 @@
* NEW: Twemoji 15.1.0 に対応しました
- Unicode 15.1 で追加された絵文字が表示されるようになります
* CHG: 設定画面でのアカウント一覧の表示形式を変更
+ * CHG: 新規アカウント追加時のダイアログの構成を変更
* CHG: 新規タブの初回に読み込まれた発言を既読状態にする(起動時の初回の読み込みと同じ動作となる)
* CHG: ドメインに x.com が使われている引用ツイートの展開・投稿に対応
* FIX: 発言の削除中にタブを切り替えるとエラーが発生する不具合を修正 (thx @Tan90909090!)
diff --git a/OpenTween.Tests/AuthDialogTest.cs b/OpenTween.Tests/SocialProtocol/Twitter/TwitterCookieSetupDialogTest.cs
similarity index 77%
rename from OpenTween.Tests/AuthDialogTest.cs
rename to OpenTween.Tests/SocialProtocol/Twitter/TwitterCookieSetupDialogTest.cs
index 58d5ce4f9..ce33b07a1 100644
--- a/OpenTween.Tests/AuthDialogTest.cs
+++ b/OpenTween.Tests/SocialProtocol/Twitter/TwitterCookieSetupDialogTest.cs
@@ -1,5 +1,5 @@
// OpenTween - Client of Twitter
-// Copyright (c) 2023 kim_upsilon (@kim_upsilon)
+// Copyright (c) 2024 kim_upsilon (@kim_upsilon)
// All rights reserved.
//
// This file is part of OpenTween.
@@ -19,21 +19,16 @@
// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
// Boston, MA 02110-1301, USA.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using Xunit;
-namespace OpenTween
+namespace OpenTween.SocialProtocol.Twitter
{
- public class AuthDialogTest
+ public class TwitterCookieSetupDialogTest
{
[WinFormsFact]
public void Initialize_Test()
{
- using var dialog = new AuthDialog();
+ using var dialog = new TwitterCookieSetupDialog();
}
}
}
diff --git a/OpenTween.Tests/AuthTypeSelectDialogTest.cs b/OpenTween.Tests/SocialProtocol/Twitter/TwitterOAuthSetupDialogTest.cs
similarity index 76%
rename from OpenTween.Tests/AuthTypeSelectDialogTest.cs
rename to OpenTween.Tests/SocialProtocol/Twitter/TwitterOAuthSetupDialogTest.cs
index 0e897711c..faf79adb8 100644
--- a/OpenTween.Tests/AuthTypeSelectDialogTest.cs
+++ b/OpenTween.Tests/SocialProtocol/Twitter/TwitterOAuthSetupDialogTest.cs
@@ -1,5 +1,5 @@
// OpenTween - Client of Twitter
-// Copyright (c) 2023 kim_upsilon (@kim_upsilon)
+// Copyright (c) 2024 kim_upsilon (@kim_upsilon)
// All rights reserved.
//
// This file is part of OpenTween.
@@ -19,21 +19,16 @@
// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
// Boston, MA 02110-1301, USA.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using Xunit;
-namespace OpenTween
+namespace OpenTween.SocialProtocol.Twitter
{
- public class AuthTypeSelectDialogTest
+ public class TwitterOAuthSetupDialogTest
{
[WinFormsFact]
public void Initialize_Test()
{
- using var dialog = new AuthTypeSelectDialog();
+ using var dialog = new TwitterOAuthSetupDialog();
}
}
}
diff --git a/OpenTween/AppendSettingDialog.cs b/OpenTween/AppendSettingDialog.cs
index 9f0939a51..435e76257 100644
--- a/OpenTween/AppendSettingDialog.cs
+++ b/OpenTween/AppendSettingDialog.cs
@@ -32,7 +32,6 @@
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
-using OpenTween.Api;
using OpenTween.Connection;
using OpenTween.Models;
using OpenTween.Setting.Panel;
@@ -47,7 +46,8 @@ public AppendSettingDialog()
{
this.InitializeComponent();
- this.BasedPanel.AddAccountButton.Click += this.AddAccountButton_Click;
+ this.BasedPanel.ApplyNetworkSettings = this.ApplyNetworkSettings;
+ this.BasedPanel.OpenInBrowser = this.OpenInBrowser;
this.GetPeriodPanel.CheckPostAndGet.CheckedChanged += this.CheckPostAndGet_CheckedChanged;
this.ActionPanel.UReadMng.CheckedChanged += this.UReadMng_CheckedChanged;
@@ -166,60 +166,6 @@ private void UReadMng_CheckedChanged(object sender, EventArgs e)
}
}
- private async void AddAccountButton_Click(object sender, EventArgs e)
- {
- using (ControlTransaction.Disabled(this.BasedPanel.AddAccountButton))
- {
- try
- {
- this.ApplyNetworkSettings();
-
- var appToken = this.SelectAuthType();
- if (appToken == null)
- return;
-
- UserAccount newAccount;
- if (appToken.AuthType == APIAuthType.TwitterComCookie)
- {
- newAccount = new()
- {
- TwitterAuthType = appToken.AuthType,
- TwitterComCookie = appToken.TwitterComCookie,
- };
-
- using var twitterApi = new TwitterApi();
- using var apiConnection = new TwitterApiConnection(new TwitterCredentialCookie(appToken), new());
- twitterApi.Initialize(apiConnection);
- var twitterUser = await twitterApi.AccountVerifyCredentials();
- newAccount.UserId = twitterUser.IdStr;
- newAccount.Username = twitterUser.ScreenName;
- }
- else
- {
- var account = await this.PinAuth(appToken);
- if (account == null)
- return;
- newAccount = account;
- }
-
- this.BasedPanel.AddAccount(newAccount);
-
- MessageBox.Show(
- this,
- Properties.Resources.AuthorizeButton_Click1,
- "Authenticate",
- MessageBoxButtons.OK);
- }
- catch (TwitterApiException ex)
- {
- var message = Properties.Resources.AuthorizeButton_Click2 + Environment.NewLine +
- string.Join(Environment.NewLine, ex.LongMessages);
-
- MessageBox.Show(this, message, "Authenticate", MessageBoxButtons.OK);
- }
- }
- }
-
///
/// 現在設定画面に入力されているネットワーク関係の設定を適用します
///
@@ -250,40 +196,10 @@ public void ApplyNetworkSettings()
TwitterApiConnection.RestApiHost = this.ConnectionPanel.TwitterAPIText.Text.Trim();
}
- private TwitterAppToken? SelectAuthType()
- {
- using var dialog = new AuthTypeSelectDialog();
-
- var ret = dialog.ShowDialog(this);
- if (ret != DialogResult.OK)
- return null;
-
- return dialog.Result;
- }
-
- private async Task PinAuth(TwitterAppToken appToken)
+ private async Task OpenInBrowser(IWin32Window? owner, Uri uri)
{
- var requestToken = await TwitterApiConnection.GetRequestTokenAsync(appToken);
-
- var pinPageUrl = TwitterApiConnection.GetAuthorizeUri(requestToken);
-
var browserPath = this.ActionPanel.BrowserPathText.Text;
- var pin = AuthDialog.DoAuth(this, pinPageUrl, browserPath);
- if (MyCommon.IsNullOrEmpty(pin))
- return null; // キャンセルされた場合
-
- var accessTokenResponse = await TwitterApiConnection.GetAccessTokenAsync(requestToken, pin);
-
- return new UserAccount
- {
- TwitterAuthType = appToken.AuthType,
- TwitterOAuth1ConsumerKey = appToken.OAuth1CustomConsumerKey?.Value ?? "",
- TwitterOAuth1ConsumerSecret = appToken.OAuth1CustomConsumerSecret?.Value ?? "",
- Username = accessTokenResponse["screen_name"],
- UserId = accessTokenResponse["user_id"],
- Token = accessTokenResponse["oauth_token"],
- TokenSecret = accessTokenResponse["oauth_token_secret"],
- };
+ await MyCommon.OpenInBrowserAsync(owner, browserPath, uri);
}
private void CheckPostAndGet_CheckedChanged(object sender, EventArgs e)
diff --git a/OpenTween/AuthDialog.Designer.cs b/OpenTween/AuthDialog.Designer.cs
deleted file mode 100644
index d4479fe9e..000000000
--- a/OpenTween/AuthDialog.Designer.cs
+++ /dev/null
@@ -1,140 +0,0 @@
-namespace OpenTween
-{
- partial class AuthDialog
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.components = new System.ComponentModel.Container();
- System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AuthDialog));
- this.label1 = new System.Windows.Forms.Label();
- this.AuthLinkLabel = new System.Windows.Forms.LinkLabel();
- this.contextMenuLinkLabel = new System.Windows.Forms.ContextMenuStrip(this.components);
- this.MenuItemCopyURL = new System.Windows.Forms.ToolStripMenuItem();
- this.label2 = new System.Windows.Forms.Label();
- this.PinTextBox = new System.Windows.Forms.TextBox();
- this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
- this.CancelBtn = new System.Windows.Forms.Button();
- this.OKBtn = new System.Windows.Forms.Button();
- this.contextMenuLinkLabel.SuspendLayout();
- this.tableLayoutPanel1.SuspendLayout();
- this.SuspendLayout();
- //
- // label1
- //
- resources.ApplyResources(this.label1, "label1");
- this.label1.Name = "label1";
- //
- // AuthLinkLabel
- //
- this.AuthLinkLabel.AutoEllipsis = true;
- this.AuthLinkLabel.ContextMenuStrip = this.contextMenuLinkLabel;
- resources.ApplyResources(this.AuthLinkLabel, "AuthLinkLabel");
- this.AuthLinkLabel.Name = "AuthLinkLabel";
- this.AuthLinkLabel.TabStop = true;
- this.AuthLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.AuthLinkLabel_LinkClicked);
- //
- // contextMenuLinkLabel
- //
- this.contextMenuLinkLabel.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.MenuItemCopyURL});
- this.contextMenuLinkLabel.Name = "contextMenuLinkLabel";
- resources.ApplyResources(this.contextMenuLinkLabel, "contextMenuLinkLabel");
- //
- // MenuItemCopyURL
- //
- this.MenuItemCopyURL.Name = "MenuItemCopyURL";
- resources.ApplyResources(this.MenuItemCopyURL, "MenuItemCopyURL");
- this.MenuItemCopyURL.Click += new System.EventHandler(this.MenuItemCopyURL_Click);
- //
- // label2
- //
- resources.ApplyResources(this.label2, "label2");
- this.label2.Name = "label2";
- //
- // PinTextBox
- //
- resources.ApplyResources(this.PinTextBox, "PinTextBox");
- this.PinTextBox.Name = "PinTextBox";
- //
- // tableLayoutPanel1
- //
- resources.ApplyResources(this.tableLayoutPanel1, "tableLayoutPanel1");
- this.tableLayoutPanel1.Controls.Add(this.CancelBtn, 1, 0);
- this.tableLayoutPanel1.Controls.Add(this.OKBtn, 0, 0);
- this.tableLayoutPanel1.Name = "tableLayoutPanel1";
- //
- // CancelBtn
- //
- resources.ApplyResources(this.CancelBtn, "CancelBtn");
- this.CancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.CancelBtn.Name = "CancelBtn";
- this.CancelBtn.UseVisualStyleBackColor = true;
- //
- // OKBtn
- //
- resources.ApplyResources(this.OKBtn, "OKBtn");
- this.OKBtn.DialogResult = System.Windows.Forms.DialogResult.OK;
- this.OKBtn.Name = "OKBtn";
- this.OKBtn.UseVisualStyleBackColor = true;
- //
- // AuthDialog
- //
- this.AcceptButton = this.OKBtn;
- resources.ApplyResources(this, "$this");
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.CancelButton = this.CancelBtn;
- this.Controls.Add(this.tableLayoutPanel1);
- this.Controls.Add(this.PinTextBox);
- this.Controls.Add(this.label2);
- this.Controls.Add(this.AuthLinkLabel);
- this.Controls.Add(this.label1);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
- this.MaximizeBox = false;
- this.Name = "AuthDialog";
- this.ShowIcon = false;
- this.ShowInTaskbar = false;
- this.contextMenuLinkLabel.ResumeLayout(false);
- this.tableLayoutPanel1.ResumeLayout(false);
- this.tableLayoutPanel1.PerformLayout();
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.Label label1;
- private System.Windows.Forms.LinkLabel AuthLinkLabel;
- private System.Windows.Forms.Label label2;
- private System.Windows.Forms.TextBox PinTextBox;
- private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
- private System.Windows.Forms.Button CancelBtn;
- private System.Windows.Forms.Button OKBtn;
- private System.Windows.Forms.ContextMenuStrip contextMenuLinkLabel;
- private System.Windows.Forms.ToolStripMenuItem MenuItemCopyURL;
- }
-}
\ No newline at end of file
diff --git a/OpenTween/AuthDialog.cs b/OpenTween/AuthDialog.cs
deleted file mode 100644
index 292656f94..000000000
--- a/OpenTween/AuthDialog.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-// OpenTween - Client of Twitter
-// Copyright (c) 2012 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.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Windows.Forms;
-
-namespace OpenTween
-{
- ///
- /// OAuth認証のPINコードの入力を求めるダイアログ
- ///
- public partial class AuthDialog : OTBaseForm
- {
- public AuthDialog()
- {
- this.InitializeComponent();
-
- // PinTextBox のフォントを OTBaseForm.GlobalFont に変更
- this.PinTextBox.Font = this.ReplaceToGlobalFont(this.PinTextBox.Font);
- }
-
- public string AuthUrl
- {
- get => this.AuthLinkLabel.Text;
- set => this.AuthLinkLabel.Text = value;
- }
-
- public string Pin
- {
- get => this.PinTextBox.Text.Trim();
- set => this.PinTextBox.Text = value;
- }
-
- public string? BrowserPath { get; set; }
-
- private async void AuthLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
- {
- // 右クリックの場合は無視する
- if (e.Button == MouseButtons.Right)
- return;
-
- this.AuthLinkLabel.LinkVisited = true;
- await MyCommon.OpenInBrowserAsync(this, this.BrowserPath, this.AuthUrl);
- }
-
- private void MenuItemCopyURL_Click(object sender, EventArgs e)
- {
- try
- {
- Clipboard.SetText(this.AuthUrl);
- }
- catch (ExternalException)
- {
- }
- }
-
- ///
- /// 指定されたURLにユーザーがアクセスするように指示してPINを入力させるだけ
- ///
- /// 親ウィンドウ
- /// 認証URL
- /// Webブラウザのパス
- /// PIN文字列
- public static string? DoAuth(IWin32Window owner, Uri authUri, string? browserPath)
- {
- using var dialog = new AuthDialog();
- dialog.AuthUrl = authUri.AbsoluteUri;
- dialog.BrowserPath = browserPath;
-
- dialog.ShowDialog(owner);
-
- if (dialog.DialogResult == DialogResult.OK)
- return dialog.Pin;
- else
- return null;
- }
- }
-}
diff --git a/OpenTween/AuthDialog.resx b/OpenTween/AuthDialog.resx
deleted file mode 100644
index 9885a533b..000000000
--- a/OpenTween/AuthDialog.resx
+++ /dev/null
@@ -1,96 +0,0 @@
-
- text/microsoft-resx
- 2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
-
-
- 96, 96
- 444, 244
- True
- CenterScreen
- AuthDialog
- AuthDialog
- OpenTween.OTBaseForm, OpenTween, Version=2.4.3.1, Culture=neutral, PublicKeyToken=null
- AuthLinkLabel
- $this
- System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 4
- CancelBtn
- tableLayoutPanel1
- System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 0
- contextMenuLinkLabel
- System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- label1
- $this
- System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 5
- label2
- $this
- System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 3
- MenuItemCopyURL
- System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- OKBtn
- tableLayoutPanel1
- System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 1
- PinTextBox
- $this
- System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 2
- tableLayoutPanel1
- $this
- System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 1
- 24, 69
- 15, 15, 15, 15
- 396, 15
- 1
- linkLabel1
- True
- 84, 3
- 86, 25
- 1
- キャンセル (&C)
- 148, 26
- 17, 17
- True
- 12, 24
- 3, 15, 3, 15
- 352, 12
- 0
- 下記のURLにブラウザでアクセスし、内容を確認の上で認証を行って下さい:
-
- True
- 12, 114
- 3, 15, 3, 15
- 228, 12
- 2
- 認証後に表示されるPINコードを入力して下さい
- 147, 22
- URLをコピー (&C)
- True
- 3, 3
- 75, 25
- 0
- &OK
- PINコード
- Top, Left, Right
- MS UI Gothic, 24pt
- 127, 147
- 190, 39
- 3
- Center
- Bottom, Right
- True
- 2
- <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="CancelBtn" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="OKBtn" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="AutoSize,0,AutoSize,0" /><Rows Styles="Percent,100" /></TableLayoutSettings>
- 259, 201
- 1
- 173, 31
- 4
-
diff --git a/OpenTween/AuthTypeSelectDialog.Designer.cs b/OpenTween/AuthTypeSelectDialog.Designer.cs
deleted file mode 100644
index b97c22189..000000000
--- a/OpenTween/AuthTypeSelectDialog.Designer.cs
+++ /dev/null
@@ -1,150 +0,0 @@
-namespace OpenTween
-{
- partial class AuthTypeSelectDialog
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AuthTypeSelectDialog));
- this.label1 = new System.Windows.Forms.Label();
- this.AuthByOAuth2RadioButton = new System.Windows.Forms.RadioButton();
- this.AuthByOAuth1BuiltinKeyRadioButton = new System.Windows.Forms.RadioButton();
- this.AuthByOAuth1RadioButton = new System.Windows.Forms.RadioButton();
- this.label2 = new System.Windows.Forms.Label();
- this.OAuth1ConsumerKeyTextBox = new System.Windows.Forms.TextBox();
- this.label3 = new System.Windows.Forms.Label();
- this.OAuth1ConsumerSecretTextBox = new System.Windows.Forms.TextBox();
- this.UseTwitterComCookieRadioButton = new System.Windows.Forms.RadioButton();
- this.TwitterComCookieTextBox = new System.Windows.Forms.TextBox();
- this.OKButton = new System.Windows.Forms.Button();
- this.SuspendLayout();
- //
- // label1
- //
- resources.ApplyResources(this.label1, "label1");
- this.label1.Name = "label1";
- //
- // AuthByOAuth2RadioButton
- //
- resources.ApplyResources(this.AuthByOAuth2RadioButton, "AuthByOAuth2RadioButton");
- this.AuthByOAuth2RadioButton.Name = "AuthByOAuth2RadioButton";
- this.AuthByOAuth2RadioButton.TabStop = true;
- this.AuthByOAuth2RadioButton.UseVisualStyleBackColor = true;
- //
- // AuthByOAuth1BuiltinKeyRadioButton
- //
- resources.ApplyResources(this.AuthByOAuth1BuiltinKeyRadioButton, "AuthByOAuth1BuiltinKeyRadioButton");
- this.AuthByOAuth1BuiltinKeyRadioButton.Name = "AuthByOAuth1BuiltinKeyRadioButton";
- this.AuthByOAuth1BuiltinKeyRadioButton.TabStop = true;
- this.AuthByOAuth1BuiltinKeyRadioButton.UseVisualStyleBackColor = true;
- //
- // AuthByOAuth1RadioButton
- //
- resources.ApplyResources(this.AuthByOAuth1RadioButton, "AuthByOAuth1RadioButton");
- this.AuthByOAuth1RadioButton.Name = "AuthByOAuth1RadioButton";
- this.AuthByOAuth1RadioButton.TabStop = true;
- this.AuthByOAuth1RadioButton.UseVisualStyleBackColor = true;
- //
- // label2
- //
- resources.ApplyResources(this.label2, "label2");
- this.label2.Name = "label2";
- //
- // OAuth1ConsumerKeyTextBox
- //
- resources.ApplyResources(this.OAuth1ConsumerKeyTextBox, "OAuth1ConsumerKeyTextBox");
- this.OAuth1ConsumerKeyTextBox.Name = "OAuth1ConsumerKeyTextBox";
- //
- // label3
- //
- resources.ApplyResources(this.label3, "label3");
- this.label3.Name = "label3";
- //
- // OAuth1ConsumerSecretTextBox
- //
- resources.ApplyResources(this.OAuth1ConsumerSecretTextBox, "OAuth1ConsumerSecretTextBox");
- this.OAuth1ConsumerSecretTextBox.Name = "OAuth1ConsumerSecretTextBox";
- //
- // UseTwitterComCookieRadioButton
- //
- resources.ApplyResources(this.UseTwitterComCookieRadioButton, "UseTwitterComCookieRadioButton");
- this.UseTwitterComCookieRadioButton.Name = "UseTwitterComCookieRadioButton";
- this.UseTwitterComCookieRadioButton.TabStop = true;
- this.UseTwitterComCookieRadioButton.UseVisualStyleBackColor = true;
- //
- // TwitterComCookieTextBox
- //
- resources.ApplyResources(this.TwitterComCookieTextBox, "TwitterComCookieTextBox");
- this.TwitterComCookieTextBox.Name = "TwitterComCookieTextBox";
- //
- // OKButton
- //
- resources.ApplyResources(this.OKButton, "OKButton");
- this.OKButton.Name = "OKButton";
- this.OKButton.UseVisualStyleBackColor = true;
- this.OKButton.Click += new System.EventHandler(this.OKButton_Click);
- //
- // AuthTypeSelectDialog
- //
- this.AcceptButton = this.OKButton;
- resources.ApplyResources(this, "$this");
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.Controls.Add(this.label1);
- this.Controls.Add(this.AuthByOAuth2RadioButton);
- this.Controls.Add(this.AuthByOAuth1BuiltinKeyRadioButton);
- this.Controls.Add(this.AuthByOAuth1RadioButton);
- this.Controls.Add(this.label2);
- this.Controls.Add(this.OAuth1ConsumerKeyTextBox);
- this.Controls.Add(this.label3);
- this.Controls.Add(this.OAuth1ConsumerSecretTextBox);
- this.Controls.Add(this.UseTwitterComCookieRadioButton);
- this.Controls.Add(this.TwitterComCookieTextBox);
- this.Controls.Add(this.OKButton);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
- this.MaximizeBox = false;
- this.Name = "AuthTypeSelectDialog";
- this.ShowIcon = false;
- this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.Label label1;
- private System.Windows.Forms.RadioButton AuthByOAuth2RadioButton;
- private System.Windows.Forms.RadioButton AuthByOAuth1BuiltinKeyRadioButton;
- private System.Windows.Forms.RadioButton AuthByOAuth1RadioButton;
- private System.Windows.Forms.Label label2;
- private System.Windows.Forms.TextBox OAuth1ConsumerKeyTextBox;
- private System.Windows.Forms.Label label3;
- private System.Windows.Forms.TextBox OAuth1ConsumerSecretTextBox;
- private System.Windows.Forms.RadioButton UseTwitterComCookieRadioButton;
- private System.Windows.Forms.TextBox TwitterComCookieTextBox;
- private System.Windows.Forms.Button OKButton;
- }
-}
\ No newline at end of file
diff --git a/OpenTween/AuthTypeSelectDialog.cs b/OpenTween/AuthTypeSelectDialog.cs
deleted file mode 100644
index 0961b9803..000000000
--- a/OpenTween/AuthTypeSelectDialog.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-// 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.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using OpenTween.Connection;
-
-namespace OpenTween
-{
- public partial class AuthTypeSelectDialog : OTBaseForm
- {
- public TwitterAppToken? Result { get; private set; }
-
- public AuthTypeSelectDialog()
- => this.InitializeComponent();
-
- private void OKButton_Click(object sender, EventArgs e)
- {
- TwitterAppToken result;
- if (this.AuthByOAuth1BuiltinKeyRadioButton.Checked)
- {
- result = TwitterAppToken.GetDefault();
- }
- else if (this.AuthByOAuth1RadioButton.Checked)
- {
- var consumerKey = this.OAuth1ConsumerKeyTextBox.Text;
- var consumerSecret = this.OAuth1ConsumerSecretTextBox.Text;
- result = new()
- {
- AuthType = APIAuthType.OAuth1,
- OAuth1CustomConsumerKey = MyCommon.IsNullOrEmpty(consumerKey) ? null : ApiKey.Create(consumerKey),
- OAuth1CustomConsumerSecret = MyCommon.IsNullOrEmpty(consumerSecret) ? null : ApiKey.Create(consumerSecret),
- };
- }
- else if (this.UseTwitterComCookieRadioButton.Checked)
- {
- result = new()
- {
- AuthType = APIAuthType.TwitterComCookie,
- TwitterComCookie = this.TwitterComCookieTextBox.Text,
- };
- }
- else
- {
- return;
- }
- this.DialogResult = DialogResult.OK;
- this.Result = result;
- }
- }
-}
diff --git a/OpenTween/AuthTypeSelectDialog.en.resx b/OpenTween/AuthTypeSelectDialog.en.resx
deleted file mode 100644
index a8fd37374..000000000
--- a/OpenTween/AuthTypeSelectDialog.en.resx
+++ /dev/null
@@ -1,18 +0,0 @@
-
- text/microsoft-resx
- 2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- 284, 16
- Use OAuth 1.0a (with OpenTween built-in API key)
- 103, 16
- Use OAuth 1.0a
- 215, 16
- Use OAuth 2.0 (Not implemented yet)
- 185, 12
- Choose how to access Twitter API:
- 232, 16
- Use cookie of twitter.com (Experimental)
-
diff --git a/OpenTween/AuthTypeSelectDialog.resx b/OpenTween/AuthTypeSelectDialog.resx
deleted file mode 100644
index 35839df3d..000000000
--- a/OpenTween/AuthTypeSelectDialog.resx
+++ /dev/null
@@ -1,114 +0,0 @@
-
- text/microsoft-resx
- 2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
-
-
- 96, 96
- 455, 304
- True
- AuthTypeSelectDialog
- OpenTween.OTBaseForm, OpenTween, Version=3.4.0.1, Culture=neutral, PublicKeyToken=null
- AuthByOAuth1BuiltinKeyRadioButton
- $this
- System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 2
- AuthByOAuth1RadioButton
- $this
- System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 3
- AuthByOAuth2RadioButton
- $this
- System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 1
- label1
- $this
- System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 0
- label2
- $this
- System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 4
- label3
- $this
- System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 6
- OAuth1ConsumerKeyTextBox
- $this
- System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 5
- OAuth1ConsumerSecretTextBox
- $this
- System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 7
- OKButton
- $this
- System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 10
- TwitterComCookieTextBox
- $this
- System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 9
- UseTwitterComCookieRadioButton
- $this
- System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 8
- True
- NoControl
- 15, 60
- 287, 16
- 2
- OAuth 1.0a を使用する(OpenTweenのAPIキーを使用)
- True
- 15, 82
- 135, 16
- 3
- OAuth 1.0a を使用する
- True
- False
- 15, 38
- 177, 16
- 1
- OAuth 2.0 を使用する(未実装)
- True
- 13, 13
- 3, 0, 3, 10
- 238, 12
- 0
- Twitter API にアクセスする方法を選択して下さい:
- True
- 29, 104
- 20, 3, 3, 3
- 132, 12
- 4
- Consumer Key (API Key)
- True
- 29, 147
- 3, 3, 3, 3
- 160, 12
- 6
- Consumer Secret (API Secret)
- 31, 122
- 400, 19
- 5
- 31, 165
- 400, 19
- 7
- Bottom, Right
- 368, 269
- 75, 23
- 10
- OK
- 31, 213
- True
- 400, 50
- 9
- True
- 15, 191
- 236, 16
- 8
- twitter.com の Cookie を使用する(実験的)
-
diff --git a/OpenTween/OpenTween.csproj b/OpenTween/OpenTween.csproj
index f505d8aa3..d1fad48eb 100644
--- a/OpenTween/OpenTween.csproj
+++ b/OpenTween/OpenTween.csproj
@@ -83,12 +83,6 @@
AppendSettingDialog.cs
-
- Form
-
-
- AuthDialog.cs
-
Form
@@ -340,12 +334,6 @@
ApiInfoDialog.cs
-
- AuthDialog.cs
-
-
- AuthDialog.cs
-
PublicSearchHeaderPanel.cs
diff --git a/OpenTween/Setting/Panel/BasedPanel.Designer.cs b/OpenTween/Setting/Panel/BasedPanel.Designer.cs
index a111e990f..2aa8e5bb5 100644
--- a/OpenTween/Setting/Panel/BasedPanel.Designer.cs
+++ b/OpenTween/Setting/Panel/BasedPanel.Designer.cs
@@ -28,6 +28,7 @@ protected override void Dispose(bool disposing)
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BasedPanel));
this.AccountListLabel = new System.Windows.Forms.Label();
this.AccountsListBox = new System.Windows.Forms.ListBox();
@@ -35,6 +36,7 @@ private void InitializeComponent()
this.RemoveAccountButton = new System.Windows.Forms.Button();
this.MakePrimaryButton = new System.Windows.Forms.Button();
this.panel1 = new System.Windows.Forms.Panel();
+ this.contextMenuAddAccount = new System.Windows.Forms.ContextMenuStrip(this.components);
this.panel1.SuspendLayout();
this.SuspendLayout();
//
@@ -54,6 +56,7 @@ private void InitializeComponent()
resources.ApplyResources(this.AddAccountButton, "AddAccountButton");
this.AddAccountButton.Name = "AddAccountButton";
this.AddAccountButton.UseVisualStyleBackColor = true;
+ this.AddAccountButton.Click += new System.EventHandler(this.AddAccountButton_Click);
//
// RemoveAccountButton
//
@@ -79,6 +82,11 @@ private void InitializeComponent()
resources.ApplyResources(this.panel1, "panel1");
this.panel1.Name = "panel1";
//
+ // contextMenuAddAccount
+ //
+ this.contextMenuAddAccount.Name = "contextMenuAddAccount";
+ resources.ApplyResources(this.contextMenuAddAccount, "contextMenuAddAccount");
+ //
// BasedPanel
//
resources.ApplyResources(this, "$this");
@@ -98,5 +106,6 @@ private void InitializeComponent()
internal System.Windows.Forms.Button RemoveAccountButton;
internal System.Windows.Forms.Button MakePrimaryButton;
private System.Windows.Forms.Panel panel1;
+ private System.Windows.Forms.ContextMenuStrip contextMenuAddAccount;
}
}
diff --git a/OpenTween/Setting/Panel/BasedPanel.cs b/OpenTween/Setting/Panel/BasedPanel.cs
index 7b9370a69..042b27b66 100644
--- a/OpenTween/Setting/Panel/BasedPanel.cs
+++ b/OpenTween/Setting/Panel/BasedPanel.cs
@@ -30,6 +30,9 @@
using System.ComponentModel;
using System.Data;
using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using OpenTween.SocialProtocol;
namespace OpenTween.Setting.Panel
{
@@ -37,6 +40,12 @@ public partial class BasedPanel : SettingPanelBase
{
internal BindingList AccountsList { get; } = new();
+ internal Action? ApplyNetworkSettings { get; set; }
+
+ internal Func? OpenInBrowser { get; set; }
+
+ private readonly AccountSetupDispatcher setupDispatcher = new();
+
internal record AccountListBoxItem(UserAccount AccountSettings, bool IsPrimary)
{
public string DisplayText
@@ -61,6 +70,7 @@ public BasedPanel()
{
this.InitializeComponent();
this.InitializeBinding();
+ this.InitializeAddAccountDropdown();
}
private void InitializeBinding()
@@ -69,6 +79,22 @@ private void InitializeBinding()
this.AccountsListBox.DisplayMember = nameof(AccountListBoxItem.DisplayText);
}
+ private void InitializeAddAccountDropdown()
+ {
+ foreach (var (id, caption) in this.setupDispatcher.GetCaptions())
+ {
+ var menuItem = new ToolStripMenuItem
+ {
+ Text = caption,
+ Tag = id,
+ };
+ menuItem.Click += this.AddAccountMenuItem_Click;
+
+ this.contextMenuAddAccount.Items.Add(menuItem);
+ this.components.Add(menuItem);
+ }
+ }
+
public void LoadConfig(SettingCommon settingCommon)
{
using (ControlTransaction.Update(this.AccountsListBox))
@@ -155,6 +181,34 @@ private void MakeAccountPrimaryAt(int index)
this.AccountsList[index] with { IsPrimary = true };
}
+ private void AddAccountButton_Click(object sender, EventArgs e)
+ {
+ this.contextMenuAddAccount.Show(
+ this.AddAccountButton,
+ new(x: 0, y: this.AddAccountButton.Height)
+ );
+ }
+
+ private void AddAccountMenuItem_Click(object sender, EventArgs e)
+ {
+ var setupId = (Guid)((ToolStripMenuItem)sender).Tag;
+
+ this.ApplyNetworkSettings?.Invoke();
+
+ var authorizedAccount = this.setupDispatcher.Dispatch(this, setupId, this.OpenInBrowser);
+ if (authorizedAccount == null)
+ return;
+
+ this.AddAccount(authorizedAccount);
+
+ MessageBox.Show(
+ this,
+ Properties.Resources.AuthorizeButton_Click1,
+ "Authenticate",
+ MessageBoxButtons.OK
+ );
+ }
+
private void RemoveAccountButton_Click(object sender, EventArgs e)
{
var selectedIndex = this.AccountsListBox.SelectedIndex;
diff --git a/OpenTween/Setting/Panel/BasedPanel.resx b/OpenTween/Setting/Panel/BasedPanel.resx
index d71e0c3ef..277b059e0 100644
--- a/OpenTween/Setting/Panel/BasedPanel.resx
+++ b/OpenTween/Setting/Panel/BasedPanel.resx
@@ -24,6 +24,8 @@
panel1
System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
2
+ contextMenuAddAccount
+ System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
MakePrimaryButton
panel1
System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
@@ -31,7 +33,7 @@
panel1
$this
System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 0
+ 1
RemoveAccountButton
panel1
System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
@@ -57,6 +59,8 @@
100, 25
2
追加
+ 181, 26
+ 17, 17
Top, Right
True
NoControl
diff --git a/OpenTween/SocialProtocol/AccountSetupDispatcher.cs b/OpenTween/SocialProtocol/AccountSetupDispatcher.cs
new file mode 100644
index 000000000..6d69d3741
--- /dev/null
+++ b/OpenTween/SocialProtocol/AccountSetupDispatcher.cs
@@ -0,0 +1,65 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2024 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.Threading.Tasks;
+using System.Windows.Forms;
+using OpenTween.SocialProtocol.Twitter;
+
+namespace OpenTween.SocialProtocol
+{
+ public class AccountSetupDispatcher
+ {
+ public record AccountSetupItem(
+ Guid Id,
+ string Caption,
+ Func CreateInstance
+ );
+
+ private readonly List setupList;
+
+ public AccountSetupDispatcher()
+ {
+ this.setupList = new()
+ {
+ new(Guid.NewGuid(), "Twitter (OAuth)", () => new TwitterOAuthSetupDialog()),
+ new(Guid.NewGuid(), "Twitter (Cookie)", () => new TwitterCookieSetupDialog()),
+ };
+ }
+
+ public (Guid Id, string Caption)[] GetCaptions()
+ => this.setupList.Select(x => (x.Id, x.Caption)).ToArray();
+
+ public UserAccount? Dispatch(IWin32Window? owner, Guid setupId, Func? openInBrowser)
+ {
+ var setupItem = this.setupList.First(x => x.Id == setupId);
+
+ using var setup = setupItem.CreateInstance();
+ setup.OpenInBrowser = openInBrowser;
+
+ return setup.ShowAccountSetupDialog(owner);
+ }
+ }
+}
diff --git a/OpenTween/SocialProtocol/IAccountFactory.cs b/OpenTween/SocialProtocol/IAccountFactory.cs
new file mode 100644
index 000000000..35a9173c4
--- /dev/null
+++ b/OpenTween/SocialProtocol/IAccountFactory.cs
@@ -0,0 +1,36 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2024 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.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace OpenTween.SocialProtocol
+{
+ public interface IAccountFactory : IDisposable
+ {
+ public Func? OpenInBrowser { get; set; }
+
+ public UserAccount? ShowAccountSetupDialog(IWin32Window? owner);
+ }
+}
diff --git a/OpenTween/SocialProtocol/Twitter/TwitterCookieSetup.cs b/OpenTween/SocialProtocol/Twitter/TwitterCookieSetup.cs
new file mode 100644
index 000000000..c5de15d13
--- /dev/null
+++ b/OpenTween/SocialProtocol/Twitter/TwitterCookieSetup.cs
@@ -0,0 +1,72 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2024 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.Threading.Tasks;
+using OpenTween.Api.GraphQL;
+using OpenTween.Connection;
+
+namespace OpenTween.SocialProtocol.Twitter
+{
+ public class TwitterCookieSetup : NotifyPropertyChangedBase
+ {
+ public string TwitterComCookie
+ {
+ get => this.twitterComCookie;
+ set => this.SetProperty(ref this.twitterComCookie, value);
+ }
+
+ public UserAccount? AuthorizedAccount { get; private set; }
+
+ private string twitterComCookie = "";
+
+ public async Task DoAuthorize()
+ {
+ var credential = new TwitterCredentialCookie(this.GetAppToken());
+ using var apiConnection = new TwitterApiConnection(credential, new());
+
+ var request = new ViewerRequest();
+ var graphqlUser = await request.Send(apiConnection)
+ .ConfigureAwait(false);
+
+ var twitterUser = graphqlUser.ToTwitterUser();
+ var authorizedUser = new UserAccount
+ {
+ TwitterAuthType = APIAuthType.TwitterComCookie,
+ TwitterComCookie = this.TwitterComCookie,
+ UserId = twitterUser.IdStr,
+ Username = twitterUser.ScreenName,
+ };
+
+ this.AuthorizedAccount = authorizedUser;
+ }
+
+ private TwitterAppToken GetAppToken()
+ {
+ return new()
+ {
+ AuthType = APIAuthType.TwitterComCookie,
+ TwitterComCookie = this.TwitterComCookie,
+ };
+ }
+ }
+}
diff --git a/OpenTween/SocialProtocol/Twitter/TwitterCookieSetupDialog.Designer.cs b/OpenTween/SocialProtocol/Twitter/TwitterCookieSetupDialog.Designer.cs
new file mode 100644
index 000000000..56417a424
--- /dev/null
+++ b/OpenTween/SocialProtocol/Twitter/TwitterCookieSetupDialog.Designer.cs
@@ -0,0 +1,103 @@
+namespace OpenTween.SocialProtocol.Twitter
+{
+ partial class TwitterCookieSetupDialog
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TwitterCookieSetupDialog));
+ this.label1 = new System.Windows.Forms.Label();
+ this.textBoxTwitterComCookie = new System.Windows.Forms.TextBox();
+ this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
+ this.buttonOK = new System.Windows.Forms.Button();
+ this.buttonCancel = new System.Windows.Forms.Button();
+ this.bindingSource = new System.Windows.Forms.BindingSource(this.components);
+ this.tableLayoutPanel1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.bindingSource)).BeginInit();
+ this.SuspendLayout();
+ //
+ // label1
+ //
+ resources.ApplyResources(this.label1, "label1");
+ this.label1.Name = "label1";
+ //
+ // textBoxTwitterComCookie
+ //
+ resources.ApplyResources(this.textBoxTwitterComCookie, "textBoxTwitterComCookie");
+ this.textBoxTwitterComCookie.Name = "textBoxTwitterComCookie";
+ //
+ // tableLayoutPanel1
+ //
+ resources.ApplyResources(this.tableLayoutPanel1, "tableLayoutPanel1");
+ this.tableLayoutPanel1.Controls.Add(this.buttonOK, 0, 0);
+ this.tableLayoutPanel1.Controls.Add(this.buttonCancel, 1, 0);
+ this.tableLayoutPanel1.Name = "tableLayoutPanel1";
+ //
+ // buttonOK
+ //
+ resources.ApplyResources(this.buttonOK, "buttonOK");
+ this.buttonOK.Name = "buttonOK";
+ this.buttonOK.UseVisualStyleBackColor = true;
+ this.buttonOK.Click += new System.EventHandler(this.ButtonOK_Click);
+ //
+ // buttonCancel
+ //
+ resources.ApplyResources(this.buttonCancel, "buttonCancel");
+ this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.UseVisualStyleBackColor = true;
+ //
+ // TwitterCookieSetupDialog
+ //
+ this.AcceptButton = this.buttonOK;
+ resources.ApplyResources(this, "$this");
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.CancelButton = this.buttonCancel;
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.textBoxTwitterComCookie);
+ this.Controls.Add(this.tableLayoutPanel1);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.Name = "TwitterCookieSetupDialog";
+ this.tableLayoutPanel1.ResumeLayout(false);
+ this.tableLayoutPanel1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.bindingSource)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.TextBox textBoxTwitterComCookie;
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
+ private System.Windows.Forms.Button buttonCancel;
+ private System.Windows.Forms.Button buttonOK;
+ private System.Windows.Forms.BindingSource bindingSource;
+ }
+}
\ No newline at end of file
diff --git a/OpenTween/SocialProtocol/Twitter/TwitterCookieSetupDialog.cs b/OpenTween/SocialProtocol/Twitter/TwitterCookieSetupDialog.cs
new file mode 100644
index 000000000..b4ae2637e
--- /dev/null
+++ b/OpenTween/SocialProtocol/Twitter/TwitterCookieSetupDialog.cs
@@ -0,0 +1,93 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2024 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.Threading.Tasks;
+using System.Windows.Forms;
+using OpenTween.Api;
+
+namespace OpenTween.SocialProtocol.Twitter
+{
+ public partial class TwitterCookieSetupDialog : OTBaseForm, IAccountFactory
+ {
+ public TwitterCookieSetup Model { get; } = new();
+
+ public Func? OpenInBrowser { get; set; }
+
+ public TwitterCookieSetupDialog()
+ {
+ this.InitializeComponent();
+ this.InitializeBinding();
+ }
+
+ private void InitializeBinding()
+ {
+ this.bindingSource.DataSource = this.Model;
+
+ this.textBoxTwitterComCookie.DataBindings.Add(
+ nameof(TextBox.Text),
+ this.bindingSource,
+ nameof(TwitterCookieSetup.TwitterComCookie)
+ );
+ }
+
+ public UserAccount? ShowAccountSetupDialog(IWin32Window? owner)
+ {
+ var ret = this.ShowDialog(owner);
+ if (ret != DialogResult.OK)
+ return null;
+
+ return this.Model.AuthorizedAccount!;
+ }
+
+ private async void ButtonOK_Click(object sender, EventArgs e)
+ {
+ if (MyCommon.IsNullOrEmpty(this.Model.TwitterComCookie))
+ return;
+
+ using (ControlTransaction.Disabled(this))
+ {
+ try
+ {
+ await this.Model.DoAuthorize();
+
+ this.DialogResult = DialogResult.OK;
+ }
+ catch (WebApiException ex)
+ {
+ this.ShowAuthErrorMessage(ex);
+ }
+ }
+ }
+
+ private void ShowAuthErrorMessage(WebApiException ex)
+ {
+ var errorBody = ex is TwitterApiException twError
+ ? string.Join(Environment.NewLine, twError.LongMessages)
+ : ex.Message;
+
+ var message = Properties.Resources.AuthorizeButton_Click2 + Environment.NewLine + errorBody;
+ MessageBox.Show(this, message, "Authorize", MessageBoxButtons.OK);
+ }
+ }
+}
diff --git a/OpenTween/AuthDialog.en.resx b/OpenTween/SocialProtocol/Twitter/TwitterCookieSetupDialog.en.resx
similarity index 51%
rename from OpenTween/AuthDialog.en.resx
rename to OpenTween/SocialProtocol/Twitter/TwitterCookieSetupDialog.en.resx
index 86d01655f..41c27c660 100644
--- a/OpenTween/AuthDialog.en.resx
+++ b/OpenTween/SocialProtocol/Twitter/TwitterCookieSetupDialog.en.resx
@@ -5,13 +5,8 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- &Cancel
- 126, 26
- 190, 12
- Access URL bellow in your browser:
- 176, 12
- Allow the app and input your PIN:
- 125, 22
- &Copy URL
- PIN Code
+ Add Twitter Account
+ &Cancel
+ 208, 12
+ Paste the cookie of twitter.com (x.com):
diff --git a/OpenTween/SocialProtocol/Twitter/TwitterCookieSetupDialog.resx b/OpenTween/SocialProtocol/Twitter/TwitterCookieSetupDialog.resx
new file mode 100644
index 000000000..d1b0ff37b
--- /dev/null
+++ b/OpenTween/SocialProtocol/Twitter/TwitterCookieSetupDialog.resx
@@ -0,0 +1,70 @@
+
+ text/microsoft-resx
+ 2.0
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ 96, 96
+ 500, 149
+ True
+ 10, 10, 10, 10
+ Twitterアカウントを追加
+ TwitterCookieSetupDialog
+ OpenTween.OTBaseForm, OpenTween, Version=3.13.0.1, Culture=neutral, PublicKeyToken=null
+ bindingSource
+ System.Windows.Forms.BindingSource, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ buttonCancel
+ tableLayoutPanel1
+ System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 1
+ buttonOK
+ tableLayoutPanel1
+ System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 0
+ label1
+ $this
+ System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 0
+ tableLayoutPanel1
+ $this
+ System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 2
+ textBoxTwitterComCookie
+ $this
+ System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 1
+ 17, 17
+ True
+ NoControl
+ 84, 3
+ 86, 25
+ 1
+ キャンセル (&C)
+ True
+ NoControl
+ 3, 3
+ 75, 25
+ 0
+ &OK
+ True
+ 13, 10
+ 194, 12
+ 0
+ twitter.com (x.com) の Cookie を入力:
+ Bottom, Right
+ True
+ 2
+ <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="buttonOK" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="buttonCancel" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /></Controls><Columns Styles="AutoSize,0,AutoSize,0" /><Rows Styles="Percent,100" /></TableLayoutSettings>
+ 314, 105
+ 1
+ 173, 31
+ 2
+ 20, 32
+ 10, 10, 10, 10
+ True
+ 460, 60
+ 1
+
diff --git a/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetup.cs b/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetup.cs
new file mode 100644
index 000000000..a7920f6d9
--- /dev/null
+++ b/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetup.cs
@@ -0,0 +1,134 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2024 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.Threading.Tasks;
+using OpenTween.Connection;
+
+namespace OpenTween.SocialProtocol.Twitter
+{
+ public class TwitterOAuthSetup : NotifyPropertyChangedBase
+ {
+ public bool UseCustomConsumerKey
+ {
+ get => this.useCustomConsumerKey;
+ set => this.SetProperty(ref this.useCustomConsumerKey, value);
+ }
+
+ public string CustomConsumerKey
+ {
+ get => this.customConsumerKey;
+ set => this.SetProperty(ref this.customConsumerKey, value);
+ }
+
+ public string CustomConsumerSecret
+ {
+ get => this.customConsumerSecret;
+ set => this.SetProperty(ref this.customConsumerSecret, value);
+ }
+
+ public Uri? AuthorizeUri
+ {
+ get => this.authorizeUri;
+ private set => this.SetProperty(ref this.authorizeUri, value);
+ }
+
+ public bool AcquirePinCode
+ {
+ get => this.acquirePinCode;
+ private set => this.SetProperty(ref this.acquirePinCode, value);
+ }
+
+ public string PinCode
+ {
+ get => this.pinCode;
+ set => this.SetProperty(ref this.pinCode, value);
+ }
+
+ public UserAccount? AuthorizedAccount { get; private set; }
+
+ private bool useCustomConsumerKey = true;
+ private string customConsumerKey = "";
+ private string customConsumerSecret = "";
+ private TwitterCredentialOAuth1? requestToken;
+ private Uri? authorizeUri = null;
+ private bool acquirePinCode = false;
+ private string pinCode = "";
+
+ public async Task GetAuthorizeUri()
+ {
+ var appToken = this.GetAppToken();
+ var requestToken = await TwitterApiConnection.GetRequestTokenAsync(appToken);
+ var authorizeUri = TwitterApiConnection.GetAuthorizeUri(requestToken);
+
+ this.GotoPinCodeStep(requestToken, authorizeUri);
+ }
+
+ private TwitterAppToken GetAppToken()
+ {
+ if (this.UseCustomConsumerKey &&
+ !MyCommon.IsNullOrEmpty(this.CustomConsumerKey) &&
+ !MyCommon.IsNullOrEmpty(this.CustomConsumerSecret))
+ {
+ return new()
+ {
+ AuthType = APIAuthType.OAuth1,
+ OAuth1CustomConsumerKey = ApiKey.Create(this.CustomConsumerKey),
+ OAuth1CustomConsumerSecret = ApiKey.Create(this.CustomConsumerSecret),
+ };
+ }
+
+ return TwitterAppToken.GetDefault();
+ }
+
+ private void GotoPinCodeStep(TwitterCredentialOAuth1 requestToken, Uri authorizeUri)
+ {
+ this.requestToken = requestToken;
+ this.AuthorizeUri = authorizeUri;
+ this.AcquirePinCode = true;
+ }
+
+ public async Task DoAuthorize()
+ {
+ if (this.requestToken == null)
+ throw new InvalidOperationException($"{nameof(this.requestToken)} is null");
+
+ if (MyCommon.IsNullOrEmpty(this.PinCode))
+ throw new InvalidOperationException($"{nameof(this.PinCode)} is empty");
+
+ var accessTokenResponse = await TwitterApiConnection.GetAccessTokenAsync(this.requestToken, this.PinCode);
+ var authorizedAccount = new UserAccount
+ {
+ TwitterAuthType = APIAuthType.OAuth1,
+ TwitterOAuth1ConsumerKey = this.CustomConsumerKey,
+ TwitterOAuth1ConsumerSecret = this.CustomConsumerSecret,
+ Username = accessTokenResponse["screen_name"],
+ UserId = accessTokenResponse["user_id"],
+ Token = accessTokenResponse["oauth_token"],
+ TokenSecret = accessTokenResponse["oauth_token_secret"],
+ };
+
+ this.AuthorizedAccount = authorizedAccount;
+ }
+ }
+}
diff --git a/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetupDialog.Designer.cs b/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetupDialog.Designer.cs
new file mode 100644
index 000000000..4e383fcd9
--- /dev/null
+++ b/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetupDialog.Designer.cs
@@ -0,0 +1,205 @@
+namespace OpenTween.SocialProtocol.Twitter
+{
+ partial class TwitterOAuthSetupDialog
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TwitterOAuthSetupDialog));
+ this.buttonCancel = new System.Windows.Forms.Button();
+ this.groupBoxInputConsumerKey = new System.Windows.Forms.GroupBox();
+ this.checkBoxUseCustomConsumerKey = new System.Windows.Forms.CheckBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.textBoxCustomConsumerKey = new System.Windows.Forms.TextBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this.textBoxCustomConsumerSecret = new System.Windows.Forms.TextBox();
+ this.buttonGetAuthorizeUri = new System.Windows.Forms.Button();
+ this.groupBoxInputPinCode = new System.Windows.Forms.GroupBox();
+ this.label3 = new System.Windows.Forms.Label();
+ this.linkLabelAuthorize = new System.Windows.Forms.LinkLabel();
+ this.contextMenuLinkLabel = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.menuItemCopyLink = new System.Windows.Forms.ToolStripMenuItem();
+ this.label4 = new System.Windows.Forms.Label();
+ this.textBoxPinCode = new System.Windows.Forms.TextBox();
+ this.buttonGetAccessToken = new System.Windows.Forms.Button();
+ this.bindingSource = new System.Windows.Forms.BindingSource(this.components);
+ this.groupBoxInputConsumerKey.SuspendLayout();
+ this.groupBoxInputPinCode.SuspendLayout();
+ this.contextMenuLinkLabel.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.bindingSource)).BeginInit();
+ this.SuspendLayout();
+ //
+ // buttonCancel
+ //
+ resources.ApplyResources(this.buttonCancel, "buttonCancel");
+ this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.UseVisualStyleBackColor = true;
+ //
+ // groupBoxInputConsumerKey
+ //
+ resources.ApplyResources(this.groupBoxInputConsumerKey, "groupBoxInputConsumerKey");
+ this.groupBoxInputConsumerKey.Controls.Add(this.checkBoxUseCustomConsumerKey);
+ this.groupBoxInputConsumerKey.Controls.Add(this.label1);
+ this.groupBoxInputConsumerKey.Controls.Add(this.textBoxCustomConsumerKey);
+ this.groupBoxInputConsumerKey.Controls.Add(this.label2);
+ this.groupBoxInputConsumerKey.Controls.Add(this.textBoxCustomConsumerSecret);
+ this.groupBoxInputConsumerKey.Controls.Add(this.buttonGetAuthorizeUri);
+ this.groupBoxInputConsumerKey.Name = "groupBoxInputConsumerKey";
+ this.groupBoxInputConsumerKey.TabStop = false;
+ //
+ // checkBoxUseCustomConsumerKey
+ //
+ resources.ApplyResources(this.checkBoxUseCustomConsumerKey, "checkBoxUseCustomConsumerKey");
+ this.checkBoxUseCustomConsumerKey.Name = "checkBoxUseCustomConsumerKey";
+ this.checkBoxUseCustomConsumerKey.UseVisualStyleBackColor = true;
+ //
+ // label1
+ //
+ resources.ApplyResources(this.label1, "label1");
+ this.label1.Name = "label1";
+ //
+ // textBoxCustomConsumerKey
+ //
+ resources.ApplyResources(this.textBoxCustomConsumerKey, "textBoxCustomConsumerKey");
+ this.textBoxCustomConsumerKey.Name = "textBoxCustomConsumerKey";
+ //
+ // label2
+ //
+ resources.ApplyResources(this.label2, "label2");
+ this.label2.Name = "label2";
+ //
+ // textBoxCustomConsumerSecret
+ //
+ resources.ApplyResources(this.textBoxCustomConsumerSecret, "textBoxCustomConsumerSecret");
+ this.textBoxCustomConsumerSecret.Name = "textBoxCustomConsumerSecret";
+ //
+ // buttonGetAuthorizeUri
+ //
+ resources.ApplyResources(this.buttonGetAuthorizeUri, "buttonGetAuthorizeUri");
+ this.buttonGetAuthorizeUri.Name = "buttonGetAuthorizeUri";
+ this.buttonGetAuthorizeUri.UseVisualStyleBackColor = true;
+ this.buttonGetAuthorizeUri.Click += new System.EventHandler(this.ButtonGetAuthorizeUri_Click);
+ //
+ // groupBoxInputPinCode
+ //
+ resources.ApplyResources(this.groupBoxInputPinCode, "groupBoxInputPinCode");
+ this.groupBoxInputPinCode.Controls.Add(this.label3);
+ this.groupBoxInputPinCode.Controls.Add(this.linkLabelAuthorize);
+ this.groupBoxInputPinCode.Controls.Add(this.label4);
+ this.groupBoxInputPinCode.Controls.Add(this.textBoxPinCode);
+ this.groupBoxInputPinCode.Controls.Add(this.buttonGetAccessToken);
+ this.groupBoxInputPinCode.Name = "groupBoxInputPinCode";
+ this.groupBoxInputPinCode.TabStop = false;
+ //
+ // label3
+ //
+ resources.ApplyResources(this.label3, "label3");
+ this.label3.Name = "label3";
+ //
+ // linkLabelAuthorize
+ //
+ resources.ApplyResources(this.linkLabelAuthorize, "linkLabelAuthorize");
+ this.linkLabelAuthorize.AutoEllipsis = true;
+ this.linkLabelAuthorize.ContextMenuStrip = this.contextMenuLinkLabel;
+ this.linkLabelAuthorize.Name = "linkLabelAuthorize";
+ this.linkLabelAuthorize.TabStop = true;
+ this.linkLabelAuthorize.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelAuthorize_LinkClicked);
+ //
+ // contextMenuLinkLabel
+ //
+ this.contextMenuLinkLabel.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.menuItemCopyLink});
+ this.contextMenuLinkLabel.Name = "contextMenuLinkLabel";
+ resources.ApplyResources(this.contextMenuLinkLabel, "contextMenuLinkLabel");
+ //
+ // menuItemCopyLink
+ //
+ this.menuItemCopyLink.Name = "menuItemCopyLink";
+ resources.ApplyResources(this.menuItemCopyLink, "menuItemCopyLink");
+ this.menuItemCopyLink.Click += new System.EventHandler(this.MenuItemCopyLink_Click);
+ //
+ // label4
+ //
+ resources.ApplyResources(this.label4, "label4");
+ this.label4.Name = "label4";
+ //
+ // textBoxPinCode
+ //
+ resources.ApplyResources(this.textBoxPinCode, "textBoxPinCode");
+ this.textBoxPinCode.Name = "textBoxPinCode";
+ //
+ // buttonGetAccessToken
+ //
+ resources.ApplyResources(this.buttonGetAccessToken, "buttonGetAccessToken");
+ this.buttonGetAccessToken.Name = "buttonGetAccessToken";
+ this.buttonGetAccessToken.UseVisualStyleBackColor = true;
+ this.buttonGetAccessToken.Click += new System.EventHandler(this.ButtonGetAccessToken_Click);
+ //
+ // TwitterOAuthSetupDialog
+ //
+ resources.ApplyResources(this, "$this");
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.CancelButton = this.buttonCancel;
+ this.Controls.Add(this.groupBoxInputConsumerKey);
+ this.Controls.Add(this.groupBoxInputPinCode);
+ this.Controls.Add(this.buttonCancel);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.Name = "TwitterOAuthSetupDialog";
+ this.groupBoxInputConsumerKey.ResumeLayout(false);
+ this.groupBoxInputConsumerKey.PerformLayout();
+ this.groupBoxInputPinCode.ResumeLayout(false);
+ this.groupBoxInputPinCode.PerformLayout();
+ this.contextMenuLinkLabel.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.bindingSource)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button buttonCancel;
+ private System.Windows.Forms.GroupBox groupBoxInputConsumerKey;
+ private System.Windows.Forms.CheckBox checkBoxUseCustomConsumerKey;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.TextBox textBoxCustomConsumerKey;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.TextBox textBoxCustomConsumerSecret;
+ private System.Windows.Forms.Button buttonGetAuthorizeUri;
+ private System.Windows.Forms.GroupBox groupBoxInputPinCode;
+ private System.Windows.Forms.LinkLabel linkLabelAuthorize;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.TextBox textBoxPinCode;
+ private System.Windows.Forms.Button buttonGetAccessToken;
+ private System.Windows.Forms.ContextMenuStrip contextMenuLinkLabel;
+ private System.Windows.Forms.ToolStripMenuItem menuItemCopyLink;
+ private System.Windows.Forms.BindingSource bindingSource;
+ }
+}
\ No newline at end of file
diff --git a/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetupDialog.cs b/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetupDialog.cs
new file mode 100644
index 000000000..3046e1f25
--- /dev/null
+++ b/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetupDialog.cs
@@ -0,0 +1,188 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2024 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.Runtime.InteropServices;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using OpenTween.Api;
+
+namespace OpenTween.SocialProtocol.Twitter
+{
+ public partial class TwitterOAuthSetupDialog : OTBaseForm, IAccountFactory
+ {
+ public TwitterOAuthSetup Model { get; } = new();
+
+ public Func? OpenInBrowser { get; set; }
+
+ public TwitterOAuthSetupDialog()
+ {
+ this.InitializeComponent();
+ this.InitializeBinding();
+
+ // textBoxPinCode のフォントを OTBaseForm.GlobalFont に変更
+ this.textBoxPinCode.Font = this.ReplaceToGlobalFont(this.textBoxPinCode.Font);
+ }
+
+ private void InitializeBinding()
+ {
+ this.bindingSource.DataSource = this.Model;
+
+ this.checkBoxUseCustomConsumerKey.DataBindings.Add(
+ nameof(CheckBox.Checked),
+ this.bindingSource,
+ nameof(TwitterOAuthSetup.UseCustomConsumerKey),
+ formattingEnabled: false,
+ DataSourceUpdateMode.OnPropertyChanged
+ );
+
+ this.textBoxCustomConsumerKey.DataBindings.Add(
+ nameof(TextBox.Enabled),
+ this.bindingSource,
+ nameof(TwitterOAuthSetup.UseCustomConsumerKey)
+ );
+
+ this.textBoxCustomConsumerKey.DataBindings.Add(
+ nameof(TextBox.Text),
+ this.bindingSource,
+ nameof(TwitterOAuthSetup.CustomConsumerKey)
+ );
+
+ this.textBoxCustomConsumerSecret.DataBindings.Add(
+ nameof(TextBox.Enabled),
+ this.bindingSource,
+ nameof(TwitterOAuthSetup.UseCustomConsumerKey)
+ );
+
+ this.textBoxCustomConsumerSecret.DataBindings.Add(
+ nameof(TextBox.Text),
+ this.bindingSource,
+ nameof(TwitterOAuthSetup.CustomConsumerSecret)
+ );
+
+ this.groupBoxInputPinCode.DataBindings.Add(
+ nameof(GroupBox.Enabled),
+ this.bindingSource,
+ nameof(TwitterOAuthSetup.AcquirePinCode)
+ );
+
+ this.linkLabelAuthorize.DataBindings.Add(
+ nameof(LinkLabel.Text),
+ this.bindingSource,
+ nameof(TwitterOAuthSetup.AuthorizeUri)
+ );
+
+ this.textBoxPinCode.DataBindings.Add(
+ nameof(TextBox.Text),
+ this.bindingSource,
+ nameof(TwitterOAuthSetup.PinCode)
+ );
+ }
+
+ public UserAccount? ShowAccountSetupDialog(IWin32Window? owner)
+ {
+ var ret = this.ShowDialog(owner);
+ if (ret != DialogResult.OK)
+ return null;
+
+ return this.Model.AuthorizedAccount!;
+ }
+
+ private async void ButtonGetAuthorizeUri_Click(object sender, EventArgs e)
+ {
+ using (ControlTransaction.Disabled(this))
+ {
+ try
+ {
+ await this.Model.GetAuthorizeUri();
+ }
+ catch (WebApiException ex)
+ {
+ this.ShowAuthErrorMessage(ex);
+ }
+ }
+
+ if (this.Model.AcquirePinCode)
+ this.groupBoxInputPinCode.Focus();
+ }
+
+ private async void LinkLabelAuthorize_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+ {
+ if (this.Model.AuthorizeUri == null)
+ return;
+
+ // 右クリックの場合は無視する
+ if (e.Button == MouseButtons.Right)
+ return;
+
+ if (this.OpenInBrowser == null)
+ throw new InvalidOperationException($"{nameof(this.OpenInBrowser)} is not set");
+
+ await this.OpenInBrowser(this, this.Model.AuthorizeUri);
+ }
+
+ private void MenuItemCopyLink_Click(object sender, EventArgs e)
+ {
+ if (this.Model.AuthorizeUri == null)
+ return;
+
+ try
+ {
+ Clipboard.SetText(this.Model.AuthorizeUri.ToString());
+ }
+ catch (ExternalException)
+ {
+ }
+ }
+
+ private async void ButtonGetAccessToken_Click(object sender, EventArgs e)
+ {
+ if (MyCommon.IsNullOrEmpty(this.Model.PinCode))
+ return;
+
+ using (ControlTransaction.Disabled(this))
+ {
+ try
+ {
+ await this.Model.DoAuthorize();
+
+ this.DialogResult = DialogResult.OK;
+ }
+ catch (WebApiException ex)
+ {
+ this.ShowAuthErrorMessage(ex);
+ }
+ }
+ }
+
+ private void ShowAuthErrorMessage(WebApiException ex)
+ {
+ var errorBody = ex is TwitterApiException twError
+ ? string.Join(Environment.NewLine, twError.LongMessages)
+ : ex.Message;
+
+ var message = Properties.Resources.AuthorizeButton_Click2 + Environment.NewLine + errorBody;
+ MessageBox.Show(this, message, "Authorize", MessageBoxButtons.OK);
+ }
+ }
+}
diff --git a/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetupDialog.en.resx b/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetupDialog.en.resx
new file mode 100644
index 000000000..0038bfdd4
--- /dev/null
+++ b/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetupDialog.en.resx
@@ -0,0 +1,17 @@
+
+ text/microsoft-resx
+ 2.0
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Add Twitter Account
+ &Cancel
+ Continue
+ 160, 16
+ Use custom consumer key
+ 166, 12
+ Open below url in your browser:
+ 268, 12
+ Please enter the PIN code displayed after approval:
+
diff --git a/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetupDialog.resx b/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetupDialog.resx
new file mode 100644
index 000000000..37454618a
--- /dev/null
+++ b/OpenTween/SocialProtocol/Twitter/TwitterOAuthSetupDialog.resx
@@ -0,0 +1,163 @@
+
+ text/microsoft-resx
+ 2.0
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ 96, 96
+ 500, 425
+ True
+ Twitterアカウントを追加
+ TwitterOAuthSetupDialog
+ OpenTween.OTBaseForm, OpenTween, Version=3.13.0.1, Culture=neutral, PublicKeyToken=null
+ bindingSource
+ System.Windows.Forms.BindingSource, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ buttonCancel
+ $this
+ System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 3
+ buttonGetAccessToken
+ groupBoxInputPinCode
+ System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 4
+ buttonGetAuthorizeUri
+ groupBoxInputConsumerKey
+ System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 5
+ checkBoxUseCustomConsumerKey
+ groupBoxInputConsumerKey
+ System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 0
+ contextMenuLinkLabel
+ System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ groupBoxInputConsumerKey
+ $this
+ System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 1
+ groupBoxInputPinCode
+ $this
+ System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 2
+ label1
+ groupBoxInputConsumerKey
+ System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 1
+ label2
+ groupBoxInputConsumerKey
+ System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 3
+ label3
+ groupBoxInputPinCode
+ System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 0
+ label4
+ groupBoxInputPinCode
+ System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 2
+ linkLabelAuthorize
+ groupBoxInputPinCode
+ System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 1
+ menuItemCopyLink
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ textBoxCustomConsumerKey
+ groupBoxInputConsumerKey
+ System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 2
+ textBoxCustomConsumerSecret
+ groupBoxInputConsumerKey
+ System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 4
+ textBoxPinCode
+ groupBoxInputPinCode
+ System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ 3
+ 192, 17
+ Bottom, Right
+ True
+ 398, 390
+ 90, 23
+ 2
+ キャンセル (&C)
+ Bottom, Right
+ NoControl
+ 362, 152
+ 100, 23
+ 4
+ OK
+ Bottom, Right
+ 362, 140
+ 3, 10, 3, 3
+ 100, 23
+ 5
+ 次へ進む
+ True
+ 13, 25
+ 188, 16
+ 0
+ Consumer Key を自分で指定する
+ 148, 26
+ 17, 17
+ Top, Left, Right
+ 13, 13
+ 10, 10, 10, 10
+ 475, 176
+ 0
+ Step 1
+ Top, Left, Right
+ 13, 196
+ 10, 10, 10, 10
+ 475, 188
+ 1
+ Step 2
+ True
+ NoControl
+ 30, 47
+ 20, 3, 3, 3
+ 132, 12
+ 1
+ Consumer Key (API Key)
+ True
+ NoControl
+ 30, 90
+ 3, 3, 3, 3
+ 160, 12
+ 3
+ Consumer Secret (API Secret)
+ True
+ 14, 26
+ 351, 12
+ 0
+ 以下のURLにアクセスし、内容を確認してアプリとの連携を許可してください:
+ True
+ 13, 83
+ 241, 12
+ 2
+ 認可後に表示される PIN コードを入力してください:
+ Top, Left, Right
+ 25, 53
+ 15, 15, 15, 15
+ 425, 15
+ 1
+ linkLabel
+ MiddleLeft
+ 147, 22
+ URLをコピー (&C)
+ 32, 65
+ 430, 19
+ 2
+ 32, 108
+ 430, 19
+ 4
+ PINコード
+ Top, Left, Right
+ MS UI Gothic, 24pt
+ 142, 105
+ 10, 10, 10, 5
+ 190, 39
+ 3
+ Center
+