mikmc commited on
Commit
ed280e7
·
verified ·
1 Parent(s): 3b71d97

Upload 32 files

Browse files
Dockerfile CHANGED
@@ -1,8 +1,8 @@
1
- # syntax=docker/dockerfile:1
2
-
3
- FROM node:18-alpine
4
- WORKDIR /app
5
- COPY . .
6
- RUN yarn install --production
7
- CMD ["node", "index.js"]
8
- EXPOSE 3649
 
1
+ # syntax=docker/dockerfile:1
2
+
3
+ FROM node:18-alpine
4
+ WORKDIR /app
5
+ COPY . .
6
+ RUN yarn install --production
7
+ CMD ["node", "index.js"]
8
+ EXPOSE 3000
New Text Document.txt ADDED
File without changes
Procfile ADDED
@@ -0,0 +1 @@
 
 
1
+ web: node index.js
README.md CHANGED
@@ -1,11 +1,11 @@
1
- ---
2
- title: Xtremio Plus
3
- emoji: 🔥
4
- colorFrom: blue
5
- colorTo: gray
6
- sdk: docker
7
- pinned: false
8
- short_description: iptv with epg and vod search
9
- ---
10
-
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ ---
2
+ title: Xtremio Plus
3
+ emoji: 🔥
4
+ colorFrom: blue
5
+ colorTo: gray
6
+ sdk: docker
7
+ pinned: false
8
+ short_description: iptv with epg and vod search
9
+ ---
10
+
11
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
addon.js ADDED
@@ -0,0 +1,421 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios').default;
2
+ const { handleChannelRequest, getEpgInfoBatch } = require('./tvGuide');
3
+
4
+ axios.defaults.headers.get["content-type"] = "application/json";
5
+ axios.defaults.timeout = 60000
6
+ axios.defaults.method = "GET"
7
+
8
+ function getUserData(userConf) {
9
+ let retrievedData, url, obj = {}
10
+ try {
11
+ retrievedData = JSON.parse(Buffer.from(userConf, 'base64').toString())
12
+ } catch (error) {
13
+ return "error while parsing url"
14
+ }
15
+
16
+ let domainName, baseURL, idPrefix
17
+
18
+ if(typeof retrievedData === "object"){
19
+ domainName = retrievedData.BaseURL.split("/")[2].split(":")[0] || "unknown"
20
+ baseURL = retrievedData.BaseURL
21
+ idPrefix = domainName.charAt(0) + domainName.substr(Math.ceil(domainName.length / 2 - 1), domainName.length % 2 === 0 ? 2 : 1) + domainName.charAt(domainName.length - 1) + ":";
22
+
23
+ obj = {
24
+ baseURL,
25
+ domainName,
26
+ idPrefix,
27
+ username: retrievedData.username,
28
+ password: retrievedData.password,
29
+ timezone: retrievedData.timezone || 'UTC'
30
+ }
31
+
32
+ } else if(retrievedData.includes("http")){
33
+ url = retrievedData
34
+
35
+ const queryString = url.split('?')[1] || "unknown"
36
+ baseURL = url.split('/')[0] + "//" + url.split('?')[0].split('/')[2] || "unknown"
37
+
38
+ domainName = url.split("?")[0].split("/")[2].split(":")[0] || "unknown"
39
+ idPrefix = domainName.charAt(0) + domainName.substr(Math.ceil(domainName.length / 2 - 1), domainName.length % 2 === 0 ? 2 : 1) + domainName.charAt(domainName.length - 1) + ":";
40
+
41
+ if(queryString === undefined){return {result:"URL does not have any queries!"}}
42
+ if(baseURL === undefined){return {result:"URL does not seem like an url!"}}
43
+
44
+ obj.baseURL = baseURL
45
+ obj.domainName = domainName
46
+ obj.idPrefix = idPrefix
47
+
48
+ const urlParams = new URLSearchParams(queryString);
49
+ const entries = urlParams.entries();
50
+
51
+ for(const entry of entries) {
52
+ obj[entry[0]] = entry[1]
53
+ }
54
+
55
+ obj.timezone = obj.timezone || 'UTC';
56
+ }
57
+
58
+ if(obj.username && obj.password && obj.baseURL){
59
+ return obj
60
+ }else{
61
+ return {}
62
+ }
63
+ }
64
+
65
+ async function getManifest(url) {
66
+ const obj = getUserData(url)
67
+
68
+ let vod
69
+ try {
70
+ vod = await axios({url:`${obj.baseURL}/player_api.php?username=${obj.username}&password=${obj.password}&action=get_vod_categories`})
71
+ } catch (error) {
72
+ return {error}
73
+ }
74
+ const vodJSON = vod.data
75
+
76
+ let movieCatalog = []
77
+ if (vod.status === 200){
78
+ vodJSON.forEach(i => {
79
+ let name = i.category_name
80
+ movieCatalog.push(name)
81
+ });
82
+ }
83
+
84
+ let series
85
+ try {
86
+ series = await axios({url:`${obj.baseURL}/player_api.php?username=${obj.username}&password=${obj.password}&action=get_series_categories`})
87
+ } catch (error) {
88
+ return {error}
89
+ }
90
+ const seriesJSON = series.data
91
+
92
+ let seriesCatalog = []
93
+ if(series.status === 200){
94
+ seriesJSON.forEach(i => {
95
+ let name = i.category_name
96
+ seriesCatalog.push(name)
97
+ });
98
+ }
99
+
100
+ let live
101
+ try {
102
+ live = await axios({url:`${obj.baseURL}/player_api.php?username=${obj.username}&password=${obj.password}&action=get_live_categories`})
103
+ } catch (error) {
104
+ return {error}
105
+ }
106
+ const liveJSON = live.data
107
+
108
+ let liveCatalog = []
109
+ if(series.status === 200){
110
+ liveJSON.forEach(i => {
111
+ let name = i.category_name
112
+ liveCatalog.push(name)
113
+ });
114
+ }
115
+
116
+ const manifest = {
117
+ id:`org.community.${obj.domainName}` || "org.community.youriptv",
118
+ version:"2.0.0",
119
+ name:obj.domainName + " IPTV" || "Your IPTV",
120
+ description:`You will access to your ${obj.domainName} IPTV with this addon!`,
121
+ idPrefixes:[obj.idPrefix, "tt"],
122
+ catalogs:[
123
+ {
124
+ id:`${obj.idPrefix}movie`,
125
+ name: obj.domainName || "Your IPTV",
126
+ type:"movie",
127
+ extra:[{name:"genre",options:movieCatalog,isRequired:true}],
128
+ isRequired: true
129
+ },
130
+ {
131
+ id:`${obj.idPrefix}series`,
132
+ name:obj.domainName || "Your IPTV",
133
+ type:"series",
134
+ extra:[{name:"genre",options:seriesCatalog,isRequired:true}],
135
+ isRequired: true
136
+ },
137
+ {
138
+ id:`${obj.idPrefix}tv`,
139
+ name: obj.domainName || "Your IPTV",
140
+ type:"tv",
141
+ extra:[{name:"genre",options:liveCatalog,isRequired:true}],
142
+ }
143
+ ],
144
+ resources:["catalog","meta","stream"],
145
+ types:["movie","series","tv"],
146
+ behaviorHints:{
147
+ configurable: true,
148
+ configurationRequired: false,
149
+ epgSupported: true
150
+ },
151
+ }
152
+
153
+ return manifest
154
+ }
155
+
156
+ function getValidUrl(url) {
157
+ try {
158
+ const urlObj = new URL(url);
159
+ return urlObj.protocol.startsWith('http') ? url : '';
160
+ } catch {
161
+ return '';
162
+ }
163
+ }
164
+
165
+ async function getCatalog(url,type,genre) {
166
+ const obj = getUserData(url)
167
+
168
+ let getCategoryID
169
+
170
+ try {
171
+ if(type === "movie"){
172
+ getCategoryID = await axios({url:`${obj.baseURL}/player_api.php?username=${obj.username}&password=${obj.password}&action=get_vod_categories`})
173
+ }
174
+ else if(type ==="series"){
175
+ getCategoryID = await axios({url:`${obj.baseURL}/player_api.php?username=${obj.username}&password=${obj.password}&action=get_series_categories`})
176
+ }
177
+ else if(type ==="tv"){
178
+ getCategoryID = await axios({url:`${obj.baseURL}/player_api.php?username=${obj.username}&password=${obj.password}&action=get_live_categories`})
179
+ }
180
+ }catch (error) {
181
+ return []
182
+ }
183
+
184
+ let catID
185
+
186
+ getCategoryID.data.forEach(i => {
187
+ if(i.category_name === genre){
188
+ catID = i.category_id
189
+ }
190
+ });
191
+
192
+ let action = type === "movie" ? "get_vod_streams" : type === "series" ? "get_series": type ==="tv" ? "get_live_streams" : "error"
193
+
194
+ let paramsCat = {
195
+ username: obj.username,
196
+ password: obj.password,
197
+ action,
198
+ category_id: catID
199
+ }
200
+
201
+ let getCatalogs
202
+ try {
203
+ getCatalogs = await axios({url:`${obj.baseURL}/player_api.php`,method:"GET",params:paramsCat})
204
+ } catch (error) {
205
+ return []
206
+ }
207
+
208
+ let metas = []
209
+
210
+ if (type === "tv") {
211
+ const channelIds = getCatalogs.data
212
+ .filter(i => i.epg_channel_id)
213
+ .map(i => ({
214
+ stream_id: i.stream_id,
215
+ epg_channel_id: i.epg_channel_id
216
+ }));
217
+ let epgInfo;
218
+ try {
219
+ epgInfo = await getEpgInfoBatch(channelIds, obj.baseURL, obj.username, obj.password, obj.timezone);
220
+ } catch (error) {
221
+ console.error('Error fetching EPG info:', error);
222
+ }
223
+
224
+ getCatalogs.data.forEach(i => {
225
+ let id = obj.idPrefix + i.stream_id || "";
226
+ let name = i.name;
227
+ let poster = getValidUrl(i.stream_icon);
228
+ let posterShape = "square";
229
+
230
+ let meta = { id, type, name, poster, posterShape };
231
+
232
+ if (epgInfo && epgInfo[i.stream_id]) {
233
+ const currentProgram = epgInfo[i.stream_id].currentProgram;
234
+ const nextProgram = epgInfo[i.stream_id].nextProgram;
235
+
236
+ let description = '';
237
+ if (currentProgram) {
238
+ description += `Now: ${currentProgram.title}\n${currentProgram.start} - ${currentProgram.description}\n`;
239
+ }
240
+ if (nextProgram) {
241
+ description += `\nNext: ${nextProgram.title}\n${nextProgram.start} - ${nextProgram.description}`;
242
+ }
243
+
244
+ meta.description = description;
245
+ } else {
246
+ meta.description = "No program information available";
247
+ }
248
+
249
+ metas.push(meta);
250
+ });
251
+ } else {
252
+ getCatalogs.data.forEach(i => {
253
+ let id, name = i.name, poster, posterShape, imdbRating
254
+
255
+ if(type === "series"){
256
+ id = obj.idPrefix + i.series_id || ""
257
+ poster = getValidUrl(i.cover)
258
+ imdbRating = i.rating || ""
259
+ posterShape = "poster"
260
+ }else if(type === "movie"){
261
+ id = obj.idPrefix + i.stream_id || ""
262
+ poster = getValidUrl(i.stream_icon)
263
+ imdbRating = i.rating || ""
264
+ posterShape = "poster"
265
+ }
266
+
267
+ metas.push({id,type,name,poster,posterShape,imdbRating})
268
+ });
269
+ }
270
+
271
+ return metas
272
+ }
273
+
274
+ async function getMeta(url,type,id) {
275
+ const streamID = id.split(":")[1]
276
+ const obj = getUserData(url)
277
+
278
+ let action = type === "movie" ? "get_vod_info" : type === "series" ? "get_series_info": type ==="tv" ? "get_live_streams" : "error"
279
+ let requestID = type === "movie" ? "vod_id" : type === "series" ? "series_id": type ==="tv" ? "stream_id" : "error"
280
+
281
+ let params = {
282
+ username: obj.username,
283
+ password: obj.password,
284
+ action,
285
+ [requestID]:streamID
286
+ }
287
+
288
+ if(type === "tv"){
289
+ delete params[requestID]
290
+ }
291
+
292
+ let getMeta
293
+
294
+ try {
295
+ getMeta = await axios({url:`${obj.baseURL}/player_api.php`,params})
296
+ } catch (error) {
297
+ console.error('Error fetching metadata:', error);
298
+ return {}
299
+ }
300
+
301
+ let meta = {}
302
+
303
+ if(type === "movie"|| type === "series"){
304
+ if (!getMeta.data || !getMeta.data.info) {
305
+ console.error('Unexpected response structure:', getMeta.data);
306
+ return {};
307
+ }
308
+ meta = {
309
+ id: obj.idPrefix + streamID || "",
310
+ type,
311
+ name: getMeta.data.info.name || "",
312
+ poster: getMeta.data.info.cover_big || "",
313
+ background: (getMeta.data.info.backdrop_path && getMeta.data.info.backdrop_path[0]) || "https://www.stremio.com/website/wallpapers/stremio-wallpaper-5.jpg",
314
+ description: getMeta.data.info.description || "",
315
+ releaseInfo: getMeta.data.info.releaseDate || getMeta.data.info.releasedate || ""
316
+ }
317
+ if (meta.releaseInfo) {
318
+ meta.releaseInfo = String(meta.releaseInfo.split("-")[0]);
319
+ }
320
+ }
321
+
322
+ if(type === "series"){
323
+ let videos = []
324
+
325
+ const seasons = Object.keys(getMeta.data.episodes || {})
326
+
327
+ seasons.forEach(season => {
328
+ (getMeta.data.episodes[season] || []).forEach(episode => {
329
+ let id = obj.idPrefix + episode.id || ""
330
+ let title = episode.title || ""
331
+ let season = episode.season || null
332
+ let episodeNo = episode.episode_num || null
333
+ let overview = episode.plot || ""
334
+ let thumbnail = episode.info?.movie_image || null
335
+ let released = episode.info?.releasedate ? new Date(episode.info.releasedate) : null
336
+ let container_extension = episode.container_extension || "mp4"
337
+
338
+ let streams = [{
339
+ name:obj.domainName,
340
+ description: title,
341
+ url: `${obj.baseURL}/series/${obj.username}/${obj.password}/${episode.id}.${container_extension}`,
342
+ }]
343
+
344
+ videos.push({id,title,season,episode:episodeNo,overview,thumbnail,released,streams})
345
+ });
346
+ });
347
+
348
+ meta.name = getMeta.data.info?.name || "",
349
+ meta.videos = videos
350
+
351
+ }else if(type === "movie"){
352
+ let imdbRating = getMeta.data.info?.rating || ""
353
+ meta.imdbRating = imdbRating
354
+
355
+ }else if(type === "tv"){
356
+ let metaTV = [];
357
+ const channelInfo = getMeta.data.find(i => Number(i.stream_id) === Number(streamID));
358
+
359
+ if (channelInfo) {
360
+ let id = obj.idPrefix + channelInfo.stream_id;
361
+ let name = channelInfo.name || "";
362
+ let background = "https://www.stremio.com/website/wallpapers/stremio-wallpaper-5.jpg";
363
+ let logo = channelInfo.stream_icon || null;
364
+
365
+ try {
366
+ const epgInfo = await handleChannelRequest(channelInfo.epg_channel_id, obj.baseURL, obj.username, obj.password, obj.timezone);
367
+
368
+ if (epgInfo && epgInfo.currentProgram) {
369
+ let description = `Now: ${epgInfo.currentProgram.title}\n${epgInfo.currentProgram.start} - ${epgInfo.currentProgram.stop}\n${epgInfo.currentProgram.description || ''}\n\n`;
370
+
371
+ if (epgInfo.nextProgram) {
372
+ description += `Next: ${epgInfo.nextProgram.title}\n${epgInfo.nextProgram.start} - ${epgInfo.nextProgram.stop}\n${epgInfo.nextProgram.description || ''}`;
373
+ }
374
+
375
+ metaTV.push({
376
+ id,
377
+ name,
378
+ type,
379
+ background,
380
+ logo,
381
+ poster: logo,
382
+ posterShape: "square",
383
+ description: description,
384
+ genres: ["Live TV"]
385
+ });
386
+ } else {
387
+ metaTV.push({
388
+ id,
389
+ name,
390
+ type,
391
+ background,
392
+ logo,
393
+ poster: logo,
394
+ posterShape: "square",
395
+ description: "No program information available",
396
+ genres: ["Live TV"]
397
+ });
398
+ }
399
+ } catch (error) {
400
+ console.error('Error fetching EPG info:', error);
401
+ metaTV.push({
402
+ id,
403
+ name,
404
+ type,
405
+ background,
406
+ logo,
407
+ poster: logo,
408
+ posterShape: "square",
409
+ description: "Error fetching program information",
410
+ genres: ["Live TV"]
411
+ });
412
+ }
413
+ }
414
+
415
+ return metaTV[0] || {};
416
+ }
417
+
418
+ return meta
419
+ }
420
+
421
+ module.exports = {getUserData, getManifest, getCatalog, getMeta}
app/Dockerfile ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # syntax=docker/dockerfile:1
2
+
3
+ FROM node:18-alpine
4
+ WORKDIR /app
5
+ COPY . .
6
+ RUN yarn install --production
7
+ CMD ["node", "index.js"]
8
+ EXPOSE 3000
app/New Text Document.txt ADDED
File without changes
app/Procfile ADDED
@@ -0,0 +1 @@
 
 
1
+ web: node index.js
app/README.md ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Xtremio Plus
3
+ emoji: 🔥
4
+ colorFrom: blue
5
+ colorTo: gray
6
+ sdk: docker
7
+ pinned: false
8
+ short_description: iptv with epg and vod search
9
+ ---
10
+
11
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app/addon.js ADDED
@@ -0,0 +1,421 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios').default;
2
+ const { handleChannelRequest, getEpgInfoBatch } = require('./tvGuide');
3
+
4
+ axios.defaults.headers.get["content-type"] = "application/json";
5
+ axios.defaults.timeout = 60000
6
+ axios.defaults.method = "GET"
7
+
8
+ function getUserData(userConf) {
9
+ let retrievedData, url, obj = {}
10
+ try {
11
+ retrievedData = JSON.parse(Buffer.from(userConf, 'base64').toString())
12
+ } catch (error) {
13
+ return "error while parsing url"
14
+ }
15
+
16
+ let domainName, baseURL, idPrefix
17
+
18
+ if(typeof retrievedData === "object"){
19
+ domainName = retrievedData.BaseURL.split("/")[2].split(":")[0] || "unknown"
20
+ baseURL = retrievedData.BaseURL
21
+ idPrefix = domainName.charAt(0) + domainName.substr(Math.ceil(domainName.length / 2 - 1), domainName.length % 2 === 0 ? 2 : 1) + domainName.charAt(domainName.length - 1) + ":";
22
+
23
+ obj = {
24
+ baseURL,
25
+ domainName,
26
+ idPrefix,
27
+ username: retrievedData.username,
28
+ password: retrievedData.password,
29
+ timezone: retrievedData.timezone || 'UTC'
30
+ }
31
+
32
+ } else if(retrievedData.includes("http")){
33
+ url = retrievedData
34
+
35
+ const queryString = url.split('?')[1] || "unknown"
36
+ baseURL = url.split('/')[0] + "//" + url.split('?')[0].split('/')[2] || "unknown"
37
+
38
+ domainName = url.split("?")[0].split("/")[2].split(":")[0] || "unknown"
39
+ idPrefix = domainName.charAt(0) + domainName.substr(Math.ceil(domainName.length / 2 - 1), domainName.length % 2 === 0 ? 2 : 1) + domainName.charAt(domainName.length - 1) + ":";
40
+
41
+ if(queryString === undefined){return {result:"URL does not have any queries!"}}
42
+ if(baseURL === undefined){return {result:"URL does not seem like an url!"}}
43
+
44
+ obj.baseURL = baseURL
45
+ obj.domainName = domainName
46
+ obj.idPrefix = idPrefix
47
+
48
+ const urlParams = new URLSearchParams(queryString);
49
+ const entries = urlParams.entries();
50
+
51
+ for(const entry of entries) {
52
+ obj[entry[0]] = entry[1]
53
+ }
54
+
55
+ obj.timezone = obj.timezone || 'UTC';
56
+ }
57
+
58
+ if(obj.username && obj.password && obj.baseURL){
59
+ return obj
60
+ }else{
61
+ return {}
62
+ }
63
+ }
64
+
65
+ async function getManifest(url) {
66
+ const obj = getUserData(url)
67
+
68
+ let vod
69
+ try {
70
+ vod = await axios({url:`${obj.baseURL}/player_api.php?username=${obj.username}&password=${obj.password}&action=get_vod_categories`})
71
+ } catch (error) {
72
+ return {error}
73
+ }
74
+ const vodJSON = vod.data
75
+
76
+ let movieCatalog = []
77
+ if (vod.status === 200){
78
+ vodJSON.forEach(i => {
79
+ let name = i.category_name
80
+ movieCatalog.push(name)
81
+ });
82
+ }
83
+
84
+ let series
85
+ try {
86
+ series = await axios({url:`${obj.baseURL}/player_api.php?username=${obj.username}&password=${obj.password}&action=get_series_categories`})
87
+ } catch (error) {
88
+ return {error}
89
+ }
90
+ const seriesJSON = series.data
91
+
92
+ let seriesCatalog = []
93
+ if(series.status === 200){
94
+ seriesJSON.forEach(i => {
95
+ let name = i.category_name
96
+ seriesCatalog.push(name)
97
+ });
98
+ }
99
+
100
+ let live
101
+ try {
102
+ live = await axios({url:`${obj.baseURL}/player_api.php?username=${obj.username}&password=${obj.password}&action=get_live_categories`})
103
+ } catch (error) {
104
+ return {error}
105
+ }
106
+ const liveJSON = live.data
107
+
108
+ let liveCatalog = []
109
+ if(series.status === 200){
110
+ liveJSON.forEach(i => {
111
+ let name = i.category_name
112
+ liveCatalog.push(name)
113
+ });
114
+ }
115
+
116
+ const manifest = {
117
+ id:`org.community.${obj.domainName}` || "org.community.youriptv",
118
+ version:"2.0.0",
119
+ name:obj.domainName + " IPTV" || "Your IPTV",
120
+ description:`You will access to your ${obj.domainName} IPTV with this addon!`,
121
+ idPrefixes:[obj.idPrefix, "tt"],
122
+ catalogs:[
123
+ {
124
+ id:`${obj.idPrefix}movie`,
125
+ name: obj.domainName || "Your IPTV",
126
+ type:"movie",
127
+ extra:[{name:"genre",options:movieCatalog,isRequired:true}],
128
+ isRequired: true
129
+ },
130
+ {
131
+ id:`${obj.idPrefix}series`,
132
+ name:obj.domainName || "Your IPTV",
133
+ type:"series",
134
+ extra:[{name:"genre",options:seriesCatalog,isRequired:true}],
135
+ isRequired: true
136
+ },
137
+ {
138
+ id:`${obj.idPrefix}tv`,
139
+ name: obj.domainName || "Your IPTV",
140
+ type:"tv",
141
+ extra:[{name:"genre",options:liveCatalog,isRequired:true}],
142
+ }
143
+ ],
144
+ resources:["catalog","meta","stream"],
145
+ types:["movie","series","tv"],
146
+ behaviorHints:{
147
+ configurable: true,
148
+ configurationRequired: false,
149
+ epgSupported: true
150
+ },
151
+ }
152
+
153
+ return manifest
154
+ }
155
+
156
+ function getValidUrl(url) {
157
+ try {
158
+ const urlObj = new URL(url);
159
+ return urlObj.protocol.startsWith('http') ? url : '';
160
+ } catch {
161
+ return '';
162
+ }
163
+ }
164
+
165
+ async function getCatalog(url,type,genre) {
166
+ const obj = getUserData(url)
167
+
168
+ let getCategoryID
169
+
170
+ try {
171
+ if(type === "movie"){
172
+ getCategoryID = await axios({url:`${obj.baseURL}/player_api.php?username=${obj.username}&password=${obj.password}&action=get_vod_categories`})
173
+ }
174
+ else if(type ==="series"){
175
+ getCategoryID = await axios({url:`${obj.baseURL}/player_api.php?username=${obj.username}&password=${obj.password}&action=get_series_categories`})
176
+ }
177
+ else if(type ==="tv"){
178
+ getCategoryID = await axios({url:`${obj.baseURL}/player_api.php?username=${obj.username}&password=${obj.password}&action=get_live_categories`})
179
+ }
180
+ }catch (error) {
181
+ return []
182
+ }
183
+
184
+ let catID
185
+
186
+ getCategoryID.data.forEach(i => {
187
+ if(i.category_name === genre){
188
+ catID = i.category_id
189
+ }
190
+ });
191
+
192
+ let action = type === "movie" ? "get_vod_streams" : type === "series" ? "get_series": type ==="tv" ? "get_live_streams" : "error"
193
+
194
+ let paramsCat = {
195
+ username: obj.username,
196
+ password: obj.password,
197
+ action,
198
+ category_id: catID
199
+ }
200
+
201
+ let getCatalogs
202
+ try {
203
+ getCatalogs = await axios({url:`${obj.baseURL}/player_api.php`,method:"GET",params:paramsCat})
204
+ } catch (error) {
205
+ return []
206
+ }
207
+
208
+ let metas = []
209
+
210
+ if (type === "tv") {
211
+ const channelIds = getCatalogs.data
212
+ .filter(i => i.epg_channel_id)
213
+ .map(i => ({
214
+ stream_id: i.stream_id,
215
+ epg_channel_id: i.epg_channel_id
216
+ }));
217
+ let epgInfo;
218
+ try {
219
+ epgInfo = await getEpgInfoBatch(channelIds, obj.baseURL, obj.username, obj.password, obj.timezone);
220
+ } catch (error) {
221
+ console.error('Error fetching EPG info:', error);
222
+ }
223
+
224
+ getCatalogs.data.forEach(i => {
225
+ let id = obj.idPrefix + i.stream_id || "";
226
+ let name = i.name;
227
+ let poster = getValidUrl(i.stream_icon);
228
+ let posterShape = "square";
229
+
230
+ let meta = { id, type, name, poster, posterShape };
231
+
232
+ if (epgInfo && epgInfo[i.stream_id]) {
233
+ const currentProgram = epgInfo[i.stream_id].currentProgram;
234
+ const nextProgram = epgInfo[i.stream_id].nextProgram;
235
+
236
+ let description = '';
237
+ if (currentProgram) {
238
+ description += `Now: ${currentProgram.title}\n${currentProgram.start} - ${currentProgram.description}\n`;
239
+ }
240
+ if (nextProgram) {
241
+ description += `\nNext: ${nextProgram.title}\n${nextProgram.start} - ${nextProgram.description}`;
242
+ }
243
+
244
+ meta.description = description;
245
+ } else {
246
+ meta.description = "No program information available";
247
+ }
248
+
249
+ metas.push(meta);
250
+ });
251
+ } else {
252
+ getCatalogs.data.forEach(i => {
253
+ let id, name = i.name, poster, posterShape, imdbRating
254
+
255
+ if(type === "series"){
256
+ id = obj.idPrefix + i.series_id || ""
257
+ poster = getValidUrl(i.cover)
258
+ imdbRating = i.rating || ""
259
+ posterShape = "poster"
260
+ }else if(type === "movie"){
261
+ id = obj.idPrefix + i.stream_id || ""
262
+ poster = getValidUrl(i.stream_icon)
263
+ imdbRating = i.rating || ""
264
+ posterShape = "poster"
265
+ }
266
+
267
+ metas.push({id,type,name,poster,posterShape,imdbRating})
268
+ });
269
+ }
270
+
271
+ return metas
272
+ }
273
+
274
+ async function getMeta(url,type,id) {
275
+ const streamID = id.split(":")[1]
276
+ const obj = getUserData(url)
277
+
278
+ let action = type === "movie" ? "get_vod_info" : type === "series" ? "get_series_info": type ==="tv" ? "get_live_streams" : "error"
279
+ let requestID = type === "movie" ? "vod_id" : type === "series" ? "series_id": type ==="tv" ? "stream_id" : "error"
280
+
281
+ let params = {
282
+ username: obj.username,
283
+ password: obj.password,
284
+ action,
285
+ [requestID]:streamID
286
+ }
287
+
288
+ if(type === "tv"){
289
+ delete params[requestID]
290
+ }
291
+
292
+ let getMeta
293
+
294
+ try {
295
+ getMeta = await axios({url:`${obj.baseURL}/player_api.php`,params})
296
+ } catch (error) {
297
+ console.error('Error fetching metadata:', error);
298
+ return {}
299
+ }
300
+
301
+ let meta = {}
302
+
303
+ if(type === "movie"|| type === "series"){
304
+ if (!getMeta.data || !getMeta.data.info) {
305
+ console.error('Unexpected response structure:', getMeta.data);
306
+ return {};
307
+ }
308
+ meta = {
309
+ id: obj.idPrefix + streamID || "",
310
+ type,
311
+ name: getMeta.data.info.name || "",
312
+ poster: getMeta.data.info.cover_big || "",
313
+ background: (getMeta.data.info.backdrop_path && getMeta.data.info.backdrop_path[0]) || "https://www.stremio.com/website/wallpapers/stremio-wallpaper-5.jpg",
314
+ description: getMeta.data.info.description || "",
315
+ releaseInfo: getMeta.data.info.releaseDate || getMeta.data.info.releasedate || ""
316
+ }
317
+ if (meta.releaseInfo) {
318
+ meta.releaseInfo = String(meta.releaseInfo.split("-")[0]);
319
+ }
320
+ }
321
+
322
+ if(type === "series"){
323
+ let videos = []
324
+
325
+ const seasons = Object.keys(getMeta.data.episodes || {})
326
+
327
+ seasons.forEach(season => {
328
+ (getMeta.data.episodes[season] || []).forEach(episode => {
329
+ let id = obj.idPrefix + episode.id || ""
330
+ let title = episode.title || ""
331
+ let season = episode.season || null
332
+ let episodeNo = episode.episode_num || null
333
+ let overview = episode.plot || ""
334
+ let thumbnail = episode.info?.movie_image || null
335
+ let released = episode.info?.releasedate ? new Date(episode.info.releasedate) : null
336
+ let container_extension = episode.container_extension || "mp4"
337
+
338
+ let streams = [{
339
+ name:obj.domainName,
340
+ description: title,
341
+ url: `${obj.baseURL}/series/${obj.username}/${obj.password}/${episode.id}.${container_extension}`,
342
+ }]
343
+
344
+ videos.push({id,title,season,episode:episodeNo,overview,thumbnail,released,streams})
345
+ });
346
+ });
347
+
348
+ meta.name = getMeta.data.info?.name || "",
349
+ meta.videos = videos
350
+
351
+ }else if(type === "movie"){
352
+ let imdbRating = getMeta.data.info?.rating || ""
353
+ meta.imdbRating = imdbRating
354
+
355
+ }else if(type === "tv"){
356
+ let metaTV = [];
357
+ const channelInfo = getMeta.data.find(i => Number(i.stream_id) === Number(streamID));
358
+
359
+ if (channelInfo) {
360
+ let id = obj.idPrefix + channelInfo.stream_id;
361
+ let name = channelInfo.name || "";
362
+ let background = "https://www.stremio.com/website/wallpapers/stremio-wallpaper-5.jpg";
363
+ let logo = channelInfo.stream_icon || null;
364
+
365
+ try {
366
+ const epgInfo = await handleChannelRequest(channelInfo.epg_channel_id, obj.baseURL, obj.username, obj.password, obj.timezone);
367
+
368
+ if (epgInfo && epgInfo.currentProgram) {
369
+ let description = `Now: ${epgInfo.currentProgram.title}\n${epgInfo.currentProgram.start} - ${epgInfo.currentProgram.stop}\n${epgInfo.currentProgram.description || ''}\n\n`;
370
+
371
+ if (epgInfo.nextProgram) {
372
+ description += `Next: ${epgInfo.nextProgram.title}\n${epgInfo.nextProgram.start} - ${epgInfo.nextProgram.stop}\n${epgInfo.nextProgram.description || ''}`;
373
+ }
374
+
375
+ metaTV.push({
376
+ id,
377
+ name,
378
+ type,
379
+ background,
380
+ logo,
381
+ poster: logo,
382
+ posterShape: "square",
383
+ description: description,
384
+ genres: ["Live TV"]
385
+ });
386
+ } else {
387
+ metaTV.push({
388
+ id,
389
+ name,
390
+ type,
391
+ background,
392
+ logo,
393
+ poster: logo,
394
+ posterShape: "square",
395
+ description: "No program information available",
396
+ genres: ["Live TV"]
397
+ });
398
+ }
399
+ } catch (error) {
400
+ console.error('Error fetching EPG info:', error);
401
+ metaTV.push({
402
+ id,
403
+ name,
404
+ type,
405
+ background,
406
+ logo,
407
+ poster: logo,
408
+ posterShape: "square",
409
+ description: "Error fetching program information",
410
+ genres: ["Live TV"]
411
+ });
412
+ }
413
+ }
414
+
415
+ return metaTV[0] || {};
416
+ }
417
+
418
+ return meta
419
+ }
420
+
421
+ module.exports = {getUserData, getManifest, getCatalog, getMeta}
app/assets/background.jpg ADDED
app/assets/logo.png ADDED
app/config.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var env = process.env.NODE_ENV ? 'beamup':'local';
2
+
3
+ var config = {
4
+ addon: 'started',
5
+ }
6
+
7
+ switch (env) {
8
+ //Public server build.
9
+ case 'beamup':
10
+ config.port = process.env.PORT
11
+ config.local = "5a0d1888fa64-your-iptv.baby-beamup.club"
12
+ break;
13
+
14
+ //Local sever build.
15
+ case 'local':
16
+ config.port = 3649
17
+ config.local = "http://127.0.0.1:" + config.port;
18
+ break;
19
+ }
20
+
21
+ module.exports = config;
app/en.jpeg ADDED
app/index.js ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const express = require("express");
2
+ const path = require("path"); // Import path module for path handling
3
+ const app = express();
4
+ const config = require('./config');
5
+ const MANIFEST = require('./manifest');
6
+ const { getManifest, getCatalog, getMeta, getUserData } = require("./addon");
7
+ const { createXtreamModule } = require("./xtream-module");
8
+
9
+ const NodeCache = require("node-cache");
10
+ const myCache = new NodeCache({ stdTTL: 200 });
11
+
12
+ // Middleware to allow CORS and set response headers
13
+ var respond = function (res, data) {
14
+ res.setHeader('Access-Control-Allow-Origin', '*');
15
+ res.setHeader('Access-Control-Allow-Headers', '*');
16
+ res.setHeader('Content-Type', 'application/json');
17
+ res.send(data);
18
+ };
19
+
20
+ // Serve static files from the 'assets' directory
21
+ app.use('/assets', express.static(path.join(__dirname, 'assets')));
22
+
23
+ app.engine('html', require('ejs').renderFile);
24
+ app.set('views', path.join(__dirname, 'views'));
25
+
26
+ app.get("/", function (req, res) {
27
+ res.redirect("/configure");
28
+ });
29
+
30
+ app.get("/:userConf?/configure", function (req, res) {
31
+ const newManifest = { ...{ MANIFEST } };
32
+ res.render('configure.html', newManifest);
33
+ });
34
+
35
+ app.get('/manifest.json', function (req, res) {
36
+ const newManifest = { ...MANIFEST };
37
+ newManifest.behaviorHints.configurationRequired = true;
38
+ respond(res, newManifest);
39
+ });
40
+
41
+ app.get('/:userConf/manifest.json', async function (req, res) {
42
+ let newManifest = { ...MANIFEST };
43
+ if (!((req || {}).params || {}).userConf) {
44
+ newManifest.behaviorHints.configurationRequired = true;
45
+ respond(res, newManifest);
46
+ } else {
47
+ try {
48
+ if (myCache.has(`manifest-${req.params.userConf}`)) {
49
+ respond(res, myCache.get(`manifest-${req.params.userConf}`));
50
+ } else {
51
+ newManifest = await getManifest(req.params.userConf);
52
+ if (newManifest && newManifest.id) {
53
+ myCache.set(`manifest-${req.params.userConf}`, newManifest);
54
+ }
55
+ respond(res, newManifest);
56
+ }
57
+ } catch (error) {
58
+ console.log(error);
59
+ respond(res, { error: error });
60
+ }
61
+ }
62
+ });
63
+
64
+ app.get('/:userConf/catalog/:type/:id/:extra?.json', async function (req, res) {
65
+ let { userConf, type, id, extra } = req.params;
66
+ let extraObj;
67
+
68
+ if (extra) {
69
+ try {
70
+ extraObj = JSON.parse('{"' + decodeURI(extra.replace(/&/g, '","').replace(/=/g, '":"')) + '"}');
71
+ } catch (error) {
72
+ console.log(error);
73
+ return respond(res, { metas: [] });
74
+ }
75
+ }
76
+
77
+ if (extraObj && extraObj.genre && extraObj.genre.includes("+")) {
78
+ extraObj.genre = extraObj.genre.replace(/\+/g, ' ');
79
+ }
80
+
81
+ let metas = [];
82
+ try {
83
+ if (myCache.has(`catalog-${userConf}-${type}-${id}-${extra}`)) {
84
+ respond(res, myCache.get(`catalog-${userConf}-${type}-${id}-${extra}`));
85
+ } else {
86
+ metas = await getCatalog(userConf, type, extraObj.genre);
87
+ if (metas.length > 0) {
88
+ myCache.set(`catalog-${userConf}-${type}-${id}-${extra}`, { metas: metas });
89
+ }
90
+ respond(res, { metas: metas });
91
+ }
92
+ } catch (error) {
93
+ console.log(error);
94
+ respond(res, { metas: [] });
95
+ }
96
+ });
97
+
98
+ app.get('/:userConf/meta/:type/:id.json', async function (req, res) {
99
+ let { userConf, type, id } = req.params;
100
+
101
+ try {
102
+ if (myCache.has(`meta-${userConf}-${type}-${id}`)) {
103
+ respond(res, myCache.get(`meta-${userConf}-${type}-${id}`));
104
+ } else {
105
+ const meta = await getMeta(userConf, type, id);
106
+ if (meta && meta.id) {
107
+ myCache.set(`meta-${userConf}-${type}-${id}`, { meta: meta });
108
+ }
109
+ respond(res, { meta: meta });
110
+ }
111
+ } catch (error) {
112
+ console.log(error);
113
+ respond(res, { error });
114
+ }
115
+ });
116
+
117
+ app.get('/:userConf/stream/:type/:id.json', async function (req, res) {
118
+ let { userConf, type, id } = req.params;
119
+ const obj = getUserData(userConf);
120
+
121
+ if (id.startsWith('tt')) {
122
+ // Handle IMDb IDs using the Xtream module
123
+ const xtreamModule = createXtreamModule(obj.baseURL, obj.username, obj.password);
124
+
125
+ try {
126
+ const xtreamResponse = await xtreamModule(id);
127
+ if (xtreamResponse && xtreamResponse.contentUrl) {
128
+ console.log('Stream URL for IMDb ID:', xtreamResponse.contentUrl);
129
+ respond(res, { streams: [{ url: xtreamResponse.contentUrl, name: xtreamResponse.title }] });
130
+ } else {
131
+ console.log('No stream found for IMDb ID:', id);
132
+ respond(res, { streams: [] });
133
+ }
134
+ } catch (error) {
135
+ console.error('Xtream module error:', error);
136
+ respond(res, { streams: [] });
137
+ }
138
+ } else {
139
+ // Existing logic for non-IMDb IDs
140
+ let extension = "mp4";
141
+ const streamID = id.split(":")[1];
142
+ let stream = [];
143
+ if (type === "tv") {
144
+ type = "live";
145
+ extension = "ts";
146
+ const url = `${obj.baseURL}/${type}/${obj.username}/${obj.password}/${streamID}.${extension}`;
147
+ console.log('Stream URL for TV:', url);
148
+ stream = [{
149
+ url: url,
150
+ name: "Watch Now",
151
+ behaviorHints: {
152
+ notWebReady: true
153
+ }
154
+ }];
155
+ } else {
156
+ const url = `${obj.baseURL}/${type}/${obj.username}/${obj.password}/${streamID}.${extension}`;
157
+ console.log('Stream URL for VOD:', url);
158
+ stream = [{
159
+ url: url,
160
+ name: "Watch Now"
161
+ }];
162
+ }
163
+
164
+ respond(res, { streams: stream });
165
+ }
166
+ });
167
+
168
+ // Listen for incoming requests
169
+ if (module.parent) {
170
+ module.exports = app;
171
+ } else {
172
+ app.listen(config.port, function () {
173
+ console.log(config);
174
+ });
175
+ }
app/manifest.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module.exports = {
2
+ id: "org.community.YourIPTV",
3
+ version: "2.0.5",
4
+ name: "HY EPG IPTV",
5
+ logo: "./assets/logo.png", // Local logo
6
+ description: "This addon brings all the Live Streams, VOD streams and Series from your IPTV subscription to your Stremio using Xtream API and supports IMDb IDs.",
7
+ types: ["movie", "series", "tv", "channel"],
8
+ background: "./assets/background.jpg", // Local background
9
+ resources: ["movie", "series", "tv"],
10
+ catalogs: [],
11
+ idPrefixes: ["yiptv:", "tt"],
12
+ behaviorHints: { configurable: true, configurationRequired: true },
13
+ };
app/package-lock.json ADDED
@@ -0,0 +1,1597 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "your-iptv-1",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 2,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "your-iptv-1",
9
+ "version": "1.0.0",
10
+ "license": "ISC",
11
+ "dependencies": {
12
+ "axios": "^0.27.2",
13
+ "ejs": "^3.1.8",
14
+ "express": "^4.18.1",
15
+ "moment-timezone": "^0.5.45",
16
+ "node-cache": "^5.1.2",
17
+ "node-fetch": "^3.3.2"
18
+ }
19
+ },
20
+ "node_modules/accepts": {
21
+ "version": "1.3.8",
22
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
23
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
24
+ "dependencies": {
25
+ "mime-types": "~2.1.34",
26
+ "negotiator": "0.6.3"
27
+ },
28
+ "engines": {
29
+ "node": ">= 0.6"
30
+ }
31
+ },
32
+ "node_modules/ansi-styles": {
33
+ "version": "4.3.0",
34
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
35
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
36
+ "dependencies": {
37
+ "color-convert": "^2.0.1"
38
+ },
39
+ "engines": {
40
+ "node": ">=8"
41
+ },
42
+ "funding": {
43
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
44
+ }
45
+ },
46
+ "node_modules/array-flatten": {
47
+ "version": "1.1.1",
48
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
49
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
50
+ },
51
+ "node_modules/async": {
52
+ "version": "3.2.4",
53
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
54
+ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
55
+ },
56
+ "node_modules/asynckit": {
57
+ "version": "0.4.0",
58
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
59
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
60
+ },
61
+ "node_modules/axios": {
62
+ "version": "0.27.2",
63
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
64
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
65
+ "dependencies": {
66
+ "follow-redirects": "^1.14.9",
67
+ "form-data": "^4.0.0"
68
+ }
69
+ },
70
+ "node_modules/balanced-match": {
71
+ "version": "1.0.2",
72
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
73
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
74
+ },
75
+ "node_modules/body-parser": {
76
+ "version": "1.20.0",
77
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
78
+ "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
79
+ "dependencies": {
80
+ "bytes": "3.1.2",
81
+ "content-type": "~1.0.4",
82
+ "debug": "2.6.9",
83
+ "depd": "2.0.0",
84
+ "destroy": "1.2.0",
85
+ "http-errors": "2.0.0",
86
+ "iconv-lite": "0.4.24",
87
+ "on-finished": "2.4.1",
88
+ "qs": "6.10.3",
89
+ "raw-body": "2.5.1",
90
+ "type-is": "~1.6.18",
91
+ "unpipe": "1.0.0"
92
+ },
93
+ "engines": {
94
+ "node": ">= 0.8",
95
+ "npm": "1.2.8000 || >= 1.4.16"
96
+ }
97
+ },
98
+ "node_modules/brace-expansion": {
99
+ "version": "1.1.11",
100
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
101
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
102
+ "dependencies": {
103
+ "balanced-match": "^1.0.0",
104
+ "concat-map": "0.0.1"
105
+ }
106
+ },
107
+ "node_modules/bytes": {
108
+ "version": "3.1.2",
109
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
110
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
111
+ "engines": {
112
+ "node": ">= 0.8"
113
+ }
114
+ },
115
+ "node_modules/call-bind": {
116
+ "version": "1.0.2",
117
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
118
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
119
+ "dependencies": {
120
+ "function-bind": "^1.1.1",
121
+ "get-intrinsic": "^1.0.2"
122
+ },
123
+ "funding": {
124
+ "url": "https://github.com/sponsors/ljharb"
125
+ }
126
+ },
127
+ "node_modules/chalk": {
128
+ "version": "4.1.2",
129
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
130
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
131
+ "dependencies": {
132
+ "ansi-styles": "^4.1.0",
133
+ "supports-color": "^7.1.0"
134
+ },
135
+ "engines": {
136
+ "node": ">=10"
137
+ },
138
+ "funding": {
139
+ "url": "https://github.com/chalk/chalk?sponsor=1"
140
+ }
141
+ },
142
+ "node_modules/clone": {
143
+ "version": "2.1.2",
144
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
145
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
146
+ "engines": {
147
+ "node": ">=0.8"
148
+ }
149
+ },
150
+ "node_modules/color-convert": {
151
+ "version": "2.0.1",
152
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
153
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
154
+ "dependencies": {
155
+ "color-name": "~1.1.4"
156
+ },
157
+ "engines": {
158
+ "node": ">=7.0.0"
159
+ }
160
+ },
161
+ "node_modules/color-name": {
162
+ "version": "1.1.4",
163
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
164
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
165
+ },
166
+ "node_modules/combined-stream": {
167
+ "version": "1.0.8",
168
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
169
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
170
+ "dependencies": {
171
+ "delayed-stream": "~1.0.0"
172
+ },
173
+ "engines": {
174
+ "node": ">= 0.8"
175
+ }
176
+ },
177
+ "node_modules/concat-map": {
178
+ "version": "0.0.1",
179
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
180
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
181
+ },
182
+ "node_modules/content-disposition": {
183
+ "version": "0.5.4",
184
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
185
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
186
+ "dependencies": {
187
+ "safe-buffer": "5.2.1"
188
+ },
189
+ "engines": {
190
+ "node": ">= 0.6"
191
+ }
192
+ },
193
+ "node_modules/content-type": {
194
+ "version": "1.0.4",
195
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
196
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
197
+ "engines": {
198
+ "node": ">= 0.6"
199
+ }
200
+ },
201
+ "node_modules/cookie": {
202
+ "version": "0.5.0",
203
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
204
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
205
+ "engines": {
206
+ "node": ">= 0.6"
207
+ }
208
+ },
209
+ "node_modules/cookie-signature": {
210
+ "version": "1.0.6",
211
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
212
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
213
+ },
214
+ "node_modules/data-uri-to-buffer": {
215
+ "version": "4.0.1",
216
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
217
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
218
+ "engines": {
219
+ "node": ">= 12"
220
+ }
221
+ },
222
+ "node_modules/debug": {
223
+ "version": "2.6.9",
224
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
225
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
226
+ "dependencies": {
227
+ "ms": "2.0.0"
228
+ }
229
+ },
230
+ "node_modules/delayed-stream": {
231
+ "version": "1.0.0",
232
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
233
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
234
+ "engines": {
235
+ "node": ">=0.4.0"
236
+ }
237
+ },
238
+ "node_modules/depd": {
239
+ "version": "2.0.0",
240
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
241
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
242
+ "engines": {
243
+ "node": ">= 0.8"
244
+ }
245
+ },
246
+ "node_modules/destroy": {
247
+ "version": "1.2.0",
248
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
249
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
250
+ "engines": {
251
+ "node": ">= 0.8",
252
+ "npm": "1.2.8000 || >= 1.4.16"
253
+ }
254
+ },
255
+ "node_modules/ee-first": {
256
+ "version": "1.1.1",
257
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
258
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
259
+ },
260
+ "node_modules/ejs": {
261
+ "version": "3.1.8",
262
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz",
263
+ "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==",
264
+ "dependencies": {
265
+ "jake": "^10.8.5"
266
+ },
267
+ "bin": {
268
+ "ejs": "bin/cli.js"
269
+ },
270
+ "engines": {
271
+ "node": ">=0.10.0"
272
+ }
273
+ },
274
+ "node_modules/encodeurl": {
275
+ "version": "1.0.2",
276
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
277
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
278
+ "engines": {
279
+ "node": ">= 0.8"
280
+ }
281
+ },
282
+ "node_modules/escape-html": {
283
+ "version": "1.0.3",
284
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
285
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
286
+ },
287
+ "node_modules/etag": {
288
+ "version": "1.8.1",
289
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
290
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
291
+ "engines": {
292
+ "node": ">= 0.6"
293
+ }
294
+ },
295
+ "node_modules/express": {
296
+ "version": "4.18.1",
297
+ "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
298
+ "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
299
+ "dependencies": {
300
+ "accepts": "~1.3.8",
301
+ "array-flatten": "1.1.1",
302
+ "body-parser": "1.20.0",
303
+ "content-disposition": "0.5.4",
304
+ "content-type": "~1.0.4",
305
+ "cookie": "0.5.0",
306
+ "cookie-signature": "1.0.6",
307
+ "debug": "2.6.9",
308
+ "depd": "2.0.0",
309
+ "encodeurl": "~1.0.2",
310
+ "escape-html": "~1.0.3",
311
+ "etag": "~1.8.1",
312
+ "finalhandler": "1.2.0",
313
+ "fresh": "0.5.2",
314
+ "http-errors": "2.0.0",
315
+ "merge-descriptors": "1.0.1",
316
+ "methods": "~1.1.2",
317
+ "on-finished": "2.4.1",
318
+ "parseurl": "~1.3.3",
319
+ "path-to-regexp": "0.1.7",
320
+ "proxy-addr": "~2.0.7",
321
+ "qs": "6.10.3",
322
+ "range-parser": "~1.2.1",
323
+ "safe-buffer": "5.2.1",
324
+ "send": "0.18.0",
325
+ "serve-static": "1.15.0",
326
+ "setprototypeof": "1.2.0",
327
+ "statuses": "2.0.1",
328
+ "type-is": "~1.6.18",
329
+ "utils-merge": "1.0.1",
330
+ "vary": "~1.1.2"
331
+ },
332
+ "engines": {
333
+ "node": ">= 0.10.0"
334
+ }
335
+ },
336
+ "node_modules/fetch-blob": {
337
+ "version": "3.2.0",
338
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
339
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
340
+ "funding": [
341
+ {
342
+ "type": "github",
343
+ "url": "https://github.com/sponsors/jimmywarting"
344
+ },
345
+ {
346
+ "type": "paypal",
347
+ "url": "https://paypal.me/jimmywarting"
348
+ }
349
+ ],
350
+ "dependencies": {
351
+ "node-domexception": "^1.0.0",
352
+ "web-streams-polyfill": "^3.0.3"
353
+ },
354
+ "engines": {
355
+ "node": "^12.20 || >= 14.13"
356
+ }
357
+ },
358
+ "node_modules/filelist": {
359
+ "version": "1.0.4",
360
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
361
+ "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
362
+ "dependencies": {
363
+ "minimatch": "^5.0.1"
364
+ }
365
+ },
366
+ "node_modules/filelist/node_modules/brace-expansion": {
367
+ "version": "2.0.1",
368
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
369
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
370
+ "dependencies": {
371
+ "balanced-match": "^1.0.0"
372
+ }
373
+ },
374
+ "node_modules/filelist/node_modules/minimatch": {
375
+ "version": "5.1.0",
376
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
377
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
378
+ "dependencies": {
379
+ "brace-expansion": "^2.0.1"
380
+ },
381
+ "engines": {
382
+ "node": ">=10"
383
+ }
384
+ },
385
+ "node_modules/finalhandler": {
386
+ "version": "1.2.0",
387
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
388
+ "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
389
+ "dependencies": {
390
+ "debug": "2.6.9",
391
+ "encodeurl": "~1.0.2",
392
+ "escape-html": "~1.0.3",
393
+ "on-finished": "2.4.1",
394
+ "parseurl": "~1.3.3",
395
+ "statuses": "2.0.1",
396
+ "unpipe": "~1.0.0"
397
+ },
398
+ "engines": {
399
+ "node": ">= 0.8"
400
+ }
401
+ },
402
+ "node_modules/follow-redirects": {
403
+ "version": "1.15.2",
404
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
405
+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
406
+ "funding": [
407
+ {
408
+ "type": "individual",
409
+ "url": "https://github.com/sponsors/RubenVerborgh"
410
+ }
411
+ ],
412
+ "engines": {
413
+ "node": ">=4.0"
414
+ },
415
+ "peerDependenciesMeta": {
416
+ "debug": {
417
+ "optional": true
418
+ }
419
+ }
420
+ },
421
+ "node_modules/form-data": {
422
+ "version": "4.0.0",
423
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
424
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
425
+ "dependencies": {
426
+ "asynckit": "^0.4.0",
427
+ "combined-stream": "^1.0.8",
428
+ "mime-types": "^2.1.12"
429
+ },
430
+ "engines": {
431
+ "node": ">= 6"
432
+ }
433
+ },
434
+ "node_modules/formdata-polyfill": {
435
+ "version": "4.0.10",
436
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
437
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
438
+ "dependencies": {
439
+ "fetch-blob": "^3.1.2"
440
+ },
441
+ "engines": {
442
+ "node": ">=12.20.0"
443
+ }
444
+ },
445
+ "node_modules/forwarded": {
446
+ "version": "0.2.0",
447
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
448
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
449
+ "engines": {
450
+ "node": ">= 0.6"
451
+ }
452
+ },
453
+ "node_modules/fresh": {
454
+ "version": "0.5.2",
455
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
456
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
457
+ "engines": {
458
+ "node": ">= 0.6"
459
+ }
460
+ },
461
+ "node_modules/function-bind": {
462
+ "version": "1.1.1",
463
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
464
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
465
+ },
466
+ "node_modules/get-intrinsic": {
467
+ "version": "1.1.3",
468
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
469
+ "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
470
+ "dependencies": {
471
+ "function-bind": "^1.1.1",
472
+ "has": "^1.0.3",
473
+ "has-symbols": "^1.0.3"
474
+ },
475
+ "funding": {
476
+ "url": "https://github.com/sponsors/ljharb"
477
+ }
478
+ },
479
+ "node_modules/has": {
480
+ "version": "1.0.3",
481
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
482
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
483
+ "dependencies": {
484
+ "function-bind": "^1.1.1"
485
+ },
486
+ "engines": {
487
+ "node": ">= 0.4.0"
488
+ }
489
+ },
490
+ "node_modules/has-flag": {
491
+ "version": "4.0.0",
492
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
493
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
494
+ "engines": {
495
+ "node": ">=8"
496
+ }
497
+ },
498
+ "node_modules/has-symbols": {
499
+ "version": "1.0.3",
500
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
501
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
502
+ "engines": {
503
+ "node": ">= 0.4"
504
+ },
505
+ "funding": {
506
+ "url": "https://github.com/sponsors/ljharb"
507
+ }
508
+ },
509
+ "node_modules/http-errors": {
510
+ "version": "2.0.0",
511
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
512
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
513
+ "dependencies": {
514
+ "depd": "2.0.0",
515
+ "inherits": "2.0.4",
516
+ "setprototypeof": "1.2.0",
517
+ "statuses": "2.0.1",
518
+ "toidentifier": "1.0.1"
519
+ },
520
+ "engines": {
521
+ "node": ">= 0.8"
522
+ }
523
+ },
524
+ "node_modules/iconv-lite": {
525
+ "version": "0.4.24",
526
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
527
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
528
+ "dependencies": {
529
+ "safer-buffer": ">= 2.1.2 < 3"
530
+ },
531
+ "engines": {
532
+ "node": ">=0.10.0"
533
+ }
534
+ },
535
+ "node_modules/inherits": {
536
+ "version": "2.0.4",
537
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
538
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
539
+ },
540
+ "node_modules/ipaddr.js": {
541
+ "version": "1.9.1",
542
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
543
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
544
+ "engines": {
545
+ "node": ">= 0.10"
546
+ }
547
+ },
548
+ "node_modules/jake": {
549
+ "version": "10.8.5",
550
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
551
+ "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
552
+ "dependencies": {
553
+ "async": "^3.2.3",
554
+ "chalk": "^4.0.2",
555
+ "filelist": "^1.0.1",
556
+ "minimatch": "^3.0.4"
557
+ },
558
+ "bin": {
559
+ "jake": "bin/cli.js"
560
+ },
561
+ "engines": {
562
+ "node": ">=10"
563
+ }
564
+ },
565
+ "node_modules/media-typer": {
566
+ "version": "0.3.0",
567
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
568
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
569
+ "engines": {
570
+ "node": ">= 0.6"
571
+ }
572
+ },
573
+ "node_modules/merge-descriptors": {
574
+ "version": "1.0.1",
575
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
576
+ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
577
+ },
578
+ "node_modules/methods": {
579
+ "version": "1.1.2",
580
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
581
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
582
+ "engines": {
583
+ "node": ">= 0.6"
584
+ }
585
+ },
586
+ "node_modules/mime": {
587
+ "version": "1.6.0",
588
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
589
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
590
+ "bin": {
591
+ "mime": "cli.js"
592
+ },
593
+ "engines": {
594
+ "node": ">=4"
595
+ }
596
+ },
597
+ "node_modules/mime-db": {
598
+ "version": "1.52.0",
599
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
600
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
601
+ "engines": {
602
+ "node": ">= 0.6"
603
+ }
604
+ },
605
+ "node_modules/mime-types": {
606
+ "version": "2.1.35",
607
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
608
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
609
+ "dependencies": {
610
+ "mime-db": "1.52.0"
611
+ },
612
+ "engines": {
613
+ "node": ">= 0.6"
614
+ }
615
+ },
616
+ "node_modules/minimatch": {
617
+ "version": "3.1.2",
618
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
619
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
620
+ "dependencies": {
621
+ "brace-expansion": "^1.1.7"
622
+ },
623
+ "engines": {
624
+ "node": "*"
625
+ }
626
+ },
627
+ "node_modules/moment": {
628
+ "version": "2.30.1",
629
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
630
+ "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
631
+ "engines": {
632
+ "node": "*"
633
+ }
634
+ },
635
+ "node_modules/moment-timezone": {
636
+ "version": "0.5.46",
637
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz",
638
+ "integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==",
639
+ "dependencies": {
640
+ "moment": "^2.29.4"
641
+ },
642
+ "engines": {
643
+ "node": "*"
644
+ }
645
+ },
646
+ "node_modules/ms": {
647
+ "version": "2.0.0",
648
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
649
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
650
+ },
651
+ "node_modules/negotiator": {
652
+ "version": "0.6.3",
653
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
654
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
655
+ "engines": {
656
+ "node": ">= 0.6"
657
+ }
658
+ },
659
+ "node_modules/node-cache": {
660
+ "version": "5.1.2",
661
+ "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz",
662
+ "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==",
663
+ "dependencies": {
664
+ "clone": "2.x"
665
+ },
666
+ "engines": {
667
+ "node": ">= 8.0.0"
668
+ }
669
+ },
670
+ "node_modules/node-domexception": {
671
+ "version": "1.0.0",
672
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
673
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
674
+ "funding": [
675
+ {
676
+ "type": "github",
677
+ "url": "https://github.com/sponsors/jimmywarting"
678
+ },
679
+ {
680
+ "type": "github",
681
+ "url": "https://paypal.me/jimmywarting"
682
+ }
683
+ ],
684
+ "engines": {
685
+ "node": ">=10.5.0"
686
+ }
687
+ },
688
+ "node_modules/node-fetch": {
689
+ "version": "3.3.2",
690
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
691
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
692
+ "dependencies": {
693
+ "data-uri-to-buffer": "^4.0.0",
694
+ "fetch-blob": "^3.1.4",
695
+ "formdata-polyfill": "^4.0.10"
696
+ },
697
+ "engines": {
698
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
699
+ },
700
+ "funding": {
701
+ "type": "opencollective",
702
+ "url": "https://opencollective.com/node-fetch"
703
+ }
704
+ },
705
+ "node_modules/object-inspect": {
706
+ "version": "1.12.2",
707
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
708
+ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
709
+ "funding": {
710
+ "url": "https://github.com/sponsors/ljharb"
711
+ }
712
+ },
713
+ "node_modules/on-finished": {
714
+ "version": "2.4.1",
715
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
716
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
717
+ "dependencies": {
718
+ "ee-first": "1.1.1"
719
+ },
720
+ "engines": {
721
+ "node": ">= 0.8"
722
+ }
723
+ },
724
+ "node_modules/parseurl": {
725
+ "version": "1.3.3",
726
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
727
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
728
+ "engines": {
729
+ "node": ">= 0.8"
730
+ }
731
+ },
732
+ "node_modules/path-to-regexp": {
733
+ "version": "0.1.7",
734
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
735
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
736
+ },
737
+ "node_modules/proxy-addr": {
738
+ "version": "2.0.7",
739
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
740
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
741
+ "dependencies": {
742
+ "forwarded": "0.2.0",
743
+ "ipaddr.js": "1.9.1"
744
+ },
745
+ "engines": {
746
+ "node": ">= 0.10"
747
+ }
748
+ },
749
+ "node_modules/qs": {
750
+ "version": "6.10.3",
751
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
752
+ "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
753
+ "dependencies": {
754
+ "side-channel": "^1.0.4"
755
+ },
756
+ "engines": {
757
+ "node": ">=0.6"
758
+ },
759
+ "funding": {
760
+ "url": "https://github.com/sponsors/ljharb"
761
+ }
762
+ },
763
+ "node_modules/range-parser": {
764
+ "version": "1.2.1",
765
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
766
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
767
+ "engines": {
768
+ "node": ">= 0.6"
769
+ }
770
+ },
771
+ "node_modules/raw-body": {
772
+ "version": "2.5.1",
773
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
774
+ "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
775
+ "dependencies": {
776
+ "bytes": "3.1.2",
777
+ "http-errors": "2.0.0",
778
+ "iconv-lite": "0.4.24",
779
+ "unpipe": "1.0.0"
780
+ },
781
+ "engines": {
782
+ "node": ">= 0.8"
783
+ }
784
+ },
785
+ "node_modules/safe-buffer": {
786
+ "version": "5.2.1",
787
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
788
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
789
+ "funding": [
790
+ {
791
+ "type": "github",
792
+ "url": "https://github.com/sponsors/feross"
793
+ },
794
+ {
795
+ "type": "patreon",
796
+ "url": "https://www.patreon.com/feross"
797
+ },
798
+ {
799
+ "type": "consulting",
800
+ "url": "https://feross.org/support"
801
+ }
802
+ ]
803
+ },
804
+ "node_modules/safer-buffer": {
805
+ "version": "2.1.2",
806
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
807
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
808
+ },
809
+ "node_modules/send": {
810
+ "version": "0.18.0",
811
+ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
812
+ "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
813
+ "dependencies": {
814
+ "debug": "2.6.9",
815
+ "depd": "2.0.0",
816
+ "destroy": "1.2.0",
817
+ "encodeurl": "~1.0.2",
818
+ "escape-html": "~1.0.3",
819
+ "etag": "~1.8.1",
820
+ "fresh": "0.5.2",
821
+ "http-errors": "2.0.0",
822
+ "mime": "1.6.0",
823
+ "ms": "2.1.3",
824
+ "on-finished": "2.4.1",
825
+ "range-parser": "~1.2.1",
826
+ "statuses": "2.0.1"
827
+ },
828
+ "engines": {
829
+ "node": ">= 0.8.0"
830
+ }
831
+ },
832
+ "node_modules/send/node_modules/ms": {
833
+ "version": "2.1.3",
834
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
835
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
836
+ },
837
+ "node_modules/serve-static": {
838
+ "version": "1.15.0",
839
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
840
+ "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
841
+ "dependencies": {
842
+ "encodeurl": "~1.0.2",
843
+ "escape-html": "~1.0.3",
844
+ "parseurl": "~1.3.3",
845
+ "send": "0.18.0"
846
+ },
847
+ "engines": {
848
+ "node": ">= 0.8.0"
849
+ }
850
+ },
851
+ "node_modules/setprototypeof": {
852
+ "version": "1.2.0",
853
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
854
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
855
+ },
856
+ "node_modules/side-channel": {
857
+ "version": "1.0.4",
858
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
859
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
860
+ "dependencies": {
861
+ "call-bind": "^1.0.0",
862
+ "get-intrinsic": "^1.0.2",
863
+ "object-inspect": "^1.9.0"
864
+ },
865
+ "funding": {
866
+ "url": "https://github.com/sponsors/ljharb"
867
+ }
868
+ },
869
+ "node_modules/statuses": {
870
+ "version": "2.0.1",
871
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
872
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
873
+ "engines": {
874
+ "node": ">= 0.8"
875
+ }
876
+ },
877
+ "node_modules/supports-color": {
878
+ "version": "7.2.0",
879
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
880
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
881
+ "dependencies": {
882
+ "has-flag": "^4.0.0"
883
+ },
884
+ "engines": {
885
+ "node": ">=8"
886
+ }
887
+ },
888
+ "node_modules/toidentifier": {
889
+ "version": "1.0.1",
890
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
891
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
892
+ "engines": {
893
+ "node": ">=0.6"
894
+ }
895
+ },
896
+ "node_modules/type-is": {
897
+ "version": "1.6.18",
898
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
899
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
900
+ "dependencies": {
901
+ "media-typer": "0.3.0",
902
+ "mime-types": "~2.1.24"
903
+ },
904
+ "engines": {
905
+ "node": ">= 0.6"
906
+ }
907
+ },
908
+ "node_modules/unpipe": {
909
+ "version": "1.0.0",
910
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
911
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
912
+ "engines": {
913
+ "node": ">= 0.8"
914
+ }
915
+ },
916
+ "node_modules/utils-merge": {
917
+ "version": "1.0.1",
918
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
919
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
920
+ "engines": {
921
+ "node": ">= 0.4.0"
922
+ }
923
+ },
924
+ "node_modules/vary": {
925
+ "version": "1.1.2",
926
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
927
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
928
+ "engines": {
929
+ "node": ">= 0.8"
930
+ }
931
+ },
932
+ "node_modules/web-streams-polyfill": {
933
+ "version": "3.3.3",
934
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
935
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
936
+ "engines": {
937
+ "node": ">= 8"
938
+ }
939
+ }
940
+ },
941
+ "dependencies": {
942
+ "accepts": {
943
+ "version": "1.3.8",
944
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
945
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
946
+ "requires": {
947
+ "mime-types": "~2.1.34",
948
+ "negotiator": "0.6.3"
949
+ }
950
+ },
951
+ "ansi-styles": {
952
+ "version": "4.3.0",
953
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
954
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
955
+ "requires": {
956
+ "color-convert": "^2.0.1"
957
+ }
958
+ },
959
+ "array-flatten": {
960
+ "version": "1.1.1",
961
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
962
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
963
+ },
964
+ "async": {
965
+ "version": "3.2.4",
966
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
967
+ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
968
+ },
969
+ "asynckit": {
970
+ "version": "0.4.0",
971
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
972
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
973
+ },
974
+ "axios": {
975
+ "version": "0.27.2",
976
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
977
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
978
+ "requires": {
979
+ "follow-redirects": "^1.14.9",
980
+ "form-data": "^4.0.0"
981
+ }
982
+ },
983
+ "balanced-match": {
984
+ "version": "1.0.2",
985
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
986
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
987
+ },
988
+ "body-parser": {
989
+ "version": "1.20.0",
990
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
991
+ "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
992
+ "requires": {
993
+ "bytes": "3.1.2",
994
+ "content-type": "~1.0.4",
995
+ "debug": "2.6.9",
996
+ "depd": "2.0.0",
997
+ "destroy": "1.2.0",
998
+ "http-errors": "2.0.0",
999
+ "iconv-lite": "0.4.24",
1000
+ "on-finished": "2.4.1",
1001
+ "qs": "6.10.3",
1002
+ "raw-body": "2.5.1",
1003
+ "type-is": "~1.6.18",
1004
+ "unpipe": "1.0.0"
1005
+ }
1006
+ },
1007
+ "brace-expansion": {
1008
+ "version": "1.1.11",
1009
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1010
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1011
+ "requires": {
1012
+ "balanced-match": "^1.0.0",
1013
+ "concat-map": "0.0.1"
1014
+ }
1015
+ },
1016
+ "bytes": {
1017
+ "version": "3.1.2",
1018
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
1019
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
1020
+ },
1021
+ "call-bind": {
1022
+ "version": "1.0.2",
1023
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
1024
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
1025
+ "requires": {
1026
+ "function-bind": "^1.1.1",
1027
+ "get-intrinsic": "^1.0.2"
1028
+ }
1029
+ },
1030
+ "chalk": {
1031
+ "version": "4.1.2",
1032
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1033
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1034
+ "requires": {
1035
+ "ansi-styles": "^4.1.0",
1036
+ "supports-color": "^7.1.0"
1037
+ }
1038
+ },
1039
+ "clone": {
1040
+ "version": "2.1.2",
1041
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
1042
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="
1043
+ },
1044
+ "color-convert": {
1045
+ "version": "2.0.1",
1046
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1047
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1048
+ "requires": {
1049
+ "color-name": "~1.1.4"
1050
+ }
1051
+ },
1052
+ "color-name": {
1053
+ "version": "1.1.4",
1054
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1055
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
1056
+ },
1057
+ "combined-stream": {
1058
+ "version": "1.0.8",
1059
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
1060
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
1061
+ "requires": {
1062
+ "delayed-stream": "~1.0.0"
1063
+ }
1064
+ },
1065
+ "concat-map": {
1066
+ "version": "0.0.1",
1067
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1068
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
1069
+ },
1070
+ "content-disposition": {
1071
+ "version": "0.5.4",
1072
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
1073
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
1074
+ "requires": {
1075
+ "safe-buffer": "5.2.1"
1076
+ }
1077
+ },
1078
+ "content-type": {
1079
+ "version": "1.0.4",
1080
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
1081
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
1082
+ },
1083
+ "cookie": {
1084
+ "version": "0.5.0",
1085
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
1086
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
1087
+ },
1088
+ "cookie-signature": {
1089
+ "version": "1.0.6",
1090
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
1091
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
1092
+ },
1093
+ "data-uri-to-buffer": {
1094
+ "version": "4.0.1",
1095
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
1096
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="
1097
+ },
1098
+ "debug": {
1099
+ "version": "2.6.9",
1100
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
1101
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
1102
+ "requires": {
1103
+ "ms": "2.0.0"
1104
+ }
1105
+ },
1106
+ "delayed-stream": {
1107
+ "version": "1.0.0",
1108
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
1109
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
1110
+ },
1111
+ "depd": {
1112
+ "version": "2.0.0",
1113
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
1114
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
1115
+ },
1116
+ "destroy": {
1117
+ "version": "1.2.0",
1118
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
1119
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
1120
+ },
1121
+ "ee-first": {
1122
+ "version": "1.1.1",
1123
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
1124
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
1125
+ },
1126
+ "ejs": {
1127
+ "version": "3.1.8",
1128
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz",
1129
+ "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==",
1130
+ "requires": {
1131
+ "jake": "^10.8.5"
1132
+ }
1133
+ },
1134
+ "encodeurl": {
1135
+ "version": "1.0.2",
1136
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
1137
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
1138
+ },
1139
+ "escape-html": {
1140
+ "version": "1.0.3",
1141
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
1142
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
1143
+ },
1144
+ "etag": {
1145
+ "version": "1.8.1",
1146
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
1147
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
1148
+ },
1149
+ "express": {
1150
+ "version": "4.18.1",
1151
+ "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
1152
+ "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
1153
+ "requires": {
1154
+ "accepts": "~1.3.8",
1155
+ "array-flatten": "1.1.1",
1156
+ "body-parser": "1.20.0",
1157
+ "content-disposition": "0.5.4",
1158
+ "content-type": "~1.0.4",
1159
+ "cookie": "0.5.0",
1160
+ "cookie-signature": "1.0.6",
1161
+ "debug": "2.6.9",
1162
+ "depd": "2.0.0",
1163
+ "encodeurl": "~1.0.2",
1164
+ "escape-html": "~1.0.3",
1165
+ "etag": "~1.8.1",
1166
+ "finalhandler": "1.2.0",
1167
+ "fresh": "0.5.2",
1168
+ "http-errors": "2.0.0",
1169
+ "merge-descriptors": "1.0.1",
1170
+ "methods": "~1.1.2",
1171
+ "on-finished": "2.4.1",
1172
+ "parseurl": "~1.3.3",
1173
+ "path-to-regexp": "0.1.7",
1174
+ "proxy-addr": "~2.0.7",
1175
+ "qs": "6.10.3",
1176
+ "range-parser": "~1.2.1",
1177
+ "safe-buffer": "5.2.1",
1178
+ "send": "0.18.0",
1179
+ "serve-static": "1.15.0",
1180
+ "setprototypeof": "1.2.0",
1181
+ "statuses": "2.0.1",
1182
+ "type-is": "~1.6.18",
1183
+ "utils-merge": "1.0.1",
1184
+ "vary": "~1.1.2"
1185
+ }
1186
+ },
1187
+ "fetch-blob": {
1188
+ "version": "3.2.0",
1189
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
1190
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
1191
+ "requires": {
1192
+ "node-domexception": "^1.0.0",
1193
+ "web-streams-polyfill": "^3.0.3"
1194
+ }
1195
+ },
1196
+ "filelist": {
1197
+ "version": "1.0.4",
1198
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
1199
+ "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
1200
+ "requires": {
1201
+ "minimatch": "^5.0.1"
1202
+ },
1203
+ "dependencies": {
1204
+ "brace-expansion": {
1205
+ "version": "2.0.1",
1206
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
1207
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
1208
+ "requires": {
1209
+ "balanced-match": "^1.0.0"
1210
+ }
1211
+ },
1212
+ "minimatch": {
1213
+ "version": "5.1.0",
1214
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
1215
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
1216
+ "requires": {
1217
+ "brace-expansion": "^2.0.1"
1218
+ }
1219
+ }
1220
+ }
1221
+ },
1222
+ "finalhandler": {
1223
+ "version": "1.2.0",
1224
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
1225
+ "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
1226
+ "requires": {
1227
+ "debug": "2.6.9",
1228
+ "encodeurl": "~1.0.2",
1229
+ "escape-html": "~1.0.3",
1230
+ "on-finished": "2.4.1",
1231
+ "parseurl": "~1.3.3",
1232
+ "statuses": "2.0.1",
1233
+ "unpipe": "~1.0.0"
1234
+ }
1235
+ },
1236
+ "follow-redirects": {
1237
+ "version": "1.15.2",
1238
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
1239
+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
1240
+ },
1241
+ "form-data": {
1242
+ "version": "4.0.0",
1243
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
1244
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
1245
+ "requires": {
1246
+ "asynckit": "^0.4.0",
1247
+ "combined-stream": "^1.0.8",
1248
+ "mime-types": "^2.1.12"
1249
+ }
1250
+ },
1251
+ "formdata-polyfill": {
1252
+ "version": "4.0.10",
1253
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
1254
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
1255
+ "requires": {
1256
+ "fetch-blob": "^3.1.2"
1257
+ }
1258
+ },
1259
+ "forwarded": {
1260
+ "version": "0.2.0",
1261
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
1262
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
1263
+ },
1264
+ "fresh": {
1265
+ "version": "0.5.2",
1266
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
1267
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
1268
+ },
1269
+ "function-bind": {
1270
+ "version": "1.1.1",
1271
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
1272
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
1273
+ },
1274
+ "get-intrinsic": {
1275
+ "version": "1.1.3",
1276
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
1277
+ "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
1278
+ "requires": {
1279
+ "function-bind": "^1.1.1",
1280
+ "has": "^1.0.3",
1281
+ "has-symbols": "^1.0.3"
1282
+ }
1283
+ },
1284
+ "has": {
1285
+ "version": "1.0.3",
1286
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
1287
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
1288
+ "requires": {
1289
+ "function-bind": "^1.1.1"
1290
+ }
1291
+ },
1292
+ "has-flag": {
1293
+ "version": "4.0.0",
1294
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1295
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
1296
+ },
1297
+ "has-symbols": {
1298
+ "version": "1.0.3",
1299
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
1300
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
1301
+ },
1302
+ "http-errors": {
1303
+ "version": "2.0.0",
1304
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
1305
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
1306
+ "requires": {
1307
+ "depd": "2.0.0",
1308
+ "inherits": "2.0.4",
1309
+ "setprototypeof": "1.2.0",
1310
+ "statuses": "2.0.1",
1311
+ "toidentifier": "1.0.1"
1312
+ }
1313
+ },
1314
+ "iconv-lite": {
1315
+ "version": "0.4.24",
1316
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
1317
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
1318
+ "requires": {
1319
+ "safer-buffer": ">= 2.1.2 < 3"
1320
+ }
1321
+ },
1322
+ "inherits": {
1323
+ "version": "2.0.4",
1324
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1325
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
1326
+ },
1327
+ "ipaddr.js": {
1328
+ "version": "1.9.1",
1329
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
1330
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
1331
+ },
1332
+ "jake": {
1333
+ "version": "10.8.5",
1334
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
1335
+ "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
1336
+ "requires": {
1337
+ "async": "^3.2.3",
1338
+ "chalk": "^4.0.2",
1339
+ "filelist": "^1.0.1",
1340
+ "minimatch": "^3.0.4"
1341
+ }
1342
+ },
1343
+ "media-typer": {
1344
+ "version": "0.3.0",
1345
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
1346
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
1347
+ },
1348
+ "merge-descriptors": {
1349
+ "version": "1.0.1",
1350
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
1351
+ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
1352
+ },
1353
+ "methods": {
1354
+ "version": "1.1.2",
1355
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
1356
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
1357
+ },
1358
+ "mime": {
1359
+ "version": "1.6.0",
1360
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
1361
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
1362
+ },
1363
+ "mime-db": {
1364
+ "version": "1.52.0",
1365
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
1366
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
1367
+ },
1368
+ "mime-types": {
1369
+ "version": "2.1.35",
1370
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
1371
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
1372
+ "requires": {
1373
+ "mime-db": "1.52.0"
1374
+ }
1375
+ },
1376
+ "minimatch": {
1377
+ "version": "3.1.2",
1378
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1379
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1380
+ "requires": {
1381
+ "brace-expansion": "^1.1.7"
1382
+ }
1383
+ },
1384
+ "moment": {
1385
+ "version": "2.30.1",
1386
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
1387
+ "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="
1388
+ },
1389
+ "moment-timezone": {
1390
+ "version": "0.5.46",
1391
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz",
1392
+ "integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==",
1393
+ "requires": {
1394
+ "moment": "^2.29.4"
1395
+ }
1396
+ },
1397
+ "ms": {
1398
+ "version": "2.0.0",
1399
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1400
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
1401
+ },
1402
+ "negotiator": {
1403
+ "version": "0.6.3",
1404
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
1405
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
1406
+ },
1407
+ "node-cache": {
1408
+ "version": "5.1.2",
1409
+ "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz",
1410
+ "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==",
1411
+ "requires": {
1412
+ "clone": "2.x"
1413
+ }
1414
+ },
1415
+ "node-domexception": {
1416
+ "version": "1.0.0",
1417
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
1418
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="
1419
+ },
1420
+ "node-fetch": {
1421
+ "version": "3.3.2",
1422
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
1423
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
1424
+ "requires": {
1425
+ "data-uri-to-buffer": "^4.0.0",
1426
+ "fetch-blob": "^3.1.4",
1427
+ "formdata-polyfill": "^4.0.10"
1428
+ }
1429
+ },
1430
+ "object-inspect": {
1431
+ "version": "1.12.2",
1432
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
1433
+ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ=="
1434
+ },
1435
+ "on-finished": {
1436
+ "version": "2.4.1",
1437
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
1438
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
1439
+ "requires": {
1440
+ "ee-first": "1.1.1"
1441
+ }
1442
+ },
1443
+ "parseurl": {
1444
+ "version": "1.3.3",
1445
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
1446
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
1447
+ },
1448
+ "path-to-regexp": {
1449
+ "version": "0.1.7",
1450
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
1451
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
1452
+ },
1453
+ "proxy-addr": {
1454
+ "version": "2.0.7",
1455
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
1456
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
1457
+ "requires": {
1458
+ "forwarded": "0.2.0",
1459
+ "ipaddr.js": "1.9.1"
1460
+ }
1461
+ },
1462
+ "qs": {
1463
+ "version": "6.10.3",
1464
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
1465
+ "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
1466
+ "requires": {
1467
+ "side-channel": "^1.0.4"
1468
+ }
1469
+ },
1470
+ "range-parser": {
1471
+ "version": "1.2.1",
1472
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
1473
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
1474
+ },
1475
+ "raw-body": {
1476
+ "version": "2.5.1",
1477
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
1478
+ "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
1479
+ "requires": {
1480
+ "bytes": "3.1.2",
1481
+ "http-errors": "2.0.0",
1482
+ "iconv-lite": "0.4.24",
1483
+ "unpipe": "1.0.0"
1484
+ }
1485
+ },
1486
+ "safe-buffer": {
1487
+ "version": "5.2.1",
1488
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1489
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
1490
+ },
1491
+ "safer-buffer": {
1492
+ "version": "2.1.2",
1493
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1494
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
1495
+ },
1496
+ "send": {
1497
+ "version": "0.18.0",
1498
+ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
1499
+ "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
1500
+ "requires": {
1501
+ "debug": "2.6.9",
1502
+ "depd": "2.0.0",
1503
+ "destroy": "1.2.0",
1504
+ "encodeurl": "~1.0.2",
1505
+ "escape-html": "~1.0.3",
1506
+ "etag": "~1.8.1",
1507
+ "fresh": "0.5.2",
1508
+ "http-errors": "2.0.0",
1509
+ "mime": "1.6.0",
1510
+ "ms": "2.1.3",
1511
+ "on-finished": "2.4.1",
1512
+ "range-parser": "~1.2.1",
1513
+ "statuses": "2.0.1"
1514
+ },
1515
+ "dependencies": {
1516
+ "ms": {
1517
+ "version": "2.1.3",
1518
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1519
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
1520
+ }
1521
+ }
1522
+ },
1523
+ "serve-static": {
1524
+ "version": "1.15.0",
1525
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
1526
+ "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
1527
+ "requires": {
1528
+ "encodeurl": "~1.0.2",
1529
+ "escape-html": "~1.0.3",
1530
+ "parseurl": "~1.3.3",
1531
+ "send": "0.18.0"
1532
+ }
1533
+ },
1534
+ "setprototypeof": {
1535
+ "version": "1.2.0",
1536
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
1537
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
1538
+ },
1539
+ "side-channel": {
1540
+ "version": "1.0.4",
1541
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
1542
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
1543
+ "requires": {
1544
+ "call-bind": "^1.0.0",
1545
+ "get-intrinsic": "^1.0.2",
1546
+ "object-inspect": "^1.9.0"
1547
+ }
1548
+ },
1549
+ "statuses": {
1550
+ "version": "2.0.1",
1551
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
1552
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
1553
+ },
1554
+ "supports-color": {
1555
+ "version": "7.2.0",
1556
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1557
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1558
+ "requires": {
1559
+ "has-flag": "^4.0.0"
1560
+ }
1561
+ },
1562
+ "toidentifier": {
1563
+ "version": "1.0.1",
1564
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
1565
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
1566
+ },
1567
+ "type-is": {
1568
+ "version": "1.6.18",
1569
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
1570
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
1571
+ "requires": {
1572
+ "media-typer": "0.3.0",
1573
+ "mime-types": "~2.1.24"
1574
+ }
1575
+ },
1576
+ "unpipe": {
1577
+ "version": "1.0.0",
1578
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1579
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
1580
+ },
1581
+ "utils-merge": {
1582
+ "version": "1.0.1",
1583
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
1584
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
1585
+ },
1586
+ "vary": {
1587
+ "version": "1.1.2",
1588
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1589
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
1590
+ },
1591
+ "web-streams-polyfill": {
1592
+ "version": "3.3.3",
1593
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
1594
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="
1595
+ }
1596
+ }
1597
+ }
app/package.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "your-iptv-1",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "start": "node index.js"
8
+ },
9
+ "keywords": [],
10
+ "author": "",
11
+ "license": "ISC",
12
+ "dependencies": {
13
+ "axios": "^0.27.2",
14
+ "ejs": "^3.1.8",
15
+ "express": "^4.18.1",
16
+ "moment-timezone": "^0.5.45",
17
+ "node-cache": "^5.1.2",
18
+ "node-fetch": "^3.3.2"
19
+ }
20
+ }
app/tvGuide.js ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const moment = require('moment-timezone');
3
+
4
+ function unixTimestampToSpecifiedTimezone(timestamp, timezone) {
5
+ // The timestamp is already in UTC, so we just need to format it for the specified timezone
6
+ return moment(timestamp, 'YYYYMMDDHHmmss ZZ').tz(timezone).format('ddd, DD MMM YYYY HH:mm:ss z');
7
+ }
8
+
9
+ async function fetchAndProcessXMLTV(baseUrl, username, password) {
10
+ const xmltvUrl = `${baseUrl}/xmltv.php?username=${username}&password=${password}`;
11
+ const response = await axios.get(xmltvUrl);
12
+ const xmlData = response.data;
13
+
14
+ function getElements(xml, tag) {
15
+ const regex = new RegExp(`<${tag}[^>]*>(.*?)<\/${tag}>`, 'gs');
16
+ return Array.from(xml.matchAll(regex)).map(match => match[0]);
17
+ }
18
+
19
+ function getAttribute(element, attr) {
20
+ const match = element.match(new RegExp(`${attr}="([^"]*)"`, 'i'));
21
+ return match ? match[1] : null;
22
+ }
23
+
24
+ function getTextContent(element) {
25
+ const match = element.match(/>([^<]*)</s);
26
+ return match ? match[1].trim() : '';
27
+ }
28
+
29
+ // Process channels
30
+ const channels = getElements(xmlData, 'channel')
31
+ .map(channel => ({
32
+ id: getAttribute(channel, 'id'),
33
+ name: getTextContent(getElements(channel, 'display-name')[0] || ''),
34
+ icon: getAttribute(getElements(channel, 'icon')[0] || '', 'src') || ''
35
+ }))
36
+ .sort((a, b) => a.name.localeCompare(b.name));
37
+
38
+ // Process programmes
39
+ const programmes = getElements(xmlData, 'programme')
40
+ .map(programme => ({
41
+ channelId: getAttribute(programme, 'channel'),
42
+ start: getAttribute(programme, 'start'),
43
+ stop: getAttribute(programme, 'stop'),
44
+ title: getTextContent(getElements(programme, 'title')[0] || ''),
45
+ description: getTextContent(getElements(programme, 'desc')[0] || '')
46
+ }))
47
+ .sort((a, b) => a.start.localeCompare(b.start));
48
+
49
+ return { channels, programmes };
50
+ }
51
+
52
+ function getCurrentAndNextProgram(programmes, timezone) {
53
+ const now = moment().tz(timezone);
54
+
55
+ let currentProgram = null;
56
+ let nextProgram = null;
57
+
58
+ for (let i = 0; i < programmes.length; i++) {
59
+ const programStart = moment(programmes[i].start, 'YYYYMMDDHHmmss ZZ');
60
+ const programStop = moment(programmes[i].stop, 'YYYYMMDDHHmmss ZZ');
61
+
62
+ if (programStart.isSameOrBefore(now) && programStop.isAfter(now)) {
63
+ currentProgram = programmes[i];
64
+ nextProgram = programmes[i + 1] || null;
65
+ break;
66
+ }
67
+ if (programStart.isAfter(now)) {
68
+ nextProgram = programmes[i];
69
+ break;
70
+ }
71
+ }
72
+
73
+ return {
74
+ currentProgram: currentProgram ? {
75
+ ...currentProgram,
76
+ start: unixTimestampToSpecifiedTimezone(currentProgram.start, timezone),
77
+ stop: unixTimestampToSpecifiedTimezone(currentProgram.stop, timezone)
78
+ } : null,
79
+ nextProgram: nextProgram ? {
80
+ ...nextProgram,
81
+ start: unixTimestampToSpecifiedTimezone(nextProgram.start, timezone),
82
+ stop: unixTimestampToSpecifiedTimezone(nextProgram.stop, timezone)
83
+ } : null
84
+ };
85
+ }
86
+
87
+ async function handleChannelRequest(epgChannelId, baseUrl, username, password, timezone) {
88
+ try {
89
+ const { channels, programmes } = await fetchAndProcessXMLTV(baseUrl, username, password);
90
+
91
+ const channelInfo = channels.find(channel => channel.id === epgChannelId);
92
+ if (!channelInfo) {
93
+ return null;
94
+ }
95
+
96
+ const channelProgrammes = programmes.filter(programme => programme.channelId === epgChannelId);
97
+
98
+ const { currentProgram, nextProgram } = getCurrentAndNextProgram(channelProgrammes, timezone);
99
+
100
+ return {
101
+ channel: channelInfo,
102
+ currentProgram: currentProgram,
103
+ nextProgram: nextProgram
104
+ };
105
+ } catch (error) {
106
+ console.error("Error in handleChannelRequest:", error);
107
+ return null;
108
+ }
109
+ }
110
+
111
+ async function handleMultiChannelRequest(channelIdsString, baseUrl, username, password, timezone) {
112
+ try {
113
+ const { channels, programmes } = await fetchAndProcessXMLTV(baseUrl, username, password);
114
+
115
+ const channelIds = channelIdsString.split(',');
116
+ const uniqueChannelIds = [...new Set(channelIds)]; // Remove duplicates
117
+
118
+ const responseData = uniqueChannelIds.map(channelId => {
119
+ const channelInfo = channels.find(channel => channel.id === channelId);
120
+ if (!channelInfo) {
121
+ return { channelId, error: 'Channel not found' };
122
+ }
123
+
124
+ const channelProgrammes = programmes.filter(programme => programme.channelId === channelId);
125
+ const { currentProgram, nextProgram } = getCurrentAndNextProgram(channelProgrammes, timezone);
126
+
127
+ return {
128
+ channel: channelInfo,
129
+ currentProgram: currentProgram,
130
+ nextProgram: nextProgram
131
+ };
132
+ });
133
+
134
+ return responseData;
135
+ } catch (error) {
136
+ console.error("Error in handleMultiChannelRequest:", error);
137
+ throw new Error('Error processing XMLTV data: ' + error.message);
138
+ }
139
+ }
140
+
141
+ async function handleChannelsListRequest(baseUrl, username, password) {
142
+ try {
143
+ const { channels } = await fetchAndProcessXMLTV(baseUrl, username, password);
144
+ return channels;
145
+ } catch (error) {
146
+ console.error("Error in handleChannelsListRequest:", error);
147
+ throw new Error('Error fetching channels list: ' + error.message);
148
+ }
149
+ }
150
+
151
+ async function getEpgInfoBatch(channelIds, baseUrl, username, password, timezone) {
152
+ try {
153
+ const { channels, programmes } = await fetchAndProcessXMLTV(baseUrl, username, password);
154
+
155
+ const results = {};
156
+ for (const channel of channelIds) {
157
+ if (!channel.epg_channel_id) {
158
+ continue;
159
+ }
160
+
161
+ const channelInfo = channels.find(c => c.id === channel.epg_channel_id);
162
+ if (!channelInfo) {
163
+ continue;
164
+ }
165
+
166
+ const channelProgrammes = programmes.filter(programme => programme.channelId === channel.epg_channel_id);
167
+ const { currentProgram, nextProgram } = getCurrentAndNextProgram(channelProgrammes, timezone);
168
+
169
+ results[channel.stream_id] = {
170
+ channel: channelInfo,
171
+ currentProgram: currentProgram,
172
+ nextProgram: nextProgram
173
+ };
174
+ }
175
+
176
+ return results;
177
+ } catch (error) {
178
+ console.error("Error in getEpgInfoBatch:", error);
179
+ throw new Error('Error processing XMLTV data: ' + error.message);
180
+ }
181
+ }
182
+
183
+ module.exports = {
184
+ handleChannelRequest,
185
+ handleChannelsListRequest,
186
+ handleMultiChannelRequest,
187
+ getEpgInfoBatch
188
+ };
app/views/configure.html ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Your IPTV - Stremio Addon</title>
6
+ <link rel="shortcut icon" href="./assets/logo.png" type="image/x-icon">
7
+ <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,700&display=swap" rel="stylesheet">
8
+ <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
9
+ <style>
10
+ * {
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body,
15
+ html {
16
+ margin: 0;
17
+ padding: 0;
18
+ height: 100%;
19
+ font-family: 'Open Sans', Arial, sans-serif;
20
+ color: white;
21
+ background-image: url('./assets/background.jpg');
22
+ background-size: cover;
23
+ background-position: center center;
24
+ background-repeat: no-repeat;
25
+ }
26
+
27
+ #logo {
28
+ position: absolute;
29
+ top: 20px;
30
+ right: 20px;
31
+ width: 50px; /* Adjust logo size */
32
+ height: auto;
33
+ z-index: 10;
34
+ opacity: 0.8;
35
+ }
36
+
37
+ #addon {
38
+ width: 90vh;
39
+ margin: auto;
40
+ padding: 5% 10%;
41
+ background: rgba(0, 0, 0, 0.7); /* Adjust opacity to see more background */
42
+ border-radius: 10px;
43
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
44
+ min-height: 80vh; /* Set a minimum height */
45
+ }
46
+
47
+ h1 {
48
+ font-size: 4.5vh;
49
+ font-weight: 700;
50
+ }
51
+
52
+ h2 {
53
+ font-size: 2.2vh;
54
+ font-weight: normal;
55
+ font-style: italic;
56
+ opacity: 0.8;
57
+ }
58
+
59
+ h3 {
60
+ font-size: 2.2vh;
61
+ }
62
+
63
+ h1,
64
+ h2,
65
+ h3,
66
+ p,
67
+ label {
68
+ margin: 0;
69
+ text-shadow: 0 0 1vh rgba(0, 0, 0, 0.15);
70
+ }
71
+
72
+ p {
73
+ font-size: 1.60vh;
74
+ }
75
+
76
+ ul {
77
+ font-size: 1.75vh;
78
+ margin: 0;
79
+ margin-top: 1vh;
80
+ padding-left: 3vh;
81
+ }
82
+
83
+ a {
84
+ color: lightblue;
85
+ }
86
+
87
+ a.install-link {
88
+ text-decoration: none;
89
+ }
90
+
91
+ button {
92
+ border: 0;
93
+ outline: 0;
94
+ color: white;
95
+ background: #8A5AAB;
96
+ padding: 1.2vh 3.5vh;
97
+ margin: auto;
98
+ text-align: center;
99
+ font-family: 'Open Sans', Arial, sans-serif;
100
+ font-size: 2.2vh;
101
+ font-weight: 600;
102
+ cursor: pointer;
103
+ display: block;
104
+ box-shadow: 0 0.5vh 1vh rgba(0, 0, 0, 0.2);
105
+ transition: box-shadow 0.1s ease-in-out;
106
+ }
107
+
108
+ button:hover {
109
+ box-shadow: none;
110
+ }
111
+
112
+ button:active {
113
+ box-shadow: 0 0 0 0.5vh white inset;
114
+ }
115
+
116
+ .separator {
117
+ margin-bottom: 4vh;
118
+ }
119
+
120
+ .label {
121
+ font-size: 2.2vh;
122
+ font-weight: 600;
123
+ padding: 0;
124
+ line-height: inherit;
125
+ }
126
+
127
+ .input {
128
+ height: 4.5vh;
129
+ width: 100%;
130
+ margin: auto;
131
+ margin-bottom: 10px;
132
+ padding: 6px 12px;
133
+ border-radius: 0;
134
+ outline: 0;
135
+ color: #333;
136
+ background-color: rgb(255, 255, 255);
137
+ box-shadow: 0 0.5vh 1vh rgba(0, 0, 0, 0.2);
138
+ border: 0.5vh solid #8a5aab;
139
+ }
140
+ </style>
141
+ </head>
142
+
143
+ <body>
144
+ <img src="./assets/logo.png" id="logo" alt="Logo"> <!-- Local logo -->
145
+
146
+ <div id="addon">
147
+ <h1 class="name">HY EPG IPTV</h1>
148
+ <h2 class="version">2.0.5</h2>
149
+ <h2 class="description">This addon brings all the Live Streams, VOD streams and Series from your IPTV subscription to your Stremio using Xtream API and supports IMDb IDs.</h2>
150
+ <div class="separator"></div>
151
+
152
+ <h3 class="gives">This addon has more:</h3>
153
+ <ul>
154
+ <li>Movies</li>
155
+ <li>Series</li>
156
+ <li>TV</li>
157
+ </ul>
158
+
159
+ <div class="separator"></div>
160
+
161
+ <p>ℹ️ You will need an IPTV subscription to use this addon. Free M3U lists are not supported❗<br></p>
162
+
163
+ <div class="separator"></div>
164
+
165
+ <label class="label" for="dnsport">DNS:PORT</label>
166
+ <input type="text" id="dnsport" class="input" placeholder="http://url_here.com:port">
167
+
168
+ <label class="label" for="username">Username:</label>
169
+ <input type="text" id="username" class="input" placeholder="Your Username">
170
+
171
+ <label class="label" for="password">Password:</label>
172
+ <input type="password" id="password" class="input" placeholder="Your Password">
173
+
174
+ <label class="label" for="timezone">Time Zone:</label>
175
+ <select id="timezone" class="input">
176
+ <option value="UTC">UTC</option>
177
+ <option value="America/New_York">Eastern Time (ET)</option>
178
+ <option value="America/Chicago">Central Time (CT)</option>
179
+ <option value="America/Denver">Mountain Time (MT)</option>
180
+ <option value="America/Los_Angeles">Pacific Time (PT)</option>
181
+ <option value="Europe/London">London</option>
182
+ <option value="Europe/Paris">Paris</option>
183
+ <option value="Asia/Tokyo">Tokyo</option>
184
+ </select>
185
+
186
+ <div class="separator"></div>
187
+
188
+ <a id="installLink" class="install-link" href="#">
189
+ <button onclick="generateInstallLink()" name="Install">INSTALL</button>
190
+ </a>
191
+
192
+ <div class="separator"></div>
193
+
194
+ <div id="installLinkInfo">
195
+ <p>ℹ️ If the installation button doesn't work, you can just paste the generated URL into the Stremio addon search bar:</p>
196
+ <input type="text" class="input" id="installURL" readonly>
197
+ <button onclick="generateInstallLink(); copy('installURL'); return false;" title="Copy to clipboard">📋</button>
198
+ </div>
199
+
200
+ <div class="separator"></div>
201
+ </div>
202
+
203
+ <script type="text/javascript">
204
+ function encode(userData) {
205
+ return btoa(JSON.stringify(userData)).replace(/\+/g, '-').replace(/\//g, '_').split('=')[0];
206
+ }
207
+
208
+ function copy(id) {
209
+ document.getElementById(id).select();
210
+ document.execCommand("copy");
211
+ }
212
+
213
+ function generateInstallLink() {
214
+ var BaseURL = $('#dnsport').val().trim() || null;
215
+ var username = $('#username').val().trim() || null;
216
+ var password = $('#password').val().trim() || null;
217
+ var timezone = $('#timezone').val().trim() || 'UTC';
218
+
219
+ var params = { username, password, BaseURL, timezone };
220
+ var isParametersValid = true;
221
+
222
+ if (params.BaseURL && !params.BaseURL.includes("http") && params.BaseURL.length > 0) {
223
+ isParametersValid = false;
224
+ alert("Please indicate http or https status!");
225
+ }
226
+
227
+ if (!params.username) {
228
+ isParametersValid = false;
229
+ alert("Username is missing!");
230
+ }
231
+
232
+ if (!params.password) {
233
+ isParametersValid = false;
234
+ alert("Password is missing!");
235
+ }
236
+
237
+ if (params.username && params.password && params.BaseURL && isParametersValid) {
238
+ var configuration = encode(params);
239
+ var installLink = document.getElementById('installLink');
240
+ installLink.href = 'stremio://' + window.location.host + '/' + configuration + '/manifest.json';
241
+ document.getElementById("installURL").value = window.location.protocol + "//" + window.location.host + "/" + configuration + "/manifest.json";
242
+ }
243
+ }
244
+ </script>
245
+ </body>
246
+ </html>
app/xtream-module.js ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+
3
+ function createXtreamModule(xtreamBaseUrl, username, password) {
4
+ const xtreamApiUrl = `${xtreamBaseUrl}/player_api.php`;
5
+
6
+ async function getDetailsFromCinemeta(ttnumber, type = 'movie') {
7
+ const url = `https://v3-cinemeta.strem.io/meta/${type}/${ttnumber}.json`;
8
+ try {
9
+ const response = await axios.get(url);
10
+ const { name: title, season, episode } = response.data.meta;
11
+ return { title, season, episode };
12
+ } catch (error) {
13
+ console.error('Error fetching data from Cinemeta:', error);
14
+ throw error;
15
+ }
16
+ }
17
+
18
+ async function getVodStreams() {
19
+ const params = { username, password, action: 'get_vod_streams' };
20
+ try {
21
+ const response = await axios.get(xtreamApiUrl, { params });
22
+ return response.data;
23
+ } catch (error) {
24
+ console.error('Error fetching VOD streams from Xtream Codes:', error);
25
+ throw error;
26
+ }
27
+ }
28
+
29
+ async function getSeries() {
30
+ const params = { username, password, action: 'get_series' };
31
+ try {
32
+ const response = await axios.get(xtreamApiUrl, { params });
33
+ return response.data;
34
+ } catch (error) {
35
+ console.error('Error fetching series from Xtream Codes:', error);
36
+ throw error;
37
+ }
38
+ }
39
+
40
+ async function getSeriesInfo(seriesId) {
41
+ const params = { username, password, action: 'get_series_info', series_id: seriesId };
42
+ try {
43
+ const response = await axios.get(xtreamApiUrl, { params });
44
+ return response.data;
45
+ } catch (error) {
46
+ console.error('Error fetching series info from Xtream Codes:', error);
47
+ throw error;
48
+ }
49
+ }
50
+
51
+ function normalizeTitle(title) {
52
+ // Remove the year and any surrounding parentheses or brackets
53
+ let normalized = title.replace(/\s*\([^)]*\)|\s*\[[^\]]*\]|\s*\d{4}$/g, '');
54
+ // Convert to lowercase and remove all non-alphanumeric characters
55
+ normalized = normalized.toLowerCase().replace(/[^a-z0-9]/g, '');
56
+ return normalized;
57
+ }
58
+
59
+ function findMatchingContent(contentList, title) {
60
+ const normalizedTitle = normalizeTitle(title);
61
+ console.log(`Searching for normalized title: ${normalizedTitle}`);
62
+
63
+ return contentList.find(item => {
64
+ const itemNormalizedTitle = normalizeTitle(item.name);
65
+ console.log(`Comparing with: ${itemNormalizedTitle}`);
66
+ return itemNormalizedTitle === normalizedTitle;
67
+ });
68
+ }
69
+
70
+ function findBestMatchingContent(contentList, title) {
71
+ const normalizedTitle = normalizeTitle(title);
72
+ console.log(`Searching for best match for normalized title: ${normalizedTitle}`);
73
+
74
+ let bestMatch = null;
75
+ let highestSimilarity = 0;
76
+
77
+ contentList.forEach(item => {
78
+ const itemNormalizedTitle = normalizeTitle(item.name);
79
+ const similarity = calculateSimilarity(normalizedTitle, itemNormalizedTitle);
80
+ console.log(`Comparing with: ${itemNormalizedTitle}, Similarity: ${similarity}`);
81
+
82
+ if (similarity > highestSimilarity) {
83
+ highestSimilarity = similarity;
84
+ bestMatch = item;
85
+ }
86
+ });
87
+
88
+ console.log(`Best match found: ${bestMatch ? bestMatch.name : 'None'} with similarity: ${highestSimilarity}`);
89
+ return highestSimilarity > 0.8 ? bestMatch : null; // Adjust threshold as needed
90
+ }
91
+
92
+ function calculateSimilarity(str1, str2) {
93
+ const len = Math.max(str1.length, str2.length);
94
+ const editDistance = levenshteinDistance(str1, str2);
95
+ return 1 - editDistance / len;
96
+ }
97
+
98
+ function levenshteinDistance(str1, str2) {
99
+ const m = str1.length;
100
+ const n = str2.length;
101
+ const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(null));
102
+
103
+ for (let i = 0; i <= m; i++) {
104
+ dp[i][0] = i;
105
+ }
106
+ for (let j = 0; j <= n; j++) {
107
+ dp[0][j] = j;
108
+ }
109
+
110
+ for (let i = 1; i <= m; i++) {
111
+ for (let j = 1; j <= n; j++) {
112
+ if (str1[i - 1] === str2[j - 1]) {
113
+ dp[i][j] = dp[i - 1][j - 1];
114
+ } else {
115
+ dp[i][j] = Math.min(
116
+ dp[i - 1][j - 1] + 1,
117
+ dp[i][j - 1] + 1,
118
+ dp[i - 1][j] + 1
119
+ );
120
+ }
121
+ }
122
+ }
123
+
124
+ return dp[m][n];
125
+ }
126
+
127
+ function buildStreamUrl(content) {
128
+ let url;
129
+ if (content.stream_type) {
130
+ // For movies
131
+ url = `${xtreamBaseUrl}/${content.stream_type}/${username}/${password}/${content.stream_id}.${content.container_extension}`;
132
+ } else if (content.id) {
133
+ // For series episodes
134
+ url = `${xtreamBaseUrl}/series/${username}/${password}/${content.id}.${content.container_extension}`;
135
+ }
136
+ console.log('Constructed stream URL:', url);
137
+ return url;
138
+ }
139
+
140
+ return async function(input) {
141
+ try {
142
+ const [ttNumber, season, episode] = input.split(':');
143
+
144
+ const type = ttNumber.startsWith('tt') ? (season && episode ? 'series' : 'movie') : 'series';
145
+
146
+ const { title } = await getDetailsFromCinemeta(ttNumber, type);
147
+ console.log(`Title from Cinemeta: ${title} (${type})`);
148
+
149
+ let contentList, matchingContent, contentInfo, specificEpisode;
150
+ if (type === 'movie') {
151
+ contentList = await getVodStreams();
152
+ matchingContent = findMatchingContent(contentList, title);
153
+ if (!matchingContent) {
154
+ console.log('Exact match not found, trying best match...');
155
+ matchingContent = findBestMatchingContent(contentList, title);
156
+ }
157
+ if (matchingContent) {
158
+ const contentUrl = buildStreamUrl(matchingContent);
159
+ return { title: matchingContent.name, contentUrl, type };
160
+ } else {
161
+ console.log(`No matching content found for movie: ${title}`);
162
+ return null;
163
+ }
164
+ } else {
165
+ contentList = await getSeries();
166
+ matchingContent = findMatchingContent(contentList, title);
167
+ if (!matchingContent) {
168
+ console.log('Exact match not found, trying best match...');
169
+ matchingContent = findBestMatchingContent(contentList, title);
170
+ }
171
+ if (matchingContent) {
172
+ contentInfo = await getSeriesInfo(matchingContent.series_id);
173
+ if (season && episode) {
174
+ specificEpisode = contentInfo.episodes[season]?.find(ep => ep.episode_num == episode);
175
+ if (specificEpisode) {
176
+ const episodeUrl = buildStreamUrl(specificEpisode);
177
+ return {
178
+ title: matchingContent.name,
179
+ type,
180
+ seriesId: matchingContent.series_id,
181
+ season,
182
+ episode,
183
+ episodeTitle: specificEpisode.title,
184
+ contentUrl: episodeUrl
185
+ };
186
+ } else {
187
+ console.log(`Episode not found: ${title} S${season}E${episode}`);
188
+ return null;
189
+ }
190
+ } else {
191
+ return {
192
+ title: matchingContent.name,
193
+ type,
194
+ seriesId: matchingContent.series_id,
195
+ seasons: contentInfo.seasons,
196
+ episodes: contentInfo.episodes
197
+ };
198
+ }
199
+ } else {
200
+ console.log(`No matching content found for series: ${title}`);
201
+ return null;
202
+ }
203
+ }
204
+ } catch (error) {
205
+ console.error('Error:', error.message);
206
+ throw error;
207
+ }
208
+ };
209
+ }
210
+
211
+ module.exports = { createXtreamModule };
assets/background.jpg ADDED
assets/logo.png ADDED
config.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var env = process.env.NODE_ENV ? 'beamup':'local';
2
+
3
+ var config = {
4
+ addon: 'started',
5
+ }
6
+
7
+ switch (env) {
8
+ //Public server build.
9
+ case 'beamup':
10
+ config.port = process.env.PORT
11
+ config.local = "5a0d1888fa64-your-iptv.baby-beamup.club"
12
+ break;
13
+
14
+ //Local sever build.
15
+ case 'local':
16
+ config.port = 3649
17
+ config.local = "http://127.0.0.1:" + config.port;
18
+ break;
19
+ }
20
+
21
+ module.exports = config;
en.jpeg ADDED
index.js ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const express = require("express");
2
+ const path = require("path"); // Import path module for path handling
3
+ const app = express();
4
+ const config = require('./config');
5
+ const MANIFEST = require('./manifest');
6
+ const { getManifest, getCatalog, getMeta, getUserData } = require("./addon");
7
+ const { createXtreamModule } = require("./xtream-module");
8
+
9
+ const NodeCache = require("node-cache");
10
+ const myCache = new NodeCache({ stdTTL: 200 });
11
+
12
+ // Middleware to allow CORS and set response headers
13
+ var respond = function (res, data) {
14
+ res.setHeader('Access-Control-Allow-Origin', '*');
15
+ res.setHeader('Access-Control-Allow-Headers', '*');
16
+ res.setHeader('Content-Type', 'application/json');
17
+ res.send(data);
18
+ };
19
+
20
+ // Serve static files from the 'assets' directory
21
+ app.use('/assets', express.static(path.join(__dirname, 'assets')));
22
+
23
+ app.engine('html', require('ejs').renderFile);
24
+ app.set('views', path.join(__dirname, 'views'));
25
+
26
+ app.get("/", function (req, res) {
27
+ res.redirect("/configure");
28
+ });
29
+
30
+ app.get("/:userConf?/configure", function (req, res) {
31
+ const newManifest = { ...{ MANIFEST } };
32
+ res.render('configure.html', newManifest);
33
+ });
34
+
35
+ app.get('/manifest.json', function (req, res) {
36
+ const newManifest = { ...MANIFEST };
37
+ newManifest.behaviorHints.configurationRequired = true;
38
+ respond(res, newManifest);
39
+ });
40
+
41
+ app.get('/:userConf/manifest.json', async function (req, res) {
42
+ let newManifest = { ...MANIFEST };
43
+ if (!((req || {}).params || {}).userConf) {
44
+ newManifest.behaviorHints.configurationRequired = true;
45
+ respond(res, newManifest);
46
+ } else {
47
+ try {
48
+ if (myCache.has(`manifest-${req.params.userConf}`)) {
49
+ respond(res, myCache.get(`manifest-${req.params.userConf}`));
50
+ } else {
51
+ newManifest = await getManifest(req.params.userConf);
52
+ if (newManifest && newManifest.id) {
53
+ myCache.set(`manifest-${req.params.userConf}`, newManifest);
54
+ }
55
+ respond(res, newManifest);
56
+ }
57
+ } catch (error) {
58
+ console.log(error);
59
+ respond(res, { error: error });
60
+ }
61
+ }
62
+ });
63
+
64
+ app.get('/:userConf/catalog/:type/:id/:extra?.json', async function (req, res) {
65
+ let { userConf, type, id, extra } = req.params;
66
+ let extraObj;
67
+
68
+ if (extra) {
69
+ try {
70
+ extraObj = JSON.parse('{"' + decodeURI(extra.replace(/&/g, '","').replace(/=/g, '":"')) + '"}');
71
+ } catch (error) {
72
+ console.log(error);
73
+ return respond(res, { metas: [] });
74
+ }
75
+ }
76
+
77
+ if (extraObj && extraObj.genre && extraObj.genre.includes("+")) {
78
+ extraObj.genre = extraObj.genre.replace(/\+/g, ' ');
79
+ }
80
+
81
+ let metas = [];
82
+ try {
83
+ if (myCache.has(`catalog-${userConf}-${type}-${id}-${extra}`)) {
84
+ respond(res, myCache.get(`catalog-${userConf}-${type}-${id}-${extra}`));
85
+ } else {
86
+ metas = await getCatalog(userConf, type, extraObj.genre);
87
+ if (metas.length > 0) {
88
+ myCache.set(`catalog-${userConf}-${type}-${id}-${extra}`, { metas: metas });
89
+ }
90
+ respond(res, { metas: metas });
91
+ }
92
+ } catch (error) {
93
+ console.log(error);
94
+ respond(res, { metas: [] });
95
+ }
96
+ });
97
+
98
+ app.get('/:userConf/meta/:type/:id.json', async function (req, res) {
99
+ let { userConf, type, id } = req.params;
100
+
101
+ try {
102
+ if (myCache.has(`meta-${userConf}-${type}-${id}`)) {
103
+ respond(res, myCache.get(`meta-${userConf}-${type}-${id}`));
104
+ } else {
105
+ const meta = await getMeta(userConf, type, id);
106
+ if (meta && meta.id) {
107
+ myCache.set(`meta-${userConf}-${type}-${id}`, { meta: meta });
108
+ }
109
+ respond(res, { meta: meta });
110
+ }
111
+ } catch (error) {
112
+ console.log(error);
113
+ respond(res, { error });
114
+ }
115
+ });
116
+
117
+ app.get('/:userConf/stream/:type/:id.json', async function (req, res) {
118
+ let { userConf, type, id } = req.params;
119
+ const obj = getUserData(userConf);
120
+
121
+ if (id.startsWith('tt')) {
122
+ // Handle IMDb IDs using the Xtream module
123
+ const xtreamModule = createXtreamModule(obj.baseURL, obj.username, obj.password);
124
+
125
+ try {
126
+ const xtreamResponse = await xtreamModule(id);
127
+ if (xtreamResponse && xtreamResponse.contentUrl) {
128
+ console.log('Stream URL for IMDb ID:', xtreamResponse.contentUrl);
129
+ respond(res, { streams: [{ url: xtreamResponse.contentUrl, name: xtreamResponse.title }] });
130
+ } else {
131
+ console.log('No stream found for IMDb ID:', id);
132
+ respond(res, { streams: [] });
133
+ }
134
+ } catch (error) {
135
+ console.error('Xtream module error:', error);
136
+ respond(res, { streams: [] });
137
+ }
138
+ } else {
139
+ // Existing logic for non-IMDb IDs
140
+ let extension = "mp4";
141
+ const streamID = id.split(":")[1];
142
+ let stream = [];
143
+ if (type === "tv") {
144
+ type = "live";
145
+ extension = "ts";
146
+ const url = `${obj.baseURL}/${type}/${obj.username}/${obj.password}/${streamID}.${extension}`;
147
+ console.log('Stream URL for TV:', url);
148
+ stream = [{
149
+ url: url,
150
+ name: "Watch Now",
151
+ behaviorHints: {
152
+ notWebReady: true
153
+ }
154
+ }];
155
+ } else {
156
+ const url = `${obj.baseURL}/${type}/${obj.username}/${obj.password}/${streamID}.${extension}`;
157
+ console.log('Stream URL for VOD:', url);
158
+ stream = [{
159
+ url: url,
160
+ name: "Watch Now"
161
+ }];
162
+ }
163
+
164
+ respond(res, { streams: stream });
165
+ }
166
+ });
167
+
168
+ // Listen for incoming requests
169
+ if (module.parent) {
170
+ module.exports = app;
171
+ } else {
172
+ app.listen(config.port, function () {
173
+ console.log(config);
174
+ });
175
+ }
manifest.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module.exports = {
2
+ id: "org.community.YourIPTV",
3
+ version: "2.0.5",
4
+ name: "HY EPG IPTV",
5
+ logo: "./assets/logo.png", // Local logo
6
+ description: "This addon brings all the Live Streams, VOD streams and Series from your IPTV subscription to your Stremio using Xtream API and supports IMDb IDs.",
7
+ types: ["movie", "series", "tv", "channel"],
8
+ background: "./assets/background.jpg", // Local background
9
+ resources: ["movie", "series", "tv"],
10
+ catalogs: [],
11
+ idPrefixes: ["yiptv:", "tt"],
12
+ behaviorHints: { configurable: true, configurationRequired: true },
13
+ };
package-lock.json ADDED
@@ -0,0 +1,1597 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "your-iptv-1",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 2,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "your-iptv-1",
9
+ "version": "1.0.0",
10
+ "license": "ISC",
11
+ "dependencies": {
12
+ "axios": "^0.27.2",
13
+ "ejs": "^3.1.8",
14
+ "express": "^4.18.1",
15
+ "moment-timezone": "^0.5.45",
16
+ "node-cache": "^5.1.2",
17
+ "node-fetch": "^3.3.2"
18
+ }
19
+ },
20
+ "node_modules/accepts": {
21
+ "version": "1.3.8",
22
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
23
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
24
+ "dependencies": {
25
+ "mime-types": "~2.1.34",
26
+ "negotiator": "0.6.3"
27
+ },
28
+ "engines": {
29
+ "node": ">= 0.6"
30
+ }
31
+ },
32
+ "node_modules/ansi-styles": {
33
+ "version": "4.3.0",
34
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
35
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
36
+ "dependencies": {
37
+ "color-convert": "^2.0.1"
38
+ },
39
+ "engines": {
40
+ "node": ">=8"
41
+ },
42
+ "funding": {
43
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
44
+ }
45
+ },
46
+ "node_modules/array-flatten": {
47
+ "version": "1.1.1",
48
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
49
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
50
+ },
51
+ "node_modules/async": {
52
+ "version": "3.2.4",
53
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
54
+ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
55
+ },
56
+ "node_modules/asynckit": {
57
+ "version": "0.4.0",
58
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
59
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
60
+ },
61
+ "node_modules/axios": {
62
+ "version": "0.27.2",
63
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
64
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
65
+ "dependencies": {
66
+ "follow-redirects": "^1.14.9",
67
+ "form-data": "^4.0.0"
68
+ }
69
+ },
70
+ "node_modules/balanced-match": {
71
+ "version": "1.0.2",
72
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
73
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
74
+ },
75
+ "node_modules/body-parser": {
76
+ "version": "1.20.0",
77
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
78
+ "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
79
+ "dependencies": {
80
+ "bytes": "3.1.2",
81
+ "content-type": "~1.0.4",
82
+ "debug": "2.6.9",
83
+ "depd": "2.0.0",
84
+ "destroy": "1.2.0",
85
+ "http-errors": "2.0.0",
86
+ "iconv-lite": "0.4.24",
87
+ "on-finished": "2.4.1",
88
+ "qs": "6.10.3",
89
+ "raw-body": "2.5.1",
90
+ "type-is": "~1.6.18",
91
+ "unpipe": "1.0.0"
92
+ },
93
+ "engines": {
94
+ "node": ">= 0.8",
95
+ "npm": "1.2.8000 || >= 1.4.16"
96
+ }
97
+ },
98
+ "node_modules/brace-expansion": {
99
+ "version": "1.1.11",
100
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
101
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
102
+ "dependencies": {
103
+ "balanced-match": "^1.0.0",
104
+ "concat-map": "0.0.1"
105
+ }
106
+ },
107
+ "node_modules/bytes": {
108
+ "version": "3.1.2",
109
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
110
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
111
+ "engines": {
112
+ "node": ">= 0.8"
113
+ }
114
+ },
115
+ "node_modules/call-bind": {
116
+ "version": "1.0.2",
117
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
118
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
119
+ "dependencies": {
120
+ "function-bind": "^1.1.1",
121
+ "get-intrinsic": "^1.0.2"
122
+ },
123
+ "funding": {
124
+ "url": "https://github.com/sponsors/ljharb"
125
+ }
126
+ },
127
+ "node_modules/chalk": {
128
+ "version": "4.1.2",
129
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
130
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
131
+ "dependencies": {
132
+ "ansi-styles": "^4.1.0",
133
+ "supports-color": "^7.1.0"
134
+ },
135
+ "engines": {
136
+ "node": ">=10"
137
+ },
138
+ "funding": {
139
+ "url": "https://github.com/chalk/chalk?sponsor=1"
140
+ }
141
+ },
142
+ "node_modules/clone": {
143
+ "version": "2.1.2",
144
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
145
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
146
+ "engines": {
147
+ "node": ">=0.8"
148
+ }
149
+ },
150
+ "node_modules/color-convert": {
151
+ "version": "2.0.1",
152
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
153
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
154
+ "dependencies": {
155
+ "color-name": "~1.1.4"
156
+ },
157
+ "engines": {
158
+ "node": ">=7.0.0"
159
+ }
160
+ },
161
+ "node_modules/color-name": {
162
+ "version": "1.1.4",
163
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
164
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
165
+ },
166
+ "node_modules/combined-stream": {
167
+ "version": "1.0.8",
168
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
169
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
170
+ "dependencies": {
171
+ "delayed-stream": "~1.0.0"
172
+ },
173
+ "engines": {
174
+ "node": ">= 0.8"
175
+ }
176
+ },
177
+ "node_modules/concat-map": {
178
+ "version": "0.0.1",
179
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
180
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
181
+ },
182
+ "node_modules/content-disposition": {
183
+ "version": "0.5.4",
184
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
185
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
186
+ "dependencies": {
187
+ "safe-buffer": "5.2.1"
188
+ },
189
+ "engines": {
190
+ "node": ">= 0.6"
191
+ }
192
+ },
193
+ "node_modules/content-type": {
194
+ "version": "1.0.4",
195
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
196
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
197
+ "engines": {
198
+ "node": ">= 0.6"
199
+ }
200
+ },
201
+ "node_modules/cookie": {
202
+ "version": "0.5.0",
203
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
204
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
205
+ "engines": {
206
+ "node": ">= 0.6"
207
+ }
208
+ },
209
+ "node_modules/cookie-signature": {
210
+ "version": "1.0.6",
211
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
212
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
213
+ },
214
+ "node_modules/data-uri-to-buffer": {
215
+ "version": "4.0.1",
216
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
217
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
218
+ "engines": {
219
+ "node": ">= 12"
220
+ }
221
+ },
222
+ "node_modules/debug": {
223
+ "version": "2.6.9",
224
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
225
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
226
+ "dependencies": {
227
+ "ms": "2.0.0"
228
+ }
229
+ },
230
+ "node_modules/delayed-stream": {
231
+ "version": "1.0.0",
232
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
233
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
234
+ "engines": {
235
+ "node": ">=0.4.0"
236
+ }
237
+ },
238
+ "node_modules/depd": {
239
+ "version": "2.0.0",
240
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
241
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
242
+ "engines": {
243
+ "node": ">= 0.8"
244
+ }
245
+ },
246
+ "node_modules/destroy": {
247
+ "version": "1.2.0",
248
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
249
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
250
+ "engines": {
251
+ "node": ">= 0.8",
252
+ "npm": "1.2.8000 || >= 1.4.16"
253
+ }
254
+ },
255
+ "node_modules/ee-first": {
256
+ "version": "1.1.1",
257
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
258
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
259
+ },
260
+ "node_modules/ejs": {
261
+ "version": "3.1.8",
262
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz",
263
+ "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==",
264
+ "dependencies": {
265
+ "jake": "^10.8.5"
266
+ },
267
+ "bin": {
268
+ "ejs": "bin/cli.js"
269
+ },
270
+ "engines": {
271
+ "node": ">=0.10.0"
272
+ }
273
+ },
274
+ "node_modules/encodeurl": {
275
+ "version": "1.0.2",
276
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
277
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
278
+ "engines": {
279
+ "node": ">= 0.8"
280
+ }
281
+ },
282
+ "node_modules/escape-html": {
283
+ "version": "1.0.3",
284
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
285
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
286
+ },
287
+ "node_modules/etag": {
288
+ "version": "1.8.1",
289
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
290
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
291
+ "engines": {
292
+ "node": ">= 0.6"
293
+ }
294
+ },
295
+ "node_modules/express": {
296
+ "version": "4.18.1",
297
+ "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
298
+ "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
299
+ "dependencies": {
300
+ "accepts": "~1.3.8",
301
+ "array-flatten": "1.1.1",
302
+ "body-parser": "1.20.0",
303
+ "content-disposition": "0.5.4",
304
+ "content-type": "~1.0.4",
305
+ "cookie": "0.5.0",
306
+ "cookie-signature": "1.0.6",
307
+ "debug": "2.6.9",
308
+ "depd": "2.0.0",
309
+ "encodeurl": "~1.0.2",
310
+ "escape-html": "~1.0.3",
311
+ "etag": "~1.8.1",
312
+ "finalhandler": "1.2.0",
313
+ "fresh": "0.5.2",
314
+ "http-errors": "2.0.0",
315
+ "merge-descriptors": "1.0.1",
316
+ "methods": "~1.1.2",
317
+ "on-finished": "2.4.1",
318
+ "parseurl": "~1.3.3",
319
+ "path-to-regexp": "0.1.7",
320
+ "proxy-addr": "~2.0.7",
321
+ "qs": "6.10.3",
322
+ "range-parser": "~1.2.1",
323
+ "safe-buffer": "5.2.1",
324
+ "send": "0.18.0",
325
+ "serve-static": "1.15.0",
326
+ "setprototypeof": "1.2.0",
327
+ "statuses": "2.0.1",
328
+ "type-is": "~1.6.18",
329
+ "utils-merge": "1.0.1",
330
+ "vary": "~1.1.2"
331
+ },
332
+ "engines": {
333
+ "node": ">= 0.10.0"
334
+ }
335
+ },
336
+ "node_modules/fetch-blob": {
337
+ "version": "3.2.0",
338
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
339
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
340
+ "funding": [
341
+ {
342
+ "type": "github",
343
+ "url": "https://github.com/sponsors/jimmywarting"
344
+ },
345
+ {
346
+ "type": "paypal",
347
+ "url": "https://paypal.me/jimmywarting"
348
+ }
349
+ ],
350
+ "dependencies": {
351
+ "node-domexception": "^1.0.0",
352
+ "web-streams-polyfill": "^3.0.3"
353
+ },
354
+ "engines": {
355
+ "node": "^12.20 || >= 14.13"
356
+ }
357
+ },
358
+ "node_modules/filelist": {
359
+ "version": "1.0.4",
360
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
361
+ "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
362
+ "dependencies": {
363
+ "minimatch": "^5.0.1"
364
+ }
365
+ },
366
+ "node_modules/filelist/node_modules/brace-expansion": {
367
+ "version": "2.0.1",
368
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
369
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
370
+ "dependencies": {
371
+ "balanced-match": "^1.0.0"
372
+ }
373
+ },
374
+ "node_modules/filelist/node_modules/minimatch": {
375
+ "version": "5.1.0",
376
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
377
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
378
+ "dependencies": {
379
+ "brace-expansion": "^2.0.1"
380
+ },
381
+ "engines": {
382
+ "node": ">=10"
383
+ }
384
+ },
385
+ "node_modules/finalhandler": {
386
+ "version": "1.2.0",
387
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
388
+ "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
389
+ "dependencies": {
390
+ "debug": "2.6.9",
391
+ "encodeurl": "~1.0.2",
392
+ "escape-html": "~1.0.3",
393
+ "on-finished": "2.4.1",
394
+ "parseurl": "~1.3.3",
395
+ "statuses": "2.0.1",
396
+ "unpipe": "~1.0.0"
397
+ },
398
+ "engines": {
399
+ "node": ">= 0.8"
400
+ }
401
+ },
402
+ "node_modules/follow-redirects": {
403
+ "version": "1.15.2",
404
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
405
+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
406
+ "funding": [
407
+ {
408
+ "type": "individual",
409
+ "url": "https://github.com/sponsors/RubenVerborgh"
410
+ }
411
+ ],
412
+ "engines": {
413
+ "node": ">=4.0"
414
+ },
415
+ "peerDependenciesMeta": {
416
+ "debug": {
417
+ "optional": true
418
+ }
419
+ }
420
+ },
421
+ "node_modules/form-data": {
422
+ "version": "4.0.0",
423
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
424
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
425
+ "dependencies": {
426
+ "asynckit": "^0.4.0",
427
+ "combined-stream": "^1.0.8",
428
+ "mime-types": "^2.1.12"
429
+ },
430
+ "engines": {
431
+ "node": ">= 6"
432
+ }
433
+ },
434
+ "node_modules/formdata-polyfill": {
435
+ "version": "4.0.10",
436
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
437
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
438
+ "dependencies": {
439
+ "fetch-blob": "^3.1.2"
440
+ },
441
+ "engines": {
442
+ "node": ">=12.20.0"
443
+ }
444
+ },
445
+ "node_modules/forwarded": {
446
+ "version": "0.2.0",
447
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
448
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
449
+ "engines": {
450
+ "node": ">= 0.6"
451
+ }
452
+ },
453
+ "node_modules/fresh": {
454
+ "version": "0.5.2",
455
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
456
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
457
+ "engines": {
458
+ "node": ">= 0.6"
459
+ }
460
+ },
461
+ "node_modules/function-bind": {
462
+ "version": "1.1.1",
463
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
464
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
465
+ },
466
+ "node_modules/get-intrinsic": {
467
+ "version": "1.1.3",
468
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
469
+ "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
470
+ "dependencies": {
471
+ "function-bind": "^1.1.1",
472
+ "has": "^1.0.3",
473
+ "has-symbols": "^1.0.3"
474
+ },
475
+ "funding": {
476
+ "url": "https://github.com/sponsors/ljharb"
477
+ }
478
+ },
479
+ "node_modules/has": {
480
+ "version": "1.0.3",
481
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
482
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
483
+ "dependencies": {
484
+ "function-bind": "^1.1.1"
485
+ },
486
+ "engines": {
487
+ "node": ">= 0.4.0"
488
+ }
489
+ },
490
+ "node_modules/has-flag": {
491
+ "version": "4.0.0",
492
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
493
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
494
+ "engines": {
495
+ "node": ">=8"
496
+ }
497
+ },
498
+ "node_modules/has-symbols": {
499
+ "version": "1.0.3",
500
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
501
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
502
+ "engines": {
503
+ "node": ">= 0.4"
504
+ },
505
+ "funding": {
506
+ "url": "https://github.com/sponsors/ljharb"
507
+ }
508
+ },
509
+ "node_modules/http-errors": {
510
+ "version": "2.0.0",
511
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
512
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
513
+ "dependencies": {
514
+ "depd": "2.0.0",
515
+ "inherits": "2.0.4",
516
+ "setprototypeof": "1.2.0",
517
+ "statuses": "2.0.1",
518
+ "toidentifier": "1.0.1"
519
+ },
520
+ "engines": {
521
+ "node": ">= 0.8"
522
+ }
523
+ },
524
+ "node_modules/iconv-lite": {
525
+ "version": "0.4.24",
526
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
527
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
528
+ "dependencies": {
529
+ "safer-buffer": ">= 2.1.2 < 3"
530
+ },
531
+ "engines": {
532
+ "node": ">=0.10.0"
533
+ }
534
+ },
535
+ "node_modules/inherits": {
536
+ "version": "2.0.4",
537
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
538
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
539
+ },
540
+ "node_modules/ipaddr.js": {
541
+ "version": "1.9.1",
542
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
543
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
544
+ "engines": {
545
+ "node": ">= 0.10"
546
+ }
547
+ },
548
+ "node_modules/jake": {
549
+ "version": "10.8.5",
550
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
551
+ "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
552
+ "dependencies": {
553
+ "async": "^3.2.3",
554
+ "chalk": "^4.0.2",
555
+ "filelist": "^1.0.1",
556
+ "minimatch": "^3.0.4"
557
+ },
558
+ "bin": {
559
+ "jake": "bin/cli.js"
560
+ },
561
+ "engines": {
562
+ "node": ">=10"
563
+ }
564
+ },
565
+ "node_modules/media-typer": {
566
+ "version": "0.3.0",
567
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
568
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
569
+ "engines": {
570
+ "node": ">= 0.6"
571
+ }
572
+ },
573
+ "node_modules/merge-descriptors": {
574
+ "version": "1.0.1",
575
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
576
+ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
577
+ },
578
+ "node_modules/methods": {
579
+ "version": "1.1.2",
580
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
581
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
582
+ "engines": {
583
+ "node": ">= 0.6"
584
+ }
585
+ },
586
+ "node_modules/mime": {
587
+ "version": "1.6.0",
588
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
589
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
590
+ "bin": {
591
+ "mime": "cli.js"
592
+ },
593
+ "engines": {
594
+ "node": ">=4"
595
+ }
596
+ },
597
+ "node_modules/mime-db": {
598
+ "version": "1.52.0",
599
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
600
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
601
+ "engines": {
602
+ "node": ">= 0.6"
603
+ }
604
+ },
605
+ "node_modules/mime-types": {
606
+ "version": "2.1.35",
607
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
608
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
609
+ "dependencies": {
610
+ "mime-db": "1.52.0"
611
+ },
612
+ "engines": {
613
+ "node": ">= 0.6"
614
+ }
615
+ },
616
+ "node_modules/minimatch": {
617
+ "version": "3.1.2",
618
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
619
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
620
+ "dependencies": {
621
+ "brace-expansion": "^1.1.7"
622
+ },
623
+ "engines": {
624
+ "node": "*"
625
+ }
626
+ },
627
+ "node_modules/moment": {
628
+ "version": "2.30.1",
629
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
630
+ "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
631
+ "engines": {
632
+ "node": "*"
633
+ }
634
+ },
635
+ "node_modules/moment-timezone": {
636
+ "version": "0.5.46",
637
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz",
638
+ "integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==",
639
+ "dependencies": {
640
+ "moment": "^2.29.4"
641
+ },
642
+ "engines": {
643
+ "node": "*"
644
+ }
645
+ },
646
+ "node_modules/ms": {
647
+ "version": "2.0.0",
648
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
649
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
650
+ },
651
+ "node_modules/negotiator": {
652
+ "version": "0.6.3",
653
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
654
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
655
+ "engines": {
656
+ "node": ">= 0.6"
657
+ }
658
+ },
659
+ "node_modules/node-cache": {
660
+ "version": "5.1.2",
661
+ "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz",
662
+ "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==",
663
+ "dependencies": {
664
+ "clone": "2.x"
665
+ },
666
+ "engines": {
667
+ "node": ">= 8.0.0"
668
+ }
669
+ },
670
+ "node_modules/node-domexception": {
671
+ "version": "1.0.0",
672
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
673
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
674
+ "funding": [
675
+ {
676
+ "type": "github",
677
+ "url": "https://github.com/sponsors/jimmywarting"
678
+ },
679
+ {
680
+ "type": "github",
681
+ "url": "https://paypal.me/jimmywarting"
682
+ }
683
+ ],
684
+ "engines": {
685
+ "node": ">=10.5.0"
686
+ }
687
+ },
688
+ "node_modules/node-fetch": {
689
+ "version": "3.3.2",
690
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
691
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
692
+ "dependencies": {
693
+ "data-uri-to-buffer": "^4.0.0",
694
+ "fetch-blob": "^3.1.4",
695
+ "formdata-polyfill": "^4.0.10"
696
+ },
697
+ "engines": {
698
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
699
+ },
700
+ "funding": {
701
+ "type": "opencollective",
702
+ "url": "https://opencollective.com/node-fetch"
703
+ }
704
+ },
705
+ "node_modules/object-inspect": {
706
+ "version": "1.12.2",
707
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
708
+ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
709
+ "funding": {
710
+ "url": "https://github.com/sponsors/ljharb"
711
+ }
712
+ },
713
+ "node_modules/on-finished": {
714
+ "version": "2.4.1",
715
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
716
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
717
+ "dependencies": {
718
+ "ee-first": "1.1.1"
719
+ },
720
+ "engines": {
721
+ "node": ">= 0.8"
722
+ }
723
+ },
724
+ "node_modules/parseurl": {
725
+ "version": "1.3.3",
726
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
727
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
728
+ "engines": {
729
+ "node": ">= 0.8"
730
+ }
731
+ },
732
+ "node_modules/path-to-regexp": {
733
+ "version": "0.1.7",
734
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
735
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
736
+ },
737
+ "node_modules/proxy-addr": {
738
+ "version": "2.0.7",
739
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
740
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
741
+ "dependencies": {
742
+ "forwarded": "0.2.0",
743
+ "ipaddr.js": "1.9.1"
744
+ },
745
+ "engines": {
746
+ "node": ">= 0.10"
747
+ }
748
+ },
749
+ "node_modules/qs": {
750
+ "version": "6.10.3",
751
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
752
+ "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
753
+ "dependencies": {
754
+ "side-channel": "^1.0.4"
755
+ },
756
+ "engines": {
757
+ "node": ">=0.6"
758
+ },
759
+ "funding": {
760
+ "url": "https://github.com/sponsors/ljharb"
761
+ }
762
+ },
763
+ "node_modules/range-parser": {
764
+ "version": "1.2.1",
765
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
766
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
767
+ "engines": {
768
+ "node": ">= 0.6"
769
+ }
770
+ },
771
+ "node_modules/raw-body": {
772
+ "version": "2.5.1",
773
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
774
+ "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
775
+ "dependencies": {
776
+ "bytes": "3.1.2",
777
+ "http-errors": "2.0.0",
778
+ "iconv-lite": "0.4.24",
779
+ "unpipe": "1.0.0"
780
+ },
781
+ "engines": {
782
+ "node": ">= 0.8"
783
+ }
784
+ },
785
+ "node_modules/safe-buffer": {
786
+ "version": "5.2.1",
787
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
788
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
789
+ "funding": [
790
+ {
791
+ "type": "github",
792
+ "url": "https://github.com/sponsors/feross"
793
+ },
794
+ {
795
+ "type": "patreon",
796
+ "url": "https://www.patreon.com/feross"
797
+ },
798
+ {
799
+ "type": "consulting",
800
+ "url": "https://feross.org/support"
801
+ }
802
+ ]
803
+ },
804
+ "node_modules/safer-buffer": {
805
+ "version": "2.1.2",
806
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
807
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
808
+ },
809
+ "node_modules/send": {
810
+ "version": "0.18.0",
811
+ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
812
+ "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
813
+ "dependencies": {
814
+ "debug": "2.6.9",
815
+ "depd": "2.0.0",
816
+ "destroy": "1.2.0",
817
+ "encodeurl": "~1.0.2",
818
+ "escape-html": "~1.0.3",
819
+ "etag": "~1.8.1",
820
+ "fresh": "0.5.2",
821
+ "http-errors": "2.0.0",
822
+ "mime": "1.6.0",
823
+ "ms": "2.1.3",
824
+ "on-finished": "2.4.1",
825
+ "range-parser": "~1.2.1",
826
+ "statuses": "2.0.1"
827
+ },
828
+ "engines": {
829
+ "node": ">= 0.8.0"
830
+ }
831
+ },
832
+ "node_modules/send/node_modules/ms": {
833
+ "version": "2.1.3",
834
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
835
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
836
+ },
837
+ "node_modules/serve-static": {
838
+ "version": "1.15.0",
839
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
840
+ "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
841
+ "dependencies": {
842
+ "encodeurl": "~1.0.2",
843
+ "escape-html": "~1.0.3",
844
+ "parseurl": "~1.3.3",
845
+ "send": "0.18.0"
846
+ },
847
+ "engines": {
848
+ "node": ">= 0.8.0"
849
+ }
850
+ },
851
+ "node_modules/setprototypeof": {
852
+ "version": "1.2.0",
853
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
854
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
855
+ },
856
+ "node_modules/side-channel": {
857
+ "version": "1.0.4",
858
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
859
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
860
+ "dependencies": {
861
+ "call-bind": "^1.0.0",
862
+ "get-intrinsic": "^1.0.2",
863
+ "object-inspect": "^1.9.0"
864
+ },
865
+ "funding": {
866
+ "url": "https://github.com/sponsors/ljharb"
867
+ }
868
+ },
869
+ "node_modules/statuses": {
870
+ "version": "2.0.1",
871
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
872
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
873
+ "engines": {
874
+ "node": ">= 0.8"
875
+ }
876
+ },
877
+ "node_modules/supports-color": {
878
+ "version": "7.2.0",
879
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
880
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
881
+ "dependencies": {
882
+ "has-flag": "^4.0.0"
883
+ },
884
+ "engines": {
885
+ "node": ">=8"
886
+ }
887
+ },
888
+ "node_modules/toidentifier": {
889
+ "version": "1.0.1",
890
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
891
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
892
+ "engines": {
893
+ "node": ">=0.6"
894
+ }
895
+ },
896
+ "node_modules/type-is": {
897
+ "version": "1.6.18",
898
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
899
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
900
+ "dependencies": {
901
+ "media-typer": "0.3.0",
902
+ "mime-types": "~2.1.24"
903
+ },
904
+ "engines": {
905
+ "node": ">= 0.6"
906
+ }
907
+ },
908
+ "node_modules/unpipe": {
909
+ "version": "1.0.0",
910
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
911
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
912
+ "engines": {
913
+ "node": ">= 0.8"
914
+ }
915
+ },
916
+ "node_modules/utils-merge": {
917
+ "version": "1.0.1",
918
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
919
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
920
+ "engines": {
921
+ "node": ">= 0.4.0"
922
+ }
923
+ },
924
+ "node_modules/vary": {
925
+ "version": "1.1.2",
926
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
927
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
928
+ "engines": {
929
+ "node": ">= 0.8"
930
+ }
931
+ },
932
+ "node_modules/web-streams-polyfill": {
933
+ "version": "3.3.3",
934
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
935
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
936
+ "engines": {
937
+ "node": ">= 8"
938
+ }
939
+ }
940
+ },
941
+ "dependencies": {
942
+ "accepts": {
943
+ "version": "1.3.8",
944
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
945
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
946
+ "requires": {
947
+ "mime-types": "~2.1.34",
948
+ "negotiator": "0.6.3"
949
+ }
950
+ },
951
+ "ansi-styles": {
952
+ "version": "4.3.0",
953
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
954
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
955
+ "requires": {
956
+ "color-convert": "^2.0.1"
957
+ }
958
+ },
959
+ "array-flatten": {
960
+ "version": "1.1.1",
961
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
962
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
963
+ },
964
+ "async": {
965
+ "version": "3.2.4",
966
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
967
+ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
968
+ },
969
+ "asynckit": {
970
+ "version": "0.4.0",
971
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
972
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
973
+ },
974
+ "axios": {
975
+ "version": "0.27.2",
976
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
977
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
978
+ "requires": {
979
+ "follow-redirects": "^1.14.9",
980
+ "form-data": "^4.0.0"
981
+ }
982
+ },
983
+ "balanced-match": {
984
+ "version": "1.0.2",
985
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
986
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
987
+ },
988
+ "body-parser": {
989
+ "version": "1.20.0",
990
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
991
+ "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
992
+ "requires": {
993
+ "bytes": "3.1.2",
994
+ "content-type": "~1.0.4",
995
+ "debug": "2.6.9",
996
+ "depd": "2.0.0",
997
+ "destroy": "1.2.0",
998
+ "http-errors": "2.0.0",
999
+ "iconv-lite": "0.4.24",
1000
+ "on-finished": "2.4.1",
1001
+ "qs": "6.10.3",
1002
+ "raw-body": "2.5.1",
1003
+ "type-is": "~1.6.18",
1004
+ "unpipe": "1.0.0"
1005
+ }
1006
+ },
1007
+ "brace-expansion": {
1008
+ "version": "1.1.11",
1009
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1010
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1011
+ "requires": {
1012
+ "balanced-match": "^1.0.0",
1013
+ "concat-map": "0.0.1"
1014
+ }
1015
+ },
1016
+ "bytes": {
1017
+ "version": "3.1.2",
1018
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
1019
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
1020
+ },
1021
+ "call-bind": {
1022
+ "version": "1.0.2",
1023
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
1024
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
1025
+ "requires": {
1026
+ "function-bind": "^1.1.1",
1027
+ "get-intrinsic": "^1.0.2"
1028
+ }
1029
+ },
1030
+ "chalk": {
1031
+ "version": "4.1.2",
1032
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1033
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1034
+ "requires": {
1035
+ "ansi-styles": "^4.1.0",
1036
+ "supports-color": "^7.1.0"
1037
+ }
1038
+ },
1039
+ "clone": {
1040
+ "version": "2.1.2",
1041
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
1042
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="
1043
+ },
1044
+ "color-convert": {
1045
+ "version": "2.0.1",
1046
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1047
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1048
+ "requires": {
1049
+ "color-name": "~1.1.4"
1050
+ }
1051
+ },
1052
+ "color-name": {
1053
+ "version": "1.1.4",
1054
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1055
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
1056
+ },
1057
+ "combined-stream": {
1058
+ "version": "1.0.8",
1059
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
1060
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
1061
+ "requires": {
1062
+ "delayed-stream": "~1.0.0"
1063
+ }
1064
+ },
1065
+ "concat-map": {
1066
+ "version": "0.0.1",
1067
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1068
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
1069
+ },
1070
+ "content-disposition": {
1071
+ "version": "0.5.4",
1072
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
1073
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
1074
+ "requires": {
1075
+ "safe-buffer": "5.2.1"
1076
+ }
1077
+ },
1078
+ "content-type": {
1079
+ "version": "1.0.4",
1080
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
1081
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
1082
+ },
1083
+ "cookie": {
1084
+ "version": "0.5.0",
1085
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
1086
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
1087
+ },
1088
+ "cookie-signature": {
1089
+ "version": "1.0.6",
1090
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
1091
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
1092
+ },
1093
+ "data-uri-to-buffer": {
1094
+ "version": "4.0.1",
1095
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
1096
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="
1097
+ },
1098
+ "debug": {
1099
+ "version": "2.6.9",
1100
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
1101
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
1102
+ "requires": {
1103
+ "ms": "2.0.0"
1104
+ }
1105
+ },
1106
+ "delayed-stream": {
1107
+ "version": "1.0.0",
1108
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
1109
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
1110
+ },
1111
+ "depd": {
1112
+ "version": "2.0.0",
1113
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
1114
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
1115
+ },
1116
+ "destroy": {
1117
+ "version": "1.2.0",
1118
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
1119
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
1120
+ },
1121
+ "ee-first": {
1122
+ "version": "1.1.1",
1123
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
1124
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
1125
+ },
1126
+ "ejs": {
1127
+ "version": "3.1.8",
1128
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz",
1129
+ "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==",
1130
+ "requires": {
1131
+ "jake": "^10.8.5"
1132
+ }
1133
+ },
1134
+ "encodeurl": {
1135
+ "version": "1.0.2",
1136
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
1137
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
1138
+ },
1139
+ "escape-html": {
1140
+ "version": "1.0.3",
1141
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
1142
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
1143
+ },
1144
+ "etag": {
1145
+ "version": "1.8.1",
1146
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
1147
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
1148
+ },
1149
+ "express": {
1150
+ "version": "4.18.1",
1151
+ "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
1152
+ "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
1153
+ "requires": {
1154
+ "accepts": "~1.3.8",
1155
+ "array-flatten": "1.1.1",
1156
+ "body-parser": "1.20.0",
1157
+ "content-disposition": "0.5.4",
1158
+ "content-type": "~1.0.4",
1159
+ "cookie": "0.5.0",
1160
+ "cookie-signature": "1.0.6",
1161
+ "debug": "2.6.9",
1162
+ "depd": "2.0.0",
1163
+ "encodeurl": "~1.0.2",
1164
+ "escape-html": "~1.0.3",
1165
+ "etag": "~1.8.1",
1166
+ "finalhandler": "1.2.0",
1167
+ "fresh": "0.5.2",
1168
+ "http-errors": "2.0.0",
1169
+ "merge-descriptors": "1.0.1",
1170
+ "methods": "~1.1.2",
1171
+ "on-finished": "2.4.1",
1172
+ "parseurl": "~1.3.3",
1173
+ "path-to-regexp": "0.1.7",
1174
+ "proxy-addr": "~2.0.7",
1175
+ "qs": "6.10.3",
1176
+ "range-parser": "~1.2.1",
1177
+ "safe-buffer": "5.2.1",
1178
+ "send": "0.18.0",
1179
+ "serve-static": "1.15.0",
1180
+ "setprototypeof": "1.2.0",
1181
+ "statuses": "2.0.1",
1182
+ "type-is": "~1.6.18",
1183
+ "utils-merge": "1.0.1",
1184
+ "vary": "~1.1.2"
1185
+ }
1186
+ },
1187
+ "fetch-blob": {
1188
+ "version": "3.2.0",
1189
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
1190
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
1191
+ "requires": {
1192
+ "node-domexception": "^1.0.0",
1193
+ "web-streams-polyfill": "^3.0.3"
1194
+ }
1195
+ },
1196
+ "filelist": {
1197
+ "version": "1.0.4",
1198
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
1199
+ "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
1200
+ "requires": {
1201
+ "minimatch": "^5.0.1"
1202
+ },
1203
+ "dependencies": {
1204
+ "brace-expansion": {
1205
+ "version": "2.0.1",
1206
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
1207
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
1208
+ "requires": {
1209
+ "balanced-match": "^1.0.0"
1210
+ }
1211
+ },
1212
+ "minimatch": {
1213
+ "version": "5.1.0",
1214
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
1215
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
1216
+ "requires": {
1217
+ "brace-expansion": "^2.0.1"
1218
+ }
1219
+ }
1220
+ }
1221
+ },
1222
+ "finalhandler": {
1223
+ "version": "1.2.0",
1224
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
1225
+ "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
1226
+ "requires": {
1227
+ "debug": "2.6.9",
1228
+ "encodeurl": "~1.0.2",
1229
+ "escape-html": "~1.0.3",
1230
+ "on-finished": "2.4.1",
1231
+ "parseurl": "~1.3.3",
1232
+ "statuses": "2.0.1",
1233
+ "unpipe": "~1.0.0"
1234
+ }
1235
+ },
1236
+ "follow-redirects": {
1237
+ "version": "1.15.2",
1238
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
1239
+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
1240
+ },
1241
+ "form-data": {
1242
+ "version": "4.0.0",
1243
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
1244
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
1245
+ "requires": {
1246
+ "asynckit": "^0.4.0",
1247
+ "combined-stream": "^1.0.8",
1248
+ "mime-types": "^2.1.12"
1249
+ }
1250
+ },
1251
+ "formdata-polyfill": {
1252
+ "version": "4.0.10",
1253
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
1254
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
1255
+ "requires": {
1256
+ "fetch-blob": "^3.1.2"
1257
+ }
1258
+ },
1259
+ "forwarded": {
1260
+ "version": "0.2.0",
1261
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
1262
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
1263
+ },
1264
+ "fresh": {
1265
+ "version": "0.5.2",
1266
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
1267
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
1268
+ },
1269
+ "function-bind": {
1270
+ "version": "1.1.1",
1271
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
1272
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
1273
+ },
1274
+ "get-intrinsic": {
1275
+ "version": "1.1.3",
1276
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
1277
+ "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
1278
+ "requires": {
1279
+ "function-bind": "^1.1.1",
1280
+ "has": "^1.0.3",
1281
+ "has-symbols": "^1.0.3"
1282
+ }
1283
+ },
1284
+ "has": {
1285
+ "version": "1.0.3",
1286
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
1287
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
1288
+ "requires": {
1289
+ "function-bind": "^1.1.1"
1290
+ }
1291
+ },
1292
+ "has-flag": {
1293
+ "version": "4.0.0",
1294
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1295
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
1296
+ },
1297
+ "has-symbols": {
1298
+ "version": "1.0.3",
1299
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
1300
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
1301
+ },
1302
+ "http-errors": {
1303
+ "version": "2.0.0",
1304
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
1305
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
1306
+ "requires": {
1307
+ "depd": "2.0.0",
1308
+ "inherits": "2.0.4",
1309
+ "setprototypeof": "1.2.0",
1310
+ "statuses": "2.0.1",
1311
+ "toidentifier": "1.0.1"
1312
+ }
1313
+ },
1314
+ "iconv-lite": {
1315
+ "version": "0.4.24",
1316
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
1317
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
1318
+ "requires": {
1319
+ "safer-buffer": ">= 2.1.2 < 3"
1320
+ }
1321
+ },
1322
+ "inherits": {
1323
+ "version": "2.0.4",
1324
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1325
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
1326
+ },
1327
+ "ipaddr.js": {
1328
+ "version": "1.9.1",
1329
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
1330
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
1331
+ },
1332
+ "jake": {
1333
+ "version": "10.8.5",
1334
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
1335
+ "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
1336
+ "requires": {
1337
+ "async": "^3.2.3",
1338
+ "chalk": "^4.0.2",
1339
+ "filelist": "^1.0.1",
1340
+ "minimatch": "^3.0.4"
1341
+ }
1342
+ },
1343
+ "media-typer": {
1344
+ "version": "0.3.0",
1345
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
1346
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
1347
+ },
1348
+ "merge-descriptors": {
1349
+ "version": "1.0.1",
1350
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
1351
+ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
1352
+ },
1353
+ "methods": {
1354
+ "version": "1.1.2",
1355
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
1356
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
1357
+ },
1358
+ "mime": {
1359
+ "version": "1.6.0",
1360
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
1361
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
1362
+ },
1363
+ "mime-db": {
1364
+ "version": "1.52.0",
1365
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
1366
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
1367
+ },
1368
+ "mime-types": {
1369
+ "version": "2.1.35",
1370
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
1371
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
1372
+ "requires": {
1373
+ "mime-db": "1.52.0"
1374
+ }
1375
+ },
1376
+ "minimatch": {
1377
+ "version": "3.1.2",
1378
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1379
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1380
+ "requires": {
1381
+ "brace-expansion": "^1.1.7"
1382
+ }
1383
+ },
1384
+ "moment": {
1385
+ "version": "2.30.1",
1386
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
1387
+ "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="
1388
+ },
1389
+ "moment-timezone": {
1390
+ "version": "0.5.46",
1391
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz",
1392
+ "integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==",
1393
+ "requires": {
1394
+ "moment": "^2.29.4"
1395
+ }
1396
+ },
1397
+ "ms": {
1398
+ "version": "2.0.0",
1399
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1400
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
1401
+ },
1402
+ "negotiator": {
1403
+ "version": "0.6.3",
1404
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
1405
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
1406
+ },
1407
+ "node-cache": {
1408
+ "version": "5.1.2",
1409
+ "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz",
1410
+ "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==",
1411
+ "requires": {
1412
+ "clone": "2.x"
1413
+ }
1414
+ },
1415
+ "node-domexception": {
1416
+ "version": "1.0.0",
1417
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
1418
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="
1419
+ },
1420
+ "node-fetch": {
1421
+ "version": "3.3.2",
1422
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
1423
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
1424
+ "requires": {
1425
+ "data-uri-to-buffer": "^4.0.0",
1426
+ "fetch-blob": "^3.1.4",
1427
+ "formdata-polyfill": "^4.0.10"
1428
+ }
1429
+ },
1430
+ "object-inspect": {
1431
+ "version": "1.12.2",
1432
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
1433
+ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ=="
1434
+ },
1435
+ "on-finished": {
1436
+ "version": "2.4.1",
1437
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
1438
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
1439
+ "requires": {
1440
+ "ee-first": "1.1.1"
1441
+ }
1442
+ },
1443
+ "parseurl": {
1444
+ "version": "1.3.3",
1445
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
1446
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
1447
+ },
1448
+ "path-to-regexp": {
1449
+ "version": "0.1.7",
1450
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
1451
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
1452
+ },
1453
+ "proxy-addr": {
1454
+ "version": "2.0.7",
1455
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
1456
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
1457
+ "requires": {
1458
+ "forwarded": "0.2.0",
1459
+ "ipaddr.js": "1.9.1"
1460
+ }
1461
+ },
1462
+ "qs": {
1463
+ "version": "6.10.3",
1464
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
1465
+ "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
1466
+ "requires": {
1467
+ "side-channel": "^1.0.4"
1468
+ }
1469
+ },
1470
+ "range-parser": {
1471
+ "version": "1.2.1",
1472
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
1473
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
1474
+ },
1475
+ "raw-body": {
1476
+ "version": "2.5.1",
1477
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
1478
+ "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
1479
+ "requires": {
1480
+ "bytes": "3.1.2",
1481
+ "http-errors": "2.0.0",
1482
+ "iconv-lite": "0.4.24",
1483
+ "unpipe": "1.0.0"
1484
+ }
1485
+ },
1486
+ "safe-buffer": {
1487
+ "version": "5.2.1",
1488
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1489
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
1490
+ },
1491
+ "safer-buffer": {
1492
+ "version": "2.1.2",
1493
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1494
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
1495
+ },
1496
+ "send": {
1497
+ "version": "0.18.0",
1498
+ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
1499
+ "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
1500
+ "requires": {
1501
+ "debug": "2.6.9",
1502
+ "depd": "2.0.0",
1503
+ "destroy": "1.2.0",
1504
+ "encodeurl": "~1.0.2",
1505
+ "escape-html": "~1.0.3",
1506
+ "etag": "~1.8.1",
1507
+ "fresh": "0.5.2",
1508
+ "http-errors": "2.0.0",
1509
+ "mime": "1.6.0",
1510
+ "ms": "2.1.3",
1511
+ "on-finished": "2.4.1",
1512
+ "range-parser": "~1.2.1",
1513
+ "statuses": "2.0.1"
1514
+ },
1515
+ "dependencies": {
1516
+ "ms": {
1517
+ "version": "2.1.3",
1518
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1519
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
1520
+ }
1521
+ }
1522
+ },
1523
+ "serve-static": {
1524
+ "version": "1.15.0",
1525
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
1526
+ "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
1527
+ "requires": {
1528
+ "encodeurl": "~1.0.2",
1529
+ "escape-html": "~1.0.3",
1530
+ "parseurl": "~1.3.3",
1531
+ "send": "0.18.0"
1532
+ }
1533
+ },
1534
+ "setprototypeof": {
1535
+ "version": "1.2.0",
1536
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
1537
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
1538
+ },
1539
+ "side-channel": {
1540
+ "version": "1.0.4",
1541
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
1542
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
1543
+ "requires": {
1544
+ "call-bind": "^1.0.0",
1545
+ "get-intrinsic": "^1.0.2",
1546
+ "object-inspect": "^1.9.0"
1547
+ }
1548
+ },
1549
+ "statuses": {
1550
+ "version": "2.0.1",
1551
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
1552
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
1553
+ },
1554
+ "supports-color": {
1555
+ "version": "7.2.0",
1556
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1557
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1558
+ "requires": {
1559
+ "has-flag": "^4.0.0"
1560
+ }
1561
+ },
1562
+ "toidentifier": {
1563
+ "version": "1.0.1",
1564
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
1565
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
1566
+ },
1567
+ "type-is": {
1568
+ "version": "1.6.18",
1569
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
1570
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
1571
+ "requires": {
1572
+ "media-typer": "0.3.0",
1573
+ "mime-types": "~2.1.24"
1574
+ }
1575
+ },
1576
+ "unpipe": {
1577
+ "version": "1.0.0",
1578
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1579
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
1580
+ },
1581
+ "utils-merge": {
1582
+ "version": "1.0.1",
1583
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
1584
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
1585
+ },
1586
+ "vary": {
1587
+ "version": "1.1.2",
1588
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1589
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
1590
+ },
1591
+ "web-streams-polyfill": {
1592
+ "version": "3.3.3",
1593
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
1594
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="
1595
+ }
1596
+ }
1597
+ }
package.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "your-iptv-1",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "start": "node index.js"
8
+ },
9
+ "keywords": [],
10
+ "author": "",
11
+ "license": "ISC",
12
+ "dependencies": {
13
+ "axios": "^0.27.2",
14
+ "ejs": "^3.1.8",
15
+ "express": "^4.18.1",
16
+ "moment-timezone": "^0.5.45",
17
+ "node-cache": "^5.1.2",
18
+ "node-fetch": "^3.3.2"
19
+ }
20
+ }
tvGuide.js ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const moment = require('moment-timezone');
3
+
4
+ function unixTimestampToSpecifiedTimezone(timestamp, timezone) {
5
+ // The timestamp is already in UTC, so we just need to format it for the specified timezone
6
+ return moment(timestamp, 'YYYYMMDDHHmmss ZZ').tz(timezone).format('ddd, DD MMM YYYY HH:mm:ss z');
7
+ }
8
+
9
+ async function fetchAndProcessXMLTV(baseUrl, username, password) {
10
+ const xmltvUrl = `${baseUrl}/xmltv.php?username=${username}&password=${password}`;
11
+ const response = await axios.get(xmltvUrl);
12
+ const xmlData = response.data;
13
+
14
+ function getElements(xml, tag) {
15
+ const regex = new RegExp(`<${tag}[^>]*>(.*?)<\/${tag}>`, 'gs');
16
+ return Array.from(xml.matchAll(regex)).map(match => match[0]);
17
+ }
18
+
19
+ function getAttribute(element, attr) {
20
+ const match = element.match(new RegExp(`${attr}="([^"]*)"`, 'i'));
21
+ return match ? match[1] : null;
22
+ }
23
+
24
+ function getTextContent(element) {
25
+ const match = element.match(/>([^<]*)</s);
26
+ return match ? match[1].trim() : '';
27
+ }
28
+
29
+ // Process channels
30
+ const channels = getElements(xmlData, 'channel')
31
+ .map(channel => ({
32
+ id: getAttribute(channel, 'id'),
33
+ name: getTextContent(getElements(channel, 'display-name')[0] || ''),
34
+ icon: getAttribute(getElements(channel, 'icon')[0] || '', 'src') || ''
35
+ }))
36
+ .sort((a, b) => a.name.localeCompare(b.name));
37
+
38
+ // Process programmes
39
+ const programmes = getElements(xmlData, 'programme')
40
+ .map(programme => ({
41
+ channelId: getAttribute(programme, 'channel'),
42
+ start: getAttribute(programme, 'start'),
43
+ stop: getAttribute(programme, 'stop'),
44
+ title: getTextContent(getElements(programme, 'title')[0] || ''),
45
+ description: getTextContent(getElements(programme, 'desc')[0] || '')
46
+ }))
47
+ .sort((a, b) => a.start.localeCompare(b.start));
48
+
49
+ return { channels, programmes };
50
+ }
51
+
52
+ function getCurrentAndNextProgram(programmes, timezone) {
53
+ const now = moment().tz(timezone);
54
+
55
+ let currentProgram = null;
56
+ let nextProgram = null;
57
+
58
+ for (let i = 0; i < programmes.length; i++) {
59
+ const programStart = moment(programmes[i].start, 'YYYYMMDDHHmmss ZZ');
60
+ const programStop = moment(programmes[i].stop, 'YYYYMMDDHHmmss ZZ');
61
+
62
+ if (programStart.isSameOrBefore(now) && programStop.isAfter(now)) {
63
+ currentProgram = programmes[i];
64
+ nextProgram = programmes[i + 1] || null;
65
+ break;
66
+ }
67
+ if (programStart.isAfter(now)) {
68
+ nextProgram = programmes[i];
69
+ break;
70
+ }
71
+ }
72
+
73
+ return {
74
+ currentProgram: currentProgram ? {
75
+ ...currentProgram,
76
+ start: unixTimestampToSpecifiedTimezone(currentProgram.start, timezone),
77
+ stop: unixTimestampToSpecifiedTimezone(currentProgram.stop, timezone)
78
+ } : null,
79
+ nextProgram: nextProgram ? {
80
+ ...nextProgram,
81
+ start: unixTimestampToSpecifiedTimezone(nextProgram.start, timezone),
82
+ stop: unixTimestampToSpecifiedTimezone(nextProgram.stop, timezone)
83
+ } : null
84
+ };
85
+ }
86
+
87
+ async function handleChannelRequest(epgChannelId, baseUrl, username, password, timezone) {
88
+ try {
89
+ const { channels, programmes } = await fetchAndProcessXMLTV(baseUrl, username, password);
90
+
91
+ const channelInfo = channels.find(channel => channel.id === epgChannelId);
92
+ if (!channelInfo) {
93
+ return null;
94
+ }
95
+
96
+ const channelProgrammes = programmes.filter(programme => programme.channelId === epgChannelId);
97
+
98
+ const { currentProgram, nextProgram } = getCurrentAndNextProgram(channelProgrammes, timezone);
99
+
100
+ return {
101
+ channel: channelInfo,
102
+ currentProgram: currentProgram,
103
+ nextProgram: nextProgram
104
+ };
105
+ } catch (error) {
106
+ console.error("Error in handleChannelRequest:", error);
107
+ return null;
108
+ }
109
+ }
110
+
111
+ async function handleMultiChannelRequest(channelIdsString, baseUrl, username, password, timezone) {
112
+ try {
113
+ const { channels, programmes } = await fetchAndProcessXMLTV(baseUrl, username, password);
114
+
115
+ const channelIds = channelIdsString.split(',');
116
+ const uniqueChannelIds = [...new Set(channelIds)]; // Remove duplicates
117
+
118
+ const responseData = uniqueChannelIds.map(channelId => {
119
+ const channelInfo = channels.find(channel => channel.id === channelId);
120
+ if (!channelInfo) {
121
+ return { channelId, error: 'Channel not found' };
122
+ }
123
+
124
+ const channelProgrammes = programmes.filter(programme => programme.channelId === channelId);
125
+ const { currentProgram, nextProgram } = getCurrentAndNextProgram(channelProgrammes, timezone);
126
+
127
+ return {
128
+ channel: channelInfo,
129
+ currentProgram: currentProgram,
130
+ nextProgram: nextProgram
131
+ };
132
+ });
133
+
134
+ return responseData;
135
+ } catch (error) {
136
+ console.error("Error in handleMultiChannelRequest:", error);
137
+ throw new Error('Error processing XMLTV data: ' + error.message);
138
+ }
139
+ }
140
+
141
+ async function handleChannelsListRequest(baseUrl, username, password) {
142
+ try {
143
+ const { channels } = await fetchAndProcessXMLTV(baseUrl, username, password);
144
+ return channels;
145
+ } catch (error) {
146
+ console.error("Error in handleChannelsListRequest:", error);
147
+ throw new Error('Error fetching channels list: ' + error.message);
148
+ }
149
+ }
150
+
151
+ async function getEpgInfoBatch(channelIds, baseUrl, username, password, timezone) {
152
+ try {
153
+ const { channels, programmes } = await fetchAndProcessXMLTV(baseUrl, username, password);
154
+
155
+ const results = {};
156
+ for (const channel of channelIds) {
157
+ if (!channel.epg_channel_id) {
158
+ continue;
159
+ }
160
+
161
+ const channelInfo = channels.find(c => c.id === channel.epg_channel_id);
162
+ if (!channelInfo) {
163
+ continue;
164
+ }
165
+
166
+ const channelProgrammes = programmes.filter(programme => programme.channelId === channel.epg_channel_id);
167
+ const { currentProgram, nextProgram } = getCurrentAndNextProgram(channelProgrammes, timezone);
168
+
169
+ results[channel.stream_id] = {
170
+ channel: channelInfo,
171
+ currentProgram: currentProgram,
172
+ nextProgram: nextProgram
173
+ };
174
+ }
175
+
176
+ return results;
177
+ } catch (error) {
178
+ console.error("Error in getEpgInfoBatch:", error);
179
+ throw new Error('Error processing XMLTV data: ' + error.message);
180
+ }
181
+ }
182
+
183
+ module.exports = {
184
+ handleChannelRequest,
185
+ handleChannelsListRequest,
186
+ handleMultiChannelRequest,
187
+ getEpgInfoBatch
188
+ };
views/configure.html ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Your IPTV - Stremio Addon</title>
6
+ <link rel="shortcut icon" href="./assets/logo.png" type="image/x-icon">
7
+ <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,700&display=swap" rel="stylesheet">
8
+ <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
9
+ <style>
10
+ * {
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body,
15
+ html {
16
+ margin: 0;
17
+ padding: 0;
18
+ height: 100%;
19
+ font-family: 'Open Sans', Arial, sans-serif;
20
+ color: white;
21
+ background-image: url('./assets/background.jpg');
22
+ background-size: cover;
23
+ background-position: center center;
24
+ background-repeat: no-repeat;
25
+ }
26
+
27
+ #logo {
28
+ position: absolute;
29
+ top: 20px;
30
+ right: 20px;
31
+ width: 50px; /* Adjust logo size */
32
+ height: auto;
33
+ z-index: 10;
34
+ opacity: 0.8;
35
+ }
36
+
37
+ #addon {
38
+ width: 90vh;
39
+ margin: auto;
40
+ padding: 5% 10%;
41
+ background: rgba(0, 0, 0, 0.7); /* Adjust opacity to see more background */
42
+ border-radius: 10px;
43
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
44
+ min-height: 80vh; /* Set a minimum height */
45
+ }
46
+
47
+ h1 {
48
+ font-size: 4.5vh;
49
+ font-weight: 700;
50
+ }
51
+
52
+ h2 {
53
+ font-size: 2.2vh;
54
+ font-weight: normal;
55
+ font-style: italic;
56
+ opacity: 0.8;
57
+ }
58
+
59
+ h3 {
60
+ font-size: 2.2vh;
61
+ }
62
+
63
+ h1,
64
+ h2,
65
+ h3,
66
+ p,
67
+ label {
68
+ margin: 0;
69
+ text-shadow: 0 0 1vh rgba(0, 0, 0, 0.15);
70
+ }
71
+
72
+ p {
73
+ font-size: 1.60vh;
74
+ }
75
+
76
+ ul {
77
+ font-size: 1.75vh;
78
+ margin: 0;
79
+ margin-top: 1vh;
80
+ padding-left: 3vh;
81
+ }
82
+
83
+ a {
84
+ color: lightblue;
85
+ }
86
+
87
+ a.install-link {
88
+ text-decoration: none;
89
+ }
90
+
91
+ button {
92
+ border: 0;
93
+ outline: 0;
94
+ color: white;
95
+ background: #8A5AAB;
96
+ padding: 1.2vh 3.5vh;
97
+ margin: auto;
98
+ text-align: center;
99
+ font-family: 'Open Sans', Arial, sans-serif;
100
+ font-size: 2.2vh;
101
+ font-weight: 600;
102
+ cursor: pointer;
103
+ display: block;
104
+ box-shadow: 0 0.5vh 1vh rgba(0, 0, 0, 0.2);
105
+ transition: box-shadow 0.1s ease-in-out;
106
+ }
107
+
108
+ button:hover {
109
+ box-shadow: none;
110
+ }
111
+
112
+ button:active {
113
+ box-shadow: 0 0 0 0.5vh white inset;
114
+ }
115
+
116
+ .separator {
117
+ margin-bottom: 4vh;
118
+ }
119
+
120
+ .label {
121
+ font-size: 2.2vh;
122
+ font-weight: 600;
123
+ padding: 0;
124
+ line-height: inherit;
125
+ }
126
+
127
+ .input {
128
+ height: 4.5vh;
129
+ width: 100%;
130
+ margin: auto;
131
+ margin-bottom: 10px;
132
+ padding: 6px 12px;
133
+ border-radius: 0;
134
+ outline: 0;
135
+ color: #333;
136
+ background-color: rgb(255, 255, 255);
137
+ box-shadow: 0 0.5vh 1vh rgba(0, 0, 0, 0.2);
138
+ border: 0.5vh solid #8a5aab;
139
+ }
140
+ </style>
141
+ </head>
142
+
143
+ <body>
144
+ <img src="./assets/logo.png" id="logo" alt="Logo"> <!-- Local logo -->
145
+
146
+ <div id="addon">
147
+ <h1 class="name">HY EPG IPTV</h1>
148
+ <h2 class="version">2.0.5</h2>
149
+ <h2 class="description">This addon brings all the Live Streams, VOD streams and Series from your IPTV subscription to your Stremio using Xtream API and supports IMDb IDs.</h2>
150
+ <div class="separator"></div>
151
+
152
+ <h3 class="gives">This addon has more:</h3>
153
+ <ul>
154
+ <li>Movies</li>
155
+ <li>Series</li>
156
+ <li>TV</li>
157
+ </ul>
158
+
159
+ <div class="separator"></div>
160
+
161
+ <p>ℹ️ You will need an IPTV subscription to use this addon. Free M3U lists are not supported❗<br></p>
162
+
163
+ <div class="separator"></div>
164
+
165
+ <label class="label" for="dnsport">DNS:PORT</label>
166
+ <input type="text" id="dnsport" class="input" placeholder="http://url_here.com:port">
167
+
168
+ <label class="label" for="username">Username:</label>
169
+ <input type="text" id="username" class="input" placeholder="Your Username">
170
+
171
+ <label class="label" for="password">Password:</label>
172
+ <input type="password" id="password" class="input" placeholder="Your Password">
173
+
174
+ <label class="label" for="timezone">Time Zone:</label>
175
+ <select id="timezone" class="input">
176
+ <option value="UTC">UTC</option>
177
+ <option value="America/New_York">Eastern Time (ET)</option>
178
+ <option value="America/Chicago">Central Time (CT)</option>
179
+ <option value="America/Denver">Mountain Time (MT)</option>
180
+ <option value="America/Los_Angeles">Pacific Time (PT)</option>
181
+ <option value="Europe/London">London</option>
182
+ <option value="Europe/Paris">Paris</option>
183
+ <option value="Asia/Tokyo">Tokyo</option>
184
+ </select>
185
+
186
+ <div class="separator"></div>
187
+
188
+ <a id="installLink" class="install-link" href="#">
189
+ <button onclick="generateInstallLink()" name="Install">INSTALL</button>
190
+ </a>
191
+
192
+ <div class="separator"></div>
193
+
194
+ <div id="installLinkInfo">
195
+ <p>ℹ️ If the installation button doesn't work, you can just paste the generated URL into the Stremio addon search bar:</p>
196
+ <input type="text" class="input" id="installURL" readonly>
197
+ <button onclick="generateInstallLink(); copy('installURL'); return false;" title="Copy to clipboard">📋</button>
198
+ </div>
199
+
200
+ <div class="separator"></div>
201
+ </div>
202
+
203
+ <script type="text/javascript">
204
+ function encode(userData) {
205
+ return btoa(JSON.stringify(userData)).replace(/\+/g, '-').replace(/\//g, '_').split('=')[0];
206
+ }
207
+
208
+ function copy(id) {
209
+ document.getElementById(id).select();
210
+ document.execCommand("copy");
211
+ }
212
+
213
+ function generateInstallLink() {
214
+ var BaseURL = $('#dnsport').val().trim() || null;
215
+ var username = $('#username').val().trim() || null;
216
+ var password = $('#password').val().trim() || null;
217
+ var timezone = $('#timezone').val().trim() || 'UTC';
218
+
219
+ var params = { username, password, BaseURL, timezone };
220
+ var isParametersValid = true;
221
+
222
+ if (params.BaseURL && !params.BaseURL.includes("http") && params.BaseURL.length > 0) {
223
+ isParametersValid = false;
224
+ alert("Please indicate http or https status!");
225
+ }
226
+
227
+ if (!params.username) {
228
+ isParametersValid = false;
229
+ alert("Username is missing!");
230
+ }
231
+
232
+ if (!params.password) {
233
+ isParametersValid = false;
234
+ alert("Password is missing!");
235
+ }
236
+
237
+ if (params.username && params.password && params.BaseURL && isParametersValid) {
238
+ var configuration = encode(params);
239
+ var installLink = document.getElementById('installLink');
240
+ installLink.href = 'stremio://' + window.location.host + '/' + configuration + '/manifest.json';
241
+ document.getElementById("installURL").value = window.location.protocol + "//" + window.location.host + "/" + configuration + "/manifest.json";
242
+ }
243
+ }
244
+ </script>
245
+ </body>
246
+ </html>
xtream-module.js ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+
3
+ function createXtreamModule(xtreamBaseUrl, username, password) {
4
+ const xtreamApiUrl = `${xtreamBaseUrl}/player_api.php`;
5
+
6
+ async function getDetailsFromCinemeta(ttnumber, type = 'movie') {
7
+ const url = `https://v3-cinemeta.strem.io/meta/${type}/${ttnumber}.json`;
8
+ try {
9
+ const response = await axios.get(url);
10
+ const { name: title, season, episode } = response.data.meta;
11
+ return { title, season, episode };
12
+ } catch (error) {
13
+ console.error('Error fetching data from Cinemeta:', error);
14
+ throw error;
15
+ }
16
+ }
17
+
18
+ async function getVodStreams() {
19
+ const params = { username, password, action: 'get_vod_streams' };
20
+ try {
21
+ const response = await axios.get(xtreamApiUrl, { params });
22
+ return response.data;
23
+ } catch (error) {
24
+ console.error('Error fetching VOD streams from Xtream Codes:', error);
25
+ throw error;
26
+ }
27
+ }
28
+
29
+ async function getSeries() {
30
+ const params = { username, password, action: 'get_series' };
31
+ try {
32
+ const response = await axios.get(xtreamApiUrl, { params });
33
+ return response.data;
34
+ } catch (error) {
35
+ console.error('Error fetching series from Xtream Codes:', error);
36
+ throw error;
37
+ }
38
+ }
39
+
40
+ async function getSeriesInfo(seriesId) {
41
+ const params = { username, password, action: 'get_series_info', series_id: seriesId };
42
+ try {
43
+ const response = await axios.get(xtreamApiUrl, { params });
44
+ return response.data;
45
+ } catch (error) {
46
+ console.error('Error fetching series info from Xtream Codes:', error);
47
+ throw error;
48
+ }
49
+ }
50
+
51
+ function normalizeTitle(title) {
52
+ // Remove the year and any surrounding parentheses or brackets
53
+ let normalized = title.replace(/\s*\([^)]*\)|\s*\[[^\]]*\]|\s*\d{4}$/g, '');
54
+ // Convert to lowercase and remove all non-alphanumeric characters
55
+ normalized = normalized.toLowerCase().replace(/[^a-z0-9]/g, '');
56
+ return normalized;
57
+ }
58
+
59
+ function findMatchingContent(contentList, title) {
60
+ const normalizedTitle = normalizeTitle(title);
61
+ console.log(`Searching for normalized title: ${normalizedTitle}`);
62
+
63
+ return contentList.find(item => {
64
+ const itemNormalizedTitle = normalizeTitle(item.name);
65
+ console.log(`Comparing with: ${itemNormalizedTitle}`);
66
+ return itemNormalizedTitle === normalizedTitle;
67
+ });
68
+ }
69
+
70
+ function findBestMatchingContent(contentList, title) {
71
+ const normalizedTitle = normalizeTitle(title);
72
+ console.log(`Searching for best match for normalized title: ${normalizedTitle}`);
73
+
74
+ let bestMatch = null;
75
+ let highestSimilarity = 0;
76
+
77
+ contentList.forEach(item => {
78
+ const itemNormalizedTitle = normalizeTitle(item.name);
79
+ const similarity = calculateSimilarity(normalizedTitle, itemNormalizedTitle);
80
+ console.log(`Comparing with: ${itemNormalizedTitle}, Similarity: ${similarity}`);
81
+
82
+ if (similarity > highestSimilarity) {
83
+ highestSimilarity = similarity;
84
+ bestMatch = item;
85
+ }
86
+ });
87
+
88
+ console.log(`Best match found: ${bestMatch ? bestMatch.name : 'None'} with similarity: ${highestSimilarity}`);
89
+ return highestSimilarity > 0.8 ? bestMatch : null; // Adjust threshold as needed
90
+ }
91
+
92
+ function calculateSimilarity(str1, str2) {
93
+ const len = Math.max(str1.length, str2.length);
94
+ const editDistance = levenshteinDistance(str1, str2);
95
+ return 1 - editDistance / len;
96
+ }
97
+
98
+ function levenshteinDistance(str1, str2) {
99
+ const m = str1.length;
100
+ const n = str2.length;
101
+ const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(null));
102
+
103
+ for (let i = 0; i <= m; i++) {
104
+ dp[i][0] = i;
105
+ }
106
+ for (let j = 0; j <= n; j++) {
107
+ dp[0][j] = j;
108
+ }
109
+
110
+ for (let i = 1; i <= m; i++) {
111
+ for (let j = 1; j <= n; j++) {
112
+ if (str1[i - 1] === str2[j - 1]) {
113
+ dp[i][j] = dp[i - 1][j - 1];
114
+ } else {
115
+ dp[i][j] = Math.min(
116
+ dp[i - 1][j - 1] + 1,
117
+ dp[i][j - 1] + 1,
118
+ dp[i - 1][j] + 1
119
+ );
120
+ }
121
+ }
122
+ }
123
+
124
+ return dp[m][n];
125
+ }
126
+
127
+ function buildStreamUrl(content) {
128
+ let url;
129
+ if (content.stream_type) {
130
+ // For movies
131
+ url = `${xtreamBaseUrl}/${content.stream_type}/${username}/${password}/${content.stream_id}.${content.container_extension}`;
132
+ } else if (content.id) {
133
+ // For series episodes
134
+ url = `${xtreamBaseUrl}/series/${username}/${password}/${content.id}.${content.container_extension}`;
135
+ }
136
+ console.log('Constructed stream URL:', url);
137
+ return url;
138
+ }
139
+
140
+ return async function(input) {
141
+ try {
142
+ const [ttNumber, season, episode] = input.split(':');
143
+
144
+ const type = ttNumber.startsWith('tt') ? (season && episode ? 'series' : 'movie') : 'series';
145
+
146
+ const { title } = await getDetailsFromCinemeta(ttNumber, type);
147
+ console.log(`Title from Cinemeta: ${title} (${type})`);
148
+
149
+ let contentList, matchingContent, contentInfo, specificEpisode;
150
+ if (type === 'movie') {
151
+ contentList = await getVodStreams();
152
+ matchingContent = findMatchingContent(contentList, title);
153
+ if (!matchingContent) {
154
+ console.log('Exact match not found, trying best match...');
155
+ matchingContent = findBestMatchingContent(contentList, title);
156
+ }
157
+ if (matchingContent) {
158
+ const contentUrl = buildStreamUrl(matchingContent);
159
+ return { title: matchingContent.name, contentUrl, type };
160
+ } else {
161
+ console.log(`No matching content found for movie: ${title}`);
162
+ return null;
163
+ }
164
+ } else {
165
+ contentList = await getSeries();
166
+ matchingContent = findMatchingContent(contentList, title);
167
+ if (!matchingContent) {
168
+ console.log('Exact match not found, trying best match...');
169
+ matchingContent = findBestMatchingContent(contentList, title);
170
+ }
171
+ if (matchingContent) {
172
+ contentInfo = await getSeriesInfo(matchingContent.series_id);
173
+ if (season && episode) {
174
+ specificEpisode = contentInfo.episodes[season]?.find(ep => ep.episode_num == episode);
175
+ if (specificEpisode) {
176
+ const episodeUrl = buildStreamUrl(specificEpisode);
177
+ return {
178
+ title: matchingContent.name,
179
+ type,
180
+ seriesId: matchingContent.series_id,
181
+ season,
182
+ episode,
183
+ episodeTitle: specificEpisode.title,
184
+ contentUrl: episodeUrl
185
+ };
186
+ } else {
187
+ console.log(`Episode not found: ${title} S${season}E${episode}`);
188
+ return null;
189
+ }
190
+ } else {
191
+ return {
192
+ title: matchingContent.name,
193
+ type,
194
+ seriesId: matchingContent.series_id,
195
+ seasons: contentInfo.seasons,
196
+ episodes: contentInfo.episodes
197
+ };
198
+ }
199
+ } else {
200
+ console.log(`No matching content found for series: ${title}`);
201
+ return null;
202
+ }
203
+ }
204
+ } catch (error) {
205
+ console.error('Error:', error.message);
206
+ throw error;
207
+ }
208
+ };
209
+ }
210
+
211
+ module.exports = { createXtreamModule };