diff --git a/deno.json b/deno.json index ab2acc2a..00ab104f 100644 --- a/deno.json +++ b/deno.json @@ -15,6 +15,7 @@ "admin:event": "deno run -A scripts/admin-event.ts", "admin:role": "deno run -A scripts/admin-role.ts", "setup": "deno run -A scripts/setup.ts", + "setup:kind0": "deno run -A scripts/setup-kind0.ts", "stats:recompute": "deno run -A scripts/stats-recompute.ts", "soapbox": "curl -O https://dl.soapbox.pub/main/soapbox.zip && mkdir -p public && mv soapbox.zip public/ && cd public/ && unzip -o soapbox.zip && rm soapbox.zip", "trends": "deno run -A scripts/trends.ts", @@ -71,6 +72,7 @@ "nostr-tools": "npm:nostr-tools@2.5.1", "nostr-wasm": "npm:nostr-wasm@^0.1.0", "path-to-regexp": "npm:path-to-regexp@^7.1.0", + "png-to-ico": "npm:png-to-ico@^2.1.8", "postgres": "https://gitlab.com/soapbox-pub/postgres.js/-/raw/e79d7d2039446fbf7a37d4eca0d17e94a94b8b53/deno/mod.js", "prom-client": "npm:prom-client@^15.1.2", "question-deno": "https://raw.githubusercontent.com/ocpu/question-deno/10022b8e52555335aa510adb08b0a300df3cf904/mod.ts", diff --git a/deno.lock b/deno.lock index 7aa234d8..b64f2f95 100644 --- a/deno.lock +++ b/deno.lock @@ -103,6 +103,7 @@ "npm:nostr-tools@^2.7.0": "npm:nostr-tools@2.7.0", "npm:nostr-wasm@^0.1.0": "npm:nostr-wasm@0.1.0", "npm:path-to-regexp@^7.1.0": "npm:path-to-regexp@7.1.0", + "npm:png-to-ico@^2.1.8": "npm:png-to-ico@2.1.8", "npm:postgres@3.4.4": "npm:postgres@3.4.4", "npm:prom-client@^15.1.2": "npm:prom-client@15.1.2", "npm:tldts@^6.0.14": "npm:tldts@6.1.18", @@ -672,6 +673,10 @@ "@types/trusted-types": "@types/trusted-types@2.0.7" } }, + "@types/node@17.0.45": { + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", + "dependencies": {} + }, "@types/node@18.16.19": { "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==", "dependencies": {} @@ -1131,6 +1136,10 @@ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dependencies": {} }, + "minimist@1.2.8": { + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dependencies": {} + }, "ms@2.1.2": { "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dependencies": {} @@ -1240,6 +1249,18 @@ "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", "dependencies": {} }, + "png-to-ico@2.1.8": { + "integrity": "sha512-Nf+IIn/cZ/DIZVdGveJp86NG5uNib1ZXMiDd/8x32HCTeKSvgpyg6D/6tUBn1QO/zybzoMK0/mc3QRgAyXdv9w==", + "dependencies": { + "@types/node": "@types/node@17.0.45", + "minimist": "minimist@1.2.8", + "pngjs": "pngjs@6.0.0" + } + }, + "pngjs@6.0.0": { + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", + "dependencies": {} + }, "postgres@3.4.4": { "integrity": "sha512-IbyN+9KslkqcXa8AO9fxpk97PA4pzewvpi2B3Dwy9u4zpV32QicaEdgmF3eSQUzdRk7ttDHQejNgAEr4XoeH4A==", "dependencies": {} @@ -2166,6 +2187,7 @@ "npm:nostr-tools@2.5.1", "npm:nostr-wasm@^0.1.0", "npm:path-to-regexp@^7.1.0", + "npm:png-to-ico@^2.1.8", "npm:prom-client@^15.1.2", "npm:tldts@^6.0.14", "npm:tseep@^1.2.1", diff --git a/scripts/setup-kind0.ts b/scripts/setup-kind0.ts new file mode 100644 index 00000000..1ef06b9d --- /dev/null +++ b/scripts/setup-kind0.ts @@ -0,0 +1,72 @@ +import { AdminSigner } from '@/signers/AdminSigner.ts'; +import { Command } from 'commander'; +import { NostrEvent } from 'nostr-tools'; +import { nostrNow } from '@/utils.ts'; +import { Buffer } from 'node:buffer'; +import { Conf } from '@/config.ts'; +import pngToIco from 'png-to-ico'; +import { Storages } from '@/storages.ts'; + +function die(code: number, ...args: any[]) { + console.error(...args); + Deno.exit(code); +} + +if (import.meta.main) { + const kind0 = new Command() + .name('setup:kind0') + .description('Set up / change the kind 0 for a Ditto instance.') + .version('0.1.0') + .showHelpAfterError(); + + kind0 + .argument('', 'The name of the Ditto instance. Can just be your hostname.') + .option( + '-l --lightning ', + 'Lightning address for the server. Can just be your own lightning address.', + ) + .option('-a --about ', 'About text. This shows up whenever a description for your server is needed.') + .option('-i --image ', 'Image URL to use for OpenGraph previews and favicon.') + .action(async (name, args) => { + const { lightning, about, image } = args; + const content: Record = {}; + if (!name || !name.trim()) die(1, 'You must atleast supply a name!'); + content.bot = true; + content.about = about; + content.lud16 = lightning; + content.name = name; + content.picture = image; + content.website = Conf.localDomain; + + const signer = new AdminSigner(); + const bare: Omit = { + created_at: nostrNow(), + kind: 0, + tags: [], + content: JSON.stringify(content), + }; + const signed = await signer.signEvent(bare); + if (image) { + try { + await fetch(image) + .then((res) => { + if (!res.ok) throw new Error('Error attempting to fetch favicon.'); + if (res.headers.get('content-type') !== 'image/png') throw new Error('Non-png images are not supported!'); + return res.blob(); + }) + .then(async (blob) => + await pngToIco(Buffer.from(await blob.arrayBuffer())) + .then(async (buf) => { + await Deno.writeFile('./public/favicon.ico', buf); + }) + ); + } catch (e) { + die(1, `Error generating favicon from url ${image}: "${e}". Please check this or try again without --image.`); + } + } + console.log({ content, signed }); + await Storages.db().then((store) => store.event(signed)); + }); + + await kind0.parseAsync(); +}