OSDN Git Service

GIFMAGAZINE のサムネイル表示に対応
[opentween/open-tween.git] / OpenTween / Thumbnail / ThumbnailGenerator.cs
index 439c90d..03ccef1 100644 (file)
@@ -1,19 +1,19 @@
 // OpenTween - Client of Twitter
-// Copyright (c) 2012      kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// Copyright (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~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. 
-// 
+// for more details.
+//
 // You should have received a copy of the GNU General Public License along
 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Net.Http;
 using System.Text;
 using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
 using OpenTween.Thumbnail.Services;
 
 namespace OpenTween.Thumbnail
 {
     class ThumbnailGenerator
     {
-        private static List<IThumbnailService> generator = new List<IThumbnailService>();
+        public static List<IThumbnailService> Services { get; protected set; }
 
-        public static void InitializeGenerator()
+        internal static ImgAzyobuziNet ImgAzyobuziNetInstance { get; private set; }
+
+        static ThumbnailGenerator()
+        {
+            ThumbnailGenerator.Services = new List<IThumbnailService>();
+        }
+
+        public static void InitializeGenerator(HttpClient http)
         {
-            ThumbnailGenerator.generator = new List<IThumbnailService>()
+            ImgAzyobuziNetInstance = new ImgAzyobuziNet(http, autoupdate: true);
+
+            ThumbnailGenerator.Services = new List<IThumbnailService>()
             {
+                // ton.twitter.com
+                new TonTwitterCom(),
+
                 // DirectLink
                 new SimpleThumbnailService(@"^https?://.*(\.jpg|\.jpeg|\.gif|\.png|\.bmp)$", "${0}"),
 
                 // img.azyobuzi.net
-                new ImgAzyobuziNet(autoupdate: true),
+                ImgAzyobuziNetInstance,
 
                 // ImgUr
-                new SimpleThumbnailService(@"^http://(?:i\.)?imgur\.com/(\w+)(?:\..{3})?$", "http://img.imgur.com/${1}l.jpg"),
+                new SimpleThumbnailService(
+                    @"^http://(?:i\.)?imgur\.com/(\w+)(?:\..{3})?$",
+                    "http://img.imgur.com/${1}l.jpg",
+                    "http://img.imgur.com/${1}.jpg"),
 
                 // Twitpic
-                new SimpleThumbnailService(@"^http://(www\.)?twitpic\.com/(?<photoId>\w+)(/full/?)?$", "http://twitpic.com/show/thumb/${photoId}"),
+                new SimpleThumbnailService(
+                    @"^http://(www\.)?twitpic\.com/(?<photoId>\w+)(/full/?)?$",
+                    "http://twitpic.com/show/thumb/${photoId}",
+                    "http://twitpic.com/show/large/${photoId}"),
 
                 // yfrog
-                new SimpleThumbnailService(@"^http://yfrog\.com/(\w+)$", "${0}:small"),
+                new SimpleThumbnailService(
+                    @"^http://yfrog\.com/(\w+)$",
+                    "${0}:small",
+                    "${0}"),
 
                 // Lockerz
-                new SimpleThumbnailService(@"^http://(tweetphoto\.com/[0-9]+|pic\.gd/[a-z0-9]+|(lockerz|plixi)\.com/[ps]/[0-9]+)$", "http://api.plixi.com/api/tpapi.svc/imagefromurl?size=thumbnail&url=${0}"),
+                new SimpleThumbnailService(
+                    @"^http://(tweetphoto\.com/[0-9]+|pic\.gd/[a-z0-9]+|(lockerz|plixi)\.com/[ps]/[0-9]+)$",
+                    "http://api.plixi.com/api/tpapi.svc/imagefromurl?size=thumbnail&url=${0}",
+                    "http://api.plixi.com/api/tpapi.svc/imagefromurl?size=big&url=${0}"),
 
                 // MobyPicture
-                new SimpleThumbnailService(@"^http://moby\.to/(\w+)$", "http://mobypicture.com/?${1}:small"),
+                new SimpleThumbnailService(
+                    @"^http://moby\.to/(\w+)$",
+                    "http://mobypicture.com/?${1}:small",
+                    "http://mobypicture.com/?${1}:full"),
 
                 // 携帯百景
-                new SimpleThumbnailService(@"^http://movapic\.com/pic/(\w+)$", "http://image.movapic.com/pic/s_${1}.jpeg"),
+                new SimpleThumbnailService(
+                    @"^http://movapic\.com/pic/(\w+)$",
+                    "http://image.movapic.com/pic/s_${1}.jpeg",
+                    "http://image.movapic.com/pic/m_${1}.jpeg"),
 
                 // はてなフォトライフ
-                new SimpleThumbnailService(@"^http://f\.hatena\.ne\.jp/(([a-z])[a-z0-9_-]{1,30}[a-z0-9])/((\d{8})\d+)$", "http://img.f.hatena.ne.jp/images/fotolife/${2}/${1}/${4}/${3}_120.jpg"),
+                new SimpleThumbnailService(
+                    @"^http://f\.hatena\.ne\.jp/(([a-z])[a-z0-9_-]{1,30}[a-z0-9])/((\d{8})\d+)$",
+                    "http://img.f.hatena.ne.jp/images/fotolife/${2}/${1}/${4}/${3}_120.jpg",
+                    "http://img.f.hatena.ne.jp/images/fotolife/${2}/${1}/${4}/${3}.jpg"),
 
                 // PhotoShare
                 new SimpleThumbnailService(@"^http://(?:www\.)?bcphotoshare\.com/photos/\d+/(\d+)$", "http://images.bcphotoshare.com/storages/${1}/thumb180.jpg"),
 
-                // PhotoShare
-                new PhotoShareShortlink(@"^http://bctiny\.com/p(\w+)$"),
-
                 // img.ly
-                new SimpleThumbnailService(@"^http://img\.ly/(\w+)$", "http://img.ly/show/thumb/${1}"),
+                new SimpleThumbnailService(@"^http://img\.ly/(\w+)$",
+                    "http://img.ly/show/thumb/${1}",
+                    "http://img.ly/show/full/${1}"),
 
                 // Twitgoo
-                new SimpleThumbnailService(@"^http://twitgoo\.com/(\w+)$", "http://twitgoo.com/${1}/mini"),
+                new SimpleThumbnailService(@"^http://twitgoo\.com/(\w+)$",
+                    "http://twitgoo.com/${1}/mini",
+                    "http://twitgoo.com/${1}/img"),
 
                 // youtube
-                new Youtube(@"^http://(?:(www\.youtube\.com)|(youtu\.be))/(watch\?v=)?(?<videoid>([\w\-]+))", "http://i.ytimg.com/vi/${videoid}/default.jpg"),
+                new Youtube(),
 
                 // ニコニコ動画
-                new Nicovideo(@"^http://(?:(www|ext)\.nicovideo\.jp/watch|nico\.ms)/(?:sm|nm)?([0-9]+)(\?.+)?$", "http://www.nicovideo.jp/api/getthumbinfo/${id}"),
+                new Nicovideo(),
 
                 // ニコニコ静画
-                new SimpleThumbnailService(@"^http://(?:seiga\.nicovideo\.jp/seiga/|nico\.ms/)im(?<id>\d+)", "http://lohas.nicoseiga.jp/thumb/${id}q?"),
+                new SimpleThumbnailService(
+                    @"^http://(?:seiga\.nicovideo\.jp/seiga/|nico\.ms/)im(?<id>\d+)",
+                    "http://lohas.nicoseiga.jp/thumb/${id}q?",
+                    "http://lohas.nicoseiga.jp/thumb/${id}l?"),
 
                 // pixiv
-                new MetaThumbnailService(@"^http://www\.pixiv\.net/(member_illust|index)\.php\?(?=.*mode=(medium|big))(?=.*illust_id=(?<illustId>[0-9]+)).*$"),
+                new Pixiv(http),
 
                 // flickr
-                new MetaThumbnailService(@"^http://www\.flickr\.com/.+$"),
+                new MetaThumbnailService(http, @"^https?://www\.flickr\.com/.+$"),
 
                 // フォト蔵
-                new SimpleThumbnailService(@"^http://photozou\.jp/photo/show/(?<userId>[0-9]+)/(?<photoId>[0-9]+)", "http://photozou.jp/p/thumb/${photoId}"),
-
-                // TwitVideo
-                new SimpleThumbnailService(@"^http://twitvideo\.jp/(\w+)$", "http://twitvideo.jp/img/thumb/${1}"),
+                new SimpleThumbnailService(
+                    @"^http://photozou\.jp/photo/show/(?<userId>[0-9]+)/(?<photoId>[0-9]+)",
+                    "http://photozou.jp/p/thumb/${photoId}",
+                    "http://photozou.jp/p/img/${photoId}"),
 
                 // Piapro
-                new MetaThumbnailService(@"^http://piapro\.jp/(?:content/[0-9a-z]+|t/[0-9a-zA-Z_\-]+)$"),
+                new MetaThumbnailService(http, @"^http://piapro\.jp/(?:content/[0-9a-z]+|t/[0-9a-zA-Z_\-]+)$"),
 
                 // Tumblr
-                new Tumblr(@"(?<base>http://.+?\.tumblr\.com/)post/(?<postID>[0-9]+)(/(?<subject>.+?)/)?", "${base}api/read?id=${postID}"),
+                new Tumblr(),
 
                 // ついっぷるフォト
                 new SimpleThumbnailService(@"^http://p\.twipple\.jp/(?<contentId>[0-9a-z]+)", "http://p.twipple.jp/show/large/${contentId}"),
@@ -112,44 +152,62 @@ namespace OpenTween.Thumbnail
                 new SimpleThumbnailService(@"^http://ow\.ly/i/(\w+)$", "http://static.ow.ly/photos/thumb/${1}.jpg"),
 
                 // vimeo
-                new Vimeo(@"http://vimeo\.com/(?<postID>[0-9]+)", "http://vimeo.com/api/oembed.xml?url=${0}"),
+                new Vimeo(http),
 
                 // cloudfiles
                 new SimpleThumbnailService(@"^http://c[0-9]+\.cdn[0-9]+\.cloudfiles\.rackspacecloud\.com/[a-z_0-9]+", "${0}"),
 
                 // Instagram
-                new SimpleThumbnailService(@"^http://instagr\.am/p/.+/", "${0}media/?size=m"),
+                new SimpleThumbnailService(
+                    @"^http://(?:instagram.com|instagr\.am)/p/.+/",
+                    "${0}media/?size=m",
+                    "${0}media/?size=l"),
 
                 // pikubo
-                new SimpleThumbnailService(@"^http://pikubo\.me/([a-z0-9-_]+)", "http://pikubo.me/q/${1}"),
+                new SimpleThumbnailService(
+                    @"^http://pikubo\.me/([a-z0-9-_]+)",
+                    "http://pikubo.me/q/${1}",
+                    "http://pikubo.me/l/${1}"),
 
                 // Foursquare
-                new Services.Foursquare(@"^https?://(4sq|foursquare)\.com/.+"),
+                new FoursquareCheckin(http),
 
                 // TINAMI
-                new Tinami(@"^http://www\.tinami\.com/view/(?<ContentId>\d+)$", "http://api.tinami.com/content/info?cont_id=${ContentId}&api_key=" + ApplicationSettings.TINAMIApiKey),
+                new Tinami(http),
 
                 // pic.twitter.com
-                new SimpleThumbnailService(@"^https?://p\.twimg\.com/.*$", "${0}:thumb"),
+                new SimpleThumbnailService(
+                    @"^https?://p\.twimg\.com/.*$",
+                    "${0}:thumb",
+                    "${0}"),
 
                 // TwitrPix
-                new SimpleThumbnailService(@"^http://twitrpix\.com/(\w+)$", "http://img.twitrpix.com/thumb/${1}"),
+                new SimpleThumbnailService(
+                    @"^http://twitrpix\.com/(\w+)$",
+                    "http://img.twitrpix.com/thumb/${1}",
+                    "http://img.twitrpix.com/${1}"),
 
                 // Pckles
-                new SimpleThumbnailService(@"^https?://pckles\.com/\w+/\w+$", "${0}.resize.jpg"),
+                new SimpleThumbnailService(
+                    @"^https?://pckles\.com/\w+/\w+$",
+                    "${0}.resize.jpg",
+                    "${0}.jpg"),
 
                 // via.me
-                new ViaMe(@"^https?://via\.me/-(\w+)$", "http://via.me/api/v1/posts/$1"),
+                new ViaMe(http),
 
                 // tuna.be
                 new SimpleThumbnailService(@"^http://tuna\.be/t/(?<entryId>[a-zA-Z0-9\.\-_]+)$", "http://tuna.be/show/thumb/${entryId}"),
 
                 // Path (path.com)
-                new MetaThumbnailService(@"^https?://path.com/p/\w+$"),
+                new MetaThumbnailService(http, @"^https?://path.com/p/\w+$"),
+
+                // GIFMAGAZINE
+                new MetaThumbnailService(http, @"^http?://gifmagazine\.net/post_images/\d+$"),
             };
         }
 
-        public static List<ThumbnailInfo> GetThumbnails(PostClass post)
+        public static async Task<IEnumerable<ThumbnailInfo>> GetThumbnailsAsync(PostClass post, CancellationToken token)
         {
             var thumbnails = new List<ThumbnailInfo>();
 
@@ -157,11 +215,13 @@ namespace OpenTween.Thumbnail
             {
                 foreach (var media in post.Media)
                 {
-                    var thumbInfo = ThumbnailGenerator.GetThumbnailInfo(media.Value, post);
+                    var thumbInfo = await ThumbnailGenerator.GetThumbnailInfoAsync(media, post, token)
+                        .ConfigureAwait(false);
+
                     if (thumbInfo != null)
-                    {
                         thumbnails.Add(thumbInfo);
-                    }
+
+                    token.ThrowIfCancellationRequested();
                 }
             }
 
@@ -179,15 +239,17 @@ namespace OpenTween.Thumbnail
             return thumbnails;
         }
 
-        public static ThumbnailInfo GetThumbnailInfo(string url, PostClass post)
+        public static async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
-            foreach (var generator in ThumbnailGenerator.generator)
+            foreach (var generator in ThumbnailGenerator.Services)
             {
-                var result = generator.GetThumbnailInfo(url, post);
+                var result = await generator.GetThumbnailInfoAsync(url, post, token)
+                    .ConfigureAwait(false);
+
                 if (result != null)
-                {
                     return result;
-                }
+
+                token.ThrowIfCancellationRequested();
             }
 
             return null;