cobalt/api/src/modules/processing/request.js

175 lines
4.7 KiB
JavaScript
Raw Normal View History

import ipaddr from "ipaddr.js";
import { normalizeURL } from "../processing/url.js";
import { createStream } from "../stream/manage.js";
import { verifyLanguageCode } from "../sub/utils.js";
const apiVar = {
allowed: {
vCodec: ["h264", "av1", "vp9"],
vQuality: ["max", "4320", "2160", "1440", "1080", "720", "480", "360", "240", "144"],
aFormat: ["best", "mp3", "ogg", "wav", "opus"],
filenamePattern: ["classic", "pretty", "basic", "nerdy"]
},
booleanOnly: [
"isAudioOnly",
"isTTFullAudio",
"isAudioMuted",
"dubLang",
"disableMetadata",
"twitterGif",
"tiktokH265"
]
}
export function createResponse(responseType, responseData) {
const internalError = (code) => {
let error = code || "Internal Server Error";
2024-05-15 17:55:14 +02:00
return {
status: 500,
body: {
status: "error",
error: {
code: code || "Internal Server Error",
},
text: error, // temporary backwards compatibility
2024-05-15 17:55:14 +02:00
critical: true
}
}
}
try {
let status = 200,
response = {};
switch(responseType) {
case "error":
status = 400;
break;
case "rate-limit":
status = 429;
break;
}
switch (responseType) {
case "error":
response = {
error: {
code: responseData.code,
context: responseData?.context,
},
text: responseData.code, // temporary backwards compatibility
}
break;
case "success":
case "rate-limit":
response = {
text: responseData.t,
}
break;
case "redirect":
response = {
url: responseData.u,
}
break;
case "stream":
response = {
url: createStream(responseData),
}
break;
case "picker":
let pickerType = "various",
audio = false;
if (responseData.service === "tiktok") {
audio = responseData.u;
pickerType = "images";
}
response = {
pickerType: pickerType,
picker: responseData.picker,
audio: audio,
}
break;
case "critical":
return internalError(responseData.code);
default:
throw "unreachable"
}
return {
status,
body: {
status: responseType,
...response
}
}
} catch {
2024-05-15 17:55:14 +02:00
return internalError()
}
}
export function normalizeRequest(request) {
try {
let template = {
url: normalizeURL(decodeURIComponent(request.url)),
vCodec: "h264",
vQuality: "720",
aFormat: "mp3",
filenamePattern: "classic",
isAudioOnly: false,
isTTFullAudio: false,
isAudioMuted: false,
disableMetadata: false,
dubLang: false,
twitterGif: false,
tiktokH265: false
}
const requestKeys = Object.keys(request);
const templateKeys = Object.keys(template);
if (requestKeys.length > templateKeys.length + 1 || !request.url) {
return false;
}
for (const i in requestKeys) {
const key = requestKeys[i];
const item = request[key];
if (String(key) !== "url" && templateKeys.includes(key)) {
if (apiVar.booleanOnly.includes(key)) {
template[key] = !!item;
} else if (apiVar.allowed[key] && apiVar.allowed[key].includes(item)) {
template[key] = String(item)
}
}
}
if (template.dubLang)
template.dubLang = verifyLanguageCode(request.dubLang);
return template
} catch {
return false
}
}
export function getIP(req) {
const strippedIP = req.ip.replace(/^::ffff:/, '');
const ip = ipaddr.parse(strippedIP);
if (ip.kind() === 'ipv4') {
return strippedIP;
}
const prefix = 56;
const v6Bytes = ip.toByteArray();
v6Bytes.fill(0, prefix / 8);
return ipaddr.fromByteArray(v6Bytes).toString();
}