Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Recently requested improvements #4755

Merged
merged 6 commits into from
Sep 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions src/Ombi.Core.Tests/Services/RecentlyRequestedServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public void Setup()
.ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
_mocker = new AutoMocker();

_mocker.Setup<ICurrentUser, Task<OmbiUser>>(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "test", Alias = "alias", Language = "en" });
_mocker.Setup<ICurrentUser, string>(x => x.Username).Returns("test");
_subject = _mocker.CreateInstance<RecentlyRequestedService>();
}

Expand Down Expand Up @@ -70,8 +73,6 @@ public async Task GetRecentlyRequested_Movies()
_mocker.Setup<IMovieRequestRepository, IQueryable<MovieRequests>>(x => x.GetAll()).Returns(movies.AsQueryable().BuildMock().Object);
_mocker.Setup<IMusicRequestRepository, IQueryable<AlbumRequest>>(x => x.GetAll()).Returns(albums.AsQueryable().BuildMock().Object);
_mocker.Setup<ITvRequestRepository, IQueryable<ChildRequests>>(x => x.GetChild()).Returns(chilRequests.AsQueryable().BuildMock().Object);
_mocker.Setup<ICurrentUser, Task<OmbiUser>>(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "test", Alias = "alias" });
_mocker.Setup<ICurrentUser, string>(x => x.Username).Returns("test");

var result = await _subject.GetRecentlyRequested(CancellationToken.None);

Expand Down Expand Up @@ -134,8 +135,6 @@ public async Task GetRecentlyRequested_Movies_HideAvailable()
_mocker.Setup<IMovieRequestRepository, IQueryable<MovieRequests>>(x => x.GetAll()).Returns(movies.AsQueryable().BuildMock().Object);
_mocker.Setup<IMusicRequestRepository, IQueryable<AlbumRequest>>(x => x.GetAll()).Returns(albums.AsQueryable().BuildMock().Object);
_mocker.Setup<ITvRequestRepository, IQueryable<ChildRequests>>(x => x.GetChild()).Returns(chilRequests.AsQueryable().BuildMock().Object);
_mocker.Setup<ICurrentUser, Task<OmbiUser>>(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "test", Alias = "alias" });
_mocker.Setup<ICurrentUser, string>(x => x.Username).Returns("test");

var result = await _subject.GetRecentlyRequested(CancellationToken.None);

Expand Down Expand Up @@ -167,8 +166,6 @@ public async Task GetRecentlyRequested()
_mocker.Setup<IMovieRequestRepository, IQueryable<MovieRequests>>(x => x.GetAll()).Returns(movies.AsQueryable().BuildMock().Object);
_mocker.Setup<IMusicRequestRepository, IQueryable<AlbumRequest>>(x => x.GetAll()).Returns(albums.AsQueryable().BuildMock().Object);
_mocker.Setup<ITvRequestRepository, IQueryable<ChildRequests>>(x => x.GetChild()).Returns(chilRequests.AsQueryable().BuildMock().Object);
_mocker.Setup<ICurrentUser, Task<OmbiUser>>(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "test", Alias = "alias" });
_mocker.Setup<ICurrentUser, string>(x => x.Username).Returns("test");

var result = await _subject.GetRecentlyRequested(CancellationToken.None);

Expand Down
3 changes: 3 additions & 0 deletions src/Ombi.Core/Models/Requests/RecentlyRequestedModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@ public class RecentlyRequestedModel
public DateTime ReleaseDate { get; set; }
public bool Approved { get; set; }
public string MediaId { get; set; }

public string PosterPath { get; set; }
public string Background { get; set; }
}
}
47 changes: 42 additions & 5 deletions src/Ombi.Core/Services/RecentlyRequestedService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using Ombi.Api.TheMovieDb;
using Ombi.Core.Authentication;
using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Helpers;
Expand All @@ -12,7 +13,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static Ombi.Core.Engine.BaseMediaEngine;
Expand All @@ -26,7 +26,8 @@ public class RecentlyRequestedService : BaseEngine, IRecentlyRequestedService
private readonly IMusicRequestRepository _musicRequestRepository;
private readonly ISettingsService<CustomizationSettings> _customizationSettings;
private readonly ISettingsService<OmbiSettings> _ombiSettings;

