├── .gitignore ├── Dockerfile ├── README.md ├── lib ├── anime_parser.js ├── api.js ├── helpers │ ├── extractors │ │ ├── fembed.js │ │ ├── goload.js │ │ └── streamsb.js │ └── random.js ├── types │ └── index.d.ts └── utils.js ├── package-lock.json ├── package.json ├── render.yaml └── vercel.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16 as builder 2 | 3 | LABEL version="1.0.0" 4 | LABEL description="anime API docker image" 5 | LABEL org.opencontainers.image.source https://github.com/kirixenyt/anime-api 6 | 7 | # update packages, to reduce risk of vulnerabilities 8 | RUN apt-get update && apt-get upgrade -y && apt-get autoclean -y && apt-get autoremove -y 9 | 10 | # set a non privileged user to use when running this image 11 | RUN groupadd -r nodejs && useradd -g nodejs -s /bin/bash -d /home/nodejs -m nodejs 12 | USER nodejs 13 | # set right (secure) folder permissions 14 | RUN mkdir -p /home/nodejs/app/node_modules && chown -R nodejs:nodejs /home/nodejs/app 15 | 16 | WORKDIR /home/nodejs/app 17 | 18 | # set default node env 19 | ARG NODE_ENV=development 20 | ARG PORT=3000 21 | # ARG NODE_ENV=production 22 | # to be able to run tests (for example in CI), do not set production as environment 23 | ENV NODE_ENV=${NODE_ENV} 24 | ENV PORT=${PORT} 25 | 26 | ENV NPM_CONFIG_LOGLEVEL=warn 27 | 28 | # copy project definition/dependencies files, for better reuse of layers 29 | COPY --chown=nodejs:nodejs package*.json ./ 30 | 31 | # install dependencies here, for better reuse of layers 32 | RUN npm install && npm update && npm cache clean --force 33 | 34 | # copy all sources in the container (exclusions in .dockerignore file) 35 | COPY --chown=nodejs:nodejs . . 36 | 37 | # exposed port/s 38 | EXPOSE 3000 39 | 40 | HEALTHCHECK --interval=30s --timeout=10s --start-period=5s CMD npm run healthcheck-manual 41 | 42 | CMD [ "npm", "start" ] 43 | 44 | # end. 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Anime API 2 | 3 | 4 | ### Broken 5 | **`As you all know, Gogoanime is currently broken and doesn't update episodes anymore.`** 6 | 7 |
8 | Details 9 | Gogoanime is experiencing issues with updating episodes, which is why the API may not return the most recent content. 10 | 11 | Kindly note that no complaints be made regarding the lack of updates as I can't do anything. 12 |
13 | 14 | ### Intro 15 | 16 | Modified api of [Gogoanime-api](https://github.com/riimuru/gogoanime-api) 17 | 18 | ### Installing 19 | 20 | Clone the Repository and run 21 | 22 | 23 | ``` 24 | git clone https://github.com/kirixen/gogo-api.git 25 | cd gogo-api 26 | npm install 27 | ``` 28 | start the server with the following command: 29 | ``` 30 | npm start 31 | ``` 32 | 33 | Now the server is running on http://localhost:3000 34 | 35 | ### Render 36 | Host your own api on render using the button below. 37 | 38 | [![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/Kirixen/gogo-api) 39 | 40 | ### Vercel 41 | 42 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fkirixen%gogo-api) 43 | 44 | Note : if u have an error after clickin the above button then fork the repo and deploy it through vercel itself 45 | 46 | [![Join our Discord server!](https://invidget.switchblade.xyz/VsPXjNRcbw)](https://discord.gg/VsPXjNRcbw) 47 | 48 | -------------------------------------------------------------------------------- /lib/anime_parser.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import cheerio from 'cheerio'; 3 | 4 | import { 5 | generateEncryptAjaxParameters, 6 | decryptEncryptAjaxResponse, 7 | } from './helpers/extractors/goload.js'; 8 | import { extractStreamSB } from './helpers/extractors/streamsb.js'; 9 | import { extractFembed } from './helpers/extractors/fembed.js'; 10 | import { USER_AGENT, renameKey } from './utils.js'; 11 | 12 | const BASE_URL = 'https://gogoanime3.co'; 13 | const BASE_URL3 = 'https://anitaku.pe/home.html'; 14 | const BASE_URL2 = 'https://anitaku.pe/'; 15 | const ajax_url = 'https://ajax.gogocdn.net/'; 16 | const anime_info_url = 'https://gogoanime3.net/category/'; 17 | const anime_movies_path = '/anime-movies.html'; 18 | const popular_path = '/popular.html'; 19 | const new_season_path = '/new-season.html'; 20 | const search_path = '/search.html'; 21 | const popular_ongoing_url = `${ajax_url}ajax/page-recent-release-ongoing.html`; 22 | const recent_release_url = `${ajax_url}ajax/page-recent-release.html`; 23 | const list_episodes_url = `${ajax_url}ajax/load-list-episode`; 24 | const seasons_url = 'https://anitaku.pe/sub-category/'; 25 | 26 | const Referer = 'https://gogoplay.io/'; 27 | const goload_stream_url = 'https://embtaku.pro/streaming.php'; 28 | export const DownloadReferer = 'https://embtaku.pro/'; 29 | 30 | const disqus_iframe = (episodeId) => 31 | `https://disqus.com/embed/comments/?base=default&f=gogoanimetv&t_u=https%3A%2F%2Fgogoanime.vc%2F${episodeId}&s_o=default#version=cfefa856cbcd7efb87102e7242c9a829`; 32 | const disqus_api = (threadId, page) => 33 | `https://disqus.com/api/3.0/threads/listPostsThreaded?limit=100&thread=${threadId}&forum=gogoanimetv&order=popular&cursor=${page}:0:0&api_key=E8Uh5l5fHZ6gD8U3KycjAIAk46f68Zw7C6eW8WSjZvCLXebZ7p0r1yrYDrLilk2F`; 34 | 35 | const Genres = [ 36 | 'action', 37 | 'adventure', 38 | 'cars', 39 | 'comedy', 40 | 'crime', 41 | 'dementia', 42 | 'demons', 43 | 'drama', 44 | 'dub', 45 | 'ecchi', 46 | 'family', 47 | 'fantasy', 48 | 'game', 49 | 'gourmet', 50 | 'harem', 51 | 'hentai', 52 | 'historical', 53 | 'horror', 54 | 'josei', 55 | 'kids', 56 | 'magic', 57 | 'martial-arts', 58 | 'mecha', 59 | 'military', 60 | 'Mmusic', 61 | 'mystery', 62 | 'parody', 63 | 'police', 64 | 'psychological', 65 | 'romance', 66 | 'samurai', 67 | 'school', 68 | 'sci-fi', 69 | 'seinen', 70 | 'shoujo', 71 | 'shoujo-ai', 72 | 'shounen', 73 | 'shounen-ai', 74 | 'slice-of-life', 75 | 'space', 76 | 'sports', 77 | 'super-power', 78 | 'supernatural', 79 | 'suspense', 80 | 'thriller', 81 | 'vampire', 82 | 'yaoi', 83 | 'yuri', 84 | 'isekai', 85 | ]; 86 | 87 | const cachedDownloadLinks = {}; 88 | 89 | export const scrapeFembed = async ({ id }) => { 90 | try { 91 | const epPage = await axios.get(BASE_URL2 + id); 92 | const $ = cheerio.load(epPage.data); 93 | 94 | const server = $('.xstreamcdn > a:nth-child(1)').attr('data-video'); 95 | const serverUrl = new URL(server); 96 | 97 | const sources = await extractFembed(serverUrl.href); 98 | 99 | if (!sources) return { error: 'No sources found!! Try different source.' }; 100 | 101 | return sources; 102 | } catch (e) { 103 | return { error: e.message }; 104 | } 105 | }; 106 | 107 | export const scrapeStreamSB = async ({ id }) => { 108 | try { 109 | const epPage = await axios.get(BASE_URL2 + id); 110 | const $ = cheerio.load(epPage.data); 111 | 112 | const server = $( 113 | 'div.anime_video_body > div.anime_muti_link > ul > li.streamsb > a' 114 | ).attr('data-video'); 115 | const serverUrl = new URL(server); 116 | 117 | const res = await extractStreamSB(serverUrl.href); 118 | 119 | if (!res.stream_data) return { error: 'No sources found!! Try different source.' }; 120 | 121 | return { 122 | headers: { Referer: serverUrl.href, 'User-Agent': USER_AGENT }, 123 | data: [{ file: res.stream_data.file }, { backup: res.stream_data.backup }], 124 | }; 125 | } catch (err) { 126 | console.log(err); 127 | return { error: err.message }; 128 | } 129 | }; 130 | 131 | 132 | export const scrapeMP4 = async ({ id }) => { 133 | let sources = []; 134 | let sources_bk = []; 135 | try { 136 | let epPage, server, $, serverUrl; 137 | 138 | if (id) { 139 | epPage = await axios.get(BASE_URL2 + id); 140 | $ = cheerio.load(epPage.data); 141 | 142 | server = $('#load_anime > div > div > iframe').attr('src'); 143 | serverUrl = new URL(server); 144 | } else throw Error("Episode id not found") 145 | 146 | const goGoServerPage = await axios.get(serverUrl.href, { 147 | headers: { 'User-Agent': USER_AGENT }, 148 | }); 149 | const $$ = cheerio.load(goGoServerPage.data); 150 | 151 | const params = await generateEncryptAjaxParameters( 152 | $$, 153 | serverUrl.searchParams.get('id') 154 | ); 155 | 156 | const fetchRes = await axios.get( 157 | ` 158 | ${serverUrl.protocol}//${serverUrl.hostname}/encrypt-ajax.php?${params}`, { 159 | headers: { 160 | 'User-Agent': USER_AGENT, 161 | 'X-Requested-With': 'XMLHttpRequest', 162 | }, 163 | } 164 | ); 165 | 166 | const res = decryptEncryptAjaxResponse(fetchRes.data); 167 | 168 | if (!res.source) return { error: 'No sources found!! Try different source.' }; 169 | 170 | res.source.forEach((source) => sources.push(source)); 171 | res.source_bk.forEach((source) => sources_bk.push(source)); 172 | 173 | return { 174 | Referer: serverUrl.href, 175 | sources: sources, 176 | sources_bk: sources_bk, 177 | }; 178 | } catch (err) { 179 | return { error: err }; 180 | } 181 | }; 182 | 183 | export const scrapeSearch = async ({ list = [], keyw, page = 1 }) => { 184 | try { 185 | const searchPage = await axios.get( 186 | `${BASE_URL2 + search_path}?keyword=${keyw}&page=${page}` 187 | ); 188 | const $ = cheerio.load(searchPage.data); 189 | 190 | $('div.last_episodes > ul > li').each((i, el) => { 191 | list.push({ 192 | anime_id: $(el).find('p.name > a').attr('href').split('/')[2], 193 | name: $(el).find('p.name > a').attr('title'), 194 | img_url: $(el).find('div > a > img').attr('src'), 195 | status: $(el).find('p.released').text().trim(), 196 | }); 197 | }); 198 | 199 | if (list.length === 0) { 200 | return { error: 'No results found' }; 201 | } 202 | 203 | return list; 204 | } catch (err) { 205 | console.log(err); 206 | return { error: err }; 207 | } 208 | }; 209 | 210 | export const scrapeRecentRelease = async ({ list = [], page = 1, type = 1 }) => { 211 | try { 212 | const mainPage = await axios.get(` 213 | ${recent_release_url}?page=${page}&type=${type} 214 | `); 215 | const $ = cheerio.load(mainPage.data); 216 | 217 | $('div.last_episodes.loaddub > ul > li').each((i, el) => { 218 | list.push({ 219 | animeId: $(el).find('p.name > a').attr('href').split('/')[1].split('-episode-')[0], 220 | episodeId: $(el).find('p.name > a').attr('href').split('/')[1], 221 | name: $(el).find('p.name > a').attr('title'), 222 | episodeNum: $(el).find('p.episode').text().replace('Episode ', '').trim(), 223 | subOrDub: $(el).find('div > a > div').attr('class').replace('type ic-', ''), 224 | imgUrl: $(el).find('div > a > img').attr('src') 225 | }); 226 | }); 227 | return list; 228 | } catch (err) { 229 | console.log(err); 230 | return { error: err }; 231 | } 232 | }; 233 | 234 | 235 | 236 | export const scrapeAnimeList = async ({ list = [], page = 1 }) => { 237 | try { 238 | const AnimeList = await axios.get(`${BASE_URL2}/anime-list.html?page=${page}`); 239 | const $ = cheerio.load(AnimeList.data); 240 | 241 | $('div.anime_list_body > ul.listing > li').each((i, el) => { 242 | list.push({ 243 | animeTitle: $(el).find('a').html().replace(/"/g, ""), 244 | animeId: $(el).find('a').attr('href').replace("/category/", ""), 245 | liTitle: $(el).attr('title') 246 | }); 247 | }); 248 | return list; 249 | } catch (err) { 250 | console.log(err); 251 | return { error: err }; 252 | } 253 | }; 254 | 255 | export const scrapeAnimeAZ = async ({ list = [], aph, page = 1 }) => { 256 | try { 257 | const AnimeAZ = await axios.get(`${BASE_URL2}/anime-list-${aph}?page=${page}`); 258 | const $ = cheerio.load(AnimeAZ.data); 259 | 260 | $('div.anime_list_body > ul.listing > li').each((i, el) => { 261 | list.push({ 262 | animeTitle: $(el).find('a').html().replace(/"/g, ""), 263 | animeId: $(el).find('a').attr('href').replace("/category/", ""), 264 | liTitle: $(el).attr('title') 265 | }); 266 | }); 267 | return list; 268 | } catch (err) { 269 | console.log(err); 270 | return { error: err }; 271 | } 272 | }; 273 | 274 | export const scrapeRecentlyAdded = async ({ list = [], page = 1 }) => { 275 | try { 276 | const RecentlyAdded = await axios.get(`${BASE_URL3}?page=${page}`); 277 | const $ = cheerio.load(RecentlyAdded.data); 278 | 279 | $('div.added_series_body.final ul.listing li').each((i, el) => { 280 | list.push({ 281 | animeId: $(el).find('a').attr('href').split('/')[2], 282 | animeName: $(el).find('a').text() 283 | }); 284 | }); 285 | return list; 286 | } catch (err) { 287 | console.log(err); 288 | return { error: err }; 289 | } 290 | }; 291 | 292 | export const scrapeOngoingSeries = async ({ list = [], page = 1 }) => { 293 | try { 294 | const OngoingSeries = await axios.get(`${BASE_URL3}?page=${page}`); 295 | const $ = cheerio.load(OngoingSeries.data); 296 | 297 | $('nav.menu_series.cron ul li').each((i, el) => { 298 | list.push({ 299 | animeId: $(el).find('a').attr('href').split('/')[2], 300 | animeName: $(el).find('a').text() 301 | }); 302 | }); 303 | return list; 304 | } catch (err) { 305 | console.log(err); 306 | return { error: err }; 307 | } 308 | }; 309 | 310 | export const scrapeNewSeason = async ({ list = [], page = 1 }) => { 311 | try { 312 | const popularPage = await axios.get(` 313 | ${BASE_URL2 + new_season_path}?page=${page} 314 | `); 315 | const $ = cheerio.load(popularPage.data); 316 | 317 | $('div.last_episodes > ul > li').each((i, el) => { 318 | list.push({ 319 | animeId: $(el).find('p.name > a').attr('href').split('/')[2], 320 | animeTitle: $(el).find('p.name > a').attr('title'), 321 | imgUrl: $(el).find('div > a > img').attr('src'), 322 | status: $(el).find('p.released').text().trim() 323 | }); 324 | }); 325 | return list; 326 | } catch (err) { 327 | console.log(err); 328 | return { error: err }; 329 | } 330 | }; 331 | 332 | export const scrapeOngoingAnime = async ({ list = [], page = 1 }) => { 333 | try { 334 | const OngoingAnime = await axios.get(`${BASE_URL2}/ongoing-anime.html?page=${page}`); 335 | const $ = cheerio.load(OngoingAnime.data); 336 | 337 | $('div.main_body div.last_episodes ul.items li').each((i, el) => { 338 | list.push({ 339 | animeId: $(el).find('p.name > a').attr('href').split('/')[2], 340 | animeTitle: $(el).find('p.name > a').attr('title'), 341 | imgUrl: $(el).find('div > a > img').attr('src'), 342 | status: $(el).find('p.released').text().trim() 343 | }); 344 | }); 345 | return list; 346 | } catch (err) { 347 | console.log(err); 348 | return { error: err }; 349 | } 350 | }; 351 | 352 | export const scrapeCompletedAnime = async ({ list = [], page = 1 }) => { 353 | try { 354 | const CompletedAnime = await axios.get(`${BASE_URL2}/completed-anime.html?page=${page}`); 355 | const $ = cheerio.load(CompletedAnime.data); 356 | 357 | $('div.main_body div.last_episodes ul.items li').each((i, el) => { 358 | list.push({ 359 | animeId: $(el).find('p.name > a').attr('href').split('/')[2], 360 | animeTitle: $(el).find('p.name > a').attr('title'), 361 | imgUrl: $(el).find('div > a > img').attr('src'), 362 | status: $(el).find('p.released').text().trim() 363 | }); 364 | }); 365 | return list; 366 | } catch (err) { 367 | console.log(err); 368 | return { error: err }; 369 | } 370 | }; 371 | 372 | export const scrapePopularAnime = async ({ list = [], page = 1 }) => { 373 | try { 374 | const popularPage = await axios.get(` 375 | ${BASE_URL2 + popular_path}?page=${page} 376 | `); 377 | const $ = cheerio.load(popularPage.data); 378 | 379 | $('div.last_episodes > ul > li').each((i, el) => { 380 | list.push({ 381 | animeId: $(el).find('p.name > a').attr('href').split('/')[2], 382 | animeTitle: $(el).find('p.name > a').attr('title'), 383 | imgUrl: $(el).find('div > a > img').attr('src'), 384 | status: $(el).find('p.released').text().trim() 385 | }); 386 | }); 387 | return list; 388 | } catch (err) { 389 | console.log(err); 390 | return { error: err }; 391 | } 392 | }; 393 | 394 | export const scrapeAnimeMovies = async ({ list = [], aph = '', page = 1 }) => { 395 | try { 396 | const popularPage = await axios.get(` 397 | ${BASE_URL2 + anime_movies_path}?aph=${aph.trim().toUpperCase()}&page=${page} 398 | `); 399 | const $ = cheerio.load(popularPage.data); 400 | 401 | $('div.last_episodes > ul > li').each((i, el) => { 402 | list.push({ 403 | animeId: $(el).find('p.name > a').attr('href').split('/')[2], 404 | animeTitle: $(el).find('p.name > a').attr('title'), 405 | imgUrl: $(el).find('div > a > img').attr('src'), 406 | status: $(el).find('p.released').text().trim(), 407 | }); 408 | }); 409 | return list; 410 | } catch (err) { 411 | console.log(err); 412 | return { error: err }; 413 | } 414 | }; 415 | 416 | export const scrapeTopAiringAnime = async ({ list = [], page = 1 }) => { 417 | try { 418 | if (page == -1) { 419 | let pageNum = 1; 420 | let hasMore = true; 421 | while (hasMore) { 422 | const popular_page = await axios.get(` 423 | ${popular_ongoing_url}?page=${pageNum} 424 | `); 425 | const $ = cheerio.load(popular_page.data); 426 | 427 | if ($('div.added_series_body.popular > ul > li').length == 0) { 428 | hasMore = false; 429 | continue; 430 | } 431 | $('div.added_series_body.popular > ul > li').each((i, el) => { 432 | let genres = []; 433 | $(el) 434 | .find('p.genres > a') 435 | .each((i, el) => { 436 | genres.push($(el).attr('title')); 437 | }); 438 | list.push({ 439 | animeId: $(el).find('a:nth-child(1)').attr('href').split('/')[2], 440 | animeTitle: $(el).find('a:nth-child(1)').attr('title'), 441 | animeImg: $(el) 442 | .find('a:nth-child(1) > div') 443 | .attr('style') 444 | .match('(https?://.*.(?:png|jpg))')[0], 445 | latestEp: $(el).find('p:nth-child(4) > a').text().trim(), 446 | animeUrl: BASE_URL2 + '/' + $(el).find('a:nth-child(1)').attr('href'), 447 | genres: genres, 448 | }); 449 | }); 450 | pageNum++; 451 | } 452 | return list; 453 | } 454 | 455 | const popular_page = await axios.get(` 456 | ${popular_ongoing_url}?page=${page} 457 | `); 458 | const $ = cheerio.load(popular_page.data); 459 | 460 | $('div.added_series_body.popular > ul > li').each((i, el) => { 461 | let genres = []; 462 | $(el) 463 | .find('p.genres > a') 464 | .each((i, el) => { 465 | genres.push($(el).attr('title')); 466 | }); 467 | list.push({ 468 | animeId: $(el).find('a:nth-child(1)').attr('href').split('/')[2], 469 | animeTitle: $(el).find('a:nth-child(1)').attr('title'), 470 | animeImg: $(el) 471 | .find('a:nth-child(1) > div') 472 | .attr('style') 473 | .match('(https?://.*.(?:png|jpg))')[0], 474 | latestEp: $(el).find('p:nth-child(4) > a').text().trim(), 475 | animeUrl: BASE_URL2 + '/' + $(el).find('a:nth-child(1)').attr('href'), 476 | genres: genres, 477 | }); 478 | }); 479 | 480 | return list; 481 | } catch (err) { 482 | console.log(err); 483 | return { error: err }; 484 | } 485 | }; 486 | 487 | export const scrapeGenre = async ({ list = [], genre, page = 1 }) => { 488 | try { 489 | genre = genre.trim().replace(/ /g, '-').toLowerCase(); 490 | 491 | if (Genres.indexOf(genre) > -1) { 492 | const genrePage = await axios.get(`${BASE_URL2}genre/${genre}?page=${page}`); 493 | const $ = cheerio.load(genrePage.data); 494 | 495 | $('div.last_episodes > ul > li').each((i, elem) => { 496 | list.push({ 497 | animeId: $(elem).find('p.name > a').attr('href').split('/')[2], 498 | animeTitle: $(elem).find('p.name > a').attr('title'), 499 | animeImg: $(elem).find('div > a > img').attr('src'), 500 | releasedDate: $(elem).find('p.released').text().trim(), 501 | animeUrl: BASE_URL2 + '/' + $(elem).find('p.name > a').attr('href'), 502 | }); 503 | }); 504 | return list; 505 | } 506 | return { error: 'Genre Not Found' }; 507 | } catch (err) { 508 | console.log(err); 509 | return { error: err }; 510 | } 511 | }; 512 | 513 | // scrapeGenre({ genre: "cars", page: 1 }).then((res) => console.log(res)) 514 | 515 | /** 516 | * @param {string} id anime id. 517 | * @returns Resolves when the scraping is complete. 518 | * @example 519 | * scrapeGoGoAnimeInfo({id: "naruto"}) 520 | * .then((res) => console.log(res)) // => The anime information is returned in an Object. 521 | * .catch((err) => console.log(err)) 522 | * 523 | */ 524 | export const scrapeAnimeDetails = async ({ id }) => { 525 | try { 526 | let epList = []; 527 | 528 | const animePageTest = await axios.get(`https://anitaku.pe/category/${id}`); 529 | 530 | const $ = cheerio.load(animePageTest.data); 531 | 532 | const animeTitle = $('div.anime_info_body_bg > h1').text(); 533 | const animeImage = $('div.anime_info_body_bg > img').attr('src'); 534 | const type = $('div.anime_info_body_bg > p.type > a').first().text(); 535 | const synopsis = $('div.anime_info_body_bg > div.description') 536 | .map((i, el) => { 537 | const content = $(el).find('p').length > 0 538 | ? $(el).find('p').map((i, p) => $(p).text()).get().join(' ') 539 | : $(el).text(); 540 | return content; 541 | }) 542 | .get() 543 | .join(' ') 544 | .replace('Plot Summary: ', ''); 545 | const genres = $('div.anime_info_body_bg > p.type:contains("Genre") > a') 546 | .map((i, el) => $(el).text()) 547 | .get() 548 | .join(', '); 549 | const releasedDate = $('div.anime_info_body_bg > p.type:contains("Released")') 550 | .text() 551 | .replace('Released: ', ''); 552 | const status = $('div.anime_info_body_bg > p:nth-child(9) > a').text(); 553 | const otherName = $('div.anime_info_body_bg > p:nth-child(10) > a') 554 | .text() 555 | .replace('Other name: ', '') 556 | .replace(/;/g, ','); 557 | 558 | $('div.anime_info_body_bg > p:nth-child(6) > a').each((i, elem) => { 559 | genres.push($(elem).attr('title').trim()); 560 | }); 561 | 562 | const ep_start = $('#episode_page > li').first().find('a').attr('ep_start'); 563 | const ep_end = $('#episode_page > li').last().find('a').attr('ep_end'); 564 | const movie_id = $('#movie_id').attr('value'); 565 | const alias = $('#alias_anime').attr('value'); 566 | const episode_info_html = $('div.anime_info_episodes_next').html(); 567 | const episode_page = $('ul#episode_page').html(); 568 | 569 | const html = await axios.get( 570 | `${list_episodes_url}?ep_start=${ep_start}&ep_end=${ep_end}&id=${movie_id}&default_ep=${0}&alias=${alias}` 571 | ); 572 | const $$ = cheerio.load(html.data); 573 | 574 | $$('#episode_related > li').each((i, el) => { 575 | epList.push({ 576 | episodeId: $(el).find('a').attr('href').split('/')[1], 577 | episodeNum: $(el).find(`div.name`).text().replace('EP ', ''), 578 | }); 579 | }); 580 | 581 | return { 582 | name: animeTitle.toString(), 583 | type: type.toString(), 584 | released: releasedDate.toString(), 585 | status: status.toString(), 586 | genres: genres, 587 | othername: otherName, 588 | synopsis: synopsis.toString(), 589 | imageUrl: animeImage.toString(), 590 | totalEpisodes: ep_end, 591 | episode_id: epList.reverse(), 592 | episode_info_html: episode_info_html.trim(), 593 | episode_page: episode_page.toString().trim(), 594 | }; 595 | } catch (err) { 596 | console.log(err); 597 | return { error: err }; 598 | } 599 | }; 600 | 601 | export const scrapeSeason = async ({ list = [], season, page = 1 }) => { 602 | try { 603 | const season_page = await axios.get(`${seasons_url}${season}?page=${page}`); 604 | const $ = cheerio.load(season_page.data); 605 | 606 | $('div.last_episodes > ul > li').each((i, el) => { 607 | list.push({ 608 | animeId: $(el).find('div > a').attr('href').split('/')[2], 609 | animeTitle: $(el).find('div > a').attr('title'), 610 | imgUrl: $(el).find('div > a > img').attr('src'), 611 | status: $(el).find('p.released').html().trim(), 612 | }); 613 | }); 614 | 615 | return list; 616 | } catch (err) { 617 | console.log(err); 618 | return { error: err }; 619 | } 620 | }; 621 | 622 | export const scrapeThread = async ({ episodeId, page = 0 }) => { 623 | try { 624 | let threadId = null; 625 | 626 | const thread_page = await axios.get(disqus_iframe(decodeURIComponent(episodeId))); 627 | const $ = cheerio.load(thread_page.data, { xmlMode: true }); 628 | 629 | const thread = JSON.parse($('#disqus-threadData')[0].children[0].data); 630 | 631 | if (thread.code === 0 && thread.cursor.total > 0) { 632 | threadId = thread.response.thread.id; 633 | } 634 | 635 | const thread_api_res = (await axios.get(disqus_api(threadId, page))).data; 636 | 637 | return { 638 | threadId: threadId, 639 | currentPage: page, 640 | hasNextPage: thread_api_res.cursor.hasNext, 641 | comments: thread_api_res.response, 642 | }; 643 | } catch (err) { 644 | if (err.response.status === 400) { 645 | return { error: 'Invalid page. Try again.' }; 646 | } 647 | return { error: err }; 648 | } 649 | }; 650 | 651 | 652 | export const scrapeWatchAnime = async ({ id }) => { 653 | try { 654 | let genres = []; 655 | let epList = []; 656 | 657 | const WatchAnime = await axios.get(`https://anitaku.pe/${id}`); 658 | 659 | const $ = cheerio.load(WatchAnime.data); 660 | 661 | const anime_category = $('div.anime-info a').attr('href').replace('/category/', '') 662 | const episode_page = $('ul#episode_page').html() 663 | const movie_id = $('#movie_id').attr('value'); 664 | const alias = $('#alias_anime').attr('value'); 665 | const episode_link = $('div.play-video > iframe').attr('src') 666 | const gogoserver = $('li.vidcdn > a').attr('data-video') 667 | const streamsb = $('li.streamsb > a').attr('data-video') 668 | const xstreamcdn = $('li.xstreamcdn > a').attr('data-video') 669 | const anime_name_with_ep = $('div.title_name h2').text() 670 | const ep_num = $('div.anime_video_body > input.default_ep').attr('value') 671 | const download = $('li.dowloads a').attr('href') 672 | const nextEpText = $('div.anime_video_body_episodes_r a').text() 673 | const nextEpLink = $('div.anime_video_body_episodes_r > a').attr('href') 674 | const prevEpText = $('div.anime_video_body_episodes_l a').text() 675 | const prevEpLink = $('div.anime_video_body_episodes_l > a').attr('href') 676 | 677 | return { 678 | video: episode_link, 679 | gogoserver: gogoserver, 680 | streamsb: streamsb, 681 | xstreamcdn: xstreamcdn, 682 | animeNameWithEP: anime_name_with_ep.toString(), 683 | ep_num: ep_num, 684 | ep_download: download, 685 | anime_info: anime_category, 686 | movie_id: movie_id, 687 | alias: alias, 688 | episode_page: episode_page, 689 | nextEpText: nextEpText, 690 | nextEpLink: nextEpLink, 691 | prevEpLink: prevEpLink, 692 | prevEpText: prevEpText, 693 | 694 | }; 695 | } catch (err) { 696 | console.log(err); 697 | return { error: err }; 698 | } 699 | }; 700 | 701 | export const scrapeSearchPage = async ({ keyw, page }) => { 702 | try { 703 | const SearchPage = await axios.get(`${BASE_URL2 + search_path}?keyword=${keyw}&page=${page}`); 704 | 705 | const $ = cheerio.load(SearchPage.data); 706 | 707 | const pagination = $('ul.pagination-list').html() 708 | 709 | return { 710 | pagination: pagination.replace("selected", "active"), 711 | } 712 | } catch (err) { 713 | console.log(err); 714 | return { error: err }; 715 | } 716 | }; 717 | 718 | export const scrapePopularPage = async ({ page }) => { 719 | try { 720 | const PopularPage = await axios.get(`${BASE_URL2}/popular.html?page=${page}`); 721 | 722 | const $ = cheerio.load(PopularPage.data); 723 | 724 | const pagination = $('ul.pagination-list').html() 725 | 726 | return { 727 | pagination: pagination.replace("selected", "active"), 728 | } 729 | } catch (err) { 730 | console.log(err); 731 | return { error: err }; 732 | } 733 | }; 734 | 735 | export const scrapeCompletedPage = async ({ page }) => { 736 | try { 737 | const CompletedPage = await axios.get(`${BASE_URL2}/completed-anime.html?page=${page}`); 738 | 739 | const $ = cheerio.load(CompletedPage.data); 740 | 741 | const pagination = $('ul.pagination-list').html() 742 | 743 | return { 744 | pagination: pagination.replace("selected", "active"), 745 | } 746 | } catch (err) { 747 | console.log(err); 748 | return { error: err }; 749 | } 750 | }; 751 | 752 | export const scrapeOngoingPage = async ({ page }) => { 753 | try { 754 | const OngoingPage = await axios.get(`${BASE_URL2}/ongoing-anime.html?page=${page}`); 755 | 756 | const $ = cheerio.load(OngoingPage.data); 757 | 758 | const pagination = $('ul.pagination-list').html() 759 | 760 | return { 761 | pagination: pagination.replace("selected", "active"), 762 | } 763 | } catch (err) { 764 | console.log(err); 765 | return { error: err }; 766 | } 767 | }; 768 | 769 | export const scrapeMoviePage = async ({ page }) => { 770 | try { 771 | const MoviePage = await axios.get(`${BASE_URL2}/anime-movies.html?aph=&page=${page}`); 772 | 773 | const $ = cheerio.load(MoviePage.data); 774 | 775 | const pagination = $('ul.pagination-list').html() 776 | 777 | return { 778 | pagination: pagination.replace("selected", "active"), 779 | } 780 | } catch (err) { 781 | console.log(err); 782 | return { error: err }; 783 | } 784 | }; 785 | 786 | 787 | export const scrapeSubCategoryPage = async ({ subCategory, page }) => { 788 | try { 789 | const SubCategoryPage = await axios.get(`${BASE_URL2}/sub-category/${subCategory}?page=${page}`); 790 | 791 | const $ = cheerio.load(SubCategoryPage.data); 792 | 793 | const pagination = $('ul.pagination-list').html() 794 | 795 | return { 796 | pagination: pagination.replace("selected", "active"), 797 | } 798 | } catch (err) { 799 | console.log(err); 800 | return { error: err }; 801 | } 802 | }; 803 | 804 | export const scrapeRecentPage = async ({ page, type }) => { 805 | try { 806 | const RecentPage = await axios.get(`${recent_release_url}?page=${page}&type=${type}`); 807 | 808 | const $ = cheerio.load(RecentPage.data); 809 | 810 | const pagination = $('ul.pagination-list').html() 811 | 812 | return { 813 | pagination: pagination.replace("selected", "active"), 814 | } 815 | } catch (err) { 816 | console.log(err); 817 | return { error: err }; 818 | } 819 | }; 820 | 821 | export const scrapeNewSeasonPage = async ({ page }) => { 822 | try { 823 | const NewSeasonPage = await axios.get(`${BASE_URL2}/new-season.html?page=${page}`); 824 | 825 | const $ = cheerio.load(NewSeasonPage.data); 826 | 827 | const pagination = $('ul.pagination-list').html() 828 | 829 | return { 830 | pagination: pagination.replace("selected", "active"), 831 | } 832 | } catch (err) { 833 | console.log(err); 834 | return { error: err }; 835 | } 836 | }; 837 | 838 | export const scrapeGenrePage = async ({ genre, page }) => { 839 | try { 840 | const GenrePage = await axios.get(`${BASE_URL2}/genre/${genre}?page=${page}`); 841 | 842 | const $ = cheerio.load(GenrePage.data); 843 | 844 | const pagination = $('ul.pagination-list').html() 845 | 846 | return { 847 | pagination: pagination.replace("selected", "active"), 848 | } 849 | } catch (err) { 850 | console.log(err); 851 | return { error: err }; 852 | } 853 | }; 854 | 855 | export const scrapeAnimeListPage = async ({ page }) => { 856 | try { 857 | const AnimeListPage = await axios.get(`${BASE_URL2}/anime-list.html?page=${page}`); 858 | 859 | const $ = cheerio.load(AnimeListPage.data); 860 | 861 | const pagination = $('ul.pagination-list').html() 862 | 863 | return { 864 | pagination: pagination.replace("selected", "active"), 865 | } 866 | } catch (err) { 867 | console.log(err); 868 | return { error: err }; 869 | } 870 | }; 871 | 872 | export const scrapeAnimeAZPage = async ({ aph, page = 1 }) => { 873 | try { 874 | const AnimeAZPage = await axios.get(`${BASE_URL2}/anime-list-${aph}?page=${page}`); 875 | 876 | const $ = cheerio.load(AnimeAZPage.data); 877 | 878 | const pagination = $('ul.pagination-list').html() 879 | 880 | return { 881 | pagination: pagination.replace("selected", "active"), 882 | } 883 | } catch (err) { 884 | console.log(err); 885 | return { error: err }; 886 | } 887 | }; 888 | -------------------------------------------------------------------------------- /lib/api.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import cors from 'cors'; 3 | import axios from 'axios'; 4 | 5 | import { 6 | scrapeGenre, 7 | scrapeTopAiringAnime, 8 | scrapeAnimeMovies, 9 | scrapePopularAnime, 10 | scrapeRecentPage, 11 | scrapeOngoingSeries, 12 | scrapeAnimeList, 13 | scrapeRecentlyAdded, 14 | scrapeAnimeAZ, 15 | scrapeAnimeAZPage, 16 | scrapeNewSeason, 17 | scrapeAnimeListPage, 18 | scrapeMoviePage, 19 | scrapeGenrePage, 20 | scrapeSubCategoryPage, 21 | scrapeRecentRelease, 22 | scrapeOngoingAnime, 23 | scrapeNewSeasonPage, 24 | scrapeSearch, 25 | scrapePopularPage, 26 | scrapeSearchPage, 27 | scrapeAnimeDetails, 28 | scrapeOngoingPage, 29 | scrapeCompletedPage, 30 | scrapeSeason, 31 | scrapeCompletedAnime, 32 | scrapeMP4, 33 | scrapeStreamSB, 34 | scrapeWatchAnime, 35 | scrapeFembed, 36 | scrapeThread, 37 | DownloadReferer, 38 | } from './anime_parser.js'; 39 | 40 | const port = process.env.PORT || 3000; 41 | 42 | const corsOptions = { 43 | origin: '*', 44 | credentails: true, 45 | optionSuccessStatus: 200, 46 | port: port, 47 | }; 48 | 49 | const app = express(); 50 | 51 | app.use(cors(corsOptions)); 52 | app.use(express.json()); 53 | 54 | app.get('/', (req, res) => { 55 | res.status(200).json('WORKING'); 56 | }); 57 | 58 | app.get('/search', async (req, res) => { 59 | try { 60 | const keyw = req.query.keyw; 61 | const page = req.query.page; 62 | 63 | if (!keyw) { 64 | return res.status(400).json({ 65 | status: 400, 66 | error: 'Bad Request', 67 | message: 'Missing query parameter: keyw', 68 | }); 69 | } 70 | 71 | const data = await scrapeSearch({ keyw: keyw, page: page }); 72 | 73 | res.status(200).json(data); 74 | } catch (err) { 75 | res.status(500).json({ 76 | status: 500, 77 | error: 'Internal Error', 78 | message: err, 79 | }); 80 | } 81 | }); 82 | 83 | app.get('/getRecentlyAdded', async (req, res) => { 84 | try { 85 | const page = req.query.page; 86 | const data = await scrapeRecentlyAdded({ page: page }); 87 | 88 | res.status(200).json(data); 89 | } catch (err) { 90 | res.status(500).json({ 91 | status: 500, 92 | error: 'Internal Error', 93 | message: err, 94 | }); 95 | } 96 | }); 97 | 98 | app.get('/getOngoingSeries', async (req, res) => { 99 | try { 100 | const page = req.query.page; 101 | const data = await scrapeOngoingSeries({ page: page }); 102 | 103 | res.status(200).json(data); 104 | } catch (err) { 105 | res.status(500).json({ 106 | status: 500, 107 | error: 'Internal Error', 108 | message: err, 109 | }); 110 | } 111 | }); 112 | 113 | 114 | app.get('/searchPage', async (req, res) => { 115 | try { 116 | const keyw = req.query.keyw; 117 | const page = req.query.page; 118 | 119 | if (!keyw) { 120 | return res.status(400).json({ 121 | status: 400, 122 | error: 'Bad Request', 123 | message: 'Missing query parameter: keyw', 124 | }); 125 | } 126 | 127 | const data = await scrapeSearchPage({ keyw: keyw, page: page }); 128 | 129 | res.status(200).json(data); 130 | } catch (err) { 131 | res.status(500).json({ 132 | status: 500, 133 | error: 'Internal Error', 134 | message: err, 135 | }); 136 | } 137 | }); 138 | 139 | app.get('/genrePage', async (req, res) => { 140 | try { 141 | const genre = req.query.genre; 142 | const page = req.query.page; 143 | 144 | if (!genre) { 145 | return res.status(400).json({ 146 | status: 400, 147 | error: 'Bad Request', 148 | message: 'Missing query parameter: genre. etc: Fantasy', 149 | }); 150 | } 151 | 152 | const data = await scrapeGenrePage({ genre: genre, page: page }); 153 | 154 | res.status(200).json(data); 155 | } catch (err) { 156 | res.status(500).json({ 157 | status: 500, 158 | error: 'Internal Error', 159 | message: err, 160 | }); 161 | } 162 | }); 163 | 164 | app.get('/anime-AZ-page', async (req, res) => { 165 | try { 166 | const aph = req.query.aph 167 | const page = req.query.page; 168 | 169 | if (!aph) { 170 | return res.status(400).json({ 171 | status: 400, 172 | error: 'Bad Request', 173 | message: 'Missing query parameter: aph. etc: A', 174 | }); 175 | } 176 | 177 | const data = await scrapeAnimeAZPage({ aph: aph, page: page }); 178 | 179 | res.status(200).json(data); 180 | } catch (err) { 181 | res.status(500).json({ 182 | status: 500, 183 | error: 'Internal Error', 184 | message: err, 185 | }); 186 | } 187 | }); 188 | 189 | app.get('/anime-list-page', async (req, res) => { 190 | try { 191 | const page = req.query.page; 192 | 193 | const data = await scrapeAnimeListPage({ page: page }); 194 | 195 | res.status(200).json(data); 196 | } catch (err) { 197 | res.status(500).json({ 198 | status: 500, 199 | error: 'Internal Error', 200 | message: err, 201 | }); 202 | } 203 | }); 204 | 205 | app.get('/animeList', async (req, res) => { //Todo: Fix 206 | try { 207 | const page = req.query.page; 208 | 209 | const data = await scrapeAnimeList({ page: page }); 210 | 211 | res.status(200).json(data); 212 | } catch (err) { 213 | res.status(500).json({ 214 | status: 500, 215 | error: 'Internal Error', 216 | message: err, 217 | }); 218 | } 219 | }); 220 | 221 | app.get('/animeListAZ', async (req, res) => { 222 | try { 223 | const aph = req.query.aph; 224 | const page = req.query.page; 225 | 226 | if (!aph) { 227 | return res.status(400).json({ 228 | status: 400, 229 | error: 'Bad Request', 230 | message: 'Missing query parameter: aph. etc: A', 231 | }); 232 | } 233 | 234 | const data = await scrapeAnimeAZ({ aph: aph, page: page }); 235 | 236 | res.status(200).json(data); 237 | } catch (err) { 238 | res.status(500).json({ 239 | status: 500, 240 | error: 'Internal Error', 241 | message: err, 242 | }); 243 | } 244 | }); 245 | 246 | app.get('/popularPage', async (req, res) => { 247 | try { 248 | const page = req.query.page; 249 | 250 | const data = await scrapePopularPage({ page: page }); 251 | 252 | res.status(200).json(data); 253 | } catch (err) { 254 | res.status(500).json({ 255 | status: 500, 256 | error: 'Internal Error', 257 | message: err, 258 | }); 259 | } 260 | }); 261 | 262 | app.get('/newSeasonPage', async (req, res) => { 263 | try { 264 | const page = req.query.page; 265 | 266 | const data = await scrapeNewSeasonPage({ page: page }); 267 | 268 | res.status(200).json(data); 269 | } catch (err) { 270 | res.status(500).json({ 271 | status: 500, 272 | error: 'Internal Error', 273 | message: err, 274 | }); 275 | } 276 | }); 277 | 278 | app.get('/completedPage', async (req, res) => { 279 | try { 280 | const page = req.query.page; 281 | 282 | const data = await scrapeCompletedPage({ page: page }); 283 | 284 | res.status(200).json(data); 285 | } catch (err) { 286 | res.status(500).json({ 287 | status: 500, 288 | error: 'Internal Error', 289 | message: err, 290 | }); 291 | } 292 | }); 293 | 294 | app.get('/ongoingPage', async (req, res) => { 295 | try { 296 | const page = req.query.page; 297 | 298 | const data = await scrapeOngoingPage({ page: page }); 299 | 300 | res.status(200).json(data); 301 | } catch (err) { 302 | res.status(500).json({ 303 | status: 500, 304 | error: 'Internal Error', 305 | message: err, 306 | }); 307 | } 308 | }); 309 | 310 | app.get('/moviePage', async (req, res) => { 311 | try { 312 | const page = req.query.page; 313 | 314 | const data = await scrapeMoviePage({ page: page }); 315 | 316 | res.status(200).json(data); 317 | } catch (err) { 318 | res.status(500).json({ 319 | status: 500, 320 | error: 'Internal Error', 321 | message: err, 322 | }); 323 | } 324 | }); 325 | 326 | app.get('/subCategoryPage', async (req, res) => { //ToDo: Fix 327 | try { 328 | const page = req.query.page; 329 | const subCategory = req.query.subCategory; 330 | 331 | const data = await scrapeSubCategoryPage({ page: page, subCategory: subCategory }); 332 | 333 | res.status(200).json(data); 334 | } catch (err) { 335 | res.status(500).json({ 336 | status: 500, 337 | error: 'Internal Error', 338 | message: err, 339 | }); 340 | } 341 | }); 342 | 343 | app.get('/recent-release-page', async (req, res) => { 344 | try { 345 | const page = req.query.page; 346 | const type = req.query.type; 347 | 348 | const data = await scrapeRecentPage({ page: page, type: type }); 349 | 350 | res.status(200).json(data); 351 | } catch (err) { 352 | res.status(500).json({ 353 | status: 500, 354 | error: 'Internal Error', 355 | message: err, 356 | }); 357 | } 358 | }); 359 | 360 | app.get('/recent-release', async (req, res) => { 361 | try { 362 | const page = req.query.page; 363 | const type = req.query.type; 364 | 365 | if (!page) { 366 | return res.status(400).json({ 367 | status: 400, 368 | error: 'Bad Request', 369 | message: 'Missing query parameter: page', 370 | }); 371 | } 372 | 373 | if (!type) { 374 | return res.status(400).json({ 375 | status: 400, 376 | error: 'Bad Request', 377 | message: 'Missing query parameter: type. 1 = SUB, 2 = DUB', 378 | }); 379 | } 380 | 381 | const data = await scrapeRecentRelease({ page: page, type: type }); 382 | 383 | res.status(200).json(data); 384 | } catch (err) { 385 | res.status(500).json({ 386 | status: 500, 387 | error: 'Internal Error', 388 | message: err, 389 | }); 390 | } 391 | }); 392 | 393 | app.get('/new-season', async (req, res) => { 394 | try { 395 | const page = req.query.page; 396 | 397 | const data = await scrapeNewSeason({ page: page }); 398 | 399 | res.status(200).json(data); 400 | } catch (err) { 401 | res.status(500).json({ 402 | status: 500, 403 | error: 'Internal Error', 404 | message: err, 405 | }); 406 | } 407 | }); 408 | 409 | app.get('/ongoing-anime', async (req, res) => { 410 | try { 411 | const page = req.query.page; 412 | 413 | const data = await scrapeOngoingAnime({ page: page }); 414 | 415 | res.status(200).json(data); 416 | } catch (err) { 417 | res.status(500).json({ 418 | status: 500, 419 | error: 'Internal Error', 420 | message: err, 421 | }); 422 | } 423 | }); 424 | 425 | app.get('/completed-anime', async (req, res) => { 426 | try { 427 | const page = req.query.page; 428 | 429 | const data = await scrapeCompletedAnime({ page: page }); 430 | 431 | res.status(200).json(data); 432 | } catch (err) { 433 | res.status(500).json({ 434 | status: 500, 435 | error: 'Internal Error', 436 | message: err, 437 | }); 438 | } 439 | }); 440 | 441 | 442 | app.get('/popular', async (req, res) => { 443 | try { 444 | const page = req.query.page; 445 | 446 | const data = await scrapePopularAnime({ page: page }); 447 | 448 | res.status(200).json(data); 449 | } catch (err) { 450 | res.status(500).json({ 451 | status: 500, 452 | error: 'Internal Error', 453 | message: err, 454 | }); 455 | } 456 | }); 457 | 458 | app.get('/anime-movies', async (req, res) => { 459 | try { 460 | const page = req.query.page; 461 | const alphabet = req.query.aph; 462 | 463 | const data = await scrapeAnimeMovies({ page: page, aph: alphabet }); 464 | 465 | res.status(200).json(data); 466 | } catch (err) { 467 | res.status(500).send({ 468 | status: 500, 469 | error: 'Internal Error', 470 | message: err, 471 | }); 472 | } 473 | }); 474 | 475 | app.get('/top-airing', async (req, res) => { 476 | try { 477 | const page = req.query.page; 478 | 479 | const data = await scrapeTopAiringAnime({ page: page }); 480 | 481 | res.status(200).json(data); 482 | } catch (err) { 483 | res.status(500).send({ 484 | status: 500, 485 | error: 'Internal Error', 486 | message: err, 487 | }); 488 | } 489 | }); 490 | 491 | app.get('/season/:season', async (req, res) => { 492 | try { 493 | const page = req.query.page; 494 | const season = req.params.season; 495 | 496 | const data = await scrapeSeason({ page: page, season: season }); 497 | 498 | res.status(200).json(data); 499 | } catch (err) { 500 | res.status(500).send({ 501 | status: 500, 502 | error: 'Internal Error', 503 | message: err, php 504 | }); 505 | } 506 | }); 507 | 508 | app.get('/genre/:genre', async (req, res) => { 509 | try { 510 | const genre = req.params.genre; 511 | const page = req.query.page; 512 | 513 | const data = await scrapeGenre({ genre: genre, page: page }); 514 | 515 | res.status(200).json(data); 516 | } catch (err) { 517 | res.status(500).send({ 518 | status: 500, 519 | error: 'Internal Error', 520 | message: err, 521 | }); 522 | } 523 | }); 524 | 525 | app.get('/getAnime/:id', async (req, res) => { 526 | try { 527 | const id = req.params.id; 528 | 529 | const data = await scrapeAnimeDetails({ id: id }); 530 | 531 | res.status(200).json(data); 532 | } catch (err) { 533 | res.status(500).json({ 534 | status: 500, 535 | error: 'Internal Error', 536 | message: err, 537 | }); 538 | } 539 | }); 540 | 541 | app.get('/fembed/watch/:id', async (req, res) => { 542 | try { 543 | const id = req.params.id; 544 | 545 | //const data = await scrapeFembed({ id: id }); 546 | 547 | res.status(410).json({ message: 'Deprecated' }); 548 | } catch (err) { 549 | res.status(500).json({ 550 | status: 500, 551 | error: 'Internal Error', 552 | message: err, 553 | }); 554 | } 555 | }); 556 | 557 | 558 | app.get('/getEpisode/:id', async (req, res) => { 559 | try { 560 | const id = req.params.id; 561 | 562 | const data = await scrapeWatchAnime({ id: id }); 563 | 564 | res.status(200).json(data); 565 | } catch (err) { 566 | res.status(500).json({ 567 | status: 500, 568 | error: 'Internal Error', 569 | message: err, 570 | }); 571 | } 572 | }); 573 | 574 | 575 | 576 | 577 | app.get('/vidcdn/watch/:id', async (req, res) => { 578 | try { 579 | const id = req.params.id; 580 | 581 | const data = await scrapeMP4({ id: id }); 582 | 583 | res.status(200).json(data); 584 | } catch (err) { 585 | res.status(500).json({ 586 | status: 500, 587 | error: 'Internal Error', 588 | message: err, 589 | }); 590 | } 591 | }); 592 | 593 | 594 | app.get('/streamsb/watch/:id', async (req, res) => { 595 | try { 596 | const id = req.params.id; 597 | 598 | const data = await scrapeStreamSB({ id: id }); 599 | 600 | res.status(200).json(data); 601 | } catch (err) { 602 | res.status(500).json({ 603 | status: 500, 604 | error: 'Internal Error', 605 | message: err, 606 | }); 607 | } 608 | }); 609 | 610 | app.get('/thread/:episodeId', async (req, res) => { 611 | try { 612 | const episodeId = req.params.episodeId; 613 | const page = req.query.page; 614 | 615 | const data = await scrapeThread({ episodeId: episodeId, page: page }); 616 | 617 | res.status(200).json(data); 618 | } catch (err) { 619 | res.status(500).json({ 620 | status: 500, 621 | error: 'Internal Error', 622 | message: err, 623 | }); 624 | } 625 | }); 626 | 627 | app.get('/download-links/:episodeId', async (req, res) => { 628 | try { 629 | const episodeId = req.params.episodeId; 630 | 631 | //const data = await scrapeDownloadLinks({ episodeId: episodeId }); 632 | 633 | res.status(410).json({ message: 'Deprecated' }); 634 | } catch (err) { 635 | console.log(err); 636 | res.status(500).json({ 637 | status: 500, 638 | error: 'Internal Error', 639 | message: err, 640 | }); 641 | } 642 | }); 643 | 644 | app.get('/download', async (req, res) => { 645 | try { 646 | const downloadLink = req.rawHeaders.find( 647 | (x) => x.includes('https://') && x.includes('.mp4') 648 | ); 649 | 650 | if (!downloadLink) { 651 | return res.status(400).json({ 652 | error: 'No downloadLink provided. Make sure to add the downloadLink in the headers.', 653 | }); 654 | } 655 | 656 | await axios 657 | .get(downloadLink, { 658 | headers: { Referer: DownloadReferer }, 659 | responseType: 'stream', 660 | }) 661 | .then((stream) => { 662 | return new Promise((r, j) => { 663 | res.writeHead(200, { 664 | ...stream.headers, 665 | }); 666 | stream.data.pipe(res); 667 | }); 668 | }); 669 | 670 | return res.status(200).json('Done Downloading.'); 671 | } catch (err) { 672 | console.log(err); 673 | res.status(500).json({ 674 | status: 500, 675 | error: 'Internal Error', 676 | message: err, 677 | }); 678 | } 679 | }); 680 | 681 | app.use((req, res) => { 682 | res.status(404).json({ 683 | status: 404, 684 | error: 'Not Found', 685 | }); 686 | }); 687 | 688 | 689 | 690 | 691 | app.listen(port, () => { 692 | console.log('Express server listening on port %d in %s mode', port, app.settings.env); 693 | }); -------------------------------------------------------------------------------- /lib/helpers/extractors/fembed.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export const extractFembed = async(url) => { 4 | try { 5 | url = new URL(url); 6 | const fembedApiUrl = url.href.replace('/v/', '/api/source/'); 7 | const res = await axios.post(fembedApiUrl, { 8 | headers: { 9 | Referer: url.href, 10 | }, 11 | }); 12 | 13 | if (!res.data.success) return false; 14 | 15 | return { 16 | headers: { 17 | Referer: url.href, 18 | }, 19 | data: res.data.data, 20 | }; 21 | } catch (e) { 22 | return { error: 'No sources found!! Try different source\n\n' + e.message }; 23 | } 24 | }; -------------------------------------------------------------------------------- /lib/helpers/extractors/goload.js: -------------------------------------------------------------------------------- 1 | import CryptoJS from 'crypto-js'; 2 | 3 | const keys = { 4 | key: CryptoJS.enc.Utf8.parse('37911490979715163134003223491201'), 5 | second_key: CryptoJS.enc.Utf8.parse('54674138327930866480207815084989'), 6 | iv: CryptoJS.enc.Utf8.parse('3134003223491201'), 7 | }; 8 | 9 | /** 10 | * Parses the embedded video URL to encrypt-ajax.php parameters 11 | * @param {cheerio} $ Cheerio object of the embedded video page 12 | * @param {string} id Id of the embedded video URL 13 | */ 14 | export async function generateEncryptAjaxParameters($, id) { 15 | // encrypt the key 16 | const encrypted_key = CryptoJS.AES['encrypt'](id, keys.key, { 17 | iv: keys.iv, 18 | }); 19 | 20 | const script = $("script[data-name='episode']").data().value; 21 | const token = CryptoJS.AES['decrypt'](script, keys.key, { 22 | iv: keys.iv, 23 | }).toString(CryptoJS.enc.Utf8); 24 | 25 | return 'id=' + encrypted_key + '&alias=' + id + '&' + token; 26 | } 27 | /** 28 | * Decrypts the encrypted-ajax.php response 29 | * @param {object} obj Response from the server 30 | */ 31 | export function decryptEncryptAjaxResponse(obj) { 32 | const decrypted = CryptoJS.enc.Utf8.stringify( 33 | CryptoJS.AES.decrypt(obj.data, keys.second_key, { 34 | iv: keys.iv, 35 | }) 36 | ); 37 | return JSON.parse(decrypted); 38 | } 39 | -------------------------------------------------------------------------------- /lib/helpers/extractors/streamsb.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import { USER_AGENT } from '../../utils.js'; 4 | 5 | const HOST = 'https://sbplay2.com/sources43'; 6 | 7 | const PAYLOAD = (hex) => 8 | `7361696b6f757c7c${hex}7c7c7361696b6f757c7c73747265616d7362/7361696b6f757c7c363136653639366436343663363136653639366436343663376337633631366536393664363436633631366536393664363436633763376336313665363936643634366336313665363936643634366337633763373337343732363536313664373336327c7c7361696b6f757c7c73747265616d7362`; 9 | 10 | export const extractStreamSB = async(url) => { 11 | url = new URL(url); 12 | 13 | const id = url.href.split('/e/').pop(); 14 | let arrBytes = new TextEncoder().encode(id); 15 | 16 | const res = await axios.get(`${HOST}/${PAYLOAD(toHexString(Array.from(arrBytes)))}`, { 17 | headers: { watchsb: 'streamsb', 'User-Agent': USER_AGENT }, 18 | }); 19 | 20 | return res.data; 21 | }; 22 | 23 | function toHexString(byteArray) { 24 | return Array.from(byteArray, function(byte) { 25 | return ('0' + (byte & 0xff).toString(16)).slice(-2); 26 | }).join(''); 27 | } -------------------------------------------------------------------------------- /lib/helpers/random.js: -------------------------------------------------------------------------------- 1 | function getRandomInt(min, max) { 2 | min = Math.ceil(min); 3 | max = Math.floor(max); 4 | return Math.floor(Math.random() * (max - min + 1)) + min; 5 | } 6 | 7 | function f_random(length) { 8 | var i = length, 9 | str = ''; 10 | while (i > 0x0) { 11 | i--, (str += getRandomInt(0, 9)); 12 | } 13 | return str; 14 | } -------------------------------------------------------------------------------- /lib/types/index.d.ts: -------------------------------------------------------------------------------- 1 | export type AnimeList = { 2 | animeId?: string; 3 | animeTitle?: string; 4 | animeUrl?: string; 5 | animeImg?: string; 6 | status?: string; 7 | }; 8 | 9 | export type GogoEpisode = { 10 | episodeId?: string; 11 | episodeNum?: number | string; 12 | episodeUrl?: string; 13 | }; 14 | 15 | export type Gogoanime = { 16 | animeId?: string; 17 | type?: string; 18 | animeTitle?: string; 19 | animeImg?: string; 20 | status?: string; 21 | genres?: string[]; 22 | otherNames?: string[] | string; 23 | synopsis?: string; 24 | totalEpisodes?: number | string; 25 | episodesList?: GogoEpisode[]; 26 | }; 27 | 28 | /** 29 | * @typedef {Object} AnimeList 30 | * @param {AnimeList[]} list out put of the anime list 31 | * @param {string} keyw query keyword to search 32 | * @param {string} page current page 33 | */ 34 | export declare function scrapeSearch( 35 | list: AnimeList[] | null | undefined, 36 | keyw: string, 37 | page: number = 1 38 | ): Promise; 39 | 40 | /** 41 | * 42 | * @param animeId anime id to scrape the anime info 43 | * @returns {Gogoanime} anime info object 44 | */ 45 | export declare function scrapeAnimeDetails( 46 | animeId: string 47 | ): Promise; 48 | 49 | // TODO: add more functions 50 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | export const USER_AGENT = 2 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'; 3 | export const renameKey = (obj, oldKey, newKey) => { 4 | if (!obj.hasOwnProperty(oldKey)) return; 5 | const oldValue = obj[oldKey]; 6 | delete obj[oldKey]; 7 | obj[newKey] = oldValue; 8 | }; -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gogoanime-api", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "gogoanime-api", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "axios": "^0.27.2", 13 | "cheerio": "^1.0.0-rc.10", 14 | "cors": "^2.8.5", 15 | "crypto-js": "^4.1.1", 16 | "express": "^4.17.1" 17 | }, 18 | "devDependencies": { 19 | "nodemon": "^2.0.22" 20 | } 21 | }, 22 | "node_modules/abbrev": { 23 | "version": "1.1.1", 24 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 25 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", 26 | "dev": true 27 | }, 28 | "node_modules/accepts": { 29 | "version": "1.3.8", 30 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 31 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 32 | "dependencies": { 33 | "mime-types": "~2.1.34", 34 | "negotiator": "0.6.3" 35 | }, 36 | "engines": { 37 | "node": ">= 0.6" 38 | } 39 | }, 40 | "node_modules/anymatch": { 41 | "version": "3.1.2", 42 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 43 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 44 | "dev": true, 45 | "dependencies": { 46 | "normalize-path": "^3.0.0", 47 | "picomatch": "^2.0.4" 48 | }, 49 | "engines": { 50 | "node": ">= 8" 51 | } 52 | }, 53 | "node_modules/array-flatten": { 54 | "version": "1.1.1", 55 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 56 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 57 | }, 58 | "node_modules/asynckit": { 59 | "version": "0.4.0", 60 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 61 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 62 | }, 63 | "node_modules/axios": { 64 | "version": "0.27.2", 65 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", 66 | "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", 67 | "dependencies": { 68 | "follow-redirects": "^1.14.9", 69 | "form-data": "^4.0.0" 70 | } 71 | }, 72 | "node_modules/balanced-match": { 73 | "version": "1.0.2", 74 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 75 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 76 | "dev": true 77 | }, 78 | "node_modules/binary-extensions": { 79 | "version": "2.2.0", 80 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 81 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 82 | "dev": true, 83 | "engines": { 84 | "node": ">=8" 85 | } 86 | }, 87 | "node_modules/body-parser": { 88 | "version": "1.20.0", 89 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", 90 | "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", 91 | "dependencies": { 92 | "bytes": "3.1.2", 93 | "content-type": "~1.0.4", 94 | "debug": "2.6.9", 95 | "depd": "2.0.0", 96 | "destroy": "1.2.0", 97 | "http-errors": "2.0.0", 98 | "iconv-lite": "0.4.24", 99 | "on-finished": "2.4.1", 100 | "qs": "6.10.3", 101 | "raw-body": "2.5.1", 102 | "type-is": "~1.6.18", 103 | "unpipe": "1.0.0" 104 | }, 105 | "engines": { 106 | "node": ">= 0.8", 107 | "npm": "1.2.8000 || >= 1.4.16" 108 | } 109 | }, 110 | "node_modules/boolbase": { 111 | "version": "1.0.0", 112 | "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", 113 | "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" 114 | }, 115 | "node_modules/brace-expansion": { 116 | "version": "1.1.11", 117 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 118 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 119 | "dev": true, 120 | "dependencies": { 121 | "balanced-match": "^1.0.0", 122 | "concat-map": "0.0.1" 123 | } 124 | }, 125 | "node_modules/braces": { 126 | "version": "3.0.2", 127 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 128 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 129 | "dev": true, 130 | "dependencies": { 131 | "fill-range": "^7.0.1" 132 | }, 133 | "engines": { 134 | "node": ">=8" 135 | } 136 | }, 137 | "node_modules/bytes": { 138 | "version": "3.1.2", 139 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 140 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 141 | "engines": { 142 | "node": ">= 0.8" 143 | } 144 | }, 145 | "node_modules/call-bind": { 146 | "version": "1.0.2", 147 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 148 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 149 | "dependencies": { 150 | "function-bind": "^1.1.1", 151 | "get-intrinsic": "^1.0.2" 152 | }, 153 | "funding": { 154 | "url": "https://github.com/sponsors/ljharb" 155 | } 156 | }, 157 | "node_modules/cheerio": { 158 | "version": "1.0.0-rc.12", 159 | "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", 160 | "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", 161 | "dependencies": { 162 | "cheerio-select": "^2.1.0", 163 | "dom-serializer": "^2.0.0", 164 | "domhandler": "^5.0.3", 165 | "domutils": "^3.0.1", 166 | "htmlparser2": "^8.0.1", 167 | "parse5": "^7.0.0", 168 | "parse5-htmlparser2-tree-adapter": "^7.0.0" 169 | }, 170 | "engines": { 171 | "node": ">= 6" 172 | }, 173 | "funding": { 174 | "url": "https://github.com/cheeriojs/cheerio?sponsor=1" 175 | } 176 | }, 177 | "node_modules/cheerio-select": { 178 | "version": "2.1.0", 179 | "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", 180 | "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", 181 | "dependencies": { 182 | "boolbase": "^1.0.0", 183 | "css-select": "^5.1.0", 184 | "css-what": "^6.1.0", 185 | "domelementtype": "^2.3.0", 186 | "domhandler": "^5.0.3", 187 | "domutils": "^3.0.1" 188 | }, 189 | "funding": { 190 | "url": "https://github.com/sponsors/fb55" 191 | } 192 | }, 193 | "node_modules/chokidar": { 194 | "version": "3.5.2", 195 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", 196 | "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", 197 | "dev": true, 198 | "dependencies": { 199 | "anymatch": "~3.1.2", 200 | "braces": "~3.0.2", 201 | "glob-parent": "~5.1.2", 202 | "is-binary-path": "~2.1.0", 203 | "is-glob": "~4.0.1", 204 | "normalize-path": "~3.0.0", 205 | "readdirp": "~3.6.0" 206 | }, 207 | "engines": { 208 | "node": ">= 8.10.0" 209 | }, 210 | "optionalDependencies": { 211 | "fsevents": "~2.3.2" 212 | } 213 | }, 214 | "node_modules/combined-stream": { 215 | "version": "1.0.8", 216 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 217 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 218 | "dependencies": { 219 | "delayed-stream": "~1.0.0" 220 | }, 221 | "engines": { 222 | "node": ">= 0.8" 223 | } 224 | }, 225 | "node_modules/concat-map": { 226 | "version": "0.0.1", 227 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 228 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 229 | "dev": true 230 | }, 231 | "node_modules/content-disposition": { 232 | "version": "0.5.4", 233 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 234 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 235 | "dependencies": { 236 | "safe-buffer": "5.2.1" 237 | }, 238 | "engines": { 239 | "node": ">= 0.6" 240 | } 241 | }, 242 | "node_modules/content-type": { 243 | "version": "1.0.4", 244 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 245 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 246 | "engines": { 247 | "node": ">= 0.6" 248 | } 249 | }, 250 | "node_modules/cookie": { 251 | "version": "0.5.0", 252 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 253 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", 254 | "engines": { 255 | "node": ">= 0.6" 256 | } 257 | }, 258 | "node_modules/cookie-signature": { 259 | "version": "1.0.6", 260 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 261 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 262 | }, 263 | "node_modules/cors": { 264 | "version": "2.8.5", 265 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 266 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 267 | "dependencies": { 268 | "object-assign": "^4", 269 | "vary": "^1" 270 | }, 271 | "engines": { 272 | "node": ">= 0.10" 273 | } 274 | }, 275 | "node_modules/crypto-js": { 276 | "version": "4.1.1", 277 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", 278 | "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" 279 | }, 280 | "node_modules/css-select": { 281 | "version": "5.1.0", 282 | "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", 283 | "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", 284 | "dependencies": { 285 | "boolbase": "^1.0.0", 286 | "css-what": "^6.1.0", 287 | "domhandler": "^5.0.2", 288 | "domutils": "^3.0.1", 289 | "nth-check": "^2.0.1" 290 | }, 291 | "funding": { 292 | "url": "https://github.com/sponsors/fb55" 293 | } 294 | }, 295 | "node_modules/css-what": { 296 | "version": "6.1.0", 297 | "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", 298 | "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", 299 | "engines": { 300 | "node": ">= 6" 301 | }, 302 | "funding": { 303 | "url": "https://github.com/sponsors/fb55" 304 | } 305 | }, 306 | "node_modules/debug": { 307 | "version": "2.6.9", 308 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 309 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 310 | "dependencies": { 311 | "ms": "2.0.0" 312 | } 313 | }, 314 | "node_modules/delayed-stream": { 315 | "version": "1.0.0", 316 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 317 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 318 | "engines": { 319 | "node": ">=0.4.0" 320 | } 321 | }, 322 | "node_modules/depd": { 323 | "version": "2.0.0", 324 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 325 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 326 | "engines": { 327 | "node": ">= 0.8" 328 | } 329 | }, 330 | "node_modules/destroy": { 331 | "version": "1.2.0", 332 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 333 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 334 | "engines": { 335 | "node": ">= 0.8", 336 | "npm": "1.2.8000 || >= 1.4.16" 337 | } 338 | }, 339 | "node_modules/dom-serializer": { 340 | "version": "2.0.0", 341 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", 342 | "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", 343 | "dependencies": { 344 | "domelementtype": "^2.3.0", 345 | "domhandler": "^5.0.2", 346 | "entities": "^4.2.0" 347 | }, 348 | "funding": { 349 | "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" 350 | } 351 | }, 352 | "node_modules/domelementtype": { 353 | "version": "2.3.0", 354 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", 355 | "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", 356 | "funding": [ 357 | { 358 | "type": "github", 359 | "url": "https://github.com/sponsors/fb55" 360 | } 361 | ] 362 | }, 363 | "node_modules/domhandler": { 364 | "version": "5.0.3", 365 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", 366 | "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", 367 | "dependencies": { 368 | "domelementtype": "^2.3.0" 369 | }, 370 | "engines": { 371 | "node": ">= 4" 372 | }, 373 | "funding": { 374 | "url": "https://github.com/fb55/domhandler?sponsor=1" 375 | } 376 | }, 377 | "node_modules/domutils": { 378 | "version": "3.0.1", 379 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", 380 | "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", 381 | "dependencies": { 382 | "dom-serializer": "^2.0.0", 383 | "domelementtype": "^2.3.0", 384 | "domhandler": "^5.0.1" 385 | }, 386 | "funding": { 387 | "url": "https://github.com/fb55/domutils?sponsor=1" 388 | } 389 | }, 390 | "node_modules/ee-first": { 391 | "version": "1.1.1", 392 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 393 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 394 | }, 395 | "node_modules/encodeurl": { 396 | "version": "1.0.2", 397 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 398 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 399 | "engines": { 400 | "node": ">= 0.8" 401 | } 402 | }, 403 | "node_modules/entities": { 404 | "version": "4.3.0", 405 | "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.0.tgz", 406 | "integrity": "sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg==", 407 | "engines": { 408 | "node": ">=0.12" 409 | }, 410 | "funding": { 411 | "url": "https://github.com/fb55/entities?sponsor=1" 412 | } 413 | }, 414 | "node_modules/escape-html": { 415 | "version": "1.0.3", 416 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 417 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 418 | }, 419 | "node_modules/etag": { 420 | "version": "1.8.1", 421 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 422 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 423 | "engines": { 424 | "node": ">= 0.6" 425 | } 426 | }, 427 | "node_modules/express": { 428 | "version": "4.18.1", 429 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", 430 | "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", 431 | "dependencies": { 432 | "accepts": "~1.3.8", 433 | "array-flatten": "1.1.1", 434 | "body-parser": "1.20.0", 435 | "content-disposition": "0.5.4", 436 | "content-type": "~1.0.4", 437 | "cookie": "0.5.0", 438 | "cookie-signature": "1.0.6", 439 | "debug": "2.6.9", 440 | "depd": "2.0.0", 441 | "encodeurl": "~1.0.2", 442 | "escape-html": "~1.0.3", 443 | "etag": "~1.8.1", 444 | "finalhandler": "1.2.0", 445 | "fresh": "0.5.2", 446 | "http-errors": "2.0.0", 447 | "merge-descriptors": "1.0.1", 448 | "methods": "~1.1.2", 449 | "on-finished": "2.4.1", 450 | "parseurl": "~1.3.3", 451 | "path-to-regexp": "0.1.7", 452 | "proxy-addr": "~2.0.7", 453 | "qs": "6.10.3", 454 | "range-parser": "~1.2.1", 455 | "safe-buffer": "5.2.1", 456 | "send": "0.18.0", 457 | "serve-static": "1.15.0", 458 | "setprototypeof": "1.2.0", 459 | "statuses": "2.0.1", 460 | "type-is": "~1.6.18", 461 | "utils-merge": "1.0.1", 462 | "vary": "~1.1.2" 463 | }, 464 | "engines": { 465 | "node": ">= 0.10.0" 466 | } 467 | }, 468 | "node_modules/fill-range": { 469 | "version": "7.0.1", 470 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 471 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 472 | "dev": true, 473 | "dependencies": { 474 | "to-regex-range": "^5.0.1" 475 | }, 476 | "engines": { 477 | "node": ">=8" 478 | } 479 | }, 480 | "node_modules/finalhandler": { 481 | "version": "1.2.0", 482 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 483 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 484 | "dependencies": { 485 | "debug": "2.6.9", 486 | "encodeurl": "~1.0.2", 487 | "escape-html": "~1.0.3", 488 | "on-finished": "2.4.1", 489 | "parseurl": "~1.3.3", 490 | "statuses": "2.0.1", 491 | "unpipe": "~1.0.0" 492 | }, 493 | "engines": { 494 | "node": ">= 0.8" 495 | } 496 | }, 497 | "node_modules/follow-redirects": { 498 | "version": "1.15.1", 499 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", 500 | "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", 501 | "funding": [ 502 | { 503 | "type": "individual", 504 | "url": "https://github.com/sponsors/RubenVerborgh" 505 | } 506 | ], 507 | "engines": { 508 | "node": ">=4.0" 509 | }, 510 | "peerDependenciesMeta": { 511 | "debug": { 512 | "optional": true 513 | } 514 | } 515 | }, 516 | "node_modules/form-data": { 517 | "version": "4.0.0", 518 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 519 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 520 | "dependencies": { 521 | "asynckit": "^0.4.0", 522 | "combined-stream": "^1.0.8", 523 | "mime-types": "^2.1.12" 524 | }, 525 | "engines": { 526 | "node": ">= 6" 527 | } 528 | }, 529 | "node_modules/forwarded": { 530 | "version": "0.2.0", 531 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 532 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 533 | "engines": { 534 | "node": ">= 0.6" 535 | } 536 | }, 537 | "node_modules/fresh": { 538 | "version": "0.5.2", 539 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 540 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 541 | "engines": { 542 | "node": ">= 0.6" 543 | } 544 | }, 545 | "node_modules/fsevents": { 546 | "version": "2.3.2", 547 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 548 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 549 | "dev": true, 550 | "hasInstallScript": true, 551 | "optional": true, 552 | "os": [ 553 | "darwin" 554 | ], 555 | "engines": { 556 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 557 | } 558 | }, 559 | "node_modules/function-bind": { 560 | "version": "1.1.1", 561 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 562 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 563 | }, 564 | "node_modules/get-intrinsic": { 565 | "version": "1.1.2", 566 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", 567 | "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", 568 | "dependencies": { 569 | "function-bind": "^1.1.1", 570 | "has": "^1.0.3", 571 | "has-symbols": "^1.0.3" 572 | }, 573 | "funding": { 574 | "url": "https://github.com/sponsors/ljharb" 575 | } 576 | }, 577 | "node_modules/glob-parent": { 578 | "version": "5.1.2", 579 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 580 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 581 | "dev": true, 582 | "dependencies": { 583 | "is-glob": "^4.0.1" 584 | }, 585 | "engines": { 586 | "node": ">= 6" 587 | } 588 | }, 589 | "node_modules/has": { 590 | "version": "1.0.3", 591 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 592 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 593 | "dependencies": { 594 | "function-bind": "^1.1.1" 595 | }, 596 | "engines": { 597 | "node": ">= 0.4.0" 598 | } 599 | }, 600 | "node_modules/has-flag": { 601 | "version": "3.0.0", 602 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 603 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 604 | "dev": true, 605 | "engines": { 606 | "node": ">=4" 607 | } 608 | }, 609 | "node_modules/has-symbols": { 610 | "version": "1.0.3", 611 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 612 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 613 | "engines": { 614 | "node": ">= 0.4" 615 | }, 616 | "funding": { 617 | "url": "https://github.com/sponsors/ljharb" 618 | } 619 | }, 620 | "node_modules/htmlparser2": { 621 | "version": "8.0.1", 622 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", 623 | "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", 624 | "funding": [ 625 | "https://github.com/fb55/htmlparser2?sponsor=1", 626 | { 627 | "type": "github", 628 | "url": "https://github.com/sponsors/fb55" 629 | } 630 | ], 631 | "dependencies": { 632 | "domelementtype": "^2.3.0", 633 | "domhandler": "^5.0.2", 634 | "domutils": "^3.0.1", 635 | "entities": "^4.3.0" 636 | } 637 | }, 638 | "node_modules/http-errors": { 639 | "version": "2.0.0", 640 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 641 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 642 | "dependencies": { 643 | "depd": "2.0.0", 644 | "inherits": "2.0.4", 645 | "setprototypeof": "1.2.0", 646 | "statuses": "2.0.1", 647 | "toidentifier": "1.0.1" 648 | }, 649 | "engines": { 650 | "node": ">= 0.8" 651 | } 652 | }, 653 | "node_modules/iconv-lite": { 654 | "version": "0.4.24", 655 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 656 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 657 | "dependencies": { 658 | "safer-buffer": ">= 2.1.2 < 3" 659 | }, 660 | "engines": { 661 | "node": ">=0.10.0" 662 | } 663 | }, 664 | "node_modules/ignore-by-default": { 665 | "version": "1.0.1", 666 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 667 | "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", 668 | "dev": true 669 | }, 670 | "node_modules/inherits": { 671 | "version": "2.0.4", 672 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 673 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 674 | }, 675 | "node_modules/ipaddr.js": { 676 | "version": "1.9.1", 677 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 678 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 679 | "engines": { 680 | "node": ">= 0.10" 681 | } 682 | }, 683 | "node_modules/is-binary-path": { 684 | "version": "2.1.0", 685 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 686 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 687 | "dev": true, 688 | "dependencies": { 689 | "binary-extensions": "^2.0.0" 690 | }, 691 | "engines": { 692 | "node": ">=8" 693 | } 694 | }, 695 | "node_modules/is-extglob": { 696 | "version": "2.1.1", 697 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 698 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 699 | "dev": true, 700 | "engines": { 701 | "node": ">=0.10.0" 702 | } 703 | }, 704 | "node_modules/is-glob": { 705 | "version": "4.0.3", 706 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 707 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 708 | "dev": true, 709 | "dependencies": { 710 | "is-extglob": "^2.1.1" 711 | }, 712 | "engines": { 713 | "node": ">=0.10.0" 714 | } 715 | }, 716 | "node_modules/is-number": { 717 | "version": "7.0.0", 718 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 719 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 720 | "dev": true, 721 | "engines": { 722 | "node": ">=0.12.0" 723 | } 724 | }, 725 | "node_modules/media-typer": { 726 | "version": "0.3.0", 727 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 728 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 729 | "engines": { 730 | "node": ">= 0.6" 731 | } 732 | }, 733 | "node_modules/merge-descriptors": { 734 | "version": "1.0.1", 735 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 736 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 737 | }, 738 | "node_modules/methods": { 739 | "version": "1.1.2", 740 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 741 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", 742 | "engines": { 743 | "node": ">= 0.6" 744 | } 745 | }, 746 | "node_modules/mime": { 747 | "version": "1.6.0", 748 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 749 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 750 | "bin": { 751 | "mime": "cli.js" 752 | }, 753 | "engines": { 754 | "node": ">=4" 755 | } 756 | }, 757 | "node_modules/mime-db": { 758 | "version": "1.52.0", 759 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 760 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 761 | "engines": { 762 | "node": ">= 0.6" 763 | } 764 | }, 765 | "node_modules/mime-types": { 766 | "version": "2.1.35", 767 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 768 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 769 | "dependencies": { 770 | "mime-db": "1.52.0" 771 | }, 772 | "engines": { 773 | "node": ">= 0.6" 774 | } 775 | }, 776 | "node_modules/minimatch": { 777 | "version": "3.1.2", 778 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 779 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 780 | "dev": true, 781 | "dependencies": { 782 | "brace-expansion": "^1.1.7" 783 | }, 784 | "engines": { 785 | "node": "*" 786 | } 787 | }, 788 | "node_modules/ms": { 789 | "version": "2.0.0", 790 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 791 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 792 | }, 793 | "node_modules/negotiator": { 794 | "version": "0.6.3", 795 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 796 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 797 | "engines": { 798 | "node": ">= 0.6" 799 | } 800 | }, 801 | "node_modules/nodemon": { 802 | "version": "2.0.22", 803 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", 804 | "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", 805 | "dev": true, 806 | "dependencies": { 807 | "chokidar": "^3.5.2", 808 | "debug": "^3.2.7", 809 | "ignore-by-default": "^1.0.1", 810 | "minimatch": "^3.1.2", 811 | "pstree.remy": "^1.1.8", 812 | "semver": "^5.7.1", 813 | "simple-update-notifier": "^1.0.7", 814 | "supports-color": "^5.5.0", 815 | "touch": "^3.1.0", 816 | "undefsafe": "^2.0.5" 817 | }, 818 | "bin": { 819 | "nodemon": "bin/nodemon.js" 820 | }, 821 | "engines": { 822 | "node": ">=8.10.0" 823 | }, 824 | "funding": { 825 | "type": "opencollective", 826 | "url": "https://opencollective.com/nodemon" 827 | } 828 | }, 829 | "node_modules/nodemon/node_modules/debug": { 830 | "version": "3.2.7", 831 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 832 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 833 | "dev": true, 834 | "dependencies": { 835 | "ms": "^2.1.1" 836 | } 837 | }, 838 | "node_modules/nodemon/node_modules/ms": { 839 | "version": "2.1.3", 840 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 841 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 842 | "dev": true 843 | }, 844 | "node_modules/nopt": { 845 | "version": "1.0.10", 846 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", 847 | "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", 848 | "dev": true, 849 | "dependencies": { 850 | "abbrev": "1" 851 | }, 852 | "bin": { 853 | "nopt": "bin/nopt.js" 854 | }, 855 | "engines": { 856 | "node": "*" 857 | } 858 | }, 859 | "node_modules/normalize-path": { 860 | "version": "3.0.0", 861 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 862 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 863 | "dev": true, 864 | "engines": { 865 | "node": ">=0.10.0" 866 | } 867 | }, 868 | "node_modules/nth-check": { 869 | "version": "2.1.1", 870 | "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", 871 | "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", 872 | "dependencies": { 873 | "boolbase": "^1.0.0" 874 | }, 875 | "funding": { 876 | "url": "https://github.com/fb55/nth-check?sponsor=1" 877 | } 878 | }, 879 | "node_modules/object-assign": { 880 | "version": "4.1.1", 881 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 882 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 883 | "engines": { 884 | "node": ">=0.10.0" 885 | } 886 | }, 887 | "node_modules/object-inspect": { 888 | "version": "1.12.2", 889 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", 890 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", 891 | "funding": { 892 | "url": "https://github.com/sponsors/ljharb" 893 | } 894 | }, 895 | "node_modules/on-finished": { 896 | "version": "2.4.1", 897 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 898 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 899 | "dependencies": { 900 | "ee-first": "1.1.1" 901 | }, 902 | "engines": { 903 | "node": ">= 0.8" 904 | } 905 | }, 906 | "node_modules/parse5": { 907 | "version": "7.0.0", 908 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", 909 | "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", 910 | "dependencies": { 911 | "entities": "^4.3.0" 912 | }, 913 | "funding": { 914 | "url": "https://github.com/inikulin/parse5?sponsor=1" 915 | } 916 | }, 917 | "node_modules/parse5-htmlparser2-tree-adapter": { 918 | "version": "7.0.0", 919 | "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", 920 | "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", 921 | "dependencies": { 922 | "domhandler": "^5.0.2", 923 | "parse5": "^7.0.0" 924 | }, 925 | "funding": { 926 | "url": "https://github.com/inikulin/parse5?sponsor=1" 927 | } 928 | }, 929 | "node_modules/parseurl": { 930 | "version": "1.3.3", 931 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 932 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 933 | "engines": { 934 | "node": ">= 0.8" 935 | } 936 | }, 937 | "node_modules/path-to-regexp": { 938 | "version": "0.1.7", 939 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 940 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 941 | }, 942 | "node_modules/picomatch": { 943 | "version": "2.3.0", 944 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 945 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 946 | "dev": true, 947 | "engines": { 948 | "node": ">=8.6" 949 | }, 950 | "funding": { 951 | "url": "https://github.com/sponsors/jonschlinkert" 952 | } 953 | }, 954 | "node_modules/proxy-addr": { 955 | "version": "2.0.7", 956 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 957 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 958 | "dependencies": { 959 | "forwarded": "0.2.0", 960 | "ipaddr.js": "1.9.1" 961 | }, 962 | "engines": { 963 | "node": ">= 0.10" 964 | } 965 | }, 966 | "node_modules/pstree.remy": { 967 | "version": "1.1.8", 968 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 969 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", 970 | "dev": true 971 | }, 972 | "node_modules/qs": { 973 | "version": "6.10.3", 974 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", 975 | "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", 976 | "dependencies": { 977 | "side-channel": "^1.0.4" 978 | }, 979 | "engines": { 980 | "node": ">=0.6" 981 | }, 982 | "funding": { 983 | "url": "https://github.com/sponsors/ljharb" 984 | } 985 | }, 986 | "node_modules/range-parser": { 987 | "version": "1.2.1", 988 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 989 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 990 | "engines": { 991 | "node": ">= 0.6" 992 | } 993 | }, 994 | "node_modules/raw-body": { 995 | "version": "2.5.1", 996 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 997 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 998 | "dependencies": { 999 | "bytes": "3.1.2", 1000 | "http-errors": "2.0.0", 1001 | "iconv-lite": "0.4.24", 1002 | "unpipe": "1.0.0" 1003 | }, 1004 | "engines": { 1005 | "node": ">= 0.8" 1006 | } 1007 | }, 1008 | "node_modules/readdirp": { 1009 | "version": "3.6.0", 1010 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1011 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1012 | "dev": true, 1013 | "dependencies": { 1014 | "picomatch": "^2.2.1" 1015 | }, 1016 | "engines": { 1017 | "node": ">=8.10.0" 1018 | } 1019 | }, 1020 | "node_modules/safe-buffer": { 1021 | "version": "5.2.1", 1022 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1023 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1024 | "funding": [ 1025 | { 1026 | "type": "github", 1027 | "url": "https://github.com/sponsors/feross" 1028 | }, 1029 | { 1030 | "type": "patreon", 1031 | "url": "https://www.patreon.com/feross" 1032 | }, 1033 | { 1034 | "type": "consulting", 1035 | "url": "https://feross.org/support" 1036 | } 1037 | ] 1038 | }, 1039 | "node_modules/safer-buffer": { 1040 | "version": "2.1.2", 1041 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1042 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1043 | }, 1044 | "node_modules/semver": { 1045 | "version": "5.7.1", 1046 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1047 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1048 | "dev": true, 1049 | "bin": { 1050 | "semver": "bin/semver" 1051 | } 1052 | }, 1053 | "node_modules/send": { 1054 | "version": "0.18.0", 1055 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 1056 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 1057 | "dependencies": { 1058 | "debug": "2.6.9", 1059 | "depd": "2.0.0", 1060 | "destroy": "1.2.0", 1061 | "encodeurl": "~1.0.2", 1062 | "escape-html": "~1.0.3", 1063 | "etag": "~1.8.1", 1064 | "fresh": "0.5.2", 1065 | "http-errors": "2.0.0", 1066 | "mime": "1.6.0", 1067 | "ms": "2.1.3", 1068 | "on-finished": "2.4.1", 1069 | "range-parser": "~1.2.1", 1070 | "statuses": "2.0.1" 1071 | }, 1072 | "engines": { 1073 | "node": ">= 0.8.0" 1074 | } 1075 | }, 1076 | "node_modules/send/node_modules/ms": { 1077 | "version": "2.1.3", 1078 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1079 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1080 | }, 1081 | "node_modules/serve-static": { 1082 | "version": "1.15.0", 1083 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 1084 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 1085 | "dependencies": { 1086 | "encodeurl": "~1.0.2", 1087 | "escape-html": "~1.0.3", 1088 | "parseurl": "~1.3.3", 1089 | "send": "0.18.0" 1090 | }, 1091 | "engines": { 1092 | "node": ">= 0.8.0" 1093 | } 1094 | }, 1095 | "node_modules/setprototypeof": { 1096 | "version": "1.2.0", 1097 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1098 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1099 | }, 1100 | "node_modules/side-channel": { 1101 | "version": "1.0.4", 1102 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 1103 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 1104 | "dependencies": { 1105 | "call-bind": "^1.0.0", 1106 | "get-intrinsic": "^1.0.2", 1107 | "object-inspect": "^1.9.0" 1108 | }, 1109 | "funding": { 1110 | "url": "https://github.com/sponsors/ljharb" 1111 | } 1112 | }, 1113 | "node_modules/simple-update-notifier": { 1114 | "version": "1.0.7", 1115 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", 1116 | "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", 1117 | "dev": true, 1118 | "dependencies": { 1119 | "semver": "~7.0.0" 1120 | }, 1121 | "engines": { 1122 | "node": ">=8.10.0" 1123 | } 1124 | }, 1125 | "node_modules/simple-update-notifier/node_modules/semver": { 1126 | "version": "7.0.0", 1127 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", 1128 | "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", 1129 | "dev": true, 1130 | "bin": { 1131 | "semver": "bin/semver.js" 1132 | } 1133 | }, 1134 | "node_modules/statuses": { 1135 | "version": "2.0.1", 1136 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1137 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 1138 | "engines": { 1139 | "node": ">= 0.8" 1140 | } 1141 | }, 1142 | "node_modules/supports-color": { 1143 | "version": "5.5.0", 1144 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1145 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1146 | "dev": true, 1147 | "dependencies": { 1148 | "has-flag": "^3.0.0" 1149 | }, 1150 | "engines": { 1151 | "node": ">=4" 1152 | } 1153 | }, 1154 | "node_modules/to-regex-range": { 1155 | "version": "5.0.1", 1156 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1157 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1158 | "dev": true, 1159 | "dependencies": { 1160 | "is-number": "^7.0.0" 1161 | }, 1162 | "engines": { 1163 | "node": ">=8.0" 1164 | } 1165 | }, 1166 | "node_modules/toidentifier": { 1167 | "version": "1.0.1", 1168 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1169 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 1170 | "engines": { 1171 | "node": ">=0.6" 1172 | } 1173 | }, 1174 | "node_modules/touch": { 1175 | "version": "3.1.0", 1176 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", 1177 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", 1178 | "dev": true, 1179 | "dependencies": { 1180 | "nopt": "~1.0.10" 1181 | }, 1182 | "bin": { 1183 | "nodetouch": "bin/nodetouch.js" 1184 | } 1185 | }, 1186 | "node_modules/type-is": { 1187 | "version": "1.6.18", 1188 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1189 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1190 | "dependencies": { 1191 | "media-typer": "0.3.0", 1192 | "mime-types": "~2.1.24" 1193 | }, 1194 | "engines": { 1195 | "node": ">= 0.6" 1196 | } 1197 | }, 1198 | "node_modules/undefsafe": { 1199 | "version": "2.0.5", 1200 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 1201 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", 1202 | "dev": true 1203 | }, 1204 | "node_modules/unpipe": { 1205 | "version": "1.0.0", 1206 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1207 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 1208 | "engines": { 1209 | "node": ">= 0.8" 1210 | } 1211 | }, 1212 | "node_modules/utils-merge": { 1213 | "version": "1.0.1", 1214 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1215 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", 1216 | "engines": { 1217 | "node": ">= 0.4.0" 1218 | } 1219 | }, 1220 | "node_modules/vary": { 1221 | "version": "1.1.2", 1222 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1223 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", 1224 | "engines": { 1225 | "node": ">= 0.8" 1226 | } 1227 | } 1228 | }, 1229 | "dependencies": { 1230 | "abbrev": { 1231 | "version": "1.1.1", 1232 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 1233 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", 1234 | "dev": true 1235 | }, 1236 | "accepts": { 1237 | "version": "1.3.8", 1238 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 1239 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 1240 | "requires": { 1241 | "mime-types": "~2.1.34", 1242 | "negotiator": "0.6.3" 1243 | } 1244 | }, 1245 | "anymatch": { 1246 | "version": "3.1.2", 1247 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 1248 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 1249 | "dev": true, 1250 | "requires": { 1251 | "normalize-path": "^3.0.0", 1252 | "picomatch": "^2.0.4" 1253 | } 1254 | }, 1255 | "array-flatten": { 1256 | "version": "1.1.1", 1257 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 1258 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 1259 | }, 1260 | "asynckit": { 1261 | "version": "0.4.0", 1262 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 1263 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 1264 | }, 1265 | "axios": { 1266 | "version": "0.27.2", 1267 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", 1268 | "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", 1269 | "requires": { 1270 | "follow-redirects": "^1.14.9", 1271 | "form-data": "^4.0.0" 1272 | } 1273 | }, 1274 | "balanced-match": { 1275 | "version": "1.0.2", 1276 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1277 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 1278 | "dev": true 1279 | }, 1280 | "binary-extensions": { 1281 | "version": "2.2.0", 1282 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 1283 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 1284 | "dev": true 1285 | }, 1286 | "body-parser": { 1287 | "version": "1.20.0", 1288 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", 1289 | "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", 1290 | "requires": { 1291 | "bytes": "3.1.2", 1292 | "content-type": "~1.0.4", 1293 | "debug": "2.6.9", 1294 | "depd": "2.0.0", 1295 | "destroy": "1.2.0", 1296 | "http-errors": "2.0.0", 1297 | "iconv-lite": "0.4.24", 1298 | "on-finished": "2.4.1", 1299 | "qs": "6.10.3", 1300 | "raw-body": "2.5.1", 1301 | "type-is": "~1.6.18", 1302 | "unpipe": "1.0.0" 1303 | } 1304 | }, 1305 | "boolbase": { 1306 | "version": "1.0.0", 1307 | "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", 1308 | "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" 1309 | }, 1310 | "brace-expansion": { 1311 | "version": "1.1.11", 1312 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 1313 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1314 | "dev": true, 1315 | "requires": { 1316 | "balanced-match": "^1.0.0", 1317 | "concat-map": "0.0.1" 1318 | } 1319 | }, 1320 | "braces": { 1321 | "version": "3.0.2", 1322 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 1323 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 1324 | "dev": true, 1325 | "requires": { 1326 | "fill-range": "^7.0.1" 1327 | } 1328 | }, 1329 | "bytes": { 1330 | "version": "3.1.2", 1331 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 1332 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 1333 | }, 1334 | "call-bind": { 1335 | "version": "1.0.2", 1336 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 1337 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 1338 | "requires": { 1339 | "function-bind": "^1.1.1", 1340 | "get-intrinsic": "^1.0.2" 1341 | } 1342 | }, 1343 | "cheerio": { 1344 | "version": "1.0.0-rc.12", 1345 | "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", 1346 | "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", 1347 | "requires": { 1348 | "cheerio-select": "^2.1.0", 1349 | "dom-serializer": "^2.0.0", 1350 | "domhandler": "^5.0.3", 1351 | "domutils": "^3.0.1", 1352 | "htmlparser2": "^8.0.1", 1353 | "parse5": "^7.0.0", 1354 | "parse5-htmlparser2-tree-adapter": "^7.0.0" 1355 | } 1356 | }, 1357 | "cheerio-select": { 1358 | "version": "2.1.0", 1359 | "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", 1360 | "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", 1361 | "requires": { 1362 | "boolbase": "^1.0.0", 1363 | "css-select": "^5.1.0", 1364 | "css-what": "^6.1.0", 1365 | "domelementtype": "^2.3.0", 1366 | "domhandler": "^5.0.3", 1367 | "domutils": "^3.0.1" 1368 | } 1369 | }, 1370 | "chokidar": { 1371 | "version": "3.5.2", 1372 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", 1373 | "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", 1374 | "dev": true, 1375 | "requires": { 1376 | "anymatch": "~3.1.2", 1377 | "braces": "~3.0.2", 1378 | "fsevents": "~2.3.2", 1379 | "glob-parent": "~5.1.2", 1380 | "is-binary-path": "~2.1.0", 1381 | "is-glob": "~4.0.1", 1382 | "normalize-path": "~3.0.0", 1383 | "readdirp": "~3.6.0" 1384 | } 1385 | }, 1386 | "combined-stream": { 1387 | "version": "1.0.8", 1388 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 1389 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 1390 | "requires": { 1391 | "delayed-stream": "~1.0.0" 1392 | } 1393 | }, 1394 | "concat-map": { 1395 | "version": "0.0.1", 1396 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1397 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 1398 | "dev": true 1399 | }, 1400 | "content-disposition": { 1401 | "version": "0.5.4", 1402 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 1403 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 1404 | "requires": { 1405 | "safe-buffer": "5.2.1" 1406 | } 1407 | }, 1408 | "content-type": { 1409 | "version": "1.0.4", 1410 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 1411 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 1412 | }, 1413 | "cookie": { 1414 | "version": "0.5.0", 1415 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 1416 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" 1417 | }, 1418 | "cookie-signature": { 1419 | "version": "1.0.6", 1420 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 1421 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 1422 | }, 1423 | "cors": { 1424 | "version": "2.8.5", 1425 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 1426 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 1427 | "requires": { 1428 | "object-assign": "^4", 1429 | "vary": "^1" 1430 | } 1431 | }, 1432 | "crypto-js": { 1433 | "version": "4.1.1", 1434 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", 1435 | "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" 1436 | }, 1437 | "css-select": { 1438 | "version": "5.1.0", 1439 | "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", 1440 | "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", 1441 | "requires": { 1442 | "boolbase": "^1.0.0", 1443 | "css-what": "^6.1.0", 1444 | "domhandler": "^5.0.2", 1445 | "domutils": "^3.0.1", 1446 | "nth-check": "^2.0.1" 1447 | } 1448 | }, 1449 | "css-what": { 1450 | "version": "6.1.0", 1451 | "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", 1452 | "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" 1453 | }, 1454 | "debug": { 1455 | "version": "2.6.9", 1456 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1457 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1458 | "requires": { 1459 | "ms": "2.0.0" 1460 | } 1461 | }, 1462 | "delayed-stream": { 1463 | "version": "1.0.0", 1464 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 1465 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" 1466 | }, 1467 | "depd": { 1468 | "version": "2.0.0", 1469 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 1470 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 1471 | }, 1472 | "destroy": { 1473 | "version": "1.2.0", 1474 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 1475 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" 1476 | }, 1477 | "dom-serializer": { 1478 | "version": "2.0.0", 1479 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", 1480 | "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", 1481 | "requires": { 1482 | "domelementtype": "^2.3.0", 1483 | "domhandler": "^5.0.2", 1484 | "entities": "^4.2.0" 1485 | } 1486 | }, 1487 | "domelementtype": { 1488 | "version": "2.3.0", 1489 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", 1490 | "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" 1491 | }, 1492 | "domhandler": { 1493 | "version": "5.0.3", 1494 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", 1495 | "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", 1496 | "requires": { 1497 | "domelementtype": "^2.3.0" 1498 | } 1499 | }, 1500 | "domutils": { 1501 | "version": "3.0.1", 1502 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", 1503 | "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", 1504 | "requires": { 1505 | "dom-serializer": "^2.0.0", 1506 | "domelementtype": "^2.3.0", 1507 | "domhandler": "^5.0.1" 1508 | } 1509 | }, 1510 | "ee-first": { 1511 | "version": "1.1.1", 1512 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 1513 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 1514 | }, 1515 | "encodeurl": { 1516 | "version": "1.0.2", 1517 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 1518 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" 1519 | }, 1520 | "entities": { 1521 | "version": "4.3.0", 1522 | "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.0.tgz", 1523 | "integrity": "sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg==" 1524 | }, 1525 | "escape-html": { 1526 | "version": "1.0.3", 1527 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 1528 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 1529 | }, 1530 | "etag": { 1531 | "version": "1.8.1", 1532 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 1533 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 1534 | }, 1535 | "express": { 1536 | "version": "4.18.1", 1537 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", 1538 | "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", 1539 | "requires": { 1540 | "accepts": "~1.3.8", 1541 | "array-flatten": "1.1.1", 1542 | "body-parser": "1.20.0", 1543 | "content-disposition": "0.5.4", 1544 | "content-type": "~1.0.4", 1545 | "cookie": "0.5.0", 1546 | "cookie-signature": "1.0.6", 1547 | "debug": "2.6.9", 1548 | "depd": "2.0.0", 1549 | "encodeurl": "~1.0.2", 1550 | "escape-html": "~1.0.3", 1551 | "etag": "~1.8.1", 1552 | "finalhandler": "1.2.0", 1553 | "fresh": "0.5.2", 1554 | "http-errors": "2.0.0", 1555 | "merge-descriptors": "1.0.1", 1556 | "methods": "~1.1.2", 1557 | "on-finished": "2.4.1", 1558 | "parseurl": "~1.3.3", 1559 | "path-to-regexp": "0.1.7", 1560 | "proxy-addr": "~2.0.7", 1561 | "qs": "6.10.3", 1562 | "range-parser": "~1.2.1", 1563 | "safe-buffer": "5.2.1", 1564 | "send": "0.18.0", 1565 | "serve-static": "1.15.0", 1566 | "setprototypeof": "1.2.0", 1567 | "statuses": "2.0.1", 1568 | "type-is": "~1.6.18", 1569 | "utils-merge": "1.0.1", 1570 | "vary": "~1.1.2" 1571 | } 1572 | }, 1573 | "fill-range": { 1574 | "version": "7.0.1", 1575 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 1576 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 1577 | "dev": true, 1578 | "requires": { 1579 | "to-regex-range": "^5.0.1" 1580 | } 1581 | }, 1582 | "finalhandler": { 1583 | "version": "1.2.0", 1584 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 1585 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 1586 | "requires": { 1587 | "debug": "2.6.9", 1588 | "encodeurl": "~1.0.2", 1589 | "escape-html": "~1.0.3", 1590 | "on-finished": "2.4.1", 1591 | "parseurl": "~1.3.3", 1592 | "statuses": "2.0.1", 1593 | "unpipe": "~1.0.0" 1594 | } 1595 | }, 1596 | "follow-redirects": { 1597 | "version": "1.15.1", 1598 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", 1599 | "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==" 1600 | }, 1601 | "form-data": { 1602 | "version": "4.0.0", 1603 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 1604 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 1605 | "requires": { 1606 | "asynckit": "^0.4.0", 1607 | "combined-stream": "^1.0.8", 1608 | "mime-types": "^2.1.12" 1609 | } 1610 | }, 1611 | "forwarded": { 1612 | "version": "0.2.0", 1613 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 1614 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 1615 | }, 1616 | "fresh": { 1617 | "version": "0.5.2", 1618 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 1619 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 1620 | }, 1621 | "fsevents": { 1622 | "version": "2.3.2", 1623 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 1624 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 1625 | "dev": true, 1626 | "optional": true 1627 | }, 1628 | "function-bind": { 1629 | "version": "1.1.1", 1630 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 1631 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 1632 | }, 1633 | "get-intrinsic": { 1634 | "version": "1.1.2", 1635 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", 1636 | "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", 1637 | "requires": { 1638 | "function-bind": "^1.1.1", 1639 | "has": "^1.0.3", 1640 | "has-symbols": "^1.0.3" 1641 | } 1642 | }, 1643 | "glob-parent": { 1644 | "version": "5.1.2", 1645 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1646 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1647 | "dev": true, 1648 | "requires": { 1649 | "is-glob": "^4.0.1" 1650 | } 1651 | }, 1652 | "has": { 1653 | "version": "1.0.3", 1654 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1655 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1656 | "requires": { 1657 | "function-bind": "^1.1.1" 1658 | } 1659 | }, 1660 | "has-flag": { 1661 | "version": "3.0.0", 1662 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 1663 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 1664 | "dev": true 1665 | }, 1666 | "has-symbols": { 1667 | "version": "1.0.3", 1668 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 1669 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 1670 | }, 1671 | "htmlparser2": { 1672 | "version": "8.0.1", 1673 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", 1674 | "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", 1675 | "requires": { 1676 | "domelementtype": "^2.3.0", 1677 | "domhandler": "^5.0.2", 1678 | "domutils": "^3.0.1", 1679 | "entities": "^4.3.0" 1680 | } 1681 | }, 1682 | "http-errors": { 1683 | "version": "2.0.0", 1684 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 1685 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 1686 | "requires": { 1687 | "depd": "2.0.0", 1688 | "inherits": "2.0.4", 1689 | "setprototypeof": "1.2.0", 1690 | "statuses": "2.0.1", 1691 | "toidentifier": "1.0.1" 1692 | } 1693 | }, 1694 | "iconv-lite": { 1695 | "version": "0.4.24", 1696 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 1697 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 1698 | "requires": { 1699 | "safer-buffer": ">= 2.1.2 < 3" 1700 | } 1701 | }, 1702 | "ignore-by-default": { 1703 | "version": "1.0.1", 1704 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 1705 | "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", 1706 | "dev": true 1707 | }, 1708 | "inherits": { 1709 | "version": "2.0.4", 1710 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1711 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1712 | }, 1713 | "ipaddr.js": { 1714 | "version": "1.9.1", 1715 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 1716 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 1717 | }, 1718 | "is-binary-path": { 1719 | "version": "2.1.0", 1720 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1721 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1722 | "dev": true, 1723 | "requires": { 1724 | "binary-extensions": "^2.0.0" 1725 | } 1726 | }, 1727 | "is-extglob": { 1728 | "version": "2.1.1", 1729 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1730 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1731 | "dev": true 1732 | }, 1733 | "is-glob": { 1734 | "version": "4.0.3", 1735 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1736 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1737 | "dev": true, 1738 | "requires": { 1739 | "is-extglob": "^2.1.1" 1740 | } 1741 | }, 1742 | "is-number": { 1743 | "version": "7.0.0", 1744 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1745 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1746 | "dev": true 1747 | }, 1748 | "media-typer": { 1749 | "version": "0.3.0", 1750 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1751 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" 1752 | }, 1753 | "merge-descriptors": { 1754 | "version": "1.0.1", 1755 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 1756 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 1757 | }, 1758 | "methods": { 1759 | "version": "1.1.2", 1760 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1761 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 1762 | }, 1763 | "mime": { 1764 | "version": "1.6.0", 1765 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1766 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 1767 | }, 1768 | "mime-db": { 1769 | "version": "1.52.0", 1770 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1771 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 1772 | }, 1773 | "mime-types": { 1774 | "version": "2.1.35", 1775 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1776 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1777 | "requires": { 1778 | "mime-db": "1.52.0" 1779 | } 1780 | }, 1781 | "minimatch": { 1782 | "version": "3.1.2", 1783 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1784 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1785 | "dev": true, 1786 | "requires": { 1787 | "brace-expansion": "^1.1.7" 1788 | } 1789 | }, 1790 | "ms": { 1791 | "version": "2.0.0", 1792 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1793 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 1794 | }, 1795 | "negotiator": { 1796 | "version": "0.6.3", 1797 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 1798 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 1799 | }, 1800 | "nodemon": { 1801 | "version": "2.0.22", 1802 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", 1803 | "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", 1804 | "dev": true, 1805 | "requires": { 1806 | "chokidar": "^3.5.2", 1807 | "debug": "^3.2.7", 1808 | "ignore-by-default": "^1.0.1", 1809 | "minimatch": "^3.1.2", 1810 | "pstree.remy": "^1.1.8", 1811 | "semver": "^5.7.1", 1812 | "simple-update-notifier": "^1.0.7", 1813 | "supports-color": "^5.5.0", 1814 | "touch": "^3.1.0", 1815 | "undefsafe": "^2.0.5" 1816 | }, 1817 | "dependencies": { 1818 | "debug": { 1819 | "version": "3.2.7", 1820 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 1821 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 1822 | "dev": true, 1823 | "requires": { 1824 | "ms": "^2.1.1" 1825 | } 1826 | }, 1827 | "ms": { 1828 | "version": "2.1.3", 1829 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1830 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1831 | "dev": true 1832 | } 1833 | } 1834 | }, 1835 | "nopt": { 1836 | "version": "1.0.10", 1837 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", 1838 | "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", 1839 | "dev": true, 1840 | "requires": { 1841 | "abbrev": "1" 1842 | } 1843 | }, 1844 | "normalize-path": { 1845 | "version": "3.0.0", 1846 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1847 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1848 | "dev": true 1849 | }, 1850 | "nth-check": { 1851 | "version": "2.1.1", 1852 | "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", 1853 | "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", 1854 | "requires": { 1855 | "boolbase": "^1.0.0" 1856 | } 1857 | }, 1858 | "object-assign": { 1859 | "version": "4.1.1", 1860 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1861 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 1862 | }, 1863 | "object-inspect": { 1864 | "version": "1.12.2", 1865 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", 1866 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" 1867 | }, 1868 | "on-finished": { 1869 | "version": "2.4.1", 1870 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1871 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1872 | "requires": { 1873 | "ee-first": "1.1.1" 1874 | } 1875 | }, 1876 | "parse5": { 1877 | "version": "7.0.0", 1878 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", 1879 | "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", 1880 | "requires": { 1881 | "entities": "^4.3.0" 1882 | } 1883 | }, 1884 | "parse5-htmlparser2-tree-adapter": { 1885 | "version": "7.0.0", 1886 | "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", 1887 | "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", 1888 | "requires": { 1889 | "domhandler": "^5.0.2", 1890 | "parse5": "^7.0.0" 1891 | } 1892 | }, 1893 | "parseurl": { 1894 | "version": "1.3.3", 1895 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1896 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 1897 | }, 1898 | "path-to-regexp": { 1899 | "version": "0.1.7", 1900 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1901 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 1902 | }, 1903 | "picomatch": { 1904 | "version": "2.3.0", 1905 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 1906 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 1907 | "dev": true 1908 | }, 1909 | "proxy-addr": { 1910 | "version": "2.0.7", 1911 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1912 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1913 | "requires": { 1914 | "forwarded": "0.2.0", 1915 | "ipaddr.js": "1.9.1" 1916 | } 1917 | }, 1918 | "pstree.remy": { 1919 | "version": "1.1.8", 1920 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 1921 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", 1922 | "dev": true 1923 | }, 1924 | "qs": { 1925 | "version": "6.10.3", 1926 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", 1927 | "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", 1928 | "requires": { 1929 | "side-channel": "^1.0.4" 1930 | } 1931 | }, 1932 | "range-parser": { 1933 | "version": "1.2.1", 1934 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1935 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1936 | }, 1937 | "raw-body": { 1938 | "version": "2.5.1", 1939 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 1940 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 1941 | "requires": { 1942 | "bytes": "3.1.2", 1943 | "http-errors": "2.0.0", 1944 | "iconv-lite": "0.4.24", 1945 | "unpipe": "1.0.0" 1946 | } 1947 | }, 1948 | "readdirp": { 1949 | "version": "3.6.0", 1950 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1951 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1952 | "dev": true, 1953 | "requires": { 1954 | "picomatch": "^2.2.1" 1955 | } 1956 | }, 1957 | "safe-buffer": { 1958 | "version": "5.2.1", 1959 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1960 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1961 | }, 1962 | "safer-buffer": { 1963 | "version": "2.1.2", 1964 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1965 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1966 | }, 1967 | "semver": { 1968 | "version": "5.7.1", 1969 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1970 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1971 | "dev": true 1972 | }, 1973 | "send": { 1974 | "version": "0.18.0", 1975 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 1976 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 1977 | "requires": { 1978 | "debug": "2.6.9", 1979 | "depd": "2.0.0", 1980 | "destroy": "1.2.0", 1981 | "encodeurl": "~1.0.2", 1982 | "escape-html": "~1.0.3", 1983 | "etag": "~1.8.1", 1984 | "fresh": "0.5.2", 1985 | "http-errors": "2.0.0", 1986 | "mime": "1.6.0", 1987 | "ms": "2.1.3", 1988 | "on-finished": "2.4.1", 1989 | "range-parser": "~1.2.1", 1990 | "statuses": "2.0.1" 1991 | }, 1992 | "dependencies": { 1993 | "ms": { 1994 | "version": "2.1.3", 1995 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1996 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1997 | } 1998 | } 1999 | }, 2000 | "serve-static": { 2001 | "version": "1.15.0", 2002 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 2003 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 2004 | "requires": { 2005 | "encodeurl": "~1.0.2", 2006 | "escape-html": "~1.0.3", 2007 | "parseurl": "~1.3.3", 2008 | "send": "0.18.0" 2009 | } 2010 | }, 2011 | "setprototypeof": { 2012 | "version": "1.2.0", 2013 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 2014 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 2015 | }, 2016 | "side-channel": { 2017 | "version": "1.0.4", 2018 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 2019 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 2020 | "requires": { 2021 | "call-bind": "^1.0.0", 2022 | "get-intrinsic": "^1.0.2", 2023 | "object-inspect": "^1.9.0" 2024 | } 2025 | }, 2026 | "simple-update-notifier": { 2027 | "version": "1.0.7", 2028 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", 2029 | "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", 2030 | "dev": true, 2031 | "requires": { 2032 | "semver": "~7.0.0" 2033 | }, 2034 | "dependencies": { 2035 | "semver": { 2036 | "version": "7.0.0", 2037 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", 2038 | "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", 2039 | "dev": true 2040 | } 2041 | } 2042 | }, 2043 | "statuses": { 2044 | "version": "2.0.1", 2045 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 2046 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" 2047 | }, 2048 | "supports-color": { 2049 | "version": "5.5.0", 2050 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 2051 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 2052 | "dev": true, 2053 | "requires": { 2054 | "has-flag": "^3.0.0" 2055 | } 2056 | }, 2057 | "to-regex-range": { 2058 | "version": "5.0.1", 2059 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2060 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2061 | "dev": true, 2062 | "requires": { 2063 | "is-number": "^7.0.0" 2064 | } 2065 | }, 2066 | "toidentifier": { 2067 | "version": "1.0.1", 2068 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 2069 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 2070 | }, 2071 | "touch": { 2072 | "version": "3.1.0", 2073 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", 2074 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", 2075 | "dev": true, 2076 | "requires": { 2077 | "nopt": "~1.0.10" 2078 | } 2079 | }, 2080 | "type-is": { 2081 | "version": "1.6.18", 2082 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 2083 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 2084 | "requires": { 2085 | "media-typer": "0.3.0", 2086 | "mime-types": "~2.1.24" 2087 | } 2088 | }, 2089 | "undefsafe": { 2090 | "version": "2.0.5", 2091 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 2092 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", 2093 | "dev": true 2094 | }, 2095 | "unpipe": { 2096 | "version": "1.0.0", 2097 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 2098 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" 2099 | }, 2100 | "utils-merge": { 2101 | "version": "1.0.1", 2102 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 2103 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 2104 | }, 2105 | "vary": { 2106 | "version": "1.1.2", 2107 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 2108 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 2109 | } 2110 | } 2111 | } 2112 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gogoanime-api", 3 | "version": "1.0.0", 4 | "description": "Anime Streaming, Discovery API made with Cheerio and Express. Uses data from Gogoanime", 5 | "main": "lib/anime_parser.js", 6 | "type": "module", 7 | "types": "lib/types/index.d.ts", 8 | "scripts": { 9 | "start": "node lib/api.js", 10 | "dev": "nodemon lib/api.js", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "keywords": [ 14 | "anime", 15 | "streaming", 16 | "discovery", 17 | "api", 18 | "gogoanime" 19 | ], 20 | "author": "https://github.com/riimuru", 21 | "license": "ISC", 22 | "dependencies": { 23 | "axios": "^0.27.2", 24 | "cheerio": "^1.0.0-rc.10", 25 | "cors": "^2.8.5", 26 | "crypto-js": "^4.1.1", 27 | "express": "^4.17.1" 28 | }, 29 | "devDependencies": { 30 | "nodemon": "^2.0.22" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /render.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | - type: web 3 | name: animeapi 4 | env: docker 5 | repo: https://github.com/kirixen/gogo-api.git 6 | plan: free 7 | branch: main 8 | envVars: 9 | - key: PORT 10 | value: 3000 11 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "builds": [ 4 | { 5 | "src": "/lib/api.js", 6 | "use": "@vercel/node" 7 | } 8 | ], 9 | "routes": [ 10 | { 11 | "src": "/(.*)", 12 | "dest": "/lib/api.js" 13 | } 14 | ] 15 | } 16 | --------------------------------------------------------------------------------