ported sdk and this works

This commit is contained in:
2026-10-04 21:44:03 -07:00
parent 3ee95c1bf5
commit 63b1a494cb
67 changed files with 6177 additions and 53 deletions

76
scripts/build-android.mjs Normal file
View File

@@ -0,0 +1,76 @@
import { build } from 'esbuild';
import fs from 'node:fs';
import path from 'node:path';
const root = process.cwd();
const tmp = path.join(root, '.build');
const sdk = path.join(tmp, 'sdk');
const shim = path.join(tmp, 'shim');
const www = path.join(root, 'www');
fs.rmSync(tmp, { recursive: true, force: true });
fs.rmSync(www, { recursive: true, force: true });
fs.mkdirSync(shim, { recursive: true });
fs.mkdirSync(path.join(www, 'js'), { recursive: true });
fs.cpSync(path.join(root, 'node_modules/@vyla-entertainment/sdk/src'), sdk, { recursive: true });
const helpers = path.join(sdk, 'utils/helpers.js');
fs.writeFileSync(helpers, fs.readFileSync(helpers, 'utf8').replace(/\}, 60000\)\.unref\(\);/, '}, 60000);'));
fs.writeFileSync(path.join(shim, 'crypto.js'), `export const webcrypto = globalThis.crypto;
export function createHash() { throw new Error('unsupported'); }
export function createDecipheriv() { throw new Error('unsupported'); }
export default { webcrypto, createHash, createDecipheriv };
`);
fs.writeFileSync(path.join(shim, 'inject.js'), `import { Buffer } from 'buffer';
globalThis.Buffer = globalThis.Buffer || Buffer;
globalThis.process = globalThis.process || { env: {} };
if (!AbortSignal.timeout) {
AbortSignal.timeout = ms => { const c = new AbortController(); setTimeout(() => c.abort(), ms); return c.signal; };
}
export { Buffer };
`);
const files = [...new Set([...fs.readFileSync(path.join(sdk, 'config.js'), 'utf8').matchAll(/sourceFile:\s*'([^']+)'/g)].map(m => m[1]))];
const entry = `import SOURCES from './sdk/config.js';
import { createStreamArgs } from './sdk/utils/helpers.js';
import { fetchSubtitles, getSubPathsMovie, getSubPathsTv } from './sdk/subtitles.js';
${files.map((f, i) => `import * as m${i} from './sdk/sources/${f}.js';`).join('\n')}
const MODS = { ${files.map((f, i) => `'${f}': m${i}`).join(', ')} };
const core = { tmdbApiKey: null, penguManifest: null };
const live = () => SOURCES.filter(c => !c.disabled && MODS[c.sourceFile]);
globalThis.VylaLocal = {
init(key) { core.tmdbApiKey = key; globalThis.process.env.TMDB_API_KEY = key; },
sources() { return live(); },
async stream(key, id, s, e, ip) {
const cfg = live().find(c => c.key === key);
if (!cfg) throw new Error('Source not found');
return await MODS[cfg.sourceFile].getStream(await createStreamArgs(cfg, core, id, s, e, ip));
},
async subtitles(id, s, e) {
const paths = s != null && e != null ? await getSubPathsTv(id, s, e) : await getSubPathsMovie(id);
return await fetchSubtitles(paths);
}
};
`;
fs.writeFileSync(path.join(tmp, 'entry.js'), entry);
await build({
entryPoints: [path.join(tmp, 'entry.js')],
bundle: true,
format: 'iife',
target: 'chrome70',
platform: 'browser',
minify: true,
alias: { 'node:crypto': path.join(shim, 'crypto.js') },
inject: [path.join(shim, 'inject.js')],
outfile: path.join(www, 'js/vyla-local.js'),
logLevel: 'info'
});
for (const p of ['index.html', 'css', 'js', 'assets']) {
const from = path.join(root, p);
if (fs.existsSync(from)) fs.cpSync(from, path.join(www, p), { recursive: true, filter: s => !s.endsWith('vyla-local.js') });
}
fs.copyFileSync(path.join(root, 'node_modules/hls.js/dist/hls.min.js'), path.join(www, 'js/hls.min.js'));

40
scripts/build-apk.mjs Normal file
View File

@@ -0,0 +1,40 @@
import { spawnSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
const root = process.cwd();
const win = process.platform === 'win32';
const androidDir = path.join(root, 'android');
const run = (cmd, args, cwd = root) => {
const r = spawnSync(cmd, args, { cwd, stdio: 'inherit', shell: win });
if (r.status !== 0) process.exit(r.status || 1);
};
const sdk = process.env.ANDROID_HOME || process.env.ANDROID_SDK_ROOT;
const lp = path.join(androidDir, 'local.properties');
if (!fs.existsSync(lp)) {
if (!sdk) {
console.error('Set ANDROID_HOME to your Android SDK folder (Android Studio: Settings > Languages & Frameworks > Android SDK).');
process.exit(1);
}
fs.writeFileSync(lp, 'sdk.dir=' + sdk.replace(/\\/g, '\\\\') + '\n');
}
const j = spawnSync('java', ['-version'], { shell: win, stdio: 'ignore' });
if (j.status !== 0) {
console.error('JDK 17 not found. Install it and make sure java is on your PATH (or set JAVA_HOME).');
process.exit(1);
}
run('node', ['scripts/build-android.mjs']);
run('npx', ['cap', 'sync', 'android']);
run(win ? 'gradlew.bat' : './gradlew', ['assembleDebug'], androidDir);
const apk = path.join(androidDir, 'app/build/outputs/apk/debug/app-debug.apk');
if (!fs.existsSync(apk)) {
console.error('APK not found at ' + apk);
process.exit(1);
}
fs.copyFileSync(apk, path.join(root, 'vyla.apk'));
console.log('\nDone: ' + path.join(root, 'vyla.apk'));