-
-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy pathNicoNicoMyListParser.cs
101 lines (84 loc) · 2.88 KB
/
NicoNicoMyListParser.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
using System.Net;
using System.Text.RegularExpressions;
using HtmlAgilityPack;
using NLog;
using Rss;
using VocaDb.Model.DataContracts.SongImport;
using VocaDb.Model.Domain.PVs;
using VocaDb.Model.Service.VideoServices;
using VocaDb.Model.Utils;
namespace VocaDb.Model.Service.SongImport;
public class NicoNicoMyListParser : ISongListImporter
{
private static readonly Logger s_log = LogManager.GetCurrentClassLogger();
private static readonly Regex s_wvrIdRegex = new(@"#(\d{3})");
private static readonly Regex[] s_linkMatchers = new[]
{
new Regex(@"www.nicovideo.jp/user/\d+/mylist/\d+"),
new Regex(@"www.nicovideo.jp/mylist/\d+"),
};
public Task<PartialImportedSongs> GetSongsAsync(string url, string nextPageToken, int maxResults, bool parseAll)
{
throw new NotSupportedException();
}
private bool IsRankingsItem(RssItem item)
{
var node = HtmlNode.CreateNode($"<div>{item.Description}</div>");
return node.InnerText.Any() && char.IsDigit(node.InnerText, 0);
}
public Task<ImportedSongListContract> ParseAsync(string url, bool parseAll)
{
if (string.IsNullOrEmpty(url))
throw new UnableToImportException("Feed URL cannot be empty");
if (!url.Contains("rss="))
url += "?rss=2.0";
RssFeed feed;
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
request.AllowAutoRedirect = true;
request.UserAgent = AppConfig.UserAgent;
try
{
feed = RssFeed.Read(request);
}
catch (UriFormatException x)
{
s_log.Warn(x, "Unable to parse URL");
throw new UnableToImportException("Unable to parse URL", x);
}
catch (WebException x)
{
s_log.Error(x, "Unable to parse feed");
throw new UnableToImportException("Unable to parse feed", x);
}
if (feed.Exceptions.LastException != null)
{
s_log.Error(feed.Exceptions.LastException, "Unable to parse feed");
throw new UnableToImportException("Unable to parse feed", feed.Exceptions.LastException);
}
var result = new ImportedSongListContract();
var channel = feed.Channels[0];
result.Name = channel.Title;
var wvrIdMatch = s_wvrIdRegex.Match(result.Name);
if (wvrIdMatch.Success)
result.WVRNumber = int.Parse(wvrIdMatch.Groups[1].Value);
var songs = new List<ImportedSongInListContract>();
var order = 1;
foreach (var item in channel.Items.Cast<RssItem>())
{
if (parseAll || IsRankingsItem(item))
{
var nicoId = VideoService.NicoNicoDouga.GetIdByUrl(item.Link.ToString());
songs.Add(new ImportedSongInListContract(PVService.NicoNicoDouga, nicoId)
{
SortIndex = order,
Name = item.Title,
Url = item.Link.ToString()
});
++order;
}
}
result.Songs = new PartialImportedSongs(songs.ToArray(), songs.Count, null);
return Task.FromResult(result);
}
public bool MatchUrl(string url) => s_linkMatchers.Any(linkMatcher => linkMatcher.IsMatch(url));
}