- Neue Tabelle 'telegram_bots' (bot_id, name, bot_token, webhook_secret, is_public)
- Automatische Migration bestehender Session-Telegram-Configs in telegram_bots
- Sessions verweisen via telegram_bot_id auf Bot (mehrere Sessions pro Bot möglich)
- Webhook-URL: /api/telegram/webhook/{botId} statt {sessionId}
- Eigene Telegram-Bot-Page (wie Agent/Cronjob/Session) statt Modal
- Bot-Page: Name, Token, Secret, Webhook-Verwaltung (registrieren/status/entfernen), Löschen
- Dashboard: Telegram Bots Section mit Cards (Name, maskierter Token, Session-Count)
- Session-Page: Bot-Picker (wie Agent-Picker) statt Token-Input, Chat-ID readonly + Unlink-Button
- Public-Flag: Bot kann von anderen Usern in ihren Sessions ausgewählt werden
- Vereinfacht: 1 Session = max. 1 Telegram Chat, allowed_chat_ids entfällt
- /start zeigt Chat-ID an, /unlink entfernt (Unlink nur über Web-UI)
- Nachrichten-Routing: Bot + Chat-ID → Session Lookup
185 lines
6.6 KiB
JavaScript
185 lines
6.6 KiB
JavaScript
// ── Telegram Bot Page ──
|
|
|
|
registerPage('telegram-bot', {
|
|
async init(params) {
|
|
var isEdit = params && params.id;
|
|
var bot = null;
|
|
|
|
var titleEl = document.getElementById('telegramBotPageTitle');
|
|
var nameInput = document.getElementById('tgBotName');
|
|
var tokenInput = document.getElementById('tgBotToken');
|
|
var secretRow = document.getElementById('tgBotSecretRow');
|
|
var secretInput = document.getElementById('tgBotSecret');
|
|
var copySecretBtn = document.getElementById('tgBotCopySecret');
|
|
var webhookSection = document.getElementById('tgBotWebhookSection');
|
|
var webhookStatus = document.getElementById('tgBotWebhookStatus');
|
|
var webhookRegisterBtn = document.getElementById('tgBotWebhookRegister');
|
|
var webhookInfoBtn = document.getElementById('tgBotWebhookInfo');
|
|
var webhookDeleteBtn = document.getElementById('tgBotWebhookDelete');
|
|
var publicCheckbox = document.getElementById('tgBotPublic');
|
|
var saveBtn = document.getElementById('tgBotSaveBtn');
|
|
var cancelBtn = document.getElementById('tgBotCancelBtn');
|
|
var deleteBtn = document.getElementById('tgBotDeleteBtn');
|
|
|
|
if (isEdit) {
|
|
bot = await apiGetTelegramBot(params.id);
|
|
if (!bot) {
|
|
showToast('Bot nicht gefunden', 'error');
|
|
navigateTo('dashboard');
|
|
return;
|
|
}
|
|
|
|
titleEl.textContent = bot.name || 'Telegram Bot';
|
|
nameInput.value = bot.name || '';
|
|
tokenInput.value = bot.botToken || '';
|
|
publicCheckbox.checked = bot.isPublic || false;
|
|
deleteBtn.hidden = false;
|
|
|
|
// Webhook-Secret anzeigen
|
|
if (bot.webhookSecret) {
|
|
secretRow.hidden = false;
|
|
secretInput.value = bot.webhookSecret;
|
|
}
|
|
|
|
// Webhook-Section anzeigen
|
|
webhookSection.hidden = false;
|
|
_loadWebhookStatus(bot.botId, webhookStatus);
|
|
} else {
|
|
titleEl.textContent = 'Neuer Telegram Bot';
|
|
deleteBtn.hidden = true;
|
|
}
|
|
|
|
// Copy Secret
|
|
copySecretBtn.addEventListener('click', async function() {
|
|
try {
|
|
await navigator.clipboard.writeText(secretInput.value);
|
|
showToast('Kopiert!');
|
|
} catch(e) {
|
|
showToast('Kopieren fehlgeschlagen', 'error');
|
|
}
|
|
});
|
|
|
|
// Webhook registrieren
|
|
webhookRegisterBtn.addEventListener('click', async function() {
|
|
var baseUrl = prompt('Base-URL der App:', window.location.origin);
|
|
if (!baseUrl) return;
|
|
await withButtonLoading(webhookRegisterBtn, 'Registriere...', async function() {
|
|
try {
|
|
var res = await apiTelegramBotRegisterWebhook(bot.botId, baseUrl.trim());
|
|
if (res.ok) {
|
|
showToast('Webhook registriert!', 'success');
|
|
_loadWebhookStatus(bot.botId, webhookStatus);
|
|
} else {
|
|
showToast('Fehler: ' + JSON.stringify(res), 'error');
|
|
}
|
|
} catch(err) {
|
|
showToast('Fehler: ' + err.message, 'error');
|
|
}
|
|
});
|
|
});
|
|
|
|
// Webhook-Status prüfen
|
|
webhookInfoBtn.addEventListener('click', async function() {
|
|
await withButtonLoading(webhookInfoBtn, 'Prüfe...', async function() {
|
|
await _loadWebhookStatus(bot.botId, webhookStatus);
|
|
});
|
|
});
|
|
|
|
// Webhook entfernen
|
|
webhookDeleteBtn.addEventListener('click', async function() {
|
|
if (!confirm('Webhook wirklich entfernen?')) return;
|
|
await withButtonLoading(webhookDeleteBtn, 'Entferne...', async function() {
|
|
try {
|
|
var res = await apiTelegramBotDeleteWebhook(bot.botId);
|
|
if (res.ok) {
|
|
showToast('Webhook entfernt', 'success');
|
|
_loadWebhookStatus(bot.botId, webhookStatus);
|
|
} else {
|
|
showToast('Fehler: ' + JSON.stringify(res), 'error');
|
|
}
|
|
} catch(err) {
|
|
showToast('Fehler: ' + err.message, 'error');
|
|
}
|
|
});
|
|
});
|
|
|
|
// Speichern
|
|
saveBtn.addEventListener('click', async function() {
|
|
var name = nameInput.value.trim();
|
|
var token = tokenInput.value.trim();
|
|
var isPublic = publicCheckbox.checked;
|
|
if (!name || !token) {
|
|
showToast('Name und Bot-Token sind erforderlich', 'error');
|
|
return;
|
|
}
|
|
|
|
await withButtonLoading(saveBtn, 'Speichern...', async function() {
|
|
try {
|
|
if (isEdit) {
|
|
await apiUpdateTelegramBot(bot.botId, name, token, isPublic);
|
|
showToast('Bot gespeichert', 'success');
|
|
// Titel aktualisieren
|
|
titleEl.textContent = name;
|
|
} else {
|
|
var created = await apiCreateTelegramBot(name, token);
|
|
showToast('Bot erstellt', 'success');
|
|
navigateTo('telegram-bot', { id: created.botId });
|
|
}
|
|
} catch(e) {
|
|
showToast('Fehler: ' + e.message, 'error');
|
|
}
|
|
});
|
|
});
|
|
|
|
// Abbrechen
|
|
cancelBtn.addEventListener('click', function() {
|
|
navigateTo('dashboard');
|
|
});
|
|
|
|
// Löschen
|
|
deleteBtn.addEventListener('click', async function() {
|
|
if (!confirm('Bot "' + (bot.name || '') + '" wirklich löschen? Alle Session-Verknüpfungen werden entfernt.')) return;
|
|
try {
|
|
await apiDeleteTelegramBot(bot.botId);
|
|
showToast('Bot gelöscht', 'success');
|
|
navigateTo('dashboard');
|
|
} catch(e) {
|
|
showToast('Fehler: ' + e.message, 'error');
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
async function _loadWebhookStatus(botId, statusEl) {
|
|
try {
|
|
var info = await apiTelegramBotWebhookInfo(botId);
|
|
var result = info.result || {};
|
|
var url = result.url || '';
|
|
var pending = result.pending_update_count || 0;
|
|
var lastError = result.last_error_message || '';
|
|
var lastErrorDate = result.last_error_date ? new Date(result.last_error_date * 1000).toLocaleString('de-AT') : '';
|
|
|
|
var parts = [];
|
|
if (url) {
|
|
parts.push('<span class="status-active"><i class="fa fa-check-circle"></i> Webhook aktiv</span>');
|
|
parts.push('<span><i class="fa fa-link"></i> ' + esc(url) + '</span>');
|
|
} else {
|
|
parts.push('<span class="status-inactive"><i class="fa fa-times-circle"></i> Kein Webhook registriert</span>');
|
|
}
|
|
|
|
if (pending > 0) {
|
|
parts.push('<span><i class="fa fa-clock-o"></i> ' + pending + ' ausstehende Updates</span>');
|
|
}
|
|
|
|
if (lastError) {
|
|
parts.push('<span class="status-error"><i class="fa fa-exclamation-triangle"></i> ' + esc(lastError) + (lastErrorDate ? ' (' + lastErrorDate + ')' : '') + '</span>');
|
|
}
|
|
|
|
statusEl.innerHTML = parts.join('');
|
|
statusEl.hidden = false;
|
|
} catch(e) {
|
|
statusEl.innerHTML = '<span class="status-error"><i class="fa fa-exclamation-triangle"></i> Status konnte nicht geladen werden</span>';
|
|
statusEl.hidden = false;
|
|
}
|
|
}
|