Add section markers

This commit is contained in:
Joakim Hellsén 2025-09-13 23:17:17 +02:00
commit 007b8f7ec6
7 changed files with 44 additions and 4 deletions

View file

@ -5,6 +5,7 @@ from django.contrib import admin
from twitch.models import DropBenefit, DropBenefitEdge, DropCampaign, Game, Organization, TimeBasedDrop
# MARK: Game
@admin.register(Game)
class GameAdmin(admin.ModelAdmin):
"""Admin configuration for Game model."""
@ -14,6 +15,7 @@ class GameAdmin(admin.ModelAdmin):
readonly_fields = ("added_at", "updated_at")
# MARK: Organization
@admin.register(Organization)
class OrganizationAdmin(admin.ModelAdmin):
"""Admin configuration for Organization model."""
@ -30,6 +32,7 @@ class TimeBasedDropInline(admin.TabularInline):
extra = 0
# MARK: DropCampaign
@admin.register(DropCampaign)
class DropCampaignAdmin(admin.ModelAdmin):
"""Admin configuration for DropCampaign model."""
@ -48,6 +51,7 @@ class DropBenefitEdgeInline(admin.TabularInline):
extra = 0
# MARK: TimeBasedDrop
@admin.register(TimeBasedDrop)
class TimeBasedDropAdmin(admin.ModelAdmin):
"""Admin configuration for TimeBasedDrop model."""
@ -68,6 +72,7 @@ class TimeBasedDropAdmin(admin.ModelAdmin):
inlines = [DropBenefitEdgeInline]
# MARK: DropBenefit
@admin.register(DropBenefit)
class DropBenefitAdmin(admin.ModelAdmin):
"""Admin configuration for DropBenefit model."""

View file

@ -12,6 +12,7 @@ if TYPE_CHECKING:
import datetime
# MARK: /rss/organizations/
class OrganizationFeed(Feed):
"""RSS feed for latest organizations."""
@ -36,6 +37,7 @@ class OrganizationFeed(Feed):
return reverse("twitch:organization_detail", args=[item.pk])
# MARK: /rss/games/
class GameFeed(Feed):
"""RSS feed for latest games."""
@ -60,6 +62,7 @@ class GameFeed(Feed):
return reverse("twitch:game_detail", args=[item.pk])
# MARK: /rss/campaigns/
class DropCampaignFeed(Feed):
"""RSS feed for latest drop campaigns."""

View file

@ -19,6 +19,7 @@ if TYPE_CHECKING:
logger: logging.Logger = logging.getLogger("ttvdrops")
# MARK: Organization
class Organization(auto_prefetch.Model):
"""Represents an organization on Twitch that can own drop campaigns."""
@ -63,6 +64,7 @@ class Organization(auto_prefetch.Model):
return self.name or self.id
# MARK: Game
class Game(auto_prefetch.Model):
"""Represents a game on Twitch."""
@ -204,6 +206,7 @@ class Game(auto_prefetch.Model):
return ""
# MARK: Channel
class Channel(auto_prefetch.Model):
"""Represents a Twitch channel that can participate in drop campaigns."""
@ -248,6 +251,7 @@ class Channel(auto_prefetch.Model):
return self.display_name or self.name or self.id
# MARK: DropCampaign
class DropCampaign(auto_prefetch.Model):
"""Represents a Twitch drop campaign."""
@ -409,6 +413,7 @@ class DropCampaign(auto_prefetch.Model):
return self.image_url or ""
# MARK: DropBenefit
class DropBenefit(auto_prefetch.Model):
"""Represents a benefit that can be earned from a drop."""
@ -501,6 +506,7 @@ class DropBenefit(auto_prefetch.Model):
return self.image_asset_url or ""
# MARK: TimeBasedDrop
class TimeBasedDrop(auto_prefetch.Model):
"""Represents a time-based drop in a drop campaign."""
@ -593,6 +599,7 @@ class TimeBasedDrop(auto_prefetch.Model):
return self.name
# MARK: DropBenefitEdge
class DropBenefitEdge(auto_prefetch.Model):
"""Represents the relationship between a TimeBasedDrop and a DropBenefit."""
@ -634,6 +641,7 @@ class DropBenefitEdge(auto_prefetch.Model):
return f"{self.drop.name} - {self.benefit.name}"
# MARK: NotificationSubscription
class NotificationSubscription(auto_prefetch.Model):
"""Users can subscribe to games to get notified."""

