feat(sources): X-Account-Verwaltung im Verwaltungsportal
Neuer Sub-Tab "X-Accounts" unter Quellen: die als Recherchequelle eingebundenen X-Accounts anzeigen, hinzufuegen, bearbeiten und entfernen. Schreibt source_type=x_account in die geteilte sources-Tabelle, von wo der Monitor sie pro Lage nutzt. - x_account im source_type-Pattern von GlobalSourceCreate/Update - primary_language in Create/Update plus INSERT (Keyword-Matching) - x_account-Typ und x-Kategorie in source_meta.py - Sub-Tab, Tabelle und Modal in dashboard.html, Logik in sources.js Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -42,7 +42,7 @@ router = APIRouter(prefix="/api/sources", tags=["sources"])
|
||||
|
||||
SOURCE_UPDATE_COLUMNS = {
|
||||
"name", "url", "domain", "source_type", "category", "status", "notes",
|
||||
"language", "bias", "fetch_strategy",
|
||||
"language", "primary_language", "bias", "fetch_strategy",
|
||||
"political_orientation", "media_type", "reliability",
|
||||
"state_affiliated", "country_code",
|
||||
}
|
||||
@@ -118,11 +118,12 @@ class GlobalSourceCreate(BaseModel):
|
||||
name: str = Field(min_length=1, max_length=200)
|
||||
url: Optional[str] = None
|
||||
domain: Optional[str] = None
|
||||
source_type: str = Field(default="rss_feed", pattern="^(rss_feed|web_source|excluded|telegram_channel|podcast_feed|pdf_document)$")
|
||||
source_type: str = Field(default="rss_feed", pattern="^(rss_feed|web_source|excluded|telegram_channel|podcast_feed|pdf_document|x_account)$")
|
||||
category: str = Field(default="sonstige")
|
||||
status: str = Field(default="active", pattern="^(active|inactive)$")
|
||||
notes: Optional[str] = None
|
||||
language: Optional[str] = Field(default=None, max_length=100)
|
||||
primary_language: Optional[str] = Field(default=None, max_length=16)
|
||||
bias: Optional[str] = Field(default=None, max_length=500)
|
||||
fetch_strategy: Optional[str] = Field(default="default", pattern="^(default|googlebot|paywall|skip)$")
|
||||
|
||||
@@ -131,11 +132,12 @@ class GlobalSourceUpdate(BaseModel):
|
||||
name: Optional[str] = Field(default=None, max_length=200)
|
||||
url: Optional[str] = None
|
||||
domain: Optional[str] = None
|
||||
source_type: Optional[str] = Field(default=None, pattern="^(rss_feed|web_source|excluded|telegram_channel|podcast_feed|pdf_document)$")
|
||||
source_type: Optional[str] = Field(default=None, pattern="^(rss_feed|web_source|excluded|telegram_channel|podcast_feed|pdf_document|x_account)$")
|
||||
category: Optional[str] = None
|
||||
status: Optional[str] = Field(default=None, pattern="^(active|inactive)$")
|
||||
notes: Optional[str] = None
|
||||
language: Optional[str] = Field(default=None, max_length=100)
|
||||
primary_language: Optional[str] = Field(default=None, max_length=16)
|
||||
bias: Optional[str] = Field(default=None, max_length=500)
|
||||
political_orientation: Optional[str] = None
|
||||
media_type: Optional[str] = None
|
||||
@@ -230,10 +232,10 @@ async def create_global_source(
|
||||
)
|
||||
|
||||
cursor = await db.execute(
|
||||
"""INSERT INTO sources (name, url, domain, source_type, category, status, notes, language, bias, fetch_strategy, added_by, tenant_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'system', NULL)""",
|
||||
"""INSERT INTO sources (name, url, domain, source_type, category, status, notes, language, primary_language, bias, fetch_strategy, added_by, tenant_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'system', NULL)""",
|
||||
(data.name, data.url, data.domain, data.source_type, data.category, data.status, data.notes,
|
||||
data.language, data.bias, data.fetch_strategy or "default"),
|
||||
data.language, data.primary_language, data.bias, data.fetch_strategy or "default"),
|
||||
)
|
||||
src_id = cursor.lastrowid
|
||||
await db.commit()
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren