SharpRSS/SharpRss/SyndicationManager.cs

138 lines
7.9 KiB
C#
Raw Normal View History

2023-05-29 18:02:24 +02:00
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Argotic.Common;
using Argotic.Extensions.Core;
2023-05-29 18:02:24 +02:00
using Argotic.Syndication;
using Serilog;
using SharpRss.Models;
2023-05-29 18:02:24 +02:00
namespace SharpRss
{
public struct SyndicationContainer
{
public GenericSyndicationFeed SyndicationFeed { get; set; }
public CategoryModel Category { get; set; }
public FeedModel FeedModel { get; set; }
public HashSet<FeedItemModel> FeedItems { get; set; }
2023-06-04 19:00:46 +02:00
public bool Fetched;
}
2023-05-29 18:02:24 +02:00
public static class SyndicationManager
{
public static SyndicationContainer CreateSyndication(string feedUrl)
2023-05-29 18:02:24 +02:00
{
GenericSyndicationFeed? syndicationFeed = null;
2023-05-29 18:02:24 +02:00
Uri feedUri = new Uri(feedUrl);
try
{
Log.Debug("Fetching feed: {FeedUri}", feedUri.ToString());
syndicationFeed = GenericSyndicationFeed.Create(feedUri);
}
catch (Exception e)
{
Log.Error(e,"Could not get feed: {FeedUrl}", feedUrl);
}
return ConstructSyndicationContainer(syndicationFeed);
}
public static Stream FeedToStream(GenericSyndicationFeed syndicationFeed)
{
MemoryStream memStream = new MemoryStream();
syndicationFeed.Resource.Save(memStream);
if (memStream.Length <= 0)
Log.Warning("Failed to serialize {FeedType} feed: {FeedUri}", syndicationFeed.Format.ToString(), syndicationFeed.Title);
memStream.Position = 0;
return memStream;
}
private static SyndicationContainer ConstructSyndicationContainer(GenericSyndicationFeed? syndicationFeed)
{
SyndicationContainer container = new SyndicationContainer();
if (syndicationFeed == null)
{
Log.Error("Could not construct syndication container!");
return container;
}
container.SyndicationFeed = syndicationFeed;
container.FeedModel = new FeedModel();
container.FeedItems = new HashSet<FeedItemModel>();
switch (syndicationFeed.Resource.Format)
{
case SyndicationContentFormat.Rss:
RssFeed rssFeed = (RssFeed)container.SyndicationFeed.Resource;
if (rssFeed.Channel == null) break;
container.FeedModel.OriginalUrl = rssFeed.Channel.SelfLink?.ToString() ?? string.Empty;
container.FeedModel.Title = rssFeed.Channel.Title ?? string.Empty;
container.FeedModel.FeedType = rssFeed.Format.ToString() ?? string.Empty;
container.FeedModel.FeedVersion = rssFeed.Version?.ToString() ?? string.Empty;
container.FeedModel.Description = rssFeed.Channel.Description ?? string.Empty;
container.FeedModel.Language = rssFeed.Channel.Language?.ToString() ?? string.Empty;
container.FeedModel.Copyright = rssFeed.Channel.Copyright ?? string.Empty;
container.FeedModel.PublicationDate = rssFeed.Channel.LastBuildDate is not { Ticks: > 0 } ? DateTimeOffset.MinValue : new DateTimeOffset(rssFeed.Channel.LastBuildDate);
container.FeedModel.Categories = rssFeed.Channel.Categories?.Select(x => x.Value).ToArray() ?? Array.Empty<string>();
container.FeedModel.ImageUrl = rssFeed.Channel.Image?.Url.ToString() ?? string.Empty;
foreach (var rssItem in rssFeed.Channel.Items)
{
FeedItemModel itemModel = new FeedItemModel()
{
Id = rssItem.Link?.ToString() ?? string.Empty,
FeedUrl = container.FeedModel.OriginalUrl ?? string.Empty,
Type = container.FeedModel.FeedType ?? string.Empty,
Title = rssItem.Title ?? string.Empty,
Description = rssItem.Description ?? string.Empty,
Link = rssItem.Link?.ToString() ?? string.Empty,
PublishingDate = rssItem.PublicationDate is not { Ticks: <= 0 } ? DateTimeOffset.MinValue : new DateTimeOffset(rssItem.PublicationDate),
Authors = rssItem.Author != null ? new []{ rssItem.Author } : Array.Empty<string>(),
Categories = rssItem.Categories?.Select(x => x.Value).ToArray() ?? Array.Empty<string>(),
Content = rssItem.Extensions?.Where(x => x is SiteSummaryContentSyndicationExtension).Select(x => (x as SiteSummaryContentSyndicationExtension)?.Context.Encoded).FirstOrDefault() ?? string.Empty,
CommentsUrl = rssItem.Extensions?.Where(x => x is WellFormedWebCommentsSyndicationExtension).Select(x => (x as WellFormedWebCommentsSyndicationExtension)?.Context.CommentsFeed.ToString()).FirstOrDefault() ?? string.Empty
};
container.FeedItems.Add(itemModel);
}
break;
case SyndicationContentFormat.Atom:
AtomFeed atomFeed = (AtomFeed)container.SyndicationFeed.Resource;
container.FeedModel.OriginalUrl = atomFeed.Id?.Uri.ToString() ?? string.Empty;
container.FeedModel.Title = atomFeed.Title?.Content ?? string.Empty;
container.FeedModel.FeedType = atomFeed.Format.ToString() ?? string.Empty;
container.FeedModel.FeedVersion = atomFeed.Version?.ToString() ?? string.Empty;
container.FeedModel.Description = atomFeed.Subtitle?.Content ?? string.Empty;
container.FeedModel.Language = atomFeed.Language?.ToString() ?? string.Empty;
container.FeedModel.Copyright = atomFeed.Rights?.Content ?? string.Empty;
container.FeedModel.PublicationDate = atomFeed.UpdatedOn != null ? new DateTimeOffset(atomFeed.UpdatedOn) : DateTimeOffset.MinValue;
container.FeedModel.Categories = atomFeed.Categories?.Select(x => x.Label).ToArray() ?? Array.Empty<string>();
container.FeedModel.ImageUrl = atomFeed.Icon?.Uri.ToString() ?? string.Empty;
foreach (var entry in atomFeed.Entries)
{
FeedItemModel itemModel = new FeedItemModel()
{
Id = entry.Id?.Uri.ToString() ?? string.Empty,
FeedUrl = container.FeedModel?.OriginalUrl ?? string.Empty,
Type = container.FeedModel?.FeedType ?? string.Empty,
Title = entry.Title?.Content ?? string.Empty,
Description = entry.Summary?.Content ?? string.Empty,
Link = entry.Id?.Uri.ToString() ?? string.Empty,
LastUpdated = entry.UpdatedOn is not { Ticks: <= 0 } ? DateTimeOffset.MinValue : new DateTimeOffset(entry.UpdatedOn),
PublishingDate = entry.PublishedOn is not { Ticks: <= 0 } ? DateTimeOffset.MinValue : new DateTimeOffset(entry.PublishedOn),
Authors = entry.Authors?.Select(auth => auth.Name).ToArray() ?? Array.Empty<string>(),
Categories = entry.Categories?.Select(cat => cat.Label).ToArray() ?? Array.Empty<string>(),
Content = entry.Content?.Content ?? string.Empty
};
container.FeedItems.Add(itemModel);
}
break;
default:
Log.Warning("Feed implementation missing!");
break;
}
2023-06-04 19:00:46 +02:00
container.Fetched = true;
return container;
2023-05-29 18:02:24 +02:00
}
public static void Init()
{
DbAccess.Initialize();
}
2023-05-29 18:02:24 +02:00
}
}