Merge pull request #316 from arcbtc/FastAPI

Front page loading!
This commit is contained in:
Arc 2021-08-23 18:23:58 +01:00 committed by GitHub
commit 89ffc621c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 84 deletions

View File

@ -38,6 +38,7 @@ async def create_app(config_object="lnbits.settings") -> FastAPI:
""" """
app = FastAPI() app = FastAPI()
app.mount("/static", StaticFiles(directory="lnbits/static"), name="static") app.mount("/static", StaticFiles(directory="lnbits/static"), name="static")
app.mount("/core/static", StaticFiles(directory="lnbits/core/static"), name="core_static")
origins = [ origins = [
"http://localhost", "http://localhost",

View File

@ -53,16 +53,16 @@ class CreateData(BaseModel):
price_per_ticket: int = Query(..., ge=0) price_per_ticket: int = Query(..., ge=0)
@events_ext.post("/api/v1/events") @events_ext.post("/api/v1/events")
@events_ext.put("/api/v1/events/<event_id>") @events_ext.put("/api/v1/events/{event_id}")
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
async def api_event_create(data: CreateData, event_id=None): async def api_event_create(data: CreateData, event_id=None):
if event_id: if event_id:
event = await get_event(event_id) event = await get_event(event_id)
if not event: if not event:
return jsonable_encoder({"message": "Form does not exist."}), HTTPStatus.NOT_FOUND return {"message": "Form does not exist."}, HTTPStatus.NOT_FOUND
if event.wallet != g.wallet.id: if event.wallet != g.wallet.id:
return jsonable_encoder({"message": "Not your event."}), HTTPStatus.FORBIDDEN return {"message": "Not your event."}, HTTPStatus.FORBIDDEN
event = await update_event(event_id, **data) event = await update_event(event_id, **data)
else: else:
@ -71,15 +71,15 @@ async def api_event_create(data: CreateData, event_id=None):
return event._asdict(), HTTPStatus.CREATED return event._asdict(), HTTPStatus.CREATED
@events_ext.delete("/api/v1/events/<event_id>") @events_ext.delete("/api/v1/events/{event_id}")
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
async def api_form_delete(event_id): async def api_form_delete(event_id):
event = await get_event(event_id) event = await get_event(event_id)
if not event: if not event:
return jsonable_encoder({"message": "Event does not exist."}), HTTPStatus.NOT_FOUND return {"message": "Event does not exist."}, HTTPStatus.NOT_FOUND
if event.wallet != g.wallet.id: if event.wallet != g.wallet.id:
return jsonable_encoder({"message": "Not your event."}), HTTPStatus.FORBIDDEN return {"message": "Not your event."}, HTTPStatus.FORBIDDEN
await delete_event(event_id) await delete_event(event_id)
return "", HTTPStatus.NO_CONTENT return "", HTTPStatus.NO_CONTENT
@ -105,11 +105,11 @@ class CreateTicketData(BaseModel):
name: str = Query(...) name: str = Query(...)
email: str email: str
@events_ext.post("/api/v1/tickets/<event_id>/<sats>") @events_ext.post("/api/v1/tickets/{event_id}/{sats}")
async def api_ticket_make_ticket(data: CreateTicketData, event_id, sats): async def api_ticket_make_ticket(data: CreateTicketData, event_id, sats):
event = await get_event(event_id) event = await get_event(event_id)
if not event: if not event:
return jsonable_encoder({"message": "Event does not exist."}), HTTPStatus.NOT_FOUND return {"message": "Event does not exist."}, HTTPStatus.NOT_FOUND
try: try:
payment_hash, payment_request = await create_invoice( payment_hash, payment_request = await create_invoice(
wallet_id=event.wallet, wallet_id=event.wallet,
@ -118,22 +118,19 @@ async def api_ticket_make_ticket(data: CreateTicketData, event_id, sats):
extra={"tag": "events"}, extra={"tag": "events"},
) )
except Exception as e: except Exception as e:
return jsonify({"message": str(e)}), HTTPStatus.INTERNAL_SERVER_ERROR return {"message": str(e)}, HTTPStatus.INTERNAL_SERVER_ERROR
ticket = await create_ticket( ticket = await create_ticket(
payment_hash=payment_hash, wallet=event.wallet, event=event_id, **data payment_hash=payment_hash, wallet=event.wallet, event=event_id, **data
) )
if not ticket: if not ticket:
return jsonable_encoder({"message": "Event could not be fetched."}), HTTPStatus.NOT_FOUND return {"message": "Event could not be fetched."}, HTTPStatus.NOT_FOUND
return ( return {"payment_hash": payment_hash, "payment_request": payment_request}, HTTPStatus.OK
jsonable_encoder({"payment_hash": payment_hash, "payment_request": payment_request}),
HTTPStatus.OK,
)
@events_ext.get("/api/v1/tickets/<payment_hash>") @events_ext.get("/api/v1/tickets/{payment_hash}")
async def api_ticket_send_ticket(payment_hash): async def api_ticket_send_ticket(payment_hash):
ticket = await get_ticket(payment_hash) ticket = await get_ticket(payment_hash)
@ -141,7 +138,7 @@ async def api_ticket_send_ticket(payment_hash):
status = await check_invoice_status(ticket.wallet, payment_hash) status = await check_invoice_status(ticket.wallet, payment_hash)
is_paid = not status.pending is_paid = not status.pending
except Exception: except Exception:
return jsonable_encoder({"message": "Not paid."}), HTTPStatus.NOT_FOUND return {"message": "Not paid."}, HTTPStatus.NOT_FOUND
if is_paid: if is_paid:
wallet = await get_wallet(ticket.wallet) wallet = await get_wallet(ticket.wallet)
@ -149,21 +146,21 @@ async def api_ticket_send_ticket(payment_hash):
await payment.set_pending(False) await payment.set_pending(False)
ticket = await set_ticket_paid(payment_hash=payment_hash) ticket = await set_ticket_paid(payment_hash=payment_hash)
return jsonable_encoder({"paid": True, "ticket_id": ticket.id}), HTTPStatus.OK return {"paid": True, "ticket_id": ticket.id}, HTTPStatus.OK
return jsonable_encoder({"paid": False}), HTTPStatus.OK return {"paid": False}, HTTPStatus.OK
@events_ext.delete("/api/v1/tickets/<ticket_id>") @events_ext.delete("/api/v1/tickets/{ticket_id}")
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
async def api_ticket_delete(ticket_id): async def api_ticket_delete(ticket_id):
ticket = await get_ticket(ticket_id) ticket = await get_ticket(ticket_id)
if not ticket: if not ticket:
return jsonable_encoder({"message": "Ticket does not exist."}), HTTPStatus.NOT_FOUND return {"message": "Ticket does not exist."}, HTTPStatus.NOT_FOUND
if ticket.wallet != g.wallet.id: if ticket.wallet != g.wallet.id:
return jsonable_encoder({"message": "Not your ticket."}), HTTPStatus.FORBIDDEN return {"message": "Not your ticket."}, HTTPStatus.FORBIDDEN
await delete_ticket(ticket_id) await delete_ticket(ticket_id)
return "", HTTPStatus.NO_CONTENT return "", HTTPStatus.NO_CONTENT
@ -172,26 +169,23 @@ async def api_ticket_delete(ticket_id):
# Event Tickets # Event Tickets
@events_ext.get("/api/v1/eventtickets/<wallet_id>/<event_id>") @events_ext.get("/api/v1/eventtickets/{wallet_id}/{event_id]")
async def api_event_tickets(wallet_id, event_id): async def api_event_tickets(wallet_id, event_id):
return ([ticket._asdict() for ticket in await get_event_tickets(wallet_id=wallet_id, event_id=event_id)], return ([ticket._asdict() for ticket in await get_event_tickets(wallet_id=wallet_id, event_id=event_id)],
HTTPStatus.OK, HTTPStatus.OK,
) )
@events_ext.get("/api/v1/register/ticket/<ticket_id>") @events_ext.get("/api/v1/register/ticket/{ticket_id}")
async def api_event_register_ticket(ticket_id): async def api_event_register_ticket(ticket_id):
ticket = await get_ticket(ticket_id) ticket = await get_ticket(ticket_id)
if not ticket: if not ticket:
return jsonable_encoder({"message": "Ticket does not exist."}), HTTPStatus.FORBIDDEN return {"message": "Ticket does not exist."}, HTTPStatus.FORBIDDEN
if not ticket.paid: if not ticket.paid:
return jsonable_encoder({"message": "Ticket not paid for."}), HTTPStatus.FORBIDDEN return {"message": "Ticket not paid for."}, HTTPStatus.FORBIDDEN
if ticket.registered == True: if ticket.registered == True:
return jsonable_encoder({"message": "Ticket already registered"}), HTTPStatus.FORBIDDEN return {"message": "Ticket already registered"}, HTTPStatus.FORBIDDEN
return ( return [ticket._asdict() for ticket in await reg_ticket(ticket_id)], HTTPStatus.OK
[ticket._asdict() for ticket in await reg_ticket(ticket_id)],
HTTPStatus.OK,
)

View File

@ -40,7 +40,7 @@ async def api_get_jukeboxs():
##################SPOTIFY AUTH##################### ##################SPOTIFY AUTH#####################
@jukebox_ext.get("/api/v1/jukebox/spotify/cb/<juke_id>") @jukebox_ext.get("/api/v1/jukebox/spotify/cb/{juke_id}")
async def api_check_credentials_callbac(juke_id): async def api_check_credentials_callbac(juke_id):
sp_code = "" sp_code = ""
sp_access_token = "" sp_access_token = ""
@ -69,7 +69,7 @@ async def api_check_credentials_callbac(juke_id):
return "<h1>Success!</h1><h2>You can close this window</h2>" return "<h1>Success!</h1><h2>You can close this window</h2>"
@jukebox_ext.get("/api/v1/jukebox/<juke_id>") @jukebox_ext.get("/api/v1/jukebox/{juke_id}")
@api_check_wallet_key("admin") @api_check_wallet_key("admin")
async def api_check_credentials_check(juke_id): async def api_check_credentials_check(juke_id):
jukebox = await get_jukebox(juke_id) jukebox = await get_jukebox(juke_id)
@ -89,7 +89,7 @@ class CreateData(BaseModel):
price: Optional[str] = None price: Optional[str] = None
@jukebox_ext.post("/api/v1/jukebox/") @jukebox_ext.post("/api/v1/jukebox/")
@jukebox_ext.put("/api/v1/jukebox/<juke_id>") @jukebox_ext.put("/api/v1/jukebox/{juke_id}")
@api_check_wallet_key("admin") @api_check_wallet_key("admin")
async def api_create_update_jukebox(data: CreateData, juke_id=None): async def api_create_update_jukebox(data: CreateData, juke_id=None):
if juke_id: if juke_id:
@ -100,7 +100,7 @@ async def api_create_update_jukebox(data: CreateData, juke_id=None):
return jukebox._asdict(), HTTPStatus.CREATED return jukebox._asdict(), HTTPStatus.CREATED
@jukebox_ext.delete("/api/v1/jukebox/<juke_id>") @jukebox_ext.delete("/api/v1/jukebox/{juke_id}")
@api_check_wallet_key("admin") @api_check_wallet_key("admin")
async def api_delete_item(juke_id): async def api_delete_item(juke_id):
await delete_jukebox(juke_id) await delete_jukebox(juke_id)
@ -120,7 +120,7 @@ async def api_delete_item(juke_id):
@jukebox_ext.get( @jukebox_ext.get(
"/api/v1/jukebox/jb/playlist/<juke_id>/<sp_playlist>" "/api/v1/jukebox/jb/playlist/{juke_id}/{sp_playlist}"
) )
async def api_get_jukebox_song(juke_id, sp_playlist, retry=False): async def api_get_jukebox_song(juke_id, sp_playlist, retry=False):
try: try:
@ -210,7 +210,7 @@ async def api_get_token(juke_id):
######CHECK DEVICE ######CHECK DEVICE
@jukebox_ext.get("/api/v1/jukebox/jb/<juke_id>") @jukebox_ext.get("/api/v1/jukebox/jb/{juke_id}")
async def api_get_jukebox_device_check(juke_id, retry=False): async def api_get_jukebox_device_check(juke_id, retry=False):
try: try:
jukebox = await get_jukebox(juke_id) jukebox = await get_jukebox(juke_id)
@ -255,7 +255,7 @@ async def api_get_jukebox_device_check(juke_id, retry=False):
######GET INVOICE STUFF ######GET INVOICE STUFF
@jukebox_ext.get("/api/v1/jukebox/jb/invoice/<juke_id>/<song_id>") @jukebox_ext.get("/api/v1/jukebox/jb/invoice/{juke_id}/{song_id}")
async def api_get_jukebox_invoice(juke_id, song_id): async def api_get_jukebox_invoice(juke_id, song_id):
try: try:
jukebox = await get_jukebox(juke_id) jukebox = await get_jukebox(juke_id)
@ -295,7 +295,7 @@ async def api_get_jukebox_invoice(juke_id, song_id):
@jukebox_ext.get( @jukebox_ext.get(
"/api/v1/jukebox/jb/checkinvoice/<pay_hash>/<juke_id>" "/api/v1/jukebox/jb/checkinvoice/{pay_hash}/{juke_id}"
) )
async def api_get_jukebox_invoice_check(pay_hash, juke_id): async def api_get_jukebox_invoice_check(pay_hash, juke_id):
try: try:
@ -320,7 +320,7 @@ async def api_get_jukebox_invoice_check(pay_hash, juke_id):
@jukebox_ext.get( @jukebox_ext.get(
"/api/v1/jukebox/jb/invoicep/<song_id>/<juke_id>/<pay_hash>" "/api/v1/jukebox/jb/invoicep/{song_id}/{juke_id}/{pay_hash}"
) )
async def api_get_jukebox_invoice_paid(song_id, juke_id, pay_hash, retry=False): async def api_get_jukebox_invoice_paid(song_id, juke_id, pay_hash, retry=False):
try: try:
@ -437,7 +437,7 @@ async def api_get_jukebox_invoice_paid(song_id, juke_id, pay_hash, retry=False):
############################GET TRACKS ############################GET TRACKS
@jukebox_ext.get("/api/v1/jukebox/jb/currently/<juke_id>") @jukebox_ext.get("/api/v1/jukebox/jb/currently/{juke_id}")
async def api_get_jukebox_currently(juke_id, retry=False): async def api_get_jukebox_currently(juke_id, retry=False):
try: try:
jukebox = await get_jukebox(juke_id) jukebox = await get_jukebox(juke_id)

View File

@ -4,6 +4,11 @@ from lnurl.exceptions import InvalidUrl as LnurlInvalidUrl # type: ignore
from lnbits.decorators import api_check_wallet_key, api_validate_post_request from lnbits.decorators import api_check_wallet_key, api_validate_post_request
from fastapi import FastAPI, Query
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from pydantic import BaseModel
from . import livestream_ext from . import livestream_ext
from .crud import ( from .crud import (
get_or_create_livestream_by_wallet, get_or_create_livestream_by_wallet,
@ -18,7 +23,7 @@ from .crud import (
) )
@livestream_ext.route("/api/v1/livestream", methods=["GET"]) @livestream_ext.get("/api/v1/livestream")
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
async def api_livestream_from_wallet(): async def api_livestream_from_wallet():
ls = await get_or_create_livestream_by_wallet(g.wallet.id) ls = await get_or_create_livestream_by_wallet(g.wallet.id)
@ -26,8 +31,7 @@ async def api_livestream_from_wallet():
producers = await get_producers(ls.id) producers = await get_producers(ls.id)
try: try:
return ( return
jsonify(
{ {
**ls._asdict(), **ls._asdict(),
**{ **{
@ -39,21 +43,19 @@ async def api_livestream_from_wallet():
"producers": [producer._asdict() for producer in producers], "producers": [producer._asdict() for producer in producers],
}, },
} }
), ,
HTTPStatus.OK, HTTPStatus.OK
)
except LnurlInvalidUrl: except LnurlInvalidUrl:
return ( return
jsonify(
{ {
"message": "LNURLs need to be delivered over a publically accessible `https` domain or Tor." "message": "LNURLs need to be delivered over a publically accessible `https` domain or Tor."
} }
), ,
HTTPStatus.UPGRADE_REQUIRED, HTTPStatus.UPGRADE_REQUIRED
)
@livestream_ext.route("/api/v1/livestream/track/<track_id>", methods=["PUT"]) @livestream_ext.put("/api/v1/livestream/track/{track_id}")
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
async def api_update_track(track_id): async def api_update_track(track_id):
try: try:
@ -68,7 +70,7 @@ async def api_update_track(track_id):
return "", HTTPStatus.NO_CONTENT return "", HTTPStatus.NO_CONTENT
@livestream_ext.route("/api/v1/livestream/fee/<fee_pct>", methods=["PUT"]) @livestream_ext.put("/api/v1/livestream/fee/{fee_pct}")
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
async def api_update_fee(fee_pct): async def api_update_fee(fee_pct):
ls = await get_or_create_livestream_by_wallet(g.wallet.id) ls = await get_or_create_livestream_by_wallet(g.wallet.id)
@ -76,33 +78,40 @@ async def api_update_fee(fee_pct):
return "", HTTPStatus.NO_CONTENT return "", HTTPStatus.NO_CONTENT
@livestream_ext.route("/api/v1/livestream/tracks", methods=["POST"]) class CreateData(BaseModel):
@livestream_ext.route("/api/v1/livestream/tracks/<id>", methods=["PUT"]) name: str
download_url: str = Query(None)
price_msat: int = Query(None, ge=0)
producer_id: int #missing the exclude thing
producer_name: str #missing the exclude thing
@livestream_ext.post("/api/v1/livestream/tracks")
@livestream_ext.put("/api/v1/livestream/tracks/{id}")
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
@api_validate_post_request( # @api_validate_post_request(
schema={ # schema={
"name": {"type": "string", "empty": False, "required": True}, # "name": {"type": "string", "empty": False, "required": True},
"download_url": {"type": "string", "empty": False, "required": False}, # "download_url": {"type": "string", "empty": False, "required": False},
"price_msat": {"type": "number", "min": 0, "required": False}, # "price_msat": {"type": "number", "min": 0, "required": False},
"producer_id": { # "producer_id": {
"type": "number", # "type": "number",
"required": True, # "required": True,
"excludes": "producer_name", # "excludes": "producer_name",
}, # },
"producer_name": { # "producer_name": {
"type": "string", # "type": "string",
"required": True, # "required": True,
"excludes": "producer_id", # "excludes": "producer_id",
}, # },
} # }
) # )
async def api_add_track(id=None): async def api_add_track(data: CreateData, id=None):
ls = await get_or_create_livestream_by_wallet(g.wallet.id) ls = await get_or_create_livestream_by_wallet(g.wallet.id)
if "producer_id" in g.data: if "producer_id" in data:
p_id = g.data["producer_id"] p_id = data["producer_id"]
elif "producer_name" in g.data: elif "producer_name" in data:
p_id = await add_producer(ls.id, g.data["producer_name"]) p_id = await add_producer(ls.id, data["producer_name"])
else: else:
raise TypeError("need either producer_id or producer_name arguments") raise TypeError("need either producer_id or producer_name arguments")
@ -110,24 +119,24 @@ async def api_add_track(id=None):
await update_track( await update_track(
ls.id, ls.id,
id, id,
g.data["name"], data["name"],
g.data.get("download_url"), data.get("download_url"),
g.data.get("price_msat", 0), data.get("price_msat", 0),
p_id, p_id,
) )
return "", HTTPStatus.OK return "", HTTPStatus.OK
else: else:
await add_track( await add_track(
ls.id, ls.id,
g.data["name"], data["name"],
g.data.get("download_url"), data.get("download_url"),
g.data.get("price_msat", 0), data.get("price_msat", 0),
p_id, p_id,
) )
return "", HTTPStatus.CREATED return "", HTTPStatus.CREATED
@livestream_ext.route("/api/v1/livestream/tracks/<track_id>", methods=["DELETE"]) @livestream_ext.delete("/api/v1/livestream/tracks/{track_id}")
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
async def api_delete_track(track_id): async def api_delete_track(track_id):
ls = await get_or_create_livestream_by_wallet(g.wallet.id) ls = await get_or_create_livestream_by_wallet(g.wallet.id)