@khang07/zing-mp3-api 1.0.1 → 1.3.2

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 CHANGED
@@ -1,323 +1,442 @@
1
- # @khang07/zing-mp3-api
2
-
3
- Node.js library để lấy stream nhạc video từ Zing MP3 dưới dạng `Readable` stream.
4
-
5
- Package này hiện tập trung vào 2 tác vụ chính:
6
-
7
- - Lấy **nhạc** theo ID trả về stream audio
8
- - Lấy **video** theo ID trả về stream video HLS
9
-
10
- Library build sẵn cho cả **ESM** **CommonJS**, type cho TypeScript.
11
-
12
- ## Tính năng
13
-
14
- - Export sẵn `client` dùng ngay
15
- - Có thể tự tạo `new Client()` để chỉnh tốc độ stream/buffer
16
- - Trả về `Readable` stream để pipe thẳng ra file, HTTP response, Discord voice pipeline, hoặc xử lý tiếp
17
- - cookie jar nội bộ để giữ cookie giữa các request
18
- - Có chữ ký request nội bộ cho API đang dùng
19
- - Hỗ trợ ESM, CJS, TypeScript
20
-
21
- ## Cài đặt
22
-
23
- ```bash
24
- npm install @khang07/zing-mp3-api
25
- ```
26
-
27
- hoặc
28
-
29
- ```bash
30
- bun add @khang07/zing-mp3-api
31
- ```
32
-
33
- ## Yêu cầu môi trường
34
-
35
- Package này chạy cho **Node.js**, không dành cho browser vì dùng:
36
-
37
- - `node:stream`
38
- - `node:crypto`
39
- - `axios` với Node adapter
40
- - `m3u8stream`
41
-
42
- ## Dùng nhanh
43
-
44
- ### ESM
45
-
46
- ```ts
47
- import client from "@khang07/zing-mp3-api";
48
- import { createWriteStream } from "node:fs";
49
-
50
- const writer = createWriteStream("music.mp3");
51
- const stream = await client.music("MUSIC_ID");
52
-
53
- stream.pipe(writer);
54
- ```
55
-
56
- ### ESM với named import
57
-
58
- ```ts
59
- import { client, Client } from "@khang07/zing-mp3-api";
60
- import { createWriteStream } from "node:fs";
61
-
62
- const musicWriter = createWriteStream("music.mp3");
63
- client.musicSyncLike("MUSIC_ID").pipe(musicWriter);
64
-
65
- const customClient = new Client({
66
- maxRate: [256 * 1024, 64 * 1024]
67
- });
68
-
69
- const videoWriter = createWriteStream("video.bin");
70
- const videoStream = await customClient.video("VIDEO_ID");
71
- videoStream.pipe(videoWriter);
72
- ```
73
-
74
- ### CommonJS
75
-
76
- ```js
77
- const { client, Client } = require("@khang07/zing-mp3-api");
78
- const { createWriteStream } = require("node:fs");
79
-
80
- const writer = createWriteStream("music.mp3");
81
- client.musicSyncLike("MUSIC_ID").pipe(writer);
82
- ```
83
-
84
- ## API
85
-
86
- ### `new Client(options?)`
87
-
88
- Tạo client mới.
89
-
90
- ```ts
91
- import { Client } from "@khang07/zing-mp3-api";
92
-
93
- const client = new Client({
94
- maxRate: [100 * 1024, 16 * 1024]
95
- });
96
- ```
97
-
98
- #### `ClientOptions`
99
-
100
- ```ts
101
- interface ClientOptions {
102
- maxRate?: [download?: number, highWaterMark?: number];
103
- }
104
- ```
105
-
106
- Ý nghĩa:
107
-
108
- - `download`: giới hạn tốc độ download cho request stream
109
- - `highWaterMark`: buffer size cho `PassThrough` của các hàm `SyncLike`
110
-
111
- Giá trị mặc định:
112
-
113
- ```ts
114
- [100 * 1024, 16 * 1024]
115
- ```
116
-
117
- ## Các method
118
-
119
- ### `await client.music(musicID)`
120
-
121
- Trả về `Promise<Readable>` cho audio stream.
122
-
123
- ```ts
124
- import client from "@khang07/zing-mp3-api";
125
- import { createWriteStream } from "node:fs";
126
-
127
- const output = createWriteStream("music.mp3");
128
- const stream = await client.music("ZZEEOZEC");
129
-
130
- stream.pipe(output);
131
- ```
132
-
133
- Ghi chú:
134
-
135
- - Method này gọi API `/api/v2/song/get/streaming`
136
- - Hiện tại code lấy URL tại `data[128]`
137
- - Nghĩa implementation hiện tại đang dùng nhánh stream **128 kbps**
138
-
139
- ### `client.musicSyncLike(musicID)`
140
-
141
- Trả về `Readable` ngay để có thể pipe trực tiếp, phù hợp khi bạn muốn viết ngắn hơn.
142
-
143
- ```ts
144
- import client from "@khang07/zing-mp3-api";
145
- import { createWriteStream } from "node:fs";
146
-
147
- client.musicSyncLike("ZZEEOZEC").pipe(createWriteStream("music.mp3"));
148
- ```
149
-
150
- ### `await client.video(videoID)`
151
-
152
- Trả về `Promise<Readable>` cho video stream.
153
-
154
- ```ts
155
- import client from "@khang07/zing-mp3-api";
156
- import { createWriteStream } from "node:fs";
157
-
158
- const output = createWriteStream("video.bin");
159
- const stream = await client.video("ZZEEOZEC");
160
-
161
- stream.pipe(output);
162
- ```
163
-
164
- Ghi chú quan trọng:
165
-
166
- - Method này gọi API `/api/v2/page/get/video`
167
- - Hiện tại code chỉ lấy `streaming.hls["360p"]`
168
- - Đây **HLS stream** lấy qua `m3u8stream`
169
- - Library **không transcode**, **không remux**, **không ép sang MP4 thật**
170
- - vậy bạn nên xem dữ liệu trả về là **stream media thô từ HLS**, không nên mặc định coi nó luôn là file `.mp4` chuẩn
171
-
172
- ### `client.videoSyncLike(videoID)`
173
-
174
- Trả về `Readable` ngay để pipe trực tiếp.
175
-
176
- ```ts
177
- import client from "@khang07/zing-mp3-api";
178
- import { createWriteStream } from "node:fs";
179
-
180
- client.videoSyncLike("ZZEEOZEC").pipe(createWriteStream("video.bin"));
181
- ```
182
-
183
- ## Bắt lỗi
184
-
185
- Khi lỗi, code ném ra error với các field thực tế đang có trong implementation:
186
-
187
- - `name`: `ZING_MP3_ERROR`
188
- - `message`
189
- - `code`
190
- - `status` (nếu có)
191
- - `cause` (nếu có)
192
-
193
- Các lỗi đang xuất hiện trong source:
194
-
195
- - `ERROR_INVALID_ID`
196
- - `ERROR_MUSIC_NOT_FOUND`
197
- - `ERROR_MUSIC_VIP_ONLY`
198
- - `ERROR_VIDEO_NOT_FOUND`
199
- - `ERROR_STREAM_URL_NOT_FOUND`
200
- - `ERROR_STREAM_DOWNLOAD`
201
- - `ERROR_MUSIC_FETCH`
202
- - `ERROR_VIDEO_FETCH`
203
-
204
- Ví dụ:
205
-
206
- ```ts
207
- import client from "@khang07/zing-mp3-api";
208
- import { createWriteStream } from "node:fs";
209
-
210
- try {
211
- const stream = await client.music("ZZEEOZEC");
212
- const writer = createWriteStream("music.mp3");
213
-
214
- stream.on("error", (error) => {
215
- console.error("Stream error:", error);
216
- });
217
-
218
- writer.on("error", (error) => {
219
- console.error("Write error:", error);
220
- });
221
-
222
- stream.pipe(writer);
223
- } catch (error) {
224
- console.error(error);
225
- }
226
- ```
227
-
228
- ## Dùng với HTTP server
229
-
230
- ```ts
231
- import http from "node:http";
232
- import client from "@khang07/zing-mp3-api";
233
-
234
- const server = http.createServer(async (_req, res) => {
235
- try {
236
- const stream = await client.music("ZZEEOZEC");
237
-
238
- res.writeHead(200, {
239
- "Content-Type": "audio/mpeg"
240
- });
241
-
242
- stream.on("error", () => {
243
- if (!res.headersSent)
244
- res.writeHead(500);
245
-
246
- res.end("Stream failed");
247
- });
248
-
249
- stream.pipe(res);
250
- } catch {
251
- res.writeHead(500);
252
- res.end("Failed to fetch music");
253
- }
254
- });
255
-
256
- server.listen(3000);
257
- ```
258
-
259
- ## Build từ source
260
-
261
- Project đang dùng TypeScript + Rollup + API Extractor.
262
-
263
- ```bash
264
- bun install
265
- bun run build
266
- ```
267
-
268
- Output build:
269
-
270
- - `dist/esm` → bản ESM
271
- - `dist/cjs` → bản CommonJS
272
- - `dist/types` → type declarations gộp
273
-
274
- Các script hiện có:
275
-
276
- ```bash
277
- bun run build:esm
278
- bun run build:cjs
279
- bun run build:types
280
- bun run build
281
- ```
282
-
283
- ## Cấu trúc dự án
284
-
285
- ```text
286
- source/
287
- index.ts
288
- types/
289
- utils/
290
- dist/
291
- esm/
292
- cjs/
293
- types/
294
- ```
295
-
296
- ## Ghi chú triển khai hiện tại
297
-
298
- vài điểm cần lưu ý:
299
-
300
- - Chưa có API search public trong `Client` dù đang export type `SearchCategory`
301
- - Video hiện mới lấy nhánh `360p`
302
- - Music hiện mới lấy nhánh `128kps`
303
- - Package phụ thuộc vào cấu trúc API/cookie/signature hiện tại của Zing MP3, nên nếu upstream đổi thì cần cập nhật source
304
-
305
- ## Ghi chú về file test trong repo
306
-
307
- Trong repo hiện có `test/index.js` và `test/index.cjs`, nhưng chúng đang import từ `"zing-mp3-api"`.
308
-
309
- Khi publish theo `package.json` hiện tại, import đúng cho người dùng ngoài sẽ là:
310
-
311
- ```js
312
- import { client } from "@khang07/zing-mp3-api";
313
- ```
314
-
315
- hoặc:
316
-
317
- ```js
318
- const { client } = require("@khang07/zing-mp3-api");
319
- ```
320
-
321
- ## License
322
-
323
- Xem tại [LICENSE](https://github.com/GiaKhang1810/zing-mp3-api#license)
1
+ # `@khang07/zing-mp3-api`
2
+
3
+ The basic APIs provide the features of ZingMp3.
4
+
5
+ ## Features
6
+
7
+ * Search songs, videos, playlists, and artists
8
+ * Fetch playlist, artist, and song details
9
+ * Get readable streams for music and video
10
+ * Accept raw resource tokens or `URL` values for resource-based methods
11
+ * Provide a cookie jar utility through a public subpath export
12
+ * Ship ESM and CommonJS entry points
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @khang07/zing-mp3-api
18
+ ```
19
+
20
+ ## Public Exports
21
+
22
+ ### Root export
23
+
24
+ #### Runtime exports
25
+
26
+ * `default`: a pre-created `Client` instance
27
+ * `Client`: the client class
28
+
29
+ #### Type exports
30
+
31
+ * `ClientOptions`
32
+ * `PlayList`
33
+ * `Artist`
34
+ * `Media`
35
+ * `SearhMedia`
36
+ * `SearchPlayList`
37
+ * `Cookies` *(type-only export from the root entry)*
38
+
39
+ ### Public subpath exports
40
+
41
+ ```ts
42
+ import { Cookies } from "@khang07/zing-mp3-api/utils/cookies";
43
+ import { createSignature } from "@khang07/zing-mp3-api/utils/encrypt";
44
+ import { Lapse } from "@khang07/zing-mp3-api/utils/lapse";
45
+ ```
46
+
47
+ ## Import
48
+
49
+ ### ESM
50
+
51
+ ```ts
52
+ import client, { Client } from "@khang07/zing-mp3-api";
53
+ ```
54
+
55
+ ### CommonJS
56
+
57
+ ```js
58
+ const zing = require("@khang07/zing-mp3-api");
59
+
60
+ const client = zing.default;
61
+ const { Client } = zing;
62
+ ```
63
+
64
+ ## Basic Usage
65
+
66
+ ### Use the default client
67
+
68
+ ```ts
69
+ import client from "@khang07/zing-mp3-api";
70
+
71
+ const items = await client.searchMusic("Do For Love Bray");
72
+ console.log(items[0]);
73
+ ```
74
+
75
+ ### Create a client
76
+
77
+ ```ts
78
+ import { Client } from "@khang07/zing-mp3-api";
79
+ import { Cookies } from "@khang07/zing-mp3-api/utils/cookies";
80
+
81
+ const client = new Client({
82
+ maxLoad: 16 * 1024,
83
+ maxHighWaterMark: 16 * 1024,
84
+ userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
85
+ jar: new Cookies()
86
+ });
87
+ ```
88
+
89
+ ### Fetch a playlist from a URL
90
+
91
+ ```ts
92
+ import client from "@khang07/zing-mp3-api";
93
+
94
+ const playlist = await client.playlist("https://zingmp3.vn/album/example/ZWZB9WAB.html");
95
+ console.log(playlist.name);
96
+ console.log(playlist.mediaCount);
97
+ ```
98
+
99
+ ### Fetch artist details
100
+
101
+ ```ts
102
+ import client from "@khang07/zing-mp3-api";
103
+
104
+ const artist = await client.artist("https://zingmp3.vn/Obito");
105
+ console.log(artist.name);
106
+ console.log(artist.followCount);
107
+ ```
108
+
109
+ ### Download a music stream
110
+
111
+ ```ts
112
+ import { createWriteStream } from "node:fs";
113
+ import client from "@khang07/zing-mp3-api";
114
+
115
+ const items = await client.searchMusic("Do For Love Bray");
116
+ const stream = await client.music(items[0].id);
117
+
118
+ stream.pipe(createWriteStream("music.mp3"));
119
+ ```
120
+
121
+ ### Download a video stream
122
+
123
+ ```ts
124
+ import { createWriteStream } from "node:fs";
125
+ import client from "@khang07/zing-mp3-api";
126
+
127
+ const items = await client.searchVideo("Do For Love Bray");
128
+ const stream = await client.video(items[0].id);
129
+
130
+ stream.pipe(createWriteStream("video.ts"));
131
+ ```
132
+
133
+ ### Use the immediate stream-returning methods
134
+
135
+ ```ts
136
+ import { createWriteStream } from "node:fs";
137
+ import client from "@khang07/zing-mp3-api";
138
+
139
+ const stream = client.musicSync("ZWZB9WAB");
140
+ stream.pipe(createWriteStream("music.mp3"));
141
+ ```
142
+
143
+ ### Handle library errors
144
+
145
+ ```ts
146
+ import client from "@khang07/zing-mp3-api";
147
+ import { Lapse } from "@khang07/zing-mp3-api/utils/lapse";
148
+
149
+ try {
150
+ await client.playlist("");
151
+ } catch (error) {
152
+ if (error instanceof Lapse) {
153
+ console.error(error.name);
154
+ console.error(error.code);
155
+ console.error(error.status);
156
+ }
157
+ }
158
+ ```
159
+
160
+ ## API Reference
161
+
162
+ ## `new Client(options?)`
163
+
164
+ Creates a new client instance.
165
+
166
+ ### `ClientOptions`
167
+
168
+ | Field | Type | Default |
169
+ | ------------------ | --------- | -------------------------------------------------------------------------------------------------------------------- |
170
+ | `maxLoad` | `number` | `1024 * 1024` |
171
+ | `maxHighWaterMark` | `number` | `16 * 1024` |
172
+ | `userAgent` | `string` | `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3` |
173
+ | `jar` | `Cookies` | `new Cookies()` |
174
+
175
+ `maxLoad` is passed to Axios as `maxRate`.
176
+
177
+ `maxHighWaterMark` is used as the `highWaterMark` when `musicSync()` and `videoSync()` create a `PassThrough` stream.
178
+
179
+ ## `Client.getIDFromURL(url)`
180
+
181
+ ```ts
182
+ static getIDFromURL(url: string): string
183
+ ```
184
+
185
+ Extracts a resource token from a ZingMp3 URL.
186
+
187
+ It throws `ERROR_INVALID_URL` when the input is not a non-empty string or when no token can be extracted.
188
+
189
+ ## Instance Methods
190
+
191
+ | Method | Returns | Description |
192
+ | ----------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
193
+ | `video(videoID)` | `Promise<Readable>` | Fetches a video stream. Accepts a raw token, URL string, or `URL`. |
194
+ | `videoSync(videoID)` | `Readable` | Returns a `PassThrough` immediately and pipes the fetched video stream into it. |
195
+ | `music(musicID)` | `Promise<Readable>` | Fetches a music stream. Accepts a raw token, URL string, or `URL`. |
196
+ | `musicSync(musicID)` | `Readable` | Returns a `PassThrough` immediately and pipes the fetched music stream into it. |
197
+ | `playlist(playlistID)` | `Promise<PlayList>` | Fetches playlist details. Accepts a raw token, URL string, or `URL`. |
198
+ | `artist(aliasID)` | `Promise<Artist>` | Fetches artist details. Accepts an alias token, URL string, or `URL`. |
199
+ | `mediaDetails(mediaID)` | `Promise<Media>` | Fetches song details. Accepts a raw token, URL string, or `URL`. |
200
+ | `searchMusic(query)` | `Promise<Media[]>` | Searches songs. |
201
+ | `searchVideo(query)` | `Promise<SearhMedia[]>` | Searches videos. |
202
+ | `searchList(query)` | `Promise<SearchPlayList[]>` | Searches playlists. |
203
+ | `searchArtist(query)` | `Promise<SearchArtist[]>` | Searches artists. |
204
+
205
+ ### Method notes
206
+
207
+ * `video()` selects `720p` first, then falls back to `360p`.
208
+ * `music()` selects `320` first when available and not equal to `"VIP"`, then falls back to `128`.
209
+ * When the music API returns `err === -1150`, `music()` retries the extra music endpoint up to 4 times and throws `ERROR_MUSIC_VIP_ONLY` if it still cannot resolve a playable URL.
210
+ * `searchMusic()`, `searchVideo()`, `searchList()`, and `searchArtist()` always request `page: 1` and `count: 20`.
211
+
212
+ ## Public Types
213
+
214
+ ### `Artist`
215
+
216
+ ```ts
217
+ interface Artist {
218
+ alias: string;
219
+ birthday: string;
220
+ biography: string;
221
+ followCount: number;
222
+ name: string;
223
+ national: string;
224
+ realname: string;
225
+ thumbnail: {
226
+ w240: string;
227
+ w600: string;
228
+ };
229
+ }
230
+ ```
231
+
232
+ ### `Media`
233
+
234
+ ```ts
235
+ interface Media {
236
+ id: string;
237
+ name: string;
238
+ alias: string;
239
+ isOffical: boolean;
240
+ username: string;
241
+ artists: Array<{
242
+ alias: string;
243
+ followCount?: number;
244
+ name: string;
245
+ thumbnail: {
246
+ w240: string;
247
+ w600: string;
248
+ };
249
+ }>;
250
+ isWorldWide: boolean;
251
+ thumbnail: {
252
+ w94: string;
253
+ w240: string;
254
+ };
255
+ duration: number;
256
+ isPrivate: boolean;
257
+ releaseDate: number;
258
+ album: {
259
+ id: string;
260
+ name: string;
261
+ isOffical: boolean;
262
+ releaseDate: string;
263
+ releasedAt: number;
264
+ artists: Array<{
265
+ alias: string;
266
+ followCount?: number;
267
+ name: string;
268
+ thumbnail: {
269
+ w240: string;
270
+ w600: string;
271
+ };
272
+ }>;
273
+ thumbnail: {
274
+ w165: string;
275
+ };
276
+ };
277
+ hasLyric: boolean;
278
+ }
279
+ ```
280
+
281
+ ### `SearhMedia`
282
+
283
+ ```ts
284
+ type SearhMedia = Omit<Media, "album">;
285
+ ```
286
+
287
+ ### `PlayList`
288
+
289
+ ```ts
290
+ interface PlayList {
291
+ id: string;
292
+ name: string;
293
+ alias: string;
294
+ artists: Array<{
295
+ alias: string;
296
+ followCount?: number;
297
+ name: string;
298
+ thumbnail: {
299
+ w240: string;
300
+ w600: string;
301
+ };
302
+ }>;
303
+ description: string;
304
+ duration: number;
305
+ isOffical: boolean;
306
+ isPrivate: boolean;
307
+ isSingle: boolean;
308
+ likeCount: number;
309
+ listenCount: number;
310
+ media: Media[];
311
+ mediaCount: number;
312
+ releaseDate: string;
313
+ releasedAt: number;
314
+ thumbnail: {
315
+ w165: string;
316
+ w320: string;
317
+ };
318
+ updatedAt: number;
319
+ }
320
+ ```
321
+
322
+ ### `SearchPlayList`
323
+
324
+ ```ts
325
+ type SearchPlayList = Omit<
326
+ PlayList,
327
+ "updatedAt" | "mediaCount" | "listenCount" | "likeCount" | "duration" | "description" | "media"
328
+ >;
329
+ ```
330
+
331
+ ## `Cookies`
332
+
333
+ Import from `@khang07/zing-mp3-api/utils/cookies`.
334
+
335
+ ### Methods
336
+
337
+ | Method | Returns |
338
+ | -------------------------------------- | ------------------------ |
339
+ | `setCookie(setCookie, requestUrl)` | `void` |
340
+ | `setCookies(setCookies, requestUrl)` | `void` |
341
+ | `getCookies(requestUrl)` | `CookieRecord[]` |
342
+ | `getCookieHeader(requestUrl)` | `string` |
343
+ | `applyToHeaders(requestUrl, headers?)` | `Record<string, string>` |
344
+ | `deleteCookie(domain, path, name)` | `void` |
345
+ | `cleanup()` | `void` |
346
+ | `toJSON()` | `CookieRecord[]` |
347
+ | `fromJSON(cookies)` | `void` |
348
+
349
+ ### Cookie record shape
350
+
351
+ ```ts
352
+ interface CookieRecord {
353
+ name: string;
354
+ value: string;
355
+ domain: string;
356
+ path: string;
357
+ expiresAt?: number;
358
+ secure: boolean;
359
+ httpOnly: boolean;
360
+ sameSite?: "Strict" | "Lax" | "None";
361
+ hostOnly: boolean;
362
+ }
363
+ ```
364
+
365
+ ### Example
366
+
367
+ ```ts
368
+ import { Cookies } from "@khang07/zing-mp3-api/utils/cookies";
369
+
370
+ const jar = new Cookies();
371
+ jar.setCookie("sid=abc; Path=/; HttpOnly", "https://zingmp3.vn/");
372
+
373
+ console.log(jar.getCookieHeader("https://zingmp3.vn/"));
374
+ ```
375
+
376
+ ## `createSignature(uri, params, secret)`
377
+
378
+ Import from `@khang07/zing-mp3-api/utils/encrypt`.
379
+
380
+ ```ts
381
+ function createSignature(uri: string, params: string, secret: string): string
382
+ ```
383
+
384
+ Generates the request signature used by the client.
385
+
386
+ ## `Lapse`
387
+
388
+ Import from `@khang07/zing-mp3-api/utils/lapse`.
389
+
390
+ ```ts
391
+ class Lapse extends Error {
392
+ code: string;
393
+ status?: number;
394
+ cause?: unknown;
395
+ }
396
+ ```
397
+
398
+ ### Constructor
399
+
400
+ ```ts
401
+ new Lapse(message: string, code: string, status?: number, cause?: unknown)
402
+ ```
403
+
404
+ ### Properties
405
+
406
+ * `name`: always set to `"ZING_MP3_ERROR"`
407
+ * `message`: inherited from `Error`
408
+ * `code`: library error code
409
+ * `status`: optional status or API error value
410
+ * `cause`: optional original error or response payload
411
+
412
+ ## Error Codes
413
+
414
+ | Code | Used by |
415
+ | ---------------------------- | ------------------------------------------------------------------ |
416
+ | `ERROR_INVALID_URL` | `Client.getIDFromURL()` |
417
+ | `ERROR_INVALID_ID` | `video()`, `music()`, `playlist()`, `artist()`, `mediaDetails()` |
418
+ | `ERROR_INVALID_QUERY` | `searchMusic()`, `searchVideo()`, `searchList()`, `searchArtist()` |
419
+ | `ERROR_VIDEO_NOT_FOUND` | `video()` |
420
+ | `ERROR_VIDEO_FETCH` | `video()`, `videoSync()` |
421
+ | `ERROR_MUSIC_VIP_ONLY` | `music()` |
422
+ | `ERROR_MUSIC_FETCH` | `music()`, `musicSync()` |
423
+ | `ERROR_PLAYLIST_NOT_FOUND` | `playlist()` |
424
+ | `ERROR_PLAYLIST_FETCH` | `playlist()` |
425
+ | `ERROR_ARTIST_NOT_FOUND` | `artist()` |
426
+ | `ERROR_ARTIST_FETCH` | `artist()` |
427
+ | `ERROR_MEDIA_NOT_FOUND` | `mediaDetails()` |
428
+ | `ERROR_MEDIA_FETCH` | `mediaDetails()` |
429
+ | `ERROR_SEARCH_FAILED` | `searchMusic()`, `searchVideo()`, `searchList()`, `searchArtist()` |
430
+ | `ERROR_SEARCH_FETCH` | `searchMusic()`, `searchVideo()`, `searchList()`, `searchArtist()` |
431
+ | `ERROR_STREAM_URL_NOT_FOUND` | `video()`, `music()` |
432
+ | `ERROR_STREAM_DOWNLOAD` | `video()`, `videoSync()`, `music()`, `musicSync()` |
433
+
434
+ ## Notes
435
+
436
+ * The root entry exports `Cookies` as a type only. To construct a cookie jar, import `Cookies` from `@khang07/zing-mp3-api/utils/cookies`.
437
+ * The root entry exports the type name `SearhMedia` exactly as written in source.
438
+ * `searchArtist()` is a public method, but its `SearchArtist` type is not re-exported from the root entry.
439
+ * No test, example, or demo files were included in the provided source bundle.
440
+
441
+ ## License
442
+ [MIT](https://github.com/GiaKhang1810/zing-mp3-api?tab=MIT-1-ov-file)