Unify ChapterRating with Rating

This commit is contained in:
Amelia 2025-04-26 20:20:14 +02:00
parent a9e2937651
commit f29c63c6c4
No known key found for this signature in database
GPG key ID: D6D0ECE365407EAA
34 changed files with 266 additions and 679 deletions

View file

@ -28,16 +28,13 @@ public class ChapterController : BaseApiController
private readonly ILocalizationService _localizationService;
private readonly IEventHub _eventHub;
private readonly ILogger<ChapterController> _logger;
private readonly IRatingService _ratingService;
public ChapterController(IUnitOfWork unitOfWork, ILocalizationService localizationService, IEventHub eventHub, ILogger<ChapterController> logger,
IRatingService ratingService)
public ChapterController(IUnitOfWork unitOfWork, ILocalizationService localizationService, IEventHub eventHub, ILogger<ChapterController> logger)
{
_unitOfWork = unitOfWork;
_localizationService = localizationService;
_eventHub = eventHub;
_logger = logger;
_ratingService = ratingService;
}
/// <summary>
@ -406,15 +403,4 @@ public class ChapterController : BaseApiController
return await _unitOfWork.UserRepository.GetUserRatingDtosForChapterAsync(chapterId, User.GetUserId());
}
[HttpPost("update-rating")]
public async Task<ActionResult> UpdateRating(UpdateChapterRatingDto dto)
{
if (await _ratingService.UpdateChapterRating(User.GetUserId(), dto))
{
return Ok();
}
return BadRequest(await _localizationService.Translate(User.GetUserId(), "generic-error"));
}
}

View file

