1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 17:06:17 +00:00

Added method to list genres

This commit is contained in:
spl0k 2018-12-08 17:18:58 +01:00
parent 9af8ee22e0
commit ac306f2725
7 changed files with 59 additions and 13 deletions

View File

@ -15,7 +15,7 @@ Current supported features are:
* starred tracks/albums and ratings * starred tracks/albums and ratings
* [Last.FM][lastfm] scrobbling * [Last.FM][lastfm] scrobbling
_Supysonic_ currently targets the version 1.8.0 of the _Subsonic_ API. For more _Supysonic_ currently targets the version 1.9.0 of the _Subsonic_ API. For more
details, go check the [API implementation status][docs-api]. details, go check the [API implementation status][docs-api].
[subsonic]: http://www.subsonic.org/ [subsonic]: http://www.subsonic.org/
@ -219,7 +219,7 @@ For more details on the command-line usage, take a look at the
The Subsonic API provides several authentication methods. One of them, known as The Subsonic API provides several authentication methods. One of them, known as
_token authentication_ was added with API version 1.13.0. As Supysonic currently _token authentication_ was added with API version 1.13.0. As Supysonic currently
targets API version 1.8.0, the token based method isn't supported. So if your targets API version 1.9.0, the token based method isn't supported. So if your
client offers you the option, you'll have to disable the token based client offers you the option, you'll have to disable the token based
authentication for it to work. authentication for it to work.

View File

