A decentralized music tracking and discovery platform built on AT Protocol 🎵 rocksky.app
spotify atproto lastfm musicbrainz scrobbling listenbrainz
0

Configure Feed

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

feat(sdk): generate types from lexicons across all 9 SDKs

Add `tools/lexgen/` — a single Bun-driven generator that parses
`apps/api/lexicons/**/*.json` once and emits typed bindings for
TypeScript, Go, Python (dataclasses + Pydantic), Rust, Kotlin, Ruby,
Elixir, Clojure (malli), and Gleam. Wired into the root as
`bun run lexgen:types`.

Each SDK now imports its public model types from the generated module
under its historical names: TS namespaces use `src/generated/types`,
Go `rocksky/types.go` aliases to `rocksky/gen`, Python `models.py`
re-exports the Pydantic generated module, Rust `models.rs` does
`pub use crate::generated::… as …`, Kotlin uses `typealias`, Gleam
aliases plus regenerated decoder constructors. Ruby/Elixir/Clojure
expose the generated modules directly since they had no hand-written
model layer.

Lexicon corrections caught along the way (fixed in Pkl source so
`pkl:gen` preserves them): two `ref` typos using `.` instead of `#`
(`album/defs`, `player/defs`), and `scrobble/defs#scrobbleViewDetailed`
gaining `liked` / `likesCount` to match the wire shape.

Every SDK's existing test suite still passes (388+ tests). Versions
bumped to 0.2.0 (Gleam 1.1.0); CHANGELOGs updated where they existed;
each SDK README and `docs/sdks/*.mdx` got a "Types" section pointing
at the regen command.

+21028 -1854
+173 -78
LEXICONS.md
··· 1 1 # Rocksky Lexicons 2 2 3 + Examples below are real records fetched from production PDSes via `com.atproto.repo.getRecord` / `com.atproto.repo.listRecords` against `https://api.rocksky.app/xrpc` and the corresponding user's PDS. Lexicon source files live under `apps/api/lexicons/`. 4 + 5 + ## `app.rocksky.actor.status` 6 + 7 + The current listening status of an actor. Single record per repo with `rkey: self`. Created/refreshed each time the actor begins playing a track and expires automatically (track duration + idle time). 8 + 9 + ### Example record 10 + ```json 11 + { 12 + "$type": "app.rocksky.actor.status", 13 + "track": { 14 + "name": "Papercut", 15 + "album": "Hybrid Theory (Bonus Edition)", 16 + "artist": "Linkin Park", 17 + "source": "spotify", 18 + "durationMs": 184866, 19 + "albumCoverUrl": "https://i.scdn.co/image/ab67616d0000b273e2f039481babe23658fc719a", 20 + "recordingMbId": "22575d46-2ada-4659-b40f-5113c0878600" 21 + }, 22 + "startedAt": "2026-06-02T13:16:03.133Z", 23 + "expiresAt": "2026-06-02T13:19:07.999Z" 24 + } 25 + ``` 26 + 3 27 ## `app.rocksky.album` 4 28 5 29 ### Example record 6 30 ```json 7 31 { 8 - "year": 2022, 9 32 "$type": "app.rocksky.album", 10 - "title": "CRASH (Deluxe)", 11 - "artist": "Charli xcx", 12 - "albumArt": { 13 - "$type": "blob", 14 - "ref": { 15 - "$link": "bafkreigxbmkowezanfdgn4qnvsl2tfbqqjoxdrkaqk7tjst3x6kcklwazy" 16 - }, 17 - "mimeType": "image/jpeg", 18 - "size": 316543 19 - }, 20 - "createdAt": "2025-09-09T11:01:35.792Z", 21 - "releaseDate": "2022-03-18T00:00:00.000Z" 33 + "title": "Jazzploitation", 34 + "artist": "Calibro 35", 35 + "year": 2024, 36 + "releaseDate": "2024-10-18T00:00:00.000Z", 37 + "albumArtUrl": "https://i.scdn.co/image/ab67616d0000b2739a8e268beabdca126a35b0f6", 38 + "createdAt": "2026-06-02T13:15:33.090Z" 39 + } 40 + ``` 41 + 42 + `albumArt` may also appear as an inline blob: 43 + ```json 44 + "albumArt": { 45 + "$type": "blob", 46 + "ref": { "$link": "bafkreigxbmkowezanfdgn4qnvsl2tfbqqjoxdrkaqk7tjst3x6kcklwazy" }, 47 + "mimeType": "image/jpeg", 48 + "size": 316543 22 49 } 23 50 ``` 24 51 ··· 27 54 ### Example record 28 55 ```json 29 56 { 30 - "name": "Lady Gaga", 31 57 "$type": "app.rocksky.artist", 32 - "picture": { 33 - "$type": "blob", 34 - "ref": { 35 - "$link": "bafkreiggssa2uk3m6cdkf4y7mqlgedl5mqsvljclne5me54giw3tkxa5w4" 36 - }, 37 - "mimeType": "image/jpeg", 38 - "size": 80534 39 - }, 40 - "createdAt": "2025-04-09T20:55:13.074Z" 58 + "name": "Calibro 35", 59 + "tags": ["jazz funk"], 60 + "pictureUrl": "https://i.scdn.co/image/ab6761610000e5ebea9472d3894a1bde2b606121", 61 + "createdAt": "2026-06-02T13:15:32.762Z" 62 + } 63 + ``` 64 + 65 + `picture` may also appear as an inline blob (`$type: blob`, `ref.$link`, `mimeType`, `size`) when the image was uploaded rather than referenced by URL. 66 + 67 + ## `app.rocksky.feed.generator` 68 + 69 + Declares a custom feed generator. `rkey` is the generator's short name. 70 + 71 + ### Example record 72 + ```json 73 + { 74 + "$type": "app.rocksky.feed.generator", 75 + "did": "did:web:discover.rocksky.app", 76 + "displayName": "Popular With Friends", 77 + "description": "A mix of popular songs from accounts you follow and songs that your follows like.", 78 + "createdAt": "2025-10-12T04:57:52.745Z" 79 + } 80 + ``` 81 + 82 + ## `app.rocksky.graph.follow` 83 + 84 + Social "follow" of another account. `subject` is a raw DID (not a strongRef). 85 + 86 + ### Example record 87 + ```json 88 + { 89 + "$type": "app.rocksky.graph.follow", 90 + "subject": "did:plc:rlwgbwqdknilpxxep5gvzc3y", 91 + "createdAt": "2026-06-01T14:21:16.806Z" 41 92 } 42 93 ``` 43 94 ··· 48 99 { 49 100 "$type": "app.rocksky.like", 50 101 "subject": { 51 - "cid": "bafyreifsx2d2vh5mckx5l7ozq5bibpqsznezgvogti4orlirjwlkor4lcy", 52 - "uri": "at://did:plc:7vdlgi2bflelz7mmuxoqjfcr/app.rocksky.song/3lymtp5nuqc25" 102 + "uri": "at://did:plc:7vdlgi2bflelz7mmuxoqjfcr/app.rocksky.song/3mmeq5hsh542r", 103 + "cid": "bafyreiamlpyy5rbnumhgq2iulz7p73l36aaogdebz4zi3q5cz3nslpbrbu" 53 104 }, 54 - "createdAt": "2025-09-12T08:27:37.871Z" 105 + "createdAt": "2026-06-01T12:43:16.524Z" 55 106 } 56 107 ``` 57 108 ··· 60 111 ### Example record 61 112 ```json 62 113 { 63 - "name": "Hip Hop US", 64 114 "$type": "app.rocksky.playlist", 115 + "name": "Hip Hop US", 116 + "description": "", 65 117 "picture": { 66 118 "$type": "blob", 67 - "ref": { 68 - "$link": "bafkreiclplbmi5s2tocvzp3227rsquh2esbtsxuaejwe2ajkaalznico3i" 69 - }, 119 + "ref": { "$link": "bafkreiclplbmi5s2tocvzp3227rsquh2esbtsxuaejwe2ajkaalznico3i" }, 70 120 "mimeType": "image/jpeg", 71 121 "size": 50247 72 122 }, 73 - "createdAt": "2025-03-09T13:07:08.176Z", 74 - "description": "", 75 - "spotifyLink": "https://open.spotify.com/playlist/40fEXcsbQix2oK4QzRPVAl" 123 + "spotifyLink": "https://open.spotify.com/playlist/40fEXcsbQix2oK4QzRPVAl", 124 + "createdAt": "2025-03-09T13:07:08.176Z" 125 + } 126 + ``` 127 + 128 + ## `app.rocksky.playlistItem` 129 + 130 + A single entry within a playlist. Lexicon defined in `apps/api/lexicons/playlist/playlistItem.json`; no on-network instances were discovered at the time of writing — the schema-based shape is: 131 + 132 + ```json 133 + { 134 + "$type": "app.rocksky.playlistItem", 135 + "subject": { 136 + "uri": "at://did:plc:.../app.rocksky.playlist/<rkey>", 137 + "cid": "bafyrei..." 138 + }, 139 + "track": { 140 + "title": "...", 141 + "artist": "...", 142 + "uri": "at://did:plc:.../app.rocksky.song/<rkey>" 143 + }, 144 + "order": 0, 145 + "createdAt": "2026-06-02T00:00:00.000Z" 146 + } 147 + ``` 148 + 149 + `track` is an `app.rocksky.song.defs#songViewBasic`. 150 + 151 + ## `app.rocksky.radio` 152 + 153 + A user-declared radio station. Lexicon defined in `apps/api/lexicons/radio/radio.json`; no on-network instances were discovered at the time of writing — the schema-based shape is: 154 + 155 + ```json 156 + { 157 + "$type": "app.rocksky.radio", 158 + "name": "FIP", 159 + "url": "https://icecast.radiofrance.fr/fip-hifi.aac", 160 + "description": "Eclectic music from Radio France.", 161 + "genre": "eclectic", 162 + "website": "https://www.radiofrance.fr/fip", 163 + "createdAt": "2026-06-02T00:00:00.000Z" 76 164 } 77 165 ``` 78 166 ··· 81 169 ### Example record 82 170 ```json 83 171 { 84 - "year": 2022, 85 172 "$type": "app.rocksky.scrobble", 86 - "album": "CRASH (Deluxe)", 87 - "title": "Every Rule", 88 - "artist": "Charli xcx", 89 - "lyrics": "[00:10.46] When I met you, it was tragic\n[00:13.01] Chemistry something like magic\n[00:15.74] You were with somebody else long term\n[00:18.12] And I was with somebody else as well\n[00:20.87] Met up late night by the Bowery\n[00:23.51] And in the morning, we got coffee\n[00:26.15] Acting like strangers and told no friends\n[00:28.78] It wasn't easy to pretend\n[00:30.33] And we know that it's wrong, but it feels real fun\n[00:33.29] Sneaking around, falling deep in love\n[00:35.66] But sometimes I get scared\n[00:36.86] 'Cause I know it's unfair\n[00:39.01] I'm hurting someone else instead\n[00:42.68] I'm breaking every rule for you\n[00:47.97] You're breaking every rule for me\n[00:53.19] I'm breaking every rule for you\n[00:56.61] But I gotta say\n[00:57.90] I want it this way\n[00:59.82] These moments really set me free\n[01:02.69] Ah, ah, ah, ah, ah, ah\n[01:07.36] Ah, ah, ah, ah, ah, ah, ah, ah\n[01:13.02] Ah, ah, ah, ah, ah, ah\n[01:17.63] Ah, ah, ah, ah, ah, ah, ah, ah\n[01:23.45] Straight away, we started falling\n[01:26.00] Conversation never boring\n[01:28.81] When your lips brushed up against my skin\n[01:31.34] All I wanted was to let you in\n[01:33.80] I wonder if people will notice\n[01:36.54] Said you find it so hard to focus\n[01:39.12] Cigarettes up on the balcony\n[01:41.87] Wrapped up in nothing but sheets\n[01:43.31] And we know that it's wrong, but it feels real fun\n[01:46.33] Sneaking around, falling deep in love\n[01:48.52] But sometimes I get scared\n[01:49.93] 'Cause I know it's unfair\n[01:51.81] I'm hurting someone else instead\n[01:55.84] I'm breaking every rule for you\n[02:01.08] You're breaking every rule for me\n[02:06.20] I'm breaking every rule for you\n[02:09.88] But I gotta say\n[02:10.98] I want it this way\n[02:12.85] These moments really set me free\n[02:15.74] Ah, ah, ah, ah, ah, ah\n[02:20.29] Ah, ah, ah, ah, ah, ah, ah, ah\n[02:26.14] Ah, ah, ah, ah, ah, ah\n[02:30.71] Ah, ah, ah, ah, ah, ah, ah, ah\n[02:35.98] ", 90 - "albumArt": { 91 - "$type": "blob", 92 - "ref": { 93 - "$link": "bafkreigxbmkowezanfdgn4qnvsl2tfbqqjoxdrkaqk7tjst3x6kcklwazy" 94 - }, 95 - "mimeType": "image/jpeg", 96 - "size": 316543 97 - }, 98 - "composer": "Alexander Guy Cook", 99 - "duration": 183120, 100 - "createdAt": "2025-09-12T08:42:04.122Z", 173 + "title": "Chaser", 174 + "artist": "Calibro 35", 175 + "artists": [ 176 + { "name": "Calibro 35", "mbid": "7b6baeda-94ec-4475-9b09-6486a36c8e40" } 177 + ], 178 + "albumArtist": "Calibro 35", 179 + "album": "Jazzploitation", 180 + "duration": 182320, 181 + "trackNumber": 1, 101 182 "discNumber": 1, 102 - "albumArtist": "Charli xcx", 103 - "releaseDate": "2022-03-18T00:00:00.000Z", 104 - "trackNumber": 9, 105 - "copyrightMessage": "℗ 2021 Warner Music UK Limited" 183 + "year": 2024, 184 + "releaseDate": "2024-10-18T00:00:00.000Z", 185 + "tags": ["jazz funk"], 186 + "mbid": "58a46583-dc71-4d4f-bdde-a7323578873e", 187 + "isrc": "ITG582400039", 188 + "albumArtUrl": "https://i.scdn.co/image/ab67616d0000b2739a8e268beabdca126a35b0f6", 189 + "spotifyLink": "https://open.spotify.com/track/3zrtwgbIxpAvUxW0QGb1Lk", 190 + "createdAt": "2026-06-02T13:15:09.000Z" 106 191 } 107 192 ``` 193 + 194 + Optional fields not in the example above but defined by the lexicon: `genre`, `composer`, `lyrics`, `copyrightMessage`, `wiki`, `label`, `albumArt` (blob), `youtubeLink`, `tidalLink`, `appleMusicLink`. 108 195 109 196 ## `app.rocksky.shout` 110 197 111 - ### Example record 198 + Reply shouts include a `parent` strongRef; top-level shouts omit it. 199 + 200 + ### Example record (reply) 112 201 ```json 113 202 { 114 203 "$type": "app.rocksky.shout", 115 - "message": "nice", 204 + "message": "test", 116 205 "subject": { 117 - "cid": "bafyreiee6ceyr65gepzufgkx5gcfa6fzksb3w22rwlmztsz2v73el2jzj4", 118 - "uri": "at://did:plc:7vdlgi2bflelz7mmuxoqjfcr/app.rocksky.artist/3lhlnky67uk2k" 206 + "uri": "at://did:plc:7vdlgi2bflelz7mmuxoqjfcr/app.rocksky.scrobble/3lik6myiabc2g", 207 + "cid": "bafyreiasxykhkr6mfdcqmd5lg3pnohkx2kgskmbnkodtjwmrjyx3ubryr4" 208 + }, 209 + "parent": { 210 + "uri": "at://did:plc:7vdlgi2bflelz7mmuxoqjfcr/app.rocksky.shout/3lik6ogwdwk2g", 211 + "cid": "bafyreifbokyl7rbgqnu6xpvzwt5tdhlxqdaf6rb4j7l67y5oi4g7r3zrym" 119 212 }, 120 - "createdAt": "2025-02-16T14:25:51.697Z" 213 + "createdAt": "2025-02-19T16:22:22.585Z" 121 214 } 122 215 ``` 123 216 217 + `subject` can target any record type — examples seen in production point at `app.rocksky.scrobble`, `app.rocksky.artist`, `app.rocksky.album`, and `app.bsky.actor.profile`. 218 + 124 219 ## `app.rocksky.song` 125 220 126 221 ### Example record 127 222 ```json 128 223 { 129 - "year": 2017, 130 224 "$type": "app.rocksky.song", 131 - "album": "Pop 2", 132 - "title": "Delicious (feat. Tommy Cash)", 133 - "artist": "Charli xcx, Tommy Cash", 134 - "lyrics": "[00:02.11] E-e-e-e-X-C-X\n[00:06.03] Это очень вкусно\n[00:08.07] Charli, Cash\n[00:11.35] Cash, cash, cash, cash, cash\n[00:13.75] I always think about you when I'm high\n[00:17.10] I wanna hear you whisper on the telephone, yeah\n[00:20.46] You call me up and then I'm satisfied\n[00:23.80] I touch myself and then I'm not alone no more\n[00:27.29] I always think about you when I'm high\n[00:30.56] I wanna hear you whisper on the telephone, yeah\n[00:34.08] You call me up and then I'm satisfied\n[00:37.37] Do somethin' special to me\n[00:41.02] Wanna take your picture, you're so delicious\n[00:44.52] Gimme icy vision, the head so clever\n[00:47.97] Can you keep me with ya?\n[00:49.66] Gotta touch your treasure, icy like November\n[00:53.04] The vicious kingdom\n[00:54.76] Wanna take your picture, you're so delicious\n[00:58.11] Like the architecture, I won't forget you\n[01:01.46] Got me in the bathroom, got me in the mirror\n[01:04.88] Puttin' on the pressure\n[01:05.96] (E-e-X-C-X)\n[01:07.85] I always think about you when I'm high\n[01:11.13] I wanna hear you whisper on the telephone, yeah\n[01:14.64] You call me up and then I'm satisfied\n[01:17.90] I touch myself and then I'm not alone no more\n[01:21.59] I always think about you when I'm high\n[01:24.74] I wanna hear you whisper on the telephone, yeah\n[01:28.19] You call me up and then I'm satisfied\n[01:31.43] Do somethin' special to me\n[01:35.78] Oh\n[01:37.51] There's no wifi in forest\n[01:39.26] I found a better connection (Connect)\n[01:41.25] No mirrors nearby, but I see a better reflection\n[01:44.46] I was fucked by the nature, we didn't use protection\n[01:47.72] Made a lot of trees, they are now in a book section\n[01:51.15] No cameras, no lights, but a lot of action (Flash)\n[01:54.43] Yeah, Summer turnin' Winter, c'mon little mama Jackson\n[01:59.02] Slow like water, no Beats by Dre, but beats by your father\n[02:02.74] (Delicious, you're delicious, man)\n[02:05.30] I always think about you when I'm high, yeah, yeah\n[02:08.50] I wanna hear you whisper on the telephone, yeah, yeah\n[02:12.01] You call me up then I'm satisfied, yeah, yeah\n[02:15.62] Touch myself then I'm not alone, yeah\n[02:18.83] I always think about you when I'm high, high, high, high\n[02:21.99] I wanna hear you whisper on the telephone, yeah\n[02:25.68] You call me up and I'm satis-satisfied, yeah, ye-\n[02:28.98] Boom clap, the sound of my heart\n[02:30.96] Алё?\n[02:32.10] Tell it to me, do it straightforward\n[02:33.83] Run it up and then we fast forward\n[02:35.44] Tint the windows on the Range Rover\n[02:37.17] Drive it in like you're the best chauffeur\n[02:39.29] Switch it up, bipolar\n[02:40.58] Colorado, how you take over\n[02:42.20] Got an angel, got me real closer\n[02:43.99] Running it just like a halo, yeah\n[02:46.06] Never let me go, never let me go, no\n[02:49.44] Want a little more, when it rains, it pours, yeah\n[02:53.09] I'ma care for you, run it up and then we fast forward\n[02:55.89] Leave a message here, record on, yeah\n[02:58.73] Yeah\n[02:59.40] I always think about you when I'm high (When I'm high)\n[03:02.66] I wanna hear you whisper on the telephone, yeah (Tele-tele)\n[03:06.19] You call me up and then I'm satisfied\n[03:09.57] I touch myself and then I'm not alone no more (No more)\n[03:12.89] I always think about you when I'm high (When I'm high)\n[03:16.54] I wanna hear you whisper on the telephone, yeah\n[03:19.60] You call me up and then I'm satisfied\n[03:22.01] (Сука, почему ты мне не звонишь, нахуй? Почему ты мне не звонишь, а?)\n[03:23.19] I touch myself and then I'm not alone no more\n[03:26.71] I always think about you when I'm high (When I'm high)\n[03:29.72] I wanna hear you whisper on the telephone, yeah\n[03:33.10] You call me up and then I'm satisfied\n[03:36.63] I touch myself and then I'm not alone no more\n[03:40.25] I always think about you when I'm high\n[03:42.10] I wanna hear you whisper on the telephone, yeah\n[03:46.72] You call me up and then I'm satisfied\n[03:50.02] Do somethin' special to me\n[03:53.61] \n[04:08.65] Delicious featuring Tommy\n[04:15.32] Delicious featuring Tommy\n[04:26.86] Delicious\n[04:27.28] ", 135 - "albumArt": { 136 - "$type": "blob", 137 - "ref": { 138 - "$link": "bafkreicv6hmvtfzmjd6ehqkuc7a32non7x5qsbsvety4gi6ch23rldcbnq" 139 - }, 140 - "mimeType": "image/jpeg", 141 - "size": 241055 142 - }, 143 - "duration": 272753, 144 - "createdAt": "2025-09-12T06:52:34.039Z", 225 + "title": "Chaser", 226 + "artist": "Calibro 35", 227 + "artists": [ 228 + { "name": "Calibro 35", "mbid": "7b6baeda-94ec-4475-9b09-6486a36c8e40" } 229 + ], 230 + "albumArtist": "Calibro 35", 231 + "album": "Jazzploitation", 232 + "duration": 182320, 233 + "trackNumber": 1, 145 234 "discNumber": 1, 146 - "albumArtist": "Charli xcx", 147 - "releaseDate": "2017-12-15T00:00:00.000Z", 148 - "trackNumber": 7, 149 - "copyrightMessage": "℗ 2017 Warner Music UK Limited" 235 + "year": 2024, 236 + "releaseDate": "2024-10-18T00:00:00.000Z", 237 + "tags": ["jazz funk"], 238 + "mbid": "58a46583-dc71-4d4f-bdde-a7323578873e", 239 + "isrc": "ITG582400039", 240 + "albumArtUrl": "https://i.scdn.co/image/ab67616d0000b2739a8e268beabdca126a35b0f6", 241 + "spotifyLink": "https://open.spotify.com/track/3zrtwgbIxpAvUxW0QGb1Lk", 242 + "createdAt": "2026-06-02T13:15:29.378Z" 150 243 } 151 - ``` 244 + ``` 245 + 246 + The `song` and `scrobble` lexicons share the same shape — a `song` is the canonical track record in the user's repo, while a `scrobble` records one play of it.
+1 -1
apps/api/lexicons/album/defs.json
··· 118 118 "type": "array", 119 119 "items": { 120 120 "type": "ref", 121 - "ref": "app.rocksky.song.defs.songViewBasic" 121 + "ref": "app.rocksky.song.defs#songViewBasic" 122 122 } 123 123 } 124 124 }
+1 -1
apps/api/lexicons/player/defs.json
··· 18 18 "type": "array", 19 19 "items": { 20 20 "type": "ref", 21 - "ref": "app.rocksky.song.defs.songViewBasic" 21 + "ref": "app.rocksky.song.defs#songViewBasic" 22 22 } 23 23 } 24 24 }
+6
apps/api/lexicons/scrobble/defs.json
··· 123 123 "type": "string", 124 124 "description": "The SHA256 hash of the scrobble data." 125 125 }, 126 + "liked": { 127 + "type": "boolean" 128 + }, 129 + "likesCount": { 130 + "type": "integer" 131 + }, 126 132 "listeners": { 127 133 "type": "integer", 128 134 "description": "The number of listeners"
+1 -1
apps/api/pkl/defs/album/defs.pkl
··· 141 141 type = "array" 142 142 items = new Ref { 143 143 type = "ref" 144 - ref = "app.rocksky.song.defs.songViewBasic" 144 + ref = "app.rocksky.song.defs#songViewBasic" 145 145 } 146 146 } 147 147 }
+1 -1
apps/api/pkl/defs/player/defs.pkl
··· 19 19 type = "array" 20 20 items = new Ref { 21 21 type = "ref" 22 - ref = "app.rocksky.song.defs.songViewBasic" 22 + ref = "app.rocksky.song.defs#songViewBasic" 23 23 } 24 24 } 25 25 }
+8
apps/api/pkl/defs/scrobble/defs.pkl
··· 144 144 description = "The SHA256 hash of the scrobble data." 145 145 } 146 146 147 + ["liked"] = new BooleanType { 148 + type = "boolean" 149 + } 150 + 151 + ["likesCount"] = new IntegerType { 152 + type = "integer" 153 + } 154 + 147 155 ["listeners"] = new IntegerType { 148 156 type = "integer" 149 157 description = "The number of listeners"
+1
bun.lock
··· 6 6 "name": "rocksky", 7 7 "devDependencies": { 8 8 "@biomejs/biome": "^2.2.3", 9 + "consola": "^3.4.2", 9 10 "prettier": "^3.5.3", 10 11 "turbo": "^2.5.8", 11 12 },
+5
docs/sdks/clojure.mdx
··· 138 138 on the wire — handy for `cond->` chains. 139 139 - **Booleans round-trip.** `:enabled false` is preserved. 140 140 141 + ## Types 142 + 143 + Lexicon-derived schemas (in [malli](https://github.com/metosin/malli) form) are exposed as `rocksky.generated.types/schemas`, a map keyed by `:TypeName` keywords covering every lex `*View*` / `*Record` / `*Input` / `*Output` / `*Params` shape from [the Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons). Regenerate with `bun run lexgen:types` at the repo root. 144 + 145 + 141 146 ## License 142 147 143 148 MIT © Tsiry Sandratraina. Source:
+5
docs/sdks/elixir.mdx
··· 187 187 Rocksky.HTTP.query(client, "app.rocksky.actor.getProfile", did: "alice") 188 188 ``` 189 189 190 + ## Types 191 + 192 + Lexicon-derived structs are available under `Rocksky.Generated.*`, mirroring every lex `*View*` / `*Record` / `*Input` / `*Output` / `*Params` shape from [the Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons). Regenerate with `bun run lexgen:types` at the repo root. 193 + 194 + 190 195 ## License 191 196 192 197 MIT © Tsiry Sandratraina. Source:
+5
docs/sdks/gleam.mdx
··· 167 167 } 168 168 ``` 169 169 170 + ## Types 171 + 172 + Most public model types alias the lexicon-derived shapes in `rocksky/generated/types`, mirroring every lex `*View*` / `*Record` / `*Input` / `*Output` / `*Params` shape from [the Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons). `ApiKey` and `Shout` are hand-written because they carry fields the lexicon does not yet declare. Regenerate with `bun run lexgen:types` at the repo root. 173 + 174 + 170 175 ## License 171 176 172 177 MIT © Tsiry Sandratraina. Source:
+5
docs/sdks/go.mdx
··· 136 136 `*rocksky.Error` carries the HTTP status, XRPC error kind/message, and helpers 137 137 like `IsUnauthorized`, `IsNotFound`, `IsRateLimited`. 138 138 139 + ## Types 140 + 141 + Public model types are derived from the [Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons) and live in `rocksky/gen` (package `gen`). The package-level type aliases in `rocksky/types.go` re-export them under their historical names. Regenerate with `bun run lexgen:types` at the repo root. 142 + 143 + 139 144 ## License 140 145 141 146 MIT © Tsiry Sandratraina. Source:
+5
docs/sdks/kotlin.mdx
··· 143 143 } 144 144 ``` 145 145 146 + ## Types 147 + 148 + Public model types are derived from the [Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons) and live in `app.rocksky.generated`. The `app.rocksky.Models` typealiases re-export them under their historical names; `Profile`, `ApiKey`, and `FollowList` extend with SDK-specific fields. Regenerate with `bun run lexgen:types` at the repo root. 149 + 150 + 146 151 ## License 147 152 148 153 MIT © Tsiry Sandratraina. Source:
+7
docs/sdks/overview.mdx
··· 65 65 | A Clojure web service or REPL workflow | [Clojure](/sdks/clojure) | 66 66 | A typed BEAM app with strict guarantees | [Gleam](/sdks/gleam) | 67 67 68 + ## Lexicon-derived types 69 + 70 + Public model types are generated from the [Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons) 71 + into each SDK and re-exported under their historical SDK names. Regenerate 72 + across all 9 SDKs with `bun run lexgen:types` at the repo root — the generator 73 + lives in [`tools/lexgen/`](https://tangled.org/@rocksky.app/rocksky/blob/main/tools/lexgen). 74 + 68 75 ## Source 69 76 70 77 All SDKs live in the monorepo at
+5
docs/sdks/python.mdx
··· 169 169 await external.aclose() 170 170 ``` 171 171 172 + ## Types 173 + 174 + Public model types are derived from the [Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons) and live in `rocksky.gen.models` (Pydantic) and `rocksky.gen.types` (dataclasses). `rocksky.models` re-exports the Pydantic shapes under their historical SDK names. Regenerate with `bun run lexgen:types` at the repo root. 175 + 176 + 172 177 ## License 173 178 174 179 MIT © Tsiry Sandratraina. Source:
+5
docs/sdks/ruby.mdx
··· 145 145 => {"did"=>"did:plc:...", "handle"=>"tsiry-sandratraina.com", ...} 146 146 ``` 147 147 148 + ## Types 149 + 150 + Lexicon-derived `Struct` types are available under `Rocksky::Generated::*`, mirroring every lex `*View*` / `*Record` / `*Input` / `*Output` / `*Params` shape from [the Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons). Regenerate with `bun run lexgen:types` at the repo root. 151 + 152 + 148 153 ## License 149 154 150 155 MIT © Tsiry Sandratraina. Source:
+5
docs/sdks/rust.mdx
··· 179 179 } 180 180 ``` 181 181 182 + ## Types 183 + 184 + Public model types are derived from the [Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons) and live in `rocksky::generated`. The hand-written `rocksky::models` module re-exports them under their historical SDK names and extends `Profile` / `ApiKey` with fields the lexicon does not yet model. Regenerate with `bun run lexgen:types` at the repo root. 185 + 186 + 182 187 ## License 183 188 184 189 MIT © Tsiry Sandratraina. Source:
+5
docs/sdks/typescript.mdx
··· 249 249 Events: `open`, `close`, `error`, `registered`, `deviceRegistered`, `message`, 250 250 `control`, `raw`. 251 251 252 + ## Types 253 + 254 + Public model types are derived from the [Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons) and live in `src/generated/types.ts`. They are regenerated from `apps/api/lexicons/**/*.json` by running `bun run lexgen:types` at the repo root. 255 + 256 + 252 257 ## License 253 258 254 259 MIT © Tsiry Sandratraina. Source:
+2
package.json
··· 3 3 "version": "0.0.0", 4 4 "devDependencies": { 5 5 "@biomejs/biome": "^2.2.3", 6 + "consola": "^3.4.2", 6 7 "prettier": "^3.5.3", 7 8 "turbo": "^2.5.8" 8 9 }, ··· 15 16 "pkl:eval": "cd apps/api && bun run pkl:eval", 16 17 "pkl:gen": "cd apps/api && bun run pkl:gen", 17 18 "lexgen": "cd apps/api && bun run lexgen", 19 + "lexgen:types": "bun run tools/lexgen/generate.ts", 18 20 "dev:analytics": "cargo run -p rockskyd --release -- analytics serve", 19 21 "dev:connect": "cargo run -p rocksky-connect --release", 20 22 "dev:dropbox": "cargo run -p rockskyd --release -- dropbox serve",
+8
sdk/clojure/CHANGELOG.md
··· 5 5 6 6 ## [Unreleased] 7 7 8 + ## [0.2.0] - 2026-06-02 9 + 10 + ### Added 11 + - Lexicon-derived malli schemas exposed as `rocksky.generated.types/schemas`. 12 + Every lex `*View*` / `*Record` / `*Input` / `*Output` / `*Params` shape is 13 + available as a keyword-keyed entry, regenerated from `apps/api/lexicons/` via 14 + `bun run lexgen:types` at the repo root. 15 + 8 16 ## [0.1.0] - 2026-05-31 9 17 10 18 ### Added
+5
sdk/clojure/README.md
··· 163 163 | `06_error_handling.clj` | Catching `ex-info` from non-2xx | 164 164 | `07_concurrent_requests.clj`| `pmap` across a shared client | 165 165 166 + ## Types 167 + 168 + Lexicon-derived schemas (in [malli](https://github.com/metosin/malli) form) are exposed as `rocksky.generated.types/schemas`, a map keyed by `:TypeName` keywords covering every lex `*View*` / `*Record` / `*Input` / `*Output` / `*Params` shape from [the Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons). Regenerate with `bun run lexgen:types` at the repo root. 169 + 170 + 166 171 ## Development 167 172 168 173 ```bash
+1 -1
sdk/clojure/build.clj
··· 13 13 [deps-deploy.deps-deploy :as dd])) 14 14 15 15 (def lib 'app.rocksky/sdk) 16 - (def version "0.1.1-SNAPSHOT") 16 + (def version "0.2.0") 17 17 (def class-dir "target/classes") 18 18 (def basis (delay (b/create-basis {:project "deps.edn"}))) 19 19 (def jar-file (format "target/%s-%s.jar" (name lib) version))
+2011
sdk/clojure/src/rocksky/generated/types.clj
··· 1 + ;; AUTO-GENERATED FILE -- DO NOT EDIT. 2 + ;; Source: apps/api/lexicons/**/*.json 3 + ;; Regenerate via: bun run lexgen:types 4 + 5 + (ns rocksky.generated.types) 6 + 7 + (def ^{:doc "Lexicon-derived schemas in malli format. Refs are :TypeName keywords."} 8 + schemas 9 + { :ActorArtistViewBasic 10 + [:map 11 + [:id {:optional true} :string] 12 + [:name {:optional true} :string] 13 + [:picture {:optional true} :string] 14 + [:uri {:optional true} :string] 15 + [:user1Rank {:optional true} :int] 16 + [:user2Rank {:optional true} :int] 17 + [:weight {:optional true} :int] 18 + ] 19 + :ActorCompatibilityViewBasic 20 + [:map 21 + [:compatibilityLevel {:optional true} :int] 22 + [:compatibilityPercentage {:optional true} :int] 23 + [:sharedArtists {:optional true} :int] 24 + [:topSharedArtistNames {:optional true} [:vector :string]] 25 + [:topSharedDetailedArtists {:optional true} [:vector :ActorArtistViewBasic]] 26 + [:user1ArtistCount {:optional true} :int] 27 + [:user2ArtistCount {:optional true} :int] 28 + ] 29 + :ActorNeighbourViewBasic 30 + [:map 31 + [:userId {:optional true} :string] 32 + [:did {:optional true} :string] 33 + [:handle {:optional true} :string] 34 + [:displayName {:optional true} :string] 35 + ;; The URL of the actor's avatar image. 36 + [:avatar {:optional true} :string] 37 + ;; The number of artists shared with the actor. 38 + [:sharedArtistsCount {:optional true} :int] 39 + ;; The similarity score with the actor. 40 + [:similarityScore {:optional true} :int] 41 + ;; The top shared artist names with the actor. 42 + [:topSharedArtistNames {:optional true} [:vector :string]] 43 + ;; The top shared artist details with the actor. 44 + [:topSharedArtistsDetails {:optional true} [:vector :ArtistViewBasic]] 45 + ] 46 + :ActorProfileViewBasic 47 + [:map 48 + ;; The unique identifier of the actor. 49 + [:id {:optional true} :string] 50 + ;; The DID of the actor. 51 + [:did {:optional true} :string] 52 + ;; The handle of the actor. 53 + [:handle {:optional true} :string] 54 + ;; The display name of the actor. 55 + [:displayName {:optional true} :string] 56 + ;; The URL of the actor's avatar image. 57 + [:avatar {:optional true} :string] 58 + ;; The date and time when the actor was created. 59 + [:createdAt {:optional true} :string] 60 + ;; The date and time when the actor was last updated. 61 + [:updatedAt {:optional true} :string] 62 + ] 63 + :ActorProfileViewDetailed 64 + [:map 65 + ;; The unique identifier of the actor. 66 + [:id {:optional true} :string] 67 + ;; The DID of the actor. 68 + [:did {:optional true} :string] 69 + ;; The handle of the actor. 70 + [:handle {:optional true} :string] 71 + ;; The display name of the actor. 72 + [:displayName {:optional true} :string] 73 + ;; The URL of the actor's avatar image. 74 + [:avatar {:optional true} :string] 75 + ;; The date and time when the actor was created. 76 + [:createdAt {:optional true} :string] 77 + ;; The date and time when the actor was last updated. 78 + [:updatedAt {:optional true} :string] 79 + ] 80 + :ActorTrackView 81 + [:map 82 + ;; The name of the track. 83 + [:name :string] 84 + ;; The primary artist name. 85 + [:artist :string] 86 + ;; The album name. 87 + [:album {:optional true} :string] 88 + ;; URL of the album cover image. 89 + [:albumCoverUrl {:optional true} :string] 90 + ;; Track duration in milliseconds. 91 + [:durationMs {:optional true} :int] 92 + ;; Music service source, e.g. 'spotify' or 'listenbrainz'. 93 + [:source {:optional true} :string] 94 + ;; MusicBrainz recording ID, if available. 95 + [:recordingMbId {:optional true} :string] 96 + ] 97 + :AddDirectoryToQueueParams 98 + [:map 99 + [:playerId {:optional true} :string] 100 + ;; The directory to add to the queue 101 + [:directory :string] 102 + ;; Position in the queue to insert the directory at, defaults to the end if not specified 103 + [:position {:optional true} :int] 104 + ;; Whether to shuffle the added directory in the queue 105 + [:shuffle {:optional true} :boolean] 106 + ] 107 + :AddItemsToQueueParams 108 + [:map 109 + [:playerId {:optional true} :string] 110 + [:items [:vector :string]] 111 + ;; Position in the queue to insert the items at, defaults to the end if not specified 112 + [:position {:optional true} :int] 113 + ;; Whether to shuffle the added items in the queue 114 + [:shuffle {:optional true} :boolean] 115 + ] 116 + :AlbumRecord 117 + [:map 118 + ;; The title of the album. 119 + [:title :string] 120 + ;; The artist of the album. 121 + [:artist :string] 122 + ;; The duration of the album in seconds. 123 + [:duration {:optional true} :int] 124 + ;; The release date of the album. 125 + [:releaseDate {:optional true} :string] 126 + ;; The year the album was released. 127 + [:year {:optional true} :int] 128 + ;; The genre of the album. 129 + [:genre {:optional true} :string] 130 + ;; The album art of the album. 131 + [:albumArt {:optional true} :BlobRef] 132 + ;; The URL of the album art of the album. 133 + [:albumArtUrl {:optional true} :string] 134 + ;; The tags of the album. 135 + [:tags {:optional true} [:vector :string]] 136 + ;; The YouTube link of the album. 137 + [:youtubeLink {:optional true} :string] 138 + ;; The Spotify link of the album. 139 + [:spotifyLink {:optional true} :string] 140 + ;; The tidal link of the album. 141 + [:tidalLink {:optional true} :string] 142 + ;; The Apple Music link of the album. 143 + [:appleMusicLink {:optional true} :string] 144 + ;; The date and time when the album was created. 145 + [:createdAt :string] 146 + ] 147 + :AlbumViewBasic 148 + [:map 149 + ;; The unique identifier of the album. 150 + [:id {:optional true} :string] 151 + ;; The URI of the album. 152 + [:uri {:optional true} :string] 153 + ;; The title of the album. 154 + [:title {:optional true} :string] 155 + ;; The artist of the album. 156 + [:artist {:optional true} :string] 157 + ;; The URI of the album's artist. 158 + [:artistUri {:optional true} :string] 159 + ;; The year the album was released. 160 + [:year {:optional true} :int] 161 + ;; The URL of the album art image. 162 + [:albumArt {:optional true} :string] 163 + ;; The release date of the album. 164 + [:releaseDate {:optional true} :string] 165 + ;; The SHA256 hash of the album. 166 + [:sha256 {:optional true} :string] 167 + ;; The number of times the album has been played. 168 + [:playCount {:optional true} :int] 169 + ;; The number of unique listeners who have played the album. 170 + [:uniqueListeners {:optional true} :int] 171 + ] 172 + :AlbumViewDetailed 173 + [:map 174 + ;; The unique identifier of the album. 175 + [:id {:optional true} :string] 176 + ;; The URI of the album. 177 + [:uri {:optional true} :string] 178 + ;; The title of the album. 179 + [:title {:optional true} :string] 180 + ;; The artist of the album. 181 + [:artist {:optional true} :string] 182 + ;; The URI of the album's artist. 183 + [:artistUri {:optional true} :string] 184 + ;; The year the album was released. 185 + [:year {:optional true} :int] 186 + ;; The URL of the album art image. 187 + [:albumArt {:optional true} :string] 188 + ;; The release date of the album. 189 + [:releaseDate {:optional true} :string] 190 + ;; The SHA256 hash of the album. 191 + [:sha256 {:optional true} :string] 192 + ;; The number of times the album has been played. 193 + [:playCount {:optional true} :int] 194 + ;; The number of unique listeners who have played the album. 195 + [:uniqueListeners {:optional true} :int] 196 + [:tags {:optional true} [:vector :string]] 197 + [:tracks {:optional true} [:vector :SongViewBasic]] 198 + ] 199 + :ApiKeyView 200 + [:map 201 + ;; The unique identifier of the API key. 202 + [:id {:optional true} :string] 203 + ;; The name of the API key. 204 + [:name {:optional true} :string] 205 + ;; A description for the API key. 206 + [:description {:optional true} :string] 207 + ;; The date and time when the API key was created. 208 + [:createdAt {:optional true} :string] 209 + ] 210 + :ArtistListenerViewBasic 211 + [:map 212 + ;; The unique identifier of the actor. 213 + [:id {:optional true} :string] 214 + ;; The DID of the listener. 215 + [:did {:optional true} :string] 216 + ;; The handle of the listener. 217 + [:handle {:optional true} :string] 218 + ;; The display name of the listener. 219 + [:displayName {:optional true} :string] 220 + ;; The URL of the listener's avatar image. 221 + [:avatar {:optional true} :string] 222 + [:mostListenedSong {:optional true} :ArtistSongViewBasic] 223 + ;; The total number of plays by the listener. 224 + [:totalPlays {:optional true} :int] 225 + ;; The rank of the listener among all listeners of the artist. 226 + [:rank {:optional true} :int] 227 + ] 228 + :ArtistMbid 229 + [:map 230 + ;; The MusicBrainz Identifier (MBID) of the artist. 231 + [:mbid {:optional true} :string] 232 + ;; The name of the artist. 233 + [:name {:optional true} :string] 234 + ] 235 + :ArtistRecentListenerView 236 + [:map 237 + ;; The unique identifier of the listener. 238 + [:id {:optional true} :string] 239 + ;; The DID of the listener. 240 + [:did {:optional true} :string] 241 + ;; The handle of the listener. 242 + [:handle {:optional true} :string] 243 + ;; The display name of the listener. 244 + [:displayName {:optional true} :string] 245 + ;; The URL of the listener's avatar image. 246 + [:avatar {:optional true} :string] 247 + ;; The timestamp of the listener's most recent scrobble of this artist. 248 + [:timestamp {:optional true} :string] 249 + ;; The URI of the listener's most recent scrobble of this artist. 250 + [:scrobbleUri {:optional true} :string] 251 + ] 252 + :ArtistRecord 253 + [:map 254 + ;; The name of the artist. 255 + [:name :string] 256 + ;; The biography of the artist. 257 + [:bio {:optional true} :string] 258 + ;; The picture of the artist. 259 + [:picture {:optional true} :BlobRef] 260 + ;; The URL of the picture of the artist. 261 + [:pictureUrl {:optional true} :string] 262 + ;; The tags of the artist. 263 + [:tags {:optional true} [:vector :string]] 264 + ;; The birth date of the artist. 265 + [:born {:optional true} :string] 266 + ;; The death date of the artist. 267 + [:died {:optional true} :string] 268 + ;; The birth place of the artist. 269 + [:bornIn {:optional true} :string] 270 + ;; The date when the artist was created. 271 + [:createdAt :string] 272 + ] 273 + :ArtistSongViewBasic 274 + [:map 275 + ;; The URI of the song. 276 + [:uri {:optional true} :string] 277 + ;; The title of the song. 278 + [:title {:optional true} :string] 279 + ;; The number of times the song has been played. 280 + [:playCount {:optional true} :int] 281 + ] 282 + :ArtistViewBasic 283 + [:map 284 + ;; The unique identifier of the artist. 285 + [:id {:optional true} :string] 286 + ;; The URI of the artist. 287 + [:uri {:optional true} :string] 288 + ;; The name of the artist. 289 + [:name {:optional true} :string] 290 + ;; The picture of the artist. 291 + [:picture {:optional true} :string] 292 + ;; The SHA256 hash of the artist. 293 + [:sha256 {:optional true} :string] 294 + ;; The number of times the artist has been played. 295 + [:playCount {:optional true} :int] 296 + ;; The number of unique listeners who have played the artist. 297 + [:uniqueListeners {:optional true} :int] 298 + [:tags {:optional true} [:vector :string]] 299 + ] 300 + :ArtistViewDetailed 301 + [:map 302 + ;; The unique identifier of the artist. 303 + [:id {:optional true} :string] 304 + ;; The URI of the artist. 305 + [:uri {:optional true} :string] 306 + ;; The name of the artist. 307 + [:name {:optional true} :string] 308 + ;; The picture of the artist. 309 + [:picture {:optional true} :string] 310 + ;; The SHA256 hash of the artist. 311 + [:sha256 {:optional true} :string] 312 + ;; The number of times the artist has been played. 313 + [:playCount {:optional true} :int] 314 + ;; The number of unique listeners who have played the artist. 315 + [:uniqueListeners {:optional true} :int] 316 + [:tags {:optional true} [:vector :string]] 317 + ] 318 + :ChartsScrobbleViewBasic 319 + [:map 320 + ;; The date of the scrobble. 321 + [:date {:optional true} :string] 322 + ;; The number of scrobbles on this date. 323 + [:count {:optional true} :int] 324 + ] 325 + :ChartsView 326 + [:map 327 + [:scrobbles {:optional true} [:vector :ChartsScrobbleViewBasic]] 328 + ] 329 + :CreateApikeyInput 330 + [:map 331 + ;; The name of the API key. 332 + [:name :string] 333 + ;; A description for the API key. 334 + [:description {:optional true} :string] 335 + ] 336 + :CreatePlaylistParams 337 + [:map 338 + ;; The name of the playlist 339 + [:name :string] 340 + ;; A brief description of the playlist 341 + [:description {:optional true} :string] 342 + ] 343 + :CreateScrobbleInput 344 + [:map 345 + ;; The title of the track being scrobbled 346 + [:title :string] 347 + ;; The artist of the track being scrobbled 348 + [:artist :string] 349 + ;; The album of the track being scrobbled 350 + [:album {:optional true} :string] 351 + ;; The duration of the track in milliseconds 352 + [:duration {:optional true} :int] 353 + ;; The MusicBrainz ID of the track, if available 354 + [:mbId {:optional true} :string] 355 + ;; The International Standard Recording Code (ISRC) of the track, if available 356 + [:isrc {:optional true} :string] 357 + ;; The URL of the album art for the track 358 + [:albumArt {:optional true} :string] 359 + ;; The track number of the track in the album 360 + [:trackNumber {:optional true} :int] 361 + ;; The release date of the track, formatted as YYYY-MM-DD 362 + [:releaseDate {:optional true} :string] 363 + ;; The year the track was released 364 + [:year {:optional true} :int] 365 + ;; The disc number of the track in the album, if applicable 366 + [:discNumber {:optional true} :int] 367 + ;; The lyrics of the track, if available 368 + [:lyrics {:optional true} :string] 369 + ;; The composer of the track, if available 370 + [:composer {:optional true} :string] 371 + ;; The copyright message for the track, if available 372 + [:copyrightMessage {:optional true} :string] 373 + ;; The record label of the track, if available 374 + [:label {:optional true} :string] 375 + ;; The URL of the artist's picture, if available 376 + [:artistPicture {:optional true} :string] 377 + ;; The Spotify link for the track, if available 378 + [:spotifyLink {:optional true} :string] 379 + ;; The Last.fm link for the track, if available 380 + [:lastfmLink {:optional true} :string] 381 + ;; The Tidal link for the track, if available 382 + [:tidalLink {:optional true} :string] 383 + ;; The Apple Music link for the track, if available 384 + [:appleMusicLink {:optional true} :string] 385 + ;; The Youtube link for the track, if available 386 + [:youtubeLink {:optional true} :string] 387 + ;; The Deezer link for the track, if available 388 + [:deezerLink {:optional true} :string] 389 + ;; The timestamp of the scrobble in seconds since epoch (Unix timestamp) 390 + [:timestamp {:optional true} :int] 391 + ] 392 + :CreateShoutInput 393 + [:map 394 + ;; The content of the shout 395 + [:message {:optional true} :string] 396 + ] 397 + :CreateSongInput 398 + [:map 399 + ;; The title of the song 400 + [:title :string] 401 + ;; The artist of the song 402 + [:artist :string] 403 + ;; The album artist of the song, if different from the main artist 404 + [:albumArtist :string] 405 + ;; The album of the song, if applicable 406 + [:album :string] 407 + ;; The duration of the song in seconds 408 + [:duration {:optional true} :int] 409 + ;; The MusicBrainz ID of the song, if available 410 + [:mbId {:optional true} :string] 411 + ;; The International Standard Recording Code (ISRC) of the song, if available 412 + [:isrc {:optional true} :string] 413 + ;; The URL of the album art for the song 414 + [:albumArt {:optional true} :string] 415 + ;; The track number of the song in the album, if applicable 416 + [:trackNumber {:optional true} :int] 417 + ;; The release date of the song, formatted as YYYY-MM-DD 418 + [:releaseDate {:optional true} :string] 419 + ;; The year the song was released 420 + [:year {:optional true} :int] 421 + ;; The disc number of the song in the album, if applicable 422 + [:discNumber {:optional true} :int] 423 + ;; The lyrics of the song, if available 424 + [:lyrics {:optional true} :string] 425 + ] 426 + :DescribeFeedGeneratorOutput 427 + [:map 428 + ;; The DID of the feed generator. 429 + [:did {:optional true} :string] 430 + ;; List of feed URIs generated by this feed generator. 431 + [:feeds {:optional true} [:vector :FeedUriView]] 432 + ] 433 + :DescribeFeedGeneratorParams 434 + [:map] 435 + :DislikeShoutInput 436 + [:map 437 + ;; The unique identifier of the shout to dislike 438 + [:uri {:optional true} :string] 439 + ] 440 + :DislikeSongInput 441 + [:map 442 + ;; The unique identifier of the song to dislike 443 + [:uri {:optional true} :string] 444 + ] 445 + :DownloadFileParams 446 + [:map 447 + ;; The unique identifier of the file to download 448 + [:fileId :string] 449 + ] 450 + :DropboxFileListView 451 + [:map 452 + ;; A list of files in the Dropbox. 453 + [:files {:optional true} [:vector :DropboxFileView]] 454 + ] 455 + :DropboxFileView 456 + [:map 457 + ;; The unique identifier of the file. 458 + [:id {:optional true} :string] 459 + ;; The name of the file. 460 + [:name {:optional true} :string] 461 + ;; The lowercased path of the file. 462 + [:pathLower {:optional true} :string] 463 + ;; The display path of the file. 464 + [:pathDisplay {:optional true} :string] 465 + ;; The last modified date and time of the file on the client. 466 + [:clientModified {:optional true} :string] 467 + ;; The last modified date and time of the file on the server. 468 + [:serverModified {:optional true} :string] 469 + ] 470 + :DropboxTemporaryLinkView 471 + [:map 472 + ;; The temporary link to access the file. 473 + [:link {:optional true} :string] 474 + ] 475 + :FeedGeneratorsView 476 + [:map 477 + [:feeds {:optional true} [:vector :FeedGeneratorView]] 478 + ] 479 + :FeedGeneratorView 480 + [:map 481 + [:id {:optional true} :string] 482 + [:name {:optional true} :string] 483 + [:description {:optional true} :string] 484 + [:uri {:optional true} :string] 485 + [:avatar {:optional true} :string] 486 + [:creator {:optional true} :ActorProfileViewBasic] 487 + ] 488 + :FeedItemView 489 + [:map 490 + [:scrobble {:optional true} :ScrobbleViewBasic] 491 + ] 492 + :FeedRecommendationsView 493 + [:map 494 + [:recommendations {:optional true} [:vector :FeedRecommendationView]] 495 + [:cursor {:optional true} :string] 496 + ] 497 + :FeedRecommendationView 498 + [:map 499 + [:title {:optional true} :string] 500 + [:artist {:optional true} :string] 501 + [:album {:optional true} :string] 502 + [:albumArt {:optional true} :string] 503 + [:trackUri {:optional true} :string] 504 + [:artistUri {:optional true} :string] 505 + [:albumUri {:optional true} :string] 506 + [:genres {:optional true} [:vector :string]] 507 + [:recommendationScore {:optional true} :int] 508 + ;; neighbour | social | serendipity 509 + [:source {:optional true} :string] 510 + [:likesCount {:optional true} :int] 511 + ] 512 + :FeedRecommendedAlbumsView 513 + [:map 514 + [:albums {:optional true} [:vector :FeedRecommendedAlbumView]] 515 + [:cursor {:optional true} :string] 516 + ] 517 + :FeedRecommendedAlbumView 518 + [:map 519 + [:id {:optional true} :string] 520 + [:uri {:optional true} :string] 521 + [:title {:optional true} :string] 522 + [:artist {:optional true} :string] 523 + [:artistUri {:optional true} :string] 524 + [:year {:optional true} :int] 525 + [:albumArt {:optional true} :string] 526 + [:recommendationScore {:optional true} :int] 527 + ;; known-artist | new-artist | serendipity 528 + [:source {:optional true} :string] 529 + ] 530 + :FeedRecommendedArtistsView 531 + [:map 532 + [:artists {:optional true} [:vector :FeedRecommendedArtistView]] 533 + [:cursor {:optional true} :string] 534 + ] 535 + :FeedRecommendedArtistView 536 + [:map 537 + [:id {:optional true} :string] 538 + [:uri {:optional true} :string] 539 + [:name {:optional true} :string] 540 + [:picture {:optional true} :string] 541 + [:genres {:optional true} [:vector :string]] 542 + [:recommendationScore {:optional true} :int] 543 + ;; neighbour | social | serendipity 544 + [:source {:optional true} :string] 545 + ] 546 + :FeedSearchResultsView 547 + [:map 548 + [:hits {:optional true} [:vector [:or :SongViewBasic :AlbumViewBasic :ArtistViewBasic :PlaylistViewBasic :ActorProfileViewBasic]]] 549 + [:processingTimeMs {:optional true} :int] 550 + [:limit {:optional true} :int] 551 + [:offset {:optional true} :int] 552 + [:estimatedTotalHits {:optional true} :int] 553 + ] 554 + :FeedStoriesView 555 + [:map 556 + [:stories {:optional true} [:vector :FeedStoryView]] 557 + ] 558 + :FeedStoryView 559 + [:map 560 + [:album {:optional true} :string] 561 + [:albumArt {:optional true} :string] 562 + [:albumArtist {:optional true} :string] 563 + [:albumUri {:optional true} :string] 564 + [:artist {:optional true} :string] 565 + [:artistUri {:optional true} :string] 566 + [:avatar {:optional true} :string] 567 + [:createdAt {:optional true} :string] 568 + [:did {:optional true} :string] 569 + [:handle {:optional true} :string] 570 + [:id {:optional true} :string] 571 + [:title {:optional true} :string] 572 + [:trackId {:optional true} :string] 573 + [:trackUri {:optional true} :string] 574 + [:uri {:optional true} :string] 575 + ] 576 + :FeedUriView 577 + [:map 578 + ;; The feed URI. 579 + [:uri {:optional true} :string] 580 + ] 581 + :FeedView 582 + [:map 583 + [:feed {:optional true} [:vector :FeedItemView]] 584 + ;; The pagination cursor for the next set of results. 585 + [:cursor {:optional true} :string] 586 + ] 587 + :FollowAccountOutput 588 + [:map 589 + [:subject :ActorProfileViewBasic] 590 + [:followers [:vector :ActorProfileViewBasic]] 591 + ;; A cursor value to pass to subsequent calls to get the next page of results. 592 + [:cursor {:optional true} :string] 593 + ] 594 + :FollowAccountParams 595 + [:map 596 + [:account :string] 597 + ] 598 + :FollowRecord 599 + [:map 600 + [:createdAt :string] 601 + [:subject :string] 602 + [:via {:optional true} :StrongRef] 603 + ] 604 + :GeneratorRecord 605 + [:map 606 + [:did :string] 607 + [:avatar {:optional true} :BlobRef] 608 + [:displayName :string] 609 + [:description {:optional true} :string] 610 + [:createdAt :string] 611 + ] 612 + :GetActorAlbumsOutput 613 + [:map 614 + [:albums {:optional true} [:vector :AlbumViewBasic]] 615 + ] 616 + :GetActorAlbumsParams 617 + [:map 618 + ;; The DID or handle of the actor 619 + [:did :string] 620 + ;; The maximum number of albums to return 621 + [:limit {:optional true} :int] 622 + ;; The offset for pagination 623 + [:offset {:optional true} :int] 624 + ;; The start date to filter albums from (ISO 8601 format) 625 + [:startDate {:optional true} :string] 626 + ;; The end date to filter albums to (ISO 8601 format) 627 + [:endDate {:optional true} :string] 628 + ] 629 + :GetActorArtistsOutput 630 + [:map 631 + [:artists {:optional true} [:vector :ArtistViewBasic]] 632 + ] 633 + :GetActorArtistsParams 634 + [:map 635 + ;; The DID or handle of the actor 636 + [:did :string] 637 + ;; The maximum number of albums to return 638 + [:limit {:optional true} :int] 639 + ;; The offset for pagination 640 + [:offset {:optional true} :int] 641 + ;; The start date to filter albums from (ISO 8601 format) 642 + [:startDate {:optional true} :string] 643 + ;; The end date to filter albums to (ISO 8601 format) 644 + [:endDate {:optional true} :string] 645 + ] 646 + :GetActorCompatibilityOutput 647 + [:map 648 + [:compatibility {:optional true} :ActorCompatibilityViewBasic] 649 + ] 650 + :GetActorCompatibilityParams 651 + [:map 652 + ;; DID or handle to get compatibility for 653 + [:did :string] 654 + ] 655 + :GetActorLovedSongsOutput 656 + [:map 657 + [:tracks {:optional true} [:vector :SongViewBasic]] 658 + ] 659 + :GetActorLovedSongsParams 660 + [:map 661 + ;; The DID or handle of the actor 662 + [:did :string] 663 + ;; The maximum number of albums to return 664 + [:limit {:optional true} :int] 665 + ;; The offset for pagination 666 + [:offset {:optional true} :int] 667 + ] 668 + :GetActorNeighboursOutput 669 + [:map 670 + [:neighbours {:optional true} [:vector :ActorNeighbourViewBasic]] 671 + ] 672 + :GetActorNeighboursParams 673 + [:map 674 + ;; The DID or handle of the actor 675 + [:did :string] 676 + ] 677 + :GetActorPlaylistsOutput 678 + [:map 679 + [:playlists {:optional true} [:vector :PlaylistViewBasic]] 680 + ] 681 + :GetActorPlaylistsParams 682 + [:map 683 + ;; The DID or handle of the actor 684 + [:did :string] 685 + ;; The maximum number of albums to return 686 + [:limit {:optional true} :int] 687 + ;; The offset for pagination 688 + [:offset {:optional true} :int] 689 + ] 690 + :GetActorScrobblesOutput 691 + [:map 692 + [:scrobbles {:optional true} [:vector :ScrobbleViewBasic]] 693 + ] 694 + :GetActorScrobblesParams 695 + [:map 696 + ;; The DID or handle of the actor 697 + [:did :string] 698 + ;; The maximum number of albums to return 699 + [:limit {:optional true} :int] 700 + ;; The offset for pagination 701 + [:offset {:optional true} :int] 702 + ] 703 + :GetActorSongsOutput 704 + [:map 705 + [:songs {:optional true} [:vector :SongViewBasic]] 706 + ] 707 + :GetActorSongsParams 708 + [:map 709 + ;; The DID or handle of the actor 710 + [:did :string] 711 + ;; The maximum number of albums to return 712 + [:limit {:optional true} :int] 713 + ;; The offset for pagination 714 + [:offset {:optional true} :int] 715 + ;; The start date to filter albums from (ISO 8601 format) 716 + [:startDate {:optional true} :string] 717 + ;; The end date to filter albums to (ISO 8601 format) 718 + [:endDate {:optional true} :string] 719 + ] 720 + :GetAlbumParams 721 + [:map 722 + ;; The URI of the album to retrieve. 723 + [:uri :string] 724 + ] 725 + :GetAlbumRecommendationsParams 726 + [:map 727 + ;; DID or handle of the user to recommend for. 728 + [:did :string] 729 + [:limit {:optional true} :int] 730 + ] 731 + :GetAlbumShoutsOutput 732 + [:map 733 + [:shouts {:optional true} [:vector :any]] 734 + ] 735 + :GetAlbumShoutsParams 736 + [:map 737 + ;; The unique identifier of the album to retrieve shouts for 738 + [:uri :string] 739 + ;; The maximum number of shouts to return 740 + [:limit {:optional true} :int] 741 + ;; The number of shouts to skip before starting to collect the result set 742 + [:offset {:optional true} :int] 743 + ] 744 + :GetAlbumsOutput 745 + [:map 746 + [:albums {:optional true} [:vector :AlbumViewBasic]] 747 + ] 748 + :GetAlbumsParams 749 + [:map 750 + ;; The maximum number of albums to return 751 + [:limit {:optional true} :int] 752 + ;; The offset for pagination 753 + [:offset {:optional true} :int] 754 + ;; The genre to filter artists by 755 + [:genre {:optional true} :string] 756 + ] 757 + :GetAlbumTracksOutput 758 + [:map 759 + [:tracks {:optional true} [:vector :SongViewBasic]] 760 + ] 761 + :GetAlbumTracksParams 762 + [:map 763 + ;; The URI of the album to retrieve tracks from 764 + [:uri :string] 765 + ] 766 + :GetApikeysOutput 767 + [:map 768 + [:apiKeys {:optional true} [:vector :any]] 769 + ] 770 + :GetApikeysParams 771 + [:map 772 + ;; The number of API keys to skip before starting to collect the result set. 773 + [:offset {:optional true} :int] 774 + ;; The number of API keys to return per page. 775 + [:limit {:optional true} :int] 776 + ] 777 + :GetArtistAlbumsOutput 778 + [:map 779 + [:albums {:optional true} [:vector :AlbumViewBasic]] 780 + ] 781 + :GetArtistAlbumsParams 782 + [:map 783 + ;; The URI of the artist to retrieve albums from 784 + [:uri :string] 785 + ] 786 + :GetArtistListenersOutput 787 + [:map 788 + [:listeners {:optional true} [:vector :ArtistListenerViewBasic]] 789 + ] 790 + :GetArtistListenersParams 791 + [:map 792 + ;; The URI of the artist to retrieve listeners from 793 + [:uri :string] 794 + ;; Number of items to skip before returning results 795 + [:offset {:optional true} :int] 796 + ;; Maximum number of results to return 797 + [:limit {:optional true} :int] 798 + ] 799 + :GetArtistParams 800 + [:map 801 + ;; The URI of the artist to retrieve details from 802 + [:uri :string] 803 + ] 804 + :GetArtistRecentListenersOutput 805 + [:map 806 + [:listeners {:optional true} [:vector :ArtistRecentListenerView]] 807 + ] 808 + :GetArtistRecentListenersParams 809 + [:map 810 + ;; The URI of the artist to retrieve recent listeners from 811 + [:uri :string] 812 + ;; Number of items to skip before returning results 813 + [:offset {:optional true} :int] 814 + ;; Maximum number of results to return 815 + [:limit {:optional true} :int] 816 + ] 817 + :GetArtistRecommendationsParams 818 + [:map 819 + ;; DID or handle of the user to recommend for. 820 + [:did :string] 821 + [:limit {:optional true} :int] 822 + ] 823 + :GetArtistShoutsOutput 824 + [:map 825 + [:shouts {:optional true} [:vector :any]] 826 + ] 827 + :GetArtistShoutsParams 828 + [:map 829 + ;; The URI of the artist to retrieve shouts for 830 + [:uri :string] 831 + ;; The maximum number of shouts to return 832 + [:limit {:optional true} :int] 833 + ;; The number of shouts to skip before starting to collect the result set 834 + [:offset {:optional true} :int] 835 + ] 836 + :GetArtistsOutput 837 + [:map 838 + [:artists {:optional true} [:vector :ArtistViewBasic]] 839 + ] 840 + :GetArtistsParams 841 + [:map 842 + ;; The maximum number of artists to return 843 + [:limit {:optional true} :int] 844 + ;; The offset for pagination 845 + [:offset {:optional true} :int] 846 + ;; The names of the artists to return 847 + [:names {:optional true} :string] 848 + ;; The genre to filter artists by 849 + [:genre {:optional true} :string] 850 + ] 851 + :GetArtistTracksOutput 852 + [:map 853 + [:tracks {:optional true} [:vector :SongViewBasic]] 854 + ] 855 + :GetArtistTracksParams 856 + [:map 857 + ;; The URI of the artist to retrieve albums from 858 + [:uri {:optional true} :string] 859 + ;; The maximum number of tracks to return 860 + [:limit {:optional true} :int] 861 + ;; The offset for pagination 862 + [:offset {:optional true} :int] 863 + ] 864 + :GetCurrentlyPlayingParams 865 + [:map 866 + [:playerId {:optional true} :string] 867 + ;; Handle or DID of the actor to retrieve the currently playing track for. If not provided, defaults to the current user. 868 + [:actor {:optional true} :string] 869 + ] 870 + :GetFeedGeneratorOutput 871 + [:map 872 + [:view {:optional true} :FeedGeneratorView] 873 + ] 874 + :GetFeedGeneratorParams 875 + [:map 876 + ;; AT-URI of the feed generator record. 877 + [:feed :string] 878 + ] 879 + :GetFeedGeneratorsParams 880 + [:map 881 + ;; The maximum number of feed generators to return. 882 + [:size {:optional true} :int] 883 + ] 884 + :GetFeedParams 885 + [:map 886 + ;; The feed URI. 887 + [:feed :string] 888 + ;; The maximum number of scrobbles to return 889 + [:limit {:optional true} :int] 890 + ;; The cursor for pagination 891 + [:cursor {:optional true} :string] 892 + ] 893 + :GetFeedSkeletonOutput 894 + [:map 895 + [:scrobbles {:optional true} [:vector :ScrobbleViewBasic]] 896 + ;; The pagination cursor for the next set of results. 897 + [:cursor {:optional true} :string] 898 + ] 899 + :GetFeedSkeletonParams 900 + [:map 901 + ;; The feed URI. 902 + [:feed :string] 903 + ;; The maximum number of scrobbles to return 904 + [:limit {:optional true} :int] 905 + ;; The offset for pagination 906 + [:offset {:optional true} :int] 907 + ;; The pagination cursor. 908 + [:cursor {:optional true} :string] 909 + ] 910 + :GetFileParams 911 + [:map 912 + ;; The unique identifier of the file to retrieve 913 + [:fileId :string] 914 + ] 915 + :GetFilesParams 916 + [:map 917 + ;; Path to the Dropbox folder or root directory 918 + [:at {:optional true} :string] 919 + ] 920 + :GetFollowersOutput 921 + [:map 922 + [:subject :ActorProfileViewBasic] 923 + [:followers [:vector :ActorProfileViewBasic]] 924 + ;; A cursor value to pass to subsequent calls to get the next page of results. 925 + [:cursor {:optional true} :string] 926 + ;; The total number of followers. 927 + [:count {:optional true} :int] 928 + ] 929 + :GetFollowersParams 930 + [:map 931 + [:actor :string] 932 + [:limit {:optional true} :int] 933 + ;; If provided, filters the followers to only include those with DIDs in this list. 934 + [:dids {:optional true} [:vector :string]] 935 + [:cursor {:optional true} :string] 936 + ] 937 + :GetFollowsOutput 938 + [:map 939 + [:subject :ActorProfileViewBasic] 940 + [:follows [:vector :ActorProfileViewBasic]] 941 + ;; A cursor value to pass to subsequent calls to get the next page of results. 942 + [:cursor {:optional true} :string] 943 + ;; The total number of follows. 944 + [:count {:optional true} :int] 945 + ] 946 + :GetFollowsParams 947 + [:map 948 + [:actor :string] 949 + [:limit {:optional true} :int] 950 + ;; If provided, filters the follows to only include those with DIDs in this list. 951 + [:dids {:optional true} [:vector :string]] 952 + [:cursor {:optional true} :string] 953 + ] 954 + :GetKnownFollowersOutput 955 + [:map 956 + [:subject :ActorProfileViewBasic] 957 + [:followers [:vector :ActorProfileViewBasic]] 958 + ;; A cursor value to pass to subsequent calls to get the next page of results. 959 + [:cursor {:optional true} :string] 960 + ] 961 + :GetKnownFollowersParams 962 + [:map 963 + [:actor :string] 964 + [:limit {:optional true} :int] 965 + [:cursor {:optional true} :string] 966 + ] 967 + :GetMetadataParams 968 + [:map 969 + ;; Path to the file or folder in Dropbox 970 + [:path :string] 971 + ] 972 + :GetMirrorSourcesOutput 973 + [:map 974 + [:sources [:vector :MirrorSourceView]] 975 + ] 976 + :GetMirrorSourcesParams 977 + [:map] 978 + :GetPlaybackQueueParams 979 + [:map 980 + [:playerId {:optional true} :string] 981 + ] 982 + :GetPlaylistParams 983 + [:map 984 + ;; The URI of the playlist to retrieve. 985 + [:uri :string] 986 + ] 987 + :GetPlaylistsOutput 988 + [:map 989 + [:playlists {:optional true} [:vector :PlaylistViewBasic]] 990 + ] 991 + :GetPlaylistsParams 992 + [:map 993 + ;; The maximum number of playlists to return. 994 + [:limit {:optional true} :int] 995 + ;; The offset for pagination, used to skip a number of playlists. 996 + [:offset {:optional true} :int] 997 + ] 998 + :GetProfileParams 999 + [:map 1000 + ;; The DID or handle of the actor 1001 + [:did {:optional true} :string] 1002 + ] 1003 + :GetProfileShoutsOutput 1004 + [:map 1005 + [:shouts {:optional true} [:vector :any]] 1006 + ] 1007 + :GetProfileShoutsParams 1008 + [:map 1009 + ;; The DID or handle of the actor 1010 + [:did :string] 1011 + ;; The offset for pagination 1012 + [:offset {:optional true} :int] 1013 + ;; The maximum number of shouts to return 1014 + [:limit {:optional true} :int] 1015 + ] 1016 + :GetRecommendationsParams 1017 + [:map 1018 + ;; DID or handle of the user to recommend for. 1019 + [:did :string] 1020 + [:limit {:optional true} :int] 1021 + ] 1022 + :GetScrobbleParams 1023 + [:map 1024 + ;; The unique identifier of the scrobble 1025 + [:uri :string] 1026 + ] 1027 + :GetScrobblesChartParams 1028 + [:map 1029 + ;; The DID or handle of the actor 1030 + [:did {:optional true} :string] 1031 + ;; The URI of the artist to filter by 1032 + [:artisturi {:optional true} :string] 1033 + ;; The URI of the album to filter by 1034 + [:albumuri {:optional true} :string] 1035 + ;; The URI of the track to filter by 1036 + [:songuri {:optional true} :string] 1037 + ;; The genre to filter by 1038 + [:genre {:optional true} :string] 1039 + ;; Start date (ISO 8601). Defaults to 6 months ago. 1040 + [:from {:optional true} :string] 1041 + ;; End date (ISO 8601). Defaults to today. 1042 + [:to {:optional true} :string] 1043 + ] 1044 + :GetScrobblesOutput 1045 + [:map 1046 + [:scrobbles {:optional true} [:vector :ScrobbleViewBasic]] 1047 + ] 1048 + :GetScrobblesParams 1049 + [:map 1050 + ;; The DID or handle of the actor 1051 + [:did {:optional true} :string] 1052 + ;; If true, only return scrobbles from actors the viewer is following. 1053 + [:following {:optional true} :boolean] 1054 + ;; The maximum number of scrobbles to return 1055 + [:limit {:optional true} :int] 1056 + ;; The offset for pagination 1057 + [:offset {:optional true} :int] 1058 + ] 1059 + :GetShoutRepliesOutput 1060 + [:map 1061 + [:shouts {:optional true} [:vector :any]] 1062 + ] 1063 + :GetShoutRepliesParams 1064 + [:map 1065 + ;; The URI of the shout to retrieve replies for 1066 + [:uri :string] 1067 + ;; The maximum number of shouts to return 1068 + [:limit {:optional true} :int] 1069 + ;; The number of shouts to skip before starting to collect the result set 1070 + [:offset {:optional true} :int] 1071 + ] 1072 + :GetSongParams 1073 + [:map 1074 + ;; The AT-URI of the song to retrieve 1075 + [:uri {:optional true} :string] 1076 + ;; The MusicBrainz ID of the song to retrieve 1077 + [:mbid {:optional true} :string] 1078 + ;; The International Standard Recording Code (ISRC) of the song to retrieve 1079 + [:isrc {:optional true} :string] 1080 + ;; The Spotify track ID of the song to retrieve (resolved internally to the Spotify track URL) 1081 + [:spotifyId {:optional true} :string] 1082 + ] 1083 + :GetSongRecentListenersOutput 1084 + [:map 1085 + [:listeners {:optional true} [:vector :SongRecentListenerView]] 1086 + ] 1087 + :GetSongRecentListenersParams 1088 + [:map 1089 + ;; The URI of the song to retrieve recent listeners from 1090 + [:uri :string] 1091 + ;; Number of items to skip before returning results 1092 + [:offset {:optional true} :int] 1093 + ;; Maximum number of results to return 1094 + [:limit {:optional true} :int] 1095 + ] 1096 + :GetSongsOutput 1097 + [:map 1098 + [:songs {:optional true} [:vector :SongViewBasic]] 1099 + ] 1100 + :GetSongsParams 1101 + [:map 1102 + ;; The maximum number of songs to return 1103 + [:limit {:optional true} :int] 1104 + ;; The offset for pagination 1105 + [:offset {:optional true} :int] 1106 + ;; The genre to filter artists by 1107 + [:genre {:optional true} :string] 1108 + ;; Filter songs by MusicBrainz ID 1109 + [:mbid {:optional true} :string] 1110 + ;; Filter songs by International Standard Recording Code (ISRC) 1111 + [:isrc {:optional true} :string] 1112 + ;; Filter songs by Spotify track ID (resolved internally to the Spotify track URL) 1113 + [:spotifyId {:optional true} :string] 1114 + ] 1115 + :GetStatsParams 1116 + [:map 1117 + ;; The DID or handle of the user to get stats for. 1118 + [:did :string] 1119 + ] 1120 + :GetStoriesParams 1121 + [:map 1122 + ;; The maximum number of stories to return. 1123 + [:size {:optional true} :int] 1124 + ] 1125 + :GetTemporaryLinkParams 1126 + [:map 1127 + ;; Path to the file in Dropbox 1128 + [:path :string] 1129 + ] 1130 + :GetTopArtistsOutput 1131 + [:map 1132 + [:artists {:optional true} [:vector :ArtistViewBasic]] 1133 + ] 1134 + :GetTopArtistsParams 1135 + [:map 1136 + ;; The maximum number of artists to return 1137 + [:limit {:optional true} :int] 1138 + ;; The offset for pagination 1139 + [:offset {:optional true} :int] 1140 + ;; The start date to filter artists from (ISO 8601 format) 1141 + [:startDate {:optional true} :string] 1142 + ;; The end date to filter artists to (ISO 8601 format) 1143 + [:endDate {:optional true} :string] 1144 + ] 1145 + :GetTopTracksOutput 1146 + [:map 1147 + [:tracks {:optional true} [:vector :SongViewBasic]] 1148 + ] 1149 + :GetTopTracksParams 1150 + [:map 1151 + ;; The maximum number of tracks to return 1152 + [:limit {:optional true} :int] 1153 + ;; The offset for pagination 1154 + [:offset {:optional true} :int] 1155 + ;; The start date to filter tracks from (ISO 8601 format) 1156 + [:startDate {:optional true} :string] 1157 + ;; The end date to filter tracks to (ISO 8601 format) 1158 + [:endDate {:optional true} :string] 1159 + ] 1160 + :GetTrackShoutsOutput 1161 + [:map 1162 + [:shouts {:optional true} [:vector :any]] 1163 + ] 1164 + :GetTrackShoutsParams 1165 + [:map 1166 + ;; The URI of the track to retrieve shouts for 1167 + [:uri :string] 1168 + ] 1169 + :GetWrappedParams 1170 + [:map 1171 + ;; The DID or handle of the user 1172 + [:did :string] 1173 + ;; The year to get wrapped stats for (defaults to current year) 1174 + [:year {:optional true} :int] 1175 + ] 1176 + :GoogledriveFileListView 1177 + [:map 1178 + [:files {:optional true} [:vector :GoogledriveFileView]] 1179 + ] 1180 + :GoogledriveFileView 1181 + [:map 1182 + ;; The unique identifier of the file. 1183 + [:id {:optional true} :string] 1184 + ] 1185 + ;; indicates that a handle or DID could not be resolved 1186 + :GraphNotFoundActor 1187 + [:map 1188 + [:actor :string] 1189 + [:notFound :boolean] 1190 + ] 1191 + :GraphRelationship 1192 + [:map 1193 + [:did :string] 1194 + ;; if the actor follows this DID, this is the AT-URI of the follow record 1195 + [:following {:optional true} :string] 1196 + ;; if the actor is followed by this DID, contains the AT-URI of the follow record 1197 + [:followedBy {:optional true} :string] 1198 + ] 1199 + :InsertDirectoryParams 1200 + [:map 1201 + ;; The URI of the playlist to start 1202 + [:uri :string] 1203 + ;; The directory (id) to insert into the playlist 1204 + [:directory :string] 1205 + ;; The position in the playlist to insert the directory at, if not specified, the directory will be appended 1206 + [:position {:optional true} :int] 1207 + ] 1208 + :InsertFilesParams 1209 + [:map 1210 + ;; The URI of the playlist to start 1211 + [:uri :string] 1212 + [:files [:vector :string]] 1213 + ;; The position in the playlist to insert the files at, if not specified, files will be appended 1214 + [:position {:optional true} :int] 1215 + ] 1216 + :LikeRecord 1217 + [:map 1218 + ;; The date when the like was created. 1219 + [:createdAt :string] 1220 + [:subject :StrongRef] 1221 + ] 1222 + :LikeShoutInput 1223 + [:map 1224 + ;; The unique identifier of the shout to like 1225 + [:uri {:optional true} :string] 1226 + ] 1227 + :LikeSongInput 1228 + [:map 1229 + ;; The unique identifier of the song to like 1230 + [:uri {:optional true} :string] 1231 + ] 1232 + :MatchSongParams 1233 + [:map 1234 + ;; The title of the song to retrieve 1235 + [:title :string] 1236 + ;; The artist of the song to retrieve 1237 + [:artist :string] 1238 + ;; Optional MusicBrainz recording ID to anchor the match 1239 + [:mbId {:optional true} :string] 1240 + ;; Optional International Standard Recording Code (ISRC) to anchor the match 1241 + [:isrc {:optional true} :string] 1242 + ] 1243 + :MirrorSourceView 1244 + [:map 1245 + ;; One of: lastfm, listenbrainz, tealfm 1246 + [:provider :string] 1247 + ;; Whether scrobbles from this source are being mirrored into Rocksky. 1248 + [:enabled :boolean] 1249 + ;; Username on the external service (Last.fm / ListenBrainz). Null for Teal.fm. 1250 + [:externalUsername {:optional true} :string] 1251 + ;; True when an API key is stored. Last.fm/ListenBrainz only; always false for Teal.fm. 1252 + [:hasCredentials :boolean] 1253 + ;; The last time the mirror process successfully polled this source. 1254 + [:lastPolledAt {:optional true} :string] 1255 + ;; Watermark — scrobbles from the external service older than this are skipped. 1256 + [:lastScrobbleSeenAt {:optional true} :string] 1257 + ] 1258 + :NextParams 1259 + [:map 1260 + [:playerId {:optional true} :string] 1261 + ] 1262 + :PauseParams 1263 + [:map 1264 + [:playerId {:optional true} :string] 1265 + ] 1266 + :PlayDirectoryParams 1267 + [:map 1268 + [:playerId {:optional true} :string] 1269 + [:directoryId :string] 1270 + [:shuffle {:optional true} :boolean] 1271 + [:recurse {:optional true} :boolean] 1272 + [:position {:optional true} :int] 1273 + ] 1274 + :PlayerCurrentlyPlayingViewDetailed 1275 + [:map 1276 + ;; The title of the currently playing track 1277 + [:title {:optional true} :string] 1278 + ] 1279 + :PlayerPlaybackQueueViewDetailed 1280 + [:map 1281 + [:tracks {:optional true} [:vector :SongViewBasic]] 1282 + ] 1283 + :PlayFileParams 1284 + [:map 1285 + [:playerId {:optional true} :string] 1286 + [:fileId :string] 1287 + ] 1288 + :PlaylistItemRecord 1289 + [:map 1290 + [:subject :StrongRef] 1291 + ;; The date the playlist was created. 1292 + [:createdAt :string] 1293 + [:track :SongViewBasic] 1294 + ;; The order of the item in the playlist. 1295 + [:order :int] 1296 + ] 1297 + :PlaylistRecord 1298 + [:map 1299 + ;; The name of the playlist. 1300 + [:name :string] 1301 + ;; The playlist description. 1302 + [:description {:optional true} :string] 1303 + ;; The picture of the playlist. 1304 + [:picture {:optional true} :BlobRef] 1305 + ;; The URL of the picture of the artist. 1306 + [:pictureUrl {:optional true} :string] 1307 + ;; The date the playlist was created. 1308 + [:createdAt :string] 1309 + ;; The Spotify link of the playlist. 1310 + [:spotifyLink {:optional true} :string] 1311 + ;; The Tidal link of the playlist. 1312 + [:tidalLink {:optional true} :string] 1313 + ;; The YouTube link of the playlist. 1314 + [:youtubeLink {:optional true} :string] 1315 + ;; The Apple Music link of the playlist. 1316 + [:appleMusicLink {:optional true} :string] 1317 + ] 1318 + ;; Basic view of a playlist, including its metadata 1319 + :PlaylistViewBasic 1320 + [:map 1321 + ;; The unique identifier of the playlist. 1322 + [:id {:optional true} :string] 1323 + ;; The title of the playlist. 1324 + [:title {:optional true} :string] 1325 + ;; The URI of the playlist. 1326 + [:uri {:optional true} :string] 1327 + ;; The DID of the curator of the playlist. 1328 + [:curatorDid {:optional true} :string] 1329 + ;; The handle of the curator of the playlist. 1330 + [:curatorHandle {:optional true} :string] 1331 + ;; The name of the curator of the playlist. 1332 + [:curatorName {:optional true} :string] 1333 + ;; The URL of the avatar image of the curator. 1334 + [:curatorAvatarUrl {:optional true} :string] 1335 + ;; A description of the playlist. 1336 + [:description {:optional true} :string] 1337 + ;; The URL of the cover image for the playlist. 1338 + [:coverImageUrl {:optional true} :string] 1339 + ;; The date and time when the playlist was created. 1340 + [:createdAt {:optional true} :string] 1341 + ;; The number of tracks in the playlist. 1342 + [:trackCount {:optional true} :int] 1343 + ] 1344 + ;; Detailed view of a playlist, including its tracks and metadata 1345 + :PlaylistViewDetailed 1346 + [:map 1347 + ;; The unique identifier of the playlist. 1348 + [:id {:optional true} :string] 1349 + ;; The title of the playlist. 1350 + [:title {:optional true} :string] 1351 + ;; The URI of the playlist. 1352 + [:uri {:optional true} :string] 1353 + ;; The DID of the curator of the playlist. 1354 + [:curatorDid {:optional true} :string] 1355 + ;; The handle of the curator of the playlist. 1356 + [:curatorHandle {:optional true} :string] 1357 + ;; The name of the curator of the playlist. 1358 + [:curatorName {:optional true} :string] 1359 + ;; The URL of the avatar image of the curator. 1360 + [:curatorAvatarUrl {:optional true} :string] 1361 + ;; A description of the playlist. 1362 + [:description {:optional true} :string] 1363 + ;; The URL of the cover image for the playlist. 1364 + [:coverImageUrl {:optional true} :string] 1365 + ;; The date and time when the playlist was created. 1366 + [:createdAt {:optional true} :string] 1367 + ;; A list of tracks in the playlist. 1368 + [:tracks {:optional true} [:vector :SongViewBasic]] 1369 + ] 1370 + :PlayParams 1371 + [:map 1372 + [:playerId {:optional true} :string] 1373 + ] 1374 + :PreviousParams 1375 + [:map 1376 + [:playerId {:optional true} :string] 1377 + ] 1378 + :ProfileRecord 1379 + [:map 1380 + [:displayName {:optional true} :string] 1381 + ;; Free-form profile description text. 1382 + [:description {:optional true} :string] 1383 + ;; Small image to be displayed next to posts from account. AKA, 'profile picture' 1384 + [:avatar {:optional true} :BlobRef] 1385 + ;; Larger horizontal image to display behind profile view. 1386 + [:banner {:optional true} :BlobRef] 1387 + ;; Self-label values, specific to the Bluesky application, on the overall account. 1388 + [:labels {:optional true} [:or :any]] 1389 + [:joinedViaStarterPack {:optional true} :StrongRef] 1390 + [:createdAt {:optional true} :string] 1391 + ] 1392 + :PutMirrorSourceInput 1393 + [:map 1394 + ;; One of: lastfm, listenbrainz, tealfm 1395 + [:provider :string] 1396 + ;; Enable or disable mirroring for this provider. 1397 + [:enabled {:optional true} :boolean] 1398 + ;; External username (Last.fm / ListenBrainz). Required when enabling those providers. Ignored for Teal.fm. 1399 + [:externalUsername {:optional true} :string] 1400 + ;; API key / token to be encrypted at rest. Omit to leave the existing key unchanged. Pass an empty string to clear it. 1401 + [:apiKey {:optional true} :string] 1402 + ] 1403 + :RadioRecord 1404 + [:map 1405 + ;; The name of the radio station. 1406 + [:name :string] 1407 + ;; The URL of the radio station. 1408 + [:url :string] 1409 + ;; A description of the radio station. 1410 + [:description {:optional true} :string] 1411 + ;; The genre of the radio station. 1412 + [:genre {:optional true} :string] 1413 + ;; The logo of the radio station. 1414 + [:logo {:optional true} :BlobRef] 1415 + ;; The website of the radio station. 1416 + [:website {:optional true} :string] 1417 + ;; The date when the radio station was created. 1418 + [:createdAt :string] 1419 + ] 1420 + :RadioViewBasic 1421 + [:map 1422 + ;; The unique identifier of the radio. 1423 + [:id {:optional true} :string] 1424 + ;; The name of the radio. 1425 + [:name {:optional true} :string] 1426 + ;; A brief description of the radio. 1427 + [:description {:optional true} :string] 1428 + ;; The date and time when the radio was created. 1429 + [:createdAt {:optional true} :string] 1430 + ] 1431 + :RadioViewDetailed 1432 + [:map 1433 + ;; The unique identifier of the radio. 1434 + [:id {:optional true} :string] 1435 + ;; The name of the radio. 1436 + [:name {:optional true} :string] 1437 + ;; A brief description of the radio. 1438 + [:description {:optional true} :string] 1439 + ;; The website of the radio. 1440 + [:website {:optional true} :string] 1441 + ;; The streaming URL of the radio. 1442 + [:url {:optional true} :string] 1443 + ;; The genre of the radio. 1444 + [:genre {:optional true} :string] 1445 + ;; The logo of the radio station. 1446 + [:logo {:optional true} :string] 1447 + ;; The date and time when the radio was created. 1448 + [:createdAt {:optional true} :string] 1449 + ] 1450 + :RemoveApikeyParams 1451 + [:map 1452 + ;; The ID of the API key to remove. 1453 + [:id :string] 1454 + ] 1455 + :RemovePlaylistParams 1456 + [:map 1457 + ;; The URI of the playlist to remove 1458 + [:uri :string] 1459 + ] 1460 + :RemoveShoutParams 1461 + [:map 1462 + ;; The ID of the shout to be removed 1463 + [:id :string] 1464 + ] 1465 + :RemoveTrackParams 1466 + [:map 1467 + ;; The URI of the playlist to remove the track from 1468 + [:uri :string] 1469 + ;; The position of the track to remove in the playlist 1470 + [:position :int] 1471 + ] 1472 + :ReplyShoutInput 1473 + [:map 1474 + ;; The unique identifier of the shout to reply to 1475 + [:shoutId :string] 1476 + ;; The content of the reply 1477 + [:message :string] 1478 + ] 1479 + :ReportShoutInput 1480 + [:map 1481 + ;; The unique identifier of the shout to report 1482 + [:shoutId :string] 1483 + ;; The reason for reporting the shout 1484 + [:reason {:optional true} :string] 1485 + ] 1486 + :ScrobbleFirstScrobbleView 1487 + [:map 1488 + ;; The handle of the user who first scrobbled this song. 1489 + [:handle {:optional true} :string] 1490 + ;; The avatar URL of the user who first scrobbled this song. 1491 + [:avatar {:optional true} :string] 1492 + ;; The timestamp of the first scrobble. 1493 + [:timestamp {:optional true} :string] 1494 + ] 1495 + :ScrobbleRecord 1496 + [:map 1497 + ;; The title of the song. 1498 + [:title :string] 1499 + ;; The artist of the song. 1500 + [:artist :string] 1501 + ;; The artists of the song with MusicBrainz IDs. 1502 + [:artists {:optional true} [:vector :ArtistMbid]] 1503 + ;; The album artist of the song. 1504 + [:albumArtist :string] 1505 + ;; The album of the song. 1506 + [:album :string] 1507 + ;; The duration of the song in milliseconds. 1508 + [:duration :int] 1509 + ;; The track number of the song in the album. 1510 + [:trackNumber {:optional true} :int] 1511 + ;; The disc number of the song in the album. 1512 + [:discNumber {:optional true} :int] 1513 + ;; The release date of the song. 1514 + [:releaseDate {:optional true} :string] 1515 + ;; The year the song was released. 1516 + [:year {:optional true} :int] 1517 + ;; The genre of the song. 1518 + [:genre {:optional true} :string] 1519 + ;; The tags of the song. 1520 + [:tags {:optional true} [:vector :string]] 1521 + ;; The composer of the song. 1522 + [:composer {:optional true} :string] 1523 + ;; The lyrics of the song. 1524 + [:lyrics {:optional true} :string] 1525 + ;; The copyright message of the song. 1526 + [:copyrightMessage {:optional true} :string] 1527 + ;; Informations about the song 1528 + [:wiki {:optional true} :string] 1529 + ;; The album art of the song. 1530 + [:albumArt {:optional true} :BlobRef] 1531 + ;; The URL of the album art of the song. 1532 + [:albumArtUrl {:optional true} :string] 1533 + ;; The YouTube link of the song. 1534 + [:youtubeLink {:optional true} :string] 1535 + ;; The Spotify link of the song. 1536 + [:spotifyLink {:optional true} :string] 1537 + ;; The Tidal link of the song. 1538 + [:tidalLink {:optional true} :string] 1539 + ;; The Apple Music link of the song. 1540 + [:appleMusicLink {:optional true} :string] 1541 + ;; The date when the song was created. 1542 + [:createdAt :string] 1543 + ;; The MusicBrainz ID of the song. 1544 + [:mbid {:optional true} :string] 1545 + ;; The label of the song. 1546 + [:label {:optional true} :string] 1547 + ;; The International Standard Recording Code (ISRC) of the song. 1548 + [:isrc {:optional true} :string] 1549 + ] 1550 + :ScrobbleViewBasic 1551 + [:map 1552 + ;; The unique identifier of the scrobble. 1553 + [:id {:optional true} :string] 1554 + ;; The handle of the user who created the scrobble. 1555 + [:user {:optional true} :string] 1556 + ;; The display name of the user who created the scrobble. 1557 + [:userDisplayName {:optional true} :string] 1558 + ;; The avatar URL of the user who created the scrobble. 1559 + [:userAvatar {:optional true} :string] 1560 + ;; The title of the scrobble. 1561 + [:title {:optional true} :string] 1562 + ;; The artist of the song. 1563 + [:artist {:optional true} :string] 1564 + ;; The URI of the artist. 1565 + [:artistUri {:optional true} :string] 1566 + ;; The album of the song. 1567 + [:album {:optional true} :string] 1568 + ;; The URI of the album. 1569 + [:albumUri {:optional true} :string] 1570 + ;; The album art URL of the song. 1571 + [:cover {:optional true} :string] 1572 + ;; The timestamp when the scrobble was created. 1573 + [:date {:optional true} :string] 1574 + ;; The URI of the scrobble. 1575 + [:uri {:optional true} :string] 1576 + ;; The SHA256 hash of the scrobble data. 1577 + [:sha256 {:optional true} :string] 1578 + [:liked {:optional true} :boolean] 1579 + [:likesCount {:optional true} :int] 1580 + ] 1581 + :ScrobbleViewDetailed 1582 + [:map 1583 + ;; The unique identifier of the scrobble. 1584 + [:id {:optional true} :string] 1585 + ;; The handle of the user who created the scrobble. 1586 + [:user {:optional true} :string] 1587 + ;; The title of the scrobble. 1588 + [:title {:optional true} :string] 1589 + ;; The artist of the song. 1590 + [:artist {:optional true} :string] 1591 + ;; The URI of the artist. 1592 + [:artistUri {:optional true} :string] 1593 + ;; The album of the song. 1594 + [:album {:optional true} :string] 1595 + ;; The URI of the album. 1596 + [:albumUri {:optional true} :string] 1597 + ;; The album art URL of the song. 1598 + [:cover {:optional true} :string] 1599 + ;; The timestamp when the scrobble was created. 1600 + [:date {:optional true} :string] 1601 + ;; The URI of the scrobble. 1602 + [:uri {:optional true} :string] 1603 + ;; The SHA256 hash of the scrobble data. 1604 + [:sha256 {:optional true} :string] 1605 + [:liked {:optional true} :boolean] 1606 + [:likesCount {:optional true} :int] 1607 + ;; The number of listeners 1608 + [:listeners {:optional true} :int] 1609 + ;; The number of scrobbles for this song 1610 + [:scrobbles {:optional true} :int] 1611 + [:artists {:optional true} [:vector :ArtistViewBasic]] 1612 + ;; The first scrobble of this song on Rocksky. 1613 + [:firstScrobble {:optional true} :ScrobbleFirstScrobbleView] 1614 + ] 1615 + :SearchParams 1616 + [:map 1617 + ;; The search query string 1618 + [:query :string] 1619 + ] 1620 + :SeekParams 1621 + [:map 1622 + [:playerId {:optional true} :string] 1623 + ;; The position in seconds to seek to 1624 + [:position :int] 1625 + ] 1626 + :ShoutAuthor 1627 + [:map 1628 + ;; The unique identifier of the author. 1629 + [:id {:optional true} :string] 1630 + ;; The decentralized identifier (DID) of the author. 1631 + [:did {:optional true} :string] 1632 + ;; The handle of the author. 1633 + [:handle {:optional true} :string] 1634 + ;; The display name of the author. 1635 + [:displayName {:optional true} :string] 1636 + ;; The URL of the author's avatar image. 1637 + [:avatar {:optional true} :string] 1638 + ] 1639 + :ShoutRecord 1640 + [:map 1641 + ;; The message of the shout. 1642 + [:message :string] 1643 + ;; The date when the shout was created. 1644 + [:createdAt :string] 1645 + [:parent {:optional true} :StrongRef] 1646 + [:subject :StrongRef] 1647 + ] 1648 + :ShoutView 1649 + [:map 1650 + ;; The unique identifier of the shout. 1651 + [:id {:optional true} :string] 1652 + ;; The content of the shout. 1653 + [:message {:optional true} :string] 1654 + ;; The ID of the parent shout if this is a reply, otherwise null. 1655 + [:parent {:optional true} :string] 1656 + ;; The date and time when the shout was created. 1657 + [:createdAt {:optional true} :string] 1658 + ;; The author of the shout. 1659 + [:author {:optional true} :ShoutAuthor] 1660 + ] 1661 + :SongFirstScrobbleView 1662 + [:map 1663 + ;; The handle of the user who first scrobbled this song. 1664 + [:handle {:optional true} :string] 1665 + ;; The avatar URL of the user who first scrobbled this song. 1666 + [:avatar {:optional true} :string] 1667 + ;; The timestamp of the first scrobble. 1668 + [:timestamp {:optional true} :string] 1669 + ] 1670 + :SongRecentListenerView 1671 + [:map 1672 + ;; The unique identifier of the listener. 1673 + [:id {:optional true} :string] 1674 + ;; The DID of the listener. 1675 + [:did {:optional true} :string] 1676 + ;; The handle of the listener. 1677 + [:handle {:optional true} :string] 1678 + ;; The display name of the listener. 1679 + [:displayName {:optional true} :string] 1680 + ;; The URL of the listener's avatar image. 1681 + [:avatar {:optional true} :string] 1682 + ;; The timestamp of the listener's most recent scrobble of this song. 1683 + [:timestamp {:optional true} :string] 1684 + ;; The URI of the listener's most recent scrobble of this song. 1685 + [:scrobbleUri {:optional true} :string] 1686 + ] 1687 + :SongRecord 1688 + [:map 1689 + ;; The title of the song. 1690 + [:title :string] 1691 + ;; The artist of the song. 1692 + [:artist :string] 1693 + ;; The artists of the song with MusicBrainz IDs. 1694 + [:artists {:optional true} [:vector :ArtistMbid]] 1695 + ;; The album artist of the song. 1696 + [:albumArtist :string] 1697 + ;; The album of the song. 1698 + [:album :string] 1699 + ;; The duration of the song in milliseconds. 1700 + [:duration :int] 1701 + ;; The track number of the song in the album. 1702 + [:trackNumber {:optional true} :int] 1703 + ;; The disc number of the song in the album. 1704 + [:discNumber {:optional true} :int] 1705 + ;; The release date of the song. 1706 + [:releaseDate {:optional true} :string] 1707 + ;; The year the song was released. 1708 + [:year {:optional true} :int] 1709 + ;; The genre of the song. 1710 + [:genre {:optional true} :string] 1711 + ;; The tags of the song. 1712 + [:tags {:optional true} [:vector :string]] 1713 + ;; The composer of the song. 1714 + [:composer {:optional true} :string] 1715 + ;; The lyrics of the song. 1716 + [:lyrics {:optional true} :string] 1717 + ;; The copyright message of the song. 1718 + [:copyrightMessage {:optional true} :string] 1719 + ;; Informations about the song 1720 + [:wiki {:optional true} :string] 1721 + ;; The album art of the song. 1722 + [:albumArt {:optional true} :BlobRef] 1723 + ;; The URL of the album art of the song. 1724 + [:albumArtUrl {:optional true} :string] 1725 + ;; The YouTube link of the song. 1726 + [:youtubeLink {:optional true} :string] 1727 + ;; The Spotify link of the song. 1728 + [:spotifyLink {:optional true} :string] 1729 + ;; The Tidal link of the song. 1730 + [:tidalLink {:optional true} :string] 1731 + ;; The Apple Music link of the song. 1732 + [:appleMusicLink {:optional true} :string] 1733 + ;; The date when the song was created. 1734 + [:createdAt :string] 1735 + ;; The MusicBrainz ID of the song. 1736 + [:mbid {:optional true} :string] 1737 + ;; The label of the song. 1738 + [:label {:optional true} :string] 1739 + ;; The International Standard Recording Code (ISRC) of the song. 1740 + [:isrc {:optional true} :string] 1741 + ] 1742 + :SongViewBasic 1743 + [:map 1744 + ;; The unique identifier of the song. 1745 + [:id {:optional true} :string] 1746 + ;; The title of the song. 1747 + [:title {:optional true} :string] 1748 + ;; The artist of the song. 1749 + [:artist {:optional true} :string] 1750 + ;; The artist of the album the song belongs to. 1751 + [:albumArtist {:optional true} :string] 1752 + ;; The URL of the album art image. 1753 + [:albumArt {:optional true} :string] 1754 + ;; The URI of the song. 1755 + [:uri {:optional true} :string] 1756 + ;; The album of the song. 1757 + [:album {:optional true} :string] 1758 + ;; The duration of the song in milliseconds. 1759 + [:duration {:optional true} :int] 1760 + ;; The track number of the song in the album. 1761 + [:trackNumber {:optional true} :int] 1762 + ;; The disc number of the song in the album. 1763 + [:discNumber {:optional true} :int] 1764 + ;; The number of times the song has been played. 1765 + [:playCount {:optional true} :int] 1766 + ;; The number of unique listeners who have played the song. 1767 + [:uniqueListeners {:optional true} :int] 1768 + ;; The URI of the album the song belongs to. 1769 + [:albumUri {:optional true} :string] 1770 + ;; The URI of the artist of the song. 1771 + [:artistUri {:optional true} :string] 1772 + ;; The SHA256 hash of the song. 1773 + [:sha256 {:optional true} :string] 1774 + ;; The MusicBrainz ID of the song. 1775 + [:mbid {:optional true} :string] 1776 + ;; The International Standard Recording Code (ISRC) of the song. 1777 + [:isrc {:optional true} :string] 1778 + [:tags {:optional true} [:vector :string]] 1779 + ;; The timestamp when the song was created. 1780 + [:createdAt {:optional true} :string] 1781 + ] 1782 + :SongViewDetailed 1783 + [:map 1784 + ;; The unique identifier of the song. 1785 + [:id {:optional true} :string] 1786 + ;; The title of the song. 1787 + [:title {:optional true} :string] 1788 + ;; The artist of the song. 1789 + [:artist {:optional true} :string] 1790 + ;; The artist of the album the song belongs to. 1791 + [:albumArtist {:optional true} :string] 1792 + ;; The URL of the album art image. 1793 + [:albumArt {:optional true} :string] 1794 + ;; The URI of the song. 1795 + [:uri {:optional true} :string] 1796 + ;; The album of the song. 1797 + [:album {:optional true} :string] 1798 + ;; The duration of the song in milliseconds. 1799 + [:duration {:optional true} :int] 1800 + ;; The track number of the song in the album. 1801 + [:trackNumber {:optional true} :int] 1802 + ;; The disc number of the song in the album. 1803 + [:discNumber {:optional true} :int] 1804 + ;; The number of times the song has been played. 1805 + [:playCount {:optional true} :int] 1806 + ;; The number of unique listeners who have played the song. 1807 + [:uniqueListeners {:optional true} :int] 1808 + ;; The URI of the album the song belongs to. 1809 + [:albumUri {:optional true} :string] 1810 + ;; The URI of the artist of the song. 1811 + [:artistUri {:optional true} :string] 1812 + ;; The SHA256 hash of the song. 1813 + [:sha256 {:optional true} :string] 1814 + ;; The MusicBrainz ID of the song. 1815 + [:mbid {:optional true} :string] 1816 + ;; The International Standard Recording Code (ISRC) of the song. 1817 + [:isrc {:optional true} :string] 1818 + [:tags {:optional true} [:vector :string]] 1819 + ;; The timestamp when the song was created. 1820 + [:createdAt {:optional true} :string] 1821 + [:artists {:optional true} [:vector :ArtistViewBasic]] 1822 + ;; The first scrobble of this song on Rocksky. 1823 + [:firstScrobble {:optional true} :SongFirstScrobbleView] 1824 + ] 1825 + :SpotifyTrackView 1826 + [:map 1827 + ;; The unique identifier of the Spotify track. 1828 + [:id {:optional true} :string] 1829 + ;; The name of the track. 1830 + [:name {:optional true} :string] 1831 + ;; The name of the artist. 1832 + [:artist {:optional true} :string] 1833 + ;; The name of the album. 1834 + [:album {:optional true} :string] 1835 + ;; The duration of the track in milliseconds. 1836 + [:duration {:optional true} :int] 1837 + ;; A URL to a preview of the track. 1838 + [:previewUrl {:optional true} :string] 1839 + ] 1840 + :StartPlaylistParams 1841 + [:map 1842 + ;; The URI of the playlist to start 1843 + [:uri :string] 1844 + ;; Whether to shuffle the playlist when starting it 1845 + [:shuffle {:optional true} :boolean] 1846 + ;; The position in the playlist to start from, if not specified, starts from the beginning 1847 + [:position {:optional true} :int] 1848 + ] 1849 + :StatsView 1850 + [:map 1851 + ;; The total number of scrobbles. 1852 + [:scrobbles {:optional true} :int] 1853 + ;; The total number of unique artists scrobbled. 1854 + [:artists {:optional true} :int] 1855 + ;; The total number of tracks marked as loved. 1856 + [:lovedTracks {:optional true} :int] 1857 + ;; The total number of unique albums scrobbled. 1858 + [:albums {:optional true} :int] 1859 + ;; The total number of unique tracks scrobbled. 1860 + [:tracks {:optional true} :int] 1861 + ] 1862 + :StatsWrappedAlbum 1863 + [:map 1864 + ;; The unique identifier of the album. 1865 + [:id {:optional true} :string] 1866 + ;; The title of the album. 1867 + [:title {:optional true} :string] 1868 + ;; The artist of the album. 1869 + [:artist {:optional true} :string] 1870 + ;; The album art URL. 1871 + [:albumArt {:optional true} :string] 1872 + ;; The AT-URI of the album. 1873 + [:uri {:optional true} :string] 1874 + ;; Number of plays in the wrapped period. 1875 + [:playCount {:optional true} :int] 1876 + ] 1877 + :StatsWrappedArtist 1878 + [:map 1879 + ;; The unique identifier of the artist. 1880 + [:id {:optional true} :string] 1881 + ;; The name of the artist. 1882 + [:name {:optional true} :string] 1883 + ;; The picture URL of the artist. 1884 + [:picture {:optional true} :string] 1885 + ;; The AT-URI of the artist. 1886 + [:uri {:optional true} :string] 1887 + ;; Number of plays in the wrapped period. 1888 + [:playCount {:optional true} :int] 1889 + ] 1890 + :StatsWrappedDayCount 1891 + [:map 1892 + ;; The date (YYYY-MM-DD). 1893 + [:date {:optional true} :string] 1894 + ;; Number of scrobbles on this day. 1895 + [:count {:optional true} :int] 1896 + ] 1897 + :StatsWrappedGenreCount 1898 + [:map 1899 + ;; The genre name. 1900 + [:genre {:optional true} :string] 1901 + ;; Number of scrobbles for this genre. 1902 + [:count {:optional true} :int] 1903 + ] 1904 + :StatsWrappedMilestone 1905 + [:map 1906 + ;; The title of the track. 1907 + [:trackTitle {:optional true} :string] 1908 + ;; The name of the artist. 1909 + [:artistName {:optional true} :string] 1910 + ;; The timestamp of the scrobble. 1911 + [:timestamp {:optional true} :string] 1912 + ;; AT-URI of the track record, used to build a clickable link to the song page. 1913 + [:trackUri {:optional true} :string] 1914 + ] 1915 + :StatsWrappedMonthCount 1916 + [:map 1917 + ;; Month number (1-12). 1918 + [:month {:optional true} :int] 1919 + ;; Number of scrobbles in this month. 1920 + [:count {:optional true} :int] 1921 + ] 1922 + :StatsWrappedTrack 1923 + [:map 1924 + ;; The unique identifier of the track. 1925 + [:id {:optional true} :string] 1926 + ;; The title of the track. 1927 + [:title {:optional true} :string] 1928 + ;; The artist of the track. 1929 + [:artist {:optional true} :string] 1930 + ;; The album art URL. 1931 + [:albumArt {:optional true} :string] 1932 + ;; The AT-URI of the track. 1933 + [:uri {:optional true} :string] 1934 + ;; The AT-URI of the artist. 1935 + [:artistUri {:optional true} :string] 1936 + ;; The AT-URI of the album. 1937 + [:albumUri {:optional true} :string] 1938 + ;; Number of plays in the wrapped period. 1939 + [:playCount {:optional true} :int] 1940 + ] 1941 + :StatsWrappedView 1942 + [:map 1943 + ;; The year of the wrapped stats. 1944 + [:year {:optional true} :int] 1945 + ;; Total scrobbles in the year. 1946 + [:totalScrobbles {:optional true} :int] 1947 + ;; Total listening time in minutes. 1948 + [:totalListeningTimeMinutes {:optional true} :int] 1949 + ;; Top 5 artists by play count. 1950 + [:topArtists {:optional true} [:vector :StatsWrappedArtist]] 1951 + ;; Top 5 tracks by play count. 1952 + [:topTracks {:optional true} [:vector :StatsWrappedTrack]] 1953 + ;; Top 5 albums by play count. 1954 + [:topAlbums {:optional true} [:vector :StatsWrappedAlbum]] 1955 + ;; Top genres by play count. 1956 + [:topGenres {:optional true} [:vector :StatsWrappedGenreCount]] 1957 + ;; Scrobble counts per month. 1958 + [:scrobblesPerMonth {:optional true} [:vector :StatsWrappedMonthCount]] 1959 + ;; The most active day of the year. 1960 + [:mostActiveDay {:optional true} :StatsWrappedDayCount] 1961 + ;; The most active hour of the day (0-23). 1962 + [:mostActiveHour {:optional true} :int] 1963 + ;; Number of artists heard for the first time this year. 1964 + [:newArtistsCount {:optional true} :int] 1965 + ;; Longest consecutive days streak. 1966 + [:longestStreak {:optional true} :int] 1967 + ;; The first scrobble of the year. 1968 + [:firstScrobble {:optional true} :StatsWrappedMilestone] 1969 + ;; The last scrobble of the year. 1970 + [:lastScrobble {:optional true} :StatsWrappedMilestone] 1971 + ] 1972 + :StatusRecord 1973 + [:map 1974 + ;; The track currently being played. 1975 + [:track :ActorTrackView] 1976 + ;; When the track started playing. 1977 + [:startedAt :string] 1978 + ;; When the status expires. Defaults to startedAt plus track duration plus idle time. 1979 + [:expiresAt {:optional true} :string] 1980 + ] 1981 + :StrongRef 1982 + [:map 1983 + [:uri :string] 1984 + [:cid :string] 1985 + ] 1986 + :UnfollowAccountOutput 1987 + [:map 1988 + [:subject :ActorProfileViewBasic] 1989 + [:followers [:vector :ActorProfileViewBasic]] 1990 + ;; A cursor value to pass to subsequent calls to get the next page of results. 1991 + [:cursor {:optional true} :string] 1992 + ] 1993 + :UnfollowAccountParams 1994 + [:map 1995 + [:account :string] 1996 + ] 1997 + :UpdateApikeyInput 1998 + [:map 1999 + ;; The ID of the API key to update. 2000 + [:id :string] 2001 + ;; The new name of the API key. 2002 + [:name :string] 2003 + ;; A new description for the API key. 2004 + [:description {:optional true} :string] 2005 + ] 2006 + }) 2007 + 2008 + (defn schema 2009 + "Look up a generated schema by keyword." 2010 + [k] 2011 + (get schemas k))
+5
sdk/elixir/README.md
··· 249 249 Rocksky.HTTP.query(client, "app.rocksky.actor.getProfile", did: "alice") 250 250 ``` 251 251 252 + ## Types 253 + 254 + Lexicon-derived structs are available under `Rocksky.Generated.*`, mirroring every lex `*View*` / `*Record` / `*Input` / `*Output` / `*Params` shape from [the Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons). Regenerate with `bun run lexgen:types` at the repo root. 255 + 256 + 252 257 ## Testing your own code 253 258 254 259 The SDK routes every request through `Req`, which means you can stub it with
+2305
sdk/elixir/lib/rocksky/generated/types.ex
··· 1 + # AUTO-GENERATED FILE -- DO NOT EDIT. 2 + # Source: apps/api/lexicons/**/*.json 3 + # Regenerate via: bun run lexgen:types 4 + 5 + defmodule Rocksky.Generated.BlobRef do 6 + @moduledoc "atproto blob reference shape." 7 + @type t :: %__MODULE__{ 8 + type: String.t() | nil, 9 + ref: map() | nil, 10 + mimeType: String.t() | nil, 11 + size: integer() | nil 12 + } 13 + defstruct [:type, :ref, :mimeType, :size] 14 + end 15 + 16 + 17 + defmodule Rocksky.Generated.ActorArtistViewBasic do 18 + @moduledoc false 19 + @type t :: %__MODULE__{ 20 + id: String.t() | nil, 21 + name: String.t() | nil, 22 + picture: String.t() | nil, 23 + uri: String.t() | nil, 24 + user1Rank: integer() | nil, 25 + user2Rank: integer() | nil, 26 + weight: integer() | nil 27 + } 28 + defstruct [:id, :name, :picture, :uri, :user1Rank, :user2Rank, :weight] 29 + end 30 + 31 + defmodule Rocksky.Generated.ActorCompatibilityViewBasic do 32 + @moduledoc false 33 + @type t :: %__MODULE__{ 34 + compatibilityLevel: integer() | nil, 35 + compatibilityPercentage: integer() | nil, 36 + sharedArtists: integer() | nil, 37 + topSharedArtistNames: list(String.t()) | nil, 38 + topSharedDetailedArtists: list(Rocksky.Generated.ActorArtistViewBasic.t()) | nil, 39 + user1ArtistCount: integer() | nil, 40 + user2ArtistCount: integer() | nil 41 + } 42 + defstruct [:compatibilityLevel, :compatibilityPercentage, :sharedArtists, :topSharedArtistNames, :topSharedDetailedArtists, :user1ArtistCount, :user2ArtistCount] 43 + end 44 + 45 + defmodule Rocksky.Generated.ActorNeighbourViewBasic do 46 + @moduledoc false 47 + @type t :: %__MODULE__{ 48 + userId: String.t() | nil, 49 + did: String.t() | nil, 50 + handle: String.t() | nil, 51 + displayName: String.t() | nil, 52 + avatar: String.t() | nil, 53 + sharedArtistsCount: integer() | nil, 54 + similarityScore: integer() | nil, 55 + topSharedArtistNames: list(String.t()) | nil, 56 + topSharedArtistsDetails: list(Rocksky.Generated.ArtistViewBasic.t()) | nil 57 + } 58 + defstruct [:userId, :did, :handle, :displayName, :avatar, :sharedArtistsCount, :similarityScore, :topSharedArtistNames, :topSharedArtistsDetails] 59 + end 60 + 61 + defmodule Rocksky.Generated.ActorProfileViewBasic do 62 + @moduledoc false 63 + @type t :: %__MODULE__{ 64 + id: String.t() | nil, 65 + did: String.t() | nil, 66 + handle: String.t() | nil, 67 + displayName: String.t() | nil, 68 + avatar: String.t() | nil, 69 + createdAt: String.t() | nil, 70 + updatedAt: String.t() | nil 71 + } 72 + defstruct [:id, :did, :handle, :displayName, :avatar, :createdAt, :updatedAt] 73 + end 74 + 75 + defmodule Rocksky.Generated.ActorProfileViewDetailed do 76 + @moduledoc false 77 + @type t :: %__MODULE__{ 78 + id: String.t() | nil, 79 + did: String.t() | nil, 80 + handle: String.t() | nil, 81 + displayName: String.t() | nil, 82 + avatar: String.t() | nil, 83 + createdAt: String.t() | nil, 84 + updatedAt: String.t() | nil 85 + } 86 + defstruct [:id, :did, :handle, :displayName, :avatar, :createdAt, :updatedAt] 87 + end 88 + 89 + defmodule Rocksky.Generated.ActorTrackView do 90 + @moduledoc false 91 + @type t :: %__MODULE__{ 92 + name: String.t(), 93 + artist: String.t(), 94 + album: String.t() | nil, 95 + albumCoverUrl: String.t() | nil, 96 + durationMs: integer() | nil, 97 + source: String.t() | nil, 98 + recordingMbId: String.t() | nil 99 + } 100 + @enforce_keys [:name, :artist] 101 + defstruct [:name, :artist, :album, :albumCoverUrl, :durationMs, :source, :recordingMbId] 102 + end 103 + 104 + defmodule Rocksky.Generated.AddDirectoryToQueueParams do 105 + @moduledoc false 106 + @type t :: %__MODULE__{ 107 + playerId: String.t() | nil, 108 + directory: String.t(), 109 + position: integer() | nil, 110 + shuffle: boolean() | nil 111 + } 112 + @enforce_keys [:directory] 113 + defstruct [:playerId, :directory, :position, :shuffle] 114 + end 115 + 116 + defmodule Rocksky.Generated.AddItemsToQueueParams do 117 + @moduledoc false 118 + @type t :: %__MODULE__{ 119 + playerId: String.t() | nil, 120 + items: list(String.t()), 121 + position: integer() | nil, 122 + shuffle: boolean() | nil 123 + } 124 + @enforce_keys [:items] 125 + defstruct [:playerId, :items, :position, :shuffle] 126 + end 127 + 128 + defmodule Rocksky.Generated.AlbumRecord do 129 + @moduledoc false 130 + @type t :: %__MODULE__{ 131 + title: String.t(), 132 + artist: String.t(), 133 + duration: integer() | nil, 134 + releaseDate: String.t() | nil, 135 + year: integer() | nil, 136 + genre: String.t() | nil, 137 + albumArt: Rocksky.Generated.BlobRef.t() | nil, 138 + albumArtUrl: String.t() | nil, 139 + tags: list(String.t()) | nil, 140 + youtubeLink: String.t() | nil, 141 + spotifyLink: String.t() | nil, 142 + tidalLink: String.t() | nil, 143 + appleMusicLink: String.t() | nil, 144 + createdAt: String.t() 145 + } 146 + @enforce_keys [:title, :artist, :createdAt] 147 + defstruct [:title, :artist, :duration, :releaseDate, :year, :genre, :albumArt, :albumArtUrl, :tags, :youtubeLink, :spotifyLink, :tidalLink, :appleMusicLink, :createdAt] 148 + end 149 + 150 + defmodule Rocksky.Generated.AlbumViewBasic do 151 + @moduledoc false 152 + @type t :: %__MODULE__{ 153 + id: String.t() | nil, 154 + uri: String.t() | nil, 155 + title: String.t() | nil, 156 + artist: String.t() | nil, 157 + artistUri: String.t() | nil, 158 + year: integer() | nil, 159 + albumArt: String.t() | nil, 160 + releaseDate: String.t() | nil, 161 + sha256: String.t() | nil, 162 + playCount: integer() | nil, 163 + uniqueListeners: integer() | nil 164 + } 165 + defstruct [:id, :uri, :title, :artist, :artistUri, :year, :albumArt, :releaseDate, :sha256, :playCount, :uniqueListeners] 166 + end 167 + 168 + defmodule Rocksky.Generated.AlbumViewDetailed do 169 + @moduledoc false 170 + @type t :: %__MODULE__{ 171 + id: String.t() | nil, 172 + uri: String.t() | nil, 173 + title: String.t() | nil, 174 + artist: String.t() | nil, 175 + artistUri: String.t() | nil, 176 + year: integer() | nil, 177 + albumArt: String.t() | nil, 178 + releaseDate: String.t() | nil, 179 + sha256: String.t() | nil, 180 + playCount: integer() | nil, 181 + uniqueListeners: integer() | nil, 182 + tags: list(String.t()) | nil, 183 + tracks: list(Rocksky.Generated.SongViewBasic.t()) | nil 184 + } 185 + defstruct [:id, :uri, :title, :artist, :artistUri, :year, :albumArt, :releaseDate, :sha256, :playCount, :uniqueListeners, :tags, :tracks] 186 + end 187 + 188 + defmodule Rocksky.Generated.ApiKeyView do 189 + @moduledoc false 190 + @type t :: %__MODULE__{ 191 + id: String.t() | nil, 192 + name: String.t() | nil, 193 + description: String.t() | nil, 194 + createdAt: String.t() | nil 195 + } 196 + defstruct [:id, :name, :description, :createdAt] 197 + end 198 + 199 + defmodule Rocksky.Generated.ArtistListenerViewBasic do 200 + @moduledoc false 201 + @type t :: %__MODULE__{ 202 + id: String.t() | nil, 203 + did: String.t() | nil, 204 + handle: String.t() | nil, 205 + displayName: String.t() | nil, 206 + avatar: String.t() | nil, 207 + mostListenedSong: Rocksky.Generated.ArtistSongViewBasic.t() | nil, 208 + totalPlays: integer() | nil, 209 + rank: integer() | nil 210 + } 211 + defstruct [:id, :did, :handle, :displayName, :avatar, :mostListenedSong, :totalPlays, :rank] 212 + end 213 + 214 + defmodule Rocksky.Generated.ArtistMbid do 215 + @moduledoc false 216 + @type t :: %__MODULE__{ 217 + mbid: String.t() | nil, 218 + name: String.t() | nil 219 + } 220 + defstruct [:mbid, :name] 221 + end 222 + 223 + defmodule Rocksky.Generated.ArtistRecentListenerView do 224 + @moduledoc false 225 + @type t :: %__MODULE__{ 226 + id: String.t() | nil, 227 + did: String.t() | nil, 228 + handle: String.t() | nil, 229 + displayName: String.t() | nil, 230 + avatar: String.t() | nil, 231 + timestamp: String.t() | nil, 232 + scrobbleUri: String.t() | nil 233 + } 234 + defstruct [:id, :did, :handle, :displayName, :avatar, :timestamp, :scrobbleUri] 235 + end 236 + 237 + defmodule Rocksky.Generated.ArtistRecord do 238 + @moduledoc false 239 + @type t :: %__MODULE__{ 240 + name: String.t(), 241 + bio: String.t() | nil, 242 + picture: Rocksky.Generated.BlobRef.t() | nil, 243 + pictureUrl: String.t() | nil, 244 + tags: list(String.t()) | nil, 245 + born: String.t() | nil, 246 + died: String.t() | nil, 247 + bornIn: String.t() | nil, 248 + createdAt: String.t() 249 + } 250 + @enforce_keys [:name, :createdAt] 251 + defstruct [:name, :bio, :picture, :pictureUrl, :tags, :born, :died, :bornIn, :createdAt] 252 + end 253 + 254 + defmodule Rocksky.Generated.ArtistSongViewBasic do 255 + @moduledoc false 256 + @type t :: %__MODULE__{ 257 + uri: String.t() | nil, 258 + title: String.t() | nil, 259 + playCount: integer() | nil 260 + } 261 + defstruct [:uri, :title, :playCount] 262 + end 263 + 264 + defmodule Rocksky.Generated.ArtistViewBasic do 265 + @moduledoc false 266 + @type t :: %__MODULE__{ 267 + id: String.t() | nil, 268 + uri: String.t() | nil, 269 + name: String.t() | nil, 270 + picture: String.t() | nil, 271 + sha256: String.t() | nil, 272 + playCount: integer() | nil, 273 + uniqueListeners: integer() | nil, 274 + tags: list(String.t()) | nil 275 + } 276 + defstruct [:id, :uri, :name, :picture, :sha256, :playCount, :uniqueListeners, :tags] 277 + end 278 + 279 + defmodule Rocksky.Generated.ArtistViewDetailed do 280 + @moduledoc false 281 + @type t :: %__MODULE__{ 282 + id: String.t() | nil, 283 + uri: String.t() | nil, 284 + name: String.t() | nil, 285 + picture: String.t() | nil, 286 + sha256: String.t() | nil, 287 + playCount: integer() | nil, 288 + uniqueListeners: integer() | nil, 289 + tags: list(String.t()) | nil 290 + } 291 + defstruct [:id, :uri, :name, :picture, :sha256, :playCount, :uniqueListeners, :tags] 292 + end 293 + 294 + defmodule Rocksky.Generated.ChartsScrobbleViewBasic do 295 + @moduledoc false 296 + @type t :: %__MODULE__{ 297 + date: String.t() | nil, 298 + count: integer() | nil 299 + } 300 + defstruct [:date, :count] 301 + end 302 + 303 + defmodule Rocksky.Generated.ChartsView do 304 + @moduledoc false 305 + @type t :: %__MODULE__{ 306 + scrobbles: list(Rocksky.Generated.ChartsScrobbleViewBasic.t()) | nil 307 + } 308 + defstruct [:scrobbles] 309 + end 310 + 311 + defmodule Rocksky.Generated.CreateApikeyInput do 312 + @moduledoc false 313 + @type t :: %__MODULE__{ 314 + name: String.t(), 315 + description: String.t() | nil 316 + } 317 + @enforce_keys [:name] 318 + defstruct [:name, :description] 319 + end 320 + 321 + defmodule Rocksky.Generated.CreatePlaylistParams do 322 + @moduledoc false 323 + @type t :: %__MODULE__{ 324 + name: String.t(), 325 + description: String.t() | nil 326 + } 327 + @enforce_keys [:name] 328 + defstruct [:name, :description] 329 + end 330 + 331 + defmodule Rocksky.Generated.CreateScrobbleInput do 332 + @moduledoc false 333 + @type t :: %__MODULE__{ 334 + title: String.t(), 335 + artist: String.t(), 336 + album: String.t() | nil, 337 + duration: integer() | nil, 338 + mbId: String.t() | nil, 339 + isrc: String.t() | nil, 340 + albumArt: String.t() | nil, 341 + trackNumber: integer() | nil, 342 + releaseDate: String.t() | nil, 343 + year: integer() | nil, 344 + discNumber: integer() | nil, 345 + lyrics: String.t() | nil, 346 + composer: String.t() | nil, 347 + copyrightMessage: String.t() | nil, 348 + label: String.t() | nil, 349 + artistPicture: String.t() | nil, 350 + spotifyLink: String.t() | nil, 351 + lastfmLink: String.t() | nil, 352 + tidalLink: String.t() | nil, 353 + appleMusicLink: String.t() | nil, 354 + youtubeLink: String.t() | nil, 355 + deezerLink: String.t() | nil, 356 + timestamp: integer() | nil 357 + } 358 + @enforce_keys [:title, :artist] 359 + defstruct [:title, :artist, :album, :duration, :mbId, :isrc, :albumArt, :trackNumber, :releaseDate, :year, :discNumber, :lyrics, :composer, :copyrightMessage, :label, :artistPicture, :spotifyLink, :lastfmLink, :tidalLink, :appleMusicLink, :youtubeLink, :deezerLink, :timestamp] 360 + end 361 + 362 + defmodule Rocksky.Generated.CreateShoutInput do 363 + @moduledoc false 364 + @type t :: %__MODULE__{ 365 + message: String.t() | nil 366 + } 367 + defstruct [:message] 368 + end 369 + 370 + defmodule Rocksky.Generated.CreateSongInput do 371 + @moduledoc false 372 + @type t :: %__MODULE__{ 373 + title: String.t(), 374 + artist: String.t(), 375 + albumArtist: String.t(), 376 + album: String.t(), 377 + duration: integer() | nil, 378 + mbId: String.t() | nil, 379 + isrc: String.t() | nil, 380 + albumArt: String.t() | nil, 381 + trackNumber: integer() | nil, 382 + releaseDate: String.t() | nil, 383 + year: integer() | nil, 384 + discNumber: integer() | nil, 385 + lyrics: String.t() | nil 386 + } 387 + @enforce_keys [:title, :artist, :albumArtist, :album] 388 + defstruct [:title, :artist, :albumArtist, :album, :duration, :mbId, :isrc, :albumArt, :trackNumber, :releaseDate, :year, :discNumber, :lyrics] 389 + end 390 + 391 + defmodule Rocksky.Generated.DescribeFeedGeneratorOutput do 392 + @moduledoc false 393 + @type t :: %__MODULE__{ 394 + did: String.t() | nil, 395 + feeds: list(Rocksky.Generated.FeedUriView.t()) | nil 396 + } 397 + defstruct [:did, :feeds] 398 + end 399 + 400 + defmodule Rocksky.Generated.DescribeFeedGeneratorParams do 401 + @moduledoc false 402 + @type t :: %__MODULE__{} 403 + defstruct [] 404 + end 405 + 406 + defmodule Rocksky.Generated.DislikeShoutInput do 407 + @moduledoc false 408 + @type t :: %__MODULE__{ 409 + uri: String.t() | nil 410 + } 411 + defstruct [:uri] 412 + end 413 + 414 + defmodule Rocksky.Generated.DislikeSongInput do 415 + @moduledoc false 416 + @type t :: %__MODULE__{ 417 + uri: String.t() | nil 418 + } 419 + defstruct [:uri] 420 + end 421 + 422 + defmodule Rocksky.Generated.DownloadFileParams do 423 + @moduledoc false 424 + @type t :: %__MODULE__{ 425 + fileId: String.t() 426 + } 427 + @enforce_keys [:fileId] 428 + defstruct [:fileId] 429 + end 430 + 431 + defmodule Rocksky.Generated.DropboxFileListView do 432 + @moduledoc false 433 + @type t :: %__MODULE__{ 434 + files: list(Rocksky.Generated.DropboxFileView.t()) | nil 435 + } 436 + defstruct [:files] 437 + end 438 + 439 + defmodule Rocksky.Generated.DropboxFileView do 440 + @moduledoc false 441 + @type t :: %__MODULE__{ 442 + id: String.t() | nil, 443 + name: String.t() | nil, 444 + pathLower: String.t() | nil, 445 + pathDisplay: String.t() | nil, 446 + clientModified: String.t() | nil, 447 + serverModified: String.t() | nil 448 + } 449 + defstruct [:id, :name, :pathLower, :pathDisplay, :clientModified, :serverModified] 450 + end 451 + 452 + defmodule Rocksky.Generated.DropboxTemporaryLinkView do 453 + @moduledoc false 454 + @type t :: %__MODULE__{ 455 + link: String.t() | nil 456 + } 457 + defstruct [:link] 458 + end 459 + 460 + defmodule Rocksky.Generated.FeedGeneratorsView do 461 + @moduledoc false 462 + @type t :: %__MODULE__{ 463 + feeds: list(Rocksky.Generated.FeedGeneratorView.t()) | nil 464 + } 465 + defstruct [:feeds] 466 + end 467 + 468 + defmodule Rocksky.Generated.FeedGeneratorView do 469 + @moduledoc false 470 + @type t :: %__MODULE__{ 471 + id: String.t() | nil, 472 + name: String.t() | nil, 473 + description: String.t() | nil, 474 + uri: String.t() | nil, 475 + avatar: String.t() | nil, 476 + creator: Rocksky.Generated.ActorProfileViewBasic.t() | nil 477 + } 478 + defstruct [:id, :name, :description, :uri, :avatar, :creator] 479 + end 480 + 481 + defmodule Rocksky.Generated.FeedItemView do 482 + @moduledoc false 483 + @type t :: %__MODULE__{ 484 + scrobble: Rocksky.Generated.ScrobbleViewBasic.t() | nil 485 + } 486 + defstruct [:scrobble] 487 + end 488 + 489 + defmodule Rocksky.Generated.FeedRecommendationsView do 490 + @moduledoc false 491 + @type t :: %__MODULE__{ 492 + recommendations: list(Rocksky.Generated.FeedRecommendationView.t()) | nil, 493 + cursor: String.t() | nil 494 + } 495 + defstruct [:recommendations, :cursor] 496 + end 497 + 498 + defmodule Rocksky.Generated.FeedRecommendationView do 499 + @moduledoc false 500 + @type t :: %__MODULE__{ 501 + title: String.t() | nil, 502 + artist: String.t() | nil, 503 + album: String.t() | nil, 504 + albumArt: String.t() | nil, 505 + trackUri: String.t() | nil, 506 + artistUri: String.t() | nil, 507 + albumUri: String.t() | nil, 508 + genres: list(String.t()) | nil, 509 + recommendationScore: integer() | nil, 510 + source: String.t() | nil, 511 + likesCount: integer() | nil 512 + } 513 + defstruct [:title, :artist, :album, :albumArt, :trackUri, :artistUri, :albumUri, :genres, :recommendationScore, :source, :likesCount] 514 + end 515 + 516 + defmodule Rocksky.Generated.FeedRecommendedAlbumsView do 517 + @moduledoc false 518 + @type t :: %__MODULE__{ 519 + albums: list(Rocksky.Generated.FeedRecommendedAlbumView.t()) | nil, 520 + cursor: String.t() | nil 521 + } 522 + defstruct [:albums, :cursor] 523 + end 524 + 525 + defmodule Rocksky.Generated.FeedRecommendedAlbumView do 526 + @moduledoc false 527 + @type t :: %__MODULE__{ 528 + id: String.t() | nil, 529 + uri: String.t() | nil, 530 + title: String.t() | nil, 531 + artist: String.t() | nil, 532 + artistUri: String.t() | nil, 533 + year: integer() | nil, 534 + albumArt: String.t() | nil, 535 + recommendationScore: integer() | nil, 536 + source: String.t() | nil 537 + } 538 + defstruct [:id, :uri, :title, :artist, :artistUri, :year, :albumArt, :recommendationScore, :source] 539 + end 540 + 541 + defmodule Rocksky.Generated.FeedRecommendedArtistsView do 542 + @moduledoc false 543 + @type t :: %__MODULE__{ 544 + artists: list(Rocksky.Generated.FeedRecommendedArtistView.t()) | nil, 545 + cursor: String.t() | nil 546 + } 547 + defstruct [:artists, :cursor] 548 + end 549 + 550 + defmodule Rocksky.Generated.FeedRecommendedArtistView do 551 + @moduledoc false 552 + @type t :: %__MODULE__{ 553 + id: String.t() | nil, 554 + uri: String.t() | nil, 555 + name: String.t() | nil, 556 + picture: String.t() | nil, 557 + genres: list(String.t()) | nil, 558 + recommendationScore: integer() | nil, 559 + source: String.t() | nil 560 + } 561 + defstruct [:id, :uri, :name, :picture, :genres, :recommendationScore, :source] 562 + end 563 + 564 + defmodule Rocksky.Generated.FeedSearchResultsView do 565 + @moduledoc false 566 + @type t :: %__MODULE__{ 567 + hits: list(term()) | nil, 568 + processingTimeMs: integer() | nil, 569 + limit: integer() | nil, 570 + offset: integer() | nil, 571 + estimatedTotalHits: integer() | nil 572 + } 573 + defstruct [:hits, :processingTimeMs, :limit, :offset, :estimatedTotalHits] 574 + end 575 + 576 + defmodule Rocksky.Generated.FeedStoriesView do 577 + @moduledoc false 578 + @type t :: %__MODULE__{ 579 + stories: list(Rocksky.Generated.FeedStoryView.t()) | nil 580 + } 581 + defstruct [:stories] 582 + end 583 + 584 + defmodule Rocksky.Generated.FeedStoryView do 585 + @moduledoc false 586 + @type t :: %__MODULE__{ 587 + album: String.t() | nil, 588 + albumArt: String.t() | nil, 589 + albumArtist: String.t() | nil, 590 + albumUri: String.t() | nil, 591 + artist: String.t() | nil, 592 + artistUri: String.t() | nil, 593 + avatar: String.t() | nil, 594 + createdAt: String.t() | nil, 595 + did: String.t() | nil, 596 + handle: String.t() | nil, 597 + id: String.t() | nil, 598 + title: String.t() | nil, 599 + trackId: String.t() | nil, 600 + trackUri: String.t() | nil, 601 + uri: String.t() | nil 602 + } 603 + defstruct [:album, :albumArt, :albumArtist, :albumUri, :artist, :artistUri, :avatar, :createdAt, :did, :handle, :id, :title, :trackId, :trackUri, :uri] 604 + end 605 + 606 + defmodule Rocksky.Generated.FeedUriView do 607 + @moduledoc false 608 + @type t :: %__MODULE__{ 609 + uri: String.t() | nil 610 + } 611 + defstruct [:uri] 612 + end 613 + 614 + defmodule Rocksky.Generated.FeedView do 615 + @moduledoc false 616 + @type t :: %__MODULE__{ 617 + feed: list(Rocksky.Generated.FeedItemView.t()) | nil, 618 + cursor: String.t() | nil 619 + } 620 + defstruct [:feed, :cursor] 621 + end 622 + 623 + defmodule Rocksky.Generated.FollowAccountOutput do 624 + @moduledoc false 625 + @type t :: %__MODULE__{ 626 + subject: Rocksky.Generated.ActorProfileViewBasic.t(), 627 + followers: list(Rocksky.Generated.ActorProfileViewBasic.t()), 628 + cursor: String.t() | nil 629 + } 630 + @enforce_keys [:subject, :followers] 631 + defstruct [:subject, :followers, :cursor] 632 + end 633 + 634 + defmodule Rocksky.Generated.FollowAccountParams do 635 + @moduledoc false 636 + @type t :: %__MODULE__{ 637 + account: String.t() 638 + } 639 + @enforce_keys [:account] 640 + defstruct [:account] 641 + end 642 + 643 + defmodule Rocksky.Generated.FollowRecord do 644 + @moduledoc false 645 + @type t :: %__MODULE__{ 646 + createdAt: String.t(), 647 + subject: String.t(), 648 + via: Rocksky.Generated.StrongRef.t() | nil 649 + } 650 + @enforce_keys [:createdAt, :subject] 651 + defstruct [:createdAt, :subject, :via] 652 + end 653 + 654 + defmodule Rocksky.Generated.GeneratorRecord do 655 + @moduledoc false 656 + @type t :: %__MODULE__{ 657 + did: String.t(), 658 + avatar: Rocksky.Generated.BlobRef.t() | nil, 659 + displayName: String.t(), 660 + description: String.t() | nil, 661 + createdAt: String.t() 662 + } 663 + @enforce_keys [:did, :displayName, :createdAt] 664 + defstruct [:did, :avatar, :displayName, :description, :createdAt] 665 + end 666 + 667 + defmodule Rocksky.Generated.GetActorAlbumsOutput do 668 + @moduledoc false 669 + @type t :: %__MODULE__{ 670 + albums: list(Rocksky.Generated.AlbumViewBasic.t()) | nil 671 + } 672 + defstruct [:albums] 673 + end 674 + 675 + defmodule Rocksky.Generated.GetActorAlbumsParams do 676 + @moduledoc false 677 + @type t :: %__MODULE__{ 678 + did: String.t(), 679 + limit: integer() | nil, 680 + offset: integer() | nil, 681 + startDate: String.t() | nil, 682 + endDate: String.t() | nil 683 + } 684 + @enforce_keys [:did] 685 + defstruct [:did, :limit, :offset, :startDate, :endDate] 686 + end 687 + 688 + defmodule Rocksky.Generated.GetActorArtistsOutput do 689 + @moduledoc false 690 + @type t :: %__MODULE__{ 691 + artists: list(Rocksky.Generated.ArtistViewBasic.t()) | nil 692 + } 693 + defstruct [:artists] 694 + end 695 + 696 + defmodule Rocksky.Generated.GetActorArtistsParams do 697 + @moduledoc false 698 + @type t :: %__MODULE__{ 699 + did: String.t(), 700 + limit: integer() | nil, 701 + offset: integer() | nil, 702 + startDate: String.t() | nil, 703 + endDate: String.t() | nil 704 + } 705 + @enforce_keys [:did] 706 + defstruct [:did, :limit, :offset, :startDate, :endDate] 707 + end 708 + 709 + defmodule Rocksky.Generated.GetActorCompatibilityOutput do 710 + @moduledoc false 711 + @type t :: %__MODULE__{ 712 + compatibility: Rocksky.Generated.ActorCompatibilityViewBasic.t() | nil 713 + } 714 + defstruct [:compatibility] 715 + end 716 + 717 + defmodule Rocksky.Generated.GetActorCompatibilityParams do 718 + @moduledoc false 719 + @type t :: %__MODULE__{ 720 + did: String.t() 721 + } 722 + @enforce_keys [:did] 723 + defstruct [:did] 724 + end 725 + 726 + defmodule Rocksky.Generated.GetActorLovedSongsOutput do 727 + @moduledoc false 728 + @type t :: %__MODULE__{ 729 + tracks: list(Rocksky.Generated.SongViewBasic.t()) | nil 730 + } 731 + defstruct [:tracks] 732 + end 733 + 734 + defmodule Rocksky.Generated.GetActorLovedSongsParams do 735 + @moduledoc false 736 + @type t :: %__MODULE__{ 737 + did: String.t(), 738 + limit: integer() | nil, 739 + offset: integer() | nil 740 + } 741 + @enforce_keys [:did] 742 + defstruct [:did, :limit, :offset] 743 + end 744 + 745 + defmodule Rocksky.Generated.GetActorNeighboursOutput do 746 + @moduledoc false 747 + @type t :: %__MODULE__{ 748 + neighbours: list(Rocksky.Generated.ActorNeighbourViewBasic.t()) | nil 749 + } 750 + defstruct [:neighbours] 751 + end 752 + 753 + defmodule Rocksky.Generated.GetActorNeighboursParams do 754 + @moduledoc false 755 + @type t :: %__MODULE__{ 756 + did: String.t() 757 + } 758 + @enforce_keys [:did] 759 + defstruct [:did] 760 + end 761 + 762 + defmodule Rocksky.Generated.GetActorPlaylistsOutput do 763 + @moduledoc false 764 + @type t :: %__MODULE__{ 765 + playlists: list(Rocksky.Generated.PlaylistViewBasic.t()) | nil 766 + } 767 + defstruct [:playlists] 768 + end 769 + 770 + defmodule Rocksky.Generated.GetActorPlaylistsParams do 771 + @moduledoc false 772 + @type t :: %__MODULE__{ 773 + did: String.t(), 774 + limit: integer() | nil, 775 + offset: integer() | nil 776 + } 777 + @enforce_keys [:did] 778 + defstruct [:did, :limit, :offset] 779 + end 780 + 781 + defmodule Rocksky.Generated.GetActorScrobblesOutput do 782 + @moduledoc false 783 + @type t :: %__MODULE__{ 784 + scrobbles: list(Rocksky.Generated.ScrobbleViewBasic.t()) | nil 785 + } 786 + defstruct [:scrobbles] 787 + end 788 + 789 + defmodule Rocksky.Generated.GetActorScrobblesParams do 790 + @moduledoc false 791 + @type t :: %__MODULE__{ 792 + did: String.t(), 793 + limit: integer() | nil, 794 + offset: integer() | nil 795 + } 796 + @enforce_keys [:did] 797 + defstruct [:did, :limit, :offset] 798 + end 799 + 800 + defmodule Rocksky.Generated.GetActorSongsOutput do 801 + @moduledoc false 802 + @type t :: %__MODULE__{ 803 + songs: list(Rocksky.Generated.SongViewBasic.t()) | nil 804 + } 805 + defstruct [:songs] 806 + end 807 + 808 + defmodule Rocksky.Generated.GetActorSongsParams do 809 + @moduledoc false 810 + @type t :: %__MODULE__{ 811 + did: String.t(), 812 + limit: integer() | nil, 813 + offset: integer() | nil, 814 + startDate: String.t() | nil, 815 + endDate: String.t() | nil 816 + } 817 + @enforce_keys [:did] 818 + defstruct [:did, :limit, :offset, :startDate, :endDate] 819 + end 820 + 821 + defmodule Rocksky.Generated.GetAlbumParams do 822 + @moduledoc false 823 + @type t :: %__MODULE__{ 824 + uri: String.t() 825 + } 826 + @enforce_keys [:uri] 827 + defstruct [:uri] 828 + end 829 + 830 + defmodule Rocksky.Generated.GetAlbumRecommendationsParams do 831 + @moduledoc false 832 + @type t :: %__MODULE__{ 833 + did: String.t(), 834 + limit: integer() | nil 835 + } 836 + @enforce_keys [:did] 837 + defstruct [:did, :limit] 838 + end 839 + 840 + defmodule Rocksky.Generated.GetAlbumShoutsOutput do 841 + @moduledoc false 842 + @type t :: %__MODULE__{ 843 + shouts: list(term()) | nil 844 + } 845 + defstruct [:shouts] 846 + end 847 + 848 + defmodule Rocksky.Generated.GetAlbumShoutsParams do 849 + @moduledoc false 850 + @type t :: %__MODULE__{ 851 + uri: String.t(), 852 + limit: integer() | nil, 853 + offset: integer() | nil 854 + } 855 + @enforce_keys [:uri] 856 + defstruct [:uri, :limit, :offset] 857 + end 858 + 859 + defmodule Rocksky.Generated.GetAlbumsOutput do 860 + @moduledoc false 861 + @type t :: %__MODULE__{ 862 + albums: list(Rocksky.Generated.AlbumViewBasic.t()) | nil 863 + } 864 + defstruct [:albums] 865 + end 866 + 867 + defmodule Rocksky.Generated.GetAlbumsParams do 868 + @moduledoc false 869 + @type t :: %__MODULE__{ 870 + limit: integer() | nil, 871 + offset: integer() | nil, 872 + genre: String.t() | nil 873 + } 874 + defstruct [:limit, :offset, :genre] 875 + end 876 + 877 + defmodule Rocksky.Generated.GetAlbumTracksOutput do 878 + @moduledoc false 879 + @type t :: %__MODULE__{ 880 + tracks: list(Rocksky.Generated.SongViewBasic.t()) | nil 881 + } 882 + defstruct [:tracks] 883 + end 884 + 885 + defmodule Rocksky.Generated.GetAlbumTracksParams do 886 + @moduledoc false 887 + @type t :: %__MODULE__{ 888 + uri: String.t() 889 + } 890 + @enforce_keys [:uri] 891 + defstruct [:uri] 892 + end 893 + 894 + defmodule Rocksky.Generated.GetApikeysOutput do 895 + @moduledoc false 896 + @type t :: %__MODULE__{ 897 + apiKeys: list(term()) | nil 898 + } 899 + defstruct [:apiKeys] 900 + end 901 + 902 + defmodule Rocksky.Generated.GetApikeysParams do 903 + @moduledoc false 904 + @type t :: %__MODULE__{ 905 + offset: integer() | nil, 906 + limit: integer() | nil 907 + } 908 + defstruct [:offset, :limit] 909 + end 910 + 911 + defmodule Rocksky.Generated.GetArtistAlbumsOutput do 912 + @moduledoc false 913 + @type t :: %__MODULE__{ 914 + albums: list(Rocksky.Generated.AlbumViewBasic.t()) | nil 915 + } 916 + defstruct [:albums] 917 + end 918 + 919 + defmodule Rocksky.Generated.GetArtistAlbumsParams do 920 + @moduledoc false 921 + @type t :: %__MODULE__{ 922 + uri: String.t() 923 + } 924 + @enforce_keys [:uri] 925 + defstruct [:uri] 926 + end 927 + 928 + defmodule Rocksky.Generated.GetArtistListenersOutput do 929 + @moduledoc false 930 + @type t :: %__MODULE__{ 931 + listeners: list(Rocksky.Generated.ArtistListenerViewBasic.t()) | nil 932 + } 933 + defstruct [:listeners] 934 + end 935 + 936 + defmodule Rocksky.Generated.GetArtistListenersParams do 937 + @moduledoc false 938 + @type t :: %__MODULE__{ 939 + uri: String.t(), 940 + offset: integer() | nil, 941 + limit: integer() | nil 942 + } 943 + @enforce_keys [:uri] 944 + defstruct [:uri, :offset, :limit] 945 + end 946 + 947 + defmodule Rocksky.Generated.GetArtistParams do 948 + @moduledoc false 949 + @type t :: %__MODULE__{ 950 + uri: String.t() 951 + } 952 + @enforce_keys [:uri] 953 + defstruct [:uri] 954 + end 955 + 956 + defmodule Rocksky.Generated.GetArtistRecentListenersOutput do 957 + @moduledoc false 958 + @type t :: %__MODULE__{ 959 + listeners: list(Rocksky.Generated.ArtistRecentListenerView.t()) | nil 960 + } 961 + defstruct [:listeners] 962 + end 963 + 964 + defmodule Rocksky.Generated.GetArtistRecentListenersParams do 965 + @moduledoc false 966 + @type t :: %__MODULE__{ 967 + uri: String.t(), 968 + offset: integer() | nil, 969 + limit: integer() | nil 970 + } 971 + @enforce_keys [:uri] 972 + defstruct [:uri, :offset, :limit] 973 + end 974 + 975 + defmodule Rocksky.Generated.GetArtistRecommendationsParams do 976 + @moduledoc false 977 + @type t :: %__MODULE__{ 978 + did: String.t(), 979 + limit: integer() | nil 980 + } 981 + @enforce_keys [:did] 982 + defstruct [:did, :limit] 983 + end 984 + 985 + defmodule Rocksky.Generated.GetArtistShoutsOutput do 986 + @moduledoc false 987 + @type t :: %__MODULE__{ 988 + shouts: list(term()) | nil 989 + } 990 + defstruct [:shouts] 991 + end 992 + 993 + defmodule Rocksky.Generated.GetArtistShoutsParams do 994 + @moduledoc false 995 + @type t :: %__MODULE__{ 996 + uri: String.t(), 997 + limit: integer() | nil, 998 + offset: integer() | nil 999 + } 1000 + @enforce_keys [:uri] 1001 + defstruct [:uri, :limit, :offset] 1002 + end 1003 + 1004 + defmodule Rocksky.Generated.GetArtistsOutput do 1005 + @moduledoc false 1006 + @type t :: %__MODULE__{ 1007 + artists: list(Rocksky.Generated.ArtistViewBasic.t()) | nil 1008 + } 1009 + defstruct [:artists] 1010 + end 1011 + 1012 + defmodule Rocksky.Generated.GetArtistsParams do 1013 + @moduledoc false 1014 + @type t :: %__MODULE__{ 1015 + limit: integer() | nil, 1016 + offset: integer() | nil, 1017 + names: String.t() | nil, 1018 + genre: String.t() | nil 1019 + } 1020 + defstruct [:limit, :offset, :names, :genre] 1021 + end 1022 + 1023 + defmodule Rocksky.Generated.GetArtistTracksOutput do 1024 + @moduledoc false 1025 + @type t :: %__MODULE__{ 1026 + tracks: list(Rocksky.Generated.SongViewBasic.t()) | nil 1027 + } 1028 + defstruct [:tracks] 1029 + end 1030 + 1031 + defmodule Rocksky.Generated.GetArtistTracksParams do 1032 + @moduledoc false 1033 + @type t :: %__MODULE__{ 1034 + uri: String.t() | nil, 1035 + limit: integer() | nil, 1036 + offset: integer() | nil 1037 + } 1038 + defstruct [:uri, :limit, :offset] 1039 + end 1040 + 1041 + defmodule Rocksky.Generated.GetCurrentlyPlayingParams do 1042 + @moduledoc false 1043 + @type t :: %__MODULE__{ 1044 + playerId: String.t() | nil, 1045 + actor: String.t() | nil 1046 + } 1047 + defstruct [:playerId, :actor] 1048 + end 1049 + 1050 + defmodule Rocksky.Generated.GetFeedGeneratorOutput do 1051 + @moduledoc false 1052 + @type t :: %__MODULE__{ 1053 + view: Rocksky.Generated.FeedGeneratorView.t() | nil 1054 + } 1055 + defstruct [:view] 1056 + end 1057 + 1058 + defmodule Rocksky.Generated.GetFeedGeneratorParams do 1059 + @moduledoc false 1060 + @type t :: %__MODULE__{ 1061 + feed: String.t() 1062 + } 1063 + @enforce_keys [:feed] 1064 + defstruct [:feed] 1065 + end 1066 + 1067 + defmodule Rocksky.Generated.GetFeedGeneratorsParams do 1068 + @moduledoc false 1069 + @type t :: %__MODULE__{ 1070 + size: integer() | nil 1071 + } 1072 + defstruct [:size] 1073 + end 1074 + 1075 + defmodule Rocksky.Generated.GetFeedParams do 1076 + @moduledoc false 1077 + @type t :: %__MODULE__{ 1078 + feed: String.t(), 1079 + limit: integer() | nil, 1080 + cursor: String.t() | nil 1081 + } 1082 + @enforce_keys [:feed] 1083 + defstruct [:feed, :limit, :cursor] 1084 + end 1085 + 1086 + defmodule Rocksky.Generated.GetFeedSkeletonOutput do 1087 + @moduledoc false 1088 + @type t :: %__MODULE__{ 1089 + scrobbles: list(Rocksky.Generated.ScrobbleViewBasic.t()) | nil, 1090 + cursor: String.t() | nil 1091 + } 1092 + defstruct [:scrobbles, :cursor] 1093 + end 1094 + 1095 + defmodule Rocksky.Generated.GetFeedSkeletonParams do 1096 + @moduledoc false 1097 + @type t :: %__MODULE__{ 1098 + feed: String.t(), 1099 + limit: integer() | nil, 1100 + offset: integer() | nil, 1101 + cursor: String.t() | nil 1102 + } 1103 + @enforce_keys [:feed] 1104 + defstruct [:feed, :limit, :offset, :cursor] 1105 + end 1106 + 1107 + defmodule Rocksky.Generated.GetFileParams do 1108 + @moduledoc false 1109 + @type t :: %__MODULE__{ 1110 + fileId: String.t() 1111 + } 1112 + @enforce_keys [:fileId] 1113 + defstruct [:fileId] 1114 + end 1115 + 1116 + defmodule Rocksky.Generated.GetFilesParams do 1117 + @moduledoc false 1118 + @type t :: %__MODULE__{ 1119 + at: String.t() | nil 1120 + } 1121 + defstruct [:at] 1122 + end 1123 + 1124 + defmodule Rocksky.Generated.GetFollowersOutput do 1125 + @moduledoc false 1126 + @type t :: %__MODULE__{ 1127 + subject: Rocksky.Generated.ActorProfileViewBasic.t(), 1128 + followers: list(Rocksky.Generated.ActorProfileViewBasic.t()), 1129 + cursor: String.t() | nil, 1130 + count: integer() | nil 1131 + } 1132 + @enforce_keys [:subject, :followers] 1133 + defstruct [:subject, :followers, :cursor, :count] 1134 + end 1135 + 1136 + defmodule Rocksky.Generated.GetFollowersParams do 1137 + @moduledoc false 1138 + @type t :: %__MODULE__{ 1139 + actor: String.t(), 1140 + limit: integer() | nil, 1141 + dids: list(String.t()) | nil, 1142 + cursor: String.t() | nil 1143 + } 1144 + @enforce_keys [:actor] 1145 + defstruct [:actor, :limit, :dids, :cursor] 1146 + end 1147 + 1148 + defmodule Rocksky.Generated.GetFollowsOutput do 1149 + @moduledoc false 1150 + @type t :: %__MODULE__{ 1151 + subject: Rocksky.Generated.ActorProfileViewBasic.t(), 1152 + follows: list(Rocksky.Generated.ActorProfileViewBasic.t()), 1153 + cursor: String.t() | nil, 1154 + count: integer() | nil 1155 + } 1156 + @enforce_keys [:subject, :follows] 1157 + defstruct [:subject, :follows, :cursor, :count] 1158 + end 1159 + 1160 + defmodule Rocksky.Generated.GetFollowsParams do 1161 + @moduledoc false 1162 + @type t :: %__MODULE__{ 1163 + actor: String.t(), 1164 + limit: integer() | nil, 1165 + dids: list(String.t()) | nil, 1166 + cursor: String.t() | nil 1167 + } 1168 + @enforce_keys [:actor] 1169 + defstruct [:actor, :limit, :dids, :cursor] 1170 + end 1171 + 1172 + defmodule Rocksky.Generated.GetKnownFollowersOutput do 1173 + @moduledoc false 1174 + @type t :: %__MODULE__{ 1175 + subject: Rocksky.Generated.ActorProfileViewBasic.t(), 1176 + followers: list(Rocksky.Generated.ActorProfileViewBasic.t()), 1177 + cursor: String.t() | nil 1178 + } 1179 + @enforce_keys [:subject, :followers] 1180 + defstruct [:subject, :followers, :cursor] 1181 + end 1182 + 1183 + defmodule Rocksky.Generated.GetKnownFollowersParams do 1184 + @moduledoc false 1185 + @type t :: %__MODULE__{ 1186 + actor: String.t(), 1187 + limit: integer() | nil, 1188 + cursor: String.t() | nil 1189 + } 1190 + @enforce_keys [:actor] 1191 + defstruct [:actor, :limit, :cursor] 1192 + end 1193 + 1194 + defmodule Rocksky.Generated.GetMetadataParams do 1195 + @moduledoc false 1196 + @type t :: %__MODULE__{ 1197 + path: String.t() 1198 + } 1199 + @enforce_keys [:path] 1200 + defstruct [:path] 1201 + end 1202 + 1203 + defmodule Rocksky.Generated.GetMirrorSourcesOutput do 1204 + @moduledoc false 1205 + @type t :: %__MODULE__{ 1206 + sources: list(Rocksky.Generated.MirrorSourceView.t()) 1207 + } 1208 + @enforce_keys [:sources] 1209 + defstruct [:sources] 1210 + end 1211 + 1212 + defmodule Rocksky.Generated.GetMirrorSourcesParams do 1213 + @moduledoc false 1214 + @type t :: %__MODULE__{} 1215 + defstruct [] 1216 + end 1217 + 1218 + defmodule Rocksky.Generated.GetPlaybackQueueParams do 1219 + @moduledoc false 1220 + @type t :: %__MODULE__{ 1221 + playerId: String.t() | nil 1222 + } 1223 + defstruct [:playerId] 1224 + end 1225 + 1226 + defmodule Rocksky.Generated.GetPlaylistParams do 1227 + @moduledoc false 1228 + @type t :: %__MODULE__{ 1229 + uri: String.t() 1230 + } 1231 + @enforce_keys [:uri] 1232 + defstruct [:uri] 1233 + end 1234 + 1235 + defmodule Rocksky.Generated.GetPlaylistsOutput do 1236 + @moduledoc false 1237 + @type t :: %__MODULE__{ 1238 + playlists: list(Rocksky.Generated.PlaylistViewBasic.t()) | nil 1239 + } 1240 + defstruct [:playlists] 1241 + end 1242 + 1243 + defmodule Rocksky.Generated.GetPlaylistsParams do 1244 + @moduledoc false 1245 + @type t :: %__MODULE__{ 1246 + limit: integer() | nil, 1247 + offset: integer() | nil 1248 + } 1249 + defstruct [:limit, :offset] 1250 + end 1251 + 1252 + defmodule Rocksky.Generated.GetProfileParams do 1253 + @moduledoc false 1254 + @type t :: %__MODULE__{ 1255 + did: String.t() | nil 1256 + } 1257 + defstruct [:did] 1258 + end 1259 + 1260 + defmodule Rocksky.Generated.GetProfileShoutsOutput do 1261 + @moduledoc false 1262 + @type t :: %__MODULE__{ 1263 + shouts: list(term()) | nil 1264 + } 1265 + defstruct [:shouts] 1266 + end 1267 + 1268 + defmodule Rocksky.Generated.GetProfileShoutsParams do 1269 + @moduledoc false 1270 + @type t :: %__MODULE__{ 1271 + did: String.t(), 1272 + offset: integer() | nil, 1273 + limit: integer() | nil 1274 + } 1275 + @enforce_keys [:did] 1276 + defstruct [:did, :offset, :limit] 1277 + end 1278 + 1279 + defmodule Rocksky.Generated.GetRecommendationsParams do 1280 + @moduledoc false 1281 + @type t :: %__MODULE__{ 1282 + did: String.t(), 1283 + limit: integer() | nil 1284 + } 1285 + @enforce_keys [:did] 1286 + defstruct [:did, :limit] 1287 + end 1288 + 1289 + defmodule Rocksky.Generated.GetScrobbleParams do 1290 + @moduledoc false 1291 + @type t :: %__MODULE__{ 1292 + uri: String.t() 1293 + } 1294 + @enforce_keys [:uri] 1295 + defstruct [:uri] 1296 + end 1297 + 1298 + defmodule Rocksky.Generated.GetScrobblesChartParams do 1299 + @moduledoc false 1300 + @type t :: %__MODULE__{ 1301 + did: String.t() | nil, 1302 + artisturi: String.t() | nil, 1303 + albumuri: String.t() | nil, 1304 + songuri: String.t() | nil, 1305 + genre: String.t() | nil, 1306 + from: String.t() | nil, 1307 + to: String.t() | nil 1308 + } 1309 + defstruct [:did, :artisturi, :albumuri, :songuri, :genre, :from, :to] 1310 + end 1311 + 1312 + defmodule Rocksky.Generated.GetScrobblesOutput do 1313 + @moduledoc false 1314 + @type t :: %__MODULE__{ 1315 + scrobbles: list(Rocksky.Generated.ScrobbleViewBasic.t()) | nil 1316 + } 1317 + defstruct [:scrobbles] 1318 + end 1319 + 1320 + defmodule Rocksky.Generated.GetScrobblesParams do 1321 + @moduledoc false 1322 + @type t :: %__MODULE__{ 1323 + did: String.t() | nil, 1324 + following: boolean() | nil, 1325 + limit: integer() | nil, 1326 + offset: integer() | nil 1327 + } 1328 + defstruct [:did, :following, :limit, :offset] 1329 + end 1330 + 1331 + defmodule Rocksky.Generated.GetShoutRepliesOutput do 1332 + @moduledoc false 1333 + @type t :: %__MODULE__{ 1334 + shouts: list(term()) | nil 1335 + } 1336 + defstruct [:shouts] 1337 + end 1338 + 1339 + defmodule Rocksky.Generated.GetShoutRepliesParams do 1340 + @moduledoc false 1341 + @type t :: %__MODULE__{ 1342 + uri: String.t(), 1343 + limit: integer() | nil, 1344 + offset: integer() | nil 1345 + } 1346 + @enforce_keys [:uri] 1347 + defstruct [:uri, :limit, :offset] 1348 + end 1349 + 1350 + defmodule Rocksky.Generated.GetSongParams do 1351 + @moduledoc false 1352 + @type t :: %__MODULE__{ 1353 + uri: String.t() | nil, 1354 + mbid: String.t() | nil, 1355 + isrc: String.t() | nil, 1356 + spotifyId: String.t() | nil 1357 + } 1358 + defstruct [:uri, :mbid, :isrc, :spotifyId] 1359 + end 1360 + 1361 + defmodule Rocksky.Generated.GetSongRecentListenersOutput do 1362 + @moduledoc false 1363 + @type t :: %__MODULE__{ 1364 + listeners: list(Rocksky.Generated.SongRecentListenerView.t()) | nil 1365 + } 1366 + defstruct [:listeners] 1367 + end 1368 + 1369 + defmodule Rocksky.Generated.GetSongRecentListenersParams do 1370 + @moduledoc false 1371 + @type t :: %__MODULE__{ 1372 + uri: String.t(), 1373 + offset: integer() | nil, 1374 + limit: integer() | nil 1375 + } 1376 + @enforce_keys [:uri] 1377 + defstruct [:uri, :offset, :limit] 1378 + end 1379 + 1380 + defmodule Rocksky.Generated.GetSongsOutput do 1381 + @moduledoc false 1382 + @type t :: %__MODULE__{ 1383 + songs: list(Rocksky.Generated.SongViewBasic.t()) | nil 1384 + } 1385 + defstruct [:songs] 1386 + end 1387 + 1388 + defmodule Rocksky.Generated.GetSongsParams do 1389 + @moduledoc false 1390 + @type t :: %__MODULE__{ 1391 + limit: integer() | nil, 1392 + offset: integer() | nil, 1393 + genre: String.t() | nil, 1394 + mbid: String.t() | nil, 1395 + isrc: String.t() | nil, 1396 + spotifyId: String.t() | nil 1397 + } 1398 + defstruct [:limit, :offset, :genre, :mbid, :isrc, :spotifyId] 1399 + end 1400 + 1401 + defmodule Rocksky.Generated.GetStatsParams do 1402 + @moduledoc false 1403 + @type t :: %__MODULE__{ 1404 + did: String.t() 1405 + } 1406 + @enforce_keys [:did] 1407 + defstruct [:did] 1408 + end 1409 + 1410 + defmodule Rocksky.Generated.GetStoriesParams do 1411 + @moduledoc false 1412 + @type t :: %__MODULE__{ 1413 + size: integer() | nil 1414 + } 1415 + defstruct [:size] 1416 + end 1417 + 1418 + defmodule Rocksky.Generated.GetTemporaryLinkParams do 1419 + @moduledoc false 1420 + @type t :: %__MODULE__{ 1421 + path: String.t() 1422 + } 1423 + @enforce_keys [:path] 1424 + defstruct [:path] 1425 + end 1426 + 1427 + defmodule Rocksky.Generated.GetTopArtistsOutput do 1428 + @moduledoc false 1429 + @type t :: %__MODULE__{ 1430 + artists: list(Rocksky.Generated.ArtistViewBasic.t()) | nil 1431 + } 1432 + defstruct [:artists] 1433 + end 1434 + 1435 + defmodule Rocksky.Generated.GetTopArtistsParams do 1436 + @moduledoc false 1437 + @type t :: %__MODULE__{ 1438 + limit: integer() | nil, 1439 + offset: integer() | nil, 1440 + startDate: String.t() | nil, 1441 + endDate: String.t() | nil 1442 + } 1443 + defstruct [:limit, :offset, :startDate, :endDate] 1444 + end 1445 + 1446 + defmodule Rocksky.Generated.GetTopTracksOutput do 1447 + @moduledoc false 1448 + @type t :: %__MODULE__{ 1449 + tracks: list(Rocksky.Generated.SongViewBasic.t()) | nil 1450 + } 1451 + defstruct [:tracks] 1452 + end 1453 + 1454 + defmodule Rocksky.Generated.GetTopTracksParams do 1455 + @moduledoc false 1456 + @type t :: %__MODULE__{ 1457 + limit: integer() | nil, 1458 + offset: integer() | nil, 1459 + startDate: String.t() | nil, 1460 + endDate: String.t() | nil 1461 + } 1462 + defstruct [:limit, :offset, :startDate, :endDate] 1463 + end 1464 + 1465 + defmodule Rocksky.Generated.GetTrackShoutsOutput do 1466 + @moduledoc false 1467 + @type t :: %__MODULE__{ 1468 + shouts: list(term()) | nil 1469 + } 1470 + defstruct [:shouts] 1471 + end 1472 + 1473 + defmodule Rocksky.Generated.GetTrackShoutsParams do 1474 + @moduledoc false 1475 + @type t :: %__MODULE__{ 1476 + uri: String.t() 1477 + } 1478 + @enforce_keys [:uri] 1479 + defstruct [:uri] 1480 + end 1481 + 1482 + defmodule Rocksky.Generated.GetWrappedParams do 1483 + @moduledoc false 1484 + @type t :: %__MODULE__{ 1485 + did: String.t(), 1486 + year: integer() | nil 1487 + } 1488 + @enforce_keys [:did] 1489 + defstruct [:did, :year] 1490 + end 1491 + 1492 + defmodule Rocksky.Generated.GoogledriveFileListView do 1493 + @moduledoc false 1494 + @type t :: %__MODULE__{ 1495 + files: list(Rocksky.Generated.GoogledriveFileView.t()) | nil 1496 + } 1497 + defstruct [:files] 1498 + end 1499 + 1500 + defmodule Rocksky.Generated.GoogledriveFileView do 1501 + @moduledoc false 1502 + @type t :: %__MODULE__{ 1503 + id: String.t() | nil 1504 + } 1505 + defstruct [:id] 1506 + end 1507 + 1508 + defmodule Rocksky.Generated.GraphNotFoundActor do 1509 + @moduledoc "indicates that a handle or DID could not be resolved" 1510 + @type t :: %__MODULE__{ 1511 + actor: String.t(), 1512 + notFound: boolean() 1513 + } 1514 + @enforce_keys [:actor, :notFound] 1515 + defstruct [:actor, :notFound] 1516 + end 1517 + 1518 + defmodule Rocksky.Generated.GraphRelationship do 1519 + @moduledoc false 1520 + @type t :: %__MODULE__{ 1521 + did: String.t(), 1522 + following: String.t() | nil, 1523 + followedBy: String.t() | nil 1524 + } 1525 + @enforce_keys [:did] 1526 + defstruct [:did, :following, :followedBy] 1527 + end 1528 + 1529 + defmodule Rocksky.Generated.InsertDirectoryParams do 1530 + @moduledoc false 1531 + @type t :: %__MODULE__{ 1532 + uri: String.t(), 1533 + directory: String.t(), 1534 + position: integer() | nil 1535 + } 1536 + @enforce_keys [:uri, :directory] 1537 + defstruct [:uri, :directory, :position] 1538 + end 1539 + 1540 + defmodule Rocksky.Generated.InsertFilesParams do 1541 + @moduledoc false 1542 + @type t :: %__MODULE__{ 1543 + uri: String.t(), 1544 + files: list(String.t()), 1545 + position: integer() | nil 1546 + } 1547 + @enforce_keys [:uri, :files] 1548 + defstruct [:uri, :files, :position] 1549 + end 1550 + 1551 + defmodule Rocksky.Generated.LikeRecord do 1552 + @moduledoc false 1553 + @type t :: %__MODULE__{ 1554 + createdAt: String.t(), 1555 + subject: Rocksky.Generated.StrongRef.t() 1556 + } 1557 + @enforce_keys [:createdAt, :subject] 1558 + defstruct [:createdAt, :subject] 1559 + end 1560 + 1561 + defmodule Rocksky.Generated.LikeShoutInput do 1562 + @moduledoc false 1563 + @type t :: %__MODULE__{ 1564 + uri: String.t() | nil 1565 + } 1566 + defstruct [:uri] 1567 + end 1568 + 1569 + defmodule Rocksky.Generated.LikeSongInput do 1570 + @moduledoc false 1571 + @type t :: %__MODULE__{ 1572 + uri: String.t() | nil 1573 + } 1574 + defstruct [:uri] 1575 + end 1576 + 1577 + defmodule Rocksky.Generated.MatchSongParams do 1578 + @moduledoc false 1579 + @type t :: %__MODULE__{ 1580 + title: String.t(), 1581 + artist: String.t(), 1582 + mbId: String.t() | nil, 1583 + isrc: String.t() | nil 1584 + } 1585 + @enforce_keys [:title, :artist] 1586 + defstruct [:title, :artist, :mbId, :isrc] 1587 + end 1588 + 1589 + defmodule Rocksky.Generated.MirrorSourceView do 1590 + @moduledoc false 1591 + @type t :: %__MODULE__{ 1592 + provider: String.t(), 1593 + enabled: boolean(), 1594 + externalUsername: String.t() | nil, 1595 + hasCredentials: boolean(), 1596 + lastPolledAt: String.t() | nil, 1597 + lastScrobbleSeenAt: String.t() | nil 1598 + } 1599 + @enforce_keys [:provider, :enabled, :hasCredentials] 1600 + defstruct [:provider, :enabled, :externalUsername, :hasCredentials, :lastPolledAt, :lastScrobbleSeenAt] 1601 + end 1602 + 1603 + defmodule Rocksky.Generated.NextParams do 1604 + @moduledoc false 1605 + @type t :: %__MODULE__{ 1606 + playerId: String.t() | nil 1607 + } 1608 + defstruct [:playerId] 1609 + end 1610 + 1611 + defmodule Rocksky.Generated.PauseParams do 1612 + @moduledoc false 1613 + @type t :: %__MODULE__{ 1614 + playerId: String.t() | nil 1615 + } 1616 + defstruct [:playerId] 1617 + end 1618 + 1619 + defmodule Rocksky.Generated.PlayDirectoryParams do 1620 + @moduledoc false 1621 + @type t :: %__MODULE__{ 1622 + playerId: String.t() | nil, 1623 + directoryId: String.t(), 1624 + shuffle: boolean() | nil, 1625 + recurse: boolean() | nil, 1626 + position: integer() | nil 1627 + } 1628 + @enforce_keys [:directoryId] 1629 + defstruct [:playerId, :directoryId, :shuffle, :recurse, :position] 1630 + end 1631 + 1632 + defmodule Rocksky.Generated.PlayerCurrentlyPlayingViewDetailed do 1633 + @moduledoc false 1634 + @type t :: %__MODULE__{ 1635 + title: String.t() | nil 1636 + } 1637 + defstruct [:title] 1638 + end 1639 + 1640 + defmodule Rocksky.Generated.PlayerPlaybackQueueViewDetailed do 1641 + @moduledoc false 1642 + @type t :: %__MODULE__{ 1643 + tracks: list(Rocksky.Generated.SongViewBasic.t()) | nil 1644 + } 1645 + defstruct [:tracks] 1646 + end 1647 + 1648 + defmodule Rocksky.Generated.PlayFileParams do 1649 + @moduledoc false 1650 + @type t :: %__MODULE__{ 1651 + playerId: String.t() | nil, 1652 + fileId: String.t() 1653 + } 1654 + @enforce_keys [:fileId] 1655 + defstruct [:playerId, :fileId] 1656 + end 1657 + 1658 + defmodule Rocksky.Generated.PlaylistItemRecord do 1659 + @moduledoc false 1660 + @type t :: %__MODULE__{ 1661 + subject: Rocksky.Generated.StrongRef.t(), 1662 + createdAt: String.t(), 1663 + track: Rocksky.Generated.SongViewBasic.t(), 1664 + order: integer() 1665 + } 1666 + @enforce_keys [:subject, :createdAt, :track, :order] 1667 + defstruct [:subject, :createdAt, :track, :order] 1668 + end 1669 + 1670 + defmodule Rocksky.Generated.PlaylistRecord do 1671 + @moduledoc false 1672 + @type t :: %__MODULE__{ 1673 + name: String.t(), 1674 + description: String.t() | nil, 1675 + picture: Rocksky.Generated.BlobRef.t() | nil, 1676 + pictureUrl: String.t() | nil, 1677 + createdAt: String.t(), 1678 + spotifyLink: String.t() | nil, 1679 + tidalLink: String.t() | nil, 1680 + youtubeLink: String.t() | nil, 1681 + appleMusicLink: String.t() | nil 1682 + } 1683 + @enforce_keys [:name, :createdAt] 1684 + defstruct [:name, :description, :picture, :pictureUrl, :createdAt, :spotifyLink, :tidalLink, :youtubeLink, :appleMusicLink] 1685 + end 1686 + 1687 + defmodule Rocksky.Generated.PlaylistViewBasic do 1688 + @moduledoc "Basic view of a playlist, including its metadata" 1689 + @type t :: %__MODULE__{ 1690 + id: String.t() | nil, 1691 + title: String.t() | nil, 1692 + uri: String.t() | nil, 1693 + curatorDid: String.t() | nil, 1694 + curatorHandle: String.t() | nil, 1695 + curatorName: String.t() | nil, 1696 + curatorAvatarUrl: String.t() | nil, 1697 + description: String.t() | nil, 1698 + coverImageUrl: String.t() | nil, 1699 + createdAt: String.t() | nil, 1700 + trackCount: integer() | nil 1701 + } 1702 + defstruct [:id, :title, :uri, :curatorDid, :curatorHandle, :curatorName, :curatorAvatarUrl, :description, :coverImageUrl, :createdAt, :trackCount] 1703 + end 1704 + 1705 + defmodule Rocksky.Generated.PlaylistViewDetailed do 1706 + @moduledoc "Detailed view of a playlist, including its tracks and metadata" 1707 + @type t :: %__MODULE__{ 1708 + id: String.t() | nil, 1709 + title: String.t() | nil, 1710 + uri: String.t() | nil, 1711 + curatorDid: String.t() | nil, 1712 + curatorHandle: String.t() | nil, 1713 + curatorName: String.t() | nil, 1714 + curatorAvatarUrl: String.t() | nil, 1715 + description: String.t() | nil, 1716 + coverImageUrl: String.t() | nil, 1717 + createdAt: String.t() | nil, 1718 + tracks: list(Rocksky.Generated.SongViewBasic.t()) | nil 1719 + } 1720 + defstruct [:id, :title, :uri, :curatorDid, :curatorHandle, :curatorName, :curatorAvatarUrl, :description, :coverImageUrl, :createdAt, :tracks] 1721 + end 1722 + 1723 + defmodule Rocksky.Generated.PlayParams do 1724 + @moduledoc false 1725 + @type t :: %__MODULE__{ 1726 + playerId: String.t() | nil 1727 + } 1728 + defstruct [:playerId] 1729 + end 1730 + 1731 + defmodule Rocksky.Generated.PreviousParams do 1732 + @moduledoc false 1733 + @type t :: %__MODULE__{ 1734 + playerId: String.t() | nil 1735 + } 1736 + defstruct [:playerId] 1737 + end 1738 + 1739 + defmodule Rocksky.Generated.ProfileRecord do 1740 + @moduledoc false 1741 + @type t :: %__MODULE__{ 1742 + displayName: String.t() | nil, 1743 + description: String.t() | nil, 1744 + avatar: Rocksky.Generated.BlobRef.t() | nil, 1745 + banner: Rocksky.Generated.BlobRef.t() | nil, 1746 + labels: term() | nil, 1747 + joinedViaStarterPack: Rocksky.Generated.StrongRef.t() | nil, 1748 + createdAt: String.t() | nil 1749 + } 1750 + defstruct [:displayName, :description, :avatar, :banner, :labels, :joinedViaStarterPack, :createdAt] 1751 + end 1752 + 1753 + defmodule Rocksky.Generated.PutMirrorSourceInput do 1754 + @moduledoc false 1755 + @type t :: %__MODULE__{ 1756 + provider: String.t(), 1757 + enabled: boolean() | nil, 1758 + externalUsername: String.t() | nil, 1759 + apiKey: String.t() | nil 1760 + } 1761 + @enforce_keys [:provider] 1762 + defstruct [:provider, :enabled, :externalUsername, :apiKey] 1763 + end 1764 + 1765 + defmodule Rocksky.Generated.RadioRecord do 1766 + @moduledoc false 1767 + @type t :: %__MODULE__{ 1768 + name: String.t(), 1769 + url: String.t(), 1770 + description: String.t() | nil, 1771 + genre: String.t() | nil, 1772 + logo: Rocksky.Generated.BlobRef.t() | nil, 1773 + website: String.t() | nil, 1774 + createdAt: String.t() 1775 + } 1776 + @enforce_keys [:name, :url, :createdAt] 1777 + defstruct [:name, :url, :description, :genre, :logo, :website, :createdAt] 1778 + end 1779 + 1780 + defmodule Rocksky.Generated.RadioViewBasic do 1781 + @moduledoc false 1782 + @type t :: %__MODULE__{ 1783 + id: String.t() | nil, 1784 + name: String.t() | nil, 1785 + description: String.t() | nil, 1786 + createdAt: String.t() | nil 1787 + } 1788 + defstruct [:id, :name, :description, :createdAt] 1789 + end 1790 + 1791 + defmodule Rocksky.Generated.RadioViewDetailed do 1792 + @moduledoc false 1793 + @type t :: %__MODULE__{ 1794 + id: String.t() | nil, 1795 + name: String.t() | nil, 1796 + description: String.t() | nil, 1797 + website: String.t() | nil, 1798 + url: String.t() | nil, 1799 + genre: String.t() | nil, 1800 + logo: String.t() | nil, 1801 + createdAt: String.t() | nil 1802 + } 1803 + defstruct [:id, :name, :description, :website, :url, :genre, :logo, :createdAt] 1804 + end 1805 + 1806 + defmodule Rocksky.Generated.RemoveApikeyParams do 1807 + @moduledoc false 1808 + @type t :: %__MODULE__{ 1809 + id: String.t() 1810 + } 1811 + @enforce_keys [:id] 1812 + defstruct [:id] 1813 + end 1814 + 1815 + defmodule Rocksky.Generated.RemovePlaylistParams do 1816 + @moduledoc false 1817 + @type t :: %__MODULE__{ 1818 + uri: String.t() 1819 + } 1820 + @enforce_keys [:uri] 1821 + defstruct [:uri] 1822 + end 1823 + 1824 + defmodule Rocksky.Generated.RemoveShoutParams do 1825 + @moduledoc false 1826 + @type t :: %__MODULE__{ 1827 + id: String.t() 1828 + } 1829 + @enforce_keys [:id] 1830 + defstruct [:id] 1831 + end 1832 + 1833 + defmodule Rocksky.Generated.RemoveTrackParams do 1834 + @moduledoc false 1835 + @type t :: %__MODULE__{ 1836 + uri: String.t(), 1837 + position: integer() 1838 + } 1839 + @enforce_keys [:uri, :position] 1840 + defstruct [:uri, :position] 1841 + end 1842 + 1843 + defmodule Rocksky.Generated.ReplyShoutInput do 1844 + @moduledoc false 1845 + @type t :: %__MODULE__{ 1846 + shoutId: String.t(), 1847 + message: String.t() 1848 + } 1849 + @enforce_keys [:shoutId, :message] 1850 + defstruct [:shoutId, :message] 1851 + end 1852 + 1853 + defmodule Rocksky.Generated.ReportShoutInput do 1854 + @moduledoc false 1855 + @type t :: %__MODULE__{ 1856 + shoutId: String.t(), 1857 + reason: String.t() | nil 1858 + } 1859 + @enforce_keys [:shoutId] 1860 + defstruct [:shoutId, :reason] 1861 + end 1862 + 1863 + defmodule Rocksky.Generated.ScrobbleFirstScrobbleView do 1864 + @moduledoc false 1865 + @type t :: %__MODULE__{ 1866 + handle: String.t() | nil, 1867 + avatar: String.t() | nil, 1868 + timestamp: String.t() | nil 1869 + } 1870 + defstruct [:handle, :avatar, :timestamp] 1871 + end 1872 + 1873 + defmodule Rocksky.Generated.ScrobbleRecord do 1874 + @moduledoc false 1875 + @type t :: %__MODULE__{ 1876 + title: String.t(), 1877 + artist: String.t(), 1878 + artists: list(Rocksky.Generated.ArtistMbid.t()) | nil, 1879 + albumArtist: String.t(), 1880 + album: String.t(), 1881 + duration: integer(), 1882 + trackNumber: integer() | nil, 1883 + discNumber: integer() | nil, 1884 + releaseDate: String.t() | nil, 1885 + year: integer() | nil, 1886 + genre: String.t() | nil, 1887 + tags: list(String.t()) | nil, 1888 + composer: String.t() | nil, 1889 + lyrics: String.t() | nil, 1890 + copyrightMessage: String.t() | nil, 1891 + wiki: String.t() | nil, 1892 + albumArt: Rocksky.Generated.BlobRef.t() | nil, 1893 + albumArtUrl: String.t() | nil, 1894 + youtubeLink: String.t() | nil, 1895 + spotifyLink: String.t() | nil, 1896 + tidalLink: String.t() | nil, 1897 + appleMusicLink: String.t() | nil, 1898 + createdAt: String.t(), 1899 + mbid: String.t() | nil, 1900 + label: String.t() | nil, 1901 + isrc: String.t() | nil 1902 + } 1903 + @enforce_keys [:title, :artist, :albumArtist, :album, :duration, :createdAt] 1904 + defstruct [:title, :artist, :artists, :albumArtist, :album, :duration, :trackNumber, :discNumber, :releaseDate, :year, :genre, :tags, :composer, :lyrics, :copyrightMessage, :wiki, :albumArt, :albumArtUrl, :youtubeLink, :spotifyLink, :tidalLink, :appleMusicLink, :createdAt, :mbid, :label, :isrc] 1905 + end 1906 + 1907 + defmodule Rocksky.Generated.ScrobbleViewBasic do 1908 + @moduledoc false 1909 + @type t :: %__MODULE__{ 1910 + id: String.t() | nil, 1911 + user: String.t() | nil, 1912 + userDisplayName: String.t() | nil, 1913 + userAvatar: String.t() | nil, 1914 + title: String.t() | nil, 1915 + artist: String.t() | nil, 1916 + artistUri: String.t() | nil, 1917 + album: String.t() | nil, 1918 + albumUri: String.t() | nil, 1919 + cover: String.t() | nil, 1920 + date: String.t() | nil, 1921 + uri: String.t() | nil, 1922 + sha256: String.t() | nil, 1923 + liked: boolean() | nil, 1924 + likesCount: integer() | nil 1925 + } 1926 + defstruct [:id, :user, :userDisplayName, :userAvatar, :title, :artist, :artistUri, :album, :albumUri, :cover, :date, :uri, :sha256, :liked, :likesCount] 1927 + end 1928 + 1929 + defmodule Rocksky.Generated.ScrobbleViewDetailed do 1930 + @moduledoc false 1931 + @type t :: %__MODULE__{ 1932 + id: String.t() | nil, 1933 + user: String.t() | nil, 1934 + title: String.t() | nil, 1935 + artist: String.t() | nil, 1936 + artistUri: String.t() | nil, 1937 + album: String.t() | nil, 1938 + albumUri: String.t() | nil, 1939 + cover: String.t() | nil, 1940 + date: String.t() | nil, 1941 + uri: String.t() | nil, 1942 + sha256: String.t() | nil, 1943 + liked: boolean() | nil, 1944 + likesCount: integer() | nil, 1945 + listeners: integer() | nil, 1946 + scrobbles: integer() | nil, 1947 + artists: list(Rocksky.Generated.ArtistViewBasic.t()) | nil, 1948 + firstScrobble: Rocksky.Generated.ScrobbleFirstScrobbleView.t() | nil 1949 + } 1950 + defstruct [:id, :user, :title, :artist, :artistUri, :album, :albumUri, :cover, :date, :uri, :sha256, :liked, :likesCount, :listeners, :scrobbles, :artists, :firstScrobble] 1951 + end 1952 + 1953 + defmodule Rocksky.Generated.SearchParams do 1954 + @moduledoc false 1955 + @type t :: %__MODULE__{ 1956 + query: String.t() 1957 + } 1958 + @enforce_keys [:query] 1959 + defstruct [:query] 1960 + end 1961 + 1962 + defmodule Rocksky.Generated.SeekParams do 1963 + @moduledoc false 1964 + @type t :: %__MODULE__{ 1965 + playerId: String.t() | nil, 1966 + position: integer() 1967 + } 1968 + @enforce_keys [:position] 1969 + defstruct [:playerId, :position] 1970 + end 1971 + 1972 + defmodule Rocksky.Generated.ShoutAuthor do 1973 + @moduledoc false 1974 + @type t :: %__MODULE__{ 1975 + id: String.t() | nil, 1976 + did: String.t() | nil, 1977 + handle: String.t() | nil, 1978 + displayName: String.t() | nil, 1979 + avatar: String.t() | nil 1980 + } 1981 + defstruct [:id, :did, :handle, :displayName, :avatar] 1982 + end 1983 + 1984 + defmodule Rocksky.Generated.ShoutRecord do 1985 + @moduledoc false 1986 + @type t :: %__MODULE__{ 1987 + message: String.t(), 1988 + createdAt: String.t(), 1989 + parent: Rocksky.Generated.StrongRef.t() | nil, 1990 + subject: Rocksky.Generated.StrongRef.t() 1991 + } 1992 + @enforce_keys [:message, :createdAt, :subject] 1993 + defstruct [:message, :createdAt, :parent, :subject] 1994 + end 1995 + 1996 + defmodule Rocksky.Generated.ShoutView do 1997 + @moduledoc false 1998 + @type t :: %__MODULE__{ 1999 + id: String.t() | nil, 2000 + message: String.t() | nil, 2001 + parent: String.t() | nil, 2002 + createdAt: String.t() | nil, 2003 + author: Rocksky.Generated.ShoutAuthor.t() | nil 2004 + } 2005 + defstruct [:id, :message, :parent, :createdAt, :author] 2006 + end 2007 + 2008 + defmodule Rocksky.Generated.SongFirstScrobbleView do 2009 + @moduledoc false 2010 + @type t :: %__MODULE__{ 2011 + handle: String.t() | nil, 2012 + avatar: String.t() | nil, 2013 + timestamp: String.t() | nil 2014 + } 2015 + defstruct [:handle, :avatar, :timestamp] 2016 + end 2017 + 2018 + defmodule Rocksky.Generated.SongRecentListenerView do 2019 + @moduledoc false 2020 + @type t :: %__MODULE__{ 2021 + id: String.t() | nil, 2022 + did: String.t() | nil, 2023 + handle: String.t() | nil, 2024 + displayName: String.t() | nil, 2025 + avatar: String.t() | nil, 2026 + timestamp: String.t() | nil, 2027 + scrobbleUri: String.t() | nil 2028 + } 2029 + defstruct [:id, :did, :handle, :displayName, :avatar, :timestamp, :scrobbleUri] 2030 + end 2031 + 2032 + defmodule Rocksky.Generated.SongRecord do 2033 + @moduledoc false 2034 + @type t :: %__MODULE__{ 2035 + title: String.t(), 2036 + artist: String.t(), 2037 + artists: list(Rocksky.Generated.ArtistMbid.t()) | nil, 2038 + albumArtist: String.t(), 2039 + album: String.t(), 2040 + duration: integer(), 2041 + trackNumber: integer() | nil, 2042 + discNumber: integer() | nil, 2043 + releaseDate: String.t() | nil, 2044 + year: integer() | nil, 2045 + genre: String.t() | nil, 2046 + tags: list(String.t()) | nil, 2047 + composer: String.t() | nil, 2048 + lyrics: String.t() | nil, 2049 + copyrightMessage: String.t() | nil, 2050 + wiki: String.t() | nil, 2051 + albumArt: Rocksky.Generated.BlobRef.t() | nil, 2052 + albumArtUrl: String.t() | nil, 2053 + youtubeLink: String.t() | nil, 2054 + spotifyLink: String.t() | nil, 2055 + tidalLink: String.t() | nil, 2056 + appleMusicLink: String.t() | nil, 2057 + createdAt: String.t(), 2058 + mbid: String.t() | nil, 2059 + label: String.t() | nil, 2060 + isrc: String.t() | nil 2061 + } 2062 + @enforce_keys [:title, :artist, :albumArtist, :album, :duration, :createdAt] 2063 + defstruct [:title, :artist, :artists, :albumArtist, :album, :duration, :trackNumber, :discNumber, :releaseDate, :year, :genre, :tags, :composer, :lyrics, :copyrightMessage, :wiki, :albumArt, :albumArtUrl, :youtubeLink, :spotifyLink, :tidalLink, :appleMusicLink, :createdAt, :mbid, :label, :isrc] 2064 + end 2065 + 2066 + defmodule Rocksky.Generated.SongViewBasic do 2067 + @moduledoc false 2068 + @type t :: %__MODULE__{ 2069 + id: String.t() | nil, 2070 + title: String.t() | nil, 2071 + artist: String.t() | nil, 2072 + albumArtist: String.t() | nil, 2073 + albumArt: String.t() | nil, 2074 + uri: String.t() | nil, 2075 + album: String.t() | nil, 2076 + duration: integer() | nil, 2077 + trackNumber: integer() | nil, 2078 + discNumber: integer() | nil, 2079 + playCount: integer() | nil, 2080 + uniqueListeners: integer() | nil, 2081 + albumUri: String.t() | nil, 2082 + artistUri: String.t() | nil, 2083 + sha256: String.t() | nil, 2084 + mbid: String.t() | nil, 2085 + isrc: String.t() | nil, 2086 + tags: list(String.t()) | nil, 2087 + createdAt: String.t() | nil 2088 + } 2089 + defstruct [:id, :title, :artist, :albumArtist, :albumArt, :uri, :album, :duration, :trackNumber, :discNumber, :playCount, :uniqueListeners, :albumUri, :artistUri, :sha256, :mbid, :isrc, :tags, :createdAt] 2090 + end 2091 + 2092 + defmodule Rocksky.Generated.SongViewDetailed do 2093 + @moduledoc false 2094 + @type t :: %__MODULE__{ 2095 + id: String.t() | nil, 2096 + title: String.t() | nil, 2097 + artist: String.t() | nil, 2098 + albumArtist: String.t() | nil, 2099 + albumArt: String.t() | nil, 2100 + uri: String.t() | nil, 2101 + album: String.t() | nil, 2102 + duration: integer() | nil, 2103 + trackNumber: integer() | nil, 2104 + discNumber: integer() | nil, 2105 + playCount: integer() | nil, 2106 + uniqueListeners: integer() | nil, 2107 + albumUri: String.t() | nil, 2108 + artistUri: String.t() | nil, 2109 + sha256: String.t() | nil, 2110 + mbid: String.t() | nil, 2111 + isrc: String.t() | nil, 2112 + tags: list(String.t()) | nil, 2113 + createdAt: String.t() | nil, 2114 + artists: list(Rocksky.Generated.ArtistViewBasic.t()) | nil, 2115 + firstScrobble: Rocksky.Generated.SongFirstScrobbleView.t() | nil 2116 + } 2117 + defstruct [:id, :title, :artist, :albumArtist, :albumArt, :uri, :album, :duration, :trackNumber, :discNumber, :playCount, :uniqueListeners, :albumUri, :artistUri, :sha256, :mbid, :isrc, :tags, :createdAt, :artists, :firstScrobble] 2118 + end 2119 + 2120 + defmodule Rocksky.Generated.SpotifyTrackView do 2121 + @moduledoc false 2122 + @type t :: %__MODULE__{ 2123 + id: String.t() | nil, 2124 + name: String.t() | nil, 2125 + artist: String.t() | nil, 2126 + album: String.t() | nil, 2127 + duration: integer() | nil, 2128 + previewUrl: String.t() | nil 2129 + } 2130 + defstruct [:id, :name, :artist, :album, :duration, :previewUrl] 2131 + end 2132 + 2133 + defmodule Rocksky.Generated.StartPlaylistParams do 2134 + @moduledoc false 2135 + @type t :: %__MODULE__{ 2136 + uri: String.t(), 2137 + shuffle: boolean() | nil, 2138 + position: integer() | nil 2139 + } 2140 + @enforce_keys [:uri] 2141 + defstruct [:uri, :shuffle, :position] 2142 + end 2143 + 2144 + defmodule Rocksky.Generated.StatsView do 2145 + @moduledoc false 2146 + @type t :: %__MODULE__{ 2147 + scrobbles: integer() | nil, 2148 + artists: integer() | nil, 2149 + lovedTracks: integer() | nil, 2150 + albums: integer() | nil, 2151 + tracks: integer() | nil 2152 + } 2153 + defstruct [:scrobbles, :artists, :lovedTracks, :albums, :tracks] 2154 + end 2155 + 2156 + defmodule Rocksky.Generated.StatsWrappedAlbum do 2157 + @moduledoc false 2158 + @type t :: %__MODULE__{ 2159 + id: String.t() | nil, 2160 + title: String.t() | nil, 2161 + artist: String.t() | nil, 2162 + albumArt: String.t() | nil, 2163 + uri: String.t() | nil, 2164 + playCount: integer() | nil 2165 + } 2166 + defstruct [:id, :title, :artist, :albumArt, :uri, :playCount] 2167 + end 2168 + 2169 + defmodule Rocksky.Generated.StatsWrappedArtist do 2170 + @moduledoc false 2171 + @type t :: %__MODULE__{ 2172 + id: String.t() | nil, 2173 + name: String.t() | nil, 2174 + picture: String.t() | nil, 2175 + uri: String.t() | nil, 2176 + playCount: integer() | nil 2177 + } 2178 + defstruct [:id, :name, :picture, :uri, :playCount] 2179 + end 2180 + 2181 + defmodule Rocksky.Generated.StatsWrappedDayCount do 2182 + @moduledoc false 2183 + @type t :: %__MODULE__{ 2184 + date: String.t() | nil, 2185 + count: integer() | nil 2186 + } 2187 + defstruct [:date, :count] 2188 + end 2189 + 2190 + defmodule Rocksky.Generated.StatsWrappedGenreCount do 2191 + @moduledoc false 2192 + @type t :: %__MODULE__{ 2193 + genre: String.t() | nil, 2194 + count: integer() | nil 2195 + } 2196 + defstruct [:genre, :count] 2197 + end 2198 + 2199 + defmodule Rocksky.Generated.StatsWrappedMilestone do 2200 + @moduledoc false 2201 + @type t :: %__MODULE__{ 2202 + trackTitle: String.t() | nil, 2203 + artistName: String.t() | nil, 2204 + timestamp: String.t() | nil, 2205 + trackUri: String.t() | nil 2206 + } 2207 + defstruct [:trackTitle, :artistName, :timestamp, :trackUri] 2208 + end 2209 + 2210 + defmodule Rocksky.Generated.StatsWrappedMonthCount do 2211 + @moduledoc false 2212 + @type t :: %__MODULE__{ 2213 + month: integer() | nil, 2214 + count: integer() | nil 2215 + } 2216 + defstruct [:month, :count] 2217 + end 2218 + 2219 + defmodule Rocksky.Generated.StatsWrappedTrack do 2220 + @moduledoc false 2221 + @type t :: %__MODULE__{ 2222 + id: String.t() | nil, 2223 + title: String.t() | nil, 2224 + artist: String.t() | nil, 2225 + albumArt: String.t() | nil, 2226 + uri: String.t() | nil, 2227 + artistUri: String.t() | nil, 2228 + albumUri: String.t() | nil, 2229 + playCount: integer() | nil 2230 + } 2231 + defstruct [:id, :title, :artist, :albumArt, :uri, :artistUri, :albumUri, :playCount] 2232 + end 2233 + 2234 + defmodule Rocksky.Generated.StatsWrappedView do 2235 + @moduledoc false 2236 + @type t :: %__MODULE__{ 2237 + year: integer() | nil, 2238 + totalScrobbles: integer() | nil, 2239 + totalListeningTimeMinutes: integer() | nil, 2240 + topArtists: list(Rocksky.Generated.StatsWrappedArtist.t()) | nil, 2241 + topTracks: list(Rocksky.Generated.StatsWrappedTrack.t()) | nil, 2242 + topAlbums: list(Rocksky.Generated.StatsWrappedAlbum.t()) | nil, 2243 + topGenres: list(Rocksky.Generated.StatsWrappedGenreCount.t()) | nil, 2244 + scrobblesPerMonth: list(Rocksky.Generated.StatsWrappedMonthCount.t()) | nil, 2245 + mostActiveDay: Rocksky.Generated.StatsWrappedDayCount.t() | nil, 2246 + mostActiveHour: integer() | nil, 2247 + newArtistsCount: integer() | nil, 2248 + longestStreak: integer() | nil, 2249 + firstScrobble: Rocksky.Generated.StatsWrappedMilestone.t() | nil, 2250 + lastScrobble: Rocksky.Generated.StatsWrappedMilestone.t() | nil 2251 + } 2252 + defstruct [:year, :totalScrobbles, :totalListeningTimeMinutes, :topArtists, :topTracks, :topAlbums, :topGenres, :scrobblesPerMonth, :mostActiveDay, :mostActiveHour, :newArtistsCount, :longestStreak, :firstScrobble, :lastScrobble] 2253 + end 2254 + 2255 + defmodule Rocksky.Generated.StatusRecord do 2256 + @moduledoc false 2257 + @type t :: %__MODULE__{ 2258 + track: Rocksky.Generated.ActorTrackView.t(), 2259 + startedAt: String.t(), 2260 + expiresAt: String.t() | nil 2261 + } 2262 + @enforce_keys [:track, :startedAt] 2263 + defstruct [:track, :startedAt, :expiresAt] 2264 + end 2265 + 2266 + defmodule Rocksky.Generated.StrongRef do 2267 + @moduledoc false 2268 + @type t :: %__MODULE__{ 2269 + uri: String.t(), 2270 + cid: String.t() 2271 + } 2272 + @enforce_keys [:uri, :cid] 2273 + defstruct [:uri, :cid] 2274 + end 2275 + 2276 + defmodule Rocksky.Generated.UnfollowAccountOutput do 2277 + @moduledoc false 2278 + @type t :: %__MODULE__{ 2279 + subject: Rocksky.Generated.ActorProfileViewBasic.t(), 2280 + followers: list(Rocksky.Generated.ActorProfileViewBasic.t()), 2281 + cursor: String.t() | nil 2282 + } 2283 + @enforce_keys [:subject, :followers] 2284 + defstruct [:subject, :followers, :cursor] 2285 + end 2286 + 2287 + defmodule Rocksky.Generated.UnfollowAccountParams do 2288 + @moduledoc false 2289 + @type t :: %__MODULE__{ 2290 + account: String.t() 2291 + } 2292 + @enforce_keys [:account] 2293 + defstruct [:account] 2294 + end 2295 + 2296 + defmodule Rocksky.Generated.UpdateApikeyInput do 2297 + @moduledoc false 2298 + @type t :: %__MODULE__{ 2299 + id: String.t(), 2300 + name: String.t(), 2301 + description: String.t() | nil 2302 + } 2303 + @enforce_keys [:id, :name] 2304 + defstruct [:id, :name, :description] 2305 + end
+1 -1
sdk/elixir/mix.exs
··· 1 1 defmodule Rocksky.MixProject do 2 2 use Mix.Project 3 3 4 - @version "0.1.0" 4 + @version "0.2.0" 5 5 @source_url "https://github.com/tsirysndr/rocksky" 6 6 7 7 def project do
+5
sdk/gleam/README.md
··· 192 192 |> rocksky.send(client) 193 193 ``` 194 194 195 + ## Types 196 + 197 + Most public model types alias the lexicon-derived shapes in `rocksky/generated/types`, mirroring every lex `*View*` / `*Record` / `*Input` / `*Output` / `*Params` shape from [the Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons). `ApiKey` and `Shout` are hand-written because they carry fields the lexicon does not yet declare. Regenerate with `bun run lexgen:types` at the repo root. 198 + 199 + 195 200 ## Examples 196 201 197 202 Runnable examples live under [`src/examples/`](./src/examples) so they are
+1 -1
sdk/gleam/gleam.toml
··· 1 1 name = "rocksky" 2 - version = "1.0.0" 2 + version = "1.1.0" 3 3 4 4 description = "Gleam SDK for the Rocksky XRPC API" 5 5 licences = ["MIT"]
+30 -12
sdk/gleam/src/rocksky/decoders.gleam
··· 4 4 5 5 import gleam/dynamic/decode.{type Decoder} 6 6 import gleam/option.{None, Some} 7 - import rocksky/types.{ 8 - type Album, type ApiKey, type Artist, type Listener, type Profile, 9 - type Scrobble, type Shout, type Song, type Stats, Album, ApiKey, Artist, 10 - Listener, Profile, Scrobble, Shout, Song, Stats, 11 - } 7 + import rocksky/generated/types as gen 8 + import rocksky/types.{type ApiKey, type Shout, ApiKey, Shout} 9 + 10 + pub type Profile = 11 + gen.ActorProfileViewBasic 12 + 13 + pub type Artist = 14 + gen.ArtistViewBasic 15 + 16 + pub type Album = 17 + gen.AlbumViewBasic 18 + 19 + pub type Song = 20 + gen.SongViewBasic 21 + 22 + pub type Scrobble = 23 + gen.ScrobbleViewBasic 24 + 25 + pub type Listener = 26 + gen.SongRecentListenerView 27 + 28 + pub type Stats = 29 + gen.StatsView 12 30 13 31 // ----- helpers -------------------------------------------------------------- 14 32 ··· 53 71 use avatar <- decode.then(opt_string("avatar")) 54 72 use created_at <- decode.then(opt_string("createdAt")) 55 73 use updated_at <- decode.then(opt_string("updatedAt")) 56 - decode.success(Profile( 74 + decode.success(gen.ActorProfileViewBasic( 57 75 id: id, 58 76 did: did, 59 77 handle: handle, ··· 73 91 use play_count <- decode.then(opt_int("playCount")) 74 92 use unique_listeners <- decode.then(opt_int("uniqueListeners")) 75 93 use tags <- decode.then(string_list("tags")) 76 - decode.success(Artist( 94 + decode.success(gen.ArtistViewBasic( 77 95 id: id, 78 96 uri: uri, 79 97 name: name, ··· 97 115 use sha256 <- decode.then(opt_string("sha256")) 98 116 use play_count <- decode.then(opt_int("playCount")) 99 117 use unique_listeners <- decode.then(opt_int("uniqueListeners")) 100 - decode.success(Album( 118 + decode.success(gen.AlbumViewBasic( 101 119 id: id, 102 120 uri: uri, 103 121 title: title, ··· 132 150 use isrc <- decode.then(opt_string("isrc")) 133 151 use tags <- decode.then(string_list("tags")) 134 152 use created_at <- decode.then(opt_string("createdAt")) 135 - decode.success(Song( 153 + decode.success(gen.SongViewBasic( 136 154 id: id, 137 155 uri: uri, 138 156 title: title, ··· 171 189 use sha256 <- decode.then(opt_string("sha256")) 172 190 use liked <- decode.then(opt_bool("liked")) 173 191 use likes_count <- decode.then(opt_int("likesCount")) 174 - decode.success(Scrobble( 192 + decode.success(gen.ScrobbleViewBasic( 175 193 id: id, 176 194 uri: uri, 177 195 user: user, ··· 198 216 use avatar <- decode.then(opt_string("avatar")) 199 217 use timestamp <- decode.then(opt_string("timestamp")) 200 218 use scrobble_uri <- decode.then(opt_string("scrobbleUri")) 201 - decode.success(Listener( 219 + decode.success(gen.SongRecentListenerView( 202 220 id: id, 203 221 did: did, 204 222 handle: handle, ··· 215 233 use loved_tracks <- decode.then(opt_int("lovedTracks")) 216 234 use albums <- decode.then(opt_int("albums")) 217 235 use tracks <- decode.then(opt_int("tracks")) 218 - decode.success(Stats( 236 + decode.success(gen.StatsView( 219 237 scrobbles: scrobbles, 220 238 artists: artists, 221 239 loved_tracks: loved_tracks,
+1823
sdk/gleam/src/rocksky/generated/types.gleam
··· 1 + // AUTO-GENERATED FILE -- DO NOT EDIT. 2 + // Source: apps/api/lexicons/**/*.json 3 + // Regenerate via: bun run lexgen:types 4 + 5 + import gleam/dynamic.{type Dynamic} 6 + import gleam/option.{type Option} 7 + 8 + pub type BlobRef { 9 + BlobRef( 10 + type_: Option(String), 11 + ref: Option(BlobCidRef), 12 + mime_type: Option(String), 13 + size: Option(Int), 14 + ) 15 + } 16 + 17 + pub type BlobCidRef { 18 + BlobCidRef(link: Option(String)) 19 + } 20 + 21 + 22 + pub type ActorArtistViewBasic { 23 + ActorArtistViewBasic( 24 + id: Option(String), 25 + name: Option(String), 26 + picture: Option(String), 27 + uri: Option(String), 28 + user1_rank: Option(Int), 29 + user2_rank: Option(Int), 30 + weight: Option(Int), 31 + ) 32 + } 33 + 34 + pub type ActorCompatibilityViewBasic { 35 + ActorCompatibilityViewBasic( 36 + compatibility_level: Option(Int), 37 + compatibility_percentage: Option(Int), 38 + shared_artists: Option(Int), 39 + top_shared_artist_names: List(String), 40 + top_shared_detailed_artists: List(ActorArtistViewBasic), 41 + user1_artist_count: Option(Int), 42 + user2_artist_count: Option(Int), 43 + ) 44 + } 45 + 46 + pub type ActorNeighbourViewBasic { 47 + ActorNeighbourViewBasic( 48 + user_id: Option(String), 49 + did: Option(String), 50 + handle: Option(String), 51 + display_name: Option(String), 52 + avatar: Option(String), 53 + shared_artists_count: Option(Int), 54 + similarity_score: Option(Int), 55 + top_shared_artist_names: List(String), 56 + top_shared_artists_details: List(ArtistViewBasic), 57 + ) 58 + } 59 + 60 + pub type ActorProfileViewBasic { 61 + ActorProfileViewBasic( 62 + id: Option(String), 63 + did: Option(String), 64 + handle: Option(String), 65 + display_name: Option(String), 66 + avatar: Option(String), 67 + created_at: Option(String), 68 + updated_at: Option(String), 69 + ) 70 + } 71 + 72 + pub type ActorProfileViewDetailed { 73 + ActorProfileViewDetailed( 74 + id: Option(String), 75 + did: Option(String), 76 + handle: Option(String), 77 + display_name: Option(String), 78 + avatar: Option(String), 79 + created_at: Option(String), 80 + updated_at: Option(String), 81 + ) 82 + } 83 + 84 + pub type ActorTrackView { 85 + ActorTrackView( 86 + name: String, 87 + artist: String, 88 + album: Option(String), 89 + album_cover_url: Option(String), 90 + duration_ms: Option(Int), 91 + source: Option(String), 92 + recording_mb_id: Option(String), 93 + ) 94 + } 95 + 96 + pub type AddDirectoryToQueueParams { 97 + AddDirectoryToQueueParams( 98 + player_id: Option(String), 99 + directory: String, 100 + position: Option(Int), 101 + shuffle: Option(Bool), 102 + ) 103 + } 104 + 105 + pub type AddItemsToQueueParams { 106 + AddItemsToQueueParams( 107 + player_id: Option(String), 108 + items: List(String), 109 + position: Option(Int), 110 + shuffle: Option(Bool), 111 + ) 112 + } 113 + 114 + pub type AlbumRecord { 115 + AlbumRecord( 116 + title: String, 117 + artist: String, 118 + duration: Option(Int), 119 + release_date: Option(String), 120 + year: Option(Int), 121 + genre: Option(String), 122 + album_art: Option(BlobRef), 123 + album_art_url: Option(String), 124 + tags: List(String), 125 + youtube_link: Option(String), 126 + spotify_link: Option(String), 127 + tidal_link: Option(String), 128 + apple_music_link: Option(String), 129 + created_at: String, 130 + ) 131 + } 132 + 133 + pub type AlbumViewBasic { 134 + AlbumViewBasic( 135 + id: Option(String), 136 + uri: Option(String), 137 + title: Option(String), 138 + artist: Option(String), 139 + artist_uri: Option(String), 140 + year: Option(Int), 141 + album_art: Option(String), 142 + release_date: Option(String), 143 + sha256: Option(String), 144 + play_count: Option(Int), 145 + unique_listeners: Option(Int), 146 + ) 147 + } 148 + 149 + pub type AlbumViewDetailed { 150 + AlbumViewDetailed( 151 + id: Option(String), 152 + uri: Option(String), 153 + title: Option(String), 154 + artist: Option(String), 155 + artist_uri: Option(String), 156 + year: Option(Int), 157 + album_art: Option(String), 158 + release_date: Option(String), 159 + sha256: Option(String), 160 + play_count: Option(Int), 161 + unique_listeners: Option(Int), 162 + tags: List(String), 163 + tracks: List(SongViewBasic), 164 + ) 165 + } 166 + 167 + pub type ApiKeyView { 168 + ApiKeyView( 169 + id: Option(String), 170 + name: Option(String), 171 + description: Option(String), 172 + created_at: Option(String), 173 + ) 174 + } 175 + 176 + pub type ArtistListenerViewBasic { 177 + ArtistListenerViewBasic( 178 + id: Option(String), 179 + did: Option(String), 180 + handle: Option(String), 181 + display_name: Option(String), 182 + avatar: Option(String), 183 + most_listened_song: Option(ArtistSongViewBasic), 184 + total_plays: Option(Int), 185 + rank: Option(Int), 186 + ) 187 + } 188 + 189 + pub type ArtistMbid { 190 + ArtistMbid( 191 + mbid: Option(String), 192 + name: Option(String), 193 + ) 194 + } 195 + 196 + pub type ArtistRecentListenerView { 197 + ArtistRecentListenerView( 198 + id: Option(String), 199 + did: Option(String), 200 + handle: Option(String), 201 + display_name: Option(String), 202 + avatar: Option(String), 203 + timestamp: Option(String), 204 + scrobble_uri: Option(String), 205 + ) 206 + } 207 + 208 + pub type ArtistRecord { 209 + ArtistRecord( 210 + name: String, 211 + bio: Option(String), 212 + picture: Option(BlobRef), 213 + picture_url: Option(String), 214 + tags: List(String), 215 + born: Option(String), 216 + died: Option(String), 217 + born_in: Option(String), 218 + created_at: String, 219 + ) 220 + } 221 + 222 + pub type ArtistSongViewBasic { 223 + ArtistSongViewBasic( 224 + uri: Option(String), 225 + title: Option(String), 226 + play_count: Option(Int), 227 + ) 228 + } 229 + 230 + pub type ArtistViewBasic { 231 + ArtistViewBasic( 232 + id: Option(String), 233 + uri: Option(String), 234 + name: Option(String), 235 + picture: Option(String), 236 + sha256: Option(String), 237 + play_count: Option(Int), 238 + unique_listeners: Option(Int), 239 + tags: List(String), 240 + ) 241 + } 242 + 243 + pub type ArtistViewDetailed { 244 + ArtistViewDetailed( 245 + id: Option(String), 246 + uri: Option(String), 247 + name: Option(String), 248 + picture: Option(String), 249 + sha256: Option(String), 250 + play_count: Option(Int), 251 + unique_listeners: Option(Int), 252 + tags: List(String), 253 + ) 254 + } 255 + 256 + pub type ChartsScrobbleViewBasic { 257 + ChartsScrobbleViewBasic( 258 + date: Option(String), 259 + count: Option(Int), 260 + ) 261 + } 262 + 263 + pub type ChartsView { 264 + ChartsView( 265 + scrobbles: List(ChartsScrobbleViewBasic), 266 + ) 267 + } 268 + 269 + pub type CreateApikeyInput { 270 + CreateApikeyInput( 271 + name: String, 272 + description: Option(String), 273 + ) 274 + } 275 + 276 + pub type CreatePlaylistParams { 277 + CreatePlaylistParams( 278 + name: String, 279 + description: Option(String), 280 + ) 281 + } 282 + 283 + pub type CreateScrobbleInput { 284 + CreateScrobbleInput( 285 + title: String, 286 + artist: String, 287 + album: Option(String), 288 + duration: Option(Int), 289 + mb_id: Option(String), 290 + isrc: Option(String), 291 + album_art: Option(String), 292 + track_number: Option(Int), 293 + release_date: Option(String), 294 + year: Option(Int), 295 + disc_number: Option(Int), 296 + lyrics: Option(String), 297 + composer: Option(String), 298 + copyright_message: Option(String), 299 + label: Option(String), 300 + artist_picture: Option(String), 301 + spotify_link: Option(String), 302 + lastfm_link: Option(String), 303 + tidal_link: Option(String), 304 + apple_music_link: Option(String), 305 + youtube_link: Option(String), 306 + deezer_link: Option(String), 307 + timestamp: Option(Int), 308 + ) 309 + } 310 + 311 + pub type CreateShoutInput { 312 + CreateShoutInput( 313 + message: Option(String), 314 + ) 315 + } 316 + 317 + pub type CreateSongInput { 318 + CreateSongInput( 319 + title: String, 320 + artist: String, 321 + album_artist: String, 322 + album: String, 323 + duration: Option(Int), 324 + mb_id: Option(String), 325 + isrc: Option(String), 326 + album_art: Option(String), 327 + track_number: Option(Int), 328 + release_date: Option(String), 329 + year: Option(Int), 330 + disc_number: Option(Int), 331 + lyrics: Option(String), 332 + ) 333 + } 334 + 335 + pub type DescribeFeedGeneratorOutput { 336 + DescribeFeedGeneratorOutput( 337 + did: Option(String), 338 + feeds: List(FeedUriView), 339 + ) 340 + } 341 + 342 + pub type DescribeFeedGeneratorParams { 343 + DescribeFeedGeneratorParams 344 + } 345 + 346 + pub type DislikeShoutInput { 347 + DislikeShoutInput( 348 + uri: Option(String), 349 + ) 350 + } 351 + 352 + pub type DislikeSongInput { 353 + DislikeSongInput( 354 + uri: Option(String), 355 + ) 356 + } 357 + 358 + pub type DownloadFileParams { 359 + DownloadFileParams( 360 + file_id: String, 361 + ) 362 + } 363 + 364 + pub type DropboxFileListView { 365 + DropboxFileListView( 366 + files: List(DropboxFileView), 367 + ) 368 + } 369 + 370 + pub type DropboxFileView { 371 + DropboxFileView( 372 + id: Option(String), 373 + name: Option(String), 374 + path_lower: Option(String), 375 + path_display: Option(String), 376 + client_modified: Option(String), 377 + server_modified: Option(String), 378 + ) 379 + } 380 + 381 + pub type DropboxTemporaryLinkView { 382 + DropboxTemporaryLinkView( 383 + link: Option(String), 384 + ) 385 + } 386 + 387 + pub type FeedGeneratorsView { 388 + FeedGeneratorsView( 389 + feeds: List(FeedGeneratorView), 390 + ) 391 + } 392 + 393 + pub type FeedGeneratorView { 394 + FeedGeneratorView( 395 + id: Option(String), 396 + name: Option(String), 397 + description: Option(String), 398 + uri: Option(String), 399 + avatar: Option(String), 400 + creator: Option(ActorProfileViewBasic), 401 + ) 402 + } 403 + 404 + pub type FeedItemView { 405 + FeedItemView( 406 + scrobble: Option(ScrobbleViewBasic), 407 + ) 408 + } 409 + 410 + pub type FeedRecommendationsView { 411 + FeedRecommendationsView( 412 + recommendations: List(FeedRecommendationView), 413 + cursor: Option(String), 414 + ) 415 + } 416 + 417 + pub type FeedRecommendationView { 418 + FeedRecommendationView( 419 + title: Option(String), 420 + artist: Option(String), 421 + album: Option(String), 422 + album_art: Option(String), 423 + track_uri: Option(String), 424 + artist_uri: Option(String), 425 + album_uri: Option(String), 426 + genres: List(String), 427 + recommendation_score: Option(Int), 428 + source: Option(String), 429 + likes_count: Option(Int), 430 + ) 431 + } 432 + 433 + pub type FeedRecommendedAlbumsView { 434 + FeedRecommendedAlbumsView( 435 + albums: List(FeedRecommendedAlbumView), 436 + cursor: Option(String), 437 + ) 438 + } 439 + 440 + pub type FeedRecommendedAlbumView { 441 + FeedRecommendedAlbumView( 442 + id: Option(String), 443 + uri: Option(String), 444 + title: Option(String), 445 + artist: Option(String), 446 + artist_uri: Option(String), 447 + year: Option(Int), 448 + album_art: Option(String), 449 + recommendation_score: Option(Int), 450 + source: Option(String), 451 + ) 452 + } 453 + 454 + pub type FeedRecommendedArtistsView { 455 + FeedRecommendedArtistsView( 456 + artists: List(FeedRecommendedArtistView), 457 + cursor: Option(String), 458 + ) 459 + } 460 + 461 + pub type FeedRecommendedArtistView { 462 + FeedRecommendedArtistView( 463 + id: Option(String), 464 + uri: Option(String), 465 + name: Option(String), 466 + picture: Option(String), 467 + genres: List(String), 468 + recommendation_score: Option(Int), 469 + source: Option(String), 470 + ) 471 + } 472 + 473 + pub type FeedSearchResultsView { 474 + FeedSearchResultsView( 475 + hits: List(Dynamic), 476 + processing_time_ms: Option(Int), 477 + limit: Option(Int), 478 + offset: Option(Int), 479 + estimated_total_hits: Option(Int), 480 + ) 481 + } 482 + 483 + pub type FeedStoriesView { 484 + FeedStoriesView( 485 + stories: List(FeedStoryView), 486 + ) 487 + } 488 + 489 + pub type FeedStoryView { 490 + FeedStoryView( 491 + album: Option(String), 492 + album_art: Option(String), 493 + album_artist: Option(String), 494 + album_uri: Option(String), 495 + artist: Option(String), 496 + artist_uri: Option(String), 497 + avatar: Option(String), 498 + created_at: Option(String), 499 + did: Option(String), 500 + handle: Option(String), 501 + id: Option(String), 502 + title: Option(String), 503 + track_id: Option(String), 504 + track_uri: Option(String), 505 + uri: Option(String), 506 + ) 507 + } 508 + 509 + pub type FeedUriView { 510 + FeedUriView( 511 + uri: Option(String), 512 + ) 513 + } 514 + 515 + pub type FeedView { 516 + FeedView( 517 + feed: List(FeedItemView), 518 + cursor: Option(String), 519 + ) 520 + } 521 + 522 + pub type FollowAccountOutput { 523 + FollowAccountOutput( 524 + subject: ActorProfileViewBasic, 525 + followers: List(ActorProfileViewBasic), 526 + cursor: Option(String), 527 + ) 528 + } 529 + 530 + pub type FollowAccountParams { 531 + FollowAccountParams( 532 + account: String, 533 + ) 534 + } 535 + 536 + pub type FollowRecord { 537 + FollowRecord( 538 + created_at: String, 539 + subject: String, 540 + via: Option(StrongRef), 541 + ) 542 + } 543 + 544 + pub type GeneratorRecord { 545 + GeneratorRecord( 546 + did: String, 547 + avatar: Option(BlobRef), 548 + display_name: String, 549 + description: Option(String), 550 + created_at: String, 551 + ) 552 + } 553 + 554 + pub type GetActorAlbumsOutput { 555 + GetActorAlbumsOutput( 556 + albums: List(AlbumViewBasic), 557 + ) 558 + } 559 + 560 + pub type GetActorAlbumsParams { 561 + GetActorAlbumsParams( 562 + did: String, 563 + limit: Option(Int), 564 + offset: Option(Int), 565 + start_date: Option(String), 566 + end_date: Option(String), 567 + ) 568 + } 569 + 570 + pub type GetActorArtistsOutput { 571 + GetActorArtistsOutput( 572 + artists: List(ArtistViewBasic), 573 + ) 574 + } 575 + 576 + pub type GetActorArtistsParams { 577 + GetActorArtistsParams( 578 + did: String, 579 + limit: Option(Int), 580 + offset: Option(Int), 581 + start_date: Option(String), 582 + end_date: Option(String), 583 + ) 584 + } 585 + 586 + pub type GetActorCompatibilityOutput { 587 + GetActorCompatibilityOutput( 588 + compatibility: Option(ActorCompatibilityViewBasic), 589 + ) 590 + } 591 + 592 + pub type GetActorCompatibilityParams { 593 + GetActorCompatibilityParams( 594 + did: String, 595 + ) 596 + } 597 + 598 + pub type GetActorLovedSongsOutput { 599 + GetActorLovedSongsOutput( 600 + tracks: List(SongViewBasic), 601 + ) 602 + } 603 + 604 + pub type GetActorLovedSongsParams { 605 + GetActorLovedSongsParams( 606 + did: String, 607 + limit: Option(Int), 608 + offset: Option(Int), 609 + ) 610 + } 611 + 612 + pub type GetActorNeighboursOutput { 613 + GetActorNeighboursOutput( 614 + neighbours: List(ActorNeighbourViewBasic), 615 + ) 616 + } 617 + 618 + pub type GetActorNeighboursParams { 619 + GetActorNeighboursParams( 620 + did: String, 621 + ) 622 + } 623 + 624 + pub type GetActorPlaylistsOutput { 625 + GetActorPlaylistsOutput( 626 + playlists: List(PlaylistViewBasic), 627 + ) 628 + } 629 + 630 + pub type GetActorPlaylistsParams { 631 + GetActorPlaylistsParams( 632 + did: String, 633 + limit: Option(Int), 634 + offset: Option(Int), 635 + ) 636 + } 637 + 638 + pub type GetActorScrobblesOutput { 639 + GetActorScrobblesOutput( 640 + scrobbles: List(ScrobbleViewBasic), 641 + ) 642 + } 643 + 644 + pub type GetActorScrobblesParams { 645 + GetActorScrobblesParams( 646 + did: String, 647 + limit: Option(Int), 648 + offset: Option(Int), 649 + ) 650 + } 651 + 652 + pub type GetActorSongsOutput { 653 + GetActorSongsOutput( 654 + songs: List(SongViewBasic), 655 + ) 656 + } 657 + 658 + pub type GetActorSongsParams { 659 + GetActorSongsParams( 660 + did: String, 661 + limit: Option(Int), 662 + offset: Option(Int), 663 + start_date: Option(String), 664 + end_date: Option(String), 665 + ) 666 + } 667 + 668 + pub type GetAlbumParams { 669 + GetAlbumParams( 670 + uri: String, 671 + ) 672 + } 673 + 674 + pub type GetAlbumRecommendationsParams { 675 + GetAlbumRecommendationsParams( 676 + did: String, 677 + limit: Option(Int), 678 + ) 679 + } 680 + 681 + pub type GetAlbumShoutsOutput { 682 + GetAlbumShoutsOutput( 683 + shouts: List(Dynamic), 684 + ) 685 + } 686 + 687 + pub type GetAlbumShoutsParams { 688 + GetAlbumShoutsParams( 689 + uri: String, 690 + limit: Option(Int), 691 + offset: Option(Int), 692 + ) 693 + } 694 + 695 + pub type GetAlbumsOutput { 696 + GetAlbumsOutput( 697 + albums: List(AlbumViewBasic), 698 + ) 699 + } 700 + 701 + pub type GetAlbumsParams { 702 + GetAlbumsParams( 703 + limit: Option(Int), 704 + offset: Option(Int), 705 + genre: Option(String), 706 + ) 707 + } 708 + 709 + pub type GetAlbumTracksOutput { 710 + GetAlbumTracksOutput( 711 + tracks: List(SongViewBasic), 712 + ) 713 + } 714 + 715 + pub type GetAlbumTracksParams { 716 + GetAlbumTracksParams( 717 + uri: String, 718 + ) 719 + } 720 + 721 + pub type GetApikeysOutput { 722 + GetApikeysOutput( 723 + api_keys: List(Dynamic), 724 + ) 725 + } 726 + 727 + pub type GetApikeysParams { 728 + GetApikeysParams( 729 + offset: Option(Int), 730 + limit: Option(Int), 731 + ) 732 + } 733 + 734 + pub type GetArtistAlbumsOutput { 735 + GetArtistAlbumsOutput( 736 + albums: List(AlbumViewBasic), 737 + ) 738 + } 739 + 740 + pub type GetArtistAlbumsParams { 741 + GetArtistAlbumsParams( 742 + uri: String, 743 + ) 744 + } 745 + 746 + pub type GetArtistListenersOutput { 747 + GetArtistListenersOutput( 748 + listeners: List(ArtistListenerViewBasic), 749 + ) 750 + } 751 + 752 + pub type GetArtistListenersParams { 753 + GetArtistListenersParams( 754 + uri: String, 755 + offset: Option(Int), 756 + limit: Option(Int), 757 + ) 758 + } 759 + 760 + pub type GetArtistParams { 761 + GetArtistParams( 762 + uri: String, 763 + ) 764 + } 765 + 766 + pub type GetArtistRecentListenersOutput { 767 + GetArtistRecentListenersOutput( 768 + listeners: List(ArtistRecentListenerView), 769 + ) 770 + } 771 + 772 + pub type GetArtistRecentListenersParams { 773 + GetArtistRecentListenersParams( 774 + uri: String, 775 + offset: Option(Int), 776 + limit: Option(Int), 777 + ) 778 + } 779 + 780 + pub type GetArtistRecommendationsParams { 781 + GetArtistRecommendationsParams( 782 + did: String, 783 + limit: Option(Int), 784 + ) 785 + } 786 + 787 + pub type GetArtistShoutsOutput { 788 + GetArtistShoutsOutput( 789 + shouts: List(Dynamic), 790 + ) 791 + } 792 + 793 + pub type GetArtistShoutsParams { 794 + GetArtistShoutsParams( 795 + uri: String, 796 + limit: Option(Int), 797 + offset: Option(Int), 798 + ) 799 + } 800 + 801 + pub type GetArtistsOutput { 802 + GetArtistsOutput( 803 + artists: List(ArtistViewBasic), 804 + ) 805 + } 806 + 807 + pub type GetArtistsParams { 808 + GetArtistsParams( 809 + limit: Option(Int), 810 + offset: Option(Int), 811 + names: Option(String), 812 + genre: Option(String), 813 + ) 814 + } 815 + 816 + pub type GetArtistTracksOutput { 817 + GetArtistTracksOutput( 818 + tracks: List(SongViewBasic), 819 + ) 820 + } 821 + 822 + pub type GetArtistTracksParams { 823 + GetArtistTracksParams( 824 + uri: Option(String), 825 + limit: Option(Int), 826 + offset: Option(Int), 827 + ) 828 + } 829 + 830 + pub type GetCurrentlyPlayingParams { 831 + GetCurrentlyPlayingParams( 832 + player_id: Option(String), 833 + actor: Option(String), 834 + ) 835 + } 836 + 837 + pub type GetFeedGeneratorOutput { 838 + GetFeedGeneratorOutput( 839 + view: Option(FeedGeneratorView), 840 + ) 841 + } 842 + 843 + pub type GetFeedGeneratorParams { 844 + GetFeedGeneratorParams( 845 + feed: String, 846 + ) 847 + } 848 + 849 + pub type GetFeedGeneratorsParams { 850 + GetFeedGeneratorsParams( 851 + size: Option(Int), 852 + ) 853 + } 854 + 855 + pub type GetFeedParams { 856 + GetFeedParams( 857 + feed: String, 858 + limit: Option(Int), 859 + cursor: Option(String), 860 + ) 861 + } 862 + 863 + pub type GetFeedSkeletonOutput { 864 + GetFeedSkeletonOutput( 865 + scrobbles: List(ScrobbleViewBasic), 866 + cursor: Option(String), 867 + ) 868 + } 869 + 870 + pub type GetFeedSkeletonParams { 871 + GetFeedSkeletonParams( 872 + feed: String, 873 + limit: Option(Int), 874 + offset: Option(Int), 875 + cursor: Option(String), 876 + ) 877 + } 878 + 879 + pub type GetFileParams { 880 + GetFileParams( 881 + file_id: String, 882 + ) 883 + } 884 + 885 + pub type GetFilesParams { 886 + GetFilesParams( 887 + at: Option(String), 888 + ) 889 + } 890 + 891 + pub type GetFollowersOutput { 892 + GetFollowersOutput( 893 + subject: ActorProfileViewBasic, 894 + followers: List(ActorProfileViewBasic), 895 + cursor: Option(String), 896 + count: Option(Int), 897 + ) 898 + } 899 + 900 + pub type GetFollowersParams { 901 + GetFollowersParams( 902 + actor: String, 903 + limit: Option(Int), 904 + dids: List(String), 905 + cursor: Option(String), 906 + ) 907 + } 908 + 909 + pub type GetFollowsOutput { 910 + GetFollowsOutput( 911 + subject: ActorProfileViewBasic, 912 + follows: List(ActorProfileViewBasic), 913 + cursor: Option(String), 914 + count: Option(Int), 915 + ) 916 + } 917 + 918 + pub type GetFollowsParams { 919 + GetFollowsParams( 920 + actor: String, 921 + limit: Option(Int), 922 + dids: List(String), 923 + cursor: Option(String), 924 + ) 925 + } 926 + 927 + pub type GetKnownFollowersOutput { 928 + GetKnownFollowersOutput( 929 + subject: ActorProfileViewBasic, 930 + followers: List(ActorProfileViewBasic), 931 + cursor: Option(String), 932 + ) 933 + } 934 + 935 + pub type GetKnownFollowersParams { 936 + GetKnownFollowersParams( 937 + actor: String, 938 + limit: Option(Int), 939 + cursor: Option(String), 940 + ) 941 + } 942 + 943 + pub type GetMetadataParams { 944 + GetMetadataParams( 945 + path: String, 946 + ) 947 + } 948 + 949 + pub type GetMirrorSourcesOutput { 950 + GetMirrorSourcesOutput( 951 + sources: List(MirrorSourceView), 952 + ) 953 + } 954 + 955 + pub type GetMirrorSourcesParams { 956 + GetMirrorSourcesParams 957 + } 958 + 959 + pub type GetPlaybackQueueParams { 960 + GetPlaybackQueueParams( 961 + player_id: Option(String), 962 + ) 963 + } 964 + 965 + pub type GetPlaylistParams { 966 + GetPlaylistParams( 967 + uri: String, 968 + ) 969 + } 970 + 971 + pub type GetPlaylistsOutput { 972 + GetPlaylistsOutput( 973 + playlists: List(PlaylistViewBasic), 974 + ) 975 + } 976 + 977 + pub type GetPlaylistsParams { 978 + GetPlaylistsParams( 979 + limit: Option(Int), 980 + offset: Option(Int), 981 + ) 982 + } 983 + 984 + pub type GetProfileParams { 985 + GetProfileParams( 986 + did: Option(String), 987 + ) 988 + } 989 + 990 + pub type GetProfileShoutsOutput { 991 + GetProfileShoutsOutput( 992 + shouts: List(Dynamic), 993 + ) 994 + } 995 + 996 + pub type GetProfileShoutsParams { 997 + GetProfileShoutsParams( 998 + did: String, 999 + offset: Option(Int), 1000 + limit: Option(Int), 1001 + ) 1002 + } 1003 + 1004 + pub type GetRecommendationsParams { 1005 + GetRecommendationsParams( 1006 + did: String, 1007 + limit: Option(Int), 1008 + ) 1009 + } 1010 + 1011 + pub type GetScrobbleParams { 1012 + GetScrobbleParams( 1013 + uri: String, 1014 + ) 1015 + } 1016 + 1017 + pub type GetScrobblesChartParams { 1018 + GetScrobblesChartParams( 1019 + did: Option(String), 1020 + artisturi: Option(String), 1021 + albumuri: Option(String), 1022 + songuri: Option(String), 1023 + genre: Option(String), 1024 + from: Option(String), 1025 + to: Option(String), 1026 + ) 1027 + } 1028 + 1029 + pub type GetScrobblesOutput { 1030 + GetScrobblesOutput( 1031 + scrobbles: List(ScrobbleViewBasic), 1032 + ) 1033 + } 1034 + 1035 + pub type GetScrobblesParams { 1036 + GetScrobblesParams( 1037 + did: Option(String), 1038 + following: Option(Bool), 1039 + limit: Option(Int), 1040 + offset: Option(Int), 1041 + ) 1042 + } 1043 + 1044 + pub type GetShoutRepliesOutput { 1045 + GetShoutRepliesOutput( 1046 + shouts: List(Dynamic), 1047 + ) 1048 + } 1049 + 1050 + pub type GetShoutRepliesParams { 1051 + GetShoutRepliesParams( 1052 + uri: String, 1053 + limit: Option(Int), 1054 + offset: Option(Int), 1055 + ) 1056 + } 1057 + 1058 + pub type GetSongParams { 1059 + GetSongParams( 1060 + uri: Option(String), 1061 + mbid: Option(String), 1062 + isrc: Option(String), 1063 + spotify_id: Option(String), 1064 + ) 1065 + } 1066 + 1067 + pub type GetSongRecentListenersOutput { 1068 + GetSongRecentListenersOutput( 1069 + listeners: List(SongRecentListenerView), 1070 + ) 1071 + } 1072 + 1073 + pub type GetSongRecentListenersParams { 1074 + GetSongRecentListenersParams( 1075 + uri: String, 1076 + offset: Option(Int), 1077 + limit: Option(Int), 1078 + ) 1079 + } 1080 + 1081 + pub type GetSongsOutput { 1082 + GetSongsOutput( 1083 + songs: List(SongViewBasic), 1084 + ) 1085 + } 1086 + 1087 + pub type GetSongsParams { 1088 + GetSongsParams( 1089 + limit: Option(Int), 1090 + offset: Option(Int), 1091 + genre: Option(String), 1092 + mbid: Option(String), 1093 + isrc: Option(String), 1094 + spotify_id: Option(String), 1095 + ) 1096 + } 1097 + 1098 + pub type GetStatsParams { 1099 + GetStatsParams( 1100 + did: String, 1101 + ) 1102 + } 1103 + 1104 + pub type GetStoriesParams { 1105 + GetStoriesParams( 1106 + size: Option(Int), 1107 + ) 1108 + } 1109 + 1110 + pub type GetTemporaryLinkParams { 1111 + GetTemporaryLinkParams( 1112 + path: String, 1113 + ) 1114 + } 1115 + 1116 + pub type GetTopArtistsOutput { 1117 + GetTopArtistsOutput( 1118 + artists: List(ArtistViewBasic), 1119 + ) 1120 + } 1121 + 1122 + pub type GetTopArtistsParams { 1123 + GetTopArtistsParams( 1124 + limit: Option(Int), 1125 + offset: Option(Int), 1126 + start_date: Option(String), 1127 + end_date: Option(String), 1128 + ) 1129 + } 1130 + 1131 + pub type GetTopTracksOutput { 1132 + GetTopTracksOutput( 1133 + tracks: List(SongViewBasic), 1134 + ) 1135 + } 1136 + 1137 + pub type GetTopTracksParams { 1138 + GetTopTracksParams( 1139 + limit: Option(Int), 1140 + offset: Option(Int), 1141 + start_date: Option(String), 1142 + end_date: Option(String), 1143 + ) 1144 + } 1145 + 1146 + pub type GetTrackShoutsOutput { 1147 + GetTrackShoutsOutput( 1148 + shouts: List(Dynamic), 1149 + ) 1150 + } 1151 + 1152 + pub type GetTrackShoutsParams { 1153 + GetTrackShoutsParams( 1154 + uri: String, 1155 + ) 1156 + } 1157 + 1158 + pub type GetWrappedParams { 1159 + GetWrappedParams( 1160 + did: String, 1161 + year: Option(Int), 1162 + ) 1163 + } 1164 + 1165 + pub type GoogledriveFileListView { 1166 + GoogledriveFileListView( 1167 + files: List(GoogledriveFileView), 1168 + ) 1169 + } 1170 + 1171 + pub type GoogledriveFileView { 1172 + GoogledriveFileView( 1173 + id: Option(String), 1174 + ) 1175 + } 1176 + 1177 + /// indicates that a handle or DID could not be resolved 1178 + pub type GraphNotFoundActor { 1179 + GraphNotFoundActor( 1180 + actor: String, 1181 + not_found: Bool, 1182 + ) 1183 + } 1184 + 1185 + pub type GraphRelationship { 1186 + GraphRelationship( 1187 + did: String, 1188 + following: Option(String), 1189 + followed_by: Option(String), 1190 + ) 1191 + } 1192 + 1193 + pub type InsertDirectoryParams { 1194 + InsertDirectoryParams( 1195 + uri: String, 1196 + directory: String, 1197 + position: Option(Int), 1198 + ) 1199 + } 1200 + 1201 + pub type InsertFilesParams { 1202 + InsertFilesParams( 1203 + uri: String, 1204 + files: List(String), 1205 + position: Option(Int), 1206 + ) 1207 + } 1208 + 1209 + pub type LikeRecord { 1210 + LikeRecord( 1211 + created_at: String, 1212 + subject: StrongRef, 1213 + ) 1214 + } 1215 + 1216 + pub type LikeShoutInput { 1217 + LikeShoutInput( 1218 + uri: Option(String), 1219 + ) 1220 + } 1221 + 1222 + pub type LikeSongInput { 1223 + LikeSongInput( 1224 + uri: Option(String), 1225 + ) 1226 + } 1227 + 1228 + pub type MatchSongParams { 1229 + MatchSongParams( 1230 + title: String, 1231 + artist: String, 1232 + mb_id: Option(String), 1233 + isrc: Option(String), 1234 + ) 1235 + } 1236 + 1237 + pub type MirrorSourceView { 1238 + MirrorSourceView( 1239 + provider: String, 1240 + enabled: Bool, 1241 + external_username: Option(String), 1242 + has_credentials: Bool, 1243 + last_polled_at: Option(String), 1244 + last_scrobble_seen_at: Option(String), 1245 + ) 1246 + } 1247 + 1248 + pub type NextParams { 1249 + NextParams( 1250 + player_id: Option(String), 1251 + ) 1252 + } 1253 + 1254 + pub type PauseParams { 1255 + PauseParams( 1256 + player_id: Option(String), 1257 + ) 1258 + } 1259 + 1260 + pub type PlayDirectoryParams { 1261 + PlayDirectoryParams( 1262 + player_id: Option(String), 1263 + directory_id: String, 1264 + shuffle: Option(Bool), 1265 + recurse: Option(Bool), 1266 + position: Option(Int), 1267 + ) 1268 + } 1269 + 1270 + pub type PlayerCurrentlyPlayingViewDetailed { 1271 + PlayerCurrentlyPlayingViewDetailed( 1272 + title: Option(String), 1273 + ) 1274 + } 1275 + 1276 + pub type PlayerPlaybackQueueViewDetailed { 1277 + PlayerPlaybackQueueViewDetailed( 1278 + tracks: List(SongViewBasic), 1279 + ) 1280 + } 1281 + 1282 + pub type PlayFileParams { 1283 + PlayFileParams( 1284 + player_id: Option(String), 1285 + file_id: String, 1286 + ) 1287 + } 1288 + 1289 + pub type PlaylistItemRecord { 1290 + PlaylistItemRecord( 1291 + subject: StrongRef, 1292 + created_at: String, 1293 + track: SongViewBasic, 1294 + order: Int, 1295 + ) 1296 + } 1297 + 1298 + pub type PlaylistRecord { 1299 + PlaylistRecord( 1300 + name: String, 1301 + description: Option(String), 1302 + picture: Option(BlobRef), 1303 + picture_url: Option(String), 1304 + created_at: String, 1305 + spotify_link: Option(String), 1306 + tidal_link: Option(String), 1307 + youtube_link: Option(String), 1308 + apple_music_link: Option(String), 1309 + ) 1310 + } 1311 + 1312 + /// Basic view of a playlist, including its metadata 1313 + pub type PlaylistViewBasic { 1314 + PlaylistViewBasic( 1315 + id: Option(String), 1316 + title: Option(String), 1317 + uri: Option(String), 1318 + curator_did: Option(String), 1319 + curator_handle: Option(String), 1320 + curator_name: Option(String), 1321 + curator_avatar_url: Option(String), 1322 + description: Option(String), 1323 + cover_image_url: Option(String), 1324 + created_at: Option(String), 1325 + track_count: Option(Int), 1326 + ) 1327 + } 1328 + 1329 + /// Detailed view of a playlist, including its tracks and metadata 1330 + pub type PlaylistViewDetailed { 1331 + PlaylistViewDetailed( 1332 + id: Option(String), 1333 + title: Option(String), 1334 + uri: Option(String), 1335 + curator_did: Option(String), 1336 + curator_handle: Option(String), 1337 + curator_name: Option(String), 1338 + curator_avatar_url: Option(String), 1339 + description: Option(String), 1340 + cover_image_url: Option(String), 1341 + created_at: Option(String), 1342 + tracks: List(SongViewBasic), 1343 + ) 1344 + } 1345 + 1346 + pub type PlayParams { 1347 + PlayParams( 1348 + player_id: Option(String), 1349 + ) 1350 + } 1351 + 1352 + pub type PreviousParams { 1353 + PreviousParams( 1354 + player_id: Option(String), 1355 + ) 1356 + } 1357 + 1358 + pub type ProfileRecord { 1359 + ProfileRecord( 1360 + display_name: Option(String), 1361 + description: Option(String), 1362 + avatar: Option(BlobRef), 1363 + banner: Option(BlobRef), 1364 + labels: Option(Dynamic), 1365 + joined_via_starter_pack: Option(StrongRef), 1366 + created_at: Option(String), 1367 + ) 1368 + } 1369 + 1370 + pub type PutMirrorSourceInput { 1371 + PutMirrorSourceInput( 1372 + provider: String, 1373 + enabled: Option(Bool), 1374 + external_username: Option(String), 1375 + api_key: Option(String), 1376 + ) 1377 + } 1378 + 1379 + pub type RadioRecord { 1380 + RadioRecord( 1381 + name: String, 1382 + url: String, 1383 + description: Option(String), 1384 + genre: Option(String), 1385 + logo: Option(BlobRef), 1386 + website: Option(String), 1387 + created_at: String, 1388 + ) 1389 + } 1390 + 1391 + pub type RadioViewBasic { 1392 + RadioViewBasic( 1393 + id: Option(String), 1394 + name: Option(String), 1395 + description: Option(String), 1396 + created_at: Option(String), 1397 + ) 1398 + } 1399 + 1400 + pub type RadioViewDetailed { 1401 + RadioViewDetailed( 1402 + id: Option(String), 1403 + name: Option(String), 1404 + description: Option(String), 1405 + website: Option(String), 1406 + url: Option(String), 1407 + genre: Option(String), 1408 + logo: Option(String), 1409 + created_at: Option(String), 1410 + ) 1411 + } 1412 + 1413 + pub type RemoveApikeyParams { 1414 + RemoveApikeyParams( 1415 + id: String, 1416 + ) 1417 + } 1418 + 1419 + pub type RemovePlaylistParams { 1420 + RemovePlaylistParams( 1421 + uri: String, 1422 + ) 1423 + } 1424 + 1425 + pub type RemoveShoutParams { 1426 + RemoveShoutParams( 1427 + id: String, 1428 + ) 1429 + } 1430 + 1431 + pub type RemoveTrackParams { 1432 + RemoveTrackParams( 1433 + uri: String, 1434 + position: Int, 1435 + ) 1436 + } 1437 + 1438 + pub type ReplyShoutInput { 1439 + ReplyShoutInput( 1440 + shout_id: String, 1441 + message: String, 1442 + ) 1443 + } 1444 + 1445 + pub type ReportShoutInput { 1446 + ReportShoutInput( 1447 + shout_id: String, 1448 + reason: Option(String), 1449 + ) 1450 + } 1451 + 1452 + pub type ScrobbleFirstScrobbleView { 1453 + ScrobbleFirstScrobbleView( 1454 + handle: Option(String), 1455 + avatar: Option(String), 1456 + timestamp: Option(String), 1457 + ) 1458 + } 1459 + 1460 + pub type ScrobbleRecord { 1461 + ScrobbleRecord( 1462 + title: String, 1463 + artist: String, 1464 + artists: List(ArtistMbid), 1465 + album_artist: String, 1466 + album: String, 1467 + duration: Int, 1468 + track_number: Option(Int), 1469 + disc_number: Option(Int), 1470 + release_date: Option(String), 1471 + year: Option(Int), 1472 + genre: Option(String), 1473 + tags: List(String), 1474 + composer: Option(String), 1475 + lyrics: Option(String), 1476 + copyright_message: Option(String), 1477 + wiki: Option(String), 1478 + album_art: Option(BlobRef), 1479 + album_art_url: Option(String), 1480 + youtube_link: Option(String), 1481 + spotify_link: Option(String), 1482 + tidal_link: Option(String), 1483 + apple_music_link: Option(String), 1484 + created_at: String, 1485 + mbid: Option(String), 1486 + label: Option(String), 1487 + isrc: Option(String), 1488 + ) 1489 + } 1490 + 1491 + pub type ScrobbleViewBasic { 1492 + ScrobbleViewBasic( 1493 + id: Option(String), 1494 + user: Option(String), 1495 + user_display_name: Option(String), 1496 + user_avatar: Option(String), 1497 + title: Option(String), 1498 + artist: Option(String), 1499 + artist_uri: Option(String), 1500 + album: Option(String), 1501 + album_uri: Option(String), 1502 + cover: Option(String), 1503 + date: Option(String), 1504 + uri: Option(String), 1505 + sha256: Option(String), 1506 + liked: Option(Bool), 1507 + likes_count: Option(Int), 1508 + ) 1509 + } 1510 + 1511 + pub type ScrobbleViewDetailed { 1512 + ScrobbleViewDetailed( 1513 + id: Option(String), 1514 + user: Option(String), 1515 + title: Option(String), 1516 + artist: Option(String), 1517 + artist_uri: Option(String), 1518 + album: Option(String), 1519 + album_uri: Option(String), 1520 + cover: Option(String), 1521 + date: Option(String), 1522 + uri: Option(String), 1523 + sha256: Option(String), 1524 + liked: Option(Bool), 1525 + likes_count: Option(Int), 1526 + listeners: Option(Int), 1527 + scrobbles: Option(Int), 1528 + artists: List(ArtistViewBasic), 1529 + first_scrobble: Option(ScrobbleFirstScrobbleView), 1530 + ) 1531 + } 1532 + 1533 + pub type SearchParams { 1534 + SearchParams( 1535 + query: String, 1536 + ) 1537 + } 1538 + 1539 + pub type SeekParams { 1540 + SeekParams( 1541 + player_id: Option(String), 1542 + position: Int, 1543 + ) 1544 + } 1545 + 1546 + pub type ShoutAuthor { 1547 + ShoutAuthor( 1548 + id: Option(String), 1549 + did: Option(String), 1550 + handle: Option(String), 1551 + display_name: Option(String), 1552 + avatar: Option(String), 1553 + ) 1554 + } 1555 + 1556 + pub type ShoutRecord { 1557 + ShoutRecord( 1558 + message: String, 1559 + created_at: String, 1560 + parent: Option(StrongRef), 1561 + subject: StrongRef, 1562 + ) 1563 + } 1564 + 1565 + pub type ShoutView { 1566 + ShoutView( 1567 + id: Option(String), 1568 + message: Option(String), 1569 + parent: Option(String), 1570 + created_at: Option(String), 1571 + author: Option(ShoutAuthor), 1572 + ) 1573 + } 1574 + 1575 + pub type SongFirstScrobbleView { 1576 + SongFirstScrobbleView( 1577 + handle: Option(String), 1578 + avatar: Option(String), 1579 + timestamp: Option(String), 1580 + ) 1581 + } 1582 + 1583 + pub type SongRecentListenerView { 1584 + SongRecentListenerView( 1585 + id: Option(String), 1586 + did: Option(String), 1587 + handle: Option(String), 1588 + display_name: Option(String), 1589 + avatar: Option(String), 1590 + timestamp: Option(String), 1591 + scrobble_uri: Option(String), 1592 + ) 1593 + } 1594 + 1595 + pub type SongRecord { 1596 + SongRecord( 1597 + title: String, 1598 + artist: String, 1599 + artists: List(ArtistMbid), 1600 + album_artist: String, 1601 + album: String, 1602 + duration: Int, 1603 + track_number: Option(Int), 1604 + disc_number: Option(Int), 1605 + release_date: Option(String), 1606 + year: Option(Int), 1607 + genre: Option(String), 1608 + tags: List(String), 1609 + composer: Option(String), 1610 + lyrics: Option(String), 1611 + copyright_message: Option(String), 1612 + wiki: Option(String), 1613 + album_art: Option(BlobRef), 1614 + album_art_url: Option(String), 1615 + youtube_link: Option(String), 1616 + spotify_link: Option(String), 1617 + tidal_link: Option(String), 1618 + apple_music_link: Option(String), 1619 + created_at: String, 1620 + mbid: Option(String), 1621 + label: Option(String), 1622 + isrc: Option(String), 1623 + ) 1624 + } 1625 + 1626 + pub type SongViewBasic { 1627 + SongViewBasic( 1628 + id: Option(String), 1629 + title: Option(String), 1630 + artist: Option(String), 1631 + album_artist: Option(String), 1632 + album_art: Option(String), 1633 + uri: Option(String), 1634 + album: Option(String), 1635 + duration: Option(Int), 1636 + track_number: Option(Int), 1637 + disc_number: Option(Int), 1638 + play_count: Option(Int), 1639 + unique_listeners: Option(Int), 1640 + album_uri: Option(String), 1641 + artist_uri: Option(String), 1642 + sha256: Option(String), 1643 + mbid: Option(String), 1644 + isrc: Option(String), 1645 + tags: List(String), 1646 + created_at: Option(String), 1647 + ) 1648 + } 1649 + 1650 + pub type SongViewDetailed { 1651 + SongViewDetailed( 1652 + id: Option(String), 1653 + title: Option(String), 1654 + artist: Option(String), 1655 + album_artist: Option(String), 1656 + album_art: Option(String), 1657 + uri: Option(String), 1658 + album: Option(String), 1659 + duration: Option(Int), 1660 + track_number: Option(Int), 1661 + disc_number: Option(Int), 1662 + play_count: Option(Int), 1663 + unique_listeners: Option(Int), 1664 + album_uri: Option(String), 1665 + artist_uri: Option(String), 1666 + sha256: Option(String), 1667 + mbid: Option(String), 1668 + isrc: Option(String), 1669 + tags: List(String), 1670 + created_at: Option(String), 1671 + artists: List(ArtistViewBasic), 1672 + first_scrobble: Option(SongFirstScrobbleView), 1673 + ) 1674 + } 1675 + 1676 + pub type SpotifyTrackView { 1677 + SpotifyTrackView( 1678 + id: Option(String), 1679 + name: Option(String), 1680 + artist: Option(String), 1681 + album: Option(String), 1682 + duration: Option(Int), 1683 + preview_url: Option(String), 1684 + ) 1685 + } 1686 + 1687 + pub type StartPlaylistParams { 1688 + StartPlaylistParams( 1689 + uri: String, 1690 + shuffle: Option(Bool), 1691 + position: Option(Int), 1692 + ) 1693 + } 1694 + 1695 + pub type StatsView { 1696 + StatsView( 1697 + scrobbles: Option(Int), 1698 + artists: Option(Int), 1699 + loved_tracks: Option(Int), 1700 + albums: Option(Int), 1701 + tracks: Option(Int), 1702 + ) 1703 + } 1704 + 1705 + pub type StatsWrappedAlbum { 1706 + StatsWrappedAlbum( 1707 + id: Option(String), 1708 + title: Option(String), 1709 + artist: Option(String), 1710 + album_art: Option(String), 1711 + uri: Option(String), 1712 + play_count: Option(Int), 1713 + ) 1714 + } 1715 + 1716 + pub type StatsWrappedArtist { 1717 + StatsWrappedArtist( 1718 + id: Option(String), 1719 + name: Option(String), 1720 + picture: Option(String), 1721 + uri: Option(String), 1722 + play_count: Option(Int), 1723 + ) 1724 + } 1725 + 1726 + pub type StatsWrappedDayCount { 1727 + StatsWrappedDayCount( 1728 + date: Option(String), 1729 + count: Option(Int), 1730 + ) 1731 + } 1732 + 1733 + pub type StatsWrappedGenreCount { 1734 + StatsWrappedGenreCount( 1735 + genre: Option(String), 1736 + count: Option(Int), 1737 + ) 1738 + } 1739 + 1740 + pub type StatsWrappedMilestone { 1741 + StatsWrappedMilestone( 1742 + track_title: Option(String), 1743 + artist_name: Option(String), 1744 + timestamp: Option(String), 1745 + track_uri: Option(String), 1746 + ) 1747 + } 1748 + 1749 + pub type StatsWrappedMonthCount { 1750 + StatsWrappedMonthCount( 1751 + month: Option(Int), 1752 + count: Option(Int), 1753 + ) 1754 + } 1755 + 1756 + pub type StatsWrappedTrack { 1757 + StatsWrappedTrack( 1758 + id: Option(String), 1759 + title: Option(String), 1760 + artist: Option(String), 1761 + album_art: Option(String), 1762 + uri: Option(String), 1763 + artist_uri: Option(String), 1764 + album_uri: Option(String), 1765 + play_count: Option(Int), 1766 + ) 1767 + } 1768 + 1769 + pub type StatsWrappedView { 1770 + StatsWrappedView( 1771 + year: Option(Int), 1772 + total_scrobbles: Option(Int), 1773 + total_listening_time_minutes: Option(Int), 1774 + top_artists: List(StatsWrappedArtist), 1775 + top_tracks: List(StatsWrappedTrack), 1776 + top_albums: List(StatsWrappedAlbum), 1777 + top_genres: List(StatsWrappedGenreCount), 1778 + scrobbles_per_month: List(StatsWrappedMonthCount), 1779 + most_active_day: Option(StatsWrappedDayCount), 1780 + most_active_hour: Option(Int), 1781 + new_artists_count: Option(Int), 1782 + longest_streak: Option(Int), 1783 + first_scrobble: Option(StatsWrappedMilestone), 1784 + last_scrobble: Option(StatsWrappedMilestone), 1785 + ) 1786 + } 1787 + 1788 + pub type StatusRecord { 1789 + StatusRecord( 1790 + track: ActorTrackView, 1791 + started_at: String, 1792 + expires_at: Option(String), 1793 + ) 1794 + } 1795 + 1796 + pub type StrongRef { 1797 + StrongRef( 1798 + uri: String, 1799 + cid: String, 1800 + ) 1801 + } 1802 + 1803 + pub type UnfollowAccountOutput { 1804 + UnfollowAccountOutput( 1805 + subject: ActorProfileViewBasic, 1806 + followers: List(ActorProfileViewBasic), 1807 + cursor: Option(String), 1808 + ) 1809 + } 1810 + 1811 + pub type UnfollowAccountParams { 1812 + UnfollowAccountParams( 1813 + account: String, 1814 + ) 1815 + } 1816 + 1817 + pub type UpdateApikeyInput { 1818 + UpdateApikeyInput( 1819 + id: String, 1820 + name: String, 1821 + description: Option(String), 1822 + ) 1823 + }
+18 -102
sdk/gleam/src/rocksky/types.gleam
··· 1 1 //// Public types returned by Rocksky endpoint functions. 2 2 //// 3 - //// These mirror the lexicon `*ViewBasic` / `*ViewDetailed` shapes. Optional 4 - //// lexicon properties (anything not marked `required`) are `Option(t)` here. 3 + //// Most types are lex-derived aliases — see `rocksky/generated/types`. A 4 + //// handful (`ApiKey`, `Shout`) carry SDK-specific shapes that the lexicon 5 + //// does not yet model and stay hand-written. 5 6 6 7 import gleam/option.{type Option} 8 + import rocksky/generated/types as gen 7 9 8 - pub type Profile { 9 - Profile( 10 - id: Option(String), 11 - did: Option(String), 12 - handle: Option(String), 13 - display_name: Option(String), 14 - avatar: Option(String), 15 - created_at: Option(String), 16 - updated_at: Option(String), 17 - ) 18 - } 10 + pub type Profile = 11 + gen.ActorProfileViewBasic 19 12 20 - pub type Artist { 21 - Artist( 22 - id: Option(String), 23 - uri: Option(String), 24 - name: Option(String), 25 - picture: Option(String), 26 - sha256: Option(String), 27 - play_count: Option(Int), 28 - unique_listeners: Option(Int), 29 - tags: List(String), 30 - ) 31 - } 13 + pub type Artist = 14 + gen.ArtistViewBasic 32 15 33 - pub type Album { 34 - Album( 35 - id: Option(String), 36 - uri: Option(String), 37 - title: Option(String), 38 - artist: Option(String), 39 - artist_uri: Option(String), 40 - year: Option(Int), 41 - album_art: Option(String), 42 - release_date: Option(String), 43 - sha256: Option(String), 44 - play_count: Option(Int), 45 - unique_listeners: Option(Int), 46 - ) 47 - } 16 + pub type Album = 17 + gen.AlbumViewBasic 48 18 49 - pub type Song { 50 - Song( 51 - id: Option(String), 52 - uri: Option(String), 53 - title: Option(String), 54 - artist: Option(String), 55 - album_artist: Option(String), 56 - album: Option(String), 57 - album_art: Option(String), 58 - album_uri: Option(String), 59 - artist_uri: Option(String), 60 - duration: Option(Int), 61 - track_number: Option(Int), 62 - disc_number: Option(Int), 63 - play_count: Option(Int), 64 - unique_listeners: Option(Int), 65 - sha256: Option(String), 66 - mbid: Option(String), 67 - isrc: Option(String), 68 - tags: List(String), 69 - created_at: Option(String), 70 - ) 71 - } 19 + pub type Song = 20 + gen.SongViewBasic 72 21 73 - pub type Scrobble { 74 - Scrobble( 75 - id: Option(String), 76 - uri: Option(String), 77 - user: Option(String), 78 - user_display_name: Option(String), 79 - user_avatar: Option(String), 80 - title: Option(String), 81 - artist: Option(String), 82 - artist_uri: Option(String), 83 - album: Option(String), 84 - album_uri: Option(String), 85 - cover: Option(String), 86 - date: Option(String), 87 - sha256: Option(String), 88 - liked: Option(Bool), 89 - likes_count: Option(Int), 90 - ) 91 - } 22 + pub type Scrobble = 23 + gen.ScrobbleViewBasic 92 24 93 - pub type Listener { 94 - Listener( 95 - id: Option(String), 96 - did: Option(String), 97 - handle: Option(String), 98 - display_name: Option(String), 99 - avatar: Option(String), 100 - timestamp: Option(String), 101 - scrobble_uri: Option(String), 102 - ) 103 - } 25 + pub type Listener = 26 + gen.SongRecentListenerView 104 27 105 - pub type Stats { 106 - Stats( 107 - scrobbles: Option(Int), 108 - artists: Option(Int), 109 - loved_tracks: Option(Int), 110 - albums: Option(Int), 111 - tracks: Option(Int), 112 - ) 113 - } 28 + pub type Stats = 29 + gen.StatsView 114 30 115 31 pub type ApiKey { 116 32 ApiKey(
+3 -3
sdk/gleam/test/rocksky/decoders_test.gleam
··· 4 4 import gleam/option.{None, Some} 5 5 import gleeunit/should 6 6 import rocksky/decoders 7 - import rocksky/types.{Profile, Stats} 7 + import rocksky/generated/types as gen 8 8 9 9 pub fn profile_decoder_full_test() { 10 10 let body = ··· 19 19 }" 20 20 let assert Ok(p) = json.parse(body, decoders.profile()) 21 21 p 22 - |> should.equal(Profile( 22 + |> should.equal(gen.ActorProfileViewBasic( 23 23 id: Some("u_1"), 24 24 did: Some("did:plc:abc"), 25 25 handle: Some("alice.bsky.social"), ··· 85 85 }" 86 86 let assert Ok(s) = json.parse(body, decoders.stats()) 87 87 s 88 - |> should.equal(Stats( 88 + |> should.equal(gen.StatsView( 89 89 scrobbles: Some(1234), 90 90 artists: Some(89), 91 91 loved_tracks: Some(12),
+5
sdk/go/README.md
··· 165 165 go run ./examples/profile -actor tsiry.bsky.social 166 166 ``` 167 167 168 + ## Types 169 + 170 + Public model types are derived from the [Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons) and live in `rocksky/gen` (package `gen`). The package-level type aliases in `rocksky/types.go` re-export them under their historical names. Regenerate with `bun run lexgen:types` at the repo root. 171 + 172 + 168 173 ## Testing 169 174 170 175 ```bash
+7 -2
sdk/go/examples/search/main.go
··· 35 35 36 36 fmt.Printf("%d hits (search took %dms)\n\n", res.EstimatedTotalHits, res.ProcessingTimeMS) 37 37 for i, hit := range res.Hits { 38 - label := pickLabel(hit) 39 - fmt.Printf("%2d. [%s] %s\n", i+1, hit["$type"], label) 38 + obj, ok := hit.(map[string]any) 39 + if !ok { 40 + fmt.Printf("%2d. (unknown shape)\n", i+1) 41 + continue 42 + } 43 + label := pickLabel(obj) 44 + fmt.Printf("%2d. [%s] %s\n", i+1, obj["$type"], label) 40 45 } 41 46 } 42 47
+2 -1
sdk/go/rocksky/endpoints_test.go
··· 209 209 if got.EstimatedTotalHits != 2 || len(got.Hits) != 2 { 210 210 t.Fatalf("got = %+v", got) 211 211 } 212 - if got.Hits[1]["name"] != "Tame Impala" { 212 + hit1, ok := got.Hits[1].(map[string]any) 213 + if !ok || hit1["name"] != "Tame Impala" { 213 214 t.Fatalf("hit[1] = %+v", got.Hits[1]) 214 215 } 215 216 }
+2017
sdk/go/rocksky/gen/types.go
··· 1 + // Code generated by tools/lexgen — DO NOT EDIT. 2 + // Source: apps/api/lexicons/**/*.json 3 + // Regenerate via: bun run lexgen:types 4 + 5 + package gen 6 + 7 + // BlobRef is the atproto blob reference shape. 8 + type BlobRef struct { 9 + Type string `json:"$type,omitempty"` 10 + Ref BlobCidRef `json:"ref,omitempty"` 11 + MimeType string `json:"mimeType,omitempty"` 12 + Size int `json:"size,omitempty"` 13 + } 14 + 15 + type BlobCidRef struct { 16 + Link string `json:"$link,omitempty"` 17 + } 18 + 19 + 20 + type ActorArtistViewBasic struct { 21 + ID string `json:"id,omitempty"` 22 + Name string `json:"name,omitempty"` 23 + Picture string `json:"picture,omitempty"` 24 + URI string `json:"uri,omitempty"` 25 + User1Rank int `json:"user1Rank,omitempty"` 26 + User2Rank int `json:"user2Rank,omitempty"` 27 + Weight int `json:"weight,omitempty"` 28 + } 29 + 30 + type ActorCompatibilityViewBasic struct { 31 + CompatibilityLevel int `json:"compatibilityLevel,omitempty"` 32 + CompatibilityPercentage int `json:"compatibilityPercentage,omitempty"` 33 + SharedArtists int `json:"sharedArtists,omitempty"` 34 + TopSharedArtistNames []string `json:"topSharedArtistNames,omitempty"` 35 + TopSharedDetailedArtists []ActorArtistViewBasic `json:"topSharedDetailedArtists,omitempty"` 36 + User1ArtistCount int `json:"user1ArtistCount,omitempty"` 37 + User2ArtistCount int `json:"user2ArtistCount,omitempty"` 38 + } 39 + 40 + type ActorNeighbourViewBasic struct { 41 + UserID string `json:"userId,omitempty"` 42 + DID string `json:"did,omitempty"` 43 + Handle string `json:"handle,omitempty"` 44 + DisplayName string `json:"displayName,omitempty"` 45 + // The URL of the actor's avatar image. 46 + Avatar string `json:"avatar,omitempty"` 47 + // The number of artists shared with the actor. 48 + SharedArtistsCount int `json:"sharedArtistsCount,omitempty"` 49 + // The similarity score with the actor. 50 + SimilarityScore int `json:"similarityScore,omitempty"` 51 + // The top shared artist names with the actor. 52 + TopSharedArtistNames []string `json:"topSharedArtistNames,omitempty"` 53 + // The top shared artist details with the actor. 54 + TopSharedArtistsDetails []ArtistViewBasic `json:"topSharedArtistsDetails,omitempty"` 55 + } 56 + 57 + type ActorProfileViewBasic struct { 58 + // The unique identifier of the actor. 59 + ID string `json:"id,omitempty"` 60 + // The DID of the actor. 61 + DID string `json:"did,omitempty"` 62 + // The handle of the actor. 63 + Handle string `json:"handle,omitempty"` 64 + // The display name of the actor. 65 + DisplayName string `json:"displayName,omitempty"` 66 + // The URL of the actor's avatar image. 67 + Avatar string `json:"avatar,omitempty"` 68 + // The date and time when the actor was created. 69 + CreatedAt string `json:"createdAt,omitempty"` 70 + // The date and time when the actor was last updated. 71 + UpdatedAt string `json:"updatedAt,omitempty"` 72 + } 73 + 74 + type ActorProfileViewDetailed struct { 75 + // The unique identifier of the actor. 76 + ID string `json:"id,omitempty"` 77 + // The DID of the actor. 78 + DID string `json:"did,omitempty"` 79 + // The handle of the actor. 80 + Handle string `json:"handle,omitempty"` 81 + // The display name of the actor. 82 + DisplayName string `json:"displayName,omitempty"` 83 + // The URL of the actor's avatar image. 84 + Avatar string `json:"avatar,omitempty"` 85 + // The date and time when the actor was created. 86 + CreatedAt string `json:"createdAt,omitempty"` 87 + // The date and time when the actor was last updated. 88 + UpdatedAt string `json:"updatedAt,omitempty"` 89 + } 90 + 91 + type ActorTrackView struct { 92 + // The name of the track. 93 + Name string `json:"name,omitempty"` 94 + // The primary artist name. 95 + Artist string `json:"artist,omitempty"` 96 + // The album name. 97 + Album string `json:"album,omitempty"` 98 + // URL of the album cover image. 99 + AlbumCoverURL string `json:"albumCoverUrl,omitempty"` 100 + // Track duration in milliseconds. 101 + DurationMS int `json:"durationMs,omitempty"` 102 + // Music service source, e.g. 'spotify' or 'listenbrainz'. 103 + Source string `json:"source,omitempty"` 104 + // MusicBrainz recording ID, if available. 105 + RecordingMbID string `json:"recordingMbId,omitempty"` 106 + } 107 + 108 + type AddDirectoryToQueueParams struct { 109 + PlayerID string `json:"playerId,omitempty"` 110 + // The directory to add to the queue 111 + Directory string `json:"directory,omitempty"` 112 + // Position in the queue to insert the directory at, defaults to the end if not specified 113 + Position int `json:"position,omitempty"` 114 + // Whether to shuffle the added directory in the queue 115 + Shuffle bool `json:"shuffle,omitempty"` 116 + } 117 + 118 + type AddItemsToQueueParams struct { 119 + PlayerID string `json:"playerId,omitempty"` 120 + Items []string `json:"items,omitempty"` 121 + // Position in the queue to insert the items at, defaults to the end if not specified 122 + Position int `json:"position,omitempty"` 123 + // Whether to shuffle the added items in the queue 124 + Shuffle bool `json:"shuffle,omitempty"` 125 + } 126 + 127 + type AlbumRecord struct { 128 + // The title of the album. 129 + Title string `json:"title,omitempty"` 130 + // The artist of the album. 131 + Artist string `json:"artist,omitempty"` 132 + // The duration of the album in seconds. 133 + Duration int `json:"duration,omitempty"` 134 + // The release date of the album. 135 + ReleaseDate string `json:"releaseDate,omitempty"` 136 + // The year the album was released. 137 + Year int `json:"year,omitempty"` 138 + // The genre of the album. 139 + Genre string `json:"genre,omitempty"` 140 + // The album art of the album. 141 + AlbumArt BlobRef `json:"albumArt,omitempty"` 142 + // The URL of the album art of the album. 143 + AlbumArtURL string `json:"albumArtUrl,omitempty"` 144 + // The tags of the album. 145 + Tags []string `json:"tags,omitempty"` 146 + // The YouTube link of the album. 147 + YoutubeLink string `json:"youtubeLink,omitempty"` 148 + // The Spotify link of the album. 149 + SpotifyLink string `json:"spotifyLink,omitempty"` 150 + // The tidal link of the album. 151 + TidalLink string `json:"tidalLink,omitempty"` 152 + // The Apple Music link of the album. 153 + AppleMusicLink string `json:"appleMusicLink,omitempty"` 154 + // The date and time when the album was created. 155 + CreatedAt string `json:"createdAt,omitempty"` 156 + } 157 + 158 + type AlbumViewBasic struct { 159 + // The unique identifier of the album. 160 + ID string `json:"id,omitempty"` 161 + // The URI of the album. 162 + URI string `json:"uri,omitempty"` 163 + // The title of the album. 164 + Title string `json:"title,omitempty"` 165 + // The artist of the album. 166 + Artist string `json:"artist,omitempty"` 167 + // The URI of the album's artist. 168 + ArtistURI string `json:"artistUri,omitempty"` 169 + // The year the album was released. 170 + Year int `json:"year,omitempty"` 171 + // The URL of the album art image. 172 + AlbumArt string `json:"albumArt,omitempty"` 173 + // The release date of the album. 174 + ReleaseDate string `json:"releaseDate,omitempty"` 175 + // The SHA256 hash of the album. 176 + SHA256 string `json:"sha256,omitempty"` 177 + // The number of times the album has been played. 178 + PlayCount int `json:"playCount,omitempty"` 179 + // The number of unique listeners who have played the album. 180 + UniqueListeners int `json:"uniqueListeners,omitempty"` 181 + } 182 + 183 + type AlbumViewDetailed struct { 184 + // The unique identifier of the album. 185 + ID string `json:"id,omitempty"` 186 + // The URI of the album. 187 + URI string `json:"uri,omitempty"` 188 + // The title of the album. 189 + Title string `json:"title,omitempty"` 190 + // The artist of the album. 191 + Artist string `json:"artist,omitempty"` 192 + // The URI of the album's artist. 193 + ArtistURI string `json:"artistUri,omitempty"` 194 + // The year the album was released. 195 + Year int `json:"year,omitempty"` 196 + // The URL of the album art image. 197 + AlbumArt string `json:"albumArt,omitempty"` 198 + // The release date of the album. 199 + ReleaseDate string `json:"releaseDate,omitempty"` 200 + // The SHA256 hash of the album. 201 + SHA256 string `json:"sha256,omitempty"` 202 + // The number of times the album has been played. 203 + PlayCount int `json:"playCount,omitempty"` 204 + // The number of unique listeners who have played the album. 205 + UniqueListeners int `json:"uniqueListeners,omitempty"` 206 + Tags []string `json:"tags,omitempty"` 207 + Tracks []SongViewBasic `json:"tracks,omitempty"` 208 + } 209 + 210 + type ApiKeyView struct { 211 + // The unique identifier of the API key. 212 + ID string `json:"id,omitempty"` 213 + // The name of the API key. 214 + Name string `json:"name,omitempty"` 215 + // A description for the API key. 216 + Description string `json:"description,omitempty"` 217 + // The date and time when the API key was created. 218 + CreatedAt string `json:"createdAt,omitempty"` 219 + } 220 + 221 + type ArtistListenerViewBasic struct { 222 + // The unique identifier of the actor. 223 + ID string `json:"id,omitempty"` 224 + // The DID of the listener. 225 + DID string `json:"did,omitempty"` 226 + // The handle of the listener. 227 + Handle string `json:"handle,omitempty"` 228 + // The display name of the listener. 229 + DisplayName string `json:"displayName,omitempty"` 230 + // The URL of the listener's avatar image. 231 + Avatar string `json:"avatar,omitempty"` 232 + MostListenedSong *ArtistSongViewBasic `json:"mostListenedSong,omitempty"` 233 + // The total number of plays by the listener. 234 + TotalPlays int `json:"totalPlays,omitempty"` 235 + // The rank of the listener among all listeners of the artist. 236 + Rank int `json:"rank,omitempty"` 237 + } 238 + 239 + type ArtistMbid struct { 240 + // The MusicBrainz Identifier (MBID) of the artist. 241 + MBID string `json:"mbid,omitempty"` 242 + // The name of the artist. 243 + Name string `json:"name,omitempty"` 244 + } 245 + 246 + type ArtistRecentListenerView struct { 247 + // The unique identifier of the listener. 248 + ID string `json:"id,omitempty"` 249 + // The DID of the listener. 250 + DID string `json:"did,omitempty"` 251 + // The handle of the listener. 252 + Handle string `json:"handle,omitempty"` 253 + // The display name of the listener. 254 + DisplayName string `json:"displayName,omitempty"` 255 + // The URL of the listener's avatar image. 256 + Avatar string `json:"avatar,omitempty"` 257 + // The timestamp of the listener's most recent scrobble of this artist. 258 + Timestamp string `json:"timestamp,omitempty"` 259 + // The URI of the listener's most recent scrobble of this artist. 260 + ScrobbleURI string `json:"scrobbleUri,omitempty"` 261 + } 262 + 263 + type ArtistRecord struct { 264 + // The name of the artist. 265 + Name string `json:"name,omitempty"` 266 + // The biography of the artist. 267 + Bio string `json:"bio,omitempty"` 268 + // The picture of the artist. 269 + Picture BlobRef `json:"picture,omitempty"` 270 + // The URL of the picture of the artist. 271 + PictureURL string `json:"pictureUrl,omitempty"` 272 + // The tags of the artist. 273 + Tags []string `json:"tags,omitempty"` 274 + // The birth date of the artist. 275 + Born string `json:"born,omitempty"` 276 + // The death date of the artist. 277 + Died string `json:"died,omitempty"` 278 + // The birth place of the artist. 279 + BornIn string `json:"bornIn,omitempty"` 280 + // The date when the artist was created. 281 + CreatedAt string `json:"createdAt,omitempty"` 282 + } 283 + 284 + type ArtistSongViewBasic struct { 285 + // The URI of the song. 286 + URI string `json:"uri,omitempty"` 287 + // The title of the song. 288 + Title string `json:"title,omitempty"` 289 + // The number of times the song has been played. 290 + PlayCount int `json:"playCount,omitempty"` 291 + } 292 + 293 + type ArtistViewBasic struct { 294 + // The unique identifier of the artist. 295 + ID string `json:"id,omitempty"` 296 + // The URI of the artist. 297 + URI string `json:"uri,omitempty"` 298 + // The name of the artist. 299 + Name string `json:"name,omitempty"` 300 + // The picture of the artist. 301 + Picture string `json:"picture,omitempty"` 302 + // The SHA256 hash of the artist. 303 + SHA256 string `json:"sha256,omitempty"` 304 + // The number of times the artist has been played. 305 + PlayCount int `json:"playCount,omitempty"` 306 + // The number of unique listeners who have played the artist. 307 + UniqueListeners int `json:"uniqueListeners,omitempty"` 308 + Tags []string `json:"tags,omitempty"` 309 + } 310 + 311 + type ArtistViewDetailed struct { 312 + // The unique identifier of the artist. 313 + ID string `json:"id,omitempty"` 314 + // The URI of the artist. 315 + URI string `json:"uri,omitempty"` 316 + // The name of the artist. 317 + Name string `json:"name,omitempty"` 318 + // The picture of the artist. 319 + Picture string `json:"picture,omitempty"` 320 + // The SHA256 hash of the artist. 321 + SHA256 string `json:"sha256,omitempty"` 322 + // The number of times the artist has been played. 323 + PlayCount int `json:"playCount,omitempty"` 324 + // The number of unique listeners who have played the artist. 325 + UniqueListeners int `json:"uniqueListeners,omitempty"` 326 + Tags []string `json:"tags,omitempty"` 327 + } 328 + 329 + type ChartsScrobbleViewBasic struct { 330 + // The date of the scrobble. 331 + Date string `json:"date,omitempty"` 332 + // The number of scrobbles on this date. 333 + Count int `json:"count,omitempty"` 334 + } 335 + 336 + type ChartsView struct { 337 + Scrobbles []ChartsScrobbleViewBasic `json:"scrobbles,omitempty"` 338 + } 339 + 340 + type CreateApikeyInput struct { 341 + // The name of the API key. 342 + Name string `json:"name,omitempty"` 343 + // A description for the API key. 344 + Description string `json:"description,omitempty"` 345 + } 346 + 347 + type CreatePlaylistParams struct { 348 + // The name of the playlist 349 + Name string `json:"name,omitempty"` 350 + // A brief description of the playlist 351 + Description string `json:"description,omitempty"` 352 + } 353 + 354 + type CreateScrobbleInput struct { 355 + // The title of the track being scrobbled 356 + Title string `json:"title,omitempty"` 357 + // The artist of the track being scrobbled 358 + Artist string `json:"artist,omitempty"` 359 + // The album of the track being scrobbled 360 + Album string `json:"album,omitempty"` 361 + // The duration of the track in milliseconds 362 + Duration int `json:"duration,omitempty"` 363 + // The MusicBrainz ID of the track, if available 364 + MbID string `json:"mbId,omitempty"` 365 + // The International Standard Recording Code (ISRC) of the track, if available 366 + ISRC string `json:"isrc,omitempty"` 367 + // The URL of the album art for the track 368 + AlbumArt string `json:"albumArt,omitempty"` 369 + // The track number of the track in the album 370 + TrackNumber int `json:"trackNumber,omitempty"` 371 + // The release date of the track, formatted as YYYY-MM-DD 372 + ReleaseDate string `json:"releaseDate,omitempty"` 373 + // The year the track was released 374 + Year int `json:"year,omitempty"` 375 + // The disc number of the track in the album, if applicable 376 + DiscNumber int `json:"discNumber,omitempty"` 377 + // The lyrics of the track, if available 378 + Lyrics string `json:"lyrics,omitempty"` 379 + // The composer of the track, if available 380 + Composer string `json:"composer,omitempty"` 381 + // The copyright message for the track, if available 382 + CopyrightMessage string `json:"copyrightMessage,omitempty"` 383 + // The record label of the track, if available 384 + Label string `json:"label,omitempty"` 385 + // The URL of the artist's picture, if available 386 + ArtistPicture string `json:"artistPicture,omitempty"` 387 + // The Spotify link for the track, if available 388 + SpotifyLink string `json:"spotifyLink,omitempty"` 389 + // The Last.fm link for the track, if available 390 + LastfmLink string `json:"lastfmLink,omitempty"` 391 + // The Tidal link for the track, if available 392 + TidalLink string `json:"tidalLink,omitempty"` 393 + // The Apple Music link for the track, if available 394 + AppleMusicLink string `json:"appleMusicLink,omitempty"` 395 + // The Youtube link for the track, if available 396 + YoutubeLink string `json:"youtubeLink,omitempty"` 397 + // The Deezer link for the track, if available 398 + DeezerLink string `json:"deezerLink,omitempty"` 399 + // The timestamp of the scrobble in seconds since epoch (Unix timestamp) 400 + Timestamp int `json:"timestamp,omitempty"` 401 + } 402 + 403 + type CreateShoutInput struct { 404 + // The content of the shout 405 + Message string `json:"message,omitempty"` 406 + } 407 + 408 + type CreateSongInput struct { 409 + // The title of the song 410 + Title string `json:"title,omitempty"` 411 + // The artist of the song 412 + Artist string `json:"artist,omitempty"` 413 + // The album artist of the song, if different from the main artist 414 + AlbumArtist string `json:"albumArtist,omitempty"` 415 + // The album of the song, if applicable 416 + Album string `json:"album,omitempty"` 417 + // The duration of the song in seconds 418 + Duration int `json:"duration,omitempty"` 419 + // The MusicBrainz ID of the song, if available 420 + MbID string `json:"mbId,omitempty"` 421 + // The International Standard Recording Code (ISRC) of the song, if available 422 + ISRC string `json:"isrc,omitempty"` 423 + // The URL of the album art for the song 424 + AlbumArt string `json:"albumArt,omitempty"` 425 + // The track number of the song in the album, if applicable 426 + TrackNumber int `json:"trackNumber,omitempty"` 427 + // The release date of the song, formatted as YYYY-MM-DD 428 + ReleaseDate string `json:"releaseDate,omitempty"` 429 + // The year the song was released 430 + Year int `json:"year,omitempty"` 431 + // The disc number of the song in the album, if applicable 432 + DiscNumber int `json:"discNumber,omitempty"` 433 + // The lyrics of the song, if available 434 + Lyrics string `json:"lyrics,omitempty"` 435 + } 436 + 437 + type DescribeFeedGeneratorOutput struct { 438 + // The DID of the feed generator. 439 + DID string `json:"did,omitempty"` 440 + // List of feed URIs generated by this feed generator. 441 + Feeds []FeedUriView `json:"feeds,omitempty"` 442 + } 443 + 444 + type DescribeFeedGeneratorParams struct { 445 + } 446 + 447 + type DislikeShoutInput struct { 448 + // The unique identifier of the shout to dislike 449 + URI string `json:"uri,omitempty"` 450 + } 451 + 452 + type DislikeSongInput struct { 453 + // The unique identifier of the song to dislike 454 + URI string `json:"uri,omitempty"` 455 + } 456 + 457 + type DownloadFileParams struct { 458 + // The unique identifier of the file to download 459 + FileID string `json:"fileId,omitempty"` 460 + } 461 + 462 + type DropboxFileListView struct { 463 + // A list of files in the Dropbox. 464 + Files []DropboxFileView `json:"files,omitempty"` 465 + } 466 + 467 + type DropboxFileView struct { 468 + // The unique identifier of the file. 469 + ID string `json:"id,omitempty"` 470 + // The name of the file. 471 + Name string `json:"name,omitempty"` 472 + // The lowercased path of the file. 473 + PathLower string `json:"pathLower,omitempty"` 474 + // The display path of the file. 475 + PathDisplay string `json:"pathDisplay,omitempty"` 476 + // The last modified date and time of the file on the client. 477 + ClientModified string `json:"clientModified,omitempty"` 478 + // The last modified date and time of the file on the server. 479 + ServerModified string `json:"serverModified,omitempty"` 480 + } 481 + 482 + type DropboxTemporaryLinkView struct { 483 + // The temporary link to access the file. 484 + Link string `json:"link,omitempty"` 485 + } 486 + 487 + type FeedGeneratorsView struct { 488 + Feeds []FeedGeneratorView `json:"feeds,omitempty"` 489 + } 490 + 491 + type FeedGeneratorView struct { 492 + ID string `json:"id,omitempty"` 493 + Name string `json:"name,omitempty"` 494 + Description string `json:"description,omitempty"` 495 + URI string `json:"uri,omitempty"` 496 + Avatar string `json:"avatar,omitempty"` 497 + Creator *ActorProfileViewBasic `json:"creator,omitempty"` 498 + } 499 + 500 + type FeedItemView struct { 501 + Scrobble *ScrobbleViewBasic `json:"scrobble,omitempty"` 502 + } 503 + 504 + type FeedRecommendationsView struct { 505 + Recommendations []FeedRecommendationView `json:"recommendations,omitempty"` 506 + Cursor string `json:"cursor,omitempty"` 507 + } 508 + 509 + type FeedRecommendationView struct { 510 + Title string `json:"title,omitempty"` 511 + Artist string `json:"artist,omitempty"` 512 + Album string `json:"album,omitempty"` 513 + AlbumArt string `json:"albumArt,omitempty"` 514 + TrackURI string `json:"trackUri,omitempty"` 515 + ArtistURI string `json:"artistUri,omitempty"` 516 + AlbumURI string `json:"albumUri,omitempty"` 517 + Genres []string `json:"genres,omitempty"` 518 + RecommendationScore int `json:"recommendationScore,omitempty"` 519 + // neighbour | social | serendipity 520 + Source string `json:"source,omitempty"` 521 + LikesCount int `json:"likesCount,omitempty"` 522 + } 523 + 524 + type FeedRecommendedAlbumsView struct { 525 + Albums []FeedRecommendedAlbumView `json:"albums,omitempty"` 526 + Cursor string `json:"cursor,omitempty"` 527 + } 528 + 529 + type FeedRecommendedAlbumView struct { 530 + ID string `json:"id,omitempty"` 531 + URI string `json:"uri,omitempty"` 532 + Title string `json:"title,omitempty"` 533 + Artist string `json:"artist,omitempty"` 534 + ArtistURI string `json:"artistUri,omitempty"` 535 + Year int `json:"year,omitempty"` 536 + AlbumArt string `json:"albumArt,omitempty"` 537 + RecommendationScore int `json:"recommendationScore,omitempty"` 538 + // known-artist | new-artist | serendipity 539 + Source string `json:"source,omitempty"` 540 + } 541 + 542 + type FeedRecommendedArtistsView struct { 543 + Artists []FeedRecommendedArtistView `json:"artists,omitempty"` 544 + Cursor string `json:"cursor,omitempty"` 545 + } 546 + 547 + type FeedRecommendedArtistView struct { 548 + ID string `json:"id,omitempty"` 549 + URI string `json:"uri,omitempty"` 550 + Name string `json:"name,omitempty"` 551 + Picture string `json:"picture,omitempty"` 552 + Genres []string `json:"genres,omitempty"` 553 + RecommendationScore int `json:"recommendationScore,omitempty"` 554 + // neighbour | social | serendipity 555 + Source string `json:"source,omitempty"` 556 + } 557 + 558 + type FeedSearchResultsView struct { 559 + Hits []any `json:"hits,omitempty"` 560 + ProcessingTimeMS int `json:"processingTimeMs,omitempty"` 561 + Limit int `json:"limit,omitempty"` 562 + Offset int `json:"offset,omitempty"` 563 + EstimatedTotalHits int `json:"estimatedTotalHits,omitempty"` 564 + } 565 + 566 + type FeedStoriesView struct { 567 + Stories []FeedStoryView `json:"stories,omitempty"` 568 + } 569 + 570 + type FeedStoryView struct { 571 + Album string `json:"album,omitempty"` 572 + AlbumArt string `json:"albumArt,omitempty"` 573 + AlbumArtist string `json:"albumArtist,omitempty"` 574 + AlbumURI string `json:"albumUri,omitempty"` 575 + Artist string `json:"artist,omitempty"` 576 + ArtistURI string `json:"artistUri,omitempty"` 577 + Avatar string `json:"avatar,omitempty"` 578 + CreatedAt string `json:"createdAt,omitempty"` 579 + DID string `json:"did,omitempty"` 580 + Handle string `json:"handle,omitempty"` 581 + ID string `json:"id,omitempty"` 582 + Title string `json:"title,omitempty"` 583 + TrackID string `json:"trackId,omitempty"` 584 + TrackURI string `json:"trackUri,omitempty"` 585 + URI string `json:"uri,omitempty"` 586 + } 587 + 588 + type FeedUriView struct { 589 + // The feed URI. 590 + URI string `json:"uri,omitempty"` 591 + } 592 + 593 + type FeedView struct { 594 + Feed []FeedItemView `json:"feed,omitempty"` 595 + // The pagination cursor for the next set of results. 596 + Cursor string `json:"cursor,omitempty"` 597 + } 598 + 599 + type FollowAccountOutput struct { 600 + Subject *ActorProfileViewBasic `json:"subject,omitempty"` 601 + Followers []ActorProfileViewBasic `json:"followers,omitempty"` 602 + // A cursor value to pass to subsequent calls to get the next page of results. 603 + Cursor string `json:"cursor,omitempty"` 604 + } 605 + 606 + type FollowAccountParams struct { 607 + Account string `json:"account,omitempty"` 608 + } 609 + 610 + type FollowRecord struct { 611 + CreatedAt string `json:"createdAt,omitempty"` 612 + Subject string `json:"subject,omitempty"` 613 + Via *StrongRef `json:"via,omitempty"` 614 + } 615 + 616 + type GeneratorRecord struct { 617 + DID string `json:"did,omitempty"` 618 + Avatar BlobRef `json:"avatar,omitempty"` 619 + DisplayName string `json:"displayName,omitempty"` 620 + Description string `json:"description,omitempty"` 621 + CreatedAt string `json:"createdAt,omitempty"` 622 + } 623 + 624 + type GetActorAlbumsOutput struct { 625 + Albums []AlbumViewBasic `json:"albums,omitempty"` 626 + } 627 + 628 + type GetActorAlbumsParams struct { 629 + // The DID or handle of the actor 630 + DID string `json:"did,omitempty"` 631 + // The maximum number of albums to return 632 + Limit int `json:"limit,omitempty"` 633 + // The offset for pagination 634 + Offset int `json:"offset,omitempty"` 635 + // The start date to filter albums from (ISO 8601 format) 636 + StartDate string `json:"startDate,omitempty"` 637 + // The end date to filter albums to (ISO 8601 format) 638 + EndDate string `json:"endDate,omitempty"` 639 + } 640 + 641 + type GetActorArtistsOutput struct { 642 + Artists []ArtistViewBasic `json:"artists,omitempty"` 643 + } 644 + 645 + type GetActorArtistsParams struct { 646 + // The DID or handle of the actor 647 + DID string `json:"did,omitempty"` 648 + // The maximum number of albums to return 649 + Limit int `json:"limit,omitempty"` 650 + // The offset for pagination 651 + Offset int `json:"offset,omitempty"` 652 + // The start date to filter albums from (ISO 8601 format) 653 + StartDate string `json:"startDate,omitempty"` 654 + // The end date to filter albums to (ISO 8601 format) 655 + EndDate string `json:"endDate,omitempty"` 656 + } 657 + 658 + type GetActorCompatibilityOutput struct { 659 + Compatibility *ActorCompatibilityViewBasic `json:"compatibility,omitempty"` 660 + } 661 + 662 + type GetActorCompatibilityParams struct { 663 + // DID or handle to get compatibility for 664 + DID string `json:"did,omitempty"` 665 + } 666 + 667 + type GetActorLovedSongsOutput struct { 668 + Tracks []SongViewBasic `json:"tracks,omitempty"` 669 + } 670 + 671 + type GetActorLovedSongsParams struct { 672 + // The DID or handle of the actor 673 + DID string `json:"did,omitempty"` 674 + // The maximum number of albums to return 675 + Limit int `json:"limit,omitempty"` 676 + // The offset for pagination 677 + Offset int `json:"offset,omitempty"` 678 + } 679 + 680 + type GetActorNeighboursOutput struct { 681 + Neighbours []ActorNeighbourViewBasic `json:"neighbours,omitempty"` 682 + } 683 + 684 + type GetActorNeighboursParams struct { 685 + // The DID or handle of the actor 686 + DID string `json:"did,omitempty"` 687 + } 688 + 689 + type GetActorPlaylistsOutput struct { 690 + Playlists []PlaylistViewBasic `json:"playlists,omitempty"` 691 + } 692 + 693 + type GetActorPlaylistsParams struct { 694 + // The DID or handle of the actor 695 + DID string `json:"did,omitempty"` 696 + // The maximum number of albums to return 697 + Limit int `json:"limit,omitempty"` 698 + // The offset for pagination 699 + Offset int `json:"offset,omitempty"` 700 + } 701 + 702 + type GetActorScrobblesOutput struct { 703 + Scrobbles []ScrobbleViewBasic `json:"scrobbles,omitempty"` 704 + } 705 + 706 + type GetActorScrobblesParams struct { 707 + // The DID or handle of the actor 708 + DID string `json:"did,omitempty"` 709 + // The maximum number of albums to return 710 + Limit int `json:"limit,omitempty"` 711 + // The offset for pagination 712 + Offset int `json:"offset,omitempty"` 713 + } 714 + 715 + type GetActorSongsOutput struct { 716 + Songs []SongViewBasic `json:"songs,omitempty"` 717 + } 718 + 719 + type GetActorSongsParams struct { 720 + // The DID or handle of the actor 721 + DID string `json:"did,omitempty"` 722 + // The maximum number of albums to return 723 + Limit int `json:"limit,omitempty"` 724 + // The offset for pagination 725 + Offset int `json:"offset,omitempty"` 726 + // The start date to filter albums from (ISO 8601 format) 727 + StartDate string `json:"startDate,omitempty"` 728 + // The end date to filter albums to (ISO 8601 format) 729 + EndDate string `json:"endDate,omitempty"` 730 + } 731 + 732 + type GetAlbumParams struct { 733 + // The URI of the album to retrieve. 734 + URI string `json:"uri,omitempty"` 735 + } 736 + 737 + type GetAlbumRecommendationsParams struct { 738 + // DID or handle of the user to recommend for. 739 + DID string `json:"did,omitempty"` 740 + Limit int `json:"limit,omitempty"` 741 + } 742 + 743 + type GetAlbumShoutsOutput struct { 744 + Shouts []any `json:"shouts,omitempty"` 745 + } 746 + 747 + type GetAlbumShoutsParams struct { 748 + // The unique identifier of the album to retrieve shouts for 749 + URI string `json:"uri,omitempty"` 750 + // The maximum number of shouts to return 751 + Limit int `json:"limit,omitempty"` 752 + // The number of shouts to skip before starting to collect the result set 753 + Offset int `json:"offset,omitempty"` 754 + } 755 + 756 + type GetAlbumsOutput struct { 757 + Albums []AlbumViewBasic `json:"albums,omitempty"` 758 + } 759 + 760 + type GetAlbumsParams struct { 761 + // The maximum number of albums to return 762 + Limit int `json:"limit,omitempty"` 763 + // The offset for pagination 764 + Offset int `json:"offset,omitempty"` 765 + // The genre to filter artists by 766 + Genre string `json:"genre,omitempty"` 767 + } 768 + 769 + type GetAlbumTracksOutput struct { 770 + Tracks []SongViewBasic `json:"tracks,omitempty"` 771 + } 772 + 773 + type GetAlbumTracksParams struct { 774 + // The URI of the album to retrieve tracks from 775 + URI string `json:"uri,omitempty"` 776 + } 777 + 778 + type GetApikeysOutput struct { 779 + APIKeys []any `json:"apiKeys,omitempty"` 780 + } 781 + 782 + type GetApikeysParams struct { 783 + // The number of API keys to skip before starting to collect the result set. 784 + Offset int `json:"offset,omitempty"` 785 + // The number of API keys to return per page. 786 + Limit int `json:"limit,omitempty"` 787 + } 788 + 789 + type GetArtistAlbumsOutput struct { 790 + Albums []AlbumViewBasic `json:"albums,omitempty"` 791 + } 792 + 793 + type GetArtistAlbumsParams struct { 794 + // The URI of the artist to retrieve albums from 795 + URI string `json:"uri,omitempty"` 796 + } 797 + 798 + type GetArtistListenersOutput struct { 799 + Listeners []ArtistListenerViewBasic `json:"listeners,omitempty"` 800 + } 801 + 802 + type GetArtistListenersParams struct { 803 + // The URI of the artist to retrieve listeners from 804 + URI string `json:"uri,omitempty"` 805 + // Number of items to skip before returning results 806 + Offset int `json:"offset,omitempty"` 807 + // Maximum number of results to return 808 + Limit int `json:"limit,omitempty"` 809 + } 810 + 811 + type GetArtistParams struct { 812 + // The URI of the artist to retrieve details from 813 + URI string `json:"uri,omitempty"` 814 + } 815 + 816 + type GetArtistRecentListenersOutput struct { 817 + Listeners []ArtistRecentListenerView `json:"listeners,omitempty"` 818 + } 819 + 820 + type GetArtistRecentListenersParams struct { 821 + // The URI of the artist to retrieve recent listeners from 822 + URI string `json:"uri,omitempty"` 823 + // Number of items to skip before returning results 824 + Offset int `json:"offset,omitempty"` 825 + // Maximum number of results to return 826 + Limit int `json:"limit,omitempty"` 827 + } 828 + 829 + type GetArtistRecommendationsParams struct { 830 + // DID or handle of the user to recommend for. 831 + DID string `json:"did,omitempty"` 832 + Limit int `json:"limit,omitempty"` 833 + } 834 + 835 + type GetArtistShoutsOutput struct { 836 + Shouts []any `json:"shouts,omitempty"` 837 + } 838 + 839 + type GetArtistShoutsParams struct { 840 + // The URI of the artist to retrieve shouts for 841 + URI string `json:"uri,omitempty"` 842 + // The maximum number of shouts to return 843 + Limit int `json:"limit,omitempty"` 844 + // The number of shouts to skip before starting to collect the result set 845 + Offset int `json:"offset,omitempty"` 846 + } 847 + 848 + type GetArtistsOutput struct { 849 + Artists []ArtistViewBasic `json:"artists,omitempty"` 850 + } 851 + 852 + type GetArtistsParams struct { 853 + // The maximum number of artists to return 854 + Limit int `json:"limit,omitempty"` 855 + // The offset for pagination 856 + Offset int `json:"offset,omitempty"` 857 + // The names of the artists to return 858 + Names string `json:"names,omitempty"` 859 + // The genre to filter artists by 860 + Genre string `json:"genre,omitempty"` 861 + } 862 + 863 + type GetArtistTracksOutput struct { 864 + Tracks []SongViewBasic `json:"tracks,omitempty"` 865 + } 866 + 867 + type GetArtistTracksParams struct { 868 + // The URI of the artist to retrieve albums from 869 + URI string `json:"uri,omitempty"` 870 + // The maximum number of tracks to return 871 + Limit int `json:"limit,omitempty"` 872 + // The offset for pagination 873 + Offset int `json:"offset,omitempty"` 874 + } 875 + 876 + type GetCurrentlyPlayingParams struct { 877 + PlayerID string `json:"playerId,omitempty"` 878 + // Handle or DID of the actor to retrieve the currently playing track for. If not provided, defaults to the current user. 879 + Actor string `json:"actor,omitempty"` 880 + } 881 + 882 + type GetFeedGeneratorOutput struct { 883 + View *FeedGeneratorView `json:"view,omitempty"` 884 + } 885 + 886 + type GetFeedGeneratorParams struct { 887 + // AT-URI of the feed generator record. 888 + Feed string `json:"feed,omitempty"` 889 + } 890 + 891 + type GetFeedGeneratorsParams struct { 892 + // The maximum number of feed generators to return. 893 + Size int `json:"size,omitempty"` 894 + } 895 + 896 + type GetFeedParams struct { 897 + // The feed URI. 898 + Feed string `json:"feed,omitempty"` 899 + // The maximum number of scrobbles to return 900 + Limit int `json:"limit,omitempty"` 901 + // The cursor for pagination 902 + Cursor string `json:"cursor,omitempty"` 903 + } 904 + 905 + type GetFeedSkeletonOutput struct { 906 + Scrobbles []ScrobbleViewBasic `json:"scrobbles,omitempty"` 907 + // The pagination cursor for the next set of results. 908 + Cursor string `json:"cursor,omitempty"` 909 + } 910 + 911 + type GetFeedSkeletonParams struct { 912 + // The feed URI. 913 + Feed string `json:"feed,omitempty"` 914 + // The maximum number of scrobbles to return 915 + Limit int `json:"limit,omitempty"` 916 + // The offset for pagination 917 + Offset int `json:"offset,omitempty"` 918 + // The pagination cursor. 919 + Cursor string `json:"cursor,omitempty"` 920 + } 921 + 922 + type GetFileParams struct { 923 + // The unique identifier of the file to retrieve 924 + FileID string `json:"fileId,omitempty"` 925 + } 926 + 927 + type GetFilesParams struct { 928 + // Path to the Dropbox folder or root directory 929 + At string `json:"at,omitempty"` 930 + } 931 + 932 + type GetFollowersOutput struct { 933 + Subject *ActorProfileViewBasic `json:"subject,omitempty"` 934 + Followers []ActorProfileViewBasic `json:"followers,omitempty"` 935 + // A cursor value to pass to subsequent calls to get the next page of results. 936 + Cursor string `json:"cursor,omitempty"` 937 + // The total number of followers. 938 + Count int `json:"count,omitempty"` 939 + } 940 + 941 + type GetFollowersParams struct { 942 + Actor string `json:"actor,omitempty"` 943 + Limit int `json:"limit,omitempty"` 944 + // If provided, filters the followers to only include those with DIDs in this list. 945 + Dids []string `json:"dids,omitempty"` 946 + Cursor string `json:"cursor,omitempty"` 947 + } 948 + 949 + type GetFollowsOutput struct { 950 + Subject *ActorProfileViewBasic `json:"subject,omitempty"` 951 + Follows []ActorProfileViewBasic `json:"follows,omitempty"` 952 + // A cursor value to pass to subsequent calls to get the next page of results. 953 + Cursor string `json:"cursor,omitempty"` 954 + // The total number of follows. 955 + Count int `json:"count,omitempty"` 956 + } 957 + 958 + type GetFollowsParams struct { 959 + Actor string `json:"actor,omitempty"` 960 + Limit int `json:"limit,omitempty"` 961 + // If provided, filters the follows to only include those with DIDs in this list. 962 + Dids []string `json:"dids,omitempty"` 963 + Cursor string `json:"cursor,omitempty"` 964 + } 965 + 966 + type GetKnownFollowersOutput struct { 967 + Subject *ActorProfileViewBasic `json:"subject,omitempty"` 968 + Followers []ActorProfileViewBasic `json:"followers,omitempty"` 969 + // A cursor value to pass to subsequent calls to get the next page of results. 970 + Cursor string `json:"cursor,omitempty"` 971 + } 972 + 973 + type GetKnownFollowersParams struct { 974 + Actor string `json:"actor,omitempty"` 975 + Limit int `json:"limit,omitempty"` 976 + Cursor string `json:"cursor,omitempty"` 977 + } 978 + 979 + type GetMetadataParams struct { 980 + // Path to the file or folder in Dropbox 981 + Path string `json:"path,omitempty"` 982 + } 983 + 984 + type GetMirrorSourcesOutput struct { 985 + Sources []MirrorSourceView `json:"sources,omitempty"` 986 + } 987 + 988 + type GetMirrorSourcesParams struct { 989 + } 990 + 991 + type GetPlaybackQueueParams struct { 992 + PlayerID string `json:"playerId,omitempty"` 993 + } 994 + 995 + type GetPlaylistParams struct { 996 + // The URI of the playlist to retrieve. 997 + URI string `json:"uri,omitempty"` 998 + } 999 + 1000 + type GetPlaylistsOutput struct { 1001 + Playlists []PlaylistViewBasic `json:"playlists,omitempty"` 1002 + } 1003 + 1004 + type GetPlaylistsParams struct { 1005 + // The maximum number of playlists to return. 1006 + Limit int `json:"limit,omitempty"` 1007 + // The offset for pagination, used to skip a number of playlists. 1008 + Offset int `json:"offset,omitempty"` 1009 + } 1010 + 1011 + type GetProfileParams struct { 1012 + // The DID or handle of the actor 1013 + DID string `json:"did,omitempty"` 1014 + } 1015 + 1016 + type GetProfileShoutsOutput struct { 1017 + Shouts []any `json:"shouts,omitempty"` 1018 + } 1019 + 1020 + type GetProfileShoutsParams struct { 1021 + // The DID or handle of the actor 1022 + DID string `json:"did,omitempty"` 1023 + // The offset for pagination 1024 + Offset int `json:"offset,omitempty"` 1025 + // The maximum number of shouts to return 1026 + Limit int `json:"limit,omitempty"` 1027 + } 1028 + 1029 + type GetRecommendationsParams struct { 1030 + // DID or handle of the user to recommend for. 1031 + DID string `json:"did,omitempty"` 1032 + Limit int `json:"limit,omitempty"` 1033 + } 1034 + 1035 + type GetScrobbleParams struct { 1036 + // The unique identifier of the scrobble 1037 + URI string `json:"uri,omitempty"` 1038 + } 1039 + 1040 + type GetScrobblesChartParams struct { 1041 + // The DID or handle of the actor 1042 + DID string `json:"did,omitempty"` 1043 + // The URI of the artist to filter by 1044 + Artisturi string `json:"artisturi,omitempty"` 1045 + // The URI of the album to filter by 1046 + Albumuri string `json:"albumuri,omitempty"` 1047 + // The URI of the track to filter by 1048 + Songuri string `json:"songuri,omitempty"` 1049 + // The genre to filter by 1050 + Genre string `json:"genre,omitempty"` 1051 + // Start date (ISO 8601). Defaults to 6 months ago. 1052 + From string `json:"from,omitempty"` 1053 + // End date (ISO 8601). Defaults to today. 1054 + To string `json:"to,omitempty"` 1055 + } 1056 + 1057 + type GetScrobblesOutput struct { 1058 + Scrobbles []ScrobbleViewBasic `json:"scrobbles,omitempty"` 1059 + } 1060 + 1061 + type GetScrobblesParams struct { 1062 + // The DID or handle of the actor 1063 + DID string `json:"did,omitempty"` 1064 + // If true, only return scrobbles from actors the viewer is following. 1065 + Following bool `json:"following,omitempty"` 1066 + // The maximum number of scrobbles to return 1067 + Limit int `json:"limit,omitempty"` 1068 + // The offset for pagination 1069 + Offset int `json:"offset,omitempty"` 1070 + } 1071 + 1072 + type GetShoutRepliesOutput struct { 1073 + Shouts []any `json:"shouts,omitempty"` 1074 + } 1075 + 1076 + type GetShoutRepliesParams struct { 1077 + // The URI of the shout to retrieve replies for 1078 + URI string `json:"uri,omitempty"` 1079 + // The maximum number of shouts to return 1080 + Limit int `json:"limit,omitempty"` 1081 + // The number of shouts to skip before starting to collect the result set 1082 + Offset int `json:"offset,omitempty"` 1083 + } 1084 + 1085 + type GetSongParams struct { 1086 + // The AT-URI of the song to retrieve 1087 + URI string `json:"uri,omitempty"` 1088 + // The MusicBrainz ID of the song to retrieve 1089 + MBID string `json:"mbid,omitempty"` 1090 + // The International Standard Recording Code (ISRC) of the song to retrieve 1091 + ISRC string `json:"isrc,omitempty"` 1092 + // The Spotify track ID of the song to retrieve (resolved internally to the Spotify track URL) 1093 + SpotifyID string `json:"spotifyId,omitempty"` 1094 + } 1095 + 1096 + type GetSongRecentListenersOutput struct { 1097 + Listeners []SongRecentListenerView `json:"listeners,omitempty"` 1098 + } 1099 + 1100 + type GetSongRecentListenersParams struct { 1101 + // The URI of the song to retrieve recent listeners from 1102 + URI string `json:"uri,omitempty"` 1103 + // Number of items to skip before returning results 1104 + Offset int `json:"offset,omitempty"` 1105 + // Maximum number of results to return 1106 + Limit int `json:"limit,omitempty"` 1107 + } 1108 + 1109 + type GetSongsOutput struct { 1110 + Songs []SongViewBasic `json:"songs,omitempty"` 1111 + } 1112 + 1113 + type GetSongsParams struct { 1114 + // The maximum number of songs to return 1115 + Limit int `json:"limit,omitempty"` 1116 + // The offset for pagination 1117 + Offset int `json:"offset,omitempty"` 1118 + // The genre to filter artists by 1119 + Genre string `json:"genre,omitempty"` 1120 + // Filter songs by MusicBrainz ID 1121 + MBID string `json:"mbid,omitempty"` 1122 + // Filter songs by International Standard Recording Code (ISRC) 1123 + ISRC string `json:"isrc,omitempty"` 1124 + // Filter songs by Spotify track ID (resolved internally to the Spotify track URL) 1125 + SpotifyID string `json:"spotifyId,omitempty"` 1126 + } 1127 + 1128 + type GetStatsParams struct { 1129 + // The DID or handle of the user to get stats for. 1130 + DID string `json:"did,omitempty"` 1131 + } 1132 + 1133 + type GetStoriesParams struct { 1134 + // The maximum number of stories to return. 1135 + Size int `json:"size,omitempty"` 1136 + } 1137 + 1138 + type GetTemporaryLinkParams struct { 1139 + // Path to the file in Dropbox 1140 + Path string `json:"path,omitempty"` 1141 + } 1142 + 1143 + type GetTopArtistsOutput struct { 1144 + Artists []ArtistViewBasic `json:"artists,omitempty"` 1145 + } 1146 + 1147 + type GetTopArtistsParams struct { 1148 + // The maximum number of artists to return 1149 + Limit int `json:"limit,omitempty"` 1150 + // The offset for pagination 1151 + Offset int `json:"offset,omitempty"` 1152 + // The start date to filter artists from (ISO 8601 format) 1153 + StartDate string `json:"startDate,omitempty"` 1154 + // The end date to filter artists to (ISO 8601 format) 1155 + EndDate string `json:"endDate,omitempty"` 1156 + } 1157 + 1158 + type GetTopTracksOutput struct { 1159 + Tracks []SongViewBasic `json:"tracks,omitempty"` 1160 + } 1161 + 1162 + type GetTopTracksParams struct { 1163 + // The maximum number of tracks to return 1164 + Limit int `json:"limit,omitempty"` 1165 + // The offset for pagination 1166 + Offset int `json:"offset,omitempty"` 1167 + // The start date to filter tracks from (ISO 8601 format) 1168 + StartDate string `json:"startDate,omitempty"` 1169 + // The end date to filter tracks to (ISO 8601 format) 1170 + EndDate string `json:"endDate,omitempty"` 1171 + } 1172 + 1173 + type GetTrackShoutsOutput struct { 1174 + Shouts []any `json:"shouts,omitempty"` 1175 + } 1176 + 1177 + type GetTrackShoutsParams struct { 1178 + // The URI of the track to retrieve shouts for 1179 + URI string `json:"uri,omitempty"` 1180 + } 1181 + 1182 + type GetWrappedParams struct { 1183 + // The DID or handle of the user 1184 + DID string `json:"did,omitempty"` 1185 + // The year to get wrapped stats for (defaults to current year) 1186 + Year int `json:"year,omitempty"` 1187 + } 1188 + 1189 + type GoogledriveFileListView struct { 1190 + Files []GoogledriveFileView `json:"files,omitempty"` 1191 + } 1192 + 1193 + type GoogledriveFileView struct { 1194 + // The unique identifier of the file. 1195 + ID string `json:"id,omitempty"` 1196 + } 1197 + 1198 + // GraphNotFoundActor indicates that a handle or DID could not be resolved 1199 + type GraphNotFoundActor struct { 1200 + Actor string `json:"actor,omitempty"` 1201 + NotFound bool `json:"notFound,omitempty"` 1202 + } 1203 + 1204 + type GraphRelationship struct { 1205 + DID string `json:"did,omitempty"` 1206 + // if the actor follows this DID, this is the AT-URI of the follow record 1207 + Following string `json:"following,omitempty"` 1208 + // if the actor is followed by this DID, contains the AT-URI of the follow record 1209 + FollowedBy string `json:"followedBy,omitempty"` 1210 + } 1211 + 1212 + type InsertDirectoryParams struct { 1213 + // The URI of the playlist to start 1214 + URI string `json:"uri,omitempty"` 1215 + // The directory (id) to insert into the playlist 1216 + Directory string `json:"directory,omitempty"` 1217 + // The position in the playlist to insert the directory at, if not specified, the directory will be appended 1218 + Position int `json:"position,omitempty"` 1219 + } 1220 + 1221 + type InsertFilesParams struct { 1222 + // The URI of the playlist to start 1223 + URI string `json:"uri,omitempty"` 1224 + Files []string `json:"files,omitempty"` 1225 + // The position in the playlist to insert the files at, if not specified, files will be appended 1226 + Position int `json:"position,omitempty"` 1227 + } 1228 + 1229 + type LikeRecord struct { 1230 + // The date when the like was created. 1231 + CreatedAt string `json:"createdAt,omitempty"` 1232 + Subject *StrongRef `json:"subject,omitempty"` 1233 + } 1234 + 1235 + type LikeShoutInput struct { 1236 + // The unique identifier of the shout to like 1237 + URI string `json:"uri,omitempty"` 1238 + } 1239 + 1240 + type LikeSongInput struct { 1241 + // The unique identifier of the song to like 1242 + URI string `json:"uri,omitempty"` 1243 + } 1244 + 1245 + type MatchSongParams struct { 1246 + // The title of the song to retrieve 1247 + Title string `json:"title,omitempty"` 1248 + // The artist of the song to retrieve 1249 + Artist string `json:"artist,omitempty"` 1250 + // Optional MusicBrainz recording ID to anchor the match 1251 + MbID string `json:"mbId,omitempty"` 1252 + // Optional International Standard Recording Code (ISRC) to anchor the match 1253 + ISRC string `json:"isrc,omitempty"` 1254 + } 1255 + 1256 + type MirrorSourceView struct { 1257 + // One of: lastfm, listenbrainz, tealfm 1258 + Provider string `json:"provider,omitempty"` 1259 + // Whether scrobbles from this source are being mirrored into Rocksky. 1260 + Enabled bool `json:"enabled,omitempty"` 1261 + // Username on the external service (Last.fm / ListenBrainz). Null for Teal.fm. 1262 + ExternalUsername string `json:"externalUsername,omitempty"` 1263 + // True when an API key is stored. Last.fm/ListenBrainz only; always false for Teal.fm. 1264 + HasCredentials bool `json:"hasCredentials,omitempty"` 1265 + // The last time the mirror process successfully polled this source. 1266 + LastPolledAt string `json:"lastPolledAt,omitempty"` 1267 + // Watermark — scrobbles from the external service older than this are skipped. 1268 + LastScrobbleSeenAt string `json:"lastScrobbleSeenAt,omitempty"` 1269 + } 1270 + 1271 + type NextParams struct { 1272 + PlayerID string `json:"playerId,omitempty"` 1273 + } 1274 + 1275 + type PauseParams struct { 1276 + PlayerID string `json:"playerId,omitempty"` 1277 + } 1278 + 1279 + type PlayDirectoryParams struct { 1280 + PlayerID string `json:"playerId,omitempty"` 1281 + DirectoryID string `json:"directoryId,omitempty"` 1282 + Shuffle bool `json:"shuffle,omitempty"` 1283 + Recurse bool `json:"recurse,omitempty"` 1284 + Position int `json:"position,omitempty"` 1285 + } 1286 + 1287 + type PlayerCurrentlyPlayingViewDetailed struct { 1288 + // The title of the currently playing track 1289 + Title string `json:"title,omitempty"` 1290 + } 1291 + 1292 + type PlayerPlaybackQueueViewDetailed struct { 1293 + Tracks []SongViewBasic `json:"tracks,omitempty"` 1294 + } 1295 + 1296 + type PlayFileParams struct { 1297 + PlayerID string `json:"playerId,omitempty"` 1298 + FileID string `json:"fileId,omitempty"` 1299 + } 1300 + 1301 + type PlaylistItemRecord struct { 1302 + Subject *StrongRef `json:"subject,omitempty"` 1303 + // The date the playlist was created. 1304 + CreatedAt string `json:"createdAt,omitempty"` 1305 + Track *SongViewBasic `json:"track,omitempty"` 1306 + // The order of the item in the playlist. 1307 + Order int `json:"order,omitempty"` 1308 + } 1309 + 1310 + type PlaylistRecord struct { 1311 + // The name of the playlist. 1312 + Name string `json:"name,omitempty"` 1313 + // The playlist description. 1314 + Description string `json:"description,omitempty"` 1315 + // The picture of the playlist. 1316 + Picture BlobRef `json:"picture,omitempty"` 1317 + // The URL of the picture of the artist. 1318 + PictureURL string `json:"pictureUrl,omitempty"` 1319 + // The date the playlist was created. 1320 + CreatedAt string `json:"createdAt,omitempty"` 1321 + // The Spotify link of the playlist. 1322 + SpotifyLink string `json:"spotifyLink,omitempty"` 1323 + // The Tidal link of the playlist. 1324 + TidalLink string `json:"tidalLink,omitempty"` 1325 + // The YouTube link of the playlist. 1326 + YoutubeLink string `json:"youtubeLink,omitempty"` 1327 + // The Apple Music link of the playlist. 1328 + AppleMusicLink string `json:"appleMusicLink,omitempty"` 1329 + } 1330 + 1331 + // PlaylistViewBasic Basic view of a playlist, including its metadata 1332 + type PlaylistViewBasic struct { 1333 + // The unique identifier of the playlist. 1334 + ID string `json:"id,omitempty"` 1335 + // The title of the playlist. 1336 + Title string `json:"title,omitempty"` 1337 + // The URI of the playlist. 1338 + URI string `json:"uri,omitempty"` 1339 + // The DID of the curator of the playlist. 1340 + CuratorDID string `json:"curatorDid,omitempty"` 1341 + // The handle of the curator of the playlist. 1342 + CuratorHandle string `json:"curatorHandle,omitempty"` 1343 + // The name of the curator of the playlist. 1344 + CuratorName string `json:"curatorName,omitempty"` 1345 + // The URL of the avatar image of the curator. 1346 + CuratorAvatarURL string `json:"curatorAvatarUrl,omitempty"` 1347 + // A description of the playlist. 1348 + Description string `json:"description,omitempty"` 1349 + // The URL of the cover image for the playlist. 1350 + CoverImageURL string `json:"coverImageUrl,omitempty"` 1351 + // The date and time when the playlist was created. 1352 + CreatedAt string `json:"createdAt,omitempty"` 1353 + // The number of tracks in the playlist. 1354 + TrackCount int `json:"trackCount,omitempty"` 1355 + } 1356 + 1357 + // PlaylistViewDetailed Detailed view of a playlist, including its tracks and metadata 1358 + type PlaylistViewDetailed struct { 1359 + // The unique identifier of the playlist. 1360 + ID string `json:"id,omitempty"` 1361 + // The title of the playlist. 1362 + Title string `json:"title,omitempty"` 1363 + // The URI of the playlist. 1364 + URI string `json:"uri,omitempty"` 1365 + // The DID of the curator of the playlist. 1366 + CuratorDID string `json:"curatorDid,omitempty"` 1367 + // The handle of the curator of the playlist. 1368 + CuratorHandle string `json:"curatorHandle,omitempty"` 1369 + // The name of the curator of the playlist. 1370 + CuratorName string `json:"curatorName,omitempty"` 1371 + // The URL of the avatar image of the curator. 1372 + CuratorAvatarURL string `json:"curatorAvatarUrl,omitempty"` 1373 + // A description of the playlist. 1374 + Description string `json:"description,omitempty"` 1375 + // The URL of the cover image for the playlist. 1376 + CoverImageURL string `json:"coverImageUrl,omitempty"` 1377 + // The date and time when the playlist was created. 1378 + CreatedAt string `json:"createdAt,omitempty"` 1379 + // A list of tracks in the playlist. 1380 + Tracks []SongViewBasic `json:"tracks,omitempty"` 1381 + } 1382 + 1383 + type PlayParams struct { 1384 + PlayerID string `json:"playerId,omitempty"` 1385 + } 1386 + 1387 + type PreviousParams struct { 1388 + PlayerID string `json:"playerId,omitempty"` 1389 + } 1390 + 1391 + type ProfileRecord struct { 1392 + DisplayName string `json:"displayName,omitempty"` 1393 + // Free-form profile description text. 1394 + Description string `json:"description,omitempty"` 1395 + // Small image to be displayed next to posts from account. AKA, 'profile picture' 1396 + Avatar BlobRef `json:"avatar,omitempty"` 1397 + // Larger horizontal image to display behind profile view. 1398 + Banner BlobRef `json:"banner,omitempty"` 1399 + // Self-label values, specific to the Bluesky application, on the overall account. 1400 + Labels any `json:"labels,omitempty"` 1401 + JoinedViaStarterPack *StrongRef `json:"joinedViaStarterPack,omitempty"` 1402 + CreatedAt string `json:"createdAt,omitempty"` 1403 + } 1404 + 1405 + type PutMirrorSourceInput struct { 1406 + // One of: lastfm, listenbrainz, tealfm 1407 + Provider string `json:"provider,omitempty"` 1408 + // Enable or disable mirroring for this provider. 1409 + Enabled bool `json:"enabled,omitempty"` 1410 + // External username (Last.fm / ListenBrainz). Required when enabling those providers. Ignored for Teal.fm. 1411 + ExternalUsername string `json:"externalUsername,omitempty"` 1412 + // API key / token to be encrypted at rest. Omit to leave the existing key unchanged. Pass an empty string to clear it. 1413 + APIKey string `json:"apiKey,omitempty"` 1414 + } 1415 + 1416 + type RadioRecord struct { 1417 + // The name of the radio station. 1418 + Name string `json:"name,omitempty"` 1419 + // The URL of the radio station. 1420 + URL string `json:"url,omitempty"` 1421 + // A description of the radio station. 1422 + Description string `json:"description,omitempty"` 1423 + // The genre of the radio station. 1424 + Genre string `json:"genre,omitempty"` 1425 + // The logo of the radio station. 1426 + Logo BlobRef `json:"logo,omitempty"` 1427 + // The website of the radio station. 1428 + Website string `json:"website,omitempty"` 1429 + // The date when the radio station was created. 1430 + CreatedAt string `json:"createdAt,omitempty"` 1431 + } 1432 + 1433 + type RadioViewBasic struct { 1434 + // The unique identifier of the radio. 1435 + ID string `json:"id,omitempty"` 1436 + // The name of the radio. 1437 + Name string `json:"name,omitempty"` 1438 + // A brief description of the radio. 1439 + Description string `json:"description,omitempty"` 1440 + // The date and time when the radio was created. 1441 + CreatedAt string `json:"createdAt,omitempty"` 1442 + } 1443 + 1444 + type RadioViewDetailed struct { 1445 + // The unique identifier of the radio. 1446 + ID string `json:"id,omitempty"` 1447 + // The name of the radio. 1448 + Name string `json:"name,omitempty"` 1449 + // A brief description of the radio. 1450 + Description string `json:"description,omitempty"` 1451 + // The website of the radio. 1452 + Website string `json:"website,omitempty"` 1453 + // The streaming URL of the radio. 1454 + URL string `json:"url,omitempty"` 1455 + // The genre of the radio. 1456 + Genre string `json:"genre,omitempty"` 1457 + // The logo of the radio station. 1458 + Logo string `json:"logo,omitempty"` 1459 + // The date and time when the radio was created. 1460 + CreatedAt string `json:"createdAt,omitempty"` 1461 + } 1462 + 1463 + type RemoveApikeyParams struct { 1464 + // The ID of the API key to remove. 1465 + ID string `json:"id,omitempty"` 1466 + } 1467 + 1468 + type RemovePlaylistParams struct { 1469 + // The URI of the playlist to remove 1470 + URI string `json:"uri,omitempty"` 1471 + } 1472 + 1473 + type RemoveShoutParams struct { 1474 + // The ID of the shout to be removed 1475 + ID string `json:"id,omitempty"` 1476 + } 1477 + 1478 + type RemoveTrackParams struct { 1479 + // The URI of the playlist to remove the track from 1480 + URI string `json:"uri,omitempty"` 1481 + // The position of the track to remove in the playlist 1482 + Position int `json:"position,omitempty"` 1483 + } 1484 + 1485 + type ReplyShoutInput struct { 1486 + // The unique identifier of the shout to reply to 1487 + ShoutID string `json:"shoutId,omitempty"` 1488 + // The content of the reply 1489 + Message string `json:"message,omitempty"` 1490 + } 1491 + 1492 + type ReportShoutInput struct { 1493 + // The unique identifier of the shout to report 1494 + ShoutID string `json:"shoutId,omitempty"` 1495 + // The reason for reporting the shout 1496 + Reason string `json:"reason,omitempty"` 1497 + } 1498 + 1499 + type ScrobbleFirstScrobbleView struct { 1500 + // The handle of the user who first scrobbled this song. 1501 + Handle string `json:"handle,omitempty"` 1502 + // The avatar URL of the user who first scrobbled this song. 1503 + Avatar string `json:"avatar,omitempty"` 1504 + // The timestamp of the first scrobble. 1505 + Timestamp string `json:"timestamp,omitempty"` 1506 + } 1507 + 1508 + type ScrobbleRecord struct { 1509 + // The title of the song. 1510 + Title string `json:"title,omitempty"` 1511 + // The artist of the song. 1512 + Artist string `json:"artist,omitempty"` 1513 + // The artists of the song with MusicBrainz IDs. 1514 + Artists []ArtistMbid `json:"artists,omitempty"` 1515 + // The album artist of the song. 1516 + AlbumArtist string `json:"albumArtist,omitempty"` 1517 + // The album of the song. 1518 + Album string `json:"album,omitempty"` 1519 + // The duration of the song in milliseconds. 1520 + Duration int `json:"duration,omitempty"` 1521 + // The track number of the song in the album. 1522 + TrackNumber int `json:"trackNumber,omitempty"` 1523 + // The disc number of the song in the album. 1524 + DiscNumber int `json:"discNumber,omitempty"` 1525 + // The release date of the song. 1526 + ReleaseDate string `json:"releaseDate,omitempty"` 1527 + // The year the song was released. 1528 + Year int `json:"year,omitempty"` 1529 + // The genre of the song. 1530 + Genre string `json:"genre,omitempty"` 1531 + // The tags of the song. 1532 + Tags []string `json:"tags,omitempty"` 1533 + // The composer of the song. 1534 + Composer string `json:"composer,omitempty"` 1535 + // The lyrics of the song. 1536 + Lyrics string `json:"lyrics,omitempty"` 1537 + // The copyright message of the song. 1538 + CopyrightMessage string `json:"copyrightMessage,omitempty"` 1539 + // Informations about the song 1540 + Wiki string `json:"wiki,omitempty"` 1541 + // The album art of the song. 1542 + AlbumArt BlobRef `json:"albumArt,omitempty"` 1543 + // The URL of the album art of the song. 1544 + AlbumArtURL string `json:"albumArtUrl,omitempty"` 1545 + // The YouTube link of the song. 1546 + YoutubeLink string `json:"youtubeLink,omitempty"` 1547 + // The Spotify link of the song. 1548 + SpotifyLink string `json:"spotifyLink,omitempty"` 1549 + // The Tidal link of the song. 1550 + TidalLink string `json:"tidalLink,omitempty"` 1551 + // The Apple Music link of the song. 1552 + AppleMusicLink string `json:"appleMusicLink,omitempty"` 1553 + // The date when the song was created. 1554 + CreatedAt string `json:"createdAt,omitempty"` 1555 + // The MusicBrainz ID of the song. 1556 + MBID string `json:"mbid,omitempty"` 1557 + // The label of the song. 1558 + Label string `json:"label,omitempty"` 1559 + // The International Standard Recording Code (ISRC) of the song. 1560 + ISRC string `json:"isrc,omitempty"` 1561 + } 1562 + 1563 + type ScrobbleViewBasic struct { 1564 + // The unique identifier of the scrobble. 1565 + ID string `json:"id,omitempty"` 1566 + // The handle of the user who created the scrobble. 1567 + User string `json:"user,omitempty"` 1568 + // The display name of the user who created the scrobble. 1569 + UserDisplayName string `json:"userDisplayName,omitempty"` 1570 + // The avatar URL of the user who created the scrobble. 1571 + UserAvatar string `json:"userAvatar,omitempty"` 1572 + // The title of the scrobble. 1573 + Title string `json:"title,omitempty"` 1574 + // The artist of the song. 1575 + Artist string `json:"artist,omitempty"` 1576 + // The URI of the artist. 1577 + ArtistURI string `json:"artistUri,omitempty"` 1578 + // The album of the song. 1579 + Album string `json:"album,omitempty"` 1580 + // The URI of the album. 1581 + AlbumURI string `json:"albumUri,omitempty"` 1582 + // The album art URL of the song. 1583 + Cover string `json:"cover,omitempty"` 1584 + // The timestamp when the scrobble was created. 1585 + Date string `json:"date,omitempty"` 1586 + // The URI of the scrobble. 1587 + URI string `json:"uri,omitempty"` 1588 + // The SHA256 hash of the scrobble data. 1589 + SHA256 string `json:"sha256,omitempty"` 1590 + Liked bool `json:"liked,omitempty"` 1591 + LikesCount int `json:"likesCount,omitempty"` 1592 + } 1593 + 1594 + type ScrobbleViewDetailed struct { 1595 + // The unique identifier of the scrobble. 1596 + ID string `json:"id,omitempty"` 1597 + // The handle of the user who created the scrobble. 1598 + User string `json:"user,omitempty"` 1599 + // The title of the scrobble. 1600 + Title string `json:"title,omitempty"` 1601 + // The artist of the song. 1602 + Artist string `json:"artist,omitempty"` 1603 + // The URI of the artist. 1604 + ArtistURI string `json:"artistUri,omitempty"` 1605 + // The album of the song. 1606 + Album string `json:"album,omitempty"` 1607 + // The URI of the album. 1608 + AlbumURI string `json:"albumUri,omitempty"` 1609 + // The album art URL of the song. 1610 + Cover string `json:"cover,omitempty"` 1611 + // The timestamp when the scrobble was created. 1612 + Date string `json:"date,omitempty"` 1613 + // The URI of the scrobble. 1614 + URI string `json:"uri,omitempty"` 1615 + // The SHA256 hash of the scrobble data. 1616 + SHA256 string `json:"sha256,omitempty"` 1617 + Liked bool `json:"liked,omitempty"` 1618 + LikesCount int `json:"likesCount,omitempty"` 1619 + // The number of listeners 1620 + Listeners int `json:"listeners,omitempty"` 1621 + // The number of scrobbles for this song 1622 + Scrobbles int `json:"scrobbles,omitempty"` 1623 + Artists []ArtistViewBasic `json:"artists,omitempty"` 1624 + // The first scrobble of this song on Rocksky. 1625 + FirstScrobble *ScrobbleFirstScrobbleView `json:"firstScrobble,omitempty"` 1626 + } 1627 + 1628 + type SearchParams struct { 1629 + // The search query string 1630 + Query string `json:"query,omitempty"` 1631 + } 1632 + 1633 + type SeekParams struct { 1634 + PlayerID string `json:"playerId,omitempty"` 1635 + // The position in seconds to seek to 1636 + Position int `json:"position,omitempty"` 1637 + } 1638 + 1639 + type ShoutAuthor struct { 1640 + // The unique identifier of the author. 1641 + ID string `json:"id,omitempty"` 1642 + // The decentralized identifier (DID) of the author. 1643 + DID string `json:"did,omitempty"` 1644 + // The handle of the author. 1645 + Handle string `json:"handle,omitempty"` 1646 + // The display name of the author. 1647 + DisplayName string `json:"displayName,omitempty"` 1648 + // The URL of the author's avatar image. 1649 + Avatar string `json:"avatar,omitempty"` 1650 + } 1651 + 1652 + type ShoutRecord struct { 1653 + // The message of the shout. 1654 + Message string `json:"message,omitempty"` 1655 + // The date when the shout was created. 1656 + CreatedAt string `json:"createdAt,omitempty"` 1657 + Parent *StrongRef `json:"parent,omitempty"` 1658 + Subject *StrongRef `json:"subject,omitempty"` 1659 + } 1660 + 1661 + type ShoutView struct { 1662 + // The unique identifier of the shout. 1663 + ID string `json:"id,omitempty"` 1664 + // The content of the shout. 1665 + Message string `json:"message,omitempty"` 1666 + // The ID of the parent shout if this is a reply, otherwise null. 1667 + Parent string `json:"parent,omitempty"` 1668 + // The date and time when the shout was created. 1669 + CreatedAt string `json:"createdAt,omitempty"` 1670 + // The author of the shout. 1671 + Author *ShoutAuthor `json:"author,omitempty"` 1672 + } 1673 + 1674 + type SongFirstScrobbleView struct { 1675 + // The handle of the user who first scrobbled this song. 1676 + Handle string `json:"handle,omitempty"` 1677 + // The avatar URL of the user who first scrobbled this song. 1678 + Avatar string `json:"avatar,omitempty"` 1679 + // The timestamp of the first scrobble. 1680 + Timestamp string `json:"timestamp,omitempty"` 1681 + } 1682 + 1683 + type SongRecentListenerView struct { 1684 + // The unique identifier of the listener. 1685 + ID string `json:"id,omitempty"` 1686 + // The DID of the listener. 1687 + DID string `json:"did,omitempty"` 1688 + // The handle of the listener. 1689 + Handle string `json:"handle,omitempty"` 1690 + // The display name of the listener. 1691 + DisplayName string `json:"displayName,omitempty"` 1692 + // The URL of the listener's avatar image. 1693 + Avatar string `json:"avatar,omitempty"` 1694 + // The timestamp of the listener's most recent scrobble of this song. 1695 + Timestamp string `json:"timestamp,omitempty"` 1696 + // The URI of the listener's most recent scrobble of this song. 1697 + ScrobbleURI string `json:"scrobbleUri,omitempty"` 1698 + } 1699 + 1700 + type SongRecord struct { 1701 + // The title of the song. 1702 + Title string `json:"title,omitempty"` 1703 + // The artist of the song. 1704 + Artist string `json:"artist,omitempty"` 1705 + // The artists of the song with MusicBrainz IDs. 1706 + Artists []ArtistMbid `json:"artists,omitempty"` 1707 + // The album artist of the song. 1708 + AlbumArtist string `json:"albumArtist,omitempty"` 1709 + // The album of the song. 1710 + Album string `json:"album,omitempty"` 1711 + // The duration of the song in milliseconds. 1712 + Duration int `json:"duration,omitempty"` 1713 + // The track number of the song in the album. 1714 + TrackNumber int `json:"trackNumber,omitempty"` 1715 + // The disc number of the song in the album. 1716 + DiscNumber int `json:"discNumber,omitempty"` 1717 + // The release date of the song. 1718 + ReleaseDate string `json:"releaseDate,omitempty"` 1719 + // The year the song was released. 1720 + Year int `json:"year,omitempty"` 1721 + // The genre of the song. 1722 + Genre string `json:"genre,omitempty"` 1723 + // The tags of the song. 1724 + Tags []string `json:"tags,omitempty"` 1725 + // The composer of the song. 1726 + Composer string `json:"composer,omitempty"` 1727 + // The lyrics of the song. 1728 + Lyrics string `json:"lyrics,omitempty"` 1729 + // The copyright message of the song. 1730 + CopyrightMessage string `json:"copyrightMessage,omitempty"` 1731 + // Informations about the song 1732 + Wiki string `json:"wiki,omitempty"` 1733 + // The album art of the song. 1734 + AlbumArt BlobRef `json:"albumArt,omitempty"` 1735 + // The URL of the album art of the song. 1736 + AlbumArtURL string `json:"albumArtUrl,omitempty"` 1737 + // The YouTube link of the song. 1738 + YoutubeLink string `json:"youtubeLink,omitempty"` 1739 + // The Spotify link of the song. 1740 + SpotifyLink string `json:"spotifyLink,omitempty"` 1741 + // The Tidal link of the song. 1742 + TidalLink string `json:"tidalLink,omitempty"` 1743 + // The Apple Music link of the song. 1744 + AppleMusicLink string `json:"appleMusicLink,omitempty"` 1745 + // The date when the song was created. 1746 + CreatedAt string `json:"createdAt,omitempty"` 1747 + // The MusicBrainz ID of the song. 1748 + MBID string `json:"mbid,omitempty"` 1749 + // The label of the song. 1750 + Label string `json:"label,omitempty"` 1751 + // The International Standard Recording Code (ISRC) of the song. 1752 + ISRC string `json:"isrc,omitempty"` 1753 + } 1754 + 1755 + type SongViewBasic struct { 1756 + // The unique identifier of the song. 1757 + ID string `json:"id,omitempty"` 1758 + // The title of the song. 1759 + Title string `json:"title,omitempty"` 1760 + // The artist of the song. 1761 + Artist string `json:"artist,omitempty"` 1762 + // The artist of the album the song belongs to. 1763 + AlbumArtist string `json:"albumArtist,omitempty"` 1764 + // The URL of the album art image. 1765 + AlbumArt string `json:"albumArt,omitempty"` 1766 + // The URI of the song. 1767 + URI string `json:"uri,omitempty"` 1768 + // The album of the song. 1769 + Album string `json:"album,omitempty"` 1770 + // The duration of the song in milliseconds. 1771 + Duration int `json:"duration,omitempty"` 1772 + // The track number of the song in the album. 1773 + TrackNumber int `json:"trackNumber,omitempty"` 1774 + // The disc number of the song in the album. 1775 + DiscNumber int `json:"discNumber,omitempty"` 1776 + // The number of times the song has been played. 1777 + PlayCount int `json:"playCount,omitempty"` 1778 + // The number of unique listeners who have played the song. 1779 + UniqueListeners int `json:"uniqueListeners,omitempty"` 1780 + // The URI of the album the song belongs to. 1781 + AlbumURI string `json:"albumUri,omitempty"` 1782 + // The URI of the artist of the song. 1783 + ArtistURI string `json:"artistUri,omitempty"` 1784 + // The SHA256 hash of the song. 1785 + SHA256 string `json:"sha256,omitempty"` 1786 + // The MusicBrainz ID of the song. 1787 + MBID string `json:"mbid,omitempty"` 1788 + // The International Standard Recording Code (ISRC) of the song. 1789 + ISRC string `json:"isrc,omitempty"` 1790 + Tags []string `json:"tags,omitempty"` 1791 + // The timestamp when the song was created. 1792 + CreatedAt string `json:"createdAt,omitempty"` 1793 + } 1794 + 1795 + type SongViewDetailed struct { 1796 + // The unique identifier of the song. 1797 + ID string `json:"id,omitempty"` 1798 + // The title of the song. 1799 + Title string `json:"title,omitempty"` 1800 + // The artist of the song. 1801 + Artist string `json:"artist,omitempty"` 1802 + // The artist of the album the song belongs to. 1803 + AlbumArtist string `json:"albumArtist,omitempty"` 1804 + // The URL of the album art image. 1805 + AlbumArt string `json:"albumArt,omitempty"` 1806 + // The URI of the song. 1807 + URI string `json:"uri,omitempty"` 1808 + // The album of the song. 1809 + Album string `json:"album,omitempty"` 1810 + // The duration of the song in milliseconds. 1811 + Duration int `json:"duration,omitempty"` 1812 + // The track number of the song in the album. 1813 + TrackNumber int `json:"trackNumber,omitempty"` 1814 + // The disc number of the song in the album. 1815 + DiscNumber int `json:"discNumber,omitempty"` 1816 + // The number of times the song has been played. 1817 + PlayCount int `json:"playCount,omitempty"` 1818 + // The number of unique listeners who have played the song. 1819 + UniqueListeners int `json:"uniqueListeners,omitempty"` 1820 + // The URI of the album the song belongs to. 1821 + AlbumURI string `json:"albumUri,omitempty"` 1822 + // The URI of the artist of the song. 1823 + ArtistURI string `json:"artistUri,omitempty"` 1824 + // The SHA256 hash of the song. 1825 + SHA256 string `json:"sha256,omitempty"` 1826 + // The MusicBrainz ID of the song. 1827 + MBID string `json:"mbid,omitempty"` 1828 + // The International Standard Recording Code (ISRC) of the song. 1829 + ISRC string `json:"isrc,omitempty"` 1830 + Tags []string `json:"tags,omitempty"` 1831 + // The timestamp when the song was created. 1832 + CreatedAt string `json:"createdAt,omitempty"` 1833 + Artists []ArtistViewBasic `json:"artists,omitempty"` 1834 + // The first scrobble of this song on Rocksky. 1835 + FirstScrobble *SongFirstScrobbleView `json:"firstScrobble,omitempty"` 1836 + } 1837 + 1838 + type SpotifyTrackView struct { 1839 + // The unique identifier of the Spotify track. 1840 + ID string `json:"id,omitempty"` 1841 + // The name of the track. 1842 + Name string `json:"name,omitempty"` 1843 + // The name of the artist. 1844 + Artist string `json:"artist,omitempty"` 1845 + // The name of the album. 1846 + Album string `json:"album,omitempty"` 1847 + // The duration of the track in milliseconds. 1848 + Duration int `json:"duration,omitempty"` 1849 + // A URL to a preview of the track. 1850 + PreviewURL string `json:"previewUrl,omitempty"` 1851 + } 1852 + 1853 + type StartPlaylistParams struct { 1854 + // The URI of the playlist to start 1855 + URI string `json:"uri,omitempty"` 1856 + // Whether to shuffle the playlist when starting it 1857 + Shuffle bool `json:"shuffle,omitempty"` 1858 + // The position in the playlist to start from, if not specified, starts from the beginning 1859 + Position int `json:"position,omitempty"` 1860 + } 1861 + 1862 + type StatsView struct { 1863 + // The total number of scrobbles. 1864 + Scrobbles int `json:"scrobbles,omitempty"` 1865 + // The total number of unique artists scrobbled. 1866 + Artists int `json:"artists,omitempty"` 1867 + // The total number of tracks marked as loved. 1868 + LovedTracks int `json:"lovedTracks,omitempty"` 1869 + // The total number of unique albums scrobbled. 1870 + Albums int `json:"albums,omitempty"` 1871 + // The total number of unique tracks scrobbled. 1872 + Tracks int `json:"tracks,omitempty"` 1873 + } 1874 + 1875 + type StatsWrappedAlbum struct { 1876 + // The unique identifier of the album. 1877 + ID string `json:"id,omitempty"` 1878 + // The title of the album. 1879 + Title string `json:"title,omitempty"` 1880 + // The artist of the album. 1881 + Artist string `json:"artist,omitempty"` 1882 + // The album art URL. 1883 + AlbumArt string `json:"albumArt,omitempty"` 1884 + // The AT-URI of the album. 1885 + URI string `json:"uri,omitempty"` 1886 + // Number of plays in the wrapped period. 1887 + PlayCount int `json:"playCount,omitempty"` 1888 + } 1889 + 1890 + type StatsWrappedArtist struct { 1891 + // The unique identifier of the artist. 1892 + ID string `json:"id,omitempty"` 1893 + // The name of the artist. 1894 + Name string `json:"name,omitempty"` 1895 + // The picture URL of the artist. 1896 + Picture string `json:"picture,omitempty"` 1897 + // The AT-URI of the artist. 1898 + URI string `json:"uri,omitempty"` 1899 + // Number of plays in the wrapped period. 1900 + PlayCount int `json:"playCount,omitempty"` 1901 + } 1902 + 1903 + type StatsWrappedDayCount struct { 1904 + // The date (YYYY-MM-DD). 1905 + Date string `json:"date,omitempty"` 1906 + // Number of scrobbles on this day. 1907 + Count int `json:"count,omitempty"` 1908 + } 1909 + 1910 + type StatsWrappedGenreCount struct { 1911 + // The genre name. 1912 + Genre string `json:"genre,omitempty"` 1913 + // Number of scrobbles for this genre. 1914 + Count int `json:"count,omitempty"` 1915 + } 1916 + 1917 + type StatsWrappedMilestone struct { 1918 + // The title of the track. 1919 + TrackTitle string `json:"trackTitle,omitempty"` 1920 + // The name of the artist. 1921 + ArtistName string `json:"artistName,omitempty"` 1922 + // The timestamp of the scrobble. 1923 + Timestamp string `json:"timestamp,omitempty"` 1924 + // AT-URI of the track record, used to build a clickable link to the song page. 1925 + TrackURI string `json:"trackUri,omitempty"` 1926 + } 1927 + 1928 + type StatsWrappedMonthCount struct { 1929 + // Month number (1-12). 1930 + Month int `json:"month,omitempty"` 1931 + // Number of scrobbles in this month. 1932 + Count int `json:"count,omitempty"` 1933 + } 1934 + 1935 + type StatsWrappedTrack struct { 1936 + // The unique identifier of the track. 1937 + ID string `json:"id,omitempty"` 1938 + // The title of the track. 1939 + Title string `json:"title,omitempty"` 1940 + // The artist of the track. 1941 + Artist string `json:"artist,omitempty"` 1942 + // The album art URL. 1943 + AlbumArt string `json:"albumArt,omitempty"` 1944 + // The AT-URI of the track. 1945 + URI string `json:"uri,omitempty"` 1946 + // The AT-URI of the artist. 1947 + ArtistURI string `json:"artistUri,omitempty"` 1948 + // The AT-URI of the album. 1949 + AlbumURI string `json:"albumUri,omitempty"` 1950 + // Number of plays in the wrapped period. 1951 + PlayCount int `json:"playCount,omitempty"` 1952 + } 1953 + 1954 + type StatsWrappedView struct { 1955 + // The year of the wrapped stats. 1956 + Year int `json:"year,omitempty"` 1957 + // Total scrobbles in the year. 1958 + TotalScrobbles int `json:"totalScrobbles,omitempty"` 1959 + // Total listening time in minutes. 1960 + TotalListeningTimeMinutes int `json:"totalListeningTimeMinutes,omitempty"` 1961 + // Top 5 artists by play count. 1962 + TopArtists []StatsWrappedArtist `json:"topArtists,omitempty"` 1963 + // Top 5 tracks by play count. 1964 + TopTracks []StatsWrappedTrack `json:"topTracks,omitempty"` 1965 + // Top 5 albums by play count. 1966 + TopAlbums []StatsWrappedAlbum `json:"topAlbums,omitempty"` 1967 + // Top genres by play count. 1968 + TopGenres []StatsWrappedGenreCount `json:"topGenres,omitempty"` 1969 + // Scrobble counts per month. 1970 + ScrobblesPerMonth []StatsWrappedMonthCount `json:"scrobblesPerMonth,omitempty"` 1971 + // The most active day of the year. 1972 + MostActiveDay *StatsWrappedDayCount `json:"mostActiveDay,omitempty"` 1973 + // The most active hour of the day (0-23). 1974 + MostActiveHour int `json:"mostActiveHour,omitempty"` 1975 + // Number of artists heard for the first time this year. 1976 + NewArtistsCount int `json:"newArtistsCount,omitempty"` 1977 + // Longest consecutive days streak. 1978 + LongestStreak int `json:"longestStreak,omitempty"` 1979 + // The first scrobble of the year. 1980 + FirstScrobble *StatsWrappedMilestone `json:"firstScrobble,omitempty"` 1981 + // The last scrobble of the year. 1982 + LastScrobble *StatsWrappedMilestone `json:"lastScrobble,omitempty"` 1983 + } 1984 + 1985 + type StatusRecord struct { 1986 + // The track currently being played. 1987 + Track *ActorTrackView `json:"track,omitempty"` 1988 + // When the track started playing. 1989 + StartedAt string `json:"startedAt,omitempty"` 1990 + // When the status expires. Defaults to startedAt plus track duration plus idle time. 1991 + ExpiresAt string `json:"expiresAt,omitempty"` 1992 + } 1993 + 1994 + type StrongRef struct { 1995 + URI string `json:"uri,omitempty"` 1996 + CID string `json:"cid,omitempty"` 1997 + } 1998 + 1999 + type UnfollowAccountOutput struct { 2000 + Subject *ActorProfileViewBasic `json:"subject,omitempty"` 2001 + Followers []ActorProfileViewBasic `json:"followers,omitempty"` 2002 + // A cursor value to pass to subsequent calls to get the next page of results. 2003 + Cursor string `json:"cursor,omitempty"` 2004 + } 2005 + 2006 + type UnfollowAccountParams struct { 2007 + Account string `json:"account,omitempty"` 2008 + } 2009 + 2010 + type UpdateApikeyInput struct { 2011 + // The ID of the API key to update. 2012 + ID string `json:"id,omitempty"` 2013 + // The new name of the API key. 2014 + Name string `json:"name,omitempty"` 2015 + // A new description for the API key. 2016 + Description string `json:"description,omitempty"` 2017 + }
+37 -312
sdk/go/rocksky/types.go
··· 1 1 package rocksky 2 2 3 - // Types mirror the view definitions in apps/api/lexicons. JSON tags use the 4 - // camelCase keys emitted by the XRPC server; Go fields keep idiomatic naming. 3 + import "github.com/tsirysndr/rocksky/sdk/go/rocksky/gen" 5 4 6 - // ProfileViewBasic is the lightweight profile shape used in lists. 7 - // Lexicon: app.rocksky.actor.defs#profileViewBasic. 8 - type ProfileViewBasic struct { 9 - ID string `json:"id,omitempty"` 10 - DID string `json:"did,omitempty"` 11 - Handle string `json:"handle,omitempty"` 12 - DisplayName string `json:"displayName,omitempty"` 13 - Avatar string `json:"avatar,omitempty"` 14 - CreatedAt string `json:"createdAt,omitempty"` 15 - UpdatedAt string `json:"updatedAt,omitempty"` 16 - } 5 + // View types are sourced from `apps/api/lexicons/**/*.json` via codegen 6 + // in `sdk/go/rocksky/gen`. This file re-exports them under the historical 7 + // SDK names and extends a few with fields the lexicon does not yet declare. 8 + 9 + type ProfileViewBasic = gen.ActorProfileViewBasic 17 10 18 - // ProfileViewDetailed is the full profile returned by Actor.GetProfile. 19 - // Lexicon: app.rocksky.actor.defs#profileViewDetailed. 20 11 type ProfileViewDetailed struct { 21 - ID string `json:"id,omitempty"` 22 - DID string `json:"did,omitempty"` 23 - Handle string `json:"handle,omitempty"` 24 - DisplayName string `json:"displayName,omitempty"` 25 - Avatar string `json:"avatar,omitempty"` 26 - CreatedAt string `json:"createdAt,omitempty"` 27 - UpdatedAt string `json:"updatedAt,omitempty"` 28 - SpotifyConnected bool `json:"spotifyConnected,omitempty"` 12 + gen.ActorProfileViewDetailed 13 + SpotifyConnected bool `json:"spotifyConnected,omitempty"` 29 14 } 30 15 31 - // ArtistViewBasic — lexicon: app.rocksky.artist.defs#artistViewBasic. 32 - type ArtistViewBasic struct { 33 - ID string `json:"id,omitempty"` 34 - URI string `json:"uri,omitempty"` 35 - Name string `json:"name,omitempty"` 36 - Picture string `json:"picture,omitempty"` 37 - SHA256 string `json:"sha256,omitempty"` 38 - PlayCount int `json:"playCount,omitempty"` 39 - UniqueListeners int `json:"uniqueListeners,omitempty"` 40 - Tags []string `json:"tags,omitempty"` 41 - } 16 + type ArtistViewBasic = gen.ArtistViewBasic 17 + type ArtistViewDetailed = gen.ArtistViewDetailed 42 18 43 - // ArtistViewDetailed — lexicon: app.rocksky.artist.defs#artistViewDetailed. 44 - type ArtistViewDetailed = ArtistViewBasic 19 + type AlbumViewBasic = gen.AlbumViewBasic 20 + type AlbumViewDetailed = gen.AlbumViewDetailed 45 21 46 - // AlbumViewBasic — lexicon: app.rocksky.album.defs#albumViewBasic. 47 - type AlbumViewBasic struct { 48 - ID string `json:"id,omitempty"` 49 - URI string `json:"uri,omitempty"` 50 - Title string `json:"title,omitempty"` 51 - Artist string `json:"artist,omitempty"` 52 - ArtistURI string `json:"artistUri,omitempty"` 53 - Year int `json:"year,omitempty"` 54 - AlbumArt string `json:"albumArt,omitempty"` 55 - ReleaseDate string `json:"releaseDate,omitempty"` 56 - SHA256 string `json:"sha256,omitempty"` 57 - PlayCount int `json:"playCount,omitempty"` 58 - UniqueListeners int `json:"uniqueListeners,omitempty"` 59 - } 22 + type SongViewBasic = gen.SongViewBasic 23 + type SongViewDetailed = gen.SongViewDetailed 60 24 61 - // AlbumViewDetailed — lexicon: app.rocksky.album.defs#albumViewDetailed. 62 - type AlbumViewDetailed struct { 63 - AlbumViewBasic 64 - Tags []string `json:"tags,omitempty"` 65 - Tracks []SongViewBasic `json:"tracks,omitempty"` 66 - } 25 + type FirstScrobbleView = gen.SongFirstScrobbleView 67 26 68 - // SongViewBasic — lexicon: app.rocksky.song.defs#songViewBasic. 69 - type SongViewBasic struct { 70 - ID string `json:"id,omitempty"` 71 - Title string `json:"title,omitempty"` 72 - Artist string `json:"artist,omitempty"` 73 - AlbumArtist string `json:"albumArtist,omitempty"` 74 - AlbumArt string `json:"albumArt,omitempty"` 75 - URI string `json:"uri,omitempty"` 76 - Album string `json:"album,omitempty"` 77 - Duration int `json:"duration,omitempty"` 78 - TrackNumber int `json:"trackNumber,omitempty"` 79 - DiscNumber int `json:"discNumber,omitempty"` 80 - PlayCount int `json:"playCount,omitempty"` 81 - UniqueListeners int `json:"uniqueListeners,omitempty"` 82 - AlbumURI string `json:"albumUri,omitempty"` 83 - ArtistURI string `json:"artistUri,omitempty"` 84 - SHA256 string `json:"sha256,omitempty"` 85 - MBID string `json:"mbid,omitempty"` 86 - ISRC string `json:"isrc,omitempty"` 87 - Tags []string `json:"tags,omitempty"` 88 - CreatedAt string `json:"createdAt,omitempty"` 89 - } 27 + type ScrobbleViewBasic = gen.ScrobbleViewBasic 28 + type ScrobbleViewDetailed = gen.ScrobbleViewDetailed 90 29 91 - // SongViewDetailed — lexicon: app.rocksky.song.defs#songViewDetailed. 92 - type SongViewDetailed struct { 93 - SongViewBasic 94 - Artists []ArtistViewBasic `json:"artists,omitempty"` 95 - FirstScrobble *FirstScrobbleView `json:"firstScrobble,omitempty"` 96 - } 30 + type RecentListenerView = gen.SongRecentListenerView 31 + type ListenerViewBasic = gen.ArtistListenerViewBasic 97 32 98 - // FirstScrobbleView — used by song and scrobble detailed views. 99 - type FirstScrobbleView struct { 100 - Handle string `json:"handle,omitempty"` 101 - Avatar string `json:"avatar,omitempty"` 102 - Timestamp string `json:"timestamp,omitempty"` 103 - } 33 + type ChartPoint = gen.ChartsScrobbleViewBasic 104 34 105 - // ScrobbleViewBasic — lexicon: app.rocksky.scrobble.defs#scrobbleViewBasic. 106 - type ScrobbleViewBasic struct { 107 - ID string `json:"id,omitempty"` 108 - User string `json:"user,omitempty"` 109 - UserDisplayName string `json:"userDisplayName,omitempty"` 110 - UserAvatar string `json:"userAvatar,omitempty"` 111 - Title string `json:"title,omitempty"` 112 - Artist string `json:"artist,omitempty"` 113 - ArtistURI string `json:"artistUri,omitempty"` 114 - Album string `json:"album,omitempty"` 115 - AlbumURI string `json:"albumUri,omitempty"` 116 - Cover string `json:"cover,omitempty"` 117 - Date string `json:"date,omitempty"` 118 - URI string `json:"uri,omitempty"` 119 - SHA256 string `json:"sha256,omitempty"` 120 - Liked bool `json:"liked,omitempty"` 121 - LikesCount int `json:"likesCount,omitempty"` 122 - } 35 + type StatsView = gen.StatsView 123 36 124 - // ScrobbleViewDetailed — lexicon: app.rocksky.scrobble.defs#scrobbleViewDetailed. 125 - type ScrobbleViewDetailed struct { 126 - ScrobbleViewBasic 127 - Listeners int `json:"listeners,omitempty"` 128 - Scrobbles int `json:"scrobbles,omitempty"` 129 - Artists []ArtistViewBasic `json:"artists,omitempty"` 130 - FirstScrobble *FirstScrobbleView `json:"firstScrobble,omitempty"` 131 - } 37 + type WrappedView = gen.StatsWrappedView 38 + type WrappedArtist = gen.StatsWrappedArtist 39 + type WrappedTrack = gen.StatsWrappedTrack 40 + type WrappedAlbum = gen.StatsWrappedAlbum 41 + type WrappedGenre = gen.StatsWrappedGenreCount 42 + type WrappedMonth = gen.StatsWrappedMonthCount 43 + type WrappedDay = gen.StatsWrappedDayCount 44 + type WrappedMilestone = gen.StatsWrappedMilestone 132 45 133 - // RecentListenerView — used by artist/song recent listeners endpoints. 134 - type RecentListenerView struct { 135 - ID string `json:"id,omitempty"` 136 - DID string `json:"did,omitempty"` 137 - Handle string `json:"handle,omitempty"` 138 - DisplayName string `json:"displayName,omitempty"` 139 - Avatar string `json:"avatar,omitempty"` 140 - Timestamp string `json:"timestamp,omitempty"` 141 - ScrobbleURI string `json:"scrobbleUri,omitempty"` 142 - } 46 + type SearchResultsView = gen.FeedSearchResultsView 47 + type StoryView = gen.FeedStoryView 48 + type RecommendationView = gen.FeedRecommendationView 49 + type RecommendedArtistView = gen.FeedRecommendedArtistView 50 + type RecommendedAlbumView = gen.FeedRecommendedAlbumView 51 + type FeedItemView = gen.FeedItemView 143 52 144 - // ListenerViewBasic — used by Artist.GetArtistListeners. 145 - type ListenerViewBasic struct { 146 - ID string `json:"id,omitempty"` 147 - DID string `json:"did,omitempty"` 148 - Handle string `json:"handle,omitempty"` 149 - DisplayName string `json:"displayName,omitempty"` 150 - Avatar string `json:"avatar,omitempty"` 151 - MostListenedSong *SongViewBasic `json:"mostListenedSong,omitempty"` 152 - TotalPlays int `json:"totalPlays,omitempty"` 153 - Rank int `json:"rank,omitempty"` 154 - } 155 - 156 - // ChartPoint — lexicon: app.rocksky.charts.defs#scrobbleViewBasic (one (date, count) bucket). 157 - type ChartPoint struct { 158 - Date string `json:"date,omitempty"` 159 - Count int `json:"count,omitempty"` 160 - } 161 - 162 - // StatsView — lexicon: app.rocksky.stats.defs#statsView. 163 - type StatsView struct { 164 - Scrobbles int `json:"scrobbles,omitempty"` 165 - Artists int `json:"artists,omitempty"` 166 - LovedTracks int `json:"lovedTracks,omitempty"` 167 - Albums int `json:"albums,omitempty"` 168 - Tracks int `json:"tracks,omitempty"` 169 - } 170 - 171 - // WrappedView — lexicon: app.rocksky.stats.defs#wrappedView. 172 - type WrappedView struct { 173 - Year int `json:"year,omitempty"` 174 - TotalScrobbles int `json:"totalScrobbles,omitempty"` 175 - TotalListeningTimeMinutes int `json:"totalListeningTimeMinutes,omitempty"` 176 - TopArtists []WrappedArtist `json:"topArtists,omitempty"` 177 - TopTracks []WrappedTrack `json:"topTracks,omitempty"` 178 - TopAlbums []WrappedAlbum `json:"topAlbums,omitempty"` 179 - TopGenres []WrappedGenre `json:"topGenres,omitempty"` 180 - ScrobblesPerMonth []WrappedMonth `json:"scrobblesPerMonth,omitempty"` 181 - MostActiveDay *WrappedDay `json:"mostActiveDay,omitempty"` 182 - MostActiveHour int `json:"mostActiveHour,omitempty"` 183 - NewArtistsCount int `json:"newArtistsCount,omitempty"` 184 - LongestStreak int `json:"longestStreak,omitempty"` 185 - FirstScrobble *WrappedMilestone `json:"firstScrobble,omitempty"` 186 - LastScrobble *WrappedMilestone `json:"lastScrobble,omitempty"` 187 - } 188 - 189 - type WrappedArtist struct { 190 - ID string `json:"id,omitempty"` 191 - Name string `json:"name,omitempty"` 192 - Picture string `json:"picture,omitempty"` 193 - URI string `json:"uri,omitempty"` 194 - PlayCount int `json:"playCount,omitempty"` 195 - } 196 - 197 - type WrappedTrack struct { 198 - ID string `json:"id,omitempty"` 199 - Title string `json:"title,omitempty"` 200 - Artist string `json:"artist,omitempty"` 201 - AlbumArt string `json:"albumArt,omitempty"` 202 - URI string `json:"uri,omitempty"` 203 - ArtistURI string `json:"artistUri,omitempty"` 204 - AlbumURI string `json:"albumUri,omitempty"` 205 - PlayCount int `json:"playCount,omitempty"` 206 - } 207 - 208 - type WrappedAlbum struct { 209 - ID string `json:"id,omitempty"` 210 - Title string `json:"title,omitempty"` 211 - Artist string `json:"artist,omitempty"` 212 - AlbumArt string `json:"albumArt,omitempty"` 213 - URI string `json:"uri,omitempty"` 214 - PlayCount int `json:"playCount,omitempty"` 215 - } 216 - 217 - type WrappedGenre struct { 218 - Genre string `json:"genre,omitempty"` 219 - Count int `json:"count,omitempty"` 220 - } 221 - 222 - type WrappedMonth struct { 223 - Month int `json:"month,omitempty"` 224 - Count int `json:"count,omitempty"` 225 - } 226 - 227 - type WrappedDay struct { 228 - Date string `json:"date,omitempty"` 229 - Count int `json:"count,omitempty"` 230 - } 231 - 232 - type WrappedMilestone struct { 233 - TrackTitle string `json:"trackTitle,omitempty"` 234 - ArtistName string `json:"artistName,omitempty"` 235 - Timestamp string `json:"timestamp,omitempty"` 236 - TrackURI string `json:"trackUri,omitempty"` 237 - } 238 - 239 - // SearchResultsView — lexicon: app.rocksky.feed.defs#searchResultsView. 240 - // Hits is a heterogeneous list (song / album / artist / playlist / profile); 241 - // each item is left as a raw map so callers can dispatch on its $type or shape. 242 - type SearchResultsView struct { 243 - Hits []map[string]any `json:"hits,omitempty"` 244 - ProcessingTimeMS int `json:"processingTimeMs,omitempty"` 245 - Limit int `json:"limit,omitempty"` 246 - Offset int `json:"offset,omitempty"` 247 - EstimatedTotalHits int `json:"estimatedTotalHits,omitempty"` 248 - } 249 - 250 - // StoryView — lexicon: app.rocksky.feed.defs#storyView. 251 - type StoryView struct { 252 - Album string `json:"album,omitempty"` 253 - AlbumArt string `json:"albumArt,omitempty"` 254 - AlbumArtist string `json:"albumArtist,omitempty"` 255 - AlbumURI string `json:"albumUri,omitempty"` 256 - Artist string `json:"artist,omitempty"` 257 - ArtistURI string `json:"artistUri,omitempty"` 258 - Avatar string `json:"avatar,omitempty"` 259 - CreatedAt string `json:"createdAt,omitempty"` 260 - DID string `json:"did,omitempty"` 261 - Handle string `json:"handle,omitempty"` 262 - ID string `json:"id,omitempty"` 263 - Title string `json:"title,omitempty"` 264 - TrackID string `json:"trackId,omitempty"` 265 - TrackURI string `json:"trackUri,omitempty"` 266 - URI string `json:"uri,omitempty"` 267 - } 268 - 269 - // RecommendationView — lexicon: app.rocksky.feed.defs#recommendationView. 270 - type RecommendationView struct { 271 - Title string `json:"title,omitempty"` 272 - Artist string `json:"artist,omitempty"` 273 - Album string `json:"album,omitempty"` 274 - AlbumArt string `json:"albumArt,omitempty"` 275 - TrackURI string `json:"trackUri,omitempty"` 276 - ArtistURI string `json:"artistUri,omitempty"` 277 - AlbumURI string `json:"albumUri,omitempty"` 278 - Genres []string `json:"genres,omitempty"` 279 - RecommendationScore int `json:"recommendationScore,omitempty"` 280 - Source string `json:"source,omitempty"` 281 - LikesCount int `json:"likesCount,omitempty"` 282 - } 283 - 284 - // RecommendedArtistView — lexicon: app.rocksky.feed.defs#recommendedArtistView. 285 - type RecommendedArtistView struct { 286 - ID string `json:"id,omitempty"` 287 - URI string `json:"uri,omitempty"` 288 - Name string `json:"name,omitempty"` 289 - Picture string `json:"picture,omitempty"` 290 - Genres []string `json:"genres,omitempty"` 291 - RecommendationScore int `json:"recommendationScore,omitempty"` 292 - Source string `json:"source,omitempty"` 293 - } 294 - 295 - // RecommendedAlbumView — lexicon: app.rocksky.feed.defs#recommendedAlbumView. 296 - type RecommendedAlbumView struct { 297 - ID string `json:"id,omitempty"` 298 - URI string `json:"uri,omitempty"` 299 - Title string `json:"title,omitempty"` 300 - Artist string `json:"artist,omitempty"` 301 - ArtistURI string `json:"artistUri,omitempty"` 302 - Year int `json:"year,omitempty"` 303 - AlbumArt string `json:"albumArt,omitempty"` 304 - RecommendationScore int `json:"recommendationScore,omitempty"` 305 - Source string `json:"source,omitempty"` 306 - } 307 - 308 - // FeedItemView wraps a single scrobble in the public feed. 309 - type FeedItemView struct { 310 - Scrobble ScrobbleViewBasic `json:"scrobble,omitempty"` 311 - } 312 - 313 - // ShoutAuthor — lexicon: app.rocksky.shout.defs#author. 314 - type ShoutAuthor struct { 315 - ID string `json:"id,omitempty"` 316 - DID string `json:"did,omitempty"` 317 - Handle string `json:"handle,omitempty"` 318 - DisplayName string `json:"displayName,omitempty"` 319 - Avatar string `json:"avatar,omitempty"` 320 - } 321 - 322 - // ShoutView — lexicon: app.rocksky.shout.defs#shoutView. 323 - type ShoutView struct { 324 - ID string `json:"id,omitempty"` 325 - Message string `json:"message,omitempty"` 326 - Parent string `json:"parent,omitempty"` 327 - CreatedAt string `json:"createdAt,omitempty"` 328 - Author *ShoutAuthor `json:"author,omitempty"` 329 - } 53 + type ShoutAuthor = gen.ShoutAuthor 54 + type ShoutView = gen.ShoutView
+5
sdk/kotlin/README.md
··· 151 151 152 152 See [`examples/src/main/kotlin/app/rocksky/examples/`](examples/src/main/kotlin/app/rocksky/examples/) for source. 153 153 154 + ## Types 155 + 156 + Public model types are derived from the [Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons) and live in `app.rocksky.generated`. The `app.rocksky.Models` typealiases re-export them under their historical names; `Profile`, `ApiKey`, and `FollowList` extend with SDK-specific fields. Regenerate with `bun run lexgen:types` at the repo root. 157 + 158 + 154 159 ## Build & test 155 160 156 161 ```bash
+3 -2
sdk/kotlin/examples/src/main/kotlin/app/rocksky/examples/SearchAndCharts.kt
··· 14 14 RockskyClient().use { client -> 15 15 println("→ Search: $query") 16 16 val results = client.feed.search(query = query) 17 - println(" ${results.estimatedTotalHits ?: results.hits.size} hits (showing first 5):") 18 - results.hits.take(5).forEach { hit -> println(" • $hit") } 17 + val hits = results.hits.orEmpty() 18 + println(" ${results.estimatedTotalHits ?: hits.size} hits (showing first 5):") 19 + hits.take(5).forEach { hit -> println(" • $hit") } 19 20 20 21 println("\n→ Top 10 tracks this week:") 21 22 val tracks = client.charts.topTracks(limit = 10)
+1 -1
sdk/kotlin/rocksky/build.gradle.kts
··· 10 10 } 11 11 12 12 group = "app.rocksky" 13 - version = "0.1.0" 13 + version = "0.2.0" 14 14 15 15 kotlin { 16 16 jvmToolchain(17)
+63 -339
sdk/kotlin/rocksky/src/main/kotlin/app/rocksky/Models.kt
··· 1 1 package app.rocksky 2 2 3 + import app.rocksky.generated.ActorCompatibilityViewBasic 4 + import app.rocksky.generated.ActorNeighbourViewBasic 5 + import app.rocksky.generated.ActorProfileViewBasic 6 + import app.rocksky.generated.AlbumViewBasic 7 + import app.rocksky.generated.AlbumViewDetailed 8 + import app.rocksky.generated.ArtistListenerViewBasic 9 + import app.rocksky.generated.ArtistViewBasic 10 + import app.rocksky.generated.FeedGeneratorView 11 + import app.rocksky.generated.FeedItemView 12 + import app.rocksky.generated.FeedRecommendationView 13 + import app.rocksky.generated.FeedRecommendationsView 14 + import app.rocksky.generated.FeedRecommendedAlbumView 15 + import app.rocksky.generated.FeedRecommendedArtistView 16 + import app.rocksky.generated.FeedSearchResultsView 17 + import app.rocksky.generated.FeedStoryView 18 + import app.rocksky.generated.FeedView 19 + import app.rocksky.generated.MirrorSourceView 20 + import app.rocksky.generated.PlaylistViewBasic 21 + import app.rocksky.generated.PlaylistViewDetailed 22 + import app.rocksky.generated.ScrobbleViewDetailed 23 + import app.rocksky.generated.ShoutView 24 + import app.rocksky.generated.SongFirstScrobbleView 25 + import app.rocksky.generated.SongRecentListenerView 26 + import app.rocksky.generated.SongViewBasic 27 + import app.rocksky.generated.SongViewDetailed 3 28 import kotlinx.serialization.SerialName 4 29 import kotlinx.serialization.Serializable 5 30 import kotlinx.serialization.json.JsonElement 6 31 7 32 /** 8 - * Data models for Rocksky API responses. 9 - * 10 - * The API speaks camelCase JSON; each field is mapped explicitly with `@SerialName` so the 11 - * generated parser tolerates extra fields and missing fields. Every field is nullable — 12 - * server responses don't always include every key, and SDK consumers shouldn't crash on it. 33 + * Public response models. Most types alias to the lexicon-generated shapes in 34 + * `app.rocksky.generated`. A handful of types (Profile, ApiKey, FollowList) 35 + * extend the generated shape with SDK-specific or paging fields. 13 36 */ 14 37 15 - @Serializable 16 - public data class ProfileBasic( 17 - public val id: String? = null, 18 - public val did: String? = null, 19 - public val handle: String? = null, 20 - @SerialName("displayName") public val displayName: String? = null, 21 - public val avatar: String? = null, 22 - @SerialName("createdAt") public val createdAt: String? = null, 23 - @SerialName("updatedAt") public val updatedAt: String? = null, 24 - ) 38 + public typealias ProfileBasic = ActorProfileViewBasic 39 + public typealias ArtistBasic = ArtistViewBasic 40 + public typealias Artist = ArtistBasic 41 + public typealias AlbumBasic = AlbumViewBasic 42 + public typealias Album = AlbumViewDetailed 43 + public typealias FirstScrobble = SongFirstScrobbleView 44 + public typealias SongBasic = SongViewBasic 45 + public typealias Song = SongViewDetailed 46 + public typealias RecentListener = SongRecentListenerView 47 + public typealias ArtistListener = ArtistListenerViewBasic 48 + public typealias Scrobble = ScrobbleViewDetailed 49 + public typealias Shout = ShoutView 50 + public typealias PlaylistBasic = PlaylistViewBasic 51 + public typealias Playlist = PlaylistViewDetailed 52 + public typealias FeedGenerator = FeedGeneratorView 53 + public typealias FeedItem = FeedItemView 54 + public typealias Feed = FeedView 55 + public typealias Story = FeedStoryView 56 + public typealias Recommendation = FeedRecommendationView 57 + public typealias Recommendations = FeedRecommendationsView 58 + public typealias RecommendedArtist = FeedRecommendedArtistView 59 + public typealias RecommendedAlbum = FeedRecommendedAlbumView 60 + public typealias SearchResults = FeedSearchResultsView 61 + public typealias Compatibility = ActorCompatibilityViewBasic 62 + public typealias Neighbour = ActorNeighbourViewBasic 63 + public typealias MirrorSource = MirrorSourceView 25 64 26 65 @Serializable 27 66 public data class Profile( ··· 40 79 ) 41 80 42 81 @Serializable 43 - public data class ArtistBasic( 44 - public val id: String? = null, 45 - public val uri: String? = null, 46 - public val name: String? = null, 47 - public val picture: String? = null, 48 - public val sha256: String? = null, 49 - @SerialName("playCount") public val playCount: Long? = null, 50 - @SerialName("uniqueListeners") public val uniqueListeners: Long? = null, 51 - public val tags: List<String>? = null, 52 - ) 53 - 54 - public typealias Artist = ArtistBasic 55 - 56 - @Serializable 57 - public data class AlbumBasic( 58 - public val id: String? = null, 59 - public val uri: String? = null, 60 - public val title: String? = null, 61 - public val artist: String? = null, 62 - @SerialName("artistUri") public val artistUri: String? = null, 63 - public val year: Int? = null, 64 - @SerialName("albumArt") public val albumArt: String? = null, 65 - @SerialName("releaseDate") public val releaseDate: String? = null, 66 - public val sha256: String? = null, 67 - @SerialName("playCount") public val playCount: Long? = null, 68 - @SerialName("uniqueListeners") public val uniqueListeners: Long? = null, 69 - ) 70 - 71 - @Serializable 72 - public data class Album( 73 - public val id: String? = null, 74 - public val uri: String? = null, 75 - public val title: String? = null, 76 - public val artist: String? = null, 77 - @SerialName("artistUri") public val artistUri: String? = null, 78 - public val year: Int? = null, 79 - @SerialName("albumArt") public val albumArt: String? = null, 80 - @SerialName("releaseDate") public val releaseDate: String? = null, 81 - public val sha256: String? = null, 82 - @SerialName("playCount") public val playCount: Long? = null, 83 - @SerialName("uniqueListeners") public val uniqueListeners: Long? = null, 84 - public val tags: List<String>? = null, 85 - public val tracks: List<SongBasic>? = null, 86 - ) 87 - 88 - @Serializable 89 - public data class FirstScrobble( 90 - public val handle: String? = null, 91 - public val avatar: String? = null, 92 - public val timestamp: String? = null, 93 - ) 94 - 95 - @Serializable 96 - public data class SongBasic( 97 - public val id: String? = null, 98 - public val title: String? = null, 99 - public val artist: String? = null, 100 - @SerialName("albumArtist") public val albumArtist: String? = null, 101 - @SerialName("albumArt") public val albumArt: String? = null, 102 - public val uri: String? = null, 103 - public val album: String? = null, 104 - public val duration: Long? = null, 105 - @SerialName("trackNumber") public val trackNumber: Int? = null, 106 - @SerialName("discNumber") public val discNumber: Int? = null, 107 - @SerialName("playCount") public val playCount: Long? = null, 108 - @SerialName("uniqueListeners") public val uniqueListeners: Long? = null, 109 - @SerialName("albumUri") public val albumUri: String? = null, 110 - @SerialName("artistUri") public val artistUri: String? = null, 111 - public val sha256: String? = null, 112 - public val mbid: String? = null, 113 - public val isrc: String? = null, 114 - public val tags: List<String>? = null, 115 - @SerialName("createdAt") public val createdAt: String? = null, 116 - ) 117 - 118 - @Serializable 119 - public data class Song( 120 - public val id: String? = null, 121 - public val title: String? = null, 122 - public val artist: String? = null, 123 - @SerialName("albumArtist") public val albumArtist: String? = null, 124 - @SerialName("albumArt") public val albumArt: String? = null, 125 - public val uri: String? = null, 126 - public val album: String? = null, 127 - public val duration: Long? = null, 128 - @SerialName("trackNumber") public val trackNumber: Int? = null, 129 - @SerialName("discNumber") public val discNumber: Int? = null, 130 - @SerialName("playCount") public val playCount: Long? = null, 131 - @SerialName("uniqueListeners") public val uniqueListeners: Long? = null, 132 - @SerialName("albumUri") public val albumUri: String? = null, 133 - @SerialName("artistUri") public val artistUri: String? = null, 134 - public val sha256: String? = null, 135 - public val mbid: String? = null, 136 - public val isrc: String? = null, 137 - public val tags: List<String>? = null, 138 - @SerialName("createdAt") public val createdAt: String? = null, 139 - public val artists: List<ArtistBasic>? = null, 140 - @SerialName("firstScrobble") public val firstScrobble: FirstScrobble? = null, 141 - ) 142 - 143 - @Serializable 144 - public data class RecentListener( 145 - public val id: String? = null, 146 - public val did: String? = null, 147 - public val handle: String? = null, 148 - @SerialName("displayName") public val displayName: String? = null, 149 - public val avatar: String? = null, 150 - public val timestamp: String? = null, 151 - @SerialName("scrobbleUri") public val scrobbleUri: String? = null, 152 - ) 153 - 154 - @Serializable 155 - public data class ArtistListener( 156 - public val id: String? = null, 157 - public val did: String? = null, 158 - public val handle: String? = null, 159 - @SerialName("displayName") public val displayName: String? = null, 160 - public val avatar: String? = null, 161 - @SerialName("mostListenedSong") public val mostListenedSong: JsonElement? = null, 162 - @SerialName("totalPlays") public val totalPlays: Long? = null, 163 - public val rank: Int? = null, 164 - ) 165 - 166 - @Serializable 167 - public data class Scrobble( 168 - public val id: String? = null, 169 - public val user: String? = null, 170 - @SerialName("userDisplayName") public val userDisplayName: String? = null, 171 - @SerialName("userAvatar") public val userAvatar: String? = null, 172 - public val title: String? = null, 173 - public val artist: String? = null, 174 - @SerialName("artistUri") public val artistUri: String? = null, 175 - public val album: String? = null, 176 - @SerialName("albumUri") public val albumUri: String? = null, 177 - public val cover: String? = null, 178 - public val date: String? = null, 179 - public val uri: String? = null, 180 - public val sha256: String? = null, 181 - public val liked: Boolean? = null, 182 - @SerialName("likesCount") public val likesCount: Long? = null, 183 - public val listeners: Long? = null, 184 - public val scrobbles: Long? = null, 185 - public val artists: List<ArtistBasic>? = null, 186 - @SerialName("firstScrobble") public val firstScrobble: FirstScrobble? = null, 187 - ) 188 - 189 - @Serializable 190 - public data class ShoutAuthor( 191 - public val id: String? = null, 192 - public val did: String? = null, 193 - public val handle: String? = null, 194 - @SerialName("displayName") public val displayName: String? = null, 195 - public val avatar: String? = null, 196 - ) 197 - 198 - @Serializable 199 - public data class Shout( 200 - public val id: String? = null, 201 - public val message: String? = null, 202 - public val parent: String? = null, 203 - @SerialName("createdAt") public val createdAt: String? = null, 204 - public val author: ShoutAuthor? = null, 205 - ) 206 - 207 - @Serializable 208 82 public data class ApiKey( 209 83 public val id: String? = null, 210 84 public val name: String? = null, ··· 216 90 @SerialName("updatedAt") public val updatedAt: String? = null, 217 91 ) 218 92 219 - @Serializable 220 - public data class PlaylistBasic( 221 - public val id: String? = null, 222 - public val title: String? = null, 223 - public val uri: String? = null, 224 - @SerialName("curatorDid") public val curatorDid: String? = null, 225 - @SerialName("curatorHandle") public val curatorHandle: String? = null, 226 - @SerialName("curatorName") public val curatorName: String? = null, 227 - @SerialName("curatorAvatarUrl") public val curatorAvatarUrl: String? = null, 228 - public val description: String? = null, 229 - @SerialName("coverImageUrl") public val coverImageUrl: String? = null, 230 - @SerialName("createdAt") public val createdAt: String? = null, 231 - @SerialName("trackCount") public val trackCount: Int? = null, 232 - ) 233 - 234 - @Serializable 235 - public data class Playlist( 236 - public val id: String? = null, 237 - public val title: String? = null, 238 - public val uri: String? = null, 239 - @SerialName("curatorDid") public val curatorDid: String? = null, 240 - @SerialName("curatorHandle") public val curatorHandle: String? = null, 241 - @SerialName("curatorName") public val curatorName: String? = null, 242 - @SerialName("curatorAvatarUrl") public val curatorAvatarUrl: String? = null, 243 - public val description: String? = null, 244 - @SerialName("coverImageUrl") public val coverImageUrl: String? = null, 245 - @SerialName("createdAt") public val createdAt: String? = null, 246 - @SerialName("trackCount") public val trackCount: Int? = null, 247 - public val tracks: List<SongBasic>? = null, 248 - ) 249 - 250 - @Serializable 251 - public data class FeedGenerator( 252 - public val id: String? = null, 253 - public val name: String? = null, 254 - public val description: String? = null, 255 - public val uri: String? = null, 256 - public val avatar: String? = null, 257 - public val creator: ProfileBasic? = null, 258 - ) 259 - 260 - @Serializable 261 - public data class FeedItem( 262 - public val scrobble: Scrobble? = null, 263 - ) 264 - 265 - @Serializable 266 - public data class Feed( 267 - public val feed: List<FeedItem> = emptyList(), 268 - public val cursor: String? = null, 269 - ) 270 - 271 - @Serializable 272 - public data class Story( 273 - public val id: String? = null, 274 - public val did: String? = null, 275 - public val handle: String? = null, 276 - public val avatar: String? = null, 277 - public val title: String? = null, 278 - public val artist: String? = null, 279 - @SerialName("artistUri") public val artistUri: String? = null, 280 - public val album: String? = null, 281 - @SerialName("albumUri") public val albumUri: String? = null, 282 - @SerialName("albumArtist") public val albumArtist: String? = null, 283 - @SerialName("albumArt") public val albumArt: String? = null, 284 - @SerialName("createdAt") public val createdAt: String? = null, 285 - @SerialName("trackId") public val trackId: String? = null, 286 - @SerialName("trackUri") public val trackUri: String? = null, 287 - public val uri: String? = null, 288 - ) 289 - 290 - @Serializable 291 - public data class Recommendation( 292 - public val title: String? = null, 293 - public val artist: String? = null, 294 - public val album: String? = null, 295 - @SerialName("albumArt") public val albumArt: String? = null, 296 - @SerialName("trackUri") public val trackUri: String? = null, 297 - @SerialName("artistUri") public val artistUri: String? = null, 298 - @SerialName("albumUri") public val albumUri: String? = null, 299 - public val genres: List<String>? = null, 300 - @SerialName("recommendationScore") public val recommendationScore: Int? = null, 301 - public val source: String? = null, 302 - @SerialName("likesCount") public val likesCount: Long? = null, 303 - ) 304 - 305 - @Serializable 306 - public data class Recommendations( 307 - public val recommendations: List<Recommendation> = emptyList(), 308 - public val cursor: String? = null, 309 - ) 310 - 311 - @Serializable 312 - public data class RecommendedArtist( 313 - public val id: String? = null, 314 - public val uri: String? = null, 315 - public val name: String? = null, 316 - public val picture: String? = null, 317 - public val genres: List<String>? = null, 318 - @SerialName("recommendationScore") public val recommendationScore: Int? = null, 319 - public val source: String? = null, 320 - ) 321 - 322 - @Serializable 323 - public data class RecommendedAlbum( 324 - public val id: String? = null, 325 - public val uri: String? = null, 326 - public val title: String? = null, 327 - public val artist: String? = null, 328 - @SerialName("artistUri") public val artistUri: String? = null, 329 - public val year: Int? = null, 330 - @SerialName("albumArt") public val albumArt: String? = null, 331 - @SerialName("recommendationScore") public val recommendationScore: Int? = null, 332 - public val source: String? = null, 333 - ) 334 - 335 - @Serializable 336 - public data class SearchResults( 337 - public val hits: List<JsonElement> = emptyList(), 338 - @SerialName("processingTimeMs") public val processingTimeMs: Int? = null, 339 - public val limit: Int? = null, 340 - public val offset: Int? = null, 341 - @SerialName("estimatedTotalHits") public val estimatedTotalHits: Int? = null, 342 - ) 343 - 344 - @Serializable 345 - public data class Compatibility( 346 - @SerialName("compatibilityLevel") public val compatibilityLevel: Int? = null, 347 - @SerialName("compatibilityPercentage") public val compatibilityPercentage: Int? = null, 348 - @SerialName("sharedArtists") public val sharedArtists: Int? = null, 349 - @SerialName("topSharedArtistNames") public val topSharedArtistNames: List<String>? = null, 350 - @SerialName("topSharedDetailedArtists") public val topSharedDetailedArtists: List<ArtistBasic>? = null, 351 - @SerialName("user1ArtistCount") public val user1ArtistCount: Int? = null, 352 - @SerialName("user2ArtistCount") public val user2ArtistCount: Int? = null, 353 - ) 354 - 355 - @Serializable 356 - public data class Neighbour( 357 - @SerialName("userId") public val userId: String? = null, 358 - public val did: String? = null, 359 - public val handle: String? = null, 360 - @SerialName("displayName") public val displayName: String? = null, 361 - public val avatar: String? = null, 362 - @SerialName("sharedArtistsCount") public val sharedArtistsCount: Int? = null, 363 - @SerialName("similarityScore") public val similarityScore: Int? = null, 364 - @SerialName("topSharedArtistNames") public val topSharedArtistNames: List<String>? = null, 365 - @SerialName("topSharedArtistsDetails") public val topSharedArtistsDetails: List<ArtistBasic>? = null, 366 - ) 367 - 368 - @Serializable 369 - public data class MirrorSource( 370 - public val id: String? = null, 371 - public val kind: String? = null, 372 - public val enabled: Boolean? = null, 373 - public val config: JsonElement? = null, 374 - @SerialName("createdAt") public val createdAt: String? = null, 375 - @SerialName("updatedAt") public val updatedAt: String? = null, 376 - ) 377 - 378 93 /** 379 94 * Paged result returned by `getFollowers` / `getFollows` / `getKnownFollowers`. Iterates 380 95 * directly over [entries]. ··· 385 100 public val cursor: String? = null, 386 101 public val count: Int? = null, 387 102 ) : List<ProfileBasic> by entries 103 + 104 + @Serializable 105 + public data class ShoutAuthor( 106 + public val id: String? = null, 107 + public val did: String? = null, 108 + public val handle: String? = null, 109 + @SerialName("displayName") public val displayName: String? = null, 110 + public val avatar: String? = null, 111 + )
+2223
sdk/kotlin/rocksky/src/main/kotlin/app/rocksky/generated/Types.kt
··· 1 + // AUTO-GENERATED FILE — DO NOT EDIT. 2 + // Source: apps/api/lexicons/**/*.json 3 + // Regenerate via: bun run lexgen:types 4 + 5 + package app.rocksky.generated 6 + 7 + import kotlinx.serialization.SerialName 8 + import kotlinx.serialization.Serializable 9 + import kotlinx.serialization.json.JsonElement 10 + 11 + @Serializable 12 + public data class BlobRef( 13 + @SerialName("\$type") public val type: String? = null, 14 + public val ref: BlobCidRef? = null, 15 + @SerialName("mimeType") public val mimeType: String? = null, 16 + public val size: Int? = null, 17 + ) 18 + 19 + @Serializable 20 + public data class BlobCidRef( 21 + @SerialName("\$link") public val link: String? = null, 22 + ) 23 + 24 + 25 + @Serializable 26 + public data class ActorArtistViewBasic( 27 + public val id: String? = null, 28 + public val name: String? = null, 29 + public val picture: String? = null, 30 + public val uri: String? = null, 31 + @SerialName("user1Rank") public val user1Rank: Int? = null, 32 + @SerialName("user2Rank") public val user2Rank: Int? = null, 33 + public val weight: Int? = null, 34 + ) 35 + 36 + @Serializable 37 + public data class ActorCompatibilityViewBasic( 38 + @SerialName("compatibilityLevel") public val compatibilityLevel: Int? = null, 39 + @SerialName("compatibilityPercentage") public val compatibilityPercentage: Int? = null, 40 + @SerialName("sharedArtists") public val sharedArtists: Int? = null, 41 + @SerialName("topSharedArtistNames") public val topSharedArtistNames: List<String>? = null, 42 + @SerialName("topSharedDetailedArtists") public val topSharedDetailedArtists: List<ActorArtistViewBasic>? = null, 43 + @SerialName("user1ArtistCount") public val user1ArtistCount: Int? = null, 44 + @SerialName("user2ArtistCount") public val user2ArtistCount: Int? = null, 45 + ) 46 + 47 + @Serializable 48 + public data class ActorNeighbourViewBasic( 49 + @SerialName("userId") public val userId: String? = null, 50 + public val did: String? = null, 51 + public val handle: String? = null, 52 + @SerialName("displayName") public val displayName: String? = null, 53 + /** The URL of the actor's avatar image. */ 54 + public val avatar: String? = null, 55 + /** The number of artists shared with the actor. */ 56 + @SerialName("sharedArtistsCount") public val sharedArtistsCount: Int? = null, 57 + /** The similarity score with the actor. */ 58 + @SerialName("similarityScore") public val similarityScore: Int? = null, 59 + /** The top shared artist names with the actor. */ 60 + @SerialName("topSharedArtistNames") public val topSharedArtistNames: List<String>? = null, 61 + /** The top shared artist details with the actor. */ 62 + @SerialName("topSharedArtistsDetails") public val topSharedArtistsDetails: List<ArtistViewBasic>? = null, 63 + ) 64 + 65 + @Serializable 66 + public data class ActorProfileViewBasic( 67 + /** The unique identifier of the actor. */ 68 + public val id: String? = null, 69 + /** The DID of the actor. */ 70 + public val did: String? = null, 71 + /** The handle of the actor. */ 72 + public val handle: String? = null, 73 + /** The display name of the actor. */ 74 + @SerialName("displayName") public val displayName: String? = null, 75 + /** The URL of the actor's avatar image. */ 76 + public val avatar: String? = null, 77 + /** The date and time when the actor was created. */ 78 + @SerialName("createdAt") public val createdAt: String? = null, 79 + /** The date and time when the actor was last updated. */ 80 + @SerialName("updatedAt") public val updatedAt: String? = null, 81 + ) 82 + 83 + @Serializable 84 + public data class ActorProfileViewDetailed( 85 + /** The unique identifier of the actor. */ 86 + public val id: String? = null, 87 + /** The DID of the actor. */ 88 + public val did: String? = null, 89 + /** The handle of the actor. */ 90 + public val handle: String? = null, 91 + /** The display name of the actor. */ 92 + @SerialName("displayName") public val displayName: String? = null, 93 + /** The URL of the actor's avatar image. */ 94 + public val avatar: String? = null, 95 + /** The date and time when the actor was created. */ 96 + @SerialName("createdAt") public val createdAt: String? = null, 97 + /** The date and time when the actor was last updated. */ 98 + @SerialName("updatedAt") public val updatedAt: String? = null, 99 + ) 100 + 101 + @Serializable 102 + public data class ActorTrackView( 103 + /** The name of the track. */ 104 + public val name: String, 105 + /** The primary artist name. */ 106 + public val artist: String, 107 + /** The album name. */ 108 + public val album: String? = null, 109 + /** URL of the album cover image. */ 110 + @SerialName("albumCoverUrl") public val albumCoverUrl: String? = null, 111 + /** Track duration in milliseconds. */ 112 + @SerialName("durationMs") public val durationMs: Int? = null, 113 + /** Music service source, e.g. 'spotify' or 'listenbrainz'. */ 114 + public val source: String? = null, 115 + /** MusicBrainz recording ID, if available. */ 116 + @SerialName("recordingMbId") public val recordingMbId: String? = null, 117 + ) 118 + 119 + @Serializable 120 + public data class AddDirectoryToQueueParams( 121 + /** The directory to add to the queue */ 122 + public val directory: String, 123 + @SerialName("playerId") public val playerId: String? = null, 124 + /** Position in the queue to insert the directory at, defaults to the end if not specified */ 125 + public val position: Int? = null, 126 + /** Whether to shuffle the added directory in the queue */ 127 + public val shuffle: Boolean? = null, 128 + ) 129 + 130 + @Serializable 131 + public data class AddItemsToQueueParams( 132 + public val items: List<String>, 133 + @SerialName("playerId") public val playerId: String? = null, 134 + /** Position in the queue to insert the items at, defaults to the end if not specified */ 135 + public val position: Int? = null, 136 + /** Whether to shuffle the added items in the queue */ 137 + public val shuffle: Boolean? = null, 138 + ) 139 + 140 + @Serializable 141 + public data class AlbumRecord( 142 + /** The title of the album. */ 143 + public val title: String, 144 + /** The artist of the album. */ 145 + public val artist: String, 146 + /** The date and time when the album was created. */ 147 + @SerialName("createdAt") public val createdAt: String, 148 + /** The duration of the album in seconds. */ 149 + public val duration: Int? = null, 150 + /** The release date of the album. */ 151 + @SerialName("releaseDate") public val releaseDate: String? = null, 152 + /** The year the album was released. */ 153 + public val year: Int? = null, 154 + /** The genre of the album. */ 155 + public val genre: String? = null, 156 + /** The album art of the album. */ 157 + @SerialName("albumArt") public val albumArt: BlobRef? = null, 158 + /** The URL of the album art of the album. */ 159 + @SerialName("albumArtUrl") public val albumArtUrl: String? = null, 160 + /** The tags of the album. */ 161 + public val tags: List<String>? = null, 162 + /** The YouTube link of the album. */ 163 + @SerialName("youtubeLink") public val youtubeLink: String? = null, 164 + /** The Spotify link of the album. */ 165 + @SerialName("spotifyLink") public val spotifyLink: String? = null, 166 + /** The tidal link of the album. */ 167 + @SerialName("tidalLink") public val tidalLink: String? = null, 168 + /** The Apple Music link of the album. */ 169 + @SerialName("appleMusicLink") public val appleMusicLink: String? = null, 170 + ) 171 + 172 + @Serializable 173 + public data class AlbumViewBasic( 174 + /** The unique identifier of the album. */ 175 + public val id: String? = null, 176 + /** The URI of the album. */ 177 + public val uri: String? = null, 178 + /** The title of the album. */ 179 + public val title: String? = null, 180 + /** The artist of the album. */ 181 + public val artist: String? = null, 182 + /** The URI of the album's artist. */ 183 + @SerialName("artistUri") public val artistUri: String? = null, 184 + /** The year the album was released. */ 185 + public val year: Int? = null, 186 + /** The URL of the album art image. */ 187 + @SerialName("albumArt") public val albumArt: String? = null, 188 + /** The release date of the album. */ 189 + @SerialName("releaseDate") public val releaseDate: String? = null, 190 + /** The SHA256 hash of the album. */ 191 + public val sha256: String? = null, 192 + /** The number of times the album has been played. */ 193 + @SerialName("playCount") public val playCount: Int? = null, 194 + /** The number of unique listeners who have played the album. */ 195 + @SerialName("uniqueListeners") public val uniqueListeners: Int? = null, 196 + ) 197 + 198 + @Serializable 199 + public data class AlbumViewDetailed( 200 + /** The unique identifier of the album. */ 201 + public val id: String? = null, 202 + /** The URI of the album. */ 203 + public val uri: String? = null, 204 + /** The title of the album. */ 205 + public val title: String? = null, 206 + /** The artist of the album. */ 207 + public val artist: String? = null, 208 + /** The URI of the album's artist. */ 209 + @SerialName("artistUri") public val artistUri: String? = null, 210 + /** The year the album was released. */ 211 + public val year: Int? = null, 212 + /** The URL of the album art image. */ 213 + @SerialName("albumArt") public val albumArt: String? = null, 214 + /** The release date of the album. */ 215 + @SerialName("releaseDate") public val releaseDate: String? = null, 216 + /** The SHA256 hash of the album. */ 217 + public val sha256: String? = null, 218 + /** The number of times the album has been played. */ 219 + @SerialName("playCount") public val playCount: Int? = null, 220 + /** The number of unique listeners who have played the album. */ 221 + @SerialName("uniqueListeners") public val uniqueListeners: Int? = null, 222 + public val tags: List<String>? = null, 223 + public val tracks: List<SongViewBasic>? = null, 224 + ) 225 + 226 + @Serializable 227 + public data class ApiKeyView( 228 + /** The unique identifier of the API key. */ 229 + public val id: String? = null, 230 + /** The name of the API key. */ 231 + public val name: String? = null, 232 + /** A description for the API key. */ 233 + public val description: String? = null, 234 + /** The date and time when the API key was created. */ 235 + @SerialName("createdAt") public val createdAt: String? = null, 236 + ) 237 + 238 + @Serializable 239 + public data class ArtistListenerViewBasic( 240 + /** The unique identifier of the actor. */ 241 + public val id: String? = null, 242 + /** The DID of the listener. */ 243 + public val did: String? = null, 244 + /** The handle of the listener. */ 245 + public val handle: String? = null, 246 + /** The display name of the listener. */ 247 + @SerialName("displayName") public val displayName: String? = null, 248 + /** The URL of the listener's avatar image. */ 249 + public val avatar: String? = null, 250 + @SerialName("mostListenedSong") public val mostListenedSong: ArtistSongViewBasic? = null, 251 + /** The total number of plays by the listener. */ 252 + @SerialName("totalPlays") public val totalPlays: Int? = null, 253 + /** The rank of the listener among all listeners of the artist. */ 254 + public val rank: Int? = null, 255 + ) 256 + 257 + @Serializable 258 + public data class ArtistMbid( 259 + /** The MusicBrainz Identifier (MBID) of the artist. */ 260 + public val mbid: String? = null, 261 + /** The name of the artist. */ 262 + public val name: String? = null, 263 + ) 264 + 265 + @Serializable 266 + public data class ArtistRecentListenerView( 267 + /** The unique identifier of the listener. */ 268 + public val id: String? = null, 269 + /** The DID of the listener. */ 270 + public val did: String? = null, 271 + /** The handle of the listener. */ 272 + public val handle: String? = null, 273 + /** The display name of the listener. */ 274 + @SerialName("displayName") public val displayName: String? = null, 275 + /** The URL of the listener's avatar image. */ 276 + public val avatar: String? = null, 277 + /** The timestamp of the listener's most recent scrobble of this artist. */ 278 + public val timestamp: String? = null, 279 + /** The URI of the listener's most recent scrobble of this artist. */ 280 + @SerialName("scrobbleUri") public val scrobbleUri: String? = null, 281 + ) 282 + 283 + @Serializable 284 + public data class ArtistRecord( 285 + /** The name of the artist. */ 286 + public val name: String, 287 + /** The date when the artist was created. */ 288 + @SerialName("createdAt") public val createdAt: String, 289 + /** The biography of the artist. */ 290 + public val bio: String? = null, 291 + /** The picture of the artist. */ 292 + public val picture: BlobRef? = null, 293 + /** The URL of the picture of the artist. */ 294 + @SerialName("pictureUrl") public val pictureUrl: String? = null, 295 + /** The tags of the artist. */ 296 + public val tags: List<String>? = null, 297 + /** The birth date of the artist. */ 298 + public val born: String? = null, 299 + /** The death date of the artist. */ 300 + public val died: String? = null, 301 + /** The birth place of the artist. */ 302 + @SerialName("bornIn") public val bornIn: String? = null, 303 + ) 304 + 305 + @Serializable 306 + public data class ArtistSongViewBasic( 307 + /** The URI of the song. */ 308 + public val uri: String? = null, 309 + /** The title of the song. */ 310 + public val title: String? = null, 311 + /** The number of times the song has been played. */ 312 + @SerialName("playCount") public val playCount: Int? = null, 313 + ) 314 + 315 + @Serializable 316 + public data class ArtistViewBasic( 317 + /** The unique identifier of the artist. */ 318 + public val id: String? = null, 319 + /** The URI of the artist. */ 320 + public val uri: String? = null, 321 + /** The name of the artist. */ 322 + public val name: String? = null, 323 + /** The picture of the artist. */ 324 + public val picture: String? = null, 325 + /** The SHA256 hash of the artist. */ 326 + public val sha256: String? = null, 327 + /** The number of times the artist has been played. */ 328 + @SerialName("playCount") public val playCount: Int? = null, 329 + /** The number of unique listeners who have played the artist. */ 330 + @SerialName("uniqueListeners") public val uniqueListeners: Int? = null, 331 + public val tags: List<String>? = null, 332 + ) 333 + 334 + @Serializable 335 + public data class ArtistViewDetailed( 336 + /** The unique identifier of the artist. */ 337 + public val id: String? = null, 338 + /** The URI of the artist. */ 339 + public val uri: String? = null, 340 + /** The name of the artist. */ 341 + public val name: String? = null, 342 + /** The picture of the artist. */ 343 + public val picture: String? = null, 344 + /** The SHA256 hash of the artist. */ 345 + public val sha256: String? = null, 346 + /** The number of times the artist has been played. */ 347 + @SerialName("playCount") public val playCount: Int? = null, 348 + /** The number of unique listeners who have played the artist. */ 349 + @SerialName("uniqueListeners") public val uniqueListeners: Int? = null, 350 + public val tags: List<String>? = null, 351 + ) 352 + 353 + @Serializable 354 + public data class ChartsScrobbleViewBasic( 355 + /** The date of the scrobble. */ 356 + public val date: String? = null, 357 + /** The number of scrobbles on this date. */ 358 + public val count: Int? = null, 359 + ) 360 + 361 + @Serializable 362 + public data class ChartsView( 363 + public val scrobbles: List<ChartsScrobbleViewBasic>? = null, 364 + ) 365 + 366 + @Serializable 367 + public data class CreateApikeyInput( 368 + /** The name of the API key. */ 369 + public val name: String, 370 + /** A description for the API key. */ 371 + public val description: String? = null, 372 + ) 373 + 374 + @Serializable 375 + public data class CreatePlaylistParams( 376 + /** The name of the playlist */ 377 + public val name: String, 378 + /** A brief description of the playlist */ 379 + public val description: String? = null, 380 + ) 381 + 382 + @Serializable 383 + public data class CreateScrobbleInput( 384 + /** The title of the track being scrobbled */ 385 + public val title: String, 386 + /** The artist of the track being scrobbled */ 387 + public val artist: String, 388 + /** The album of the track being scrobbled */ 389 + public val album: String? = null, 390 + /** The duration of the track in milliseconds */ 391 + public val duration: Int? = null, 392 + /** The MusicBrainz ID of the track, if available */ 393 + @SerialName("mbId") public val mbId: String? = null, 394 + /** The International Standard Recording Code (ISRC) of the track, if available */ 395 + public val isrc: String? = null, 396 + /** The URL of the album art for the track */ 397 + @SerialName("albumArt") public val albumArt: String? = null, 398 + /** The track number of the track in the album */ 399 + @SerialName("trackNumber") public val trackNumber: Int? = null, 400 + /** The release date of the track, formatted as YYYY-MM-DD */ 401 + @SerialName("releaseDate") public val releaseDate: String? = null, 402 + /** The year the track was released */ 403 + public val year: Int? = null, 404 + /** The disc number of the track in the album, if applicable */ 405 + @SerialName("discNumber") public val discNumber: Int? = null, 406 + /** The lyrics of the track, if available */ 407 + public val lyrics: String? = null, 408 + /** The composer of the track, if available */ 409 + public val composer: String? = null, 410 + /** The copyright message for the track, if available */ 411 + @SerialName("copyrightMessage") public val copyrightMessage: String? = null, 412 + /** The record label of the track, if available */ 413 + public val label: String? = null, 414 + /** The URL of the artist's picture, if available */ 415 + @SerialName("artistPicture") public val artistPicture: String? = null, 416 + /** The Spotify link for the track, if available */ 417 + @SerialName("spotifyLink") public val spotifyLink: String? = null, 418 + /** The Last.fm link for the track, if available */ 419 + @SerialName("lastfmLink") public val lastfmLink: String? = null, 420 + /** The Tidal link for the track, if available */ 421 + @SerialName("tidalLink") public val tidalLink: String? = null, 422 + /** The Apple Music link for the track, if available */ 423 + @SerialName("appleMusicLink") public val appleMusicLink: String? = null, 424 + /** The Youtube link for the track, if available */ 425 + @SerialName("youtubeLink") public val youtubeLink: String? = null, 426 + /** The Deezer link for the track, if available */ 427 + @SerialName("deezerLink") public val deezerLink: String? = null, 428 + /** The timestamp of the scrobble in seconds since epoch (Unix timestamp) */ 429 + public val timestamp: Int? = null, 430 + ) 431 + 432 + @Serializable 433 + public data class CreateShoutInput( 434 + /** The content of the shout */ 435 + public val message: String? = null, 436 + ) 437 + 438 + @Serializable 439 + public data class CreateSongInput( 440 + /** The title of the song */ 441 + public val title: String, 442 + /** The artist of the song */ 443 + public val artist: String, 444 + /** The album artist of the song, if different from the main artist */ 445 + @SerialName("albumArtist") public val albumArtist: String, 446 + /** The album of the song, if applicable */ 447 + public val album: String, 448 + /** The duration of the song in seconds */ 449 + public val duration: Int? = null, 450 + /** The MusicBrainz ID of the song, if available */ 451 + @SerialName("mbId") public val mbId: String? = null, 452 + /** The International Standard Recording Code (ISRC) of the song, if available */ 453 + public val isrc: String? = null, 454 + /** The URL of the album art for the song */ 455 + @SerialName("albumArt") public val albumArt: String? = null, 456 + /** The track number of the song in the album, if applicable */ 457 + @SerialName("trackNumber") public val trackNumber: Int? = null, 458 + /** The release date of the song, formatted as YYYY-MM-DD */ 459 + @SerialName("releaseDate") public val releaseDate: String? = null, 460 + /** The year the song was released */ 461 + public val year: Int? = null, 462 + /** The disc number of the song in the album, if applicable */ 463 + @SerialName("discNumber") public val discNumber: Int? = null, 464 + /** The lyrics of the song, if available */ 465 + public val lyrics: String? = null, 466 + ) 467 + 468 + @Serializable 469 + public data class DescribeFeedGeneratorOutput( 470 + /** The DID of the feed generator. */ 471 + public val did: String? = null, 472 + /** List of feed URIs generated by this feed generator. */ 473 + public val feeds: List<FeedUriView>? = null, 474 + ) 475 + 476 + @Serializable 477 + public class DescribeFeedGeneratorParams 478 + 479 + @Serializable 480 + public data class DislikeShoutInput( 481 + /** The unique identifier of the shout to dislike */ 482 + public val uri: String? = null, 483 + ) 484 + 485 + @Serializable 486 + public data class DislikeSongInput( 487 + /** The unique identifier of the song to dislike */ 488 + public val uri: String? = null, 489 + ) 490 + 491 + @Serializable 492 + public data class DownloadFileParams( 493 + /** The unique identifier of the file to download */ 494 + @SerialName("fileId") public val fileId: String, 495 + ) 496 + 497 + @Serializable 498 + public data class DropboxFileListView( 499 + /** A list of files in the Dropbox. */ 500 + public val files: List<DropboxFileView>? = null, 501 + ) 502 + 503 + @Serializable 504 + public data class DropboxFileView( 505 + /** The unique identifier of the file. */ 506 + public val id: String? = null, 507 + /** The name of the file. */ 508 + public val name: String? = null, 509 + /** The lowercased path of the file. */ 510 + @SerialName("pathLower") public val pathLower: String? = null, 511 + /** The display path of the file. */ 512 + @SerialName("pathDisplay") public val pathDisplay: String? = null, 513 + /** The last modified date and time of the file on the client. */ 514 + @SerialName("clientModified") public val clientModified: String? = null, 515 + /** The last modified date and time of the file on the server. */ 516 + @SerialName("serverModified") public val serverModified: String? = null, 517 + ) 518 + 519 + @Serializable 520 + public data class DropboxTemporaryLinkView( 521 + /** The temporary link to access the file. */ 522 + public val link: String? = null, 523 + ) 524 + 525 + @Serializable 526 + public data class FeedGeneratorsView( 527 + public val feeds: List<FeedGeneratorView>? = null, 528 + ) 529 + 530 + @Serializable 531 + public data class FeedGeneratorView( 532 + public val id: String? = null, 533 + public val name: String? = null, 534 + public val description: String? = null, 535 + public val uri: String? = null, 536 + public val avatar: String? = null, 537 + public val creator: ActorProfileViewBasic? = null, 538 + ) 539 + 540 + @Serializable 541 + public data class FeedItemView( 542 + public val scrobble: ScrobbleViewBasic? = null, 543 + ) 544 + 545 + @Serializable 546 + public data class FeedRecommendationsView( 547 + public val recommendations: List<FeedRecommendationView>? = null, 548 + public val cursor: String? = null, 549 + ) 550 + 551 + @Serializable 552 + public data class FeedRecommendationView( 553 + public val title: String? = null, 554 + public val artist: String? = null, 555 + public val album: String? = null, 556 + @SerialName("albumArt") public val albumArt: String? = null, 557 + @SerialName("trackUri") public val trackUri: String? = null, 558 + @SerialName("artistUri") public val artistUri: String? = null, 559 + @SerialName("albumUri") public val albumUri: String? = null, 560 + public val genres: List<String>? = null, 561 + @SerialName("recommendationScore") public val recommendationScore: Int? = null, 562 + /** neighbour | social | serendipity */ 563 + public val source: String? = null, 564 + @SerialName("likesCount") public val likesCount: Int? = null, 565 + ) 566 + 567 + @Serializable 568 + public data class FeedRecommendedAlbumsView( 569 + public val albums: List<FeedRecommendedAlbumView>? = null, 570 + public val cursor: String? = null, 571 + ) 572 + 573 + @Serializable 574 + public data class FeedRecommendedAlbumView( 575 + public val id: String? = null, 576 + public val uri: String? = null, 577 + public val title: String? = null, 578 + public val artist: String? = null, 579 + @SerialName("artistUri") public val artistUri: String? = null, 580 + public val year: Int? = null, 581 + @SerialName("albumArt") public val albumArt: String? = null, 582 + @SerialName("recommendationScore") public val recommendationScore: Int? = null, 583 + /** known-artist | new-artist | serendipity */ 584 + public val source: String? = null, 585 + ) 586 + 587 + @Serializable 588 + public data class FeedRecommendedArtistsView( 589 + public val artists: List<FeedRecommendedArtistView>? = null, 590 + public val cursor: String? = null, 591 + ) 592 + 593 + @Serializable 594 + public data class FeedRecommendedArtistView( 595 + public val id: String? = null, 596 + public val uri: String? = null, 597 + public val name: String? = null, 598 + public val picture: String? = null, 599 + public val genres: List<String>? = null, 600 + @SerialName("recommendationScore") public val recommendationScore: Int? = null, 601 + /** neighbour | social | serendipity */ 602 + public val source: String? = null, 603 + ) 604 + 605 + @Serializable 606 + public data class FeedSearchResultsView( 607 + public val hits: List<JsonElement>? = null, 608 + @SerialName("processingTimeMs") public val processingTimeMs: Int? = null, 609 + public val limit: Int? = null, 610 + public val offset: Int? = null, 611 + @SerialName("estimatedTotalHits") public val estimatedTotalHits: Int? = null, 612 + ) 613 + 614 + @Serializable 615 + public data class FeedStoriesView( 616 + public val stories: List<FeedStoryView>? = null, 617 + ) 618 + 619 + @Serializable 620 + public data class FeedStoryView( 621 + public val album: String? = null, 622 + @SerialName("albumArt") public val albumArt: String? = null, 623 + @SerialName("albumArtist") public val albumArtist: String? = null, 624 + @SerialName("albumUri") public val albumUri: String? = null, 625 + public val artist: String? = null, 626 + @SerialName("artistUri") public val artistUri: String? = null, 627 + public val avatar: String? = null, 628 + @SerialName("createdAt") public val createdAt: String? = null, 629 + public val did: String? = null, 630 + public val handle: String? = null, 631 + public val id: String? = null, 632 + public val title: String? = null, 633 + @SerialName("trackId") public val trackId: String? = null, 634 + @SerialName("trackUri") public val trackUri: String? = null, 635 + public val uri: String? = null, 636 + ) 637 + 638 + @Serializable 639 + public data class FeedUriView( 640 + /** The feed URI. */ 641 + public val uri: String? = null, 642 + ) 643 + 644 + @Serializable 645 + public data class FeedView( 646 + public val feed: List<FeedItemView>? = null, 647 + /** The pagination cursor for the next set of results. */ 648 + public val cursor: String? = null, 649 + ) 650 + 651 + @Serializable 652 + public data class FollowAccountOutput( 653 + public val subject: ActorProfileViewBasic, 654 + public val followers: List<ActorProfileViewBasic>, 655 + /** A cursor value to pass to subsequent calls to get the next page of results. */ 656 + public val cursor: String? = null, 657 + ) 658 + 659 + @Serializable 660 + public data class FollowAccountParams( 661 + public val account: String, 662 + ) 663 + 664 + @Serializable 665 + public data class FollowRecord( 666 + @SerialName("createdAt") public val createdAt: String, 667 + public val subject: String, 668 + public val via: StrongRef? = null, 669 + ) 670 + 671 + @Serializable 672 + public data class GeneratorRecord( 673 + public val did: String, 674 + @SerialName("displayName") public val displayName: String, 675 + @SerialName("createdAt") public val createdAt: String, 676 + public val avatar: BlobRef? = null, 677 + public val description: String? = null, 678 + ) 679 + 680 + @Serializable 681 + public data class GetActorAlbumsOutput( 682 + public val albums: List<AlbumViewBasic>? = null, 683 + ) 684 + 685 + @Serializable 686 + public data class GetActorAlbumsParams( 687 + /** The DID or handle of the actor */ 688 + public val did: String, 689 + /** The maximum number of albums to return */ 690 + public val limit: Int? = null, 691 + /** The offset for pagination */ 692 + public val offset: Int? = null, 693 + /** The start date to filter albums from (ISO 8601 format) */ 694 + @SerialName("startDate") public val startDate: String? = null, 695 + /** The end date to filter albums to (ISO 8601 format) */ 696 + @SerialName("endDate") public val endDate: String? = null, 697 + ) 698 + 699 + @Serializable 700 + public data class GetActorArtistsOutput( 701 + public val artists: List<ArtistViewBasic>? = null, 702 + ) 703 + 704 + @Serializable 705 + public data class GetActorArtistsParams( 706 + /** The DID or handle of the actor */ 707 + public val did: String, 708 + /** The maximum number of albums to return */ 709 + public val limit: Int? = null, 710 + /** The offset for pagination */ 711 + public val offset: Int? = null, 712 + /** The start date to filter albums from (ISO 8601 format) */ 713 + @SerialName("startDate") public val startDate: String? = null, 714 + /** The end date to filter albums to (ISO 8601 format) */ 715 + @SerialName("endDate") public val endDate: String? = null, 716 + ) 717 + 718 + @Serializable 719 + public data class GetActorCompatibilityOutput( 720 + public val compatibility: ActorCompatibilityViewBasic? = null, 721 + ) 722 + 723 + @Serializable 724 + public data class GetActorCompatibilityParams( 725 + /** DID or handle to get compatibility for */ 726 + public val did: String, 727 + ) 728 + 729 + @Serializable 730 + public data class GetActorLovedSongsOutput( 731 + public val tracks: List<SongViewBasic>? = null, 732 + ) 733 + 734 + @Serializable 735 + public data class GetActorLovedSongsParams( 736 + /** The DID or handle of the actor */ 737 + public val did: String, 738 + /** The maximum number of albums to return */ 739 + public val limit: Int? = null, 740 + /** The offset for pagination */ 741 + public val offset: Int? = null, 742 + ) 743 + 744 + @Serializable 745 + public data class GetActorNeighboursOutput( 746 + public val neighbours: List<ActorNeighbourViewBasic>? = null, 747 + ) 748 + 749 + @Serializable 750 + public data class GetActorNeighboursParams( 751 + /** The DID or handle of the actor */ 752 + public val did: String, 753 + ) 754 + 755 + @Serializable 756 + public data class GetActorPlaylistsOutput( 757 + public val playlists: List<PlaylistViewBasic>? = null, 758 + ) 759 + 760 + @Serializable 761 + public data class GetActorPlaylistsParams( 762 + /** The DID or handle of the actor */ 763 + public val did: String, 764 + /** The maximum number of albums to return */ 765 + public val limit: Int? = null, 766 + /** The offset for pagination */ 767 + public val offset: Int? = null, 768 + ) 769 + 770 + @Serializable 771 + public data class GetActorScrobblesOutput( 772 + public val scrobbles: List<ScrobbleViewBasic>? = null, 773 + ) 774 + 775 + @Serializable 776 + public data class GetActorScrobblesParams( 777 + /** The DID or handle of the actor */ 778 + public val did: String, 779 + /** The maximum number of albums to return */ 780 + public val limit: Int? = null, 781 + /** The offset for pagination */ 782 + public val offset: Int? = null, 783 + ) 784 + 785 + @Serializable 786 + public data class GetActorSongsOutput( 787 + public val songs: List<SongViewBasic>? = null, 788 + ) 789 + 790 + @Serializable 791 + public data class GetActorSongsParams( 792 + /** The DID or handle of the actor */ 793 + public val did: String, 794 + /** The maximum number of albums to return */ 795 + public val limit: Int? = null, 796 + /** The offset for pagination */ 797 + public val offset: Int? = null, 798 + /** The start date to filter albums from (ISO 8601 format) */ 799 + @SerialName("startDate") public val startDate: String? = null, 800 + /** The end date to filter albums to (ISO 8601 format) */ 801 + @SerialName("endDate") public val endDate: String? = null, 802 + ) 803 + 804 + @Serializable 805 + public data class GetAlbumParams( 806 + /** The URI of the album to retrieve. */ 807 + public val uri: String, 808 + ) 809 + 810 + @Serializable 811 + public data class GetAlbumRecommendationsParams( 812 + /** DID or handle of the user to recommend for. */ 813 + public val did: String, 814 + public val limit: Int? = null, 815 + ) 816 + 817 + @Serializable 818 + public data class GetAlbumShoutsOutput( 819 + public val shouts: List<JsonElement>? = null, 820 + ) 821 + 822 + @Serializable 823 + public data class GetAlbumShoutsParams( 824 + /** The unique identifier of the album to retrieve shouts for */ 825 + public val uri: String, 826 + /** The maximum number of shouts to return */ 827 + public val limit: Int? = null, 828 + /** The number of shouts to skip before starting to collect the result set */ 829 + public val offset: Int? = null, 830 + ) 831 + 832 + @Serializable 833 + public data class GetAlbumsOutput( 834 + public val albums: List<AlbumViewBasic>? = null, 835 + ) 836 + 837 + @Serializable 838 + public data class GetAlbumsParams( 839 + /** The maximum number of albums to return */ 840 + public val limit: Int? = null, 841 + /** The offset for pagination */ 842 + public val offset: Int? = null, 843 + /** The genre to filter artists by */ 844 + public val genre: String? = null, 845 + ) 846 + 847 + @Serializable 848 + public data class GetAlbumTracksOutput( 849 + public val tracks: List<SongViewBasic>? = null, 850 + ) 851 + 852 + @Serializable 853 + public data class GetAlbumTracksParams( 854 + /** The URI of the album to retrieve tracks from */ 855 + public val uri: String, 856 + ) 857 + 858 + @Serializable 859 + public data class GetApikeysOutput( 860 + @SerialName("apiKeys") public val apiKeys: List<JsonElement>? = null, 861 + ) 862 + 863 + @Serializable 864 + public data class GetApikeysParams( 865 + /** The number of API keys to skip before starting to collect the result set. */ 866 + public val offset: Int? = null, 867 + /** The number of API keys to return per page. */ 868 + public val limit: Int? = null, 869 + ) 870 + 871 + @Serializable 872 + public data class GetArtistAlbumsOutput( 873 + public val albums: List<AlbumViewBasic>? = null, 874 + ) 875 + 876 + @Serializable 877 + public data class GetArtistAlbumsParams( 878 + /** The URI of the artist to retrieve albums from */ 879 + public val uri: String, 880 + ) 881 + 882 + @Serializable 883 + public data class GetArtistListenersOutput( 884 + public val listeners: List<ArtistListenerViewBasic>? = null, 885 + ) 886 + 887 + @Serializable 888 + public data class GetArtistListenersParams( 889 + /** The URI of the artist to retrieve listeners from */ 890 + public val uri: String, 891 + /** Number of items to skip before returning results */ 892 + public val offset: Int? = null, 893 + /** Maximum number of results to return */ 894 + public val limit: Int? = null, 895 + ) 896 + 897 + @Serializable 898 + public data class GetArtistParams( 899 + /** The URI of the artist to retrieve details from */ 900 + public val uri: String, 901 + ) 902 + 903 + @Serializable 904 + public data class GetArtistRecentListenersOutput( 905 + public val listeners: List<ArtistRecentListenerView>? = null, 906 + ) 907 + 908 + @Serializable 909 + public data class GetArtistRecentListenersParams( 910 + /** The URI of the artist to retrieve recent listeners from */ 911 + public val uri: String, 912 + /** Number of items to skip before returning results */ 913 + public val offset: Int? = null, 914 + /** Maximum number of results to return */ 915 + public val limit: Int? = null, 916 + ) 917 + 918 + @Serializable 919 + public data class GetArtistRecommendationsParams( 920 + /** DID or handle of the user to recommend for. */ 921 + public val did: String, 922 + public val limit: Int? = null, 923 + ) 924 + 925 + @Serializable 926 + public data class GetArtistShoutsOutput( 927 + public val shouts: List<JsonElement>? = null, 928 + ) 929 + 930 + @Serializable 931 + public data class GetArtistShoutsParams( 932 + /** The URI of the artist to retrieve shouts for */ 933 + public val uri: String, 934 + /** The maximum number of shouts to return */ 935 + public val limit: Int? = null, 936 + /** The number of shouts to skip before starting to collect the result set */ 937 + public val offset: Int? = null, 938 + ) 939 + 940 + @Serializable 941 + public data class GetArtistsOutput( 942 + public val artists: List<ArtistViewBasic>? = null, 943 + ) 944 + 945 + @Serializable 946 + public data class GetArtistsParams( 947 + /** The maximum number of artists to return */ 948 + public val limit: Int? = null, 949 + /** The offset for pagination */ 950 + public val offset: Int? = null, 951 + /** The names of the artists to return */ 952 + public val names: String? = null, 953 + /** The genre to filter artists by */ 954 + public val genre: String? = null, 955 + ) 956 + 957 + @Serializable 958 + public data class GetArtistTracksOutput( 959 + public val tracks: List<SongViewBasic>? = null, 960 + ) 961 + 962 + @Serializable 963 + public data class GetArtistTracksParams( 964 + /** The URI of the artist to retrieve albums from */ 965 + public val uri: String? = null, 966 + /** The maximum number of tracks to return */ 967 + public val limit: Int? = null, 968 + /** The offset for pagination */ 969 + public val offset: Int? = null, 970 + ) 971 + 972 + @Serializable 973 + public data class GetCurrentlyPlayingParams( 974 + @SerialName("playerId") public val playerId: String? = null, 975 + /** Handle or DID of the actor to retrieve the currently playing track for. If not provided, defaults to the current user. */ 976 + public val actor: String? = null, 977 + ) 978 + 979 + @Serializable 980 + public data class GetFeedGeneratorOutput( 981 + public val view: FeedGeneratorView? = null, 982 + ) 983 + 984 + @Serializable 985 + public data class GetFeedGeneratorParams( 986 + /** AT-URI of the feed generator record. */ 987 + public val feed: String, 988 + ) 989 + 990 + @Serializable 991 + public data class GetFeedGeneratorsParams( 992 + /** The maximum number of feed generators to return. */ 993 + public val size: Int? = null, 994 + ) 995 + 996 + @Serializable 997 + public data class GetFeedParams( 998 + /** The feed URI. */ 999 + public val feed: String, 1000 + /** The maximum number of scrobbles to return */ 1001 + public val limit: Int? = null, 1002 + /** The cursor for pagination */ 1003 + public val cursor: String? = null, 1004 + ) 1005 + 1006 + @Serializable 1007 + public data class GetFeedSkeletonOutput( 1008 + public val scrobbles: List<ScrobbleViewBasic>? = null, 1009 + /** The pagination cursor for the next set of results. */ 1010 + public val cursor: String? = null, 1011 + ) 1012 + 1013 + @Serializable 1014 + public data class GetFeedSkeletonParams( 1015 + /** The feed URI. */ 1016 + public val feed: String, 1017 + /** The maximum number of scrobbles to return */ 1018 + public val limit: Int? = null, 1019 + /** The offset for pagination */ 1020 + public val offset: Int? = null, 1021 + /** The pagination cursor. */ 1022 + public val cursor: String? = null, 1023 + ) 1024 + 1025 + @Serializable 1026 + public data class GetFileParams( 1027 + /** The unique identifier of the file to retrieve */ 1028 + @SerialName("fileId") public val fileId: String, 1029 + ) 1030 + 1031 + @Serializable 1032 + public data class GetFilesParams( 1033 + /** Path to the Dropbox folder or root directory */ 1034 + public val at: String? = null, 1035 + ) 1036 + 1037 + @Serializable 1038 + public data class GetFollowersOutput( 1039 + public val subject: ActorProfileViewBasic, 1040 + public val followers: List<ActorProfileViewBasic>, 1041 + /** A cursor value to pass to subsequent calls to get the next page of results. */ 1042 + public val cursor: String? = null, 1043 + /** The total number of followers. */ 1044 + public val count: Int? = null, 1045 + ) 1046 + 1047 + @Serializable 1048 + public data class GetFollowersParams( 1049 + public val actor: String, 1050 + public val limit: Int? = null, 1051 + /** If provided, filters the followers to only include those with DIDs in this list. */ 1052 + public val dids: List<String>? = null, 1053 + public val cursor: String? = null, 1054 + ) 1055 + 1056 + @Serializable 1057 + public data class GetFollowsOutput( 1058 + public val subject: ActorProfileViewBasic, 1059 + public val follows: List<ActorProfileViewBasic>, 1060 + /** A cursor value to pass to subsequent calls to get the next page of results. */ 1061 + public val cursor: String? = null, 1062 + /** The total number of follows. */ 1063 + public val count: Int? = null, 1064 + ) 1065 + 1066 + @Serializable 1067 + public data class GetFollowsParams( 1068 + public val actor: String, 1069 + public val limit: Int? = null, 1070 + /** If provided, filters the follows to only include those with DIDs in this list. */ 1071 + public val dids: List<String>? = null, 1072 + public val cursor: String? = null, 1073 + ) 1074 + 1075 + @Serializable 1076 + public data class GetKnownFollowersOutput( 1077 + public val subject: ActorProfileViewBasic, 1078 + public val followers: List<ActorProfileViewBasic>, 1079 + /** A cursor value to pass to subsequent calls to get the next page of results. */ 1080 + public val cursor: String? = null, 1081 + ) 1082 + 1083 + @Serializable 1084 + public data class GetKnownFollowersParams( 1085 + public val actor: String, 1086 + public val limit: Int? = null, 1087 + public val cursor: String? = null, 1088 + ) 1089 + 1090 + @Serializable 1091 + public data class GetMetadataParams( 1092 + /** Path to the file or folder in Dropbox */ 1093 + public val path: String, 1094 + ) 1095 + 1096 + @Serializable 1097 + public data class GetMirrorSourcesOutput( 1098 + public val sources: List<MirrorSourceView>, 1099 + ) 1100 + 1101 + @Serializable 1102 + public class GetMirrorSourcesParams 1103 + 1104 + @Serializable 1105 + public data class GetPlaybackQueueParams( 1106 + @SerialName("playerId") public val playerId: String? = null, 1107 + ) 1108 + 1109 + @Serializable 1110 + public data class GetPlaylistParams( 1111 + /** The URI of the playlist to retrieve. */ 1112 + public val uri: String, 1113 + ) 1114 + 1115 + @Serializable 1116 + public data class GetPlaylistsOutput( 1117 + public val playlists: List<PlaylistViewBasic>? = null, 1118 + ) 1119 + 1120 + @Serializable 1121 + public data class GetPlaylistsParams( 1122 + /** The maximum number of playlists to return. */ 1123 + public val limit: Int? = null, 1124 + /** The offset for pagination, used to skip a number of playlists. */ 1125 + public val offset: Int? = null, 1126 + ) 1127 + 1128 + @Serializable 1129 + public data class GetProfileParams( 1130 + /** The DID or handle of the actor */ 1131 + public val did: String? = null, 1132 + ) 1133 + 1134 + @Serializable 1135 + public data class GetProfileShoutsOutput( 1136 + public val shouts: List<JsonElement>? = null, 1137 + ) 1138 + 1139 + @Serializable 1140 + public data class GetProfileShoutsParams( 1141 + /** The DID or handle of the actor */ 1142 + public val did: String, 1143 + /** The offset for pagination */ 1144 + public val offset: Int? = null, 1145 + /** The maximum number of shouts to return */ 1146 + public val limit: Int? = null, 1147 + ) 1148 + 1149 + @Serializable 1150 + public data class GetRecommendationsParams( 1151 + /** DID or handle of the user to recommend for. */ 1152 + public val did: String, 1153 + public val limit: Int? = null, 1154 + ) 1155 + 1156 + @Serializable 1157 + public data class GetScrobbleParams( 1158 + /** The unique identifier of the scrobble */ 1159 + public val uri: String, 1160 + ) 1161 + 1162 + @Serializable 1163 + public data class GetScrobblesChartParams( 1164 + /** The DID or handle of the actor */ 1165 + public val did: String? = null, 1166 + /** The URI of the artist to filter by */ 1167 + public val artisturi: String? = null, 1168 + /** The URI of the album to filter by */ 1169 + public val albumuri: String? = null, 1170 + /** The URI of the track to filter by */ 1171 + public val songuri: String? = null, 1172 + /** The genre to filter by */ 1173 + public val genre: String? = null, 1174 + /** Start date (ISO 8601). Defaults to 6 months ago. */ 1175 + public val from: String? = null, 1176 + /** End date (ISO 8601). Defaults to today. */ 1177 + public val to: String? = null, 1178 + ) 1179 + 1180 + @Serializable 1181 + public data class GetScrobblesOutput( 1182 + public val scrobbles: List<ScrobbleViewBasic>? = null, 1183 + ) 1184 + 1185 + @Serializable 1186 + public data class GetScrobblesParams( 1187 + /** The DID or handle of the actor */ 1188 + public val did: String? = null, 1189 + /** If true, only return scrobbles from actors the viewer is following. */ 1190 + public val following: Boolean? = null, 1191 + /** The maximum number of scrobbles to return */ 1192 + public val limit: Int? = null, 1193 + /** The offset for pagination */ 1194 + public val offset: Int? = null, 1195 + ) 1196 + 1197 + @Serializable 1198 + public data class GetShoutRepliesOutput( 1199 + public val shouts: List<JsonElement>? = null, 1200 + ) 1201 + 1202 + @Serializable 1203 + public data class GetShoutRepliesParams( 1204 + /** The URI of the shout to retrieve replies for */ 1205 + public val uri: String, 1206 + /** The maximum number of shouts to return */ 1207 + public val limit: Int? = null, 1208 + /** The number of shouts to skip before starting to collect the result set */ 1209 + public val offset: Int? = null, 1210 + ) 1211 + 1212 + @Serializable 1213 + public data class GetSongParams( 1214 + /** The AT-URI of the song to retrieve */ 1215 + public val uri: String? = null, 1216 + /** The MusicBrainz ID of the song to retrieve */ 1217 + public val mbid: String? = null, 1218 + /** The International Standard Recording Code (ISRC) of the song to retrieve */ 1219 + public val isrc: String? = null, 1220 + /** The Spotify track ID of the song to retrieve (resolved internally to the Spotify track URL) */ 1221 + @SerialName("spotifyId") public val spotifyId: String? = null, 1222 + ) 1223 + 1224 + @Serializable 1225 + public data class GetSongRecentListenersOutput( 1226 + public val listeners: List<SongRecentListenerView>? = null, 1227 + ) 1228 + 1229 + @Serializable 1230 + public data class GetSongRecentListenersParams( 1231 + /** The URI of the song to retrieve recent listeners from */ 1232 + public val uri: String, 1233 + /** Number of items to skip before returning results */ 1234 + public val offset: Int? = null, 1235 + /** Maximum number of results to return */ 1236 + public val limit: Int? = null, 1237 + ) 1238 + 1239 + @Serializable 1240 + public data class GetSongsOutput( 1241 + public val songs: List<SongViewBasic>? = null, 1242 + ) 1243 + 1244 + @Serializable 1245 + public data class GetSongsParams( 1246 + /** The maximum number of songs to return */ 1247 + public val limit: Int? = null, 1248 + /** The offset for pagination */ 1249 + public val offset: Int? = null, 1250 + /** The genre to filter artists by */ 1251 + public val genre: String? = null, 1252 + /** Filter songs by MusicBrainz ID */ 1253 + public val mbid: String? = null, 1254 + /** Filter songs by International Standard Recording Code (ISRC) */ 1255 + public val isrc: String? = null, 1256 + /** Filter songs by Spotify track ID (resolved internally to the Spotify track URL) */ 1257 + @SerialName("spotifyId") public val spotifyId: String? = null, 1258 + ) 1259 + 1260 + @Serializable 1261 + public data class GetStatsParams( 1262 + /** The DID or handle of the user to get stats for. */ 1263 + public val did: String, 1264 + ) 1265 + 1266 + @Serializable 1267 + public data class GetStoriesParams( 1268 + /** The maximum number of stories to return. */ 1269 + public val size: Int? = null, 1270 + ) 1271 + 1272 + @Serializable 1273 + public data class GetTemporaryLinkParams( 1274 + /** Path to the file in Dropbox */ 1275 + public val path: String, 1276 + ) 1277 + 1278 + @Serializable 1279 + public data class GetTopArtistsOutput( 1280 + public val artists: List<ArtistViewBasic>? = null, 1281 + ) 1282 + 1283 + @Serializable 1284 + public data class GetTopArtistsParams( 1285 + /** The maximum number of artists to return */ 1286 + public val limit: Int? = null, 1287 + /** The offset for pagination */ 1288 + public val offset: Int? = null, 1289 + /** The start date to filter artists from (ISO 8601 format) */ 1290 + @SerialName("startDate") public val startDate: String? = null, 1291 + /** The end date to filter artists to (ISO 8601 format) */ 1292 + @SerialName("endDate") public val endDate: String? = null, 1293 + ) 1294 + 1295 + @Serializable 1296 + public data class GetTopTracksOutput( 1297 + public val tracks: List<SongViewBasic>? = null, 1298 + ) 1299 + 1300 + @Serializable 1301 + public data class GetTopTracksParams( 1302 + /** The maximum number of tracks to return */ 1303 + public val limit: Int? = null, 1304 + /** The offset for pagination */ 1305 + public val offset: Int? = null, 1306 + /** The start date to filter tracks from (ISO 8601 format) */ 1307 + @SerialName("startDate") public val startDate: String? = null, 1308 + /** The end date to filter tracks to (ISO 8601 format) */ 1309 + @SerialName("endDate") public val endDate: String? = null, 1310 + ) 1311 + 1312 + @Serializable 1313 + public data class GetTrackShoutsOutput( 1314 + public val shouts: List<JsonElement>? = null, 1315 + ) 1316 + 1317 + @Serializable 1318 + public data class GetTrackShoutsParams( 1319 + /** The URI of the track to retrieve shouts for */ 1320 + public val uri: String, 1321 + ) 1322 + 1323 + @Serializable 1324 + public data class GetWrappedParams( 1325 + /** The DID or handle of the user */ 1326 + public val did: String, 1327 + /** The year to get wrapped stats for (defaults to current year) */ 1328 + public val year: Int? = null, 1329 + ) 1330 + 1331 + @Serializable 1332 + public data class GoogledriveFileListView( 1333 + public val files: List<GoogledriveFileView>? = null, 1334 + ) 1335 + 1336 + @Serializable 1337 + public data class GoogledriveFileView( 1338 + /** The unique identifier of the file. */ 1339 + public val id: String? = null, 1340 + ) 1341 + 1342 + /** indicates that a handle or DID could not be resolved */ 1343 + @Serializable 1344 + public data class GraphNotFoundActor( 1345 + public val actor: String, 1346 + @SerialName("notFound") public val notFound: Boolean, 1347 + ) 1348 + 1349 + @Serializable 1350 + public data class GraphRelationship( 1351 + public val did: String, 1352 + /** if the actor follows this DID, this is the AT-URI of the follow record */ 1353 + public val following: String? = null, 1354 + /** if the actor is followed by this DID, contains the AT-URI of the follow record */ 1355 + @SerialName("followedBy") public val followedBy: String? = null, 1356 + ) 1357 + 1358 + @Serializable 1359 + public data class InsertDirectoryParams( 1360 + /** The URI of the playlist to start */ 1361 + public val uri: String, 1362 + /** The directory (id) to insert into the playlist */ 1363 + public val directory: String, 1364 + /** The position in the playlist to insert the directory at, if not specified, the directory will be appended */ 1365 + public val position: Int? = null, 1366 + ) 1367 + 1368 + @Serializable 1369 + public data class InsertFilesParams( 1370 + /** The URI of the playlist to start */ 1371 + public val uri: String, 1372 + public val files: List<String>, 1373 + /** The position in the playlist to insert the files at, if not specified, files will be appended */ 1374 + public val position: Int? = null, 1375 + ) 1376 + 1377 + @Serializable 1378 + public data class LikeRecord( 1379 + /** The date when the like was created. */ 1380 + @SerialName("createdAt") public val createdAt: String, 1381 + public val subject: StrongRef, 1382 + ) 1383 + 1384 + @Serializable 1385 + public data class LikeShoutInput( 1386 + /** The unique identifier of the shout to like */ 1387 + public val uri: String? = null, 1388 + ) 1389 + 1390 + @Serializable 1391 + public data class LikeSongInput( 1392 + /** The unique identifier of the song to like */ 1393 + public val uri: String? = null, 1394 + ) 1395 + 1396 + @Serializable 1397 + public data class MatchSongParams( 1398 + /** The title of the song to retrieve */ 1399 + public val title: String, 1400 + /** The artist of the song to retrieve */ 1401 + public val artist: String, 1402 + /** Optional MusicBrainz recording ID to anchor the match */ 1403 + @SerialName("mbId") public val mbId: String? = null, 1404 + /** Optional International Standard Recording Code (ISRC) to anchor the match */ 1405 + public val isrc: String? = null, 1406 + ) 1407 + 1408 + @Serializable 1409 + public data class MirrorSourceView( 1410 + /** One of: lastfm, listenbrainz, tealfm */ 1411 + public val provider: String, 1412 + /** Whether scrobbles from this source are being mirrored into Rocksky. */ 1413 + public val enabled: Boolean, 1414 + /** True when an API key is stored. Last.fm/ListenBrainz only; always false for Teal.fm. */ 1415 + @SerialName("hasCredentials") public val hasCredentials: Boolean, 1416 + /** Username on the external service (Last.fm / ListenBrainz). Null for Teal.fm. */ 1417 + @SerialName("externalUsername") public val externalUsername: String? = null, 1418 + /** The last time the mirror process successfully polled this source. */ 1419 + @SerialName("lastPolledAt") public val lastPolledAt: String? = null, 1420 + /** Watermark — scrobbles from the external service older than this are skipped. */ 1421 + @SerialName("lastScrobbleSeenAt") public val lastScrobbleSeenAt: String? = null, 1422 + ) 1423 + 1424 + @Serializable 1425 + public data class NextParams( 1426 + @SerialName("playerId") public val playerId: String? = null, 1427 + ) 1428 + 1429 + @Serializable 1430 + public data class PauseParams( 1431 + @SerialName("playerId") public val playerId: String? = null, 1432 + ) 1433 + 1434 + @Serializable 1435 + public data class PlayDirectoryParams( 1436 + @SerialName("directoryId") public val directoryId: String, 1437 + @SerialName("playerId") public val playerId: String? = null, 1438 + public val shuffle: Boolean? = null, 1439 + public val recurse: Boolean? = null, 1440 + public val position: Int? = null, 1441 + ) 1442 + 1443 + @Serializable 1444 + public data class PlayerCurrentlyPlayingViewDetailed( 1445 + /** The title of the currently playing track */ 1446 + public val title: String? = null, 1447 + ) 1448 + 1449 + @Serializable 1450 + public data class PlayerPlaybackQueueViewDetailed( 1451 + public val tracks: List<SongViewBasic>? = null, 1452 + ) 1453 + 1454 + @Serializable 1455 + public data class PlayFileParams( 1456 + @SerialName("fileId") public val fileId: String, 1457 + @SerialName("playerId") public val playerId: String? = null, 1458 + ) 1459 + 1460 + @Serializable 1461 + public data class PlaylistItemRecord( 1462 + public val subject: StrongRef, 1463 + /** The date the playlist was created. */ 1464 + @SerialName("createdAt") public val createdAt: String, 1465 + public val track: SongViewBasic, 1466 + /** The order of the item in the playlist. */ 1467 + public val order: Int, 1468 + ) 1469 + 1470 + @Serializable 1471 + public data class PlaylistRecord( 1472 + /** The name of the playlist. */ 1473 + public val name: String, 1474 + /** The date the playlist was created. */ 1475 + @SerialName("createdAt") public val createdAt: String, 1476 + /** The playlist description. */ 1477 + public val description: String? = null, 1478 + /** The picture of the playlist. */ 1479 + public val picture: BlobRef? = null, 1480 + /** The URL of the picture of the artist. */ 1481 + @SerialName("pictureUrl") public val pictureUrl: String? = null, 1482 + /** The Spotify link of the playlist. */ 1483 + @SerialName("spotifyLink") public val spotifyLink: String? = null, 1484 + /** The Tidal link of the playlist. */ 1485 + @SerialName("tidalLink") public val tidalLink: String? = null, 1486 + /** The YouTube link of the playlist. */ 1487 + @SerialName("youtubeLink") public val youtubeLink: String? = null, 1488 + /** The Apple Music link of the playlist. */ 1489 + @SerialName("appleMusicLink") public val appleMusicLink: String? = null, 1490 + ) 1491 + 1492 + /** Basic view of a playlist, including its metadata */ 1493 + @Serializable 1494 + public data class PlaylistViewBasic( 1495 + /** The unique identifier of the playlist. */ 1496 + public val id: String? = null, 1497 + /** The title of the playlist. */ 1498 + public val title: String? = null, 1499 + /** The URI of the playlist. */ 1500 + public val uri: String? = null, 1501 + /** The DID of the curator of the playlist. */ 1502 + @SerialName("curatorDid") public val curatorDid: String? = null, 1503 + /** The handle of the curator of the playlist. */ 1504 + @SerialName("curatorHandle") public val curatorHandle: String? = null, 1505 + /** The name of the curator of the playlist. */ 1506 + @SerialName("curatorName") public val curatorName: String? = null, 1507 + /** The URL of the avatar image of the curator. */ 1508 + @SerialName("curatorAvatarUrl") public val curatorAvatarUrl: String? = null, 1509 + /** A description of the playlist. */ 1510 + public val description: String? = null, 1511 + /** The URL of the cover image for the playlist. */ 1512 + @SerialName("coverImageUrl") public val coverImageUrl: String? = null, 1513 + /** The date and time when the playlist was created. */ 1514 + @SerialName("createdAt") public val createdAt: String? = null, 1515 + /** The number of tracks in the playlist. */ 1516 + @SerialName("trackCount") public val trackCount: Int? = null, 1517 + ) 1518 + 1519 + /** Detailed view of a playlist, including its tracks and metadata */ 1520 + @Serializable 1521 + public data class PlaylistViewDetailed( 1522 + /** The unique identifier of the playlist. */ 1523 + public val id: String? = null, 1524 + /** The title of the playlist. */ 1525 + public val title: String? = null, 1526 + /** The URI of the playlist. */ 1527 + public val uri: String? = null, 1528 + /** The DID of the curator of the playlist. */ 1529 + @SerialName("curatorDid") public val curatorDid: String? = null, 1530 + /** The handle of the curator of the playlist. */ 1531 + @SerialName("curatorHandle") public val curatorHandle: String? = null, 1532 + /** The name of the curator of the playlist. */ 1533 + @SerialName("curatorName") public val curatorName: String? = null, 1534 + /** The URL of the avatar image of the curator. */ 1535 + @SerialName("curatorAvatarUrl") public val curatorAvatarUrl: String? = null, 1536 + /** A description of the playlist. */ 1537 + public val description: String? = null, 1538 + /** The URL of the cover image for the playlist. */ 1539 + @SerialName("coverImageUrl") public val coverImageUrl: String? = null, 1540 + /** The date and time when the playlist was created. */ 1541 + @SerialName("createdAt") public val createdAt: String? = null, 1542 + /** A list of tracks in the playlist. */ 1543 + public val tracks: List<SongViewBasic>? = null, 1544 + ) 1545 + 1546 + @Serializable 1547 + public data class PlayParams( 1548 + @SerialName("playerId") public val playerId: String? = null, 1549 + ) 1550 + 1551 + @Serializable 1552 + public data class PreviousParams( 1553 + @SerialName("playerId") public val playerId: String? = null, 1554 + ) 1555 + 1556 + @Serializable 1557 + public data class ProfileRecord( 1558 + @SerialName("displayName") public val displayName: String? = null, 1559 + /** Free-form profile description text. */ 1560 + public val description: String? = null, 1561 + /** Small image to be displayed next to posts from account. AKA, 'profile picture' */ 1562 + public val avatar: BlobRef? = null, 1563 + /** Larger horizontal image to display behind profile view. */ 1564 + public val banner: BlobRef? = null, 1565 + /** Self-label values, specific to the Bluesky application, on the overall account. */ 1566 + public val labels: JsonElement? = null, 1567 + @SerialName("joinedViaStarterPack") public val joinedViaStarterPack: StrongRef? = null, 1568 + @SerialName("createdAt") public val createdAt: String? = null, 1569 + ) 1570 + 1571 + @Serializable 1572 + public data class PutMirrorSourceInput( 1573 + /** One of: lastfm, listenbrainz, tealfm */ 1574 + public val provider: String, 1575 + /** Enable or disable mirroring for this provider. */ 1576 + public val enabled: Boolean? = null, 1577 + /** External username (Last.fm / ListenBrainz). Required when enabling those providers. Ignored for Teal.fm. */ 1578 + @SerialName("externalUsername") public val externalUsername: String? = null, 1579 + /** API key / token to be encrypted at rest. Omit to leave the existing key unchanged. Pass an empty string to clear it. */ 1580 + @SerialName("apiKey") public val apiKey: String? = null, 1581 + ) 1582 + 1583 + @Serializable 1584 + public data class RadioRecord( 1585 + /** The name of the radio station. */ 1586 + public val name: String, 1587 + /** The URL of the radio station. */ 1588 + public val url: String, 1589 + /** The date when the radio station was created. */ 1590 + @SerialName("createdAt") public val createdAt: String, 1591 + /** A description of the radio station. */ 1592 + public val description: String? = null, 1593 + /** The genre of the radio station. */ 1594 + public val genre: String? = null, 1595 + /** The logo of the radio station. */ 1596 + public val logo: BlobRef? = null, 1597 + /** The website of the radio station. */ 1598 + public val website: String? = null, 1599 + ) 1600 + 1601 + @Serializable 1602 + public data class RadioViewBasic( 1603 + /** The unique identifier of the radio. */ 1604 + public val id: String? = null, 1605 + /** The name of the radio. */ 1606 + public val name: String? = null, 1607 + /** A brief description of the radio. */ 1608 + public val description: String? = null, 1609 + /** The date and time when the radio was created. */ 1610 + @SerialName("createdAt") public val createdAt: String? = null, 1611 + ) 1612 + 1613 + @Serializable 1614 + public data class RadioViewDetailed( 1615 + /** The unique identifier of the radio. */ 1616 + public val id: String? = null, 1617 + /** The name of the radio. */ 1618 + public val name: String? = null, 1619 + /** A brief description of the radio. */ 1620 + public val description: String? = null, 1621 + /** The website of the radio. */ 1622 + public val website: String? = null, 1623 + /** The streaming URL of the radio. */ 1624 + public val url: String? = null, 1625 + /** The genre of the radio. */ 1626 + public val genre: String? = null, 1627 + /** The logo of the radio station. */ 1628 + public val logo: String? = null, 1629 + /** The date and time when the radio was created. */ 1630 + @SerialName("createdAt") public val createdAt: String? = null, 1631 + ) 1632 + 1633 + @Serializable 1634 + public data class RemoveApikeyParams( 1635 + /** The ID of the API key to remove. */ 1636 + public val id: String, 1637 + ) 1638 + 1639 + @Serializable 1640 + public data class RemovePlaylistParams( 1641 + /** The URI of the playlist to remove */ 1642 + public val uri: String, 1643 + ) 1644 + 1645 + @Serializable 1646 + public data class RemoveShoutParams( 1647 + /** The ID of the shout to be removed */ 1648 + public val id: String, 1649 + ) 1650 + 1651 + @Serializable 1652 + public data class RemoveTrackParams( 1653 + /** The URI of the playlist to remove the track from */ 1654 + public val uri: String, 1655 + /** The position of the track to remove in the playlist */ 1656 + public val position: Int, 1657 + ) 1658 + 1659 + @Serializable 1660 + public data class ReplyShoutInput( 1661 + /** The unique identifier of the shout to reply to */ 1662 + @SerialName("shoutId") public val shoutId: String, 1663 + /** The content of the reply */ 1664 + public val message: String, 1665 + ) 1666 + 1667 + @Serializable 1668 + public data class ReportShoutInput( 1669 + /** The unique identifier of the shout to report */ 1670 + @SerialName("shoutId") public val shoutId: String, 1671 + /** The reason for reporting the shout */ 1672 + public val reason: String? = null, 1673 + ) 1674 + 1675 + @Serializable 1676 + public data class ScrobbleFirstScrobbleView( 1677 + /** The handle of the user who first scrobbled this song. */ 1678 + public val handle: String? = null, 1679 + /** The avatar URL of the user who first scrobbled this song. */ 1680 + public val avatar: String? = null, 1681 + /** The timestamp of the first scrobble. */ 1682 + public val timestamp: String? = null, 1683 + ) 1684 + 1685 + @Serializable 1686 + public data class ScrobbleRecord( 1687 + /** The title of the song. */ 1688 + public val title: String, 1689 + /** The artist of the song. */ 1690 + public val artist: String, 1691 + /** The album artist of the song. */ 1692 + @SerialName("albumArtist") public val albumArtist: String, 1693 + /** The album of the song. */ 1694 + public val album: String, 1695 + /** The duration of the song in milliseconds. */ 1696 + public val duration: Int, 1697 + /** The date when the song was created. */ 1698 + @SerialName("createdAt") public val createdAt: String, 1699 + /** The artists of the song with MusicBrainz IDs. */ 1700 + public val artists: List<ArtistMbid>? = null, 1701 + /** The track number of the song in the album. */ 1702 + @SerialName("trackNumber") public val trackNumber: Int? = null, 1703 + /** The disc number of the song in the album. */ 1704 + @SerialName("discNumber") public val discNumber: Int? = null, 1705 + /** The release date of the song. */ 1706 + @SerialName("releaseDate") public val releaseDate: String? = null, 1707 + /** The year the song was released. */ 1708 + public val year: Int? = null, 1709 + /** The genre of the song. */ 1710 + public val genre: String? = null, 1711 + /** The tags of the song. */ 1712 + public val tags: List<String>? = null, 1713 + /** The composer of the song. */ 1714 + public val composer: String? = null, 1715 + /** The lyrics of the song. */ 1716 + public val lyrics: String? = null, 1717 + /** The copyright message of the song. */ 1718 + @SerialName("copyrightMessage") public val copyrightMessage: String? = null, 1719 + /** Informations about the song */ 1720 + public val wiki: String? = null, 1721 + /** The album art of the song. */ 1722 + @SerialName("albumArt") public val albumArt: BlobRef? = null, 1723 + /** The URL of the album art of the song. */ 1724 + @SerialName("albumArtUrl") public val albumArtUrl: String? = null, 1725 + /** The YouTube link of the song. */ 1726 + @SerialName("youtubeLink") public val youtubeLink: String? = null, 1727 + /** The Spotify link of the song. */ 1728 + @SerialName("spotifyLink") public val spotifyLink: String? = null, 1729 + /** The Tidal link of the song. */ 1730 + @SerialName("tidalLink") public val tidalLink: String? = null, 1731 + /** The Apple Music link of the song. */ 1732 + @SerialName("appleMusicLink") public val appleMusicLink: String? = null, 1733 + /** The MusicBrainz ID of the song. */ 1734 + public val mbid: String? = null, 1735 + /** The label of the song. */ 1736 + public val label: String? = null, 1737 + /** The International Standard Recording Code (ISRC) of the song. */ 1738 + public val isrc: String? = null, 1739 + ) 1740 + 1741 + @Serializable 1742 + public data class ScrobbleViewBasic( 1743 + /** The unique identifier of the scrobble. */ 1744 + public val id: String? = null, 1745 + /** The handle of the user who created the scrobble. */ 1746 + public val user: String? = null, 1747 + /** The display name of the user who created the scrobble. */ 1748 + @SerialName("userDisplayName") public val userDisplayName: String? = null, 1749 + /** The avatar URL of the user who created the scrobble. */ 1750 + @SerialName("userAvatar") public val userAvatar: String? = null, 1751 + /** The title of the scrobble. */ 1752 + public val title: String? = null, 1753 + /** The artist of the song. */ 1754 + public val artist: String? = null, 1755 + /** The URI of the artist. */ 1756 + @SerialName("artistUri") public val artistUri: String? = null, 1757 + /** The album of the song. */ 1758 + public val album: String? = null, 1759 + /** The URI of the album. */ 1760 + @SerialName("albumUri") public val albumUri: String? = null, 1761 + /** The album art URL of the song. */ 1762 + public val cover: String? = null, 1763 + /** The timestamp when the scrobble was created. */ 1764 + public val date: String? = null, 1765 + /** The URI of the scrobble. */ 1766 + public val uri: String? = null, 1767 + /** The SHA256 hash of the scrobble data. */ 1768 + public val sha256: String? = null, 1769 + public val liked: Boolean? = null, 1770 + @SerialName("likesCount") public val likesCount: Int? = null, 1771 + ) 1772 + 1773 + @Serializable 1774 + public data class ScrobbleViewDetailed( 1775 + /** The unique identifier of the scrobble. */ 1776 + public val id: String? = null, 1777 + /** The handle of the user who created the scrobble. */ 1778 + public val user: String? = null, 1779 + /** The title of the scrobble. */ 1780 + public val title: String? = null, 1781 + /** The artist of the song. */ 1782 + public val artist: String? = null, 1783 + /** The URI of the artist. */ 1784 + @SerialName("artistUri") public val artistUri: String? = null, 1785 + /** The album of the song. */ 1786 + public val album: String? = null, 1787 + /** The URI of the album. */ 1788 + @SerialName("albumUri") public val albumUri: String? = null, 1789 + /** The album art URL of the song. */ 1790 + public val cover: String? = null, 1791 + /** The timestamp when the scrobble was created. */ 1792 + public val date: String? = null, 1793 + /** The URI of the scrobble. */ 1794 + public val uri: String? = null, 1795 + /** The SHA256 hash of the scrobble data. */ 1796 + public val sha256: String? = null, 1797 + public val liked: Boolean? = null, 1798 + @SerialName("likesCount") public val likesCount: Int? = null, 1799 + /** The number of listeners */ 1800 + public val listeners: Int? = null, 1801 + /** The number of scrobbles for this song */ 1802 + public val scrobbles: Int? = null, 1803 + public val artists: List<ArtistViewBasic>? = null, 1804 + /** The first scrobble of this song on Rocksky. */ 1805 + @SerialName("firstScrobble") public val firstScrobble: ScrobbleFirstScrobbleView? = null, 1806 + ) 1807 + 1808 + @Serializable 1809 + public data class SearchParams( 1810 + /** The search query string */ 1811 + public val query: String, 1812 + ) 1813 + 1814 + @Serializable 1815 + public data class SeekParams( 1816 + /** The position in seconds to seek to */ 1817 + public val position: Int, 1818 + @SerialName("playerId") public val playerId: String? = null, 1819 + ) 1820 + 1821 + @Serializable 1822 + public data class ShoutAuthor( 1823 + /** The unique identifier of the author. */ 1824 + public val id: String? = null, 1825 + /** The decentralized identifier (DID) of the author. */ 1826 + public val did: String? = null, 1827 + /** The handle of the author. */ 1828 + public val handle: String? = null, 1829 + /** The display name of the author. */ 1830 + @SerialName("displayName") public val displayName: String? = null, 1831 + /** The URL of the author's avatar image. */ 1832 + public val avatar: String? = null, 1833 + ) 1834 + 1835 + @Serializable 1836 + public data class ShoutRecord( 1837 + /** The message of the shout. */ 1838 + public val message: String, 1839 + /** The date when the shout was created. */ 1840 + @SerialName("createdAt") public val createdAt: String, 1841 + public val subject: StrongRef, 1842 + public val parent: StrongRef? = null, 1843 + ) 1844 + 1845 + @Serializable 1846 + public data class ShoutView( 1847 + /** The unique identifier of the shout. */ 1848 + public val id: String? = null, 1849 + /** The content of the shout. */ 1850 + public val message: String? = null, 1851 + /** The ID of the parent shout if this is a reply, otherwise null. */ 1852 + public val parent: String? = null, 1853 + /** The date and time when the shout was created. */ 1854 + @SerialName("createdAt") public val createdAt: String? = null, 1855 + /** The author of the shout. */ 1856 + public val author: ShoutAuthor? = null, 1857 + ) 1858 + 1859 + @Serializable 1860 + public data class SongFirstScrobbleView( 1861 + /** The handle of the user who first scrobbled this song. */ 1862 + public val handle: String? = null, 1863 + /** The avatar URL of the user who first scrobbled this song. */ 1864 + public val avatar: String? = null, 1865 + /** The timestamp of the first scrobble. */ 1866 + public val timestamp: String? = null, 1867 + ) 1868 + 1869 + @Serializable 1870 + public data class SongRecentListenerView( 1871 + /** The unique identifier of the listener. */ 1872 + public val id: String? = null, 1873 + /** The DID of the listener. */ 1874 + public val did: String? = null, 1875 + /** The handle of the listener. */ 1876 + public val handle: String? = null, 1877 + /** The display name of the listener. */ 1878 + @SerialName("displayName") public val displayName: String? = null, 1879 + /** The URL of the listener's avatar image. */ 1880 + public val avatar: String? = null, 1881 + /** The timestamp of the listener's most recent scrobble of this song. */ 1882 + public val timestamp: String? = null, 1883 + /** The URI of the listener's most recent scrobble of this song. */ 1884 + @SerialName("scrobbleUri") public val scrobbleUri: String? = null, 1885 + ) 1886 + 1887 + @Serializable 1888 + public data class SongRecord( 1889 + /** The title of the song. */ 1890 + public val title: String, 1891 + /** The artist of the song. */ 1892 + public val artist: String, 1893 + /** The album artist of the song. */ 1894 + @SerialName("albumArtist") public val albumArtist: String, 1895 + /** The album of the song. */ 1896 + public val album: String, 1897 + /** The duration of the song in milliseconds. */ 1898 + public val duration: Int, 1899 + /** The date when the song was created. */ 1900 + @SerialName("createdAt") public val createdAt: String, 1901 + /** The artists of the song with MusicBrainz IDs. */ 1902 + public val artists: List<ArtistMbid>? = null, 1903 + /** The track number of the song in the album. */ 1904 + @SerialName("trackNumber") public val trackNumber: Int? = null, 1905 + /** The disc number of the song in the album. */ 1906 + @SerialName("discNumber") public val discNumber: Int? = null, 1907 + /** The release date of the song. */ 1908 + @SerialName("releaseDate") public val releaseDate: String? = null, 1909 + /** The year the song was released. */ 1910 + public val year: Int? = null, 1911 + /** The genre of the song. */ 1912 + public val genre: String? = null, 1913 + /** The tags of the song. */ 1914 + public val tags: List<String>? = null, 1915 + /** The composer of the song. */ 1916 + public val composer: String? = null, 1917 + /** The lyrics of the song. */ 1918 + public val lyrics: String? = null, 1919 + /** The copyright message of the song. */ 1920 + @SerialName("copyrightMessage") public val copyrightMessage: String? = null, 1921 + /** Informations about the song */ 1922 + public val wiki: String? = null, 1923 + /** The album art of the song. */ 1924 + @SerialName("albumArt") public val albumArt: BlobRef? = null, 1925 + /** The URL of the album art of the song. */ 1926 + @SerialName("albumArtUrl") public val albumArtUrl: String? = null, 1927 + /** The YouTube link of the song. */ 1928 + @SerialName("youtubeLink") public val youtubeLink: String? = null, 1929 + /** The Spotify link of the song. */ 1930 + @SerialName("spotifyLink") public val spotifyLink: String? = null, 1931 + /** The Tidal link of the song. */ 1932 + @SerialName("tidalLink") public val tidalLink: String? = null, 1933 + /** The Apple Music link of the song. */ 1934 + @SerialName("appleMusicLink") public val appleMusicLink: String? = null, 1935 + /** The MusicBrainz ID of the song. */ 1936 + public val mbid: String? = null, 1937 + /** The label of the song. */ 1938 + public val label: String? = null, 1939 + /** The International Standard Recording Code (ISRC) of the song. */ 1940 + public val isrc: String? = null, 1941 + ) 1942 + 1943 + @Serializable 1944 + public data class SongViewBasic( 1945 + /** The unique identifier of the song. */ 1946 + public val id: String? = null, 1947 + /** The title of the song. */ 1948 + public val title: String? = null, 1949 + /** The artist of the song. */ 1950 + public val artist: String? = null, 1951 + /** The artist of the album the song belongs to. */ 1952 + @SerialName("albumArtist") public val albumArtist: String? = null, 1953 + /** The URL of the album art image. */ 1954 + @SerialName("albumArt") public val albumArt: String? = null, 1955 + /** The URI of the song. */ 1956 + public val uri: String? = null, 1957 + /** The album of the song. */ 1958 + public val album: String? = null, 1959 + /** The duration of the song in milliseconds. */ 1960 + public val duration: Int? = null, 1961 + /** The track number of the song in the album. */ 1962 + @SerialName("trackNumber") public val trackNumber: Int? = null, 1963 + /** The disc number of the song in the album. */ 1964 + @SerialName("discNumber") public val discNumber: Int? = null, 1965 + /** The number of times the song has been played. */ 1966 + @SerialName("playCount") public val playCount: Int? = null, 1967 + /** The number of unique listeners who have played the song. */ 1968 + @SerialName("uniqueListeners") public val uniqueListeners: Int? = null, 1969 + /** The URI of the album the song belongs to. */ 1970 + @SerialName("albumUri") public val albumUri: String? = null, 1971 + /** The URI of the artist of the song. */ 1972 + @SerialName("artistUri") public val artistUri: String? = null, 1973 + /** The SHA256 hash of the song. */ 1974 + public val sha256: String? = null, 1975 + /** The MusicBrainz ID of the song. */ 1976 + public val mbid: String? = null, 1977 + /** The International Standard Recording Code (ISRC) of the song. */ 1978 + public val isrc: String? = null, 1979 + public val tags: List<String>? = null, 1980 + /** The timestamp when the song was created. */ 1981 + @SerialName("createdAt") public val createdAt: String? = null, 1982 + ) 1983 + 1984 + @Serializable 1985 + public data class SongViewDetailed( 1986 + /** The unique identifier of the song. */ 1987 + public val id: String? = null, 1988 + /** The title of the song. */ 1989 + public val title: String? = null, 1990 + /** The artist of the song. */ 1991 + public val artist: String? = null, 1992 + /** The artist of the album the song belongs to. */ 1993 + @SerialName("albumArtist") public val albumArtist: String? = null, 1994 + /** The URL of the album art image. */ 1995 + @SerialName("albumArt") public val albumArt: String? = null, 1996 + /** The URI of the song. */ 1997 + public val uri: String? = null, 1998 + /** The album of the song. */ 1999 + public val album: String? = null, 2000 + /** The duration of the song in milliseconds. */ 2001 + public val duration: Int? = null, 2002 + /** The track number of the song in the album. */ 2003 + @SerialName("trackNumber") public val trackNumber: Int? = null, 2004 + /** The disc number of the song in the album. */ 2005 + @SerialName("discNumber") public val discNumber: Int? = null, 2006 + /** The number of times the song has been played. */ 2007 + @SerialName("playCount") public val playCount: Int? = null, 2008 + /** The number of unique listeners who have played the song. */ 2009 + @SerialName("uniqueListeners") public val uniqueListeners: Int? = null, 2010 + /** The URI of the album the song belongs to. */ 2011 + @SerialName("albumUri") public val albumUri: String? = null, 2012 + /** The URI of the artist of the song. */ 2013 + @SerialName("artistUri") public val artistUri: String? = null, 2014 + /** The SHA256 hash of the song. */ 2015 + public val sha256: String? = null, 2016 + /** The MusicBrainz ID of the song. */ 2017 + public val mbid: String? = null, 2018 + /** The International Standard Recording Code (ISRC) of the song. */ 2019 + public val isrc: String? = null, 2020 + public val tags: List<String>? = null, 2021 + /** The timestamp when the song was created. */ 2022 + @SerialName("createdAt") public val createdAt: String? = null, 2023 + public val artists: List<ArtistViewBasic>? = null, 2024 + /** The first scrobble of this song on Rocksky. */ 2025 + @SerialName("firstScrobble") public val firstScrobble: SongFirstScrobbleView? = null, 2026 + ) 2027 + 2028 + @Serializable 2029 + public data class SpotifyTrackView( 2030 + /** The unique identifier of the Spotify track. */ 2031 + public val id: String? = null, 2032 + /** The name of the track. */ 2033 + public val name: String? = null, 2034 + /** The name of the artist. */ 2035 + public val artist: String? = null, 2036 + /** The name of the album. */ 2037 + public val album: String? = null, 2038 + /** The duration of the track in milliseconds. */ 2039 + public val duration: Int? = null, 2040 + /** A URL to a preview of the track. */ 2041 + @SerialName("previewUrl") public val previewUrl: String? = null, 2042 + ) 2043 + 2044 + @Serializable 2045 + public data class StartPlaylistParams( 2046 + /** The URI of the playlist to start */ 2047 + public val uri: String, 2048 + /** Whether to shuffle the playlist when starting it */ 2049 + public val shuffle: Boolean? = null, 2050 + /** The position in the playlist to start from, if not specified, starts from the beginning */ 2051 + public val position: Int? = null, 2052 + ) 2053 + 2054 + @Serializable 2055 + public data class StatsView( 2056 + /** The total number of scrobbles. */ 2057 + public val scrobbles: Int? = null, 2058 + /** The total number of unique artists scrobbled. */ 2059 + public val artists: Int? = null, 2060 + /** The total number of tracks marked as loved. */ 2061 + @SerialName("lovedTracks") public val lovedTracks: Int? = null, 2062 + /** The total number of unique albums scrobbled. */ 2063 + public val albums: Int? = null, 2064 + /** The total number of unique tracks scrobbled. */ 2065 + public val tracks: Int? = null, 2066 + ) 2067 + 2068 + @Serializable 2069 + public data class StatsWrappedAlbum( 2070 + /** The unique identifier of the album. */ 2071 + public val id: String? = null, 2072 + /** The title of the album. */ 2073 + public val title: String? = null, 2074 + /** The artist of the album. */ 2075 + public val artist: String? = null, 2076 + /** The album art URL. */ 2077 + @SerialName("albumArt") public val albumArt: String? = null, 2078 + /** The AT-URI of the album. */ 2079 + public val uri: String? = null, 2080 + /** Number of plays in the wrapped period. */ 2081 + @SerialName("playCount") public val playCount: Int? = null, 2082 + ) 2083 + 2084 + @Serializable 2085 + public data class StatsWrappedArtist( 2086 + /** The unique identifier of the artist. */ 2087 + public val id: String? = null, 2088 + /** The name of the artist. */ 2089 + public val name: String? = null, 2090 + /** The picture URL of the artist. */ 2091 + public val picture: String? = null, 2092 + /** The AT-URI of the artist. */ 2093 + public val uri: String? = null, 2094 + /** Number of plays in the wrapped period. */ 2095 + @SerialName("playCount") public val playCount: Int? = null, 2096 + ) 2097 + 2098 + @Serializable 2099 + public data class StatsWrappedDayCount( 2100 + /** The date (YYYY-MM-DD). */ 2101 + public val date: String? = null, 2102 + /** Number of scrobbles on this day. */ 2103 + public val count: Int? = null, 2104 + ) 2105 + 2106 + @Serializable 2107 + public data class StatsWrappedGenreCount( 2108 + /** The genre name. */ 2109 + public val genre: String? = null, 2110 + /** Number of scrobbles for this genre. */ 2111 + public val count: Int? = null, 2112 + ) 2113 + 2114 + @Serializable 2115 + public data class StatsWrappedMilestone( 2116 + /** The title of the track. */ 2117 + @SerialName("trackTitle") public val trackTitle: String? = null, 2118 + /** The name of the artist. */ 2119 + @SerialName("artistName") public val artistName: String? = null, 2120 + /** The timestamp of the scrobble. */ 2121 + public val timestamp: String? = null, 2122 + /** AT-URI of the track record, used to build a clickable link to the song page. */ 2123 + @SerialName("trackUri") public val trackUri: String? = null, 2124 + ) 2125 + 2126 + @Serializable 2127 + public data class StatsWrappedMonthCount( 2128 + /** Month number (1-12). */ 2129 + public val month: Int? = null, 2130 + /** Number of scrobbles in this month. */ 2131 + public val count: Int? = null, 2132 + ) 2133 + 2134 + @Serializable 2135 + public data class StatsWrappedTrack( 2136 + /** The unique identifier of the track. */ 2137 + public val id: String? = null, 2138 + /** The title of the track. */ 2139 + public val title: String? = null, 2140 + /** The artist of the track. */ 2141 + public val artist: String? = null, 2142 + /** The album art URL. */ 2143 + @SerialName("albumArt") public val albumArt: String? = null, 2144 + /** The AT-URI of the track. */ 2145 + public val uri: String? = null, 2146 + /** The AT-URI of the artist. */ 2147 + @SerialName("artistUri") public val artistUri: String? = null, 2148 + /** The AT-URI of the album. */ 2149 + @SerialName("albumUri") public val albumUri: String? = null, 2150 + /** Number of plays in the wrapped period. */ 2151 + @SerialName("playCount") public val playCount: Int? = null, 2152 + ) 2153 + 2154 + @Serializable 2155 + public data class StatsWrappedView( 2156 + /** The year of the wrapped stats. */ 2157 + public val year: Int? = null, 2158 + /** Total scrobbles in the year. */ 2159 + @SerialName("totalScrobbles") public val totalScrobbles: Int? = null, 2160 + /** Total listening time in minutes. */ 2161 + @SerialName("totalListeningTimeMinutes") public val totalListeningTimeMinutes: Int? = null, 2162 + /** Top 5 artists by play count. */ 2163 + @SerialName("topArtists") public val topArtists: List<StatsWrappedArtist>? = null, 2164 + /** Top 5 tracks by play count. */ 2165 + @SerialName("topTracks") public val topTracks: List<StatsWrappedTrack>? = null, 2166 + /** Top 5 albums by play count. */ 2167 + @SerialName("topAlbums") public val topAlbums: List<StatsWrappedAlbum>? = null, 2168 + /** Top genres by play count. */ 2169 + @SerialName("topGenres") public val topGenres: List<StatsWrappedGenreCount>? = null, 2170 + /** Scrobble counts per month. */ 2171 + @SerialName("scrobblesPerMonth") public val scrobblesPerMonth: List<StatsWrappedMonthCount>? = null, 2172 + /** The most active day of the year. */ 2173 + @SerialName("mostActiveDay") public val mostActiveDay: StatsWrappedDayCount? = null, 2174 + /** The most active hour of the day (0-23). */ 2175 + @SerialName("mostActiveHour") public val mostActiveHour: Int? = null, 2176 + /** Number of artists heard for the first time this year. */ 2177 + @SerialName("newArtistsCount") public val newArtistsCount: Int? = null, 2178 + /** Longest consecutive days streak. */ 2179 + @SerialName("longestStreak") public val longestStreak: Int? = null, 2180 + /** The first scrobble of the year. */ 2181 + @SerialName("firstScrobble") public val firstScrobble: StatsWrappedMilestone? = null, 2182 + /** The last scrobble of the year. */ 2183 + @SerialName("lastScrobble") public val lastScrobble: StatsWrappedMilestone? = null, 2184 + ) 2185 + 2186 + @Serializable 2187 + public data class StatusRecord( 2188 + /** The track currently being played. */ 2189 + public val track: ActorTrackView, 2190 + /** When the track started playing. */ 2191 + @SerialName("startedAt") public val startedAt: String, 2192 + /** When the status expires. Defaults to startedAt plus track duration plus idle time. */ 2193 + @SerialName("expiresAt") public val expiresAt: String? = null, 2194 + ) 2195 + 2196 + @Serializable 2197 + public data class StrongRef( 2198 + public val uri: String, 2199 + public val cid: String, 2200 + ) 2201 + 2202 + @Serializable 2203 + public data class UnfollowAccountOutput( 2204 + public val subject: ActorProfileViewBasic, 2205 + public val followers: List<ActorProfileViewBasic>, 2206 + /** A cursor value to pass to subsequent calls to get the next page of results. */ 2207 + public val cursor: String? = null, 2208 + ) 2209 + 2210 + @Serializable 2211 + public data class UnfollowAccountParams( 2212 + public val account: String, 2213 + ) 2214 + 2215 + @Serializable 2216 + public data class UpdateApikeyInput( 2217 + /** The ID of the API key to update. */ 2218 + public val id: String, 2219 + /** The new name of the API key. */ 2220 + public val name: String, 2221 + /** A new description for the API key. */ 2222 + public val description: String? = null, 2223 + )
+5
sdk/python/README.md
··· 207 207 208 208 `APIError` exposes `status_code`, `method`, `error`, `message`, and `body`. 209 209 210 + ## Types 211 + 212 + Public model types are derived from the [Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons) and live in `rocksky.gen.models` (Pydantic) and `rocksky.gen.types` (dataclasses). `rocksky.models` re-exports the Pydantic shapes under their historical SDK names. Regenerate with `bun run lexgen:types` at the repo root. 213 + 214 + 210 215 ## Testing your code against the SDK 211 216 212 217 Inject your own `httpx.AsyncClient` so you can mount a mock transport:
+1 -1
sdk/python/pyproject.toml
··· 1 1 [project] 2 2 name = "rocksky" 3 - version = "0.1.0" 3 + version = "0.2.0" 4 4 description = "Async Python SDK for the Rocksky XRPC API" 5 5 readme = "README.md" 6 6 license = { text = "MIT" }
+1 -1
sdk/python/src/rocksky/_version.py
··· 1 - __version__ = "0.1.0" 1 + __version__ = "0.2.0"
+1
sdk/python/src/rocksky/gen/__init__.py
··· 1 + from .types import * # noqa: F401,F403
+1650
sdk/python/src/rocksky/gen/models.py
··· 1 + """AUTO-GENERATED FILE -- DO NOT EDIT. 2 + 3 + Source: apps/api/lexicons/**/*.json 4 + Regenerate via: bun run lexgen:types 5 + """ 6 + from __future__ import annotations 7 + 8 + from datetime import datetime 9 + from typing import Any 10 + 11 + from pydantic import BaseModel, ConfigDict, Field 12 + 13 + 14 + def _camel(name: str) -> str: 15 + head, *tail = name.split("_") 16 + return head + "".join(part.title() for part in tail) 17 + 18 + 19 + class RockskyModel(BaseModel): 20 + """Base model used by every generated SDK type. 21 + 22 + Accepts both camelCase (alias) and snake_case (field name) input, preserves 23 + unknown fields ("extra=allow"), and never crashes on a missing key. 24 + """ 25 + 26 + model_config = ConfigDict( 27 + alias_generator=_camel, 28 + populate_by_name=True, 29 + extra="allow", 30 + str_strip_whitespace=True, 31 + ) 32 + 33 + 34 + class BlobRef(RockskyModel): 35 + """atproto blob reference shape.""" 36 + 37 + type: str | None = Field(default=None, alias="$type") 38 + ref: dict[str, Any] | None = None 39 + mime_type: str | None = None 40 + size: int | None = None 41 + 42 + 43 + 44 + class ActorArtistViewBasic(RockskyModel): 45 + id: str | None = None 46 + name: str | None = None 47 + picture: str | None = None 48 + uri: str | None = None 49 + user1_rank: int | None = Field(default=None, alias="user1Rank") 50 + user2_rank: int | None = Field(default=None, alias="user2Rank") 51 + weight: int | None = None 52 + 53 + 54 + class ActorCompatibilityViewBasic(RockskyModel): 55 + compatibility_level: int | None = Field(default=None, alias="compatibilityLevel") 56 + compatibility_percentage: int | None = Field(default=None, alias="compatibilityPercentage") 57 + shared_artists: int | None = Field(default=None, alias="sharedArtists") 58 + top_shared_artist_names: list[str] | None = Field(default=None, alias="topSharedArtistNames") 59 + top_shared_detailed_artists: list[ActorArtistViewBasic] | None = Field(default=None, alias="topSharedDetailedArtists") 60 + user1_artist_count: int | None = Field(default=None, alias="user1ArtistCount") 61 + user2_artist_count: int | None = Field(default=None, alias="user2ArtistCount") 62 + 63 + 64 + class ActorNeighbourViewBasic(RockskyModel): 65 + user_id: str | None = Field(default=None, alias="userId") 66 + did: str | None = None 67 + handle: str | None = None 68 + display_name: str | None = Field(default=None, alias="displayName") 69 + avatar: str | None = None 70 + shared_artists_count: int | None = Field(default=None, alias="sharedArtistsCount") 71 + similarity_score: int | None = Field(default=None, alias="similarityScore") 72 + top_shared_artist_names: list[str] | None = Field(default=None, alias="topSharedArtistNames") 73 + top_shared_artists_details: list[ArtistViewBasic] | None = Field(default=None, alias="topSharedArtistsDetails") 74 + 75 + 76 + class ActorProfileViewBasic(RockskyModel): 77 + id: str | None = None 78 + did: str | None = None 79 + handle: str | None = None 80 + display_name: str | None = Field(default=None, alias="displayName") 81 + avatar: str | None = None 82 + created_at: datetime | None = Field(default=None, alias="createdAt") 83 + updated_at: datetime | None = Field(default=None, alias="updatedAt") 84 + 85 + 86 + class ActorProfileViewDetailed(RockskyModel): 87 + id: str | None = None 88 + did: str | None = None 89 + handle: str | None = None 90 + display_name: str | None = Field(default=None, alias="displayName") 91 + avatar: str | None = None 92 + created_at: datetime | None = Field(default=None, alias="createdAt") 93 + updated_at: datetime | None = Field(default=None, alias="updatedAt") 94 + 95 + 96 + class ActorTrackView(RockskyModel): 97 + name: str | None = None 98 + artist: str | None = None 99 + album: str | None = None 100 + album_cover_url: str | None = Field(default=None, alias="albumCoverUrl") 101 + duration_ms: int | None = Field(default=None, alias="durationMs") 102 + source: str | None = None 103 + recording_mb_id: str | None = Field(default=None, alias="recordingMbId") 104 + 105 + 106 + class AddDirectoryToQueueParams(RockskyModel): 107 + player_id: str | None = Field(default=None, alias="playerId") 108 + directory: str | None = None 109 + position: int | None = None 110 + shuffle: bool | None = None 111 + 112 + 113 + class AddItemsToQueueParams(RockskyModel): 114 + player_id: str | None = Field(default=None, alias="playerId") 115 + items: list[str] | None = None 116 + position: int | None = None 117 + shuffle: bool | None = None 118 + 119 + 120 + class AlbumRecord(RockskyModel): 121 + title: str | None = None 122 + artist: str | None = None 123 + duration: int | None = None 124 + release_date: datetime | None = Field(default=None, alias="releaseDate") 125 + year: int | None = None 126 + genre: str | None = None 127 + album_art: BlobRef | None = Field(default=None, alias="albumArt") 128 + album_art_url: str | None = Field(default=None, alias="albumArtUrl") 129 + tags: list[str] | None = None 130 + youtube_link: str | None = Field(default=None, alias="youtubeLink") 131 + spotify_link: str | None = Field(default=None, alias="spotifyLink") 132 + tidal_link: str | None = Field(default=None, alias="tidalLink") 133 + apple_music_link: str | None = Field(default=None, alias="appleMusicLink") 134 + created_at: datetime | None = Field(default=None, alias="createdAt") 135 + 136 + 137 + class AlbumViewBasic(RockskyModel): 138 + id: str | None = None 139 + uri: str | None = None 140 + title: str | None = None 141 + artist: str | None = None 142 + artist_uri: str | None = Field(default=None, alias="artistUri") 143 + year: int | None = None 144 + album_art: str | None = Field(default=None, alias="albumArt") 145 + release_date: str | None = Field(default=None, alias="releaseDate") 146 + sha256: str | None = None 147 + play_count: int | None = Field(default=None, alias="playCount") 148 + unique_listeners: int | None = Field(default=None, alias="uniqueListeners") 149 + 150 + 151 + class AlbumViewDetailed(RockskyModel): 152 + id: str | None = None 153 + uri: str | None = None 154 + title: str | None = None 155 + artist: str | None = None 156 + artist_uri: str | None = Field(default=None, alias="artistUri") 157 + year: int | None = None 158 + album_art: str | None = Field(default=None, alias="albumArt") 159 + release_date: str | None = Field(default=None, alias="releaseDate") 160 + sha256: str | None = None 161 + play_count: int | None = Field(default=None, alias="playCount") 162 + unique_listeners: int | None = Field(default=None, alias="uniqueListeners") 163 + tags: list[str] | None = None 164 + tracks: list[SongViewBasic] | None = None 165 + 166 + 167 + class ApiKeyView(RockskyModel): 168 + id: str | None = None 169 + name: str | None = None 170 + description: str | None = None 171 + created_at: datetime | None = Field(default=None, alias="createdAt") 172 + 173 + 174 + class ArtistListenerViewBasic(RockskyModel): 175 + id: str | None = None 176 + did: str | None = None 177 + handle: str | None = None 178 + display_name: str | None = Field(default=None, alias="displayName") 179 + avatar: str | None = None 180 + most_listened_song: ArtistSongViewBasic | None = Field(default=None, alias="mostListenedSong") 181 + total_plays: int | None = Field(default=None, alias="totalPlays") 182 + rank: int | None = None 183 + 184 + 185 + class ArtistMbid(RockskyModel): 186 + mbid: str | None = None 187 + name: str | None = None 188 + 189 + 190 + class ArtistRecentListenerView(RockskyModel): 191 + id: str | None = None 192 + did: str | None = None 193 + handle: str | None = None 194 + display_name: str | None = Field(default=None, alias="displayName") 195 + avatar: str | None = None 196 + timestamp: datetime | None = None 197 + scrobble_uri: str | None = Field(default=None, alias="scrobbleUri") 198 + 199 + 200 + class ArtistRecord(RockskyModel): 201 + name: str | None = None 202 + bio: str | None = None 203 + picture: BlobRef | None = None 204 + picture_url: str | None = Field(default=None, alias="pictureUrl") 205 + tags: list[str] | None = None 206 + born: datetime | None = None 207 + died: datetime | None = None 208 + born_in: str | None = Field(default=None, alias="bornIn") 209 + created_at: datetime | None = Field(default=None, alias="createdAt") 210 + 211 + 212 + class ArtistSongViewBasic(RockskyModel): 213 + uri: str | None = None 214 + title: str | None = None 215 + play_count: int | None = Field(default=None, alias="playCount") 216 + 217 + 218 + class ArtistViewBasic(RockskyModel): 219 + id: str | None = None 220 + uri: str | None = None 221 + name: str | None = None 222 + picture: str | None = None 223 + sha256: str | None = None 224 + play_count: int | None = Field(default=None, alias="playCount") 225 + unique_listeners: int | None = Field(default=None, alias="uniqueListeners") 226 + tags: list[str] | None = None 227 + 228 + 229 + class ArtistViewDetailed(RockskyModel): 230 + id: str | None = None 231 + uri: str | None = None 232 + name: str | None = None 233 + picture: str | None = None 234 + sha256: str | None = None 235 + play_count: int | None = Field(default=None, alias="playCount") 236 + unique_listeners: int | None = Field(default=None, alias="uniqueListeners") 237 + tags: list[str] | None = None 238 + 239 + 240 + class ChartsScrobbleViewBasic(RockskyModel): 241 + date: datetime | None = None 242 + count: int | None = None 243 + 244 + 245 + class ChartsView(RockskyModel): 246 + scrobbles: list[ChartsScrobbleViewBasic] | None = None 247 + 248 + 249 + class CreateApikeyInput(RockskyModel): 250 + name: str | None = None 251 + description: str | None = None 252 + 253 + 254 + class CreatePlaylistParams(RockskyModel): 255 + name: str | None = None 256 + description: str | None = None 257 + 258 + 259 + class CreateScrobbleInput(RockskyModel): 260 + title: str | None = None 261 + artist: str | None = None 262 + album: str | None = None 263 + duration: int | None = None 264 + mb_id: str | None = Field(default=None, alias="mbId") 265 + isrc: str | None = None 266 + album_art: str | None = Field(default=None, alias="albumArt") 267 + track_number: int | None = Field(default=None, alias="trackNumber") 268 + release_date: str | None = Field(default=None, alias="releaseDate") 269 + year: int | None = None 270 + disc_number: int | None = Field(default=None, alias="discNumber") 271 + lyrics: str | None = None 272 + composer: str | None = None 273 + copyright_message: str | None = Field(default=None, alias="copyrightMessage") 274 + label: str | None = None 275 + artist_picture: str | None = Field(default=None, alias="artistPicture") 276 + spotify_link: str | None = Field(default=None, alias="spotifyLink") 277 + lastfm_link: str | None = Field(default=None, alias="lastfmLink") 278 + tidal_link: str | None = Field(default=None, alias="tidalLink") 279 + apple_music_link: str | None = Field(default=None, alias="appleMusicLink") 280 + youtube_link: str | None = Field(default=None, alias="youtubeLink") 281 + deezer_link: str | None = Field(default=None, alias="deezerLink") 282 + timestamp: int | None = None 283 + 284 + 285 + class CreateShoutInput(RockskyModel): 286 + message: str | None = None 287 + 288 + 289 + class CreateSongInput(RockskyModel): 290 + title: str | None = None 291 + artist: str | None = None 292 + album_artist: str | None = Field(default=None, alias="albumArtist") 293 + album: str | None = None 294 + duration: int | None = None 295 + mb_id: str | None = Field(default=None, alias="mbId") 296 + isrc: str | None = None 297 + album_art: str | None = Field(default=None, alias="albumArt") 298 + track_number: int | None = Field(default=None, alias="trackNumber") 299 + release_date: str | None = Field(default=None, alias="releaseDate") 300 + year: int | None = None 301 + disc_number: int | None = Field(default=None, alias="discNumber") 302 + lyrics: str | None = None 303 + 304 + 305 + class DescribeFeedGeneratorOutput(RockskyModel): 306 + did: str | None = None 307 + feeds: list[FeedUriView] | None = None 308 + 309 + 310 + class DescribeFeedGeneratorParams(RockskyModel): 311 + pass 312 + 313 + 314 + class DislikeShoutInput(RockskyModel): 315 + uri: str | None = None 316 + 317 + 318 + class DislikeSongInput(RockskyModel): 319 + uri: str | None = None 320 + 321 + 322 + class DownloadFileParams(RockskyModel): 323 + file_id: str | None = Field(default=None, alias="fileId") 324 + 325 + 326 + class DropboxFileListView(RockskyModel): 327 + files: list[DropboxFileView] | None = None 328 + 329 + 330 + class DropboxFileView(RockskyModel): 331 + id: str | None = None 332 + name: str | None = None 333 + path_lower: str | None = Field(default=None, alias="pathLower") 334 + path_display: str | None = Field(default=None, alias="pathDisplay") 335 + client_modified: datetime | None = Field(default=None, alias="clientModified") 336 + server_modified: datetime | None = Field(default=None, alias="serverModified") 337 + 338 + 339 + class DropboxTemporaryLinkView(RockskyModel): 340 + link: str | None = None 341 + 342 + 343 + class FeedGeneratorsView(RockskyModel): 344 + feeds: list[FeedGeneratorView] | None = None 345 + 346 + 347 + class FeedGeneratorView(RockskyModel): 348 + id: str | None = None 349 + name: str | None = None 350 + description: str | None = None 351 + uri: str | None = None 352 + avatar: str | None = None 353 + creator: ActorProfileViewBasic | None = None 354 + 355 + 356 + class FeedItemView(RockskyModel): 357 + scrobble: ScrobbleViewBasic | None = None 358 + 359 + 360 + class FeedRecommendationsView(RockskyModel): 361 + recommendations: list[FeedRecommendationView] | None = None 362 + cursor: str | None = None 363 + 364 + 365 + class FeedRecommendationView(RockskyModel): 366 + title: str | None = None 367 + artist: str | None = None 368 + album: str | None = None 369 + album_art: str | None = Field(default=None, alias="albumArt") 370 + track_uri: str | None = Field(default=None, alias="trackUri") 371 + artist_uri: str | None = Field(default=None, alias="artistUri") 372 + album_uri: str | None = Field(default=None, alias="albumUri") 373 + genres: list[str] | None = None 374 + recommendation_score: int | None = Field(default=None, alias="recommendationScore") 375 + source: str | None = None 376 + likes_count: int | None = Field(default=None, alias="likesCount") 377 + 378 + 379 + class FeedRecommendedAlbumsView(RockskyModel): 380 + albums: list[FeedRecommendedAlbumView] | None = None 381 + cursor: str | None = None 382 + 383 + 384 + class FeedRecommendedAlbumView(RockskyModel): 385 + id: str | None = None 386 + uri: str | None = None 387 + title: str | None = None 388 + artist: str | None = None 389 + artist_uri: str | None = Field(default=None, alias="artistUri") 390 + year: int | None = None 391 + album_art: str | None = Field(default=None, alias="albumArt") 392 + recommendation_score: int | None = Field(default=None, alias="recommendationScore") 393 + source: str | None = None 394 + 395 + 396 + class FeedRecommendedArtistsView(RockskyModel): 397 + artists: list[FeedRecommendedArtistView] | None = None 398 + cursor: str | None = None 399 + 400 + 401 + class FeedRecommendedArtistView(RockskyModel): 402 + id: str | None = None 403 + uri: str | None = None 404 + name: str | None = None 405 + picture: str | None = None 406 + genres: list[str] | None = None 407 + recommendation_score: int | None = Field(default=None, alias="recommendationScore") 408 + source: str | None = None 409 + 410 + 411 + class FeedSearchResultsView(RockskyModel): 412 + hits: list[SongViewBasic | AlbumViewBasic | ArtistViewBasic | PlaylistViewBasic | ActorProfileViewBasic] | None = None 413 + processing_time_ms: int | None = Field(default=None, alias="processingTimeMs") 414 + limit: int | None = None 415 + offset: int | None = None 416 + estimated_total_hits: int | None = Field(default=None, alias="estimatedTotalHits") 417 + 418 + 419 + class FeedStoriesView(RockskyModel): 420 + stories: list[FeedStoryView] | None = None 421 + 422 + 423 + class FeedStoryView(RockskyModel): 424 + album: str | None = None 425 + album_art: str | None = Field(default=None, alias="albumArt") 426 + album_artist: str | None = Field(default=None, alias="albumArtist") 427 + album_uri: str | None = Field(default=None, alias="albumUri") 428 + artist: str | None = None 429 + artist_uri: str | None = Field(default=None, alias="artistUri") 430 + avatar: str | None = None 431 + created_at: str | None = Field(default=None, alias="createdAt") 432 + did: str | None = None 433 + handle: str | None = None 434 + id: str | None = None 435 + title: str | None = None 436 + track_id: str | None = Field(default=None, alias="trackId") 437 + track_uri: str | None = Field(default=None, alias="trackUri") 438 + uri: str | None = None 439 + 440 + 441 + class FeedUriView(RockskyModel): 442 + uri: str | None = None 443 + 444 + 445 + class FeedView(RockskyModel): 446 + feed: list[FeedItemView] | None = None 447 + cursor: str | None = None 448 + 449 + 450 + class FollowAccountOutput(RockskyModel): 451 + subject: ActorProfileViewBasic | None = None 452 + followers: list[ActorProfileViewBasic] | None = None 453 + cursor: str | None = None 454 + 455 + 456 + class FollowAccountParams(RockskyModel): 457 + account: str | None = None 458 + 459 + 460 + class FollowRecord(RockskyModel): 461 + created_at: datetime | None = Field(default=None, alias="createdAt") 462 + subject: str | None = None 463 + via: StrongRef | None = None 464 + 465 + 466 + class GeneratorRecord(RockskyModel): 467 + did: str | None = None 468 + avatar: BlobRef | None = None 469 + display_name: str | None = Field(default=None, alias="displayName") 470 + description: str | None = None 471 + created_at: datetime | None = Field(default=None, alias="createdAt") 472 + 473 + 474 + class GetActorAlbumsOutput(RockskyModel): 475 + albums: list[AlbumViewBasic] | None = None 476 + 477 + 478 + class GetActorAlbumsParams(RockskyModel): 479 + did: str | None = None 480 + limit: int | None = None 481 + offset: int | None = None 482 + start_date: datetime | None = Field(default=None, alias="startDate") 483 + end_date: datetime | None = Field(default=None, alias="endDate") 484 + 485 + 486 + class GetActorArtistsOutput(RockskyModel): 487 + artists: list[ArtistViewBasic] | None = None 488 + 489 + 490 + class GetActorArtistsParams(RockskyModel): 491 + did: str | None = None 492 + limit: int | None = None 493 + offset: int | None = None 494 + start_date: datetime | None = Field(default=None, alias="startDate") 495 + end_date: datetime | None = Field(default=None, alias="endDate") 496 + 497 + 498 + class GetActorCompatibilityOutput(RockskyModel): 499 + compatibility: ActorCompatibilityViewBasic | None = None 500 + 501 + 502 + class GetActorCompatibilityParams(RockskyModel): 503 + did: str | None = None 504 + 505 + 506 + class GetActorLovedSongsOutput(RockskyModel): 507 + tracks: list[SongViewBasic] | None = None 508 + 509 + 510 + class GetActorLovedSongsParams(RockskyModel): 511 + did: str | None = None 512 + limit: int | None = None 513 + offset: int | None = None 514 + 515 + 516 + class GetActorNeighboursOutput(RockskyModel): 517 + neighbours: list[ActorNeighbourViewBasic] | None = None 518 + 519 + 520 + class GetActorNeighboursParams(RockskyModel): 521 + did: str | None = None 522 + 523 + 524 + class GetActorPlaylistsOutput(RockskyModel): 525 + playlists: list[PlaylistViewBasic] | None = None 526 + 527 + 528 + class GetActorPlaylistsParams(RockskyModel): 529 + did: str | None = None 530 + limit: int | None = None 531 + offset: int | None = None 532 + 533 + 534 + class GetActorScrobblesOutput(RockskyModel): 535 + scrobbles: list[ScrobbleViewBasic] | None = None 536 + 537 + 538 + class GetActorScrobblesParams(RockskyModel): 539 + did: str | None = None 540 + limit: int | None = None 541 + offset: int | None = None 542 + 543 + 544 + class GetActorSongsOutput(RockskyModel): 545 + songs: list[SongViewBasic] | None = None 546 + 547 + 548 + class GetActorSongsParams(RockskyModel): 549 + did: str | None = None 550 + limit: int | None = None 551 + offset: int | None = None 552 + start_date: datetime | None = Field(default=None, alias="startDate") 553 + end_date: datetime | None = Field(default=None, alias="endDate") 554 + 555 + 556 + class GetAlbumParams(RockskyModel): 557 + uri: str | None = None 558 + 559 + 560 + class GetAlbumRecommendationsParams(RockskyModel): 561 + did: str | None = None 562 + limit: int | None = None 563 + 564 + 565 + class GetAlbumShoutsOutput(RockskyModel): 566 + shouts: list[Any] | None = None 567 + 568 + 569 + class GetAlbumShoutsParams(RockskyModel): 570 + uri: str | None = None 571 + limit: int | None = None 572 + offset: int | None = None 573 + 574 + 575 + class GetAlbumsOutput(RockskyModel): 576 + albums: list[AlbumViewBasic] | None = None 577 + 578 + 579 + class GetAlbumsParams(RockskyModel): 580 + limit: int | None = None 581 + offset: int | None = None 582 + genre: str | None = None 583 + 584 + 585 + class GetAlbumTracksOutput(RockskyModel): 586 + tracks: list[SongViewBasic] | None = None 587 + 588 + 589 + class GetAlbumTracksParams(RockskyModel): 590 + uri: str | None = None 591 + 592 + 593 + class GetApikeysOutput(RockskyModel): 594 + api_keys: list[Any] | None = Field(default=None, alias="apiKeys") 595 + 596 + 597 + class GetApikeysParams(RockskyModel): 598 + offset: int | None = None 599 + limit: int | None = None 600 + 601 + 602 + class GetArtistAlbumsOutput(RockskyModel): 603 + albums: list[AlbumViewBasic] | None = None 604 + 605 + 606 + class GetArtistAlbumsParams(RockskyModel): 607 + uri: str | None = None 608 + 609 + 610 + class GetArtistListenersOutput(RockskyModel): 611 + listeners: list[ArtistListenerViewBasic] | None = None 612 + 613 + 614 + class GetArtistListenersParams(RockskyModel): 615 + uri: str | None = None 616 + offset: int | None = None 617 + limit: int | None = None 618 + 619 + 620 + class GetArtistParams(RockskyModel): 621 + uri: str | None = None 622 + 623 + 624 + class GetArtistRecentListenersOutput(RockskyModel): 625 + listeners: list[ArtistRecentListenerView] | None = None 626 + 627 + 628 + class GetArtistRecentListenersParams(RockskyModel): 629 + uri: str | None = None 630 + offset: int | None = None 631 + limit: int | None = None 632 + 633 + 634 + class GetArtistRecommendationsParams(RockskyModel): 635 + did: str | None = None 636 + limit: int | None = None 637 + 638 + 639 + class GetArtistShoutsOutput(RockskyModel): 640 + shouts: list[Any] | None = None 641 + 642 + 643 + class GetArtistShoutsParams(RockskyModel): 644 + uri: str | None = None 645 + limit: int | None = None 646 + offset: int | None = None 647 + 648 + 649 + class GetArtistsOutput(RockskyModel): 650 + artists: list[ArtistViewBasic] | None = None 651 + 652 + 653 + class GetArtistsParams(RockskyModel): 654 + limit: int | None = None 655 + offset: int | None = None 656 + names: str | None = None 657 + genre: str | None = None 658 + 659 + 660 + class GetArtistTracksOutput(RockskyModel): 661 + tracks: list[SongViewBasic] | None = None 662 + 663 + 664 + class GetArtistTracksParams(RockskyModel): 665 + uri: str | None = None 666 + limit: int | None = None 667 + offset: int | None = None 668 + 669 + 670 + class GetCurrentlyPlayingParams(RockskyModel): 671 + player_id: str | None = Field(default=None, alias="playerId") 672 + actor: str | None = None 673 + 674 + 675 + class GetFeedGeneratorOutput(RockskyModel): 676 + view: FeedGeneratorView | None = None 677 + 678 + 679 + class GetFeedGeneratorParams(RockskyModel): 680 + feed: str | None = None 681 + 682 + 683 + class GetFeedGeneratorsParams(RockskyModel): 684 + size: int | None = None 685 + 686 + 687 + class GetFeedParams(RockskyModel): 688 + feed: str | None = None 689 + limit: int | None = None 690 + cursor: str | None = None 691 + 692 + 693 + class GetFeedSkeletonOutput(RockskyModel): 694 + scrobbles: list[ScrobbleViewBasic] | None = None 695 + cursor: str | None = None 696 + 697 + 698 + class GetFeedSkeletonParams(RockskyModel): 699 + feed: str | None = None 700 + limit: int | None = None 701 + offset: int | None = None 702 + cursor: str | None = None 703 + 704 + 705 + class GetFileParams(RockskyModel): 706 + file_id: str | None = Field(default=None, alias="fileId") 707 + 708 + 709 + class GetFilesParams(RockskyModel): 710 + at: str | None = None 711 + 712 + 713 + class GetFollowersOutput(RockskyModel): 714 + subject: ActorProfileViewBasic | None = None 715 + followers: list[ActorProfileViewBasic] | None = None 716 + cursor: str | None = None 717 + count: int | None = None 718 + 719 + 720 + class GetFollowersParams(RockskyModel): 721 + actor: str | None = None 722 + limit: int | None = None 723 + dids: list[str] | None = None 724 + cursor: str | None = None 725 + 726 + 727 + class GetFollowsOutput(RockskyModel): 728 + subject: ActorProfileViewBasic | None = None 729 + follows: list[ActorProfileViewBasic] | None = None 730 + cursor: str | None = None 731 + count: int | None = None 732 + 733 + 734 + class GetFollowsParams(RockskyModel): 735 + actor: str | None = None 736 + limit: int | None = None 737 + dids: list[str] | None = None 738 + cursor: str | None = None 739 + 740 + 741 + class GetKnownFollowersOutput(RockskyModel): 742 + subject: ActorProfileViewBasic | None = None 743 + followers: list[ActorProfileViewBasic] | None = None 744 + cursor: str | None = None 745 + 746 + 747 + class GetKnownFollowersParams(RockskyModel): 748 + actor: str | None = None 749 + limit: int | None = None 750 + cursor: str | None = None 751 + 752 + 753 + class GetMetadataParams(RockskyModel): 754 + path: str | None = None 755 + 756 + 757 + class GetMirrorSourcesOutput(RockskyModel): 758 + sources: list[MirrorSourceView] | None = None 759 + 760 + 761 + class GetMirrorSourcesParams(RockskyModel): 762 + pass 763 + 764 + 765 + class GetPlaybackQueueParams(RockskyModel): 766 + player_id: str | None = Field(default=None, alias="playerId") 767 + 768 + 769 + class GetPlaylistParams(RockskyModel): 770 + uri: str | None = None 771 + 772 + 773 + class GetPlaylistsOutput(RockskyModel): 774 + playlists: list[PlaylistViewBasic] | None = None 775 + 776 + 777 + class GetPlaylistsParams(RockskyModel): 778 + limit: int | None = None 779 + offset: int | None = None 780 + 781 + 782 + class GetProfileParams(RockskyModel): 783 + did: str | None = None 784 + 785 + 786 + class GetProfileShoutsOutput(RockskyModel): 787 + shouts: list[Any] | None = None 788 + 789 + 790 + class GetProfileShoutsParams(RockskyModel): 791 + did: str | None = None 792 + offset: int | None = None 793 + limit: int | None = None 794 + 795 + 796 + class GetRecommendationsParams(RockskyModel): 797 + did: str | None = None 798 + limit: int | None = None 799 + 800 + 801 + class GetScrobbleParams(RockskyModel): 802 + uri: str | None = None 803 + 804 + 805 + class GetScrobblesChartParams(RockskyModel): 806 + did: str | None = None 807 + artisturi: str | None = None 808 + albumuri: str | None = None 809 + songuri: str | None = None 810 + genre: str | None = None 811 + from_: str | None = Field(default=None, alias="from") 812 + to: str | None = None 813 + 814 + 815 + class GetScrobblesOutput(RockskyModel): 816 + scrobbles: list[ScrobbleViewBasic] | None = None 817 + 818 + 819 + class GetScrobblesParams(RockskyModel): 820 + did: str | None = None 821 + following: bool | None = None 822 + limit: int | None = None 823 + offset: int | None = None 824 + 825 + 826 + class GetShoutRepliesOutput(RockskyModel): 827 + shouts: list[Any] | None = None 828 + 829 + 830 + class GetShoutRepliesParams(RockskyModel): 831 + uri: str | None = None 832 + limit: int | None = None 833 + offset: int | None = None 834 + 835 + 836 + class GetSongParams(RockskyModel): 837 + uri: str | None = None 838 + mbid: str | None = None 839 + isrc: str | None = None 840 + spotify_id: str | None = Field(default=None, alias="spotifyId") 841 + 842 + 843 + class GetSongRecentListenersOutput(RockskyModel): 844 + listeners: list[SongRecentListenerView] | None = None 845 + 846 + 847 + class GetSongRecentListenersParams(RockskyModel): 848 + uri: str | None = None 849 + offset: int | None = None 850 + limit: int | None = None 851 + 852 + 853 + class GetSongsOutput(RockskyModel): 854 + songs: list[SongViewBasic] | None = None 855 + 856 + 857 + class GetSongsParams(RockskyModel): 858 + limit: int | None = None 859 + offset: int | None = None 860 + genre: str | None = None 861 + mbid: str | None = None 862 + isrc: str | None = None 863 + spotify_id: str | None = Field(default=None, alias="spotifyId") 864 + 865 + 866 + class GetStatsParams(RockskyModel): 867 + did: str | None = None 868 + 869 + 870 + class GetStoriesParams(RockskyModel): 871 + size: int | None = None 872 + 873 + 874 + class GetTemporaryLinkParams(RockskyModel): 875 + path: str | None = None 876 + 877 + 878 + class GetTopArtistsOutput(RockskyModel): 879 + artists: list[ArtistViewBasic] | None = None 880 + 881 + 882 + class GetTopArtistsParams(RockskyModel): 883 + limit: int | None = None 884 + offset: int | None = None 885 + start_date: datetime | None = Field(default=None, alias="startDate") 886 + end_date: datetime | None = Field(default=None, alias="endDate") 887 + 888 + 889 + class GetTopTracksOutput(RockskyModel): 890 + tracks: list[SongViewBasic] | None = None 891 + 892 + 893 + class GetTopTracksParams(RockskyModel): 894 + limit: int | None = None 895 + offset: int | None = None 896 + start_date: datetime | None = Field(default=None, alias="startDate") 897 + end_date: datetime | None = Field(default=None, alias="endDate") 898 + 899 + 900 + class GetTrackShoutsOutput(RockskyModel): 901 + shouts: list[Any] | None = None 902 + 903 + 904 + class GetTrackShoutsParams(RockskyModel): 905 + uri: str | None = None 906 + 907 + 908 + class GetWrappedParams(RockskyModel): 909 + did: str | None = None 910 + year: int | None = None 911 + 912 + 913 + class GoogledriveFileListView(RockskyModel): 914 + files: list[GoogledriveFileView] | None = None 915 + 916 + 917 + class GoogledriveFileView(RockskyModel): 918 + id: str | None = None 919 + 920 + 921 + class GraphNotFoundActor(RockskyModel): 922 + """indicates that a handle or DID could not be resolved""" 923 + 924 + actor: str | None = None 925 + not_found: bool | None = Field(default=None, alias="notFound") 926 + 927 + 928 + class GraphRelationship(RockskyModel): 929 + did: str | None = None 930 + following: str | None = None 931 + followed_by: str | None = Field(default=None, alias="followedBy") 932 + 933 + 934 + class InsertDirectoryParams(RockskyModel): 935 + uri: str | None = None 936 + directory: str | None = None 937 + position: int | None = None 938 + 939 + 940 + class InsertFilesParams(RockskyModel): 941 + uri: str | None = None 942 + files: list[str] | None = None 943 + position: int | None = None 944 + 945 + 946 + class LikeRecord(RockskyModel): 947 + created_at: datetime | None = Field(default=None, alias="createdAt") 948 + subject: StrongRef | None = None 949 + 950 + 951 + class LikeShoutInput(RockskyModel): 952 + uri: str | None = None 953 + 954 + 955 + class LikeSongInput(RockskyModel): 956 + uri: str | None = None 957 + 958 + 959 + class MatchSongParams(RockskyModel): 960 + title: str | None = None 961 + artist: str | None = None 962 + mb_id: str | None = Field(default=None, alias="mbId") 963 + isrc: str | None = None 964 + 965 + 966 + class MirrorSourceView(RockskyModel): 967 + provider: str | None = None 968 + enabled: bool | None = None 969 + external_username: str | None = Field(default=None, alias="externalUsername") 970 + has_credentials: bool | None = Field(default=None, alias="hasCredentials") 971 + last_polled_at: datetime | None = Field(default=None, alias="lastPolledAt") 972 + last_scrobble_seen_at: datetime | None = Field(default=None, alias="lastScrobbleSeenAt") 973 + 974 + 975 + class NextParams(RockskyModel): 976 + player_id: str | None = Field(default=None, alias="playerId") 977 + 978 + 979 + class PauseParams(RockskyModel): 980 + player_id: str | None = Field(default=None, alias="playerId") 981 + 982 + 983 + class PlayDirectoryParams(RockskyModel): 984 + player_id: str | None = Field(default=None, alias="playerId") 985 + directory_id: str | None = Field(default=None, alias="directoryId") 986 + shuffle: bool | None = None 987 + recurse: bool | None = None 988 + position: int | None = None 989 + 990 + 991 + class PlayerCurrentlyPlayingViewDetailed(RockskyModel): 992 + title: str | None = None 993 + 994 + 995 + class PlayerPlaybackQueueViewDetailed(RockskyModel): 996 + tracks: list[SongViewBasic] | None = None 997 + 998 + 999 + class PlayFileParams(RockskyModel): 1000 + player_id: str | None = Field(default=None, alias="playerId") 1001 + file_id: str | None = Field(default=None, alias="fileId") 1002 + 1003 + 1004 + class PlaylistItemRecord(RockskyModel): 1005 + subject: StrongRef | None = None 1006 + created_at: datetime | None = Field(default=None, alias="createdAt") 1007 + track: SongViewBasic | None = None 1008 + order: int | None = None 1009 + 1010 + 1011 + class PlaylistRecord(RockskyModel): 1012 + name: str | None = None 1013 + description: str | None = None 1014 + picture: BlobRef | None = None 1015 + picture_url: str | None = Field(default=None, alias="pictureUrl") 1016 + created_at: datetime | None = Field(default=None, alias="createdAt") 1017 + spotify_link: str | None = Field(default=None, alias="spotifyLink") 1018 + tidal_link: str | None = Field(default=None, alias="tidalLink") 1019 + youtube_link: str | None = Field(default=None, alias="youtubeLink") 1020 + apple_music_link: str | None = Field(default=None, alias="appleMusicLink") 1021 + 1022 + 1023 + class PlaylistViewBasic(RockskyModel): 1024 + """Basic view of a playlist, including its metadata""" 1025 + 1026 + id: str | None = None 1027 + title: str | None = None 1028 + uri: str | None = None 1029 + curator_did: str | None = Field(default=None, alias="curatorDid") 1030 + curator_handle: str | None = Field(default=None, alias="curatorHandle") 1031 + curator_name: str | None = Field(default=None, alias="curatorName") 1032 + curator_avatar_url: str | None = Field(default=None, alias="curatorAvatarUrl") 1033 + description: str | None = None 1034 + cover_image_url: str | None = Field(default=None, alias="coverImageUrl") 1035 + created_at: datetime | None = Field(default=None, alias="createdAt") 1036 + track_count: int | None = Field(default=None, alias="trackCount") 1037 + 1038 + 1039 + class PlaylistViewDetailed(RockskyModel): 1040 + """Detailed view of a playlist, including its tracks and metadata""" 1041 + 1042 + id: str | None = None 1043 + title: str | None = None 1044 + uri: str | None = None 1045 + curator_did: str | None = Field(default=None, alias="curatorDid") 1046 + curator_handle: str | None = Field(default=None, alias="curatorHandle") 1047 + curator_name: str | None = Field(default=None, alias="curatorName") 1048 + curator_avatar_url: str | None = Field(default=None, alias="curatorAvatarUrl") 1049 + description: str | None = None 1050 + cover_image_url: str | None = Field(default=None, alias="coverImageUrl") 1051 + created_at: datetime | None = Field(default=None, alias="createdAt") 1052 + tracks: list[SongViewBasic] | None = None 1053 + 1054 + 1055 + class PlayParams(RockskyModel): 1056 + player_id: str | None = Field(default=None, alias="playerId") 1057 + 1058 + 1059 + class PreviousParams(RockskyModel): 1060 + player_id: str | None = Field(default=None, alias="playerId") 1061 + 1062 + 1063 + class ProfileRecord(RockskyModel): 1064 + display_name: str | None = Field(default=None, alias="displayName") 1065 + description: str | None = None 1066 + avatar: BlobRef | None = None 1067 + banner: BlobRef | None = None 1068 + labels: Any | None = None 1069 + joined_via_starter_pack: StrongRef | None = Field(default=None, alias="joinedViaStarterPack") 1070 + created_at: datetime | None = Field(default=None, alias="createdAt") 1071 + 1072 + 1073 + class PutMirrorSourceInput(RockskyModel): 1074 + provider: str | None = None 1075 + enabled: bool | None = None 1076 + external_username: str | None = Field(default=None, alias="externalUsername") 1077 + api_key: str | None = Field(default=None, alias="apiKey") 1078 + 1079 + 1080 + class RadioRecord(RockskyModel): 1081 + name: str | None = None 1082 + url: str | None = None 1083 + description: str | None = None 1084 + genre: str | None = None 1085 + logo: BlobRef | None = None 1086 + website: str | None = None 1087 + created_at: datetime | None = Field(default=None, alias="createdAt") 1088 + 1089 + 1090 + class RadioViewBasic(RockskyModel): 1091 + id: str | None = None 1092 + name: str | None = None 1093 + description: str | None = None 1094 + created_at: datetime | None = Field(default=None, alias="createdAt") 1095 + 1096 + 1097 + class RadioViewDetailed(RockskyModel): 1098 + id: str | None = None 1099 + name: str | None = None 1100 + description: str | None = None 1101 + website: str | None = None 1102 + url: str | None = None 1103 + genre: str | None = None 1104 + logo: str | None = None 1105 + created_at: datetime | None = Field(default=None, alias="createdAt") 1106 + 1107 + 1108 + class RemoveApikeyParams(RockskyModel): 1109 + id: str | None = None 1110 + 1111 + 1112 + class RemovePlaylistParams(RockskyModel): 1113 + uri: str | None = None 1114 + 1115 + 1116 + class RemoveShoutParams(RockskyModel): 1117 + id: str | None = None 1118 + 1119 + 1120 + class RemoveTrackParams(RockskyModel): 1121 + uri: str | None = None 1122 + position: int | None = None 1123 + 1124 + 1125 + class ReplyShoutInput(RockskyModel): 1126 + shout_id: str | None = Field(default=None, alias="shoutId") 1127 + message: str | None = None 1128 + 1129 + 1130 + class ReportShoutInput(RockskyModel): 1131 + shout_id: str | None = Field(default=None, alias="shoutId") 1132 + reason: str | None = None 1133 + 1134 + 1135 + class ScrobbleFirstScrobbleView(RockskyModel): 1136 + handle: str | None = None 1137 + avatar: str | None = None 1138 + timestamp: datetime | None = None 1139 + 1140 + 1141 + class ScrobbleRecord(RockskyModel): 1142 + title: str | None = None 1143 + artist: str | None = None 1144 + artists: list[ArtistMbid] | None = None 1145 + album_artist: str | None = Field(default=None, alias="albumArtist") 1146 + album: str | None = None 1147 + duration: int | None = None 1148 + track_number: int | None = Field(default=None, alias="trackNumber") 1149 + disc_number: int | None = Field(default=None, alias="discNumber") 1150 + release_date: datetime | None = Field(default=None, alias="releaseDate") 1151 + year: int | None = None 1152 + genre: str | None = None 1153 + tags: list[str] | None = None 1154 + composer: str | None = None 1155 + lyrics: str | None = None 1156 + copyright_message: str | None = Field(default=None, alias="copyrightMessage") 1157 + wiki: str | None = None 1158 + album_art: BlobRef | None = Field(default=None, alias="albumArt") 1159 + album_art_url: str | None = Field(default=None, alias="albumArtUrl") 1160 + youtube_link: str | None = Field(default=None, alias="youtubeLink") 1161 + spotify_link: str | None = Field(default=None, alias="spotifyLink") 1162 + tidal_link: str | None = Field(default=None, alias="tidalLink") 1163 + apple_music_link: str | None = Field(default=None, alias="appleMusicLink") 1164 + created_at: datetime | None = Field(default=None, alias="createdAt") 1165 + mbid: str | None = None 1166 + label: str | None = None 1167 + isrc: str | None = None 1168 + 1169 + 1170 + class ScrobbleViewBasic(RockskyModel): 1171 + id: str | None = None 1172 + user: str | None = None 1173 + user_display_name: str | None = Field(default=None, alias="userDisplayName") 1174 + user_avatar: str | None = Field(default=None, alias="userAvatar") 1175 + title: str | None = None 1176 + artist: str | None = None 1177 + artist_uri: str | None = Field(default=None, alias="artistUri") 1178 + album: str | None = None 1179 + album_uri: str | None = Field(default=None, alias="albumUri") 1180 + cover: str | None = None 1181 + date: datetime | None = None 1182 + uri: str | None = None 1183 + sha256: str | None = None 1184 + liked: bool | None = None 1185 + likes_count: int | None = Field(default=None, alias="likesCount") 1186 + 1187 + 1188 + class ScrobbleViewDetailed(RockskyModel): 1189 + id: str | None = None 1190 + user: str | None = None 1191 + title: str | None = None 1192 + artist: str | None = None 1193 + artist_uri: str | None = Field(default=None, alias="artistUri") 1194 + album: str | None = None 1195 + album_uri: str | None = Field(default=None, alias="albumUri") 1196 + cover: str | None = None 1197 + date: datetime | None = None 1198 + uri: str | None = None 1199 + sha256: str | None = None 1200 + liked: bool | None = None 1201 + likes_count: int | None = Field(default=None, alias="likesCount") 1202 + listeners: int | None = None 1203 + scrobbles: int | None = None 1204 + artists: list[ArtistViewBasic] | None = None 1205 + first_scrobble: ScrobbleFirstScrobbleView | None = Field(default=None, alias="firstScrobble") 1206 + 1207 + 1208 + class SearchParams(RockskyModel): 1209 + query: str | None = None 1210 + 1211 + 1212 + class SeekParams(RockskyModel): 1213 + player_id: str | None = Field(default=None, alias="playerId") 1214 + position: int | None = None 1215 + 1216 + 1217 + class ShoutAuthor(RockskyModel): 1218 + id: str | None = None 1219 + did: str | None = None 1220 + handle: str | None = None 1221 + display_name: str | None = Field(default=None, alias="displayName") 1222 + avatar: str | None = None 1223 + 1224 + 1225 + class ShoutRecord(RockskyModel): 1226 + message: str | None = None 1227 + created_at: datetime | None = Field(default=None, alias="createdAt") 1228 + parent: StrongRef | None = None 1229 + subject: StrongRef | None = None 1230 + 1231 + 1232 + class ShoutView(RockskyModel): 1233 + id: str | None = None 1234 + message: str | None = None 1235 + parent: str | None = None 1236 + created_at: datetime | None = Field(default=None, alias="createdAt") 1237 + author: ShoutAuthor | None = None 1238 + 1239 + 1240 + class SongFirstScrobbleView(RockskyModel): 1241 + handle: str | None = None 1242 + avatar: str | None = None 1243 + timestamp: datetime | None = None 1244 + 1245 + 1246 + class SongRecentListenerView(RockskyModel): 1247 + id: str | None = None 1248 + did: str | None = None 1249 + handle: str | None = None 1250 + display_name: str | None = Field(default=None, alias="displayName") 1251 + avatar: str | None = None 1252 + timestamp: datetime | None = None 1253 + scrobble_uri: str | None = Field(default=None, alias="scrobbleUri") 1254 + 1255 + 1256 + class SongRecord(RockskyModel): 1257 + title: str | None = None 1258 + artist: str | None = None 1259 + artists: list[ArtistMbid] | None = None 1260 + album_artist: str | None = Field(default=None, alias="albumArtist") 1261 + album: str | None = None 1262 + duration: int | None = None 1263 + track_number: int | None = Field(default=None, alias="trackNumber") 1264 + disc_number: int | None = Field(default=None, alias="discNumber") 1265 + release_date: datetime | None = Field(default=None, alias="releaseDate") 1266 + year: int | None = None 1267 + genre: str | None = None 1268 + tags: list[str] | None = None 1269 + composer: str | None = None 1270 + lyrics: str | None = None 1271 + copyright_message: str | None = Field(default=None, alias="copyrightMessage") 1272 + wiki: str | None = None 1273 + album_art: BlobRef | None = Field(default=None, alias="albumArt") 1274 + album_art_url: str | None = Field(default=None, alias="albumArtUrl") 1275 + youtube_link: str | None = Field(default=None, alias="youtubeLink") 1276 + spotify_link: str | None = Field(default=None, alias="spotifyLink") 1277 + tidal_link: str | None = Field(default=None, alias="tidalLink") 1278 + apple_music_link: str | None = Field(default=None, alias="appleMusicLink") 1279 + created_at: datetime | None = Field(default=None, alias="createdAt") 1280 + mbid: str | None = None 1281 + label: str | None = None 1282 + isrc: str | None = None 1283 + 1284 + 1285 + class SongViewBasic(RockskyModel): 1286 + id: str | None = None 1287 + title: str | None = None 1288 + artist: str | None = None 1289 + album_artist: str | None = Field(default=None, alias="albumArtist") 1290 + album_art: str | None = Field(default=None, alias="albumArt") 1291 + uri: str | None = None 1292 + album: str | None = None 1293 + duration: int | None = None 1294 + track_number: int | None = Field(default=None, alias="trackNumber") 1295 + disc_number: int | None = Field(default=None, alias="discNumber") 1296 + play_count: int | None = Field(default=None, alias="playCount") 1297 + unique_listeners: int | None = Field(default=None, alias="uniqueListeners") 1298 + album_uri: str | None = Field(default=None, alias="albumUri") 1299 + artist_uri: str | None = Field(default=None, alias="artistUri") 1300 + sha256: str | None = None 1301 + mbid: str | None = None 1302 + isrc: str | None = None 1303 + tags: list[str] | None = None 1304 + created_at: datetime | None = Field(default=None, alias="createdAt") 1305 + 1306 + 1307 + class SongViewDetailed(RockskyModel): 1308 + id: str | None = None 1309 + title: str | None = None 1310 + artist: str | None = None 1311 + album_artist: str | None = Field(default=None, alias="albumArtist") 1312 + album_art: str | None = Field(default=None, alias="albumArt") 1313 + uri: str | None = None 1314 + album: str | None = None 1315 + duration: int | None = None 1316 + track_number: int | None = Field(default=None, alias="trackNumber") 1317 + disc_number: int | None = Field(default=None, alias="discNumber") 1318 + play_count: int | None = Field(default=None, alias="playCount") 1319 + unique_listeners: int | None = Field(default=None, alias="uniqueListeners") 1320 + album_uri: str | None = Field(default=None, alias="albumUri") 1321 + artist_uri: str | None = Field(default=None, alias="artistUri") 1322 + sha256: str | None = None 1323 + mbid: str | None = None 1324 + isrc: str | None = None 1325 + tags: list[str] | None = None 1326 + created_at: datetime | None = Field(default=None, alias="createdAt") 1327 + artists: list[ArtistViewBasic] | None = None 1328 + first_scrobble: SongFirstScrobbleView | None = Field(default=None, alias="firstScrobble") 1329 + 1330 + 1331 + class SpotifyTrackView(RockskyModel): 1332 + id: str | None = None 1333 + name: str | None = None 1334 + artist: str | None = None 1335 + album: str | None = None 1336 + duration: int | None = None 1337 + preview_url: str | None = Field(default=None, alias="previewUrl") 1338 + 1339 + 1340 + class StartPlaylistParams(RockskyModel): 1341 + uri: str | None = None 1342 + shuffle: bool | None = None 1343 + position: int | None = None 1344 + 1345 + 1346 + class StatsView(RockskyModel): 1347 + scrobbles: int | None = None 1348 + artists: int | None = None 1349 + loved_tracks: int | None = Field(default=None, alias="lovedTracks") 1350 + albums: int | None = None 1351 + tracks: int | None = None 1352 + 1353 + 1354 + class StatsWrappedAlbum(RockskyModel): 1355 + id: str | None = None 1356 + title: str | None = None 1357 + artist: str | None = None 1358 + album_art: str | None = Field(default=None, alias="albumArt") 1359 + uri: str | None = None 1360 + play_count: int | None = Field(default=None, alias="playCount") 1361 + 1362 + 1363 + class StatsWrappedArtist(RockskyModel): 1364 + id: str | None = None 1365 + name: str | None = None 1366 + picture: str | None = None 1367 + uri: str | None = None 1368 + play_count: int | None = Field(default=None, alias="playCount") 1369 + 1370 + 1371 + class StatsWrappedDayCount(RockskyModel): 1372 + date: str | None = None 1373 + count: int | None = None 1374 + 1375 + 1376 + class StatsWrappedGenreCount(RockskyModel): 1377 + genre: str | None = None 1378 + count: int | None = None 1379 + 1380 + 1381 + class StatsWrappedMilestone(RockskyModel): 1382 + track_title: str | None = Field(default=None, alias="trackTitle") 1383 + artist_name: str | None = Field(default=None, alias="artistName") 1384 + timestamp: datetime | None = None 1385 + track_uri: str | None = Field(default=None, alias="trackUri") 1386 + 1387 + 1388 + class StatsWrappedMonthCount(RockskyModel): 1389 + month: int | None = None 1390 + count: int | None = None 1391 + 1392 + 1393 + class StatsWrappedTrack(RockskyModel): 1394 + id: str | None = None 1395 + title: str | None = None 1396 + artist: str | None = None 1397 + album_art: str | None = Field(default=None, alias="albumArt") 1398 + uri: str | None = None 1399 + artist_uri: str | None = Field(default=None, alias="artistUri") 1400 + album_uri: str | None = Field(default=None, alias="albumUri") 1401 + play_count: int | None = Field(default=None, alias="playCount") 1402 + 1403 + 1404 + class StatsWrappedView(RockskyModel): 1405 + year: int | None = None 1406 + total_scrobbles: int | None = Field(default=None, alias="totalScrobbles") 1407 + total_listening_time_minutes: int | None = Field(default=None, alias="totalListeningTimeMinutes") 1408 + top_artists: list[StatsWrappedArtist] | None = Field(default=None, alias="topArtists") 1409 + top_tracks: list[StatsWrappedTrack] | None = Field(default=None, alias="topTracks") 1410 + top_albums: list[StatsWrappedAlbum] | None = Field(default=None, alias="topAlbums") 1411 + top_genres: list[StatsWrappedGenreCount] | None = Field(default=None, alias="topGenres") 1412 + scrobbles_per_month: list[StatsWrappedMonthCount] | None = Field(default=None, alias="scrobblesPerMonth") 1413 + most_active_day: StatsWrappedDayCount | None = Field(default=None, alias="mostActiveDay") 1414 + most_active_hour: int | None = Field(default=None, alias="mostActiveHour") 1415 + new_artists_count: int | None = Field(default=None, alias="newArtistsCount") 1416 + longest_streak: int | None = Field(default=None, alias="longestStreak") 1417 + first_scrobble: StatsWrappedMilestone | None = Field(default=None, alias="firstScrobble") 1418 + last_scrobble: StatsWrappedMilestone | None = Field(default=None, alias="lastScrobble") 1419 + 1420 + 1421 + class StatusRecord(RockskyModel): 1422 + track: ActorTrackView | None = None 1423 + started_at: datetime | None = Field(default=None, alias="startedAt") 1424 + expires_at: datetime | None = Field(default=None, alias="expiresAt") 1425 + 1426 + 1427 + class StrongRef(RockskyModel): 1428 + uri: str | None = None 1429 + cid: str | None = None 1430 + 1431 + 1432 + class UnfollowAccountOutput(RockskyModel): 1433 + subject: ActorProfileViewBasic | None = None 1434 + followers: list[ActorProfileViewBasic] | None = None 1435 + cursor: str | None = None 1436 + 1437 + 1438 + class UnfollowAccountParams(RockskyModel): 1439 + account: str | None = None 1440 + 1441 + 1442 + class UpdateApikeyInput(RockskyModel): 1443 + id: str | None = None 1444 + name: str | None = None 1445 + description: str | None = None 1446 + 1447 + 1448 + ActorArtistViewBasic.model_rebuild() 1449 + ActorCompatibilityViewBasic.model_rebuild() 1450 + ActorNeighbourViewBasic.model_rebuild() 1451 + ActorProfileViewBasic.model_rebuild() 1452 + ActorProfileViewDetailed.model_rebuild() 1453 + ActorTrackView.model_rebuild() 1454 + AddDirectoryToQueueParams.model_rebuild() 1455 + AddItemsToQueueParams.model_rebuild() 1456 + AlbumRecord.model_rebuild() 1457 + AlbumViewBasic.model_rebuild() 1458 + AlbumViewDetailed.model_rebuild() 1459 + ApiKeyView.model_rebuild() 1460 + ArtistListenerViewBasic.model_rebuild() 1461 + ArtistMbid.model_rebuild() 1462 + ArtistRecentListenerView.model_rebuild() 1463 + ArtistRecord.model_rebuild() 1464 + ArtistSongViewBasic.model_rebuild() 1465 + ArtistViewBasic.model_rebuild() 1466 + ArtistViewDetailed.model_rebuild() 1467 + ChartsScrobbleViewBasic.model_rebuild() 1468 + ChartsView.model_rebuild() 1469 + CreateApikeyInput.model_rebuild() 1470 + CreatePlaylistParams.model_rebuild() 1471 + CreateScrobbleInput.model_rebuild() 1472 + CreateShoutInput.model_rebuild() 1473 + CreateSongInput.model_rebuild() 1474 + DescribeFeedGeneratorOutput.model_rebuild() 1475 + DescribeFeedGeneratorParams.model_rebuild() 1476 + DislikeShoutInput.model_rebuild() 1477 + DislikeSongInput.model_rebuild() 1478 + DownloadFileParams.model_rebuild() 1479 + DropboxFileListView.model_rebuild() 1480 + DropboxFileView.model_rebuild() 1481 + DropboxTemporaryLinkView.model_rebuild() 1482 + FeedGeneratorsView.model_rebuild() 1483 + FeedGeneratorView.model_rebuild() 1484 + FeedItemView.model_rebuild() 1485 + FeedRecommendationsView.model_rebuild() 1486 + FeedRecommendationView.model_rebuild() 1487 + FeedRecommendedAlbumsView.model_rebuild() 1488 + FeedRecommendedAlbumView.model_rebuild() 1489 + FeedRecommendedArtistsView.model_rebuild() 1490 + FeedRecommendedArtistView.model_rebuild() 1491 + FeedSearchResultsView.model_rebuild() 1492 + FeedStoriesView.model_rebuild() 1493 + FeedStoryView.model_rebuild() 1494 + FeedUriView.model_rebuild() 1495 + FeedView.model_rebuild() 1496 + FollowAccountOutput.model_rebuild() 1497 + FollowAccountParams.model_rebuild() 1498 + FollowRecord.model_rebuild() 1499 + GeneratorRecord.model_rebuild() 1500 + GetActorAlbumsOutput.model_rebuild() 1501 + GetActorAlbumsParams.model_rebuild() 1502 + GetActorArtistsOutput.model_rebuild() 1503 + GetActorArtistsParams.model_rebuild() 1504 + GetActorCompatibilityOutput.model_rebuild() 1505 + GetActorCompatibilityParams.model_rebuild() 1506 + GetActorLovedSongsOutput.model_rebuild() 1507 + GetActorLovedSongsParams.model_rebuild() 1508 + GetActorNeighboursOutput.model_rebuild() 1509 + GetActorNeighboursParams.model_rebuild() 1510 + GetActorPlaylistsOutput.model_rebuild() 1511 + GetActorPlaylistsParams.model_rebuild() 1512 + GetActorScrobblesOutput.model_rebuild() 1513 + GetActorScrobblesParams.model_rebuild() 1514 + GetActorSongsOutput.model_rebuild() 1515 + GetActorSongsParams.model_rebuild() 1516 + GetAlbumParams.model_rebuild() 1517 + GetAlbumRecommendationsParams.model_rebuild() 1518 + GetAlbumShoutsOutput.model_rebuild() 1519 + GetAlbumShoutsParams.model_rebuild() 1520 + GetAlbumsOutput.model_rebuild() 1521 + GetAlbumsParams.model_rebuild() 1522 + GetAlbumTracksOutput.model_rebuild() 1523 + GetAlbumTracksParams.model_rebuild() 1524 + GetApikeysOutput.model_rebuild() 1525 + GetApikeysParams.model_rebuild() 1526 + GetArtistAlbumsOutput.model_rebuild() 1527 + GetArtistAlbumsParams.model_rebuild() 1528 + GetArtistListenersOutput.model_rebuild() 1529 + GetArtistListenersParams.model_rebuild() 1530 + GetArtistParams.model_rebuild() 1531 + GetArtistRecentListenersOutput.model_rebuild() 1532 + GetArtistRecentListenersParams.model_rebuild() 1533 + GetArtistRecommendationsParams.model_rebuild() 1534 + GetArtistShoutsOutput.model_rebuild() 1535 + GetArtistShoutsParams.model_rebuild() 1536 + GetArtistsOutput.model_rebuild() 1537 + GetArtistsParams.model_rebuild() 1538 + GetArtistTracksOutput.model_rebuild() 1539 + GetArtistTracksParams.model_rebuild() 1540 + GetCurrentlyPlayingParams.model_rebuild() 1541 + GetFeedGeneratorOutput.model_rebuild() 1542 + GetFeedGeneratorParams.model_rebuild() 1543 + GetFeedGeneratorsParams.model_rebuild() 1544 + GetFeedParams.model_rebuild() 1545 + GetFeedSkeletonOutput.model_rebuild() 1546 + GetFeedSkeletonParams.model_rebuild() 1547 + GetFileParams.model_rebuild() 1548 + GetFilesParams.model_rebuild() 1549 + GetFollowersOutput.model_rebuild() 1550 + GetFollowersParams.model_rebuild() 1551 + GetFollowsOutput.model_rebuild() 1552 + GetFollowsParams.model_rebuild() 1553 + GetKnownFollowersOutput.model_rebuild() 1554 + GetKnownFollowersParams.model_rebuild() 1555 + GetMetadataParams.model_rebuild() 1556 + GetMirrorSourcesOutput.model_rebuild() 1557 + GetMirrorSourcesParams.model_rebuild() 1558 + GetPlaybackQueueParams.model_rebuild() 1559 + GetPlaylistParams.model_rebuild() 1560 + GetPlaylistsOutput.model_rebuild() 1561 + GetPlaylistsParams.model_rebuild() 1562 + GetProfileParams.model_rebuild() 1563 + GetProfileShoutsOutput.model_rebuild() 1564 + GetProfileShoutsParams.model_rebuild() 1565 + GetRecommendationsParams.model_rebuild() 1566 + GetScrobbleParams.model_rebuild() 1567 + GetScrobblesChartParams.model_rebuild() 1568 + GetScrobblesOutput.model_rebuild() 1569 + GetScrobblesParams.model_rebuild() 1570 + GetShoutRepliesOutput.model_rebuild() 1571 + GetShoutRepliesParams.model_rebuild() 1572 + GetSongParams.model_rebuild() 1573 + GetSongRecentListenersOutput.model_rebuild() 1574 + GetSongRecentListenersParams.model_rebuild() 1575 + GetSongsOutput.model_rebuild() 1576 + GetSongsParams.model_rebuild() 1577 + GetStatsParams.model_rebuild() 1578 + GetStoriesParams.model_rebuild() 1579 + GetTemporaryLinkParams.model_rebuild() 1580 + GetTopArtistsOutput.model_rebuild() 1581 + GetTopArtistsParams.model_rebuild() 1582 + GetTopTracksOutput.model_rebuild() 1583 + GetTopTracksParams.model_rebuild() 1584 + GetTrackShoutsOutput.model_rebuild() 1585 + GetTrackShoutsParams.model_rebuild() 1586 + GetWrappedParams.model_rebuild() 1587 + GoogledriveFileListView.model_rebuild() 1588 + GoogledriveFileView.model_rebuild() 1589 + GraphNotFoundActor.model_rebuild() 1590 + GraphRelationship.model_rebuild() 1591 + InsertDirectoryParams.model_rebuild() 1592 + InsertFilesParams.model_rebuild() 1593 + LikeRecord.model_rebuild() 1594 + LikeShoutInput.model_rebuild() 1595 + LikeSongInput.model_rebuild() 1596 + MatchSongParams.model_rebuild() 1597 + MirrorSourceView.model_rebuild() 1598 + NextParams.model_rebuild() 1599 + PauseParams.model_rebuild() 1600 + PlayDirectoryParams.model_rebuild() 1601 + PlayerCurrentlyPlayingViewDetailed.model_rebuild() 1602 + PlayerPlaybackQueueViewDetailed.model_rebuild() 1603 + PlayFileParams.model_rebuild() 1604 + PlaylistItemRecord.model_rebuild() 1605 + PlaylistRecord.model_rebuild() 1606 + PlaylistViewBasic.model_rebuild() 1607 + PlaylistViewDetailed.model_rebuild() 1608 + PlayParams.model_rebuild() 1609 + PreviousParams.model_rebuild() 1610 + ProfileRecord.model_rebuild() 1611 + PutMirrorSourceInput.model_rebuild() 1612 + RadioRecord.model_rebuild() 1613 + RadioViewBasic.model_rebuild() 1614 + RadioViewDetailed.model_rebuild() 1615 + RemoveApikeyParams.model_rebuild() 1616 + RemovePlaylistParams.model_rebuild() 1617 + RemoveShoutParams.model_rebuild() 1618 + RemoveTrackParams.model_rebuild() 1619 + ReplyShoutInput.model_rebuild() 1620 + ReportShoutInput.model_rebuild() 1621 + ScrobbleFirstScrobbleView.model_rebuild() 1622 + ScrobbleRecord.model_rebuild() 1623 + ScrobbleViewBasic.model_rebuild() 1624 + ScrobbleViewDetailed.model_rebuild() 1625 + SearchParams.model_rebuild() 1626 + SeekParams.model_rebuild() 1627 + ShoutAuthor.model_rebuild() 1628 + ShoutRecord.model_rebuild() 1629 + ShoutView.model_rebuild() 1630 + SongFirstScrobbleView.model_rebuild() 1631 + SongRecentListenerView.model_rebuild() 1632 + SongRecord.model_rebuild() 1633 + SongViewBasic.model_rebuild() 1634 + SongViewDetailed.model_rebuild() 1635 + SpotifyTrackView.model_rebuild() 1636 + StartPlaylistParams.model_rebuild() 1637 + StatsView.model_rebuild() 1638 + StatsWrappedAlbum.model_rebuild() 1639 + StatsWrappedArtist.model_rebuild() 1640 + StatsWrappedDayCount.model_rebuild() 1641 + StatsWrappedGenreCount.model_rebuild() 1642 + StatsWrappedMilestone.model_rebuild() 1643 + StatsWrappedMonthCount.model_rebuild() 1644 + StatsWrappedTrack.model_rebuild() 1645 + StatsWrappedView.model_rebuild() 1646 + StatusRecord.model_rebuild() 1647 + StrongRef.model_rebuild() 1648 + UnfollowAccountOutput.model_rebuild() 1649 + UnfollowAccountParams.model_rebuild() 1650 + UpdateApikeyInput.model_rebuild()
+1624
sdk/python/src/rocksky/gen/types.py
··· 1 + """AUTO-GENERATED FILE — DO NOT EDIT. 2 + 3 + Source: apps/api/lexicons/**/*.json 4 + Regenerate via: bun run lexgen:types 5 + """ 6 + from __future__ import annotations 7 + 8 + from dataclasses import dataclass, field 9 + from typing import Any, List, Optional, Union 10 + 11 + 12 + @dataclass 13 + class BlobRef: 14 + """atproto blob reference shape.""" 15 + 16 + type: Optional[str] = None 17 + ref: Optional[dict] = None 18 + mimeType: Optional[str] = None 19 + size: Optional[int] = None 20 + 21 + 22 + 23 + @dataclass 24 + class ActorArtistViewBasic: 25 + id: Optional[str] = None 26 + name: Optional[str] = None 27 + picture: Optional[str] = None 28 + uri: Optional[str] = None 29 + user1Rank: Optional[int] = None 30 + user2Rank: Optional[int] = None 31 + weight: Optional[int] = None 32 + 33 + 34 + @dataclass 35 + class ActorCompatibilityViewBasic: 36 + compatibilityLevel: Optional[int] = None 37 + compatibilityPercentage: Optional[int] = None 38 + sharedArtists: Optional[int] = None 39 + topSharedArtistNames: Optional[List[str]] = None 40 + topSharedDetailedArtists: Optional[List["ActorArtistViewBasic"]] = None 41 + user1ArtistCount: Optional[int] = None 42 + user2ArtistCount: Optional[int] = None 43 + 44 + 45 + @dataclass 46 + class ActorNeighbourViewBasic: 47 + userId: Optional[str] = None 48 + did: Optional[str] = None 49 + handle: Optional[str] = None 50 + displayName: Optional[str] = None 51 + avatar: Optional[str] = None 52 + sharedArtistsCount: Optional[int] = None 53 + similarityScore: Optional[int] = None 54 + topSharedArtistNames: Optional[List[str]] = None 55 + topSharedArtistsDetails: Optional[List["ArtistViewBasic"]] = None 56 + 57 + 58 + @dataclass 59 + class ActorProfileViewBasic: 60 + id: Optional[str] = None 61 + did: Optional[str] = None 62 + handle: Optional[str] = None 63 + displayName: Optional[str] = None 64 + avatar: Optional[str] = None 65 + createdAt: Optional[str] = None 66 + updatedAt: Optional[str] = None 67 + 68 + 69 + @dataclass 70 + class ActorProfileViewDetailed: 71 + id: Optional[str] = None 72 + did: Optional[str] = None 73 + handle: Optional[str] = None 74 + displayName: Optional[str] = None 75 + avatar: Optional[str] = None 76 + createdAt: Optional[str] = None 77 + updatedAt: Optional[str] = None 78 + 79 + 80 + @dataclass 81 + class ActorTrackView: 82 + name: str 83 + artist: str 84 + album: Optional[str] = None 85 + albumCoverUrl: Optional[str] = None 86 + durationMs: Optional[int] = None 87 + source: Optional[str] = None 88 + recordingMbId: Optional[str] = None 89 + 90 + 91 + @dataclass 92 + class AddDirectoryToQueueParams: 93 + directory: str 94 + playerId: Optional[str] = None 95 + position: Optional[int] = None 96 + shuffle: Optional[bool] = None 97 + 98 + 99 + @dataclass 100 + class AddItemsToQueueParams: 101 + items: List[str] 102 + playerId: Optional[str] = None 103 + position: Optional[int] = None 104 + shuffle: Optional[bool] = None 105 + 106 + 107 + @dataclass 108 + class AlbumRecord: 109 + title: str 110 + artist: str 111 + createdAt: str 112 + duration: Optional[int] = None 113 + releaseDate: Optional[str] = None 114 + year: Optional[int] = None 115 + genre: Optional[str] = None 116 + albumArt: Optional[BlobRef] = None 117 + albumArtUrl: Optional[str] = None 118 + tags: Optional[List[str]] = None 119 + youtubeLink: Optional[str] = None 120 + spotifyLink: Optional[str] = None 121 + tidalLink: Optional[str] = None 122 + appleMusicLink: Optional[str] = None 123 + 124 + 125 + @dataclass 126 + class AlbumViewBasic: 127 + id: Optional[str] = None 128 + uri: Optional[str] = None 129 + title: Optional[str] = None 130 + artist: Optional[str] = None 131 + artistUri: Optional[str] = None 132 + year: Optional[int] = None 133 + albumArt: Optional[str] = None 134 + releaseDate: Optional[str] = None 135 + sha256: Optional[str] = None 136 + playCount: Optional[int] = None 137 + uniqueListeners: Optional[int] = None 138 + 139 + 140 + @dataclass 141 + class AlbumViewDetailed: 142 + id: Optional[str] = None 143 + uri: Optional[str] = None 144 + title: Optional[str] = None 145 + artist: Optional[str] = None 146 + artistUri: Optional[str] = None 147 + year: Optional[int] = None 148 + albumArt: Optional[str] = None 149 + releaseDate: Optional[str] = None 150 + sha256: Optional[str] = None 151 + playCount: Optional[int] = None 152 + uniqueListeners: Optional[int] = None 153 + tags: Optional[List[str]] = None 154 + tracks: Optional[List["SongViewBasic"]] = None 155 + 156 + 157 + @dataclass 158 + class ApiKeyView: 159 + id: Optional[str] = None 160 + name: Optional[str] = None 161 + description: Optional[str] = None 162 + createdAt: Optional[str] = None 163 + 164 + 165 + @dataclass 166 + class ArtistListenerViewBasic: 167 + id: Optional[str] = None 168 + did: Optional[str] = None 169 + handle: Optional[str] = None 170 + displayName: Optional[str] = None 171 + avatar: Optional[str] = None 172 + mostListenedSong: Optional["ArtistSongViewBasic"] = None 173 + totalPlays: Optional[int] = None 174 + rank: Optional[int] = None 175 + 176 + 177 + @dataclass 178 + class ArtistMbid: 179 + mbid: Optional[str] = None 180 + name: Optional[str] = None 181 + 182 + 183 + @dataclass 184 + class ArtistRecentListenerView: 185 + id: Optional[str] = None 186 + did: Optional[str] = None 187 + handle: Optional[str] = None 188 + displayName: Optional[str] = None 189 + avatar: Optional[str] = None 190 + timestamp: Optional[str] = None 191 + scrobbleUri: Optional[str] = None 192 + 193 + 194 + @dataclass 195 + class ArtistRecord: 196 + name: str 197 + createdAt: str 198 + bio: Optional[str] = None 199 + picture: Optional[BlobRef] = None 200 + pictureUrl: Optional[str] = None 201 + tags: Optional[List[str]] = None 202 + born: Optional[str] = None 203 + died: Optional[str] = None 204 + bornIn: Optional[str] = None 205 + 206 + 207 + @dataclass 208 + class ArtistSongViewBasic: 209 + uri: Optional[str] = None 210 + title: Optional[str] = None 211 + playCount: Optional[int] = None 212 + 213 + 214 + @dataclass 215 + class ArtistViewBasic: 216 + id: Optional[str] = None 217 + uri: Optional[str] = None 218 + name: Optional[str] = None 219 + picture: Optional[str] = None 220 + sha256: Optional[str] = None 221 + playCount: Optional[int] = None 222 + uniqueListeners: Optional[int] = None 223 + tags: Optional[List[str]] = None 224 + 225 + 226 + @dataclass 227 + class ArtistViewDetailed: 228 + id: Optional[str] = None 229 + uri: Optional[str] = None 230 + name: Optional[str] = None 231 + picture: Optional[str] = None 232 + sha256: Optional[str] = None 233 + playCount: Optional[int] = None 234 + uniqueListeners: Optional[int] = None 235 + tags: Optional[List[str]] = None 236 + 237 + 238 + @dataclass 239 + class ChartsScrobbleViewBasic: 240 + date: Optional[str] = None 241 + count: Optional[int] = None 242 + 243 + 244 + @dataclass 245 + class ChartsView: 246 + scrobbles: Optional[List["ChartsScrobbleViewBasic"]] = None 247 + 248 + 249 + @dataclass 250 + class CreateApikeyInput: 251 + name: str 252 + description: Optional[str] = None 253 + 254 + 255 + @dataclass 256 + class CreatePlaylistParams: 257 + name: str 258 + description: Optional[str] = None 259 + 260 + 261 + @dataclass 262 + class CreateScrobbleInput: 263 + title: str 264 + artist: str 265 + album: Optional[str] = None 266 + duration: Optional[int] = None 267 + mbId: Optional[str] = None 268 + isrc: Optional[str] = None 269 + albumArt: Optional[str] = None 270 + trackNumber: Optional[int] = None 271 + releaseDate: Optional[str] = None 272 + year: Optional[int] = None 273 + discNumber: Optional[int] = None 274 + lyrics: Optional[str] = None 275 + composer: Optional[str] = None 276 + copyrightMessage: Optional[str] = None 277 + label: Optional[str] = None 278 + artistPicture: Optional[str] = None 279 + spotifyLink: Optional[str] = None 280 + lastfmLink: Optional[str] = None 281 + tidalLink: Optional[str] = None 282 + appleMusicLink: Optional[str] = None 283 + youtubeLink: Optional[str] = None 284 + deezerLink: Optional[str] = None 285 + timestamp: Optional[int] = None 286 + 287 + 288 + @dataclass 289 + class CreateShoutInput: 290 + message: Optional[str] = None 291 + 292 + 293 + @dataclass 294 + class CreateSongInput: 295 + title: str 296 + artist: str 297 + albumArtist: str 298 + album: str 299 + duration: Optional[int] = None 300 + mbId: Optional[str] = None 301 + isrc: Optional[str] = None 302 + albumArt: Optional[str] = None 303 + trackNumber: Optional[int] = None 304 + releaseDate: Optional[str] = None 305 + year: Optional[int] = None 306 + discNumber: Optional[int] = None 307 + lyrics: Optional[str] = None 308 + 309 + 310 + @dataclass 311 + class DescribeFeedGeneratorOutput: 312 + did: Optional[str] = None 313 + feeds: Optional[List["FeedUriView"]] = None 314 + 315 + 316 + @dataclass 317 + class DescribeFeedGeneratorParams: 318 + pass 319 + 320 + 321 + @dataclass 322 + class DislikeShoutInput: 323 + uri: Optional[str] = None 324 + 325 + 326 + @dataclass 327 + class DislikeSongInput: 328 + uri: Optional[str] = None 329 + 330 + 331 + @dataclass 332 + class DownloadFileParams: 333 + fileId: str 334 + 335 + 336 + @dataclass 337 + class DropboxFileListView: 338 + files: Optional[List["DropboxFileView"]] = None 339 + 340 + 341 + @dataclass 342 + class DropboxFileView: 343 + id: Optional[str] = None 344 + name: Optional[str] = None 345 + pathLower: Optional[str] = None 346 + pathDisplay: Optional[str] = None 347 + clientModified: Optional[str] = None 348 + serverModified: Optional[str] = None 349 + 350 + 351 + @dataclass 352 + class DropboxTemporaryLinkView: 353 + link: Optional[str] = None 354 + 355 + 356 + @dataclass 357 + class FeedGeneratorsView: 358 + feeds: Optional[List["FeedGeneratorView"]] = None 359 + 360 + 361 + @dataclass 362 + class FeedGeneratorView: 363 + id: Optional[str] = None 364 + name: Optional[str] = None 365 + description: Optional[str] = None 366 + uri: Optional[str] = None 367 + avatar: Optional[str] = None 368 + creator: Optional["ActorProfileViewBasic"] = None 369 + 370 + 371 + @dataclass 372 + class FeedItemView: 373 + scrobble: Optional["ScrobbleViewBasic"] = None 374 + 375 + 376 + @dataclass 377 + class FeedRecommendationsView: 378 + recommendations: Optional[List["FeedRecommendationView"]] = None 379 + cursor: Optional[str] = None 380 + 381 + 382 + @dataclass 383 + class FeedRecommendationView: 384 + title: Optional[str] = None 385 + artist: Optional[str] = None 386 + album: Optional[str] = None 387 + albumArt: Optional[str] = None 388 + trackUri: Optional[str] = None 389 + artistUri: Optional[str] = None 390 + albumUri: Optional[str] = None 391 + genres: Optional[List[str]] = None 392 + recommendationScore: Optional[int] = None 393 + source: Optional[str] = None 394 + likesCount: Optional[int] = None 395 + 396 + 397 + @dataclass 398 + class FeedRecommendedAlbumsView: 399 + albums: Optional[List["FeedRecommendedAlbumView"]] = None 400 + cursor: Optional[str] = None 401 + 402 + 403 + @dataclass 404 + class FeedRecommendedAlbumView: 405 + id: Optional[str] = None 406 + uri: Optional[str] = None 407 + title: Optional[str] = None 408 + artist: Optional[str] = None 409 + artistUri: Optional[str] = None 410 + year: Optional[int] = None 411 + albumArt: Optional[str] = None 412 + recommendationScore: Optional[int] = None 413 + source: Optional[str] = None 414 + 415 + 416 + @dataclass 417 + class FeedRecommendedArtistsView: 418 + artists: Optional[List["FeedRecommendedArtistView"]] = None 419 + cursor: Optional[str] = None 420 + 421 + 422 + @dataclass 423 + class FeedRecommendedArtistView: 424 + id: Optional[str] = None 425 + uri: Optional[str] = None 426 + name: Optional[str] = None 427 + picture: Optional[str] = None 428 + genres: Optional[List[str]] = None 429 + recommendationScore: Optional[int] = None 430 + source: Optional[str] = None 431 + 432 + 433 + @dataclass 434 + class FeedSearchResultsView: 435 + hits: Optional[List[Union["SongViewBasic", "AlbumViewBasic", "ArtistViewBasic", "PlaylistViewBasic", "ActorProfileViewBasic"]]] = None 436 + processingTimeMs: Optional[int] = None 437 + limit: Optional[int] = None 438 + offset: Optional[int] = None 439 + estimatedTotalHits: Optional[int] = None 440 + 441 + 442 + @dataclass 443 + class FeedStoriesView: 444 + stories: Optional[List["FeedStoryView"]] = None 445 + 446 + 447 + @dataclass 448 + class FeedStoryView: 449 + album: Optional[str] = None 450 + albumArt: Optional[str] = None 451 + albumArtist: Optional[str] = None 452 + albumUri: Optional[str] = None 453 + artist: Optional[str] = None 454 + artistUri: Optional[str] = None 455 + avatar: Optional[str] = None 456 + createdAt: Optional[str] = None 457 + did: Optional[str] = None 458 + handle: Optional[str] = None 459 + id: Optional[str] = None 460 + title: Optional[str] = None 461 + trackId: Optional[str] = None 462 + trackUri: Optional[str] = None 463 + uri: Optional[str] = None 464 + 465 + 466 + @dataclass 467 + class FeedUriView: 468 + uri: Optional[str] = None 469 + 470 + 471 + @dataclass 472 + class FeedView: 473 + feed: Optional[List["FeedItemView"]] = None 474 + cursor: Optional[str] = None 475 + 476 + 477 + @dataclass 478 + class FollowAccountOutput: 479 + subject: "ActorProfileViewBasic" 480 + followers: List["ActorProfileViewBasic"] 481 + cursor: Optional[str] = None 482 + 483 + 484 + @dataclass 485 + class FollowAccountParams: 486 + account: str 487 + 488 + 489 + @dataclass 490 + class FollowRecord: 491 + createdAt: str 492 + subject: str 493 + via: Optional["StrongRef"] = None 494 + 495 + 496 + @dataclass 497 + class GeneratorRecord: 498 + did: str 499 + displayName: str 500 + createdAt: str 501 + avatar: Optional[BlobRef] = None 502 + description: Optional[str] = None 503 + 504 + 505 + @dataclass 506 + class GetActorAlbumsOutput: 507 + albums: Optional[List["AlbumViewBasic"]] = None 508 + 509 + 510 + @dataclass 511 + class GetActorAlbumsParams: 512 + did: str 513 + limit: Optional[int] = None 514 + offset: Optional[int] = None 515 + startDate: Optional[str] = None 516 + endDate: Optional[str] = None 517 + 518 + 519 + @dataclass 520 + class GetActorArtistsOutput: 521 + artists: Optional[List["ArtistViewBasic"]] = None 522 + 523 + 524 + @dataclass 525 + class GetActorArtistsParams: 526 + did: str 527 + limit: Optional[int] = None 528 + offset: Optional[int] = None 529 + startDate: Optional[str] = None 530 + endDate: Optional[str] = None 531 + 532 + 533 + @dataclass 534 + class GetActorCompatibilityOutput: 535 + compatibility: Optional["ActorCompatibilityViewBasic"] = None 536 + 537 + 538 + @dataclass 539 + class GetActorCompatibilityParams: 540 + did: str 541 + 542 + 543 + @dataclass 544 + class GetActorLovedSongsOutput: 545 + tracks: Optional[List["SongViewBasic"]] = None 546 + 547 + 548 + @dataclass 549 + class GetActorLovedSongsParams: 550 + did: str 551 + limit: Optional[int] = None 552 + offset: Optional[int] = None 553 + 554 + 555 + @dataclass 556 + class GetActorNeighboursOutput: 557 + neighbours: Optional[List["ActorNeighbourViewBasic"]] = None 558 + 559 + 560 + @dataclass 561 + class GetActorNeighboursParams: 562 + did: str 563 + 564 + 565 + @dataclass 566 + class GetActorPlaylistsOutput: 567 + playlists: Optional[List["PlaylistViewBasic"]] = None 568 + 569 + 570 + @dataclass 571 + class GetActorPlaylistsParams: 572 + did: str 573 + limit: Optional[int] = None 574 + offset: Optional[int] = None 575 + 576 + 577 + @dataclass 578 + class GetActorScrobblesOutput: 579 + scrobbles: Optional[List["ScrobbleViewBasic"]] = None 580 + 581 + 582 + @dataclass 583 + class GetActorScrobblesParams: 584 + did: str 585 + limit: Optional[int] = None 586 + offset: Optional[int] = None 587 + 588 + 589 + @dataclass 590 + class GetActorSongsOutput: 591 + songs: Optional[List["SongViewBasic"]] = None 592 + 593 + 594 + @dataclass 595 + class GetActorSongsParams: 596 + did: str 597 + limit: Optional[int] = None 598 + offset: Optional[int] = None 599 + startDate: Optional[str] = None 600 + endDate: Optional[str] = None 601 + 602 + 603 + @dataclass 604 + class GetAlbumParams: 605 + uri: str 606 + 607 + 608 + @dataclass 609 + class GetAlbumRecommendationsParams: 610 + did: str 611 + limit: Optional[int] = None 612 + 613 + 614 + @dataclass 615 + class GetAlbumShoutsOutput: 616 + shouts: Optional[List[Any]] = None 617 + 618 + 619 + @dataclass 620 + class GetAlbumShoutsParams: 621 + uri: str 622 + limit: Optional[int] = None 623 + offset: Optional[int] = None 624 + 625 + 626 + @dataclass 627 + class GetAlbumsOutput: 628 + albums: Optional[List["AlbumViewBasic"]] = None 629 + 630 + 631 + @dataclass 632 + class GetAlbumsParams: 633 + limit: Optional[int] = None 634 + offset: Optional[int] = None 635 + genre: Optional[str] = None 636 + 637 + 638 + @dataclass 639 + class GetAlbumTracksOutput: 640 + tracks: Optional[List["SongViewBasic"]] = None 641 + 642 + 643 + @dataclass 644 + class GetAlbumTracksParams: 645 + uri: str 646 + 647 + 648 + @dataclass 649 + class GetApikeysOutput: 650 + apiKeys: Optional[List[Any]] = None 651 + 652 + 653 + @dataclass 654 + class GetApikeysParams: 655 + offset: Optional[int] = None 656 + limit: Optional[int] = None 657 + 658 + 659 + @dataclass 660 + class GetArtistAlbumsOutput: 661 + albums: Optional[List["AlbumViewBasic"]] = None 662 + 663 + 664 + @dataclass 665 + class GetArtistAlbumsParams: 666 + uri: str 667 + 668 + 669 + @dataclass 670 + class GetArtistListenersOutput: 671 + listeners: Optional[List["ArtistListenerViewBasic"]] = None 672 + 673 + 674 + @dataclass 675 + class GetArtistListenersParams: 676 + uri: str 677 + offset: Optional[int] = None 678 + limit: Optional[int] = None 679 + 680 + 681 + @dataclass 682 + class GetArtistParams: 683 + uri: str 684 + 685 + 686 + @dataclass 687 + class GetArtistRecentListenersOutput: 688 + listeners: Optional[List["ArtistRecentListenerView"]] = None 689 + 690 + 691 + @dataclass 692 + class GetArtistRecentListenersParams: 693 + uri: str 694 + offset: Optional[int] = None 695 + limit: Optional[int] = None 696 + 697 + 698 + @dataclass 699 + class GetArtistRecommendationsParams: 700 + did: str 701 + limit: Optional[int] = None 702 + 703 + 704 + @dataclass 705 + class GetArtistShoutsOutput: 706 + shouts: Optional[List[Any]] = None 707 + 708 + 709 + @dataclass 710 + class GetArtistShoutsParams: 711 + uri: str 712 + limit: Optional[int] = None 713 + offset: Optional[int] = None 714 + 715 + 716 + @dataclass 717 + class GetArtistsOutput: 718 + artists: Optional[List["ArtistViewBasic"]] = None 719 + 720 + 721 + @dataclass 722 + class GetArtistsParams: 723 + limit: Optional[int] = None 724 + offset: Optional[int] = None 725 + names: Optional[str] = None 726 + genre: Optional[str] = None 727 + 728 + 729 + @dataclass 730 + class GetArtistTracksOutput: 731 + tracks: Optional[List["SongViewBasic"]] = None 732 + 733 + 734 + @dataclass 735 + class GetArtistTracksParams: 736 + uri: Optional[str] = None 737 + limit: Optional[int] = None 738 + offset: Optional[int] = None 739 + 740 + 741 + @dataclass 742 + class GetCurrentlyPlayingParams: 743 + playerId: Optional[str] = None 744 + actor: Optional[str] = None 745 + 746 + 747 + @dataclass 748 + class GetFeedGeneratorOutput: 749 + view: Optional["FeedGeneratorView"] = None 750 + 751 + 752 + @dataclass 753 + class GetFeedGeneratorParams: 754 + feed: str 755 + 756 + 757 + @dataclass 758 + class GetFeedGeneratorsParams: 759 + size: Optional[int] = None 760 + 761 + 762 + @dataclass 763 + class GetFeedParams: 764 + feed: str 765 + limit: Optional[int] = None 766 + cursor: Optional[str] = None 767 + 768 + 769 + @dataclass 770 + class GetFeedSkeletonOutput: 771 + scrobbles: Optional[List["ScrobbleViewBasic"]] = None 772 + cursor: Optional[str] = None 773 + 774 + 775 + @dataclass 776 + class GetFeedSkeletonParams: 777 + feed: str 778 + limit: Optional[int] = None 779 + offset: Optional[int] = None 780 + cursor: Optional[str] = None 781 + 782 + 783 + @dataclass 784 + class GetFileParams: 785 + fileId: str 786 + 787 + 788 + @dataclass 789 + class GetFilesParams: 790 + at: Optional[str] = None 791 + 792 + 793 + @dataclass 794 + class GetFollowersOutput: 795 + subject: "ActorProfileViewBasic" 796 + followers: List["ActorProfileViewBasic"] 797 + cursor: Optional[str] = None 798 + count: Optional[int] = None 799 + 800 + 801 + @dataclass 802 + class GetFollowersParams: 803 + actor: str 804 + limit: Optional[int] = None 805 + dids: Optional[List[str]] = None 806 + cursor: Optional[str] = None 807 + 808 + 809 + @dataclass 810 + class GetFollowsOutput: 811 + subject: "ActorProfileViewBasic" 812 + follows: List["ActorProfileViewBasic"] 813 + cursor: Optional[str] = None 814 + count: Optional[int] = None 815 + 816 + 817 + @dataclass 818 + class GetFollowsParams: 819 + actor: str 820 + limit: Optional[int] = None 821 + dids: Optional[List[str]] = None 822 + cursor: Optional[str] = None 823 + 824 + 825 + @dataclass 826 + class GetKnownFollowersOutput: 827 + subject: "ActorProfileViewBasic" 828 + followers: List["ActorProfileViewBasic"] 829 + cursor: Optional[str] = None 830 + 831 + 832 + @dataclass 833 + class GetKnownFollowersParams: 834 + actor: str 835 + limit: Optional[int] = None 836 + cursor: Optional[str] = None 837 + 838 + 839 + @dataclass 840 + class GetMetadataParams: 841 + path: str 842 + 843 + 844 + @dataclass 845 + class GetMirrorSourcesOutput: 846 + sources: List["MirrorSourceView"] 847 + 848 + 849 + @dataclass 850 + class GetMirrorSourcesParams: 851 + pass 852 + 853 + 854 + @dataclass 855 + class GetPlaybackQueueParams: 856 + playerId: Optional[str] = None 857 + 858 + 859 + @dataclass 860 + class GetPlaylistParams: 861 + uri: str 862 + 863 + 864 + @dataclass 865 + class GetPlaylistsOutput: 866 + playlists: Optional[List["PlaylistViewBasic"]] = None 867 + 868 + 869 + @dataclass 870 + class GetPlaylistsParams: 871 + limit: Optional[int] = None 872 + offset: Optional[int] = None 873 + 874 + 875 + @dataclass 876 + class GetProfileParams: 877 + did: Optional[str] = None 878 + 879 + 880 + @dataclass 881 + class GetProfileShoutsOutput: 882 + shouts: Optional[List[Any]] = None 883 + 884 + 885 + @dataclass 886 + class GetProfileShoutsParams: 887 + did: str 888 + offset: Optional[int] = None 889 + limit: Optional[int] = None 890 + 891 + 892 + @dataclass 893 + class GetRecommendationsParams: 894 + did: str 895 + limit: Optional[int] = None 896 + 897 + 898 + @dataclass 899 + class GetScrobbleParams: 900 + uri: str 901 + 902 + 903 + @dataclass 904 + class GetScrobblesChartParams: 905 + did: Optional[str] = None 906 + artisturi: Optional[str] = None 907 + albumuri: Optional[str] = None 908 + songuri: Optional[str] = None 909 + genre: Optional[str] = None 910 + from_: Optional[str] = None 911 + to: Optional[str] = None 912 + 913 + 914 + @dataclass 915 + class GetScrobblesOutput: 916 + scrobbles: Optional[List["ScrobbleViewBasic"]] = None 917 + 918 + 919 + @dataclass 920 + class GetScrobblesParams: 921 + did: Optional[str] = None 922 + following: Optional[bool] = None 923 + limit: Optional[int] = None 924 + offset: Optional[int] = None 925 + 926 + 927 + @dataclass 928 + class GetShoutRepliesOutput: 929 + shouts: Optional[List[Any]] = None 930 + 931 + 932 + @dataclass 933 + class GetShoutRepliesParams: 934 + uri: str 935 + limit: Optional[int] = None 936 + offset: Optional[int] = None 937 + 938 + 939 + @dataclass 940 + class GetSongParams: 941 + uri: Optional[str] = None 942 + mbid: Optional[str] = None 943 + isrc: Optional[str] = None 944 + spotifyId: Optional[str] = None 945 + 946 + 947 + @dataclass 948 + class GetSongRecentListenersOutput: 949 + listeners: Optional[List["SongRecentListenerView"]] = None 950 + 951 + 952 + @dataclass 953 + class GetSongRecentListenersParams: 954 + uri: str 955 + offset: Optional[int] = None 956 + limit: Optional[int] = None 957 + 958 + 959 + @dataclass 960 + class GetSongsOutput: 961 + songs: Optional[List["SongViewBasic"]] = None 962 + 963 + 964 + @dataclass 965 + class GetSongsParams: 966 + limit: Optional[int] = None 967 + offset: Optional[int] = None 968 + genre: Optional[str] = None 969 + mbid: Optional[str] = None 970 + isrc: Optional[str] = None 971 + spotifyId: Optional[str] = None 972 + 973 + 974 + @dataclass 975 + class GetStatsParams: 976 + did: str 977 + 978 + 979 + @dataclass 980 + class GetStoriesParams: 981 + size: Optional[int] = None 982 + 983 + 984 + @dataclass 985 + class GetTemporaryLinkParams: 986 + path: str 987 + 988 + 989 + @dataclass 990 + class GetTopArtistsOutput: 991 + artists: Optional[List["ArtistViewBasic"]] = None 992 + 993 + 994 + @dataclass 995 + class GetTopArtistsParams: 996 + limit: Optional[int] = None 997 + offset: Optional[int] = None 998 + startDate: Optional[str] = None 999 + endDate: Optional[str] = None 1000 + 1001 + 1002 + @dataclass 1003 + class GetTopTracksOutput: 1004 + tracks: Optional[List["SongViewBasic"]] = None 1005 + 1006 + 1007 + @dataclass 1008 + class GetTopTracksParams: 1009 + limit: Optional[int] = None 1010 + offset: Optional[int] = None 1011 + startDate: Optional[str] = None 1012 + endDate: Optional[str] = None 1013 + 1014 + 1015 + @dataclass 1016 + class GetTrackShoutsOutput: 1017 + shouts: Optional[List[Any]] = None 1018 + 1019 + 1020 + @dataclass 1021 + class GetTrackShoutsParams: 1022 + uri: str 1023 + 1024 + 1025 + @dataclass 1026 + class GetWrappedParams: 1027 + did: str 1028 + year: Optional[int] = None 1029 + 1030 + 1031 + @dataclass 1032 + class GoogledriveFileListView: 1033 + files: Optional[List["GoogledriveFileView"]] = None 1034 + 1035 + 1036 + @dataclass 1037 + class GoogledriveFileView: 1038 + id: Optional[str] = None 1039 + 1040 + 1041 + @dataclass 1042 + class GraphNotFoundActor: 1043 + """indicates that a handle or DID could not be resolved""" 1044 + actor: str 1045 + notFound: bool 1046 + 1047 + 1048 + @dataclass 1049 + class GraphRelationship: 1050 + did: str 1051 + following: Optional[str] = None 1052 + followedBy: Optional[str] = None 1053 + 1054 + 1055 + @dataclass 1056 + class InsertDirectoryParams: 1057 + uri: str 1058 + directory: str 1059 + position: Optional[int] = None 1060 + 1061 + 1062 + @dataclass 1063 + class InsertFilesParams: 1064 + uri: str 1065 + files: List[str] 1066 + position: Optional[int] = None 1067 + 1068 + 1069 + @dataclass 1070 + class LikeRecord: 1071 + createdAt: str 1072 + subject: "StrongRef" 1073 + 1074 + 1075 + @dataclass 1076 + class LikeShoutInput: 1077 + uri: Optional[str] = None 1078 + 1079 + 1080 + @dataclass 1081 + class LikeSongInput: 1082 + uri: Optional[str] = None 1083 + 1084 + 1085 + @dataclass 1086 + class MatchSongParams: 1087 + title: str 1088 + artist: str 1089 + mbId: Optional[str] = None 1090 + isrc: Optional[str] = None 1091 + 1092 + 1093 + @dataclass 1094 + class MirrorSourceView: 1095 + provider: str 1096 + enabled: bool 1097 + hasCredentials: bool 1098 + externalUsername: Optional[str] = None 1099 + lastPolledAt: Optional[str] = None 1100 + lastScrobbleSeenAt: Optional[str] = None 1101 + 1102 + 1103 + @dataclass 1104 + class NextParams: 1105 + playerId: Optional[str] = None 1106 + 1107 + 1108 + @dataclass 1109 + class PauseParams: 1110 + playerId: Optional[str] = None 1111 + 1112 + 1113 + @dataclass 1114 + class PlayDirectoryParams: 1115 + directoryId: str 1116 + playerId: Optional[str] = None 1117 + shuffle: Optional[bool] = None 1118 + recurse: Optional[bool] = None 1119 + position: Optional[int] = None 1120 + 1121 + 1122 + @dataclass 1123 + class PlayerCurrentlyPlayingViewDetailed: 1124 + title: Optional[str] = None 1125 + 1126 + 1127 + @dataclass 1128 + class PlayerPlaybackQueueViewDetailed: 1129 + tracks: Optional[List["SongViewBasic"]] = None 1130 + 1131 + 1132 + @dataclass 1133 + class PlayFileParams: 1134 + fileId: str 1135 + playerId: Optional[str] = None 1136 + 1137 + 1138 + @dataclass 1139 + class PlaylistItemRecord: 1140 + subject: "StrongRef" 1141 + createdAt: str 1142 + track: "SongViewBasic" 1143 + order: int 1144 + 1145 + 1146 + @dataclass 1147 + class PlaylistRecord: 1148 + name: str 1149 + createdAt: str 1150 + description: Optional[str] = None 1151 + picture: Optional[BlobRef] = None 1152 + pictureUrl: Optional[str] = None 1153 + spotifyLink: Optional[str] = None 1154 + tidalLink: Optional[str] = None 1155 + youtubeLink: Optional[str] = None 1156 + appleMusicLink: Optional[str] = None 1157 + 1158 + 1159 + @dataclass 1160 + class PlaylistViewBasic: 1161 + """Basic view of a playlist, including its metadata""" 1162 + id: Optional[str] = None 1163 + title: Optional[str] = None 1164 + uri: Optional[str] = None 1165 + curatorDid: Optional[str] = None 1166 + curatorHandle: Optional[str] = None 1167 + curatorName: Optional[str] = None 1168 + curatorAvatarUrl: Optional[str] = None 1169 + description: Optional[str] = None 1170 + coverImageUrl: Optional[str] = None 1171 + createdAt: Optional[str] = None 1172 + trackCount: Optional[int] = None 1173 + 1174 + 1175 + @dataclass 1176 + class PlaylistViewDetailed: 1177 + """Detailed view of a playlist, including its tracks and metadata""" 1178 + id: Optional[str] = None 1179 + title: Optional[str] = None 1180 + uri: Optional[str] = None 1181 + curatorDid: Optional[str] = None 1182 + curatorHandle: Optional[str] = None 1183 + curatorName: Optional[str] = None 1184 + curatorAvatarUrl: Optional[str] = None 1185 + description: Optional[str] = None 1186 + coverImageUrl: Optional[str] = None 1187 + createdAt: Optional[str] = None 1188 + tracks: Optional[List["SongViewBasic"]] = None 1189 + 1190 + 1191 + @dataclass 1192 + class PlayParams: 1193 + playerId: Optional[str] = None 1194 + 1195 + 1196 + @dataclass 1197 + class PreviousParams: 1198 + playerId: Optional[str] = None 1199 + 1200 + 1201 + @dataclass 1202 + class ProfileRecord: 1203 + displayName: Optional[str] = None 1204 + description: Optional[str] = None 1205 + avatar: Optional[BlobRef] = None 1206 + banner: Optional[BlobRef] = None 1207 + labels: Optional[Union[Any]] = None 1208 + joinedViaStarterPack: Optional["StrongRef"] = None 1209 + createdAt: Optional[str] = None 1210 + 1211 + 1212 + @dataclass 1213 + class PutMirrorSourceInput: 1214 + provider: str 1215 + enabled: Optional[bool] = None 1216 + externalUsername: Optional[str] = None 1217 + apiKey: Optional[str] = None 1218 + 1219 + 1220 + @dataclass 1221 + class RadioRecord: 1222 + name: str 1223 + url: str 1224 + createdAt: str 1225 + description: Optional[str] = None 1226 + genre: Optional[str] = None 1227 + logo: Optional[BlobRef] = None 1228 + website: Optional[str] = None 1229 + 1230 + 1231 + @dataclass 1232 + class RadioViewBasic: 1233 + id: Optional[str] = None 1234 + name: Optional[str] = None 1235 + description: Optional[str] = None 1236 + createdAt: Optional[str] = None 1237 + 1238 + 1239 + @dataclass 1240 + class RadioViewDetailed: 1241 + id: Optional[str] = None 1242 + name: Optional[str] = None 1243 + description: Optional[str] = None 1244 + website: Optional[str] = None 1245 + url: Optional[str] = None 1246 + genre: Optional[str] = None 1247 + logo: Optional[str] = None 1248 + createdAt: Optional[str] = None 1249 + 1250 + 1251 + @dataclass 1252 + class RemoveApikeyParams: 1253 + id: str 1254 + 1255 + 1256 + @dataclass 1257 + class RemovePlaylistParams: 1258 + uri: str 1259 + 1260 + 1261 + @dataclass 1262 + class RemoveShoutParams: 1263 + id: str 1264 + 1265 + 1266 + @dataclass 1267 + class RemoveTrackParams: 1268 + uri: str 1269 + position: int 1270 + 1271 + 1272 + @dataclass 1273 + class ReplyShoutInput: 1274 + shoutId: str 1275 + message: str 1276 + 1277 + 1278 + @dataclass 1279 + class ReportShoutInput: 1280 + shoutId: str 1281 + reason: Optional[str] = None 1282 + 1283 + 1284 + @dataclass 1285 + class ScrobbleFirstScrobbleView: 1286 + handle: Optional[str] = None 1287 + avatar: Optional[str] = None 1288 + timestamp: Optional[str] = None 1289 + 1290 + 1291 + @dataclass 1292 + class ScrobbleRecord: 1293 + title: str 1294 + artist: str 1295 + albumArtist: str 1296 + album: str 1297 + duration: int 1298 + createdAt: str 1299 + artists: Optional[List["ArtistMbid"]] = None 1300 + trackNumber: Optional[int] = None 1301 + discNumber: Optional[int] = None 1302 + releaseDate: Optional[str] = None 1303 + year: Optional[int] = None 1304 + genre: Optional[str] = None 1305 + tags: Optional[List[str]] = None 1306 + composer: Optional[str] = None 1307 + lyrics: Optional[str] = None 1308 + copyrightMessage: Optional[str] = None 1309 + wiki: Optional[str] = None 1310 + albumArt: Optional[BlobRef] = None 1311 + albumArtUrl: Optional[str] = None 1312 + youtubeLink: Optional[str] = None 1313 + spotifyLink: Optional[str] = None 1314 + tidalLink: Optional[str] = None 1315 + appleMusicLink: Optional[str] = None 1316 + mbid: Optional[str] = None 1317 + label: Optional[str] = None 1318 + isrc: Optional[str] = None 1319 + 1320 + 1321 + @dataclass 1322 + class ScrobbleViewBasic: 1323 + id: Optional[str] = None 1324 + user: Optional[str] = None 1325 + userDisplayName: Optional[str] = None 1326 + userAvatar: Optional[str] = None 1327 + title: Optional[str] = None 1328 + artist: Optional[str] = None 1329 + artistUri: Optional[str] = None 1330 + album: Optional[str] = None 1331 + albumUri: Optional[str] = None 1332 + cover: Optional[str] = None 1333 + date: Optional[str] = None 1334 + uri: Optional[str] = None 1335 + sha256: Optional[str] = None 1336 + liked: Optional[bool] = None 1337 + likesCount: Optional[int] = None 1338 + 1339 + 1340 + @dataclass 1341 + class ScrobbleViewDetailed: 1342 + id: Optional[str] = None 1343 + user: Optional[str] = None 1344 + title: Optional[str] = None 1345 + artist: Optional[str] = None 1346 + artistUri: Optional[str] = None 1347 + album: Optional[str] = None 1348 + albumUri: Optional[str] = None 1349 + cover: Optional[str] = None 1350 + date: Optional[str] = None 1351 + uri: Optional[str] = None 1352 + sha256: Optional[str] = None 1353 + liked: Optional[bool] = None 1354 + likesCount: Optional[int] = None 1355 + listeners: Optional[int] = None 1356 + scrobbles: Optional[int] = None 1357 + artists: Optional[List["ArtistViewBasic"]] = None 1358 + firstScrobble: Optional["ScrobbleFirstScrobbleView"] = None 1359 + 1360 + 1361 + @dataclass 1362 + class SearchParams: 1363 + query: str 1364 + 1365 + 1366 + @dataclass 1367 + class SeekParams: 1368 + position: int 1369 + playerId: Optional[str] = None 1370 + 1371 + 1372 + @dataclass 1373 + class ShoutAuthor: 1374 + id: Optional[str] = None 1375 + did: Optional[str] = None 1376 + handle: Optional[str] = None 1377 + displayName: Optional[str] = None 1378 + avatar: Optional[str] = None 1379 + 1380 + 1381 + @dataclass 1382 + class ShoutRecord: 1383 + message: str 1384 + createdAt: str 1385 + subject: "StrongRef" 1386 + parent: Optional["StrongRef"] = None 1387 + 1388 + 1389 + @dataclass 1390 + class ShoutView: 1391 + id: Optional[str] = None 1392 + message: Optional[str] = None 1393 + parent: Optional[str] = None 1394 + createdAt: Optional[str] = None 1395 + author: Optional["ShoutAuthor"] = None 1396 + 1397 + 1398 + @dataclass 1399 + class SongFirstScrobbleView: 1400 + handle: Optional[str] = None 1401 + avatar: Optional[str] = None 1402 + timestamp: Optional[str] = None 1403 + 1404 + 1405 + @dataclass 1406 + class SongRecentListenerView: 1407 + id: Optional[str] = None 1408 + did: Optional[str] = None 1409 + handle: Optional[str] = None 1410 + displayName: Optional[str] = None 1411 + avatar: Optional[str] = None 1412 + timestamp: Optional[str] = None 1413 + scrobbleUri: Optional[str] = None 1414 + 1415 + 1416 + @dataclass 1417 + class SongRecord: 1418 + title: str 1419 + artist: str 1420 + albumArtist: str 1421 + album: str 1422 + duration: int 1423 + createdAt: str 1424 + artists: Optional[List["ArtistMbid"]] = None 1425 + trackNumber: Optional[int] = None 1426 + discNumber: Optional[int] = None 1427 + releaseDate: Optional[str] = None 1428 + year: Optional[int] = None 1429 + genre: Optional[str] = None 1430 + tags: Optional[List[str]] = None 1431 + composer: Optional[str] = None 1432 + lyrics: Optional[str] = None 1433 + copyrightMessage: Optional[str] = None 1434 + wiki: Optional[str] = None 1435 + albumArt: Optional[BlobRef] = None 1436 + albumArtUrl: Optional[str] = None 1437 + youtubeLink: Optional[str] = None 1438 + spotifyLink: Optional[str] = None 1439 + tidalLink: Optional[str] = None 1440 + appleMusicLink: Optional[str] = None 1441 + mbid: Optional[str] = None 1442 + label: Optional[str] = None 1443 + isrc: Optional[str] = None 1444 + 1445 + 1446 + @dataclass 1447 + class SongViewBasic: 1448 + id: Optional[str] = None 1449 + title: Optional[str] = None 1450 + artist: Optional[str] = None 1451 + albumArtist: Optional[str] = None 1452 + albumArt: Optional[str] = None 1453 + uri: Optional[str] = None 1454 + album: Optional[str] = None 1455 + duration: Optional[int] = None 1456 + trackNumber: Optional[int] = None 1457 + discNumber: Optional[int] = None 1458 + playCount: Optional[int] = None 1459 + uniqueListeners: Optional[int] = None 1460 + albumUri: Optional[str] = None 1461 + artistUri: Optional[str] = None 1462 + sha256: Optional[str] = None 1463 + mbid: Optional[str] = None 1464 + isrc: Optional[str] = None 1465 + tags: Optional[List[str]] = None 1466 + createdAt: Optional[str] = None 1467 + 1468 + 1469 + @dataclass 1470 + class SongViewDetailed: 1471 + id: Optional[str] = None 1472 + title: Optional[str] = None 1473 + artist: Optional[str] = None 1474 + albumArtist: Optional[str] = None 1475 + albumArt: Optional[str] = None 1476 + uri: Optional[str] = None 1477 + album: Optional[str] = None 1478 + duration: Optional[int] = None 1479 + trackNumber: Optional[int] = None 1480 + discNumber: Optional[int] = None 1481 + playCount: Optional[int] = None 1482 + uniqueListeners: Optional[int] = None 1483 + albumUri: Optional[str] = None 1484 + artistUri: Optional[str] = None 1485 + sha256: Optional[str] = None 1486 + mbid: Optional[str] = None 1487 + isrc: Optional[str] = None 1488 + tags: Optional[List[str]] = None 1489 + createdAt: Optional[str] = None 1490 + artists: Optional[List["ArtistViewBasic"]] = None 1491 + firstScrobble: Optional["SongFirstScrobbleView"] = None 1492 + 1493 + 1494 + @dataclass 1495 + class SpotifyTrackView: 1496 + id: Optional[str] = None 1497 + name: Optional[str] = None 1498 + artist: Optional[str] = None 1499 + album: Optional[str] = None 1500 + duration: Optional[int] = None 1501 + previewUrl: Optional[str] = None 1502 + 1503 + 1504 + @dataclass 1505 + class StartPlaylistParams: 1506 + uri: str 1507 + shuffle: Optional[bool] = None 1508 + position: Optional[int] = None 1509 + 1510 + 1511 + @dataclass 1512 + class StatsView: 1513 + scrobbles: Optional[int] = None 1514 + artists: Optional[int] = None 1515 + lovedTracks: Optional[int] = None 1516 + albums: Optional[int] = None 1517 + tracks: Optional[int] = None 1518 + 1519 + 1520 + @dataclass 1521 + class StatsWrappedAlbum: 1522 + id: Optional[str] = None 1523 + title: Optional[str] = None 1524 + artist: Optional[str] = None 1525 + albumArt: Optional[str] = None 1526 + uri: Optional[str] = None 1527 + playCount: Optional[int] = None 1528 + 1529 + 1530 + @dataclass 1531 + class StatsWrappedArtist: 1532 + id: Optional[str] = None 1533 + name: Optional[str] = None 1534 + picture: Optional[str] = None 1535 + uri: Optional[str] = None 1536 + playCount: Optional[int] = None 1537 + 1538 + 1539 + @dataclass 1540 + class StatsWrappedDayCount: 1541 + date: Optional[str] = None 1542 + count: Optional[int] = None 1543 + 1544 + 1545 + @dataclass 1546 + class StatsWrappedGenreCount: 1547 + genre: Optional[str] = None 1548 + count: Optional[int] = None 1549 + 1550 + 1551 + @dataclass 1552 + class StatsWrappedMilestone: 1553 + trackTitle: Optional[str] = None 1554 + artistName: Optional[str] = None 1555 + timestamp: Optional[str] = None 1556 + trackUri: Optional[str] = None 1557 + 1558 + 1559 + @dataclass 1560 + class StatsWrappedMonthCount: 1561 + month: Optional[int] = None 1562 + count: Optional[int] = None 1563 + 1564 + 1565 + @dataclass 1566 + class StatsWrappedTrack: 1567 + id: Optional[str] = None 1568 + title: Optional[str] = None 1569 + artist: Optional[str] = None 1570 + albumArt: Optional[str] = None 1571 + uri: Optional[str] = None 1572 + artistUri: Optional[str] = None 1573 + albumUri: Optional[str] = None 1574 + playCount: Optional[int] = None 1575 + 1576 + 1577 + @dataclass 1578 + class StatsWrappedView: 1579 + year: Optional[int] = None 1580 + totalScrobbles: Optional[int] = None 1581 + totalListeningTimeMinutes: Optional[int] = None 1582 + topArtists: Optional[List["StatsWrappedArtist"]] = None 1583 + topTracks: Optional[List["StatsWrappedTrack"]] = None 1584 + topAlbums: Optional[List["StatsWrappedAlbum"]] = None 1585 + topGenres: Optional[List["StatsWrappedGenreCount"]] = None 1586 + scrobblesPerMonth: Optional[List["StatsWrappedMonthCount"]] = None 1587 + mostActiveDay: Optional["StatsWrappedDayCount"] = None 1588 + mostActiveHour: Optional[int] = None 1589 + newArtistsCount: Optional[int] = None 1590 + longestStreak: Optional[int] = None 1591 + firstScrobble: Optional["StatsWrappedMilestone"] = None 1592 + lastScrobble: Optional["StatsWrappedMilestone"] = None 1593 + 1594 + 1595 + @dataclass 1596 + class StatusRecord: 1597 + track: "ActorTrackView" 1598 + startedAt: str 1599 + expiresAt: Optional[str] = None 1600 + 1601 + 1602 + @dataclass 1603 + class StrongRef: 1604 + uri: str 1605 + cid: str 1606 + 1607 + 1608 + @dataclass 1609 + class UnfollowAccountOutput: 1610 + subject: "ActorProfileViewBasic" 1611 + followers: List["ActorProfileViewBasic"] 1612 + cursor: Optional[str] = None 1613 + 1614 + 1615 + @dataclass 1616 + class UnfollowAccountParams: 1617 + account: str 1618 + 1619 + 1620 + @dataclass 1621 + class UpdateApikeyInput: 1622 + id: str 1623 + name: str 1624 + description: Optional[str] = None
+41 -333
sdk/python/src/rocksky/models.py
··· 1 - """Pydantic models for Rocksky API responses. 1 + """Backward-compatible model surface for Rocksky SDK consumers. 2 2 3 - The API speaks camelCase JSON; models accept both camelCase (alias) and snake_case 4 - (field name) so consumers may use whichever feels natural. Unknown fields are 5 - preserved rather than rejected, so additions to the API surface won't break 6 - existing SDK consumers. 3 + Lexicon-derived types are auto-generated in ``rocksky.gen.models``. This module 4 + re-exports them under the historical SDK names and extends a few with fields 5 + that the public API returns but the lexicon does not yet declare. 7 6 """ 8 7 9 8 from __future__ import annotations ··· 11 10 from datetime import datetime 12 11 from typing import Any 13 12 14 - from pydantic import BaseModel, ConfigDict, Field 13 + from pydantic import Field 14 + 15 + from .gen.models import ( 16 + ActorCompatibilityViewBasic as Compatibility, 17 + ActorNeighbourViewBasic as Neighbour, 18 + ActorProfileViewBasic as ProfileBasic, 19 + AlbumViewBasic as AlbumBasic, 20 + ApiKeyView as ApiKeyBase, 21 + ArtistListenerViewBasic as ArtistListener, 22 + ArtistViewBasic as ArtistBasic, 23 + FeedGeneratorView as FeedGenerator, 24 + FeedItemView as FeedItem, 25 + FeedRecommendationsView as Recommendations, 26 + FeedRecommendationView as Recommendation, 27 + FeedRecommendedAlbumView as RecommendedAlbum, 28 + FeedRecommendedArtistView as RecommendedArtist, 29 + FeedSearchResultsView as SearchResults, 30 + FeedStoryView as Story, 31 + FeedView as Feed, 32 + MirrorSourceView as MirrorSource, 33 + PlaylistViewBasic as PlaylistBasic, 34 + RockskyModel, 35 + ScrobbleViewBasic as ScrobbleBase, 36 + ShoutAuthor, 37 + ShoutView as Shout, 38 + SongFirstScrobbleView as FirstScrobble, 39 + SongRecentListenerView as RecentListener, 40 + SongViewBasic as SongBasic, 41 + ) 15 42 16 43 __all__ = [ 17 44 "Album", ··· 47 74 ] 48 75 49 76 50 - def _camel(name: str) -> str: 51 - head, *tail = name.split("_") 52 - return head + "".join(part.title() for part in tail) 53 - 54 - 55 - class RockskyModel(BaseModel): 56 - """Base model used by every SDK response type.""" 57 - 58 - model_config = ConfigDict( 59 - alias_generator=_camel, 60 - populate_by_name=True, 61 - extra="allow", 62 - str_strip_whitespace=True, 63 - ) 64 - 65 - 66 - # --------------------------------------------------------------------------- # 67 - # Actor 68 - # --------------------------------------------------------------------------- # 69 - 70 - 71 - class ProfileBasic(RockskyModel): 72 - id: str | None = None 73 - did: str | None = None 74 - handle: str | None = None 75 - display_name: str | None = None 76 - avatar: str | None = None 77 - created_at: datetime | None = None 78 - updated_at: datetime | None = None 79 - 80 - 81 77 class Profile(ProfileBasic): 82 78 spotify_connected: bool | None = None 83 79 spotify_user: dict[str, Any] | None = None ··· 86 82 dropbox: dict[str, Any] | None = None 87 83 88 84 89 - # --------------------------------------------------------------------------- # 90 - # Artist 91 - # --------------------------------------------------------------------------- # 92 - 93 - 94 - class ArtistBasic(RockskyModel): 95 - id: str | None = None 96 - uri: str | None = None 97 - name: str | None = None 98 - picture: str | None = None 99 - sha256: str | None = None 100 - play_count: int | None = None 101 - unique_listeners: int | None = None 102 - tags: list[str] | None = None 103 - 104 - 105 85 class Artist(ArtistBasic): 106 86 """Detailed artist view (currently identical fields to basic on the server).""" 107 87 108 88 109 - # --------------------------------------------------------------------------- # 110 - # Album 111 - # --------------------------------------------------------------------------- # 112 - 113 - 114 - class AlbumBasic(RockskyModel): 115 - id: str | None = None 116 - uri: str | None = None 117 - title: str | None = None 118 - artist: str | None = None 119 - artist_uri: str | None = None 120 - year: int | None = None 121 - album_art: str | None = None 122 - release_date: str | None = None 123 - sha256: str | None = None 124 - play_count: int | None = None 125 - unique_listeners: int | None = None 126 - 127 - 128 89 class Album(AlbumBasic): 129 90 tags: list[str] | None = None 130 91 tracks: list[SongBasic] | None = None 131 92 132 93 133 - # --------------------------------------------------------------------------- # 134 - # Song 135 - # --------------------------------------------------------------------------- # 136 - 137 - 138 - class FirstScrobble(RockskyModel): 139 - handle: str | None = None 140 - avatar: str | None = None 141 - timestamp: datetime | None = None 142 - 143 - 144 - class SongBasic(RockskyModel): 145 - id: str | None = None 146 - title: str | None = None 147 - artist: str | None = None 148 - album_artist: str | None = None 149 - album_art: str | None = None 150 - uri: str | None = None 151 - album: str | None = None 152 - duration: int | None = None 153 - track_number: int | None = None 154 - disc_number: int | None = None 155 - play_count: int | None = None 156 - unique_listeners: int | None = None 157 - album_uri: str | None = None 158 - artist_uri: str | None = None 159 - sha256: str | None = None 160 - mbid: str | None = None 161 - isrc: str | None = None 162 - tags: list[str] | None = None 163 - created_at: datetime | None = None 164 - 165 - 166 94 class Song(SongBasic): 167 95 artists: list[ArtistBasic] | None = None 168 96 first_scrobble: FirstScrobble | None = None 169 97 170 98 171 - class RecentListener(RockskyModel): 172 - id: str | None = None 173 - did: str | None = None 174 - handle: str | None = None 175 - display_name: str | None = None 176 - avatar: str | None = None 177 - timestamp: datetime | None = None 178 - scrobble_uri: str | None = None 179 - 180 - 181 - class ArtistListener(RockskyModel): 182 - id: str | None = None 183 - did: str | None = None 184 - handle: str | None = None 185 - display_name: str | None = None 186 - avatar: str | None = None 187 - most_listened_song: dict[str, Any] | None = None 188 - total_plays: int | None = None 189 - rank: int | None = None 190 - 191 - 192 - # --------------------------------------------------------------------------- # 193 - # Scrobble 194 - # --------------------------------------------------------------------------- # 195 - 196 - 197 - class Scrobble(RockskyModel): 198 - id: str | None = None 199 - user: str | None = None 200 - user_display_name: str | None = None 201 - user_avatar: str | None = None 202 - title: str | None = None 203 - artist: str | None = None 204 - artist_uri: str | None = None 205 - album: str | None = None 206 - album_uri: str | None = None 207 - cover: str | None = None 208 - date: datetime | None = None 209 - uri: str | None = None 210 - sha256: str | None = None 211 - liked: bool | None = None 212 - likes_count: int | None = None 99 + class Scrobble(ScrobbleBase): 213 100 listeners: int | None = None 214 101 scrobbles: int | None = None 215 102 artists: list[ArtistBasic] | None = None 216 103 first_scrobble: FirstScrobble | None = None 217 104 218 105 219 - # --------------------------------------------------------------------------- # 220 - # Shouts 221 - # --------------------------------------------------------------------------- # 222 - 223 - 224 - class ShoutAuthor(RockskyModel): 225 - id: str | None = None 226 - did: str | None = None 227 - handle: str | None = None 228 - display_name: str | None = None 229 - avatar: str | None = None 230 - 231 - 232 - class Shout(RockskyModel): 233 - id: str | None = None 234 - message: str | None = None 235 - parent: str | None = None 236 - created_at: datetime | None = None 237 - author: ShoutAuthor | None = None 238 - 239 - 240 - # --------------------------------------------------------------------------- # 241 - # API Keys 242 - # --------------------------------------------------------------------------- # 106 + class Playlist(PlaylistBasic): 107 + tracks: list[SongBasic] | None = None 243 108 244 109 245 - class ApiKey(RockskyModel): 246 - id: str | None = None 247 - name: str | None = None 248 - description: str | None = None 110 + class ApiKey(ApiKeyBase): 249 111 enabled: bool | None = None 250 112 api_key: str | None = Field(default=None, alias="apiKey") 251 113 shared_secret: str | None = Field(default=None, alias="sharedSecret") 252 - created_at: datetime | None = None 253 - updated_at: datetime | None = None 254 - 255 - 256 - # --------------------------------------------------------------------------- # 257 - # Playlist 258 - # --------------------------------------------------------------------------- # 259 - 260 - 261 - class PlaylistBasic(RockskyModel): 262 - id: str | None = None 263 - title: str | None = None 264 - uri: str | None = None 265 - curator_did: str | None = None 266 - curator_handle: str | None = None 267 - curator_name: str | None = None 268 - curator_avatar_url: str | None = None 269 - description: str | None = None 270 - cover_image_url: str | None = None 271 - created_at: datetime | None = None 272 - track_count: int | None = None 273 - 274 - 275 - class Playlist(PlaylistBasic): 276 - tracks: list[SongBasic] | None = None 277 - 278 - 279 - # --------------------------------------------------------------------------- # 280 - # Feed 281 - # --------------------------------------------------------------------------- # 282 - 283 - 284 - class FeedGenerator(RockskyModel): 285 - id: str | None = None 286 - name: str | None = None 287 - description: str | None = None 288 - uri: str | None = None 289 - avatar: str | None = None 290 - creator: ProfileBasic | None = None 291 - 292 - 293 - class FeedItem(RockskyModel): 294 - scrobble: Scrobble | None = None 295 - 296 - 297 - class Feed(RockskyModel): 298 - feed: list[FeedItem] = Field(default_factory=list) 299 - cursor: str | None = None 300 - 301 - 302 - class Story(RockskyModel): 303 - id: str | None = None 304 - did: str | None = None 305 - handle: str | None = None 306 - avatar: str | None = None 307 - title: str | None = None 308 - artist: str | None = None 309 - artist_uri: str | None = None 310 - album: str | None = None 311 - album_uri: str | None = None 312 - album_artist: str | None = None 313 - album_art: str | None = None 314 - created_at: str | None = None 315 - track_id: str | None = None 316 - track_uri: str | None = None 317 - uri: str | None = None 318 - 319 - 320 - class Recommendation(RockskyModel): 321 - title: str | None = None 322 - artist: str | None = None 323 - album: str | None = None 324 - album_art: str | None = None 325 - track_uri: str | None = None 326 - artist_uri: str | None = None 327 - album_uri: str | None = None 328 - genres: list[str] | None = None 329 - recommendation_score: int | None = None 330 - source: str | None = None 331 - likes_count: int | None = None 332 - 333 - 334 - class Recommendations(RockskyModel): 335 - recommendations: list[Recommendation] = Field(default_factory=list) 336 - cursor: str | None = None 337 - 338 - 339 - class RecommendedArtist(RockskyModel): 340 - id: str | None = None 341 - uri: str | None = None 342 - name: str | None = None 343 - picture: str | None = None 344 - genres: list[str] | None = None 345 - recommendation_score: int | None = None 346 - source: str | None = None 347 - 348 - 349 - class RecommendedAlbum(RockskyModel): 350 - id: str | None = None 351 - uri: str | None = None 352 - title: str | None = None 353 - artist: str | None = None 354 - artist_uri: str | None = None 355 - year: int | None = None 356 - album_art: str | None = None 357 - recommendation_score: int | None = None 358 - source: str | None = None 359 - 360 - 361 - class SearchResults(RockskyModel): 362 - """Heterogeneous search hits — items may be songs, albums, artists, playlists, or profiles.""" 363 - 364 - hits: list[dict[str, Any]] = Field(default_factory=list) 365 - processing_time_ms: int | None = None 366 - limit: int | None = None 367 - offset: int | None = None 368 - estimated_total_hits: int | None = None 369 - 370 - 371 - # --------------------------------------------------------------------------- # 372 - # Actor compatibility / neighbours 373 - # --------------------------------------------------------------------------- # 374 - 375 - 376 - class Compatibility(RockskyModel): 377 - compatibility_level: int | None = None 378 - compatibility_percentage: int | None = None 379 - shared_artists: int | None = None 380 - top_shared_artist_names: list[str] | None = None 381 - top_shared_detailed_artists: list[ArtistBasic] | None = None 382 - user1_artist_count: int | None = None 383 - user2_artist_count: int | None = None 384 - 385 - 386 - class Neighbour(RockskyModel): 387 - user_id: str | None = None 388 - did: str | None = None 389 - handle: str | None = None 390 - display_name: str | None = None 391 - avatar: str | None = None 392 - shared_artists_count: int | None = None 393 - similarity_score: int | None = None 394 - top_shared_artist_names: list[str] | None = None 395 - top_shared_artists_details: list[ArtistBasic] | None = None 396 - 397 - 398 - # --------------------------------------------------------------------------- # 399 - # Mirror 400 - # --------------------------------------------------------------------------- # 401 - 402 - 403 - class MirrorSource(RockskyModel): 404 - id: str | None = None 405 - kind: str | None = None 406 - enabled: bool | None = None 407 - config: dict[str, Any] | None = None 408 - created_at: datetime | None = None 409 - updated_at: datetime | None = None 114 + updated_at: datetime | None = Field(default=None, alias="updatedAt") 410 115 411 116 412 117 Album.model_rebuild() 118 + Playlist.model_rebuild() 119 + Song.model_rebuild() 120 + Scrobble.model_rebuild()
+6
sdk/ruby/CHANGELOG.md
··· 1 1 # Changelog 2 2 3 + ## 0.2.0 4 + 5 + - Added lexicon-derived `Struct`s under `Rocksky::Generated::*` covering every 6 + lex `*View*` / `*Record` / `*Input` / `*Output` / `*Params` shape. Generated 7 + from `apps/api/lexicons/` via `bun run lexgen:types` at the repo root. 8 + 3 9 ## 0.1.0 4 10 5 11 - Initial release. Coverage for all `app.rocksky.*` XRPC endpoints across the
+5
sdk/ruby/README.md
··· 194 194 | `open_timeout` | `10` seconds | — | 195 195 | `read_timeout` | `30` seconds | — | 196 196 197 + ## Types 198 + 199 + Lexicon-derived `Struct` types are available under `Rocksky::Generated::*`, mirroring every lex `*View*` / `*Record` / `*Input` / `*Output` / `*Params` shape from [the Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons). Regenerate with `bun run lexgen:types` at the repo root. 200 + 201 + 197 202 ## Examples 198 203 199 204 The `examples/` directory contains runnable scripts:
+1
sdk/ruby/lib/rocksky.rb
··· 19 19 require "rocksky/resources/spotify" 20 20 require "rocksky/resources/stats" 21 21 require "rocksky/client" 22 + require "rocksky/generated/types" 22 23 23 24 module Rocksky 24 25 # Build a new Rocksky client.
+217
sdk/ruby/lib/rocksky/generated/types.rb
··· 1 + # frozen_string_literal: true 2 + # AUTO-GENERATED FILE -- DO NOT EDIT. 3 + # Source: apps/api/lexicons/**/*.json 4 + # Regenerate via: bun run lexgen:types 5 + 6 + module Rocksky 7 + module Generated 8 + BlobRef = Struct.new(:type, :ref, :mimeType, :size, keyword_init: true) 9 + 10 + ActorArtistViewBasic = Struct.new(:id, :name, :picture, :uri, :user1Rank, :user2Rank, :weight, keyword_init: true) 11 + ActorCompatibilityViewBasic = Struct.new(:compatibilityLevel, :compatibilityPercentage, :sharedArtists, :topSharedArtistNames, :topSharedDetailedArtists, :user1ArtistCount, :user2ArtistCount, keyword_init: true) 12 + ActorNeighbourViewBasic = Struct.new(:userId, :did, :handle, :displayName, :avatar, :sharedArtistsCount, :similarityScore, :topSharedArtistNames, :topSharedArtistsDetails, keyword_init: true) 13 + ActorProfileViewBasic = Struct.new(:id, :did, :handle, :displayName, :avatar, :createdAt, :updatedAt, keyword_init: true) 14 + ActorProfileViewDetailed = Struct.new(:id, :did, :handle, :displayName, :avatar, :createdAt, :updatedAt, keyword_init: true) 15 + ActorTrackView = Struct.new(:name, :artist, :album, :albumCoverUrl, :durationMs, :source, :recordingMbId, keyword_init: true) 16 + AddDirectoryToQueueParams = Struct.new(:playerId, :directory, :position, :shuffle, keyword_init: true) 17 + AddItemsToQueueParams = Struct.new(:playerId, :items, :position, :shuffle, keyword_init: true) 18 + AlbumRecord = Struct.new(:title, :artist, :duration, :releaseDate, :year, :genre, :albumArt, :albumArtUrl, :tags, :youtubeLink, :spotifyLink, :tidalLink, :appleMusicLink, :createdAt, keyword_init: true) 19 + AlbumViewBasic = Struct.new(:id, :uri, :title, :artist, :artistUri, :year, :albumArt, :releaseDate, :sha256, :playCount, :uniqueListeners, keyword_init: true) 20 + AlbumViewDetailed = Struct.new(:id, :uri, :title, :artist, :artistUri, :year, :albumArt, :releaseDate, :sha256, :playCount, :uniqueListeners, :tags, :tracks, keyword_init: true) 21 + ApiKeyView = Struct.new(:id, :name, :description, :createdAt, keyword_init: true) 22 + ArtistListenerViewBasic = Struct.new(:id, :did, :handle, :displayName, :avatar, :mostListenedSong, :totalPlays, :rank, keyword_init: true) 23 + ArtistMbid = Struct.new(:mbid, :name, keyword_init: true) 24 + ArtistRecentListenerView = Struct.new(:id, :did, :handle, :displayName, :avatar, :timestamp, :scrobbleUri, keyword_init: true) 25 + ArtistRecord = Struct.new(:name, :bio, :picture, :pictureUrl, :tags, :born, :died, :bornIn, :createdAt, keyword_init: true) 26 + ArtistSongViewBasic = Struct.new(:uri, :title, :playCount, keyword_init: true) 27 + ArtistViewBasic = Struct.new(:id, :uri, :name, :picture, :sha256, :playCount, :uniqueListeners, :tags, keyword_init: true) 28 + ArtistViewDetailed = Struct.new(:id, :uri, :name, :picture, :sha256, :playCount, :uniqueListeners, :tags, keyword_init: true) 29 + ChartsScrobbleViewBasic = Struct.new(:date, :count, keyword_init: true) 30 + ChartsView = Struct.new(:scrobbles, keyword_init: true) 31 + CreateApikeyInput = Struct.new(:name, :description, keyword_init: true) 32 + CreatePlaylistParams = Struct.new(:name, :description, keyword_init: true) 33 + CreateScrobbleInput = Struct.new(:title, :artist, :album, :duration, :mbId, :isrc, :albumArt, :trackNumber, :releaseDate, :year, :discNumber, :lyrics, :composer, :copyrightMessage, :label, :artistPicture, :spotifyLink, :lastfmLink, :tidalLink, :appleMusicLink, :youtubeLink, :deezerLink, :timestamp, keyword_init: true) 34 + CreateShoutInput = Struct.new(:message, keyword_init: true) 35 + CreateSongInput = Struct.new(:title, :artist, :albumArtist, :album, :duration, :mbId, :isrc, :albumArt, :trackNumber, :releaseDate, :year, :discNumber, :lyrics, keyword_init: true) 36 + DescribeFeedGeneratorOutput = Struct.new(:did, :feeds, keyword_init: true) 37 + DescribeFeedGeneratorParams = Struct.new(keyword_init: true) 38 + DislikeShoutInput = Struct.new(:uri, keyword_init: true) 39 + DislikeSongInput = Struct.new(:uri, keyword_init: true) 40 + DownloadFileParams = Struct.new(:fileId, keyword_init: true) 41 + DropboxFileListView = Struct.new(:files, keyword_init: true) 42 + DropboxFileView = Struct.new(:id, :name, :pathLower, :pathDisplay, :clientModified, :serverModified, keyword_init: true) 43 + DropboxTemporaryLinkView = Struct.new(:link, keyword_init: true) 44 + FeedGeneratorsView = Struct.new(:feeds, keyword_init: true) 45 + FeedGeneratorView = Struct.new(:id, :name, :description, :uri, :avatar, :creator, keyword_init: true) 46 + FeedItemView = Struct.new(:scrobble, keyword_init: true) 47 + FeedRecommendationsView = Struct.new(:recommendations, :cursor, keyword_init: true) 48 + FeedRecommendationView = Struct.new(:title, :artist, :album, :albumArt, :trackUri, :artistUri, :albumUri, :genres, :recommendationScore, :source, :likesCount, keyword_init: true) 49 + FeedRecommendedAlbumsView = Struct.new(:albums, :cursor, keyword_init: true) 50 + FeedRecommendedAlbumView = Struct.new(:id, :uri, :title, :artist, :artistUri, :year, :albumArt, :recommendationScore, :source, keyword_init: true) 51 + FeedRecommendedArtistsView = Struct.new(:artists, :cursor, keyword_init: true) 52 + FeedRecommendedArtistView = Struct.new(:id, :uri, :name, :picture, :genres, :recommendationScore, :source, keyword_init: true) 53 + FeedSearchResultsView = Struct.new(:hits, :processingTimeMs, :limit, :offset, :estimatedTotalHits, keyword_init: true) 54 + FeedStoriesView = Struct.new(:stories, keyword_init: true) 55 + FeedStoryView = Struct.new(:album, :albumArt, :albumArtist, :albumUri, :artist, :artistUri, :avatar, :createdAt, :did, :handle, :id, :title, :trackId, :trackUri, :uri, keyword_init: true) 56 + FeedUriView = Struct.new(:uri, keyword_init: true) 57 + FeedView = Struct.new(:feed, :cursor, keyword_init: true) 58 + FollowAccountOutput = Struct.new(:subject, :followers, :cursor, keyword_init: true) 59 + FollowAccountParams = Struct.new(:account, keyword_init: true) 60 + FollowRecord = Struct.new(:createdAt, :subject, :via, keyword_init: true) 61 + GeneratorRecord = Struct.new(:did, :avatar, :displayName, :description, :createdAt, keyword_init: true) 62 + GetActorAlbumsOutput = Struct.new(:albums, keyword_init: true) 63 + GetActorAlbumsParams = Struct.new(:did, :limit, :offset, :startDate, :endDate, keyword_init: true) 64 + GetActorArtistsOutput = Struct.new(:artists, keyword_init: true) 65 + GetActorArtistsParams = Struct.new(:did, :limit, :offset, :startDate, :endDate, keyword_init: true) 66 + GetActorCompatibilityOutput = Struct.new(:compatibility, keyword_init: true) 67 + GetActorCompatibilityParams = Struct.new(:did, keyword_init: true) 68 + GetActorLovedSongsOutput = Struct.new(:tracks, keyword_init: true) 69 + GetActorLovedSongsParams = Struct.new(:did, :limit, :offset, keyword_init: true) 70 + GetActorNeighboursOutput = Struct.new(:neighbours, keyword_init: true) 71 + GetActorNeighboursParams = Struct.new(:did, keyword_init: true) 72 + GetActorPlaylistsOutput = Struct.new(:playlists, keyword_init: true) 73 + GetActorPlaylistsParams = Struct.new(:did, :limit, :offset, keyword_init: true) 74 + GetActorScrobblesOutput = Struct.new(:scrobbles, keyword_init: true) 75 + GetActorScrobblesParams = Struct.new(:did, :limit, :offset, keyword_init: true) 76 + GetActorSongsOutput = Struct.new(:songs, keyword_init: true) 77 + GetActorSongsParams = Struct.new(:did, :limit, :offset, :startDate, :endDate, keyword_init: true) 78 + GetAlbumParams = Struct.new(:uri, keyword_init: true) 79 + GetAlbumRecommendationsParams = Struct.new(:did, :limit, keyword_init: true) 80 + GetAlbumShoutsOutput = Struct.new(:shouts, keyword_init: true) 81 + GetAlbumShoutsParams = Struct.new(:uri, :limit, :offset, keyword_init: true) 82 + GetAlbumsOutput = Struct.new(:albums, keyword_init: true) 83 + GetAlbumsParams = Struct.new(:limit, :offset, :genre, keyword_init: true) 84 + GetAlbumTracksOutput = Struct.new(:tracks, keyword_init: true) 85 + GetAlbumTracksParams = Struct.new(:uri, keyword_init: true) 86 + GetApikeysOutput = Struct.new(:apiKeys, keyword_init: true) 87 + GetApikeysParams = Struct.new(:offset, :limit, keyword_init: true) 88 + GetArtistAlbumsOutput = Struct.new(:albums, keyword_init: true) 89 + GetArtistAlbumsParams = Struct.new(:uri, keyword_init: true) 90 + GetArtistListenersOutput = Struct.new(:listeners, keyword_init: true) 91 + GetArtistListenersParams = Struct.new(:uri, :offset, :limit, keyword_init: true) 92 + GetArtistParams = Struct.new(:uri, keyword_init: true) 93 + GetArtistRecentListenersOutput = Struct.new(:listeners, keyword_init: true) 94 + GetArtistRecentListenersParams = Struct.new(:uri, :offset, :limit, keyword_init: true) 95 + GetArtistRecommendationsParams = Struct.new(:did, :limit, keyword_init: true) 96 + GetArtistShoutsOutput = Struct.new(:shouts, keyword_init: true) 97 + GetArtistShoutsParams = Struct.new(:uri, :limit, :offset, keyword_init: true) 98 + GetArtistsOutput = Struct.new(:artists, keyword_init: true) 99 + GetArtistsParams = Struct.new(:limit, :offset, :names, :genre, keyword_init: true) 100 + GetArtistTracksOutput = Struct.new(:tracks, keyword_init: true) 101 + GetArtistTracksParams = Struct.new(:uri, :limit, :offset, keyword_init: true) 102 + GetCurrentlyPlayingParams = Struct.new(:playerId, :actor, keyword_init: true) 103 + GetFeedGeneratorOutput = Struct.new(:view, keyword_init: true) 104 + GetFeedGeneratorParams = Struct.new(:feed, keyword_init: true) 105 + GetFeedGeneratorsParams = Struct.new(:size, keyword_init: true) 106 + GetFeedParams = Struct.new(:feed, :limit, :cursor, keyword_init: true) 107 + GetFeedSkeletonOutput = Struct.new(:scrobbles, :cursor, keyword_init: true) 108 + GetFeedSkeletonParams = Struct.new(:feed, :limit, :offset, :cursor, keyword_init: true) 109 + GetFileParams = Struct.new(:fileId, keyword_init: true) 110 + GetFilesParams = Struct.new(:at, keyword_init: true) 111 + GetFollowersOutput = Struct.new(:subject, :followers, :cursor, :count, keyword_init: true) 112 + GetFollowersParams = Struct.new(:actor, :limit, :dids, :cursor, keyword_init: true) 113 + GetFollowsOutput = Struct.new(:subject, :follows, :cursor, :count, keyword_init: true) 114 + GetFollowsParams = Struct.new(:actor, :limit, :dids, :cursor, keyword_init: true) 115 + GetKnownFollowersOutput = Struct.new(:subject, :followers, :cursor, keyword_init: true) 116 + GetKnownFollowersParams = Struct.new(:actor, :limit, :cursor, keyword_init: true) 117 + GetMetadataParams = Struct.new(:path, keyword_init: true) 118 + GetMirrorSourcesOutput = Struct.new(:sources, keyword_init: true) 119 + GetMirrorSourcesParams = Struct.new(keyword_init: true) 120 + GetPlaybackQueueParams = Struct.new(:playerId, keyword_init: true) 121 + GetPlaylistParams = Struct.new(:uri, keyword_init: true) 122 + GetPlaylistsOutput = Struct.new(:playlists, keyword_init: true) 123 + GetPlaylistsParams = Struct.new(:limit, :offset, keyword_init: true) 124 + GetProfileParams = Struct.new(:did, keyword_init: true) 125 + GetProfileShoutsOutput = Struct.new(:shouts, keyword_init: true) 126 + GetProfileShoutsParams = Struct.new(:did, :offset, :limit, keyword_init: true) 127 + GetRecommendationsParams = Struct.new(:did, :limit, keyword_init: true) 128 + GetScrobbleParams = Struct.new(:uri, keyword_init: true) 129 + GetScrobblesChartParams = Struct.new(:did, :artisturi, :albumuri, :songuri, :genre, :from, :to, keyword_init: true) 130 + GetScrobblesOutput = Struct.new(:scrobbles, keyword_init: true) 131 + GetScrobblesParams = Struct.new(:did, :following, :limit, :offset, keyword_init: true) 132 + GetShoutRepliesOutput = Struct.new(:shouts, keyword_init: true) 133 + GetShoutRepliesParams = Struct.new(:uri, :limit, :offset, keyword_init: true) 134 + GetSongParams = Struct.new(:uri, :mbid, :isrc, :spotifyId, keyword_init: true) 135 + GetSongRecentListenersOutput = Struct.new(:listeners, keyword_init: true) 136 + GetSongRecentListenersParams = Struct.new(:uri, :offset, :limit, keyword_init: true) 137 + GetSongsOutput = Struct.new(:songs, keyword_init: true) 138 + GetSongsParams = Struct.new(:limit, :offset, :genre, :mbid, :isrc, :spotifyId, keyword_init: true) 139 + GetStatsParams = Struct.new(:did, keyword_init: true) 140 + GetStoriesParams = Struct.new(:size, keyword_init: true) 141 + GetTemporaryLinkParams = Struct.new(:path, keyword_init: true) 142 + GetTopArtistsOutput = Struct.new(:artists, keyword_init: true) 143 + GetTopArtistsParams = Struct.new(:limit, :offset, :startDate, :endDate, keyword_init: true) 144 + GetTopTracksOutput = Struct.new(:tracks, keyword_init: true) 145 + GetTopTracksParams = Struct.new(:limit, :offset, :startDate, :endDate, keyword_init: true) 146 + GetTrackShoutsOutput = Struct.new(:shouts, keyword_init: true) 147 + GetTrackShoutsParams = Struct.new(:uri, keyword_init: true) 148 + GetWrappedParams = Struct.new(:did, :year, keyword_init: true) 149 + GoogledriveFileListView = Struct.new(:files, keyword_init: true) 150 + GoogledriveFileView = Struct.new(:id, keyword_init: true) 151 + # indicates that a handle or DID could not be resolved 152 + GraphNotFoundActor = Struct.new(:actor, :notFound, keyword_init: true) 153 + GraphRelationship = Struct.new(:did, :following, :followedBy, keyword_init: true) 154 + InsertDirectoryParams = Struct.new(:uri, :directory, :position, keyword_init: true) 155 + InsertFilesParams = Struct.new(:uri, :files, :position, keyword_init: true) 156 + LikeRecord = Struct.new(:createdAt, :subject, keyword_init: true) 157 + LikeShoutInput = Struct.new(:uri, keyword_init: true) 158 + LikeSongInput = Struct.new(:uri, keyword_init: true) 159 + MatchSongParams = Struct.new(:title, :artist, :mbId, :isrc, keyword_init: true) 160 + MirrorSourceView = Struct.new(:provider, :enabled, :externalUsername, :hasCredentials, :lastPolledAt, :lastScrobbleSeenAt, keyword_init: true) 161 + NextParams = Struct.new(:playerId, keyword_init: true) 162 + PauseParams = Struct.new(:playerId, keyword_init: true) 163 + PlayDirectoryParams = Struct.new(:playerId, :directoryId, :shuffle, :recurse, :position, keyword_init: true) 164 + PlayerCurrentlyPlayingViewDetailed = Struct.new(:title, keyword_init: true) 165 + PlayerPlaybackQueueViewDetailed = Struct.new(:tracks, keyword_init: true) 166 + PlayFileParams = Struct.new(:playerId, :fileId, keyword_init: true) 167 + PlaylistItemRecord = Struct.new(:subject, :createdAt, :track, :order, keyword_init: true) 168 + PlaylistRecord = Struct.new(:name, :description, :picture, :pictureUrl, :createdAt, :spotifyLink, :tidalLink, :youtubeLink, :appleMusicLink, keyword_init: true) 169 + # Basic view of a playlist, including its metadata 170 + PlaylistViewBasic = Struct.new(:id, :title, :uri, :curatorDid, :curatorHandle, :curatorName, :curatorAvatarUrl, :description, :coverImageUrl, :createdAt, :trackCount, keyword_init: true) 171 + # Detailed view of a playlist, including its tracks and metadata 172 + PlaylistViewDetailed = Struct.new(:id, :title, :uri, :curatorDid, :curatorHandle, :curatorName, :curatorAvatarUrl, :description, :coverImageUrl, :createdAt, :tracks, keyword_init: true) 173 + PlayParams = Struct.new(:playerId, keyword_init: true) 174 + PreviousParams = Struct.new(:playerId, keyword_init: true) 175 + ProfileRecord = Struct.new(:displayName, :description, :avatar, :banner, :labels, :joinedViaStarterPack, :createdAt, keyword_init: true) 176 + PutMirrorSourceInput = Struct.new(:provider, :enabled, :externalUsername, :apiKey, keyword_init: true) 177 + RadioRecord = Struct.new(:name, :url, :description, :genre, :logo, :website, :createdAt, keyword_init: true) 178 + RadioViewBasic = Struct.new(:id, :name, :description, :createdAt, keyword_init: true) 179 + RadioViewDetailed = Struct.new(:id, :name, :description, :website, :url, :genre, :logo, :createdAt, keyword_init: true) 180 + RemoveApikeyParams = Struct.new(:id, keyword_init: true) 181 + RemovePlaylistParams = Struct.new(:uri, keyword_init: true) 182 + RemoveShoutParams = Struct.new(:id, keyword_init: true) 183 + RemoveTrackParams = Struct.new(:uri, :position, keyword_init: true) 184 + ReplyShoutInput = Struct.new(:shoutId, :message, keyword_init: true) 185 + ReportShoutInput = Struct.new(:shoutId, :reason, keyword_init: true) 186 + ScrobbleFirstScrobbleView = Struct.new(:handle, :avatar, :timestamp, keyword_init: true) 187 + ScrobbleRecord = Struct.new(:title, :artist, :artists, :albumArtist, :album, :duration, :trackNumber, :discNumber, :releaseDate, :year, :genre, :tags, :composer, :lyrics, :copyrightMessage, :wiki, :albumArt, :albumArtUrl, :youtubeLink, :spotifyLink, :tidalLink, :appleMusicLink, :createdAt, :mbid, :label, :isrc, keyword_init: true) 188 + ScrobbleViewBasic = Struct.new(:id, :user, :userDisplayName, :userAvatar, :title, :artist, :artistUri, :album, :albumUri, :cover, :date, :uri, :sha256, :liked, :likesCount, keyword_init: true) 189 + ScrobbleViewDetailed = Struct.new(:id, :user, :title, :artist, :artistUri, :album, :albumUri, :cover, :date, :uri, :sha256, :liked, :likesCount, :listeners, :scrobbles, :artists, :firstScrobble, keyword_init: true) 190 + SearchParams = Struct.new(:query, keyword_init: true) 191 + SeekParams = Struct.new(:playerId, :position, keyword_init: true) 192 + ShoutAuthor = Struct.new(:id, :did, :handle, :displayName, :avatar, keyword_init: true) 193 + ShoutRecord = Struct.new(:message, :createdAt, :parent, :subject, keyword_init: true) 194 + ShoutView = Struct.new(:id, :message, :parent, :createdAt, :author, keyword_init: true) 195 + SongFirstScrobbleView = Struct.new(:handle, :avatar, :timestamp, keyword_init: true) 196 + SongRecentListenerView = Struct.new(:id, :did, :handle, :displayName, :avatar, :timestamp, :scrobbleUri, keyword_init: true) 197 + SongRecord = Struct.new(:title, :artist, :artists, :albumArtist, :album, :duration, :trackNumber, :discNumber, :releaseDate, :year, :genre, :tags, :composer, :lyrics, :copyrightMessage, :wiki, :albumArt, :albumArtUrl, :youtubeLink, :spotifyLink, :tidalLink, :appleMusicLink, :createdAt, :mbid, :label, :isrc, keyword_init: true) 198 + SongViewBasic = Struct.new(:id, :title, :artist, :albumArtist, :albumArt, :uri, :album, :duration, :trackNumber, :discNumber, :playCount, :uniqueListeners, :albumUri, :artistUri, :sha256, :mbid, :isrc, :tags, :createdAt, keyword_init: true) 199 + SongViewDetailed = Struct.new(:id, :title, :artist, :albumArtist, :albumArt, :uri, :album, :duration, :trackNumber, :discNumber, :playCount, :uniqueListeners, :albumUri, :artistUri, :sha256, :mbid, :isrc, :tags, :createdAt, :artists, :firstScrobble, keyword_init: true) 200 + SpotifyTrackView = Struct.new(:id, :name, :artist, :album, :duration, :previewUrl, keyword_init: true) 201 + StartPlaylistParams = Struct.new(:uri, :shuffle, :position, keyword_init: true) 202 + StatsView = Struct.new(:scrobbles, :artists, :lovedTracks, :albums, :tracks, keyword_init: true) 203 + StatsWrappedAlbum = Struct.new(:id, :title, :artist, :albumArt, :uri, :playCount, keyword_init: true) 204 + StatsWrappedArtist = Struct.new(:id, :name, :picture, :uri, :playCount, keyword_init: true) 205 + StatsWrappedDayCount = Struct.new(:date, :count, keyword_init: true) 206 + StatsWrappedGenreCount = Struct.new(:genre, :count, keyword_init: true) 207 + StatsWrappedMilestone = Struct.new(:trackTitle, :artistName, :timestamp, :trackUri, keyword_init: true) 208 + StatsWrappedMonthCount = Struct.new(:month, :count, keyword_init: true) 209 + StatsWrappedTrack = Struct.new(:id, :title, :artist, :albumArt, :uri, :artistUri, :albumUri, :playCount, keyword_init: true) 210 + StatsWrappedView = Struct.new(:year, :totalScrobbles, :totalListeningTimeMinutes, :topArtists, :topTracks, :topAlbums, :topGenres, :scrobblesPerMonth, :mostActiveDay, :mostActiveHour, :newArtistsCount, :longestStreak, :firstScrobble, :lastScrobble, keyword_init: true) 211 + StatusRecord = Struct.new(:track, :startedAt, :expiresAt, keyword_init: true) 212 + StrongRef = Struct.new(:uri, :cid, keyword_init: true) 213 + UnfollowAccountOutput = Struct.new(:subject, :followers, :cursor, keyword_init: true) 214 + UnfollowAccountParams = Struct.new(:account, keyword_init: true) 215 + UpdateApikeyInput = Struct.new(:id, :name, :description, keyword_init: true) 216 + end 217 + end
+1 -1
sdk/ruby/lib/rocksky/version.rb
··· 1 1 module Rocksky 2 - VERSION = "0.1.0".freeze 2 + VERSION = "0.2.0".freeze 3 3 end
+1 -1
sdk/rust/Cargo.toml
··· 2 2 3 3 [package] 4 4 name = "rocksky" 5 - version = "0.1.0" 5 + version = "0.2.0" 6 6 edition = "2021" 7 7 rust-version = "1.75" 8 8 authors = ["Tsiry Sandratraina <tsiry.sndr@rocksky.app>"]
+5
sdk/rust/README.md
··· 191 191 cargo run --example quickstart -- tsiry-sandratraina.com 192 192 ``` 193 193 194 + ## Types 195 + 196 + Public model types are derived from the [Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons) and live in `rocksky::generated`. The hand-written `rocksky::models` module re-exports them under their historical SDK names and extends `Profile` / `ApiKey` with fields the lexicon does not yet model. Regenerate with `bun run lexgen:types` at the repo root. 197 + 198 + 194 199 ## Testing your own code against the SDK 195 200 196 201 Provide your own `reqwest::Client` and point the SDK at a mock server.
+2912
sdk/rust/src/generated.rs
··· 1 + // Code generated by tools/lexgen — DO NOT EDIT. 2 + // Source: apps/api/lexicons/**/*.json 3 + // Regenerate via: bun run lexgen:types 4 + 5 + #![allow(non_snake_case, non_camel_case_types, dead_code, clippy::large_enum_variant)] 6 + 7 + use chrono::{DateTime, Utc}; 8 + use serde::{Deserialize, Serialize}; 9 + use serde_json::Value; 10 + 11 + /// atproto blob reference shape. 12 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 13 + pub struct BlobRef { 14 + #[serde(rename = "$type", default, skip_serializing_if = "Option::is_none")] 15 + pub r#type: Option<String>, 16 + #[serde(default, skip_serializing_if = "Option::is_none")] 17 + pub ref_: Option<BlobCidRef>, 18 + #[serde(default, skip_serializing_if = "Option::is_none")] 19 + pub mime_type: Option<String>, 20 + #[serde(default, skip_serializing_if = "Option::is_none")] 21 + pub size: Option<i64>, 22 + } 23 + 24 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 25 + pub struct BlobCidRef { 26 + #[serde(rename = "$link", default, skip_serializing_if = "Option::is_none")] 27 + pub link: Option<String>, 28 + } 29 + 30 + 31 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 32 + pub struct ActorArtistViewBasic { 33 + #[serde(default, skip_serializing_if = "Option::is_none")] 34 + pub id: Option<String>, 35 + #[serde(default, skip_serializing_if = "Option::is_none")] 36 + pub name: Option<String>, 37 + #[serde(default, skip_serializing_if = "Option::is_none")] 38 + pub picture: Option<String>, 39 + #[serde(default, skip_serializing_if = "Option::is_none")] 40 + pub uri: Option<String>, 41 + #[serde(rename = "user1Rank", default, skip_serializing_if = "Option::is_none")] 42 + pub user1_rank: Option<i64>, 43 + #[serde(rename = "user2Rank", default, skip_serializing_if = "Option::is_none")] 44 + pub user2_rank: Option<i64>, 45 + #[serde(default, skip_serializing_if = "Option::is_none")] 46 + pub weight: Option<i64>, 47 + } 48 + 49 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 50 + pub struct ActorCompatibilityViewBasic { 51 + #[serde(rename = "compatibilityLevel", default, skip_serializing_if = "Option::is_none")] 52 + pub compatibility_level: Option<i64>, 53 + #[serde(rename = "compatibilityPercentage", default, skip_serializing_if = "Option::is_none")] 54 + pub compatibility_percentage: Option<i64>, 55 + #[serde(rename = "sharedArtists", default, skip_serializing_if = "Option::is_none")] 56 + pub shared_artists: Option<i64>, 57 + #[serde(rename = "topSharedArtistNames", default, skip_serializing_if = "Vec::is_empty")] 58 + pub top_shared_artist_names: Vec<String>, 59 + #[serde(rename = "topSharedDetailedArtists", default, skip_serializing_if = "Vec::is_empty")] 60 + pub top_shared_detailed_artists: Vec<ActorArtistViewBasic>, 61 + #[serde(rename = "user1ArtistCount", default, skip_serializing_if = "Option::is_none")] 62 + pub user1_artist_count: Option<i64>, 63 + #[serde(rename = "user2ArtistCount", default, skip_serializing_if = "Option::is_none")] 64 + pub user2_artist_count: Option<i64>, 65 + } 66 + 67 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 68 + pub struct ActorNeighbourViewBasic { 69 + #[serde(rename = "userId", default, skip_serializing_if = "Option::is_none")] 70 + pub user_id: Option<String>, 71 + #[serde(default, skip_serializing_if = "Option::is_none")] 72 + pub did: Option<String>, 73 + #[serde(default, skip_serializing_if = "Option::is_none")] 74 + pub handle: Option<String>, 75 + #[serde(rename = "displayName", default, skip_serializing_if = "Option::is_none")] 76 + pub display_name: Option<String>, 77 + /// The URL of the actor's avatar image. 78 + #[serde(default, skip_serializing_if = "Option::is_none")] 79 + pub avatar: Option<String>, 80 + /// The number of artists shared with the actor. 81 + #[serde(rename = "sharedArtistsCount", default, skip_serializing_if = "Option::is_none")] 82 + pub shared_artists_count: Option<i64>, 83 + /// The similarity score with the actor. 84 + #[serde(rename = "similarityScore", default, skip_serializing_if = "Option::is_none")] 85 + pub similarity_score: Option<i64>, 86 + /// The top shared artist names with the actor. 87 + #[serde(rename = "topSharedArtistNames", default, skip_serializing_if = "Vec::is_empty")] 88 + pub top_shared_artist_names: Vec<String>, 89 + /// The top shared artist details with the actor. 90 + #[serde(rename = "topSharedArtistsDetails", default, skip_serializing_if = "Vec::is_empty")] 91 + pub top_shared_artists_details: Vec<ArtistViewBasic>, 92 + } 93 + 94 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 95 + pub struct ActorProfileViewBasic { 96 + /// The unique identifier of the actor. 97 + #[serde(default, skip_serializing_if = "Option::is_none")] 98 + pub id: Option<String>, 99 + /// The DID of the actor. 100 + #[serde(default, skip_serializing_if = "Option::is_none")] 101 + pub did: Option<String>, 102 + /// The handle of the actor. 103 + #[serde(default, skip_serializing_if = "Option::is_none")] 104 + pub handle: Option<String>, 105 + /// The display name of the actor. 106 + #[serde(rename = "displayName", default, skip_serializing_if = "Option::is_none")] 107 + pub display_name: Option<String>, 108 + /// The URL of the actor's avatar image. 109 + #[serde(default, skip_serializing_if = "Option::is_none")] 110 + pub avatar: Option<String>, 111 + /// The date and time when the actor was created. 112 + #[serde(rename = "createdAt", default, skip_serializing_if = "Option::is_none")] 113 + pub created_at: Option<DateTime<Utc>>, 114 + /// The date and time when the actor was last updated. 115 + #[serde(rename = "updatedAt", default, skip_serializing_if = "Option::is_none")] 116 + pub updated_at: Option<DateTime<Utc>>, 117 + } 118 + 119 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 120 + pub struct ActorProfileViewDetailed { 121 + /// The unique identifier of the actor. 122 + #[serde(default, skip_serializing_if = "Option::is_none")] 123 + pub id: Option<String>, 124 + /// The DID of the actor. 125 + #[serde(default, skip_serializing_if = "Option::is_none")] 126 + pub did: Option<String>, 127 + /// The handle of the actor. 128 + #[serde(default, skip_serializing_if = "Option::is_none")] 129 + pub handle: Option<String>, 130 + /// The display name of the actor. 131 + #[serde(rename = "displayName", default, skip_serializing_if = "Option::is_none")] 132 + pub display_name: Option<String>, 133 + /// The URL of the actor's avatar image. 134 + #[serde(default, skip_serializing_if = "Option::is_none")] 135 + pub avatar: Option<String>, 136 + /// The date and time when the actor was created. 137 + #[serde(rename = "createdAt", default, skip_serializing_if = "Option::is_none")] 138 + pub created_at: Option<DateTime<Utc>>, 139 + /// The date and time when the actor was last updated. 140 + #[serde(rename = "updatedAt", default, skip_serializing_if = "Option::is_none")] 141 + pub updated_at: Option<DateTime<Utc>>, 142 + } 143 + 144 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 145 + pub struct ActorTrackView { 146 + /// The name of the track. 147 + pub name: String, 148 + /// The primary artist name. 149 + pub artist: String, 150 + /// The album name. 151 + #[serde(default, skip_serializing_if = "Option::is_none")] 152 + pub album: Option<String>, 153 + /// URL of the album cover image. 154 + #[serde(rename = "albumCoverUrl", default, skip_serializing_if = "Option::is_none")] 155 + pub album_cover_url: Option<String>, 156 + /// Track duration in milliseconds. 157 + #[serde(rename = "durationMs", default, skip_serializing_if = "Option::is_none")] 158 + pub duration_ms: Option<i64>, 159 + /// Music service source, e.g. 'spotify' or 'listenbrainz'. 160 + #[serde(default, skip_serializing_if = "Option::is_none")] 161 + pub source: Option<String>, 162 + /// MusicBrainz recording ID, if available. 163 + #[serde(rename = "recordingMbId", default, skip_serializing_if = "Option::is_none")] 164 + pub recording_mb_id: Option<String>, 165 + } 166 + 167 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 168 + pub struct AddDirectoryToQueueParams { 169 + #[serde(rename = "playerId", default, skip_serializing_if = "Option::is_none")] 170 + pub player_id: Option<String>, 171 + /// The directory to add to the queue 172 + pub directory: String, 173 + /// Position in the queue to insert the directory at, defaults to the end if not specified 174 + #[serde(default, skip_serializing_if = "Option::is_none")] 175 + pub position: Option<i64>, 176 + /// Whether to shuffle the added directory in the queue 177 + #[serde(default, skip_serializing_if = "Option::is_none")] 178 + pub shuffle: Option<bool>, 179 + } 180 + 181 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 182 + pub struct AddItemsToQueueParams { 183 + #[serde(rename = "playerId", default, skip_serializing_if = "Option::is_none")] 184 + pub player_id: Option<String>, 185 + pub items: Vec<String>, 186 + /// Position in the queue to insert the items at, defaults to the end if not specified 187 + #[serde(default, skip_serializing_if = "Option::is_none")] 188 + pub position: Option<i64>, 189 + /// Whether to shuffle the added items in the queue 190 + #[serde(default, skip_serializing_if = "Option::is_none")] 191 + pub shuffle: Option<bool>, 192 + } 193 + 194 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 195 + pub struct AlbumRecord { 196 + /// The title of the album. 197 + pub title: String, 198 + /// The artist of the album. 199 + pub artist: String, 200 + /// The duration of the album in seconds. 201 + #[serde(default, skip_serializing_if = "Option::is_none")] 202 + pub duration: Option<i64>, 203 + /// The release date of the album. 204 + #[serde(rename = "releaseDate", default, skip_serializing_if = "Option::is_none")] 205 + pub release_date: Option<DateTime<Utc>>, 206 + /// The year the album was released. 207 + #[serde(default, skip_serializing_if = "Option::is_none")] 208 + pub year: Option<i64>, 209 + /// The genre of the album. 210 + #[serde(default, skip_serializing_if = "Option::is_none")] 211 + pub genre: Option<String>, 212 + /// The album art of the album. 213 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 214 + pub album_art: Option<BlobRef>, 215 + /// The URL of the album art of the album. 216 + #[serde(rename = "albumArtUrl", default, skip_serializing_if = "Option::is_none")] 217 + pub album_art_url: Option<String>, 218 + /// The tags of the album. 219 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 220 + pub tags: Vec<String>, 221 + /// The YouTube link of the album. 222 + #[serde(rename = "youtubeLink", default, skip_serializing_if = "Option::is_none")] 223 + pub youtube_link: Option<String>, 224 + /// The Spotify link of the album. 225 + #[serde(rename = "spotifyLink", default, skip_serializing_if = "Option::is_none")] 226 + pub spotify_link: Option<String>, 227 + /// The tidal link of the album. 228 + #[serde(rename = "tidalLink", default, skip_serializing_if = "Option::is_none")] 229 + pub tidal_link: Option<String>, 230 + /// The Apple Music link of the album. 231 + #[serde(rename = "appleMusicLink", default, skip_serializing_if = "Option::is_none")] 232 + pub apple_music_link: Option<String>, 233 + /// The date and time when the album was created. 234 + #[serde(rename = "createdAt")] 235 + pub created_at: DateTime<Utc>, 236 + } 237 + 238 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 239 + pub struct AlbumViewBasic { 240 + /// The unique identifier of the album. 241 + #[serde(default, skip_serializing_if = "Option::is_none")] 242 + pub id: Option<String>, 243 + /// The URI of the album. 244 + #[serde(default, skip_serializing_if = "Option::is_none")] 245 + pub uri: Option<String>, 246 + /// The title of the album. 247 + #[serde(default, skip_serializing_if = "Option::is_none")] 248 + pub title: Option<String>, 249 + /// The artist of the album. 250 + #[serde(default, skip_serializing_if = "Option::is_none")] 251 + pub artist: Option<String>, 252 + /// The URI of the album's artist. 253 + #[serde(rename = "artistUri", default, skip_serializing_if = "Option::is_none")] 254 + pub artist_uri: Option<String>, 255 + /// The year the album was released. 256 + #[serde(default, skip_serializing_if = "Option::is_none")] 257 + pub year: Option<i64>, 258 + /// The URL of the album art image. 259 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 260 + pub album_art: Option<String>, 261 + /// The release date of the album. 262 + #[serde(rename = "releaseDate", default, skip_serializing_if = "Option::is_none")] 263 + pub release_date: Option<String>, 264 + /// The SHA256 hash of the album. 265 + #[serde(default, skip_serializing_if = "Option::is_none")] 266 + pub sha256: Option<String>, 267 + /// The number of times the album has been played. 268 + #[serde(rename = "playCount", default, skip_serializing_if = "Option::is_none")] 269 + pub play_count: Option<i64>, 270 + /// The number of unique listeners who have played the album. 271 + #[serde(rename = "uniqueListeners", default, skip_serializing_if = "Option::is_none")] 272 + pub unique_listeners: Option<i64>, 273 + } 274 + 275 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 276 + pub struct AlbumViewDetailed { 277 + /// The unique identifier of the album. 278 + #[serde(default, skip_serializing_if = "Option::is_none")] 279 + pub id: Option<String>, 280 + /// The URI of the album. 281 + #[serde(default, skip_serializing_if = "Option::is_none")] 282 + pub uri: Option<String>, 283 + /// The title of the album. 284 + #[serde(default, skip_serializing_if = "Option::is_none")] 285 + pub title: Option<String>, 286 + /// The artist of the album. 287 + #[serde(default, skip_serializing_if = "Option::is_none")] 288 + pub artist: Option<String>, 289 + /// The URI of the album's artist. 290 + #[serde(rename = "artistUri", default, skip_serializing_if = "Option::is_none")] 291 + pub artist_uri: Option<String>, 292 + /// The year the album was released. 293 + #[serde(default, skip_serializing_if = "Option::is_none")] 294 + pub year: Option<i64>, 295 + /// The URL of the album art image. 296 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 297 + pub album_art: Option<String>, 298 + /// The release date of the album. 299 + #[serde(rename = "releaseDate", default, skip_serializing_if = "Option::is_none")] 300 + pub release_date: Option<String>, 301 + /// The SHA256 hash of the album. 302 + #[serde(default, skip_serializing_if = "Option::is_none")] 303 + pub sha256: Option<String>, 304 + /// The number of times the album has been played. 305 + #[serde(rename = "playCount", default, skip_serializing_if = "Option::is_none")] 306 + pub play_count: Option<i64>, 307 + /// The number of unique listeners who have played the album. 308 + #[serde(rename = "uniqueListeners", default, skip_serializing_if = "Option::is_none")] 309 + pub unique_listeners: Option<i64>, 310 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 311 + pub tags: Vec<String>, 312 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 313 + pub tracks: Vec<SongViewBasic>, 314 + } 315 + 316 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 317 + pub struct ApiKeyView { 318 + /// The unique identifier of the API key. 319 + #[serde(default, skip_serializing_if = "Option::is_none")] 320 + pub id: Option<String>, 321 + /// The name of the API key. 322 + #[serde(default, skip_serializing_if = "Option::is_none")] 323 + pub name: Option<String>, 324 + /// A description for the API key. 325 + #[serde(default, skip_serializing_if = "Option::is_none")] 326 + pub description: Option<String>, 327 + /// The date and time when the API key was created. 328 + #[serde(rename = "createdAt", default, skip_serializing_if = "Option::is_none")] 329 + pub created_at: Option<DateTime<Utc>>, 330 + } 331 + 332 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 333 + pub struct ArtistListenerViewBasic { 334 + /// The unique identifier of the actor. 335 + #[serde(default, skip_serializing_if = "Option::is_none")] 336 + pub id: Option<String>, 337 + /// The DID of the listener. 338 + #[serde(default, skip_serializing_if = "Option::is_none")] 339 + pub did: Option<String>, 340 + /// The handle of the listener. 341 + #[serde(default, skip_serializing_if = "Option::is_none")] 342 + pub handle: Option<String>, 343 + /// The display name of the listener. 344 + #[serde(rename = "displayName", default, skip_serializing_if = "Option::is_none")] 345 + pub display_name: Option<String>, 346 + /// The URL of the listener's avatar image. 347 + #[serde(default, skip_serializing_if = "Option::is_none")] 348 + pub avatar: Option<String>, 349 + #[serde(rename = "mostListenedSong", default, skip_serializing_if = "Option::is_none")] 350 + pub most_listened_song: Option<ArtistSongViewBasic>, 351 + /// The total number of plays by the listener. 352 + #[serde(rename = "totalPlays", default, skip_serializing_if = "Option::is_none")] 353 + pub total_plays: Option<i64>, 354 + /// The rank of the listener among all listeners of the artist. 355 + #[serde(default, skip_serializing_if = "Option::is_none")] 356 + pub rank: Option<i64>, 357 + } 358 + 359 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 360 + pub struct ArtistMbid { 361 + /// The MusicBrainz Identifier (MBID) of the artist. 362 + #[serde(default, skip_serializing_if = "Option::is_none")] 363 + pub mbid: Option<String>, 364 + /// The name of the artist. 365 + #[serde(default, skip_serializing_if = "Option::is_none")] 366 + pub name: Option<String>, 367 + } 368 + 369 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 370 + pub struct ArtistRecentListenerView { 371 + /// The unique identifier of the listener. 372 + #[serde(default, skip_serializing_if = "Option::is_none")] 373 + pub id: Option<String>, 374 + /// The DID of the listener. 375 + #[serde(default, skip_serializing_if = "Option::is_none")] 376 + pub did: Option<String>, 377 + /// The handle of the listener. 378 + #[serde(default, skip_serializing_if = "Option::is_none")] 379 + pub handle: Option<String>, 380 + /// The display name of the listener. 381 + #[serde(rename = "displayName", default, skip_serializing_if = "Option::is_none")] 382 + pub display_name: Option<String>, 383 + /// The URL of the listener's avatar image. 384 + #[serde(default, skip_serializing_if = "Option::is_none")] 385 + pub avatar: Option<String>, 386 + /// The timestamp of the listener's most recent scrobble of this artist. 387 + #[serde(default, skip_serializing_if = "Option::is_none")] 388 + pub timestamp: Option<DateTime<Utc>>, 389 + /// The URI of the listener's most recent scrobble of this artist. 390 + #[serde(rename = "scrobbleUri", default, skip_serializing_if = "Option::is_none")] 391 + pub scrobble_uri: Option<String>, 392 + } 393 + 394 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 395 + pub struct ArtistRecord { 396 + /// The name of the artist. 397 + pub name: String, 398 + /// The biography of the artist. 399 + #[serde(default, skip_serializing_if = "Option::is_none")] 400 + pub bio: Option<String>, 401 + /// The picture of the artist. 402 + #[serde(default, skip_serializing_if = "Option::is_none")] 403 + pub picture: Option<BlobRef>, 404 + /// The URL of the picture of the artist. 405 + #[serde(rename = "pictureUrl", default, skip_serializing_if = "Option::is_none")] 406 + pub picture_url: Option<String>, 407 + /// The tags of the artist. 408 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 409 + pub tags: Vec<String>, 410 + /// The birth date of the artist. 411 + #[serde(default, skip_serializing_if = "Option::is_none")] 412 + pub born: Option<DateTime<Utc>>, 413 + /// The death date of the artist. 414 + #[serde(default, skip_serializing_if = "Option::is_none")] 415 + pub died: Option<DateTime<Utc>>, 416 + /// The birth place of the artist. 417 + #[serde(rename = "bornIn", default, skip_serializing_if = "Option::is_none")] 418 + pub born_in: Option<String>, 419 + /// The date when the artist was created. 420 + #[serde(rename = "createdAt")] 421 + pub created_at: DateTime<Utc>, 422 + } 423 + 424 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 425 + pub struct ArtistSongViewBasic { 426 + /// The URI of the song. 427 + #[serde(default, skip_serializing_if = "Option::is_none")] 428 + pub uri: Option<String>, 429 + /// The title of the song. 430 + #[serde(default, skip_serializing_if = "Option::is_none")] 431 + pub title: Option<String>, 432 + /// The number of times the song has been played. 433 + #[serde(rename = "playCount", default, skip_serializing_if = "Option::is_none")] 434 + pub play_count: Option<i64>, 435 + } 436 + 437 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 438 + pub struct ArtistViewBasic { 439 + /// The unique identifier of the artist. 440 + #[serde(default, skip_serializing_if = "Option::is_none")] 441 + pub id: Option<String>, 442 + /// The URI of the artist. 443 + #[serde(default, skip_serializing_if = "Option::is_none")] 444 + pub uri: Option<String>, 445 + /// The name of the artist. 446 + #[serde(default, skip_serializing_if = "Option::is_none")] 447 + pub name: Option<String>, 448 + /// The picture of the artist. 449 + #[serde(default, skip_serializing_if = "Option::is_none")] 450 + pub picture: Option<String>, 451 + /// The SHA256 hash of the artist. 452 + #[serde(default, skip_serializing_if = "Option::is_none")] 453 + pub sha256: Option<String>, 454 + /// The number of times the artist has been played. 455 + #[serde(rename = "playCount", default, skip_serializing_if = "Option::is_none")] 456 + pub play_count: Option<i64>, 457 + /// The number of unique listeners who have played the artist. 458 + #[serde(rename = "uniqueListeners", default, skip_serializing_if = "Option::is_none")] 459 + pub unique_listeners: Option<i64>, 460 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 461 + pub tags: Vec<String>, 462 + } 463 + 464 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 465 + pub struct ArtistViewDetailed { 466 + /// The unique identifier of the artist. 467 + #[serde(default, skip_serializing_if = "Option::is_none")] 468 + pub id: Option<String>, 469 + /// The URI of the artist. 470 + #[serde(default, skip_serializing_if = "Option::is_none")] 471 + pub uri: Option<String>, 472 + /// The name of the artist. 473 + #[serde(default, skip_serializing_if = "Option::is_none")] 474 + pub name: Option<String>, 475 + /// The picture of the artist. 476 + #[serde(default, skip_serializing_if = "Option::is_none")] 477 + pub picture: Option<String>, 478 + /// The SHA256 hash of the artist. 479 + #[serde(default, skip_serializing_if = "Option::is_none")] 480 + pub sha256: Option<String>, 481 + /// The number of times the artist has been played. 482 + #[serde(rename = "playCount", default, skip_serializing_if = "Option::is_none")] 483 + pub play_count: Option<i64>, 484 + /// The number of unique listeners who have played the artist. 485 + #[serde(rename = "uniqueListeners", default, skip_serializing_if = "Option::is_none")] 486 + pub unique_listeners: Option<i64>, 487 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 488 + pub tags: Vec<String>, 489 + } 490 + 491 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 492 + pub struct ChartsScrobbleViewBasic { 493 + /// The date of the scrobble. 494 + #[serde(default, skip_serializing_if = "Option::is_none")] 495 + pub date: Option<DateTime<Utc>>, 496 + /// The number of scrobbles on this date. 497 + #[serde(default, skip_serializing_if = "Option::is_none")] 498 + pub count: Option<i64>, 499 + } 500 + 501 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 502 + pub struct ChartsView { 503 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 504 + pub scrobbles: Vec<ChartsScrobbleViewBasic>, 505 + } 506 + 507 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 508 + pub struct CreateApikeyInput { 509 + /// The name of the API key. 510 + pub name: String, 511 + /// A description for the API key. 512 + #[serde(default, skip_serializing_if = "Option::is_none")] 513 + pub description: Option<String>, 514 + } 515 + 516 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 517 + pub struct CreatePlaylistParams { 518 + /// The name of the playlist 519 + pub name: String, 520 + /// A brief description of the playlist 521 + #[serde(default, skip_serializing_if = "Option::is_none")] 522 + pub description: Option<String>, 523 + } 524 + 525 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 526 + pub struct CreateScrobbleInput { 527 + /// The title of the track being scrobbled 528 + pub title: String, 529 + /// The artist of the track being scrobbled 530 + pub artist: String, 531 + /// The album of the track being scrobbled 532 + #[serde(default, skip_serializing_if = "Option::is_none")] 533 + pub album: Option<String>, 534 + /// The duration of the track in milliseconds 535 + #[serde(default, skip_serializing_if = "Option::is_none")] 536 + pub duration: Option<i64>, 537 + /// The MusicBrainz ID of the track, if available 538 + #[serde(rename = "mbId", default, skip_serializing_if = "Option::is_none")] 539 + pub mb_id: Option<String>, 540 + /// The International Standard Recording Code (ISRC) of the track, if available 541 + #[serde(default, skip_serializing_if = "Option::is_none")] 542 + pub isrc: Option<String>, 543 + /// The URL of the album art for the track 544 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 545 + pub album_art: Option<String>, 546 + /// The track number of the track in the album 547 + #[serde(rename = "trackNumber", default, skip_serializing_if = "Option::is_none")] 548 + pub track_number: Option<i64>, 549 + /// The release date of the track, formatted as YYYY-MM-DD 550 + #[serde(rename = "releaseDate", default, skip_serializing_if = "Option::is_none")] 551 + pub release_date: Option<String>, 552 + /// The year the track was released 553 + #[serde(default, skip_serializing_if = "Option::is_none")] 554 + pub year: Option<i64>, 555 + /// The disc number of the track in the album, if applicable 556 + #[serde(rename = "discNumber", default, skip_serializing_if = "Option::is_none")] 557 + pub disc_number: Option<i64>, 558 + /// The lyrics of the track, if available 559 + #[serde(default, skip_serializing_if = "Option::is_none")] 560 + pub lyrics: Option<String>, 561 + /// The composer of the track, if available 562 + #[serde(default, skip_serializing_if = "Option::is_none")] 563 + pub composer: Option<String>, 564 + /// The copyright message for the track, if available 565 + #[serde(rename = "copyrightMessage", default, skip_serializing_if = "Option::is_none")] 566 + pub copyright_message: Option<String>, 567 + /// The record label of the track, if available 568 + #[serde(default, skip_serializing_if = "Option::is_none")] 569 + pub label: Option<String>, 570 + /// The URL of the artist's picture, if available 571 + #[serde(rename = "artistPicture", default, skip_serializing_if = "Option::is_none")] 572 + pub artist_picture: Option<String>, 573 + /// The Spotify link for the track, if available 574 + #[serde(rename = "spotifyLink", default, skip_serializing_if = "Option::is_none")] 575 + pub spotify_link: Option<String>, 576 + /// The Last.fm link for the track, if available 577 + #[serde(rename = "lastfmLink", default, skip_serializing_if = "Option::is_none")] 578 + pub lastfm_link: Option<String>, 579 + /// The Tidal link for the track, if available 580 + #[serde(rename = "tidalLink", default, skip_serializing_if = "Option::is_none")] 581 + pub tidal_link: Option<String>, 582 + /// The Apple Music link for the track, if available 583 + #[serde(rename = "appleMusicLink", default, skip_serializing_if = "Option::is_none")] 584 + pub apple_music_link: Option<String>, 585 + /// The Youtube link for the track, if available 586 + #[serde(rename = "youtubeLink", default, skip_serializing_if = "Option::is_none")] 587 + pub youtube_link: Option<String>, 588 + /// The Deezer link for the track, if available 589 + #[serde(rename = "deezerLink", default, skip_serializing_if = "Option::is_none")] 590 + pub deezer_link: Option<String>, 591 + /// The timestamp of the scrobble in seconds since epoch (Unix timestamp) 592 + #[serde(default, skip_serializing_if = "Option::is_none")] 593 + pub timestamp: Option<i64>, 594 + } 595 + 596 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 597 + pub struct CreateShoutInput { 598 + /// The content of the shout 599 + #[serde(default, skip_serializing_if = "Option::is_none")] 600 + pub message: Option<String>, 601 + } 602 + 603 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 604 + pub struct CreateSongInput { 605 + /// The title of the song 606 + pub title: String, 607 + /// The artist of the song 608 + pub artist: String, 609 + /// The album artist of the song, if different from the main artist 610 + #[serde(rename = "albumArtist")] 611 + pub album_artist: String, 612 + /// The album of the song, if applicable 613 + pub album: String, 614 + /// The duration of the song in seconds 615 + #[serde(default, skip_serializing_if = "Option::is_none")] 616 + pub duration: Option<i64>, 617 + /// The MusicBrainz ID of the song, if available 618 + #[serde(rename = "mbId", default, skip_serializing_if = "Option::is_none")] 619 + pub mb_id: Option<String>, 620 + /// The International Standard Recording Code (ISRC) of the song, if available 621 + #[serde(default, skip_serializing_if = "Option::is_none")] 622 + pub isrc: Option<String>, 623 + /// The URL of the album art for the song 624 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 625 + pub album_art: Option<String>, 626 + /// The track number of the song in the album, if applicable 627 + #[serde(rename = "trackNumber", default, skip_serializing_if = "Option::is_none")] 628 + pub track_number: Option<i64>, 629 + /// The release date of the song, formatted as YYYY-MM-DD 630 + #[serde(rename = "releaseDate", default, skip_serializing_if = "Option::is_none")] 631 + pub release_date: Option<String>, 632 + /// The year the song was released 633 + #[serde(default, skip_serializing_if = "Option::is_none")] 634 + pub year: Option<i64>, 635 + /// The disc number of the song in the album, if applicable 636 + #[serde(rename = "discNumber", default, skip_serializing_if = "Option::is_none")] 637 + pub disc_number: Option<i64>, 638 + /// The lyrics of the song, if available 639 + #[serde(default, skip_serializing_if = "Option::is_none")] 640 + pub lyrics: Option<String>, 641 + } 642 + 643 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 644 + pub struct DescribeFeedGeneratorOutput { 645 + /// The DID of the feed generator. 646 + #[serde(default, skip_serializing_if = "Option::is_none")] 647 + pub did: Option<String>, 648 + /// List of feed URIs generated by this feed generator. 649 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 650 + pub feeds: Vec<FeedUriView>, 651 + } 652 + 653 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 654 + pub struct DescribeFeedGeneratorParams { 655 + } 656 + 657 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 658 + pub struct DislikeShoutInput { 659 + /// The unique identifier of the shout to dislike 660 + #[serde(default, skip_serializing_if = "Option::is_none")] 661 + pub uri: Option<String>, 662 + } 663 + 664 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 665 + pub struct DislikeSongInput { 666 + /// The unique identifier of the song to dislike 667 + #[serde(default, skip_serializing_if = "Option::is_none")] 668 + pub uri: Option<String>, 669 + } 670 + 671 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 672 + pub struct DownloadFileParams { 673 + /// The unique identifier of the file to download 674 + #[serde(rename = "fileId")] 675 + pub file_id: String, 676 + } 677 + 678 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 679 + pub struct DropboxFileListView { 680 + /// A list of files in the Dropbox. 681 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 682 + pub files: Vec<DropboxFileView>, 683 + } 684 + 685 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 686 + pub struct DropboxFileView { 687 + /// The unique identifier of the file. 688 + #[serde(default, skip_serializing_if = "Option::is_none")] 689 + pub id: Option<String>, 690 + /// The name of the file. 691 + #[serde(default, skip_serializing_if = "Option::is_none")] 692 + pub name: Option<String>, 693 + /// The lowercased path of the file. 694 + #[serde(rename = "pathLower", default, skip_serializing_if = "Option::is_none")] 695 + pub path_lower: Option<String>, 696 + /// The display path of the file. 697 + #[serde(rename = "pathDisplay", default, skip_serializing_if = "Option::is_none")] 698 + pub path_display: Option<String>, 699 + /// The last modified date and time of the file on the client. 700 + #[serde(rename = "clientModified", default, skip_serializing_if = "Option::is_none")] 701 + pub client_modified: Option<DateTime<Utc>>, 702 + /// The last modified date and time of the file on the server. 703 + #[serde(rename = "serverModified", default, skip_serializing_if = "Option::is_none")] 704 + pub server_modified: Option<DateTime<Utc>>, 705 + } 706 + 707 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 708 + pub struct DropboxTemporaryLinkView { 709 + /// The temporary link to access the file. 710 + #[serde(default, skip_serializing_if = "Option::is_none")] 711 + pub link: Option<String>, 712 + } 713 + 714 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 715 + pub struct FeedGeneratorsView { 716 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 717 + pub feeds: Vec<FeedGeneratorView>, 718 + } 719 + 720 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 721 + pub struct FeedGeneratorView { 722 + #[serde(default, skip_serializing_if = "Option::is_none")] 723 + pub id: Option<String>, 724 + #[serde(default, skip_serializing_if = "Option::is_none")] 725 + pub name: Option<String>, 726 + #[serde(default, skip_serializing_if = "Option::is_none")] 727 + pub description: Option<String>, 728 + #[serde(default, skip_serializing_if = "Option::is_none")] 729 + pub uri: Option<String>, 730 + #[serde(default, skip_serializing_if = "Option::is_none")] 731 + pub avatar: Option<String>, 732 + #[serde(default, skip_serializing_if = "Option::is_none")] 733 + pub creator: Option<ActorProfileViewBasic>, 734 + } 735 + 736 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 737 + pub struct FeedItemView { 738 + #[serde(default, skip_serializing_if = "Option::is_none")] 739 + pub scrobble: Option<ScrobbleViewBasic>, 740 + } 741 + 742 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 743 + pub struct FeedRecommendationsView { 744 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 745 + pub recommendations: Vec<FeedRecommendationView>, 746 + #[serde(default, skip_serializing_if = "Option::is_none")] 747 + pub cursor: Option<String>, 748 + } 749 + 750 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 751 + pub struct FeedRecommendationView { 752 + #[serde(default, skip_serializing_if = "Option::is_none")] 753 + pub title: Option<String>, 754 + #[serde(default, skip_serializing_if = "Option::is_none")] 755 + pub artist: Option<String>, 756 + #[serde(default, skip_serializing_if = "Option::is_none")] 757 + pub album: Option<String>, 758 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 759 + pub album_art: Option<String>, 760 + #[serde(rename = "trackUri", default, skip_serializing_if = "Option::is_none")] 761 + pub track_uri: Option<String>, 762 + #[serde(rename = "artistUri", default, skip_serializing_if = "Option::is_none")] 763 + pub artist_uri: Option<String>, 764 + #[serde(rename = "albumUri", default, skip_serializing_if = "Option::is_none")] 765 + pub album_uri: Option<String>, 766 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 767 + pub genres: Vec<String>, 768 + #[serde(rename = "recommendationScore", default, skip_serializing_if = "Option::is_none")] 769 + pub recommendation_score: Option<i64>, 770 + /// neighbour | social | serendipity 771 + #[serde(default, skip_serializing_if = "Option::is_none")] 772 + pub source: Option<String>, 773 + #[serde(rename = "likesCount", default, skip_serializing_if = "Option::is_none")] 774 + pub likes_count: Option<i64>, 775 + } 776 + 777 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 778 + pub struct FeedRecommendedAlbumsView { 779 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 780 + pub albums: Vec<FeedRecommendedAlbumView>, 781 + #[serde(default, skip_serializing_if = "Option::is_none")] 782 + pub cursor: Option<String>, 783 + } 784 + 785 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 786 + pub struct FeedRecommendedAlbumView { 787 + #[serde(default, skip_serializing_if = "Option::is_none")] 788 + pub id: Option<String>, 789 + #[serde(default, skip_serializing_if = "Option::is_none")] 790 + pub uri: Option<String>, 791 + #[serde(default, skip_serializing_if = "Option::is_none")] 792 + pub title: Option<String>, 793 + #[serde(default, skip_serializing_if = "Option::is_none")] 794 + pub artist: Option<String>, 795 + #[serde(rename = "artistUri", default, skip_serializing_if = "Option::is_none")] 796 + pub artist_uri: Option<String>, 797 + #[serde(default, skip_serializing_if = "Option::is_none")] 798 + pub year: Option<i64>, 799 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 800 + pub album_art: Option<String>, 801 + #[serde(rename = "recommendationScore", default, skip_serializing_if = "Option::is_none")] 802 + pub recommendation_score: Option<i64>, 803 + /// known-artist | new-artist | serendipity 804 + #[serde(default, skip_serializing_if = "Option::is_none")] 805 + pub source: Option<String>, 806 + } 807 + 808 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 809 + pub struct FeedRecommendedArtistsView { 810 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 811 + pub artists: Vec<FeedRecommendedArtistView>, 812 + #[serde(default, skip_serializing_if = "Option::is_none")] 813 + pub cursor: Option<String>, 814 + } 815 + 816 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 817 + pub struct FeedRecommendedArtistView { 818 + #[serde(default, skip_serializing_if = "Option::is_none")] 819 + pub id: Option<String>, 820 + #[serde(default, skip_serializing_if = "Option::is_none")] 821 + pub uri: Option<String>, 822 + #[serde(default, skip_serializing_if = "Option::is_none")] 823 + pub name: Option<String>, 824 + #[serde(default, skip_serializing_if = "Option::is_none")] 825 + pub picture: Option<String>, 826 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 827 + pub genres: Vec<String>, 828 + #[serde(rename = "recommendationScore", default, skip_serializing_if = "Option::is_none")] 829 + pub recommendation_score: Option<i64>, 830 + /// neighbour | social | serendipity 831 + #[serde(default, skip_serializing_if = "Option::is_none")] 832 + pub source: Option<String>, 833 + } 834 + 835 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 836 + pub struct FeedSearchResultsView { 837 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 838 + pub hits: Vec<Value>, 839 + #[serde(rename = "processingTimeMs", default, skip_serializing_if = "Option::is_none")] 840 + pub processing_time_ms: Option<i64>, 841 + #[serde(default, skip_serializing_if = "Option::is_none")] 842 + pub limit: Option<i64>, 843 + #[serde(default, skip_serializing_if = "Option::is_none")] 844 + pub offset: Option<i64>, 845 + #[serde(rename = "estimatedTotalHits", default, skip_serializing_if = "Option::is_none")] 846 + pub estimated_total_hits: Option<i64>, 847 + } 848 + 849 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 850 + pub struct FeedStoriesView { 851 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 852 + pub stories: Vec<FeedStoryView>, 853 + } 854 + 855 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 856 + pub struct FeedStoryView { 857 + #[serde(default, skip_serializing_if = "Option::is_none")] 858 + pub album: Option<String>, 859 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 860 + pub album_art: Option<String>, 861 + #[serde(rename = "albumArtist", default, skip_serializing_if = "Option::is_none")] 862 + pub album_artist: Option<String>, 863 + #[serde(rename = "albumUri", default, skip_serializing_if = "Option::is_none")] 864 + pub album_uri: Option<String>, 865 + #[serde(default, skip_serializing_if = "Option::is_none")] 866 + pub artist: Option<String>, 867 + #[serde(rename = "artistUri", default, skip_serializing_if = "Option::is_none")] 868 + pub artist_uri: Option<String>, 869 + #[serde(default, skip_serializing_if = "Option::is_none")] 870 + pub avatar: Option<String>, 871 + #[serde(rename = "createdAt", default, skip_serializing_if = "Option::is_none")] 872 + pub created_at: Option<String>, 873 + #[serde(default, skip_serializing_if = "Option::is_none")] 874 + pub did: Option<String>, 875 + #[serde(default, skip_serializing_if = "Option::is_none")] 876 + pub handle: Option<String>, 877 + #[serde(default, skip_serializing_if = "Option::is_none")] 878 + pub id: Option<String>, 879 + #[serde(default, skip_serializing_if = "Option::is_none")] 880 + pub title: Option<String>, 881 + #[serde(rename = "trackId", default, skip_serializing_if = "Option::is_none")] 882 + pub track_id: Option<String>, 883 + #[serde(rename = "trackUri", default, skip_serializing_if = "Option::is_none")] 884 + pub track_uri: Option<String>, 885 + #[serde(default, skip_serializing_if = "Option::is_none")] 886 + pub uri: Option<String>, 887 + } 888 + 889 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 890 + pub struct FeedUriView { 891 + /// The feed URI. 892 + #[serde(default, skip_serializing_if = "Option::is_none")] 893 + pub uri: Option<String>, 894 + } 895 + 896 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 897 + pub struct FeedView { 898 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 899 + pub feed: Vec<FeedItemView>, 900 + /// The pagination cursor for the next set of results. 901 + #[serde(default, skip_serializing_if = "Option::is_none")] 902 + pub cursor: Option<String>, 903 + } 904 + 905 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 906 + pub struct FollowAccountOutput { 907 + pub subject: ActorProfileViewBasic, 908 + pub followers: Vec<ActorProfileViewBasic>, 909 + /// A cursor value to pass to subsequent calls to get the next page of results. 910 + #[serde(default, skip_serializing_if = "Option::is_none")] 911 + pub cursor: Option<String>, 912 + } 913 + 914 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 915 + pub struct FollowAccountParams { 916 + pub account: String, 917 + } 918 + 919 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 920 + pub struct FollowRecord { 921 + #[serde(rename = "createdAt")] 922 + pub created_at: DateTime<Utc>, 923 + pub subject: String, 924 + #[serde(default, skip_serializing_if = "Option::is_none")] 925 + pub via: Option<StrongRef>, 926 + } 927 + 928 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 929 + pub struct GeneratorRecord { 930 + pub did: String, 931 + #[serde(default, skip_serializing_if = "Option::is_none")] 932 + pub avatar: Option<BlobRef>, 933 + #[serde(rename = "displayName")] 934 + pub display_name: String, 935 + #[serde(default, skip_serializing_if = "Option::is_none")] 936 + pub description: Option<String>, 937 + #[serde(rename = "createdAt")] 938 + pub created_at: DateTime<Utc>, 939 + } 940 + 941 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 942 + pub struct GetActorAlbumsOutput { 943 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 944 + pub albums: Vec<AlbumViewBasic>, 945 + } 946 + 947 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 948 + pub struct GetActorAlbumsParams { 949 + /// The DID or handle of the actor 950 + pub did: String, 951 + /// The maximum number of albums to return 952 + #[serde(default, skip_serializing_if = "Option::is_none")] 953 + pub limit: Option<i64>, 954 + /// The offset for pagination 955 + #[serde(default, skip_serializing_if = "Option::is_none")] 956 + pub offset: Option<i64>, 957 + /// The start date to filter albums from (ISO 8601 format) 958 + #[serde(rename = "startDate", default, skip_serializing_if = "Option::is_none")] 959 + pub start_date: Option<DateTime<Utc>>, 960 + /// The end date to filter albums to (ISO 8601 format) 961 + #[serde(rename = "endDate", default, skip_serializing_if = "Option::is_none")] 962 + pub end_date: Option<DateTime<Utc>>, 963 + } 964 + 965 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 966 + pub struct GetActorArtistsOutput { 967 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 968 + pub artists: Vec<ArtistViewBasic>, 969 + } 970 + 971 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 972 + pub struct GetActorArtistsParams { 973 + /// The DID or handle of the actor 974 + pub did: String, 975 + /// The maximum number of albums to return 976 + #[serde(default, skip_serializing_if = "Option::is_none")] 977 + pub limit: Option<i64>, 978 + /// The offset for pagination 979 + #[serde(default, skip_serializing_if = "Option::is_none")] 980 + pub offset: Option<i64>, 981 + /// The start date to filter albums from (ISO 8601 format) 982 + #[serde(rename = "startDate", default, skip_serializing_if = "Option::is_none")] 983 + pub start_date: Option<DateTime<Utc>>, 984 + /// The end date to filter albums to (ISO 8601 format) 985 + #[serde(rename = "endDate", default, skip_serializing_if = "Option::is_none")] 986 + pub end_date: Option<DateTime<Utc>>, 987 + } 988 + 989 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 990 + pub struct GetActorCompatibilityOutput { 991 + #[serde(default, skip_serializing_if = "Option::is_none")] 992 + pub compatibility: Option<ActorCompatibilityViewBasic>, 993 + } 994 + 995 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 996 + pub struct GetActorCompatibilityParams { 997 + /// DID or handle to get compatibility for 998 + pub did: String, 999 + } 1000 + 1001 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1002 + pub struct GetActorLovedSongsOutput { 1003 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1004 + pub tracks: Vec<SongViewBasic>, 1005 + } 1006 + 1007 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1008 + pub struct GetActorLovedSongsParams { 1009 + /// The DID or handle of the actor 1010 + pub did: String, 1011 + /// The maximum number of albums to return 1012 + #[serde(default, skip_serializing_if = "Option::is_none")] 1013 + pub limit: Option<i64>, 1014 + /// The offset for pagination 1015 + #[serde(default, skip_serializing_if = "Option::is_none")] 1016 + pub offset: Option<i64>, 1017 + } 1018 + 1019 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1020 + pub struct GetActorNeighboursOutput { 1021 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1022 + pub neighbours: Vec<ActorNeighbourViewBasic>, 1023 + } 1024 + 1025 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1026 + pub struct GetActorNeighboursParams { 1027 + /// The DID or handle of the actor 1028 + pub did: String, 1029 + } 1030 + 1031 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1032 + pub struct GetActorPlaylistsOutput { 1033 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1034 + pub playlists: Vec<PlaylistViewBasic>, 1035 + } 1036 + 1037 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1038 + pub struct GetActorPlaylistsParams { 1039 + /// The DID or handle of the actor 1040 + pub did: String, 1041 + /// The maximum number of albums to return 1042 + #[serde(default, skip_serializing_if = "Option::is_none")] 1043 + pub limit: Option<i64>, 1044 + /// The offset for pagination 1045 + #[serde(default, skip_serializing_if = "Option::is_none")] 1046 + pub offset: Option<i64>, 1047 + } 1048 + 1049 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1050 + pub struct GetActorScrobblesOutput { 1051 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1052 + pub scrobbles: Vec<ScrobbleViewBasic>, 1053 + } 1054 + 1055 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1056 + pub struct GetActorScrobblesParams { 1057 + /// The DID or handle of the actor 1058 + pub did: String, 1059 + /// The maximum number of albums to return 1060 + #[serde(default, skip_serializing_if = "Option::is_none")] 1061 + pub limit: Option<i64>, 1062 + /// The offset for pagination 1063 + #[serde(default, skip_serializing_if = "Option::is_none")] 1064 + pub offset: Option<i64>, 1065 + } 1066 + 1067 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1068 + pub struct GetActorSongsOutput { 1069 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1070 + pub songs: Vec<SongViewBasic>, 1071 + } 1072 + 1073 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1074 + pub struct GetActorSongsParams { 1075 + /// The DID or handle of the actor 1076 + pub did: String, 1077 + /// The maximum number of albums to return 1078 + #[serde(default, skip_serializing_if = "Option::is_none")] 1079 + pub limit: Option<i64>, 1080 + /// The offset for pagination 1081 + #[serde(default, skip_serializing_if = "Option::is_none")] 1082 + pub offset: Option<i64>, 1083 + /// The start date to filter albums from (ISO 8601 format) 1084 + #[serde(rename = "startDate", default, skip_serializing_if = "Option::is_none")] 1085 + pub start_date: Option<DateTime<Utc>>, 1086 + /// The end date to filter albums to (ISO 8601 format) 1087 + #[serde(rename = "endDate", default, skip_serializing_if = "Option::is_none")] 1088 + pub end_date: Option<DateTime<Utc>>, 1089 + } 1090 + 1091 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1092 + pub struct GetAlbumParams { 1093 + /// The URI of the album to retrieve. 1094 + pub uri: String, 1095 + } 1096 + 1097 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1098 + pub struct GetAlbumRecommendationsParams { 1099 + /// DID or handle of the user to recommend for. 1100 + pub did: String, 1101 + #[serde(default, skip_serializing_if = "Option::is_none")] 1102 + pub limit: Option<i64>, 1103 + } 1104 + 1105 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1106 + pub struct GetAlbumShoutsOutput { 1107 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1108 + pub shouts: Vec<Value>, 1109 + } 1110 + 1111 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1112 + pub struct GetAlbumShoutsParams { 1113 + /// The unique identifier of the album to retrieve shouts for 1114 + pub uri: String, 1115 + /// The maximum number of shouts to return 1116 + #[serde(default, skip_serializing_if = "Option::is_none")] 1117 + pub limit: Option<i64>, 1118 + /// The number of shouts to skip before starting to collect the result set 1119 + #[serde(default, skip_serializing_if = "Option::is_none")] 1120 + pub offset: Option<i64>, 1121 + } 1122 + 1123 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1124 + pub struct GetAlbumsOutput { 1125 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1126 + pub albums: Vec<AlbumViewBasic>, 1127 + } 1128 + 1129 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1130 + pub struct GetAlbumsParams { 1131 + /// The maximum number of albums to return 1132 + #[serde(default, skip_serializing_if = "Option::is_none")] 1133 + pub limit: Option<i64>, 1134 + /// The offset for pagination 1135 + #[serde(default, skip_serializing_if = "Option::is_none")] 1136 + pub offset: Option<i64>, 1137 + /// The genre to filter artists by 1138 + #[serde(default, skip_serializing_if = "Option::is_none")] 1139 + pub genre: Option<String>, 1140 + } 1141 + 1142 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1143 + pub struct GetAlbumTracksOutput { 1144 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1145 + pub tracks: Vec<SongViewBasic>, 1146 + } 1147 + 1148 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1149 + pub struct GetAlbumTracksParams { 1150 + /// The URI of the album to retrieve tracks from 1151 + pub uri: String, 1152 + } 1153 + 1154 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1155 + pub struct GetApikeysOutput { 1156 + #[serde(rename = "apiKeys", default, skip_serializing_if = "Vec::is_empty")] 1157 + pub api_keys: Vec<Value>, 1158 + } 1159 + 1160 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1161 + pub struct GetApikeysParams { 1162 + /// The number of API keys to skip before starting to collect the result set. 1163 + #[serde(default, skip_serializing_if = "Option::is_none")] 1164 + pub offset: Option<i64>, 1165 + /// The number of API keys to return per page. 1166 + #[serde(default, skip_serializing_if = "Option::is_none")] 1167 + pub limit: Option<i64>, 1168 + } 1169 + 1170 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1171 + pub struct GetArtistAlbumsOutput { 1172 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1173 + pub albums: Vec<AlbumViewBasic>, 1174 + } 1175 + 1176 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1177 + pub struct GetArtistAlbumsParams { 1178 + /// The URI of the artist to retrieve albums from 1179 + pub uri: String, 1180 + } 1181 + 1182 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1183 + pub struct GetArtistListenersOutput { 1184 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1185 + pub listeners: Vec<ArtistListenerViewBasic>, 1186 + } 1187 + 1188 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1189 + pub struct GetArtistListenersParams { 1190 + /// The URI of the artist to retrieve listeners from 1191 + pub uri: String, 1192 + /// Number of items to skip before returning results 1193 + #[serde(default, skip_serializing_if = "Option::is_none")] 1194 + pub offset: Option<i64>, 1195 + /// Maximum number of results to return 1196 + #[serde(default, skip_serializing_if = "Option::is_none")] 1197 + pub limit: Option<i64>, 1198 + } 1199 + 1200 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1201 + pub struct GetArtistParams { 1202 + /// The URI of the artist to retrieve details from 1203 + pub uri: String, 1204 + } 1205 + 1206 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1207 + pub struct GetArtistRecentListenersOutput { 1208 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1209 + pub listeners: Vec<ArtistRecentListenerView>, 1210 + } 1211 + 1212 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1213 + pub struct GetArtistRecentListenersParams { 1214 + /// The URI of the artist to retrieve recent listeners from 1215 + pub uri: String, 1216 + /// Number of items to skip before returning results 1217 + #[serde(default, skip_serializing_if = "Option::is_none")] 1218 + pub offset: Option<i64>, 1219 + /// Maximum number of results to return 1220 + #[serde(default, skip_serializing_if = "Option::is_none")] 1221 + pub limit: Option<i64>, 1222 + } 1223 + 1224 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1225 + pub struct GetArtistRecommendationsParams { 1226 + /// DID or handle of the user to recommend for. 1227 + pub did: String, 1228 + #[serde(default, skip_serializing_if = "Option::is_none")] 1229 + pub limit: Option<i64>, 1230 + } 1231 + 1232 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1233 + pub struct GetArtistShoutsOutput { 1234 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1235 + pub shouts: Vec<Value>, 1236 + } 1237 + 1238 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1239 + pub struct GetArtistShoutsParams { 1240 + /// The URI of the artist to retrieve shouts for 1241 + pub uri: String, 1242 + /// The maximum number of shouts to return 1243 + #[serde(default, skip_serializing_if = "Option::is_none")] 1244 + pub limit: Option<i64>, 1245 + /// The number of shouts to skip before starting to collect the result set 1246 + #[serde(default, skip_serializing_if = "Option::is_none")] 1247 + pub offset: Option<i64>, 1248 + } 1249 + 1250 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1251 + pub struct GetArtistsOutput { 1252 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1253 + pub artists: Vec<ArtistViewBasic>, 1254 + } 1255 + 1256 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1257 + pub struct GetArtistsParams { 1258 + /// The maximum number of artists to return 1259 + #[serde(default, skip_serializing_if = "Option::is_none")] 1260 + pub limit: Option<i64>, 1261 + /// The offset for pagination 1262 + #[serde(default, skip_serializing_if = "Option::is_none")] 1263 + pub offset: Option<i64>, 1264 + /// The names of the artists to return 1265 + #[serde(default, skip_serializing_if = "Option::is_none")] 1266 + pub names: Option<String>, 1267 + /// The genre to filter artists by 1268 + #[serde(default, skip_serializing_if = "Option::is_none")] 1269 + pub genre: Option<String>, 1270 + } 1271 + 1272 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1273 + pub struct GetArtistTracksOutput { 1274 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1275 + pub tracks: Vec<SongViewBasic>, 1276 + } 1277 + 1278 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1279 + pub struct GetArtistTracksParams { 1280 + /// The URI of the artist to retrieve albums from 1281 + #[serde(default, skip_serializing_if = "Option::is_none")] 1282 + pub uri: Option<String>, 1283 + /// The maximum number of tracks to return 1284 + #[serde(default, skip_serializing_if = "Option::is_none")] 1285 + pub limit: Option<i64>, 1286 + /// The offset for pagination 1287 + #[serde(default, skip_serializing_if = "Option::is_none")] 1288 + pub offset: Option<i64>, 1289 + } 1290 + 1291 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1292 + pub struct GetCurrentlyPlayingParams { 1293 + #[serde(rename = "playerId", default, skip_serializing_if = "Option::is_none")] 1294 + pub player_id: Option<String>, 1295 + /// Handle or DID of the actor to retrieve the currently playing track for. If not provided, defaults to the current user. 1296 + #[serde(default, skip_serializing_if = "Option::is_none")] 1297 + pub actor: Option<String>, 1298 + } 1299 + 1300 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1301 + pub struct GetFeedGeneratorOutput { 1302 + #[serde(default, skip_serializing_if = "Option::is_none")] 1303 + pub view: Option<FeedGeneratorView>, 1304 + } 1305 + 1306 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1307 + pub struct GetFeedGeneratorParams { 1308 + /// AT-URI of the feed generator record. 1309 + pub feed: String, 1310 + } 1311 + 1312 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1313 + pub struct GetFeedGeneratorsParams { 1314 + /// The maximum number of feed generators to return. 1315 + #[serde(default, skip_serializing_if = "Option::is_none")] 1316 + pub size: Option<i64>, 1317 + } 1318 + 1319 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1320 + pub struct GetFeedParams { 1321 + /// The feed URI. 1322 + pub feed: String, 1323 + /// The maximum number of scrobbles to return 1324 + #[serde(default, skip_serializing_if = "Option::is_none")] 1325 + pub limit: Option<i64>, 1326 + /// The cursor for pagination 1327 + #[serde(default, skip_serializing_if = "Option::is_none")] 1328 + pub cursor: Option<String>, 1329 + } 1330 + 1331 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1332 + pub struct GetFeedSkeletonOutput { 1333 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1334 + pub scrobbles: Vec<ScrobbleViewBasic>, 1335 + /// The pagination cursor for the next set of results. 1336 + #[serde(default, skip_serializing_if = "Option::is_none")] 1337 + pub cursor: Option<String>, 1338 + } 1339 + 1340 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1341 + pub struct GetFeedSkeletonParams { 1342 + /// The feed URI. 1343 + pub feed: String, 1344 + /// The maximum number of scrobbles to return 1345 + #[serde(default, skip_serializing_if = "Option::is_none")] 1346 + pub limit: Option<i64>, 1347 + /// The offset for pagination 1348 + #[serde(default, skip_serializing_if = "Option::is_none")] 1349 + pub offset: Option<i64>, 1350 + /// The pagination cursor. 1351 + #[serde(default, skip_serializing_if = "Option::is_none")] 1352 + pub cursor: Option<String>, 1353 + } 1354 + 1355 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1356 + pub struct GetFileParams { 1357 + /// The unique identifier of the file to retrieve 1358 + #[serde(rename = "fileId")] 1359 + pub file_id: String, 1360 + } 1361 + 1362 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1363 + pub struct GetFilesParams { 1364 + /// Path to the Dropbox folder or root directory 1365 + #[serde(default, skip_serializing_if = "Option::is_none")] 1366 + pub at: Option<String>, 1367 + } 1368 + 1369 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1370 + pub struct GetFollowersOutput { 1371 + pub subject: ActorProfileViewBasic, 1372 + pub followers: Vec<ActorProfileViewBasic>, 1373 + /// A cursor value to pass to subsequent calls to get the next page of results. 1374 + #[serde(default, skip_serializing_if = "Option::is_none")] 1375 + pub cursor: Option<String>, 1376 + /// The total number of followers. 1377 + #[serde(default, skip_serializing_if = "Option::is_none")] 1378 + pub count: Option<i64>, 1379 + } 1380 + 1381 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1382 + pub struct GetFollowersParams { 1383 + pub actor: String, 1384 + #[serde(default, skip_serializing_if = "Option::is_none")] 1385 + pub limit: Option<i64>, 1386 + /// If provided, filters the followers to only include those with DIDs in this list. 1387 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1388 + pub dids: Vec<String>, 1389 + #[serde(default, skip_serializing_if = "Option::is_none")] 1390 + pub cursor: Option<String>, 1391 + } 1392 + 1393 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1394 + pub struct GetFollowsOutput { 1395 + pub subject: ActorProfileViewBasic, 1396 + pub follows: Vec<ActorProfileViewBasic>, 1397 + /// A cursor value to pass to subsequent calls to get the next page of results. 1398 + #[serde(default, skip_serializing_if = "Option::is_none")] 1399 + pub cursor: Option<String>, 1400 + /// The total number of follows. 1401 + #[serde(default, skip_serializing_if = "Option::is_none")] 1402 + pub count: Option<i64>, 1403 + } 1404 + 1405 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1406 + pub struct GetFollowsParams { 1407 + pub actor: String, 1408 + #[serde(default, skip_serializing_if = "Option::is_none")] 1409 + pub limit: Option<i64>, 1410 + /// If provided, filters the follows to only include those with DIDs in this list. 1411 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1412 + pub dids: Vec<String>, 1413 + #[serde(default, skip_serializing_if = "Option::is_none")] 1414 + pub cursor: Option<String>, 1415 + } 1416 + 1417 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1418 + pub struct GetKnownFollowersOutput { 1419 + pub subject: ActorProfileViewBasic, 1420 + pub followers: Vec<ActorProfileViewBasic>, 1421 + /// A cursor value to pass to subsequent calls to get the next page of results. 1422 + #[serde(default, skip_serializing_if = "Option::is_none")] 1423 + pub cursor: Option<String>, 1424 + } 1425 + 1426 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1427 + pub struct GetKnownFollowersParams { 1428 + pub actor: String, 1429 + #[serde(default, skip_serializing_if = "Option::is_none")] 1430 + pub limit: Option<i64>, 1431 + #[serde(default, skip_serializing_if = "Option::is_none")] 1432 + pub cursor: Option<String>, 1433 + } 1434 + 1435 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1436 + pub struct GetMetadataParams { 1437 + /// Path to the file or folder in Dropbox 1438 + pub path: String, 1439 + } 1440 + 1441 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1442 + pub struct GetMirrorSourcesOutput { 1443 + pub sources: Vec<MirrorSourceView>, 1444 + } 1445 + 1446 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1447 + pub struct GetMirrorSourcesParams { 1448 + } 1449 + 1450 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1451 + pub struct GetPlaybackQueueParams { 1452 + #[serde(rename = "playerId", default, skip_serializing_if = "Option::is_none")] 1453 + pub player_id: Option<String>, 1454 + } 1455 + 1456 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1457 + pub struct GetPlaylistParams { 1458 + /// The URI of the playlist to retrieve. 1459 + pub uri: String, 1460 + } 1461 + 1462 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1463 + pub struct GetPlaylistsOutput { 1464 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1465 + pub playlists: Vec<PlaylistViewBasic>, 1466 + } 1467 + 1468 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1469 + pub struct GetPlaylistsParams { 1470 + /// The maximum number of playlists to return. 1471 + #[serde(default, skip_serializing_if = "Option::is_none")] 1472 + pub limit: Option<i64>, 1473 + /// The offset for pagination, used to skip a number of playlists. 1474 + #[serde(default, skip_serializing_if = "Option::is_none")] 1475 + pub offset: Option<i64>, 1476 + } 1477 + 1478 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1479 + pub struct GetProfileParams { 1480 + /// The DID or handle of the actor 1481 + #[serde(default, skip_serializing_if = "Option::is_none")] 1482 + pub did: Option<String>, 1483 + } 1484 + 1485 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1486 + pub struct GetProfileShoutsOutput { 1487 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1488 + pub shouts: Vec<Value>, 1489 + } 1490 + 1491 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1492 + pub struct GetProfileShoutsParams { 1493 + /// The DID or handle of the actor 1494 + pub did: String, 1495 + /// The offset for pagination 1496 + #[serde(default, skip_serializing_if = "Option::is_none")] 1497 + pub offset: Option<i64>, 1498 + /// The maximum number of shouts to return 1499 + #[serde(default, skip_serializing_if = "Option::is_none")] 1500 + pub limit: Option<i64>, 1501 + } 1502 + 1503 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1504 + pub struct GetRecommendationsParams { 1505 + /// DID or handle of the user to recommend for. 1506 + pub did: String, 1507 + #[serde(default, skip_serializing_if = "Option::is_none")] 1508 + pub limit: Option<i64>, 1509 + } 1510 + 1511 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1512 + pub struct GetScrobbleParams { 1513 + /// The unique identifier of the scrobble 1514 + pub uri: String, 1515 + } 1516 + 1517 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1518 + pub struct GetScrobblesChartParams { 1519 + /// The DID or handle of the actor 1520 + #[serde(default, skip_serializing_if = "Option::is_none")] 1521 + pub did: Option<String>, 1522 + /// The URI of the artist to filter by 1523 + #[serde(default, skip_serializing_if = "Option::is_none")] 1524 + pub artisturi: Option<String>, 1525 + /// The URI of the album to filter by 1526 + #[serde(default, skip_serializing_if = "Option::is_none")] 1527 + pub albumuri: Option<String>, 1528 + /// The URI of the track to filter by 1529 + #[serde(default, skip_serializing_if = "Option::is_none")] 1530 + pub songuri: Option<String>, 1531 + /// The genre to filter by 1532 + #[serde(default, skip_serializing_if = "Option::is_none")] 1533 + pub genre: Option<String>, 1534 + /// Start date (ISO 8601). Defaults to 6 months ago. 1535 + #[serde(default, skip_serializing_if = "Option::is_none")] 1536 + pub from: Option<String>, 1537 + /// End date (ISO 8601). Defaults to today. 1538 + #[serde(default, skip_serializing_if = "Option::is_none")] 1539 + pub to: Option<String>, 1540 + } 1541 + 1542 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1543 + pub struct GetScrobblesOutput { 1544 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1545 + pub scrobbles: Vec<ScrobbleViewBasic>, 1546 + } 1547 + 1548 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1549 + pub struct GetScrobblesParams { 1550 + /// The DID or handle of the actor 1551 + #[serde(default, skip_serializing_if = "Option::is_none")] 1552 + pub did: Option<String>, 1553 + /// If true, only return scrobbles from actors the viewer is following. 1554 + #[serde(default, skip_serializing_if = "Option::is_none")] 1555 + pub following: Option<bool>, 1556 + /// The maximum number of scrobbles to return 1557 + #[serde(default, skip_serializing_if = "Option::is_none")] 1558 + pub limit: Option<i64>, 1559 + /// The offset for pagination 1560 + #[serde(default, skip_serializing_if = "Option::is_none")] 1561 + pub offset: Option<i64>, 1562 + } 1563 + 1564 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1565 + pub struct GetShoutRepliesOutput { 1566 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1567 + pub shouts: Vec<Value>, 1568 + } 1569 + 1570 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1571 + pub struct GetShoutRepliesParams { 1572 + /// The URI of the shout to retrieve replies for 1573 + pub uri: String, 1574 + /// The maximum number of shouts to return 1575 + #[serde(default, skip_serializing_if = "Option::is_none")] 1576 + pub limit: Option<i64>, 1577 + /// The number of shouts to skip before starting to collect the result set 1578 + #[serde(default, skip_serializing_if = "Option::is_none")] 1579 + pub offset: Option<i64>, 1580 + } 1581 + 1582 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1583 + pub struct GetSongParams { 1584 + /// The AT-URI of the song to retrieve 1585 + #[serde(default, skip_serializing_if = "Option::is_none")] 1586 + pub uri: Option<String>, 1587 + /// The MusicBrainz ID of the song to retrieve 1588 + #[serde(default, skip_serializing_if = "Option::is_none")] 1589 + pub mbid: Option<String>, 1590 + /// The International Standard Recording Code (ISRC) of the song to retrieve 1591 + #[serde(default, skip_serializing_if = "Option::is_none")] 1592 + pub isrc: Option<String>, 1593 + /// The Spotify track ID of the song to retrieve (resolved internally to the Spotify track URL) 1594 + #[serde(rename = "spotifyId", default, skip_serializing_if = "Option::is_none")] 1595 + pub spotify_id: Option<String>, 1596 + } 1597 + 1598 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1599 + pub struct GetSongRecentListenersOutput { 1600 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1601 + pub listeners: Vec<SongRecentListenerView>, 1602 + } 1603 + 1604 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1605 + pub struct GetSongRecentListenersParams { 1606 + /// The URI of the song to retrieve recent listeners from 1607 + pub uri: String, 1608 + /// Number of items to skip before returning results 1609 + #[serde(default, skip_serializing_if = "Option::is_none")] 1610 + pub offset: Option<i64>, 1611 + /// Maximum number of results to return 1612 + #[serde(default, skip_serializing_if = "Option::is_none")] 1613 + pub limit: Option<i64>, 1614 + } 1615 + 1616 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1617 + pub struct GetSongsOutput { 1618 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1619 + pub songs: Vec<SongViewBasic>, 1620 + } 1621 + 1622 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1623 + pub struct GetSongsParams { 1624 + /// The maximum number of songs to return 1625 + #[serde(default, skip_serializing_if = "Option::is_none")] 1626 + pub limit: Option<i64>, 1627 + /// The offset for pagination 1628 + #[serde(default, skip_serializing_if = "Option::is_none")] 1629 + pub offset: Option<i64>, 1630 + /// The genre to filter artists by 1631 + #[serde(default, skip_serializing_if = "Option::is_none")] 1632 + pub genre: Option<String>, 1633 + /// Filter songs by MusicBrainz ID 1634 + #[serde(default, skip_serializing_if = "Option::is_none")] 1635 + pub mbid: Option<String>, 1636 + /// Filter songs by International Standard Recording Code (ISRC) 1637 + #[serde(default, skip_serializing_if = "Option::is_none")] 1638 + pub isrc: Option<String>, 1639 + /// Filter songs by Spotify track ID (resolved internally to the Spotify track URL) 1640 + #[serde(rename = "spotifyId", default, skip_serializing_if = "Option::is_none")] 1641 + pub spotify_id: Option<String>, 1642 + } 1643 + 1644 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1645 + pub struct GetStatsParams { 1646 + /// The DID or handle of the user to get stats for. 1647 + pub did: String, 1648 + } 1649 + 1650 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1651 + pub struct GetStoriesParams { 1652 + /// The maximum number of stories to return. 1653 + #[serde(default, skip_serializing_if = "Option::is_none")] 1654 + pub size: Option<i64>, 1655 + } 1656 + 1657 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1658 + pub struct GetTemporaryLinkParams { 1659 + /// Path to the file in Dropbox 1660 + pub path: String, 1661 + } 1662 + 1663 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1664 + pub struct GetTopArtistsOutput { 1665 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1666 + pub artists: Vec<ArtistViewBasic>, 1667 + } 1668 + 1669 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1670 + pub struct GetTopArtistsParams { 1671 + /// The maximum number of artists to return 1672 + #[serde(default, skip_serializing_if = "Option::is_none")] 1673 + pub limit: Option<i64>, 1674 + /// The offset for pagination 1675 + #[serde(default, skip_serializing_if = "Option::is_none")] 1676 + pub offset: Option<i64>, 1677 + /// The start date to filter artists from (ISO 8601 format) 1678 + #[serde(rename = "startDate", default, skip_serializing_if = "Option::is_none")] 1679 + pub start_date: Option<DateTime<Utc>>, 1680 + /// The end date to filter artists to (ISO 8601 format) 1681 + #[serde(rename = "endDate", default, skip_serializing_if = "Option::is_none")] 1682 + pub end_date: Option<DateTime<Utc>>, 1683 + } 1684 + 1685 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1686 + pub struct GetTopTracksOutput { 1687 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1688 + pub tracks: Vec<SongViewBasic>, 1689 + } 1690 + 1691 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1692 + pub struct GetTopTracksParams { 1693 + /// The maximum number of tracks to return 1694 + #[serde(default, skip_serializing_if = "Option::is_none")] 1695 + pub limit: Option<i64>, 1696 + /// The offset for pagination 1697 + #[serde(default, skip_serializing_if = "Option::is_none")] 1698 + pub offset: Option<i64>, 1699 + /// The start date to filter tracks from (ISO 8601 format) 1700 + #[serde(rename = "startDate", default, skip_serializing_if = "Option::is_none")] 1701 + pub start_date: Option<DateTime<Utc>>, 1702 + /// The end date to filter tracks to (ISO 8601 format) 1703 + #[serde(rename = "endDate", default, skip_serializing_if = "Option::is_none")] 1704 + pub end_date: Option<DateTime<Utc>>, 1705 + } 1706 + 1707 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1708 + pub struct GetTrackShoutsOutput { 1709 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1710 + pub shouts: Vec<Value>, 1711 + } 1712 + 1713 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1714 + pub struct GetTrackShoutsParams { 1715 + /// The URI of the track to retrieve shouts for 1716 + pub uri: String, 1717 + } 1718 + 1719 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1720 + pub struct GetWrappedParams { 1721 + /// The DID or handle of the user 1722 + pub did: String, 1723 + /// The year to get wrapped stats for (defaults to current year) 1724 + #[serde(default, skip_serializing_if = "Option::is_none")] 1725 + pub year: Option<i64>, 1726 + } 1727 + 1728 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1729 + pub struct GoogledriveFileListView { 1730 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1731 + pub files: Vec<GoogledriveFileView>, 1732 + } 1733 + 1734 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1735 + pub struct GoogledriveFileView { 1736 + /// The unique identifier of the file. 1737 + #[serde(default, skip_serializing_if = "Option::is_none")] 1738 + pub id: Option<String>, 1739 + } 1740 + 1741 + /// indicates that a handle or DID could not be resolved 1742 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1743 + pub struct GraphNotFoundActor { 1744 + pub actor: String, 1745 + #[serde(rename = "notFound")] 1746 + pub not_found: bool, 1747 + } 1748 + 1749 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1750 + pub struct GraphRelationship { 1751 + pub did: String, 1752 + /// if the actor follows this DID, this is the AT-URI of the follow record 1753 + #[serde(default, skip_serializing_if = "Option::is_none")] 1754 + pub following: Option<String>, 1755 + /// if the actor is followed by this DID, contains the AT-URI of the follow record 1756 + #[serde(rename = "followedBy", default, skip_serializing_if = "Option::is_none")] 1757 + pub followed_by: Option<String>, 1758 + } 1759 + 1760 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1761 + pub struct InsertDirectoryParams { 1762 + /// The URI of the playlist to start 1763 + pub uri: String, 1764 + /// The directory (id) to insert into the playlist 1765 + pub directory: String, 1766 + /// The position in the playlist to insert the directory at, if not specified, the directory will be appended 1767 + #[serde(default, skip_serializing_if = "Option::is_none")] 1768 + pub position: Option<i64>, 1769 + } 1770 + 1771 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1772 + pub struct InsertFilesParams { 1773 + /// The URI of the playlist to start 1774 + pub uri: String, 1775 + pub files: Vec<String>, 1776 + /// The position in the playlist to insert the files at, if not specified, files will be appended 1777 + #[serde(default, skip_serializing_if = "Option::is_none")] 1778 + pub position: Option<i64>, 1779 + } 1780 + 1781 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1782 + pub struct LikeRecord { 1783 + /// The date when the like was created. 1784 + #[serde(rename = "createdAt")] 1785 + pub created_at: DateTime<Utc>, 1786 + pub subject: StrongRef, 1787 + } 1788 + 1789 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1790 + pub struct LikeShoutInput { 1791 + /// The unique identifier of the shout to like 1792 + #[serde(default, skip_serializing_if = "Option::is_none")] 1793 + pub uri: Option<String>, 1794 + } 1795 + 1796 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1797 + pub struct LikeSongInput { 1798 + /// The unique identifier of the song to like 1799 + #[serde(default, skip_serializing_if = "Option::is_none")] 1800 + pub uri: Option<String>, 1801 + } 1802 + 1803 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1804 + pub struct MatchSongParams { 1805 + /// The title of the song to retrieve 1806 + pub title: String, 1807 + /// The artist of the song to retrieve 1808 + pub artist: String, 1809 + /// Optional MusicBrainz recording ID to anchor the match 1810 + #[serde(rename = "mbId", default, skip_serializing_if = "Option::is_none")] 1811 + pub mb_id: Option<String>, 1812 + /// Optional International Standard Recording Code (ISRC) to anchor the match 1813 + #[serde(default, skip_serializing_if = "Option::is_none")] 1814 + pub isrc: Option<String>, 1815 + } 1816 + 1817 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1818 + pub struct MirrorSourceView { 1819 + /// One of: lastfm, listenbrainz, tealfm 1820 + pub provider: String, 1821 + /// Whether scrobbles from this source are being mirrored into Rocksky. 1822 + pub enabled: bool, 1823 + /// Username on the external service (Last.fm / ListenBrainz). Null for Teal.fm. 1824 + #[serde(rename = "externalUsername", default, skip_serializing_if = "Option::is_none")] 1825 + pub external_username: Option<String>, 1826 + /// True when an API key is stored. Last.fm/ListenBrainz only; always false for Teal.fm. 1827 + #[serde(rename = "hasCredentials")] 1828 + pub has_credentials: bool, 1829 + /// The last time the mirror process successfully polled this source. 1830 + #[serde(rename = "lastPolledAt", default, skip_serializing_if = "Option::is_none")] 1831 + pub last_polled_at: Option<DateTime<Utc>>, 1832 + /// Watermark — scrobbles from the external service older than this are skipped. 1833 + #[serde(rename = "lastScrobbleSeenAt", default, skip_serializing_if = "Option::is_none")] 1834 + pub last_scrobble_seen_at: Option<DateTime<Utc>>, 1835 + } 1836 + 1837 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1838 + pub struct NextParams { 1839 + #[serde(rename = "playerId", default, skip_serializing_if = "Option::is_none")] 1840 + pub player_id: Option<String>, 1841 + } 1842 + 1843 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1844 + pub struct PauseParams { 1845 + #[serde(rename = "playerId", default, skip_serializing_if = "Option::is_none")] 1846 + pub player_id: Option<String>, 1847 + } 1848 + 1849 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1850 + pub struct PlayDirectoryParams { 1851 + #[serde(rename = "playerId", default, skip_serializing_if = "Option::is_none")] 1852 + pub player_id: Option<String>, 1853 + #[serde(rename = "directoryId")] 1854 + pub directory_id: String, 1855 + #[serde(default, skip_serializing_if = "Option::is_none")] 1856 + pub shuffle: Option<bool>, 1857 + #[serde(default, skip_serializing_if = "Option::is_none")] 1858 + pub recurse: Option<bool>, 1859 + #[serde(default, skip_serializing_if = "Option::is_none")] 1860 + pub position: Option<i64>, 1861 + } 1862 + 1863 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1864 + pub struct PlayerCurrentlyPlayingViewDetailed { 1865 + /// The title of the currently playing track 1866 + #[serde(default, skip_serializing_if = "Option::is_none")] 1867 + pub title: Option<String>, 1868 + } 1869 + 1870 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1871 + pub struct PlayerPlaybackQueueViewDetailed { 1872 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1873 + pub tracks: Vec<SongViewBasic>, 1874 + } 1875 + 1876 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1877 + pub struct PlayFileParams { 1878 + #[serde(rename = "playerId", default, skip_serializing_if = "Option::is_none")] 1879 + pub player_id: Option<String>, 1880 + #[serde(rename = "fileId")] 1881 + pub file_id: String, 1882 + } 1883 + 1884 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1885 + pub struct PlaylistItemRecord { 1886 + pub subject: StrongRef, 1887 + /// The date the playlist was created. 1888 + #[serde(rename = "createdAt")] 1889 + pub created_at: DateTime<Utc>, 1890 + pub track: SongViewBasic, 1891 + /// The order of the item in the playlist. 1892 + pub order: i64, 1893 + } 1894 + 1895 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1896 + pub struct PlaylistRecord { 1897 + /// The name of the playlist. 1898 + pub name: String, 1899 + /// The playlist description. 1900 + #[serde(default, skip_serializing_if = "Option::is_none")] 1901 + pub description: Option<String>, 1902 + /// The picture of the playlist. 1903 + #[serde(default, skip_serializing_if = "Option::is_none")] 1904 + pub picture: Option<BlobRef>, 1905 + /// The URL of the picture of the artist. 1906 + #[serde(rename = "pictureUrl", default, skip_serializing_if = "Option::is_none")] 1907 + pub picture_url: Option<String>, 1908 + /// The date the playlist was created. 1909 + #[serde(rename = "createdAt")] 1910 + pub created_at: DateTime<Utc>, 1911 + /// The Spotify link of the playlist. 1912 + #[serde(rename = "spotifyLink", default, skip_serializing_if = "Option::is_none")] 1913 + pub spotify_link: Option<String>, 1914 + /// The Tidal link of the playlist. 1915 + #[serde(rename = "tidalLink", default, skip_serializing_if = "Option::is_none")] 1916 + pub tidal_link: Option<String>, 1917 + /// The YouTube link of the playlist. 1918 + #[serde(rename = "youtubeLink", default, skip_serializing_if = "Option::is_none")] 1919 + pub youtube_link: Option<String>, 1920 + /// The Apple Music link of the playlist. 1921 + #[serde(rename = "appleMusicLink", default, skip_serializing_if = "Option::is_none")] 1922 + pub apple_music_link: Option<String>, 1923 + } 1924 + 1925 + /// Basic view of a playlist, including its metadata 1926 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1927 + pub struct PlaylistViewBasic { 1928 + /// The unique identifier of the playlist. 1929 + #[serde(default, skip_serializing_if = "Option::is_none")] 1930 + pub id: Option<String>, 1931 + /// The title of the playlist. 1932 + #[serde(default, skip_serializing_if = "Option::is_none")] 1933 + pub title: Option<String>, 1934 + /// The URI of the playlist. 1935 + #[serde(default, skip_serializing_if = "Option::is_none")] 1936 + pub uri: Option<String>, 1937 + /// The DID of the curator of the playlist. 1938 + #[serde(rename = "curatorDid", default, skip_serializing_if = "Option::is_none")] 1939 + pub curator_did: Option<String>, 1940 + /// The handle of the curator of the playlist. 1941 + #[serde(rename = "curatorHandle", default, skip_serializing_if = "Option::is_none")] 1942 + pub curator_handle: Option<String>, 1943 + /// The name of the curator of the playlist. 1944 + #[serde(rename = "curatorName", default, skip_serializing_if = "Option::is_none")] 1945 + pub curator_name: Option<String>, 1946 + /// The URL of the avatar image of the curator. 1947 + #[serde(rename = "curatorAvatarUrl", default, skip_serializing_if = "Option::is_none")] 1948 + pub curator_avatar_url: Option<String>, 1949 + /// A description of the playlist. 1950 + #[serde(default, skip_serializing_if = "Option::is_none")] 1951 + pub description: Option<String>, 1952 + /// The URL of the cover image for the playlist. 1953 + #[serde(rename = "coverImageUrl", default, skip_serializing_if = "Option::is_none")] 1954 + pub cover_image_url: Option<String>, 1955 + /// The date and time when the playlist was created. 1956 + #[serde(rename = "createdAt", default, skip_serializing_if = "Option::is_none")] 1957 + pub created_at: Option<DateTime<Utc>>, 1958 + /// The number of tracks in the playlist. 1959 + #[serde(rename = "trackCount", default, skip_serializing_if = "Option::is_none")] 1960 + pub track_count: Option<i64>, 1961 + } 1962 + 1963 + /// Detailed view of a playlist, including its tracks and metadata 1964 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 1965 + pub struct PlaylistViewDetailed { 1966 + /// The unique identifier of the playlist. 1967 + #[serde(default, skip_serializing_if = "Option::is_none")] 1968 + pub id: Option<String>, 1969 + /// The title of the playlist. 1970 + #[serde(default, skip_serializing_if = "Option::is_none")] 1971 + pub title: Option<String>, 1972 + /// The URI of the playlist. 1973 + #[serde(default, skip_serializing_if = "Option::is_none")] 1974 + pub uri: Option<String>, 1975 + /// The DID of the curator of the playlist. 1976 + #[serde(rename = "curatorDid", default, skip_serializing_if = "Option::is_none")] 1977 + pub curator_did: Option<String>, 1978 + /// The handle of the curator of the playlist. 1979 + #[serde(rename = "curatorHandle", default, skip_serializing_if = "Option::is_none")] 1980 + pub curator_handle: Option<String>, 1981 + /// The name of the curator of the playlist. 1982 + #[serde(rename = "curatorName", default, skip_serializing_if = "Option::is_none")] 1983 + pub curator_name: Option<String>, 1984 + /// The URL of the avatar image of the curator. 1985 + #[serde(rename = "curatorAvatarUrl", default, skip_serializing_if = "Option::is_none")] 1986 + pub curator_avatar_url: Option<String>, 1987 + /// A description of the playlist. 1988 + #[serde(default, skip_serializing_if = "Option::is_none")] 1989 + pub description: Option<String>, 1990 + /// The URL of the cover image for the playlist. 1991 + #[serde(rename = "coverImageUrl", default, skip_serializing_if = "Option::is_none")] 1992 + pub cover_image_url: Option<String>, 1993 + /// The date and time when the playlist was created. 1994 + #[serde(rename = "createdAt", default, skip_serializing_if = "Option::is_none")] 1995 + pub created_at: Option<DateTime<Utc>>, 1996 + /// A list of tracks in the playlist. 1997 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 1998 + pub tracks: Vec<SongViewBasic>, 1999 + } 2000 + 2001 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2002 + pub struct PlayParams { 2003 + #[serde(rename = "playerId", default, skip_serializing_if = "Option::is_none")] 2004 + pub player_id: Option<String>, 2005 + } 2006 + 2007 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2008 + pub struct PreviousParams { 2009 + #[serde(rename = "playerId", default, skip_serializing_if = "Option::is_none")] 2010 + pub player_id: Option<String>, 2011 + } 2012 + 2013 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2014 + pub struct ProfileRecord { 2015 + #[serde(rename = "displayName", default, skip_serializing_if = "Option::is_none")] 2016 + pub display_name: Option<String>, 2017 + /// Free-form profile description text. 2018 + #[serde(default, skip_serializing_if = "Option::is_none")] 2019 + pub description: Option<String>, 2020 + /// Small image to be displayed next to posts from account. AKA, 'profile picture' 2021 + #[serde(default, skip_serializing_if = "Option::is_none")] 2022 + pub avatar: Option<BlobRef>, 2023 + /// Larger horizontal image to display behind profile view. 2024 + #[serde(default, skip_serializing_if = "Option::is_none")] 2025 + pub banner: Option<BlobRef>, 2026 + /// Self-label values, specific to the Bluesky application, on the overall account. 2027 + #[serde(default, skip_serializing_if = "Option::is_none")] 2028 + pub labels: Option<Value>, 2029 + #[serde(rename = "joinedViaStarterPack", default, skip_serializing_if = "Option::is_none")] 2030 + pub joined_via_starter_pack: Option<StrongRef>, 2031 + #[serde(rename = "createdAt", default, skip_serializing_if = "Option::is_none")] 2032 + pub created_at: Option<DateTime<Utc>>, 2033 + } 2034 + 2035 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2036 + pub struct PutMirrorSourceInput { 2037 + /// One of: lastfm, listenbrainz, tealfm 2038 + pub provider: String, 2039 + /// Enable or disable mirroring for this provider. 2040 + #[serde(default, skip_serializing_if = "Option::is_none")] 2041 + pub enabled: Option<bool>, 2042 + /// External username (Last.fm / ListenBrainz). Required when enabling those providers. Ignored for Teal.fm. 2043 + #[serde(rename = "externalUsername", default, skip_serializing_if = "Option::is_none")] 2044 + pub external_username: Option<String>, 2045 + /// API key / token to be encrypted at rest. Omit to leave the existing key unchanged. Pass an empty string to clear it. 2046 + #[serde(rename = "apiKey", default, skip_serializing_if = "Option::is_none")] 2047 + pub api_key: Option<String>, 2048 + } 2049 + 2050 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2051 + pub struct RadioRecord { 2052 + /// The name of the radio station. 2053 + pub name: String, 2054 + /// The URL of the radio station. 2055 + pub url: String, 2056 + /// A description of the radio station. 2057 + #[serde(default, skip_serializing_if = "Option::is_none")] 2058 + pub description: Option<String>, 2059 + /// The genre of the radio station. 2060 + #[serde(default, skip_serializing_if = "Option::is_none")] 2061 + pub genre: Option<String>, 2062 + /// The logo of the radio station. 2063 + #[serde(default, skip_serializing_if = "Option::is_none")] 2064 + pub logo: Option<BlobRef>, 2065 + /// The website of the radio station. 2066 + #[serde(default, skip_serializing_if = "Option::is_none")] 2067 + pub website: Option<String>, 2068 + /// The date when the radio station was created. 2069 + #[serde(rename = "createdAt")] 2070 + pub created_at: DateTime<Utc>, 2071 + } 2072 + 2073 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2074 + pub struct RadioViewBasic { 2075 + /// The unique identifier of the radio. 2076 + #[serde(default, skip_serializing_if = "Option::is_none")] 2077 + pub id: Option<String>, 2078 + /// The name of the radio. 2079 + #[serde(default, skip_serializing_if = "Option::is_none")] 2080 + pub name: Option<String>, 2081 + /// A brief description of the radio. 2082 + #[serde(default, skip_serializing_if = "Option::is_none")] 2083 + pub description: Option<String>, 2084 + /// The date and time when the radio was created. 2085 + #[serde(rename = "createdAt", default, skip_serializing_if = "Option::is_none")] 2086 + pub created_at: Option<DateTime<Utc>>, 2087 + } 2088 + 2089 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2090 + pub struct RadioViewDetailed { 2091 + /// The unique identifier of the radio. 2092 + #[serde(default, skip_serializing_if = "Option::is_none")] 2093 + pub id: Option<String>, 2094 + /// The name of the radio. 2095 + #[serde(default, skip_serializing_if = "Option::is_none")] 2096 + pub name: Option<String>, 2097 + /// A brief description of the radio. 2098 + #[serde(default, skip_serializing_if = "Option::is_none")] 2099 + pub description: Option<String>, 2100 + /// The website of the radio. 2101 + #[serde(default, skip_serializing_if = "Option::is_none")] 2102 + pub website: Option<String>, 2103 + /// The streaming URL of the radio. 2104 + #[serde(default, skip_serializing_if = "Option::is_none")] 2105 + pub url: Option<String>, 2106 + /// The genre of the radio. 2107 + #[serde(default, skip_serializing_if = "Option::is_none")] 2108 + pub genre: Option<String>, 2109 + /// The logo of the radio station. 2110 + #[serde(default, skip_serializing_if = "Option::is_none")] 2111 + pub logo: Option<String>, 2112 + /// The date and time when the radio was created. 2113 + #[serde(rename = "createdAt", default, skip_serializing_if = "Option::is_none")] 2114 + pub created_at: Option<DateTime<Utc>>, 2115 + } 2116 + 2117 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2118 + pub struct RemoveApikeyParams { 2119 + /// The ID of the API key to remove. 2120 + pub id: String, 2121 + } 2122 + 2123 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2124 + pub struct RemovePlaylistParams { 2125 + /// The URI of the playlist to remove 2126 + pub uri: String, 2127 + } 2128 + 2129 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2130 + pub struct RemoveShoutParams { 2131 + /// The ID of the shout to be removed 2132 + pub id: String, 2133 + } 2134 + 2135 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2136 + pub struct RemoveTrackParams { 2137 + /// The URI of the playlist to remove the track from 2138 + pub uri: String, 2139 + /// The position of the track to remove in the playlist 2140 + pub position: i64, 2141 + } 2142 + 2143 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2144 + pub struct ReplyShoutInput { 2145 + /// The unique identifier of the shout to reply to 2146 + #[serde(rename = "shoutId")] 2147 + pub shout_id: String, 2148 + /// The content of the reply 2149 + pub message: String, 2150 + } 2151 + 2152 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2153 + pub struct ReportShoutInput { 2154 + /// The unique identifier of the shout to report 2155 + #[serde(rename = "shoutId")] 2156 + pub shout_id: String, 2157 + /// The reason for reporting the shout 2158 + #[serde(default, skip_serializing_if = "Option::is_none")] 2159 + pub reason: Option<String>, 2160 + } 2161 + 2162 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2163 + pub struct ScrobbleFirstScrobbleView { 2164 + /// The handle of the user who first scrobbled this song. 2165 + #[serde(default, skip_serializing_if = "Option::is_none")] 2166 + pub handle: Option<String>, 2167 + /// The avatar URL of the user who first scrobbled this song. 2168 + #[serde(default, skip_serializing_if = "Option::is_none")] 2169 + pub avatar: Option<String>, 2170 + /// The timestamp of the first scrobble. 2171 + #[serde(default, skip_serializing_if = "Option::is_none")] 2172 + pub timestamp: Option<DateTime<Utc>>, 2173 + } 2174 + 2175 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2176 + pub struct ScrobbleRecord { 2177 + /// The title of the song. 2178 + pub title: String, 2179 + /// The artist of the song. 2180 + pub artist: String, 2181 + /// The artists of the song with MusicBrainz IDs. 2182 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 2183 + pub artists: Vec<ArtistMbid>, 2184 + /// The album artist of the song. 2185 + #[serde(rename = "albumArtist")] 2186 + pub album_artist: String, 2187 + /// The album of the song. 2188 + pub album: String, 2189 + /// The duration of the song in milliseconds. 2190 + pub duration: i64, 2191 + /// The track number of the song in the album. 2192 + #[serde(rename = "trackNumber", default, skip_serializing_if = "Option::is_none")] 2193 + pub track_number: Option<i64>, 2194 + /// The disc number of the song in the album. 2195 + #[serde(rename = "discNumber", default, skip_serializing_if = "Option::is_none")] 2196 + pub disc_number: Option<i64>, 2197 + /// The release date of the song. 2198 + #[serde(rename = "releaseDate", default, skip_serializing_if = "Option::is_none")] 2199 + pub release_date: Option<DateTime<Utc>>, 2200 + /// The year the song was released. 2201 + #[serde(default, skip_serializing_if = "Option::is_none")] 2202 + pub year: Option<i64>, 2203 + /// The genre of the song. 2204 + #[serde(default, skip_serializing_if = "Option::is_none")] 2205 + pub genre: Option<String>, 2206 + /// The tags of the song. 2207 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 2208 + pub tags: Vec<String>, 2209 + /// The composer of the song. 2210 + #[serde(default, skip_serializing_if = "Option::is_none")] 2211 + pub composer: Option<String>, 2212 + /// The lyrics of the song. 2213 + #[serde(default, skip_serializing_if = "Option::is_none")] 2214 + pub lyrics: Option<String>, 2215 + /// The copyright message of the song. 2216 + #[serde(rename = "copyrightMessage", default, skip_serializing_if = "Option::is_none")] 2217 + pub copyright_message: Option<String>, 2218 + /// Informations about the song 2219 + #[serde(default, skip_serializing_if = "Option::is_none")] 2220 + pub wiki: Option<String>, 2221 + /// The album art of the song. 2222 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 2223 + pub album_art: Option<BlobRef>, 2224 + /// The URL of the album art of the song. 2225 + #[serde(rename = "albumArtUrl", default, skip_serializing_if = "Option::is_none")] 2226 + pub album_art_url: Option<String>, 2227 + /// The YouTube link of the song. 2228 + #[serde(rename = "youtubeLink", default, skip_serializing_if = "Option::is_none")] 2229 + pub youtube_link: Option<String>, 2230 + /// The Spotify link of the song. 2231 + #[serde(rename = "spotifyLink", default, skip_serializing_if = "Option::is_none")] 2232 + pub spotify_link: Option<String>, 2233 + /// The Tidal link of the song. 2234 + #[serde(rename = "tidalLink", default, skip_serializing_if = "Option::is_none")] 2235 + pub tidal_link: Option<String>, 2236 + /// The Apple Music link of the song. 2237 + #[serde(rename = "appleMusicLink", default, skip_serializing_if = "Option::is_none")] 2238 + pub apple_music_link: Option<String>, 2239 + /// The date when the song was created. 2240 + #[serde(rename = "createdAt")] 2241 + pub created_at: DateTime<Utc>, 2242 + /// The MusicBrainz ID of the song. 2243 + #[serde(default, skip_serializing_if = "Option::is_none")] 2244 + pub mbid: Option<String>, 2245 + /// The label of the song. 2246 + #[serde(default, skip_serializing_if = "Option::is_none")] 2247 + pub label: Option<String>, 2248 + /// The International Standard Recording Code (ISRC) of the song. 2249 + #[serde(default, skip_serializing_if = "Option::is_none")] 2250 + pub isrc: Option<String>, 2251 + } 2252 + 2253 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2254 + pub struct ScrobbleViewBasic { 2255 + /// The unique identifier of the scrobble. 2256 + #[serde(default, skip_serializing_if = "Option::is_none")] 2257 + pub id: Option<String>, 2258 + /// The handle of the user who created the scrobble. 2259 + #[serde(default, skip_serializing_if = "Option::is_none")] 2260 + pub user: Option<String>, 2261 + /// The display name of the user who created the scrobble. 2262 + #[serde(rename = "userDisplayName", default, skip_serializing_if = "Option::is_none")] 2263 + pub user_display_name: Option<String>, 2264 + /// The avatar URL of the user who created the scrobble. 2265 + #[serde(rename = "userAvatar", default, skip_serializing_if = "Option::is_none")] 2266 + pub user_avatar: Option<String>, 2267 + /// The title of the scrobble. 2268 + #[serde(default, skip_serializing_if = "Option::is_none")] 2269 + pub title: Option<String>, 2270 + /// The artist of the song. 2271 + #[serde(default, skip_serializing_if = "Option::is_none")] 2272 + pub artist: Option<String>, 2273 + /// The URI of the artist. 2274 + #[serde(rename = "artistUri", default, skip_serializing_if = "Option::is_none")] 2275 + pub artist_uri: Option<String>, 2276 + /// The album of the song. 2277 + #[serde(default, skip_serializing_if = "Option::is_none")] 2278 + pub album: Option<String>, 2279 + /// The URI of the album. 2280 + #[serde(rename = "albumUri", default, skip_serializing_if = "Option::is_none")] 2281 + pub album_uri: Option<String>, 2282 + /// The album art URL of the song. 2283 + #[serde(default, skip_serializing_if = "Option::is_none")] 2284 + pub cover: Option<String>, 2285 + /// The timestamp when the scrobble was created. 2286 + #[serde(default, skip_serializing_if = "Option::is_none")] 2287 + pub date: Option<DateTime<Utc>>, 2288 + /// The URI of the scrobble. 2289 + #[serde(default, skip_serializing_if = "Option::is_none")] 2290 + pub uri: Option<String>, 2291 + /// The SHA256 hash of the scrobble data. 2292 + #[serde(default, skip_serializing_if = "Option::is_none")] 2293 + pub sha256: Option<String>, 2294 + #[serde(default, skip_serializing_if = "Option::is_none")] 2295 + pub liked: Option<bool>, 2296 + #[serde(rename = "likesCount", default, skip_serializing_if = "Option::is_none")] 2297 + pub likes_count: Option<i64>, 2298 + } 2299 + 2300 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2301 + pub struct ScrobbleViewDetailed { 2302 + /// The unique identifier of the scrobble. 2303 + #[serde(default, skip_serializing_if = "Option::is_none")] 2304 + pub id: Option<String>, 2305 + /// The handle of the user who created the scrobble. 2306 + #[serde(default, skip_serializing_if = "Option::is_none")] 2307 + pub user: Option<String>, 2308 + /// The title of the scrobble. 2309 + #[serde(default, skip_serializing_if = "Option::is_none")] 2310 + pub title: Option<String>, 2311 + /// The artist of the song. 2312 + #[serde(default, skip_serializing_if = "Option::is_none")] 2313 + pub artist: Option<String>, 2314 + /// The URI of the artist. 2315 + #[serde(rename = "artistUri", default, skip_serializing_if = "Option::is_none")] 2316 + pub artist_uri: Option<String>, 2317 + /// The album of the song. 2318 + #[serde(default, skip_serializing_if = "Option::is_none")] 2319 + pub album: Option<String>, 2320 + /// The URI of the album. 2321 + #[serde(rename = "albumUri", default, skip_serializing_if = "Option::is_none")] 2322 + pub album_uri: Option<String>, 2323 + /// The album art URL of the song. 2324 + #[serde(default, skip_serializing_if = "Option::is_none")] 2325 + pub cover: Option<String>, 2326 + /// The timestamp when the scrobble was created. 2327 + #[serde(default, skip_serializing_if = "Option::is_none")] 2328 + pub date: Option<DateTime<Utc>>, 2329 + /// The URI of the scrobble. 2330 + #[serde(default, skip_serializing_if = "Option::is_none")] 2331 + pub uri: Option<String>, 2332 + /// The SHA256 hash of the scrobble data. 2333 + #[serde(default, skip_serializing_if = "Option::is_none")] 2334 + pub sha256: Option<String>, 2335 + #[serde(default, skip_serializing_if = "Option::is_none")] 2336 + pub liked: Option<bool>, 2337 + #[serde(rename = "likesCount", default, skip_serializing_if = "Option::is_none")] 2338 + pub likes_count: Option<i64>, 2339 + /// The number of listeners 2340 + #[serde(default, skip_serializing_if = "Option::is_none")] 2341 + pub listeners: Option<i64>, 2342 + /// The number of scrobbles for this song 2343 + #[serde(default, skip_serializing_if = "Option::is_none")] 2344 + pub scrobbles: Option<i64>, 2345 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 2346 + pub artists: Vec<ArtistViewBasic>, 2347 + /// The first scrobble of this song on Rocksky. 2348 + #[serde(rename = "firstScrobble", default, skip_serializing_if = "Option::is_none")] 2349 + pub first_scrobble: Option<ScrobbleFirstScrobbleView>, 2350 + } 2351 + 2352 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2353 + pub struct SearchParams { 2354 + /// The search query string 2355 + pub query: String, 2356 + } 2357 + 2358 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2359 + pub struct SeekParams { 2360 + #[serde(rename = "playerId", default, skip_serializing_if = "Option::is_none")] 2361 + pub player_id: Option<String>, 2362 + /// The position in seconds to seek to 2363 + pub position: i64, 2364 + } 2365 + 2366 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2367 + pub struct ShoutAuthor { 2368 + /// The unique identifier of the author. 2369 + #[serde(default, skip_serializing_if = "Option::is_none")] 2370 + pub id: Option<String>, 2371 + /// The decentralized identifier (DID) of the author. 2372 + #[serde(default, skip_serializing_if = "Option::is_none")] 2373 + pub did: Option<String>, 2374 + /// The handle of the author. 2375 + #[serde(default, skip_serializing_if = "Option::is_none")] 2376 + pub handle: Option<String>, 2377 + /// The display name of the author. 2378 + #[serde(rename = "displayName", default, skip_serializing_if = "Option::is_none")] 2379 + pub display_name: Option<String>, 2380 + /// The URL of the author's avatar image. 2381 + #[serde(default, skip_serializing_if = "Option::is_none")] 2382 + pub avatar: Option<String>, 2383 + } 2384 + 2385 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2386 + pub struct ShoutRecord { 2387 + /// The message of the shout. 2388 + pub message: String, 2389 + /// The date when the shout was created. 2390 + #[serde(rename = "createdAt")] 2391 + pub created_at: DateTime<Utc>, 2392 + #[serde(default, skip_serializing_if = "Option::is_none")] 2393 + pub parent: Option<StrongRef>, 2394 + pub subject: StrongRef, 2395 + } 2396 + 2397 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2398 + pub struct ShoutView { 2399 + /// The unique identifier of the shout. 2400 + #[serde(default, skip_serializing_if = "Option::is_none")] 2401 + pub id: Option<String>, 2402 + /// The content of the shout. 2403 + #[serde(default, skip_serializing_if = "Option::is_none")] 2404 + pub message: Option<String>, 2405 + /// The ID of the parent shout if this is a reply, otherwise null. 2406 + #[serde(default, skip_serializing_if = "Option::is_none")] 2407 + pub parent: Option<String>, 2408 + /// The date and time when the shout was created. 2409 + #[serde(rename = "createdAt", default, skip_serializing_if = "Option::is_none")] 2410 + pub created_at: Option<DateTime<Utc>>, 2411 + /// The author of the shout. 2412 + #[serde(default, skip_serializing_if = "Option::is_none")] 2413 + pub author: Option<ShoutAuthor>, 2414 + } 2415 + 2416 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2417 + pub struct SongFirstScrobbleView { 2418 + /// The handle of the user who first scrobbled this song. 2419 + #[serde(default, skip_serializing_if = "Option::is_none")] 2420 + pub handle: Option<String>, 2421 + /// The avatar URL of the user who first scrobbled this song. 2422 + #[serde(default, skip_serializing_if = "Option::is_none")] 2423 + pub avatar: Option<String>, 2424 + /// The timestamp of the first scrobble. 2425 + #[serde(default, skip_serializing_if = "Option::is_none")] 2426 + pub timestamp: Option<DateTime<Utc>>, 2427 + } 2428 + 2429 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2430 + pub struct SongRecentListenerView { 2431 + /// The unique identifier of the listener. 2432 + #[serde(default, skip_serializing_if = "Option::is_none")] 2433 + pub id: Option<String>, 2434 + /// The DID of the listener. 2435 + #[serde(default, skip_serializing_if = "Option::is_none")] 2436 + pub did: Option<String>, 2437 + /// The handle of the listener. 2438 + #[serde(default, skip_serializing_if = "Option::is_none")] 2439 + pub handle: Option<String>, 2440 + /// The display name of the listener. 2441 + #[serde(rename = "displayName", default, skip_serializing_if = "Option::is_none")] 2442 + pub display_name: Option<String>, 2443 + /// The URL of the listener's avatar image. 2444 + #[serde(default, skip_serializing_if = "Option::is_none")] 2445 + pub avatar: Option<String>, 2446 + /// The timestamp of the listener's most recent scrobble of this song. 2447 + #[serde(default, skip_serializing_if = "Option::is_none")] 2448 + pub timestamp: Option<DateTime<Utc>>, 2449 + /// The URI of the listener's most recent scrobble of this song. 2450 + #[serde(rename = "scrobbleUri", default, skip_serializing_if = "Option::is_none")] 2451 + pub scrobble_uri: Option<String>, 2452 + } 2453 + 2454 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2455 + pub struct SongRecord { 2456 + /// The title of the song. 2457 + pub title: String, 2458 + /// The artist of the song. 2459 + pub artist: String, 2460 + /// The artists of the song with MusicBrainz IDs. 2461 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 2462 + pub artists: Vec<ArtistMbid>, 2463 + /// The album artist of the song. 2464 + #[serde(rename = "albumArtist")] 2465 + pub album_artist: String, 2466 + /// The album of the song. 2467 + pub album: String, 2468 + /// The duration of the song in milliseconds. 2469 + pub duration: i64, 2470 + /// The track number of the song in the album. 2471 + #[serde(rename = "trackNumber", default, skip_serializing_if = "Option::is_none")] 2472 + pub track_number: Option<i64>, 2473 + /// The disc number of the song in the album. 2474 + #[serde(rename = "discNumber", default, skip_serializing_if = "Option::is_none")] 2475 + pub disc_number: Option<i64>, 2476 + /// The release date of the song. 2477 + #[serde(rename = "releaseDate", default, skip_serializing_if = "Option::is_none")] 2478 + pub release_date: Option<DateTime<Utc>>, 2479 + /// The year the song was released. 2480 + #[serde(default, skip_serializing_if = "Option::is_none")] 2481 + pub year: Option<i64>, 2482 + /// The genre of the song. 2483 + #[serde(default, skip_serializing_if = "Option::is_none")] 2484 + pub genre: Option<String>, 2485 + /// The tags of the song. 2486 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 2487 + pub tags: Vec<String>, 2488 + /// The composer of the song. 2489 + #[serde(default, skip_serializing_if = "Option::is_none")] 2490 + pub composer: Option<String>, 2491 + /// The lyrics of the song. 2492 + #[serde(default, skip_serializing_if = "Option::is_none")] 2493 + pub lyrics: Option<String>, 2494 + /// The copyright message of the song. 2495 + #[serde(rename = "copyrightMessage", default, skip_serializing_if = "Option::is_none")] 2496 + pub copyright_message: Option<String>, 2497 + /// Informations about the song 2498 + #[serde(default, skip_serializing_if = "Option::is_none")] 2499 + pub wiki: Option<String>, 2500 + /// The album art of the song. 2501 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 2502 + pub album_art: Option<BlobRef>, 2503 + /// The URL of the album art of the song. 2504 + #[serde(rename = "albumArtUrl", default, skip_serializing_if = "Option::is_none")] 2505 + pub album_art_url: Option<String>, 2506 + /// The YouTube link of the song. 2507 + #[serde(rename = "youtubeLink", default, skip_serializing_if = "Option::is_none")] 2508 + pub youtube_link: Option<String>, 2509 + /// The Spotify link of the song. 2510 + #[serde(rename = "spotifyLink", default, skip_serializing_if = "Option::is_none")] 2511 + pub spotify_link: Option<String>, 2512 + /// The Tidal link of the song. 2513 + #[serde(rename = "tidalLink", default, skip_serializing_if = "Option::is_none")] 2514 + pub tidal_link: Option<String>, 2515 + /// The Apple Music link of the song. 2516 + #[serde(rename = "appleMusicLink", default, skip_serializing_if = "Option::is_none")] 2517 + pub apple_music_link: Option<String>, 2518 + /// The date when the song was created. 2519 + #[serde(rename = "createdAt")] 2520 + pub created_at: DateTime<Utc>, 2521 + /// The MusicBrainz ID of the song. 2522 + #[serde(default, skip_serializing_if = "Option::is_none")] 2523 + pub mbid: Option<String>, 2524 + /// The label of the song. 2525 + #[serde(default, skip_serializing_if = "Option::is_none")] 2526 + pub label: Option<String>, 2527 + /// The International Standard Recording Code (ISRC) of the song. 2528 + #[serde(default, skip_serializing_if = "Option::is_none")] 2529 + pub isrc: Option<String>, 2530 + } 2531 + 2532 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2533 + pub struct SongViewBasic { 2534 + /// The unique identifier of the song. 2535 + #[serde(default, skip_serializing_if = "Option::is_none")] 2536 + pub id: Option<String>, 2537 + /// The title of the song. 2538 + #[serde(default, skip_serializing_if = "Option::is_none")] 2539 + pub title: Option<String>, 2540 + /// The artist of the song. 2541 + #[serde(default, skip_serializing_if = "Option::is_none")] 2542 + pub artist: Option<String>, 2543 + /// The artist of the album the song belongs to. 2544 + #[serde(rename = "albumArtist", default, skip_serializing_if = "Option::is_none")] 2545 + pub album_artist: Option<String>, 2546 + /// The URL of the album art image. 2547 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 2548 + pub album_art: Option<String>, 2549 + /// The URI of the song. 2550 + #[serde(default, skip_serializing_if = "Option::is_none")] 2551 + pub uri: Option<String>, 2552 + /// The album of the song. 2553 + #[serde(default, skip_serializing_if = "Option::is_none")] 2554 + pub album: Option<String>, 2555 + /// The duration of the song in milliseconds. 2556 + #[serde(default, skip_serializing_if = "Option::is_none")] 2557 + pub duration: Option<i64>, 2558 + /// The track number of the song in the album. 2559 + #[serde(rename = "trackNumber", default, skip_serializing_if = "Option::is_none")] 2560 + pub track_number: Option<i64>, 2561 + /// The disc number of the song in the album. 2562 + #[serde(rename = "discNumber", default, skip_serializing_if = "Option::is_none")] 2563 + pub disc_number: Option<i64>, 2564 + /// The number of times the song has been played. 2565 + #[serde(rename = "playCount", default, skip_serializing_if = "Option::is_none")] 2566 + pub play_count: Option<i64>, 2567 + /// The number of unique listeners who have played the song. 2568 + #[serde(rename = "uniqueListeners", default, skip_serializing_if = "Option::is_none")] 2569 + pub unique_listeners: Option<i64>, 2570 + /// The URI of the album the song belongs to. 2571 + #[serde(rename = "albumUri", default, skip_serializing_if = "Option::is_none")] 2572 + pub album_uri: Option<String>, 2573 + /// The URI of the artist of the song. 2574 + #[serde(rename = "artistUri", default, skip_serializing_if = "Option::is_none")] 2575 + pub artist_uri: Option<String>, 2576 + /// The SHA256 hash of the song. 2577 + #[serde(default, skip_serializing_if = "Option::is_none")] 2578 + pub sha256: Option<String>, 2579 + /// The MusicBrainz ID of the song. 2580 + #[serde(default, skip_serializing_if = "Option::is_none")] 2581 + pub mbid: Option<String>, 2582 + /// The International Standard Recording Code (ISRC) of the song. 2583 + #[serde(default, skip_serializing_if = "Option::is_none")] 2584 + pub isrc: Option<String>, 2585 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 2586 + pub tags: Vec<String>, 2587 + /// The timestamp when the song was created. 2588 + #[serde(rename = "createdAt", default, skip_serializing_if = "Option::is_none")] 2589 + pub created_at: Option<DateTime<Utc>>, 2590 + } 2591 + 2592 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2593 + pub struct SongViewDetailed { 2594 + /// The unique identifier of the song. 2595 + #[serde(default, skip_serializing_if = "Option::is_none")] 2596 + pub id: Option<String>, 2597 + /// The title of the song. 2598 + #[serde(default, skip_serializing_if = "Option::is_none")] 2599 + pub title: Option<String>, 2600 + /// The artist of the song. 2601 + #[serde(default, skip_serializing_if = "Option::is_none")] 2602 + pub artist: Option<String>, 2603 + /// The artist of the album the song belongs to. 2604 + #[serde(rename = "albumArtist", default, skip_serializing_if = "Option::is_none")] 2605 + pub album_artist: Option<String>, 2606 + /// The URL of the album art image. 2607 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 2608 + pub album_art: Option<String>, 2609 + /// The URI of the song. 2610 + #[serde(default, skip_serializing_if = "Option::is_none")] 2611 + pub uri: Option<String>, 2612 + /// The album of the song. 2613 + #[serde(default, skip_serializing_if = "Option::is_none")] 2614 + pub album: Option<String>, 2615 + /// The duration of the song in milliseconds. 2616 + #[serde(default, skip_serializing_if = "Option::is_none")] 2617 + pub duration: Option<i64>, 2618 + /// The track number of the song in the album. 2619 + #[serde(rename = "trackNumber", default, skip_serializing_if = "Option::is_none")] 2620 + pub track_number: Option<i64>, 2621 + /// The disc number of the song in the album. 2622 + #[serde(rename = "discNumber", default, skip_serializing_if = "Option::is_none")] 2623 + pub disc_number: Option<i64>, 2624 + /// The number of times the song has been played. 2625 + #[serde(rename = "playCount", default, skip_serializing_if = "Option::is_none")] 2626 + pub play_count: Option<i64>, 2627 + /// The number of unique listeners who have played the song. 2628 + #[serde(rename = "uniqueListeners", default, skip_serializing_if = "Option::is_none")] 2629 + pub unique_listeners: Option<i64>, 2630 + /// The URI of the album the song belongs to. 2631 + #[serde(rename = "albumUri", default, skip_serializing_if = "Option::is_none")] 2632 + pub album_uri: Option<String>, 2633 + /// The URI of the artist of the song. 2634 + #[serde(rename = "artistUri", default, skip_serializing_if = "Option::is_none")] 2635 + pub artist_uri: Option<String>, 2636 + /// The SHA256 hash of the song. 2637 + #[serde(default, skip_serializing_if = "Option::is_none")] 2638 + pub sha256: Option<String>, 2639 + /// The MusicBrainz ID of the song. 2640 + #[serde(default, skip_serializing_if = "Option::is_none")] 2641 + pub mbid: Option<String>, 2642 + /// The International Standard Recording Code (ISRC) of the song. 2643 + #[serde(default, skip_serializing_if = "Option::is_none")] 2644 + pub isrc: Option<String>, 2645 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 2646 + pub tags: Vec<String>, 2647 + /// The timestamp when the song was created. 2648 + #[serde(rename = "createdAt", default, skip_serializing_if = "Option::is_none")] 2649 + pub created_at: Option<DateTime<Utc>>, 2650 + #[serde(default, skip_serializing_if = "Vec::is_empty")] 2651 + pub artists: Vec<ArtistViewBasic>, 2652 + /// The first scrobble of this song on Rocksky. 2653 + #[serde(rename = "firstScrobble", default, skip_serializing_if = "Option::is_none")] 2654 + pub first_scrobble: Option<SongFirstScrobbleView>, 2655 + } 2656 + 2657 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2658 + pub struct SpotifyTrackView { 2659 + /// The unique identifier of the Spotify track. 2660 + #[serde(default, skip_serializing_if = "Option::is_none")] 2661 + pub id: Option<String>, 2662 + /// The name of the track. 2663 + #[serde(default, skip_serializing_if = "Option::is_none")] 2664 + pub name: Option<String>, 2665 + /// The name of the artist. 2666 + #[serde(default, skip_serializing_if = "Option::is_none")] 2667 + pub artist: Option<String>, 2668 + /// The name of the album. 2669 + #[serde(default, skip_serializing_if = "Option::is_none")] 2670 + pub album: Option<String>, 2671 + /// The duration of the track in milliseconds. 2672 + #[serde(default, skip_serializing_if = "Option::is_none")] 2673 + pub duration: Option<i64>, 2674 + /// A URL to a preview of the track. 2675 + #[serde(rename = "previewUrl", default, skip_serializing_if = "Option::is_none")] 2676 + pub preview_url: Option<String>, 2677 + } 2678 + 2679 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2680 + pub struct StartPlaylistParams { 2681 + /// The URI of the playlist to start 2682 + pub uri: String, 2683 + /// Whether to shuffle the playlist when starting it 2684 + #[serde(default, skip_serializing_if = "Option::is_none")] 2685 + pub shuffle: Option<bool>, 2686 + /// The position in the playlist to start from, if not specified, starts from the beginning 2687 + #[serde(default, skip_serializing_if = "Option::is_none")] 2688 + pub position: Option<i64>, 2689 + } 2690 + 2691 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2692 + pub struct StatsView { 2693 + /// The total number of scrobbles. 2694 + #[serde(default, skip_serializing_if = "Option::is_none")] 2695 + pub scrobbles: Option<i64>, 2696 + /// The total number of unique artists scrobbled. 2697 + #[serde(default, skip_serializing_if = "Option::is_none")] 2698 + pub artists: Option<i64>, 2699 + /// The total number of tracks marked as loved. 2700 + #[serde(rename = "lovedTracks", default, skip_serializing_if = "Option::is_none")] 2701 + pub loved_tracks: Option<i64>, 2702 + /// The total number of unique albums scrobbled. 2703 + #[serde(default, skip_serializing_if = "Option::is_none")] 2704 + pub albums: Option<i64>, 2705 + /// The total number of unique tracks scrobbled. 2706 + #[serde(default, skip_serializing_if = "Option::is_none")] 2707 + pub tracks: Option<i64>, 2708 + } 2709 + 2710 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2711 + pub struct StatsWrappedAlbum { 2712 + /// The unique identifier of the album. 2713 + #[serde(default, skip_serializing_if = "Option::is_none")] 2714 + pub id: Option<String>, 2715 + /// The title of the album. 2716 + #[serde(default, skip_serializing_if = "Option::is_none")] 2717 + pub title: Option<String>, 2718 + /// The artist of the album. 2719 + #[serde(default, skip_serializing_if = "Option::is_none")] 2720 + pub artist: Option<String>, 2721 + /// The album art URL. 2722 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 2723 + pub album_art: Option<String>, 2724 + /// The AT-URI of the album. 2725 + #[serde(default, skip_serializing_if = "Option::is_none")] 2726 + pub uri: Option<String>, 2727 + /// Number of plays in the wrapped period. 2728 + #[serde(rename = "playCount", default, skip_serializing_if = "Option::is_none")] 2729 + pub play_count: Option<i64>, 2730 + } 2731 + 2732 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2733 + pub struct StatsWrappedArtist { 2734 + /// The unique identifier of the artist. 2735 + #[serde(default, skip_serializing_if = "Option::is_none")] 2736 + pub id: Option<String>, 2737 + /// The name of the artist. 2738 + #[serde(default, skip_serializing_if = "Option::is_none")] 2739 + pub name: Option<String>, 2740 + /// The picture URL of the artist. 2741 + #[serde(default, skip_serializing_if = "Option::is_none")] 2742 + pub picture: Option<String>, 2743 + /// The AT-URI of the artist. 2744 + #[serde(default, skip_serializing_if = "Option::is_none")] 2745 + pub uri: Option<String>, 2746 + /// Number of plays in the wrapped period. 2747 + #[serde(rename = "playCount", default, skip_serializing_if = "Option::is_none")] 2748 + pub play_count: Option<i64>, 2749 + } 2750 + 2751 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2752 + pub struct StatsWrappedDayCount { 2753 + /// The date (YYYY-MM-DD). 2754 + #[serde(default, skip_serializing_if = "Option::is_none")] 2755 + pub date: Option<String>, 2756 + /// Number of scrobbles on this day. 2757 + #[serde(default, skip_serializing_if = "Option::is_none")] 2758 + pub count: Option<i64>, 2759 + } 2760 + 2761 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2762 + pub struct StatsWrappedGenreCount { 2763 + /// The genre name. 2764 + #[serde(default, skip_serializing_if = "Option::is_none")] 2765 + pub genre: Option<String>, 2766 + /// Number of scrobbles for this genre. 2767 + #[serde(default, skip_serializing_if = "Option::is_none")] 2768 + pub count: Option<i64>, 2769 + } 2770 + 2771 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2772 + pub struct StatsWrappedMilestone { 2773 + /// The title of the track. 2774 + #[serde(rename = "trackTitle", default, skip_serializing_if = "Option::is_none")] 2775 + pub track_title: Option<String>, 2776 + /// The name of the artist. 2777 + #[serde(rename = "artistName", default, skip_serializing_if = "Option::is_none")] 2778 + pub artist_name: Option<String>, 2779 + /// The timestamp of the scrobble. 2780 + #[serde(default, skip_serializing_if = "Option::is_none")] 2781 + pub timestamp: Option<DateTime<Utc>>, 2782 + /// AT-URI of the track record, used to build a clickable link to the song page. 2783 + #[serde(rename = "trackUri", default, skip_serializing_if = "Option::is_none")] 2784 + pub track_uri: Option<String>, 2785 + } 2786 + 2787 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2788 + pub struct StatsWrappedMonthCount { 2789 + /// Month number (1-12). 2790 + #[serde(default, skip_serializing_if = "Option::is_none")] 2791 + pub month: Option<i64>, 2792 + /// Number of scrobbles in this month. 2793 + #[serde(default, skip_serializing_if = "Option::is_none")] 2794 + pub count: Option<i64>, 2795 + } 2796 + 2797 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2798 + pub struct StatsWrappedTrack { 2799 + /// The unique identifier of the track. 2800 + #[serde(default, skip_serializing_if = "Option::is_none")] 2801 + pub id: Option<String>, 2802 + /// The title of the track. 2803 + #[serde(default, skip_serializing_if = "Option::is_none")] 2804 + pub title: Option<String>, 2805 + /// The artist of the track. 2806 + #[serde(default, skip_serializing_if = "Option::is_none")] 2807 + pub artist: Option<String>, 2808 + /// The album art URL. 2809 + #[serde(rename = "albumArt", default, skip_serializing_if = "Option::is_none")] 2810 + pub album_art: Option<String>, 2811 + /// The AT-URI of the track. 2812 + #[serde(default, skip_serializing_if = "Option::is_none")] 2813 + pub uri: Option<String>, 2814 + /// The AT-URI of the artist. 2815 + #[serde(rename = "artistUri", default, skip_serializing_if = "Option::is_none")] 2816 + pub artist_uri: Option<String>, 2817 + /// The AT-URI of the album. 2818 + #[serde(rename = "albumUri", default, skip_serializing_if = "Option::is_none")] 2819 + pub album_uri: Option<String>, 2820 + /// Number of plays in the wrapped period. 2821 + #[serde(rename = "playCount", default, skip_serializing_if = "Option::is_none")] 2822 + pub play_count: Option<i64>, 2823 + } 2824 + 2825 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2826 + pub struct StatsWrappedView { 2827 + /// The year of the wrapped stats. 2828 + #[serde(default, skip_serializing_if = "Option::is_none")] 2829 + pub year: Option<i64>, 2830 + /// Total scrobbles in the year. 2831 + #[serde(rename = "totalScrobbles", default, skip_serializing_if = "Option::is_none")] 2832 + pub total_scrobbles: Option<i64>, 2833 + /// Total listening time in minutes. 2834 + #[serde(rename = "totalListeningTimeMinutes", default, skip_serializing_if = "Option::is_none")] 2835 + pub total_listening_time_minutes: Option<i64>, 2836 + /// Top 5 artists by play count. 2837 + #[serde(rename = "topArtists", default, skip_serializing_if = "Vec::is_empty")] 2838 + pub top_artists: Vec<StatsWrappedArtist>, 2839 + /// Top 5 tracks by play count. 2840 + #[serde(rename = "topTracks", default, skip_serializing_if = "Vec::is_empty")] 2841 + pub top_tracks: Vec<StatsWrappedTrack>, 2842 + /// Top 5 albums by play count. 2843 + #[serde(rename = "topAlbums", default, skip_serializing_if = "Vec::is_empty")] 2844 + pub top_albums: Vec<StatsWrappedAlbum>, 2845 + /// Top genres by play count. 2846 + #[serde(rename = "topGenres", default, skip_serializing_if = "Vec::is_empty")] 2847 + pub top_genres: Vec<StatsWrappedGenreCount>, 2848 + /// Scrobble counts per month. 2849 + #[serde(rename = "scrobblesPerMonth", default, skip_serializing_if = "Vec::is_empty")] 2850 + pub scrobbles_per_month: Vec<StatsWrappedMonthCount>, 2851 + /// The most active day of the year. 2852 + #[serde(rename = "mostActiveDay", default, skip_serializing_if = "Option::is_none")] 2853 + pub most_active_day: Option<StatsWrappedDayCount>, 2854 + /// The most active hour of the day (0-23). 2855 + #[serde(rename = "mostActiveHour", default, skip_serializing_if = "Option::is_none")] 2856 + pub most_active_hour: Option<i64>, 2857 + /// Number of artists heard for the first time this year. 2858 + #[serde(rename = "newArtistsCount", default, skip_serializing_if = "Option::is_none")] 2859 + pub new_artists_count: Option<i64>, 2860 + /// Longest consecutive days streak. 2861 + #[serde(rename = "longestStreak", default, skip_serializing_if = "Option::is_none")] 2862 + pub longest_streak: Option<i64>, 2863 + /// The first scrobble of the year. 2864 + #[serde(rename = "firstScrobble", default, skip_serializing_if = "Option::is_none")] 2865 + pub first_scrobble: Option<StatsWrappedMilestone>, 2866 + /// The last scrobble of the year. 2867 + #[serde(rename = "lastScrobble", default, skip_serializing_if = "Option::is_none")] 2868 + pub last_scrobble: Option<StatsWrappedMilestone>, 2869 + } 2870 + 2871 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2872 + pub struct StatusRecord { 2873 + /// The track currently being played. 2874 + pub track: ActorTrackView, 2875 + /// When the track started playing. 2876 + #[serde(rename = "startedAt")] 2877 + pub started_at: DateTime<Utc>, 2878 + /// When the status expires. Defaults to startedAt plus track duration plus idle time. 2879 + #[serde(rename = "expiresAt", default, skip_serializing_if = "Option::is_none")] 2880 + pub expires_at: Option<DateTime<Utc>>, 2881 + } 2882 + 2883 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2884 + pub struct StrongRef { 2885 + pub uri: String, 2886 + pub cid: String, 2887 + } 2888 + 2889 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2890 + pub struct UnfollowAccountOutput { 2891 + pub subject: ActorProfileViewBasic, 2892 + pub followers: Vec<ActorProfileViewBasic>, 2893 + /// A cursor value to pass to subsequent calls to get the next page of results. 2894 + #[serde(default, skip_serializing_if = "Option::is_none")] 2895 + pub cursor: Option<String>, 2896 + } 2897 + 2898 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2899 + pub struct UnfollowAccountParams { 2900 + pub account: String, 2901 + } 2902 + 2903 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 2904 + pub struct UpdateApikeyInput { 2905 + /// The ID of the API key to update. 2906 + pub id: String, 2907 + /// The new name of the API key. 2908 + pub name: String, 2909 + /// A new description for the API key. 2910 + #[serde(default, skip_serializing_if = "Option::is_none")] 2911 + pub description: Option<String>, 2912 + }
+1
sdk/rust/src/lib.rs
··· 48 48 49 49 pub mod client; 50 50 pub mod error; 51 + pub mod generated; 51 52 pub mod http; 52 53 pub mod models; 53 54 pub mod resources;
+37 -392
sdk/rust/src/models.rs
··· 1 1 //! Strongly typed response models. 2 2 //! 3 - //! The Rocksky API speaks camelCase JSON; every model is annotated with 4 - //! `#[serde(rename_all = "camelCase")]` and accepts unknown fields silently 5 - //! (so adding new fields server-side won't break compiled SDK consumers). 6 - //! 7 - //! Every field is `Option<…>` — the API is generous about returning partial 8 - //! shapes (e.g. an empty `{}` for an unknown handle). 3 + //! Lex-derived shapes live in `crate::generated`. This module re-exports them 4 + //! under the historical SDK names and extends a few with fields the lexicon 5 + //! does not yet declare. List-endpoint envelopes are SDK-internal and stay 6 + //! hand-written. 9 7 10 8 use chrono::{DateTime, Utc}; 11 9 use serde::{Deserialize, Serialize}; 12 10 use serde_json::Value; 13 11 14 - /// Trim trailing/leading whitespace on string fields without forcing callers 15 - /// to think about it. 16 - fn trim_string<'de, D>(de: D) -> Result<Option<String>, D::Error> 17 - where 18 - D: serde::Deserializer<'de>, 19 - { 20 - let raw: Option<String> = Option::deserialize(de)?; 21 - Ok(raw.map(|s| s.trim().to_string())) 22 - } 23 - 24 - // --- Actor ---------------------------------------------------------------- 12 + pub use crate::generated::{ 13 + ActorCompatibilityViewBasic as Compatibility, 14 + ActorNeighbourViewBasic as Neighbour, 15 + ActorProfileViewBasic as ProfileBasic, 16 + AlbumViewBasic as AlbumBasic, 17 + AlbumViewDetailed as Album, 18 + ArtistListenerViewBasic as ArtistListener, 19 + ArtistViewBasic as ArtistBasic, 20 + FeedGeneratorView as FeedGenerator, 21 + FeedItemView as FeedItem, 22 + FeedRecommendationsView as Recommendations, 23 + FeedRecommendationView as Recommendation, 24 + FeedRecommendedAlbumView as RecommendedAlbum, 25 + FeedRecommendedArtistView as RecommendedArtist, 26 + FeedSearchResultsView as SearchResults, 27 + FeedStoryView as Story, 28 + FeedView as Feed, 29 + MirrorSourceView as MirrorSource, 30 + PlaylistViewBasic as PlaylistBasic, 31 + PlaylistViewDetailed as Playlist, 32 + ScrobbleViewDetailed as Scrobble, 33 + ShoutAuthor, ShoutView as Shout, 34 + SongFirstScrobbleView as FirstScrobble, 35 + SongRecentListenerView as RecentListener, 36 + SongViewBasic as SongBasic, 37 + SongViewDetailed as Song, 38 + }; 25 39 26 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 27 - #[serde(rename_all = "camelCase")] 28 - pub struct ProfileBasic { 29 - pub id: Option<String>, 30 - pub did: Option<String>, 31 - pub handle: Option<String>, 32 - #[serde(default, deserialize_with = "trim_string")] 33 - pub display_name: Option<String>, 34 - pub avatar: Option<String>, 35 - pub created_at: Option<DateTime<Utc>>, 36 - pub updated_at: Option<DateTime<Utc>>, 37 - } 40 + pub type Artist = ArtistBasic; 38 41 39 42 #[derive(Debug, Clone, Default, Serialize, Deserialize)] 40 43 #[serde(rename_all = "camelCase")] ··· 55 58 } 56 59 } 57 60 58 - // --- Artist --------------------------------------------------------------- 59 - 60 61 #[derive(Debug, Clone, Default, Serialize, Deserialize)] 61 62 #[serde(rename_all = "camelCase")] 62 - pub struct ArtistBasic { 63 - pub id: Option<String>, 64 - pub uri: Option<String>, 65 - pub name: Option<String>, 66 - pub picture: Option<String>, 67 - pub sha256: Option<String>, 68 - pub play_count: Option<u64>, 69 - pub unique_listeners: Option<u64>, 70 - pub tags: Option<Vec<String>>, 71 - } 72 - 73 - pub type Artist = ArtistBasic; 74 - 75 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 76 - #[serde(rename_all = "camelCase")] 77 - pub struct ArtistListener { 78 - pub id: Option<String>, 79 - pub did: Option<String>, 80 - pub handle: Option<String>, 81 - pub display_name: Option<String>, 82 - pub avatar: Option<String>, 83 - pub most_listened_song: Option<Value>, 84 - pub total_plays: Option<u64>, 85 - pub rank: Option<u32>, 86 - } 87 - 88 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 89 - #[serde(rename_all = "camelCase")] 90 - pub struct RecentListener { 91 - pub id: Option<String>, 92 - pub did: Option<String>, 93 - pub handle: Option<String>, 94 - pub display_name: Option<String>, 95 - pub avatar: Option<String>, 96 - pub timestamp: Option<DateTime<Utc>>, 97 - pub scrobble_uri: Option<String>, 98 - } 99 - 100 - // --- Album ---------------------------------------------------------------- 101 - 102 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 103 - #[serde(rename_all = "camelCase")] 104 - pub struct AlbumBasic { 105 - pub id: Option<String>, 106 - pub uri: Option<String>, 107 - pub title: Option<String>, 108 - pub artist: Option<String>, 109 - pub artist_uri: Option<String>, 110 - pub year: Option<i32>, 111 - pub album_art: Option<String>, 112 - pub release_date: Option<String>, 113 - pub sha256: Option<String>, 114 - pub play_count: Option<u64>, 115 - pub unique_listeners: Option<u64>, 116 - } 117 - 118 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 119 - #[serde(rename_all = "camelCase")] 120 - pub struct Album { 63 + pub struct ApiKey { 121 64 #[serde(flatten)] 122 - pub basic: AlbumBasic, 123 - pub tags: Option<Vec<String>>, 124 - pub tracks: Option<Vec<SongBasic>>, 125 - } 126 - 127 - impl std::ops::Deref for Album { 128 - type Target = AlbumBasic; 129 - fn deref(&self) -> &Self::Target { 130 - &self.basic 131 - } 132 - } 133 - 134 - // --- Song ----------------------------------------------------------------- 135 - 136 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 137 - #[serde(rename_all = "camelCase")] 138 - pub struct FirstScrobble { 139 - pub handle: Option<String>, 140 - pub avatar: Option<String>, 141 - pub timestamp: Option<DateTime<Utc>>, 142 - } 143 - 144 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 145 - #[serde(rename_all = "camelCase")] 146 - pub struct SongBasic { 147 - pub id: Option<String>, 148 - pub title: Option<String>, 149 - pub artist: Option<String>, 150 - pub album_artist: Option<String>, 151 - pub album_art: Option<String>, 152 - pub uri: Option<String>, 153 - pub album: Option<String>, 154 - pub duration: Option<u64>, 155 - pub track_number: Option<u32>, 156 - pub disc_number: Option<u32>, 157 - pub play_count: Option<u64>, 158 - pub unique_listeners: Option<u64>, 159 - pub album_uri: Option<String>, 160 - pub artist_uri: Option<String>, 161 - pub sha256: Option<String>, 162 - pub mbid: Option<String>, 163 - pub isrc: Option<String>, 164 - pub tags: Option<Vec<String>>, 165 - pub created_at: Option<DateTime<Utc>>, 166 - } 167 - 168 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 169 - #[serde(rename_all = "camelCase")] 170 - pub struct Song { 171 - #[serde(flatten)] 172 - pub basic: SongBasic, 173 - pub artists: Option<Vec<ArtistBasic>>, 174 - pub first_scrobble: Option<FirstScrobble>, 175 - } 176 - 177 - impl std::ops::Deref for Song { 178 - type Target = SongBasic; 179 - fn deref(&self) -> &Self::Target { 180 - &self.basic 181 - } 182 - } 183 - 184 - // --- Scrobble ------------------------------------------------------------- 185 - 186 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 187 - #[serde(rename_all = "camelCase")] 188 - pub struct Scrobble { 189 - pub id: Option<String>, 190 - pub user: Option<String>, 191 - pub user_display_name: Option<String>, 192 - pub user_avatar: Option<String>, 193 - pub title: Option<String>, 194 - pub artist: Option<String>, 195 - pub artist_uri: Option<String>, 196 - pub album: Option<String>, 197 - pub album_uri: Option<String>, 198 - pub cover: Option<String>, 199 - pub date: Option<DateTime<Utc>>, 200 - pub uri: Option<String>, 201 - pub sha256: Option<String>, 202 - pub liked: Option<bool>, 203 - pub likes_count: Option<u32>, 204 - pub listeners: Option<u64>, 205 - pub scrobbles: Option<u64>, 206 - pub artists: Option<Vec<ArtistBasic>>, 207 - pub first_scrobble: Option<FirstScrobble>, 208 - } 209 - 210 - // --- Shouts --------------------------------------------------------------- 211 - 212 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 213 - #[serde(rename_all = "camelCase")] 214 - pub struct ShoutAuthor { 215 - pub id: Option<String>, 216 - pub did: Option<String>, 217 - pub handle: Option<String>, 218 - pub display_name: Option<String>, 219 - pub avatar: Option<String>, 220 - } 221 - 222 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 223 - #[serde(rename_all = "camelCase")] 224 - pub struct Shout { 225 - pub id: Option<String>, 226 - pub message: Option<String>, 227 - pub parent: Option<String>, 228 - pub created_at: Option<DateTime<Utc>>, 229 - pub author: Option<ShoutAuthor>, 230 - } 231 - 232 - // --- API keys ------------------------------------------------------------- 233 - 234 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 235 - #[serde(rename_all = "camelCase")] 236 - pub struct ApiKey { 237 - pub id: Option<String>, 238 - pub name: Option<String>, 239 - pub description: Option<String>, 65 + pub base: crate::generated::ApiKeyView, 240 66 pub enabled: Option<bool>, 241 67 pub api_key: Option<String>, 242 68 pub shared_secret: Option<String>, 243 - pub created_at: Option<DateTime<Utc>>, 244 69 pub updated_at: Option<DateTime<Utc>>, 245 70 } 246 71 247 - // --- Playlist ------------------------------------------------------------- 248 - 249 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 250 - #[serde(rename_all = "camelCase")] 251 - pub struct PlaylistBasic { 252 - pub id: Option<String>, 253 - pub title: Option<String>, 254 - pub uri: Option<String>, 255 - pub curator_did: Option<String>, 256 - pub curator_handle: Option<String>, 257 - pub curator_name: Option<String>, 258 - pub curator_avatar_url: Option<String>, 259 - pub description: Option<String>, 260 - pub cover_image_url: Option<String>, 261 - pub created_at: Option<DateTime<Utc>>, 262 - pub track_count: Option<u32>, 263 - } 264 - 265 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 266 - #[serde(rename_all = "camelCase")] 267 - pub struct Playlist { 268 - #[serde(flatten)] 269 - pub basic: PlaylistBasic, 270 - pub tracks: Option<Vec<SongBasic>>, 271 - } 272 - 273 - impl std::ops::Deref for Playlist { 274 - type Target = PlaylistBasic; 72 + impl std::ops::Deref for ApiKey { 73 + type Target = crate::generated::ApiKeyView; 275 74 fn deref(&self) -> &Self::Target { 276 - &self.basic 75 + &self.base 277 76 } 278 77 } 279 78 280 - // --- Feed ----------------------------------------------------------------- 281 - 282 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 283 - #[serde(rename_all = "camelCase")] 284 - pub struct FeedGenerator { 285 - pub id: Option<String>, 286 - pub name: Option<String>, 287 - pub description: Option<String>, 288 - pub uri: Option<String>, 289 - pub avatar: Option<String>, 290 - pub creator: Option<ProfileBasic>, 291 - } 292 - 293 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 294 - #[serde(rename_all = "camelCase")] 295 - pub struct FeedItem { 296 - pub scrobble: Option<Scrobble>, 297 - } 298 - 299 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 300 - #[serde(rename_all = "camelCase")] 301 - pub struct Feed { 302 - #[serde(default)] 303 - pub feed: Vec<FeedItem>, 304 - pub cursor: Option<String>, 305 - } 306 - 307 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 308 - #[serde(rename_all = "camelCase")] 309 - pub struct Story { 310 - pub id: Option<String>, 311 - pub did: Option<String>, 312 - pub handle: Option<String>, 313 - pub avatar: Option<String>, 314 - pub title: Option<String>, 315 - pub artist: Option<String>, 316 - pub artist_uri: Option<String>, 317 - pub album: Option<String>, 318 - pub album_uri: Option<String>, 319 - pub album_artist: Option<String>, 320 - pub album_art: Option<String>, 321 - pub created_at: Option<String>, 322 - pub track_id: Option<String>, 323 - pub track_uri: Option<String>, 324 - pub uri: Option<String>, 325 - } 326 - 327 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 328 - #[serde(rename_all = "camelCase")] 329 - pub struct Recommendation { 330 - pub title: Option<String>, 331 - pub artist: Option<String>, 332 - pub album: Option<String>, 333 - pub album_art: Option<String>, 334 - pub track_uri: Option<String>, 335 - pub artist_uri: Option<String>, 336 - pub album_uri: Option<String>, 337 - pub genres: Option<Vec<String>>, 338 - pub recommendation_score: Option<i32>, 339 - pub source: Option<String>, 340 - pub likes_count: Option<u32>, 341 - } 342 - 343 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 344 - #[serde(rename_all = "camelCase")] 345 - pub struct Recommendations { 346 - #[serde(default)] 347 - pub recommendations: Vec<Recommendation>, 348 - pub cursor: Option<String>, 349 - } 350 - 351 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 352 - #[serde(rename_all = "camelCase")] 353 - pub struct RecommendedArtist { 354 - pub id: Option<String>, 355 - pub uri: Option<String>, 356 - pub name: Option<String>, 357 - pub picture: Option<String>, 358 - pub genres: Option<Vec<String>>, 359 - pub recommendation_score: Option<i32>, 360 - pub source: Option<String>, 361 - } 362 - 363 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 364 - #[serde(rename_all = "camelCase")] 365 - pub struct RecommendedAlbum { 366 - pub id: Option<String>, 367 - pub uri: Option<String>, 368 - pub title: Option<String>, 369 - pub artist: Option<String>, 370 - pub artist_uri: Option<String>, 371 - pub year: Option<i32>, 372 - pub album_art: Option<String>, 373 - pub recommendation_score: Option<i32>, 374 - pub source: Option<String>, 375 - } 376 - 377 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 378 - #[serde(rename_all = "camelCase")] 379 - pub struct SearchResults { 380 - /// Heterogeneous hits — items may be songs, albums, artists, playlists, profiles. 381 - #[serde(default)] 382 - pub hits: Vec<Value>, 383 - pub processing_time_ms: Option<u64>, 384 - pub limit: Option<u32>, 385 - pub offset: Option<u32>, 386 - pub estimated_total_hits: Option<u64>, 387 - } 388 - 389 - // --- Actor compatibility / neighbours ------------------------------------- 390 - 391 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 392 - #[serde(rename_all = "camelCase")] 393 - pub struct Compatibility { 394 - pub compatibility_level: Option<i32>, 395 - pub compatibility_percentage: Option<i32>, 396 - pub shared_artists: Option<u32>, 397 - pub top_shared_artist_names: Option<Vec<String>>, 398 - pub top_shared_detailed_artists: Option<Vec<ArtistBasic>>, 399 - pub user1_artist_count: Option<u32>, 400 - pub user2_artist_count: Option<u32>, 401 - } 402 - 403 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 404 - #[serde(rename_all = "camelCase")] 405 - pub struct Neighbour { 406 - pub user_id: Option<String>, 407 - pub did: Option<String>, 408 - pub handle: Option<String>, 409 - pub display_name: Option<String>, 410 - pub avatar: Option<String>, 411 - pub shared_artists_count: Option<u32>, 412 - pub similarity_score: Option<i32>, 413 - pub top_shared_artist_names: Option<Vec<String>>, 414 - pub top_shared_artists_details: Option<Vec<ArtistBasic>>, 415 - } 416 - 417 - // --- Mirror --------------------------------------------------------------- 418 - 419 - #[derive(Debug, Clone, Default, Serialize, Deserialize)] 420 - #[serde(rename_all = "camelCase")] 421 - pub struct MirrorSource { 422 - pub id: Option<String>, 423 - pub kind: Option<String>, 424 - pub enabled: Option<bool>, 425 - pub config: Option<Value>, 426 - pub created_at: Option<DateTime<Utc>>, 427 - pub updated_at: Option<DateTime<Utc>>, 428 - } 429 - 430 79 // --- Containers used by list endpoints ------------------------------------ 431 - // 432 - // Several list endpoints wrap their payload in a typed key. We provide the 433 - // wrapper types so callers can read `result.scrobbles` directly without 434 - // hand-rolling envelope shapes. 435 80 436 81 #[derive(Debug, Clone, Default, Serialize, Deserialize)] 437 82 #[serde(rename_all = "camelCase")]
+3 -4
sdk/rust/tests/models.rs
··· 32 32 .unwrap(); 33 33 assert_eq!(a.title.as_deref(), Some("Hounds of Love")); 34 34 assert_eq!(a.year, Some(1985)); 35 - let tracks = a.tracks.expect("tracks"); 36 - assert_eq!(tracks.len(), 1); 37 - assert_eq!(tracks[0].title.as_deref(), Some("Running Up That Hill")); 38 - assert_eq!(a.tags.unwrap()[1], "art rock"); 35 + assert_eq!(a.tracks.len(), 1); 36 + assert_eq!(a.tracks[0].title.as_deref(), Some("Running Up That Hill")); 37 + assert_eq!(a.tags[1], "art rock"); 39 38 } 40 39 41 40 #[test]
+2 -2
sdk/rust/tests/scrobble.rs
··· 63 63 64 64 let s = client.scrobble().get("at://scrobble1").await.unwrap(); 65 65 assert_eq!(s.scrobbles, Some(12)); 66 - let artists = s.artists.expect("artists missing"); 67 - assert_eq!(artists[0].name.as_deref(), Some("Avril Lavigne")); 66 + assert!(!s.artists.is_empty(), "artists missing"); 67 + assert_eq!(s.artists[0].name.as_deref(), Some("Avril Lavigne")); 68 68 } 69 69 70 70 #[tokio::test]
+5
sdk/typescript/README.md
··· 255 255 256 256 For tests, pass a fake `WebSocket` constructor via `.webSocket(FakeWebSocket)`. 257 257 258 + ## Types 259 + 260 + Public model types are derived from the [Rocksky lexicons](https://tangled.org/rocksky.app/rocksky/tree/main/apps/api/lexicons) and live in `src/generated/types.ts`. They are regenerated from `apps/api/lexicons/**/*.json` by running `bun run lexgen:types` at the repo root. 261 + 262 + 258 263 ## Development 259 264 260 265 ```bash
+1 -1
sdk/typescript/package.json
··· 1 1 { 2 2 "name": "@rocksky/sdk", 3 - "version": "0.1.0", 3 + "version": "0.2.0", 4 4 "description": "TypeScript SDK for the Rocksky XRPC API", 5 5 "license": "MIT", 6 6 "repository": {
+2019
sdk/typescript/src/generated/types.ts
··· 1 + // AUTO-GENERATED FILE — DO NOT EDIT. 2 + // Source: apps/api/lexicons/**/*.json 3 + // Regenerate via: bun run lexgen:types 4 + 5 + export interface BlobRef { 6 + $type?: "blob"; 7 + ref?: { $link?: string }; 8 + mimeType?: string; 9 + size?: number; 10 + } 11 + 12 + export type CidLink = string; 13 + export type DateTime = string; 14 + export type AtUri = string; 15 + export type AtIdentifier = string; 16 + export type Did = string; 17 + export type Cid = string; 18 + export type Uri = string; 19 + 20 + export interface ActorArtistViewBasic { 21 + id?: string; 22 + name?: string; 23 + picture?: Uri; 24 + uri?: AtUri; 25 + user1Rank?: number; 26 + user2Rank?: number; 27 + weight?: number; 28 + } 29 + 30 + export interface ActorCompatibilityViewBasic { 31 + compatibilityLevel?: number; 32 + compatibilityPercentage?: number; 33 + sharedArtists?: number; 34 + topSharedArtistNames?: string[]; 35 + topSharedDetailedArtists?: ActorArtistViewBasic[]; 36 + user1ArtistCount?: number; 37 + user2ArtistCount?: number; 38 + } 39 + 40 + export interface ActorNeighbourViewBasic { 41 + userId?: string; 42 + did?: string; 43 + handle?: string; 44 + displayName?: string; 45 + /** The URL of the actor's avatar image. */ 46 + avatar?: Uri; 47 + /** The number of artists shared with the actor. */ 48 + sharedArtistsCount?: number; 49 + /** The similarity score with the actor. */ 50 + similarityScore?: number; 51 + /** The top shared artist names with the actor. */ 52 + topSharedArtistNames?: string[]; 53 + /** The top shared artist details with the actor. */ 54 + topSharedArtistsDetails?: ArtistViewBasic[]; 55 + } 56 + 57 + export interface ActorProfileViewBasic { 58 + /** The unique identifier of the actor. */ 59 + id?: string; 60 + /** The DID of the actor. */ 61 + did?: string; 62 + /** The handle of the actor. */ 63 + handle?: string; 64 + /** The display name of the actor. */ 65 + displayName?: string; 66 + /** The URL of the actor's avatar image. */ 67 + avatar?: Uri; 68 + /** The date and time when the actor was created. */ 69 + createdAt?: DateTime; 70 + /** The date and time when the actor was last updated. */ 71 + updatedAt?: DateTime; 72 + } 73 + 74 + export interface ActorProfileViewDetailed { 75 + /** The unique identifier of the actor. */ 76 + id?: string; 77 + /** The DID of the actor. */ 78 + did?: string; 79 + /** The handle of the actor. */ 80 + handle?: string; 81 + /** The display name of the actor. */ 82 + displayName?: string; 83 + /** The URL of the actor's avatar image. */ 84 + avatar?: Uri; 85 + /** The date and time when the actor was created. */ 86 + createdAt?: DateTime; 87 + /** The date and time when the actor was last updated. */ 88 + updatedAt?: DateTime; 89 + } 90 + 91 + export interface ActorTrackView { 92 + /** The name of the track. */ 93 + name: string; 94 + /** The primary artist name. */ 95 + artist: string; 96 + /** The album name. */ 97 + album?: string; 98 + /** URL of the album cover image. */ 99 + albumCoverUrl?: Uri; 100 + /** Track duration in milliseconds. */ 101 + durationMs?: number; 102 + /** Music service source, e.g. 'spotify' or 'listenbrainz'. */ 103 + source?: string; 104 + /** MusicBrainz recording ID, if available. */ 105 + recordingMbId?: string; 106 + } 107 + 108 + export interface AddDirectoryToQueueParams { 109 + playerId?: string; 110 + /** The directory to add to the queue */ 111 + directory: string; 112 + /** Position in the queue to insert the directory at, defaults to the end if not specified */ 113 + position?: number; 114 + /** Whether to shuffle the added directory in the queue */ 115 + shuffle?: boolean; 116 + } 117 + 118 + export interface AddItemsToQueueParams { 119 + playerId?: string; 120 + items: string[]; 121 + /** Position in the queue to insert the items at, defaults to the end if not specified */ 122 + position?: number; 123 + /** Whether to shuffle the added items in the queue */ 124 + shuffle?: boolean; 125 + } 126 + 127 + export interface AlbumRecord { 128 + /** The title of the album. */ 129 + title: string; 130 + /** The artist of the album. */ 131 + artist: string; 132 + /** The duration of the album in seconds. */ 133 + duration?: number; 134 + /** The release date of the album. */ 135 + releaseDate?: DateTime; 136 + /** The year the album was released. */ 137 + year?: number; 138 + /** The genre of the album. */ 139 + genre?: string; 140 + /** The album art of the album. */ 141 + albumArt?: BlobRef; 142 + /** The URL of the album art of the album. */ 143 + albumArtUrl?: Uri; 144 + /** The tags of the album. */ 145 + tags?: string[]; 146 + /** The YouTube link of the album. */ 147 + youtubeLink?: Uri; 148 + /** The Spotify link of the album. */ 149 + spotifyLink?: Uri; 150 + /** The tidal link of the album. */ 151 + tidalLink?: Uri; 152 + /** The Apple Music link of the album. */ 153 + appleMusicLink?: Uri; 154 + /** The date and time when the album was created. */ 155 + createdAt: DateTime; 156 + } 157 + 158 + export interface AlbumViewBasic { 159 + /** The unique identifier of the album. */ 160 + id?: string; 161 + /** The URI of the album. */ 162 + uri?: AtUri; 163 + /** The title of the album. */ 164 + title?: string; 165 + /** The artist of the album. */ 166 + artist?: string; 167 + /** The URI of the album's artist. */ 168 + artistUri?: AtUri; 169 + /** The year the album was released. */ 170 + year?: number; 171 + /** The URL of the album art image. */ 172 + albumArt?: Uri; 173 + /** The release date of the album. */ 174 + releaseDate?: string; 175 + /** The SHA256 hash of the album. */ 176 + sha256?: string; 177 + /** The number of times the album has been played. */ 178 + playCount?: number; 179 + /** The number of unique listeners who have played the album. */ 180 + uniqueListeners?: number; 181 + } 182 + 183 + export interface AlbumViewDetailed { 184 + /** The unique identifier of the album. */ 185 + id?: string; 186 + /** The URI of the album. */ 187 + uri?: AtUri; 188 + /** The title of the album. */ 189 + title?: string; 190 + /** The artist of the album. */ 191 + artist?: string; 192 + /** The URI of the album's artist. */ 193 + artistUri?: AtUri; 194 + /** The year the album was released. */ 195 + year?: number; 196 + /** The URL of the album art image. */ 197 + albumArt?: Uri; 198 + /** The release date of the album. */ 199 + releaseDate?: string; 200 + /** The SHA256 hash of the album. */ 201 + sha256?: string; 202 + /** The number of times the album has been played. */ 203 + playCount?: number; 204 + /** The number of unique listeners who have played the album. */ 205 + uniqueListeners?: number; 206 + tags?: string[]; 207 + tracks?: SongViewBasic[]; 208 + } 209 + 210 + export interface ApiKeyView { 211 + /** The unique identifier of the API key. */ 212 + id?: string; 213 + /** The name of the API key. */ 214 + name?: string; 215 + /** A description for the API key. */ 216 + description?: string; 217 + /** The date and time when the API key was created. */ 218 + createdAt?: DateTime; 219 + } 220 + 221 + export interface ArtistListenerViewBasic { 222 + /** The unique identifier of the actor. */ 223 + id?: string; 224 + /** The DID of the listener. */ 225 + did?: string; 226 + /** The handle of the listener. */ 227 + handle?: string; 228 + /** The display name of the listener. */ 229 + displayName?: string; 230 + /** The URL of the listener's avatar image. */ 231 + avatar?: Uri; 232 + mostListenedSong?: ArtistSongViewBasic; 233 + /** The total number of plays by the listener. */ 234 + totalPlays?: number; 235 + /** The rank of the listener among all listeners of the artist. */ 236 + rank?: number; 237 + } 238 + 239 + export interface ArtistMbid { 240 + /** The MusicBrainz Identifier (MBID) of the artist. */ 241 + mbid?: string; 242 + /** The name of the artist. */ 243 + name?: string; 244 + } 245 + 246 + export interface ArtistRecentListenerView { 247 + /** The unique identifier of the listener. */ 248 + id?: string; 249 + /** The DID of the listener. */ 250 + did?: string; 251 + /** The handle of the listener. */ 252 + handle?: string; 253 + /** The display name of the listener. */ 254 + displayName?: string; 255 + /** The URL of the listener's avatar image. */ 256 + avatar?: Uri; 257 + /** The timestamp of the listener's most recent scrobble of this artist. */ 258 + timestamp?: DateTime; 259 + /** The URI of the listener's most recent scrobble of this artist. */ 260 + scrobbleUri?: AtUri; 261 + } 262 + 263 + export interface ArtistRecord { 264 + /** The name of the artist. */ 265 + name: string; 266 + /** The biography of the artist. */ 267 + bio?: string; 268 + /** The picture of the artist. */ 269 + picture?: BlobRef; 270 + /** The URL of the picture of the artist. */ 271 + pictureUrl?: Uri; 272 + /** The tags of the artist. */ 273 + tags?: string[]; 274 + /** The birth date of the artist. */ 275 + born?: DateTime; 276 + /** The death date of the artist. */ 277 + died?: DateTime; 278 + /** The birth place of the artist. */ 279 + bornIn?: string; 280 + /** The date when the artist was created. */ 281 + createdAt: DateTime; 282 + } 283 + 284 + export interface ArtistSongViewBasic { 285 + /** The URI of the song. */ 286 + uri?: AtUri; 287 + /** The title of the song. */ 288 + title?: string; 289 + /** The number of times the song has been played. */ 290 + playCount?: number; 291 + } 292 + 293 + export interface ArtistViewBasic { 294 + /** The unique identifier of the artist. */ 295 + id?: string; 296 + /** The URI of the artist. */ 297 + uri?: AtUri; 298 + /** The name of the artist. */ 299 + name?: string; 300 + /** The picture of the artist. */ 301 + picture?: string; 302 + /** The SHA256 hash of the artist. */ 303 + sha256?: string; 304 + /** The number of times the artist has been played. */ 305 + playCount?: number; 306 + /** The number of unique listeners who have played the artist. */ 307 + uniqueListeners?: number; 308 + tags?: string[]; 309 + } 310 + 311 + export interface ArtistViewDetailed { 312 + /** The unique identifier of the artist. */ 313 + id?: string; 314 + /** The URI of the artist. */ 315 + uri?: AtUri; 316 + /** The name of the artist. */ 317 + name?: string; 318 + /** The picture of the artist. */ 319 + picture?: string; 320 + /** The SHA256 hash of the artist. */ 321 + sha256?: string; 322 + /** The number of times the artist has been played. */ 323 + playCount?: number; 324 + /** The number of unique listeners who have played the artist. */ 325 + uniqueListeners?: number; 326 + tags?: string[]; 327 + } 328 + 329 + export interface ChartsScrobbleViewBasic { 330 + /** The date of the scrobble. */ 331 + date?: DateTime; 332 + /** The number of scrobbles on this date. */ 333 + count?: number; 334 + } 335 + 336 + export interface ChartsView { 337 + scrobbles?: ChartsScrobbleViewBasic[]; 338 + } 339 + 340 + export interface CreateApikeyInput { 341 + /** The name of the API key. */ 342 + name: string; 343 + /** A description for the API key. */ 344 + description?: string; 345 + } 346 + 347 + export interface CreatePlaylistParams { 348 + /** The name of the playlist */ 349 + name: string; 350 + /** A brief description of the playlist */ 351 + description?: string; 352 + } 353 + 354 + export interface CreateScrobbleInput { 355 + /** The title of the track being scrobbled */ 356 + title: string; 357 + /** The artist of the track being scrobbled */ 358 + artist: string; 359 + /** The album of the track being scrobbled */ 360 + album?: string; 361 + /** The duration of the track in milliseconds */ 362 + duration?: number; 363 + /** The MusicBrainz ID of the track, if available */ 364 + mbId?: string; 365 + /** The International Standard Recording Code (ISRC) of the track, if available */ 366 + isrc?: string; 367 + /** The URL of the album art for the track */ 368 + albumArt?: Uri; 369 + /** The track number of the track in the album */ 370 + trackNumber?: number; 371 + /** The release date of the track, formatted as YYYY-MM-DD */ 372 + releaseDate?: string; 373 + /** The year the track was released */ 374 + year?: number; 375 + /** The disc number of the track in the album, if applicable */ 376 + discNumber?: number; 377 + /** The lyrics of the track, if available */ 378 + lyrics?: string; 379 + /** The composer of the track, if available */ 380 + composer?: string; 381 + /** The copyright message for the track, if available */ 382 + copyrightMessage?: string; 383 + /** The record label of the track, if available */ 384 + label?: string; 385 + /** The URL of the artist's picture, if available */ 386 + artistPicture?: Uri; 387 + /** The Spotify link for the track, if available */ 388 + spotifyLink?: Uri; 389 + /** The Last.fm link for the track, if available */ 390 + lastfmLink?: Uri; 391 + /** The Tidal link for the track, if available */ 392 + tidalLink?: Uri; 393 + /** The Apple Music link for the track, if available */ 394 + appleMusicLink?: Uri; 395 + /** The Youtube link for the track, if available */ 396 + youtubeLink?: Uri; 397 + /** The Deezer link for the track, if available */ 398 + deezerLink?: Uri; 399 + /** The timestamp of the scrobble in seconds since epoch (Unix timestamp) */ 400 + timestamp?: number; 401 + } 402 + 403 + export interface CreateShoutInput { 404 + /** The content of the shout */ 405 + message?: string; 406 + } 407 + 408 + export interface CreateSongInput { 409 + /** The title of the song */ 410 + title: string; 411 + /** The artist of the song */ 412 + artist: string; 413 + /** The album artist of the song, if different from the main artist */ 414 + albumArtist: string; 415 + /** The album of the song, if applicable */ 416 + album: string; 417 + /** The duration of the song in seconds */ 418 + duration?: number; 419 + /** The MusicBrainz ID of the song, if available */ 420 + mbId?: string; 421 + /** The International Standard Recording Code (ISRC) of the song, if available */ 422 + isrc?: string; 423 + /** The URL of the album art for the song */ 424 + albumArt?: Uri; 425 + /** The track number of the song in the album, if applicable */ 426 + trackNumber?: number; 427 + /** The release date of the song, formatted as YYYY-MM-DD */ 428 + releaseDate?: string; 429 + /** The year the song was released */ 430 + year?: number; 431 + /** The disc number of the song in the album, if applicable */ 432 + discNumber?: number; 433 + /** The lyrics of the song, if available */ 434 + lyrics?: string; 435 + } 436 + 437 + export interface DescribeFeedGeneratorOutput { 438 + /** The DID of the feed generator. */ 439 + did?: AtIdentifier; 440 + /** List of feed URIs generated by this feed generator. */ 441 + feeds?: FeedUriView[]; 442 + } 443 + 444 + export interface DescribeFeedGeneratorParams { 445 + 446 + } 447 + 448 + export interface DislikeShoutInput { 449 + /** The unique identifier of the shout to dislike */ 450 + uri?: AtUri; 451 + } 452 + 453 + export interface DislikeSongInput { 454 + /** The unique identifier of the song to dislike */ 455 + uri?: AtUri; 456 + } 457 + 458 + export interface DownloadFileParams { 459 + /** The unique identifier of the file to download */ 460 + fileId: string; 461 + } 462 + 463 + export interface DropboxFileListView { 464 + /** A list of files in the Dropbox. */ 465 + files?: DropboxFileView[]; 466 + } 467 + 468 + export interface DropboxFileView { 469 + /** The unique identifier of the file. */ 470 + id?: string; 471 + /** The name of the file. */ 472 + name?: string; 473 + /** The lowercased path of the file. */ 474 + pathLower?: string; 475 + /** The display path of the file. */ 476 + pathDisplay?: string; 477 + /** The last modified date and time of the file on the client. */ 478 + clientModified?: DateTime; 479 + /** The last modified date and time of the file on the server. */ 480 + serverModified?: DateTime; 481 + } 482 + 483 + export interface DropboxTemporaryLinkView { 484 + /** The temporary link to access the file. */ 485 + link?: Uri; 486 + } 487 + 488 + export interface FeedGeneratorsView { 489 + feeds?: FeedGeneratorView[]; 490 + } 491 + 492 + export interface FeedGeneratorView { 493 + id?: string; 494 + name?: string; 495 + description?: string; 496 + uri?: AtUri; 497 + avatar?: Uri; 498 + creator?: ActorProfileViewBasic; 499 + } 500 + 501 + export interface FeedItemView { 502 + scrobble?: ScrobbleViewBasic; 503 + } 504 + 505 + export interface FeedRecommendationsView { 506 + recommendations?: FeedRecommendationView[]; 507 + cursor?: string; 508 + } 509 + 510 + export interface FeedRecommendationView { 511 + title?: string; 512 + artist?: string; 513 + album?: string; 514 + albumArt?: Uri; 515 + trackUri?: AtUri; 516 + artistUri?: AtUri; 517 + albumUri?: AtUri; 518 + genres?: string[]; 519 + recommendationScore?: number; 520 + /** neighbour | social | serendipity */ 521 + source?: string; 522 + likesCount?: number; 523 + } 524 + 525 + export interface FeedRecommendedAlbumsView { 526 + albums?: FeedRecommendedAlbumView[]; 527 + cursor?: string; 528 + } 529 + 530 + export interface FeedRecommendedAlbumView { 531 + id?: string; 532 + uri?: AtUri; 533 + title?: string; 534 + artist?: string; 535 + artistUri?: AtUri; 536 + year?: number; 537 + albumArt?: Uri; 538 + recommendationScore?: number; 539 + /** known-artist | new-artist | serendipity */ 540 + source?: string; 541 + } 542 + 543 + export interface FeedRecommendedArtistsView { 544 + artists?: FeedRecommendedArtistView[]; 545 + cursor?: string; 546 + } 547 + 548 + export interface FeedRecommendedArtistView { 549 + id?: string; 550 + uri?: AtUri; 551 + name?: string; 552 + picture?: Uri; 553 + genres?: string[]; 554 + recommendationScore?: number; 555 + /** neighbour | social | serendipity */ 556 + source?: string; 557 + } 558 + 559 + export interface FeedSearchResultsView { 560 + hits?: SongViewBasic | AlbumViewBasic | ArtistViewBasic | PlaylistViewBasic | ActorProfileViewBasic[]; 561 + processingTimeMs?: number; 562 + limit?: number; 563 + offset?: number; 564 + estimatedTotalHits?: number; 565 + } 566 + 567 + export interface FeedStoriesView { 568 + stories?: FeedStoryView[]; 569 + } 570 + 571 + export interface FeedStoryView { 572 + album?: string; 573 + albumArt?: Uri; 574 + albumArtist?: string; 575 + albumUri?: AtUri; 576 + artist?: string; 577 + artistUri?: AtUri; 578 + avatar?: Uri; 579 + createdAt?: string; 580 + did?: AtIdentifier; 581 + handle?: string; 582 + id?: string; 583 + title?: string; 584 + trackId?: string; 585 + trackUri?: AtUri; 586 + uri?: AtUri; 587 + } 588 + 589 + export interface FeedUriView { 590 + /** The feed URI. */ 591 + uri?: AtUri; 592 + } 593 + 594 + export interface FeedView { 595 + feed?: FeedItemView[]; 596 + /** The pagination cursor for the next set of results. */ 597 + cursor?: string; 598 + } 599 + 600 + export interface FollowAccountOutput { 601 + subject: ActorProfileViewBasic; 602 + followers: ActorProfileViewBasic[]; 603 + /** A cursor value to pass to subsequent calls to get the next page of results. */ 604 + cursor?: string; 605 + } 606 + 607 + export interface FollowAccountParams { 608 + account: AtIdentifier; 609 + } 610 + 611 + export interface FollowRecord { 612 + createdAt: DateTime; 613 + subject: Did; 614 + via?: StrongRef; 615 + } 616 + 617 + export interface GeneratorRecord { 618 + did: Did; 619 + avatar?: BlobRef; 620 + displayName: string; 621 + description?: string; 622 + createdAt: DateTime; 623 + } 624 + 625 + export interface GetActorAlbumsOutput { 626 + albums?: AlbumViewBasic[]; 627 + } 628 + 629 + export interface GetActorAlbumsParams { 630 + /** The DID or handle of the actor */ 631 + did: AtIdentifier; 632 + /** The maximum number of albums to return */ 633 + limit?: number; 634 + /** The offset for pagination */ 635 + offset?: number; 636 + /** The start date to filter albums from (ISO 8601 format) */ 637 + startDate?: DateTime; 638 + /** The end date to filter albums to (ISO 8601 format) */ 639 + endDate?: DateTime; 640 + } 641 + 642 + export interface GetActorArtistsOutput { 643 + artists?: ArtistViewBasic[]; 644 + } 645 + 646 + export interface GetActorArtistsParams { 647 + /** The DID or handle of the actor */ 648 + did: AtIdentifier; 649 + /** The maximum number of albums to return */ 650 + limit?: number; 651 + /** The offset for pagination */ 652 + offset?: number; 653 + /** The start date to filter albums from (ISO 8601 format) */ 654 + startDate?: DateTime; 655 + /** The end date to filter albums to (ISO 8601 format) */ 656 + endDate?: DateTime; 657 + } 658 + 659 + export interface GetActorCompatibilityOutput { 660 + compatibility?: ActorCompatibilityViewBasic; 661 + } 662 + 663 + export interface GetActorCompatibilityParams { 664 + /** DID or handle to get compatibility for */ 665 + did: AtIdentifier; 666 + } 667 + 668 + export interface GetActorLovedSongsOutput { 669 + tracks?: SongViewBasic[]; 670 + } 671 + 672 + export interface GetActorLovedSongsParams { 673 + /** The DID or handle of the actor */ 674 + did: AtIdentifier; 675 + /** The maximum number of albums to return */ 676 + limit?: number; 677 + /** The offset for pagination */ 678 + offset?: number; 679 + } 680 + 681 + export interface GetActorNeighboursOutput { 682 + neighbours?: ActorNeighbourViewBasic[]; 683 + } 684 + 685 + export interface GetActorNeighboursParams { 686 + /** The DID or handle of the actor */ 687 + did: AtIdentifier; 688 + } 689 + 690 + export interface GetActorPlaylistsOutput { 691 + playlists?: PlaylistViewBasic[]; 692 + } 693 + 694 + export interface GetActorPlaylistsParams { 695 + /** The DID or handle of the actor */ 696 + did: AtIdentifier; 697 + /** The maximum number of albums to return */ 698 + limit?: number; 699 + /** The offset for pagination */ 700 + offset?: number; 701 + } 702 + 703 + export interface GetActorScrobblesOutput { 704 + scrobbles?: ScrobbleViewBasic[]; 705 + } 706 + 707 + export interface GetActorScrobblesParams { 708 + /** The DID or handle of the actor */ 709 + did: AtIdentifier; 710 + /** The maximum number of albums to return */ 711 + limit?: number; 712 + /** The offset for pagination */ 713 + offset?: number; 714 + } 715 + 716 + export interface GetActorSongsOutput { 717 + songs?: SongViewBasic[]; 718 + } 719 + 720 + export interface GetActorSongsParams { 721 + /** The DID or handle of the actor */ 722 + did: AtIdentifier; 723 + /** The maximum number of albums to return */ 724 + limit?: number; 725 + /** The offset for pagination */ 726 + offset?: number; 727 + /** The start date to filter albums from (ISO 8601 format) */ 728 + startDate?: DateTime; 729 + /** The end date to filter albums to (ISO 8601 format) */ 730 + endDate?: DateTime; 731 + } 732 + 733 + export interface GetAlbumParams { 734 + /** The URI of the album to retrieve. */ 735 + uri: AtUri; 736 + } 737 + 738 + export interface GetAlbumRecommendationsParams { 739 + /** DID or handle of the user to recommend for. */ 740 + did: string; 741 + limit?: number; 742 + } 743 + 744 + export interface GetAlbumShoutsOutput { 745 + shouts?: unknown[]; 746 + } 747 + 748 + export interface GetAlbumShoutsParams { 749 + /** The unique identifier of the album to retrieve shouts for */ 750 + uri: AtUri; 751 + /** The maximum number of shouts to return */ 752 + limit?: number; 753 + /** The number of shouts to skip before starting to collect the result set */ 754 + offset?: number; 755 + } 756 + 757 + export interface GetAlbumsOutput { 758 + albums?: AlbumViewBasic[]; 759 + } 760 + 761 + export interface GetAlbumsParams { 762 + /** The maximum number of albums to return */ 763 + limit?: number; 764 + /** The offset for pagination */ 765 + offset?: number; 766 + /** The genre to filter artists by */ 767 + genre?: string; 768 + } 769 + 770 + export interface GetAlbumTracksOutput { 771 + tracks?: SongViewBasic[]; 772 + } 773 + 774 + export interface GetAlbumTracksParams { 775 + /** The URI of the album to retrieve tracks from */ 776 + uri: AtUri; 777 + } 778 + 779 + export interface GetApikeysOutput { 780 + apiKeys?: unknown[]; 781 + } 782 + 783 + export interface GetApikeysParams { 784 + /** The number of API keys to skip before starting to collect the result set. */ 785 + offset?: number; 786 + /** The number of API keys to return per page. */ 787 + limit?: number; 788 + } 789 + 790 + export interface GetArtistAlbumsOutput { 791 + albums?: AlbumViewBasic[]; 792 + } 793 + 794 + export interface GetArtistAlbumsParams { 795 + /** The URI of the artist to retrieve albums from */ 796 + uri: AtUri; 797 + } 798 + 799 + export interface GetArtistListenersOutput { 800 + listeners?: ArtistListenerViewBasic[]; 801 + } 802 + 803 + export interface GetArtistListenersParams { 804 + /** The URI of the artist to retrieve listeners from */ 805 + uri: AtUri; 806 + /** Number of items to skip before returning results */ 807 + offset?: number; 808 + /** Maximum number of results to return */ 809 + limit?: number; 810 + } 811 + 812 + export interface GetArtistParams { 813 + /** The URI of the artist to retrieve details from */ 814 + uri: AtUri; 815 + } 816 + 817 + export interface GetArtistRecentListenersOutput { 818 + listeners?: ArtistRecentListenerView[]; 819 + } 820 + 821 + export interface GetArtistRecentListenersParams { 822 + /** The URI of the artist to retrieve recent listeners from */ 823 + uri: AtUri; 824 + /** Number of items to skip before returning results */ 825 + offset?: number; 826 + /** Maximum number of results to return */ 827 + limit?: number; 828 + } 829 + 830 + export interface GetArtistRecommendationsParams { 831 + /** DID or handle of the user to recommend for. */ 832 + did: string; 833 + limit?: number; 834 + } 835 + 836 + export interface GetArtistShoutsOutput { 837 + shouts?: unknown[]; 838 + } 839 + 840 + export interface GetArtistShoutsParams { 841 + /** The URI of the artist to retrieve shouts for */ 842 + uri: AtUri; 843 + /** The maximum number of shouts to return */ 844 + limit?: number; 845 + /** The number of shouts to skip before starting to collect the result set */ 846 + offset?: number; 847 + } 848 + 849 + export interface GetArtistsOutput { 850 + artists?: ArtistViewBasic[]; 851 + } 852 + 853 + export interface GetArtistsParams { 854 + /** The maximum number of artists to return */ 855 + limit?: number; 856 + /** The offset for pagination */ 857 + offset?: number; 858 + /** The names of the artists to return */ 859 + names?: string; 860 + /** The genre to filter artists by */ 861 + genre?: string; 862 + } 863 + 864 + export interface GetArtistTracksOutput { 865 + tracks?: SongViewBasic[]; 866 + } 867 + 868 + export interface GetArtistTracksParams { 869 + /** The URI of the artist to retrieve albums from */ 870 + uri?: AtUri; 871 + /** The maximum number of tracks to return */ 872 + limit?: number; 873 + /** The offset for pagination */ 874 + offset?: number; 875 + } 876 + 877 + export interface GetCurrentlyPlayingParams { 878 + playerId?: string; 879 + /** Handle or DID of the actor to retrieve the currently playing track for. If not provided, defaults to the current user. */ 880 + actor?: AtIdentifier; 881 + } 882 + 883 + export interface GetFeedGeneratorOutput { 884 + view?: FeedGeneratorView; 885 + } 886 + 887 + export interface GetFeedGeneratorParams { 888 + /** AT-URI of the feed generator record. */ 889 + feed: AtUri; 890 + } 891 + 892 + export interface GetFeedGeneratorsParams { 893 + /** The maximum number of feed generators to return. */ 894 + size?: number; 895 + } 896 + 897 + export interface GetFeedParams { 898 + /** The feed URI. */ 899 + feed: AtUri; 900 + /** The maximum number of scrobbles to return */ 901 + limit?: number; 902 + /** The cursor for pagination */ 903 + cursor?: string; 904 + } 905 + 906 + export interface GetFeedSkeletonOutput { 907 + scrobbles?: ScrobbleViewBasic[]; 908 + /** The pagination cursor for the next set of results. */ 909 + cursor?: string; 910 + } 911 + 912 + export interface GetFeedSkeletonParams { 913 + /** The feed URI. */ 914 + feed: AtUri; 915 + /** The maximum number of scrobbles to return */ 916 + limit?: number; 917 + /** The offset for pagination */ 918 + offset?: number; 919 + /** The pagination cursor. */ 920 + cursor?: string; 921 + } 922 + 923 + export interface GetFileParams { 924 + /** The unique identifier of the file to retrieve */ 925 + fileId: string; 926 + } 927 + 928 + export interface GetFilesParams { 929 + /** Path to the Dropbox folder or root directory */ 930 + at?: string; 931 + } 932 + 933 + export interface GetFollowersOutput { 934 + subject: ActorProfileViewBasic; 935 + followers: ActorProfileViewBasic[]; 936 + /** A cursor value to pass to subsequent calls to get the next page of results. */ 937 + cursor?: string; 938 + /** The total number of followers. */ 939 + count?: number; 940 + } 941 + 942 + export interface GetFollowersParams { 943 + actor: AtIdentifier; 944 + limit?: number; 945 + /** If provided, filters the followers to only include those with DIDs in this list. */ 946 + dids?: Did[]; 947 + cursor?: string; 948 + } 949 + 950 + export interface GetFollowsOutput { 951 + subject: ActorProfileViewBasic; 952 + follows: ActorProfileViewBasic[]; 953 + /** A cursor value to pass to subsequent calls to get the next page of results. */ 954 + cursor?: string; 955 + /** The total number of follows. */ 956 + count?: number; 957 + } 958 + 959 + export interface GetFollowsParams { 960 + actor: AtIdentifier; 961 + limit?: number; 962 + /** If provided, filters the follows to only include those with DIDs in this list. */ 963 + dids?: Did[]; 964 + cursor?: string; 965 + } 966 + 967 + export interface GetKnownFollowersOutput { 968 + subject: ActorProfileViewBasic; 969 + followers: ActorProfileViewBasic[]; 970 + /** A cursor value to pass to subsequent calls to get the next page of results. */ 971 + cursor?: string; 972 + } 973 + 974 + export interface GetKnownFollowersParams { 975 + actor: AtIdentifier; 976 + limit?: number; 977 + cursor?: string; 978 + } 979 + 980 + export interface GetMetadataParams { 981 + /** Path to the file or folder in Dropbox */ 982 + path: string; 983 + } 984 + 985 + export interface GetMirrorSourcesOutput { 986 + sources: MirrorSourceView[]; 987 + } 988 + 989 + export interface GetMirrorSourcesParams { 990 + 991 + } 992 + 993 + export interface GetPlaybackQueueParams { 994 + playerId?: string; 995 + } 996 + 997 + export interface GetPlaylistParams { 998 + /** The URI of the playlist to retrieve. */ 999 + uri: AtUri; 1000 + } 1001 + 1002 + export interface GetPlaylistsOutput { 1003 + playlists?: PlaylistViewBasic[]; 1004 + } 1005 + 1006 + export interface GetPlaylistsParams { 1007 + /** The maximum number of playlists to return. */ 1008 + limit?: number; 1009 + /** The offset for pagination, used to skip a number of playlists. */ 1010 + offset?: number; 1011 + } 1012 + 1013 + export interface GetProfileParams { 1014 + /** The DID or handle of the actor */ 1015 + did?: AtIdentifier; 1016 + } 1017 + 1018 + export interface GetProfileShoutsOutput { 1019 + shouts?: unknown[]; 1020 + } 1021 + 1022 + export interface GetProfileShoutsParams { 1023 + /** The DID or handle of the actor */ 1024 + did: AtIdentifier; 1025 + /** The offset for pagination */ 1026 + offset?: number; 1027 + /** The maximum number of shouts to return */ 1028 + limit?: number; 1029 + } 1030 + 1031 + export interface GetRecommendationsParams { 1032 + /** DID or handle of the user to recommend for. */ 1033 + did: string; 1034 + limit?: number; 1035 + } 1036 + 1037 + export interface GetScrobbleParams { 1038 + /** The unique identifier of the scrobble */ 1039 + uri: AtUri; 1040 + } 1041 + 1042 + export interface GetScrobblesChartParams { 1043 + /** The DID or handle of the actor */ 1044 + did?: AtIdentifier; 1045 + /** The URI of the artist to filter by */ 1046 + artisturi?: AtUri; 1047 + /** The URI of the album to filter by */ 1048 + albumuri?: AtUri; 1049 + /** The URI of the track to filter by */ 1050 + songuri?: AtUri; 1051 + /** The genre to filter by */ 1052 + genre?: string; 1053 + /** Start date (ISO 8601). Defaults to 6 months ago. */ 1054 + from?: string; 1055 + /** End date (ISO 8601). Defaults to today. */ 1056 + to?: string; 1057 + } 1058 + 1059 + export interface GetScrobblesOutput { 1060 + scrobbles?: ScrobbleViewBasic[]; 1061 + } 1062 + 1063 + export interface GetScrobblesParams { 1064 + /** The DID or handle of the actor */ 1065 + did?: AtIdentifier; 1066 + /** If true, only return scrobbles from actors the viewer is following. */ 1067 + following?: boolean; 1068 + /** The maximum number of scrobbles to return */ 1069 + limit?: number; 1070 + /** The offset for pagination */ 1071 + offset?: number; 1072 + } 1073 + 1074 + export interface GetShoutRepliesOutput { 1075 + shouts?: unknown[]; 1076 + } 1077 + 1078 + export interface GetShoutRepliesParams { 1079 + /** The URI of the shout to retrieve replies for */ 1080 + uri: AtUri; 1081 + /** The maximum number of shouts to return */ 1082 + limit?: number; 1083 + /** The number of shouts to skip before starting to collect the result set */ 1084 + offset?: number; 1085 + } 1086 + 1087 + export interface GetSongParams { 1088 + /** The AT-URI of the song to retrieve */ 1089 + uri?: AtUri; 1090 + /** The MusicBrainz ID of the song to retrieve */ 1091 + mbid?: string; 1092 + /** The International Standard Recording Code (ISRC) of the song to retrieve */ 1093 + isrc?: string; 1094 + /** The Spotify track ID of the song to retrieve (resolved internally to the Spotify track URL) */ 1095 + spotifyId?: string; 1096 + } 1097 + 1098 + export interface GetSongRecentListenersOutput { 1099 + listeners?: SongRecentListenerView[]; 1100 + } 1101 + 1102 + export interface GetSongRecentListenersParams { 1103 + /** The URI of the song to retrieve recent listeners from */ 1104 + uri: AtUri; 1105 + /** Number of items to skip before returning results */ 1106 + offset?: number; 1107 + /** Maximum number of results to return */ 1108 + limit?: number; 1109 + } 1110 + 1111 + export interface GetSongsOutput { 1112 + songs?: SongViewBasic[]; 1113 + } 1114 + 1115 + export interface GetSongsParams { 1116 + /** The maximum number of songs to return */ 1117 + limit?: number; 1118 + /** The offset for pagination */ 1119 + offset?: number; 1120 + /** The genre to filter artists by */ 1121 + genre?: string; 1122 + /** Filter songs by MusicBrainz ID */ 1123 + mbid?: string; 1124 + /** Filter songs by International Standard Recording Code (ISRC) */ 1125 + isrc?: string; 1126 + /** Filter songs by Spotify track ID (resolved internally to the Spotify track URL) */ 1127 + spotifyId?: string; 1128 + } 1129 + 1130 + export interface GetStatsParams { 1131 + /** The DID or handle of the user to get stats for. */ 1132 + did: AtIdentifier; 1133 + } 1134 + 1135 + export interface GetStoriesParams { 1136 + /** The maximum number of stories to return. */ 1137 + size?: number; 1138 + } 1139 + 1140 + export interface GetTemporaryLinkParams { 1141 + /** Path to the file in Dropbox */ 1142 + path: string; 1143 + } 1144 + 1145 + export interface GetTopArtistsOutput { 1146 + artists?: ArtistViewBasic[]; 1147 + } 1148 + 1149 + export interface GetTopArtistsParams { 1150 + /** The maximum number of artists to return */ 1151 + limit?: number; 1152 + /** The offset for pagination */ 1153 + offset?: number; 1154 + /** The start date to filter artists from (ISO 8601 format) */ 1155 + startDate?: DateTime; 1156 + /** The end date to filter artists to (ISO 8601 format) */ 1157 + endDate?: DateTime; 1158 + } 1159 + 1160 + export interface GetTopTracksOutput { 1161 + tracks?: SongViewBasic[]; 1162 + } 1163 + 1164 + export interface GetTopTracksParams { 1165 + /** The maximum number of tracks to return */ 1166 + limit?: number; 1167 + /** The offset for pagination */ 1168 + offset?: number; 1169 + /** The start date to filter tracks from (ISO 8601 format) */ 1170 + startDate?: DateTime; 1171 + /** The end date to filter tracks to (ISO 8601 format) */ 1172 + endDate?: DateTime; 1173 + } 1174 + 1175 + export interface GetTrackShoutsOutput { 1176 + shouts?: unknown[]; 1177 + } 1178 + 1179 + export interface GetTrackShoutsParams { 1180 + /** The URI of the track to retrieve shouts for */ 1181 + uri: AtUri; 1182 + } 1183 + 1184 + export interface GetWrappedParams { 1185 + /** The DID or handle of the user */ 1186 + did: AtIdentifier; 1187 + /** The year to get wrapped stats for (defaults to current year) */ 1188 + year?: number; 1189 + } 1190 + 1191 + export interface GoogledriveFileListView { 1192 + files?: GoogledriveFileView[]; 1193 + } 1194 + 1195 + export interface GoogledriveFileView { 1196 + /** The unique identifier of the file. */ 1197 + id?: string; 1198 + } 1199 + 1200 + /** indicates that a handle or DID could not be resolved */ 1201 + export interface GraphNotFoundActor { 1202 + actor: AtIdentifier; 1203 + notFound: boolean; 1204 + } 1205 + 1206 + export interface GraphRelationship { 1207 + did: Did; 1208 + /** if the actor follows this DID, this is the AT-URI of the follow record */ 1209 + following?: AtUri; 1210 + /** if the actor is followed by this DID, contains the AT-URI of the follow record */ 1211 + followedBy?: AtUri; 1212 + } 1213 + 1214 + export interface InsertDirectoryParams { 1215 + /** The URI of the playlist to start */ 1216 + uri: AtUri; 1217 + /** The directory (id) to insert into the playlist */ 1218 + directory: string; 1219 + /** The position in the playlist to insert the directory at, if not specified, the directory will be appended */ 1220 + position?: number; 1221 + } 1222 + 1223 + export interface InsertFilesParams { 1224 + /** The URI of the playlist to start */ 1225 + uri: AtUri; 1226 + files: string[]; 1227 + /** The position in the playlist to insert the files at, if not specified, files will be appended */ 1228 + position?: number; 1229 + } 1230 + 1231 + export interface LikeRecord { 1232 + /** The date when the like was created. */ 1233 + createdAt: DateTime; 1234 + subject: StrongRef; 1235 + } 1236 + 1237 + export interface LikeShoutInput { 1238 + /** The unique identifier of the shout to like */ 1239 + uri?: AtUri; 1240 + } 1241 + 1242 + export interface LikeSongInput { 1243 + /** The unique identifier of the song to like */ 1244 + uri?: AtUri; 1245 + } 1246 + 1247 + export interface MatchSongParams { 1248 + /** The title of the song to retrieve */ 1249 + title: string; 1250 + /** The artist of the song to retrieve */ 1251 + artist: string; 1252 + /** Optional MusicBrainz recording ID to anchor the match */ 1253 + mbId?: string; 1254 + /** Optional International Standard Recording Code (ISRC) to anchor the match */ 1255 + isrc?: string; 1256 + } 1257 + 1258 + export interface MirrorSourceView { 1259 + /** One of: lastfm, listenbrainz, tealfm */ 1260 + provider: string; 1261 + /** Whether scrobbles from this source are being mirrored into Rocksky. */ 1262 + enabled: boolean; 1263 + /** Username on the external service (Last.fm / ListenBrainz). Null for Teal.fm. */ 1264 + externalUsername?: string; 1265 + /** True when an API key is stored. Last.fm/ListenBrainz only; always false for Teal.fm. */ 1266 + hasCredentials: boolean; 1267 + /** The last time the mirror process successfully polled this source. */ 1268 + lastPolledAt?: DateTime; 1269 + /** Watermark — scrobbles from the external service older than this are skipped. */ 1270 + lastScrobbleSeenAt?: DateTime; 1271 + } 1272 + 1273 + export interface NextParams { 1274 + playerId?: string; 1275 + } 1276 + 1277 + export interface PauseParams { 1278 + playerId?: string; 1279 + } 1280 + 1281 + export interface PlayDirectoryParams { 1282 + playerId?: string; 1283 + directoryId: string; 1284 + shuffle?: boolean; 1285 + recurse?: boolean; 1286 + position?: number; 1287 + } 1288 + 1289 + export interface PlayerCurrentlyPlayingViewDetailed { 1290 + /** The title of the currently playing track */ 1291 + title?: string; 1292 + } 1293 + 1294 + export interface PlayerPlaybackQueueViewDetailed { 1295 + tracks?: SongViewBasic[]; 1296 + } 1297 + 1298 + export interface PlayFileParams { 1299 + playerId?: string; 1300 + fileId: string; 1301 + } 1302 + 1303 + export interface PlaylistItemRecord { 1304 + subject: StrongRef; 1305 + /** The date the playlist was created. */ 1306 + createdAt: DateTime; 1307 + track: SongViewBasic; 1308 + /** The order of the item in the playlist. */ 1309 + order: number; 1310 + } 1311 + 1312 + export interface PlaylistRecord { 1313 + /** The name of the playlist. */ 1314 + name: string; 1315 + /** The playlist description. */ 1316 + description?: string; 1317 + /** The picture of the playlist. */ 1318 + picture?: BlobRef; 1319 + /** The URL of the picture of the artist. */ 1320 + pictureUrl?: Uri; 1321 + /** The date the playlist was created. */ 1322 + createdAt: DateTime; 1323 + /** The Spotify link of the playlist. */ 1324 + spotifyLink?: string; 1325 + /** The Tidal link of the playlist. */ 1326 + tidalLink?: string; 1327 + /** The YouTube link of the playlist. */ 1328 + youtubeLink?: string; 1329 + /** The Apple Music link of the playlist. */ 1330 + appleMusicLink?: string; 1331 + } 1332 + 1333 + /** Basic view of a playlist, including its metadata */ 1334 + export interface PlaylistViewBasic { 1335 + /** The unique identifier of the playlist. */ 1336 + id?: string; 1337 + /** The title of the playlist. */ 1338 + title?: string; 1339 + /** The URI of the playlist. */ 1340 + uri?: AtUri; 1341 + /** The DID of the curator of the playlist. */ 1342 + curatorDid?: AtIdentifier; 1343 + /** The handle of the curator of the playlist. */ 1344 + curatorHandle?: AtIdentifier; 1345 + /** The name of the curator of the playlist. */ 1346 + curatorName?: string; 1347 + /** The URL of the avatar image of the curator. */ 1348 + curatorAvatarUrl?: Uri; 1349 + /** A description of the playlist. */ 1350 + description?: string; 1351 + /** The URL of the cover image for the playlist. */ 1352 + coverImageUrl?: Uri; 1353 + /** The date and time when the playlist was created. */ 1354 + createdAt?: DateTime; 1355 + /** The number of tracks in the playlist. */ 1356 + trackCount?: number; 1357 + } 1358 + 1359 + /** Detailed view of a playlist, including its tracks and metadata */ 1360 + export interface PlaylistViewDetailed { 1361 + /** The unique identifier of the playlist. */ 1362 + id?: string; 1363 + /** The title of the playlist. */ 1364 + title?: string; 1365 + /** The URI of the playlist. */ 1366 + uri?: AtUri; 1367 + /** The DID of the curator of the playlist. */ 1368 + curatorDid?: AtIdentifier; 1369 + /** The handle of the curator of the playlist. */ 1370 + curatorHandle?: AtIdentifier; 1371 + /** The name of the curator of the playlist. */ 1372 + curatorName?: string; 1373 + /** The URL of the avatar image of the curator. */ 1374 + curatorAvatarUrl?: Uri; 1375 + /** A description of the playlist. */ 1376 + description?: string; 1377 + /** The URL of the cover image for the playlist. */ 1378 + coverImageUrl?: Uri; 1379 + /** The date and time when the playlist was created. */ 1380 + createdAt?: DateTime; 1381 + /** A list of tracks in the playlist. */ 1382 + tracks?: SongViewBasic[]; 1383 + } 1384 + 1385 + export interface PlayParams { 1386 + playerId?: string; 1387 + } 1388 + 1389 + export interface PreviousParams { 1390 + playerId?: string; 1391 + } 1392 + 1393 + export interface ProfileRecord { 1394 + displayName?: string; 1395 + /** Free-form profile description text. */ 1396 + description?: string; 1397 + /** Small image to be displayed next to posts from account. AKA, 'profile picture' */ 1398 + avatar?: BlobRef; 1399 + /** Larger horizontal image to display behind profile view. */ 1400 + banner?: BlobRef; 1401 + /** Self-label values, specific to the Bluesky application, on the overall account. */ 1402 + labels?: unknown; 1403 + joinedViaStarterPack?: StrongRef; 1404 + createdAt?: DateTime; 1405 + } 1406 + 1407 + export interface PutMirrorSourceInput { 1408 + /** One of: lastfm, listenbrainz, tealfm */ 1409 + provider: string; 1410 + /** Enable or disable mirroring for this provider. */ 1411 + enabled?: boolean; 1412 + /** External username (Last.fm / ListenBrainz). Required when enabling those providers. Ignored for Teal.fm. */ 1413 + externalUsername?: string; 1414 + /** API key / token to be encrypted at rest. Omit to leave the existing key unchanged. Pass an empty string to clear it. */ 1415 + apiKey?: string; 1416 + } 1417 + 1418 + export interface RadioRecord { 1419 + /** The name of the radio station. */ 1420 + name: string; 1421 + /** The URL of the radio station. */ 1422 + url: Uri; 1423 + /** A description of the radio station. */ 1424 + description?: string; 1425 + /** The genre of the radio station. */ 1426 + genre?: string; 1427 + /** The logo of the radio station. */ 1428 + logo?: BlobRef; 1429 + /** The website of the radio station. */ 1430 + website?: Uri; 1431 + /** The date when the radio station was created. */ 1432 + createdAt: DateTime; 1433 + } 1434 + 1435 + export interface RadioViewBasic { 1436 + /** The unique identifier of the radio. */ 1437 + id?: string; 1438 + /** The name of the radio. */ 1439 + name?: string; 1440 + /** A brief description of the radio. */ 1441 + description?: string; 1442 + /** The date and time when the radio was created. */ 1443 + createdAt?: DateTime; 1444 + } 1445 + 1446 + export interface RadioViewDetailed { 1447 + /** The unique identifier of the radio. */ 1448 + id?: string; 1449 + /** The name of the radio. */ 1450 + name?: string; 1451 + /** A brief description of the radio. */ 1452 + description?: string; 1453 + /** The website of the radio. */ 1454 + website?: Uri; 1455 + /** The streaming URL of the radio. */ 1456 + url?: Uri; 1457 + /** The genre of the radio. */ 1458 + genre?: string; 1459 + /** The logo of the radio station. */ 1460 + logo?: string; 1461 + /** The date and time when the radio was created. */ 1462 + createdAt?: DateTime; 1463 + } 1464 + 1465 + export interface RemoveApikeyParams { 1466 + /** The ID of the API key to remove. */ 1467 + id: string; 1468 + } 1469 + 1470 + export interface RemovePlaylistParams { 1471 + /** The URI of the playlist to remove */ 1472 + uri: AtUri; 1473 + } 1474 + 1475 + export interface RemoveShoutParams { 1476 + /** The ID of the shout to be removed */ 1477 + id: string; 1478 + } 1479 + 1480 + export interface RemoveTrackParams { 1481 + /** The URI of the playlist to remove the track from */ 1482 + uri: AtUri; 1483 + /** The position of the track to remove in the playlist */ 1484 + position: number; 1485 + } 1486 + 1487 + export interface ReplyShoutInput { 1488 + /** The unique identifier of the shout to reply to */ 1489 + shoutId: string; 1490 + /** The content of the reply */ 1491 + message: string; 1492 + } 1493 + 1494 + export interface ReportShoutInput { 1495 + /** The unique identifier of the shout to report */ 1496 + shoutId: string; 1497 + /** The reason for reporting the shout */ 1498 + reason?: string; 1499 + } 1500 + 1501 + export interface ScrobbleFirstScrobbleView { 1502 + /** The handle of the user who first scrobbled this song. */ 1503 + handle?: string; 1504 + /** The avatar URL of the user who first scrobbled this song. */ 1505 + avatar?: Uri; 1506 + /** The timestamp of the first scrobble. */ 1507 + timestamp?: DateTime; 1508 + } 1509 + 1510 + export interface ScrobbleRecord { 1511 + /** The title of the song. */ 1512 + title: string; 1513 + /** The artist of the song. */ 1514 + artist: string; 1515 + /** The artists of the song with MusicBrainz IDs. */ 1516 + artists?: ArtistMbid[]; 1517 + /** The album artist of the song. */ 1518 + albumArtist: string; 1519 + /** The album of the song. */ 1520 + album: string; 1521 + /** The duration of the song in milliseconds. */ 1522 + duration: number; 1523 + /** The track number of the song in the album. */ 1524 + trackNumber?: number; 1525 + /** The disc number of the song in the album. */ 1526 + discNumber?: number; 1527 + /** The release date of the song. */ 1528 + releaseDate?: DateTime; 1529 + /** The year the song was released. */ 1530 + year?: number; 1531 + /** The genre of the song. */ 1532 + genre?: string; 1533 + /** The tags of the song. */ 1534 + tags?: string[]; 1535 + /** The composer of the song. */ 1536 + composer?: string; 1537 + /** The lyrics of the song. */ 1538 + lyrics?: string; 1539 + /** The copyright message of the song. */ 1540 + copyrightMessage?: string; 1541 + /** Informations about the song */ 1542 + wiki?: string; 1543 + /** The album art of the song. */ 1544 + albumArt?: BlobRef; 1545 + /** The URL of the album art of the song. */ 1546 + albumArtUrl?: Uri; 1547 + /** The YouTube link of the song. */ 1548 + youtubeLink?: Uri; 1549 + /** The Spotify link of the song. */ 1550 + spotifyLink?: Uri; 1551 + /** The Tidal link of the song. */ 1552 + tidalLink?: Uri; 1553 + /** The Apple Music link of the song. */ 1554 + appleMusicLink?: Uri; 1555 + /** The date when the song was created. */ 1556 + createdAt: DateTime; 1557 + /** The MusicBrainz ID of the song. */ 1558 + mbid?: string; 1559 + /** The label of the song. */ 1560 + label?: string; 1561 + /** The International Standard Recording Code (ISRC) of the song. */ 1562 + isrc?: string; 1563 + } 1564 + 1565 + export interface ScrobbleViewBasic { 1566 + /** The unique identifier of the scrobble. */ 1567 + id?: string; 1568 + /** The handle of the user who created the scrobble. */ 1569 + user?: string; 1570 + /** The display name of the user who created the scrobble. */ 1571 + userDisplayName?: string; 1572 + /** The avatar URL of the user who created the scrobble. */ 1573 + userAvatar?: Uri; 1574 + /** The title of the scrobble. */ 1575 + title?: string; 1576 + /** The artist of the song. */ 1577 + artist?: string; 1578 + /** The URI of the artist. */ 1579 + artistUri?: AtUri; 1580 + /** The album of the song. */ 1581 + album?: string; 1582 + /** The URI of the album. */ 1583 + albumUri?: AtUri; 1584 + /** The album art URL of the song. */ 1585 + cover?: Uri; 1586 + /** The timestamp when the scrobble was created. */ 1587 + date?: DateTime; 1588 + /** The URI of the scrobble. */ 1589 + uri?: Uri; 1590 + /** The SHA256 hash of the scrobble data. */ 1591 + sha256?: string; 1592 + liked?: boolean; 1593 + likesCount?: number; 1594 + } 1595 + 1596 + export interface ScrobbleViewDetailed { 1597 + /** The unique identifier of the scrobble. */ 1598 + id?: string; 1599 + /** The handle of the user who created the scrobble. */ 1600 + user?: string; 1601 + /** The title of the scrobble. */ 1602 + title?: string; 1603 + /** The artist of the song. */ 1604 + artist?: string; 1605 + /** The URI of the artist. */ 1606 + artistUri?: AtUri; 1607 + /** The album of the song. */ 1608 + album?: string; 1609 + /** The URI of the album. */ 1610 + albumUri?: AtUri; 1611 + /** The album art URL of the song. */ 1612 + cover?: Uri; 1613 + /** The timestamp when the scrobble was created. */ 1614 + date?: DateTime; 1615 + /** The URI of the scrobble. */ 1616 + uri?: Uri; 1617 + /** The SHA256 hash of the scrobble data. */ 1618 + sha256?: string; 1619 + liked?: boolean; 1620 + likesCount?: number; 1621 + /** The number of listeners */ 1622 + listeners?: number; 1623 + /** The number of scrobbles for this song */ 1624 + scrobbles?: number; 1625 + artists?: ArtistViewBasic[]; 1626 + /** The first scrobble of this song on Rocksky. */ 1627 + firstScrobble?: ScrobbleFirstScrobbleView; 1628 + } 1629 + 1630 + export interface SearchParams { 1631 + /** The search query string */ 1632 + query: string; 1633 + } 1634 + 1635 + export interface SeekParams { 1636 + playerId?: string; 1637 + /** The position in seconds to seek to */ 1638 + position: number; 1639 + } 1640 + 1641 + export interface ShoutAuthor { 1642 + /** The unique identifier of the author. */ 1643 + id?: string; 1644 + /** The decentralized identifier (DID) of the author. */ 1645 + did?: AtIdentifier; 1646 + /** The handle of the author. */ 1647 + handle?: AtIdentifier; 1648 + /** The display name of the author. */ 1649 + displayName?: string; 1650 + /** The URL of the author's avatar image. */ 1651 + avatar?: Uri; 1652 + } 1653 + 1654 + export interface ShoutRecord { 1655 + /** The message of the shout. */ 1656 + message: string; 1657 + /** The date when the shout was created. */ 1658 + createdAt: DateTime; 1659 + parent?: StrongRef; 1660 + subject: StrongRef; 1661 + } 1662 + 1663 + export interface ShoutView { 1664 + /** The unique identifier of the shout. */ 1665 + id?: string; 1666 + /** The content of the shout. */ 1667 + message?: string; 1668 + /** The ID of the parent shout if this is a reply, otherwise null. */ 1669 + parent?: string; 1670 + /** The date and time when the shout was created. */ 1671 + createdAt?: DateTime; 1672 + /** The author of the shout. */ 1673 + author?: ShoutAuthor; 1674 + } 1675 + 1676 + export interface SongFirstScrobbleView { 1677 + /** The handle of the user who first scrobbled this song. */ 1678 + handle?: string; 1679 + /** The avatar URL of the user who first scrobbled this song. */ 1680 + avatar?: Uri; 1681 + /** The timestamp of the first scrobble. */ 1682 + timestamp?: DateTime; 1683 + } 1684 + 1685 + export interface SongRecentListenerView { 1686 + /** The unique identifier of the listener. */ 1687 + id?: string; 1688 + /** The DID of the listener. */ 1689 + did?: string; 1690 + /** The handle of the listener. */ 1691 + handle?: string; 1692 + /** The display name of the listener. */ 1693 + displayName?: string; 1694 + /** The URL of the listener's avatar image. */ 1695 + avatar?: Uri; 1696 + /** The timestamp of the listener's most recent scrobble of this song. */ 1697 + timestamp?: DateTime; 1698 + /** The URI of the listener's most recent scrobble of this song. */ 1699 + scrobbleUri?: AtUri; 1700 + } 1701 + 1702 + export interface SongRecord { 1703 + /** The title of the song. */ 1704 + title: string; 1705 + /** The artist of the song. */ 1706 + artist: string; 1707 + /** The artists of the song with MusicBrainz IDs. */ 1708 + artists?: ArtistMbid[]; 1709 + /** The album artist of the song. */ 1710 + albumArtist: string; 1711 + /** The album of the song. */ 1712 + album: string; 1713 + /** The duration of the song in milliseconds. */ 1714 + duration: number; 1715 + /** The track number of the song in the album. */ 1716 + trackNumber?: number; 1717 + /** The disc number of the song in the album. */ 1718 + discNumber?: number; 1719 + /** The release date of the song. */ 1720 + releaseDate?: DateTime; 1721 + /** The year the song was released. */ 1722 + year?: number; 1723 + /** The genre of the song. */ 1724 + genre?: string; 1725 + /** The tags of the song. */ 1726 + tags?: string[]; 1727 + /** The composer of the song. */ 1728 + composer?: string; 1729 + /** The lyrics of the song. */ 1730 + lyrics?: string; 1731 + /** The copyright message of the song. */ 1732 + copyrightMessage?: string; 1733 + /** Informations about the song */ 1734 + wiki?: string; 1735 + /** The album art of the song. */ 1736 + albumArt?: BlobRef; 1737 + /** The URL of the album art of the song. */ 1738 + albumArtUrl?: Uri; 1739 + /** The YouTube link of the song. */ 1740 + youtubeLink?: Uri; 1741 + /** The Spotify link of the song. */ 1742 + spotifyLink?: Uri; 1743 + /** The Tidal link of the song. */ 1744 + tidalLink?: Uri; 1745 + /** The Apple Music link of the song. */ 1746 + appleMusicLink?: Uri; 1747 + /** The date when the song was created. */ 1748 + createdAt: DateTime; 1749 + /** The MusicBrainz ID of the song. */ 1750 + mbid?: string; 1751 + /** The label of the song. */ 1752 + label?: string; 1753 + /** The International Standard Recording Code (ISRC) of the song. */ 1754 + isrc?: string; 1755 + } 1756 + 1757 + export interface SongViewBasic { 1758 + /** The unique identifier of the song. */ 1759 + id?: string; 1760 + /** The title of the song. */ 1761 + title?: string; 1762 + /** The artist of the song. */ 1763 + artist?: string; 1764 + /** The artist of the album the song belongs to. */ 1765 + albumArtist?: string; 1766 + /** The URL of the album art image. */ 1767 + albumArt?: Uri; 1768 + /** The URI of the song. */ 1769 + uri?: AtUri; 1770 + /** The album of the song. */ 1771 + album?: string; 1772 + /** The duration of the song in milliseconds. */ 1773 + duration?: number; 1774 + /** The track number of the song in the album. */ 1775 + trackNumber?: number; 1776 + /** The disc number of the song in the album. */ 1777 + discNumber?: number; 1778 + /** The number of times the song has been played. */ 1779 + playCount?: number; 1780 + /** The number of unique listeners who have played the song. */ 1781 + uniqueListeners?: number; 1782 + /** The URI of the album the song belongs to. */ 1783 + albumUri?: AtUri; 1784 + /** The URI of the artist of the song. */ 1785 + artistUri?: AtUri; 1786 + /** The SHA256 hash of the song. */ 1787 + sha256?: string; 1788 + /** The MusicBrainz ID of the song. */ 1789 + mbid?: string; 1790 + /** The International Standard Recording Code (ISRC) of the song. */ 1791 + isrc?: string; 1792 + tags?: string[]; 1793 + /** The timestamp when the song was created. */ 1794 + createdAt?: DateTime; 1795 + } 1796 + 1797 + export interface SongViewDetailed { 1798 + /** The unique identifier of the song. */ 1799 + id?: string; 1800 + /** The title of the song. */ 1801 + title?: string; 1802 + /** The artist of the song. */ 1803 + artist?: string; 1804 + /** The artist of the album the song belongs to. */ 1805 + albumArtist?: string; 1806 + /** The URL of the album art image. */ 1807 + albumArt?: Uri; 1808 + /** The URI of the song. */ 1809 + uri?: AtUri; 1810 + /** The album of the song. */ 1811 + album?: string; 1812 + /** The duration of the song in milliseconds. */ 1813 + duration?: number; 1814 + /** The track number of the song in the album. */ 1815 + trackNumber?: number; 1816 + /** The disc number of the song in the album. */ 1817 + discNumber?: number; 1818 + /** The number of times the song has been played. */ 1819 + playCount?: number; 1820 + /** The number of unique listeners who have played the song. */ 1821 + uniqueListeners?: number; 1822 + /** The URI of the album the song belongs to. */ 1823 + albumUri?: AtUri; 1824 + /** The URI of the artist of the song. */ 1825 + artistUri?: AtUri; 1826 + /** The SHA256 hash of the song. */ 1827 + sha256?: string; 1828 + /** The MusicBrainz ID of the song. */ 1829 + mbid?: string; 1830 + /** The International Standard Recording Code (ISRC) of the song. */ 1831 + isrc?: string; 1832 + tags?: string[]; 1833 + /** The timestamp when the song was created. */ 1834 + createdAt?: DateTime; 1835 + artists?: ArtistViewBasic[]; 1836 + /** The first scrobble of this song on Rocksky. */ 1837 + firstScrobble?: SongFirstScrobbleView; 1838 + } 1839 + 1840 + export interface SpotifyTrackView { 1841 + /** The unique identifier of the Spotify track. */ 1842 + id?: string; 1843 + /** The name of the track. */ 1844 + name?: string; 1845 + /** The name of the artist. */ 1846 + artist?: string; 1847 + /** The name of the album. */ 1848 + album?: string; 1849 + /** The duration of the track in milliseconds. */ 1850 + duration?: number; 1851 + /** A URL to a preview of the track. */ 1852 + previewUrl?: string; 1853 + } 1854 + 1855 + export interface StartPlaylistParams { 1856 + /** The URI of the playlist to start */ 1857 + uri: AtUri; 1858 + /** Whether to shuffle the playlist when starting it */ 1859 + shuffle?: boolean; 1860 + /** The position in the playlist to start from, if not specified, starts from the beginning */ 1861 + position?: number; 1862 + } 1863 + 1864 + export interface StatsView { 1865 + /** The total number of scrobbles. */ 1866 + scrobbles?: number; 1867 + /** The total number of unique artists scrobbled. */ 1868 + artists?: number; 1869 + /** The total number of tracks marked as loved. */ 1870 + lovedTracks?: number; 1871 + /** The total number of unique albums scrobbled. */ 1872 + albums?: number; 1873 + /** The total number of unique tracks scrobbled. */ 1874 + tracks?: number; 1875 + } 1876 + 1877 + export interface StatsWrappedAlbum { 1878 + /** The unique identifier of the album. */ 1879 + id?: string; 1880 + /** The title of the album. */ 1881 + title?: string; 1882 + /** The artist of the album. */ 1883 + artist?: string; 1884 + /** The album art URL. */ 1885 + albumArt?: string; 1886 + /** The AT-URI of the album. */ 1887 + uri?: AtUri; 1888 + /** Number of plays in the wrapped period. */ 1889 + playCount?: number; 1890 + } 1891 + 1892 + export interface StatsWrappedArtist { 1893 + /** The unique identifier of the artist. */ 1894 + id?: string; 1895 + /** The name of the artist. */ 1896 + name?: string; 1897 + /** The picture URL of the artist. */ 1898 + picture?: string; 1899 + /** The AT-URI of the artist. */ 1900 + uri?: AtUri; 1901 + /** Number of plays in the wrapped period. */ 1902 + playCount?: number; 1903 + } 1904 + 1905 + export interface StatsWrappedDayCount { 1906 + /** The date (YYYY-MM-DD). */ 1907 + date?: string; 1908 + /** Number of scrobbles on this day. */ 1909 + count?: number; 1910 + } 1911 + 1912 + export interface StatsWrappedGenreCount { 1913 + /** The genre name. */ 1914 + genre?: string; 1915 + /** Number of scrobbles for this genre. */ 1916 + count?: number; 1917 + } 1918 + 1919 + export interface StatsWrappedMilestone { 1920 + /** The title of the track. */ 1921 + trackTitle?: string; 1922 + /** The name of the artist. */ 1923 + artistName?: string; 1924 + /** The timestamp of the scrobble. */ 1925 + timestamp?: DateTime; 1926 + /** AT-URI of the track record, used to build a clickable link to the song page. */ 1927 + trackUri?: AtUri; 1928 + } 1929 + 1930 + export interface StatsWrappedMonthCount { 1931 + /** Month number (1-12). */ 1932 + month?: number; 1933 + /** Number of scrobbles in this month. */ 1934 + count?: number; 1935 + } 1936 + 1937 + export interface StatsWrappedTrack { 1938 + /** The unique identifier of the track. */ 1939 + id?: string; 1940 + /** The title of the track. */ 1941 + title?: string; 1942 + /** The artist of the track. */ 1943 + artist?: string; 1944 + /** The album art URL. */ 1945 + albumArt?: string; 1946 + /** The AT-URI of the track. */ 1947 + uri?: AtUri; 1948 + /** The AT-URI of the artist. */ 1949 + artistUri?: AtUri; 1950 + /** The AT-URI of the album. */ 1951 + albumUri?: AtUri; 1952 + /** Number of plays in the wrapped period. */ 1953 + playCount?: number; 1954 + } 1955 + 1956 + export interface StatsWrappedView { 1957 + /** The year of the wrapped stats. */ 1958 + year?: number; 1959 + /** Total scrobbles in the year. */ 1960 + totalScrobbles?: number; 1961 + /** Total listening time in minutes. */ 1962 + totalListeningTimeMinutes?: number; 1963 + /** Top 5 artists by play count. */ 1964 + topArtists?: StatsWrappedArtist[]; 1965 + /** Top 5 tracks by play count. */ 1966 + topTracks?: StatsWrappedTrack[]; 1967 + /** Top 5 albums by play count. */ 1968 + topAlbums?: StatsWrappedAlbum[]; 1969 + /** Top genres by play count. */ 1970 + topGenres?: StatsWrappedGenreCount[]; 1971 + /** Scrobble counts per month. */ 1972 + scrobblesPerMonth?: StatsWrappedMonthCount[]; 1973 + /** The most active day of the year. */ 1974 + mostActiveDay?: StatsWrappedDayCount; 1975 + /** The most active hour of the day (0-23). */ 1976 + mostActiveHour?: number; 1977 + /** Number of artists heard for the first time this year. */ 1978 + newArtistsCount?: number; 1979 + /** Longest consecutive days streak. */ 1980 + longestStreak?: number; 1981 + /** The first scrobble of the year. */ 1982 + firstScrobble?: StatsWrappedMilestone; 1983 + /** The last scrobble of the year. */ 1984 + lastScrobble?: StatsWrappedMilestone; 1985 + } 1986 + 1987 + export interface StatusRecord { 1988 + /** The track currently being played. */ 1989 + track: ActorTrackView; 1990 + /** When the track started playing. */ 1991 + startedAt: DateTime; 1992 + /** When the status expires. Defaults to startedAt plus track duration plus idle time. */ 1993 + expiresAt?: DateTime; 1994 + } 1995 + 1996 + export interface StrongRef { 1997 + uri: AtUri; 1998 + cid: Cid; 1999 + } 2000 + 2001 + export interface UnfollowAccountOutput { 2002 + subject: ActorProfileViewBasic; 2003 + followers: ActorProfileViewBasic[]; 2004 + /** A cursor value to pass to subsequent calls to get the next page of results. */ 2005 + cursor?: string; 2006 + } 2007 + 2008 + export interface UnfollowAccountParams { 2009 + account: AtIdentifier; 2010 + } 2011 + 2012 + export interface UpdateApikeyInput { 2013 + /** The ID of the API key to update. */ 2014 + id: string; 2015 + /** The new name of the API key. */ 2016 + name: string; 2017 + /** A new description for the API key. */ 2018 + description?: string; 2019 + }
+3 -3
sdk/typescript/src/http.ts
··· 11 11 } from "./types"; 12 12 13 13 export type XrpcCallOptions = RequestOptions & { 14 - params?: Record<string, unknown>; 14 + params?: object; 15 15 body?: unknown; 16 16 requireAuth?: boolean; 17 17 }; ··· 65 65 } 66 66 67 67 export function serializeParams( 68 - params: Record<string, unknown> | undefined, 68 + params: object | undefined, 69 69 ): string { 70 70 if (!params) return ""; 71 71 const usp = new URLSearchParams(); 72 - for (const [k, v] of Object.entries(params)) { 72 + for (const [k, v] of Object.entries(params as Record<string, unknown>)) { 73 73 if (v == null) continue; 74 74 if (Array.isArray(v)) { 75 75 for (const item of v) {
+1 -1
sdk/typescript/src/namespaces/_helpers.ts
··· 5 5 nsid: string, 6 6 method: "GET" | "POST", 7 7 opts?: { 8 - params?: Record<string, unknown>; 8 + params?: object; 9 9 body?: unknown; 10 10 requireAuth?: boolean; 11 11 } & RequestOptions,
+23 -19
sdk/typescript/src/namespaces/actor.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + GetActorAlbumsParams, 3 + GetActorArtistsParams, 4 + GetActorCompatibilityParams, 5 + GetActorLovedSongsParams, 6 + GetActorNeighboursParams, 7 + GetActorPlaylistsParams, 8 + GetActorScrobblesParams, 9 + GetActorSongsParams, 10 + GetProfileParams, 11 + } from "../generated/types"; 2 12 import type { RequestOptions } from "../types"; 13 + import type { Call } from "./_helpers"; 3 14 4 - export type GetProfileParams = { did?: string }; 5 - export type DidParam = { did: string }; 6 - export type ActorPagedParams = DidParam & { 7 - limit?: number; 8 - offset?: number; 9 - }; 10 - export type ActorRangeParams = ActorPagedParams & { 11 - startDate?: string; 12 - endDate?: string; 13 - }; 15 + export type { GetProfileParams }; 16 + export type ActorPagedParams = GetActorScrobblesParams; 17 + export type ActorRangeParams = GetActorAlbumsParams; 14 18 15 19 export class ActorNamespace { 16 20 constructor(private readonly call: Call) {} ··· 22 26 }); 23 27 } 24 28 25 - getActorAlbums<T = unknown>(params: ActorRangeParams, opts?: RequestOptions) { 29 + getActorAlbums<T = unknown>(params: GetActorAlbumsParams, opts?: RequestOptions) { 26 30 return this.call<T>("app.rocksky.actor.getActorAlbums", "GET", { 27 31 params, 28 32 ...opts, 29 33 }); 30 34 } 31 35 32 - getActorArtists<T = unknown>(params: ActorRangeParams, opts?: RequestOptions) { 36 + getActorArtists<T = unknown>(params: GetActorArtistsParams, opts?: RequestOptions) { 33 37 return this.call<T>("app.rocksky.actor.getActorArtists", "GET", { 34 38 params, 35 39 ...opts, 36 40 }); 37 41 } 38 42 39 - getActorSongs<T = unknown>(params: ActorRangeParams, opts?: RequestOptions) { 43 + getActorSongs<T = unknown>(params: GetActorSongsParams, opts?: RequestOptions) { 40 44 return this.call<T>("app.rocksky.actor.getActorSongs", "GET", { 41 45 params, 42 46 ...opts, ··· 44 48 } 45 49 46 50 getActorScrobbles<T = unknown>( 47 - params: ActorPagedParams, 51 + params: GetActorScrobblesParams, 48 52 opts?: RequestOptions, 49 53 ) { 50 54 return this.call<T>("app.rocksky.actor.getActorScrobbles", "GET", { ··· 54 58 } 55 59 56 60 getActorLovedSongs<T = unknown>( 57 - params: ActorPagedParams, 61 + params: GetActorLovedSongsParams, 58 62 opts?: RequestOptions, 59 63 ) { 60 64 return this.call<T>("app.rocksky.actor.getActorLovedSongs", "GET", { ··· 64 68 } 65 69 66 70 getActorPlaylists<T = unknown>( 67 - params: ActorPagedParams, 71 + params: GetActorPlaylistsParams, 68 72 opts?: RequestOptions, 69 73 ) { 70 74 return this.call<T>("app.rocksky.actor.getActorPlaylists", "GET", { ··· 73 77 }); 74 78 } 75 79 76 - getActorNeighbours<T = unknown>(params: DidParam, opts?: RequestOptions) { 80 + getActorNeighbours<T = unknown>(params: GetActorNeighboursParams, opts?: RequestOptions) { 77 81 return this.call<T>("app.rocksky.actor.getActorNeighbours", "GET", { 78 82 params, 79 83 ...opts, 80 84 }); 81 85 } 82 86 83 - getActorCompatibility<T = unknown>(params: DidParam, opts?: RequestOptions) { 87 + getActorCompatibility<T = unknown>(params: GetActorCompatibilityParams, opts?: RequestOptions) { 84 88 return this.call<T>("app.rocksky.actor.getActorCompatibility", "GET", { 85 89 params, 86 90 ...opts,
+9 -9
sdk/typescript/src/namespaces/album.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + GetAlbumParams, 3 + GetAlbumsParams, 4 + GetAlbumTracksParams, 5 + } from "../generated/types"; 2 6 import type { RequestOptions } from "../types"; 7 + import type { Call } from "./_helpers"; 3 8 4 - export type UriParam = { uri: string }; 5 - export type GetAlbumsParams = { 6 - limit?: number; 7 - offset?: number; 8 - genre?: string; 9 - }; 9 + export type { GetAlbumsParams }; 10 10 11 11 export class AlbumNamespace { 12 12 constructor(private readonly call: Call) {} 13 13 14 - getAlbum<T = unknown>(params: UriParam, opts?: RequestOptions) { 14 + getAlbum<T = unknown>(params: GetAlbumParams, opts?: RequestOptions) { 15 15 return this.call<T>("app.rocksky.album.getAlbum", "GET", { 16 16 params, 17 17 ...opts, ··· 25 25 }); 26 26 } 27 27 28 - getAlbumTracks<T = unknown>(params: UriParam, opts?: RequestOptions) { 28 + getAlbumTracks<T = unknown>(params: GetAlbumTracksParams, opts?: RequestOptions) { 29 29 return this.call<T>("app.rocksky.album.getAlbumTracks", "GET", { 30 30 params, 31 31 ...opts,
+9 -9
sdk/typescript/src/namespaces/apikey.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + CreateApikeyInput, 3 + GetApikeysParams, 4 + RemoveApikeyParams, 5 + UpdateApikeyInput, 6 + } from "../generated/types"; 2 7 import type { RequestOptions } from "../types"; 8 + import type { Call } from "./_helpers"; 3 9 4 - export type ListApikeysParams = { limit?: number; offset?: number }; 5 - export type CreateApikeyInput = { name: string; description?: string }; 6 - export type UpdateApikeyInput = { 7 - id: string; 8 - name: string; 9 - description?: string; 10 - }; 11 - export type RemoveApikeyParams = { id: string }; 10 + export type { CreateApikeyInput, UpdateApikeyInput }; 11 + export type ListApikeysParams = GetApikeysParams; 12 12 13 13 export class ApikeyNamespace { 14 14 constructor(private readonly call: Call) {}
+15 -21
sdk/typescript/src/namespaces/artist.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + GetArtistAlbumsParams, 3 + GetArtistListenersParams, 4 + GetArtistParams, 5 + GetArtistRecentListenersParams, 6 + GetArtistsParams, 7 + GetArtistTracksParams, 8 + } from "../generated/types"; 2 9 import type { RequestOptions } from "../types"; 10 + import type { Call } from "./_helpers"; 3 11 4 - export type UriParam = { uri: string }; 5 - export type ArtistListenersParams = UriParam & { 6 - limit?: number; 7 - offset?: number; 8 - }; 9 - export type GetArtistsParams = { 10 - limit?: number; 11 - offset?: number; 12 - names?: string; 13 - genre?: string; 14 - }; 15 - export type GetArtistTracksParams = { 16 - uri?: string; 17 - limit?: number; 18 - offset?: number; 19 - }; 12 + export type { GetArtistsParams, GetArtistTracksParams }; 13 + export type ArtistListenersParams = GetArtistListenersParams; 20 14 21 15 export class ArtistNamespace { 22 16 constructor(private readonly call: Call) {} 23 17 24 - getArtist<T = unknown>(params: UriParam, opts?: RequestOptions) { 18 + getArtist<T = unknown>(params: GetArtistParams, opts?: RequestOptions) { 25 19 return this.call<T>("app.rocksky.artist.getArtist", "GET", { 26 20 params, 27 21 ...opts, ··· 35 29 }); 36 30 } 37 31 38 - getArtistAlbums<T = unknown>(params: UriParam, opts?: RequestOptions) { 32 + getArtistAlbums<T = unknown>(params: GetArtistAlbumsParams, opts?: RequestOptions) { 39 33 return this.call<T>("app.rocksky.artist.getArtistAlbums", "GET", { 40 34 params, 41 35 ...opts, ··· 53 47 } 54 48 55 49 getArtistListeners<T = unknown>( 56 - params: ArtistListenersParams, 50 + params: GetArtistListenersParams, 57 51 opts?: RequestOptions, 58 52 ) { 59 53 return this.call<T>("app.rocksky.artist.getArtistListeners", "GET", { ··· 63 57 } 64 58 65 59 getArtistRecentListeners<T = unknown>( 66 - params: ArtistListenersParams, 60 + params: GetArtistRecentListenersParams, 67 61 opts?: RequestOptions, 68 62 ) { 69 63 return this.call<T>("app.rocksky.artist.getArtistRecentListeners", "GET", {
+10 -19
sdk/typescript/src/namespaces/charts.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + GetScrobblesChartParams, 3 + GetTopArtistsParams, 4 + GetTopTracksParams, 5 + } from "../generated/types"; 2 6 import type { RequestOptions } from "../types"; 7 + import type { Call } from "./_helpers"; 3 8 4 - export type ScrobblesChartParams = { 5 - did?: string; 6 - artisturi?: string; 7 - albumuri?: string; 8 - songuri?: string; 9 - genre?: string; 10 - from?: string; 11 - to?: string; 12 - }; 13 - 14 - export type TopChartParams = { 15 - limit?: number; 16 - offset?: number; 17 - startDate?: string; 18 - endDate?: string; 19 - }; 9 + export type ScrobblesChartParams = GetScrobblesChartParams; 10 + export type TopChartParams = GetTopArtistsParams; 20 11 21 12 export class ChartsNamespace { 22 13 constructor(private readonly call: Call) {} ··· 31 22 }); 32 23 } 33 24 34 - getTopArtists<T = unknown>(params: TopChartParams = {}, opts?: RequestOptions) { 25 + getTopArtists<T = unknown>(params: GetTopArtistsParams = {}, opts?: RequestOptions) { 35 26 return this.call<T>("app.rocksky.charts.getTopArtists", "GET", { 36 27 params, 37 28 ...opts, 38 29 }); 39 30 } 40 31 41 - getTopTracks<T = unknown>(params: TopChartParams = {}, opts?: RequestOptions) { 32 + getTopTracks<T = unknown>(params: GetTopTracksParams = {}, opts?: RequestOptions) { 42 33 return this.call<T>("app.rocksky.charts.getTopTracks", "GET", { 43 34 params, 44 35 ...opts,
+11 -5
sdk/typescript/src/namespaces/dropbox.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + DownloadFileParams, 3 + GetFilesParams, 4 + GetMetadataParams, 5 + GetTemporaryLinkParams, 6 + } from "../generated/types"; 2 7 import type { RequestOptions } from "../types"; 8 + import type { Call } from "./_helpers"; 3 9 4 10 export class DropboxNamespace { 5 11 constructor(private readonly call: Call) {} 6 12 7 13 getFiles<T = unknown>( 8 - params: { at?: string } = {}, 14 + params: GetFilesParams = {}, 9 15 opts?: RequestOptions, 10 16 ) { 11 17 return this.call<T>("app.rocksky.dropbox.getFiles", "GET", { ··· 15 21 }); 16 22 } 17 23 18 - getMetadata<T = unknown>(params: { path: string }, opts?: RequestOptions) { 24 + getMetadata<T = unknown>(params: GetMetadataParams, opts?: RequestOptions) { 19 25 return this.call<T>("app.rocksky.dropbox.getMetadata", "GET", { 20 26 params, 21 27 requireAuth: true, ··· 24 30 } 25 31 26 32 getTemporaryLink<T = unknown>( 27 - params: { path: string }, 33 + params: GetTemporaryLinkParams, 28 34 opts?: RequestOptions, 29 35 ) { 30 36 return this.call<T>("app.rocksky.dropbox.getTemporaryLink", "GET", { ··· 35 41 } 36 42 37 43 downloadFile<T = unknown>( 38 - params: { fileId: string }, 44 + params: DownloadFileParams, 39 45 opts?: RequestOptions, 40 46 ) { 41 47 return this.call<T>("app.rocksky.dropbox.downloadFile", "GET", {
+22 -16
sdk/typescript/src/namespaces/feed.ts
··· 1 + import type { 2 + GetAlbumRecommendationsParams, 3 + GetArtistRecommendationsParams, 4 + GetFeedGeneratorParams, 5 + GetFeedGeneratorsParams, 6 + GetFeedParams, 7 + GetFeedSkeletonParams, 8 + GetRecommendationsParams, 9 + GetStoriesParams, 10 + SearchParams, 11 + } from "../generated/types"; 12 + import type { RequestOptions } from "../types"; 1 13 import type { Call } from "./_helpers"; 2 - import type { RequestOptions } from "../types"; 3 14 4 - export type RecommendParams = { did: string; limit?: number }; 15 + export type RecommendParams = GetRecommendationsParams; 5 16 6 17 export class FeedNamespace { 7 18 constructor(private readonly call: Call) {} 8 19 9 - search<T = unknown>(params: { query: string }, opts?: RequestOptions) { 20 + search<T = unknown>(params: SearchParams, opts?: RequestOptions) { 10 21 return this.call<T>("app.rocksky.feed.search", "GET", { 11 22 params, 12 23 ...opts, ··· 14 25 } 15 26 16 27 getFeed<T = unknown>( 17 - params: { feed: string; limit?: number; cursor?: string }, 28 + params: GetFeedParams, 18 29 opts?: RequestOptions, 19 30 ) { 20 31 return this.call<T>("app.rocksky.feed.getFeed", "GET", { ··· 24 35 } 25 36 26 37 getFeedGenerators<T = unknown>( 27 - params: { size?: number } = {}, 38 + params: GetFeedGeneratorsParams = {}, 28 39 opts?: RequestOptions, 29 40 ) { 30 41 return this.call<T>("app.rocksky.feed.getFeedGenerators", "GET", { ··· 34 45 } 35 46 36 47 getFeedGenerator<T = unknown>( 37 - params: { feed: string }, 48 + params: GetFeedGeneratorParams, 38 49 opts?: RequestOptions, 39 50 ) { 40 51 return this.call<T>("app.rocksky.feed.getFeedGenerator", "GET", { ··· 50 61 } 51 62 52 63 getFeedSkeleton<T = unknown>( 53 - params: { 54 - feed: string; 55 - limit?: number; 56 - offset?: number; 57 - cursor?: string; 58 - }, 64 + params: GetFeedSkeletonParams, 59 65 opts?: RequestOptions, 60 66 ) { 61 67 return this.call<T>("app.rocksky.feed.getFeedSkeleton", "GET", { ··· 65 71 } 66 72 67 73 getRecommendations<T = unknown>( 68 - params: RecommendParams, 74 + params: GetRecommendationsParams, 69 75 opts?: RequestOptions, 70 76 ) { 71 77 return this.call<T>("app.rocksky.feed.getRecommendations", "GET", { ··· 75 81 } 76 82 77 83 getArtistRecommendations<T = unknown>( 78 - params: RecommendParams, 84 + params: GetArtistRecommendationsParams, 79 85 opts?: RequestOptions, 80 86 ) { 81 87 return this.call<T>("app.rocksky.feed.getArtistRecommendations", "GET", { ··· 85 91 } 86 92 87 93 getAlbumRecommendations<T = unknown>( 88 - params: RecommendParams, 94 + params: GetAlbumRecommendationsParams, 89 95 opts?: RequestOptions, 90 96 ) { 91 97 return this.call<T>("app.rocksky.feed.getAlbumRecommendations", "GET", { ··· 95 101 } 96 102 97 103 getStories<T = unknown>( 98 - params: { size?: number } = {}, 104 + params: GetStoriesParams = {}, 99 105 opts?: RequestOptions, 100 106 ) { 101 107 return this.call<T>("app.rocksky.feed.getStories", "GET", {
+9 -4
sdk/typescript/src/namespaces/googledrive.ts
··· 1 + import type { 2 + DownloadFileParams, 3 + GetFileParams, 4 + GetFilesParams, 5 + } from "../generated/types"; 6 + import type { RequestOptions } from "../types"; 1 7 import type { Call } from "./_helpers"; 2 - import type { RequestOptions } from "../types"; 3 8 4 9 export class GoogleDriveNamespace { 5 10 constructor(private readonly call: Call) {} 6 11 7 - getFile<T = unknown>(params: { fileId: string }, opts?: RequestOptions) { 12 + getFile<T = unknown>(params: GetFileParams, opts?: RequestOptions) { 8 13 return this.call<T>("app.rocksky.googledrive.getFile", "GET", { 9 14 params, 10 15 requireAuth: true, ··· 13 18 } 14 19 15 20 getFiles<T = unknown>( 16 - params: { at?: string } = {}, 21 + params: GetFilesParams = {}, 17 22 opts?: RequestOptions, 18 23 ) { 19 24 return this.call<T>("app.rocksky.googledrive.getFiles", "GET", { ··· 24 29 } 25 30 26 31 downloadFile<T = unknown>( 27 - params: { fileId: string }, 32 + params: DownloadFileParams, 28 33 opts?: RequestOptions, 29 34 ) { 30 35 return this.call<T>("app.rocksky.googledrive.downloadFile", "GET", {
+15 -16
sdk/typescript/src/namespaces/graph.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + FollowAccountParams, 3 + GetFollowersParams, 4 + GetFollowsParams, 5 + GetKnownFollowersParams, 6 + UnfollowAccountParams, 7 + } from "../generated/types"; 2 8 import type { RequestOptions } from "../types"; 9 + import type { Call } from "./_helpers"; 3 10 4 - export type ActorParam = { actor: string }; 5 - export type FollowListParams = ActorParam & { 6 - limit?: number; 7 - cursor?: string; 8 - dids?: string[]; 9 - }; 10 - export type KnownFollowersParams = ActorParam & { 11 - limit?: number; 12 - cursor?: string; 13 - }; 11 + export type FollowListParams = GetFollowersParams; 12 + export type KnownFollowersParams = GetKnownFollowersParams; 14 13 15 14 export class GraphNamespace { 16 15 constructor(private readonly call: Call) {} 17 16 18 17 followAccount<T = unknown>( 19 - params: { account: string }, 18 + params: FollowAccountParams, 20 19 opts?: RequestOptions, 21 20 ) { 22 21 return this.call<T>("app.rocksky.graph.followAccount", "POST", { ··· 27 26 } 28 27 29 28 unfollowAccount<T = unknown>( 30 - params: { account: string }, 29 + params: UnfollowAccountParams, 31 30 opts?: RequestOptions, 32 31 ) { 33 32 return this.call<T>("app.rocksky.graph.unfollowAccount", "POST", { ··· 37 36 }); 38 37 } 39 38 40 - getFollowers<T = unknown>(params: FollowListParams, opts?: RequestOptions) { 39 + getFollowers<T = unknown>(params: GetFollowersParams, opts?: RequestOptions) { 41 40 return this.call<T>("app.rocksky.graph.getFollowers", "GET", { 42 41 params, 43 42 ...opts, 44 43 }); 45 44 } 46 45 47 - getFollows<T = unknown>(params: FollowListParams, opts?: RequestOptions) { 46 + getFollows<T = unknown>(params: GetFollowsParams, opts?: RequestOptions) { 48 47 return this.call<T>("app.rocksky.graph.getFollows", "GET", { 49 48 params, 50 49 ...opts, ··· 52 51 } 53 52 54 53 getKnownFollowers<T = unknown>( 55 - params: KnownFollowersParams, 54 + params: GetKnownFollowersParams, 56 55 opts?: RequestOptions, 57 56 ) { 58 57 return this.call<T>("app.rocksky.graph.getKnownFollowers", "GET", {
+12 -6
sdk/typescript/src/namespaces/like.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + DislikeShoutInput, 3 + DislikeSongInput, 4 + LikeShoutInput, 5 + LikeSongInput, 6 + } from "../generated/types"; 2 7 import type { RequestOptions } from "../types"; 8 + import type { Call } from "./_helpers"; 3 9 4 - export type LikeInput = { uri?: string }; 10 + export type LikeInput = LikeSongInput; 5 11 6 12 export class LikeNamespace { 7 13 constructor(private readonly call: Call) {} 8 14 9 - likeSong<T = unknown>(input: LikeInput = {}, opts?: RequestOptions) { 15 + likeSong<T = unknown>(input: LikeSongInput = {}, opts?: RequestOptions) { 10 16 return this.call<T>("app.rocksky.like.likeSong", "POST", { 11 17 body: input, 12 18 requireAuth: true, ··· 14 20 }); 15 21 } 16 22 17 - dislikeSong<T = unknown>(input: LikeInput = {}, opts?: RequestOptions) { 23 + dislikeSong<T = unknown>(input: DislikeSongInput = {}, opts?: RequestOptions) { 18 24 return this.call<T>("app.rocksky.like.dislikeSong", "POST", { 19 25 body: input, 20 26 requireAuth: true, ··· 22 28 }); 23 29 } 24 30 25 - likeShout<T = unknown>(input: LikeInput = {}, opts?: RequestOptions) { 31 + likeShout<T = unknown>(input: LikeShoutInput = {}, opts?: RequestOptions) { 26 32 return this.call<T>("app.rocksky.like.likeShout", "POST", { 27 33 body: input, 28 34 requireAuth: true, ··· 30 36 }); 31 37 } 32 38 33 - dislikeShout<T = unknown>(input: LikeInput = {}, opts?: RequestOptions) { 39 + dislikeShout<T = unknown>(input: DislikeShoutInput = {}, opts?: RequestOptions) { 34 40 return this.call<T>("app.rocksky.like.dislikeShout", "POST", { 35 41 body: input, 36 42 requireAuth: true,
+3 -7
sdk/typescript/src/namespaces/mirror.ts
··· 1 + import type { PutMirrorSourceInput } from "../generated/types"; 2 + import type { RequestOptions } from "../types"; 1 3 import type { Call } from "./_helpers"; 2 - import type { RequestOptions } from "../types"; 3 4 4 - export type PutMirrorSourceInput = { 5 - provider: string; 6 - enabled?: boolean; 7 - externalUsername?: string; 8 - apiKey?: string; 9 - }; 5 + export type { PutMirrorSourceInput }; 10 6 11 7 export class MirrorNamespace { 12 8 constructor(private readonly call: Call) {}
+25 -27
sdk/typescript/src/namespaces/player.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + AddDirectoryToQueueParams, 3 + AddItemsToQueueParams, 4 + GetCurrentlyPlayingParams, 5 + GetPlaybackQueueParams, 6 + NextParams, 7 + PauseParams, 8 + PlayDirectoryParams, 9 + PlayFileParams, 10 + PlayParams, 11 + PreviousParams, 12 + SeekParams, 13 + } from "../generated/types"; 2 14 import type { RequestOptions } from "../types"; 3 - 4 - type PlayerId = { playerId?: string }; 15 + import type { Call } from "./_helpers"; 5 16 6 17 export class PlayerNamespace { 7 18 constructor(private readonly call: Call) {} 8 19 9 20 getCurrentlyPlaying<T = unknown>( 10 - params: PlayerId & { actor?: string } = {}, 21 + params: GetCurrentlyPlayingParams = {}, 11 22 opts?: RequestOptions, 12 23 ) { 13 24 return this.call<T>("app.rocksky.player.getCurrentlyPlaying", "GET", { ··· 17 28 } 18 29 19 30 getPlaybackQueue<T = unknown>( 20 - params: PlayerId = {}, 31 + params: GetPlaybackQueueParams = {}, 21 32 opts?: RequestOptions, 22 33 ) { 23 34 return this.call<T>("app.rocksky.player.getPlaybackQueue", "GET", { ··· 26 37 }); 27 38 } 28 39 29 - play<T = unknown>(params: PlayerId = {}, opts?: RequestOptions) { 40 + play<T = unknown>(params: PlayParams = {}, opts?: RequestOptions) { 30 41 return this.call<T>("app.rocksky.player.play", "POST", { 31 42 params, 32 43 requireAuth: true, ··· 34 45 }); 35 46 } 36 47 37 - pause<T = unknown>(params: PlayerId = {}, opts?: RequestOptions) { 48 + pause<T = unknown>(params: PauseParams = {}, opts?: RequestOptions) { 38 49 return this.call<T>("app.rocksky.player.pause", "POST", { 39 50 params, 40 51 requireAuth: true, ··· 42 53 }); 43 54 } 44 55 45 - next<T = unknown>(params: PlayerId = {}, opts?: RequestOptions) { 56 + next<T = unknown>(params: NextParams = {}, opts?: RequestOptions) { 46 57 return this.call<T>("app.rocksky.player.next", "POST", { 47 58 params, 48 59 requireAuth: true, ··· 50 61 }); 51 62 } 52 63 53 - previous<T = unknown>(params: PlayerId = {}, opts?: RequestOptions) { 64 + previous<T = unknown>(params: PreviousParams = {}, opts?: RequestOptions) { 54 65 return this.call<T>("app.rocksky.player.previous", "POST", { 55 66 params, 56 67 requireAuth: true, ··· 59 70 } 60 71 61 72 seek<T = unknown>( 62 - params: PlayerId & { position: number }, 73 + params: SeekParams, 63 74 opts?: RequestOptions, 64 75 ) { 65 76 return this.call<T>("app.rocksky.player.seek", "POST", { ··· 70 81 } 71 82 72 83 playFile<T = unknown>( 73 - params: PlayerId & { fileId: string }, 84 + params: PlayFileParams, 74 85 opts?: RequestOptions, 75 86 ) { 76 87 return this.call<T>("app.rocksky.player.playFile", "POST", { ··· 81 92 } 82 93 83 94 playDirectory<T = unknown>( 84 - params: PlayerId & { 85 - directoryId: string; 86 - shuffle?: boolean; 87 - recurse?: boolean; 88 - position?: number; 89 - }, 95 + params: PlayDirectoryParams, 90 96 opts?: RequestOptions, 91 97 ) { 92 98 return this.call<T>("app.rocksky.player.playDirectory", "POST", { ··· 97 103 } 98 104 99 105 addItemsToQueue<T = unknown>( 100 - params: PlayerId & { 101 - items: string[]; 102 - position?: number; 103 - shuffle?: boolean; 104 - }, 106 + params: AddItemsToQueueParams, 105 107 opts?: RequestOptions, 106 108 ) { 107 109 return this.call<T>("app.rocksky.player.addItemsToQueue", "POST", { ··· 112 114 } 113 115 114 116 addDirectoryToQueue<T = unknown>( 115 - params: PlayerId & { 116 - directory: string; 117 - position?: number; 118 - shuffle?: boolean; 119 - }, 117 + params: AddDirectoryToQueueParams, 120 118 opts?: RequestOptions, 121 119 ) { 122 120 return this.call<T>("app.rocksky.player.addDirectoryToQueue", "POST", {
+19 -9
sdk/typescript/src/namespaces/playlist.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + CreatePlaylistParams, 3 + GetPlaylistParams, 4 + GetPlaylistsParams, 5 + InsertDirectoryParams, 6 + InsertFilesParams, 7 + RemovePlaylistParams, 8 + RemoveTrackParams, 9 + StartPlaylistParams, 10 + } from "../generated/types"; 2 11 import type { RequestOptions } from "../types"; 12 + import type { Call } from "./_helpers"; 3 13 4 14 export class PlaylistNamespace { 5 15 constructor(private readonly call: Call) {} 6 16 7 17 getPlaylists<T = unknown>( 8 - params: { limit?: number; offset?: number } = {}, 18 + params: GetPlaylistsParams = {}, 9 19 opts?: RequestOptions, 10 20 ) { 11 21 return this.call<T>("app.rocksky.playlist.getPlaylists", "GET", { ··· 14 24 }); 15 25 } 16 26 17 - getPlaylist<T = unknown>(params: { uri: string }, opts?: RequestOptions) { 27 + getPlaylist<T = unknown>(params: GetPlaylistParams, opts?: RequestOptions) { 18 28 return this.call<T>("app.rocksky.playlist.getPlaylist", "GET", { 19 29 params, 20 30 ...opts, ··· 22 32 } 23 33 24 34 createPlaylist<T = unknown>( 25 - params: { name: string; description?: string }, 35 + params: CreatePlaylistParams, 26 36 opts?: RequestOptions, 27 37 ) { 28 38 return this.call<T>("app.rocksky.playlist.createPlaylist", "POST", { ··· 32 42 }); 33 43 } 34 44 35 - removePlaylist<T = unknown>(params: { uri: string }, opts?: RequestOptions) { 45 + removePlaylist<T = unknown>(params: RemovePlaylistParams, opts?: RequestOptions) { 36 46 return this.call<T>("app.rocksky.playlist.removePlaylist", "POST", { 37 47 params, 38 48 requireAuth: true, ··· 41 51 } 42 52 43 53 startPlaylist<T = unknown>( 44 - params: { uri: string; shuffle?: boolean; position?: number }, 54 + params: StartPlaylistParams, 45 55 opts?: RequestOptions, 46 56 ) { 47 57 return this.call<T>("app.rocksky.playlist.startPlaylist", "POST", { ··· 52 62 } 53 63 54 64 insertDirectory<T = unknown>( 55 - params: { uri: string; directory: string; position?: number }, 65 + params: InsertDirectoryParams, 56 66 opts?: RequestOptions, 57 67 ) { 58 68 return this.call<T>("app.rocksky.playlist.insertDirectory", "POST", { ··· 63 73 } 64 74 65 75 insertFiles<T = unknown>( 66 - params: { uri: string; files: string[]; position?: number }, 76 + params: InsertFilesParams, 67 77 opts?: RequestOptions, 68 78 ) { 69 79 return this.call<T>("app.rocksky.playlist.insertFiles", "POST", { ··· 74 84 } 75 85 76 86 removeTrack<T = unknown>( 77 - params: { uri: string; position: number }, 87 + params: RemoveTrackParams, 78 88 opts?: RequestOptions, 79 89 ) { 80 90 return this.call<T>("app.rocksky.playlist.removeTrack", "POST", {
+8 -34
sdk/typescript/src/namespaces/scrobble.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + CreateScrobbleInput, 3 + GetScrobbleParams, 4 + GetScrobblesParams, 5 + } from "../generated/types"; 2 6 import type { RequestOptions } from "../types"; 3 - 4 - export type CreateScrobbleInput = { 5 - title: string; 6 - artist: string; 7 - album?: string; 8 - duration?: number; 9 - mbId?: string; 10 - isrc?: string; 11 - albumArt?: string; 12 - trackNumber?: number; 13 - releaseDate?: string; 14 - year?: number; 15 - discNumber?: number; 16 - lyrics?: string; 17 - composer?: string; 18 - copyrightMessage?: string; 19 - label?: string; 20 - artistPicture?: string; 21 - spotifyLink?: string; 22 - lastfmLink?: string; 23 - tidalLink?: string; 24 - appleMusicLink?: string; 25 - youtubeLink?: string; 26 - deezerLink?: string; 27 - timestamp?: number; 28 - }; 7 + import type { Call } from "./_helpers"; 29 8 30 - export type GetScrobblesParams = { 31 - did?: string; 32 - following?: boolean; 33 - limit?: number; 34 - offset?: number; 35 - }; 9 + export type { CreateScrobbleInput, GetScrobblesParams }; 36 10 37 11 export class ScrobbleNamespace { 38 12 constructor(private readonly call: Call) {} ··· 48 22 }); 49 23 } 50 24 51 - getScrobble<T = unknown>(params: { uri: string }, opts?: RequestOptions) { 25 + getScrobble<T = unknown>(params: GetScrobbleParams, opts?: RequestOptions) { 52 26 return this.call<T>("app.rocksky.scrobble.getScrobble", "GET", { 53 27 params, 54 28 ...opts,
+21 -12
sdk/typescript/src/namespaces/shout.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + CreateShoutInput, 3 + GetAlbumShoutsParams, 4 + GetArtistShoutsParams, 5 + GetProfileShoutsParams, 6 + GetShoutRepliesParams, 7 + GetTrackShoutsParams, 8 + RemoveShoutParams, 9 + ReplyShoutInput, 10 + ReportShoutInput, 11 + } from "../generated/types"; 2 12 import type { RequestOptions } from "../types"; 3 - 4 - type UriPage = { uri: string; limit?: number; offset?: number }; 13 + import type { Call } from "./_helpers"; 5 14 6 15 export class ShoutNamespace { 7 16 constructor(private readonly call: Call) {} 8 17 9 18 createShout<T = unknown>( 10 - input: { message?: string } = {}, 19 + input: CreateShoutInput = {}, 11 20 opts?: RequestOptions, 12 21 ) { 13 22 return this.call<T>("app.rocksky.shout.createShout", "POST", { ··· 18 27 } 19 28 20 29 replyShout<T = unknown>( 21 - input: { shoutId: string; message: string }, 30 + input: ReplyShoutInput, 22 31 opts?: RequestOptions, 23 32 ) { 24 33 return this.call<T>("app.rocksky.shout.replyShout", "POST", { ··· 29 38 } 30 39 31 40 reportShout<T = unknown>( 32 - input: { shoutId: string; reason?: string }, 41 + input: ReportShoutInput, 33 42 opts?: RequestOptions, 34 43 ) { 35 44 return this.call<T>("app.rocksky.shout.reportShout", "POST", { ··· 39 48 }); 40 49 } 41 50 42 - removeShout<T = unknown>(params: { id: string }, opts?: RequestOptions) { 51 + removeShout<T = unknown>(params: RemoveShoutParams, opts?: RequestOptions) { 43 52 return this.call<T>("app.rocksky.shout.removeShout", "POST", { 44 53 params, 45 54 requireAuth: true, ··· 47 56 }); 48 57 } 49 58 50 - getShoutReplies<T = unknown>(params: UriPage, opts?: RequestOptions) { 59 + getShoutReplies<T = unknown>(params: GetShoutRepliesParams, opts?: RequestOptions) { 51 60 return this.call<T>("app.rocksky.shout.getShoutReplies", "GET", { 52 61 params, 53 62 ...opts, ··· 55 64 } 56 65 57 66 getProfileShouts<T = unknown>( 58 - params: { did: string; limit?: number; offset?: number }, 67 + params: GetProfileShoutsParams, 59 68 opts?: RequestOptions, 60 69 ) { 61 70 return this.call<T>("app.rocksky.shout.getProfileShouts", "GET", { ··· 65 74 } 66 75 67 76 getTrackShouts<T = unknown>( 68 - params: { uri: string }, 77 + params: GetTrackShoutsParams, 69 78 opts?: RequestOptions, 70 79 ) { 71 80 return this.call<T>("app.rocksky.shout.getTrackShouts", "GET", { ··· 74 83 }); 75 84 } 76 85 77 - getArtistShouts<T = unknown>(params: UriPage, opts?: RequestOptions) { 86 + getArtistShouts<T = unknown>(params: GetArtistShoutsParams, opts?: RequestOptions) { 78 87 return this.call<T>("app.rocksky.shout.getArtistShouts", "GET", { 79 88 params, 80 89 ...opts, 81 90 }); 82 91 } 83 92 84 - getAlbumShouts<T = unknown>(params: UriPage, opts?: RequestOptions) { 93 + getAlbumShouts<T = unknown>(params: GetAlbumShoutsParams, opts?: RequestOptions) { 85 94 return this.call<T>("app.rocksky.shout.getAlbumShouts", "GET", { 86 95 params, 87 96 ...opts,
+15 -36
sdk/typescript/src/namespaces/song.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + CreateSongInput, 3 + GetSongParams, 4 + GetSongRecentListenersParams, 5 + GetSongsParams, 6 + MatchSongParams, 7 + } from "../generated/types"; 2 8 import type { RequestOptions } from "../types"; 3 - 4 - export type GetSongParams = { 5 - uri?: string; 6 - mbid?: string; 7 - isrc?: string; 8 - spotifyId?: string; 9 - }; 9 + import type { Call } from "./_helpers"; 10 10 11 - export type GetSongsParams = GetSongParams & { 12 - limit?: number; 13 - offset?: number; 14 - genre?: string; 15 - }; 16 - 17 - export type MatchSongParams = { 18 - title: string; 19 - artist: string; 20 - mbId?: string; 21 - isrc?: string; 22 - }; 23 - 24 - export type CreateSongInput = { 25 - title: string; 26 - artist: string; 27 - albumArtist: string; 28 - album: string; 29 - duration?: number; 30 - mbId?: string; 31 - isrc?: string; 32 - albumArt?: string; 33 - trackNumber?: number; 34 - releaseDate?: string; 35 - year?: number; 36 - discNumber?: number; 37 - lyrics?: string; 11 + export type { 12 + CreateSongInput, 13 + GetSongParams, 14 + GetSongRecentListenersParams, 15 + GetSongsParams, 16 + MatchSongParams, 38 17 }; 39 18 40 19 export class SongNamespace { ··· 55 34 } 56 35 57 36 getSongRecentListeners<T = unknown>( 58 - params: { uri: string; limit?: number; offset?: number }, 37 + params: GetSongRecentListenersParams, 59 38 opts?: RequestOptions, 60 39 ) { 61 40 return this.call<T>("app.rocksky.song.getSongRecentListeners", "GET", {
+7 -3
sdk/typescript/src/namespaces/spotify.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + GetCurrentlyPlayingParams, 3 + SeekParams, 4 + } from "../generated/types"; 2 5 import type { RequestOptions } from "../types"; 6 + import type { Call } from "./_helpers"; 3 7 4 8 export class SpotifyNamespace { 5 9 constructor(private readonly call: Call) {} 6 10 7 11 getCurrentlyPlaying<T = unknown>( 8 - params: { actor?: string } = {}, 12 + params: GetCurrentlyPlayingParams = {}, 9 13 opts?: RequestOptions, 10 14 ) { 11 15 return this.call<T>("app.rocksky.spotify.getCurrentlyPlaying", "GET", { ··· 42 46 }); 43 47 } 44 48 45 - seek<T = unknown>(params: { position: number }, opts?: RequestOptions) { 49 + seek<T = unknown>(params: SeekParams, opts?: RequestOptions) { 46 50 return this.call<T>("app.rocksky.spotify.seek", "POST", { 47 51 params, 48 52 requireAuth: true,
+7 -3
sdk/typescript/src/namespaces/stats.ts
··· 1 - import type { Call } from "./_helpers"; 1 + import type { 2 + GetStatsParams, 3 + GetWrappedParams, 4 + } from "../generated/types"; 2 5 import type { RequestOptions } from "../types"; 6 + import type { Call } from "./_helpers"; 3 7 4 8 export class StatsNamespace { 5 9 constructor(private readonly call: Call) {} 6 10 7 - getStats<T = unknown>(params: { did: string }, opts?: RequestOptions) { 11 + getStats<T = unknown>(params: GetStatsParams, opts?: RequestOptions) { 8 12 return this.call<T>("app.rocksky.stats.getStats", "GET", { 9 13 params, 10 14 ...opts, ··· 12 16 } 13 17 14 18 getWrapped<T = unknown>( 15 - params: { did: string; year?: number }, 19 + params: GetWrappedParams, 16 20 opts?: RequestOptions, 17 21 ) { 18 22 return this.call<T>("app.rocksky.stats.getWrapped", "GET", {
+83
tools/lexgen/emit-clojure.ts
··· 1 + import type { Registry, NamedType, TypeRef } from "./registry"; 2 + 3 + const HEADER = `;; AUTO-GENERATED FILE -- DO NOT EDIT. 4 + ;; Source: apps/api/lexicons/**/*.json 5 + ;; Regenerate via: bun run lexgen:types 6 + 7 + (ns rocksky.generated.types) 8 + `; 9 + 10 + function cljPrim(name: string): string { 11 + switch (name) { 12 + case "string": 13 + case "datetime": 14 + case "at-uri": 15 + case "uri": 16 + case "at-identifier": 17 + case "did": 18 + case "cid": 19 + case "cid-link": 20 + return ":string"; 21 + case "integer": 22 + return ":int"; 23 + case "boolean": 24 + return ":boolean"; 25 + case "bytes": 26 + return ":bytes"; 27 + case "blob": 28 + return ":BlobRef"; 29 + default: 30 + return ":any"; 31 + } 32 + } 33 + 34 + function cljType(t: TypeRef): string { 35 + switch (t.kind) { 36 + case "primitive": 37 + return cljPrim(t.name); 38 + case "array": 39 + return `[:vector ${cljType(t.items)}]`; 40 + case "ref": 41 + return t.targetId === "unknown" ? ":any" : `:${t.targetId}`; 42 + case "union": 43 + if (t.options.length === 0) return ":any"; 44 + return `[:or ${t.options.map((o) => (o === "unknown" ? ":any" : `:${o}`)).join(" ")}]`; 45 + case "unknown": 46 + return ":any"; 47 + } 48 + } 49 + 50 + function emitEntry(t: NamedType, isFirst: boolean): string { 51 + const lines: string[] = []; 52 + if (t.description) lines.push(` ;; ${t.description.replace(/\n/g, " ")}`); 53 + lines.push(` :${t.name}`); 54 + if (t.fields.length === 0) { 55 + lines.push(` [:map]`); 56 + return lines.join("\n"); 57 + } 58 + lines.push(` [:map`); 59 + for (const f of t.fields) { 60 + if (f.description) lines.push(` ;; ${f.description.replace(/\n/g, " ")}`); 61 + const opt = f.required ? "" : "{:optional true} "; 62 + const fieldKey = `:${f.name}`; 63 + lines.push(` [${fieldKey} ${opt}${cljType(f.type)}]`); 64 + } 65 + lines.push(` ]`); 66 + return lines.join("\n"); 67 + } 68 + 69 + export function emitClojure(reg: Registry): string { 70 + const entries = reg.types.map((t, i) => emitEntry(t, i === 0)); 71 + const body = entries.join("\n"); 72 + return `${HEADER} 73 + (def ^{:doc "Lexicon-derived schemas in malli format. Refs are :TypeName keywords."} 74 + schemas 75 + {${body} 76 + }) 77 + 78 + (defn schema 79 + "Look up a generated schema by keyword." 80 + [k] 81 + (get schemas k)) 82 + `; 83 + }
+92
tools/lexgen/emit-elixir.ts
··· 1 + import type { Registry, NamedType, TypeRef } from "./registry"; 2 + 3 + const HEADER = `# AUTO-GENERATED FILE -- DO NOT EDIT. 4 + # Source: apps/api/lexicons/**/*.json 5 + # Regenerate via: bun run lexgen:types 6 + 7 + defmodule Rocksky.Generated.BlobRef do 8 + @moduledoc "atproto blob reference shape." 9 + @type t :: %__MODULE__{ 10 + type: String.t() | nil, 11 + ref: map() | nil, 12 + mimeType: String.t() | nil, 13 + size: integer() | nil 14 + } 15 + defstruct [:type, :ref, :mimeType, :size] 16 + end 17 + `; 18 + 19 + function exPrim(name: string): string { 20 + switch (name) { 21 + case "string": 22 + case "datetime": 23 + case "at-uri": 24 + case "uri": 25 + case "at-identifier": 26 + case "did": 27 + case "cid": 28 + case "cid-link": 29 + return "String.t()"; 30 + case "integer": 31 + return "integer()"; 32 + case "boolean": 33 + return "boolean()"; 34 + case "bytes": 35 + return "binary()"; 36 + case "blob": 37 + return "Rocksky.Generated.BlobRef.t()"; 38 + default: 39 + return "term()"; 40 + } 41 + } 42 + 43 + function exType(t: TypeRef): string { 44 + switch (t.kind) { 45 + case "primitive": 46 + return exPrim(t.name); 47 + case "array": 48 + return `list(${exType(t.items)})`; 49 + case "ref": 50 + return t.targetId === "unknown" ? "term()" : `Rocksky.Generated.${t.targetId}.t()`; 51 + case "union": 52 + return "term()"; 53 + case "unknown": 54 + return "term()"; 55 + } 56 + } 57 + 58 + function emitModule(t: NamedType): string { 59 + const lines: string[] = []; 60 + lines.push(`defmodule Rocksky.Generated.${t.name} do`); 61 + if (t.description) { 62 + lines.push(` @moduledoc ${JSON.stringify(t.description)}`); 63 + } else { 64 + lines.push(` @moduledoc false`); 65 + } 66 + if (t.fields.length === 0) { 67 + lines.push(` @type t :: %__MODULE__{}`); 68 + lines.push(` defstruct []`); 69 + lines.push(`end`); 70 + return lines.join("\n"); 71 + } 72 + const required = t.fields.filter((f) => f.required); 73 + lines.push(` @type t :: %__MODULE__{`); 74 + const fieldTypes = t.fields.map((f, i) => { 75 + const sep = i === t.fields.length - 1 ? "" : ","; 76 + const ty = exType(f.type) + (f.required ? "" : " | nil"); 77 + return ` ${f.name}: ${ty}${sep}`; 78 + }); 79 + lines.push(fieldTypes.join("\n")); 80 + lines.push(` }`); 81 + const atomList = (names: string[]) => `[${names.map((n) => `:${n}`).join(", ")}]`; 82 + if (required.length > 0) { 83 + lines.push(` @enforce_keys ${atomList(required.map((f) => f.name))}`); 84 + } 85 + lines.push(` defstruct ${atomList(t.fields.map((f) => f.name))}`); 86 + lines.push(`end`); 87 + return lines.join("\n"); 88 + } 89 + 90 + export function emitElixir(reg: Registry): string { 91 + return [HEADER, ...reg.types.map(emitModule)].join("\n\n") + "\n"; 92 + }
+109
tools/lexgen/emit-gleam.ts
··· 1 + import type { Registry, NamedType, TypeRef } from "./registry"; 2 + 3 + const HEADER = `// AUTO-GENERATED FILE -- DO NOT EDIT. 4 + // Source: apps/api/lexicons/**/*.json 5 + // Regenerate via: bun run lexgen:types 6 + 7 + import gleam/dynamic.{type Dynamic} 8 + import gleam/option.{type Option} 9 + 10 + pub type BlobRef { 11 + BlobRef( 12 + type_: Option(String), 13 + ref: Option(BlobCidRef), 14 + mime_type: Option(String), 15 + size: Option(Int), 16 + ) 17 + } 18 + 19 + pub type BlobCidRef { 20 + BlobCidRef(link: Option(String)) 21 + } 22 + `; 23 + 24 + const GLEAM_KEYWORDS = new Set([ 25 + "as", "assert", "case", "const", "external", "fn", "if", "import", 26 + "let", "opaque", "panic", "pub", "todo", "type", "use", "echo", 27 + ]); 28 + 29 + function camelToSnake(s: string): string { 30 + return s.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, ""); 31 + } 32 + 33 + function gleamFieldName(camel: string): string { 34 + let snake = camelToSnake(camel); 35 + if (GLEAM_KEYWORDS.has(snake)) snake = snake + "_"; 36 + if (/^[0-9]/.test(snake)) snake = "_" + snake; 37 + return snake; 38 + } 39 + 40 + function gleamPrim(name: string): string { 41 + switch (name) { 42 + case "string": 43 + case "datetime": 44 + case "at-uri": 45 + case "uri": 46 + case "at-identifier": 47 + case "did": 48 + case "cid": 49 + case "cid-link": 50 + return "String"; 51 + case "integer": 52 + return "Int"; 53 + case "boolean": 54 + return "Bool"; 55 + case "bytes": 56 + return "BitArray"; 57 + case "blob": 58 + return "BlobRef"; 59 + default: 60 + return "Dynamic"; 61 + } 62 + } 63 + 64 + function gleamType(t: TypeRef): string { 65 + switch (t.kind) { 66 + case "primitive": 67 + return gleamPrim(t.name); 68 + case "array": 69 + return `List(${gleamType(t.items)})`; 70 + case "ref": 71 + return t.targetId === "unknown" ? "Dynamic" : t.targetId; 72 + case "union": 73 + return "Dynamic"; 74 + case "unknown": 75 + return "Dynamic"; 76 + } 77 + } 78 + 79 + function emitType(t: NamedType): string { 80 + const lines: string[] = []; 81 + if (t.description) lines.push(`/// ${t.description.replace(/\n/g, " ")}`); 82 + lines.push(`pub type ${t.name} {`); 83 + if (t.fields.length === 0) { 84 + lines.push(` ${t.name}`); 85 + lines.push(`}`); 86 + return lines.join("\n"); 87 + } 88 + lines.push(` ${t.name}(`); 89 + for (const f of t.fields) { 90 + const name = gleamFieldName(f.name); 91 + const base = gleamType(f.type); 92 + let ty: string; 93 + if (f.required) { 94 + ty = base; 95 + } else if (f.type.kind === "array") { 96 + ty = base; 97 + } else { 98 + ty = `Option(${base})`; 99 + } 100 + lines.push(` ${name}: ${ty},`); 101 + } 102 + lines.push(` )`); 103 + lines.push(`}`); 104 + return lines.join("\n"); 105 + } 106 + 107 + export function emitGleam(reg: Registry): string { 108 + return [HEADER, ...reg.types.map(emitType)].join("\n\n") + "\n"; 109 + }
+139
tools/lexgen/emit-go.ts
··· 1 + import type { Registry, NamedType, TypeRef } from "./registry"; 2 + 3 + const HEADER = `// Code generated by tools/lexgen — DO NOT EDIT. 4 + // Source: apps/api/lexicons/**/*.json 5 + // Regenerate via: bun run lexgen:types 6 + 7 + package gen 8 + 9 + // BlobRef is the atproto blob reference shape. 10 + type BlobRef struct { 11 + \tType string \`json:"$type,omitempty"\` 12 + \tRef BlobCidRef \`json:"ref,omitempty"\` 13 + \tMimeType string \`json:"mimeType,omitempty"\` 14 + \tSize int \`json:"size,omitempty"\` 15 + } 16 + 17 + type BlobCidRef struct { 18 + \tLink string \`json:"$link,omitempty"\` 19 + } 20 + `; 21 + 22 + const GO_ACRONYMS: Record<string, string> = { 23 + Id: "ID", 24 + Url: "URL", 25 + Uri: "URI", 26 + Did: "DID", 27 + Mbid: "MBID", 28 + Isrc: "ISRC", 29 + Sha256: "SHA256", 30 + Json: "JSON", 31 + Xml: "XML", 32 + Html: "HTML", 33 + Http: "HTTP", 34 + Https: "HTTPS", 35 + Api: "API", 36 + Cid: "CID", 37 + Cors: "CORS", 38 + Css: "CSS", 39 + Csv: "CSV", 40 + Dns: "DNS", 41 + Eof: "EOF", 42 + Guid: "GUID", 43 + Ip: "IP", 44 + Sql: "SQL", 45 + Ssh: "SSH", 46 + Tcp: "TCP", 47 + Tls: "TLS", 48 + Ttl: "TTL", 49 + Udp: "UDP", 50 + Utf8: "UTF8", 51 + Uuid: "UUID", 52 + Yaml: "YAML", 53 + Ms: "MS", 54 + }; 55 + 56 + const ACRONYM_UPPER = new Set(Object.values(GO_ACRONYMS).map((s) => s.toLowerCase())); 57 + 58 + function splitCamel(s: string): string[] { 59 + return s 60 + .replace(/([a-z0-9])([A-Z])/g, "$1 $2") 61 + .replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2") 62 + .split(/[^A-Za-z0-9]+/) 63 + .filter(Boolean); 64 + } 65 + 66 + function pascal(s: string): string { 67 + if (!s) return s; 68 + const segs = splitCamel(s); 69 + return segs 70 + .map((seg) => { 71 + const lower = seg.toLowerCase(); 72 + if (ACRONYM_UPPER.has(lower)) return lower.toUpperCase(); 73 + return lower[0].toUpperCase() + lower.slice(1); 74 + }) 75 + .join(""); 76 + } 77 + 78 + function goPrim(name: string): string { 79 + switch (name) { 80 + case "string": 81 + case "datetime": 82 + case "at-uri": 83 + case "uri": 84 + case "at-identifier": 85 + case "did": 86 + case "cid": 87 + case "cid-link": 88 + return "string"; 89 + case "integer": 90 + return "int"; 91 + case "boolean": 92 + return "bool"; 93 + case "bytes": 94 + return "[]byte"; 95 + case "blob": 96 + return "BlobRef"; 97 + default: 98 + return "any"; 99 + } 100 + } 101 + 102 + function goType(t: TypeRef, inArray = false): string { 103 + switch (t.kind) { 104 + case "primitive": 105 + return goPrim(t.name); 106 + case "array": 107 + return "[]" + goType(t.items, true); 108 + case "ref": { 109 + if (t.targetId === "unknown") return "any"; 110 + return inArray ? t.targetId : "*" + t.targetId; 111 + } 112 + case "union": 113 + return "any"; 114 + case "unknown": 115 + return "any"; 116 + } 117 + } 118 + 119 + function jsonTag(name: string): string { 120 + return `\`json:"${name},omitempty"\``; 121 + } 122 + 123 + function emitStruct(t: NamedType): string { 124 + const lines: string[] = []; 125 + if (t.description) lines.push(`// ${t.name} ${t.description.replace(/\n/g, " ")}`); 126 + lines.push(`type ${t.name} struct {`); 127 + for (const f of t.fields) { 128 + if (f.description) lines.push(`\t// ${f.description.replace(/\n/g, " ")}`); 129 + const goName = pascal(f.name); 130 + const ty = goType(f.type); 131 + lines.push(`\t${goName} ${ty} ${jsonTag(f.name)}`); 132 + } 133 + lines.push("}"); 134 + return lines.join("\n"); 135 + } 136 + 137 + export function emitGo(reg: Registry): string { 138 + return [HEADER, ...reg.types.map(emitStruct)].join("\n\n") + "\n"; 139 + }
+105
tools/lexgen/emit-kotlin.ts
··· 1 + import type { Registry, NamedType, TypeRef } from "./registry"; 2 + 3 + const HEADER = `// AUTO-GENERATED FILE — DO NOT EDIT. 4 + // Source: apps/api/lexicons/**/*.json 5 + // Regenerate via: bun run lexgen:types 6 + 7 + package app.rocksky.generated 8 + 9 + import kotlinx.serialization.SerialName 10 + import kotlinx.serialization.Serializable 11 + import kotlinx.serialization.json.JsonElement 12 + 13 + @Serializable 14 + public data class BlobRef( 15 + @SerialName("\\$type") public val type: String? = null, 16 + public val ref: BlobCidRef? = null, 17 + @SerialName("mimeType") public val mimeType: String? = null, 18 + public val size: Int? = null, 19 + ) 20 + 21 + @Serializable 22 + public data class BlobCidRef( 23 + @SerialName("\\$link") public val link: String? = null, 24 + ) 25 + `; 26 + 27 + const KOTLIN_KEYWORDS = new Set([ 28 + "as", "break", "class", "continue", "do", "else", "false", "for", "fun", 29 + "if", "in", "interface", "is", "null", "object", "package", "return", 30 + "super", "this", "throw", "true", "try", "typealias", "typeof", "val", 31 + "var", "when", "while", 32 + ]); 33 + 34 + function kotlinField(name: string): string { 35 + if (KOTLIN_KEYWORDS.has(name)) return name + "_"; 36 + return name; 37 + } 38 + 39 + function kotlinPrim(name: string): string { 40 + switch (name) { 41 + case "string": 42 + case "datetime": 43 + case "at-uri": 44 + case "uri": 45 + case "at-identifier": 46 + case "did": 47 + case "cid": 48 + case "cid-link": 49 + return "String"; 50 + case "integer": 51 + return "Int"; 52 + case "boolean": 53 + return "Boolean"; 54 + case "bytes": 55 + return "ByteArray"; 56 + case "blob": 57 + return "BlobRef"; 58 + default: 59 + return "JsonElement"; 60 + } 61 + } 62 + 63 + function kotlinType(t: TypeRef): string { 64 + switch (t.kind) { 65 + case "primitive": 66 + return kotlinPrim(t.name); 67 + case "array": 68 + return `List<${kotlinType(t.items)}>`; 69 + case "ref": 70 + return t.targetId === "unknown" ? "JsonElement" : t.targetId; 71 + case "union": 72 + return "JsonElement"; 73 + case "unknown": 74 + return "JsonElement"; 75 + } 76 + } 77 + 78 + function emitDataClass(t: NamedType): string { 79 + const lines: string[] = []; 80 + if (t.description) lines.push(`/** ${t.description.replace(/\*\//g, "*\\/").replace(/\n/g, " ")} */`); 81 + lines.push(`@Serializable`); 82 + if (t.fields.length === 0) { 83 + lines.push(`public class ${t.name}`); 84 + return lines.join("\n"); 85 + } 86 + lines.push(`public data class ${t.name}(`); 87 + const fieldLines: string[] = []; 88 + const orderedFields = [...t.fields].sort((a, b) => Number(b.required) - Number(a.required)); 89 + for (const f of orderedFields) { 90 + const safeName = kotlinField(f.name); 91 + const ty = kotlinType(f.type); 92 + const doc = f.description ? ` /** ${f.description.replace(/\*\//g, "*\\/").replace(/\n/g, " ")} */\n` : ""; 93 + const ann = safeName !== f.name || /[A-Z]/.test(f.name) ? `@SerialName("${f.name}") ` : ""; 94 + const nullable = f.required ? "" : "?"; 95 + const defaultV = f.required ? "" : " = null"; 96 + fieldLines.push(`${doc} ${ann}public val ${safeName}: ${ty}${nullable}${defaultV},`); 97 + } 98 + lines.push(fieldLines.join("\n")); 99 + lines.push(`)`); 100 + return lines.join("\n"); 101 + } 102 + 103 + export function emitKotlin(reg: Registry): string { 104 + return [HEADER, ...reg.types.map(emitDataClass)].join("\n\n") + "\n"; 105 + }
+134
tools/lexgen/emit-python-pydantic.ts
··· 1 + import type { Registry, NamedType, TypeRef } from "./registry"; 2 + 3 + const HEADER = `"""AUTO-GENERATED FILE -- DO NOT EDIT. 4 + 5 + Source: apps/api/lexicons/**/*.json 6 + Regenerate via: bun run lexgen:types 7 + """ 8 + from __future__ import annotations 9 + 10 + from datetime import datetime 11 + from typing import Any 12 + 13 + from pydantic import BaseModel, ConfigDict, Field 14 + 15 + 16 + def _camel(name: str) -> str: 17 + head, *tail = name.split("_") 18 + return head + "".join(part.title() for part in tail) 19 + 20 + 21 + class RockskyModel(BaseModel): 22 + """Base model used by every generated SDK type. 23 + 24 + Accepts both camelCase (alias) and snake_case (field name) input, preserves 25 + unknown fields ("extra=allow"), and never crashes on a missing key. 26 + """ 27 + 28 + model_config = ConfigDict( 29 + alias_generator=_camel, 30 + populate_by_name=True, 31 + extra="allow", 32 + str_strip_whitespace=True, 33 + ) 34 + 35 + 36 + class BlobRef(RockskyModel): 37 + """atproto blob reference shape.""" 38 + 39 + type: str | None = Field(default=None, alias="$type") 40 + ref: dict[str, Any] | None = None 41 + mime_type: str | None = None 42 + size: int | None = None 43 + `; 44 + 45 + const PY_KEYWORDS = new Set([ 46 + "False", "None", "True", "and", "as", "assert", "async", "await", "break", 47 + "class", "continue", "def", "del", "elif", "else", "except", "finally", 48 + "for", "from", "global", "if", "import", "in", "is", "lambda", "nonlocal", 49 + "not", "or", "pass", "raise", "return", "try", "while", "with", "yield", 50 + ]); 51 + 52 + function camelToSnake(s: string): string { 53 + return s.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, ""); 54 + } 55 + 56 + function pySnake(name: string): string { 57 + let snake = camelToSnake(name); 58 + if (PY_KEYWORDS.has(snake)) snake = snake + "_"; 59 + if (/^[0-9]/.test(snake)) snake = "_" + snake; 60 + return snake; 61 + } 62 + 63 + function pyPrim(name: string): string { 64 + switch (name) { 65 + case "string": 66 + case "at-uri": 67 + case "uri": 68 + case "at-identifier": 69 + case "did": 70 + case "cid": 71 + case "cid-link": 72 + return "str"; 73 + case "datetime": 74 + return "datetime"; 75 + case "integer": 76 + return "int"; 77 + case "boolean": 78 + return "bool"; 79 + case "bytes": 80 + return "bytes"; 81 + case "blob": 82 + return "BlobRef"; 83 + default: 84 + return "Any"; 85 + } 86 + } 87 + 88 + function pyType(t: TypeRef): string { 89 + switch (t.kind) { 90 + case "primitive": 91 + return pyPrim(t.name); 92 + case "array": 93 + return `list[${pyType(t.items)}]`; 94 + case "ref": 95 + return t.targetId === "unknown" ? "Any" : t.targetId; 96 + case "union": { 97 + if (t.options.length === 0) return "Any"; 98 + const opts = t.options.map((o) => (o === "unknown" ? "Any" : o)); 99 + return opts.join(" | "); 100 + } 101 + case "unknown": 102 + return "Any"; 103 + } 104 + } 105 + 106 + function emitClass(t: NamedType): string { 107 + const lines: string[] = []; 108 + lines.push(`class ${t.name}(RockskyModel):`); 109 + if (t.description) { 110 + lines.push(` """${t.description.replace(/"""/g, '\\"\\"\\"')}"""`); 111 + lines.push(""); 112 + } 113 + if (t.fields.length === 0) { 114 + lines.push(` pass`); 115 + return lines.join("\n"); 116 + } 117 + for (const f of t.fields) { 118 + const snake = pySnake(f.name); 119 + const ty = pyType(f.type); 120 + const renameNeeded = snake !== f.name; 121 + if (renameNeeded) { 122 + lines.push(` ${snake}: ${ty} | None = Field(default=None, alias="${f.name}")`); 123 + } else { 124 + lines.push(` ${snake}: ${ty} | None = None`); 125 + } 126 + } 127 + return lines.join("\n"); 128 + } 129 + 130 + export function emitPythonPydantic(reg: Registry): string { 131 + const body = [HEADER, ...reg.types.map(emitClass)].join("\n\n\n"); 132 + const rebuilds = reg.types.map((t) => `${t.name}.model_rebuild()`).join("\n"); 133 + return `${body}\n\n\n${rebuilds}\n`; 134 + }
+105
tools/lexgen/emit-python.ts
··· 1 + import type { Registry, NamedType, TypeRef } from "./registry"; 2 + 3 + const HEADER = `"""AUTO-GENERATED FILE — DO NOT EDIT. 4 + 5 + Source: apps/api/lexicons/**/*.json 6 + Regenerate via: bun run lexgen:types 7 + """ 8 + from __future__ import annotations 9 + 10 + from dataclasses import dataclass, field 11 + from typing import Any, List, Optional, Union 12 + 13 + 14 + @dataclass 15 + class BlobRef: 16 + """atproto blob reference shape.""" 17 + 18 + type: Optional[str] = None 19 + ref: Optional[dict] = None 20 + mimeType: Optional[str] = None 21 + size: Optional[int] = None 22 + `; 23 + 24 + function pyPrim(name: string): string { 25 + switch (name) { 26 + case "string": 27 + case "datetime": 28 + case "at-uri": 29 + case "uri": 30 + case "at-identifier": 31 + case "did": 32 + case "cid": 33 + case "cid-link": 34 + return "str"; 35 + case "integer": 36 + return "int"; 37 + case "boolean": 38 + return "bool"; 39 + case "bytes": 40 + return "bytes"; 41 + case "blob": 42 + return "BlobRef"; 43 + default: 44 + return "Any"; 45 + } 46 + } 47 + 48 + const PY_KEYWORDS = new Set([ 49 + "False", "None", "True", "and", "as", "assert", "async", "await", "break", 50 + "class", "continue", "def", "del", "elif", "else", "except", "finally", 51 + "for", "from", "global", "if", "import", "in", "is", "lambda", "nonlocal", 52 + "not", "or", "pass", "raise", "return", "try", "while", "with", "yield", 53 + ]); 54 + 55 + function pyFieldName(name: string): string { 56 + if (PY_KEYWORDS.has(name)) return name + "_"; 57 + if (/^[0-9]/.test(name)) return "_" + name; 58 + return name; 59 + } 60 + 61 + function pyType(t: TypeRef): string { 62 + switch (t.kind) { 63 + case "primitive": 64 + return pyPrim(t.name); 65 + case "array": 66 + return `List[${pyType(t.items)}]`; 67 + case "ref": 68 + return t.targetId === "unknown" ? "Any" : `"${t.targetId}"`; 69 + case "union": { 70 + if (t.options.length === 0) return "Any"; 71 + const opts = t.options.map((o) => (o === "unknown" ? "Any" : `"${o}"`)); 72 + return `Union[${opts.join(", ")}]`; 73 + } 74 + case "unknown": 75 + return "Any"; 76 + } 77 + } 78 + 79 + function emitDataclass(t: NamedType): string { 80 + const lines: string[] = []; 81 + lines.push(`@dataclass`); 82 + lines.push(`class ${t.name}:`); 83 + if (t.description) { 84 + lines.push(` """${t.description.replace(/"""/g, '\\"\\"\\"')}"""`); 85 + } 86 + const required = t.fields.filter((f) => f.required); 87 + const optional = t.fields.filter((f) => !f.required); 88 + if (required.length === 0 && optional.length === 0) { 89 + lines.push(` pass`); 90 + return lines.join("\n"); 91 + } 92 + for (const f of required) { 93 + const ty = pyType(f.type); 94 + lines.push(` ${pyFieldName(f.name)}: ${ty}`); 95 + } 96 + for (const f of optional) { 97 + const ty = pyType(f.type); 98 + lines.push(` ${pyFieldName(f.name)}: Optional[${ty}] = None`); 99 + } 100 + return lines.join("\n"); 101 + } 102 + 103 + export function emitPython(reg: Registry): string { 104 + return [HEADER, ...reg.types.map(emitDataclass)].join("\n\n\n") + "\n"; 105 + }
+40
tools/lexgen/emit-ruby.ts
··· 1 + import type { Registry, NamedType, TypeRef } from "./registry"; 2 + 3 + const HEADER = `# frozen_string_literal: true 4 + # AUTO-GENERATED FILE -- DO NOT EDIT. 5 + # Source: apps/api/lexicons/**/*.json 6 + # Regenerate via: bun run lexgen:types 7 + 8 + module Rocksky 9 + module Generated 10 + BlobRef = Struct.new(:type, :ref, :mimeType, :size, keyword_init: true) 11 + `; 12 + 13 + const FOOTER = ` end 14 + end 15 + `; 16 + 17 + function commentLines(s: string, indent: string): string { 18 + return s.split(/\n/).map((line) => `${indent}# ${line}`).join("\n"); 19 + } 20 + 21 + function fieldList(t: NamedType): string { 22 + return t.fields.map((f) => `:${f.name}`).join(", "); 23 + } 24 + 25 + function emitStruct(t: NamedType): string { 26 + const lines: string[] = []; 27 + if (t.description) lines.push(commentLines(t.description, " ")); 28 + if (t.fields.length === 0) { 29 + lines.push(` ${t.name} = Struct.new(keyword_init: true)`); 30 + return lines.join("\n"); 31 + } 32 + const fields = fieldList(t); 33 + lines.push(` ${t.name} = Struct.new(${fields}, keyword_init: true)`); 34 + return lines.join("\n"); 35 + } 36 + 37 + export function emitRuby(reg: Registry): string { 38 + void (null as unknown as TypeRef); 39 + return [HEADER, ...reg.types.map(emitStruct), FOOTER].join("\n"); 40 + }
+122
tools/lexgen/emit-rust.ts
··· 1 + import type { Registry, NamedType, TypeRef } from "./registry"; 2 + 3 + const HEADER = `// Code generated by tools/lexgen — DO NOT EDIT. 4 + // Source: apps/api/lexicons/**/*.json 5 + // Regenerate via: bun run lexgen:types 6 + 7 + #![allow(non_snake_case, non_camel_case_types, dead_code, clippy::large_enum_variant)] 8 + 9 + use chrono::{DateTime, Utc}; 10 + use serde::{Deserialize, Serialize}; 11 + use serde_json::Value; 12 + 13 + /// atproto blob reference shape. 14 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 15 + pub struct BlobRef { 16 + #[serde(rename = "$type", default, skip_serializing_if = "Option::is_none")] 17 + pub r#type: Option<String>, 18 + #[serde(default, skip_serializing_if = "Option::is_none")] 19 + pub ref_: Option<BlobCidRef>, 20 + #[serde(default, skip_serializing_if = "Option::is_none")] 21 + pub mime_type: Option<String>, 22 + #[serde(default, skip_serializing_if = "Option::is_none")] 23 + pub size: Option<i64>, 24 + } 25 + 26 + #[derive(Debug, Clone, Serialize, Deserialize, Default)] 27 + pub struct BlobCidRef { 28 + #[serde(rename = "$link", default, skip_serializing_if = "Option::is_none")] 29 + pub link: Option<String>, 30 + } 31 + `; 32 + 33 + function camelToSnake(s: string): string { 34 + return s.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, ""); 35 + } 36 + 37 + const RUST_KEYWORDS = new Set([ 38 + "as", "break", "const", "continue", "crate", "else", "enum", "extern", 39 + "false", "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", 40 + "move", "mut", "pub", "ref", "return", "self", "Self", "static", "struct", 41 + "super", "trait", "true", "type", "unsafe", "use", "where", "while", 42 + "async", "await", "dyn", "abstract", "become", "box", "do", "final", 43 + "macro", "override", "priv", "typeof", "unsized", "virtual", "yield", 44 + ]); 45 + 46 + function rustFieldName(camel: string): string { 47 + let snake = camelToSnake(camel); 48 + if (RUST_KEYWORDS.has(snake)) snake = snake + "_"; 49 + return snake; 50 + } 51 + 52 + function rustPrim(name: string): string { 53 + switch (name) { 54 + case "string": 55 + case "at-uri": 56 + case "uri": 57 + case "at-identifier": 58 + case "did": 59 + case "cid": 60 + case "cid-link": 61 + return "String"; 62 + case "datetime": 63 + return "DateTime<Utc>"; 64 + case "integer": 65 + return "i64"; 66 + case "boolean": 67 + return "bool"; 68 + case "bytes": 69 + return "Vec<u8>"; 70 + case "blob": 71 + return "BlobRef"; 72 + default: 73 + return "Value"; 74 + } 75 + } 76 + 77 + function rustType(t: TypeRef): string { 78 + switch (t.kind) { 79 + case "primitive": 80 + return rustPrim(t.name); 81 + case "array": 82 + return `Vec<${rustType(t.items)}>`; 83 + case "ref": 84 + return t.targetId === "unknown" ? "Value" : t.targetId; 85 + case "union": 86 + return "Value"; 87 + case "unknown": 88 + return "Value"; 89 + } 90 + } 91 + 92 + function emitStruct(t: NamedType): string { 93 + const lines: string[] = []; 94 + if (t.description) lines.push(`/// ${t.description.replace(/\n/g, " ")}`); 95 + lines.push(`#[derive(Debug, Clone, Serialize, Deserialize, Default)]`); 96 + lines.push(`pub struct ${t.name} {`); 97 + for (const f of t.fields) { 98 + if (f.description) lines.push(` /// ${f.description.replace(/\n/g, " ")}`); 99 + const snake = rustFieldName(f.name); 100 + const renameNeeded = snake !== f.name; 101 + const ty = rustType(f.type); 102 + const isArray = f.type.kind === "array"; 103 + if (f.required) { 104 + const tag = renameNeeded ? ` #[serde(rename = "${f.name}")]\n` : ""; 105 + lines.push(`${tag} pub ${snake}: ${ty},`); 106 + } else if (isArray) { 107 + const renamePart = renameNeeded ? `rename = "${f.name}", ` : ""; 108 + lines.push(` #[serde(${renamePart}default, skip_serializing_if = "Vec::is_empty")]`); 109 + lines.push(` pub ${snake}: ${ty},`); 110 + } else { 111 + const renamePart = renameNeeded ? `rename = "${f.name}", ` : ""; 112 + lines.push(` #[serde(${renamePart}default, skip_serializing_if = "Option::is_none")]`); 113 + lines.push(` pub ${snake}: Option<${ty}>,`); 114 + } 115 + } 116 + lines.push(`}`); 117 + return lines.join("\n"); 118 + } 119 + 120 + export function emitRust(reg: Registry): string { 121 + return [HEADER, ...reg.types.map(emitStruct)].join("\n\n") + "\n"; 122 + }
+84
tools/lexgen/emit-typescript.ts
··· 1 + import type { Registry, NamedType, TypeRef } from "./registry"; 2 + 3 + const HEADER = `// AUTO-GENERATED FILE — DO NOT EDIT. 4 + // Source: apps/api/lexicons/**/*.json 5 + // Regenerate via: bun run lexgen:types 6 + 7 + export interface BlobRef { 8 + $type?: "blob"; 9 + ref?: { $link?: string }; 10 + mimeType?: string; 11 + size?: number; 12 + } 13 + 14 + export type CidLink = string; 15 + export type DateTime = string; 16 + export type AtUri = string; 17 + export type AtIdentifier = string; 18 + export type Did = string; 19 + export type Cid = string; 20 + export type Uri = string; 21 + `; 22 + 23 + function tsType(t: TypeRef): string { 24 + switch (t.kind) { 25 + case "primitive": 26 + switch (t.name) { 27 + case "string": 28 + return "string"; 29 + case "integer": 30 + return "number"; 31 + case "boolean": 32 + return "boolean"; 33 + case "bytes": 34 + return "Uint8Array"; 35 + case "blob": 36 + return "BlobRef"; 37 + case "cid-link": 38 + return "CidLink"; 39 + case "cid": 40 + return "Cid"; 41 + case "datetime": 42 + return "DateTime"; 43 + case "at-uri": 44 + return "AtUri"; 45 + case "uri": 46 + return "Uri"; 47 + case "at-identifier": 48 + return "AtIdentifier"; 49 + case "did": 50 + return "Did"; 51 + } 52 + case "array": 53 + return `${tsType(t.items)}[]`; 54 + case "ref": 55 + return t.targetId === "unknown" ? "unknown" : t.targetId; 56 + case "union": 57 + return t.options.length === 0 ? "unknown" : t.options.map((o) => (o === "unknown" ? "unknown" : o)).join(" | "); 58 + case "unknown": 59 + return "unknown"; 60 + } 61 + } 62 + 63 + function jsdoc(desc?: string, indent = " "): string { 64 + if (!desc) return ""; 65 + const clean = desc.replace(/\*\//g, "*\\/").trim(); 66 + return `${indent}/** ${clean} */\n`; 67 + } 68 + 69 + function emitInterface(t: NamedType): string { 70 + const head = jsdoc(t.description, "") + `export interface ${t.name} {\n`; 71 + const body = t.fields 72 + .map((f) => { 73 + const doc = jsdoc(f.description, " "); 74 + const opt = f.required ? "" : "?"; 75 + return `${doc} ${f.name}${opt}: ${tsType(f.type)};`; 76 + }) 77 + .join("\n"); 78 + return head + body + "\n}\n"; 79 + } 80 + 81 + export function emitTypescript(reg: Registry): string { 82 + const parts = [HEADER, ...reg.types.map(emitInterface)]; 83 + return parts.join("\n"); 84 + }
+369
tools/lexgen/generate.ts
··· 1 + #!/usr/bin/env bun 2 + import { readdirSync, readFileSync, statSync, mkdirSync, writeFileSync, existsSync } from "node:fs"; 3 + import { join, dirname, resolve } from "node:path"; 4 + import { fileURLToPath } from "node:url"; 5 + 6 + import { createConsola } from "consola"; 7 + 8 + import { emitTypescript } from "./emit-typescript"; 9 + import { emitGo } from "./emit-go"; 10 + import { emitPython } from "./emit-python"; 11 + import { emitPythonPydantic } from "./emit-python-pydantic"; 12 + import { emitRust } from "./emit-rust"; 13 + import { emitKotlin } from "./emit-kotlin"; 14 + import { emitRuby } from "./emit-ruby"; 15 + import { emitElixir } from "./emit-elixir"; 16 + import { emitClojure } from "./emit-clojure"; 17 + import { emitGleam } from "./emit-gleam"; 18 + 19 + import type { Registry, NamedType, Field, TypeRef } from "./registry"; 20 + 21 + const log = createConsola({ 22 + level: 4, 23 + formatOptions: { date: false, colors: true, compact: false }, 24 + }); 25 + const tag = (name: string) => log.withTag(name); 26 + 27 + const HERE = dirname(fileURLToPath(import.meta.url)); 28 + const REPO = resolve(HERE, "..", ".."); 29 + const LEX_DIR = join(REPO, "apps", "api", "lexicons"); 30 + 31 + function walk(dir: string, out: string[] = []): string[] { 32 + for (const name of readdirSync(dir)) { 33 + const p = join(dir, name); 34 + const s = statSync(p); 35 + if (s.isDirectory()) walk(p, out); 36 + else if (name.endsWith(".json")) out.push(p); 37 + } 38 + return out; 39 + } 40 + 41 + function pascal(s: string): string { 42 + return s 43 + .replace(/[^A-Za-z0-9]+/g, " ") 44 + .split(/\s+/) 45 + .filter(Boolean) 46 + .map((p) => p[0].toUpperCase() + p.slice(1)) 47 + .join(""); 48 + } 49 + 50 + function nsidNs(nsid: string): string { 51 + const segs = nsid.split("."); 52 + let last = segs[segs.length - 1]; 53 + if ((last === "defs" || last === "def") && segs.length >= 2) { 54 + last = segs[segs.length - 2]; 55 + } 56 + return pascal(last); 57 + } 58 + 59 + function typeNameFor( 60 + nsid: string, 61 + defName: string, 62 + kind: "record" | "object" | "params", 63 + mainSuffix?: string, 64 + ): string { 65 + const ns = nsidNs(nsid); 66 + if (defName === "main") { 67 + if (kind === "record") return ns + "Record"; 68 + if (kind === "params") return ns + (mainSuffix ?? "Params"); 69 + return ns + (mainSuffix ?? ""); 70 + } 71 + const dn = pascal(defName); 72 + return dn.toLowerCase().startsWith(ns.toLowerCase()) ? dn : ns + dn; 73 + } 74 + 75 + function resolveRef(currentNsid: string, ref: string): { nsid: string; def: string } { 76 + const [maybeNsid, defPart] = ref.split("#"); 77 + const nsid = maybeNsid && maybeNsid.length > 0 ? maybeNsid : currentNsid; 78 + const def = defPart && defPart.length > 0 ? defPart : "main"; 79 + return { nsid, def }; 80 + } 81 + 82 + const FORMAT_PRIM: Record<string, TypeRef> = { 83 + datetime: { kind: "primitive", name: "datetime" }, 84 + "at-uri": { kind: "primitive", name: "at-uri" }, 85 + uri: { kind: "primitive", name: "uri" }, 86 + "at-identifier": { kind: "primitive", name: "at-identifier" }, 87 + did: { kind: "primitive", name: "did" }, 88 + cid: { kind: "primitive", name: "cid" }, 89 + handle: { kind: "primitive", name: "at-identifier" }, 90 + }; 91 + 92 + interface ParseCtx { 93 + nsid: string; 94 + parentTypeName: string; 95 + hoist: (name: string, t: NamedType) => void; 96 + refs: Set<string>; 97 + refMap: Map<string, string>; 98 + } 99 + 100 + function parseTypeRef(node: any, ctx: ParseCtx, fieldNameForHoist?: string): TypeRef { 101 + if (!node || typeof node !== "object") return { kind: "unknown" }; 102 + switch (node.type) { 103 + case "string": { 104 + if (node.knownValues && Array.isArray(node.knownValues)) { 105 + return { kind: "primitive", name: "string" }; 106 + } 107 + if (node.format && FORMAT_PRIM[node.format]) { 108 + return FORMAT_PRIM[node.format]; 109 + } 110 + return { kind: "primitive", name: "string" }; 111 + } 112 + case "integer": 113 + return { kind: "primitive", name: "integer" }; 114 + case "boolean": 115 + return { kind: "primitive", name: "boolean" }; 116 + case "bytes": 117 + return { kind: "primitive", name: "bytes" }; 118 + case "blob": 119 + return { kind: "primitive", name: "blob" }; 120 + case "cid-link": 121 + return { kind: "primitive", name: "cid-link" }; 122 + case "unknown": 123 + return { kind: "unknown" }; 124 + case "array": 125 + return { kind: "array", items: parseTypeRef(node.items, ctx, fieldNameForHoist) }; 126 + case "ref": { 127 + const r = resolveRef(ctx.nsid, node.ref); 128 + const id = `${r.nsid}#${r.def}`; 129 + ctx.refs.add(id); 130 + return { kind: "ref", targetId: id }; 131 + } 132 + case "union": { 133 + const ids: string[] = []; 134 + for (const ref of node.refs ?? []) { 135 + const r = resolveRef(ctx.nsid, ref); 136 + const id = `${r.nsid}#${r.def}`; 137 + ctx.refs.add(id); 138 + ids.push(id); 139 + } 140 + return { kind: "union", options: ids }; 141 + } 142 + case "object": { 143 + const hoistName = ctx.parentTypeName + (fieldNameForHoist ? pascal(fieldNameForHoist) : "Object"); 144 + const nested = buildNamedType(hoistName, node, ctx); 145 + ctx.hoist(hoistName, nested); 146 + return { kind: "ref", targetId: `__inline:${hoistName}` }; 147 + } 148 + default: 149 + return { kind: "unknown" }; 150 + } 151 + } 152 + 153 + function buildNamedType(name: string, node: any, ctx: ParseCtx): NamedType { 154 + const required: string[] = node.required ?? []; 155 + const fields: Field[] = []; 156 + const props = node.properties ?? {}; 157 + for (const [propName, propNode] of Object.entries<any>(props)) { 158 + const childCtx: ParseCtx = { ...ctx, parentTypeName: name }; 159 + const t = parseTypeRef(propNode, childCtx, propName); 160 + fields.push({ 161 + name: propName, 162 + description: propNode.description, 163 + required: required.includes(propName), 164 + type: t, 165 + }); 166 + } 167 + return { name, description: node.description, fields }; 168 + } 169 + 170 + function buildRegistry(): Registry { 171 + const files = walk(LEX_DIR).sort(); 172 + const types: NamedType[] = []; 173 + const refMap = new Map<string, string>(); 174 + const refs = new Set<string>(); 175 + 176 + const hoist = (name: string, t: NamedType) => { 177 + if (!types.find((x) => x.name === name)) types.push(t); 178 + }; 179 + 180 + const recordDef = (nsid: string, defName: string, name: string) => { 181 + refMap.set(`${nsid}#${defName}`, name); 182 + }; 183 + 184 + for (const f of files) { 185 + const raw = readFileSync(f, "utf8"); 186 + let doc: any; 187 + try { 188 + doc = JSON.parse(raw); 189 + } catch { 190 + continue; 191 + } 192 + const nsid: string = doc.id; 193 + if (!nsid) continue; 194 + const defs = doc.defs ?? {}; 195 + for (const [defName, def] of Object.entries<any>(defs)) { 196 + const baseCtx = { nsid, refs, refMap }; 197 + switch (def.type) { 198 + case "record": { 199 + const name = typeNameFor(nsid, defName, "record"); 200 + recordDef(nsid, defName, name); 201 + const ctx: ParseCtx = { ...baseCtx, parentTypeName: name, hoist }; 202 + const t = buildNamedType(name, def.record ?? {}, ctx); 203 + types.push(t); 204 + break; 205 + } 206 + case "object": { 207 + const name = typeNameFor(nsid, defName, "object"); 208 + recordDef(nsid, defName, name); 209 + const ctx: ParseCtx = { ...baseCtx, parentTypeName: name, hoist }; 210 + const t = buildNamedType(name, def, ctx); 211 + types.push(t); 212 + break; 213 + } 214 + case "query": 215 + case "procedure": 216 + case "subscription": { 217 + const paramsName = typeNameFor(nsid, "main", "params", "Params"); 218 + if (def.parameters && def.parameters.properties) { 219 + const ctx: ParseCtx = { ...baseCtx, parentTypeName: paramsName, hoist }; 220 + const t = buildNamedType(paramsName, def.parameters, ctx); 221 + types.push(t); 222 + } 223 + if (def.type === "procedure" && def.input?.schema?.type === "object") { 224 + const name = nsidNs(nsid) + "Input"; 225 + const ctx: ParseCtx = { ...baseCtx, parentTypeName: name, hoist }; 226 + const t = buildNamedType(name, def.input.schema, ctx); 227 + types.push(t); 228 + } 229 + if (def.output?.schema?.type === "object") { 230 + const name = nsidNs(nsid) + "Output"; 231 + const ctx: ParseCtx = { ...baseCtx, parentTypeName: name, hoist }; 232 + const t = buildNamedType(name, def.output.schema, ctx); 233 + types.push(t); 234 + } 235 + if (def.message?.schema?.type === "object") { 236 + const name = nsidNs(nsid) + "Message"; 237 + const ctx: ParseCtx = { ...baseCtx, parentTypeName: name, hoist }; 238 + const t = buildNamedType(name, def.message.schema, ctx); 239 + types.push(t); 240 + } 241 + break; 242 + } 243 + default: 244 + break; 245 + } 246 + } 247 + } 248 + 249 + for (const t of types) { 250 + if (t.name.startsWith("__inline:")) continue; 251 + refMap.set(`__inline:${t.name}`, t.name); 252 + } 253 + 254 + for (const t of types) { 255 + for (const f of t.fields) f.type = resolveTypeRef(f.type, refMap); 256 + } 257 + 258 + const seen = new Map<string, NamedType>(); 259 + for (const t of types) { 260 + if (!seen.has(t.name)) seen.set(t.name, t); 261 + } 262 + const deduped = Array.from(seen.values()).sort((a, b) => a.name.localeCompare(b.name)); 263 + 264 + return { types: deduped, refMap }; 265 + } 266 + 267 + function resolveTypeRef(t: TypeRef, refMap: Map<string, string>): TypeRef { 268 + switch (t.kind) { 269 + case "array": 270 + return { kind: "array", items: resolveTypeRef(t.items, refMap) }; 271 + case "ref": { 272 + const name = refMap.get(t.targetId) ?? "unknown"; 273 + return { kind: "ref", targetId: name }; 274 + } 275 + case "union": { 276 + const opts = t.options.map((id) => refMap.get(id) ?? "unknown"); 277 + return { kind: "union", options: opts }; 278 + } 279 + default: 280 + return t; 281 + } 282 + } 283 + 284 + function fmtBytes(n: number): string { 285 + if (n < 1024) return `${n} B`; 286 + if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`; 287 + return `${(n / 1024 / 1024).toFixed(2)} MB`; 288 + } 289 + 290 + function writeOut(langLog: ReturnType<typeof tag>, p: string, content: string) { 291 + mkdirSync(dirname(p), { recursive: true }); 292 + const existed = existsSync(p); 293 + writeFileSync(p, content, "utf8"); 294 + const rel = p.replace(REPO + "/", ""); 295 + const verb = existed ? "updated" : "created"; 296 + langLog.success(`${verb} \`${rel}\` (${fmtBytes(content.length)})`); 297 + } 298 + 299 + const LANG_ICONS: Record<string, string> = { 300 + typescript: "TS", 301 + go: "GO", 302 + python: "PY", 303 + "python-pydantic": "PYD", 304 + rust: "RS", 305 + kotlin: "KT", 306 + ruby: "RB", 307 + elixir: "EX", 308 + clojure: "CLJ", 309 + gleam: "GLM", 310 + }; 311 + 312 + async function main() { 313 + const t0 = Date.now(); 314 + log.box({ 315 + title: "rocksky · lexgen", 316 + message: "generating SDK type bindings from atproto lexicons", 317 + style: { borderColor: "magenta", padding: 1 }, 318 + }); 319 + 320 + const parseLog = tag("parse"); 321 + parseLog.start(`scanning ${LEX_DIR.replace(REPO + "/", "")}`); 322 + const reg = buildRegistry(); 323 + parseLog.success(`parsed ${reg.types.length} named types`); 324 + 325 + const targets = [ 326 + { lang: "typescript", path: join(REPO, "sdk/typescript/src/generated/types.ts"), fn: emitTypescript }, 327 + { lang: "go", path: join(REPO, "sdk/go/rocksky/gen/types.go"), fn: emitGo }, 328 + { lang: "python", path: join(REPO, "sdk/python/src/rocksky/gen/types.py"), fn: emitPython }, 329 + { lang: "python-pydantic", path: join(REPO, "sdk/python/src/rocksky/gen/models.py"), fn: emitPythonPydantic }, 330 + { lang: "rust", path: join(REPO, "sdk/rust/src/generated.rs"), fn: emitRust }, 331 + { lang: "kotlin", path: join(REPO, "sdk/kotlin/rocksky/src/main/kotlin/app/rocksky/generated/Types.kt"), fn: emitKotlin }, 332 + { lang: "ruby", path: join(REPO, "sdk/ruby/lib/rocksky/generated/types.rb"), fn: emitRuby }, 333 + { lang: "elixir", path: join(REPO, "sdk/elixir/lib/rocksky/generated/types.ex"), fn: emitElixir }, 334 + { lang: "clojure", path: join(REPO, "sdk/clojure/src/rocksky/generated/types.clj"), fn: emitClojure }, 335 + { lang: "gleam", path: join(REPO, "sdk/gleam/src/rocksky/generated/types.gleam"), fn: emitGleam }, 336 + ]; 337 + 338 + let totalBytes = 0; 339 + for (const t of targets) { 340 + const langLog = tag(`${LANG_ICONS[t.lang] ?? t.lang}`); 341 + langLog.start(`emitting ${t.lang}`); 342 + const content = t.fn(reg); 343 + totalBytes += content.length; 344 + writeOut(langLog, t.path, content); 345 + } 346 + 347 + const pyLog = tag("PY"); 348 + const initPy = join(REPO, "sdk/python/src/rocksky/gen/__init__.py"); 349 + const initContent = "from .types import * # noqa: F401,F403\n"; 350 + totalBytes += initContent.length; 351 + writeOut(pyLog, initPy, initContent); 352 + 353 + const ms = Date.now() - t0; 354 + log.box({ 355 + title: "done", 356 + message: [ 357 + `${reg.types.length} types · ${targets.length} languages`, 358 + `${fmtBytes(totalBytes)} written · ${ms} ms`, 359 + ].join("\n"), 360 + style: { borderColor: "green", padding: 1 }, 361 + }); 362 + } 363 + 364 + try { 365 + await main(); 366 + } catch (err) { 367 + log.error(err); 368 + process.exit(1); 369 + }
+38
tools/lexgen/registry.ts
··· 1 + export type Primitive = 2 + | "string" 3 + | "integer" 4 + | "boolean" 5 + | "bytes" 6 + | "blob" 7 + | "cid-link" 8 + | "cid" 9 + | "datetime" 10 + | "at-uri" 11 + | "uri" 12 + | "at-identifier" 13 + | "did"; 14 + 15 + export type TypeRef = 16 + | { kind: "primitive"; name: Primitive } 17 + | { kind: "array"; items: TypeRef } 18 + | { kind: "ref"; targetId: string } 19 + | { kind: "union"; options: string[] } 20 + | { kind: "unknown" }; 21 + 22 + export interface Field { 23 + name: string; 24 + description?: string; 25 + required: boolean; 26 + type: TypeRef; 27 + } 28 + 29 + export interface NamedType { 30 + name: string; 31 + description?: string; 32 + fields: Field[]; 33 + } 34 + 35 + export interface Registry { 36 + types: NamedType[]; 37 + refMap: Map<string, string>; 38 + }