from __future__ import annotations import logging from typing import ClassVar import auto_prefetch from django.contrib.auth.models import AbstractUser from django.db import models logger: logging.Logger = logging.getLogger(__name__) class User(AbstractUser): """Custom user model.""" class Meta: ordering: ClassVar[list[str]] = ["username"] def __str__(self) -> str: """Return the username.""" return self.username class ScrapedJson(auto_prefetch.Model): """The JSON data from the Twitch API. This data is from https://github.com/TheLovinator1/TwitchDropsMiner. """ json_data = models.JSONField(unique=True, help_text="The JSON data from the Twitch API.") created_at = models.DateTimeField(auto_now_add=True) modified_at = models.DateTimeField(auto_now=True) imported_at = models.DateTimeField(null=True) class Meta(auto_prefetch.Model.Meta): ordering: ClassVar[list[str]] = ["-created_at"] def __str__(self) -> str: """Return the created at date and optionally if not imported yet.""" return f"{'' if self.imported_at else 'Not imported - '}{self.created_at}" class Organization(auto_prefetch.Model): """Represents the owner/organization of a Drop Campaign.""" org_id = models.TextField(primary_key=True, unique=True, help_text="The Twitch ID of the owner.") name = models.TextField(blank=True, help_text="The name of the owner.") created_at = models.DateTimeField(auto_now_add=True) modified_at = models.DateTimeField(auto_now=True) class Meta(auto_prefetch.Model.Meta): ordering: ClassVar[list[str]] = ["name"] def __str__(self) -> str: """Return the name of the owner.""" return f"{self.name or self.org_id} - {self.created_at}" class Game(auto_prefetch.Model): """The game the drop campaign is for. Note that some reward campaigns are not tied to a game.""" game_id = models.TextField(primary_key=True, help_text="The Twitch ID of the game.") game_url = models.URLField(blank=True, help_text="The URL to the game on Twitch.") display_name = models.TextField(blank=True, help_text="The display name of the game.") box_art_url = models.URLField(blank=True, help_text="URL to the box art of the game.") slug = models.SlugField(blank=True, help_text="The slug for the game.") created_at = models.DateTimeField(auto_now_add=True, help_text="When the game was first added to the database.") modified_at = models.DateTimeField(auto_now=True, help_text="When the game was last modified.") class Meta(auto_prefetch.Model.Meta): ordering: ClassVar[list[str]] = ["display_name"] def __str__(self) -> str: """Return the name of the game and when it was created.""" return f"{self.display_name or self.game_id} - {self.created_at}" class DropCampaign(auto_prefetch.Model): """This is the drop campaign we will see on the front end.""" campaign_id = models.TextField(primary_key=True, unique=True, help_text="The Twitch ID of the drop campaign.") account_link_url = models.URLField(blank=True, help_text="The URL to link accounts for the drop campaign.") description = models.TextField(blank=True, help_text="The description of the drop campaign.") details_url = models.URLField(blank=True, help_text="The URL to the details of the drop campaign.") end_at = models.DateTimeField(null=True, help_text="When the drop campaign ends.") start_at = models.DateTimeField(null=True, help_text="When the drop campaign starts.") image_url = models.URLField(blank=True, help_text="The URL to the image for the drop campaign.") name = models.TextField(blank=True, help_text="The name of the drop campaign.") status = models.TextField(blank=True, help_text="The status of the drop campaign.") game = auto_prefetch.ForeignKey( to=Game, help_text="The game associated with this campaign", null=True, on_delete=models.SET_NULL, related_name="drop_campaigns", ) owner = auto_prefetch.ForeignKey( Organization, help_text="The organization running this campaign", null=True, on_delete=models.SET_NULL, related_name="drop_campaigns", ) created_at = models.DateTimeField( auto_now_add=True, help_text="When the drop campaign was first added to the database.", ) modified_at = models.DateTimeField(auto_now=True, help_text="When the drop campaign was last modified.") class Meta(auto_prefetch.Model.Meta): ordering: ClassVar[list[str]] = ["end_at"] def __str__(self) -> str: """Return the name of the drop campaign and when it was created.""" return f"{self.name or self.campaign_id} - {self.created_at}" class Benefit(auto_prefetch.Model): """Represents a specific reward/benefit within a Drop.""" benefit_id = models.TextField(primary_key=True, unique=True, help_text="Twitch's unique ID for the benefit") twitch_created_at = models.DateTimeField(null=True, help_text="When the benefit was created on Twitch.") entitlement_limit = models.PositiveBigIntegerField( default=1, help_text="How many times this benefit can be claimed per user", ) image_asset_url = models.URLField(blank=True, help_text="The URL to the image for the benefit.") is_ios_available = models.BooleanField(null=True, help_text="If the benefit is farmable on iOS.") name = models.TextField(blank=True, help_text="Name of the benefit/reward") game = auto_prefetch.ForeignKey(Game, on_delete=models.SET_NULL, related_name="benefits", null=True) owner_organization = auto_prefetch.ForeignKey( Organization, on_delete=models.SET_NULL, related_name="benefits", null=True, ) distribution_type = models.TextField(blank=True, help_text="The distribution type of the benefit.") created_at = models.DateTimeField(auto_now_add=True) modified_at = models.DateTimeField(auto_now=True) class Meta(auto_prefetch.Model.Meta): ordering: ClassVar[list[str]] = ["-twitch_created_at"] def __str__(self) -> str: """Return the name of the benefit and when it was created.""" return f"{self.name or self.benefit_id} - {self.twitch_created_at}" class TimeBasedDrop(auto_prefetch.Model): """Represents a time-based drop within a Campaign.""" drop_id = models.TextField(primary_key=True, unique=True, help_text="The Twitch ID of the drop.") required_subs = models.PositiveBigIntegerField(null=True, help_text="The number of subs required for the drop.") ends_at = models.DateTimeField(null=True, help_text="When the drop ends.") name = models.TextField(blank=True, help_text="Name of the time-based drop") required_minutes_watched = models.PositiveBigIntegerField( null=True, help_text="The number of minutes watched required.", ) start_at = models.DateTimeField(help_text="Drop start time") end_at = models.DateTimeField(help_text="Drop end time") campaign = auto_prefetch.ForeignKey( DropCampaign, help_text="The campaign this drop belongs to", on_delete=models.CASCADE, related_name="time_based_drops", ) benefits = models.ManyToManyField( Benefit, related_name="time_based_drops", help_text="Benefits awarded by this drop", ) created_at = models.DateTimeField(auto_now_add=True, help_text="When the drop was first added to the database.") modified_at = models.DateTimeField(auto_now=True, help_text="When the drop was last modified.") class Meta(auto_prefetch.Model.Meta): ordering: ClassVar[list[str]] = ["required_minutes_watched"] def __str__(self) -> str: """Return the name of the drop and when it was created.""" return f"{self.name or self.drop_id} - {self.created_at}"