diff --git a/bundle_checker.py b/bundle_checker.py index 4b37dff..ec57e16 100644 --- a/bundle_checker.py +++ b/bundle_checker.py @@ -1,282 +1,19 @@ -#!/usr/bin/env python3 -import requests -import json -import hashlib +# bundle_checker.py import logging -import difflib -from datetime import datetime -from bs4 import BeautifulSoup +from bundle_parser import BundleParser -from sqlalchemy import create_engine, Column, Integer, String, Float, DateTime, ForeignKey, Text -from sqlalchemy.orm import declarative_base, relationship, sessionmaker - -# Konfiguriere Logging – ändere das Level bei Bedarf (DEBUG, INFO, WARNING, ERROR) -DEBUG_LEVEL = logging.DEBUG -logging.basicConfig( - level=DEBUG_LEVEL, - format="%(asctime)s [%(levelname)s] %(message)s", - datefmt="%Y-%m-%d %H:%M:%S" -) logger = logging.getLogger(__name__) -# Basis-Klasse für SQLAlchemy-Modelle (2.0-konform) -Base = declarative_base() - -# --------------------------- -# Datenbank-Modelle -# --------------------------- - -class Bundle(Base): - __tablename__ = 'bundles' - id = Column(Integer, primary_key=True) - machine_name = Column(String, unique=True) - human_name = Column(String) # Kann leer bleiben, wenn nicht extrahiert - current_version_id = Column(Integer, ForeignKey('bundle_versions.id')) - - # Beziehung zur aktuellen Version (post_update=True hilft bei zirkulären Abhängigkeiten) - current_version = relationship("BundleVersion", uselist=False, - foreign_keys=[current_version_id], - post_update=True) - # Alle Versionen (historisch) - versions = relationship("BundleVersion", back_populates="bundle", - foreign_keys=lambda: [BundleVersion.bundle_id]) - # Verkaufshistorie - sales_history = relationship("BundleSalesHistory", back_populates="bundle") - # Einzelne Elemente des Bundles (z. B. enthaltene Bücher, Spiele etc.) - items = relationship("BundleItem", back_populates="bundle") - -class BundleVersion(Base): - __tablename__ = 'bundle_versions' - id = Column(Integer, primary_key=True) - bundle_id = Column(Integer, ForeignKey('bundles.id')) - version_hash = Column(String) - version_data = Column(Text) # JSON-Daten als String - timestamp = Column(DateTime, default=datetime.utcnow) - - # Explizite Angabe des Fremdschlüssels - bundle = relationship("Bundle", back_populates="versions", foreign_keys=[bundle_id]) - -class BundleSalesHistory(Base): - __tablename__ = 'bundle_sales_history' - id = Column(Integer, primary_key=True) - bundle_id = Column(Integer, ForeignKey('bundles.id')) - bundles_sold = Column(Float) - timestamp = Column(DateTime, default=datetime.utcnow) - - bundle = relationship("Bundle", back_populates="sales_history") - -class BundleItem(Base): - __tablename__ = 'bundle_items' - id = Column(Integer, primary_key=True) - bundle_id = Column(Integer, ForeignKey('bundles.id')) - title = Column(String) # Titel des Elements (z. B. Buch- oder Spielname) - category = Column(String) # Kategorie, z. B. "book", "game" oder "software" - details = Column(Text) # Optionale Detaildaten als JSON-String - - bundle = relationship("Bundle", back_populates="items") - -# --------------------------- -# Hilfsfunktionen -# --------------------------- - -def calculate_hash(data: dict) -> str: - """Berechnet einen SHA-256-Hash aus dem sortierten JSON-String der Daten.""" - json_string = json.dumps(data, sort_keys=True, ensure_ascii=False) - hash_value = hashlib.sha256(json_string.encode('utf-8')).hexdigest() - logger.debug(f"Berechneter Hash: {hash_value}") - return hash_value - -def log_diff(old_data: dict, new_data: dict): - """ - Vergleicht zwei JSON-Daten (als dict) und gibt einen unified diff als String aus. - Nur im DEBUG-Level wird der detaillierte Vergleich ausgegeben. - """ - old_str = json.dumps(old_data, sort_keys=True, indent=4, ensure_ascii=False).splitlines() - new_str = json.dumps(new_data, sort_keys=True, indent=4, ensure_ascii=False).splitlines() - diff = difflib.unified_diff(old_str, new_str, fromfile="alte_version", tofile="neue_version", lineterm="") - diff_text = "\n".join(diff) - logger.debug("Unterschiede zwischen den Versionen:\n" + diff_text) - -def fetch_bundle_data(url: str) -> dict: - """ - Lädt die Detailseite eines Bundles und extrahiert den JSON-Inhalt aus dem