@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
@@ -0,0 +1,277 @@
1
+ /** The `movies.watchProgress` area: how far into each title the user got, and what "Continuar a ver" is built from. */
2
+ import { Resource } from "../../http";
3
+ import type { BaseRecord, Id, RequestOptions, Timestamp } from "../../types";
4
+ import type { MovieType } from "./types";
5
+ /**
6
+ * Fraction of the runtime that counts as watched when the server derives
7
+ * `finished` itself.
8
+ */
9
+ export declare const MOVIE_WATCH_FINISHED_THRESHOLD = 0.95;
10
+ /**
11
+ * Rows `POST /movie_watch_progresses/bulk` will accept in one call.
12
+ *
13
+ * The server keeps the first 200 entries: the rest are dropped in SILENCE and
14
+ * the call still answers `200` with the 200 rows it did save, so a client
15
+ * marking a 300-episode series watched would believe it succeeded.
16
+ * {@link MovieWatchProgressesNamespace.saveMany} raises instead.
17
+ */
18
+ export declare const MOVIE_WATCH_BULK_LIMIT = 200;
19
+ /**
20
+ * Rows `GET /movie_watch_progresses` returns, at most. Hard-coded, with no
21
+ * paging and no way to reach row 501 - see
22
+ * {@link MovieWatchProgressesNamespace.list}.
23
+ */
24
+ export declare const MOVIE_WATCH_LIST_LIMIT = 500;
25
+ /** One title-or-episode the user has started, and how far in they got. */
26
+ export interface MovieWatchProgress extends BaseRecord {
27
+ readonly user_id: Id;
28
+ readonly movie_type: MovieType;
29
+ /** The addon's id for the TITLE. A series shares it across every episode. */
30
+ readonly movie_id: string;
31
+ /**
32
+ * The addon's id for the specific playable. For a film this is usually the
33
+ * same string as `movie_id`; for a series it is the episode.
34
+ *
35
+ * `(user_id, movie_id, video_id)` is the row's identity and carries a unique
36
+ * index.
37
+ */
38
+ readonly video_id: string;
39
+ readonly season: number | null;
40
+ readonly episode: number | null;
41
+ readonly name: string | null;
42
+ readonly episode_title: string | null;
43
+ readonly poster: string | null;
44
+ /** Seconds into the playable. A float, `NOT NULL DEFAULT 0.0`. */
45
+ readonly position: number;
46
+ /** Runtime in seconds, as the player measured it. `0` when unknown. */
47
+ readonly duration: number;
48
+ /** See {@link MovieWatchProgressInput.finished} for how this gets its value. */
49
+ readonly finished: boolean;
50
+ /** What "Continuar a ver" sorts on, descending. */
51
+ readonly last_watched_at: Timestamp;
52
+ }
53
+ /**
54
+ * One row to upsert, through {@link MovieWatchProgressesNamespace.save} or
55
+ * {@link MovieWatchProgressesNamespace.saveMany}.
56
+ *
57
+ * `movie_id`, `video_id` and `movie_type` are checked up front and a missing
58
+ * one is `400 "movie_id, video_id, movie_type are required"`. Everything else
59
+ * is optional, but read the notes on `finished` and `last_watched_at` before
60
+ * leaving them out: both are cases where omitting the field does something
61
+ * other than "leave it as it was".
62
+ */
63
+ export interface MovieWatchProgressInput {
64
+ readonly movie_type: MovieType;
65
+ /** Identity, with `video_id`. Changing `movie_type` does NOT make a new row. */
66
+ readonly movie_id: string;
67
+ /** Identity, with `movie_id`. */
68
+ readonly video_id: string;
69
+ readonly season?: number | null;
70
+ readonly episode?: number | null;
71
+ readonly name?: string | null;
72
+ readonly episode_title?: string | null;
73
+ readonly poster?: string | null;
74
+ /** Seconds into the playable. Negative is `400 "Position must be greater than or equal to 0"`. */
75
+ readonly position?: number;
76
+ /** Runtime in seconds. Negative is a `400` the same way. */
77
+ readonly duration?: number;
78
+ /**
79
+ * Three states, not two.
80
+ *
81
+ * - **omitted** - the server derives it:
82
+ * `finished = position >= duration * 0.95`, and if `duration <= 0` it
83
+ * leaves the stored flag ALONE. This is what a playback tick should send.
84
+ * - **`true` / `false`** - the user said so. The value is written as given,
85
+ * even when `duration <= 0`.
86
+ * - **`null`** - dropped before it is read, and therefore identical to
87
+ * omitting it.
88
+ *
89
+ * That last branch is the bug that was fixed here. "Marcar como nao visto"
90
+ * sends `position: 0, duration: 0`, which used to hit the `duration <= 0`
91
+ * guard and leave `finished` true forever. Sending an explicit `false` is
92
+ * what makes it stick - sending `null`, or leaving the key out, still does
93
+ * nothing at all. {@link MovieWatchProgressesNamespace.setWatched} spells it
94
+ * out so you cannot get this wrong by accident.
95
+ *
96
+ * An explicit value only pins the flag for THAT save. The next tick that
97
+ * omits `finished` goes back to deriving it from the position.
98
+ */
99
+ readonly finished?: boolean;
100
+ /**
101
+ * When the user last watched, ISO-8601.
102
+ *
103
+ * SEND IT ON EVERY CALL. It is only defaulted when the row is first
104
+ * created - so an upsert that omits it keeps whatever timestamp was there
105
+ * when the row was first created. The Continue Watching list is ordered by
106
+ * it, descending, so omitting this pins the title where it first appeared
107
+ * and it never moves back to the front. `new Date().toISOString()` at the
108
+ * call site is the whole fix.
109
+ */
110
+ readonly last_watched_at?: Timestamp;
111
+ }
112
+ /**
113
+ * The same arithmetic the server uses, for a client that wants to render a
114
+ * "watched" tick before the round trip lands.
115
+ *
116
+ * Returns `null` - not `false` - when `duration` is zero or negative, because
117
+ * that is precisely the case where the server declines to decide and leaves the
118
+ * stored flag untouched. Treating that as `false` is how an optimistic UI ends
119
+ * up un-ticking something the server still considers watched.
120
+ */
121
+ export declare function movieWatchFinished(position: number, duration: number): boolean | null;
122
+ /**
123
+ * The `movies.watchProgress` namespace: how far into each title the user got,
124
+ * and what "Continuar a ver" is built from.
125
+ *
126
+ * This family is the odd one out: none of the list DSL applies, `create`
127
+ * answers `200`, and there is no `show` and no `update`. Everything is an
128
+ * upsert keyed on `(user, movie_id, video_id)`.
129
+ */
130
+ export declare class MovieWatchProgressesNamespace extends Resource {
131
+ /**
132
+ * `GET /movie_watch_progresses` - the caller's rows, newest first.
133
+ *
134
+ * Not paginated, and not filterable. The query string is ignored entirely
135
+ * and the answer is always the 500 most recently watched rows, so:
136
+ *
137
+ * - there is NO way to reach row 501. A user with more history than that
138
+ * simply cannot read the tail through this API;
139
+ * - `search[...]` / `exact_search[...]` / `modifiers[...]` are not rejected,
140
+ * they are silently ignored - this index never raises
141
+ * `400 "Unknown search filter"`. A client that thinks it asked for one
142
+ * title gets all 500 rows and, if it trusts the filter, the wrong answer.
143
+ * Filter client-side; that is why this method takes no params;
144
+ * - there is no `ETag` either.
145
+ *
146
+ * Finished rows are included. Build "Continuar a ver" by dropping
147
+ * `finished === true` yourself, and remember an episode can be finished while
148
+ * its series is not.
149
+ *
150
+ * @throws {OmsApiError} 401 for an anonymous caller, 403 for an OAuth token.
151
+ */
152
+ list(options?: RequestOptions): Promise<MovieWatchProgress[]>;
153
+ /**
154
+ * `POST /movie_watch_progresses` - upserts ONE row. **`200`, not `201`.**
155
+ *
156
+ * This is the playback tick: call it while something is playing, throttled
157
+ * by the player to whatever interval you like. The server finds by
158
+ * `(user, movie_id, video_id)` and updates in place, so it is idempotent and
159
+ * safe to repeat - the only create in this file where opting into
160
+ * `options.retry` is a good idea rather than a way to make duplicates.
161
+ * (The transport does not replay non-safe methods unless you ask.)
162
+ *
163
+ * `movie_type` is NOT part of the key. Posting the same `(movie_id,
164
+ * video_id)` with a different type rewrites the existing row's type rather
165
+ * than creating a second one.
166
+ *
167
+ * Read {@link MovieWatchProgressInput.finished} and
168
+ * {@link MovieWatchProgressInput.last_watched_at} before using this: a tick
169
+ * that omits `last_watched_at` does not move the title up the list, and
170
+ * `finished` has three states rather than two. A `finished` of `null` is
171
+ * dropped by this method rather than sent, matching what the server would do
172
+ * with it, so `finished` reaches the wire only as a real boolean.
173
+ *
174
+ * Use {@link saveMany} instead when you have more than a couple of rows -
175
+ * see its docs for why one request is not just faster but differently shaped.
176
+ *
177
+ * @throws {OmsError} `invalid_request` when `movie_id`, `video_id` or
178
+ * `movie_type` is blank.
179
+ * @throws {OmsApiError} 400 `"movie_id, video_id, movie_type are required"`
180
+ * from the server's own check, or a validation sentence such as
181
+ * `"Position must be greater than or equal to 0"`.
182
+ */
183
+ save(input: MovieWatchProgressInput, options?: RequestOptions): Promise<MovieWatchProgress>;
184
+ /**
185
+ * `POST /movie_watch_progresses/bulk` - upserts up to
186
+ * {@link MOVIE_WATCH_BULK_LIMIT} rows in ONE request and ONE transaction.
187
+ * `200`, with the saved rows in the order sent.
188
+ *
189
+ * ## Why this endpoint exists, and when to reach for it
190
+ *
191
+ * "Marcar temporada como vista" is one row per episode. A 24-episode season
192
+ * through {@link save} is 24 POSTs: 24 round trips, 24 chances for one to
193
+ * fail and leave the season half-marked, and 24 requests against the
194
+ * caller's 600/min ceiling. This collapses it into one.
195
+ *
196
+ * The transaction is the other half of the point, and it cuts both ways:
197
+ *
198
+ * - **use {@link saveMany}** for a statement about several rows at once that
199
+ * must be all-or-nothing - mark a season watched or unwatched, restore a
200
+ * device's offline queue, seed history on first sync. If any entry is
201
+ * invalid the whole batch rolls back and answers `400`, so you never end up
202
+ * with episodes 1-9 marked and 10-24 not.
203
+ * - **use {@link save}** for the continuous playback tick. One row, and a
204
+ * failure costs one tick that the next one will overwrite anyway. Batching
205
+ * ticks would trade a lost second for a lost minute.
206
+ *
207
+ * ## The silent-truncation trap this method closes
208
+ *
209
+ * The server keeps the first 200 entries: the rest are dropped without a
210
+ * word and the response is a cheerful `200` listing the 200 that were saved.
211
+ * A 300-episode batch would look like it worked. This method raises before
212
+ * sending instead, so split the work yourself - and note that separate
213
+ * batches are separate transactions, so a split is no longer atomic end to
214
+ * end.
215
+ *
216
+ * Retrying the whole batch is safe: every entry is the same upsert
217
+ * {@link save} performs.
218
+ *
219
+ * @throws {OmsError} `invalid_request` for an empty list, for more than
220
+ * {@link MOVIE_WATCH_BULK_LIMIT} entries, or for an entry missing
221
+ * `movie_id`, `video_id` or `movie_type`.
222
+ * @throws {OmsApiError} 400 `"items is required"` for an empty list that got
223
+ * through, or the first failing entry's validation sentence - and in that
224
+ * case NOTHING was saved.
225
+ */
226
+ saveMany(inputs: readonly MovieWatchProgressInput[], options?: RequestOptions): Promise<MovieWatchProgress[]>;
227
+ /**
228
+ * Marks one playable watched or unwatched, explicitly.
229
+ *
230
+ * Sugar over {@link save} that exists because this is the exact call the
231
+ * fixed bug was about. Marking something UNWATCHED sends `position: 0,
232
+ * duration: 0`, and with `finished` absent the server's `duration <= 0`
233
+ * guard leaves the stored flag as it was - so the tick never came off.
234
+ * Passing the boolean outright skips that guard and writes what you said.
235
+ *
236
+ * Defaults `position` and `duration` to `0` when you do not supply them,
237
+ * which is right for "mark unwatched" and harmless for "mark watched"
238
+ * precisely because the explicit flag stops the server deriving anything from
239
+ * them. Supply the real numbers when you have them; the progress bar reads
240
+ * them.
241
+ *
242
+ * `last_watched_at` is still yours to send, and still matters: marking an
243
+ * episode watched without one leaves the series where it was in the list.
244
+ */
245
+ setWatched(input: Omit<MovieWatchProgressInput, "finished">, watched: boolean, options?: RequestOptions): Promise<MovieWatchProgress>;
246
+ /**
247
+ * `DELETE /movie_watch_progresses/:id` - forgets ONE playable. `204`, empty
248
+ * body.
249
+ *
250
+ * The id is the progress row's primary key, which for a series is one
251
+ * episode. To forget a whole title use {@link forgetMovie}.
252
+ *
253
+ * @throws {OmsApiError} 404 `"Resource not found"` for a row that is not
254
+ * yours.
255
+ */
256
+ delete(id: Id, options?: RequestOptions): Promise<void>;
257
+ /**
258
+ * `DELETE /movie_watch_progresses/for_movie?movie_id=...` - forgets EVERY row
259
+ * for a title. `204`, empty body.
260
+ *
261
+ * This is the "remover de Continuar a ver" button. For a series it destroys
262
+ * the progress of every episode, not just the one on screen; there is no
263
+ * per-season form and no undo.
264
+ *
265
+ * Note the verb: despite the `?movie_id=` query string this is a **DELETE**,
266
+ * not a read. It is a collection route, so the `movie_id` is the addon's id
267
+ * for the title (an IMDb id, say), never a `movie_watch_progresses` primary
268
+ * key.
269
+ *
270
+ * `204` even when nothing matched, so the answer does not tell you whether
271
+ * anything was there.
272
+ *
273
+ * @throws {OmsError} `invalid_request` for a blank id.
274
+ * @throws {OmsApiError} 400 `"movie_id is required"`.
275
+ */
276
+ forgetMovie(movieId: string, options?: RequestOptions): Promise<void>;
277
+ }
@@ -24,24 +24,19 @@
24
24
  * OAuth access token gets `403 {"error":"insufficient_scope"}` on every
