from django.db import models from django.contrib.auth import get_user_model from django.utils import timezone from django.core.exceptions import ValidationError User = get_user_model() class SteamAPIKey(models.Model): """Model to store Steam API key configuration - Admin only""" name = models.CharField( max_length=100, unique=True, help_text="Descriptive name for this API key (e.g., 'Production Key', 'Development Key')" ) api_key = models.CharField( max_length=64, help_text="Steam Web API key from https://steamcommunity.com/dev/apikey" ) is_active = models.BooleanField( default=True, help_text="Whether this API key should be used" ) description = models.TextField( blank=True, help_text="Optional description or notes about this API key" ) # Metadata created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) last_used = models.DateTimeField( null=True, blank=True, help_text="When this API key was last used" ) class Meta: verbose_name = "Steam API Key" verbose_name_plural = "Steam API Keys" ordering = ['-is_active', 'name'] def __str__(self): status = "Active" if self.is_active else "Inactive" return f"{self.name} ({status})" def clean(self): """Validate the API key format""" if self.api_key: # Steam API keys are typically 32 characters of hexadecimal if len(self.api_key) != 32: raise ValidationError("Steam API key should be 32 characters long") # Check if it's hexadecimal try: int(self.api_key, 16) except ValueError: raise ValidationError("Steam API key should contain only hexadecimal characters (0-9, A-F)") def save(self, *args, **kwargs): self.full_clean() super().save(*args, **kwargs) @classmethod def get_active_key(cls): """Get the currently active API key""" return cls.objects.filter(is_active=True).first() @property def masked_key(self): """Return a masked version of the API key for display""" if not self.api_key: return "" return f"{self.api_key[:8]}{'*' * 16}{self.api_key[-8:]}" class SteamCollection(models.Model): """Model representing a Steam Workshop collection""" # Basic collection info steam_id = models.CharField( max_length=50, unique=True, help_text="Steam collection ID from URL" ) url = models.URLField(help_text="Full Steam Workshop collection URL") title = models.CharField(max_length=255, blank=True, help_text="Collection title") description = models.TextField(blank=True, help_text="Collection description") # Author information author_name = models.CharField( max_length=100, blank=True, help_text="Steam username of collection creator" ) author_steam_id = models.CharField( max_length=50, blank=True, help_text="Steam ID of collection creator" ) # Collection metadata total_items = models.PositiveIntegerField( default=0, help_text="Number of items in collection" ) unique_visitors = models.PositiveIntegerField( default=0, help_text="Number of unique visitors" ) current_favorites = models.PositiveIntegerField( default=0, help_text="Current number of favorites" ) total_favorites = models.PositiveIntegerField( default=0, help_text="Total unique favorites" ) # Timestamps steam_created_date = models.DateTimeField( null=True, blank=True, help_text="When collection was created on Steam" ) steam_updated_date = models.DateTimeField( null=True, blank=True, help_text="When collection was last updated on Steam" ) # Local tracking created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) last_fetched = models.DateTimeField( null=True, blank=True, help_text="When data was last fetched from Steam" ) # Status is_active = models.BooleanField( default=True, help_text="Whether this collection is actively tracked" ) fetch_error = models.TextField( blank=True, help_text="Last error encountered when fetching data" ) class Meta: ordering = ["-created_at"] verbose_name = "Steam Collection" verbose_name_plural = "Steam Collections" def __str__(self): return f"{self.title or f'Collection {self.steam_id}'}" @property def steam_url(self): """Generate the Steam Workshop URL from steam_id""" return f"https://steamcommunity.com/workshop/filedetails/?id={self.steam_id}" class SteamCollectionItem(models.Model): """Model representing individual items within a Steam collection""" # Relationships collection = models.ForeignKey( SteamCollection, on_delete=models.CASCADE, related_name="items" ) # Item identification steam_item_id = models.CharField(max_length=50, help_text="Steam Workshop item ID") title = models.CharField(max_length=255, blank=True, help_text="Item title") # Author information author_name = models.CharField( max_length=100, blank=True, help_text="Steam username of item creator" ) author_steam_id = models.CharField( max_length=50, blank=True, help_text="Steam ID of item creator" ) # Item metadata description = models.TextField(blank=True, help_text="Item description") tags = models.JSONField( default=list, blank=True, help_text="Item tags as JSON array" ) # Position in collection order_index = models.PositiveIntegerField( default=0, help_text="Order of item in collection" ) # Timestamps created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["collection", "order_index"] unique_together = ["collection", "steam_item_id"] verbose_name = "Steam Collection Item" verbose_name_plural = "Steam Collection Items" def __str__(self): return f"{self.title or f'Item {self.steam_item_id}'} (in {self.collection})" @property def steam_url(self): """Generate the Steam Workshop URL for this item""" return ( f"https://steamcommunity.com/workshop/filedetails/?id={self.steam_item_id}" )