diff --git a/project/thscoreboard/replays/urls/replay_urls.py b/project/thscoreboard/replays/urls/replay_urls.py index a3bd2e77..b44f0c9f 100644 --- a/project/thscoreboard/replays/urls/replay_urls.py +++ b/project/thscoreboard/replays/urls/replay_urls.py @@ -21,10 +21,21 @@ path("user/", user.user_page, name="user_page"), path("user//json", user.user_page_json), path("reanalyze_all", reanalyze_all_replays.reanalyze_all), - path("", replay_list.game_scoreboard), - path("/json", replay_list.game_scoreboard_json), - path("/d", replay_list.game_scoreboard), - path("/d/", replay_list.game_scoreboard), + path("", replay_list.game_scoreboard, name="Replays/GameScoreboard"), + path( + "/json", + replay_list.game_scoreboard_json, + ), + path( + "/d", + replay_list.game_scoreboard_old_url, + name="Replays/GameScoreboardOldRedirect", + ), + path( + "/d/", + replay_list.game_scoreboard_old_url, + name="Replays/GameScoreboardOldRedirect", + ), path( "/", view_replay.replay_details, diff --git a/project/thscoreboard/replays/views/replay_list.py b/project/thscoreboard/replays/views/replay_list.py index 0e3d23ce..7c68f2b1 100644 --- a/project/thscoreboard/replays/views/replay_list.py +++ b/project/thscoreboard/replays/views/replay_list.py @@ -1,7 +1,10 @@ """Contains views which list various replays.""" +from typing import Optional + +from django import urls from django.views.decorators import http as http_decorators -from django.shortcuts import get_object_or_404, render +from django.shortcuts import get_object_or_404, render, redirect from django.db.models import Manager from django.core.handlers.wsgi import WSGIRequest @@ -19,6 +22,26 @@ def game_scoreboard_json(request: WSGIRequest, game_id: str): return stream_json_bytes_to_http_reponse(replay_jsons) +def game_scoreboard_old_url( + request: WSGIRequest, game_id: str, difficulty: int, shot_id: Optional[str] = None +): + """Redirect requests going to the old filtered game scoreboard URLs. + + We still get occasional requests to these URLs. + + Note that the extra parameters are currently ignored. If we add query + strings or similar filter representations to the game scoreboard page, we + should update this function to use them. + + Args: + request: The request object. + game_id: The game ID the user is interested in viewing. + difficulty: An integer corresponding to the replay difficulty to display. + shot_id: The shot ID the user is interested in viewing. + """ + return redirect(urls.reverse("Replays/GameScoreboard", args=[game_id])) + + @http_decorators.require_safe def game_scoreboard( request: WSGIRequest, diff --git a/project/thscoreboard/replays/views/test_replay_list.py b/project/thscoreboard/replays/views/test_replay_list.py new file mode 100644 index 00000000..44de235c --- /dev/null +++ b/project/thscoreboard/replays/views/test_replay_list.py @@ -0,0 +1,37 @@ +from django import test as django_test +from django import urls + +from replays import game_ids +from replays.views import replay_list +from replays.testing import test_case + + +class GameScoreboardRedirectTestCase(test_case.ReplayTestCase): + def setUp(self): + super().setUp() + self.factory = django_test.RequestFactory() + + def _Get(self, game_id, difficulty, shot_id=None): + kwargs = {"game_id": game_id, "difficulty": difficulty} + if shot_id is not None: + kwargs["shot_id"] = shot_id + url = urls.reverse("Replays/GameScoreboardOldRedirect", kwargs=kwargs) + + request = self.factory.get(url) + return replay_list.game_scoreboard_old_url(request, **kwargs) + + def testRedirectsWithShot(self): + response = self._Get(game_ids.GameIDs.TH07, difficulty=1, shot_id="ReimuA") + self.assertEqual(response.status_code, 302) + self.assertEqual( + response.url, + urls.reverse("Replays/GameScoreboard", args=[game_ids.GameIDs.TH07]), + ) + + def testRedirectsWithoutShot(self): + response = self._Get(game_ids.GameIDs.TH07, difficulty=1) + self.assertEqual(response.status_code, 302) + self.assertEqual( + response.url, + urls.reverse("Replays/GameScoreboard", args=[game_ids.GameIDs.TH07]), + ) diff --git a/requirements-dev.txt b/requirements-dev.txt index b2d0994a..b0e227c7 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -3,4 +3,4 @@ django-rosetta==0.9.9 flake8==6.1.0 python-dotenv==1.0.0 -black==23.7.0 \ No newline at end of file +black==23.7.0