initial push from external dev branches

This commit is contained in:
iFlip721
2026-06-11 16:40:21 -04:00
parent 986e83632b
commit 245034a43a
182 changed files with 15465 additions and 0 deletions

116
server/dist/sources/adapters/dulo.js vendored Normal file
View File

@@ -0,0 +1,116 @@
// dulo.tv source adapter (Phase 1). Ported from ../d-combine/sources/dulo/adapter.mjs.
//
// dulo.tv exposes a JSON catalog API and each channel's `source_url` IS a token-free HLS master
// playlist. The memfs hosts gate playback behind an Origin allowlist, so the proxy injects
// `Origin: https://dulo.tv` on every hop. No server-side resolve is needed.
import { readFileSync } from 'node:fs';
import { snapshotFile } from '../paths.js';
const SNAPSHOT = snapshotFile('dulo');
const DULO_ORIGIN = 'https://dulo.tv';
const DULO_API = process.env.DULO_API || 'https://dulo.tv/api/live-tv/channels';
function isHttpUrl(url) {
if (typeof url !== 'string')
return false;
try {
const u = new URL(url);
return u.protocol === 'https:' || u.protocol === 'http:';
}
catch {
return false;
}
}
function toIso(ts) {
if (!ts || typeof ts !== 'string')
return null;
const d = new Date(ts);
return Number.isNaN(d.getTime()) ? null : d.toISOString();
}
const duloAdapter = {
id: 'dulo',
label: 'dulo',
// Prefer the live catalog API; fall back to the captured snapshot when offline / region-blocked.
async listChannels() {
try {
const res = await fetch(DULO_API, { headers: { Origin: DULO_ORIGIN } });
if (!res.ok)
throw new Error(`HTTP ${res.status}`);
const body = (await res.json());
const raw = body.channels || [];
if (!raw.length)
throw new Error('empty channel list');
return { raw, meta: { endpoint: DULO_API, live: true, fetchedAt: new Date().toISOString() } };
}
catch (err) {
const snap = JSON.parse(readFileSync(SNAPSHOT, 'utf8'));
return {
raw: snap.channels || [],
meta: {
endpoint: DULO_API,
live: false,
fallback: 'dulo.snapshot.json',
reason: err.message,
fetchedAt: new Date().toISOString(),
},
};
}
},
normalize(raw, { ingestedAt }) {
const sourceChannelId = String(raw.id);
const category = raw.category || null;
return {
_id: `dulo:${sourceChannelId}`,
source: 'dulo',
sourceChannelId,
name: raw.name,
category, // dulo has real semantic categories
groupKey: category || 'uncategorized',
groupLabel: category || 'uncategorized',
logoUrl: raw.logo_url || null,
streamEntryUrl: raw.source_url, // token-free master .m3u8 (handed straight to the proxy)
isPlayable: isHttpUrl(raw.source_url),
sourceCreatedAt: toIso(raw.created_at),
sourceUpdatedAt: toIso(raw.updated_at),
ingestedAt,
};
},
grouping: { by: 'groupKey', groupOrder: 'alpha', channelOrder: 'name' },
isEntryUrl() {
return false; // dulo source_url is already the master — nothing to resolve
},
async resolveStream(entryUrl) {
return { masterUrl: entryUrl }; // identity no-op
},
proxy: {
upstreamHeaders() {
return { Origin: DULO_ORIGIN }; // the memfs Origin allowlist gate
},
isAllowedUpstream(url) {
try {
const u = new URL(url);
return (u.protocol === 'https:' || u.protocol === 'http:') && u.hostname.endsWith('.dulo.tv');
}
catch {
return false;
}
},
onPlaylistChildHost: null, // static allowlist — nothing to learn at runtime
relabelSegmentContentType(_url, contentType) {
return contentType || 'application/octet-stream'; // plain TS — pass the upstream type through
},
classifyArtifact(url) {
try {
const p = new URL(url).pathname.toLowerCase();
if (p.endsWith('.ts'))
return 'segment';
if (p.endsWith('.m3u8'))
return p.includes('_output_') ? 'variant' : 'master';
return 'other';
}
catch {
return 'other';
}
},
},
};
export default duloAdapter;
//# sourceMappingURL=dulo.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"dulo.js","sourceRoot":"","sources":["../../../src/sources/adapters/dulo.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,EAAE;AACF,gGAAgG;AAChG,2FAA2F;AAC3F,4EAA4E;AAE5E,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AACtC,MAAM,WAAW,GAAG,iBAAiB,CAAC;AACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,sCAAsC,CAAC;AAEhF,SAAS,SAAS,CAAC,GAAY;IAC7B,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC1C,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACvB,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,EAAW;IACxB,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC/C,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;IACvB,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;AAC5D,CAAC;AAED,MAAM,WAAW,GAAkB;IACjC,EAAE,EAAE,MAAM;IACV,KAAK,EAAE,MAAM;IAEb,iGAAiG;IACjG,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;YACxE,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YACnD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAyB,CAAC;YACxD,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;YAChC,IAAI,CAAC,GAAG,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;YACvD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC;QAChG,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAyB,CAAC;YAChF,OAAO;gBACL,GAAG,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;gBACxB,IAAI,EAAE;oBACJ,QAAQ,EAAE,QAAQ;oBAClB,IAAI,EAAE,KAAK;oBACX,QAAQ,EAAE,oBAAoB;oBAC9B,MAAM,EAAG,GAAa,CAAC,OAAO;oBAC9B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACpC;aACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,SAAS,CAAC,GAAQ,EAAE,EAAE,UAAU,EAAE;QAChC,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC;QACtC,OAAO;YACL,GAAG,EAAE,QAAQ,eAAe,EAAE;YAC9B,MAAM,EAAE,MAAM;YACd,eAAe;YACf,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,QAAQ,EAAE,oCAAoC;YAC9C,QAAQ,EAAE,QAAQ,IAAI,eAAe;YACrC,UAAU,EAAE,QAAQ,IAAI,eAAe;YACvC,OAAO,EAAE,GAAG,CAAC,QAAQ,IAAI,IAAI;YAC7B,cAAc,EAAE,GAAG,CAAC,UAAU,EAAE,yDAAyD;YACzF,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC;YACrC,eAAe,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;YACtC,eAAe,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;YACtC,UAAU;SACX,CAAC;IACJ,CAAC;IAED,QAAQ,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE;IAEvE,UAAU;QACR,OAAO,KAAK,CAAC,CAAC,6DAA6D;IAC7E,CAAC;IACD,KAAK,CAAC,aAAa,CAAC,QAAgB;QAClC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,iBAAiB;IACnD,CAAC;IAED,KAAK,EAAE;QACL,eAAe;YACb,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,kCAAkC;QACpE,CAAC;QACD,iBAAiB,CAAC,GAAW;YAC3B,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;gBACvB,OAAO,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAChG,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QACD,mBAAmB,EAAE,IAAI,EAAE,iDAAiD;QAC5E,yBAAyB,CAAC,IAAY,EAAE,WAAmB;YACzD,OAAO,WAAW,IAAI,0BAA0B,CAAC,CAAC,4CAA4C;QAChG,CAAC;QACD,gBAAgB,CAAC,GAAW;YAC1B,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;gBAC9C,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;oBAAE,OAAO,SAAS,CAAC;gBACxC,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;oBAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;gBAC9E,OAAO,OAAO,CAAC;YACjB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;KACF;CACF,CAAC;AAEF,eAAe,WAAW,CAAC"}