aboutsummaryrefslogtreecommitdiffstats
path: root/pydis_site
diff options
context:
space:
mode:
Diffstat (limited to 'pydis_site')
-rw-r--r--pydis_site/apps/content/resources/privacy.md7
-rw-r--r--pydis_site/apps/home/urls.py1
-rw-r--r--pydis_site/apps/redirect/__init__.py0
-rw-r--r--pydis_site/apps/redirect/apps.py7
-rw-r--r--pydis_site/apps/redirect/migrations/__init__.py0
-rw-r--r--pydis_site/apps/redirect/redirects.yaml194
-rw-r--r--pydis_site/apps/redirect/tests.py58
-rw-r--r--pydis_site/apps/redirect/urls.py19
-rw-r--r--pydis_site/apps/redirect/views.py26
-rw-r--r--pydis_site/settings.py3
-rw-r--r--pydis_site/templates/base/navbar.html18
11 files changed, 324 insertions, 9 deletions
diff --git a/pydis_site/apps/content/resources/privacy.md b/pydis_site/apps/content/resources/privacy.md
new file mode 100644
index 00000000..88916b79
--- /dev/null
+++ b/pydis_site/apps/content/resources/privacy.md
@@ -0,0 +1,7 @@
+---
+title: Privacy Policy
+description: Our server's privacy policy.
+icon: fab fa-discord
+---
+
+You should be redirected. If you are not, [please click here](https://www.notion.so/pythondiscord/Python-Discord-Privacy-ee2581fea4854ddcb1ebc06c1dbb9fbd).
diff --git a/pydis_site/apps/home/urls.py b/pydis_site/apps/home/urls.py
index 3c716875..e475c491 100644
--- a/pydis_site/apps/home/urls.py
+++ b/pydis_site/apps/home/urls.py
@@ -6,6 +6,7 @@ from .views import HomeView
app_name = 'home'
urlpatterns = [
path('', HomeView.as_view(), name='home'),
+ path('', include('pydis_site.apps.redirect.urls')),
path('admin/', admin.site.urls),
path('resources/', include('pydis_site.apps.resources.urls')),
path('pages/', include('pydis_site.apps.content.urls')),
diff --git a/pydis_site/apps/redirect/__init__.py b/pydis_site/apps/redirect/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/pydis_site/apps/redirect/__init__.py
diff --git a/pydis_site/apps/redirect/apps.py b/pydis_site/apps/redirect/apps.py
new file mode 100644
index 00000000..9b70d169
--- /dev/null
+++ b/pydis_site/apps/redirect/apps.py
@@ -0,0 +1,7 @@
+from django.apps import AppConfig
+
+
+class RedirectConfig(AppConfig):
+ """AppConfig instance for Redirect app."""
+
+ name = 'redirect'
diff --git a/pydis_site/apps/redirect/migrations/__init__.py b/pydis_site/apps/redirect/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/pydis_site/apps/redirect/migrations/__init__.py
diff --git a/pydis_site/apps/redirect/redirects.yaml b/pydis_site/apps/redirect/redirects.yaml
new file mode 100644
index 00000000..ce789b61
--- /dev/null
+++ b/pydis_site/apps/redirect/redirects.yaml
@@ -0,0 +1,194 @@
+# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+# The redirects here are for dewikification backwards compatibility
+# and SHOULD NOT be used for adding new redirects for convenience.
+#
+# Convenience redirects should be added using our cloudflare worker
+# at https://github.com/python-discord/workers/tree/main/short-urls
+# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+# Root pages
+roles_redirect:
+ original_path: pages/roles/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["server-info/roles"]
+
+roles_expectations_redirect:
+ original_path: pages/roles/staff-role-expectations/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["server-info/staff-role-expectations"]
+
+contributing_redirect:
+ original_path: pages/contributing/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["guides/pydis-guides/contributing"]
+
+# Guides
+guides_redirect:
+ original_path: pages/resources/guides/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["guides"]
+
+# - Python guides
+discord_py_redirect:
+ original_path: pages/resources/guides/discordpy/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["guides/python-guides/discordpy"]
+
+mutability_redirect:
+ original_path: pages/resources/guides/core-concepts/mutability/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["guides/python-guides/mutability"]
+
+function_params_redirect:
+ original_path: pages/resources/guides/core-concepts/parameters-and-arguments/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["guides/python-guides/parameters-and-arguments"]
+
+# - Pydis guides
+help_channel_redirect:
+ original_path: pages/resources/guides/help-channels/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["guides/pydis-guides/help-channel-guide"]
+
+good_questions_redirect:
+ original_path: pages/resources/guides/asking-good-questions/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["guides/pydis-guides/asking-good-questions"]
+
+helping_others_redirect:
+ original_path: pages/resources/guides/helping-others/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["guides/pydis-guides/helping-others"]
+
+code_review_redirect:
+ original_path: pages/resources/guides/code-reviews-primer/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["guides/pydis-guides/code-reviews-primer"]
+
+off-topic_redirect:
+ original_path: pages/resources/guides/off-topic-etiquette/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["guides/pydis-guides/off-topic-etiquette"]
+
+# Resources
+resources_index_redirect:
+ original_path: pages/resources/
+ redirect_route: "resources:index"
+
+resources_resources_redirect:
+ original_path: pages/resources/<str:category>/
+ redirect_route: "resources:resources"
+
+# Events
+events_index_redirect:
+ original_path: pages/events/
+ redirect_route: "events:index"
+
+events_code_jams_index_redirect:
+ original_path: pages/code-jams/
+ redirect_route: "events:page"
+ redirect_arguments: ["code-jams"]
+
+events_code_jams_one_redirect:
+ original_path: pages/code-jams/code-jam-1-snakes-bot/
+ redirect_route: "events:page"
+ redirect_arguments: ["code-jams/1"]
+
+events_code_jams_two_redirect:
+ original_path: pages/code-jams/code-jam-2/
+ redirect_route: "events:page"
+ redirect_arguments: ["code-jams/2"]
+
+events_code_jams_three_redirect:
+ original_path: pages/code-jams/code-jam-3/
+ redirect_route: "events:page"
+ redirect_arguments: ["code-jams/3"]
+
+events_code_jams_four_redirect:
+ original_path: pages/code-jams/code-jam-4/
+ redirect_route: "events:page"
+ redirect_arguments: ["code-jams/4"]
+
+events_code_jams_five_redirect:
+ original_path: pages/code-jams/code-jam-5/
+ redirect_route: "events:page"
+ redirect_arguments: ["code-jams/5"]
+
+events_code_jams_six_redirect:
+ original_path: pages/code-jams/code-jam-6/
+ redirect_route: "events:page"
+ redirect_arguments: ["code-jams/6"]
+
+events_code_jams_six_rules_redirect:
+ original_path: pages/code-jams/code-jam-6/rules/
+ redirect_route: "events:page"
+ redirect_arguments: ["code-jams/6/rules"]
+
+events_code_jams_seven_redirect:
+ original_path: pages/code-jams/code-jam-7/
+ redirect_route: "events:page"
+ redirect_arguments: ["code-jams/7"]
+
+events_code_jams_seven_rules_redirect:
+ original_path: pages/code-jams/code-jam-7/rules/
+ redirect_route: "events:page"
+ redirect_arguments: ["code-jams/7/rules"]
+
+events_code_jams_how_to_use_git_redirect:
+ original_path: pages/code-jams/using-git/
+ redirect_route: "events:page"
+ redirect_arguments: ["code-jams/using-git"]
+
+events_code_jams_judging_redirect:
+ original_path: pages/code-jams/judging/
+ redirect_route: "events:page"
+ redirect_arguments: ["code-jams/judging"]
+
+events_code_jams_pull_request_redirect:
+ original_path: pages/code-jams/pull-request/
+ redirect_route: "events:page"
+ redirect_arguments: ["code-jams/pull-request"]
+
+events_game_jams_twenty_twenty_index_redirect:
+ original_path: pages/events/game-jam-2020/
+ redirect_route: "events:page"
+ redirect_arguments: ["game-jams/2020"]
+
+events_game_jams_twenty_twenty_judging_redirect:
+ original_path: pages/events/game-jam-2020/judging/
+ redirect_route: "events:page"
+ redirect_arguments: ["game-jams/2020/judging"]
+
+events_game_jams_twenty_twenty_project_setup_redirect:
+ original_path: pages/events/game-jam-2020/project-setup/
+ redirect_route: "events:page"
+ redirect_arguments: ["game-jams/2020/project-setup"]
+
+events_game_jams_twenty_twenty_rules_redirect:
+ original_path: pages/events/game-jam-2020/rules/
+ redirect_route: "events:page"
+ redirect_arguments: ["game-jams/2020/rules"]
+
+events_game_jams_twenty_twenty_technical_requirements_redirect:
+ original_path: pages/events/game-jam-2020/technical-requirements
+ redirect_route: "events:page"
+ redirect_arguments: ["game-jams/2020/technical-requirements"]
+
+# This are overrides for the contributing prefix redirect
+security_notice_redirect:
+ original_path: pages/contributing/security-notice/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["security-notice"]
+
+sir-lancebot_env_var_redirect:
+ original_path: pages/contributing/sir-lancebot/sir-lancebot-env-var-reference/
+ redirect_route: "content:page_category"
+ redirect_arguments: ["guides/pydis-guides/contributing/sir-lancebot/env-var-reference"]
+
+# Prefix redirects
+# Prefix redirects must be last in each group.
+guides_pydis_guides_contributing_prefix_redirect:
+ original_path: pages/contributing/<path:path>/ # path:path will be joined together with static arguments.
+ redirect_route: "content:page_category"
+ redirect_arguments: ["guides/pydis-guides/contributing/"] # It is important to put / at end in prefix redirect!
+ prefix_redirect: true
diff --git a/pydis_site/apps/redirect/tests.py b/pydis_site/apps/redirect/tests.py
new file mode 100644
index 00000000..c145ecda
--- /dev/null
+++ b/pydis_site/apps/redirect/tests.py
@@ -0,0 +1,58 @@
+import yaml
+from django.conf import settings
+from django.test import TestCase
+from django.urls import reverse
+
+TESTING_ARGUMENTS = {
+ "resources_resources_redirect": ("reading",),
+ "guides_pydis_guides_contributing_prefix_redirect": ("sir-lancebot/env-var-reference",),
+}
+
+
+class RedirectTests(TestCase):
+ """Survival tests for redirects."""
+
+ def test_redirects(self) -> None:
+ """
+ Should redirect to given route based on redirect rules.
+
+ Makes sure that every redirect:
+ 1. Redirects only once.
+ 2. Redirects to right URL.
+ 3. Resulting page status code is 200.
+ """
+ for name, data in yaml.safe_load(settings.REDIRECTIONS_PATH.read_text()).items():
+ with self.subTest(
+ original_path=data["original_path"],
+ redirect_route=data["redirect_route"],
+ name=name,
+ redirect_arguments=tuple(data.get("redirect_arguments", ())),
+ args=TESTING_ARGUMENTS.get(name, ())
+ ):
+ resp = self.client.get(
+ reverse(
+ f"home:redirect:{name}",
+ args=TESTING_ARGUMENTS.get(name, ())
+ ),
+ follow=True
+ )
+
+ if data.get("prefix_redirect", False):
+ expected_args = (
+ "".join(
+ tuple(data.get("redirect_arguments", ())) + TESTING_ARGUMENTS.get(name, ())
+ ),
+ )
+ else:
+ expected_args = TESTING_ARGUMENTS.get(name, ()) + tuple(data.get("redirect_arguments", ()))
+
+ self.assertEqual(1, len(resp.redirect_chain))
+ self.assertRedirects(
+ resp,
+ reverse(
+ f"home:{data['redirect_route']}",
+ args=expected_args
+ ),
+ status_code=302
+ )
+ self.assertEqual(resp.status_code, 200)
diff --git a/pydis_site/apps/redirect/urls.py b/pydis_site/apps/redirect/urls.py
new file mode 100644
index 00000000..6187af17
--- /dev/null
+++ b/pydis_site/apps/redirect/urls.py
@@ -0,0 +1,19 @@
+import yaml
+from django.conf import settings
+from django.urls import path
+
+from pydis_site.apps.redirect.views import CustomRedirectView
+
+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()
+]
diff --git a/pydis_site/apps/redirect/views.py b/pydis_site/apps/redirect/views.py
new file mode 100644
index 00000000..9dc9881a
--- /dev/null
+++ b/pydis_site/apps/redirect/views.py
@@ -0,0 +1,26 @@
+import typing as t
+
+from django.views.generic import RedirectView
+
+
+class CustomRedirectView(RedirectView):
+ """Extended RedirectView for manual route args."""
+
+ # We want temporary redirects for the time being, after this is running on prod and
+ # stable we can enable permanent redirects.
+ permanent = False
+ static_args = ()
+ prefix_redirect = False
+
+ @classmethod
+ def as_view(cls, **initkwargs):
+ """Overwrites original as_view to add static args."""
+ return super().as_view(**initkwargs)
+
+ def get_redirect_url(self, *args, **kwargs) -> t.Optional[str]:
+ """Extends default behaviour to use static args."""
+ args = self.static_args + args + tuple(kwargs.values())
+ if self.prefix_redirect:
+ args = ("".join(args),)
+
+ return super().get_redirect_url(*args)
diff --git a/pydis_site/settings.py b/pydis_site/settings.py
index d409bb21..65bd8e7a 100644
--- a/pydis_site/settings.py
+++ b/pydis_site/settings.py
@@ -87,6 +87,7 @@ INSTALLED_APPS = [
'pydis_site.apps.resources',
'pydis_site.apps.content',
'pydis_site.apps.events',
+ 'pydis_site.apps.redirect',
'django.contrib.admin',
'django.contrib.auth',
@@ -290,3 +291,5 @@ EVENTS_PAGES_PATH = Path(BASE_DIR, "pydis_site", "templates", "events", "pages")
# Path for content pages
CONTENT_PAGES_PATH = Path(BASE_DIR, "pydis_site", "apps", "content", "resources")
+
+REDIRECTIONS_PATH = Path(BASE_DIR, "pydis_site", "apps", "redirect", "redirects.yaml")
diff --git a/pydis_site/templates/base/navbar.html b/pydis_site/templates/base/navbar.html
index 6c8d52a1..ebafa269 100644
--- a/pydis_site/templates/base/navbar.html
+++ b/pydis_site/templates/base/navbar.html
@@ -61,35 +61,35 @@
More
</a>
<div class="navbar-dropdown">
- <a class="navbar-item" href="#">
+ <a class="navbar-item" href="{% url "resources:index" %}">
Resources
</a>
- <a class="navbar-item" href="#">
+ <a class="navbar-item" href="{% url "resources:resources" category="tools" %}">
Tools
</a>
- <a class="navbar-item" href="#">
+ <a class="navbar-item" href="{% url "content:page_category" location="guides/pydis-guides/contributing"%}">
Contributing
</a>
- <a class="navbar-item" href="#">
+ <a class="navbar-item" href="{% url "content:page_category" location="frequently-asked-questions" %}">
FAQ
</a>
- <a class="navbar-item" href="#">
+ <a class="navbar-item" href="{% url "content:page_category" location="rules" %}">
Rules
</a>
- <a class="navbar-item" href="#">
+ <a class="navbar-item" href="{% url "content:page_category" location="code-of-conduct" %}">
Code of Conduct
</a>
- <a class="navbar-item" href="#">
+ <a class="navbar-item" href="{% url "content:page_category" location="privacy" %}">
Privacy
</a>
<hr class="navbar-divider">
<div class="navbar-item">
<strong>Events</strong>
</div>
- <a class="navbar-item" href="#">
+ <a class="navbar-item" href="{% url "events:page" path="code-jams/7" %}">
Most Recent: Code Jam 7
</a>
- <a class="navbar-item" href="#">
+ <a class="navbar-item" href="{% url "events:index" %}">
All events
</a>
</div>