ttvdrops/twitch/migrations/0001_initial.py

996 lines
34 KiB
Python

# Generated by Django 6.0 on 2025-12-11 10:49
import django.db.models.deletion
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
"""Initial migration for Twitch-related models."""
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name="Game",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"twitch_id",
models.TextField(unique=True, verbose_name="Twitch game ID"),
),
(
"slug",
models.TextField(
blank=True,
default="",
help_text="Short unique identifier for the game.",
max_length=200,
verbose_name="Slug",
),
),
("name", models.TextField(blank=True, default="", verbose_name="Name")),
(
"display_name",
models.TextField(
blank=True,
default="",
verbose_name="Display name",
),
),
(
"box_art",
models.URLField(
blank=True,
default="",
max_length=500,
verbose_name="Box art URL",
),
),
(
"box_art_file",
models.FileField(
blank=True,
help_text="Locally cached box art image served from this site.",
null=True,
upload_to="games/box_art/",
),
),
(
"added_at",
models.DateTimeField(
auto_now_add=True,
help_text="Timestamp when this game record was created.",
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True,
help_text="Timestamp when this game record was last updated.",
),
),
],
options={"ordering": ["display_name"]},
),
migrations.CreateModel(
name="Channel",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"twitch_id",
models.TextField(
help_text="The unique Twitch identifier for the channel.",
unique=True,
verbose_name="Channel ID",
),
),
(
"name",
models.TextField(
help_text="The lowercase username of the channel.",
verbose_name="Username",
),
),
(
"display_name",
models.TextField(
help_text="The display name of the channel (with proper capitalization).",
verbose_name="Display Name",
),
),
(
"added_at",
models.DateTimeField(
auto_now_add=True,
help_text="Timestamp when this channel record was created.",
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True,
help_text="Timestamp when this channel record was last updated.",
),
),
],
options={
"ordering": ["display_name"],
"indexes": [
models.Index(
fields=["display_name"],
name="twitch_chan_display_2bf213_idx",
),
models.Index(fields=["name"], name="twitch_chan_name_15d566_idx"),
models.Index(
fields=["twitch_id"],
name="twitch_chan_twitch__c8bbc6_idx",
),
models.Index(
fields=["added_at"],
name="twitch_chan_added_a_5ce7b4_idx",
),
models.Index(
fields=["updated_at"],
name="twitch_chan_updated_828594_idx",
),
],
},
),
migrations.CreateModel(
name="DropBenefit",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"twitch_id",
models.TextField(
editable=False,
help_text="The Twitch ID for this benefit.",
unique=True,
),
),
(
"name",
models.TextField(
blank=True,
default="N/A",
help_text="Name of the drop benefit.",
),
),
(
"image_asset_url",
models.URLField(
blank=True,
default="",
help_text="URL to the benefit's image asset.",
max_length=500,
),
),
(
"image_file",
models.FileField(
blank=True,
help_text="Locally cached benefit image served from this site.",
null=True,
upload_to="benefits/images/",
),
),
(
"created_at",
models.DateTimeField(
help_text="Timestamp when the benefit was created. This is from Twitch API and not auto-generated.",
null=True,
),
),
(
"entitlement_limit",
models.PositiveIntegerField(
default=1,
help_text="Maximum number of times this benefit can be earned.",
),
),
(
"is_ios_available",
models.BooleanField(
default=False,
help_text="Whether the benefit is available on iOS.",
),
),
(
"distribution_type",
models.TextField(
blank=True,
default="",
help_text="Type of distribution for this benefit.",
max_length=50,
),
),
(
"added_at",
models.DateTimeField(
auto_now_add=True,
help_text="Timestamp when this benefit record was created.",
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True,
help_text="Timestamp when this benefit record was last updated.",
),
),
],
options={
"ordering": ["-created_at"],
"indexes": [
models.Index(
fields=["-created_at"],
name="twitch_drop_created_5d2280_idx",
),
models.Index(
fields=["twitch_id"],
name="twitch_drop_twitch__6eab58_idx",
),
models.Index(fields=["name"], name="twitch_drop_name_7125ff_idx"),
models.Index(
fields=["distribution_type"],
name="twitch_drop_distrib_08b224_idx",
),
models.Index(
fields=["is_ios_available"],
name="twitch_drop_is_ios__5f3dcf_idx",
),
models.Index(
fields=["added_at"],
name="twitch_drop_added_a_fba438_idx",
),
models.Index(
fields=["updated_at"],
name="twitch_drop_updated_7aaae3_idx",
),
],
},
),
migrations.CreateModel(
name="DropBenefitEdge",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"entitlement_limit",
models.PositiveIntegerField(
default=1,
help_text="Max times this benefit can be claimed for this drop.",
),
),
(
"added_at",
models.DateTimeField(
auto_now_add=True,
help_text="Timestamp when this drop-benefit edge was created.",
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True,
help_text="Timestamp when this drop-benefit edge was last updated.",
),
),
(
"benefit",
models.ForeignKey(
help_text="The benefit in this relationship.",
on_delete=django.db.models.deletion.CASCADE,
to="twitch.dropbenefit",
),
),
],
),
migrations.CreateModel(
name="DropCampaign",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"twitch_id",
models.TextField(
editable=False,
help_text="The Twitch ID for this campaign.",
unique=True,
),
),
("name", models.TextField(help_text="Name of the drop campaign.")),
(
"description",
models.TextField(
blank=True,
help_text="Detailed description of the campaign.",
),
),
(
"details_url",
models.URLField(
blank=True,
default="",
help_text="URL with campaign details.",
max_length=500,
),
),
(
"account_link_url",
models.URLField(
blank=True,
default="",
help_text="URL to link a Twitch account for the campaign.",
max_length=500,
),
),
(
"image_url",
models.URLField(
blank=True,
default="",
help_text="URL to an image representing the campaign.",
max_length=500,
),
),
(
"image_file",
models.FileField(
blank=True,
help_text="Locally cached campaign image served from this site.",
null=True,
upload_to="campaigns/images/",
),
),
(
"start_at",
models.DateTimeField(
blank=True,
help_text="Datetime when the campaign starts.",
null=True,
),
),
(
"end_at",
models.DateTimeField(
blank=True,
help_text="Datetime when the campaign ends.",
null=True,
),
),
(
"is_account_connected",
models.BooleanField(
default=False,
help_text="Indicates if the user account is linked.",
),
),
(
"allow_is_enabled",
models.BooleanField(
default=True,
help_text="Whether the campaign allows participation.",
),
),
(
"operation_name",
models.TextField(
blank=True,
default="",
help_text="The GraphQL operation name used to fetch this campaign data (e.g., 'ViewerDropsDashboard').",
),
),
(
"added_at",
models.DateTimeField(
auto_now_add=True,
help_text="Timestamp when this campaign record was created.",
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True,
help_text="Timestamp when this campaign record was last updated.",
),
),
(
"allow_channels",
models.ManyToManyField(
blank=True,
help_text="Channels that are allowed to participate in this campaign.",
related_name="allowed_campaigns",
to="twitch.channel",
),
),
(
"game",
models.ForeignKey(
help_text="Game associated with this campaign.",
on_delete=django.db.models.deletion.CASCADE,
related_name="drop_campaigns",
to="twitch.game",
verbose_name="Game",
),
),
],
options={"ordering": ["-start_at"]},
),
migrations.CreateModel(
name="Organization",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"twitch_id",
models.TextField(
editable=False,
help_text="The unique Twitch identifier for the organization.",
unique=True,
verbose_name="Organization ID",
),
),
(
"name",
models.TextField(
help_text="Display name of the organization.",
unique=True,
verbose_name="Name",
),
),
(
"added_at",
models.DateTimeField(
auto_now_add=True,
help_text="Timestamp when this organization record was created.",
verbose_name="Added At",
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True,
help_text="Timestamp when this organization record was last updated.",
verbose_name="Updated At",
),
),
],
options={
"ordering": ["name"],
"indexes": [
models.Index(fields=["name"], name="twitch_orga_name_febe72_idx"),
models.Index(
fields=["twitch_id"],
name="twitch_orga_twitch__b89b29_idx",
),
models.Index(
fields=["added_at"],
name="twitch_orga_added_a_8297ac_idx",
),
models.Index(
fields=["updated_at"],
name="twitch_orga_updated_d7d431_idx",
),
],
},
),
migrations.AddField(
model_name="game",
name="owner",
field=models.ForeignKey(
blank=True,
help_text="The organization that owns this game.",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="games",
to="twitch.organization",
verbose_name="Organization",
),
),
migrations.CreateModel(
name="TimeBasedDrop",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"twitch_id",
models.TextField(
editable=False,
help_text="The Twitch ID for this time-based drop.",
unique=True,
),
),
("name", models.TextField(help_text="Name of the time-based drop.")),
(
"required_minutes_watched",
models.PositiveIntegerField(
blank=True,
help_text="Minutes required to watch before earning this drop.",
null=True,
),
),
(
"required_subs",
models.PositiveIntegerField(
default=0,
help_text="Number of subscriptions required to unlock this drop.",
),
),
(
"start_at",
models.DateTimeField(
blank=True,
help_text="Datetime when this drop becomes available.",
null=True,
),
),
(
"end_at",
models.DateTimeField(
blank=True,
help_text="Datetime when this drop expires.",
null=True,
),
),
(
"added_at",
models.DateTimeField(
auto_now_add=True,
help_text="Timestamp when this time-based drop record was created.",
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True,
help_text="Timestamp when this time-based drop record was last updated.",
),
),
(
"benefits",
models.ManyToManyField(
help_text="Benefits unlocked by this drop.",
related_name="drops",
through="twitch.DropBenefitEdge",
to="twitch.dropbenefit",
),
),
(
"campaign",
models.ForeignKey(
help_text="The campaign this drop belongs to.",
on_delete=django.db.models.deletion.CASCADE,
related_name="time_based_drops",
to="twitch.dropcampaign",
),
),
],
options={"ordering": ["start_at"]},
),
migrations.AddField(
model_name="dropbenefitedge",
name="drop",
field=models.ForeignKey(
help_text="The time-based drop in this relationship.",
on_delete=django.db.models.deletion.CASCADE,
to="twitch.timebaseddrop",
),
),
migrations.CreateModel(
name="TwitchGameData",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"twitch_id",
models.TextField(
help_text="The Twitch ID for this game.",
unique=True,
verbose_name="Twitch Game ID",
),
),
("name", models.TextField(blank=True, default="", verbose_name="Name")),
(
"box_art_url",
models.URLField(
blank=True,
default="",
help_text="URL template with {width}x{height} placeholders for the box art image.",
max_length=500,
verbose_name="Box art URL",
),
),
(
"igdb_id",
models.TextField(blank=True, default="", verbose_name="IGDB ID"),
),
(
"added_at",
models.DateTimeField(
auto_now_add=True,
help_text="Record creation time.",
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True,
help_text="Record last update time.",
),
),
(
"game",
models.ForeignKey(
blank=True,
help_text="Optional link to the local Game record for this Twitch game.",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="twitch_game_data",
to="twitch.game",
verbose_name="Game",
),
),
],
options={"ordering": ["name"]},
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(
fields=["-start_at"],
name="twitch_drop_start_a_929f09_idx",
),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(fields=["end_at"], name="twitch_drop_end_at_6560b0_idx"),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(fields=["game"], name="twitch_drop_game_id_868e70_idx"),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(
fields=["twitch_id"],
name="twitch_drop_twitch__b717a1_idx",
),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(fields=["name"], name="twitch_drop_name_3b70b3_idx"),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(
fields=["description"],
name="twitch_drop_descrip_5bc290_idx",
),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(
fields=["is_account_connected"],
name="twitch_drop_is_acco_7e9078_idx",
),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(
fields=["allow_is_enabled"],
name="twitch_drop_allow_i_b64555_idx",
),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(
fields=["operation_name"],
name="twitch_drop_operati_8cfeb5_idx",
),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(
fields=["added_at"],
name="twitch_drop_added_a_babe28_idx",
),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(
fields=["updated_at"],
name="twitch_drop_updated_0df991_idx",
),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(
fields=["game", "-start_at"],
name="twitch_drop_game_id_5e9b01_idx",
),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(
fields=["start_at", "end_at"],
name="twitch_drop_start_a_6e5fb6_idx",
),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(
fields=["start_at", "end_at", "game"],
name="twitch_drop_start_a_b02d4c_idx",
),
),
migrations.AddIndex(
model_name="dropcampaign",
index=models.Index(
fields=["end_at", "-start_at"],
name="twitch_drop_end_at_81e51b_idx",
),
),
migrations.AddIndex(
model_name="game",
index=models.Index(
fields=["display_name"],
name="twitch_game_display_a35ba3_idx",
),
),
migrations.AddIndex(
model_name="game",
index=models.Index(fields=["name"], name="twitch_game_name_c92c15_idx"),
),
migrations.AddIndex(
model_name="game",
index=models.Index(fields=["slug"], name="twitch_game_slug_a02d3c_idx"),
),
migrations.AddIndex(
model_name="game",
index=models.Index(
fields=["twitch_id"],
name="twitch_game_twitch__887f78_idx",
),
),
migrations.AddIndex(
model_name="game",
index=models.Index(fields=["owner"], name="twitch_game_owner_i_398fa9_idx"),
),
migrations.AddIndex(
model_name="game",
index=models.Index(
fields=["added_at"],
name="twitch_game_added_a_9e7e19_idx",
),
),
migrations.AddIndex(
model_name="game",
index=models.Index(
fields=["updated_at"],
name="twitch_game_updated_01df03_idx",
),
),
migrations.AddIndex(
model_name="game",
index=models.Index(
fields=["owner", "display_name"],
name="twitch_game_owner_i_7f9043_idx",
),
),
migrations.AddIndex(
model_name="timebaseddrop",
index=models.Index(
fields=["start_at"],
name="twitch_time_start_a_13de4a_idx",
),
),
migrations.AddIndex(
model_name="timebaseddrop",
index=models.Index(fields=["end_at"], name="twitch_time_end_at_3df95a_idx"),
),
migrations.AddIndex(
model_name="timebaseddrop",
index=models.Index(
fields=["campaign"],
name="twitch_time_campaig_bbe349_idx",
),
),
migrations.AddIndex(
model_name="timebaseddrop",
index=models.Index(
fields=["twitch_id"],
name="twitch_time_twitch__31707a_idx",
),
),
migrations.AddIndex(
model_name="timebaseddrop",
index=models.Index(fields=["name"], name="twitch_time_name_47c0f4_idx"),
),
migrations.AddIndex(
model_name="timebaseddrop",
index=models.Index(
fields=["required_minutes_watched"],
name="twitch_time_require_82c30c_idx",
),
),
migrations.AddIndex(
model_name="timebaseddrop",
index=models.Index(
fields=["required_subs"],
name="twitch_time_require_959431_idx",
),
),
migrations.AddIndex(
model_name="timebaseddrop",
index=models.Index(
fields=["added_at"],
name="twitch_time_added_a_a7de2e_idx",
),
),
migrations.AddIndex(
model_name="timebaseddrop",
index=models.Index(
fields=["updated_at"],
name="twitch_time_updated_9e9d9e_idx",
),
),
migrations.AddIndex(
model_name="timebaseddrop",
index=models.Index(
fields=["campaign", "start_at"],
name="twitch_time_campaig_29ac87_idx",
),
),
migrations.AddIndex(
model_name="timebaseddrop",
index=models.Index(
fields=["campaign", "required_minutes_watched"],
name="twitch_time_campaig_920ae4_idx",
),
),
migrations.AddIndex(
model_name="timebaseddrop",
index=models.Index(
fields=["start_at", "end_at"],
name="twitch_time_start_a_c481f1_idx",
),
),
migrations.AddIndex(
model_name="dropbenefitedge",
index=models.Index(fields=["drop"], name="twitch_drop_drop_id_3a2994_idx"),
),
migrations.AddIndex(
model_name="dropbenefitedge",
index=models.Index(
fields=["benefit"],
name="twitch_drop_benefit_c92c87_idx",
),
),
migrations.AddIndex(
model_name="dropbenefitedge",
index=models.Index(
fields=["entitlement_limit"],
name="twitch_drop_entitle_bee3a0_idx",
),
),
migrations.AddIndex(
model_name="dropbenefitedge",
index=models.Index(
fields=["added_at"],
name="twitch_drop_added_a_2100ba_idx",
),
),
migrations.AddIndex(
model_name="dropbenefitedge",
index=models.Index(
fields=["updated_at"],
name="twitch_drop_updated_00e3f2_idx",
),
),
migrations.AddConstraint(
model_name="dropbenefitedge",
constraint=models.UniqueConstraint(
fields=("drop", "benefit"),
name="unique_drop_benefit",
),
),
migrations.AddIndex(
model_name="twitchgamedata",
index=models.Index(fields=["name"], name="twitch_twit_name_5dda5f_idx"),
),
migrations.AddIndex(
model_name="twitchgamedata",
index=models.Index(
fields=["twitch_id"],
name="twitch_twit_twitch__2207e6_idx",
),
),
migrations.AddIndex(
model_name="twitchgamedata",
index=models.Index(fields=["game"], name="twitch_twit_game_id_0d820a_idx"),
),
migrations.AddIndex(
model_name="twitchgamedata",
index=models.Index(
fields=["igdb_id"],
name="twitch_twit_igdb_id_161335_idx",
),
),
migrations.AddIndex(
model_name="twitchgamedata",
index=models.Index(
fields=["added_at"],
name="twitch_twit_added_a_2f4f36_idx",
),
),
migrations.AddIndex(
model_name="twitchgamedata",
index=models.Index(
fields=["updated_at"],
name="twitch_twit_updated_ca8c4b_idx",
),
),
]