Skip to content

Commit

Permalink
Merge pull request Ombi-app#4312 from Ombi-app/feature/request-limits
Browse files Browse the repository at this point in the history
Feature/request limits
  • Loading branch information
tidusjar authored Sep 26, 2021
2 parents f83abaf + d608798 commit e302cf6
Show file tree
Hide file tree
Showing 38 changed files with 7,726 additions and 222 deletions.
527 changes: 527 additions & 0 deletions src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs

Large diffs are not rendered by default.

527 changes: 527 additions & 0 deletions src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs

Large diffs are not rendered by default.

665 changes: 665 additions & 0 deletions src/Ombi.Core.Tests/Engine/TvRequestLimitsTests.cs

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/Ombi.Core.Tests/Ombi.Core.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
<ItemGroup>
<PackageReference Include="AutoFixture" Version="4.11.0" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
<PackageReference Include="Moq" Version="4.14.1" />
<PackageReference Include="Moq" Version="4.15.1" />
<PackageReference Include="Moq.AutoMock" Version="3.0.0" />
<PackageReference Include="Nunit" Version="3.12.0" />
<PackageReference Include="NUnit.ConsoleRunner" Version="3.11.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1">
Expand Down
258 changes: 258 additions & 0 deletions src/Ombi.Core.Tests/Rule/Request/RequestLimitRuleTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
using Moq;
using Moq.AutoMock;
using NUnit.Framework;
using Ombi.Core.Rule;
using Ombi.Core.Rule.Rules.Request;
using Ombi.Core.Services;
using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository.Requests;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ombi.Core.Tests.Rule.Request
{
[TestFixture]
public class RequestLimitRuleTests
{
private AutoMocker _mocker;
private RequestLimitRule _subject;

[SetUp]
public void SetUp()
{
_mocker = new AutoMocker();
_subject = _mocker.CreateInstance<RequestLimitRule>();
}

[Test]
public async Task MovieRule_No_Limit()
{
var limitService = _mocker.GetMock<IRequestLimitService>();
limitService.Setup(x => x.GetRemainingMovieRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
{
HasLimit = false
});

var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
{
RequestType = RequestType.Movie
});

Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(true));
}

[Test]
public async Task MovieRule_Limit_NotReached()
{
var limitService = _mocker.GetMock<IRequestLimitService>();
limitService.Setup(x => x.GetRemainingMovieRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
{
HasLimit = true,
Limit = 2,
Remaining = 1
});

var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
{
RequestType = RequestType.Movie
});

Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(true));
}


[Test]
public async Task MovieRule_Limit_Reached()
{
var limitService = _mocker.GetMock<IRequestLimitService>();
limitService.Setup(x => x.GetRemainingMovieRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
{
HasLimit = true,
Limit = 1,
Remaining = 0
});

var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
{
RequestType = RequestType.Movie
});

Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(false));
}
[Test]
public async Task MusicRule_No_Limit()
{
var limitService = _mocker.GetMock<IRequestLimitService>();
limitService.Setup(x => x.GetRemainingMusicRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
{
HasLimit = false
});

var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
{
RequestType = RequestType.Album
});

Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(true));
}

[Test]
public async Task MusicRule_Limit_NotReached()
{
var limitService = _mocker.GetMock<IRequestLimitService>();
limitService.Setup(x => x.GetRemainingMusicRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
{
HasLimit = true,
Limit = 2,
Remaining = 1
});

var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
{
RequestType = RequestType.Album
});

Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(true));
}


[Test]
public async Task MusicRule_Limit_Reached()
{
var limitService = _mocker.GetMock<IRequestLimitService>();
limitService.Setup(x => x.GetRemainingMusicRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
{
HasLimit = true,
Limit = 1,
Remaining = 0
});

var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
{
RequestType = RequestType.Album
});

Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(false));
}

[Test]
public async Task TvRule_No_Limit()
{
var limitService = _mocker.GetMock<IRequestLimitService>();
limitService.Setup(x => x.GetRemainingTvRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
{
HasLimit = false
});

var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
{
RequestType = RequestType.TvShow
});

Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(true));
}

[Test]
public async Task TvRule_Limit_NotReached()
{
var limitService = _mocker.GetMock<IRequestLimitService>();
limitService.Setup(x => x.GetRemainingTvRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
{
HasLimit = true,
Limit = 2,
Remaining = 1
});

var result = await _subject.Execute(new ChildRequests
{
RequestType = RequestType.TvShow,
SeasonRequests = new List<SeasonRequests>
{
new SeasonRequests
{
Episodes = new List<EpisodeRequests>
{
new EpisodeRequests()
}
}
}
});

Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(true));
}


