Skip to content

Instantly share code, notes, and snippets.

import { AltTextBot } from './find-altless-posts.js';
let mockAtpAgent;
const resolvedHandle = {
did: 'handle-did'
};
const resetAtpAgentMock = () => {
mockAtpAgent = {
const resetAtpAgentMock = () => {
mockAtpAgent = {
getPost: vi.fn(),
resolveHandle: vi.fn().mockResolvedValue({
data: resolvedHandle
}),
login: vi.fn()
};
}
<!DOCTYPE html>
<html lang="en">
<head>
<script type="module" defer>
import { AltTextBot } from './agent/find-altless-posts.ts';
async function start() {
const bot = new AltTextBot();
console.log(await bot.checkSinglePost('https://bsky.app/profile/yonatankra.com/post/3lczalvz7uk2l'));
}
#returnPostWithAltlessImages(post: { uri: string; cid: string; value: Record; }) {
const images = post.value?.embed?.images || [];
const imagesWithoutAlt = images.filter(img => !img.alt);
return { post, imagesWithoutAlt };
}
async checkSinglePost(postUri: string) {
try {
const post = await this.#agent.getPost(await parsePostUri(postUri, this.#agent));
return this.#returnPostWithAltlessImages(post);
it('should return the post with altLess images list', async () => {
const imageWithoutAlt = { alt: '' };
const imageWithAlt = { alt: 'I have Alt text!' };
const post = {
uri: 'postUri',
cid: 'postCid',
value: {
embed: {
images: [imageWithoutAlt, imageWithAlt, imageWithoutAlt],
$type: 'image'
async function parsePostUri(uri: string, agent: AtpAgent): Promise<{ repo: string; collection: string; rkey: string; } | boolean> {
// Extract handle and post ID
const match = uri.match(/profile\/([^/]+)\/post\/([^/]+)/);
if (!match) {
return false;
}
const [, handle, rkey] = match;
// Get the did
const { data: { did: repo }} = await agent.resolveHandle({handle});
it('should get the post using atpAgent', async () => {
const postUri = 'https://bsky.app/profile/yonatankra.com/post/3lczalvz7uk2l';
mockAtpAgent.getPost.mockResolvedValueOnce(postUri);
await bot.checkSinglePost(postUri);
expect(mockAtpAgent.getPost).toHaveBeenCalledWith({
"collection": "app.bsky.feed.post",
"repo": "handle-did",
"rkey": "3lczalvz7uk2l",
describe('AltTextBot', () => {
const postUri = 'postUri';
let bot: AltTextBot;
beforeEach(async () => {
resetAtpAgentMock();
bot = new AltTextBot();
});
it('should initialize a new instance', async () => {
import { AtpAgent } from "@atproto/api";
export class AltTextBot {
#agent = new AtpAgent({ service: 'https://bsky.social' });
async checkSinglePost(postUri: string) {
try {
await this.#agent.getPost(await parsePostUri(postUri, this.#agent));
} catch (e) {
return e;
}
{
"name": "alt-text-game",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "vitest",
"start": "vite"
},
"keywords": [],
"author": "",