Tranform completed shows in watching state when a new item is added

This commit is contained in:
Zoe Roux 2023-12-06 23:01:20 +01:00
parent 1178e8fd6c
commit 38cb4c4f28

View File

@ -29,6 +29,7 @@ using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Abstractions.Models.Utils; using Kyoo.Abstractions.Models.Utils;
using Kyoo.Postgresql; using Kyoo.Postgresql;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace Kyoo.Core.Controllers; namespace Kyoo.Core.Controllers;
@ -52,21 +53,36 @@ public class WatchStatusRepository : IWatchStatusRepository
// The second one can be converted to sql wherase the first can't (tries to compare WatchStatus with int). // The second one can be converted to sql wherase the first can't (tries to compare WatchStatus with int).
private WatchStatus Watching = WatchStatus.Watching; private WatchStatus Watching = WatchStatus.Watching;
private WatchStatus Completed = WatchStatus.Completed; private WatchStatus Completed = WatchStatus.Completed;
private WatchStatus Planned = WatchStatus.Planned;
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
private readonly IRepository<Episode> _episodes;
private readonly IRepository<Movie> _movies; private readonly IRepository<Movie> _movies;
private readonly DbConnection _db; private readonly DbConnection _db;
private readonly SqlVariableContext _context; private readonly SqlVariableContext _context;
static WatchStatusRepository()
{
IRepository<Episode>.OnCreated += async (ep) =>
{
await using AsyncServiceScope scope = CoreModule.Services.CreateAsyncScope();
DatabaseContext db = scope.ServiceProvider.GetRequiredService<DatabaseContext>();
WatchStatusRepository repo = scope.ServiceProvider.GetRequiredService<WatchStatusRepository>();
List<Guid> users = await db.ShowWatchStatus
.IgnoreQueryFilters()
.Where(x => x.ShowId == ep.ShowId && x.Status == WatchStatus.Completed)
.Select(x => x.UserId)
.ToListAsync();
foreach (Guid userId in users)
await repo._SetShowStatus(ep.ShowId, userId, WatchStatus.Watching, true);
};
}
public WatchStatusRepository(DatabaseContext database, public WatchStatusRepository(DatabaseContext database,
IRepository<Episode> episodes,
IRepository<Movie> movies, IRepository<Movie> movies,
DbConnection db, DbConnection db,
SqlVariableContext context) SqlVariableContext context)
{ {
_database = database; _database = database;
_episodes = episodes;
_movies = movies; _movies = movies;
_db = db; _db = db;
_context = context; _context = context;
@ -260,39 +276,70 @@ public class WatchStatusRepository : IWatchStatusRepository
} }
/// <inheritdoc /> /// <inheritdoc />
public async Task<ShowWatchStatus?> SetShowStatus( public Task<ShowWatchStatus?> SetShowStatus(
Guid showId, Guid showId,
Guid userId, Guid userId,
WatchStatus status) WatchStatus status
) => _SetShowStatus(showId, userId, status);
private async Task<ShowWatchStatus?> _SetShowStatus(
Guid showId,
Guid userId,
WatchStatus status,
bool newEpisode = false)
{ {
int unseenEpisodeCount = await _database.Episodes int unseenEpisodeCount = status != WatchStatus.Completed
.Where(x => x.ShowId == showId) ? await _database.Episodes
.Where(x => x.WatchStatus!.Status != WatchStatus.Completed) .Where(x => x.ShowId == showId)
.CountAsync(); .Where(x => x.Watched!.First(x => x.UserId == userId)!.Status != WatchStatus.Completed)
.CountAsync()
: 0;
if (unseenEpisodeCount == 0) if (unseenEpisodeCount == 0)
status = WatchStatus.Completed; status = WatchStatus.Completed;
Episode? cursor = null; EpisodeWatchStatus? cursorWatchStatus = null;
Guid? nextEpisodeId = null; Guid? nextEpisodeId = null;
if (status == WatchStatus.Watching) if (status == WatchStatus.Watching)
{ {
cursor = await _episodes.GetOrDefault( var cursor = await _database.Episodes
new Filter<Episode>.Lambda( .IgnoreQueryFilters()
x => x.ShowId == showId .Where(x => x.ShowId == showId)
&& (x.WatchStatus!.Status == WatchStatus.Completed .OrderByDescending(x => x.AbsoluteNumber)
|| x.WatchStatus.Status == WatchStatus.Watching) .OrderByDescending(x => x.SeasonNumber)
), .OrderByDescending(x => x.EpisodeNumber)
new Include<Episode>(nameof(Episode.WatchStatus)), .Select(x => new { x.Id, Status = x.Watched!.First(x => x.UserId == userId) })
reverse: true .FirstOrDefaultAsync(x => x.Status.Status == WatchStatus.Completed || x.Status.Status == WatchStatus.Watching);
); cursorWatchStatus = cursor?.Status;
nextEpisodeId = cursor?.WatchStatus?.Status == WatchStatus.Watching nextEpisodeId = cursor?.Status.Status == WatchStatus.Watching
? cursor.Id ? cursor.Id
: ((await _episodes.GetOrDefault( : await _database.Episodes
new Filter<Episode>.Lambda( .IgnoreQueryFilters()
x => x.ShowId == showId && x.WatchStatus!.Status != WatchStatus.Completed .Where(x => x.ShowId == showId)
), .OrderByDescending(x => x.AbsoluteNumber)
afterId: cursor?.Id .OrderByDescending(x => x.SeasonNumber)
))?.Id); .OrderByDescending(x => x.EpisodeNumber)
.Select(x => new { x.Id, Status = x.Watched!.FirstOrDefault(x => x.UserId == userId) })
.Where(x => x.Status == null || x.Status.Status != WatchStatus.Completed)
.Select(x => x.Id)
.FirstOrDefaultAsync();
}
else if (status == WatchStatus.Completed)
{
List<Guid> episodes = await _database.Episodes
.Where(x => x.ShowId == showId)
.Select(x => x.Id)
.ToListAsync();
await _database.EpisodeWatchStatus
.UpsertRange(episodes.Select(episodeId => new EpisodeWatchStatus
{
UserId = userId,
EpisodeId = episodeId,
Status = WatchStatus.Completed,
AddedDate = DateTime.UtcNow,
PlayedDate = DateTime.UtcNow
}))
.UpdateIf(x => x.Status == Watching || x.Status == Planned)
.RunAsync();
} }
ShowWatchStatus ret = new() ShowWatchStatus ret = new()
@ -302,17 +349,17 @@ public class WatchStatusRepository : IWatchStatusRepository
Status = status, Status = status,
AddedDate = DateTime.UtcNow, AddedDate = DateTime.UtcNow,
NextEpisodeId = nextEpisodeId, NextEpisodeId = nextEpisodeId,
WatchedTime = cursor?.WatchStatus?.Status == WatchStatus.Watching WatchedTime = cursorWatchStatus?.Status == WatchStatus.Watching
? cursor.WatchStatus.WatchedTime ? cursorWatchStatus.WatchedTime
: null, : null,
WatchedPercent = cursor?.WatchStatus?.Status == WatchStatus.Watching WatchedPercent = cursorWatchStatus?.Status == WatchStatus.Watching
? cursor.WatchStatus.WatchedPercent ? cursorWatchStatus.WatchedPercent
: null, : null,
UnseenEpisodesCount = unseenEpisodeCount, UnseenEpisodesCount = unseenEpisodeCount,
PlayedDate = status == WatchStatus.Completed ? DateTime.UtcNow : null, PlayedDate = status == WatchStatus.Completed ? DateTime.UtcNow : null,
}; };
await _database.ShowWatchStatus.Upsert(ret) await _database.ShowWatchStatus.Upsert(ret)
.UpdateIf(x => status != Watching || x.Status != Completed) .UpdateIf(x => status != Watching || x.Status != Completed || newEpisode)
.RunAsync(); .RunAsync();
return ret; return ret;
} }
@ -344,7 +391,7 @@ public class WatchStatusRepository : IWatchStatusRepository
WatchStatus status, WatchStatus status,
int? watchedTime) int? watchedTime)
{ {
Episode episode = await _episodes.Get(episodeId); Episode episode = await _database.Episodes.FirstAsync(x => x.Id == episodeId);
int? percent = watchedTime != null && episode.Runtime > 0 int? percent = watchedTime != null && episode.Runtime > 0
? (int)Math.Round(watchedTime.Value / (episode.Runtime * 60f) * 100f) ? (int)Math.Round(watchedTime.Value / (episode.Runtime * 60f) * 100f)
: null; : null;