From 5a8db02c6034f3656484c5993b7a51772f827930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dni=20=E2=9A=A1?= Date: Mon, 20 Feb 2023 11:06:59 +0100 Subject: [PATCH] remove tipjar (#1522) --- lnbits/extensions/tipjar/README.md | 15 - lnbits/extensions/tipjar/__init__.py | 25 - lnbits/extensions/tipjar/config.json | 6 - lnbits/extensions/tipjar/crud.py | 123 ----- lnbits/extensions/tipjar/migrations.py | 27 -- lnbits/extensions/tipjar/models.py | 56 --- .../extensions/tipjar/static/image/tipjar.png | Bin 20331 -> 0 bytes .../tipjar/templates/tipjar/_api_docs.html | 19 - .../tipjar/templates/tipjar/display.html | 94 ---- .../tipjar/templates/tipjar/index.html | 443 ------------------ lnbits/extensions/tipjar/views.py | 35 -- lnbits/extensions/tipjar/views_api.py | 220 --------- 12 files changed, 1063 deletions(-) delete mode 100644 lnbits/extensions/tipjar/README.md delete mode 100644 lnbits/extensions/tipjar/__init__.py delete mode 100644 lnbits/extensions/tipjar/config.json delete mode 100644 lnbits/extensions/tipjar/crud.py delete mode 100644 lnbits/extensions/tipjar/migrations.py delete mode 100644 lnbits/extensions/tipjar/models.py delete mode 100644 lnbits/extensions/tipjar/static/image/tipjar.png delete mode 100644 lnbits/extensions/tipjar/templates/tipjar/_api_docs.html delete mode 100644 lnbits/extensions/tipjar/templates/tipjar/display.html delete mode 100644 lnbits/extensions/tipjar/templates/tipjar/index.html delete mode 100644 lnbits/extensions/tipjar/views.py delete mode 100644 lnbits/extensions/tipjar/views_api.py diff --git a/lnbits/extensions/tipjar/README.md b/lnbits/extensions/tipjar/README.md deleted file mode 100644 index 4965ec93..00000000 --- a/lnbits/extensions/tipjar/README.md +++ /dev/null @@ -1,15 +0,0 @@ -

Tip Jars

-

Accept tips in Bitcoin, with small messages attached!

-The TipJar extension allows you to integrate Bitcoin Lightning (and on-chain) tips into your website or social media! - -![image](https://user-images.githubusercontent.com/28876473/134997129-c2f3f13c-a65d-42ed-a9c4-8a1da569d74f.png) - -

How to set it up

- -1. Simply create a new Tip Jar with the desired details (onchain optional): -![image](https://user-images.githubusercontent.com/28876473/134996842-ec2f2783-2eef-4671-8eaf-023713865512.png) -1. Share the URL you get from this little button: -![image](https://user-images.githubusercontent.com/28876473/134996973-f8ed4632-ea2f-4b62-83f1-1e4c6b6c91fa.png) - - -

And that's it already! Let the sats flow!

diff --git a/lnbits/extensions/tipjar/__init__.py b/lnbits/extensions/tipjar/__init__.py deleted file mode 100644 index b7e2b967..00000000 --- a/lnbits/extensions/tipjar/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -from fastapi import APIRouter -from fastapi.staticfiles import StaticFiles - -from lnbits.db import Database -from lnbits.helpers import template_renderer - -db = Database("ext_tipjar") - -tipjar_ext: APIRouter = APIRouter(prefix="/tipjar", tags=["tipjar"]) - -tipjar_static_files = [ - { - "path": "/tipjar/static", - "app": StaticFiles(directory="lnbits/extensions/tipjar/static"), - "name": "tipjar_static", - } -] - - -def tipjar_renderer(): - return template_renderer(["lnbits/extensions/tipjar/templates"]) - - -from .views import * # noqa: F401,F403 -from .views_api import * # noqa: F401,F403 diff --git a/lnbits/extensions/tipjar/config.json b/lnbits/extensions/tipjar/config.json deleted file mode 100644 index 90f634ed..00000000 --- a/lnbits/extensions/tipjar/config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "Tip Jar", - "short_description": "Accept Bitcoin donations, with messages attached!", - "tile": "/tipjar/static/image/tipjar.png", - "contributors": ["Fittiboy"] -} diff --git a/lnbits/extensions/tipjar/crud.py b/lnbits/extensions/tipjar/crud.py deleted file mode 100644 index 3ea45d0d..00000000 --- a/lnbits/extensions/tipjar/crud.py +++ /dev/null @@ -1,123 +0,0 @@ -from typing import Optional - -from lnbits.db import SQLITE - -# todo: use the API, not direct import -from ..satspay.crud import delete_charge # type: ignore -from . import db -from .models import Tip, TipJar, createTipJar - - -async def create_tip( - id: str, wallet: str, message: str, name: str, sats: int, tipjar: str -) -> Tip: - """Create a new Tip""" - await db.execute( - """ - INSERT INTO tipjar.Tips ( - id, - wallet, - name, - message, - sats, - tipjar - ) - VALUES (?, ?, ?, ?, ?, ?) - """, - (id, wallet, name, message, sats, tipjar), - ) - - tip = await get_tip(id) - assert tip, "Newly created tip couldn't be retrieved" - return tip - - -async def create_tipjar(data: createTipJar) -> TipJar: - """Create a new TipJar""" - - returning = "" if db.type == SQLITE else "RETURNING ID" - method = db.execute if db.type == SQLITE else db.fetchone - - result = await (method)( - f""" - INSERT INTO tipjar.TipJars ( - name, - wallet, - webhook, - onchain - ) - VALUES (?, ?, ?, ?) - {returning} - """, - (data.name, data.wallet, data.webhook, data.onchain), - ) - if db.type == SQLITE: - tipjar_id = result._result_proxy.lastrowid - else: - tipjar_id = result[0] - - tipjar = await get_tipjar(tipjar_id) - assert tipjar - return tipjar - - -async def get_tipjar(tipjar_id: int) -> Optional[TipJar]: - """Return a tipjar by ID""" - row = await db.fetchone("SELECT * FROM tipjar.TipJars WHERE id = ?", (tipjar_id,)) - return TipJar(**row) if row else None - - -async def get_tipjars(wallet_id: str) -> Optional[list]: - """Return all TipJars belonging assigned to the wallet_id""" - rows = await db.fetchall( - "SELECT * FROM tipjar.TipJars WHERE wallet = ?", (wallet_id,) - ) - return [TipJar(**row) for row in rows] if rows else None - - -async def delete_tipjar(tipjar_id: int) -> None: - """Delete a TipJar and all corresponding Tips""" - rows = await db.fetchall("SELECT * FROM tipjar.Tips WHERE tipjar = ?", (tipjar_id,)) - for row in rows: - await delete_tip(row["id"]) - await db.execute("DELETE FROM tipjar.TipJars WHERE id = ?", (tipjar_id,)) - - -async def get_tip(tip_id: str) -> Optional[Tip]: - """Return a Tip""" - row = await db.fetchone("SELECT * FROM tipjar.Tips WHERE id = ?", (tip_id,)) - return Tip(**row) if row else None - - -async def get_tips(wallet_id: str) -> Optional[list]: - """Return all Tips assigned to wallet_id""" - rows = await db.fetchall("SELECT * FROM tipjar.Tips WHERE wallet = ?", (wallet_id,)) - return [Tip(**row) for row in rows] if rows else None - - -async def delete_tip(tip_id: str) -> None: - """Delete a Tip and its corresponding statspay charge""" - await db.execute("DELETE FROM tipjar.Tips WHERE id = ?", (tip_id,)) - await delete_charge(tip_id) - - -async def update_tip(tip_id: str, **kwargs) -> Tip: - """Update a Tip""" - q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) - await db.execute( - f"UPDATE tipjar.Tips SET {q} WHERE id = ?", (*kwargs.values(), tip_id) - ) - row = await db.fetchone("SELECT * FROM tipjar.Tips WHERE id = ?", (tip_id,)) - assert row, "Newly updated tip couldn't be retrieved" - return Tip(**row) - - -async def update_tipjar(tipjar_id: str, **kwargs) -> TipJar: - """Update a tipjar""" - q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) - await db.execute( - f"UPDATE tipjar.TipJars SET {q} WHERE id = ?", (*kwargs.values(), tipjar_id) - ) - row = await db.fetchone("SELECT * FROM tipjar.TipJars WHERE id = ?", (tipjar_id,)) - assert row, "Newly updated tipjar couldn't be retrieved" - return TipJar(**row) diff --git a/lnbits/extensions/tipjar/migrations.py b/lnbits/extensions/tipjar/migrations.py deleted file mode 100644 index d8f6da3f..00000000 --- a/lnbits/extensions/tipjar/migrations.py +++ /dev/null @@ -1,27 +0,0 @@ -async def m001_initial(db): - - await db.execute( - f""" - CREATE TABLE IF NOT EXISTS tipjar.TipJars ( - id {db.serial_primary_key}, - name TEXT NOT NULL, - wallet TEXT NOT NULL, - onchain TEXT, - webhook TEXT - ); - """ - ) - - await db.execute( - f""" - CREATE TABLE IF NOT EXISTS tipjar.Tips ( - id TEXT PRIMARY KEY, - wallet TEXT NOT NULL, - name TEXT NOT NULL, - message TEXT NOT NULL, - sats {db.big_int} NOT NULL, - tipjar {db.big_int} NOT NULL, - FOREIGN KEY(tipjar) REFERENCES {db.references_schema}TipJars(id) - ); - """ - ) diff --git a/lnbits/extensions/tipjar/models.py b/lnbits/extensions/tipjar/models.py deleted file mode 100644 index 655888da..00000000 --- a/lnbits/extensions/tipjar/models.py +++ /dev/null @@ -1,56 +0,0 @@ -from sqlite3 import Row -from typing import Optional - -from pydantic import BaseModel - - -class createTip(BaseModel): - id: str - wallet: str - sats: int - tipjar: int - name: str = "Anonymous" - message: str = "" - - -class Tip(BaseModel): - """A Tip represents a single donation""" - - id: str # This ID always corresponds to a satspay charge ID - wallet: str - name: str # Name of the donor - message: str # Donation message - sats: int - tipjar: int # The ID of the corresponding tip jar - - @classmethod - def from_row(cls, row: Row) -> "Tip": - return cls(**dict(row)) - - -class createTipJar(BaseModel): - name: str - wallet: str - webhook: Optional[str] - onchain: Optional[str] - - -class createTips(BaseModel): - name: str - sats: str - tipjar: str - message: str - - -class TipJar(BaseModel): - """A TipJar represents a user's tip jar""" - - id: int - name: str # The name of the donatee - wallet: str # Lightning wallet - onchain: Optional[str] # Watchonly wallet - webhook: Optional[str] # URL to POST tips to - - @classmethod - def from_row(cls, row: Row) -> "TipJar": - return cls(**dict(row)) diff --git a/lnbits/extensions/tipjar/static/image/tipjar.png b/lnbits/extensions/tipjar/static/image/tipjar.png deleted file mode 100644 index 6f0d69b75785b1171e129d68f1fce6e2794b048d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20331 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 - -

- Tip Jar: Receive tips with messages! -

-

- Your personal Bitcoin tip page, which supports lightning and on-chain - payments. Notifications, including a donation message, can be sent via - webhook. - - Created by, - Fitti -

-
- - diff --git a/lnbits/extensions/tipjar/templates/tipjar/display.html b/lnbits/extensions/tipjar/templates/tipjar/display.html deleted file mode 100644 index 80e5c6fe..00000000 --- a/lnbits/extensions/tipjar/templates/tipjar/display.html +++ /dev/null @@ -1,94 +0,0 @@ -{% extends "public.html" %} {% block page %} -
-
- - -
Tip {{ donatee }} some sats!
-
- - - - -
- Submit -
-
-
-
-
-
- -{% endblock %} {% block scripts %} - -{% endblock %} diff --git a/lnbits/extensions/tipjar/templates/tipjar/index.html b/lnbits/extensions/tipjar/templates/tipjar/index.html deleted file mode 100644 index 19fca6e4..00000000 --- a/lnbits/extensions/tipjar/templates/tipjar/index.html +++ /dev/null @@ -1,443 +0,0 @@ -{% extends "base.html" %} {% from "macros.jinja" import window_vars with context -%} {% block page %} -
-
- - - New TipJar - - - - - -
-
-
TipJars
-
-
- Export to CSV -
-
- - {% raw %} - - - {% endraw %} - -
-
- - - -
-
-
Tips
-
-
- Export to CSV -
-
- - {% raw %} - - - {% endraw %} - -
-
-
-
- - -
- {{SITE_TITLE}} TipJar extension -
-
- - - {% include "tipjar/_api_docs.html" %} - -
-
- - - - - - -
-
-
- -
-
- - - Watch-Only extension MUST be activated and have a wallet - - -
-
-
-
- -
- - -
- Update TipJar - - Create TipJar - Cancel -
-
-
-
-
-{% endblock %} {% block scripts %} {{ window_vars(user) }} - -{% endblock %} diff --git a/lnbits/extensions/tipjar/views.py b/lnbits/extensions/tipjar/views.py deleted file mode 100644 index ddb1b63c..00000000 --- a/lnbits/extensions/tipjar/views.py +++ /dev/null @@ -1,35 +0,0 @@ -from http import HTTPStatus - -from fastapi import Depends, Query, Request -from fastapi.templating import Jinja2Templates -from starlette.exceptions import HTTPException - -from lnbits.core.models import User -from lnbits.decorators import check_user_exists - -from . import tipjar_ext, tipjar_renderer -from .crud import get_tipjar - -templates = Jinja2Templates(directory="templates") - - -@tipjar_ext.get("/") -async def index(request: Request, user: User = Depends(check_user_exists)): - return tipjar_renderer().TemplateResponse( - "tipjar/index.html", {"request": request, "user": user.dict()} - ) - - -@tipjar_ext.get("/{tipjar_id}") -async def tip(request: Request, tipjar_id: int = Query(None)): - """Return the donation form for the Tipjar corresponding to id""" - tipjar = await get_tipjar(tipjar_id) - if not tipjar: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="TipJar does not exist." - ) - - return tipjar_renderer().TemplateResponse( - "tipjar/display.html", - {"request": request, "donatee": tipjar.name, "tipjar": tipjar.id}, - ) diff --git a/lnbits/extensions/tipjar/views_api.py b/lnbits/extensions/tipjar/views_api.py deleted file mode 100644 index 7d420fae..00000000 --- a/lnbits/extensions/tipjar/views_api.py +++ /dev/null @@ -1,220 +0,0 @@ -from http import HTTPStatus - -from fastapi import Depends, Query -from starlette.exceptions import HTTPException - -from lnbits.core.crud import get_user, get_wallet -from lnbits.decorators import WalletTypeInfo, get_key_type - -# todo: use the API, not direct import -from ..satspay.crud import create_charge # type: ignore -from ..satspay.models import CreateCharge # type: ignore -from . import tipjar_ext -from .crud import ( - create_tip, - create_tipjar, - delete_tip, - delete_tipjar, - get_tip, - get_tipjar, - get_tipjars, - get_tips, - update_tip, - update_tipjar, -) -from .models import createTip, createTipJar, createTips - - -@tipjar_ext.post("/api/v1/tipjars") -async def api_create_tipjar(data: createTipJar): - """Create a tipjar, which holds data about how/where to post tips""" - try: - tipjar = await create_tipjar(data) - except Exception as e: - raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)) - - return tipjar.dict() - - -async def user_from_wallet(wallet: WalletTypeInfo = Depends(get_key_type)): - return wallet.wallet.user - - -@tipjar_ext.post("/api/v1/tips") -async def api_create_tip(data: createTips): - """Take data from tip form and return satspay charge""" - sats = int(data.sats) - message = data.message - if not message: - message = "No message" - tipjar_id = int(data.tipjar) - tipjar = await get_tipjar(tipjar_id) - if not tipjar: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="Tipjar does not exist." - ) - - wallet_id = tipjar.wallet - wallet = await get_wallet(wallet_id) - if not wallet: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="Tipjar wallet does not exist." - ) - - name = data.name - - # Ensure that description string can be split reliably - name = name.replace('"', "''") - if not name: - name = "Anonymous" - - description = f"{name}: {message}" - charge = await create_charge( - user=wallet.user, - data=CreateCharge( - amount=sats, - webhook=tipjar.webhook or "", - description=description, - onchainwallet=tipjar.onchain or "", - lnbitswallet=tipjar.wallet, - completelink="/tipjar/" + str(tipjar_id), - completelinktext="Thanks for the tip!", - time=1440, - custom_css="", - ), - ) - - await create_tip( - id=charge.id, - wallet=tipjar.wallet, - message=message, - name=name, - sats=int(data.sats), - tipjar=data.tipjar, - ) - - return {"redirect_url": f"/satspay/{charge.id}"} - - -@tipjar_ext.get("/api/v1/tipjars") -async def api_get_tipjars(wallet: WalletTypeInfo = Depends(get_key_type)): - """Return list of all tipjars assigned to wallet with given invoice key""" - user = await get_user(wallet.wallet.user) - if not user: - return [] - tipjars = [] - for wallet_id in user.wallet_ids: - new_tipjars = await get_tipjars(wallet_id) - tipjars += new_tipjars if new_tipjars else [] - return [tipjar.dict() for tipjar in tipjars] - - -@tipjar_ext.get("/api/v1/tips") -async def api_get_tips(wallet: WalletTypeInfo = Depends(get_key_type)): - """Return list of all tips assigned to wallet with given invoice key""" - user = await get_user(wallet.wallet.user) - if not user: - return [] - tips = [] - for wallet_id in user.wallet_ids: - new_tips = await get_tips(wallet_id) - tips += new_tips if new_tips else [] - return [tip.dict() for tip in tips] - - -@tipjar_ext.put("/api/v1/tips/{tip_id}") -async def api_update_tip( - data: createTip, - wallet: WalletTypeInfo = Depends(get_key_type), - tip_id: str = Query(None), -): - """Update a tip with the data given in the request""" - if tip_id: - tip = await get_tip(tip_id) - - if not tip: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="Tip does not exist." - ) - - if tip.wallet != wallet.wallet.id: - - raise HTTPException( - status_code=HTTPStatus.FORBIDDEN, detail="Not your tip." - ) - - tip = await update_tip(tip_id, **data.dict()) - else: - raise HTTPException( - status_code=HTTPStatus.BAD_REQUEST, detail="No tip ID specified" - ) - return tip.dict() - - -@tipjar_ext.put("/api/v1/tipjars/{tipjar_id}") -async def api_update_tipjar( - data: createTipJar, - wallet: WalletTypeInfo = Depends(get_key_type), - tipjar_id: int = Query(None), -): - """Update a tipjar with the data given in the request""" - if tipjar_id: - tipjar = await get_tipjar(tipjar_id) - - if not tipjar: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="TipJar does not exist." - ) - - if tipjar.wallet != wallet.wallet.id: - raise HTTPException( - status_code=HTTPStatus.FORBIDDEN, detail="Not your tipjar." - ) - - tipjar = await update_tipjar(str(tipjar_id), **data.dict()) - else: - raise HTTPException( - status_code=HTTPStatus.BAD_REQUEST, detail="No tipjar ID specified" - ) - return tipjar.dict() - - -@tipjar_ext.delete("/api/v1/tips/{tip_id}") -async def api_delete_tip( - wallet: WalletTypeInfo = Depends(get_key_type), tip_id: str = Query(None) -): - """Delete the tip with the given tip_id""" - tip = await get_tip(tip_id) - if not tip: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="No tip with this ID!" - ) - if tip.wallet != wallet.wallet.id: - raise HTTPException( - status_code=HTTPStatus.FORBIDDEN, - detail="Not authorized to delete this tip!", - ) - await delete_tip(tip_id) - - return "", HTTPStatus.NO_CONTENT - - -@tipjar_ext.delete("/api/v1/tipjars/{tipjar_id}") -async def api_delete_tipjar( - wallet: WalletTypeInfo = Depends(get_key_type), tipjar_id: int = Query(None) -): - """Delete the tipjar with the given tipjar_id""" - tipjar = await get_tipjar(tipjar_id) - if not tipjar: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="No tipjar with this ID!" - ) - if tipjar.wallet != wallet.wallet.id: - - raise HTTPException( - status_code=HTTPStatus.FORBIDDEN, - detail="Not authorized to delete this tipjar!", - ) - await delete_tipjar(tipjar_id) - - return "", HTTPStatus.NO_CONTENT