wyzie-lib 2.0.6 → 2.0.7

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
@@ -36,22 +36,30 @@ yarn add wyzie-lib
36
36
  ```ts
37
37
  import { type SubtitleData, searchSubtitles } from "wyzie-lib";
38
38
 
39
- // IMDB is faster then TMDB due to less API calls behind the scenes
39
+ // Basic usage - get subtitles
40
40
  const data: SubtitleData[] = await searchSubtitles({ tmdb_id: 286217 });
41
41
  console.log(data[0]); // Prints the object of the first subtitle provided in the search
42
+
43
+ // Get subtitles with VTT parsing
44
+ const { subtitles, vttContent } = await searchSubtitles({
45
+ tmdb_id: 286217,
46
+ parseVTT: true,
47
+ });
48
+ console.log(vttContent); // Prints the VTT formatted subtitle content
42
49
  ```
43
50
 
44
51
  ### Parameters
45
52
 
46
- | Parameter | Name | Description |
47
- | ----------------------- | ----------------- | ----------------------------------------------------------------------------------------- |
48
- | **tmdb_id** - _number_ | TmdbId | The TMDB ID of the movie or TV show. _(tmdb_id or imdb_id is required)_ |
49
- | **imdb_id** - _number_ | ImdbId | The IMDB ID of the movie or TV show. _(imdb_id or tmdb_id is required)_ |
50
- | **format** - _string_ | format | The file format of the subtitles returned. _(srt, ass, vtt, txt, sub, mpl, webvtt, dfxp)_ |
51
- | **season** - _number_ | season | Disired season of subtites _(this requires episode parameter aswell)_ |
52
- | **episode** - _number_ | episode | The episode of the given season. |
53
- | **language** - _string_ | language | The ISO 3166 code of the provided subtitles. |
54
- | **hi** - _boolean_ | isHearingImpaired | A boolean indicating if the subtitles are hearing impaired. |
53
+ | Parameter | Name | Description |
54
+ | ------------------------ | ----------------- | ----------------------------------------------------------------------------------------- |
55
+ | **tmdb_id** - _number_ | TmdbId | The TMDB ID of the movie or TV show. _(tmdb_id or imdb_id is required)_ |
56
+ | **imdb_id** - _number_ | ImdbId | The IMDB ID of the movie or TV show. _(imdb_id or tmdb_id is required)_ |
57
+ | **format** - _string_ | format | The file format of the subtitles returned. _(srt, ass, vtt, txt, sub, mpl, webvtt, dfxp)_ |
58
+ | **season** - _number_ | season | Disired season of subtites _(this requires episode parameter aswell)_ |
59
+ | **episode** - _number_ | episode | The episode of the given season. |
60
+ | **language** - _string_ | language | The ISO 3166 code of the provided subtitles. |
61
+ | **hi** - _boolean_ | isHearingImpaired | A boolean indicating if the subtitles are hearing impaired. |
62
+ | **parseVTT** - _boolean_ | parseVTT | Parse and return the first subtitle in VTT format. |
55
63
 
56
64
  ### Types
57
65
 
@@ -94,6 +102,52 @@ type SubtitleData = {
94
102
  };
