Add /emotes/

This commit is contained in:
Joakim Hellsén 2026-01-10 23:15:09 +01:00
commit b8df95e317
No known key found for this signature in database
4 changed files with 61 additions and 9 deletions

View file

@ -18,21 +18,22 @@ app_name = "twitch"
urlpatterns: list[URLPattern] = [
path("", views.dashboard, name="dashboard"),
path("search/", views.search_view, name="search"),
path("debug/", views.debug_view, name="debug"),
path("campaigns/", views.drop_campaign_list_view, name="campaign_list"),
path("campaigns/<str:twitch_id>/", views.drop_campaign_detail_view, name="campaign_detail"),
path("games/", views.GamesGridView.as_view(), name="game_list"),
path("games/list/", views.GamesListView.as_view(), name="game_list_simple"),
path("games/<str:twitch_id>/", views.GameDetailView.as_view(), name="game_detail"),
path("organizations/", views.org_list_view, name="org_list"),
path("organizations/<str:twitch_id>/", views.organization_detail_view, name="organization_detail"),
path("channels/", views.ChannelListView.as_view(), name="channel_list"),
path("channels/<str:twitch_id>/", views.ChannelDetailView.as_view(), name="channel_detail"),
path("rss/organizations/", OrganizationFeed(), name="organization_feed"),
path("rss/organizations/<str:twitch_id>/campaigns/", OrganizationCampaignFeed(), name="organization_campaign_feed"),
path("debug/", views.debug_view, name="debug"),
path("docs/rss/", views.docs_rss_view, name="docs_rss"),
path("emotes/", views.emote_gallery_view, name="emote_gallery"),
path("games/", views.GamesGridView.as_view(), name="game_list"),
path("games/<str:twitch_id>/", views.GameDetailView.as_view(), name="game_detail"),
path("games/list/", views.GamesListView.as_view(), name="game_list_simple"),
path("organizations/", views.org_list_view, name="org_list"),
path("organizations/<str:twitch_id>/", views.organization_detail_view, name="organization_detail"),
path("rss/campaigns/", DropCampaignFeed(), name="campaign_feed"),
path("rss/games/", GameFeed(), name="game_feed"),
path("rss/games/<str:twitch_id>/campaigns/", GameCampaignFeed(), name="game_campaign_feed"),
path("rss/campaigns/", DropCampaignFeed(), name="campaign_feed"),
path("docs/rss/", views.docs_rss_view, name="docs_rss"),
path("rss/organizations/", OrganizationFeed(), name="organization_feed"),
path("rss/organizations/<str:twitch_id>/campaigns/", OrganizationCampaignFeed(), name="organization_campaign_feed"),
path("search/", views.search_view, name="search"),
]

View file

@ -49,6 +49,42 @@ MIN_QUERY_LENGTH_FOR_FTS = 3
MIN_SEARCH_RANK = 0.05
def emote_gallery_view(request: HttpRequest) -> HttpResponse:
"""View to display all emote images (distribution_type='EMOTE'), clickable to their campaign.
Args:
request: The HTTP request.
Returns:
HttpResponse: The rendered emote gallery page.
"""
emote_benefits: QuerySet[DropBenefit, DropBenefit] = (
DropBenefit.objects
.filter(distribution_type="EMOTE")
.select_related()
.prefetch_related(
Prefetch(
"drops",
queryset=TimeBasedDrop.objects.select_related("campaign"),
to_attr="_emote_drops",
),
)
)
emotes: list[dict[str, str | DropCampaign]] = []
for benefit in emote_benefits:
# Find the first drop with a campaign for this benefit
drop: TimeBasedDrop | None = next((d for d in getattr(benefit, "_emote_drops", []) if d.campaign), None)
if drop and drop.campaign:
emotes.append({
"image_url": benefit.image_best_url,
"campaign": drop.campaign,
})
context: dict[str, list[dict[str, Any]]] = {"emotes": emotes}
return render(request, "twitch/emote_gallery.html", context)
# MARK: /search/
def search_view(request: HttpRequest) -> HttpResponse:
"""Search view for all models.