97 lines
2.7 KiB
TypeScript
97 lines
2.7 KiB
TypeScript
import pino from "pino";
|
|
import WebSocket from "ws";
|
|
import { lambdaRequestTracker, pinoLambdaDestination } from "pino-lambda";
|
|
import { MicroBlogBackend } from "./pocketbase";
|
|
|
|
// custom destination formatter
|
|
const destination = pinoLambdaDestination();
|
|
const logger = pino({}, destination);
|
|
const withRequest = lambdaRequestTracker();
|
|
|
|
const pb = new MicroBlogBackend(logger);
|
|
|
|
const fetcherNpub = process.env.NOSTR_FETCHER_NPUB!;
|
|
const myNpub = process.env.NOSTR_ID!;
|
|
|
|
type NostrTag = ["t" | "r" | "imeta", string];
|
|
type NostrEvent = [
|
|
"EVENT" | "EOSE",
|
|
string,
|
|
{
|
|
id: string;
|
|
pubkey: string;
|
|
created_at: number;
|
|
kind: number; // 1
|
|
tags: NostrTag[];
|
|
content: string;
|
|
sig: string;
|
|
},
|
|
];
|
|
|
|
exports.run = async (event: any, context: any) => {
|
|
withRequest(event, context);
|
|
const events: NostrEvent[] = [];
|
|
|
|
// figure out when the last post of wasved
|
|
const lastSavedPost = await pb.getLatestPostBySource("nostr");
|
|
let since: number | undefined;
|
|
if (lastSavedPost) {
|
|
since = new Date(lastSavedPost.posted).getTime() / 1000;
|
|
}
|
|
// listen for new events for 30 seconds
|
|
logger.info("trying to connecting to nostr relay");
|
|
const ws = new WebSocket(process.env.NOSTR_RELAY!);
|
|
// Other Relay URLs
|
|
// "wss://nos.lol",
|
|
// "wss://nostr.wine",
|
|
// "wss://nostr.einundzwanzig.space",
|
|
ws.on("error", logger.error);
|
|
ws.on("message", function message(data: Buffer) {
|
|
const decodedData = JSON.parse(
|
|
Buffer.from(data).toString("utf8")
|
|
) as NostrEvent;
|
|
logger.info({ decodedData }, "recived a message from nostr relay");
|
|
if (decodedData[0] === "EVENT") {
|
|
events.push(decodedData);
|
|
}
|
|
});
|
|
ws.on("open", function open() {
|
|
logger.info("connection established");
|
|
ws.send(
|
|
JSON.stringify([
|
|
"REQ",
|
|
fetcherNpub,
|
|
{ kinds: [1], authors: [myNpub], ...(since ? { since } : {}) },
|
|
])
|
|
);
|
|
});
|
|
await new Promise((resolve) => setTimeout(resolve, 30000));
|
|
logger.info("closing connection to nostr relay");
|
|
ws.close();
|
|
logger.info("saving nostr posts");
|
|
for (const event of events) {
|
|
const post = await pb.savePost({
|
|
remoteId: event[2].id,
|
|
fullPost: event[2],
|
|
posted: new Date(event[2].created_at * 1000).toISOString(),
|
|
source: "nostr",
|
|
authorId: event[1],
|
|
});
|
|
|
|
for (const tag of event[2].tags) {
|
|
if (tag[0] === "t") {
|
|
await pb.setTag(tag[1], post.id);
|
|
} else if (tag[0] === "imeta") {
|
|
const value = tag[1];
|
|
// remove "url " from the start of the string
|
|
const url = value.slice(4);
|
|
await pb.saveAndSetImage(
|
|
{
|
|
remoteURL: url,
|
|
},
|
|
post.id
|
|
);
|
|
}
|
|
}
|
|
}
|
|
};
|