@ -6,6 +6,7 @@ using API.Constants;
using API.Data;
using API.DTOs;
using API.Extensions;
using API.Services;
using API.Services.Plus;
using EasyCaching.Core;
using Microsoft.AspNetCore.Mvc;
@ -21,31 +22,45 @@ namespace API.Controllers;
public class RatingController : BaseApiController
{
private readonly IUnitOfWork _unitOfWork;
private readonly IRatingService _ratingService;
private readonly ILocalizationService _localizationService;
public RatingController(IUnitOfWork unitOfWork)
public RatingController(IUnitOfWork unitOfWork, IRatingService ratingService, ILocalizationService localizationService)
{
_unitOfWork = unitOfWork;
_ratingService = ratingService;
_localizationService = localizationService;
}
[HttpPost]
public async Task<ActionResult> UpdateRating(UpdateRatingDto updateRating)
{
if (await _ratingService.UpdateRating(User.GetUserId(), updateRating))
{
return Ok();
}
return BadRequest(await _localizationService.Translate(User.GetUserId(), "generic-error"));
}
[HttpGet("overall")]
public async Task<ActionResult<RatingDto>> GetOverallRating(int seriesId)
public async Task<ActionResult<RatingDto>> GetOverallRating(int seriesId, [FromQuery] int? chapterId)
{
int average;
if (chapterId != null)
{
average = await _unitOfWork.ChapterRepository.GetAverageUserRating(chapterId.Value, User.GetUserId());
}
else
{
average = await _unitOfWork.SeriesRepository.GetAverageUserRating(seriesId, User.GetUserId());
}
return Ok(new RatingDto()
{
Provider = ScrobbleProvider.Kavita,
AverageScore = await _unitOfWork.SeriesRepository.GetAverageUserRating(seriesId, User.GetUserId()),
FavoriteCount = 0
});
}
[HttpGet("overall/chapter")]
public async Task<ActionResult<RatingDto>> GetOverallChapterRating([FromQuery] int chapterId)
{
return Ok(new RatingDto
{
Provider = ScrobbleProvider.Kavita,
AverageScore = await _unitOfWork.ChapterRepository.GetAverageUserRating(chapterId, User.GetUserId()),
AverageScore = average,
FavoriteCount = 0,
});
}

View file

@ -1,4 +1,5 @@
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using API.Data;
using API.Data.Repositories;
@ -29,9 +30,24 @@ public class ReviewController : BaseApiController
_scrobblingService = scrobblingService;
}
/// <summary>
/// Get all reviews for the series, or chapter
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<IList<UserReviewDto>> GetReviews([FromQuery] int seriesId, [FromQuery] int? chapterId)
{
if (chapterId == null)
{
return await _unitOfWork.UserRepository.GetUserRatingDtosForSeriesAsync(seriesId, User.GetUserId());
}
return await _unitOfWork.UserRepository.GetUserRatingDtosForChapterAsync(chapterId.Value, User.GetUserId());
}
/// <summary>
/// Updates the review for a given series
/// Updates the review for a given series, or chapter
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
@ -41,7 +57,7 @@ public class ReviewController : BaseApiController
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(User.GetUserId(), AppUserIncludes.Ratings);
if (user == null) return Unauthorized();
var ratingBuilder = new RatingBuilder(user.Ratings.FirstOrDefault(r => r.SeriesId == dto.SeriesId));
var ratingBuilder = new RatingBuilder(await _unitOfWork.UserRepository.GetUserRatingAsync(dto.SeriesId, user.Id, dto.ChapterId));
var rating = ratingBuilder
.WithBody(dto.Body)
@ -64,78 +80,18 @@ public class ReviewController : BaseApiController
return Ok(_mapper.Map<UserReviewDto>(rating));
}
/// <summary>
/// Updates the review for a given series
/// </summary>
/// <param name="dto"></param>
/// <param name="chapterId"></param>
/// <returns></returns>
[HttpPost("chapter/{chapterId}")]
public async Task<ActionResult<UserReviewDto>> UpdateChapterReview(int chapterId, UpdateUserReviewDto dto)
{
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(User.GetUserId(), AppUserIncludes.ChapterRatings);
if (user == null) return Unauthorized();
var chapter = await _unitOfWork.ChapterRepository.GetChapterAsync(chapterId, ChapterIncludes.None);
if (chapter == null) return BadRequest();
var builder = new ChapterRatingBuilder(user.ChapterRatings.FirstOrDefault(r => r.SeriesId == dto.SeriesId));
var rating = builder
.WithSeriesId(dto.SeriesId)
.WithVolumeId(chapter.VolumeId)
.WithChapterId(chapter.Id)
.WithRating(dto.Rating)
.WithReview(dto.Body)
.WithProvider(ScrobbleProvider.Kavita)
.Build();
if (rating.Id == 0)
{
user.ChapterRatings.Add(rating);
}
_unitOfWork.UserRepository.Update(user);
await _unitOfWork.CommitAsync();
// Do I need this?
//BackgroundJob.Enqueue(() =>
// _scrobblingService.ScrobbleReviewUpdate(user.Id, dto.SeriesId, string.Empty, dto.Body));
return Ok(_mapper.Map<UserReviewDto>(rating));
}
/// <summary>
/// Deletes the user's review for the given series
/// Deletes the user's review for the given series, or chapter
/// </summary>
/// <returns></returns>
[HttpDelete]
public async Task<ActionResult> DeleteReview(int seriesId)
public async Task<ActionResult> DeleteReview([FromQuery] int seriesId, [FromQuery] int? chapterId)
{
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(User.GetUserId(), AppUserIncludes.Ratings);
if (user == null) return Unauthorized();
user.Ratings = user.Ratings.Where(r => r.SeriesId != seriesId).ToList();
_unitOfWork.UserRepository.Update(user);
await _unitOfWork.CommitAsync();
return Ok();
}
/// <summary>
/// Deletes the user's review for a given chapter
/// </summary>
/// <param name="chapterId"></param>
/// <returns></returns>
[HttpDelete("chapter/{chapterId}")]
public async Task<IActionResult> DeleteChapterReview(int chapterId)
{
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(User.GetUserId(), AppUserIncludes.ChapterRatings);
if (user == null) return Unauthorized();
user.ChapterRatings = user.ChapterRatings.Where(c => c.ChapterId != chapterId).ToList();
user.Ratings = user.Ratings.Where(r => !(r.SeriesId == seriesId && r.ChapterId == chapterId)).ToList();
_unitOfWork.UserRepository.Update(user);

View file

@ -191,21 +191,6 @@ public class SeriesController : BaseApiController
return Ok(await _unitOfWork.ChapterRepository.GetChapterMetadataDtoAsync(chapterId));
}
/// <summary>
/// Update the user rating for the given series
/// </summary>
/// <param name="updateSeriesRatingDto"></param>
/// <returns></returns>
[HttpPost("update-rating")]
public async Task<ActionResult> UpdateSeriesRating(UpdateSeriesRatingDto updateSeriesRatingDto)
{
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername(), AppUserIncludes.Ratings);
if (!await _seriesService.UpdateRating(user!, updateSeriesRatingDto))
return BadRequest(await _localizationService.Translate(User.GetUserId(), "generic-error"));
return Ok();
}
/// <summary>
/// Updates the Series
/// </summary>

View file

@ -83,15 +83,4 @@ public class VolumeController : BaseApiController
return Ok(true);
}
/// <summary>
/// Returns all reviews related to this volume, that is, the union of reviews of this volumes chapters
/// </summary>
/// <param name="volumeId"></param>
/// <returns></returns>
[HttpGet("review")]
public async Task<IList<UserReviewDto>> VolumeReviews([FromQuery] int volumeId)
{
return await _unitOfWork.UserRepository.GetUserRatingDtosForVolumeAsync(volumeId, User.GetUserId());
}
}