View file

@ -1,5 +1,7 @@
from __future__ import annotations
from typing import TYPE_CHECKING
from django.urls import path
from twitch import views
@ -9,9 +11,12 @@ from twitch.feeds import (
OrganizationFeed,
)
if TYPE_CHECKING:
from django.urls.resolvers import URLPattern
app_name = "twitch"
urlpatterns = [
urlpatterns: list[URLPattern] = [
path("", views.dashboard, name="dashboard"),
path("search/", views.search_view, name="search"),
path("debug/", views.debug_view, name="debug"),

View file

@ -35,6 +35,7 @@ MIN_QUERY_LENGTH_FOR_FTS = 3
MIN_SEARCH_RANK = 0.05
# MARK: /search/
def search_view(request: HttpRequest) -> HttpResponse:
"""Search view for all models.
@ -95,6 +96,7 @@ def search_view(request: HttpRequest) -> HttpResponse:
return render(request, "twitch/search_results.html", {"query": query, "results": results})
# MARK: /organizations/
class OrgListView(ListView):
"""List view for organization."""
@ -103,6 +105,7 @@ class OrgListView(ListView):
context_object_name = "orgs"
# MARK: /organizations/<pk>/
class OrgDetailView(DetailView):
"""Detail view for organization."""
@ -157,6 +160,7 @@ class OrgDetailView(DetailView):
return context
# MARK: /campaigns/
class DropCampaignListView(ListView):
"""List view for drop campaigns."""
@ -213,6 +217,7 @@ def format_and_color_json(code: str) -> str:
return highlight(formatted_code, JsonLexer(), HtmlFormatter())
# MARK: /campaigns/<pk>/
class DropCampaignDetailView(DetailView):
"""Detail view for a drop campaign."""
@ -342,6 +347,7 @@ class DropCampaignDetailView(DetailView):
return context
# MARK: /games/
class GamesGridView(ListView):
"""List view for games grouped by organization."""
@ -412,6 +418,7 @@ class GamesGridView(ListView):
return context
# MARK: /games/<pk>/
class GameDetailView(DetailView):
"""Detail view for a game."""
@ -574,6 +581,7 @@ def dashboard(request: HttpRequest) -> HttpResponse:
)
# MARK: /debug/
@login_required
def debug_view(request: HttpRequest) -> HttpResponse:
"""Debug view showing potentially broken or inconsistent data.
@ -635,6 +643,7 @@ def debug_view(request: HttpRequest) -> HttpResponse:
return render(request, "twitch/debug.html", context)
# MARK: /games/<pk>/subscribe/
@login_required
def subscribe_game_notifications(request: HttpRequest, game_id: str) -> HttpResponseRedirect:
"""Update Game notification for a user.
@ -678,6 +687,7 @@ def subscribe_game_notifications(request: HttpRequest, game_id: str) -> HttpResp
return redirect("twitch:game_detail", pk=game.id)
# MARK: /organizations/<pk>/subscribe/
@login_required
def subscribe_org_notifications(request: HttpRequest, org_id: str) -> HttpResponseRedirect:
"""Update Organization notification for a user.
@ -722,12 +732,14 @@ def subscribe_org_notifications(request: HttpRequest, org_id: str) -> HttpRespon
return redirect("twitch:organization_detail", pk=organization.id)
# MARK: /games/list/
class GamesListView(GamesGridView):
"""List view for games in simple list format."""
template_name = "twitch/games_list.html"
# MARK: /docs/rss/
def docs_rss_view(request: HttpRequest) -> HttpResponse:
"""View for /docs/rss that lists all available RSS feeds.
@ -757,6 +769,7 @@ def docs_rss_view(request: HttpRequest) -> HttpResponse:
return render(request, "twitch/docs_rss.html", {"feeds": feeds})
# MARK: /channels/
class ChannelListView(ListView):
"""List view for channels."""
@ -793,6 +806,7 @@ class ChannelListView(ListView):
return context
# MARK: /channels/<pk>/
class ChannelDetailView(DetailView):
"""Detail view for a channel."""