From c4ef7f3be10dc08516284accb616893f5c51975a Mon Sep 17 00:00:00 2001 From: Timothy Baldridge <tbaldridge@gmail.com> Date: Fri, 10 Apr 2020 16:31:06 -0600 Subject: [PATCH] Can load and dedupe RSS feeds --- Wabbajack.Lib/NexusApi/NexusUpdatesFeeds.cs | 80 +++++++++++++++++++++ Wabbajack.Lib/Wabbajack.Lib.csproj | 3 + Wabbajack.Test/NexusTests.cs | 32 +++++++++ 3 files changed, 115 insertions(+) create mode 100644 Wabbajack.Lib/NexusApi/NexusUpdatesFeeds.cs create mode 100644 Wabbajack.Test/NexusTests.cs diff --git a/Wabbajack.Lib/NexusApi/NexusUpdatesFeeds.cs b/Wabbajack.Lib/NexusApi/NexusUpdatesFeeds.cs new file mode 100644 index 00000000..c33655c2 --- /dev/null +++ b/Wabbajack.Lib/NexusApi/NexusUpdatesFeeds.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.ServiceModel.Syndication; +using System.Threading.Tasks; +using System.Xml; +using Wabbajack.Common; + +namespace Wabbajack.Lib.NexusApi +{ + public class NexusUpdatesFeeds + { + + public static async Task<IEnumerable<UpdateRecord>> GetUpdates() + { + var updated = GetFeed(new Uri("https://www.nexusmods.com/rss/updatedtoday")); + var newToday = GetFeed(new Uri("https://www.nexusmods.com/rss/newtoday")); + + var sorted = (await updated).Concat(await newToday).OrderByDescending(f => f.TimeStamp); + var deduped = sorted.GroupBy(g => (g.Game, g.ModId)).Select(g => g.First()); + return deduped; + } + + private static bool TryParseGameUrl(SyndicationLink link, out Game game, out long modId) + { + var parts = link.Uri.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries); + + var foundGame = GameRegistry.GetByFuzzyName(parts[0]); + if (foundGame == null) + { + game = Game.Oblivion; + modId = 0; + return false; + } + + if (long.TryParse(parts[2], out modId)) + { + game = foundGame.Game; + return true; + } + + game = Game.Oblivion; + modId = 0; + return false; + } + + private static async Task<IEnumerable<UpdateRecord>> GetFeed(Uri uri) + { + var client = new Common.Http.Client(); + var data = await client.GetStringAsync(uri); + var reader = XmlReader.Create(new StringReader(data)); + var results = SyndicationFeed.Load(reader); + return results.Items + .Select(itm => + { + if (TryParseGameUrl(itm.Links.First(), out var game, out var modId)) + { + return new UpdateRecord + { + TimeStamp = itm.PublishDate.UtcDateTime, + Game = game, + ModId = modId + }; + } + + return null; + }).Where(v => v != null); + } + + + public class UpdateRecord + { + public Game Game { get; set; } + public long ModId { get; set; } + public DateTime TimeStamp { get; set; } + } + + } +} diff --git a/Wabbajack.Lib/Wabbajack.Lib.csproj b/Wabbajack.Lib/Wabbajack.Lib.csproj index b79980e0..7e8793e3 100644 --- a/Wabbajack.Lib/Wabbajack.Lib.csproj +++ b/Wabbajack.Lib/Wabbajack.Lib.csproj @@ -51,6 +51,9 @@ <PackageReference Include="System.Net.Http"> <Version>4.3.4</Version> </PackageReference> + <PackageReference Include="System.ServiceModel.Syndication"> + <Version>4.7.0</Version> + </PackageReference> <PackageReference Include="WebSocketSharp-netstandard"> <Version>1.0.1</Version> </PackageReference> diff --git a/Wabbajack.Test/NexusTests.cs b/Wabbajack.Test/NexusTests.cs new file mode 100644 index 00000000..49391260 --- /dev/null +++ b/Wabbajack.Test/NexusTests.cs @@ -0,0 +1,32 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Wabbajack.Common; +using Wabbajack.Lib.NexusApi; +using Xunit; +using Xunit.Abstractions; + +namespace Wabbajack.Test +{ + public class NexusTests : ATestBase + { + [Fact] + public async Task CanGetNexusRSSUpdates() + { + var results = (await NexusUpdatesFeeds.GetUpdates()).ToArray(); + + Assert.NotEmpty(results); + + Utils.Log($"Loaded {results.Length} updates from the Nexus"); + + foreach (var result in results) + { + Assert.True(DateTime.UtcNow - result.TimeStamp < TimeSpan.FromDays(1)); + } + } + + public NexusTests(ITestOutputHelper output) : base(output) + { + } + } +}