···11+/**
22+ * GENERATED CODE - DO NOT MODIFY
33+ */
44+import {
55+ createServer as createXrpcServer,
66+ Server as XrpcServer,
77+ Options as XrpcOptions,
88+ AuthVerifier,
99+ StreamAuthVerifier,
1010+} from '@atproto/xrpc-server'
1111+import { schemas } from './lexicons'
1212+1313+export function createServer(options?: XrpcOptions): Server {
1414+ return new Server(options)
1515+}
1616+1717+export class Server {
1818+ xrpc: XrpcServer
1919+ app: AppNS
2020+ fm: FmNS
2121+ xyz: XyzNS
2222+2323+ constructor(options?: XrpcOptions) {
2424+ this.xrpc = createXrpcServer(schemas, options)
2525+ this.app = new AppNS(this)
2626+ this.fm = new FmNS(this)
2727+ this.xyz = new XyzNS(this)
2828+ }
2929+}
3030+3131+export class AppNS {
3232+ _server: Server
3333+ bsky: AppBskyNS
3434+3535+ constructor(server: Server) {
3636+ this._server = server
3737+ this.bsky = new AppBskyNS(server)
3838+ }
3939+}
4040+4141+export class AppBskyNS {
4242+ _server: Server
4343+ actor: AppBskyActorNS
4444+ richtext: AppBskyRichtextNS
4545+4646+ constructor(server: Server) {
4747+ this._server = server
4848+ this.actor = new AppBskyActorNS(server)
4949+ this.richtext = new AppBskyRichtextNS(server)
5050+ }
5151+}
5252+5353+export class AppBskyActorNS {
5454+ _server: Server
5555+5656+ constructor(server: Server) {
5757+ this._server = server
5858+ }
5959+}
6060+6161+export class AppBskyRichtextNS {
6262+ _server: Server
6363+6464+ constructor(server: Server) {
6565+ this._server = server
6666+ }
6767+}
6868+6969+export class FmNS {
7070+ _server: Server
7171+ teal: FmTealNS
7272+7373+ constructor(server: Server) {
7474+ this._server = server
7575+ this.teal = new FmTealNS(server)
7676+ }
7777+}
7878+7979+export class FmTealNS {
8080+ _server: Server
8181+ alpha: FmTealAlphaNS
8282+8383+ constructor(server: Server) {
8484+ this._server = server
8585+ this.alpha = new FmTealAlphaNS(server)
8686+ }
8787+}
8888+8989+export class FmTealAlphaNS {
9090+ _server: Server
9191+ actor: FmTealAlphaActorNS
9292+9393+ constructor(server: Server) {
9494+ this._server = server
9595+ this.actor = new FmTealAlphaActorNS(server)
9696+ }
9797+}
9898+9999+export class FmTealAlphaActorNS {
100100+ _server: Server
101101+102102+ constructor(server: Server) {
103103+ this._server = server
104104+ }
105105+}
106106+107107+export class XyzNS {
108108+ _server: Server
109109+ statusphere: XyzStatusphereNS
110110+111111+ constructor(server: Server) {
112112+ this._server = server
113113+ this.statusphere = new XyzStatusphereNS(server)
114114+ }
115115+}
116116+117117+export class XyzStatusphereNS {
118118+ _server: Server
119119+120120+ constructor(server: Server) {
121121+ this._server = server
122122+ }
123123+}
124124+125125+type SharedRateLimitOpts<T> = {
126126+ name: string
127127+ calcKey?: (ctx: T) => string
128128+ calcPoints?: (ctx: T) => number
129129+}
130130+type RouteRateLimitOpts<T> = {
131131+ durationMs: number
132132+ points: number
133133+ calcKey?: (ctx: T) => string
134134+ calcPoints?: (ctx: T) => number
135135+}
136136+type HandlerOpts = { blobLimit?: number }
137137+type HandlerRateLimitOpts<T> = SharedRateLimitOpts<T> | RouteRateLimitOpts<T>
138138+type ConfigOf<Auth, Handler, ReqCtx> =
139139+ | Handler
140140+ | {
141141+ auth?: Auth
142142+ opts?: HandlerOpts
143143+ rateLimit?: HandlerRateLimitOpts<ReqCtx> | HandlerRateLimitOpts<ReqCtx>[]
144144+ handler: Handler
145145+ }
146146+type ExtractAuth<AV extends AuthVerifier | StreamAuthVerifier> = Extract<
147147+ Awaited<ReturnType<AV>>,
148148+ { credentials: unknown }
149149+>
+368
lexicons/server/lexicons.ts
···11+/**
22+ * GENERATED CODE - DO NOT MODIFY
33+ */
44+import { LexiconDoc, Lexicons } from '@atproto/lexicon'
55+66+export const schemaDict = {
77+ AppBskyActorProfile: {
88+ lexicon: 1,
99+ id: 'app.bsky.actor.profile',
1010+ defs: {
1111+ main: {
1212+ type: 'record',
1313+ description: 'A declaration of a Bluesky account profile.',
1414+ key: 'literal:self',
1515+ record: {
1616+ type: 'object',
1717+ properties: {
1818+ displayName: {
1919+ type: 'string',
2020+ maxGraphemes: 64,
2121+ maxLength: 640,
2222+ },
2323+ description: {
2424+ type: 'string',
2525+ description: 'Free-form profile description text.',
2626+ maxGraphemes: 256,
2727+ maxLength: 2560,
2828+ },
2929+ avatar: {
3030+ type: 'blob',
3131+ description:
3232+ "Small image to be displayed next to posts from account. AKA, 'profile picture'",
3333+ accept: ['image/png', 'image/jpeg'],
3434+ maxSize: 1000000,
3535+ },
3636+ banner: {
3737+ type: 'blob',
3838+ description:
3939+ 'Larger horizontal image to display behind profile view.',
4040+ accept: ['image/png', 'image/jpeg'],
4141+ maxSize: 1000000,
4242+ },
4343+ labels: {
4444+ type: 'union',
4545+ description:
4646+ 'Self-label values, specific to the Bluesky application, on the overall account.',
4747+ refs: ['lex:com.atproto.label.defs#selfLabels'],
4848+ },
4949+ joinedViaStarterPack: {
5050+ type: 'ref',
5151+ ref: 'lex:com.atproto.repo.strongRef',
5252+ },
5353+ createdAt: {
5454+ type: 'string',
5555+ format: 'datetime',
5656+ },
5757+ },
5858+ },
5959+ },
6060+ },
6161+ },
6262+ AppBskyRichtextFacet: {
6363+ lexicon: 1,
6464+ id: 'app.bsky.richtext.facet',
6565+ defs: {
6666+ main: {
6767+ type: 'object',
6868+ description: 'Annotation of a sub-string within rich text.',
6969+ required: ['index', 'features'],
7070+ properties: {
7171+ index: {
7272+ type: 'ref',
7373+ ref: 'lex:app.bsky.richtext.facet#byteSlice',
7474+ },
7575+ features: {
7676+ type: 'array',
7777+ items: {
7878+ type: 'union',
7979+ refs: [
8080+ 'lex:app.bsky.richtext.facet#mention',
8181+ 'lex:app.bsky.richtext.facet#link',
8282+ 'lex:app.bsky.richtext.facet#tag',
8383+ ],
8484+ },
8585+ },
8686+ },
8787+ },
8888+ mention: {
8989+ type: 'object',
9090+ description:
9191+ "Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID.",
9292+ required: ['did'],
9393+ properties: {
9494+ did: {
9595+ type: 'string',
9696+ format: 'did',
9797+ },
9898+ },
9999+ },
100100+ link: {
101101+ type: 'object',
102102+ description:
103103+ 'Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.',
104104+ required: ['uri'],
105105+ properties: {
106106+ uri: {
107107+ type: 'string',
108108+ format: 'uri',
109109+ },
110110+ },
111111+ },
112112+ tag: {
113113+ type: 'object',
114114+ description:
115115+ "Facet feature for a hashtag. The text usually includes a '#' prefix, but the facet reference should not (except in the case of 'double hash tags').",
116116+ required: ['tag'],
117117+ properties: {
118118+ tag: {
119119+ type: 'string',
120120+ maxLength: 640,
121121+ maxGraphemes: 64,
122122+ },
123123+ },
124124+ },
125125+ byteSlice: {
126126+ type: 'object',
127127+ description:
128128+ 'Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets.',
129129+ required: ['byteStart', 'byteEnd'],
130130+ properties: {
131131+ byteStart: {
132132+ type: 'integer',
133133+ minimum: 0,
134134+ },
135135+ byteEnd: {
136136+ type: 'integer',
137137+ minimum: 0,
138138+ },
139139+ },
140140+ },
141141+ },
142142+ },
143143+ FmTealAlphaActorProfile: {
144144+ lexicon: 1,
145145+ id: 'fm.teal.alpha.actor.profile',
146146+ defs: {
147147+ main: {
148148+ type: 'record',
149149+ description:
150150+ 'This lexicon is in a not officially released state. It is subject to change. | A declaration of a teal.fm account profile.',
151151+ key: 'literal:self',
152152+ record: {
153153+ type: 'object',
154154+ properties: {
155155+ displayName: {
156156+ type: 'string',
157157+ maxGraphemes: 64,
158158+ maxLength: 640,
159159+ },
160160+ description: {
161161+ type: 'string',
162162+ description: 'Free-form profile description text.',
163163+ maxGraphemes: 256,
164164+ maxLength: 2560,
165165+ },
166166+ descriptionFacets: {
167167+ type: 'array',
168168+ description:
169169+ 'Annotations of text in the profile description (mentions, URLs, hashtags, etc).',
170170+ items: {
171171+ type: 'ref',
172172+ ref: 'lex:app.bsky.richtext.facet',
173173+ },
174174+ },
175175+ featuredItem: {
176176+ type: 'ref',
177177+ description:
178178+ "The user's most recent item featured on their profile.",
179179+ ref: 'lex:fm.teal.alpha.actor.profile#featuredItem',
180180+ },
181181+ avatar: {
182182+ type: 'blob',
183183+ description:
184184+ "Small image to be displayed next to posts from account. AKA, 'profile picture'",
185185+ accept: ['image/png', 'image/jpeg'],
186186+ maxSize: 1000000,
187187+ },
188188+ banner: {
189189+ type: 'blob',
190190+ description:
191191+ 'Larger horizontal image to display behind profile view.',
192192+ accept: ['image/png', 'image/jpeg'],
193193+ maxSize: 1000000,
194194+ },
195195+ createdAt: {
196196+ type: 'string',
197197+ format: 'datetime',
198198+ },
199199+ },
200200+ },
201201+ },
202202+ featuredItem: {
203203+ type: 'object',
204204+ required: ['mbid', 'type'],
205205+ properties: {
206206+ mbid: {
207207+ type: 'string',
208208+ description: 'The Musicbrainz ID of the item',
209209+ },
210210+ type: {
211211+ type: 'string',
212212+ description:
213213+ 'The type of the item. Must be a valid Musicbrainz type, e.g. album, track, recording, etc.',
214214+ },
215215+ },
216216+ },
217217+ },
218218+ },
219219+ FmTealAlphaActorStatus: {
220220+ lexicon: 1,
221221+ id: 'fm.teal.alpha.actor.status',
222222+ defs: {
223223+ main: {
224224+ type: 'record',
225225+ description:
226226+ 'This lexicon is in a not officially released state. It is subject to change. | A declaration of the status of the actor. Only one can be shown at a time. If there are multiple, the latest record should be picked and earlier records should be deleted or tombstoned.',
227227+ key: 'literal:self',
228228+ record: {
229229+ type: 'object',
230230+ required: ['time', 'item'],
231231+ properties: {
232232+ time: {
233233+ type: 'string',
234234+ format: 'datetime',
235235+ description: 'The unix timestamp of when the item was recorded',
236236+ },
237237+ item: {
238238+ type: 'union',
239239+ refs: ['lex:fm.teal.alpha.play#record'],
240240+ },
241241+ },
242242+ },
243243+ },
244244+ },
245245+ },
246246+ FmTealAlphaPlay: {
247247+ lexicon: 1,
248248+ id: 'fm.teal.alpha.play',
249249+ description:
250250+ "This lexicon is in a not officially released state. It is subject to change. | A declaration of a teal.fm play. Plays are submitted as a result of a user listening to a track. Plays should be marked as tracked when a user has listened to the entire track if it's under 2 minutes long, or half of the track's duration up to 4 minutes, whichever is longest.",
251251+ defs: {
252252+ main: {
253253+ type: 'record',
254254+ key: 'tid',
255255+ record: {
256256+ type: 'object',
257257+ required: ['trackName', 'artistName'],
258258+ properties: {
259259+ trackName: {
260260+ type: 'string',
261261+ minLength: 1,
262262+ maxLength: 256,
263263+ maxGraphemes: 2560,
264264+ description: 'The name of the track',
265265+ },
266266+ trackMbId: {
267267+ type: 'string',
268268+ description: 'The Musicbrainz ID of the track',
269269+ },
270270+ recordingMbId: {
271271+ type: 'string',
272272+ description: 'The Musicbrainz recording ID of the track',
273273+ },
274274+ duration: {
275275+ type: 'integer',
276276+ description: 'The length of the track in seconds',
277277+ },
278278+ artistName: {
279279+ type: 'string',
280280+ minLength: 1,
281281+ maxLength: 256,
282282+ maxGraphemes: 2560,
283283+ description: 'The name of the artist',
284284+ },
285285+ artistMbIds: {
286286+ type: 'array',
287287+ items: {
288288+ type: 'string',
289289+ },
290290+ description: 'Array of Musicbrainz artist IDs',
291291+ },
292292+ releaseName: {
293293+ type: 'string',
294294+ maxLength: 256,
295295+ maxGraphemes: 2560,
296296+ description: 'The name of the release/album',
297297+ },
298298+ releaseMbId: {
299299+ type: 'string',
300300+ description: 'The Musicbrainz release ID',
301301+ },
302302+ isrc: {
303303+ type: 'string',
304304+ description: 'The ISRC code associated with the recording',
305305+ },
306306+ originUrl: {
307307+ type: 'string',
308308+ description: 'The URL associated with this track',
309309+ },
310310+ musicServiceBaseDomain: {
311311+ type: 'string',
312312+ description:
313313+ 'The base domain of the music service. e.g. music.apple.com, tidal.com, spotify.com.',
314314+ },
315315+ submissionClientAgent: {
316316+ type: 'string',
317317+ maxLength: 256,
318318+ maxGraphemes: 2560,
319319+ description:
320320+ 'A user-agent style string specifying the user agent. e.g. tealtracker/0.0.1b',
321321+ },
322322+ playedTime: {
323323+ type: 'string',
324324+ format: 'datetime',
325325+ description: 'The unix timestamp of when the track was played',
326326+ },
327327+ },
328328+ },
329329+ },
330330+ },
331331+ },
332332+ XyzStatusphereStatus: {
333333+ lexicon: 1,
334334+ id: 'xyz.statusphere.status',
335335+ defs: {
336336+ main: {
337337+ type: 'record',
338338+ key: 'tid',
339339+ record: {
340340+ type: 'object',
341341+ required: ['status', 'createdAt'],
342342+ properties: {
343343+ status: {
344344+ type: 'string',
345345+ minLength: 1,
346346+ maxGraphemes: 1,
347347+ maxLength: 32,
348348+ },
349349+ createdAt: {
350350+ type: 'string',
351351+ format: 'datetime',
352352+ },
353353+ },
354354+ },
355355+ },
356356+ },
357357+ },
358358+}
359359+export const schemas: LexiconDoc[] = Object.values(schemaDict) as LexiconDoc[]
360360+export const lexicons: Lexicons = new Lexicons(schemas)
361361+export const ids = {
362362+ AppBskyActorProfile: 'app.bsky.actor.profile',
363363+ AppBskyRichtextFacet: 'app.bsky.richtext.facet',
364364+ FmTealAlphaActorProfile: 'fm.teal.alpha.actor.profile',
365365+ FmTealAlphaActorStatus: 'fm.teal.alpha.actor.status',
366366+ FmTealAlphaPlay: 'fm.teal.alpha.play',
367367+ XyzStatusphereStatus: 'xyz.statusphere.status',
368368+}
+38
lexicons/server/types/app/bsky/actor/profile.ts
···11+/**
22+ * GENERATED CODE - DO NOT MODIFY
33+ */
44+import { ValidationResult, BlobRef } from '@atproto/lexicon'
55+import { lexicons } from '../../../../lexicons'
66+import { isObj, hasProp } from '../../../../util'
77+import { CID } from 'multiformats/cid'
88+import * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs'
99+import * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef'
1010+1111+export interface Record {
1212+ displayName?: string
1313+ /** Free-form profile description text. */
1414+ description?: string
1515+ /** Small image to be displayed next to posts from account. AKA, 'profile picture' */
1616+ avatar?: BlobRef
1717+ /** Larger horizontal image to display behind profile view. */
1818+ banner?: BlobRef
1919+ labels?:
2020+ | ComAtprotoLabelDefs.SelfLabels
2121+ | { $type: string; [k: string]: unknown }
2222+ joinedViaStarterPack?: ComAtprotoRepoStrongRef.Main
2323+ createdAt?: string
2424+ [k: string]: unknown
2525+}
2626+2727+export function isRecord(v: unknown): v is Record {
2828+ return (
2929+ isObj(v) &&
3030+ hasProp(v, '$type') &&
3131+ (v.$type === 'app.bsky.actor.profile#main' ||
3232+ v.$type === 'app.bsky.actor.profile')
3333+ )
3434+}
3535+3636+export function validateRecord(v: unknown): ValidationResult {
3737+ return lexicons.validate('app.bsky.actor.profile#main', v)
3838+}
+98
lexicons/server/types/app/bsky/richtext/facet.ts
···11+/**
22+ * GENERATED CODE - DO NOT MODIFY
33+ */
44+import { ValidationResult, BlobRef } from '@atproto/lexicon'
55+import { lexicons } from '../../../../lexicons'
66+import { isObj, hasProp } from '../../../../util'
77+import { CID } from 'multiformats/cid'
88+99+/** Annotation of a sub-string within rich text. */
1010+export interface Main {
1111+ index: ByteSlice
1212+ features: (Mention | Link | Tag | { $type: string; [k: string]: unknown })[]
1313+ [k: string]: unknown
1414+}
1515+1616+export function isMain(v: unknown): v is Main {
1717+ return (
1818+ isObj(v) &&
1919+ hasProp(v, '$type') &&
2020+ (v.$type === 'app.bsky.richtext.facet#main' ||
2121+ v.$type === 'app.bsky.richtext.facet')
2222+ )
2323+}
2424+2525+export function validateMain(v: unknown): ValidationResult {
2626+ return lexicons.validate('app.bsky.richtext.facet#main', v)
2727+}
2828+2929+/** Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID. */
3030+export interface Mention {
3131+ did: string
3232+ [k: string]: unknown
3333+}
3434+3535+export function isMention(v: unknown): v is Mention {
3636+ return (
3737+ isObj(v) &&
3838+ hasProp(v, '$type') &&
3939+ v.$type === 'app.bsky.richtext.facet#mention'
4040+ )
4141+}
4242+4343+export function validateMention(v: unknown): ValidationResult {
4444+ return lexicons.validate('app.bsky.richtext.facet#mention', v)
4545+}
4646+4747+/** Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL. */
4848+export interface Link {
4949+ uri: string
5050+ [k: string]: unknown
5151+}
5252+5353+export function isLink(v: unknown): v is Link {
5454+ return (
5555+ isObj(v) &&
5656+ hasProp(v, '$type') &&
5757+ v.$type === 'app.bsky.richtext.facet#link'
5858+ )
5959+}
6060+6161+export function validateLink(v: unknown): ValidationResult {
6262+ return lexicons.validate('app.bsky.richtext.facet#link', v)
6363+}
6464+6565+/** Facet feature for a hashtag. The text usually includes a '#' prefix, but the facet reference should not (except in the case of 'double hash tags'). */
6666+export interface Tag {
6767+ tag: string
6868+ [k: string]: unknown
6969+}
7070+7171+export function isTag(v: unknown): v is Tag {
7272+ return (
7373+ isObj(v) && hasProp(v, '$type') && v.$type === 'app.bsky.richtext.facet#tag'
7474+ )
7575+}
7676+7777+export function validateTag(v: unknown): ValidationResult {
7878+ return lexicons.validate('app.bsky.richtext.facet#tag', v)
7979+}
8080+8181+/** Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets. */
8282+export interface ByteSlice {
8383+ byteStart: number
8484+ byteEnd: number
8585+ [k: string]: unknown
8686+}
8787+8888+export function isByteSlice(v: unknown): v is ByteSlice {
8989+ return (
9090+ isObj(v) &&
9191+ hasProp(v, '$type') &&
9292+ v.$type === 'app.bsky.richtext.facet#byteSlice'
9393+ )
9494+}
9595+9696+export function validateByteSlice(v: unknown): ValidationResult {
9797+ return lexicons.validate('app.bsky.richtext.facet#byteSlice', v)
9898+}
···11+/**
22+ * GENERATED CODE - DO NOT MODIFY
33+ */
44+import { ValidationResult, BlobRef } from '@atproto/lexicon'
55+import { lexicons } from '../../../../../lexicons'
66+import { isObj, hasProp } from '../../../../../util'
77+import { CID } from 'multiformats/cid'
88+import * as FmTealAlphaPlay from '../play'
99+1010+export interface Record {
1111+ /** The unix timestamp of when the item was recorded */
1212+ time: string
1313+ item: FmTealAlphaPlay.Record | { $type: string; [k: string]: unknown }
1414+ [k: string]: unknown
1515+}
1616+1717+export function isRecord(v: unknown): v is Record {
1818+ return (
1919+ isObj(v) &&
2020+ hasProp(v, '$type') &&
2121+ (v.$type === 'fm.teal.alpha.actor.status#main' ||
2222+ v.$type === 'fm.teal.alpha.actor.status')
2323+ )
2424+}
2525+2626+export function validateRecord(v: unknown): ValidationResult {
2727+ return lexicons.validate('fm.teal.alpha.actor.status#main', v)
2828+}
+49
lexicons/server/types/fm/teal/alpha/play.ts
···11+/**
22+ * GENERATED CODE - DO NOT MODIFY
33+ */
44+import { ValidationResult, BlobRef } from '@atproto/lexicon'
55+import { lexicons } from '../../../../lexicons'
66+import { isObj, hasProp } from '../../../../util'
77+import { CID } from 'multiformats/cid'
88+99+export interface Record {
1010+ /** The name of the track */
1111+ trackName: string
1212+ /** The Musicbrainz ID of the track */
1313+ trackMbId?: string
1414+ /** The Musicbrainz recording ID of the track */
1515+ recordingMbId?: string
1616+ /** The length of the track in seconds */
1717+ duration?: number
1818+ /** The name of the artist */
1919+ artistName: string
2020+ /** Array of Musicbrainz artist IDs */
2121+ artistMbIds?: string[]
2222+ /** The name of the release/album */
2323+ releaseName?: string
2424+ /** The Musicbrainz release ID */
2525+ releaseMbId?: string
2626+ /** The ISRC code associated with the recording */
2727+ isrc?: string
2828+ /** The URL associated with this track */
2929+ originUrl?: string
3030+ /** The base domain of the music service. e.g. music.apple.com, tidal.com, spotify.com. */
3131+ musicServiceBaseDomain?: string
3232+ /** A user-agent style string specifying the user agent. e.g. tealtracker/0.0.1b */
3333+ submissionClientAgent?: string
3434+ /** The unix timestamp of when the track was played */
3535+ playedTime?: string
3636+ [k: string]: unknown
3737+}
3838+3939+export function isRecord(v: unknown): v is Record {
4040+ return (
4141+ isObj(v) &&
4242+ hasProp(v, '$type') &&
4343+ (v.$type === 'fm.teal.alpha.play#main' || v.$type === 'fm.teal.alpha.play')
4444+ )
4545+}
4646+4747+export function validateRecord(v: unknown): ValidationResult {
4848+ return lexicons.validate('fm.teal.alpha.play#main', v)
4949+}
+26
lexicons/server/types/xyz/statusphere/status.ts
···11+/**
22+ * GENERATED CODE - DO NOT MODIFY
33+ */
44+import { ValidationResult, BlobRef } from '@atproto/lexicon'
55+import { lexicons } from '../../../lexicons'
66+import { isObj, hasProp } from '../../../util'
77+import { CID } from 'multiformats/cid'
88+99+export interface Record {
1010+ status: string
1111+ createdAt: string
1212+ [k: string]: unknown
1313+}
1414+1515+export function isRecord(v: unknown): v is Record {
1616+ return (
1717+ isObj(v) &&
1818+ hasProp(v, '$type') &&
1919+ (v.$type === 'xyz.statusphere.status#main' ||
2020+ v.$type === 'xyz.statusphere.status')
2121+ )
2222+}
2323+2424+export function validateRecord(v: unknown): ValidationResult {
2525+ return lexicons.validate('xyz.statusphere.status#main', v)
2626+}
+13
lexicons/server/util.ts
···11+/**
22+ * GENERATED CODE - DO NOT MODIFY
33+ */
44+export function isObj(v: unknown): v is Record<string, unknown> {
55+ return typeof v === 'object' && v !== null
66+}
77+88+export function hasProp<K extends PropertyKey>(
99+ data: object,
1010+ prop: K,
1111+): data is Record<K, unknown> {
1212+ return prop in data
1313+}
···11+{
22+ "lexicon": 1,
33+ "id": "app.bsky.richtext.facet",
44+ "defs": {
55+ "main": {
66+ "type": "object",
77+ "description": "Annotation of a sub-string within rich text.",
88+ "required": ["index", "features"],
99+ "properties": {
1010+ "index": { "type": "ref", "ref": "#byteSlice" },
1111+ "features": {
1212+ "type": "array",
1313+ "items": { "type": "union", "refs": ["#mention", "#link", "#tag"] }
1414+ }
1515+ }
1616+ },
1717+ "mention": {
1818+ "type": "object",
1919+ "description": "Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID.",
2020+ "required": ["did"],
2121+ "properties": {
2222+ "did": { "type": "string", "format": "did" }
2323+ }
2424+ },
2525+ "link": {
2626+ "type": "object",
2727+ "description": "Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.",
2828+ "required": ["uri"],
2929+ "properties": {
3030+ "uri": { "type": "string", "format": "uri" }
3131+ }
3232+ },
3333+ "tag": {
3434+ "type": "object",
3535+ "description": "Facet feature for a hashtag. The text usually includes a '#' prefix, but the facet reference should not (except in the case of 'double hash tags').",
3636+ "required": ["tag"],
3737+ "properties": {
3838+ "tag": { "type": "string", "maxLength": 640, "maxGraphemes": 64 }
3939+ }
4040+ },
4141+ "byteSlice": {
4242+ "type": "object",
4343+ "description": "Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets.",
4444+ "required": ["byteStart", "byteEnd"],
4545+ "properties": {
4646+ "byteStart": { "type": "integer", "minimum": 0 },
4747+ "byteEnd": { "type": "integer", "minimum": 0 }
4848+ }
4949+ }
5050+ }
5151+}
+64
lexicons/src/fm.teal.alpha.actor.profile.json
···11+{
22+ "lexicon": 1,
33+ "id": "fm.teal.alpha.actor.profile",
44+ "defs": {
55+ "main": {
66+ "type": "record",
77+ "description": "This lexicon is in a not officially released state. It is subject to change. | A declaration of a teal.fm account profile.",
88+ "key": "literal:self",
99+ "record": {
1010+ "type": "object",
1111+ "properties": {
1212+ "displayName": {
1313+ "type": "string",
1414+ "maxGraphemes": 64,
1515+ "maxLength": 640
1616+ },
1717+ "description": {
1818+ "type": "string",
1919+ "description": "Free-form profile description text.",
2020+ "maxGraphemes": 256,
2121+ "maxLength": 2560
2222+ },
2323+ "descriptionFacets": {
2424+ "type": "array",
2525+ "description": "Annotations of text in the profile description (mentions, URLs, hashtags, etc).",
2626+ "items": { "type": "ref", "ref": "app.bsky.richtext.facet" }
2727+ },
2828+ "featuredItem": {
2929+ "type": "ref",
3030+ "description": "The user's most recent item featured on their profile.",
3131+ "ref": "#featuredItem"
3232+ },
3333+ "avatar": {
3434+ "type": "blob",
3535+ "description": "Small image to be displayed next to posts from account. AKA, 'profile picture'",
3636+ "accept": ["image/png", "image/jpeg"],
3737+ "maxSize": 1000000
3838+ },
3939+ "banner": {
4040+ "type": "blob",
4141+ "description": "Larger horizontal image to display behind profile view.",
4242+ "accept": ["image/png", "image/jpeg"],
4343+ "maxSize": 1000000
4444+ },
4545+ "createdAt": { "type": "string", "format": "datetime" }
4646+ }
4747+ }
4848+ },
4949+ "featuredItem": {
5050+ "type": "object",
5151+ "required": ["mbid", "type"],
5252+ "properties": {
5353+ "mbid": {
5454+ "type": "string",
5555+ "description": "The Musicbrainz ID of the item"
5656+ },
5757+ "type": {
5858+ "type": "string",
5959+ "description": "The type of the item. Must be a valid Musicbrainz type, e.g. album, track, recording, etc."
6060+ }
6161+ }
6262+ }
6363+ }
6464+}
+23
lexicons/src/fm.teal.alpha.actor.status.json
···11+{
22+ "lexicon": 1,
33+ "id": "fm.teal.alpha.actor.status",
44+ "defs": {
55+ "main": {
66+ "type": "record",
77+ "description": "This lexicon is in a not officially released state. It is subject to change. | A declaration of the status of the actor. Only one can be shown at a time. If there are multiple, the latest record should be picked and earlier records should be deleted or tombstoned.",
88+ "key": "literal:self",
99+ "record": {
1010+ "type": "object",
1111+ "required": ["time", "item"],
1212+ "properties": {
1313+ "time": {
1414+ "type": "string",
1515+ "format": "datetime",
1616+ "description": "The unix timestamp of when the item was recorded"
1717+ },
1818+ "item": { "type": "union", "refs": ["fm.teal.alpha.play#record"] }
1919+ }
2020+ }
2121+ }
2222+ }
2323+}
+84
lexicons/src/fm.teal.alpha.play.json
···11+{
22+ "lexicon": 1,
33+ "id": "fm.teal.alpha.play",
44+ "description": "This lexicon is in a not officially released state. It is subject to change. | A declaration of a teal.fm play. Plays are submitted as a result of a user listening to a track. Plays should be marked as tracked when a user has listened to the entire track if it's under 2 minutes long, or half of the track's duration up to 4 minutes, whichever is longest.",
55+ "defs": {
66+ "main": {
77+ "type": "record",
88+ "key": "tid",
99+ "record": {
1010+ "type": "object",
1111+ "required": ["trackName", "artistName"],
1212+ "properties": {
1313+ "trackName": {
1414+ "type": "string",
1515+ "minLength": 1,
1616+ "maxLength": 256,
1717+ "maxGraphemes": 2560,
1818+ "description": "The name of the track"
1919+ },
2020+ "trackMbId": {
2121+ "type": "string",
2222+2323+ "description": "The Musicbrainz ID of the track"
2424+ },
2525+ "recordingMbId": {
2626+ "type": "string",
2727+ "description": "The Musicbrainz recording ID of the track"
2828+ },
2929+ "duration": {
3030+ "type": "integer",
3131+ "description": "The length of the track in seconds"
3232+ },
3333+ "artistName": {
3434+ "type": "string",
3535+ "minLength": 1,
3636+ "maxLength": 256,
3737+ "maxGraphemes": 2560,
3838+ "description": "The name of the artist"
3939+ },
4040+ "artistMbIds": {
4141+ "type": "array",
4242+ "items": {
4343+ "type": "string"
4444+ },
4545+ "description": "Array of Musicbrainz artist IDs"
4646+ },
4747+ "releaseName": {
4848+ "type": "string",
4949+ "maxLength": 256,
5050+ "maxGraphemes": 2560,
5151+ "description": "The name of the release/album"
5252+ },
5353+ "releaseMbId": {
5454+ "type": "string",
5555+ "description": "The Musicbrainz release ID"
5656+ },
5757+ "isrc": {
5858+ "type": "string",
5959+ "description": "The ISRC code associated with the recording"
6060+ },
6161+ "originUrl": {
6262+ "type": "string",
6363+ "description": "The URL associated with this track"
6464+ },
6565+ "musicServiceBaseDomain": {
6666+ "type": "string",
6767+ "description": "The base domain of the music service. e.g. music.apple.com, tidal.com, spotify.com."
6868+ },
6969+ "submissionClientAgent": {
7070+ "type": "string",
7171+ "maxLength": 256,
7272+ "maxGraphemes": 2560,
7373+ "description": "A user-agent style string specifying the user agent. e.g. tealtracker/0.0.1b"
7474+ },
7575+ "playedTime": {
7676+ "type": "string",
7777+ "format": "datetime",
7878+ "description": "The unix timestamp of when the track was played"
7979+ }
8080+ }
8181+ }
8282+ }
8383+ }
8484+}