diff --git a/lnbits/extensions/lnticket/README.md b/lnbits/extensions/lnticket/README.md
deleted file mode 100644
index bd0714506..000000000
--- a/lnbits/extensions/lnticket/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Support Tickets
-
-## Get paid sats to answer questions
-
-Charge a per word amount for people to contact you.
-
-Possible applications include, paid support ticketing, PAYG language services, contact spam protection.
-
-1. Click "NEW FORM" to create a new contact form\
- 
-2. Fill out the contact form
- - set the wallet to use
- - give your form a name
- - set an optional webhook that will get called when the form receives a payment
- - give it a small description
- - set the amount you want to charge, per **word**, for people to contact you\
- 
-3. Your new contact form will appear on the _Forms_ section. Note that you can create various forms with different rates per word, for different purposes\
- 
-4. When a user wants to reach out to you, they will get to the contact form. They can fill out some information:
- - a name
- - an optional email if they want you to reply
- - and the actual message
- - at the bottom, a value in satoshis, will display how much it will cost them to send this message\
- 
- - after submiting the Lightning Network invoice will pop up and after payment the message will be sent to you\
- 
-5. Back in "Support ticket" extension you'll get the messages your fans, users, haters, etc, sent you on the _Tickets_ section\
- 
diff --git a/lnbits/extensions/lnticket/__init__.py b/lnbits/extensions/lnticket/__init__.py
deleted file mode 100644
index 3c52fd2a2..000000000
--- a/lnbits/extensions/lnticket/__init__.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import asyncio
-import json
-
-from fastapi import APIRouter
-from starlette.staticfiles import StaticFiles
-
-from lnbits.db import Database
-from lnbits.helpers import template_renderer
-from lnbits.tasks import catch_everything_and_restart
-
-db = Database("ext_lnticket")
-
-lnticket_ext: APIRouter = APIRouter(prefix="/lnticket", tags=["LNTicket"])
-
-lnticket_static_files = [
- {
- "path": "/lnticket/static",
- "app": StaticFiles(directory="lnbits/extensions/lnticket/static"),
- "name": "lnticket_static",
- }
-]
-
-
-def lnticket_renderer():
- return template_renderer(["lnbits/extensions/lnticket/templates"])
-
-
-from .tasks import wait_for_paid_invoices
-from .views import * # noqa
-from .views_api import * # noqa
-
-
-def lnticket_start():
- loop = asyncio.get_event_loop()
- loop.create_task(catch_everything_and_restart(wait_for_paid_invoices))
diff --git a/lnbits/extensions/lnticket/config.json b/lnbits/extensions/lnticket/config.json
deleted file mode 100644
index e8e55f2ff..000000000
--- a/lnbits/extensions/lnticket/config.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "Support Tickets",
- "short_description": "LN support ticket system",
- "tile": "/lnticket/static/image/lntickets.png",
- "contributors": ["benarc"]
-}
diff --git a/lnbits/extensions/lnticket/crud.py b/lnbits/extensions/lnticket/crud.py
deleted file mode 100644
index 3254ad438..000000000
--- a/lnbits/extensions/lnticket/crud.py
+++ /dev/null
@@ -1,162 +0,0 @@
-from typing import List, Optional, Union
-
-import httpx
-
-from lnbits.core.models import Wallet
-from lnbits.helpers import urlsafe_short_hash
-
-from . import db
-from .models import CreateFormData, CreateTicketData, Forms, Tickets
-
-
-async def create_ticket(
- payment_hash: str, wallet: str, data: CreateTicketData
-) -> Tickets:
- await db.execute(
- """
- INSERT INTO lnticket.ticket (id, form, email, ltext, name, wallet, sats, paid)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
- """,
- (
- payment_hash,
- data.form,
- data.email,
- data.ltext,
- data.name,
- wallet,
- data.sats,
- False,
- ),
- )
-
- 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 lnticket.ticket WHERE id = ?", (payment_hash,)
- )
- if row[7] == False:
- await db.execute(
- """
- UPDATE lnticket.ticket
- SET paid = true
- WHERE id = ?
- """,
- (payment_hash,),
- )
-
- formdata = await get_form(row[1])
- assert formdata, "Couldn't get form from paid ticket"
-
- amount = formdata.amountmade + row[7]
- await db.execute(
- """
- UPDATE lnticket.form2
- SET amountmade = ?
- WHERE id = ?
- """,
- (amount, row[1]),
- )
-
- ticket = await get_ticket(payment_hash)
- assert ticket, "Newly paid ticket could not be retrieved"
-
- if formdata.webhook:
- async with httpx.AsyncClient() as client:
- await client.post(
- formdata.webhook,
- json={
- "form": ticket.form,
- "name": ticket.name,
- "email": ticket.email,
- "content": ticket.ltext,
- },
- timeout=40,
- )
- return ticket
-
- ticket = await get_ticket(payment_hash)
- assert ticket, "Newly paid ticket could not be retrieved"
- return ticket
-
-
-async def get_ticket(ticket_id: str) -> Optional[Tickets]:
- row = await db.fetchone("SELECT * FROM lnticket.ticket WHERE id = ?", (ticket_id,))
- return Tickets(**row) if row else None
-
-
-async def get_tickets(wallet_ids: Union[str, List[str]]) -> List[Tickets]:
- if isinstance(wallet_ids, str):
- wallet_ids = [wallet_ids]
-
- q = ",".join(["?"] * len(wallet_ids))
- rows = await db.fetchall(
- 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 lnticket.ticket WHERE id = ?", (ticket_id,))
-
-
-# FORMS
-
-
-async def create_form(data: CreateFormData, wallet: Wallet) -> Forms:
- form_id = urlsafe_short_hash()
- await db.execute(
- """
- INSERT INTO lnticket.form2 (id, wallet, name, webhook, description, flatrate, amount, amountmade)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
- """,
- (
- form_id,
- wallet.id,
- wallet.name,
- data.webhook,
- data.description,
- data.flatrate,
- data.amount,
- 0,
- ),
- )
-
- form = await get_form(form_id)
- assert form, "Newly created forms couldn't be retrieved"
- return 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 lnticket.form2 SET {q} WHERE id = ?", (*kwargs.values(), form_id)
- )
- row = await db.fetchone("SELECT * FROM lnticket.form2 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 lnticket.form2 WHERE id = ?", (form_id,))
- return Forms(**row) if row else None
-
-
-async def get_forms(wallet_ids: Union[str, List[str]]) -> List[Forms]:
- if isinstance(wallet_ids, str):
- wallet_ids = [wallet_ids]
-
- q = ",".join(["?"] * len(wallet_ids))
- rows = await db.fetchall(
- f"SELECT * FROM lnticket.form2 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 lnticket.form2 WHERE id = ?", (form_id,))
diff --git a/lnbits/extensions/lnticket/migrations.py b/lnbits/extensions/lnticket/migrations.py
deleted file mode 100644
index 44c2e0f10..000000000
--- a/lnbits/extensions/lnticket/migrations.py
+++ /dev/null
@@ -1,177 +0,0 @@
-async def m001_initial(db):
-
- await db.execute(
- """
- 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 """
- + db.timestamp_now
- + """
- );
- """
- )
-
- await db.execute(
- """
- CREATE TABLE lnticket.tickets (
- id TEXT PRIMARY KEY,
- form TEXT NOT NULL,
- email TEXT NOT NULL,
- ltext TEXT NOT NULL,
- name TEXT NOT NULL,
- wallet TEXT NOT NULL,
- sats INTEGER NOT NULL,
- time TIMESTAMP NOT NULL DEFAULT """
- + db.timestamp_now
- + """
- );
- """
- )
-
-
-async def m002_changed(db):
-
- await db.execute(
- """
- CREATE TABLE lnticket.ticket (
- id TEXT PRIMARY KEY,
- form TEXT NOT NULL,
- email TEXT NOT NULL,
- ltext TEXT NOT NULL,
- name TEXT NOT NULL,
- wallet TEXT NOT NULL,
- sats INTEGER NOT NULL,
- paid BOOLEAN NOT NULL,
- time TIMESTAMP NOT NULL DEFAULT """
- + db.timestamp_now
- + """
- );
- """
- )
-
- for row in [
- list(row) for row in await db.fetchall("SELECT * FROM lnticket.tickets")
- ]:
- usescsv = ""
-
- for i in range(row[5]):
- if row[7]:
- usescsv += "," + str(i + 1)
- else:
- usescsv += "," + str(1)
- usescsv = usescsv[1:]
- await db.execute(
- """
- INSERT INTO lnticket.ticket (
- id,
- form,
- email,
- ltext,
- name,
- wallet,
- sats,
- paid
- )
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
- """,
- (row[0], row[1], row[2], row[3], row[4], row[5], row[6], True),
- )
- await db.execute("DROP TABLE lnticket.tickets")
-
-
-async def m003_changed(db):
-
- await db.execute(
- """
- CREATE TABLE IF NOT EXISTS lnticket.form (
- id TEXT PRIMARY KEY,
- wallet TEXT NOT NULL,
- name TEXT NOT NULL,
- webhook TEXT,
- description TEXT NOT NULL,
- costpword INTEGER NOT NULL,
- amountmade INTEGER NOT NULL,
- time TIMESTAMP NOT NULL DEFAULT """
- + db.timestamp_now
- + """
- );
- """
- )
-
- for row in [list(row) for row in await db.fetchall("SELECT * FROM lnticket.forms")]:
- usescsv = ""
-
- for i in range(row[5]):
- if row[7]:
- usescsv += "," + str(i + 1)
- else:
- usescsv += "," + str(1)
- usescsv = usescsv[1:]
- await db.execute(
- """
- INSERT INTO lnticket.form (
- id,
- wallet,
- name,
- webhook,
- description,
- costpword,
- amountmade
- )
- VALUES (?, ?, ?, ?, ?, ?, ?)
- """,
- (row[0], row[1], row[2], row[3], row[4], row[5], row[6]),
- )
- await db.execute("DROP TABLE lnticket.forms")
-
-
-async def m004_changed(db):
-
- await db.execute(
- """
- CREATE TABLE lnticket.form2 (
- id TEXT PRIMARY KEY,
- wallet TEXT NOT NULL,
- name TEXT NOT NULL,
- webhook TEXT,
- description TEXT NOT NULL,
- flatrate INTEGER DEFAULT 0,
- amount INTEGER NOT NULL,
- amountmade INTEGER NOT NULL,
- time TIMESTAMP NOT NULL DEFAULT """
- + db.timestamp_now
- + """
- );
- """
- )
-
- for row in [list(row) for row in await db.fetchall("SELECT * FROM lnticket.form")]:
- usescsv = ""
-
- for i in range(row[5]):
- if row[7]:
- usescsv += "," + str(i + 1)
- else:
- usescsv += "," + str(1)
- usescsv = usescsv[1:]
- await db.execute(
- """
- INSERT INTO lnticket.form2 (
- id,
- wallet,
- name,
- webhook,
- description,
- amount,
- amountmade
- )
- VALUES (?, ?, ?, ?, ?, ?, ?)
- """,
- (row[0], row[1], row[2], row[3], row[4], row[5], row[6]),
- )
- await db.execute("DROP TABLE lnticket.form")
diff --git a/lnbits/extensions/lnticket/models.py b/lnbits/extensions/lnticket/models.py
deleted file mode 100644
index a7a3cf8c3..000000000
--- a/lnbits/extensions/lnticket/models.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from typing import Optional
-
-from fastapi.param_functions import Query
-from pydantic import BaseModel
-
-
-class CreateFormData(BaseModel):
- name: str = Query(...)
- webhook: str = Query(None)
- description: str = Query(..., min_length=0)
- amount: int = Query(..., ge=0)
- flatrate: int = Query(...)
-
-
-class CreateTicketData(BaseModel):
- form: str = Query(...)
- name: str = Query(...)
- email: str = Query("")
- ltext: str = Query(...)
- sats: int = Query(..., ge=0)
-
-
-class Forms(BaseModel):
- id: str
- wallet: str
- name: str
- webhook: Optional[str]
- description: str
- amount: int
- flatrate: int
- amountmade: int
- time: int
-
-
-class Tickets(BaseModel):
- id: str
- form: str
- email: str
- ltext: str
- name: str
- wallet: str
- sats: int
- paid: bool
- time: int
diff --git a/lnbits/extensions/lnticket/static/image/lntickets.png b/lnbits/extensions/lnticket/static/image/lntickets.png
deleted file mode 100644
index 875b41547..000000000
Binary files a/lnbits/extensions/lnticket/static/image/lntickets.png and /dev/null differ
diff --git a/lnbits/extensions/lnticket/tasks.py b/lnbits/extensions/lnticket/tasks.py
deleted file mode 100644
index 746ebea94..000000000
--- a/lnbits/extensions/lnticket/tasks.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import asyncio
-
-from loguru import logger
-
-from lnbits.core.models import Payment
-from lnbits.helpers import get_current_extension_name
-from lnbits.tasks import register_invoice_listener
-
-from .crud import get_ticket, set_ticket_paid
-
-
-async def wait_for_paid_invoices():
- invoice_queue = asyncio.Queue()
- register_invoice_listener(invoice_queue, get_current_extension_name())
-
- while True:
- payment = await invoice_queue.get()
- await on_invoice_paid(payment)
-
-
-async def on_invoice_paid(payment: Payment) -> None:
- if payment.extra.get("tag") != "lnticket":
- # not a lnticket invoice
- return
-
- ticket = await get_ticket(payment.checking_id)
- if not ticket:
- logger.error("this should never happen", payment)
- return
-
- await payment.set_pending(False)
- await set_ticket_paid(payment.payment_hash)
diff --git a/lnbits/extensions/lnticket/templates/lnticket/_api_docs.html b/lnbits/extensions/lnticket/templates/lnticket/_api_docs.html
deleted file mode 100644
index 97a0fe6b1..000000000
--- a/lnbits/extensions/lnticket/templates/lnticket/_api_docs.html
+++ /dev/null
@@ -1,26 +0,0 @@
-
- Charge people per word for contacting you. Possible applications incude,
- paid support ticketing, PAYG language services, contact spam
- protection.
- Support Tickets: Get paid sats to answer questions
-
-
-
- Created by,
- Ben Arc
-
{% raw %}{{amountWords}}{% endraw %}
-{{this.ticketDialog.data.content}}
-