mirror of
https://gitlab.com/vyla-entertainment/home.git
synced 2026-11-09 19:57:20 -05:00
removed stream-api & auth no need, fixed some issues aswell
This commit is contained in:
@@ -16,7 +16,7 @@ Vyla Home is a native desktop app that:
|
|||||||
|
|
||||||
When you launch Vyla Home, it:
|
When you launch Vyla Home, it:
|
||||||
|
|
||||||
1. Starts the necessary background services (authentication proxy, streaming API, media player)
|
1. Starts the necessary background services (media player server)
|
||||||
2. Loads your saved settings and credentials (encrypted for security)
|
2. Loads your saved settings and credentials (encrypted for security)
|
||||||
3. Checks for updates and installs them if available
|
3. Checks for updates and installs them if available
|
||||||
4. Opens the user interface in a secure, embedded browser window
|
4. Opens the user interface in a secure, embedded browser window
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const AdmZip = require('adm-zip');
|
|||||||
const { execSync } = require('child_process');
|
const { execSync } = require('child_process');
|
||||||
|
|
||||||
const BUILD_DIR = path.join(__dirname, 'dist-build');
|
const BUILD_DIR = path.join(__dirname, 'dist-build');
|
||||||
const REPOS = ['frontend', 'player', 'auth-proxy', 'stream-api'];
|
const REPOS = ['frontend', 'player'];
|
||||||
|
|
||||||
const TEMP_EXTRACT_DIR = path.join(__dirname, 'temp-validation-extract');
|
const TEMP_EXTRACT_DIR = path.join(__dirname, 'temp-validation-extract');
|
||||||
|
|
||||||
@@ -14,8 +14,6 @@ const GITLAB_GROUP = 'vyla-entertainment';
|
|||||||
const REPO_CONFIG = {
|
const REPO_CONFIG = {
|
||||||
'frontend': { name: 'frontend', branch: 'main' },
|
'frontend': { name: 'frontend', branch: 'main' },
|
||||||
'player': { name: 'player', branch: 'main' },
|
'player': { name: 'player', branch: 'main' },
|
||||||
'auth-proxy': { name: 'auth-proxy', branch: 'main' },
|
|
||||||
'stream-api': { name: 'stream-api', branch: 'main' },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const clonedRepos = new Set();
|
const clonedRepos = new Set();
|
||||||
@@ -174,12 +172,10 @@ function validatePayload(zipPath) {
|
|||||||
zip.extractAllTo(TEMP_EXTRACT_DIR, true);
|
zip.extractAllTo(TEMP_EXTRACT_DIR, true);
|
||||||
|
|
||||||
const requiredFiles = [
|
const requiredFiles = [
|
||||||
'player/index.html',
|
'player/server.js',
|
||||||
'auth-proxy/server.js',
|
|
||||||
'stream-api/server.js',
|
|
||||||
'frontend/index.html'
|
'frontend/index.html'
|
||||||
];
|
];
|
||||||
|
|
||||||
const validationResults = {
|
const validationResults = {
|
||||||
valid: true,
|
valid: true,
|
||||||
errors: [],
|
errors: [],
|
||||||
|
|||||||
@@ -1,16 +1,5 @@
|
|||||||
{
|
{
|
||||||
"player": {
|
"player": {
|
||||||
"TMDB_KEY": "YOUR_TMDB_KEY_HERE",
|
"TMDB_KEY": "YOUR_TMDB_KEY_HERE"
|
||||||
"API_KEY": "YOUR_API_KEY_HERE"
|
|
||||||
},
|
|
||||||
"auth-proxy": {
|
|
||||||
"VITE_API_KEY": "YOUR_VITE_API_KEY_HERE",
|
|
||||||
"PROXY_VITE_API_KEY": "YOUR_PROXY_VITE_API_KEY_HERE"
|
|
||||||
},
|
|
||||||
"stream-api": {
|
|
||||||
"TMDB_API_KEY": "YOUR_TMDB_API_KEY_HERE",
|
|
||||||
"GA_MEASUREMENT_ID": "YOUR_GA_MEASUREMENT_ID_HERE",
|
|
||||||
"GA_API_SECRET": "YOUR_GA_API_SECRET_HERE",
|
|
||||||
"TOKEN_SECRET": "YOUR_TOKEN_SECRET_HERE"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,5 @@
|
|||||||
{
|
{
|
||||||
"player": {
|
"player": {
|
||||||
"PORT": "3001",
|
"PORT": "3000"
|
||||||
"BASE_URL": "http://localhost:7860",
|
|
||||||
"BYPASS_AUTH": "true"
|
|
||||||
},
|
|
||||||
"auth-proxy": {
|
|
||||||
"PORT": "3000",
|
|
||||||
"VITE_BASE_URL": "http://localhost:7860",
|
|
||||||
"DEV_BYPASS_AUTH": "true"
|
|
||||||
},
|
|
||||||
"stream-api": {
|
|
||||||
"PORT": "7860",
|
|
||||||
"PROXY_URL": "https://txt.primebox.workers.dev",
|
|
||||||
"PROXY_STREAMS": "true",
|
|
||||||
"ENABLE_DEBUG_ROUTE": "true",
|
|
||||||
"BYPASS_AUTH": "true",
|
|
||||||
"TOKEN_SECRET": "vyla_default_secure_token_secret_local_dev_32chars"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,40 +2,17 @@
|
|||||||
"frontend": [
|
"frontend": [
|
||||||
{
|
{
|
||||||
"find": "https://player.vyla.cc",
|
"find": "https://player.vyla.cc",
|
||||||
"replace": "http://localhost:3001"
|
"replace": "http://localhost:3000"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"find": "http://player.vyla.cc",
|
"find": "http://player.vyla.cc",
|
||||||
"replace": "http://localhost:3001"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"find": "https://api.vyla.cc",
|
|
||||||
"replace": "http://localhost:7860"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"find": "https://auth.vyla.cc",
|
|
||||||
"replace": "http://localhost:3000"
|
"replace": "http://localhost:3000"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"player": [
|
"player": [
|
||||||
{
|
|
||||||
"find": "https://api.vyla.cc",
|
|
||||||
"replace": "http://localhost:7860"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"find": "https://auth.vyla.cc",
|
|
||||||
"replace": "http://localhost:3000"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"find": "https://player.vyla.cc",
|
"find": "https://player.vyla.cc",
|
||||||
"replace": "http://localhost:4890"
|
"replace": "http://localhost:4890"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"auth-proxy": [
|
|
||||||
{
|
|
||||||
"find": "https://player.vyla.cc",
|
|
||||||
"replace": "http://localhost:3001"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stream-api": []
|
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,7 @@ const path = require('path');
|
|||||||
|
|
||||||
const REPOS = {
|
const REPOS = {
|
||||||
frontend: { branch: 'main' },
|
frontend: { branch: 'main' },
|
||||||
player: { branch: 'main' },
|
player: { branch: 'main' }
|
||||||
'stream-api': { branch: 'main' },
|
|
||||||
'auth-proxy': { branch: 'main' }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const GITLAB_GROUP = 'vyla-entertainment';
|
const GITLAB_GROUP = 'vyla-entertainment';
|
||||||
|
|||||||
122
main.js
122
main.js
@@ -34,8 +34,6 @@ debugLog("--- Node.js Process Started ---");
|
|||||||
let serviceManager;
|
let serviceManager;
|
||||||
let expressApp;
|
let expressApp;
|
||||||
let expressServer;
|
let expressServer;
|
||||||
let playerExpressApp;
|
|
||||||
let playerExpressServer;
|
|
||||||
|
|
||||||
debugLog(`AppData Dir: ${APPDATA_DIR}`);
|
debugLog(`AppData Dir: ${APPDATA_DIR}`);
|
||||||
|
|
||||||
@@ -217,27 +215,51 @@ async function start() {
|
|||||||
let localSha = patcher.getCurrentSha();
|
let localSha = patcher.getCurrentSha();
|
||||||
debugLog(`Is First Run: ${isFirstRun}, Local Version: ${localVersion}, Local SHA: ${localSha}`);
|
debugLog(`Is First Run: ${isFirstRun}, Local Version: ${localVersion}, Local SHA: ${localSha}`);
|
||||||
|
|
||||||
const localZipPath = path.join(__dirname, 'update-payload.zip');
|
function findLocalZip() {
|
||||||
const localManifestPath = path.join(__dirname, 'manifest.json');
|
const searchRoots = [__dirname, process.cwd()];
|
||||||
let localZipManifest = null;
|
for (const root of searchRoots) {
|
||||||
|
let cur = root;
|
||||||
if (fs.existsSync(localZipPath) && fs.existsSync(localManifestPath)) {
|
for (let i = 0; i < 6; i++) {
|
||||||
try { localZipManifest = JSON.parse(fs.readFileSync(localManifestPath, 'utf8')); } catch (e) { }
|
const zp = path.join(cur, 'update-payload.zip');
|
||||||
|
if (fs.existsSync(zp)) {
|
||||||
|
const mp = path.join(cur, 'manifest.json');
|
||||||
|
return { zipPath: zp, manifestPath: fs.existsSync(mp) ? mp : null };
|
||||||
|
}
|
||||||
|
const parent = path.dirname(cur);
|
||||||
|
if (parent === cur) break;
|
||||||
|
cur = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (localZipManifest && (isFirstRun || localZipManifest.sha256 !== localSha)) {
|
const localFound = findLocalZip();
|
||||||
debugLog("New local payload detected! Applying local build...");
|
let localZipPath = localFound ? localFound.zipPath : null;
|
||||||
|
let localManifestPath = localFound ? localFound.manifestPath : null;
|
||||||
|
let localZipManifest = null;
|
||||||
|
|
||||||
|
if (localManifestPath) {
|
||||||
|
try {
|
||||||
|
localZipManifest = JSON.parse(fs.readFileSync(localManifestPath, 'utf8'));
|
||||||
|
} catch (e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localZipPath && (isFirstRun || (localZipManifest && localZipManifest.sha256 !== localSha))) {
|
||||||
|
debugLog(`Applying local development payload from: ${localZipPath}`);
|
||||||
sendToTauri('status', { message: 'Extracting local development payload...' });
|
sendToTauri('status', { message: 'Extracting local development payload...' });
|
||||||
patcher.purgeOldCode();
|
patcher.purgeOldCode();
|
||||||
patcher.extractZipPayload(localZipPath);
|
patcher.extractZipPayload(localZipPath);
|
||||||
patcher.applyPatches(getReplacementsConfig());
|
patcher.applyPatches(getReplacementsConfig());
|
||||||
patcher.bridgeCredentials(serviceManager.credentialManager);
|
patcher.bridgeCredentials(serviceManager.credentialManager);
|
||||||
patcher.saveCurrentVersion(localZipManifest.version, localZipManifest.sha256);
|
|
||||||
|
const ver = localZipManifest ? localZipManifest.version : '1.1.32';
|
||||||
|
const sha = localZipManifest ? localZipManifest.sha256 : null;
|
||||||
|
patcher.saveCurrentVersion(ver, sha);
|
||||||
serviceManager.envConfig = getEnvConfig();
|
serviceManager.envConfig = getEnvConfig();
|
||||||
|
|
||||||
isFirstRun = false;
|
isFirstRun = false;
|
||||||
localVersion = localZipManifest.version;
|
localVersion = ver;
|
||||||
localSha = localZipManifest.sha256;
|
localSha = sha;
|
||||||
debugLog("Local payload applied successfully.");
|
debugLog("Local payload applied successfully.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,18 +269,43 @@ async function start() {
|
|||||||
debugLog("Fetching updates from updateClient...");
|
debugLog("Fetching updates from updateClient...");
|
||||||
release = await updateClient.checkForUpdates();
|
release = await updateClient.checkForUpdates();
|
||||||
debugLog(`Update check finished. Found: ${release ? release.version : 'None'}`);
|
debugLog(`Update check finished. Found: ${release ? release.version : 'None'}`);
|
||||||
|
|
||||||
|
let appPkgVer = '0.0.0';
|
||||||
|
try {
|
||||||
|
appPkgVer = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8')).version || '0.0.0';
|
||||||
|
} catch (e) { }
|
||||||
|
|
||||||
|
if (release && release.version) {
|
||||||
|
const rVer = release.version.replace('v', '').split('.').map(Number);
|
||||||
|
const aVer = appPkgVer.split('.').map(Number);
|
||||||
|
let isOlder = false;
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
if ((rVer[i] || 0) < (aVer[i] || 0)) { isOlder = true; break; }
|
||||||
|
if ((rVer[i] || 0) > (aVer[i] || 0)) { break; }
|
||||||
|
}
|
||||||
|
if (isOlder) {
|
||||||
|
debugLog(`Remote version ${release.version} is older than local package ${appPkgVer}. Ignoring remote release.`);
|
||||||
|
release = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugLog(`Update check failed (offline?): ${e.message}`);
|
debugLog(`Update check failed (offline?): ${e.message}`);
|
||||||
sendToTauri('status', { message: `Update server check skipped (${e.message})` });
|
sendToTauri('status', { message: `Update server check skipped (${e.message})` });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const normalizeVer = (v) => (v || '').toString().replace(/^v/, '').trim();
|
||||||
|
|
||||||
if (release) {
|
if (release) {
|
||||||
const hasUpdate = release.version !== localVersion || (release.sha256 && release.sha256 !== localSha);
|
const isNewerSha = release.sha256 && localSha && release.sha256 !== localSha;
|
||||||
|
const isDifferentVer = normalizeVer(release.version) !== normalizeVer(localVersion);
|
||||||
|
const hasUpdate = (isDifferentVer || isNewerSha) && !localZipPath;
|
||||||
|
|
||||||
if (isFirstRun) {
|
if (isFirstRun) {
|
||||||
debugLog("First run. Installing remote build...");
|
debugLog("First run with no local payload. Installing remote build...");
|
||||||
sendToTauri('status', { message: 'First run detected. Preparing initial installation...' });
|
sendToTauri('status', { message: 'First run detected. Preparing initial installation...' });
|
||||||
await installBuild(release);
|
await installBuild(release);
|
||||||
} else if (hasUpdate) {
|
} else if (hasUpdate) {
|
||||||
|
|
||||||
debugLog("Update available. Prompting user...");
|
debugLog("Update available. Prompting user...");
|
||||||
sendToTauri('status', { message: `New update available (${release.version}). Awaiting confirmation...` });
|
sendToTauri('status', { message: `New update available (${release.version}). Awaiting confirmation...` });
|
||||||
|
|
||||||
@@ -327,51 +374,21 @@ async function start() {
|
|||||||
|
|
||||||
sendToTauri('status', { message: 'Validating critical components...' });
|
sendToTauri('status', { message: 'Validating critical components...' });
|
||||||
if (!patcher.verifyExtraction()) {
|
if (!patcher.verifyExtraction()) {
|
||||||
throw new Error('No application files found. Check your internet connection and try again.');
|
throw new Error('No application files found. Ensure you run "npm run build:payload" to generate the local development payload.');
|
||||||
}
|
}
|
||||||
|
|
||||||
sendToTauri('status', { message: 'Loading encrypted credentials...' });
|
sendToTauri('status', { message: 'Loading encrypted credentials...' });
|
||||||
serviceManager.credentialManager.loadCredentials();
|
serviceManager.credentialManager.loadCredentials();
|
||||||
|
|
||||||
sendToTauri('status', { message: 'Starting background services (auth-proxy, stream-api)...' });
|
sendToTauri('status', { message: 'Starting background services (player)...' });
|
||||||
await serviceManager.startServices([
|
await serviceManager.startServices([
|
||||||
{ name: 'auth-proxy', relativeDir: 'auth-proxy' },
|
{ name: 'player', relativeDir: 'player', startScript: 'server.js' }
|
||||||
{ name: 'stream-api', relativeDir: 'stream-api' },
|
|
||||||
]);
|
]);
|
||||||
debugLog("Backend services spawn requested.");
|
debugLog("Backend services spawn requested.");
|
||||||
|
|
||||||
sendToTauri('status', { message: 'Binding player web server on port 3001...' });
|
sendToTauri('status', { message: 'Waiting for microservices to bind port 3000...' });
|
||||||
const playerDir = path.join(APPDATA_DIR, 'player');
|
await serviceManager.waitForPorts([3000]);
|
||||||
playerExpressApp = express();
|
debugLog("Port 3000 is ready.");
|
||||||
playerExpressApp.use((req, res, next) => {
|
|
||||||
res.header('Access-Control-Allow-Origin', '*');
|
|
||||||
res.header('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
|
|
||||||
res.header('Access-Control-Allow-Headers', '*');
|
|
||||||
if (req.method === 'OPTIONS') return res.sendStatus(200);
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
playerExpressApp.get('/__tauri_cmd/:cmd', (req, res) => {
|
|
||||||
debugLog(`[PLAYER-SERVER:3001] Command received: ${req.params.cmd} (window: ${req.query.window || 'main'})`);
|
|
||||||
sendToTauri('tauri-cmd', { cmd: req.params.cmd, url: req.query.url, window: req.query.window });
|
|
||||||
res.sendStatus(200);
|
|
||||||
});
|
|
||||||
playerExpressApp.use(sameTabNavMiddleware(playerDir));
|
|
||||||
playerExpressApp.use(express.static(playerDir, {
|
|
||||||
etag: false,
|
|
||||||
setHeaders: (res) => {
|
|
||||||
res.set('Cache-Control', 'no-store, no-cache, must-revalidate, private');
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
playerExpressApp.get('*', (req, res) => {
|
|
||||||
res.set('Cache-Control', 'no-store, no-cache, must-revalidate, private');
|
|
||||||
res.sendFile(path.join(playerDir, 'index.html'));
|
|
||||||
});
|
|
||||||
playerExpressServer = playerExpressApp.listen(3001, '127.0.0.1');
|
|
||||||
debugLog("Player Express running on 3001");
|
|
||||||
|
|
||||||
sendToTauri('status', { message: 'Waiting for microservices to bind ports (3000, 3001, 7860)...' });
|
|
||||||
await serviceManager.waitForPorts([3000, 3001, 7860]);
|
|
||||||
debugLog("Ports 3000, 3001, 7860 are ready.");
|
|
||||||
|
|
||||||
sendToTauri('status', { message: 'Binding UI server on port 4890...' });
|
sendToTauri('status', { message: 'Binding UI server on port 4890...' });
|
||||||
const frontendDir = path.join(APPDATA_DIR, 'frontend');
|
const frontendDir = path.join(APPDATA_DIR, 'frontend');
|
||||||
@@ -409,9 +426,6 @@ async function start() {
|
|||||||
|
|
||||||
const FRONTEND_PORT = 4890;
|
const FRONTEND_PORT = 4890;
|
||||||
expressApp.use('/build', express.static(path.join(__dirname, 'build')));
|
expressApp.use('/build', express.static(path.join(__dirname, 'build')));
|
||||||
if (playerExpressApp) {
|
|
||||||
playerExpressApp.use('/build', express.static(path.join(__dirname, 'build')));
|
|
||||||
}
|
|
||||||
|
|
||||||
expressServer = expressApp.listen(FRONTEND_PORT, () => {
|
expressServer = expressApp.listen(FRONTEND_PORT, () => {
|
||||||
sendToTauri('status', { message: 'All backend services running and healthy.' });
|
sendToTauri('status', { message: 'All backend services running and healthy.' });
|
||||||
|
|||||||
@@ -54,4 +54,4 @@
|
|||||||
"installerHeaderIcon": "build/icon.ico"
|
"installerHeaderIcon": "build/icon.ico"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,9 +99,7 @@ class Patcher {
|
|||||||
|
|
||||||
verifyExtraction() {
|
verifyExtraction() {
|
||||||
const requiredFiles = [
|
const requiredFiles = [
|
||||||
'player/index.html',
|
'player/server.js',
|
||||||
'auth-proxy/server.js',
|
|
||||||
'stream-api/server.js',
|
|
||||||
'frontend/index.html'
|
'frontend/index.html'
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -155,7 +153,7 @@ class Patcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
applyPatches(replacements) {
|
applyPatches(replacements) {
|
||||||
const targetDirs = ['frontend', 'player', 'auth-proxy', 'stream-api'];
|
const targetDirs = ['frontend', 'player'];
|
||||||
for (const dirName of targetDirs) {
|
for (const dirName of targetDirs) {
|
||||||
const dirPath = path.join(this.appDataPath, dirName);
|
const dirPath = path.join(this.appDataPath, dirName);
|
||||||
if (!fs.existsSync(dirPath)) continue;
|
if (!fs.existsSync(dirPath)) continue;
|
||||||
|
|||||||
@@ -40,18 +40,16 @@ class ServiceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let tokenSecret = process.env.TOKEN_SECRET ||
|
let tokenSecret = process.env.TOKEN_SECRET ||
|
||||||
process.env.STREAM_API_TOKEN_SECRET ||
|
this.credentialManager.getCredential('player', 'TOKEN_SECRET');
|
||||||
this.credentialManager.getCredential('stream-api', 'TOKEN_SECRET');
|
|
||||||
|
|
||||||
if (!tokenSecret || tokenSecret.length < 32) {
|
if (!tokenSecret || tokenSecret.length < 32) {
|
||||||
tokenSecret = require('crypto').randomBytes(32).toString('hex');
|
tokenSecret = require('crypto').randomBytes(32).toString('hex');
|
||||||
this.credentialManager.setCredential('stream-api', 'TOKEN_SECRET', tokenSecret);
|
this.credentialManager.setCredential('player', 'TOKEN_SECRET', tokenSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
const env = {
|
const env = {
|
||||||
...process.env,
|
...process.env,
|
||||||
TOKEN_SECRET: tokenSecret,
|
TOKEN_SECRET: tokenSecret,
|
||||||
STREAM_API_TOKEN_SECRET: tokenSecret,
|
|
||||||
...(this.envConfig[name] || {}),
|
...(this.envConfig[name] || {}),
|
||||||
...(this.credentialManager.getServiceCredentials(name) || {})
|
...(this.credentialManager.getServiceCredentials(name) || {})
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -45,4 +45,4 @@
|
|||||||
"../node_modules/**/*"
|
"../node_modules/**/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user