Further customize copied code

This commit is contained in:
Fitti 2021-06-28 17:18:35 +02:00
parent 3f353a6eae
commit 39844b257b
6 changed files with 177 additions and 58 deletions

View file

@ -31,6 +31,7 @@ async def get_charge_details(service_id):
async def create_donation( async def create_donation(
id: str, id: str,
wallet: str,
cur_code: str, cur_code: str,
sats: int, sats: int,
amount: float, amount: float,
@ -43,6 +44,7 @@ async def create_donation(
""" """
INSERT INTO Donations ( INSERT INTO Donations (
id, id,
wallet,
name, name,
message, message,
cur_code, cur_code,
@ -51,10 +53,11 @@ async def create_donation(
service, service,
posted posted
) )
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
""", """,
( (
id, id,
wallet,
name, name,
message, message,
cur_code, cur_code,
@ -223,14 +226,10 @@ async def get_donation(donation_id: str) -> Optional[Donation]:
async def get_donations(wallet_id: str) -> Optional[list]: async def get_donations(wallet_id: str) -> Optional[list]:
services = await get_services(wallet_id) rows = await db.fetchall(
service_ids = [service.id for service in services] "SELECT * FROM Donations WHERE wallet = ?",
rows = [] (wallet_id,)
for service_id in service_ids: )
rows.append(await db.fetchall(
"SELECT * FROM Donations WHERE service = ?",
(service_id,)
))
return [Donation.from_row(row) for row in rows] if rows else None return [Donation.from_row(row) for row in rows] if rows else None
@ -240,3 +239,23 @@ async def delete_donation(donation_id: str) -> None:
(donation_id,) (donation_id,)
) )
await delete_charge(donation_id) await delete_charge(donation_id)
async def update_donation(donation_id: str, **kwargs) -> Donation:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
await db.execute(f"UPDATE form SET {q} WHERE id = ?", (*kwargs.values(),
donation_id))
row = await db.fetchone("SELECT * FROM Donations WHERE id = ?",
(donation_id,))
assert row, "Newly updated donation couldn't be retrieved"
return Donation(**row)
async def update_service(service_id: str, **kwargs) -> Donation:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
await db.execute(f"UPDATE form SET {q} WHERE id = ?", (*kwargs.values(),
service_id))
row = await db.fetchone("SELECT * FROM Services WHERE id = ?",
(service_id,))
assert row, "Newly updated service couldn't be retrieved"
return Service(**row)

View file

@ -21,6 +21,7 @@ async def m001_initial(db):
""" """
CREATE TABLE IF NOT EXISTS Donations ( CREATE TABLE IF NOT EXISTS Donations (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
wallet TEXT NOT NULL,
name TEXT NOT NULL, name TEXT NOT NULL,
message TEXT NOT NULL, message TEXT NOT NULL,
cur_code TEXT NOT NULL, cur_code TEXT NOT NULL,

View file

@ -4,6 +4,7 @@ from typing import NamedTuple, Optional
class Donation(NamedTuple): class Donation(NamedTuple):
id: str id: str
wallet: str
name: str name: str
message: str message: str
cur_code: str cur_code: str

View file

@ -1,22 +1,17 @@
<q-expansion-item
group="extras"
icon="swap_vertical_circle"
label="Info"
:content-inset-level="0.5"
>
<q-card> <q-card>
<q-card-section> <q-card-section>
<h5 class="text-subtitle1 q-my-none"> <h4 class="text-subtitle1 q-my-none">
Twitch Alerts: Integrate Bitcoin into your stream alerts! Twitch Alerts: Integrate Bitcoin into your stream alerts!
</h5> </h4>
<p> <p>
Accept Bitcoin donations on Twitch, and integrate them into your alerts. Accept Bitcoin donations on Twitch, and integrate them into your alerts.
Present your viewers with a simple donation page, and add those donations Present your viewers with a simple donation page, and add those donations
to Streamlabs to play alerts on your stream!<br /> to Streamlabs to play alerts on your stream!<br />
For detailed setup instructions, check out <a href="https://github.com/Fittiboy/bitcoin-on-twitch">
this guide!</a><br />
<small> <small>
Created by, <a href="https://github.com/Fittiboy">Fitti</a></small Created by, <a href="https://github.com/Fittiboy">Fitti</a></small
> >
</p> </p>
</q-card-section> </q-card-section>
</q-card> </q-card>
</q-expansion-item>

View file

@ -177,31 +177,30 @@
<q-input <q-input
filled filled
dense dense
v-model.trim="formDialog.data.username" v-model.trim="formDialog.data.twitchuser"
type="name" type="name"
label="Twitch Username *" label="Twitch Username *"
></q-input> ></q-input>
<q-input <q-select
filled filled
dense dense
v-model.trim="formDialog.data.service" emit-value
type="text" v-model="formDialog.data.servicename"
:options="servicenames"
label="Streamlabs" label="Streamlabs"
hint="The service you use for alerts. (Currently only Streamlabs)" hint="The service you use for alerts. (Currently only Streamlabs)"
readonly ></q-select>
placeholder="Streamlabs"
></q-input>
<q-input <q-input
filled filled
dense dense
v-model.trim="formDialog.data.clientid" v-model.trim="formDialog.data.client_id"
type="name" type="name"
label="Client ID *" label="Client ID *"
></q-input> ></q-input>
<q-input <q-input
filled filled
dense dense
v-model.trim="formDialog.data.clientsecret" v-model.trim="formDialog.data.client_secret"
type="name" type="name"
label="Client Secret *" label="Client Secret *"
></q-input> ></q-input>
@ -218,7 +217,7 @@
v-else v-else
unelevated unelevated
color="deep-purple" color="deep-purple"
:disable="formDialog.data.clientid == null || formDialog.data.clientsecret == 0 || formDialog.data.username == null" :disable="formDialog.data.client_id == null || formDialog.data.client_secret == 0 || formDialog.data.twitchuser == null"
type="submit" type="submit"
>Create Service</q-btn >Create Service</q-btn
> >
@ -247,30 +246,37 @@
mixins: [windowMixin], mixins: [windowMixin],
data: function() { data: function() {
return { return {
servicenames: ["Streamlabs"],
services: [], services: [],
donations: [], donations: [],
servicesTable: { servicesTable: {
columns: [ columns: [
{name: 'id', align: 'left', label: 'ID', field: 'id'}, {name: 'id', align: 'left', label: 'ID', field: 'id'},
{name: 'username', align: 'left', label: 'Twitch Username', field: 'username'}, {name: 'twitchuser', align: 'left', label: 'Twitch Username', field: 'twitchuser'},
{name: 'wallet', align: 'left', label: 'Wallet', field: 'wallet'}, {name: 'wallet', align: 'left', label: 'Wallet', field: 'wallet'},
{ {
name: 'service', name: 'servicename',
align: 'left', align: 'left',
label: 'Service', label: 'Service',
field: 'service' field: 'servicename'
}, },
{ {
name: 'clientid', name: 'client_id',
align: 'left', align: 'left',
label: 'Client ID', label: 'Client ID',
field: 'clientid' field: 'client_id'
}, },
{ {
name: 'clientsecret', name: 'client_secret',
align: 'left', align: 'left',
label: 'Client Secret', label: 'Client Secret',
field: 'clientsecret' field: 'client_secret'
},
{
name: 'authenticated',
align: 'left',
label: 'Authenticated',
field: 'authenticated'
} }
], ],
pagination: { pagination: {
@ -310,17 +316,17 @@
}) })
}) })
}, },
deleteDonation: function(ticketId) { deleteDonation: function(donationId) {
var self = this var self = this
var donations = _.findWhere(this.donations, {id: ticketId}) var donations = _.findWhere(this.donations, {id: donationId})
LNbits.utils LNbits.utils
.confirmDialog('Are you sure you want to delete this ticket') .confirmDialog('Are you sure you want to delete this donation?')
.onOk(function() { .onOk(function() {
LNbits.api LNbits.api
.request( .request(
'DELETE', 'DELETE',
'/twitchalerts/api/v1/donations/' + ticketId, '/twitchalerts/api/v1/donations/' + donationId,
_.findWhere(self.g.user.wallets, {id: donations.wallet}).inkey _.findWhere(self.g.user.wallets, {id: donations.wallet}).inkey
) )
.then(function(response) { .then(function(response) {
@ -343,7 +349,7 @@
LNbits.api LNbits.api
.request( .request(
'GET', 'GET',
'/twitchalerts/api/v1/services?all_wallets', '/twitchalerts/api/v1/services',
this.g.user.wallets[0].inkey this.g.user.wallets[0].inkey
) )
.then(function(response) { .then(function(response) {

View file

@ -9,15 +9,20 @@ from .crud import (
get_charge_details, get_charge_details,
create_donation, create_donation,
post_donation, post_donation,
get_donation,
get_donations, get_donations,
delete_donation,
create_service, create_service,
get_service, get_service,
authenticate_service get_services,
authenticate_service,
update_donation,
update_service
) )
from ..satspay.crud import create_charge, get_charge from ..satspay.crud import create_charge, get_charge
@twitchalerts_ext.route("/api/v1/createservice", methods=["POST"]) @twitchalerts_ext.route("/api/v1/services", methods=["POST"])
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
@api_validate_post_request( @api_validate_post_request(
schema={ schema={
@ -88,7 +93,7 @@ async def api_authenticate_service(service_id):
) )
@twitchalerts_ext.route("/api/v1/createdonation", methods=["POST"]) @twitchalerts_ext.route("/api/v1/donations", methods=["POST"])
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
@api_validate_post_request( @api_validate_post_request(
schema={ schema={
@ -114,6 +119,7 @@ async def api_create_donation():
**charge_details) **charge_details)
await create_donation( await create_donation(
id=charge.id, id=charge.id,
wallet=service.wallet,
name=name, name=name,
cur_code=g.data["cur_code"], cur_code=g.data["cur_code"],
sats=g.data["sats"], sats=g.data["sats"],
@ -145,13 +151,104 @@ async def api_post_donation():
) )
@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"]) @twitchalerts_ext.route("/api/v1/donations", methods=["GET"])
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
async def api_get_donations(): async def api_get_donations():
wallet_ids = (await get_user(g.wallet.user)).wallet_ids wallet_ids = (await get_user(g.wallet.user)).wallet_ids
donations = []
for wallet_id in wallet_ids:
donations += await get_donations(wallet_id)
return ( return (
jsonify([ jsonify([
donation._asdict() for donation in await get_donations(wallet_ids) donation._asdict() for donation in donations
]), ] if donations else []),
HTTPStatus.OK, 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