2021-10-12 19:54:35 +01:00
|
|
|
import json
|
|
|
|
import hashlib
|
|
|
|
import math
|
2021-10-12 22:34:43 +01:00
|
|
|
from fastapi import Request
|
|
|
|
import hashlib
|
|
|
|
from http import HTTPStatus
|
|
|
|
|
|
|
|
from starlette.exceptions import HTTPException
|
|
|
|
from starlette.responses import HTMLResponse, JSONResponse # type: ignore
|
|
|
|
import base64
|
2021-10-17 18:33:29 +01:00
|
|
|
from lnurl import (
|
|
|
|
LnurlPayResponse,
|
|
|
|
LnurlPayActionResponse,
|
|
|
|
LnurlErrorResponse,
|
|
|
|
) # type: ignore
|
2021-10-12 19:54:35 +01:00
|
|
|
from lnurl.types import LnurlPayMetadata
|
|
|
|
from lnbits.core.services import create_invoice
|
2021-10-12 22:34:43 +01:00
|
|
|
from .models import Copilots, CreateCopilotData
|
2021-10-12 19:54:35 +01:00
|
|
|
from . import copilot_ext
|
|
|
|
from .crud import get_copilot
|
2021-10-12 22:34:43 +01:00
|
|
|
from typing import Optional
|
|
|
|
from fastapi.params import Depends
|
|
|
|
from fastapi.param_functions import Query
|
2021-10-12 19:54:35 +01:00
|
|
|
|
|
|
|
|
2021-10-12 22:34:43 +01:00
|
|
|
@copilot_ext.get("/lnurl/{cp_id}", response_class=HTMLResponse)
|
|
|
|
async def lnurl_response(req: Request, cp_id: str = Query(None)):
|
2021-10-12 19:54:35 +01:00
|
|
|
cp = await get_copilot(cp_id)
|
|
|
|
if not cp:
|
2021-10-12 22:34:43 +01:00
|
|
|
raise HTTPException(
|
2021-10-17 18:33:29 +01:00
|
|
|
status_code=HTTPStatus.NOT_FOUND, detail="Copilot not found"
|
2021-10-12 22:34:43 +01:00
|
|
|
)
|
2021-10-12 19:54:35 +01:00
|
|
|
|
|
|
|
resp = LnurlPayResponse(
|
2021-10-12 22:34:43 +01:00
|
|
|
callback=req.url_for("copilot.lnurl_callback", cp_id=cp_id, _external=True),
|
2021-10-12 19:54:35 +01:00
|
|
|
min_sendable=10000,
|
|
|
|
max_sendable=50000000,
|
|
|
|
metadata=LnurlPayMetadata(json.dumps([["text/plain", str(cp.lnurl_title)]])),
|
|
|
|
)
|
|
|
|
|
|
|
|
params = resp.dict()
|
|
|
|
if cp.show_message:
|
|
|
|
params["commentAllowed"] = 300
|
|
|
|
|
2021-10-12 22:34:43 +01:00
|
|
|
return params
|
2021-10-12 19:54:35 +01:00
|
|
|
|
|
|
|
|
2021-10-12 22:34:43 +01:00
|
|
|
@copilot_ext.get("/lnurl/cb/{cp_id}", response_class=HTMLResponse)
|
|
|
|
async def lnurl_callback(
|
|
|
|
cp_id: str = Query(None), amount: str = Query(None), comment: str = Query(None)
|
|
|
|
):
|
2021-10-12 19:54:35 +01:00
|
|
|
cp = await get_copilot(cp_id)
|
|
|
|
if not cp:
|
2021-10-12 22:34:43 +01:00
|
|
|
raise HTTPException(
|
2021-10-17 18:33:29 +01:00
|
|
|
status_code=HTTPStatus.NOT_FOUND, detail="Copilot not found"
|
2021-10-12 22:34:43 +01:00
|
|
|
)
|
2021-10-12 19:54:35 +01:00
|
|
|
|
2021-10-12 22:34:43 +01:00
|
|
|
amount_received = int(amount)
|
2021-10-12 19:54:35 +01:00
|
|
|
|
|
|
|
if amount_received < 10000:
|
2021-10-12 22:34:43 +01:00
|
|
|
return LnurlErrorResponse(
|
|
|
|
reason=f"Amount {round(amount_received / 1000)} is smaller than minimum 10 sats."
|
|
|
|
).dict()
|
2021-10-12 19:54:35 +01:00
|
|
|
elif amount_received / 1000 > 10000000:
|
2021-10-12 22:34:43 +01:00
|
|
|
return LnurlErrorResponse(
|
|
|
|
reason=f"Amount {round(amount_received / 1000)} is greater than maximum 50000."
|
|
|
|
).dict()
|
2021-10-12 19:54:35 +01:00
|
|
|
comment = ""
|
2021-10-12 22:34:43 +01:00
|
|
|
if comment:
|
2021-10-12 19:54:35 +01:00
|
|
|
if len(comment or "") > 300:
|
2021-10-12 22:34:43 +01:00
|
|
|
return LnurlErrorResponse(
|
|
|
|
reason=f"Got a comment with {len(comment)} characters, but can only accept 300"
|
|
|
|
).dict()
|
2021-10-12 19:54:35 +01:00
|
|
|
if len(comment) < 1:
|
|
|
|
comment = "none"
|
|
|
|
|
|
|
|
payment_hash, payment_request = await create_invoice(
|
|
|
|
wallet_id=cp.wallet,
|
|
|
|
amount=int(amount_received / 1000),
|
|
|
|
memo=cp.lnurl_title,
|
|
|
|
description_hash=hashlib.sha256(
|
|
|
|
(
|
|
|
|
LnurlPayMetadata(json.dumps([["text/plain", str(cp.lnurl_title)]]))
|
|
|
|
).encode("utf-8")
|
|
|
|
).digest(),
|
|
|
|
extra={"tag": "copilot", "copilot": cp.id, "comment": comment},
|
|
|
|
)
|
|
|
|
resp = LnurlPayActionResponse(
|
2021-10-17 18:33:29 +01:00
|
|
|
pr=payment_request, success_action=None, disposable=False, routes=[]
|
2021-10-12 19:54:35 +01:00
|
|
|
)
|
2021-10-12 22:34:43 +01:00
|
|
|
return resp.dict()
|