@ -4,7 +4,7 @@ This page lists all the API methods and their parameters up to the version
1.16.0 (Subsonic 6.1.2). Here you'll find details about which API features 1.16.0 (Subsonic 6.1.2). Here you'll find details about which API features
_Supysonic_ support, plan on supporting, or won't. _Supysonic_ support, plan on supporting, or won't.
At the moment, the current target API version is 1.8.0. At the moment, the current target API version is 1.9.0.
The following information was gathered by _diff_-ing various snapshots of the The following information was gathered by _diff_-ing various snapshots of the
[Subsonic API page](http://www.subsonic.org/pages/api.jsp). [Subsonic API page](http://www.subsonic.org/pages/api.jsp).
@ -34,7 +34,7 @@ or with version 1.8.0.
| [`getMusicFolders`](#getmusicfolders) | | ✔️ | | [`getMusicFolders`](#getmusicfolders) | | ✔️ |
| [`getIndexes`](#getindexes) | | ✔️ | | [`getIndexes`](#getindexes) | | ✔️ |
| [`getMusicDirectory`](#getmusicdirectory) | | ✔️ | | [`getMusicDirectory`](#getmusicdirectory) | | ✔️ |
| [`getGenres`](#getgenres) | 1.9.0 | 📅 | | [`getGenres`](#getgenres) | 1.9.0 | ✔️ |
| [`getArtists`](#getartists) | | ✔️ | | [`getArtists`](#getartists) | | ✔️ |
| [`getArtist`](#getartist) | | ✔️ | | [`getArtist`](#getartist) | | ✔️ |
| [`getAlbum`](#getalbum) | | ✔️ | | [`getAlbum`](#getalbum) | | ✔️ |
@ -166,7 +166,7 @@ No parameter
| `id` | | ✔️ | | `id` | | ✔️ |
#### `getGenres` #### `getGenres`
📅 1.9.0 ✔️ 1.9.0
No parameter No parameter
#### `getArtists` #### `getArtists`

View File

@ -7,7 +7,7 @@
# #
# Distributed under terms of the GNU AGPLv3 license. # Distributed under terms of the GNU AGPLv3 license.
API_VERSION = '1.8.0' API_VERSION = '1.9.0'
import binascii import binascii
import uuid import uuid

View File

@ -11,7 +11,7 @@ import string
import uuid import uuid
from flask import request from flask import request
from pony.orm import ObjectNotFound from pony.orm import ObjectNotFound, select
from ..db import Folder, Artist, Album, Track from ..db import Folder, Artist, Album, Track
from ..py23 import dict from ..py23 import dict
@ -93,6 +93,12 @@ def show_directory():
return request.formatter('directory', directory) return request.formatter('directory', directory)
@api.route('/getGenres.view', methods = [ 'GET', 'POST' ])
def list_genres():
return request.formatter('genres', dict(
genre = [ dict(_value_ = genre) for genre in select(t.genre for t in Track if t.genre) ]
))
@api.route('/getArtists.view', methods = [ 'GET', 'POST' ]) @api.route('/getArtists.view', methods = [ 'GET', 'POST' ])
def list_artists(): def list_artists():
# According to the API page, there are no parameters? # According to the API page, there are no parameters?

View File

@ -26,7 +26,7 @@ class ApiTestBase(TestBase):
def setUp(self): def setUp(self):
super(ApiTestBase, self).setUp() super(ApiTestBase, self).setUp()
xsd = etree.parse('tests/assets/subsonic-rest-api-1.8.0.xsd') xsd = etree.parse('tests/assets/subsonic-rest-api-1.9.0.xsd')
self.schema = etree.XMLSchema(xsd) self.schema = etree.XMLSchema(xsd)
def _find(self, xml, path): def _find(self, xml, path):
@ -68,7 +68,7 @@ class ApiTestBase(TestBase):
if tag and not isinstance(tag, strtype): if tag and not isinstance(tag, strtype):
raise TypeError("'tag', expecting a str, got " + type(tag).__name__) raise TypeError("'tag', expecting a str, got " + type(tag).__name__)
args.update({ 'c': 'tests', 'v': '1.8.0' }) args.update({ 'c': 'tests', 'v': '1.9.0' })
if 'u' not in args: if 'u' not in args:
args.update({ 'u': 'alice', 'p': 'Alic3' }) args.update({ 'u': 'alice', 'p': 'Alic3' })

View File

@ -32,7 +32,7 @@ class TranscodingTestCase(ApiTestBase):
self.trackid = Track.get().id self.trackid = Track.get().id
def _stream(self, **kwargs): def _stream(self, **kwargs):
kwargs.update({ 'u': 'alice', 'p': 'Alic3', 'c': 'tests', 'v': '1.8.0', 'id': self.trackid }) kwargs.update({ 'u': 'alice', 'p': 'Alic3', 'c': 'tests', 'v': '1.9.0', 'id': self.trackid })
rv = self.client.get('/rest/stream.view', query_string = kwargs) rv = self.client.get('/rest/stream.view', query_string = kwargs)
self.assertEqual(rv.status_code, 200) self.assertEqual(rv.status_code, 200)

View File

@ -4,7 +4,7 @@
targetNamespace="http://subsonic.org/restapi" targetNamespace="http://subsonic.org/restapi"
attributeFormDefault="unqualified" attributeFormDefault="unqualified"
elementFormDefault="qualified" elementFormDefault="qualified"
version="1.8.0"> version="1.9.0">
<xs:element name="subsonic-response" type="sub:Response"/> <xs:element name="subsonic-response" type="sub:Response"/>
@ -13,6 +13,7 @@
<xs:element name="musicFolders" type="sub:MusicFolders" minOccurs="1" maxOccurs="1"/> <xs:element name="musicFolders" type="sub:MusicFolders" minOccurs="1" maxOccurs="1"/>
<xs:element name="indexes" type="sub:Indexes" minOccurs="1" maxOccurs="1"/> <xs:element name="indexes" type="sub:Indexes" minOccurs="1" maxOccurs="1"/>
<xs:element name="directory" type="sub:Directory" minOccurs="1" maxOccurs="1"/> <xs:element name="directory" type="sub:Directory" minOccurs="1" maxOccurs="1"/>
<xs:element name="genres" type="sub:Genres" minOccurs="1" maxOccurs="1"/>
<xs:element name="artists" type="sub:ArtistsID3" minOccurs="1" maxOccurs="1"/> <xs:element name="artists" type="sub:ArtistsID3" minOccurs="1" maxOccurs="1"/>
<xs:element name="artist" type="sub:ArtistWithAlbumsID3" minOccurs="1" maxOccurs="1"/> <xs:element name="artist" type="sub:ArtistWithAlbumsID3" minOccurs="1" maxOccurs="1"/>
<xs:element name="album" type="sub:AlbumWithSongsID3" minOccurs="1" maxOccurs="1"/> <xs:element name="album" type="sub:AlbumWithSongsID3" minOccurs="1" maxOccurs="1"/>
@ -32,9 +33,12 @@
<xs:element name="chatMessages" type="sub:ChatMessages" minOccurs="1" maxOccurs="1"/> <xs:element name="chatMessages" type="sub:ChatMessages" minOccurs="1" maxOccurs="1"/>
<xs:element name="albumList" type="sub:AlbumList" minOccurs="1" maxOccurs="1"/> <xs:element name="albumList" type="sub:AlbumList" minOccurs="1" maxOccurs="1"/>
<xs:element name="albumList2" type="sub:AlbumList2" minOccurs="1" maxOccurs="1"/> <xs:element name="albumList2" type="sub:AlbumList2" minOccurs="1" maxOccurs="1"/>
<xs:element name="randomSongs" type="sub:RandomSongs" minOccurs="1" maxOccurs="1"/> <xs:element name="randomSongs" type="sub:Songs" minOccurs="1" maxOccurs="1"/>
<xs:element name="songsByGenre" type="sub:Songs" minOccurs="1" maxOccurs="1"/>
<xs:element name="lyrics" type="sub:Lyrics" minOccurs="1" maxOccurs="1"/> <xs:element name="lyrics" type="sub:Lyrics" minOccurs="1" maxOccurs="1"/>
<xs:element name="podcasts" type="sub:Podcasts" minOccurs="1" maxOccurs="1"/> <xs:element name="podcasts" type="sub:Podcasts" minOccurs="1" maxOccurs="1"/>
<xs:element name="internetRadioStations" type="sub:InternetRadioStations" minOccurs="1" maxOccurs="1"/>
<xs:element name="bookmarks" type="sub:Bookmarks" minOccurs="1" maxOccurs="1"/>
<xs:element name="shares" type="sub:Shares" minOccurs="1" maxOccurs="1"/> <xs:element name="shares" type="sub:Shares" minOccurs="1" maxOccurs="1"/>
<xs:element name="starred" type="sub:Starred" minOccurs="1" maxOccurs="1"/> <xs:element name="starred" type="sub:Starred" minOccurs="1" maxOccurs="1"/>
<xs:element name="starred2" type="sub:Starred2" minOccurs="1" maxOccurs="1"/> <xs:element name="starred2" type="sub:Starred2" minOccurs="1" maxOccurs="1"/>
@ -89,6 +93,12 @@
<xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType> </xs:complexType>
<xs:complexType name="Genres">
<xs:sequence>
<xs:element name="genre" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ArtistsID3"> <xs:complexType name="ArtistsID3">
<xs:sequence> <xs:sequence>
<xs:element name="index" type="sub:IndexID3" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="index" type="sub:IndexID3" minOccurs="0" maxOccurs="unbounded"/>
@ -323,7 +333,7 @@
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
<xs:complexType name="RandomSongs"> <xs:complexType name="Songs">
<xs:sequence> <xs:sequence>
<xs:element name="song" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="song" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence> </xs:sequence>
@ -374,6 +384,36 @@
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
<xs:complexType name="InternetRadioStations">
<xs:sequence>
<xs:element name="internetRadioStation" type="sub:InternetRadioStation" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="InternetRadioStation">
<xs:attribute name="id" type="xs:string" use="required"/>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="streamUrl" type="xs:string" use="required"/>
<xs:attribute name="homePageUrl" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="Bookmarks">
<xs:sequence>
<xs:element name="bookmark" type="sub:Bookmark" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Bookmark">
<xs:sequence>
<xs:element name="entry" type="sub:Child" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="position" type="xs:long" use="required"/> <!-- In milliseconds -->
<xs:attribute name="username" type="xs:string" use="required"/>
<xs:attribute name="comment" type="xs:string" use="optional"/>
<xs:attribute name="created" type="xs:dateTime" use="required"/>
<xs:attribute name="changed" type="xs:dateTime" use="required"/>
</xs:complexType>
<xs:complexType name="Shares"> <xs:complexType name="Shares">
<xs:sequence> <xs:sequence>
<xs:element name="share" type="sub:Share" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="share" type="sub:Share" minOccurs="0" maxOccurs="unbounded"/>