feat: Add manual trigger bypass for web UI autonomous engagement

- Added manual_trigger parameter to /autonomous/engage endpoint to bypass 12h cooldown
- Updated miku_engage_random_user_for_server() and miku_engage_random_user() to accept manual_trigger flag
- Modified Web UI to always send manual_trigger=true when engaging users from the UI
- Users can now manually engage the same user multiple times from web UI without cooldown restriction
- Regular autonomous schedules still respect the 12h cooldown between engagements to the same user

Changes:
- bot/api.py: Added manual_trigger parameter with string-to-boolean conversion
- bot/static/index.html: Added manual_trigger=true to engage user request
- bot/utils/autonomous_v1_legacy.py: Added manual_trigger parameter and cooldown bypass logic
This commit is contained in:
2026-02-20 00:53:42 +02:00
parent 9972edb06d
commit 2f0d430c35
3 changed files with 277 additions and 30 deletions

View File

@@ -807,7 +807,17 @@
</div>
</div>
<button onclick="triggerAutonomous('tweet')">Share Tweet</button>
<!-- Share Tweet Submenu -->
<div style="margin-bottom: 1rem;">
<button onclick="toggleTweetSubmenu()">Share Tweet ▼</button>
<div id="tweet-submenu" style="display: none; margin-left: 1rem; margin-top: 0.5rem; padding: 1rem; background: #1e1e1e; border: 1px solid #444; border-radius: 4px;">
<div style="margin-bottom: 0.5rem;">
<label for="tweet-url" style="display: block; margin-bottom: 0.3rem;">Tweet URL (leave empty for auto-fetch):</label>
<input type="text" id="tweet-url" placeholder="https://x.com/... or https://twitter.com/... or https://fxtwitter.com/..." style="width: 100%;">
</div>
<button onclick="triggerShareTweet()">🐦 Share Tweet</button>
</div>
</div>
<button onclick="triggerAutonomous('reaction')">React to Message</button>
<button onclick="triggerAutonomous('join-conversation')">Detect and Join Conversation</button>
<button onclick="toggleCustomPrompt()">Custom Prompt</button>
@@ -3051,6 +3061,9 @@ async function triggerEngageUser() {
params.append('engagement_type', engageType);
}
// Add manual_trigger flag to bypass cooldown checks
params.append('manual_trigger', 'true');
if (params.toString()) {
endpoint += `?${params.toString()}`;
}
@@ -3075,6 +3088,76 @@ async function triggerEngageUser() {
}
}
// Toggle Share Tweet Submenu
function toggleTweetSubmenu() {
const submenu = document.getElementById('tweet-submenu');
if (submenu.style.display === 'none') {
submenu.style.display = 'block';
} else {
submenu.style.display = 'none';
}
}
// Trigger Share Tweet with optional URL
async function triggerShareTweet() {
const selectedServer = document.getElementById('server-select').value;
const tweetUrl = document.getElementById('tweet-url').value.trim();
// Validate URL if provided
if (tweetUrl) {
const validDomains = ['x.com', 'twitter.com', 'fxtwitter.com'];
let isValid = false;
try {
const urlObj = new URL(tweetUrl);
const hostname = urlObj.hostname.toLowerCase();
isValid = validDomains.some(domain => hostname === domain || hostname.endsWith('.' + domain));
} catch (e) {
// Invalid URL format
}
if (!isValid) {
showNotification('Invalid tweet URL. Must be from x.com, twitter.com, or fxtwitter.com', 'error');
return;
}
}
try {
let endpoint = '/autonomous/tweet';
const params = new URLSearchParams();
// Add guild_id if a specific server is selected
if (selectedServer !== 'all') {
params.append('guild_id', selectedServer);
}
// Add tweet_url if specified
if (tweetUrl) {
params.append('tweet_url', tweetUrl);
}
if (params.toString()) {
endpoint += `?${params.toString()}`;
}
const response = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
if (response.ok) {
showNotification(result.message || 'Tweet share triggered successfully');
} else {
throw new Error(result.message || 'Failed to trigger tweet share');
}
} catch (error) {
console.error('Failed to trigger tweet share:', error);
showNotification(error.message || 'Failed to trigger tweet share', 'error');
}
}
// Profile Picture Management
async function changeProfilePicture() {
const selectedServer = document.getElementById('server-select').value;