X-Problem gelöst
Dieser Commit ist enthalten in:
74
domain/entities/platform.py
Normale Datei
74
domain/entities/platform.py
Normale Datei
@ -0,0 +1,74 @@
|
||||
"""
|
||||
Platform Entity - Represents a social media platform
|
||||
"""
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional, Dict, Any
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class PlatformStatus(Enum):
|
||||
"""Platform availability status"""
|
||||
ENABLED = "enabled"
|
||||
DISABLED = "disabled"
|
||||
UPCOMING = "upcoming"
|
||||
|
||||
|
||||
@dataclass
|
||||
class Platform:
|
||||
"""
|
||||
Platform entity representing a social media platform.
|
||||
Clean Architecture: Domain Entity
|
||||
"""
|
||||
id: str
|
||||
display_name: str
|
||||
status: PlatformStatus
|
||||
icon: str
|
||||
color: str
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str,
|
||||
display_name: str,
|
||||
enabled: bool = True,
|
||||
icon: str = None,
|
||||
color: str = "#000000"
|
||||
):
|
||||
self.id = id
|
||||
self.display_name = display_name
|
||||
self.status = PlatformStatus.ENABLED if enabled else PlatformStatus.DISABLED
|
||||
self.icon = icon or f"{id}.svg"
|
||||
self.color = color
|
||||
|
||||
@property
|
||||
def is_enabled(self) -> bool:
|
||||
"""Check if platform is enabled"""
|
||||
return self.status == PlatformStatus.ENABLED
|
||||
|
||||
@property
|
||||
def is_disabled(self) -> bool:
|
||||
"""Check if platform is disabled"""
|
||||
return self.status == PlatformStatus.DISABLED
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""Convert to dictionary"""
|
||||
return {
|
||||
'id': self.id,
|
||||
'display_name': self.display_name,
|
||||
'status': self.status.value,
|
||||
'icon': self.icon,
|
||||
'color': self.color
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> 'Platform':
|
||||
"""Create from dictionary"""
|
||||
return cls(
|
||||
id=data.get('id'),
|
||||
display_name=data.get('display_name'),
|
||||
enabled=data.get('enabled', True),
|
||||
icon=data.get('icon'),
|
||||
color=data.get('color', '#000000')
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Platform(id={self.id}, name={self.display_name}, status={self.status.value})"
|
||||
160
domain/value_objects/platform_name.py
Normale Datei
160
domain/value_objects/platform_name.py
Normale Datei
@ -0,0 +1,160 @@
|
||||
"""
|
||||
Platform Name Value Object - Standardisiert Platform-Namen
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class PlatformName:
|
||||
"""
|
||||
Value Object für standardisierte Platform-Namen.
|
||||
Stellt sicher, dass Platform-Namen konsistent behandelt werden.
|
||||
"""
|
||||
|
||||
# Mapping von verschiedenen Schreibweisen zu kanonischen Namen
|
||||
PLATFORM_MAPPINGS = {
|
||||
# Kanonische Namen (für DB und interne Verwendung)
|
||||
'instagram': 'instagram',
|
||||
'facebook': 'facebook',
|
||||
'tiktok': 'tiktok',
|
||||
'x': 'x',
|
||||
'gmail': 'gmail',
|
||||
'vk': 'vk',
|
||||
'ok': 'ok',
|
||||
|
||||
# Alternative Schreibweisen
|
||||
'X': 'x',
|
||||
'twitter': 'x',
|
||||
'Twitter': 'x',
|
||||
'X (Twitter)': 'x',
|
||||
'ok.ru': 'ok',
|
||||
'OK.ru': 'ok',
|
||||
'VK': 'vk',
|
||||
'Gmail': 'gmail',
|
||||
'Instagram': 'instagram',
|
||||
'Facebook': 'facebook',
|
||||
'TikTok': 'tiktok'
|
||||
}
|
||||
|
||||
# Display-Namen für UI
|
||||
DISPLAY_NAMES = {
|
||||
'instagram': 'Instagram',
|
||||
'facebook': 'Facebook',
|
||||
'tiktok': 'TikTok',
|
||||
'x': 'X',
|
||||
'gmail': 'Gmail',
|
||||
'vk': 'VK',
|
||||
'ok': 'OK.ru'
|
||||
}
|
||||
|
||||
def __init__(self, name: str):
|
||||
"""
|
||||
Initialisiert ein PlatformName Value Object.
|
||||
|
||||
Args:
|
||||
name: Platform-Name in beliebiger Schreibweise
|
||||
"""
|
||||
self._canonical_name = self._normalize(name)
|
||||
if not self._canonical_name:
|
||||
raise ValueError(f"Unknown platform: {name}")
|
||||
|
||||
def _normalize(self, name: str) -> Optional[str]:
|
||||
"""
|
||||
Normalisiert einen Platform-Namen zu seiner kanonischen Form.
|
||||
|
||||
Args:
|
||||
name: Platform-Name in beliebiger Schreibweise
|
||||
|
||||
Returns:
|
||||
Kanonischer Platform-Name oder None
|
||||
"""
|
||||
if not name:
|
||||
return None
|
||||
|
||||
# Trimmen und in Mapping suchen
|
||||
normalized = name.strip()
|
||||
return self.PLATFORM_MAPPINGS.get(normalized, self.PLATFORM_MAPPINGS.get(normalized.lower()))
|
||||
|
||||
@property
|
||||
def canonical(self) -> str:
|
||||
"""
|
||||
Gibt den kanonischen Namen zurück (für DB und interne Verwendung).
|
||||
Immer lowercase.
|
||||
"""
|
||||
return self._canonical_name
|
||||
|
||||
@property
|
||||
def display(self) -> str:
|
||||
"""
|
||||
Gibt den Display-Namen zurück (für UI).
|
||||
Mit korrekter Groß-/Kleinschreibung.
|
||||
"""
|
||||
return self.DISPLAY_NAMES.get(self._canonical_name, self._canonical_name.title())
|
||||
|
||||
@property
|
||||
def db_value(self) -> str:
|
||||
"""
|
||||
Gibt den Wert für Datenbank-Speicherung zurück.
|
||||
Alias für canonical.
|
||||
"""
|
||||
return self.canonical
|
||||
|
||||
def matches(self, other: str) -> bool:
|
||||
"""
|
||||
Prüft, ob ein anderer Platform-Name diesem entspricht.
|
||||
|
||||
Args:
|
||||
other: Zu vergleichender Platform-Name
|
||||
|
||||
Returns:
|
||||
True wenn die Platforms übereinstimmen
|
||||
"""
|
||||
other_normalized = self._normalize(other)
|
||||
return other_normalized == self._canonical_name if other_normalized else False
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""String-Repräsentation (Display-Name)."""
|
||||
return self.display
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""Debug-Repräsentation."""
|
||||
return f"PlatformName(canonical='{self.canonical}', display='{self.display}')"
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
"""Gleichheitsvergleich."""
|
||||
if isinstance(other, PlatformName):
|
||||
return self._canonical_name == other._canonical_name
|
||||
elif isinstance(other, str):
|
||||
return self.matches(other)
|
||||
return False
|
||||
|
||||
def __hash__(self) -> int:
|
||||
"""Hash-Wert für Set/Dict-Verwendung."""
|
||||
return hash(self._canonical_name)
|
||||
|
||||
@classmethod
|
||||
def is_valid(cls, name: str) -> bool:
|
||||
"""
|
||||
Prüft, ob ein Platform-Name gültig ist.
|
||||
|
||||
Args:
|
||||
name: Zu prüfender Platform-Name
|
||||
|
||||
Returns:
|
||||
True wenn der Name gültig ist
|
||||
"""
|
||||
try:
|
||||
cls(name)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def get_all_canonical(cls) -> list:
|
||||
"""
|
||||
Gibt alle kanonischen Platform-Namen zurück.
|
||||
|
||||
Returns:
|
||||
Liste aller kanonischen Platform-Namen
|
||||
"""
|
||||
return list(set(cls.PLATFORM_MAPPINGS.values()))
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren