···11import { sql } from "drizzle-orm";
22import { index, integer, sqliteTable, text, unique } from "drizzle-orm/sqlite-core";
33-import { EmbedData, PostLabel, RepostInfo } from '../types';
33+import { EmbedData, PostLabel } from "../types/posts";
44+import { RepostInfo } from "../classes/repost";
45import { users } from "./auth.schema";
5667export const posts = sqliteTable('posts', {
+1-1
src/endpoints/account.tsx
···66import { authMiddleware } from "../middleware/auth";
77import { corsHelperMiddleware } from "../middleware/corsHelper";
88import { verifyTurnstile } from "../middleware/turnstile";
99-import { Bindings, LooseObj } from "../types";
99+import { Bindings } from "../types/settings";
1010import { lookupBskyHandle, lookupBskyPDS } from "../utils/bskyApi";
1111import { checkIfCanDMUser } from "../utils/bskyMsg";
1212import { getAllMediaOfUser } from "../utils/db/file";
+1-1
src/endpoints/admin.tsx
···55import { authAdminOnlyMiddleware } from "../middleware/adminOnly";
66import { corsHelperMiddleware } from "../middleware/corsHelper";
77import { APP_NAME, SITE_URL } from "../siteinfo";
88-import { Bindings } from "../types";
88+import { Bindings } from "../types/settings";
99import { getAllAbandonedMedia } from "../utils/db/file";
1010import { runMaintenanceUpdates } from "../utils/db/maintain";
1111import { makeInviteKey } from "../utils/inviteKeys";
+1-1
src/endpoints/openapi.tsx
···33import { Context, Hono } from "hono";
44import { describeRoute, resolver, validator } from "hono-openapi";
55import { ContextVariables } from "../auth";
66-import { Bindings } from "../types";
66+import { Bindings } from "../types/settings";
77import { AccountDeleteSchema, AccountForgotSchema } from "../validation/accountForgotDeleteSchema";
88import {
99 AccountResetSchema, PasswordResetCheckCallbackParam,
+4-5
src/endpoints/post.tsx
···33import isEmpty from "just-is-empty";
44import { validate as isValid } from 'uuid';
55import { ContextVariables } from "../auth";
66+import { Post } from "../classes/post";
67import { PostEdit } from "../layout/editPost";
78import { PostHTML } from "../layout/post";
89import { ScheduledPostList } from "../layout/postList";
910import { authMiddleware } from "../middleware/auth";
1011import { corsHelperMiddleware } from "../middleware/corsHelper";
1111-import {
1212- Bindings, CreateObjectResponse, CreatePostQueryResponse,
1313- DeleteResponse,
1414- EmbedDataType, LooseObj, Post
1515-} from "../types";
1212+import { EmbedDataType } from "../types/posts";
1313+import { CreateObjectResponse, CreatePostQueryResponse, DeleteResponse } from "../types/responses";
1414+import { Bindings } from "../types/settings";
1615import {
1716 createPost, createRepost,
1817 deletePost, getPostById,
+1-1
src/endpoints/preview.tsx
···55import { BSKY_IMG_MIME_TYPES } from "../limits";
66import { authMiddleware } from "../middleware/auth";
77import { corsHelperMiddleware } from "../middleware/corsHelper";
88-import { Bindings } from "../types";
88+import { Bindings } from "../types/settings";
99import { FileContentSchema } from "../validation/mediaSchema";
10101111export const preview = new Hono<{ Bindings: Bindings, Variables: ContextVariables }>();
+3-1
src/index.tsx
···11import { drizzle } from "drizzle-orm/d1";
22import { Env, Hono } from "hono";
33import { ContextVariables, createAuth } from "./auth";
44+import { ScheduledContext } from "./classes/context";
45import { account } from "./endpoints/account";
56import { admin } from "./endpoints/admin";
67import { post } from "./endpoints/post";
···1718import Signup from "./pages/signup";
1819import TermsOfService from "./pages/tos";
1920import { SITE_URL } from "./siteinfo";
2020-import { Bindings, QueueTaskData, ScheduledContext, TaskType } from "./types";
2121+import { QueueTaskData, TaskType } from "./types/queue";
2222+import { Bindings } from "./types/settings";
2123import { AgentMap } from "./utils/bskyAgents";
2224import { makeConstScript } from "./utils/constScriptGen";
2325import {
+2-1
src/layout/editPost.tsx
···11+import { Post } from "../classes/post";
12import { MAX_LENGTH } from "../limits";
22-import { EmbedDataType, Post } from "../types";
33+import { EmbedDataType } from "../types/posts";
34import { PostContent } from "./post";
4556type EditedPostProps = {
+1-1
src/layout/helpers/includesTags.tsx
···11-import { PreloadRules } from "../../types";
11+import { PreloadRules } from "../../types/site";
2233type DepTagsType = {
44 scripts?: PreloadRules[]
+1-1
src/layout/main.tsx
···11import { html } from 'hono/html';
22import { Child } from 'hono/jsx';
33import { APP_NAME } from "../siteinfo";
44-import { PreloadRules } from '../types';
44+import { PreloadRules } from "../types/site";
55import { mainScriptStr } from '../utils/appScripts';
66import { PreloadDependencyTags } from './helpers/includesTags';
77import MetaTags from './helpers/metaTags';
+1-1
src/layout/makePost.tsx
···1010 R2_FILE_SIZE_LIMIT_IN_MB
1111} from "../limits";
1212import { APP_NAME } from "../siteinfo";
1313-import { PreloadRules } from "../types";
1313+import { PreloadRules } from "../types/site";
1414import { ConstScriptPreload } from "../utils/constScriptGen";
1515import { IncludeDependencyTags } from "./helpers/includesTags";
1616import { ContentLabelOptions } from "./options/contentLabelOptions";
+1-1
src/layout/passwordFields.tsx
···11import { html } from "hono/html";
22import { BSKY_MAX_APP_PASSWORD_LENGTH, MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits";
33-import { PWAutoCompleteSettings } from "../types";
33+import { PWAutoCompleteSettings } from "../types/site";
4455type PasswordFieldSettings = {
66 required?: boolean
+1-1
src/layout/post.tsx
···11import { html } from "hono/html";
22+import { Post } from "../classes/post";
23import { MAX_POSTED_LENGTH } from "../limits";
33-import { Post } from "../types";
44import { PostDataFooter, PostDataHeader } from "./posts/wrappers";
5566type PostContentProps = {
+1-1
src/layout/postList.tsx
···11import { Context } from "hono";
22import isEmpty from "just-is-empty";
33-import { Post } from "../types";
33+import { Post } from "../classes/post";
44import { getPostsForUser } from "../utils/dbQuery";
55import { PostHTML } from "./post";
66
+1-1
src/layout/posts/repostData.tsx
···11import { raw } from "hono/html";
22import isEmpty from "just-is-empty";
33-import { RepostInfo } from "../../types";
33+import { RepostInfo } from "../../classes/repost";
4455type RepostIconProps = {
66 isRepost?: boolean;
+1-1
src/layout/posts/wrappers.tsx
···11import { raw } from "hono/html";
22import isEmpty from "just-is-empty";
33-import { Post } from "../../types";
33+import { Post } from "../../classes/post";
44import { AddPostToThreadButton, DeletePostButton, EditPostButton } from "./buttons";
55import { RepostCountElement, RepostIcon } from "./repostData";
66
+1-1
src/layout/settings.tsx
···11import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits";
22import { APP_NAME } from "../siteinfo";
33-import { PWAutoCompleteSettings } from "../types";
33+import { PWAutoCompleteSettings } from "../types/site";
44import { settingsScriptStr } from "../utils/appScripts";
55import { BSkyAppPasswordField, DashboardPasswordField } from "./passwordFields";
66import { UsernameField } from "./usernameField";
+3-3
src/pages/dashboard.tsx
···22import { AltTextDialog } from "../layout/altTextModal";
33import FooterCopyright from "../layout/helpers/footer";
44import { IncludeDependencyTags } from "../layout/helpers/includesTags";
55+import { LogoImage } from "../layout/helpers/logo";
56import { BaseLayout } from "../layout/main";
67import { PostCreation, PreloadPostCreation } from "../layout/makePost";
78import { MakeRetweet } from "../layout/makeRetweet";
···910import { Settings, SettingsButton } from "../layout/settings";
1011import { ViolationNoticeBar } from "../layout/violationsBar";
1112import { APP_NAME, SHOW_SUPPORT_PROGRESS_BAR } from "../siteinfo";
1212-import { PreloadRules } from "../types";
1313+import { PreloadRules } from "../types/site";
1314import {
1415 dashboardScriptStr,
1516 settingsScriptStr
1617} from "../utils/appScripts";
1717-import { LogoImage } from "../layout/helpers/logo";
18181919-export default function Dashboard(props:any) {
1919+export default function Dashboard(props: any) {
2020 const ctx: Context = props.c;
2121 // 3rd party dependencies
2222 const defaultDashboardPreloads: PreloadRules[] = [
+1-1
src/pages/login.tsx
···33import { BaseLayout } from "../layout/main";
44import { DashboardPasswordField } from "../layout/passwordFields";
55import { UsernameField } from "../layout/usernameField";
66-import { PWAutoCompleteSettings } from "../types";
66+import { PWAutoCompleteSettings } from "../types/site";
7788export default function Login() {
99 const links = [{title: "Sign Up", url: "/signup"}, {title: "Forgot Password", url: "/forgot"}];
+1-1
src/pages/signup.tsx
···77import { BSkyAppPasswordField, DashboardPasswordField } from "../layout/passwordFields";
88import { UsernameField } from "../layout/usernameField";
99import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits";
1010-import { PWAutoCompleteSettings } from "../types";
1010+import { PWAutoCompleteSettings } from "../types/site";
1111import { getInviteThread, isUsingInviteKeys } from "../utils/inviteKeys";
12121313export default function Signup(props:any) {
+7
src/types.d.ts
···11+// Easy type declares for typescript type checking
22+// not used otherwise
33+declare type LooseObj = {
44+ [key: string]: any;
55+};
66+declare type BatchQuery = [BatchItem<'sqlite'>, ...BatchItem<'sqlite'>[]];
77+declare type AllContext = Context | ScheduledContext;
···11+import { EmbedDataType } from "./posts";
22+33+export type BskyEmbedWrapper = {
44+ type: EmbedDataType;
55+ data?: any;
66+};
77+88+export type BskyRecordWrapper = {
99+ cid?: string;
1010+ uri?: string;
1111+};
+11
src/types/data.ts
···11+// Used for the pruning and database operations
22+export type GetAllPostedBatch = {
33+ id: string;
44+ uri: string|null;
55+};
66+77+export type R2BucketObject = {
88+ name: string;
99+ user: string|null;
1010+ date: Date
1111+};
···11+// Used for jsx rendering
22+export type PreloadRules = {
33+ type: string;
44+ href: string;
55+};
66+77+export enum PWAutoCompleteSettings {
88+ Off,
99+ NewPass,
1010+ CurrentPass
1111+};
+5-4
src/utils/bskyAgents.ts
···44//
55// Also just handles general login.
66import AtpAgent from "@atproto/api";
77-import {
88- AccountStatus, AgentConfigSettings,
99- AllContext, LooseObj, Post, Repost, TaskType
1010-} from "../types";
77+import { Post } from "../classes/post";
88+import { Repost } from "../classes/repost";
99+import { AccountStatus } from "../types/accounts";
1010+import { TaskType } from "../types/queue";
1111+import { AgentConfigSettings } from "../types/settings";
1112import { getBskyUserPassForId } from "./db/userinfo";
1213import { createViolationForUser } from "./db/violations";
1314
+10-8
src/utils/bskyApi.ts
···44import has from 'just-has';
55import isEmpty from "just-is-empty";
66import truncate from "just-truncate";
77+import { Post } from "../classes/post";
88+import { Repost } from "../classes/repost";
79import { BSKY_IMG_SIZE_LIMIT, MAX_ALT_TEXT, MAX_EMBEDS_PER_POST } from '../limits';
88-import {
99- AccountStatus,
1010- AllContext,
1111- BskyEmbedWrapper, BskyRecordWrapper, EmbedData, EmbedDataType,
1212- LooseObj, Post, PostLabel,
1313- PostRecordResponse, PostStatus, Repost
1414-} from '../types';
1010+import { AccountStatus } from "../types/accounts";
1111+import { BskyEmbedWrapper, BskyRecordWrapper } from "../types/bsky";
1212+import { EmbedData, EmbedDataType, PostLabel } from "../types/posts";
1313+import { PostRecordResponse, PostStatus } from "../types/responses";
1514import { atpRecordURI } from '../validation/regexCases';
1615import { makeAgentForUser } from './bskyAgents';
1717-import { bulkUpdatePostedData, getChildPostsOfThread, isPostAlreadyPosted, setPostNowOffForPost } from './db/data';
1616+import {
1717+ bulkUpdatePostedData, getChildPostsOfThread,
1818+ isPostAlreadyPosted, setPostNowOffForPost
1919+} from './db/data';
1820import { getUsernameForUserId } from './db/userinfo';
1921import { createViolationForUser } from './db/violations';
2022import { deleteEmbedsFromR2 } from './r2Query';
+2-1
src/utils/bskyMsg.ts
···11import { AtpAgent, RichText } from '@atproto/api';
22-import { AccountStatus, Bindings } from '../types';
22+import { AccountStatus } from "../types/accounts";
33+import { Bindings } from '../types/settings';
34import { loginToBsky } from './bskyAgents';
4556const chatHeaders = {headers: {
-1
src/utils/bskyPrune.ts
···11import isEmpty from 'just-is-empty';
22import split from 'just-split';
33-import { AllContext } from '../types';
43import { getPostRecords } from './bskyApi';
54import { getAllPostedPosts, getAllPostedPostsOfUser } from './db/data';
65
+1-1
src/utils/constScriptGen.ts
···1212 MAX_THUMBNAIL_SIZE,
1313 R2_FILE_SIZE_LIMIT
1414} from "../limits";
1515-import { PreloadRules } from "../types";
1515+import { PreloadRules } from "../types/site";
1616import { postRecordURI } from "../validation/regexCases";
17171818const CONST_SCRIPT_VERSION: number = 8;
+9-13
src/utils/db/data.ts
···33import { DrizzleD1Database } from "drizzle-orm/d1";
44import isEmpty from "just-is-empty";
55import { validate as uuidValid } from 'uuid';
66+import { Post } from "../../classes/post";
77+import { Repost } from "../../classes/repost";
68import { posts, repostCounts, reposts } from "../../db/app.schema";
79import { violations } from "../../db/enforcement.schema";
810import { MAX_HOLD_DAYS_BEFORE_PURGE, MAX_POSTED_LENGTH } from "../../limits";
99-import {
1010- AllContext,
1111- BatchQuery,
1212- GetAllPostedBatch,
1313- Post,
1414- PostRecordResponse,
1515- Repost
1616-} from "../../types";
1717-import { createPostObject, createRepostObject, floorCurrentTime } from "../helpers";
1111+import { GetAllPostedBatch } from "../../types/data";
1212+import { PostRecordResponse } from "../../types/responses";
1313+import { floorCurrentTime } from "../helpers";
18141915export const getAllPostsForCurrentTime = async (c: AllContext, removeThreads: boolean = false): Promise<Post[]> => {
2016 // Get all scheduled posts for current time
···4238 ));
4339 const results = await db.with(postsToMake).select().from(postsToMake)
4440 .where(notInArray(postsToMake.userId, violationUsers)).orderBy(asc(postsToMake.createdAt)).all();
4545- return results.map((item) => createPostObject(item));
4141+ return results.map((item) => new Post(item));
4642};
47434844export const getAllRepostsForGivenTime = async (c: AllContext, givenDate: Date): Promise<Repost[]> => {
···6056 .where(and(inArray(posts.uuid, query), notInArray(posts.userId, violationsQuery)))
6157 .all();
62586363- return results.map((item) => createRepostObject(item));
5959+ return results.map((item) => new Repost(item));
6460};
65616662export const getAllRepostsForCurrentTime = async (c: AllContext): Promise<Repost[]> => {
···234230 .where(and(isNotNull(posts.parentPost), eq(posts.rootPost, rootId)))
235231 .orderBy(asc(posts.threadOrder), desc(posts.createdAt)).all();
236232 if (query.length > 0) {
237237- return query.map((child) => createPostObject(child));
233233+ return query.map((child) => new Post(child));
238234 }
239235 return null;
240236};
···304300 .limit(1).all();
305301306302 if (!isEmpty(result))
307307- return createPostObject(result[0]);
303303+ return new Post(result[0]);
308304 return null;
309305};
+1-1
src/utils/db/file.ts
···22import { DrizzleD1Database } from "drizzle-orm/d1";
33import flatten from "just-flatten-it";
44import { mediaFiles, posts } from "../../db/app.schema";
55-import { AllContext, EmbedDataType, LooseObj } from "../../types";
55+import { EmbedDataType } from "../../types/posts";
66import { daysAgo } from "../helpers";
7788export const addFileListing = async (c: AllContext, file: string, user: string|null, createDate: Date|null=null) => {
+1-1
src/utils/db/maintain.ts
···55import { mediaFiles, posts, repostCounts, reposts } from "../../db/app.schema";
66import { users } from "../../db/auth.schema";
77import { MAX_POSTED_LENGTH } from "../../limits";
88-import { AllContext, BatchQuery, R2BucketObject } from "../../types";
88+import { R2BucketObject } from "../../types/data";
99import { getAllFilesList } from "../r2Query";
1010import { addFileListing, getAllMediaOfUser } from "./file";
1111
···33import flatten from "just-flatten-it";
44import isEmpty from "just-is-empty";
55import { bannedUsers, violations } from "../../db/enforcement.schema";
66-import { AccountStatus, AllContext, LooseObj, Violation } from "../../types";
66+import { AccountStatus, Violation } from "../../types/accounts";
77import { lookupBskyHandle } from "../bskyApi";
88import { getUsernameForUserId } from "./userinfo";
99
+12-17
src/utils/dbQuery.ts
···55import has from "just-has";
66import isEmpty from "just-is-empty";
77import { v4 as uuidv4, validate as uuidValid } from 'uuid';
88+import { Post } from "../classes/post";
99+import { RepostInfo } from "../classes/repost";
810import { mediaFiles, posts, repostCounts, reposts } from "../db/app.schema";
911import { accounts, users } from "../db/auth.schema";
1012import { MAX_POSTS_PER_THREAD, MAX_REPOST_POSTS, MAX_REPOST_RULES_PER_POST } from "../limits";
1113import { APP_NAME } from "../siteinfo";
1212-import {
1313- AccountStatus,
1414- AllContext,
1515- BatchQuery,
1616- CreateObjectResponse, CreatePostQueryResponse,
1717- DeleteResponse,
1818- EmbedDataType,
1919- Post, PostLabel,
2020- RepostInfo
2121-} from "../types";
1414+import { AccountStatus } from "../types/accounts";
1515+import { EmbedDataType, PostLabel } from "../types/posts";
1616+import { CreateObjectResponse, CreatePostQueryResponse, DeleteResponse } from "../types/responses";
2217import { PostSchema } from "../validation/postSchema";
2318import { RepostSchema } from "../validation/repostSchema";
2419import { getChildPostsOfThread, getPostByCID, getPostThreadCount, updatePostForGivenUser } from "./db/data";
2520import { getViolationsForUser, removeViolation, removeViolations, userHasViolations } from "./db/violations";
2626-import { createPostObject, createRepostInfo, floorGivenTime } from "./helpers";
2121+import { floorGivenTime } from "./helpers";
2722import { deleteEmbedsFromR2 } from "./r2Query";
28232924export const getPostsForUser = async (c: AllContext): Promise<Post[]|null> => {
···4237 if (isEmpty(results))
4338 return null;
44394545- return results.map((itm) => createPostObject(itm));
4040+ return results.map((itm) => new Post(itm));
4641 }
4742 } catch(err) {
4843 console.error(`Failed to get posts for user, session could not be fetched ${err}`);
···255250 // Create repost metadata
256251 const scheduleGUID = (!isThreadedPost) ? uuidv4() : undefined;
257252 const repostInfo = (!isThreadedPost) ?
258258- createRepostInfo(scheduleGUID!, scheduleDate, false, repostData) : undefined;
253253+ new RepostInfo(scheduleGUID!, scheduleDate, false, repostData) : undefined;
259254260255 // Create the posts
261256 const postUUID = uuidv4();
···358353 if (violationData.tosViolation) {
359354 return {ok: false, msg: `This account is unable to use ${APP_NAME} services at this time`};
360355 } else if (violationData.userPassInvalid) {
361361- return {ok: false, msg: "The BSky account credentials is invalid, please update these in the settings"};
356356+ return {ok: false, msg: "The BSky account credentials is invalid, please update th/ese in the settings"};
362357 }
363358 }
364359 let postUUID;
365360 let dbOperations: BatchItem<"sqlite">[] = [];
366361 const scheduleGUID = uuidv4();
367367- const repostInfo: RepostInfo = createRepostInfo(scheduleGUID, scheduleDate, true, repostData);
362362+ const repostInfo: RepostInfo = new RepostInfo(scheduleGUID, scheduleDate, true, repostData);
368363369364 // Check to see if the post already exists
370365 // (check also against the userId here as well to avoid cross account data collisions)
···470465 .limit(1).all();
471466472467 if (!isEmpty(result))
473473- return createPostObject(result[0]);
468468+ return new Post(result[0]);
474469 return null;
475470};
476471···495490 .limit(1).all();
496491497492 if (!isEmpty(result))
498498- return createPostObject(result[0]);
493493+ return new Post(result[0]);
499494 return null;
500495};
-94
src/utils/helpers.ts
···11import { startOfHour, subDays } from "date-fns";
22import { Context } from "hono";
33-import has from "just-has";
44-import isEmpty from "just-is-empty";
55-import { BskyAPILoginCreds, Post, Repost, RepostInfo } from "../types";
66-77-export function createPostObject(data: any) {
88- const postData: Post = (new Object() as Post);
99- postData.user = data.userId;
1010- postData.postid = data.uuid;
1111- postData.embeds = data.embedContent;
1212- postData.label = data.contentLabel;
1313- postData.text = data.content;
1414- postData.postNow = data.postNow;
1515- postData.threadOrder = data.threadOrder;
1616-1717- if (has(data, "repostCount"))
1818- postData.repostCount = data.repostCount;
1919-2020- if (data.scheduledDate)
2121- postData.scheduledDate = data.scheduledDate;
2222-2323- if (data.repostInfo)
2424- postData.repostInfo = data.repostInfo;
2525-2626- if (data.rootPost)
2727- postData.rootPost = data.rootPost;
2828-2929- if (data.parentPost) {
3030- postData.parentPost = data.parentPost;
3131- postData.isChildPost = true;
3232- } else {
3333- postData.isChildPost = false;
3434- }
3535-3636- if (data.threadOrder == 0)
3737- postData.isThreadRoot = true;
3838- else
3939- postData.isThreadRoot = false;
4040-4141- // ATProto data
4242- if (data.uri)
4343- postData.uri = data.uri;
4444- if (data.cid)
4545- postData.cid = data.cid;
4646-4747- if (has(data, "isRepost"))
4848- postData.isRepost = data.isRepost;
4949-5050- if (has(data, "posted"))
5151- postData.posted = data.posted;
5252-5353- // if a cid flag appears for the object and it's a thread root, then the post (if marked not posted) is posted.
5454- if (postData.posted == false && !isEmpty(data.cid) && postData.isThreadRoot)
5555- postData.posted = true;
5656-5757- return postData;
5858-}
5959-6060-export function createRepostObject(data: any) {
6161- const repostObj: Repost = (new Object() as Repost);
6262- repostObj.postid = data.uuid;
6363- repostObj.cid = data.cid;
6464- repostObj.uri = data.uri;
6565- repostObj.userId = data.userId;
6666- if (data.scheduleGuid)
6767- repostObj.scheduleGuid = data.scheduleGuid;
6868- return repostObj;
6969-}
7070-7171-export function createRepostInfo(id: string, time: Date, isRepost: boolean, repostData: any) {
7272- const repostObj: RepostInfo = (new Object() as RepostInfo);
7373- repostObj.time = time;
7474- repostObj.guid = id;
7575- if (has(repostData, "hours") && has(repostData, "times")) {
7676- repostObj.hours = repostData.hours;
7777- repostObj.count = repostData.times;
7878- } else {
7979- repostObj.count = (isRepost) ? 1 : 0;
8080- repostObj.hours = 0;
8181- }
8282- return repostObj;
8383-}
8484-8585-export function createLoginCredsObj(data: any) {
8686- const loginCreds: BskyAPILoginCreds = (new Object() as BskyAPILoginCreds);
8787- if (isEmpty(data)) {
8888- loginCreds.password = loginCreds.username = loginCreds.pds = "";
8989- } else {
9090- loginCreds.pds = data.pds;
9191- loginCreds.username = data.user;
9292- loginCreds.password = data.pass;
9393- }
9494- loginCreds.valid = !isEmpty(data.user) && !isEmpty(data.pass);
9595- return loginCreds;
9696-}
973984export function floorCurrentTime() {
995 return startOfHour(new Date());
+4-1
src/utils/queuePublisher.ts
···11import isEmpty from 'just-is-empty';
22import random from 'just-random';
33import get from 'just-safe-get';
44-import { AllContext, Bindings, Post, QueueTaskData, Repost, TaskType } from "../types";
44+import { Post } from "../classes/post";
55+import { Repost } from "../classes/repost";
66+import { QueueTaskData, TaskType } from "../types/queue";
77+import { Bindings } from '../types/settings';
5869const queueContentType = 'v8';
710
+2-1
src/utils/r2Query.ts
···1515 R2_FILE_SIZE_LIMIT,
1616 R2_FILE_SIZE_LIMIT_IN_MB
1717} from "../limits";
1818-import { AllContext, EmbedData, EmbedDataType, R2BucketObject } from '../types';
1818+import { R2BucketObject } from '../types/data';
1919+import { EmbedData, EmbedDataType } from "../types/posts";
1920import { addFileListing, deleteFileListings } from './db/file';
20212122type FileMetaData = {
+7-2
src/utils/scheduler.ts
···11import AtpAgent from '@atproto/api';
22import isEmpty from 'just-is-empty';
33-import { AllContext, Post, Repost, TaskType } from '../types';
33+import { Post } from "../classes/post";
44+import { Repost } from "../classes/repost";
55+import { TaskType } from "../types/queue";
46import { AgentMap } from './bskyAgents';
57import { makePost, makeRepost } from './bskyApi';
68import { pruneBskyPosts } from './bskyPrune';
···1012 setPostNowOffForPost
1113} from './db/data';
1214import { getAllAbandonedMedia } from './db/file';
1313-import { enqueuePost, enqueueRepost, isQueueEnabled, isRepostQueueEnabled, shouldPostNowQueue, shouldPostThreadQueue } from './queuePublisher';
1515+import {
1616+ enqueuePost, enqueueRepost, isQueueEnabled, isRepostQueueEnabled,
1717+ shouldPostNowQueue, shouldPostThreadQueue
1818+} from './queuePublisher';
1419import { deleteFromR2 } from './r2Query';
15201621export const handlePostTask = async(runtime: AllContext, postData: Post, agent: AtpAgent|null) => {
+1-1
src/validation/embedSchema.ts
···11import isEmpty from "just-is-empty";
22import * as z from "zod/v4";
33import { BSKY_VIDEO_LENGTH_LIMIT } from "../limits";
44-import { EmbedDataType } from "../types";
44+import { EmbedDataType } from "../types/posts";
55import { FileContentSchema } from "./mediaSchema";
66import { atpRecordURI } from "./regexCases";
77import { AltTextSchema } from "./sharedValidations";
+9-3
src/validation/postSchema.ts
···11import * as z from "zod/v4";
22-import { MAX_LENGTH, MAX_REPOST_INTERVAL_LIMIT, MAX_REPOST_IN_HOURS, MIN_LENGTH } from "../limits";
33-import { EmbedDataType, PostLabel } from "../types";
44-import { ImageEmbedSchema, LinkEmbedSchema, PostRecordSchema, VideoEmbedSchema } from "./embedSchema";
22+import {
33+ MAX_LENGTH, MAX_REPOST_INTERVAL_LIMIT,
44+ MAX_REPOST_IN_HOURS, MIN_LENGTH
55+} from "../limits";
66+import { EmbedDataType, PostLabel } from "../types/posts";
77+import {
88+ ImageEmbedSchema, LinkEmbedSchema,
99+ PostRecordSchema, VideoEmbedSchema
1010+} from "./embedSchema";
511import { FileContentSchema } from "./mediaSchema";
612import { AltTextSchema } from "./sharedValidations";
713