private readonly IMovieDbApi _movieDbApi;
private readonly ICacheService _cache;
private const int AmountToTake = 7;

public RecentlyRequestedService(
Expand All @@ -37,13 +38,17 @@ public RecentlyRequestedService(
ISettingsService<OmbiSettings> ombiSettings,
ICurrentUser user,
OmbiUserManager um,
IRuleEvaluator rules) : base(user, um, rules)
IRuleEvaluator rules,
IMovieDbApi movieDbApi,
ICacheService cache) : base(user, um, rules)
{
_movieRequestRepository = movieRequestRepository;
_tvRequestRepository = tvRequestRepository;
_musicRequestRepository = musicRequestRepository;
_customizationSettings = customizationSettings;
_ombiSettings = ombiSettings;
_movieDbApi = movieDbApi;
_cache = cache;
}

public async Task<IEnumerable<RecentlyRequestedModel>> GetRecentlyRequested(CancellationToken cancellationToken)
Expand All @@ -65,8 +70,10 @@ public async Task<IEnumerable<RecentlyRequestedModel>> GetRecentlyRequested(Canc

var model = new List<RecentlyRequestedModel>();

var lang = await DefaultLanguageCode();
foreach (var item in await recentMovieRequests.ToListAsync(cancellationToken))
{
var images = await _cache.GetOrAddAsync($"{CacheKeys.TmdbImages}movie{item.TheMovieDbId}", () => _movieDbApi.GetMovieImages(item.TheMovieDbId.ToString(), cancellationToken), DateTimeOffset.Now.AddDays(1));
model.Add(new RecentlyRequestedModel
{
RequestId = item.Id,
Expand All @@ -80,6 +87,8 @@ public async Task<IEnumerable<RecentlyRequestedModel>> GetRecentlyRequested(Canc
UserId = hideUsers.Hide ? string.Empty : item.RequestedUserId,
Username = hideUsers.Hide ? string.Empty : item.RequestedUser.UserAlias,
MediaId = item.TheMovieDbId.ToString(),
PosterPath = images?.posters?.Where(x => lang.Equals(x?.iso_639_1, StringComparison.InvariantCultureIgnoreCase))?.OrderByDescending(x => x.vote_count)?.Select(x => x.file_path)?.FirstOrDefault(),
Background = images?.backdrops?.Where(x => lang.Equals(x?.iso_639_1, StringComparison.InvariantCultureIgnoreCase))?.OrderByDescending(x => x.vote_count)?.Select(x => x.file_path)?.FirstOrDefault(),
});
}

Expand All @@ -103,6 +112,9 @@ public async Task<IEnumerable<RecentlyRequestedModel>> GetRecentlyRequested(Canc

foreach (var item in await recentTvRequests.ToListAsync(cancellationToken))
{
var providerId = item.ParentRequest.ExternalProviderId.ToString();
var images = await _cache.GetOrAddAsync($"{CacheKeys.TmdbImages}tv{providerId}", () => _movieDbApi.GetTvImages(providerId.ToString(), cancellationToken), DateTimeOffset.Now.AddDays(1));

var partialAvailability = item.SeasonRequests.SelectMany(x => x.Episodes).Any(e => e.Available);
model.Add(new RecentlyRequestedModel
{
Expand All @@ -117,7 +129,9 @@ public async Task<IEnumerable<RecentlyRequestedModel>> GetRecentlyRequested(Canc
Type = RequestType.TvShow,
UserId = hideUsers.Hide ? string.Empty : item.RequestedUserId,
Username = hideUsers.Hide ? string.Empty : item.RequestedUser.UserAlias,
MediaId = item.ParentRequest.ExternalProviderId.ToString()
MediaId = providerId.ToString(),
PosterPath = images?.posters?.Where(x => lang.Equals(x?.iso_639_1, StringComparison.InvariantCultureIgnoreCase))?.OrderByDescending(x => x.vote_count)?.Select(x => x.file_path)?.FirstOrDefault(),
Background = images?.backdrops?.Where(x => lang.Equals(x?.iso_639_1, StringComparison.InvariantCultureIgnoreCase))?.OrderByDescending(x => x.vote_count)?.Select(x => x.file_path)?.FirstOrDefault(),
});
}

Expand All @@ -134,13 +148,36 @@ private async Task<HideResult> HideFromOtherUsers()
UserId = user.Id
};
}
var settings = await _ombiSettings.GetSettingsAsync();
var settings = await GetOmbiSettings();
var result = new HideResult
{
Hide = settings.HideRequestsUsers,
UserId = user.Id
};
return result;
}
protected async Task<string> DefaultLanguageCode()
{
var user = await GetUser();
if (user == null)
{
return "en";
}

if (string.IsNullOrEmpty(user.Language))
{
var s = await GetOmbiSettings();
return s.DefaultLanguageCode;
}

return user.Language;
}


private OmbiSettings ombiSettings;
protected async Task<OmbiSettings> GetOmbiSettings()
{
return ombiSettings ??= await _ombiSettings.GetSettingsAsync();
}
}
}
3 changes: 2 additions & 1 deletion src/Ombi.TheMovieDbApi/IMovieDbApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public interface IMovieDbApi
Task<List<Language>> GetLanguages(CancellationToken cancellationToken);
Task<List<WatchProvidersResults>> SearchWatchProviders(string media, string searchTerm, CancellationToken cancellationToken);
Task<List<MovieDbSearchResult>> AdvancedSearch(DiscoverModel model, int page, CancellationToken cancellationToken);
Task<TvImages> GetTvImages(string theMovieDbId, CancellationToken token);
Task<MovieDbImages> GetTvImages(string theMovieDbId, CancellationToken token);
Task<MovieDbImages> GetMovieImages(string theMovieDbId, CancellationToken token);
}
}
2 changes: 1 addition & 1 deletion src/Ombi.TheMovieDbApi/Models/TvImages.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Ombi.Api.TheMovieDb.Models
{
public class TvImages
public class MovieDbImages
{
public Backdrop[] backdrops { get; set; }
public int id { get; set; }
Expand Down
14 changes: 11 additions & 3 deletions src/Ombi.TheMovieDbApi/TheMovieDbApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -514,12 +514,20 @@ public Task<WatchProviders> GetTvWatchProviders(int theMoviedbId, CancellationTo
return Api.Request<WatchProviders>(request, token);
}

public Task<TvImages> GetTvImages(string theMovieDbId, CancellationToken token)
public Task<MovieDbImages> GetTvImages(string theMovieDbId, CancellationToken token)
{
var request = new Request($"tv/{theMovieDbId}/images", BaseUri, HttpMethod.Get);
request.AddQueryString("api_key", ApiToken);

return Api.Request<TvImages>(request, token);

return Api.Request<MovieDbImages>(request, token);
}

public Task<MovieDbImages> GetMovieImages(string theMovieDbId, CancellationToken token)
{
var request = new Request($"movie/{theMovieDbId}/images", BaseUri, HttpMethod.Get);
request.AddQueryString("api_key", ApiToken);

return Api.Request<MovieDbImages>(request, token);
}

private async Task AddDiscoverSettings(Request request)
Expand Down
18 changes: 0 additions & 18 deletions src/Ombi/ClientApp/src/app/components/button/button.component.scss

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { MatButtonModule } from "@angular/material/button";
selector: 'ombi-button',
imports: [...OmbiCommonModules, MatButtonModule],
changeDetection: ChangeDetectionStrategy.OnPush,
styleUrls: ['./button.component.scss'],
template: `
<button [id]="id" [type]="type" [class]="class" [data-toggle]="dataToggle" mat-raised-button [data-target]="dataTarget">{{text}}</button>
`
Expand All @@ -17,7 +16,7 @@ import { MatButtonModule } from "@angular/material/button";
@Input() public text: string;

@Input() public id: string;
@Input() public type: string;
@Input() public type: string = "primary";
@Input() public class: string;
@Input('data-toggle') public dataToggle: string;
@Input('data-target') public dataTarget: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div id="detailed-{{request.mediaId}}" class="detailed-container" (click)="click()" [style.background-image]="background">
<div id="detailed-{{request.mediaId}}" class="detailed-container" [style.background-image]="background">
<div class="row">
<div class="col-xl-5 col-lg-5 col-md-5 col-sm-12 posterColumn">
<ombi-image [src]="request.posterPath" [type]="request.type" class="poster" alt="{{request.title}}">
<ombi-image (click)="click()" [src]="request.posterPath" [type]="request.type" class="poster" alt="{{request.title}}">
</ombi-image>
</div>
<div class="col-xl-7 col-lg-7 col-md-7 col-sm-12">
Expand All @@ -20,6 +20,11 @@ <h3 id="detailed-request-title-{{request.mediaId}}">{{request.title}}</h3>
<p id="detailed-request-status-{{request.mediaId}}">{{'MediaDetails.Status' | translate}} <span class="badge badge-{{getClass(request)}}">{{getStatus(request) | translate}}</span></p>
</div>
</div>
<div class="row action-items">
<div class="col-12" *ngIf="isAdmin">
<button *ngIf="!request.approved" id="detailed-request-approve-{{request.mediaId}}" color="accent" mat-raised-button (click)="approve()">{{'Common.Approve' | translate}}</button>
</div>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

.detailed-container {
width: 400px;
height: auto;
height: 250px;
margin: 10px;
padding: 10px;
border-radius: 10px;
border: 1px solid $ombi-background-primary-accent;

@media (max-width:768px) {
width: 200px;
height: auto;
}

background-color: $ombi-background-accent;
Expand All @@ -36,12 +37,18 @@
border-radius: 10px;
opacity: 1;
display: block;
height: 225px;
width: 100%;
height: 200px;
transition: .5s ease;
backface-visibility: hidden;
border: 1px solid #35465c;
}

.action-items {
@media (min-width:768px) {
bottom: 0;
position: absolute;
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ NewMovieRequest.args = {
overview: 'The Matrix is a movie about a group of people who are forced to fight against a powerful computer system that controls them.',
releaseDate: new Date(2020, 1, 1),
} as IRecentlyRequested,
isAdmin: false,
};

export const MovieNoUsername = Template.bind({});
Expand Down Expand Up @@ -206,4 +207,60 @@ TvNoUsername.args = {
mediaId: '603',
releaseDate: new Date(2020, 1, 1),
} as IRecentlyRequested,
};

export const AdminNewMovie = Template.bind({});
// More on args: https://storybook.js.org/docs/angular/writing-stories/args
AdminNewMovie.args = {
request: {
title: 'The Matrix',
approved: false,
available: false,
tvPartiallyAvailable: false,
requestDate: new Date(2022, 1, 1),
username: 'John Doe',
userId: '12345',
type: RequestType.movie,
mediaId: '603',
overview: 'The Matrix is a movie about a group of people who are forced to fight against a powerful computer system that controls them.',
releaseDate: new Date(2020, 1, 1),
} as IRecentlyRequested,
isAdmin: true,
};

export const AdminTvShow = Template.bind({});
// More on args: https://storybook.js.org/docs/angular/writing-stories/args
AdminTvShow.args = {
request: {
title: 'For All Mankind',
approved: false,
available: false,
tvPartiallyAvailable: true,
requestDate: new Date(2022, 1, 1),
userId: '12345',
type: RequestType.tvShow,
mediaId: '603',
username: 'John Doe',
releaseDate: new Date(2020, 1, 1),
} as IRecentlyRequested,
isAdmin: true,
};

export const AdminApprovedMovie = Template.bind({});
// More on args: https://storybook.js.org/docs/angular/writing-stories/args
AdminApprovedMovie.args = {
request: {
title: 'The Matrix',
approved: true,
available: false,
tvPartiallyAvailable: false,
requestDate: new Date(2022, 1, 1),
username: 'John Doe',
userId: '12345',
type: RequestType.movie,
mediaId: '603',
overview: 'The Matrix is a movie about a group of people who are forced to fight against a powerful computer system that controls them.',
releaseDate: new Date(2020, 1, 1),
} as IRecentlyRequested,
isAdmin: true,
};
Loading