OSDN Git Service

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