Remove debug JSON from templates and views
This commit is contained in:
parent
d05996fd3b
commit
92ca0404a6
13 changed files with 4 additions and 329 deletions
|
|
@ -7,13 +7,11 @@
|
||||||
<h1>{{ badge_sets.count }} Twitch Chat Badges</h1>
|
<h1>{{ badge_sets.count }} Twitch Chat Badges</h1>
|
||||||
{% if badge_sets %}
|
{% if badge_sets %}
|
||||||
{% for data in badge_data %}
|
{% for data in badge_data %}
|
||||||
<!-- {{ data.set.set_id }} - {{ data.badges|length }} version{% if data.badges|length > 1 %}s{% endif %} -->
|
|
||||||
<h2>
|
<h2>
|
||||||
<a href="{% url 'twitch:badge_set_detail' set_id=data.set.set_id %}">{{ data.set.set_id }}</a>
|
<a href="{% url 'twitch:badge_set_detail' set_id=data.set.set_id %}">{{ data.set.set_id }}</a>
|
||||||
</h2>
|
</h2>
|
||||||
<table>
|
<table>
|
||||||
{% for badge in data.badges %}
|
{% for badge in data.badges %}
|
||||||
<!-- {{ badge.title }} {% if badge.description != badge.title %}- {{ badge.description }}{% else %}{% endif %} -->
|
|
||||||
<tr>
|
<tr>
|
||||||
<td style="width: 40px;">
|
<td style="width: 40px;">
|
||||||
<a href="{% url 'twitch:badge_set_detail' set_id=data.set.set_id %}">
|
<a href="{% url 'twitch:badge_set_detail' set_id=data.set.set_id %}">
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for badge in badges %}
|
{% for badge in badges %}
|
||||||
<!-- {{ badge.title }} {% if badge.description != badge.title %}- {{ badge.description }}{% else %}{% endif %} -->
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<code>{{ badge.badge_id }}</code>
|
<code>{{ badge.badge_id }}</code>
|
||||||
|
|
@ -48,5 +47,4 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>No badges found in this set.</p>
|
<p>No badges found in this set.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ set_data|safe }}
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,6 @@
|
||||||
<table style="border-collapse: collapse; width: 100%;">
|
<table style="border-collapse: collapse; width: 100%;">
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for drop in drops %}
|
{% for drop in drops %}
|
||||||
<!-- {{ drop.drop.name }} - {{ drop.drop.benefits.all|join:", " }} -->
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
{% for benefit in drop.drop.benefits.all %}
|
{% for benefit in drop.drop.benefits.all %}
|
||||||
|
|
@ -177,7 +176,6 @@
|
||||||
<h5>Allowed Channels</h5>
|
<h5>Allowed Channels</h5>
|
||||||
<div>
|
<div>
|
||||||
{% for channel in allowed_channels %}
|
{% for channel in allowed_channels %}
|
||||||
<!-- {{ channel.display_name }} https://www.twitch.tv/{{ channel.display_name }} -->
|
|
||||||
<a href="{% url 'twitch:channel_detail' channel.twitch_id %}">{{ channel.display_name }}</a>
|
<a href="{% url 'twitch:channel_detail' channel.twitch_id %}">{{ channel.display_name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -189,6 +187,4 @@
|
||||||
Go to a participating live channel
|
Go to a participating live channel
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<!-- Campaign JSON -->
|
|
||||||
{{ campaign_data|safe }}
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load image_tags %}
|
{% load image_tags %}
|
||||||
{% load image_tags %}
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
Drop Campaigns
|
Drop Campaigns
|
||||||
{% endblock title %}
|
{% endblock title %}
|
||||||
|
|
@ -47,7 +46,6 @@
|
||||||
<select name="game">
|
<select name="game">
|
||||||
<option value="">All Games</option>
|
<option value="">All Games</option>
|
||||||
{% for game in games %}
|
{% for game in games %}
|
||||||
<!-- Game option with Twitch ID {{ game.twitch_id }} and display name "{{ game.display_name }}" -->
|
|
||||||
<option value="{{ game.twitch_id }}"
|
<option value="{{ game.twitch_id }}"
|
||||||
{% if selected_game == game.twitch_id %}selected{% endif %}>
|
{% if selected_game == game.twitch_id %}selected{% endif %}>
|
||||||
{{ game.display_name|default:game.name|default:game.slug|default:game.twitch_id }}
|
{{ game.display_name|default:game.name|default:game.slug|default:game.twitch_id }}
|
||||||
|
|
@ -58,7 +56,6 @@
|
||||||
<select id="status" name="status">
|
<select id="status" name="status">
|
||||||
<option value="">All Statuses</option>
|
<option value="">All Statuses</option>
|
||||||
{% for status in status_options %}
|
{% for status in status_options %}
|
||||||
<!-- Status option "{{ status }}" -->
|
|
||||||
<option value="{{ status }}"
|
<option value="{{ status }}"
|
||||||
{% if selected_status == status %}selected{% endif %}>{{ status|title }}</option>
|
{% if selected_status == status %}selected{% endif %}>{{ status|title }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
@ -71,7 +68,6 @@
|
||||||
{% if campaigns %}
|
{% if campaigns %}
|
||||||
{% regroup campaigns by game as campaigns_by_game %}
|
{% regroup campaigns by game as campaigns_by_game %}
|
||||||
{% for game_group in campaigns_by_game %}
|
{% for game_group in campaigns_by_game %}
|
||||||
<!-- Game group for game "{{ game_group.grouper.display_name }}" with {{ game_group.list|length }} campaigns -->
|
|
||||||
<section>
|
<section>
|
||||||
<div style="display: flex; gap: 1rem;">
|
<div style="display: flex; gap: 1rem;">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -108,9 +104,6 @@
|
||||||
<div style="overflow-x: auto;">
|
<div style="overflow-x: auto;">
|
||||||
<div style="display: flex; gap: 1rem; min-width: max-content;">
|
<div style="display: flex; gap: 1rem; min-width: max-content;">
|
||||||
{% for campaign in game_group.list %}
|
{% for campaign in game_group.list %}
|
||||||
<!-- Campaign "{{ campaign.clean_name }}" with Twitch ID {{ campaign.twitch_id }} -->
|
|
||||||
<!-- https://ttvdrops.lovinator.space{% url 'twitch:campaign_detail' campaign.twitch_id %} -->
|
|
||||||
<!-- https://ttvdrops.lovinator.space{{ campaign.image_best_url }} -->
|
|
||||||
<article style="display: flex;
|
<article style="display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
@ -165,7 +158,6 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<!-- Pagination -->
|
<!-- Pagination -->
|
||||||
{% if is_paginated %}
|
{% if is_paginated %}
|
||||||
<!-- {{ page_obj.paginator.count }} total campaigns, showing {{ page_obj.start_index }} to {{ page_obj.end_index }} on page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }} -->
|
|
||||||
<nav style="text-align: center;">
|
<nav style="text-align: center;">
|
||||||
<div>
|
<div>
|
||||||
{% if page_obj.has_previous %}
|
{% if page_obj.has_previous %}
|
||||||
|
|
|
||||||
|
|
@ -33,17 +33,13 @@
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for campaign in active_campaigns %}
|
{% for campaign in active_campaigns %}
|
||||||
<!-- Campaign {{ campaign.name }} ({{ campaign.twitch_id }}) -->
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url 'twitch:campaign_detail' campaign.twitch_id %}">{{ campaign.clean_name }}</a>
|
<a href="{% url 'twitch:campaign_detail' campaign.twitch_id %}">{{ campaign.clean_name }}</a>
|
||||||
{% if campaign.time_based_drops.all %}
|
{% if campaign.time_based_drops.all %}
|
||||||
<!-- If the campaign has time-based drops, show the benefits in a nested div -->
|
<!-- If the campaign has time-based drops, show the benefits in a nested div -->
|
||||||
<div>
|
<div>
|
||||||
<!-- swag swag swag {{campaign.sorted_benefits}} -->
|
|
||||||
{% for benefit in campaign.sorted_benefits %}
|
{% for benefit in campaign.sorted_benefits %}
|
||||||
<!-- Benefit {{ benefit.name }} ({{ benefit.twitch_id }}) -->
|
|
||||||
<!-- {{ benefit.image_best_url }} -->
|
|
||||||
<span title="{{ benefit.name }}">
|
<span title="{{ benefit.name }}">
|
||||||
{% if benefit.image_best_url or benefit.image_asset_url %}
|
{% if benefit.image_best_url or benefit.image_asset_url %}
|
||||||
<!-- Show the benefit image if available -->
|
<!-- Show the benefit image if available -->
|
||||||
|
|
@ -85,7 +81,6 @@
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for campaign in upcoming_campaigns %}
|
{% for campaign in upcoming_campaigns %}
|
||||||
<!-- Campaign {{ campaign.name }} ({{ campaign.twitch_id }}) -->
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url 'twitch:campaign_detail' campaign.twitch_id %}">{{ campaign.clean_name }}</a>
|
<a href="{% url 'twitch:campaign_detail' campaign.twitch_id %}">{{ campaign.clean_name }}</a>
|
||||||
|
|
@ -93,7 +88,6 @@
|
||||||
<!-- If the campaign has time-based drops, show the benefits in a nested div -->
|
<!-- If the campaign has time-based drops, show the benefits in a nested div -->
|
||||||
<div>
|
<div>
|
||||||
{% for benefit in campaign.sorted_benefits %}
|
{% for benefit in campaign.sorted_benefits %}
|
||||||
<!-- Benefit {{ benefit.name }} ({{ benefit.twitch_id }}) -->
|
|
||||||
<span title="{{ benefit.name }}">
|
<span title="{{ benefit.name }}">
|
||||||
{% if benefit.image_best_url or benefit.image_asset_url %}
|
{% if benefit.image_best_url or benefit.image_asset_url %}
|
||||||
<!-- Show the benefit image if available -->
|
<!-- Show the benefit image if available -->
|
||||||
|
|
@ -135,7 +129,6 @@
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for campaign in expired_campaigns %}
|
{% for campaign in expired_campaigns %}
|
||||||
<!-- Campaign {{ campaign.name }} ({{ campaign.twitch_id }}) -->
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url 'twitch:campaign_detail' campaign.twitch_id %}">{{ campaign.clean_name }}</a>
|
<a href="{% url 'twitch:campaign_detail' campaign.twitch_id %}">{{ campaign.clean_name }}</a>
|
||||||
|
|
@ -143,7 +136,6 @@
|
||||||
<!-- If the campaign has time-based drops, show the benefits in a nested div -->
|
<!-- If the campaign has time-based drops, show the benefits in a nested div -->
|
||||||
<div>
|
<div>
|
||||||
{% for benefit in campaign.sorted_benefits %}
|
{% for benefit in campaign.sorted_benefits %}
|
||||||
<!-- Benefit {{ benefit.name }} ({{ benefit.twitch_id }}) -->
|
|
||||||
<span title="{{ benefit.name }}">
|
<span title="{{ benefit.name }}">
|
||||||
{% if benefit.image_best_url or benefit.image_asset_url %}
|
{% if benefit.image_best_url or benefit.image_asset_url %}
|
||||||
<img src="{{ benefit.image_best_url|default:benefit.image_asset_url }}"
|
<img src="{{ benefit.image_best_url|default:benefit.image_asset_url }}"
|
||||||
|
|
@ -181,5 +173,4 @@
|
||||||
{% if not active_campaigns and not upcoming_campaigns and not expired_campaigns %}
|
{% if not active_campaigns and not upcoming_campaigns and not expired_campaigns %}
|
||||||
<p>No campaigns found for this channel.</p>
|
<p>No campaigns found for this channel.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ channel_data|safe }}
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,6 @@
|
||||||
<div style="flex: 1; overflow-x: auto;">
|
<div style="flex: 1; overflow-x: auto;">
|
||||||
<div style="display: flex; gap: 1rem; min-width: max-content;">
|
<div style="display: flex; gap: 1rem; min-width: max-content;">
|
||||||
{% for campaign_data in game_data.campaigns %}
|
{% for campaign_data in game_data.campaigns %}
|
||||||
<!-- {{ campaign_data.campaign.name }} -->
|
|
||||||
<article style="display: flex;
|
<article style="display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -106,7 +105,6 @@
|
||||||
{% if campaign_data.campaign.allow_is_enabled %}
|
{% if campaign_data.campaign.allow_is_enabled %}
|
||||||
{% if campaign_data.allowed_channels %}
|
{% if campaign_data.allowed_channels %}
|
||||||
{% for channel in campaign_data.allowed_channels|slice:":5" %}
|
{% for channel in campaign_data.allowed_channels|slice:":5" %}
|
||||||
<!-- {{ channel.name }} -->
|
|
||||||
<li style="margin-bottom: 0.1rem;">
|
<li style="margin-bottom: 0.1rem;">
|
||||||
<a href="https://twitch.tv/{{ channel.name }}"
|
<a href="https://twitch.tv/{{ channel.name }}"
|
||||||
rel="nofollow ugc"
|
rel="nofollow ugc"
|
||||||
|
|
@ -132,14 +130,12 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if campaign_data.allowed_channels|length > 5 %}
|
{% if campaign_data.allowed_channels|length > 5 %}
|
||||||
<!-- {{ campaign_data.allowed_channels|length }} allowed channels -->
|
|
||||||
<li style="margin-bottom: 0.1rem; color: #666; font-style: italic;">
|
<li style="margin-bottom: 0.1rem; color: #666; font-style: italic;">
|
||||||
... and {{ campaign_data.allowed_channels|length|add:"-5" }} more
|
... and {{ campaign_data.allowed_channels|length|add:"-5" }} more
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if campaign_data.campaign.game.twitch_directory_url %}
|
{% if campaign_data.campaign.game.twitch_directory_url %}
|
||||||
<!--{{ campaign_data.campaign.game.display_name }} Twitch directory URL: {{ campaign_data.campaign.game.twitch_directory_url }} -->
|
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ campaign_data.campaign.game.twitch_directory_url }}"
|
<a href="{{ campaign_data.campaign.game.twitch_directory_url }}"
|
||||||
rel="nofollow ugc"
|
rel="nofollow ugc"
|
||||||
|
|
@ -148,7 +144,6 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<!-- {{ campaign_data.campaign.game.display_name }} Twitch directory URL not available -->
|
|
||||||
<li>Failed to get Twitch directory URL :(</li>
|
<li>Failed to get Twitch directory URL :(</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,6 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Emotes</h1>
|
<h1>Emotes</h1>
|
||||||
{% for emote in emotes %}
|
{% for emote in emotes %}
|
||||||
<!-- Emote from campaign {{ emote.campaign.name }} -->
|
|
||||||
<!-- https://ttvdrops.lovinator.space{{ emote.image_url }} -->
|
|
||||||
<a href="{% url 'twitch:campaign_detail' emote.campaign.twitch_id %}"
|
<a href="{% url 'twitch:campaign_detail' emote.campaign.twitch_id %}"
|
||||||
title="{{ emote.campaign.name }}"
|
title="{{ emote.campaign.name }}"
|
||||||
style="display: inline-block">
|
style="display: inline-block">
|
||||||
|
|
|
||||||
|
|
@ -158,5 +158,4 @@
|
||||||
{% if not active_campaigns and not upcoming_campaigns and not expired_campaigns %}
|
{% if not active_campaigns and not upcoming_campaigns and not expired_campaigns %}
|
||||||
<p id="no-campaigns-message">No campaigns found for this game.</p>
|
<p id="no-campaigns-message">No campaigns found for this game.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ game_data|safe }}
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
|
||||||
|
|
@ -27,5 +27,4 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>No organizations found.</p>
|
<p>No organizations found.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ orgs_data|safe }}
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,4 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<hr />
|
|
||||||
{{ org_data|safe }}
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,4 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<hr />
|
|
||||||
{{ campaign_data|safe }}
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
|
||||||
|
|
@ -958,7 +958,7 @@ class TestChannelListView:
|
||||||
client: Client,
|
client: Client,
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Game detail JSON payload should use `owners` (M2M), not stale `owner`."""
|
"""Game detail view should no longer expose debug JSON payload in context."""
|
||||||
org: Organization = Organization.objects.create(
|
org: Organization = Organization.objects.create(
|
||||||
twitch_id="org-game-detail",
|
twitch_id="org-game-detail",
|
||||||
name="Org Game Detail",
|
name="Org Game Detail",
|
||||||
|
|
@ -970,17 +970,10 @@ class TestChannelListView:
|
||||||
)
|
)
|
||||||
game.owners.add(org)
|
game.owners.add(org)
|
||||||
|
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
|
|
||||||
url: str = reverse("twitch:game_detail", args=[game.twitch_id])
|
url: str = reverse("twitch:game_detail", args=[game.twitch_id])
|
||||||
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
assert "game_data" not in response.context
|
||||||
game_data: dict[str, Any] = response.context["game_data"]
|
|
||||||
fields: dict[str, Any] = game_data["fields"]
|
|
||||||
assert "owners" in fields
|
|
||||||
assert fields["owners"] == [org.pk]
|
|
||||||
assert "owner" not in fields
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_org_list_view(self, client: Client) -> None:
|
def test_org_list_view(self, client: Client) -> None:
|
||||||
|
|
@ -1703,7 +1696,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""VideoGame schema image should be an ImageObject, not a plain URL."""
|
"""VideoGame schema image should be an ImageObject, not a plain URL."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
url: str = reverse("twitch:game_detail", args=[game.twitch_id])
|
url: str = reverse("twitch:game_detail", args=[game.twitch_id])
|
||||||
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
@ -1724,7 +1716,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""VideoGame ImageObject should carry creditText and copyrightNotice."""
|
"""VideoGame ImageObject should carry creditText and copyrightNotice."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
url: str = reverse("twitch:game_detail", args=[game.twitch_id])
|
url: str = reverse("twitch:game_detail", args=[game.twitch_id])
|
||||||
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
||||||
|
|
||||||
|
|
@ -1739,7 +1730,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""VideoGame schema should omit image key when box_art is empty."""
|
"""VideoGame schema should omit image key when box_art is empty."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
game_no_art: Game = Game.objects.create(
|
game_no_art: Game = Game.objects.create(
|
||||||
twitch_id="game-no-art",
|
twitch_id="game-no-art",
|
||||||
name="no_art_game",
|
name="no_art_game",
|
||||||
|
|
@ -1760,7 +1750,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""VideoGame schema publisher name should match the owning organization."""
|
"""VideoGame schema publisher name should match the owning organization."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
url: str = reverse("twitch:game_detail", args=[game.twitch_id])
|
url: str = reverse("twitch:game_detail", args=[game.twitch_id])
|
||||||
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
||||||
|
|
||||||
|
|
@ -1775,7 +1764,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""publisher.name and image.creditText should be the same value."""
|
"""publisher.name and image.creditText should be the same value."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
url: str = reverse("twitch:game_detail", args=[game.twitch_id])
|
url: str = reverse("twitch:game_detail", args=[game.twitch_id])
|
||||||
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
||||||
|
|
||||||
|
|
@ -1788,7 +1776,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""When owner.name is empty, twitch_id is used as credit fallback."""
|
"""When owner.name is empty, twitch_id is used as credit fallback."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
nameless_org: Organization = Organization.objects.create(
|
nameless_org: Organization = Organization.objects.create(
|
||||||
twitch_id="org-nameless",
|
twitch_id="org-nameless",
|
||||||
name="",
|
name="",
|
||||||
|
|
@ -1816,7 +1803,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Event schema image should be an ImageObject, not a plain URL string."""
|
"""Event schema image should be an ImageObject, not a plain URL string."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
url: str = reverse("twitch:campaign_detail", args=[campaign.twitch_id])
|
url: str = reverse("twitch:campaign_detail", args=[campaign.twitch_id])
|
||||||
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
@ -1837,7 +1823,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Event ImageObject should carry creditText and copyrightNotice."""
|
"""Event ImageObject should carry creditText and copyrightNotice."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
url: str = reverse("twitch:campaign_detail", args=[campaign.twitch_id])
|
url: str = reverse("twitch:campaign_detail", args=[campaign.twitch_id])
|
||||||
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
||||||
|
|
||||||
|
|
@ -1853,7 +1838,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Event schema should omit image key when campaign has no image."""
|
"""Event schema should omit image key when campaign has no image."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
campaign_no_img: DropCampaign = DropCampaign.objects.create(
|
campaign_no_img: DropCampaign = DropCampaign.objects.create(
|
||||||
twitch_id="camp-no-img",
|
twitch_id="camp-no-img",
|
||||||
name="No Image Campaign",
|
name="No Image Campaign",
|
||||||
|
|
@ -1875,7 +1859,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Event schema organizer name should match the owning organization."""
|
"""Event schema organizer name should match the owning organization."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
url: str = reverse("twitch:campaign_detail", args=[campaign.twitch_id])
|
url: str = reverse("twitch:campaign_detail", args=[campaign.twitch_id])
|
||||||
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
||||||
|
|
||||||
|
|
@ -1889,7 +1872,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""organizer.name and image.creditText should be the same value."""
|
"""organizer.name and image.creditText should be the same value."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
url: str = reverse("twitch:campaign_detail", args=[campaign.twitch_id])
|
url: str = reverse("twitch:campaign_detail", args=[campaign.twitch_id])
|
||||||
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
response: _MonkeyPatchedWSGIResponse = client.get(url)
|
||||||
|
|
||||||
|
|
@ -1902,7 +1884,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""When campaign has no owning org, creditText falls back to 'Twitch'."""
|
"""When campaign has no owning org, creditText falls back to 'Twitch'."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
game_no_owner: Game = Game.objects.create(
|
game_no_owner: Game = Game.objects.create(
|
||||||
twitch_id="game-no-owner",
|
twitch_id="game-no-owner",
|
||||||
name="no_owner_game",
|
name="no_owner_game",
|
||||||
|
|
@ -1930,7 +1911,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""When one owner is 'Twitch Gaming' and another is not, the non-generic one is used."""
|
"""When one owner is 'Twitch Gaming' and another is not, the non-generic one is used."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
twitch_gaming: Organization = Organization.objects.create(
|
twitch_gaming: Organization = Organization.objects.create(
|
||||||
twitch_id="twitch-gaming",
|
twitch_id="twitch-gaming",
|
||||||
name="Twitch Gaming",
|
name="Twitch Gaming",
|
||||||
|
|
@ -1960,7 +1940,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""When the only owner is 'Twitch Gaming', it is still used (no other choice)."""
|
"""When the only owner is 'Twitch Gaming', it is still used (no other choice)."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
twitch_gaming: Organization = Organization.objects.create(
|
twitch_gaming: Organization = Organization.objects.create(
|
||||||
twitch_id="twitch-gaming-solo",
|
twitch_id="twitch-gaming-solo",
|
||||||
name="Twitch Gaming",
|
name="Twitch Gaming",
|
||||||
|
|
@ -1985,7 +1964,6 @@ class TestImageObjectStructuredData:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Campaign schema prefers a non-generic publisher over 'Twitch Gaming'."""
|
"""Campaign schema prefers a non-generic publisher over 'Twitch Gaming'."""
|
||||||
monkeypatch.setattr("twitch.views.format_and_color_json", lambda data: data)
|
|
||||||
twitch_gaming: Organization = Organization.objects.create(
|
twitch_gaming: Organization = Organization.objects.create(
|
||||||
twitch_id="twitch-gaming-camp",
|
twitch_id="twitch-gaming-camp",
|
||||||
name="Twitch Gaming",
|
name="Twitch Gaming",
|
||||||
|
|
|
||||||
269
twitch/views.py
269
twitch/views.py
|
|
@ -14,7 +14,6 @@ from django.core.paginator import EmptyPage
|
||||||
from django.core.paginator import Page
|
from django.core.paginator import Page
|
||||||
from django.core.paginator import PageNotAnInteger
|
from django.core.paginator import PageNotAnInteger
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
from django.core.serializers import serialize
|
|
||||||
from django.db.models import Case
|
from django.db.models import Case
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from django.db.models import Prefetch
|
from django.db.models import Prefetch
|
||||||
|
|
@ -28,9 +27,6 @@ from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.views.generic import DetailView
|
from django.views.generic import DetailView
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
from pygments import highlight
|
|
||||||
from pygments.formatters import HtmlFormatter
|
|
||||||
from pygments.lexers.data import JsonLexer
|
|
||||||
|
|
||||||
from twitch.models import Channel
|
from twitch.models import Channel
|
||||||
from twitch.models import ChatBadge
|
from twitch.models import ChatBadge
|
||||||
|
|
@ -264,14 +260,6 @@ def org_list_view(request: HttpRequest) -> HttpResponse:
|
||||||
"""
|
"""
|
||||||
orgs: QuerySet[Organization] = Organization.objects.all().order_by("name")
|
orgs: QuerySet[Organization] = Organization.objects.all().order_by("name")
|
||||||
|
|
||||||
# Serialize all organizations
|
|
||||||
serialized_orgs: str = serialize(
|
|
||||||
"json",
|
|
||||||
orgs,
|
|
||||||
fields=("twitch_id", "name", "added_at", "updated_at"),
|
|
||||||
)
|
|
||||||
orgs_data: list[dict] = json.loads(serialized_orgs)
|
|
||||||
|
|
||||||
# CollectionPage schema for organizations list
|
# CollectionPage schema for organizations list
|
||||||
collection_schema: dict[str, str] = {
|
collection_schema: dict[str, str] = {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
|
|
@ -288,7 +276,6 @@ def org_list_view(request: HttpRequest) -> HttpResponse:
|
||||||
)
|
)
|
||||||
context: dict[str, Any] = {
|
context: dict[str, Any] = {
|
||||||
"orgs": orgs,
|
"orgs": orgs,
|
||||||
"orgs_data": format_and_color_json(orgs_data),
|
|
||||||
**seo_context,
|
**seo_context,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -296,7 +283,7 @@ def org_list_view(request: HttpRequest) -> HttpResponse:
|
||||||
|
|
||||||
|
|
||||||
# MARK: /organizations/<twitch_id>/
|
# MARK: /organizations/<twitch_id>/
|
||||||
def organization_detail_view(request: HttpRequest, twitch_id: str) -> HttpResponse: # noqa: PLR0914
|
def organization_detail_view(request: HttpRequest, twitch_id: str) -> HttpResponse:
|
||||||
"""Function-based view for organization detail.
|
"""Function-based view for organization detail.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
@ -317,30 +304,6 @@ def organization_detail_view(request: HttpRequest, twitch_id: str) -> HttpRespon
|
||||||
|
|
||||||
games: QuerySet[Game] = organization.games.all() # pyright: ignore[reportAttributeAccessIssue]
|
games: QuerySet[Game] = organization.games.all() # pyright: ignore[reportAttributeAccessIssue]
|
||||||
|
|
||||||
serialized_org: str = serialize(
|
|
||||||
"json",
|
|
||||||
[organization],
|
|
||||||
fields=("twitch_id", "name", "added_at", "updated_at"),
|
|
||||||
)
|
|
||||||
org_data: list[dict] = json.loads(serialized_org)
|
|
||||||
|
|
||||||
if games.exists():
|
|
||||||
serialized_games: str = serialize(
|
|
||||||
"json",
|
|
||||||
games,
|
|
||||||
fields=(
|
|
||||||
"twitch_id",
|
|
||||||
"slug",
|
|
||||||
"name",
|
|
||||||
"display_name",
|
|
||||||
"box_art",
|
|
||||||
"added_at",
|
|
||||||
"updated_at",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
games_data: list[dict] = json.loads(serialized_games)
|
|
||||||
org_data[0]["fields"]["games"] = games_data
|
|
||||||
|
|
||||||
org_name: str = organization.name or organization.twitch_id
|
org_name: str = organization.name or organization.twitch_id
|
||||||
games_count: int = games.count()
|
games_count: int = games.count()
|
||||||
s: Literal["", "s"] = "" if games_count == 1 else "s"
|
s: Literal["", "s"] = "" if games_count == 1 else "s"
|
||||||
|
|
@ -394,7 +357,6 @@ def organization_detail_view(request: HttpRequest, twitch_id: str) -> HttpRespon
|
||||||
context: dict[str, Any] = {
|
context: dict[str, Any] = {
|
||||||
"organization": organization,
|
"organization": organization,
|
||||||
"games": games,
|
"games": games,
|
||||||
"org_data": format_and_color_json(org_data[0]),
|
|
||||||
**seo_context,
|
**seo_context,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -505,22 +467,6 @@ def drop_campaign_list_view(request: HttpRequest) -> HttpResponse: # noqa: PLR0
|
||||||
return render(request, "twitch/campaign_list.html", context)
|
return render(request, "twitch/campaign_list.html", context)
|
||||||
|
|
||||||
|
|
||||||
def format_and_color_json(data: dict[str, Any] | list[dict] | str) -> str:
|
|
||||||
"""Format and color a JSON string for HTML display.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
data: Either a dictionary, list of dictionaries, or a JSON string to format.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: The formatted code with HTML styles.
|
|
||||||
"""
|
|
||||||
if isinstance(data, (dict, list)):
|
|
||||||
formatted_code: str = json.dumps(data, indent=4)
|
|
||||||
else:
|
|
||||||
formatted_code = data
|
|
||||||
return highlight(formatted_code, JsonLexer(), HtmlFormatter())
|
|
||||||
|
|
||||||
|
|
||||||
def _enhance_drops_with_context(
|
def _enhance_drops_with_context(
|
||||||
drops: QuerySet[TimeBasedDrop],
|
drops: QuerySet[TimeBasedDrop],
|
||||||
now: datetime.datetime,
|
now: datetime.datetime,
|
||||||
|
|
@ -564,7 +510,7 @@ def _enhance_drops_with_context(
|
||||||
|
|
||||||
|
|
||||||
# MARK: /campaigns/<twitch_id>/
|
# MARK: /campaigns/<twitch_id>/
|
||||||
def drop_campaign_detail_view(request: HttpRequest, twitch_id: str) -> HttpResponse: # noqa: PLR0914, PLR0915
|
def drop_campaign_detail_view(request: HttpRequest, twitch_id: str) -> HttpResponse: # noqa: PLR0914
|
||||||
"""Function-based view for a drop campaign detail.
|
"""Function-based view for a drop campaign detail.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
@ -598,96 +544,6 @@ def drop_campaign_detail_view(request: HttpRequest, twitch_id: str) -> HttpRespo
|
||||||
.order_by("required_minutes_watched")
|
.order_by("required_minutes_watched")
|
||||||
)
|
)
|
||||||
|
|
||||||
serialized_campaign: str = serialize(
|
|
||||||
"json",
|
|
||||||
[campaign],
|
|
||||||
fields=(
|
|
||||||
"twitch_id",
|
|
||||||
"name",
|
|
||||||
"description",
|
|
||||||
"details_url",
|
|
||||||
"account_link_url",
|
|
||||||
"image_url",
|
|
||||||
"start_at",
|
|
||||||
"end_at",
|
|
||||||
"allow_is_enabled",
|
|
||||||
"operation_names",
|
|
||||||
"game",
|
|
||||||
"created_at",
|
|
||||||
"updated_at",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
campaign_data: list[dict[str, Any]] = json.loads(serialized_campaign)
|
|
||||||
|
|
||||||
if drops.exists():
|
|
||||||
badge_benefit_names: set[str] = {
|
|
||||||
benefit.name
|
|
||||||
for drop in drops
|
|
||||||
for benefit in drop.benefits.all()
|
|
||||||
if benefit.distribution_type == "BADGE" and benefit.name
|
|
||||||
}
|
|
||||||
badge_descriptions_by_title: dict[str, str] = dict(
|
|
||||||
ChatBadge.objects.filter(title__in=badge_benefit_names).values_list(
|
|
||||||
"title",
|
|
||||||
"description",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
serialized_drops = serialize(
|
|
||||||
"json",
|
|
||||||
drops,
|
|
||||||
fields=(
|
|
||||||
"twitch_id",
|
|
||||||
"name",
|
|
||||||
"required_minutes_watched",
|
|
||||||
"required_subs",
|
|
||||||
"start_at",
|
|
||||||
"end_at",
|
|
||||||
"added_at",
|
|
||||||
"updated_at",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
drops_data: list[dict[str, Any]] = json.loads(serialized_drops)
|
|
||||||
|
|
||||||
for i, drop in enumerate(drops):
|
|
||||||
drop_benefits: list[DropBenefit] = list(drop.benefits.all())
|
|
||||||
if drop_benefits:
|
|
||||||
serialized_benefits: str = serialize(
|
|
||||||
"json",
|
|
||||||
drop_benefits,
|
|
||||||
fields=(
|
|
||||||
"twitch_id",
|
|
||||||
"name",
|
|
||||||
"image_asset_url",
|
|
||||||
"added_at",
|
|
||||||
"updated_at",
|
|
||||||
"created_at",
|
|
||||||
"entitlement_limit",
|
|
||||||
"is_ios_available",
|
|
||||||
"distribution_type",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
benefits_data: list[dict[str, Any]] = json.loads(serialized_benefits)
|
|
||||||
|
|
||||||
for benefit_data in benefits_data:
|
|
||||||
fields: dict[str, Any] = benefit_data.get("fields", {})
|
|
||||||
if fields.get("distribution_type") != "BADGE":
|
|
||||||
continue
|
|
||||||
|
|
||||||
# DropBenefit doesn't have a description field; fetch it from ChatBadge when possible.
|
|
||||||
if fields.get("description"):
|
|
||||||
continue
|
|
||||||
|
|
||||||
badge_description: str | None = badge_descriptions_by_title.get(
|
|
||||||
fields.get("name", ""),
|
|
||||||
)
|
|
||||||
if badge_description:
|
|
||||||
fields["description"] = badge_description
|
|
||||||
|
|
||||||
drops_data[i]["fields"]["benefits"] = benefits_data
|
|
||||||
|
|
||||||
campaign_data[0]["fields"]["drops"] = drops_data
|
|
||||||
|
|
||||||
now: datetime.datetime = timezone.now()
|
now: datetime.datetime = timezone.now()
|
||||||
enhanced_drops: list[dict[str, Any]] = _enhance_drops_with_context(drops, now)
|
enhanced_drops: list[dict[str, Any]] = _enhance_drops_with_context(drops, now)
|
||||||
# Attach awarded_badge to each drop in enhanced_drops
|
# Attach awarded_badge to each drop in enhanced_drops
|
||||||
|
|
@ -706,7 +562,6 @@ def drop_campaign_detail_view(request: HttpRequest, twitch_id: str) -> HttpRespo
|
||||||
"campaign": campaign,
|
"campaign": campaign,
|
||||||
"now": now,
|
"now": now,
|
||||||
"drops": enhanced_drops,
|
"drops": enhanced_drops,
|
||||||
"campaign_data": format_and_color_json(campaign_data[0]),
|
|
||||||
"owners": list(campaign.game.owners.all()),
|
"owners": list(campaign.game.owners.all()),
|
||||||
"allowed_channels": getattr(campaign, "channels_ordered", []),
|
"allowed_channels": getattr(campaign, "channels_ordered", []),
|
||||||
}
|
}
|
||||||
|
|
@ -1043,45 +898,6 @@ class GameDetailView(DetailView):
|
||||||
if campaign.end_at is not None and campaign.end_at < now
|
if campaign.end_at is not None and campaign.end_at < now
|
||||||
]
|
]
|
||||||
|
|
||||||
serialized_game: str = serialize(
|
|
||||||
"json",
|
|
||||||
[game],
|
|
||||||
fields=(
|
|
||||||
"twitch_id",
|
|
||||||
"slug",
|
|
||||||
"name",
|
|
||||||
"display_name",
|
|
||||||
"box_art",
|
|
||||||
"owners",
|
|
||||||
"added_at",
|
|
||||||
"updated_at",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
game_data: list[dict[str, Any]] = json.loads(serialized_game)
|
|
||||||
|
|
||||||
if campaigns_list:
|
|
||||||
serialized_campaigns = serialize(
|
|
||||||
"json",
|
|
||||||
campaigns_list,
|
|
||||||
fields=(
|
|
||||||
"twitch_id",
|
|
||||||
"name",
|
|
||||||
"description",
|
|
||||||
"details_url",
|
|
||||||
"account_link_url",
|
|
||||||
"image_url",
|
|
||||||
"start_at",
|
|
||||||
"end_at",
|
|
||||||
"allow_is_enabled",
|
|
||||||
"game",
|
|
||||||
"operation_names",
|
|
||||||
"added_at",
|
|
||||||
"updated_at",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
campaigns_data: list[dict[str, Any]] = json.loads(serialized_campaigns)
|
|
||||||
game_data[0]["fields"]["campaigns"] = campaigns_data
|
|
||||||
|
|
||||||
owners: list[Organization] = list(game.owners.all())
|
owners: list[Organization] = list(game.owners.all())
|
||||||
|
|
||||||
game_name: str = game.display_name or game.name or game.twitch_id
|
game_name: str = game.display_name or game.name or game.twitch_id
|
||||||
|
|
@ -1159,7 +975,6 @@ class GameDetailView(DetailView):
|
||||||
"owners": owners,
|
"owners": owners,
|
||||||
"drop_awarded_badges": drop_awarded_badges,
|
"drop_awarded_badges": drop_awarded_badges,
|
||||||
"now": now,
|
"now": now,
|
||||||
"game_data": format_and_color_json(game_data[0]),
|
|
||||||
**seo_context,
|
**seo_context,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -1379,28 +1194,6 @@ def reward_campaign_detail_view(request: HttpRequest, twitch_id: str) -> HttpRes
|
||||||
msg = "No reward campaign found matching the query"
|
msg = "No reward campaign found matching the query"
|
||||||
raise Http404(msg) from exc
|
raise Http404(msg) from exc
|
||||||
|
|
||||||
serialized_campaign: str = serialize(
|
|
||||||
"json",
|
|
||||||
[reward_campaign],
|
|
||||||
fields=(
|
|
||||||
"twitch_id",
|
|
||||||
"name",
|
|
||||||
"brand",
|
|
||||||
"summary",
|
|
||||||
"instructions",
|
|
||||||
"external_url",
|
|
||||||
"about_url",
|
|
||||||
"reward_value_url_param",
|
|
||||||
"starts_at",
|
|
||||||
"ends_at",
|
|
||||||
"is_sitewide",
|
|
||||||
"game",
|
|
||||||
"added_at",
|
|
||||||
"updated_at",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
campaign_data: list[dict[str, Any]] = json.loads(serialized_campaign)
|
|
||||||
|
|
||||||
now: datetime.datetime = timezone.now()
|
now: datetime.datetime = timezone.now()
|
||||||
|
|
||||||
campaign_name: str = reward_campaign.name or reward_campaign.twitch_id
|
campaign_name: str = reward_campaign.name or reward_campaign.twitch_id
|
||||||
|
|
@ -1480,7 +1273,6 @@ def reward_campaign_detail_view(request: HttpRequest, twitch_id: str) -> HttpRes
|
||||||
context: dict[str, Any] = {
|
context: dict[str, Any] = {
|
||||||
"reward_campaign": reward_campaign,
|
"reward_campaign": reward_campaign,
|
||||||
"now": now,
|
"now": now,
|
||||||
"campaign_data": format_and_color_json(campaign_data[0]),
|
|
||||||
"is_active": reward_campaign.is_active,
|
"is_active": reward_campaign.is_active,
|
||||||
**seo_context,
|
**seo_context,
|
||||||
}
|
}
|
||||||
|
|
@ -1672,33 +1464,6 @@ class ChannelDetailView(DetailView):
|
||||||
if campaign.end_at is not None and campaign.end_at < now
|
if campaign.end_at is not None and campaign.end_at < now
|
||||||
]
|
]
|
||||||
|
|
||||||
serialized_channel: str = serialize(
|
|
||||||
"json",
|
|
||||||
[channel],
|
|
||||||
fields=("twitch_id", "name", "display_name", "added_at", "updated_at"),
|
|
||||||
)
|
|
||||||
channel_data: list[dict[str, Any]] = json.loads(serialized_channel)
|
|
||||||
|
|
||||||
if campaigns_list:
|
|
||||||
serialized_campaigns: str = serialize(
|
|
||||||
"json",
|
|
||||||
campaigns_list,
|
|
||||||
fields=(
|
|
||||||
"twitch_id",
|
|
||||||
"name",
|
|
||||||
"description",
|
|
||||||
"details_url",
|
|
||||||
"account_link_url",
|
|
||||||
"image_url",
|
|
||||||
"start_at",
|
|
||||||
"end_at",
|
|
||||||
"added_at",
|
|
||||||
"updated_at",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
campaigns_data: list[dict[str, Any]] = json.loads(serialized_campaigns)
|
|
||||||
channel_data[0]["fields"]["campaigns"] = campaigns_data
|
|
||||||
|
|
||||||
name: str = channel.display_name or channel.name or channel.twitch_id
|
name: str = channel.display_name or channel.name or channel.twitch_id
|
||||||
total_campaigns: int = len(campaigns_list)
|
total_campaigns: int = len(campaigns_list)
|
||||||
description: str = f"{name} participates in {total_campaigns} drop campaign"
|
description: str = f"{name} participates in {total_campaigns} drop campaign"
|
||||||
|
|
@ -1761,7 +1526,6 @@ class ChannelDetailView(DetailView):
|
||||||
"upcoming_campaigns": upcoming_campaigns,
|
"upcoming_campaigns": upcoming_campaigns,
|
||||||
"expired_campaigns": expired_campaigns,
|
"expired_campaigns": expired_campaigns,
|
||||||
"now": now,
|
"now": now,
|
||||||
"channel_data": format_and_color_json(channel_data[0]),
|
|
||||||
**seo_context,
|
**seo_context,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -1878,34 +1642,6 @@ def badge_set_detail_view(request: HttpRequest, set_id: str) -> HttpResponse:
|
||||||
).distinct()
|
).distinct()
|
||||||
badge.award_campaigns = list(campaigns) # pyright: ignore[reportAttributeAccessIssue]
|
badge.award_campaigns = list(campaigns) # pyright: ignore[reportAttributeAccessIssue]
|
||||||
|
|
||||||
# Serialize for JSON display
|
|
||||||
serialized_set: str = serialize(
|
|
||||||
"json",
|
|
||||||
[badge_set],
|
|
||||||
fields=("set_id", "added_at", "updated_at"),
|
|
||||||
)
|
|
||||||
set_data: list[dict[str, Any]] = json.loads(serialized_set)
|
|
||||||
|
|
||||||
if badges:
|
|
||||||
serialized_badges: str = serialize(
|
|
||||||
"json",
|
|
||||||
badges,
|
|
||||||
fields=(
|
|
||||||
"badge_id",
|
|
||||||
"image_url_1x",
|
|
||||||
"image_url_2x",
|
|
||||||
"image_url_4x",
|
|
||||||
"title",
|
|
||||||
"description",
|
|
||||||
"click_action",
|
|
||||||
"click_url",
|
|
||||||
"added_at",
|
|
||||||
"updated_at",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
badges_data: list[dict[str, Any]] = json.loads(serialized_badges)
|
|
||||||
set_data[0]["fields"]["badges"] = badges_data
|
|
||||||
|
|
||||||
badge_set_name: str = badge_set.set_id
|
badge_set_name: str = badge_set.set_id
|
||||||
badge_set_description: str = f"Twitch chat badge set {badge_set_name} with {len(badges)} badge{'s' if len(badges) != 1 else ''} awarded through drop campaigns."
|
badge_set_description: str = f"Twitch chat badge set {badge_set_name} with {len(badges)} badge{'s' if len(badges) != 1 else ''} awarded through drop campaigns."
|
||||||
|
|
||||||
|
|
@ -1927,7 +1663,6 @@ def badge_set_detail_view(request: HttpRequest, set_id: str) -> HttpResponse:
|
||||||
context: dict[str, Any] = {
|
context: dict[str, Any] = {
|
||||||
"badge_set": badge_set,
|
"badge_set": badge_set,
|
||||||
"badges": badges,
|
"badges": badges,
|
||||||
"set_data": format_and_color_json(set_data[0]),
|
|
||||||
**seo_context,
|
**seo_context,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue