1 // OpenTween - Client of Twitter
2 // Copyright (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
5 // This file is part of OpenTween.
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)
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
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.
23 using System.Collections.Generic;
25 using System.Net.Http;
27 using System.Text.RegularExpressions;
28 using System.Threading;
29 using System.Threading.Tasks;
30 using OpenTween.Thumbnail.Services;
32 namespace OpenTween.Thumbnail
34 class ThumbnailGenerator
36 public static List<IThumbnailService> Services { get; protected set; }
38 internal static ImgAzyobuziNet ImgAzyobuziNetInstance { get; private set; }
40 static ThumbnailGenerator()
42 ThumbnailGenerator.Services = new List<IThumbnailService>();
45 public static void InitializeGenerator()
47 ImgAzyobuziNetInstance = new ImgAzyobuziNet(autoupdate: true);
49 ThumbnailGenerator.Services = new List<IThumbnailService>()
54 // twitter.com/tweet_video
55 new TwitterComVideo(),
58 new SimpleThumbnailService(@"^https?://.*(\.jpg|\.jpeg|\.gif|\.png|\.bmp)$", "${0}"),
61 ImgAzyobuziNetInstance,
64 new SimpleThumbnailService(
65 @"^https?://(?:i\.)?imgur\.com/(\w+)(?:\..{3})?$",
66 "http://img.imgur.com/${1}l.jpg",
67 "http://img.imgur.com/${1}.jpg"),
70 new SimpleThumbnailService(
71 @"^http://(www\.)?twitpic\.com/(?<photoId>\w+)(/full/?)?$",
72 "http://twitpic.com/show/thumb/${photoId}",
73 "http://twitpic.com/show/large/${photoId}"),
76 new SimpleThumbnailService(
77 @"^https?://yfrog\.com/(\w+)$",
82 new SimpleThumbnailService(
83 @"^https?://(tweetphoto\.com/[0-9]+|pic\.gd/[a-z0-9]+|(lockerz|plixi)\.com/[ps]/[0-9]+)$",
84 "http://api.plixi.com/api/tpapi.svc/imagefromurl?size=thumbnail&url=${0}",
85 "http://api.plixi.com/api/tpapi.svc/imagefromurl?size=big&url=${0}"),
88 new SimpleThumbnailService(
89 @"^https?://moby\.to/(\w+)$",
90 "http://mobypicture.com/?${1}:small",
91 "http://mobypicture.com/?${1}:full"),
94 new SimpleThumbnailService(
95 @"^https?://movapic\.com/pic/(\w+)$",
96 "http://image.movapic.com/pic/s_${1}.jpeg",
97 "http://image.movapic.com/pic/m_${1}.jpeg"),
100 new SimpleThumbnailService(
101 @"^https?://f\.hatena\.ne\.jp/(([a-z])[a-z0-9_-]{1,30}[a-z0-9])/((\d{8})\d+)$",
102 "http://img.f.hatena.ne.jp/images/fotolife/${2}/${1}/${4}/${3}_120.jpg",
103 "http://img.f.hatena.ne.jp/images/fotolife/${2}/${1}/${4}/${3}.jpg"),
106 new SimpleThumbnailService(@"^https?://(?:www\.)?bcphotoshare\.com/photos/\d+/(\d+)$", "http://images.bcphotoshare.com/storages/${1}/thumb180.jpg"),
109 new SimpleThumbnailService(@"^https?://img\.ly/(\w+)$",
110 "http://img.ly/show/thumb/${1}",
111 "http://img.ly/show/full/${1}"),
114 new SimpleThumbnailService(@"^https?://twitgoo\.com/(\w+)$",
115 "http://twitgoo.com/${1}/mini",
116 "http://twitgoo.com/${1}/img"),
125 new SimpleThumbnailService(
126 @"^https?://(?:seiga\.nicovideo\.jp/seiga/|nico\.ms/)im(?<id>\d+)",
127 "http://lohas.nicoseiga.jp/thumb/${id}q?",
128 "http://lohas.nicoseiga.jp/thumb/${id}l?"),
134 new MetaThumbnailService(@"^https?://www\.flickr\.com/.+$"),
137 new SimpleThumbnailService(
138 @"^https?://photozou\.jp/photo/show/(?<userId>[0-9]+)/(?<photoId>[0-9]+)",
139 "http://photozou.jp/p/thumb/${photoId}",
140 "http://photozou.jp/p/img/${photoId}"),
143 new MetaThumbnailService(@"^https?://piapro\.jp/(?:content/[0-9a-z]+|t/[0-9a-zA-Z_\-]+)$"),
149 new SimpleThumbnailService(@"^https?://p\.twipple\.jp/(?<contentId>[0-9a-z]+)", "http://p.twipple.jp/show/large/${contentId}"),
152 new SimpleThumbnailService(@"^https?://www\.(mypix\.jp|shamoji\.info)/app\.php/picture/(?<contentId>[0-9a-z]+)", "${0}/thumb.jpg"),
155 new SimpleThumbnailService(@"^https?://ow\.ly/i/(\w+)$", "http://static.ow.ly/photos/thumb/${1}.jpg"),
161 new SimpleThumbnailService(@"^https?://c[0-9]+\.cdn[0-9]+\.cloudfiles\.rackspacecloud\.com/[a-z_0-9]+", "${0}"),
164 new SimpleThumbnailService(
165 @"^https?://(?:instagram.com|instagr\.am|i\.instagram\.com)/p/.+/",
167 "${0}media/?size=l"),
170 new SimpleThumbnailService(
171 @"^https?://pikubo\.me/([a-z0-9-_]+)",
172 "http://pikubo.me/q/${1}",
173 "http://pikubo.me/l/${1}"),
176 new FoursquareCheckin(),
182 new SimpleThumbnailService(
183 @"^https?://p\.twimg\.com/.*$",
188 new SimpleThumbnailService(
189 @"^https?://twitrpix\.com/(\w+)$",
190 "http://img.twitrpix.com/thumb/${1}",
191 "http://img.twitrpix.com/${1}"),
194 new SimpleThumbnailService(
195 @"^https?://pckles\.com/\w+/\w+$",
203 new SimpleThumbnailService(@"^https?://tuna\.be/t/(?<entryId>[a-zA-Z0-9\.\-_]+)$", "http://tuna.be/show/thumb/${entryId}"),
206 new MetaThumbnailService(@"^https?://path.com/p/\w+$"),
209 new SimpleThumbnailService(@"^https?://gifmagazine\.net/post_images/(\d+)", "http://img.gifmagazine.net/gifmagazine/images/${1}/original.gif"),
213 public static async Task<IEnumerable<ThumbnailInfo>> GetThumbnailsAsync(PostClass post, CancellationToken token)
215 var thumbnails = new List<ThumbnailInfo>();
217 foreach (var media in post.Media)
219 var thumbInfo = await ThumbnailGenerator.GetThumbnailInfoAsync(media.Url, post, token)
220 .ConfigureAwait(false);
222 if (thumbInfo != null)
223 thumbnails.Add(thumbInfo);
225 token.ThrowIfCancellationRequested();
228 if (post.PostGeo != null && !(post.PostGeo.Lat == 0 && post.PostGeo.Lng == 0))
230 var map = MapThumb.GetDefaultInstance();
231 thumbnails.Add(new ThumbnailInfo()
233 ImageUrl = map.CreateMapLinkUrl(post.PostGeo.Lat, post.PostGeo.Lng),
234 ThumbnailUrl = map.CreateStaticMapUrl(post.PostGeo.Lat, post.PostGeo.Lng),
242 public static async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
244 foreach (var generator in ThumbnailGenerator.Services)
246 var result = await generator.GetThumbnailInfoAsync(url, post, token)
247 .ConfigureAwait(false);
252 token.ThrowIfCancellationRequested();