Subsonic API: reported correct starred date/time
This commit is contained in:
@@ -39,8 +39,7 @@ namespace Scrobbling
|
|||||||
{
|
{
|
||||||
using namespace Database;
|
using namespace Database;
|
||||||
|
|
||||||
std::unique_ptr<IScrobblingService>
|
std::unique_ptr<IScrobblingService> createScrobblingService(boost::asio::io_context& ioContext, Db& db)
|
||||||
createScrobblingService(boost::asio::io_context& ioContext, Db& db)
|
|
||||||
{
|
{
|
||||||
return std::make_unique<ScrobblingService>(ioContext, db);
|
return std::make_unique<ScrobblingService>(ioContext, db);
|
||||||
}
|
}
|
||||||
@@ -59,29 +58,25 @@ namespace Scrobbling
|
|||||||
LMS_LOG(SCROBBLING, INFO) << "Service stopped!";
|
LMS_LOG(SCROBBLING, INFO) << "Service stopped!";
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ScrobblingService::listenStarted(const Listen& listen)
|
||||||
ScrobblingService::listenStarted(const Listen& listen)
|
|
||||||
{
|
{
|
||||||
if (std::optional<Scrobbler> scrobbler{ getUserScrobbler(listen.userId) })
|
if (std::optional<Scrobbler> scrobbler{ getUserScrobbler(listen.userId) })
|
||||||
_scrobblers[*scrobbler]->listenStarted(listen);
|
_scrobblers[*scrobbler]->listenStarted(listen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ScrobblingService::listenFinished(const Listen& listen, std::optional<std::chrono::seconds> duration)
|
||||||
ScrobblingService::listenFinished(const Listen& listen, std::optional<std::chrono::seconds> duration)
|
|
||||||
{
|
{
|
||||||
if (std::optional<Scrobbler> scrobbler{ getUserScrobbler(listen.userId) })
|
if (std::optional<Scrobbler> scrobbler{ getUserScrobbler(listen.userId) })
|
||||||
_scrobblers[*scrobbler]->listenFinished(listen, duration);
|
_scrobblers[*scrobbler]->listenFinished(listen, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ScrobblingService::addTimedListen(const TimedListen& listen)
|
||||||
ScrobblingService::addTimedListen(const TimedListen& listen)
|
|
||||||
{
|
{
|
||||||
if (std::optional<Scrobbler> scrobbler{ getUserScrobbler(listen.userId) })
|
if (std::optional<Scrobbler> scrobbler{ getUserScrobbler(listen.userId) })
|
||||||
_scrobblers[*scrobbler]->addTimedListen(listen);
|
_scrobblers[*scrobbler]->addTimedListen(listen);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Scrobbler>
|
std::optional<Scrobbler> ScrobblingService::getUserScrobbler(UserId userId)
|
||||||
ScrobblingService::getUserScrobbler(UserId userId)
|
|
||||||
{
|
{
|
||||||
std::optional<Scrobbler> scrobbler;
|
std::optional<Scrobbler> scrobbler;
|
||||||
|
|
||||||
@@ -93,8 +88,7 @@ namespace Scrobbling
|
|||||||
return scrobbler;
|
return scrobbler;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrobblingService::ArtistContainer
|
ScrobblingService::ArtistContainer ScrobblingService::getRecentArtists(UserId userId, const std::vector<ClusterId>& clusterIds, std::optional<TrackArtistLinkType> linkType, Range range)
|
||||||
ScrobblingService::getRecentArtists(UserId userId, const std::vector<ClusterId>& clusterIds, std::optional<TrackArtistLinkType> linkType, Range range)
|
|
||||||
{
|
{
|
||||||
ArtistContainer res;
|
ArtistContainer res;
|
||||||
|
|
||||||
@@ -109,8 +103,7 @@ namespace Scrobbling
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrobblingService::ReleaseContainer
|
ScrobblingService::ReleaseContainer ScrobblingService::getRecentReleases(UserId userId, const std::vector<ClusterId>& clusterIds, Range range)
|
||||||
ScrobblingService::getRecentReleases(UserId userId, const std::vector<ClusterId>& clusterIds, Range range)
|
|
||||||
{
|
{
|
||||||
ReleaseContainer res;
|
ReleaseContainer res;
|
||||||
|
|
||||||
@@ -125,8 +118,7 @@ namespace Scrobbling
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrobblingService::TrackContainer
|
ScrobblingService::TrackContainer ScrobblingService::getRecentTracks(UserId userId, const std::vector<ClusterId>& clusterIds, Range range)
|
||||||
ScrobblingService::getRecentTracks(UserId userId, const std::vector<ClusterId>& clusterIds, Range range)
|
|
||||||
{
|
{
|
||||||
TrackContainer res;
|
TrackContainer res;
|
||||||
|
|
||||||
@@ -142,8 +134,7 @@ namespace Scrobbling
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Top
|
// Top
|
||||||
ScrobblingService::ArtistContainer
|
ScrobblingService::ArtistContainer ScrobblingService::getTopArtists(UserId userId, const std::vector<ClusterId>& clusterIds, std::optional<TrackArtistLinkType> linkType, Range range)
|
||||||
ScrobblingService::getTopArtists(UserId userId, const std::vector<ClusterId>& clusterIds, std::optional<TrackArtistLinkType> linkType, Range range)
|
|
||||||
{
|
{
|
||||||
ArtistContainer res;
|
ArtistContainer res;
|
||||||
|
|
||||||
@@ -158,8 +149,7 @@ namespace Scrobbling
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrobblingService::ReleaseContainer
|
ScrobblingService::ReleaseContainer ScrobblingService::getTopReleases(UserId userId, const std::vector<ClusterId>& clusterIds, Range range)
|
||||||
ScrobblingService::getTopReleases(UserId userId, const std::vector<ClusterId>& clusterIds, Range range)
|
|
||||||
{
|
{
|
||||||
ReleaseContainer res;
|
ReleaseContainer res;
|
||||||
|
|
||||||
@@ -174,8 +164,7 @@ namespace Scrobbling
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrobblingService::TrackContainer
|
ScrobblingService::TrackContainer ScrobblingService::getTopTracks(UserId userId, const std::vector<ClusterId>& clusterIds, Range range)
|
||||||
ScrobblingService::getTopTracks(UserId userId, const std::vector<ClusterId>& clusterIds, Range range)
|
|
||||||
{
|
{
|
||||||
TrackContainer res;
|
TrackContainer res;
|
||||||
|
|
||||||
@@ -190,26 +179,27 @@ namespace Scrobbling
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ScrobblingService::star(UserId userId, ArtistId artistId)
|
||||||
ScrobblingService::star(UserId userId, ArtistId artistId)
|
|
||||||
{
|
{
|
||||||
star<Artist, ArtistId, StarredArtist>(userId, artistId);
|
star<Artist, ArtistId, StarredArtist>(userId, artistId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ScrobblingService::unstar(UserId userId, ArtistId artistId)
|
||||||
ScrobblingService::unstar(UserId userId, ArtistId artistId)
|
|
||||||
{
|
{
|
||||||
unstar<Artist, ArtistId, StarredArtist>(userId, artistId);
|
unstar<Artist, ArtistId, StarredArtist>(userId, artistId);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool ScrobblingService::isStarred(UserId userId, ArtistId artistId)
|
||||||
ScrobblingService::isStarred(UserId userId, ArtistId artistId)
|
|
||||||
{
|
{
|
||||||
return isStarred<Artist, ArtistId, StarredArtist>(userId, artistId);
|
return isStarred<Artist, ArtistId, StarredArtist>(userId, artistId);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrobblingService::ArtistContainer
|
Wt::WDateTime ScrobblingService::getStarredDateTime(UserId userId, ArtistId artistId)
|
||||||
ScrobblingService::getStarredArtists(UserId userId, const std::vector<ClusterId>& clusterIds,
|
{
|
||||||
|
return getStarredDateTime<Artist, ArtistId, StarredArtist>(userId, artistId);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrobblingService::ArtistContainer ScrobblingService::getStarredArtists(UserId userId, const std::vector<ClusterId>& clusterIds,
|
||||||
std::optional<TrackArtistLinkType> linkType,
|
std::optional<TrackArtistLinkType> linkType,
|
||||||
ArtistSortMethod sortMethod,
|
ArtistSortMethod sortMethod,
|
||||||
Range range)
|
Range range)
|
||||||
@@ -231,26 +221,27 @@ namespace Scrobbling
|
|||||||
return Artist::find(session, params);
|
return Artist::find(session, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ScrobblingService::star(UserId userId, ReleaseId releaseId)
|
||||||
ScrobblingService::star(UserId userId, ReleaseId releaseId)
|
|
||||||
{
|
{
|
||||||
star<Release, ReleaseId, StarredRelease>(userId, releaseId);
|
star<Release, ReleaseId, StarredRelease>(userId, releaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ScrobblingService::unstar(UserId userId, ReleaseId releaseId)
|
||||||
ScrobblingService::unstar(UserId userId, ReleaseId releaseId)
|
|
||||||
{
|
{
|
||||||
unstar<Release, ReleaseId, StarredRelease>(userId, releaseId);
|
unstar<Release, ReleaseId, StarredRelease>(userId, releaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool ScrobblingService::isStarred(UserId userId, ReleaseId releaseId)
|
||||||
ScrobblingService::isStarred(UserId userId, ReleaseId releaseId)
|
|
||||||
{
|
{
|
||||||
return isStarred<Release, ReleaseId, StarredRelease>(userId, releaseId);
|
return isStarred<Release, ReleaseId, StarredRelease>(userId, releaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrobblingService::ReleaseContainer
|
Wt::WDateTime ScrobblingService::getStarredDateTime(UserId userId, ReleaseId releaseId)
|
||||||
ScrobblingService::getStarredReleases(UserId userId, const std::vector<ClusterId>& clusterIds, Range range)
|
{
|
||||||
|
return getStarredDateTime<Release, ReleaseId, StarredRelease>(userId, releaseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrobblingService::ReleaseContainer ScrobblingService::getStarredReleases(UserId userId, const std::vector<ClusterId>& clusterIds, Range range)
|
||||||
{
|
{
|
||||||
auto scrobbler{ getUserScrobbler(userId) };
|
auto scrobbler{ getUserScrobbler(userId) };
|
||||||
if (!scrobbler)
|
if (!scrobbler)
|
||||||
@@ -268,26 +259,27 @@ namespace Scrobbling
|
|||||||
return Release::find(session, params);
|
return Release::find(session, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ScrobblingService::star(UserId userId, TrackId trackId)
|
||||||
ScrobblingService::star(UserId userId, TrackId trackId)
|
|
||||||
{
|
{
|
||||||
star<Track, TrackId, StarredTrack>(userId, trackId);
|
star<Track, TrackId, StarredTrack>(userId, trackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ScrobblingService::unstar(UserId userId, TrackId trackId)
|
||||||
ScrobblingService::unstar(UserId userId, TrackId trackId)
|
|
||||||
{
|
{
|
||||||
unstar<Track, TrackId, StarredTrack>(userId, trackId);
|
unstar<Track, TrackId, StarredTrack>(userId, trackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool ScrobblingService::isStarred(UserId userId, TrackId trackId)
|
||||||
ScrobblingService::isStarred(UserId userId, TrackId trackId)
|
|
||||||
{
|
{
|
||||||
return isStarred<Track, TrackId, StarredTrack>(userId, trackId);
|
return isStarred<Track, TrackId, StarredTrack>(userId, trackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrobblingService::TrackContainer
|
Wt::WDateTime ScrobblingService::getStarredDateTime(UserId userId, TrackId trackId)
|
||||||
ScrobblingService::getStarredTracks(UserId userId, const std::vector<ClusterId>& clusterIds, Range range)
|
{
|
||||||
|
return getStarredDateTime<Track, TrackId, StarredTrack>(userId, trackId);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrobblingService::TrackContainer ScrobblingService::getStarredTracks(UserId userId, const std::vector<ClusterId>& clusterIds, Range range)
|
||||||
{
|
{
|
||||||
auto scrobbler{ getUserScrobbler(userId) };
|
auto scrobbler{ getUserScrobbler(userId) };
|
||||||
if (!scrobbler)
|
if (!scrobbler)
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ namespace Scrobbling
|
|||||||
void star(Database::UserId userId, Database::ArtistId artistId) override;
|
void star(Database::UserId userId, Database::ArtistId artistId) override;
|
||||||
void unstar(Database::UserId userId, Database::ArtistId artistId) override;
|
void unstar(Database::UserId userId, Database::ArtistId artistId) override;
|
||||||
bool isStarred(Database::UserId userId, Database::ArtistId artistId) override;
|
bool isStarred(Database::UserId userId, Database::ArtistId artistId) override;
|
||||||
|
Wt::WDateTime getStarredDateTime(Database::UserId userId, Database::ArtistId artistId) override;
|
||||||
ArtistContainer getStarredArtists(Database::UserId userId,
|
ArtistContainer getStarredArtists(Database::UserId userId,
|
||||||
const std::vector<Database::ClusterId>& clusterIds,
|
const std::vector<Database::ClusterId>& clusterIds,
|
||||||
std::optional<Database::TrackArtistLinkType> linkType,
|
std::optional<Database::TrackArtistLinkType> linkType,
|
||||||
@@ -76,12 +77,14 @@ namespace Scrobbling
|
|||||||
|
|
||||||
void star(Database::UserId userId, Database::ReleaseId releaseId) override;
|
void star(Database::UserId userId, Database::ReleaseId releaseId) override;
|
||||||
void unstar(Database::UserId userId, Database::ReleaseId releaseId) override;
|
void unstar(Database::UserId userId, Database::ReleaseId releaseId) override;
|
||||||
bool isStarred(Database::UserId userId, Database::ReleaseId artistId) override;
|
bool isStarred(Database::UserId userId, Database::ReleaseId releasedId) override;
|
||||||
|
Wt::WDateTime getStarredDateTime(Database::UserId userId, Database::ReleaseId releasedId) override;
|
||||||
ReleaseContainer getStarredReleases(Database::UserId userId, const std::vector<Database::ClusterId>& clusterIds, Database::Range range) override;
|
ReleaseContainer getStarredReleases(Database::UserId userId, const std::vector<Database::ClusterId>& clusterIds, Database::Range range) override;
|
||||||
|
|
||||||
void star(Database::UserId userId, Database::TrackId trackId) override;
|
void star(Database::UserId userId, Database::TrackId trackId) override;
|
||||||
void unstar(Database::UserId userId, Database::TrackId trackId) override;
|
void unstar(Database::UserId userId, Database::TrackId trackId) override;
|
||||||
bool isStarred(Database::UserId userId, Database::TrackId trackId) override;
|
bool isStarred(Database::UserId userId, Database::TrackId trackId) override;
|
||||||
|
Wt::WDateTime getStarredDateTime(Database::UserId userId, Database::TrackId trackId) override;
|
||||||
TrackContainer getStarredTracks(Database::UserId userId, const std::vector<Database::ClusterId>& clusterIds, Database::Range range) override;
|
TrackContainer getStarredTracks(Database::UserId userId, const std::vector<Database::ClusterId>& clusterIds, Database::Range range) override;
|
||||||
|
|
||||||
std::optional<Database::Scrobbler> getUserScrobbler(Database::UserId userId);
|
std::optional<Database::Scrobbler> getUserScrobbler(Database::UserId userId);
|
||||||
@@ -92,6 +95,8 @@ namespace Scrobbling
|
|||||||
void unstar(Database::UserId userId, ObjIdType id);
|
void unstar(Database::UserId userId, ObjIdType id);
|
||||||
template <typename ObjType, typename ObjIdType, typename StarredObjType>
|
template <typename ObjType, typename ObjIdType, typename StarredObjType>
|
||||||
bool isStarred(Database::UserId userId, ObjIdType id);
|
bool isStarred(Database::UserId userId, ObjIdType id);
|
||||||
|
template <typename ObjType, typename ObjIdType, typename StarredObjType>
|
||||||
|
Wt::WDateTime getStarredDateTime(Database::UserId userId, ObjIdType id);
|
||||||
|
|
||||||
Database::Db& _db;
|
Database::Db& _db;
|
||||||
std::unordered_map<Database::Scrobbler, std::unique_ptr<IScrobbler>> _scrobblers;
|
std::unordered_map<Database::Scrobbler, std::unique_ptr<IScrobbler>> _scrobblers;
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ namespace Scrobbling
|
|||||||
using namespace Database;
|
using namespace Database;
|
||||||
|
|
||||||
template <typename ObjType, typename ObjIdType, typename StarredObjType>
|
template <typename ObjType, typename ObjIdType, typename StarredObjType>
|
||||||
void
|
void ScrobblingService::star(UserId userId, ObjIdType objId)
|
||||||
ScrobblingService::star(UserId userId, ObjIdType objId)
|
|
||||||
{
|
{
|
||||||
auto scrobbler {getUserScrobbler(userId)};
|
auto scrobbler {getUserScrobbler(userId)};
|
||||||
if (!scrobbler)
|
if (!scrobbler)
|
||||||
@@ -60,8 +59,7 @@ namespace Scrobbling
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ObjType, typename ObjIdType, typename StarredObjType>
|
template <typename ObjType, typename ObjIdType, typename StarredObjType>
|
||||||
void
|
void ScrobblingService::unstar(UserId userId, ObjIdType objId)
|
||||||
ScrobblingService::unstar(UserId userId, ObjIdType objId)
|
|
||||||
{
|
{
|
||||||
auto scrobbler {getUserScrobbler(userId)};
|
auto scrobbler {getUserScrobbler(userId)};
|
||||||
if (!scrobbler)
|
if (!scrobbler)
|
||||||
@@ -82,8 +80,7 @@ namespace Scrobbling
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ObjType, typename ObjIdType, typename StarredObjType>
|
template <typename ObjType, typename ObjIdType, typename StarredObjType>
|
||||||
bool
|
bool ScrobblingService::isStarred(UserId userId, ObjIdType objId)
|
||||||
ScrobblingService::isStarred(UserId userId, ObjIdType objId)
|
|
||||||
{
|
{
|
||||||
auto scrobbler {getUserScrobbler(userId)};
|
auto scrobbler {getUserScrobbler(userId)};
|
||||||
if (!scrobbler)
|
if (!scrobbler)
|
||||||
@@ -96,5 +93,22 @@ namespace Scrobbling
|
|||||||
return starredObj && (starredObj->getScrobblingState() != ScrobblingState::PendingRemove);
|
return starredObj && (starredObj->getScrobblingState() != ScrobblingState::PendingRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ObjType, typename ObjIdType, typename StarredObjType>
|
||||||
|
Wt::WDateTime ScrobblingService::getStarredDateTime(UserId userId, ObjIdType objId)
|
||||||
|
{
|
||||||
|
auto scrobbler {getUserScrobbler(userId)};
|
||||||
|
if (!scrobbler)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
Session& session {_db.getTLSSession()};
|
||||||
|
auto transaction {session.createSharedTransaction()};
|
||||||
|
|
||||||
|
typename StarredObjType::pointer starredObj {StarredObjType::find(session, objId, userId, *scrobbler)};
|
||||||
|
if (starredObj && (starredObj->getScrobblingState() != ScrobblingState::PendingRemove))
|
||||||
|
return starredObj->getDateTime();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
} // ns Scrobbling
|
} // ns Scrobbling
|
||||||
|
|
||||||
|
|||||||
@@ -55,14 +55,12 @@ namespace Scrobbling
|
|||||||
: _db{ db }
|
: _db{ db }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void
|
void InternalScrobbler::listenStarted(const Listen&)
|
||||||
InternalScrobbler::listenStarted(const Listen&)
|
|
||||||
{
|
{
|
||||||
// nothing to do
|
// nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void InternalScrobbler::listenFinished(const Listen& listen, std::optional<std::chrono::seconds> duration)
|
||||||
InternalScrobbler::listenFinished(const Listen& listen, std::optional<std::chrono::seconds> duration)
|
|
||||||
{
|
{
|
||||||
// only record tracks that have been played for at least of few seconds...
|
// only record tracks that have been played for at least of few seconds...
|
||||||
if (duration && *duration < std::chrono::seconds{ 5 })
|
if (duration && *duration < std::chrono::seconds{ 5 })
|
||||||
@@ -71,8 +69,7 @@ namespace Scrobbling
|
|||||||
addTimedListen({ listen, Wt::WDateTime::currentDateTime() });
|
addTimedListen({ listen, Wt::WDateTime::currentDateTime() });
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void InternalScrobbler::addTimedListen(const TimedListen& listen)
|
||||||
InternalScrobbler::addTimedListen(const TimedListen& listen)
|
|
||||||
{
|
{
|
||||||
Database::Session& session{ _db.getTLSSession() };
|
Database::Session& session{ _db.getTLSSession() };
|
||||||
auto transaction{ session.createUniqueTransaction() };
|
auto transaction{ session.createUniqueTransaction() };
|
||||||
@@ -92,20 +89,17 @@ namespace Scrobbling
|
|||||||
dbListen.modify()->setScrobblingState(Database::ScrobblingState::Synchronized);
|
dbListen.modify()->setScrobblingState(Database::ScrobblingState::Synchronized);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void InternalScrobbler::onStarred(Database::StarredArtistId starredArtistId)
|
||||||
InternalScrobbler::onStarred(Database::StarredArtistId starredArtistId)
|
|
||||||
{
|
{
|
||||||
::onStarred<Database::StarredArtist>(_db.getTLSSession(), starredArtistId);
|
::onStarred<Database::StarredArtist>(_db.getTLSSession(), starredArtistId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void InternalScrobbler::onUnstarred(Database::StarredArtistId starredArtistId)
|
||||||
InternalScrobbler::onUnstarred(Database::StarredArtistId starredArtistId)
|
|
||||||
{
|
{
|
||||||
::onUnstarred<Database::StarredArtist>(_db.getTLSSession(), starredArtistId);
|
::onUnstarred<Database::StarredArtist>(_db.getTLSSession(), starredArtistId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void InternalScrobbler::onStarred(Database::StarredReleaseId starredReleaseId)
|
||||||
InternalScrobbler::onStarred(Database::StarredReleaseId starredReleaseId)
|
|
||||||
{
|
{
|
||||||
::onStarred<Database::StarredRelease>(_db.getTLSSession(), starredReleaseId);
|
::onStarred<Database::StarredRelease>(_db.getTLSSession(), starredReleaseId);
|
||||||
}
|
}
|
||||||
@@ -115,14 +109,12 @@ namespace Scrobbling
|
|||||||
::onUnstarred<Database::StarredRelease>(_db.getTLSSession(), starredReleaseId);
|
::onUnstarred<Database::StarredRelease>(_db.getTLSSession(), starredReleaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void InternalScrobbler::onStarred(Database::StarredTrackId starredTrackId)
|
||||||
InternalScrobbler::onStarred(Database::StarredTrackId starredTrackId)
|
|
||||||
{
|
{
|
||||||
::onStarred<Database::StarredTrack>(_db.getTLSSession(), starredTrackId);
|
::onStarred<Database::StarredTrack>(_db.getTLSSession(), starredTrackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void InternalScrobbler::onUnstarred(Database::StarredTrackId starredTrackId)
|
||||||
InternalScrobbler::onUnstarred(Database::StarredTrackId starredTrackId)
|
|
||||||
{
|
{
|
||||||
::onUnstarred<Database::StarredTrack>(_db.getTLSSession(), starredTrackId);
|
::onUnstarred<Database::StarredTrack>(_db.getTLSSession(), starredTrackId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <boost/asio/io_service.hpp>
|
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <boost/asio/io_service.hpp>
|
||||||
|
#include <Wt/WDateTime.h>
|
||||||
|
|
||||||
#include "services/scrobbling/Listen.hpp"
|
#include "services/scrobbling/Listen.hpp"
|
||||||
#include "services/database/ArtistId.hpp"
|
#include "services/database/ArtistId.hpp"
|
||||||
@@ -87,6 +87,7 @@ namespace Scrobbling
|
|||||||
virtual void star(Database::UserId userId, Database::ArtistId artistId) = 0;
|
virtual void star(Database::UserId userId, Database::ArtistId artistId) = 0;
|
||||||
virtual void unstar(Database::UserId userId, Database::ArtistId artistId) = 0;
|
virtual void unstar(Database::UserId userId, Database::ArtistId artistId) = 0;
|
||||||
virtual bool isStarred(Database::UserId userId, Database::ArtistId artistId) = 0;
|
virtual bool isStarred(Database::UserId userId, Database::ArtistId artistId) = 0;
|
||||||
|
virtual Wt::WDateTime getStarredDateTime(Database::UserId userId, Database::ArtistId artistId) = 0;
|
||||||
virtual ArtistContainer getStarredArtists(Database::UserId userId,
|
virtual ArtistContainer getStarredArtists(Database::UserId userId,
|
||||||
const std::vector<Database::ClusterId>& clusterIds,
|
const std::vector<Database::ClusterId>& clusterIds,
|
||||||
std::optional<Database::TrackArtistLinkType> linkType,
|
std::optional<Database::TrackArtistLinkType> linkType,
|
||||||
@@ -96,11 +97,13 @@ namespace Scrobbling
|
|||||||
virtual void star(Database::UserId userId, Database::ReleaseId releaseId) = 0;
|
virtual void star(Database::UserId userId, Database::ReleaseId releaseId) = 0;
|
||||||
virtual void unstar(Database::UserId userId, Database::ReleaseId releaseId) = 0;
|
virtual void unstar(Database::UserId userId, Database::ReleaseId releaseId) = 0;
|
||||||
virtual bool isStarred(Database::UserId userId, Database::ReleaseId artistId) = 0;
|
virtual bool isStarred(Database::UserId userId, Database::ReleaseId artistId) = 0;
|
||||||
|
virtual Wt::WDateTime getStarredDateTime(Database::UserId userId, Database::ReleaseId artistId) = 0;
|
||||||
virtual ReleaseContainer getStarredReleases(Database::UserId userId, const std::vector<Database::ClusterId>& clusterIds, Database::Range range) = 0;
|
virtual ReleaseContainer getStarredReleases(Database::UserId userId, const std::vector<Database::ClusterId>& clusterIds, Database::Range range) = 0;
|
||||||
|
|
||||||
virtual void star(Database::UserId userId, Database::TrackId trackId) = 0;
|
virtual void star(Database::UserId userId, Database::TrackId trackId) = 0;
|
||||||
virtual void unstar(Database::UserId userId, Database::TrackId trackId) = 0;
|
virtual void unstar(Database::UserId userId, Database::TrackId trackId) = 0;
|
||||||
virtual bool isStarred(Database::UserId userId, Database::TrackId artistId) = 0;
|
virtual bool isStarred(Database::UserId userId, Database::TrackId artistId) = 0;
|
||||||
|
virtual Wt::WDateTime getStarredDateTime(Database::UserId userId, Database::TrackId artistId) = 0;
|
||||||
virtual TrackContainer getStarredTracks(Database::UserId userId, const std::vector<Database::ClusterId>& clusterIds, Database::Range range) = 0;
|
virtual TrackContainer getStarredTracks(Database::UserId userId, const std::vector<Database::ClusterId>& clusterIds, Database::Range range) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,6 @@
|
|||||||
|
|
||||||
namespace API::Subsonic
|
namespace API::Subsonic
|
||||||
{
|
{
|
||||||
static const std::string_view reportedDummyStarredDate{ "2000-01-01T00:00:00" };
|
|
||||||
|
|
||||||
using namespace Database;
|
using namespace Database;
|
||||||
|
|
||||||
Response::Node createAlbumNode(const Release::pointer& release, Session& dbSession, const User::pointer& user, bool id3)
|
Response::Node createAlbumNode(const Release::pointer& release, Session& dbSession, const User::pointer& user, bool id3)
|
||||||
@@ -95,8 +93,8 @@ namespace API::Subsonic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Service<Scrobbling::IScrobblingService>::get()->isStarred(user->getId(), release->getId()))
|
if (const Wt::WDateTime dateTime{ Service<Scrobbling::IScrobblingService>::get()->getStarredDateTime(user->getId(), release->getId()) }; dateTime.isValid())
|
||||||
albumNode.setAttribute("starred", reportedDummyStarredDate); // TODO report correct date/time
|
albumNode.setAttribute("starred", StringUtils::toISO8601String(dateTime)); // TODO report correct date/time
|
||||||
|
|
||||||
return albumNode;
|
return albumNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,13 +24,12 @@
|
|||||||
#include "services/database/User.hpp"
|
#include "services/database/User.hpp"
|
||||||
#include "services/scrobbling/IScrobblingService.hpp"
|
#include "services/scrobbling/IScrobblingService.hpp"
|
||||||
#include "utils/Service.hpp"
|
#include "utils/Service.hpp"
|
||||||
|
#include "utils/String.hpp"
|
||||||
|
|
||||||
#include "SubsonicId.hpp"
|
#include "SubsonicId.hpp"
|
||||||
|
|
||||||
namespace API::Subsonic
|
namespace API::Subsonic
|
||||||
{
|
{
|
||||||
static const std::string_view reportedDummyStarredDate{ "2000-01-01T00:00:00" };
|
|
||||||
|
|
||||||
using namespace Database;
|
using namespace Database;
|
||||||
|
|
||||||
namespace Utils
|
namespace Utils
|
||||||
@@ -66,8 +65,8 @@ namespace API::Subsonic
|
|||||||
artistNode.setAttribute("albumCount", releases.results.size());
|
artistNode.setAttribute("albumCount", releases.results.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Service<Scrobbling::IScrobblingService>::get()->isStarred(user->getId(), artist->getId()))
|
if (const Wt::WDateTime dateTime{ Service<Scrobbling::IScrobblingService>::get()->getStarredDateTime(user->getId(), artist->getId()) }; dateTime.isValid())
|
||||||
artistNode.setAttribute("starred", reportedDummyStarredDate); // TODO handle date/time
|
artistNode.setAttribute("starred", StringUtils::toISO8601String(dateTime));
|
||||||
|
|
||||||
return artistNode;
|
return artistNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ namespace API::Subsonic
|
|||||||
{
|
{
|
||||||
using namespace Database;
|
using namespace Database;
|
||||||
|
|
||||||
static const std::string_view reportedDummyStarredDate{ "2000-01-01T00:00:00" };
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
std::string_view formatToSuffix(AudioFormat format)
|
std::string_view formatToSuffix(AudioFormat format)
|
||||||
@@ -143,8 +141,8 @@ namespace API::Subsonic
|
|||||||
trackResponse.setAttribute("type", "music");
|
trackResponse.setAttribute("type", "music");
|
||||||
trackResponse.setAttribute("created", StringUtils::toISO8601String(track->getLastWritten()));
|
trackResponse.setAttribute("created", StringUtils::toISO8601String(track->getLastWritten()));
|
||||||
|
|
||||||
if (Service<Scrobbling::IScrobblingService>::get()->isStarred(user->getId(), track->getId()))
|
if (const Wt::WDateTime dateTime{ Service<Scrobbling::IScrobblingService>::get()->getStarredDateTime(user->getId(), track->getId()) }; dateTime.isValid())
|
||||||
trackResponse.setAttribute("starred", reportedDummyStarredDate); // TODO handle date/time
|
trackResponse.setAttribute("starred", StringUtils::toISO8601String(dateTime));
|
||||||
|
|
||||||
// Report the first GENRE for this track
|
// Report the first GENRE for this track
|
||||||
ClusterType::pointer clusterType{ ClusterType::find(dbSession, "GENRE") };
|
ClusterType::pointer clusterType{ ClusterType::find(dbSession, "GENRE") };
|
||||||
|
|||||||
@@ -288,11 +288,13 @@ namespace StringUtils
|
|||||||
|
|
||||||
std::string toISO8601String(const Wt::WDateTime& dateTime)
|
std::string toISO8601String(const Wt::WDateTime& dateTime)
|
||||||
{
|
{
|
||||||
|
// assume UTC
|
||||||
return dateTime.toString("yyyy-MM-ddThh:mm:ss.zzz", false).toUTF8();
|
return dateTime.toString("yyyy-MM-ddThh:mm:ss.zzz", false).toUTF8();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string toISO8601String(const Wt::WDate& date)
|
std::string toISO8601String(const Wt::WDate& date)
|
||||||
{
|
{
|
||||||
|
// assume UTC
|
||||||
return date.toString("yyyy-MM-dd").toUTF8();
|
return date.toString("yyyy-MM-dd").toUTF8();
|
||||||
}
|
}
|
||||||
} // StringUtils
|
} // StringUtils
|
||||||
|
|||||||
Reference in New Issue
Block a user