Files
Lotto-Tip-Generator/scripts/utils/notifier.py
T
cbazzaandClaude Sonnet 4.5 9d2e4dfbc9 Improve Telegram notifications and update automation
- Enhanced Telegram message format to show TOP 3 by Confidence AND Quality
- Added average statistics (Confidence & Quality) to notifications
- Generated new tips with updated data (3,090 draws, latest: Jan 10)
- Added run_update_and_learn.sh wrapper script
- Created com.lotto.update.plist for automated updates
- Updated AlleLottozahlen.csv with latest draws

Benefits:
- Better tip selection with dual metrics visibility
- Clearer understanding of tip performance
- More informed decision-making for users

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

351 lines
12 KiB
Python

#!/usr/bin/env python3
"""
Lotto 6aus49 Benachrichtigungs-System
Unterstützt:
- Telegram Bot Notifications
- Email Notifications (optional)
Konfiguration über config/notifications.json
"""
import os
import json
import requests
from typing import List, Dict, Any
class LottoNotifier:
"""Benachrichtigungs-System für Lotto 6aus49."""
def __init__(self, config_path: str = None):
"""
Initialisiert Notifier.
Args:
config_path: Pfad zur Konfigurationsdatei
"""
if config_path is None:
# Default: config/notifications.json im Projekt-Root
script_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(os.path.dirname(script_dir))
config_path = os.path.join(project_root, 'config', 'notifications.json')
self.config_path = config_path
self.config = self._load_config()
def _load_config(self) -> dict:
"""Lädt Konfiguration."""
if not os.path.exists(self.config_path):
print(f"⚠️ Konfigurationsdatei nicht gefunden: {self.config_path}")
return {
"telegram": {"enabled": False},
"email": {"enabled": False}
}
try:
with open(self.config_path, 'r') as f:
config = json.load(f)
return config
except Exception as e:
print(f"⚠️ Fehler beim Laden der Konfiguration: {e}")
return {
"telegram": {"enabled": False},
"email": {"enabled": False}
}
def send_tips_generated(self, tips: List[Dict], timestamp: str, best_tip: Dict):
"""
Sendet Benachrichtigung über generierte Tipps.
Args:
tips: Liste aller generierten Tipps
timestamp: Timestamp der Generierung
best_tip: Bester Tipp (höchste Confidence)
"""
if self.config['telegram']['enabled']:
self._send_telegram_tips(tips, timestamp, best_tip)
if self.config['email']['enabled']:
self._send_email_tips(tips, timestamp, best_tip)
def _send_telegram_tips(self, tips: List[Dict], timestamp: str, best_tip: Dict):
"""Sendet Telegram-Nachricht."""
try:
bot_token = self.config['telegram']['bot_token']
chat_id = self.config['telegram']['chat_id']
# Formatiere Nachricht
message = self._format_telegram_message(tips, timestamp, best_tip)
# Sende über Telegram Bot API
url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
data = {
"chat_id": chat_id,
"text": message,
"parse_mode": "Markdown"
}
response = requests.post(url, data=data, timeout=10)
if response.status_code == 200:
print("✅ Telegram-Benachrichtigung gesendet")
else:
print(f"⚠️ Telegram-Fehler: {response.status_code}")
print(f" Response: {response.text}")
except Exception as e:
print(f"⚠️ Telegram-Benachrichtigung fehlgeschlagen: {e}")
def _format_telegram_message(self, tips: List[Dict], timestamp: str, best_tip: Dict) -> str:
"""Formatiert Telegram-Nachricht."""
# Header
message = "🎲 *LOTTO 6AUS49 - NEUE TIPPS GENERIERT*\n"
message += "=" * 40 + "\n\n"
# Timestamp
message += f"📅 *Generiert:* {timestamp}\n"
message += f"📊 *Anzahl Tipps:* {len(tips)}\n\n"
# Statistiken
avg_conf = sum(t['confidence'] for t in tips) / len(tips)
avg_qual = sum(t['quality'] for t in tips) / len(tips)
message += "📊 *STATISTIKEN:*\n"
message += f"🎯 Ø Confidence: `{avg_conf:.4f}`\n"
message += f"💎 Ø Quality: `{avg_qual:.4f}`\n\n"
# Top 3 nach Confidence
message += "🎯 *TOP 3 NACH CONFIDENCE:*\n"
message += "━━━━━━━━━━━━━━━━━━━━━━━\n"
sorted_by_conf = sorted(tips, key=lambda t: t['confidence'], reverse=True)[:3]
for i, tip in enumerate(sorted_by_conf, 1):
emoji = "🥇" if i == 1 else "🥈" if i == 2 else "🥉"
nums = '-'.join([f"{n:02d}" for n in tip['numbers']])
message += f"\n{emoji} *#{i}* Conf: `{tip['confidence']:.2%}` | Q: `{tip['quality']:.3f}`\n"
message += f"🔢 `{nums}` + SZ `{tip['superzahl']}`\n"
message += f"📈 {tip['strategy']}\n"
# Top 3 nach Quality
message += "\n💎 *TOP 3 NACH QUALITY:*\n"
message += "━━━━━━━━━━━━━━━━━━━━━━━\n"
sorted_by_qual = sorted(tips, key=lambda t: t['quality'], reverse=True)[:3]
for i, tip in enumerate(sorted_by_qual, 1):
emoji = "🥇" if i == 1 else "🥈" if i == 2 else "🥉"
nums = '-'.join([f"{n:02d}" for n in tip['numbers']])
message += f"\n{emoji} *#{i}* Q: `{tip['quality']:.3f}` | Conf: `{tip['confidence']:.2%}`\n"
message += f"🔢 `{nums}` + SZ `{tip['superzahl']}`\n"
message += f"📈 {tip['strategy']}\n"
message += "\n💡 Alle 10 Tipps in der CSV-Datei!\n"
message += "🍀 *Viel Glück!*"
return message
def _send_email_tips(self, tips: List[Dict], timestamp: str, best_tip: Dict):
"""Sendet Email-Benachrichtigung."""
# TODO: Email-Versand implementieren wenn gewünscht
print("⚠️ Email-Benachrichtigung noch nicht implementiert")
def send_draw_results(self, draw: Dict, evaluation_summary: Dict, best_match: Dict):
"""
Sendet Benachrichtigung über Ziehungs-Ergebnisse und Tipp-Evaluation.
Args:
draw: Dict mit Ziehungsdaten (date, Z1-Z6, SZ)
evaluation_summary: Dict mit avg_main, sz_rate
best_match: Dict mit main_matches, sz_match
"""
if self.config['telegram']['enabled']:
self._send_telegram_draw_results(draw, evaluation_summary, best_match)
if self.config['email']['enabled']:
self._send_email_draw_results(draw, evaluation_summary, best_match)
def _send_telegram_draw_results(self, draw: Dict, evaluation_summary: Dict, best_match: Dict):
"""Sendet Telegram-Nachricht mit Ziehungsergebnissen."""
try:
bot_token = self.config['telegram']['bot_token']
chat_id = self.config['telegram']['chat_id']
# Formatiere Nachricht
message = self._format_draw_results_message(draw, evaluation_summary, best_match)
# Sende über Telegram Bot API
url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
data = {
"chat_id": chat_id,
"text": message,
"parse_mode": "Markdown"
}
response = requests.post(url, data=data, timeout=10)
if response.status_code == 200:
print("✅ Telegram-Benachrichtigung gesendet")
else:
print(f"⚠️ Telegram-Fehler: {response.status_code}")
print(f" Response: {response.text}")
except Exception as e:
print(f"⚠️ Telegram-Benachrichtigung fehlgeschlagen: {e}")
def _format_draw_results_message(self, draw: Dict, evaluation_summary: Dict, best_match: Dict) -> str:
"""Formatiert Telegram-Nachricht für Ziehungsergebnisse."""
# Header
message = "🎲 *LOTTO 6AUS49 - ZIEHUNGSERGEBNISSE*\n"
message += "=" * 40 + "\n\n"
# Ziehungsdatum
draw_date = draw['date']
if hasattr(draw_date, 'strftime'):
date_str = draw_date.strftime('%d.%m.%Y')
else:
date_str = str(draw_date)
message += f"📅 *Ziehung vom:* {date_str}\n\n"
# Gezogene Zahlen
drawn_numbers = [draw.get(f'Z{i}') for i in range(1, 7)]
numbers_str = ' - '.join([f"{n:02d}" for n in drawn_numbers if n is not None])
message += f"🎯 *Gewinnzahlen:* `{numbers_str}`\n"
if draw.get('SZ') is not None:
message += f"🌟 *Superzahl:* `{draw['SZ']}`\n\n"
else:
message += "\n"
# Evaluation Summary
message += "📊 *TIPP-EVALUATION:*\n"
if evaluation_summary:
avg_main = evaluation_summary.get('avg_main', 0)
sz_rate = evaluation_summary.get('sz_rate', 0)
message += f"🎯 Ø Treffer Hauptzahlen: `{avg_main:.2f}`\n"
message += f"🌟 Superzahl-Rate: `{sz_rate*100:.1f}%`\n\n"
# Bester Tipp
message += "🏆 *BESTER TIPP:*\n"
if best_match:
main_matches = best_match.get('main_matches', 0)
sz_match = best_match.get('sz_match', False)
# Rating emoji
if main_matches == 6 and sz_match:
rating = "🏆 JACKPOT!"
elif main_matches == 6:
rating = "💰 Klasse 2"
elif main_matches == 5 and sz_match:
rating = "💰 Klasse 3"
elif main_matches == 5:
rating = "💰 Klasse 4"
elif main_matches == 4:
rating = "💵 Klasse 6"
elif main_matches == 3:
rating = "✅ Klasse 8"
elif main_matches >= 2:
rating = "👍 OK"
else:
rating = "⚪ Niedrig"
sz_indicator = "✅" if sz_match else "⚪"
message += f"🎯 Treffer Hauptzahlen: `{main_matches}/6`\n"
message += f"🌟 Superzahl: {sz_indicator}\n"
message += f"📈 Bewertung: {rating}\n"
message += "\n🔄 *System wurde aktualisiert und trainiert!*"
return message
def _send_email_draw_results(self, draw: Dict, evaluation_summary: Dict, best_match: Dict):
"""Sendet Email-Benachrichtigung."""
# TODO: Email-Versand implementieren wenn gewünscht
print("⚠️ Email-Benachrichtigung noch nicht implementiert")
def send_test_notification(self):
"""Sendet Test-Benachrichtigung."""
if self.config['telegram']['enabled']:
try:
bot_token = self.config['telegram']['bot_token']
chat_id = self.config['telegram']['chat_id']
message = "🧪 *LOTTO 6AUS49 TEST*\n\n"
message += "✅ Benachrichtigungs-System funktioniert!\n"
message += f"📅 {os.popen('date').read().strip()}"
url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
data = {
"chat_id": chat_id,
"text": message,
"parse_mode": "Markdown"
}
response = requests.post(url, data=data, timeout=10)
if response.status_code == 200:
print("✅ Test-Benachrichtigung erfolgreich gesendet")
return True
else:
print(f"❌ Fehler: {response.status_code}")
print(f" Response: {response.text}")
return False
except Exception as e:
print(f"❌ Test fehlgeschlagen: {e}")
return False
else:
print("⚠️ Telegram nicht aktiviert in config/notifications.json")
return False
def main():
"""Test-Funktion."""
import argparse
parser = argparse.ArgumentParser(description="Lotto 6aus49 Notifier Test")
parser.add_argument(
'--test',
action='store_true',
help='Sende Test-Benachrichtigung'
)
parser.add_argument(
'--config',
type=str,
help='Pfad zur Config-Datei'
)
args = parser.parse_args()
notifier = LottoNotifier(config_path=args.config)
if args.test:
notifier.send_test_notification()
else:
# Beispiel-Tipps
example_tips = [
{
'numbers': [7, 14, 21, 28, 35, 42],
'superzahl': 3,
'confidence': 0.7234,
'quality': 0.6891,
'strategy': 'PURE-AI'
},
{
'numbers': [2, 11, 19, 27, 36, 45],
'superzahl': 7,
'confidence': 0.6978,
'quality': 0.6543,
'strategy': 'HYBRID-OPT'
}
]
best = example_tips[0]
notifier.send_tips_generated(example_tips, "2024-11-27 16:00", best)
if __name__ == "__main__":
main()