Further customize copied code
This commit is contained in:
parent
3f353a6eae
commit
39844b257b
6 changed files with 177 additions and 58 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue