Your music, beautifully tracked. All yours. (coming soon) teal.fm
teal-fm atproto

lexicons should compile correctly now!

+567 -16
+50
packages/lexicons/generated/server/index.ts
··· 17 17 export class Server { 18 18 xrpc: XrpcServer 19 19 app: AppNS 20 + fm: FmNS 20 21 xyz: XyzNS 21 22 22 23 constructor(options?: XrpcOptions) { 23 24 this.xrpc = createXrpcServer(schemas, options) 24 25 this.app = new AppNS(this) 26 + this.fm = new FmNS(this) 25 27 this.xyz = new XyzNS(this) 26 28 } 27 29 } ··· 39 41 export class AppBskyNS { 40 42 _server: Server 41 43 actor: AppBskyActorNS 44 + richtext: AppBskyRichtextNS 42 45 43 46 constructor(server: Server) { 44 47 this._server = server 45 48 this.actor = new AppBskyActorNS(server) 49 + this.richtext = new AppBskyRichtextNS(server) 46 50 } 47 51 } 48 52 49 53 export class AppBskyActorNS { 54 + _server: Server 55 + 56 + constructor(server: Server) { 57 + this._server = server 58 + } 59 + } 60 + 61 + export class AppBskyRichtextNS { 62 + _server: Server 63 + 64 + constructor(server: Server) { 65 + this._server = server 66 + } 67 + } 68 + 69 + export class FmNS { 70 + _server: Server 71 + teal: FmTealNS 72 + 73 + constructor(server: Server) { 74 + this._server = server 75 + this.teal = new FmTealNS(server) 76 + } 77 + } 78 + 79 + export class FmTealNS { 80 + _server: Server 81 + alpha: FmTealAlphaNS 82 + 83 + constructor(server: Server) { 84 + this._server = server 85 + this.alpha = new FmTealAlphaNS(server) 86 + } 87 + } 88 + 89 + export class FmTealAlphaNS { 90 + _server: Server 91 + actor: FmTealAlphaActorNS 92 + 93 + constructor(server: Server) { 94 + this._server = server 95 + this.actor = new FmTealAlphaActorNS(server) 96 + } 97 + } 98 + 99 + export class FmTealAlphaActorNS { 50 100 _server: Server 51 101 52 102 constructor(server: Server) {
+274
packages/lexicons/generated/server/lexicons.ts
··· 59 59 }, 60 60 }, 61 61 }, 62 + AppBskyRichtextFacet: { 63 + lexicon: 1, 64 + id: 'app.bsky.richtext.facet', 65 + defs: { 66 + main: { 67 + type: 'object', 68 + description: 'Annotation of a sub-string within rich text.', 69 + required: ['index', 'features'], 70 + properties: { 71 + index: { 72 + type: 'ref', 73 + ref: 'lex:app.bsky.richtext.facet#byteSlice', 74 + }, 75 + features: { 76 + type: 'array', 77 + items: { 78 + type: 'union', 79 + refs: [ 80 + 'lex:app.bsky.richtext.facet#mention', 81 + 'lex:app.bsky.richtext.facet#link', 82 + 'lex:app.bsky.richtext.facet#tag', 83 + ], 84 + }, 85 + }, 86 + }, 87 + }, 88 + mention: { 89 + type: 'object', 90 + description: 91 + "Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID.", 92 + required: ['did'], 93 + properties: { 94 + did: { 95 + type: 'string', 96 + format: 'did', 97 + }, 98 + }, 99 + }, 100 + link: { 101 + type: 'object', 102 + description: 103 + 'Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.', 104 + required: ['uri'], 105 + properties: { 106 + uri: { 107 + type: 'string', 108 + format: 'uri', 109 + }, 110 + }, 111 + }, 112 + tag: { 113 + type: 'object', 114 + description: 115 + "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').", 116 + required: ['tag'], 117 + properties: { 118 + tag: { 119 + type: 'string', 120 + maxLength: 640, 121 + maxGraphemes: 64, 122 + }, 123 + }, 124 + }, 125 + byteSlice: { 126 + type: 'object', 127 + description: 128 + '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.', 129 + required: ['byteStart', 'byteEnd'], 130 + properties: { 131 + byteStart: { 132 + type: 'integer', 133 + minimum: 0, 134 + }, 135 + byteEnd: { 136 + type: 'integer', 137 + minimum: 0, 138 + }, 139 + }, 140 + }, 141 + }, 142 + }, 143 + FmTealAlphaActorStatus: { 144 + lexicon: 1, 145 + id: 'fm.teal.alpha.actor.status', 146 + defs: { 147 + main: { 148 + type: 'record', 149 + description: 150 + '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, pick the latest record.', 151 + key: 'literal:self', 152 + record: { 153 + type: 'object', 154 + required: ['time', 'item'], 155 + properties: { 156 + time: { 157 + type: 'string', 158 + format: 'datetime', 159 + description: 'The unix timestamp of when the item was recorded', 160 + }, 161 + item: { 162 + type: 'union', 163 + refs: ['lex:fm.teal.alpha.play#main'], 164 + }, 165 + }, 166 + }, 167 + }, 168 + }, 169 + }, 170 + FmTealAlphaActorProfile: { 171 + lexicon: 1, 172 + id: 'fm.teal.alpha.actor.profile', 173 + defs: { 174 + main: { 175 + type: 'record', 176 + description: 177 + 'This lexicon is in a not officially released state. It is subject to change. | A declaration of a teal.fm account profile.', 178 + key: 'literal:self', 179 + record: { 180 + type: 'object', 181 + properties: { 182 + displayName: { 183 + type: 'string', 184 + maxGraphemes: 64, 185 + maxLength: 640, 186 + }, 187 + description: { 188 + type: 'string', 189 + description: 'Free-form profile description text.', 190 + maxGraphemes: 256, 191 + maxLength: 2560, 192 + }, 193 + descriptionFacets: { 194 + type: 'array', 195 + description: 196 + 'Annotations of text in the profile description (mentions, URLs, hashtags, etc).', 197 + items: { 198 + type: 'ref', 199 + ref: 'lex:app.bsky.richtext.facet', 200 + }, 201 + }, 202 + featuredItem: { 203 + type: 'ref', 204 + description: 205 + "The user's most recent item featured on their profile.", 206 + ref: 'lex:fm.teal.alpha.actor.profile#featuredItem', 207 + }, 208 + avatar: { 209 + type: 'blob', 210 + description: 211 + "Small image to be displayed next to posts from account. AKA, 'profile picture'", 212 + accept: ['image/png', 'image/jpeg'], 213 + maxSize: 1000000, 214 + }, 215 + banner: { 216 + type: 'blob', 217 + description: 218 + 'Larger horizontal image to display behind profile view.', 219 + accept: ['image/png', 'image/jpeg'], 220 + maxSize: 1000000, 221 + }, 222 + createdAt: { 223 + type: 'string', 224 + format: 'datetime', 225 + }, 226 + }, 227 + }, 228 + }, 229 + featuredPlay: { 230 + type: 'object', 231 + required: ['mbid', 'type'], 232 + properties: { 233 + mbid: { 234 + type: 'string', 235 + description: 'The Musicbrainz ID of the item', 236 + }, 237 + type: { 238 + type: 'string', 239 + description: 240 + 'The type of the item. Must be a valid Musicbrainz type, e.g. album, track, recording, etc.', 241 + }, 242 + }, 243 + }, 244 + }, 245 + }, 246 + FmTealAlphaPlay: { 247 + lexicon: 1, 248 + id: 'fm.teal.alpha.play', 249 + description: 250 + "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.", 251 + defs: { 252 + main: { 253 + type: 'record', 254 + key: 'tid', 255 + record: { 256 + type: 'object', 257 + required: ['trackName', 'artistName'], 258 + properties: { 259 + trackName: { 260 + type: 'string', 261 + minLength: 1, 262 + maxLength: 256, 263 + maxGraphemes: 2560, 264 + description: 'The name of the track', 265 + }, 266 + trackMbId: { 267 + type: 'string', 268 + description: 'The Musicbrainz ID of the track', 269 + }, 270 + recordingMbId: { 271 + type: 'string', 272 + description: 'The Musicbrainz recording ID of the track', 273 + }, 274 + duration: { 275 + type: 'integer', 276 + description: 'The length of the track in seconds', 277 + }, 278 + artistName: { 279 + type: 'string', 280 + minLength: 1, 281 + maxLength: 256, 282 + maxGraphemes: 2560, 283 + description: 'The name of the artist', 284 + }, 285 + artistMbIds: { 286 + type: 'array', 287 + items: { 288 + type: 'string', 289 + }, 290 + description: 'Array of Musicbrainz artist IDs', 291 + }, 292 + releaseName: { 293 + type: 'string', 294 + maxLength: 256, 295 + maxGraphemes: 2560, 296 + description: 'The name of the release/album', 297 + }, 298 + releaseMbId: { 299 + type: 'string', 300 + description: 'The Musicbrainz release ID', 301 + }, 302 + isrc: { 303 + type: 'string', 304 + description: 'The ISRC code associated with the recording', 305 + }, 306 + originUrl: { 307 + type: 'string', 308 + description: 'The URL associated with this track', 309 + }, 310 + musicServiceBaseDomain: { 311 + type: 'string', 312 + description: 313 + 'The base domain of the music service. e.g. music.apple.com, tidal.com, spotify.com.', 314 + }, 315 + submissionClientAgent: { 316 + type: 'string', 317 + maxLength: 256, 318 + maxGraphemes: 2560, 319 + description: 320 + 'A user-agent style string specifying the user agent. e.g. tealtracker/0.0.1b', 321 + }, 322 + playedTime: { 323 + type: 'string', 324 + format: 'datetime', 325 + description: 'The unix timestamp of when the track was played', 326 + }, 327 + }, 328 + }, 329 + }, 330 + }, 331 + }, 62 332 XyzStatusphereStatus: { 63 333 lexicon: 1, 64 334 id: 'xyz.statusphere.status', ··· 90 360 export const lexicons: Lexicons = new Lexicons(schemas) 91 361 export const ids = { 92 362 AppBskyActorProfile: 'app.bsky.actor.profile', 363 + AppBskyRichtextFacet: 'app.bsky.richtext.facet', 364 + FmTealAlphaActorStatus: 'fm.teal.alpha.actor.status', 365 + FmTealAlphaActorProfile: 'fm.teal.alpha.actor.profile', 366 + FmTealAlphaPlay: 'fm.teal.alpha.play', 93 367 XyzStatusphereStatus: 'xyz.statusphere.status', 94 368 }
+98
packages/lexicons/generated/server/types/app/bsky/richtext/facet.ts
··· 1 + /** 2 + * GENERATED CODE - DO NOT MODIFY 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 + 9 + /** Annotation of a sub-string within rich text. */ 10 + export interface Main { 11 + index: ByteSlice 12 + features: (Mention | Link | Tag | { $type: string; [k: string]: unknown })[] 13 + [k: string]: unknown 14 + } 15 + 16 + export function isMain(v: unknown): v is Main { 17 + return ( 18 + isObj(v) && 19 + hasProp(v, '$type') && 20 + (v.$type === 'app.bsky.richtext.facet#main' || 21 + v.$type === 'app.bsky.richtext.facet') 22 + ) 23 + } 24 + 25 + export function validateMain(v: unknown): ValidationResult { 26 + return lexicons.validate('app.bsky.richtext.facet#main', v) 27 + } 28 + 29 + /** Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID. */ 30 + export interface Mention { 31 + did: string 32 + [k: string]: unknown 33 + } 34 + 35 + export function isMention(v: unknown): v is Mention { 36 + return ( 37 + isObj(v) && 38 + hasProp(v, '$type') && 39 + v.$type === 'app.bsky.richtext.facet#mention' 40 + ) 41 + } 42 + 43 + export function validateMention(v: unknown): ValidationResult { 44 + return lexicons.validate('app.bsky.richtext.facet#mention', v) 45 + } 46 + 47 + /** Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL. */ 48 + export interface Link { 49 + uri: string 50 + [k: string]: unknown 51 + } 52 + 53 + export function isLink(v: unknown): v is Link { 54 + return ( 55 + isObj(v) && 56 + hasProp(v, '$type') && 57 + v.$type === 'app.bsky.richtext.facet#link' 58 + ) 59 + } 60 + 61 + export function validateLink(v: unknown): ValidationResult { 62 + return lexicons.validate('app.bsky.richtext.facet#link', v) 63 + } 64 + 65 + /** 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'). */ 66 + export interface Tag { 67 + tag: string 68 + [k: string]: unknown 69 + } 70 + 71 + export function isTag(v: unknown): v is Tag { 72 + return ( 73 + isObj(v) && hasProp(v, '$type') && v.$type === 'app.bsky.richtext.facet#tag' 74 + ) 75 + } 76 + 77 + export function validateTag(v: unknown): ValidationResult { 78 + return lexicons.validate('app.bsky.richtext.facet#tag', v) 79 + } 80 + 81 + /** 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. */ 82 + export interface ByteSlice { 83 + byteStart: number 84 + byteEnd: number 85 + [k: string]: unknown 86 + } 87 + 88 + export function isByteSlice(v: unknown): v is ByteSlice { 89 + return ( 90 + isObj(v) && 91 + hasProp(v, '$type') && 92 + v.$type === 'app.bsky.richtext.facet#byteSlice' 93 + ) 94 + } 95 + 96 + export function validateByteSlice(v: unknown): ValidationResult { 97 + return lexicons.validate('app.bsky.richtext.facet#byteSlice', v) 98 + }
+56
packages/lexicons/generated/server/types/fm/teal/alpha/actor/profile.ts
··· 1 + /** 2 + * GENERATED CODE - DO NOT MODIFY 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 AppBskyRichtextFacet from '../../../../app/bsky/richtext/facet' 9 + 10 + export interface Record { 11 + displayName?: string 12 + /** Free-form profile description text. */ 13 + description?: string 14 + /** Annotations of text in the profile description (mentions, URLs, hashtags, etc). */ 15 + descriptionFacets?: AppBskyRichtextFacet.Main[] 16 + featuredItem?: FeaturedItem 17 + /** Small image to be displayed next to posts from account. AKA, 'profile picture' */ 18 + avatar?: BlobRef 19 + /** Larger horizontal image to display behind profile view. */ 20 + banner?: BlobRef 21 + createdAt?: string 22 + [k: string]: unknown 23 + } 24 + 25 + export function isRecord(v: unknown): v is Record { 26 + return ( 27 + isObj(v) && 28 + hasProp(v, '$type') && 29 + (v.$type === 'fm.teal.alpha.actor.profile#main' || 30 + v.$type === 'fm.teal.alpha.actor.profile') 31 + ) 32 + } 33 + 34 + export function validateRecord(v: unknown): ValidationResult { 35 + return lexicons.validate('fm.teal.alpha.actor.profile#main', v) 36 + } 37 + 38 + export interface FeaturedPlay { 39 + /** The Musicbrainz ID of the item */ 40 + mbid: string 41 + /** The type of the item. Must be a valid Musicbrainz type, e.g. album, track, recording, etc. */ 42 + type: string 43 + [k: string]: unknown 44 + } 45 + 46 + export function isFeaturedPlay(v: unknown): v is FeaturedPlay { 47 + return ( 48 + isObj(v) && 49 + hasProp(v, '$type') && 50 + v.$type === 'fm.teal.alpha.actor.profile#featuredPlay' 51 + ) 52 + } 53 + 54 + export function validateFeaturedPlay(v: unknown): ValidationResult { 55 + return lexicons.validate('fm.teal.alpha.actor.profile#featuredPlay', v) 56 + }
+28
packages/lexicons/generated/server/types/fm/teal/alpha/actor/status.ts
··· 1 + /** 2 + * GENERATED CODE - DO NOT MODIFY 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 FmTealAlphaPlay from '../play' 9 + 10 + export interface Record { 11 + /** The unix timestamp of when the item was recorded */ 12 + time: string 13 + item: FmTealAlphaPlay.Main | { $type: string; [k: string]: unknown } 14 + [k: string]: unknown 15 + } 16 + 17 + export function isRecord(v: unknown): v is Record { 18 + return ( 19 + isObj(v) && 20 + hasProp(v, '$type') && 21 + (v.$type === 'fm.teal.alpha.actor.status#main' || 22 + v.$type === 'fm.teal.alpha.actor.status') 23 + ) 24 + } 25 + 26 + export function validateRecord(v: unknown): ValidationResult { 27 + return lexicons.validate('fm.teal.alpha.actor.status#main', v) 28 + }
+49
packages/lexicons/generated/server/types/fm/teal/alpha/play.ts
··· 1 + /** 2 + * GENERATED CODE - DO NOT MODIFY 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 + 9 + export interface Record { 10 + /** The name of the track */ 11 + trackName: string 12 + /** The Musicbrainz ID of the track */ 13 + trackMbId?: string 14 + /** The Musicbrainz recording ID of the track */ 15 + recordingMbId?: string 16 + /** The length of the track in seconds */ 17 + duration?: number 18 + /** The name of the artist */ 19 + artistName: string 20 + /** Array of Musicbrainz artist IDs */ 21 + artistMbIds?: string[] 22 + /** The name of the release/album */ 23 + releaseName?: string 24 + /** The Musicbrainz release ID */ 25 + releaseMbId?: string 26 + /** The ISRC code associated with the recording */ 27 + isrc?: string 28 + /** The URL associated with this track */ 29 + originUrl?: string 30 + /** The base domain of the music service. e.g. music.apple.com, tidal.com, spotify.com. */ 31 + musicServiceBaseDomain?: string 32 + /** A user-agent style string specifying the user agent. e.g. tealtracker/0.0.1b */ 33 + submissionClientAgent?: string 34 + /** The unix timestamp of when the track was played */ 35 + playedTime?: string 36 + [k: string]: unknown 37 + } 38 + 39 + export function isRecord(v: unknown): v is Record { 40 + return ( 41 + isObj(v) && 42 + hasProp(v, '$type') && 43 + (v.$type === 'fm.teal.alpha.play#main' || v.$type === 'fm.teal.alpha.play') 44 + ) 45 + } 46 + 47 + export function validateRecord(v: unknown): ValidationResult { 48 + return lexicons.validate('fm.teal.alpha.play#main', v) 49 + }
+2 -2
packages/lexicons/src/fm.teal.alpha.actor.currentListen.json
··· 4 4 "defs": { 5 5 "main": { 6 6 "type": "record", 7 - "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, pick the latest record.", 7 + "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.", 8 8 "key": "literal:self", 9 9 "record": { 10 10 "type": "object", 11 - "required": ["listeningTo"], 11 + "required": ["time", "item"], 12 12 "properties": { 13 13 "time": { 14 14 "type": "string",
+10 -14
packages/lexicons/src/fm.teal.alpha.actor.profile.json
··· 47 47 } 48 48 }, 49 49 "featuredPlay": { 50 - "type": "record", 51 - "key": "tid", 52 - "record": { 53 - "type": "object", 54 - "required": ["mbid", "type"], 55 - "properties": { 56 - "mbid": { 57 - "type": "string", 58 - "description": "The Musicbrainz ID of the item" 59 - }, 60 - "type": { 61 - "type": "string", 62 - "description": "The type of the item. Must be a valid Musicbrainz type, e.g. album, track, recording, etc." 63 - } 50 + "type": "object", 51 + "required": ["mbid", "type"], 52 + "properties": { 53 + "mbid": { 54 + "type": "string", 55 + "description": "The Musicbrainz ID of the item" 56 + }, 57 + "type": { 58 + "type": "string", 59 + "description": "The type of the item. Must be a valid Musicbrainz type, e.g. album, track, recording, etc." 64 60 } 65 61 } 66 62 }