[Test]
public async Task TvRule_Limit_Reached()
{
var limitService = _mocker.GetMock<IRequestLimitService>();
limitService.Setup(x => x.GetRemainingTvRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
{
HasLimit = true,
Limit = 1,
Remaining = 0
});

var result = await _subject.Execute(new ChildRequests
{
RequestType = RequestType.TvShow,
SeasonRequests = new List<SeasonRequests>
{
new SeasonRequests
{
Episodes = new List<EpisodeRequests>
{
new EpisodeRequests()
}
}
}
});

Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(false));
}

[Test]
public async Task TvRule_Limit_Reached_ManyEpisodes()
{
var limitService = _mocker.GetMock<IRequestLimitService>();
limitService.Setup(x => x.GetRemainingTvRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
{
HasLimit = true,
Limit = 1,
Remaining = 5
});

var result = await _subject.Execute(new ChildRequests
{
RequestType = RequestType.TvShow,
SeasonRequests = new List<SeasonRequests>
{
new SeasonRequests
{
Episodes = new List<EpisodeRequests>
{
new EpisodeRequests(),
new EpisodeRequests(),
new EpisodeRequests(),
}
},
new SeasonRequests
{
Episodes = new List<EpisodeRequests>
{
new EpisodeRequests(),
new EpisodeRequests(),
new EpisodeRequests(),
}
}
}
});

Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(false));
}
}
}
1 change: 0 additions & 1 deletion src/Ombi.Core/Engine/IMusicRequestEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public interface IMusicRequestEngine
Task<RequestEngineResult> RequestAlbum(MusicAlbumRequestViewModel model);
Task<IEnumerable<AlbumRequest>> SearchAlbumRequest(string search);
Task<bool> UserHasRequest(string userId);
Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user = null);
Task<RequestsViewModel<AlbumRequest>> GetRequestsByStatus(int count, int position, string sort, string sortOrder, RequestStatus available);
Task<RequestsViewModel<AlbumRequest>> GetRequests(int count, int position, string sort, string sortOrder);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Ombi.Core/Engine/Interfaces/BaseEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ protected async Task<OmbiUser> GetUser()
return null;
}
var username = Username.ToUpper();
return _user ?? (_user = await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username));
return _user ??= await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username);
}

protected async Task<string> UserAlias()
Expand Down
1 change: 0 additions & 1 deletion src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public interface IRequestEngine<T>
Task<int> GetTotal();
Task UnSubscribeRequest(int requestId, RequestType type);
Task SubscribeToRequest(int requestId, RequestType type);
Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user = null);
Task<RequestEngineResult> ReProcessRequest(int requestId, CancellationToken cancellationToken);
}
}
48 changes: 2 additions & 46 deletions src/Ombi.Core/Engine/MovieRequestEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ public async Task<RequestEngineResult> RequestCollection(int collectionId, Cance
{
var langCode = await DefaultLanguageCode(null);
var collections = await Cache.GetOrAddAsync($"GetCollection{collectionId}{langCode}",
() => MovieApi.GetCollection(langCode, collectionId, cancellationToken), DateTimeOffset.Now.AddDays(1));
() => MovieApi.GetCollection(langCode, collectionId, cancellationToken), DateTimeOffset.Now.AddDays(1));

var results = new List<RequestEngineResult>();
foreach (var collection in collections.parts)
Expand All @@ -583,7 +583,7 @@ public async Task<RequestEngineResult> RequestCollection(int collectionId, Cance
new RequestEngineResult { Result = false, ErrorMessage = $"The whole collection {collections.name} Is already monitored or requested!" };
}

return new RequestEngineResult { Result = true, Message = $"The collection {collections.name} has been successfully added!", RequestId = results.FirstOrDefault().RequestId};
return new RequestEngineResult { Result = true, Message = $"The collection {collections.name} has been successfully added!", RequestId = results.FirstOrDefault().RequestId };
}

private async Task<RequestEngineResult> ProcessSendingMovie(MovieRequests request)
Expand Down Expand Up @@ -753,49 +753,5 @@ await _requestLog.Add(new RequestLog

return new RequestEngineResult { Result = true, Message = $"{movieName} has been successfully added!", RequestId = model.Id };
}

public async Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user)
{
if (user == null)
{
user = await GetUser();

// If user is still null after attempting to get the logged in user, return null.
if (user == null)
{
return null;
}
}

int limit = user.MovieRequestLimit ?? 0;

if (limit <= 0)
{
return new RequestQuotaCountModel()
{
HasLimit = false,
Limit = 0,
Remaining = 0,
NextRequest = DateTime.Now,
};
}

IQueryable<RequestLog> log = _requestLog.GetAll().Where(x => x.UserId == user.Id && x.RequestType == RequestType.Movie);

int count = limit - await log.CountAsync(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7));

DateTime oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7))
.OrderBy(x => x.RequestDate)
.Select(x => x.RequestDate)
.FirstOrDefaultAsync();

return new RequestQuotaCountModel()
{
HasLimit = true,
Limit = limit,
Remaining = count,
NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc),
};
}
}
}
Loading

0 comments on commit e302cf6

Please sign in to comment.