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 #36

Merged
merged 5 commits into from
Oct 11, 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 @@ -2,7 +2,7 @@
"name": "Events",
"short_description": "Sell and register event tickets",
"tile": "/events/static/image/events.png",
"min_lnbits_version": "0.12.5",
"min_lnbits_version": "1.0.0",
"contributors": [
{
"name": "talvasconcelos",
Expand Down
180 changes: 53 additions & 127 deletions crud.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from datetime import datetime, timedelta
from typing import List, Optional, Union
from datetime import datetime, timedelta, timezone
from typing import Optional, Union

from lnbits.db import Database
from lnbits.helpers import urlsafe_short_hash
Expand All @@ -12,177 +12,103 @@
async def create_ticket(
payment_hash: str, wallet: str, event: str, name: str, email: str
) -> Ticket:
await db.execute(
"""
INSERT INTO events.ticket (id, wallet, event, name, email, registered, paid)
VALUES (?, ?, ?, ?, ?, ?, ?)
""",
(payment_hash, wallet, event, name, email, False, False),
now = datetime.now(timezone.utc)
ticket = Ticket(
id=payment_hash,
wallet=wallet,
event=event,
name=name,
email=email,
registered=False,
paid=False,
reg_timestamp=now,
time=now,
)

ticket = await get_ticket(payment_hash)
assert ticket, "Newly created ticket couldn't be retrieved"
await db.insert("events.ticket", ticket)
return ticket


async def set_ticket_paid(payment_hash: str) -> Ticket:
ticket = await get_ticket(payment_hash)
assert ticket, "Ticket couldn't be retrieved"
if ticket.paid:
return ticket

await db.execute(
"""
UPDATE events.ticket
SET paid = ?
WHERE id = ?
""",
(True, ticket.id),
)

await update_event_sold(ticket.event)

async def update_ticket(ticket: Ticket) -> Ticket:
await db.update("events.ticket", ticket)
return ticket


async def update_event_sold(event_id: str):
event = await get_event(event_id)
assert event, "Couldn't get event from ticket being paid"
sold = event.sold + 1
amount_tickets = event.amount_tickets - 1
await db.execute(
"""
UPDATE events.events
SET sold = ?, amount_tickets = ?
WHERE id = ?
""",
(sold, amount_tickets, event_id),
)

return


async def get_ticket(payment_hash: str) -> Optional[Ticket]:
row = await db.fetchone("SELECT * FROM events.ticket WHERE id = ?", (payment_hash,))
return Ticket(**row) if row else None
return await db.fetchone(
"SELECT * FROM events.ticket WHERE id = :id",
{"id": payment_hash},
Ticket,
)


async def get_tickets(wallet_ids: Union[str, List[str]]) -> List[Ticket]:
async def get_tickets(wallet_ids: Union[str, list[str]]) -> list[Ticket]:
if isinstance(wallet_ids, str):
wallet_ids = [wallet_ids]

q = ",".join(["?"] * len(wallet_ids))
rows = await db.fetchall(
f"SELECT * FROM events.ticket WHERE wallet IN ({q})", (*wallet_ids,)
q = ",".join([f"'{wallet_id}'" for wallet_id in wallet_ids])
return await db.fetchall(
f"SELECT * FROM events.ticket WHERE wallet IN ({q})",
model=Ticket,
)
return [Ticket(**row) for row in rows]


async def delete_ticket(payment_hash: str) -> None:
await db.execute("DELETE FROM events.ticket WHERE id = ?", (payment_hash,))
await db.execute("DELETE FROM events.ticket WHERE id = :id", {"id": payment_hash})


async def delete_event_tickets(event_id: str) -> None:
await db.execute("DELETE FROM events.ticket WHERE event = ?", (event_id,))
await db.execute(
"DELETE FROM events.ticket WHERE event = :event", {"event": event_id}
)


async def purge_unpaid_tickets(event_id: str) -> None:
time_diff = datetime.now() - timedelta(hours=24)
await db.execute(
f"""
DELETE FROM events.ticket WHERE event = ? AND paid = false
AND time < {db.timestamp_placeholder}
DELETE FROM events.ticket WHERE event = :event AND paid = false
AND time < {db.timestamp_placeholder("time")}
""",
(
event_id,
time_diff.timestamp(),
),
{"time": time_diff.timestamp(), "event": event_id},
)


async def create_event(data: CreateEvent) -> Event:
event_id = urlsafe_short_hash()
await db.execute(
"""
INSERT INTO events.events (
id, wallet, name, info, banner, closing_date, event_start_date,
event_end_date, currency, amount_tickets, price_per_ticket, sold
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
event_id,
data.wallet,
data.name,
data.info,
data.banner,
data.closing_date,
data.event_start_date,
data.event_end_date,
data.currency,
data.amount_tickets,
data.price_per_ticket,
0,
),
)

event = await get_event(event_id)
assert event, "Newly created event couldn't be retrieved"
event = Event(id=event_id, time=datetime.now(timezone.utc), **data.dict())
await db.insert("events.events", event)
return event


async def update_event(event_id: str, **kwargs) -> Event:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
await db.execute(
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"
async def update_event(event: Event) -> Event:
await db.update("events.events", event)
return event


async def get_event(event_id: str) -> Optional[Event]:
row = await db.fetchone("SELECT * FROM events.events WHERE id = ?", (event_id,))
return Event(**row) if row else None
return await db.fetchone(
"SELECT * FROM events.events WHERE id = :id",
{"id": event_id},
Event,
)


async def get_events(wallet_ids: Union[str, List[str]]) -> List[Event]:
async def get_events(wallet_ids: Union[str, list[str]]) -> list[Event]:
if isinstance(wallet_ids, str):
wallet_ids = [wallet_ids]

q = ",".join(["?"] * len(wallet_ids))
rows = await db.fetchall(
f"SELECT * FROM events.events WHERE wallet IN ({q})", (*wallet_ids,)
q = ",".join([f"'{wallet_id}'" for wallet_id in wallet_ids])
return await db.fetchall(
f"SELECT * FROM events.events WHERE wallet IN ({q})",
model=Event,
)

return [Event(**row) for row in rows]


async def delete_event(event_id: str) -> None:
await db.execute("DELETE FROM events.events WHERE id = ?", (event_id,))
await db.execute("DELETE FROM events.events WHERE id = :id", {"id": event_id})


# EVENTTICKETS


async def get_event_tickets(event_id: str, wallet_id: str) -> List[Ticket]:
rows = await db.fetchall(
"SELECT * FROM events.ticket WHERE wallet = ? AND event = ?",
(wallet_id, event_id),
)
return [Ticket(**row) for row in rows]


async def reg_ticket(ticket_id: str) -> List[Ticket]:
await db.execute(
f"""
UPDATE events.ticket SET registered = ?,
reg_timestamp = {db.timestamp_now} 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],)
async def get_event_tickets(event_id: str) -> list[Ticket]:
return await db.fetchall(
"SELECT * FROM events.ticket WHERE event = :event",
{"event": event_id},
Ticket,
)
return [Ticket(**row) for row in rows]
13 changes: 7 additions & 6 deletions models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from datetime import datetime
from typing import Optional

from fastapi import Query
Expand All @@ -8,13 +9,13 @@ class CreateEvent(BaseModel):
wallet: str
name: str
info: str
banner: Optional[str]
closing_date: str
event_start_date: str
event_end_date: str
currency: str = "sat"
amount_tickets: int = Query(..., ge=0)
price_per_ticket: float = Query(..., ge=0)
banner: Optional[str] = None


class CreateTicket(BaseModel):
Expand All @@ -27,15 +28,15 @@ class Event(BaseModel):
wallet: str
name: str
info: str
banner: Optional[str]
closing_date: str
event_start_date: str
event_end_date: str
currency: str
amount_tickets: int
price_per_ticket: float
sold: int
time: int
time: datetime
sold: int = 0
banner: Optional[str] = None


class Ticket(BaseModel):
Expand All @@ -45,6 +46,6 @@ class Ticket(BaseModel):
name: str
email: str
registered: bool
reg_timestamp: Optional[int]
paid: bool
time: int
time: datetime
reg_timestamp: datetime
Loading
Loading