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
@@ -23,6 +23,9 @@
#include "core/ILogger.hpp"
#include "database/Artist.hpp"
#include "database/Db.hpp"
#include "database/RatedArtist.hpp"
#include "database/RatedRelease.hpp"
#include "database/RatedTrack.hpp"
#include "database/Release.hpp"
#include "database/Session.hpp"
#include "database/StarredArtist.hpp"
@@ -108,6 +111,16 @@ namespace lms::feedback
return Artist::findIds(session, searchParams);
}
void FeedbackService::setRating(db::UserId userId, db::ArtistId artistId, std::optional<db::Rating> rating)
{
setRating<Artist, ArtistId, RatedArtist>(userId, artistId, rating);
}
std::optional<db::Rating> FeedbackService::getRating(db::UserId userId, db::ArtistId artistId)
{
return getRating<Artist, ArtistId, RatedArtist>(userId, artistId);
}
void FeedbackService::star(UserId userId, ReleaseId releaseId)
{
star<Release, ReleaseId, StarredRelease>(userId, releaseId);
@@ -148,6 +161,16 @@ namespace lms::feedback
return Release::findIds(session, searchParams);
}
void FeedbackService::setRating(db::UserId userId, db::ReleaseId releaseId, std::optional<db::Rating> rating)
{
setRating<Release, ReleaseId, RatedRelease>(userId, releaseId, rating);
}
std::optional<db::Rating> FeedbackService::getRating(db::UserId userId, db::ReleaseId releaseId)
{
return getRating<Release, ReleaseId, RatedRelease>(userId, releaseId);
}
void FeedbackService::star(UserId userId, TrackId trackId)
{
star<Track, TrackId, StarredTrack>(userId, trackId);
@@ -187,4 +210,14 @@ namespace lms::feedback
return Track::findIds(session, searchParams);
}
void FeedbackService::setRating(db::UserId userId, db::TrackId trackId, std::optional<db::Rating> rating)
{
setRating<db::Track, db::TrackId, db::RatedTrack>(userId, trackId, rating);
}
std::optional<db::Rating> FeedbackService::getRating(db::UserId userId, db::TrackId trackId)
{
return getRating<db::Track, db::TrackId, db::RatedTrack>(userId, trackId);
}
} // namespace lms::feedback
@@ -49,18 +49,28 @@ namespace lms::feedback
Wt::WDateTime getStarredDateTime(db::UserId userId, db::ArtistId artistId) override;
ArtistContainer findStarredArtists(const ArtistFindParameters& params) override;
virtual void setRating(db::UserId userId, db::ArtistId artistId, std::optional<db::Rating> rating) override;
virtual std::optional<db::Rating> getRating(db::UserId userId, db::ArtistId artistId) override;
void star(db::UserId userId, db::ReleaseId releaseId) override;
void unstar(db::UserId userId, db::ReleaseId releaseId) override;
bool isStarred(db::UserId userId, db::ReleaseId releasedId) override;
Wt::WDateTime getStarredDateTime(db::UserId userId, db::ReleaseId releasedId) override;
ReleaseContainer findStarredReleases(const FindParameters& params) override;
virtual void setRating(db::UserId userId, db::ReleaseId releaseId, std::optional<db::Rating> rating) override;
virtual std::optional<db::Rating> getRating(db::UserId userId, db::ReleaseId releaseId) override;
void star(db::UserId userId, db::TrackId trackId) override;
void unstar(db::UserId userId, db::TrackId trackId) override;
bool isStarred(db::UserId userId, db::TrackId trackId) override;
Wt::WDateTime getStarredDateTime(db::UserId userId, db::TrackId trackId) override;
TrackContainer findStarredTracks(const FindParameters& params) override;
void setRating(db::UserId userId, db::TrackId trackId, std::optional<db::Rating> rating) override;
std::optional<db::Rating> getRating(db::UserId userId, db::TrackId trackId) override;
private:
std::optional<db::FeedbackBackend> getUserFeedbackBackend(db::UserId userId);
template<typename ObjType, typename ObjIdType, typename StarredObjType>
@@ -72,6 +82,12 @@ namespace lms::feedback
template<typename ObjType, typename ObjIdType, typename StarredObjType>
Wt::WDateTime getStarredDateTime(db::UserId userId, ObjIdType id);
template<typename ObjType, typename ObjIdType, typename RatedObjType>
void setRating(db::UserId userId, ObjIdType objectId, std::optional<db::Rating> rating);
template<typename ObjType, typename ObjIdType, typename RatedObjType>
std::optional<db::Rating> getRating(db::UserId userId, ObjIdType objectId);
db::Db& _db;
std::unordered_map<db::FeedbackBackend, std::unique_ptr<IFeedbackBackend>> _backends;
};
@@ -102,4 +102,46 @@ namespace lms::feedback
return {};
}
template<typename ObjType, typename ObjIdType, typename RatedObjType>
void FeedbackService::setRating(db::UserId userId, ObjIdType objectId, std::optional<db::Rating> rating)
{
Session& session{ _db.getTLSSession() };
auto transaction{ session.createWriteTransaction() };
typename RatedObjType::pointer ratedObject{ RatedObjType::find(session, objectId, userId) };
if (rating)
{
if (!ratedObject)
{
typename ObjType::pointer obj{ ObjType::find(session, objectId) };
const User::pointer user{ User::find(session, userId) };
if (!obj || !user)
return;
ratedObject = session.create<RatedObjType>(obj, user);
}
ratedObject.modify()->setRating(*rating);
}
else
{
if (ratedObject)
ratedObject.remove();
}
}
template<typename ObjType, typename ObjIdType, typename RatedObjType>
std::optional<db::Rating> FeedbackService::getRating(db::UserId userId, ObjIdType objectId)
{
Session& session{ _db.getTLSSession() };
auto transaction{ session.createReadTransaction() };
const typename RatedObjType::pointer ratedObj{ RatedObjType::find(session, objectId, userId) };
if (!ratedObj)
return std::nullopt;
return ratedObj->getRating();
}
} // namespace lms::feedback
@@ -109,6 +109,9 @@ namespace lms::feedback
virtual Wt::WDateTime getStarredDateTime(db::UserId userId, db::ArtistId artistId) = 0;
virtual ArtistContainer findStarredArtists(const ArtistFindParameters& params) = 0;
virtual void setRating(db::UserId userId, db::ArtistId artistId, std::optional<db::Rating> rating) = 0;
virtual std::optional<db::Rating> getRating(db::UserId userId, db::ArtistId artistId) = 0;
// Releases
virtual void star(db::UserId userId, db::ReleaseId releaseId) = 0;
virtual void unstar(db::UserId userId, db::ReleaseId releaseId) = 0;
@@ -116,12 +119,18 @@ namespace lms::feedback
virtual Wt::WDateTime getStarredDateTime(db::UserId userId, db::ReleaseId artistId) = 0;
virtual ReleaseContainer findStarredReleases(const FindParameters& params) = 0;
virtual void setRating(db::UserId userId, db::ReleaseId releaseId, std::optional<db::Rating> rating) = 0;
virtual std::optional<db::Rating> getRating(db::UserId userId, db::ReleaseId releaseId) = 0;
// Tracks
virtual void star(db::UserId userId, db::TrackId trackId) = 0;
virtual void unstar(db::UserId userId, db::TrackId trackId) = 0;
virtual bool isStarred(db::UserId userId, db::TrackId artistId) = 0;
virtual Wt::WDateTime getStarredDateTime(db::UserId userId, db::TrackId artistId) = 0;
virtual TrackContainer findStarredTracks(const FindParameters& params) = 0;
virtual void setRating(db::UserId userId, db::TrackId trackId, std::optional<db::Rating> rating) = 0;
virtual std::optional<db::Rating> getRating(db::UserId userId, db::TrackId trackId) = 0;
};
std::unique_ptr<IFeedbackService> createFeedbackService(boost::asio::io_service& ioService, db::Db& db);