diff --git a/bundle_checker.py b/bundle_checker.py index 0a2dae0..b796bbb 100644 --- a/bundle_checker.py +++ b/bundle_checker.py @@ -2,28 +2,41 @@ import requests import json import hashlib +import logging from datetime import datetime from bs4 import BeautifulSoup -# Importiere declarative_base aus sqlalchemy.orm (SQLAlchemy 2.0-konform) -from sqlalchemy.orm import declarative_base, relationship, sessionmaker from sqlalchemy import create_engine, Column, Integer, String, Float, DateTime, ForeignKey, Text +from sqlalchemy.orm import declarative_base, relationship, sessionmaker -# Basis-Klasse für SQLAlchemy-Modelle +# Konfiguriere Logging – passe das Level bei Bedarf an (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 (SQLAlchemy 2.0-konform) Base = declarative_base() # Tabelle für das Bundle (statische Identifikation) class Bundle(Base): __tablename__ = 'bundles' id = Column(Integer, primary_key=True) - machine_name = Column(String, unique=True) # z. B. "linuxfrombeginnertoprofessionaloreilly_bookbundle" + machine_name = Column(String, unique=True) human_name = Column(String) + # current_version_id verweist auf die aktuelle Version in bundle_versions current_version_id = Column(Integer, ForeignKey('bundle_versions.id')) - # Beziehung zur aktuellen Version - current_version = relationship("BundleVersion", uselist=False, foreign_keys=[current_version_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='BundleVersion.bundle_id') + versions = relationship("BundleVersion", back_populates="bundle", + foreign_keys=lambda: [BundleVersion.bundle_id]) # Verkaufshistorie sales_history = relationship("BundleSalesHistory", back_populates="bundle") @@ -32,13 +45,14 @@ class BundleVersion(Base): __tablename__ = 'bundle_versions' id = Column(Integer, primary_key=True) bundle_id = Column(Integer, ForeignKey('bundles.id')) - version_hash = Column(String) # SHA-256 Hash der relevanten Daten - version_data = Column(Text) # Alle relevanten Bundle-Daten als JSON-String + version_hash = Column(String) + version_data = Column(Text) # Relevante Bundle-Daten als JSON-String timestamp = Column(DateTime, default=datetime.utcnow) - bundle = relationship("Bundle", back_populates="versions") + # Eindeutige Beziehung: wir verwenden hier explizit bundle_id + bundle = relationship("Bundle", back_populates="versions", foreign_keys=[bundle_id]) -# Tabelle für Verkaufshistorie (zur zeitlichen Analyse der Verkaufszahlen) +# Tabelle für Verkaufshistorie class BundleSalesHistory(Base): __tablename__ = 'bundle_sales_history' id = Column(Integer, primary_key=True) @@ -51,17 +65,23 @@ class BundleSalesHistory(Base): def calculate_hash(data: dict) -> str: """Berechnet einen SHA-256 Hash aus dem sortierten JSON-String der relevanten Daten.""" json_string = json.dumps(data, sort_keys=True, ensure_ascii=False) - return hashlib.sha256(json_string.encode('utf-8')).hexdigest() + hash_value = hashlib.sha256(json_string.encode('utf-8')).hexdigest() + logger.debug(f"Berechneter Hash: {hash_value}") + return hash_value def fetch_bundle_data(url: str) -> dict: """Lädt die Detailseite eines Bundles und extrahiert den JSON-Inhalt aus dem