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

fix error codes

apparently htmx does not like any error codes

+19 -19
+6 -6
src/endpoints/account.tsx
··· 37 37 return <li>{el.message}</li>; 38 38 })} 39 39 </ul> 40 - </div>, 400); 40 + </div>); 41 41 } catch { 42 - return c.html(<div class="validation-error btn-error"><b>Internal Error</b>: Please try again</div>, 400); 42 + return c.html(<div class="validation-error btn-error"><b>Internal Error</b>: Please try again</div>); 43 43 } 44 44 } 45 45 ··· 107 107 c.header("HX-Trigger-After-Swap", "accountViolations"); 108 108 return c.html(<></>, 200); 109 109 } 110 - return c.html(<b class="btn-error">Unknown error occurred</b>, 400); 110 + return c.html(<b class="btn-error">Unknown error occurred</b>); 111 111 }); 112 112 113 113 // endpoint that just returns current username ··· 299 299 300 300 // Make sure we still have data 301 301 if (!usrAccount || !usrAccount.password) { 302 - return c.html(<b class="btn-error">Failed: User Data Missing...</b>, 400); 302 + return c.html(<b class="btn-error">Failed: User Data Missing...</b>); 303 303 } 304 304 305 305 // Do a hash verification on the user's input to see if the passwords match ··· 316 316 c.header("HX-Redirect", "/?deleted"); 317 317 return c.html(<></>); 318 318 } else { 319 - return c.html(<b class="btn-error">Failed: Invalid Password</b>, 400); 319 + return c.html(<b class="btn-error">Failed: Invalid Password</b>); 320 320 } 321 321 } catch (err: any) { 322 322 console.error(`failed to delete user ${userId} had error ${err.message || err.msg || 'no code'}`); 323 - return c.html(<b class="btn-error">Failed: Server Error</b>, 501); 323 + return c.html(<b class="btn-error">Failed: Server Error</b>); 324 324 } 325 325 });
+12 -12
src/endpoints/post.tsx
··· 95 95 post.get("/edit/:id", async (c: Context) => { 96 96 const { id } = c.req.param(); 97 97 if (!isValid(id)) 98 - return c.html(<></>, 400); 98 + return c.html(<></>); 99 99 100 100 const postInfo = await getPostById(c, id); 101 101 if (postInfo !== null) { 102 102 c.header("HX-Trigger-After-Swap", `{"editPost": "${id}"}`); 103 103 return c.html(<PostEdit post={postInfo} />); 104 104 } 105 - return c.html(<></>, 400); 105 + return c.html(<></>); 106 106 }); 107 107 108 108 post.post("/edit/:id", async (c: Context) => { ··· 110 110 const swapErrEvents: string = "refreshPosts, scrollTop, scrollListTop"; 111 111 if (!isValid(id)) { 112 112 c.header("HX-Trigger-After-Swap", swapErrEvents); 113 - return c.html(<b class="btn-error">Post was invalid</b>, 400); 113 + return c.html(<b class="btn-error">Post was invalid</b>); 114 114 } 115 115 116 116 const body = await c.req.json(); 117 117 const validation = EditSchema.safeParse(body); 118 118 if (!validation.success) { 119 - return c.html(<b class="btn-error">New post had invalid data</b>, 400); 119 + return c.html(<b class="btn-error">New post had invalid data</b>); 120 120 } 121 121 122 122 const { content, altEdits } = validation.data; ··· 124 124 // get the original data for the post so that we can just inline edit it via a push 125 125 if (originalPost === null) { 126 126 c.header("HX-Trigger-After-Settle", swapErrEvents); 127 - return c.html(<b class="btn-error">Could not find post to edit</b>, 400); 127 + return c.html(<b class="btn-error">Could not find post to edit</b>); 128 128 } 129 129 130 130 let hasEmbedEdits = false; 131 131 if (originalPost.posted === true) { 132 132 c.header("HX-Trigger-After-Settle", "scrollTop"); 133 - return c.html(<b class="btn-error">This post has already been posted</b>, 400); 133 + return c.html(<b class="btn-error">This post has already been posted</b>); 134 134 } 135 135 136 136 // Handle alt text and stuffs ··· 138 138 // Check to see if this post had editable data 139 139 if (originalPost.embeds === undefined) { 140 140 c.header("HX-Trigger-After-Settle", swapErrEvents); 141 - return c.html(<b class="btn-error">Post did not have media content that was editable</b>, 400); 141 + return c.html(<b class="btn-error">Post did not have media content that was editable</b>); 142 142 } 143 143 144 144 // Create an easy map to match content with quickly ··· 153 153 // if we have anything other than an image, this is an error 154 154 if (embedData.type !== EmbedDataType.Image) { 155 155 c.header("HX-Trigger-After-Settle", swapErrEvents); 156 - return c.html(<b class="btn-error">Invalid operation performed</b>, 400); 156 + return c.html(<b class="btn-error">Invalid operation performed</b>); 157 157 } 158 158 // Check to see if this text was edited 159 159 const newAltText = editsMap.get(embedData.content); ··· 177 177 } 178 178 179 179 c.header("HX-Trigger-After-Settle", swapErrEvents); 180 - return c.html(<b class="btn-error">Failed to process edit</b>, 400); 180 + return c.html(<b class="btn-error">Failed to process edit</b>); 181 181 }); 182 182 183 183 post.get("/edit/:id/cancel", async (c: Context) => { 184 184 const { id } = c.req.param(); 185 185 if (!isValid(id)) 186 - return c.html(<></>, 400); 186 + return c.html(<></>); 187 187 188 188 const postInfo = await getPostByIdWithReposts(c, id); 189 189 // Get the original post to replace with ··· 194 194 195 195 // Refresh sidebar otherwise 196 196 c.header("HX-Trigger-After-Swap", "refreshPosts, timeSidebar, scrollListTop, scrollTop"); 197 - return c.html(<b class="btn-error">Internal error occurred, reloading...</b>, 400); 197 + return c.html(<b class="btn-error">Internal error occurred, reloading...</b>); 198 198 }); 199 199 200 200 // delete a post ··· 215 215 } 216 216 } 217 217 c.header("HX-Trigger-After-Swap", "postFailedDelete"); 218 - return c.html(<></>, 400); 218 + return c.html(<></>); 219 219 });
+1 -1
src/middleware/rateLimit.ts
··· 23 23 await next(); 24 24 } else { 25 25 if (prop.html) { 26 - return c.html(html`<b class="btn-error">You are being rate limited, try again later</b>`, 429); 26 + return c.html(html`<b class="btn-error">You are being rate limited, try again later</b>`); 27 27 } else { 28 28 return c.json({ok: false, msg: "You are currently rate limited, try again in a minute"}, 429); 29 29 }