OSDN Git Service

pbs.twimg.com の画像URLのフォーマット変更に対応
[opentween/open-tween.git] / OpenTween / AppendSettingDialog.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 //           (c) 2008-2011 Moz (@syo68k)
4 //           (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 //           (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 //           (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
7 //           (c) 2011      kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
8 // All rights reserved.
9 // 
10 // This file is part of OpenTween.
11 // 
12 // This program is free software; you can redistribute it and/or modify it
13 // under the terms of the GNU General Public License as published by the Free
14 // Software Foundation; either version 3 of the License, or (at your option)
15 // any later version.
16 // 
17 // This program is distributed in the hope that it will be useful, but
18 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 // for more details. 
21 // 
22 // You should have received a copy of the GNU General Public License along
23 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
24 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
25 // Boston, MA 02110-1301, USA.
26
27 #nullable enable
28
29 using System;
30 using System.Collections.Generic;
31 using System.ComponentModel;
32 using System.Data;
33 using System.Drawing;
34 using System.Linq;
35 using System.Net.Http;
36 using System.Text;
37 using System.Windows.Forms;
38 using System.Threading;
39 using System.IO;
40 using System.Resources;
41 using OpenTween.Api;
42 using OpenTween.Connection;
43 using OpenTween.Thumbnail;
44 using System.Threading.Tasks;
45 using OpenTween.Setting.Panel;
46
47 namespace OpenTween
48 {
49     public partial class AppendSettingDialog : OTBaseForm
50     {
51         public event EventHandler<IntervalChangedEventArgs>? IntervalChanged;
52
53         internal Twitter tw = null!;
54         internal TwitterApi twitterApi = null!;
55
56         public AppendSettingDialog()
57         {
58             this.InitializeComponent();
59
60             this.BasedPanel.StartAuthButton.Click += this.StartAuthButton_Click;
61             this.BasedPanel.CreateAccountButton.Click += this.CreateAccountButton_Click;
62             this.GetPeriodPanel.CheckPostAndGet.CheckedChanged += this.CheckPostAndGet_CheckedChanged;
63             this.ActionPanel.UReadMng.CheckedChanged += this.UReadMng_CheckedChanged;
64
65             this.Icon = Properties.Resources.MIcon;
66         }
67
68         public void LoadConfig(SettingCommon settingCommon, SettingLocal settingLocal)
69         {
70             this.BasedPanel.LoadConfig(settingCommon);
71             this.GetPeriodPanel.LoadConfig(settingCommon);
72             this.StartupPanel.LoadConfig(settingCommon);
73             this.TweetPrvPanel.LoadConfig(settingCommon);
74             this.TweetActPanel.LoadConfig(settingCommon, settingLocal);
75             this.ActionPanel.LoadConfig(settingCommon, settingLocal);
76             this.FontPanel.LoadConfig(settingLocal);
77             this.FontPanel2.LoadConfig(settingLocal);
78             this.PreviewPanel.LoadConfig(settingCommon);
79             this.GetCountPanel.LoadConfig(settingCommon);
80             this.ShortUrlPanel.LoadConfig(settingCommon);
81             this.ProxyPanel.LoadConfig(settingLocal);
82             this.CooperatePanel.LoadConfig(settingCommon);
83             this.ConnectionPanel.LoadConfig(settingCommon);
84             this.NotifyPanel.LoadConfig(settingCommon);
85
86             var activeUser = settingCommon.UserAccounts.FirstOrDefault(x => x.UserId == this.tw.UserId);
87             if (activeUser != null)
88             {
89                 this.BasedPanel.AuthUserCombo.SelectedItem = activeUser;
90             }
91         }
92
93         public void SaveConfig(SettingCommon settingCommon, SettingLocal settingLocal)
94         {
95             this.BasedPanel.SaveConfig(settingCommon);
96             this.GetPeriodPanel.SaveConfig(settingCommon);
97             this.StartupPanel.SaveConfig(settingCommon);
98             this.TweetPrvPanel.SaveConfig(settingCommon);
99             this.TweetActPanel.SaveConfig(settingCommon, settingLocal);
100             this.ActionPanel.SaveConfig(settingCommon, settingLocal);
101             this.FontPanel.SaveConfig(settingLocal);
102             this.FontPanel2.SaveConfig(settingLocal);
103             this.PreviewPanel.SaveConfig(settingCommon);
104             this.GetCountPanel.SaveConfig(settingCommon);
105             this.ShortUrlPanel.SaveConfig(settingCommon);
106             this.ProxyPanel.SaveConfig(settingLocal);
107             this.CooperatePanel.SaveConfig(settingCommon);
108             this.ConnectionPanel.SaveConfig(settingCommon);
109             this.NotifyPanel.SaveConfig(settingCommon);
110
111             var userAccountIdx = this.BasedPanel.AuthUserCombo.SelectedIndex;
112             if (userAccountIdx != -1)
113             {
114                 var u = settingCommon.UserAccounts[userAccountIdx];
115                 this.tw.Initialize(u.Token, u.TokenSecret, u.Username, u.UserId);
116             }
117             else
118             {
119                 this.tw.ClearAuthInfo();
120                 this.tw.Initialize("", "", "", 0);
121             }
122         }
123
124         private void TreeViewSetting_BeforeSelect(object sender, TreeViewCancelEventArgs e)
125         {
126             if (this.TreeViewSetting.SelectedNode == null) return;
127             var pnl = (SettingPanelBase)this.TreeViewSetting.SelectedNode.Tag;
128             if (pnl == null) return;
129             pnl.Enabled = false;
130             pnl.Visible = false;
131         }
132
133         private void TreeViewSetting_AfterSelect(object sender, TreeViewEventArgs e)
134         {
135             if (e.Node == null) return;
136             var pnl = (SettingPanelBase)e.Node.Tag;
137             if (pnl == null) return;
138             pnl.Enabled = true;
139             pnl.Visible = true;
140
141             if (pnl.Name == "PreviewPanel")
142             {
143                 if (GrowlHelper.IsDllExists)
144                 {
145                     this.PreviewPanel.IsNotifyUseGrowlCheckBox.Enabled = true;
146                 }
147                 else
148                 {
149                     this.PreviewPanel.IsNotifyUseGrowlCheckBox.Enabled = false;
150                 }
151             }
152         }
153
154         private void Setting_FormClosing(object sender, FormClosingEventArgs e)
155         {
156             if (MyCommon._endingFlag) return;
157
158             if (this.BasedPanel.AuthUserCombo.SelectedIndex == -1 && e.CloseReason == CloseReason.None)
159             {
160                 if (MessageBox.Show(Properties.Resources.Setting_FormClosing1, "Confirm", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
161                 {
162                     e.Cancel = true;
163                 }
164             }
165             if (e.Cancel == false && TreeViewSetting.SelectedNode != null)
166             {
167                 var curPanel = (SettingPanelBase)TreeViewSetting.SelectedNode.Tag;
168                 curPanel.Visible = false;
169                 curPanel.Enabled = false;
170             }
171         }
172
173         private void Setting_Load(object sender, EventArgs e)
174         {
175             this.TreeViewSetting.Nodes["BasedNode"].Tag = BasedPanel;
176             this.TreeViewSetting.Nodes["BasedNode"].Nodes["PeriodNode"].Tag = GetPeriodPanel;
177             this.TreeViewSetting.Nodes["BasedNode"].Nodes["StartUpNode"].Tag = StartupPanel;
178             this.TreeViewSetting.Nodes["BasedNode"].Nodes["GetCountNode"].Tag = GetCountPanel;
179             this.TreeViewSetting.Nodes["ActionNode"].Tag = ActionPanel;
180             this.TreeViewSetting.Nodes["ActionNode"].Nodes["TweetActNode"].Tag = TweetActPanel;
181             this.TreeViewSetting.Nodes["PreviewNode"].Tag = PreviewPanel;
182             this.TreeViewSetting.Nodes["PreviewNode"].Nodes["TweetPrvNode"].Tag = TweetPrvPanel;
183             this.TreeViewSetting.Nodes["PreviewNode"].Nodes["NotifyNode"].Tag = NotifyPanel;
184             this.TreeViewSetting.Nodes["FontNode"].Tag = FontPanel;
185             this.TreeViewSetting.Nodes["FontNode"].Nodes["FontNode2"].Tag = FontPanel2;
186             this.TreeViewSetting.Nodes["ConnectionNode"].Tag = ConnectionPanel;
187             this.TreeViewSetting.Nodes["ConnectionNode"].Nodes["ProxyNode"].Tag = ProxyPanel;
188             this.TreeViewSetting.Nodes["ConnectionNode"].Nodes["CooperateNode"].Tag = CooperatePanel;
189             this.TreeViewSetting.Nodes["ConnectionNode"].Nodes["ShortUrlNode"].Tag = ShortUrlPanel;
190
191             this.TreeViewSetting.SelectedNode = this.TreeViewSetting.Nodes[0];
192             this.TreeViewSetting.ExpandAll();
193
194             ActiveControl = BasedPanel.StartAuthButton;
195         }
196
197         private void UReadMng_CheckedChanged(object sender, EventArgs e)
198         {
199             if (this.ActionPanel.UReadMng.Checked == true)
200             {
201                 this.StartupPanel.StartupReaded.Enabled = true;
202             }
203             else
204             {
205                 this.StartupPanel.StartupReaded.Enabled = false;
206             }
207         }
208
209         private async void StartAuthButton_Click(object sender, EventArgs e)
210         {
211             using (ControlTransaction.Disabled(this.BasedPanel.StartAuthButton))
212             {
213                 try
214                 {
215                     this.ApplyNetworkSettings();
216
217                     var newAccount = await this.PinAuth();
218                     if (newAccount == null)
219                         return;
220
221                     var authUserCombo = this.BasedPanel.AuthUserCombo;
222
223                     var oldAccount = authUserCombo.Items.Cast<UserAccount>()
224                         .FirstOrDefault(x => x.UserId == newAccount.UserId);
225
226                     int idx;
227                     if (oldAccount != null)
228                     {
229                         idx = authUserCombo.Items.IndexOf(oldAccount);
230                         authUserCombo.Items[idx] = newAccount;
231                     }
232                     else
233                     {
234                         idx = authUserCombo.Items.Add(newAccount);
235                     }
236
237                     authUserCombo.SelectedIndex = idx;
238
239                     MessageBox.Show(this, Properties.Resources.AuthorizeButton_Click1,
240                         "Authenticate", MessageBoxButtons.OK);
241                 }
242                 catch (WebApiException ex)
243                 {
244                     var message = Properties.Resources.AuthorizeButton_Click2 + Environment.NewLine + ex.Message;
245                     MessageBox.Show(this, message, "Authenticate", MessageBoxButtons.OK);
246                 }
247             }
248         }
249
250         /// <summary>
251         /// 現在設定画面に入力されているネットワーク関係の設定を適用します
252         /// </summary>
253         public void ApplyNetworkSettings()
254         {
255             ProxyType proxyType;
256             if (this.ProxyPanel.RadioProxyNone.Checked)
257                 proxyType = ProxyType.None;
258             else if (this.ProxyPanel.RadioProxyIE.Checked)
259                 proxyType = ProxyType.IE;
260             else
261                 proxyType = ProxyType.Specified;
262
263             var proxyAddress = this.ProxyPanel.TextProxyAddress.Text.Trim();
264             var proxyPort = int.Parse(this.ProxyPanel.TextProxyPort.Text.Trim());
265             var proxyUser = this.ProxyPanel.TextProxyUser.Text.Trim();
266             var proxyPassword = this.ProxyPanel.TextProxyPassword.Text.Trim();
267             Networking.SetWebProxy(proxyType, proxyAddress, proxyPort, proxyUser, proxyPassword);
268
269             var timeout = int.Parse(this.ConnectionPanel.ConnectionTimeOut.Text.Trim());
270             Networking.DefaultTimeout = TimeSpan.FromSeconds(timeout);
271
272             var uploadImageTimeout = int.Parse(this.ConnectionPanel.UploadImageTimeout.Text.Trim());
273             Networking.UploadImageTimeout = TimeSpan.FromSeconds(uploadImageTimeout);
274
275             Networking.ForceIPv4 = this.ConnectionPanel.checkBoxForceIPv4.Checked;
276
277             TwitterApiConnection.RestApiHost = this.ConnectionPanel.TwitterAPIText.Text.Trim();
278         }
279
280         private async Task<UserAccount?> PinAuth()
281         {
282             var requestToken = await TwitterApiConnection.GetRequestTokenAsync();
283
284             var pinPageUrl = TwitterApiConnection.GetAuthorizeUri(requestToken);
285
286             var pin = AuthDialog.DoAuth(this, pinPageUrl);
287             if (MyCommon.IsNullOrEmpty(pin))
288                 return null; // キャンセルされた場合
289
290             var accessTokenResponse = await TwitterApiConnection.GetAccessTokenAsync(requestToken, pin);
291
292             return new UserAccount
293             {
294                 Username = accessTokenResponse["screen_name"],
295                 UserId = long.Parse(accessTokenResponse["user_id"]),
296                 Token = accessTokenResponse["oauth_token"],
297                 TokenSecret = accessTokenResponse["oauth_token_secret"],
298             };
299         }
300
301         private void CheckPostAndGet_CheckedChanged(object sender, EventArgs e)
302             => this.GetPeriodPanel.LabelPostAndGet.Visible = this.GetPeriodPanel.CheckPostAndGet.Checked && !tw.UserStreamActive;
303
304         private void Setting_Shown(object sender, EventArgs e)
305         {
306             do
307             {
308                 Thread.Sleep(10);
309                 if (this.Disposing || this.IsDisposed) return;
310             } while (!this.IsHandleCreated);
311             this.TopMost = this.PreviewPanel.CheckAlwaysTop.Checked;
312
313             this.GetPeriodPanel.LabelPostAndGet.Visible = this.GetPeriodPanel.CheckPostAndGet.Checked && !tw.UserStreamActive;
314             this.GetPeriodPanel.LabelUserStreamActive.Visible = tw.UserStreamActive;
315         }
316
317         private void OpenUrl(string url)
318         {
319             var myPath = url;
320             var path = this.ActionPanel.BrowserPathText.Text;
321             try
322             {
323                 if (!MyCommon.IsNullOrEmpty(path))
324                 {
325                     if (path.StartsWith("\"", StringComparison.Ordinal) && path.Length > 2 && path.IndexOf("\"", 2, StringComparison.Ordinal) > -1)
326                     {
327                         var sep = path.IndexOf("\"", 2, StringComparison.Ordinal);
328                         var browserPath = path.Substring(1, sep - 1);
329                         var arg = "";
330                         if (sep < path.Length - 1)
331                         {
332                             arg = path.Substring(sep + 1);
333                         }
334                         myPath = arg + " " + myPath;
335                         System.Diagnostics.Process.Start(browserPath, myPath);
336                     }
337                     else
338                     {
339                         System.Diagnostics.Process.Start(path, myPath);
340                     }
341                 }
342                 else
343                 {
344                     System.Diagnostics.Process.Start(myPath);
345                 }
346             }
347             catch(Exception)
348             {
349             }
350         }
351
352         private void CreateAccountButton_Click(object sender, EventArgs e)
353             => this.OpenUrl("https://twitter.com/signup");
354
355         private void GetPeriodPanel_IntervalChanged(object sender, IntervalChangedEventArgs e)
356             => this.IntervalChanged?.Invoke(sender, e);
357     }
358
359     public class IntervalChangedEventArgs : EventArgs
360     {
361         public bool UserStream;
362         public bool Timeline;
363         public bool Reply;
364         public bool DirectMessage;
365         public bool PublicSearch;
366         public bool Lists;
367         public bool UserTimeline;
368
369         public static IntervalChangedEventArgs ResetAll => new IntervalChangedEventArgs
370         {
371             UserStream = true,
372             Timeline = true,
373             Reply = true,
374             DirectMessage = true,
375             PublicSearch = true,
376             Lists = true,
377             UserTimeline = true,
378         };
379     }
380 }