@omelhorsite/sdk 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +113 -131
  2. package/dist/index.js +1049 -1246
  3. package/dist/types/auth/device.d.ts +1 -1
  4. package/dist/types/auth/index.d.ts +2 -2
  5. package/dist/types/auth/tokens.d.ts +15 -15
  6. package/dist/types/client.d.ts +10 -10
  7. package/dist/types/errors.d.ts +12 -15
  8. package/dist/types/http.d.ts +74 -118
  9. package/dist/types/index.d.ts +2 -2
  10. package/dist/types/internal/attachments.d.ts +17 -0
  11. package/dist/types/internal/helpers.d.ts +9 -0
  12. package/dist/types/listing.d.ts +90 -0
  13. package/dist/types/local/qr.d.ts +1 -1
  14. package/dist/types/local/wordlist.d.ts +2 -3
  15. package/dist/types/resources/account.d.ts +19 -19
  16. package/dist/types/resources/admin/authorizedApplications.d.ts +133 -0
  17. package/dist/types/resources/admin/chests.d.ts +51 -0
  18. package/dist/types/resources/admin/eventAlerts.d.ts +60 -0
  19. package/dist/types/resources/admin/identities.d.ts +99 -0
  20. package/dist/types/resources/admin/index.d.ts +77 -0
  21. package/dist/types/resources/admin/jobs.d.ts +97 -0
  22. package/dist/types/resources/admin/myOauthApplications.d.ts +282 -0
  23. package/dist/types/resources/admin/notepads.d.ts +49 -0
  24. package/dist/types/resources/admin/oauthApplications.d.ts +309 -0
  25. package/dist/types/resources/admin/quotas.d.ts +114 -0
  26. package/dist/types/resources/admin/shortLinks.d.ts +201 -0
  27. package/dist/types/resources/admin/types.d.ts +222 -0
  28. package/dist/types/resources/admin/vocalSeparations.d.ts +98 -0
  29. package/dist/types/resources/admin.d.ts +17 -13
  30. package/dist/types/resources/auth/index.d.ts +1 -1
  31. package/dist/types/resources/auth/passkeys.d.ts +127 -163
  32. package/dist/types/resources/auth/sessions.d.ts +116 -161
  33. package/dist/types/resources/chests.d.ts +27 -31
  34. package/dist/types/resources/content/analysis.d.ts +62 -0
  35. package/dist/types/resources/content/blogs.d.ts +471 -0
  36. package/dist/types/resources/content/feedbacks.d.ts +263 -0
  37. package/dist/types/resources/content/index.d.ts +52 -0
  38. package/dist/types/resources/content/intel/articles.d.ts +230 -0
  39. package/dist/types/resources/content/intel/config.d.ts +135 -0
  40. package/dist/types/resources/content/intel/index.d.ts +53 -0
  41. package/dist/types/resources/content/intel/items.d.ts +91 -0
  42. package/dist/types/resources/content/intel/reports.d.ts +108 -0
  43. package/dist/types/resources/content/intel/scripts.d.ts +152 -0
  44. package/dist/types/resources/content/intel/sources.d.ts +236 -0
  45. package/dist/types/resources/content/intel/stats.d.ts +105 -0
  46. package/dist/types/resources/content/intel/types.d.ts +86 -0
  47. package/dist/types/resources/content/jokes.d.ts +93 -0
  48. package/dist/types/resources/content/notifications.d.ts +147 -0
  49. package/dist/types/resources/content/serviceUsages.d.ts +73 -0
  50. package/dist/types/resources/content/servicesStatus.d.ts +194 -0
  51. package/dist/types/resources/content/siteConfig.d.ts +43 -0
  52. package/dist/types/resources/content/spaceInvaders.d.ts +154 -0
  53. package/dist/types/resources/content.d.ts +41 -236
  54. package/dist/types/resources/dynamicQrs.d.ts +29 -45
  55. package/dist/types/resources/forms.d.ts +37 -58
  56. package/dist/types/resources/jobs.d.ts +35 -44
  57. package/dist/types/resources/library/annotations.d.ts +162 -0
  58. package/dist/types/resources/library/books.d.ts +534 -0
  59. package/dist/types/resources/library/chat.d.ts +259 -0
  60. package/dist/types/resources/library/index.d.ts +39 -0
  61. package/dist/types/resources/library/shelves.d.ts +237 -0
  62. package/dist/types/resources/library/types.d.ts +120 -0
  63. package/dist/types/resources/library.d.ts +20 -22
  64. package/dist/types/resources/media.d.ts +48 -61
  65. package/dist/types/resources/movies/addons.d.ts +388 -0
  66. package/dist/types/resources/movies/collections.d.ts +352 -0
  67. package/dist/types/resources/movies/index.d.ts +29 -0
  68. package/dist/types/resources/movies/types.d.ts +50 -0
  69. package/dist/types/resources/movies/watchProgress.d.ts +277 -0
  70. package/dist/types/resources/movies.d.ts +27 -53
  71. package/dist/types/resources/music/artists.d.ts +182 -246
  72. package/dist/types/resources/music/imports.d.ts +190 -218
  73. package/dist/types/resources/music/index.d.ts +8 -7
  74. package/dist/types/resources/music/playlists.d.ts +85 -117
  75. package/dist/types/resources/music/social.d.ts +153 -228
  76. package/dist/types/resources/music/songs.d.ts +165 -227
  77. package/dist/types/resources/realtime.d.ts +75 -88
  78. package/dist/types/resources/shortLinks.d.ts +38 -47
  79. package/dist/types/resources/social/groupChats.d.ts +458 -0
  80. package/dist/types/resources/social/index.d.ts +19 -0
  81. package/dist/types/resources/social/messages.d.ts +424 -0
  82. package/dist/types/resources/social/relationships.d.ts +322 -0
  83. package/dist/types/resources/social/types.d.ts +37 -0
  84. package/dist/types/resources/social.d.ts +21 -3
  85. package/dist/types/resources/storage/upload.d.ts +42 -56
  86. package/dist/types/resources/storage.d.ts +94 -109
  87. package/dist/types/resources/tickets.d.ts +19 -10
  88. package/dist/types/resources/tools/backgroundRemoval.d.ts +11 -13
  89. package/dist/types/resources/tools/captions.d.ts +107 -135
  90. package/dist/types/resources/tools/upscale.d.ts +12 -16
  91. package/dist/types/types.d.ts +29 -38
  92. package/package.json +1 -1
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * The music domain, reachable as `oms.music`.
3
3
  *
4
- * Five modules split by what they own rather than by which controller serves
5
- * them, because the Rails routes here are flatter than the concepts are:
6
- * `/songs`, `/artists`, `/playlists`, `/song_imports`, `/jams` and a dozen more
7
- * all hang off the root, and grouping them by prefix would have produced a
8
- * surface nobody could guess from.
4
+ * Five modules split by what they own rather than by URL prefix, because the
5
+ * routes here are flatter than the concepts are: `/songs`, `/artists`,
6
+ * `/playlists`, `/song_imports`, `/jams` and a dozen more all hang off the
7
+ * root, and grouping them by prefix would have produced a surface nobody could
8
+ * guess from.
9
9
  *
10
10
  * ```ts
11
11
  * const songs = await oms.music.songs.list({ artist: "Nina Simone" });
@@ -18,7 +18,8 @@
18
18
  *
19
19
  * `songs`, `artists`, `playlists`, `playlist_songs`, `liked_songs`,
20
20
  * `play_events`, `jams`, `song_imports` and `artist_imports` are INTEGERS over
21
- * HTTP. The same song ids come back as STRINGS on the cable. The types in each
21
+ * HTTP. The same song ids come back as STRINGS on the realtime stream. The
22
+ * types in each
22
23
  * module say which one applies where; do not normalise them yourself on the way
23
24
  * in, because `exact_search` compares them typed and a stringified integer
24
25
  * silently matches nothing.
@@ -53,7 +54,7 @@ export declare class MusicNamespace extends Resource {
53
54
  readonly artists: MusicArtistsNamespace;
54
55
  /** Playlists, plus `.songs`, `.mixes`, `.radios` and `.plays`. */
55
56
  readonly playlists: MusicPlaylistsNamespace;
56
- /** Getting audio in: uploads, yt-dlp, `.spotify` sync and `.srMachine`. */
57
+ /** Getting audio in: uploads, URL downloads, `.spotify` sync and `.srMachine`. */
57
58
  readonly imports: MusicImportsNamespace;
58
59
  /** Jams, music profiles, the assistant and the DJ. */
59
60
  readonly social: MusicSocialNamespace;
@@ -20,9 +20,8 @@
20
20
  * 2. **System playlists are half read-only.** A playlist whose `source_kind`
21
21
  * is present and not `"manual"` is maintained by an external sync
22
22
  * (Spotify today). Renaming it, re-arting it and reordering it are refused
23
- * with `401`; adding, removing, hiding and copying are NOT. That split is
24
- * newer than `docs/api-music.md`, which still says every structural edit is
25
- * refused. Test with {@link isSystemPlaylist}.
23
+ * with `401`; adding, removing, hiding and copying are NOT. Test with
24
+ * {@link isSystemPlaylist}.
26
25
  * 3. **Removing a song from a synced playlist does not delete anything.** The
27
26
  * sync would just put it back, so the row is marked `hidden` instead and
28
27
  * the API still answers `204`. The row keeps coming back in listings for
@@ -30,12 +29,13 @@
30
29
  * {@link PlaylistSongsNamespace.remove}.
31
30
  * 4. **`/music_radios/*` is throttled at 60 requests per minute**, and the
32
31
  * bucket is keyed by the `Authorization` header - or by the client IP when
33
- * there is none. A cookie-authenticated web client therefore shares one
32
+ * there is none. A cookie-authenticated browser therefore shares one
34
33
  * budget with every other visitor behind the same address. See
35
34
  * {@link MusicRadiosNamespace}.
36
35
  */
