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"); });