73 lines
2.6 KiB
C#
73 lines
2.6 KiB
C#
using System.ServiceModel.Syndication;
|
|
using System.Xml;
|
|
using FinlyticCore.Dtos.News;
|
|
|
|
namespace FinlyticNews.Adapters.Discovery;
|
|
|
|
/// <summary>
|
|
/// Discovery adapter targeting standard RSS/Atom syndication feeds.
|
|
/// </summary>
|
|
public class RssDiscoveryAdapter : ArticleDiscoveryAdapter
|
|
{
|
|
/// <inheritdoc />
|
|
public override string Name => "rss";
|
|
|
|
/// <inheritdoc />
|
|
public override List<DiscoveredArticle> ExtractUrls(string content, string sourceUrl)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(content)) return [];
|
|
|
|
var articles = new List<DiscoveredArticle>();
|
|
if (!Uri.TryCreate(sourceUrl, UriKind.Absolute, out var baseUri)) return articles;
|
|
|
|
try
|
|
{
|
|
using var stringReader = new StringReader(content);
|
|
using var xmlReader = XmlReader.Create(stringReader, new XmlReaderSettings
|
|
{
|
|
DtdProcessing = DtdProcessing.Ignore,
|
|
IgnoreWhitespace = true
|
|
});
|
|
|
|
var feed = SyndicationFeed.Load(xmlReader);
|
|
var feedLanguage = feed?.Language;
|
|
var feedTitle = feed?.Title?.Text;
|
|
|
|
if (feed?.Items != null)
|
|
{
|
|
foreach (var item in feed.Items)
|
|
{
|
|
var link = item.Links.FirstOrDefault()?.Uri?.ToString() ?? item.Id;
|
|
|
|
if (!string.IsNullOrWhiteSpace(link) && Uri.TryCreate(baseUri, link, out var absoluteUri))
|
|
{
|
|
var title = item.Title?.Text?.Trim();
|
|
var summary = item.Summary?.Text?.Trim();
|
|
|
|
DateTime? pubDate = item.PublishDate != DateTimeOffset.MinValue
|
|
? item.PublishDate.UtcDateTime
|
|
: (item.LastUpdatedTime != DateTimeOffset.MinValue ? item.LastUpdatedTime.UtcDateTime : null);
|
|
|
|
articles.Add(new DiscoveredArticle(
|
|
Url: absoluteUri.ToString(),
|
|
Isins: null,
|
|
Title: title,
|
|
Summary: summary,
|
|
PublishedAt: pubDate,
|
|
Language: feedLanguage,
|
|
SourceName: feedTitle
|
|
));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Graceful handling fehlerhafter Feeds
|
|
}
|
|
|
|
return articles.GroupBy(u => u.Url, StringComparer.OrdinalIgnoreCase)
|
|
.Select(g => g.First())
|
|
.ToList();
|
|
}
|
|
} |