Schedule posts to Bluesky with Cloudflare workers. skyscheduler.work
cf tool bsky-tool cloudflare bluesky schedule bsky service social-media cloudflare-workers

minor updates

just some easy to change settings that are safe

+58 -5
+1
assets/main.js
··· 1 1 function pushToast(msg, isSuccess) { 2 2 Toastify({ 3 3 text: msg, 4 + duration: !isSuccess ? 10000 : Toastify.defaults.duration, 4 5 style: { 5 6 background: isSuccess ? 'green' : 'red' 6 7 }
+16
assets/stylesheet.css
··· 134 134 135 135 .credits a { 136 136 margin-left: 5px; 137 + } 138 + 139 + .warning-box { 140 + position: relative; 141 + padding: 3px; 142 + background: linear-gradient(to right, orange, orangered); 143 + margin-bottom: 5px; 144 + } 145 + 146 + .warning { 147 + color: white; 148 + } 149 + 150 + #accountResponse .btn-error *, #accountDelete .btn-error * { 151 + margin-left: 5px; 152 + color: white; 137 153 }
+9 -2
src/endpoints/account.tsx
··· 53 53 const body = await c.req.parseBody(); 54 54 const validation = AccountUpdateSchema.safeParse(body); 55 55 if (!validation.success) { 56 - console.log(validation.error); 57 - return c.html(<b class="btn-error">Failed Validation</b>); 56 + const errorMsgs = JSON.parse(validation.error.message); 57 + return c.html(<div class="btn-error"> 58 + <b>Failed Validation</b>: 59 + <ul> 60 + {errorMsgs.map((el: { message: string; }) => { 61 + return <li>{el.message}</li>; 62 + })} 63 + </ul> 64 + </div>); 58 65 } 59 66 60 67 const auth = c.get("auth");
+1 -1
src/layout/footer.tsx
··· 3 3 return ( 4 4 <> 5 5 <a class="secondary" target="_blank" href="https://github.com/SocksTheWolf/SkyScheduler">SkyScheduler</a> &copy; {new Date().getFullYear()} 6 - <span class="credits"><a href="https://socksthewolf.com">SocksTheWolf</a> - 6 + <span class="credits"><a rel="author" href="https://socksthewolf.com">SocksTheWolf</a> - 7 7 <a class="secondary" target="_blank" href="https://ko-fi.com/socksthewolf">Tip/Donate</a></span> 8 8 </> 9 9 );
+1
src/layout/postList.tsx
··· 17 17 } 18 18 19 19 export function ScheduledPost(content: Post) { 20 + // Throwaway gibberish generator to make htmx link up properly across a lot of posts 20 21 const postID = randomstring.generate(7); 21 22 22 23 return html`
+29 -1
src/types.d.ts
··· 37 37 // Basically a copy of the schema 38 38 export type Post = { 39 39 postid: string; 40 + // SkyScheduler User Id 40 41 user: string; 41 42 text: string; 42 43 embeds?: EmbedData[]; ··· 52 53 uri: string; 53 54 cid: string; 54 55 userId: string; 55 - } 56 + }; 57 + 58 + export type Violation = { 59 + userId: string; 60 + tosViolation: boolean; 61 + userPassInvalid: boolean; 62 + accountSuspended: boolean; 63 + accountGone: boolean; 64 + createdAt: string; 65 + }; 56 66 57 67 export type PostResponseObject = { 58 68 uri: string; ··· 61 71 62 72 export interface LooseObj { 63 73 [key: string]: any; 74 + }; 75 + 76 + export enum PlatformLoginResponse { 77 + None = 0, 78 + Ok, 79 + InvalidCreds, 80 + Suspended, 81 + Deactivated, 82 + TakenDown, 83 + InvalidAccount, 84 + PlatformOutage, 85 + UnhandledError 86 + }; 87 + 88 + export enum PWAutoCompleteSettings { 89 + Off, 90 + NewPass, 91 + CurrentPass 64 92 };
+1 -1
src/validation/accountUpdateSchema.ts
··· 15 15 .or(z.literal("")), 16 16 bskyAppPassword: z.string().trim() 17 17 .max(BSKY_MAX_APP_PASSWORD_LENGTH, "app password too long") 18 - .regex(appPasswordRegex) 18 + .regex(appPasswordRegex, "not a valid bsky app password") 19 19 .optional() 20 20 .or(z.literal("")), 21 21 bskyUserPDS: z.url("PDS should be in the format of an URL").trim()