This commit is contained in:
benarc 2021-11-12 04:14:55 +00:00
parent 860709f48c
commit 267dea4f75
61 changed files with 23219 additions and 13297 deletions

View File

@ -305,9 +305,7 @@ async def perform_lnurlauth(
async def check_invoice_status(
wallet_id: str,
payment_hash: str,
conn: Optional[Connection] = None,
wallet_id: str, payment_hash: str, conn: Optional[Connection] = None
) -> PaymentStatus:
payment = await get_wallet_payment(wallet_id, payment_hash, conn=conn)
if not payment:

View File

@ -54,10 +54,7 @@ async def api_wallet(wallet: WalletTypeInfo = Depends(get_key_type)):
"balance": wallet.wallet.balance_msat,
}
else:
return {
"name": wallet.wallet.name,
"balance": wallet.wallet.balance_msat,
}
return {"name": wallet.wallet.name, "balance": wallet.wallet.balance_msat}
@core_app.put("/api/v1/wallet/{new_name}")
@ -74,11 +71,7 @@ async def api_update_wallet(
@core_app.get("/api/v1/payments")
async def api_payments(wallet: WalletTypeInfo = Depends(get_key_type)):
await get_payments(
wallet_id=wallet.wallet.id,
pending=True,
complete=True,
)
await get_payments(wallet_id=wallet.wallet.id, pending=True, complete=True)
pendingPayments = await get_payments(wallet_id=wallet.wallet.id, pending=True)
for payment in pendingPayments:
await check_invoice_status(
@ -91,7 +84,7 @@ class CreateInvoiceData(BaseModel):
out: Optional[bool] = True
amount: int = Query(None, ge=1)
memo: str = None
unit: Optional[str] = 'sat'
unit: Optional[str] = "sat"
description_hash: Optional[str] = None
lnurl_callback: Optional[str] = None
lnurl_balance_check: Optional[str] = None
@ -107,7 +100,7 @@ async def api_payments_create_invoice(data: CreateInvoiceData, wallet: Wallet):
else:
description_hash = b""
memo = data.memo
if data.unit == 'sat':
if data.unit == "sat":
amount = data.amount
else:
price_in_sats = await fiat_amount_as_satoshis(data.amount, data.unit)
@ -334,8 +327,7 @@ async def api_payment(payment_hash):
payment = await get_standalone_payment(payment_hash)
if not payment:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Payment does not exist.",
status_code=HTTPStatus.NOT_FOUND, detail="Payment does not exist."
)
elif not payment.pending:
return {"paid": True, "preimage": payment.preimage}

View File

@ -14,14 +14,13 @@ bleskomat_static_files = [
}
]
bleskomat_ext: APIRouter = APIRouter(
prefix="/bleskomat",
tags=["Bleskomat"]
)
bleskomat_ext: APIRouter = APIRouter(prefix="/bleskomat", tags=["Bleskomat"])
def bleskomat_renderer():
return template_renderer(["lnbits/extensions/bleskomat/templates"])
from .lnurl_api import * # noqa
from .views import * # noqa
from .views_api import * # noqa

View File

@ -8,10 +8,7 @@ from .helpers import generate_bleskomat_lnurl_hash
from .models import Bleskomat, BleskomatLnurl, CreateBleskomat
async def create_bleskomat(
data: CreateBleskomat,
wallet_id: str,
) -> Bleskomat:
async def create_bleskomat(data: CreateBleskomat, wallet_id: str) -> Bleskomat:
bleskomat_id = uuid4().hex
api_key_id = secrets.token_hex(8)
api_key_secret = secrets.token_hex(32)

View File

@ -20,24 +20,25 @@ class CreateBleskomat(BaseModel):
exchange_rate_provider: str = Query(...)
fee: str = Query(...)
@validator('fiat_currency')
@validator("fiat_currency")
def allowed_fiat_currencies(cls, v):
if(v not in fiat_currencies.keys()):
raise ValueError('Not allowed currency')
if v not in fiat_currencies.keys():
raise ValueError("Not allowed currency")
return v
@validator('exchange_rate_provider')
@validator("exchange_rate_provider")
def allowed_providers(cls, v):
if(v not in exchange_rate_providers.keys()):
raise ValueError('Not allowed provider')
if v not in exchange_rate_providers.keys():
raise ValueError("Not allowed provider")
return v
@validator('fee')
@validator("fee")
def fee_type(cls, v):
if(not isinstance(v, (str, float, int))):
raise ValueError('Fee type not allowed')
if not isinstance(v, (str, float, int)):
raise ValueError("Fee type not allowed")
return v
class Bleskomat(BaseModel):
id: str
wallet: str
@ -119,8 +120,7 @@ class BleskomatLnurl(BaseModel):
if tag == "withdrawRequest":
try:
payment_hash = await pay_invoice(
wallet_id=self.wallet,
payment_request=query["pr"],
wallet_id=self.wallet, payment_request=query["pr"]
)
except Exception:
raise LnurlValidationError("Failed to pay invoice")

View File

@ -1,4 +1,3 @@
from fastapi import Request
from fastapi.params import Depends
from fastapi.templating import Jinja2Templates
@ -22,5 +21,6 @@ async def index(request: Request, user: User = Depends(check_user_exists)):
"fiat_currencies": fiat_currencies,
}
return bleskomat_renderer().TemplateResponse(
"bleskomat/index.html", {"request": request, "user": user.dict(), "bleskomat_vars": bleskomat_vars}
"bleskomat/index.html",
{"request": request, "user": user.dict(), "bleskomat_vars": bleskomat_vars},
)

View File

