WIP
This commit is contained in:
@ -2,28 +2,33 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container mt-4">
|
<div class="container mt-4">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for game in games %}
|
<div class="col-lg-3">{{ toc|safe }}</div>
|
||||||
<div class="col-xl-3 col-lg-4 col-md-6 col-sm-12 mb-4">
|
<div class="col-lg-9">
|
||||||
<div class="card h-100 shadow-sm">
|
<div class="row">
|
||||||
<img src="{{ game.image_url }}"
|
{% for game in games %}
|
||||||
class="card-img-top"
|
<div class="col-xl-3 col-lg-4 col-md-6 col-sm-12 mb-4">
|
||||||
alt="{{ game.display_name }}">
|
<div class="card h-100 shadow-sm">
|
||||||
<div class="card-body d-flex flex-column">
|
<img src="{{ game.image_url }}"
|
||||||
<h5 class="card-title">{{ game.display_name }}</h5>
|
class="card-img-top"
|
||||||
<div class="mt-auto">
|
alt="{{ game.display_name }}">
|
||||||
<div class="form-check form-switch">
|
<div class="card-body d-flex flex-column">
|
||||||
<input class="form-check-input" type="checkbox" role="switch" id="new">
|
<h5 class="card-title">{{ game.display_name }}</h5>
|
||||||
<label class="form-check-label" for="new">Notify when new</label>
|
<div class="mt-auto">
|
||||||
</div>
|
<div class="form-check form-switch">
|
||||||
<div class="form-check form-switch">
|
<input class="form-check-input" type="checkbox" role="switch" id="new">
|
||||||
<input class="form-check-input" type="checkbox" role="switch" id="live">
|
<label class="form-check-label" for="new">Notify when new</label>
|
||||||
<label class="form-check-label" for="live">Notify when farmable</label>
|
</div>
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" role="switch" id="live">
|
||||||
|
<label class="form-check-label" for="live">Notify when farmable</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container mt-4">
|
<div class="container mt-4">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3">{% include "partials/toc.html" %}</div>
|
<div class="col-lg-3">{{ toc|safe }}</div>
|
||||||
<div class="col-lg-9">
|
<div class="col-lg-9">
|
||||||
{% include "partials/info_box.html" %}
|
{% include "partials/info_box.html" %}
|
||||||
{% include "partials/news.html" %}
|
{% include "partials/news.html" %}
|
||||||
|
@ -7,15 +7,15 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href='{% url "core:games" %}'>Games</a>
|
<a class="nav-link" href='{% url "core:games" %}'>Games</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="nav-link" href='{% url "core:reward_campaigns" %}'>Reward campaigns</a>
|
||||||
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href=''>API</a>
|
<a class="nav-link" href=''>API</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item d-none d-sm-block">
|
<li class="nav-item d-none d-sm-block">
|
||||||
<a class="nav-link" href="https://github.com/sponsors/TheLovinator1">Donate</a>
|
<a class="nav-link" href="https://github.com/sponsors/TheLovinator1">Donate</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<a class="nav-link" href='{% url "core:reward_campaigns" %}'>Reward campaigns</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
<div class="position-sticky d-none d-lg-block toc">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<div id="toc-list" class="list-group">
|
|
||||||
{% for campaign in reward_campaigns %}
|
|
||||||
<a class="list-group-item list-group-item-action plain-text-item"
|
|
||||||
href="#reward-{{ campaign.id }}">{{ campaign }}</a>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,19 +0,0 @@
|
|||||||
<div class="position-sticky d-none d-lg-block toc">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<div id="toc-list" class="list-group">
|
|
||||||
<a class="list-group-item list-group-item-action plain-text-item"
|
|
||||||
href="#info-box">Information</a>
|
|
||||||
<a class="list-group-item list-group-item-action plain-text-item"
|
|
||||||
href="#game-list">Site news</a>
|
|
||||||
{% for org in orgs %}
|
|
||||||
{{ org }}
|
|
||||||
{% for game in org.games.all %}
|
|
||||||
<a class="list-group-item list-group-item-action plain-text-item"
|
|
||||||
href="#game-{{ game.game_id }}">{{ game.display_name }}</a>
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -3,7 +3,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container mt-4">
|
<div class="container mt-4">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3">{% include "partials/reward_campaigns_toc.html" %}</div>
|
<div class="col-lg-3">{{ toc }}</div>
|
||||||
<div class="col-lg-9">
|
<div class="col-lg-9">
|
||||||
<h2>Reward Campaigns</h2>
|
<h2>Reward Campaigns</h2>
|
||||||
<div>
|
<div>
|
||||||
|
@ -2,7 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from django.urls import URLPattern, URLResolver, path
|
from django.urls import URLPattern, URLResolver, path
|
||||||
|
|
||||||
from core.views import GameView, RewardCampaignView, index
|
from core.views import game_view, index, reward_campaign_view
|
||||||
|
|
||||||
app_name: str = "core"
|
app_name: str = "core"
|
||||||
|
|
||||||
@ -10,12 +10,12 @@ urlpatterns: list[URLPattern | URLResolver] = [
|
|||||||
path(route="", view=index, name="index"),
|
path(route="", view=index, name="index"),
|
||||||
path(
|
path(
|
||||||
route="games/",
|
route="games/",
|
||||||
view=GameView.as_view(),
|
view=game_view,
|
||||||
name="games",
|
name="games",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
route="reward_campaigns/",
|
route="reward_campaigns/",
|
||||||
view=RewardCampaignView.as_view(),
|
view=reward_campaign_view,
|
||||||
name="reward_campaigns",
|
name="reward_campaigns",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
from dataclasses import dataclass
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import hishel
|
import hishel
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.db.models.manager import BaseManager
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
from django.views.generic import ListView
|
|
||||||
|
|
||||||
from core.data import WebhookData
|
from core.data import WebhookData
|
||||||
from twitch_app.models import Game, RewardCampaign
|
from twitch_app.models import Game, RewardCampaign
|
||||||
@ -58,26 +59,59 @@ def get_webhook_data(webhook: str) -> WebhookData:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TOCItem:
|
||||||
|
"""Table of contents item."""
|
||||||
|
|
||||||
|
name: str
|
||||||
|
toc_id: str
|
||||||
|
|
||||||
|
|
||||||
|
def build_toc(list_of_things: list[TOCItem]) -> str:
|
||||||
|
"""Build the table of contents."""
|
||||||
|
html: str = """
|
||||||
|
<div class="position-sticky d-none d-lg-block toc">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div id="toc-list" class="list-group">
|
||||||
|
"""
|
||||||
|
|
||||||
|
for item in list_of_things:
|
||||||
|
html += (
|
||||||
|
f'<a class="list-group-item list-group-item-action plain-text-item" href="#{item.toc_id}">{item.name}</a>'
|
||||||
|
)
|
||||||
|
html += """</div></div></div></div>"""
|
||||||
|
return html
|
||||||
|
|
||||||
|
|
||||||
def index(request: HttpRequest) -> HttpResponse:
|
def index(request: HttpRequest) -> HttpResponse:
|
||||||
"""Render the index page."""
|
"""Render the index page."""
|
||||||
reward_campaigns: BaseManager[RewardCampaign] = RewardCampaign.objects.all()
|
reward_campaigns: BaseManager[RewardCampaign] = RewardCampaign.objects.all()
|
||||||
|
|
||||||
return TemplateResponse(
|
toc: str = build_toc([
|
||||||
request=request,
|
TOCItem(name="Information", toc_id="#info-box"),
|
||||||
template="index.html",
|
TOCItem(name="Games", toc_id="#games"),
|
||||||
context={"reward_campaigns": reward_campaigns},
|
])
|
||||||
)
|
|
||||||
|
context: dict[str, BaseManager[RewardCampaign] | str] = {"reward_campaigns": reward_campaigns, "toc": toc}
|
||||||
|
return TemplateResponse(request=request, template="index.html", context=context)
|
||||||
|
|
||||||
|
|
||||||
class GameView(ListView):
|
def game_view(request: HttpRequest) -> HttpResponse:
|
||||||
model = Game
|
"""Render the game view page."""
|
||||||
template_name: str = "games.html"
|
games: BaseManager[Game] = Game.objects.all()
|
||||||
context_object_name: str = "games"
|
|
||||||
paginate_by = 100
|
tocs: list[TOCItem] = [
|
||||||
|
TOCItem(name=game.display_name, toc_id=game.slug) for game in games if game.display_name and game.slug
|
||||||
|
]
|
||||||
|
toc: str = build_toc(tocs)
|
||||||
|
|
||||||
|
context: dict[str, BaseManager[Game] | str] = {"games": games, "toc": toc}
|
||||||
|
return TemplateResponse(request=request, template="games.html", context=context)
|
||||||
|
|
||||||
|
|
||||||
class RewardCampaignView(ListView):
|
def reward_campaign_view(request: HttpRequest) -> HttpResponse:
|
||||||
model = RewardCampaign
|
"""Render the reward campaign view page."""
|
||||||
template_name: str = "reward_campaigns.html"
|
reward_campaigns: BaseManager[RewardCampaign] = RewardCampaign.objects.all()
|
||||||
context_object_name: str = "reward_campaigns"
|
context: dict[str, BaseManager[RewardCampaign]] = {"reward_campaigns": reward_campaigns}
|
||||||
paginate_by = 100
|
return TemplateResponse(request=request, template="reward_campaigns.html", context=context)
|
||||||
|
380
testboi.py
Normal file
380
testboi.py
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Any
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
|
|
||||||
|
class ChannelTypename(Enum):
|
||||||
|
CHANNEL = "Channel"
|
||||||
|
GAME = "Game"
|
||||||
|
ORGANIZATION = "Organization"
|
||||||
|
|
||||||
|
|
||||||
|
class Channel:
|
||||||
|
id: int
|
||||||
|
display_name: str
|
||||||
|
name: str
|
||||||
|
typename: ChannelTypename
|
||||||
|
|
||||||
|
def __init__(self, id: int, display_name: str, name: str, typename: ChannelTypename) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.display_name = display_name
|
||||||
|
self.name = name
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class AllowTypename(Enum):
|
||||||
|
DROP_CAMPAIGN_ACL = "DropCampaignACL"
|
||||||
|
|
||||||
|
|
||||||
|
class Allow:
|
||||||
|
channels: list[Channel] | None
|
||||||
|
is_enabled: bool
|
||||||
|
typename: AllowTypename
|
||||||
|
|
||||||
|
def __init__(self, channels: list[Channel] | None, is_enabled: bool, typename: AllowTypename) -> None:
|
||||||
|
self.channels = channels
|
||||||
|
self.is_enabled = is_enabled
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class SelfTypename(Enum):
|
||||||
|
DROP_CAMPAIGN_SELF_EDGE = "DropCampaignSelfEdge"
|
||||||
|
|
||||||
|
|
||||||
|
class Self:
|
||||||
|
is_account_connected: bool
|
||||||
|
typename: SelfTypename
|
||||||
|
|
||||||
|
def __init__(self, is_account_connected: bool, typename: SelfTypename) -> None:
|
||||||
|
self.is_account_connected = is_account_connected
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class Game:
|
||||||
|
id: int
|
||||||
|
slug: str
|
||||||
|
display_name: str
|
||||||
|
typename: ChannelTypename
|
||||||
|
|
||||||
|
def __init__(self, id: int, slug: str, display_name: str, typename: ChannelTypename) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.slug = slug
|
||||||
|
self.display_name = display_name
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class PurpleOwner:
|
||||||
|
id: UUID | int
|
||||||
|
name: str | None
|
||||||
|
typename: ChannelTypename
|
||||||
|
display_name: str | None
|
||||||
|
slug: str | None
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: UUID | int,
|
||||||
|
name: str | None,
|
||||||
|
typename: ChannelTypename,
|
||||||
|
display_name: str | None,
|
||||||
|
slug: str | None,
|
||||||
|
) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.name = name
|
||||||
|
self.typename = typename
|
||||||
|
self.display_name = display_name
|
||||||
|
self.slug = slug
|
||||||
|
|
||||||
|
|
||||||
|
class Status(Enum):
|
||||||
|
ACTIVE = "ACTIVE"
|
||||||
|
EXPIRED = "EXPIRED"
|
||||||
|
|
||||||
|
|
||||||
|
class GameClass:
|
||||||
|
id: UUID | int
|
||||||
|
name: str
|
||||||
|
typename: ChannelTypename
|
||||||
|
|
||||||
|
def __init__(self, id: UUID | int, name: str, typename: ChannelTypename) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.name = name
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class BenefitTypename(Enum):
|
||||||
|
DROP_BENEFIT = "DropBenefit"
|
||||||
|
|
||||||
|
|
||||||
|
class Benefit:
|
||||||
|
id: str
|
||||||
|
created_at: datetime
|
||||||
|
entitlement_limit: int
|
||||||
|
game: GameClass
|
||||||
|
image_asset_url: str
|
||||||
|
is_ios_available: bool
|
||||||
|
name: str
|
||||||
|
owner_organization: GameClass
|
||||||
|
typename: BenefitTypename
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: str,
|
||||||
|
created_at: datetime,
|
||||||
|
entitlement_limit: int,
|
||||||
|
game: GameClass,
|
||||||
|
image_asset_url: str,
|
||||||
|
is_ios_available: bool,
|
||||||
|
name: str,
|
||||||
|
owner_organization: GameClass,
|
||||||
|
typename: BenefitTypename,
|
||||||
|
) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.created_at = created_at
|
||||||
|
self.entitlement_limit = entitlement_limit
|
||||||
|
self.game = game
|
||||||
|
self.image_asset_url = image_asset_url
|
||||||
|
self.is_ios_available = is_ios_available
|
||||||
|
self.name = name
|
||||||
|
self.owner_organization = owner_organization
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class BenefitEdgeTypename(Enum):
|
||||||
|
DROP_BENEFIT_EDGE = "DropBenefitEdge"
|
||||||
|
|
||||||
|
|
||||||
|
class BenefitEdge:
|
||||||
|
benefit: Benefit
|
||||||
|
entitlement_limit: int
|
||||||
|
typename: BenefitEdgeTypename
|
||||||
|
|
||||||
|
def __init__(self, benefit: Benefit, entitlement_limit: int, typename: BenefitEdgeTypename) -> None:
|
||||||
|
self.benefit = benefit
|
||||||
|
self.entitlement_limit = entitlement_limit
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class TimeBasedDropTypename(Enum):
|
||||||
|
TIME_BASED_DROP = "TimeBasedDrop"
|
||||||
|
|
||||||
|
|
||||||
|
class TimeBasedDrop:
|
||||||
|
id: UUID
|
||||||
|
required_subs: int
|
||||||
|
benefit_edges: list[BenefitEdge]
|
||||||
|
end_at: datetime
|
||||||
|
name: str
|
||||||
|
precondition_drops: None
|
||||||
|
required_minutes_watched: int
|
||||||
|
start_at: datetime
|
||||||
|
typename: TimeBasedDropTypename
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: UUID,
|
||||||
|
required_subs: int,
|
||||||
|
benefit_edges: list[BenefitEdge],
|
||||||
|
end_at: datetime,
|
||||||
|
name: str,
|
||||||
|
precondition_drops: None,
|
||||||
|
required_minutes_watched: int,
|
||||||
|
start_at: datetime,
|
||||||
|
typename: TimeBasedDropTypename,
|
||||||
|
) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.required_subs = required_subs
|
||||||
|
self.benefit_edges = benefit_edges
|
||||||
|
self.end_at = end_at
|
||||||
|
self.name = name
|
||||||
|
self.precondition_drops = precondition_drops
|
||||||
|
self.required_minutes_watched = required_minutes_watched
|
||||||
|
self.start_at = start_at
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class DropCampaignTypename(Enum):
|
||||||
|
DROP_CAMPAIGN = "DropCampaign"
|
||||||
|
|
||||||
|
|
||||||
|
class PurpleDropCampaign:
|
||||||
|
id: UUID
|
||||||
|
drop_campaign_self: Self
|
||||||
|
allow: Allow
|
||||||
|
account_link_url: str
|
||||||
|
description: str
|
||||||
|
details_url: str
|
||||||
|
end_at: datetime
|
||||||
|
event_based_drops: list[Any]
|
||||||
|
game: Game
|
||||||
|
image_url: str
|
||||||
|
name: str
|
||||||
|
owner: PurpleOwner
|
||||||
|
start_at: datetime
|
||||||
|
status: Status
|
||||||
|
time_based_drops: list[TimeBasedDrop]
|
||||||
|
typename: DropCampaignTypename
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: UUID,
|
||||||
|
drop_campaign_self: Self,
|
||||||
|
allow: Allow,
|
||||||
|
account_link_url: str,
|
||||||
|
description: str,
|
||||||
|
details_url: str,
|
||||||
|
end_at: datetime,
|
||||||
|
event_based_drops: list[Any],
|
||||||
|
game: Game,
|
||||||
|
image_url: str,
|
||||||
|
name: str,
|
||||||
|
owner: PurpleOwner,
|
||||||
|
start_at: datetime,
|
||||||
|
status: Status,
|
||||||
|
time_based_drops: list[TimeBasedDrop],
|
||||||
|
typename: DropCampaignTypename,
|
||||||
|
) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.drop_campaign_self = drop_campaign_self
|
||||||
|
self.allow = allow
|
||||||
|
self.account_link_url = account_link_url
|
||||||
|
self.description = description
|
||||||
|
self.details_url = details_url
|
||||||
|
self.end_at = end_at
|
||||||
|
self.event_based_drops = event_based_drops
|
||||||
|
self.game = game
|
||||||
|
self.image_url = image_url
|
||||||
|
self.name = name
|
||||||
|
self.owner = owner
|
||||||
|
self.start_at = start_at
|
||||||
|
self.status = status
|
||||||
|
self.time_based_drops = time_based_drops
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class UserTypename(Enum):
|
||||||
|
USER = "User"
|
||||||
|
|
||||||
|
|
||||||
|
class PurpleUser:
|
||||||
|
id: int
|
||||||
|
drop_campaign: PurpleDropCampaign
|
||||||
|
typename: UserTypename
|
||||||
|
|
||||||
|
def __init__(self, id: int, drop_campaign: PurpleDropCampaign, typename: UserTypename) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.drop_campaign = drop_campaign
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class DropCampaign100_Data:
|
||||||
|
user: PurpleUser
|
||||||
|
|
||||||
|
def __init__(self, user: PurpleUser) -> None:
|
||||||
|
self.user = user
|
||||||
|
|
||||||
|
|
||||||
|
class OperationName(Enum):
|
||||||
|
DROP_CAMPAIGN_DETAILS = "DropCampaignDetails"
|
||||||
|
|
||||||
|
|
||||||
|
class Extensions:
|
||||||
|
duration_milliseconds: int
|
||||||
|
operation_name: OperationName
|
||||||
|
request_id: str
|
||||||
|
|
||||||
|
def __init__(self, duration_milliseconds: int, operation_name: OperationName, request_id: str) -> None:
|
||||||
|
self.duration_milliseconds = duration_milliseconds
|
||||||
|
self.operation_name = operation_name
|
||||||
|
self.request_id = request_id
|
||||||
|
|
||||||
|
|
||||||
|
class DropCampaign99:
|
||||||
|
data: DropCampaign100_Data
|
||||||
|
extensions: Extensions
|
||||||
|
|
||||||
|
def __init__(self, data: DropCampaign100_Data, extensions: Extensions) -> None:
|
||||||
|
self.data = data
|
||||||
|
self.extensions = extensions
|
||||||
|
|
||||||
|
|
||||||
|
class FluffyDropCampaign:
|
||||||
|
id: UUID
|
||||||
|
drop_campaign_self: Self
|
||||||
|
allow: Allow
|
||||||
|
account_link_url: str
|
||||||
|
description: str
|
||||||
|
details_url: str
|
||||||
|
end_at: datetime
|
||||||
|
event_based_drops: list[Any]
|
||||||
|
game: Game
|
||||||
|
image_url: str
|
||||||
|
name: str
|
||||||
|
owner: GameClass
|
||||||
|
start_at: datetime
|
||||||
|
status: Status
|
||||||
|
time_based_drops: list[TimeBasedDrop]
|
||||||
|
typename: DropCampaignTypename
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: UUID,
|
||||||
|
drop_campaign_self: Self,
|
||||||
|
allow: Allow,
|
||||||
|
account_link_url: str,
|
||||||
|
description: str,
|
||||||
|
details_url: str,
|
||||||
|
end_at: datetime,
|
||||||
|
event_based_drops: list[Any],
|
||||||
|
game: Game,
|
||||||
|
image_url: str,
|
||||||
|
name: str,
|
||||||
|
owner: GameClass,
|
||||||
|
start_at: datetime,
|
||||||
|
status: Status,
|
||||||
|
time_based_drops: list[TimeBasedDrop],
|
||||||
|
typename: DropCampaignTypename,
|
||||||
|
) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.drop_campaign_self = drop_campaign_self
|
||||||
|
self.allow = allow
|
||||||
|
self.account_link_url = account_link_url
|
||||||
|
self.description = description
|
||||||
|
self.details_url = details_url
|
||||||
|
self.end_at = end_at
|
||||||
|
self.event_based_drops = event_based_drops
|
||||||
|
self.game = game
|
||||||
|
self.image_url = image_url
|
||||||
|
self.name = name
|
||||||
|
self.owner = owner
|
||||||
|
self.start_at = start_at
|
||||||
|
self.status = status
|
||||||
|
self.time_based_drops = time_based_drops
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class FluffyUser:
|
||||||
|
id: int
|
||||||
|
drop_campaign: FluffyDropCampaign
|
||||||
|
typename: UserTypename
|
||||||
|
|
||||||
|
def __init__(self, id: int, drop_campaign: FluffyDropCampaign, typename: UserTypename) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.drop_campaign = drop_campaign
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class DropCampaign109_Data:
|
||||||
|
user: FluffyUser
|
||||||
|
|
||||||
|
def __init__(self, user: FluffyUser) -> None:
|
||||||
|
self.user = user
|
||||||
|
|
||||||
|
|
||||||
|
class DropCampaign149:
|
||||||
|
data: DropCampaign109_Data
|
||||||
|
extensions: Extensions
|
||||||
|
|
||||||
|
def __init__(self, data: DropCampaign109_Data, extensions: Extensions) -> None:
|
||||||
|
self.data = data
|
||||||
|
self.extensions = extensions
|
252
testboi2.py
Normal file
252
testboi2.py
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
|
|
||||||
|
class SelfTypename(Enum):
|
||||||
|
DROP_CAMPAIGN_SELF_EDGE = "DropCampaignSelfEdge"
|
||||||
|
|
||||||
|
|
||||||
|
class Self:
|
||||||
|
is_account_connected: bool
|
||||||
|
typename: SelfTypename
|
||||||
|
|
||||||
|
def __init__(self, is_account_connected: bool, typename: SelfTypename) -> None:
|
||||||
|
self.is_account_connected = is_account_connected
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class GameTypename(Enum):
|
||||||
|
GAME = "Game"
|
||||||
|
|
||||||
|
|
||||||
|
class Game:
|
||||||
|
id: int
|
||||||
|
display_name: str
|
||||||
|
box_art_url: str
|
||||||
|
typename: GameTypename
|
||||||
|
|
||||||
|
def __init__(self, id: int, display_name: str, box_art_url: str, typename: GameTypename) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.display_name = display_name
|
||||||
|
self.box_art_url = box_art_url
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class OwnerTypename(Enum):
|
||||||
|
ORGANIZATION = "Organization"
|
||||||
|
|
||||||
|
|
||||||
|
class Owner:
|
||||||
|
id: UUID
|
||||||
|
name: str
|
||||||
|
typename: OwnerTypename
|
||||||
|
|
||||||
|
def __init__(self, id: UUID, name: str, typename: OwnerTypename) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.name = name
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class Status(Enum):
|
||||||
|
ACTIVE = "ACTIVE"
|
||||||
|
EXPIRED = "EXPIRED"
|
||||||
|
|
||||||
|
|
||||||
|
class DropCampaignTypename(Enum):
|
||||||
|
DROP_CAMPAIGN = "DropCampaign"
|
||||||
|
|
||||||
|
|
||||||
|
class DropCampaign:
|
||||||
|
id: UUID
|
||||||
|
name: str
|
||||||
|
owner: Owner
|
||||||
|
game: Game
|
||||||
|
status: Status
|
||||||
|
start_at: datetime
|
||||||
|
end_at: datetime
|
||||||
|
details_url: str
|
||||||
|
account_link_url: str
|
||||||
|
drop_campaign_self: Self
|
||||||
|
typename: DropCampaignTypename
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: UUID,
|
||||||
|
name: str,
|
||||||
|
owner: Owner,
|
||||||
|
game: Game,
|
||||||
|
status: Status,
|
||||||
|
start_at: datetime,
|
||||||
|
end_at: datetime,
|
||||||
|
details_url: str,
|
||||||
|
account_link_url: str,
|
||||||
|
drop_campaign_self: Self,
|
||||||
|
typename: DropCampaignTypename,
|
||||||
|
) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.name = name
|
||||||
|
self.owner = owner
|
||||||
|
self.game = game
|
||||||
|
self.status = status
|
||||||
|
self.start_at = start_at
|
||||||
|
self.end_at = end_at
|
||||||
|
self.details_url = details_url
|
||||||
|
self.account_link_url = account_link_url
|
||||||
|
self.drop_campaign_self = drop_campaign_self
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class CurrentUser:
|
||||||
|
id: int
|
||||||
|
login: str
|
||||||
|
drop_campaigns: list[DropCampaign]
|
||||||
|
typename: str
|
||||||
|
|
||||||
|
def __init__(self, id: int, login: str, drop_campaigns: list[DropCampaign], typename: str) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.login = login
|
||||||
|
self.drop_campaigns = drop_campaigns
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class Image:
|
||||||
|
image1_x_url: str
|
||||||
|
typename: str
|
||||||
|
|
||||||
|
def __init__(self, image1_x_url: str, typename: str) -> None:
|
||||||
|
self.image1_x_url = image1_x_url
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class Reward:
|
||||||
|
id: UUID
|
||||||
|
name: str
|
||||||
|
banner_image: Image
|
||||||
|
thumbnail_image: Image
|
||||||
|
earnable_until: datetime
|
||||||
|
redemption_instructions: str
|
||||||
|
redemption_url: str
|
||||||
|
typename: str
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: UUID,
|
||||||
|
name: str,
|
||||||
|
banner_image: Image,
|
||||||
|
thumbnail_image: Image,
|
||||||
|
earnable_until: datetime,
|
||||||
|
redemption_instructions: str,
|
||||||
|
redemption_url: str,
|
||||||
|
typename: str,
|
||||||
|
) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.name = name
|
||||||
|
self.banner_image = banner_image
|
||||||
|
self.thumbnail_image = thumbnail_image
|
||||||
|
self.earnable_until = earnable_until
|
||||||
|
self.redemption_instructions = redemption_instructions
|
||||||
|
self.redemption_url = redemption_url
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class UnlockRequirements:
|
||||||
|
subs_goal: int
|
||||||
|
minute_watched_goal: int
|
||||||
|
typename: str
|
||||||
|
|
||||||
|
def __init__(self, subs_goal: int, minute_watched_goal: int, typename: str) -> None:
|
||||||
|
self.subs_goal = subs_goal
|
||||||
|
self.minute_watched_goal = minute_watched_goal
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class RewardCampaignsAvailableToUser:
|
||||||
|
id: UUID
|
||||||
|
name: str
|
||||||
|
brand: str
|
||||||
|
starts_at: datetime
|
||||||
|
ends_at: datetime
|
||||||
|
status: str
|
||||||
|
summary: str
|
||||||
|
instructions: str
|
||||||
|
external_url: str
|
||||||
|
reward_value_url_param: str
|
||||||
|
about_url: str
|
||||||
|
is_sitewide: bool
|
||||||
|
game: None
|
||||||
|
unlock_requirements: UnlockRequirements
|
||||||
|
image: Image
|
||||||
|
rewards: list[Reward]
|
||||||
|
typename: str
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: UUID,
|
||||||
|
name: str,
|
||||||
|
brand: str,
|
||||||
|
starts_at: datetime,
|
||||||
|
ends_at: datetime,
|
||||||
|
status: str,
|
||||||
|
summary: str,
|
||||||
|
instructions: str,
|
||||||
|
external_url: str,
|
||||||
|
reward_value_url_param: str,
|
||||||
|
about_url: str,
|
||||||
|
is_sitewide: bool,
|
||||||
|
game: None,
|
||||||
|
unlock_requirements: UnlockRequirements,
|
||||||
|
image: Image,
|
||||||
|
rewards: list[Reward],
|
||||||
|
typename: str,
|
||||||
|
) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.name = name
|
||||||
|
self.brand = brand
|
||||||
|
self.starts_at = starts_at
|
||||||
|
self.ends_at = ends_at
|
||||||
|
self.status = status
|
||||||
|
self.summary = summary
|
||||||
|
self.instructions = instructions
|
||||||
|
self.external_url = external_url
|
||||||
|
self.reward_value_url_param = reward_value_url_param
|
||||||
|
self.about_url = about_url
|
||||||
|
self.is_sitewide = is_sitewide
|
||||||
|
self.game = game
|
||||||
|
self.unlock_requirements = unlock_requirements
|
||||||
|
self.image = image
|
||||||
|
self.rewards = rewards
|
||||||
|
self.typename = typename
|
||||||
|
|
||||||
|
|
||||||
|
class Data:
|
||||||
|
current_user: CurrentUser
|
||||||
|
reward_campaigns_available_to_user: list[RewardCampaignsAvailableToUser]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
current_user: CurrentUser,
|
||||||
|
reward_campaigns_available_to_user: list[RewardCampaignsAvailableToUser],
|
||||||
|
) -> None:
|
||||||
|
self.current_user = current_user
|
||||||
|
self.reward_campaigns_available_to_user = reward_campaigns_available_to_user
|
||||||
|
|
||||||
|
|
||||||
|
class Extensions:
|
||||||
|
duration_milliseconds: int
|
||||||
|
operation_name: str
|
||||||
|
request_id: str
|
||||||
|
|
||||||
|
def __init__(self, duration_milliseconds: int, operation_name: str, request_id: str) -> None:
|
||||||
|
self.duration_milliseconds = duration_milliseconds
|
||||||
|
self.operation_name = operation_name
|
||||||
|
self.request_id = request_id
|
||||||
|
|
||||||
|
|
||||||
|
class RewardCampaign11:
|
||||||
|
data: Data
|
||||||
|
extensions: Extensions
|
||||||
|
|
||||||
|
def __init__(self, data: Data, extensions: Extensions) -> None:
|
||||||
|
self.data = data
|
||||||
|
self.extensions = extensions
|
@ -28,6 +28,7 @@ from twitch_app.models import (
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from playwright.async_api._generated import BrowserContext, Page
|
from playwright.async_api._generated import BrowserContext, Page
|
||||||
|
import json
|
||||||
|
|
||||||
# Where to store the Chrome profile
|
# Where to store the Chrome profile
|
||||||
data_dir = Path(
|
data_dir = Path(
|
||||||
@ -66,6 +67,7 @@ async def add_or_get_game(json_data: dict, name: str) -> tuple[Game | None, bool
|
|||||||
"slug": json_data.get("slug"),
|
"slug": json_data.get("slug"),
|
||||||
"display_name": json_data.get("displayName"),
|
"display_name": json_data.get("displayName"),
|
||||||
"typename": json_data.get("__typename"),
|
"typename": json_data.get("__typename"),
|
||||||
|
"box_art_url": json_data.get("boxArtURL"), # Only for RewardCampaigns
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -204,6 +206,9 @@ async def add_or_get_drop_campaign(
|
|||||||
logger.warning("No drop campaign data found")
|
logger.warning("No drop campaign data found")
|
||||||
return None, False
|
return None, False
|
||||||
|
|
||||||
|
if drop_campaign_data.get("__typename") != "Game":
|
||||||
|
logger.error("__typename is not 'Game' for %s", drop_campaign_data.get("name", "Unknown Drop Campaign"))
|
||||||
|
|
||||||
drop_campaign, _ = await DropCampaign.objects.aupdate_or_create(
|
drop_campaign, _ = await DropCampaign.objects.aupdate_or_create(
|
||||||
id=drop_campaign_data["id"],
|
id=drop_campaign_data["id"],
|
||||||
defaults={
|
defaults={
|
||||||
@ -546,16 +551,35 @@ class Command(BaseCommand):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if "rewardCampaignsAvailableToUser" in campaign["data"]:
|
if "rewardCampaignsAvailableToUser" in campaign["data"]:
|
||||||
|
# Save to folder named "reward_campaigns"
|
||||||
|
dir_name: Path = Path("reward_campaigns")
|
||||||
|
dir_name.mkdir(parents=True, exist_ok=True)
|
||||||
|
with open(file=Path(dir_name / f"reward_campaign_{num}.json"), mode="w", encoding="utf-8") as f:
|
||||||
|
json.dump(campaign, f, indent=4)
|
||||||
|
|
||||||
await add_reward_campaign(campaign)
|
await add_reward_campaign(campaign)
|
||||||
|
|
||||||
if "dropCampaign" in campaign.get("data", {}).get("user", {}):
|
if "dropCampaign" in campaign.get("data", {}).get("user", {}):
|
||||||
if not campaign["data"]["user"]["dropCampaign"]:
|
if not campaign["data"]["user"]["dropCampaign"]:
|
||||||
logger.warning("No drop campaign found")
|
logger.warning("No drop campaign found")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Save to folder named "drop_campaign"
|
||||||
|
dir_name: Path = Path("drop_campaign")
|
||||||
|
dir_name.mkdir(parents=True, exist_ok=True)
|
||||||
|
with open(file=Path(dir_name / f"drop_campaign_{num}.json"), mode="w", encoding="utf-8") as f:
|
||||||
|
json.dump(campaign, f, indent=4)
|
||||||
|
|
||||||
await add_drop_campaign(campaign)
|
await add_drop_campaign(campaign)
|
||||||
|
|
||||||
if "dropCampaigns" in campaign.get("data", {}).get("user", {}):
|
if "dropCampaigns" in campaign.get("data", {}).get("user", {}):
|
||||||
for drop_campaign in campaign["data"]["user"]["dropCampaigns"]:
|
for drop_campaign in campaign["data"]["user"]["dropCampaigns"]:
|
||||||
|
# Save to folder named "drop_campaigns"
|
||||||
|
dir_name: Path = Path("drop_campaigns")
|
||||||
|
dir_name.mkdir(parents=True, exist_ok=True)
|
||||||
|
with open(file=Path(dir_name / f"drop_campaign_{num}.json"), mode="w", encoding="utf-8") as f:
|
||||||
|
json.dump(drop_campaign, f, indent=4)
|
||||||
|
|
||||||
await add_drop_campaign(drop_campaign)
|
await add_drop_campaign(drop_campaign)
|
||||||
|
|
||||||
return json_data
|
return json_data
|
||||||
|
@ -0,0 +1,135 @@
|
|||||||
|
# Generated by Django 5.1rc1 on 2024-08-02 01:20
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.db.models.manager
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("twitch_app", "0009_alter_benefit_entitlement_limit_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="FrontEndChannel",
|
||||||
|
fields=[
|
||||||
|
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
|
||||||
|
("name", models.TextField(blank=True, null=True)),
|
||||||
|
("twitch_url", models.URLField(blank=True, null=True)),
|
||||||
|
("live", models.BooleanField(default=False)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"abstract": False,
|
||||||
|
"base_manager_name": "prefetch_manager",
|
||||||
|
},
|
||||||
|
managers=[
|
||||||
|
("objects", django.db.models.manager.Manager()),
|
||||||
|
("prefetch_manager", django.db.models.manager.Manager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="FrontEndGame",
|
||||||
|
fields=[
|
||||||
|
("twitch_id", models.TextField(primary_key=True, serialize=False)),
|
||||||
|
("game_url", models.URLField(blank=True, null=True)),
|
||||||
|
("display_name", models.TextField(blank=True, null=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"abstract": False,
|
||||||
|
"base_manager_name": "prefetch_manager",
|
||||||
|
},
|
||||||
|
managers=[
|
||||||
|
("objects", django.db.models.manager.Manager()),
|
||||||
|
("prefetch_manager", django.db.models.manager.Manager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="FrontEndOrg",
|
||||||
|
fields=[
|
||||||
|
("id", models.TextField(primary_key=True, serialize=False)),
|
||||||
|
("name", models.TextField(blank=True, null=True)),
|
||||||
|
("url", models.TextField(blank=True, null=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"abstract": False,
|
||||||
|
"base_manager_name": "prefetch_manager",
|
||||||
|
},
|
||||||
|
managers=[
|
||||||
|
("objects", django.db.models.manager.Manager()),
|
||||||
|
("prefetch_manager", django.db.models.manager.Manager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="game",
|
||||||
|
name="box_art_url",
|
||||||
|
field=models.URLField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="FrontEndDropCampaign",
|
||||||
|
fields=[
|
||||||
|
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
|
||||||
|
("account_link_url", models.URLField(blank=True, null=True)),
|
||||||
|
("about_url", models.URLField(blank=True, null=True)),
|
||||||
|
("ends_at", models.DateTimeField(null=True)),
|
||||||
|
("starts_at", models.DateTimeField(null=True)),
|
||||||
|
("channels", models.ManyToManyField(related_name="drop_campaigns", to="twitch_app.frontendchannel")),
|
||||||
|
(
|
||||||
|
"game",
|
||||||
|
models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="drop_campaigns",
|
||||||
|
to="twitch_app.frontendgame",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"abstract": False,
|
||||||
|
"base_manager_name": "prefetch_manager",
|
||||||
|
},
|
||||||
|
managers=[
|
||||||
|
("objects", django.db.models.manager.Manager()),
|
||||||
|
("prefetch_manager", django.db.models.manager.Manager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="FrontEndDrop",
|
||||||
|
fields=[
|
||||||
|
("id", models.TextField(primary_key=True, serialize=False)),
|
||||||
|
("created_at", models.DateTimeField(null=True)),
|
||||||
|
("name", models.TextField(blank=True, null=True)),
|
||||||
|
("image_url", models.URLField(blank=True, null=True)),
|
||||||
|
("limit", models.PositiveBigIntegerField(null=True)),
|
||||||
|
("is_ios_available", models.BooleanField(null=True)),
|
||||||
|
("minutes_watched", models.PositiveBigIntegerField(null=True)),
|
||||||
|
(
|
||||||
|
"drop_campaign",
|
||||||
|
models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="drops",
|
||||||
|
to="twitch_app.frontenddropcampaign",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"abstract": False,
|
||||||
|
"base_manager_name": "prefetch_manager",
|
||||||
|
},
|
||||||
|
managers=[
|
||||||
|
("objects", django.db.models.manager.Manager()),
|
||||||
|
("prefetch_manager", django.db.models.manager.Manager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="frontendgame",
|
||||||
|
name="org",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="games",
|
||||||
|
to="twitch_app.frontendorg",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
@ -1,3 +1,5 @@
|
|||||||
|
import typing
|
||||||
|
|
||||||
import auto_prefetch
|
import auto_prefetch
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
@ -25,6 +27,7 @@ class Game(auto_prefetch.Model):
|
|||||||
id = models.AutoField(primary_key=True)
|
id = models.AutoField(primary_key=True)
|
||||||
slug = models.TextField(null=True, blank=True)
|
slug = models.TextField(null=True, blank=True)
|
||||||
display_name = models.TextField(null=True, blank=True)
|
display_name = models.TextField(null=True, blank=True)
|
||||||
|
box_art_url = models.URLField(null=True, blank=True)
|
||||||
typename = models.TextField(null=True, blank=True)
|
typename = models.TextField(null=True, blank=True)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
@ -502,6 +505,11 @@ class DropCampaign(auto_prefetch.Model):
|
|||||||
typename (str): The type name of the object, typically "DropCampaign".
|
typename (str): The type name of the object, typically "DropCampaign".
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
STATUS_CHOICES: typing.ClassVar[list[tuple[str, str]]] = [
|
||||||
|
("ACTIVE", "Active"),
|
||||||
|
("EXPIRED", "Expired"),
|
||||||
|
]
|
||||||
|
|
||||||
id = models.TextField(primary_key=True)
|
id = models.TextField(primary_key=True)
|
||||||
allow = auto_prefetch.ForeignKey(Allow, on_delete=models.CASCADE, related_name="drop_campaigns", null=True)
|
allow = auto_prefetch.ForeignKey(Allow, on_delete=models.CASCADE, related_name="drop_campaigns", null=True)
|
||||||
account_link_url = models.URLField(null=True, blank=True)
|
account_link_url = models.URLField(null=True, blank=True)
|
||||||
@ -514,9 +522,68 @@ class DropCampaign(auto_prefetch.Model):
|
|||||||
name = models.TextField(null=True, blank=True)
|
name = models.TextField(null=True, blank=True)
|
||||||
owner = auto_prefetch.ForeignKey(Owner, on_delete=models.CASCADE, related_name="drop_campaigns", null=True)
|
owner = auto_prefetch.ForeignKey(Owner, on_delete=models.CASCADE, related_name="drop_campaigns", null=True)
|
||||||
starts_at = models.DateTimeField(null=True)
|
starts_at = models.DateTimeField(null=True)
|
||||||
status = models.TextField(null=True, blank=True)
|
status = models.TextField(choices=STATUS_CHOICES, null=True, blank=True)
|
||||||
time_based_drops = models.ManyToManyField(TimeBasedDrop, related_name="drop_campaigns")
|
time_based_drops = models.ManyToManyField(TimeBasedDrop, related_name="drop_campaigns")
|
||||||
typename = models.TextField(null=True, blank=True)
|
typename = models.TextField(null=True, blank=True)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.name or "Unknown"
|
return self.name or "Unknown"
|
||||||
|
|
||||||
|
|
||||||
|
class FrontEndChannel(auto_prefetch.Model):
|
||||||
|
"""This is the channel we will see on the front end."""
|
||||||
|
|
||||||
|
name = models.TextField(null=True, blank=True)
|
||||||
|
twitch_url = models.URLField(null=True, blank=True)
|
||||||
|
live = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
|
||||||
|
class FrontEndOrg(auto_prefetch.Model):
|
||||||
|
"""Drops are group by organization -> by game -> by drop campaign."""
|
||||||
|
|
||||||
|
id = models.TextField(primary_key=True)
|
||||||
|
name = models.TextField(null=True, blank=True)
|
||||||
|
url = models.TextField(null=True, blank=True)
|
||||||
|
|
||||||
|
|
||||||
|
class FrontEndGame(auto_prefetch.Model):
|
||||||
|
"""This is the game we will see on the front end."""
|
||||||
|
|
||||||
|
twitch_id = models.TextField(primary_key=True)
|
||||||
|
game_url = models.URLField(null=True, blank=True)
|
||||||
|
display_name = models.TextField(null=True, blank=True)
|
||||||
|
|
||||||
|
org = models.ForeignKey(FrontEndOrg, on_delete=models.CASCADE, related_name="games", null=True)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.display_name or "Unknown"
|
||||||
|
|
||||||
|
|
||||||
|
class FrontEndDropCampaign(auto_prefetch.Model):
|
||||||
|
"""This is the drop campaign we will see on the front end."""
|
||||||
|
|
||||||
|
account_link_url = models.URLField(null=True, blank=True)
|
||||||
|
about_url = models.URLField(null=True, blank=True)
|
||||||
|
|
||||||
|
ends_at = models.DateTimeField(null=True)
|
||||||
|
starts_at = models.DateTimeField(null=True)
|
||||||
|
|
||||||
|
game = models.ForeignKey(FrontEndGame, on_delete=models.CASCADE, related_name="drop_campaigns", null=True)
|
||||||
|
|
||||||
|
channels = models.ManyToManyField(FrontEndChannel, related_name="drop_campaigns")
|
||||||
|
|
||||||
|
|
||||||
|
class FrontEndDrop(auto_prefetch.Model):
|
||||||
|
"""This is the drop we will see on the front end."""
|
||||||
|
|
||||||
|
id = models.TextField(primary_key=True)
|
||||||
|
created_at = models.DateTimeField(null=True)
|
||||||
|
|
||||||
|
name = models.TextField(null=True, blank=True)
|
||||||
|
image_url = models.URLField(null=True, blank=True)
|
||||||
|
|
||||||
|
drop_campaign = models.ForeignKey(FrontEndDropCampaign, on_delete=models.CASCADE, related_name="drops", null=True)
|
||||||
|
|
||||||
|
limit = models.PositiveBigIntegerField(null=True)
|
||||||
|
is_ios_available = models.BooleanField(null=True)
|
||||||
|
minutes_watched = models.PositiveBigIntegerField(null=True)
|
||||||
|
Reference in New Issue
Block a user