From 967f46f82af770e1e7373670894a15042ded1308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dni=20=E2=9A=A1?= Date: Fri, 17 Feb 2023 15:18:39 +0100 Subject: [PATCH] remove paywall (#1518) --- lnbits/extensions/paywall/README.md | 22 -- lnbits/extensions/paywall/__init__.py | 25 -- lnbits/extensions/paywall/config.json | 6 - lnbits/extensions/paywall/crud.py | 52 --- lnbits/extensions/paywall/migrations.py | 63 ---- lnbits/extensions/paywall/models.py | 41 --- .../paywall/static/image/paywall.png | Bin 16793 -> 0 bytes .../paywall/templates/paywall/_api_docs.html | 148 --------- .../paywall/templates/paywall/display.html | 168 ---------- .../paywall/templates/paywall/index.html | 312 ------------------ lnbits/extensions/paywall/views.py | 30 -- lnbits/extensions/paywall/views_api.py | 105 ------ 12 files changed, 972 deletions(-) delete mode 100644 lnbits/extensions/paywall/README.md delete mode 100644 lnbits/extensions/paywall/__init__.py delete mode 100644 lnbits/extensions/paywall/config.json delete mode 100644 lnbits/extensions/paywall/crud.py delete mode 100644 lnbits/extensions/paywall/migrations.py delete mode 100644 lnbits/extensions/paywall/models.py delete mode 100644 lnbits/extensions/paywall/static/image/paywall.png delete mode 100644 lnbits/extensions/paywall/templates/paywall/_api_docs.html delete mode 100644 lnbits/extensions/paywall/templates/paywall/display.html delete mode 100644 lnbits/extensions/paywall/templates/paywall/index.html delete mode 100644 lnbits/extensions/paywall/views.py delete mode 100644 lnbits/extensions/paywall/views_api.py diff --git a/lnbits/extensions/paywall/README.md b/lnbits/extensions/paywall/README.md deleted file mode 100644 index 738485e2..00000000 --- a/lnbits/extensions/paywall/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Paywall - -## Hide content behind a paywall, a user has to pay some amount to access your hidden content - -A Paywall is a way of restricting to content via a purchase or paid subscription. For example to read a determined blog post, or to continue reading further, to access a downloads area, etc... - -## Usage - -1. Create a paywall by clicking "NEW PAYWALL"\ - ![create new paywall](https://i.imgur.com/q0ZIekC.png) -2. Fill the options for your PAYWALL - - select the wallet - - set the link that will be unlocked after a successful payment - - give your paywall a _Title_ - - an optional small description - - and set an amount a user must pay to access the hidden content. Note this is the minimum amount, a user can over pay if they wish - - if _Remember payments_ is checked, a returning paying user won't have to pay again for the same content.\ - ![paywall config](https://i.imgur.com/CBW48F6.png) -3. You can then use your paywall link to secure your awesome content\ - ![paywall link](https://i.imgur.com/hDQmCDf.png) -4. When a user wants to access your hidden content, he can use the minimum amount or increase and click the "_Check icon_" to generate an invoice, user will then be redirected to the content page\ - ![user paywall view](https://i.imgur.com/3pLywkZ.png) diff --git a/lnbits/extensions/paywall/__init__.py b/lnbits/extensions/paywall/__init__.py deleted file mode 100644 index 5565a934..00000000 --- a/lnbits/extensions/paywall/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -from fastapi import APIRouter -from starlette.staticfiles import StaticFiles - -from lnbits.db import Database -from lnbits.helpers import template_renderer - -db = Database("ext_paywall") - -paywall_ext: APIRouter = APIRouter(prefix="/paywall", tags=["Paywall"]) - -paywall_static_files = [ - { - "path": "/paywall/static", - "app": StaticFiles(directory="lnbits/extensions/paywall/static"), - "name": "paywall_static", - } -] - - -def paywall_renderer(): - return template_renderer(["lnbits/extensions/paywall/templates"]) - - -from .views import * # noqa: F401,F403 -from .views_api import * # noqa: F401,F403 diff --git a/lnbits/extensions/paywall/config.json b/lnbits/extensions/paywall/config.json deleted file mode 100644 index 749d1989..00000000 --- a/lnbits/extensions/paywall/config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "Paywall", - "short_description": "Create paywalls for content", - "tile": "/paywall/static/image/paywall.png", - "contributors": ["eillarra"] -} diff --git a/lnbits/extensions/paywall/crud.py b/lnbits/extensions/paywall/crud.py deleted file mode 100644 index cb9e210d..00000000 --- a/lnbits/extensions/paywall/crud.py +++ /dev/null @@ -1,52 +0,0 @@ -from typing import List, Optional, Union - -from lnbits.helpers import urlsafe_short_hash - -from . import db -from .models import CreatePaywall, Paywall - - -async def create_paywall(wallet_id: str, data: CreatePaywall) -> Paywall: - paywall_id = urlsafe_short_hash() - await db.execute( - """ - INSERT INTO paywall.paywalls (id, wallet, url, memo, description, amount, remembers) - VALUES (?, ?, ?, ?, ?, ?, ?) - """, - ( - paywall_id, - wallet_id, - data.url, - data.memo, - data.description, - data.amount, - int(data.remembers), - ), - ) - - paywall = await get_paywall(paywall_id) - assert paywall, "Newly created paywall couldn't be retrieved" - return paywall - - -async def get_paywall(paywall_id: str) -> Optional[Paywall]: - row = await db.fetchone( - "SELECT * FROM paywall.paywalls WHERE id = ?", (paywall_id,) - ) - return Paywall.from_row(row) if row else None - - -async def get_paywalls(wallet_ids: Union[str, List[str]]) -> List[Paywall]: - if isinstance(wallet_ids, str): - wallet_ids = [wallet_ids] - - q = ",".join(["?"] * len(wallet_ids)) - rows = await db.fetchall( - f"SELECT * FROM paywall.paywalls WHERE wallet IN ({q})", (*wallet_ids,) - ) - - return [Paywall.from_row(row) for row in rows] - - -async def delete_paywall(paywall_id: str) -> None: - await db.execute("DELETE FROM paywall.paywalls WHERE id = ?", (paywall_id,)) diff --git a/lnbits/extensions/paywall/migrations.py b/lnbits/extensions/paywall/migrations.py deleted file mode 100644 index 9b3341fd..00000000 --- a/lnbits/extensions/paywall/migrations.py +++ /dev/null @@ -1,63 +0,0 @@ -async def m001_initial(db): - """ - Initial paywalls table. - """ - await db.execute( - f""" - CREATE TABLE paywall.paywalls ( - id TEXT PRIMARY KEY, - wallet TEXT NOT NULL, - secret TEXT NOT NULL, - url TEXT NOT NULL, - memo TEXT NOT NULL, - amount {db.big_int} NOT NULL, - time TIMESTAMP NOT NULL DEFAULT """ - + db.timestamp_now - + """ - ); - """ - ) - - -async def m002_redux(db): - """ - Creates an improved paywalls table and migrates the existing data. - """ - await db.execute("ALTER TABLE paywall.paywalls RENAME TO paywalls_old") - await db.execute( - f""" - CREATE TABLE paywall.paywalls ( - id TEXT PRIMARY KEY, - wallet TEXT NOT NULL, - url TEXT NOT NULL, - memo TEXT NOT NULL, - description TEXT NULL, - amount {db.big_int} DEFAULT 0, - time TIMESTAMP NOT NULL DEFAULT """ - + db.timestamp_now - + """, - remembers INTEGER DEFAULT 0, - extras TEXT NULL - ); - """ - ) - - for row in [ - list(row) for row in await db.fetchall("SELECT * FROM paywall.paywalls_old") - ]: - await db.execute( - """ - INSERT INTO paywall.paywalls ( - id, - wallet, - url, - memo, - amount, - time - ) - VALUES (?, ?, ?, ?, ?, ?) - """, - (row[0], row[1], row[3], row[4], row[5], row[6]), - ) - - await db.execute("DROP TABLE paywall.paywalls_old") diff --git a/lnbits/extensions/paywall/models.py b/lnbits/extensions/paywall/models.py deleted file mode 100644 index 7082c541..00000000 --- a/lnbits/extensions/paywall/models.py +++ /dev/null @@ -1,41 +0,0 @@ -import json -from sqlite3 import Row -from typing import Optional - -from fastapi import Query -from pydantic import BaseModel - - -class CreatePaywall(BaseModel): - url: str = Query(...) - memo: str = Query(...) - description: str = Query(None) - amount: int = Query(..., ge=0) - remembers: bool = Query(...) - - -class CreatePaywallInvoice(BaseModel): - amount: int = Query(..., ge=1) - - -class CheckPaywallInvoice(BaseModel): - payment_hash: str = Query(...) - - -class Paywall(BaseModel): - id: str - wallet: str - url: str - memo: str - description: Optional[str] - amount: int - time: int - remembers: bool - extras: Optional[dict] - - @classmethod - def from_row(cls, row: Row) -> "Paywall": - data = dict(row) - data["remembers"] = bool(data["remembers"]) - data["extras"] = json.loads(data["extras"]) if data["extras"] else None - return cls(**data) diff --git a/lnbits/extensions/paywall/static/image/paywall.png b/lnbits/extensions/paywall/static/image/paywall.png deleted file mode 100644 index 0331a953c9d6ebd914706e3bffaba804ff5f1dc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16793 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 diff --git a/lnbits/extensions/paywall/templates/paywall/_api_docs.html b/lnbits/extensions/paywall/templates/paywall/_api_docs.html deleted file mode 100644 index 0fd8bdd3..00000000 --- a/lnbits/extensions/paywall/templates/paywall/_api_docs.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - GET /paywall/api/v1/paywalls -
Headers
- {"X-Api-Key": <invoice_key>}
-
Body (application/json)
-
- Returns 200 OK (application/json) -
- [<paywall_object>, ...] -
Curl example
- curl -X GET {{ request.base_url }}paywall/api/v1/paywalls -H - "X-Api-Key: {{ user.wallets[0].inkey }}" - -
-
-
- - - - POST /paywall/api/v1/paywalls -
Headers
- {"X-Api-Key": <admin_key>}
-
Body (application/json)
- {"amount": <integer>, "description": <string>, "memo": - <string>, "remembers": <boolean>, "url": - <string>} -
- Returns 201 CREATED (application/json) -
- {"amount": <integer>, "description": <string>, "id": - <string>, "memo": <string>, "remembers": <boolean>, - "time": <int>, "url": <string>, "wallet": - <string>} -
Curl example
- curl -X POST {{ request.base_url }}paywall/api/v1/paywalls -d - '{"url": <string>, "memo": <string>, "description": - <string>, "amount": <integer>, "remembers": - <boolean>}' -H "Content-type: application/json" -H "X-Api-Key: - {{ user.wallets[0].adminkey }}" - -
-
-
- - - - POST - /paywall/api/v1/paywalls/<paywall_id>/invoice -
Body (application/json)
- {"amount": <integer>} -
- Returns 201 CREATED (application/json) -
- {"payment_hash": <string>, "payment_request": - <string>} -
Curl example
- curl -X POST {{ request.base_url - }}paywall/api/v1/paywalls/<paywall_id>/invoice -d '{"amount": - <integer>}' -H "Content-type: application/json" - -
-
-
- - - - POST - /paywall/api/v1/paywalls/<paywall_id>/check_invoice -
Body (application/json)
- {"payment_hash": <string>} -
- Returns 200 OK (application/json) -
- {"paid": false}
- {"paid": true, "url": <string>, "remembers": - <boolean>} -
Curl example
- curl -X POST {{ request.base_url - }}paywall/api/v1/paywalls/<paywall_id>/check_invoice -d - '{"payment_hash": <string>}' -H "Content-type: application/json" - -
-
-
- - - - DELETE - /paywall/api/v1/paywalls/<paywall_id> -
Headers
- {"X-Api-Key": <admin_key>}
-
Returns 204 NO CONTENT
- -
Curl example
- curl -X DELETE {{ request.base_url - }}paywall/api/v1/paywalls/<paywall_id> -H "X-Api-Key: {{ - user.wallets[0].adminkey }}" - -
-
-
-
diff --git a/lnbits/extensions/paywall/templates/paywall/display.html b/lnbits/extensions/paywall/templates/paywall/display.html deleted file mode 100644 index a5edd102..00000000 --- a/lnbits/extensions/paywall/templates/paywall/display.html +++ /dev/null @@ -1,168 +0,0 @@ -{% extends "public.html" %} {% block page %} -
-
- - -
{{ paywall.memo }}
- {% if paywall.description %} -

{{ paywall.description }}

- {% endif %} -
- - - -
- Send -
-
-
- - - - - -
- Copy invoice - Cancel -
-
-
-
- -

- You can access the URL behind this paywall:
- {% raw %}{{ redirectUrl }}{% endraw %} -

-
- Open URL -
-
-
-
-
-
-{% endblock %} {% block scripts %} - -{% endblock %} diff --git a/lnbits/extensions/paywall/templates/paywall/index.html b/lnbits/extensions/paywall/templates/paywall/index.html deleted file mode 100644 index 482d1465..00000000 --- a/lnbits/extensions/paywall/templates/paywall/index.html +++ /dev/null @@ -1,312 +0,0 @@ -{% extends "base.html" %} {% from "macros.jinja" import window_vars with context -%} {% block page %} -
-
- - - New paywall - - - - - -
-
-
Paywalls
-
-
- Export to CSV -
-
- - {% raw %} - - - {% endraw %} - -
-
-
- -
- - -
- {{SITE_TITLE}} paywall extension -
-
- - - {% include "paywall/_api_docs.html" %} - -
-
- - - - - - - - - - - - - - - - - Remember payments - A succesful payment will be registered in the browser's - storage, so the user doesn't need to pay again to access the - URL. - - - -
- Create paywall - Cancel -
-
-
-
-
-{% endblock %} {% block scripts %} {{ window_vars(user) }} - -{% endblock %} diff --git a/lnbits/extensions/paywall/views.py b/lnbits/extensions/paywall/views.py deleted file mode 100644 index 340f23c3..00000000 --- a/lnbits/extensions/paywall/views.py +++ /dev/null @@ -1,30 +0,0 @@ -from http import HTTPStatus - -from fastapi import Depends -from starlette.exceptions import HTTPException -from starlette.requests import Request - -from lnbits.core.models import User -from lnbits.decorators import check_user_exists - -from . import paywall_ext, paywall_renderer -from .crud import get_paywall - - -@paywall_ext.get("/") -async def index(request: Request, user: User = Depends(check_user_exists)): - return paywall_renderer().TemplateResponse( - "paywall/index.html", {"request": request, "user": user.dict()} - ) - - -@paywall_ext.get("/{paywall_id}") -async def display(request: Request, paywall_id): - paywall = await get_paywall(paywall_id) - if not paywall: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="Paywall does not exist." - ) - return paywall_renderer().TemplateResponse( - "paywall/display.html", {"request": request, "paywall": paywall} - ) diff --git a/lnbits/extensions/paywall/views_api.py b/lnbits/extensions/paywall/views_api.py deleted file mode 100644 index 26480e01..00000000 --- a/lnbits/extensions/paywall/views_api.py +++ /dev/null @@ -1,105 +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.core.services import check_transaction_status, create_invoice -from lnbits.decorators import WalletTypeInfo, get_key_type - -from . import paywall_ext -from .crud import create_paywall, delete_paywall, get_paywall, get_paywalls -from .models import CheckPaywallInvoice, CreatePaywall, CreatePaywallInvoice - - -@paywall_ext.get("/api/v1/paywalls") -async def api_paywalls( - wallet: WalletTypeInfo = Depends(get_key_type), all_wallets: bool = Query(False) -): - wallet_ids = [wallet.wallet.id] - - if all_wallets: - user = await get_user(wallet.wallet.user) - wallet_ids = user.wallet_ids if user else [] - - return [paywall.dict() for paywall in await get_paywalls(wallet_ids)] - - -@paywall_ext.post("/api/v1/paywalls") -async def api_paywall_create( - data: CreatePaywall, wallet: WalletTypeInfo = Depends(get_key_type) -): - paywall = await create_paywall(wallet_id=wallet.wallet.id, data=data) - return paywall.dict() - - -@paywall_ext.delete("/api/v1/paywalls/{paywall_id}") -async def api_paywall_delete( - paywall_id, wallet: WalletTypeInfo = Depends(get_key_type) -): - paywall = await get_paywall(paywall_id) - - if not paywall: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="Paywall does not exist." - ) - - if paywall.wallet != wallet.wallet.id: - raise HTTPException( - status_code=HTTPStatus.FORBIDDEN, detail="Not your paywall." - ) - - await delete_paywall(paywall_id) - return "", HTTPStatus.NO_CONTENT - - -@paywall_ext.post("/api/v1/paywalls/invoice/{paywall_id}") -async def api_paywall_create_invoice( - data: CreatePaywallInvoice, paywall_id: str = Query(None) -): - paywall = await get_paywall(paywall_id) - assert paywall - if data.amount < paywall.amount: - raise HTTPException( - status_code=HTTPStatus.BAD_REQUEST, - detail=f"Minimum amount is {paywall.amount} sat.", - ) - try: - amount = data.amount if data.amount > paywall.amount else paywall.amount - payment_hash, payment_request = await create_invoice( - wallet_id=paywall.wallet, - amount=amount, - memo=f"{paywall.memo}", - extra={"tag": "paywall"}, - ) - except Exception as e: - raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)) - - return {"payment_hash": payment_hash, "payment_request": payment_request} - - -@paywall_ext.post("/api/v1/paywalls/check_invoice/{paywall_id}") -async def api_paywal_check_invoice( - data: CheckPaywallInvoice, paywall_id: str = Query(None) -): - paywall = await get_paywall(paywall_id) - payment_hash = data.payment_hash - if not paywall: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="Paywall does not exist." - ) - try: - status = await check_transaction_status(paywall.wallet, payment_hash) - is_paid = not status.pending - except Exception: - return {"paid": False} - - if is_paid: - wallet = await get_wallet(paywall.wallet) - assert wallet - payment = await wallet.get_payment(payment_hash) - assert payment - await payment.set_pending(False) - - return {"paid": True, "url": paywall.url, "remembers": paywall.remembers} - return {"paid": False}