@ -19,7 +19,10 @@ from .exchange_rates import fetch_fiat_exchange_rate
@bleskomat_ext.get("/api/v1/bleskomats")
async def api_bleskomats(wallet: WalletTypeInfo = Depends(require_admin_key), all_wallets: bool = Query(False)):
async def api_bleskomats(
wallet: WalletTypeInfo = Depends(require_admin_key),
all_wallets: bool = Query(False),
):
wallet_ids = [wallet.wallet.id]
if all_wallets:
@ -29,21 +32,27 @@ async def api_bleskomats(wallet: WalletTypeInfo = Depends(require_admin_key), al
@bleskomat_ext.get("/api/v1/bleskomat/{bleskomat_id}")
async def api_bleskomat_retrieve(bleskomat_id, wallet: WalletTypeInfo = Depends(require_admin_key)):
async def api_bleskomat_retrieve(
bleskomat_id, wallet: WalletTypeInfo = Depends(require_admin_key)
):
bleskomat = await get_bleskomat(bleskomat_id)
if not bleskomat or bleskomat.wallet != wallet.wallet.id:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Bleskomat configuration not found."
)
status_code=HTTPStatus.NOT_FOUND,
detail="Bleskomat configuration not found.",
)
return bleskomat.dict()
@bleskomat_ext.post("/api/v1/bleskomat")
@bleskomat_ext.put("/api/v1/bleskomat/{bleskomat_id}",)
async def api_bleskomat_create_or_update(data: CreateBleskomat, wallet: WalletTypeInfo = Depends(require_admin_key), bleskomat_id=None):
@bleskomat_ext.put("/api/v1/bleskomat/{bleskomat_id}")
async def api_bleskomat_create_or_update(
data: CreateBleskomat,
wallet: WalletTypeInfo = Depends(require_admin_key),
bleskomat_id=None,
):
try:
fiat_currency = data.fiat_currency
exchange_rate_provider = data.exchange_rate_provider
@ -54,7 +63,7 @@ async def api_bleskomat_create_or_update(data: CreateBleskomat, wallet: WalletTy
print(e)
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=f'Failed to fetch BTC/{fiat_currency} currency pair from "{exchange_rate_provider}"'
detail=f'Failed to fetch BTC/{fiat_currency} currency pair from "{exchange_rate_provider}"',
)
if bleskomat_id:
@ -62,9 +71,9 @@ async def api_bleskomat_create_or_update(data: CreateBleskomat, wallet: WalletTy
if not bleskomat or bleskomat.wallet != wallet.wallet.id:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Bleskomat configuration not found."
detail="Bleskomat configuration not found.",
)
bleskomat = await update_bleskomat(bleskomat_id, **data.dict())
else:
bleskomat = await create_bleskomat(wallet_id=wallet.wallet.id, data=data)
@ -73,14 +82,16 @@ async def api_bleskomat_create_or_update(data: CreateBleskomat, wallet: WalletTy
@bleskomat_ext.delete("/api/v1/bleskomat/{bleskomat_id}")
async def api_bleskomat_delete(bleskomat_id, wallet: WalletTypeInfo = Depends(require_admin_key)):
async def api_bleskomat_delete(
bleskomat_id, wallet: WalletTypeInfo = Depends(require_admin_key)
):
bleskomat = await get_bleskomat(bleskomat_id)
if not bleskomat or bleskomat.wallet != wallet.wallet.id:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Bleskomat configuration not found."
)
status_code=HTTPStatus.NOT_FOUND,
detail="Bleskomat configuration not found.",
)
await delete_bleskomat(bleskomat_id)
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)

View File

@ -31,4 +31,4 @@ from .views_api import * # noqa
def copilot_start():
loop = asyncio.get_event_loop()
loop.create_task(catch_everything_and_restart(wait_for_paid_invoices))
loop.create_task(catch_everything_and_restart(wait_for_paid_invoices))

View File

@ -49,7 +49,7 @@ async def lnurl_callback(
status_code=HTTPStatus.NOT_FOUND, detail="Copilot not found"
)
amount_received = int(amount)
if amount_received < 10000:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN,
@ -80,8 +80,5 @@ async def lnurl_callback(
).digest(),
extra={"tag": "copilot", "copilotid": cp.id, "comment": comment},
)
payResponse = {
"pr": payment_request,
"routes": [],
}
payResponse = {"pr": payment_request, "routes": []}
return json.dumps(payResponse)

View File

@ -6,13 +6,12 @@ from lnbits.helpers import template_renderer
db = Database("ext_events")
events_ext: APIRouter = APIRouter(
prefix="/events",
tags=["Events"]
)
events_ext: APIRouter = APIRouter(prefix="/events", tags=["Events"])
def events_renderer():
return template_renderer(["lnbits/extensions/events/templates"])
from .views import * # noqa
from .views_api import * # noqa

View File

@ -74,6 +74,7 @@ async def get_tickets(wallet_ids: Union[str, List[str]]) -> List[Tickets]:
async def delete_ticket(payment_hash: str) -> None:
await db.execute("DELETE FROM events.ticket WHERE id = ?", (payment_hash,))
async def delete_event_tickets(event_id: str) -> None:
await db.execute("DELETE FROM events.tickets WHERE event = ?", (event_id,))
@ -81,9 +82,7 @@ async def delete_event_tickets(event_id: str) -> None:
# EVENTS
async def create_event(
data: CreateEvent
) -> Events:
async def create_event(data: CreateEvent) -> Events:
event_id = urlsafe_short_hash()
await db.execute(
"""

View File

@ -78,14 +78,6 @@ async def m002_changed(db):
)
VALUES (?, ?, ?, ?, ?, ?, ?)
""",
(
row[0],
row[1],
row[2],
row[3],
row[4],
row[5],
True,
),
(row[0], row[1], row[2], row[3], row[4], row[5], True),
)
await db.execute("DROP TABLE events.tickets")

View File

@ -5,17 +5,19 @@ from pydantic import BaseModel
class CreateEvent(BaseModel):
wallet: str
name: str
info: str
closing_date: str
event_start_date: str
info: str
closing_date: str
event_start_date: str
event_end_date: str
amount_tickets: int = Query(..., ge=0)
price_per_ticket: int = Query(..., ge=0)
class CreateTicket(BaseModel):
name: str
email: str
class Events(BaseModel):
id: str
wallet: str

View File

@ -18,7 +18,9 @@ templates = Jinja2Templates(directory="templates")
@events_ext.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_user_exists)):
return events_renderer().TemplateResponse("events/index.html", {"request": request, "user": user.dict()})
return events_renderer().TemplateResponse(
"events/index.html", {"request": request, "user": user.dict()}
)
@events_ext.get("/{event_id}", response_class=HTMLResponse)
@ -35,8 +37,8 @@ async def display(request: Request, event_id):
{
"request": request,
"event_name": event.name,
"event_error": "Sorry, tickets are sold out :("
}
"event_error": "Sorry, tickets are sold out :(",
},
)
datetime_object = datetime.strptime(event.closing_date, "%Y-%m-%d").date()
if date.today() > datetime_object:
@ -45,8 +47,8 @@ async def display(request: Request, event_id):
{
"request": request,
"event_name": event.name,
"event_error": "Sorry, ticket closing date has passed :("
}
"event_error": "Sorry, ticket closing date has passed :(",
},
)
return events_renderer().TemplateResponse(
@ -57,8 +59,7 @@ async def display(request: Request, event_id):
"event_name": event.name,
"event_info": event.info,
"event_price": event.price_per_ticket,
}
},
)
@ -83,8 +84,7 @@ async def ticket(request: Request, ticket_id):
"ticket_id": ticket_id,
"ticket_name": event.name,
"ticket_info": event.info,
}
},
)
@ -103,5 +103,5 @@ async def register(request: Request, event_id):
"event_id": event_id,
"event_name": event.name,
"wallet_id": event.wallet,
}
},
)

View File

@ -5,10 +5,8 @@ from lnbits.helpers import template_renderer
db = Database("ext_hivemind")
hivemind_ext: APIRouter = APIRouter(
prefix="/hivemind",
tags=["hivemind"]
)
hivemind_ext: APIRouter = APIRouter(prefix="/hivemind", tags=["hivemind"])
def hivemind_renderer():
return template_renderer(["lnbits/extensions/hivemind/templates"])

View File

@ -10,4 +10,6 @@ from . import hivemind_ext, hivemind_renderer
@hivemind_ext.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_user_exists)):
return hivemind_renderer().TemplateResponse("hivemind/index.html", {"request": request, "user": user.dict()})
return hivemind_renderer().TemplateResponse(
"hivemind/index.html", {"request": request, "user": user.dict()}
)

View File

@ -17,14 +17,13 @@ livestream_static_files = [
}
]
livestream_ext: APIRouter = APIRouter(
prefix="/livestream",
tags=["livestream"]
)
livestream_ext: APIRouter = APIRouter(prefix="/livestream", tags=["livestream"])
def livestream_renderer():
return template_renderer(["lnbits/extensions/livestream/templates"])
from .lnurl import * # noqa
from .tasks import wait_for_paid_invoices
from .views import * # noqa

View File

@ -67,8 +67,7 @@ async def update_current_track(ls_id: int, track_id: Optional[int]):
async def update_livestream_fee(ls_id: int, fee_pct: int):
await db.execute(
"UPDATE livestream.livestreams SET fee_pct = ? WHERE id = ?",
(fee_pct, ls_id),
"UPDATE livestream.livestreams SET fee_pct = ? WHERE id = ?", (fee_pct, ls_id)
)

View File

@ -19,21 +19,17 @@ async def lnurl_livestream(ls_id, request: Request):
ls = await get_livestream(ls_id)
if not ls:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Livestream not found."
status_code=HTTPStatus.NOT_FOUND, detail="Livestream not found."
)
track = await get_track(ls.current_track)
if not track:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="This livestream is offline."
status_code=HTTPStatus.NOT_FOUND, detail="This livestream is offline."
)
resp = LnurlPayResponse(
callback=request.url_for(
"livestream.lnurl_callback", track_id=track.id
),
callback=request.url_for("livestream.lnurl_callback", track_id=track.id),
min_sendable=track.min_sendable,
max_sendable=track.max_sendable,
metadata=await track.lnurlpay_metadata(),
@ -49,15 +45,10 @@ async def lnurl_livestream(ls_id, request: Request):
async def lnurl_track(track_id, request: Request):
track = await get_track(track_id)
if not track:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Track not found."
)
raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="Track not found.")
resp = LnurlPayResponse(
callback=request.url_for(
"livestream.lnurl_callback", track_id=track.id
),
callback=request.url_for("livestream.lnurl_callback", track_id=track.id),
min_sendable=track.min_sendable,
max_sendable=track.max_sendable,
metadata=await track.lnurlpay_metadata(),
@ -70,29 +61,28 @@ async def lnurl_track(track_id, request: Request):
@livestream_ext.get("/lnurl/cb/{track_id}", name="livestream.lnurl_callback")
async def lnurl_callback(track_id, request: Request, amount: int = Query(...), comment: str = Query("")):
async def lnurl_callback(
track_id, request: Request, amount: int = Query(...), comment: str = Query("")
):
track = await get_track(track_id)
if not track:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Track not found."
)
raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="Track not found.")
amount_received = int(amount or 0)
if amount_received < track.min_sendable:
return LnurlErrorResponse(
reason=f"Amount {round(amount_received / 1000)} is smaller than minimum {math.floor(track.min_sendable)}."
).dict()
reason=f"Amount {round(amount_received / 1000)} is smaller than minimum {math.floor(track.min_sendable)}."
).dict()
elif track.max_sendable < amount_received:
return LnurlErrorResponse(
reason=f"Amount {round(amount_received / 1000)} is greater than maximum {math.floor(track.max_sendable)}."
).dict()
reason=f"Amount {round(amount_received / 1000)} is greater than maximum {math.floor(track.max_sendable)}."
).dict()
if len(comment or "") > 300:
return LnurlErrorResponse(
reason=f"Got a comment with {len(comment)} characters, but can only accept 300"
).dict()
reason=f"Got a comment with {len(comment)} characters, but can only accept 300"
).dict()
ls = await get_livestream_by_track(track_id)
@ -112,9 +102,7 @@ async def lnurl_callback(track_id, request: Request, amount: int = Query(...), c
success_action = track.success_action(payment_hash, request=request)
resp = LnurlPayActionResponse(
pr=payment_request,
success_action=success_action,
routes=[],
pr=payment_request, success_action=success_action, routes=[]
)
return resp.dict()

View File

@ -17,6 +17,7 @@ class CreateTrack(BaseModel):
producer_id: str = Query(None)
producer_name: str = Query(None)
class Livestream(BaseModel):
id: int
wallet: str
@ -68,15 +69,15 @@ class Track(BaseModel):
return LnurlPayMetadata(json.dumps([["text/plain", description]]))
def success_action(self, payment_hash: str, request: Request) -> Optional[LnurlPaySuccessAction]:
def success_action(
self, payment_hash: str, request: Request
) -> Optional[LnurlPaySuccessAction]:
if not self.download_url:
return None
return UrlAction(
url=request.url_for(
"livestream.track_redirect_download",
track_id=self.id,
p=payment_hash
"livestream.track_redirect_download", track_id=self.id, p=payment_hash
),
description=f"Download the track {self.name}!",
)

View File

@ -18,6 +18,7 @@ async def wait_for_paid_invoices():
payment = await invoice_queue.get()
await on_invoice_paid(payment)
# async def register_listeners():
# invoice_paid_chan_send, invoice_paid_chan_recv = trio.open_memory_channel(2)
# register_invoice_listener(invoice_paid_chan_send)

View File

@ -17,7 +17,9 @@ from .crud import get_livestream_by_track, get_track
@livestream_ext.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_user_exists)):
return livestream_renderer().TemplateResponse("livestream/index.html", {"request": request, "user": user.dict()})
return livestream_renderer().TemplateResponse(
"livestream/index.html", {"request": request, "user": user.dict()}
)
@livestream_ext.get("/track/{track_id}", name="livestream.track_redirect_download")
@ -31,12 +33,12 @@ async def track_redirect_download(track_id, p: str = Query(...)):
if not payment:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail=f"Couldn't find the payment {payment_hash} or track {track.id}."
detail=f"Couldn't find the payment {payment_hash} or track {track.id}.",
)
if payment.pending:
raise HTTPException(
status_code=HTTPStatus.PAYMENT_REQUIRED,
detail=f"Payment {payment_hash} wasn't received yet. Please try again in a minute."
detail=f"Payment {payment_hash} wasn't received yet. Please try again in a minute.",
)
return RedirectResponse(url=track.download_url)

View File

@ -23,27 +23,29 @@ from .crud import (
@livestream_ext.get("/api/v1/livestream")
async def api_livestream_from_wallet(req: Request, g: WalletTypeInfo = Depends(get_key_type)):
async def api_livestream_from_wallet(
req: Request, g: WalletTypeInfo = Depends(get_key_type)
):
ls = await get_or_create_livestream_by_wallet(g.wallet.id)
tracks = await get_tracks(ls.id)
producers = await get_producers(ls.id)
print("INIT", ls, tracks, producers)
try:
return {
**ls.dict(),
**{
"lnurl": ls.lnurl(request=req),
"tracks": [
dict(lnurl=track.lnurl(request=req), **track.dict())
for track in tracks
],
"producers": [producer.dict() for producer in producers],
},
}
**ls.dict(),
**{
"lnurl": ls.lnurl(request=req),
"tracks": [
dict(lnurl=track.lnurl(request=req), **track.dict())
for track in tracks
],
"producers": [producer.dict() for producer in producers],
},
}
except LnurlInvalidUrl:
raise HTTPException(
status_code=HTTPStatus.UPGRADE_REQUIRED,
detail="LNURLs need to be delivered over a publically accessible `https` domain or Tor."
detail="LNURLs need to be delivered over a publically accessible `https` domain or Tor.",
)
@ -70,7 +72,9 @@ async def api_update_fee(fee_pct, g: WalletTypeInfo = Depends(get_key_type)):
@livestream_ext.post("/api/v1/livestream/tracks")
@livestream_ext.put("/api/v1/livestream/tracks/{id}")
async def api_add_track(data: CreateTrack, id=None, g: WalletTypeInfo = Depends(get_key_type)):
async def api_add_track(
data: CreateTrack, id=None, g: WalletTypeInfo = Depends(get_key_type)
):
ls = await get_or_create_livestream_by_wallet(g.wallet.id)
if data.producer_id:
@ -82,21 +86,10 @@ async def api_add_track(data: CreateTrack, id=None, g: WalletTypeInfo = Depends(
if id:
await update_track(
ls.id,
id,
data.name,
data.download_url,
data.price_msat or 0,
p_id,
ls.id, id, data.name, data.download_url, data.price_msat or 0, p_id
)
else:
await add_track(
ls.id,
data.name,
data.download_url,
data.price_msat or 0,
p_id,
)
await add_track(ls.id, data.name, data.download_url, data.price_msat or 0, p_id)
return

View File

@ -91,7 +91,7 @@ async def lndhub_payinvoice(
raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="Payment failed")
invoice: bolt11.Invoice = bolt11.decode(r_invoice.invoice)
return {
"payment_error": "",
"payment_preimage": "0" * 64,

View File

@ -8,9 +8,7 @@ from .models import lnurlposs, lnurlpospayment, createLnurlpos
###############lnurlposS##########################
async def create_lnurlpos(
data: createLnurlpos,
) -> lnurlposs:
async def create_lnurlpos(data: createLnurlpos,) -> lnurlposs:
print(data)
lnurlpos_id = urlsafe_short_hash()
lnurlpos_key = urlsafe_short_hash()

View File

@ -1,7 +1,11 @@
import json
import hashlib
import math
from lnurl import LnurlPayResponse, LnurlPayActionResponse, LnurlErrorResponse # type: ignore
from lnurl import (
LnurlPayResponse,
LnurlPayActionResponse,
LnurlErrorResponse,
) # type: ignore
from lnurl.types import LnurlPayMetadata
from lnbits.core.services import create_invoice
from hashlib import md5

View File

@ -54,6 +54,5 @@ async def displaypin(request: Request, paymentid: str = Query(None)):
"lnurlpos/paid.html", {"request": request, "pin": lnurlpospayment.pin}
)
return lnurlpos_renderer().TemplateResponse(
"lnurlpos/error.html",
{"request": request, "pin": "filler", "not_paid": True},
"lnurlpos/error.html", {"request": request, "pin": "filler", "not_paid": True}
)

View File

@ -5,10 +5,8 @@ from lnbits.helpers import template_renderer
db = Database("ext_paywall")
paywall_ext: APIRouter = APIRouter(
prefix="/paywall",
tags=["Paywall"]
)
paywall_ext: APIRouter = APIRouter(prefix="/paywall", tags=["Paywall"])
def paywall_renderer():
return template_renderer(["lnbits/extensions/paywall/templates"])

View File

@ -6,17 +6,22 @@ from . import db
from .models import CreatePaywall, Paywall
async def create_paywall(
wallet_id: str,
data: CreatePaywall
) -> Paywall:
async def create_paywall(wallet_id: str, data: CreatePaywall) -> Paywall:
paywall_id = urlsafe_short_hash()
await db.execute(
"""
INSERT INTO paywall.paywalls (id, wallet, url, memo, description, amount, remembers)
VALUES (?, ?, ?, ?, ?, ?, ?)
""",
(paywall_id, wallet_id, data.url, data.memo, data.description, data.amount, int(data.remembers)),
(
paywall_id,
wallet_id,
data.url,
data.memo,
data.description,
data.amount,
int(data.remembers),
),
)
paywall = await get_paywall(paywall_id)

View File

@ -13,12 +13,15 @@ class CreatePaywall(BaseModel):
amount: int = Query(..., ge=0)
remembers: bool = Query(...)
class CreatePaywallInvoice(BaseModel):
amount: int = Query(..., ge=1)
class CheckPaywallInvoice(BaseModel):
payment_hash: str = Query(...)
class Paywall(BaseModel):
id: str
wallet: str

View File

@ -13,7 +13,9 @@ from .crud import get_paywall
@paywall_ext.get("/")
async def index(request: Request, user: User = Depends(check_user_exists)):
return paywall_renderer().TemplateResponse("paywall/index.html", {"request": request, "user": user.dict()})
return paywall_renderer().TemplateResponse(
"paywall/index.html", {"request": request, "user": user.dict()}
)
@paywall_ext.get("/{paywall_id}")
@ -23,4 +25,6 @@ async def display(request: Request, paywall_id):
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Paywall does not exist."
)
return paywall_renderer().TemplateResponse("paywall/display.html", {"request": request, "paywall": paywall})
return paywall_renderer().TemplateResponse(
"paywall/display.html", {"request": request, "paywall": paywall}
)

View File

@ -13,7 +13,9 @@ from .models import CheckPaywallInvoice, CreatePaywall, CreatePaywallInvoice
@paywall_ext.get("/api/v1/paywalls")
async def api_paywalls(wallet: WalletTypeInfo = Depends(get_key_type), all_wallets: bool = Query(False)):
async def api_paywalls(
wallet: WalletTypeInfo = Depends(get_key_type), all_wallets: bool = Query(False)
):
wallet_ids = [wallet.wallet.id]
if all_wallets:
@ -23,47 +25,51 @@ async def api_paywalls(wallet: WalletTypeInfo = Depends(get_key_type), all_walle
@paywall_ext.post("/api/v1/paywalls")
async def api_paywall_create(data: CreatePaywall, wallet: WalletTypeInfo = Depends(get_key_type)):
async def api_paywall_create(
data: CreatePaywall, wallet: WalletTypeInfo = Depends(get_key_type)
):
paywall = await create_paywall(wallet_id=wallet.wallet.id, data=data)
return paywall.dict()
@paywall_ext.delete("/api/v1/paywalls/{paywall_id}")
async def api_paywall_delete(paywall_id, wallet: WalletTypeInfo = Depends(get_key_type)):
async def api_paywall_delete(
paywall_id, wallet: WalletTypeInfo = Depends(get_key_type)
):
paywall = await get_paywall(paywall_id)
if not paywall:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Paywall does not exist."
)
status_code=HTTPStatus.NOT_FOUND, detail="Paywall does not exist."
)
if paywall.wallet != wallet.wallet.id:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN,
detail="Not your paywall."
)
status_code=HTTPStatus.FORBIDDEN, detail="Not your paywall."
)
await delete_paywall(paywall_id)
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
@paywall_ext.post("/api/v1/paywalls/{paywall_id}/invoice")
async def api_paywall_create_invoice(paywall_id, data: CreatePaywallInvoice, wallet: WalletTypeInfo = Depends(get_key_type)):
async def api_paywall_create_invoice(
paywall_id,
data: CreatePaywallInvoice,
wallet: WalletTypeInfo = Depends(get_key_type),
):
paywall = await get_paywall(paywall_id)
print("PAYW", paywall)
print("DATA", data)
if data.amount < paywall.amount:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail=f"Minimum amount is {paywall.amount} sat."
)
status_code=HTTPStatus.BAD_REQUEST,
detail=f"Minimum amount is {paywall.amount} sat.",
)
try:
amount = (
data.amount if data.amount > paywall.amount else paywall.amount
)
amount = data.amount if data.amount > paywall.amount else paywall.amount
payment_hash, payment_request = await create_invoice(
wallet_id=paywall.wallet,
amount=amount,
@ -71,10 +77,7 @@ async def api_paywall_create_invoice(paywall_id, data: CreatePaywallInvoice, wal
extra={"tag": "paywall"},
)
except Exception as e:
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=str(e)
)
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e))
return {"payment_hash": payment_hash, "payment_request": payment_request}
@ -85,9 +88,8 @@ async def api_paywal_check_invoice(data: CheckPaywallInvoice, paywall_id):
payment_hash = data.payment_hash
if not paywall:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Paywall does not exist."
)
status_code=HTTPStatus.NOT_FOUND, detail="Paywall does not exist."
)
try:
status = await check_invoice_status(paywall.wallet, payment_hash)

