OSDN Git Service

HttpTwitter.SendDirectMessageメソッドをTwitterApiクラスに置き換え
[opentween/open-tween.git] / OpenTween / Connection / Mobypicture.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2014 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
4 //
5 // This file is part of OpenTween.
6 //
7 // This program is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by the Free
9 // Software Foundation; either version 3 of the License, or (at your option)
10 // any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 // for more details.
16 //
17 // You should have received a copy of the GNU General Public License along
18 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 // Boston, MA 02110-1301, USA.
21
22 using System;
23 using System.Collections.Generic;
24 using System.IO;
25 using System.Linq;
26 using System.Net;
27 using System.Text;
28 using System.Threading.Tasks;
29 using System.Windows.Forms;
30 using System.Xml.Linq;
31 using System.Xml.XPath;
32 using OpenTween.Api.DataModel;
33
34 namespace OpenTween.Connection
35 {
36     public class Mobypicture : IMediaUploadService
37     {
38         private static readonly long MaxFileSize = 5L * 1024 * 1024; // 上限不明
39
40         // 参照: http://developers.mobypicture.com/documentation/1-0/postmedia/
41         private static readonly IEnumerable<string> AllowedExtensions = new[]
42         {
43             // Photo
44             ".jpg",
45             ".gif",
46             ".png",
47             ".bmp",
48
49             // Video
50             ".flv",
51             ".mpg",
52             ".mpeg",
53             ".mkv",
54             ".wmv",
55             ".mov",
56             ".3gp",
57             ".mp4",
58             ".avi",
59
60             // Audio
61             ".mp3",
62             ".wma",
63             ".aac",
64             ".aif",
65             ".au",
66             ".flac",
67             ".ra",
68             ".wav",
69             ".ogg",
70             ".3gp",
71         };
72
73         private readonly Twitter twitter;
74         private readonly MobypictureApi mobypictureApi;
75
76         private TwitterConfiguration twitterConfig;
77
78         public Mobypicture(Twitter twitter, TwitterConfiguration twitterConfig)
79         {
80             if (twitter == null)
81                 throw new ArgumentNullException(nameof(twitter));
82             if (twitterConfig == null)
83                 throw new ArgumentNullException(nameof(twitterConfig));
84
85             this.twitter = twitter;
86             this.twitterConfig = twitterConfig;
87
88             this.mobypictureApi = new MobypictureApi(twitter.AccessToken, twitter.AccessTokenSecret);
89         }
90
91         public int MaxMediaCount
92         {
93             get { return 1; }
94         }
95
96         public string SupportedFormatsStrForDialog
97         {
98             get
99             {
100                 var filterFormatExtensions = "";
101                 foreach (var pictureExtension in AllowedExtensions)
102                 {
103                     filterFormatExtensions += '*' + pictureExtension + ';';
104                 }
105                 return "Media Files(" + filterFormatExtensions + ")|" + filterFormatExtensions;
106             }
107         }
108
109         public bool CheckFileExtension(string fileExtension)
110         {
111             return AllowedExtensions.Contains(fileExtension, StringComparer.OrdinalIgnoreCase);
112         }
113
114         public bool CheckFileSize(string fileExtension, long fileSize)
115         {
116             var maxFileSize = this.GetMaxFileSize(fileExtension);
117             return maxFileSize == null || fileSize <= maxFileSize.Value;
118         }
119
120         public long? GetMaxFileSize(string fileExtension)
121         {
122             return MaxFileSize;
123         }
124
125         public async Task PostStatusAsync(string text, long? inReplyToStatusId, IMediaItem[] mediaItems)
126         {
127             if (mediaItems == null)
128                 throw new ArgumentNullException(nameof(mediaItems));
129
130             if (mediaItems.Length != 1)
131                 throw new ArgumentOutOfRangeException(nameof(mediaItems));
132
133             var item = mediaItems[0];
134
135             if (item == null)
136                 throw new ArgumentException("Err:Media not specified.");
137
138             if (!item.Exists)
139                 throw new ArgumentException("Err:Media not found.");
140
141             var xml = await this.mobypictureApi.UploadFileAsync(item, text)
142                 .ConfigureAwait(false);
143
144             var imageUrlElm = xml.XPathSelectElement("/rsp/media/mediaurl");
145             if (imageUrlElm == null)
146                 throw new WebApiException("Invalid API response", xml.ToString());
147
148             var textWithImageUrl = text + " " + imageUrlElm.Value.Trim();
149
150             await this.twitter.PostStatus(textWithImageUrl, inReplyToStatusId)
151                 .ConfigureAwait(false);
152         }
153
154         public int GetReservedTextLength(int mediaCount)
155         {
156             return this.twitterConfig.ShortUrlLength;
157         }
158
159         public void UpdateTwitterConfiguration(TwitterConfiguration config)
160         {
161             this.twitterConfig = config;
162         }
163
164         public class MobypictureApi : HttpConnectionOAuthEcho
165         {
166             private static readonly Uri UploadEndpoint = new Uri("https://api.mobypicture.com/2.0/upload.xml");
167
168             public MobypictureApi(string twitterAccessToken, string twitterAccessTokenSecret)
169                 : base(new Uri("http://api.twitter.com/"), new Uri("https://api.twitter.com/1.1/account/verify_credentials.json"))
170             {
171                 this.Initialize(ApplicationSettings.TwitterConsumerKey, ApplicationSettings.TwitterConsumerSecret,
172                     twitterAccessToken, twitterAccessTokenSecret, "", "");
173
174                 this.InstanceTimeout = 60000;
175             }
176
177             /// <summary>
178             /// 画像のアップロードを行います
179             /// </summary>
180             /// <exception cref="WebApiException"/>
181             /// <exception cref="XmlException"/>
182             public async Task<XDocument> UploadFileAsync(IMediaItem item, string message)
183             {
184                 // 参照: http://developers.mobypicture.com/documentation/2-0/upload/
185
186                 var param = new Dictionary<string, string>
187                 {
188                     ["key"] = ApplicationSettings.MobypictureKey,
189                     ["message"] = message,
190                 };
191                 var paramFiles = new List<KeyValuePair<string, IMediaItem>>
192                 {
193                     new KeyValuePair<string, IMediaItem>("media", item),
194                 };
195                 var response = "";
196
197                 var uploadTask = Task.Run(() => this.GetContent(HttpConnection.PostMethod,
198                     UploadEndpoint, param, paramFiles, ref response, null, null));
199
200                 var ret = await uploadTask.ConfigureAwait(false);
201
202                 if (ret != HttpStatusCode.OK)
203                     throw new WebApiException("Err:" + ret, response);
204
205                 return XDocument.Parse(response);
206             }
207         }
208     }
209 }