@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.
- package/README.md +113 -131
- package/dist/index.js +1049 -1246
- package/dist/types/auth/device.d.ts +1 -1
- package/dist/types/auth/index.d.ts +2 -2
- package/dist/types/auth/tokens.d.ts +15 -15
- package/dist/types/client.d.ts +10 -10
- package/dist/types/errors.d.ts +12 -15
- package/dist/types/http.d.ts +74 -118
- package/dist/types/index.d.ts +2 -2
- package/dist/types/internal/attachments.d.ts +17 -0
- package/dist/types/internal/helpers.d.ts +9 -0
- package/dist/types/listing.d.ts +90 -0
- package/dist/types/local/qr.d.ts +1 -1
- package/dist/types/local/wordlist.d.ts +2 -3
- package/dist/types/resources/account.d.ts +19 -19
- package/dist/types/resources/admin/authorizedApplications.d.ts +133 -0
- package/dist/types/resources/admin/chests.d.ts +51 -0
- package/dist/types/resources/admin/eventAlerts.d.ts +60 -0
- package/dist/types/resources/admin/identities.d.ts +99 -0
- package/dist/types/resources/admin/index.d.ts +77 -0
- package/dist/types/resources/admin/jobs.d.ts +97 -0
- package/dist/types/resources/admin/myOauthApplications.d.ts +282 -0
- package/dist/types/resources/admin/notepads.d.ts +49 -0
- package/dist/types/resources/admin/oauthApplications.d.ts +309 -0
- package/dist/types/resources/admin/quotas.d.ts +114 -0
- package/dist/types/resources/admin/shortLinks.d.ts +201 -0
- package/dist/types/resources/admin/types.d.ts +222 -0
- package/dist/types/resources/admin/vocalSeparations.d.ts +98 -0
- package/dist/types/resources/admin.d.ts +17 -13
- package/dist/types/resources/auth/index.d.ts +1 -1
- package/dist/types/resources/auth/passkeys.d.ts +127 -163
- package/dist/types/resources/auth/sessions.d.ts +116 -161
- package/dist/types/resources/chests.d.ts +27 -31
- package/dist/types/resources/content/analysis.d.ts +62 -0
- package/dist/types/resources/content/blogs.d.ts +471 -0
- package/dist/types/resources/content/feedbacks.d.ts +263 -0
- package/dist/types/resources/content/index.d.ts +52 -0
- package/dist/types/resources/content/intel/articles.d.ts +230 -0
- package/dist/types/resources/content/intel/config.d.ts +135 -0
- package/dist/types/resources/content/intel/index.d.ts +53 -0
- package/dist/types/resources/content/intel/items.d.ts +91 -0
- package/dist/types/resources/content/intel/reports.d.ts +108 -0
- package/dist/types/resources/content/intel/scripts.d.ts +152 -0
- package/dist/types/resources/content/intel/sources.d.ts +236 -0
- package/dist/types/resources/content/intel/stats.d.ts +105 -0
- package/dist/types/resources/content/intel/types.d.ts +86 -0
- package/dist/types/resources/content/jokes.d.ts +93 -0
- package/dist/types/resources/content/notifications.d.ts +147 -0
- package/dist/types/resources/content/serviceUsages.d.ts +73 -0
- package/dist/types/resources/content/servicesStatus.d.ts +194 -0
- package/dist/types/resources/content/siteConfig.d.ts +43 -0
- package/dist/types/resources/content/spaceInvaders.d.ts +154 -0
- package/dist/types/resources/content.d.ts +41 -236
- package/dist/types/resources/dynamicQrs.d.ts +29 -45
- package/dist/types/resources/forms.d.ts +37 -58
- package/dist/types/resources/jobs.d.ts +35 -44
- package/dist/types/resources/library/annotations.d.ts +162 -0
- package/dist/types/resources/library/books.d.ts +534 -0
- package/dist/types/resources/library/chat.d.ts +259 -0
- package/dist/types/resources/library/index.d.ts +39 -0
- package/dist/types/resources/library/shelves.d.ts +237 -0
- package/dist/types/resources/library/types.d.ts +120 -0
- package/dist/types/resources/library.d.ts +20 -22
- package/dist/types/resources/media.d.ts +48 -61
- package/dist/types/resources/movies/addons.d.ts +388 -0
- package/dist/types/resources/movies/collections.d.ts +352 -0
- package/dist/types/resources/movies/index.d.ts +29 -0
- package/dist/types/resources/movies/types.d.ts +50 -0
- package/dist/types/resources/movies/watchProgress.d.ts +277 -0
- package/dist/types/resources/movies.d.ts +27 -53
- package/dist/types/resources/music/artists.d.ts +182 -246
- package/dist/types/resources/music/imports.d.ts +190 -218
- package/dist/types/resources/music/index.d.ts +8 -7
- package/dist/types/resources/music/playlists.d.ts +85 -117
- package/dist/types/resources/music/social.d.ts +153 -228
- package/dist/types/resources/music/songs.d.ts +165 -227
- package/dist/types/resources/realtime.d.ts +75 -88
- package/dist/types/resources/shortLinks.d.ts +38 -47
- package/dist/types/resources/social/groupChats.d.ts +458 -0
- package/dist/types/resources/social/index.d.ts +19 -0
- package/dist/types/resources/social/messages.d.ts +424 -0
- package/dist/types/resources/social/relationships.d.ts +322 -0
- package/dist/types/resources/social/types.d.ts +37 -0
- package/dist/types/resources/social.d.ts +21 -3
- package/dist/types/resources/storage/upload.d.ts +42 -56
- package/dist/types/resources/storage.d.ts +94 -109
- package/dist/types/resources/tickets.d.ts +19 -10
- package/dist/types/resources/tools/backgroundRemoval.d.ts +11 -13
- package/dist/types/resources/tools/captions.d.ts +107 -135
- package/dist/types/resources/tools/upscale.d.ts +12 -16
- package/dist/types/types.d.ts +29 -38
- 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.
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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 {
|
|
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
|
-
/**
|
|
169
|
-
readonly manifest_json
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
*
|