index.ts (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
type ErrorResponse = {
error: string;
code: string;
};
type PostClicksSelfResponse = {
success: true;
dndSuppressed: boolean;
};
type WrappedResponse<T> =
{ data: T; error: null } | { data: null; error: ErrorResponse };
const API_KEY = process.env.TOKEN!;
const API_URL = "https://puppyclicker-api.boundfire.com/api/v2/clicks/self";
async function sendClick(
message?: string,
): Promise<WrappedResponse<PostClicksSelfResponse>> {
try {
const res = await fetch(API_URL, {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
...(message ? { "Content-Type": "application/json" } : {}),
},
...(message ? { body: JSON.stringify({ message }) } : {}),
});
const body = await res.json().catch(() => null);
if (res.ok && body) {
return { data: body as PostClicksSelfResponse, error: null };
}
return {
data: null,
error: (body as ErrorResponse) ?? {
error: res.statusText || "Request failed",
code: `HTTP_${res.status}`,
},
};
} catch (err) {
const message = err instanceof Error ? err.message : "Internal error";
return {
data: null,
error: { error: message, code: "FETCH_ERROR" },
};
}
}
function parseMessage(body: unknown): string | undefined {
if (
typeof body === "object" &&
body !== null &&
"message" in body &&
typeof body.message === "string"
) {
return body.message;
}
return undefined;
}
const server = Bun.serve({
routes: {
"/": () => new Response(Bun.file("./index.html")),
"/assets/main.css": () => new Response(Bun.file("./assets/main.css")),
"/api/click": {
POST: async (req) => {
const body = await req.json().catch(() => null);
const message = parseMessage(body);
const result = await sendClick(message);
const status = result.error ? 502 : 200;
return Response.json(result, { status });
},
},
},
});
console.log(`Server running at ${server.url}`);
|