// OpenTween - Client of Twitter // Copyright (c) 2013 kim_upsilon (@kim_upsilon) // All rights reserved. // // This file is part of OpenTween. // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 3 of the License, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with this program. If not, see , or write to // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, // Boston, MA 02110-1301, USA. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; using OpenTween.Api.DataModel; namespace OpenTween.Connection { public class Imgur : IMediaUploadService { private readonly static long MaxFileSize = 10L * 1024 * 1024; private readonly static Uri UploadEndpoint = new Uri("https://api.imgur.com/3/image.xml"); private readonly static IEnumerable SupportedExtensions = new[] { ".jpg", ".jpeg", ".gif", ".png", ".tif", ".tiff", ".bmp", ".pdf", ".xcf", }; private readonly Twitter twitter; private TwitterConfiguration twitterConfig; public Imgur(Twitter tw, TwitterConfiguration twitterConfig) { this.twitter = tw; this.twitterConfig = twitterConfig; } public int MaxMediaCount { get { return 1; } } public string SupportedFormatsStrForDialog { get { var formats = new StringBuilder(); foreach (var extension in SupportedExtensions) formats.AppendFormat("*{0};", extension); return "Image Files(" + formats + ")|" + formats; } } public bool CheckFileExtension(string fileExtension) { return SupportedExtensions.Contains(fileExtension, StringComparer.OrdinalIgnoreCase); } public bool CheckFileSize(string fileExtension, long fileSize) { var maxFileSize = this.GetMaxFileSize(fileExtension); return maxFileSize == null || fileSize <= maxFileSize.Value; } public long? GetMaxFileSize(string fileExtension) { return MaxFileSize; } public async Task PostStatusAsync(string text, long? inReplyToStatusId, IMediaItem[] mediaItems) { if (mediaItems == null) throw new ArgumentNullException(nameof(mediaItems)); if (mediaItems.Length != 1) throw new ArgumentOutOfRangeException(nameof(mediaItems)); var item = mediaItems[0]; if (item == null) throw new ArgumentException("Err:Media not specified."); if (!item.Exists) throw new ArgumentException("Err:Media not found."); XDocument xml; try { xml = await this.UploadFileAsync(item, text) .ConfigureAwait(false); } catch (HttpRequestException ex) { throw new WebApiException("Err:" + ex.Message, ex); } catch (OperationCanceledException ex) { throw new WebApiException("Err:Timeout", ex); } var imageElm = xml.Element("data"); if (imageElm.Attribute("success").Value != "1") throw new WebApiException("Err:" + imageElm.Attribute("status").Value); var imageUrl = imageElm.Element("link").Value; var textWithImageUrl = text + " " + imageUrl.Trim(); await this.twitter.PostStatus(textWithImageUrl, inReplyToStatusId) .ConfigureAwait(false); } public int GetReservedTextLength(int mediaCount) { return this.twitterConfig.ShortUrlLength; } public void UpdateTwitterConfiguration(TwitterConfiguration config) { this.twitterConfig = config; } public async Task UploadFileAsync(IMediaItem item, string title) { using (var content = new MultipartFormDataContent()) using (var mediaStream = item.OpenRead()) using (var mediaContent = new StreamContent(mediaStream)) using (var titleContent = new StringContent(title)) { content.Add(mediaContent, "image", item.Name); content.Add(titleContent, "title"); using (var request = new HttpRequestMessage(HttpMethod.Post, UploadEndpoint)) { request.Headers.Authorization = new AuthenticationHeaderValue("Client-ID", ApplicationSettings.ImgurClientID); request.Content = content; using (var response = await Networking.Http.SendAsync(request).ConfigureAwait(false)) { response.EnsureSuccessStatusCode(); using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) { return XDocument.Load(stream); } } } } } } }