Compare commits
8 Commits
feature/ta
...
204b4f44c7
| Author | SHA1 | Date | |
|---|---|---|---|
| 204b4f44c7 | |||
|
8e802f314a
|
|||
|
f4d1ba897b
|
|||
| 7f975f2dbb | |||
|
5e1e249052
|
|||
|
b376bbd2aa
|
|||
|
51ae16e57f
|
|||
|
2ac3180c0f
|
18
.gitea/workflows/ci.yml
Normal file
18
.gitea/workflows/ci.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
jobs:
|
||||
test_and_lint:
|
||||
name: Test and lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
- uses: denoland/setup-deno@v2
|
||||
with:
|
||||
deno-version: v2.1.x
|
||||
- run: "deno task test"
|
||||
- run: "deno lint"
|
||||
18
deno.json
18
deno.json
@@ -1,18 +1,20 @@
|
||||
{
|
||||
"tasks": {
|
||||
"dev": "deno run --allow-all --watch server.ts",
|
||||
"server": "deno run --allow-all server.ts"
|
||||
"server": "deno run --allow-all server.ts",
|
||||
"compile": "deno compile --allow-all --include ./assets/ --output substr server.ts",
|
||||
"test": "deno test --allow-read --allow-env"
|
||||
},
|
||||
"imports": {
|
||||
"@deno/gfm": "jsr:@deno/gfm@^0.9.0",
|
||||
"@nostr/tools": "jsr:@nostr/tools@^2.3.1",
|
||||
"@nostrify/nostrify": "jsr:@nostrify/nostrify@^0.36.1",
|
||||
"@oak/oak": "jsr:@oak/oak@^17.1.0",
|
||||
"@deno/gfm": "jsr:@deno/gfm@^0.10.0",
|
||||
"@nostr/tools": "jsr:@nostr/tools@^2.10.4",
|
||||
"@nostrify/nostrify": "jsr:@nostrify/nostrify@^0.36.2",
|
||||
"@oak/oak": "jsr:@oak/oak@^17.1.3",
|
||||
"@std/dotenv": "jsr:@std/dotenv@^0.225.2",
|
||||
"@std/expect": "jsr:@std/expect@^1.0.5",
|
||||
"@std/testing": "jsr:@std/testing@^1.0.3",
|
||||
"@std/expect": "jsr:@std/expect@^1.0.8",
|
||||
"@std/testing": "jsr:@std/testing@^1.0.5",
|
||||
"@std/yaml": "jsr:@std/yaml@^1.0.5",
|
||||
"ldapts": "npm:ldapts@^7.2.1"
|
||||
"ldapts": "npm:ldapts@^7.2.2"
|
||||
},
|
||||
"fmt": {
|
||||
"exclude": [
|
||||
|
||||
215
deno.lock
generated
215
deno.lock
generated
@@ -1,60 +1,67 @@
|
||||
{
|
||||
"version": "4",
|
||||
"specifiers": {
|
||||
"jsr:@deno/gfm@0.9": "0.9.0",
|
||||
"jsr:@deno/gfm@0.10": "0.10.0",
|
||||
"jsr:@denosaurs/emoji@0.3": "0.3.1",
|
||||
"jsr:@nostr/tools@^2.3.1": "2.3.1",
|
||||
"jsr:@nostrify/nostrify@~0.36.1": "0.36.1",
|
||||
"jsr:@nostr/tools@^2.10.4": "2.10.4",
|
||||
"jsr:@nostrify/nostrify@~0.36.2": "0.36.2",
|
||||
"jsr:@nostrify/types@0.35": "0.35.0",
|
||||
"jsr:@oak/commons@1": "1.0.0",
|
||||
"jsr:@oak/oak@^17.1.0": "17.1.0",
|
||||
"jsr:@std/assert@1": "1.0.6",
|
||||
"jsr:@std/assert@^1.0.6": "1.0.6",
|
||||
"jsr:@std/bytes@1": "1.0.2",
|
||||
"jsr:@std/bytes@^1.0.2": "1.0.2",
|
||||
"jsr:@oak/oak@^17.1.3": "17.1.3",
|
||||
"jsr:@std/assert@0.224": "0.224.0",
|
||||
"jsr:@std/assert@1": "1.0.8",
|
||||
"jsr:@std/assert@^1.0.8": "1.0.8",
|
||||
"jsr:@std/bytes@1": "1.0.4",
|
||||
"jsr:@std/bytes@^1.0.2": "1.0.4",
|
||||
"jsr:@std/crypto@0.224": "0.224.0",
|
||||
"jsr:@std/crypto@1": "1.0.3",
|
||||
"jsr:@std/data-structures@^1.0.4": "1.0.4",
|
||||
"jsr:@std/dotenv@~0.225.2": "0.225.2",
|
||||
"jsr:@std/encoding@0.224": "0.224.3",
|
||||
"jsr:@std/encoding@1": "1.0.5",
|
||||
"jsr:@std/encoding@^1.0.5": "1.0.5",
|
||||
"jsr:@std/encoding@~0.224.1": "0.224.3",
|
||||
"jsr:@std/expect@^1.0.5": "1.0.5",
|
||||
"jsr:@std/fs@^1.0.4": "1.0.4",
|
||||
"jsr:@std/http@1": "1.0.8",
|
||||
"jsr:@std/internal@^1.0.4": "1.0.4",
|
||||
"jsr:@std/expect@^1.0.8": "1.0.8",
|
||||
"jsr:@std/fs@^1.0.5": "1.0.5",
|
||||
"jsr:@std/http@1": "1.0.10",
|
||||
"jsr:@std/internal@^1.0.5": "1.0.5",
|
||||
"jsr:@std/io@0.224": "0.224.9",
|
||||
"jsr:@std/media-types@1": "1.0.3",
|
||||
"jsr:@std/path@1": "1.0.6",
|
||||
"jsr:@std/path@^1.0.6": "1.0.6",
|
||||
"jsr:@std/testing@^1.0.3": "1.0.3",
|
||||
"jsr:@std/media-types@1": "1.1.0",
|
||||
"jsr:@std/path@1": "1.0.8",
|
||||
"jsr:@std/path@^1.0.7": "1.0.8",
|
||||
"jsr:@std/path@^1.0.8": "1.0.8",
|
||||
"jsr:@std/testing@^1.0.5": "1.0.5",
|
||||
"jsr:@std/yaml@*": "1.0.5",
|
||||
"jsr:@std/yaml@^1.0.5": "1.0.5",
|
||||
"npm:@noble/ciphers@~0.5.1": "0.5.3",
|
||||
"npm:@noble/curves@1.2.0": "1.2.0",
|
||||
"npm:@noble/hashes@1.3.1": "1.3.1",
|
||||
"npm:@scure/base@1.1.1": "1.1.1",
|
||||
"npm:@scure/bip32@^1.4.0": "1.4.0",
|
||||
"npm:@scure/bip39@^1.3.0": "1.3.0",
|
||||
"npm:@scure/base@^1.1.6": "1.2.1",
|
||||
"npm:@scure/bip32@1.3.1": "1.3.1",
|
||||
"npm:@scure/bip32@^1.4.0": "1.6.0",
|
||||
"npm:@scure/bip39@1.2.1": "1.2.1",
|
||||
"npm:@scure/bip39@^1.3.0": "1.5.0",
|
||||
"npm:github-slugger@2": "2.0.0",
|
||||
"npm:he@^1.2.0": "1.2.0",
|
||||
"npm:katex@0.16": "0.16.11",
|
||||
"npm:ldapts@^7.2.1": "7.2.1",
|
||||
"npm:lru-cache@^10.2.0": "10.2.2",
|
||||
"npm:marked-alert@2": "2.1.0_marked@12.0.2",
|
||||
"npm:ldapts@^7.2.2": "7.2.2",
|
||||
"npm:lru-cache@^10.2.0": "10.4.3",
|
||||
"npm:marked-alert@2": "2.1.2_marked@12.0.2",
|
||||
"npm:marked-footnote@^1.2.0": "1.2.4_marked@12.0.2",
|
||||
"npm:marked-gfm-heading-id@^3.1.0": "3.2.0_marked@12.0.2",
|
||||
"npm:marked@12": "12.0.2",
|
||||
"npm:nostr-tools@^2.7.0": "2.7.0",
|
||||
"npm:path-to-regexp@*": "6.2.1",
|
||||
"npm:nostr-tools@^2.7.0": "2.10.4",
|
||||
"npm:nostr-wasm@0.1.0": "0.1.0",
|
||||
"npm:path-to-regexp@6.2.1": "6.2.1",
|
||||
"npm:prismjs@^1.29.0": "1.29.0",
|
||||
"npm:sanitize-html@^2.11.0": "2.13.1",
|
||||
"npm:sanitize-html@^2.13.0": "2.13.1",
|
||||
"npm:websocket-ts@^2.1.5": "2.1.5",
|
||||
"npm:zod@^3.23.8": "3.23.8"
|
||||
},
|
||||
"jsr": {
|
||||
"@deno/gfm@0.9.0": {
|
||||
"integrity": "9002dbdb6e382e247509edfeae3afdb9232f5ca98a8210ef186d42084e9ded30",
|
||||
"@deno/gfm@0.10.0": {
|
||||
"integrity": "51708205e3559a4aeb6afb29d07c5bfafe7941f91bb360351ef6621de9a39527",
|
||||
"dependencies": [
|
||||
"jsr:@denosaurs/emoji",
|
||||
"npm:github-slugger",
|
||||
@@ -71,22 +78,27 @@
|
||||
"@denosaurs/emoji@0.3.1": {
|
||||
"integrity": "b0aed5f55dec99e83da7c9637fe0a36d1d6252b7c99deaaa3fc5dea3fcf3da8b"
|
||||
},
|
||||
"@nostr/tools@2.3.1": {
|
||||
"integrity": "af01dc45cb28784c584d7a0699707196f397bcc53946efa582a01b11ddde4d61",
|
||||
"@nostr/tools@2.10.4": {
|
||||
"integrity": "7fda015c96b4f674727843aecb990e2af1989e4724588415ccf6f69066abfd4f",
|
||||
"dependencies": [
|
||||
"npm:@noble/ciphers",
|
||||
"npm:@noble/curves",
|
||||
"npm:@noble/hashes",
|
||||
"npm:@scure/base"
|
||||
"npm:@scure/base@1.1.1",
|
||||
"npm:@scure/bip32@1.3.1",
|
||||
"npm:@scure/bip39@1.2.1",
|
||||
"npm:nostr-wasm"
|
||||
]
|
||||
},
|
||||
"@nostrify/nostrify@0.36.1": {
|
||||
"integrity": "f76c803c0bda5df1c172f25d2313980344b0431df2a973ab3e1dd61e9e7b4b1a",
|
||||
"@nostrify/nostrify@0.36.2": {
|
||||
"integrity": "cc4787ca170b623a2e5dfed1baa4426077daa6143af728ea7dd325d58f4d04d6",
|
||||
"dependencies": [
|
||||
"jsr:@nostrify/types",
|
||||
"jsr:@std/crypto@0.224",
|
||||
"jsr:@std/encoding@~0.224.1",
|
||||
"npm:@scure/bip32",
|
||||
"npm:@scure/bip39",
|
||||
"npm:@scure/base@^1.1.6",
|
||||
"npm:@scure/bip32@^1.4.0",
|
||||
"npm:@scure/bip39@^1.3.0",
|
||||
"npm:lru-cache",
|
||||
"npm:nostr-tools",
|
||||
"npm:websocket-ts",
|
||||
@@ -101,34 +113,44 @@
|
||||
"dependencies": [
|
||||
"jsr:@std/assert@1",
|
||||
"jsr:@std/bytes@1",
|
||||
"jsr:@std/crypto",
|
||||
"jsr:@std/crypto@1",
|
||||
"jsr:@std/encoding@1",
|
||||
"jsr:@std/http",
|
||||
"jsr:@std/media-types"
|
||||
]
|
||||
},
|
||||
"@oak/oak@17.1.0": {
|
||||
"integrity": "14ffb400c3c268bdc7b3a838664fab782b4ed35bb0dfe7669013c95bb12a9503",
|
||||
"@oak/oak@17.1.3": {
|
||||
"integrity": "d89296c22db91681dd3a2a1e1fd14e258d0d5a9654de55637aee5b661c159f33",
|
||||
"dependencies": [
|
||||
"jsr:@oak/commons",
|
||||
"jsr:@std/assert@1",
|
||||
"jsr:@std/bytes@1",
|
||||
"jsr:@std/crypto",
|
||||
"jsr:@std/crypto@1",
|
||||
"jsr:@std/http",
|
||||
"jsr:@std/io",
|
||||
"jsr:@std/media-types",
|
||||
"jsr:@std/path@1",
|
||||
"npm:path-to-regexp@6.2.1"
|
||||
"npm:path-to-regexp"
|
||||
]
|
||||
},
|
||||
"@std/assert@1.0.6": {
|
||||
"integrity": "1904c05806a25d94fe791d6d883b685c9e2dcd60e4f9fc30f4fc5cf010c72207",
|
||||
"@std/assert@0.224.0": {
|
||||
"integrity": "8643233ec7aec38a940a8264a6e3eed9bfa44e7a71cc6b3c8874213ff401967f"
|
||||
},
|
||||
"@std/assert@1.0.8": {
|
||||
"integrity": "ebe0bd7eb488ee39686f77003992f389a06c3da1bbd8022184804852b2fa641b",
|
||||
"dependencies": [
|
||||
"jsr:@std/internal"
|
||||
]
|
||||
},
|
||||
"@std/bytes@1.0.2": {
|
||||
"integrity": "fbdee322bbd8c599a6af186a1603b3355e59a5fb1baa139f8f4c3c9a1b3e3d57"
|
||||
"@std/bytes@1.0.4": {
|
||||
"integrity": "11a0debe522707c95c7b7ef89b478c13fb1583a7cfb9a85674cd2cc2e3a28abc"
|
||||
},
|
||||
"@std/crypto@0.224.0": {
|
||||
"integrity": "154ef3ff08ef535562ef1a718718c5b2c5fc3808f0f9100daad69e829bfcdf2d",
|
||||
"dependencies": [
|
||||
"jsr:@std/assert@0.224",
|
||||
"jsr:@std/encoding@0.224"
|
||||
]
|
||||
},
|
||||
"@std/crypto@1.0.3": {
|
||||
"integrity": "a2a32f51ddef632d299e3879cd027c630dcd4d1d9a5285d6e6788072f4e51e7f"
|
||||
@@ -145,27 +167,27 @@
|
||||
"@std/encoding@1.0.5": {
|
||||
"integrity": "ecf363d4fc25bd85bd915ff6733a7e79b67e0e7806334af15f4645c569fefc04"
|
||||
},
|
||||
"@std/expect@1.0.5": {
|
||||
"integrity": "8c7ac797e2ffe57becc6399c0f2fd06230cb9ef124d45229c6e592c563824af1",
|
||||
"@std/expect@1.0.8": {
|
||||
"integrity": "27e40d8f3aefb372fc6a703fb0b69e34560e72a2f78705178babdffa00119a5f",
|
||||
"dependencies": [
|
||||
"jsr:@std/assert@^1.0.6",
|
||||
"jsr:@std/assert@^1.0.8",
|
||||
"jsr:@std/internal"
|
||||
]
|
||||
},
|
||||
"@std/fs@1.0.4": {
|
||||
"integrity": "2907d32d8d1d9e540588fd5fe0ec21ee638134bd51df327ad4e443aaef07123c",
|
||||
"@std/fs@1.0.5": {
|
||||
"integrity": "41806ad6823d0b5f275f9849a2640d87e4ef67c51ee1b8fb02426f55e02fd44e",
|
||||
"dependencies": [
|
||||
"jsr:@std/path@^1.0.6"
|
||||
"jsr:@std/path@^1.0.7"
|
||||
]
|
||||
},
|
||||
"@std/http@1.0.8": {
|
||||
"integrity": "6ea1b2e8d33929967754a3b6d6c6f399ad6647d7bbb5a466c1eaf9b294a6ebcd",
|
||||
"@std/http@1.0.10": {
|
||||
"integrity": "4e32d11493ab04e3ef09f104f0cb9beb4228b1d4b47c5469573c2c294c0d3692",
|
||||
"dependencies": [
|
||||
"jsr:@std/encoding@^1.0.5"
|
||||
]
|
||||
},
|
||||
"@std/internal@1.0.4": {
|
||||
"integrity": "62e8e4911527e5e4f307741a795c0b0a9e6958d0b3790716ae71ce085f755422"
|
||||
"@std/internal@1.0.5": {
|
||||
"integrity": "54a546004f769c1ac9e025abd15a76b6671ddc9687e2313b67376125650dc7ba"
|
||||
},
|
||||
"@std/io@0.224.9": {
|
||||
"integrity": "4414664b6926f665102e73c969cfda06d2c4c59bd5d0c603fd4f1b1c840d6ee3",
|
||||
@@ -173,20 +195,20 @@
|
||||
"jsr:@std/bytes@^1.0.2"
|
||||
]
|
||||
},
|
||||
"@std/media-types@1.0.3": {
|
||||
"integrity": "b12d30a7852f7578f4d210622df713bbfd1cbdd9b4ec2eaf5c1845ab70bab159"
|
||||
"@std/media-types@1.1.0": {
|
||||
"integrity": "c9d093f0c05c3512932b330e3cc1fe1d627b301db33a4c2c2185c02471d6eaa4"
|
||||
},
|
||||
"@std/path@1.0.6": {
|
||||
"integrity": "ab2c55f902b380cf28e0eec501b4906e4c1960d13f00e11cfbcd21de15f18fed"
|
||||
"@std/path@1.0.8": {
|
||||
"integrity": "548fa456bb6a04d3c1a1e7477986b6cffbce95102d0bb447c67c4ee70e0364be"
|
||||
},
|
||||
"@std/testing@1.0.3": {
|
||||
"integrity": "f98c2bee53860a5916727d7e7d3abe920dd6f9edace022e2d059f00d05c2cf42",
|
||||
"@std/testing@1.0.5": {
|
||||
"integrity": "6e693cbec94c81a1ad3df668685c7ba8e20742bb10305bc7137faa5cf16d2ec4",
|
||||
"dependencies": [
|
||||
"jsr:@std/assert@^1.0.6",
|
||||
"jsr:@std/assert@^1.0.8",
|
||||
"jsr:@std/data-structures",
|
||||
"jsr:@std/fs",
|
||||
"jsr:@std/internal",
|
||||
"jsr:@std/path@^1.0.6"
|
||||
"jsr:@std/path@^1.0.8"
|
||||
]
|
||||
},
|
||||
"@std/yaml@1.0.5": {
|
||||
@@ -209,10 +231,10 @@
|
||||
"@noble/hashes@1.3.2"
|
||||
]
|
||||
},
|
||||
"@noble/curves@1.4.0": {
|
||||
"integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==",
|
||||
"@noble/curves@1.7.0": {
|
||||
"integrity": "sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==",
|
||||
"dependencies": [
|
||||
"@noble/hashes@1.4.0"
|
||||
"@noble/hashes@1.6.0"
|
||||
]
|
||||
},
|
||||
"@noble/hashes@1.3.1": {
|
||||
@@ -221,43 +243,46 @@
|
||||
"@noble/hashes@1.3.2": {
|
||||
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ=="
|
||||
},
|
||||
"@noble/hashes@1.4.0": {
|
||||
"integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg=="
|
||||
"@noble/hashes@1.6.0": {
|
||||
"integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ=="
|
||||
},
|
||||
"@noble/hashes@1.6.1": {
|
||||
"integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w=="
|
||||
},
|
||||
"@scure/base@1.1.1": {
|
||||
"integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA=="
|
||||
},
|
||||
"@scure/base@1.1.7": {
|
||||
"integrity": "sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g=="
|
||||
"@scure/base@1.2.1": {
|
||||
"integrity": "sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ=="
|
||||
},
|
||||
"@scure/bip32@1.3.1": {
|
||||
"integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==",
|
||||
"dependencies": [
|
||||
"@noble/curves@1.1.0",
|
||||
"@noble/hashes@1.3.2",
|
||||
"@scure/base@1.1.7"
|
||||
"@scure/base@1.1.1"
|
||||
]
|
||||
},
|
||||
"@scure/bip32@1.4.0": {
|
||||
"integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==",
|
||||
"@scure/bip32@1.6.0": {
|
||||
"integrity": "sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA==",
|
||||
"dependencies": [
|
||||
"@noble/curves@1.4.0",
|
||||
"@noble/hashes@1.4.0",
|
||||
"@scure/base@1.1.7"
|
||||
"@noble/curves@1.7.0",
|
||||
"@noble/hashes@1.6.1",
|
||||
"@scure/base@1.2.1"
|
||||
]
|
||||
},
|
||||
"@scure/bip39@1.2.1": {
|
||||
"integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==",
|
||||
"dependencies": [
|
||||
"@noble/hashes@1.3.2",
|
||||
"@scure/base@1.1.7"
|
||||
"@scure/base@1.1.1"
|
||||
]
|
||||
},
|
||||
"@scure/bip39@1.3.0": {
|
||||
"integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==",
|
||||
"@scure/bip39@1.5.0": {
|
||||
"integrity": "sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A==",
|
||||
"dependencies": [
|
||||
"@noble/hashes@1.4.0",
|
||||
"@scure/base@1.1.7"
|
||||
"@noble/hashes@1.6.1",
|
||||
"@scure/base@1.2.1"
|
||||
]
|
||||
},
|
||||
"@types/asn1@0.2.4": {
|
||||
@@ -345,8 +370,8 @@
|
||||
"commander"
|
||||
]
|
||||
},
|
||||
"ldapts@7.2.1": {
|
||||
"integrity": "sha512-2NSA9drjHdRiApF+TO18c+Hy/uyBLs96OS6Gia4+dPQWPxvqDbu3Ji2beCbNCXTvvgxDj4cLZ0WoOZLt5ojfAg==",
|
||||
"ldapts@7.2.2": {
|
||||
"integrity": "sha512-UotAq24/vJEz0m3w/jgwZm7JGNw8M6vexL/5KU5pe3aIZWBkT/HRhjsPw/buRqKSK5Y0vTu5Zv8iyPgQF7ozzg==",
|
||||
"dependencies": [
|
||||
"@types/asn1",
|
||||
"asn1",
|
||||
@@ -356,11 +381,11 @@
|
||||
"whatwg-url"
|
||||
]
|
||||
},
|
||||
"lru-cache@10.2.2": {
|
||||
"integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ=="
|
||||
"lru-cache@10.4.3": {
|
||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
|
||||
},
|
||||
"marked-alert@2.1.0_marked@12.0.2": {
|
||||
"integrity": "sha512-X95Z8PCDgWa0bBfM70GxZG3LD/leUrhXc3cx3w1eFExBhswd1oXn/S4S+9H8ypPdCY7okREb4dItUOc+VJq4jQ==",
|
||||
"marked-alert@2.1.2_marked@12.0.2": {
|
||||
"integrity": "sha512-EFNRZ08d8L/iEIPLTlQMDjvwIsj03gxWCczYTht6DCiHJIZhMk4NK5gtPY9UqAYb09eV5VGT+jD4lp396E0I+w==",
|
||||
"dependencies": [
|
||||
"marked"
|
||||
]
|
||||
@@ -387,8 +412,8 @@
|
||||
"nanoid@3.3.7": {
|
||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="
|
||||
},
|
||||
"nostr-tools@2.7.0": {
|
||||
"integrity": "sha512-jJoL2J1CBiKDxaXZww27nY/Wsuxzx7AULxmGKFce4sskDu1tohNyfnzYQ8BvDyvkstU8kNZUAXPL32tre33uig==",
|
||||
"nostr-tools@2.10.4": {
|
||||
"integrity": "sha512-biU7sk+jxHgVASfobg2T5ttxOGGSt69wEVBC51sHHOEaKAAdzHBLV/I2l9Rf61UzClhliZwNouYhqIso4a3HYg==",
|
||||
"dependencies": [
|
||||
"@noble/ciphers",
|
||||
"@noble/curves@1.2.0",
|
||||
@@ -454,8 +479,8 @@
|
||||
"undici-types@6.19.8": {
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
|
||||
},
|
||||
"uuid@10.0.0": {
|
||||
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="
|
||||
"uuid@11.0.3": {
|
||||
"integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg=="
|
||||
},
|
||||
"webidl-conversions@7.0.0": {
|
||||
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="
|
||||
@@ -488,15 +513,15 @@
|
||||
},
|
||||
"workspace": {
|
||||
"dependencies": [
|
||||
"jsr:@deno/gfm@0.9",
|
||||
"jsr:@nostr/tools@^2.3.1",
|
||||
"jsr:@nostrify/nostrify@~0.36.1",
|
||||
"jsr:@oak/oak@^17.1.0",
|
||||
"jsr:@deno/gfm@0.10",
|
||||
"jsr:@nostr/tools@^2.10.4",
|
||||
"jsr:@nostrify/nostrify@~0.36.2",
|
||||
"jsr:@oak/oak@^17.1.3",
|
||||
"jsr:@std/dotenv@~0.225.2",
|
||||
"jsr:@std/expect@^1.0.5",
|
||||
"jsr:@std/testing@^1.0.3",
|
||||
"jsr:@std/expect@^1.0.8",
|
||||
"jsr:@std/testing@^1.0.5",
|
||||
"jsr:@std/yaml@^1.0.5",
|
||||
"npm:ldapts@^7.2.1"
|
||||
"npm:ldapts@^7.2.2"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
2
feeds.ts
2
feeds.ts
@@ -36,7 +36,7 @@ export async function profileAtomFeed(
|
||||
<title>${profile.name} on Nostr (Articles)</title>
|
||||
<id>${feedId}</id>
|
||||
<updated>${isoDate(lastUpdate)}</updated>
|
||||
<icon>${profile.picture}</icon>
|
||||
<icon>${profile.avatarImageUrl}</icon>
|
||||
<author>
|
||||
<name>${name}</name>
|
||||
</author>
|
||||
|
||||
@@ -9,7 +9,6 @@ const nprofileHandler = async function (ctx: Context) {
|
||||
|
||||
try {
|
||||
data = nip19.decode(nprofile).data as nip19.ProfilePointer;
|
||||
console.log(data);
|
||||
} catch (_e) {
|
||||
notFoundHandler(ctx);
|
||||
return;
|
||||
|
||||
@@ -27,7 +27,7 @@ const userEventHandler = async function (ctx: Context) {
|
||||
const article = new Article(articleEvent);
|
||||
const profile = new Profile(profileEvent, username);
|
||||
const html = await articleHtml(article, profile);
|
||||
generateOgProfileImage(profile);
|
||||
await generateOgProfileImage(profile);
|
||||
|
||||
ctx.response.body = html;
|
||||
} else {
|
||||
|
||||
@@ -21,7 +21,7 @@ const userProfileHandler = async function (ctx: Context) {
|
||||
const profile = new Profile(profileEvent, username);
|
||||
const articles = await fetchArticlesByAuthor(pubkey, 210);
|
||||
const html = await profilePageHtml(profile, articles);
|
||||
generateOgProfileImage(profile);
|
||||
await generateOgProfileImage(profile);
|
||||
|
||||
ctx.response.body = html;
|
||||
} else {
|
||||
|
||||
6
html.ts
6
html.ts
@@ -55,7 +55,7 @@ export async function articleHtml(
|
||||
${draftLabel}
|
||||
<h1>${titleHtml(article.title)}</h1>
|
||||
<div class="meta">
|
||||
<img class="avatar" src="${profile.picture}" alt="User Avatar" />
|
||||
<img class="avatar" src="${profile.avatarImageUrl}" alt="User Avatar" />
|
||||
<div class="content">
|
||||
<span class="name"><a href="/@${profile.username}">${profile.name}</a></span>
|
||||
<span class="date">${publishedAtFormatted}</span>
|
||||
@@ -148,7 +148,7 @@ export async function profilePageHtml(
|
||||
const body = `
|
||||
<main class="profile-page">
|
||||
<header>
|
||||
<img class="avatar" src="${profile.picture}" alt="User Avatar" />
|
||||
<img class="avatar" src="${profile.avatarImageUrl}" alt="User Avatar" />
|
||||
<div class="bio">
|
||||
<h1>${profile.name}</h1>
|
||||
${nip05Html}
|
||||
@@ -211,6 +211,7 @@ function feedLinksHtml(profile: Profile) {
|
||||
|
||||
function profileMetaHtml(profile: Profile) {
|
||||
return `
|
||||
<link rel="icon" href="${profile.avatarImageUrl}" type="image/png">
|
||||
<meta property="og:url" content="${profile.profileUrl}">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="${profile.name} on Nostr">
|
||||
@@ -229,6 +230,7 @@ function articleMetaHtml(article: Article, profile: Profile) {
|
||||
const imageUrl = article.image || profile.ogImageUrl;
|
||||
|
||||
return `
|
||||
<link rel="icon" href="${profile.avatarImageUrl}" type="image/png">
|
||||
<meta property="og:url" content="${article.url}">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="${article.title}">
|
||||
|
||||
66
magick.ts
66
magick.ts
@@ -8,7 +8,7 @@ if (!magick) {
|
||||
log("ImageMagick is not installed. Cannot generate preview images", "yellow")
|
||||
}
|
||||
|
||||
function createRoundedImage(profile: Profile) {
|
||||
function createProfileImage(profile: Profile) {
|
||||
if (!magick || !profile.picture) return false;
|
||||
|
||||
const args = [
|
||||
@@ -16,24 +16,44 @@ function createRoundedImage(profile: Profile) {
|
||||
'-resize', '256x256^',
|
||||
'-gravity', 'center',
|
||||
'-extent', '256x256',
|
||||
'(', '+clone', '-alpha', 'extract',
|
||||
'-draw', "fill black polygon 0,0 0,128 128,0 fill white circle 128,128 128,0",
|
||||
'(', '+clone', '-flip', ')', '-compose', 'Multiply', '-composite',
|
||||
'(', '+clone', '-flop', ')', '-compose', 'Multiply', '-composite',
|
||||
')',
|
||||
'-alpha', 'off',
|
||||
'-compose', 'CopyOpacity',
|
||||
'-composite',
|
||||
`${tmpImgDir}/p-${profile.event.id}-rounded.png`
|
||||
`${tmpImgDir}/p-${profile.event.id}.png`
|
||||
];
|
||||
|
||||
return runCommand(magick, args);
|
||||
}
|
||||
|
||||
async function createRoundedProfileImage(profile: Profile) {
|
||||
if (!magick || !profile.picture) return false;
|
||||
|
||||
const status = await generateProfileImage(profile);
|
||||
|
||||
if (status && status.success) {
|
||||
const args = [
|
||||
`${tmpImgDir}/p-${profile.event.id}.png`,
|
||||
'-resize', '256x256^',
|
||||
'-gravity', 'center',
|
||||
'-extent', '256x256',
|
||||
'(', '+clone', '-alpha', 'extract',
|
||||
'-draw', "fill black polygon 0,0 0,128 128,0 fill white circle 128,128 128,0",
|
||||
'(', '+clone', '-flip', ')', '-compose', 'Multiply', '-composite',
|
||||
'(', '+clone', '-flop', ')', '-compose', 'Multiply', '-composite',
|
||||
')',
|
||||
'-alpha', 'off',
|
||||
'-compose', 'CopyOpacity',
|
||||
'-composite',
|
||||
`${tmpImgDir}/p-${profile.event.id}-rounded.png`
|
||||
];
|
||||
|
||||
return runCommand(magick, args);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function createOgImage(profile: Profile, ogImagePath: string, backgroundColor: string) {
|
||||
if (!magick) return false;
|
||||
|
||||
const status = await createRoundedImage(profile);
|
||||
const status = await createRoundedProfileImage(profile);
|
||||
|
||||
if (status && status.success) {
|
||||
const args = [
|
||||
@@ -51,6 +71,25 @@ async function createOgImage(profile: Profile, ogImagePath: string, backgroundCo
|
||||
}
|
||||
};
|
||||
|
||||
export async function generateProfileImage(profile: Profile) {
|
||||
if (!magick || !profile.picture) return false;
|
||||
|
||||
const imagePath = `${tmpImgDir}/p-${profile.event.id}.png`;
|
||||
const fileExists = await checkFileExists(imagePath);
|
||||
|
||||
if (fileExists) {
|
||||
return { success: true };
|
||||
} else {
|
||||
const status = await createProfileImage(profile);
|
||||
if (status && status.success) {
|
||||
log(`Created avatar image for ${profile.username}: ${imagePath}`, "blue")
|
||||
return status;
|
||||
} else {
|
||||
log(`Could not create avatar image for ${profile.username}`, "yellow")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateOgProfileImage(profile: Profile) {
|
||||
if (!magick || !profile.picture) return false;
|
||||
|
||||
@@ -58,10 +97,13 @@ export async function generateOgProfileImage(profile: Profile) {
|
||||
const backgroundColor = "#333333";
|
||||
const fileExists = await checkFileExists(ogImagePath);
|
||||
|
||||
if (!fileExists) {
|
||||
if (fileExists) {
|
||||
return { success: true };
|
||||
} else {
|
||||
const status = await createOgImage(profile, ogImagePath, backgroundColor);
|
||||
if (status && status.success) {
|
||||
log(`Created OG image for ${profile.username}: ${ogImagePath}`, "blue")
|
||||
return status;
|
||||
} else {
|
||||
log(`Could not create OG image for ${profile.username}`, "yellow")
|
||||
}
|
||||
|
||||
@@ -63,6 +63,14 @@ export default class Profile {
|
||||
return `${config.base_url}/@${this.username}`;
|
||||
}
|
||||
|
||||
get avatarImageUrl(): string {
|
||||
if (magick) {
|
||||
return `${config.base_url}/assets/g/img/p-${this.event.id}.png`;
|
||||
} else {
|
||||
return this.picture || "";
|
||||
}
|
||||
}
|
||||
|
||||
get ogImageUrl(): string {
|
||||
if (magick) {
|
||||
return `${config.base_url}/assets/g/img/og-p-${this.event.id}.png`;
|
||||
|
||||
Reference in New Issue
Block a user