Refactor RSS feed documentation and optimize query limits in views

This commit is contained in:
Joakim Hellsén 2026-02-09 23:23:36 +01:00
commit 0a0345f217
Signed by: Joakim Hellsén
SSH key fingerprint: SHA256:/9h/CsExpFp+PRhsfA0xznFx2CGfTT5R/kpuFfUgEQk
4 changed files with 177 additions and 44 deletions

View file

@ -32,6 +32,7 @@ if TYPE_CHECKING:
from django.db.models import Model
from django.db.models import QuerySet
from django.http import HttpRequest
from django.http import HttpResponse
logger: logging.Logger = logging.getLogger("ttvdrops")
@ -308,10 +309,30 @@ class OrganizationRSSFeed(Feed):
link: str = "/organizations/"
description: str = "Latest organizations on TTVDrops"
feed_copyright: str = "Information wants to be free."
_limit: int | None = None
def __call__(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
"""Override to capture limit parameter from request.
Args:
request (HttpRequest): The incoming HTTP request, potentially containing a 'limit' query parameter.
*args: Additional positional arguments.
**kwargs: Additional keyword arguments.
Returns:
HttpResponse: The HTTP response generated by the parent Feed class after processing the request.
"""
if request.GET.get("limit"):
try:
self._limit = int(request.GET.get("limit", 200))
except ValueError, TypeError:
self._limit = None
return super().__call__(request, *args, **kwargs)
def items(self) -> QuerySet[Organization, Organization]:
"""Return the latest 200 organizations."""
return Organization.objects.order_by("-added_at")[:200]
"""Return the latest organizations (default 200, or limited by ?limit query param)."""
limit: int = self._limit if self._limit is not None else 200
return Organization.objects.order_by("-added_at")[:limit]
def item_title(self, item: Organization) -> SafeText:
"""Return the organization name as the item title."""
@ -355,10 +376,30 @@ class GameFeed(Feed):
link: str = "/games/"
description: str = "Latest games on TTVDrops"
feed_copyright: str = "Information wants to be free."
_limit: int | None = None
def __call__(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
"""Override to capture limit parameter from request.
Args:
request (HttpRequest): The incoming HTTP request, potentially containing a 'limit' query parameter.
*args: Additional positional arguments.
**kwargs: Additional keyword arguments.
Returns:
HttpResponse: The HTTP response generated by the parent Feed class after processing the request.
"""
if request.GET.get("limit"):
try:
self._limit = int(request.GET.get("limit", 200))
except ValueError, TypeError:
self._limit = None
return super().__call__(request, *args, **kwargs)
def items(self) -> list[Game]:
"""Return the latest 200 games."""
return list(Game.objects.order_by("-added_at")[:200])
"""Return the latest games (default 200, or limited by ?limit query param)."""
limit: int = self._limit if self._limit is not None else 200
return list(Game.objects.order_by("-added_at")[:limit])
def item_title(self, item: Model) -> SafeText:
"""Return the game name as the item title (SafeText for RSS)."""
@ -472,11 +513,31 @@ class DropCampaignFeed(Feed):
description: str = "Latest Twitch drop campaigns on TTVDrops"
feed_url: str = "/rss/campaigns/"
feed_copyright: str = "Information wants to be free."
_limit: int | None = None
def __call__(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
"""Override to capture limit parameter from request.
Args:
request (HttpRequest): The incoming HTTP request, potentially containing a 'limit' query parameter.
*args: Additional positional arguments.
**kwargs: Additional keyword arguments.
Returns:
HttpResponse: The HTTP response generated by the parent Feed class after processing the request.
"""
if request.GET.get("limit"):
try:
self._limit = int(request.GET.get("limit", 200))
except ValueError, TypeError:
self._limit = None
return super().__call__(request, *args, **kwargs)
def items(self) -> list[DropCampaign]:
"""Return the latest 200 drop campaigns ordered by most recent start date."""
"""Return the latest drop campaigns ordered by most recent start date (default 200, or limited by ?limit query param).""" # noqa: E501
limit: int = self._limit if self._limit is not None else 200
queryset: QuerySet[DropCampaign] = DropCampaign.objects.order_by("-start_at")
return list(_with_campaign_related(queryset)[:200])
return list(_with_campaign_related(queryset)[:limit])
def item_title(self, item: Model) -> SafeText:
"""Return the campaign name as the item title (SafeText for RSS)."""
@ -593,6 +654,25 @@ class GameCampaignFeed(Feed):
"""RSS feed for the latest drop campaigns of a specific game."""
feed_copyright: str = "Information wants to be free."
_limit: int | None = None
def __call__(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
"""Override to capture limit parameter from request.
Args:
request (HttpRequest): The incoming HTTP request, potentially containing a 'limit' query parameter
*args: Additional positional arguments.
**kwargs: Additional keyword arguments.
Returns:
HttpResponse: The HTTP response generated by the parent Feed class after processing the request.
"""
if request.GET.get("limit"):
try:
self._limit = int(request.GET.get("limit", 200))
except ValueError, TypeError:
self._limit = None
return super().__call__(request, *args, **kwargs)
def get_object(self, request: HttpRequest, twitch_id: str) -> Game: # noqa: ARG002
"""Retrieve the Game instance for the given Twitch ID.
@ -623,9 +703,10 @@ class GameCampaignFeed(Feed):
return reverse("twitch:game_campaign_feed", args=[obj.twitch_id])
def items(self, obj: Game) -> list[DropCampaign]:
"""Return the latest 200 drop campaigns for this game, ordered by most recent start date."""
"""Return the latest drop campaigns for this game, ordered by most recent start date (default 200, or limited by ?limit query param).""" # noqa: E501
limit: int = self._limit if self._limit is not None else 200
queryset: QuerySet[DropCampaign] = DropCampaign.objects.filter(game=obj).order_by("-start_at")
return list(_with_campaign_related(queryset)[:200])
return list(_with_campaign_related(queryset)[:limit])
def item_title(self, item: Model) -> SafeText:
"""Return the campaign name as the item title (SafeText for RSS)."""
@ -738,6 +819,26 @@ class GameCampaignFeed(Feed):
class OrganizationCampaignFeed(Feed):
"""RSS feed for campaigns of a specific organization."""
_limit: int | None = None
def __call__(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
"""Override to capture limit parameter from request.
Args:
request (HttpRequest): The incoming HTTP request, potentially containing a 'limit' query parameter
*args: Additional positional arguments.
**kwargs: Additional keyword arguments.
Returns:
HttpResponse: The HTTP response generated by the parent Feed class after processing the request.
"""
if request.GET.get("limit"):
try:
self._limit = int(request.GET.get("limit", 200))
except ValueError, TypeError:
self._limit = None
return super().__call__(request, *args, **kwargs)
def get_object(self, request: HttpRequest, twitch_id: str) -> Organization: # noqa: ARG002
"""Retrieve the Organization instance for the given Twitch ID.
@ -763,9 +864,10 @@ class OrganizationCampaignFeed(Feed):
return f"Latest drop campaigns for organization {obj.name}"
def items(self, obj: Organization) -> list[DropCampaign]:
"""Return the latest 200 drop campaigns for this organization, ordered by most recent start date."""
"""Return the latest drop campaigns for this organization, ordered by most recent start date (default 200, or limited by ?limit query param).""" # noqa: E501
limit: int = self._limit if self._limit is not None else 200
queryset: QuerySet[DropCampaign] = DropCampaign.objects.filter(game__owners=obj).order_by("-start_at")
return list(_with_campaign_related(queryset)[:200])
return list(_with_campaign_related(queryset)[:limit])
def item_author_name(self, item: DropCampaign) -> str:
"""Return the author name for the campaign, typically the game name."""
@ -874,11 +976,31 @@ class RewardCampaignFeed(Feed):
description: str = "Latest Twitch reward campaigns (Quest rewards) on TTVDrops"
feed_url: str = "/rss/reward-campaigns/"
feed_copyright: str = "Information wants to be free."
_limit: int | None = None
def __call__(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
"""Override to capture limit parameter from request.
Args:
request (HttpRequest): The incoming HTTP request, potentially containing a 'limit' query parameter.
*args: Additional positional arguments.
**kwargs: Additional keyword arguments.
Returns:
HttpResponse: The HTTP response generated by the parent Feed class after processing the request.
"""
if request.GET.get("limit"):
try:
self._limit = int(request.GET.get("limit", 200))
except ValueError, TypeError:
self._limit = None
return super().__call__(request, *args, **kwargs)
def items(self) -> list[RewardCampaign]:
"""Return the latest 200 reward campaigns."""
"""Return the latest reward campaigns (default 200, or limited by ?limit query param)."""
limit: int = self._limit if self._limit is not None else 200
return list(
RewardCampaign.objects.select_related("game").order_by("-added_at")[:200],
RewardCampaign.objects.select_related("game").order_by("-added_at")[:limit],
)
def item_title(self, item: Model) -> SafeText: