OSDN Git Service

6f9b2a571ae395d57e8649352ca1f188b54f69d6
[opentween/open-tween.git] / OpenTween / Connection / Imgur.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2013 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.Http;
27 using System.Net.Http.Headers;
28 using System.Text;
29 using System.Threading.Tasks;
30 using System.Xml.Linq;
31 using OpenTween.Api;
32
33 namespace OpenTween.Connection
34 {
35     public class Imgur : IMediaUploadService
36     {
37         private readonly static long MaxFileSize = 10L * 1024 * 1024;
38         private readonly static Uri UploadEndpoint = new Uri("https://api.imgur.com/3/image.xml");
39
40         private readonly static IEnumerable<string> SupportedExtensions = new[]
41         {
42             ".jpg",
43             ".jpeg",
44             ".gif",
45             ".png",
46             ".tif",
47             ".tiff",
48             ".bmp",
49             ".pdf",
50             ".xcf",
51         };
52
53         private readonly Twitter twitter;
54         private TwitterConfiguration twitterConfig;
55
56         public Imgur(Twitter tw, TwitterConfiguration twitterConfig)
57         {
58             this.twitter = tw;
59             this.twitterConfig = twitterConfig;
60         }
61
62         public int MaxMediaCount
63         {
64             get { return 1; }
65         }
66
67         public string SupportedFormatsStrForDialog
68         {
69             get
70             {
71                 var formats = new StringBuilder();
72
73                 foreach (var extension in SupportedExtensions)
74                     formats.AppendFormat("*{0};", extension);
75
76                 return "Image Files(" + formats + ")|" + formats;
77             }
78         }
79
80         public bool CheckFileExtension(string fileExtension)
81         {
82             return SupportedExtensions.Contains(fileExtension, StringComparer.OrdinalIgnoreCase);
83         }
84
85         public bool CheckFileSize(string fileExtension, long fileSize)
86         {
87             var maxFileSize = this.GetMaxFileSize(fileExtension);
88             return maxFileSize == null || fileSize <= maxFileSize.Value;
89         }
90
91         public long? GetMaxFileSize(string fileExtension)
92         {
93             return MaxFileSize;
94         }
95
96         public async Task PostStatusAsync(string text, long? inReplyToStatusId, IMediaItem[] mediaItems)
97         {
98             if (mediaItems.Length != 1)
99                 throw new ArgumentOutOfRangeException("mediaItems");
100
101             var item = mediaItems[0] as FileMediaItem;
102
103             if (item == null)
104                 throw new NotImplementedException();
105
106             if (!item.Exists)
107                 throw new ArgumentException("File isn't exists.", "mediaItems[0]");
108
109             XDocument xml;
110             try
111             {
112                 xml = await this.UploadFileAsync(item.FileInfo, text)
113                     .ConfigureAwait(false);
114             }
115             catch (HttpRequestException ex)
116             {
117                 throw new WebApiException("Err:" + ex.Message, ex);
118             }
119
120             var imageElm = xml.Element("data");
121
122             if (imageElm.Attribute("success").Value != "1")
123                 throw new WebApiException("Err:" + imageElm.Attribute("status").Value);
124
125             var imageUrl = imageElm.Element("link").Value;
126
127             var textWithImageUrl = text + " " + imageUrl.Trim();
128
129             await Task.Run(() => this.twitter.PostStatus(textWithImageUrl, inReplyToStatusId))
130                 .ConfigureAwait(false);
131         }
132
133         public int GetReservedTextLength(int mediaCount)
134         {
135             return this.twitterConfig.ShortUrlLength;
136         }
137
138         public void UpdateTwitterConfiguration(TwitterConfiguration config)
139         {
140             this.twitterConfig = config;
141         }
142
143         public async Task<XDocument> UploadFileAsync(FileInfo file, string title)
144         {
145             using (var content = new MultipartFormDataContent())
146             using (var fileStream = file.OpenRead())
147             using (var fileContent = new StreamContent(fileStream))
148             using (var titleContent = new StringContent(title))
149             {
150                 content.Add(fileContent, "image", file.Name);
151                 content.Add(titleContent, "title");
152
153                 using (var request = new HttpRequestMessage(HttpMethod.Post, UploadEndpoint))
154                 {
155                     request.Headers.Authorization =
156                         new AuthenticationHeaderValue("Client-ID", ApplicationSettings.ImgurClientID);
157                     request.Content = content;
158
159                     using (var response = await Networking.Http.SendAsync(request).ConfigureAwait(false))
160                     {
161                         response.EnsureSuccessStatusCode();
162
163                         using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
164                         {
165                             return XDocument.Load(stream);
166                         }
167                     }
168                 }
169             }
170         }
171     }
172 }