from __future__ import annotations
from typing import TYPE_CHECKING
from django.contrib.syndication.views import Feed
from django.urls import reverse
from django.utils.html import format_html
from twitch.models import DropCampaign, Game, Organization
if TYPE_CHECKING:
import datetime
class OrganizationFeed(Feed):
"""RSS feed for latest organizations."""
title = "TTVDrops Organizations"
link = "/organizations/"
description = "Latest organizations on TTVDrops"
def items(self) -> list[Organization]:
"""Return the latest 100 organizations."""
return list(Organization.objects.order_by("-id")[:100])
def item_title(self, item: Organization) -> str:
"""Return the organization name as the item title."""
return item.name
def item_description(self, item: Organization) -> str:
"""Return a description of the organization."""
return f"Organization {item.name}"
def item_link(self, item: Organization) -> str:
"""Return the link to the organization detail."""
return reverse("twitch:organization_detail", args=[item.pk])
class GameFeed(Feed):
"""RSS feed for latest games."""
title = "TTVDrops Games"
link = "/games/"
description = "Latest games on TTVDrops"
def items(self) -> list[Game]:
"""Return the latest 100 games."""
return list(Game.objects.order_by("-id")[:100])
def item_title(self, item: Game) -> str:
"""Return the game name as the item title."""
return str(item)
def item_description(self, item: Game) -> str:
"""Return a description of the game."""
return f"Game {item.display_name}"
def item_link(self, item: Game) -> str:
"""Return the link to the game detail."""
return reverse("twitch:game_detail", args=[item.pk])
class DropCampaignFeed(Feed):
"""RSS feed for latest drop campaigns."""
title = "Twitch Drop Campaigns"
link = "/campaigns/"
description = "Latest Twitch drop campaigns"
feed_url = "/rss/campaigns/"
feed_copyright = "Information wants to be free."
def items(self) -> list[DropCampaign]:
"""Return the latest 100 drop campaigns."""
return list(DropCampaign.objects.select_related("game").order_by("-added_at")[:100])
def item_title(self, item: DropCampaign) -> str:
"""Return the campaign name as the item title."""
return f"{item.game.display_name}: {item.clean_name}"
def item_description(self, item: DropCampaign) -> str:
"""Return a description of the campaign."""
description = ""
# Include the campaign image if available
if item.image_url:
description += format_html(
'
',
item.image_url,
item.name,
)
# Add the campaign description text
description += format_html("
{}
", item.description) if item.description else "" # Add start and end dates for clarity if item.start_at: description += f"Starts: {item.start_at.strftime('%Y-%m-%d %H:%M %Z')}
" if item.end_at: description += f"Ends: {item.end_at.strftime('%Y-%m-%d %H:%M %Z')}
" # Add a clear link to the campaign details page if item.details_url: description += format_html('', item.details_url) return f"{description}" def item_link(self, item: DropCampaign) -> str: """Return the link to the campaign detail.""" return reverse("twitch:campaign_detail", args=[item.pk]) def item_pubdate(self, item: DropCampaign) -> datetime.datetime: """Returns the publication date to the feed item.""" return item.start_at def item_updateddate(self, item: DropCampaign) -> datetime.datetime: """Returns the campaign's last update time.""" return item.updated_at def item_categories(self, item: DropCampaign) -> tuple[str, ...]: """Returns the associated game's name as a category.""" if item.game: return ( "twitch", item.game.get_game_name, ) return () def item_guid(self, item: DropCampaign) -> str: """Return a unique identifier for each campaign.""" return item.id def item_author_name(self, item: DropCampaign) -> str: """Return the author name for the campaign, typically the game name.""" if item.game and item.game.display_name: return item.game.display_name return "Twitch" def item_enclosure_url(self, item: DropCampaign) -> str: """Returns the URL of the campaign image for enclosure.""" return item.image_url def item_enclosure_length(self, item: DropCampaign) -> int: # noqa: ARG002 """Returns the length of the enclosure. Currently not tracked, so return 0.""" return 0 def item_enclosure_mime_type(self, item: DropCampaign) -> str: # noqa: ARG002 """Returns the MIME type of the enclosure.""" return "image/jpeg"