Improve admin page
This commit is contained in:
@ -76,6 +76,7 @@ INSTALLED_APPS: list[str] = [
|
|||||||
"allauth.account",
|
"allauth.account",
|
||||||
"allauth.socialaccount",
|
"allauth.socialaccount",
|
||||||
"allauth.socialaccount.providers.twitch",
|
"allauth.socialaccount.providers.twitch",
|
||||||
|
"simple_history",
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE: list[str] = [
|
MIDDLEWARE: list[str] = [
|
||||||
@ -88,6 +89,7 @@ MIDDLEWARE: list[str] = [
|
|||||||
"django.contrib.messages.middleware.MessageMiddleware",
|
"django.contrib.messages.middleware.MessageMiddleware",
|
||||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||||
"allauth.account.middleware.AccountMiddleware",
|
"allauth.account.middleware.AccountMiddleware",
|
||||||
|
"simple_history.middleware.HistoryRequestMiddleware",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -166,9 +168,16 @@ LOGIN_REDIRECT_URL = "/"
|
|||||||
LOGOUT_REDIRECT_URL = "/"
|
LOGOUT_REDIRECT_URL = "/"
|
||||||
SOCIALACCOUNT_ONLY = True
|
SOCIALACCOUNT_ONLY = True
|
||||||
ACCOUNT_EMAIL_VERIFICATION = "none"
|
ACCOUNT_EMAIL_VERIFICATION = "none"
|
||||||
|
SOCIALACCOUNT_STORE_TOKENS = True
|
||||||
|
|
||||||
AUTHENTICATION_BACKENDS: list[str] = [
|
AUTHENTICATION_BACKENDS: list[str] = [
|
||||||
"django.contrib.auth.backends.ModelBackend",
|
"django.contrib.auth.backends.ModelBackend",
|
||||||
"allauth.account.auth_backends.AuthenticationBackend",
|
"allauth.account.auth_backends.AuthenticationBackend",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
SOCIALACCOUNT_PROVIDERS = {
|
||||||
|
"twitch": {
|
||||||
|
"SCOPE": ["user:read:email"],
|
||||||
|
"AUTH_PARAMS": {"force_verify": True},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from simple_history.admin import SimpleHistoryAdmin
|
||||||
|
|
||||||
from .models import DiscordSetting, Subscription
|
from .models import DiscordSetting, Subscription
|
||||||
|
|
||||||
admin.site.register(DiscordSetting)
|
# https://django-simple-history.readthedocs.io/en/latest/admin.html
|
||||||
admin.site.register(Subscription)
|
admin.site.register(DiscordSetting, SimpleHistoryAdmin)
|
||||||
|
admin.site.register(Subscription, SimpleHistoryAdmin)
|
||||||
|
@ -0,0 +1,146 @@
|
|||||||
|
# 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,5 +1,6 @@
|
|||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from simple_history.models import HistoricalRecords
|
||||||
|
|
||||||
from twitch_app.models import Game
|
from twitch_app.models import Game
|
||||||
|
|
||||||
@ -8,6 +9,7 @@ class DiscordSetting(models.Model):
|
|||||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
webhook_url = models.URLField()
|
webhook_url = models.URLField()
|
||||||
|
history = HistoricalRecords()
|
||||||
disabled = models.BooleanField(default=False)
|
disabled = models.BooleanField(default=False)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
@ -18,6 +20,7 @@ class Subscription(models.Model):
|
|||||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
game = models.ForeignKey(Game, on_delete=models.CASCADE)
|
game = models.ForeignKey(Game, on_delete=models.CASCADE)
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
history = HistoricalRecords()
|
||||||
discord_webhook = models.ForeignKey(DiscordSetting, on_delete=models.CASCADE)
|
discord_webhook = models.ForeignKey(DiscordSetting, on_delete=models.CASCADE)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
|
@ -9,8 +9,5 @@ playwright
|
|||||||
playwright
|
playwright
|
||||||
psycopg[binary]
|
psycopg[binary]
|
||||||
python-dotenv
|
python-dotenv
|
||||||
redis[hiredis]
|
|
||||||
selectolax
|
|
||||||
sentry-sdk[django]
|
sentry-sdk[django]
|
||||||
twitchAPI
|
|
||||||
whitenoise[brotli]
|
whitenoise[brotli]
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from simple_history.admin import SimpleHistoryAdmin
|
||||||
|
|
||||||
from .models import DropBenefit, DropCampaign, Game, Organization, TimeBasedDrop
|
from .models import DropBenefit, DropCampaign, Game, Organization, TimeBasedDrop
|
||||||
|
|
||||||
admin.site.register(DropBenefit)
|
# https://django-simple-history.readthedocs.io/en/latest/admin.html
|
||||||
admin.site.register(DropCampaign)
|
admin.site.register(DropBenefit, SimpleHistoryAdmin)
|
||||||
admin.site.register(Game)
|
admin.site.register(DropCampaign, SimpleHistoryAdmin)
|
||||||
admin.site.register(Organization)
|
admin.site.register(Game, SimpleHistoryAdmin)
|
||||||
admin.site.register(TimeBasedDrop)
|
admin.site.register(Organization, SimpleHistoryAdmin)
|
||||||
|
admin.site.register(TimeBasedDrop, SimpleHistoryAdmin)
|
||||||
|
@ -16,7 +16,6 @@ from twitch_app.models import (
|
|||||||
Game,
|
Game,
|
||||||
Organization,
|
Organization,
|
||||||
TimeBasedDrop,
|
TimeBasedDrop,
|
||||||
User,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -50,7 +49,7 @@ async def insert_data(data: dict) -> None: # noqa: PLR0914, C901
|
|||||||
logger.debug("No user data found")
|
logger.debug("No user data found")
|
||||||
return
|
return
|
||||||
|
|
||||||
user_id = 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:
|
||||||
return
|
return
|
||||||
@ -155,12 +154,6 @@ async def insert_data(data: dict) -> None: # noqa: PLR0914, C901
|
|||||||
if created:
|
if created:
|
||||||
logger.debug("Time-based drop created: %s", time_based_drop)
|
logger.debug("Time-based drop created: %s", time_based_drop)
|
||||||
|
|
||||||
# Create or get the user
|
|
||||||
user, created = await sync_to_async(User.objects.get_or_create)(id=user_id)
|
|
||||||
await sync_to_async(user.drop_campaigns.add)(drop_campaign)
|
|
||||||
if created:
|
|
||||||
logger.debug("User created: %s", user)
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Scrape Twitch Drops Campaigns with login using Firefox"
|
help = "Scrape Twitch Drops Campaigns with login using Firefox"
|
||||||
|
@ -0,0 +1,308 @@
|
|||||||
|
# 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),
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,23 @@
|
|||||||
|
# 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",
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,92 @@
|
|||||||
|
# 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,8 +1,11 @@
|
|||||||
|
from django.contrib.humanize.templatetags.humanize import naturaltime
|
||||||
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 django.utils import timezone
|
||||||
|
from simple_history.models import HistoricalRecords
|
||||||
|
|
||||||
|
|
||||||
class Organization(models.Model):
|
class Organization(models.Model):
|
||||||
@ -11,6 +14,11 @@ class Organization(models.Model):
|
|||||||
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)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = "Organization"
|
||||||
|
verbose_name_plural = "Organizations"
|
||||||
|
ordering = ("name",)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.name or self.id
|
return self.name or self.id
|
||||||
|
|
||||||
@ -35,6 +43,12 @@ class Game(models.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:
|
||||||
|
verbose_name = "Game"
|
||||||
|
verbose_name_plural = "Games"
|
||||||
|
ordering = ("display_name",)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.display_name or self.slug or self.id
|
return self.display_name or self.slug or self.id
|
||||||
@ -51,9 +65,15 @@ class DropBenefit(models.Model):
|
|||||||
game = models.ForeignKey(Game, on_delete=models.CASCADE)
|
game = models.ForeignKey(Game, on_delete=models.CASCADE)
|
||||||
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:
|
||||||
|
verbose_name = "Drop Benefit"
|
||||||
|
verbose_name_plural = "Drop Benefits"
|
||||||
|
ordering = ("name",)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.name or self.id
|
return f"{self.owner_organization.name} - {self.game.display_name} - {self.name}"
|
||||||
|
|
||||||
|
|
||||||
class TimeBasedDrop(models.Model):
|
class TimeBasedDrop(models.Model):
|
||||||
@ -66,9 +86,19 @@ class TimeBasedDrop(models.Model):
|
|||||||
benefits = models.ManyToManyField(DropBenefit)
|
benefits = models.ManyToManyField(DropBenefit)
|
||||||
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:
|
||||||
|
verbose_name = "Time-Based Drop"
|
||||||
|
verbose_name_plural = "Time-Based Drops"
|
||||||
|
ordering = ("name",)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.name or self.id
|
if self.end_at:
|
||||||
|
if self.end_at < timezone.now():
|
||||||
|
return f"{self.benefits.first()} - {self.name} - Ended {naturaltime(self.end_at)}"
|
||||||
|
return f"{self.benefits.first()} - {self.name} - Ends in {naturaltime(self.end_at)}"
|
||||||
|
return f"{self.benefits.first()} - {self.name}"
|
||||||
|
|
||||||
|
|
||||||
class DropCampaign(models.Model):
|
class DropCampaign(models.Model):
|
||||||
@ -94,16 +124,12 @@ class DropCampaign(models.Model):
|
|||||||
time_based_drops = models.ManyToManyField(TimeBasedDrop)
|
time_based_drops = models.ManyToManyField(TimeBasedDrop)
|
||||||
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:
|
||||||
|
verbose_name = "Drop Campaign"
|
||||||
|
verbose_name_plural = "Drop Campaigns"
|
||||||
|
ordering = ("name",)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.name or self.id
|
return f"{self.owner.name} - {self.game.display_name} - {self.name}"
|
||||||
|
|
||||||
|
|
||||||
class User(models.Model):
|
|
||||||
id = models.TextField(primary_key=True)
|
|
||||||
drop_campaigns = models.ManyToManyField(DropCampaign)
|
|
||||||
added_at = models.DateTimeField(blank=True, null=True, auto_now_add=True)
|
|
||||||
modified_at = models.DateTimeField(blank=True, null=True, auto_now=True)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return self.id
|
|
||||||
|
Reference in New Issue
Block a user