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:
darkizone 2026-04-12 21:10:15 +01:00
parent a636575b09
commit 0bd5eb39e4
4 changed files with 105 additions and 0 deletions

View file

@ -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"

View file

@ -20,6 +20,13 @@ export const services = {
],
tld: "app",
},
darkibox: {
patterns: [
":id",
"d/:id",
"embed-:id.html",
],
},
dailymotion: {
patterns: ["video/:id"],
},

View file

@ -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 =>

View 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}`,
}
}
}