Compare commits
7
Commits
f7c6034fb0
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d8c500430 | ||
|
|
7da707522c | ||
|
|
c64f6ca781 | ||
|
|
8b11c41267 | ||
|
|
6c86cfe5d2 | ||
|
|
a74d7b91b8 | ||
|
|
5f6e638903 |
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 David Lick
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
setup:
|
setup:
|
||||||
export EAGER_SERVICE_LOADING=1 \
|
export EAGER_SERVICE_LOADING=1 \
|
||||||
SERVICES=lambda,ssm \
|
SERVICES=lambda,ssm,kms \
|
||||||
|
LAMBDA_EXECUTOR=docker \
|
||||||
AWS_ACCESS_KEY_ID=test \
|
AWS_ACCESS_KEY_ID=test \
|
||||||
AWS_SECRET_ACCESS_KEY=test
|
AWS_SECRET_ACCESS_KEY=test
|
||||||
dockerd &
|
dockerd &
|
||||||
@@ -10,13 +11,20 @@ setup:
|
|||||||
--function-name rss-nostr-lambda \
|
--function-name rss-nostr-lambda \
|
||||||
--runtime nodejs20.x \
|
--runtime nodejs20.x \
|
||||||
--timeout 900 \
|
--timeout 900 \
|
||||||
|
--memory-size 1024 \
|
||||||
--zip-file fileb://handler.zip \
|
--zip-file fileb://handler.zip \
|
||||||
--handler index.handler \
|
--handler index.handler \
|
||||||
--role arn:aws:iam::000000000000:role/lambda-role \
|
--role arn:aws:iam::000000000000:role/lambda-role \
|
||||||
--region us-east-1
|
--region us-east-1
|
||||||
awslocal ssm put-parameter \
|
awslocal ssm put-parameter \
|
||||||
--name /rss-nostr-lambda/last-run-time \
|
--name /rss-nostr-lambda/last-run-time \
|
||||||
--value "2023-11-24T00:00:00Z" \
|
--value "2023-11-23T14:46:56Z" \
|
||||||
|
--type "String" \
|
||||||
|
--overwrite
|
||||||
|
awslocal ssm put-parameter \
|
||||||
|
--name /rss-nostr-lambda/nsec \
|
||||||
|
--value "nsec1azwx0ajvjquay870m69vxxmkf7prxekdj58fq92yulvt2l02zwnsmzt5vf" \
|
||||||
|
--type "SecureString" \
|
||||||
--overwrite
|
--overwrite
|
||||||
rm handler.zip
|
rm handler.zip
|
||||||
|
|
||||||
@@ -25,7 +33,15 @@ invoke:
|
|||||||
--region us-east-1 \
|
--region us-east-1 \
|
||||||
--function-name rss-nostr-lambda \
|
--function-name rss-nostr-lambda \
|
||||||
--cli-binary-format raw-in-base64-out \
|
--cli-binary-format raw-in-base64-out \
|
||||||
--payload '{"dryRun":true,"feedUrl":"https://nitter.1d4.us/culturaltutor/rss","nostrNsec":"nsec1wp68lflspznnmelmjh5ktflyv6c4ljf8xrlkey0w8yqr4305awcs8wyakj","lastRunTimeParam":"/rss-nostr-lambda/last-run-time"}' \
|
--payload '{"feedUrl":"https://nitter.1d4.us/culturaltutor/rss","nostrNsecParam":"/rss-nostr-lambda/nsec","lastRunTimeParam":"/rss-nostr-lambda/last-run-time"}' \
|
||||||
|
response.json
|
||||||
|
|
||||||
|
invoke-dryrun:
|
||||||
|
awslocal lambda invoke \
|
||||||
|
--region us-east-1 \
|
||||||
|
--function-name rss-nostr-lambda \
|
||||||
|
--cli-binary-format raw-in-base64-out \
|
||||||
|
--payload '{"dryRun":true,"feedUrl":"https://nitter.1d4.us/culturaltutor/rss","nostrNsecParam":"/rss-nostr-lambda/nsec","lastRunTimeParam":"/rss-nostr-lambda/last-run-time"}' \
|
||||||
response.json
|
response.json
|
||||||
|
|
||||||
recreate:
|
recreate:
|
||||||
|
|||||||
@@ -1,3 +1,45 @@
|
|||||||
# rss-nostr-lambda
|
# rss-nostr-lambda
|
||||||
|
|
||||||
An AWS Lambda function that posts content found in an RSS feed to Nostr.
|
An AWS Lambda function that posts content found in an RSS feed to Nostr.
|
||||||
|
|
||||||
|
## Running Locally
|
||||||
|
|
||||||
|
### Local environment
|
||||||
|
A [nix-shell development environment](https://nixos.wiki/wiki/Development_environment_with_nix-shell) is configured in this repo. You can use it by running `nix-shell` from within the project directory. This is the easiest way to get started working with this application.
|
||||||
|
|
||||||
|
If you are not running [nix](https://nixos.wiki/wiki/Nix_package_manager) you will need to configure your environment manually. You will need the following dependencies:
|
||||||
|
|
||||||
|
- [awscliv2](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) is used for creating and updating resources in AWS.
|
||||||
|
- [LocalStack](https://docs.localstack.cloud/getting-started/) is a service that mocks AWS services locally on your machine.
|
||||||
|
- [Docker](https://docs.docker.com/engine/install/) is used by LocalStack under the hood. You'll need the Docker daemon up and running to use LocalStack.
|
||||||
|
- [awscli-local](https://github.com/localstack/awscli-local) is a thin wrapper around the awscli which provides the `awslocal` command and allows you to call awscli commands without needing to provide the `--endpoint=http://localhost:xxxx` for LocalStack on each call.
|
||||||
|
|
||||||
|
### Makefile
|
||||||
|
A [Makefile](https://www.gnu.org/software/make/manual/make.html) has been set up to bundle some of the commands used to set up and use this Lambda.
|
||||||
|
|
||||||
|
## Running in AWS
|
||||||
|
|
||||||
|
This function runs in AWS Lambda and uses SSM to store state like the `last-run-time`. The function will read and write parameters in Parameter Store under the paths provided in the event spec below; be sure to [grant the proper permissions](https://docs.aws.amazon.com/systems-manager/latest/userguide/ps-integration-lambda-extensions.html) or this function will fail.
|
||||||
|
|
||||||
|
The function requires the `AWS_REGION` environment variable to be set. This should already be set for you by AWS Lambda.
|
||||||
|
|
||||||
|
### Event Specification
|
||||||
|
|
||||||
|
This Lambda function expects the following event to be passed in:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"feedUrl": String - The url of the RSS feed,
|
||||||
|
"nostrNsecParam": String - The path of the SSM parameter holding the nsec,
|
||||||
|
"lastRunTimeParam": String - The path of the SSM parameter holding the last run time
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Things to be awre of
|
||||||
|
|
||||||
|
The following are not ideal and may be changed in the future:
|
||||||
|
|
||||||
|
- This function uses a checkpointing algorithm based on the last run time. If the last run time is set to too long of a timeframe this function will timeout and misbehave. It's recommended to set the last run time to something recent -- like the last day or two.
|
||||||
|
- This function does not generalize a way to provide the path to the needed data in the RSS feed.
|
||||||
|
- This function hard-codes in the https://nostr.build URL. This is tightly coupled to using that service and provides no alternatives.
|
||||||
|
- Further, if the function fails to upload the image to https://nostr.build it will simply remove the image entirely. There's room to improve this.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { extract } from '@extractus/feed-extractor'
|
|||||||
import NDK, { NDKEvent, NDKPrivateKeySigner } from '@nostr-dev-kit/ndk'
|
import NDK, { NDKEvent, NDKPrivateKeySigner } from '@nostr-dev-kit/ndk'
|
||||||
import bech32 from 'bech32-buffer'
|
import bech32 from 'bech32-buffer'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
import FormData from 'form-data'
|
||||||
|
|
||||||
const toHexString = nsec => {
|
const toHexString = nsec => {
|
||||||
let buffer = bech32.decode(nsec).data
|
let buffer = bech32.decode(nsec).data
|
||||||
@@ -13,12 +14,79 @@ const toHexString = nsec => {
|
|||||||
return s + hex;
|
return s + hex;
|
||||||
}, '');
|
}, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const imgUrls = html => {
|
||||||
|
const re = /<img[^>]+src="?([^"\s]+)"?[^>]*\/>/g
|
||||||
|
const urls = []
|
||||||
|
let m
|
||||||
|
|
||||||
|
while (m = re.exec(html)) {
|
||||||
|
urls.push(m[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return urls
|
||||||
|
}
|
||||||
|
|
||||||
|
const putImgPlaceholders = html => {
|
||||||
|
const re = /<img[^>]+src="?([^"\s]+)"?[^>]*\/>/g
|
||||||
|
const placeholders = []
|
||||||
|
let replaced = html
|
||||||
|
const matches = html.matchAll(re)
|
||||||
|
let img = 0
|
||||||
|
|
||||||
|
for(let match of matches) {
|
||||||
|
replaced = replaced.replace(match[0], `%%${img}%%`)
|
||||||
|
placeholders.push(`%%${img}%%`)
|
||||||
|
img++
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
replaced,
|
||||||
|
placeholders
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const stripHtml = html => {
|
||||||
|
return html.replaceAll(/<[^>]*>/g, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
const replaceImgsWithNostrBuildUrls = async (storeUrl, html, npub) => {
|
||||||
|
const urls = imgUrls(html)
|
||||||
|
let { replaced, placeholders } = putImgPlaceholders(html)
|
||||||
|
|
||||||
|
let count = 0
|
||||||
|
for (let placeholder of placeholders) {
|
||||||
|
const nbUrl = await uploadImgStore(storeUrl, urls[count], npub)
|
||||||
|
if (nbUrl) {
|
||||||
|
replaced = replaced.replace(placeholder, nbUrl)
|
||||||
|
} else {
|
||||||
|
replaced = replaced.replace(placeholder, '')
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
return replaced
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploadImgStore = async (hostUrl, imgUrl, npub) => {
|
||||||
|
const response = await fetch(hostUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||||
|
body: new URLSearchParams({
|
||||||
|
"url": imgUrl,
|
||||||
|
"npub": npub
|
||||||
|
}) })
|
||||||
|
const json = await response.json()
|
||||||
|
|
||||||
|
if (json.status !== "success") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return json.data[0].url
|
||||||
|
}
|
||||||
|
|
||||||
export const handler = async (event) => {
|
export const handler = async (event) => {
|
||||||
const region = process.env.AWS_REGION || "us-east-1"
|
const region = process.env.AWS_REGION || "us-east-1"
|
||||||
const feed = event.feedUrl
|
const feed = event.feedUrl
|
||||||
const privkey = toHexString(event.nostrNsec)
|
const nostrNsecParam = event.nostrNsecParam
|
||||||
const lastRunTimeParam = event.lastRunTimeParam
|
const lastRunTimeParam = event.lastRunTimeParam
|
||||||
const dryrun = event.dryRun
|
const dryrun = event.dryRun
|
||||||
|
|
||||||
@@ -33,93 +101,120 @@ export const handler = async (event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ssmClient = new SSMClient({ region })
|
const ssmClient = new SSMClient({ region })
|
||||||
const params = {
|
const ssmGetLastRunCommand = new GetParameterCommand({
|
||||||
Name: lastRunTimeParam
|
Name: lastRunTimeParam
|
||||||
}
|
});
|
||||||
const ssmGetCommand = new GetParameterCommand(params);
|
|
||||||
|
|
||||||
let since = new Date()
|
let since = new Date()
|
||||||
ssmClient.send(ssmGetCommand)
|
await ssmClient.send(ssmGetLastRunCommand)
|
||||||
.then(data => {
|
.then(data => {
|
||||||
console.log("Using since date:", data.Parameter.Value)
|
|
||||||
since = data.Parameter.Value
|
since = data.Parameter.Value
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error(err)
|
console.dir(err)
|
||||||
|
response.errors.push(err)
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
|
||||||
|
const ssmGetNsecCommand = new GetParameterCommand({
|
||||||
|
Name: nostrNsecParam,
|
||||||
|
WithDecryption: true
|
||||||
|
})
|
||||||
|
|
||||||
|
let privkey = ''
|
||||||
|
await ssmClient.send(ssmGetNsecCommand)
|
||||||
|
.then(data => {
|
||||||
|
privkey = toHexString(data.Parameter.Value)
|
||||||
|
}).catch(err => {
|
||||||
|
console.dir(err)
|
||||||
response.errors.push(err)
|
response.errors.push(err)
|
||||||
return response
|
return response
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
if (feed === "") {
|
if (feed === "") {
|
||||||
console.error("feedUrl was not set.")
|
console.dir("feedUrl was not set.")
|
||||||
return {
|
return {
|
||||||
statusCode: 400,
|
statusCode: 400,
|
||||||
body: "feedUrl must be provided in payload."
|
body: "feedUrl must be provided in payload."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ndk = new NDK({
|
const ndk = new NDK({
|
||||||
signer: new NDKPrivateKeySigner(privkey),
|
|
||||||
explicitRelayUrls: [
|
explicitRelayUrls: [
|
||||||
"wss://nostr.mom",
|
"wss://nostr.mom",
|
||||||
"wss://nostr.snort.social",
|
"wss://nostr.snort.social",
|
||||||
"wss://nostr.lol"
|
"wss://nostr.lol",
|
||||||
|
"wss://nostr.oxtr.dev",
|
||||||
|
"wss://relay.nostr.bg",
|
||||||
|
"wss://nostr-pub.wellorder.net",
|
||||||
|
"wss://relay.damus.io",
|
||||||
|
"wss://nostr.milou.lol",
|
||||||
|
"wss://nostr.bitcoiner.social"
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
const user = await ndk.signer.user()
|
|
||||||
|
|
||||||
for (let url of user.relayUrls) {
|
|
||||||
ndk.pool.relays.push(url)
|
|
||||||
}
|
|
||||||
|
|
||||||
await ndk.connect(6000).catch(err => {
|
await ndk.connect(6000).catch(err => {
|
||||||
console.error(err)
|
console.dir(err)
|
||||||
response.errors.push ("failed to connect to relay", err)
|
response.errors.push("failed to connect to relay", err)
|
||||||
})
|
})
|
||||||
|
|
||||||
let rss = await extract(feed)
|
const signer = new NDKPrivateKeySigner(privkey)
|
||||||
|
ndk.signer = signer
|
||||||
|
|
||||||
|
let rss = await extract(feed, { descriptionMaxLen: 0, normalization: false })
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error(err.error);
|
console.dir(err);
|
||||||
return response
|
return response
|
||||||
})
|
})
|
||||||
|
|
||||||
let filtered = rss.entries.filter(item => moment(item.published).isAfter(since))
|
let filtered = rss.item.filter(item => moment(item.pubDate).isAfter(since))
|
||||||
response.totalItems = filtered.length
|
response.totalItems = filtered.length
|
||||||
|
|
||||||
for (let item of filtered) {
|
for (let item of filtered) {
|
||||||
|
const user = await ndk.signer.user()
|
||||||
|
let content = ''
|
||||||
|
let replaced = await replaceImgsWithNostrBuildUrls(
|
||||||
|
'https://nostr.build/api/v2/upload/url',
|
||||||
|
item.description,
|
||||||
|
user.npub)
|
||||||
|
if (replaced) {
|
||||||
|
content = stripHtml(replaced)
|
||||||
|
}
|
||||||
|
|
||||||
let ndkEvent = new NDKEvent(ndk, {
|
let ndkEvent = new NDKEvent(ndk, {
|
||||||
kind: 1,
|
kind: 1,
|
||||||
pubkey: user.hexpubkey,
|
pubkey: user.hexpubkey,
|
||||||
content: `${item.description}\n${item.link}`,
|
content,
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
})
|
})
|
||||||
|
|
||||||
if (dryrun) {
|
if (dryrun) {
|
||||||
|
console.dir(content)
|
||||||
response.successes++
|
response.successes++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
await ndkEvent.publish()
|
try {
|
||||||
.then(() => {
|
await ndkEvent.sign(ndk.signer)
|
||||||
|
const published = await ndkEvent.publish()
|
||||||
|
if (published) {
|
||||||
response.successes++
|
response.successes++
|
||||||
}).catch(err => {
|
const ssmPutCommand = new PutParameterCommand({
|
||||||
console.error(err)
|
Name: lastRunTimeParam,
|
||||||
response.errors.push(err)
|
Value: new Date().toISOString(),
|
||||||
})
|
Type: "String",
|
||||||
}
|
Overwrite: true
|
||||||
|
})
|
||||||
params.Name = lastRunTimeParam
|
await ssmClient.send(ssmPutCommand)
|
||||||
params.Value = new Date().toISOString()
|
continue
|
||||||
params.Type = "String"
|
}
|
||||||
params.Overwrite = true
|
console.dir(`failed to publish note`)
|
||||||
|
response.errors.push(`failed to publish note`)
|
||||||
const ssmPutCommand = new PutParameterCommand(params)
|
} catch(e) {
|
||||||
ssmClient.send(ssmPutCommand)
|
console.dir(e)
|
||||||
.catch(err => {
|
response.errors.push(e)
|
||||||
console.error(err)
|
|
||||||
response.errors.push(err)
|
|
||||||
return response
|
return response
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|||||||
+116
-71
@@ -624,6 +624,28 @@
|
|||||||
"url": "https://paulmillr.com/funding/"
|
"url": "https://paulmillr.com/funding/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@noble/curves": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": "1.3.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@noble/curves/node_modules/@noble/hashes": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@noble/hashes": {
|
"node_modules/@noble/hashes": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||||
@@ -647,40 +669,23 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@nostr-dev-kit/ndk": {
|
"node_modules/@nostr-dev-kit/ndk": {
|
||||||
"version": "2.0.5",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@nostr-dev-kit/ndk/-/ndk-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nostr-dev-kit/ndk/-/ndk-2.1.1.tgz",
|
||||||
"integrity": "sha512-EvVr43y+4N9lMSZIIe5V8jFWYlKTVkMyyJfbgRaDGCGiBZAm9iy0wcO2Yi+W57awOAlvr3mjT5fAwG9RDb6HSA==",
|
"integrity": "sha512-sMD4re3QVpSVMzoyvJAFiftPxJBXkhjRInrK5DcjhSkkPTlJhI+oiVXCpcvCJ3PHT5PilhDgKkg3LyOvv135UQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@noble/hashes": "^1.3.1",
|
"@noble/hashes": "^1.3.1",
|
||||||
"@noble/secp256k1": "^2.0.0",
|
"@noble/secp256k1": "^2.0.0",
|
||||||
"@scure/base": "^1.1.1",
|
"@scure/base": "^1.1.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"eventemitter3": "^5.0.1",
|
|
||||||
"light-bolt11-decoder": "^3.0.0",
|
"light-bolt11-decoder": "^3.0.0",
|
||||||
"node-fetch": "^3.3.1",
|
"node-fetch": "^3.3.1",
|
||||||
"nostr-tools": "^1.15.0",
|
"nostr-tools": "^1.15.0",
|
||||||
|
"tseep": "^1.1.1",
|
||||||
"typescript-lru-cache": "^2.0.0",
|
"typescript-lru-cache": "^2.0.0",
|
||||||
"utf8-buffer": "^1.0.0",
|
"utf8-buffer": "^1.0.0",
|
||||||
"websocket-polyfill": "^0.0.3"
|
"websocket-polyfill": "^0.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nostr-dev-kit/ndk/node_modules/node-fetch": {
|
|
||||||
"version": "3.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
|
|
||||||
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
|
||||||
"dependencies": {
|
|
||||||
"data-uri-to-buffer": "^4.0.0",
|
|
||||||
"fetch-blob": "^3.1.4",
|
|
||||||
"formdata-polyfill": "^4.0.10"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/node-fetch"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@scure/base": {
|
"node_modules/@scure/base": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.3.tgz",
|
||||||
@@ -702,28 +707,6 @@
|
|||||||
"url": "https://paulmillr.com/funding/"
|
"url": "https://paulmillr.com/funding/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@scure/bip32/node_modules/@noble/curves": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==",
|
|
||||||
"dependencies": {
|
|
||||||
"@noble/hashes": "1.3.1"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://paulmillr.com/funding/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@scure/bip32/node_modules/@noble/hashes": {
|
|
||||||
"version": "1.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
|
|
||||||
"integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 16"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://paulmillr.com/funding/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@scure/bip39": {
|
"node_modules/@scure/bip39": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz",
|
||||||
@@ -1250,6 +1233,11 @@
|
|||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||||
|
},
|
||||||
"node_modules/bech32-buffer": {
|
"node_modules/bech32-buffer": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/bech32-buffer/-/bech32-buffer-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/bech32-buffer/-/bech32-buffer-0.2.1.tgz",
|
||||||
@@ -1283,6 +1271,17 @@
|
|||||||
"node": ">=6.14.2"
|
"node": ">=6.14.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cross-fetch": {
|
"node_modules/cross-fetch": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
|
||||||
@@ -1291,6 +1290,25 @@
|
|||||||
"node-fetch": "^2.6.12"
|
"node-fetch": "^2.6.12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cross-fetch/node_modules/node-fetch": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"encoding": "^0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"encoding": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/d": {
|
"node_modules/d": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
|
||||||
@@ -1324,6 +1342,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/es5-ext": {
|
"node_modules/es5-ext": {
|
||||||
"version": "0.10.62",
|
"version": "0.10.62",
|
||||||
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
|
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
|
||||||
@@ -1357,11 +1383,6 @@
|
|||||||
"ext": "^1.1.2"
|
"ext": "^1.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eventemitter3": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
|
|
||||||
},
|
|
||||||
"node_modules/ext": {
|
"node_modules/ext": {
|
||||||
"version": "1.7.0",
|
"version": "1.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
|
||||||
@@ -1418,6 +1439,19 @@
|
|||||||
"node": "^12.20 || >= 14.13"
|
"node": "^12.20 || >= 14.13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/formdata-polyfill": {
|
"node_modules/formdata-polyfill": {
|
||||||
"version": "4.0.10",
|
"version": "4.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||||
@@ -1468,6 +1502,25 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/moment": {
|
"node_modules/moment": {
|
||||||
"version": "2.29.4",
|
"version": "2.29.4",
|
||||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||||
@@ -1505,22 +1558,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/node-fetch": {
|
"node_modules/node-fetch": {
|
||||||
"version": "2.7.0",
|
"version": "3.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
|
||||||
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"whatwg-url": "^5.0.0"
|
"data-uri-to-buffer": "^4.0.0",
|
||||||
|
"fetch-blob": "^3.1.4",
|
||||||
|
"formdata-polyfill": "^4.0.10"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "4.x || >=6.0.0"
|
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"funding": {
|
||||||
"encoding": "^0.1.0"
|
"type": "opencollective",
|
||||||
},
|
"url": "https://opencollective.com/node-fetch"
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"encoding": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/node-gyp-build": {
|
"node_modules/node-gyp-build": {
|
||||||
@@ -1554,17 +1605,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/nostr-tools/node_modules/@noble/curves": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==",
|
|
||||||
"dependencies": {
|
|
||||||
"@noble/hashes": "1.3.1"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://paulmillr.com/funding/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/nostr-tools/node_modules/@noble/hashes": {
|
"node_modules/nostr-tools/node_modules/@noble/hashes": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
|
||||||
@@ -1597,6 +1637,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/tseep": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tseep/-/tseep-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-deBIcIlXUMlr3xaN0UEochqjU/zXGaZGPqHPd1rxo4w6DklBdRM6WQQtsk7bekIF+qY6QTeen3nE6OA7BxL9rg=="
|
||||||
|
},
|
||||||
"node_modules/tslib": {
|
"node_modules/tslib": {
|
||||||
"version": "2.6.2",
|
"version": "2.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||||
|
|||||||
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user