We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Ticket Counter Broken
Test bought 2 tickets. Amount available didn't decrease. Amount Sold didn't increase...
![2022-08-24 22_43_47-LNbits — Mozilla Firefox](https://user-images.githubusercontent.com/9597295/186563808-2e7f4d33-66e0-45f6-8658-37821791ff32.png)



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lnbits/extensions/events/views_api.py`
Content:
```
1 from http import HTTPStatus
2 
3 from fastapi.param_functions import Query
4 from fastapi.params import Depends
5 from starlette.exceptions import HTTPException
6 from starlette.requests import Request
7 
8 from lnbits.core.crud import get_user
9 from lnbits.core.services import create_invoice
10 from lnbits.core.views.api import api_payment
11 from lnbits.decorators import WalletTypeInfo, get_key_type
12 from lnbits.extensions.events.models import CreateEvent, CreateTicket
13 
14 from . import events_ext
15 from .crud import (
16     create_event,
17     create_ticket,
18     delete_event,
19     delete_event_tickets,
20     delete_ticket,
21     get_event,
22     get_event_tickets,
23     get_events,
24     get_ticket,
25     get_tickets,
26     reg_ticket,
27     set_ticket_paid,
28     update_event,
29 )
30 
31 # Events
32 
33 
34 @events_ext.get("/api/v1/events")
35 async def api_events(
36     all_wallets: bool = Query(False), wallet: WalletTypeInfo = Depends(get_key_type)
37 ):
38     wallet_ids = [wallet.wallet.id]
39 
40     if all_wallets:
41         wallet_ids = (await get_user(wallet.wallet.user)).wallet_ids
42 
43     return [event.dict() for event in await get_events(wallet_ids)]
44 
45 
46 @events_ext.post("/api/v1/events")
47 @events_ext.put("/api/v1/events/{event_id}")
48 async def api_event_create(
49     data: CreateEvent, event_id=None, wallet: WalletTypeInfo = Depends(get_key_type)
50 ):
51     if event_id:
52         event = await get_event(event_id)
53         if not event:
54             raise HTTPException(
55                 status_code=HTTPStatus.NOT_FOUND, detail=f"Event does not exist."
56             )
57 
58         if event.wallet != wallet.wallet.id:
59             raise HTTPException(
60                 status_code=HTTPStatus.FORBIDDEN, detail=f"Not your event."
61             )
62         event = await update_event(event_id, **data.dict())
63     else:
64         event = await create_event(data=data)
65 
66     return event.dict()
67 
68 
69 @events_ext.delete("/api/v1/events/{event_id}")
70 async def api_form_delete(event_id, wallet: WalletTypeInfo = Depends(get_key_type)):
71     event = await get_event(event_id)
72     if not event:
73         raise HTTPException(
74             status_code=HTTPStatus.NOT_FOUND, detail=f"Event does not exist."
75         )
76 
77     if event.wallet != wallet.wallet.id:
78         raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail=f"Not your event.")
79 
80     await delete_event(event_id)
81     await delete_event_tickets(event_id)
82     raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
83 
84 
85 #########Tickets##########
86 
87 
88 @events_ext.get("/api/v1/tickets")
89 async def api_tickets(
90     all_wallets: bool = Query(False), wallet: WalletTypeInfo = Depends(get_key_type)
91 ):
92     wallet_ids = [wallet.wallet.id]
93 
94     if all_wallets:
95         wallet_ids = (await get_user(wallet.wallet.user)).wallet_ids
96 
97     return [ticket.dict() for ticket in await get_tickets(wallet_ids)]
98 
99 
100 @events_ext.get("/api/v1/tickets/{event_id}")
101 async def api_ticket_make_ticket(event_id):
102     event = await get_event(event_id)
103     if not event:
104         raise HTTPException(
105             status_code=HTTPStatus.NOT_FOUND, detail=f"Event does not exist."
106         )
107     try:
108         payment_hash, payment_request = await create_invoice(
109             wallet_id=event.wallet,
110             amount=event.price_per_ticket,
111             memo=f"{event_id}",
112             extra={"tag": "events"},
113         )
114     except Exception as e:
115         raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e))
116 
117     return {"payment_hash": payment_hash, "payment_request": payment_request}
118 
119 
120 @events_ext.post("/api/v1/tickets/{event_id}/{payment_hash}")
121 async def api_ticket_send_ticket(event_id, payment_hash, data: CreateTicket):
122     event = await get_event(event_id)
123     try:
124         status = await api_payment(payment_hash)
125         if status["paid"]:
126             ticket = await create_ticket(
127                 payment_hash=payment_hash,
128                 wallet=event.wallet,
129                 event=event_id,
130                 name=data.name,
131                 email=data.email,
132             )
133 
134             if not ticket:
135                 raise HTTPException(
136                     status_code=HTTPStatus.NOT_FOUND,
137                     detail=f"Event could not be fetched.",
138                 )
139 
140             return {"paid": True, "ticket_id": ticket.id}
141     except Exception:
142         raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="Not paid")
143     return {"paid": False}
144 
145 
146 @events_ext.delete("/api/v1/tickets/{ticket_id}")
147 async def api_ticket_delete(ticket_id, wallet: WalletTypeInfo = Depends(get_key_type)):
148     ticket = await get_ticket(ticket_id)
149     if not ticket:
150         raise HTTPException(
151             status_code=HTTPStatus.NOT_FOUND, detail=f"Ticket does not exist."
152         )
153 
154     if ticket.wallet != wallet.wallet.id:
155         raise HTTPException(
156             status_code=HTTPStatus.FORBIDDEN, detail=f"Not your ticket."
157         )
158 
159     await delete_ticket(ticket_id)
160     raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
161 
162 
163 # Event Tickets
164 
165 
166 @events_ext.get("/api/v1/eventtickets/{wallet_id}/{event_id}")
167 async def api_event_tickets(wallet_id, event_id):
168     return [
169         ticket.dict()
170         for ticket in await get_event_tickets(wallet_id=wallet_id, event_id=event_id)
171     ]
172 
173 
174 @events_ext.get("/api/v1/register/ticket/{ticket_id}")
175 async def api_event_register_ticket(ticket_id):
176     ticket = await get_ticket(ticket_id)
177     if not ticket:
178         raise HTTPException(
179             status_code=HTTPStatus.NOT_FOUND, detail="Ticket does not exist."
180         )
181 
182     if not ticket.paid:
183         raise HTTPException(
184             status_code=HTTPStatus.FORBIDDEN, detail="Ticket not paid for."
185         )
186 
187     if ticket.registered == True:
188         raise HTTPException(
189             status_code=HTTPStatus.FORBIDDEN, detail="Ticket already registered"
190         )
191 
192     return [ticket.dict() for ticket in await reg_ticket(ticket_id)]
193
```

Path: `lnbits/extensions/events/crud.py`
Content:
```
1 from typing import List, Optional, Union
2 
3 from lnbits.helpers import urlsafe_short_hash
4 
5 from . import db
6 from .models import CreateEvent, Events, Tickets
7 
8 # TICKETS
9 
10 
11 async def create_ticket(
12     payment_hash: str, wallet: str, event: str, name: str, email: str
13 ) -> Tickets:
14     await db.execute(
15         """
16         INSERT INTO events.ticket (id, wallet, event, name, email, registered, paid)
17         VALUES (?, ?, ?, ?, ?, ?, ?)
18         """,
19         (payment_hash, wallet, event, name, email, False, True),
20     )
21 
22     ticket = await get_ticket(payment_hash)
23     assert ticket, "Newly created ticket couldn't be retrieved"
24     return ticket
25 
26 
27 async def set_ticket_paid(payment_hash: str) -> Tickets:
28     row = await db.fetchone("SELECT * FROM events.ticket WHERE id = ?", (payment_hash,))
29     if row[6] != True:
30         await db.execute(
31             """
32             UPDATE events.ticket
33             SET paid = true
34             WHERE id = ?
35             """,
36             (payment_hash,),
37         )
38 
39         eventdata = await get_event(row[2])
40         assert eventdata, "Couldn't get event from ticket being paid"
41 
42         sold = eventdata.sold + 1
43         amount_tickets = eventdata.amount_tickets - 1
44         await db.execute(
45             """
46             UPDATE events.events
47             SET sold = ?, amount_tickets = ?
48             WHERE id = ?
49             """,
50             (sold, amount_tickets, row[2]),
51         )
52 
53     ticket = await get_ticket(payment_hash)
54     assert ticket, "Newly updated ticket couldn't be retrieved"
55     return ticket
56 
57 
58 async def get_ticket(payment_hash: str) -> Optional[Tickets]:
59     row = await db.fetchone("SELECT * FROM events.ticket WHERE id = ?", (payment_hash,))
60     return Tickets(**row) if row else None
61 
62 
63 async def get_tickets(wallet_ids: Union[str, List[str]]) -> List[Tickets]:
64     if isinstance(wallet_ids, str):
65         wallet_ids = [wallet_ids]
66 
67     q = ",".join(["?"] * len(wallet_ids))
68     rows = await db.fetchall(
69         f"SELECT * FROM events.ticket WHERE wallet IN ({q})", (*wallet_ids,)
70     )
71     return [Tickets(**row) for row in rows]
72 
73 
74 async def delete_ticket(payment_hash: str) -> None:
75     await db.execute("DELETE FROM events.ticket WHERE id = ?", (payment_hash,))
76 
77 
78 async def delete_event_tickets(event_id: str) -> None:
79     await db.execute("DELETE FROM events.ticket WHERE event = ?", (event_id,))
80 
81 
82 # EVENTS
83 
84 
85 async def create_event(data: CreateEvent) -> Events:
86     event_id = urlsafe_short_hash()
87     await db.execute(
88         """
89         INSERT INTO events.events (id, wallet, name, info, closing_date, event_start_date, event_end_date, amount_tickets, price_per_ticket, sold)
90         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
91         """,
92         (
93             event_id,
94             data.wallet,
95             data.name,
96             data.info,
97             data.closing_date,
98             data.event_start_date,
99             data.event_end_date,
100             data.amount_tickets,
101             data.price_per_ticket,
102             0,
103         ),
104     )
105 
106     event = await get_event(event_id)
107     assert event, "Newly created event couldn't be retrieved"
108     return event
109 
110 
111 async def update_event(event_id: str, **kwargs) -> Events:
112     q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
113     await db.execute(
114         f"UPDATE events.events SET {q} WHERE id = ?", (*kwargs.values(), event_id)
115     )
116     event = await get_event(event_id)
117     assert event, "Newly updated event couldn't be retrieved"
118     return event
119 
120 
121 async def get_event(event_id: str) -> Optional[Events]:
122     row = await db.fetchone("SELECT * FROM events.events WHERE id = ?", (event_id,))
123     return Events(**row) if row else None
124 
125 
126 async def get_events(wallet_ids: Union[str, List[str]]) -> List[Events]:
127     if isinstance(wallet_ids, str):
128         wallet_ids = [wallet_ids]
129 
130     q = ",".join(["?"] * len(wallet_ids))
131     rows = await db.fetchall(
132         f"SELECT * FROM events.events WHERE wallet IN ({q})", (*wallet_ids,)
133     )
134 
135     return [Events(**row) for row in rows]
136 
137 
138 async def delete_event(event_id: str) -> None:
139     await db.execute("DELETE FROM events.events WHERE id = ?", (event_id,))
140 
141 
142 # EVENTTICKETS
143 
144 
145 async def get_event_tickets(event_id: str, wallet_id: str) -> List[Tickets]:
146     rows = await db.fetchall(
147         "SELECT * FROM events.ticket WHERE wallet = ? AND event = ?",
148         (wallet_id, event_id),
149     )
150     return [Tickets(**row) for row in rows]
151 
152 
153 async def reg_ticket(ticket_id: str) -> List[Tickets]:
154     await db.execute(
155         "UPDATE events.ticket SET registered = ? WHERE id = ?", (True, ticket_id)
156     )
157     ticket = await db.fetchone("SELECT * FROM events.ticket WHERE id = ?", (ticket_id,))
158     rows = await db.fetchall(
159         "SELECT * FROM events.ticket WHERE event = ?", (ticket[1],)
160     )
161     return [Tickets(**row) for row in rows]
162
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/lnbits/extensions/events/crud.py b/lnbits/extensions/events/crud.py
--- a/lnbits/extensions/events/crud.py
+++ b/lnbits/extensions/events/crud.py
@@ -19,39 +19,22 @@
         (payment_hash, wallet, event, name, email, False, True),
     )
 
-    ticket = await get_ticket(payment_hash)
-    assert ticket, "Newly created ticket couldn't be retrieved"
-    return ticket
-
-
-async def set_ticket_paid(payment_hash: str) -> Tickets:
-    row = await db.fetchone("SELECT * FROM events.ticket WHERE id = ?", (payment_hash,))
-    if row[6] != True:
-        await db.execute(
-            """
-            UPDATE events.ticket
-            SET paid = true
-            WHERE id = ?
-            """,
-            (payment_hash,),
-        )
-
-        eventdata = await get_event(row[2])
-        assert eventdata, "Couldn't get event from ticket being paid"
-
-        sold = eventdata.sold + 1
-        amount_tickets = eventdata.amount_tickets - 1
-        await db.execute(
-            """
-            UPDATE events.events
-            SET sold = ?, amount_tickets = ?
-            WHERE id = ?
-            """,
-            (sold, amount_tickets, row[2]),
-        )
+    # UPDATE EVENT DATA ON SOLD TICKET
+    eventdata = await get_event(event)
+    assert eventdata, "Couldn't get event from ticket being paid"
+    sold = eventdata.sold + 1
+    amount_tickets = eventdata.amount_tickets - 1
+    await db.execute(
+        """
+        UPDATE events.events
+        SET sold = ?, amount_tickets = ?
+        WHERE id = ?
+        """,
+        (sold, amount_tickets, event),
+    )
 
     ticket = await get_ticket(payment_hash)
