More Polish (#2665)
This commit is contained in:
parent
47547c23dd
commit
e8d9a8b3a3
14 changed files with 151 additions and 91 deletions
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Constants;
|
||||
|
@ -26,6 +27,7 @@ public interface IExternalSeriesMetadataRepository
|
|||
void Remove(IEnumerable<ExternalRating>? ratings);
|
||||
void Remove(IEnumerable<ExternalRecommendation>? recommendations);
|
||||
Task<ExternalSeriesMetadata?> GetExternalSeriesMetadata(int seriesId, int limit = 25);
|
||||
Task<bool> ExternalSeriesMetadataNeedsRefresh(int seriesId, DateTime expireTime);
|
||||
Task<SeriesDetailPlusDto> GetSeriesDetailPlusDto(int seriesId, int libraryId, AppUser user);
|
||||
Task LinkRecommendationsToSeries(Series series);
|
||||
}
|
||||
|
@ -86,24 +88,22 @@ public class ExternalSeriesMetadataRepository : IExternalSeriesMetadataRepositor
|
|||
return _context.ExternalSeriesMetadata
|
||||
.Where(s => s.SeriesId == seriesId)
|
||||
.Include(s => s.ExternalReviews.Take(limit))
|
||||
.Include(s => s.ExternalRatings.Take(limit))
|
||||
.Include(s => s.ExternalRecommendations.Take(limit))
|
||||
.Include(s => s.ExternalRatings.OrderBy(r => r.AverageScore).Take(limit))
|
||||
.Include(s => s.ExternalRecommendations.OrderBy(r => r.Id).Take(limit))
|
||||
.AsSplitQuery()
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> ExternalSeriesMetadataNeedsRefresh(int seriesId, DateTime expireTime)
|
||||
{
|
||||
var row = await _context.ExternalSeriesMetadata
|
||||
.Where(s => s.SeriesId == seriesId)
|
||||
.FirstOrDefaultAsync();
|
||||
return row == null || row.LastUpdatedUtc <= expireTime;
|
||||
}
|
||||
|
||||
public async Task<SeriesDetailPlusDto> GetSeriesDetailPlusDto(int seriesId, int libraryId, AppUser user)
|
||||
{
|
||||
var canSeeExternalSeries = user is { AgeRestriction: AgeRating.NotApplicable } &&
|
||||
await _userManager.IsInRoleAsync(user, PolicyConstants.AdminRole);
|
||||
|
||||
var allowedLibraries = await _context.Library
|
||||
.Where(library => library.AppUsers.Any(x => x.Id == user.Id))
|
||||
.Select(l => l.Id)
|
||||
.ToListAsync();
|
||||
|
||||
var userRating = await _context.AppUser.GetUserAgeRestriction(user.Id);
|
||||
|
||||
var seriesDetailDto = await _context.ExternalSeriesMetadata
|
||||
.Where(m => m.SeriesId == seriesId)
|
||||
.Include(m => m.ExternalRatings)
|
||||
|
@ -116,29 +116,30 @@ public class ExternalSeriesMetadataRepository : IExternalSeriesMetadataRepositor
|
|||
return null; // or handle the case when seriesDetailDto is not found
|
||||
}
|
||||
|
||||
var externalSeriesRecommendations = new List<ExternalSeriesDto>();
|
||||
if (!canSeeExternalSeries)
|
||||
{
|
||||
externalSeriesRecommendations = seriesDetailDto.ExternalRecommendations
|
||||
.Where(r => r.SeriesId is null or 0)
|
||||
.Select(r => _mapper.Map<ExternalSeriesDto>(r))
|
||||
.ToList();
|
||||
}
|
||||
var externalSeriesRecommendations = seriesDetailDto.ExternalRecommendations
|
||||
.Where(r => r.SeriesId == null)
|
||||
.Select(r => _mapper.Map<ExternalSeriesDto>(r))
|
||||
.ToList();
|
||||
|
||||
var ownedIds = seriesDetailDto.ExternalRecommendations
|
||||
.Where(r => r.SeriesId != null)
|
||||
.Select(r => r.SeriesId)
|
||||
.ToList();
|
||||
|
||||
var ownedSeriesRecommendations = await _context.ExternalRecommendation
|
||||
.Where(r => r.SeriesId > 0 && allowedLibraries.Contains(r.Series.LibraryId))
|
||||
.Join(_context.Series, r => r.SeriesId, s => s.Id, (recommendation, series) => series)
|
||||
.RestrictAgainstAgeRestriction(userRating)
|
||||
var ownedSeriesRecommendations = await _context.Series
|
||||
.Where(s => ownedIds.Contains(s.Id))
|
||||
.OrderBy(s => s.SortName.ToLower())
|
||||
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider)
|
||||
.AsNoTracking()
|
||||
.ToListAsync();
|
||||
|
||||
var seriesDetailPlusDto = new SeriesDetailPlusDto()
|
||||
{
|
||||
Ratings = seriesDetailDto.ExternalRatings.Select(r => _mapper.Map<RatingDto>(r)),
|
||||
Reviews = seriesDetailDto.ExternalReviews.OrderByDescending(r => r.Score)
|
||||
Ratings = seriesDetailDto.ExternalRatings
|
||||
.DefaultIfEmpty()
|
||||
.Select(r => _mapper.Map<RatingDto>(r)),
|
||||
Reviews = seriesDetailDto.ExternalReviews
|
||||
.DefaultIfEmpty()
|
||||
.OrderByDescending(r => r.Score)
|
||||
.Select(r =>
|
||||
{
|
||||
var ret = _mapper.Map<UserReviewDto>(r);
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using API.Constants;
|
||||
using API.Data.ManualMigrations;
|
||||
using API.Data.Misc;
|
||||
using API.Data.Scanner;
|
||||
using API.DTOs;
|
||||
|
@ -14,7 +12,6 @@ using API.DTOs.Dashboard;
|
|||
using API.DTOs.Filtering;
|
||||
using API.DTOs.Filtering.v2;
|
||||
using API.DTOs.Metadata;
|
||||
using API.DTOs.Reader;
|
||||
using API.DTOs.ReadingLists;
|
||||
using API.DTOs.Search;
|
||||
using API.DTOs.SeriesDetail;
|
||||
|
@ -34,7 +31,6 @@ using AutoMapper;
|
|||
using AutoMapper.QueryableExtensions;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SQLite;
|
||||
|
||||
|
||||
namespace API.Data.Repositories;
|
||||
|
@ -95,6 +91,7 @@ public interface ISeriesRepository
|
|||
Task<IEnumerable<Series>> GetSeriesForLibraryIdAsync(int libraryId, SeriesIncludes includes = SeriesIncludes.None);
|
||||
Task<SeriesDto?> GetSeriesDtoByIdAsync(int seriesId, int userId);
|
||||
Task<Series?> GetSeriesByIdAsync(int seriesId, SeriesIncludes includes = SeriesIncludes.Volumes | SeriesIncludes.Metadata);
|
||||
Task<IList<SeriesDto>> GetSeriesDtoByIdsAsync(IEnumerable<int> seriesIds, AppUser user);
|
||||
Task<IList<Series>> GetSeriesByIdsAsync(IList<int> seriesIds);
|
||||
Task<int[]> GetChapterIdsForSeriesAsync(IList<int> seriesIds);
|
||||
Task<IDictionary<int, IList<int>>> GetChapterIdWithSeriesIdForSeriesAsync(int[] seriesIds);
|
||||
|
@ -569,6 +566,26 @@ public class SeriesRepository : ISeriesRepository
|
|||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<IList<SeriesDto>> GetSeriesDtoByIdsAsync(IEnumerable<int> seriesIds, AppUser user)
|
||||
{
|
||||
var allowedLibraries = await _context.Library
|
||||
.Where(library => library.AppUsers.Any(x => x.Id == user.Id))
|
||||
.Select(l => l.Id)
|
||||
.ToListAsync();
|
||||
var restriction = new AgeRestriction()
|
||||
{
|
||||
AgeRating = user.AgeRestriction,
|
||||
IncludeUnknowns = user.AgeRestrictionIncludeUnknowns
|
||||
};
|
||||
return await _context.Series
|
||||
.Include(s => s.Metadata)
|
||||
.Where(s => seriesIds.Contains(s.Id) && allowedLibraries.Contains(s.LibraryId))
|
||||
.RestrictAgainstAgeRestriction(restriction)
|
||||
.AsSplitQuery()
|
||||
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<int[]> GetChapterIdsForSeriesAsync(IList<int> seriesIds)
|
||||
{
|
||||
var volumes = await _context.Volume
|
||||
|
@ -1889,22 +1906,25 @@ public class SeriesRepository : ISeriesRepository
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses multiple names to find a match against a series then ensures the user has appropriate access to it. If not, returns null.
|
||||
/// Uses multiple names to find a match against a series. If not, returns null.
|
||||
/// </summary>
|
||||
/// <remarks>This does not restrict to the user at all. That is handled at the API level.</remarks>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="names"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<SeriesDto?> GetSeriesDtoByNamesAndMetadataIdsForUser(int userId, IEnumerable<string> names, LibraryType libraryType, string aniListUrl, string malUrl)
|
||||
{
|
||||
var userRating = await _context.AppUser.GetUserAgeRestriction(userId);
|
||||
var libraryIds = await _context.Library.GetUserLibrariesByType(userId, libraryType).ToListAsync();
|
||||
var libraryIds = await _context.Library
|
||||
.Where(lib => lib.Type == libraryType)
|
||||
.Select(l => l.Id)
|
||||
.ToListAsync();
|
||||
|
||||
var normalizedNames = names.Select(n => n.ToNormalized()).ToList();
|
||||
SeriesDto? result = null;
|
||||
if (!string.IsNullOrEmpty(aniListUrl) || !string.IsNullOrEmpty(malUrl))
|
||||
{
|
||||
// TODO: I can likely work AniList and MalIds from ExternalSeriesMetadata in here
|
||||
result = await _context.Series
|
||||
.RestrictAgainstAgeRestriction(userRating)
|
||||
.Where(s => !string.IsNullOrEmpty(s.Metadata.WebLinks))
|
||||
.Where(s => libraryIds.Contains(s.Library.Id))
|
||||
.WhereIf(!string.IsNullOrEmpty(aniListUrl), s => s.Metadata.WebLinks.Contains(aniListUrl))
|
||||
|
@ -1917,7 +1937,6 @@ public class SeriesRepository : ISeriesRepository
|
|||
if (result != null) return result;
|
||||
|
||||
return await _context.Series
|
||||
.RestrictAgainstAgeRestriction(userRating)
|
||||
.Where(s => normalizedNames.Contains(s.NormalizedName) ||
|
||||
normalizedNames.Contains(s.NormalizedLocalizedName))
|
||||
.Where(s => libraryIds.Contains(s.Library.Id))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue