Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update to lnbits 1.0.0 #8

Merged
merged 6 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
"short_description": "Sell tracks and split revenue (lnurl-pay)",
"tile": "/livestream/static/image/livestream.png",
"contributors": ["fiatjaf", "cryptograffiti"],
"min_lnbits_version": "0.12.5",
"min_lnbits_version": "1.0.0",
"hidden": false
}
232 changes: 91 additions & 141 deletions crud.py
Original file line number Diff line number Diff line change
@@ -1,206 +1,156 @@
from typing import Optional

from lnbits.core.crud import create_account, create_wallet
from lnbits.db import SQLITE, Database
from lnbits.db import Database
from lnbits.helpers import urlsafe_short_hash

from .models import Livestream, Producer, Track
from .models import CreateTrack, Livestream, Producer, Track

db = Database("ext_livestream")


async def create_livestream(*, wallet_id: str) -> int:
returning = "" if db.type == SQLITE else "RETURNING ID"
method = db.execute if db.type == SQLITE else db.fetchone

result = await method(
f"""
INSERT INTO livestream.livestreams (wallet)
VALUES (?)
{returning}
""",
(wallet_id,),
async def create_livestream(wallet_id: str) -> Livestream:
livestream = Livestream(
id=urlsafe_short_hash(),
wallet=wallet_id,
)

if db.type == SQLITE:
return result._result_proxy.lastrowid
else:
return result[0] # type: ignore
await db.insert("livestream.livestreams", livestream)
return livestream


async def get_livestream(ls_id: int) -> Optional[Livestream]:
row = await db.fetchone(
"SELECT * FROM livestream.livestreams WHERE id = ?", (ls_id,)
async def get_livestream(ls_id: str) -> Optional[Livestream]:
return await db.fetchone(
"SELECT * FROM livestream.livestreams WHERE id = :id",
{"id": ls_id},
Livestream,
)
return Livestream(**row) if row else None


async def get_livestream_by_track(track_id: int) -> Optional[Livestream]:
row = await db.fetchone(
"""
SELECT * FROM livestream.tracks WHERE tracks.id = ?
""",
(track_id,),
)
row2 = await db.fetchone(
async def get_livestream_by_track(track_id: str) -> Optional[Livestream]:
return await db.fetchone(
"""
SELECT * FROM livestream.livestreams WHERE livestreams.id = ?
SELECT a.* FROM livestream.tracks as b
LEFT JOIN livestream.livestreams as a ON a.id = b.livestream
WHERE b.id = :id
""",
(row.livestream,),
{"id": track_id},
Livestream,
)
return Livestream(**row2) if row2 else None


async def get_or_create_livestream_by_wallet(wallet: str) -> Livestream:
row = await db.fetchone(
"SELECT * FROM livestream.livestreams WHERE wallet = ?", (wallet,)
livestream = await db.fetchone(
"SELECT * FROM livestream.livestreams WHERE wallet = :wallet",
{"wallet": wallet},
Livestream,
)
if row:
return Livestream(**row)
if livestream:
return livestream

# create on the fly
ls_id = await create_livestream(wallet_id=wallet)
ls = await get_livestream(ls_id)
assert ls, "Newly created livestream should exist."
ls = await create_livestream(wallet)
return ls


async def update_current_track(ls_id: int, track_id: Optional[int]):
async def update_current_track(ls_id: str, track_id: Optional[str]):
await db.execute(
"UPDATE livestream.livestreams SET current_track = ? WHERE id = ?",
(track_id, ls_id),
"UPDATE livestream.livestreams SET current_track = :track_id WHERE id = :id",
{"track_id": track_id, "id": ls_id},
)


async def update_livestream_fee(ls_id: int, fee_pct: int):
async def update_livestream_fee(ls_id: str, fee_pct: int):
await db.execute(
"UPDATE livestream.livestreams SET fee_pct = ? WHERE id = ?", (fee_pct, ls_id)
"UPDATE livestream.livestreams SET fee_pct = :fee_pct WHERE id = :id",
{"fee_pct": fee_pct, "id": ls_id},
)


async def add_track(
livestream: int,
name: str,
download_url: Optional[str],
price_msat: int,
producer: Optional[int],
) -> int:
result = await db.execute(
"""
INSERT INTO livestream.tracks \
(livestream, name, download_url, price_msat, producer)
VALUES (?, ?, ?, ?, ?)
""",
(livestream, name, download_url, price_msat, producer),
)
return result._result_proxy.lastrowid


async def update_track(
livestream: int,
track_id: int,
name: str,
download_url: Optional[str],
price_msat: int,
producer: int,
) -> int:
result = await db.execute(
"""
UPDATE livestream.tracks SET
name = ?,
download_url = ?,
price_msat = ?,
producer = ?
WHERE livestream = ? AND id = ?
""",
(name, download_url, price_msat, producer, livestream, track_id),
async def create_track(
livestream: str,
producer: str,
data: CreateTrack,
) -> Track:
track = Track(
id=urlsafe_short_hash(),
livestream=livestream,
producer=producer,
name=data.name,
download_url=data.download_url,
price_msat=data.price_msat,
)
return result._result_proxy.lastrowid
await db.insert("livestream.tracks", track)
return track


async def get_track(track_id: Optional[int]) -> Optional[Track]:
if not track_id:
return None
async def update_track(track: Track) -> Track:
await db.update("livestream.tracks", track)
return track

row = await db.fetchone(
"""
SELECT id, download_url, price_msat, name, producer
FROM livestream.tracks WHERE id = ?
""",
(track_id,),

async def get_track(track_id: str) -> Optional[Track]:
return await db.fetchone(
"SELECT * FROM livestream.tracks WHERE id = :id",
{"id": track_id},
Track,
)
return Track(**row) if row else None


async def get_tracks(livestream: int) -> list[Track]:
rows = await db.fetchall(
"""
SELECT id, download_url, price_msat, name, producer
FROM livestream.tracks WHERE livestream = ?
""",
(livestream,),
async def get_tracks(livestream: str) -> list[Track]:
return await db.fetchall(
"SELECT * FROM livestream.tracks WHERE livestream = :livestream",
{"livestream": livestream},
Track,
)
return [Track(**row) for row in rows]


async def delete_track_from_livestream(livestream: int, track_id: int):
async def delete_track_from_livestream(livestream: str, track_id: str):
await db.execute(
"""
DELETE FROM livestream.tracks WHERE livestream = ? AND id = ?
DELETE FROM livestream.tracks WHERE livestream = :livestream AND id = :id
""",
(livestream, track_id),
{"livestream": livestream, "id": track_id},
)


async def add_producer(livestream: int, name: str) -> int:
async def create_producer(livestream_id: str, name: str) -> Producer:
name = name.strip()

existing = await db.fetchall(
producer = await db.fetchone(
"""
SELECT id FROM livestream.producers
WHERE livestream = ? AND lower(name) = ?
SELECT * FROM livestream.producers
WHERE livestream = :livestream AND lower(name) = :name
""",
(livestream, name.lower()),
{"livestream": livestream_id, "name": name.lower()},
Producer,
)
if existing:
return existing[0].id
if producer:
return producer

user = await create_account()
wallet = await create_wallet(user_id=user.id, wallet_name="livestream: " + name)

returning = "" if db.type == SQLITE else "RETURNING ID"
method = db.execute if db.type == SQLITE else db.fetchone

result = await method(
f"""
INSERT INTO livestream.producers (livestream, name, "user", wallet)
VALUES (?, ?, ?, ?)
{returning}
""",
(livestream, name, user.id, wallet.id),
producer = Producer(
id=urlsafe_short_hash(),
livestream=livestream_id,
user=user.id,
wallet=wallet.id,
name=name,
)
if db.type == SQLITE:
return result._result_proxy.lastrowid
else:
return result[0] # type: ignore
await db.insert("livestream.producers", producer)
return producer


async def get_producer(producer_id: int) -> Optional[Producer]:
row = await db.fetchone(
"""
SELECT id, "user", wallet, name
FROM livestream.producers WHERE id = ?
""",
(producer_id,),
async def get_producer(producer_id: str) -> Optional[Producer]:
return await db.fetchone(
"SELECT * FROM livestream.producers WHERE id = :id",
{"id": producer_id},
Producer,
)
return Producer(**row) if row else None


async def get_producers(livestream: int) -> list[Producer]:
rows = await db.fetchall(
"""
SELECT id, "user", wallet, name
FROM livestream.producers WHERE livestream = ?
""",
(livestream,),
async def get_producers(livestream: str) -> list[Producer]:
return await db.fetchall(
"SELECT * FROM livestream.producers WHERE livestream = :livestream",
{"livestream": livestream},
Producer,
)
return [Producer(**row) for row in rows]
24 changes: 13 additions & 11 deletions migrations.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
async def m001_initial(db):
from lnbits.db import Connection


async def m001_initial(db: Connection):
"""
Initial livestream tables.
"""
ref = db.references_schema
await db.execute(
f"""
"""
CREATE TABLE livestream.livestreams (
id {db.serial_primary_key},
id TEXT PRIMARY KEY,
wallet TEXT NOT NULL,
fee_pct INTEGER NOT NULL DEFAULT 10,
current_track INTEGER
Expand All @@ -15,10 +17,10 @@ async def m001_initial(db):
)

await db.execute(
f"""
"""
CREATE TABLE livestream.producers (
livestream INTEGER NOT NULL REFERENCES {ref}livestreams (id),
id {db.serial_primary_key},
id TEXT PRIMARY KEY,
livestream TEXT NOT NULL,
"user" TEXT NOT NULL,
wallet TEXT NOT NULL,
name TEXT NOT NULL
Expand All @@ -27,14 +29,14 @@ async def m001_initial(db):
)

await db.execute(
f"""
"""
CREATE TABLE livestream.tracks (
livestream INTEGER NOT NULL REFERENCES {ref}livestreams (id),
id {db.serial_primary_key},
id TEXT PRIMARY KEY,
livestream TEXT NOT NULL,
download_url TEXT,
price_msat INTEGER NOT NULL DEFAULT 0,
name TEXT,
producer INTEGER REFERENCES {ref}producers (id) NOT NULL
producer TEXT NOT NULL
);
"""
)
Loading