atproto pastebin service: https://plonk.li

add headers on all views

Changed files
+928 -889
src
+1 -1
src/auth/client.ts
··· 9 9 const enc = encodeURIComponent; 10 10 return new NodeOAuthClient({ 11 11 clientMetadata: { 12 - client_name: "AT Protocol Express App", 12 + client_name: "plonk.li", 13 13 client_id: publicUrl 14 14 ? `${url}/client-metadata.json` 15 15 : `http://localhost?redirect_uri=${enc(`${url}/oauth/callback`)}&scope=${enc("atproto transition:generic")}`,
+2 -2
src/db.ts
··· 47 47 indexedAt: string; 48 48 pasteUri: string; 49 49 pasteCid: string; 50 - } 50 + }; 51 51 52 52 type AuthSessionJson = string; 53 53 type AuthStateJson = string; ··· 115 115 async down(db: Kysely<unknown>) { 116 116 await db.schema.dropTable("comments").execute(); 117 117 }, 118 - } 118 + }; 119 119 120 120 function generateShortString(length: number): string { 121 121 return randomBytes(length).toString("base64url").substring(0, length);
+1 -1
src/ingester.ts
··· 86 86 .deleteFrom("comment") 87 87 .where("uri", "=", evt.uri.toString()) 88 88 .execute(); 89 - } 89 + } 90 90 }, 91 91 onError: (err) => { 92 92 logger.error({ err }, "error on firehose ingestion");
+103 -103
src/lexicons/index.ts
··· 2 2 * GENERATED CODE - DO NOT MODIFY 3 3 */ 4 4 import { 5 - createServer as createXrpcServer, 6 - Server as XrpcServer, 7 - Options as XrpcOptions, 8 - AuthVerifier, 9 - StreamAuthVerifier, 10 - } from '@atproto/xrpc-server' 11 - import { schemas } from './lexicons' 12 - import * as ComAtprotoRepoGetRecord from './types/com/atproto/repo/getRecord' 13 - import * as ComAtprotoRepoListRecords from './types/com/atproto/repo/listRecords' 5 + createServer as createXrpcServer, 6 + Server as XrpcServer, 7 + Options as XrpcOptions, 8 + AuthVerifier, 9 + StreamAuthVerifier, 10 + } from "@atproto/xrpc-server"; 11 + import { schemas } from "./lexicons"; 12 + import * as ComAtprotoRepoGetRecord from "./types/com/atproto/repo/getRecord"; 13 + import * as ComAtprotoRepoListRecords from "./types/com/atproto/repo/listRecords"; 14 14 15 15 export function createServer(options?: XrpcOptions): Server { 16 - return new Server(options) 16 + return new Server(options); 17 17 } 18 18 19 19 export class Server { 20 - xrpc: XrpcServer 21 - li: LiNS 22 - com: ComNS 23 - app: AppNS 20 + xrpc: XrpcServer; 21 + li: LiNS; 22 + com: ComNS; 23 + app: AppNS; 24 24 25 - constructor(options?: XrpcOptions) { 26 - this.xrpc = createXrpcServer(schemas, options) 27 - this.li = new LiNS(this) 28 - this.com = new ComNS(this) 29 - this.app = new AppNS(this) 30 - } 25 + constructor(options?: XrpcOptions) { 26 + this.xrpc = createXrpcServer(schemas, options); 27 + this.li = new LiNS(this); 28 + this.com = new ComNS(this); 29 + this.app = new AppNS(this); 30 + } 31 31 } 32 32 33 33 export class LiNS { 34 - _server: Server 35 - plonk: LiPlonkNS 34 + _server: Server; 35 + plonk: LiPlonkNS; 36 36 37 - constructor(server: Server) { 38 - this._server = server 39 - this.plonk = new LiPlonkNS(server) 40 - } 37 + constructor(server: Server) { 38 + this._server = server; 39 + this.plonk = new LiPlonkNS(server); 40 + } 41 41 } 42 42 43 43 export class LiPlonkNS { 44 - _server: Server 44 + _server: Server; 45 45 46 - constructor(server: Server) { 47 - this._server = server 48 - } 46 + constructor(server: Server) { 47 + this._server = server; 48 + } 49 49 } 50 50 51 51 export class ComNS { 52 - _server: Server 53 - atproto: ComAtprotoNS 52 + _server: Server; 53 + atproto: ComAtprotoNS; 54 54 55 - constructor(server: Server) { 56 - this._server = server 57 - this.atproto = new ComAtprotoNS(server) 58 - } 55 + constructor(server: Server) { 56 + this._server = server; 57 + this.atproto = new ComAtprotoNS(server); 58 + } 59 59 } 60 60 61 61 export class ComAtprotoNS { 62 - _server: Server 63 - repo: ComAtprotoRepoNS 62 + _server: Server; 63 + repo: ComAtprotoRepoNS; 64 64 65 - constructor(server: Server) { 66 - this._server = server 67 - this.repo = new ComAtprotoRepoNS(server) 68 - } 65 + constructor(server: Server) { 66 + this._server = server; 67 + this.repo = new ComAtprotoRepoNS(server); 68 + } 69 69 } 70 70 71 71 export class ComAtprotoRepoNS { 72 - _server: Server 72 + _server: Server; 73 73 74 - constructor(server: Server) { 75 - this._server = server 76 - } 74 + constructor(server: Server) { 75 + this._server = server; 76 + } 77 77 78 - getRecord<AV extends AuthVerifier>( 79 - cfg: ConfigOf< 80 - AV, 81 - ComAtprotoRepoGetRecord.Handler<ExtractAuth<AV>>, 82 - ComAtprotoRepoGetRecord.HandlerReqCtx<ExtractAuth<AV>> 83 - >, 84 - ) { 85 - const nsid = 'com.atproto.repo.getRecord' // @ts-ignore 86 - return this._server.xrpc.method(nsid, cfg) 87 - } 78 + getRecord<AV extends AuthVerifier>( 79 + cfg: ConfigOf< 80 + AV, 81 + ComAtprotoRepoGetRecord.Handler<ExtractAuth<AV>>, 82 + ComAtprotoRepoGetRecord.HandlerReqCtx<ExtractAuth<AV>> 83 + >, 84 + ) { 85 + const nsid = "com.atproto.repo.getRecord"; // @ts-ignore 86 + return this._server.xrpc.method(nsid, cfg); 87 + } 88 88 89 - listRecords<AV extends AuthVerifier>( 90 - cfg: ConfigOf< 91 - AV, 92 - ComAtprotoRepoListRecords.Handler<ExtractAuth<AV>>, 93 - ComAtprotoRepoListRecords.HandlerReqCtx<ExtractAuth<AV>> 94 - >, 95 - ) { 96 - const nsid = 'com.atproto.repo.listRecords' // @ts-ignore 97 - return this._server.xrpc.method(nsid, cfg) 98 - } 89 + listRecords<AV extends AuthVerifier>( 90 + cfg: ConfigOf< 91 + AV, 92 + ComAtprotoRepoListRecords.Handler<ExtractAuth<AV>>, 93 + ComAtprotoRepoListRecords.HandlerReqCtx<ExtractAuth<AV>> 94 + >, 95 + ) { 96 + const nsid = "com.atproto.repo.listRecords"; // @ts-ignore 97 + return this._server.xrpc.method(nsid, cfg); 98 + } 99 99 } 100 100 101 101 export class AppNS { 102 - _server: Server 103 - bsky: AppBskyNS 102 + _server: Server; 103 + bsky: AppBskyNS; 104 104 105 - constructor(server: Server) { 106 - this._server = server 107 - this.bsky = new AppBskyNS(server) 108 - } 105 + constructor(server: Server) { 106 + this._server = server; 107 + this.bsky = new AppBskyNS(server); 108 + } 109 109 } 110 110 111 111 export class AppBskyNS { 112 - _server: Server 113 - actor: AppBskyActorNS 112 + _server: Server; 113 + actor: AppBskyActorNS; 114 114 115 - constructor(server: Server) { 116 - this._server = server 117 - this.actor = new AppBskyActorNS(server) 118 - } 115 + constructor(server: Server) { 116 + this._server = server; 117 + this.actor = new AppBskyActorNS(server); 118 + } 119 119 } 120 120 121 121 export class AppBskyActorNS { 122 - _server: Server 122 + _server: Server; 123 123 124 - constructor(server: Server) { 125 - this._server = server 126 - } 124 + constructor(server: Server) { 125 + this._server = server; 126 + } 127 127 } 128 128 129 129 type SharedRateLimitOpts<T> = { 130 - name: string 131 - calcKey?: (ctx: T) => string 132 - calcPoints?: (ctx: T) => number 133 - } 130 + name: string; 131 + calcKey?: (ctx: T) => string; 132 + calcPoints?: (ctx: T) => number; 133 + }; 134 134 type RouteRateLimitOpts<T> = { 135 - durationMs: number 136 - points: number 137 - calcKey?: (ctx: T) => string 138 - calcPoints?: (ctx: T) => number 139 - } 140 - type HandlerOpts = { blobLimit?: number } 141 - type HandlerRateLimitOpts<T> = SharedRateLimitOpts<T> | RouteRateLimitOpts<T> 135 + durationMs: number; 136 + points: number; 137 + calcKey?: (ctx: T) => string; 138 + calcPoints?: (ctx: T) => number; 139 + }; 140 + type HandlerOpts = { blobLimit?: number }; 141 + type HandlerRateLimitOpts<T> = SharedRateLimitOpts<T> | RouteRateLimitOpts<T>; 142 142 type ConfigOf<Auth, Handler, ReqCtx> = 143 - | Handler 144 - | { 145 - auth?: Auth 146 - opts?: HandlerOpts 147 - rateLimit?: HandlerRateLimitOpts<ReqCtx> | HandlerRateLimitOpts<ReqCtx>[] 148 - handler: Handler 149 - } 143 + | Handler 144 + | { 145 + auth?: Auth; 146 + opts?: HandlerOpts; 147 + rateLimit?: HandlerRateLimitOpts<ReqCtx> | HandlerRateLimitOpts<ReqCtx>[]; 148 + handler: Handler; 149 + }; 150 150 type ExtractAuth<AV extends AuthVerifier | StreamAuthVerifier> = Extract< 151 - Awaited<ReturnType<AV>>, 152 - { credentials: unknown } 153 - > 151 + Awaited<ReturnType<AV>>, 152 + { credentials: unknown } 153 + >;
+491 -491
src/lexicons/lexicons.ts
··· 1 1 /** 2 2 * GENERATED CODE - DO NOT MODIFY 3 3 */ 4 - import { LexiconDoc, Lexicons } from '@atproto/lexicon' 4 + import { LexiconDoc, Lexicons } from "@atproto/lexicon"; 5 5 6 6 export const schemaDict = { 7 - LiPlonkComment: { 8 - lexicon: 1, 9 - id: 'li.plonk.comment', 10 - defs: { 11 - main: { 12 - type: 'record', 13 - key: 'tid', 14 - record: { 15 - type: 'object', 16 - required: ['content', 'createdAt', 'post'], 17 - properties: { 18 - content: { 19 - type: 'string', 20 - maxLength: 100000, 21 - maxGraphemes: 10000, 22 - description: 'comment body', 23 - }, 24 - createdAt: { 25 - type: 'string', 26 - format: 'datetime', 27 - description: 'comment creation timestamp', 28 - }, 29 - post: { 30 - type: 'ref', 31 - ref: 'lex:com.atproto.repo.strongRef', 32 - }, 33 - }, 34 - }, 35 - }, 36 - }, 37 - }, 38 - ComAtprotoLabelDefs: { 39 - lexicon: 1, 40 - id: 'com.atproto.label.defs', 41 - defs: { 42 - label: { 43 - type: 'object', 44 - description: 45 - 'Metadata tag on an atproto resource (eg, repo or record).', 46 - required: ['src', 'uri', 'val', 'cts'], 47 - properties: { 48 - ver: { 49 - type: 'integer', 50 - description: 'The AT Protocol version of the label object.', 51 - }, 52 - src: { 53 - type: 'string', 54 - format: 'did', 55 - description: 'DID of the actor who created this label.', 56 - }, 57 - uri: { 58 - type: 'string', 59 - format: 'uri', 60 - description: 61 - 'AT URI of the record, repository (account), or other resource that this label applies to.', 62 - }, 63 - cid: { 64 - type: 'string', 65 - format: 'cid', 66 - description: 67 - "Optionally, CID specifying the specific version of 'uri' resource this label applies to.", 68 - }, 69 - val: { 70 - type: 'string', 71 - maxLength: 128, 72 - description: 73 - 'The short string name of the value or type of this label.', 74 - }, 75 - neg: { 76 - type: 'boolean', 77 - description: 78 - 'If true, this is a negation label, overwriting a previous label.', 79 - }, 80 - cts: { 81 - type: 'string', 82 - format: 'datetime', 83 - description: 'Timestamp when this label was created.', 84 - }, 85 - exp: { 86 - type: 'string', 87 - format: 'datetime', 88 - description: 89 - 'Timestamp at which this label expires (no longer applies).', 90 - }, 91 - sig: { 92 - type: 'bytes', 93 - description: 'Signature of dag-cbor encoded label.', 94 - }, 95 - }, 96 - }, 97 - selfLabels: { 98 - type: 'object', 99 - description: 100 - 'Metadata tags on an atproto record, published by the author within the record.', 101 - required: ['values'], 102 - properties: { 103 - values: { 104 - type: 'array', 105 - items: { 106 - type: 'ref', 107 - ref: 'lex:com.atproto.label.defs#selfLabel', 108 - }, 109 - maxLength: 10, 110 - }, 111 - }, 112 - }, 113 - selfLabel: { 114 - type: 'object', 115 - description: 116 - 'Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.', 117 - required: ['val'], 118 - properties: { 119 - val: { 120 - type: 'string', 121 - maxLength: 128, 122 - description: 123 - 'The short string name of the value or type of this label.', 124 - }, 125 - }, 126 - }, 127 - labelValueDefinition: { 128 - type: 'object', 129 - description: 130 - 'Declares a label value and its expected interpretations and behaviors.', 131 - required: ['identifier', 'severity', 'blurs', 'locales'], 132 - properties: { 133 - identifier: { 134 - type: 'string', 135 - description: 136 - "The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).", 137 - maxLength: 100, 138 - maxGraphemes: 100, 139 - }, 140 - severity: { 141 - type: 'string', 142 - description: 143 - "How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.", 144 - knownValues: ['inform', 'alert', 'none'], 145 - }, 146 - blurs: { 147 - type: 'string', 148 - description: 149 - "What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing.", 150 - knownValues: ['content', 'media', 'none'], 151 - }, 152 - defaultSetting: { 153 - type: 'string', 154 - description: 'The default setting for this label.', 155 - knownValues: ['ignore', 'warn', 'hide'], 156 - default: 'warn', 157 - }, 158 - adultOnly: { 159 - type: 'boolean', 160 - description: 161 - 'Does the user need to have adult content enabled in order to configure this label?', 162 - }, 163 - locales: { 164 - type: 'array', 165 - items: { 166 - type: 'ref', 167 - ref: 'lex:com.atproto.label.defs#labelValueDefinitionStrings', 168 - }, 169 - }, 170 - }, 171 - }, 172 - labelValueDefinitionStrings: { 173 - type: 'object', 174 - description: 175 - 'Strings which describe the label in the UI, localized into a specific language.', 176 - required: ['lang', 'name', 'description'], 177 - properties: { 178 - lang: { 179 - type: 'string', 180 - description: 181 - 'The code of the language these strings are written in.', 182 - format: 'language', 183 - }, 184 - name: { 185 - type: 'string', 186 - description: 'A short human-readable name for the label.', 187 - maxGraphemes: 64, 188 - maxLength: 640, 189 - }, 190 - description: { 191 - type: 'string', 192 - description: 193 - 'A longer description of what the label means and why it might be applied.', 194 - maxGraphemes: 10000, 195 - maxLength: 100000, 196 - }, 197 - }, 198 - }, 199 - labelValue: { 200 - type: 'string', 201 - knownValues: [ 202 - '!hide', 203 - '!no-promote', 204 - '!warn', 205 - '!no-unauthenticated', 206 - 'dmca-violation', 207 - 'doxxing', 208 - 'porn', 209 - 'sexual', 210 - 'nudity', 211 - 'nsfl', 212 - 'gore', 213 - ], 214 - }, 215 - }, 216 - }, 217 - ComAtprotoRepoGetRecord: { 218 - lexicon: 1, 219 - id: 'com.atproto.repo.getRecord', 220 - defs: { 221 - main: { 222 - type: 'query', 223 - description: 224 - 'Get a single record from a repository. Does not require auth.', 225 - parameters: { 226 - type: 'params', 227 - required: ['repo', 'collection', 'rkey'], 228 - properties: { 229 - repo: { 230 - type: 'string', 231 - format: 'at-identifier', 232 - description: 'The handle or DID of the repo.', 233 - }, 234 - collection: { 235 - type: 'string', 236 - format: 'nsid', 237 - description: 'The NSID of the record collection.', 238 - }, 239 - rkey: { 240 - type: 'string', 241 - description: 'The Record Key.', 242 - }, 243 - cid: { 244 - type: 'string', 245 - format: 'cid', 246 - description: 247 - 'The CID of the version of the record. If not specified, then return the most recent version.', 248 - }, 249 - }, 250 - }, 251 - output: { 252 - encoding: 'application/json', 253 - schema: { 254 - type: 'object', 255 - required: ['uri', 'value'], 256 - properties: { 257 - uri: { 258 - type: 'string', 259 - format: 'at-uri', 260 - }, 261 - cid: { 262 - type: 'string', 263 - format: 'cid', 264 - }, 265 - value: { 266 - type: 'unknown', 267 - }, 268 - }, 269 - }, 270 - }, 271 - errors: [ 272 - { 273 - name: 'RecordNotFound', 274 - }, 275 - ], 276 - }, 277 - }, 278 - }, 279 - ComAtprotoRepoListRecords: { 280 - lexicon: 1, 281 - id: 'com.atproto.repo.listRecords', 282 - defs: { 283 - main: { 284 - type: 'query', 285 - description: 286 - 'List a range of records in a repository, matching a specific collection. Does not require auth.', 287 - parameters: { 288 - type: 'params', 289 - required: ['repo', 'collection'], 290 - properties: { 291 - repo: { 292 - type: 'string', 293 - format: 'at-identifier', 294 - description: 'The handle or DID of the repo.', 295 - }, 296 - collection: { 297 - type: 'string', 298 - format: 'nsid', 299 - description: 'The NSID of the record type.', 300 - }, 301 - limit: { 302 - type: 'integer', 303 - minimum: 1, 304 - maximum: 100, 305 - default: 50, 306 - description: 'The number of records to return.', 307 - }, 308 - cursor: { 309 - type: 'string', 310 - }, 311 - rkeyStart: { 312 - type: 'string', 313 - description: 314 - 'DEPRECATED: The lowest sort-ordered rkey to start from (exclusive)', 315 - }, 316 - rkeyEnd: { 317 - type: 'string', 318 - description: 319 - 'DEPRECATED: The highest sort-ordered rkey to stop at (exclusive)', 320 - }, 321 - reverse: { 322 - type: 'boolean', 323 - description: 'Flag to reverse the order of the returned records.', 324 - }, 325 - }, 326 - }, 327 - output: { 328 - encoding: 'application/json', 329 - schema: { 330 - type: 'object', 331 - required: ['records'], 332 - properties: { 333 - cursor: { 334 - type: 'string', 335 - }, 336 - records: { 337 - type: 'array', 338 - items: { 339 - type: 'ref', 340 - ref: 'lex:com.atproto.repo.listRecords#record', 341 - }, 342 - }, 343 - }, 344 - }, 345 - }, 346 - }, 347 - record: { 348 - type: 'object', 349 - required: ['uri', 'cid', 'value'], 350 - properties: { 351 - uri: { 352 - type: 'string', 353 - format: 'at-uri', 354 - }, 355 - cid: { 356 - type: 'string', 357 - format: 'cid', 358 - }, 359 - value: { 360 - type: 'unknown', 361 - }, 362 - }, 363 - }, 364 - }, 365 - }, 366 - LiPlonkPaste: { 367 - lexicon: 1, 368 - id: 'li.plonk.paste', 369 - defs: { 370 - main: { 371 - type: 'record', 372 - key: 'tid', 373 - record: { 374 - type: 'object', 375 - required: ['code', 'shortUrl', 'lang', 'title', 'createdAt'], 376 - properties: { 377 - code: { 378 - type: 'string', 379 - minLength: 1, 380 - maxGraphemes: 65536, 381 - maxLength: 65536, 382 - }, 383 - shortUrl: { 384 - type: 'string', 385 - minLength: 2, 386 - maxGraphemes: 10, 387 - maxLength: 10, 388 - }, 389 - lang: { 390 - type: 'string', 391 - minLength: 1, 392 - maxGraphemes: 20, 393 - maxLength: 20, 394 - }, 395 - title: { 396 - type: 'string', 397 - minLength: 1, 398 - maxGraphemes: 100, 399 - maxLength: 100, 400 - }, 401 - createdAt: { 402 - type: 'string', 403 - format: 'datetime', 404 - }, 405 - }, 406 - }, 407 - }, 408 - }, 409 - }, 410 - AppBskyActorProfile: { 411 - lexicon: 1, 412 - id: 'app.bsky.actor.profile', 413 - defs: { 414 - main: { 415 - type: 'record', 416 - description: 'A declaration of a Bluesky account profile.', 417 - key: 'literal:self', 418 - record: { 419 - type: 'object', 420 - properties: { 421 - displayName: { 422 - type: 'string', 423 - maxGraphemes: 64, 424 - maxLength: 640, 425 - }, 426 - description: { 427 - type: 'string', 428 - description: 'Free-form profile description text.', 429 - maxGraphemes: 256, 430 - maxLength: 2560, 431 - }, 432 - avatar: { 433 - type: 'blob', 434 - description: 435 - "Small image to be displayed next to posts from account. AKA, 'profile picture'", 436 - accept: ['image/png', 'image/jpeg'], 437 - maxSize: 1000000, 438 - }, 439 - banner: { 440 - type: 'blob', 441 - description: 442 - 'Larger horizontal image to display behind profile view.', 443 - accept: ['image/png', 'image/jpeg'], 444 - maxSize: 1000000, 445 - }, 446 - labels: { 447 - type: 'union', 448 - description: 449 - 'Self-label values, specific to the Bluesky application, on the overall account.', 450 - refs: ['lex:com.atproto.label.defs#selfLabels'], 451 - }, 452 - joinedViaStarterPack: { 453 - type: 'ref', 454 - ref: 'lex:com.atproto.repo.strongRef', 455 - }, 456 - createdAt: { 457 - type: 'string', 458 - format: 'datetime', 459 - }, 460 - }, 461 - }, 462 - }, 463 - }, 464 - }, 465 - ComAtprotoRepoStrongRef: { 466 - lexicon: 1, 467 - id: 'com.atproto.repo.strongRef', 468 - description: 'A URI with a content-hash fingerprint.', 469 - defs: { 470 - main: { 471 - type: 'object', 472 - required: ['uri', 'cid'], 473 - properties: { 474 - uri: { 475 - type: 'string', 476 - format: 'at-uri', 477 - }, 478 - cid: { 479 - type: 'string', 480 - format: 'cid', 481 - }, 482 - }, 483 - }, 484 - }, 485 - }, 486 - } 487 - export const schemas: LexiconDoc[] = Object.values(schemaDict) as LexiconDoc[] 488 - export const lexicons: Lexicons = new Lexicons(schemas) 7 + LiPlonkComment: { 8 + lexicon: 1, 9 + id: "li.plonk.comment", 10 + defs: { 11 + main: { 12 + type: "record", 13 + key: "tid", 14 + record: { 15 + type: "object", 16 + required: ["content", "createdAt", "post"], 17 + properties: { 18 + content: { 19 + type: "string", 20 + maxLength: 100000, 21 + maxGraphemes: 10000, 22 + description: "comment body", 23 + }, 24 + createdAt: { 25 + type: "string", 26 + format: "datetime", 27 + description: "comment creation timestamp", 28 + }, 29 + post: { 30 + type: "ref", 31 + ref: "lex:com.atproto.repo.strongRef", 32 + }, 33 + }, 34 + }, 35 + }, 36 + }, 37 + }, 38 + ComAtprotoLabelDefs: { 39 + lexicon: 1, 40 + id: "com.atproto.label.defs", 41 + defs: { 42 + label: { 43 + type: "object", 44 + description: 45 + "Metadata tag on an atproto resource (eg, repo or record).", 46 + required: ["src", "uri", "val", "cts"], 47 + properties: { 48 + ver: { 49 + type: "integer", 50 + description: "The AT Protocol version of the label object.", 51 + }, 52 + src: { 53 + type: "string", 54 + format: "did", 55 + description: "DID of the actor who created this label.", 56 + }, 57 + uri: { 58 + type: "string", 59 + format: "uri", 60 + description: 61 + "AT URI of the record, repository (account), or other resource that this label applies to.", 62 + }, 63 + cid: { 64 + type: "string", 65 + format: "cid", 66 + description: 67 + "Optionally, CID specifying the specific version of 'uri' resource this label applies to.", 68 + }, 69 + val: { 70 + type: "string", 71 + maxLength: 128, 72 + description: 73 + "The short string name of the value or type of this label.", 74 + }, 75 + neg: { 76 + type: "boolean", 77 + description: 78 + "If true, this is a negation label, overwriting a previous label.", 79 + }, 80 + cts: { 81 + type: "string", 82 + format: "datetime", 83 + description: "Timestamp when this label was created.", 84 + }, 85 + exp: { 86 + type: "string", 87 + format: "datetime", 88 + description: 89 + "Timestamp at which this label expires (no longer applies).", 90 + }, 91 + sig: { 92 + type: "bytes", 93 + description: "Signature of dag-cbor encoded label.", 94 + }, 95 + }, 96 + }, 97 + selfLabels: { 98 + type: "object", 99 + description: 100 + "Metadata tags on an atproto record, published by the author within the record.", 101 + required: ["values"], 102 + properties: { 103 + values: { 104 + type: "array", 105 + items: { 106 + type: "ref", 107 + ref: "lex:com.atproto.label.defs#selfLabel", 108 + }, 109 + maxLength: 10, 110 + }, 111 + }, 112 + }, 113 + selfLabel: { 114 + type: "object", 115 + description: 116 + "Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.", 117 + required: ["val"], 118 + properties: { 119 + val: { 120 + type: "string", 121 + maxLength: 128, 122 + description: 123 + "The short string name of the value or type of this label.", 124 + }, 125 + }, 126 + }, 127 + labelValueDefinition: { 128 + type: "object", 129 + description: 130 + "Declares a label value and its expected interpretations and behaviors.", 131 + required: ["identifier", "severity", "blurs", "locales"], 132 + properties: { 133 + identifier: { 134 + type: "string", 135 + description: 136 + "The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).", 137 + maxLength: 100, 138 + maxGraphemes: 100, 139 + }, 140 + severity: { 141 + type: "string", 142 + description: 143 + "How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.", 144 + knownValues: ["inform", "alert", "none"], 145 + }, 146 + blurs: { 147 + type: "string", 148 + description: 149 + "What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing.", 150 + knownValues: ["content", "media", "none"], 151 + }, 152 + defaultSetting: { 153 + type: "string", 154 + description: "The default setting for this label.", 155 + knownValues: ["ignore", "warn", "hide"], 156 + default: "warn", 157 + }, 158 + adultOnly: { 159 + type: "boolean", 160 + description: 161 + "Does the user need to have adult content enabled in order to configure this label?", 162 + }, 163 + locales: { 164 + type: "array", 165 + items: { 166 + type: "ref", 167 + ref: "lex:com.atproto.label.defs#labelValueDefinitionStrings", 168 + }, 169 + }, 170 + }, 171 + }, 172 + labelValueDefinitionStrings: { 173 + type: "object", 174 + description: 175 + "Strings which describe the label in the UI, localized into a specific language.", 176 + required: ["lang", "name", "description"], 177 + properties: { 178 + lang: { 179 + type: "string", 180 + description: 181 + "The code of the language these strings are written in.", 182 + format: "language", 183 + }, 184 + name: { 185 + type: "string", 186 + description: "A short human-readable name for the label.", 187 + maxGraphemes: 64, 188 + maxLength: 640, 189 + }, 190 + description: { 191 + type: "string", 192 + description: 193 + "A longer description of what the label means and why it might be applied.", 194 + maxGraphemes: 10000, 195 + maxLength: 100000, 196 + }, 197 + }, 198 + }, 199 + labelValue: { 200 + type: "string", 201 + knownValues: [ 202 + "!hide", 203 + "!no-promote", 204 + "!warn", 205 + "!no-unauthenticated", 206 + "dmca-violation", 207 + "doxxing", 208 + "porn", 209 + "sexual", 210 + "nudity", 211 + "nsfl", 212 + "gore", 213 + ], 214 + }, 215 + }, 216 + }, 217 + ComAtprotoRepoGetRecord: { 218 + lexicon: 1, 219 + id: "com.atproto.repo.getRecord", 220 + defs: { 221 + main: { 222 + type: "query", 223 + description: 224 + "Get a single record from a repository. Does not require auth.", 225 + parameters: { 226 + type: "params", 227 + required: ["repo", "collection", "rkey"], 228 + properties: { 229 + repo: { 230 + type: "string", 231 + format: "at-identifier", 232 + description: "The handle or DID of the repo.", 233 + }, 234 + collection: { 235 + type: "string", 236 + format: "nsid", 237 + description: "The NSID of the record collection.", 238 + }, 239 + rkey: { 240 + type: "string", 241 + description: "The Record Key.", 242 + }, 243 + cid: { 244 + type: "string", 245 + format: "cid", 246 + description: 247 + "The CID of the version of the record. If not specified, then return the most recent version.", 248 + }, 249 + }, 250 + }, 251 + output: { 252 + encoding: "application/json", 253 + schema: { 254 + type: "object", 255 + required: ["uri", "value"], 256 + properties: { 257 + uri: { 258 + type: "string", 259 + format: "at-uri", 260 + }, 261 + cid: { 262 + type: "string", 263 + format: "cid", 264 + }, 265 + value: { 266 + type: "unknown", 267 + }, 268 + }, 269 + }, 270 + }, 271 + errors: [ 272 + { 273 + name: "RecordNotFound", 274 + }, 275 + ], 276 + }, 277 + }, 278 + }, 279 + ComAtprotoRepoListRecords: { 280 + lexicon: 1, 281 + id: "com.atproto.repo.listRecords", 282 + defs: { 283 + main: { 284 + type: "query", 285 + description: 286 + "List a range of records in a repository, matching a specific collection. Does not require auth.", 287 + parameters: { 288 + type: "params", 289 + required: ["repo", "collection"], 290 + properties: { 291 + repo: { 292 + type: "string", 293 + format: "at-identifier", 294 + description: "The handle or DID of the repo.", 295 + }, 296 + collection: { 297 + type: "string", 298 + format: "nsid", 299 + description: "The NSID of the record type.", 300 + }, 301 + limit: { 302 + type: "integer", 303 + minimum: 1, 304 + maximum: 100, 305 + default: 50, 306 + description: "The number of records to return.", 307 + }, 308 + cursor: { 309 + type: "string", 310 + }, 311 + rkeyStart: { 312 + type: "string", 313 + description: 314 + "DEPRECATED: The lowest sort-ordered rkey to start from (exclusive)", 315 + }, 316 + rkeyEnd: { 317 + type: "string", 318 + description: 319 + "DEPRECATED: The highest sort-ordered rkey to stop at (exclusive)", 320 + }, 321 + reverse: { 322 + type: "boolean", 323 + description: "Flag to reverse the order of the returned records.", 324 + }, 325 + }, 326 + }, 327 + output: { 328 + encoding: "application/json", 329 + schema: { 330 + type: "object", 331 + required: ["records"], 332 + properties: { 333 + cursor: { 334 + type: "string", 335 + }, 336 + records: { 337 + type: "array", 338 + items: { 339 + type: "ref", 340 + ref: "lex:com.atproto.repo.listRecords#record", 341 + }, 342 + }, 343 + }, 344 + }, 345 + }, 346 + }, 347 + record: { 348 + type: "object", 349 + required: ["uri", "cid", "value"], 350 + properties: { 351 + uri: { 352 + type: "string", 353 + format: "at-uri", 354 + }, 355 + cid: { 356 + type: "string", 357 + format: "cid", 358 + }, 359 + value: { 360 + type: "unknown", 361 + }, 362 + }, 363 + }, 364 + }, 365 + }, 366 + LiPlonkPaste: { 367 + lexicon: 1, 368 + id: "li.plonk.paste", 369 + defs: { 370 + main: { 371 + type: "record", 372 + key: "tid", 373 + record: { 374 + type: "object", 375 + required: ["code", "shortUrl", "lang", "title", "createdAt"], 376 + properties: { 377 + code: { 378 + type: "string", 379 + minLength: 1, 380 + maxGraphemes: 65536, 381 + maxLength: 65536, 382 + }, 383 + shortUrl: { 384 + type: "string", 385 + minLength: 2, 386 + maxGraphemes: 10, 387 + maxLength: 10, 388 + }, 389 + lang: { 390 + type: "string", 391 + minLength: 1, 392 + maxGraphemes: 20, 393 + maxLength: 20, 394 + }, 395 + title: { 396 + type: "string", 397 + minLength: 1, 398 + maxGraphemes: 100, 399 + maxLength: 100, 400 + }, 401 + createdAt: { 402 + type: "string", 403 + format: "datetime", 404 + }, 405 + }, 406 + }, 407 + }, 408 + }, 409 + }, 410 + AppBskyActorProfile: { 411 + lexicon: 1, 412 + id: "app.bsky.actor.profile", 413 + defs: { 414 + main: { 415 + type: "record", 416 + description: "A declaration of a Bluesky account profile.", 417 + key: "literal:self", 418 + record: { 419 + type: "object", 420 + properties: { 421 + displayName: { 422 + type: "string", 423 + maxGraphemes: 64, 424 + maxLength: 640, 425 + }, 426 + description: { 427 + type: "string", 428 + description: "Free-form profile description text.", 429 + maxGraphemes: 256, 430 + maxLength: 2560, 431 + }, 432 + avatar: { 433 + type: "blob", 434 + description: 435 + "Small image to be displayed next to posts from account. AKA, 'profile picture'", 436 + accept: ["image/png", "image/jpeg"], 437 + maxSize: 1000000, 438 + }, 439 + banner: { 440 + type: "blob", 441 + description: 442 + "Larger horizontal image to display behind profile view.", 443 + accept: ["image/png", "image/jpeg"], 444 + maxSize: 1000000, 445 + }, 446 + labels: { 447 + type: "union", 448 + description: 449 + "Self-label values, specific to the Bluesky application, on the overall account.", 450 + refs: ["lex:com.atproto.label.defs#selfLabels"], 451 + }, 452 + joinedViaStarterPack: { 453 + type: "ref", 454 + ref: "lex:com.atproto.repo.strongRef", 455 + }, 456 + createdAt: { 457 + type: "string", 458 + format: "datetime", 459 + }, 460 + }, 461 + }, 462 + }, 463 + }, 464 + }, 465 + ComAtprotoRepoStrongRef: { 466 + lexicon: 1, 467 + id: "com.atproto.repo.strongRef", 468 + description: "A URI with a content-hash fingerprint.", 469 + defs: { 470 + main: { 471 + type: "object", 472 + required: ["uri", "cid"], 473 + properties: { 474 + uri: { 475 + type: "string", 476 + format: "at-uri", 477 + }, 478 + cid: { 479 + type: "string", 480 + format: "cid", 481 + }, 482 + }, 483 + }, 484 + }, 485 + }, 486 + }; 487 + export const schemas: LexiconDoc[] = Object.values(schemaDict) as LexiconDoc[]; 488 + export const lexicons: Lexicons = new Lexicons(schemas); 489 489 export const ids = { 490 - LiPlonkComment: 'li.plonk.comment', 491 - ComAtprotoLabelDefs: 'com.atproto.label.defs', 492 - ComAtprotoRepoGetRecord: 'com.atproto.repo.getRecord', 493 - ComAtprotoRepoListRecords: 'com.atproto.repo.listRecords', 494 - LiPlonkPaste: 'li.plonk.paste', 495 - AppBskyActorProfile: 'app.bsky.actor.profile', 496 - ComAtprotoRepoStrongRef: 'com.atproto.repo.strongRef', 497 - } 490 + LiPlonkComment: "li.plonk.comment", 491 + ComAtprotoLabelDefs: "com.atproto.label.defs", 492 + ComAtprotoRepoGetRecord: "com.atproto.repo.getRecord", 493 + ComAtprotoRepoListRecords: "com.atproto.repo.listRecords", 494 + LiPlonkPaste: "li.plonk.paste", 495 + AppBskyActorProfile: "app.bsky.actor.profile", 496 + ComAtprotoRepoStrongRef: "com.atproto.repo.strongRef", 497 + };
+26 -26
src/lexicons/types/app/bsky/actor/profile.ts
··· 1 1 /** 2 2 * GENERATED CODE - DO NOT MODIFY 3 3 */ 4 - import { ValidationResult, BlobRef } from '@atproto/lexicon' 5 - import { lexicons } from '../../../../lexicons' 6 - import { isObj, hasProp } from '../../../../util' 7 - import { CID } from 'multiformats/cid' 8 - import * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs' 9 - import * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef' 4 + import { ValidationResult, BlobRef } from "@atproto/lexicon"; 5 + import { lexicons } from "../../../../lexicons"; 6 + import { isObj, hasProp } from "../../../../util"; 7 + import { CID } from "multiformats/cid"; 8 + import * as ComAtprotoLabelDefs from "../../../com/atproto/label/defs"; 9 + import * as ComAtprotoRepoStrongRef from "../../../com/atproto/repo/strongRef"; 10 10 11 11 export interface Record { 12 - displayName?: string 13 - /** Free-form profile description text. */ 14 - description?: string 15 - /** Small image to be displayed next to posts from account. AKA, 'profile picture' */ 16 - avatar?: BlobRef 17 - /** Larger horizontal image to display behind profile view. */ 18 - banner?: BlobRef 19 - labels?: 20 - | ComAtprotoLabelDefs.SelfLabels 21 - | { $type: string; [k: string]: unknown } 22 - joinedViaStarterPack?: ComAtprotoRepoStrongRef.Main 23 - createdAt?: string 24 - [k: string]: unknown 12 + displayName?: string; 13 + /** Free-form profile description text. */ 14 + description?: string; 15 + /** Small image to be displayed next to posts from account. AKA, 'profile picture' */ 16 + avatar?: BlobRef; 17 + /** Larger horizontal image to display behind profile view. */ 18 + banner?: BlobRef; 19 + labels?: 20 + | ComAtprotoLabelDefs.SelfLabels 21 + | { $type: string; [k: string]: unknown }; 22 + joinedViaStarterPack?: ComAtprotoRepoStrongRef.Main; 23 + createdAt?: string; 24 + [k: string]: unknown; 25 25 } 26 26 27 27 export function isRecord(v: unknown): v is Record { 28 - return ( 29 - isObj(v) && 30 - hasProp(v, '$type') && 31 - (v.$type === 'app.bsky.actor.profile#main' || 32 - v.$type === 'app.bsky.actor.profile') 33 - ) 28 + return ( 29 + isObj(v) && 30 + hasProp(v, "$type") && 31 + (v.$type === "app.bsky.actor.profile#main" || 32 + v.$type === "app.bsky.actor.profile") 33 + ); 34 34 } 35 35 36 36 export function validateRecord(v: unknown): ValidationResult { 37 - return lexicons.validate('app.bsky.actor.profile#main', v) 37 + return lexicons.validate("app.bsky.actor.profile#main", v); 38 38 }
+94 -94
src/lexicons/types/com/atproto/label/defs.ts
··· 1 1 /** 2 2 * GENERATED CODE - DO NOT MODIFY 3 3 */ 4 - import { ValidationResult, BlobRef } from '@atproto/lexicon' 5 - import { lexicons } from '../../../../lexicons' 6 - import { isObj, hasProp } from '../../../../util' 7 - import { CID } from 'multiformats/cid' 4 + import { ValidationResult, BlobRef } from "@atproto/lexicon"; 5 + import { lexicons } from "../../../../lexicons"; 6 + import { isObj, hasProp } from "../../../../util"; 7 + import { CID } from "multiformats/cid"; 8 8 9 9 /** Metadata tag on an atproto resource (eg, repo or record). */ 10 10 export interface Label { 11 - /** The AT Protocol version of the label object. */ 12 - ver?: number 13 - /** DID of the actor who created this label. */ 14 - src: string 15 - /** AT URI of the record, repository (account), or other resource that this label applies to. */ 16 - uri: string 17 - /** Optionally, CID specifying the specific version of 'uri' resource this label applies to. */ 18 - cid?: string 19 - /** The short string name of the value or type of this label. */ 20 - val: string 21 - /** If true, this is a negation label, overwriting a previous label. */ 22 - neg?: boolean 23 - /** Timestamp when this label was created. */ 24 - cts: string 25 - /** Timestamp at which this label expires (no longer applies). */ 26 - exp?: string 27 - /** Signature of dag-cbor encoded label. */ 28 - sig?: Uint8Array 29 - [k: string]: unknown 11 + /** The AT Protocol version of the label object. */ 12 + ver?: number; 13 + /** DID of the actor who created this label. */ 14 + src: string; 15 + /** AT URI of the record, repository (account), or other resource that this label applies to. */ 16 + uri: string; 17 + /** Optionally, CID specifying the specific version of 'uri' resource this label applies to. */ 18 + cid?: string; 19 + /** The short string name of the value or type of this label. */ 20 + val: string; 21 + /** If true, this is a negation label, overwriting a previous label. */ 22 + neg?: boolean; 23 + /** Timestamp when this label was created. */ 24 + cts: string; 25 + /** Timestamp at which this label expires (no longer applies). */ 26 + exp?: string; 27 + /** Signature of dag-cbor encoded label. */ 28 + sig?: Uint8Array; 29 + [k: string]: unknown; 30 30 } 31 31 32 32 export function isLabel(v: unknown): v is Label { 33 - return ( 34 - isObj(v) && 35 - hasProp(v, '$type') && 36 - v.$type === 'com.atproto.label.defs#label' 37 - ) 33 + return ( 34 + isObj(v) && 35 + hasProp(v, "$type") && 36 + v.$type === "com.atproto.label.defs#label" 37 + ); 38 38 } 39 39 40 40 export function validateLabel(v: unknown): ValidationResult { 41 - return lexicons.validate('com.atproto.label.defs#label', v) 41 + return lexicons.validate("com.atproto.label.defs#label", v); 42 42 } 43 43 44 44 /** Metadata tags on an atproto record, published by the author within the record. */ 45 45 export interface SelfLabels { 46 - values: SelfLabel[] 47 - [k: string]: unknown 46 + values: SelfLabel[]; 47 + [k: string]: unknown; 48 48 } 49 49 50 50 export function isSelfLabels(v: unknown): v is SelfLabels { 51 - return ( 52 - isObj(v) && 53 - hasProp(v, '$type') && 54 - v.$type === 'com.atproto.label.defs#selfLabels' 55 - ) 51 + return ( 52 + isObj(v) && 53 + hasProp(v, "$type") && 54 + v.$type === "com.atproto.label.defs#selfLabels" 55 + ); 56 56 } 57 57 58 58 export function validateSelfLabels(v: unknown): ValidationResult { 59 - return lexicons.validate('com.atproto.label.defs#selfLabels', v) 59 + return lexicons.validate("com.atproto.label.defs#selfLabels", v); 60 60 } 61 61 62 62 /** Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel. */ 63 63 export interface SelfLabel { 64 - /** The short string name of the value or type of this label. */ 65 - val: string 66 - [k: string]: unknown 64 + /** The short string name of the value or type of this label. */ 65 + val: string; 66 + [k: string]: unknown; 67 67 } 68 68 69 69 export function isSelfLabel(v: unknown): v is SelfLabel { 70 - return ( 71 - isObj(v) && 72 - hasProp(v, '$type') && 73 - v.$type === 'com.atproto.label.defs#selfLabel' 74 - ) 70 + return ( 71 + isObj(v) && 72 + hasProp(v, "$type") && 73 + v.$type === "com.atproto.label.defs#selfLabel" 74 + ); 75 75 } 76 76 77 77 export function validateSelfLabel(v: unknown): ValidationResult { 78 - return lexicons.validate('com.atproto.label.defs#selfLabel', v) 78 + return lexicons.validate("com.atproto.label.defs#selfLabel", v); 79 79 } 80 80 81 81 /** Declares a label value and its expected interpretations and behaviors. */ 82 82 export interface LabelValueDefinition { 83 - /** The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+). */ 84 - identifier: string 85 - /** How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing. */ 86 - severity: 'inform' | 'alert' | 'none' | (string & {}) 87 - /** What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing. */ 88 - blurs: 'content' | 'media' | 'none' | (string & {}) 89 - /** The default setting for this label. */ 90 - defaultSetting: 'ignore' | 'warn' | 'hide' | (string & {}) 91 - /** Does the user need to have adult content enabled in order to configure this label? */ 92 - adultOnly?: boolean 93 - locales: LabelValueDefinitionStrings[] 94 - [k: string]: unknown 83 + /** The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+). */ 84 + identifier: string; 85 + /** How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing. */ 86 + severity: "inform" | "alert" | "none" | (string & {}); 87 + /** What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing. */ 88 + blurs: "content" | "media" | "none" | (string & {}); 89 + /** The default setting for this label. */ 90 + defaultSetting: "ignore" | "warn" | "hide" | (string & {}); 91 + /** Does the user need to have adult content enabled in order to configure this label? */ 92 + adultOnly?: boolean; 93 + locales: LabelValueDefinitionStrings[]; 94 + [k: string]: unknown; 95 95 } 96 96 97 97 export function isLabelValueDefinition(v: unknown): v is LabelValueDefinition { 98 - return ( 99 - isObj(v) && 100 - hasProp(v, '$type') && 101 - v.$type === 'com.atproto.label.defs#labelValueDefinition' 102 - ) 98 + return ( 99 + isObj(v) && 100 + hasProp(v, "$type") && 101 + v.$type === "com.atproto.label.defs#labelValueDefinition" 102 + ); 103 103 } 104 104 105 105 export function validateLabelValueDefinition(v: unknown): ValidationResult { 106 - return lexicons.validate('com.atproto.label.defs#labelValueDefinition', v) 106 + return lexicons.validate("com.atproto.label.defs#labelValueDefinition", v); 107 107 } 108 108 109 109 /** Strings which describe the label in the UI, localized into a specific language. */ 110 110 export interface LabelValueDefinitionStrings { 111 - /** The code of the language these strings are written in. */ 112 - lang: string 113 - /** A short human-readable name for the label. */ 114 - name: string 115 - /** A longer description of what the label means and why it might be applied. */ 116 - description: string 117 - [k: string]: unknown 111 + /** The code of the language these strings are written in. */ 112 + lang: string; 113 + /** A short human-readable name for the label. */ 114 + name: string; 115 + /** A longer description of what the label means and why it might be applied. */ 116 + description: string; 117 + [k: string]: unknown; 118 118 } 119 119 120 120 export function isLabelValueDefinitionStrings( 121 - v: unknown, 121 + v: unknown, 122 122 ): v is LabelValueDefinitionStrings { 123 - return ( 124 - isObj(v) && 125 - hasProp(v, '$type') && 126 - v.$type === 'com.atproto.label.defs#labelValueDefinitionStrings' 127 - ) 123 + return ( 124 + isObj(v) && 125 + hasProp(v, "$type") && 126 + v.$type === "com.atproto.label.defs#labelValueDefinitionStrings" 127 + ); 128 128 } 129 129 130 130 export function validateLabelValueDefinitionStrings( 131 - v: unknown, 131 + v: unknown, 132 132 ): ValidationResult { 133 - return lexicons.validate( 134 - 'com.atproto.label.defs#labelValueDefinitionStrings', 135 - v, 136 - ) 133 + return lexicons.validate( 134 + "com.atproto.label.defs#labelValueDefinitionStrings", 135 + v, 136 + ); 137 137 } 138 138 139 139 export type LabelValue = 140 - | '!hide' 141 - | '!no-promote' 142 - | '!warn' 143 - | '!no-unauthenticated' 144 - | 'dmca-violation' 145 - | 'doxxing' 146 - | 'porn' 147 - | 'sexual' 148 - | 'nudity' 149 - | 'nsfl' 150 - | 'gore' 151 - | (string & {}) 140 + | "!hide" 141 + | "!no-promote" 142 + | "!warn" 143 + | "!no-unauthenticated" 144 + | "dmca-violation" 145 + | "doxxing" 146 + | "porn" 147 + | "sexual" 148 + | "nudity" 149 + | "nsfl" 150 + | "gore" 151 + | (string & {});
+35 -35
src/lexicons/types/com/atproto/repo/getRecord.ts
··· 1 1 /** 2 2 * GENERATED CODE - DO NOT MODIFY 3 3 */ 4 - import express from 'express' 5 - import { ValidationResult, BlobRef } from '@atproto/lexicon' 6 - import { lexicons } from '../../../../lexicons' 7 - import { isObj, hasProp } from '../../../../util' 8 - import { CID } from 'multiformats/cid' 9 - import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server' 4 + import express from "express"; 5 + import { ValidationResult, BlobRef } from "@atproto/lexicon"; 6 + import { lexicons } from "../../../../lexicons"; 7 + import { isObj, hasProp } from "../../../../util"; 8 + import { CID } from "multiformats/cid"; 9 + import { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 11 11 export interface QueryParams { 12 - /** The handle or DID of the repo. */ 13 - repo: string 14 - /** The NSID of the record collection. */ 15 - collection: string 16 - /** The Record Key. */ 17 - rkey: string 18 - /** The CID of the version of the record. If not specified, then return the most recent version. */ 19 - cid?: string 12 + /** The handle or DID of the repo. */ 13 + repo: string; 14 + /** The NSID of the record collection. */ 15 + collection: string; 16 + /** The Record Key. */ 17 + rkey: string; 18 + /** The CID of the version of the record. If not specified, then return the most recent version. */ 19 + cid?: string; 20 20 } 21 21 22 - export type InputSchema = undefined 22 + export type InputSchema = undefined; 23 23 24 24 export interface OutputSchema { 25 - uri: string 26 - cid?: string 27 - value: {} 28 - [k: string]: unknown 25 + uri: string; 26 + cid?: string; 27 + value: {}; 28 + [k: string]: unknown; 29 29 } 30 30 31 - export type HandlerInput = undefined 31 + export type HandlerInput = undefined; 32 32 33 33 export interface HandlerSuccess { 34 - encoding: 'application/json' 35 - body: OutputSchema 36 - headers?: { [key: string]: string } 34 + encoding: "application/json"; 35 + body: OutputSchema; 36 + headers?: { [key: string]: string }; 37 37 } 38 38 39 39 export interface HandlerError { 40 - status: number 41 - message?: string 42 - error?: 'RecordNotFound' 40 + status: number; 41 + message?: string; 42 + error?: "RecordNotFound"; 43 43 } 44 44 45 - export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough 45 + export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough; 46 46 export type HandlerReqCtx<HA extends HandlerAuth = never> = { 47 - auth: HA 48 - params: QueryParams 49 - input: HandlerInput 50 - req: express.Request 51 - res: express.Response 52 - } 47 + auth: HA; 48 + params: QueryParams; 49 + input: HandlerInput; 50 + req: express.Request; 51 + res: express.Response; 52 + }; 53 53 export type Handler<HA extends HandlerAuth = never> = ( 54 - ctx: HandlerReqCtx<HA>, 55 - ) => Promise<HandlerOutput> | HandlerOutput 54 + ctx: HandlerReqCtx<HA>, 55 + ) => Promise<HandlerOutput> | HandlerOutput;
+48 -48
src/lexicons/types/com/atproto/repo/listRecords.ts
··· 1 1 /** 2 2 * GENERATED CODE - DO NOT MODIFY 3 3 */ 4 - import express from 'express' 5 - import { ValidationResult, BlobRef } from '@atproto/lexicon' 6 - import { lexicons } from '../../../../lexicons' 7 - import { isObj, hasProp } from '../../../../util' 8 - import { CID } from 'multiformats/cid' 9 - import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server' 4 + import express from "express"; 5 + import { ValidationResult, BlobRef } from "@atproto/lexicon"; 6 + import { lexicons } from "../../../../lexicons"; 7 + import { isObj, hasProp } from "../../../../util"; 8 + import { CID } from "multiformats/cid"; 9 + import { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 11 11 export interface QueryParams { 12 - /** The handle or DID of the repo. */ 13 - repo: string 14 - /** The NSID of the record type. */ 15 - collection: string 16 - /** The number of records to return. */ 17 - limit: number 18 - cursor?: string 19 - /** DEPRECATED: The lowest sort-ordered rkey to start from (exclusive) */ 20 - rkeyStart?: string 21 - /** DEPRECATED: The highest sort-ordered rkey to stop at (exclusive) */ 22 - rkeyEnd?: string 23 - /** Flag to reverse the order of the returned records. */ 24 - reverse?: boolean 12 + /** The handle or DID of the repo. */ 13 + repo: string; 14 + /** The NSID of the record type. */ 15 + collection: string; 16 + /** The number of records to return. */ 17 + limit: number; 18 + cursor?: string; 19 + /** DEPRECATED: The lowest sort-ordered rkey to start from (exclusive) */ 20 + rkeyStart?: string; 21 + /** DEPRECATED: The highest sort-ordered rkey to stop at (exclusive) */ 22 + rkeyEnd?: string; 23 + /** Flag to reverse the order of the returned records. */ 24 + reverse?: boolean; 25 25 } 26 26 27 - export type InputSchema = undefined 27 + export type InputSchema = undefined; 28 28 29 29 export interface OutputSchema { 30 - cursor?: string 31 - records: Record[] 32 - [k: string]: unknown 30 + cursor?: string; 31 + records: Record[]; 32 + [k: string]: unknown; 33 33 } 34 34 35 - export type HandlerInput = undefined 35 + export type HandlerInput = undefined; 36 36 37 37 export interface HandlerSuccess { 38 - encoding: 'application/json' 39 - body: OutputSchema 40 - headers?: { [key: string]: string } 38 + encoding: "application/json"; 39 + body: OutputSchema; 40 + headers?: { [key: string]: string }; 41 41 } 42 42 43 43 export interface HandlerError { 44 - status: number 45 - message?: string 44 + status: number; 45 + message?: string; 46 46 } 47 47 48 - export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough 48 + export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough; 49 49 export type HandlerReqCtx<HA extends HandlerAuth = never> = { 50 - auth: HA 51 - params: QueryParams 52 - input: HandlerInput 53 - req: express.Request 54 - res: express.Response 55 - } 50 + auth: HA; 51 + params: QueryParams; 52 + input: HandlerInput; 53 + req: express.Request; 54 + res: express.Response; 55 + }; 56 56 export type Handler<HA extends HandlerAuth = never> = ( 57 - ctx: HandlerReqCtx<HA>, 58 - ) => Promise<HandlerOutput> | HandlerOutput 57 + ctx: HandlerReqCtx<HA>, 58 + ) => Promise<HandlerOutput> | HandlerOutput; 59 59 60 60 export interface Record { 61 - uri: string 62 - cid: string 63 - value: {} 64 - [k: string]: unknown 61 + uri: string; 62 + cid: string; 63 + value: {}; 64 + [k: string]: unknown; 65 65 } 66 66 67 67 export function isRecord(v: unknown): v is Record { 68 - return ( 69 - isObj(v) && 70 - hasProp(v, '$type') && 71 - v.$type === 'com.atproto.repo.listRecords#record' 72 - ) 68 + return ( 69 + isObj(v) && 70 + hasProp(v, "$type") && 71 + v.$type === "com.atproto.repo.listRecords#record" 72 + ); 73 73 } 74 74 75 75 export function validateRecord(v: unknown): ValidationResult { 76 - return lexicons.validate('com.atproto.repo.listRecords#record', v) 76 + return lexicons.validate("com.atproto.repo.listRecords#record", v); 77 77 }
+14 -14
src/lexicons/types/com/atproto/repo/strongRef.ts
··· 1 1 /** 2 2 * GENERATED CODE - DO NOT MODIFY 3 3 */ 4 - import { ValidationResult, BlobRef } from '@atproto/lexicon' 5 - import { lexicons } from '../../../../lexicons' 6 - import { isObj, hasProp } from '../../../../util' 7 - import { CID } from 'multiformats/cid' 4 + import { ValidationResult, BlobRef } from "@atproto/lexicon"; 5 + import { lexicons } from "../../../../lexicons"; 6 + import { isObj, hasProp } from "../../../../util"; 7 + import { CID } from "multiformats/cid"; 8 8 9 9 export interface Main { 10 - uri: string 11 - cid: string 12 - [k: string]: unknown 10 + uri: string; 11 + cid: string; 12 + [k: string]: unknown; 13 13 } 14 14 15 15 export function isMain(v: unknown): v is Main { 16 - return ( 17 - isObj(v) && 18 - hasProp(v, '$type') && 19 - (v.$type === 'com.atproto.repo.strongRef#main' || 20 - v.$type === 'com.atproto.repo.strongRef') 21 - ) 16 + return ( 17 + isObj(v) && 18 + hasProp(v, "$type") && 19 + (v.$type === "com.atproto.repo.strongRef#main" || 20 + v.$type === "com.atproto.repo.strongRef") 21 + ); 22 22 } 23 23 24 24 export function validateMain(v: unknown): ValidationResult { 25 - return lexicons.validate('com.atproto.repo.strongRef#main', v) 25 + return lexicons.validate("com.atproto.repo.strongRef#main", v); 26 26 }
+17 -17
src/lexicons/types/li/plonk/comment.ts
··· 1 1 /** 2 2 * GENERATED CODE - DO NOT MODIFY 3 3 */ 4 - import { ValidationResult, BlobRef } from '@atproto/lexicon' 5 - import { lexicons } from '../../../lexicons' 6 - import { isObj, hasProp } from '../../../util' 7 - import { CID } from 'multiformats/cid' 8 - import * as ComAtprotoRepoStrongRef from '../../com/atproto/repo/strongRef' 4 + import { ValidationResult, BlobRef } from "@atproto/lexicon"; 5 + import { lexicons } from "../../../lexicons"; 6 + import { isObj, hasProp } from "../../../util"; 7 + import { CID } from "multiformats/cid"; 8 + import * as ComAtprotoRepoStrongRef from "../../com/atproto/repo/strongRef"; 9 9 10 10 export interface Record { 11 - /** comment body */ 12 - content: string 13 - /** comment creation timestamp */ 14 - createdAt: string 15 - post: ComAtprotoRepoStrongRef.Main 16 - [k: string]: unknown 11 + /** comment body */ 12 + content: string; 13 + /** comment creation timestamp */ 14 + createdAt: string; 15 + post: ComAtprotoRepoStrongRef.Main; 16 + [k: string]: unknown; 17 17 } 18 18 19 19 export function isRecord(v: unknown): v is Record { 20 - return ( 21 - isObj(v) && 22 - hasProp(v, '$type') && 23 - (v.$type === 'li.plonk.comment#main' || v.$type === 'li.plonk.comment') 24 - ) 20 + return ( 21 + isObj(v) && 22 + hasProp(v, "$type") && 23 + (v.$type === "li.plonk.comment#main" || v.$type === "li.plonk.comment") 24 + ); 25 25 } 26 26 27 27 export function validateRecord(v: unknown): ValidationResult { 28 - return lexicons.validate('li.plonk.comment#main', v) 28 + return lexicons.validate("li.plonk.comment#main", v); 29 29 }
+16 -16
src/lexicons/types/li/plonk/paste.ts
··· 1 1 /** 2 2 * GENERATED CODE - DO NOT MODIFY 3 3 */ 4 - import { ValidationResult, BlobRef } from '@atproto/lexicon' 5 - import { lexicons } from '../../../lexicons' 6 - import { isObj, hasProp } from '../../../util' 7 - import { CID } from 'multiformats/cid' 4 + import { ValidationResult, BlobRef } from "@atproto/lexicon"; 5 + import { lexicons } from "../../../lexicons"; 6 + import { isObj, hasProp } from "../../../util"; 7 + import { CID } from "multiformats/cid"; 8 8 9 9 export interface Record { 10 - code: string 11 - shortUrl: string 12 - lang: string 13 - title: string 14 - createdAt: string 15 - [k: string]: unknown 10 + code: string; 11 + shortUrl: string; 12 + lang: string; 13 + title: string; 14 + createdAt: string; 15 + [k: string]: unknown; 16 16 } 17 17 18 18 export function isRecord(v: unknown): v is Record { 19 - return ( 20 - isObj(v) && 21 - hasProp(v, '$type') && 22 - (v.$type === 'li.plonk.paste#main' || v.$type === 'li.plonk.paste') 23 - ) 19 + return ( 20 + isObj(v) && 21 + hasProp(v, "$type") && 22 + (v.$type === "li.plonk.paste#main" || v.$type === "li.plonk.paste") 23 + ); 24 24 } 25 25 26 26 export function validateRecord(v: unknown): ValidationResult { 27 - return lexicons.validate('li.plonk.paste#main', v) 27 + return lexicons.validate("li.plonk.paste#main", v); 28 28 }
+4 -4
src/lexicons/util.ts
··· 2 2 * GENERATED CODE - DO NOT MODIFY 3 3 */ 4 4 export function isObj(v: unknown): v is Record<string, unknown> { 5 - return typeof v === 'object' && v !== null 5 + return typeof v === "object" && v !== null; 6 6 } 7 7 8 8 export function hasProp<K extends PropertyKey>( 9 - data: object, 10 - prop: K, 9 + data: object, 10 + prop: K, 11 11 ): data is Record<K, unknown> { 12 - return prop in data 12 + return prop in data; 13 13 }
+17
src/mixins/header.pug
··· 1 + mixin header(ownDid, didHandleMap) 2 + div.header 3 + div.left-side 4 + if ownDid 5 + | logged in as @#{didHandleMap[ownDid]} 6 + div.right-side 7 + p 8 + a(href="/") home 9 + | &nbsp;·&nbsp; 10 + if ownDid 11 + a(href=`/u/${encodeURIComponent(ownDid)}`) my plonks 12 + | &nbsp;·&nbsp; 13 + a(href="/logout") logout 14 + else 15 + a(href="/login") login 16 + |&nbsp;to get plonkin' 17 +
+53 -23
src/routes.ts
··· 61 61 cookieName: "plonk-id", 62 62 password: env.COOKIE_SECRET, 63 63 }); 64 - ctx.logger.info(clientSession.did, "client session did"); 65 64 //assert(!clientSession.did, "session already exists"); 66 65 clientSession.did = session.did; 67 66 await clientSession.save(); ··· 117 116 118 117 // Map user DIDs to their domain-name handles 119 118 const didHandleMap = await ctx.resolver.resolveDidsToHandles( 120 - pastes.map((s) => s.authorDid).concat(agent? [agent.assertDid]:[]), 119 + pastes.map((s) => s.authorDid).concat(agent ? [agent.assertDid] : []), 121 120 ); 122 121 123 122 if (!agent) { ··· 145 144 const agent = new Agent(pds); 146 145 const response = await agent.com.atproto.repo.listRecords({ 147 146 repo: authorDid, 148 - collection: 'li.plonk.paste', 147 + collection: "li.plonk.paste", 149 148 limit: 99, 150 149 }); 151 150 const pastes = response.data.records; 152 151 let didHandleMap = {}; 153 152 didHandleMap[authorDid] = await ctx.resolver.resolveDidToHandle(authorDid); 154 - return res.render("user", { pastes, authorDid, didHandleMap }); 153 + const ownAgent = await getSessionAgent(req, res, ctx); 154 + if (!ownAgent) { 155 + return res.render("user", { pastes, authorDid, didHandleMap }); 156 + } else { 157 + const ownDid = ownAgent.assertDid; 158 + didHandleMap[ownDid] = await ctx.resolver.resolveDidToHandle(ownDid); 159 + return res.render("user", { pastes, authorDid, ownDid, didHandleMap }); 160 + } 155 161 }); 156 162 157 163 router.get("/p/:shortUrl", async (req, res) => { ··· 167 173 var comments = await ctx.db 168 174 .selectFrom("comment") 169 175 .selectAll() 170 - .where("pasteUri", '=', ret.uri) 176 + .where("pasteUri", "=", ret.uri) 171 177 .execute(); 172 178 const { authorDid: did, uri } = ret; 173 - const didHandleMap = await ctx.resolver.resolveDidsToHandles( 179 + let didHandleMap = await ctx.resolver.resolveDidsToHandles( 174 180 comments.map((c) => c.authorDid).concat([did]), 175 - ) 181 + ); 176 182 const resolver = new DidResolver({}); 177 183 const didDocument = await resolver.resolve(did); 178 184 if (!didDocument) { ··· 187 193 const response = await agent.com.atproto.repo.getRecord({ 188 194 repo: aturi.hostname, 189 195 collection: aturi.collection, 190 - rkey: aturi.rkey 196 + rkey: aturi.rkey, 191 197 }); 192 198 193 199 const paste = ··· 196 202 ? response.data.value 197 203 : {}; 198 204 199 - return res.render("paste", { paste, authorDid: did, uri: response.data.uri, didHandleMap, shortUrl, comments }); 205 + const ownAgent = await getSessionAgent(req, res, ctx); 206 + if (!ownAgent) { 207 + return res.render("paste", { 208 + paste, 209 + authorDid: did, 210 + uri: response.data.uri, 211 + didHandleMap, 212 + shortUrl, 213 + comments, 214 + }); 215 + } else { 216 + const ownDid = ownAgent.assertDid; 217 + didHandleMap[ownDid] = await ctx.resolver.resolveDidToHandle(ownDid); 218 + return res.render("paste", { 219 + paste, 220 + authorDid: did, 221 + uri: response.data.uri, 222 + ownDid, 223 + didHandleMap, 224 + shortUrl, 225 + comments, 226 + }); 227 + } 200 228 }); 201 229 202 230 router.get("/p/:shortUrl/raw", async (req, res) => { 203 - res.redirect(`/r/${req.params.shortUrl}`) 231 + res.redirect(`/r/${req.params.shortUrl}`); 204 232 }); 205 233 router.get("/r/:shortUrl", async (req, res) => { 206 234 const { shortUrl } = req.params; ··· 220 248 router.get("/reset", async (req, res) => { 221 249 const agent = await getSessionAgent(req, res, ctx); 222 250 if (!agent) { 223 - return res.redirect('/'); 251 + return res.redirect("/"); 224 252 } 225 253 const response = await agent.com.atproto.repo.listRecords({ 226 254 repo: agent.assertDid, 227 - collection: 'li.plonk.paste', 255 + collection: "li.plonk.paste", 228 256 limit: 10, 229 257 }); 230 258 const vals = response.data.records; ··· 236 264 rkey: aturl.rkey, 237 265 }); 238 266 } 239 - return res.redirect('/'); 267 + return res.redirect("/"); 240 268 }); 241 269 242 270 router.post("/paste", async (req, res) => { ··· 319 347 .type("html") 320 348 .send("<h1>Error: Session required</h1>"); 321 349 } 322 - 350 + 323 351 const pasteUri = req.params.paste; 324 352 const aturi = new AtUri(pasteUri); 325 353 const pasteResponse = await agent.com.atproto.repo.getRecord({ 326 354 repo: aturi.hostname, 327 355 collection: aturi.collection, 328 - rkey: aturi.rkey 356 + rkey: aturi.rkey, 329 357 }); 330 358 const pasteCid = pasteResponse.data.cid; 331 359 if (!pasteCid) { 332 - return res 333 - .status(401) 334 - .type("html") 335 - .send("invalid paste"); 360 + return res.status(401).type("html").send("invalid paste"); 336 361 } 337 362 338 363 const rkey = TID.nextStr(); ··· 341 366 content: req.body?.comment, 342 367 post: { 343 368 uri: pasteUri, 344 - cid: pasteCid 369 + cid: pasteCid, 345 370 }, 346 371 createdAt: new Date().toISOString(), 347 372 }; ··· 384 409 indexedAt: new Date().toISOString(), 385 410 }) 386 411 .execute(); 387 - ctx.logger.info(res, "wrote back to db"); 388 - const originalPaste = await ctx.db.selectFrom('paste').selectAll().where('uri', '=', pasteUri).executeTakeFirst(); 389 - return res.redirect(`/p/${originalPaste.shortUrl}#${encodeURIComponent(uri)}`); 412 + const originalPaste = await ctx.db 413 + .selectFrom("paste") 414 + .selectAll() 415 + .where("uri", "=", pasteUri) 416 + .executeTakeFirst(); 417 + return res.redirect( 418 + `/p/${originalPaste.shortUrl}#${encodeURIComponent(uri)}`, 419 + ); 390 420 } catch (err) { 391 421 ctx.logger.warn( 392 422 { err },
+2 -14
src/views/index.pug
··· 1 1 include ../mixins/mkPost 2 2 include ../mixins/head 3 + include ../mixins/header 3 4 include ../mixins/utils 4 5 include ../mixins/post 5 6 ··· 24 25 +head("timeline") 25 26 body 26 27 main#content 27 - div.header 28 - div.left-side 29 - if ownDid 30 - | logged in as @#{didHandleMap[ownDid]} 31 - div.right-side 32 - if ownDid 33 - p 34 - a(href=`/u/${encodeURIComponent(ownDid)}`) my plonks 35 - | &nbsp;·&nbsp; 36 - a(href="/logout") logout 37 - else 38 - p 39 - a(href="/login") login 40 - |&nbsp;to get plonkin' 28 + +header(ownDid, didHandleMap) 41 29 42 30 if ownDid 43 31 +mkPost()
+2
src/views/paste.pug
··· 1 1 - var now = new Date() 2 2 include ../mixins/head 3 + include ../mixins/header 3 4 include ../mixins/utils 4 5 doctype html 5 6 html 6 7 +head(paste.title) 7 8 body 8 9 main#content 10 + +header(ownDid, didHandleMap) 9 11 h1 #{paste.title} 10 12 p 11 13 | by @#{didHandleMap[authorDid]} ·
+2
src/views/user.pug
··· 1 1 - var now = new Date() 2 2 - var handle = didHandleMap[authorDid] 3 3 include ../mixins/head 4 + include ../mixins/header 4 5 include ../mixins/utils 5 6 include ../mixins/post 6 7 doctype html ··· 8 9 +head(handle) 9 10 body 10 11 main#content 12 + +header(ownDid, didHandleMap) 11 13 h1 plonks by @#{handle} 12 14 div.timeline 13 15 each paste in pastes