Fix watch status message payload

This commit is contained in:
Zoe Roux 2024-03-20 19:34:55 +01:00
parent 6937a982d4
commit 1f3a985d3a
No known key found for this signature in database
5 changed files with 107 additions and 40 deletions

View File

@ -47,8 +47,8 @@ public interface IWatchStatusRepository
int? percent int? percent
); );
static event ResourceEventHandler<MovieWatchStatus> OnMovieStatusChangedHandler; static event ResourceEventHandler<WatchStatus<Movie>> OnMovieStatusChangedHandler;
protected static Task OnMovieStatusChanged(MovieWatchStatus obj) => protected static Task OnMovieStatusChanged(WatchStatus<Movie> obj) =>
OnMovieStatusChangedHandler?.Invoke(obj) ?? Task.CompletedTask; OnMovieStatusChangedHandler?.Invoke(obj) ?? Task.CompletedTask;
Task DeleteMovieStatus(Guid movieId, Guid userId); Task DeleteMovieStatus(Guid movieId, Guid userId);
@ -57,8 +57,8 @@ public interface IWatchStatusRepository
Task<ShowWatchStatus?> SetShowStatus(Guid showId, Guid userId, WatchStatus status); Task<ShowWatchStatus?> SetShowStatus(Guid showId, Guid userId, WatchStatus status);
static event ResourceEventHandler<ShowWatchStatus> OnShowStatusChangedHandler; static event ResourceEventHandler<WatchStatus<Show>> OnShowStatusChangedHandler;
protected static Task OnShowStatusChanged(ShowWatchStatus obj) => protected static Task OnShowStatusChanged(WatchStatus<Show> obj) =>
OnShowStatusChangedHandler?.Invoke(obj) ?? Task.CompletedTask; OnShowStatusChangedHandler?.Invoke(obj) ?? Task.CompletedTask;
Task DeleteShowStatus(Guid showId, Guid userId); Task DeleteShowStatus(Guid showId, Guid userId);
@ -75,8 +75,8 @@ public interface IWatchStatusRepository
int? percent int? percent
); );
static event ResourceEventHandler<EpisodeWatchStatus> OnEpisodeStatusChangedHandler; static event ResourceEventHandler<WatchStatus<Episode>> OnEpisodeStatusChangedHandler;
protected static Task OnEpisodeStatusChanged(EpisodeWatchStatus obj) => protected static Task OnEpisodeStatusChanged(WatchStatus<Episode> obj) =>
OnEpisodeStatusChangedHandler?.Invoke(obj) ?? Task.CompletedTask; OnEpisodeStatusChangedHandler?.Invoke(obj) ?? Task.CompletedTask;
Task DeleteEpisodeStatus(Guid episodeId, Guid userId); Task DeleteEpisodeStatus(Guid episodeId, Guid userId);

View File