View File

@ -15,10 +15,7 @@ from .models import (
)
async def create_satsdice_pay(
wallet_id: str,
data: CreateSatsDiceLink,
) -> satsdiceLink:
async def create_satsdice_pay(wallet_id: str, data: CreateSatsDiceLink) -> satsdiceLink:
satsdice_id = urlsafe_short_hash()
await db.execute(
"""

View File

@ -49,9 +49,7 @@ async def api_lnurlp_response(req: Request, link_id: str = Query(None)):
name="satsdice.api_lnurlp_callback",
)
async def api_lnurlp_callback(
req: Request,
link_id: str = Query(None),
amount: str = Query(None),
req: Request, link_id: str = Query(None), amount: str = Query(None)
):
link = await get_satsdice_pay(link_id)
print(link)
@ -95,11 +93,7 @@ async def api_lnurlp_callback(
}
await create_satsdice_payment(data)
payResponse = {
"pr": payment_request,
"successAction": success_action,
"routes": [],
}
payResponse = {"pr": payment_request, "successAction": success_action, "routes": []}
print(json.dumps(payResponse))
return json.dumps(payResponse)

View File

@ -94,12 +94,7 @@ async def displaywin(
if not rand < chance or not status["paid"]:
return satsdice_renderer().TemplateResponse(
"satsdice/error.html",
{
"request": request,
"link": satsdicelink.id,
"paid": False,
"lost": True,
},
{"request": request, "link": satsdicelink.id, "paid": False, "lost": True},
)
await update_satsdice_payment(payment_hash, paid=1)
paylink = await get_satsdice_payment(payment_hash)

View File

@ -92,7 +92,6 @@ async def api_link_create_or_update(
detail="Come on, seriously, this isn't your satsdice!",
)
data.wallet = wallet.wallet.id
link = await update_satsdice_pay(link_id, **data.dict())
else:

View File

@ -10,6 +10,7 @@ class Target(BaseModel):
percent: int
alias: Optional[str]
class TargetPutList(BaseModel):
wallet: str = Query(...)
alias: str = Query("")

View File

@ -38,8 +38,7 @@ async def api_targets_set(
if wallet.id == wal.wallet.id:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="Can't split to itself.",
status_code=HTTPStatus.BAD_REQUEST, detail="Can't split to itself."
)
if entry.percent < 0:
@ -49,14 +48,18 @@ async def api_targets_set(
)
targets.append(
Target(wallet=wallet.id, source=wal.wallet.id, percent=entry.percent, alias=entry.alias)
Target(
wallet=wallet.id,
source=wal.wallet.id,
percent=entry.percent,
alias=entry.alias,
)
)
percent_sum = sum([target.percent for target in targets])
if percent_sum > 100:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="Splitting over 100%.",
status_code=HTTPStatus.BAD_REQUEST, detail="Splitting over 100%."
)
await set_targets(wal.wallet.id, targets)

View File

@ -5,13 +5,12 @@ from lnbits.helpers import template_renderer
db = Database("ext_streamalerts")
streamalerts_ext: APIRouter = APIRouter(
prefix="/streamalerts",
tags=["streamalerts"]
)
streamalerts_ext: APIRouter = APIRouter(prefix="/streamalerts", tags=["streamalerts"])
def streamalerts_renderer():
return template_renderer(["lnbits/extensions/streamalerts/templates"])
from .views import * # noqa
from .views_api import * # noqa

View File

@ -25,9 +25,7 @@ async def get_charge_details(service_id):
These might be different depending for services implemented in the future.
"""
details = {
"time": 1440,
}
details = {"time": 1440}
service = await get_service(service_id)
wallet_id = service.wallet
wallet = await get_wallet(wallet_id)
@ -111,9 +109,7 @@ async def post_donation(donation_id: str) -> tuple:
return response.json()
async def create_service(
data: CreateService
) -> Service:
async def create_service(data: CreateService) -> Service:
"""Create a new Service"""
returning = "" if db.type == SQLITE else "RETURNING ID"
@ -215,10 +211,7 @@ async def service_add_token(service_id, token):
return False
await db.execute(
"UPDATE streamalerts.Services SET authenticated = 1, token = ? where id = ?",
(
token,
service_id,
),
(token, service_id),
)
return True

View File

@ -13,12 +13,14 @@ class CreateService(BaseModel):
servicename: str = Query(...)
onchain: str = Query(None)
class CreateDonation(BaseModel):
name: str = Query("Anonymous")
sats: int = Query(..., ge=1)
service: int = Query(...)
message: str = Query("")
class ValidateDonation(BaseModel):
id: str = Query(...)

View File

@ -18,7 +18,9 @@ templates = Jinja2Templates(directory="templates")
@streamalerts_ext.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_user_exists)):
"""Return the extension's settings page"""
return streamalerts_renderer().TemplateResponse("streamalerts/index.html", {"request": request, "user": user.dict()})
return streamalerts_renderer().TemplateResponse(
"streamalerts/index.html", {"request": request, "user": user.dict()}
)
@streamalerts_ext.get("/{state}")
@ -31,9 +33,5 @@ async def donation(state, request: Request):
)
return streamalerts_renderer().TemplateResponse(
"streamalerts/display.html",
{
"request": request,
"twitchuser": service.twitchuser,
"service":service.id
}
{"request": request, "twitchuser": service.twitchuser, "service": service.id},
)

View File

@ -35,14 +35,14 @@ from .crud import (
@streamalerts_ext.post("/api/v1/services")
async def api_create_service(data : CreateService, wallet: WalletTypeInfo = Depends(get_key_type)):
async def api_create_service(
data: CreateService, wallet: WalletTypeInfo = Depends(get_key_type)
):
"""Create a service, which holds data about how/where to post donations"""
try:
service = await create_service(data=data)
except Exception as e:
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)
)
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e))
return service.dict()
@ -68,23 +68,24 @@ async def api_get_access(service_id, request: Request):
return RedirectResponse(redirect_url)
else:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="Service does not exist!"
status_code=HTTPStatus.BAD_REQUEST, detail="Service does not exist!"
)
@streamalerts_ext.get("/api/v1/authenticate/{service_id}")
async def api_authenticate_service(service_id, request: Request, code: str = Query(...), state: str = Query(...)):
async def api_authenticate_service(
service_id, request: Request, code: str = Query(...), state: str = Query(...)
):
"""Endpoint visited via redirect during third party API authentication
If successful, an API access token will be added to the service, and
the user will be redirected to index.html.
"""
service = await get_service(service_id)
if service.state != state:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="State doesn't match!"
status_code=HTTPStatus.BAD_REQUEST, detail="State doesn't match!"
)
redirect_uri = request.url.scheme + "://" + request.headers["Host"]
@ -94,8 +95,7 @@ async def api_authenticate_service(service_id, request: Request, code: str = Que
return RedirectResponse(url)
else:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="Service already authenticated!"
status_code=HTTPStatus.BAD_REQUEST, detail="Service already authenticated!"
)
@ -114,7 +114,7 @@ async def api_create_donation(data: CreateDonation, request: Request):
service = await get_service(service_id)
charge_details = await get_charge_details(service.id)
name = data.name
description = f"{sats} sats donation from {name} to {service.twitchuser}"
charge = await create_charge(
amount=sats,
@ -132,7 +132,7 @@ async def api_create_donation(data: CreateDonation, request: Request):
cur_code=cur_code,
sats=data.sats,
amount=amount,
service=data.service
service=data.service,
)
return {"redirect_url": f"/satspay/{charge.id}"}
@ -141,15 +141,14 @@ async def api_create_donation(data: CreateDonation, request: Request):
async def api_post_donation(request: Request, data: ValidateDonation):
"""Post a paid donation to Stremalabs/StreamElements.
This endpoint acts as a webhook for the SatsPayServer extension."""
donation_id = data.id
charge = await get_charge(donation_id)
if charge and charge.paid:
return await post_donation(donation_id)
else:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="Not a paid charge!"
status_code=HTTPStatus.BAD_REQUEST, detail="Not a paid charge!"
)
@ -178,58 +177,55 @@ async def api_get_donations(g: WalletTypeInfo = Depends(get_key_type)):
@streamalerts_ext.put("/api/v1/donations/{donation_id}")
async def api_update_donation(data: CreateDonation, donation_id=None, g: WalletTypeInfo = Depends(get_key_type)):
async def api_update_donation(
data: CreateDonation, donation_id=None, g: WalletTypeInfo = Depends(get_key_type)
):
"""Update a donation with the data given in the request"""
if donation_id:
donation = await get_donation(donation_id)
if not donation:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Donation does not exist."
status_code=HTTPStatus.NOT_FOUND, detail="Donation does not exist."
)
if donation.wallet != g.wallet.id:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN,
detail="Not your donation."
status_code=HTTPStatus.FORBIDDEN, detail="Not your donation."
)
donation = await update_donation(donation_id, **data.dict())
else:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="No donation ID specified"
)
status_code=HTTPStatus.BAD_REQUEST, detail="No donation ID specified"
)
return donation.dict()
@streamalerts_ext.put("/api/v1/services/{service_id}")
async def api_update_service(data: CreateService, service_id=None, g: WalletTypeInfo = Depends(get_key_type)):
async def api_update_service(
data: CreateService, service_id=None, g: WalletTypeInfo = Depends(get_key_type)
):
"""Update a service with the data given in the request"""
if service_id:
service = await get_service(service_id)
if not service:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Service does not exist."
status_code=HTTPStatus.NOT_FOUND, detail="Service does not exist."
)
if service.wallet != g.wallet.id:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN,
detail="Not your service."
status_code=HTTPStatus.FORBIDDEN, detail="Not your service."
)
service = await update_service(service_id, **data.dict())
else:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="No service ID specified"
)
status_code=HTTPStatus.BAD_REQUEST, detail="No service ID specified"
)
return service.dict()
@ -239,14 +235,13 @@ async def api_delete_donation(donation_id, g: WalletTypeInfo = Depends(get_key_t
donation = await get_donation(donation_id)
if not donation:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="No donation with this ID!"
)
status_code=HTTPStatus.NOT_FOUND, detail="No donation with this ID!"
)
if donation.wallet != g.wallet.id:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN,
detail="Not authorized to delete this donation!"
)
status_code=HTTPStatus.FORBIDDEN,
detail="Not authorized to delete this donation!",
)
await delete_donation(donation_id)
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
@ -257,13 +252,12 @@ async def api_delete_service(service_id, g: WalletTypeInfo = Depends(get_key_typ
service = await get_service(service_id)
if not service:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="No service with this ID!"
)
status_code=HTTPStatus.NOT_FOUND, detail="No service with this ID!"
)
if service.wallet != g.wallet.id:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN,
detail="Not authorized to delete this service!"
)
status_code=HTTPStatus.FORBIDDEN,
detail="Not authorized to delete this service!",
)
await delete_service(service_id)
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)

View File

@ -8,10 +8,8 @@ from lnbits.tasks import catch_everything_and_restart
db = Database("ext_subdomains")
subdomains_ext: APIRouter = APIRouter(
prefix="/subdomains",
tags=["subdomains"]
)
subdomains_ext: APIRouter = APIRouter(prefix="/subdomains", tags=["subdomains"])
def subdomains_renderer():
return template_renderer(["lnbits/extensions/subdomains/templates"])
@ -25,4 +23,3 @@ from .views_api import * # noqa
def subdomains_start():
loop = asyncio.get_event_loop()
loop.create_task(catch_everything_and_restart(wait_for_paid_invoices))

View File

@ -50,11 +50,7 @@ async def cloudflare_deletesubdomain(domain: Domains, domain_id: str):
}
async with httpx.AsyncClient() as client:
try:
r = await client.delete(
url + "/" + domain_id,
headers=header,
timeout=40,
)
r = await client.delete(url + "/" + domain_id, headers=header, timeout=40)
cf_response = r.text
except AssertionError:
cf_response = "Error occured"

View File

@ -6,11 +6,7 @@ from . import db
from .models import CreateDomain, Domains, Subdomains
async def create_subdomain(
payment_hash,
wallet,
data: CreateDomain
) -> Subdomains:
async def create_subdomain(payment_hash, wallet, data: CreateDomain) -> Subdomains:
await db.execute(
"""
INSERT INTO subdomains.subdomain (id, domain, email, subdomain, ip, wallet, sats, duration, paid, record_type)
@ -105,9 +101,7 @@ async def delete_subdomain(subdomain_id: str) -> None:
# Domains
async def create_domain(
data: CreateDomain
) -> Domains:
async def create_domain(data: CreateDomain) -> Domains:
domain_id = urlsafe_short_hash()
await db.execute(
"""

View File

@ -12,6 +12,7 @@ class CreateDomain(BaseModel):
cost: int = Query(..., ge=0)
allowed_record_types: str = Query(...)
class CreateSubdomain(BaseModel):
domain: str = Query(...)
subdomain: str = Query(...)
@ -21,6 +22,7 @@ class CreateSubdomain(BaseModel):
duration: int = Query(...)
record_type: str = Query(...)
class Domains(BaseModel):
id: str
wallet: str
@ -34,6 +36,7 @@ class Domains(BaseModel):
time: int
allowed_record_types: str
class Subdomains(BaseModel):
id: str
wallet: str

View File

@ -17,6 +17,7 @@ async def wait_for_paid_invoices():
payment = await invoice_queue.get()
await on_invoice_paid(payment)
# async def register_listeners():
# invoice_paid_chan_send, invoice_paid_chan_recv = trio.open_memory_channel(2)
# register_invoice_listener(invoice_paid_chan_send)

View File

@ -14,9 +14,12 @@ from .crud import get_domain
templates = Jinja2Templates(directory="templates")
@subdomains_ext.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_user_exists)):
return subdomains_renderer().TemplateResponse("subdomains/index.html", {"request": request, "user": user.dict()})
return subdomains_renderer().TemplateResponse(
"subdomains/index.html", {"request": request, "user": user.dict()}
)
@subdomains_ext.get("/{domain_id}")
@ -24,20 +27,20 @@ async def display(request: Request, domain_id):
domain = await get_domain(domain_id)
if not domain:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Domain does not exist."
status_code=HTTPStatus.NOT_FOUND, detail="Domain does not exist."
)
allowed_records = (
domain.allowed_record_types.replace('"', "").replace(" ", "").split(",")
)
return subdomains_renderer().TemplateResponse(
"subdomains/display.html",{
"subdomains/display.html",
{
"request": request,
"domain_id": domain.id,
"domain_domain": domain.domain,
"domain_desc": domain.description,
"domain_cost": domain.cost,
"domain_allowed_record_types": allowed_records,
}
},
)

View File

@ -28,7 +28,9 @@ from .crud import (
@subdomains_ext.get("/api/v1/domains")
async def api_domains(g: WalletTypeInfo = Depends(get_key_type), all_wallets: bool = Query(False)):
async def api_domains(
g: WalletTypeInfo = Depends(get_key_type), all_wallets: bool = Query(False)
):
wallet_ids = [g.wallet.id]
if all_wallets:
@ -39,19 +41,19 @@ async def api_domains(g: WalletTypeInfo = Depends(get_key_type), all_wallets: bo
@subdomains_ext.post("/api/v1/domains")
@subdomains_ext.put("/api/v1/domains/{domain_id}")
async def api_domain_create(data: CreateDomain, domain_id=None, g: WalletTypeInfo = Depends(get_key_type)):
async def api_domain_create(
data: CreateDomain, domain_id=None, g: WalletTypeInfo = Depends(get_key_type)
):
if domain_id:
domain = await get_domain(domain_id)
if not domain:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Domain does not exist."
status_code=HTTPStatus.NOT_FOUND, detail="Domain does not exist."
)
if domain.wallet != g.wallet.id:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN,
detail="Not your domain."
status_code=HTTPStatus.FORBIDDEN, detail="Not your domain."
)
domain = await update_domain(domain_id, **data.dict())
@ -66,14 +68,10 @@ async def api_domain_delete(domain_id, g: WalletTypeInfo = Depends(get_key_type)
if not domain:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Domain does not exist."
)
status_code=HTTPStatus.NOT_FOUND, detail="Domain does not exist."
)
if domain.wallet != g.wallet.id:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN,
detail="Not your domain."
)
raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail="Not your domain.")
await delete_domain(domain_id)
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
@ -83,7 +81,9 @@ async def api_domain_delete(domain_id, g: WalletTypeInfo = Depends(get_key_type)
@subdomains_ext.get("/api/v1/subdomains")
async def api_subdomains(all_wallets: bool = Query(False), g: WalletTypeInfo = Depends(get_key_type)):
async def api_subdomains(
all_wallets: bool = Query(False), g: WalletTypeInfo = Depends(get_key_type)
):
wallet_ids = [g.wallet.id]
if all_wallets:
@ -99,22 +99,21 @@ async def api_subdomain_make_subdomain(domain_id, data: CreateSubdomain):
# If the request is coming for the non-existant domain
if not domain:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="LNsubdomain does not exist."
)
status_code=HTTPStatus.NOT_FOUND, detail="LNsubdomain does not exist."
)
## If record_type is not one of the allowed ones reject the request
if data.record_type not in domain.allowed_record_types:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail=f"{data.record_type} not a valid record."
)
status_code=HTTPStatus.BAD_REQUEST,
detail=f"{data.record_type} not a valid record.",
)
## If domain already exist in our database reject it
if await get_subdomainBySubdomain(data.subdomain) is not None:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail=f"{data.subdomain}.{domain.domain} domain already taken."
)
status_code=HTTPStatus.BAD_REQUEST,
detail=f"{data.subdomain}.{domain.domain} domain already taken.",
)
## Dry run cloudflare... (create and if create is sucessful delete it)
cf_response = await cloudflare_create_subdomain(
@ -124,12 +123,14 @@ async def api_subdomain_make_subdomain(domain_id, data: CreateSubdomain):
ip=data.ip,
)
if cf_response["success"] == True:
await cloudflare_deletesubdomain(domain=domain, domain_id=cf_response["result"]["id"])
await cloudflare_deletesubdomain(
domain=domain, domain_id=cf_response["result"]["id"]
)
else:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail=f'Problem with cloudflare: {cf_response["errors"][0]["message"]}'
)
status_code=HTTPStatus.BAD_REQUEST,
detail=f'Problem with cloudflare: {cf_response["errors"][0]["message"]}',
)
## ALL OK - create an invoice and return it to the user
sats = data.sats
@ -142,10 +143,7 @@ async def api_subdomain_make_subdomain(domain_id, data: CreateSubdomain):
extra={"tag": "lnsubdomain"},
)
except Exception as e:
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=str(e)
)
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e))
subdomain = await create_subdomain(
payment_hash=payment_hash, wallet=domain.wallet, data=data
@ -153,9 +151,8 @@ async def api_subdomain_make_subdomain(domain_id, data: CreateSubdomain):
if not subdomain:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="LNsubdomain could not be fetched."
)
status_code=HTTPStatus.NOT_FOUND, detail="LNsubdomain could not be fetched."
)
return {"payment_hash": payment_hash, "payment_request": payment_request}
@ -181,15 +178,13 @@ async def api_subdomain_delete(subdomain_id, g: WalletTypeInfo = Depends(get_key
if not subdomain:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="LNsubdomain does not exist."
)
status_code=HTTPStatus.NOT_FOUND, detail="LNsubdomain does not exist."
)
if subdomain.wallet != g.wallet.id:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN,
detail="Not your subdomain."
)
status_code=HTTPStatus.FORBIDDEN, detail="Not your subdomain."
)
await delete_subdomain(subdomain_id)
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)

View File

