@redseat/api 0.3.5 → 0.3.6

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.
@@ -483,6 +483,42 @@ export declare enum RsSort {
483
483
  Name = "name",
484
484
  Size = "size"
485
485
  }
486
+ export type MediaType = 'episode' | 'movie' | 'book' | 'song' | 'media';
487
+ export interface IWatched {
488
+ type: MediaType;
489
+ id: string;
490
+ userRef?: string;
491
+ date: number;
492
+ modified: number;
493
+ }
494
+ export interface IWatchedForAdd {
495
+ type: MediaType;
496
+ id: string;
497
+ date: number;
498
+ }
499
+ export interface IViewProgress {
500
+ type: MediaType;
501
+ id: string;
502
+ userRef: string;
503
+ progress: number;
504
+ parent?: string;
505
+ modified: number;
506
+ }
507
+ export interface IViewProgressForAdd {
508
+ type: MediaType;
509
+ id: string;
510
+ parent?: string;
511
+ progress: number;
512
+ }
513
+ export interface HistoryQuery {
514
+ sort?: RsSort;
515
+ order?: SqlOrder;
516
+ before?: number;
517
+ after?: number;
518
+ types?: MediaType[];
519
+ id?: string;
520
+ pageKey?: number;
521
+ }
486
522
  export type MovieSort = 'modified' | 'added' | 'created' | 'name' | 'digitalairdate';
487
523
  export interface DeletedQuery {
488
524
  after?: number;
package/dist/library.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Observable } from 'rxjs';
2
- import { IFile, ITag, IPerson, ISerie, IMovie, MediaRequest, IEpisode, ExternalImage, IBackupFile, ILibrary, SerieInMedia, DeletedQuery, RsDeleted, MovieSort, RsSort, SqlOrder, RsRequest, DetectedFaceResult, UnassignFaceResponse, RsGroupDownload } from './interfaces.js';
2
+ import { IFile, ITag, IPerson, ISerie, IMovie, MediaRequest, IEpisode, ExternalImage, IBackupFile, ILibrary, SerieInMedia, DeletedQuery, RsDeleted, MovieSort, RsSort, SqlOrder, RsRequest, DetectedFaceResult, UnassignFaceResponse, RsGroupDownload, IViewProgress, IWatched } from './interfaces.js';
3
3
  import { SSEMediasEvent, SSEUploadProgressEvent, SSEConvertProgressEvent, SSEEpisodesEvent, SSESeriesEvent, SSEMoviesEvent, SSEPeopleEvent, SSETagsEvent, SSELibraryStatusEvent, SSEMediaRatingEvent, SSEMediaProgressEvent } from './sse-types.js';
4
4
  import { EncryptFileOptions, EncryptedFile } from './encryption.js';
5
5
  export interface MediaForUpdate {
@@ -194,6 +194,9 @@ export declare class LibraryApi {
194
194
  updateMovie(movieId: string, updates: Partial<IMovie>): Promise<IMovie>;
195
195
  getMovieImages(movieId: string): Promise<ExternalImage[]>;
196
196
  setMovieWatched(movieId: string, date: number): Promise<void>;
197
+ getMovieWatched(movieId: string): Promise<IWatched>;
198
+ getMovieProgress(movieId: string): Promise<IViewProgress>;
199
+ setMovieProgress(movieId: string, progress: number): Promise<void>;
197
200
  searchMovies(name: string): Promise<IMovie[]>;
198
201
  movieRename(movieId: string, newName: string): Promise<IMovie>;
199
202
  updateMoviePoster(movieId: string, poster: FormData, type: string): Promise<void>;
@@ -214,6 +217,9 @@ export declare class LibraryApi {
214
217
  updatePersonPortrait(personId: string, portrait: FormData): Promise<void>;
215
218
  searchSeries(name: string): Promise<ISerie[]>;
216
219
  setEpisodeWatched(serieId: string, season: number, number: number, date: number): Promise<void>;
220
+ getEpisodeWatched(serieId: string, season: number, episode: number): Promise<IWatched>;
221
+ getEpisodeProgress(serieId: string, season: number, episode: number): Promise<IViewProgress>;
222
+ setEpisodeProgress(serieId: string, season: number, episode: number, progress: number): Promise<void>;
217
223
  /**
218
224
  * Searches for available media sources for a specific episode.
219
225
  * @param serieId - The series identifier
package/dist/library.js CHANGED
@@ -368,6 +368,17 @@ export class LibraryApi {
368
368
  async setMovieWatched(movieId, date) {
369
369
  await this.client.post(this.getUrl(`/movies/${movieId}/watched`), { date });
370
370
  }
371
+ async getMovieWatched(movieId) {
372
+ const res = await this.client.get(this.getUrl(`/movies/${movieId}/watched`));
373
+ return res.data;
374
+ }
375
+ async getMovieProgress(movieId) {
376
+ const res = await this.client.get(this.getUrl(`/movies/${movieId}/progress`));
377
+ return res.data;
378
+ }
379
+ async setMovieProgress(movieId, progress) {
380
+ await this.client.post(this.getUrl(`/movies/${movieId}/progress`), { progress });
381
+ }
371
382
  async searchMovies(name) {
372
383
  const res = await this.client.get(this.getUrl(`/movies/search?name=${name}`));
373
384
  return res.data;
@@ -460,6 +471,17 @@ export class LibraryApi {
460
471
  async setEpisodeWatched(serieId, season, number, date) {
461
472
  await this.client.post(this.getUrl(`/series/${serieId}/seasons/${season}/episodes/${number}/watched`), { date });
462
473
  }
474
+ async getEpisodeWatched(serieId, season, episode) {
475
+ const res = await this.client.get(this.getUrl(`/series/${serieId}/seasons/${season}/episodes/${episode}/watched`));
476
+ return res.data;
477
+ }
478
+ async getEpisodeProgress(serieId, season, episode) {
479
+ const res = await this.client.get(this.getUrl(`/series/${serieId}/seasons/${season}/episodes/${episode}/progress`));
480
+ return res.data;
481
+ }
482
+ async setEpisodeProgress(serieId, season, episode, progress) {
483
+ await this.client.post(this.getUrl(`/series/${serieId}/seasons/${season}/episodes/${episode}/progress`), { progress });
484
+ }
463
485
  /**
464
486
  * Searches for available media sources for a specific episode.
465
487
  * @param serieId - The series identifier
package/dist/server.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { RedseatClient } from './client.js';
2
- import { ILibrary, IPlugin, ICredential } from './interfaces.js';
2
+ import { ILibrary, IPlugin, ICredential, IWatched, IWatchedForAdd, IViewProgress, IViewProgressForAdd, HistoryQuery } from './interfaces.js';
3
3
  export declare class ServerApi {
4
4
  private client;
5
5
  constructor(client: RedseatClient);
@@ -19,4 +19,10 @@ export declare class ServerApi {
19
19
  deleteCredential(id: string): Promise<void>;
20
20
  saveOAuthCredentials(pluginId: string, params: Record<string, string>): Promise<void>;
21
21
  addLibraryCredential(credential: any): Promise<ILibrary>;
22
+ getHistory(query?: HistoryQuery): Promise<IWatched[]>;
23
+ addToHistory(watched: IWatchedForAdd): Promise<void>;
24
+ getProgressById(id: string): Promise<IViewProgress | null>;
25
+ addProgress(progress: IViewProgressForAdd): Promise<void>;
26
+ getAdminHistory(): Promise<IWatched[]>;
27
+ importHistory(watcheds: IWatchedForAdd[]): Promise<void>;
22
28
  }
package/dist/server.js CHANGED
@@ -48,4 +48,44 @@ export class ServerApi {
48
48
  const res = await this.client.post('/libraries/credential', credential);
49
49
  return res.data;
50
50
  }
51
+ // History methods
52
+ async getHistory(query) {
53
+ const params = {};
54
+ if (query) {
55
+ if (query.sort !== undefined)
56
+ params.sort = query.sort;
57
+ if (query.order !== undefined)
58
+ params.order = query.order;
59
+ if (query.before !== undefined)
60
+ params.before = query.before;
61
+ if (query.after !== undefined)
62
+ params.after = query.after;
63
+ if (query.types !== undefined && query.types.length > 0)
64
+ params.types = query.types;
65
+ if (query.id !== undefined)
66
+ params.id = query.id;
67
+ if (query.pageKey !== undefined)
68
+ params.pageKey = query.pageKey;
69
+ }
70
+ const res = await this.client.get('/users/me/history', { params });
71
+ return res.data;
72
+ }
73
+ async addToHistory(watched) {
74
+ await this.client.post('/users/me/history', watched);
75
+ }
76
+ async getProgressById(id) {
77
+ const res = await this.client.get(`/users/me/history/progress/${id}`);
78
+ return res.data;
79
+ }
80
+ async addProgress(progress) {
81
+ await this.client.post('/users/me/history/progress', progress);
82
+ }
83
+ // Admin history methods
84
+ async getAdminHistory() {
85
+ const res = await this.client.get('/users/admin/history');
86
+ return res.data;
87
+ }
88
+ async importHistory(watcheds) {
89
+ await this.client.post('/users/admin/history/import', watcheds);
90
+ }
51
91
  }
package/libraries.md CHANGED
@@ -912,6 +912,62 @@ Marks an episode as watched.
912
912
  await libraryApi.setEpisodeWatched('serie-id', 1, 1, Date.now());
913
913
  ```
914
914
 
915
+ ### `getEpisodeWatched(serieId: string, season: number, episode: number): Promise<IWatched>`
916
+
917
+ Gets the watched status for an episode.
918
+
919
+ **Parameters:**
920
+
921
+ - `serieId`: The ID of the series
922
+ - `season`: Season number
923
+ - `episode`: Episode number
924
+
925
+ **Returns:** Promise resolving to an `IWatched` object containing watched date and metadata
926
+
927
+ **Example:**
928
+
929
+ ```typescript
930
+ const watched = await libraryApi.getEpisodeWatched('serie-id', 1, 1);
931
+ console.log(`Watched on: ${new Date(watched.date).toLocaleDateString()}`);
932
+ ```
933
+
934
+ ### `getEpisodeProgress(serieId: string, season: number, episode: number): Promise<IViewProgress>`
935
+
936
+ Gets the view progress for an episode.
937
+
938
+ **Parameters:**
939
+
940
+ - `serieId`: The ID of the series
941
+ - `season`: Season number
942
+ - `episode`: Episode number
943
+
944
+ **Returns:** Promise resolving to an `IViewProgress` object containing progress value
945
+
946
+ **Example:**
947
+
948
+ ```typescript
949
+ const progress = await libraryApi.getEpisodeProgress('serie-id', 1, 1);
950
+ console.log(`Progress: ${progress.progress}ms`);
951
+ ```
952
+
953
+ ### `setEpisodeProgress(serieId: string, season: number, episode: number, progress: number): Promise<void>`
954
+
955
+ Sets the view progress for an episode.
956
+
957
+ **Parameters:**
958
+
959
+ - `serieId`: The ID of the series
960
+ - `season`: Season number
961
+ - `episode`: Episode number
962
+ - `progress`: Progress value (typically in milliseconds for video playback position)
963
+
964
+ **Example:**
965
+
966
+ ```typescript
967
+ // Save progress at 30 minutes
968
+ await libraryApi.setEpisodeProgress('serie-id', 1, 1, 1800000);
969
+ ```
970
+
915
971
  ---
916
972
 
917
973
  ## Movies
@@ -1034,6 +1090,56 @@ Marks a movie as watched.
1034
1090
  await libraryApi.setMovieWatched('movie-id', Date.now());
1035
1091
  ```
1036
1092
 
1093
+ ### `getMovieWatched(movieId: string): Promise<IWatched>`
1094
+
1095
+ Gets the watched status for a movie.
1096
+
1097
+ **Parameters:**
1098
+
1099
+ - `movieId`: The ID of the movie
1100
+
1101
+ **Returns:** Promise resolving to an `IWatched` object containing watched date and metadata
1102
+
1103
+ **Example:**
1104
+
1105
+ ```typescript
1106
+ const watched = await libraryApi.getMovieWatched('movie-id');
1107
+ console.log(`Watched on: ${new Date(watched.date).toLocaleDateString()}`);
1108
+ ```
1109
+
1110
+ ### `getMovieProgress(movieId: string): Promise<IViewProgress>`
1111
+
1112
+ Gets the view progress for a movie.
1113
+
1114
+ **Parameters:**
1115
+
1116
+ - `movieId`: The ID of the movie
1117
+
1118
+ **Returns:** Promise resolving to an `IViewProgress` object containing progress value
1119
+
1120
+ **Example:**
1121
+
1122
+ ```typescript
1123
+ const progress = await libraryApi.getMovieProgress('movie-id');
1124
+ console.log(`Progress: ${progress.progress}ms`);
1125
+ ```
1126
+
1127
+ ### `setMovieProgress(movieId: string, progress: number): Promise<void>`
1128
+
1129
+ Sets the view progress for a movie.
1130
+
1131
+ **Parameters:**
1132
+
1133
+ - `movieId`: The ID of the movie
1134
+ - `progress`: Progress value (typically in milliseconds for video playback position)
1135
+
1136
+ **Example:**
1137
+
1138
+ ```typescript
1139
+ // Save progress at 45 minutes
1140
+ await libraryApi.setMovieProgress('movie-id', 2700000);
1141
+ ```
1142
+
1037
1143
  ### `searchMovies(name: string): Promise<IMovie[]>`
1038
1144
 
1039
1145
  Searches for movies by name.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redseat/api",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "description": "TypeScript API client library for interacting with Redseat servers",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/server.md CHANGED
@@ -222,6 +222,127 @@ const library = await serverApi.addLibraryCredential({
222
222
  });
223
223
  ```
224
224
 
225
+ ## History Methods
226
+
227
+ These methods manage the user's watch history and progress tracking across all libraries.
228
+
229
+ ### `getHistory(query?: HistoryQuery): Promise<IWatched[]>`
230
+
231
+ Retrieves the current user's watch history.
232
+
233
+ **Parameters:**
234
+ - `query`: Optional query object with filtering parameters:
235
+ - `sort`: Sort key using `RsSort` enum
236
+ - `order`: Sort direction using `SqlOrder` enum (`ASC` or `DESC`)
237
+ - `before`: Filter entries before this timestamp
238
+ - `after`: Filter entries after this timestamp
239
+ - `types`: Array of `MediaType` to filter by (`'episode'`, `'movie'`, `'book'`, `'song'`, `'media'`)
240
+ - `id`: Filter by specific ID
241
+ - `pageKey`: Pagination key
242
+
243
+ **Returns:** Promise resolving to an array of `IWatched` objects
244
+
245
+ **Example:**
246
+ ```typescript
247
+ // Get all history
248
+ const history = await serverApi.getHistory();
249
+
250
+ // Get recent movie watch history
251
+ const movieHistory = await serverApi.getHistory({
252
+ types: ['movie'],
253
+ order: SqlOrder.DESC,
254
+ after: Date.now() - 86400000 * 30 // Last 30 days
255
+ });
256
+ ```
257
+
258
+ ### `addToHistory(watched: IWatchedForAdd): Promise<void>`
259
+
260
+ Adds an entry to the user's watch history.
261
+
262
+ **Parameters:**
263
+ - `watched`: Object containing:
264
+ - `type`: The `MediaType` (`'episode'`, `'movie'`, `'book'`, `'song'`, `'media'`)
265
+ - `id`: The ID of the watched item
266
+ - `date`: Timestamp when it was watched
267
+
268
+ **Returns:** Promise resolving when the entry is added
269
+
270
+ **Example:**
271
+ ```typescript
272
+ await serverApi.addToHistory({
273
+ type: 'movie',
274
+ id: 'movie-123',
275
+ date: Date.now()
276
+ });
277
+ ```
278
+
279
+ ### `getProgressById(id: string): Promise<IViewProgress | null>`
280
+
281
+ Gets the view progress for a specific item by ID.
282
+
283
+ **Parameters:**
284
+ - `id`: The ID of the item to get progress for
285
+
286
+ **Returns:** Promise resolving to `IViewProgress` object or `null` if not found
287
+
288
+ **Example:**
289
+ ```typescript
290
+ const progress = await serverApi.getProgressById('movie-123');
291
+ if (progress) {
292
+ console.log(`Progress: ${progress.progress}ms`);
293
+ }
294
+ ```
295
+
296
+ ### `addProgress(progress: IViewProgressForAdd): Promise<void>`
297
+
298
+ Adds or updates view progress for an item.
299
+
300
+ **Parameters:**
301
+ - `progress`: Object containing:
302
+ - `type`: The `MediaType`
303
+ - `id`: The ID of the item
304
+ - `progress`: Progress value (typically in milliseconds for video)
305
+ - `parent`: Optional parent ID (e.g., series ID for episodes)
306
+
307
+ **Returns:** Promise resolving when progress is saved
308
+
309
+ **Example:**
310
+ ```typescript
311
+ await serverApi.addProgress({
312
+ type: 'movie',
313
+ id: 'movie-123',
314
+ progress: 3600000 // 1 hour in milliseconds
315
+ });
316
+ ```
317
+
318
+ ### `getAdminHistory(): Promise<IWatched[]>`
319
+
320
+ **Admin only.** Retrieves watch history for all users.
321
+
322
+ **Returns:** Promise resolving to an array of `IWatched` objects
323
+
324
+ **Example:**
325
+ ```typescript
326
+ const allHistory = await serverApi.getAdminHistory();
327
+ ```
328
+
329
+ ### `importHistory(watcheds: IWatchedForAdd[]): Promise<void>`
330
+
331
+ **Admin only.** Imports watch history entries in bulk.
332
+
333
+ **Parameters:**
334
+ - `watcheds`: Array of `IWatchedForAdd` objects to import
335
+
336
+ **Returns:** Promise resolving when import is complete
337
+
338
+ **Example:**
339
+ ```typescript
340
+ await serverApi.importHistory([
341
+ { type: 'movie', id: 'movie-1', date: Date.now() - 86400000 },
342
+ { type: 'episode', id: 'episode-1', date: Date.now() }
343
+ ]);
344
+ ```
345
+
225
346
  ## Usage Examples
226
347
 
227
348
  ### Complete Workflow: Create Library and Get Info