OSDN Git Service

GIFMAGAZINE のサムネイル表示に対応
[opentween/open-tween.git] / OpenTween / Thumbnail / ThumbnailGenerator.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2012 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.Linq;
25 using System.Net.Http;
26 using System.Text;
27 using System.Text.RegularExpressions;
28 using System.Threading;
29 using System.Threading.Tasks;
30 using OpenTween.Thumbnail.Services;
31
32 namespace OpenTween.Thumbnail
33 {
34     class ThumbnailGenerator
35     {
36         public static List<IThumbnailService> Services { get; protected set; }
37
38         internal static ImgAzyobuziNet ImgAzyobuziNetInstance { get; private set; }
39
40         static ThumbnailGenerator()
41         {
42             ThumbnailGenerator.Services = new List<IThumbnailService>();
43         }
44
45         public static void InitializeGenerator(HttpClient http)
46         {
47             ImgAzyobuziNetInstance = new ImgAzyobuziNet(http, autoupdate: true);
48
49             ThumbnailGenerator.Services = new List<IThumbnailService>()
50             {
51                 // ton.twitter.com
52                 new TonTwitterCom(),
53
54                 // DirectLink
55                 new SimpleThumbnailService(@"^https?://.*(\.jpg|\.jpeg|\.gif|\.png|\.bmp)$", "${0}"),
56
57                 // img.azyobuzi.net
58                 ImgAzyobuziNetInstance,
59
60                 // ImgUr
61                 new SimpleThumbnailService(
62                     @"^http://(?:i\.)?imgur\.com/(\w+)(?:\..{3})?$",
63                     "http://img.imgur.com/${1}l.jpg",
64                     "http://img.imgur.com/${1}.jpg"),
65
66                 // Twitpic
67                 new SimpleThumbnailService(
68                     @"^http://(www\.)?twitpic\.com/(?<photoId>\w+)(/full/?)?$",
69                     "http://twitpic.com/show/thumb/${photoId}",
70                     "http://twitpic.com/show/large/${photoId}"),
71
72                 // yfrog
73                 new SimpleThumbnailService(
74                     @"^http://yfrog\.com/(\w+)$",
75                     "${0}:small",
76                     "${0}"),
77
78                 // Lockerz
79                 new SimpleThumbnailService(
80                     @"^http://(tweetphoto\.com/[0-9]+|pic\.gd/[a-z0-9]+|(lockerz|plixi)\.com/[ps]/[0-9]+)$",
81                     "http://api.plixi.com/api/tpapi.svc/imagefromurl?size=thumbnail&url=${0}",
82                     "http://api.plixi.com/api/tpapi.svc/imagefromurl?size=big&url=${0}"),
83
84                 // MobyPicture
85                 new SimpleThumbnailService(
86                     @"^http://moby\.to/(\w+)$",
87                     "http://mobypicture.com/?${1}:small",
88                     "http://mobypicture.com/?${1}:full"),
89
90                 // 携帯百景
91                 new SimpleThumbnailService(
92                     @"^http://movapic\.com/pic/(\w+)$",
93                     "http://image.movapic.com/pic/s_${1}.jpeg",
94                     "http://image.movapic.com/pic/m_${1}.jpeg"),
95
96                 // はてなフォトライフ
97                 new SimpleThumbnailService(
98                     @"^http://f\.hatena\.ne\.jp/(([a-z])[a-z0-9_-]{1,30}[a-z0-9])/((\d{8})\d+)$",
99                     "http://img.f.hatena.ne.jp/images/fotolife/${2}/${1}/${4}/${3}_120.jpg",
100                     "http://img.f.hatena.ne.jp/images/fotolife/${2}/${1}/${4}/${3}.jpg"),
101
102                 // PhotoShare
103                 new SimpleThumbnailService(@"^http://(?:www\.)?bcphotoshare\.com/photos/\d+/(\d+)$", "http://images.bcphotoshare.com/storages/${1}/thumb180.jpg"),
104
105                 // img.ly
106                 new SimpleThumbnailService(@"^http://img\.ly/(\w+)$",
107                     "http://img.ly/show/thumb/${1}",
108                     "http://img.ly/show/full/${1}"),
109
110                 // Twitgoo
111                 new SimpleThumbnailService(@"^http://twitgoo\.com/(\w+)$",
112                     "http://twitgoo.com/${1}/mini",
113                     "http://twitgoo.com/${1}/img"),
114
115                 // youtube
116                 new Youtube(),
117
118                 // ニコニコ動画
119                 new Nicovideo(),
120
121                 // ニコニコ静画
122                 new SimpleThumbnailService(
123                     @"^http://(?:seiga\.nicovideo\.jp/seiga/|nico\.ms/)im(?<id>\d+)",
124                     "http://lohas.nicoseiga.jp/thumb/${id}q?",
125                     "http://lohas.nicoseiga.jp/thumb/${id}l?"),
126
127                 // pixiv
128                 new Pixiv(http),
129
130                 // flickr
131                 new MetaThumbnailService(http, @"^https?://www\.flickr\.com/.+$"),
132
133                 // フォト蔵
134                 new SimpleThumbnailService(
135                     @"^http://photozou\.jp/photo/show/(?<userId>[0-9]+)/(?<photoId>[0-9]+)",
136                     "http://photozou.jp/p/thumb/${photoId}",
137                     "http://photozou.jp/p/img/${photoId}"),
138
139                 // Piapro
140                 new MetaThumbnailService(http, @"^http://piapro\.jp/(?:content/[0-9a-z]+|t/[0-9a-zA-Z_\-]+)$"),
141
142                 // Tumblr
143                 new Tumblr(),
144
145                 // ついっぷるフォト
146                 new SimpleThumbnailService(@"^http://p\.twipple\.jp/(?<contentId>[0-9a-z]+)", "http://p.twipple.jp/show/large/${contentId}"),
147
148                 // mypix/shamoji
149                 new SimpleThumbnailService(@"^http://www\.(mypix\.jp|shamoji\.info)/app\.php/picture/(?<contentId>[0-9a-z]+)", "${0}/thumb.jpg"),
150
151                 // ow.ly
152                 new SimpleThumbnailService(@"^http://ow\.ly/i/(\w+)$", "http://static.ow.ly/photos/thumb/${1}.jpg"),
153
154                 // vimeo
155                 new Vimeo(http),
156
157                 // cloudfiles
158                 new SimpleThumbnailService(@"^http://c[0-9]+\.cdn[0-9]+\.cloudfiles\.rackspacecloud\.com/[a-z_0-9]+", "${0}"),
159
160                 // Instagram
161                 new SimpleThumbnailService(
162                     @"^http://(?:instagram.com|instagr\.am)/p/.+/",
163                     "${0}media/?size=m",
164                     "${0}media/?size=l"),
165
166                 // pikubo
167                 new SimpleThumbnailService(
168                     @"^http://pikubo\.me/([a-z0-9-_]+)",
169                     "http://pikubo.me/q/${1}",
170                     "http://pikubo.me/l/${1}"),
171
172                 // Foursquare
173                 new FoursquareCheckin(http),
174
175                 // TINAMI
176                 new Tinami(http),
177
178                 // pic.twitter.com
179                 new SimpleThumbnailService(
180                     @"^https?://p\.twimg\.com/.*$",
181                     "${0}:thumb",
182                     "${0}"),
183
184                 // TwitrPix
185                 new SimpleThumbnailService(
186                     @"^http://twitrpix\.com/(\w+)$",
187                     "http://img.twitrpix.com/thumb/${1}",
188                     "http://img.twitrpix.com/${1}"),
189
190                 // Pckles
191                 new SimpleThumbnailService(
192                     @"^https?://pckles\.com/\w+/\w+$",
193                     "${0}.resize.jpg",
194                     "${0}.jpg"),
195
196                 // via.me
197                 new ViaMe(http),
198
199                 // tuna.be
200                 new SimpleThumbnailService(@"^http://tuna\.be/t/(?<entryId>[a-zA-Z0-9\.\-_]+)$", "http://tuna.be/show/thumb/${entryId}"),
201
202                 // Path (path.com)
203                 new MetaThumbnailService(http, @"^https?://path.com/p/\w+$"),
204
205                 // GIFMAGAZINE
206                 new MetaThumbnailService(http, @"^http?://gifmagazine\.net/post_images/\d+$"),
207             };
208         }
209
210         public static async Task<IEnumerable<ThumbnailInfo>> GetThumbnailsAsync(PostClass post, CancellationToken token)
211         {
212             var thumbnails = new List<ThumbnailInfo>();
213
214             if (post.Media != null)
215             {
216                 foreach (var media in post.Media)
217                 {
218                     var thumbInfo = await ThumbnailGenerator.GetThumbnailInfoAsync(media, post, token)
219                         .ConfigureAwait(false);
220
221                     if (thumbInfo != null)
222                         thumbnails.Add(thumbInfo);
223
224                     token.ThrowIfCancellationRequested();
225                 }
226             }
227
228             if (post.PostGeo != null && !(post.PostGeo.Lat == 0 && post.PostGeo.Lng == 0))
229             {
230                 var map = MapThumb.GetDefaultInstance();
231                 thumbnails.Add(new ThumbnailInfo()
232                 {
233                     ImageUrl = map.CreateMapLinkUrl(post.PostGeo.Lat, post.PostGeo.Lng),
234                     ThumbnailUrl = map.CreateStaticMapUrl(post.PostGeo.Lat, post.PostGeo.Lng),
235                     TooltipText = null,
236                 });
237             }
238
239             return thumbnails;
240         }
241
242         public static async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
243         {
244             foreach (var generator in ThumbnailGenerator.Services)
245             {
246                 var result = await generator.GetThumbnailInfoAsync(url, post, token)
247                     .ConfigureAwait(false);
248
249                 if (result != null)
250                     return result;
251
252                 token.ThrowIfCancellationRequested();
253             }
254
255             return null;
256         }
257     }
258 }