Fixed subsonic scrobble command + internal scrobbler: do not record listen that have been played for less than 5s
This commit is contained in:
@@ -43,7 +43,7 @@ namespace Scrobbling
|
|||||||
virtual ~IScrobbler() = default;
|
virtual ~IScrobbler() = default;
|
||||||
|
|
||||||
virtual void listenStarted(const Listen& listen) = 0;
|
virtual void listenStarted(const Listen& listen) = 0;
|
||||||
virtual void listenFinished(const Listen& listen, std::chrono::seconds duration) = 0;
|
virtual void listenFinished(const Listen& listen, std::optional<std::chrono::seconds> duration) = 0;
|
||||||
|
|
||||||
virtual void addListen(const Listen& listen, const Wt::WDateTime& timePoint) = 0;
|
virtual void addListen(const Listen& listen, const Wt::WDateTime& timePoint) = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace Scrobbling
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Scrobbling::listenFinished(const Listen& listen, std::chrono::seconds duration)
|
Scrobbling::listenFinished(const Listen& listen, std::optional<std::chrono::seconds> duration)
|
||||||
{
|
{
|
||||||
if (auto scrobbler {getUserScrobbler(listen.userId)})
|
if (auto scrobbler {getUserScrobbler(listen.userId)})
|
||||||
_scrobblers[*scrobbler]->listenFinished(listen, duration);
|
_scrobblers[*scrobbler]->listenFinished(listen, duration);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace Scrobbling
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void listenStarted(const Listen& listen) override;
|
void listenStarted(const Listen& listen) override;
|
||||||
void listenFinished(const Listen& listen, std::chrono::seconds duration) override;
|
void listenFinished(const Listen& listen, std::optional<std::chrono::seconds> duration) override;
|
||||||
void addListen(const Listen& listen, Wt::WDateTime timePoint) override;
|
void addListen(const Listen& listen, Wt::WDateTime timePoint) override;
|
||||||
|
|
||||||
std::vector<Wt::Dbo::ptr<Database::Artist>> getRecentArtists(Database::Session& session,
|
std::vector<Wt::Dbo::ptr<Database::Artist>> getRecentArtists(Database::Session& session,
|
||||||
|
|||||||
@@ -35,15 +35,19 @@ namespace Scrobbling
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
void
|
void
|
||||||
InternalScrobbler::listenStarted(const Listen& listen)
|
InternalScrobbler::listenStarted(const Listen& /*listen*/)
|
||||||
{
|
{
|
||||||
addListen(listen, Wt::WDateTime::currentDateTime());
|
// nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
InternalScrobbler::listenFinished(const Listen& /*event*/, std::chrono::seconds /* duration */)
|
InternalScrobbler::listenFinished(const Listen& listen, std::optional<std::chrono::seconds> duration)
|
||||||
{
|
{
|
||||||
// nothing to do
|
// record tracks that have been played for at least of few seconds...
|
||||||
|
if (duration && *duration < std::chrono::seconds {5})
|
||||||
|
return;
|
||||||
|
|
||||||
|
addListen(listen, Wt::WDateTime::currentDateTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace Scrobbling
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void listenStarted(const Listen& listen) override;
|
void listenStarted(const Listen& listen) override;
|
||||||
void listenFinished(const Listen& listen, std::chrono::seconds duration) override;
|
void listenFinished(const Listen& listen, std::optional<std::chrono::seconds> duration) override;
|
||||||
|
|
||||||
void addListen(const Listen& listen, const Wt::WDateTime& timePoint) override;
|
void addListen(const Listen& listen, const Wt::WDateTime& timePoint) override;
|
||||||
|
|
||||||
|
|||||||
@@ -214,13 +214,13 @@ namespace Scrobbling
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ListenBrainzScrobbler::listenFinished(const Listen& listen, std::chrono::seconds duration)
|
ListenBrainzScrobbler::listenFinished(const Listen& listen, std::optional<std::chrono::seconds> duration)
|
||||||
{
|
{
|
||||||
if (!canBeScrobbled(_db.getTLSSession(), listen.trackId, duration))
|
if (duration && !canBeScrobbled(_db.getTLSSession(), listen.trackId, *duration))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Listen timedListen {listen};
|
Listen timedListen {listen};
|
||||||
const Wt::WDateTime now {Wt::WDateTime::currentDateTime().addSecs(-duration.count())};
|
const Wt::WDateTime now {Wt::WDateTime::currentDateTime()};
|
||||||
|
|
||||||
_ioService.post([=]
|
_ioService.post([=]
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace Scrobbling
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void listenStarted(const Listen& listen) override;
|
void listenStarted(const Listen& listen) override;
|
||||||
void listenFinished(const Listen& listen, std::chrono::seconds duration) override;
|
void listenFinished(const Listen& listen, std::optional<std::chrono::seconds> duration) override;
|
||||||
void addListen(const Listen& listen, const Wt::WDateTime& timePoint) override;
|
void addListen(const Listen& listen, const Wt::WDateTime& timePoint) override;
|
||||||
|
|
||||||
Wt::Dbo::ptr<Database::TrackList> getListensTrackList(Database::Session& session, Wt::Dbo::ptr<Database::User> user) override;
|
Wt::Dbo::ptr<Database::TrackList> getListensTrackList(Database::Session& session, Wt::Dbo::ptr<Database::User> user) override;
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ namespace Scrobbling
|
|||||||
|
|
||||||
// Scrobbling
|
// Scrobbling
|
||||||
virtual void listenStarted(const Listen& listen) = 0;
|
virtual void listenStarted(const Listen& listen) = 0;
|
||||||
virtual void listenFinished(const Listen& listen, std::chrono::seconds duration) = 0;
|
virtual void listenFinished(const Listen& listen, std::optional<std::chrono::seconds> playedDuration = std::nullopt) = 0;
|
||||||
|
|
||||||
virtual void addListen(const Listen& listen, Wt::WDateTime timePoint) = 0;
|
virtual void addListen(const Listen& listen, Wt::WDateTime timePoint) = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -1644,52 +1644,46 @@ Response
|
|||||||
handleScrobble(RequestContext& context)
|
handleScrobble(RequestContext& context)
|
||||||
{
|
{
|
||||||
const std::vector<Id> ids {getMandatoryMultiParametersAs<Id>(context.parameters, "id")};
|
const std::vector<Id> ids {getMandatoryMultiParametersAs<Id>(context.parameters, "id")};
|
||||||
const std::vector<unsigned long> times {getMandatoryMultiParametersAs<unsigned long>(context.parameters, "time")};
|
const std::vector<unsigned long> times {getMultiParametersAs<unsigned long>(context.parameters, "time")};
|
||||||
|
const bool submission{getParameterAs<bool>(context.parameters, "submission").value_or(true)};
|
||||||
|
|
||||||
|
// only for tracks
|
||||||
if (!std::all_of(std::cbegin(ids), std::cend(ids), [](const Id& id) { return id.type == Id::Type::Track; }))
|
if (!std::all_of(std::cbegin(ids), std::cend(ids), [](const Id& id) { return id.type == Id::Type::Track; }))
|
||||||
throw BadParameterGenericError {"id"};
|
throw BadParameterGenericError {"id"};
|
||||||
|
|
||||||
if (ids.size() != times.size())
|
// playing now => no time to be provided
|
||||||
|
if (!submission && !times.empty())
|
||||||
throw BadParameterGenericError {"time"};
|
throw BadParameterGenericError {"time"};
|
||||||
|
|
||||||
struct Scrobble
|
// playing now => only one at a time
|
||||||
|
if (!submission && ids.size() > 1)
|
||||||
|
throw BadParameterGenericError {"id"};
|
||||||
|
|
||||||
|
// if multiple submissions, must have times
|
||||||
|
if (ids.size() > 1 && ids.size() != times.size())
|
||||||
|
throw BadParameterGenericError {"time"};
|
||||||
|
|
||||||
|
if (!submission)
|
||||||
{
|
{
|
||||||
Scrobbling::Listen listen;
|
Service<Scrobbling::IScrobbling>::get()->listenStarted({context.userId, ids.front().value});
|
||||||
Wt::WDateTime timePoint;
|
}
|
||||||
};
|
else
|
||||||
|
|
||||||
std::vector<Scrobble> scrobbles;
|
|
||||||
scrobbles.reserve(ids.size());
|
|
||||||
|
|
||||||
{
|
{
|
||||||
auto transaction {context.dbSession.createSharedTransaction()};
|
if (times.empty())
|
||||||
|
|
||||||
User::pointer user {User::getById(context.dbSession, context.userId)};
|
|
||||||
if (!user)
|
|
||||||
throw RequestedDataNotFoundError {};
|
|
||||||
|
|
||||||
Scrobble scrobble;
|
|
||||||
scrobble.listen.userId = context.userId;
|
|
||||||
|
|
||||||
for (std::size_t i {}; i < ids.size(); ++i)
|
|
||||||
{
|
{
|
||||||
const Id id {ids[i]};
|
Service<Scrobbling::IScrobbling>::get()->listenFinished({context.userId, ids.front().value});
|
||||||
const unsigned long time {times[i]};
|
}
|
||||||
|
else
|
||||||
const Track::pointer track {Track::getById(context.dbSession, id.value)};
|
{
|
||||||
if (!track)
|
for (std::size_t i {}; i < ids.size(); ++i)
|
||||||
continue;
|
{
|
||||||
|
const Database::IdType trackId {ids[i].value};
|
||||||
scrobble.listen.trackId = id.value;
|
const unsigned long time {times[i]};
|
||||||
scrobble.timePoint.setTime_t(static_cast<std::time_t>(time / 1000));
|
Service<Scrobbling::IScrobbling>::get()->addListen({context.userId, trackId}, Wt::WDateTime::fromTime_t(static_cast<std::time_t>(time / 1000)));
|
||||||
|
}
|
||||||
scrobbles.emplace_back(scrobble);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const Scrobble& scrobble : scrobbles)
|
|
||||||
Service<Scrobbling::IScrobbling>::get()->addListen(scrobble.listen, scrobble.timePoint);
|
|
||||||
|
|
||||||
return Response::createOkResponse(context);
|
return Response::createOkResponse(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user