feat(x-scraper): X-Recherche-Konten im Verwaltungsportal verwalten
Neuer Sub-Tab "X-Recherche-Konten" unter Quellen: die X-Login-Konten, mit denen der Monitor bei X scrapt (twscrape-Account-Pool), anzeigen, hinzufuegen, Cookies erneuern, aktiv/inaktiv schalten, entfernen, plus Sperren-Reset. - neuer Router x_scraper.py, verwaltet den twscrape-Pool ueber dessen API - X_ACCOUNTS_DB_PATH in config.py - twscrape als Abhaengigkeit (git-main-Pin) - Sub-Tab, Tabelle und zwei Modals in dashboard.html, Logik in x-scraper.js Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -329,6 +329,7 @@
|
||||
<button class="nav-tab" data-subtab="tenant-sources">Kundenquellen</button>
|
||||
<button class="nav-tab" data-subtab="source-health">Quellen-Health</button>
|
||||
<button class="nav-tab" data-subtab="classification-review">Klassifikation <span class="sources-tab-badge" id="classificationPendingBadge">0</span></button>
|
||||
<button class="nav-tab" data-subtab="x-scraper">X-Recherche-Konten</button>
|
||||
</div>
|
||||
|
||||
<!-- Grundquellen -->
|
||||
@@ -471,6 +472,37 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- X-Recherche-Konten (Sub-Tab) -->
|
||||
<div class="section" id="sub-x-scraper">
|
||||
<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;">
|
||||
<button class="btn btn-secondary" onclick="resetXScraperLocks()">Sperren zurücksetzen</button>
|
||||
<button class="btn btn-primary" onclick="openXScraperAddModal()">+ Konto hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<p class="text-secondary" style="padding:0 4px 12px;">X-Login-Konten, mit denen der Monitor bei X recherchiert. Mehr Konten bedeuten paralleleres, schnelleres Scrapen. Cookies laufen periodisch ab und müssen dann erneuert werden.</p>
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Benutzername</th>
|
||||
<th>E-Mail</th>
|
||||
<th>Status</th>
|
||||
<th>Anfragen</th>
|
||||
<th>Letzte Nutzung</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="xScraperTable"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div> <!-- /sec-sources -->
|
||||
|
||||
<!-- Audit-Log Section -->
|
||||
@@ -938,8 +970,77 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal: X-Recherche-Konto hinzufügen -->
|
||||
<div class="modal-overlay" id="modalXScraperAdd">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<h3>X-Recherche-Konto hinzufügen</h3>
|
||||
<button class="modal-close" onclick="closeModal('modalXScraperAdd')">×</button>
|
||||
</div>
|
||||
<form id="xScraperAddForm">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="xsUsername">X-Benutzername</label>
|
||||
<input type="text" id="xsUsername" required placeholder="Login-Handle des Kontos, ohne @">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="xsPassword">X-Passwort</label>
|
||||
<input type="password" id="xsPassword" placeholder="optional">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="xsEmail">E-Mail</label>
|
||||
<input type="text" id="xsEmail" placeholder="optional, z.B. konto@protonmail.com">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="xsEmailPassword">E-Mail-Passwort</label>
|
||||
<input type="password" id="xsEmailPassword" placeholder="optional">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="xsCookies">Cookies</label>
|
||||
<textarea id="xsCookies" rows="3" required placeholder="auth_token=...; ct0=..."></textarea>
|
||||
<small class="text-secondary">Aus dem eingeloggten X-Browser exportiert, mindestens auth_token und ct0.</small>
|
||||
</div>
|
||||
<div id="xScraperAddError" class="error-msg" style="display:none"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" onclick="closeModal('modalXScraperAdd')">Abbrechen</button>
|
||||
<button type="submit" class="btn btn-primary">Konto anlegen</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal: X-Recherche-Konto Cookies erneuern -->
|
||||
<div class="modal-overlay" id="modalXScraperCookies">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<h3>Cookies erneuern</h3>
|
||||
<button class="modal-close" onclick="closeModal('modalXScraperCookies')">×</button>
|
||||
</div>
|
||||
<form id="xScraperCookiesForm">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="xsCookiesUsername">Konto</label>
|
||||
<input type="text" id="xsCookiesUsername" readonly>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="xsCookiesValue">Neue Cookies</label>
|
||||
<textarea id="xsCookiesValue" rows="3" required placeholder="auth_token=...; ct0=..."></textarea>
|
||||
<small class="text-secondary">Frisch aus dem eingeloggten X-Browser exportieren.</small>
|
||||
</div>
|
||||
<div id="xScraperCookiesError" class="error-msg" style="display:none"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" onclick="closeModal('modalXScraperCookies')">Abbrechen</button>
|
||||
<button type="submit" class="btn btn-primary">Cookies setzen</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/static/js/app.js?v=20260522a"></script>
|
||||
<script src="/static/js/sources.js?v=20260509d"></script>
|
||||
<script src="/static/js/sources.js?v=20260522x2"></script>
|
||||
<script src="/static/js/x-scraper.js?v=20260522a"></script>
|
||||
<script src="/static/js/source-health.js?v=20260509l"></script>
|
||||
<script src="/static/js/audit.js?v=20260509d"></script>
|
||||
<div id="toastContainer" class="toast-container" aria-live="polite" aria-atomic="true"></div>
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren