yasomi/src/index.ts

77 lines
1.8 KiB
TypeScript

import * as dotenv from "dotenv";
import express from "express";
import _Ajv from "ajv";
const Ajv = _Ajv as unknown as typeof _Ajv.default;
import { CreatePostRequest, CreatePostRequestSchema } from "./types.js";
import bsky from "@atproto/api";
const { BskyAgent, RichText } = bsky;
const ajv = new Ajv({ allErrors: true });
const valid = {
CreatePostRequest: ajv.compile(CreatePostRequestSchema),
};
dotenv.config();
const agent = new BskyAgent({
service: process.env.BLUESKY_ENDPOINT as string,
});
await agent.login({
identifier: process.env.BLUESKY_EMAIL as string,
password: process.env.BLUESKY_PASSWORD as string,
});
const app: express.Application = express();
const port: number = 3000;
app.get("/", async (_req, resp) => {
resp.send("Yasomi online.");
});
app.post("/create", express.json(), async (req, resp, next) => {
if (!valid.CreatePostRequest(req.body)) {
resp.status(400);
resp.json({
errors: valid.CreatePostRequest.errors,
});
return;
}
const cpr = req.body as unknown as CreatePostRequest;
const rt = new RichText({ text: cpr.body });
await rt.detectFacets(agent);
if (rt.graphemeLength > 300) {
resp.status(400);
resp.json({
errors: ["message must be less than 300 characters"],
});
return;
}
const postRecord = {
$type: "app.bsky.feed.post",
text: rt.text,
facets: rt.facets,
createdAt: new Date().toISOString(),
};
try {
const postData = await agent.post(postRecord);
const [_, did, __, postID] = postData.uri.split(
/^at:\/\/(.+)\/(.+)\/(.+)$/
);
const url = `https://staging.bsky.app/profile/${did}/post/${postID}`;
resp.json({ atProto: postData, input: cpr, url });
} catch (error) {
next(error);
}
});
app.listen(port, () => {
console.log("http://pneuma:3000");
});