diff --git a/conv.py b/conv.py index 159c7dc0e..aa66a998d 100644 --- a/conv.py +++ b/conv.py @@ -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 diff --git a/lnbits/bolt11.py b/lnbits/bolt11.py index 74f739630..e52219840 100644 --- a/lnbits/bolt11.py +++ b/lnbits/bolt11.py @@ -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), ) diff --git a/lnbits/core/views/api.py b/lnbits/core/views/api.py index 3be3a460e..3b2f8b3a2 100644 --- a/lnbits/core/views/api.py +++ b/lnbits/core/views/api.py @@ -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} diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py index 16a2fbac1..d9687e160 100644 --- a/lnbits/core/views/generic.py +++ b/lnbits/core/views/generic.py @@ -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) diff --git a/lnbits/decorators.py b/lnbits/decorators.py index 76cb8a54b..d6f73f406 100644 --- a/lnbits/decorators.py +++ b/lnbits/decorators.py @@ -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: diff --git a/lnbits/extensions/discordbot/models.py b/lnbits/extensions/discordbot/models.py index 4be367f80..985eb096f 100644 --- a/lnbits/extensions/discordbot/models.py +++ b/lnbits/extensions/discordbot/models.py @@ -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 diff --git a/lnbits/extensions/discordbot/views_api.py b/lnbits/extensions/discordbot/views_api.py index 64d1df1a7..6f213a89a 100644 --- a/lnbits/extensions/discordbot/views_api.py +++ b/lnbits/extensions/discordbot/views_api.py @@ -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}") diff --git a/lnbits/extensions/example/__init__.py b/lnbits/extensions/example/__init__.py index 29a0f0b65..96cc6428c 100644 --- a/lnbits/extensions/example/__init__.py +++ b/lnbits/extensions/example/__init__.py @@ -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(): diff --git a/lnbits/extensions/example/models.py b/lnbits/extensions/example/models.py index 0347a06f3..bfeb7517f 100644 --- a/lnbits/extensions/example/models.py +++ b/lnbits/extensions/example/models.py @@ -3,4 +3,3 @@ # class Example(BaseModel): # id: str # wallet: str - diff --git a/lnbits/extensions/example/views_api.py b/lnbits/extensions/example/views_api.py index f144fe76d..5b702717e 100644 --- a/lnbits/extensions/example/views_api.py +++ b/lnbits/extensions/example/views_api.py @@ -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.""" diff --git a/lnbits/extensions/jukebox/crud.py b/lnbits/extensions/jukebox/crud.py index caaac7e56..d160daeec 100644 --- a/lnbits/extensions/jukebox/crud.py +++ b/lnbits/extensions/jukebox/crud.py @@ -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 diff --git a/lnbits/extensions/jukebox/views_api.py b/lnbits/extensions/jukebox/views_api.py index 3ba8cbf25..1f3723a74 100644 --- a/lnbits/extensions/jukebox/views_api.py +++ b/lnbits/extensions/jukebox/views_api.py @@ -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", ) diff --git a/lnbits/extensions/livestream/views.py b/lnbits/extensions/livestream/views.py index 4f1bd1c5c..ef0354315 100644 --- a/lnbits/extensions/livestream/views.py +++ b/lnbits/extensions/livestream/views.py @@ -1,4 +1,5 @@ from http import HTTPStatus + # from mmap import MAP_DENYWRITE from fastapi.param_functions import Depends diff --git a/lnbits/extensions/offlineshop/helpers.py b/lnbits/extensions/offlineshop/helpers.py index db2c19cce..6b56cf559 100644 --- a/lnbits/extensions/offlineshop/helpers.py +++ b/lnbits/extensions/offlineshop/helpers.py @@ -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) diff --git a/lnbits/extensions/paywall/views_api.py b/lnbits/extensions/paywall/views_api.py index 3d1c2575d..8052c63ba 100644 --- a/lnbits/extensions/paywall/views_api.py +++ b/lnbits/extensions/paywall/views_api.py @@ -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: diff --git a/lnbits/extensions/streamalerts/views_api.py b/lnbits/extensions/streamalerts/views_api.py index 0a678d8ba..bb2998ee5 100644 --- a/lnbits/extensions/streamalerts/views_api.py +++ b/lnbits/extensions/streamalerts/views_api.py @@ -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( diff --git a/lnbits/extensions/withdraw/lnurl.py b/lnbits/extensions/withdraw/lnurl.py index 603e7dad1..0e253d323 100644 --- a/lnbits/extensions/withdraw/lnurl.py +++ b/lnbits/extensions/withdraw/lnurl.py @@ -33,7 +33,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", @@ -51,7 +53,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()) @@ -61,7 +67,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.") @@ -84,7 +92,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." @@ -155,7 +163,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 diff --git a/lnbits/extensions/withdraw/views.py b/lnbits/extensions/withdraw/views.py index 81aeef98c..1f059a4b0 100644 --- a/lnbits/extensions/withdraw/views.py +++ b/lnbits/extensions/withdraw/views.py @@ -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} - ) \ No newline at end of file + ) diff --git a/lnbits/extensions/withdraw/views_api.py b/lnbits/extensions/withdraw/views_api.py index c48a26b75..027b2925a 100644 --- a/lnbits/extensions/withdraw/views_api.py +++ b/lnbits/extensions/withdraw/views_api.py @@ -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 diff --git a/lnbits/helpers.py b/lnbits/helpers.py index c0f37821d..c456d468f 100644 --- a/lnbits/helpers.py +++ b/lnbits/helpers.py @@ -25,7 +25,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] diff --git a/lnbits/settings.py b/lnbits/settings.py index 46b988fc1..18537b84d 100644 --- a/lnbits/settings.py +++ b/lnbits/settings.py @@ -28,7 +28,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 ) diff --git a/lnbits/wallets/eclair.py b/lnbits/wallets/eclair.py index 04fd498f2..aa7ddc395 100644 --- a/lnbits/wallets/eclair.py +++ b/lnbits/wallets/eclair.py @@ -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") diff --git a/lnbits/wallets/macaroon/__init__.py b/lnbits/wallets/macaroon/__init__.py index b7cadcfeb..4967c1008 100644 --- a/lnbits/wallets/macaroon/__init__.py +++ b/lnbits/wallets/macaroon/__init__.py @@ -1 +1 @@ -from .macaroon import load_macaroon, AESCipher \ No newline at end of file +from .macaroon import load_macaroon, AESCipher diff --git a/lnbits/wallets/macaroon/macaroon.py b/lnbits/wallets/macaroon/macaroon.py index dd6ff6369..3548e9e29 100644 --- a/lnbits/wallets/macaroon/macaroon.py +++ b/lnbits/wallets/macaroon/macaroon.py @@ -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__": diff --git a/tests/conftest.py b/tests/conftest.py index 127233c15..27ba9137a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -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 diff --git a/tests/core/views/test_generic.py b/tests/core/views/test_generic.py index 4917cde41..5d3db0fb1 100644 --- a/tests/core/views/test_generic.py +++ b/tests/core/views/test_generic.py @@ -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("/") diff --git a/tests/extensions/bleskomat/conftest.py b/tests/extensions/bleskomat/conftest.py index 924998a71..265d3be0c 100644 --- a/tests/extensions/bleskomat/conftest.py +++ b/tests/extensions/bleskomat/conftest.py @@ -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) diff --git a/tests/helpers.py b/tests/helpers.py index 1687e25d8..3774f6fc0 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -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 )