mirror of
https://github.com/skoelle/calender_sync.git
synced 2026-09-17 18:20:24 +00:00
new feature: weekly blacklistwords
This commit is contained in:
@@ -46,3 +46,4 @@ API_PORT=8000
|
|||||||
# WEEKLY_NOTIFY_TIMEZONE=Europe/Berlin
|
# WEEKLY_NOTIFY_TIMEZONE=Europe/Berlin
|
||||||
# WEEKLY_NOTIFY_EMAIL=empfaenger@example.com
|
# WEEKLY_NOTIFY_EMAIL=empfaenger@example.com
|
||||||
# WEEKLY_SEARCHWORDS=Termin1,Termin2
|
# WEEKLY_SEARCHWORDS=Termin1,Termin2
|
||||||
|
# WEEKLY_BLACKLISTWORDS=Ausgeschlossen1,Ausgeschlossen2
|
||||||
|
|||||||
@@ -75,13 +75,14 @@ Sendet täglich um konfigurierte Uhrzeit eine HTML-Email mit anstehenden Termine
|
|||||||
### Wöchentliche E-Mail-Benachrichtigung (Vorab-Info)
|
### Wöchentliche E-Mail-Benachrichtigung (Vorab-Info)
|
||||||
Sendet wöchentlich (standardmäßig Freitags) eine HTML-Email mit Terminen, die auf Suchbegriffe passen:
|
Sendet wöchentlich (standardmäßig Freitags) eine HTML-Email mit Terminen, die auf Suchbegriffe passen:
|
||||||
- Sucht nach Begriffen in summary, description und location
|
- Sucht nach Begriffen in summary, description und location
|
||||||
|
- Optionale Blacklist: Begriffe die ausgeschlossen werden (z.B. `WEEKLY_BLACKLISTWORDS=Ausgeschlossen1,Ausgeschlossen2`)
|
||||||
- Zeitraum: Samstag bis Freitag der nächsten Woche
|
- Zeitraum: Samstag bis Freitag der nächsten Woche
|
||||||
- Subject: Bei 1 Termin "Vorab-Info: Termin am Mo, DD.MM.", bei mehreren "Vorab-Info: X Termine nächste Woche"
|
- Subject: Bei 1 Termin "Vorab-Info: Termin am Mo, DD.MM.", bei mehreren "Vorab-Info: X Termine nächste Woche"
|
||||||
- Tracking via `weekly_notification_log` Tabelle (verhindert Doppelversand)
|
- Tracking via `weekly_notification_log` Tabelle (verhindert Doppelversand)
|
||||||
- Nur Termine mit Uhrzeit (`all_day=0`), keine Ganztagstermine
|
- Nur Termine mit Uhrzeit (`all_day=0`), keine Ganztagstermine
|
||||||
- Keine Email wenn keine Treffer
|
- Keine Email wenn keine Treffer
|
||||||
- Konfiguration über WEEKLY_* Umgebungsvariablen
|
- Konfiguration über WEEKLY_* Umgebungsvariablen
|
||||||
- Funktionen: `parse_weekly_searchwords()`, `get_weekly_events()`, `should_send_weekly()`, `send_weekly_notification()`, `log_weekly_notification()`, `check_and_send_weekly_notification()`
|
- Funktionen: `parse_weekly_searchwords()`, `parse_weekly_blacklistwords()`, `get_weekly_events()`, `should_send_weekly()`, `send_weekly_notification()`, `log_weekly_notification()`, `check_and_send_weekly_notification()`
|
||||||
|
|
||||||
## Entwicklung
|
## Entwicklung
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ WEEKLY_NOTIFY_TIME = int(os.environ.get("WEEKLY_NOTIFY_TIME", "16"))
|
|||||||
WEEKLY_NOTIFY_TIMEZONE = os.environ.get("WEEKLY_NOTIFY_TIMEZONE", "Europe/Berlin")
|
WEEKLY_NOTIFY_TIMEZONE = os.environ.get("WEEKLY_NOTIFY_TIMEZONE", "Europe/Berlin")
|
||||||
WEEKLY_NOTIFY_EMAIL = os.environ.get("WEEKLY_NOTIFY_EMAIL", "")
|
WEEKLY_NOTIFY_EMAIL = os.environ.get("WEEKLY_NOTIFY_EMAIL", "")
|
||||||
WEEKLY_SEARCHWORDS = os.environ.get("WEEKLY_SEARCHWORDS", "")
|
WEEKLY_SEARCHWORDS = os.environ.get("WEEKLY_SEARCHWORDS", "")
|
||||||
|
WEEKLY_BLACKLISTWORDS = os.environ.get("WEEKLY_BLACKLISTWORDS", "")
|
||||||
|
|
||||||
|
|
||||||
def bootstrap_database():
|
def bootstrap_database():
|
||||||
@@ -436,7 +437,13 @@ def parse_weekly_searchwords():
|
|||||||
return [w.strip() for w in WEEKLY_SEARCHWORDS.split(",") if w.strip()]
|
return [w.strip() for w in WEEKLY_SEARCHWORDS.split(",") if w.strip()]
|
||||||
|
|
||||||
|
|
||||||
def get_weekly_events(conn, calendar_label, searchwords):
|
def parse_weekly_blacklistwords():
|
||||||
|
if not WEEKLY_BLACKLISTWORDS:
|
||||||
|
return []
|
||||||
|
return [w.strip() for w in WEEKLY_BLACKLISTWORDS.split(",") if w.strip()]
|
||||||
|
|
||||||
|
|
||||||
|
def get_weekly_events(conn, calendar_label, searchwords, blacklistwords=None):
|
||||||
tz = ZoneInfo(WEEKLY_NOTIFY_TIMEZONE)
|
tz = ZoneInfo(WEEKLY_NOTIFY_TIMEZONE)
|
||||||
now = datetime.now(tz)
|
now = datetime.now(tz)
|
||||||
today = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
today = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||||
@@ -459,6 +466,17 @@ def get_weekly_events(conn, calendar_label, searchwords):
|
|||||||
|
|
||||||
where_search = " OR ".join(search_clauses) if search_clauses else "1=1"
|
where_search = " OR ".join(search_clauses) if search_clauses else "1=1"
|
||||||
|
|
||||||
|
blacklist_clauses = []
|
||||||
|
blacklist_params = []
|
||||||
|
for word in (blacklistwords or []):
|
||||||
|
like = f"%{word}%"
|
||||||
|
blacklist_clauses.append("(summary LIKE %s OR description LIKE %s OR location LIKE %s)")
|
||||||
|
blacklist_params.extend([like, like, like])
|
||||||
|
|
||||||
|
where_blacklist = ""
|
||||||
|
if blacklist_clauses:
|
||||||
|
where_blacklist = f"AND NOT ({' OR '.join(blacklist_clauses)})"
|
||||||
|
|
||||||
cur = conn.cursor(dictionary=True)
|
cur = conn.cursor(dictionary=True)
|
||||||
cur.execute(
|
cur.execute(
|
||||||
f"""
|
f"""
|
||||||
@@ -470,9 +488,10 @@ def get_weekly_events(conn, calendar_label, searchwords):
|
|||||||
AND start_at >= %s
|
AND start_at >= %s
|
||||||
AND start_at <= %s
|
AND start_at <= %s
|
||||||
AND ({where_search})
|
AND ({where_search})
|
||||||
|
{where_blacklist}
|
||||||
ORDER BY start_at ASC
|
ORDER BY start_at ASC
|
||||||
""",
|
""",
|
||||||
(calendar_label, week_start_naive, week_end_naive, *search_params),
|
(calendar_label, week_start_naive, week_end_naive, *search_params, *blacklist_params),
|
||||||
)
|
)
|
||||||
events = cur.fetchall()
|
events = cur.fetchall()
|
||||||
cur.close()
|
cur.close()
|
||||||
@@ -510,7 +529,7 @@ def log_weekly_notification(conn, event_count):
|
|||||||
cur.close()
|
cur.close()
|
||||||
|
|
||||||
|
|
||||||
def send_weekly_notification(events, searchwords, week_start, week_end):
|
def send_weekly_notification(events, searchwords, week_start, week_end, blacklistwords=None):
|
||||||
email = WEEKLY_NOTIFY_EMAIL or NOTIFY_EMAIL
|
email = WEEKLY_NOTIFY_EMAIL or NOTIFY_EMAIL
|
||||||
if not SMTP_HOST or not email:
|
if not SMTP_HOST or not email:
|
||||||
log.warning("SMTP-Konfiguration unvollstaendig, ueberspringe Wochenbenachrichtigung")
|
log.warning("SMTP-Konfiguration unvollstaendig, ueberspringe Wochenbenachrichtigung")
|
||||||
@@ -543,6 +562,8 @@ def send_weekly_notification(events, searchwords, week_start, week_end):
|
|||||||
</tr>"""
|
</tr>"""
|
||||||
|
|
||||||
words_display = ", ".join(searchwords)
|
words_display = ", ".join(searchwords)
|
||||||
|
blacklist_display = ", ".join(blacklistwords) if blacklistwords else ""
|
||||||
|
blacklist_line = f"Ausgeschlossen: {blacklist_display}" if blacklist_display else ""
|
||||||
|
|
||||||
html = f"""
|
html = f"""
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@@ -554,7 +575,7 @@ def send_weekly_notification(events, searchwords, week_start, week_end):
|
|||||||
<table style="width: 100%; border-collapse: collapse; margin: 20px 0; background: #f9f9f9; border-radius: 8px; overflow: hidden;">
|
<table style="width: 100%; border-collapse: collapse; margin: 20px 0; background: #f9f9f9; border-radius: 8px; overflow: hidden;">
|
||||||
{event_rows}
|
{event_rows}
|
||||||
</table>
|
</table>
|
||||||
<p style="color: #888; font-size: 12px;">Suchbegriffe: {words_display}</p>
|
<p style="color: #888; font-size: 12px;">Suchbegriffe: {words_display}{" " + blacklist_line if blacklist_line else ""}</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
@@ -590,9 +611,10 @@ def check_and_send_weekly_notification():
|
|||||||
try:
|
try:
|
||||||
if should_send_weekly(conn):
|
if should_send_weekly(conn):
|
||||||
searchwords = parse_weekly_searchwords()
|
searchwords = parse_weekly_searchwords()
|
||||||
events, week_start, week_end = get_weekly_events(conn, CALENDAR_LABEL, searchwords)
|
blacklistwords = parse_weekly_blacklistwords()
|
||||||
|
events, week_start, week_end = get_weekly_events(conn, CALENDAR_LABEL, searchwords, blacklistwords)
|
||||||
if events:
|
if events:
|
||||||
send_weekly_notification(events, searchwords, week_start, week_end)
|
send_weekly_notification(events, searchwords, week_start, week_end, blacklistwords)
|
||||||
log_weekly_notification(conn, len(events))
|
log_weekly_notification(conn, len(events))
|
||||||
log.info("Wochenbenachrichtigung fuer %d Events gesendet", len(events))
|
log.info("Wochenbenachrichtigung fuer %d Events gesendet", len(events))
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user