OSDN Git Service

C# 8.0 のnull許容参照型を有効化
[opentween/open-tween.git] / OpenTween / Thumbnail / Services / Nicovideo.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 //           (c) 2008-2011 Moz (@syo68k)
4 //           (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 //           (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 //           (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
7 //           (c) 2012      kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
8 // All rights reserved.
9 //
10 // This file is part of OpenTween.
11 //
12 // This program is free software; you can redistribute it and/or modify it
13 // under the terms of the GNU General Public License as published by the Free
14 // Software Foundation; either version 3 of the License, or (at your option)
15 // any later version.
16 //
17 // This program is distributed in the hope that it will be useful, but
18 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
24 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
25 // Boston, MA 02110-1301, USA.
26
27 #nullable enable
28
29 using System;
30 using System.Collections.Generic;
31 using System.Globalization;
32 using System.Linq;
33 using System.Net.Http;
34 using System.Text;
35 using System.Text.RegularExpressions;
36 using System.Threading;
37 using System.Threading.Tasks;
38 using System.Xml;
39 using System.Xml.Linq;
40 using OpenTween.Connection;
41 using OpenTween.Models;
42
43 namespace OpenTween.Thumbnail.Services
44 {
45     class Nicovideo : IThumbnailService
46     {
47         public static readonly Regex UrlPatternRegex =
48             new Regex(@"^https?://(?:(www|ext)\.nicovideo\.jp/watch|nico\.ms)/(?<id>(?:sm|nm)?[0-9]+)(\?.+)?$");
49
50         public override async Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
51         {
52             var match = Nicovideo.UrlPatternRegex.Match(url);
53             if (!match.Success)
54                 return null;
55
56             try
57             {
58                 var requestUri = new Uri("http://www.nicovideo.jp/api/getthumbinfo/" + match.Groups["id"].Value);
59                 var responseText = await Networking.Http.GetStringAsync(requestUri);
60
61                 var xdoc = XDocument.Parse(responseText);
62
63                 var responseElement = xdoc.Element("nicovideo_thumb_response");
64                 if (responseElement == null || responseElement.Attribute("status").Value != "ok")
65                     return null;
66
67                 var thumbElement = responseElement.Element("thumb");
68                 if (thumbElement == null)
69                     return null;
70
71                 var thumbUrlElement = thumbElement.Element("thumbnail_url");
72                 if (thumbUrlElement == null)
73                     return null;
74
75                 return new ThumbnailInfo
76                 {
77                     MediaPageUrl = url,
78                     ThumbnailImageUrl = thumbUrlElement.Value,
79                     TooltipText = BuildTooltip(thumbElement),
80                     IsPlayable = true,
81                 };
82             }
83             catch (XmlException) { }
84             catch (HttpRequestException) { }
85
86             return null;
87         }
88
89         internal static string BuildTooltip(XElement thumbElement)
90         {
91             var tooltip = new StringBuilder(200);
92
93             var titleElement = thumbElement.Element("title");
94             if (titleElement != null)
95             {
96                 tooltip.Append(Properties.Resources.NiconicoInfoText1);
97                 tooltip.Append(titleElement.Value);
98                 tooltip.AppendLine();
99             }
100
101             var lengthElement = thumbElement.Element("length");
102             if (lengthElement != null)
103             {
104                 tooltip.Append(Properties.Resources.NiconicoInfoText2);
105                 tooltip.Append(lengthElement.Value);
106                 tooltip.AppendLine();
107             }
108
109             var firstRetrieveElement = thumbElement.Element("first_retrieve");
110             if (firstRetrieveElement != null && DateTimeUtc.TryParse(firstRetrieveElement.Value, DateTimeFormatInfo.InvariantInfo, out var firstRetrieveDate))
111             {
112                 tooltip.Append(Properties.Resources.NiconicoInfoText3);
113                 tooltip.Append(firstRetrieveDate.ToLocalTimeString());
114                 tooltip.AppendLine();
115             }
116
117             var viewCounterElement = thumbElement.Element("view_counter");
118             if (viewCounterElement != null)
119             {
120                 tooltip.Append(Properties.Resources.NiconicoInfoText4);
121                 tooltip.Append(viewCounterElement.Value);
122                 tooltip.AppendLine();
123             }
124
125             var commentNumElement = thumbElement.Element("comment_num");
126             if (commentNumElement != null)
127             {
128                 tooltip.Append(Properties.Resources.NiconicoInfoText5);
129                 tooltip.Append(commentNumElement.Value);
130                 tooltip.AppendLine();
131             }
132
133             var mylistCounterElement = thumbElement.Element("mylist_counter");
134             if (mylistCounterElement != null)
135             {
136                 tooltip.Append(Properties.Resources.NiconicoInfoText6);
137                 tooltip.Append(mylistCounterElement.Value);
138                 tooltip.AppendLine();
139             }
140
141             return tooltip.ToString();
142         }
143     }
144 }