upgrade to sanic-ext
This commit is contained in:
parent
eeaa845dbd
commit
34134cd81c
|
@ -6,7 +6,7 @@ Why "Grzegorz"? [Great taste in humor of course!](https://youtu.be/t-fcrn1Edik)
|
||||||
|
|
||||||
When `grzegorz` starts, it launches an instance of MPV and maintains it. It is designed to be used as an info screen or HTPC, and supports multiple users to push changes to the MPV instance.
|
When `grzegorz` starts, it launches an instance of MPV and maintains it. It is designed to be used as an info screen or HTPC, and supports multiple users to push changes to the MPV instance.
|
||||||
|
|
||||||
The API is described and can be tested at `http:/localhost:8080/swagger` while the server is running. All API endpoints are available under `/api`
|
The API is described and can be tested at `http:/localhost:8080/docs/swagger` while the server is running. All API endpoints are available under `/api`
|
||||||
|
|
||||||
|
|
||||||
## How install and run it
|
## How install and run it
|
||||||
|
|
14
flake.nix
14
flake.nix
|
@ -22,14 +22,14 @@
|
||||||
in {
|
in {
|
||||||
|
|
||||||
packages = forAllSystems ({ system, pkgs, ...}: rec {
|
packages = forAllSystems ({ system, pkgs, ...}: rec {
|
||||||
sanic-openapi = with pkgs.python3.pkgs; buildPythonPackage rec {
|
sanic-ext = with pkgs.python3.pkgs; buildPythonPackage rec {
|
||||||
pname = "sanic-openapi";
|
pname = "sanic-ext";
|
||||||
version = "21.12.0";
|
version = "23.6.0";
|
||||||
src = fetchPypi {
|
src = fetchPypi {
|
||||||
inherit pname version;
|
inherit pname version;
|
||||||
hash = "sha256-fNpiI00IyWX3OeqsawWejyRNhwYdlzNcVyh/1q4Wv1I=";
|
hash = "sha256-gd0Ta2t7ef2otP7CRE2YIjlFVXecKYqJFVxnKHoYSQI=";
|
||||||
};
|
};
|
||||||
propagatedBuildInputs = [ sanic pyyaml ];
|
propagatedBuildInputs = [ pyyaml ];
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
};
|
};
|
||||||
grzegorz = with pkgs.python3.pkgs; buildPythonPackage {
|
grzegorz = with pkgs.python3.pkgs; buildPythonPackage {
|
||||||
|
@ -40,12 +40,12 @@
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
'';
|
'';
|
||||||
nativeBuildInputs = [ poetry-core ];
|
nativeBuildInputs = [ poetry-core ];
|
||||||
propagatedBuildInputs = [ sanic sanic-openapi youtube-dl mpv ];
|
propagatedBuildInputs = [ setuptools sanic sanic-ext youtube-dl mpv ];
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
};
|
};
|
||||||
grzegorz-run = pkgs.writeShellApplication {
|
grzegorz-run = pkgs.writeShellApplication {
|
||||||
name = "grzegorz-run";
|
name = "grzegorz-run";
|
||||||
runtimeInputs = [ grzegorz pkgs.mpv ];
|
runtimeInputs = [ (pkgs.python3.withPackages (ps: [ grzegorz ])) pkgs.mpv ];
|
||||||
text = ''
|
text = ''
|
||||||
TOOMANYARGS=()
|
TOOMANYARGS=()
|
||||||
if test -z "$*"; then
|
if test -z "$*"; then
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic_openapi import swagger_blueprint#, openapi2_blueprint
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import traceback
|
import traceback
|
||||||
from . import mpv
|
from . import mpv
|
||||||
|
@ -15,20 +14,11 @@ app = Sanic(module_name, env_prefix=module_name.upper() + '_')
|
||||||
app.blueprint(api.bp, url_prefix="/api")
|
app.blueprint(api.bp, url_prefix="/api")
|
||||||
app.add_task(api.PLAYLIST_DATA_CACHE.run())
|
app.add_task(api.PLAYLIST_DATA_CACHE.run())
|
||||||
|
|
||||||
|
|
||||||
# openapi:
|
# openapi:
|
||||||
app.config.API_VERSION = '1.0'
|
app.ext.openapi.describe("Grzegorz API",
|
||||||
app.config.API_TITLE = 'Grzegorz API'
|
version = "1.0.0.",
|
||||||
app.config.API_DESCRIPTION \
|
description = "The Grzegorz Brzeczyszczykiewicz API, used to control a running mpv instance",
|
||||||
= 'The Grzegorz Brzeczyszczykiewicz API, used to control a running mpv instance'
|
)
|
||||||
#app.config.API_TERMS_OF_SERVICE = ''# Supposed to be a link
|
|
||||||
app.config.API_PRODUCES_CONTENT_TYPES = ['application/json']
|
|
||||||
app.config.API_CONTACT_EMAIL = 'drift@pvv.ntnu.no'
|
|
||||||
#app.config.API_LICENSE_NAME = 'MIT'
|
|
||||||
#app.config.API_LICENSE_URL = 'todo'
|
|
||||||
|
|
||||||
#app.blueprint(openapi2_blueprint)
|
|
||||||
app.blueprint(swagger_blueprint)
|
|
||||||
|
|
||||||
|
|
||||||
# mpv:
|
# mpv:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from sanic import Request, Blueprint, response
|
from sanic import Request, Blueprint, response
|
||||||
from sanic_openapi import doc
|
from sanic_ext import openapi
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from .mpv import MPVControl
|
from .mpv import MPVControl
|
||||||
from .playlist_data import PlaylistDataCache
|
from .playlist_data import PlaylistDataCache
|
||||||
|
@ -44,15 +44,15 @@ PLAYLIST_DATA_CACHE = PlaylistDataCache(auto_fetch_data=True)
|
||||||
|
|
||||||
#routes:
|
#routes:
|
||||||
@bp.get("")
|
@bp.get("")
|
||||||
@doc.exclude(True)
|
@openapi.exclude(True)
|
||||||
@response_text
|
@response_text
|
||||||
async def root(request: Request):
|
async def root(request: Request):
|
||||||
return "Hello friend, I hope you're having a lovely day"
|
return "Hello friend, I hope you're having a lovely day"
|
||||||
|
|
||||||
@bp.post("/load")
|
@bp.post("/load")
|
||||||
@doc.summary("Add item to playlist")
|
@openapi.summary("Add item to playlist")
|
||||||
@doc.consumes({"path": doc.String("Link to the resource to enqueue")}, required=True)
|
@openapi.parameter("path", openapi.String(description="Link to the resource to enqueue"), required=True)
|
||||||
@doc.consumes({"body":doc.Dictionary(description="Any data you want stored with the queued item")}, location="body")
|
@openapi.parameter("body", openapi.Object(description="Any data you want stored with the queued item"), location="body")
|
||||||
@response_json
|
@response_json
|
||||||
async def loadfile(request: Request, mpv_control: MPVControl):
|
async def loadfile(request: Request, mpv_control: MPVControl):
|
||||||
if "path" not in request.args:
|
if "path" not in request.args:
|
||||||
|
@ -63,15 +63,15 @@ async def loadfile(request: Request, mpv_control: MPVControl):
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.get("/play")
|
@bp.get("/play")
|
||||||
@doc.summary("Check whether the player is paused or playing")
|
@openapi.summary("Check whether the player is paused or playing")
|
||||||
@response_json
|
@response_json
|
||||||
async def play_get(request: Request, mpv_control: MPVControl):
|
async def play_get(request: Request, mpv_control: MPVControl):
|
||||||
value = await mpv_control.pause_get() == False
|
value = await mpv_control.pause_get() == False
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.post("/play")
|
@bp.post("/play")
|
||||||
@doc.summary("Set whether the player is paused or playing")
|
@openapi.summary("Set whether the player is paused or playing")
|
||||||
@doc.consumes({"play": doc.Boolean("Whether to be playing or not")})
|
@openapi.parameter("play", openapi.Boolean(description="Whether to be playing or not"))
|
||||||
@response_json
|
@response_json
|
||||||
async def play_set(request: Request, mpv_control: MPVControl):
|
async def play_set(request: Request, mpv_control: MPVControl):
|
||||||
if "play" not in request.args:
|
if "play" not in request.args:
|
||||||
|
@ -81,15 +81,15 @@ async def play_set(request: Request, mpv_control: MPVControl):
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.get("/volume")
|
@bp.get("/volume")
|
||||||
@doc.summary("Get the current player volume")
|
@openapi.summary("Get the current player volume")
|
||||||
@response_json
|
@response_json
|
||||||
async def volume_get(request: Request, mpv_control: MPVControl):
|
async def volume_get(request: Request, mpv_control: MPVControl):
|
||||||
value = await mpv_control.volume_get()
|
value = await mpv_control.volume_get()
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.post("/volume")
|
@bp.post("/volume")
|
||||||
@doc.summary("Set the player volume")
|
@openapi.summary("Set the player volume")
|
||||||
@doc.consumes({"volume": doc.Integer("A number between 0 and 100")})
|
@openapi.parameter("volume", openapi.Integer(description="A number between 0 and 100"))
|
||||||
@response_json
|
@response_json
|
||||||
async def volume_set(request: Request, mpv_control: MPVControl):
|
async def volume_set(request: Request, mpv_control: MPVControl):
|
||||||
if "volume" not in request.args:
|
if "volume" not in request.args:
|
||||||
|
@ -99,7 +99,7 @@ async def volume_set(request: Request, mpv_control: MPVControl):
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.get("/time")
|
@bp.get("/time")
|
||||||
@doc.summary("Get current playback position")
|
@openapi.summary("Get current playback position")
|
||||||
@response_json
|
@response_json
|
||||||
async def time_get(request: Request, mpv_control: MPVControl):
|
async def time_get(request: Request, mpv_control: MPVControl):
|
||||||
value = {
|
value = {
|
||||||
|
@ -110,8 +110,9 @@ async def time_get(request: Request, mpv_control: MPVControl):
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.post("/time")
|
@bp.post("/time")
|
||||||
@doc.summary("Set playback position")
|
@openapi.summary("Set playback position")
|
||||||
@doc.consumes({"pos": doc.Float("Seconds to seek to"), "pos": doc.Integer("Percent to seek to")})
|
@openapi.parameter("pos", openapi.Float(description="Seconds to seek to"))
|
||||||
|
@openapi.parameter("percent", openapi.Integer(description="Percent to seek to"))
|
||||||
@response_json
|
@response_json
|
||||||
async def time_set(request: Request, mpv_control: MPVControl):
|
async def time_set(request: Request, mpv_control: MPVControl):
|
||||||
if "pos" in request.args:
|
if "pos" in request.args:
|
||||||
|
@ -123,7 +124,7 @@ async def time_set(request: Request, mpv_control: MPVControl):
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.get("/playlist")
|
@bp.get("/playlist")
|
||||||
@doc.summary("Get the current playlist")
|
@openapi.summary("Get the current playlist")
|
||||||
@response_json
|
@response_json
|
||||||
async def playlist_get(request: Request, mpv_control: MPVControl):
|
async def playlist_get(request: Request, mpv_control: MPVControl):
|
||||||
value = await mpv_control.playlist_get()
|
value = await mpv_control.playlist_get()
|
||||||
|
@ -136,22 +137,22 @@ async def playlist_get(request: Request, mpv_control: MPVControl):
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.post("/playlist/next")
|
@bp.post("/playlist/next")
|
||||||
@doc.summary("Skip to the next item in the playlist")
|
@openapi.summary("Skip to the next item in the playlist")
|
||||||
@response_json
|
@response_json
|
||||||
async def playlist_next(request: Request, mpv_control: MPVControl):
|
async def playlist_next(request: Request, mpv_control: MPVControl):
|
||||||
success = await mpv_control.playlist_next()
|
success = await mpv_control.playlist_next()
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.post("/playlist/previous")
|
@bp.post("/playlist/previous")
|
||||||
@doc.summary("Go back to the previous item in the playlist")
|
@openapi.summary("Go back to the previous item in the playlist")
|
||||||
@response_json
|
@response_json
|
||||||
async def playlist_previous(request: Request, mpv_control: MPVControl):
|
async def playlist_previous(request: Request, mpv_control: MPVControl):
|
||||||
success = await mpv_control.playlist_prev()
|
success = await mpv_control.playlist_prev()
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.post("/playlist/goto")
|
@bp.post("/playlist/goto")
|
||||||
@doc.summary("Go chosen item in the playlist")
|
@openapi.summary("Go chosen item in the playlist")
|
||||||
@doc.consumes({"index": doc.Integer("The 0 indexed playlist item to go to")}, required=True)
|
@openapi.parameter("index", openapi.Integer(description="The 0 indexed playlist item to go to"), required=True)
|
||||||
@response_json
|
@response_json
|
||||||
async def playlist_goto(request: Request, mpv_control: MPVControl):
|
async def playlist_goto(request: Request, mpv_control: MPVControl):
|
||||||
if "index" not in request.args:
|
if "index" not in request.args:
|
||||||
|
@ -161,8 +162,8 @@ async def playlist_goto(request: Request, mpv_control: MPVControl):
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.delete("/playlist")
|
@bp.delete("/playlist")
|
||||||
@doc.summary("Clears single item or whole playlist")
|
@openapi.summary("Clears single item or whole playlist")
|
||||||
@doc.consumes({"index": doc.Integer("Index to item in playlist to remove. If unset, the whole playlist is cleared")})
|
@openapi.parameter("index", openapi.Integer(description="Index to item in playlist to remove. If unset, the whole playlist is cleared"))
|
||||||
@response_json
|
@response_json
|
||||||
async def playlist_remove_or_clear(request: Request, mpv_control: MPVControl):
|
async def playlist_remove_or_clear(request: Request, mpv_control: MPVControl):
|
||||||
if "index" in request.args:
|
if "index" in request.args:
|
||||||
|
@ -174,15 +175,15 @@ async def playlist_remove_or_clear(request: Request, mpv_control: MPVControl):
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.post("/playlist/move")
|
@bp.post("/playlist/move")
|
||||||
@doc.summary("Move playlist item to new position")
|
@openapi.summary("Move playlist item to new position")
|
||||||
@doc.description(
|
@openapi.description(
|
||||||
"Move the playlist entry at index1, so that it takes the "
|
"Move the playlist entry at index1, so that it takes the "
|
||||||
"place of the entry index2. (Paradoxically, the moved playlist "
|
"place of the entry index2. (Paradoxically, the moved playlist "
|
||||||
"entry will not have the index value index2 after moving if index1 "
|
"entry will not have the index value index2 after moving if index1 "
|
||||||
"was lower than index2, because index2 refers to the target entry, "
|
"was lower than index2, because index2 refers to the target entry, "
|
||||||
"not the index the entry will have after moving.)")
|
"not the index the entry will have after moving.)")
|
||||||
@doc.consumes({"index2": int}, required=True)
|
@openapi.parameter("index2", int, required=True)
|
||||||
@doc.consumes({"index1": int}, required=True)
|
@openapi.parameter("index1", int, required=True)
|
||||||
@response_json
|
@response_json
|
||||||
async def playlist_move(request: Request, mpv_control: MPVControl):
|
async def playlist_move(request: Request, mpv_control: MPVControl):
|
||||||
if "index1" not in request.args or "index2" not in request.args:
|
if "index1" not in request.args or "index2" not in request.args:
|
||||||
|
@ -195,22 +196,22 @@ async def playlist_move(request: Request, mpv_control: MPVControl):
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.post("/playlist/shuffle")
|
@bp.post("/playlist/shuffle")
|
||||||
@doc.summary("Clears single item or whole playlist")
|
@openapi.summary("Clears single item or whole playlist")
|
||||||
@response_json
|
@response_json
|
||||||
async def playlist_shuffle(request: Request, mpv_control: MPVControl):
|
async def playlist_shuffle(request: Request, mpv_control: MPVControl):
|
||||||
success = await mpv_control.playlist_shuffle()
|
success = await mpv_control.playlist_shuffle()
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.get("/playlist/loop")
|
@bp.get("/playlist/loop")
|
||||||
@doc.summary("See whether it loops the playlist or not")
|
@openapi.summary("See whether it loops the playlist or not")
|
||||||
@response_json
|
@response_json
|
||||||
async def playlist_get_looping(request: Request, mpv_control: MPVControl):
|
async def playlist_get_looping(request: Request, mpv_control: MPVControl):
|
||||||
value = await mpv_control.playlist_get_looping()
|
value = await mpv_control.playlist_get_looping()
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@bp.post("/playlist/loop")
|
@bp.post("/playlist/loop")
|
||||||
@doc.summary("Sets whether to loop the playlist or not")
|
@openapi.summary("Sets whether to loop the playlist or not")
|
||||||
@doc.consumes({"loop": doc.Boolean("Whether to be looping or not")}, required=True)
|
@openapi.parameter("loop", openapi.Boolean(description="Whether to be looping or not"), required=True)
|
||||||
@response_json
|
@response_json
|
||||||
async def playlist_set_looping(request: Request, mpv_control: MPVControl):
|
async def playlist_set_looping(request: Request, mpv_control: MPVControl):
|
||||||
if "loop" not in request.args:
|
if "loop" not in request.args:
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,7 +10,8 @@ python = ">=3.7,<4.0"
|
||||||
mpv = ">=0.1" # TODO: do we use this?
|
mpv = ">=0.1" # TODO: do we use this?
|
||||||
youtube_dl = "^2021.12.17"
|
youtube_dl = "^2021.12.17"
|
||||||
sanic = ">=21.12.2"
|
sanic = ">=21.12.2"
|
||||||
sanic-openapi = ">=21.6.1"
|
sanic-ext = ">=23.6.0"
|
||||||
|
#sanic-openapi = ">=21.6.1"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
python-lsp-server = {extras = ["all"], version = "^1.3.3"}
|
python-lsp-server = {extras = ["all"], version = "^1.3.3"}
|
||||||
|
|
Loading…
Reference in New Issue