Implemented Subsonic's user rating for tracks, albums and artists, fixes #511

This commit is contained in:
emeric
2024-08-30 19:40:15 +02:00
parent cd0e88d28d
commit 29d0610eb2
30 changed files with 991 additions and 5 deletions
@@ -19,6 +19,7 @@
#include "MediaAnnotation.hpp"
#include <variant>
#include <vector>
#include "core/Service.hpp"
@@ -77,6 +78,37 @@ namespace lms::api::subsonic
return res ? res->getId() : ReleaseId{};
}
struct RatingParameters
{
std::variant<ArtistId, ReleaseId, TrackId, DirectoryId> id;
std::optional<Rating> rating;
};
RatingParameters getRatingParameters(const Wt::Http::ParameterMap& parameters)
{
RatingParameters res;
if (const auto artistId{ getParameterAs<ArtistId>(parameters, "id") })
res.id = *artistId;
else if (const auto releaseId{ getParameterAs<ReleaseId>(parameters, "id") })
res.id = *releaseId;
else if (const auto trackId{ getParameterAs<TrackId>(parameters, "id") })
res.id = *trackId;
else if (const auto directoryId{ getParameterAs<DirectoryId>(parameters, "id") })
res.id = *directoryId;
else
throw RequiredParameterMissingError{ "id" };
const int rating = getMandatoryParameterAs<int>(parameters, "rating"); // The rating between 1 and 5 (inclusive), or 0 to remove the rating
if (rating < 0 || rating > 5)
throw BadParameterGenericError{ "rating must be 0 or in range 1-5" };
if (rating > 0)
res.rating = rating;
return res;
}
} // namespace
Response handleStarRequest(RequestContext& context)
@@ -103,7 +135,7 @@ namespace lms::api::subsonic
Response handleUnstarRequest(RequestContext& context)
{
StarParameters params{ getStarParameters(context.parameters) };
const StarParameters params{ getStarParameters(context.parameters) };
for (const DirectoryId id : params.directoryIds)
{
@@ -123,6 +155,25 @@ namespace lms::api::subsonic
return Response::createOkResponse(context.serverProtocolVersion);
}
Response handleSetRating(RequestContext& context)
{
const RatingParameters params{ getRatingParameters(context.parameters) };
if (const ArtistId * artistId{ std::get_if<ArtistId>(&params.id) })
core::Service<feedback::IFeedbackService>::get()->setRating(context.user->getId(), *artistId, params.rating);
else if (const DirectoryId * directoryId{ std::get_if<DirectoryId>(&params.id) })
{
if (const ReleaseId releaseId{ getReleaseFromDirectory(context.dbSession, *directoryId) }; releaseId.isValid())
core::Service<feedback::IFeedbackService>::get()->setRating(context.user->getId(), releaseId, params.rating);
}
else if (const ReleaseId * releaseId{ std::get_if<ReleaseId>(&params.id) })
core::Service<feedback::IFeedbackService>::get()->setRating(context.user->getId(), *releaseId, params.rating);
else if (const TrackId * trackId{ std::get_if<TrackId>(&params.id) })
core::Service<feedback::IFeedbackService>::get()->setRating(context.user->getId(), *trackId, params.rating);
return Response::createOkResponse(context.serverProtocolVersion);
}
Response handleScrobble(RequestContext& context)
{
const std::vector<TrackId> ids{ getMandatoryMultiParametersAs<TrackId>(context.parameters, "id") };