MAL Interest Stacks (#2932)

This commit is contained in:
Joe Milazzo 2024-05-04 15:23:58 -05:00 committed by GitHub
parent 29eb65c783
commit b23300b1a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
61 changed files with 4104 additions and 382 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace API.Data.Migrations
{
/// <inheritdoc />
public partial class SmartCollectionFields : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "MissingSeriesFromSource",
table: "AppUserCollection",
type: "TEXT",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "TotalSourceCount",
table: "AppUserCollection",
type: "INTEGER",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "MissingSeriesFromSource",
table: "AppUserCollection");
migrationBuilder.DropColumn(
name: "TotalSourceCount",
table: "AppUserCollection");
}
}
}

View file

@ -224,6 +224,9 @@ namespace API.Data.Migrations
b.Property<DateTime>("LastSyncUtc")
.HasColumnType("TEXT");
b.Property<string>("MissingSeriesFromSource")
.HasColumnType("TEXT");
b.Property<string>("NormalizedTitle")
.HasColumnType("TEXT");
@ -242,6 +245,9 @@ namespace API.Data.Migrations
b.Property<string>("Title")
.HasColumnType("TEXT");
b.Property<int>("TotalSourceCount")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("AppUserId");

View file

@ -9,6 +9,7 @@ using API.Entities.Enums;
using API.Extensions;
using API.Extensions.QueryExtensions;
using API.Extensions.QueryExtensions.Filtering;
using API.Services.Plus;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using Microsoft.EntityFrameworkCore;
@ -57,6 +58,7 @@ public interface ICollectionTagRepository
Task<IList<AppUserCollection>> GetCollectionsForUserAsync(int userId, CollectionIncludes includes = CollectionIncludes.None);
Task UpdateCollectionAgeRating(AppUserCollection tag);
Task<IEnumerable<AppUserCollection>> GetCollectionsByIds(IEnumerable<int> tags, CollectionIncludes includes = CollectionIncludes.None);
Task<IList<AppUserCollection>> GetAllCollectionsForSyncing(DateTime expirationTime);
}
public class CollectionTagRepository : ICollectionTagRepository
{
@ -207,6 +209,16 @@ public class CollectionTagRepository : ICollectionTagRepository
.ToListAsync();
}
public async Task<IList<AppUserCollection>> GetAllCollectionsForSyncing(DateTime expirationTime)
{
return await _context.AppUserCollection
.Where(c => c.Source == ScrobbleProvider.Mal)
.Where(c => c.LastSyncUtc <= expirationTime)
.Include(c => c.Items)
.AsSplitQuery()
.ToListAsync();
}
public async Task<AppUserCollection?> GetCollectionAsync(int tagId, CollectionIncludes includes = CollectionIncludes.None)
{

View file

@ -73,6 +73,7 @@ public interface ISeriesRepository
void Update(Series series);
void Remove(Series series);
void Remove(IEnumerable<Series> series);
void Detach(Series series);
Task<bool> DoesSeriesNameExistInLibrary(string name, int libraryId, MangaFormat format);
/// <summary>
/// Adds user information like progress, ratings, etc
@ -96,7 +97,7 @@ public interface ISeriesRepository
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<IList<Series>> GetSeriesByIdsAsync(IList<int> seriesIds, bool fullSeries = true);
Task<int[]> GetChapterIdsForSeriesAsync(IList<int> seriesIds);
Task<IDictionary<int, IList<int>>> GetChapterIdWithSeriesIdForSeriesAsync(int[] seriesIds);
/// <summary>
@ -138,6 +139,7 @@ public interface ISeriesRepository
Task<IEnumerable<Series>> GetAllSeriesByNameAsync(IList<string> normalizedNames,
int userId, SeriesIncludes includes = SeriesIncludes.None);
Task<Series?> GetFullSeriesByAnyName(string seriesName, string localizedName, int libraryId, MangaFormat format, bool withFullIncludes = true);
Task<Series?> GetSeriesByAnyName(string seriesName, string localizedName, IList<MangaFormat> formats, int userId);
public Task<IList<Series>> GetAllSeriesByAnyName(string seriesName, string localizedName, int libraryId,
MangaFormat format);
Task<IList<Series>> RemoveSeriesNotInList(IList<ParsedSeries> seenSeries, int libraryId);
@ -204,6 +206,11 @@ public class SeriesRepository : ISeriesRepository
_context.Series.RemoveRange(series);
}
public void Detach(Series series)
{
_context.Entry(series).State = EntityState.Detached;
}
/// <summary>
/// Returns if a series name and format exists already in a library
/// </summary>
@ -531,15 +538,19 @@ public class SeriesRepository : ISeriesRepository
/// Returns Full Series including all external links
/// </summary>
/// <param name="seriesIds"></param>
/// <param name="fullSeries">Include all the includes or just the Series</param>
/// <returns></returns>
public async Task<IList<Series>> GetSeriesByIdsAsync(IList<int> seriesIds)
public async Task<IList<Series>> GetSeriesByIdsAsync(IList<int> seriesIds, bool fullSeries = true)
{
return await _context.Series
.Include(s => s.Volumes)
var query = _context.Series
.Where(s => seriesIds.Contains(s.Id))
.AsSplitQuery();
if (!fullSeries) return await query.ToListAsync();
return await query.Include(s => s.Volumes)
.Include(s => s.Relations)
.Include(s => s.Metadata)
.ThenInclude(m => m.CollectionTags)
.Include(s => s.ExternalSeriesMetadata)
@ -549,9 +560,6 @@ public class SeriesRepository : ISeriesRepository
.ThenInclude(e => e.ExternalReviews)
.Include(s => s.ExternalSeriesMetadata)
.ThenInclude(e => e.ExternalRecommendations)
.Where(s => seriesIds.Contains(s.Id))
.AsSplitQuery()
.ToListAsync();
}
@ -1670,6 +1678,26 @@ public class SeriesRepository : ISeriesRepository
#nullable enable
}
public async Task<Series?> GetSeriesByAnyName(string seriesName, string localizedName, IList<MangaFormat> formats, int userId)
{
var libraryIds = GetLibraryIdsForUser(userId);
var normalizedSeries = seriesName.ToNormalized();
var normalizedLocalized = localizedName.ToNormalized();
return await _context.Series
.Where(s => libraryIds.Contains(s.LibraryId))
.Where(s => formats.Contains(s.Format))
.Where(s =>
s.NormalizedName.Equals(normalizedSeries)
|| s.NormalizedName.Equals(normalizedLocalized)
|| s.NormalizedLocalizedName.Equals(normalizedSeries)
|| (!string.IsNullOrEmpty(normalizedLocalized) && s.NormalizedLocalizedName.Equals(normalizedLocalized))
|| (s.OriginalName != null && s.OriginalName.Equals(seriesName))
)
.FirstOrDefaultAsync();
}
public async Task<IList<Series>> GetAllSeriesByAnyName(string seriesName, string localizedName, int libraryId,
MangaFormat format)
{