@ -9,12 +9,7 @@ from lnbits.db import SQLITE
async def create_tip(
id: int,
wallet: str,
message: str,
name: str,
sats: int,
tipjar: str,
id: int, wallet: str, message: str, name: str, sats: int, tipjar: str
) -> Tip:
"""Create a new Tip"""
await db.execute(
@ -110,8 +105,7 @@ async def update_tip(tip_id: str, **kwargs) -> Tip:
"""Update a Tip"""
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
await db.execute(
f"UPDATE tipjar.Tips SET {q} WHERE id = ?",
(*kwargs.values(), tip_id),
f"UPDATE tipjar.Tips SET {q} WHERE id = ?", (*kwargs.values(), tip_id)
)
row = await db.fetchone("SELECT * FROM tipjar.Tips WHERE id = ?", (tip_id,))
assert row, "Newly updated tip couldn't be retrieved"
@ -122,8 +116,7 @@ async def update_tipjar(tipjar_id: str, **kwargs) -> TipJar:
"""Update a tipjar"""
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
await db.execute(
f"UPDATE tipjar.TipJars SET {q} WHERE id = ?",
(*kwargs.values(), tipjar_id),
f"UPDATE tipjar.TipJars SET {q} WHERE id = ?", (*kwargs.values(), tipjar_id)
)
row = await db.fetchone("SELECT * FROM tipjar.TipJars WHERE id = ?", (tipjar_id,))
assert row, "Newly updated tipjar couldn't be retrieved"

View File

@ -6,10 +6,7 @@ from fastapi.params import Depends
from lnurl.exceptions import InvalidUrl as LnurlInvalidUrl # type: ignore
from starlette.exceptions import HTTPException
from lnbits.decorators import (
WalletTypeInfo,
get_key_type,
)
from lnbits.decorators import WalletTypeInfo, get_key_type
from lnbits.core.crud import get_user
from . import tipjar_ext
@ -193,8 +190,7 @@ async def api_delete_tipjar(
tipjar = await get_tipjar(tipjar_id)
if not tipjar:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="No tipjar with this ID!",
status_code=HTTPStatus.NOT_FOUND, detail="No tipjar with this ID!"
)
if tipjar.wallet != g.wallet.id:

View File

@ -5,10 +5,7 @@ from lnbits.helpers import template_renderer
db = Database("ext_tpos")
tpos_ext: APIRouter = APIRouter(
prefix="/tpos",
tags=["TPoS"]
)
tpos_ext: APIRouter = APIRouter(prefix="/tpos", tags=["TPoS"])
def tpos_renderer():

View File

@ -5,10 +5,7 @@ from lnbits.helpers import template_renderer
db = Database("ext_usermanager")
usermanager_ext: APIRouter = APIRouter(
prefix="/usermanager",
tags=["usermanager"]
)
usermanager_ext: APIRouter = APIRouter(prefix="/usermanager", tags=["usermanager"])
def usermanager_renderer():

View File

@ -11,6 +11,7 @@ class CreateUserData(BaseModel):
email: str = Query("")
password: str = Query("")
class CreateUserWallet(BaseModel):
user_id: str = Query(...)
wallet_name: str = Query(...)

View File

@ -93,10 +93,11 @@ async def api_usermanager_activate_extension(
@usermanager_ext.post("/api/v1/wallets")
async def api_usermanager_wallets_create(
data: CreateUserWallet,
wallet: WalletTypeInfo = Depends(get_key_type)
data: CreateUserWallet, wallet: WalletTypeInfo = Depends(get_key_type)
):
user = await create_usermanager_wallet(user_id=data.user_id, wallet_name=data.wallet_name, admin_id=data.admin_id)
user = await create_usermanager_wallet(
user_id=data.user_id, wallet_name=data.wallet_name, admin_id=data.admin_id
)
return user.dict()

View File

@ -93,11 +93,12 @@ async def api_lnurl_multi_response(request: Request, unique_hash, id_unique_hash
# CALLBACK
@withdraw_ext.get(
"/api/v1/lnurl/cb/{unique_hash}",
status_code=HTTPStatus.OK,
name="withdraw.api_lnurl_callback"
)
"/api/v1/lnurl/cb/{unique_hash}",
status_code=HTTPStatus.OK,
name="withdraw.api_lnurl_callback",
)
async def api_lnurl_callback(
request: Request,
unique_hash: str = Query(...),
@ -153,4 +154,3 @@ async def api_lnurl_callback(
except Exception as e:
await update_withdraw_link(link.id, **changesback)
return {"status": "ERROR", "reason": "Link not working"}

View File

@ -46,7 +46,9 @@ async def api_links(
@withdraw_ext.get("/api/v1/links/{link_id}", status_code=HTTPStatus.OK)
async def api_link_retrieve(link_id, request: Request, wallet: WalletTypeInfo = Depends(get_key_type)):
async def api_link_retrieve(
link_id, request: Request, wallet: WalletTypeInfo = Depends(get_key_type)
):
link = await get_withdraw_link(link_id, 0)
if not link:
@ -93,7 +95,9 @@ async def api_link_create_or_update(
raise HTTPException(
detail="Not your withdraw link.", status_code=HTTPStatus.FORBIDDEN
)
link = await update_withdraw_link(link_id, **data.dict(), usescsv=usescsv, used=0)
link = await update_withdraw_link(
link_id, **data.dict(), usescsv=usescsv, used=0
)
else:
link = await create_withdraw_link(
wallet_id=wallet.wallet.id, data=data, usescsv=usescsv

View File

@ -234,13 +234,14 @@ async def btc_price(currency: str) -> float:
failures += 1
if len(rates) >= 2 or len(rates) == 1 and failures >= 2:
for t in tasks: t.cancel()
for t in tasks:
t.cancel()
break
if failures == len(exchange_rate_providers):
for t in tasks: t.cancel()
for t in tasks:
t.cancel()
break
async def fetch_price(provider: Provider):
url = provider.api_url.format(**replacements)
try:
@ -251,19 +252,18 @@ async def btc_price(currency: str) -> float:
rate = float(provider.getter(data, replacements))
await send_channel.put(rate)
except (
TypeError, # CoinMate returns HTTPStatus 200 but no data when a currency pair is not found
TypeError, # CoinMate returns HTTPStatus 200 but no data when a currency pair is not found
httpx.ConnectTimeout,
httpx.ConnectError,
httpx.ReadTimeout,
httpx.HTTPStatusError, # Some providers throw a 404 when a currency pair is not found
httpx.HTTPStatusError, # Some providers throw a 404 when a currency pair is not found
):
await send_channel.put(None)
asyncio.create_task(controller())
for _, provider in exchange_rate_providers.items():
tasks.append(asyncio.create_task(fetch_price(provider)))
try:
await asyncio.gather(*tasks)
except asyncio.CancelledError:

View File

@ -139,4 +139,4 @@ class CLightningWallet(Wallet):
wrapped = async_wrap(_paid_invoices_stream)
paid = await wrapped(self.ln, self.last_pay_index)
self.last_pay_index = paid["pay_index"]
yield paid["label"]
yield paid["label"]

File diff suppressed because one or more lines are too long