diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9b2675e..5afd11d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: denoland/deno:1.33.2 +image: denoland/deno:1.36.0 default: interruptible: true @@ -14,6 +14,10 @@ lint: stage: test script: deno lint +check: + stage: test + script: deno task check + test: stage: test script: deno task test \ No newline at end of file diff --git a/.tool-versions b/.tool-versions index f2c3d11..d2861dc 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -deno 1.33.2 +deno 1.36.0 diff --git a/deno.json b/deno.json index f0c10e6..b3a4d58 100644 --- a/deno.json +++ b/deno.json @@ -2,8 +2,9 @@ "$schema": "https://deno.land/x/deno@v1.32.3/cli/schemas/config-file.v1.json", "lock": false, "tasks": { - "dev": "deno run --allow-read --allow-write --allow-env --allow-net --allow-ffi --unstable --watch src/server.ts", - "test": "deno test -A --unstable src" + "start": "deno run --allow-read --allow-write=data --allow-env --allow-net --unstable --watch src/server.ts", + "test": "deno test --allow-read --allow-write=data --allow-env --unstable src", + "check": "deno check --unstable src/server.ts" }, "imports": { "@/": "./src/" diff --git a/src/config.ts b/src/config.ts index 69d0057..07e899d 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,4 +1,11 @@ -import { nip19, secp } from '@/deps.ts'; +import { dotenv, nip19, secp } from '@/deps.ts'; + +/** Load environment config from `.env` */ +await dotenv.load({ + export: true, + defaultsPath: null, + examplePath: null, +}); /** Application-wide configuration. */ const Conf = { @@ -22,7 +29,7 @@ const Conf = { get cryptoKey() { return crypto.subtle.importKey( 'raw', - secp.utils.hexToBytes(Conf.seckey), + secp.etc.hexToBytes(Conf.seckey), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign', 'verify'], diff --git a/src/controllers/activitypub/actor.ts b/src/controllers/activitypub/actor.ts index 8d09255..5d78609 100644 --- a/src/controllers/activitypub/actor.ts +++ b/src/controllers/activitypub/actor.ts @@ -12,7 +12,7 @@ const actorController: AppController = async (c) => { const event = await getAuthor(user.pubkey); if (!event) return notFound(c); - const actor = await toActor(event); + const actor = await toActor(event, user.username); if (!actor) return notFound(c); return activityJson(c, actor); diff --git a/src/deps.ts b/src/deps.ts index d3091e1..12800d2 100644 --- a/src/deps.ts +++ b/src/deps.ts @@ -3,12 +3,12 @@ export { type Env as HonoEnv, type Handler, Hono, + HTTPException, type MiddlewareHandler, -} from 'https://deno.land/x/hono@v3.0.2/mod.ts'; -export { HTTPException } from 'https://deno.land/x/hono@v3.0.2/http-exception.ts'; -export { cors, logger } from 'https://deno.land/x/hono@v3.0.2/middleware.ts'; +} from 'https://deno.land/x/hono@v3.3.4/mod.ts'; +export { cors, logger } from 'https://deno.land/x/hono@v3.3.4/middleware.ts'; export { z } from 'https://deno.land/x/zod@v3.21.4/mod.ts'; -export { Author, RelayPool } from 'https://dev.jspm.io/nostr-relaypool@0.5.3'; +export { Author, RelayPool } from 'https://dev.jspm.io/nostr-relaypool@0.6.28'; export { type Filter, finishEvent, @@ -21,24 +21,23 @@ export { nip19, nip21, verifySignature, -} from 'npm:nostr-tools@^1.12.1'; +} from 'npm:nostr-tools@^1.14.0'; export { findReplyTag } from 'https://gitlab.com/soapbox-pub/mostr/-/raw/c67064aee5ade5e01597c6d23e22e53c628ef0e2/src/nostr/tags.ts'; export { parseFormData } from 'npm:formdata-helper@^0.3.0'; // @deno-types="npm:@types/lodash@4.14.194" export { default as lodash } from 'https://esm.sh/lodash@4.17.21'; -export { default as linkify } from 'npm:linkifyjs@^4.1.0'; -export { default as linkifyStr } from 'npm:linkify-string@^4.1.0'; -import 'npm:linkify-plugin-hashtag@^4.1.0'; +export { default as linkify } from 'npm:linkifyjs@^4.1.1'; +export { default as linkifyStr } from 'npm:linkify-string@^4.1.1'; +import 'npm:linkify-plugin-hashtag@^4.1.1'; // @deno-types="npm:@types/mime@3.0.0" export { default as mime } from 'npm:mime@^3.0.0'; export { unfurl } from 'npm:unfurl.js@^6.3.2'; -export { default as TTLCache } from 'npm:@isaacs/ttlcache@^1.4.0'; +export { default as TTLCache } from 'npm:@isaacs/ttlcache@^1.4.1'; export { default as uuid62 } from 'npm:uuid62@^1.0.2'; // @deno-types="npm:@types/sanitize-html@2.9.0" -export { default as sanitizeHtml } from 'npm:sanitize-html@^2.10.0'; +export { default as sanitizeHtml } from 'npm:sanitize-html@^2.11.0'; export { default as ISO6391 } from 'npm:iso-639-1@2.1.15'; -export { Dongoose } from 'https://raw.githubusercontent.com/alexgleason/dongoose/68b7ad9dd7b6ec0615e246a9f1603123c1709793/mod.ts'; -export { createPentagon } from 'https://deno.land/x/pentagon@v0.1.1/mod.ts'; +export { createPentagon } from 'https://deno.land/x/pentagon@v0.1.4/mod.ts'; export { type ParsedSignature, pemToPublicKey, @@ -47,7 +46,7 @@ export { verifyRequest, } from 'https://gitlab.com/soapbox-pub/fedisign/-/raw/v0.2.1/mod.ts'; export { generateSeededRsa } from 'https://gitlab.com/soapbox-pub/seeded-rsa/-/raw/v1.0.0/mod.ts'; -export * as secp from 'npm:@noble/secp256k1@^1.7.1'; +export * as secp from 'npm:@noble/secp256k1@^2.0.0'; export { LRUCache } from 'npm:lru-cache@^10.0.0'; -export { DB as Sqlite } from 'https://deno.land/x/sqlite@v3.7.0/mod.ts'; -export { serve } from 'https://deno.land/std@0.177.0/http/server.ts'; +export { DB as Sqlite } from 'https://deno.land/x/sqlite@v3.7.3/mod.ts'; +export * as dotenv from 'https://deno.land/std@0.197.0/dotenv/mod.ts'; diff --git a/src/server.ts b/src/server.ts index c9d3f4f..76cbc9f 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,6 +1,3 @@ -import 'https://deno.land/std@0.177.0/dotenv/load.ts'; -import { serve } from '@/deps.ts'; - import app from './app.ts'; -serve(app.fetch); +Deno.serve(app.fetch); diff --git a/src/transformers/nostr-to-activitypub.ts b/src/transformers/nostr-to-activitypub.ts index 82f328d..ae7ea77 100644 --- a/src/transformers/nostr-to-activitypub.ts +++ b/src/transformers/nostr-to-activitypub.ts @@ -6,13 +6,9 @@ import type { Event } from '@/event.ts'; import type { Actor } from '@/schemas/activitypub.ts'; /** Nostr metadata event to ActivityPub actor. */ -async function toActor(event: Event<0>): Promise { +async function toActor(event: Event<0>, username: string): Promise { const content = parseMetaContent(event); - if (!content.nip05) return; - const [username, hostname] = content.nip05.split('@'); - if (hostname !== Conf.url.hostname) return; - return { type: 'Person', id: Conf.local(`/users/${username}`), diff --git a/src/utils/rsa.ts b/src/utils/rsa.ts index b6865b4..9155a72 100644 --- a/src/utils/rsa.ts +++ b/src/utils/rsa.ts @@ -11,7 +11,7 @@ async function buildSeed(pubkey: string): Promise { const key = await Conf.cryptoKey; const data = new TextEncoder().encode(pubkey); const signature = await window.crypto.subtle.sign('HMAC', key, data); - return secp.utils.bytesToHex(new Uint8Array(signature)); + return secp.etc.bytesToHex(new Uint8Array(signature)); } async function getPublicKeyPem(pubkey: string): Promise {