95
103
  ```
96
104
 
105
+ ### VTT Parsing Features
106
+
107
+ The VTT parser now includes several improvements for handling subtitle files:
108
+
109
+ - **Robust Format Handling**: Automatically handles both SRT and VTT input formats
110
+ - **Timestamp Normalization**: Converts all timestamps to WebVTT format (HH:MM:SS.mmm)
111
+ - **Smart Block Processing**:
112
+ - Maintains proper spacing between subtitle blocks
113
+ - Removes subtitle numbers
114
+ - Handles multi-line subtitles
115
+ - Preserves text formatting
116
+ - **Error Handling**: Gracefully handles malformed input and network errors
117
+
118
+ Example VTT output:
119
+
120
+ ```vtt
121
+ WEBVTT
122
+
123
+ 00:02:05.872 --> 00:02:08.024
124
+ All right, team,
125
+ stay in sight of each other.
126
+
127
+ 00:02:08.124 --> 00:02:10.484
128
+ Let's make NASA proud today.
129
+ ```
130
+
131
+ ### Error Handling
132
+
133
+ The library provides detailed error messages for common issues:
134
+
135
+ ```ts
136
+ try {
137
+ const { subtitles, vttContent } = await searchSubtitles({
138
+ tmdb_id: 286217,
139
+ parseVTT: true,
140
+ });
141
+ } catch (error) {
142
+ // Handles various error cases:
143
+ // - Network errors
144
+ // - Invalid subtitle format
145
+ // - Missing required parameters
146
+ // - API errors
147
+ console.error(error);
148
+ }
149
+ ```
150
+
97
151
  <hr />
98
152
 
99
153
  <sup>
@@ -0,0 +1,7 @@
1
+ import { SearchSubtitlesParams, SubtitleData } from "./types";
2
+ export declare function searchSubtitles(params: SearchSubtitlesParams & {
3
+ parseVTT?: boolean;
4
+ }): Promise<SubtitleData[] | {
5
+ subtitles: SubtitleData[];
6
+ vttContent: string;
7
+ }>;
@@ -0,0 +1,4 @@
1
+ import { SearchSubtitlesParams, SubtitleData, QueryParams } from "./types";
2
+ import { searchSubtitles } from "./funcs";
3
+ export { searchSubtitles };
4
+ export type { SubtitleData, SearchSubtitlesParams, QueryParams };
@@ -0,0 +1,28 @@
1
+ export interface SearchSubtitlesParams {
2
+ tmdb_id?: number;
3
+ imdb_id?: number;
4
+ season?: number;
5
+ episode?: number;
6
+ language?: string;
7
+ format?: string;
8
+ hi?: boolean;
9
+ parseVTT?: boolean;
10
+ }
11
+ export type SubtitleData = {
12
+ id: string;
13
+ url: string;
14
+ format: string;
15
+ isHearingImpaired: boolean;
16
+ flagUrl: string;
17
+ media: string;
18
+ display: string;
19
+ language: string;
20
+ };
21
+ export interface QueryParams {
22
+ id: string;
23
+ season?: number;
24
+ episode?: number;
25
+ language?: string;
26
+ format?: string;
27
+ hi?: boolean;
28
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});async function h({tmdb_id:n,imdb_id:t,season:r,episode:o,language:u,format:f,hi:d}){const c=new URL("https://sub.wyzie.ru/search"),s={id:String(n||t),season:r,episode:o,language:u,format:f,hi:d};return Object.entries(s).forEach(([i,a])=>{a!==void 0&&c.searchParams.append(i,a)}),c}async function p(n){const t=await fetch(n.toString());if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);return t.json()}async function w(n){try{const t=await fetch(n);if(!t.ok)throw new Error(`Failed to fetch subtitle content: ${t.status}`);const o=(await t.text()).replace(/\r\n/g,`
2
+ `).replace(/\r/g,`
3
+ `).trim();let u=`WEBVTT
4
+
5
+ `;const f=o.split(/\n\n+/);for(const c of f){if(!c.trim())continue;const s=c.split(`
6
+ `).map(e=>e.trim()).filter(e=>e.length>0);if(s.length<2)continue;const i=s.findIndex(e=>/^\d{1,2}:\d{2}(?::\d{2})?[,\.]\d{3}(?:\.|,)?\s*-->\s*\d{1,2}:\d{2}(?::\d{2})?[,\.]\d{3}(?:\.|,)?$/.test(e));if(i===-1)continue;const a=s.slice(i+1).filter(e=>!/^\d+$/.test(e)).filter(e=>e.length>0);if(a.length===0)continue;let l=s[i];l=l.replace(/[,.](?=\s*-->)/,"").replace(/[,.]$/,""),l=l.replace(/,(\d{3})/g,".$1"),u+=`${l}
7
+ ${a.join(`
8
+ `)}
9
+
10
+ `}return u.replace(/\n{3,}/g,`
11
+
12
+ `).trim()+`
13
+
14
+ `}catch(t){throw console.error("Error in parseToVTT:",t),t}}async function g(n){try{const t=await h(n),r=await p(t);if(n.parseVTT&&r.length>0){const o=await w(r[0].url);return{subtitles:r,vttContent:o}}return r}catch(t){throw new Error(`Error fetching subtitles: ${t}`)}}exports.searchSubtitles=g;
@@ -0,0 +1,85 @@
1
+ async function d({
2
+ tmdb_id: e,
3
+ imdb_id: t,
4
+ season: r,
5
+ episode: s,
6
+ language: u,
7
+ format: f,
8
+ hi: h
9
+ }) {
10
+ const c = new URL("https://sub.wyzie.ru/search"), o = {
11
+ id: String(e || t),
12
+ season: r,
13
+ episode: s,
14
+ language: u,
15
+ format: f,
16
+ hi: h
17
+ };
18
+ return Object.entries(o).forEach(([i, a]) => {
19
+ a !== void 0 && c.searchParams.append(i, a);
20
+ }), c;
21
+ }
22
+ async function p(e) {
23
+ const t = await fetch(e.toString());
24
+ if (!t.ok)
25
+ throw new Error(`HTTP error! status: ${t.status}`);
26
+ return t.json();
27
+ }
28
+ async function w(e) {
29
+ try {
30
+ const t = await fetch(e);
31
+ if (!t.ok)
32
+ throw new Error(`Failed to fetch subtitle content: ${t.status}`);
33
+ const s = (await t.text()).replace(/\r\n/g, `
34
+ `).replace(/\r/g, `
35
+ `).trim();
36
+ let u = `WEBVTT
37
+
38
+ `;
39
+ const f = s.split(/\n\n+/);
40
+ for (const c of f) {
41
+ if (!c.trim())
42
+ continue;
43
+ const o = c.split(`
44
+ `).map((n) => n.trim()).filter((n) => n.length > 0);
45
+ if (o.length < 2)
46
+ continue;
47
+ const i = o.findIndex(
48
+ (n) => /^\d{1,2}:\d{2}(?::\d{2})?[,\.]\d{3}(?:\.|,)?\s*-->\s*\d{1,2}:\d{2}(?::\d{2})?[,\.]\d{3}(?:\.|,)?$/.test(n)
49
+ );
50
+ if (i === -1)
51
+ continue;
52
+ const a = o.slice(i + 1).filter((n) => !/^\d+$/.test(n)).filter((n) => n.length > 0);
53
+ if (a.length === 0)
54
+ continue;
55
+ let l = o[i];
56
+ l = l.replace(/[,.](?=\s*-->)/, "").replace(/[,.]$/, ""), l = l.replace(/,(\d{3})/g, ".$1"), u += `${l}
57
+ ${a.join(`
58
+ `)}
59
+
60
+ `;
61
+ }
62
+ return u.replace(/\n{3,}/g, `
63
+
64
+ `).trim() + `
65
+
66
+ `;
67
+ } catch (t) {
68
+ throw console.error("Error in parseToVTT:", t), t;
69
+ }
70
+ }
71
+ async function g(e) {
72
+ try {
73
+ const t = await d(e), r = await p(t);
74
+ if (e.parseVTT && r.length > 0) {
75
+ const s = await w(r[0].url);
76
+ return { subtitles: r, vttContent: s };
77
+ }
78
+ return r;
79
+ } catch (t) {
80
+ throw new Error(`Error fetching subtitles: ${t}`);
81
+ }
82
+ }
83
+ export {
84
+ g as searchSubtitles
85
+ };
@@ -0,0 +1,14 @@
1
+ var WyzieLib=function(f){"use strict";async function p({tmdb_id:e,imdb_id:t,season:r,episode:s,language:u,format:d,hi:h}){const c=new URL("https://sub.wyzie.ru/search"),o={id:String(e||t),season:r,episode:s,language:u,format:d,hi:h};return Object.entries(o).forEach(([i,a])=>{a!==void 0&&c.searchParams.append(i,a)}),c}async function w(e){const t=await fetch(e.toString());if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);return t.json()}async function g(e){try{const t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch subtitle content: ${t.status}`);const s=(await t.text()).replace(/\r\n/g,`
2
+ `).replace(/\r/g,`
3
+ `).trim();let u=`WEBVTT
4
+
5
+ `;const d=s.split(/\n\n+/);for(const c of d){if(!c.trim())continue;const o=c.split(`
6
+ `).map(n=>n.trim()).filter(n=>n.length>0);if(o.length<2)continue;const i=o.findIndex(n=>/^\d{1,2}:\d{2}(?::\d{2})?[,\.]\d{3}(?:\.|,)?\s*-->\s*\d{1,2}:\d{2}(?::\d{2})?[,\.]\d{3}(?:\.|,)?$/.test(n));if(i===-1)continue;const a=o.slice(i+1).filter(n=>!/^\d+$/.test(n)).filter(n=>n.length>0);if(a.length===0)continue;let l=o[i];l=l.replace(/[,.](?=\s*-->)/,"").replace(/[,.]$/,""),l=l.replace(/,(\d{3})/g,".$1"),u+=`${l}
7
+ ${a.join(`
8
+ `)}
9
+
10
+ `}return u.replace(/\n{3,}/g,`
11
+
12
+ `).trim()+`
13
+
14
+ `}catch(t){throw console.error("Error in parseToVTT:",t),t}}async function b(e){try{const t=await p(e),r=await w(t);if(e.parseVTT&&r.length>0){const s=await g(r[0].url);return{subtitles:r,vttContent:s}}return r}catch(t){throw new Error(`Error fetching subtitles: ${t}`)}}return f.searchSubtitles=b,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"}),f}({});
@@ -0,0 +1,14 @@
1
+ (function(o,i){typeof exports=="object"&&typeof module<"u"?i(exports):typeof define=="function"&&define.amd?define(["exports"],i):(o=typeof globalThis<"u"?globalThis:o||self,i(o.WyzieLib={}))})(this,function(o){"use strict";async function i({tmdb_id:n,imdb_id:t,season:r,episode:c,language:d,format:h,hi:p}){const a=new URL("https://sub.wyzie.ru/search"),s={id:String(n||t),season:r,episode:c,language:d,format:h,hi:p};return Object.entries(s).forEach(([l,u])=>{u!==void 0&&a.searchParams.append(l,u)}),a}async function w(n){const t=await fetch(n.toString());if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);return t.json()}async function T(n){try{const t=await fetch(n);if(!t.ok)throw new Error(`Failed to fetch subtitle content: ${t.status}`);const c=(await t.text()).replace(/\r\n/g,`
2
+ `).replace(/\r/g,`
3
+ `).trim();let d=`WEBVTT
4
+
5
+ `;const h=c.split(/\n\n+/);for(const a of h){if(!a.trim())continue;const s=a.split(`
6
+ `).map(e=>e.trim()).filter(e=>e.length>0);if(s.length<2)continue;const l=s.findIndex(e=>/^\d{1,2}:\d{2}(?::\d{2})?[,\.]\d{3}(?:\.|,)?\s*-->\s*\d{1,2}:\d{2}(?::\d{2})?[,\.]\d{3}(?:\.|,)?$/.test(e));if(l===-1)continue;const u=s.slice(l+1).filter(e=>!/^\d+$/.test(e)).filter(e=>e.length>0);if(u.length===0)continue;let f=s[l];f=f.replace(/[,.](?=\s*-->)/,"").replace(/[,.]$/,""),f=f.replace(/,(\d{3})/g,".$1"),d+=`${f}
7
+ ${u.join(`
8
+ `)}
9
+
10
+ `}return d.replace(/\n{3,}/g,`
11
+
12
+ `).trim()+`
13
+
14
+ `}catch(t){throw console.error("Error in parseToVTT:",t),t}}async function b(n){try{const t=await i(n),r=await w(t);if(n.parseVTT&&r.length>0){const c=await T(r[0].url);return{subtitles:r,vttContent:c}}return r}catch(t){throw new Error(`Error fetching subtitles: ${t}`)}}o.searchSubtitles=b,Object.defineProperty(o,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wyzie-lib",
3
- "version": "2.0.6",
3
+ "version": "2.0.7",
4
4
  "icon": "https://i.postimg.cc/L5ppKYC5/cclogo.png",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -29,15 +29,15 @@
29
29
  }
30
30
  },
31
31
  "devDependencies": {
32
- "@eslint/js": "^9.14.0",
33
- "eslint": "^9.14.0",
32
+ "@eslint/js": "^9.17.0",
33
+ "eslint": "^9.17.0",
34
34
  "eslint-config-prettier": "^9.1.0",
35
35
  "eslint-plugin-import": "^2.31.0",
36
36
  "eslint-plugin-prettier": "^5.2.1",
37
- "globals": "^15.12.0",
38
- "prettier": "^3.3.3",
39
- "typescript": "^5.6.3",
40
- "typescript-eslint": "^8.14.0",
37
+ "globals": "^15.14.0",
38
+ "prettier": "^3.4.2",
39
+ "typescript": "^5.7.2",
40
+ "typescript-eslint": "^8.19.0",
41
41
  "vite": "^4.5.5"
42
42
  },
43
43
  "scripts": {