Skip to content

Commit

Permalink
feat: update to v1.0.0 (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
dni authored Oct 23, 2024
1 parent 5cfd10b commit ff5103c
Show file tree
Hide file tree
Showing 9 changed files with 1,392 additions and 1,283 deletions.
7 changes: 3 additions & 4 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from fastapi import APIRouter
from lnbits.db import Database
from lnbits.tasks import create_permanent_unique_task
from loguru import logger

from .tasks import wait_for_paid_invoices
Expand Down Expand Up @@ -34,7 +33,7 @@ def example_stop():


def example_start():
# ignore will be removed in lnbits `0.12.6`
# https://github.com/lnbits/lnbits/pull/2417
task = create_permanent_unique_task("ext_testing", wait_for_paid_invoices) # type: ignore
from lnbits.tasks import create_permanent_unique_task

task = create_permanent_unique_task("ext_testing", wait_for_paid_invoices)
scheduled_tasks.append(task)
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "Build your own!",
"short_description": "Extension building guide",
"tile": "https://raw.githubusercontent.com/lnbits/example/main/static/bitcoin-extension.png",
"min_lnbits_version": "0.12.6",
"min_lnbits_version": "1.0.0",
"donate": "donate@legend.lnbits.com",
"contributors": [
{
Expand Down
2,421 changes: 1,271 additions & 1,150 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors = ["Alan Bits <alan@lnbits.com>"]

[tool.poetry.dependencies]
python = "^3.10 | ^3.9"
lnbits = "*"
lnbits = {version = "*", allow-prereleases = true}

[tool.poetry.group.dev.dependencies]
black = "^24.3.0"
Expand Down
85 changes: 85 additions & 0 deletions static/js/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
const mapObject = obj => {
// obj.date = Quasar.date.formatDate(new Date(obj.time), 'YYYY-MM-DD HH:mm')
// here you can do something with the mapped data
return obj
}

window.app = Vue.createApp({
el: '#vue',
mixins: [windowMixin],
// Declare models/variables
data() {
return {
protocol: window.location.protocol,
location: '//' + window.location.hostname,
thingDialog: {
show: false,
data: {}
},
someBool: true,
splitterModel: 20,
exampleData: [],
tab: 'frameworks',
framworktab: 'fastapi',
usefultab: 'magicalg',
vettedData: ''
}
},
// Where functions live
methods: {
exampleFunction(data) {
LNbits.api
.request(
'GET', // Type of request
'/example/api/v1/test/00000000', // URL of the endpoint
this.g.user.wallets[0].inkey, // Often endpoints require a key
data
)
.then(response => {
this.exampleData = response.data.map(mapObject) // Often whats returned is mapped onto some model
})
// Error will be passed to the frontend
.catch(LNbits.utils.notifyApiError)
},
getVettedReadme() {
// This is a function that gets the vetted readme from the LNbits repo and converts it from makrdown to html.
LNbits.api
.request('GET', '/example/api/v1/vetted', this.g.user.wallets[0].inkey)
.then(response => {
this.vettedData = LNbits.utils.convertMarkdown(response.data)
})
.catch(LNbits.utils.notifyApiError)
},
async initWs() {
if (location.protocol !== 'http:') {
localUrl =
'wss://' +
document.domain +
':' +
location.port +
'/api/v1/ws/32872r23g29'
} else {
localUrl =
'ws://' +
document.domain +
':' +
location.port +
'/api/v1/ws/32872r23g29'
}
this.ws = new WebSocket(localUrl)
this.ws.addEventListener('message', async ({data}) => {
const res = data.toString()
document.getElementById('text-to-change').innerHTML = res
})
},
sendThingDialog() {
console.log(this.thingDialog)
}
},
// To run on startup
created() {
this.exampleFunction('lorum')
this.initWs()
this.getVettedReadme()
}
})
8 changes: 4 additions & 4 deletions tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@

async def wait_for_paid_invoices():
invoice_queue = asyncio.Queue()
register_invoice_listener(invoice_queue, "example")
register_invoice_listener(invoice_queue, "ext_example")

while True:
payment = await invoice_queue.get()
await on_invoice_paid(payment)


async def on_invoice_paid(payment: Payment) -> None:
if (
payment.extra.get("tag") == "example"
): # Will grab any payment with the tag "example"
# Will grab any payment with the tag "example"
if payment.extra.get("tag") == "example":
logger.info("example extension received payment")
logger.debug(payment)
107 changes: 4 additions & 103 deletions templates/example/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
%} {% block page %}

%} {% block scripts %} {{ window_vars(user) }}
<script src="{{ static_url_for('example/static', path='js/index.js') }}"></script>
<!-- Do not remove. Test install extension version: 2 -->
{% endblock %} {% block page %}
<q-dialog v-model="thingDialog.show" position="top">
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
<q-form @submit="sendThingDialog" class="q-gutter-md">
Expand Down Expand Up @@ -371,105 +373,4 @@
</q-card>
</q-card-section>
</q-card>
{% endblock %} {% block scripts %} {{ window_vars(user) }}

<script>
var someMapObject = obj => {
obj._data = _.clone(obj)
obj.date = Quasar.utils.date.formatDate(
new Date(obj.time * 1000),
'YYYY-MM-DD HH:mm'
)
// here you can do something with the mapped data
return obj
}
new Vue({
el: '#vue',
mixins: [windowMixin],
data: function () {
return {
///// Declare models/variables /////
protocol: window.location.protocol,
location: '//' + window.location.hostname,
thingDialog: {
show: false,
data: {}
},
someBool: true,
splitterModel: 20,
exampleData: [],
tab: 'frameworks',
framworktab: 'fastapi',
usefultab: 'magicalg',
vettedData: ''
}
},
///// Where functions live /////
methods: {
exampleFunction: function (data) {
var theData = data
LNbits.api
.request(
'GET', // Type of request
'/example/api/v1/test/' + theData, // URL of the endpoint
this.g.user.wallets[0].inkey // Often endpoints require a key
)
.then(response => {
this.exampleData = response.data.map(someMapObject) // Often whats returned is mapped onto some model
})
.catch(error => {
LNbits.utils.notifyApiError(error) // Error will be passed to the frontend
})
},
getVettedReadme: function () {
// This is a function that gets the vetted readme from the LNbits repo and converts it from makrdown to html.
LNbits.api
.request(
'GET',
'/example/api/v1/vetted',
this.g.user.wallets[0].inkey
)
.then(response => {
this.vettedData = LNbits.utils.convertMarkdown(response.data)
})
.catch(error => {
LNbits.utils.notifyApiError(error)
})
},
initWs: async function () {
if (location.protocol !== 'http:') {
localUrl =
'wss://' +
document.domain +
':' +
location.port +
'/api/v1/ws/32872r23g29'
} else {
localUrl =
'ws://' +
document.domain +
':' +
location.port +
'/api/v1/ws/32872r23g29'
}
this.ws = new WebSocket(localUrl)
this.ws.addEventListener('message', async ({data}) => {
const res = data.toString()
document.getElementById('text-to-change').innerHTML = res
})
},
sendThingDialog() {
console.log(this.thingDialog)
}
},
///// To run on startup /////
created: function () {
self = this // Often used to run a real object, rather than the event (all a bit confusing really)
self.exampleFunction('lorum')
self.initWs()
self.getVettedReadme()
}
})
</script>
<!-- Do not remove. Test install extension version: 2 -->
{% endblock %}
2 changes: 1 addition & 1 deletion views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ async def index(
user: User = Depends(check_user_exists),
):
return template_renderer(["example/templates"]).TemplateResponse(
request, "example/index.html", {"user": user.dict()}
request, "example/index.html", {"user": user.json()}
)
41 changes: 22 additions & 19 deletions views_api.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from http import HTTPStatus

import httpx
from fastapi import APIRouter, Depends
from fastapi.exceptions import HTTPException
from lnbits.decorators import WalletTypeInfo, get_key_type
from fastapi import APIRouter, Depends, HTTPException
from lnbits.decorators import require_invoice_key

from .models import Example

Expand All @@ -16,20 +15,24 @@


@example_ext_api.get("/test/{example_data}", description="Example API endpoint")
async def api_example(example_data: str) -> Example:
# Do some python things and return the data
return Example(id="2", wallet=example_data)


@example_ext_api.get("/vetted", description="Get the vetted extension readme")
async def api_get_vetted(wallet: WalletTypeInfo = Depends(get_key_type)):
try:
async with httpx.AsyncClient() as client:
resp = await client.get(
"https://raw.githubusercontent.com/lnbits/lnbits-extensions/main/README.md"
)
return resp.text
except Exception as e:
async def api_example(example_data: str) -> list[Example]:
if example_data != "00000000":
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)
) from e
status_code=HTTPStatus.BAD_REQUEST,
detail="Invalid example data",
)
# Do some python things and return the data
return [Example(id="1", wallet=example_data), Example(id="2", wallet=example_data)]


@example_ext_api.get(
"/vetted",
description="Get the vetted extension readme",
dependencies=[Depends(require_invoice_key)],
)
async def api_get_vetted():
async with httpx.AsyncClient() as client:
resp = await client.get(
"https://raw.githubusercontent.com/lnbits/lnbits-extensions/main/README.md"
)
return resp.text

0 comments on commit ff5103c

Please sign in to comment.