black formating

This commit is contained in:
callebtc 2022-06-01 14:53:05 +02:00
parent 7c4ce9bf96
commit f8400512f7
28 changed files with 127 additions and 81 deletions

View File

@ -1,6 +1,7 @@
import psycopg2
import sqlite3
import os
# Python script to migrate an LNbits SQLite DB to Postgres
# All credits to @Fritz446 for the awesome work

View File

@ -165,7 +165,7 @@ def lnencode(addr, privkey):
if addr.amount:
amount = Decimal(str(addr.amount))
# We can only send down to millisatoshi.
if amount * 10 ** 12 % 10:
if amount * 10**12 % 10:
raise ValueError(
"Cannot encode {}: too many decimal places".format(addr.amount)
)
@ -270,7 +270,7 @@ class LnAddr(object):
def shorten_amount(amount):
"""Given an amount in bitcoin, shorten it"""
# Convert to pico initially
amount = int(amount * 10 ** 12)
amount = int(amount * 10**12)
units = ["p", "n", "u", "m", ""]
for unit in units:
if amount % 1000 == 0:
@ -289,7 +289,7 @@ def _unshorten_amount(amount: str) -> int:
# * `u` (micro): multiply by 0.000001
# * `n` (nano): multiply by 0.000000001
# * `p` (pico): multiply by 0.000000000001
units = {"p": 10 ** 12, "n": 10 ** 9, "u": 10 ** 6, "m": 10 ** 3}
units = {"p": 10**12, "n": 10**9, "u": 10**6, "m": 10**3}
unit = str(amount)[-1]
# BOLT #11:
@ -348,9 +348,9 @@ def _trim_to_bytes(barr):
def _readable_scid(short_channel_id: int) -> str:
return "{blockheight}x{transactionindex}x{outputindex}".format(
blockheight=((short_channel_id >> 40) & 0xffffff),
transactionindex=((short_channel_id >> 16) & 0xffffff),
outputindex=(short_channel_id & 0xffff),
blockheight=((short_channel_id >> 40) & 0xFFFFFF),
transactionindex=((short_channel_id >> 16) & 0xFFFFFF),
outputindex=(short_channel_id & 0xFFFF),
)

View File

@ -391,7 +391,11 @@ async def api_payment(payment_hash, X_Api_Key: Optional[str] = Header(None)):
return {"paid": False}
if wallet and wallet.id == payment.wallet_id:
return {"paid": not payment.pending, "preimage": payment.preimage, "details": payment}
return {
"paid": not payment.pending,
"preimage": payment.preimage,
"details": payment,
}
return {"paid": not payment.pending, "preimage": payment.preimage}

View File

@ -226,7 +226,9 @@ async def lnurl_balance_notify(request: Request, service: str):
redeem_lnurl_withdraw(bc.wallet, bc.url)
@core_html_routes.get("/lnurlwallet", response_class=RedirectResponse, name="core.lnurlwallet")
@core_html_routes.get(
"/lnurlwallet", response_class=RedirectResponse, name="core.lnurlwallet"
)
async def lnurlwallet(request: Request):
async with db.connect() as conn:
account = await create_account(conn=conn)

View File

@ -13,7 +13,11 @@ from starlette.requests import Request
from lnbits.core.crud import get_user, get_wallet_for_key
from lnbits.core.models import User, Wallet
from lnbits.requestvars import g
from lnbits.settings import LNBITS_ALLOWED_USERS, LNBITS_ADMIN_USERS, LNBITS_ADMIN_EXTENSIONS
from lnbits.settings import (
LNBITS_ALLOWED_USERS,
LNBITS_ADMIN_USERS,
LNBITS_ADMIN_EXTENSIONS,
)
class KeyChecker(SecurityBase):
@ -122,7 +126,7 @@ async def get_key_type(
# 0: admin
# 1: invoice
# 2: invalid
pathname = r['path'].split('/')[1]
pathname = r["path"].split("/")[1]
if not api_key_header and not api_key_query:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST)
@ -133,8 +137,12 @@ async def get_key_type(
checker = WalletAdminKeyChecker(api_key=token)
await checker.__call__(r)
wallet = WalletTypeInfo(0, checker.wallet)
if (LNBITS_ADMIN_USERS and wallet.wallet.user not in LNBITS_ADMIN_USERS) and (LNBITS_ADMIN_EXTENSIONS and pathname in LNBITS_ADMIN_EXTENSIONS):
raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized.")
if (LNBITS_ADMIN_USERS and wallet.wallet.user not in LNBITS_ADMIN_USERS) and (
LNBITS_ADMIN_EXTENSIONS and pathname in LNBITS_ADMIN_EXTENSIONS
):
raise HTTPException(
status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized."
)
return wallet
except HTTPException as e:
if e.status_code == HTTPStatus.BAD_REQUEST:
@ -148,8 +156,12 @@ async def get_key_type(
checker = WalletInvoiceKeyChecker(api_key=token)
await checker.__call__(r)
wallet = WalletTypeInfo(1, checker.wallet)
if (LNBITS_ADMIN_USERS and wallet.wallet.user not in LNBITS_ADMIN_USERS) and (LNBITS_ADMIN_EXTENSIONS and pathname in LNBITS_ADMIN_EXTENSIONS):
raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized.")
if (LNBITS_ADMIN_USERS and wallet.wallet.user not in LNBITS_ADMIN_USERS) and (
LNBITS_ADMIN_EXTENSIONS and pathname in LNBITS_ADMIN_EXTENSIONS
):
raise HTTPException(
status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized."
)
return wallet
except HTTPException as e:
if e.status_code == HTTPStatus.BAD_REQUEST:

View File

@ -11,6 +11,7 @@ class CreateUserData(BaseModel):
admin_id: str = Query(...)
discord_id: str = Query("")
class CreateUserWallet(BaseModel):
user_id: str = Query(...)
wallet_name: str = Query(...)
@ -23,6 +24,7 @@ class Users(BaseModel):
admin: str
discord_id: str
class Wallets(BaseModel):
id: str
admin: str

View File

@ -109,9 +109,7 @@ async def api_discordbot_wallet_transactions(
async def api_discordbot_users_wallets(
user_id, wallet: WalletTypeInfo = Depends(get_key_type)
):
return [
s_wallet.dict() for s_wallet in await get_discordbot_users_wallets(user_id)
]
return [s_wallet.dict() for s_wallet in await get_discordbot_users_wallets(user_id)]
@discordbot_ext.delete("/api/v1/wallets/{wallet_id}")

View File

@ -5,10 +5,7 @@ from lnbits.helpers import template_renderer
db = Database("ext_example")
example_ext: APIRouter = APIRouter(
prefix="/example",
tags=["example"]
)
example_ext: APIRouter = APIRouter(prefix="/example", tags=["example"])
def example_renderer():

View File

@ -3,4 +3,3 @@
# class Example(BaseModel):
# id: str
# wallet: str

View File

@ -10,6 +10,7 @@ from . import example_ext
# add your endpoints here
@example_ext.get("/api/v1/tools")
async def api_example():
"""Try to add descriptions for others."""

View File

@ -41,7 +41,7 @@ async def update_jukebox(
q = ", ".join([f"{field[0]} = ?" for field in data])
items = [f"{field[1]}" for field in data]
items.append(juke_id)
q = q.replace("user", '"user"', 1) # hack to make user be "user"!
q = q.replace("user", '"user"', 1) # hack to make user be "user"!
await db.execute(f"UPDATE jukebox.jukebox SET {q} WHERE id = ?", (items))
row = await db.fetchone("SELECT * FROM jukebox.jukebox WHERE id = ?", (juke_id,))
return Jukebox(**row) if row else None

View File

@ -455,5 +455,6 @@ async def api_get_jukebox_currently(
)
except:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Something went wrong, or no song is playing yet"
status_code=HTTPStatus.NOT_FOUND,
detail="Something went wrong, or no song is playing yet",
)

View File

@ -1,4 +1,5 @@
from http import HTTPStatus
# from mmap import MAP_DENYWRITE
from fastapi.param_functions import Depends

View File

@ -8,8 +8,8 @@ def hotp(key, counter, digits=6, digest="sha1"):
key = base64.b32decode(key.upper() + "=" * ((8 - len(key)) % 8))
counter = struct.pack(">Q", counter)
mac = hmac.new(key, counter, digest).digest()
offset = mac[-1] & 0x0f
binary = struct.unpack(">L", mac[offset : offset + 4])[0] & 0x7fffffff
offset = mac[-1] & 0x0F
binary = struct.unpack(">L", mac[offset : offset + 4])[0] & 0x7FFFFFFF
return str(binary)[-digits:].zfill(digits)

View File

@ -54,8 +54,7 @@ async def api_paywall_delete(
@paywall_ext.post("/api/v1/paywalls/invoice/{paywall_id}")
async def api_paywall_create_invoice(
data: CreatePaywallInvoice,
paywall_id: str = Query(None)
data: CreatePaywallInvoice, paywall_id: str = Query(None)
):
paywall = await get_paywall(paywall_id)
if data.amount < paywall.amount:
@ -78,7 +77,9 @@ async def api_paywall_create_invoice(
@paywall_ext.post("/api/v1/paywalls/check_invoice/{paywall_id}")
async def api_paywal_check_invoice(data: CheckPaywallInvoice, paywall_id: str = Query(None)):
async def api_paywal_check_invoice(
data: CheckPaywallInvoice, paywall_id: str = Query(None)
):
paywall = await get_paywall(paywall_id)
payment_hash = data.payment_hash
if not paywall:

View File

@ -123,7 +123,7 @@ async def api_create_donation(data: CreateDonation, request: Request):
completelinktext="Back to Stream!",
webhook=webhook_base + "/streamalerts/api/v1/postdonation",
description=description,
**charge_details
**charge_details,
)
charge = await create_charge(user=charge_details["user"], data=create_charge_data)
await create_donation(

View File

@ -30,7 +30,9 @@ async def api_lnurl_response(request: Request, unique_hash):
)
if link.is_spent:
raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="Withdraw is spent.")
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Withdraw is spent."
)
url = request.url_for("withdraw.api_lnurl_callback", unique_hash=link.unique_hash)
withdrawResponse = {
"tag": "withdrawRequest",
@ -48,7 +50,11 @@ async def api_lnurl_response(request: Request, unique_hash):
@withdraw_ext.get("/api/v1/lnurl/cb/{unique_hash}", name="withdraw.api_lnurl_callback")
async def api_lnurl_callback(
unique_hash, request: Request, k1: str = Query(...), pr: str = Query(...), id_unique_hash=None
unique_hash,
request: Request,
k1: str = Query(...),
pr: str = Query(...),
id_unique_hash=None,
):
link = await get_withdraw_link_by_hash(unique_hash)
now = int(datetime.now().timestamp())
@ -58,7 +64,9 @@ async def api_lnurl_callback(
)
if link.is_spent:
raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="Withdraw is spent.")
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Withdraw is spent."
)
if link.k1 != k1:
raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="Bad request.")
@ -81,7 +89,7 @@ async def api_lnurl_callback(
if id_unique_hash == shortuuid.uuid(name=tohash):
found = True
useslist.pop(ind)
usescsv = ','.join(useslist)
usescsv = ",".join(useslist)
if not found:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="LNURL-withdraw not found."
@ -134,7 +142,9 @@ async def api_lnurl_multi_response(request: Request, unique_hash, id_unique_hash
)
if link.is_spent:
raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="Withdraw is spent.")
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Withdraw is spent."
)
useslist = link.usescsv.split(",")
found = False

View File

@ -103,6 +103,7 @@ async def print_qr(request: Request, link_id):
"withdraw/print_qr.html", {"request": request, "link": linked, "unique": True}
)
@withdraw_ext.get("/csv/{link_id}", response_class=HTMLResponse)
async def print_qr(request: Request, link_id):
link = await get_withdraw_link(link_id)
@ -135,4 +136,4 @@ async def print_qr(request: Request, link_id):
return withdraw_renderer().TemplateResponse(
"withdraw/csv.html", {"request": request, "link": linked, "unique": True}
)
)

View File

@ -72,10 +72,8 @@ async def api_link_create_or_update(
wallet: WalletTypeInfo = Depends(require_admin_key),
):
if data.uses > 250:
raise HTTPException(
detail="250 uses max.", status_code=HTTPStatus.BAD_REQUEST
)
raise HTTPException(detail="250 uses max.", status_code=HTTPStatus.BAD_REQUEST)
if data.min_withdrawable < 1:
raise HTTPException(
detail="Min must be more than 1.", status_code=HTTPStatus.BAD_REQUEST

View File

@ -26,7 +26,9 @@ class Extension(NamedTuple):
class ExtensionManager:
def __init__(self):
self._disabled: List[str] = settings.LNBITS_DISABLED_EXTENSIONS
self._admin_only: List[str] = [x.strip(' ') for x in settings.LNBITS_ADMIN_EXTENSIONS]
self._admin_only: List[str] = [
x.strip(" ") for x in settings.LNBITS_ADMIN_EXTENSIONS
]
self._extension_folders: List[str] = [
x[1] for x in os.walk(os.path.join(settings.LNBITS_PATH, "extensions"))
][0]

View File

@ -29,7 +29,9 @@ LNBITS_ALLOWED_USERS: List[str] = env.list(
"LNBITS_ALLOWED_USERS", default=[], subcast=str
)
LNBITS_ADMIN_USERS: List[str] = env.list("LNBITS_ADMIN_USERS", default=[], subcast=str)
LNBITS_ADMIN_EXTENSIONS: List[str] = env.list("LNBITS_ADMIN_EXTENSIONS", default=[], subcast=str)
LNBITS_ADMIN_EXTENSIONS: List[str] = env.list(
"LNBITS_ADMIN_EXTENSIONS", default=[], subcast=str
)
LNBITS_DISABLED_EXTENSIONS: List[str] = env.list(
"LNBITS_DISABLED_EXTENSIONS", default=[], subcast=str
)

View File

@ -29,6 +29,7 @@ class EclairError(Exception):
class UnknownError(Exception):
pass
class EclairWallet(Wallet):
def __init__(self):
url = getenv("ECLAIR_URL")
@ -41,13 +42,10 @@ class EclairWallet(Wallet):
auth = str(encodedAuth, "utf-8")
self.auth = {"Authorization": f"Basic {auth}"}
async def status(self) -> StatusResponse:
async with httpx.AsyncClient() as client:
r = await client.post(
f"{self.url}/usablebalances",
headers=self.auth,
timeout=40
f"{self.url}/usablebalances", headers=self.auth, timeout=40
)
try:
data = r.json()
@ -55,7 +53,7 @@ class EclairWallet(Wallet):
return StatusResponse(
f"Failed to connect to {self.url}, got: '{r.text[:200]}...'", 0
)
if r.is_error:
return StatusResponse(data["error"], 0)
@ -76,10 +74,7 @@ class EclairWallet(Wallet):
async with httpx.AsyncClient() as client:
r = await client.post(
f"{self.url}/createinvoice",
headers=self.auth,
data=data,
timeout=40
f"{self.url}/createinvoice", headers=self.auth, data=data, timeout=40
)
if r.is_error:
@ -95,7 +90,6 @@ class EclairWallet(Wallet):
data = r.json()
return InvoiceResponse(True, data["paymentHash"], data["serialized"], None)
async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse:
async with httpx.AsyncClient() as client:
r = await client.post(
@ -113,10 +107,9 @@ class EclairWallet(Wallet):
error_message = r.text
pass
return PaymentResponse(False, None, 0, None, error_message)
data = r.json()
checking_id = data["paymentHash"]
preimage = data["paymentPreimage"]
@ -135,22 +128,22 @@ class EclairWallet(Wallet):
except:
error_message = r.text
pass
return PaymentResponse(True, checking_id, 0, preimage, error_message) ## ?? is this ok ??
return PaymentResponse(
True, checking_id, 0, preimage, error_message
) ## ?? is this ok ??
data = r.json()
fees = [i["status"] for i in data]
fee_msat = sum([i["feesPaid"] for i in fees])
return PaymentResponse(True, checking_id, fee_msat, preimage, None)
return PaymentResponse(True, checking_id, fee_msat, preimage, None)
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
async with httpx.AsyncClient() as client:
r = await client.post(
f"{self.url}/getreceivedinfo",
headers=self.auth,
data={"paymentHash": checking_id}
data={"paymentHash": checking_id},
)
data = r.json()
@ -160,31 +153,33 @@ class EclairWallet(Wallet):
if data["status"]["type"] != "received":
return PaymentStatus(False)
return PaymentStatus(True)
return PaymentStatus(True)
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
async with httpx.AsyncClient() as client:
r = await client.post(
url=f"{self.url}/getsentinfo",
headers=self.auth,
data={"paymentHash": checking_id}
data={"paymentHash": checking_id},
)
data = r.json()[0]
if r.is_error:
return PaymentStatus(None)
if data["status"]["type"] != "sent":
return PaymentStatus(False)
return PaymentStatus(True)
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
try:
async with connect(self.ws_url, extra_headers=[('Authorization', self.auth["Authorization"])]) as ws:
async with connect(
self.ws_url,
extra_headers=[("Authorization", self.auth["Authorization"])],
) as ws:
while True:
message = await ws.recv()
message = json.loads(message)
@ -192,8 +187,13 @@ class EclairWallet(Wallet):
if message and message["type"] == "payment-received":
yield message["paymentHash"]
except (OSError, ConnectionClosedOK, ConnectionClosedError, ConnectionClosed) as ose:
print('OSE', ose)
except (
OSError,
ConnectionClosedOK,
ConnectionClosedError,
ConnectionClosed,
) as ose:
print("OSE", ose)
pass
print("lost connection to eclair's websocket, retrying in 5 seconds")

View File

@ -1 +1 @@
from .macaroon import load_macaroon, AESCipher
from .macaroon import load_macaroon, AESCipher

View File

@ -5,10 +5,11 @@ from hashlib import md5
import getpass
BLOCK_SIZE = 16
import getpass
import getpass
def load_macaroon(macaroon: str) -> str:
"""Returns hex version of a macaroon encoded in base64 or the file path.
"""Returns hex version of a macaroon encoded in base64 or the file path.
:param macaroon: Macaroon encoded in base64 or file path.
:type macaroon: str
@ -29,6 +30,7 @@ def load_macaroon(macaroon: str) -> str:
pass
return macaroon
class AESCipher(object):
"""This class is compatible with crypto-js/aes.js
@ -39,6 +41,7 @@ class AESCipher(object):
AES.decrypt(encrypted, password).toString(Utf8);
"""
def __init__(self, key=None, description=""):
self.key = key
self.description = description + " "
@ -47,7 +50,6 @@ class AESCipher(object):
length = BLOCK_SIZE - (len(data) % BLOCK_SIZE)
return data + (chr(length) * length).encode()
def unpad(self, data):
return data[: -(data[-1] if type(data[-1]) == int else ord(data[-1]))]
@ -70,8 +72,7 @@ class AESCipher(object):
return final_key[:output]
def decrypt(self, encrypted: str) -> str:
"""Decrypts a string using AES-256-CBC.
"""
"""Decrypts a string using AES-256-CBC."""
passphrase = self.passphrase
encrypted = base64.b64decode(encrypted)
assert encrypted[0:8] == b"Salted__"
@ -92,7 +93,10 @@ class AESCipher(object):
key = key_iv[:32]
iv = key_iv[32:]
aes = AES.new(key, AES.MODE_CBC, iv)
return base64.b64encode(b"Salted__" + salt + aes.encrypt(self.pad(message))).decode()
return base64.b64encode(
b"Salted__" + salt + aes.encrypt(self.pad(message))
).decode()
# if this file is executed directly, ask for a macaroon and encrypt it
if __name__ == "__main__":

View File

@ -19,9 +19,10 @@ def app():
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()
@pytest.fixture
async def client(app):
client = AsyncClient(app=app, base_url=f'http://{HOST}:{PORT}')
client = AsyncClient(app=app, base_url=f"http://{HOST}:{PORT}")
# yield and pass the client to the test
yield client
# close the async client after the test has finished

View File

@ -1,6 +1,7 @@
import pytest
from tests.conftest import client
@pytest.mark.asyncio
async def test_core_views_generic(client):
response = await client.get("/")

View File

@ -4,16 +4,22 @@ import secrets
from lnbits.core.crud import create_account, create_wallet
from lnbits.extensions.bleskomat.crud import create_bleskomat, create_bleskomat_lnurl
from lnbits.extensions.bleskomat.models import CreateBleskomat
from lnbits.extensions.bleskomat.helpers import generate_bleskomat_lnurl_secret, generate_bleskomat_lnurl_signature, prepare_lnurl_params, query_to_signing_payload
from lnbits.extensions.bleskomat.helpers import (
generate_bleskomat_lnurl_secret,
generate_bleskomat_lnurl_signature,
prepare_lnurl_params,
query_to_signing_payload,
)
from lnbits.extensions.bleskomat.exchange_rates import exchange_rate_providers
exchange_rate_providers["dummy"] = {
"name": "dummy",
"domain": None,
"api_url": None,
"getter": lambda data, replacements: str(1e8),# 1 BTC = 100000000 sats
"getter": lambda data, replacements: str(1e8), # 1 BTC = 100000000 sats
}
@pytest.fixture
async def bleskomat():
user = await create_account()
@ -22,11 +28,12 @@ async def bleskomat():
name="Test Bleskomat",
fiat_currency="EUR",
exchange_rate_provider="dummy",
fee="0"
fee="0",
)
bleskomat = await create_bleskomat(data=data, wallet_id=wallet.id)
return bleskomat
@pytest.fixture
async def lnurl(bleskomat):
query = {
@ -43,7 +50,7 @@ async def lnurl(bleskomat):
signature = generate_bleskomat_lnurl_signature(
payload=payload,
api_key_secret=bleskomat.api_key_secret,
api_key_encoding=bleskomat.api_key_encoding
api_key_encoding=bleskomat.api_key_encoding,
)
secret = generate_bleskomat_lnurl_secret(bleskomat.api_key_id, signature)
params = json.JSONEncoder().encode(params)

View File

@ -2,6 +2,7 @@ import hashlib
import secrets
from lnbits.core.crud import create_payment
async def credit_wallet(wallet_id: str, amount: int):
preimage = secrets.token_hex(32)
m = hashlib.sha256()
@ -14,6 +15,6 @@ async def credit_wallet(wallet_id: str, amount: int):
checking_id=payment_hash,
preimage=preimage,
memo="",
amount=amount,# msat
pending=False,# not pending, so it will increase the wallet's balance
amount=amount, # msat
pending=False, # not pending, so it will increase the wallet's balance
)