@ -53,20 +53,11 @@ public enum WatchStatus
Deleted, Deleted,
} }
public interface IWatchStatus
{
/// <summary>
/// Has the user started watching, is it planned?
/// </summary>
public WatchStatus Status { get; set; }
}
/// <summary> /// <summary>
/// Metadata of what an user as started/planned to watch. /// Metadata of what an user as started/planned to watch.
/// </summary> /// </summary>
[SqlFirstColumn(nameof(UserId))] [SqlFirstColumn(nameof(UserId))]
public class MovieWatchStatus : IAddedDate, IWatchStatus public class MovieWatchStatus : IAddedDate
{ {
/// <summary> /// <summary>
/// The ID of the user that started watching this episode. /// The ID of the user that started watching this episode.
@ -121,7 +112,7 @@ public class MovieWatchStatus : IAddedDate, IWatchStatus
} }
[SqlFirstColumn(nameof(UserId))] [SqlFirstColumn(nameof(UserId))]
public class EpisodeWatchStatus : IAddedDate, IWatchStatus public class EpisodeWatchStatus : IAddedDate
{ {
/// <summary> /// <summary>
/// The ID of the user that started watching this episode. /// The ID of the user that started watching this episode.
@ -176,7 +167,7 @@ public class EpisodeWatchStatus : IAddedDate, IWatchStatus
} }
[SqlFirstColumn(nameof(UserId))] [SqlFirstColumn(nameof(UserId))]
public class ShowWatchStatus : IAddedDate, IWatchStatus public class ShowWatchStatus : IAddedDate
{ {
/// <summary> /// <summary>
/// The ID of the user that started watching this episode. /// The ID of the user that started watching this episode.
@ -244,3 +235,45 @@ public class ShowWatchStatus : IAddedDate, IWatchStatus
/// </remarks> /// </remarks>
public int? WatchedPercent { get; set; } public int? WatchedPercent { get; set; }
} }
public class WatchStatus<T> : IAddedDate
{
/// <summary>
/// Has the user started watching, is it planned?
/// </summary>
public required WatchStatus Status { get; set; }
/// <inheritdoc/>
public DateTime AddedDate { get; set; }
/// <summary>
/// The date at which this item was played.
/// </summary>
public DateTime? PlayedDate { get; set; }
/// <summary>
/// Where the player has stopped watching the episode (in seconds).
/// </summary>
/// <remarks>
/// Null if the status is not Watching or if the next episode is not started.
/// </remarks>
public int? WatchedTime { get; set; }
/// <summary>
/// Where the player has stopped watching the episode (in percentage between 0 and 100).
/// </summary>
/// <remarks>
/// Null if the status is not Watching or if the next episode is not started.
/// </remarks>
public int? WatchedPercent { get; set; }
/// <summary>
/// The user that started watching this episode.
/// </summary>
public required User User { get; set; }
/// <summary>
/// The episode/show/movie whose status changed
/// </summary>
public required T Resource { get; set; }
}

View File

@ -36,6 +36,9 @@ namespace Kyoo.Core.Controllers;
public class WatchStatusRepository( public class WatchStatusRepository(
DatabaseContext database, DatabaseContext database,
IRepository<Movie> movies, IRepository<Movie> movies,
IRepository<Show> shows,
IRepository<Episode> episodes,
IRepository<User> users,
DbConnection db, DbConnection db,
SqlVariableContext context SqlVariableContext context
) : IWatchStatusRepository ) : IWatchStatusRepository
@ -265,7 +268,18 @@ public class WatchStatusRepository(
.MovieWatchStatus.Upsert(ret) .MovieWatchStatus.Upsert(ret)
.UpdateIf(x => status != Watching || x.Status != Completed) .UpdateIf(x => status != Watching || x.Status != Completed)
.RunAsync(); .RunAsync();
await IWatchStatusRepository.OnMovieStatusChanged(ret); await IWatchStatusRepository.OnMovieStatusChanged(
new()
{
User = await users.Get(ret.UserId),
Resource = await movies.Get(ret.MovieId),
Status = ret.Status,
WatchedTime = ret.WatchedTime,
WatchedPercent = ret.WatchedPercent,
AddedDate = ret.AddedDate,
PlayedDate = ret.PlayedDate,
}
);
return ret; return ret;
} }
@ -278,8 +292,8 @@ public class WatchStatusRepository(
await IWatchStatusRepository.OnMovieStatusChanged( await IWatchStatusRepository.OnMovieStatusChanged(
new() new()
{ {
UserId = userId, User = await users.Get(userId),
MovieId = movieId, Resource = await movies.Get(movieId),
AddedDate = DateTime.UtcNow, AddedDate = DateTime.UtcNow,
Status = WatchStatus.Deleted, Status = WatchStatus.Deleted,
} }
@ -413,7 +427,18 @@ public class WatchStatusRepository(
.ShowWatchStatus.Upsert(ret) .ShowWatchStatus.Upsert(ret)
.UpdateIf(x => status != Watching || x.Status != Completed || newEpisode) .UpdateIf(x => status != Watching || x.Status != Completed || newEpisode)
.RunAsync(); .RunAsync();
await IWatchStatusRepository.OnShowStatusChanged(ret); await IWatchStatusRepository.OnShowStatusChanged(
new()
{
User = await users.Get(ret.UserId),
Resource = await shows.Get(ret.ShowId),
Status = ret.Status,
WatchedTime = ret.WatchedTime,
WatchedPercent = ret.WatchedPercent,
AddedDate = ret.AddedDate,
PlayedDate = ret.PlayedDate,
}
);
return ret; return ret;
} }
@ -430,8 +455,8 @@ public class WatchStatusRepository(
await IWatchStatusRepository.OnShowStatusChanged( await IWatchStatusRepository.OnShowStatusChanged(
new() new()
{ {
UserId = userId, User = await users.Get(userId),
ShowId = showId, Resource = await shows.Get(showId),
AddedDate = DateTime.UtcNow, AddedDate = DateTime.UtcNow,
Status = WatchStatus.Deleted, Status = WatchStatus.Deleted,
} }
@ -495,7 +520,18 @@ public class WatchStatusRepository(
.EpisodeWatchStatus.Upsert(ret) .EpisodeWatchStatus.Upsert(ret)
.UpdateIf(x => status != Watching || x.Status != Completed) .UpdateIf(x => status != Watching || x.Status != Completed)
.RunAsync(); .RunAsync();
await IWatchStatusRepository.OnEpisodeStatusChanged(ret); await IWatchStatusRepository.OnEpisodeStatusChanged(
new()
{
User = await users.Get(ret.UserId),
Resource = await episodes.Get(ret.EpisodeId),
Status = ret.Status,
WatchedTime = ret.WatchedTime,
WatchedPercent = ret.WatchedPercent,
AddedDate = ret.AddedDate,
PlayedDate = ret.PlayedDate,
}
);
await SetShowStatus(episode.ShowId, userId, WatchStatus.Watching); await SetShowStatus(episode.ShowId, userId, WatchStatus.Watching);
return ret; return ret;
} }
@ -509,8 +545,8 @@ public class WatchStatusRepository(
await IWatchStatusRepository.OnEpisodeStatusChanged( await IWatchStatusRepository.OnEpisodeStatusChanged(
new() new()
{ {
UserId = userId, User = await users.Get(userId),
EpisodeId = episodeId, Resource = await episodes.Get(episodeId),
AddedDate = DateTime.UtcNow, AddedDate = DateTime.UtcNow,
Status = WatchStatus.Deleted, Status = WatchStatus.Deleted,
} }

View File

@ -21,11 +21,11 @@ using System.Text.Json;
namespace Kyoo.RabbitMq; namespace Kyoo.RabbitMq;
public class Message public class Message<T>
{ {
public string Action { get; set; } public string Action { get; set; }
public string Type { get; set; } public string Type { get; set; }
public object Value { get; set; } public T Value { get; set; }
public string AsRoutingKey() public string AsRoutingKey()
{ {

View File

@ -40,14 +40,11 @@ public class RabbitProducer
_ListenResourceEvents<User>("events.resource"); _ListenResourceEvents<User>("events.resource");
_channel.ExchangeDeclare("events.watched", ExchangeType.Topic); _channel.ExchangeDeclare("events.watched", ExchangeType.Topic);
IWatchStatusRepository.OnMovieStatusChangedHandler += _PublishWatchStatus<MovieWatchStatus>( IWatchStatusRepository.OnMovieStatusChangedHandler += _PublishWatchStatus<Movie>("movie");
"movie" IWatchStatusRepository.OnShowStatusChangedHandler += _PublishWatchStatus<Show>("show");
IWatchStatusRepository.OnEpisodeStatusChangedHandler += _PublishWatchStatus<Episode>(
"episode"
); );
IWatchStatusRepository.OnShowStatusChangedHandler += _PublishWatchStatus<ShowWatchStatus>(
"show"
);
IWatchStatusRepository.OnEpisodeStatusChangedHandler +=
_PublishWatchStatus<EpisodeWatchStatus>("episode");
} }
private void _ListenResourceEvents<T>(string exchange) private void _ListenResourceEvents<T>(string exchange)
@ -69,7 +66,7 @@ public class RabbitProducer
{ {
return (T resource) => return (T resource) =>
{ {
Message message = Message<T> message =
new() new()
{ {
Action = action, Action = action,
@ -85,12 +82,13 @@ public class RabbitProducer
}; };
} }
private IWatchStatusRepository.ResourceEventHandler<T> _PublishWatchStatus<T>(string resource) private IWatchStatusRepository.ResourceEventHandler<WatchStatus<T>> _PublishWatchStatus<T>(
where T : IWatchStatus string resource
)
{ {
return (status) => return (status) =>
{ {
Message message = Message<WatchStatus<T>> message =
new() new()
{ {
Type = resource, Type = resource,