Subsonic API: added star support

This commit is contained in:
emeric
2019-06-16 15:11:42 +02:00
parent 08988b17a2
commit ef648d5cb6
12 changed files with 611 additions and 55 deletions
+1
View File
@@ -26,6 +26,7 @@
#include "Release.hpp"
#include "SqlQuery.hpp"
#include "Track.hpp"
#include "User.hpp"
namespace Database
{
+3
View File
@@ -37,6 +37,7 @@ class Cluster;
class ClusterType;
class Release;
class Track;
class User;
class Artist : public Wt::Dbo::Dbo<Artist>
{
@@ -93,6 +94,7 @@ class Artist : public Wt::Dbo::Dbo<Artist>
Wt::Dbo::field(a, _MBID, "mbid");
Wt::Dbo::hasMany(a, _trackArtistLinks, Wt::Dbo::ManyToOne, "artist");
Wt::Dbo::hasMany(a, _starringUsers, Wt::Dbo::ManyToMany, "user_release_starred", "", Wt::Dbo::OnDeleteCascade);
}
private:
@@ -104,6 +106,7 @@ class Artist : public Wt::Dbo::Dbo<Artist>
std::string _MBID; // Musicbrainz Identifier
Wt::Dbo::collection<Wt::Dbo::ptr<TrackArtistLink>> _trackArtistLinks; // Tracks involving this artist
Wt::Dbo::collection<Wt::Dbo::ptr<User>> _starringUsers; // Users that starred this artist
};
} // namespace Database
+63 -13
View File
@@ -46,7 +46,7 @@
namespace Database {
#define LMS_DATABASE_VERSION 3
#define LMS_DATABASE_VERSION 4
namespace {
Wt::Auth::AuthService authService;
@@ -82,6 +82,67 @@ class VersionInfo
int _version {LMS_DATABASE_VERSION};
};
static
void
doDatabaseMigrationIfNeeded(Wt::Dbo::Session& session)
{
Wt::Dbo::Transaction transaction {session};
static const std::string outdatedMsg {"Outdated database, please rebuild it (delete the .db file and restart)"};
Version version;
try
{
version = VersionInfo::get(session)->getVersion();
if (version == LMS_DATABASE_VERSION)
return;
}
catch (std::exception& e)
{
LMS_LOG(DB, ERROR) << "Cannot get database version info: " << e.what();
throw LmsException {outdatedMsg};
}
switch (version)
{
case 3:
LMS_LOG(DB, INFO) << "Migrating database from version 3...";
session.execute(R"(CREATE TABLE IF NOT EXISTS "user_artist_starred" (
"user_id" bigint,
"artist_id" bigint,
primary key ("user_id", "artist_id"),
constraint "fk_user_artist_starred_key1" foreign key ("user_id") references "user" ("id") on delete cascade deferrable initially deferred,
constraint "fk_user_artist_starred_key2" foreign key ("artist_id") references "artist" ("id") deferrable initially deferred);)");
session.execute(R"(CREATE INDEX "user_artist_starred_user" on "user_artist_starred" ("user_id");)");
session.execute(R"(CREATE INDEX "user_artist_starred_artist" on "user_artist_starred" ("artist_id");)");
session.execute(R"(CREATE TABLE IF NOT EXISTS "user_release_starred" (
"user_id" bigint,
"release_id" bigint,
primary key ("user_id", "release_id"),
constraint "fk_user_release_starred_key1" foreign key ("user_id") references "user" ("id") on delete cascade deferrable initially deferred,
constraint "fk_user_release_starred_key2" foreign key ("release_id") references "release" ("id") on delete cascade deferrable initially deferred);)");
session.execute(R"(CREATE INDEX "user_release_starred_user" on "user_release_starred" ("user_id");)");
session.execute(R"(CREATE INDEX "user_release_starred_release" on "user_release_starred" ("release_id");)");
session.execute(R"(CREATE TABLE IF NOT EXISTS "user_track_starred" (
"user_id" bigint,
"track_id" bigint,
primary key ("user_id", "track_id"),
constraint "fk_user_track_starred_key1" foreign key ("user_id") references "user" ("id") on delete cascade deferrable initially deferred,
constraint "fk_user_track_starred_key2" foreign key ("track_id") references "track" ("id") on delete cascade deferrable initially deferred);)");
session.execute(R"(CREATE INDEX "user_track_starred_user" on "user_track_starred" ("user_id");)");
session.execute(R"(CREATE INDEX "user_track_starred_track" on "user_track_starred" ("track_id");)");
break;
default:
LMS_LOG(DB, ERROR) << "Database version " << version << " cannot be handled using migration";
throw LmsException {outdatedMsg};
}
VersionInfo::get(session).modify()->setVersion(LMS_DATABASE_VERSION);
}
void
Handler::configureAuth(void)
@@ -163,18 +224,7 @@ Handler::Handler(Wt::Dbo::SqlConnectionPool& connectionPool)
LMS_LOG(DB, ERROR) << "Cannot create tables: " << e.what();
}
try
{
Wt::Dbo::Transaction transaction {_session};
Version version {VersionInfo::get(_session)->getVersion()};
if (version != LMS_DATABASE_VERSION)
throw LmsException {"Outdated database, please rebuild it (database migration not yet implemented)"};
}
catch (std::exception& e)
{
throw LmsException {"Cannot get database version, please rebuild it (database migration not yet implemented)"};
}
doDatabaseMigrationIfNeeded(_session);
{
Wt::Dbo::Transaction transaction {_session};
+1
View File
@@ -25,6 +25,7 @@
#include "Cluster.hpp"
#include "SqlQuery.hpp"
#include "Track.hpp"
#include "User.hpp"
namespace Database
{
+5 -2
View File
@@ -29,11 +29,12 @@
namespace Database
{
class Track;
class Release;
class Artist;
class Cluster;
class ClusterType;
class Release;
class Track;
class User;
class Release : public Wt::Dbo::Dbo<Release>
{
@@ -104,6 +105,7 @@ class Release : public Wt::Dbo::Dbo<Release>
Wt::Dbo::field(a, _totalTrackNumber, "total_track_number");
Wt::Dbo::hasMany(a, _tracks, Wt::Dbo::ManyToOne, "release");
Wt::Dbo::hasMany(a, _starringUsers, Wt::Dbo::ManyToMany, "user_release_starred", "", Wt::Dbo::OnDeleteCascade);
}
private:
@@ -115,6 +117,7 @@ class Release : public Wt::Dbo::Dbo<Release>
int _totalTrackNumber {};
Wt::Dbo::collection<Wt::Dbo::ptr<Track>> _tracks; // Tracks in the release
Wt::Dbo::collection<Wt::Dbo::ptr<User>> _starringUsers; // Users that starred this release
};
} // namespace Database
+3
View File
@@ -41,6 +41,7 @@ class Release;
class TrackFeatures;
class TrackListEntry;
class TrackStats;
class User;
class Track : public Wt::Dbo::Dbo<Track>
{
@@ -144,6 +145,7 @@ class Track : public Wt::Dbo::Dbo<Track>
Wt::Dbo::hasMany(a, _trackArtistLinks, Wt::Dbo::ManyToOne, "track");
Wt::Dbo::hasMany(a, _clusters, Wt::Dbo::ManyToMany, "track_cluster", "", Wt::Dbo::OnDeleteCascade);
Wt::Dbo::hasMany(a, _playlistEntries, Wt::Dbo::ManyToOne, "track");
Wt::Dbo::hasMany(a, _starringUsers, Wt::Dbo::ManyToMany, "user_track_starred", "", Wt::Dbo::OnDeleteCascade);
Wt::Dbo::hasOne(a, _trackFeatures);
}
@@ -175,6 +177,7 @@ class Track : public Wt::Dbo::Dbo<Track>
Wt::Dbo::collection<Wt::Dbo::ptr<TrackArtistLink>> _trackArtistLinks;
Wt::Dbo::collection<Wt::Dbo::ptr<Cluster>> _clusters;
Wt::Dbo::collection<Wt::Dbo::ptr<TrackListEntry>> _playlistEntries;
Wt::Dbo::collection<Wt::Dbo::ptr<User>> _starringUsers;
Wt::Dbo::weak_ptr<TrackFeatures> _trackFeatures;
};
+82
View File
@@ -19,6 +19,9 @@
#include "User.hpp"
#include "Artist.hpp"
#include "Release.hpp"
#include "Track.hpp"
#include "TrackList.hpp"
namespace Database {
@@ -123,6 +126,85 @@ User::getQueuedTrackList() const
return res;
}
void
User::starArtist(Wt::Dbo::ptr<Artist> artist)
{
if (_starredArtists.count(artist) == 0)
_starredArtists.insert(artist);
}
void
User::unstarArtist(Wt::Dbo::ptr<Artist> artist)
{
if (_starredArtists.count(artist) != 0)
_starredArtists.erase(artist);
}
bool
User::hasStarredArtist(Wt::Dbo::ptr<Artist> artist) const
{
return _starredArtists.count(artist) != 0;
}
std::vector<Wt::Dbo::ptr<Artist>>
User::getStarredArtists() const
{
return std::vector<Wt::Dbo::ptr<Artist>>(_starredArtists.begin(), _starredArtists.end());
}
void
User::starRelease(Wt::Dbo::ptr<Release> release)
{
if (_starredReleases.count(release) == 0)
_starredReleases.insert(release);
}
void
User::unstarRelease(Wt::Dbo::ptr<Release> release)
{
if (_starredReleases.count(release) != 0)
_starredReleases.erase(release);
}
bool
User::hasStarredRelease(Wt::Dbo::ptr<Release> release) const
{
return _starredReleases.count(release) != 0;
}
std::vector<Wt::Dbo::ptr<Release>>
User::getStarredReleases() const
{
return std::vector<Wt::Dbo::ptr<Release>>(_starredReleases.begin(), _starredReleases.end());
}
void
User::starTrack(Wt::Dbo::ptr<Track> track)
{
if (_starredTracks.count(track) == 0)
_starredTracks.insert(track);
}
void
User::unstarTrack(Wt::Dbo::ptr<Track> track)
{
if (_starredTracks.count(track) != 0)
_starredTracks.erase(track);
}
bool
User::hasStarredTrack(Wt::Dbo::ptr<Track> track) const
{
return _starredTracks.count(track) != 0;
}
std::vector<Wt::Dbo::ptr<Track>>
User::getStarredTracks() const
{
return std::vector<Wt::Dbo::ptr<Track>>(_starredTracks.begin(), _starredTracks.end());
}
} // namespace Database
+25 -1
View File
@@ -31,7 +31,10 @@ namespace Database {
class User;
using AuthInfo = Wt::Auth::Dbo::AuthInfo<User>;
class Artist;
class Release;
class TrackList;
class Track;
// User selectable audio formats
// Do not change values
@@ -97,6 +100,21 @@ class User : public Wt::Dbo::Dbo<User>
Wt::Dbo::ptr<TrackList> getQueuedTrackList() const;
Wt::Dbo::ptr<TrackList> getPlayedTrackList() const;
void starArtist(Wt::Dbo::ptr<Artist> artist);
void unstarArtist(Wt::Dbo::ptr<Artist> artist);
bool hasStarredArtist(Wt::Dbo::ptr<Artist> artist) const;
std::vector<Wt::Dbo::ptr<Artist>> getStarredArtists() const;
void starRelease(Wt::Dbo::ptr<Release> release);
void unstarRelease(Wt::Dbo::ptr<Release> release);
bool hasStarredRelease(Wt::Dbo::ptr<Release> release) const;
std::vector<Wt::Dbo::ptr<Release>> getStarredReleases() const;
void starTrack(Wt::Dbo::ptr<Track> track);
void unstarTrack(Wt::Dbo::ptr<Track> track);
bool hasStarredTrack(Wt::Dbo::ptr<Track> track) const;
std::vector<Wt::Dbo::ptr<Track>> getStarredTracks() const;
template<class Action>
void persist(Action& a)
{
@@ -110,6 +128,9 @@ class User : public Wt::Dbo::Dbo<User>
Wt::Dbo::field(a, _repeatAll, "repeat_all");
Wt::Dbo::field(a, _radio, "radio");
Wt::Dbo::hasMany(a, _tracklists, Wt::Dbo::ManyToOne, "user");
Wt::Dbo::hasMany(a, _starredArtists, Wt::Dbo::ManyToMany, "user_artist_starred", "", Wt::Dbo::OnDeleteCascade);
Wt::Dbo::hasMany(a, _starredReleases, Wt::Dbo::ManyToMany, "user_release_starred", "", Wt::Dbo::OnDeleteCascade);
Wt::Dbo::hasMany(a, _starredTracks, Wt::Dbo::ManyToMany, "user_track_starred", "", Wt::Dbo::OnDeleteCascade);
}
private:
@@ -132,7 +153,10 @@ class User : public Wt::Dbo::Dbo<User>
bool _repeatAll {};
bool _radio {};
Wt::Dbo::collection< Wt::Dbo::ptr<TrackList> > _tracklists;
Wt::Dbo::collection<Wt::Dbo::ptr<TrackList>> _tracklists;
Wt::Dbo::collection<Wt::Dbo::ptr<Artist>> _starredArtists;
Wt::Dbo::collection<Wt::Dbo::ptr<Release>> _starredReleases;
Wt::Dbo::collection<Wt::Dbo::ptr<Track>> _starredTracks;
};