diff --git a/.env.example b/.env.example index 2d9916b06..50bb0c97b 100644 --- a/.env.example +++ b/.env.example @@ -8,7 +8,11 @@ PORT=5000 LNBITS_ALLOWED_USERS="" LNBITS_DEFAULT_WALLET_NAME="LNbits wallet" + +# Database: by default we will use SQLite, but you can replace that with a Postgres URL LNBITS_DATA_FOLDER="./data" +# LNBITS_DATABASE_URL="postgres:///" + LNBITS_DISABLED_EXTENSIONS="amilk" LNBITS_FORCE_HTTPS=true LNBITS_SERVICE_FEE="0.0" diff --git a/Pipfile.lock b/Pipfile.lock index 81b4d6898..1b1212d73 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "8c4056a80c682fac834266c11892573ce53807226c0810e4564976656ea5ff45" + "sha256": "4067e94f45066ab088fc12ce09371b360c2bdb6b29f10c84f8ca06b3a9ede22a" }, "pipfile-spec": 6, "requires": { @@ -289,42 +289,6 @@ "markers": "python_version >= '3.5'", "version": "==3.12.1" }, - "mypy": { - "hashes": [ - "sha256:0190fb77e93ce971954c9e54ea61de2802065174e5e990c9d4c1d0f54fbeeca2", - "sha256:0756529da2dd4d53d26096b7969ce0a47997123261a5432b48cc6848a2cb0bd4", - "sha256:2f9fedc1f186697fda191e634ac1d02f03d4c260212ccb018fabbb6d4b03eee8", - "sha256:353aac2ce41ddeaf7599f1c73fed2b75750bef3b44b6ad12985a991bc002a0da", - "sha256:3f12705eabdd274b98f676e3e5a89f247ea86dc1af48a2d5a2b080abac4e1243", - "sha256:4efc67b9b3e2fddbe395700f91d5b8deb5980bfaaccb77b306310bd0b9e002eb", - "sha256:517e7528d1be7e187a5db7f0a3e479747307c1b897d9706b1c662014faba3116", - "sha256:68a098c104ae2b75e946b107ef69dd8398d54cb52ad57580dfb9fc78f7f997f0", - "sha256:746e0b0101b8efec34902810047f26a8c80e1efbb4fc554956d848c05ef85d76", - "sha256:8be7bbd091886bde9fcafed8dd089a766fa76eb223135fe5c9e9798f78023a20", - "sha256:9236c21194fde5df1b4d8ebc2ef2c1f2a5dc7f18bcbea54274937cae2e20a01c", - "sha256:9ef5355eaaf7a23ab157c21a44c614365238a7bdb3552ec3b80c393697d974e1", - "sha256:9f1d74eeb3f58c7bd3f3f92b8f63cb1678466a55e2c4612bf36909105d0724ab", - "sha256:a26d0e53e90815c765f91966442775cf03b8a7514a4e960de7b5320208b07269", - "sha256:ae94c31bb556ddb2310e4f913b706696ccbd43c62d3331cd3511caef466871d2", - "sha256:b5ba1f0d5f9087e03bf5958c28d421a03a4c1ad260bf81556195dffeccd979c4", - "sha256:b5dfcd22c6bab08dfeded8d5b44bdcb68c6f1ab261861e35c470b89074f78a70", - "sha256:cd01c599cf9f897b6b6c6b5d8b182557fb7d99326bcdf5d449a0fbbb4ccee4b9", - "sha256:e89880168c67cf4fde4506b80ee42f1537ad66ad366c101d388b3fd7d7ce2afd", - "sha256:ebe2bc9cb638475f5d39068d2dbe8ae1d605bb8d8d3ff281c695df1670ab3987", - "sha256:f89bfda7f0f66b789792ab64ce0978e4a991a0e4dd6197349d0767b0f1095b21", - "sha256:fc4d63da57ef0e8cd4ab45131f3fe5c286ce7dd7f032650d0fbc239c6190e167", - "sha256:fd634bc17b1e2d6ce716f0e43446d0d61cdadb1efcad5c56ca211c22b246ebc8" - ], - "markers": "implementation_name == 'cpython'", - "version": "==0.902" - }, - "mypy-extensions": { - "hashes": [ - "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", - "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" - ], - "version": "==0.4.3" - }, "outcome": { "hashes": [ "sha256:c7dd9375cfd3c12db9801d080a3b63d4b0a261aa996c4c13152380587288d958", @@ -447,14 +411,6 @@ ], "version": "==1.5.0" }, - "secure": { - "hashes": [ - "sha256:6e30939d8f95bf3b8effb8a36ebb5ed57f265daeeae905e3aa9677ea538ab64e", - "sha256:a93b720c7614809c131ca80e477263140107c6c212829d0a6e1f7bc8d859c608" - ], - "index": "pypi", - "version": "==0.3.0" - }, "shortuuid": { "hashes": [ "sha256:3c11d2007b915c43bee3e10625f068d8a349e04f0d81f08f5fa08507427ebf1f", @@ -554,14 +510,6 @@ "index": "pypi", "version": "==0.16.0" }, - "trio-typing": { - "hashes": [ - "sha256:35f1bec8df2150feab6c8b073b54135321722c9d9289bbffa78a9a091ea83b72", - "sha256:f2007df617a6c26a2294db0dd63645b5451149757e1bde4cb8dbf3e1369174fb" - ], - "index": "pypi", - "version": "==0.5.0" - }, "typing-extensions": { "hashes": [ "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497", @@ -725,7 +673,7 @@ "sha256:fc4d63da57ef0e8cd4ab45131f3fe5c286ce7dd7f032650d0fbc239c6190e167", "sha256:fd634bc17b1e2d6ce716f0e43446d0d61cdadb1efcad5c56ca211c22b246ebc8" ], - "markers": "implementation_name == 'cpython'", + "index": "pypi", "version": "==0.902" }, "mypy-extensions": { @@ -882,6 +830,14 @@ "index": "pypi", "version": "==0.16.0" }, + "trio-typing": { + "hashes": [ + "sha256:35f1bec8df2150feab6c8b073b54135321722c9d9289bbffa78a9a091ea83b72", + "sha256:f2007df617a6c26a2294db0dd63645b5451149757e1bde4cb8dbf3e1369174fb" + ], + "index": "pypi", + "version": "==0.5.0" + }, "typed-ast": { "hashes": [ "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace", diff --git a/lnbits/commands.py b/lnbits/commands.py index 2e9b837fd..02fac66db 100644 --- a/lnbits/commands.py +++ b/lnbits/commands.py @@ -4,8 +4,8 @@ import click import importlib import re import os -from sqlalchemy.exc import OperationalError # type: ignore +from .db import SQLITE, POSTGRES from .core import db as core_db, migrations as core_migrations from .helpers import ( get_valid_extensions, @@ -53,41 +53,59 @@ def bundle_vendored(): async def migrate_databases(): """Creates the necessary databases if they don't exist already; or migrates them.""" - async with core_db.connect() as conn: - try: - rows = await (await conn.execute("SELECT * FROM dbversions")).fetchall() - except OperationalError: - # migration 3 wasn't ran - await core_migrations.m000_create_migrations_table(conn) - rows = await (await conn.execute("SELECT * FROM dbversions")).fetchall() + async def set_migration_version(conn, db_name, version): + await conn.execute( + """ + INSERT INTO dbversions (db, version) VALUES (?, ?) + ON CONFLICT (db) DO UPDATE SET version = ? + """, + (db_name, version, version), + ) + async def run_migration(db, migrations_module): + db_name = migrations_module.__name__.split(".")[-2] + for key, migrate in migrations_module.__dict__.items(): + match = match = matcher.match(key) + if match: + version = int(match.group(1)) + if version > current_versions.get(db_name, 0): + print(f"running migration {db_name}.{version}") + await migrate(db) + + if db.schema == None: + await set_migration_version(db, db_name, version) + else: + async with core_db.connect() as conn: + await set_migration_version(conn, db_name, version) + + async with core_db.connect() as conn: + if conn.type == SQLITE: + exists = await conn.fetchone( + "SELECT * FROM sqlite_master WHERE type='table' AND name='dbversions'" + ) + elif conn.type == POSTGRES: + exists = await conn.fetchone( + "SELECT * FROM information_schema.tables WHERE table_name = 'dbversions'" + ) + + if not exists: + await core_migrations.m000_create_migrations_table(conn) + + rows = await (await conn.execute("SELECT * FROM dbversions")).fetchall() current_versions = {row["db"]: row["version"] for row in rows} matcher = re.compile(r"^m(\d\d\d)_") - - async def run_migration(db, migrations_module): - db_name = migrations_module.__name__.split(".")[-2] - for key, migrate in migrations_module.__dict__.items(): - match = match = matcher.match(key) - if match: - version = int(match.group(1)) - if version > current_versions.get(db_name, 0): - print(f"running migration {db_name}.{version}") - await migrate(db) - await conn.execute( - "INSERT OR REPLACE INTO dbversions (db, version) VALUES (?, ?)", - (db_name, version), - ) - await run_migration(conn, core_migrations) - for ext in get_valid_extensions(): - try: - ext_migrations = importlib.import_module( - f"lnbits.extensions.{ext.code}.migrations" - ) - ext_db = importlib.import_module(f"lnbits.extensions.{ext.code}").db - await run_migration(ext_db, ext_migrations) - except ImportError: - raise ImportError( - f"Please make sure that the extension `{ext.code}` has a migrations file." - ) + for ext in get_valid_extensions(): + try: + ext_migrations = importlib.import_module( + f"lnbits.extensions.{ext.code}.migrations" + ) + ext_db = importlib.import_module(f"lnbits.extensions.{ext.code}").db + except ImportError: + raise ImportError( + f"Please make sure that the extension `{ext.code}` has a migrations file." + ) + + async with ext_db.connect() as ext_conn: + await run_migration(ext_conn, ext_migrations) diff --git a/lnbits/core/crud.py b/lnbits/core/crud.py index 47623cc26..ab9026e3a 100644 --- a/lnbits/core/crud.py +++ b/lnbits/core/crud.py @@ -5,7 +5,7 @@ from typing import List, Optional, Dict, Any from urllib.parse import urlparse from lnbits import bolt11 -from lnbits.db import Connection +from lnbits.db import Connection, POSTGRES from lnbits.settings import DEFAULT_WALLET_NAME from . import db @@ -43,13 +43,14 @@ async def get_user(user_id: str, conn: Optional[Connection] = None) -> Optional[ if user: extensions = await (conn or db).fetchall( - "SELECT extension FROM extensions WHERE user = ? AND active = 1", (user_id,) + """SELECT extension FROM extensions WHERE "user" = ? AND active""", + (user_id,), ) wallets = await (conn or db).fetchall( """ SELECT *, COALESCE((SELECT balance FROM balances WHERE wallet = wallets.id), 0) AS balance_msat FROM wallets - WHERE user = ? + WHERE "user" = ? """, (user_id,), ) @@ -70,14 +71,14 @@ async def get_user(user_id: str, conn: Optional[Connection] = None) -> Optional[ async def update_user_extension( - *, user_id: str, extension: str, active: int, conn: Optional[Connection] = None + *, user_id: str, extension: str, active: bool, conn: Optional[Connection] = None ) -> None: await (conn or db).execute( """ - INSERT OR REPLACE INTO extensions (user, extension, active) - VALUES (?, ?, ?) + INSERT INTO extensions ("user", extension, active) VALUES (?, ?, ?) + ON CONFLICT ("user", extension) DO UPDATE SET active = ? """, - (user_id, extension, active), + (user_id, extension, active, active), ) @@ -94,7 +95,7 @@ async def create_wallet( wallet_id = uuid4().hex await (conn or db).execute( """ - INSERT INTO wallets (id, name, user, adminkey, inkey) + INSERT INTO wallets (id, name, "user", adminkey, inkey) VALUES (?, ?, ?, ?, ?) """, ( @@ -119,10 +120,10 @@ async def delete_wallet( """ UPDATE wallets AS w SET - user = 'del:' || w.user, + "user" = 'del:' || w."user", adminkey = 'del:' || w.adminkey, inkey = 'del:' || w.inkey - WHERE id = ? AND user = ? + WHERE id = ? AND "user" = ? """, (wallet_id, user_id), ) @@ -218,7 +219,10 @@ async def get_payments( clause: List[str] = [] if since != None: - clause.append("time > ?") + if db.type == POSTGRES: + clause.append("time > to_timestamp(?)") + else: + clause.append("time > ?") args.append(since) if wallet_id: @@ -228,9 +232,9 @@ async def get_payments( if complete and pending: pass elif complete: - clause.append("((amount > 0 AND pending = 0) OR amount < 0)") + clause.append("((amount > 0 AND pending = false) OR amount < 0)") elif pending: - clause.append("pending = 1") + clause.append("pending = true") else: pass @@ -269,20 +273,21 @@ async def delete_expired_invoices( ) -> None: # first we delete all invoices older than one month await (conn or db).execute( - """ + f""" DELETE FROM apipayments - WHERE pending = 1 AND amount > 0 AND time < strftime('%s', 'now') - 2592000 + WHERE pending = true AND amount > 0 + AND time < {db.timestamp_now} - {db.interval_seconds(2592000)} """ ) # then we delete all expired invoices, checking one by one rows = await (conn or db).fetchall( - """ + f""" SELECT bolt11 FROM apipayments - WHERE pending = 1 + WHERE pending = true AND bolt11 IS NOT NULL - AND amount > 0 AND time < strftime('%s', 'now') - 86400 + AND amount > 0 AND time < {db.timestamp_now} - {db.interval_seconds(86400)} """ ) for (payment_request,) in rows: @@ -298,7 +303,7 @@ async def delete_expired_invoices( await (conn or db).execute( """ DELETE FROM apipayments - WHERE pending = 1 AND hash = ? + WHERE pending = true AND hash = ? """, (invoice.payment_hash,), ) @@ -337,7 +342,7 @@ async def create_payment( payment_hash, preimage, amount, - int(pending), + pending, memo, fee, json.dumps(extra) @@ -361,7 +366,7 @@ async def update_payment_status( await (conn or db).execute( "UPDATE apipayments SET pending = ? WHERE checking_id = ?", ( - int(pending), + pending, checking_id, ), ) @@ -406,10 +411,10 @@ async def save_balance_check( await (conn or db).execute( """ - INSERT OR REPLACE INTO balance_check (wallet, service, url) - VALUES (?, ?, ?) + INSERT INTO balance_check (wallet, service, url) VALUES (?, ?, ?) + ON CONFLICT (wallet, service) DO UPDATE SET url = ? """, - (wallet_id, domain, url), + (wallet_id, domain, url, url), ) @@ -445,10 +450,10 @@ async def save_balance_notify( ): await (conn or db).execute( """ - INSERT OR REPLACE INTO balance_notify (wallet, url) - VALUES (?, ?) + INSERT INTO balance_notify (wallet, url) VALUES (?, ?) + ON CONFLICT (wallet) DO UPDATE SET url = ? """, - (wallet_id, url), + (wallet_id, url, url), ) diff --git a/lnbits/core/migrations.py b/lnbits/core/migrations.py index 64de9acf1..466867164 100644 --- a/lnbits/core/migrations.py +++ b/lnbits/core/migrations.py @@ -18,7 +18,7 @@ async def m001_initial(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS accounts ( + CREATE TABLE accounts ( id TEXT PRIMARY KEY, email TEXT, pass TEXT @@ -27,37 +27,36 @@ async def m001_initial(db): ) await db.execute( """ - CREATE TABLE IF NOT EXISTS extensions ( - user TEXT NOT NULL, + CREATE TABLE extensions ( + "user" TEXT NOT NULL, extension TEXT NOT NULL, - active BOOLEAN DEFAULT 0, + active BOOLEAN DEFAULT false, - UNIQUE (user, extension) + UNIQUE ("user", extension) ); """ ) await db.execute( """ - CREATE TABLE IF NOT EXISTS wallets ( + CREATE TABLE wallets ( id TEXT PRIMARY KEY, name TEXT NOT NULL, - user TEXT NOT NULL, + "user" TEXT NOT NULL, adminkey TEXT NOT NULL, inkey TEXT ); """ ) await db.execute( - """ - CREATE TABLE IF NOT EXISTS apipayments ( + f""" + CREATE TABLE apipayments ( payhash TEXT NOT NULL, amount INTEGER NOT NULL, fee INTEGER NOT NULL DEFAULT 0, wallet TEXT NOT NULL, pending BOOLEAN NOT NULL, memo TEXT, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')), - + time TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}, UNIQUE (wallet, payhash) ); """ @@ -65,18 +64,18 @@ async def m001_initial(db): await db.execute( """ - CREATE VIEW IF NOT EXISTS balances AS + CREATE VIEW balances AS SELECT wallet, COALESCE(SUM(s), 0) AS balance FROM ( SELECT wallet, SUM(amount) AS s -- incoming FROM apipayments - WHERE amount > 0 AND pending = 0 -- don't sum pending + WHERE amount > 0 AND pending = false -- don't sum pending GROUP BY wallet UNION ALL SELECT wallet, SUM(amount + fee) AS s -- outgoing, sum fees FROM apipayments WHERE amount < 0 -- do sum pending GROUP BY wallet - ) + )x GROUP BY wallet; """ ) @@ -143,21 +142,20 @@ async def m004_ensure_fees_are_always_negative(db): """ await db.execute("DROP VIEW balances") - await db.execute( """ - CREATE VIEW IF NOT EXISTS balances AS + CREATE VIEW balances AS SELECT wallet, COALESCE(SUM(s), 0) AS balance FROM ( SELECT wallet, SUM(amount) AS s -- incoming FROM apipayments - WHERE amount > 0 AND pending = 0 -- don't sum pending + WHERE amount > 0 AND pending = false -- don't sum pending GROUP BY wallet UNION ALL SELECT wallet, SUM(amount - abs(fee)) AS s -- outgoing, sum fees FROM apipayments WHERE amount < 0 -- do sum pending GROUP BY wallet - ) + )x GROUP BY wallet; """ ) @@ -171,7 +169,7 @@ async def m005_balance_check_balance_notify(db): await db.execute( """ CREATE TABLE balance_check ( - wallet INTEGER NOT NULL REFERENCES wallets (id), + wallet TEXT NOT NULL REFERENCES wallets (id), service TEXT NOT NULL, url TEXT NOT NULL, @@ -183,7 +181,7 @@ async def m005_balance_check_balance_notify(db): await db.execute( """ CREATE TABLE balance_notify ( - wallet INTEGER NOT NULL REFERENCES wallets (id), + wallet TEXT NOT NULL REFERENCES wallets (id), url TEXT NOT NULL, UNIQUE(wallet, url) diff --git a/lnbits/core/static/js/wallet.js b/lnbits/core/static/js/wallet.js index d01910514..712824088 100644 --- a/lnbits/core/static/js/wallet.js +++ b/lnbits/core/static/js/wallet.js @@ -202,9 +202,7 @@ new Vue({ return this.parse.invoice.sat <= this.balance }, pendingPaymentsExist: function () { - return this.payments - ? _.where(this.payments, {pending: 1}).length > 0 - : false + return this.payments.findIndex(payment => payment.pending) !== -1 } }, filters: { diff --git a/lnbits/core/tasks.py b/lnbits/core/tasks.py index fa2df9645..b05909a28 100644 --- a/lnbits/core/tasks.py +++ b/lnbits/core/tasks.py @@ -66,7 +66,7 @@ async def dispatch_webhook(payment: Payment): async def mark_webhook_sent(payment: Payment, status: int) -> None: await db.execute( """ - UPDATE apipayments SET webhook_status = ? + UPDATE core.apipayments SET webhook_status = ? WHERE hash = ? """, (status, payment.payment_hash), diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py index 16f648305..0d1b78a99 100644 --- a/lnbits/core/views/generic.py +++ b/lnbits/core/views/generic.py @@ -56,11 +56,11 @@ async def extensions(): if extension_to_enable: await update_user_extension( - user_id=g.user.id, extension=extension_to_enable, active=1 + user_id=g.user.id, extension=extension_to_enable, active=True ) elif extension_to_disable: await update_user_extension( - user_id=g.user.id, extension=extension_to_disable, active=0 + user_id=g.user.id, extension=extension_to_disable, active=False ) return await render_template("core/extensions.html", user=await get_user(g.user.id)) diff --git a/lnbits/db.py b/lnbits/db.py index 9da3b6ecf..746735479 100644 --- a/lnbits/db.py +++ b/lnbits/db.py @@ -1,36 +1,107 @@ import os import trio +import psycopg2 from contextlib import asynccontextmanager from sqlalchemy import create_engine # type: ignore from sqlalchemy_aio import TRIO_STRATEGY # type: ignore from sqlalchemy_aio.base import AsyncConnection # type: ignore -from .settings import LNBITS_DATA_FOLDER +from .settings import LNBITS_DATA_FOLDER, LNBITS_DATABASE_URL + +POSTGRES = "POSTGRES" +SQLITE = "SQLITE" -class Connection: - def __init__(self, conn: AsyncConnection): +class Compat: + type = "" + schema = "" + + def interval_seconds(self, seconds: int) -> str: + if self.type == POSTGRES: + return f"interval '{seconds} seconds'" + elif self.type == SQLITE: + return f"{seconds}" + return "" + + @property + def timestamp_now(self) -> str: + if self.type == POSTGRES: + return "now()" + elif self.type == SQLITE: + return "(strftime('%s', 'now'))" + return "" + + @property + def serial_primary_key(self) -> str: + if self.type == POSTGRES: + return "SERIAL PRIMARY KEY" + elif self.type == SQLITE: + return "INTEGER PRIMARY KEY AUTOINCREMENT" + return "" + + @property + def references_schema(self) -> str: + if self.type == POSTGRES: + return f"{self.schema}." + elif self.type == SQLITE: + return "" + return "" + + +class Connection(Compat): + def __init__(self, conn: AsyncConnection, txn, typ, name, schema): self.conn = conn + self.txn = txn + self.type = typ + self.name = name + self.schema = schema + + def rewrite_query(self, query) -> str: + if self.type == POSTGRES: + query = query.replace("%", "%%") + query = query.replace("?", "%s") + return query async def fetchall(self, query: str, values: tuple = ()) -> list: - result = await self.conn.execute(query, values) + result = await self.conn.execute(self.rewrite_query(query), values) return await result.fetchall() async def fetchone(self, query: str, values: tuple = ()): - result = await self.conn.execute(query, values) + result = await self.conn.execute(self.rewrite_query(query), values) row = await result.fetchone() await result.close() return row async def execute(self, query: str, values: tuple = ()): - return await self.conn.execute(query, values) + return await self.conn.execute(self.rewrite_query(query), values) -class Database: +class Database(Compat): def __init__(self, db_name: str): - self.db_name = db_name - db_path = os.path.join(LNBITS_DATA_FOLDER, f"{db_name}.sqlite3") - self.engine = create_engine(f"sqlite:///{db_path}", strategy=TRIO_STRATEGY) + self.name = db_name + + if LNBITS_DATABASE_URL: + database_uri = LNBITS_DATABASE_URL + self.type = POSTGRES + + DEC2FLOAT = psycopg2.extensions.new_type( + psycopg2.extensions.DECIMAL.values, + "DEC2FLOAT", + lambda value, curs: float(value) if value is not None else None, + ) + psycopg2.extensions.register_type(DEC2FLOAT) + else: + self.path = os.path.join(LNBITS_DATA_FOLDER, f"{self.name}.sqlite3") + database_uri = f"sqlite:///{self.path}" + self.type = SQLITE + + self.schema = self.name + if self.name.startswith("ext_"): + self.schema = self.name[4:] + else: + self.schema = None + + self.engine = create_engine(database_uri, strategy=TRIO_STRATEGY) self.lock = trio.StrictFIFOLock() @asynccontextmanager @@ -38,8 +109,20 @@ class Database: await self.lock.acquire() try: async with self.engine.connect() as conn: - async with conn.begin(): - yield Connection(conn) + async with conn.begin() as txn: + wconn = Connection(conn, txn, self.type, self.name, self.schema) + + if self.schema: + if self.type == POSTGRES: + await wconn.execute( + f"CREATE SCHEMA IF NOT EXISTS {self.schema}" + ) + elif self.type == SQLITE: + await wconn.execute( + f"ATTACH '{self.path}' AS {self.schema}" + ) + + yield wconn finally: self.lock.release() diff --git a/lnbits/extensions/amilk/crud.py b/lnbits/extensions/amilk/crud.py index 773caa42b..859d2fa84 100644 --- a/lnbits/extensions/amilk/crud.py +++ b/lnbits/extensions/amilk/crud.py @@ -10,7 +10,7 @@ async def create_amilk(*, wallet_id: str, lnurl: str, atime: int, amount: int) - amilk_id = urlsafe_b64encode(uuid4().bytes_le).decode("utf-8") await db.execute( """ - INSERT INTO amilks (id, wallet, lnurl, atime, amount) + INSERT INTO amilk.amilks (id, wallet, lnurl, atime, amount) VALUES (?, ?, ?, ?, ?) """, (amilk_id, wallet_id, lnurl, atime, amount), @@ -22,7 +22,7 @@ async def create_amilk(*, wallet_id: str, lnurl: str, atime: int, amount: int) - async def get_amilk(amilk_id: str) -> Optional[AMilk]: - row = await db.fetchone("SELECT * FROM amilks WHERE id = ?", (amilk_id,)) + row = await db.fetchone("SELECT * FROM amilk.amilks WHERE id = ?", (amilk_id,)) return AMilk(**row) if row else None @@ -32,11 +32,11 @@ async def get_amilks(wallet_ids: Union[str, List[str]]) -> List[AMilk]: q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( - f"SELECT * FROM amilks WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM amilk.amilks WHERE wallet IN ({q})", (*wallet_ids,) ) return [AMilk(**row) for row in rows] async def delete_amilk(amilk_id: str) -> None: - await db.execute("DELETE FROM amilks WHERE id = ?", (amilk_id,)) + await db.execute("DELETE FROM amilk.amilks WHERE id = ?", (amilk_id,)) diff --git a/lnbits/extensions/amilk/migrations.py b/lnbits/extensions/amilk/migrations.py index f096ccdb2..596a86335 100644 --- a/lnbits/extensions/amilk/migrations.py +++ b/lnbits/extensions/amilk/migrations.py @@ -4,7 +4,7 @@ async def m001_initial(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS amilks ( + CREATE TABLE amilk.amilks ( id TEXT PRIMARY KEY, wallet TEXT NOT NULL, lnurl TEXT NOT NULL, diff --git a/lnbits/extensions/bleskomat/crud.py b/lnbits/extensions/bleskomat/crud.py index 206cec1f6..11dcb49c4 100644 --- a/lnbits/extensions/bleskomat/crud.py +++ b/lnbits/extensions/bleskomat/crud.py @@ -21,7 +21,7 @@ async def create_bleskomat( api_key_encoding = "hex" await db.execute( """ - INSERT INTO bleskomats (id, wallet, api_key_id, api_key_secret, api_key_encoding, name, fiat_currency, exchange_rate_provider, fee) + INSERT INTO bleskomat.bleskomats (id, wallet, api_key_id, api_key_secret, api_key_encoding, name, fiat_currency, exchange_rate_provider, fee) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( @@ -42,13 +42,13 @@ async def create_bleskomat( async def get_bleskomat(bleskomat_id: str) -> Optional[Bleskomat]: - row = await db.fetchone("SELECT * FROM bleskomats WHERE id = ?", (bleskomat_id,)) + row = await db.fetchone("SELECT * FROM bleskomat.bleskomats WHERE id = ?", (bleskomat_id,)) return Bleskomat(**row) if row else None async def get_bleskomat_by_api_key_id(api_key_id: str) -> Optional[Bleskomat]: row = await db.fetchone( - "SELECT * FROM bleskomats WHERE api_key_id = ?", (api_key_id,) + "SELECT * FROM bleskomat.bleskomats WHERE api_key_id = ?", (api_key_id,) ) return Bleskomat(**row) if row else None @@ -58,7 +58,7 @@ async def get_bleskomats(wallet_ids: Union[str, List[str]]) -> List[Bleskomat]: wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( - f"SELECT * FROM bleskomats WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM bleskomat.bleskomats WHERE wallet IN ({q})", (*wallet_ids,) ) return [Bleskomat(**row) for row in rows] @@ -66,14 +66,14 @@ async def get_bleskomats(wallet_ids: Union[str, List[str]]) -> List[Bleskomat]: async def update_bleskomat(bleskomat_id: str, **kwargs) -> Optional[Bleskomat]: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) await db.execute( - f"UPDATE bleskomats SET {q} WHERE id = ?", (*kwargs.values(), bleskomat_id) + f"UPDATE bleskomat.bleskomats SET {q} WHERE id = ?", (*kwargs.values(), bleskomat_id) ) - row = await db.fetchone("SELECT * FROM bleskomats WHERE id = ?", (bleskomat_id,)) + row = await db.fetchone("SELECT * FROM bleskomat.bleskomats WHERE id = ?", (bleskomat_id,)) return Bleskomat(**row) if row else None async def delete_bleskomat(bleskomat_id: str) -> None: - await db.execute("DELETE FROM bleskomats WHERE id = ?", (bleskomat_id,)) + await db.execute("DELETE FROM bleskomat.bleskomats WHERE id = ?", (bleskomat_id,)) async def create_bleskomat_lnurl( @@ -84,7 +84,7 @@ async def create_bleskomat_lnurl( now = int(time.time()) await db.execute( """ - INSERT INTO bleskomat_lnurls (id, bleskomat, wallet, hash, tag, params, api_key_id, initial_uses, remaining_uses, created_time, updated_time) + INSERT INTO bleskomat.bleskomat_lnurls (id, bleskomat, wallet, hash, tag, params, api_key_id, initial_uses, remaining_uses, created_time, updated_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( @@ -108,5 +108,5 @@ async def create_bleskomat_lnurl( async def get_bleskomat_lnurl(secret: str) -> Optional[BleskomatLnurl]: hash = generate_bleskomat_lnurl_hash(secret) - row = await db.fetchone("SELECT * FROM bleskomat_lnurls WHERE hash = ?", (hash,)) + row = await db.fetchone("SELECT * FROM bleskomat.bleskomat_lnurls WHERE hash = ?", (hash,)) return BleskomatLnurl(**row) if row else None diff --git a/lnbits/extensions/bleskomat/migrations.py b/lnbits/extensions/bleskomat/migrations.py index f79565009..84e886e56 100644 --- a/lnbits/extensions/bleskomat/migrations.py +++ b/lnbits/extensions/bleskomat/migrations.py @@ -2,7 +2,7 @@ async def m001_initial(db): await db.execute( """ - CREATE TABLE IF NOT EXISTS bleskomats ( + CREATE TABLE bleskomat.bleskomats ( id TEXT PRIMARY KEY, wallet TEXT NOT NULL, api_key_id TEXT NOT NULL, @@ -19,7 +19,7 @@ async def m001_initial(db): await db.execute( """ - CREATE TABLE IF NOT EXISTS bleskomat_lnurls ( + CREATE TABLE bleskomat.bleskomat_lnurls ( id TEXT PRIMARY KEY, bleskomat TEXT NOT NULL, wallet TEXT NOT NULL, diff --git a/lnbits/extensions/bleskomat/models.py b/lnbits/extensions/bleskomat/models.py index 54633146d..216f83c60 100644 --- a/lnbits/extensions/bleskomat/models.py +++ b/lnbits/extensions/bleskomat/models.py @@ -100,7 +100,7 @@ class BleskomatLnurl(NamedTuple): now = int(time.time()) result = await conn.execute( """ - UPDATE bleskomat_lnurls + UPDATE bleskomat.bleskomat_lnurls SET remaining_uses = remaining_uses - 1, updated_time = ? WHERE id = ? AND remaining_uses > 0 diff --git a/lnbits/extensions/captcha/crud.py b/lnbits/extensions/captcha/crud.py index 7526306b6..17cbb4f58 100644 --- a/lnbits/extensions/captcha/crud.py +++ b/lnbits/extensions/captcha/crud.py @@ -18,7 +18,7 @@ async def create_captcha( captcha_id = urlsafe_short_hash() await db.execute( """ - INSERT INTO captchas (id, wallet, url, memo, description, amount, remembers) + INSERT INTO captcha.captchas (id, wallet, url, memo, description, amount, remembers) VALUES (?, ?, ?, ?, ?, ?, ?) """, (captcha_id, wallet_id, url, memo, description, amount, int(remembers)), @@ -30,7 +30,7 @@ async def create_captcha( async def get_captcha(captcha_id: str) -> Optional[Captcha]: - row = await db.fetchone("SELECT * FROM captchas WHERE id = ?", (captcha_id,)) + row = await db.fetchone("SELECT * FROM captcha.captchas WHERE id = ?", (captcha_id,)) return Captcha.from_row(row) if row else None @@ -41,11 +41,11 @@ async def get_captchas(wallet_ids: Union[str, List[str]]) -> List[Captcha]: q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( - f"SELECT * FROM captchas WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM captcha.captchas WHERE wallet IN ({q})", (*wallet_ids,) ) return [Captcha.from_row(row) for row in rows] async def delete_captcha(captcha_id: str) -> None: - await db.execute("DELETE FROM captchas WHERE id = ?", (captcha_id,)) + await db.execute("DELETE FROM captcha.captchas WHERE id = ?", (captcha_id,)) diff --git a/lnbits/extensions/captcha/migrations.py b/lnbits/extensions/captcha/migrations.py index 9fe2e604f..744fc5067 100644 --- a/lnbits/extensions/captcha/migrations.py +++ b/lnbits/extensions/captcha/migrations.py @@ -1,20 +1,19 @@ -from sqlalchemy.exc import OperationalError # type: ignore - - async def m001_initial(db): """ Initial captchas table. """ await db.execute( """ - CREATE TABLE IF NOT EXISTS captchas ( + CREATE TABLE captcha.captchas ( id TEXT PRIMARY KEY, wallet TEXT NOT NULL, secret TEXT NOT NULL, url TEXT NOT NULL, memo TEXT NOT NULL, amount INTEGER NOT NULL, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')) + time TIMESTAMP NOT NULL DEFAULT """ + + db.timestamp_now + + """ ); """ ) @@ -24,44 +23,41 @@ async def m002_redux(db): """ Creates an improved captchas table and migrates the existing data. """ - try: - await db.execute("SELECT remembers FROM captchas") + await db.execute("ALTER TABLE captcha.captchas RENAME TO captchas_old") + await db.execute( + """ + CREATE TABLE captcha.captchas ( + id TEXT PRIMARY KEY, + wallet TEXT NOT NULL, + url TEXT NOT NULL, + memo TEXT NOT NULL, + description TEXT NULL, + amount INTEGER DEFAULT 0, + time TIMESTAMP NOT NULL DEFAULT """ + + db.timestamp_now + + """, + remembers INTEGER DEFAULT 0, + extras TEXT NULL + ); + """ + ) - except OperationalError: - await db.execute("ALTER TABLE captchas RENAME TO captchas_old") + for row in [ + list(row) for row in await db.fetchall("SELECT * FROM captcha.captchas_old") + ]: await db.execute( """ - CREATE TABLE IF NOT EXISTS captchas ( - id TEXT PRIMARY KEY, - wallet TEXT NOT NULL, - url TEXT NOT NULL, - memo TEXT NOT NULL, - description TEXT NULL, - amount INTEGER DEFAULT 0, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')), - remembers INTEGER DEFAULT 0, - extras TEXT NULL - ); - """ - ) - await db.execute("CREATE INDEX IF NOT EXISTS wallet_idx ON captchas (wallet)") - - for row in [ - list(row) for row in await db.fetchall("SELECT * FROM captchas_old") - ]: - await db.execute( - """ - INSERT INTO captchas ( - id, - wallet, - url, - memo, - amount, - time - ) - VALUES (?, ?, ?, ?, ?, ?) - """, - (row[0], row[1], row[3], row[4], row[5], row[6]), + INSERT INTO captcha.captchas ( + id, + wallet, + url, + memo, + amount, + time ) + VALUES (?, ?, ?, ?, ?, ?) + """, + (row[0], row[1], row[3], row[4], row[5], row[6]), + ) - await db.execute("DROP TABLE captchas_old") + await db.execute("DROP TABLE captcha.captchas_old") diff --git a/lnbits/extensions/diagonalley/crud.py b/lnbits/extensions/diagonalley/crud.py index 8e89c35a5..33f020bfd 100644 --- a/lnbits/extensions/diagonalley/crud.py +++ b/lnbits/extensions/diagonalley/crud.py @@ -34,7 +34,7 @@ def create_diagonalleys_product( product_id = urlsafe_b64encode(uuid4().bytes_le).decode("utf-8") db.execute( """ - INSERT INTO products (id, wallet, product, categories, description, image, price, quantity) + INSERT INTO diagonalley.products (id, wallet, product, categories, description, image, price, quantity) VALUES (?, ?, ?, ?, ?, ?, ?, ?) """, ( @@ -57,16 +57,16 @@ def update_diagonalleys_product(product_id: str, **kwargs) -> Optional[Indexers] with open_ext_db("diagonalley") as db: db.execute( - f"UPDATE products SET {q} WHERE id = ?", (*kwargs.values(), product_id) + f"UPDATE diagonalley.products SET {q} WHERE id = ?", (*kwargs.values(), product_id) ) - row = db.fetchone("SELECT * FROM products WHERE id = ?", (product_id,)) + row = db.fetchone("SELECT * FROM diagonalley.products WHERE id = ?", (product_id,)) return get_diagonalleys_indexer(product_id) def get_diagonalleys_product(product_id: str) -> Optional[Products]: with open_ext_db("diagonalley") as db: - row = db.fetchone("SELECT * FROM products WHERE id = ?", (product_id,)) + row = db.fetchone("SELECT * FROM diagonalley.products WHERE id = ?", (product_id,)) return Products(**row) if row else None @@ -78,7 +78,7 @@ def get_diagonalleys_products(wallet_ids: Union[str, List[str]]) -> List[Product with open_ext_db("diagonalley") as db: q = ",".join(["?"] * len(wallet_ids)) rows = db.fetchall( - f"SELECT * FROM products WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM diagonalley.products WHERE wallet IN ({q})", (*wallet_ids,) ) return [Products(**row) for row in rows] @@ -86,7 +86,7 @@ def get_diagonalleys_products(wallet_ids: Union[str, List[str]]) -> List[Product def delete_diagonalleys_product(product_id: str) -> None: with open_ext_db("diagonalley") as db: - db.execute("DELETE FROM products WHERE id = ?", (product_id,)) + db.execute("DELETE FROM diagonalley.products WHERE id = ?", (product_id,)) ###Indexers @@ -106,7 +106,7 @@ def create_diagonalleys_indexer( indexer_id = urlsafe_b64encode(uuid4().bytes_le).decode("utf-8") db.execute( """ - INSERT INTO indexers (id, wallet, shopname, indexeraddress, online, rating, shippingzone1, shippingzone2, zone1cost, zone2cost, email) + INSERT INTO diagonalley.indexers (id, wallet, shopname, indexeraddress, online, rating, shippingzone1, shippingzone2, zone1cost, zone2cost, email) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( @@ -131,16 +131,16 @@ def update_diagonalleys_indexer(indexer_id: str, **kwargs) -> Optional[Indexers] with open_ext_db("diagonalley") as db: db.execute( - f"UPDATE indexers SET {q} WHERE id = ?", (*kwargs.values(), indexer_id) + f"UPDATE diagonalley.indexers SET {q} WHERE id = ?", (*kwargs.values(), indexer_id) ) - row = db.fetchone("SELECT * FROM indexers WHERE id = ?", (indexer_id,)) + row = db.fetchone("SELECT * FROM diagonalley.indexers WHERE id = ?", (indexer_id,)) return get_diagonalleys_indexer(indexer_id) def get_diagonalleys_indexer(indexer_id: str) -> Optional[Indexers]: with open_ext_db("diagonalley") as db: - roww = db.fetchone("SELECT * FROM indexers WHERE id = ?", (indexer_id,)) + roww = db.fetchone("SELECT * FROM diagonalley.indexers WHERE id = ?", (indexer_id,)) try: x = httpx.get(roww["indexeraddress"] + "/" + roww["ratingkey"]) if x.status_code == 200: @@ -148,7 +148,7 @@ def get_diagonalleys_indexer(indexer_id: str) -> Optional[Indexers]: print("poo") with open_ext_db("diagonalley") as db: db.execute( - "UPDATE indexers SET online = ? WHERE id = ?", + "UPDATE diagonalley.indexers SET online = ? WHERE id = ?", ( True, indexer_id, @@ -157,7 +157,7 @@ def get_diagonalleys_indexer(indexer_id: str) -> Optional[Indexers]: else: with open_ext_db("diagonalley") as db: db.execute( - "UPDATE indexers SET online = ? WHERE id = ?", + "UPDATE diagonalley.indexers SET online = ? WHERE id = ?", ( False, indexer_id, @@ -166,7 +166,7 @@ def get_diagonalleys_indexer(indexer_id: str) -> Optional[Indexers]: except: print("An exception occurred") with open_ext_db("diagonalley") as db: - row = db.fetchone("SELECT * FROM indexers WHERE id = ?", (indexer_id,)) + row = db.fetchone("SELECT * FROM diagonalley.indexers WHERE id = ?", (indexer_id,)) return Indexers(**row) if row else None @@ -177,7 +177,7 @@ def get_diagonalleys_indexers(wallet_ids: Union[str, List[str]]) -> List[Indexer with open_ext_db("diagonalley") as db: q = ",".join(["?"] * len(wallet_ids)) rows = db.fetchall( - f"SELECT * FROM indexers WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM diagonalley.indexers WHERE wallet IN ({q})", (*wallet_ids,) ) for r in rows: @@ -186,7 +186,7 @@ def get_diagonalleys_indexers(wallet_ids: Union[str, List[str]]) -> List[Indexer if x.status_code == 200: with open_ext_db("diagonalley") as db: db.execute( - "UPDATE indexers SET online = ? WHERE id = ?", + "UPDATE diagonalley.indexers SET online = ? WHERE id = ?", ( True, r["id"], @@ -195,7 +195,7 @@ def get_diagonalleys_indexers(wallet_ids: Union[str, List[str]]) -> List[Indexer else: with open_ext_db("diagonalley") as db: db.execute( - "UPDATE indexers SET online = ? WHERE id = ?", + "UPDATE diagonalley.indexers SET online = ? WHERE id = ?", ( False, r["id"], @@ -206,14 +206,14 @@ def get_diagonalleys_indexers(wallet_ids: Union[str, List[str]]) -> List[Indexer with open_ext_db("diagonalley") as db: q = ",".join(["?"] * len(wallet_ids)) rows = db.fetchall( - f"SELECT * FROM indexers WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM diagonalley.indexers WHERE wallet IN ({q})", (*wallet_ids,) ) return [Indexers(**row) for row in rows] def delete_diagonalleys_indexer(indexer_id: str) -> None: with open_ext_db("diagonalley") as db: - db.execute("DELETE FROM indexers WHERE id = ?", (indexer_id,)) + db.execute("DELETE FROM diagonalley.indexers WHERE id = ?", (indexer_id,)) ###Orders @@ -236,7 +236,7 @@ def create_diagonalleys_order( order_id = urlsafe_b64encode(uuid4().bytes_le).decode("utf-8") db.execute( """ - INSERT INTO orders (id, productid, wallet, product, quantity, shippingzone, address, email, invoiceid, paid, shipped) + INSERT INTO diagonalley.orders (id, productid, wallet, product, quantity, shippingzone, address, email, invoiceid, paid, shipped) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( @@ -259,7 +259,7 @@ def create_diagonalleys_order( def get_diagonalleys_order(order_id: str) -> Optional[Orders]: with open_ext_db("diagonalley") as db: - row = db.fetchone("SELECT * FROM orders WHERE id = ?", (order_id,)) + row = db.fetchone("SELECT * FROM diagonalley.orders WHERE id = ?", (order_id,)) return Orders(**row) if row else None @@ -271,25 +271,25 @@ def get_diagonalleys_orders(wallet_ids: Union[str, List[str]]) -> List[Orders]: with open_ext_db("diagonalley") as db: q = ",".join(["?"] * len(wallet_ids)) rows = db.fetchall( - f"SELECT * FROM orders WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM diagonalley.orders WHERE wallet IN ({q})", (*wallet_ids,) ) for r in rows: PAID = (await WALLET.get_invoice_status(r["invoiceid"])).paid if PAID: with open_ext_db("diagonalley") as db: db.execute( - "UPDATE orders SET paid = ? WHERE id = ?", + "UPDATE diagonalley.orders SET paid = ? WHERE id = ?", ( True, r["id"], ), ) rows = db.fetchall( - f"SELECT * FROM orders WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM diagonalley.orders WHERE wallet IN ({q})", (*wallet_ids,) ) return [Orders(**row) for row in rows] def delete_diagonalleys_order(order_id: str) -> None: with open_ext_db("diagonalley") as db: - db.execute("DELETE FROM orders WHERE id = ?", (order_id,)) + db.execute("DELETE FROM diagonalley.orders WHERE id = ?", (order_id,)) diff --git a/lnbits/extensions/diagonalley/migrations.py b/lnbits/extensions/diagonalley/migrations.py index a70368fc5..9f2b787f9 100644 --- a/lnbits/extensions/diagonalley/migrations.py +++ b/lnbits/extensions/diagonalley/migrations.py @@ -4,7 +4,7 @@ async def m001_initial(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS products ( + CREATE TABLE diagonalley.products ( id TEXT PRIMARY KEY, wallet TEXT NOT NULL, product TEXT NOT NULL, @@ -22,7 +22,7 @@ async def m001_initial(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS indexers ( + CREATE TABLE diagonalley.indexers ( id TEXT PRIMARY KEY, wallet TEXT NOT NULL, shopname TEXT NOT NULL, @@ -43,7 +43,7 @@ async def m001_initial(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS orders ( + CREATE TABLE diagonalley.orders ( id TEXT PRIMARY KEY, productid TEXT NOT NULL, wallet TEXT NOT NULL, diff --git a/lnbits/extensions/diagonalley/views_api.py b/lnbits/extensions/diagonalley/views_api.py index cfb835666..07aad712f 100644 --- a/lnbits/extensions/diagonalley/views_api.py +++ b/lnbits/extensions/diagonalley/views_api.py @@ -230,7 +230,7 @@ async def api_diagonalley_order_delete(order_id): async def api_diagonalleys_order_paid(order_id): with open_ext_db("diagonalley") as db: db.execute( - "UPDATE orders SET paid = ? WHERE id = ?", + "UPDATE diagonalley.orders SET paid = ? WHERE id = ?", ( True, order_id, @@ -244,13 +244,13 @@ async def api_diagonalleys_order_paid(order_id): async def api_diagonalleys_order_shipped(order_id): with open_ext_db("diagonalley") as db: db.execute( - "UPDATE orders SET shipped = ? WHERE id = ?", + "UPDATE diagonalley.orders SET shipped = ? WHERE id = ?", ( True, order_id, ), ) - order = db.fetchone("SELECT * FROM orders WHERE id = ?", (order_id,)) + order = db.fetchone("SELECT * FROM diagonalley.orders WHERE id = ?", (order_id,)) return ( jsonify( @@ -268,12 +268,12 @@ async def api_diagonalleys_order_shipped(order_id): ) async def api_diagonalleys_stall_products(indexer_id): with open_ext_db("diagonalley") as db: - rows = db.fetchone("SELECT * FROM indexers WHERE id = ?", (indexer_id,)) + rows = db.fetchone("SELECT * FROM diagonalley.indexers WHERE id = ?", (indexer_id,)) print(rows[1]) if not rows: return jsonify({"message": "Indexer does not exist."}), HTTPStatus.NOT_FOUND - products = db.fetchone("SELECT * FROM products WHERE wallet = ?", (rows[1],)) + products = db.fetchone("SELECT * FROM diagonalley.products WHERE wallet = ?", (rows[1],)) if not products: return jsonify({"message": "No products"}), HTTPStatus.NOT_FOUND @@ -293,7 +293,7 @@ async def api_diagonalleys_stall_products(indexer_id): ) async def api_diagonalleys_stall_checkshipped(checking_id): with open_ext_db("diagonalley") as db: - rows = db.fetchone("SELECT * FROM orders WHERE invoiceid = ?", (checking_id,)) + rows = db.fetchone("SELECT * FROM diagonalley.orders WHERE invoiceid = ?", (checking_id,)) return jsonify({"shipped": rows["shipped"]}), HTTPStatus.OK @@ -329,7 +329,7 @@ async def api_diagonalley_stall_order(indexer_id): with open_ext_db("diagonalley") as db: db.execute( """ - INSERT INTO orders (id, productid, wallet, product, quantity, shippingzone, address, email, invoiceid, paid, shipped) + INSERT INTO diagonalley.orders (id, productid, wallet, product, quantity, shippingzone, address, email, invoiceid, paid, shipped) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( diff --git a/lnbits/extensions/events/crud.py b/lnbits/extensions/events/crud.py index 20faa09ac..f7839b934 100644 --- a/lnbits/extensions/events/crud.py +++ b/lnbits/extensions/events/crud.py @@ -14,7 +14,7 @@ async def create_ticket( ) -> Tickets: await db.execute( """ - INSERT INTO ticket (id, wallet, event, name, email, registered, paid) + INSERT INTO events.ticket (id, wallet, event, name, email, registered, paid) VALUES (?, ?, ?, ?, ?, ?, ?) """, (payment_hash, wallet, event, name, email, False, False), @@ -26,11 +26,11 @@ async def create_ticket( async def set_ticket_paid(payment_hash: str) -> Tickets: - row = await db.fetchone("SELECT * FROM ticket WHERE id = ?", (payment_hash,)) + row = await db.fetchone("SELECT * FROM events.ticket WHERE id = ?", (payment_hash,)) if row[6] != True: await db.execute( """ - UPDATE ticket + UPDATE events.ticket SET paid = true WHERE id = ? """, @@ -44,7 +44,7 @@ async def set_ticket_paid(payment_hash: str) -> Tickets: amount_tickets = eventdata.amount_tickets - 1 await db.execute( """ - UPDATE events + UPDATE events.events SET sold = ?, amount_tickets = ? WHERE id = ? """, @@ -57,7 +57,7 @@ async def set_ticket_paid(payment_hash: str) -> Tickets: async def get_ticket(payment_hash: str) -> Optional[Tickets]: - row = await db.fetchone("SELECT * FROM ticket WHERE id = ?", (payment_hash,)) + row = await db.fetchone("SELECT * FROM events.ticket WHERE id = ?", (payment_hash,)) return Tickets(**row) if row else None @@ -67,13 +67,13 @@ async def get_tickets(wallet_ids: Union[str, List[str]]) -> List[Tickets]: q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( - f"SELECT * FROM ticket WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM events.ticket WHERE wallet IN ({q})", (*wallet_ids,) ) return [Tickets(**row) for row in rows] async def delete_ticket(payment_hash: str) -> None: - await db.execute("DELETE FROM ticket WHERE id = ?", (payment_hash,)) + await db.execute("DELETE FROM events.ticket WHERE id = ?", (payment_hash,)) # EVENTS @@ -93,7 +93,7 @@ async def create_event( event_id = urlsafe_short_hash() await db.execute( """ - INSERT INTO events (id, wallet, name, info, closing_date, event_start_date, event_end_date, amount_tickets, price_per_ticket, sold) + INSERT INTO events.events (id, wallet, name, info, closing_date, event_start_date, event_end_date, amount_tickets, price_per_ticket, sold) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( @@ -118,7 +118,7 @@ async def create_event( async def update_event(event_id: str, **kwargs) -> Events: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) await db.execute( - f"UPDATE events SET {q} WHERE id = ?", (*kwargs.values(), event_id) + f"UPDATE events.events SET {q} WHERE id = ?", (*kwargs.values(), event_id) ) event = await get_event(event_id) assert event, "Newly updated event couldn't be retrieved" @@ -126,7 +126,7 @@ async def update_event(event_id: str, **kwargs) -> Events: async def get_event(event_id: str) -> Optional[Events]: - row = await db.fetchone("SELECT * FROM events WHERE id = ?", (event_id,)) + row = await db.fetchone("SELECT * FROM events.events WHERE id = ?", (event_id,)) return Events(**row) if row else None @@ -136,14 +136,14 @@ async def get_events(wallet_ids: Union[str, List[str]]) -> List[Events]: q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( - f"SELECT * FROM events WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM events.events WHERE wallet IN ({q})", (*wallet_ids,) ) return [Events(**row) for row in rows] async def delete_event(event_id: str) -> None: - await db.execute("DELETE FROM events WHERE id = ?", (event_id,)) + await db.execute("DELETE FROM events.events WHERE id = ?", (event_id,)) # EVENTTICKETS @@ -151,13 +151,13 @@ async def delete_event(event_id: str) -> None: async def get_event_tickets(event_id: str, wallet_id: str) -> List[Tickets]: rows = await db.fetchall( - "SELECT * FROM ticket WHERE wallet = ? AND event = ?", (wallet_id, event_id) + "SELECT * FROM events.ticket WHERE wallet = ? AND event = ?", (wallet_id, event_id) ) return [Tickets(**row) for row in rows] async def reg_ticket(ticket_id: str) -> List[Tickets]: - await db.execute("UPDATE ticket SET registered = ? WHERE id = ?", (True, ticket_id)) - ticket = await db.fetchone("SELECT * FROM ticket WHERE id = ?", (ticket_id,)) - rows = await db.fetchall("SELECT * FROM ticket WHERE event = ?", (ticket[1],)) + await db.execute("UPDATE events.ticket SET registered = ? WHERE id = ?", (True, ticket_id)) + ticket = await db.fetchone("SELECT * FROM events.ticket WHERE id = ?", (ticket_id,)) + rows = await db.fetchall("SELECT * FROM events.ticket WHERE event = ?", (ticket[1],)) return [Tickets(**row) for row in rows] diff --git a/lnbits/extensions/events/migrations.py b/lnbits/extensions/events/migrations.py index 5d0e58403..ae4e45f79 100644 --- a/lnbits/extensions/events/migrations.py +++ b/lnbits/extensions/events/migrations.py @@ -2,7 +2,7 @@ async def m001_initial(db): await db.execute( """ - CREATE TABLE IF NOT EXISTS events ( + CREATE TABLE events.events ( id TEXT PRIMARY KEY, wallet TEXT NOT NULL, name TEXT NOT NULL, @@ -13,21 +13,21 @@ async def m001_initial(db): amount_tickets INTEGER NOT NULL, price_per_ticket INTEGER NOT NULL, sold INTEGER NOT NULL, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')) + time TIMESTAMP NOT NULL DEFAULT """ + db.timestamp_now + """ ); """ ) await db.execute( """ - CREATE TABLE IF NOT EXISTS tickets ( + CREATE TABLE events.tickets ( id TEXT PRIMARY KEY, wallet TEXT NOT NULL, event TEXT NOT NULL, name TEXT NOT NULL, email TEXT NOT NULL, registered BOOLEAN NOT NULL, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')) + time TIMESTAMP NOT NULL DEFAULT """ + db.timestamp_now + """ ); """ ) @@ -37,7 +37,7 @@ async def m002_changed(db): await db.execute( """ - CREATE TABLE IF NOT EXISTS ticket ( + CREATE TABLE events.ticket ( id TEXT PRIMARY KEY, wallet TEXT NOT NULL, event TEXT NOT NULL, @@ -45,12 +45,12 @@ async def m002_changed(db): email TEXT NOT NULL, registered BOOLEAN NOT NULL, paid BOOLEAN NOT NULL, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')) + time TIMESTAMP NOT NULL DEFAULT """ + db.timestamp_now + """ ); """ ) - for row in [list(row) for row in await db.fetchall("SELECT * FROM tickets")]: + for row in [list(row) for row in await db.fetchall("SELECT * FROM events.tickets")]: usescsv = "" for i in range(row[5]): @@ -61,7 +61,7 @@ async def m002_changed(db): usescsv = usescsv[1:] await db.execute( """ - INSERT INTO ticket ( + INSERT INTO events.ticket ( id, wallet, event, @@ -82,4 +82,4 @@ async def m002_changed(db): True, ), ) - await db.execute("DROP TABLE tickets") + await db.execute("DROP TABLE events.tickets") diff --git a/lnbits/extensions/example/migrations.py b/lnbits/extensions/example/migrations.py index aca4a27e4..f9b8b37dc 100644 --- a/lnbits/extensions/example/migrations.py +++ b/lnbits/extensions/example/migrations.py @@ -2,10 +2,10 @@ # await db.execute( # """ -# CREATE TABLE IF NOT EXISTS example ( +# CREATE TABLE example.example ( # id TEXT PRIMARY KEY, # wallet TEXT NOT NULL, -# time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')) +# time TIMESTAMP NOT NULL DEFAULT """ + db.timestamp_now + """ # ); # """ # ) diff --git a/lnbits/extensions/jukebox/crud.py b/lnbits/extensions/jukebox/crud.py index a24d8a7ec..4e3ba2f15 100644 --- a/lnbits/extensions/jukebox/crud.py +++ b/lnbits/extensions/jukebox/crud.py @@ -21,7 +21,7 @@ async def create_jukebox( juke_id = urlsafe_short_hash() result = await db.execute( """ - INSERT INTO jukebox (id, user, title, wallet, sp_user, sp_secret, sp_access_token, sp_refresh_token, sp_device, sp_playlists, price, profit) + INSERT INTO jukebox.jukebox (id, user, title, wallet, sp_user, sp_secret, sp_access_token, sp_refresh_token, sp_device, sp_playlists, price, profit) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( @@ -47,35 +47,35 @@ async def create_jukebox( async def update_jukebox(juke_id: str, **kwargs) -> Optional[Jukebox]: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) await db.execute( - f"UPDATE jukebox SET {q} WHERE id = ?", (*kwargs.values(), juke_id) + f"UPDATE jukebox.jukebox SET {q} WHERE id = ?", (*kwargs.values(), juke_id) ) - row = await db.fetchone("SELECT * FROM jukebox WHERE id = ?", (juke_id,)) + row = await db.fetchone("SELECT * FROM jukebox.jukebox WHERE id = ?", (juke_id,)) return Jukebox(**row) if row else None async def get_jukebox(juke_id: str) -> Optional[Jukebox]: - row = await db.fetchone("SELECT * FROM jukebox WHERE id = ?", (juke_id,)) + row = await db.fetchone("SELECT * FROM jukebox.jukebox WHERE id = ?", (juke_id,)) return Jukebox(**row) if row else None async def get_jukebox_by_user(user: str) -> Optional[Jukebox]: - row = await db.fetchone("SELECT * FROM jukebox WHERE sp_user = ?", (user,)) + row = await db.fetchone("SELECT * FROM jukebox.jukebox WHERE sp_user = ?", (user,)) return Jukebox(**row) if row else None async def get_jukeboxs(user: str) -> List[Jukebox]: - rows = await db.fetchall("SELECT * FROM jukebox WHERE user = ?", (user,)) + rows = await db.fetchall("SELECT * FROM jukebox.jukebox WHERE user = ?", (user,)) for row in rows: if row.sp_playlists == "": await delete_jukebox(row.id) - rows = await db.fetchall("SELECT * FROM jukebox WHERE user = ?", (user,)) + rows = await db.fetchall("SELECT * FROM jukebox.jukebox WHERE user = ?", (user,)) return [Jukebox.from_row(row) for row in rows] async def delete_jukebox(juke_id: str): await db.execute( """ - DELETE FROM jukebox WHERE id = ? + DELETE FROM jukebox.jukebox WHERE id = ? """, (juke_id), ) @@ -89,7 +89,7 @@ async def create_jukebox_payment( ) -> JukeboxPayment: result = await db.execute( """ - INSERT INTO jukebox_payment (payment_hash, juke_id, song_id, paid) + INSERT INTO jukebox.jukebox_payment (payment_hash, juke_id, song_id, paid) VALUES (?, ?, ?, ?) """, ( @@ -109,7 +109,7 @@ async def update_jukebox_payment( ) -> Optional[JukeboxPayment]: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) await db.execute( - f"UPDATE jukebox_payment SET {q} WHERE payment_hash = ?", + f"UPDATE jukebox.jukebox_payment SET {q} WHERE payment_hash = ?", (*kwargs.values(), payment_hash), ) return await get_jukebox_payment(payment_hash) @@ -117,6 +117,6 @@ async def update_jukebox_payment( async def get_jukebox_payment(payment_hash: str) -> Optional[JukeboxPayment]: row = await db.fetchone( - "SELECT * FROM jukebox_payment WHERE payment_hash = ?", (payment_hash,) + "SELECT * FROM jukebox.jukebox_payment WHERE payment_hash = ?", (payment_hash,) ) return JukeboxPayment(**row) if row else None diff --git a/lnbits/extensions/jukebox/migrations.py b/lnbits/extensions/jukebox/migrations.py index 7d4fe2e34..a0a3bd285 100644 --- a/lnbits/extensions/jukebox/migrations.py +++ b/lnbits/extensions/jukebox/migrations.py @@ -4,9 +4,9 @@ async def m001_initial(db): """ await db.execute( """ - CREATE TABLE jukebox ( + CREATE TABLE jukebox.jukebox ( id TEXT PRIMARY KEY, - user TEXT, + "user" TEXT, title TEXT, wallet TEXT, inkey TEXT, @@ -29,7 +29,7 @@ async def m002_initial(db): """ await db.execute( """ - CREATE TABLE jukebox_payment ( + CREATE TABLE jukebox.jukebox_payment ( payment_hash TEXT PRIMARY KEY, juke_id TEXT, song_id TEXT, diff --git a/lnbits/extensions/livestream/crud.py b/lnbits/extensions/livestream/crud.py index 1c1043db2..360b2ceaa 100644 --- a/lnbits/extensions/livestream/crud.py +++ b/lnbits/extensions/livestream/crud.py @@ -9,7 +9,7 @@ from .models import Livestream, Track, Producer async def create_livestream(*, wallet_id: str) -> int: result = await db.execute( """ - INSERT INTO livestreams (wallet) + INSERT INTO livestream.livestreams (wallet) VALUES (?) """, (wallet_id,), @@ -18,14 +18,16 @@ async def create_livestream(*, wallet_id: str) -> int: async def get_livestream(ls_id: int) -> Optional[Livestream]: - row = await db.fetchone("SELECT * FROM livestreams WHERE id = ?", (ls_id,)) + row = await db.fetchone( + "SELECT * FROM livestream.livestreams WHERE id = ?", (ls_id,) + ) return Livestream(**dict(row)) if row else None async def get_livestream_by_track(track_id: int) -> Optional[Livestream]: row = await db.fetchone( """ - SELECT livestreams.* FROM livestreams + SELECT livestreams.* FROM livestream.livestreams INNER JOIN tracks ON tracks.livestream = livestreams.id WHERE tracks.id = ? """, @@ -35,7 +37,9 @@ async def get_livestream_by_track(track_id: int) -> Optional[Livestream]: async def get_or_create_livestream_by_wallet(wallet: str) -> Optional[Livestream]: - row = await db.fetchone("SELECT * FROM livestreams WHERE wallet = ?", (wallet,)) + row = await db.fetchone( + "SELECT * FROM livestream.livestreams WHERE wallet = ?", (wallet,) + ) if not row: # create on the fly @@ -47,14 +51,14 @@ async def get_or_create_livestream_by_wallet(wallet: str) -> Optional[Livestream async def update_current_track(ls_id: int, track_id: Optional[int]): await db.execute( - "UPDATE livestreams SET current_track = ? WHERE id = ?", + "UPDATE livestream.livestreams SET current_track = ? WHERE id = ?", (track_id, ls_id), ) async def update_livestream_fee(ls_id: int, fee_pct: int): await db.execute( - "UPDATE livestreams SET fee_pct = ? WHERE id = ?", + "UPDATE livestream.livestreams SET fee_pct = ? WHERE id = ?", (fee_pct, ls_id), ) @@ -68,7 +72,7 @@ async def add_track( ) -> int: result = await db.execute( """ - INSERT INTO tracks (livestream, name, download_url, price_msat, producer) + INSERT INTO livestream.tracks (livestream, name, download_url, price_msat, producer) VALUES (?, ?, ?, ?, ?) """, (livestream, name, download_url, price_msat, producer), @@ -86,7 +90,7 @@ async def update_track( ) -> int: result = await db.execute( """ - UPDATE tracks SET + UPDATE livestream.tracks SET name = ?, download_url = ?, price_msat = ?, @@ -105,7 +109,7 @@ async def get_track(track_id: Optional[int]) -> Optional[Track]: row = await db.fetchone( """ SELECT id, download_url, price_msat, name, producer - FROM tracks WHERE id = ? + FROM livestream.tracks WHERE id = ? """, (track_id,), ) @@ -116,7 +120,7 @@ async def get_tracks(livestream: int) -> List[Track]: rows = await db.fetchall( """ SELECT id, download_url, price_msat, name, producer - FROM tracks WHERE livestream = ? + FROM livestream.tracks WHERE livestream = ? """, (livestream,), ) @@ -126,7 +130,7 @@ async def get_tracks(livestream: int) -> List[Track]: async def delete_track_from_livestream(livestream: int, track_id: int): await db.execute( """ - DELETE FROM tracks WHERE livestream = ? AND id = ? + DELETE FROM livestream.tracks WHERE livestream = ? AND id = ? """, (livestream, track_id), ) @@ -137,7 +141,7 @@ async def add_producer(livestream: int, name: str) -> int: existing = await db.fetchall( """ - SELECT id FROM producers + SELECT id FROM livestream.producers WHERE livestream = ? AND lower(name) = ? """, (livestream, name.lower()), @@ -150,7 +154,7 @@ async def add_producer(livestream: int, name: str) -> int: result = await db.execute( """ - INSERT INTO producers (livestream, name, user, wallet) + INSERT INTO livestream.producers (livestream, name, "user", wallet) VALUES (?, ?, ?, ?) """, (livestream, name, user.id, wallet.id), @@ -161,8 +165,8 @@ async def add_producer(livestream: int, name: str) -> int: async def get_producer(producer_id: int) -> Optional[Producer]: row = await db.fetchone( """ - SELECT id, user, wallet, name - FROM producers WHERE id = ? + SELECT id, "user", wallet, name + FROM livestream.producers WHERE id = ? """, (producer_id,), ) @@ -172,8 +176,8 @@ async def get_producer(producer_id: int) -> Optional[Producer]: async def get_producers(livestream: int) -> List[Producer]: rows = await db.fetchall( """ - SELECT id, user, wallet, name - FROM producers WHERE livestream = ? + SELECT id, "user", wallet, name + FROM livestream.producers WHERE livestream = ? """, (livestream,), ) diff --git a/lnbits/extensions/livestream/migrations.py b/lnbits/extensions/livestream/migrations.py index 465d04ee1..fb664ab16 100644 --- a/lnbits/extensions/livestream/migrations.py +++ b/lnbits/extensions/livestream/migrations.py @@ -3,9 +3,9 @@ async def m001_initial(db): Initial livestream tables. """ await db.execute( - """ - CREATE TABLE IF NOT EXISTS livestreams ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + f""" + CREATE TABLE livestream.livestreams ( + id {db.serial_primary_key}, wallet TEXT NOT NULL, fee_pct INTEGER NOT NULL DEFAULT 10, current_track INTEGER @@ -14,11 +14,11 @@ async def m001_initial(db): ) await db.execute( - """ - CREATE TABLE IF NOT EXISTS producers ( - livestream INTEGER NOT NULL REFERENCES livestreams (id), - id INTEGER PRIMARY KEY AUTOINCREMENT, - user TEXT NOT NULL, + f""" + CREATE TABLE livestream.producers ( + livestream INTEGER NOT NULL REFERENCES {db.references_schema}livestreams (id), + id {db.serial_primary_key}, + "user" TEXT NOT NULL, wallet TEXT NOT NULL, name TEXT NOT NULL ); @@ -26,14 +26,14 @@ async def m001_initial(db): ) await db.execute( - """ - CREATE TABLE IF NOT EXISTS tracks ( - livestream INTEGER NOT NULL REFERENCES livestreams (id), - id INTEGER PRIMARY KEY AUTOINCREMENT, + f""" + CREATE TABLE livestream.tracks ( + livestream INTEGER NOT NULL REFERENCES {db.references_schema}livestreams (id), + id {db.serial_primary_key}, download_url TEXT, price_msat INTEGER NOT NULL DEFAULT 0, name TEXT, - producer INTEGER REFERENCES producers (id) NOT NULL + producer INTEGER REFERENCES {db.references_schema}producers (id) NOT NULL ); """ ) diff --git a/lnbits/extensions/livestream/tasks.py b/lnbits/extensions/livestream/tasks.py index 52f86d155..158e9c73b 100644 --- a/lnbits/extensions/livestream/tasks.py +++ b/lnbits/extensions/livestream/tasks.py @@ -49,7 +49,7 @@ async def on_invoice_paid(payment: Payment) -> None: # and reduce it by the amount we're going to send to the producer await core_db.execute( """ - UPDATE apipayments + UPDATE livestream.apipayments SET extra = ?, amount = ? WHERE hash = ? AND checking_id NOT LIKE 'internal_%' diff --git a/lnbits/extensions/lnticket/crud.py b/lnbits/extensions/lnticket/crud.py index ed8c22710..e7bf52624 100644 --- a/lnbits/extensions/lnticket/crud.py +++ b/lnbits/extensions/lnticket/crud.py @@ -18,7 +18,7 @@ async def create_ticket( ) -> Tickets: await db.execute( """ - INSERT INTO ticket (id, form, email, ltext, name, wallet, sats, paid) + INSERT INTO lnticket.ticket (id, form, email, ltext, name, wallet, sats, paid) VALUES (?, ?, ?, ?, ?, ?, ?, ?) """, (payment_hash, form, email, ltext, name, wallet, sats, False), @@ -30,11 +30,11 @@ async def create_ticket( async def set_ticket_paid(payment_hash: str) -> Tickets: - row = await db.fetchone("SELECT * FROM ticket WHERE id = ?", (payment_hash,)) + row = await db.fetchone("SELECT * FROM lnticket.ticket WHERE id = ?", (payment_hash,)) if row[7] == False: await db.execute( """ - UPDATE ticket + UPDATE lnticket.ticket SET paid = true WHERE id = ? """, @@ -47,7 +47,7 @@ async def set_ticket_paid(payment_hash: str) -> Tickets: amount = formdata.amountmade + row[7] await db.execute( """ - UPDATE form + UPDATE lnticket.form SET amountmade = ? WHERE id = ? """, @@ -77,7 +77,7 @@ async def set_ticket_paid(payment_hash: str) -> Tickets: async def get_ticket(ticket_id: str) -> Optional[Tickets]: - row = await db.fetchone("SELECT * FROM ticket WHERE id = ?", (ticket_id,)) + row = await db.fetchone("SELECT * FROM lnticket.ticket WHERE id = ?", (ticket_id,)) return Tickets(**row) if row else None @@ -87,14 +87,14 @@ async def get_tickets(wallet_ids: Union[str, List[str]]) -> List[Tickets]: q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( - f"SELECT * FROM ticket WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM lnticket.ticket WHERE wallet IN ({q})", (*wallet_ids,) ) return [Tickets(**row) for row in rows] async def delete_ticket(ticket_id: str) -> None: - await db.execute("DELETE FROM ticket WHERE id = ?", (ticket_id,)) + await db.execute("DELETE FROM lnticket.ticket WHERE id = ?", (ticket_id,)) # FORMS @@ -111,7 +111,7 @@ async def create_form( form_id = urlsafe_short_hash() await db.execute( """ - INSERT INTO form (id, wallet, name, webhook, description, costpword, amountmade) + INSERT INTO lnticket.form (id, wallet, name, webhook, description, costpword, amountmade) VALUES (?, ?, ?, ?, ?, ?, ?) """, (form_id, wallet, name, webhook, description, costpword, 0), @@ -124,14 +124,14 @@ async def create_form( async def update_form(form_id: str, **kwargs) -> Forms: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) - await db.execute(f"UPDATE form SET {q} WHERE id = ?", (*kwargs.values(), form_id)) - row = await db.fetchone("SELECT * FROM form WHERE id = ?", (form_id,)) + await db.execute(f"UPDATE lnticket.form SET {q} WHERE id = ?", (*kwargs.values(), form_id)) + row = await db.fetchone("SELECT * FROM lnticket.form WHERE id = ?", (form_id,)) assert row, "Newly updated form couldn't be retrieved" return Forms(**row) async def get_form(form_id: str) -> Optional[Forms]: - row = await db.fetchone("SELECT * FROM form WHERE id = ?", (form_id,)) + row = await db.fetchone("SELECT * FROM lnticket.form WHERE id = ?", (form_id,)) return Forms(**row) if row else None @@ -141,11 +141,11 @@ async def get_forms(wallet_ids: Union[str, List[str]]) -> List[Forms]: q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( - f"SELECT * FROM form WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM lnticket.form WHERE wallet IN ({q})", (*wallet_ids,) ) return [Forms(**row) for row in rows] async def delete_form(form_id: str) -> None: - await db.execute("DELETE FROM form WHERE id = ?", (form_id,)) + await db.execute("DELETE FROM lnticket.form WHERE id = ?", (form_id,)) diff --git a/lnbits/extensions/lnticket/migrations.py b/lnbits/extensions/lnticket/migrations.py index 8ced65ef7..c2c2d2755 100644 --- a/lnbits/extensions/lnticket/migrations.py +++ b/lnbits/extensions/lnticket/migrations.py @@ -2,21 +2,21 @@ async def m001_initial(db): await db.execute( """ - CREATE TABLE IF NOT EXISTS forms ( + CREATE TABLE lnticket.forms ( id TEXT PRIMARY KEY, wallet TEXT NOT NULL, name TEXT NOT NULL, description TEXT NOT NULL, costpword INTEGER NOT NULL, amountmade INTEGER NOT NULL, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')) + time TIMESTAMP NOT NULL DEFAULT """ + db.timestamp_now + """ ); """ ) await db.execute( """ - CREATE TABLE IF NOT EXISTS tickets ( + CREATE TABLE lnticket.tickets ( id TEXT PRIMARY KEY, form TEXT NOT NULL, email TEXT NOT NULL, @@ -24,7 +24,7 @@ async def m001_initial(db): name TEXT NOT NULL, wallet TEXT NOT NULL, sats INTEGER NOT NULL, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')) + time TIMESTAMP NOT NULL DEFAULT """ + db.timestamp_now + """ ); """ ) @@ -34,7 +34,7 @@ async def m002_changed(db): await db.execute( """ - CREATE TABLE IF NOT EXISTS ticket ( + CREATE TABLE lnticket.ticket ( id TEXT PRIMARY KEY, form TEXT NOT NULL, email TEXT NOT NULL, @@ -43,12 +43,12 @@ async def m002_changed(db): wallet TEXT NOT NULL, sats INTEGER NOT NULL, paid BOOLEAN NOT NULL, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')) + time TIMESTAMP NOT NULL DEFAULT """ + db.timestamp_now + """ ); """ ) - for row in [list(row) for row in await db.fetchall("SELECT * FROM tickets")]: + for row in [list(row) for row in await db.fetchall("SELECT * FROM lnticket.tickets")]: usescsv = "" for i in range(row[5]): @@ -59,7 +59,7 @@ async def m002_changed(db): usescsv = usescsv[1:] await db.execute( """ - INSERT INTO ticket ( + INSERT INTO lnticket.ticket ( id, form, email, @@ -82,14 +82,14 @@ async def m002_changed(db): True, ), ) - await db.execute("DROP TABLE tickets") + await db.execute("DROP TABLE lnticket.tickets") async def m003_changed(db): await db.execute( """ - CREATE TABLE IF NOT EXISTS form ( + CREATE TABLE lnticket.form ( id TEXT PRIMARY KEY, wallet TEXT NOT NULL, name TEXT NOT NULL, @@ -97,12 +97,12 @@ async def m003_changed(db): description TEXT NOT NULL, costpword INTEGER NOT NULL, amountmade INTEGER NOT NULL, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')) + time TIMESTAMP NOT NULL DEFAULT """ + db.timestamp_now + """ ); """ ) - for row in [list(row) for row in await db.fetchall("SELECT * FROM forms")]: + for row in [list(row) for row in await db.fetchall("SELECT * FROM lnticket.forms")]: usescsv = "" for i in range(row[5]): @@ -113,7 +113,7 @@ async def m003_changed(db): usescsv = usescsv[1:] await db.execute( """ - INSERT INTO form ( + INSERT INTO lnticket.form ( id, wallet, name, @@ -134,4 +134,4 @@ async def m003_changed(db): row[6], ), ) - await db.execute("DROP TABLE forms") + await db.execute("DROP TABLE lnticket.forms") diff --git a/lnbits/extensions/lnurlp/crud.py b/lnbits/extensions/lnurlp/crud.py index 9c2b182a9..4d47a592d 100644 --- a/lnbits/extensions/lnurlp/crud.py +++ b/lnbits/extensions/lnurlp/crud.py @@ -18,7 +18,7 @@ async def create_pay_link( ) -> PayLink: result = await db.execute( """ - INSERT INTO pay_links ( + INSERT INTO lnurlp.pay_links ( wallet, description, min, @@ -52,7 +52,7 @@ async def create_pay_link( async def get_pay_link(link_id: int) -> Optional[PayLink]: - row = await db.fetchone("SELECT * FROM pay_links WHERE id = ?", (link_id,)) + row = await db.fetchone("SELECT * FROM lnurlp.pay_links WHERE id = ?", (link_id,)) return PayLink.from_row(row) if row else None @@ -63,7 +63,7 @@ async def get_pay_links(wallet_ids: Union[str, List[str]]) -> List[PayLink]: q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( f""" - SELECT * FROM pay_links WHERE wallet IN ({q}) + SELECT * FROM lnurlp.pay_links WHERE wallet IN ({q}) ORDER BY Id """, (*wallet_ids,), @@ -75,20 +75,20 @@ async def get_pay_links(wallet_ids: Union[str, List[str]]) -> List[PayLink]: async def update_pay_link(link_id: int, **kwargs) -> Optional[PayLink]: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) await db.execute( - f"UPDATE pay_links SET {q} WHERE id = ?", (*kwargs.values(), link_id) + f"UPDATE lnurlp.pay_links SET {q} WHERE id = ?", (*kwargs.values(), link_id) ) - row = await db.fetchone("SELECT * FROM pay_links WHERE id = ?", (link_id,)) + row = await db.fetchone("SELECT * FROM lnurlp.pay_links WHERE id = ?", (link_id,)) return PayLink.from_row(row) if row else None async def increment_pay_link(link_id: int, **kwargs) -> Optional[PayLink]: q = ", ".join([f"{field[0]} = {field[0]} + ?" for field in kwargs.items()]) await db.execute( - f"UPDATE pay_links SET {q} WHERE id = ?", (*kwargs.values(), link_id) + f"UPDATE lnurlp.pay_links SET {q} WHERE id = ?", (*kwargs.values(), link_id) ) - row = await db.fetchone("SELECT * FROM pay_links WHERE id = ?", (link_id,)) + row = await db.fetchone("SELECT * FROM lnurlp.pay_links WHERE id = ?", (link_id,)) return PayLink.from_row(row) if row else None async def delete_pay_link(link_id: int) -> None: - await db.execute("DELETE FROM pay_links WHERE id = ?", (link_id,)) + await db.execute("DELETE FROM lnurlp.pay_links WHERE id = ?", (link_id,)) diff --git a/lnbits/extensions/lnurlp/migrations.py b/lnbits/extensions/lnurlp/migrations.py index b7ebd3f1b..428bde2c8 100644 --- a/lnbits/extensions/lnurlp/migrations.py +++ b/lnbits/extensions/lnurlp/migrations.py @@ -3,9 +3,9 @@ async def m001_initial(db): Initial pay table. """ await db.execute( - """ - CREATE TABLE IF NOT EXISTS pay_links ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + f""" + CREATE TABLE lnurlp.pay_links ( + id {db.serial_primary_key}, wallet TEXT NOT NULL, description TEXT NOT NULL, amount INTEGER NOT NULL, @@ -20,13 +20,13 @@ async def m002_webhooks_and_success_actions(db): """ Webhooks and success actions. """ - await db.execute("ALTER TABLE pay_links ADD COLUMN webhook_url TEXT;") - await db.execute("ALTER TABLE pay_links ADD COLUMN success_text TEXT;") - await db.execute("ALTER TABLE pay_links ADD COLUMN success_url TEXT;") + await db.execute("ALTER TABLE lnurlp.pay_links ADD COLUMN webhook_url TEXT;") + await db.execute("ALTER TABLE lnurlp.pay_links ADD COLUMN success_text TEXT;") + await db.execute("ALTER TABLE lnurlp.pay_links ADD COLUMN success_url TEXT;") await db.execute( - """ - CREATE TABLE invoices ( - pay_link INTEGER NOT NULL REFERENCES pay_links (id), + f""" + CREATE TABLE lnurlp.invoices ( + pay_link INTEGER NOT NULL REFERENCES {db.references_schema}pay_links (id), payment_hash TEXT NOT NULL, webhook_sent INT, -- null means not sent, otherwise store status expiry INT @@ -41,12 +41,12 @@ async def m003_min_max_comment_fiat(db): converted automatically to satoshis based on some API. """ await db.execute( - "ALTER TABLE pay_links ADD COLUMN currency TEXT;" + "ALTER TABLE lnurlp.pay_links ADD COLUMN currency TEXT;" ) # null = satoshis await db.execute( - "ALTER TABLE pay_links ADD COLUMN comment_chars INTEGER DEFAULT 0;" + "ALTER TABLE lnurlp.pay_links ADD COLUMN comment_chars INTEGER DEFAULT 0;" ) - await db.execute("ALTER TABLE pay_links RENAME COLUMN amount TO min;") - await db.execute("ALTER TABLE pay_links ADD COLUMN max INTEGER;") - await db.execute("UPDATE pay_links SET max = min;") - await db.execute("DROP TABLE invoices") + await db.execute("ALTER TABLE lnurlp.pay_links RENAME COLUMN amount TO min;") + await db.execute("ALTER TABLE lnurlp.pay_links ADD COLUMN max INTEGER;") + await db.execute("UPDATE lnurlp.pay_links SET max = min;") + await db.execute("DROP TABLE lnurlp.invoices") diff --git a/lnbits/extensions/lnurlp/tasks.py b/lnbits/extensions/lnurlp/tasks.py index e8d6a453f..49bdc797b 100644 --- a/lnbits/extensions/lnurlp/tasks.py +++ b/lnbits/extensions/lnurlp/tasks.py @@ -54,7 +54,7 @@ async def mark_webhook_sent(payment: Payment, status: int) -> None: await core_db.execute( """ - UPDATE apipayments SET extra = ? + UPDATE lnurlp.apipayments SET extra = ? WHERE hash = ? """, (json.dumps(payment.extra), payment.payment_hash), diff --git a/lnbits/extensions/offlineshop/crud.py b/lnbits/extensions/offlineshop/crud.py index e6bd0d6c6..eb19c9396 100644 --- a/lnbits/extensions/offlineshop/crud.py +++ b/lnbits/extensions/offlineshop/crud.py @@ -8,7 +8,7 @@ from .models import Shop, Item async def create_shop(*, wallet_id: str) -> int: result = await db.execute( """ - INSERT INTO shops (wallet, wordlist, method) + INSERT INTO offlineshop.shops (wallet, wordlist, method) VALUES (?, ?, 'wordlist') """, (wallet_id, "\n".join(animals)), @@ -17,12 +17,12 @@ async def create_shop(*, wallet_id: str) -> int: async def get_shop(id: int) -> Optional[Shop]: - row = await db.fetchone("SELECT * FROM shops WHERE id = ?", (id,)) + row = await db.fetchone("SELECT * FROM offlineshop.shops WHERE id = ?", (id,)) return Shop(**dict(row)) if row else None async def get_or_create_shop_by_wallet(wallet: str) -> Optional[Shop]: - row = await db.fetchone("SELECT * FROM shops WHERE wallet = ?", (wallet,)) + row = await db.fetchone("SELECT * FROM offlineshop.shops WHERE wallet = ?", (wallet,)) if not row: # create on the fly @@ -34,7 +34,7 @@ async def get_or_create_shop_by_wallet(wallet: str) -> Optional[Shop]: async def set_method(shop: int, method: str, wordlist: str = "") -> Optional[Shop]: await db.execute( - "UPDATE shops SET method = ?, wordlist = ? WHERE id = ?", + "UPDATE offlineshop.shops SET method = ?, wordlist = ? WHERE id = ?", (method, wordlist, shop), ) return await get_shop(shop) @@ -50,7 +50,7 @@ async def add_item( ) -> int: result = await db.execute( """ - INSERT INTO items (shop, name, description, image, price, unit) + INSERT INTO offlineshop.items (shop, name, description, image, price, unit) VALUES (?, ?, ?, ?, ?, ?) """, (shop, name, description, image, price, unit), @@ -69,7 +69,7 @@ async def update_item( ) -> int: await db.execute( """ - UPDATE items SET + UPDATE offlineshop.items SET name = ?, description = ?, image = ?, @@ -83,19 +83,19 @@ async def update_item( async def get_item(id: int) -> Optional[Item]: - row = await db.fetchone("SELECT * FROM items WHERE id = ? LIMIT 1", (id,)) + row = await db.fetchone("SELECT * FROM offlineshop.items WHERE id = ? LIMIT 1", (id,)) return Item(**dict(row)) if row else None async def get_items(shop: int) -> List[Item]: - rows = await db.fetchall("SELECT * FROM items WHERE shop = ?", (shop,)) + rows = await db.fetchall("SELECT * FROM offlineshop.items WHERE shop = ?", (shop,)) return [Item(**dict(row)) for row in rows] async def delete_item_from_shop(shop: int, item_id: int): await db.execute( """ - DELETE FROM items WHERE shop = ? AND id = ? + DELETE FROM offlineshop.items WHERE shop = ? AND id = ? """, (shop, item_id), ) diff --git a/lnbits/extensions/offlineshop/migrations.py b/lnbits/extensions/offlineshop/migrations.py index ee3bf76f8..f7c2dfec8 100644 --- a/lnbits/extensions/offlineshop/migrations.py +++ b/lnbits/extensions/offlineshop/migrations.py @@ -3,9 +3,9 @@ async def m001_initial(db): Initial offlineshop tables. """ await db.execute( - """ - CREATE TABLE IF NOT EXISTS shops ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + f""" + CREATE TABLE offlineshop.shops ( + id {db.serial_primary_key}, wallet TEXT NOT NULL, method TEXT NOT NULL, wordlist TEXT @@ -14,10 +14,10 @@ async def m001_initial(db): ) await db.execute( - """ - CREATE TABLE IF NOT EXISTS items ( - shop INTEGER NOT NULL REFERENCES shop (id), - id INTEGER PRIMARY KEY AUTOINCREMENT, + f""" + CREATE TABLE offlineshop.items ( + shop INTEGER NOT NULL REFERENCES {db.references_schema}shops (id), + id {db.serial_primary_key}, name TEXT NOT NULL, description TEXT NOT NULL, image TEXT, -- image/png;base64,... diff --git a/lnbits/extensions/paywall/crud.py b/lnbits/extensions/paywall/crud.py index b12cc1ecb..758d6a04d 100644 --- a/lnbits/extensions/paywall/crud.py +++ b/lnbits/extensions/paywall/crud.py @@ -18,7 +18,7 @@ async def create_paywall( paywall_id = urlsafe_short_hash() await db.execute( """ - INSERT INTO paywalls (id, wallet, url, memo, description, amount, remembers) + INSERT INTO paywall.paywalls (id, wallet, url, memo, description, amount, remembers) VALUES (?, ?, ?, ?, ?, ?, ?) """, (paywall_id, wallet_id, url, memo, description, amount, int(remembers)), @@ -30,7 +30,7 @@ async def create_paywall( async def get_paywall(paywall_id: str) -> Optional[Paywall]: - row = await db.fetchone("SELECT * FROM paywalls WHERE id = ?", (paywall_id,)) + row = await db.fetchone("SELECT * FROM paywall.paywalls WHERE id = ?", (paywall_id,)) return Paywall.from_row(row) if row else None @@ -41,11 +41,11 @@ async def get_paywalls(wallet_ids: Union[str, List[str]]) -> List[Paywall]: q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( - f"SELECT * FROM paywalls WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM paywall.paywalls WHERE wallet IN ({q})", (*wallet_ids,) ) return [Paywall.from_row(row) for row in rows] async def delete_paywall(paywall_id: str) -> None: - await db.execute("DELETE FROM paywalls WHERE id = ?", (paywall_id,)) + await db.execute("DELETE FROM paywall.paywalls WHERE id = ?", (paywall_id,)) diff --git a/lnbits/extensions/paywall/migrations.py b/lnbits/extensions/paywall/migrations.py index f2faae2b4..8afe58b18 100644 --- a/lnbits/extensions/paywall/migrations.py +++ b/lnbits/extensions/paywall/migrations.py @@ -7,14 +7,16 @@ async def m001_initial(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS paywalls ( + CREATE TABLE paywall.paywalls ( id TEXT PRIMARY KEY, wallet TEXT NOT NULL, secret TEXT NOT NULL, url TEXT NOT NULL, memo TEXT NOT NULL, amount INTEGER NOT NULL, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')) + time TIMESTAMP NOT NULL DEFAULT """ + + db.timestamp_now + + """ ); """ ) @@ -24,44 +26,41 @@ async def m002_redux(db): """ Creates an improved paywalls table and migrates the existing data. """ - try: - await db.execute("SELECT remembers FROM paywalls") + await db.execute("ALTER TABLE paywall.paywalls RENAME TO paywalls_old") + await db.execute( + """ + CREATE TABLE paywall.paywalls ( + id TEXT PRIMARY KEY, + wallet TEXT NOT NULL, + url TEXT NOT NULL, + memo TEXT NOT NULL, + description TEXT NULL, + amount INTEGER DEFAULT 0, + time TIMESTAMP NOT NULL DEFAULT """ + + db.timestamp_now + + """, + remembers INTEGER DEFAULT 0, + extras TEXT NULL + ); + """ + ) - except OperationalError: - await db.execute("ALTER TABLE paywalls RENAME TO paywalls_old") + for row in [ + list(row) for row in await db.fetchall("SELECT * FROM paywall.paywalls_old") + ]: await db.execute( """ - CREATE TABLE IF NOT EXISTS paywalls ( - id TEXT PRIMARY KEY, - wallet TEXT NOT NULL, - url TEXT NOT NULL, - memo TEXT NOT NULL, - description TEXT NULL, - amount INTEGER DEFAULT 0, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')), - remembers INTEGER DEFAULT 0, - extras TEXT NULL - ); - """ - ) - await db.execute("CREATE INDEX IF NOT EXISTS wallet_idx ON paywalls (wallet)") - - for row in [ - list(row) for row in await db.fetchall("SELECT * FROM paywalls_old") - ]: - await db.execute( - """ - INSERT INTO paywalls ( - id, - wallet, - url, - memo, - amount, - time - ) - VALUES (?, ?, ?, ?, ?, ?) - """, - (row[0], row[1], row[3], row[4], row[5], row[6]), + INSERT INTO paywall.paywalls ( + id, + wallet, + url, + memo, + amount, + time ) + VALUES (?, ?, ?, ?, ?, ?) + """, + (row[0], row[1], row[3], row[4], row[5], row[6]), + ) - await db.execute("DROP TABLE paywalls_old") + await db.execute("DROP TABLE paywall.paywalls_old") diff --git a/lnbits/extensions/satspay/crud.py b/lnbits/extensions/satspay/crud.py index c4d284565..56cabdbe3 100644 --- a/lnbits/extensions/satspay/crud.py +++ b/lnbits/extensions/satspay/crud.py @@ -42,9 +42,9 @@ async def create_charge( payment_request = None await db.execute( """ - INSERT INTO charges ( + INSERT INTO satspay.charges ( id, - user, + "user", description, onchainwallet, onchainaddress, @@ -83,24 +83,26 @@ async def create_charge( async def update_charge(charge_id: str, **kwargs) -> Optional[Charges]: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) await db.execute( - f"UPDATE charges SET {q} WHERE id = ?", (*kwargs.values(), charge_id) + f"UPDATE satspay.charges SET {q} WHERE id = ?", (*kwargs.values(), charge_id) ) - row = await db.fetchone("SELECT * FROM charges WHERE id = ?", (charge_id,)) + row = await db.fetchone("SELECT * FROM satspay.charges WHERE id = ?", (charge_id,)) return Charges.from_row(row) if row else None async def get_charge(charge_id: str) -> Charges: - row = await db.fetchone("SELECT * FROM charges WHERE id = ?", (charge_id,)) + row = await db.fetchone("SELECT * FROM satspay.charges WHERE id = ?", (charge_id,)) return Charges.from_row(row) if row else None async def get_charges(user: str) -> List[Charges]: - rows = await db.fetchall("SELECT * FROM charges WHERE user = ?", (user,)) + rows = await db.fetchall( + """SELECT * FROM satspay.charges WHERE "user" = ?""", (user,) + ) return [Charges.from_row(row) for row in rows] async def delete_charge(charge_id: str) -> None: - await db.execute("DELETE FROM charges WHERE id = ?", (charge_id,)) + await db.execute("DELETE FROM satspay.charges WHERE id = ?", (charge_id,)) async def check_address_balance(charge_id: str) -> List[Charges]: @@ -124,5 +126,5 @@ async def check_address_balance(charge_id: str) -> List[Charges]: ) if invoice_status.paid: return await update_charge(charge_id=charge_id, balance=charge.amount) - row = await db.fetchone("SELECT * FROM charges WHERE id = ?", (charge_id,)) + row = await db.fetchone("SELECT * FROM satspay.charges WHERE id = ?", (charge_id,)) return Charges.from_row(row) if row else None diff --git a/lnbits/extensions/satspay/migrations.py b/lnbits/extensions/satspay/migrations.py index 79048f9e7..87446c800 100644 --- a/lnbits/extensions/satspay/migrations.py +++ b/lnbits/extensions/satspay/migrations.py @@ -5,9 +5,9 @@ async def m001_initial(db): await db.execute( """ - CREATE TABLE IF NOT EXISTS charges ( + CREATE TABLE satspay.charges ( id TEXT NOT NULL PRIMARY KEY, - user TEXT, + "user" TEXT, description TEXT, onchainwallet TEXT, onchainaddress TEXT, @@ -20,7 +20,9 @@ async def m001_initial(db): time INTEGER, amount INTEGER, balance INTEGER DEFAULT 0, - timestamp TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')) + timestamp TIMESTAMP NOT NULL DEFAULT """ + + db.timestamp_now + + """ ); """ ) diff --git a/lnbits/extensions/splitpayments/crud.py b/lnbits/extensions/splitpayments/crud.py index 82a59c34d..105499303 100644 --- a/lnbits/extensions/splitpayments/crud.py +++ b/lnbits/extensions/splitpayments/crud.py @@ -5,17 +5,17 @@ from .models import Target async def get_targets(source_wallet: str) -> List[Target]: - rows = await db.fetchall("SELECT * FROM targets WHERE source = ?", (source_wallet,)) + rows = await db.fetchall("SELECT * FROM splitpayments.targets WHERE source = ?", (source_wallet,)) return [Target(**dict(row)) for row in rows] async def set_targets(source_wallet: str, targets: List[Target]): async with db.connect() as conn: - await conn.execute("DELETE FROM targets WHERE source = ?", (source_wallet,)) + await conn.execute("DELETE FROM splitpayments.targets WHERE source = ?", (source_wallet,)) for target in targets: await conn.execute( """ - INSERT INTO targets + INSERT INTO splitpayments.targets (source, wallet, percent, alias) VALUES (?, ?, ?, ?) """, diff --git a/lnbits/extensions/splitpayments/migrations.py b/lnbits/extensions/splitpayments/migrations.py index c3cc46d70..735afc6c3 100644 --- a/lnbits/extensions/splitpayments/migrations.py +++ b/lnbits/extensions/splitpayments/migrations.py @@ -4,7 +4,7 @@ async def m001_initial(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS targets ( + CREATE TABLE splitpayments.targets ( wallet TEXT NOT NULL, source TEXT NOT NULL, percent INTEGER NOT NULL CHECK (percent >= 0 AND percent <= 100), diff --git a/lnbits/extensions/splitpayments/tasks.py b/lnbits/extensions/splitpayments/tasks.py index 50057d9ff..512150766 100644 --- a/lnbits/extensions/splitpayments/tasks.py +++ b/lnbits/extensions/splitpayments/tasks.py @@ -47,7 +47,7 @@ async def on_invoice_paid(payment: Payment) -> None: # and reduce it by the amount we're going to send to the producer await core_db.execute( """ - UPDATE apipayments + UPDATE splitpayments.apipayments SET extra = ?, amount = ? WHERE hash = ? AND checking_id NOT LIKE 'internal_%' diff --git a/lnbits/extensions/subdomains/crud.py b/lnbits/extensions/subdomains/crud.py index 6e2c2e7e4..0f98d8bc5 100644 --- a/lnbits/extensions/subdomains/crud.py +++ b/lnbits/extensions/subdomains/crud.py @@ -19,7 +19,7 @@ async def create_subdomain( ) -> Subdomains: await db.execute( """ - INSERT INTO subdomain (id, domain, email, subdomain, ip, wallet, sats, duration, paid, record_type) + INSERT INTO subdomains.subdomain (id, domain, email, subdomain, ip, wallet, sats, duration, paid, record_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( @@ -43,13 +43,13 @@ async def create_subdomain( async def set_subdomain_paid(payment_hash: str) -> Subdomains: row = await db.fetchone( - "SELECT s.*, d.domain as domain_name FROM subdomain s INNER JOIN domain d ON (s.domain = d.id) WHERE s.id = ?", + "SELECT s.*, d.domain as domain_name FROM subdomains.subdomain s INNER JOIN domain d ON (s.domain = d.id) WHERE s.id = ?", (payment_hash,), ) if row[8] == False: await db.execute( """ - UPDATE subdomain + UPDATE subdomains.subdomain SET paid = true WHERE id = ? """, @@ -62,7 +62,7 @@ async def set_subdomain_paid(payment_hash: str) -> Subdomains: amount = domaindata.amountmade + row[8] await db.execute( """ - UPDATE domain + UPDATE subdomains.domain SET amountmade = ? WHERE id = ? """, @@ -76,7 +76,7 @@ async def set_subdomain_paid(payment_hash: str) -> Subdomains: async def get_subdomain(subdomain_id: str) -> Optional[Subdomains]: row = await db.fetchone( - "SELECT s.*, d.domain as domain_name FROM subdomain s INNER JOIN domain d ON (s.domain = d.id) WHERE s.id = ?", + "SELECT s.*, d.domain as domain_name FROM subdomains.subdomain s INNER JOIN domain d ON (s.domain = d.id) WHERE s.id = ?", (subdomain_id,), ) return Subdomains(**row) if row else None @@ -84,7 +84,7 @@ async def get_subdomain(subdomain_id: str) -> Optional[Subdomains]: async def get_subdomainBySubdomain(subdomain: str) -> Optional[Subdomains]: row = await db.fetchone( - "SELECT s.*, d.domain as domain_name FROM subdomain s INNER JOIN domain d ON (s.domain = d.id) WHERE s.subdomain = ?", + "SELECT s.*, d.domain as domain_name FROM subdomains.subdomain s INNER JOIN domain d ON (s.domain = d.id) WHERE s.subdomain = ?", (subdomain,), ) print(row) @@ -97,7 +97,7 @@ async def get_subdomains(wallet_ids: Union[str, List[str]]) -> List[Subdomains]: q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( - f"SELECT s.*, d.domain as domain_name FROM subdomain s INNER JOIN domain d ON (s.domain = d.id) WHERE s.wallet IN ({q})", + f"SELECT s.*, d.domain as domain_name FROM subdomains.subdomain s INNER JOIN domain d ON (s.domain = d.id) WHERE s.wallet IN ({q})", (*wallet_ids,), ) @@ -105,7 +105,7 @@ async def get_subdomains(wallet_ids: Union[str, List[str]]) -> List[Subdomains]: async def delete_subdomain(subdomain_id: str) -> None: - await db.execute("DELETE FROM subdomain WHERE id = ?", (subdomain_id,)) + await db.execute("DELETE FROM subdomains.subdomain WHERE id = ?", (subdomain_id,)) # Domains @@ -125,7 +125,7 @@ async def create_domain( domain_id = urlsafe_short_hash() await db.execute( """ - INSERT INTO domain (id, wallet, domain, webhook, cf_token, cf_zone_id, description, cost, amountmade, allowed_record_types) + INSERT INTO subdomains.domain (id, wallet, domain, webhook, cf_token, cf_zone_id, description, cost, amountmade, allowed_record_types) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( @@ -150,15 +150,15 @@ async def create_domain( async def update_domain(domain_id: str, **kwargs) -> Domains: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) await db.execute( - f"UPDATE domain SET {q} WHERE id = ?", (*kwargs.values(), domain_id) + f"UPDATE subdomains.domain SET {q} WHERE id = ?", (*kwargs.values(), domain_id) ) - row = await db.fetchone("SELECT * FROM domain WHERE id = ?", (domain_id,)) + row = await db.fetchone("SELECT * FROM subdomains.domain WHERE id = ?", (domain_id,)) assert row, "Newly updated domain couldn't be retrieved" return Domains(**row) async def get_domain(domain_id: str) -> Optional[Domains]: - row = await db.fetchone("SELECT * FROM domain WHERE id = ?", (domain_id,)) + row = await db.fetchone("SELECT * FROM subdomains.domain WHERE id = ?", (domain_id,)) return Domains(**row) if row else None @@ -168,11 +168,11 @@ async def get_domains(wallet_ids: Union[str, List[str]]) -> List[Domains]: q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( - f"SELECT * FROM domain WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM subdomains.domain WHERE wallet IN ({q})", (*wallet_ids,) ) return [Domains(**row) for row in rows] async def delete_domain(domain_id: str) -> None: - await db.execute("DELETE FROM domain WHERE id = ?", (domain_id,)) + await db.execute("DELETE FROM subdomains.domain WHERE id = ?", (domain_id,)) diff --git a/lnbits/extensions/subdomains/migrations.py b/lnbits/extensions/subdomains/migrations.py index 4864377d4..374741529 100644 --- a/lnbits/extensions/subdomains/migrations.py +++ b/lnbits/extensions/subdomains/migrations.py @@ -2,7 +2,7 @@ async def m001_initial(db): await db.execute( """ - CREATE TABLE IF NOT EXISTS domain ( + CREATE TABLE subdomains.domain ( id TEXT PRIMARY KEY, wallet TEXT NOT NULL, domain TEXT NOT NULL, @@ -13,14 +13,14 @@ async def m001_initial(db): cost INTEGER NOT NULL, amountmade INTEGER NOT NULL, allowed_record_types TEXT NOT NULL, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')) + time TIMESTAMP NOT NULL DEFAULT """ + db.timestamp_now + """ ); """ ) await db.execute( """ - CREATE TABLE IF NOT EXISTS subdomain ( + CREATE TABLE subdomains.subdomain ( id TEXT PRIMARY KEY, domain TEXT NOT NULL, email TEXT NOT NULL, @@ -31,7 +31,7 @@ async def m001_initial(db): duration INTEGER NOT NULL, paid BOOLEAN NOT NULL, record_type TEXT NOT NULL, - time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now')) + time TIMESTAMP NOT NULL DEFAULT """ + db.timestamp_now + """ ); """ ) diff --git a/lnbits/extensions/tpos/crud.py b/lnbits/extensions/tpos/crud.py index afd4f9732..99dab6627 100644 --- a/lnbits/extensions/tpos/crud.py +++ b/lnbits/extensions/tpos/crud.py @@ -10,7 +10,7 @@ async def create_tpos(*, wallet_id: str, name: str, currency: str) -> TPoS: tpos_id = urlsafe_short_hash() await db.execute( """ - INSERT INTO tposs (id, wallet, name, currency) + INSERT INTO tpos.tposs (id, wallet, name, currency) VALUES (?, ?, ?, ?) """, (tpos_id, wallet_id, name, currency), @@ -22,7 +22,7 @@ async def create_tpos(*, wallet_id: str, name: str, currency: str) -> TPoS: async def get_tpos(tpos_id: str) -> Optional[TPoS]: - row = await db.fetchone("SELECT * FROM tposs WHERE id = ?", (tpos_id,)) + row = await db.fetchone("SELECT * FROM tpos.tposs WHERE id = ?", (tpos_id,)) return TPoS.from_row(row) if row else None @@ -32,11 +32,11 @@ async def get_tposs(wallet_ids: Union[str, List[str]]) -> List[TPoS]: q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( - f"SELECT * FROM tposs WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM tpos.tposs WHERE wallet IN ({q})", (*wallet_ids,) ) return [TPoS.from_row(row) for row in rows] async def delete_tpos(tpos_id: str) -> None: - await db.execute("DELETE FROM tposs WHERE id = ?", (tpos_id,)) + await db.execute("DELETE FROM tpos.tposs WHERE id = ?", (tpos_id,)) diff --git a/lnbits/extensions/tpos/migrations.py b/lnbits/extensions/tpos/migrations.py index 243ebe0b3..7a7fff0d5 100644 --- a/lnbits/extensions/tpos/migrations.py +++ b/lnbits/extensions/tpos/migrations.py @@ -4,7 +4,7 @@ async def m001_initial(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS tposs ( + CREATE TABLE tpos.tposs ( id TEXT PRIMARY KEY, wallet TEXT NOT NULL, name TEXT NOT NULL, diff --git a/lnbits/extensions/usermanager/crud.py b/lnbits/extensions/usermanager/crud.py index dbee287c9..24899e322 100644 --- a/lnbits/extensions/usermanager/crud.py +++ b/lnbits/extensions/usermanager/crud.py @@ -31,7 +31,7 @@ async def create_usermanager_user( await db.execute( """ - INSERT INTO users (id, name, admin, email, password) + INSERT INTO usermanager.users (id, name, admin, email, password) VALUES (?, ?, ?, ?, ?) """, (user.id, user_name, admin_id, email, password), @@ -39,7 +39,7 @@ async def create_usermanager_user( await db.execute( """ - INSERT INTO wallets (id, admin, name, user, adminkey, inkey) + INSERT INTO usermanager.wallets (id, admin, name, "user", adminkey, inkey) VALUES (?, ?, ?, ?, ?, ?) """, (wallet.id, admin_id, wallet_name, user.id, wallet.adminkey, wallet.inkey), @@ -51,12 +51,12 @@ async def create_usermanager_user( async def get_usermanager_user(user_id: str) -> Optional[Users]: - row = await db.fetchone("SELECT * FROM users WHERE id = ?", (user_id,)) + row = await db.fetchone("SELECT * FROM usermanager.users WHERE id = ?", (user_id,)) return Users(**row) if row else None async def get_usermanager_users(user_id: str) -> List[Users]: - rows = await db.fetchall("SELECT * FROM users WHERE admin = ?", (user_id,)) + rows = await db.fetchall("SELECT * FROM usermanager.users WHERE admin = ?", (user_id,)) return [Users(**row) for row in rows] @@ -65,8 +65,8 @@ async def delete_usermanager_user(user_id: str) -> None: for wallet in wallets: await delete_wallet(user_id=user_id, wallet_id=wallet.id) - await db.execute("DELETE FROM users WHERE id = ?", (user_id,)) - await db.execute("DELETE FROM wallets WHERE user = ?", (user_id,)) + await db.execute("DELETE FROM usermanager.users WHERE id = ?", (user_id,)) + await db.execute("""DELETE FROM usermanager.wallets WHERE "user" = ?""", (user_id,)) ### Wallets @@ -78,7 +78,7 @@ async def create_usermanager_wallet( wallet = await create_wallet(user_id=user_id, wallet_name=wallet_name) await db.execute( """ - INSERT INTO wallets (id, admin, name, user, adminkey, inkey) + INSERT INTO usermanager.wallets (id, admin, name, "user", adminkey, inkey) VALUES (?, ?, ?, ?, ?, ?) """, (wallet.id, admin_id, wallet_name, user_id, wallet.adminkey, wallet.inkey), @@ -89,17 +89,17 @@ async def create_usermanager_wallet( async def get_usermanager_wallet(wallet_id: str) -> Optional[Wallets]: - row = await db.fetchone("SELECT * FROM wallets WHERE id = ?", (wallet_id,)) + row = await db.fetchone("SELECT * FROM usermanager.wallets WHERE id = ?", (wallet_id,)) return Wallets(**row) if row else None async def get_usermanager_wallets(admin_id: str) -> Optional[Wallets]: - rows = await db.fetchall("SELECT * FROM wallets WHERE admin = ?", (admin_id,)) + rows = await db.fetchall("SELECT * FROM usermanager.wallets WHERE admin = ?", (admin_id,)) return [Wallets(**row) for row in rows] async def get_usermanager_users_wallets(user_id: str) -> Optional[Wallets]: - rows = await db.fetchall("SELECT * FROM wallets WHERE user = ?", (user_id,)) + rows = await db.fetchall("""SELECT * FROM usermanager.wallets WHERE "user" = ?""", (user_id,)) return [Wallets(**row) for row in rows] @@ -111,4 +111,4 @@ async def get_usermanager_wallet_transactions(wallet_id: str) -> Optional[Paymen async def delete_usermanager_wallet(wallet_id: str, user_id: str) -> None: await delete_wallet(user_id=user_id, wallet_id=wallet_id) - await db.execute("DELETE FROM wallets WHERE id = ?", (wallet_id,)) + await db.execute("DELETE FROM usermanager.wallets WHERE id = ?", (wallet_id,)) diff --git a/lnbits/extensions/usermanager/migrations.py b/lnbits/extensions/usermanager/migrations.py index 9b60fa669..62a215752 100644 --- a/lnbits/extensions/usermanager/migrations.py +++ b/lnbits/extensions/usermanager/migrations.py @@ -4,7 +4,7 @@ async def m001_initial(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS users ( + CREATE TABLE usermanager.users ( id TEXT PRIMARY KEY, name TEXT NOT NULL, admin TEXT NOT NULL, @@ -19,11 +19,11 @@ async def m001_initial(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS wallets ( + CREATE TABLE usermanager.wallets ( id TEXT PRIMARY KEY, admin TEXT NOT NULL, name TEXT NOT NULL, - user TEXT NOT NULL, + "user" TEXT NOT NULL, adminkey TEXT NOT NULL, inkey TEXT NOT NULL ); diff --git a/lnbits/extensions/watchonly/crud.py b/lnbits/extensions/watchonly/crud.py index 24f6896e3..1531b174a 100644 --- a/lnbits/extensions/watchonly/crud.py +++ b/lnbits/extensions/watchonly/crud.py @@ -1,16 +1,13 @@ -from typing import List, Optional, Union +from typing import List, Optional -# from lnbits.db import open_ext_db from . import db from .models import Wallets, Addresses, Mempool from lnbits.helpers import urlsafe_short_hash -from embit.descriptor import Descriptor, Key -from embit.descriptor.arguments import AllowedDerivation -from embit.networks import NETWORKS - -import httpx +from embit.descriptor import Descriptor, Key # type: ignore +from embit.descriptor.arguments import AllowedDerivation # type: ignore +from embit.networks import NETWORKS # type: ignore ##########################WALLETS#################### @@ -83,9 +80,9 @@ async def create_watch_wallet(*, user: str, masterpub: str, title: str) -> Walle wallet_id = urlsafe_short_hash() await db.execute( """ - INSERT INTO wallets ( + INSERT INTO watchonly.wallets ( id, - user, + "user", masterpub, title, address_no, @@ -101,13 +98,17 @@ async def create_watch_wallet(*, user: str, masterpub: str, title: str) -> Walle return await get_watch_wallet(wallet_id) -async def get_watch_wallet(wallet_id: str) -> Wallets: - row = await db.fetchone("SELECT * FROM wallets WHERE id = ?", (wallet_id,)) +async def get_watch_wallet(wallet_id: str) -> Optional[Wallets]: + row = await db.fetchone( + "SELECT * FROM watchonly.wallets WHERE id = ?", (wallet_id,) + ) return Wallets.from_row(row) if row else None async def get_watch_wallets(user: str) -> List[Wallets]: - rows = await db.fetchall("SELECT * FROM wallets WHERE user = ?", (user,)) + rows = await db.fetchall( + """SELECT * FROM watchonly.wallets WHERE "user" = ?""", (user,) + ) return [Wallets(**row) for row in rows] @@ -115,28 +116,31 @@ async def update_watch_wallet(wallet_id: str, **kwargs) -> Optional[Wallets]: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) await db.execute( - f"UPDATE wallets SET {q} WHERE id = ?", (*kwargs.values(), wallet_id) + f"UPDATE watchonly.wallets SET {q} WHERE id = ?", (*kwargs.values(), wallet_id) + ) + row = await db.fetchone( + "SELECT * FROM watchonly.wallets WHERE id = ?", (wallet_id,) ) - row = await db.fetchone("SELECT * FROM wallets WHERE id = ?", (wallet_id,)) return Wallets.from_row(row) if row else None async def delete_watch_wallet(wallet_id: str) -> None: - await db.execute("DELETE FROM wallets WHERE id = ?", (wallet_id,)) + await db.execute("DELETE FROM watchonly.wallets WHERE id = ?", (wallet_id,)) ########################ADDRESSES####################### async def get_derive_address(wallet_id: str, num: int): - wallet = await get_watch_wallet(wallet_id) key = wallet[2] desc, network = parse_key(key) return desc.derive(num).address(network=network) -async def get_fresh_address(wallet_id: str) -> Addresses: +async def get_fresh_address(wallet_id: str) -> Optional[Addresses]: wallet = await get_watch_wallet(wallet_id) + if not wallet: + return None address = await get_derive_address(wallet_id, wallet[4] + 1) @@ -144,7 +148,7 @@ async def get_fresh_address(wallet_id: str) -> Addresses: masterpub_id = urlsafe_short_hash() await db.execute( """ - INSERT INTO addresses ( + INSERT INTO watchonly.addresses ( id, address, wallet, @@ -158,42 +162,52 @@ async def get_fresh_address(wallet_id: str) -> Addresses: return await get_address(address) -async def get_address(address: str) -> Addresses: - row = await db.fetchone("SELECT * FROM addresses WHERE address = ?", (address,)) +async def get_address(address: str) -> Optional[Addresses]: + row = await db.fetchone( + "SELECT * FROM watchonly.addresses WHERE address = ?", (address,) + ) return Addresses.from_row(row) if row else None async def get_addresses(wallet_id: str) -> List[Addresses]: - rows = await db.fetchall("SELECT * FROM addresses WHERE wallet = ?", (wallet_id,)) + rows = await db.fetchall( + "SELECT * FROM watchonly.addresses WHERE wallet = ?", (wallet_id,) + ) return [Addresses(**row) for row in rows] ######################MEMPOOL####################### -async def create_mempool(user: str) -> Mempool: +async def create_mempool(user: str) -> Optional[Mempool]: await db.execute( """ - INSERT INTO mempool ( - user, - endpoint - ) + INSERT INTO watchonly.mempool ("user",endpoint) VALUES (?, ?) """, (user, "https://mempool.space"), ) - row = await db.fetchone("SELECT * FROM mempool WHERE user = ?", (user,)) + row = await db.fetchone( + """SELECT * FROM watchonly.mempool WHERE "user" = ?""", (user,) + ) return Mempool.from_row(row) if row else None async def update_mempool(user: str, **kwargs) -> Optional[Mempool]: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) - await db.execute(f"UPDATE mempool SET {q} WHERE user = ?", (*kwargs.values(), user)) - row = await db.fetchone("SELECT * FROM mempool WHERE user = ?", (user,)) + await db.execute( + f"""UPDATE watchonly.mempool SET {q} WHERE "user" = ?""", + (*kwargs.values(), user), + ) + row = await db.fetchone( + """SELECT * FROM watchonly.mempool WHERE "user" = ?""", (user,) + ) return Mempool.from_row(row) if row else None async def get_mempool(user: str) -> Mempool: - row = await db.fetchone("SELECT * FROM mempool WHERE user = ?", (user,)) + row = await db.fetchone( + """SELECT * FROM watchonly.mempool WHERE "user" = ?""", (user,) + ) return Mempool.from_row(row) if row else None diff --git a/lnbits/extensions/watchonly/migrations.py b/lnbits/extensions/watchonly/migrations.py index 0057f3e9d..05c229b53 100644 --- a/lnbits/extensions/watchonly/migrations.py +++ b/lnbits/extensions/watchonly/migrations.py @@ -4,9 +4,9 @@ async def m001_initial(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS wallets ( + CREATE TABLE watchonly.wallets ( id TEXT NOT NULL PRIMARY KEY, - user TEXT, + "user" TEXT, masterpub TEXT NOT NULL, title TEXT NOT NULL, address_no INTEGER NOT NULL DEFAULT 0, @@ -17,7 +17,7 @@ async def m001_initial(db): await db.execute( """ - CREATE TABLE IF NOT EXISTS addresses ( + CREATE TABLE watchonly.addresses ( id TEXT NOT NULL PRIMARY KEY, address TEXT NOT NULL, wallet TEXT NOT NULL, @@ -28,8 +28,8 @@ async def m001_initial(db): await db.execute( """ - CREATE TABLE IF NOT EXISTS mempool ( - user TEXT NOT NULL, + CREATE TABLE watchonly.mempool ( + "user" TEXT NOT NULL, endpoint TEXT NOT NULL ); """ diff --git a/lnbits/extensions/withdraw/crud.py b/lnbits/extensions/withdraw/crud.py index dcc72af68..f161df741 100644 --- a/lnbits/extensions/withdraw/crud.py +++ b/lnbits/extensions/withdraw/crud.py @@ -20,7 +20,7 @@ async def create_withdraw_link( link_id = urlsafe_short_hash() await db.execute( """ - INSERT INTO withdraw_link ( + INSERT INTO withdraw.withdraw_link ( id, wallet, title, @@ -57,7 +57,7 @@ async def create_withdraw_link( async def get_withdraw_link(link_id: str, num=0) -> Optional[WithdrawLink]: - row = await db.fetchone("SELECT * FROM withdraw_link WHERE id = ?", (link_id,)) + row = await db.fetchone("SELECT * FROM withdraw.withdraw_link WHERE id = ?", (link_id,)) if not row: return None @@ -70,7 +70,7 @@ async def get_withdraw_link(link_id: str, num=0) -> Optional[WithdrawLink]: async def get_withdraw_link_by_hash(unique_hash: str, num=0) -> Optional[WithdrawLink]: row = await db.fetchone( - "SELECT * FROM withdraw_link WHERE unique_hash = ?", (unique_hash,) + "SELECT * FROM withdraw.withdraw_link WHERE unique_hash = ?", (unique_hash,) ) if not row: return None @@ -88,7 +88,7 @@ async def get_withdraw_links(wallet_ids: Union[str, List[str]]) -> List[Withdraw q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( - f"SELECT * FROM withdraw_link WHERE wallet IN ({q})", (*wallet_ids,) + f"SELECT * FROM withdraw.withdraw_link WHERE wallet IN ({q})", (*wallet_ids,) ) return [WithdrawLink.from_row(row) for row in rows] @@ -97,14 +97,14 @@ async def get_withdraw_links(wallet_ids: Union[str, List[str]]) -> List[Withdraw async def update_withdraw_link(link_id: str, **kwargs) -> Optional[WithdrawLink]: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) await db.execute( - f"UPDATE withdraw_link SET {q} WHERE id = ?", (*kwargs.values(), link_id) + f"UPDATE withdraw.withdraw_link SET {q} WHERE id = ?", (*kwargs.values(), link_id) ) - row = await db.fetchone("SELECT * FROM withdraw_link WHERE id = ?", (link_id,)) + row = await db.fetchone("SELECT * FROM withdraw.withdraw_link WHERE id = ?", (link_id,)) return WithdrawLink.from_row(row) if row else None async def delete_withdraw_link(link_id: str) -> None: - await db.execute("DELETE FROM withdraw_link WHERE id = ?", (link_id,)) + await db.execute("DELETE FROM withdraw.withdraw_link WHERE id = ?", (link_id,)) def chunks(lst, n): @@ -118,7 +118,7 @@ async def create_hash_check( ) -> HashCheck: await db.execute( """ - INSERT INTO hash_check ( + INSERT INTO withdraw.hash_check ( id, lnurl_id ) @@ -134,9 +134,9 @@ async def create_hash_check( async def get_hash_check(the_hash: str, lnurl_id: str) -> Optional[HashCheck]: - rowid = await db.fetchone("SELECT * FROM hash_check WHERE id = ?", (the_hash,)) + rowid = await db.fetchone("SELECT * FROM withdraw.hash_check WHERE id = ?", (the_hash,)) rowlnurl = await db.fetchone( - "SELECT * FROM hash_check WHERE lnurl_id = ?", (lnurl_id,) + "SELECT * FROM withdraw.hash_check WHERE lnurl_id = ?", (lnurl_id,) ) if not rowlnurl: await create_hash_check(the_hash, lnurl_id) diff --git a/lnbits/extensions/withdraw/migrations.py b/lnbits/extensions/withdraw/migrations.py index 197a629c2..beff4c994 100644 --- a/lnbits/extensions/withdraw/migrations.py +++ b/lnbits/extensions/withdraw/migrations.py @@ -4,7 +4,7 @@ async def m001_initial(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS withdraw_links ( + CREATE TABLE withdraw.withdraw_links ( id TEXT PRIMARY KEY, wallet TEXT, title TEXT, @@ -29,7 +29,7 @@ async def m002_change_withdraw_table(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS withdraw_link ( + CREATE TABLE withdraw.withdraw_link ( id TEXT PRIMARY KEY, wallet TEXT, title TEXT, @@ -46,12 +46,8 @@ async def m002_change_withdraw_table(db): ); """ ) - await db.execute("CREATE INDEX IF NOT EXISTS wallet_idx ON withdraw_link (wallet)") - await db.execute( - "CREATE UNIQUE INDEX IF NOT EXISTS unique_hash_idx ON withdraw_link (unique_hash)" - ) - for row in [list(row) for row in await db.fetchall("SELECT * FROM withdraw_links")]: + for row in [list(row) for row in await db.fetchall("SELECT * FROM withdraw.withdraw_links")]: usescsv = "" for i in range(row[5]): @@ -62,7 +58,7 @@ async def m002_change_withdraw_table(db): usescsv = usescsv[1:] await db.execute( """ - INSERT INTO withdraw_link ( + INSERT INTO withdraw.withdraw_link ( id, wallet, title, @@ -95,7 +91,7 @@ async def m002_change_withdraw_table(db): usescsv, ), ) - await db.execute("DROP TABLE withdraw_links") + await db.execute("DROP TABLE withdraw.withdraw_links") async def m003_make_hash_check(db): @@ -104,7 +100,7 @@ async def m003_make_hash_check(db): """ await db.execute( """ - CREATE TABLE IF NOT EXISTS hash_check ( + CREATE TABLE withdraw.hash_check ( id TEXT PRIMARY KEY, lnurl_id TEXT ); diff --git a/lnbits/settings.py b/lnbits/settings.py index 248d6e9aa..a351b5f11 100644 --- a/lnbits/settings.py +++ b/lnbits/settings.py @@ -23,6 +23,8 @@ LNBITS_PATH = path.dirname(path.realpath(__file__)) LNBITS_DATA_FOLDER = env.str( "LNBITS_DATA_FOLDER", default=path.join(LNBITS_PATH, "data") ) +LNBITS_DATABASE_URL = env.str("LNBITS_DATABASE_URL", default=None) + LNBITS_ALLOWED_USERS: List[str] = env.list( "LNBITS_ALLOWED_USERS", default=[], subcast=str ) diff --git a/lnbits/static/js/base.js b/lnbits/static/js/base.js index 44d02036e..f44be4053 100644 --- a/lnbits/static/js/base.js +++ b/lnbits/static/js/base.js @@ -190,7 +190,7 @@ window.LNbits = { obj.fsat = new Intl.NumberFormat(window.LOCALE).format(obj.sat) obj.isIn = obj.amount > 0 obj.isOut = obj.amount < 0 - obj.isPaid = obj.pending === 0 + obj.isPaid = !obj.pending obj._q = [obj.memo, obj.sat].join(' ').toLowerCase() return obj } diff --git a/lnbits/wallets/lnbits.py b/lnbits/wallets/lnbits.py index aa392ce35..31bc32d39 100644 --- a/lnbits/wallets/lnbits.py +++ b/lnbits/wallets/lnbits.py @@ -28,7 +28,14 @@ class LNbitsWallet(Wallet): async def status(self) -> StatusResponse: async with httpx.AsyncClient() as client: - r = await client.get(url=f"{self.endpoint}/api/v1/wallet", headers=self.key) + try: + r = await client.get( + url=f"{self.endpoint}/api/v1/wallet", headers=self.key + ) + except Exception as exc: + return StatusResponse( + f"Failed to connect to {self.endpoint} due to: {exc}", 0 + ) try: data = r.json()