diff --git a/src/lib/components/CmsDesign.svelte b/src/lib/components/CmsDesign.svelte index f1a0bbeff..3ef1f96c9 100644 --- a/src/lib/components/CmsDesign.svelte +++ b/src/lib/components/CmsDesign.svelte @@ -182,6 +182,12 @@ : ''}{token.height ? `height: ${token.height}px;` : ''}" /> + {:else if token.type === 'qrCode'} + {#if token.slug === 'Bolt12'} + + QR code + + {/if} {:else if token.type === 'currencyCalculatorWidget'} {:else if token.type === 'html'} @@ -258,6 +264,16 @@ /> {:else if token.type === 'pictureWidget'} + {:else if token.type === 'qrCode'} + {#if token.slug === 'Bolt12'} + + QR code + + {/if} {:else if token.type === 'currencyCalculatorWidget'} {:else if token.type === 'html'} diff --git a/src/lib/server/cms.ts b/src/lib/server/cms.ts index bdd49bb41..f4774ca13 100644 --- a/src/lib/server/cms.ts +++ b/src/lib/server/cms.ts @@ -77,6 +77,7 @@ type TokenObject = display: string | undefined; raw: string; } + | { type: 'qrCode'; slug: string; raw: string } | { type: 'currencyCalculatorWidget'; slug: string; raw: string }; export async function cmsFromContent( @@ -100,6 +101,7 @@ export async function cmsFromContent( /\[TagProducts=(?[\p{L}\d_-]+)(?:[?\s]display=(?[a-z0-9-]+))?\]/giu; const GALLERY_WIDGET_REGEX = /\[Gallery=(?[\p{L}\d_-]+)(?:[?\s]display=(?[a-z0-9-]+))?\]/giu; + const QRCODE_REGEX = /\[QRCode=(?[\p{L}\d_-]+)\]/giu; const CURRENCY_CALCULATOR_WIDGET_REGEX = /\[CurrencyCalculator=(?[a-z0-9-]+)\]/giu; const productSlugs = new Set(); @@ -112,6 +114,7 @@ export async function cmsFromContent( const countdownFormSlugs = new Set(); const tagProductsSlugs = new Set(); const gallerySlugs = new Set(); + const qrCodeSlugs = new Set(); const currencyCalculatorSlugs = new Set(); const tokens: { @@ -143,6 +146,7 @@ export async function cmsFromContent( ...matchAndSort(content, COUNTDOWN_WIDGET_REGEX, 'countdownWidget'), ...matchAndSort(content, TAG_PRODUCTS_REGEX, 'tagProducts'), ...matchAndSort(content, GALLERY_WIDGET_REGEX, 'galleryWidget'), + ...matchAndSort(content, QRCODE_REGEX, 'qrCode'), ...matchAndSort(content, CURRENCY_CALCULATOR_WIDGET_REGEX, 'currencyCalculatorWidget') ].sort((a, b) => (a.index ?? 0) - (b.index ?? 0)); for (const match of matches) { @@ -250,6 +254,14 @@ export async function cmsFromContent( raw: match[0] }); break; + case 'qrCode': + qrCodeSlugs.add(match.groups.slug); + token.push({ + type: 'qrCode', + slug: match.groups.slug, + raw: match[0] + }); + break; case 'currencyCalculatorWidget': currencyCalculatorSlugs.add(match.groups.slug); token.push({ diff --git a/src/lib/server/phoenixd.ts b/src/lib/server/phoenixd.ts index 47cd7e777..752d83be7 100644 --- a/src/lib/server/phoenixd.ts +++ b/src/lib/server/phoenixd.ts @@ -34,6 +34,21 @@ export async function phoenixdBalance(): Promise<{ balanceSat: number; feeCredit return await res.json(); } +export async function phoenixdGetBolt12(): Promise { + const res = await fetch(`${runtimeConfig.phoenixd.url}/getoffer`, { + headers: { + Authorization: `Basic ${Buffer.from(`:${runtimeConfig.phoenixd.password}`).toString( + 'base64' + )}` + } + }); + + if (!res.ok) { + throw error(500, `Error fetching Bolt12 offer: ${res.status} ${await res.text()}`); + } + + return await res.text(); +} export async function phoenixdDetected(url?: string): Promise { return await Promise.race([ fetch(`${url || runtimeConfig.phoenixd.url}/getinfo`).then( diff --git a/src/lib/server/runtime-config.ts b/src/lib/server/runtime-config.ts index 8dbbef1e9..081006670 100644 --- a/src/lib/server/runtime-config.ts +++ b/src/lib/server/runtime-config.ts @@ -123,7 +123,8 @@ const baseConfig = { phoenixd: { url: 'http://localhost:9740', enabled: false, - password: '' + password: '', + bolt12Address: '' }, productActionSettings: { eShop: { diff --git a/src/routes/(app)/admin[[hash=admin_hash]]/phoenixd/+page.server.ts b/src/routes/(app)/admin[[hash=admin_hash]]/phoenixd/+page.server.ts index 26b7760f7..7651fd2fd 100644 --- a/src/routes/(app)/admin[[hash=admin_hash]]/phoenixd/+page.server.ts +++ b/src/routes/(app)/admin[[hash=admin_hash]]/phoenixd/+page.server.ts @@ -5,6 +5,7 @@ import { isPhoenixdConfigured, phoenixdBalance, phoenixdDetected, + phoenixdGetBolt12, phoenixdInfo, phoenixdPayInvoice, phoenixdSendOnChain @@ -29,17 +30,19 @@ export const load = async () => { try { const nodeInfo = await phoenixdInfo(); const balance = await phoenixdBalance(); - + const bolt12Address = await phoenixdGetBolt12(); return { phoenixd: runtimeConfig.phoenixd, nodeInfo, - balance + balance, + bolt12Address }; } catch (err) { return { phoenixd: runtimeConfig.phoenixd, nodeInfo: null, - balance: null + balance: null, + bolt12Address: null }; } }; @@ -76,7 +79,7 @@ export const actions = { .parse(Object.fromEntries(await event.request.formData())); runtimeConfig.phoenixd.password = parsed.password; - + runtimeConfig.phoenixd.bolt12Address = await phoenixdGetBolt12(); await collections.runtimeConfig.updateOne( { _id: 'phoenixd' }, { diff --git a/src/routes/(app)/admin[[hash=admin_hash]]/phoenixd/+page.svelte b/src/routes/(app)/admin[[hash=admin_hash]]/phoenixd/+page.svelte index 2691a1073..33f677ed0 100644 --- a/src/routes/(app)/admin[[hash=admin_hash]]/phoenixd/+page.svelte +++ b/src/routes/(app)/admin[[hash=admin_hash]]/phoenixd/+page.svelte @@ -22,6 +22,7 @@ let withdrawMode = 'bolt11' as 'bolt11' | 'bitcoin'; let defaultUrl = data.phoenixd.url || 'http://localhost:9740'; + let showBolt12 = false;

