mirror of
https://github.com/JustAnimeCore/HiAnime-Api.git
synced 2026-04-17 13:51:44 +00:00
feature, not a bug
This commit is contained in:
6
.env.example
Normal file
6
.env.example
Normal file
@@ -0,0 +1,6 @@
|
||||
# Origins you want to allow, use * to allow all origins (not recommended for production)
|
||||
|
||||
ALLOWED_ORIGINS=<https://site1.com>,<https://site2.com>,...
|
||||
|
||||
# Port the server will run on [OPTIONAL - default: 4444]
|
||||
PORT=4444
|
||||
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
.vscode
|
||||
node_modules
|
||||
.env
|
||||
dist
|
||||
package-lock.json
|
||||
.idea
|
||||
yarn.lock
|
||||
pnpm-lock.yaml
|
||||
17
Dockerfile
Normal file
17
Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
||||
FROM node:20-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies
|
||||
RUN apk add --no-cache git netcat-openbsd
|
||||
|
||||
# Copy package files
|
||||
COPY package.json ./
|
||||
|
||||
RUN npm install
|
||||
|
||||
# Copy the rest
|
||||
COPY . .
|
||||
|
||||
# Start app
|
||||
CMD ["npm", "start"]
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 JustAnime
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
33
package.json
Normal file
33
package.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "anime-api",
|
||||
"version": "1.0.0",
|
||||
"description": "A restful api to provide all information about anime",
|
||||
"main": "./server.js",
|
||||
"scripts": {
|
||||
"start": "node ./server.js",
|
||||
"dev": "nodemon server.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Sayan Das",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "^1.11.0",
|
||||
"bcrypt": "^6.0.0",
|
||||
"cheerio": "^1.0.0-rc.12",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"cors": "^2.8.5",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dotenv": "^17.2.0",
|
||||
"express": "^5.2.1",
|
||||
"image-pixels": "^2.2.2",
|
||||
"jsonwebtoken": "^9.0.2"
|
||||
},
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.10"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/itzzzme/anime-api.git"
|
||||
}
|
||||
}
|
||||
91
public/404.html
Normal file
91
public/404.html
Normal file
@@ -0,0 +1,91 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>404 not found!</title>
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css?family=Poppins:400,500,600,700&display=swap");
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
font-family: "Poppins", sans-serif;
|
||||
}
|
||||
body {
|
||||
height: 100vh;
|
||||
background-color: #1e1e1e;
|
||||
color: #ce9178;
|
||||
}
|
||||
#error-page {
|
||||
position: absolute;
|
||||
top: 10%;
|
||||
left: 15%;
|
||||
right: 15%;
|
||||
bottom: 10%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
#error-page .content {
|
||||
max-width: 600px;
|
||||
text-align: center;
|
||||
}
|
||||
.content img.header {
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
position: relative;
|
||||
}
|
||||
.content h4 {
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 20px;
|
||||
text-transform: uppercase;
|
||||
font-size: 2em;
|
||||
max-width: 600px;
|
||||
position: relative;
|
||||
}
|
||||
.content p {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
.content .btns {
|
||||
margin: 25px 0;
|
||||
display: inline-flex;
|
||||
}
|
||||
.content .btns a {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
text-decoration: none;
|
||||
border: 2px solid #69a6ce;
|
||||
color: #69a6ce;
|
||||
font-weight: 500;
|
||||
padding: 10px 25px;
|
||||
border-radius: 25px;
|
||||
text-transform: uppercase;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.content .btns a:hover {
|
||||
background: #69a6ce;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="error-page">
|
||||
<div class="content">
|
||||
<img class="header" data-text="404" src="https://media.tenor.com/TPvxRCmycL4AAAAi/gray-hair-big-eyes.gif"/>
|
||||
<h4 data-text="Opps! Page not found">404! Page not found :(</h4>
|
||||
<p>
|
||||
Sorry, the page you're looking for doesn't exist. If you think
|
||||
something is broken, report a problem.
|
||||
</p>
|
||||
<div class="btns">
|
||||
<a href="/">return home</a>
|
||||
<a href="https://github.com/itzzzme/anime-api" target="_blank"
|
||||
>report problem</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
public/anya.gif
Normal file
BIN
public/anya.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.0 MiB |
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
BIN
public/image.webp
Normal file
BIN
public/image.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 67 KiB |
132
public/index.html
Normal file
132
public/index.html
Normal file
@@ -0,0 +1,132 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon" />
|
||||
<title>Anime Api</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
/>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
max-height: 100vh;
|
||||
max-width: 100vw;
|
||||
background-color: #1e1e1e;
|
||||
color: #ce9178;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
grid-template-columns: 1fr;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.image-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-size: cover;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
text-align: center;
|
||||
font-family: "Gill Sans", "Gill Sans MT", Calibri, "Trebuchet MS",
|
||||
sans-serif;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#gif,
|
||||
#mirrored-gif {
|
||||
height: 300px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
#mirrored-gif {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
#pic {
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
border-radius: 50%;
|
||||
object-position: center;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.profile {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 2;
|
||||
}
|
||||
.github {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
.fa-github {
|
||||
color: grey;
|
||||
}
|
||||
a {
|
||||
font-size: 1.3rem;
|
||||
color: #7cdcfe;
|
||||
}
|
||||
@media (max-width: 700px) {
|
||||
.image-container {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Welcome to API 🎉</h1>
|
||||
<div class="profile">
|
||||
<img id="pic" src="image.webp" alt="" />
|
||||
<div class="github">
|
||||
<i class="fa fa-github" style="font-size: 36px"></i>
|
||||
<a href="https://github.com/itzzzme/anime-api" target="_blank"
|
||||
>Click here to refer docs</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="image-container">
|
||||
<img
|
||||
id="gif"
|
||||
src="./wlc.gif"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
id="mirrored-gif"
|
||||
src="./wlc.gif"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
public/pic.jpg
Normal file
BIN
public/pic.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
BIN
public/wlc.gif
Normal file
BIN
public/wlc.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 427 KiB |
13
render.yaml
Normal file
13
render.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
services:
|
||||
- type: web
|
||||
name: anime-api
|
||||
env: node
|
||||
buildCommand: npm install
|
||||
startCommand: npm start
|
||||
branch: main
|
||||
plan: free
|
||||
envVars:
|
||||
- key: NODE_ENV
|
||||
value: production
|
||||
- key: PORT
|
||||
value: 6969
|
||||
64
server.js
Normal file
64
server.js
Normal file
@@ -0,0 +1,64 @@
|
||||
import dotenv from "dotenv";
|
||||
import express from "express";
|
||||
import cors from "cors";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname } from "path";
|
||||
import { createApiRoutes } from "./src/routes/apiRoutes.js";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 4444;
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const publicDir = path.join(dirname(__filename), "public");
|
||||
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(",");
|
||||
|
||||
app.use(
|
||||
cors({
|
||||
origin: allowedOrigins?.includes("*") ? "*" : allowedOrigins || [],
|
||||
methods: ["GET"],
|
||||
})
|
||||
);
|
||||
|
||||
// Custom CORS middleware
|
||||
app.use((req, res, next) => {
|
||||
const origin = req.headers.origin;
|
||||
if (
|
||||
!allowedOrigins ||
|
||||
allowedOrigins.includes("*") ||
|
||||
(origin && allowedOrigins.includes(origin))
|
||||
) {
|
||||
res.setHeader("Access-Control-Allow-Origin", origin || "*");
|
||||
res.setHeader("Access-Control-Allow-Methods", "GET");
|
||||
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
||||
return next();
|
||||
}
|
||||
res
|
||||
.status(403)
|
||||
.json({ success: false, message: "Forbidden: Origin not allowed" });
|
||||
});
|
||||
|
||||
app.use(express.static(publicDir, { redirect: false }));
|
||||
|
||||
const jsonResponse = (res, data, status = 200) =>
|
||||
res.status(status).json({ success: true, results: data });
|
||||
|
||||
const jsonError = (res, message = "Internal server error", status = 500) =>
|
||||
res.status(status).json({ success: false, message });
|
||||
|
||||
createApiRoutes(app, jsonResponse, jsonError);
|
||||
|
||||
app.use((req, res) => {
|
||||
const filePath = path.join(publicDir, "404.html");
|
||||
if (fs.existsSync(filePath)) {
|
||||
res.status(404).sendFile(filePath);
|
||||
} else {
|
||||
res.status(500).send("Error loading 404 page.");
|
||||
}
|
||||
});
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.info(`Listening at ${PORT}`);
|
||||
});
|
||||
2
src/configs/dataUrl.js
Normal file
2
src/configs/dataUrl.js
Normal file
File diff suppressed because one or more lines are too long
4
src/configs/header.config.js
Normal file
4
src/configs/header.config.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const DEFAULT_HEADERS = {
|
||||
"User-Agent":
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
|
||||
};
|
||||
2
src/configs/player_v1.config.js
Normal file
2
src/configs/player_v1.config.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export const PLAYER_SCRIPT_URL =
|
||||
"https://megacloud.club/js/player/a/e1-player.min.js";
|
||||
2
src/configs/player_v2.config.js
Normal file
2
src/configs/player_v2.config.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export const PLAYER_SCRIPT_URL =
|
||||
"https://rapid-cloud.co/js/player/prod/e6-player-v2.min.js";
|
||||
20
src/controllers/actors.controller.js
Normal file
20
src/controllers/actors.controller.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import extractVoiceActor from "../extractors/actors.extractor.js";
|
||||
|
||||
const getVoiceActor = async (req, res) => {
|
||||
const id = req.params.id;
|
||||
try {
|
||||
const voiceActorData = await extractVoiceActor(id);
|
||||
|
||||
// Ensure the data is structured correctly
|
||||
if (!voiceActorData || voiceActorData.results.data.length === 0) {
|
||||
return res.status(404).json({ error: "No voice actor found." });
|
||||
}
|
||||
|
||||
return res.json(voiceActorData); // Return the desired structure
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return res.status(500).json({ error: "An error occurred" });
|
||||
}
|
||||
};
|
||||
|
||||
export default getVoiceActor;
|
||||
27
src/controllers/animeInfo.controller.js
Normal file
27
src/controllers/animeInfo.controller.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import extractAnimeInfo from "../extractors/animeInfo.extractor.js";
|
||||
import extractSeasons from "../extractors/seasons.extractor.js";
|
||||
import { getCachedData, setCachedData } from "../helper/cache.helper.js";
|
||||
|
||||
export const getAnimeInfo = async (req, res) => {
|
||||
const { id } = req.query;
|
||||
// const cacheKey = `animeInfo_${id}`;
|
||||
|
||||
try {
|
||||
// const cachedResponse = await getCachedData(cacheKey);
|
||||
// if (cachedResponse && Object.keys(cachedResponse).length > 0) {
|
||||
// return cachedResponse;
|
||||
// }
|
||||
const [seasons, data] = await Promise.all([
|
||||
extractSeasons(id),
|
||||
extractAnimeInfo(id),
|
||||
]);
|
||||
const responseData = { data: data, seasons: seasons };
|
||||
// setCachedData(cacheKey, responseData).catch((err) => {
|
||||
// console.error("Failed to set cache:", err);
|
||||
// });
|
||||
return responseData;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return res.status(500).json({ error: "An error occurred" });
|
||||
}
|
||||
};
|
||||
29
src/controllers/category.controller.js
Normal file
29
src/controllers/category.controller.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import { extractor } from "../extractors/category.extractor.js";
|
||||
import { getCachedData, setCachedData } from "../helper/cache.helper.js";
|
||||
|
||||
export const getCategory = async (req, res, routeType) => {
|
||||
if (routeType === "genre/martial-arts") {
|
||||
routeType = "genre/marial-arts";
|
||||
}
|
||||
const requestedPage = parseInt(req.query.page) || 1;
|
||||
// const cacheKey = `${routeType.replace(/\//g, "_")}_page_${requestedPage}`;
|
||||
try {
|
||||
// const cachedResponse = await getCachedData(cacheKey);
|
||||
// if (cachedResponse && Object.keys(cachedResponse).length > 0)
|
||||
// return cachedResponse;
|
||||
const { data, totalPages } = await extractor(routeType, requestedPage);
|
||||
if (requestedPage > totalPages) {
|
||||
const error = new Error("Requested page exceeds total available pages.");
|
||||
error.status = 404;
|
||||
throw error;
|
||||
}
|
||||
const responseData = { totalPages: totalPages, data: data };
|
||||
// setCachedData(cacheKey, responseData).catch((err) => {
|
||||
// console.error("Failed to set cache:", err);
|
||||
// });
|
||||
return responseData;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return e;
|
||||
}
|
||||
};
|
||||
20
src/controllers/characters.controller.js
Normal file
20
src/controllers/characters.controller.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import extractCharacter from "../extractors/characters.extractor.js";
|
||||
|
||||
const getCharacter = async (req, res) => {
|
||||
const id = req.params.id;
|
||||
try {
|
||||
const characterData = await extractCharacter(id);
|
||||
|
||||
// Ensure the data is structured correctly
|
||||
if (!characterData || characterData.results.data.length === 0) {
|
||||
return res.status(404).json({ error: "Character not found." });
|
||||
}
|
||||
|
||||
return res.json(characterData); // Return the desired structure
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return res.status(500).json({ error: "An error occurred" });
|
||||
}
|
||||
};
|
||||
|
||||
export default getCharacter;
|
||||
21
src/controllers/episodeList.controller.js
Normal file
21
src/controllers/episodeList.controller.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import extractEpisodesList from "../extractors/episodeList.extractor.js";
|
||||
import { getCachedData, setCachedData } from "../helper/cache.helper.js";
|
||||
|
||||
export const getEpisodes = async (req,res) => {
|
||||
const { id } = req.params;
|
||||
// const cacheKey = `episodes_${id}`;
|
||||
try {
|
||||
// const cachedResponse = await getCachedData(cacheKey);
|
||||
// if (cachedResponse && Object.keys(cachedResponse).length > 0) {
|
||||
// return cachedResponse;
|
||||
// }
|
||||
const data = await extractEpisodesList(encodeURIComponent(id));
|
||||
// setCachedData(cacheKey, data).catch((err) => {
|
||||
// console.error("Failed to set cache:", err);
|
||||
// });
|
||||
return data;
|
||||
} catch (e) {
|
||||
console.error("Error fetching episodes:", e);
|
||||
return e;
|
||||
}
|
||||
};
|
||||
66
src/controllers/filter.controller.js
Normal file
66
src/controllers/filter.controller.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import extractFilterResults from "../extractors/filter.extractor.js";
|
||||
|
||||
export const filter = async (req) => {
|
||||
try {
|
||||
// Extract all possible query parameters
|
||||
const {
|
||||
type,
|
||||
status,
|
||||
rated,
|
||||
score,
|
||||
season,
|
||||
language,
|
||||
genres,
|
||||
sort,
|
||||
sy, // Start year
|
||||
sm, // Start month
|
||||
sd, // Start day
|
||||
ey, // End year
|
||||
em, // End month
|
||||
ed, // End day
|
||||
keyword,
|
||||
page = 1
|
||||
} = req.query;
|
||||
|
||||
// Convert page to number
|
||||
const pageNum = parseInt(page);
|
||||
|
||||
// Create params object only with provided values
|
||||
const params = {};
|
||||
if (type) params.type = type;
|
||||
if (status) params.status = status;
|
||||
if (rated) params.rated = rated;
|
||||
if (score) params.score = score;
|
||||
if (season) params.season = season;
|
||||
if (language) params.language = language;
|
||||
if (genres) params.genres = genres;
|
||||
if (sort) params.sort = sort;
|
||||
if (sy) params.sy = sy;
|
||||
if (sm) params.sm = sm;
|
||||
if (sd) params.sd = sd;
|
||||
if (ey) params.ey = ey;
|
||||
if (em) params.em = em;
|
||||
if (ed) params.ed = ed;
|
||||
if (keyword) params.keyword = keyword;
|
||||
if (pageNum > 1) params.page = pageNum;
|
||||
|
||||
// Log params for debugging
|
||||
// console.log("Controller params:", params);
|
||||
|
||||
const [totalPage, data, currentPage, hasNextPage] = await extractFilterResults(params);
|
||||
|
||||
if (pageNum > totalPage) {
|
||||
const error = new Error("Requested page exceeds total available pages.");
|
||||
error.status = 404;
|
||||
throw error;
|
||||
}
|
||||
|
||||
return { data, totalPage, currentPage, hasNextPage };
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (e.status === 404) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("An error occurred while processing your request.");
|
||||
}
|
||||
};
|
||||
68
src/controllers/homeInfo.controller.js
Normal file
68
src/controllers/homeInfo.controller.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import getSpotlights from "../extractors/spotlight.extractor.js";
|
||||
import getTrending from "../extractors/trending.extractor.js";
|
||||
import extractPage from "../helper/extractPages.helper.js";
|
||||
import extractTopTen from "../extractors/topten.extractor.js";
|
||||
import { routeTypes } from "../routes/category.route.js";
|
||||
import extractSchedule from "../extractors/schedule.extractor.js";
|
||||
import { getCachedData, setCachedData } from "../helper/cache.helper.js";
|
||||
|
||||
const genres = routeTypes
|
||||
.slice(0, 41)
|
||||
.map((genre) => genre.replace("genre/", ""));
|
||||
|
||||
export const getHomeInfo = async (req,res) => {
|
||||
// const cacheKey = "homeInfo";
|
||||
try {
|
||||
// const cachedResponse = await getCachedData(cacheKey);
|
||||
// if (cachedResponse && Object.keys(cachedResponse).length > 0) {
|
||||
// return cachedResponse;
|
||||
// }
|
||||
const [
|
||||
spotlights,
|
||||
trending,
|
||||
topTen,
|
||||
schedule,
|
||||
topAiring,
|
||||
mostPopular,
|
||||
mostFavorite,
|
||||
latestCompleted,
|
||||
latestEpisode,
|
||||
topUpcoming,
|
||||
recentlyAdded,
|
||||
] = await Promise.all([
|
||||
getSpotlights(),
|
||||
getTrending(),
|
||||
extractTopTen(),
|
||||
extractSchedule(new Date().toISOString().split("T")[0]),
|
||||
extractPage(1, "top-airing"),
|
||||
extractPage(1, "most-popular"),
|
||||
extractPage(1, "most-favorite"),
|
||||
extractPage(1, "completed"),
|
||||
extractPage(1, "recently-updated"),
|
||||
extractPage(1, "top-upcoming"),
|
||||
extractPage(1, "recently-added"),
|
||||
]);
|
||||
const responseData = {
|
||||
spotlights,
|
||||
trending,
|
||||
topTen,
|
||||
today: { schedule },
|
||||
topAiring: topAiring[0],
|
||||
mostPopular: mostPopular[0],
|
||||
mostFavorite: mostFavorite[0],
|
||||
latestCompleted: latestCompleted[0],
|
||||
latestEpisode: latestEpisode[0],
|
||||
topUpcoming: topUpcoming[0],
|
||||
recentlyAdded: recentlyAdded[0],
|
||||
genres,
|
||||
};
|
||||
|
||||
// setCachedData(cacheKey, responseData).catch((err) => {
|
||||
// console.error("Failed to set cache:", err);
|
||||
// });
|
||||
return responseData;
|
||||
} catch (fetchError) {
|
||||
console.error("Error fetching fresh data:", fetchError);
|
||||
return fetchError;
|
||||
}
|
||||
};
|
||||
12
src/controllers/nextEpisodeSchedule.controller.js
Normal file
12
src/controllers/nextEpisodeSchedule.controller.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import extractNextEpisodeSchedule from "../extractors/getNextEpisodeSchedule.extractor.js";
|
||||
|
||||
export const getNextEpisodeSchedule = async (req) => {
|
||||
const { id } = req.params;
|
||||
try {
|
||||
const nextEpisodeSchedule = await extractNextEpisodeSchedule(id);
|
||||
return { nextEpisodeSchedule: nextEpisodeSchedule };
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return e;
|
||||
}
|
||||
};
|
||||
32
src/controllers/producer.controller.js
Normal file
32
src/controllers/producer.controller.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import { getCachedData, setCachedData } from "../helper/cache.helper.js";
|
||||
import extractPage from "../helper/extractPages.helper.js";
|
||||
|
||||
export const getProducer = async (req) => {
|
||||
const { id } = req.params;
|
||||
const routeType = `producer/${id}`;
|
||||
const requestedPage = parseInt(req.query.page) || 1;
|
||||
// const cacheKey = `${routeType.replace(/\//g, "_")}_page_${requestedPage}`;
|
||||
try {
|
||||
// const cachedResponse = await getCachedData(cacheKey);
|
||||
// if (cachedResponse && Object.keys(cachedResponse).length > 0) {
|
||||
// return cachedResponse;
|
||||
// }
|
||||
const [data, totalPages] = await extractPage(requestedPage, routeType);
|
||||
if (requestedPage > totalPages) {
|
||||
const error = new Error("Requested page exceeds total available pages.");
|
||||
error.status = 404;
|
||||
throw error;
|
||||
}
|
||||
const responseData = { totalPages: totalPages, data: data };
|
||||
// setCachedData(cacheKey, responseData).catch((err) => {
|
||||
// console.error("Failed to set cache:", err);
|
||||
// });
|
||||
return { data, totalPages };
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (e.status === 404) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("An error occurred while processing your request.");
|
||||
}
|
||||
};
|
||||
12
src/controllers/qtip.controller.js
Normal file
12
src/controllers/qtip.controller.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import extractQtip from "../extractors/qtip.extractor.js";
|
||||
|
||||
export const getQtip = async (req) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const data = await extractQtip(id);
|
||||
return data;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return e;
|
||||
}
|
||||
};
|
||||
11
src/controllers/random.controller.js
Normal file
11
src/controllers/random.controller.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import extractRandom from "../extractors/random.extractor.js";
|
||||
|
||||
export const getRandom = async (req,res) => {
|
||||
try {
|
||||
const data = await extractRandom();
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Error getting random anime:", error.message);
|
||||
return e;
|
||||
}
|
||||
};
|
||||
11
src/controllers/randomId.controller.js
Normal file
11
src/controllers/randomId.controller.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import extractRandomId from "../extractors/randomId.extractor.js";
|
||||
|
||||
export const getRandomId = async (req,res) => {
|
||||
try {
|
||||
const data = await extractRandomId();
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Error getting random anime ID:", error.message);
|
||||
return e;
|
||||
}
|
||||
};
|
||||
13
src/controllers/schedule.controller.js
Normal file
13
src/controllers/schedule.controller.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import extractSchedule from "../extractors/schedule.extractor.js";
|
||||
|
||||
export const getSchedule = async (req) => {
|
||||
const date = req.query.date;
|
||||
const tzOffset = req.query.tzOffset || -330;
|
||||
try {
|
||||
const data = await extractSchedule(date, tzOffset);
|
||||
return data;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return e;
|
||||
}
|
||||
};
|
||||
43
src/controllers/search.controller.js
Normal file
43
src/controllers/search.controller.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import extractSearchResults from "../extractors/search.extractor.js";
|
||||
import convertForeignLanguage from "../helper/foreignInput.helper.js";
|
||||
|
||||
export const search = async (req) => {
|
||||
try {
|
||||
let { keyword, type, status, rated, score, season, language, genres, sort, sy, sm, sd, ey, em, ed } = req.query;
|
||||
let page = parseInt(req.query.page) || 1;
|
||||
|
||||
// Check if the search keyword is in a foreign language and if it can be converted
|
||||
keyword = await convertForeignLanguage(keyword);
|
||||
|
||||
const [totalPage, data] = await extractSearchResults({
|
||||
keyword: keyword,
|
||||
type: type,
|
||||
status: status,
|
||||
rated: rated,
|
||||
score: score,
|
||||
season: season,
|
||||
language: language,
|
||||
genres: genres,
|
||||
sort: sort,
|
||||
page: page,
|
||||
sy: sy,
|
||||
sm: sm,
|
||||
sd: sd,
|
||||
ey: ey,
|
||||
em: em,
|
||||
ed: ed,
|
||||
});
|
||||
if (page > totalPage) {
|
||||
const error = new Error("Requested page exceeds total available pages.");
|
||||
error.status = 404;
|
||||
throw error;
|
||||
}
|
||||
return { data, totalPage };
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (e.status === 404) {
|
||||
throw e;
|
||||
}
|
||||
throw new Error("An error occurred while processing your request.");
|
||||
}
|
||||
};
|
||||
12
src/controllers/servers.controller.js
Normal file
12
src/controllers/servers.controller.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import { extractServers } from "../extractors/streamInfo.extractor.js";
|
||||
|
||||
export const getServers = async (req) => {
|
||||
try {
|
||||
const { ep } = req.query;
|
||||
const servers = await extractServers(ep);
|
||||
return servers;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return e;
|
||||
}
|
||||
};
|
||||
17
src/controllers/streamInfo.controller.js
Normal file
17
src/controllers/streamInfo.controller.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import { extractStreamingInfo } from "../extractors/streamInfo.extractor.js";
|
||||
|
||||
export const getStreamInfo = async (req, res, fallback = false) => {
|
||||
try {
|
||||
const input = req.query.id;
|
||||
const server = req.query.server;
|
||||
const type = req.query.type;
|
||||
const match = input.match(/ep=(\d+)/);
|
||||
if (!match) throw new Error("Invalid URL format");
|
||||
const finalId = match[1];
|
||||
const streamingInfo = await extractStreamingInfo(finalId, server, type, fallback);
|
||||
return streamingInfo;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return { error: e.message };
|
||||
}
|
||||
};
|
||||
17
src/controllers/suggestion.controller.js
Normal file
17
src/controllers/suggestion.controller.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import getSuggestion from "../extractors/suggestion.extractor.js";
|
||||
import convertForeignLanguage from "../helper/foreignInput.helper.js";
|
||||
|
||||
export const getSuggestions = async (req) => {
|
||||
let { keyword } = req.query;
|
||||
|
||||
// Check if the search keyword is in a foreign language and if it can be converted
|
||||
keyword = await convertForeignLanguage(keyword);
|
||||
|
||||
try {
|
||||
const data = await getSuggestion(encodeURIComponent(keyword));
|
||||
return data;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return e;
|
||||
}
|
||||
};
|
||||
13
src/controllers/topsearch.controller.js
Normal file
13
src/controllers/topsearch.controller.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import extractTopSearch from "../extractors/topsearch.extractor.js";
|
||||
|
||||
const getTopSearch = async () => {
|
||||
try {
|
||||
const data = await extractTopSearch();
|
||||
return data;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return e;
|
||||
}
|
||||
};
|
||||
|
||||
export default getTopSearch;
|
||||
22
src/controllers/topten.controller.js
Normal file
22
src/controllers/topten.controller.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import extractTopTen from "../extractors/topten.extractor.js";
|
||||
import { getCachedData, setCachedData } from "../helper/cache.helper.js";
|
||||
|
||||
export const getTopTen = async (req,res) => {
|
||||
// const cacheKey = "topTen";
|
||||
try {
|
||||
// const cachedResponse = await getCachedData(cacheKey);
|
||||
// if (cachedResponse && Object.keys(cachedResponse).length > 0) {
|
||||
// return cachedResponse;
|
||||
// }
|
||||
const topTen = await extractTopTen();
|
||||
// await setCachedData(cacheKey, topTen).catch((err) => {
|
||||
// console.error("Failed to set cache:", err);
|
||||
// });
|
||||
return topTen;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return c
|
||||
.status(500)
|
||||
.json({ success: false, error: "Internal Server Error" });
|
||||
}
|
||||
};
|
||||
16
src/controllers/voiceactor.controller.js
Normal file
16
src/controllers/voiceactor.controller.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import extractVoiceActor from "../extractors/voiceactor.extractor.js";
|
||||
|
||||
export const getVoiceActors = async (req, res) => {
|
||||
const requestedPage = parseInt(req.query.page) || 1;
|
||||
const id = req.params.id;
|
||||
try {
|
||||
const { totalPages, charactersVoiceActors: data } = await extractVoiceActor(
|
||||
id,
|
||||
requestedPage
|
||||
);
|
||||
return { currentPage: requestedPage, totalPages, data };
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return e;
|
||||
}
|
||||
};
|
||||
40
src/controllers/watchlist.controller.js
Normal file
40
src/controllers/watchlist.controller.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import extractWatchlist from "../extractors/watchlist.extractor.js";
|
||||
|
||||
export const getWatchlist = async (req, res) => {
|
||||
const { userId, page = 1 } = req.params;
|
||||
|
||||
try {
|
||||
const { watchlist, totalPages } = await extractWatchlist(userId, page);
|
||||
|
||||
// Restructuring the response
|
||||
return res.json({
|
||||
success: true,
|
||||
results: {
|
||||
totalPages, // Include total pages in the response
|
||||
data: watchlist.map(item => ({
|
||||
id: item.id,
|
||||
data_id: item.data_id,
|
||||
poster: item.poster,
|
||||
title: item.title,
|
||||
japanese_title: item.japanese_title,
|
||||
description: item.description,
|
||||
tvInfo: {
|
||||
showType: item.tvInfo.showType,
|
||||
duration: item.tvInfo.duration,
|
||||
sub: item.tvInfo.sub,
|
||||
dub: item.tvInfo.dub,
|
||||
// Include eps if it exists
|
||||
...(item.tvInfo.eps && { eps: item.tvInfo.eps })
|
||||
},
|
||||
adultContent: item.adultContent,
|
||||
}))
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error getting watchlist:", error.message);
|
||||
|
||||
if (!res.headersSent) {
|
||||
return res.status(500).json({ error: "An error occurred while fetching the watchlist." });
|
||||
}
|
||||
}
|
||||
};
|
||||
91
src/extractors/actors.extractor.js
Normal file
91
src/extractors/actors.extractor.js
Normal file
@@ -0,0 +1,91 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
export async function extractVoiceActor(id) {
|
||||
try {
|
||||
const response = await axios.get(`https://${v1_base_url}/people/${id}`);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
// Extract basic information
|
||||
const name = $(".apw-detail .name").text().trim();
|
||||
const japaneseName = $(".apw-detail .sub-name").text().trim();
|
||||
|
||||
// Extract profile image
|
||||
const profile = $(".avatar-circle img").attr("src"); // Extracting the profile image URL
|
||||
|
||||
// Extract about information as a full bio description
|
||||
const bioText = $("#bio .bio").text().trim();
|
||||
const bioHtml = $("#bio .bio").html(); // Capture the raw HTML
|
||||
const about = {
|
||||
description: bioText, // Store the full bio as a single description
|
||||
style: bioHtml, // Store the full HTML structure
|
||||
};
|
||||
|
||||
// Extract voice acting roles
|
||||
const roles = [];
|
||||
$(".bac-list-wrap .bac-item").each((_, element) => {
|
||||
const animeElement = $(element).find(".per-info.anime-info.ltr");
|
||||
const characterElement = $(element).find(".per-info.rtl");
|
||||
|
||||
const role = {
|
||||
anime: {
|
||||
id: animeElement.find(".pi-name a").attr("href")?.split("/").pop(),
|
||||
title: animeElement.find(".pi-name a").text().trim(),
|
||||
poster:
|
||||
animeElement.find(".pi-avatar img").attr("data-src") ||
|
||||
animeElement.find(".pi-avatar img").attr("src"),
|
||||
type: animeElement
|
||||
.find(".pi-cast")
|
||||
.text()
|
||||
.trim()
|
||||
.split(",")[0]
|
||||
.trim(),
|
||||
year: animeElement
|
||||
.find(".pi-cast")
|
||||
.text()
|
||||
.trim()
|
||||
.split(",")[1]
|
||||
?.trim(),
|
||||
},
|
||||
character: {
|
||||
id: characterElement
|
||||
.find(".pi-name a")
|
||||
.attr("href")
|
||||
?.split("/")
|
||||
.pop(),
|
||||
name: characterElement.find(".pi-name a").text().trim(),
|
||||
profile:
|
||||
characterElement.find(".pi-avatar img").attr("data-src") ||
|
||||
characterElement.find(".pi-avatar img").attr("src"),
|
||||
role: characterElement.find(".pi-cast").text().trim(),
|
||||
},
|
||||
};
|
||||
roles.push(role);
|
||||
});
|
||||
|
||||
// Construct the final response
|
||||
const voiceActorData = {
|
||||
success: true,
|
||||
results: {
|
||||
data: [
|
||||
{
|
||||
id,
|
||||
name,
|
||||
profile,
|
||||
japaneseName,
|
||||
about,
|
||||
roles,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
return voiceActorData;
|
||||
} catch (error) {
|
||||
console.error("Error extracting voice actor data:", error);
|
||||
throw new Error("Failed to extract voice actor information");
|
||||
}
|
||||
}
|
||||
|
||||
export default extractVoiceActor;
|
||||
194
src/extractors/animeInfo.extractor.js
Normal file
194
src/extractors/animeInfo.extractor.js
Normal file
@@ -0,0 +1,194 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import formatTitle from "../helper/formatTitle.helper.js";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
import extractRecommendedData from "./recommend.extractor.js";
|
||||
import extractRelatedData from "./related.extractor.js";
|
||||
import extractPopularData from "./popular.extractor.js";
|
||||
|
||||
async function extractAnimeInfo(id) {
|
||||
try {
|
||||
const [resp, characterData] = await Promise.all([
|
||||
axios.get(`https://${v1_base_url}/${id}`),
|
||||
axios.get(
|
||||
`https://${v1_base_url}/ajax/character/list/${id.split("-").pop()}`
|
||||
),
|
||||
]);
|
||||
const characterHtml = characterData.data?.html || "";
|
||||
const $1 = cheerio.load(characterHtml);
|
||||
const $ = cheerio.load(resp.data);
|
||||
const data_id = id.split("-").pop();
|
||||
const titleElement = $("#ani_detail .film-name");
|
||||
const showType = $("#ani_detail .prebreadcrumb ol li")
|
||||
.eq(1)
|
||||
.find("a")
|
||||
.text()
|
||||
.trim();
|
||||
const posterElement = $("#ani_detail .film-poster");
|
||||
const tvInfoElement = $("#ani_detail .film-stats");
|
||||
const tvInfo = {};
|
||||
tvInfoElement.find(".tick-item, span.item").each((_, element) => {
|
||||
const el = $(element);
|
||||
const text = el.text().trim();
|
||||
if (el.hasClass("tick-quality")) tvInfo.quality = text;
|
||||
else if (el.hasClass("tick-sub")) tvInfo.sub = text;
|
||||
else if (el.hasClass("tick-dub")) tvInfo.dub = text;
|
||||
else if (el.hasClass("tick-eps")) tvInfo.eps = text;
|
||||
else if (el.hasClass("tick-pg")) tvInfo.rating = text;
|
||||
else if (el.is("span.item")) {
|
||||
if (!tvInfo.showType) tvInfo.showType = text;
|
||||
else if (!tvInfo.duration) tvInfo.duration = text;
|
||||
}
|
||||
});
|
||||
|
||||
const element = $(
|
||||
"#ani_detail > .ani_detail-stage > .container > .anis-content > .anisc-info-wrap > .anisc-info > .item"
|
||||
);
|
||||
const overviewElement = $("#ani_detail .film-description .text");
|
||||
|
||||
const title = titleElement.text().trim();
|
||||
const japanese_title = titleElement.attr("data-jname");
|
||||
const synonyms = $('.item.item-title:has(.item-head:contains("Synonyms")) .name').text().trim();
|
||||
const poster = posterElement.find("img").attr("src");
|
||||
const syncDataScript = $("#syncData").html();
|
||||
let anilistId = null;
|
||||
let malId = null;
|
||||
|
||||
if (syncDataScript) {
|
||||
try {
|
||||
const syncData = JSON.parse(syncDataScript);
|
||||
anilistId = syncData.anilist_id || null;
|
||||
malId = syncData.mal_id || null;
|
||||
} catch (error) {
|
||||
console.error("Error parsing syncData:", error);
|
||||
}
|
||||
}
|
||||
|
||||
const animeInfo = {};
|
||||
element.each((_, el) => {
|
||||
const key = $(el).find(".item-head").text().trim().replace(":", "");
|
||||
const value =
|
||||
key === "Genres" || key === "Producers"
|
||||
? $(el)
|
||||
.find("a")
|
||||
.map((_, a) => $(a).text().split(" ").join("-").trim())
|
||||
.get()
|
||||
: $(el).find(".name").text().split(" ").join("-").trim();
|
||||
animeInfo[key] = value;
|
||||
});
|
||||
|
||||
const trailers = [];
|
||||
$('.block_area-promotions-list .screen-items .item').each((_, element) => {
|
||||
const el = $(element);
|
||||
const title = el.attr('data-title');
|
||||
const url = el.attr('data-src');
|
||||
if (url) {
|
||||
const fullUrl = url.startsWith('//') ? `https:${url}` : url;
|
||||
let videoId = null;
|
||||
const match = fullUrl.match(/\/embed\/([^?&]+)/);
|
||||
if (match && match[1]) {
|
||||
videoId = match[1];
|
||||
}
|
||||
trailers.push({
|
||||
title: title || null,
|
||||
url: fullUrl,
|
||||
thumbnail: videoId ? `https://img.youtube.com/vi/${videoId}/hqdefault.jpg` : null
|
||||
});
|
||||
}
|
||||
});
|
||||
animeInfo.trailers = trailers;
|
||||
|
||||
const season_id = formatTitle(title, data_id);
|
||||
animeInfo["Overview"] = overviewElement.text().trim();
|
||||
animeInfo["tvInfo"] = tvInfo;
|
||||
|
||||
let adultContent = false;
|
||||
const tickRateText = $(".tick-rate", posterElement).text().trim();
|
||||
if (tickRateText.includes("18+")) {
|
||||
adultContent = true;
|
||||
}
|
||||
|
||||
const [recommended_data, related_data, popular_data] = await Promise.all([
|
||||
extractRecommendedData($),
|
||||
extractRelatedData($),
|
||||
extractPopularData($),
|
||||
]);
|
||||
let charactersVoiceActors = [];
|
||||
if (characterHtml) {
|
||||
charactersVoiceActors = $1(".bac-list-wrap .bac-item")
|
||||
.map((index, el) => {
|
||||
const character = {
|
||||
id:
|
||||
$1(el)
|
||||
.find(".per-info.ltr .pi-avatar")
|
||||
.attr("href")
|
||||
?.split("/")[2] || "",
|
||||
poster:
|
||||
$1(el).find(".per-info.ltr .pi-avatar img").attr("data-src") ||
|
||||
"",
|
||||
name: $1(el).find(".per-info.ltr .pi-detail a").text(),
|
||||
cast: $1(el).find(".per-info.ltr .pi-detail .pi-cast").text(),
|
||||
};
|
||||
|
||||
let voiceActors = [];
|
||||
const rtlVoiceActors = $1(el).find(".per-info.rtl");
|
||||
const xxVoiceActors = $1(el).find(
|
||||
".per-info.per-info-xx .pix-list .pi-avatar"
|
||||
);
|
||||
if (rtlVoiceActors.length > 0) {
|
||||
voiceActors = rtlVoiceActors
|
||||
.map((_, actorEl) => ({
|
||||
id: $1(actorEl).find("a").attr("href")?.split("/").pop() || "",
|
||||
poster: $1(actorEl).find("img").attr("data-src") || "",
|
||||
name:
|
||||
$1(actorEl).find(".pi-detail .pi-name a").text().trim() || "",
|
||||
}))
|
||||
.get();
|
||||
} else if (xxVoiceActors.length > 0) {
|
||||
voiceActors = xxVoiceActors
|
||||
.map((_, actorEl) => ({
|
||||
id: $1(actorEl).attr("href")?.split("/").pop() || "",
|
||||
poster: $1(actorEl).find("img").attr("data-src") || "",
|
||||
name: $1(actorEl).attr("title") || "",
|
||||
}))
|
||||
.get();
|
||||
}
|
||||
if (voiceActors.length === 0) {
|
||||
voiceActors = $1(el)
|
||||
.find(".per-info.per-info-xx .pix-list .pi-avatar")
|
||||
.map((_, actorEl) => ({
|
||||
id: $1(actorEl).attr("href")?.split("/")[2] || "",
|
||||
poster: $1(actorEl).find("img").attr("data-src") || "",
|
||||
name: $1(actorEl).attr("title") || "",
|
||||
}))
|
||||
.get();
|
||||
}
|
||||
|
||||
return { character, voiceActors };
|
||||
})
|
||||
.get();
|
||||
}
|
||||
|
||||
return {
|
||||
adultContent,
|
||||
data_id,
|
||||
id: season_id,
|
||||
anilistId,
|
||||
malId,
|
||||
title,
|
||||
japanese_title,
|
||||
synonyms,
|
||||
poster,
|
||||
showType,
|
||||
animeInfo,
|
||||
charactersVoiceActors,
|
||||
recommended_data,
|
||||
related_data,
|
||||
popular_data,
|
||||
};
|
||||
} catch (e) {
|
||||
console.error("Error extracting anime info:", e);
|
||||
}
|
||||
}
|
||||
|
||||
export default extractAnimeInfo;
|
||||
14
src/extractors/category.extractor.js
Normal file
14
src/extractors/category.extractor.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import extractPage from "../helper/extractPages.helper.js";
|
||||
|
||||
export async function extractor(path, page) {
|
||||
try {
|
||||
const [data, totalPages] = await extractPage(page, path);
|
||||
return { data, totalPages };
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Error extracting data for ${path} from page ${page}:`,
|
||||
error.message
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
91
src/extractors/characters.extractor.js
Normal file
91
src/extractors/characters.extractor.js
Normal file
@@ -0,0 +1,91 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
export async function extractCharacter(id) {
|
||||
try {
|
||||
const response = await axios.get(`https://${v1_base_url}//character/${id}`);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
// Extract basic information
|
||||
const name = $(".apw-detail .name").text().trim();
|
||||
const japaneseName = $(".apw-detail .sub-name").text().trim();
|
||||
|
||||
// Extract profile image
|
||||
const profile = $(".avatar-circle img").attr("src");
|
||||
|
||||
// Extract about information
|
||||
const bioText = $("#bio .bio").text().trim();
|
||||
const bioHtml = $("#bio .bio").html();
|
||||
const about = {
|
||||
description: bioText,
|
||||
style: bioHtml,
|
||||
};
|
||||
|
||||
// Extract voice actors
|
||||
const voiceActors = [];
|
||||
$("#voiactor .per-info").each((_, element) => {
|
||||
const voiceActorElement = $(element);
|
||||
|
||||
const voiceActor = {
|
||||
name: voiceActorElement.find(".pi-name a").text().trim(),
|
||||
profile: voiceActorElement.find(".pi-avatar img").attr("src"),
|
||||
language: voiceActorElement.find(".pi-cast").text().trim(),
|
||||
id: voiceActorElement.find(".pi-name a").attr("href")?.split("/").pop(),
|
||||
};
|
||||
|
||||
if (voiceActor.name && voiceActor.id) {
|
||||
voiceActors.push(voiceActor);
|
||||
}
|
||||
});
|
||||
|
||||
// Extract animeography
|
||||
const animeography = [];
|
||||
$(".anif-block-ul li").each((_, el) => {
|
||||
const item = $(el);
|
||||
const anchor = item.find(".film-name a.dynamic-name");
|
||||
|
||||
const title = anchor.text().trim();
|
||||
const japanese_title = anchor.attr("data-jname")?.trim();
|
||||
const id = anchor.attr("href")?.split("/").pop();
|
||||
const role = item.find(".fdi-item").first().text().trim();
|
||||
const type = item.find(".fdi-item").last().text().trim();
|
||||
const poster = item.find(".film-poster img").attr("src");
|
||||
|
||||
if (title && id) {
|
||||
animeography.push({
|
||||
title,
|
||||
japanese_title,
|
||||
id,
|
||||
role: role.replace(" (Role)", ""),
|
||||
type,
|
||||
poster,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const characterData = {
|
||||
success: true,
|
||||
results: {
|
||||
data: [
|
||||
{
|
||||
id,
|
||||
name,
|
||||
profile,
|
||||
japaneseName,
|
||||
about,
|
||||
voiceActors,
|
||||
animeography,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
return characterData;
|
||||
} catch (error) {
|
||||
console.error("Error extracting character data:", error);
|
||||
throw new Error("Failed to extract character information");
|
||||
}
|
||||
}
|
||||
|
||||
export default extractCharacter;
|
||||
39
src/extractors/episodeList.extractor.js
Normal file
39
src/extractors/episodeList.extractor.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
async function extractEpisodesList(id) {
|
||||
try {
|
||||
const showId = id.split("-").pop();
|
||||
const response = await axios.get(
|
||||
`https://${v1_base_url}/ajax/v2/episode/list/${showId}`,
|
||||
{
|
||||
headers: {
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
Referer: `https://${v1_base_url}/watch/${id}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
if (!response.data.html) return [];
|
||||
const $ = cheerio.load(response.data.html);
|
||||
const res = {
|
||||
totalEpisodes: 0,
|
||||
episodes: [],
|
||||
};
|
||||
res.totalEpisodes = Number($(".detail-infor-content .ss-list a").length);
|
||||
$(".detail-infor-content .ss-list a").each((_, el) => {
|
||||
res.episodes.push({
|
||||
episode_no: Number($(el).attr("data-number")),
|
||||
id: $(el)?.attr("href")?.split("/")?.pop() || null,
|
||||
title: $(el)?.attr("title")?.trim() || null,
|
||||
japanese_title: $(el).find(".ep-name").attr("data-jname"),
|
||||
filler: $(el).hasClass("ssl-item-filler"),
|
||||
});
|
||||
});
|
||||
return res;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
export default extractEpisodesList;
|
||||
174
src/extractors/filter.extractor.js
Normal file
174
src/extractors/filter.extractor.js
Normal file
@@ -0,0 +1,174 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { DEFAULT_HEADERS } from "../configs/header.config.js";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
import {
|
||||
FILTER_LANGUAGE_MAP,
|
||||
GENRE_MAP,
|
||||
FILTER_TYPES,
|
||||
FILTER_STATUS,
|
||||
FILTER_RATED,
|
||||
FILTER_SCORE,
|
||||
FILTER_SEASON,
|
||||
FILTER_SORT,
|
||||
} from "../routes/filter.maping.js";
|
||||
|
||||
async function extractFilterResults(params = {}) {
|
||||
try {
|
||||
const normalizeParam = (param, mapping) => {
|
||||
if (!param) return undefined;
|
||||
|
||||
if (typeof param === "string") {
|
||||
const isAlreadyId = Object.values(mapping).includes(param);
|
||||
if (isAlreadyId) {
|
||||
return param;
|
||||
}
|
||||
|
||||
const key = param.trim().toUpperCase();
|
||||
return mapping.hasOwnProperty(key) ? mapping[key] : undefined;
|
||||
}
|
||||
return param;
|
||||
};
|
||||
|
||||
const typeParam = normalizeParam(params.type, FILTER_TYPES);
|
||||
const statusParam = normalizeParam(params.status, FILTER_STATUS);
|
||||
const ratedParam = normalizeParam(params.rated, FILTER_RATED);
|
||||
const scoreParam = normalizeParam(params.score, FILTER_SCORE);
|
||||
const seasonParam = normalizeParam(params.season, FILTER_SEASON);
|
||||
const sortParam = normalizeParam(params.sort, FILTER_SORT);
|
||||
|
||||
let languageParam = params.language;
|
||||
if (languageParam != null) {
|
||||
languageParam = String(languageParam).trim().toUpperCase();
|
||||
languageParam = FILTER_LANGUAGE_MAP[languageParam] ?? (Object.values(FILTER_LANGUAGE_MAP).includes(languageParam) ? languageParam : undefined);
|
||||
}
|
||||
|
||||
let genresParam = params.genres;
|
||||
if (typeof genresParam === "string") {
|
||||
genresParam = genresParam
|
||||
.split(",")
|
||||
.map((genre) => GENRE_MAP[genre.trim().toUpperCase()] || genre.trim())
|
||||
.join(",");
|
||||
}
|
||||
|
||||
const filteredParams = {
|
||||
type: typeParam,
|
||||
status: statusParam,
|
||||
rated: ratedParam,
|
||||
score: scoreParam,
|
||||
season: seasonParam,
|
||||
language: languageParam,
|
||||
genres: genresParam,
|
||||
sort: sortParam,
|
||||
page: params.page || 1,
|
||||
sy: params.sy || undefined,
|
||||
sm: params.sm || undefined,
|
||||
sd: params.sd || undefined,
|
||||
ey: params.ey || undefined,
|
||||
em: params.em || undefined,
|
||||
ed: params.ed || undefined,
|
||||
keyword: params.keyword || undefined,
|
||||
};
|
||||
|
||||
Object.keys(filteredParams).forEach((key) => {
|
||||
if (filteredParams[key] === undefined) {
|
||||
delete filteredParams[key];
|
||||
}
|
||||
});
|
||||
|
||||
const queryParams = new URLSearchParams(filteredParams).toString();
|
||||
|
||||
let apiUrl = `https://${v1_base_url}/filter?${queryParams}`;
|
||||
|
||||
if (filteredParams.keyword) {
|
||||
apiUrl = `https://${v1_base_url}/search?${queryParams}`;
|
||||
}
|
||||
|
||||
const resp = await axios.get(apiUrl, {
|
||||
headers: {
|
||||
Accept:
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
|
||||
|
||||
"Accept-Encoding": "gzip, deflate, br",
|
||||
"User-Agent": DEFAULT_HEADERS,
|
||||
},
|
||||
});
|
||||
|
||||
const $ = cheerio.load(resp.data);
|
||||
const elements = ".flw-item";
|
||||
const result = [];
|
||||
|
||||
$(elements).each((_, el) => {
|
||||
const $el = $(el);
|
||||
const href = $el.find(".film-poster-ahref").attr("href");
|
||||
const data_id = Number($el.find(".film-poster-ahref").attr("data-id"));
|
||||
|
||||
result.push({
|
||||
id: href ? href.slice(1) : null,
|
||||
data_id: data_id ? `${data_id}` : null,
|
||||
poster:
|
||||
$el.find(".film-poster .film-poster-img").attr("data-src") ||
|
||||
$el.find(".film-poster .film-poster-img").attr("src") ||
|
||||
null,
|
||||
title: $el.find(".film-name .dynamic-name").text().trim(),
|
||||
japanese_title:
|
||||
$el.find(".film-name .dynamic-name").attr("data-jname") || null,
|
||||
tvInfo: {
|
||||
showType:
|
||||
$el.find(".fd-infor .fdi-item:first-child").text().trim() ||
|
||||
"Unknown",
|
||||
duration: $el.find(".fd-infor .fdi-duration").text().trim() || null,
|
||||
sub:
|
||||
Number(
|
||||
$el
|
||||
.find(".tick-sub")
|
||||
.text()
|
||||
.replace(/[^0-9]/g, "")
|
||||
) || null,
|
||||
dub:
|
||||
Number(
|
||||
$el
|
||||
.find(".tick-dub")
|
||||
.text()
|
||||
.replace(/[^0-9]/g, "")
|
||||
) || null,
|
||||
eps:
|
||||
Number(
|
||||
$el
|
||||
.find(".tick-eps")
|
||||
.text()
|
||||
.replace(/[^0-9]/g, "")
|
||||
) || null,
|
||||
},
|
||||
adultContent: $el.find(".tick-rate").text().trim() || null,
|
||||
});
|
||||
});
|
||||
|
||||
const totalPage = Number(
|
||||
$('.pre-pagination nav .pagination > .page-item a[title="Last"]')
|
||||
?.attr("href")
|
||||
?.split("=")
|
||||
.pop() ||
|
||||
$('.pre-pagination nav .pagination > .page-item a[title="Next"]')
|
||||
?.attr("href")
|
||||
?.split("=")
|
||||
.pop() ||
|
||||
$(".pre-pagination nav .pagination > .page-item.active a")
|
||||
?.text()
|
||||
?.trim() ||
|
||||
1
|
||||
);
|
||||
|
||||
return [
|
||||
parseInt(totalPage, 10),
|
||||
result.length > 0 ? result : [],
|
||||
parseInt(params.page, 10) || 1,
|
||||
parseInt(params.page, 10) < parseInt(totalPage, 10),
|
||||
];
|
||||
} catch (e) {
|
||||
console.error("Error fetching data:", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
export { extractFilterResults as default };
|
||||
16
src/extractors/getNextEpisodeSchedule.extractor.js
Normal file
16
src/extractors/getNextEpisodeSchedule.extractor.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
export default async function extractNextEpisodeSchedule(id) {
|
||||
try {
|
||||
const { data } = await axios.get(`https://${v1_base_url}/watch/${id}`);
|
||||
const $ = cheerio.load(data);
|
||||
const nextEpisodeSchedule = $(
|
||||
".schedule-alert > .alert.small > span:last"
|
||||
).attr("data-value");
|
||||
return nextEpisodeSchedule;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
49
src/extractors/popular.extractor.js
Normal file
49
src/extractors/popular.extractor.js
Normal file
@@ -0,0 +1,49 @@
|
||||
export default async function extractPopularData($) {
|
||||
const popularSection = $('#main-sidebar .block_area:has(.cat-heading:contains("Most Popular"))');
|
||||
|
||||
const popularElements = popularSection.find(".anif-block-ul .ulclear li");
|
||||
|
||||
return await Promise.all(
|
||||
popularElements
|
||||
.map(async (index, element) => {
|
||||
const $el = $(element);
|
||||
const id = $el.find(".film-detail .film-name a").attr("href")?.split("/").pop();
|
||||
const data_id = $el.find(".film-poster").attr("data-id");
|
||||
const title = $el.find(".film-detail .film-name a").text().trim();
|
||||
const japanese_title = $el.find(".film-detail .film-name a").attr("data-jname")?.trim();
|
||||
const poster = $el.find(".film-poster img").attr("data-src") || $el.find(".film-poster img").attr("src");
|
||||
|
||||
// Extract show type like "TV", "Movie", etc.
|
||||
const showTypeText = $el.find(".tick").text().toLowerCase();
|
||||
const showTypeMatch = ["TV", "ONA", "Movie", "OVA", "Special"].find(type =>
|
||||
showTypeText.toLowerCase().includes(type.toLowerCase())
|
||||
);
|
||||
const tvInfo = {
|
||||
showType: showTypeMatch || "Unknown"
|
||||
};
|
||||
|
||||
// Extract tick items like sub, dub, eps
|
||||
["sub", "dub", "eps"].forEach((type) => {
|
||||
const value = $el.find(`.tick-item.tick-${type}`).text().trim();
|
||||
if (value) {
|
||||
tvInfo[type] = value;
|
||||
}
|
||||
});
|
||||
|
||||
// Adult content check
|
||||
const tickRateText = $el.find(".film-poster > .tick-rate").text().trim();
|
||||
const adultContent = tickRateText.includes("18+");
|
||||
|
||||
return {
|
||||
data_id,
|
||||
id,
|
||||
title,
|
||||
japanese_title,
|
||||
poster,
|
||||
tvInfo,
|
||||
adultContent,
|
||||
};
|
||||
})
|
||||
.get()
|
||||
);
|
||||
}
|
||||
65
src/extractors/qtip.extractor.js
Normal file
65
src/extractors/qtip.extractor.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
export default async function extractQtip(id) {
|
||||
try {
|
||||
const { data } = await axios.get(
|
||||
`https://${v1_base_url}/ajax/movie/qtip/${id}`,
|
||||
{
|
||||
headers: {
|
||||
"x-requested-with": "XMLHttpRequest",
|
||||
},
|
||||
}
|
||||
);
|
||||
const $ = cheerio.load(data);
|
||||
|
||||
const title = $(".pre-qtip-title").text();
|
||||
const rating = $(".pqd-li i.fas.fa-star").parent().text().trim();
|
||||
const quality = $(".tick-item.tick-quality").text();
|
||||
const subCount = $(".tick-item.tick-sub").text().trim();
|
||||
const dubCount = $(".tick-item.tick-dub").text().trim();
|
||||
const episodeCount = $(".tick-item.tick-eps").text().trim();
|
||||
const type = $(".badge.badge-quality").text();
|
||||
const description = $(".pre-qtip-description").text().trim();
|
||||
const japaneseTitle = $(".pre-qtip-line:contains('Japanese:') .stick-text")
|
||||
.text()
|
||||
.trim();
|
||||
const airedDate = $(".pre-qtip-line:contains('Aired:') .stick-text")
|
||||
.text()
|
||||
.trim();
|
||||
const status = $(".pre-qtip-line:contains('Status:') .stick-text")
|
||||
.text()
|
||||
.trim();
|
||||
const Synonyms = $(".pre-qtip-line:contains('Synonyms:') .stick-text")
|
||||
.text()
|
||||
.trim();
|
||||
const genres = [];
|
||||
$(".pre-qtip-line:contains('Genres:') a").each((i, elem) => {
|
||||
genres.push($(elem).text().trim().split(" ").join("-"));
|
||||
});
|
||||
|
||||
const watchLink = $(".pre-qtip-button a.btn.btn-play").attr("href");
|
||||
|
||||
const extractedData = {
|
||||
title,
|
||||
rating,
|
||||
quality,
|
||||
subCount,
|
||||
dubCount,
|
||||
episodeCount,
|
||||
type,
|
||||
description,
|
||||
japaneseTitle,
|
||||
Synonyms,
|
||||
airedDate,
|
||||
status,
|
||||
genres,
|
||||
watchLink,
|
||||
};
|
||||
return extractedData;
|
||||
} catch (error) {
|
||||
console.error("Error extracting data:", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
18
src/extractors/random.extractor.js
Normal file
18
src/extractors/random.extractor.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import axios from "axios";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
import extractAnimeInfo from "./animeInfo.extractor.js";
|
||||
import { DEFAULT_HEADERS } from "../configs/header.config.js";
|
||||
|
||||
const axiosInstance = axios.create({ headers: DEFAULT_HEADERS });
|
||||
|
||||
export default async function extractRandom() {
|
||||
try {
|
||||
const resp = await axiosInstance.get(`https://${v1_base_url}/random`);
|
||||
const redirectedUrl = resp.request.res.responseUrl;
|
||||
const id = redirectedUrl.split("/").pop();
|
||||
const animeInfo = await extractAnimeInfo(id);
|
||||
return animeInfo;
|
||||
} catch (error) {
|
||||
console.error("Error extracting random anime info:", error);
|
||||
}
|
||||
}
|
||||
16
src/extractors/randomId.extractor.js
Normal file
16
src/extractors/randomId.extractor.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import axios from "axios";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
import { DEFAULT_HEADERS } from "../configs/header.config.js";
|
||||
|
||||
const axiosInstance = axios.create({ headers: DEFAULT_HEADERS });
|
||||
|
||||
export default async function extractRandomId() {
|
||||
try {
|
||||
const resp = await axiosInstance.get(`https://${v1_base_url}/random`);
|
||||
const redirectedUrl = resp.request.res.responseUrl;
|
||||
const id = redirectedUrl.split("/").pop();
|
||||
return id;
|
||||
} catch (error) {
|
||||
console.error("Error extracting random anime info:", error);
|
||||
}
|
||||
}
|
||||
65
src/extractors/recommend.extractor.js
Normal file
65
src/extractors/recommend.extractor.js
Normal file
@@ -0,0 +1,65 @@
|
||||
export default async function extractRecommendedData($) {
|
||||
const recommendedElements = $(
|
||||
"#main-content .block_area_category .tab-content .block_area-content .film_list-wrap .flw-item"
|
||||
);
|
||||
return await Promise.all(
|
||||
recommendedElements
|
||||
.map(async (index, element) => {
|
||||
const id = $(element)
|
||||
.find(".film-detail .film-name a")
|
||||
.attr("href")
|
||||
.split("/")
|
||||
.pop();
|
||||
const data_id = $(element).find(".film-poster a").attr("data-id");
|
||||
const title = $(element)
|
||||
.find(".film-detail .film-name a")
|
||||
.text()
|
||||
.trim();
|
||||
const japanese_title = $(element)
|
||||
.find(".film-detail .film-name a")
|
||||
.attr("data-jname")
|
||||
.trim();
|
||||
const poster = $(element).find(".film-poster img").attr("data-src");
|
||||
const $fdiItems = $(".film-detail .fd-infor .fdi-item", element);
|
||||
const showType = $fdiItems
|
||||
.filter((_, item) => {
|
||||
const text = $(item).text().trim().toLowerCase();
|
||||
return ["tv", "ona", "movie", "ova", "special"].some((type) =>
|
||||
text.includes(type)
|
||||
);
|
||||
})
|
||||
.first();
|
||||
|
||||
const tvInfo = {
|
||||
showType: showType ? showType.text().trim() : "Unknown",
|
||||
duration: $(".film-detail .fd-infor .fdi-duration", element)
|
||||
.text()
|
||||
.trim(),
|
||||
};
|
||||
|
||||
["sub", "dub", "eps"].forEach((property) => {
|
||||
const value = $(`.tick .tick-${property}`, element).text().trim();
|
||||
if (value) {
|
||||
tvInfo[property] = value;
|
||||
}
|
||||
});
|
||||
let adultContent = false;
|
||||
const tickRateText = $(".film-poster>.tick-rate", element)
|
||||
.text()
|
||||
.trim();
|
||||
if (tickRateText.includes("18+")) {
|
||||
adultContent = true;
|
||||
}
|
||||
return {
|
||||
data_id,
|
||||
id,
|
||||
title,
|
||||
japanese_title,
|
||||
poster,
|
||||
tvInfo,
|
||||
adultContent,
|
||||
};
|
||||
})
|
||||
.get()
|
||||
);
|
||||
}
|
||||
51
src/extractors/related.extractor.js
Normal file
51
src/extractors/related.extractor.js
Normal file
@@ -0,0 +1,51 @@
|
||||
export default async function extractRelatedData($) {
|
||||
const relatedSection = $('#main-sidebar .block_area:has(.cat-heading:contains("Related Anime"))');
|
||||
|
||||
const relatedElements = relatedSection.find(
|
||||
".anif-block-ul .ulclear li"
|
||||
);
|
||||
|
||||
return await Promise.all(
|
||||
relatedElements
|
||||
.map(async (index, element) => {
|
||||
const $el = $(element);
|
||||
const id = $el.find(".film-detail .film-name a").attr("href")?.split("/").pop();
|
||||
const data_id = $el.find(".film-poster").attr("data-id");
|
||||
const title = $el.find(".film-detail .film-name a").text().trim();
|
||||
const japanese_title = $el.find(".film-detail .film-name a").attr("data-jname")?.trim();
|
||||
const poster = $el.find(".film-poster img").attr("data-src") || $el.find(".film-poster img").attr("src");
|
||||
|
||||
// Extract show type like "TV", "Movie", etc.
|
||||
const showTypeText = $el.find(".tick").text().toLowerCase();
|
||||
const showTypeMatch = ["TV", "ONA", "Movie", "OVA", "Special"].find(type =>
|
||||
showTypeText.toLowerCase().includes(type.toLowerCase())
|
||||
);
|
||||
const tvInfo = {
|
||||
showType: showTypeMatch || "Unknown"
|
||||
};
|
||||
|
||||
// Extract tick items like sub, dub, eps
|
||||
["sub", "dub", "eps"].forEach((type) => {
|
||||
const value = $el.find(`.tick-item.tick-${type}`).text().trim();
|
||||
if (value) {
|
||||
tvInfo[type] = value;
|
||||
}
|
||||
});
|
||||
|
||||
// Adult content check
|
||||
const tickRateText = $el.find(".film-poster > .tick-rate").text().trim();
|
||||
const adultContent = tickRateText.includes("18+");
|
||||
|
||||
return {
|
||||
data_id,
|
||||
id,
|
||||
title,
|
||||
japanese_title,
|
||||
poster,
|
||||
tvInfo,
|
||||
adultContent,
|
||||
};
|
||||
})
|
||||
.get()
|
||||
);
|
||||
}
|
||||
51
src/extractors/schedule.extractor.js
Normal file
51
src/extractors/schedule.extractor.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
export default async function extractSchedule(date, tzOffset) {
|
||||
try {
|
||||
tzOffset = tzOffset ?? -330;
|
||||
|
||||
const resp = await axios.get(
|
||||
`https://${v1_base_url}/ajax/schedule/list?tzOffset=${tzOffset}&date=${date}`
|
||||
);
|
||||
const $ = cheerio.load(resp.data.html);
|
||||
const results = [];
|
||||
|
||||
$("li").each((i, element) => {
|
||||
const id = $(element)
|
||||
?.find("a")
|
||||
.attr("href")
|
||||
.split("?")[0]
|
||||
.replace("/", "");
|
||||
const data_id = id?.split("-").pop();
|
||||
const title = $(element).find(".film-name").text().trim();
|
||||
const japanese_title = $(element)
|
||||
.find(".film-name")
|
||||
.attr("data-jname")
|
||||
?.trim();
|
||||
const releaseDate = date;
|
||||
const time = $(element).find(".time").text().trim();
|
||||
const episode_no = $(element)
|
||||
?.find(".btn-play")
|
||||
.text()
|
||||
.trim()
|
||||
.split(" ")
|
||||
.pop();
|
||||
results.push({
|
||||
id,
|
||||
data_id,
|
||||
title,
|
||||
japanese_title,
|
||||
releaseDate,
|
||||
time,
|
||||
episode_no,
|
||||
});
|
||||
});
|
||||
|
||||
return results;
|
||||
} catch (error) {
|
||||
console.log(error.message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
184
src/extractors/search.extractor.js
Normal file
184
src/extractors/search.extractor.js
Normal file
@@ -0,0 +1,184 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { DEFAULT_HEADERS } from "../configs/header.config.js";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
import {
|
||||
FILTER_LANGUAGE_MAP,
|
||||
GENRE_MAP,
|
||||
FILTER_TYPES,
|
||||
FILTER_STATUS,
|
||||
FILTER_RATED,
|
||||
FILTER_SCORE,
|
||||
FILTER_SEASON,
|
||||
FILTER_SORT,
|
||||
} from "../routes/filter.maping.js";
|
||||
|
||||
async function extractSearchResults(params = {}) {
|
||||
try {
|
||||
const normalizeParam = (param, mapping) => {
|
||||
if (!param) return undefined;
|
||||
|
||||
if (typeof param === "string") {
|
||||
const isAlreadyId = Object.values(mapping).includes(param);
|
||||
if (isAlreadyId) {
|
||||
return param;
|
||||
}
|
||||
|
||||
const key = param.trim().toUpperCase();
|
||||
return mapping.hasOwnProperty(key) ? mapping[key] : undefined;
|
||||
}
|
||||
return param;
|
||||
};
|
||||
|
||||
const typeParam = normalizeParam(params.type, FILTER_TYPES);
|
||||
const statusParam = normalizeParam(params.status, FILTER_STATUS);
|
||||
const ratedParam = normalizeParam(params.rated, FILTER_RATED);
|
||||
const scoreParam = normalizeParam(params.score, FILTER_SCORE);
|
||||
const seasonParam = normalizeParam(params.season, FILTER_SEASON);
|
||||
const sortParam = normalizeParam(params.sort, FILTER_SORT);
|
||||
|
||||
let languageParam = params.language;
|
||||
if (languageParam != null) {
|
||||
languageParam = String(languageParam).trim().toUpperCase();
|
||||
languageParam = FILTER_LANGUAGE_MAP[languageParam] ?? (Object.values(FILTER_LANGUAGE_MAP).includes(languageParam) ? languageParam : undefined);
|
||||
}
|
||||
|
||||
let genresParam = params.genres;
|
||||
if (typeof genresParam === "string") {
|
||||
genresParam = genresParam
|
||||
.split(",")
|
||||
.map((genre) => GENRE_MAP[genre.trim().toUpperCase()] || genre.trim())
|
||||
.join(",");
|
||||
}
|
||||
|
||||
const filteredParams = {
|
||||
type: typeParam,
|
||||
status: statusParam,
|
||||
rated: ratedParam,
|
||||
score: scoreParam,
|
||||
season: seasonParam,
|
||||
language: languageParam,
|
||||
genres: genresParam,
|
||||
sort: sortParam,
|
||||
page: params.page || 1,
|
||||
sy: params.sy || undefined,
|
||||
sm: params.sm || undefined,
|
||||
sd: params.sd || undefined,
|
||||
ey: params.ey || undefined,
|
||||
em: params.em || undefined,
|
||||
ed: params.ed || undefined,
|
||||
keyword: params.keyword || undefined,
|
||||
};
|
||||
|
||||
Object.keys(filteredParams).forEach((key) => {
|
||||
if (filteredParams[key] === undefined) {
|
||||
delete filteredParams[key];
|
||||
}
|
||||
});
|
||||
|
||||
const queryParams = new URLSearchParams(filteredParams).toString();
|
||||
|
||||
const resp = await axios.get(`https://${v1_base_url}/search?${queryParams}`, {
|
||||
headers: {
|
||||
Accept:
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
||||
"Accept-Encoding": "gzip, deflate, br",
|
||||
"User-Agent": DEFAULT_HEADERS,
|
||||
},
|
||||
});
|
||||
|
||||
const $ = cheerio.load(resp.data);
|
||||
const elements = "#main-content .film_list-wrap .flw-item";
|
||||
|
||||
const totalPage =
|
||||
Number(
|
||||
$('.pre-pagination nav .pagination > .page-item a[title="Last"]')
|
||||
?.attr("href")
|
||||
?.split("=")
|
||||
.pop() ??
|
||||
$('.pre-pagination nav .pagination > .page-item a[title="Next"]')
|
||||
?.attr("href")
|
||||
?.split("=")
|
||||
.pop() ??
|
||||
$(".pre-pagination nav .pagination > .page-item.active a")
|
||||
?.text()
|
||||
?.trim()
|
||||
) || 1;
|
||||
|
||||
const result = [];
|
||||
$(elements).each((_, el) => {
|
||||
const id =
|
||||
$(el)
|
||||
.find(".film-detail .film-name .dynamic-name")
|
||||
?.attr("href")
|
||||
?.slice(1)
|
||||
.split("?ref=search")[0] || null;
|
||||
result.push({
|
||||
id: id,
|
||||
data_id: $(el)
|
||||
.find(".film-poster .film-poster-ahref").attr("data-id"),
|
||||
title: $(el)
|
||||
.find(".film-detail .film-name .dynamic-name")
|
||||
?.text()
|
||||
?.trim(),
|
||||
japanese_title:
|
||||
$(el)
|
||||
.find(".film-detail .film-name .dynamic-name")
|
||||
?.attr("data-jname")
|
||||
?.trim() || null,
|
||||
poster:
|
||||
$(el)
|
||||
.find(".film-poster .film-poster-img")
|
||||
?.attr("data-src")
|
||||
?.trim() || null,
|
||||
duration:
|
||||
$(el)
|
||||
.find(".film-detail .fd-infor .fdi-item.fdi-duration")
|
||||
?.text()
|
||||
?.trim(),
|
||||
tvInfo: {
|
||||
showType:
|
||||
$(el)
|
||||
.find(".film-detail .fd-infor .fdi-item:nth-of-type(1)")
|
||||
.text()
|
||||
.trim() || "Unknown",
|
||||
rating: $(el).find(".film-poster .tick-rate")?.text()?.trim() || null,
|
||||
sub:
|
||||
Number(
|
||||
$(el)
|
||||
.find(".film-poster .tick-sub")
|
||||
?.text()
|
||||
?.trim()
|
||||
.split(" ")
|
||||
.pop()
|
||||
) || null,
|
||||
dub:
|
||||
Number(
|
||||
$(el)
|
||||
.find(".film-poster .tick-dub")
|
||||
?.text()
|
||||
?.trim()
|
||||
.split(" ")
|
||||
.pop()
|
||||
) || null,
|
||||
eps:
|
||||
Number(
|
||||
$(el)
|
||||
.find(".film-poster .tick-eps")
|
||||
?.text()
|
||||
?.trim()
|
||||
.split(" ")
|
||||
.pop()
|
||||
) || null,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
return [parseInt(totalPage, 10), result.length > 0 ? result : []];
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
export default extractSearchResults;
|
||||
30
src/extractors/seasons.extractor.js
Normal file
30
src/extractors/seasons.extractor.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import formatTitle from "../helper/formatTitle.helper.js";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
async function extractSeasons(id) {
|
||||
try {
|
||||
const resp = await axios.get(`https://${v1_base_url}/watch/${id}`);
|
||||
const $ = cheerio.load(resp.data);
|
||||
const seasons = $(".anis-watch>.other-season>.inner>.os-list>a")
|
||||
.map((index, element) => {
|
||||
const data_number = index;
|
||||
const data_id = parseInt($(element).attr("href").split("-").pop());
|
||||
const season = $(element).find(".title").text().trim();
|
||||
const title = $(element).attr("title").trim();
|
||||
const id = href.replace(/^\/+/, "");
|
||||
const season_poster = $(element)
|
||||
.find(".season-poster")
|
||||
.attr("style")
|
||||
.match(/url\((.*?)\)/)[1];
|
||||
return { id, data_number, data_id, season, title, season_poster };
|
||||
})
|
||||
.get();
|
||||
return seasons;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
export default extractSeasons;
|
||||
103
src/extractors/spotlight.extractor.js
Normal file
103
src/extractors/spotlight.extractor.js
Normal file
@@ -0,0 +1,103 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
async function extractSpotlights() {
|
||||
try {
|
||||
const resp = await axios.get(`https://${v1_base_url}/home`);
|
||||
const $ = cheerio.load(resp.data);
|
||||
|
||||
const slideElements = $(
|
||||
"div.deslide-wrap > div.container > div#slider > div.swiper-wrapper > div.swiper-slide"
|
||||
);
|
||||
|
||||
const promises = slideElements
|
||||
.map(async (ind, ele) => {
|
||||
const poster = $(ele)
|
||||
.find(
|
||||
"div.deslide-item > div.deslide-cover > div.deslide-cover-img > img.film-poster-img"
|
||||
)
|
||||
.attr("data-src");
|
||||
const title = $(ele)
|
||||
.find(
|
||||
"div.deslide-item > div.deslide-item-content > div.desi-head-title"
|
||||
)
|
||||
.text()
|
||||
.trim();
|
||||
const japanese_title = $(ele)
|
||||
.find(
|
||||
"div.deslide-item > div.deslide-item-content > div.desi-head-title"
|
||||
)
|
||||
.attr("data-jname")
|
||||
.trim();
|
||||
const description = $(ele)
|
||||
.find(
|
||||
"div.deslide-item > div.deslide-item-content > div.desi-description"
|
||||
)
|
||||
.text()
|
||||
.trim();
|
||||
const id = $(ele)
|
||||
.find(
|
||||
".deslide-item > .deslide-item-content > .desi-buttons > a:eq(0)"
|
||||
)
|
||||
.attr("href")
|
||||
.split("/")
|
||||
.pop();
|
||||
const data_id = $(ele)
|
||||
.find(
|
||||
".deslide-item > .deslide-item-content > .desi-buttons > a:eq(0)"
|
||||
)
|
||||
.attr("href")
|
||||
.split("/")
|
||||
.pop()
|
||||
.split("-")
|
||||
.pop();
|
||||
const tvInfoMapping = {
|
||||
0: "showType",
|
||||
1: "duration",
|
||||
2: "releaseDate",
|
||||
3: "quality",
|
||||
4: "episodeInfo",
|
||||
};
|
||||
|
||||
const tvInfo = {};
|
||||
|
||||
await Promise.all(
|
||||
$(ele)
|
||||
.find("div.sc-detail > div.scd-item")
|
||||
.map(async (index, element) => {
|
||||
const key = tvInfoMapping[index];
|
||||
let value = $(element).text().trim().replace(/\n/g, "");
|
||||
|
||||
const tickContainer = $(element).find(".tick");
|
||||
|
||||
if (tickContainer.length > 0) {
|
||||
value = {
|
||||
sub: tickContainer.find(".tick-sub").text().trim(),
|
||||
dub: tickContainer.find(".tick-dub").text().trim(),
|
||||
};
|
||||
}
|
||||
tvInfo[key] = value;
|
||||
})
|
||||
);
|
||||
return {
|
||||
id,
|
||||
data_id,
|
||||
poster,
|
||||
title,
|
||||
japanese_title,
|
||||
description,
|
||||
tvInfo,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const serverData = await Promise.all(promises);
|
||||
return JSON.parse(JSON.stringify(serverData, null, 2));
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error.message);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
export default extractSpotlights;
|
||||
68
src/extractors/streamInfo.extractor.js
Normal file
68
src/extractors/streamInfo.extractor.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
// import decryptMegacloud from "../parsers/decryptors/megacloud.decryptor.js";
|
||||
// import AniplayExtractor from "../parsers/aniplay.parser.js";
|
||||
import { decryptSources_v1 } from "../parsers/decryptors/decrypt_v1.decryptor.js";
|
||||
|
||||
export async function extractServers(id) {
|
||||
try {
|
||||
const resp = await axios.get(
|
||||
`https://${v1_base_url}/ajax/v2/episode/servers?episodeId=${id}`
|
||||
);
|
||||
const $ = cheerio.load(resp.data.html);
|
||||
const serverData = [];
|
||||
$(".server-item").each((index, element) => {
|
||||
const data_id = $(element).attr("data-id");
|
||||
const server_id = $(element).attr("data-server-id");
|
||||
const type = $(element).attr("data-type");
|
||||
|
||||
const serverName = $(element).find("a").text().trim();
|
||||
serverData.push({
|
||||
type,
|
||||
data_id,
|
||||
server_id,
|
||||
serverName,
|
||||
});
|
||||
});
|
||||
return serverData;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function extractStreamingInfo(id, name, type, fallback) {
|
||||
try {
|
||||
const servers = await extractServers(id.split("?ep=").pop());
|
||||
let requestedServer = servers.filter(
|
||||
(server) =>
|
||||
server.serverName.toLowerCase() === name.toLowerCase() &&
|
||||
server.type.toLowerCase() === type.toLowerCase()
|
||||
);
|
||||
if (requestedServer.length === 0) {
|
||||
requestedServer = servers.filter(
|
||||
(server) =>
|
||||
server.serverName.toLowerCase() === name.toLowerCase() &&
|
||||
server.type.toLowerCase() === "raw"
|
||||
);
|
||||
}
|
||||
if (requestedServer.length === 0) {
|
||||
throw new Error(
|
||||
`No matching server found for name: ${name}, type: ${type}`
|
||||
);
|
||||
}
|
||||
const streamingLink = await decryptSources_v1(
|
||||
id,
|
||||
requestedServer[0].data_id,
|
||||
name,
|
||||
type,
|
||||
fallback
|
||||
);
|
||||
return { streamingLink, servers };
|
||||
} catch (error) {
|
||||
console.error("An error occurred:", error);
|
||||
return { streamingLink: [], servers: [] };
|
||||
}
|
||||
}
|
||||
export { extractStreamingInfo };
|
||||
19
src/extractors/subtitle.extractor.js
Normal file
19
src/extractors/subtitle.extractor.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import axios from "axios";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
import { provider } from "../utils/provider.js";
|
||||
|
||||
export async function extractSubtitle(id) {
|
||||
const resp = await axios.get(
|
||||
`https://${v1_base_url}/ajax/v2/episode/sources/?id=${id}`
|
||||
);
|
||||
const source = await axios.get(
|
||||
`${provider}/embed-2/ajax/e-1/getSources?id=${resp.data.link
|
||||
.split("/")
|
||||
.pop()
|
||||
.replace(/\?k=\d?/g, "")}`
|
||||
);
|
||||
const subtitles = source.data.tracks;
|
||||
const intro = source.data.intro;
|
||||
const outro = source.data.outro;
|
||||
return { subtitles, intro, outro };
|
||||
}
|
||||
50
src/extractors/suggestion.extractor.js
Normal file
50
src/extractors/suggestion.extractor.js
Normal file
@@ -0,0 +1,50 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
async function getSuggestions(keyword) {
|
||||
try {
|
||||
const resp = await axios.get(
|
||||
`https://${v1_base_url}/ajax/search/suggest?keyword=${keyword}`
|
||||
);
|
||||
const $ = cheerio.load(resp.data.html);
|
||||
const results = [];
|
||||
$(".nav-item")
|
||||
.not(".nav-bottom")
|
||||
.each((i, element) => {
|
||||
const id = $(element).attr("href").split("?")[0].replace("/", "");
|
||||
const data_id = id.split("-").pop();
|
||||
const poster = $(element).find(".film-poster-img").attr("data-src");
|
||||
const title = $(element).find(".film-name").text().trim();
|
||||
const japanese_title = $(element).find(".film-name").attr("data-jname").trim();
|
||||
const releaseDate = $(element)
|
||||
.find(".film-infor span")
|
||||
.first()
|
||||
.text()
|
||||
.trim();
|
||||
const filmInforHtml = $(element).find(".film-infor").html();
|
||||
const showTypeMatch = /<i class="dot"><\/i>([^<]+)<i class="dot"><\/i>/;
|
||||
const showType = showTypeMatch.exec(filmInforHtml)?.[1]?.trim() || "";
|
||||
const duration = $(element)
|
||||
.find(".film-infor span")
|
||||
.last()
|
||||
.text()
|
||||
.trim();
|
||||
results.push({
|
||||
id,
|
||||
data_id,
|
||||
poster,
|
||||
title,
|
||||
japanese_title,
|
||||
releaseDate,
|
||||
showType,
|
||||
duration,
|
||||
});
|
||||
});
|
||||
return results;
|
||||
} catch (error) {
|
||||
console.log(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
export default getSuggestions;
|
||||
21
src/extractors/topsearch.extractor.js
Normal file
21
src/extractors/topsearch.extractor.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
async function extractTopSearch() {
|
||||
try {
|
||||
const { data } = await axios.get(`https://${v1_base_url}`);
|
||||
const $ = cheerio.load(data);
|
||||
const results = [];
|
||||
$(".xhashtag a.item").each((_, element) => {
|
||||
const title = $(element).text().trim();
|
||||
const link = $(element).attr("href");
|
||||
results.push({ title, link });
|
||||
});
|
||||
return results;
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error.message);
|
||||
}
|
||||
}
|
||||
|
||||
export default extractTopSearch;
|
||||
51
src/extractors/topten.extractor.js
Normal file
51
src/extractors/topten.extractor.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
async function extractTopTen() {
|
||||
try {
|
||||
const resp = await axios.get(`https://${v1_base_url}/home`);
|
||||
const $ = cheerio.load(resp.data);
|
||||
|
||||
const labels = ["today", "week", "month"];
|
||||
const result = {};
|
||||
|
||||
labels.forEach((label, idx) => {
|
||||
const data = $(
|
||||
`#main-sidebar .block_area-realtime .block_area-content ul:eq(${idx})>li`
|
||||
)
|
||||
.map((index, element) => {
|
||||
const number = $(".film-number>span", element).text().trim();
|
||||
const title = $(".film-detail>.film-name>a", element).text().trim();
|
||||
const poster = $(".film-poster>img", element).attr("data-src");
|
||||
const japanese_title = $(".film-detail>.film-name>a", element)
|
||||
.attr("data-jname")
|
||||
.trim();
|
||||
const data_id = $(".film-poster", element).attr("data-id");
|
||||
const id = $(".film-detail>.film-name>a", element)
|
||||
.attr("href")
|
||||
.split("/")
|
||||
.pop();
|
||||
const tvInfo = ["sub", "dub", "eps"].reduce((info, property) => {
|
||||
const value = $(`.tick .tick-${property}`, element).text().trim();
|
||||
if (value) {
|
||||
info[property] = value;
|
||||
}
|
||||
return info;
|
||||
}, {});
|
||||
|
||||
return { id, data_id, number, title, japanese_title, poster, tvInfo };
|
||||
})
|
||||
.get();
|
||||
|
||||
result[label] = data;
|
||||
});
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export default extractTopTen;
|
||||
35
src/extractors/trending.extractor.js
Normal file
35
src/extractors/trending.extractor.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
async function fetchAnimeDetails(element) {
|
||||
const data_id = element.attr("data-id");
|
||||
const number = element.find(".number > span").text();
|
||||
const poster = element.find("img").attr("data-src");
|
||||
const title = element.find(".film-title").text().trim();
|
||||
const japanese_title = element.find(".film-title").attr("data-jname").trim();
|
||||
const id = element.find("a").attr("href").split("/").pop();
|
||||
return { id, data_id, number, poster, title, japanese_title };
|
||||
}
|
||||
|
||||
async function extractTrending() {
|
||||
try {
|
||||
const resp = await axios.get(`https://${v1_base_url}/home`);
|
||||
const $ = cheerio.load(resp.data);
|
||||
|
||||
const trendingElements = $("#anime-trending #trending-home .swiper-slide");
|
||||
const elementPromises = trendingElements
|
||||
.map((index, element) => {
|
||||
return fetchAnimeDetails($(element));
|
||||
})
|
||||
.get();
|
||||
|
||||
const trendingData = await Promise.all(elementPromises);
|
||||
return JSON.parse(JSON.stringify(trendingData));
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error.message);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
export default extractTrending;
|
||||
78
src/extractors/voiceactor.extractor.js
Normal file
78
src/extractors/voiceactor.extractor.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
export default async function extractVoiceActor(id, page) {
|
||||
try {
|
||||
const resp = await axios.get(
|
||||
`https://${v1_base_url}/ajax/character/list/${id
|
||||
.split("-")
|
||||
.pop()}?page=${page}`
|
||||
);
|
||||
const $ = cheerio.load(resp.data.html);
|
||||
let totalPages = 1;
|
||||
const paginationList = $(".pre-pagination nav ul");
|
||||
if (paginationList.length) {
|
||||
const lastPageLink = paginationList.find("li").last().find("a");
|
||||
const pageNumber =
|
||||
lastPageLink.attr("data-url")?.match(/page=(\d+)/)?.[1] ||
|
||||
lastPageLink.text().trim();
|
||||
totalPages = parseInt(pageNumber) || totalPages;
|
||||
}
|
||||
const charactersVoiceActors = $(".bac-list-wrap .bac-item")
|
||||
.map((index, el) => {
|
||||
const character = {
|
||||
id:
|
||||
$(el)
|
||||
.find(".per-info.ltr .pi-avatar")
|
||||
.attr("href")
|
||||
?.split("/")[2] || "",
|
||||
poster:
|
||||
$(el).find(".per-info.ltr .pi-avatar img").attr("data-src") || "",
|
||||
name: $(el).find(".per-info.ltr .pi-detail a").text(),
|
||||
cast: $(el).find(".per-info.ltr .pi-detail .pi-cast").text(),
|
||||
};
|
||||
|
||||
let voiceActors = [];
|
||||
const rtlVoiceActors = $(el).find(".per-info.rtl");
|
||||
const xxVoiceActors = $(el).find(
|
||||
".per-info.per-info-xx .pix-list .pi-avatar"
|
||||
);
|
||||
if (rtlVoiceActors.length > 0) {
|
||||
voiceActors = rtlVoiceActors
|
||||
.map((_, actorEl) => ({
|
||||
id: $(actorEl).find("a").attr("href")?.split("/").pop() || "",
|
||||
poster: $(actorEl).find("img").attr("data-src") || "",
|
||||
name:
|
||||
$(actorEl).find(".pi-detail .pi-name a").text().trim() || "",
|
||||
}))
|
||||
.get();
|
||||
} else if (xxVoiceActors.length > 0) {
|
||||
voiceActors = xxVoiceActors
|
||||
.map((_, actorEl) => ({
|
||||
id: $(actorEl).attr("href")?.split("/").pop() || "",
|
||||
poster: $(actorEl).find("img").attr("data-src") || "",
|
||||
name: $(actorEl).attr("title") || "",
|
||||
}))
|
||||
.get();
|
||||
}
|
||||
if (voiceActors.length === 0) {
|
||||
voiceActors = $(el)
|
||||
.find(".per-info.per-info-xx .pix-list .pi-avatar")
|
||||
.map((_, actorEl) => ({
|
||||
id: $(actorEl).attr("href")?.split("/")[2] || "",
|
||||
poster: $(actorEl).find("img").attr("data-src") || "",
|
||||
name: $(actorEl).attr("title") || "",
|
||||
}))
|
||||
.get();
|
||||
}
|
||||
|
||||
return { character, voiceActors };
|
||||
})
|
||||
.get();
|
||||
return { totalPages, charactersVoiceActors };
|
||||
} catch (error) {
|
||||
console.error("Error in extractVoiceActor:", error);
|
||||
throw new Error("Could not extract voice actors");
|
||||
}
|
||||
}
|
||||
63
src/extractors/watchlist.extractor.js
Normal file
63
src/extractors/watchlist.extractor.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
export default async function extractWatchlist(userId, page = 1) {
|
||||
try {
|
||||
const url = `https://${v1_base_url}/community/user/${userId}/watch-list?page=${page}`;
|
||||
const { data } = await axios.get(url);
|
||||
const $ = cheerio.load(data);
|
||||
const watchlist = [];
|
||||
|
||||
const totalPages =
|
||||
Number(
|
||||
$('.pre-pagination nav .pagination > .page-item a[title="Last"]')
|
||||
?.attr("href")
|
||||
?.split("=")
|
||||
.pop() ??
|
||||
$('.pre-pagination nav .pagination > .page-item a[title="Next"]')
|
||||
?.attr("href")
|
||||
?.split("=")
|
||||
.pop() ??
|
||||
$(".pre-pagination nav .pagination > .page-item.active a")
|
||||
?.text()
|
||||
?.trim()
|
||||
) || 1;
|
||||
|
||||
$(".flw-item").each((index, element) => {
|
||||
const title = $(".film-name a", element).text().trim();
|
||||
const poster = $(".film-poster img", element).attr("data-src");
|
||||
const duration = $(".fdi-duration", element).text().trim();
|
||||
const type = $(".fdi-item", element).first().text().trim();
|
||||
const id = $(".film-poster a", element).attr("data-id");
|
||||
const subCount = $(".tick-item.tick-sub", element).text().trim();
|
||||
const dubCount = $(".tick-item.tick-dub", element).text().trim();
|
||||
const link = $(".film-name a", element).attr("href");
|
||||
|
||||
const animeId = link.split("/").pop();
|
||||
|
||||
watchlist.push({
|
||||
id: animeId,
|
||||
title,
|
||||
poster,
|
||||
duration,
|
||||
type,
|
||||
subCount,
|
||||
dubCount,
|
||||
link: `https://${v1_base_url}${link}`,
|
||||
showType: type,
|
||||
tvInfo: {
|
||||
showType: type,
|
||||
duration: duration,
|
||||
sub: subCount,
|
||||
dub: dubCount,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
return { watchlist, totalPages };
|
||||
} catch (error) {
|
||||
console.error("Error fetching watchlist:", error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
34
src/helper/cache.helper.js
Normal file
34
src/helper/cache.helper.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import axios from "axios";
|
||||
import dotenv from "dotenv";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const CACHE_SERVER_URL = process.env.CACHE_URL || null;
|
||||
|
||||
export const getCachedData = async (key) => {
|
||||
try {
|
||||
if (!CACHE_SERVER_URL) {
|
||||
console.log(CACHE_SERVER_URL);
|
||||
return;
|
||||
}
|
||||
const response = await axios.get(`${CACHE_SERVER_URL}/${key}`);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
if (error.response && error.response.status === 404) {
|
||||
return null;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const setCachedData = async (key, value) => {
|
||||
try {
|
||||
if (!CACHE_SERVER_URL) {
|
||||
return;
|
||||
}
|
||||
await axios.post(CACHE_SERVER_URL, { key, value });
|
||||
} catch (error) {
|
||||
console.error("Error setting cache data:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
24
src/helper/countPages.helper.js
Normal file
24
src/helper/countPages.helper.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { DEFAULT_HEADERS } from "../configs/header.config.js";
|
||||
|
||||
const axiosInstance = axios.create({ headers: DEFAULT_HEADERS });
|
||||
|
||||
async function countPages(url) {
|
||||
try {
|
||||
const { data } = await axiosInstance.get(url);
|
||||
const $ = cheerio.load(data);
|
||||
const lastPageHref = $(
|
||||
".tab-content .pagination .page-item:last-child a"
|
||||
).attr("href");
|
||||
const lastPageNumber = lastPageHref
|
||||
? parseInt(lastPageHref.split("=").pop())
|
||||
: 1;
|
||||
return lastPageNumber;
|
||||
} catch (error) {
|
||||
console.error("Error counting pages:", error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export default countPages;
|
||||
92
src/helper/extractPages.helper.js
Normal file
92
src/helper/extractPages.helper.js
Normal file
@@ -0,0 +1,92 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
import { DEFAULT_HEADERS } from "../configs/header.config.js";
|
||||
|
||||
const axiosInstance = axios.create({ headers: DEFAULT_HEADERS });
|
||||
|
||||
async function extractPage(page, params) {
|
||||
try {
|
||||
const resp = await axiosInstance.get(`https://${v1_base_url}/${params}?page=${page}`);
|
||||
const $ = cheerio.load(resp.data);
|
||||
const totalPages =
|
||||
Number(
|
||||
$('.pre-pagination nav .pagination > .page-item a[title="Last"]')
|
||||
?.attr("href")
|
||||
?.split("=")
|
||||
.pop() ??
|
||||
$('.pre-pagination nav .pagination > .page-item a[title="Next"]')
|
||||
?.attr("href")
|
||||
?.split("=")
|
||||
.pop() ??
|
||||
$(".pre-pagination nav .pagination > .page-item.active a")
|
||||
?.text()
|
||||
?.trim()
|
||||
) || 1;
|
||||
|
||||
const contentSelector = params.includes("az-list")
|
||||
? ".tab-content"
|
||||
: "#main-content";
|
||||
const data = await Promise.all(
|
||||
$(`${contentSelector} .film_list-wrap .flw-item`).map(
|
||||
async (index, element) => {
|
||||
const $fdiItems = $(".film-detail .fd-infor .fdi-item", element);
|
||||
const showType = $fdiItems
|
||||
.filter((_, item) => {
|
||||
const text = $(item).text().trim().toLowerCase();
|
||||
return ["tv", "ona", "movie", "ova", "special", "music"].some((type) =>
|
||||
text.includes(type)
|
||||
);
|
||||
})
|
||||
.first();
|
||||
const poster = $(".film-poster>img", element).attr("data-src");
|
||||
const title = $(".film-detail .film-name", element).text();
|
||||
const japanese_title = $(".film-detail>.film-name>a", element).attr(
|
||||
"data-jname"
|
||||
);
|
||||
const description = $(".film-detail .description", element)
|
||||
.text()
|
||||
.trim();
|
||||
const data_id = $(".film-poster>a", element).attr("data-id");
|
||||
const id = $(".film-poster>a", element).attr("href").split("/").pop();
|
||||
const tvInfo = {
|
||||
showType: showType ? showType.text().trim() : "Unknown",
|
||||
duration: $(".film-detail .fd-infor .fdi-duration", element)
|
||||
.text()
|
||||
.trim(),
|
||||
};
|
||||
let adultContent = false;
|
||||
const tickRateText = $(".film-poster>.tick-rate", element)
|
||||
.text()
|
||||
.trim();
|
||||
if (tickRateText.includes("18+")) {
|
||||
adultContent = true;
|
||||
}
|
||||
|
||||
["sub", "dub", "eps"].forEach((property) => {
|
||||
const value = $(`.tick .tick-${property}`, element).text().trim();
|
||||
if (value) {
|
||||
tvInfo[property] = value;
|
||||
}
|
||||
});
|
||||
return {
|
||||
id,
|
||||
data_id,
|
||||
poster,
|
||||
title,
|
||||
japanese_title,
|
||||
description,
|
||||
tvInfo,
|
||||
adultContent,
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
return [data, parseInt(totalPages, 10)];
|
||||
} catch (error) {
|
||||
console.error(`Error extracting data from page ${page}:`, error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export default extractPage;
|
||||
8
src/helper/fetchScript.helper.js
Normal file
8
src/helper/fetchScript.helper.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import axios from "axios";
|
||||
|
||||
async function fetchScript(url) {
|
||||
const response = await axios.get(url);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export default fetchScript;
|
||||
76
src/helper/foreignInput.helper.js
Normal file
76
src/helper/foreignInput.helper.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import axios from "axios";
|
||||
// import { getCachedData, setCachedData } from "./cache.helper";
|
||||
|
||||
async function getEnglishTitleFromAniList(userInput) {
|
||||
// const cacheKey = `translation:${userInput}`;
|
||||
|
||||
try {
|
||||
// Check cache
|
||||
// const cachedValue = await getCachedData(cacheKey);
|
||||
// if (cachedValue) {
|
||||
// console.log(`Cache Hit ${userInput} -> ${cachedValue}`)
|
||||
// }
|
||||
|
||||
const query = `
|
||||
query ($search: String) {
|
||||
Media (search: $search, type: ANIME) {
|
||||
title {
|
||||
romaji
|
||||
english
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const response = await axios.post('https://graphql.anilist.co', {
|
||||
query,
|
||||
variables: { search: userInput }
|
||||
}, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
timeout: 3000 // 3 seconds
|
||||
});
|
||||
|
||||
const titles = response.data?.data?.Media?.title;
|
||||
|
||||
if (!titles) {
|
||||
console.log(`AniList no match found for: ${userInput}`);
|
||||
return userInput;
|
||||
}
|
||||
|
||||
const result = titles.english || titles.romaji || userInput;
|
||||
|
||||
// await setCachedData(cacheKey, result);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error("AniList API Error:", error.response?.data || error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function convertForeignLanguage(userInput) {
|
||||
try {
|
||||
if (!userInput) return '';
|
||||
|
||||
// If it's only Latin characters, return as-is
|
||||
if (/^[a-zA-Z\s]+$/.test(userInput)) {
|
||||
return userInput;
|
||||
}
|
||||
|
||||
// Detect if it is Japanese, Chinese or Korean
|
||||
const isForeign = /[\u3040-\u30ff\u3000-\u303f\u4e00-\u9faf\uac00-\ud7af]/.test(userInput);
|
||||
|
||||
if (isForeign) {
|
||||
const translated = await getEnglishTitleFromAniList(userInput);
|
||||
|
||||
return translated;
|
||||
}
|
||||
|
||||
return userInput;
|
||||
} catch (error) {
|
||||
console.error(`Error converting foreign input ${userInput}:`, error.message);
|
||||
return userInput;
|
||||
}
|
||||
}
|
||||
|
||||
export default convertForeignLanguage;
|
||||
9
src/helper/formatTitle.helper.js
Normal file
9
src/helper/formatTitle.helper.js
Normal file
@@ -0,0 +1,9 @@
|
||||
function formatTitle(title, data_id) {
|
||||
let formattedTitle = title.replace(/[^\w\s]/g, "");
|
||||
formattedTitle = formattedTitle.toLowerCase();
|
||||
formattedTitle = formattedTitle.replace(/\s+/g, "-");
|
||||
formattedTitle = `${formattedTitle}-${data_id}`;
|
||||
return formattedTitle;
|
||||
}
|
||||
|
||||
export default formatTitle;
|
||||
34
src/helper/getKey.helper.js
Normal file
34
src/helper/getKey.helper.js
Normal file
@@ -0,0 +1,34 @@
|
||||
class ErrorLoadingException extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "ErrorLoadingException";
|
||||
}
|
||||
}
|
||||
|
||||
function matchingKey(value, script) {
|
||||
const regex = new RegExp(`,${value}=((?:0x)?([0-9a-fA-F]+))`);
|
||||
const match = script.match(regex);
|
||||
if (match) {
|
||||
return match[2];
|
||||
} else {
|
||||
throw new ErrorLoadingException("Failed to match the key");
|
||||
}
|
||||
}
|
||||
|
||||
function getKeys(script) {
|
||||
const regex =
|
||||
/case\s*0x[0-9a-f]+:(?![^;]*=partKey)\s*\w+\s*=\s*(\w+)\s*,\s*\w+\s*=\s*(\w+);/g;
|
||||
const matches = script.matchAll(regex);
|
||||
|
||||
return Array.from(matches, (match) => {
|
||||
const matchKey1 = matchingKey(match[1], script);
|
||||
const matchKey2 = matchingKey(match[2], script);
|
||||
try {
|
||||
return [parseInt(matchKey1, 16), parseInt(matchKey2, 16)];
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}).filter((pair) => pair.length > 0);
|
||||
}
|
||||
|
||||
export default getKeys;
|
||||
71
src/helper/token.helper.js
Normal file
71
src/helper/token.helper.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import axios from 'axios';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { v1_base_url } from '../utils/base_v1.js';
|
||||
|
||||
export default async function extractToken(url) {
|
||||
try {
|
||||
const { data: html } = await axios.get(url, {
|
||||
headers: {
|
||||
Referer: `https://${v1_base_url}/`
|
||||
}
|
||||
});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
const results = {};
|
||||
|
||||
// 1. Meta tag
|
||||
const meta = $('meta[name="_gg_fb"]').attr('content');
|
||||
if (meta) results.meta = meta;
|
||||
|
||||
// 2. Data attribute
|
||||
const dpi = $('[data-dpi]').attr('data-dpi');
|
||||
if (dpi) results.dataDpi = dpi;
|
||||
|
||||
// 3. Nonce from empty script
|
||||
const nonceScript = $('script[nonce]').filter((i, el) => {
|
||||
return $(el).text().includes('empty nonce script');
|
||||
}).attr('nonce');
|
||||
if (nonceScript) results.nonce = nonceScript;
|
||||
|
||||
// 4. JS string assignment: window.<key> = "value";
|
||||
const stringAssignRegex = /window\.(\w+)\s*=\s*["']([\w-]+)["']/g;
|
||||
const stringMatches = [...html.matchAll(stringAssignRegex)];
|
||||
for (const [_, key, value] of stringMatches) {
|
||||
results[`window.${key}`] = value;
|
||||
}
|
||||
|
||||
// 5. JS object assignment: window.<key> = { ... };
|
||||
const objectAssignRegex = /window\.(\w+)\s*=\s*(\{[\s\S]*?\});/g;
|
||||
const matches = [...html.matchAll(objectAssignRegex)];
|
||||
for (const [_, varName, rawObj] of matches) {
|
||||
try {
|
||||
const parsedObj = eval('(' + rawObj + ')');
|
||||
if (parsedObj && typeof parsedObj === 'object') {
|
||||
const stringValues = Object.values(parsedObj).filter(val => typeof val === 'string');
|
||||
const concatenated = stringValues.join('');
|
||||
if (concatenated.length >= 20) {
|
||||
results[`window.${varName}`] = concatenated;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Skip invalid object
|
||||
}
|
||||
}
|
||||
|
||||
// 6. HTML comment: <!-- _is_th:... -->
|
||||
$('*').contents().each(function () {
|
||||
if (this.type === 'comment') {
|
||||
const match = this.data.trim().match(/^_is_th:([\w-]+)$/);
|
||||
if (match) {
|
||||
results.commentToken = match[1].trim();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const token = Object.values(results)[0];
|
||||
return token || null;
|
||||
} catch (err) {
|
||||
console.error('Error:', err.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
94
src/parsers/aniplay.parser.js
Normal file
94
src/parsers/aniplay.parser.js
Normal file
@@ -0,0 +1,94 @@
|
||||
import axios from "axios";
|
||||
import { v3_base_url } from "../utils/base_v3.js";
|
||||
|
||||
const DEFAULT_BASE_URL = `https://${v3_base_url}`;
|
||||
|
||||
class AniplayExtractor {
|
||||
constructor(baseUrl = DEFAULT_BASE_URL) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.keys = null;
|
||||
this.keysTs = 0;
|
||||
}
|
||||
|
||||
isCacheValid() {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
return this.keys && now - this.keysTs < 3600;
|
||||
}
|
||||
|
||||
async fetchHtml(url) {
|
||||
const { data } = await axios.get(url);
|
||||
return data;
|
||||
}
|
||||
|
||||
async fetchStaticJsUrl() {
|
||||
const html = await this.fetchHtml(`${this.baseUrl}/anime/watch/1`);
|
||||
const prefix = "/_next/static/chunks/app/(user)/(media)/";
|
||||
const start = html.indexOf(prefix);
|
||||
if (start === -1) throw new Error("Static chunk path not found in HTML.");
|
||||
|
||||
const slugStart = start + prefix.length;
|
||||
const slugEnd = html.indexOf('"', slugStart);
|
||||
const jsSlug = html.slice(slugStart, slugEnd);
|
||||
return `${this.baseUrl}${prefix}${jsSlug}`;
|
||||
}
|
||||
|
||||
async extractKeys() {
|
||||
if (this.isCacheValid()) return this.keys;
|
||||
|
||||
const scriptUrl = await this.fetchStaticJsUrl();
|
||||
const script = await this.fetchHtml(scriptUrl);
|
||||
|
||||
const regex =
|
||||
/\(0,\w+\.createServerReference\)\("([a-f0-9]+)",\w+\.callServer,void 0,\w+\.findSourceMapURL,"(getSources|getEpisodes)"\)/g;
|
||||
|
||||
const matches = script.matchAll(regex);
|
||||
const keysMap = { baseUrl: this.baseUrl };
|
||||
|
||||
for (const match of matches) {
|
||||
const [, hash, fn] = match;
|
||||
keysMap[fn] = hash;
|
||||
}
|
||||
|
||||
if (!keysMap["getSources"] || !keysMap["getEpisodes"]) {
|
||||
throw new Error("Could not extract all required keys.");
|
||||
}
|
||||
|
||||
this.keys = keysMap;
|
||||
this.keysTs = Math.floor(Date.now() / 1000);
|
||||
return keysMap;
|
||||
}
|
||||
|
||||
async getNextAction() {
|
||||
const keys = await this.extractKeys();
|
||||
return {
|
||||
watch: keys["getSources"],
|
||||
info: keys["getEpisodes"],
|
||||
};
|
||||
}
|
||||
|
||||
async fetchEpisode(animeId, ep, host = "hika", type = "sub") {
|
||||
const nextAction = await this.getNextAction();
|
||||
const url = `${this.baseUrl}/anime/watch/${animeId}?host=${host}&ep=${ep}&type=${type}`;
|
||||
const payload = [
|
||||
String(animeId),
|
||||
host,
|
||||
`${animeId}/${ep}`,
|
||||
String(ep),
|
||||
type,
|
||||
];
|
||||
|
||||
try {
|
||||
const res = await axios.post(url, payload, {
|
||||
headers: {
|
||||
"Next-Action": nextAction.watch,
|
||||
},
|
||||
});
|
||||
const dataStr = res.data.split("1:")[1];
|
||||
return JSON.parse(dataStr);
|
||||
} catch (err) {
|
||||
throw new Error(`Request failed: ${err.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default AniplayExtractor;
|
||||
844
src/parsers/decryptors/decodedpng.js
Normal file
844
src/parsers/decryptors/decodedpng.js
Normal file
@@ -0,0 +1,844 @@
|
||||
export const data = new Uint8ClampedArray([
|
||||
246, 246, 246, 255, 226, 234, 236, 255, 113, 170, 187, 255, 60, 139, 164, 255,
|
||||
60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255,
|
||||
60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255,
|
||||
60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255,
|
||||
60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 0,
|
||||
255, 255, 1, 61, 139, 163, 192, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 130, 180, 196, 254, 242, 243, 244, 254, 246, 246,
|
||||
246, 254, 243, 244, 245, 254, 105, 165, 184, 254, 60, 140, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 140,
|
||||
164, 255, 60, 139, 164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 140,
|
||||
164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 140,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 140,
|
||||
164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 132, 181,
|
||||
196, 254, 243, 245, 245, 254, 188, 212, 220, 254, 60, 139, 164, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 140,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 139,
|
||||
164, 255, 60, 139, 164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 140,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 140,
|
||||
164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 140,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 140,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 139,
|
||||
164, 254, 63, 142, 165, 254, 217, 230, 233, 254, 132, 181, 196, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 255, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 255, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 177, 206, 216, 254, 119, 174,
|
||||
190, 255, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 164, 198,
|
||||
210, 255, 119, 174, 190, 254, 60, 140, 164, 254, 60, 140, 165, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140, 165, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 165, 254, 60, 140, 164, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 165, 254, 60, 140, 164, 254, 60, 140,
|
||||
164, 255, 60, 140, 165, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140,
|
||||
165, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140,
|
||||
165, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140, 165, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140, 165, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 165, 254, 60, 140, 164, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 165, 254, 60, 140, 164, 254, 60, 140,
|
||||
164, 254, 60, 140, 165, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140,
|
||||
165, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140,
|
||||
165, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140, 165, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140, 165, 254, 60, 140,
|
||||
164, 254, 60, 140, 164, 254, 60, 140, 165, 254, 60, 140, 164, 254, 60, 140,
|
||||
164, 254, 60, 140, 165, 254, 60, 140, 164, 254, 60, 140, 164, 254, 60, 140,
|
||||
164, 255, 163, 198, 210, 254, 119, 174, 190, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 255, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 255, 60, 139, 164, 254, 163, 198, 210, 254, 119, 174, 190, 254, 60, 139,
|
||||
164, 254, 60, 140, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139,
|
||||
164, 255, 60, 140, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 140,
|
||||
164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 139, 164, 254, 60, 140,
|
||||
164, 255, 60, 139, 164, 254, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140,
|
||||
164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140,
|
||||
164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 139,
|
||||
164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 139,
|
||||
164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140,
|
||||
164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 139,
|
||||
164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 163, 198, 210, 255, 119, 174,
|
||||
190, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 131, 180,
|
||||
195, 255, 233, 239, 240, 255, 233, 239, 240, 255, 233, 239, 240, 255, 233,
|
||||
239, 240, 255, 233, 239, 240, 255, 233, 239, 240, 255, 233, 239, 240, 255,
|
||||
233, 239, 240, 255, 233, 239, 240, 255, 233, 239, 240, 255, 233, 239, 240,
|
||||
255, 233, 239, 240, 255, 233, 239, 240, 255, 233, 239, 240, 255, 233, 239,
|
||||
240, 255, 233, 239, 240, 255, 233, 239, 240, 255, 233, 239, 240, 255, 233,
|
||||
239, 240, 255, 233, 239, 240, 255, 233, 239, 240, 255, 233, 239, 240, 255,
|
||||
233, 239, 240, 255, 233, 239, 240, 255, 233, 239, 240, 255, 233, 239, 240,
|
||||
255, 233, 239, 240, 255, 233, 239, 240, 255, 233, 239, 240, 255, 233, 239,
|
||||
240, 255, 233, 239, 240, 255, 233, 239, 240, 255, 233, 239, 240, 255, 233,
|
||||
239, 240, 255, 233, 239, 240, 255, 218, 230, 234, 255, 143, 187, 200, 255, 66,
|
||||
143, 167, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60,
|
||||
140, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60,
|
||||
140, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60,
|
||||
139, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 140, 164, 255, 163, 198, 210, 255, 119, 173, 190, 255, 60,
|
||||
139, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 139, 185, 199, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 223, 233, 236,
|
||||
255, 136, 183, 197, 255, 69, 145, 168, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 140, 164,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140, 164,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 139, 164,
|
||||
255, 60, 140, 164, 255, 163, 198, 210, 255, 119, 174, 190, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 139, 184, 199, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 242, 243, 244, 255, 219, 231, 235, 255, 217, 229, 233, 255,
|
||||
217, 229, 233, 255, 217, 229, 233, 255, 217, 229, 233, 255, 217, 229, 233,
|
||||
255, 217, 229, 233, 255, 217, 229, 233, 255, 217, 229, 233, 255, 217, 229,
|
||||
233, 255, 217, 229, 233, 255, 217, 229, 233, 255, 217, 229, 233, 255, 217,
|
||||
229, 233, 255, 217, 229, 233, 255, 97, 160, 180, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 163, 198, 210, 255, 119, 174, 190, 255, 60,
|
||||
140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 139, 185, 199, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 140, 164, 255, 163, 198, 210, 255, 119, 173, 190,
|
||||
255, 60, 140, 164, 255, 60, 140, 165, 255, 60, 140, 164, 255, 139, 185, 199,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60,
|
||||
140, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 163, 198, 210, 255, 119,
|
||||
174, 190, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 139,
|
||||
185, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164,
|
||||
183, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 163, 198,
|
||||
210, 255, 119, 174, 190, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 139,
|
||||
164, 255, 139, 185, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 102, 164, 183, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140, 164,
|
||||
255, 163, 198, 210, 255, 119, 174, 190, 255, 60, 140, 164, 255, 60, 140, 164,
|
||||
255, 60, 139, 164, 255, 139, 185, 199, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 102, 164, 183, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
140, 164, 255, 163, 198, 210, 255, 119, 173, 190, 255, 60, 139, 164, 255, 60,
|
||||
140, 164, 255, 60, 140, 164, 255, 139, 185, 199, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 102, 164, 183, 255, 60, 140, 164, 255, 60, 139, 164,
|
||||
255, 60, 140, 164, 255, 163, 198, 210, 255, 119, 174, 190, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 139, 184, 199, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 163, 198, 210, 255, 119, 174, 190, 255, 60,
|
||||
140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 139, 185, 199, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 140, 164, 255, 163, 198, 210, 255, 119, 173, 190,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 139, 185, 199,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 163, 198, 210, 255, 119,
|
||||
174, 190, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 139,
|
||||
185, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 241, 243, 244, 255, 227, 235, 238, 255, 243, 245, 245, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
230, 237, 239, 255, 239, 242, 243, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 233, 239, 241, 255, 235, 239, 241,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 239, 242, 243, 255, 230, 236, 239, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164,
|
||||
183, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 163, 198,
|
||||
210, 255, 119, 174, 190, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 139,
|
||||
164, 255, 139, 185, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 216, 230, 233, 255, 94, 160, 179, 255, 66, 143, 166, 255, 99, 161, 182,
|
||||
255, 221, 232, 236, 255, 246, 246, 246, 255, 245, 245, 245, 255, 127, 178,
|
||||
194, 255, 68, 144, 168, 255, 79, 150, 173, 255, 187, 213, 220, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 154, 193, 205, 255, 73, 147, 170, 255, 72, 146, 169,
|
||||
255, 156, 194, 206, 255, 246, 246, 246, 255, 246, 246, 246, 255, 208, 223,
|
||||
229, 255, 85, 154, 176, 255, 65, 143, 166, 255, 112, 169, 187, 255, 236, 240,
|
||||
242, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164, 183,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 163, 198, 210,
|
||||
255, 119, 174, 190, 255, 60, 140, 164, 255, 60, 140, 165, 255, 60, 140, 164,
|
||||
255, 139, 185, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
137, 184, 197, 255, 60, 140, 165, 255, 60, 140, 164, 255, 60, 140, 164, 255,
|
||||
88, 156, 177, 255, 210, 226, 230, 255, 133, 181, 196, 255, 60, 140, 164, 255,
|
||||
60, 140, 165, 255, 60, 140, 164, 255, 85, 154, 175, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 239,
|
||||
242, 243, 255, 64, 143, 166, 255, 60, 140, 165, 255, 60, 140, 164, 255, 60,
|
||||
140, 164, 255, 146, 189, 202, 255, 203, 221, 227, 255, 70, 145, 168, 255, 60,
|
||||
140, 164, 255, 60, 140, 165, 255, 60, 140, 164, 255, 165, 200, 210, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60, 140, 164,
|
||||
255, 60, 140, 164, 255, 60, 140, 164, 255, 163, 198, 210, 255, 119, 173, 190,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 139, 185, 199,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 137, 183, 198, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 67,
|
||||
144, 167, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 86, 154, 175, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 237, 241, 242, 255, 64, 142, 166,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140, 164,
|
||||
255, 64, 141, 166, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 164, 200, 211, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 102, 163, 183, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 163, 198, 210, 255, 119, 174, 190, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 139, 184, 199, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 218, 230, 234, 255, 83, 153, 174, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 67, 144, 167, 255, 174, 206, 215,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 153, 193, 205, 255, 60, 139, 164, 255,
|
||||
60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255,
|
||||
60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 101, 163, 182, 255,
|
||||
226, 235, 238, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102,
|
||||
164, 183, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 163,
|
||||
198, 210, 255, 119, 174, 190, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60,
|
||||
139, 164, 255, 139, 185, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 213, 227, 231, 255, 85, 154, 175, 255, 60, 140,
|
||||
164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140,
|
||||
164, 255, 64, 142, 165, 255, 178, 208, 216, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 242, 243, 244, 255, 148, 189, 203, 255, 60, 139, 164,
|
||||
255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 60, 140, 164, 255, 97, 160, 180, 255, 231, 238, 240, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 163, 198, 210, 255, 119,
|
||||
173, 190, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 139,
|
||||
185, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 244, 245, 245, 255, 112, 169, 187, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 67, 143,
|
||||
167, 255, 229, 236, 239, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 200, 220, 226, 255, 61, 141, 165, 255, 60, 139,
|
||||
164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 140, 186, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 163, 198, 210, 255, 119, 174, 190,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 139, 185, 199,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 235, 240, 242, 255,
|
||||
133, 181, 196, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255,
|
||||
60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255,
|
||||
86, 155, 176, 255, 221, 232, 236, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 203,
|
||||
221, 227, 255, 70, 145, 168, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 150, 191, 204, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 60, 139, 164, 255, 163, 198, 210, 255, 119, 174, 190, 255, 60, 140,
|
||||
164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 139, 185, 199, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 165, 199, 210, 255, 60, 139, 164, 255,
|
||||
60, 139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255,
|
||||
60, 139, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255,
|
||||
115, 171, 188, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 245, 245, 245, 255, 83, 153, 174, 255, 60,
|
||||
140, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 61,
|
||||
141, 165, 255, 192, 215, 222, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 102, 164, 183, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140,
|
||||
164, 255, 163, 198, 210, 255, 119, 174, 190, 255, 60, 140, 164, 255, 60, 140,
|
||||
165, 255, 60, 140, 164, 255, 139, 185, 199, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 131, 181, 196, 255, 60, 140, 165, 255, 60, 140, 164, 255,
|
||||
60, 140, 164, 255, 67, 143, 168, 255, 140, 185, 200, 255, 83, 153, 174, 255,
|
||||
60, 140, 164, 255, 60, 140, 165, 255, 60, 140, 164, 255, 79, 151, 173, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 231, 238, 240, 255, 60, 140, 164, 255, 60, 140, 165, 255, 60,
|
||||
140, 164, 255, 60, 140, 164, 255, 89, 156, 177, 255, 124, 176, 192, 255, 60,
|
||||
140, 164, 255, 60, 140, 164, 255, 60, 140, 165, 255, 60, 140, 164, 255, 158,
|
||||
195, 207, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164,
|
||||
183, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 163, 198,
|
||||
210, 255, 119, 173, 190, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 139, 185, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 181, 208, 217, 255, 68, 144, 167, 255, 60, 139, 164, 255, 64, 141, 166,
|
||||
255, 174, 205, 214, 255, 245, 246, 246, 255, 209, 224, 229, 255, 81, 151, 173,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 129, 179, 194, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
245, 246, 246, 255, 104, 165, 184, 255, 60, 139, 164, 255, 60, 139, 164, 255,
|
||||
96, 160, 180, 255, 231, 237, 239, 255, 242, 244, 244, 255, 140, 185, 200, 255,
|
||||
60, 139, 164, 255, 60, 139, 164, 255, 68, 144, 168, 255, 205, 222, 228, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 163, 183, 255, 60, 139,
|
||||
164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 163, 198, 210, 255, 119, 174,
|
||||
190, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 139, 185,
|
||||
199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 192, 215, 222, 255, 155, 194, 206, 255, 194, 216, 223, 255, 245, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 220, 231, 235, 255, 160,
|
||||
197, 208, 255, 177, 207, 215, 255, 238, 242, 242, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 227, 236, 237, 255, 169, 202, 212, 255, 169, 202, 212, 255,
|
||||
226, 234, 237, 255, 246, 246, 246, 255, 246, 246, 246, 255, 242, 244, 244,
|
||||
255, 183, 210, 219, 255, 155, 194, 206, 255, 205, 222, 228, 255, 245, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164, 183,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 163, 198, 210,
|
||||
255, 119, 174, 190, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 139, 164,
|
||||
255, 139, 185, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
102, 164, 183, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255,
|
||||
163, 198, 210, 255, 119, 173, 190, 255, 60, 139, 164, 255, 60, 139, 164, 255,
|
||||
60, 139, 164, 255, 139, 185, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 102, 164, 183, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 163, 198, 210, 255, 119, 174, 190, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 60, 139, 164, 255, 139, 184, 199, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 102, 164, 183, 255, 60, 139, 164, 255, 60, 139, 164, 255,
|
||||
60, 139, 164, 255, 163, 198, 210, 255, 119, 174, 190, 255, 60, 140, 164, 255,
|
||||
60, 140, 164, 255, 60, 139, 164, 255, 139, 185, 199, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 215, 229, 233, 255, 222, 233, 236,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 223, 233, 236, 255, 213, 227, 232, 255, 245, 245, 245, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 60, 140, 164, 255, 163, 198, 210, 255, 119, 174, 190, 255, 60, 140,
|
||||
164, 255, 60, 140, 165, 255, 60, 140, 164, 255, 139, 185, 199, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 242, 244, 244, 255, 111, 169, 186, 255, 60, 140, 165, 255, 64, 142,
|
||||
166, 255, 132, 181, 196, 255, 216, 229, 233, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 222, 233, 236, 255, 164, 199, 210, 255, 97, 161, 180, 255, 73,
|
||||
147, 170, 255, 106, 166, 184, 255, 178, 207, 216, 255, 235, 239, 242, 255,
|
||||
246, 246, 246, 255, 241, 243, 244, 255, 201, 221, 226, 255, 117, 172, 189,
|
||||
255, 61, 141, 165, 255, 61, 140, 164, 255, 138, 185, 198, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 102, 164, 183, 255, 60, 140, 164, 255, 60, 140, 164,
|
||||
255, 60, 140, 164, 255, 163, 198, 210, 255, 119, 173, 190, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 139, 185, 199, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 196, 217, 224, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 74, 147, 171, 255, 132, 181, 195, 255, 150, 191, 204,
|
||||
255, 77, 149, 172, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 95, 160, 180, 255, 158, 196, 207,
|
||||
255, 120, 173, 191, 255, 61, 140, 165, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 63, 141, 165, 255, 230, 237, 239, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 102, 163, 183, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 163, 198, 210, 255, 119, 174, 190, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 139, 185, 199, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 202, 221, 226,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 67, 144, 167, 255, 236, 241, 242, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164, 183,
|
||||
255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 163, 198, 210,
|
||||
255, 119, 174, 190, 255, 60, 140, 164, 255, 60, 140, 165, 255, 60, 140, 164,
|
||||
255, 139, 185, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 136, 183,
|
||||
198, 255, 64, 142, 166, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 140,
|
||||
165, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 140,
|
||||
165, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 140, 165, 255, 60, 140,
|
||||
164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 140, 165, 255, 60, 140,
|
||||
164, 255, 60, 140, 164, 255, 60, 140, 165, 255, 71, 145, 168, 255, 153, 192,
|
||||
205, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60, 140,
|
||||
164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 163, 198, 210, 255, 119, 173,
|
||||
190, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 139, 185,
|
||||
199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 206,
|
||||
224, 229, 255, 118, 172, 190, 255, 64, 141, 165, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 95,
|
||||
160, 180, 255, 143, 187, 200, 255, 87, 155, 176, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 63,
|
||||
141, 165, 255, 134, 181, 196, 255, 225, 235, 237, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 102, 163, 183, 255, 60, 139, 164, 255,
|
||||
60, 139, 164, 255, 60, 139, 164, 255, 163, 198, 210, 255, 119, 174, 190, 255,
|
||||
60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 139, 184, 199, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 212, 227, 231, 255, 129, 179, 194, 255, 89, 157, 177,
|
||||
255, 85, 154, 175, 255, 111, 169, 187, 255, 183, 210, 219, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 243, 245, 245, 255, 172, 203, 213, 255, 106, 165,
|
||||
184, 255, 83, 153, 174, 255, 93, 159, 179, 255, 142, 187, 201, 255, 221, 231,
|
||||
235, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 163, 198, 210, 255, 119, 174, 190, 255, 60,
|
||||
140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 139, 185, 199, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 244, 245, 246,
|
||||
255, 244, 245, 245, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 243, 244, 245, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60, 139, 164,
|
||||
255, 60, 139, 164, 255, 60, 140, 164, 255, 163, 198, 210, 255, 119, 174, 190,
|
||||
255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 139, 185, 199,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 164, 183, 255, 60,
|
||||
140, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 163, 198, 210, 255, 119,
|
||||
174, 190, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 139,
|
||||
185, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 102, 163,
|
||||
183, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 163, 198,
|
||||
210, 255, 119, 174, 190, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139,
|
||||
164, 255, 139, 185, 199, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246,
|
||||
246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246,
|
||||
246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255,
|
||||
246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246, 255, 246, 246, 246,
|
||||
255, 102, 164, 183, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164,
|
||||
255, 163, 198, 210, 255, 129, 180, 195, 255, 60, 140, 164, 255, 60, 140, 165,
|
||||
255, 60, 140, 164, 255, 93, 158, 178, 255, 158, 196, 207, 255, 159, 197, 207,
|
||||
255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197,
|
||||
207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159,
|
||||
197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255,
|
||||
159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207,
|
||||
255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197,
|
||||
207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159,
|
||||
197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255,
|
||||
159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207,
|
||||
255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197,
|
||||
207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159,
|
||||
197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255,
|
||||
159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207,
|
||||
255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197,
|
||||
207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 159, 197, 207, 255, 156,
|
||||
194, 207, 255, 69, 144, 168, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60,
|
||||
140, 164, 255, 169, 202, 212, 255, 176, 206, 215, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 203, 221, 227, 255, 234, 239, 240, 255, 84,
|
||||
153, 175, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 107, 167, 185, 255, 241, 243, 244, 255, 246,
|
||||
246, 246, 255, 203, 221, 227, 255, 85, 154, 176, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60,
|
||||
140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60,
|
||||
140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60,
|
||||
140, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60,
|
||||
140, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60,
|
||||
139, 164, 255, 60, 139, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60,
|
||||
139, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60,
|
||||
139, 164, 255, 60, 140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60,
|
||||
140, 164, 255, 60, 140, 164, 255, 60, 139, 164, 255, 60, 139, 164, 255, 60,
|
||||
140, 164, 255, 60, 139, 164, 255, 92, 157, 179, 255, 222, 232, 236, 255, 246,
|
||||
246, 246, 255,
|
||||
]);
|
||||
22
src/parsers/decryptors/decryptAllServers.decryptor.js
Normal file
22
src/parsers/decryptors/decryptAllServers.decryptor.js
Normal file
@@ -0,0 +1,22 @@
|
||||
// this is kept as backup in case megacloud's architecture rollback to it's previous architecture
|
||||
|
||||
|
||||
// import decryptMegacloud from "./megacloud.decryptor.js";
|
||||
|
||||
// export async function decryptAllServers(data) {
|
||||
// const promises = data.map(async (server) => {
|
||||
// try {
|
||||
// if (
|
||||
// server.type === "sub" ||
|
||||
// server.type === "dub" ||
|
||||
// server.type === "raw"
|
||||
// ) {
|
||||
// return await decryptMegacloud(server.id, server.name, server.type);
|
||||
// }
|
||||
// } catch (error) {
|
||||
// console.error(`Error decrypting server ${server.id}:`, error);
|
||||
// return null;
|
||||
// }
|
||||
// });
|
||||
// return Promise.all(promises);
|
||||
// }
|
||||
152
src/parsers/decryptors/decrypt_v1.decryptor.js
Normal file
152
src/parsers/decryptors/decrypt_v1.decryptor.js
Normal file
@@ -0,0 +1,152 @@
|
||||
import axios from "axios";
|
||||
import CryptoJS from "crypto-js";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../../utils/base_v1.js";
|
||||
import { v4_base_url } from "../../utils/base_v4.js";
|
||||
import { fallback_1, fallback_2 } from "../../utils/fallback.js";
|
||||
|
||||
function fetch_key(data) {
|
||||
let key = null;
|
||||
|
||||
const xyMatch = data.match(/window\._xy_ws\s*=\s*["']([^"']+)["']/);
|
||||
if (xyMatch) {
|
||||
key = xyMatch[1];
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
const lkMatch = data.match(/window\._lk_db\s*=\s*\{([^}]+)\}/);
|
||||
|
||||
if (lkMatch) {
|
||||
key = [...lkMatch[1].matchAll(/:\s*["']([^"']+)["']/g)]
|
||||
.map((v) => v[1])
|
||||
.join("");
|
||||
}
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
const nonceMatch = data.match(/nonce\s*=\s*["']([^"']+)["']/);
|
||||
if (nonceMatch) {
|
||||
key = nonceMatch[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
const dpiMatch = data.match(/data-dpi\s*=\s*["']([^"']+)["']/);
|
||||
if (dpiMatch) {
|
||||
key = dpiMatch[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
const metaMatch = data.match(
|
||||
/<meta[^>]*name\s*=\s*["']_gg_fb["'][^>]*content\s*=\s*["']([^"']+)["']/i,
|
||||
);
|
||||
if (metaMatch) {
|
||||
key = metaMatch[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
const isThMatch = data.match(/_is_th\s*:\s*([A-Za-z0-9]+)/);
|
||||
if (isThMatch) {
|
||||
key = isThMatch[1];
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
export async function decryptSources_v1(epID, id, name, type, fallback) {
|
||||
try {
|
||||
let decryptedSources = null;
|
||||
let iframeURL = null;
|
||||
|
||||
if (fallback) {
|
||||
const fallback_server = ["hd-1", "hd-3"].includes(name.toLowerCase())
|
||||
? fallback_1
|
||||
: fallback_2;
|
||||
|
||||
iframeURL = `https://${fallback_server}/stream/s-2/${epID}/${type}`;
|
||||
|
||||
const { data } = await axios.get(
|
||||
`https://${fallback_server}/stream/s-2/${epID}/${type}`,
|
||||
{
|
||||
headers: {
|
||||
Referer: `https://${fallback_server}/`,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const $ = cheerio.load(data);
|
||||
const dataId = $("#megaplay-player").attr("data-id");
|
||||
const { data: decryptedData } = await axios.get(
|
||||
`https://${fallback_server}/stream/getSources?id=${dataId}`,
|
||||
{
|
||||
headers: {
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
},
|
||||
},
|
||||
);
|
||||
decryptedSources = decryptedData;
|
||||
} else {
|
||||
const { data: sourcesData } = await axios.get(
|
||||
`https://${v1_base_url}/ajax/v2/episode/sources?id=${id}`,
|
||||
);
|
||||
|
||||
const ajaxLink = sourcesData?.link;
|
||||
if (!ajaxLink) throw new Error("Missing link in sourcesData");
|
||||
console.log(ajaxLink);
|
||||
const sourceIdMatch = /\/([^/?]+)\?/.exec(ajaxLink);
|
||||
const sourceId = sourceIdMatch?.[1];
|
||||
if (!sourceId) throw new Error("Unable to extract sourceId from link");
|
||||
const new_url = `https://megacloud.blog/embed-2/v3/e-1/${sourceId}?k=1`;
|
||||
const { data: stream_data } = await axios.post(
|
||||
"https://megacloud.zenime.site/get-sources",
|
||||
{
|
||||
embedUrl: new_url,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
decryptedSources = stream_data;
|
||||
// const baseUrlMatch = ajaxLink.match(
|
||||
// /^(https?:\/\/[^\/]+(?:\/[^\/]+){3})/,
|
||||
// );
|
||||
// if (!baseUrlMatch) throw new Error("Could not extract base URL");
|
||||
// const baseUrl = baseUrlMatch[1];
|
||||
|
||||
// iframeURL = `${baseUrl}/${sourceId}?k=1&autoPlay=0&oa=0&asi=1`;
|
||||
|
||||
// const { data: rawSourceData } = await axios.get(
|
||||
// `${baseUrl}/getSources?id=${sourceId}`,
|
||||
// );
|
||||
// decryptedSources = rawSourceData;
|
||||
}
|
||||
|
||||
return {
|
||||
id,
|
||||
type,
|
||||
link: {
|
||||
file: fallback
|
||||
? (decryptedSources?.sources?.file ?? "")
|
||||
: (decryptedSources?.sources?.[0].file ?? ""),
|
||||
type: "hls",
|
||||
},
|
||||
tracks: decryptedSources.tracks ?? [],
|
||||
intro: decryptedSources.intro ?? null,
|
||||
outro: decryptedSources.outro ?? null,
|
||||
iframe: iframeURL,
|
||||
server: name,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Error during decryptSources_v1(${id}, epID=${epID}, server=${name}):`,
|
||||
error.message,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
68
src/parsers/decryptors/decrypt_v2.decryptor.js
Normal file
68
src/parsers/decryptors/decrypt_v2.decryptor.js
Normal file
@@ -0,0 +1,68 @@
|
||||
// this is kept as backup in case megacloud's architecture rollback to it's previous architecture
|
||||
|
||||
|
||||
// import axios from "axios";
|
||||
// import CryptoJS from "crypto-js";
|
||||
// import { v2_base_url } from "../../utils/base_v2.js";
|
||||
// import fetchScript from "../../helper/fetchScript.helper.js";
|
||||
// import getKeys from "../../helper/getKey.helper.js";
|
||||
// import { PLAYER_SCRIPT_URL } from "../../configs/player_v2.config.js";
|
||||
|
||||
// async function decryptSources_v2(id, name, type) {
|
||||
// try {
|
||||
// const [{ data: sourcesData }, decryptKey_v2] = await Promise.all([
|
||||
// axios.get(`https://${v2_base_url}/ajax/episode/sources?id=${id}`),
|
||||
// getKeys(await fetchScript(PLAYER_SCRIPT_URL)),
|
||||
// ]);
|
||||
// const ajaxResp = sourcesData.link;
|
||||
// const [hostname] = /^(https?:\/\/(?:www\.)?[^\/\?]+)/.exec(ajaxResp) || [];
|
||||
// const [_, sourceId] = /\/([^\/\?]+)\?/.exec(ajaxResp) || [];
|
||||
// const { data: source } = await axios.get(
|
||||
// `${hostname}/ajax/embed-6-v2/getSources?id=${sourceId}`
|
||||
// );
|
||||
|
||||
// if (source.encrypted === true) {
|
||||
// const sourcesArray = source.sources.split("");
|
||||
// let extractedKey = "";
|
||||
// let currentIndex = 0;
|
||||
|
||||
// for (const index of decryptKey_v2) {
|
||||
// const start = index[0] + currentIndex;
|
||||
// const end = start + index[1];
|
||||
|
||||
// for (let i = start; i < end; i++) {
|
||||
// extractedKey += sourcesArray[i];
|
||||
// sourcesArray[i] = "";
|
||||
// }
|
||||
// currentIndex += index[1];
|
||||
// }
|
||||
|
||||
// const decrypted = CryptoJS.AES.decrypt(
|
||||
// sourcesArray.join(""),
|
||||
// extractedKey
|
||||
// ).toString(CryptoJS.enc.Utf8);
|
||||
// const decryptedSources = JSON.parse(decrypted);
|
||||
// source.sources = null;
|
||||
// source.sources = {
|
||||
// file: decryptedSources[0].file,
|
||||
// type: "hls",
|
||||
// };
|
||||
// }
|
||||
// if (source.hasOwnProperty("server")) {
|
||||
// delete source.server;
|
||||
// }
|
||||
// return {
|
||||
// id: id,
|
||||
// type: type,
|
||||
// link: source.sources,
|
||||
// tracks: source.tracks,
|
||||
// intro: source.intro,
|
||||
// outro: source.outro,
|
||||
// server: name,
|
||||
// };
|
||||
// } catch (error) {
|
||||
// console.error("Error during decryption:", error);
|
||||
// }
|
||||
// }
|
||||
|
||||
// export { decryptSources_v2 };
|
||||
811
src/parsers/decryptors/megacloud.decryptor.js
Normal file
811
src/parsers/decryptors/megacloud.decryptor.js
Normal file
@@ -0,0 +1,811 @@
|
||||
//inspired from https://github.com/drblgn/rabbit_wasm
|
||||
|
||||
import util from "util";
|
||||
import pixels from "image-pixels";
|
||||
import cryptoJs from "crypto-js";
|
||||
import axios from "axios";
|
||||
const user_agent =
|
||||
"Mozilla/5.0 (X11; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0";
|
||||
import { webcrypto } from "crypto";
|
||||
const crypto = webcrypto;
|
||||
import { dataURL } from "../../configs/dataUrl.js";
|
||||
// import { v1_base_url } from "../../utils/base_v1.js";
|
||||
import { v4_base_url } from "../../utils/base_v4.js";
|
||||
|
||||
let wasm;
|
||||
let arr = new Array(128).fill(void 0);
|
||||
const dateNow = Date.now();
|
||||
let content;
|
||||
let referrer = "";
|
||||
|
||||
function isDetached(buffer) {
|
||||
if (buffer.byteLength === 0) {
|
||||
const formatted = util.format(buffer);
|
||||
return formatted.includes("detached");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const meta = {
|
||||
content: content,
|
||||
};
|
||||
|
||||
const image_data = {
|
||||
height: 50,
|
||||
width: 65,
|
||||
data: new Uint8ClampedArray(),
|
||||
};
|
||||
|
||||
const canvas = {
|
||||
baseUrl: "",
|
||||
width: 0,
|
||||
height: 0,
|
||||
style: {
|
||||
style: {
|
||||
display: "inline",
|
||||
},
|
||||
},
|
||||
context2d: {},
|
||||
};
|
||||
|
||||
const fake_window = {
|
||||
localStorage: {
|
||||
setItem: function (item, value) {
|
||||
fake_window.localStorage[item] = value;
|
||||
},
|
||||
},
|
||||
navigator: {
|
||||
webdriver: false,
|
||||
userAgent: user_agent,
|
||||
},
|
||||
length: 0,
|
||||
document: {
|
||||
cookie: "",
|
||||
},
|
||||
origin: "",
|
||||
location: {
|
||||
href: "",
|
||||
origin: "",
|
||||
},
|
||||
performance: {
|
||||
timeOrigin: dateNow,
|
||||
},
|
||||
xrax: "",
|
||||
c: false,
|
||||
G: "",
|
||||
z: function (a) {
|
||||
return [
|
||||
(4278190080 & a) >> 24,
|
||||
(16711680 & a) >> 16,
|
||||
(65280 & a) >> 8,
|
||||
255 & a,
|
||||
];
|
||||
},
|
||||
crypto: crypto,
|
||||
msCrypto: crypto,
|
||||
browser_version: 1676800512,
|
||||
};
|
||||
|
||||
const nodeList = {
|
||||
image: {
|
||||
src: "",
|
||||
height: 50,
|
||||
width: 65,
|
||||
complete: true,
|
||||
},
|
||||
context2d: {},
|
||||
length: 1,
|
||||
};
|
||||
|
||||
function get(index) {
|
||||
return arr[index];
|
||||
}
|
||||
|
||||
arr.push(void 0, null, true, false);
|
||||
|
||||
let size = 0;
|
||||
let memoryBuff;
|
||||
|
||||
function getMemBuff() {
|
||||
return (memoryBuff =
|
||||
null !== memoryBuff && 0 !== memoryBuff.byteLength
|
||||
? memoryBuff
|
||||
: new Uint8Array(wasm.memory.buffer));
|
||||
}
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
const encode = function (text, array) {
|
||||
return encoder.encodeInto(text, array);
|
||||
};
|
||||
|
||||
function parse(text, func, func2) {
|
||||
if (void 0 === func2) {
|
||||
var encoded = encoder.encode(text);
|
||||
const parsedIndex = func(encoded.length, 1) >>> 0;
|
||||
return (
|
||||
getMemBuff()
|
||||
.subarray(parsedIndex, parsedIndex + encoded.length)
|
||||
.set(encoded),
|
||||
(size = encoded.length),
|
||||
parsedIndex
|
||||
);
|
||||
}
|
||||
let len = text.length;
|
||||
let parsedLen = func(len, 1) >>> 0;
|
||||
var new_arr = getMemBuff();
|
||||
let i = 0;
|
||||
for (; i < len; i++) {
|
||||
var char = text.charCodeAt(i);
|
||||
if (127 < char) {
|
||||
break;
|
||||
}
|
||||
new_arr[parsedLen + i] = char;
|
||||
}
|
||||
return (
|
||||
i !== len &&
|
||||
(0 !== i && (text = text.slice(i)),
|
||||
(parsedLen = func2(parsedLen, len, (len = i + 3 * text.length), 1) >>> 0),
|
||||
(encoded = getMemBuff().subarray(parsedLen + i, parsedLen + len)),
|
||||
(i += encode(text, encoded).written),
|
||||
(parsedLen = func2(parsedLen, len, i, 1) >>> 0)),
|
||||
(size = i),
|
||||
parsedLen
|
||||
);
|
||||
}
|
||||
|
||||
let dataView;
|
||||
|
||||
function isNull(test) {
|
||||
return null == test;
|
||||
}
|
||||
|
||||
function getDataView() {
|
||||
return (dataView =
|
||||
dataView === null ||
|
||||
isDetached(dataView.buffer) ||
|
||||
dataView.buffer !== wasm.memory.buffer
|
||||
? new DataView(wasm.memory.buffer)
|
||||
: dataView);
|
||||
}
|
||||
|
||||
let pointer = arr.length;
|
||||
|
||||
function shift(QP) {
|
||||
QP < 132 || ((arr[QP] = pointer), (pointer = QP));
|
||||
}
|
||||
|
||||
function shiftGet(QP) {
|
||||
var Qn = get(QP);
|
||||
return shift(QP), Qn;
|
||||
}
|
||||
|
||||
const decoder = new TextDecoder("utf-8", {
|
||||
fatal: true,
|
||||
ignoreBOM: true,
|
||||
});
|
||||
|
||||
function decodeSub(index, offset) {
|
||||
return (
|
||||
(index >>>= 0), decoder.decode(getMemBuff().subarray(index, index + offset))
|
||||
);
|
||||
}
|
||||
|
||||
function addToStack(item) {
|
||||
pointer === arr.length && arr.push(arr.length + 1);
|
||||
var Qn = pointer;
|
||||
return (pointer = arr[Qn]), (arr[Qn] = item), Qn;
|
||||
}
|
||||
|
||||
function args(QP, Qn, QT, func) {
|
||||
const Qx = {
|
||||
a: QP,
|
||||
b: Qn,
|
||||
cnt: 1,
|
||||
dtor: QT,
|
||||
};
|
||||
return (
|
||||
(QP = (...Qw) => {
|
||||
Qx.cnt++;
|
||||
try {
|
||||
return func(Qx.a, Qx.b, ...Qw);
|
||||
} finally {
|
||||
0 == --Qx.cnt &&
|
||||
(wasm.__wbindgen_export_2.get(Qx.dtor)(Qx.a, Qx.b), (Qx.a = 0));
|
||||
}
|
||||
}),
|
||||
((QP.original = Qx), QP)
|
||||
);
|
||||
}
|
||||
|
||||
function export3(QP, Qn) {
|
||||
return shiftGet(wasm.__wbindgen_export_3(QP, Qn));
|
||||
}
|
||||
|
||||
function export4(Qy, QO, QX) {
|
||||
wasm.__wbindgen_export_4(Qy, QO, addToStack(QX));
|
||||
}
|
||||
|
||||
function export5(QP, Qn) {
|
||||
wasm.__wbindgen_export_5(QP, Qn);
|
||||
}
|
||||
|
||||
function applyToWindow(func, args) {
|
||||
try {
|
||||
return func.apply(fake_window, args);
|
||||
} catch (error) {
|
||||
wasm.__wbindgen_export_6(addToStack(error));
|
||||
}
|
||||
}
|
||||
|
||||
function Qj(QP, Qn) {
|
||||
return (
|
||||
(Qn = Qn(+QP.length, 1) >>> 0),
|
||||
(getMemBuff().set(QP, Qn), (size = QP.length), Qn)
|
||||
);
|
||||
}
|
||||
|
||||
async function QN(QP, Qn) {
|
||||
let QT, Qt;
|
||||
return "function" == typeof Response && QP instanceof Response
|
||||
? ((QT = await QP.arrayBuffer()),
|
||||
(Qt = await WebAssembly.instantiate(QT, Qn)),
|
||||
Object.assign(Qt, { bytes: QT }))
|
||||
: (Qt = await WebAssembly.instantiate(QP, Qn)) instanceof
|
||||
WebAssembly.Instance
|
||||
? {
|
||||
instance: Qt,
|
||||
module: QP,
|
||||
}
|
||||
: Qt;
|
||||
}
|
||||
|
||||
function initWasm() {
|
||||
const wasmObj = {
|
||||
wbg: {
|
||||
__wbindgen_is_function: function (index) {
|
||||
return typeof get(index) == "function";
|
||||
},
|
||||
__wbindgen_is_string: function (index) {
|
||||
return typeof get(index) == "string";
|
||||
},
|
||||
__wbindgen_is_object: function (index) {
|
||||
let object = get(index);
|
||||
return typeof object == "object" && object !== null;
|
||||
},
|
||||
__wbindgen_number_get: function (offset, index) {
|
||||
let number = get(index);
|
||||
getDataView().setFloat64(offset + 8, isNull(number) ? 0 : number, true);
|
||||
getDataView().setInt32(offset, isNull(number) ? 0 : 1, true);
|
||||
},
|
||||
__wbindgen_string_get: function (offset, index) {
|
||||
let str = get(index);
|
||||
let val = parse(
|
||||
str,
|
||||
wasm.__wbindgen_export_0,
|
||||
wasm.__wbindgen_export_1
|
||||
);
|
||||
getDataView().setInt32(offset + 4, size, true);
|
||||
getDataView().setInt32(offset, val, true);
|
||||
},
|
||||
__wbindgen_object_drop_ref: function (index) {
|
||||
shiftGet(index);
|
||||
},
|
||||
__wbindgen_cb_drop: function (index) {
|
||||
let org = shiftGet(index).original;
|
||||
return 1 == org.cnt-- && !(org.a = 0);
|
||||
},
|
||||
__wbindgen_string_new: function (index, offset) {
|
||||
return addToStack(decodeSub(index, offset));
|
||||
},
|
||||
__wbindgen_is_null: function (index) {
|
||||
return null === get(index);
|
||||
},
|
||||
__wbindgen_is_undefined: function (index) {
|
||||
return void 0 === get(index);
|
||||
},
|
||||
__wbindgen_boolean_get: function (index) {
|
||||
let bool = get(index);
|
||||
return "boolean" == typeof bool ? (bool ? 1 : 0) : 2;
|
||||
},
|
||||
__wbg_instanceof_CanvasRenderingContext2d_4ec30ddd3f29f8f9: function () {
|
||||
return true;
|
||||
},
|
||||
__wbg_subarray_adc418253d76e2f1: function (index, num1, num2) {
|
||||
return addToStack(get(index).subarray(num1 >>> 0, num2 >>> 0));
|
||||
},
|
||||
__wbg_randomFillSync_5c9c955aa56b6049: function () {},
|
||||
__wbg_getRandomValues_3aa56aa6edec874c: function () {
|
||||
return applyToWindow(function (index1, index2) {
|
||||
get(index1).getRandomValues(get(index2));
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_msCrypto_eb05e62b530a1508: function (index) {
|
||||
return addToStack(get(index).msCrypto);
|
||||
},
|
||||
__wbg_toString_6eb7c1f755c00453: function (index) {
|
||||
let fakestr = "[object Storage]";
|
||||
return addToStack(fakestr);
|
||||
},
|
||||
__wbg_toString_139023ab33acec36: function (index) {
|
||||
return addToStack(get(index).toString());
|
||||
},
|
||||
__wbg_require_cca90b1a94a0255b: function () {
|
||||
return applyToWindow(function () {
|
||||
return addToStack(module.require);
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_crypto_1d1f22824a6a080c: function (index) {
|
||||
return addToStack(get(index).crypto);
|
||||
},
|
||||
__wbg_process_4a72847cc503995b: function (index) {
|
||||
return addToStack(get(index).process);
|
||||
},
|
||||
__wbg_versions_f686565e586dd935: function (index) {
|
||||
return addToStack(get(index).versions);
|
||||
},
|
||||
__wbg_node_104a2ff8d6ea03a2: function (index) {
|
||||
return addToStack(get(index).node);
|
||||
},
|
||||
__wbg_localStorage_3d538af21ea07fcc: function () {
|
||||
return applyToWindow(function (index) {
|
||||
let data = fake_window.localStorage;
|
||||
if (isNull(data)) {
|
||||
return 0;
|
||||
} else {
|
||||
return addToStack(data);
|
||||
}
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_setfillStyle_59f426135f52910f: function () {},
|
||||
__wbg_setshadowBlur_229c56539d02f401: function () {},
|
||||
__wbg_setshadowColor_340d5290cdc4ae9d: function () {},
|
||||
__wbg_setfont_16d6e31e06a420a5: function () {},
|
||||
__wbg_settextBaseline_c3266d3bd4a6695c: function () {},
|
||||
__wbg_drawImage_cb13768a1bdc04bd: function () {},
|
||||
__wbg_getImageData_66269d289f37d3c7: function () {
|
||||
return applyToWindow(function () {
|
||||
return addToStack(image_data);
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_rect_2fa1df87ef638738: function () {},
|
||||
__wbg_fillRect_4dd28e628381d240: function () {},
|
||||
__wbg_fillText_07e5da9e41652f20: function () {},
|
||||
__wbg_setProperty_5144ddce66bbde41: function () {},
|
||||
__wbg_createElement_03cf347ddad1c8c0: function () {
|
||||
return applyToWindow(function (index, decodeIndex, decodeIndexOffset) {
|
||||
return addToStack(canvas);
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_querySelector_118a0639aa1f51cd: function () {
|
||||
return applyToWindow(function (index, decodeIndex, decodeOffset) {
|
||||
return addToStack(meta);
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_querySelectorAll_50c79cd4f7573825: function () {
|
||||
return applyToWindow(function () {
|
||||
return addToStack(nodeList);
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_getAttribute_706ae88bd37410fa: function (
|
||||
offset,
|
||||
index,
|
||||
decodeIndex,
|
||||
decodeOffset
|
||||
) {
|
||||
let attr = meta.content;
|
||||
let todo = isNull(attr)
|
||||
? 0
|
||||
: parse(attr, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||
getDataView().setInt32(offset + 4, size, true);
|
||||
getDataView().setInt32(offset, todo, true);
|
||||
},
|
||||
__wbg_target_6795373f170fd786: function (index) {
|
||||
let target = get(index).target;
|
||||
return isNull(target) ? 0 : addToStack(target);
|
||||
},
|
||||
__wbg_addEventListener_f984e99465a6a7f4: function () {},
|
||||
__wbg_instanceof_HtmlCanvasElement_1e81f71f630e46bc: function () {
|
||||
return true;
|
||||
},
|
||||
__wbg_setwidth_233645b297bb3318: function (index, set) {
|
||||
get(index).width = set >>> 0;
|
||||
},
|
||||
__wbg_setheight_fcb491cf54e3527c: function (index, set) {
|
||||
get(index).height = set >>> 0;
|
||||
},
|
||||
__wbg_getContext_dfc91ab0837db1d1: function () {
|
||||
return applyToWindow(function (index) {
|
||||
return addToStack(get(index).context2d);
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_toDataURL_97b108dd1a4b7454: function () {
|
||||
return applyToWindow(function (offset, index) {
|
||||
let _dataUrl = parse(
|
||||
dataURL,
|
||||
wasm.__wbindgen_export_0,
|
||||
wasm.__wbindgen_export_1
|
||||
);
|
||||
getDataView().setInt32(offset + 4, size, true);
|
||||
getDataView().setInt32(offset, _dataUrl, true);
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_instanceof_HtmlDocument_1100f8a983ca79f9: function () {
|
||||
return true;
|
||||
},
|
||||
__wbg_style_ca229e3326b3c3fb: function (index) {
|
||||
addToStack(get(index).style);
|
||||
},
|
||||
__wbg_instanceof_HtmlImageElement_9c82d4e3651a8533: function () {
|
||||
return true;
|
||||
},
|
||||
__wbg_src_87a0e38af6229364: function (offset, index) {
|
||||
let _src = parse(
|
||||
get(index).src,
|
||||
wasm.__wbindgen_export_0,
|
||||
wasm.__wbindgen_export_1
|
||||
);
|
||||
getDataView().setInt32(offset + 4, size, true);
|
||||
getDataView().setInt32(offset, _src, true);
|
||||
},
|
||||
__wbg_width_e1a38bdd483e1283: function (index) {
|
||||
return get(index).width;
|
||||
},
|
||||
__wbg_height_e4cc2294187313c9: function (index) {
|
||||
return get(index).height;
|
||||
},
|
||||
__wbg_complete_1162c2697406af11: function (index) {
|
||||
return get(index).complete;
|
||||
},
|
||||
__wbg_data_d34dc554f90b8652: function (offset, index) {
|
||||
var _data = Qj(get(index).data, wasm.__wbindgen_export_0);
|
||||
getDataView().setInt32(offset + 4, size, true);
|
||||
getDataView().setInt32(offset, _data, true);
|
||||
},
|
||||
__wbg_origin_305402044aa148ce: function () {
|
||||
return applyToWindow(function (offset, index) {
|
||||
let _origin = parse(
|
||||
get(index).origin,
|
||||
wasm.__wbindgen_export_0,
|
||||
wasm.__wbindgen_export_1
|
||||
);
|
||||
getDataView().setInt32(offset + 4, size, true);
|
||||
getDataView().setInt32(offset, _origin, true);
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_length_8a9352f7b7360c37: function (index) {
|
||||
return get(index).length;
|
||||
},
|
||||
__wbg_get_c30ae0782d86747f: function (index) {
|
||||
let _image = get(index).image;
|
||||
return isNull(_image) ? 0 : addToStack(_image);
|
||||
},
|
||||
__wbg_timeOrigin_f462952854d802ec: function (index) {
|
||||
return get(index).timeOrigin;
|
||||
},
|
||||
__wbg_instanceof_Window_cee7a886d55e7df5: function () {
|
||||
return true;
|
||||
},
|
||||
__wbg_document_eb7fd66bde3ee213: function (index) {
|
||||
let _document = get(index).document;
|
||||
return isNull(_document) ? 0 : addToStack(_document);
|
||||
},
|
||||
__wbg_location_b17760ac7977a47a: function (index) {
|
||||
return addToStack(get(index).location);
|
||||
},
|
||||
__wbg_performance_4ca1873776fdb3d2: function (index) {
|
||||
let _performance = get(index).performance;
|
||||
return isNull(_performance) ? 0 : addToStack(_performance);
|
||||
},
|
||||
__wbg_origin_e1f8acdeb3a39a2b: function (offset, index) {
|
||||
let _origin = parse(
|
||||
get(index).origin,
|
||||
wasm.__wbindgen_export_0,
|
||||
wasm.__wbindgen_export_1
|
||||
);
|
||||
getDataView().setInt32(offset + 4, size, true);
|
||||
getDataView().setInt32(offset, _origin, true);
|
||||
},
|
||||
__wbg_get_8986951b1ee310e0: function (index, decode1, decode2) {
|
||||
let data = get(index)[decodeSub(decode1, decode2)];
|
||||
return isNull(data) ? 0 : addToStack(data);
|
||||
},
|
||||
__wbg_setTimeout_6ed7182ebad5d297: function () {
|
||||
return applyToWindow(function () {
|
||||
return 7;
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_self_05040bd9523805b9: function () {
|
||||
return applyToWindow(function () {
|
||||
return addToStack(fake_window);
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_window_adc720039f2cb14f: function () {
|
||||
return applyToWindow(function () {
|
||||
return addToStack(fake_window);
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_globalThis_622105db80c1457d: function () {
|
||||
return applyToWindow(function () {
|
||||
return addToStack(fake_window);
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_global_f56b013ed9bcf359: function () {
|
||||
return applyToWindow(function () {
|
||||
return addToStack(fake_window);
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_newnoargs_cfecb3965268594c: function (index, offset) {
|
||||
return addToStack(new Function(decodeSub(index, offset)));
|
||||
},
|
||||
__wbindgen_object_clone_ref: function (index) {
|
||||
return addToStack(get(index));
|
||||
},
|
||||
__wbg_eval_c824e170787ad184: function () {
|
||||
return applyToWindow(function (index, offset) {
|
||||
let fake_str = "fake_" + decodeSub(index, offset);
|
||||
let ev = eval(fake_str);
|
||||
return addToStack(ev);
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_call_3f093dd26d5569f8: function () {
|
||||
return applyToWindow(function (index, index2) {
|
||||
return addToStack(get(index).call(get(index2)));
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_call_67f2111acd2dfdb6: function () {
|
||||
return applyToWindow(function (index, index2, index3) {
|
||||
return addToStack(get(index).call(get(index2), get(index3)));
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_set_961700853a212a39: function () {
|
||||
return applyToWindow(function (index, index2, index3) {
|
||||
return Reflect.set(get(index), get(index2), get(index3));
|
||||
}, arguments);
|
||||
},
|
||||
__wbg_buffer_b914fb8b50ebbc3e: function (index) {
|
||||
return addToStack(get(index).buffer);
|
||||
},
|
||||
__wbg_newwithbyteoffsetandlength_0de9ee56e9f6ee6e: function (
|
||||
index,
|
||||
val,
|
||||
val2
|
||||
) {
|
||||
return addToStack(new Uint8Array(get(index), val >>> 0, val2 >>> 0));
|
||||
},
|
||||
__wbg_newwithlength_0d03cef43b68a530: function (length) {
|
||||
return addToStack(new Uint8Array(length >>> 0));
|
||||
},
|
||||
__wbg_new_b1f2d6842d615181: function (index) {
|
||||
return addToStack(new Uint8Array(get(index)));
|
||||
},
|
||||
__wbg_buffer_67e624f5a0ab2319: function (index) {
|
||||
return addToStack(get(index).buffer);
|
||||
},
|
||||
__wbg_length_21c4b0ae73cba59d: function (index) {
|
||||
return get(index).length;
|
||||
},
|
||||
__wbg_set_7d988c98e6ced92d: function (index, index2, val) {
|
||||
get(index).set(get(index2), val >>> 0);
|
||||
},
|
||||
__wbindgen_debug_string: function () {},
|
||||
__wbindgen_throw: function (index, offset) {
|
||||
throw new Error(decodeSub(index, offset));
|
||||
},
|
||||
__wbindgen_memory: function () {
|
||||
return addToStack(wasm.memory);
|
||||
},
|
||||
__wbindgen_closure_wrapper117: function (Qn, QT) {
|
||||
return addToStack(args(Qn, QT, 2, export3));
|
||||
},
|
||||
__wbindgen_closure_wrapper119: function (Qn, QT) {
|
||||
return addToStack(args(Qn, QT, 2, export4));
|
||||
},
|
||||
__wbindgen_closure_wrapper121: function (Qn, QT) {
|
||||
return addToStack(args(Qn, QT, 2, export5));
|
||||
},
|
||||
__wbindgen_closure_wrapper123: function (Qn, QT) {
|
||||
let test = addToStack(args(Qn, QT, 9, export4));
|
||||
return test;
|
||||
},
|
||||
},
|
||||
};
|
||||
return wasmObj;
|
||||
}
|
||||
|
||||
function assignWasm(resp) {
|
||||
wasm = resp.exports;
|
||||
(dataView = null), (memoryBuff = null), wasm;
|
||||
}
|
||||
|
||||
function QZ(QP) {
|
||||
let Qn;
|
||||
return (
|
||||
(Qn = initWasm()),
|
||||
QP instanceof WebAssembly.Module || (QP = new WebAssembly.Module(QP)),
|
||||
assignWasm(new WebAssembly.Instance(QP, Qn))
|
||||
);
|
||||
}
|
||||
|
||||
async function loadWasm(url) {
|
||||
let mod, buffer;
|
||||
return (
|
||||
(mod = initWasm()),
|
||||
({
|
||||
instance: url,
|
||||
module: mod,
|
||||
bytes: buffer,
|
||||
} = ((url = fetch(url)), void 0, await QN(await url, mod))),
|
||||
assignWasm(url),
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
const grootLoader = {
|
||||
groot: function () {
|
||||
wasm.groot();
|
||||
},
|
||||
};
|
||||
|
||||
let wasmLoader = Object.assign(loadWasm, { initSync: QZ }, grootLoader);
|
||||
|
||||
const V = async (url) => {
|
||||
let Q0 = await wasmLoader(url);
|
||||
fake_window.bytes = Q0;
|
||||
try {
|
||||
wasmLoader.groot();
|
||||
} catch (error) {
|
||||
console.error("error: ", error);
|
||||
}
|
||||
fake_window.jwt_plugin(Q0);
|
||||
return fake_window.navigate();
|
||||
};
|
||||
|
||||
const getMeta = async (url) => {
|
||||
let resp = await fetch(url, {
|
||||
headers: {
|
||||
UserAgent: user_agent,
|
||||
Referrer: referrer,
|
||||
},
|
||||
});
|
||||
let txt = await resp.text();
|
||||
let regx = /name="j_crt" content="[A-Za-z0-9]*/g;
|
||||
let match = txt.match(regx)[0];
|
||||
let content = match.slice(match.lastIndexOf('"') + 1);
|
||||
meta.content = content + "==";
|
||||
};
|
||||
|
||||
const i = (a, P) => {
|
||||
try {
|
||||
for (let Q0 = 0; Q0 < a.length; Q0++) {
|
||||
a[Q0] = a[Q0] ^ P[Q0 % P.length];
|
||||
}
|
||||
} catch (Q1) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const M = (a, P) => {
|
||||
try {
|
||||
var Q0 = cryptoJs.AES.decrypt(a, P);
|
||||
return JSON.parse(Q0.toString(cryptoJs.enc.Utf8));
|
||||
} catch (Q1) {
|
||||
var Q0 = cryptoJs.AES.decrypt(a, P);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
function z(a) {
|
||||
return [
|
||||
(a & 4278190080) >> 24,
|
||||
(a & 16711680) >> 16,
|
||||
(a & 65280) >> 8,
|
||||
a & 255,
|
||||
];
|
||||
}
|
||||
|
||||
const decryptSource = async (embed_url) => {
|
||||
referrer = embed_url.includes("mega")
|
||||
? `https://${v4_base_url}`
|
||||
: new URL(embed_url).origin;
|
||||
// let regx = /([A-Z])\w+/;
|
||||
let xrax = embed_url.split("/").pop().split("?").shift();
|
||||
// regx = /https:\/\/[a-zA-Z0-9.]*/;
|
||||
// let base_url = embed_url.match(regx)[0];
|
||||
const base_url = new URL(embed_url).origin;
|
||||
nodeList.image.src = base_url + "/images/image.png?v=0.0.9";
|
||||
let data = new Uint8ClampedArray((await pixels(nodeList.image.src)).data);
|
||||
image_data.data = data;
|
||||
let test = embed_url.split("/");
|
||||
let browser_version = 1676800512;
|
||||
canvas.baseUrl = base_url;
|
||||
fake_window.origin = base_url;
|
||||
fake_window.location.origin = base_url;
|
||||
fake_window.location.href = embed_url;
|
||||
fake_window.xrax = xrax;
|
||||
fake_window.G = xrax;
|
||||
|
||||
await getMeta(embed_url);
|
||||
|
||||
let Q5 = await V(base_url + "/images/loading.png?v=0.0.9");
|
||||
|
||||
let getSourcesUrl = "";
|
||||
|
||||
if (base_url.includes("mega")) {
|
||||
getSourcesUrl =
|
||||
base_url +
|
||||
"/" +
|
||||
test[3] +
|
||||
"/ajax/" +
|
||||
test[4] +
|
||||
"/getSources?id=" +
|
||||
fake_window.pid +
|
||||
"&v=" +
|
||||
fake_window.localStorage.kversion +
|
||||
"&h=" +
|
||||
fake_window.localStorage.kid +
|
||||
"&b=" +
|
||||
browser_version;
|
||||
} else {
|
||||
getSourcesUrl =
|
||||
base_url +
|
||||
"/ajax/" +
|
||||
test[3] +
|
||||
// "/" +
|
||||
// test[4] +
|
||||
"/getSources?id=" +
|
||||
fake_window.pid +
|
||||
"&v=" +
|
||||
fake_window.localStorage.kversion +
|
||||
"&h=" +
|
||||
fake_window.localStorage.kid +
|
||||
"&b=" +
|
||||
browser_version;
|
||||
}
|
||||
|
||||
let { data: resp } = await axios.get(getSourcesUrl, {
|
||||
headers: {
|
||||
"User-Agent": user_agent,
|
||||
Referrer: embed_url + "&autoPlay=1&oa=0&asi=1",
|
||||
"Accept-Language": "en,bn;q=0.9,en-US;q=0.8",
|
||||
"sec-ch-ua":
|
||||
'"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
||||
"sec-ch-ua-mobile": "?1",
|
||||
"sec-ch-ua-platform": '"Android"',
|
||||
"Sec-Fetch-Dest": "empty",
|
||||
"Sec-Fetch-Site": "same-origin",
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
"Sec-Fetch-Mode": "cors",
|
||||
},
|
||||
});
|
||||
|
||||
let Q3 = fake_window.localStorage.kversion;
|
||||
let Q1 = z(Q3);
|
||||
Q5 = new Uint8Array(Q5);
|
||||
let Q8 = resp.t != 0 ? (i(Q5, Q1), Q5) : ((Q8 = resp.k), i(Q8, Q1), Q8);
|
||||
let str = btoa(String.fromCharCode.apply(null, new Uint8Array(Q8)));
|
||||
var decryptedSource = M(resp.sources, str);
|
||||
resp.sources = decryptedSource;
|
||||
return resp;
|
||||
};
|
||||
|
||||
export default async function decryptMegacloud(id, name, type) {
|
||||
try {
|
||||
const { data: sourcesData } = await axios.get(
|
||||
// `https://${v1_base_url}/ajax/v2/episode/sources?id=${id}`
|
||||
`https://${v4_base_url}/ajax/episode/sources?id=${id}`
|
||||
);
|
||||
const source = await decryptSource(sourcesData.link);
|
||||
return {
|
||||
id: id,
|
||||
type: type,
|
||||
link: source.sources[0],
|
||||
tracks: source.tracks,
|
||||
intro: source.intro,
|
||||
outro: source.outro,
|
||||
server: name,
|
||||
iframe: sourcesData.link,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error during decryption:", error);
|
||||
}
|
||||
}
|
||||
29
src/parsers/idFetch_v1.parser.js
Normal file
29
src/parsers/idFetch_v1.parser.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v1_base_url } from "../utils/base_v1.js";
|
||||
|
||||
export async function fetchServerData_v1(id) {
|
||||
try {
|
||||
const { data } = await axios.get(
|
||||
`https://${v1_base_url}/ajax/v2/episode/servers?episodeId=${id}`
|
||||
);
|
||||
const $ = cheerio.load(data.html);
|
||||
|
||||
const serverData = $("div.ps_-block > div.ps__-list > div.server-item")
|
||||
.filter((_, ele) => {
|
||||
const name = $(ele).find("a.btn").text();
|
||||
return name === "HD-1" || name === "HD-2";
|
||||
})
|
||||
.map((_, ele) => ({
|
||||
name: $(ele).find("a.btn").text(),
|
||||
id: $(ele).attr("data-id"),
|
||||
type: $(ele).attr("data-type"),
|
||||
}))
|
||||
.get();
|
||||
|
||||
return serverData;
|
||||
} catch (error) {
|
||||
console.error("Error fetching server data:", error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
29
src/parsers/idFetch_v2.parser.js
Normal file
29
src/parsers/idFetch_v2.parser.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import axios from "axios";
|
||||
import * as cheerio from "cheerio";
|
||||
import { v2_base_url } from "../utils/base_v2.js";
|
||||
|
||||
export async function fetchServerData_v2(id) {
|
||||
try {
|
||||
const { data } = await axios.get(
|
||||
`https://${v2_base_url}/ajax/episode/servers?episodeId=${id}`
|
||||
);
|
||||
const $ = cheerio.load(data.html);
|
||||
|
||||
const serverData = $("div.ps_-block > div.ps__-list > div.server-item")
|
||||
.filter((_, ele) => {
|
||||
const name = $(ele).find("a.btn").text().trim();
|
||||
return name === "Vidcloud";
|
||||
})
|
||||
.map((_, ele) => ({
|
||||
name: $(ele).find("a.btn").text().trim(),
|
||||
id: $(ele).attr("data-id"),
|
||||
type: $(ele).attr("data-type"),
|
||||
}))
|
||||
.get();
|
||||
|
||||
return serverData;
|
||||
} catch (error) {
|
||||
console.error("Error fetching server data:", error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
89
src/routes/apiRoutes.js
Normal file
89
src/routes/apiRoutes.js
Normal file
@@ -0,0 +1,89 @@
|
||||
import * as homeInfoController from "../controllers/homeInfo.controller.js";
|
||||
import * as categoryController from "../controllers/category.controller.js";
|
||||
import * as topTenController from "../controllers/topten.controller.js";
|
||||
import * as animeInfoController from "../controllers/animeInfo.controller.js";
|
||||
import * as streamController from "../controllers/streamInfo.controller.js";
|
||||
import * as searchController from "../controllers/search.controller.js";
|
||||
import * as episodeListController from "../controllers/episodeList.controller.js";
|
||||
import * as suggestionsController from "../controllers/suggestion.controller.js";
|
||||
import * as scheduleController from "../controllers/schedule.controller.js";
|
||||
import * as serversController from "../controllers/servers.controller.js";
|
||||
import * as randomController from "../controllers/random.controller.js";
|
||||
import * as qtipController from "../controllers/qtip.controller.js";
|
||||
import * as randomIdController from "../controllers/randomId.controller.js";
|
||||
import * as producerController from "../controllers/producer.controller.js";
|
||||
import * as characterListController from "../controllers/voiceactor.controller.js";
|
||||
import * as nextEpisodeScheduleController from "../controllers/nextEpisodeSchedule.controller.js";
|
||||
import { routeTypes } from "./category.route.js";
|
||||
import { getWatchlist } from "../controllers/watchlist.controller.js";
|
||||
import getVoiceActors from "../controllers/actors.controller.js";
|
||||
import getCharacter from "../controllers/characters.controller.js";
|
||||
import * as filterController from "../controllers/filter.controller.js";
|
||||
import getTopSearch from "../controllers/topsearch.controller.js";
|
||||
|
||||
export const createApiRoutes = (app, jsonResponse, jsonError) => {
|
||||
const createRoute = (path, controllerMethod) => {
|
||||
app.get(path, async (req, res) => {
|
||||
try {
|
||||
const data = await controllerMethod(req, res);
|
||||
if (!res.headersSent) {
|
||||
return jsonResponse(res, data);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`Error in route ${path}:`, err);
|
||||
if (!res.headersSent) {
|
||||
return jsonError(res, err.message || "Internal server error");
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
["/api", "/api/"].forEach((route) => {
|
||||
app.get(route, async (req, res) => {
|
||||
try {
|
||||
const data = await homeInfoController.getHomeInfo(req, res);
|
||||
if (!res.headersSent) {
|
||||
return jsonResponse(res, data);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error in home route:", err);
|
||||
if (!res.headersSent) {
|
||||
return jsonError(res, err.message || "Internal server error");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
routeTypes.forEach((routeType) =>
|
||||
createRoute(`/api/${routeType}`, (req, res) =>
|
||||
categoryController.getCategory(req, res, routeType)
|
||||
)
|
||||
);
|
||||
|
||||
createRoute("/api/top-ten", topTenController.getTopTen);
|
||||
createRoute("/api/info", animeInfoController.getAnimeInfo);
|
||||
createRoute("/api/episodes/:id", episodeListController.getEpisodes);
|
||||
createRoute("/api/servers/:id", serversController.getServers);
|
||||
createRoute("/api/stream", (req, res) => streamController.getStreamInfo(req, res, false));
|
||||
createRoute("/api/stream/fallback", (req, res) => streamController.getStreamInfo(req, res, true));
|
||||
createRoute("/api/search", searchController.search);
|
||||
createRoute("/api/filter", filterController.filter);
|
||||
createRoute("/api/search/suggest", suggestionsController.getSuggestions);
|
||||
createRoute("/api/schedule", scheduleController.getSchedule);
|
||||
createRoute(
|
||||
"/api/schedule/:id",
|
||||
nextEpisodeScheduleController.getNextEpisodeSchedule
|
||||
);
|
||||
createRoute("/api/random", randomController.getRandom);
|
||||
createRoute("/api/random/id", randomIdController.getRandomId);
|
||||
createRoute("/api/qtip/:id", qtipController.getQtip);
|
||||
createRoute("/api/producer/:id", producerController.getProducer);
|
||||
createRoute(
|
||||
"/api/character/list/:id",
|
||||
characterListController.getVoiceActors
|
||||
);
|
||||
createRoute("/api/watchlist/:userId{/:page}", getWatchlist);
|
||||
createRoute("/api/actors/:id", getVoiceActors);
|
||||
createRoute("/api/character/:id", getCharacter);
|
||||
createRoute("/api/top-search", getTopSearch);
|
||||
};
|
||||
87
src/routes/category.route.js
Normal file
87
src/routes/category.route.js
Normal file
@@ -0,0 +1,87 @@
|
||||
export const routeTypes = [
|
||||
"genre/action",
|
||||
"genre/adventure",
|
||||
"genre/cars",
|
||||
"genre/comedy",
|
||||
"genre/dementia",
|
||||
"genre/demons",
|
||||
"genre/drama",
|
||||
"genre/ecchi",
|
||||
"genre/fantasy",
|
||||
"genre/game",
|
||||
"genre/harem",
|
||||
"genre/historical",
|
||||
"genre/horror",
|
||||
"genre/isekai",
|
||||
"genre/josei",
|
||||
"genre/kids",
|
||||
"genre/magic",
|
||||
"genre/martial-arts",
|
||||
"genre/mecha",
|
||||
"genre/military",
|
||||
"genre/music",
|
||||
"genre/mystery",
|
||||
"genre/parody",
|
||||
"genre/police",
|
||||
"genre/psychological",
|
||||
"genre/romance",
|
||||
"genre/samurai",
|
||||
"genre/school",
|
||||
"genre/sci-fi",
|
||||
"genre/seinen",
|
||||
"genre/shoujo",
|
||||
"genre/shoujo-ai",
|
||||
"genre/shounen",
|
||||
"genre/shounen-ai",
|
||||
"genre/slice-of-life",
|
||||
"genre/space",
|
||||
"genre/sports",
|
||||
"genre/super-power",
|
||||
"genre/supernatural",
|
||||
"genre/thriller",
|
||||
"genre/vampire",
|
||||
"top-airing",
|
||||
"most-popular",
|
||||
"most-favorite",
|
||||
"completed",
|
||||
"recently-updated",
|
||||
"recently-added",
|
||||
"top-upcoming",
|
||||
"subbed-anime",
|
||||
"dubbed-anime",
|
||||
"movie",
|
||||
"special",
|
||||
"ova",
|
||||
"ona",
|
||||
"tv",
|
||||
"music",
|
||||
"az-list",
|
||||
"az-list/other",
|
||||
"az-list/0-9",
|
||||
"az-list/a",
|
||||
"az-list/b",
|
||||
"az-list/c",
|
||||
"az-list/d",
|
||||
"az-list/e",
|
||||
"az-list/f",
|
||||
"az-list/g",
|
||||
"az-list/h",
|
||||
"az-list/i",
|
||||
"az-list/j",
|
||||
"az-list/k",
|
||||
"az-list/l",
|
||||
"az-list/m",
|
||||
"az-list/n",
|
||||
"az-list/o",
|
||||
"az-list/p",
|
||||
"az-list/q",
|
||||
"az-list/r",
|
||||
"az-list/s",
|
||||
"az-list/t",
|
||||
"az-list/u",
|
||||
"az-list/v",
|
||||
"az-list/w",
|
||||
"az-list/x",
|
||||
"az-list/y",
|
||||
"az-list/z",
|
||||
];
|
||||
129
src/routes/filter.maping.js
Normal file
129
src/routes/filter.maping.js
Normal file
@@ -0,0 +1,129 @@
|
||||
const FILTER_LANGUAGE_MAP = {
|
||||
ALL: '',
|
||||
SUB: '1',
|
||||
DUB: '2',
|
||||
SUB_DUB: '3'
|
||||
};
|
||||
|
||||
const GENRE_MAP = {
|
||||
ACTION: '1',
|
||||
ADVENTURE: '2',
|
||||
CARS: '3',
|
||||
COMEDY: '4',
|
||||
DEMENTIA: '5',
|
||||
DEMONS: '6',
|
||||
DRAMA: '8',
|
||||
ECCHI: '9',
|
||||
FANTASY: '10',
|
||||
GAME: '11',
|
||||
HAREM: '35',
|
||||
HISTORICAL: '13',
|
||||
HORROR: '14',
|
||||
ISEKAI: '44',
|
||||
JOSEI: '43',
|
||||
KIDS: '15',
|
||||
MAGIC: '16',
|
||||
MARTIAL_ARTS: '17',
|
||||
MECHA: '18',
|
||||
MILITARY: '38',
|
||||
MUSIC: '19',
|
||||
MYSTERY: '7',
|
||||
PARODY: '20',
|
||||
POLICE: '39',
|
||||
PSYCHOLOGICAL: '40',
|
||||
ROMANCE: '22',
|
||||
SAMURAI: '21',
|
||||
SCHOOL: '23',
|
||||
SCI_FI: '24',
|
||||
SEINEN: '42',
|
||||
SHOUJO: '25',
|
||||
SHOUJO_AI: '26',
|
||||
SHOUNEN: '27',
|
||||
SHOUNEN_AI: '28',
|
||||
SLICE_OF_LIFE: '36',
|
||||
SPACE: '29',
|
||||
SPORTS: '30',
|
||||
SUPER_POWER: '31',
|
||||
SUPERNATURAL: '37',
|
||||
THRILLER: '41',
|
||||
VAMPIRE: '32'
|
||||
|
||||
};
|
||||
|
||||
const FILTER_TYPES = {
|
||||
ALL: '',
|
||||
MOVIE: '1',
|
||||
TV: '2',
|
||||
OVA: '3',
|
||||
ONA: '4',
|
||||
SPECIAL: '5',
|
||||
MUSIC: '6'
|
||||
};
|
||||
|
||||
const FILTER_STATUS = {
|
||||
ALL: '',
|
||||
FINISHED: '1',
|
||||
CURRENTLY_AIRING: '2',
|
||||
NOT_YET_AIRED: '3'
|
||||
};
|
||||
|
||||
const FILTER_RATED = {
|
||||
ALL: '',
|
||||
G: '1',
|
||||
PG: '2',
|
||||
PG_13: '3',
|
||||
R: '4',
|
||||
R_PLUS: '5',
|
||||
RX: '6'
|
||||
};
|
||||
|
||||
const FILTER_SCORE = {
|
||||
ALL: '',
|
||||
APPALLING: '1',
|
||||
HORRIBLE: '2',
|
||||
VERY_BAD: '3',
|
||||
BAD: '4',
|
||||
AVERAGE: '5',
|
||||
FINE: '6',
|
||||
GOOD: '7',
|
||||
VERY_GOOD: '8',
|
||||
GREAT: '9',
|
||||
MASTERPIECE: '10'
|
||||
};
|
||||
|
||||
const FILTER_SEASON = {
|
||||
ALL: '',
|
||||
SPRING: '1',
|
||||
SUMMER: '2',
|
||||
FALL: '3',
|
||||
WINTER: '4'
|
||||
};
|
||||
|
||||
const FILTER_LANGUAGE = {
|
||||
ALL: '',
|
||||
SUB: '1',
|
||||
DUB: '2',
|
||||
SUB_DUB: '3'
|
||||
};
|
||||
|
||||
const FILTER_SORT = {
|
||||
DEFAULT: 'default',
|
||||
RECENTLY_ADDED: 'recently_added',
|
||||
RECENTLY_UPDATED: 'recently_updated',
|
||||
SCORE: 'score',
|
||||
NAME_AZ: 'name_az',
|
||||
RELEASED_DATE: 'released_date',
|
||||
MOST_WATCHED: 'most_watched'
|
||||
};
|
||||
|
||||
export {
|
||||
FILTER_LANGUAGE_MAP,
|
||||
GENRE_MAP,
|
||||
FILTER_TYPES,
|
||||
FILTER_STATUS,
|
||||
FILTER_RATED,
|
||||
FILTER_SCORE,
|
||||
FILTER_SEASON,
|
||||
FILTER_LANGUAGE,
|
||||
FILTER_SORT
|
||||
};
|
||||
1
src/utils/base_v1.js
Normal file
1
src/utils/base_v1.js
Normal file
@@ -0,0 +1 @@
|
||||
export const v1_base_url = "hianime.do";
|
||||
1
src/utils/base_v2.js
Normal file
1
src/utils/base_v2.js
Normal file
@@ -0,0 +1 @@
|
||||
export const v2_base_url = "kaido.to";
|
||||
1
src/utils/base_v3.js
Normal file
1
src/utils/base_v3.js
Normal file
@@ -0,0 +1 @@
|
||||
export const v3_base_url = "aniplay.lol";
|
||||
1
src/utils/base_v4.js
Normal file
1
src/utils/base_v4.js
Normal file
@@ -0,0 +1 @@
|
||||
export const v4_base_url = "9animetv.to";
|
||||
2
src/utils/fallback.js
Normal file
2
src/utils/fallback.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export const fallback_1="megaplay.buzz"
|
||||
export const fallback_2="vidwish.live"
|
||||
1
src/utils/provider.js
Normal file
1
src/utils/provider.js
Normal file
@@ -0,0 +1 @@
|
||||
export const provider = "https://megacloud.club";
|
||||
18
vercel.json
Normal file
18
vercel.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{
|
||||
"src": "server.js",
|
||||
"use": "@vercel/node"
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"src": "/(.*)",
|
||||
"dest": "server.js",
|
||||
"headers": {
|
||||
"Access-Control-Allow-Origin": "*"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user