OSDN Git Service

ArgumentExceptionのコンストラクタにparamNameが指定されていないか不正である箇所を修正 (CA2208)
[opentween/open-tween.git] / OpenTween / Connection / TwipplePhoto.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2013 ANIKITI (@anikiti07) <https://twitter.com/anikiti07>
3 //           (c) 2014 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
4 // All rights reserved.
5 //
6 // This file is part of OpenTween.
7 //
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 3 of the License, or (at your option)
11 // any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 // for more details.
17 //
18 // You should have received a copy of the GNU General Public License along
19 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
20 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
21 // Boston, MA 02110-1301, USA.
22
23 using System;
24 using System.Collections.Generic;
25 using System.IO;
26 using System.Linq;
27 using System.Net;
28 using System.Threading.Tasks;
29 using System.Windows.Forms;
30 using System.Xml;
31 using System.Xml.Linq;
32 using System.Xml.XPath;
33 using OpenTween.Api;
34
35 namespace OpenTween.Connection
36 {
37     public sealed class TwipplePhoto : IMediaUploadService
38     {
39         private static readonly long MaxFileSize = 4L * 1024 * 1024;
40         private static readonly IEnumerable<string> SupportedPictureExtensions = new[]
41         {
42             ".gif",
43             ".jpg",
44             ".png",
45         };
46
47         private readonly Twitter twitter;
48         private readonly TwippleApi twippleApi;
49
50         private TwitterConfiguration twitterConfig;
51
52         #region Constructors
53
54         public TwipplePhoto(Twitter twitter, TwitterConfiguration twitterConfig)
55         {
56             if (twitter == null)
57                 throw new ArgumentNullException("twitter");
58             if (twitterConfig == null)
59                 throw new ArgumentNullException("twitterConfig");
60
61             this.twitter = twitter;
62             this.twitterConfig = twitterConfig;
63
64             this.twippleApi = new TwippleApi(twitter.AccessToken, twitter.AccessTokenSecret);
65         }
66
67         #endregion
68
69         public int MaxMediaCount
70         {
71             get { return 1; }
72         }
73
74         public string SupportedFormatsStrForDialog
75         {
76             get
77             {
78                 var filterFormatExtensions = "";
79                 foreach (var pictureExtension in SupportedPictureExtensions)
80                 {
81                     filterFormatExtensions += '*';
82                     filterFormatExtensions += pictureExtension;
83                     filterFormatExtensions += ';';
84                 }
85                 return "Image Files(" + filterFormatExtensions + ")|" + filterFormatExtensions;
86             }
87         }
88
89         public bool CheckFileExtension(string fileExtension)
90         {
91             return SupportedPictureExtensions.Contains(fileExtension, StringComparer.OrdinalIgnoreCase);
92         }
93
94         public bool CheckFileSize(string fileExtension, long fileSize)
95         {
96             var maxFileSize = this.GetMaxFileSize(fileExtension);
97             return maxFileSize == null || fileSize <= maxFileSize.Value;
98         }
99
100         public long? GetMaxFileSize(string fileExtension)
101         {
102             return MaxFileSize;
103         }
104
105         public async Task PostStatusAsync(string text, long? inReplyToStatusId, string[] filePaths)
106         {
107             if (filePaths.Length != 1)
108                 throw new ArgumentOutOfRangeException("filePaths");
109
110             var file = new FileInfo(filePaths[0]);
111
112             if (!file.Exists)
113                 throw new ArgumentException("Err:File isn't exists.", "filePaths[0]");
114
115             var xml = await this.twippleApi.UploadFileAsync(file)
116                 .ConfigureAwait(false);
117
118             var imageUrlElm = xml.XPathSelectElement("/rsp/mediaurl");
119             if (imageUrlElm == null)
120                 throw new WebApiException("Invalid API response", xml.ToString());
121
122             var textWithImageUrl = text + " " + imageUrlElm.Value.Trim();
123
124             await Task.Run(() => this.twitter.PostStatus(textWithImageUrl, inReplyToStatusId))
125                 .ConfigureAwait(false);
126         }
127
128         public int GetReservedTextLength(int mediaCount)
129         {
130             return this.twitterConfig.ShortUrlLength;
131         }
132
133         public void UpdateTwitterConfiguration(TwitterConfiguration config)
134         {
135             this.twitterConfig = config;
136         }
137
138         public class TwippleApi : HttpConnectionOAuthEcho
139         {
140             private static readonly Uri UploadEndpoint = new Uri("http://p.twipple.jp/api/upload2");
141
142             public TwippleApi(string twitterAccessToken, string twitterAccessTokenSecret)
143                 : base(new Uri("http://api.twitter.com/"), new Uri("https://api.twitter.com/1.1/account/verify_credentials.json"))
144             {
145                 this.Initialize(ApplicationSettings.TwitterConsumerKey, ApplicationSettings.TwitterConsumerSecret,
146                     twitterAccessToken, twitterAccessTokenSecret, "", "");
147
148                 this.InstanceTimeout = 60000;
149             }
150
151             /// <summary>
152             /// 画像のアップロードを行います
153             /// </summary>
154             /// <exception cref="WebApiException"/>
155             /// <exception cref="XmlException"/>
156             public async Task<XDocument> UploadFileAsync(FileInfo file)
157             {
158                 // 参照: http://p.twipple.jp/wiki/API_Upload2/ja
159
160                 var param = new Dictionary<string, string>
161                 {
162                     {"upload_from", Application.ProductName},
163                 };
164                 var paramFiles = new List<KeyValuePair<string, FileInfo>>
165                 {
166                     new KeyValuePair<string, FileInfo>("media", file),
167                 };
168                 var response = "";
169
170                 var uploadTask = Task.Run(() => this.GetContent(HttpConnection.PostMethod,
171                     UploadEndpoint, param, paramFiles, ref response, null, null));
172
173                 var ret = await uploadTask.ConfigureAwait(false);
174
175                 if (ret != HttpStatusCode.OK)
176                     throw new WebApiException("Err:" + ret, response);
177
178                 return XDocument.Parse(response);
179             }
180         }
181     }
182 }