mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-03 20:13:02 +00:00
add api docs for artist routes
+ extract hash and limit schemas
This commit is contained in:
committed by
Mungai Njoroge
parent
9e50eb4395
commit
7d064a8562
+16
-4
@@ -2,6 +2,7 @@
|
||||
This module combines all API blueprints into a single Flask app instance.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
from flask_cors import CORS
|
||||
from flask_compress import Compress
|
||||
|
||||
@@ -28,6 +29,19 @@ from app.api import (
|
||||
getall,
|
||||
)
|
||||
|
||||
open_api_description = f"""
|
||||
The REST API exposed by your Swing Music server
|
||||
|
||||
### Definition of terms:
|
||||
|
||||
#### 1. `limit`: The number of items to return.
|
||||
|
||||
In endpoints that request multiple lists of items, this represents the number of items to return for each list.
|
||||
|
||||
---
|
||||
|
||||
[MIT License](https://github.com/swing-opensource/swingmusic?tab=MIT-1-ov-file#MIT-1-ov-file) | Copyright (c) {datetime.datetime.now().year} [Mungai Njoroge](https://mungai.vercel.app)
|
||||
"""
|
||||
|
||||
def create_api():
|
||||
"""
|
||||
@@ -36,9 +50,7 @@ def create_api():
|
||||
api_info = Info(
|
||||
title=f"Swing Music",
|
||||
version=f"v{Keys.SWINGMUSIC_APP_VERSION}",
|
||||
license={"name": "MIT", "url": "https://github.com/swing-opensource/swingmusic?tab=MIT-1-ov-file#MIT-1-ov-file"},
|
||||
contact={"name": "Mungai Njoroge", "url": "https://mungai.vercel.app", "email": "geoffreymungai45@gmail.com"},
|
||||
description="The REST API exposed by your Swing Music server",
|
||||
description=open_api_description,
|
||||
)
|
||||
|
||||
app = OpenAPI(__name__, info=api_info)
|
||||
@@ -52,7 +64,7 @@ def create_api():
|
||||
|
||||
with app.app_context():
|
||||
app.register_api(album.api)
|
||||
app.register_blueprint(artist.api)
|
||||
app.register_api(artist.api)
|
||||
app.register_blueprint(send_file.api)
|
||||
app.register_blueprint(search.api)
|
||||
app.register_blueprint(folder.api)
|
||||
|
||||
+33
-48
@@ -7,6 +7,7 @@ import random
|
||||
from flask_openapi3 import Tag
|
||||
from flask_openapi3 import APIBlueprint
|
||||
from pydantic import BaseModel, Field
|
||||
from app.api.apischemas import AlbumHashSchema, AlbumLimitSchema, ArtistHashSchema
|
||||
|
||||
from app.db.sqlite.albumcolors import SQLiteAlbumMethods as adb
|
||||
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
|
||||
@@ -23,22 +24,15 @@ from app.utils.hashing import create_hash
|
||||
get_albums_by_albumartist = adb.get_albums_by_albumartist
|
||||
check_is_fav = favdb.check_is_favorite
|
||||
|
||||
book_tag = Tag(name="Album", description="Single album")
|
||||
api = APIBlueprint("album", __name__, url_prefix="", abp_tags=[book_tag])
|
||||
bp_tag = Tag(name="Album", description="Single album")
|
||||
api = APIBlueprint("album", __name__, url_prefix="", abp_tags=[bp_tag])
|
||||
|
||||
|
||||
class GetAlbumBody(BaseModel):
|
||||
albumhash: str = Field(
|
||||
description="The hash of the album to get",
|
||||
example="49e4819273",
|
||||
min_length=Defaults.HASH_LENGTH,
|
||||
max_length=Defaults.HASH_LENGTH,
|
||||
)
|
||||
|
||||
|
||||
@api.post("/album", summary="Get album")
|
||||
def get_album_tracks_and_info(body: GetAlbumBody):
|
||||
@api.post("/album")
|
||||
def get_album_tracks_and_info(body: AlbumHashSchema):
|
||||
"""
|
||||
Get album and tracks
|
||||
|
||||
Returns album info and tracks for the given albumhash.
|
||||
"""
|
||||
albumhash = body.albumhash
|
||||
@@ -84,43 +78,39 @@ def get_album_tracks_and_info(body: GetAlbumBody):
|
||||
"info": album,
|
||||
}
|
||||
|
||||
class GetAlbumTracksQuery(BaseModel):
|
||||
albumhash: str = Field(
|
||||
description="The hash of the album",
|
||||
example="49e4819273",
|
||||
min_length=Defaults.HASH_LENGTH,
|
||||
max_length=Defaults.HASH_LENGTH,
|
||||
)
|
||||
|
||||
@api.get("/album/<albumhash>/tracks", summary="Get album tracks")
|
||||
def get_album_tracks(query: GetAlbumTracksQuery):
|
||||
@api.get("/album/<albumhash>/tracks")
|
||||
def get_album_tracks(path: AlbumHashSchema):
|
||||
"""
|
||||
Get album tracks
|
||||
|
||||
Returns all the tracks in the given album, sorted by disc and track number.
|
||||
NOTE: No album info is returned.
|
||||
"""
|
||||
tracks = TrackStore.get_tracks_by_albumhash(query.albumhash)
|
||||
tracks = TrackStore.get_tracks_by_albumhash(path.albumhash)
|
||||
tracks = sort_by_track_no(tracks)
|
||||
|
||||
return tracks
|
||||
|
||||
class GetMoreFromArtistsBody(BaseModel):
|
||||
|
||||
class GetMoreFromArtistsBody(AlbumLimitSchema):
|
||||
albumartists: str = Field(
|
||||
description="The artist hashes to get more albums from",
|
||||
example=Defaults.API_ARTISTHASH
|
||||
)
|
||||
limit: int = Field(
|
||||
description="The maximum number of albums to return per artist",
|
||||
example=7,
|
||||
default=7,
|
||||
example=Defaults.API_ARTISTHASH,
|
||||
)
|
||||
|
||||
base_title: str = Field(
|
||||
description="The base title of the album to exclude from the results.",
|
||||
example=Defaults.API_ALBUMNAME,
|
||||
default=None,
|
||||
)
|
||||
|
||||
@api.post("/album/from-artist", summary="More from artist")
|
||||
|
||||
@api.post("/album/from-artist")
|
||||
def get_more_from_artist(body: GetMoreFromArtistsBody):
|
||||
"""
|
||||
Get more from artist
|
||||
|
||||
Returns more albums from the given artist hashes.
|
||||
"""
|
||||
albumartists = body.albumartists
|
||||
@@ -151,7 +141,7 @@ def get_more_from_artist(body: GetMoreFromArtistsBody):
|
||||
return albums
|
||||
|
||||
|
||||
class GetAlbumVersionsBody(BaseModel):
|
||||
class GetAlbumVersionsBody(ArtistHashSchema):
|
||||
og_album_title: str = Field(
|
||||
description="The original album title (album.og_title)",
|
||||
example=Defaults.API_ALBUMNAME,
|
||||
@@ -160,14 +150,13 @@ class GetAlbumVersionsBody(BaseModel):
|
||||
description="The base title of the album to exclude from the results.",
|
||||
example=Defaults.API_ALBUMNAME,
|
||||
)
|
||||
artisthash: str = Field(
|
||||
description="The artist hash",
|
||||
example=Defaults.API_ARTISTHASH,
|
||||
)
|
||||
|
||||
@api.post("/album/other-versions", summary="Get other versions")
|
||||
|
||||
@api.post("/album/other-versions")
|
||||
def get_album_versions(body: GetAlbumVersionsBody):
|
||||
"""
|
||||
Get other versions
|
||||
|
||||
Returns other versions of the given album.
|
||||
"""
|
||||
og_album_title = body.og_album_title
|
||||
@@ -189,20 +178,16 @@ def get_album_versions(body: GetAlbumVersionsBody):
|
||||
|
||||
return albums
|
||||
|
||||
class GetSimilarAlbumsQuery(BaseModel):
|
||||
artisthash: str = Field(
|
||||
description="The artist hash",
|
||||
example=Defaults.API_ARTISTHASH,
|
||||
)
|
||||
limit: int = Field(
|
||||
description="The maximum number of albums to return",
|
||||
example=Defaults.API_CARD_LIMIT,
|
||||
default=Defaults.API_CARD_LIMIT,
|
||||
)
|
||||
|
||||
@api.get("/album/similar", summary="Get similar albums")
|
||||
class GetSimilarAlbumsQuery(ArtistHashSchema, AlbumLimitSchema):
|
||||
pass
|
||||
|
||||
|
||||
@api.get("/album/similar")
|
||||
def get_similar_albums(query: GetSimilarAlbumsQuery):
|
||||
"""
|
||||
Get similar albums
|
||||
|
||||
Returns similar albums to the given album.
|
||||
"""
|
||||
artisthash = query.artisthash
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
Reusable Pydantic basic schemas for the API
|
||||
"""
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.settings import Defaults
|
||||
|
||||
|
||||
|
||||
class AlbumHashSchema(BaseModel):
|
||||
"""
|
||||
Extending this class will give you a model with the `albumhash` field
|
||||
"""
|
||||
|
||||
albumhash: str = Field(
|
||||
description="The album hash",
|
||||
example=Defaults.API_ALBUMHASH,
|
||||
min_length=Defaults.HASH_LENGTH,
|
||||
max_length=Defaults.HASH_LENGTH,
|
||||
)
|
||||
|
||||
|
||||
class ArtistHashSchema(BaseModel):
|
||||
"""
|
||||
Extending this class will give you a model with the `artisthash` field
|
||||
"""
|
||||
|
||||
artisthash: str = Field(
|
||||
description="The artist hash",
|
||||
example=Defaults.API_ARTISTHASH,
|
||||
min_length=Defaults.HASH_LENGTH,
|
||||
max_length=Defaults.HASH_LENGTH,
|
||||
)
|
||||
|
||||
|
||||
class GenericLimitSchema(BaseModel):
|
||||
"""
|
||||
Extending this class will give you a model with the `limit` field
|
||||
"""
|
||||
|
||||
limit: int = Field(
|
||||
description="The number of items to return",
|
||||
example=Defaults.API_CARD_LIMIT,
|
||||
default=Defaults.API_CARD_LIMIT
|
||||
)
|
||||
|
||||
|
||||
# INFO: The following 3 classes are duplicated to specify the type of items
|
||||
class TrackLimitSchema(BaseModel):
|
||||
"""
|
||||
Extending this class will give you a model with the `limit` field
|
||||
"""
|
||||
|
||||
limit: int = Field(
|
||||
description="The number of tracks to return",
|
||||
example=Defaults.API_CARD_LIMIT,
|
||||
default=Defaults.API_CARD_LIMIT
|
||||
)
|
||||
|
||||
|
||||
class AlbumLimitSchema(BaseModel):
|
||||
"""
|
||||
Extending this class will give you a model with the `limit` field
|
||||
"""
|
||||
|
||||
limit: int = Field(
|
||||
description="The number of albums to return",
|
||||
example=Defaults.API_CARD_LIMIT,
|
||||
default=Defaults.API_CARD_LIMIT
|
||||
)
|
||||
|
||||
|
||||
class ArtistLimitSchema(BaseModel):
|
||||
"""
|
||||
Extending this class will give you a model with the `limit` field
|
||||
"""
|
||||
|
||||
limit: int = Field(
|
||||
description="The number of artists to return",
|
||||
example=Defaults.API_CARD_LIMIT,
|
||||
default=Defaults.API_CARD_LIMIT
|
||||
)
|
||||
+31
-29
@@ -1,11 +1,15 @@
|
||||
"""
|
||||
Contains all the artist(s) routes.
|
||||
"""
|
||||
|
||||
import math
|
||||
import random
|
||||
from datetime import datetime
|
||||
|
||||
from flask import Blueprint, request
|
||||
from flask import request
|
||||
from flask_openapi3 import APIBlueprint, Tag
|
||||
from pydantic import BaseModel, Field
|
||||
from app.api.apischemas import AlbumLimitSchema, ArtistHashSchema, ArtistLimitSchema, TrackLimitSchema
|
||||
|
||||
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
|
||||
from app.db.sqlite.lastfm.similar_artists import SQLiteLastFMSimilarArtists as fmdb
|
||||
@@ -16,20 +20,19 @@ from app.store.albums import AlbumStore
|
||||
from app.store.artists import ArtistStore
|
||||
from app.store.tracks import TrackStore
|
||||
|
||||
api = Blueprint("artist", __name__, url_prefix="/")
|
||||
bp_tag = Tag(name="Artist", description="Single artist")
|
||||
api = APIBlueprint("artist", __name__, url_prefix="/", abp_tags=[bp_tag])
|
||||
|
||||
|
||||
@api.route("/artist/<artisthash>", methods=["GET"])
|
||||
def get_artist(artisthash: str):
|
||||
@api.get("/artist/<string:artisthash>")
|
||||
def get_artist(path: ArtistHashSchema, query: TrackLimitSchema):
|
||||
"""
|
||||
Get artist data.
|
||||
|
||||
Returns artist data, tracks and genres for the given artisthash.
|
||||
"""
|
||||
limit = request.args.get("limit")
|
||||
|
||||
if limit is None:
|
||||
limit = 6
|
||||
|
||||
limit = int(limit)
|
||||
artisthash = path.artisthash
|
||||
limit = query.limit
|
||||
|
||||
artist = ArtistStore.get_artist_by_hash(artisthash)
|
||||
|
||||
@@ -79,16 +82,18 @@ def get_artist(artisthash: str):
|
||||
}
|
||||
|
||||
|
||||
@api.route("/artist/<artisthash>/albums", methods=["GET"])
|
||||
def get_artist_albums(artisthash: str):
|
||||
limit = request.args.get("limit")
|
||||
class GetArtistAlbumsQuery(AlbumLimitSchema):
|
||||
all: bool = Field(
|
||||
description="Whether to ignore limit and return all albums", default=False
|
||||
)
|
||||
|
||||
if limit is None:
|
||||
limit = 6
|
||||
|
||||
return_all = request.args.get("all")
|
||||
@api.get("/artist/<artisthash>/albums")
|
||||
def get_artist_albums(path: ArtistHashSchema, query: GetArtistAlbumsQuery):
|
||||
return_all = query.all
|
||||
artisthash = path.artisthash
|
||||
|
||||
limit = int(limit)
|
||||
limit = query.limit
|
||||
|
||||
all_albums = AlbumStore.get_albums_by_artisthash(artisthash)
|
||||
|
||||
@@ -170,29 +175,26 @@ def get_artist_albums(artisthash: str):
|
||||
}
|
||||
|
||||
|
||||
@api.route("/artist/<artisthash>/tracks", methods=["GET"])
|
||||
def get_all_artist_tracks(artisthash: str):
|
||||
@api.get("/artist/<artisthash>/tracks")
|
||||
def get_all_artist_tracks(path: ArtistHashSchema):
|
||||
"""
|
||||
Get all artist tracks
|
||||
|
||||
Returns all artists by a given artist.
|
||||
"""
|
||||
tracks = TrackStore.get_tracks_by_artisthash(artisthash)
|
||||
tracks = TrackStore.get_tracks_by_artisthash(path.artisthash)
|
||||
|
||||
return {"tracks": serialize_tracks(tracks)}
|
||||
|
||||
|
||||
@api.route("/artist/<artisthash>/similar", methods=["GET"])
|
||||
def get_similar_artists(artisthash: str):
|
||||
@api.get("/artist/<artisthash>/similar")
|
||||
def get_similar_artists(path: ArtistHashSchema, query: ArtistLimitSchema):
|
||||
"""
|
||||
Returns similar artists.
|
||||
"""
|
||||
limit = request.args.get("limit")
|
||||
limit = query.limit
|
||||
|
||||
if limit is None:
|
||||
limit = 6
|
||||
|
||||
limit = int(limit)
|
||||
|
||||
artist = ArtistStore.get_artist_by_hash(artisthash)
|
||||
artist = ArtistStore.get_artist_by_hash(path.artisthash)
|
||||
|
||||
if artist is None:
|
||||
return {"error": "Artist not found"}, 404
|
||||
|
||||
Reference in New Issue
Block a user