Something went wrong. Try again.
Schedule posts and reposts to Bluesky (and other PDSes) with Cloudflare workers. skyscheduler.work
scheduling social-media cloudflare bsky service cloudflare-workers bsky-tool bluesky
Something went wrong. Try again.
3.6 kB · 129 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130import isEmpty from "just-is-empty";import { CAN_REPOST_SCHEDULED_POSTS } from "../config";import type { PostLabel } from "../enums";import { MAX_REPOST_RULES_PER_POST } from "../limits";import type { BaseContent, EmbedData, MentionCache } from "../types";import { has } from "../utils/helpers";import type { RepostInfo } from "./repost";
// This is a real copy of the schemainterface DBPost { uuid: string; content: string; embedContent?: EmbedData[]; mentionsCache?: MentionCache[]; contentLabel: PostLabel; userId: string; cid?: string | null; uri?: string | null; scheduledDate?: Date | string; postNow: boolean | null; threadOrder: number | null; repostInfo: RepostInfo[] | null; isRepost: boolean | null; posted: boolean | null; rootPost: string | null; parentPost: string | null; repostCount?: number | null;}
export type PostIntakeType = Post | DBPost;
// Basically a copy of the schemaexport class Post implements BaseContent { // guid for post uuid: string; // SkyScheduler User Id userId: string; // post data content: string; embedContent?: EmbedData[]; mentionsCache?: MentionCache[]; contentLabel: PostLabel; // post flags postNow: boolean; posted?: boolean; isRepost?: boolean; // repost metadata repostInfo?: RepostInfo[]; scheduledDate?: string; repostCount?: number; // atproto data cid: string; uri: string; // thread data threadOrder: number; rootPost?: string; parentPost?: string;
constructor(data: PostIntakeType) { this.userId = data.userId; this.uuid = data.uuid; this.embedContent = data.embedContent; this.mentionsCache = data.mentionsCache;
this.contentLabel = data.contentLabel; this.content = data.content; this.postNow = data.postNow ?? false; this.threadOrder = data.threadOrder ?? -1;
if (has(data, "repostCount")) this.repostCount = data.repostCount!;
if (has(data, "scheduledDate")) this.scheduledDate = data.scheduledDate instanceof Date ? data.scheduledDate.toISOString() : data.scheduledDate;
if (has(data, "repostInfo")) this.repostInfo = data.repostInfo!;
if (has(data, "rootPost")) this.rootPost = data.rootPost!;
if (has(data, "parentPost")) this.parentPost = data.parentPost!;
// ATProto data this.uri = data.uri ?? ""; this.cid = data.cid ?? "";
if (has(data, "isRepost")) this.isRepost = data.isRepost!;
if (has(data, "posted")) this.posted = data.posted!;
// if a cid flag appears for the object and it's a thread root, then the post (if marked not posted) is posted. if (this.posted == false && !isEmpty(data.cid) && this.isThreadRoot) this.posted = true; } getURI(): string | null { return this.uri ? "https://bsky.app/profile/" + this.uri.replace("at://", "").replace("app.bsky.feed.", "") : null; } getUser(): string { return this.userId; } canAddMoreRepostRules(): boolean { if (!this.posted && !CAN_REPOST_SCHEDULED_POSTS) return false;
return !this.isChildPost && (this.repostInfo === undefined || this.repostInfo.length < MAX_REPOST_RULES_PER_POST); } hasEmbeds(): boolean { return this.embedContent !== undefined && this.embedContent.length > 0; } get isThread() { return this.threadOrder >= 0; } get isThreadRoot() { return this.threadOrder == 0; } get isChildPost() { return this.parentPost !== undefined; } get isPosted() { return this.posted ?? false; } get isARepost() { return this.isRepost ?? false; }}