Telegram Bots als eigenständige Entität mit eigener Page
- 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
This commit is contained in:
1 parent
3b7bdb7a20
commit
ec73ccd71e
13 files changed
+907
-371
No files matched your search
+68
-15
@@ -284,29 +284,61 @@ async function apiChangePassword(currentPassword, newPassword) {
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
// ── Telegram API (pro Session) ──
|
||||
// ── Telegram Bot API ──
|
||||
|
||||
async function apiSessionTelegramGet(sessionId) {
|
||||
const resp = await fetch(`/api/sessions/${sessionId}/telegram`);
|
||||
if (!resp.ok) return { configured: false };
|
||||
async function apiGetTelegramBots() {
|
||||
const resp = await fetch('/api/telegram/bots');
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
async function apiSessionTelegramSave(sessionId, botToken, webhookSecret, allowedChatIds) {
|
||||
const resp = await fetch(`/api/sessions/${sessionId}/telegram`, {
|
||||
method: 'PUT',
|
||||
async function apiGetTelegramBot(botId) {
|
||||
const resp = await fetch(`/api/telegram/bots/${botId}`);
|
||||
if (!resp.ok) return null;
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
async function apiCreateTelegramBot(name, botToken) {
|
||||
const resp = await fetch('/api/telegram/bots', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ botToken, webhookSecret, allowedChatIds })
|
||||
body: JSON.stringify({ name, botToken })
|
||||
});
|
||||
if (!resp.ok) {
|
||||
const err = await resp.json().catch(() => ({}));
|
||||
throw new Error(err.error || 'Telegram-Config speichern fehlgeschlagen');
|
||||
throw new Error(err.error || 'Bot erstellen fehlgeschlagen');
|
||||
}
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
async function apiSessionTelegramRegisterWebhook(sessionId, baseUrl) {
|
||||
const resp = await fetch(`/api/sessions/${sessionId}/telegram/register-webhook`, {
|
||||
async function apiGetAvailableTelegramBots() {
|
||||
const resp = await fetch('/api/telegram/bots/available');
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
async function apiUpdateTelegramBot(botId, name, botToken, isPublic) {
|
||||
const resp = await fetch(`/api/telegram/bots/${botId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name, botToken, isPublic })
|
||||
});
|
||||
if (!resp.ok) {
|
||||
const err = await resp.json().catch(() => ({}));
|
||||
throw new Error(err.error || 'Bot speichern fehlgeschlagen');
|
||||
}
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
async function apiDeleteTelegramBot(botId) {
|
||||
const resp = await fetch(`/api/telegram/bots/${botId}`, { method: 'DELETE' });
|
||||
if (!resp.ok) {
|
||||
const err = await resp.json().catch(() => ({}));
|
||||
throw new Error(err.error || 'Bot löschen fehlgeschlagen');
|
||||
}
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
async function apiTelegramBotRegisterWebhook(botId, baseUrl) {
|
||||
const resp = await fetch(`/api/telegram/bots/${botId}/register-webhook`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ baseUrl })
|
||||
@@ -315,18 +347,39 @@ async function apiSessionTelegramRegisterWebhook(sessionId, baseUrl) {
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
async function apiSessionTelegramWebhookInfo(sessionId) {
|
||||
const resp = await fetch(`/api/sessions/${sessionId}/telegram/webhook-info`);
|
||||
async function apiTelegramBotWebhookInfo(botId) {
|
||||
const resp = await fetch(`/api/telegram/bots/${botId}/webhook-info`);
|
||||
if (!resp.ok) throw new Error('Webhook-Info fehlgeschlagen');
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
async function apiSessionTelegramDeleteWebhook(sessionId) {
|
||||
const resp = await fetch(`/api/sessions/${sessionId}/telegram/webhook`, { method: 'DELETE' });
|
||||
async function apiTelegramBotDeleteWebhook(botId) {
|
||||
const resp = await fetch(`/api/telegram/bots/${botId}/webhook`, { method: 'DELETE' });
|
||||
if (!resp.ok) throw new Error('Webhook-Löschung fehlgeschlagen');
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
// ── Session Telegram Config ──
|
||||
|
||||
async function apiSessionTelegramGet(sessionId) {
|
||||
const resp = await fetch(`/api/sessions/${sessionId}/telegram`);
|
||||
if (!resp.ok) return { configured: false };
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
async function apiSessionTelegramSave(sessionId, telegramBotId, chatId) {
|
||||
const resp = await fetch(`/api/sessions/${sessionId}/telegram`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ telegramBotId, chatId })
|
||||
});
|
||||
if (!resp.ok) {
|
||||
const err = await resp.json().catch(() => ({}));
|
||||
throw new Error(err.error || 'Telegram-Config speichern fehlgeschlagen');
|
||||
}
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
async function apiGetSettings() {
|
||||
const resp = await fetch('/api/settings');
|
||||
if (!resp.ok) return {};
|
||||
|
||||
@@ -46,6 +46,47 @@ function buildSessionCard(session, agent) {
|
||||
}
|
||||
|
||||
|
||||
// ── Telegram Bot Card Helper ──
|
||||
|
||||
function buildTelegramBotCard(bot) {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'card card-compact';
|
||||
|
||||
const badges = [];
|
||||
if (bot.isPublic) {
|
||||
badges.push('<span class="badge badge-feature"><i class="fa fa-globe"></i> Public</span>');
|
||||
}
|
||||
if (bot.isOwner === false) {
|
||||
badges.push('<span class="badge badge-off"><i class="fa fa-user"></i> Fremd</span>');
|
||||
}
|
||||
if (bot.sessionCount > 0) {
|
||||
badges.push(`<span class="badge badge-feature"><i class="fa fa-comment"></i> ${bot.sessionCount} ${bot.sessionCount === 1 ? 'Session' : 'Sessions'}</span>`);
|
||||
}
|
||||
|
||||
// Meta-Items nur anzeigen wenn Daten vorhanden
|
||||
const metaParts = [];
|
||||
if (bot.botToken) {
|
||||
const maskedToken = '•••' + bot.botToken.slice(-4);
|
||||
metaParts.push(`<span class="card-meta-item"><i class="fa fa-key"></i> ${esc(maskedToken)}</span>`);
|
||||
}
|
||||
if (bot.createdAt) {
|
||||
metaParts.push(`<span class="card-meta-item"><i class="fa fa-clock-o"></i> ${formatDate(bot.createdAt)}</span>`);
|
||||
}
|
||||
|
||||
card.innerHTML = `
|
||||
<div class="card-body">
|
||||
<div class="card-title-row">
|
||||
<span class="card-title"><i class="fa fa-paper-plane"></i> ${esc(bot.name)}</span>
|
||||
${badges.join('')}
|
||||
</div>
|
||||
${metaParts.length ? `<div class="card-meta">${metaParts.join('')}</div>` : ''}
|
||||
</div>
|
||||
`;
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
|
||||
// ── Agent Card Helper ──
|
||||
// Erzeugt ein .card-Element für einen Agent (wiederverwendbar für Dashboard + Picker).
|
||||
|
||||
|
||||
@@ -172,6 +172,20 @@ function _openPickerModal(title, items, currentId, onSelect, options) {
|
||||
});
|
||||
}
|
||||
|
||||
// ── Telegram Bot Picker Modal ──
|
||||
|
||||
function openTelegramBotPickerModal(bots, currentBotId, onSelect) {
|
||||
var items = bots.map(function(b) {
|
||||
b._pickerId = b.botId;
|
||||
return b;
|
||||
});
|
||||
_openPickerModal('Telegram Bot auswählen', items, currentBotId, onSelect, {
|
||||
noneLabel: 'Kein Bot',
|
||||
noneIcon: 'fa-paper-plane',
|
||||
buildCard: function(b) { return buildTelegramBotCard(b); }
|
||||
});
|
||||
}
|
||||
|
||||
// ── OpenClaw Import Modal ──
|
||||
|
||||
async function showOpenClawImportModal(sessionId) {
|
||||
|
||||
@@ -35,8 +35,8 @@ registerPage('dashboard', {
|
||||
|
||||
// Telegram-Config parallel pro Session laden (sessions werden gleich geladen)
|
||||
|
||||
const [agents, sessions, cronjobs, shares] = await Promise.all([
|
||||
apiGetAgents(), apiGetSessions(), apiGetCronjobs(), apiListShares()
|
||||
const [agents, sessions, cronjobs, shares, telegramBots] = await Promise.all([
|
||||
apiGetAgents(), apiGetSessions(), apiGetCronjobs(), apiListShares(), apiGetTelegramBots()
|
||||
]);
|
||||
const agentMap = {};
|
||||
for (const a of agents) agentMap[a.agentId] = a;
|
||||
@@ -253,6 +253,24 @@ registerPage('dashboard', {
|
||||
// Neuer Cronjob Button
|
||||
document.getElementById('newCronjobBtn').addEventListener('click', () => navigateTo('cronjob'));
|
||||
|
||||
// Telegram Bots
|
||||
const tgGrid = document.getElementById('telegramBotCards');
|
||||
tgGrid.innerHTML = '';
|
||||
|
||||
for (const bot of telegramBots) {
|
||||
const card = buildTelegramBotCard(bot);
|
||||
|
||||
// Card klickbar → direkt zur Edit-Seite
|
||||
card.classList.add('clickable');
|
||||
card.addEventListener('click', () => navigateTo('telegram-bot', { id: bot.botId }));
|
||||
|
||||
tgGrid.appendChild(card);
|
||||
}
|
||||
|
||||
document.getElementById('newTelegramBotBtn').addEventListener('click', () => {
|
||||
navigateTo('telegram-bot');
|
||||
});
|
||||
|
||||
// Shared Links
|
||||
const sharedSection = document.getElementById('sharedLinksSection');
|
||||
const sharedGrid = document.getElementById('sharedLinksCards');
|
||||
|
||||
@@ -71,7 +71,7 @@ registerPage('session', {
|
||||
|
||||
// Telegram-Section nur für existierende Sessions
|
||||
if (!isNew) {
|
||||
initSessionTelegram(sessionId);
|
||||
initSessionTelegram(sessionId, session);
|
||||
}
|
||||
|
||||
// Agents laden + Skills parallel
|
||||
@@ -175,16 +175,14 @@ registerPage('session', {
|
||||
await apiCreateSession(data);
|
||||
} else {
|
||||
await apiUpdateSession(sessionId, data);
|
||||
// Telegram-Config mitspeichern (falls Section sichtbar)
|
||||
var tgToken = document.getElementById('sessionTelegramToken');
|
||||
var tgSecret = document.getElementById('sessionTelegramSecret');
|
||||
if (tgToken) {
|
||||
try {
|
||||
await saveTelegramConfig(sessionId, tgToken, tgSecret);
|
||||
} catch(e) {
|
||||
showToast('Session gespeichert, aber Telegram-Fehler: ' + e.message, 'error');
|
||||
return;
|
||||
}
|
||||
// Telegram-Config mitspeichern
|
||||
try {
|
||||
var tgBotId = document.getElementById('telegramBotSelect').value || '';
|
||||
var tgChatId = document.getElementById('sessionTelegramChatId').value.trim();
|
||||
await apiSessionTelegramSave(sessionId, tgBotId, tgChatId);
|
||||
} catch(e) {
|
||||
showToast('Session gespeichert, aber Telegram-Fehler: ' + e.message, 'error');
|
||||
return;
|
||||
}
|
||||
}
|
||||
navigateTo('dashboard');
|
||||
@@ -223,121 +221,59 @@ function openAgentPickerModal(agents, agentSkillsMap, currentId, onSelect) {
|
||||
});
|
||||
}
|
||||
|
||||
function initSessionTelegram(sessionId) {
|
||||
var tokenInput = document.getElementById('sessionTelegramToken');
|
||||
var secretInput = document.getElementById('sessionTelegramSecret');
|
||||
var allowedInput = document.getElementById('sessionTelegramAllowed');
|
||||
var registerBtn = document.getElementById('sessionTelegramRegisterBtn');
|
||||
var deleteBtn = document.getElementById('sessionTelegramDeleteBtn');
|
||||
var statusBox = document.getElementById('sessionTelegramStatusBox');
|
||||
function initSessionTelegram(sessionId, session) {
|
||||
var botSelectCard = document.getElementById('telegramBotSelectCard');
|
||||
var botSelect = document.getElementById('telegramBotSelect');
|
||||
var chatIdInput = document.getElementById('sessionTelegramChatId');
|
||||
var unlinkBtn = document.getElementById('sessionTelegramUnlink');
|
||||
|
||||
// Vorhandene Config laden + Status abrufen
|
||||
apiSessionTelegramGet(sessionId).then(async function(config) {
|
||||
if (config.botToken) tokenInput.value = config.botToken;
|
||||
if (config.allowedChatIds) allowedInput.value = config.allowedChatIds;
|
||||
if (config.webhookSecret) {
|
||||
secretInput.value = config.webhookSecret;
|
||||
} else {
|
||||
// Secret einmalig generieren und sofort persistent speichern
|
||||
var newSecret = crypto.randomUUID().replace(/-/g, '');
|
||||
secretInput.value = newSecret;
|
||||
await apiSessionTelegramSave(sessionId, config.botToken || '', newSecret);
|
||||
}
|
||||
// Status automatisch abrufen wenn Token konfiguriert ist
|
||||
if (config.botToken) {
|
||||
refreshTelegramStatus(sessionId, statusBox, registerBtn, deleteBtn);
|
||||
} else {
|
||||
showTelegramUnconfigured(statusBox, registerBtn, deleteBtn);
|
||||
}
|
||||
// Unlink-Button
|
||||
unlinkBtn.addEventListener('click', function() {
|
||||
if (!chatIdInput.value) return;
|
||||
if (!confirm('Telegram-Verknüpfung wirklich lösen?')) return;
|
||||
chatIdInput.value = '';
|
||||
showToast('Chat-ID entfernt. Speichern nicht vergessen.', 'info');
|
||||
});
|
||||
|
||||
// Config laden
|
||||
apiSessionTelegramGet(sessionId).then(function(config) {
|
||||
if (config.chatId) chatIdInput.value = config.chatId;
|
||||
if (config.telegramBotId) botSelect.value = config.telegramBotId;
|
||||
|
||||
// Bot-Picker initialisieren
|
||||
initTelegramBotPicker(botSelectCard, botSelect, config.telegramBotId);
|
||||
}).catch(function() {
|
||||
showTelegramUnconfigured(statusBox, registerBtn, deleteBtn);
|
||||
});
|
||||
|
||||
// Webhook registrieren
|
||||
registerBtn.addEventListener('click', async function() {
|
||||
var baseUrl = prompt('Base-URL der App:', window.location.origin);
|
||||
if (!baseUrl) return;
|
||||
await withButtonLoading(registerBtn, 'Wird registriert...', async () => {
|
||||
try {
|
||||
await saveTelegramConfig(sessionId, tokenInput, secretInput);
|
||||
var res = await apiSessionTelegramRegisterWebhook(sessionId, baseUrl.trim());
|
||||
if (res.ok) {
|
||||
showToast('Webhook registriert!', 'success');
|
||||
} else {
|
||||
showToast('Antwort: ' + JSON.stringify(res), 'error');
|
||||
}
|
||||
} catch(e) {
|
||||
showToast('Fehler: ' + e.message, 'error');
|
||||
}
|
||||
});
|
||||
refreshTelegramStatus(sessionId, statusBox, registerBtn, deleteBtn);
|
||||
});
|
||||
|
||||
// Webhook entfernen
|
||||
deleteBtn.addEventListener('click', async function() {
|
||||
if (!confirm('Webhook wirklich entfernen?')) return;
|
||||
await withButtonLoading(deleteBtn, 'Wird entfernt...', async () => {
|
||||
try {
|
||||
var res = await apiSessionTelegramDeleteWebhook(sessionId);
|
||||
if (res.ok) {
|
||||
showToast('Webhook entfernt', 'success');
|
||||
} else {
|
||||
showToast('Antwort: ' + JSON.stringify(res), 'error');
|
||||
}
|
||||
} catch(e) {
|
||||
showToast('Fehler: ' + e.message, 'error');
|
||||
}
|
||||
});
|
||||
refreshTelegramStatus(sessionId, statusBox, registerBtn, deleteBtn);
|
||||
initTelegramBotPicker(botSelectCard, botSelect, null);
|
||||
});
|
||||
}
|
||||
|
||||
function showTelegramUnconfigured(statusBox, registerBtn, deleteBtn) {
|
||||
statusBox.innerHTML = '<p>⚠️ Kein Bot-Token konfiguriert. Speichere zuerst die Session mit einem Token.</p>';
|
||||
statusBox.hidden = false;
|
||||
registerBtn.hidden = true;
|
||||
deleteBtn.hidden = true;
|
||||
}
|
||||
|
||||
async function refreshTelegramStatus(sessionId, statusBox, registerBtn, deleteBtn) {
|
||||
statusBox.hidden = true;
|
||||
async function initTelegramBotPicker(cardEl, selectEl, currentBotId) {
|
||||
var bots = [];
|
||||
try {
|
||||
var info = await apiSessionTelegramWebhookInfo(sessionId);
|
||||
var result = info.result || {};
|
||||
var url = result.url || '';
|
||||
var pending = result.pending_update_count || 0;
|
||||
var lastError = result.last_error_message;
|
||||
var active = !!url;
|
||||
var result = await apiGetAvailableTelegramBots();
|
||||
if (Array.isArray(result)) bots = result;
|
||||
} catch(e) { /* ignore */ }
|
||||
var botMap = {};
|
||||
for (var i = 0; i < bots.length; i++) botMap[bots[i].botId] = bots[i];
|
||||
|
||||
var html = '';
|
||||
if (active) {
|
||||
html += '<p>✅ <strong>Webhook aktiv</strong></p>';
|
||||
html += '<p><strong>URL:</strong> ' + esc(url) + '</p>';
|
||||
html += '<p><strong>Ausstehend:</strong> ' + pending + '</p>';
|
||||
if (lastError) html += '<p class="tg-error"><strong>Letzter Fehler:</strong> ' + esc(lastError) + '</p>';
|
||||
} else {
|
||||
html += '<p>⚠️ <strong>Webhook nicht registriert</strong></p>';
|
||||
}
|
||||
statusBox.innerHTML = html;
|
||||
statusBox.hidden = false;
|
||||
|
||||
// Buttons ein/ausblenden je nach Status
|
||||
registerBtn.hidden = active;
|
||||
deleteBtn.hidden = !active;
|
||||
} catch(e) {
|
||||
statusBox.innerHTML = '<p class="tg-error">Status konnte nicht abgerufen werden: ' + esc(e.message) + '</p>';
|
||||
statusBox.hidden = false;
|
||||
registerBtn.hidden = false;
|
||||
deleteBtn.hidden = true;
|
||||
function renderBotInCard(bot) {
|
||||
var inner = bot ? buildTelegramBotCard(bot) : null;
|
||||
_renderCardPreview(cardEl, inner, 'fa-paper-plane', 'Kein Bot zugewiesen', 'tg-bot-select-change');
|
||||
}
|
||||
}
|
||||
|
||||
async function saveTelegramConfig(sessionId, tokenInput, secretInput) {
|
||||
var token = tokenInput.value.trim();
|
||||
var secret = secretInput.value.trim();
|
||||
var allowedInput = document.getElementById('sessionTelegramAllowed');
|
||||
var allowed = allowedInput ? allowedInput.value.trim() : '';
|
||||
await apiSessionTelegramSave(sessionId, token, secret, allowed);
|
||||
if (currentBotId && botMap[currentBotId]) {
|
||||
selectEl.value = currentBotId;
|
||||
renderBotInCard(botMap[currentBotId]);
|
||||
} else {
|
||||
renderBotInCard(null);
|
||||
}
|
||||
|
||||
cardEl.addEventListener('click', function() {
|
||||
openTelegramBotPickerModal(bots, selectEl.value, function(selectedBotId) {
|
||||
selectEl.value = selectedBotId || '';
|
||||
renderBotInCard(selectedBotId ? botMap[selectedBotId] : null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
// ── 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;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user