parent
048aff3db4
commit
a3619d40c6
5 changed files with 149 additions and 156 deletions
|
|
@ -3,7 +3,7 @@ from .funding_source import (
|
||||||
switch_to_voidwallet,
|
switch_to_voidwallet,
|
||||||
)
|
)
|
||||||
from .lnurl import perform_lnurlauth, redeem_lnurl_withdraw
|
from .lnurl import perform_lnurlauth, redeem_lnurl_withdraw
|
||||||
from .notifications import enqueue_notification
|
from .notifications import enqueue_notification, send_payment_notification
|
||||||
from .payments import (
|
from .payments import (
|
||||||
calculate_fiat_amounts,
|
calculate_fiat_amounts,
|
||||||
check_transaction_status,
|
check_transaction_status,
|
||||||
|
|
@ -12,7 +12,6 @@ from .payments import (
|
||||||
fee_reserve,
|
fee_reserve,
|
||||||
fee_reserve_total,
|
fee_reserve_total,
|
||||||
pay_invoice,
|
pay_invoice,
|
||||||
send_payment_notification,
|
|
||||||
service_fee,
|
service_fee,
|
||||||
update_pending_payments,
|
update_pending_payments,
|
||||||
update_wallet_balance,
|
update_wallet_balance,
|
||||||
|
|
@ -40,6 +39,7 @@ __all__ = [
|
||||||
"perform_lnurlauth",
|
"perform_lnurlauth",
|
||||||
# notifications
|
# notifications
|
||||||
"enqueue_notification",
|
"enqueue_notification",
|
||||||
|
"send_payment_notification",
|
||||||
# payments
|
# payments
|
||||||
"calculate_fiat_amounts",
|
"calculate_fiat_amounts",
|
||||||
"check_transaction_status",
|
"check_transaction_status",
|
||||||
|
|
@ -48,7 +48,6 @@ __all__ = [
|
||||||
"fee_reserve",
|
"fee_reserve",
|
||||||
"fee_reserve_total",
|
"fee_reserve_total",
|
||||||
"pay_invoice",
|
"pay_invoice",
|
||||||
"send_payment_notification",
|
|
||||||
"service_fee",
|
"service_fee",
|
||||||
"update_pending_payments",
|
"update_pending_payments",
|
||||||
"update_wallet_balance",
|
"update_wallet_balance",
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,27 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import json
|
||||||
|
from http import HTTPStatus
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
from py_vapid import Vapid
|
||||||
|
from pywebpush import WebPushException, webpush
|
||||||
|
|
||||||
|
from lnbits.core.crud import (
|
||||||
|
delete_webpush_subscriptions,
|
||||||
|
get_webpush_subscriptions_for_user,
|
||||||
|
mark_webhook_sent,
|
||||||
|
)
|
||||||
|
from lnbits.core.models import Payment, Wallet
|
||||||
from lnbits.core.models.notifications import (
|
from lnbits.core.models.notifications import (
|
||||||
NOTIFICATION_TEMPLATES,
|
NOTIFICATION_TEMPLATES,
|
||||||
NotificationMessage,
|
NotificationMessage,
|
||||||
NotificationType,
|
NotificationType,
|
||||||
)
|
)
|
||||||
from lnbits.core.services.nostr import fetch_nip5_details, send_nostr_dm
|
from lnbits.core.services.nostr import fetch_nip5_details, send_nostr_dm
|
||||||
|
from lnbits.core.services.websockets import websocket_manager
|
||||||
|
from lnbits.helpers import check_callback_url
|
||||||
from lnbits.settings import settings
|
from lnbits.settings import settings
|
||||||
from lnbits.utils.nostr import normalize_private_key
|
from lnbits.utils.nostr import normalize_private_key
|
||||||
|
|
||||||
|
|
@ -123,3 +135,134 @@ def _notification_message_to_text(
|
||||||
text = meesage_value
|
text = meesage_value
|
||||||
text = f"""[{settings.lnbits_site_title}]\n{text}"""
|
text = f"""[{settings.lnbits_site_title}]\n{text}"""
|
||||||
return message_type, text
|
return message_type, text
|
||||||
|
|
||||||
|
|
||||||
|
async def dispatch_webhook(payment: Payment):
|
||||||
|
"""
|
||||||
|
Dispatches the webhook to the webhook url.
|
||||||
|
"""
|
||||||
|
logger.debug("sending webhook", payment.webhook)
|
||||||
|
|
||||||
|
if not payment.webhook:
|
||||||
|
return await mark_webhook_sent(payment.payment_hash, -1)
|
||||||
|
|
||||||
|
headers = {"User-Agent": settings.user_agent}
|
||||||
|
async with httpx.AsyncClient(headers=headers) as client:
|
||||||
|
data = payment.dict()
|
||||||
|
try:
|
||||||
|
check_callback_url(payment.webhook)
|
||||||
|
r = await client.post(payment.webhook, json=data, timeout=40)
|
||||||
|
r.raise_for_status()
|
||||||
|
await mark_webhook_sent(payment.payment_hash, r.status_code)
|
||||||
|
except httpx.HTTPStatusError as exc:
|
||||||
|
await mark_webhook_sent(payment.payment_hash, exc.response.status_code)
|
||||||
|
logger.warning(
|
||||||
|
f"webhook returned a bad status_code: {exc.response.status_code} "
|
||||||
|
f"while requesting {exc.request.url!r}."
|
||||||
|
)
|
||||||
|
except httpx.RequestError:
|
||||||
|
await mark_webhook_sent(payment.payment_hash, -1)
|
||||||
|
logger.warning(f"Could not send webhook to {payment.webhook}")
|
||||||
|
|
||||||
|
|
||||||
|
async def send_payment_notification(wallet: Wallet, payment: Payment):
|
||||||
|
try:
|
||||||
|
await send_ws_payment_notification(wallet, payment)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Error sending websocket payment notification", e)
|
||||||
|
try:
|
||||||
|
send_chat_payment_notification(wallet, payment)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Error sending chat payment notification", e)
|
||||||
|
try:
|
||||||
|
await send_payment_push_notification(wallet, payment)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Error sending push payment notification", e)
|
||||||
|
|
||||||
|
if payment.webhook and not payment.webhook_status:
|
||||||
|
await dispatch_webhook(payment)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_ws_payment_notification(wallet: Wallet, payment: Payment):
|
||||||
|
# TODO: websocket message should be a clean payment model
|
||||||
|
# await websocket_manager.send_data(payment.json(), wallet.inkey)
|
||||||
|
# TODO: figure out why we send the balance with the payment here.
|
||||||
|
# cleaner would be to have a separate message for the balance
|
||||||
|
# and send it with the id of the wallet so wallets can subscribe to it
|
||||||
|
payment_notification = json.dumps(
|
||||||
|
{
|
||||||
|
"wallet_balance": wallet.balance,
|
||||||
|
# use pydantic json serialization to get the correct datetime format
|
||||||
|
"payment": json.loads(payment.json()),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
await websocket_manager.send_data(payment_notification, wallet.inkey)
|
||||||
|
await websocket_manager.send_data(payment_notification, wallet.adminkey)
|
||||||
|
|
||||||
|
await websocket_manager.send_data(
|
||||||
|
json.dumps({"pending": payment.pending}), payment.payment_hash
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def send_chat_payment_notification(wallet: Wallet, payment: Payment):
|
||||||
|
amount_sats = abs(payment.sat)
|
||||||
|
values: dict = {
|
||||||
|
"wallet_id": wallet.id,
|
||||||
|
"wallet_name": wallet.name,
|
||||||
|
"amount_sats": amount_sats,
|
||||||
|
"fiat_value_fmt": "",
|
||||||
|
}
|
||||||
|
if payment.extra.get("wallet_fiat_currency", None):
|
||||||
|
amount_fiat = payment.extra.get("wallet_fiat_amount", None)
|
||||||
|
currency = payment.extra.get("wallet_fiat_currency", None)
|
||||||
|
values["fiat_value_fmt"] = f"`{amount_fiat}`*{currency}* / "
|
||||||
|
|
||||||
|
if payment.is_out:
|
||||||
|
if amount_sats >= settings.lnbits_notification_outgoing_payment_amount_sats:
|
||||||
|
enqueue_notification(NotificationType.outgoing_payment, values)
|
||||||
|
else:
|
||||||
|
if amount_sats >= settings.lnbits_notification_incoming_payment_amount_sats:
|
||||||
|
enqueue_notification(NotificationType.incoming_payment, values)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_payment_push_notification(wallet: Wallet, payment: Payment):
|
||||||
|
subscriptions = await get_webpush_subscriptions_for_user(wallet.user)
|
||||||
|
|
||||||
|
amount = int(payment.amount / 1000)
|
||||||
|
|
||||||
|
title = f"LNbits: {wallet.name}"
|
||||||
|
body = f"You just received {amount} sat{'s'[:amount^1]}!"
|
||||||
|
|
||||||
|
if payment.memo:
|
||||||
|
body += f"\r\n{payment.memo}"
|
||||||
|
|
||||||
|
for subscription in subscriptions:
|
||||||
|
# todo: review permissions when user-id-only not allowed
|
||||||
|
# todo: replace all this logic with websockets?
|
||||||
|
url = f"https://{subscription.host}/wallet?usr={wallet.user}&wal={wallet.id}"
|
||||||
|
await send_push_notification(subscription, title, body, url)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_push_notification(subscription, title, body, url=""):
|
||||||
|
vapid = Vapid()
|
||||||
|
try:
|
||||||
|
logger.debug("sending push notification")
|
||||||
|
webpush(
|
||||||
|
json.loads(subscription.data),
|
||||||
|
json.dumps({"title": title, "body": body, "url": url}),
|
||||||
|
(
|
||||||
|
vapid.from_pem(bytes(settings.lnbits_webpush_privkey, "utf-8"))
|
||||||
|
if settings.lnbits_webpush_privkey
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
{"aud": "", "sub": "mailto:alan@lnbits.com"},
|
||||||
|
)
|
||||||
|
except WebPushException as e:
|
||||||
|
if e.response and e.response.status_code == HTTPStatus.GONE:
|
||||||
|
# cleanup unsubscribed or expired push subscriptions
|
||||||
|
await delete_webpush_subscriptions(subscription.endpoint)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"failed sending push notification: "
|
||||||
|
f"{e.response.text if e.response else e}"
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
@ -12,8 +11,6 @@ from loguru import logger
|
||||||
from lnbits.core.crud.payments import get_daily_stats
|
from lnbits.core.crud.payments import get_daily_stats
|
||||||
from lnbits.core.db import db
|
from lnbits.core.db import db
|
||||||
from lnbits.core.models import PaymentDailyStats, PaymentFilters
|
from lnbits.core.models import PaymentDailyStats, PaymentFilters
|
||||||
from lnbits.core.models.notifications import NotificationType
|
|
||||||
from lnbits.core.services.notifications import enqueue_notification
|
|
||||||
from lnbits.db import Connection, Filters
|
from lnbits.db import Connection, Filters
|
||||||
from lnbits.decorators import check_user_extension_access
|
from lnbits.decorators import check_user_extension_access
|
||||||
from lnbits.exceptions import InvoiceError, PaymentError
|
from lnbits.exceptions import InvoiceError, PaymentError
|
||||||
|
|
@ -45,7 +42,7 @@ from ..models import (
|
||||||
PaymentState,
|
PaymentState,
|
||||||
Wallet,
|
Wallet,
|
||||||
)
|
)
|
||||||
from .websockets import websocket_manager
|
from .notifications import send_payment_notification
|
||||||
|
|
||||||
|
|
||||||
async def pay_invoice(
|
async def pay_invoice(
|
||||||
|
|
@ -278,60 +275,6 @@ async def update_wallet_balance(
|
||||||
await internal_invoice_queue.put(payment.checking_id)
|
await internal_invoice_queue.put(payment.checking_id)
|
||||||
|
|
||||||
|
|
||||||
async def send_payment_notification(wallet: Wallet, payment: Payment):
|
|
||||||
try:
|
|
||||||
await send_ws_payment_notification(wallet, payment)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("Error sending websocket payment notification", e)
|
|
||||||
|
|
||||||
try:
|
|
||||||
send_chat_payment_notification(wallet, payment)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("Error sending chat payment notification", e)
|
|
||||||
|
|
||||||
|
|
||||||
async def send_ws_payment_notification(wallet: Wallet, payment: Payment):
|
|
||||||
# TODO: websocket message should be a clean payment model
|
|
||||||
# await websocket_manager.send_data(payment.json(), wallet.inkey)
|
|
||||||
# TODO: figure out why we send the balance with the payment here.
|
|
||||||
# cleaner would be to have a separate message for the balance
|
|
||||||
# and send it with the id of the wallet so wallets can subscribe to it
|
|
||||||
payment_notification = json.dumps(
|
|
||||||
{
|
|
||||||
"wallet_balance": wallet.balance,
|
|
||||||
# use pydantic json serialization to get the correct datetime format
|
|
||||||
"payment": json.loads(payment.json()),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
await websocket_manager.send_data(payment_notification, wallet.inkey)
|
|
||||||
await websocket_manager.send_data(payment_notification, wallet.adminkey)
|
|
||||||
|
|
||||||
await websocket_manager.send_data(
|
|
||||||
json.dumps({"pending": payment.pending}), payment.payment_hash
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def send_chat_payment_notification(wallet: Wallet, payment: Payment):
|
|
||||||
amount_sats = abs(payment.sat)
|
|
||||||
values: dict = {
|
|
||||||
"wallet_id": wallet.id,
|
|
||||||
"wallet_name": wallet.name,
|
|
||||||
"amount_sats": amount_sats,
|
|
||||||
"fiat_value_fmt": "",
|
|
||||||
}
|
|
||||||
if payment.extra.get("wallet_fiat_currency", None):
|
|
||||||
amount_fiat = payment.extra.get("wallet_fiat_amount", None)
|
|
||||||
currency = payment.extra.get("wallet_fiat_currency", None)
|
|
||||||
values["fiat_value_fmt"] = f"`{amount_fiat}`*{currency}* / "
|
|
||||||
|
|
||||||
if payment.is_out:
|
|
||||||
if amount_sats >= settings.lnbits_notification_outgoing_payment_amount_sats:
|
|
||||||
enqueue_notification(NotificationType.outgoing_payment, values)
|
|
||||||
else:
|
|
||||||
if amount_sats >= settings.lnbits_notification_incoming_payment_amount_sats:
|
|
||||||
enqueue_notification(NotificationType.incoming_payment, values)
|
|
||||||
|
|
||||||
|
|
||||||
async def check_wallet_limits(
|
async def check_wallet_limits(
|
||||||
wallet_id: str, amount_msat: int, conn: Optional[Connection] = None
|
wallet_id: str, amount_msat: int, conn: Optional[Connection] = None
|
||||||
):
|
):
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,19 @@ import asyncio
|
||||||
import traceback
|
import traceback
|
||||||
from typing import Callable, Coroutine
|
from typing import Callable, Coroutine
|
||||||
|
|
||||||
import httpx
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from lnbits.core.crud import (
|
from lnbits.core.crud import (
|
||||||
create_audit_entry,
|
create_audit_entry,
|
||||||
get_wallet,
|
get_wallet,
|
||||||
get_webpush_subscriptions_for_user,
|
|
||||||
mark_webhook_sent,
|
|
||||||
)
|
)
|
||||||
from lnbits.core.crud.audit import delete_expired_audit_entries
|
from lnbits.core.crud.audit import delete_expired_audit_entries
|
||||||
from lnbits.core.crud.payments import get_payments_status_count
|
from lnbits.core.crud.payments import get_payments_status_count
|
||||||
from lnbits.core.crud.users import get_accounts
|
from lnbits.core.crud.users import get_accounts
|
||||||
from lnbits.core.crud.wallets import get_wallets_count
|
from lnbits.core.crud.wallets import get_wallets_count
|
||||||
from lnbits.core.models import AuditEntry, Payment
|
from lnbits.core.models import AuditEntry
|
||||||
from lnbits.core.models.extensions import InstallableExtension
|
from lnbits.core.models.extensions import InstallableExtension
|
||||||
from lnbits.core.models.notifications import NotificationType
|
from lnbits.core.models.notifications import NotificationType
|
||||||
from lnbits.core.services import (
|
|
||||||
send_payment_notification,
|
|
||||||
)
|
|
||||||
from lnbits.core.services.funding_source import (
|
from lnbits.core.services.funding_source import (
|
||||||
check_balance_delta_changed,
|
check_balance_delta_changed,
|
||||||
check_server_balance_against_node,
|
check_server_balance_against_node,
|
||||||
|
|
@ -29,11 +23,11 @@ from lnbits.core.services.funding_source import (
|
||||||
from lnbits.core.services.notifications import (
|
from lnbits.core.services.notifications import (
|
||||||
enqueue_notification,
|
enqueue_notification,
|
||||||
process_next_notification,
|
process_next_notification,
|
||||||
|
send_payment_notification,
|
||||||
)
|
)
|
||||||
from lnbits.db import Filters
|
from lnbits.db import Filters
|
||||||
from lnbits.helpers import check_callback_url
|
|
||||||
from lnbits.settings import settings
|
from lnbits.settings import settings
|
||||||
from lnbits.tasks import create_unique_task, send_push_notification
|
from lnbits.tasks import create_unique_task
|
||||||
from lnbits.utils.exchange_rates import btc_rates
|
from lnbits.utils.exchange_rates import btc_rates
|
||||||
|
|
||||||
audit_queue: asyncio.Queue = asyncio.Queue()
|
audit_queue: asyncio.Queue = asyncio.Queue()
|
||||||
|
|
@ -106,62 +100,6 @@ async def wait_for_paid_invoices(invoice_paid_queue: asyncio.Queue):
|
||||||
wallet = await get_wallet(payment.wallet_id)
|
wallet = await get_wallet(payment.wallet_id)
|
||||||
if wallet:
|
if wallet:
|
||||||
await send_payment_notification(wallet, payment)
|
await send_payment_notification(wallet, payment)
|
||||||
# dispatch webhook
|
|
||||||
if payment.webhook and not payment.webhook_status:
|
|
||||||
await dispatch_webhook(payment)
|
|
||||||
# dispatch push notification
|
|
||||||
await send_payment_push_notification(payment)
|
|
||||||
|
|
||||||
|
|
||||||
async def dispatch_webhook(payment: Payment):
|
|
||||||
"""
|
|
||||||
Dispatches the webhook to the webhook url.
|
|
||||||
"""
|
|
||||||
logger.debug("sending webhook", payment.webhook)
|
|
||||||
|
|
||||||
if not payment.webhook:
|
|
||||||
return await mark_webhook_sent(payment.payment_hash, -1)
|
|
||||||
|
|
||||||
headers = {"User-Agent": settings.user_agent}
|
|
||||||
async with httpx.AsyncClient(headers=headers) as client:
|
|
||||||
data = payment.dict()
|
|
||||||
try:
|
|
||||||
check_callback_url(payment.webhook)
|
|
||||||
r = await client.post(payment.webhook, json=data, timeout=40)
|
|
||||||
r.raise_for_status()
|
|
||||||
await mark_webhook_sent(payment.payment_hash, r.status_code)
|
|
||||||
except httpx.HTTPStatusError as exc:
|
|
||||||
await mark_webhook_sent(payment.payment_hash, exc.response.status_code)
|
|
||||||
logger.warning(
|
|
||||||
f"webhook returned a bad status_code: {exc.response.status_code} "
|
|
||||||
f"while requesting {exc.request.url!r}."
|
|
||||||
)
|
|
||||||
except httpx.RequestError:
|
|
||||||
await mark_webhook_sent(payment.payment_hash, -1)
|
|
||||||
logger.warning(f"Could not send webhook to {payment.webhook}")
|
|
||||||
|
|
||||||
|
|
||||||
async def send_payment_push_notification(payment: Payment):
|
|
||||||
wallet = await get_wallet(payment.wallet_id)
|
|
||||||
|
|
||||||
if wallet:
|
|
||||||
subscriptions = await get_webpush_subscriptions_for_user(wallet.user)
|
|
||||||
|
|
||||||
amount = int(payment.amount / 1000)
|
|
||||||
|
|
||||||
title = f"LNbits: {wallet.name}"
|
|
||||||
body = f"You just received {amount} sat{'s'[:amount^1]}!"
|
|
||||||
|
|
||||||
if payment.memo:
|
|
||||||
body += f"\r\n{payment.memo}"
|
|
||||||
|
|
||||||
for subscription in subscriptions:
|
|
||||||
# todo: review permissions when user-id-only not allowed
|
|
||||||
# todo: replace all this logic with websockets?
|
|
||||||
url = (
|
|
||||||
f"https://{subscription.host}/wallet?usr={wallet.user}&wal={wallet.id}"
|
|
||||||
)
|
|
||||||
await send_push_notification(subscription, title, body, url)
|
|
||||||
|
|
||||||
|
|
||||||
async def wait_for_audit_data():
|
async def wait_for_audit_data():
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
import uuid
|
import uuid
|
||||||
from http import HTTPStatus
|
|
||||||
from typing import (
|
from typing import (
|
||||||
Callable,
|
Callable,
|
||||||
Coroutine,
|
Coroutine,
|
||||||
|
|
@ -13,11 +11,8 @@ from typing import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from py_vapid import Vapid
|
|
||||||
from pywebpush import WebPushException, webpush
|
|
||||||
|
|
||||||
from lnbits.core.crud import (
|
from lnbits.core.crud import (
|
||||||
delete_webpush_subscriptions,
|
|
||||||
get_payments,
|
get_payments,
|
||||||
get_standalone_payment,
|
get_standalone_payment,
|
||||||
update_payment,
|
update_payment,
|
||||||
|
|
@ -216,28 +211,3 @@ async def invoice_callback_dispatcher(checking_id: str, is_internal: bool = Fals
|
||||||
for name, send_chan in invoice_listeners.items():
|
for name, send_chan in invoice_listeners.items():
|
||||||
logger.trace(f"invoice listeners: sending to `{name}`")
|
logger.trace(f"invoice listeners: sending to `{name}`")
|
||||||
await send_chan.put(payment)
|
await send_chan.put(payment)
|
||||||
|
|
||||||
|
|
||||||
async def send_push_notification(subscription, title, body, url=""):
|
|
||||||
vapid = Vapid()
|
|
||||||
try:
|
|
||||||
logger.debug("sending push notification")
|
|
||||||
webpush(
|
|
||||||
json.loads(subscription.data),
|
|
||||||
json.dumps({"title": title, "body": body, "url": url}),
|
|
||||||
(
|
|
||||||
vapid.from_pem(bytes(settings.lnbits_webpush_privkey, "utf-8"))
|
|
||||||
if settings.lnbits_webpush_privkey
|
|
||||||
else None
|
|
||||||
),
|
|
||||||
{"aud": "", "sub": "mailto:alan@lnbits.com"},
|
|
||||||
)
|
|
||||||
except WebPushException as e:
|
|
||||||
if e.response and e.response.status_code == HTTPStatus.GONE:
|
|
||||||
# cleanup unsubscribed or expired push subscriptions
|
|
||||||
await delete_webpush_subscriptions(subscription.endpoint)
|
|
||||||
else:
|
|
||||||
logger.error(
|
|
||||||
f"failed sending push notification: "
|
|
||||||
f"{e.response.text if e.response else e}"
|
|
||||||
)
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue