Add editor exclusion defaults and newsletter filtering controls.

This makes it possible to exclude specific editors (e.g. Aranzinger) from edited-article results by default, including dashboard generation and scheduled SMTP runs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
smueller
2026-07-09 10:53:01 +02:00
parent b8073f659d
commit 48410d39da
6 changed files with 57 additions and 8 deletions

View File

@@ -76,11 +76,21 @@ def filter_articles(
]
def split_articles_by_type(articles: list[dict[str, Any]]) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
def parse_excluded_users(raw: str | None) -> set[str]:
if not raw:
return set()
return {part.strip().lower() for part in raw.split(",") if part.strip()}
def split_articles_by_type(
articles: list[dict[str, Any]],
excluded_edited_users: set[str] | None = None,
) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
sorted_articles = sorted(articles, key=lambda a: a.get("timestamp", ""), reverse=True)
new_articles: list[dict[str, Any]] = []
edited_articles: list[dict[str, Any]] = []
new_titles: set[str] = set()
excluded_edited_users = excluded_edited_users or set()
for item in sorted_articles:
title = item.get("title", "")
@@ -93,8 +103,11 @@ def split_articles_by_type(articles: list[dict[str, Any]]) -> tuple[list[dict[st
seen_edited: set[str] = set()
for item in sorted_articles:
title = item.get("title", "")
editor = str(item.get("user", "")).strip().lower()
if not title or title in new_titles or title in seen_edited:
continue
if editor in excluded_edited_users:
continue
edited_articles.append(item)
seen_edited.add(title)
@@ -204,9 +217,10 @@ def create_plain_text(
period: tuple[str, str] | None = None,
article_type: str = "all",
contact_email: str = "",
excluded_edited_users: set[str] | None = None,
) -> str:
display = display or DEFAULT_DISPLAY
new_articles, edited_articles = split_articles_by_type(articles)
new_articles, edited_articles = split_articles_by_type(articles, excluded_edited_users=excluded_edited_users)
show_new = article_type in ("all", "new")
show_edited = article_type in ("all", "edited")
period_start, period_end = period if period else _period_range(days)
@@ -308,9 +322,10 @@ def create_html(
article_type: str = "all",
month_label: str | None = None,
contact_email: str = "",
excluded_edited_users: set[str] | None = None,
) -> str:
display = display or DEFAULT_DISPLAY
new_articles, edited_articles = split_articles_by_type(articles)
new_articles, edited_articles = split_articles_by_type(articles, excluded_edited_users=excluded_edited_users)
show_new = article_type in ("all", "new")
show_edited = article_type in ("all", "edited")
period_start, period_end = period if period else _period_range(days)
@@ -707,10 +722,11 @@ def create_outlook_html(
article_type: str = "all",
month_label: str | None = None,
contact_email: str = "",
excluded_edited_users: set[str] | None = None,
) -> str:
"""Word/Outlook-kompatibles HTML mit font-Tags und bgcolor (überlebt Einfügen in Outlook)."""
display = display or DEFAULT_DISPLAY
new_articles, edited_articles = split_articles_by_type(articles)
new_articles, edited_articles = split_articles_by_type(articles, excluded_edited_users=excluded_edited_users)
show_new = article_type in ("all", "new")
show_edited = article_type in ("all", "edited")
period_start, period_end = period if period else _period_range(days)

View File

@@ -8,6 +8,7 @@ from typing import Sequence
from sqlalchemy.orm import Session
from app.core.config import settings
from app.core.email_utils import parse_recipient_list
from app.models.system import SendLog
from app.services.config_store import get_config
@@ -40,6 +41,7 @@ def get_smtp_settings(db: Session) -> dict[str, str]:
"gen_days": get_config(db, "smtp.gen_days", "30"),
"gen_article_type": get_config(db, "smtp.gen_article_type", "new"),
"gen_category": get_config(db, "smtp.gen_category", ""),
"gen_excluded_users": get_config(db, "smtp.gen_excluded_users", settings.default_excluded_users),
}