Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds zaps to switches #4

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from loguru import logger

from .crud import db
from .tasks import wait_for_paid_invoices
from .tasks import get_nostr_events, wait_for_paid_invoices
from .views import bitcoinswitch_generic_router
from .views_api import bitcoinswitch_api_router
from .views_lnurl import bitcoinswitch_lnurl_router
Expand Down Expand Up @@ -36,14 +36,15 @@ def bitcoinswitch_stop():
def bitcoinswitch_start():
from lnbits.tasks import create_permanent_unique_task

task = create_permanent_unique_task("ext_bitcoinswitch", wait_for_paid_invoices)
scheduled_tasks.append(task)
task1 = create_permanent_unique_task("ext_bitcoinswitch", wait_for_paid_invoices)
task2 = create_permanent_unique_task("ext_bitcoinswitch", get_nostr_events)
scheduled_tasks.extend([task1, task2])


__all__ = [
"db",
"bitcoinswitch_ext",
"bitcoinswitch_static_files",
"bitcoinswitch_start",
"bitcoinswitch_static_files",
"bitcoinswitch_stop",
"db",
]
15 changes: 15 additions & 0 deletions crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ async def create_bitcoinswitch(
title=data.title,
wallet=data.wallet,
currency=data.currency,
npub=data.npub if data.npub != "" else None,
switches=data.switches,
)
await db.insert("bitcoinswitch.switch", device)
Expand Down Expand Up @@ -152,3 +153,17 @@ async def get_recent_bitcoinswitch_payment(
{"payload": payload},
BitcoinswitchPayment,
)


async def get_public_keys():
records = await db.fetchall("SELECT * FROM bitcoinswitch.switch ORDER BY id")
npubs = [record.npub for record in records if record.npub]
return npubs


