Removed send_push.js

This commit is contained in:
hbrain 2026-06-07 14:26:28 +00:00
parent bacb335e38
commit 8fc2e3b4c9
4 changed files with 0 additions and 433 deletions

View file

@ -1,191 +0,0 @@
<?php
// examples/enable_show_local.php
// Web-server side handler to toggle "Show" for an MVLog job and send a web-push immediately if appropriate.
// This runs entirely on the web server and does not call the worker.
//
// Usage (POST): job=<job> show=1|0
// Configure $MVLOG_ROOT and $PUSH_CONFIG below.
// Configuration - update to match your server
$MVLOG_ROOT = '/var/www/html/mvlog';
$PUSH_CONFIG_CANDIDATES = [
"$MVLOG_ROOT/push.json",
getenv('HOME') !== false ? getenv('HOME') . '/.config/mvlog/push.json' : null,
'/etc/mvlog/push.json',
];
$LOGFILE = '/var/log/mvlog_notify.log';
$job = $_POST['job'] ?? '';
$show = isset($_POST['show']) ? filter_var($_POST['show'], FILTER_VALIDATE_BOOLEAN) : true;
// Basic validation for job name; adjust to your naming policy if needed
if (!preg_match('/^[0-9]{8}[-_][A-Za-z0-9._-]+$/', $job)) {
http_response_code(400);
echo 'invalid job';
exit;
}
$jobdir = "$MVLOG_ROOT/in-dir/$job";
if (!is_dir($jobdir)) {
http_response_code(404);
echo 'job not found';
exit;
}
$enabled_file = "$jobdir/.movmaker-enabled";
$hidden_file = "$jobdir/.mvlog-hidden";
$subs_file = "$MVLOG_ROOT/cache/push_subscriptions.json";
$cache_file = "$MVLOG_ROOT/cache/push_notifications.json";
// Find push config
$push_config = null;
foreach ($PUSH_CONFIG_CANDIDATES as $candidate) {
if (!$candidate) continue;
if (file_exists($candidate) && is_readable($candidate)) {
$push_config = $candidate;
break;
}
}
if ($show) {
// Create marker file atomically
file_put_contents($enabled_file, date(DATE_ATOM) . PHP_EOL, LOCK_EX);
// Try to send push (non-fatal)
$sent = try_send_show_notification($job, $jobdir, $MVLOG_ROOT, $subs_file, $cache_file, $push_config, $LOGFILE);
if ($sent) {
echo 'enabled';
} else {
echo 'enabled (no notification)';
}
} else {
// Remove marker and do not touch notifications
@unlink($enabled_file);
echo 'disabled';
}
exit;
function try_send_show_notification($job, $jobdir, $root, $subs_file, $cache_file, $push_config, $logfile)
{
// Skip if hidden
if (file_exists($jobdir . '/.mvlog-hidden')) {
error_log("[mvlog] job $job hidden, skipping push\n", 3, $logfile);
return false;
}
// Ensure we have subscriptions
if (!file_exists($subs_file)) {
error_log("[mvlog] subscriptions file missing, skipping push for $job\n", 3, $logfile);
return false;
}
$subs_raw = file_get_contents($subs_file);
if (!trim($subs_raw)) {
error_log("[mvlog] subscriptions empty, skipping push for $job\n", 3, $logfile);
return false;
}
$subs = json_decode($subs_raw, true);
if (!is_array($subs) || count($subs) === 0) {
error_log("[mvlog] subscriptions invalid/empty, skipping push for $job\n", 3, $logfile);
return false;
}
// Read cache and check if already shown
$cache = [];
if (file_exists($cache_file)) {
$cache = json_decode(@file_get_contents($cache_file), true) ?: [];
}
$shown = isset($cache['shown']) && is_array($cache['shown']) ? $cache['shown'] : [];
if (isset($shown[$job])) {
error_log("[mvlog] push already sent for $job, skipping\n", 3, $logfile);
return false;
}
// Ensure push config present
if (!$push_config) {
error_log("[mvlog] push config not found, skipping push for $job\n", 3, $logfile);
return false;
}
// Determine title (prefer output filename from state file)
$title = preg_replace('/_+/', ' ', $job);
$title = ucwords($title);
$state_file = $jobdir . '/.movmaker-state.json';
if (file_exists($state_file)) {
$state = json_decode(@file_get_contents($state_file), true) ?: [];
if (!empty($state['output']) && is_string($state['output'])) {
$out = pathinfo($state['output'], PATHINFO_FILENAME);
if ($out) {
$title = preg_replace('/_+/', ' ', $out);
$title = ucwords($title);
}
}
}
$article_id_file = $jobdir . '/.mvlog-id';
$article_id = file_exists($article_id_file) ? strtolower(trim((string)@file_get_contents($article_id_file))) : '';
if (!preg_match('/^[0-9]{14}[a-f0-9]{16}$/', $article_id)) {
error_log("[mvlog] article id missing, skipping push for $job\n", 3, $logfile);
return false;
}
$payload = json_encode([
'title' => 'Show enabled',
'body' => $title,
'url' => './?id=' . rawurlencode($article_id),
'tag' => "mvlog-show-$article_id",
], JSON_UNESCAPED_UNICODE);
// Call node send_push.js with subscriptions on stdin
$send_script = escapeshellarg($root . '/send_push.js');
$push_config_esc = escapeshellarg($push_config);
$payload_esc = escapeshellarg($payload);
$cmd = "node $send_script $push_config_esc $payload_esc";
$descriptorspec = [
0 => ['pipe', 'r'], // stdin
1 => ['pipe', 'w'], // stdout
2 => ['pipe', 'w'], // stderr
];
$proc = proc_open($cmd, $descriptorspec, $pipes);
if (!is_resource($proc)) {
error_log("[mvlog] failed to start node send_push process for $job\n", 3, $logfile);
return false;
}
// Write subscriptions to stdin
fwrite($pipes[0], $subs_raw);
fclose($pipes[0]);
$stdout = stream_get_contents($pipes[1]); fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]); fclose($pipes[2]);
$rc = proc_close($proc);
if ($rc !== 0) {
error_log("[mvlog] send_push failed for $job rc=$rc stdout=" . trim($stdout) . " stderr=" . trim($stderr) . "\n", 3, $logfile);
return false;
}
// On success, record in cache['shown']
if (!is_array($cache)) $cache = [];
if (!isset($cache['shown']) || !is_array($cache['shown'])) $cache['shown'] = [];
$cache['shown'][$job] = ['sent_at' => date(DATE_ATOM)];
// Atomic write: write to tmp then rename
$tmp = $cache_file . '.tmp.' . bin2hex(random_bytes(6));
$json = json_encode($cache, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
if (@file_put_contents($tmp, $json, LOCK_EX) === false) {
error_log("[mvlog] failed to write cache temp file for $job\n", 3, $logfile);
return false;
}
@chmod($tmp, 0664);
if (!@rename($tmp, $cache_file)) {
@unlink($tmp);
error_log("[mvlog] failed to atomically write cache file for $job\n", 3, $logfile);
return false;
}
error_log("[mvlog] show-notification sent: $job\n", 3, $logfile);
return true;
}

190
package-lock.json generated
View file

@ -1,190 +0,0 @@
{
"name": "movmaker",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "movmaker",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"web-push": "^3.6.7"
}
},
"node_modules/agent-base": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
"license": "MIT",
"engines": {
"node": ">= 14"
}
},
"node_modules/asn1.js": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
"integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
"license": "MIT",
"dependencies": {
"bn.js": "^4.0.0",
"inherits": "^2.0.1",
"minimalistic-assert": "^1.0.0",
"safer-buffer": "^2.1.0"
}
},
"node_modules/bn.js": {
"version": "4.12.3",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz",
"integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==",
"license": "MIT"
},
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
"license": "BSD-3-Clause"
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"license": "Apache-2.0",
"dependencies": {
"safe-buffer": "^5.0.1"
}
},
"node_modules/http_ece": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http_ece/-/http_ece-1.2.0.tgz",
"integrity": "sha512-JrF8SSLVmcvc5NducxgyOrKXe3EsyHMgBFgSaIUGmArKe+rwr0uphRkRXvwiom3I+fpIfoItveHrfudL8/rxuA==",
"license": "MIT",
"engines": {
"node": ">=16"
}
},
"node_modules/https-proxy-agent": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.2",
"debug": "4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/jwa": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
"integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
"license": "MIT",
"dependencies": {
"buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jws": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
"integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
"license": "MIT",
"dependencies": {
"jwa": "^2.0.1",
"safe-buffer": "^5.0.1"
}
},
"node_modules/minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
"license": "ISC"
},
"node_modules/minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/web-push": {
"version": "3.6.7",
"resolved": "https://registry.npmjs.org/web-push/-/web-push-3.6.7.tgz",
"integrity": "sha512-OpiIUe8cuGjrj3mMBFWY+e4MMIkW3SVT+7vEIjvD9kejGUypv8GPDf84JdPWskK8zMRIJ6xYGm+Kxr8YkPyA0A==",
"license": "MPL-2.0",
"dependencies": {
"asn1.js": "^5.3.0",
"http_ece": "1.2.0",
"https-proxy-agent": "^7.0.0",
"jws": "^4.0.0",
"minimist": "^1.2.5"
},
"bin": {
"web-push": "src/cli.js"
},
"engines": {
"node": ">= 16"
}
}
}
}

View file

@ -1,19 +0,0 @@
{
"name": "movmaker",
"version": "1.0.0",
"description": "Simple Python + ffmpeg movie maker.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://piagent:a8caa8227e2d80f84f4746c90aba3fdafea6d28e@git.novosel.dk/marijo/movmaker.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"web-push": "^3.6.7"
}
}

View file

@ -1,33 +0,0 @@
#!/usr/bin/env node
const fs = require('fs');
const webpush = require('web-push');
function readStdin() {
return new Promise(resolve => {
let data = '';
process.stdin.setEncoding('utf8');
process.stdin.on('data', chunk => data += chunk);
process.stdin.on('end', () => resolve(data));
});
}
(async () => {
const configPath = process.argv[2] || `${process.env.HOME}/.config/mvlog/push.json`;
const payload = process.argv[3] || '{}';
const cfg = JSON.parse(fs.readFileSync(configPath, 'utf8'));
const input = JSON.parse(await readStdin() || '[]');
const subs = Array.isArray(input) ? input : [];
if (!cfg.public_key || !cfg.private_key || !subs.length) return;
webpush.setVapidDetails(cfg.subject || 'mailto:admin@bubulescu.org', cfg.public_key, cfg.private_key);
let sent = 0;
for (const sub of subs) {
try {
await webpush.sendNotification(sub, payload);
sent++;
} catch (err) {
const code = err && err.statusCode ? ` status=${err.statusCode}` : '';
console.error(`push failed${code}: ${err.message || err}`);
}
}
console.log(`push sent: ${sent}/${subs.length}`);
})().catch(err => { console.error(err.stack || err); process.exit(1); });