lnbits-legend/lnbits/extensions/livestream/lnurl.py

119 lines
3.8 KiB
Python
Raw Normal View History

2021-10-28 17:02:07 +01:00
import math
from http import HTTPStatus
2023-01-05 09:28:38 +01:00
from fastapi import HTTPException, Query, Request
2021-10-28 17:02:07 +01:00
from lnurl import LnurlErrorResponse, LnurlPayActionResponse, LnurlPayResponse
2023-01-05 09:28:38 +01:00
from lnurl.models import ClearnetUrl, LightningInvoice, MilliSatoshi
2021-10-28 17:02:07 +01:00
from lnbits.core.services import create_invoice
from . import livestream_ext
from .crud import get_livestream, get_livestream_by_track, get_track
@livestream_ext.get("/lnurl/{ls_id}", name="livestream.lnurl_livestream")
async def lnurl_livestream(ls_id, request: Request):
ls = await get_livestream(ls_id)
if not ls:
raise HTTPException(
2021-11-12 04:14:55 +00:00
status_code=HTTPStatus.NOT_FOUND, detail="Livestream not found."
2021-10-28 17:02:07 +01:00
)
track = await get_track(ls.current_track)
if not track:
raise HTTPException(
2021-11-12 04:14:55 +00:00
status_code=HTTPStatus.NOT_FOUND, detail="This livestream is offline."
2021-10-28 17:02:07 +01:00
)
resp = LnurlPayResponse(
2023-01-05 09:28:38 +01:00
callback=ClearnetUrl(
request.url_for("livestream.lnurl_callback", track_id=track.id),
scheme="https",
),
minSendable=MilliSatoshi(track.min_sendable),
maxSendable=MilliSatoshi(track.max_sendable),
2021-10-28 17:02:07 +01:00
metadata=await track.lnurlpay_metadata(),
)
params = resp.dict()
params["commentAllowed"] = 300
return params
@livestream_ext.get("/lnurl/t/{track_id}", name="livestream.lnurl_track")
async def lnurl_track(track_id, request: Request):
track = await get_track(track_id)
if not track:
2021-11-12 04:14:55 +00:00
raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="Track not found.")
2021-10-28 17:02:07 +01:00
resp = LnurlPayResponse(
2023-01-05 09:28:38 +01:00
callback=ClearnetUrl(
request.url_for("livestream.lnurl_callback", track_id=track.id),
scheme="https",
),
minSendable=MilliSatoshi(track.min_sendable),
maxSendable=MilliSatoshi(track.max_sendable),
2021-10-28 17:02:07 +01:00
metadata=await track.lnurlpay_metadata(),
)
params = resp.dict()
params["commentAllowed"] = 300
return params
@livestream_ext.get("/lnurl/cb/{track_id}", name="livestream.lnurl_callback")
2021-11-12 04:14:55 +00:00
async def lnurl_callback(
track_id, request: Request, amount: int = Query(...), comment: str = Query("")
):
2021-10-28 17:02:07 +01:00
track = await get_track(track_id)
if not track:
2021-11-12 04:14:55 +00:00
raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="Track not found.")
2021-10-28 17:02:07 +01:00
amount_received = int(amount or 0)
if amount_received < track.min_sendable:
return LnurlErrorResponse(
2021-11-12 04:14:55 +00:00
reason=f"Amount {round(amount_received / 1000)} is smaller than minimum {math.floor(track.min_sendable)}."
).dict()
2021-10-28 17:02:07 +01:00
elif track.max_sendable < amount_received:
return LnurlErrorResponse(
2021-11-12 04:14:55 +00:00
reason=f"Amount {round(amount_received / 1000)} is greater than maximum {math.floor(track.max_sendable)}."
).dict()
2021-10-28 17:02:07 +01:00
if len(comment or "") > 300:
return LnurlErrorResponse(
2021-11-12 04:14:55 +00:00
reason=f"Got a comment with {len(comment)} characters, but can only accept 300"
).dict()
2021-10-28 17:02:07 +01:00
ls = await get_livestream_by_track(track_id)
2023-01-05 09:28:38 +01:00
assert ls
2021-10-28 17:02:07 +01:00
2023-01-06 12:45:55 +00:00
extra_amount = amount_received - int(amount_received * (100 - ls.fee_pct) / 100)
2021-10-28 17:02:07 +01:00
payment_hash, payment_request = await create_invoice(
wallet_id=ls.wallet,
2023-01-06 12:45:55 +00:00
amount=int(amount_received / 1000),
2021-10-28 17:02:07 +01:00
memo=await track.fullname(),
unhashed_description=(await track.lnurlpay_metadata()).encode(),
2023-01-06 12:45:55 +00:00
extra={
"tag": "livestream",
"track": track.id,
"comment": comment,
"amount": int(extra_amount / 1000),
},
2021-10-28 17:02:07 +01:00
)
2023-01-05 09:28:38 +01:00
assert track.price_msat
2021-10-28 17:02:07 +01:00
if amount_received < track.price_msat:
success_action = None
else:
success_action = track.success_action(payment_hash, request=request)
resp = LnurlPayActionResponse(
2023-01-05 09:28:38 +01:00
pr=LightningInvoice(payment_request), successAction=success_action, routes=[]
2021-10-28 17:02:07 +01:00
)
return resp.dict()