OSDN Git Service

画像共有サービスに使用するインタフェースを設計し直し
[opentween/open-tween.git] / OpenTween / Connection / Imgur.cs
index 9b01834..a01c82a 100644 (file)
 
 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.Net;
-using System.IO;
+using System.Threading.Tasks;
 using System.Xml.Linq;
-using System.Xml;
+using OpenTween.Api;
 
 namespace OpenTween.Connection
 {
-    public class Imgur : HttpConnectionOAuth, IMultimediaShareService
+    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");
@@ -48,132 +50,123 @@ namespace OpenTween.Connection
             ".xcf",
         };
 
-        private readonly Twitter _twitter;
+        private readonly Twitter twitter;
+        private TwitterConfiguration twitterConfig;
 
-        public Imgur(Twitter tw)
+        public Imgur(Twitter tw, TwitterConfiguration twitterConfig)
         {
-            this._twitter = tw;
-
-            Initialize(ApplicationSettings.TwitterConsumerKey, ApplicationSettings.TwitterConsumerSecret,
-                       tw.AccessToken, tw.AccessTokenSecret,
-                       "", "");
+            this.twitter = tw;
+            this.twitterConfig = twitterConfig;
         }
 
-        protected override void AppendOAuthInfo(HttpWebRequest webRequest, Dictionary<string, string> query, string token, string tokenSecret)
+        public int MaxMediaCount
         {
-            webRequest.Headers[HttpRequestHeader.Authorization] =
-                string.Format("Client-ID {0}", ApplicationSettings.ImgurClientID);
+            get { return 1; }
         }
 
-        public string Upload(ref string filePath, ref string message, long? reply_to)
+        public string SupportedFormatsStrForDialog
         {
-            if (!File.Exists(filePath))
-                return "Err:File isn't exists.";
-
-            var mediaFile = new FileInfo(filePath);
-            var content = "";
-            HttpStatusCode result;
-            try
-            {
-                result = this.UploadFile(mediaFile, message, ref content);
-            }
-            catch (Exception ex)
+            get
             {
-                return "Err:" + ex.Message;
-            }
+                var formats = new StringBuilder();
 
-            if (result != HttpStatusCode.OK)
-            {
-                return "Err:" + result;
-            }
+                foreach (var extension in SupportedExtensions)
+                    formats.AppendFormat("*{0};", extension);
 
-            var imageUrl = "";
-            try
-            {
-                var xdoc = XDocument.Parse(content);
-                var image = xdoc.Element("data");
-                if (image.Attribute("success").Value != "1")
-                {
-                    return "APIErr:" + image.Attribute("status").Value;
-                }
-                imageUrl = image.Element("link").Value;
-            }
-            catch (XmlException ex)
-            {
-                return "XmlErr:" + ex.Message;
+                return "Image Files(" + formats + ")|" + formats;
             }
+        }
 
-            filePath = "";
-            if (message == null)
-                message = "";
+        public bool CheckFileExtension(string fileExtension)
+        {
+            return SupportedExtensions.Contains(fileExtension, StringComparer.OrdinalIgnoreCase);
+        }
 
-            // Post to twitter
-            if (message.Length + AppendSettingDialog.Instance.TwitterConfiguration.CharactersReservedPerMedia + 1 > 140)
-            {
-                message = message.Substring(0, 140 - AppendSettingDialog.Instance.TwitterConfiguration.CharactersReservedPerMedia - 1) + " " + imageUrl;
-            }
-            else
-            {
-                message += " " + imageUrl;
-            }
-            return _twitter.PostStatus(message, reply_to);
+        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;
         }
 
-        private HttpStatusCode UploadFile(FileInfo mediaFile, string message, ref string content)
+        public async Task PostStatusAsync(string text, long? inReplyToStatusId, string[] filePaths)
         {
-            if (!CheckValidExtension(mediaFile.Extension))
-                throw new ArgumentException("Service don't support this filetype", "mediaFile");
-            if (!CheckValidFilesize(mediaFile.Extension, mediaFile.Length))
-                throw new ArgumentException("File is too large", "mediaFile");
+            if (filePaths.Length != 1)
+                throw new ArgumentOutOfRangeException("filePaths");
+
+            var file = new FileInfo(filePaths[0]);
+
+            if (!file.Exists)
+                throw new ArgumentException("File isn't exists.", "filePaths[0]");
 
-            var param = new Dictionary<string, string>
+            XDocument xml;
+            try
             {
-                {"title", message},
-            };
-            var binary = new List<KeyValuePair<string, FileInfo>>
+                xml = await this.UploadFileAsync(file, text)
+                    .ConfigureAwait(false);
+            }
+            catch (HttpRequestException ex)
             {
-                new KeyValuePair<string, FileInfo>("image", mediaFile)
-            };
-            this.InstanceTimeout = 60000;
+                throw new WebApiException("Err:" + ex.Message, ex);
+            }
 
-            return this.GetContent(PostMethod, UploadEndpoint, param, binary, ref content, null, null);
-        }
+            var imageElm = xml.Element("data");
 
-        public bool CheckValidExtension(string ext)
-        {
-            return SupportedExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase);
-        }
+            if (imageElm.Attribute("success").Value != "1")
+                throw new WebApiException("Err:" + imageElm.Attribute("status").Value);
 
-        public string GetFileOpenDialogFilter()
-        {
-            var formats = new StringBuilder();
+            var imageUrl = imageElm.Element("link").Value;
 
-            foreach (var extension in SupportedExtensions)
-                formats.AppendFormat("*{0};", extension);
+            var textWithImageUrl = text + " " + imageUrl.Trim();
 
-            return "Image Files(" + formats + ")|" + formats;
+            await Task.Run(() => this.twitter.PostStatus(textWithImageUrl, inReplyToStatusId))
+                .ConfigureAwait(false);
         }
 
-        public MyCommon.UploadFileType GetFileType(string ext)
+        public int GetReservedTextLength(int mediaCount)
         {
-            return this.CheckValidExtension(ext)
-                ? MyCommon.UploadFileType.Picture
-                : MyCommon.UploadFileType.Invalid;
+            return this.twitterConfig.ShortUrlLength;
         }
 
-        public bool IsSupportedFileType(MyCommon.UploadFileType type)
+        public void UpdateTwitterConfiguration(TwitterConfiguration config)
         {
-            return type == MyCommon.UploadFileType.Picture;
+            this.twitterConfig = config;
         }
 
-        public bool CheckValidFilesize(string ext, long fileSize)
+        public async Task<XDocument> UploadFileAsync(FileInfo file, string title)
         {
-            return CheckValidExtension(ext) && fileSize <= MaxFileSize;
-        }
+            using (var content = new MultipartFormDataContent())
+            using (var fileStream = file.OpenRead())
+            using (var fileContent = new StreamContent(fileStream))
+            using (var titleContent = new StringContent(title))
+            {
+                content.Add(fileContent, "image", file.Name);
+                content.Add(titleContent, "title");
 
-        public bool Configuration(string key, object value)
-        {
-            throw new NotImplementedException();
+                using (var http = MyCommon.CreateHttpClient())
+                using (var request = new HttpRequestMessage(HttpMethod.Post, UploadEndpoint))
+                {
+                    http.Timeout = TimeSpan.FromMinutes(1);
+
+                    request.Headers.Authorization =
+                        new AuthenticationHeaderValue("Client-ID", ApplicationSettings.ImgurClientID);
+                    request.Content = content;
+
+                    using (var response = await http.SendAsync(request).ConfigureAwait(false))
+                    {
+                        response.EnsureSuccessStatusCode();
+
+                        using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
+                        {
+                            return XDocument.Load(stream);
+                        }
+                    }
+                }
+            }
         }
     }
 }