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.
10 // This file is part of OpenTween.
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)
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
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.
30 using System.Collections.Generic;
31 using System.Windows.Forms;
32 using System.Xml.Serialization;
33 using OpenTween.Connection;
34 using OpenTween.Thumbnail;
38 [XmlSerializerAssembly(null, null)] // OpenTween アセンブリ内の XmlSerializerContract を使用させる
39 public class SettingCommon : SettingBase<SettingCommon>
41 #region "Settingクラス基本"
42 public static SettingCommon Load(string settingsPath)
43 => LoadSettings(settingsPath);
45 public void Save(string settingsPath)
46 => SaveSettings(this, settingsPath);
49 public List<UserAccount> UserAccounts = new();
51 public Guid? SelectedAccountKey { get; set; } = null;
54 public UserAccount? SelectedAccount
55 => this.UserAccounts.Find(x => x.UniqueKey == this.SelectedAccountKey);
57 public string UserName = "";
60 public string Password = "";
62 public string EncryptPassword
64 get => this.Encrypt(this.Password);
65 set => this.Password = this.Decrypt(value);
68 public string Token = "";
70 public string TokenSecret = "";
72 public string EncryptTokenSecret
74 get => this.Encrypt(this.TokenSecret);
75 set => this.TokenSecret = this.Decrypt(value);
78 private string Encrypt(string password)
80 if (MyCommon.IsNullOrEmpty(password)) password = "";
81 if (password.Length > 0)
85 return MyCommon.EncryptString(password);
98 private string Decrypt(string password)
100 if (MyCommon.IsNullOrEmpty(password)) password = "";
101 if (password.Length > 0)
105 password = MyCommon.DecryptString(password);
115 public long UserId = 0;
116 public List<string> TabList = new();
117 public int TimelinePeriod = 90;
118 public int ReplyPeriod = 180;
119 public int DMPeriod = 600;
120 public int PubSearchPeriod = 180;
121 public int ListsPeriod = 180;
124 /// 起動時読み込み分を既読にするか。trueなら既読として処理
126 public bool Read = true;
128 public bool ListLock = false;
129 public MyCommon.IconSizes IconSize = MyCommon.IconSizes.Icon16;
130 public bool NewAllPop = true;
131 public string TranslateLanguage = Properties.Resources.TranslateDefaultLanguage;
134 /// サウンド再生(タブ別設定より優先)
136 public bool PlaySound = false;
139 /// 未読管理。trueなら未読管理する
141 public bool UnreadManage = true;
144 /// 片思い表示。trueなら片思い表示する
146 public bool OneWayLove = true;
148 public MyCommon.NameBalloonEnum NameBalloon = MyCommon.NameBalloonEnum.NickName;
149 public bool PostCtrlEnter = true;
150 public bool PostShiftEnter = false;
151 public int CountApi = 60;
152 public int CountApiReply = 40;
153 public bool PostAndGet = true;
154 public bool DispUsername = false;
155 public bool MinimizeToTray = false;
156 public bool CloseToExit = false;
157 public MyCommon.DispTitleEnum DispLatestPost = MyCommon.DispTitleEnum.Post;
158 public bool SortOrderLock = false;
163 public bool ViewTabBottom = true;
165 public bool TinyUrlResolve = true;
166 public bool StartupVersion = true;
167 public bool StartupFollowers = true;
170 /// Twitter API v2 の使用を有効にする
173 public bool EnableTwitterV2Api => false;
175 public bool RestrictFavCheck = false;
176 public bool AlwaysTop = false;
177 public string CultureCode = "";
178 public bool UrlConvertAuto = false;
179 public int SortColumn = 3;
180 public int SortOrder = 1;
181 public bool IsMonospace = false;
182 public bool ReadOldPosts = false;
183 public string Language = "OS";
184 public bool Nicoms = false;
185 public List<string> HashTags = new();
186 public string HashSelected = "";
187 public bool HashIsPermanent = false;
188 public bool HashIsHead = false;
189 public bool HashIsNotAddToAtReply = true;
190 public bool PreviewEnable = true;
191 public bool StatusAreaAtBottom = true;
193 public MyCommon.UrlConverter AutoShortUrlFirst = MyCommon.UrlConverter.Uxnu;
194 public bool UseUnreadStyle = true;
195 public string DateTimeFormat = "yyyy/MM/dd H:mm:ss";
196 public int DefaultTimeOut = 20;
198 /// <summary>画像アップロードのタイムアウト設定 (秒)</summary>
199 public int UploadImageTimeout { get; set; } = 60;
201 public bool RetweetNoConfirm = false;
202 public bool LimitBalloon = false;
203 public bool TabIconDisp = true;
204 public MyCommon.REPLY_ICONSTATE ReplyIconState = MyCommon.REPLY_ICONSTATE.StaticIcon;
205 public bool WideSpaceConvert = true;
206 public bool ReadOwnPost = false;
207 public bool GetFav = true;
208 public string BilyUser = "";
209 public string BitlyPwd = "";
211 /// <summary>Bitly API アクセストークン</summary>
212 public string BitlyAccessToken { get; set; } = "";
214 public bool ShowGrid = false;
215 public bool UseAtIdSupplement = true;
216 public bool UseHashSupplement = true;
218 [XmlElement(ElementName = "TwitterUrl")]
219 public string TwitterApiHost = "api.twitter.com";
221 public bool HotkeyEnabled = false;
222 public Keys HotkeyModifier = Keys.None;
223 public Keys HotkeyKey = Keys.None;
224 public int HotkeyValue = 0;
225 public bool BlinkNewMentions = false;
226 public bool FocusLockToStatusText = false;
227 public bool UseAdditionalCount = false;
228 public int MoreCountApi = 200;
229 public int FirstCountApi = 100;
230 public int SearchCountApi = 100;
231 public int FavoritesCountApi = 40;
232 public int UserTimelineCountApi = 20;
233 public int UserTimelinePeriod = 600;
234 public bool OpenUserTimeline = true;
235 public int ListCountApi = 100;
236 public int UseImageService = 0;
237 public string UseImageServiceName = "";
240 public MyCommon.ListItemDoubleClickActionType ListDoubleClickAction { get; set; } = MyCommon.ListItemDoubleClickActionType.Reply;
242 [XmlElement(ElementName = nameof(ListDoubleClickAction))]
243 public int ListDoubleClickActionNumeric
245 get => (int)this.ListDoubleClickAction;
246 set => this.ListDoubleClickAction = (MyCommon.ListItemDoubleClickActionType)value;
249 public string UserAppointUrl = "";
250 public bool HideDuplicatedRetweets = false;
251 public bool EnableImgAzyobuziNet = true;
252 public bool ImgAzyobuziNetDisabledInDM = true;
253 public int MapThumbnailHeight = 200;
254 public int MapThumbnailWidth = 200;
255 public int MapThumbnailZoom = 15;
256 public MapProvider MapThumbnailProvider = MapProvider.OpenStreetMap;
258 /// <summary>Listの発言取得に公式RTを含める</summary>
259 public bool IsListsIncludeRts = true;
261 public bool TabMouseLock = false;
262 public bool IsUseNotifyGrowl = false;
263 public bool ForceIPv4 = false;
264 public bool ErrorReportAnonymous = true;
266 /// <summary>pic.twitter.com への画像アップロード時に JPEG への変換を回避する</summary>
267 public bool AlphaPNGWorkaround { get; set; } = false;
269 /// <summary>アップデート通知を無視するバージョン番号</summary>
271 public Version? SkipUpdateVersion
273 get => MyCommon.IsNullOrEmpty(this.SkipUpdateVersionStr) ? null : Version.Parse(this.SkipUpdateVersionStr);
274 set => this.SkipUpdateVersionStr = value == null ? "" : value.ToString();
277 [XmlElement(ElementName = nameof(SkipUpdateVersion))]
278 public string SkipUpdateVersionStr { get; set; } = "";
280 public void Validate()
282 if (this.TimelinePeriod < 0)
283 this.TimelinePeriod = 15;
285 if (this.ReplyPeriod < 0)
286 this.ReplyPeriod = 15;
288 if (this.DMPeriod < 0)
291 if (this.PubSearchPeriod < 0)
292 this.PubSearchPeriod = 30;
294 if (this.UserTimelinePeriod < 0)
295 this.UserTimelinePeriod = 15;
297 if (this.ListsPeriod < 0)
298 this.ListsPeriod = 15;
300 if (!Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.Timeline, this.CountApi))
303 if (!Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.Reply, this.CountApiReply))
304 this.CountApiReply = 40;
306 if (this.MoreCountApi != 0 && !Twitter.VerifyMoreApiResultCount(this.MoreCountApi))
307 this.MoreCountApi = 200;
309 if (this.FirstCountApi != 0 && !Twitter.VerifyFirstApiResultCount(this.FirstCountApi))
310 this.FirstCountApi = 100;
312 if (this.FavoritesCountApi != 0 && !Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.Favorites, this.FavoritesCountApi))
313 this.FavoritesCountApi = 40;
315 if (this.ListCountApi != 0 && !Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.List, this.ListCountApi))
316 this.ListCountApi = 100;
318 if (this.SearchCountApi != 0 && !Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.PublicSearch, this.SearchCountApi))
319 this.SearchCountApi = 100;
321 if (this.UserTimelineCountApi != 0 && !Twitter.VerifyApiResultCount(MyCommon.WORKERTYPE.UserTimeline, this.UserTimelineCountApi))
322 this.UserTimelineCountApi = 20;
324 // 廃止サービスが選択されていた場合ux.nuへ読み替え
325 if (this.AutoShortUrlFirst < 0)
326 this.AutoShortUrlFirst = MyCommon.UrlConverter.Uxnu;
328 UserAccount? selectedAccount;
329 if (this.SelectedAccountKey != null)
331 selectedAccount = this.SelectedAccount;
335 selectedAccount = this.UserAccounts.Find(
336 x => string.Equals(x.Username, this.UserName, StringComparison.InvariantCultureIgnoreCase)
340 this.SelectedAccountKey = selectedAccount?.UniqueKey;
342 if (selectedAccount?.UserId == 0)
343 selectedAccount.UserId = this.UserId;
345 if (MyCommon.IsNullOrEmpty(this.Token))
350 public class UserAccount
352 public Guid UniqueKey { get; set; } = Guid.NewGuid();
354 public string Username = "";
355 public long UserId = 0;
357 public APIAuthType TwitterAuthType { get; set; }
359 public string TwitterOAuth1ConsumerKey { get; set; } = "";
362 public string TwitterOAuth1ConsumerSecret { get; set; } = "";
364 public string TwitterOAuth1ConsumerSecretEncrypted
366 get => this.Encrypt(this.TwitterOAuth1ConsumerSecret);
367 set => this.TwitterOAuth1ConsumerSecret = this.Decrypt(value);
371 public string TwitterComCookie { get; set; } = "";
373 public string TwitterComCookieEncrypted
375 get => this.Encrypt(this.TwitterComCookie);
376 set => this.TwitterComCookie = this.Decrypt(value);
379 public string Token = "";
382 public string TokenSecret = "";
384 public string EncryptTokenSecret
386 get => this.Encrypt(this.TokenSecret);
387 set => this.TokenSecret = this.Decrypt(value);
390 public TwitterAppToken GetTwitterAppToken()
394 AuthType = this.TwitterAuthType,
395 OAuth1CustomConsumerKey = MyCommon.IsNullOrEmpty(this.TwitterOAuth1ConsumerKey) ? null : ApiKey.Create(this.TwitterOAuth1ConsumerKey),
396 OAuth1CustomConsumerSecret = MyCommon.IsNullOrEmpty(this.TwitterOAuth1ConsumerSecret) ? null : ApiKey.Create(this.TwitterOAuth1ConsumerSecret),
397 TwitterComCookie = this.TwitterComCookie,
401 public ITwitterCredential GetTwitterCredential()
403 var appToken = this.GetTwitterAppToken();
405 return appToken.AuthType switch
408 => new TwitterCredentialOAuth1(appToken, this.TwitterOAuth1ConsumerKey, this.TwitterOAuth1ConsumerSecret),
409 APIAuthType.TwitterComCookie
410 => new TwitterCredentialCookie(appToken),
411 _ => new TwitterCredentialNone(),
415 private string Encrypt(string password)
417 if (MyCommon.IsNullOrEmpty(password)) password = "";
418 if (password.Length > 0)
422 return MyCommon.EncryptString(password);
435 private string Decrypt(string password)
437 if (MyCommon.IsNullOrEmpty(password)) password = "";
438 if (password.Length > 0)
442 password = MyCommon.DecryptString(password);
452 public override string ToString()
456 public enum APIAuthType