Telegram-Kanaele als Quelle: Parser, Pipeline, UI-Checkbox, Validate-Endpoint
- Neuer source_type telegram_channel in models.py (Source + Incident) - DB-Migration: include_telegram Spalte fuer incidents - feeds/telegram_parser.py: Telethon-basierter Parser (analog RSS) - Orchestrator: Telegram-Pipeline parallel zu RSS + WebSearch - sources.py: POST /api/sources/telegram/validate Endpoint - incidents.py: include_telegram in Create/Update/Response - dashboard.html: Telegram-Checkbox + Filter-Option - app.js: FormData, EditModal, SourceStats, TypeLabels - config.py: TELEGRAM_API_ID, API_HASH, SESSION_PATH - requirements.txt: telethon hinzugefuegt
Dieser Commit ist enthalten in:
@@ -20,7 +20,7 @@ router = APIRouter(prefix="/api/incidents", tags=["incidents"])
|
||||
|
||||
INCIDENT_UPDATE_COLUMNS = {
|
||||
"title", "description", "type", "status", "refresh_mode",
|
||||
"refresh_interval", "retention_days", "international_sources", "visibility",
|
||||
"refresh_interval", "retention_days", "international_sources", "include_telegram", "visibility",
|
||||
}
|
||||
|
||||
|
||||
@@ -105,9 +105,9 @@ async def create_incident(
|
||||
now = datetime.now(TIMEZONE).strftime('%Y-%m-%d %H:%M:%S')
|
||||
cursor = await db.execute(
|
||||
"""INSERT INTO incidents (title, description, type, refresh_mode, refresh_interval,
|
||||
retention_days, international_sources, visibility,
|
||||
retention_days, international_sources, include_telegram, visibility,
|
||||
tenant_id, created_by, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(
|
||||
data.title,
|
||||
data.description,
|
||||
@@ -116,6 +116,7 @@ async def create_incident(
|
||||
data.refresh_interval,
|
||||
data.retention_days,
|
||||
1 if data.international_sources else 0,
|
||||
1 if data.include_telegram else 0,
|
||||
data.visibility,
|
||||
tenant_id,
|
||||
current_user["id"],
|
||||
@@ -721,6 +722,7 @@ def _build_json_export(
|
||||
"updated_at": incident.get("updated_at"),
|
||||
"summary": incident.get("summary"),
|
||||
"international_sources": bool(incident.get("international_sources")),
|
||||
"include_telegram": bool(incident.get("include_telegram")),
|
||||
},
|
||||
"sources": sources,
|
||||
"fact_checks": [
|
||||
|
||||
@@ -87,6 +87,7 @@ async def get_source_stats(
|
||||
stats = {
|
||||
"rss_feed": {"count": 0, "articles": 0},
|
||||
"web_source": {"count": 0, "articles": 0},
|
||||
"telegram_channel": {"count": 0, "articles": 0},
|
||||
"excluded": {"count": 0, "articles": 0},
|
||||
}
|
||||
for row in rows:
|
||||
@@ -516,6 +517,32 @@ async def delete_source(
|
||||
await db.commit()
|
||||
|
||||
|
||||
|
||||
|
||||
@router.post("/telegram/validate")
|
||||
async def validate_telegram_channel(
|
||||
data: dict,
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
"""Prueft ob ein Telegram-Kanal erreichbar ist und gibt Kanalinfo zurueck."""
|
||||
channel_id = data.get("channel_id", "").strip()
|
||||
if not channel_id:
|
||||
raise HTTPException(status_code=400, detail="channel_id ist erforderlich")
|
||||
|
||||
try:
|
||||
from feeds.telegram_parser import TelegramParser
|
||||
parser = TelegramParser()
|
||||
result = await parser.validate_channel(channel_id)
|
||||
if result:
|
||||
return result
|
||||
raise HTTPException(status_code=404, detail="Kanal nicht erreichbar oder nicht gefunden")
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error("Telegram-Validierung fehlgeschlagen: %s", e, exc_info=True)
|
||||
raise HTTPException(status_code=500, detail="Telegram-Validierung fehlgeschlagen")
|
||||
|
||||
|
||||
@router.post("/refresh-counts")
|
||||
async def trigger_refresh_counts(
|
||||
current_user: dict = Depends(get_current_user),
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren