Add stylesheet to RSS/Atom feeds
All checks were successful
Deploy to Server / deploy (push) Successful in 10s
All checks were successful
Deploy to Server / deploy (push) Successful in 10s
This commit is contained in:
parent
f3bb95cc4f
commit
a73fdc4e66
4 changed files with 846 additions and 270 deletions
158
twitch/models.py
158
twitch/models.py
|
|
@ -2,13 +2,11 @@ import logging
|
|||
from typing import TYPE_CHECKING
|
||||
|
||||
import auto_prefetch
|
||||
from django.contrib.humanize.templatetags.humanize import naturaltime
|
||||
from django.contrib.postgres.indexes import GinIndex
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import SafeText
|
||||
|
||||
from twitch.utils import normalize_twitch_box_art_url
|
||||
|
||||
|
|
@ -209,6 +207,11 @@ class Game(auto_prefetch.Model):
|
|||
logger.debug("Failed to resolve Game.box_art_file url: %s", exc)
|
||||
return normalize_twitch_box_art_url(self.box_art or "")
|
||||
|
||||
@property
|
||||
def image_best_url(self) -> str:
|
||||
"""Alias for box_art_best_url to provide a common interface with benefits."""
|
||||
return self.box_art_best_url
|
||||
|
||||
|
||||
# MARK: TwitchGame
|
||||
class TwitchGameData(auto_prefetch.Model):
|
||||
|
|
@ -554,51 +557,6 @@ class DropCampaign(auto_prefetch.Model):
|
|||
"""Determine if the campaign is subscription only based on its benefits."""
|
||||
return any(drop.required_subs > 0 for drop in self.time_based_drops.all()) # pyright: ignore[reportAttributeAccessIssue]
|
||||
|
||||
def get_feed_title(self) -> str:
|
||||
"""Return the campaign title for RSS feeds."""
|
||||
game_name: str = self.game.display_name if self.game else ""
|
||||
return f"{game_name}: {self.clean_name}"
|
||||
|
||||
def get_feed_link(self) -> str:
|
||||
"""Return the link to the campaign detail."""
|
||||
return reverse("twitch:campaign_detail", args=[self.twitch_id])
|
||||
|
||||
def get_feed_pubdate(self) -> datetime.datetime:
|
||||
"""Return the publication date for the feed item."""
|
||||
if self.added_at:
|
||||
return self.added_at
|
||||
return timezone.now()
|
||||
|
||||
def get_feed_categories(self) -> tuple[str, ...]:
|
||||
"""Return category tags for the feed item."""
|
||||
categories: list[str] = ["twitch", "drops"]
|
||||
|
||||
game: Game | None = self.game
|
||||
if game:
|
||||
categories.append(game.get_game_name)
|
||||
# Add first owner if available
|
||||
first_owner: Organization | None = game.owners.first()
|
||||
if first_owner:
|
||||
categories.extend((str(first_owner.name), str(first_owner.twitch_id)))
|
||||
|
||||
return tuple(categories)
|
||||
|
||||
def get_feed_guid(self) -> str:
|
||||
"""Return a unique identifier for the feed item."""
|
||||
return f"{self.twitch_id}@ttvdrops.com"
|
||||
|
||||
def get_feed_author_name(self) -> str:
|
||||
"""Return the author name for the feed item."""
|
||||
game: Game | None = self.game
|
||||
if game and game.display_name:
|
||||
return game.display_name
|
||||
|
||||
return "Twitch"
|
||||
|
||||
def get_feed_enclosure_url(self) -> str:
|
||||
"""Return the campaign image URL for RSS enclosures."""
|
||||
return self.image_best_url
|
||||
|
||||
@property
|
||||
def sorted_benefits(self) -> list[DropBenefit]:
|
||||
"""Return a sorted list of benefits for the campaign."""
|
||||
|
|
@ -976,112 +934,6 @@ class RewardCampaign(auto_prefetch.Model):
|
|||
logger.debug("Failed to resolve RewardCampaign.image_file url: %s", exc)
|
||||
return self.image_url or ""
|
||||
|
||||
def get_feed_title(self) -> str:
|
||||
"""Return the reward campaign name as the feed item title."""
|
||||
if self.brand:
|
||||
return f"{self.brand}: {self.name}"
|
||||
return self.name
|
||||
|
||||
def get_feed_description(self) -> str:
|
||||
"""Return HTML description of the reward campaign for RSS feeds."""
|
||||
parts: list = []
|
||||
|
||||
if self.summary:
|
||||
parts.append(format_html("<p>{}</p>", self.summary))
|
||||
|
||||
if self.starts_at or self.ends_at:
|
||||
start_part = (
|
||||
format_html(
|
||||
"Starts: {} ({})",
|
||||
self.starts_at.strftime("%Y-%m-%d %H:%M %Z"),
|
||||
naturaltime(self.starts_at),
|
||||
)
|
||||
if self.starts_at
|
||||
else ""
|
||||
)
|
||||
end_part = (
|
||||
format_html(
|
||||
"Ends: {} ({})",
|
||||
self.ends_at.strftime("%Y-%m-%d %H:%M %Z"),
|
||||
naturaltime(self.ends_at),
|
||||
)
|
||||
if self.ends_at
|
||||
else ""
|
||||
)
|
||||
if start_part and end_part:
|
||||
parts.append(format_html("<p>{}<br />{}</p>", start_part, end_part))
|
||||
elif start_part:
|
||||
parts.append(format_html("<p>{}</p>", start_part))
|
||||
elif end_part:
|
||||
parts.append(format_html("<p>{}</p>", end_part))
|
||||
|
||||
if self.is_sitewide:
|
||||
parts.append(
|
||||
SafeText("<p><strong>This is a sitewide reward campaign</strong></p>"),
|
||||
)
|
||||
elif self.game:
|
||||
parts.append(
|
||||
format_html(
|
||||
"<p>Game: {}</p>",
|
||||
self.game.display_name or self.game.name,
|
||||
),
|
||||
)
|
||||
|
||||
if self.about_url:
|
||||
parts.append(
|
||||
format_html('<p><a href="{}">Learn more</a></p>', self.about_url),
|
||||
)
|
||||
|
||||
if self.external_url:
|
||||
parts.append(
|
||||
format_html('<p><a href="{}">Redeem reward</a></p>', self.external_url),
|
||||
)
|
||||
|
||||
return "".join(str(p) for p in parts)
|
||||
|
||||
def get_feed_link(self) -> str:
|
||||
"""Return the link to the reward campaign (external URL or dashboard)."""
|
||||
if self.external_url:
|
||||
return self.external_url
|
||||
return reverse("twitch:dashboard")
|
||||
|
||||
def get_feed_pubdate(self) -> datetime.datetime:
|
||||
"""Return the publication date for the feed item.
|
||||
|
||||
Uses starts_at (when the reward starts). Fallback to added_at or now if missing.
|
||||
"""
|
||||
if self.starts_at:
|
||||
return self.starts_at
|
||||
if self.added_at:
|
||||
return self.added_at
|
||||
return timezone.now()
|
||||
|
||||
def get_feed_categories(self) -> tuple[str, ...]:
|
||||
"""Return category tags for the feed item."""
|
||||
categories: list[str] = ["twitch", "rewards", "quests"]
|
||||
|
||||
if self.brand:
|
||||
categories.append(self.brand)
|
||||
|
||||
if self.game:
|
||||
categories.append(self.game.get_game_name)
|
||||
|
||||
return tuple(categories)
|
||||
|
||||
def get_feed_guid(self) -> str:
|
||||
"""Return a unique identifier for the feed item."""
|
||||
return f"{self.twitch_id}@ttvdrops.com"
|
||||
|
||||
def get_feed_author_name(self) -> str:
|
||||
"""Return the author name for the feed item."""
|
||||
if self.brand:
|
||||
return self.brand
|
||||
|
||||
if self.game and self.game.display_name:
|
||||
return self.game.display_name
|
||||
|
||||
return "Twitch"
|
||||
|
||||
|
||||
# MARK: ChatBadgeSet
|
||||
class ChatBadgeSet(auto_prefetch.Model):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue