Merge remote-tracking branch 'origin/main' into main

This commit is contained in:
benarc 2022-03-07 04:26:40 +00:00
commit 72f2ec0be8
12 changed files with 89 additions and 38 deletions

View File

@ -84,18 +84,19 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
def check_funding_source(app: FastAPI) -> None:
@app.on_event("startup")
async def check_wallet_status():
error_message, balance = await WALLET.status()
if error_message:
while True:
error_message, balance = await WALLET.status()
if not error_message:
break
warnings.warn(
f" × The backend for {WALLET.__class__.__name__} isn't working properly: '{error_message}'",
RuntimeWarning,
)
sys.exit(4)
else:
print(
f" ✔️ {WALLET.__class__.__name__} seems to be connected and with a balance of {balance} msat."
)
print("Retrying connection to backend in 5 seconds...")
await asyncio.sleep(5)
print(
f" ✔️ {WALLET.__class__.__name__} seems to be connected and with a balance of {balance} msat."
)
def register_routes(app: FastAPI) -> None:

View File

@ -24,24 +24,24 @@ from lnbits.decorators import (
WalletTypeInfo,
get_key_type,
)
from lnbits.helpers import url_for
from lnbits.helpers import url_for, urlsafe_short_hash
from lnbits.requestvars import g
from lnbits.settings import LNBITS_ADMIN_USERS, LNBITS_SITE_TITLE
from lnbits.utils.exchange_rates import (
currencies,
fiat_amount_as_satoshis,
satoshis_amount_as_fiat,
)
from lnbits.settings import LNBITS_SITE_TITLE
from .. import core_app, db
from ..crud import (
create_payment,
get_payments,
get_standalone_payment,
save_balance_check,
update_wallet,
create_payment,
get_wallet,
save_balance_check,
update_payment_status,
update_wallet,
)
from ..services import (
InvoiceFailure,
@ -52,8 +52,6 @@ from ..services import (
perform_lnurlauth,
)
from ..tasks import api_invoice_listeners
from lnbits.settings import LNBITS_ADMIN_USERS
from lnbits.helpers import urlsafe_short_hash
@core_app.get("/api/v1/wallet")
@ -503,12 +501,13 @@ async def api_lnurlscan(code: str):
@core_app.post("/api/v1/payments/decode")
async def api_payments_decode(data: str = Query(None)):
print(data)
try:
if data["data"][:5] == "LNURL":
url = lnurl.decode(data["data"])
if data[:5] == "LNURL":
url = lnurl.decode(data)
return {"domain": url}
else:
invoice = bolt11.decode(data["data"])
invoice = bolt11.decode(data)
return {
"payment_hash": invoice.payment_hash,
"amount_msat": invoice.amount_msat,

View File

@ -88,7 +88,7 @@ async def get_copilot(copilot_id: str) -> Copilots:
async def get_copilots(user: str) -> List[Copilots]:
rows = await db.fetchall(
"SELECT * FROM copilot.newer_copilots WHERE user = ?", (user,)
'SELECT * FROM copilot.newer_copilots WHERE "user" = ?', (user,)
)
return [Copilots(**row) for row in rows]

View File

@ -76,7 +76,7 @@ async def delete_ticket(payment_hash: str) -> None:
async def delete_event_tickets(event_id: str) -> None:
await db.execute("DELETE FROM events.tickets WHERE event = ?", (event_id,))
await db.execute("DELETE FROM events.ticket WHERE event = ?", (event_id,))
# EVENTS

View File

@ -12,7 +12,7 @@ async def create_jukebox(
juke_id = urlsafe_short_hash()
result = await db.execute(
"""
INSERT INTO jukebox.jukebox (id, user, title, wallet, sp_user, sp_secret, sp_access_token, sp_refresh_token, sp_device, sp_playlists, price, profit)
INSERT INTO jukebox.jukebox (id, "user", title, wallet, sp_user, sp_secret, sp_access_token, sp_refresh_token, sp_device, sp_playlists, price, profit)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
@ -41,6 +41,7 @@ async def update_jukebox(
q = ", ".join([f"{field[0]} = ?" for field in data])
items = [f"{field[1]}" for field in data]
items.append(juke_id)
q = q.replace("user", '"user"', 1) # hack to make user be "user"!
await db.execute(f"UPDATE jukebox.jukebox SET {q} WHERE id = ?", (items))
row = await db.fetchone("SELECT * FROM jukebox.jukebox WHERE id = ?", (juke_id,))
return Jukebox(**row) if row else None
@ -57,11 +58,11 @@ async def get_jukebox_by_user(user: str) -> Optional[Jukebox]:
async def get_jukeboxs(user: str) -> List[Jukebox]:
rows = await db.fetchall("SELECT * FROM jukebox.jukebox WHERE user = ?", (user,))
rows = await db.fetchall('SELECT * FROM jukebox.jukebox WHERE "user" = ?', (user,))
for row in rows:
if row.sp_playlists == None:
await delete_jukebox(row.id)
rows = await db.fetchall("SELECT * FROM jukebox.jukebox WHERE user = ?", (user,))
rows = await db.fetchall('SELECT * FROM jukebox.jukebox WHERE "user" = ?', (user,))
return [Jukebox(**row) for row in rows]

View File

@ -75,7 +75,6 @@ async def api_check_credentials_check(
juke_id: str = Query(None), wallet: WalletTypeInfo = Depends(require_admin_key)
):
jukebox = await get_jukebox(juke_id)
return jukebox
@ -442,7 +441,7 @@ async def api_get_jukebox_currently(
token = await api_get_token(juke_id)
if token == False:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="INvoice not paid"
status_code=HTTPStatus.FORBIDDEN, detail="Invoice not paid"
)
elif retry:
raise HTTPException(
@ -456,5 +455,5 @@ async def api_get_jukebox_currently(
)
except:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Something went wrong"
status_code=HTTPStatus.NOT_FOUND, detail="Something went wrong, or no song is playing yet"
)

View File

@ -117,9 +117,10 @@
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width></q-th>
<q-th auto-width></q-th>
<q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label }}
{{ col.label }}
</q-th>
</q-tr>
</template>
@ -136,9 +137,19 @@
:href="'mailto:' + props.row.email"
></q-btn>
</q-td>
<q-td auto-width>
<q-btn
unelevated
dense
size="xs"
icon="launch"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
@click="ticketCard(props)"
><q-tooltip> Click to show ticket </q-tooltip></q-btn>
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
{{ col.label == "Ticket" ? col.value.length > 20 ? `${col.value.substring(0, 20)}...` : col.value : col.value }}
</q-td>
<q-td auto-width>
@ -249,6 +260,29 @@
</q-form>
</q-card>
</q-dialog>
<!-- Read Ticket Dialog -->
<q-dialog v-model="ticketDialog.show" position="top">
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
{% raw %}
<q-card-section>
<h4 class="text-subtitle1 q-my-none">
<i>{{this.ticketDialog.data.name}}</i> sent a ticket
</h4>
<div v-if="this.ticketDialog.data.email">
<small>{{this.ticketDialog.data.email}}</small>
</div>
<small>{{this.ticketDialog.data.date}}</small>
</q-card-section>
<q-separator></q-separator>
<q-card-section>
<p>{{this.ticketDialog.data.content}}</p>
</q-card-section>
{% endraw %}
<q-card-actions align="right">
<q-btn flat label="CLOSE" color="primary" v-close-popup />
</q-card-actions>
</q-card>
</q-dialog>
</div>
{% endblock %} {% block scripts %} {{ window_vars(user) }}
<script>
@ -318,6 +352,10 @@
formDialog: {
show: false,
data: {flatrate: false}
},
ticketDialog: {
show: false,
data: {}
}
}
},
@ -372,6 +410,16 @@
})
})
},
ticketCard(ticket){
this.ticketDialog.show = true
let {date, email, ltext, name} = ticket.row
this.ticketDialog.data = {
date,
email,
content: ltext,
name
}
},
exportticketsCSV: function () {
LNbits.utils.exportCSV(this.ticketsTable.columns, this.tickets)
},
@ -421,12 +469,13 @@
},
updateformDialog: function (formId) {
var link = _.findWhere(this.forms, {id: formId})
console.log("LINK", link)
this.formDialog.data.id = link.id
this.formDialog.data.wallet = link.wallet
this.formDialog.data.name = link.name
this.formDialog.data.description = link.description
this.formDialog.data.flatrate = link.flatrate
this.formDialog.data.flatrate = Boolean(link.flatrate)
this.formDialog.data.amount = link.amount
this.formDialog.show = true
},

View File

@ -60,7 +60,7 @@ class Service(BaseModel):
onchain: Optional[str]
servicename: str # Currently, this will just always be "Streamlabs"
authenticated: bool # Whether a token (see below) has been acquired yet
token: Optional[int] # The token with which to authenticate requests
token: Optional[str] # The token with which to authenticate requests
@classmethod
def from_row(cls, row: Row) -> "Service":

View File

@ -62,7 +62,7 @@
donationDialog: {
show: false,
data: {
name: '',
name: null,
sats: '',
message: ''
}

View File

@ -7,6 +7,7 @@ from starlette.responses import RedirectResponse
from lnbits.core.crud import get_user
from lnbits.decorators import WalletTypeInfo, get_key_type
from lnbits.extensions.satspay.models import CreateCharge
from lnbits.extensions.streamalerts.models import (
CreateDonation,
CreateService,
@ -113,17 +114,18 @@ async def api_create_donation(data: CreateDonation, request: Request):
service_id = data.service
service = await get_service(service_id)
charge_details = await get_charge_details(service.id)
name = data.name
name = data.name if data.name else "Anonymous"
description = f"{sats} sats donation from {name} to {service.twitchuser}"
charge = await create_charge(
create_charge_data = CreateCharge(
amount=sats,
completelink=f"https://twitch.tv/{service.twitchuser}",
completelinktext="Back to Stream!",
webhook=webhook_base + "/streamalerts/api/v1/postdonation",
description=description,
**charge_details,
**charge_details
)
charge = await create_charge(user=charge_details["user"], data=create_charge_data)
await create_donation(
id=charge.id,
wallet=service.wallet,

View File

@ -1,5 +1,5 @@
from sqlite3 import Row
from typing import NamedTuple, Optional
from typing import Optional
from fastapi.param_functions import Query
from pydantic import BaseModel
@ -26,7 +26,7 @@ class createTip(BaseModel):
message: str = ""
class Tip(NamedTuple):
class Tip(BaseModel):
"""A Tip represents a single donation"""
id: str # This ID always corresponds to a satspay charge ID
@ -55,7 +55,7 @@ class createTips(BaseModel):
message: str
class TipJar(NamedTuple):
class TipJar(BaseModel):
"""A TipJar represents a user's tip jar"""
id: int

View File

@ -112,7 +112,7 @@ async def api_get_addresses(wallet_id, w: WalletTypeInfo = Depends(get_key_type)
async def api_update_mempool(
endpoint: str = Query(...), w: WalletTypeInfo = Depends(require_admin_key)
):
mempool = await update_mempool(endpoint, user=w.wallet.user)
mempool = await update_mempool(**{"endpoint": endpoint}, user=w.wallet.user)
return mempool.dict()