New: PassThePopcorn collection as import lists

Co-authored-by: Winter <78392041+winterqt@users.noreply.github.com>
This commit is contained in:
Bogdan 2023-11-12 01:42:57 +02:00
parent 198e6324e0
commit 1955392beb
5 changed files with 183 additions and 0 deletions

View File

@ -0,0 +1,31 @@
using System;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.ImportLists.PassThePopcorn.Collection;
public class PassThePopcornCollectionImport : HttpImportListBase<PassThePopcornCollectionSettings>
{
public override string Name => "PassThePopcorn Collection";
public override ImportListType ListType => ImportListType.Other;
public override TimeSpan MinRefreshInterval => TimeSpan.FromHours(12);
public override int PageSize => 60;
public override TimeSpan RateLimit => TimeSpan.FromSeconds(10);
public PassThePopcornCollectionImport(IHttpClient httpClient, IImportListStatusService importListStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
: base(httpClient, importListStatusService, configService, parsingService, logger)
{
}
public override IImportListRequestGenerator GetRequestGenerator()
{
return new PassThePopcornCollectionRequestGenerator(Settings);
}
public override IParseImportListResponse GetParser()
{
return new PassThePopcornCollectionParser();
}
}

View File

@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.ImportLists.Exceptions;
using NzbDrone.Core.ImportLists.ImportListMovies;
namespace NzbDrone.Core.ImportLists.PassThePopcorn.Collection;
public class PassThePopcornCollectionParser : IParseImportListResponse
{
public IList<ImportListMovie> ParseResponse(ImportListResponse importListResponse)
{
if (!STJson.TryDeserialize<PassThePopcornCollectionResponse>(importListResponse.Content, out var jsonResponse))
{
throw new ImportListException(importListResponse, "List responded with invalid JSON content. Site is likely blocked or unavailable.");
}
return jsonResponse.CoverView
.Movies
.Select(item => new ImportListMovie
{
ImdbId = item.ImdbId,
Title = WebUtility.HtmlDecode(item.Title),
Year = int.Parse(item.Year)
})
.ToList();
}
}

View File

@ -0,0 +1,51 @@
using System.Collections.Generic;
using NzbDrone.Common.Http;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.ImportLists.PassThePopcorn.Collection;
public class PassThePopcornCollectionRequestGenerator : IImportListRequestGenerator
{
private readonly PassThePopcornCollectionSettings _settings;
public PassThePopcornCollectionRequestGenerator(PassThePopcornCollectionSettings settings)
{
_settings = settings;
}
public ImportListPageableRequestChain GetMovies()
{
var pageableRequests = new ImportListPageableRequestChain();
pageableRequests.Add(GetPagedRequests());
return pageableRequests;
}
private IEnumerable<ImportListRequest> GetPagedRequests()
{
_settings.Validate().Filter("ApiUser", "ApiKey", "MaxPages").ThrowOnError();
var requestBuilder = BuildRequest();
for (var pageNumber = 1; pageNumber <= _settings.MaxPages; pageNumber++)
{
requestBuilder.AddQueryParam("page", pageNumber, true);
var request = requestBuilder.Build();
yield return new ImportListRequest(request);
}
}
private HttpRequestBuilder BuildRequest()
{
return new HttpRequestBuilder(_settings.CollectionUrl)
.Accept(HttpAccept.Json)
.SetHeader("ApiUser", _settings.ApiUser)
.SetHeader("ApiKey", _settings.ApiKey)
.AddQueryParam("action", "get_page")
.AddQueryParam("filter_cat[1]", "1")
.WithRateLimit(5);
}
}

View File

@ -0,0 +1,20 @@
using System.Collections.Generic;
namespace NzbDrone.Core.ImportLists.PassThePopcorn.Collection;
internal class PassThePopcornCollectionResponse
{
public PassThePopcornCoverView CoverView { get; set; }
}
internal class PassThePopcornCoverView
{
public IList<PassThePopcornCollectionMovie> Movies { get; set; }
}
internal class PassThePopcornCollectionMovie
{
public string Title { get; set; }
public string Year { get; set; }
public string ImdbId { get; set; }
}

View File

@ -0,0 +1,52 @@
using System.Text.RegularExpressions;
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.ImportLists.PassThePopcorn.Collection;
public class PassThePopcornCollectionSettingsValidator : AbstractValidator<PassThePopcornCollectionSettings>
{
public PassThePopcornCollectionSettingsValidator()
{
RuleFor(c => c.CollectionUrl).NotEmpty().IsValidUrl();
RuleFor(c => c.CollectionUrl)
.Matches(@"^https://passthepopcorn\.me/collages\.php\?id=\d+(?:&[\w-]+(=[\w-]*)?)*?$", RegexOptions.IgnoreCase)
.WithMessage("Invalid Collection URL. Acceptable format: 'https://passthepopcorn.me/collages.php?id=21&order_by=year&order_way=desc'");
RuleFor(c => c.ApiUser).NotEmpty();
RuleFor(c => c.ApiKey).NotEmpty();
RuleFor(c => c.MaxPages).InclusiveBetween(1, 20);
}
}
public class PassThePopcornCollectionSettings : IProviderConfig
{
private static readonly PassThePopcornCollectionSettingsValidator Validator = new ();
public PassThePopcornCollectionSettings()
{
CollectionUrl = "https://passthepopcorn.me/collages.php?id=21";
MaxPages = 5;
}
[FieldDefinition(0, Label = "Collection URL", HelpText = "Provide a fully URL to your wanted collection, including filters to your liking.", HelpTextWarning = "By default only the category Feature Film will be imported.", HelpLink = "https://passthepopcorn.me/collages.php")]
public string CollectionUrl { get; set; }
[FieldDefinition(1, Label = "API User", HelpText = "These settings are found in your PassThePopcorn security settings (Edit Profile > Security).", Privacy = PrivacyLevel.UserName)]
public string ApiUser { get; set; }
[FieldDefinition(2, Label = "API Key", Type = FieldType.Password, Privacy = PrivacyLevel.Password)]
public string ApiKey { get; set; }
[FieldDefinition(3, Label = "Max Pages", HelpText = "Number of pages to pull from list (Max 20)", Type = FieldType.Number)]
public int MaxPages { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}