From c8a9ae89e1aa24cd7b12260cf5c10283ace2f0fa Mon Sep 17 00:00:00 2001 From: dave Date: Sat, 7 Apr 2018 16:26:27 -0700 Subject: [PATCH] basic podcast browsing apis --- pysonic/api.py | 37 ++++++++++++++++- pysonic/database.py | 99 +++++++++------------------------------------ pysonic/library.py | 1 + pysonic/schema.py | 94 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 150 insertions(+), 81 deletions(-) create mode 100644 pysonic/schema.py diff --git a/pysonic/api.py b/pysonic/api.py index ba1c052..63fd925 100644 --- a/pysonic/api.py +++ b/pysonic/api.py @@ -275,7 +275,7 @@ class PysonicSubsonicApi(object): playlistRole="true", coverArtRole="false", commentRole="false", - podcastRole="false", + podcastRole="true", streamRole="true", jukeboxRole="false", shareRole="true", @@ -525,3 +525,38 @@ class PysonicSubsonicApi(object): self.library.delete_playlist(plinfo["id"]) return ApiResponse() + + # + # + # + # + # Podcast related endpoints + @cherrypy.expose + @formatresponse + def getPodcasts_view(self, includeEpisodes=False, **kwargs): + #TODO implement includeEpisodes + response = ApiResponse() + response.add_child("podcasts") + for podcast in self.library.get_podcasts(): + response.add_child("channel", + _parent="podcasts", + id=podcast["id"], + title=podcast["title"], + url=podcast["url"], + description=podcast["description"], + # coverArt="pl-1" + # originalImageUrl="", + status="completed" # or "downloading" + ) + return response + + @cherrypy.expose + @formatresponse + def createPodcastChannel_view(self, url, **kwargs): + self.library.db.add_postcast(url) + return ApiResponse() + + @cherrypy.expose + @formatresponse + def refreshPodcasts_view(self, **kwargs): + return ApiResponse() diff --git a/pysonic/database.py b/pysonic/database.py index cdcc2f7..d9b08db 100644 --- a/pysonic/database.py +++ b/pysonic/database.py @@ -4,6 +4,8 @@ from hashlib import sha512 from time import time from contextlib import closing from collections import Iterable +from pysonic.schema import table_quers + logging = logging.getLogger("database") keys_in_table = ["title", "album", "artist", "type", "size"] @@ -56,91 +58,13 @@ class PysonicDatabase(object): def migrate(self): # Create db - queries = ["""CREATE TABLE 'libraries' ( - 'id' INTEGER PRIMARY KEY AUTOINCREMENT, - 'name' TEXT, - 'path' TEXT UNIQUE);""", - """CREATE TABLE 'dirs' ( - 'id' INTEGER PRIMARY KEY AUTOINCREMENT, - 'library' INTEGER, - 'parent' INTEGER, - 'name' TEXT, - UNIQUE(parent, name) - )""", - """CREATE TABLE 'genres' ( - 'id' INTEGER PRIMARY KEY AUTOINCREMENT, - 'name' TEXT UNIQUE)""", - """CREATE TABLE 'artists' ( - 'id' INTEGER PRIMARY KEY AUTOINCREMENT, - 'libraryid' INTEGER, - 'dir' INTEGER UNIQUE, - 'name' TEXT)""", - """CREATE TABLE 'albums' ( - 'id' INTEGER PRIMARY KEY AUTOINCREMENT, - 'artistid' INTEGER, - 'coverid' INTEGER, - 'dir' INTEGER, - 'name' TEXT, - 'added' INTEGER NOT NULL DEFAULT -1, - 'played' INTEGER, - 'plays' INTEGER NOT NULL DEFAULT 0, - UNIQUE (artistid, dir));""", - """CREATE TABLE 'songs' ( - 'id' INTEGER PRIMARY KEY AUTOINCREMENT, - 'library' INTEGER, - 'albumid' BOOLEAN, - 'genre' INTEGER DEFAULT NULL, - 'file' TEXT UNIQUE, -- path from the library root - 'size' INTEGER NOT NULL DEFAULT -1, - 'title' TEXT NOT NULL, - 'lastscan' INTEGER NOT NULL DEFAULT -1, - 'format' TEXT, - 'length' INTEGER, - 'bitrate' INTEGER, - 'track' INTEGER, - 'year' INTEGER - )""", - """CREATE TABLE 'covers' ( - 'id' INTEGER PRIMARY KEY AUTOINCREMENT, - 'library' INTEGER, - 'type' TEXT, - 'size' TEXT, - 'path' TEXT UNIQUE);""", - """CREATE TABLE 'users' ( - 'id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - 'username' TEXT UNIQUE NOT NULL, - 'password' TEXT NOT NULL, - 'admin' BOOLEAN DEFAULT 0, - 'email' TEXT)""", - """CREATE TABLE 'stars' ( - 'userid' INTEGER, - 'songid' INTEGER, - primary key ('userid', 'songid'))""", - """CREATE TABLE 'playlists' ( - 'id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - 'ownerid' INTEGER, - 'name' TEXT, - 'public' BOOLEAN, - 'created' INTEGER, - 'changed' INTEGER, - 'cover' INTEGER, - UNIQUE ('ownerid', 'name'))""", - """CREATE TABLE 'playlist_entries' ( - 'playlistid' INTEGER, - 'songid' INTEGER, - 'order' FLOAT)""", - """CREATE TABLE 'meta' ( - 'key' TEXT PRIMARY KEY NOT NULL, - 'value' TEXT);""", - """INSERT INTO meta VALUES ('db_version', '1');"""] - with closing(self.db.cursor()) as cursor: cursor.execute("SELECT * FROM sqlite_master WHERE type='table' AND name='meta'") - # Initialize DB if len(cursor.fetchall()) == 0: logging.warning("Initializing database") - for query in queries: + for query in table_quers: + print(query) cursor.execute(query) cursor.execute("COMMIT") else: @@ -495,3 +419,18 @@ class PysonicDatabase(object): return cursor.execute("SELECT * FROM users WHERE {}=?;".format(column), (user, )).fetchall()[0] except IndexError: raise NotFoundError("User doesn't exist") + + # + # Podcast related + @readcursor + def get_podcasts(self, cursor): + podcasts = [] + for row in cursor.execute("SELECT * FROM podcasts ORDER BY title ASC"): #TODO order by newest episode + podcasts.append(row) + return podcasts + + @readcursor + def add_postcast(self, cursor, url, title=None): + cursor.execute("INSERT INTO podcasts (title, url) VALUES (?, ?)", + (title if title else url, url, )) + cursor.execute("COMMIT") diff --git a/pysonic/library.py b/pysonic/library.py index 92c8d28..4a4d435 100644 --- a/pysonic/library.py +++ b/pysonic/library.py @@ -37,6 +37,7 @@ class PysonicLibrary(object): self.get_albums = self.db.get_albums # self.get_song = self.db.get_song # self.get_cover = self.db.get_cover + self.get_podcasts = self.db.get_podcasts self.scanner = PysonicFilesystemScanner(self) logging.info("library ready") diff --git a/pysonic/schema.py b/pysonic/schema.py new file mode 100644 index 0000000..93fb0ba --- /dev/null +++ b/pysonic/schema.py @@ -0,0 +1,94 @@ +table_quers = ["""CREATE TABLE 'libraries' ( + 'id' INTEGER PRIMARY KEY AUTOINCREMENT, + 'name' TEXT, + 'path' TEXT UNIQUE);""", + """CREATE TABLE 'dirs' ( + 'id' INTEGER PRIMARY KEY AUTOINCREMENT, + 'library' INTEGER, + 'parent' INTEGER, + 'name' TEXT, + UNIQUE(parent, name) + )""", + """CREATE TABLE 'genres' ( + 'id' INTEGER PRIMARY KEY AUTOINCREMENT, + 'name' TEXT UNIQUE)""", + """CREATE TABLE 'artists' ( + 'id' INTEGER PRIMARY KEY AUTOINCREMENT, + 'libraryid' INTEGER, + 'dir' INTEGER UNIQUE, + 'name' TEXT)""", + """CREATE TABLE 'albums' ( + 'id' INTEGER PRIMARY KEY AUTOINCREMENT, + 'artistid' INTEGER, + 'coverid' INTEGER, + 'dir' INTEGER, + 'name' TEXT, + 'added' INTEGER NOT NULL DEFAULT -1, + 'played' INTEGER, + 'plays' INTEGER NOT NULL DEFAULT 0, + UNIQUE (artistid, dir));""", + """CREATE TABLE 'songs' ( + 'id' INTEGER PRIMARY KEY AUTOINCREMENT, + 'library' INTEGER, + 'albumid' BOOLEAN, + 'genre' INTEGER DEFAULT NULL, + 'file' TEXT UNIQUE, -- path from the library root + 'size' INTEGER NOT NULL DEFAULT -1, + 'title' TEXT NOT NULL, + 'lastscan' INTEGER NOT NULL DEFAULT -1, + 'format' TEXT, + 'length' INTEGER, + 'bitrate' INTEGER, + 'track' INTEGER, + 'year' INTEGER + )""", + """CREATE TABLE 'covers' ( + 'id' INTEGER PRIMARY KEY AUTOINCREMENT, + 'library' INTEGER, + 'type' TEXT, + 'size' TEXT, + 'path' TEXT UNIQUE);""", + """CREATE TABLE 'users' ( + 'id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + 'username' TEXT UNIQUE NOT NULL, + 'password' TEXT NOT NULL, + 'admin' BOOLEAN DEFAULT 0, + 'email' TEXT)""", + """CREATE TABLE 'stars' ( + 'userid' INTEGER, + 'songid' INTEGER, + primary key ('userid', 'songid'))""", + """CREATE TABLE 'playlists' ( + 'id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + 'ownerid' INTEGER, + 'name' TEXT, + 'public' BOOLEAN, + 'created' INTEGER, + 'changed' INTEGER, + 'cover' INTEGER, + UNIQUE ('ownerid', 'name'))""", + """CREATE TABLE 'playlist_entries' ( + 'playlistid' INTEGER, + 'songid' INTEGER, + 'order' FLOAT)""", + """CREATE TABLE 'podcasts' ( + 'id' INTEGER PRIMARY KEY AUTOINCREMENT, + 'lastscan' INTEGER NOT NULL DEFAULT 0, + 'interval' INTEGER NOT NULL DEFAULT 60, + 'url' TEXT UNIQUE, + 'title' TEXT NOT NULL, + 'description' TEXT, + 'cover' INTEGER, + 'rss_cover' TEXT, + 'status' TEXT)""", + """CREATE TABLE 'podcast_episodes' ( + 'id' INTEGER PRIMARY KEY AUTOINCREMENT, + 'podcastid' INTEGER, + 'date' INTEGER + 'title' TEXT NOT NULL, + 'description' TEXT, + 'status' TEXT)""", + """CREATE TABLE 'meta' ( + 'key' TEXT PRIMARY KEY NOT NULL, + 'value' TEXT);""", + """INSERT INTO meta VALUES ('db_version', '1');"""]