-    assert ticket, "Newly updated ticket couldn't be retrieved"
+    assert ticket, "Newly created ticket couldn't be retrieved"
     return ticket
 
 
diff --git a/lnbits/extensions/events/views_api.py b/lnbits/extensions/events/views_api.py
--- a/lnbits/extensions/events/views_api.py
+++ b/lnbits/extensions/events/views_api.py
@@ -24,7 +24,6 @@
     get_ticket,
     get_tickets,
     reg_ticket,
-    set_ticket_paid,
     update_event,
 )

{"golden_diff": "diff --git a/lnbits/extensions/events/crud.py b/lnbits/extensions/events/crud.py\n--- a/lnbits/extensions/events/crud.py\n+++ b/lnbits/extensions/events/crud.py\n@@ -19,39 +19,22 @@\n         (payment_hash, wallet, event, name, email, False, True),\n     )\n \n-    ticket = await get_ticket(payment_hash)\n-    assert ticket, \"Newly created ticket couldn't be retrieved\"\n-    return ticket\n-\n-\n-async def set_ticket_paid(payment_hash: str) -> Tickets:\n-    row = await db.fetchone(\"SELECT * FROM events.ticket WHERE id = ?\", (payment_hash,))\n-    if row[6] != True:\n-        await db.execute(\n-            \"\"\"\n-            UPDATE events.ticket\n-            SET paid = true\n-            WHERE id = ?\n-            \"\"\",\n-            (payment_hash,),\n-        )\n-\n-        eventdata = await get_event(row[2])\n-        assert eventdata, \"Couldn't get event from ticket being paid\"\n-\n-        sold = eventdata.sold + 1\n-        amount_tickets = eventdata.amount_tickets - 1\n-        await db.execute(\n-            \"\"\"\n-            UPDATE events.events\n-            SET sold = ?, amount_tickets = ?\n-            WHERE id = ?\n-            \"\"\",\n-            (sold, amount_tickets, row[2]),\n-        )\n+    # UPDATE EVENT DATA ON SOLD TICKET\n+    eventdata = await get_event(event)\n+    assert eventdata, \"Couldn't get event from ticket being paid\"\n+    sold = eventdata.sold + 1\n+    amount_tickets = eventdata.amount_tickets - 1\n+    await db.execute(\n+        \"\"\"\n+        UPDATE events.events\n+        SET sold = ?, amount_tickets = ?\n+        WHERE id = ?\n+        \"\"\",\n+        (sold, amount_tickets, event),\n+    )\n \n     ticket = await get_ticket(payment_hash)\n-    assert ticket, \"Newly updated ticket couldn't be retrieved\"\n+    assert ticket, \"Newly created ticket couldn't be retrieved\"\n     return ticket\n \n \ndiff --git a/lnbits/extensions/events/views_api.py b/lnbits/extensions/events/views_api.py\n--- a/lnbits/extensions/events/views_api.py\n+++ b/lnbits/extensions/events/views_api.py\n@@ -24,7 +24,6 @@\n     get_ticket,\n     get_tickets,\n     reg_ticket,\n-    set_ticket_paid,\n     update_event,\n )\n", "issue": "Ticket Counter Broken\nTest bought 2 tickets. Amount available didn't decrease. Amount Sold didn't increase...\r\n![2022-08-24 22_43_47-LNbits \u2014 Mozilla Firefox](https://user-images.githubusercontent.com/9597295/186563808-2e7f4d33-66e0-45f6-8658-37821791ff32.png)\r\n\r\n\n", "before_files": [{"content": "from http import HTTPStatus\n\nfrom fastapi.param_functions import Query\nfrom fastapi.params import Depends\nfrom starlette.exceptions import HTTPException\nfrom starlette.requests import Request\n\nfrom lnbits.core.crud import get_user\nfrom lnbits.core.services import create_invoice\nfrom lnbits.core.views.api import api_payment\nfrom lnbits.decorators import WalletTypeInfo, get_key_type\nfrom lnbits.extensions.events.models import CreateEvent, CreateTicket\n\nfrom . import events_ext\nfrom .crud import (\n    create_event,\n    create_ticket,\n    delete_event,\n    delete_event_tickets,\n    delete_ticket,\n    get_event,\n    get_event_tickets,\n    get_events,\n    get_ticket,\n    get_tickets,\n    reg_ticket,\n    set_ticket_paid,\n    update_event,\n)\n\n# Events\n\n\n@events_ext.get(\"/api/v1/events\")\nasync def api_events(\n    all_wallets: bool = Query(False), wallet: WalletTypeInfo = Depends(get_key_type)\n):\n    wallet_ids = [wallet.wallet.id]\n\n    if all_wallets:\n        wallet_ids = (await get_user(wallet.wallet.user)).wallet_ids\n\n    return [event.dict() for event in await get_events(wallet_ids)]\n\n\n@events_ext.post(\"/api/v1/events\")\n@events_ext.put(\"/api/v1/events/{event_id}\")\nasync def api_event_create(\n    data: CreateEvent, event_id=None, wallet: WalletTypeInfo = Depends(get_key_type)\n):\n    if event_id:\n        event = await get_event(event_id)\n        if not event:\n            raise HTTPException(\n                status_code=HTTPStatus.NOT_FOUND, detail=f\"Event does not exist.\"\n            )\n\n        if event.wallet != wallet.wallet.id:\n            raise HTTPException(\n                status_code=HTTPStatus.FORBIDDEN, detail=f\"Not your event.\"\n            )\n        event = await update_event(event_id, **data.dict())\n    else:\n        event = await create_event(data=data)\n\n    return event.dict()\n\n\n@events_ext.delete(\"/api/v1/events/{event_id}\")\nasync def api_form_delete(event_id, wallet: WalletTypeInfo = Depends(get_key_type)):\n    event = await get_event(event_id)\n    if not event:\n        raise HTTPException(\n            status_code=HTTPStatus.NOT_FOUND, detail=f\"Event does not exist.\"\n        )\n\n    if event.wallet != wallet.wallet.id:\n        raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail=f\"Not your event.\")\n\n    await delete_event(event_id)\n    await delete_event_tickets(event_id)\n    raise HTTPException(status_code=HTTPStatus.NO_CONTENT)\n\n\n#########Tickets##########\n\n\n@events_ext.get(\"/api/v1/tickets\")\nasync def api_tickets(\n    all_wallets: bool = Query(False), wallet: WalletTypeInfo = Depends(get_key_type)\n):\n    wallet_ids = [wallet.wallet.id]\n\n    if all_wallets:\n        wallet_ids = (await get_user(wallet.wallet.user)).wallet_ids\n\n    return [ticket.dict() for ticket in await get_tickets(wallet_ids)]\n\n\n@events_ext.get(\"/api/v1/tickets/{event_id}\")\nasync def api_ticket_make_ticket(event_id):\n    event = await get_event(event_id)\n    if not event:\n        raise HTTPException(\n            status_code=HTTPStatus.NOT_FOUND, detail=f\"Event does not exist.\"\n        )\n    try:\n        payment_hash, payment_request = await create_invoice(\n            wallet_id=event.wallet,\n            amount=event.price_per_ticket,\n            memo=f\"{event_id}\",\n            extra={\"tag\": \"events\"},\n        )\n    except Exception as e:\n        raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e))\n\n    return {\"payment_hash\": payment_hash, \"payment_request\": payment_request}\n\n\n@events_ext.post(\"/api/v1/tickets/{event_id}/{payment_hash}\")\nasync def api_ticket_send_ticket(event_id, payment_hash, data: CreateTicket):\n    event = await get_event(event_id)\n    try:\n        status = await api_payment(payment_hash)\n        if status[\"paid\"]:\n            ticket = await create_ticket(\n                payment_hash=payment_hash,\n                wallet=event.wallet,\n                event=event_id,\n                name=data.name,\n                email=data.email,\n            )\n\n            if not ticket:\n                raise HTTPException(\n                    status_code=HTTPStatus.NOT_FOUND,\n                    detail=f\"Event could not be fetched.\",\n                )\n\n            return {\"paid\": True, \"ticket_id\": ticket.id}\n    except Exception:\n        raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail=\"Not paid\")\n    return {\"paid\": False}\n\n\n@events_ext.delete(\"/api/v1/tickets/{ticket_id}\")\nasync def api_ticket_delete(ticket_id, wallet: WalletTypeInfo = Depends(get_key_type)):\n    ticket = await get_ticket(ticket_id)\n    if not ticket:\n        raise HTTPException(\n            status_code=HTTPStatus.NOT_FOUND, detail=f\"Ticket does not exist.\"\n        )\n\n    if ticket.wallet != wallet.wallet.id:\n        raise HTTPException(\n            status_code=HTTPStatus.FORBIDDEN, detail=f\"Not your ticket.\"\n        )\n\n    await delete_ticket(ticket_id)\n    raise HTTPException(status_code=HTTPStatus.NO_CONTENT)\n\n\n# Event Tickets\n\n\n@events_ext.get(\"/api/v1/eventtickets/{wallet_id}/{event_id}\")\nasync def api_event_tickets(wallet_id, event_id):\n    return [\n        ticket.dict()\n        for ticket in await get_event_tickets(wallet_id=wallet_id, event_id=event_id)\n    ]\n\n\n@events_ext.get(\"/api/v1/register/ticket/{ticket_id}\")\nasync def api_event_register_ticket(ticket_id):\n    ticket = await get_ticket(ticket_id)\n    if not ticket:\n        raise HTTPException(\n            status_code=HTTPStatus.NOT_FOUND, detail=\"Ticket does not exist.\"\n        )\n\n    if not ticket.paid:\n        raise HTTPException(\n            status_code=HTTPStatus.FORBIDDEN, detail=\"Ticket not paid for.\"\n        )\n\n    if ticket.registered == True:\n        raise HTTPException(\n            status_code=HTTPStatus.FORBIDDEN, detail=\"Ticket already registered\"\n        )\n\n    return [ticket.dict() for ticket in await reg_ticket(ticket_id)]\n", "path": "lnbits/extensions/events/views_api.py"}, {"content": "from typing import List, Optional, Union\n\nfrom lnbits.helpers import urlsafe_short_hash\n\nfrom . import db\nfrom .models import CreateEvent, Events, Tickets\n\n# TICKETS\n\n\nasync def create_ticket(\n    payment_hash: str, wallet: str, event: str, name: str, email: str\n) -> Tickets:\n    await db.execute(\n        \"\"\"\n        INSERT INTO events.ticket (id, wallet, event, name, email, registered, paid)\n        VALUES (?, ?, ?, ?, ?, ?, ?)\n        \"\"\",\n        (payment_hash, wallet, event, name, email, False, True),\n    )\n\n    ticket = await get_ticket(payment_hash)\n    assert ticket, \"Newly created ticket couldn't be retrieved\"\n    return ticket\n\n\nasync def set_ticket_paid(payment_hash: str) -> Tickets:\n    row = await db.fetchone(\"SELECT * FROM events.ticket WHERE id = ?\", (payment_hash,))\n    if row[6] != True:\n        await db.execute(\n            \"\"\"\n            UPDATE events.ticket\n            SET paid = true\n            WHERE id = ?\n            \"\"\",\n            (payment_hash,),\n        )\n\n        eventdata = await get_event(row[2])\n        assert eventdata, \"Couldn't get event from ticket being paid\"\n\n        sold = eventdata.sold + 1\n        amount_tickets = eventdata.amount_tickets - 1\n        await db.execute(\n            \"\"\"\n            UPDATE events.events\n            SET sold = ?, amount_tickets = ?\n            WHERE id = ?\n            \"\"\",\n            (sold, amount_tickets, row[2]),\n        )\n\n    ticket = await get_ticket(payment_hash)\n    assert ticket, \"Newly updated ticket couldn't be retrieved\"\n    return ticket\n\n\nasync def get_ticket(payment_hash: str) -> Optional[Tickets]:\n    row = await db.fetchone(\"SELECT * FROM events.ticket WHERE id = ?\", (payment_hash,))\n    return Tickets(**row) if row else None\n\n\nasync def get_tickets(wallet_ids: Union[str, List[str]]) -> List[Tickets]:\n    if isinstance(wallet_ids, str):\n        wallet_ids = [wallet_ids]\n\n    q = \",\".join([\"?\"] * len(wallet_ids))\n    rows = await db.fetchall(\n        f\"SELECT * FROM events.ticket WHERE wallet IN ({q})\", (*wallet_ids,)\n    )\n    return [Tickets(**row) for row in rows]\n\n\nasync def delete_ticket(payment_hash: str) -> None:\n    await db.execute(\"DELETE FROM events.ticket WHERE id = ?\", (payment_hash,))\n\n\nasync def delete_event_tickets(event_id: str) -> None:\n    await db.execute(\"DELETE FROM events.ticket WHERE event = ?\", (event_id,))\n\n\n# EVENTS\n\n\nasync def create_event(data: CreateEvent) -> Events:\n    event_id = urlsafe_short_hash()\n    await db.execute(\n        \"\"\"\n        INSERT INTO events.events (id, wallet, name, info, closing_date, event_start_date, event_end_date, amount_tickets, price_per_ticket, sold)\n        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n        \"\"\",\n        (\n            event_id,\n            data.wallet,\n            data.name,\n            data.info,\n            data.closing_date,\n            data.event_start_date,\n            data.event_end_date,\n            data.amount_tickets,\n            data.price_per_ticket,\n            0,\n        ),\n    )\n\n    event = await get_event(event_id)\n    assert event, \"Newly created event couldn't be retrieved\"\n    return event\n\n\nasync def update_event(event_id: str, **kwargs) -> Events:\n    q = \", \".join([f\"{field[0]} = ?\" for field in kwargs.items()])\n    await db.execute(\n        f\"UPDATE events.events SET {q} WHERE id = ?\", (*kwargs.values(), event_id)\n    )\n    event = await get_event(event_id)\n    assert event, \"Newly updated event couldn't be retrieved\"\n    return event\n\n\nasync def get_event(event_id: str) -> Optional[Events]:\n    row = await db.fetchone(\"SELECT * FROM events.events WHERE id = ?\", (event_id,))\n    return Events(**row) if row else None\n\n\nasync def get_events(wallet_ids: Union[str, List[str]]) -> List[Events]:\n    if isinstance(wallet_ids, str):\n        wallet_ids = [wallet_ids]\n\n    q = \",\".join([\"?\"] * len(wallet_ids))\n    rows = await db.fetchall(\n        f\"SELECT * FROM events.events WHERE wallet IN ({q})\", (*wallet_ids,)\n    )\n\n    return [Events(**row) for row in rows]\n\n\nasync def delete_event(event_id: str) -> None:\n    await db.execute(\"DELETE FROM events.events WHERE id = ?\", (event_id,))\n\n\n# EVENTTICKETS\n\n\nasync def get_event_tickets(event_id: str, wallet_id: str) -> List[Tickets]:\n    rows = await db.fetchall(\n        \"SELECT * FROM events.ticket WHERE wallet = ? AND event = ?\",\n        (wallet_id, event_id),\n    )\n    return [Tickets(**row) for row in rows]\n\n\nasync def reg_ticket(ticket_id: str) -> List[Tickets]:\n    await db.execute(\n        \"UPDATE events.ticket SET registered = ? WHERE id = ?\", (True, ticket_id)\n    )\n    ticket = await db.fetchone(\"SELECT * FROM events.ticket WHERE id = ?\", (ticket_id,))\n    rows = await db.fetchall(\n        \"SELECT * FROM events.ticket WHERE event = ?\", (ticket[1],)\n    )\n    return [Tickets(**row) for row in rows]\n", "path": "lnbits/extensions/events/crud.py"}], "after_files": [{"content": "from http import HTTPStatus\n\nfrom fastapi.param_functions import Query\nfrom fastapi.params import Depends\nfrom starlette.exceptions import HTTPException\nfrom starlette.requests import Request\n\nfrom lnbits.core.crud import get_user\nfrom lnbits.core.services import create_invoice\nfrom lnbits.core.views.api import api_payment\nfrom lnbits.decorators import WalletTypeInfo, get_key_type\nfrom lnbits.extensions.events.models import CreateEvent, CreateTicket\n\nfrom . import events_ext\nfrom .crud import (\n    create_event,\n    create_ticket,\n    delete_event,\n    delete_event_tickets,\n    delete_ticket,\n    get_event,\n    get_event_tickets,\n    get_events,\n    get_ticket,\n    get_tickets,\n    reg_ticket,\n    update_event,\n)\n\n# Events\n\n\n@events_ext.get(\"/api/v1/events\")\nasync def api_events(\n    all_wallets: bool = Query(False), wallet: WalletTypeInfo = Depends(get_key_type)\n):\n    wallet_ids = [wallet.wallet.id]\n\n    if all_wallets:\n        wallet_ids = (await get_user(wallet.wallet.user)).wallet_ids\n\n    return [event.dict() for event in await get_events(wallet_ids)]\n\n\n@events_ext.post(\"/api/v1/events\")\n@events_ext.put(\"/api/v1/events/{event_id}\")\nasync def api_event_create(\n    data: CreateEvent, event_id=None, wallet: WalletTypeInfo = Depends(get_key_type)\n):\n    if event_id:\n        event = await get_event(event_id)\n        if not event:\n            raise HTTPException(\n                status_code=HTTPStatus.NOT_FOUND, detail=f\"Event does not exist.\"\n            )\n\n        if event.wallet != wallet.wallet.id:\n            raise HTTPException(\n                status_code=HTTPStatus.FORBIDDEN, detail=f\"Not your event.\"\n            )\n        event = await update_event(event_id, **data.dict())\n    else:\n        event = await create_event(data=data)\n\n    return event.dict()\n\n\n@events_ext.delete(\"/api/v1/events/{event_id}\")\nasync def api_form_delete(event_id, wallet: WalletTypeInfo = Depends(get_key_type)):\n    event = await get_event(event_id)\n    if not event:\n        raise HTTPException(\n            status_code=HTTPStatus.NOT_FOUND, detail=f\"Event does not exist.\"\n        )\n\n    if event.wallet != wallet.wallet.id:\n        raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail=f\"Not your event.\")\n\n    await delete_event(event_id)\n    await delete_event_tickets(event_id)\n    raise HTTPException(status_code=HTTPStatus.NO_CONTENT)\n\n\n#########Tickets##########\n\n\n@events_ext.get(\"/api/v1/tickets\")\nasync def api_tickets(\n    all_wallets: bool = Query(False), wallet: WalletTypeInfo = Depends(get_key_type)\n):\n    wallet_ids = [wallet.wallet.id]\n\n    if all_wallets:\n        wallet_ids = (await get_user(wallet.wallet.user)).wallet_ids\n\n    return [ticket.dict() for ticket in await get_tickets(wallet_ids)]\n\n\n@events_ext.get(\"/api/v1/tickets/{event_id}\")\nasync def api_ticket_make_ticket(event_id):\n    event = await get_event(event_id)\n    if not event:\n        raise HTTPException(\n            status_code=HTTPStatus.NOT_FOUND, detail=f\"Event does not exist.\"\n        )\n    try:\n        payment_hash, payment_request = await create_invoice(\n            wallet_id=event.wallet,\n            amount=event.price_per_ticket,\n            memo=f\"{event_id}\",\n            extra={\"tag\": \"events\"},\n        )\n    except Exception as e:\n        raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e))\n\n    return {\"payment_hash\": payment_hash, \"payment_request\": payment_request}\n\n\n@events_ext.post(\"/api/v1/tickets/{event_id}/{payment_hash}\")\nasync def api_ticket_send_ticket(event_id, payment_hash, data: CreateTicket):\n    event = await get_event(event_id)\n    try:\n        status = await api_payment(payment_hash)\n        if status[\"paid\"]:\n            ticket = await create_ticket(\n                payment_hash=payment_hash,\n                wallet=event.wallet,\n                event=event_id,\n                name=data.name,\n                email=data.email,\n            )\n\n            if not ticket:\n                raise HTTPException(\n                    status_code=HTTPStatus.NOT_FOUND,\n                    detail=f\"Event could not be fetched.\",\n                )\n\n            return {\"paid\": True, \"ticket_id\": ticket.id}\n    except Exception:\n        raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail=\"Not paid\")\n    return {\"paid\": False}\n\n\n@events_ext.delete(\"/api/v1/tickets/{ticket_id}\")\nasync def api_ticket_delete(ticket_id, wallet: WalletTypeInfo = Depends(get_key_type)):\n    ticket = await get_ticket(ticket_id)\n    if not ticket:\n        raise HTTPException(\n            status_code=HTTPStatus.NOT_FOUND, detail=f\"Ticket does not exist.\"\n        )\n\n    if ticket.wallet != wallet.wallet.id:\n        raise HTTPException(\n            status_code=HTTPStatus.FORBIDDEN, detail=f\"Not your ticket.\"\n        )\n\n    await delete_ticket(ticket_id)\n    raise HTTPException(status_code=HTTPStatus.NO_CONTENT)\n\n\n# Event Tickets\n\n\n@events_ext.get(\"/api/v1/eventtickets/{wallet_id}/{event_id}\")\nasync def api_event_tickets(wallet_id, event_id):\n    return [\n        ticket.dict()\n        for ticket in await get_event_tickets(wallet_id=wallet_id, event_id=event_id)\n    ]\n\n\n@events_ext.get(\"/api/v1/register/ticket/{ticket_id}\")\nasync def api_event_register_ticket(ticket_id):\n    ticket = await get_ticket(ticket_id)\n    if not ticket:\n        raise HTTPException(\n            status_code=HTTPStatus.NOT_FOUND, detail=\"Ticket does not exist.\"\n        )\n\n    if not ticket.paid:\n        raise HTTPException(\n            status_code=HTTPStatus.FORBIDDEN, detail=\"Ticket not paid for.\"\n        )\n\n    if ticket.registered == True:\n        raise HTTPException(\n            status_code=HTTPStatus.FORBIDDEN, detail=\"Ticket already registered\"\n        )\n\n    return [ticket.dict() for ticket in await reg_ticket(ticket_id)]\n", "path": "lnbits/extensions/events/views_api.py"}, {"content": "from typing import List, Optional, Union\n\nfrom lnbits.helpers import urlsafe_short_hash\n\nfrom . import db\nfrom .models import CreateEvent, Events, Tickets\n\n# TICKETS\n\n\nasync def create_ticket(\n    payment_hash: str, wallet: str, event: str, name: str, email: str\n) -> Tickets:\n    await db.execute(\n        \"\"\"\n        INSERT INTO events.ticket (id, wallet, event, name, email, registered, paid)\n        VALUES (?, ?, ?, ?, ?, ?, ?)\n        \"\"\",\n        (payment_hash, wallet, event, name, email, False, True),\n    )\n\n    # UPDATE EVENT DATA ON SOLD TICKET\n    eventdata = await get_event(event)\n    assert eventdata, \"Couldn't get event from ticket being paid\"\n    sold = eventdata.sold + 1\n    amount_tickets = eventdata.amount_tickets - 1\n    await db.execute(\n        \"\"\"\n        UPDATE events.events\n        SET sold = ?, amount_tickets = ?\n        WHERE id = ?\n        \"\"\",\n        (sold, amount_tickets, event),\n    )\n\n    ticket = await get_ticket(payment_hash)\n    assert ticket, \"Newly created ticket couldn't be retrieved\"\n    return ticket\n\n\nasync def get_ticket(payment_hash: str) -> Optional[Tickets]:\n    row = await db.fetchone(\"SELECT * FROM events.ticket WHERE id = ?\", (payment_hash,))\n    return Tickets(**row) if row else None\n\n\nasync def get_tickets(wallet_ids: Union[str, List[str]]) -> List[Tickets]:\n    if isinstance(wallet_ids, str):\n        wallet_ids = [wallet_ids]\n\n    q = \",\".join([\"?\"] * len(wallet_ids))\n    rows = await db.fetchall(\n        f\"SELECT * FROM events.ticket WHERE wallet IN ({q})\", (*wallet_ids,)\n    )\n    return [Tickets(**row) for row in rows]\n\n\nasync def delete_ticket(payment_hash: str) -> None:\n    await db.execute(\"DELETE FROM events.ticket WHERE id = ?\", (payment_hash,))\n\n\nasync def delete_event_tickets(event_id: str) -> None:\n    await db.execute(\"DELETE FROM events.ticket WHERE event = ?\", (event_id,))\n\n\n# EVENTS\n\n\nasync def create_event(data: CreateEvent) -> Events:\n    event_id = urlsafe_short_hash()\n    await db.execute(\n        \"\"\"\n        INSERT INTO events.events (id, wallet, name, info, closing_date, event_start_date, event_end_date, amount_tickets, price_per_ticket, sold)\n        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n        \"\"\",\n        (\n            event_id,\n            data.wallet,\n            data.name,\n            data.info,\n            data.closing_date,\n            data.event_start_date,\n            data.event_end_date,\n            data.amount_tickets,\n            data.price_per_ticket,\n            0,\n        ),\n    )\n\n    event = await get_event(event_id)\n    assert event, \"Newly created event couldn't be retrieved\"\n    return event\n\n\nasync def update_event(event_id: str, **kwargs) -> Events:\n    q = \", \".join([f\"{field[0]} = ?\" for field in kwargs.items()])\n    await db.execute(\n        f\"UPDATE events.events SET {q} WHERE id = ?\", (*kwargs.values(), event_id)\n    )\n    event = await get_event(event_id)\n    assert event, \"Newly updated event couldn't be retrieved\"\n    return event\n\n\nasync def get_event(event_id: str) -> Optional[Events]:\n    row = await db.fetchone(\"SELECT * FROM events.events WHERE id = ?\", (event_id,))\n    return Events(**row) if row else None\n\n\nasync def get_events(wallet_ids: Union[str, List[str]]) -> List[Events]:\n    if isinstance(wallet_ids, str):\n        wallet_ids = [wallet_ids]\n\n    q = \",\".join([\"?\"] * len(wallet_ids))\n    rows = await db.fetchall(\n        f\"SELECT * FROM events.events WHERE wallet IN ({q})\", (*wallet_ids,)\n    )\n\n    return [Events(**row) for row in rows]\n\n\nasync def delete_event(event_id: str) -> None:\n    await db.execute(\"DELETE FROM events.events WHERE id = ?\", (event_id,))\n\n\n# EVENTTICKETS\n\n\nasync def get_event_tickets(event_id: str, wallet_id: str) -> List[Tickets]:\n    rows = await db.fetchall(\n        \"SELECT * FROM events.ticket WHERE wallet = ? AND event = ?\",\n        (wallet_id, event_id),\n    )\n    return [Tickets(**row) for row in rows]\n\n\nasync def reg_ticket(ticket_id: str) -> List[Tickets]:\n    await db.execute(\n        \"UPDATE events.ticket SET registered = ? WHERE id = ?\", (True, ticket_id)\n    )\n    ticket = await db.fetchone(\"SELECT * FROM events.ticket WHERE id = ?\", (ticket_id,))\n    rows = await db.fetchall(\n        \"SELECT * FROM events.ticket WHERE event = ?\", (ticket[1],)\n    )\n    return [Tickets(**row) for row in rows]\n", "path": "lnbits/extensions/events/crud.py"}]}