PhoenixD

@@ -92,6 +93,9 @@
+ {#if data.nodeInfo}
+ {#if showBolt12} +

Bolt12 address: {data.bolt12Address}

+

To use it on page CMS, use this code : [QRCode=Bolt12]

+ {/if}
diff --git a/src/routes/(app)/phoenixd/bolt12/qrcode/+server.ts b/src/routes/(app)/phoenixd/bolt12/qrcode/+server.ts new file mode 100644 index 000000000..ce4e47030 --- /dev/null +++ b/src/routes/(app)/phoenixd/bolt12/qrcode/+server.ts @@ -0,0 +1,22 @@ +import { runtimeConfig } from '$lib/server/runtime-config'; +import qrcode from 'qrcode'; + +export async function GET({}) { + try { + const bolt12Address = runtimeConfig.phoenixd.bolt12Address; + + const svgQRCode = await qrcode.toString('lightning:' + bolt12Address, { type: 'svg' }); + + return new Response(svgQRCode, { + headers: { 'content-type': 'image/svg+xml' }, + status: 200 + }); + } catch (error) { + console.error('Error on phoenixdGetBolt12:', error); + + return new Response("Erreur lors de la génération de l'adresse Bolt12", { + headers: { 'content-type': 'text/plain' }, + status: 500 + }); + } +} diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts index 2d269b889..fa823f43b 100644 --- a/src/routes/+layout.server.ts +++ b/src/routes/+layout.server.ts @@ -38,6 +38,7 @@ export async function load(event) { viewportWidth, contactModes: runtimeConfig.contactModes, hideFromSearchEngines: runtimeConfig.hideFromSearchEngines, - ageRestriction: runtimeConfig.ageRestriction + ageRestriction: runtimeConfig.ageRestriction, + bolt12Address: runtimeConfig.phoenixd.bolt12Address }; }