feat(zugaenge): X-Zugang und Telegram-Zugang als gleichwertige Dienst-Karten
Beide Dienste erscheinen als Karte mit Lucide-Icon im Titel (X-Kreuz, Telegram-Papierflieger) und derselben Tabellenstruktur (Benutzername, E-Mail bzw. Telefon, Status, Anfragen, Letzte Nutzung/Pruefung, Aktionen). Die nackte Konten-Zaehlung entfaellt, die X-Knoepfe ziehen in den Kartenkopf. Telegram-Zeile zeigt Konto, Telefonnummer (Monitor-Commit 5450fd2), Status und letzte Pruefung. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -358,19 +358,13 @@
|
|||||||
<!-- Recherche-Zugänge (Sub-Tab): X-Konten + Telegram-Session-Status -->
|
<!-- Recherche-Zugänge (Sub-Tab): X-Konten + Telegram-Session-Status -->
|
||||||
<div class="section" id="sub-x-scraper">
|
<div class="section" id="sub-x-scraper">
|
||||||
<div class="card" style="margin-bottom:16px;">
|
<div class="card" style="margin-bottom:16px;">
|
||||||
<div class="card-header"><h2>Telegram-Zugang</h2></div>
|
<div class="card-header">
|
||||||
<div class="card-body" id="telegramStatusBox">Lade…</div>
|
<h2><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="vertical-align:-2px;margin-right:6px;"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>X-Zugang</h2>
|
||||||
</div>
|
|
||||||
<div class="action-bar">
|
|
||||||
<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap;">
|
|
||||||
<span class="text-secondary" id="xScraperCount"></span>
|
|
||||||
</div>
|
|
||||||
<div style="display:flex;gap:8px;">
|
<div style="display:flex;gap:8px;">
|
||||||
<button class="btn btn-secondary" onclick="resetXScraperLocks()">Sperren zurücksetzen</button>
|
<button class="btn btn-secondary btn-small" onclick="resetXScraperLocks()">Sperren zurücksetzen</button>
|
||||||
<button class="btn btn-primary" onclick="openXScraperAddModal()">+ Konto hinzufügen</button>
|
<button class="btn btn-primary btn-small" onclick="openXScraperAddModal()">+ Konto hinzufügen</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
|
||||||
<div class="table-wrap">
|
<div class="table-wrap">
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
@@ -387,6 +381,26 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="vertical-align:-2px;margin-right:6px;"><path d="m22 2-7 20-4-9-9-4Z"/><path d="M22 2 11 13"/></svg>Telegram-Zugang</h2>
|
||||||
|
</div>
|
||||||
|
<div class="table-wrap">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Benutzername</th>
|
||||||
|
<th>Telefon</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Anfragen</th>
|
||||||
|
<th>Letzte Prüfung</th>
|
||||||
|
<th>Aktionen</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="telegramStatusTable"><tr><td colspan="6" class="text-muted">Lade…</td></tr></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div> <!-- /sec-sources -->
|
</div> <!-- /sec-sources -->
|
||||||
@@ -976,7 +990,7 @@
|
|||||||
<script src="/static/js/app.js?v=20260725v"></script>
|
<script src="/static/js/app.js?v=20260725v"></script>
|
||||||
<script src="/static/js/sources.js?v=20260725f"></script>
|
<script src="/static/js/sources.js?v=20260725f"></script>
|
||||||
<script src="/static/js/aufgaben.js?v=20260725d"></script>
|
<script src="/static/js/aufgaben.js?v=20260725d"></script>
|
||||||
<script src="/static/js/x-scraper.js?v=20260725b"></script>
|
<script src="/static/js/x-scraper.js?v=20260725c"></script>
|
||||||
<script src="/static/js/audit.js?v=20260725a"></script>
|
<script src="/static/js/audit.js?v=20260725a"></script>
|
||||||
<div id="toastContainer" class="toast-container" aria-live="polite" aria-atomic="true"></div>
|
<div id="toastContainer" class="toast-container" aria-live="polite" aria-atomic="true"></div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -16,36 +16,38 @@ async function loadXScraperAccounts() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Telegram-Session-Status (vom Monitor in die geteilte DB gemeldet)
|
// Telegram-Session-Status (vom Monitor in die geteilte DB gemeldet),
|
||||||
|
// dargestellt als Tabellenzeile im selben Format wie die X-Konten
|
||||||
async function loadTelegramStatus() {
|
async function loadTelegramStatus() {
|
||||||
const box = document.getElementById("telegramStatusBox");
|
const tbody = document.getElementById("telegramStatusTable");
|
||||||
if (!box) return;
|
if (!tbody) return;
|
||||||
try {
|
try {
|
||||||
const st = await API.get("/api/x-scraper/telegram-status");
|
const st = await API.get("/api/x-scraper/telegram-status");
|
||||||
if (!st.available) {
|
if (!st.available) {
|
||||||
box.innerHTML = '<span class="text-muted">Noch keine Statusmeldung vom Monitor vorhanden. '
|
tbody.innerHTML = '<tr><td colspan="6" class="text-muted">Noch keine Statusmeldung vom Monitor vorhanden. Der Monitor meldet beim Start und täglich um 04:30 Uhr.</td></tr>';
|
||||||
+ 'Der Monitor meldet den Status beim Start und täglich um 04:30 Uhr.</span>';
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const stand = `<span class="text-secondary" style="margin-left:10px;font-size:12px;">Stand ${formatDateTime(st.updated_at)}</span>`;
|
const status = st.ok
|
||||||
if (st.ok) {
|
? '<span style="color:var(--success,#2e7d32);">Aktiv</span>'
|
||||||
box.innerHTML = `<span class="badge badge-active">Session gültig</span> `
|
: '<span style="color:var(--danger,#c62828);">Problem</span> <span class="text-secondary" style="font-size:12px;">' + esc(st.error || "Session nicht autorisiert") + '</span>';
|
||||||
+ `<span style="margin-left:6px;">Verbunden${st.account ? " als " + esc(st.account) : ""}. `
|
const aktion = st.ok
|
||||||
+ `Die Telegram-Anmeldung läuft nicht periodisch ab, hier ist normalerweise nichts zu tun.</span>${stand}`;
|
? '<span class="text-muted" title="Die Telegram-Anmeldung läuft nicht periodisch ab, hier ist normalerweise nichts zu tun.">—</span>'
|
||||||
} else {
|
: '<span class="text-secondary" style="font-size:12px;">Neu-Login nur auf dem Server möglich</span>';
|
||||||
box.innerHTML = `<span class="badge badge-inactive">Problem</span> `
|
tbody.innerHTML = `<tr>
|
||||||
+ `<span style="margin-left:6px;">${esc(st.error || "Session nicht autorisiert")}. `
|
<td>${esc(st.account || "—")}</td>
|
||||||
+ `Die Telegram-Recherche ist pausiert, bis auf dem Server neu eingeloggt wurde.</span>${stand}`;
|
<td class="text-secondary">${esc(st.phone || "—")}</td>
|
||||||
}
|
<td>${status}</td>
|
||||||
|
<td class="text-secondary">—</td>
|
||||||
|
<td class="text-secondary">${formatDateTime(st.updated_at)}</td>
|
||||||
|
<td>${aktion}</td>
|
||||||
|
</tr>`;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
box.innerHTML = '<span class="text-muted">Status konnte nicht geladen werden. ' + esc(err.message || "") + '</span>';
|
tbody.innerHTML = '<tr><td colspan="6" class="text-muted">Status konnte nicht geladen werden. ' + esc(err.message || "") + '</td></tr>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderXScraperAccounts(list) {
|
function renderXScraperAccounts(list) {
|
||||||
const tbody = document.getElementById("xScraperTable");
|
const tbody = document.getElementById("xScraperTable");
|
||||||
const cnt = document.getElementById("xScraperCount");
|
|
||||||
if (cnt) cnt.textContent = list.length + (list.length === 1 ? " Konto" : " Konten");
|
|
||||||
if (!list.length) {
|
if (!list.length) {
|
||||||
tbody.innerHTML = '<tr><td colspan="6" class="text-muted">Keine X-Recherche-Konten. Mit „+ Konto hinzufügen" anlegen.</td></tr>';
|
tbody.innerHTML = '<tr><td colspan="6" class="text-muted">Keine X-Recherche-Konten. Mit „+ Konto hinzufügen" anlegen.</td></tr>';
|
||||||
return;
|
return;
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren