pleroma-like client for Bluesky pl.hexmani.ac
bluesky pleroma social-media

Create basic write-only text posts through post form

hexmani.ac 18468c0b 7eb5c43c

verified
Changed files
+66 -3
src
components
+7
bun.lock
··· 4 "": { 5 "name": "vite-template-solid", 6 "dependencies": { 7 "@atcute/bluesky": "^3.2.8", 8 "@atcute/client": "^4.0.5", 9 "@atcute/lexicons": "^1.2.2", 10 "@atcute/oauth-browser-client": "^1.0.27", 11 "@solidjs/router": "^0.15.3", 12 "solid-js": "^1.9.5", 13 }, ··· 26 27 "@atcute/bluesky": ["@atcute/bluesky@3.2.8", "", { "dependencies": { "@atcute/atproto": "^3.1.8", "@atcute/lexicons": "^1.2.2" } }, "sha512-wxEnSOvX7nLH4sVzX9YFCkaNEWIDrTv3pTs6/x4NgJ3AJ3XJio0OYPM8tR7wAgsklY6BHvlAgt3yoCDK0cl1CA=="], 28 29 "@atcute/client": ["@atcute/client@4.0.5", "", { "dependencies": { "@atcute/identity": "^1.1.1", "@atcute/lexicons": "^1.2.2" } }, "sha512-R8Qen8goGmEkynYGg2m6XFlVmz0GTDvQ+9w+4QqOob+XMk8/WDpF4aImev7WKEde/rV2gjcqW7zM8E6W9NShDA=="], 30 31 "@atcute/identity": ["@atcute/identity@1.1.1", "", { "dependencies": { "@atcute/lexicons": "^1.2.2", "@badrap/valita": "^0.4.6" } }, "sha512-zax42n693VEhnC+5tndvO2KLDTMkHOz8UExwmklvJv7R9VujfEwiSWhcv6Jgwb3ellaG8wjiQ1lMOIjLLvwh0Q=="], ··· 35 "@atcute/multibase": ["@atcute/multibase@1.1.6", "", { "dependencies": { "@atcute/uint8array": "^1.0.5" } }, "sha512-HBxuCgYLKPPxETV0Rot4VP9e24vKl8JdzGCZOVsDaOXJgbRZoRIF67Lp0H/OgnJeH/Xpva8Z5ReoTNJE5dn3kg=="], 36 37 "@atcute/oauth-browser-client": ["@atcute/oauth-browser-client@1.0.27", "", { "dependencies": { "@atcute/client": "^4.0.4", "@atcute/identity": "^1.1.1", "@atcute/lexicons": "^1.2.2", "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5", "nanoid": "^5.1.5" } }, "sha512-Ng1tCOTMLgFHHoIHXTtCZR1/ND62an1qxPX2kBoUzkxxd7iCP7IBYYqOiKyJYT5n1R4zS+s29hFS4t9mxXa5kQ=="], 38 39 "@atcute/uint8array": ["@atcute/uint8array@1.0.5", "", {}, "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q=="], 40
··· 4 "": { 5 "name": "vite-template-solid", 6 "dependencies": { 7 + "@atcute/atproto": "^3.1.8", 8 "@atcute/bluesky": "^3.2.8", 9 + "@atcute/bluesky-richtext-builder": "^2.0.4", 10 "@atcute/client": "^4.0.5", 11 "@atcute/lexicons": "^1.2.2", 12 "@atcute/oauth-browser-client": "^1.0.27", 13 + "@atcute/tid": "^1.0.3", 14 "@solidjs/router": "^0.15.3", 15 "solid-js": "^1.9.5", 16 }, ··· 29 30 "@atcute/bluesky": ["@atcute/bluesky@3.2.8", "", { "dependencies": { "@atcute/atproto": "^3.1.8", "@atcute/lexicons": "^1.2.2" } }, "sha512-wxEnSOvX7nLH4sVzX9YFCkaNEWIDrTv3pTs6/x4NgJ3AJ3XJio0OYPM8tR7wAgsklY6BHvlAgt3yoCDK0cl1CA=="], 31 32 + "@atcute/bluesky-richtext-builder": ["@atcute/bluesky-richtext-builder@2.0.4", "", { "dependencies": { "@atcute/bluesky": "^3.2.5", "@atcute/lexicons": "^1.2.2" } }, "sha512-ydA9VWBPsBE/gbu1vYbmh7AZ8FLfxp+LE4eH5GgOTCOxwhs7Mgy1oHrHY+Er6gu6PfdoUoGso0uI3Wl3ZF/Mxg=="], 33 + 34 "@atcute/client": ["@atcute/client@4.0.5", "", { "dependencies": { "@atcute/identity": "^1.1.1", "@atcute/lexicons": "^1.2.2" } }, "sha512-R8Qen8goGmEkynYGg2m6XFlVmz0GTDvQ+9w+4QqOob+XMk8/WDpF4aImev7WKEde/rV2gjcqW7zM8E6W9NShDA=="], 35 36 "@atcute/identity": ["@atcute/identity@1.1.1", "", { "dependencies": { "@atcute/lexicons": "^1.2.2", "@badrap/valita": "^0.4.6" } }, "sha512-zax42n693VEhnC+5tndvO2KLDTMkHOz8UExwmklvJv7R9VujfEwiSWhcv6Jgwb3ellaG8wjiQ1lMOIjLLvwh0Q=="], ··· 40 "@atcute/multibase": ["@atcute/multibase@1.1.6", "", { "dependencies": { "@atcute/uint8array": "^1.0.5" } }, "sha512-HBxuCgYLKPPxETV0Rot4VP9e24vKl8JdzGCZOVsDaOXJgbRZoRIF67Lp0H/OgnJeH/Xpva8Z5ReoTNJE5dn3kg=="], 41 42 "@atcute/oauth-browser-client": ["@atcute/oauth-browser-client@1.0.27", "", { "dependencies": { "@atcute/client": "^4.0.4", "@atcute/identity": "^1.1.1", "@atcute/lexicons": "^1.2.2", "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5", "nanoid": "^5.1.5" } }, "sha512-Ng1tCOTMLgFHHoIHXTtCZR1/ND62an1qxPX2kBoUzkxxd7iCP7IBYYqOiKyJYT5n1R4zS+s29hFS4t9mxXa5kQ=="], 43 + 44 + "@atcute/tid": ["@atcute/tid@1.0.3", "", {}, "sha512-wfMJx1IMdnu0CZgWl0uR4JO2s6PGT1YPhpytD4ZHzEYKKQVuqV6Eb/7vieaVo1eYNMp2FrY67FZObeR7utRl2w=="], 45 46 "@atcute/uint8array": ["@atcute/uint8array@1.0.5", "", {}, "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q=="], 47
+3
package.json
··· 19 "vite-plugin-solid": "^2.11.8" 20 }, 21 "dependencies": { 22 "@atcute/bluesky": "^3.2.8", 23 "@atcute/client": "^4.0.5", 24 "@atcute/lexicons": "^1.2.2", 25 "@atcute/oauth-browser-client": "^1.0.27", 26 "@solidjs/router": "^0.15.3", 27 "solid-js": "^1.9.5" 28 }
··· 19 "vite-plugin-solid": "^2.11.8" 20 }, 21 "dependencies": { 22 + "@atcute/atproto": "^3.1.8", 23 "@atcute/bluesky": "^3.2.8", 24 + "@atcute/bluesky-richtext-builder": "^2.0.4", 25 "@atcute/client": "^4.0.5", 26 "@atcute/lexicons": "^1.2.2", 27 "@atcute/oauth-browser-client": "^1.0.27", 28 + "@atcute/tid": "^1.0.3", 29 "@solidjs/router": "^0.15.3", 30 "solid-js": "^1.9.5" 31 }
+55 -2
src/components/postForm.tsx
··· 1 - import { Component } from "solid-js"; 2 3 const PostForm: Component = () => { 4 return ( 5 <> 6 <form ··· 14 rows="1" 15 cols="1" 16 placeholder="The car's on fire, and there's no driver at the wheel..." 17 ></textarea> 18 - <button type="submit">Post</button> 19 </form> 20 </> 21 ); 22 };
··· 1 + import { Component, createSignal } from "solid-js"; 2 + import { agent } from "./login"; 3 + import { Client } from "@atcute/client"; 4 + import * as TID from "@atcute/tid"; 5 + import RichtextBuilder from "@atcute/bluesky-richtext-builder"; 6 7 const PostForm: Component = () => { 8 + const [notice, setNotice] = createSignal(""); 9 + const [text, setText] = createSignal(""); 10 + 11 + async function handleSubmit() { 12 + const rpc = new Client({ handler: agent }); 13 + const rawText = text(); 14 + 15 + document.querySelector(".submitInfo")?.removeAttribute("hidden"); 16 + 17 + try { 18 + const res = await rpc.post("com.atproto.repo.createRecord", { 19 + input: { 20 + collection: "app.bsky.feed.post", 21 + record: { 22 + $type: "app.bsky.feed.post", 23 + text: rawText, 24 + langs: ["en"], 25 + createdAt: new Date().toISOString(), 26 + }, 27 + repo: agent.sub, 28 + rkey: TID.now(), 29 + }, 30 + }); 31 + 32 + if (!res.ok) { 33 + throw new Error(`${res.data.error}/${res.data.message}`); 34 + } 35 + 36 + console.log(res); 37 + setNotice("Post successful"); 38 + setTimeout(() => { 39 + setNotice(""); 40 + document.querySelector(".submitInfo")?.setAttribute("hidden", ""); 41 + }, 3000); 42 + } catch (e: unknown) { 43 + if (e instanceof Error) { 44 + setNotice(`Failed to post: ${e.message}`); 45 + } else { 46 + setNotice(`Failed to post`); 47 + } 48 + } 49 + } 50 + 51 return ( 52 <> 53 <form ··· 61 rows="1" 62 cols="1" 63 placeholder="The car's on fire, and there's no driver at the wheel..." 64 + onchange={(e) => setText(e.target.value)} 65 ></textarea> 66 + <button type="submit" onclick={handleSubmit}> 67 + Post 68 + </button> 69 </form> 70 + <p class="submitInfo" hidden> 71 + {notice()} 72 + </p> 73 </> 74 ); 75 };
+1 -1
tsconfig.json
··· 15 16 // Type Checking & Safety 17 "strict": true, 18 - "types": ["vite/client", "@atcute/bluesky"] 19 } 20 }
··· 15 16 // Type Checking & Safety 17 "strict": true, 18 + "types": ["vite/client", "@atcute/bluesky", "@atcute/atproto"] 19 } 20 }