25
25
  * route in this file. Cookie sessions and personal tokens work; third-party
26
26
  * OAuth clients do not. See {@link MoviesNamespace}.
27
- * 3. **`PATCH /movie_addons/:id` wipes `manifest_json` unless you resend it.**
28
- * The controller assigns the key unconditionally, so a partial patch sends
29
- * `nil` into a `presence: true` validation and answers `400`. That is why
30
- * {@link UpdateMovieAddonInput.manifest_json} is REQUIRED here, and why
31
- * {@link MovieAddonsNamespace.moveToGroup} exists.
32
- * 4. **Listing collections has a side effect**: it is the only place that
27
+ * 3. **Listing collections has a side effect**: it is the only place that
33
28
  * creates the user's "Favoritos" row. See
34
29
  * {@link MovieCollectionsNamespace.list}.
35
- * 5. **`POST /movie_watch_progresses` is an upsert that answers `200`, not
30
+ * 4. **`POST /movie_watch_progresses` is an upsert that answers `200`, not
36
31
  * `201`**, and its identity is `(user, movie_id, video_id)` - `movie_type`
37
32
  * is NOT part of the key. It is one of the very few creates in the API that
38
33
  * breaks the 201 convention, because it is not really a create.
39
- * 6. **`finished` is a three-state field, not a boolean.** Omitted means "you
34
+ * 5. **`finished` is a three-state field, not a boolean.** Omitted means "you
40
35
  * decide from the position"; `true`/`false` means "the user said so". A
41
36
  * `null` is deleted by the controller and reads as omitted, which is
42
37
  * exactly the bug that once made "marcar como nao visto" silently do
43
38
  * nothing. See {@link MovieWatchProgressInput.finished}.
44
- * 7. **`last_watched_at` is only defaulted on INSERT.** The model does
39
+ * 6. **`last_watched_at` is only defaulted on INSERT.** The model does
45
40
  * `self.last_watched_at ||= Time.current`, so an upsert onto an existing row
46
41
  * that omits it keeps the OLD timestamp - and the Continue Watching list is
47
42
  * ordered by exactly that column. Always send one. See
@@ -53,7 +48,8 @@
53
48
  * never applies.
54
49
  */
55
50
  import { ApiClient, Resource } from "../http";
56
- import type { BaseRecord, Id, PageParams, Paginated, RequestOptions, Timestamp } from "../types";
51
+ import type { ListParams } from "../listing";
52
+ import type { BaseRecord, Id, Paginated, RequestOptions, Timestamp } from "../types";
57
53
  import type { User } from "./account";
58
54
  /**
59
55
  * What a title is. Stremio's own vocabulary, and the backend stores it as a
@@ -151,22 +147,10 @@ export interface CreateMovieAddonInput {
151
147
  */
152
148
  readonly movie_addon_group_id?: Id | null;
153
149
  }
154
- /**
155
- * Arguments for {@link MovieAddonsNamespace.update}.
156
- *
157
- * `manifest_json` is required, and that is not an oversight to work around.
158
- * `MovieAddonsController#movie_addon_params` is shared by create and update and
159
- * ends with an unconditional `permitted[:manifest_json] = params[:manifest_json]`,
160
- * so a PATCH that omits the key assigns `nil` over the stored manifest and then
161
- * trips `validates :manifest_json, presence: true`. The row survives (the save
162
- * failed) but the call is a `400`, which is how `moveAddonToGroup` in the web
163
- * frontend is broken today - it sends `{ movie_addon_group_id }` alone. Resend
164
- * the manifest you already hold; {@link MovieAddonsNamespace.moveToGroup} does
165
- * it for you.
166
- */
150
+ /** Arguments for {@link MovieAddonsNamespace.update}. Every field is optional; omitted ones are left alone. */
167
151
  export interface UpdateMovieAddonInput {
168
- /** Resend the stored manifest verbatim. See the interface docs for why. */
169
- readonly manifest_json: StremioManifest;
152
+ /** A replacement manifest. Must be a non-empty object. */
153
+ readonly manifest_json?: StremioManifest;
170
154
  /** `null` un-groups the addon. Omitting the key leaves the group alone. */
171
155
  readonly movie_addon_group_id?: Id | null;
172
156
  /**
@@ -185,12 +169,14 @@ export interface UpdateMovieAddonInput {
185
169
  * the query - so there is deliberately no way to list by
186
170
  * `movie_addon_group_id`. Group client-side off the field on each row.
187
171
  */
188
- export interface ListMovieAddonsParams extends PageParams {
172
+ export interface ListMovieAddonsParams extends ListParams<(typeof MOVIE_ADDON_FILTER_COLUMNS)[number]> {
189
173
  /** Exact match. Use it to split your own addons from the shared ones. */
190
174
  readonly userId?: Id;
191
175
  /** Exact match on the primary key. */
192
176
  readonly id?: Id;
193
177
  }
178
+ /** Filter columns of `GET /movie_addons`, on top of {@link BASE_FILTER_COLUMNS}. */
179
+ export declare const MOVIE_ADDON_FILTER_COLUMNS: readonly ["user_id"];
194
180
  /** Arguments for {@link MovieAddonGroupsNamespace.create}. */
195
181
  export interface CreateMovieAddonGroupInput {
196
182
  /** Required, at most {@link MOVIE_ADDON_GROUP_NAME_MAX_LENGTH} characters. */
@@ -207,10 +193,12 @@ export interface MovieAddonGroup extends BaseRecord {
207
193
  readonly name: string;
208
194
  }
209
195
  /** Filters for {@link MovieAddonGroupsNamespace.list}. */
210
- export interface ListMovieAddonGroupsParams extends PageParams {
196
+ export interface ListMovieAddonGroupsParams extends ListParams<never> {
211
197
  /** Exact match on the primary key. The only filter this index allows. */
212
198
  readonly id?: Id;
213
199
  }
200
+ /** `GET /movie_addon_groups` filters on {@link BASE_FILTER_COLUMNS} only. */
201
+ export declare const MOVIE_ADDON_GROUP_FILTER_COLUMNS: readonly [];
214
202
  /**
215
203
  * A share: one addon, or one whole group, handed to one other user.
216
204
  *
@@ -265,10 +253,12 @@ export interface CreateMovieAddonGrantInput {
265
253
  * one addon - those are `400`s. Filter on `grantor_id` / `grantee_id` /
266
254
  * `movie_addon_id` client-side after listing.
267
255
  */
268
- export interface ListMovieAddonGrantsParams extends PageParams {
256
+ export interface ListMovieAddonGrantsParams extends ListParams<never> {
269
257
  /** Exact match on the primary key. */
270
258
  readonly id?: Id;
271
259
  }
260
+ /** `GET /movie_addon_grants` filters on {@link BASE_FILTER_COLUMNS} only. */
261
+ export declare const MOVIE_ADDON_GRANT_FILTER_COLUMNS: readonly [];
272
262
  /** The manual kind: a collection the user created and may rename or delete. */
273
263
  export declare const MOVIE_COLLECTION_MANUAL_KIND = "manual";
274
264
  /**
@@ -351,7 +341,7 @@ export interface UpdateMovieCollectionInput {
351
341
  * Allowlist: `id`, `name`, `kind`, `created_at`, `updated_at`. Anything else is
352
342
  * `400 "Unknown search filter: ..."`.
353
343
  */
354
- export interface ListMovieCollectionsParams extends PageParams {
344
+ export interface ListMovieCollectionsParams extends ListParams<(typeof MOVIE_COLLECTION_FILTER_COLUMNS)[number]> {
355
345
  /** Exact match, or `IN (...)` when given an array. */
356
346
  readonly id?: Id | readonly Id[];
357
347
  /**
@@ -362,6 +352,8 @@ export interface ListMovieCollectionsParams extends PageParams {
362
352
  /** Exact match. `"favorites"` finds the one system row. */
363
353
  readonly kind?: MovieCollectionKind;
364
354
  }
355
+ /** Filter columns of `GET /movie_collections`. */
356
+ export declare const MOVIE_COLLECTION_FILTER_COLUMNS: readonly ["id", "name", "kind", "created_at", "updated_at"];
365
357
  /** Arguments for {@link MovieCollectionItemsNamespace.create}. */
366
358
  export interface CreateMovieCollectionItemInput {
367
359
  readonly movie_collection_id: Id;
@@ -379,7 +371,7 @@ export interface CreateMovieCollectionItemInput {
379
371
  * Allowlist: `id`, `movie_collection_id`, `movie_type`, `movie_id`,
380
372
  * `position`, `created_at`, `updated_at`.
381
373
  */
382
- export interface ListMovieCollectionItemsParams extends PageParams {
374
+ export interface ListMovieCollectionItemsParams extends ListParams<(typeof MOVIE_COLLECTION_ITEM_FILTER_COLUMNS)[number]> {
383
375
  /** Exact match, or `IN (...)` when given an array. */
384
376
  readonly id?: Id | readonly Id[];
385
377
  /**
@@ -395,6 +387,8 @@ export interface ListMovieCollectionItemsParams extends PageParams {
395
387
  /** Exact match on the sort key. */
396
388
  readonly position?: number;
397
389
  }
390
+ /** Filter columns of `GET /movie_collection_items`. */
391
+ export declare const MOVIE_COLLECTION_ITEM_FILTER_COLUMNS: readonly ["id", "movie_collection_id", "movie_type", "movie_id", "position", "created_at", "updated_at"];
398
392
  /**
399
393
  * Fraction of the runtime that counts as watched when the server derives
400
394
  * `finished` itself. Mirrors `MovieWatchProgress::FINISHED_THRESHOLD`.
@@ -730,25 +724,10 @@ export declare class MovieAddonsNamespace extends Resource {
730
724
  */
731
725
  create(input: CreateMovieAddonInput, options?: RequestOptions): Promise<MovieAddon>;
732
726
  /**
733
- * `PATCH /movie_addons/:id` - `200`.
727
+ * `PATCH /movie_addons/:id` - `200`. A partial update: omitted fields are
728
+ * left alone. Only the owner may update; a shared row is `401`.
734
729
  *
735
- * **This is not a partial update, whatever the verb says.**
736
- * `movie_addon_params` is shared between create and update and finishes with
737
- * an unconditional `permitted[:manifest_json] = params[:manifest_json]`, so
738
- * the key is always assigned - as `nil` when you did not send one. `nil` then
739
- * fails `validates :manifest_json, presence: true` and the whole call is
740
- * `400 "Manifest json can't be blank"`. Nothing is written; the row is fine.
741
- * It simply cannot be patched without resending the manifest.
742
- *
743
- * That is a live divergence: the web frontend's
744
- * `MovieAddonsService.update(id, { movie_addon_group_id })` sends the group
745
- * alone and therefore 400s. {@link UpdateMovieAddonInput.manifest_json} is
746
- * required here so the same mistake is a compile error, and
747
- * {@link moveToGroup} carries the manifest across for you.
748
- *
749
- * Only the owner may update: a shared row is `401`.
750
- *
751
- * @throws {OmsError} `invalid_request` when `manifest_json` is missing or empty.
730
+ * @throws {OmsError} `invalid_request` when `manifest_json` is given but empty.
752
731
  * @throws {OmsApiError} 404 for an id you cannot see, 401 for one you can see
753
732
  * but do not own.
754
733
  */
@@ -756,11 +735,6 @@ export declare class MovieAddonsNamespace extends Resource {
756
735
  /**
757
736
  * Files an addon under a group, or un-groups it with `null`.
758
737
  *
759
- * Sugar over {@link update} that exists purely because the endpoint demands
760
- * the manifest back on every patch. Pass the {@link MovieAddon} you already
761
- * hold and its `manifest_json` is resent unchanged; there is no extra request
762
- * and no fetch of the manifest.
763
- *
764
738
  * Refuses a shared addon before the round trip: the server would answer
765
739
  * `401`, and the message here says why.
766
740
  *