@serifpersia/dango 3.0.3

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.
Files changed (141) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +247 -0
  3. package/client/dist/assets/AnimeInfo-CMxs0nRH.css +1 -0
  4. package/client/dist/assets/AnimeInfo-DVdaocCl.js +1 -0
  5. package/client/dist/assets/AnimeInfoPage-Bx5EvGt-.js +2 -0
  6. package/client/dist/assets/Asmr-C2i9GKD4.css +1 -0
  7. package/client/dist/assets/Asmr-CIjmFtRH.js +2 -0
  8. package/client/dist/assets/Asmr.module-DPG2JhDJ.js +1 -0
  9. package/client/dist/assets/AvSyncCalibrator-CIYcyon5.css +1 -0
  10. package/client/dist/assets/AvSyncCalibrator-vqErH7Cm.js +10 -0
  11. package/client/dist/assets/ErrorMessage-BwSjzblw.js +1 -0
  12. package/client/dist/assets/ErrorMessage-CXoRbrLN.css +1 -0
  13. package/client/dist/assets/Home-D7YfGBUk.js +1 -0
  14. package/client/dist/assets/Home-DKCfEiwl.css +1 -0
  15. package/client/dist/assets/Insights-BljI64Ua.css +1 -0
  16. package/client/dist/assets/Insights-CLQGrlpX.js +1 -0
  17. package/client/dist/assets/Manga-DQ9HYnpk.js +1 -0
  18. package/client/dist/assets/Manga-H8Wb04w3.css +1 -0
  19. package/client/dist/assets/Map-CXFqXmsZ.css +1 -0
  20. package/client/dist/assets/Map-L_ryVBTq.js +1 -0
  21. package/client/dist/assets/Mature-BeWzAJ7B.js +1 -0
  22. package/client/dist/assets/Mature-DJmUUtlF.css +1 -0
  23. package/client/dist/assets/Player-CYpd__FP.js +30 -0
  24. package/client/dist/assets/Player-DreAhybc.css +1 -0
  25. package/client/dist/assets/PlayerRedirect-fxUAp9JV.js +1 -0
  26. package/client/dist/assets/PlayerSettings-BcsotxP9.js +1 -0
  27. package/client/dist/assets/PlayerSettings-Cqua1CDD.css +1 -0
  28. package/client/dist/assets/QueueRail-B9Pgbqc3.js +1 -0
  29. package/client/dist/assets/QueueRail-BnaltOP8.css +1 -0
  30. package/client/dist/assets/Radio-BvdY5twD.js +1 -0
  31. package/client/dist/assets/Radio-CUuYy3DY.css +1 -0
  32. package/client/dist/assets/Search-BzO-aRP7.css +1 -0
  33. package/client/dist/assets/Search-R9YLAXS1.js +1 -0
  34. package/client/dist/assets/Search.module-D8ZbQAiK.js +1 -0
  35. package/client/dist/assets/Settings-9kYcXdTR.js +21 -0
  36. package/client/dist/assets/Settings-DF8JThUL.css +1 -0
  37. package/client/dist/assets/SkeletonGrid-D5vRvX5q.js +1 -0
  38. package/client/dist/assets/SkeletonGrid-DEbYtO4H.css +1 -0
  39. package/client/dist/assets/SynopsisText-BlFw0R-0.js +1 -0
  40. package/client/dist/assets/SynopsisText-CUgOjOxt.css +1 -0
  41. package/client/dist/assets/Trackers-DfZlnnVq.js +2 -0
  42. package/client/dist/assets/Trackers-Dt9lR_uP.css +1 -0
  43. package/client/dist/assets/Tv-CVKC2YBs.css +1 -0
  44. package/client/dist/assets/Tv-Db1Wx_b7.js +15 -0
  45. package/client/dist/assets/Watchlist-B2nkNZqM.css +1 -0
  46. package/client/dist/assets/Watchlist-a77CYtzu.js +1 -0
  47. package/client/dist/assets/hls-6Owgw2Aj.js +1 -0
  48. package/client/dist/assets/hls-BOLXTnjL.js +42 -0
  49. package/client/dist/assets/index-B6qdXFtl.css +1 -0
  50. package/client/dist/assets/index-B8TPVaIS.js +30354 -0
  51. package/client/dist/assets/index-CpjgU8ou.js +178 -0
  52. package/client/dist/assets/useAnimeInfoData-BOfyi9UJ.js +1 -0
  53. package/client/dist/assets/useIsMobile-CM15uQn8.css +1 -0
  54. package/client/dist/assets/useIsMobile-Cb8HcKRj.js +1 -0
  55. package/client/dist/assets/useMatureConsent-CZMYBVXd.js +1 -0
  56. package/client/dist/assets/vendor-rLNfZm7Y.js +1 -0
  57. package/client/dist/av-sync-test.mp4 +0 -0
  58. package/client/dist/favicon.ico +0 -0
  59. package/client/dist/index.html +31 -0
  60. package/client/dist/logo-mochi.png +0 -0
  61. package/client/dist/logo-sakura.png +0 -0
  62. package/client/dist/logo.png +0 -0
  63. package/client/dist/placeholder.svg +4 -0
  64. package/client/dist/robots.txt +3 -0
  65. package/orchestrator.js +416 -0
  66. package/package.json +89 -0
  67. package/server/dist/app-auth.js +231 -0
  68. package/server/dist/config.js +133 -0
  69. package/server/dist/controllers/auth.controller.js +247 -0
  70. package/server/dist/controllers/data.controller.js +785 -0
  71. package/server/dist/controllers/insights.controller.js +197 -0
  72. package/server/dist/controllers/proxy.controller.js +665 -0
  73. package/server/dist/controllers/settings.controller.js +267 -0
  74. package/server/dist/controllers/watchlist.controller.js +967 -0
  75. package/server/dist/db.js +152 -0
  76. package/server/dist/discord-gateway.js +381 -0
  77. package/server/dist/discord-rpc.js +424 -0
  78. package/server/dist/github-sync.js +403 -0
  79. package/server/dist/google.js +549 -0
  80. package/server/dist/lib/anilist.js +1519 -0
  81. package/server/dist/lib/anischedule.js +202 -0
  82. package/server/dist/lib/ipc.js +32 -0
  83. package/server/dist/lib/kitsu.js +552 -0
  84. package/server/dist/lib/mal.js +886 -0
  85. package/server/dist/lib/migration.js +335 -0
  86. package/server/dist/lib/temp-ids.js +11 -0
  87. package/server/dist/lib/tmdb.js +71 -0
  88. package/server/dist/lib/tracker/anilist-tracker.js +250 -0
  89. package/server/dist/lib/tracker/sync.service.js +312 -0
  90. package/server/dist/logger.js +19 -0
  91. package/server/dist/providers/123anime.provider.js +240 -0
  92. package/server/dist/providers/anilight.provider.js +366 -0
  93. package/server/dist/providers/animepahe.provider.js +531 -0
  94. package/server/dist/providers/animeya.provider.js +746 -0
  95. package/server/dist/providers/base-provider.js +45 -0
  96. package/server/dist/providers/hn.provider.js +473 -0
  97. package/server/dist/providers/ht.provider.js +439 -0
  98. package/server/dist/providers/jasmr.provider.js +504 -0
  99. package/server/dist/providers/kaa.provider.js +388 -0
  100. package/server/dist/providers/manga/manga.types.js +10 -0
  101. package/server/dist/providers/manga/mangadex.provider.js +227 -0
  102. package/server/dist/providers/manga/mangapill.provider.js +232 -0
  103. package/server/dist/providers/megaplay.provider.js +583 -0
  104. package/server/dist/providers/op.provider.js +440 -0
  105. package/server/dist/providers/provider.interface.js +2 -0
  106. package/server/dist/providers/title-matching.js +234 -0
  107. package/server/dist/providers/wh.provider.js +600 -0
  108. package/server/dist/rclone.js +126 -0
  109. package/server/dist/repositories/insights.repository.js +43 -0
  110. package/server/dist/repositories/mal-cache.repository.js +66 -0
  111. package/server/dist/repositories/notifications.repository.js +40 -0
  112. package/server/dist/repositories/queue.repository.js +64 -0
  113. package/server/dist/repositories/settings.repository.js +15 -0
  114. package/server/dist/repositories/shows-meta.repository.js +43 -0
  115. package/server/dist/repositories/temp-show-ids.repository.js +54 -0
  116. package/server/dist/repositories/watched-episodes.repository.js +54 -0
  117. package/server/dist/repositories/watchlist.repository.js +74 -0
  118. package/server/dist/routes/asmr.routes.js +72 -0
  119. package/server/dist/routes/auth.routes.js +28 -0
  120. package/server/dist/routes/data.routes.js +50 -0
  121. package/server/dist/routes/discord-gateway.routes.js +57 -0
  122. package/server/dist/routes/insights.routes.js +12 -0
  123. package/server/dist/routes/lan-auth.routes.js +49 -0
  124. package/server/dist/routes/manga.routes.js +115 -0
  125. package/server/dist/routes/proxy.routes.js +15 -0
  126. package/server/dist/routes/radio.routes.js +143 -0
  127. package/server/dist/routes/settings.routes.js +27 -0
  128. package/server/dist/routes/tracker.routes.js +143 -0
  129. package/server/dist/routes/translate.routes.js +90 -0
  130. package/server/dist/routes/tv.routes.js +843 -0
  131. package/server/dist/routes/watchlist.routes.js +312 -0
  132. package/server/dist/server.js +310 -0
  133. package/server/dist/shipped-defaults.js +8 -0
  134. package/server/dist/sync-config.js +32 -0
  135. package/server/dist/sync.js +506 -0
  136. package/server/dist/utils/cookie.utils.js +17 -0
  137. package/server/dist/utils/db-utils.js +15 -0
  138. package/server/dist/utils/env.utils.js +83 -0
  139. package/server/dist/utils/machine-id.js +46 -0
  140. package/server/dist/utils/request-context.js +5 -0
  141. package/server/dist/utils/security.utils.js +99 -0
@@ -0,0 +1,366 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AnilightProvider = void 0;
7
+ const logger_1 = __importDefault(require("../logger"));
8
+ const node_child_process_1 = require("node:child_process");
9
+ const base_provider_1 = require("./base-provider");
10
+ const ANILIGHT_API = 'https://api.anilight.live/api';
11
+ const SITE_BASE = 'https://anilight.live';
12
+ const BROWSER_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' +
13
+ '(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36';
14
+ function curlGetJSON(url) {
15
+ const args = [
16
+ '-sSL',
17
+ '-A',
18
+ BROWSER_UA,
19
+ '-H',
20
+ 'Referer: https://anilight.live/',
21
+ '-H',
22
+ 'Origin: https://anilight.live',
23
+ '-H',
24
+ 'Accept: application/json,text/plain,*/*;q=0.8',
25
+ '-H',
26
+ 'Accept-Language: en-US,en;q=0.9',
27
+ '-H',
28
+ 'Sec-Ch-Ua: "Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"',
29
+ '-H',
30
+ 'Sec-Ch-Ua-Mobile: ?0',
31
+ '-H',
32
+ 'Sec-Ch-Ua-Platform: "Windows"',
33
+ '-H',
34
+ 'Sec-Fetch-Dest: empty',
35
+ '-H',
36
+ 'Sec-Fetch-Mode: cors',
37
+ '-H',
38
+ 'Sec-Fetch-Site: cross-site',
39
+ '--max-time',
40
+ '15',
41
+ '-w',
42
+ '\n__HTTP_STATUS__%{http_code}',
43
+ '--',
44
+ url,
45
+ ];
46
+ let out;
47
+ try {
48
+ out = (0, node_child_process_1.execFileSync)('curl', args, {
49
+ encoding: 'utf-8',
50
+ maxBuffer: 10 * 1024 * 1024,
51
+ });
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ const m = out.match(/__HTTP_STATUS__(\d+)\s*$/);
57
+ const status = m ? parseInt(m[1], 10) : 0;
58
+ const body = m ? out.slice(0, m.index) : out;
59
+ if (status !== 200)
60
+ return null;
61
+ try {
62
+ return JSON.parse(body);
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ function curlGetText(url) {
69
+ const args = [
70
+ '-sSL',
71
+ '-A',
72
+ BROWSER_UA,
73
+ '-H',
74
+ 'Referer: https://anilight.live/',
75
+ '-H',
76
+ 'Origin: https://anilight.live',
77
+ '--max-time',
78
+ '15',
79
+ '-w',
80
+ '\n__HTTP_STATUS__%{http_code}',
81
+ '--',
82
+ url,
83
+ ];
84
+ let out;
85
+ try {
86
+ out = (0, node_child_process_1.execFileSync)('curl', args, {
87
+ encoding: 'utf-8',
88
+ maxBuffer: 10 * 1024 * 1024,
89
+ });
90
+ }
91
+ catch {
92
+ return null;
93
+ }
94
+ const m = out.match(/__HTTP_STATUS__(\d+)\s*$/);
95
+ const status = m ? parseInt(m[1], 10) : 0;
96
+ const body = m ? out.slice(0, m.index) : out;
97
+ if (status !== 200)
98
+ return null;
99
+ return body;
100
+ }
101
+ function toAbsolute(url) {
102
+ if (!url)
103
+ return url;
104
+ if (url.startsWith('http'))
105
+ return url;
106
+ return `${SITE_BASE}${url}`;
107
+ }
108
+ const slugByAnilistId = new Map();
109
+ function parseShowId(id) {
110
+ if (id.startsWith('al:')) {
111
+ const rest = id.slice(3);
112
+ const colonIdx = rest.indexOf(':');
113
+ if (colonIdx > 0) {
114
+ const anilistId = Number(rest.slice(0, colonIdx));
115
+ const slug = rest.slice(colonIdx + 1);
116
+ return {
117
+ anilistId: Number.isFinite(anilistId) && anilistId > 0 ? anilistId : null,
118
+ slug: slug || null,
119
+ };
120
+ }
121
+ const anilistId = Number(rest);
122
+ if (Number.isFinite(anilistId) && anilistId > 0) {
123
+ return { anilistId, slug: slugByAnilistId.get(anilistId) ?? null };
124
+ }
125
+ }
126
+ if (id && id.length > 3) {
127
+ return { anilistId: null, slug: id };
128
+ }
129
+ return { anilistId: null, slug: null };
130
+ }
131
+ function mapAnimeToShow(item) {
132
+ if (item.anilistId && item.slug) {
133
+ slugByAnilistId.set(item.anilistId, item.slug);
134
+ }
135
+ const title = item.title || {};
136
+ return {
137
+ _id: `al:${item.anilistId || ''}:${item.slug || ''}`,
138
+ id: `al:${item.anilistId || ''}:${item.slug || ''}`,
139
+ name: title.english || title.romaji || title.native || 'Unknown',
140
+ englishName: title.english || title.romaji || title.native || 'Unknown',
141
+ nativeName: title.native,
142
+ names: {
143
+ romaji: title.romaji,
144
+ english: title.english,
145
+ native: title.native,
146
+ },
147
+ thumbnail: toAbsolute(item.coverImage?.large || item.coverImage?.extraLarge || ''),
148
+ bannerImage: toAbsolute(item.bannerImage || ''),
149
+ description: item.description || '',
150
+ type: item.format || 'TV',
151
+ year: item.seasonYear || item.startDate?.year || null,
152
+ episodeCount: item.episodes ?? null,
153
+ episodeDuration: item.duration ? Number(item.duration) : null,
154
+ averageScore: item.averageScore ?? null,
155
+ score: item.popularity ?? null,
156
+ status: item.status || '',
157
+ season: item.season ? { season: item.season } : null,
158
+ genres: (item.genres || []).map((g) => ({ name: g })),
159
+ studios: (item.studios?.nodes || []).map((s) => ({ name: s.name || '' })),
160
+ availableEpisodesDetail: { sub: [], dub: [] },
161
+ nextAiring: item.nextAiringEpisode
162
+ ? {
163
+ episode: item.nextAiringEpisode.episode || 0,
164
+ timeUntilAiring: item.nextAiringEpisode.airingAt || 0,
165
+ }
166
+ : undefined,
167
+ };
168
+ }
169
+ class AnilightProvider extends base_provider_1.BaseProvider {
170
+ name = 'Anilight';
171
+ getWatchCacheKey(slug) {
172
+ return `anilight_watch_${slug}`;
173
+ }
174
+ async getWatchDocument(slug) {
175
+ const cacheKey = this.getWatchCacheKey(slug);
176
+ const cached = this.cache.get(cacheKey);
177
+ if (cached)
178
+ return cached;
179
+ const data = await curlGetJSON(`${ANILIGHT_API}/watch/${encodeURIComponent(slug)}`);
180
+ if (data) {
181
+ this.cache.set(cacheKey, data, 300);
182
+ }
183
+ return data;
184
+ }
185
+ async search(options) {
186
+ try {
187
+ const query = (options.query || '').trim();
188
+ if (!query)
189
+ return [];
190
+ const data = await curlGetJSON(`${ANILIGHT_API}/search?q=${encodeURIComponent(query)}`);
191
+ const results = Array.isArray(data) ? data : [];
192
+ if (!results.length)
193
+ return [];
194
+ return results.map(mapAnimeToShow);
195
+ }
196
+ catch (error) {
197
+ logger_1.default.error({ error }, '[Anilight] Search failed');
198
+ return [];
199
+ }
200
+ }
201
+ async getEpisodes(showId) {
202
+ try {
203
+ const { slug } = parseShowId(showId);
204
+ if (!slug)
205
+ return null;
206
+ const data = await this.getWatchDocument(slug);
207
+ const episodes = data?.episodes || [];
208
+ if (!episodes.length) {
209
+ return { episodes: [], description: '' };
210
+ }
211
+ const episodeNumbers = episodes.map((ep) => String(ep.number)).filter(Boolean);
212
+ return { episodes: episodeNumbers, description: '' };
213
+ }
214
+ catch (error) {
215
+ logger_1.default.error({ error, showId }, '[Anilight] getEpisodes failed');
216
+ return null;
217
+ }
218
+ }
219
+ async getStreamUrls(showId, episodeNumber, mode) {
220
+ try {
221
+ const { slug } = parseShowId(showId);
222
+ if (!slug)
223
+ return null;
224
+ const watch = await this.getWatchDocument(slug);
225
+ if (!watch)
226
+ return null;
227
+ const providers = (mode === 'sub' ? watch.servers?.subProviders : watch.servers?.dubProviders) ?? [];
228
+ const sources = [];
229
+ for (const provider of providers) {
230
+ const data = await curlGetJSON(`${ANILIGHT_API}/sources?id=${watch.id}\u0026epNum=${episodeNumber}\u0026type=${mode}\u0026providerId=${provider.id}`);
231
+ if (!data?.sources)
232
+ continue;
233
+ const links = [];
234
+ for (const source of data.sources) {
235
+ let rawUrl = source.url || '';
236
+ if (!rawUrl)
237
+ continue;
238
+ if (rawUrl.includes('vibeplayer.site')) {
239
+ rawUrl = rawUrl.replace('vibeplayer.site', 'vivibebe.site');
240
+ }
241
+ if (rawUrl.includes('24stream.xyz')) {
242
+ rawUrl = rawUrl.replace('24stream.xyz', 'aniwatchtv.site');
243
+ }
244
+ const isHls = rawUrl.includes('.m3u8') || source.quality === 'auto';
245
+ let proxyUrl = `/api/proxy?url=${encodeURIComponent(rawUrl)}&referer=${encodeURIComponent('https://anilight.live/')}`;
246
+ if (provider.id === 'misa') {
247
+ proxyUrl = `${ANILIGHT_API}/lb/misa/proxy?url=${encodeURIComponent(rawUrl)}`;
248
+ }
249
+ if (provider.id === 'mello') {
250
+ proxyUrl = `${ANILIGHT_API}/lb/mello/proxy?url=${encodeURIComponent(rawUrl)}`;
251
+ }
252
+ if (provider.id === 'misora') {
253
+ proxyUrl = `${ANILIGHT_API}/proxy?url=${encodeURIComponent(rawUrl)}&referer=${encodeURIComponent('https://anilight.live/')}`;
254
+ }
255
+ if (provider.id === 'ryu') {
256
+ proxyUrl = `${ANILIGHT_API}/proxy/ryu?url=${encodeURIComponent(rawUrl)}`;
257
+ }
258
+ const qualityLabel = source.quality && source.quality !== 'auto'
259
+ ? source.quality.endsWith('p')
260
+ ? source.quality
261
+ : `${source.quality}p`
262
+ : 'Auto';
263
+ links.push({ resolutionStr: qualityLabel, link: proxyUrl, hls: isHls });
264
+ if (isHls && rawUrl.endsWith('master.m3u8')) {
265
+ try {
266
+ const masterContent = curlGetText(rawUrl);
267
+ if (typeof masterContent === 'string' &&
268
+ masterContent.includes('#EXT-X-STREAM-INF')) {
269
+ const lines = masterContent.split('\n');
270
+ const baseUrl = new URL(rawUrl);
271
+ for (let i = 0; i < lines.length; i++) {
272
+ const line = lines[i].trim();
273
+ if (line.startsWith('#EXT-X-STREAM-INF')) {
274
+ const nameMatch = line.match(/NAME="([^"]+)"/) || line.match(/RESOLUTION=\d+x(\d+)/);
275
+ const resLabel = nameMatch
276
+ ? nameMatch[1].endsWith('p')
277
+ ? nameMatch[1]
278
+ : `${nameMatch[1]}p`
279
+ : 'HD';
280
+ const nextLine = (lines[i + 1] || '').trim();
281
+ if (nextLine && !nextLine.startsWith('#')) {
282
+ const subUrl = new URL(nextLine, baseUrl).href;
283
+ const subProxyUrl = `/api/proxy?url=${encodeURIComponent(subUrl)}&referer=${encodeURIComponent('https://anilight.live/')}`;
284
+ links.push({ resolutionStr: resLabel, link: subProxyUrl, hls: true });
285
+ }
286
+ }
287
+ }
288
+ }
289
+ }
290
+ catch (e) {
291
+ logger_1.default.warn({ rawUrl }, '[Anilight] Master playlist resolution parsing failed');
292
+ }
293
+ }
294
+ }
295
+ if (links.length === 0)
296
+ continue;
297
+ const subtitles = (data.tracks || [])
298
+ .filter((t) => t.file || t.url)
299
+ .map((t) => {
300
+ const raw = t.file || t.url || '';
301
+ return {
302
+ language: t.lang || t.label || 'en',
303
+ label: t.label || t.lang || 'English',
304
+ url: provider.id === 'misa' || provider.id === 'misora'
305
+ ? `${ANILIGHT_API}/proxy/captions?url=${encodeURIComponent(raw)}`
306
+ : raw,
307
+ };
308
+ });
309
+ if (provider.id === 'misora' || provider.id === 'misa') {
310
+ const m3u8Subs = subtitles
311
+ .map((s, i) => ({ ...s, i }))
312
+ .filter((s) => s.url.includes('.m3u8'));
313
+ for (const sub of m3u8Subs) {
314
+ let vttUrl = null;
315
+ try {
316
+ const base = sub.url.replace(/\/[^/]*\.m3u8$/, '/');
317
+ const candidate = `${base}sub.vtt`;
318
+ const vttResp = curlGetText(candidate);
319
+ if (vttResp && vttResp.includes('WEBVTT')) {
320
+ vttUrl = candidate;
321
+ }
322
+ }
323
+ catch {
324
+ // ignore
325
+ }
326
+ if (!vttUrl) {
327
+ try {
328
+ const hashMatch = sub.url.match(/\/cachesub\/([^/]+)\//);
329
+ if (hashMatch?.[1]) {
330
+ const candidate = `https://ani10.nukitashi.top/${hashMatch[1]}/sub.vtt`;
331
+ const vttResp = curlGetText(candidate);
332
+ if (vttResp && vttResp.includes('WEBVTT')) {
333
+ vttUrl = candidate;
334
+ }
335
+ }
336
+ }
337
+ catch {
338
+ // ignore
339
+ }
340
+ }
341
+ if (vttUrl) {
342
+ subtitles[sub.i] = {
343
+ language: sub.language,
344
+ label: sub.label,
345
+ url: vttUrl,
346
+ };
347
+ }
348
+ }
349
+ }
350
+ sources.push({
351
+ sourceName: provider.id,
352
+ links,
353
+ subtitles: subtitles.length ? subtitles : undefined,
354
+ type: 'player',
355
+ actualEpisodeNumber: episodeNumber,
356
+ });
357
+ }
358
+ return sources.length ? sources : null;
359
+ }
360
+ catch (error) {
361
+ logger_1.default.error({ error, showId, episodeNumber }, '[Anilight] getStreamUrls failed');
362
+ return null;
363
+ }
364
+ }
365
+ }
366
+ exports.AnilightProvider = AnilightProvider;