forked from laantungir/super_ball
create daemon
This commit is contained in:
@@ -343,6 +343,7 @@
|
||||
privacyPolicy: '',
|
||||
termsOfService: '',
|
||||
refreshRate: 60, // default 60 seconds
|
||||
maxDelay: 86460, // default 1 day + 60 seconds maximum delay
|
||||
content: event.content || ''
|
||||
};
|
||||
|
||||
@@ -386,6 +387,9 @@
|
||||
case 'refresh_rate':
|
||||
thrower.refreshRate = parseInt(tag[1]) || 60;
|
||||
break;
|
||||
case 'max_delay':
|
||||
thrower.maxDelay = parseInt(tag[1]) || 86460;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -571,6 +575,10 @@
|
||||
<span><strong>Refresh Rate:</strong></span>
|
||||
<span>${thrower.refreshRate}s</span>
|
||||
</div>
|
||||
<div class="thrower-detail">
|
||||
<span><strong>Max Delay:</strong></span>
|
||||
<span>${thrower.maxDelay}s</span>
|
||||
</div>
|
||||
<div class="thrower-detail">
|
||||
<span><strong>Last Update:</strong></span>
|
||||
<span>${lastSeen}</span>
|
||||
@@ -816,6 +824,8 @@
|
||||
|
||||
// Clear relay dropdown until manual input is provided
|
||||
clearRelayDropdown(bounceId);
|
||||
// Reset delay constraints for manual input
|
||||
updateDelayConstraints(bounceId, null);
|
||||
} else if (select.value) {
|
||||
// Hide manual input and use selected thrower
|
||||
manualDiv.classList.add('hidden');
|
||||
@@ -824,11 +834,15 @@
|
||||
|
||||
// Populate relay dropdown based on selected thrower
|
||||
populateRelayDropdown(bounceId, select.value);
|
||||
// Update delay constraints based on selected thrower
|
||||
updateDelayConstraints(bounceId, select.value);
|
||||
} else {
|
||||
// No selection - hide manual input and clear relay dropdown
|
||||
manualDiv.classList.add('hidden');
|
||||
input.value = '';
|
||||
clearRelayDropdown(bounceId);
|
||||
// Reset delay constraints
|
||||
updateDelayConstraints(bounceId, null);
|
||||
}
|
||||
|
||||
// Check if bounce inputs are valid and update button state
|
||||
@@ -882,6 +896,7 @@
|
||||
pubkey = window.NostrTools.nip19.decode(pubkey).data;
|
||||
} catch (error) {
|
||||
clearRelayDropdown(bounceId);
|
||||
updateDelayConstraints(bounceId, null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -889,11 +904,14 @@
|
||||
// Find thrower in discovered list and populate relays
|
||||
if (pubkey && /^[0-9a-fA-F]{64}$/.test(pubkey)) {
|
||||
populateRelayDropdown(bounceId, pubkey);
|
||||
updateDelayConstraints(bounceId, pubkey);
|
||||
} else {
|
||||
clearRelayDropdown(bounceId);
|
||||
updateDelayConstraints(bounceId, null);
|
||||
}
|
||||
} else {
|
||||
clearRelayDropdown(bounceId);
|
||||
updateDelayConstraints(bounceId, null);
|
||||
}
|
||||
|
||||
// Update button state after thrower input change
|
||||
@@ -1099,6 +1117,41 @@
|
||||
return relayUrls.join(', ');
|
||||
}
|
||||
|
||||
// Update delay input constraints based on selected thrower's maximum delay
|
||||
function updateDelayConstraints(bounceId, throwerPubkey) {
|
||||
const delayInput = document.getElementById(`delay-${bounceId}`);
|
||||
if (!delayInput) return;
|
||||
|
||||
if (!throwerPubkey) {
|
||||
// No thrower selected - reset to default constraints
|
||||
delayInput.max = '';
|
||||
delayInput.title = 'Enter delay in seconds (minimum 1 second)';
|
||||
console.log('INFO', `Reset delay constraints for bounce ${bounceId} - no thrower selected`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the thrower and get its maximum delay
|
||||
const thrower = discoveredThrowers.find(t => t.pubkey === throwerPubkey);
|
||||
if (thrower && thrower.maxDelay) {
|
||||
delayInput.max = thrower.maxDelay;
|
||||
delayInput.title = `Enter delay in seconds (minimum 1, maximum ${thrower.maxDelay} for this thrower)`;
|
||||
|
||||
// If current value exceeds max, reset to max
|
||||
const currentValue = parseInt(delayInput.value);
|
||||
if (currentValue > thrower.maxDelay) {
|
||||
delayInput.value = thrower.maxDelay;
|
||||
console.log('INFO', `Reduced delay from ${currentValue}s to ${thrower.maxDelay}s (thrower maximum) for bounce ${bounceId}`);
|
||||
}
|
||||
|
||||
console.log('INFO', `Set maximum delay constraint to ${thrower.maxDelay}s for bounce ${bounceId} (thrower: ${thrower.name})`);
|
||||
} else {
|
||||
// Thrower found but no max delay info - reset constraints
|
||||
delayInput.max = '';
|
||||
delayInput.title = 'Enter delay in seconds (minimum 1 second) - thrower maximum delay unknown';
|
||||
console.log('INFO', `No maximum delay info available for bounce ${bounceId} thrower`);
|
||||
}
|
||||
}
|
||||
|
||||
// Decrypt and display bounce content for testing
|
||||
function decryptBounce(bounceId) {
|
||||
try {
|
||||
@@ -1308,6 +1361,13 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate delay against thrower's maximum delay
|
||||
const thrower = discoveredThrowers.find(t => t.pubkey === throwerPubkey);
|
||||
if (thrower && thrower.maxDelay && delay > thrower.maxDelay) {
|
||||
alert(`Delay of ${delay}s exceeds this thrower's maximum delay of ${thrower.maxDelay}s. Please reduce the delay.`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Determine what event to wrap
|
||||
let eventToWrap;
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
<div><strong>Info Status:</strong> <span id="thrower-info-status">Loading...</span></div>
|
||||
<div><strong>Last Updated:</strong> <span id="thrower-info-updated">Never</span></div>
|
||||
<div><strong>Refresh Rate:</strong> <span id="thrower-info-refresh">300 seconds</span></div>
|
||||
<div><strong>Maximum Delay:</strong> <span id="thrower-max-delay">86460 seconds</span></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -153,6 +154,10 @@
|
||||
<label for="edit-refresh-rate">Refresh Rate (seconds):</label>
|
||||
<input type="number" id="edit-refresh-rate" placeholder="300" value="300" min="10" max="3600">
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="edit-max-delay">Maximum Delay (seconds):</label>
|
||||
<input type="number" id="edit-max-delay" placeholder="86460" value="86460" min="1" max="86460">
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="edit-thrower-content">Additional Content (optional):</label>
|
||||
<textarea id="edit-thrower-content" rows="2"
|
||||
@@ -1128,6 +1133,7 @@
|
||||
privacyPolicy: '',
|
||||
termsOfService: '',
|
||||
refreshRate: 300,
|
||||
maxDelay: 86460,
|
||||
content: event.content || ''
|
||||
};
|
||||
|
||||
@@ -1145,6 +1151,7 @@
|
||||
else if (tag[0] === 'privacy_policy') currentThrowerInfo.privacyPolicy = tag[1] || '';
|
||||
else if (tag[0] === 'terms_of_service') currentThrowerInfo.termsOfService = tag[1] || '';
|
||||
else if (tag[0] === 'refresh_rate') currentThrowerInfo.refreshRate = parseInt(tag[1]) || 300;
|
||||
else if (tag[0] === 'max_delay') currentThrowerInfo.maxDelay = parseInt(tag[1]) || 86460;
|
||||
});
|
||||
|
||||
lastThrowerInfoPublish = event.created_at;
|
||||
@@ -1164,6 +1171,7 @@
|
||||
privacyPolicy: '',
|
||||
termsOfService: '',
|
||||
refreshRate: 300,
|
||||
maxDelay: 86460,
|
||||
content: ''
|
||||
};
|
||||
displayThrowerInfo(currentThrowerInfo);
|
||||
@@ -1179,6 +1187,7 @@
|
||||
function displayThrowerInfo(info) {
|
||||
document.getElementById('thrower-info-status').textContent = 'Loaded';
|
||||
document.getElementById('thrower-info-refresh').textContent = `${info.refreshRate} seconds`;
|
||||
document.getElementById('thrower-max-delay').textContent = `${info.maxDelay} seconds`;
|
||||
|
||||
if (lastThrowerInfoPublish) {
|
||||
const lastUpdate = new Date(lastThrowerInfoPublish * 1000);
|
||||
@@ -1209,6 +1218,7 @@
|
||||
document.getElementById('edit-privacy-policy').value = currentThrowerInfo.privacyPolicy || '';
|
||||
document.getElementById('edit-terms-service').value = currentThrowerInfo.termsOfService || '';
|
||||
document.getElementById('edit-refresh-rate').value = currentThrowerInfo.refreshRate || 300;
|
||||
document.getElementById('edit-max-delay').value = currentThrowerInfo.maxDelay || 86460;
|
||||
document.getElementById('edit-thrower-content').value = currentThrowerInfo.content || '';
|
||||
}
|
||||
|
||||
@@ -1233,6 +1243,7 @@
|
||||
const privacyPolicy = document.getElementById('edit-privacy-policy').value.trim();
|
||||
const termsOfService = document.getElementById('edit-terms-service').value.trim();
|
||||
const refreshRate = parseInt(document.getElementById('edit-refresh-rate').value) || 300;
|
||||
const maxDelay = parseInt(document.getElementById('edit-max-delay').value) || 86460;
|
||||
const content = document.getElementById('edit-thrower-content').value.trim();
|
||||
|
||||
try {
|
||||
@@ -1251,6 +1262,7 @@
|
||||
if (privacyPolicy) tags.push(['privacy_policy', privacyPolicy]);
|
||||
if (termsOfService) tags.push(['terms_of_service', termsOfService]);
|
||||
tags.push(['refresh_rate', refreshRate.toString()]);
|
||||
tags.push(['max_delay', maxDelay.toString()]);
|
||||
|
||||
const eventTemplate = {
|
||||
kind: 12222,
|
||||
@@ -1319,6 +1331,7 @@
|
||||
privacyPolicy,
|
||||
termsOfService,
|
||||
refreshRate,
|
||||
maxDelay,
|
||||
content
|
||||
};
|
||||
|
||||
@@ -1401,6 +1414,7 @@
|
||||
if (currentThrowerInfo.privacyPolicy) tags.push(['privacy_policy', currentThrowerInfo.privacyPolicy]);
|
||||
if (currentThrowerInfo.termsOfService) tags.push(['terms_of_service', currentThrowerInfo.termsOfService]);
|
||||
tags.push(['refresh_rate', currentThrowerInfo.refreshRate.toString()]);
|
||||
tags.push(['max_delay', currentThrowerInfo.maxDelay.toString()]);
|
||||
|
||||
const eventTemplate = {
|
||||
kind: 12222,
|
||||
@@ -1838,6 +1852,14 @@
|
||||
if (!Array.isArray(routing.relays) || routing.relays.length === 0) return false;
|
||||
if (typeof routing.delay !== 'number' || routing.delay < 0) return false;
|
||||
if (!routing.audit || typeof routing.audit !== 'string') return false;
|
||||
|
||||
// Check maximum delay constraint
|
||||
const maxDelay = currentThrowerInfo.maxDelay || 86460;
|
||||
if (routing.delay > maxDelay) {
|
||||
addLogEntry('error', `Routing delay ${routing.delay}s exceeds maximum allowed delay ${maxDelay}s - rejecting event`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user