init nostr
This commit is contained in:
parent
4f94b5fc1f
commit
bec30f2ab0
7 changed files with 1082 additions and 9 deletions
|
|
@ -1 +1 @@
|
||||||
nodeLinker: "node-modules"
|
nodeLinker: node-modules
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@
|
||||||
"serverless": "4"
|
"serverless": "4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@nostr-dev-kit/ndk": "^2.8.2",
|
||||||
"pino": "^9.2.0",
|
"pino": "^9.2.0",
|
||||||
"pino-lambda": "^4.4.0",
|
"pino-lambda": "^4.4.0",
|
||||||
"pocketbase": "^0.21.3"
|
"pocketbase": "^0.21.3"
|
||||||
}
|
},
|
||||||
|
"packageManager": "yarn@4.3.1"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,10 @@ provider:
|
||||||
BLUE_SKY_USERNAME: ${env:BLUE_SKY_USERNAME}
|
BLUE_SKY_USERNAME: ${env:BLUE_SKY_USERNAME}
|
||||||
|
|
||||||
functions:
|
functions:
|
||||||
|
nostr:
|
||||||
|
handler: src/nostr.run
|
||||||
|
events:
|
||||||
|
- schedule: rate(1 hour)
|
||||||
pixelfed:
|
pixelfed:
|
||||||
handler: src/pixelfed.run
|
handler: src/pixelfed.run
|
||||||
events:
|
events:
|
||||||
|
|
|
||||||
127
src/nostr.ts
Normal file
127
src/nostr.ts
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
import pino from "pino";
|
||||||
|
import { lambdaRequestTracker, pinoLambdaDestination } from "pino-lambda";
|
||||||
|
import { MicroBlogBackend } from "./pocketbase";
|
||||||
|
import NDK, { type NDKFilter } from "@nostr-dev-kit/ndk";
|
||||||
|
|
||||||
|
// custom destination formatter
|
||||||
|
const destination = pinoLambdaDestination();
|
||||||
|
const logger = pino({}, destination);
|
||||||
|
const withRequest = lambdaRequestTracker();
|
||||||
|
|
||||||
|
const pb = new MicroBlogBackend(logger);
|
||||||
|
|
||||||
|
const npub = "npub1tcmsctewqs3yy0a9q2xh6r0tlm97dxdqcuehuyumyh4jkyfdg5xsmyvw2y";
|
||||||
|
const ndk = new NDK({
|
||||||
|
explicitRelayUrls: [
|
||||||
|
"wss://nos.lol",
|
||||||
|
// "wss://nostr.wine",
|
||||||
|
// "wss://nostr.einundzwanzig.space",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// const feedEvents = await npubA.feed();
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
exports.run = async (event: any, context: any) => {
|
||||||
|
withRequest(event, context);
|
||||||
|
logger.info("connecting to nostr relays");
|
||||||
|
await ndk.connect();
|
||||||
|
logger.info("connected to nostr relays");
|
||||||
|
// const lastSavedPostId = await pb.getLatestPostRemoteIDBySource("mastodon");
|
||||||
|
// console.log({ lastSavedPostId });
|
||||||
|
// const posts = await getPostUntilId({ lastSavedId: lastSavedPostId });
|
||||||
|
// const user = ndk.getUser({
|
||||||
|
// npub,
|
||||||
|
// });
|
||||||
|
// await user.fetchProfile();
|
||||||
|
const filter: NDKFilter = { kinds: [1], authors: [npub] };
|
||||||
|
const evt = await ndk.fetchEvent(filter, { closeOnEose: true });
|
||||||
|
logger.info({ evt }, "Got event");
|
||||||
|
|
||||||
|
// logger.info({ profile: user.profile }, "Got user profile");
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
@ -101,9 +101,7 @@ exports.run = async (event: any, context: any) => {
|
||||||
for (const post of posts) {
|
for (const post of posts) {
|
||||||
logger.info({ post }, "saving post");
|
logger.info({ post }, "saving post");
|
||||||
const savedNewPost = await savePost(post);
|
const savedNewPost = await savePost(post);
|
||||||
if (savedNewPost) {
|
|
||||||
await saveTags(post, savedNewPost.id);
|
await saveTags(post, savedNewPost.id);
|
||||||
await saveImages(post, savedNewPost.id);
|
await saveImages(post, savedNewPost.id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ export class MicroBlogBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getLatestPostRemoteIDBySource(postSource: MicroBlogPostSource) {
|
public async getLatestPostRemoteIDBySource(postSource: MicroBlogPostSource) {
|
||||||
|
await this.checkLogin();
|
||||||
const post = await this.getLatestPostBySource(postSource);
|
const post = await this.getLatestPostBySource(postSource);
|
||||||
return post?.remoteId;
|
return post?.remoteId;
|
||||||
}
|
}
|
||||||
|
|
@ -137,6 +138,7 @@ export class MicroBlogBackend {
|
||||||
public async savePost(
|
public async savePost(
|
||||||
post: Omit<MicroBlogPost, "id" | "expand">
|
post: Omit<MicroBlogPost, "id" | "expand">
|
||||||
): Promise<MicroBlogPost> {
|
): Promise<MicroBlogPost> {
|
||||||
|
await this.checkLogin();
|
||||||
const existingPost = await this.checkForPost(post.remoteId);
|
const existingPost = await this.checkForPost(post.remoteId);
|
||||||
if (!existingPost) {
|
if (!existingPost) {
|
||||||
return await this.pb
|
return await this.pb
|
||||||
|
|
@ -148,6 +150,7 @@ export class MicroBlogBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setTag(rawTag: string, postId: string) {
|
public async setTag(rawTag: string, postId: string) {
|
||||||
|
await this.checkLogin();
|
||||||
let tag = await this.getTag(rawTag);
|
let tag = await this.getTag(rawTag);
|
||||||
if (!tag) {
|
if (!tag) {
|
||||||
tag = await this.pb
|
tag = await this.pb
|
||||||
|
|
@ -166,6 +169,7 @@ export class MicroBlogBackend {
|
||||||
imageToSave: Omit<MicroBlogPostImage, "id" | "image" | "collectionId">,
|
imageToSave: Omit<MicroBlogPostImage, "id" | "image" | "collectionId">,
|
||||||
postId: string
|
postId: string
|
||||||
) {
|
) {
|
||||||
|
await this.checkLogin();
|
||||||
let image = await this.getImageByRemoteURL(imageToSave.remoteURL);
|
let image = await this.getImageByRemoteURL(imageToSave.remoteURL);
|
||||||
if (!image) {
|
if (!image) {
|
||||||
const imageResponse = await fetch(imageToSave.remoteURL);
|
const imageResponse = await fetch(imageToSave.remoteURL);
|
||||||
|
|
@ -183,13 +187,15 @@ export class MicroBlogBackend {
|
||||||
image = await this.pb
|
image = await this.pb
|
||||||
.collection<MicroBlogPostTag>("micro_blog_images")
|
.collection<MicroBlogPostTag>("micro_blog_images")
|
||||||
.create(data);
|
.create(data);
|
||||||
|
this.logger.info({ image }, "Created image");
|
||||||
}
|
}
|
||||||
if (!image) {
|
if (!image) {
|
||||||
throw new Error("Failed to create image");
|
throw new Error("Failed to create image");
|
||||||
}
|
}
|
||||||
await this.pb.collection("micro_blog_posts").update(postId, {
|
const res = await this.pb.collection("micro_blog_posts").update(postId, {
|
||||||
"images+": image.id,
|
"images+": image.id,
|
||||||
});
|
});
|
||||||
|
this.logger.info({ res }, "Updated post with image");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getPosts(page: number, limit = 20) {
|
public async getPosts(page: number, limit = 20) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue