mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-23 01:16:18 +00:00
Added method to list genres
This commit is contained in:
parent
9af8ee22e0
commit
ac306f2725
@ -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.
|
||||||
|
|
||||||
|
@ -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`
|
||||||
|
@ -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
|
||||||
|
@ -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?
|
||||||
|
@ -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' })
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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"/>
|
Loading…
Reference in New Issue
Block a user