From 5a7fe3a013621426c7f043ff5e9455e95a99e634 Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 5 Oct 2020 22:12:40 -0700 Subject: [PATCH] playcount --- pysonic/api.py | 71 +++++++++++++++++++++++++++++++++------------ pysonic/database.py | 8 ++++- 2 files changed, 60 insertions(+), 19 deletions(-) diff --git a/pysonic/api.py b/pysonic/api.py index fd23e96..1207e9c 100644 --- a/pysonic/api.py +++ b/pysonic/api.py @@ -96,10 +96,10 @@ class PysonicSubsonicApi(object): title=album["name"], album=album["name"], artist=album["artistname"], - coverArt=album["coverid"] + coverArt=album["coverid"], + playCount=album["plays"], #year=TODO - # playCount="0" - # created="2016-05-08T05:31:31.000Z"/>) + #created="2016-05-08T05:31:31.000Z"/>) ) response.add_child("album", _parent="albumList", **album_kw) return response @@ -108,16 +108,26 @@ class PysonicSubsonicApi(object): @formatresponse def getMusicDirectory_view(self, id, **kwargs): """ - List an artist dir + List either and artist or album dir """ dir_id = int(id) dirtype, dirinfo, entity = self.library.db.get_subsonic_musicdir(dirid=dir_id) response = ApiResponse() - response.add_child("directory") - response.set_attrs(_path="directory", name=entity['name'], id=entity['id'], - parent=dirinfo['parent'], playCount=420) + # artists just need this + response.add_child("directory", + name=entity['name'], + id=entity['id']) + + if dirtype == "album": + # albums can also have + # - parent (album dir id) + # - playcount + response.set_attrs(_path="directory", + parent=dirinfo["parent"], + playCount=entity["plays"]) + #TODO Meeeeee for childtype, child in entity["children"]: # omit not dirs and media in browser # if not item["isdir"] and item["type"] not in MUSIC_TYPES: @@ -229,6 +239,29 @@ class PysonicSubsonicApi(object): @cherrypy.expose def getCoverArt_view(self, id, **kwargs): + """ + id is a string and if it's a number it's the album at for a...?? could be song or album either by id or directory id lol + it could also be: + pl-1234 - playlist + + for now, if the first character isn't a number, we error + """ + if id.startswith("pl-"): # get art from first track in playlist + playlist_id = int(id[len("pl-"):]) + _, songs = self.library.get_playlist(playlist_id) + for song in songs: + if song["albumcoverid"]: + id = song["albumcoverid"] + break + else: + raise cherrypy.HTTPError(404, message=f"no art for any of the {len(songs)} tracks in playlist {playlist_id}") + elif id[0] not in "0123456789": + #TODO + print("TODO support getCoverArt id format", repr(id)) + raise cherrypy.HTTPError(500, message=f"coverid format {repr(id)} not supported") + else: + id = int(id) + cover = self.library.get_cover(id) fpath = cover["_fullpath"] type2ct = { @@ -405,10 +438,10 @@ class PysonicSubsonicApi(object): title=album["name"], album=album["name"], artist=album["artistname"], - coverArt=album["coverid"] + coverArt=album["coverid"], + playCount=album["plays"], #year=TODO - # playCount="0" - # created="2016-05-08T05:31:31.000Z"/>) + #created="2016-05-08T05:31:31.000Z"/>) ) albums += 1 if albums >= albumCount: @@ -416,7 +449,7 @@ class PysonicSubsonicApi(object): # TODO make this more efficient songs = 0 - for song in self.library.db.get_songs(): + for song in self.library.db.get_songs(): #TODO Meeee too if query not in song["title"].lower(): continue @@ -436,7 +469,7 @@ class PysonicSubsonicApi(object): duration=song["length"], bitRate=song["bitrate"], path=song["file"], - playCount=420, + playCount=song["plays"], albumId=song["albumid"], type="music" # suffix="mp3" @@ -457,11 +490,13 @@ class PysonicSubsonicApi(object): @cherrypy.expose def savePlayQueue_view(self, id, current, position, **kwargs): - print("TODO save playqueue with items {} current {} position {}".format(id, current, position)) - - song = self.library.get_song(int(current)) + print("TODO save playqueue with items {} current {} position {}".format(id, repr(current), repr(position))) + current = int(current) + song = self.library.get_song(current) self.library.db.update_album_played(song['albumid'], time()) self.library.db.increment_album_plays(song['albumid']) + if int(position) == 0: + self.library.db.increment_track_plays(current) # TODO save playlist with items ['378', '386', '384', '380', '383'] current 383 position 4471 # id entries are strings! @@ -493,7 +528,7 @@ class PysonicSubsonicApi(object): duration=420, # changed="2018-04-05T23:23:38.263Z" # created="2018-04-05T23:23:38.252Z" - # coverArt="pl-1" + coverArt="pl-{}".format(playlist["id"]) ) return response @@ -529,9 +564,9 @@ class PysonicSubsonicApi(object): contentType=song["format"], # suffix="mp3" duration=song["length"], - bitRate=song["bitrate"] / 1024, + bitRate=song["bitrate"] / 1024 if song["bitrate"] else None, #TODO macro for this sort of logic path=song["file"], - playCount="1", + playCount=song["plays"], # created="2015-06-09T15:26:01.000Z" albumId=song["albumid"], artistId=song["artistid"], diff --git a/pysonic/database.py b/pysonic/database.py index d387ee9..d40aa0c 100644 --- a/pysonic/database.py +++ b/pysonic/database.py @@ -98,7 +98,8 @@ class PysonicDatabase(object): 'length' INTEGER, 'bitrate' INTEGER, 'track' INTEGER, - 'year' INTEGER + 'year' INTEGER, + 'plays' INTEGER NOT NULL DEFAULT 0 )""", """CREATE TABLE 'covers' ( 'id' INTEGER PRIMARY KEY AUTOINCREMENT, @@ -478,6 +479,11 @@ class PysonicDatabase(object): cursor.execute("UPDATE albums SET plays = plays + 1 WHERE id=?", (album_id, )) cursor.execute("COMMIT") + @readcursor + def increment_track_plays(self, cursor, track_id): + cursor.execute("UPDATE songs SET plays = plays + 1 WHERE id=?", (track_id, )) + cursor.execute("COMMIT") + # User related @readcursor def add_user(self, cursor, username, password, is_admin=False):