1
0
mirror of https://github.com/mxpv/podsync.git synced 2024-05-11 05:55:04 +00:00

Move feed management to separate service, update RSS contracts

This commit is contained in:
Maksym Pavlenko
2017-01-13 18:43:17 -08:00
parent 803b93fb63
commit f69da18a54
17 changed files with 92 additions and 50 deletions

View File

@@ -10,7 +10,7 @@ using Podsync.Services;
using Podsync.Services.Links;
using Podsync.Services.Resolver;
using Podsync.Services.Rss;
using Podsync.Services.Rss.Feed;
using Podsync.Services.Rss.Contracts;
using Podsync.Services.Storage;
using Shared;
@@ -26,15 +26,13 @@ namespace Podsync.Controllers
["audio/mp4"] = "m4a"
};
private readonly IRssBuilder _rssBuilder;
private readonly ILinkService _linkService;
private readonly IStorageService _storageService;
private readonly IFeedService _feedService;
public FeedController(IRssBuilder rssBuilder, ILinkService linkService, IStorageService storageService)
public FeedController(IRssBuilder rssBuilder, ILinkService linkService, IStorageService storageService, IFeedService feedService)
{
_rssBuilder = rssBuilder;
_linkService = linkService;
_storageService = storageService;
_feedService = feedService;
}
[HttpPost]
@@ -44,11 +42,6 @@ namespace Podsync.Controllers
{
var linkInfo = _linkService.Parse(new Uri(request.Url));
if (linkInfo.Provider != Provider.YouTube && request.Quality.HasValue && request.Quality.Value.IsAudio())
{
throw new ArgumentException("Only YouTube supports audio feeds");
}
var feed = new FeedMetadata
{
Provider = linkInfo.Provider,
@@ -69,9 +62,7 @@ namespace Podsync.Controllers
feed.Quality = ResolveFormat.VideoHigh;
}
feed.PageSize = Constants.DefaultPageSize;
var feedId = await _storageService.Save(feed);
var feedId = await _feedService.Create(feed);
var url = _linkService.Feed(Request.GetBaseUrl(), feedId);
return url;
@@ -82,11 +73,11 @@ namespace Podsync.Controllers
[ValidateModelState]
public async Task<IActionResult> Feed([Required] string feedId)
{
Rss rss;
Feed feed;
try
{
rss = await _rssBuilder.Query(feedId);
feed = await _feedService.Get(feedId);
}
catch (KeyNotFoundException)
{
@@ -98,16 +89,16 @@ namespace Podsync.Controllers
// Set atom link to this feed
// See https://validator.w3.org/feed/docs/warning/MissingAtomSelfLink.html
var selfLink = new Uri(selfHost, Request.Path);
rss.Channels.ForEach(x => x.AtomLink = selfLink);
feed.Channels.ForEach(x => x.AtomLink = selfLink);
// No magic here, just make download links to DownloadController.Download
rss.Channels.SelectMany(x => x.Items).ForEach(item =>
feed.Channels.SelectMany(x => x.Items).ForEach(item =>
{
var ext = Extensions[item.ContentType];
item.DownloadLink = new Uri(selfHost, $"download/{feedId}/{item.Id}.{ext}");
});
return Content(rss.ToString(), "application/rss+xml; charset=UTF-8");
return Content(feed.ToString(), "application/rss+xml; charset=UTF-8");
}
}
}

View File

@@ -9,7 +9,7 @@ using Podsync.Services.Links;
using Podsync.Services.Storage;
using Shared;
namespace Podsync.Services.Rss
namespace Podsync.Services.Rss.Builders
{
// ReSharper disable once ClassNeverInstantiated.Global
public class CompositeRssBuilder : RssBuilderBase
@@ -34,7 +34,7 @@ namespace Podsync.Services.Rss
get { throw new NotSupportedException(); }
}
public override Task<Feed.Rss> Query(FeedMetadata feed)
public override Task<Contracts.Feed> Query(FeedMetadata feed)
{
try
{

View File

@@ -2,7 +2,7 @@
using Podsync.Services.Links;
using Podsync.Services.Storage;
namespace Podsync.Services.Rss
namespace Podsync.Services.Rss.Builders
{
public abstract class RssBuilderBase : IRssBuilder
{
@@ -15,13 +15,13 @@ namespace Podsync.Services.Rss
public abstract Provider Provider { get; }
public async Task<Feed.Rss> Query(string feedId)
public async Task<Contracts.Feed> Query(string feedId)
{
var metadata = await _storageService.Load(feedId);
return await Query(metadata);
}
public abstract Task<Feed.Rss> Query(FeedMetadata metadata);
public abstract Task<Contracts.Feed> Query(FeedMetadata metadata);
}
}

View File

@@ -3,11 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Podsync.Services.Links;
using Podsync.Services.Rss.Feed;
using Podsync.Services.Rss.Contracts;
using Podsync.Services.Storage;
using Podsync.Services.Videos.Vimeo;
namespace Podsync.Services.Rss
namespace Podsync.Services.Rss.Builders
{
// ReSharper disable once ClassNeverInstantiated.Global
public class VimeoRssBuilder : RssBuilderBase
@@ -21,7 +21,7 @@ namespace Podsync.Services.Rss
public override Provider Provider { get; } = Provider.Vimeo;
public override async Task<Feed.Rss> Query(FeedMetadata metadata)
public override async Task<Feed> Query(FeedMetadata metadata)
{
var linkType = metadata.LinkType;
@@ -54,7 +54,7 @@ namespace Podsync.Services.Rss
throw new NotSupportedException("URL type is not supported");
}
var rss = new Feed.Rss
var rss = new Feed
{
Channels = new[] { channel }
};

View File

@@ -3,13 +3,13 @@ using System.Linq;
using System.Threading.Tasks;
using Podsync.Services.Links;
using Podsync.Services.Resolver;
using Podsync.Services.Rss.Feed;
using Podsync.Services.Rss.Contracts;
using Podsync.Services.Storage;
using Podsync.Services.Videos.YouTube;
using Channel = Podsync.Services.Rss.Feed.Channel;
using Channel = Podsync.Services.Rss.Contracts.Channel;
using Video = Podsync.Services.Videos.YouTube.Video;
namespace Podsync.Services.Rss
namespace Podsync.Services.Rss.Builders
{
public class YouTubeRssBuilder : RssBuilderBase
{
@@ -22,7 +22,7 @@ namespace Podsync.Services.Rss
public override Provider Provider { get; } = Provider.YouTube;
public override async Task<Feed.Rss> Query(FeedMetadata metadata)
public override async Task<Feed> Query(FeedMetadata metadata)
{
if (metadata.Provider != Provider.YouTube)
{
@@ -57,7 +57,7 @@ namespace Podsync.Services.Rss
channel.Items = videos.Select(youtubeVideo => MakeItem(youtubeVideo, metadata)).ToArray();
var rss = new Feed.Rss
var rss = new Feed
{
Channels = new[] { channel }
};

View File

@@ -4,7 +4,7 @@ using System.Xml.Schema;
using System.Xml.Serialization;
using Shared;
namespace Podsync.Services.Rss.Feed
namespace Podsync.Services.Rss.Contracts
{
[XmlRoot("channel")]
public class Channel : IXmlSerializable

View File

@@ -4,19 +4,18 @@ using System.Linq;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using Podsync.Services.Rss.Feed.Internal;
using Shared;
namespace Podsync.Services.Rss.Feed
namespace Podsync.Services.Rss.Contracts
{
[XmlRoot("rss")]
public class Rss : IXmlSerializable
public class Feed : IXmlSerializable
{
public const string Version = "2.0";
public IEnumerable<Channel> Channels { get; set; }
public Rss()
public Feed()
{
Channels = Enumerable.Empty<Channel>();
}
@@ -47,7 +46,7 @@ namespace Podsync.Services.Rss.Feed
public override string ToString()
{
var serializer = new XmlSerializer(typeof(Rss));
var serializer = new XmlSerializer(typeof(Feed));
// Serialize feed to XML string
using (var writer = new Utf8StringWriter())

View File

@@ -4,7 +4,7 @@ using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace Podsync.Services.Rss.Feed
namespace Podsync.Services.Rss.Contracts
{
[XmlRoot("item")]
public class Item : IXmlSerializable

View File

@@ -1,4 +1,4 @@
namespace Podsync.Services.Rss.Feed
namespace Podsync.Services.Rss.Contracts
{
public static class Namespaces
{

View File

@@ -0,0 +1,37 @@
using System;
using System.Threading.Tasks;
using Podsync.Helpers;
using Podsync.Services.Links;
using Podsync.Services.Storage;
namespace Podsync.Services.Rss
{
public class FeedService : IFeedService
{
private readonly IStorageService _storageService;
private readonly IRssBuilder _rssBuilder;
public FeedService(IStorageService storageService, IRssBuilder rssBuilder)
{
_storageService = storageService;
_rssBuilder = rssBuilder;
}
public Task<string> Create(FeedMetadata metadata)
{
if (metadata.Provider != Provider.YouTube && metadata.Quality.IsAudio())
{
throw new ArgumentException("Only YouTube supports audio feeds");
}
metadata.PageSize = Constants.DefaultPageSize;
return _storageService.Save(metadata);
}
public Task<Contracts.Feed> Get(string id)
{
return _rssBuilder.Query(id);
}
}
}

View File

@@ -0,0 +1,12 @@
using System.Threading.Tasks;
using Podsync.Services.Storage;
namespace Podsync.Services.Rss
{
public interface IFeedService
{
Task<string> Create(FeedMetadata metadata);
Task<Contracts.Feed> Get(string id);
}
}

View File

@@ -1,5 +1,6 @@
using System.Threading.Tasks;
using Podsync.Services.Links;
using Podsync.Services.Rss.Contracts;
using Podsync.Services.Storage;
namespace Podsync.Services.Rss
@@ -8,8 +9,8 @@ namespace Podsync.Services.Rss
{
Provider Provider { get; }
Task<Feed.Rss> Query(string feedId);
Task<Feed> Query(string feedId);
Task<Feed.Rss> Query(FeedMetadata metadata);
Task<Feed> Query(FeedMetadata metadata);
}
}

View File

@@ -1,7 +1,7 @@
using System.IO;
using System.Text;
namespace Podsync.Services.Rss.Feed.Internal
namespace Podsync.Services.Rss
{
public class Utf8StringWriter : StringWriter
{

View File

@@ -15,6 +15,7 @@ using Podsync.Services.Links;
using Podsync.Services.Patreon;
using Podsync.Services.Resolver;
using Podsync.Services.Rss;
using Podsync.Services.Rss.Builders;
using Podsync.Services.Storage;
using Podsync.Services.Videos.Vimeo;
using Podsync.Services.Videos.YouTube;
@@ -55,6 +56,7 @@ namespace Podsync
services.AddSingleton<IStorageService, RedisStorage>();
services.AddSingleton<IRssBuilder, CompositeRssBuilder>();
services.AddSingleton<IPatreonApi, PatreonApi>();
services.AddSingleton<IFeedService, FeedService>();
// Add authentication services
services.AddAuthentication(config => config.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme);

View File

@@ -1,10 +1,10 @@
using System;
using System.IO;
using System.Xml.Serialization;
using Podsync.Services.Rss.Feed;
using Podsync.Services.Rss.Contracts;
using Xunit;
namespace Podsync.Tests.Services.Rss.Feed
namespace Podsync.Tests.Services.Rss.Contracts
{
public class FeedSerializationTests
{
@@ -13,7 +13,7 @@ namespace Podsync.Tests.Services.Rss.Feed
[Fact]
public void SerializeFeedTest()
{
var feed = new Podsync.Services.Rss.Feed.Rss();
var feed = new Feed();
var item = new Item
{
@@ -50,7 +50,7 @@ namespace Podsync.Tests.Services.Rss.Feed
channel
};
var serializer = new XmlSerializer(typeof(Podsync.Services.Rss.Feed.Rss));
var serializer = new XmlSerializer(typeof(Feed));
string body;
using (var writer = new StringWriter())

View File

@@ -3,7 +3,7 @@ using System.Linq;
using System.Threading.Tasks;
using Moq;
using Podsync.Services.Links;
using Podsync.Services.Rss;
using Podsync.Services.Rss.Builders;
using Podsync.Services.Storage;
using Podsync.Services.Videos.Vimeo;
using Xunit;

View File

@@ -3,7 +3,7 @@ using System.Linq;
using System.Threading.Tasks;
using Moq;
using Podsync.Services.Links;
using Podsync.Services.Rss;
using Podsync.Services.Rss.Builders;
using Podsync.Services.Storage;
using Podsync.Services.Videos.YouTube;
using Xunit;