Files
lnbits/lnbits/extensions/twitchalerts/views_api.py
T
2021-06-28 17:18:35 +02:00

255 lines
8.1 KiB
Python

from quart import g, redirect, request, jsonify
from http import HTTPStatus
from lnbits.decorators import api_validate_post_request, api_check_wallet_key
from lnbits.core.crud import get_wallet, get_user
from . import twitchalerts_ext
from .crud import (
get_charge_details,
create_donation,
post_donation,
get_donation,
get_donations,
delete_donation,
create_service,
get_service,
get_services,
authenticate_service,
update_donation,
update_service
)
from ..satspay.crud import create_charge, get_charge
@twitchalerts_ext.route("/api/v1/services", methods=["POST"])
@api_check_wallet_key("invoice")
@api_validate_post_request(
schema={
"twitchuser": {"type": "string", "required": True},
"client_id": {"type": "string", "required": True},
"client_secret": {"type": "string", "required": True},
"wallet": {"type": "string", "required": True},
"servicename": {"type": "string", "required": True},
"onchain": {"type": "string"}
}
)
async def api_create_service():
"""Create a service, which holds data about how/where to post donations"""
service = await create_service(**g.data)
wallet = await get_wallet(service.wallet)
user = wallet.user
redirect_url = request.scheme + "://" + request.headers["Host"]
redirect_url += f"/twitchalerts/?usr={user}&created={str(service.id)}"
return redirect(redirect_url)
@twitchalerts_ext.route("/api/v1/getaccess/<service_id>", methods=["GET"])
async def api_get_access(service_id):
service = await get_service(service_id)
if service:
uri_base = request.scheme + "://"
uri_base += request.headers["Host"] + "/twitchalerts/api/v1"
redirect_uri = uri_base + f"/authenticate/{service_id}"
params = {
"response_type": "code",
"client_id": service.client_id,
"redirect_uri": redirect_uri,
"scope": "donations.create",
"state": service.state
}
endpoint_url = "https://streamlabs.com/api/v1.0/authorize/?"
querystring = "&".join(
[f"{key}={value}" for key, value in params.items()]
)
redirect_url = endpoint_url + querystring
return redirect(redirect_url)
else:
return (
jsonify({"message": "Service does not exist!"}),
HTTPStatus.BAD_REQUEST
)
@twitchalerts_ext.route("/api/v1/authenticate/<service_id>", methods=["GET"])
async def api_authenticate_service(service_id):
code = request.args.get('code')
state = request.args.get('state')
service = await get_service(service_id)
if service.state != state:
return (
jsonify({"message": "State doesn't match!"}),
HTTPStatus.BAD_Request
)
redirect_uri = request.scheme + "://" + request.headers["Host"]
redirect_uri += f"/twitchalerts/api/v1/authenticate/{service_id}"
url, success = await authenticate_service(service_id, code, redirect_uri)
if success:
return redirect(url)
else:
return (
jsonify({"message": "Service already authenticated!"}),
HTTPStatus.BAD_REQUEST
)
@twitchalerts_ext.route("/api/v1/donations", methods=["POST"])
@api_check_wallet_key("invoice")
@api_validate_post_request(
schema={
"name": {"type": "string"},
"sats": {"type": "integer", "required": True},
"service": {"type": "integer", "required": True},
"cur_code": {"type": "string", "required": True},
"amount": {"type": "float", "required": True}
}
)
async def api_create_donation():
"""Takes data from donation form and creates+returns SatsPay charge"""
webhook_base = request.scheme + "://" + request.headers["Host"]
service_id = g.data["service"]
service = await get_service(service_id)
charge_details = await get_charge_details(service.id)
name = g.data.get("name", "Anonymous")
charge = await create_charge(
amount=g.data["sats"],
completelink=f"https://twitch.tv/{service.twitchuser}",
completelinktext="Back to Stream!",
webhook=webhook_base + "/twitchalerts/api/v1/postdonation",
**charge_details)
await create_donation(
id=charge.id,
wallet=service.wallet,
name=name,
cur_code=g.data["cur_code"],
sats=g.data["sats"],
amount=g.data["amount"],
service=g.data["service"],
)
return redirect(f"/satspay/{charge.id}")
@twitchalerts_ext.route("/api/v1/postdonation", methods=["POST"])
@api_validate_post_request(
schema={
"id": {"type": "string", "required": True},
}
)
async def api_post_donation():
"""Posts a paid donation to Stremalabs/StreamElements.
This endpoint acts as a webhook for the SatsPayServer extension."""
data = await request.get_json(force=True)
donation_id = data.get("id", "No ID")
charge = await get_charge(donation_id)
if charge and charge.paid:
return await post_donation(donation_id)
else:
return (
jsonify({"message": "Not a paid charge!"}),
HTTPStatus.BAD_REQUEST
)
@twitchalerts_ext.route("/api/v1/services", methods=["GET"])
@api_check_wallet_key("invoice")
async def api_get_services():
wallet_ids = (await get_user(g.wallet.user)).wallet_ids
services = []
for wallet_id in wallet_ids:
services += await get_services(wallet_id)
return (
jsonify([
service._asdict() for service in services
] if services else []),
HTTPStatus.OK,
)
@twitchalerts_ext.route("/api/v1/donations", methods=["GET"])
@api_check_wallet_key("invoice")
async def api_get_donations():
wallet_ids = (await get_user(g.wallet.user)).wallet_ids
donations = []
for wallet_id in wallet_ids:
donations += await get_donations(wallet_id)
return (
jsonify([
donation._asdict() for donation in donations
] if donations else []),
HTTPStatus.OK,
)
@twitchalerts_ext.route("/api/v1/donations/<donation_id>", methods=["PUT"])
@api_check_wallet_key("invoice")
async def api_update_donation(donation_id=None):
if donation_id:
donation = await get_donation(donation_id)
if not donation:
return (
jsonify({"message": "Donation does not exist."}),
HTTPStatus.NOT_FOUND
)
if donation.wallet != g.wallet.id:
return (
jsonify({"message": "Not your donation."}),
HTTPStatus.FORBIDDEN
)
donation = await update_donation(donation_id, **g.data)
else:
return (
jsonify({"message": "No donation ID specified"}),
HTTPStatus.BAD_REQUEST
)
return jsonify(donation._asdict()), HTTPStatus.CREATED
@twitchalerts_ext.route("/api/v1/services/<service_id>", methods=["PUT"])
@api_check_wallet_key("invoice")
async def api_update_service(service_id=None):
if service_id:
service = await get_service(service_id)
if not service:
return (
jsonify({"message": "Service does not exist."}),
HTTPStatus.NOT_FOUND
)
if service.wallet != g.wallet.id:
return (
jsonify({"message": "Not your service."}),
HTTPStatus.FORBIDDEN
)
service = await update_service(service_id, **g.data)
else:
return (
jsonify({"message": "No service ID specified"}),
HTTPStatus.BAD_REQUEST
)
return jsonify(service._asdict()), HTTPStatus.CREATED
@twitchalerts_ext.route("/api/v1/donations/<donation_id>", methods=["DELETE"])
@api_check_wallet_key("invoice")
async def api_delete_donation(donation_id):
donation = await get_donation(donation_id)
if not donation:
return (
jsonify({"message": "No donation with this ID!"}),
HTTPStatus.NOT_FOUND
)
if donation.wallet != g.wallet.id:
return (
jsonify({"message": "Not authorized to delete this donation!"}),
HTTPStatus.FORBIDDEN
)
await delete_donation(donation_id)
return "", HTTPStatus.NO_CONTENT