Files
AccountForger-neuerUpload/licensing/license_manager.py
Claude Project Manager 04585e95b6 Initial commit
2025-08-01 23:50:28 +02:00

472 Zeilen
17 KiB
Python

"""
Lizenzverwaltungsfunktionalität für den Social Media Account Generator.
"""
import os
import json
import time
import uuid
import hmac
import hashlib
import logging
import requests
from datetime import datetime, timedelta
from typing import Dict, List, Any, Optional, Tuple, Union
from .api_client import LicenseAPIClient
from .hardware_fingerprint import HardwareFingerprint
from .session_manager import SessionManager
logger = logging.getLogger("license_manager")
class LicenseManager:
"""Klasse zur Verwaltung von Softwarelizenzen."""
CONFIG_FILE = os.path.join("config", "license.json")
def __init__(self):
"""Initialisiert den LicenseManager und lädt die Konfiguration."""
# API Client und andere Komponenten initialisieren
self.api_client = LicenseAPIClient()
self.hardware_fingerprint = HardwareFingerprint()
self.session_manager = SessionManager(self.api_client)
self.license_data = self.load_license_data()
self.machine_id = self.hardware_fingerprint.get_machine_name()
self.hardware_hash = self.hardware_fingerprint.get_or_create_fingerprint()
# Stelle sicher, dass das Konfigurationsverzeichnis existiert
os.makedirs(os.path.dirname(self.CONFIG_FILE), exist_ok=True)
def load_license_data(self) -> Dict[str, Any]:
"""Lädt die Lizenzdaten aus der Konfigurationsdatei."""
if not os.path.exists(self.CONFIG_FILE):
return {
"key": "",
"activation_id": None,
"activation_date": "",
"expiry_date": "",
"status": "inactive",
"status_text": "Keine Lizenz aktiviert",
"features": [],
"last_online_check": "",
"max_activations": 0,
"max_users": 0
}
try:
with open(self.CONFIG_FILE, "r", encoding="utf-8") as f:
license_data = json.load(f)
logger.info(f"Lizenzdaten geladen: Status '{license_data.get('status', 'unbekannt')}'")
return license_data
except Exception as e:
logger.error(f"Fehler beim Laden der Lizenzdaten: {e}")
return {
"key": "",
"activation_id": None,
"activation_date": "",
"expiry_date": "",
"status": "inactive",
"status_text": "Fehler beim Laden der Lizenz",
"features": [],
"last_online_check": "",
"max_activations": 0,
"max_users": 0
}
def save_license_data(self) -> bool:
"""Speichert die Lizenzdaten in die Konfigurationsdatei."""
try:
with open(self.CONFIG_FILE, "w", encoding="utf-8") as f:
json.dump(self.license_data, f, indent=2)
logger.info("Lizenzdaten gespeichert")
return True
except Exception as e:
logger.error(f"Fehler beim Speichern der Lizenzdaten: {e}")
return False
def clear_license_data(self) -> None:
"""Löscht alle Lizenzdaten und setzt auf Standardwerte zurück."""
self.license_data = {
"key": "",
"activation_id": None,
"activation_date": "",
"expiry_date": "",
"status": "inactive",
"status_text": "Keine Lizenz aktiviert",
"features": [],
"last_online_check": "",
"max_activations": 0,
"max_users": 0
}
self.save_license_data()
# Session beenden
if self.session_manager.is_session_active():
self.session_manager.end_session()
def get_license_info(self) -> Dict[str, Any]:
"""Gibt die aktuellen Lizenzdaten zurück."""
return self.license_data
def is_licensed(self) -> bool:
"""
Überprüft, ob eine gültige Lizenz vorhanden ist.
Returns:
True, wenn eine gültige Lizenz vorhanden ist, sonst False
"""
# Prüfe den Status der Lizenz
if self.license_data["status"] not in ["active", "trial"]:
return False
# Prüfe, ob die Lizenz abgelaufen ist
if self.license_data["expiry_date"]:
try:
expiry_date = datetime.fromisoformat(self.license_data["expiry_date"])
if datetime.now() > expiry_date:
logger.warning("Lizenz ist abgelaufen")
self.license_data["status"] = "expired"
self.license_data["status_text"] = "Lizenz abgelaufen"
self.save_license_data()
return False
except Exception as e:
logger.error(f"Fehler beim Parsen des Ablaufdatums: {e}")
return False
# Prüfe, ob regelmäßige Online-Verifizierung erforderlich ist
if self.license_data["last_online_check"]:
try:
last_check = datetime.fromisoformat(self.license_data["last_online_check"])
max_offline_days = 7 # Maximale Tage ohne Online-Check
if datetime.now() > last_check + timedelta(days=max_offline_days):
logger.warning(f"Letzte Online-Überprüfung ist mehr als {max_offline_days} Tage her")
# Versuche, eine Online-Überprüfung durchzuführen
if not self.online_verification():
self.license_data["status"] = "verification_required"
self.license_data["status_text"] = "Online-Überprüfung erforderlich"
self.save_license_data()
return False
except Exception as e:
logger.error(f"Fehler bei der Überprüfung der Online-Verifizierung: {e}")
return True
def online_verification(self) -> bool:
"""
Führt eine Online-Verifizierung der Lizenz durch.
Returns:
True, wenn die Online-Verifizierung erfolgreich war, sonst False
"""
if not self.license_data.get("activation_id"):
logger.warning("Keine Aktivierungs-ID vorhanden")
return False
logger.info("Führe Online-Verifizierung durch...")
try:
# API Call für Verifizierung
result = self.api_client.verify_license(
license_key=self.license_data["key"],
hardware_hash=self.hardware_hash,
machine_id=self.machine_id,
activation_id=self.license_data["activation_id"],
app_version="1.0.0"
)
if result.get("success"):
data = result.get("data", {})
# Update license data
if data.get("valid"):
self.license_data["last_online_check"] = datetime.now().isoformat()
self.license_data["status"] = "active"
self.license_data["status_text"] = "Lizenz aktiv"
# Update expiry date if provided
license_info = data.get("license", {})
if license_info.get("valid_until"):
self.license_data["expiry_date"] = license_info["valid_until"]
self.save_license_data()
logger.info("Online-Verifizierung erfolgreich")
return True
else:
logger.warning("Lizenz ist nicht mehr gültig")
self.license_data["status"] = "invalid"
self.license_data["status_text"] = data.get("message", "Lizenz ungültig")
self.save_license_data()
return False
else:
logger.error(f"Online-Verifizierung fehlgeschlagen: {result.get('error')}")
return False
except Exception as e:
logger.error(f"Fehler bei der Online-Verifizierung: {e}")
return False
def activate_license(self, license_key: str) -> Dict[str, Any]:
"""
Aktiviert eine Lizenz mit dem angegebenen Schlüssel.
Args:
license_key: Zu aktivierender Lizenzschlüssel
Returns:
Dictionary mit Erfolg und Nachricht
"""
if not license_key:
return {
"success": False,
"error": "Bitte geben Sie einen Lizenzschlüssel ein."
}
logger.info(f"Aktiviere Lizenz: {license_key[:4]}...")
try:
# API Call für Aktivierung
result = self.api_client.activate_license(
license_key=license_key,
hardware_hash=self.hardware_hash,
machine_name=self.machine_id,
app_version="1.0.0"
)
if result.get("success"):
data = result.get("data", {})
activation = data.get("activation", {})
# Speichere Lizenzdaten
self.license_data["key"] = license_key
self.license_data["activation_id"] = activation.get("id")
self.license_data["activation_date"] = activation.get("activated_at", datetime.now().isoformat())
self.license_data["status"] = "active"
self.license_data["status_text"] = "Lizenz erfolgreich aktiviert"
self.license_data["last_online_check"] = datetime.now().isoformat()
# Hole zusätzliche Lizenzinfos
info_result = self.api_client.get_license_info(license_key)
if info_result.get("success"):
license_info = info_result.get("data", {}).get("license", {})
self.license_data["expiry_date"] = license_info.get("valid_until", "")
self.license_data["max_activations"] = license_info.get("max_activations", 0)
self.license_data["max_users"] = license_info.get("max_users", 0)
self.license_data["features"] = self._extract_features(license_info)
self.save_license_data()
# Starte Session
session_result = self.session_manager.start_session(
license_key=license_key,
activation_id=self.license_data["activation_id"]
)
if not session_result.get("success"):
logger.warning(f"Session konnte nicht gestartet werden: {session_result.get('error')}")
logger.info("Lizenz erfolgreich aktiviert")
return {
"success": True,
"message": "Lizenz erfolgreich aktiviert",
"update_available": session_result.get("update_info", {}).get("available", False),
"latest_version": session_result.get("update_info", {}).get("version")
}
else:
error = result.get("error", "Unbekannter Fehler")
status = result.get("status", 0)
# Spezifische Fehlermeldungen
if status == 404:
error = "Lizenzschlüssel nicht gefunden"
elif status == 409:
error = "Lizenz ist bereits auf einem anderen System aktiviert"
elif status == 422:
error = "Ungültiges Lizenzformat"
elif status == 403:
error = "Lizenz ist deaktiviert oder abgelaufen"
logger.error(f"Lizenzaktivierung fehlgeschlagen: {error}")
return {
"success": False,
"error": error
}
except Exception as e:
logger.error(f"Fehler bei der Lizenzaktivierung: {e}")
return {
"success": False,
"error": f"Fehler bei der Aktivierung: {str(e)}"
}
def deactivate_license(self) -> Dict[str, Any]:
"""
Deaktiviert die aktuelle Lizenz.
Returns:
Dictionary mit Erfolg und Nachricht
"""
if not self.is_licensed():
return {
"success": False,
"error": "Keine aktive Lizenz vorhanden"
}
logger.info("Deaktiviere Lizenz...")
# Session beenden
if self.session_manager.is_session_active():
self.session_manager.end_session()
# TODO: API Call für Deaktivierung wenn implementiert
# Lokale Daten löschen
self.clear_license_data()
logger.info("Lizenz deaktiviert")
return {
"success": True,
"message": "Lizenz erfolgreich deaktiviert"
}
def start_session(self) -> bool:
"""
Startet eine Session für die aktuelle Lizenz.
Returns:
True wenn erfolgreich, False sonst
"""
if not self.is_licensed():
logger.warning("Keine gültige Lizenz für Session-Start")
return False
result = self.session_manager.start_session(
license_key=self.license_data["key"],
activation_id=self.license_data.get("activation_id")
)
return result.get("success", False)
def resume_session(self) -> bool:
"""
Versucht eine gespeicherte Session fortzusetzen.
Returns:
True wenn erfolgreich, False sonst
"""
return self.session_manager.resume_session()
def has_feature(self, feature: str) -> bool:
"""
Prüft, ob ein Feature in der Lizenz enthalten ist.
Args:
feature: Name des Features
Returns:
True, wenn das Feature verfügbar ist, sonst False
"""
if not self.is_licensed():
return False
# "all" bedeutet alle Features verfügbar
if "all" in self.license_data.get("features", []):
return True
return feature in self.license_data.get("features", [])
def _extract_features(self, license_info: Dict[str, Any]) -> List[str]:
"""
Extrahiert Features basierend auf dem Lizenztyp.
Args:
license_info: Lizenzinformationen vom Server
Returns:
Liste der verfügbaren Features
"""
license_type = license_info.get("type", "basic")
# Feature-Mapping basierend auf Lizenztyp
feature_map = {
"basic": ["account_creation", "basic_export"],
"premium": ["account_creation", "basic_export", "multi_account",
"proxy_rotation", "advanced_export"],
"enterprise": ["all"]
}
return feature_map.get(license_type, ["account_creation"])
def get_status_text(self) -> str:
"""
Gibt einen lesbaren Status-Text zurück.
Returns:
Status-Text
"""
status = self.license_data.get("status", "inactive")
if status == "active":
if self.license_data.get("expiry_date"):
try:
expiry = datetime.fromisoformat(self.license_data["expiry_date"])
days_left = (expiry - datetime.now()).days
if days_left > 0:
return f"Aktiv (noch {days_left} Tage)"
else:
return "Abgelaufen"
except:
pass
return "Aktiv (unbegrenzt)"
elif status == "trial":
if self.license_data.get("expiry_date"):
try:
expiry = datetime.fromisoformat(self.license_data["expiry_date"])
days_left = (expiry - datetime.now()).days
if days_left > 0:
return f"Testversion (noch {days_left} Tage)"
else:
return "Testversion abgelaufen"
except:
pass
return "Testversion"
return self.license_data.get("status_text", "Keine Lizenz aktiviert")
# Test-Funktion
if __name__ == "__main__":
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
print("=== License Manager Test ===\n")
# License Manager erstellen
license_mgr = LicenseManager()
# Lizenz-Info anzeigen
print("Aktuelle Lizenz-Info:")
info = license_mgr.get_license_info()
print(f" Status: {info.get('status')}")
print(f" Status-Text: {license_mgr.get_status_text()}")
print(f" Lizenzschlüssel: {info.get('key', 'Keine')}")
print(f" Aktivierungs-ID: {info.get('activation_id', 'Keine')}")
# Session-Status
print(f"\nSession aktiv: {license_mgr.session_manager.is_session_active()}")
print("\n=== Test abgeschlossen ===")