Add WIP
This commit is contained in:
@ -1,7 +0,0 @@
|
|||||||
from django.contrib import admin
|
|
||||||
from simple_history.admin import SimpleHistoryAdmin
|
|
||||||
|
|
||||||
from .models import Webhook
|
|
||||||
|
|
||||||
# https://django-simple-history.readthedocs.io/en/latest/admin.html
|
|
||||||
admin.site.register(Webhook, SimpleHistoryAdmin)
|
|
@ -1,62 +0,0 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-06-30 23:42
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
from django.db.migrations.operations.base import Operation
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies: list[tuple[str, str]] = [
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations: list[Operation] = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="NotificationType",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"id",
|
|
||||||
models.BigAutoField(
|
|
||||||
auto_created=True,
|
|
||||||
primary_key=True,
|
|
||||||
serialize=False,
|
|
||||||
verbose_name="ID",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("name", models.CharField(max_length=255)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="DiscordSetting",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"id",
|
|
||||||
models.BigAutoField(
|
|
||||||
auto_created=True,
|
|
||||||
primary_key=True,
|
|
||||||
serialize=False,
|
|
||||||
verbose_name="ID",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("webhook_url", models.URLField()),
|
|
||||||
("disabled", models.BooleanField(default=False)),
|
|
||||||
(
|
|
||||||
"user",
|
|
||||||
models.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
to=settings.AUTH_USER_MODEL,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"notification_type",
|
|
||||||
models.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
to="core.notificationtype",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,26 +0,0 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-07-01 01:10
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
from django.db.migrations.operations.base import Operation
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies: list[tuple[str, str]] = [
|
|
||||||
("core", "0001_initial"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations: list[Operation] = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name="discordsetting",
|
|
||||||
name="notification_type",
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="discordsetting",
|
|
||||||
name="name",
|
|
||||||
field=models.CharField(default="No name", max_length=255),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.DeleteModel(
|
|
||||||
name="NotificationType",
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,53 +0,0 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-07-01 03:28
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
from django.db.migrations.operations.base import Operation
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies: list[tuple[str, str]] = [
|
|
||||||
("core", "0002_remove_discordsetting_notification_type_and_more"),
|
|
||||||
("twitch_app", "0001_initial"),
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations: list[Operation] = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="Subscription",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"id",
|
|
||||||
models.BigAutoField(
|
|
||||||
auto_created=True,
|
|
||||||
primary_key=True,
|
|
||||||
serialize=False,
|
|
||||||
verbose_name="ID",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
||||||
(
|
|
||||||
"discord_webhook",
|
|
||||||
models.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
to="core.discordsetting",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"game",
|
|
||||||
models.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
to="twitch_app.game",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"user",
|
|
||||||
models.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
to=settings.AUTH_USER_MODEL,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,146 +0,0 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-07-01 15:17
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
import simple_history.models
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
from django.db.migrations.operations.base import Operation
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies: list[tuple[str, str]] = [
|
|
||||||
("core", "0003_subscription"),
|
|
||||||
("twitch_app", "0003_historicaldropbenefit_historicaldropcampaign_and_more"),
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations: list[Operation] = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="HistoricalDiscordSetting",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"id",
|
|
||||||
models.BigIntegerField(
|
|
||||||
auto_created=True,
|
|
||||||
blank=True,
|
|
||||||
db_index=True,
|
|
||||||
verbose_name="ID",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("name", models.CharField(max_length=255)),
|
|
||||||
("webhook_url", models.URLField()),
|
|
||||||
("disabled", models.BooleanField(default=False)),
|
|
||||||
("history_id", models.AutoField(primary_key=True, serialize=False)),
|
|
||||||
("history_date", models.DateTimeField(db_index=True)),
|
|
||||||
("history_change_reason", models.CharField(max_length=100, null=True)),
|
|
||||||
(
|
|
||||||
"history_type",
|
|
||||||
models.CharField(
|
|
||||||
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
|
|
||||||
max_length=1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"history_user",
|
|
||||||
models.ForeignKey(
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.SET_NULL,
|
|
||||||
related_name="+",
|
|
||||||
to=settings.AUTH_USER_MODEL,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"user",
|
|
||||||
models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
db_constraint=False,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
||||||
related_name="+",
|
|
||||||
to=settings.AUTH_USER_MODEL,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "historical discord setting",
|
|
||||||
"verbose_name_plural": "historical discord settings",
|
|
||||||
"ordering": ("-history_date", "-history_id"),
|
|
||||||
"get_latest_by": ("history_date", "history_id"),
|
|
||||||
},
|
|
||||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="HistoricalSubscription",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"id",
|
|
||||||
models.BigIntegerField(
|
|
||||||
auto_created=True,
|
|
||||||
blank=True,
|
|
||||||
db_index=True,
|
|
||||||
verbose_name="ID",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("created_at", models.DateTimeField(blank=True, editable=False)),
|
|
||||||
("history_id", models.AutoField(primary_key=True, serialize=False)),
|
|
||||||
("history_date", models.DateTimeField(db_index=True)),
|
|
||||||
("history_change_reason", models.CharField(max_length=100, null=True)),
|
|
||||||
(
|
|
||||||
"history_type",
|
|
||||||
models.CharField(
|
|
||||||
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
|
|
||||||
max_length=1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"discord_webhook",
|
|
||||||
models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
db_constraint=False,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
||||||
related_name="+",
|
|
||||||
to="core.discordsetting",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"game",
|
|
||||||
models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
db_constraint=False,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
||||||
related_name="+",
|
|
||||||
to="twitch_app.game",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"history_user",
|
|
||||||
models.ForeignKey(
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.SET_NULL,
|
|
||||||
related_name="+",
|
|
||||||
to=settings.AUTH_USER_MODEL,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"user",
|
|
||||||
models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
db_constraint=False,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
||||||
related_name="+",
|
|
||||||
to=settings.AUTH_USER_MODEL,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "historical subscription",
|
|
||||||
"verbose_name_plural": "historical subscriptions",
|
|
||||||
"ordering": ("-history_date", "-history_id"),
|
|
||||||
"get_latest_by": ("history_date", "history_id"),
|
|
||||||
},
|
|
||||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,33 +0,0 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-07-01 21:47
|
|
||||||
|
|
||||||
import django.utils.timezone
|
|
||||||
from django.db import migrations, models
|
|
||||||
from django.db.migrations.operations.base import Operation
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies: list[tuple[str, str]] = [
|
|
||||||
("core", "0004_historicaldiscordsetting_historicalsubscription"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations: list[Operation] = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="discordsetting",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
auto_now_add=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="historicaldiscordsetting",
|
|
||||||
name="created_at",
|
|
||||||
field=models.DateTimeField(
|
|
||||||
blank=True,
|
|
||||||
default=django.utils.timezone.now,
|
|
||||||
editable=False,
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,26 +0,0 @@
|
|||||||
from typing import Literal
|
|
||||||
|
|
||||||
import auto_prefetch
|
|
||||||
from django.db import models
|
|
||||||
from simple_history.models import HistoricalRecords
|
|
||||||
|
|
||||||
from twitch_app.models import Game
|
|
||||||
|
|
||||||
|
|
||||||
class Webhook(auto_prefetch.Model):
|
|
||||||
"""Webhooks to send notifications to."""
|
|
||||||
|
|
||||||
url = models.URLField(unique=True)
|
|
||||||
game = models.ForeignKey(Game, on_delete=models.CASCADE)
|
|
||||||
disabled = models.BooleanField(default=False)
|
|
||||||
added_at = models.DateTimeField(blank=True, null=True, auto_now_add=True)
|
|
||||||
modified_at = models.DateTimeField(blank=True, null=True, auto_now=True)
|
|
||||||
history = HistoricalRecords()
|
|
||||||
|
|
||||||
class Meta(auto_prefetch.Model.Meta):
|
|
||||||
verbose_name: str = "Webhook"
|
|
||||||
verbose_name_plural: str = "Webhooks"
|
|
||||||
ordering: tuple[Literal["url"]] = ("url",)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return self.url
|
|
@ -5,6 +5,10 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3">{% include "partials/toc.html" %}</div>
|
<div class="col-lg-3">{% include "partials/toc.html" %}</div>
|
||||||
<div class="col-lg-9">
|
<div class="col-lg-9">
|
||||||
|
{% for org in orgs %}
|
||||||
|
{{ org }}
|
||||||
|
fsafa
|
||||||
|
{% endfor %}
|
||||||
{% include "partials/info_box.html" %}
|
{% include "partials/info_box.html" %}
|
||||||
{% include "partials/news.html" %}
|
{% include "partials/news.html" %}
|
||||||
{% for game in games %}
|
{% for game in games %}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import datetime
|
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
@ -9,17 +8,15 @@ from django.conf import settings
|
|||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
|
|
||||||
from core.data import CampaignContext, DropContext, GameContext, WebhookData
|
from core.data import WebhookData
|
||||||
from twitch_app.models import (
|
from twitch_app.models import (
|
||||||
DropBenefit,
|
Organization,
|
||||||
DropCampaign,
|
|
||||||
Game,
|
|
||||||
TimeBasedDrop,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from django.db.models.manager import BaseManager
|
||||||
from django.http import (
|
from django.http import (
|
||||||
HttpRequest,
|
HttpRequest,
|
||||||
HttpResponse,
|
HttpResponse,
|
||||||
@ -44,111 +41,12 @@ controller = hishel.Controller(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def fetch_campaigns(game: Game) -> list[CampaignContext]:
|
|
||||||
"""Fetch active campaigns for a given game."""
|
|
||||||
campaigns: list[CampaignContext] = []
|
|
||||||
for campaign in DropCampaign.objects.filter(
|
|
||||||
game=game,
|
|
||||||
status="ACTIVE",
|
|
||||||
end_at__gt=datetime.datetime.now(tz=datetime.UTC),
|
|
||||||
).only(
|
|
||||||
"id",
|
|
||||||
"name",
|
|
||||||
"image_url",
|
|
||||||
"status",
|
|
||||||
"account_link_url",
|
|
||||||
"description",
|
|
||||||
"details_url",
|
|
||||||
"start_at",
|
|
||||||
"end_at",
|
|
||||||
):
|
|
||||||
drops = fetch_drops(campaign)
|
|
||||||
if not drops:
|
|
||||||
logger.info("No drops found for %s", campaign.name)
|
|
||||||
continue
|
|
||||||
|
|
||||||
campaigns.append(
|
|
||||||
CampaignContext(
|
|
||||||
drop_id=campaign.id,
|
|
||||||
name=campaign.name,
|
|
||||||
image_url=campaign.image_url,
|
|
||||||
status=campaign.status,
|
|
||||||
account_link_url=campaign.account_link_url,
|
|
||||||
description=campaign.description,
|
|
||||||
details_url=campaign.details_url,
|
|
||||||
start_at=campaign.start_at,
|
|
||||||
end_at=campaign.end_at,
|
|
||||||
drops=drops,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
return campaigns
|
|
||||||
|
|
||||||
|
|
||||||
def fetch_drops(campaign: DropCampaign) -> list[DropContext]:
|
|
||||||
"""Fetch drops for a given campaign."""
|
|
||||||
drops: list[DropContext] = []
|
|
||||||
drop: TimeBasedDrop
|
|
||||||
for drop in campaign.time_based_drops.all().only(
|
|
||||||
"id",
|
|
||||||
"name",
|
|
||||||
"required_minutes_watched",
|
|
||||||
"required_subs",
|
|
||||||
):
|
|
||||||
benefit: DropBenefit | None = drop.benefits.first()
|
|
||||||
|
|
||||||
image_asset_url: str = "https://static-cdn.jtvnw.net/twitch-quests-assets/CAMPAIGN/default.png"
|
|
||||||
if benefit and benefit.image_asset_url:
|
|
||||||
image_asset_url = benefit.image_asset_url
|
|
||||||
|
|
||||||
drops.append(
|
|
||||||
DropContext(
|
|
||||||
drops_id=drop.id,
|
|
||||||
image_url=image_asset_url,
|
|
||||||
name=drop.name,
|
|
||||||
required_minutes_watched=drop.required_minutes_watched,
|
|
||||||
required_subs=drop.required_subs,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
return drops
|
|
||||||
|
|
||||||
|
|
||||||
def sort_games_by_campaign_start(list_of_games: list[GameContext]) -> list[GameContext]:
|
|
||||||
"""Sort games by the start date of the first campaign and reverse the list so the latest games are first."""
|
|
||||||
if list_of_games and list_of_games[0].campaigns:
|
|
||||||
list_of_games.sort(
|
|
||||||
key=lambda x: x.campaigns[0].start_at
|
|
||||||
if x.campaigns and x.campaigns[0].start_at is not None
|
|
||||||
else datetime.datetime.min,
|
|
||||||
)
|
|
||||||
list_of_games.reverse()
|
|
||||||
return list_of_games
|
|
||||||
|
|
||||||
|
|
||||||
def get_webhooks(request: HttpRequest) -> list[str]:
|
def get_webhooks(request: HttpRequest) -> list[str]:
|
||||||
"""Get the webhooks from the cookie."""
|
"""Get the webhooks from the cookie."""
|
||||||
cookie: str = request.COOKIES.get("webhooks", "")
|
cookie: str = request.COOKIES.get("webhooks", "")
|
||||||
return list(filter(None, cookie.split(",")))
|
return list(filter(None, cookie.split(",")))
|
||||||
|
|
||||||
|
|
||||||
def prepare_game_contexts() -> list[GameContext]:
|
|
||||||
"""Prepare game contexts with their respective campaigns and drops."""
|
|
||||||
list_of_games: list[GameContext] = []
|
|
||||||
for game in list(Game.objects.all().only("id", "image_url", "display_name", "slug")):
|
|
||||||
campaigns: list[CampaignContext] = fetch_campaigns(game)
|
|
||||||
if not campaigns:
|
|
||||||
continue
|
|
||||||
list_of_games.append(
|
|
||||||
GameContext(
|
|
||||||
game_id=game.id,
|
|
||||||
campaigns=campaigns,
|
|
||||||
image_url=game.image_url,
|
|
||||||
display_name=game.display_name,
|
|
||||||
twitch_url=game.twitch_url,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
return list_of_games
|
|
||||||
|
|
||||||
|
|
||||||
def get_avatar(webhook_response: Response) -> str:
|
def get_avatar(webhook_response: Response) -> str:
|
||||||
"""Get the avatar URL from the webhook response."""
|
"""Get the avatar URL from the webhook response."""
|
||||||
avatar: str = "https://cdn.discordapp.com/embed/avatars/0.png"
|
avatar: str = "https://cdn.discordapp.com/embed/avatars/0.png"
|
||||||
@ -173,12 +71,11 @@ def get_webhook_data(webhook: str) -> WebhookData:
|
|||||||
|
|
||||||
def index(request: HttpRequest) -> HttpResponse:
|
def index(request: HttpRequest) -> HttpResponse:
|
||||||
"""Render the index page."""
|
"""Render the index page."""
|
||||||
list_of_games: list[GameContext] = prepare_game_contexts()
|
orgs: BaseManager[Organization] = Organization.objects.all()
|
||||||
sorted_list_of_games: list[GameContext] = sort_games_by_campaign_start(list_of_games)
|
|
||||||
webhooks: list[WebhookData] = [get_webhook_data(webhook) for webhook in get_webhooks(request)]
|
webhooks: list[WebhookData] = [get_webhook_data(webhook) for webhook in get_webhooks(request)]
|
||||||
|
|
||||||
return TemplateResponse(
|
return TemplateResponse(
|
||||||
request=request,
|
request=request,
|
||||||
template="index.html",
|
template="index.html",
|
||||||
context={"games": sorted_list_of_games, "webhooks": webhooks},
|
context={"orgs": orgs, "webhooks": webhooks},
|
||||||
)
|
)
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from simple_history.admin import SimpleHistoryAdmin
|
from simple_history.admin import SimpleHistoryAdmin
|
||||||
|
|
||||||
from .models import DropBenefit, DropCampaign, Game, Organization, TimeBasedDrop
|
from .models import Drop, DropCampaign, Game, Organization
|
||||||
|
|
||||||
# https://django-simple-history.readthedocs.io/en/latest/admin.html
|
# https://django-simple-history.readthedocs.io/en/latest/admin.html
|
||||||
admin.site.register(DropBenefit, SimpleHistoryAdmin)
|
admin.site.register(Drop, SimpleHistoryAdmin)
|
||||||
admin.site.register(DropCampaign, SimpleHistoryAdmin)
|
admin.site.register(DropCampaign, SimpleHistoryAdmin)
|
||||||
admin.site.register(Game, SimpleHistoryAdmin)
|
admin.site.register(Game, SimpleHistoryAdmin)
|
||||||
admin.site.register(Organization, SimpleHistoryAdmin)
|
admin.site.register(Organization, SimpleHistoryAdmin)
|
||||||
admin.site.register(TimeBasedDrop, SimpleHistoryAdmin)
|
|
||||||
|
@ -5,11 +5,10 @@ from django.http import HttpRequest
|
|||||||
from ninja import Router, Schema
|
from ninja import Router, Schema
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
DropBenefit,
|
Drop,
|
||||||
DropCampaign,
|
DropCampaign,
|
||||||
Game,
|
Game,
|
||||||
Organization,
|
Organization,
|
||||||
TimeBasedDrop,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
router = Router(
|
router = Router(
|
||||||
@ -98,13 +97,6 @@ def get_games(request: HttpRequest) -> BaseManager[Game]: # noqa: ARG001
|
|||||||
return Game.objects.all()
|
return Game.objects.all()
|
||||||
|
|
||||||
|
|
||||||
# http://localhost:8000/api/twitch/drop_benefits
|
|
||||||
@router.get("/drop_benefits", response=list[DropBenefitSchema])
|
|
||||||
def get_drop_benefits(request: HttpRequest) -> BaseManager[DropBenefit]: # noqa: ARG001
|
|
||||||
"""Get all drop benefits."""
|
|
||||||
return DropBenefit.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
# http://localhost:8000/api/twitch/drop_campaigns
|
# http://localhost:8000/api/twitch/drop_campaigns
|
||||||
@router.get("/drop_campaigns", response=list[DropCampaignSchema])
|
@router.get("/drop_campaigns", response=list[DropCampaignSchema])
|
||||||
def get_drop_campaigns(request: HttpRequest) -> BaseManager[DropCampaign]: # noqa: ARG001
|
def get_drop_campaigns(request: HttpRequest) -> BaseManager[DropCampaign]: # noqa: ARG001
|
||||||
@ -112,8 +104,8 @@ def get_drop_campaigns(request: HttpRequest) -> BaseManager[DropCampaign]: # no
|
|||||||
return DropCampaign.objects.all()
|
return DropCampaign.objects.all()
|
||||||
|
|
||||||
|
|
||||||
# http://localhost:8000/api/twitch/time_based_drops
|
# http://localhost:8000/api/twitch/drops
|
||||||
@router.get("/time_based_drops", response=list[TimeBasedDropSchema])
|
@router.get("/drops", response=list[TimeBasedDropSchema])
|
||||||
def get_time_based_drops(request: HttpRequest) -> BaseManager[TimeBasedDrop]: # noqa: ARG001
|
def get_drops(request: HttpRequest) -> BaseManager[Drop]: # noqa: ARG001
|
||||||
"""Get all time-based drops."""
|
"""Get all time-based drops."""
|
||||||
return TimeBasedDrop.objects.all()
|
return Drop.objects.all()
|
||||||
|
@ -11,11 +11,10 @@ from playwright.async_api import Playwright, async_playwright
|
|||||||
from playwright.async_api._generated import Response
|
from playwright.async_api._generated import Response
|
||||||
|
|
||||||
from twitch_app.models import (
|
from twitch_app.models import (
|
||||||
DropBenefit,
|
Drop,
|
||||||
DropCampaign,
|
DropCampaign,
|
||||||
Game,
|
Game,
|
||||||
Organization,
|
Organization,
|
||||||
TimeBasedDrop,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -35,10 +34,10 @@ if not data_dir:
|
|||||||
msg = "DATA_DIR is not set in settings.py"
|
msg = "DATA_DIR is not set in settings.py"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
logger: logging.Logger = logging.getLogger("twitch.management.commands.scrape_twitch")
|
logger: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
async def insert_data(data: dict) -> None: # noqa: PLR0914, C901
|
async def insert_data(data: dict) -> None: # noqa: C901, PLR0914
|
||||||
"""Insert data into the database.
|
"""Insert data into the database.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -52,6 +51,7 @@ async def insert_data(data: dict) -> None: # noqa: PLR0914, C901
|
|||||||
user_data["id"]
|
user_data["id"]
|
||||||
drop_campaign_data = user_data["dropCampaign"]
|
drop_campaign_data = user_data["dropCampaign"]
|
||||||
if not drop_campaign_data:
|
if not drop_campaign_data:
|
||||||
|
logger.debug("No drop campaign data found")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Create or get the organization
|
# Create or get the organization
|
||||||
@ -62,6 +62,8 @@ async def insert_data(data: dict) -> None: # noqa: PLR0914, C901
|
|||||||
)
|
)
|
||||||
if created:
|
if created:
|
||||||
logger.debug("Organization created: %s", owner)
|
logger.debug("Organization created: %s", owner)
|
||||||
|
else:
|
||||||
|
logger.debug("Organization found: %s", owner)
|
||||||
|
|
||||||
# Create or get the game
|
# Create or get the game
|
||||||
game_data = drop_campaign_data["game"]
|
game_data = drop_campaign_data["game"]
|
||||||
@ -70,6 +72,7 @@ async def insert_data(data: dict) -> None: # noqa: PLR0914, C901
|
|||||||
defaults={
|
defaults={
|
||||||
"slug": game_data["slug"],
|
"slug": game_data["slug"],
|
||||||
"display_name": game_data["displayName"],
|
"display_name": game_data["displayName"],
|
||||||
|
"organization": owner,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if created:
|
if created:
|
||||||
@ -79,16 +82,15 @@ async def insert_data(data: dict) -> None: # noqa: PLR0914, C901
|
|||||||
drop_campaign, created = await sync_to_async(DropCampaign.objects.get_or_create)(
|
drop_campaign, created = await sync_to_async(DropCampaign.objects.get_or_create)(
|
||||||
id=drop_campaign_data["id"],
|
id=drop_campaign_data["id"],
|
||||||
defaults={
|
defaults={
|
||||||
"account_link_url": drop_campaign_data["accountLinkURL"],
|
"account_link_url": drop_campaign_data.get("accountLinkURL"),
|
||||||
"description": drop_campaign_data["description"],
|
"description": drop_campaign_data.get("description"),
|
||||||
"details_url": drop_campaign_data["detailsURL"],
|
"details_url": drop_campaign_data.get("detailsURL"),
|
||||||
"end_at": drop_campaign_data["endAt"],
|
"end_at": drop_campaign_data.get("endAt"),
|
||||||
"image_url": drop_campaign_data["imageURL"],
|
"image_url": drop_campaign_data.get("imageURL"),
|
||||||
"name": drop_campaign_data["name"],
|
"name": drop_campaign_data.get("name"),
|
||||||
"start_at": drop_campaign_data["startAt"],
|
"start_at": drop_campaign_data.get("startAt"),
|
||||||
"status": drop_campaign_data["status"],
|
"status": drop_campaign_data.get("status"),
|
||||||
"game": game,
|
"game": game,
|
||||||
"owner": owner,
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if created:
|
if created:
|
||||||
@ -97,62 +99,58 @@ async def insert_data(data: dict) -> None: # noqa: PLR0914, C901
|
|||||||
# Create time-based drops
|
# Create time-based drops
|
||||||
for drop_data in drop_campaign_data["timeBasedDrops"]:
|
for drop_data in drop_campaign_data["timeBasedDrops"]:
|
||||||
drop_benefit_edges = drop_data["benefitEdges"]
|
drop_benefit_edges = drop_data["benefitEdges"]
|
||||||
drop_benefits = []
|
|
||||||
|
time_based_drop, created = await sync_to_async(Drop.objects.get_or_create)(
|
||||||
|
id=drop_data["id"],
|
||||||
|
defaults={
|
||||||
|
"required_subs": drop_data.get("requiredSubs"),
|
||||||
|
"end_at": drop_data.get("endAt"),
|
||||||
|
"name": drop_data.get("name"),
|
||||||
|
"required_minutes_watched": drop_data.get("requiredMinutesWatched"),
|
||||||
|
"start_at": drop_data.get("startAt"),
|
||||||
|
"drop_campaign": drop_campaign,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if created:
|
||||||
|
logger.debug("Time-based drop created: %s", time_based_drop)
|
||||||
|
|
||||||
for edge in drop_benefit_edges:
|
for edge in drop_benefit_edges:
|
||||||
benefit_data = edge["benefit"]
|
benefit_data = edge["benefit"]
|
||||||
benefit_owner_data = benefit_data["ownerOrganization"]
|
benefit_owner_data = benefit_data["ownerOrganization"]
|
||||||
|
|
||||||
benefit_owner, created = await sync_to_async(
|
org, created = await sync_to_async(
|
||||||
Organization.objects.get_or_create,
|
Organization.objects.get_or_create,
|
||||||
)(
|
)(
|
||||||
id=benefit_owner_data["id"],
|
id=benefit_owner_data["id"],
|
||||||
defaults={"name": benefit_owner_data["name"]},
|
defaults={"name": benefit_owner_data["name"]},
|
||||||
)
|
)
|
||||||
if created:
|
if created:
|
||||||
logger.debug("Benefit owner created: %s", benefit_owner)
|
logger.debug("Organization created: %s", org)
|
||||||
|
|
||||||
benefit_game_data = benefit_data["game"]
|
benefit_game_data = benefit_data["game"]
|
||||||
benefit_game, created = await sync_to_async(Game.objects.get_or_create)(
|
benefit_game, created = await sync_to_async(Game.objects.get_or_create)(
|
||||||
id=benefit_game_data["id"],
|
id=benefit_game_data["id"],
|
||||||
defaults={"name": benefit_game_data["name"]},
|
defaults={"display_name": benefit_game_data["name"]},
|
||||||
)
|
)
|
||||||
if created:
|
if created:
|
||||||
logger.debug("Benefit game created: %s", benefit_game)
|
logger.debug("Benefit game created: %s", benefit_game)
|
||||||
|
|
||||||
benefit, created = await sync_to_async(DropBenefit.objects.get_or_create)(
|
# Get the drop to add the data to
|
||||||
id=benefit_data["id"],
|
drop, created = await sync_to_async(Drop.objects.get_or_create)(
|
||||||
|
id=drop_data["id"],
|
||||||
defaults={
|
defaults={
|
||||||
"created_at": benefit_data["createdAt"],
|
"created_at": benefit_data.get("createdAt"),
|
||||||
"entitlement_limit": benefit_data["entitlementLimit"],
|
"entitlement_limit": benefit_data.get("entitlementLimit"),
|
||||||
"image_asset_url": benefit_data["imageAssetURL"],
|
"image_asset_url": benefit_data.get("imageAssetURL"),
|
||||||
"is_ios_available": benefit_data["isIosAvailable"],
|
"is_ios_available": benefit_data.get("isIosAvailable"),
|
||||||
"name": benefit_data["name"],
|
"name": benefit_data.get("name"),
|
||||||
"owner_organization": benefit_owner,
|
"owner_organization": org,
|
||||||
"game": benefit_game,
|
"game": benefit_game,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
drop_benefits.append(benefit)
|
|
||||||
if created:
|
if created:
|
||||||
logger.debug("Benefit created: %s", benefit)
|
logger.debug("Drop created: %s", drop)
|
||||||
|
|
||||||
time_based_drop, created = await sync_to_async(
|
|
||||||
TimeBasedDrop.objects.get_or_create,
|
|
||||||
)(
|
|
||||||
id=drop_data["id"],
|
|
||||||
defaults={
|
|
||||||
"required_subs": drop_data["requiredSubs"],
|
|
||||||
"end_at": drop_data["endAt"],
|
|
||||||
"name": drop_data["name"],
|
|
||||||
"required_minutes_watched": drop_data["requiredMinutesWatched"],
|
|
||||||
"start_at": drop_data["startAt"],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
await sync_to_async(time_based_drop.benefits.set)(drop_benefits)
|
|
||||||
await sync_to_async(drop_campaign.time_based_drops.add)(time_based_drop)
|
|
||||||
|
|
||||||
if created:
|
|
||||||
logger.debug("Time-based drop created: %s", time_based_drop)
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
@ -162,18 +160,20 @@ class Command(BaseCommand):
|
|||||||
self,
|
self,
|
||||||
playwright: Playwright,
|
playwright: Playwright,
|
||||||
) -> list[dict[str, typing.Any]]:
|
) -> list[dict[str, typing.Any]]:
|
||||||
profile_dir: Path = Path(data_dir / "firefox-profile")
|
profile_dir: Path = Path(data_dir / "chrome-profile")
|
||||||
profile_dir.mkdir(parents=True, exist_ok=True)
|
profile_dir.mkdir(parents=True, exist_ok=True)
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Launching Firefox browser with user data directory: %s",
|
"Launching Chrome browser with user data directory: %s",
|
||||||
profile_dir,
|
profile_dir,
|
||||||
)
|
)
|
||||||
|
|
||||||
browser: BrowserContext = await playwright.firefox.launch_persistent_context(
|
browser: BrowserContext = await playwright.chromium.launch_persistent_context(
|
||||||
user_data_dir=profile_dir,
|
user_data_dir=profile_dir,
|
||||||
headless=True,
|
headless=False,
|
||||||
|
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36", # noqa: E501
|
||||||
|
viewport={"width": 1920, "height": 1080},
|
||||||
)
|
)
|
||||||
logger.debug("Launched Firefox browser")
|
logger.debug("Launched Chrome browser")
|
||||||
|
|
||||||
page: Page = await browser.new_page()
|
page: Page = await browser.new_page()
|
||||||
json_data: list[dict] = []
|
json_data: list[dict] = []
|
||||||
@ -198,7 +198,7 @@ class Command(BaseCommand):
|
|||||||
try:
|
try:
|
||||||
await page.wait_for_selector(
|
await page.wait_for_selector(
|
||||||
'div[data-a-target="top-nav-avatar"]',
|
'div[data-a-target="top-nav-avatar"]',
|
||||||
timeout=30000,
|
timeout=300000,
|
||||||
)
|
)
|
||||||
logged_in = True
|
logged_in = True
|
||||||
logger.info("Logged in to Twitch")
|
logger.info("Logged in to Twitch")
|
||||||
@ -211,6 +211,9 @@ class Command(BaseCommand):
|
|||||||
await page.wait_for_load_state("networkidle")
|
await page.wait_for_load_state("networkidle")
|
||||||
logger.debug("Page loaded. Scraping data...")
|
logger.debug("Page loaded. Scraping data...")
|
||||||
|
|
||||||
|
# Wait 5 seconds for the page to load
|
||||||
|
await asyncio.sleep(5)
|
||||||
|
|
||||||
await browser.close()
|
await browser.close()
|
||||||
|
|
||||||
for num, campaign in enumerate(json_data, start=1):
|
for num, campaign in enumerate(json_data, start=1):
|
||||||
|
@ -1,17 +1,45 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-07-01 00:08
|
# Generated by Django 5.1b1 on 2024-07-09 22:26
|
||||||
|
|
||||||
|
import auto_prefetch
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
import django.db.models.functions.text
|
import django.db.models.functions.text
|
||||||
|
import django.db.models.manager
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
from django.db.migrations.operations.base import Operation
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies: list[tuple[str, str]] = []
|
dependencies = []
|
||||||
|
|
||||||
operations: list[Operation] = [
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="DropCampaign",
|
||||||
|
fields=[
|
||||||
|
("id", models.TextField(primary_key=True, serialize=False)),
|
||||||
|
("account_link_url", models.URLField(blank=True, null=True)),
|
||||||
|
("description", models.TextField(blank=True, null=True)),
|
||||||
|
("details_url", models.URLField(blank=True, null=True)),
|
||||||
|
("end_at", models.DateTimeField(blank=True, null=True)),
|
||||||
|
("image_url", models.URLField(blank=True, null=True)),
|
||||||
|
("name", models.TextField(blank=True, null=True)),
|
||||||
|
("start_at", models.DateTimeField(blank=True, null=True)),
|
||||||
|
("status", models.TextField(blank=True, null=True)),
|
||||||
|
("added_at", models.DateTimeField(auto_now_add=True, null=True)),
|
||||||
|
("modified_at", models.DateTimeField(auto_now=True, null=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Drop Campaign",
|
||||||
|
"verbose_name_plural": "Drop Campaigns",
|
||||||
|
"ordering": ("name",),
|
||||||
|
"abstract": False,
|
||||||
|
"base_manager_name": "prefetch_manager",
|
||||||
|
},
|
||||||
|
managers=[
|
||||||
|
("objects", django.db.models.manager.Manager()),
|
||||||
|
("prefetch_manager", django.db.models.manager.Manager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="Game",
|
name="Game",
|
||||||
fields=[
|
fields=[
|
||||||
@ -28,10 +56,33 @@ class Migration(migrations.Migration):
|
|||||||
output_field=models.TextField(),
|
output_field=models.TextField(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"image_url",
|
||||||
|
models.GeneratedField( # type: ignore # noqa: PGH003
|
||||||
|
db_persist=True,
|
||||||
|
expression=django.db.models.functions.text.Concat(
|
||||||
|
models.Value("https://static-cdn.jtvnw.net/ttv-boxart/"),
|
||||||
|
"id",
|
||||||
|
models.Value("_IGDB.jpg"),
|
||||||
|
),
|
||||||
|
output_field=models.URLField(),
|
||||||
|
),
|
||||||
|
),
|
||||||
("display_name", models.TextField(blank=True, null=True)),
|
("display_name", models.TextField(blank=True, null=True)),
|
||||||
("added_at", models.DateTimeField(auto_now_add=True, null=True)),
|
("added_at", models.DateTimeField(auto_now_add=True, null=True)),
|
||||||
("modified_at", models.DateTimeField(auto_now=True, null=True)),
|
("modified_at", models.DateTimeField(auto_now=True, null=True)),
|
||||||
],
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Game",
|
||||||
|
"verbose_name_plural": "Games",
|
||||||
|
"ordering": ("display_name",),
|
||||||
|
"abstract": False,
|
||||||
|
"base_manager_name": "prefetch_manager",
|
||||||
|
},
|
||||||
|
managers=[
|
||||||
|
("objects", django.db.models.manager.Manager()),
|
||||||
|
("prefetch_manager", django.db.models.manager.Manager()),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="Organization",
|
name="Organization",
|
||||||
@ -41,97 +92,69 @@ class Migration(migrations.Migration):
|
|||||||
("added_at", models.DateTimeField(auto_now_add=True, null=True)),
|
("added_at", models.DateTimeField(auto_now_add=True, null=True)),
|
||||||
("modified_at", models.DateTimeField(auto_now=True, null=True)),
|
("modified_at", models.DateTimeField(auto_now=True, null=True)),
|
||||||
],
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Organization",
|
||||||
|
"verbose_name_plural": "Organizations",
|
||||||
|
"ordering": ("name",),
|
||||||
|
"abstract": False,
|
||||||
|
"base_manager_name": "prefetch_manager",
|
||||||
|
},
|
||||||
|
managers=[
|
||||||
|
("objects", django.db.models.manager.Manager()),
|
||||||
|
("prefetch_manager", django.db.models.manager.Manager()),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="DropBenefit",
|
name="Drop",
|
||||||
fields=[
|
fields=[
|
||||||
("id", models.TextField(primary_key=True, serialize=False)),
|
("id", models.TextField(primary_key=True, serialize=False)),
|
||||||
("created_at", models.DateTimeField(blank=True, null=True)),
|
("created_at", models.DateTimeField(blank=True, null=True)),
|
||||||
("entitlement_limit", models.IntegerField(blank=True, null=True)),
|
("entitlement_limit", models.IntegerField(blank=True, null=True)),
|
||||||
("image_asset_url", models.URLField(blank=True, null=True)),
|
("image_asset_url", models.URLField(blank=True, null=True)),
|
||||||
("is_ios_available", models.BooleanField(blank=True, null=True)),
|
|
||||||
("name", models.TextField(blank=True, null=True)),
|
("name", models.TextField(blank=True, null=True)),
|
||||||
("added_at", models.DateTimeField(auto_now_add=True, null=True)),
|
("added_at", models.DateTimeField(auto_now_add=True, null=True)),
|
||||||
("modified_at", models.DateTimeField(auto_now=True, null=True)),
|
("modified_at", models.DateTimeField(auto_now=True, null=True)),
|
||||||
(
|
|
||||||
"game",
|
|
||||||
models.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
to="twitch_app.game",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"owner_organization",
|
|
||||||
models.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
to="twitch_app.organization",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="TimeBasedDrop",
|
|
||||||
fields=[
|
|
||||||
("id", models.TextField(primary_key=True, serialize=False)),
|
|
||||||
("required_subs", models.IntegerField(blank=True, null=True)),
|
("required_subs", models.IntegerField(blank=True, null=True)),
|
||||||
("end_at", models.DateTimeField(blank=True, null=True)),
|
("end_at", models.DateTimeField(blank=True, null=True)),
|
||||||
("name", models.TextField(blank=True, null=True)),
|
("required_minutes_watched", models.IntegerField(blank=True, null=True)),
|
||||||
(
|
|
||||||
"required_minutes_watched",
|
|
||||||
models.IntegerField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
("start_at", models.DateTimeField(blank=True, null=True)),
|
("start_at", models.DateTimeField(blank=True, null=True)),
|
||||||
("added_at", models.DateTimeField(auto_now_add=True, null=True)),
|
|
||||||
("modified_at", models.DateTimeField(auto_now=True, null=True)),
|
|
||||||
("benefits", models.ManyToManyField(to="twitch_app.dropbenefit")),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="DropCampaign",
|
|
||||||
fields=[
|
|
||||||
("id", models.TextField(primary_key=True, serialize=False)),
|
|
||||||
("account_link_url", models.URLField(blank=True, null=True)),
|
|
||||||
("description", models.TextField(blank=True, null=True)),
|
|
||||||
("details_url", models.URLField(blank=True, null=True)),
|
|
||||||
("end_at", models.DateTimeField(blank=True, null=True)),
|
|
||||||
("image_url", models.URLField(blank=True, null=True)),
|
|
||||||
("name", models.TextField(blank=True, null=True)),
|
|
||||||
("start_at", models.DateTimeField(blank=True, null=True)),
|
|
||||||
("status", models.TextField(blank=True, null=True)),
|
|
||||||
("added_at", models.DateTimeField(auto_now_add=True, null=True)),
|
|
||||||
("modified_at", models.DateTimeField(auto_now=True, null=True)),
|
|
||||||
(
|
(
|
||||||
"game",
|
"drop_campaign",
|
||||||
models.ForeignKey(
|
auto_prefetch.ForeignKey(
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
related_name="drop_campaigns",
|
related_name="drops",
|
||||||
to="twitch_app.game",
|
to="twitch_app.dropcampaign",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
],
|
||||||
"owner",
|
options={
|
||||||
models.ForeignKey(
|
"verbose_name": "Drop",
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
"verbose_name_plural": "Drops",
|
||||||
related_name="drop_campaigns",
|
"ordering": ("name",),
|
||||||
to="twitch_app.organization",
|
"abstract": False,
|
||||||
),
|
"base_manager_name": "prefetch_manager",
|
||||||
),
|
},
|
||||||
(
|
managers=[
|
||||||
"time_based_drops",
|
("objects", django.db.models.manager.Manager()),
|
||||||
models.ManyToManyField(to="twitch_app.timebaseddrop"),
|
("prefetch_manager", django.db.models.manager.Manager()),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.AddField(
|
||||||
name="User",
|
model_name="dropcampaign",
|
||||||
fields=[
|
name="game",
|
||||||
("id", models.TextField(primary_key=True, serialize=False)),
|
field=auto_prefetch.ForeignKey(
|
||||||
("added_at", models.DateTimeField(auto_now_add=True, null=True)),
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
("modified_at", models.DateTimeField(auto_now=True, null=True)),
|
related_name="drop_campaigns",
|
||||||
(
|
to="twitch_app.game",
|
||||||
"drop_campaigns",
|
),
|
||||||
models.ManyToManyField(to="twitch_app.dropcampaign"),
|
),
|
||||||
),
|
migrations.AddField(
|
||||||
],
|
model_name="game",
|
||||||
|
name="organization",
|
||||||
|
field=auto_prefetch.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="games",
|
||||||
|
to="twitch_app.organization",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-07-01 03:49
|
|
||||||
|
|
||||||
import django.db.models.functions.text
|
|
||||||
from django.db import migrations, models
|
|
||||||
from django.db.migrations.operations.base import Operation
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies: list[tuple[str, str]] = [
|
|
||||||
("twitch_app", "0001_initial"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations: list[Operation] = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="game",
|
|
||||||
name="image_url",
|
|
||||||
field=models.GeneratedField( # type: ignore # noqa: PGH003
|
|
||||||
db_persist=True,
|
|
||||||
expression=django.db.models.functions.text.Concat(
|
|
||||||
models.Value("https://static-cdn.jtvnw.net/ttv-boxart/"),
|
|
||||||
"id",
|
|
||||||
models.Value("_IGDB.jpg"),
|
|
||||||
),
|
|
||||||
output_field=models.URLField(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,308 +0,0 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-07-01 15:17
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
import django.db.models.functions.text
|
|
||||||
import simple_history.models
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
from django.db.migrations.operations.base import Operation
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies: list[tuple[str, str]] = [
|
|
||||||
("twitch_app", "0002_game_image_url"),
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations: list[Operation] = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="HistoricalDropBenefit",
|
|
||||||
fields=[
|
|
||||||
("id", models.TextField(db_index=True)),
|
|
||||||
("created_at", models.DateTimeField(blank=True, null=True)),
|
|
||||||
("entitlement_limit", models.IntegerField(blank=True, null=True)),
|
|
||||||
("image_asset_url", models.URLField(blank=True, null=True)),
|
|
||||||
("is_ios_available", models.BooleanField(blank=True, null=True)),
|
|
||||||
("name", models.TextField(blank=True, null=True)),
|
|
||||||
(
|
|
||||||
"added_at",
|
|
||||||
models.DateTimeField(blank=True, editable=False, null=True),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"modified_at",
|
|
||||||
models.DateTimeField(blank=True, editable=False, null=True),
|
|
||||||
),
|
|
||||||
("history_id", models.AutoField(primary_key=True, serialize=False)),
|
|
||||||
("history_date", models.DateTimeField(db_index=True)),
|
|
||||||
("history_change_reason", models.CharField(max_length=100, null=True)),
|
|
||||||
(
|
|
||||||
"history_type",
|
|
||||||
models.CharField(
|
|
||||||
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
|
|
||||||
max_length=1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"game",
|
|
||||||
models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
db_constraint=False,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
||||||
related_name="+",
|
|
||||||
to="twitch_app.game",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"history_user",
|
|
||||||
models.ForeignKey(
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.SET_NULL,
|
|
||||||
related_name="+",
|
|
||||||
to=settings.AUTH_USER_MODEL,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"owner_organization",
|
|
||||||
models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
db_constraint=False,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
||||||
related_name="+",
|
|
||||||
to="twitch_app.organization",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "historical drop benefit",
|
|
||||||
"verbose_name_plural": "historical drop benefits",
|
|
||||||
"ordering": ("-history_date", "-history_id"),
|
|
||||||
"get_latest_by": ("history_date", "history_id"),
|
|
||||||
},
|
|
||||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="HistoricalDropCampaign",
|
|
||||||
fields=[
|
|
||||||
("id", models.TextField(db_index=True)),
|
|
||||||
("account_link_url", models.URLField(blank=True, null=True)),
|
|
||||||
("description", models.TextField(blank=True, null=True)),
|
|
||||||
("details_url", models.URLField(blank=True, null=True)),
|
|
||||||
("end_at", models.DateTimeField(blank=True, null=True)),
|
|
||||||
("image_url", models.URLField(blank=True, null=True)),
|
|
||||||
("name", models.TextField(blank=True, null=True)),
|
|
||||||
("start_at", models.DateTimeField(blank=True, null=True)),
|
|
||||||
("status", models.TextField(blank=True, null=True)),
|
|
||||||
(
|
|
||||||
"added_at",
|
|
||||||
models.DateTimeField(blank=True, editable=False, null=True),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"modified_at",
|
|
||||||
models.DateTimeField(blank=True, editable=False, null=True),
|
|
||||||
),
|
|
||||||
("history_id", models.AutoField(primary_key=True, serialize=False)),
|
|
||||||
("history_date", models.DateTimeField(db_index=True)),
|
|
||||||
("history_change_reason", models.CharField(max_length=100, null=True)),
|
|
||||||
(
|
|
||||||
"history_type",
|
|
||||||
models.CharField(
|
|
||||||
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
|
|
||||||
max_length=1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"game",
|
|
||||||
models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
db_constraint=False,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
||||||
related_name="+",
|
|
||||||
to="twitch_app.game",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"history_user",
|
|
||||||
models.ForeignKey(
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.SET_NULL,
|
|
||||||
related_name="+",
|
|
||||||
to=settings.AUTH_USER_MODEL,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"owner",
|
|
||||||
models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
db_constraint=False,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
||||||
related_name="+",
|
|
||||||
to="twitch_app.organization",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "historical drop campaign",
|
|
||||||
"verbose_name_plural": "historical drop campaigns",
|
|
||||||
"ordering": ("-history_date", "-history_id"),
|
|
||||||
"get_latest_by": ("history_date", "history_id"),
|
|
||||||
},
|
|
||||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="HistoricalGame",
|
|
||||||
fields=[
|
|
||||||
("id", models.TextField(db_index=True)),
|
|
||||||
("slug", models.TextField(blank=True, null=True)),
|
|
||||||
(
|
|
||||||
"twitch_url",
|
|
||||||
models.GeneratedField( # type: ignore # noqa: PGH003
|
|
||||||
db_persist=True,
|
|
||||||
expression=django.db.models.functions.text.Concat(
|
|
||||||
models.Value("https://www.twitch.tv/directory/category/"),
|
|
||||||
"slug",
|
|
||||||
),
|
|
||||||
output_field=models.TextField(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"image_url",
|
|
||||||
models.GeneratedField( # type: ignore # noqa: PGH003
|
|
||||||
db_persist=True,
|
|
||||||
expression=django.db.models.functions.text.Concat(
|
|
||||||
models.Value("https://static-cdn.jtvnw.net/ttv-boxart/"),
|
|
||||||
"id",
|
|
||||||
models.Value("_IGDB.jpg"),
|
|
||||||
),
|
|
||||||
output_field=models.URLField(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("display_name", models.TextField(blank=True, null=True)),
|
|
||||||
(
|
|
||||||
"added_at",
|
|
||||||
models.DateTimeField(blank=True, editable=False, null=True),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"modified_at",
|
|
||||||
models.DateTimeField(blank=True, editable=False, null=True),
|
|
||||||
),
|
|
||||||
("history_id", models.AutoField(primary_key=True, serialize=False)),
|
|
||||||
("history_date", models.DateTimeField(db_index=True)),
|
|
||||||
("history_change_reason", models.CharField(max_length=100, null=True)),
|
|
||||||
(
|
|
||||||
"history_type",
|
|
||||||
models.CharField(
|
|
||||||
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
|
|
||||||
max_length=1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"history_user",
|
|
||||||
models.ForeignKey(
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.SET_NULL,
|
|
||||||
related_name="+",
|
|
||||||
to=settings.AUTH_USER_MODEL,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "historical game",
|
|
||||||
"verbose_name_plural": "historical games",
|
|
||||||
"ordering": ("-history_date", "-history_id"),
|
|
||||||
"get_latest_by": ("history_date", "history_id"),
|
|
||||||
},
|
|
||||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="HistoricalTimeBasedDrop",
|
|
||||||
fields=[
|
|
||||||
("id", models.TextField(db_index=True)),
|
|
||||||
("required_subs", models.IntegerField(blank=True, null=True)),
|
|
||||||
("end_at", models.DateTimeField(blank=True, null=True)),
|
|
||||||
("name", models.TextField(blank=True, null=True)),
|
|
||||||
(
|
|
||||||
"required_minutes_watched",
|
|
||||||
models.IntegerField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
("start_at", models.DateTimeField(blank=True, null=True)),
|
|
||||||
(
|
|
||||||
"added_at",
|
|
||||||
models.DateTimeField(blank=True, editable=False, null=True),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"modified_at",
|
|
||||||
models.DateTimeField(blank=True, editable=False, null=True),
|
|
||||||
),
|
|
||||||
("history_id", models.AutoField(primary_key=True, serialize=False)),
|
|
||||||
("history_date", models.DateTimeField(db_index=True)),
|
|
||||||
("history_change_reason", models.CharField(max_length=100, null=True)),
|
|
||||||
(
|
|
||||||
"history_type",
|
|
||||||
models.CharField(
|
|
||||||
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
|
|
||||||
max_length=1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"history_user",
|
|
||||||
models.ForeignKey(
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.SET_NULL,
|
|
||||||
related_name="+",
|
|
||||||
to=settings.AUTH_USER_MODEL,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "historical time based drop",
|
|
||||||
"verbose_name_plural": "historical time based drops",
|
|
||||||
"ordering": ("-history_date", "-history_id"),
|
|
||||||
"get_latest_by": ("history_date", "history_id"),
|
|
||||||
},
|
|
||||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="HistoricalUser",
|
|
||||||
fields=[
|
|
||||||
("id", models.TextField(db_index=True)),
|
|
||||||
(
|
|
||||||
"added_at",
|
|
||||||
models.DateTimeField(blank=True, editable=False, null=True),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"modified_at",
|
|
||||||
models.DateTimeField(blank=True, editable=False, null=True),
|
|
||||||
),
|
|
||||||
("history_id", models.AutoField(primary_key=True, serialize=False)),
|
|
||||||
("history_date", models.DateTimeField(db_index=True)),
|
|
||||||
("history_change_reason", models.CharField(max_length=100, null=True)),
|
|
||||||
(
|
|
||||||
"history_type",
|
|
||||||
models.CharField(
|
|
||||||
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
|
|
||||||
max_length=1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"history_user",
|
|
||||||
models.ForeignKey(
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.SET_NULL,
|
|
||||||
related_name="+",
|
|
||||||
to=settings.AUTH_USER_MODEL,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "historical user",
|
|
||||||
"verbose_name_plural": "historical users",
|
|
||||||
"ordering": ("-history_date", "-history_id"),
|
|
||||||
"get_latest_by": ("history_date", "history_id"),
|
|
||||||
},
|
|
||||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,23 +0,0 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-07-01 15:23
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
from django.db.migrations.operations.base import Operation
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies: list[tuple[str, str]] = [
|
|
||||||
("twitch_app", "0003_historicaldropbenefit_historicaldropcampaign_and_more"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations: list[Operation] = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name="user",
|
|
||||||
name="drop_campaigns",
|
|
||||||
),
|
|
||||||
migrations.DeleteModel(
|
|
||||||
name="HistoricalUser",
|
|
||||||
),
|
|
||||||
migrations.DeleteModel(
|
|
||||||
name="User",
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,92 +0,0 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-07-01 15:40
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
from django.db.migrations.operations.base import Operation
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies: list[tuple[str, str]] = [
|
|
||||||
(
|
|
||||||
"twitch_app",
|
|
||||||
"0004_remove_user_drop_campaigns_delete_historicaluser_and_more",
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations: list[Operation] = [
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="dropbenefit",
|
|
||||||
options={
|
|
||||||
"ordering": ("name",),
|
|
||||||
"verbose_name": "Drop Benefit",
|
|
||||||
"verbose_name_plural": "Drop Benefits",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="dropcampaign",
|
|
||||||
options={
|
|
||||||
"ordering": ("name",),
|
|
||||||
"verbose_name": "Drop Campaign",
|
|
||||||
"verbose_name_plural": "Drop Campaigns",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="game",
|
|
||||||
options={
|
|
||||||
"ordering": ("display_name",),
|
|
||||||
"verbose_name": "Game",
|
|
||||||
"verbose_name_plural": "Games",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="historicaldropbenefit",
|
|
||||||
options={
|
|
||||||
"get_latest_by": ("history_date", "history_id"),
|
|
||||||
"ordering": ("-history_date", "-history_id"),
|
|
||||||
"verbose_name": "historical Drop Benefit",
|
|
||||||
"verbose_name_plural": "historical Drop Benefits",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="historicaldropcampaign",
|
|
||||||
options={
|
|
||||||
"get_latest_by": ("history_date", "history_id"),
|
|
||||||
"ordering": ("-history_date", "-history_id"),
|
|
||||||
"verbose_name": "historical Drop Campaign",
|
|
||||||
"verbose_name_plural": "historical Drop Campaigns",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="historicalgame",
|
|
||||||
options={
|
|
||||||
"get_latest_by": ("history_date", "history_id"),
|
|
||||||
"ordering": ("-history_date", "-history_id"),
|
|
||||||
"verbose_name": "historical Game",
|
|
||||||
"verbose_name_plural": "historical Games",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="historicaltimebaseddrop",
|
|
||||||
options={
|
|
||||||
"get_latest_by": ("history_date", "history_id"),
|
|
||||||
"ordering": ("-history_date", "-history_id"),
|
|
||||||
"verbose_name": "historical Time-Based Drop",
|
|
||||||
"verbose_name_plural": "historical Time-Based Drops",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="organization",
|
|
||||||
options={
|
|
||||||
"ordering": ("name",),
|
|
||||||
"verbose_name": "Organization",
|
|
||||||
"verbose_name_plural": "Organizations",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="timebaseddrop",
|
|
||||||
options={
|
|
||||||
"ordering": ("name",),
|
|
||||||
"verbose_name": "Time-Based Drop",
|
|
||||||
"verbose_name_plural": "Time-Based Drops",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,172 +0,0 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-07-01 15:44
|
|
||||||
|
|
||||||
import auto_prefetch
|
|
||||||
import django.db.models.deletion
|
|
||||||
import django.db.models.manager
|
|
||||||
from django.db import migrations
|
|
||||||
from django.db.migrations.operations.base import Operation
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies: list[tuple[str, str]] = [
|
|
||||||
("twitch_app", "0005_alter_dropbenefit_options_alter_dropcampaign_options_and_more"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations: list[Operation] = [
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="dropbenefit",
|
|
||||||
options={
|
|
||||||
"base_manager_name": "prefetch_manager",
|
|
||||||
"ordering": ("name",),
|
|
||||||
"verbose_name": "Drop Benefit",
|
|
||||||
"verbose_name_plural": "Drop Benefits",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="dropcampaign",
|
|
||||||
options={
|
|
||||||
"base_manager_name": "prefetch_manager",
|
|
||||||
"ordering": ("name",),
|
|
||||||
"verbose_name": "Drop Campaign",
|
|
||||||
"verbose_name_plural": "Drop Campaigns",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="game",
|
|
||||||
options={
|
|
||||||
"base_manager_name": "prefetch_manager",
|
|
||||||
"ordering": ("display_name",),
|
|
||||||
"verbose_name": "Game",
|
|
||||||
"verbose_name_plural": "Games",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="organization",
|
|
||||||
options={
|
|
||||||
"base_manager_name": "prefetch_manager",
|
|
||||||
"ordering": ("name",),
|
|
||||||
"verbose_name": "Organization",
|
|
||||||
"verbose_name_plural": "Organizations",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="timebaseddrop",
|
|
||||||
options={
|
|
||||||
"base_manager_name": "prefetch_manager",
|
|
||||||
"ordering": ("name",),
|
|
||||||
"verbose_name": "Time-Based Drop",
|
|
||||||
"verbose_name_plural": "Time-Based Drops",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AlterModelManagers(
|
|
||||||
name="dropbenefit",
|
|
||||||
managers=[
|
|
||||||
("objects", django.db.models.manager.Manager()),
|
|
||||||
("prefetch_manager", django.db.models.manager.Manager()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AlterModelManagers(
|
|
||||||
name="dropcampaign",
|
|
||||||
managers=[
|
|
||||||
("objects", django.db.models.manager.Manager()),
|
|
||||||
("prefetch_manager", django.db.models.manager.Manager()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AlterModelManagers(
|
|
||||||
name="game",
|
|
||||||
managers=[
|
|
||||||
("objects", django.db.models.manager.Manager()),
|
|
||||||
("prefetch_manager", django.db.models.manager.Manager()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AlterModelManagers(
|
|
||||||
name="organization",
|
|
||||||
managers=[
|
|
||||||
("objects", django.db.models.manager.Manager()),
|
|
||||||
("prefetch_manager", django.db.models.manager.Manager()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AlterModelManagers(
|
|
||||||
name="timebaseddrop",
|
|
||||||
managers=[
|
|
||||||
("objects", django.db.models.manager.Manager()),
|
|
||||||
("prefetch_manager", django.db.models.manager.Manager()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="dropbenefit",
|
|
||||||
name="game",
|
|
||||||
field=auto_prefetch.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="twitch_app.game"),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="dropbenefit",
|
|
||||||
name="owner_organization",
|
|
||||||
field=auto_prefetch.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="twitch_app.organization"),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="dropcampaign",
|
|
||||||
name="game",
|
|
||||||
field=auto_prefetch.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
related_name="drop_campaigns",
|
|
||||||
to="twitch_app.game",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="dropcampaign",
|
|
||||||
name="owner",
|
|
||||||
field=auto_prefetch.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
related_name="drop_campaigns",
|
|
||||||
to="twitch_app.organization",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="historicaldropbenefit",
|
|
||||||
name="game",
|
|
||||||
field=auto_prefetch.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
db_constraint=False,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
||||||
related_name="+",
|
|
||||||
to="twitch_app.game",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="historicaldropbenefit",
|
|
||||||
name="owner_organization",
|
|
||||||
field=auto_prefetch.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
db_constraint=False,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
||||||
related_name="+",
|
|
||||||
to="twitch_app.organization",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="historicaldropcampaign",
|
|
||||||
name="game",
|
|
||||||
field=auto_prefetch.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
db_constraint=False,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
||||||
related_name="+",
|
|
||||||
to="twitch_app.game",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="historicaldropcampaign",
|
|
||||||
name="owner",
|
|
||||||
field=auto_prefetch.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
db_constraint=False,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
||||||
related_name="+",
|
|
||||||
to="twitch_app.organization",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,23 +0,0 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-07-02 17:11
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
from django.db.migrations.operations.base import Operation
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies: list[tuple[str, str]] = [
|
|
||||||
("twitch_app", "0006_alter_dropbenefit_options_alter_dropcampaign_options_and_more"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations: list[Operation] = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="dropcampaign",
|
|
||||||
name="time_based_drops",
|
|
||||||
field=models.ManyToManyField(related_name="drop_campaigns", to="twitch_app.timebaseddrop"),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="timebaseddrop",
|
|
||||||
name="benefits",
|
|
||||||
field=models.ManyToManyField(related_name="time_based_drops", to="twitch_app.dropbenefit"),
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,33 +0,0 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-07-03 21:19
|
|
||||||
|
|
||||||
import auto_prefetch
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.db import migrations
|
|
||||||
from django.db.migrations.operations.base import Operation
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies: list[tuple[str, str]] = [
|
|
||||||
("twitch_app", "0007_alter_dropcampaign_time_based_drops_and_more"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations: list[Operation] = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="dropbenefit",
|
|
||||||
name="game",
|
|
||||||
field=auto_prefetch.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
related_name="drop_benefits",
|
|
||||||
to="twitch_app.game",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="dropbenefit",
|
|
||||||
name="owner_organization",
|
|
||||||
field=auto_prefetch.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
related_name="drop_benefits",
|
|
||||||
to="twitch_app.organization",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
@ -3,10 +3,7 @@ from typing import Literal
|
|||||||
import auto_prefetch
|
import auto_prefetch
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Value
|
from django.db.models import Value
|
||||||
from django.db.models.functions import (
|
from django.db.models.functions import Concat
|
||||||
Concat,
|
|
||||||
)
|
|
||||||
from simple_history.models import HistoricalRecords
|
|
||||||
|
|
||||||
|
|
||||||
class Organization(auto_prefetch.Model):
|
class Organization(auto_prefetch.Model):
|
||||||
@ -35,6 +32,11 @@ class Game(auto_prefetch.Model):
|
|||||||
For example, MultiVersus.
|
For example, MultiVersus.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
organization = auto_prefetch.ForeignKey(
|
||||||
|
Organization,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name="games",
|
||||||
|
)
|
||||||
id = models.TextField(primary_key=True)
|
id = models.TextField(primary_key=True)
|
||||||
slug = models.TextField(blank=True, null=True)
|
slug = models.TextField(blank=True, null=True)
|
||||||
twitch_url = models.GeneratedField( # type: ignore # noqa: PGH003
|
twitch_url = models.GeneratedField( # type: ignore # noqa: PGH003
|
||||||
@ -54,7 +56,6 @@ class Game(auto_prefetch.Model):
|
|||||||
display_name = models.TextField(blank=True, null=True)
|
display_name = models.TextField(blank=True, null=True)
|
||||||
added_at = models.DateTimeField(blank=True, null=True, auto_now_add=True)
|
added_at = models.DateTimeField(blank=True, null=True, auto_now_add=True)
|
||||||
modified_at = models.DateTimeField(blank=True, null=True, auto_now=True)
|
modified_at = models.DateTimeField(blank=True, null=True, auto_now=True)
|
||||||
history = HistoricalRecords()
|
|
||||||
|
|
||||||
class Meta(auto_prefetch.Model.Meta):
|
class Meta(auto_prefetch.Model.Meta):
|
||||||
verbose_name: str = "Game"
|
verbose_name: str = "Game"
|
||||||
@ -65,55 +66,29 @@ class Game(auto_prefetch.Model):
|
|||||||
return self.display_name or self.slug or self.id
|
return self.display_name or self.slug or self.id
|
||||||
|
|
||||||
|
|
||||||
class DropBenefit(auto_prefetch.Model):
|
class Drop(auto_prefetch.Model):
|
||||||
"""Information about the drop."""
|
"""The actual drop that is being given out."""
|
||||||
|
|
||||||
id = models.TextField(primary_key=True)
|
id = models.TextField(primary_key=True)
|
||||||
created_at = models.DateTimeField(blank=True, null=True)
|
created_at = models.DateTimeField(blank=True, null=True)
|
||||||
entitlement_limit = models.IntegerField(blank=True, null=True)
|
entitlement_limit = models.IntegerField(blank=True, null=True)
|
||||||
image_asset_url = models.URLField(blank=True, null=True)
|
image_asset_url = models.URLField(blank=True, null=True)
|
||||||
is_ios_available = models.BooleanField(blank=True, null=True)
|
|
||||||
name = models.TextField(blank=True, null=True)
|
name = models.TextField(blank=True, null=True)
|
||||||
owner_organization = auto_prefetch.ForeignKey(
|
|
||||||
Organization,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
related_name="drop_benefits",
|
|
||||||
)
|
|
||||||
game = auto_prefetch.ForeignKey(Game, on_delete=models.CASCADE, related_name="drop_benefits")
|
|
||||||
added_at = models.DateTimeField(blank=True, null=True, auto_now_add=True)
|
added_at = models.DateTimeField(blank=True, null=True, auto_now_add=True)
|
||||||
modified_at = models.DateTimeField(blank=True, null=True, auto_now=True)
|
modified_at = models.DateTimeField(blank=True, null=True, auto_now=True)
|
||||||
history = HistoricalRecords()
|
|
||||||
|
|
||||||
class Meta(auto_prefetch.Model.Meta):
|
|
||||||
verbose_name: str = "Drop Benefit"
|
|
||||||
verbose_name_plural: str = "Drop Benefits"
|
|
||||||
ordering: tuple[Literal["name"]] = ("name",)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return f"{self.owner_organization.name} - {self.game.display_name} - {self.name}"
|
|
||||||
|
|
||||||
|
|
||||||
class TimeBasedDrop(auto_prefetch.Model):
|
|
||||||
"""The actual drop that is being given out."""
|
|
||||||
|
|
||||||
id = models.TextField(primary_key=True)
|
|
||||||
required_subs = models.IntegerField(blank=True, null=True)
|
required_subs = models.IntegerField(blank=True, null=True)
|
||||||
end_at = models.DateTimeField(blank=True, null=True)
|
end_at = models.DateTimeField(blank=True, null=True)
|
||||||
name = models.TextField(blank=True, null=True)
|
|
||||||
required_minutes_watched = models.IntegerField(blank=True, null=True)
|
required_minutes_watched = models.IntegerField(blank=True, null=True)
|
||||||
start_at = models.DateTimeField(blank=True, null=True)
|
start_at = models.DateTimeField(blank=True, null=True)
|
||||||
benefits = models.ManyToManyField(DropBenefit, related_name="time_based_drops")
|
drop_campaign = auto_prefetch.ForeignKey("DropCampaign", on_delete=models.CASCADE, related_name="drops")
|
||||||
added_at = models.DateTimeField(blank=True, null=True, auto_now_add=True)
|
|
||||||
modified_at = models.DateTimeField(blank=True, null=True, auto_now=True)
|
|
||||||
history = HistoricalRecords()
|
|
||||||
|
|
||||||
class Meta(auto_prefetch.Model.Meta):
|
class Meta(auto_prefetch.Model.Meta):
|
||||||
verbose_name: str = "Time-Based Drop"
|
verbose_name: str = "Drop"
|
||||||
verbose_name_plural: str = "Time-Based Drops"
|
verbose_name_plural: str = "Drops"
|
||||||
ordering: tuple[Literal["name"]] = ("name",)
|
ordering: tuple[Literal["name"]] = ("name",)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return f"{self.benefits.first()} - {self.name}"
|
return f"{self.name}"
|
||||||
|
|
||||||
|
|
||||||
class DropCampaign(auto_prefetch.Model):
|
class DropCampaign(auto_prefetch.Model):
|
||||||
@ -136,15 +111,8 @@ class DropCampaign(auto_prefetch.Model):
|
|||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name="drop_campaigns",
|
related_name="drop_campaigns",
|
||||||
)
|
)
|
||||||
owner = auto_prefetch.ForeignKey(
|
|
||||||
Organization,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
related_name="drop_campaigns",
|
|
||||||
)
|
|
||||||
time_based_drops = models.ManyToManyField(TimeBasedDrop, related_name="drop_campaigns")
|
|
||||||
added_at = models.DateTimeField(blank=True, null=True, auto_now_add=True)
|
added_at = models.DateTimeField(blank=True, null=True, auto_now_add=True)
|
||||||
modified_at = models.DateTimeField(blank=True, null=True, auto_now=True)
|
modified_at = models.DateTimeField(blank=True, null=True, auto_now=True)
|
||||||
history = HistoricalRecords()
|
|
||||||
|
|
||||||
class Meta(auto_prefetch.Model.Meta):
|
class Meta(auto_prefetch.Model.Meta):
|
||||||
verbose_name: str = "Drop Campaign"
|
verbose_name: str = "Drop Campaign"
|
||||||
@ -152,4 +120,4 @@ class DropCampaign(auto_prefetch.Model):
|
|||||||
ordering: tuple[Literal["name"]] = ("name",)
|
ordering: tuple[Literal["name"]] = ("name",)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return f"{self.owner.name} - {self.game.display_name} - {self.name}"
|
return f"{self.game.display_name} - {self.name}"
|
||||||
|
Reference in New Issue
Block a user