first

xxwhirlpool f97dd18a

+3
.gitignore
··· 1 + atproto-did 2 + katproto_users.js 3 + node_modules
+13
README.md
··· 1 + # katproto index 2 + 3 + these are the files that make up the [katproto](https://katproto.girlonthemoon.xyz/) PDS index page. 4 + 5 + the dynamic user list is modified (honestly, mostly copy pasted) from a script by [@vielle.dev](https://tangled.org/@vielle.dev/server-config/blob/master/landing/landing.ts). to make it work client-side, run the below commands: 6 + 7 + ```bash 8 + # git clone & cd to the repo folder 9 + 10 + npm install 11 + 12 + npx tsc --p tsconfig.json 13 + ```
+170
index.html
··· 1 + <!DOCTYPE html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8" /> 5 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 + 7 + <meta name="title" content="girl on the moon :: atproto" /> 8 + <meta name="description" content="girl on the moon PDS" /> 9 + <meta name="author" content="girlonthemoon.xyz" /> 10 + <meta property="og:title" content="girl on the moon :: atproto" /> 11 + <meta property="og:description" content="girl on the moon PDS" /> 12 + <meta property="og:type" content="website" /> 13 + <meta property="og:url" content="https://katproto.girlonthemoon.xyz" /> 14 + <meta property="og:image" content="https://stash.4-walls.net/pics/pochacco.jpg" /> 15 + 16 + <link rel="canonical" href="https://katproto.girlonthemoon.xyz" /> 17 + <link rel="icon" type="image/png" sizes="64x64" href="https://stash.4-walls.net/pics/pochacco_favicon.png" /> 18 + 19 + <script src="https://stash.4-walls.net/katproto_demo/katproto_users.js"></script> 20 + 21 + <title>katproto</title> 22 + 23 + <style> 24 + @import url(https://fonts.bunny.net/css?family=victor-mono:100,100i,200,200i,300,300i,400,400i,500,500i,600,600i,700,700i); 25 + 26 + :root { 27 + --font: "Victor Mono", monospace; 28 + --main-color: #ff69b4; 29 + } 30 + 31 + body { 32 + font-family: var(--font) !important; 33 + counter-reset: Span-count; 34 + font-size: .9rem; 35 + } 36 + 37 + pre { 38 + font-family: var(--font) !important; 39 + margin: 0 !important; 40 + padding: 0 !important; 41 + } 42 + 43 + .nosc { 44 + font-family: var(--font) !important; 45 + font-size: .9rem; 46 + } 47 + 48 + div[aria-label] { 49 + margin: 0 !important; 50 + padding: 0 !important; 51 + } 52 + 53 + pre h1 { 54 + color: var(--main-color); 55 + margin: 0 0 0 1rem; 56 + padding: 0 !important; 57 + font-style: italic; 58 + } 59 + 60 + h2 { 61 + color: var(--main-color); 62 + padding: 0 !important; 63 + font-style: italic; 64 + } 65 + 66 + a { 67 + text-underline-offset: 4px; 68 + color: var(--main-color); 69 + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); 70 + } 71 + 72 + dfn, i { 73 + color: var(--main-color); 74 + } 75 + 76 + a:hover { 77 + text-decoration: none; 78 + text-shadow: none; 79 + } 80 + 81 + hr { 82 + border: 1px dashed var(--main-color); 83 + width: 40%; 84 + margin: 1rem 1rem 1rem 0; 85 + padding: 0; 86 + } 87 + 88 + #not-pre { 89 + margin: 0 0 0 1rem; 90 + } 91 + 92 + #list-users { 93 + font-family: var(--font); 94 + font-size: .9rem; 95 + margin: 0 !important; 96 + padding: 0 !important; 97 + } 98 + 99 + .user-count { 100 + counter-increment: Span-count; 101 + display: inline-block; 102 + margin-bottom: .5rem; 103 + } 104 + 105 + .user-count:before { 106 + content: counter(Span-count) ". "; 107 + } 108 + </style> 109 + </head> 110 + 111 + <body> 112 + 113 + <pre> 114 + <div aria-label="ASCII text art of pochacco" role="img"> 115 + ,8, 116 + d8b 117 + 888 118 + __ , 888 119 + d88888b. -.\,- 888 120 + `Y8888b."```"-888 121 + /`" `8\ 122 + | | 123 + | | 124 + | | 125 + __ / O _ O \ 126 + /` '.\ '-' / 127 + \ .'. .; 128 + '. .' `"""""""` \ 129 + `\ /.-.| 130 + `| |` | 131 + | \___/ 132 + ;-.._______..-; 133 + jgs / | \ 134 + \___,---'---,___/ 135 + </div> 136 + <h1 id="katproto">katproto</h1> 137 + this is an at protocol <dfn>personal data server</dfn> (aka, an atproto PDS); more specifically, it's <a href="https://girlonthemoon.xyz/">kat</a>'s PDS! 138 + </pre> 139 + 140 + <div id="not-pre"> 141 + <hr> 142 + 143 + <h2 id="users">users</h2> 144 + 145 + <div id="list-users"> 146 + </div> 147 + 148 + <hr> 149 + 150 + <noscript> 151 + <span class="nosc">sorry, to see the dynamic list of users, you must have javascript enabled!</span> 152 + <hr> 153 + </noscript> 154 + 155 + <script> 156 + async function printUsers() { 157 + document.getElementById("list-users").innerHTML = await getKatprotoUsers(); 158 + } 159 + printUsers(); 160 + </script> 161 + 162 + <h2 id="credits">credits</h2> 163 + 164 + <p> 165 + PDS: <a href="https://github.com/bluesky-social/pds">github.com/bluesky-social/pds</a><br> 166 + dynamic user list: <a href="https://tangled.org/@vielle.dev/server-config/blob/master/landing/landing.ts">most of the code here</a><br> 167 + </p> 168 + </div> 169 + 170 + </html>
+39
katproto_users.ts
··· 1 + async function getKatprotoUsers() { 2 + const users = fetch("https://katproto.girlonthemoon.xyz/xrpc/com.atproto.sync.listRepos") 3 + // type cast because no point validating for smthn like this 4 + // real type has more info; not needed here 5 + .then((res) => res.json() as Promise<{ repos: { did: string }[] }>) 6 + .then((res) => 7 + // get display name, handle, and did for each user 8 + res.repos.map((repo) => ({ 9 + display: fetch( 10 + `https://katproto.girlonthemoon.xyz/xrpc/com.atproto.repo.getRecord?repo=${repo.did}&collection=app.bsky.actor.profile&rkey=self` 11 + ) 12 + .then((res) => res.json()) 13 + .then((profile) => profile.value.displayName), 14 + // dont validate handles because I'm Lazy + trust myself 15 + handle: fetch( 16 + repo.did.startsWith("did:plc") 17 + ? "https://plc.directory/" + repo.did 18 + : `https://${repo.did.replace("did:web:", "")}/.well-known/did.json` 19 + ) 20 + .then((res) => res.json()) 21 + .then((doc) => doc.alsoKnownAs[0].replace("at://", "")), 22 + did: repo.did 23 + })) 24 + ) 25 + .then(async (users) => 26 + ( 27 + await Promise.all( 28 + users.map( 29 + async (x) => 30 + `<span class="user-count"><a href="https://bsky.app/profile/${x.did}">${await x.display}</a></span>` 31 + ) 32 + ) 33 + ) 34 + ) 35 + const fin = Array.from(await users).join("<br>"); 36 + return (await fin); 37 + }; 38 + 39 + getKatprotoUsers();
+25
package-lock.json
··· 1 + { 2 + "name": "bsky", 3 + "lockfileVersion": 3, 4 + "requires": true, 5 + "packages": { 6 + "": { 7 + "dependencies": { 8 + "typescript": "^5.9.2" 9 + } 10 + }, 11 + "node_modules/typescript": { 12 + "version": "5.9.2", 13 + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", 14 + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", 15 + "license": "Apache-2.0", 16 + "bin": { 17 + "tsc": "bin/tsc", 18 + "tsserver": "bin/tsserver" 19 + }, 20 + "engines": { 21 + "node": ">=14.17" 22 + } 23 + } 24 + } 25 + }
+6
package.json
··· 1 + { 2 + "type": "module", 3 + "dependencies": { 4 + "typescript": "^5.9.2" 5 + } 6 + }
pic.png

This is a binary file and will not be displayed.

pochacco.jpg

This is a binary file and will not be displayed.

+12
tsconfig.json
··· 1 + { 2 + "compilerOptions": { 3 + "target": "es2022", 4 + "module": "es2022", 5 + "esModuleInterop": true, 6 + "lib": ["ES2017", "DOM", "ES2021.String", "es2020"], 7 + "preserveConstEnums": true, 8 + "moduleResolution": "node", 9 + "strict": true, 10 + "inlineSourceMap": true, 11 + }, 12 + }