From b5643c4abad577cd91c397db92f86da3f1748c0d Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 10 Jun 2023 17:15:08 -0500 Subject: [PATCH] Refactor config to use a better interface --- src/client.ts | 12 ++++++------ src/config.ts | 27 ++++++++++++++++++++++----- src/controllers/api/instance.ts | 10 +++++----- src/controllers/site.ts | 4 ++-- src/deps.ts | 1 + src/note.ts | 4 ++-- src/transmute.ts | 10 +++++----- src/utils.ts | 6 +++--- 8 files changed, 46 insertions(+), 28 deletions(-) diff --git a/src/client.ts b/src/client.ts index b73c4ad..b796b37 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,7 +1,7 @@ import { Author, findReplyTag, matchFilter, RelayPool, TTLCache } from '@/deps.ts'; import { type Event, type SignedEvent } from '@/event.ts'; -import { poolRelays, publishRelays } from './config.ts'; +import { Conf } from './config.ts'; import { eventDateComparator, nostrNow } from './utils.ts'; @@ -24,7 +24,7 @@ function getPool(): Pool { if (cached !== undefined) return cached; console.log('Creating new pool.'); - const pool = new RelayPool(poolRelays); + const pool = new RelayPool(Conf.poolRelays); poolCache.set(0, pool); return pool; } @@ -52,7 +52,7 @@ function getFilter(filter: Filter, opts: GetFilterOpts = {} const unsub = getPool().subscribe( [filter], - poolRelays, + Conf.poolRelays, (event: SignedEvent | null) => { if (event && matchFilter(filter, event)) { results.push({ @@ -90,7 +90,7 @@ function getFilter(filter: Filter, opts: GetFilterOpts = {} /** Get a Nostr event by its ID. */ const getEvent = async (id: string, kind?: K): Promise | undefined> => { - const event = await (getPool().getEventById(id, poolRelays, 0) as Promise); + const event = await (getPool().getEventById(id, Conf.poolRelays, 0) as Promise); if (event) { if (event.id !== id) return undefined; if (kind && event.kind !== kind) return undefined; @@ -100,7 +100,7 @@ const getEvent = async (id: string, kind?: K): Promis /** Get a Nostr `set_medatadata` event for a user's pubkey. */ const getAuthor = async (pubkey: string): Promise | undefined> => { - const author = new Author(getPool(), poolRelays, pubkey); + const author = new Author(getPool(), Conf.poolRelays, pubkey); const event: SignedEvent<0> | null = await new Promise((resolve) => author.metaData(resolve, 0)); return event?.pubkey === pubkey ? event : undefined; }; @@ -170,7 +170,7 @@ function getDescendants(eventId: string): Promise[]> { } /** Publish an event to the Nostr relay. */ -function publish(event: SignedEvent, relays = publishRelays): void { +function publish(event: SignedEvent, relays = Conf.publishRelays): void { console.log('Publishing event', event); try { getPool().publish(event, relays); diff --git a/src/config.ts b/src/config.ts index 21f84a2..d07b790 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,6 +1,23 @@ -export const LOCAL_DOMAIN = Deno.env.get('LOCAL_DOMAIN') || 'http://localhost:8000'; -export const POST_CHAR_LIMIT = Number(Deno.env.get('POST_CHAR_LIMIT') || 5000); -export const ADMIN_EMAIL = Deno.env.get('ADMIN_EMAIL') || 'webmaster@localhost'; +/** Application-wide configuration. */ +const Conf = { + get nsec() { + return Deno.env.get('DITTO_NSEC'); + }, + get localDomain() { + return Deno.env.get('LOCAL_DOMAIN') || 'http://localhost:8000'; + }, + get postCharLimit() { + return Number(Deno.env.get('POST_CHAR_LIMIT') || 5000); + }, + get adminEmail() { + return Deno.env.get('ADMIN_EMAIL') || 'webmaster@localhost'; + }, + get poolRelays() { + return (Deno.env.get('RELAY_POOL') || '').split(',').filter(Boolean); + }, + get publishRelays() { + return ['wss://relay.mostr.pub']; + }, +}; -export const poolRelays = (Deno.env.get('RELAY_POOL') || '').split(',').filter(Boolean); -export const publishRelays = ['wss://relay.mostr.pub']; +export { Conf }; diff --git a/src/controllers/api/instance.ts b/src/controllers/api/instance.ts index ec8a3d3..6394faa 100644 --- a/src/controllers/api/instance.ts +++ b/src/controllers/api/instance.ts @@ -1,9 +1,9 @@ -import { ADMIN_EMAIL, LOCAL_DOMAIN, POST_CHAR_LIMIT } from '@/config.ts'; +import { Conf } from '@/config.ts'; import type { Context } from '@/deps.ts'; function instanceController(c: Context) { - const { host, protocol } = new URL(LOCAL_DOMAIN); + const { host, protocol } = new URL(Conf.localDomain); return c.json({ uri: host, @@ -11,7 +11,7 @@ function instanceController(c: Context) { description: 'An efficient and flexible social media server.', short_description: 'An efficient and flexible social media server.', registrations: false, - max_toot_chars: POST_CHAR_LIMIT, + max_toot_chars: Conf.postCharLimit, configuration: { media_attachments: { image_size_limit: 100000000, @@ -24,7 +24,7 @@ function instanceController(c: Context) { min_expiration: 0, }, statuses: { - max_characters: POST_CHAR_LIMIT, + max_characters: Conf.postCharLimit, max_media_attachments: 20, }, }, @@ -38,7 +38,7 @@ function instanceController(c: Context) { streaming_api: `${protocol === 'http:' ? 'ws:' : 'wss:'}//${host}`, }, version: '0.0.0 (compatible; Ditto 0.0.1)', - email: ADMIN_EMAIL, + email: Conf.adminEmail, rules: [], }); } diff --git a/src/controllers/site.ts b/src/controllers/site.ts index 8c0f4a9..b7f34dd 100644 --- a/src/controllers/site.ts +++ b/src/controllers/site.ts @@ -1,4 +1,4 @@ -import { LOCAL_DOMAIN } from '@/config.ts'; +import { Conf } from '@/config.ts'; import type { AppController } from '@/app.ts'; @@ -6,7 +6,7 @@ import type { AppController } from '@/app.ts'; const indexController: AppController = (c) => { return c.text(`Please connect with a Mastodon client: - ${LOCAL_DOMAIN} + ${Conf.localDomain} Ditto `); diff --git a/src/deps.ts b/src/deps.ts index f85dba7..6657bbd 100644 --- a/src/deps.ts +++ b/src/deps.ts @@ -12,6 +12,7 @@ export { z } from 'https://deno.land/x/zod@v3.20.5/mod.ts'; export { Author, RelayPool } from 'https://dev.jspm.io/nostr-relaypool@0.5.3'; export { type Filter, + finishEvent, getEventHash, getPublicKey, getSignature, diff --git a/src/note.ts b/src/note.ts index a778e0d..a4344ea 100644 --- a/src/note.ts +++ b/src/note.ts @@ -1,10 +1,10 @@ -import { LOCAL_DOMAIN } from '@/config.ts'; +import { Conf } from '@/config.ts'; import { linkify, linkifyStr, mime, nip19, nip21 } from '@/deps.ts'; linkify.registerCustomProtocol('nostr', true); linkify.registerCustomProtocol('wss'); -const url = (path: string) => new URL(path, LOCAL_DOMAIN).toString(); +const url = (path: string) => new URL(path, Conf.localDomain).toString(); const linkifyOpts: linkify.Opts = { render: { diff --git a/src/transmute.ts b/src/transmute.ts index 81aa548..a2b90fe 100644 --- a/src/transmute.ts +++ b/src/transmute.ts @@ -2,7 +2,7 @@ import { findReplyTag, lodash, nip19, sanitizeHtml, TTLCache, unfurl, z } from ' import { type Event } from '@/event.ts'; import { emojiTagSchema, filteredArray, type MetaContent, parseMetaContent } from '@/schema.ts'; -import { LOCAL_DOMAIN } from './config.ts'; +import { Conf } from './config.ts'; import { getAuthor } from './client.ts'; import { verifyNip05Cached } from './nip05.ts'; import { getMediaLinks, type MediaLink, parseNoteContent } from './note.ts'; @@ -20,7 +20,7 @@ async function toAccount(event: Event<0>, opts: ToAccountOpts = {}) { const { pubkey } = event; const { name, nip05, picture, banner, about }: MetaContent = parseMetaContent(event); - const { origin } = new URL(LOCAL_DOMAIN); + const { origin } = new URL(Conf.localDomain); const npub = nip19.npubEncode(pubkey); let parsed05: Nip05 | undefined; @@ -81,7 +81,7 @@ async function toMention(pubkey: string) { url: account.url, }; } else { - const { origin } = new URL(LOCAL_DOMAIN); + const { origin } = new URL(Conf.localDomain); const npub = nip19.npubEncode(pubkey); return { id: pubkey, @@ -143,8 +143,8 @@ async function toStatus(event: Event<1>) { tags: [], emojis: toEmojis(event), poll: null, - uri: `${LOCAL_DOMAIN}/posts/${event.id}`, - url: `${LOCAL_DOMAIN}/posts/${event.id}`, + uri: `${Conf.localDomain}/posts/${event.id}`, + url: `${Conf.localDomain}/posts/${event.id}`, }; } diff --git a/src/utils.ts b/src/utils.ts index b47cd73..0d2bf30 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,5 +1,5 @@ import { getAuthor } from '@/client.ts'; -import { LOCAL_DOMAIN } from '@/config.ts'; +import { Conf } from '@/config.ts'; import { nip19, parseFormData, z } from '@/deps.ts'; import { type Event } from '@/event.ts'; import { lookupNip05Cached } from '@/nip05.ts'; @@ -87,8 +87,8 @@ function buildLinkHeader(url: string, events: Event[]): string | undefined { const lastEvent = events[events.length - 1]; const { pathname, search } = new URL(url); - const next = new URL(pathname + search, LOCAL_DOMAIN); - const prev = new URL(pathname + search, LOCAL_DOMAIN); + const next = new URL(pathname + search, Conf.localDomain); + const prev = new URL(pathname + search, Conf.localDomain); next.searchParams.set('until', String(lastEvent.created_at)); prev.searchParams.set('since', String(firstEvent.created_at));