mirror of
https://github.com/imputnet/cobalt.git
synced 2025-07-13 08:48:26 +00:00
added devcontainer and made a custom cookie workaround for a specific problem
This commit is contained in:
parent
98ad968606
commit
5bf86f1daa
@ -6,6 +6,13 @@
|
||||
"image": "mcr.microsoft.com/devcontainers/universal:2-linux",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": {}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"svelte.svelte-vscode"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// Features to add to the dev container. More info: https://containers.dev/features.
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@ desktop.ini
|
||||
|
||||
# node
|
||||
node_modules
|
||||
.pnpm-store
|
||||
|
||||
# static build
|
||||
build
|
||||
|
@ -154,41 +154,43 @@ export const runAPI = async (express, app, __dirname, isPrimary = true) => {
|
||||
});
|
||||
|
||||
app.post('/', (req, res, next) => {
|
||||
if (!env.sessionEnabled || req.rateLimitKey) {
|
||||
return next();
|
||||
}
|
||||
// if (!env.sessionEnabled || req.rateLimitKey) {
|
||||
// return next();
|
||||
// }
|
||||
|
||||
try {
|
||||
const authorization = req.header("Authorization");
|
||||
if (!authorization) {
|
||||
return fail(res, "error.api.auth.jwt.missing");
|
||||
}
|
||||
// try {
|
||||
// const authorization = req.header("Authorization");
|
||||
// if (!authorization) {
|
||||
// return fail(res, "error.api.auth.jwt.missing");
|
||||
// }
|
||||
|
||||
if (authorization.length >= 256) {
|
||||
return fail(res, "error.api.auth.jwt.invalid");
|
||||
}
|
||||
// if (authorization.length >= 256) {
|
||||
// return fail(res, "error.api.auth.jwt.invalid");
|
||||
// }
|
||||
|
||||
const [ type, token, ...rest ] = authorization.split(" ");
|
||||
if (!token || type.toLowerCase() !== 'bearer' || rest.length) {
|
||||
return fail(res, "error.api.auth.jwt.invalid");
|
||||
}
|
||||
// const [ type, token, ...rest ] = authorization.split(" ");
|
||||
// if (!token || type.toLowerCase() !== 'bearer' || rest.length) {
|
||||
// return fail(res, "error.api.auth.jwt.invalid");
|
||||
// }
|
||||
|
||||
if (!jwt.verify(token)) {
|
||||
return fail(res, "error.api.auth.jwt.invalid");
|
||||
}
|
||||
// if (!jwt.verify(token)) {
|
||||
// return fail(res, "error.api.auth.jwt.invalid");
|
||||
// }
|
||||
|
||||
req.rateLimitKey = hashHmac(token, 'rate');
|
||||
} catch {
|
||||
return fail(res, "error.api.generic");
|
||||
}
|
||||
// req.rateLimitKey = hashHmac(token, 'rate');
|
||||
// } catch {
|
||||
// return fail(res, "error.api.generic");
|
||||
// }
|
||||
next();
|
||||
});
|
||||
|
||||
app.post('/', apiLimiter);
|
||||
app.use('/', express.json({ limit: 1024 }));
|
||||
app.use('/', express.json({ limit: 8192 }));
|
||||
|
||||
app.use('/', (err, _, res, next) => {
|
||||
app.use('/', (err, req, res, next) => {
|
||||
if (err) {
|
||||
// console.error('Failed to normalize request:', req);
|
||||
console.error('error:', err);
|
||||
const { status, body } = createResponse("error", {
|
||||
code: "error.api.invalid_body",
|
||||
});
|
||||
@ -234,6 +236,8 @@ export const runAPI = async (express, app, __dirname, isPrimary = true) => {
|
||||
|
||||
const { success, data: normalizedRequest } = await normalizeRequest(request);
|
||||
if (!success) {
|
||||
console.error('Failed to normalize request:', request);
|
||||
console.log('data:', normalizedRequest);
|
||||
return fail(res, "error.api.invalid_body");
|
||||
}
|
||||
|
||||
@ -250,15 +254,20 @@ export const runAPI = async (express, app, __dirname, isPrimary = true) => {
|
||||
return fail(res, `error.api.${parsed.error}`, context);
|
||||
}
|
||||
|
||||
if (!request.cookies)
|
||||
request.cookies = {"X-nocookies" : "included"};
|
||||
|
||||
try {
|
||||
const result = await match({
|
||||
host: parsed.host,
|
||||
patternMatch: parsed.patternMatch,
|
||||
params: normalizedRequest,
|
||||
inputCookies: request.cookies,
|
||||
});
|
||||
|
||||
res.status(result.status).json(result.body);
|
||||
} catch {
|
||||
} catch (e) {
|
||||
console.error("Failed to match request", request, e);
|
||||
fail(res, "error.api.generic");
|
||||
}
|
||||
})
|
||||
|
@ -29,14 +29,24 @@ import loom from "./services/loom.js";
|
||||
import facebook from "./services/facebook.js";
|
||||
import bluesky from "./services/bluesky.js";
|
||||
import xiaohongshu from "./services/xiaohongshu.js";
|
||||
import Cookie from "./cookie/cookie.js";
|
||||
|
||||
let freebind;
|
||||
|
||||
export default async function({ host, patternMatch, params }) {
|
||||
export default async function({ host, patternMatch, params, inputCookies }) {
|
||||
const { url } = params;
|
||||
assert(url instanceof URL);
|
||||
let dispatcher, requestIP;
|
||||
|
||||
console.log('Calling with cookies:', inputCookies);
|
||||
|
||||
let cookies = new Cookie({});
|
||||
for (const [k, v] of Object.entries(inputCookies)) {
|
||||
cookies.set(k, v);
|
||||
}
|
||||
|
||||
console.log('Calling with cookies:', cookies);
|
||||
|
||||
if (env.freebindCIDR) {
|
||||
if (!freebind) {
|
||||
freebind = await import('freebind');
|
||||
@ -133,6 +143,7 @@ export default async function({ host, patternMatch, params }) {
|
||||
isAudioOnly,
|
||||
h265: params.tiktokH265,
|
||||
alwaysProxy: params.alwaysProxy,
|
||||
cookies: cookies,
|
||||
});
|
||||
break;
|
||||
|
||||
|
@ -77,9 +77,10 @@ export function createResponse(responseType, responseData) {
|
||||
}
|
||||
|
||||
export function normalizeRequest(request) {
|
||||
return apiSchema.safeParseAsync(request).catch(() => (
|
||||
{ success: false }
|
||||
));
|
||||
return apiSchema.safeParseAsync(request).catch((err) => {
|
||||
console.log('Zod validation error:', JSON.stringify(err, null, 2));
|
||||
return { success: false };
|
||||
});
|
||||
}
|
||||
|
||||
export function getIP(req) {
|
||||
|
@ -47,5 +47,7 @@ export const apiSchema = z.object({
|
||||
twitterGif: z.boolean().default(true),
|
||||
|
||||
youtubeHLS: z.boolean().default(false),
|
||||
|
||||
cookies: z.record(z.string()).default({}),
|
||||
})
|
||||
.strict();
|
||||
|
@ -8,9 +8,12 @@ import { createStream } from "../../stream/manage.js";
|
||||
const shortDomain = "https://vt.tiktok.com/";
|
||||
|
||||
export default async function(obj) {
|
||||
const cookie = new Cookie({});
|
||||
// const cookie = new Cookie({});
|
||||
const cookie = obj.cookies;
|
||||
let postId = obj.postId;
|
||||
|
||||
console.log("With TikTok using cookies", cookie);
|
||||
|
||||
if (!postId) {
|
||||
let html = await fetch(`${shortDomain}${obj.shortLink}`, {
|
||||
redirect: "manual",
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"gotit": "got it",
|
||||
"signin": "sign into service",
|
||||
"cancel": "cancel",
|
||||
"reset": "reset",
|
||||
"done": "done",
|
||||
|
@ -59,7 +59,7 @@
|
||||
|
||||
"api.content.post.unavailable": "couldn't find anything about this post. its visibility may be limited or it may not exist. make sure your link works and try again in a few seconds!",
|
||||
"api.content.post.private": "couldn't get anything about this post because it's from a private account. try a different link!",
|
||||
"api.content.post.age": "this post is age-restricted and isn't available without logging in. try a different link!",
|
||||
"api.content.post.age": "this post is age-restricted and isn't available without logging in. Sign in to your account.",
|
||||
|
||||
"api.youtube.no_matching_format": "youtube didn't return a valid video + audio format combo, either video or audio is missing. formats for this video may be re-encoding on youtube's side or something went wrong when parsing them. try enabling the hls option in video settings!",
|
||||
"api.youtube.decipher": "youtube updated its decipher algorithm and i couldn't extract the info about the video. try again in a few seconds, but if this issue sticks, please report it!",
|
||||
|
@ -38,7 +38,8 @@
|
||||
let isDisabled = false;
|
||||
let isLoading = false;
|
||||
|
||||
$: isBotCheckOngoing = $turnstileEnabled && !$turnstileSolved;
|
||||
// $: isBotCheckOngoing = $turnstileEnabled && !$turnstileSolved;
|
||||
$: isBotCheckOngoing = false;
|
||||
|
||||
const validLink = (url: string) => {
|
||||
try {
|
||||
@ -132,7 +133,8 @@
|
||||
-->
|
||||
{#if env.DEFAULT_API || (!$page.url.host.endsWith(".cobalt.tools") && $page.url.host !== "cobalt.tools")}
|
||||
<div id="instance-label">
|
||||
{$t("save.label.community_instance")}
|
||||
KDDResearch Instance
|
||||
<!-- {$t("save.label.community_instance")} -->
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@ -155,13 +157,14 @@
|
||||
autocapitalize="off"
|
||||
maxlength="512"
|
||||
placeholder={$t("save.input.placeholder")}
|
||||
aria-label={isBotCheckOngoing
|
||||
? $t("a11y.save.link_area.turnstile")
|
||||
: $t("a11y.save.link_area")}
|
||||
data-form-type="other"
|
||||
disabled={isDisabled}
|
||||
/>
|
||||
|
||||
<!-- aria-label={isBotCheckOngoing
|
||||
? $t("a11y.save.link_area.turnstile")
|
||||
: $t("a11y.save.link_area")} -->
|
||||
|
||||
{#if $link && !isLoading}
|
||||
<ClearButton click={() => ($link = "")} />
|
||||
{/if}
|
||||
|
@ -77,6 +77,50 @@
|
||||
if (response.status === "error") {
|
||||
changeDownloadButton("error");
|
||||
|
||||
console.log(response.error.code);
|
||||
|
||||
if (response.error.code == "error.api.content.post.age") {
|
||||
return createDialog({
|
||||
id: "save-error",
|
||||
type: "small",
|
||||
meowbalt: "error",
|
||||
buttons: [
|
||||
{
|
||||
text: $t("button.signin"),
|
||||
main: true,
|
||||
action: () => {
|
||||
// opens a new tab for the user and redirects them to the login page
|
||||
|
||||
const website = URL.parse(link);
|
||||
|
||||
if (!website)
|
||||
throw new Error("Invalid URL");
|
||||
|
||||
console.log(website);
|
||||
|
||||
switch (website.hostname) {
|
||||
case "www.tiktok.com":
|
||||
website.pathname = "/login/qrcode";
|
||||
break;
|
||||
default:
|
||||
website.pathname = "/login";
|
||||
break;
|
||||
}
|
||||
|
||||
window.open(website.href, "_blank");
|
||||
},
|
||||
},
|
||||
{
|
||||
text: $t("button.cancel"),
|
||||
main: false,
|
||||
action: () => {},
|
||||
},
|
||||
],
|
||||
bodyText: $t(response.error.code, response?.error?.context),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return createDialog({
|
||||
...defaultErrorPopup,
|
||||
bodyText: $t(response.error.code, response?.error?.context),
|
||||
|
@ -8,10 +8,11 @@ export const turnstileCreated = writable(false);
|
||||
export const turnstileEnabled = derived(
|
||||
[settings, cachedInfo],
|
||||
([$settings, $cachedInfo]) => {
|
||||
return !!$cachedInfo?.info?.cobalt?.turnstileSitekey &&
|
||||
!(
|
||||
$settings.processing.enableCustomApiKey &&
|
||||
$settings.processing.customApiKey.length > 0
|
||||
)
|
||||
// return !!$cachedInfo?.info?.cobalt?.turnstileSitekey &&
|
||||
// !(
|
||||
// $settings.processing.enableCustomApiKey &&
|
||||
// $settings.processing.customApiKey.length > 0
|
||||
// )
|
||||
return false;
|
||||
}
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user