37
36
  import { Resource } from "../../http";
38
- import type { FileInput, Id, NativeFile, PageParams, Paginated, RequestOptions, Timestamp } from "../../types";
37
+ import type { ListParams } from "../../listing";
38
+ import type { FileInput, Id, NativeFile, Paginated, RequestOptions, Timestamp } from "../../types";
39
39
  /**
40
40
  * Primary key of a playlist. A NUMBER: `playlists` never moved to the opaque
41
41
  * string ids the account-side tables use.
@@ -54,7 +54,7 @@ export type PlaylistVisibility = "private" | "friends";
54
54
  /**
55
55
  * Where a playlist came from. `"manual"` (or `null` on very old rows) is a
56
56
  * playlist the user built; anything else marks it as maintained by a sync and
57
- * makes {@link isSystemPlaylist} true. The column is a free string, so treat
57
+ * makes {@link isSystemPlaylist} true. The field is a free string, so treat
58
58
  * unknown values as system rather than as a bug.
59
59
  */
60
60
  export type PlaylistSourceKind = "manual" | "imported" | "spotify_sync" | (string & {});
@@ -70,13 +70,12 @@ export type PlaylistSongOrigin = "sync" | "manual";
70
70
  * The sync numbers its own rows from 1 upwards and never reaches here, so a
71
71
  * user's additions to a synced playlist are parked above the floor and the
72
72
  * next sync run can renumber its own rows without colliding with them.
73
- * Mirrors `PlaylistSong::MANUAL_BLOCK_FLOOR`.
74
73
  */
75
74
  export declare const PLAYLIST_MANUAL_BLOCK_FLOOR = 100000;
76
75
  /**
77
- * Most songs `POST /playlists` will seed from `song_ids` in one call. Mirrors
78
- * `PlaylistsController::SEED_CAP`; the server takes the first 500 and drops
79
- * the rest in silence, so the SDK raises instead.
76
+ * Most songs `POST /playlists` will seed from `song_ids` in one call. The
77
+ * server takes the first 500 and drops the rest in silence, so the SDK raises
78
+ * instead.
80
79
  */
81
80
  export declare const PLAYLIST_SEED_CAP = 500;
82
81
  /**
@@ -87,13 +86,13 @@ export declare const PLAYLIST_SEED_CAP = 500;
87
86
  export declare const MUSIC_RADIO_RATE_LIMIT_PER_MINUTE = 60;
88
87
  /**
89
88
  * Window in which a repeat play of the same song is swallowed rather than
90
- * recorded. Mirrors `PlayEvent::DEDUPE_WINDOW`.
89
+ * recorded.
91
90
  */
92
91
  export declare const PLAY_EVENT_DEDUPE_WINDOW_MS = 30000;
93
92
  /**
94
- * Client labels the backend will store on a play event.
93
+ * Client labels the server will store on a play event.
95
94
  *
96
- * A value outside this list does NOT fail the request: the controller records
95
+ * A value outside this list does NOT fail the request: the server records
97
96
  * the play with a `null` source rather than losing real listening history over
98
97
  * a typo. So a misspelt label is invisible until somebody audits by origin and
99
98
  * finds a pile of unlabelled rows.
@@ -116,13 +115,10 @@ export declare const MIX_KINDS: readonly ["top_artist", "this_is", "monthly_rewi
116
115
  */
117
116
  export type MixKind = (typeof MIX_KINDS)[number] | (string & {});
118
117
  /**
119
- * The compact `ArtistBlueprint` view, as it is embedded in mixes and in the
120
- * album/artist rows of the history endpoints.
121
- *
122
- * Blueprinter views ADD to the base rather than replace it, so `compact`
123
- * carries `id`, `created_at` and `updated_at` too. The `*_fs_node_id` keys are
124
- * a deliberate duplicate of the `*_media_id` ones, kept for the old web
125
- * frontend; read the `_media_id` form in new code.
118
+ * The compact artist, as it is embedded in mixes and in the album/artist rows
119
+ * of the history endpoints. It carries `id`, `created_at` and `updated_at`
120
+ * too. The `*_fs_node_id` keys are a legacy duplicate of the `*_media_id`
121
+ * ones; read the `_media_id` form in new code.
126
122
  */
127
123
  export interface MusicArtistPayload {
128
124
  readonly id: number;
@@ -137,7 +133,7 @@ export interface MusicArtistPayload {
137
133
  /** @deprecated Legacy twin of `compressed_image_media_id`, same value. */
138
134
  readonly compressed_image_fs_node_id?: string | null;
139
135
  }
140
- /** One artist credit on a song, as `SongArtistBlueprint` renders it. */
136
+ /** One artist credit on a song. */
141
137
  export interface MusicSongArtistPayload {
142
138
  readonly id: number;
143
139
  readonly created_at: Timestamp;
@@ -159,9 +155,9 @@ export interface MusicSongArtistPayload {
159
155
  /**
160
156
  * A song, as it is embedded in playlist rows, mixes, radios and history.
161
157
  *
162
- * This is a deliberate SUBSET of what `SongBlueprint` sends: the fields every
158
+ * This is a deliberate SUBSET of what the server sends: the fields every
163
159
  * consumer in this file needs, and no more. The full song type belongs to the
164
- * songs namespace, and duplicating thirty audio-metadata columns in two places
160
+ * songs namespace, and duplicating thirty audio-metadata fields in two places
165
161
  * is how the two copies drift apart. Extra keys ARE on the wire - cast when
166
162
  * you need `isrc`, the codec fields or the stem media ids.
167
163
  */
@@ -182,12 +178,8 @@ export interface MusicSongPayload {
182
178
  readonly compressed_artwork_media_id: string | null;
183
179
  }
184
180
  /**
185
- * A playlist.
186
- *
187
- * `visibility` and `owned` are newer than `docs/api-music.md` and than the
188
- * `Playlist` type in `oms-music/src/domain/playlist.ts`; both are on the wire
189
- * today. `owned` is computed against the ASKING user, which is what makes a
190
- * followed playlist distinguishable from your own in one listing.
181
+ * A playlist. `owned` is computed against the ASKING user, which is what makes
182
+ * a followed playlist distinguishable from your own in one listing.
191
183
  */
192
184
  export interface MusicPlaylist {
193
185
  readonly id: MusicPlaylistId;
@@ -233,9 +225,8 @@ export interface MusicPlaylistSong {
233
225
  readonly origin: PlaylistSongOrigin;
234
226
  /**
235
227
  * A `sync` row the owner removed. It stays so the next sync run finds it and
236
- * leaves it alone. Only the OWNER ever sees a hidden row: the listing filters
237
- * `hidden = FALSE OR playlists.user_id = <you>`, so a follower's page count
238
- * and the owner's differ for the same playlist.
228
+ * leaves it alone. Only the OWNER ever sees a hidden row, so a follower's
229
+ * page count and the owner's differ for the same playlist.
239
230
  */
240
231
  readonly hidden: boolean;
241
232
  /** The full song. Present on every row of every view. */
@@ -323,14 +314,7 @@ export interface RecentSongPlay {
323
314
  /** One row of `GET /play_events/recent?group_by=album`. */
324
315
  export interface RecentAlbumPlay {
325
316
  readonly album: string | null;
326
- /**
327
- * Lead artist of the album, compact view, or `null`.
328
- *
329
- * `oms-music/src/api/endpoints/playEvents.ts` types this as
330
- * `Artist | string | null` and calls the string case "legacy rows". No such
331
- * case exists in the Rails this was checked against: the album grouping joins
332
- * `song_artists` and renders a blueprint or `nil`, never a bare name.
333
- */
317
+ /** Lead artist of the album, compact view, or `null`. Never a bare name. */
334
318
  readonly artist: MusicArtistPayload | null;
335
319
  readonly artwork_media_id: string | null;
336
320
  /** @deprecated Legacy twin of `artwork_media_id`, same value. */
@@ -356,19 +340,21 @@ export interface TopArtistRow {
356
340
  readonly artist: MusicArtistPayload;
357
341
  readonly play_count: number;
358
342
  }
343
+ /** Filter columns of `GET /playlists`. */
344
+ export declare const PLAYLIST_FILTER_COLUMNS: readonly ["id", "name", "created_at", "updated_at"];
359
345
  /** Filters for {@link MusicPlaylistsNamespace.list}. */
360
- export interface ListPlaylistsParams extends PageParams {
346
+ export interface ListPlaylistsParams extends ListParams<(typeof PLAYLIST_FILTER_COLUMNS)[number]> {
361
347
  /**
362
348
  * Partial, accent-insensitive match on the name, sent as `search[name]`.
363
349
  *
364
- * There is no filter for the owner and none for the visibility: the
365
- * controller's allowlist is `id`, `name`, `created_at`, `updated_at` and
366
- * nothing else, and an unrecognised filter key is a `400`, not a wider
350
+ * There is no filter for the owner and none for the visibility: the filter
351
+ * allowlist is `id`, `name`, `created_at`, `updated_at` and nothing else,
352
+ * and an unrecognised filter key is a `400`, not a wider
367
353
  * result. Use the `owned` flag on each row to tell yours from the ones you
368
354
  * follow.
369
355
  */
370
356
  readonly name?: string;
371
- /** Exact ids, sent as `exact_search[id][]`, which the backend turns into `IN`. */
357
+ /** Exact ids, sent as `exact_search[id][]`; any of them matches. */
372
358
  readonly ids?: readonly MusicPlaylistId[];
373
359
  }
374
360
  /** Arguments for {@link MusicPlaylistsNamespace.create}. */
@@ -404,14 +390,15 @@ export interface UpdatePlaylistInput {
404
390
  * Point the cover at an existing attachment, or pass `null` to purge the
405
391
  * current one. Refused with `401` on a system playlist.
406
392
  *
407
- * Omitting the key and passing `null` are different requests: the server
408
- * tests `params.key?`, so an absent key leaves the artwork alone and an
409
- * explicit `null` deletes it.
393
+ * Omitting the key and passing `null` are different requests: an absent key
394
+ * leaves the artwork alone and an explicit `null` deletes it.
410
395
  */
411
396
  readonly artworkMediaId?: string | null;
412
397
  }
398
+ /** Filter columns of `GET /playlist_songs`. */
399
+ export declare const PLAYLIST_SONG_FILTER_COLUMNS: readonly ["id", "playlist_id", "song_id", "position", "origin", "hidden", "created_at", "updated_at"];
413
400
  /** Filters for {@link PlaylistSongsNamespace.list}. */
414
- export interface ListPlaylistSongsParams extends PageParams {
401
+ export interface ListPlaylistSongsParams extends ListParams<(typeof PLAYLIST_SONG_FILTER_COLUMNS)[number]> {
415
402
  readonly playlistId?: MusicPlaylistId;
416
403
  readonly songId?: number;
417
404
  readonly ids?: readonly MusicPlaylistSongId[];
@@ -453,7 +440,7 @@ export interface TopPlaysParams {
453
440
  /** Arguments for {@link PlayEventsNamespace.topSongs}. */
454
441
  export interface TopSongsParams extends TopPlaysParams {
455
442
  /**
456
- * Narrow to one artist by NAME - the backend canonicalises it and looks it
443
+ * Narrow to one artist by NAME - the server canonicalises it and looks it
457
444
  * up in your own roster. A name that matches nothing yields an empty array
458
445
  * rather than a `404`, so an empty result does not tell you which of the two
459
446
  * happened. Only `scope=song` honours this.
@@ -518,9 +505,9 @@ export declare class MusicPlaylistsNamespace extends Resource {
518
505
  * playlist you have not followed is readable by id but never enumerated here.
519
506
  *
520
507
  * The default order is `created_at:desc` rather than the server's, which is
521
- * unspecified. Offset pagination over an unordered query in Postgres can
522
- * repeat a row on one page and skip it on the next, so the SDK always sends
523
- * an order. Pass `order` to choose another one.
508
+ * unspecified. Offset pagination over an unordered query can repeat a row on
509
+ * one page and skip it on the next, so the SDK always sends an order. Pass
510
+ * `order` to choose another one.
524
511
  *
525
512
  * Filters are `name` and `ids` and nothing else - see
526
513
  * {@link ListPlaylistsParams.name} for why. Indexes carry an `ETag`, so a
@@ -552,7 +539,7 @@ export declare class MusicPlaylistsNamespace extends Resource {
552
539
  *
553
540
  * Not retried on a lost answer (the transport's default for a `POST`), because
554
541
  * a replay mints a second playlist. A `429` is still retried, and safely so:
555
- * this backend refuses before it writes.
542
+ * the server refuses before it writes.
556
543
  *
557
544
  * Ceiling: the general authenticated 600/min.
558
545
  *
@@ -607,8 +594,8 @@ export declare class MusicPlaylistsNamespace extends Resource {
607
594
  * renumbered densely from 1.
608
595
  *
609
596
  * Two things it will not do. It only copies a playlist you OWN - a friend's
610
- * playlist that {@link get} opens happily answers `401 "not yours"` here,
611
- * which `docs/api-music.md` does not mention. And the new name is built
597
+ * playlist that {@link get} opens happily answers `401 "not yours"` here.
598
+ * And the new name is built
612
599
  * server-side as `"<name> (cópia)"`, in Portuguese, whatever the client's
613
600
  * locale; rename it afterwards with {@link update} if that matters.
614
601
  *
@@ -623,13 +610,7 @@ export declare class MusicPlaylistsNamespace extends Resource {
623
610
  * `POST /playlists/:id/reorder` - rewrites the order of the playlist.
624
611
  *
625
612
  * Read this before calling it. The endpoint is not "move song X to slot N";
626
- * it is "here is the complete order", and the implementation is one line that
627
- * makes three things true at once:
628
- *
629
- * ```ruby
630
- * new_position = @song_ids.index(ps.song_id)
631
- * ps.update(position: new_position) if new_position
632
- * ```
613
+ * it is "here is the complete order", and three things are true at once:
633
614
  *
634
615
  * 1. **Positions become the INDEX in your array, so they start at 0.** Every
635
616
  * other path numbers from 1 (seeding) or from `max + 1` (appending). After
@@ -639,20 +620,19 @@ export declare class MusicPlaylistsNamespace extends Resource {
639
620
  * interleaves with, or collides with, the renumbered rows. So send the
640
621
  * complete order, always. Ordering by `position` after a partial reorder
641
622
  * gives an arrangement nobody asked for.
642
- * 3. **The ids are matched with `Array#index`, which is `==` on Integers.**
643
- * A string id matches nothing, so `["12","5"]` moves NOTHING and still
644
- * answers `200`. This is the silent failure this method exists to prevent:
645
- * it coerces to numbers and throws on anything that is not an integer.
623
+ * 3. **The ids are matched by identity against integers.** A string id
624
+ * matches nothing, so `["12","5"]` moves NOTHING and still answers `200`.
625
+ * This is the silent failure this method exists to prevent: it coerces to
626
+ * numbers and throws on anything that is not an integer.
646
627
  *
647
- * The response body is the reorderer's internal output (raw ActiveRecord JSON
648
- * of the join rows, not the blueprint) and is not part of the contract, so
649
- * this resolves to `undefined`. Refetch with
650
- * {@link PlaylistSongsNamespace.list} if you need the new state.
628
+ * The response body is not part of the contract, so this resolves to
629
+ * `undefined`. Refetch with {@link PlaylistSongsNamespace.list} if you need
630
+ * the new state.
651
631
  *
652
632
  * Ceiling: the general authenticated 600/min.
653
633
  *
654
- * @throws {TypeError} on an empty array (the service raises `ArgumentError`
655
- * for it, which is a 500, not a 400) or on an id that is not an integer.
634
+ * @throws {TypeError} on an empty array (the server answers a 500 for it,
635
+ * not a 400) or on an id that is not an integer.
656
636
  * @throws {OmsApiError} 404 when the playlist is not visible, 401 `"not yours"`
657
637
  * when it is visible but somebody else's - following it is not enough - and
658
638
  * 401 with the "make a copy first" sentence on a system playlist.
@@ -672,12 +652,12 @@ export declare class MusicPlaylistsNamespace extends Resource {
672
652
  * a 200 with no file in it.
673
653
  *
674
654
  * The bytes go through the music quota funnel, and replacing a cover
675
- * `purge_later`s the previous blob rather than leaking it. Note that this is
676
- * the only artwork path that spends quota: pointing `artworkMediaId` at an
655
+ * discards the previous blob rather than leaking it. Note that this is the
656
+ * only artwork path that spends quota: pointing `artworkMediaId` at an
677
657
  * existing attachment reuses the blob and costs nothing.
678
658
  *
679
659
  * Uploads are capped at roughly 100 MB by the CDN in front of the API, well
680
- * above anything an image crop produces; the app sends a JPEG of about 2 MB.
660
+ * above anything an image crop produces.
681
661
  *
682
662
  * Ceiling: the general authenticated 600/min.
683
663
  *
@@ -686,8 +666,6 @@ export declare class MusicPlaylistsNamespace extends Resource {
686
666
  * it is not yours or is a system playlist.
687
667
  */
688
668
  uploadArtwork(id: MusicPlaylistId, artwork: FileInput | NativeFile, options?: RequestOptions): Promise<MusicPlaylist>;
689
- /** One page of the playlist listing. */
690
- private fetchPage;
691
669
  }
692
670
  /**
693
671
  * The `playlist_songs` join rows: membership, order, and the semi-sync dance
@@ -707,11 +685,10 @@ export declare class PlaylistSongsNamespace extends Resource {
707
685
  * "add to playlist" dialogue needs: one request tells you which playlists
708
686
  * already contain the song.
709
687
  *
710
- * The scope is `Playlist.viewable_by`, so this also lists a friend's `friends`
711
- * playlist. What a follower does NOT see is the hidden rows: the query is
712
- * `hidden = FALSE OR playlists.user_id = <you>`, so the same playlist has a
713
- * different length depending on who is asking. Do not use a row count from
714
- * here as the owner's row count.
688
+ * This also lists a friend's `friends` playlist. What a follower does NOT
689
+ * see is the hidden rows, so the same playlist has a different length
690
+ * depending on who is asking. Do not use a row count from here as the
691
+ * owner's row count.
715
692
  *
716
693
  * Every row carries a fully preloaded song (artists, artwork, audio and stem
717
694
  * media ids), so a page of 100 is a large payload. Ask for the page size you
@@ -728,10 +705,9 @@ export declare class PlaylistSongsNamespace extends Resource {
728
705
  * least {@link PLAYLIST_MANUAL_BLOCK_FLOOR} with `origin: "manual"`, so the
729
706
  * addition sits in a block the sync never renumbers.
730
707
  *
731
- * Adding to a system playlist WORKS. `docs/api-music.md` still says this is a
732
- * `401`, and it was before semi-sync landed; the current controller only
733
- * requires that you own the playlist. What is still refused on a system
734
- * playlist is renaming it, re-arting it and reordering it.
708
+ * Adding to a system playlist WORKS; the only requirement is that you own
709
+ * the playlist. What is still refused on a system playlist is renaming it,
710
+ * re-arting it and reordering it.
735
711
  *
736
712
  * Not retried on a lost answer: the unique index would turn the replay into a
737
713
  * `400`, reporting a failure for a row that was in fact created.
@@ -770,10 +746,7 @@ export declare class PlaylistSongsNamespace extends Resource {
770
746
  * with the updated row.
771
747
  *
772
748
  * This is what {@link remove} does implicitly to a sync row, made explicit and
773
- * available for manual rows too. Included even though it is not in the route
774
- * list this module was commissioned from, because exposing the hiding half of
775
- * the mechanism without {@link unhide} would leave a caller unable to undo a
776
- * `remove`.
749
+ * available for manual rows too.
777
750
  *
778
751
  * @throws {OmsApiError} 404 when the row is not visible, 401 when the playlist
779
752
  * is not yours.
@@ -791,8 +764,6 @@ export declare class PlaylistSongsNamespace extends Resource {
791
764
  * is not yours.
792
765
  */
793
766
  unhide(rowId: MusicPlaylistSongId, options?: RequestOptions): Promise<MusicPlaylistSong>;
794
- /** One page of the join-row listing. */
795
- private fetchPage;
796
767
  }
797
768
  /**
798
769
  * Generated mix shelves: "This is X", the monthly rewind, the year mix, the
@@ -817,7 +788,7 @@ export declare class MusicMixesNamespace extends Resource {
817
788
  *
818
789
  * Titles come twice over. `title` and `description` are an English fallback;
819
790
  * `title_key`/`title_params` and their description twins are the i18n
820
- * template the UI should actually render, so the shelf follows the app
791
+ * template the UI should actually render, so the shelf follows the caller's
821
792
  * language instead of being permanently one language. The embedded `artist`
822
793
  * is resolved at render time rather than cached with the shelf, so a picture
823
794
  * that lands today shows up today.
@@ -850,14 +821,13 @@ export declare class MusicMixesNamespace extends Resource {
850
821
  * Artist and song radios: about 40 tracks built by intersecting Last.fm
851
822
  * similar-artist data with what the caller actually owns.
852
823
  *
853
- * **This is the throttled family.** `/music_radios/*` sits behind
854
- * rack-attack's `external_proxy/by_session` rule at
824
+ * **This is the throttled family.** `/music_radios/*` is limited to
855
825
  * {@link MUSIC_RADIO_RATE_LIMIT_PER_MINUTE} requests per minute, shared with
856
826
  * `/lyrics`, `/artists/*` and `/artist_metadata/*`. The bucket key is the
857
827
  * `Authorization` HEADER when there is one and the client IP when there is not,
858
- * which has a consequence worth planning around: a cookie-authenticated web
859
- * client sends no `Authorization`, so every visitor behind one address shares a
860
- * single 60/min budget. Token clients get a bucket per token.
828
+ * which has a consequence worth planning around: a cookie-authenticated
829
+ * browser sends no `Authorization`, so every visitor behind one address shares
830
+ * a single 60/min budget. Token clients get a bucket per token.
861
831
  *
862
832
  * Over the limit the API answers `429` with a `Retry-After`, which the transport
863
833
  * honours by sleeping and retrying - a rate-limited call can therefore take most
@@ -869,20 +839,19 @@ export declare class MusicRadiosNamespace extends Resource {
869
839
  /**
870
840
  * `GET /music_radios/artist/:artist` - a radio seeded on one artist.
871
841
  *
872
- * Takes the artist's SLUG or their name: the backend canonicalises what you
873
- * send and tries `canonical_name` first, then `slug`. `docs/api-music.md` says
874
- * slug only, which understates it. Either way the lookup is against the
875
- * caller's own roster and never creates an artist, so an artist you do not
876
- * have is a `404` rather than an empty radio.
842
+ * Takes the artist's SLUG or their name: the server canonicalises what you
843
+ * send and tries `canonical_name` first, then `slug`. Either way the lookup
844
+ * is against the caller's own roster and never creates an artist, so an
845
+ * artist you do not have is a `404` rather than an empty radio.
877
846
  *
878
847
  * Roughly 30% of the tracks come from the seed artist and the rest from
879
- * similar artists you own, shuffled. The mix is drawn with `RANDOM()` on the
880
- * first build and then frozen for 7 days, so calling twice gives the same
881
- * radio, not a reshuffle.
848
+ * similar artists you own, shuffled. The mix is drawn at random on the first
849
+ * build and then frozen for 7 days, so calling twice gives the same radio,
850
+ * not a reshuffle.
882
851
  *
883
852
  * Ceiling: {@link MUSIC_RADIO_RATE_LIMIT_PER_MINUTE} per minute. A cold build
884
- * runs several queries over the whole library; the mobile app allows 60
885
- * seconds for it, and passing `timeoutMs` is reasonable here.
853
+ * runs several queries over the whole library; a `timeoutMs` of around 60
854
+ * seconds is reasonable here.
886
855
  *
887
856
  * @throws {OmsApiError} 404 `"Could not build radio for <artist>"` - the same
888
857
  * answer for "no such artist in your library" and for "nothing similar to
@@ -935,9 +904,8 @@ export declare class PlayEventsNamespace extends Resource {
935
904
  * doubled. The transport still will not replay a `POST` by default, so pass
936
905
  * `retry: {}` if a lost answer on a flaky connection should be tried again.
937
906
  *
938
- * Hosts usually treat this as fire-and-forget - the app does, with no error
939
- * UI - because a lost play event is worth less than an error toast during
940
- * playback.
907
+ * Treat this as fire-and-forget: a lost play event is worth less than an
908
+ * error toast during playback.
941
909
  *
942
910
  * `listenedSeconds` is clamped server-side rather than validated: `0` is the
943
911
  * floor and three times the track's duration is the ceiling, or 24 hours when
@@ -947,8 +915,8 @@ export declare class PlayEventsNamespace extends Resource {
947
915
  * Ceiling: the general authenticated 600/min. A client that posts one event
948
916
  * per track is nowhere near it; one that posts on every seek is not.
949
917
  *
950
- * @throws {OmsApiError} 400 when `songId` is missing (`ParameterMissing`), 404
951
- * `"Song not found"` when the song is not visible to you.
918
+ * @throws {OmsApiError} 400 when `songId` is missing, 404 `"Song not found"`
919
+ * when the song is not visible to you.
952
920
  */
953
921
  record(input: RecordPlayInput, options?: RequestOptions): Promise<RecordPlayResult>;
954
922
  /**
@@ -970,9 +938,9 @@ export declare class PlayEventsNamespace extends Resource {
970
938
  * `GET /play_events/recent?group_by=album` - recently played albums.
971
939
  *
972
940
  * Grouped by album name AND lead artist, so two albums with the same title by
973
- * different artists stay apart. Songs with no album are excluded entirely -
974
- * the query filters `album NOT IN (NULL, '')` - so a library of loose singles
975
- * produces an empty shelf here while {@link recentSongs} is full.
941
+ * different artists stay apart. Songs with no album (null or empty) are
942
+ * excluded entirely, so a library of loose singles produces an empty shelf
943
+ * here while {@link recentSongs} is full.
976
944
  *
977
945
  * Ceiling: the general authenticated 600/min.
978
946
  */