switch to simple ws backed nostr fetcher

This commit is contained in:
Travis Shears 2024-07-05 17:27:41 +02:00
parent c5e5e24802
commit a481626e47
6 changed files with 84 additions and 375 deletions

View file

@ -1,9 +1,7 @@
import pino from "pino";
import WebSocket from "ws";
import { lambdaRequestTracker, pinoLambdaDestination } from "pino-lambda";
import { MicroBlogBackend } from "./pocketbase";
import { RelayClient } from "@nostr-ts/node";
import { NFilters, EventsRequest, CLIENT_MESSAGE_TYPE } from "@nostr-ts/common";
import Client from "pocketbase";
// custom destination formatter
const destination = pinoLambdaDestination();
@ -12,147 +10,90 @@ const withRequest = lambdaRequestTracker();
const pb = new MicroBlogBackend(logger);
// const feedEvents = await npubA.feed();
const fetcherNpub =
"npub1qqqqqqp350slvdds7028l4yre5cuh8v38zseert25mxf7lkr2trsy0j2m8";
const myNpub =
"5e370c2f2e0422423fa5028d7d0debfecbe699a0c7337e139b25eb2b112d450d";
// type MastodonPost = {
// media_attachments: {
// type: string; //'image',
// url: string;
// description: string; // 'Blurry gate',
// }[];
// id: string;
// content: string;
// account: {
// id: string;
// };
// created_at: string;
// tags: { name: string }[];
// };
// const getPostUntilId = async ({
// lastSavedId,
// maxId,
// carryPosts = [],
// }: {
// lastSavedId?: string;
// maxId?: string;
// carryPosts?: MastodonPost[];
// }): Promise<MastodonPost[]> => {
// const params = new URLSearchParams();
// params.append("limit", "10");
// const urlWithParams = new URL(
// `${baseURL}/api/v1/accounts/${accountId}/statuses`
// );
// urlWithParams.search = params.toString();
// const res = await fetch(urlWithParams);
// const posts = (await res.json()) as MastodonPost[];
// const containsId = posts.some((post) => post.id === lastSavedId);
// if (!containsId && posts.length >= 5) {
// return getPostUntilId({
// lastSavedId,
// carryPosts: carryPosts?.concat(posts),
// maxId: posts[posts.length - 1]?.id,
// });
// }
// const allPosts = carryPosts?.concat(posts).reverse();
// if (lastSavedId) {
// const index = allPosts.findIndex((post) => post.id === lastSavedId);
// return allPosts.slice(index + 1);
// }
// return allPosts;
// };
// const savePost = async (post: MastodonPost) => {
// const postData = {
// remoteId: post.id,
// authorId: post.account.id,
// posted: post.created_at,
// source: "mastodon" as const,
// fullPost: post,
// };
// return await pb.savePost(postData);
// };
// const saveTags = async (post: MastodonPost, postId: string) => {
// logger.info({ tags: post.tags }, "saving tags");
// for (const tag of post.tags) {
// await pb.setTag(tag.name, postId);
// }
// };
// const saveImages = async (post: MastodonPost, postId: string) => {
// logger.info({ images: post.media_attachments }, "saving images");
// for (const image of post.media_attachments) {
// await pb.saveAndSetImage(
// { remoteURL: image.url, alt: image.description },
// postId
// );
// }
// };
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);
logger.info("connecting to nostr relays");
const npub =
"npub1tcmsctewqs3yy0a9q2xh6r0tlm97dxdqcuehuyumyh4jkyfdg5xsmyvw2y";
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("wss://travis-shears-nostr-relay-v2.fly.dev/");
// Other Relay URLs
// "wss://nos.lol",
// "wss://nostr.wine",
// "wss://nostr.einundzwanzig.space",
let client = new RelayClient([
{
url: "wss://travis-shears-nostr-relay-v2.fly.dev/",
read: true,
write: false,
},
// {
// url: "wss://nos.lol",
// read: true,
// write: false,
// },
// {
// url: "wss://nostr.einundzwanzig.space",
// read: true,
// write: false,
// },
]);
const info = await client.getRelayInformation();
logger.info({ info }, "relay info");
const filters = new NFilters();
filters.addAuthor(npub);
const req: EventsRequest = {
filters,
type: CLIENT_MESSAGE_TYPE.REQ,
options: {
timeoutIn: 10000,
},
};
client.subscribe(req);
client.listen((payload) => {
logger.info(
{ info: payload.meta.info, url: payload.meta.url },
"received event"
);
// logRelayMessage(payload.data);
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);
}
});
client.disconnect();
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],
});
// const lastSavedPostId = await pb.getLatestPostRemoteIDBySource("mastodon");
// console.log({ lastSavedPostId });
// const posts = await getPostUntilId({ lastSavedId: lastSavedPostId });
// const user = ndk.getUser({
// npub,
// });
// await user.fetchProfile();
// for (const post of posts) {
// logger.info({ post }, "saving post");
// const savedNewPost = await savePost(post);
// await saveTags(post, savedNewPost.id);
// await saveImages(post, savedNewPost.id);
// }
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
);
}
}
}
};

View file

@ -18,7 +18,8 @@ export type MicroBlogPostSource =
| "blue_sky"
| "mastodon"
| "pleroma"
| "pixelfed";
| "pixelfed"
| "nostr";
export type MicroBlogPost = {
source: MicroBlogPostSource;
@ -26,6 +27,7 @@ export type MicroBlogPost = {
remoteId: string;
authorId: string;
id: string;
posted: string;
expand: {
images?: MicroBlogPostImage[];
tags?: {