ichime-ts-api-client 1.0.3 → 1.0.5
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/dist/index.d.mts +293 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +691 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +9 -6
- package/.github/workflows/publish.yml +0 -34
- package/biome.json +0 -52
- package/src/api/api-client.ts +0 -173
- package/src/api/date-decoder.ts +0 -57
- package/src/api/errors.ts +0 -43
- package/src/api/index.ts +0 -4
- package/src/api/types/episode.ts +0 -16
- package/src/api/types/index.ts +0 -15
- package/src/api/types/series-type.ts +0 -10
- package/src/api/types/series.ts +0 -44
- package/src/api/types/translation.ts +0 -30
- package/src/http-session.ts +0 -99
- package/src/index.ts +0 -53
- package/src/web/errors.ts +0 -43
- package/src/web/helpers.ts +0 -70
- package/src/web/index.ts +0 -4
- package/src/web/types/anime-list-status.ts +0 -70
- package/src/web/types/anime-list.ts +0 -23
- package/src/web/types/index.ts +0 -21
- package/src/web/types/moment.ts +0 -25
- package/src/web/types/personal-episode.ts +0 -19
- package/src/web/types/profile.ts +0 -5
- package/src/web/web-client.ts +0 -810
- package/tests/auth.test.ts +0 -92
- package/tsconfig.json +0 -24
- package/tsdown.config.ts +0 -11
- package/vitest.config.ts +0 -14
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { CookieJar } from "tough-cookie";
|
|
2
|
+
import * as cheerio from "cheerio";
|
|
3
|
+
|
|
4
|
+
//#region src/http-session.d.ts
|
|
5
|
+
interface RequestOptions extends Omit<RequestInit, "dispatcher"> {
|
|
6
|
+
timeout?: number;
|
|
7
|
+
}
|
|
8
|
+
declare class HttpSession {
|
|
9
|
+
readonly jar: CookieJar;
|
|
10
|
+
readonly baseUrl: string;
|
|
11
|
+
constructor(baseUrl: string);
|
|
12
|
+
request(path: string, options?: RequestOptions): Promise<Response>;
|
|
13
|
+
getCookie(name: string): Promise<string | undefined>;
|
|
14
|
+
getCookieString(): Promise<string>;
|
|
15
|
+
setCookie(name: string, value: string): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/api/types/series-type.d.ts
|
|
19
|
+
type SeriesType = "tv" | "tv_special" | "movie" | "ova" | "music" | "ona" | "special" | "pv" | "cm";
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/api/types/series.d.ts
|
|
22
|
+
interface Titles {
|
|
23
|
+
ru: string | null;
|
|
24
|
+
romaji: string | null;
|
|
25
|
+
}
|
|
26
|
+
interface Series {
|
|
27
|
+
id: number;
|
|
28
|
+
title: string;
|
|
29
|
+
titles: Titles;
|
|
30
|
+
posterUrl: string | null;
|
|
31
|
+
myAnimeListScore: string;
|
|
32
|
+
season: string;
|
|
33
|
+
type: SeriesType | null;
|
|
34
|
+
year: number | null;
|
|
35
|
+
}
|
|
36
|
+
interface SeriesFullGenre {
|
|
37
|
+
id: number;
|
|
38
|
+
title: string;
|
|
39
|
+
}
|
|
40
|
+
interface SeriesFullDescription {
|
|
41
|
+
source: string;
|
|
42
|
+
value: string;
|
|
43
|
+
}
|
|
44
|
+
interface SeriesFull {
|
|
45
|
+
id: number;
|
|
46
|
+
title: string;
|
|
47
|
+
posterUrl: string | null;
|
|
48
|
+
myAnimeListScore: string;
|
|
49
|
+
myAnimeListId: number;
|
|
50
|
+
isAiring: number;
|
|
51
|
+
numberOfEpisodes: number;
|
|
52
|
+
season: string;
|
|
53
|
+
type: SeriesType | null;
|
|
54
|
+
titles: Titles;
|
|
55
|
+
genres: SeriesFullGenre[] | null;
|
|
56
|
+
descriptions: SeriesFullDescription[] | null;
|
|
57
|
+
episodes: Episode[] | null;
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/api/types/translation.d.ts
|
|
61
|
+
interface Translation {
|
|
62
|
+
id: number;
|
|
63
|
+
activeDateTime: Date;
|
|
64
|
+
addedDateTime: Date;
|
|
65
|
+
isActive: number;
|
|
66
|
+
qualityType: string;
|
|
67
|
+
typeKind: string;
|
|
68
|
+
typeLang: string;
|
|
69
|
+
authorsSummary: string;
|
|
70
|
+
height: number;
|
|
71
|
+
}
|
|
72
|
+
interface TranslationFull {
|
|
73
|
+
episode: Episode;
|
|
74
|
+
series: Series;
|
|
75
|
+
}
|
|
76
|
+
interface TranslationEmbedStream {
|
|
77
|
+
height: number;
|
|
78
|
+
urls: string[];
|
|
79
|
+
}
|
|
80
|
+
interface TranslationEmbed {
|
|
81
|
+
stream: TranslationEmbedStream[];
|
|
82
|
+
subtitlesUrl: string | null;
|
|
83
|
+
subtitlesVttUrl: string | null;
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/api/types/episode.d.ts
|
|
87
|
+
interface Episode {
|
|
88
|
+
id: number;
|
|
89
|
+
episodeFull: string;
|
|
90
|
+
episodeInt: string;
|
|
91
|
+
episodeType: string;
|
|
92
|
+
firstUploadedDateTime: Date;
|
|
93
|
+
isActive: number;
|
|
94
|
+
isFirstUploaded: number;
|
|
95
|
+
}
|
|
96
|
+
interface EpisodeFull extends Episode {
|
|
97
|
+
seriesId: number;
|
|
98
|
+
translations: Translation[];
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/api/api-client.d.ts
|
|
102
|
+
interface ListSeriesOptions {
|
|
103
|
+
query?: string;
|
|
104
|
+
limit?: number;
|
|
105
|
+
offset?: number;
|
|
106
|
+
chips?: Record<string, string>;
|
|
107
|
+
myAnimeListId?: number;
|
|
108
|
+
}
|
|
109
|
+
interface ListEpisodesOptions {
|
|
110
|
+
seriesId?: number;
|
|
111
|
+
limit?: number;
|
|
112
|
+
offset?: number;
|
|
113
|
+
}
|
|
114
|
+
declare class ApiClient {
|
|
115
|
+
private readonly session;
|
|
116
|
+
constructor(session: HttpSession);
|
|
117
|
+
sendRequest<T>(endpoint: string, queryItems?: Record<string, string>): Promise<T>;
|
|
118
|
+
private isApiErrorResponse;
|
|
119
|
+
private isApiSuccessfulResponse;
|
|
120
|
+
getSeries(seriesId: number): Promise<SeriesFull>;
|
|
121
|
+
getEpisode(episodeId: number): Promise<EpisodeFull>;
|
|
122
|
+
listSeries(options?: ListSeriesOptions): Promise<Series[]>;
|
|
123
|
+
listEpisodes(options?: ListEpisodesOptions): Promise<Episode[]>;
|
|
124
|
+
getTranslation(translationId: number): Promise<TranslationFull>;
|
|
125
|
+
getTranslationEmbed(translationId: number): Promise<TranslationEmbed>;
|
|
126
|
+
}
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/api/date-decoder.d.ts
|
|
129
|
+
/**
|
|
130
|
+
* Парсит даты в формате API Anime365: "yyyy-MM-dd HH:mm:ss" в московской таймзоне.
|
|
131
|
+
*/
|
|
132
|
+
declare function parseApiDate(dateString: string): Date;
|
|
133
|
+
/**
|
|
134
|
+
* Проверяет, является ли дата "пустой" датой-заглушкой API (2000-01-01 00:00:00).
|
|
135
|
+
*/
|
|
136
|
+
declare function isEmptyDate(date: Date): boolean;
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/api/errors.d.ts
|
|
139
|
+
declare class ApiError extends Error {
|
|
140
|
+
readonly code: number;
|
|
141
|
+
constructor(code: number, message: string);
|
|
142
|
+
static authenticationRequired(): ApiError;
|
|
143
|
+
static notFound(): ApiError;
|
|
144
|
+
static other(code: number, message: string): ApiError;
|
|
145
|
+
}
|
|
146
|
+
declare class ApiClientError extends Error {
|
|
147
|
+
readonly cause?: (ApiError | Error) | undefined;
|
|
148
|
+
constructor(message: string, cause?: (ApiError | Error) | undefined);
|
|
149
|
+
static canNotDecodeResponseJson(error?: Error): ApiClientError;
|
|
150
|
+
static apiError(error: ApiError): ApiClientError;
|
|
151
|
+
static requestFailed(error?: Error): ApiClientError;
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region src/web/errors.d.ts
|
|
155
|
+
declare class WebClientError extends Error {
|
|
156
|
+
constructor(message: string);
|
|
157
|
+
static couldNotConvertResponseToHttpResponse(): WebClientError;
|
|
158
|
+
static couldNotConvertResponseDataToString(): WebClientError;
|
|
159
|
+
static badStatusCode(statusCode: number): WebClientError;
|
|
160
|
+
static authenticationRequired(): WebClientError;
|
|
161
|
+
static couldNotParseHtml(): WebClientError;
|
|
162
|
+
static unknownError(error: Error): WebClientError;
|
|
163
|
+
}
|
|
164
|
+
declare class WebClientTypeNormalizationError extends Error {
|
|
165
|
+
constructor(message: string);
|
|
166
|
+
static failedCreatingDTOFromHTMLElement(message: string): WebClientTypeNormalizationError;
|
|
167
|
+
}
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/web/helpers.d.ts
|
|
170
|
+
/**
|
|
171
|
+
* Извлекает ID сериала и эпизода из URL вида /catalog/{seriesId}-{slug}/{episodeId}-{slug}
|
|
172
|
+
*/
|
|
173
|
+
declare function extractIdentifiersFromUrl(url: URL): {
|
|
174
|
+
seriesId: number | null;
|
|
175
|
+
episodeId: number | null;
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Парсит строку длительности формата "mm:ss" или "hh:mm:ss" в секунды.
|
|
179
|
+
*/
|
|
180
|
+
declare function parseDurationString(durationString: string): number | null;
|
|
181
|
+
/**
|
|
182
|
+
* Парсит дату в формате "dd.MM.yyyy HH:mm" в московской таймзоне.
|
|
183
|
+
*/
|
|
184
|
+
declare function parseWebDate(dateString: string): Date | null;
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/web/types/anime-list-status.d.ts
|
|
187
|
+
type AnimeListEntryStatus = "watching" | "completed" | "onHold" | "dropped" | "planned" | "notInList";
|
|
188
|
+
declare const AnimeListEntryStatusNumericId: Record<AnimeListEntryStatus, number>;
|
|
189
|
+
declare function animeListEntryStatusFromNumericId(id: number): AnimeListEntryStatus | null;
|
|
190
|
+
type AnimeListCategory = "watching" | "completed" | "onHold" | "dropped" | "planned";
|
|
191
|
+
declare const AnimeListCategoryWebPath: Record<AnimeListCategory, string>;
|
|
192
|
+
declare const AnimeListCategoryNumericId: Record<AnimeListCategory, number>;
|
|
193
|
+
declare function animeListCategoryFromNumericId(id: number): AnimeListCategory | null;
|
|
194
|
+
//#endregion
|
|
195
|
+
//#region src/web/types/anime-list.d.ts
|
|
196
|
+
interface AnimeListEntry {
|
|
197
|
+
seriesId: number;
|
|
198
|
+
seriesTitleFull: string;
|
|
199
|
+
episodesWatched: number;
|
|
200
|
+
episodesTotal: number | null;
|
|
201
|
+
score: number | null;
|
|
202
|
+
}
|
|
203
|
+
interface AnimeListEditableEntry {
|
|
204
|
+
episodesWatched: number;
|
|
205
|
+
status: AnimeListEntryStatus;
|
|
206
|
+
score: number | null;
|
|
207
|
+
commentary: string | null;
|
|
208
|
+
}
|
|
209
|
+
interface EditAnimeListResult {
|
|
210
|
+
id: number;
|
|
211
|
+
status: string;
|
|
212
|
+
score: string;
|
|
213
|
+
episodes: string;
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
//#region src/web/types/moment.d.ts
|
|
217
|
+
interface MomentPreview {
|
|
218
|
+
momentId: number;
|
|
219
|
+
coverUrl: string;
|
|
220
|
+
momentTitle: string;
|
|
221
|
+
sourceDescription: string;
|
|
222
|
+
/** Duration in seconds */
|
|
223
|
+
durationSeconds: number;
|
|
224
|
+
}
|
|
225
|
+
interface MomentDetails {
|
|
226
|
+
seriesId: number;
|
|
227
|
+
seriesTitle: string;
|
|
228
|
+
episodeId: number;
|
|
229
|
+
}
|
|
230
|
+
interface VideoSource {
|
|
231
|
+
height: number;
|
|
232
|
+
urls: string[];
|
|
233
|
+
}
|
|
234
|
+
interface MomentEmbed {
|
|
235
|
+
videoUrl: string;
|
|
236
|
+
}
|
|
237
|
+
type MomentSorting = "new" | "old" | "popular";
|
|
238
|
+
//#endregion
|
|
239
|
+
//#region src/web/types/personal-episode.d.ts
|
|
240
|
+
interface NewPersonalEpisode {
|
|
241
|
+
seriesId: number;
|
|
242
|
+
seriesPosterUrl: string;
|
|
243
|
+
seriesTitleRu: string;
|
|
244
|
+
seriesTitleRomaji: string;
|
|
245
|
+
episodeId: number;
|
|
246
|
+
episodeNumberLabel: string;
|
|
247
|
+
episodeUpdateType: string;
|
|
248
|
+
}
|
|
249
|
+
interface NewRecentEpisode {
|
|
250
|
+
seriesId: number;
|
|
251
|
+
seriesPosterUrl: string;
|
|
252
|
+
seriesTitleRu: string;
|
|
253
|
+
seriesTitleRomaji: string;
|
|
254
|
+
episodeId: number;
|
|
255
|
+
episodeNumberLabel: string;
|
|
256
|
+
episodeUploadedAt: Date;
|
|
257
|
+
}
|
|
258
|
+
//#endregion
|
|
259
|
+
//#region src/web/types/profile.d.ts
|
|
260
|
+
interface Profile {
|
|
261
|
+
id: number;
|
|
262
|
+
name: string;
|
|
263
|
+
avatarUrl: string;
|
|
264
|
+
}
|
|
265
|
+
//#endregion
|
|
266
|
+
//#region src/web/web-client.d.ts
|
|
267
|
+
declare class WebClient {
|
|
268
|
+
private readonly session;
|
|
269
|
+
constructor(session: HttpSession);
|
|
270
|
+
get baseUrl(): string;
|
|
271
|
+
sendRequest(path: string, queryItems?: Record<string, string>): Promise<string>;
|
|
272
|
+
sendPostRequest(path: string, queryItems?: Record<string, string>, formData?: Record<string, string>): Promise<string>;
|
|
273
|
+
parseHtml(html: string): cheerio.CheerioAPI;
|
|
274
|
+
login(username: string, password: string): Promise<void>;
|
|
275
|
+
getProfile(): Promise<Profile>;
|
|
276
|
+
getPersonalEpisodes(page: number): Promise<NewPersonalEpisode[]>;
|
|
277
|
+
private parsePersonalEpisode;
|
|
278
|
+
getRecentEpisodes(page: number): Promise<NewRecentEpisode[]>;
|
|
279
|
+
private parseRecentEpisode;
|
|
280
|
+
getAnimeList(userId: number, category: AnimeListCategory): Promise<AnimeListEntry[]>;
|
|
281
|
+
private parseAnimeListEntry;
|
|
282
|
+
getAnimeListEditableEntry(seriesId: number): Promise<AnimeListEditableEntry>;
|
|
283
|
+
editAnimeListEntry(seriesId: number, score: number, episodes: number, status: number, comment: string): Promise<void>;
|
|
284
|
+
markEpisodeAsWatched(translationId: number): Promise<void>;
|
|
285
|
+
getMoments(page: number, sort?: MomentSorting): Promise<MomentPreview[]>;
|
|
286
|
+
getMomentsBySeries(seriesId: number, page: number): Promise<MomentPreview[]>;
|
|
287
|
+
private parseMomentPreview;
|
|
288
|
+
getMomentDetails(momentId: number): Promise<MomentDetails>;
|
|
289
|
+
getMomentEmbed(momentId: number): Promise<MomentEmbed>;
|
|
290
|
+
}
|
|
291
|
+
//#endregion
|
|
292
|
+
export { type AnimeListCategory, AnimeListCategoryNumericId, AnimeListCategoryWebPath, type AnimeListEditableEntry, type AnimeListEntry, type AnimeListEntryStatus, AnimeListEntryStatusNumericId, ApiClient, ApiClientError, ApiError, type EditAnimeListResult, type Episode, type EpisodeFull, HttpSession, type ListEpisodesOptions, type ListSeriesOptions, type MomentDetails, type MomentEmbed, type MomentPreview, type MomentSorting, type NewPersonalEpisode, type NewRecentEpisode, type Profile, type RequestOptions, type Series, type SeriesFull, type SeriesFullDescription, type SeriesFullGenre, type SeriesType, type Titles, type Translation, type TranslationEmbed, type TranslationEmbedStream, type TranslationFull, type VideoSource, WebClient, WebClientError, WebClientTypeNormalizationError, animeListCategoryFromNumericId, animeListEntryStatusFromNumericId, extractIdentifiersFromUrl, isEmptyDate, parseApiDate, parseDurationString, parseWebDate };
|
|
293
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/http-session.ts","../src/api/types/series-type.ts","../src/api/types/series.ts","../src/api/types/translation.ts","../src/api/types/episode.ts","../src/api/api-client.ts","../src/api/date-decoder.ts","../src/api/errors.ts","../src/web/errors.ts","../src/web/helpers.ts","../src/web/types/anime-list-status.ts","../src/web/types/anime-list.ts","../src/web/types/moment.ts","../src/web/types/personal-episode.ts","../src/web/types/profile.ts","../src/web/web-client.ts"],"mappings":"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"}
|