async def get_switch_from_npub(npub: str) -> Bitcoinswitch:
return await db.fetchone(
"SELECT * FROM bitcoinswitch.switch WHERE npub = :npub",
{"npub": npub},
Bitcoinswitch,
)
11 changes: 11 additions & 0 deletions migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,14 @@ async def m001_initial(db):
);
"""
)


async def m002_add_npub(db):
"""
Add npubs
"""
await db.execute(
"""
ALTER TABLE bitcoinswitch.switch ADD npub TEXT NULL;
"""
)
2 changes: 2 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ class CreateBitcoinswitch(BaseModel):
wallet: str
currency: str
switches: list[Switch]
npub: Optional[str] = ""


class Bitcoinswitch(BaseModel):
id: str
title: str
wallet: str
currency: str
npub: Optional[str] = ""
key: str
switches: list[Switch]
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
Expand Down
12 changes: 11 additions & 1 deletion static/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,14 @@ window.app = Vue.createApp({
switches: [],
lnurl_toggle: false,
show_message: false,
nostrfy: false,
show_ack: false,
show_price: 'None',
device: 'pos',
profit: 1,
amount: 1,
title: ''
title: '',
npub: ''
}
},
qrCodeDialog: {
Expand All @@ -66,6 +68,14 @@ window.app = Vue.createApp({
}
}
},
watch: {
'formDialog.data.npub': {
immediate: true,
handler(newValue) {
this.formDialog.data.nostrfy = newValue !== ''
}
}
},
computed: {
wsMessage() {
return this.websocketMessage
Expand Down
56 changes: 56 additions & 0 deletions tasks.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import asyncio

from bech32 import bech32_decode, convertbits
from lnbits.core.models import Payment
from lnbits.core.services import websocket_updater
from lnbits.settings import settings
from lnbits.tasks import register_invoice_listener
from nostr.filter import Filter, Filters
from nostr.relay_manager import RelayManager

from .crud import (
get_bitcoinswitch_payment,
get_public_keys,
get_switch_from_npub,
update_bitcoinswitch_payment,
)

Expand Down Expand Up @@ -48,3 +54,53 @@ async def on_invoice_paid(payment: Payment) -> None:
bitcoinswitch_payment.bitcoinswitch_id,
payload,
)


async def get_nostr_events():
pub_keys = await get_public_keys()
target_keys_hex = [
decode_npub_to_hex(pk) if pk.startswith("npub") else pk for pk in pub_keys
]

relay_url = f"wss://localhost:{settings.port}/nostrclient/api/v1/relay"
relay_manager = RelayManager()
relay_manager.add_relay(relay_url)

zap_filter = Filter(kinds=[9735], pubkey_refs=target_keys_hex)
filters = Filters([zap_filter])

relay_manager.add_subscription("bitcoinswitch_zaps", filters)
relay_manager.open_connections()

try:
while True:
while relay_manager.message_pool.has_events():
event_message = relay_manager.message_pool.get_event()
event = event_message.event
for tag in event.tags:
if tag[0] == "p" and tag[1] in target_keys_hex:
switch = await get_switch_from_npub(event.sender)
if not switch:
continue
payload = int(event.amount)
if switch.variable:
payload = str(
(switch.amount / int(event.amount)) * switch.amount
)
payload = f"{switch.pin}-{payload}"
await websocket_updater(
switch.id,
payload,
)
break
await asyncio.sleep(1)
finally:
relay_manager.close_connections()


def decode_npub_to_hex(npub):
hrp, data = bech32_decode(npub)
if hrp != "npub" or data is None:
raise ValueError(f"Invalid npub: {npub}")
decoded_bytes = bytes(convertbits(data, 5, 8, False))
return decoded_bytes.hex()
32 changes: 31 additions & 1 deletion templates/bitcoinswitch/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ <h5 v-html="formDialog.data.device" v-if="formDialog.data.id"></h5>
:options="currency"
></q-select>
<q-btn
:disable="formDialog.data.switches.length > 0 && formDialog.data.nostrfy == true"
unelevated
class="q-mb-lg"
round
Expand Down Expand Up @@ -264,7 +265,9 @@ <h5 v-html="formDialog.data.device" v-if="formDialog.data.id"></h5>
label="GPIO pin"
></q-input>
</div>
<div class="col q-ml-md">
</div>
<div class="row">
<div class="col">
<q-checkbox
v-model="_switch.variable"
color="primary"
Expand All @@ -275,6 +278,8 @@ <h5 v-html="formDialog.data.device" v-if="formDialog.data.id"></h5>
>Variable time (Amount * Duration)</q-tooltip
></q-checkbox
>
</div>
<div class="col q-ml-md">
<q-checkbox
v-model="_switch.comment"
color="primary"
Expand All @@ -285,6 +290,31 @@ <h5 v-html="formDialog.data.device" v-if="formDialog.data.id"></h5>
<q-tooltip>Enable LNURLp comments with payments</q-tooltip>
</q-checkbox>
</div>
<div class="col q-ml-md">
<q-checkbox
v-if="formDialog.data.switches.length < 2"
v-model="formDialog.data.nostrfy"
color="primary"
label="Zaps"
size="xs"
dense
>
<q-tooltip>Use zaps for payments</q-tooltip>
</q-checkbox>
</div>
</div>
<div class="row">
<div class="col">
<q-input
v-if="formDialog.data.nostrfy"
filled
dense
v-model.trim="formDialog.data.npub"
type="text"
label="Add your npub (limits to only one switch)"
>
</q-input>
</div>
</div>
</div>
<div class="row q-mt-lg">
Expand Down
10 changes: 10 additions & 0 deletions views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
async def api_bitcoinswitch_create(
request: Request, data: CreateBitcoinswitch
) -> Bitcoinswitch:
if len(data.switches) > 1 and data.npub != "":
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="Only one switch allowed if using an npub.",
)

bitcoinswitch_id = urlsafe_short_hash()

Expand All @@ -52,6 +57,11 @@ async def api_bitcoinswitch_update(
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="bitcoinswitch does not exist"
)
if len(data.switches) > 1 and data.npub != "":
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="Only one switch allowed if using an npub.",
)

for k, v in data.dict().items():
if v is not None:
Expand Down
Loading