this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

'username' endpoint

alice 81045c8e 686cdb5e

+64 -5
icon.png

This is a binary file and will not be displayed.

+64 -5
index.ts
··· 2 2 import os from 'node:os'; 3 3 4 4 // Type the @ username that you want. Do not include an "@". 5 - const username = encodeURI(process.env.USERNAME!); 5 + const apUsername = encodeURIComponent(process.env.USERNAME!); 6 6 7 7 // This is the user's "real" name. 8 8 const realName = process.env.REALNAME!; ··· 12 12 13 13 // Generate locally or from https://cryptotools.net/rsagen 14 14 // Newlines must be replaced with "\n" 15 - const key_private = process.env.KEY_PRIVATE!.replace('\n', '\n'); 16 - const key_public = process.env.KEY_PUBLIC!.replace('\n', '\n'); 15 + const keyPrivate = process.env.KEY_PRIVATE!.replace('\n', '\n'); 16 + const keyPublic = process.env.KEY_PUBLIC!.replace('\n', '\n'); 17 17 18 18 // Password for sending messages 19 19 const password = process.env.PASSWORD!; ··· 133 133 }); 134 134 } 135 135 136 + // User: 137 + // Requesting `example.com/username` returns a JSON document with the user's information. 138 + function username(req: Request) { 139 + // Check if HTML was requested 140 + // If so, probably a browser - redirect to homepage 141 + const headers = req.headers; 142 + const accept = headers.get('Accept'); 143 + if (accept && accept.split(',')[0] === 'text/html') { 144 + return new Response(null, { 145 + status: 302, 146 + headers: { 147 + 'Location': `https://${serverHostName}/` 148 + } 149 + }); 150 + } 151 + 152 + const user = { 153 + "@context": [ 154 + "https://www.w3.org/ns/activitystreams", 155 + "https://w3id.org/security/v1" 156 + ], 157 + "id": `https://${serverHostName}/${apUsername}`, 158 + "type": "Application", 159 + "following": `https://${serverHostName}/following`, 160 + "followers": `https://${serverHostName}/followers`, 161 + "inbox": `https://${serverHostName}/inbox`, 162 + "outbox": `https://${serverHostName}/outbox`, 163 + "preferredUsername": decodeURIComponent(apUsername), 164 + "name": realName, 165 + "summary": summary, 166 + "url": `https://${serverHostName}/${apUsername}`, 167 + "manuallyApprovesFollowers": false, 168 + "discoverable": true, 169 + "published": "2024-02-29T12:34:56Z", 170 + "icon": { 171 + "type": "Image", 172 + "mediaType": "image/png", 173 + "url": `https://${serverHostName}/icon.png` 174 + }, 175 + "image": { 176 + "type": "Image", 177 + "mediaType": "image/png", 178 + "url": `https://${serverHostName}/banner.png` 179 + }, 180 + "publicKey": { 181 + "id": `https://${serverHostName}/${apUsername}#main-key`, 182 + "owner": `https://${serverHostName}/${apUsername}`, 183 + "publicKeyPem": keyPublic 184 + } 185 + }; 186 + 187 + return new Response(JSON.stringify(user), { 188 + headers: { 189 + 'Content-Type': 'application/activity+json' 190 + } 191 + }); 192 + } 193 + 194 + 136 195 const server = Bun.serve({ 137 196 port: 3003, 138 197 fetch(req, server) { ··· 143 202 return wk_nodeinfo(); // Optional. Static. 144 203 } else if (path === '/nodeinfo/2.1') { 145 204 return nodeinfo(); // Optional. Static. 146 - } else if (path === `/${decodeURI(username)}` || path === `/@${decodeURI(username)}`) { 147 - return username(); // Mandatory. Static 205 + } else if (path === `/${decodeURIComponent(apUsername)}` || path === `/@${decodeURIComponent(apUsername)}`) { 206 + return username(req); // Mandatory. Static 148 207 } else if (path === '/following') { 149 208 return following(); // Mandatory. Can be static or dynamic. 150 209 } else if (path === '/followers') {