Files
Eurojackpot-Tipp-Generator/scripts/utils/notifier.py
T
cbazzaandClaude Sonnet 4.5 ca003e44b7 Improve Telegram notifications and fix data paths
- Enhanced Telegram message format to show TOP 3 by Confidence AND Quality
- Added average statistics (Confidence & Quality) to notifications
- Fixed hardcoded iCloud path in generator (now uses --data-dir parameter)
- Updated AlleEurojackpotzahlen.csv with latest draw (Jan 9)
- Added run_update_and_learn.sh wrapper script
- Created com.eurojackpot.update.plist for automated updates

Benefits:
- Better tip selection with dual metrics visibility
- Generator now works with correct project paths
- More robust automation setup

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-14 10:48:15 +01:00

344 lines
11 KiB
Python

#!/usr/bin/env python3
"""
Eurojackpot Notification System
Sendet Benachrichtigungen via:
- Telegram Bot
- E-Mail (SMTP)
Konfiguration via config/notifications.json
"""
import os
import json
import requests
from typing import Optional, Dict, List
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib
class EurojackpotNotifier:
"""Benachrichtigungssystem für Eurojackpot-Events."""
def __init__(self, config_file: Optional[str] = None):
if config_file is None:
# Default config path
script_dir = os.path.dirname(os.path.abspath(__file__))
project_dir = os.path.dirname(os.path.dirname(script_dir))
config_file = os.path.join(project_dir, "config", "notifications.json")
self.config_file = config_file
self.config = self._load_config()
def _load_config(self) -> dict:
"""Lädt Konfiguration."""
if not os.path.exists(self.config_file):
return {
"telegram": {"enabled": False},
"email": {"enabled": False}
}
try:
with open(self.config_file, 'r') as f:
return json.load(f)
except Exception as e:
print(f"⚠️ Fehler beim Laden der Notification-Config: {e}")
return {
"telegram": {"enabled": False},
"email": {"enabled": False}
}
def send_tips_generated(self, tips: List[Dict], timestamp: str, best_tip: Dict):
"""
Benachrichtigung: Neue Tipps generiert.
Args:
tips: Liste der generierten Tipps
timestamp: Zeitstempel der Generierung
best_tip: Bester Tipp mit höchster Confidence
"""
subject = f"🎲 {len(tips)} neue Eurojackpot-Tipps generiert!"
# Statistiken
avg_conf = sum(t.get('confidence', 0) for t in tips) / len(tips) if tips else 0
avg_qual = sum(t.get('quality', 0) for t in tips) / len(tips) if tips else 0
# Top 3 nach Confidence
sorted_by_conf = sorted(tips, key=lambda x: x.get('confidence', 0), reverse=True)[:3]
top3_conf_text = ""
for i, tip in enumerate(sorted_by_conf, 1):
emoji = "🥇" if i == 1 else "🥈" if i == 2 else "🥉"
main = tip.get('main_numbers', '?')
euro = tip.get('euro_numbers', '?')
conf = tip.get('confidence', 0)
qual = tip.get('quality', 0)
strat = tip.get('strategy', 'UNKNOWN')
top3_conf_text += f"""{emoji} #{i} - Conf: {conf:.2%} | Q: {qual:.3f}
🔢 {main} + ⭐ {euro}
📈 {strat}
"""
# Top 3 nach Quality
sorted_by_qual = sorted(tips, key=lambda x: x.get('quality', 0), reverse=True)[:3]
top3_qual_text = ""
for i, tip in enumerate(sorted_by_qual, 1):
emoji = "🥇" if i == 1 else "🥈" if i == 2 else "🥉"
main = tip.get('main_numbers', '?')
euro = tip.get('euro_numbers', '?')
conf = tip.get('confidence', 0)
qual = tip.get('quality', 0)
strat = tip.get('strategy', 'UNKNOWN')
top3_qual_text += f"""{emoji} #{i} - Q: {qual:.3f} | Conf: {conf:.2%}
🔢 {main} + ⭐ {euro}
📈 {strat}
"""
message = f"""🎲 NEUE EUROJACKPOT-TIPPS GENERIERT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 Anzahl Tipps: {len(tips)}
⏰ Zeitpunkt: {timestamp}
📊 STATISTIKEN:
🎯 Ø Confidence: {avg_conf:.4f}
💎 Ø Quality: {avg_qual:.4f}
🎯 TOP 3 NACH CONFIDENCE:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
{top3_conf_text}
💎 TOP 3 NACH QUALITY:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
{top3_qual_text}
💡 Alle 10 Tipps findest du in der CSV-Datei!
Viel Glück! 🍀
"""
# Sende via Telegram
if self.config.get("telegram", {}).get("enabled"):
self._send_telegram(message)
# Sende via Email
if self.config.get("email", {}).get("enabled"):
self._send_email(subject, message)
def send_draw_results(self, draw: Dict, evaluation: Dict, best_match: Dict):
"""
Benachrichtigung: Ziehung evaluiert.
Args:
draw: Gezogene Zahlen
evaluation: Evaluierungsergebnisse
best_match: Bester Tipp
"""
# Formatiere gezogene Zahlen
main = [draw[f'Z{i}'] for i in range(1, 6)]
euro = [draw['SZ1'], draw['SZ2']]
date = draw.get('date', 'unknown')
# Formatiere besten Tipp
best_main_matches = best_match.get('main_matches', 0)
best_euro_matches = best_match.get('euro_matches', 0)
total_matches = best_main_matches + best_euro_matches
# Bewertungs-Emoji
if total_matches >= 5:
emoji = "🎉🎉🎉"
rating = "FANTASTISCH!"
elif total_matches >= 4:
emoji = "🎊"
rating = "Sehr gut!"
elif total_matches >= 3:
emoji = "✅"
rating = "Gut!"
elif total_matches >= 2:
emoji = "👍"
rating = "OK"
else:
emoji = "⚪"
rating = "Nächstes Mal besser"
subject = f"🎰 Ziehung vom {date}: {total_matches} Treffer!"
message = f"""🎰 EUROJACKPOT-ZIEHUNG AUSGEWERTET
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📅 Datum: {date}
🎲 GEZOGENE ZAHLEN:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔢 Hauptzahlen: {'-'.join(map(str, main))}
⭐ Eurozahlen: {'-'.join(map(str, euro))}
{emoji} DEINE BESTEN TREFFER:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔢 Hauptzahlen: {best_main_matches} Treffer
⭐ Eurozahlen: {best_euro_matches} Treffer
🎯 Gesamt: {total_matches} Treffer
📊 Bewertung: {rating}
📈 DURCHSCHNITT ALLER TIPPS:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔢 Main: {evaluation.get('avg_main', 0):.1f} Treffer
⭐ Euro: {evaluation.get('avg_euro', 0):.1f} Treffer
💡 Details im Performance-Report!
"""
# Sende via Telegram
if self.config.get("telegram", {}).get("enabled"):
self._send_telegram(message)
# Sende via Email
if self.config.get("email", {}).get("enabled"):
self._send_email(subject, message)
def send_error(self, error_msg: str, context: str = ""):
"""
Benachrichtigung: Fehler aufgetreten.
Args:
error_msg: Fehlermeldung
context: Kontext (z.B. "Tipp-Generierung")
"""
subject = f"❌ Eurojackpot Fehler: {context}"
message = f"""❌ FEHLER IM EUROJACKPOT-SYSTEM
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📍 Kontext: {context}
🔴 Fehler: {error_msg}
💡 Bitte System-Logs prüfen!
"""
# Sende nur via Telegram (Fehler sind dringender)
if self.config.get("telegram", {}).get("enabled"):
self._send_telegram(message)
def _send_telegram(self, message: str):
"""Sendet Nachricht via Telegram Bot."""
try:
telegram_config = self.config.get("telegram", {})
bot_token = telegram_config.get("bot_token")
chat_id = telegram_config.get("chat_id")
if not bot_token or not chat_id:
return
url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
payload = {
"chat_id": chat_id,
"text": message,
"disable_web_page_preview": True
}
response = requests.post(url, json=payload, timeout=10)
if response.status_code != 200:
error_detail = response.json() if response.text else {}
print(f"⚠️ Telegram API Error: {error_detail}")
response.raise_for_status()
except Exception as e:
print(f"⚠️ Telegram-Benachrichtigung fehlgeschlagen: {e}")
def _send_email(self, subject: str, message: str):
"""Sendet E-Mail via SMTP."""
try:
email_config = self.config.get("email", {})
smtp_server = email_config.get("smtp_server")
smtp_port = email_config.get("smtp_port", 587)
smtp_user = email_config.get("smtp_user")
smtp_password = email_config.get("smtp_password")
from_email = email_config.get("from_email", smtp_user)
to_email = email_config.get("to_email")
if not all([smtp_server, smtp_user, smtp_password, to_email]):
return
# Erstelle E-Mail
msg = MIMEMultipart("alternative")
msg["Subject"] = subject
msg["From"] = from_email
msg["To"] = to_email
# Plain text
text_part = MIMEText(message, "plain", "utf-8")
msg.attach(text_part)
# Sende via SMTP
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls()
server.login(smtp_user, smtp_password)
server.send_message(msg)
except Exception as e:
print(f"⚠️ E-Mail-Benachrichtigung fehlgeschlagen: {e}")
def test_notifications(self):
"""Testet alle konfigurierten Benachrichtigungen."""
print("\n🧪 TESTE BENACHRICHTIGUNGEN")
print("=" * 70)
test_message = """🧪 TEST-BENACHRICHTIGUNG
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Das Eurojackpot-Benachrichtigungssystem funktioniert! ✅
Wenn du diese Nachricht erhältst, ist alles korrekt konfiguriert.
"""
# Test Telegram
if self.config.get("telegram", {}).get("enabled"):
print("\n📱 Teste Telegram...")
self._send_telegram(test_message)
print(" ✅ Telegram-Nachricht gesendet")
# Test Email
if self.config.get("email", {}).get("enabled"):
print("\n📧 Teste E-Mail...")
self._send_email("🧪 Eurojackpot Test", test_message)
print(" ✅ E-Mail gesendet")
print("\n" + "=" * 70)
print("✅ Test abgeschlossen - prüfe deine Nachrichten!")
def main():
"""Test-Funktion."""
import argparse
parser = argparse.ArgumentParser(description="Eurojackpot Notifier Test")
parser.add_argument(
'--test',
action='store_true',
help='Sendet Test-Benachrichtigungen'
)
parser.add_argument(
'--config',
type=str,
help='Pfad zur Config-Datei'
)
args = parser.parse_args()
notifier = EurojackpotNotifier(config_file=args.config)
if args.test:
notifier.test_notifications()
else:
print("Nutze --test um Test-Benachrichtigungen zu senden")
if __name__ == "__main__":
main()