Update webhook page
This commit is contained in:
@ -21,9 +21,9 @@ repos:
|
|||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: mixed-line-ending
|
- id: mixed-line-ending
|
||||||
- id: name-tests-test
|
- id: name-tests-test
|
||||||
args: [--pytest-test-first]
|
args: [ --pytest-test-first ]
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
args: [--markdown-linebreak-ext=md]
|
args: [ --markdown-linebreak-ext=md ]
|
||||||
exclude_types:
|
exclude_types:
|
||||||
- "html"
|
- "html"
|
||||||
|
|
||||||
@ -32,22 +32,22 @@ repos:
|
|||||||
rev: "1.19.0"
|
rev: "1.19.0"
|
||||||
hooks:
|
hooks:
|
||||||
- id: django-upgrade
|
- id: django-upgrade
|
||||||
args: [--target-version, "5.1"]
|
args: [ --target-version, "5.1" ]
|
||||||
|
|
||||||
# Run Pyupgrade on all Python files. This will upgrade the code to Python 3.12.
|
# Run Pyupgrade on all Python files. This will upgrade the code to Python 3.12.
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
rev: v3.16.0
|
rev: v3.16.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
args: ["--py312-plus"]
|
args: [ "--py312-plus" ]
|
||||||
|
|
||||||
# An extremely fast Python linter and formatter.
|
# An extremely fast Python linter and formatter.
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.5.0
|
rev: v0.5.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
- id: ruff
|
- id: ruff
|
||||||
args: ["--fix", "--exit-non-zero-on-fix"]
|
args: [ "--fix", "--exit-non-zero-on-fix" ]
|
||||||
|
|
||||||
# Static checker for GitHub Actions workflow files.
|
# Static checker for GitHub Actions workflow files.
|
||||||
- repo: https://github.com/rhysd/actionlint
|
- repo: https://github.com/rhysd/actionlint
|
||||||
|
@ -8,7 +8,6 @@ from platformdirs import user_data_dir
|
|||||||
|
|
||||||
load_dotenv(dotenv_path=find_dotenv(), verbose=True)
|
load_dotenv(dotenv_path=find_dotenv(), verbose=True)
|
||||||
|
|
||||||
|
|
||||||
DATA_DIR = Path(
|
DATA_DIR = Path(
|
||||||
user_data_dir(
|
user_data_dir(
|
||||||
appname="TTVDrops",
|
appname="TTVDrops",
|
||||||
@ -28,7 +27,6 @@ sentry_sdk.init(
|
|||||||
profiles_sample_rate=0.2,
|
profiles_sample_rate=0.2,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
BASE_DIR: Path = Path(__file__).resolve().parent.parent
|
BASE_DIR: Path = Path(__file__).resolve().parent.parent
|
||||||
ADMINS: list[tuple[str, str]] = [("Joakim Hellsén", "tlovinator@gmail.com")]
|
ADMINS: list[tuple[str, str]] = [("Joakim Hellsén", "tlovinator@gmail.com")]
|
||||||
WSGI_APPLICATION = "config.wsgi.application"
|
WSGI_APPLICATION = "config.wsgi.application"
|
||||||
@ -89,7 +87,6 @@ MIDDLEWARE: list[str] = [
|
|||||||
"simple_history.middleware.HistoryRequestMiddleware",
|
"simple_history.middleware.HistoryRequestMiddleware",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1 class="my-4">Add Discord Webhook</h1>
|
<h1 class="my-4">Add Discord Webhook</h1>
|
||||||
|
<div class="card card-body mb-3">
|
||||||
|
Webhooks will be saved in a cookie and will be sent to the server when you subscribe to a drop.
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
<form method="post" class="needs-validation" novalidate>
|
<form method="post" class="needs-validation" novalidate>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form.non_field_errors }}
|
{{ form.non_field_errors }}
|
||||||
@ -18,6 +22,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary">Add Webhook</button>
|
<button type="submit" class="btn btn-primary">Add Webhook</button>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
<h2 class="mt-5">Webhooks</h2>
|
<h2 class="mt-5">Webhooks</h2>
|
||||||
{% if webhooks %}
|
{% if webhooks %}
|
||||||
<ul class="list-group mt-3">
|
<ul class="list-group mt-3">
|
||||||
|
@ -8,13 +8,13 @@ if TYPE_CHECKING:
|
|||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture
|
||||||
def factory() -> RequestFactory:
|
def factory() -> RequestFactory:
|
||||||
"""Factory for creating requests."""
|
"""Factory for creating requests."""
|
||||||
return RequestFactory()
|
return RequestFactory()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db()
|
@pytest.mark.django_db
|
||||||
def test_index_view(client: Client) -> None:
|
def test_index_view(client: Client) -> None:
|
||||||
"""Test index view."""
|
"""Test index view."""
|
||||||
url: str = reverse(viewname="core:index")
|
url: str = reverse(viewname="core:index")
|
||||||
|
@ -6,7 +6,6 @@ from . import views
|
|||||||
|
|
||||||
app_name: str = "core"
|
app_name: str = "core"
|
||||||
|
|
||||||
|
|
||||||
urlpatterns: list[URLPattern | URLResolver] = [
|
urlpatterns: list[URLPattern | URLResolver] = [
|
||||||
path(route="", view=views.index, name="index"),
|
path(route="", view=views.index, name="index"),
|
||||||
path(
|
path(
|
||||||
|
@ -11,7 +11,6 @@ from django.contrib import messages
|
|||||||
from django.http.response import HttpResponse
|
from django.http.response import HttpResponse
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
from django.views.generic import FormView, ListView
|
from django.views.generic import FormView, ListView
|
||||||
from httpx._models import Response
|
|
||||||
|
|
||||||
from twitch_app.models import (
|
from twitch_app.models import (
|
||||||
DropBenefit,
|
DropBenefit,
|
||||||
@ -33,7 +32,6 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
logger: logging.Logger = logging.getLogger(__name__)
|
logger: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
cache_dir: Path = settings.DATA_DIR / "cache"
|
cache_dir: Path = settings.DATA_DIR / "cache"
|
||||||
cache_dir.mkdir(exist_ok=True, parents=True)
|
cache_dir.mkdir(exist_ok=True, parents=True)
|
||||||
storage = hishel.FileStorage(base_path=cache_dir)
|
storage = hishel.FileStorage(base_path=cache_dir)
|
||||||
@ -284,7 +282,7 @@ class WebhooksView(FormView):
|
|||||||
|
|
||||||
webhooks.append(webhook)
|
webhooks.append(webhook)
|
||||||
response: HttpResponse = self.render_to_response(self.get_context_data(form=form))
|
response: HttpResponse = self.render_to_response(self.get_context_data(form=form))
|
||||||
response.set_cookie(key="webhooks", value=",".join(webhooks), max_age=60 * 60 * 24 * 365)
|
response.set_cookie(key="webhooks", value=",".join(webhooks), max_age=315360000) # 10 years
|
||||||
|
|
||||||
messages.success(self.request, "Webhook successfully added.")
|
messages.success(self.request, "Webhook successfully added.")
|
||||||
return response
|
return response
|
||||||
|
@ -6,7 +6,7 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
ulimits:
|
ulimits:
|
||||||
memlock: -1
|
memlock: -1
|
||||||
command: ["--auth", "Password", "--password", "${GARNET_PASSWORD}", "--storage-tier", "--logdir", "/logs", "--aof", "--port", "6380"]
|
command: [ "--auth", "Password", "--password", "${GARNET_PASSWORD}", "--storage-tier", "--logdir", "/logs", "--aof", "--port", "6380" ]
|
||||||
ports:
|
ports:
|
||||||
- "6380:6380"
|
- "6380:6380"
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -37,7 +37,7 @@ lint.ignore = [
|
|||||||
[tool.djlint]
|
[tool.djlint]
|
||||||
profile = "django"
|
profile = "django"
|
||||||
format_attribute_template_tags = true
|
format_attribute_template_tags = true
|
||||||
ignore="H006" # Img tag should have height and width attributes.
|
ignore = "H006" # Img tag should have height and width attributes.
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
DJANGO_SETTINGS_MODULE = "config.settings"
|
DJANGO_SETTINGS_MODULE = "config.settings"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
djlint
|
djlint
|
||||||
|
pip
|
||||||
pre-commit
|
pre-commit
|
||||||
ruff
|
|
||||||
pytest
|
pytest
|
||||||
pytest-django
|
pytest-django
|
||||||
|
ruff
|
||||||
|
@ -8,7 +8,6 @@ httpx
|
|||||||
pillow
|
pillow
|
||||||
platformdirs
|
platformdirs
|
||||||
playwright
|
playwright
|
||||||
psycopg[binary]
|
|
||||||
python-dotenv
|
python-dotenv
|
||||||
sentry-sdk[django]
|
sentry-sdk[django]
|
||||||
whitenoise[brotli]
|
whitenoise[brotli]
|
||||||
|
@ -86,9 +86,7 @@ class DropCampaignSchema(Schema):
|
|||||||
|
|
||||||
# http://localhost:8000/api/twitch/organizations
|
# http://localhost:8000/api/twitch/organizations
|
||||||
@router.get("/organizations", response=list[OrganizationSchema])
|
@router.get("/organizations", response=list[OrganizationSchema])
|
||||||
def get_organizations(
|
def get_organizations(request: HttpRequest) -> BaseManager[Organization]: # noqa: ARG001
|
||||||
request: HttpRequest, # noqa: ARG001
|
|
||||||
) -> BaseManager[Organization]:
|
|
||||||
"""Get all organizations."""
|
"""Get all organizations."""
|
||||||
return Organization.objects.all()
|
return Organization.objects.all()
|
||||||
|
|
||||||
@ -109,17 +107,13 @@ def get_drop_benefits(request: HttpRequest) -> BaseManager[DropBenefit]: # noqa
|
|||||||
|
|
||||||
# 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(
|
def get_drop_campaigns(request: HttpRequest) -> BaseManager[DropCampaign]: # noqa: ARG001
|
||||||
request: HttpRequest, # noqa: ARG001
|
|
||||||
) -> BaseManager[DropCampaign]:
|
|
||||||
"""Get all drop campaigns."""
|
"""Get all drop campaigns."""
|
||||||
return DropCampaign.objects.all()
|
return DropCampaign.objects.all()
|
||||||
|
|
||||||
|
|
||||||
# http://localhost:8000/api/twitch/time_based_drops
|
# http://localhost:8000/api/twitch/time_based_drops
|
||||||
@router.get("/time_based_drops", response=list[TimeBasedDropSchema])
|
@router.get("/time_based_drops", response=list[TimeBasedDropSchema])
|
||||||
def get_time_based_drops(
|
def get_time_based_drops(request: HttpRequest) -> BaseManager[TimeBasedDrop]: # noqa: ARG001
|
||||||
request: HttpRequest, # noqa: ARG001
|
|
||||||
) -> BaseManager[TimeBasedDrop]:
|
|
||||||
"""Get all time-based drops."""
|
"""Get all time-based drops."""
|
||||||
return TimeBasedDrop.objects.all()
|
return TimeBasedDrop.objects.all()
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
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
|
||||||
@ -19,9 +21,9 @@ class Organization(auto_prefetch.Model):
|
|||||||
modified_at = models.DateTimeField(blank=True, null=True, auto_now=True)
|
modified_at = models.DateTimeField(blank=True, null=True, auto_now=True)
|
||||||
|
|
||||||
class Meta(auto_prefetch.Model.Meta):
|
class Meta(auto_prefetch.Model.Meta):
|
||||||
verbose_name = "Organization"
|
verbose_name: str = "Organization"
|
||||||
verbose_name_plural = "Organizations"
|
verbose_name_plural: str = "Organizations"
|
||||||
ordering = ("name",)
|
ordering: tuple[Literal["name"]] = ("name",)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.name or self.id
|
return self.name or self.id
|
||||||
@ -55,9 +57,9 @@ class Game(auto_prefetch.Model):
|
|||||||
history = HistoricalRecords()
|
history = HistoricalRecords()
|
||||||
|
|
||||||
class Meta(auto_prefetch.Model.Meta):
|
class Meta(auto_prefetch.Model.Meta):
|
||||||
verbose_name = "Game"
|
verbose_name: str = "Game"
|
||||||
verbose_name_plural = "Games"
|
verbose_name_plural: str = "Games"
|
||||||
ordering = ("display_name",)
|
ordering: tuple[Literal["display_name"]] = ("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
|
||||||
@ -83,9 +85,9 @@ class DropBenefit(auto_prefetch.Model):
|
|||||||
history = HistoricalRecords()
|
history = HistoricalRecords()
|
||||||
|
|
||||||
class Meta(auto_prefetch.Model.Meta):
|
class Meta(auto_prefetch.Model.Meta):
|
||||||
verbose_name = "Drop Benefit"
|
verbose_name: str = "Drop Benefit"
|
||||||
verbose_name_plural = "Drop Benefits"
|
verbose_name_plural: str = "Drop Benefits"
|
||||||
ordering = ("name",)
|
ordering: tuple[Literal["name"]] = ("name",)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return f"{self.owner_organization.name} - {self.game.display_name} - {self.name}"
|
return f"{self.owner_organization.name} - {self.game.display_name} - {self.name}"
|
||||||
@ -106,9 +108,9 @@ class TimeBasedDrop(auto_prefetch.Model):
|
|||||||
history = HistoricalRecords()
|
history = HistoricalRecords()
|
||||||
|
|
||||||
class Meta(auto_prefetch.Model.Meta):
|
class Meta(auto_prefetch.Model.Meta):
|
||||||
verbose_name = "Time-Based Drop"
|
verbose_name: str = "Time-Based Drop"
|
||||||
verbose_name_plural = "Time-Based Drops"
|
verbose_name_plural: str = "Time-Based Drops"
|
||||||
ordering = ("name",)
|
ordering: tuple[Literal["name"]] = ("name",)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return f"{self.benefits.first()} - {self.name}"
|
return f"{self.benefits.first()} - {self.name}"
|
||||||
@ -145,9 +147,9 @@ class DropCampaign(auto_prefetch.Model):
|
|||||||
history = HistoricalRecords()
|
history = HistoricalRecords()
|
||||||
|
|
||||||
class Meta(auto_prefetch.Model.Meta):
|
class Meta(auto_prefetch.Model.Meta):
|
||||||
verbose_name = "Drop Campaign"
|
verbose_name: str = "Drop Campaign"
|
||||||
verbose_name_plural = "Drop Campaigns"
|
verbose_name_plural: str = "Drop Campaigns"
|
||||||
ordering = ("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.owner.name} - {self.game.display_name} - {self.name}"
|
||||||
|
Reference in New Issue
Block a user