mirror of
https://github.com/imputnet/cobalt.git
synced 2026-08-04 15:28:34 +00:00
feat: add darkibox.com service
Add extractor for darkibox.com, an XFileSharing-based video hosting platform. Extraction flow: - POSTs to /dl endpoint with embed parameters - Unpacks Dean Edwards packed JavaScript - Extracts video URL from PlayerJS file: parameter Supports direct (/FILECODE), /d/FILECODE, and embed URLs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a636575b09
commit
0bd5eb39e4
4 changed files with 105 additions and 0 deletions
|
|
@ -29,6 +29,7 @@ import loom from "./services/loom.js";
|
|||
import facebook from "./services/facebook.js";
|
||||
import bluesky from "./services/bluesky.js";
|
||||
import newgrounds from "./services/newgrounds.js";
|
||||
import darkibox from "./services/darkibox.js";
|
||||
|
||||
let freebind;
|
||||
|
||||
|
|
@ -266,6 +267,14 @@ export default async function({ host, patternMatch, params, authType }) {
|
|||
});
|
||||
break;
|
||||
|
||||
case "darkibox":
|
||||
r = await darkibox({
|
||||
id: patternMatch.id,
|
||||
quality: params.videoQuality,
|
||||
isAudioOnly,
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
return createResponse("error", {
|
||||
code: "error.api.service.unsupported"
|
||||
|
|
|
|||
|
|
@ -20,6 +20,13 @@ export const services = {
|
|||
],
|
||||
tld: "app",
|
||||
},
|
||||
darkibox: {
|
||||
patterns: [
|
||||
":id",
|
||||
"d/:id",
|
||||
"embed-:id.html",
|
||||
],
|
||||
},
|
||||
dailymotion: {
|
||||
patterns: ["video/:id"],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ export const testers = {
|
|||
"bsky": pattern =>
|
||||
pattern.user?.length <= 128 && pattern.post?.length <= 128,
|
||||
|
||||
"darkibox": pattern =>
|
||||
pattern.id?.length <= 12,
|
||||
|
||||
"dailymotion": pattern => pattern.id?.length <= 32,
|
||||
|
||||
"facebook": pattern =>
|
||||
|
|
|
|||
86
api/src/processing/services/darkibox.js
Normal file
86
api/src/processing/services/darkibox.js
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import { genericUserAgent } from "../../config.js";
|
||||
|
||||
function unpack(packed) {
|
||||
const match = packed.match(
|
||||
/eval\(function\(p,a,c,k,e,d\)\{.*?\}?\('(.*?)','(\d+)',(\d+),'(.*?)'\.split/s
|
||||
);
|
||||
if (!match) return null;
|
||||
|
||||
let [, p, a, c, keywords] = match;
|
||||
a = parseInt(a);
|
||||
c = parseInt(c);
|
||||
const kw = keywords.split('|');
|
||||
|
||||
const base = (num, radix) => {
|
||||
const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
let result = '';
|
||||
while (num > 0) {
|
||||
result = chars[num % radix] + result;
|
||||
num = Math.floor(num / radix);
|
||||
}
|
||||
return result || '0';
|
||||
};
|
||||
|
||||
const decoded = p.replace(/\b\w+\b/g, (word) => {
|
||||
const index = parseInt(word, a) || 0;
|
||||
if (index < c && kw[index]) {
|
||||
return kw[index];
|
||||
}
|
||||
return word;
|
||||
});
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
export default async function(obj) {
|
||||
const html = await fetch(`https://darkibox.com/dl`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"user-agent": genericUserAgent,
|
||||
"content-type": "application/x-www-form-urlencoded",
|
||||
"referer": `https://darkibox.com/${obj.id}`,
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
op: "embed",
|
||||
file_code: obj.id,
|
||||
auto: "1",
|
||||
}),
|
||||
})
|
||||
.then(r => r.status === 200 ? r.text() : false)
|
||||
.catch(() => {});
|
||||
|
||||
if (!html) return { error: "fetch.fail" };
|
||||
|
||||
let videoUrl;
|
||||
|
||||
// try to find URL in packed JS
|
||||
const packedMatch = html.match(/eval\(function\(p,a,c,k,e,d\)\{.*?\)\)/s);
|
||||
if (packedMatch) {
|
||||
const unpacked = unpack(packedMatch[0]);
|
||||
if (unpacked) {
|
||||
const fileMatch = unpacked.match(/file\s*:\s*"(https?:\/\/[^"]+)"/);
|
||||
if (fileMatch) {
|
||||
videoUrl = fileMatch[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fallback: try direct regex on html
|
||||
if (!videoUrl) {
|
||||
const directMatch = html.match(/file\s*:\s*"(https?:\/\/[^"]+)"/);
|
||||
if (directMatch) {
|
||||
videoUrl = directMatch[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (!videoUrl) return { error: "fetch.fail" };
|
||||
|
||||
return {
|
||||
urls: videoUrl,
|
||||
filename: `darkibox_${obj.id}.mp4`,
|
||||
audioFilename: `darkibox_${obj.id}_audio`,
|
||||
fileMetadata: {
|
||||
title: `darkibox_${obj.id}`,
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue