add mastodon fetcher

This commit is contained in:
Travis Shears 2024-06-25 11:46:54 +02:00
parent f283893064
commit ac1cad9fb6
3 changed files with 116 additions and 1 deletions

View file

@ -10,7 +10,7 @@ The Micro Blog Repo is made up of a PocketBase db and these lambda functions. To
- [X] Post support - [X] Post support
- [X] Post with image support - [X] Post with image support
- [X] [Pixelfed via gram.social](https://gram.social/i/web/profile/703621281309160235) - [X] [Pixelfed via gram.social](https://gram.social/i/web/profile/703621281309160235)
- [ ] [Mastodon via dice.camp](https://dice.camp/@travisshears) - [X] [Mastodon via dice.camp](https://dice.camp/@travisshears)
- [ ] [Nostr profile1qqs9....](https://snort.social/nprofile1qqs9udcv9uhqggjz87js9rtaph4lajlxnxsvwvm7zwdjt6etzyk52rgpypmhxue69uhkummnw3ezuetfde6kuer6wasku7nfvuh8xurpvdjj7qgkwaehxw309ajkgetw9ehx7um5wghxcctwvshszrnhwden5te0dehhxtnvdakz7z94haj) - [ ] [Nostr profile1qqs9....](https://snort.social/nprofile1qqs9udcv9uhqggjz87js9rtaph4lajlxnxsvwvm7zwdjt6etzyk52rgpypmhxue69uhkummnw3ezuetfde6kuer6wasku7nfvuh8xurpvdjj7qgkwaehxw309ajkgetw9ehx7um5wghxcctwvshszrnhwden5te0dehhxtnvdakz7z94haj)
@ -32,7 +32,10 @@ $ yarn exec serverless invoke --function bluesky
```shell ```shell
$ nvm use
$ yarn exec serverless invoke local --function bluesky $ yarn exec serverless invoke local --function bluesky
``` ```
_note: insure you are on the correct version of nodejs, 20_
There is also the new `serverless dev` command. I still need to check that out. There is also the new `serverless dev` command. I still need to check that out.

View file

@ -24,3 +24,7 @@ functions:
handler: src/bluesky.run handler: src/bluesky.run
events: events:
- schedule: rate(1 hour) - schedule: rate(1 hour)
mastodon:
handler: src/mastodon.run
events:
- schedule: rate(1 hour)

108
src/mastodon.ts Normal file
View file

@ -0,0 +1,108 @@
import pino from "pino";
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 baseURL = "https://dice.camp";
const accountId = "112364858295724350";
const username = "travisshears";
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);
const lastSavedPostId = await pb.getLatestPostRemoteIDBySource("mastodon");
console.log({ lastSavedPostId });
const posts = await getPostUntilId({ lastSavedId: lastSavedPostId });
console.log({ posts });
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);
}
};