Add watch apis

This commit is contained in:
Zoe Roux 2023-11-13 22:51:45 +01:00
parent 6567e78c8c
commit 48f77c2f7a
4 changed files with 166 additions and 2 deletions

View File

@ -95,6 +95,7 @@ public class WatchStatusRepository : IWatchStatusRepository
MovieId = movieId,
Status = status,
WatchedTime = watchedTime,
AddedDate = DateTime.UtcNow
};
await _database.MovieWatchStatus.Upsert(ret)
.UpdateIf(x => !(status == WatchStatus.Watching && x.Status == WatchStatus.Completed))
@ -149,6 +150,7 @@ public class WatchStatusRepository : IWatchStatusRepository
)
: null,
UnseenEpisodesCount = unseenEpisodeCount,
AddedDate = DateTime.UtcNow
};
await _database.ShowWatchStatus.Upsert(ret)
.UpdateIf(x => !(status == WatchStatus.Watching && x.Status == WatchStatus.Completed))
@ -211,6 +213,7 @@ public class WatchStatusRepository : IWatchStatusRepository
Status = status,
WatchedTime = watchedTime,
WatchedPercent = percent,
AddedDate = DateTime.UtcNow
};
await _database.EpisodeWatchStatus.Upsert(ret)
.UpdateIf(x => !(status == WatchStatus.Watching && x.Status == WatchStatus.Completed))

View File

@ -22,6 +22,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Abstractions.Models.Utils;
using Kyoo.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using static Kyoo.Abstractions.Models.Utils.Constants;
@ -108,5 +109,86 @@ namespace Kyoo.Core.Api
? NotFound()
: NoContent();
}
/// <summary>
/// Get watch status
/// </summary>
/// <remarks>
/// Get when an item has been wathed and if it was watched.
/// </remarks>
/// <param name="identifier">The ID or slug of the <see cref="Episode"/>.</param>
/// <returns>The status.</returns>
/// <response code="204">This episode does not have a specific status.</response>
/// <response code="404">No episode with the given ID or slug could be found.</response>
[HttpGet("{identifier:id}/watchStatus")]
[HttpGet("{identifier:id}/watchStatus", Order = AlternativeRoute)]
[UserOnly]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<EpisodeWatchStatus?> GetWatchStatus(Identifier identifier)
{
return await _libraryManager.WatchStatus.GetEpisodeStatus(
identifier.IsSame<Episode>(),
User.GetId()!.Value
);
}
/// <summary>
/// Set watch status
/// </summary>
/// <remarks>
/// Set when an item has been wathed and if it was watched.
/// </remarks>
/// <param name="identifier">The ID or slug of the <see cref="Episode"/>.</param>
/// <param name="status">The new watch status.</param>
/// <param name="watchedTime">Where the user stopped watching.</param>
/// <returns>The newly set status.</returns>
/// <response code="200">The status has been set</response>
/// <response code="204">The status was not considered impactfull enough to be saved (less then 5% of watched for example).</response>
/// <response code="404">No episode with the given ID or slug could be found.</response>
[HttpPost("{identifier:id}/watchStatus")]
[HttpPost("{identifier:id}/watchStatus", Order = AlternativeRoute)]
[UserOnly]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<EpisodeWatchStatus?> SetWatchStatus(Identifier identifier, WatchStatus status, int? watchedTime)
{
int id = await identifier.Match(
id => Task.FromResult(id),
async slug => (await _libraryManager.Episodes.Get(slug)).Id
);
return await _libraryManager.WatchStatus.SetEpisodeStatus(
id,
User.GetId()!.Value,
status,
watchedTime
);
}
/// <summary>
/// Delete watch status
/// </summary>
/// <remarks>
/// Delete watch status (to rewatch for example).
/// </remarks>
/// <param name="identifier">The ID or slug of the <see cref="Episode"/>.</param>
/// <returns>The newly set status.</returns>
/// <response code="204">The status has been deleted.</response>
/// <response code="404">No episode with the given ID or slug could be found.</response>
[HttpDelete("{identifier:id}/watchStatus")]
[HttpDelete("{identifier:id}/watchStatus", Order = AlternativeRoute)]
[UserOnly]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task DeleteWatchStatus(Identifier identifier)
{
await _libraryManager.WatchStatus.DeleteEpisodeStatus(
identifier.IsSame<Episode>(),
User.GetId()!.Value
);
}
}
}

View File

@ -24,6 +24,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Abstractions.Models.Utils;
using Kyoo.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using static Kyoo.Abstractions.Models.Utils.Constants;
@ -226,5 +227,84 @@ namespace Kyoo.Core.Api
return NotFound();
return Page(resources, pagination.Limit);
}
/// <summary>
/// Get watch status
/// </summary>
/// <remarks>
/// Get when an item has been wathed and if it was watched.
/// </remarks>
/// <param name="identifier">The ID or slug of the <see cref="Show"/>.</param>
/// <returns>The status.</returns>
/// <response code="204">This show does not have a specific status.</response>
/// <response code="404">No show with the given ID or slug could be found.</response>
[HttpGet("{identifier:id}/watchStatus")]
[HttpGet("{identifier:id}/watchStatus", Order = AlternativeRoute)]
[UserOnly]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ShowWatchStatus?> GetWatchStatus(Identifier identifier)
{
return await _libraryManager.WatchStatus.GetShowStatus(
identifier.IsSame<Show>(),
User.GetId()!.Value
);
}
/// <summary>
/// Set watch status
/// </summary>
/// <remarks>
/// Set when an item has been wathed and if it was watched.
/// </remarks>
/// <param name="identifier">The ID or slug of the <see cref="Show"/>.</param>
/// <param name="status">The new watch status.</param>
/// <returns>The newly set status.</returns>
/// <response code="200">The status has been set</response>
/// <response code="204">The status was not considered impactfull enough to be saved (less then 5% of watched for example).</response>
/// <response code="404">No movie with the given ID or slug could be found.</response>
[HttpPost("{identifier:id}/watchStatus")]
[HttpPost("{identifier:id}/watchStatus", Order = AlternativeRoute)]
[UserOnly]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ShowWatchStatus?> SetWatchStatus(Identifier identifier, WatchStatus status)
{
int id = await identifier.Match(
id => Task.FromResult(id),
async slug => (await _libraryManager.Shows.Get(slug)).Id
);
return await _libraryManager.WatchStatus.SetShowStatus(
id,
User.GetId()!.Value,
status
);
}
/// <summary>
/// Delete watch status
/// </summary>
/// <remarks>
/// Delete watch status (to rewatch for example).
/// </remarks>
/// <param name="identifier">The ID or slug of the <see cref="Show"/>.</param>
/// <returns>The newly set status.</returns>
/// <response code="204">The status has been deleted.</response>
/// <response code="404">No show with the given ID or slug could be found.</response>
[HttpDelete("{identifier:id}/watchStatus")]
[HttpDelete("{identifier:id}/watchStatus", Order = AlternativeRoute)]
[UserOnly]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task DeleteWatchStatus(Identifier identifier)
{
await _libraryManager.WatchStatus.DeleteShowStatus(
identifier.IsSame<Show>(),
User.GetId()!.Value
);
}
}
}

View File

@ -4,7 +4,7 @@ services:
back:
image: zoriya/kyoo_back:edge
restart: unless-stopped
cpus: 0.8
cpus: 1.5
env_file:
- ./.env
depends_on:
@ -36,7 +36,6 @@ services:
transcoder:
image: zoriya/kyoo_transcoder:edge
restart: unless-stopped
cpus: 0.8
env_file:
- ./.env
volumes: