Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions helpers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from fastapi import Request
from lnurl import encode as lnurl_encode

from .nostr.key import PrivateKey


Expand All @@ -6,3 +9,13 @@ def parse_nostr_private_key(key: str) -> PrivateKey:
return PrivateKey.from_nsec(key)
else:
return PrivateKey(bytes.fromhex(key))


def lnurl_encode_link_id(req: Request, link_id: str) -> str:
url = req.url_for("lnurlp.api_lnurl_response", link_id=link_id)
url = url.replace(path=url.path)
url_str = str(url)
if url.netloc.endswith(".onion"):
# change url string scheme to http
url_str = url_str.replace("https://", "http://")
return str(lnurl_encode(url_str).bech32)
10 changes: 10 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ class PayLink(BaseModel):
comment_chars: int
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
lnurl: str | None = Field(
default=None,
no_database=True,
deprecated=True,
description=(
"Deprecated: Instead of using this bech32 encoded string, dynamically "
"generate your own static link (lud17/bech32) on the client side. "
"Example: lnurlp://${window.location.hostname}/lnurlp/${paylink_id}"
),
)
username: str | None = None
zaps: bool | None = None
webhook_url: str | None = None
Expand Down
13 changes: 10 additions & 3 deletions views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import re
from http import HTTPStatus

from fastapi import APIRouter, Depends, HTTPException, Query
from fastapi import APIRouter, Depends, HTTPException, Query, Request
from lnbits.core.crud import get_user, get_wallet
from lnbits.core.models import SimpleStatus, WalletTypeInfo
from lnbits.decorators import (
Expand All @@ -22,14 +22,15 @@
update_lnurlp_settings,
update_pay_link,
)
from .helpers import parse_nostr_private_key
from .helpers import lnurl_encode_link_id, parse_nostr_private_key
from .models import CreatePayLinkData, LnurlpSettings, PayLink

lnurlp_api_router = APIRouter()


@lnurlp_api_router.get("/api/v1/links", status_code=HTTPStatus.OK)
async def api_links(
req: Request,
key_info: WalletTypeInfo = Depends(require_invoice_key),
all_wallets: bool = Query(False),
) -> list[PayLink]:
Expand All @@ -39,12 +40,14 @@ async def api_links(
wallet_ids = user.wallet_ids if user else []

links = await get_pay_links(wallet_ids)
for link in links:
link.lnurl = lnurl_encode_link_id(req=req, link_id=link.id)
return links


@lnurlp_api_router.get("/api/v1/links/{link_id}", status_code=HTTPStatus.OK)
async def api_link_retrieve(
link_id: str, key_info: WalletTypeInfo = Depends(require_invoice_key)
req: Request, link_id: str, key_info: WalletTypeInfo = Depends(require_invoice_key)
) -> PayLink:
link = await get_pay_link(link_id)

Expand All @@ -62,6 +65,8 @@ async def api_link_retrieve(
raise HTTPException(
detail="Not your pay link.", status_code=HTTPStatus.FORBIDDEN
)

link.lnurl = lnurl_encode_link_id(req, link.id)
return link


Expand All @@ -77,6 +82,7 @@ async def check_username_exists(username: str):
@lnurlp_api_router.post("/api/v1/links", status_code=HTTPStatus.CREATED)
@lnurlp_api_router.put("/api/v1/links/{link_id}", status_code=HTTPStatus.OK)
async def api_link_create_or_update(
req: Request,
data: CreatePayLinkData,
link_id: str | None = None,
key_info: WalletTypeInfo = Depends(require_admin_key),
Expand Down Expand Up @@ -172,6 +178,7 @@ async def api_link_create_or_update(

link = await create_pay_link(data)

link.lnurl = lnurl_encode_link_id(req, link.id)
return link


Expand Down