diff options
Diffstat (limited to '')
| -rw-r--r-- | pydis_site/apps/redirect/redirects.yaml | 2 | ||||
| -rw-r--r-- | pydis_site/apps/redirect/urls.py | 114 | ||||
| -rw-r--r-- | pydis_site/urls.py | 16 | 
3 files changed, 112 insertions, 20 deletions
| diff --git a/pydis_site/apps/redirect/redirects.yaml b/pydis_site/apps/redirect/redirects.yaml index def4154b..9bcf3afd 100644 --- a/pydis_site/apps/redirect/redirects.yaml +++ b/pydis_site/apps/redirect/redirects.yaml @@ -182,7 +182,7 @@ events_game_jams_twenty_twenty_rules_redirect:    redirect_arguments: ["game-jams/2020/rules"]  events_game_jams_twenty_twenty_technical_requirements_redirect: -  original_path: pages/events/game-jam-2020/technical-requirements +  original_path: pages/events/game-jam-2020/technical-requirements/    redirect_route: "events:page"    redirect_arguments: ["game-jams/2020/technical-requirements"] diff --git a/pydis_site/apps/redirect/urls.py b/pydis_site/apps/redirect/urls.py index 6187af17..f7ddf45b 100644 --- a/pydis_site/apps/redirect/urls.py +++ b/pydis_site/apps/redirect/urls.py @@ -1,19 +1,105 @@ +import dataclasses +import re +  import yaml -from django.conf import settings -from django.urls import path +from django import conf +from django.urls import URLPattern, path +from django_distill import distill_path +from pydis_site import settings +from pydis_site.apps.content import urls as pages_urls  from pydis_site.apps.redirect.views import CustomRedirectView +from pydis_site.apps.resources import urls as resources_urls  app_name = "redirect" -urlpatterns = [ -    path( -        data["original_path"], -        CustomRedirectView.as_view( -            pattern_name=data["redirect_route"], -            static_args=tuple(data.get("redirect_arguments", ())), -            prefix_redirect=data.get("prefix_redirect", False) -        ), -        name=name -    ) -    for name, data in yaml.safe_load(settings.REDIRECTIONS_PATH.read_text()).items() -] + + +__PARAMETER_REGEX = re.compile(r"<\w+:\w+>") +REDIRECT_TEMPLATE = "<meta http-equiv=\"refresh\" content=\"0; URL={url}\"/>" + + [email protected](frozen=True) +class Redirect: +    """Metadata about a redirect route.""" + +    original_path: str +    redirect_route: str +    redirect_arguments: tuple[str] = tuple() + +    prefix_redirect: bool = False + + +def map_redirect(name: str, data: Redirect) -> list[URLPattern]: +    """Return a pattern using the Redirects app, or a static HTML redirect for static builds.""" +    if not settings.env("STATIC_BUILD"): +        # Normal dynamic redirect +        return [path( +            data.original_path, +            CustomRedirectView.as_view( +                pattern_name=data.redirect_route, +                static_args=tuple(data.redirect_arguments), +                prefix_redirect=data.prefix_redirect +            ), +            name=name +        )] + +    # Create static HTML redirects for static builds +    new_app_name = data.redirect_route.split(":")[0] + +    if __PARAMETER_REGEX.search(data.original_path): +        # Redirects for paths which accept parameters +        # We generate an HTML redirect file for all possible entries +        paths = [] + +        class RedirectFunc: +            def __init__(self, new_url: str, _name: str): +                self.result = REDIRECT_TEMPLATE.format(url=new_url) +                self.__qualname__ = _name + +            def __call__(self, *args, **kwargs): +                return self.result + +        if new_app_name == resources_urls.app_name: +            items = resources_urls.get_all_resources() +        elif new_app_name == pages_urls.app_name: +            items = pages_urls.get_all_pages() +        else: +            raise ValueError(f"Unknown app in redirect: {new_app_name}") + +        for item in items: +            entry = list(item.values())[0] + +            # Replace dynamic redirect with concrete path +            concrete_path = __PARAMETER_REGEX.sub(entry, data.original_path) +            new_redirect = f"/{new_app_name}/{entry}" +            pattern_name = f"{name}_{entry}" + +            paths.append(distill_path( +                concrete_path, +                RedirectFunc(new_redirect, pattern_name), +                name=pattern_name +            )) + +        return paths + +    else: +        redirect_path_name = "pages" if new_app_name == "content" else new_app_name +        if len(data.redirect_arguments) > 0: +            redirect_arg = data.redirect_arguments[0] +        else: +            redirect_arg = "resources/" +        new_redirect = f"/{redirect_path_name}/{redirect_arg}" + +        if new_redirect == "/resources/resources/": +            new_redirect = "/resources/" + +        return [distill_path( +            data.original_path, +            lambda *args: REDIRECT_TEMPLATE.format(url=new_redirect), +            name=name, +        )] + + +urlpatterns = [] +for _name, _data in yaml.safe_load(conf.settings.REDIRECTIONS_PATH.read_text()).items(): +    urlpatterns.extend(map_redirect(_name, Redirect(**_data))) diff --git a/pydis_site/urls.py b/pydis_site/urls.py index 51ef4214..6cd31f26 100644 --- a/pydis_site/urls.py +++ b/pydis_site/urls.py @@ -11,19 +11,25 @@ NON_STATIC_PATTERNS = [      # Internal API ingress (cluster local)      path('pydis-api/', include('pydis_site.apps.api.urls', namespace='internal_api')), -    # This must be mounted before the `content` app to prevent Django -    # from wildcard matching all requests to `pages/...`. -    path('', include('pydis_site.apps.redirect.urls')),      path('', include('django_prometheus.urls')), - -    path('staff/', include('pydis_site.apps.staff.urls', namespace='staff')),  ] if not settings.env("STATIC_BUILD") else []  urlpatterns = (      *NON_STATIC_PATTERNS, + +    # This must be mounted before the `content` app to prevent Django +    # from wildcard matching all requests to `pages/...`. +    path('', include('pydis_site.apps.redirect.urls')), +      path('pages/', include('pydis_site.apps.content.urls', namespace='content')),      path('resources/', include('pydis_site.apps.resources.urls')),      path('events/', include('pydis_site.apps.events.urls', namespace='events')),      path('', include('pydis_site.apps.home.urls', namespace='home')),  ) + + +if not settings.env("STATIC_BUILD"): +    urlpatterns += ( +        path('staff/', include('pydis_site.apps.staff.urls', namespace='staff')), +    ) | 
