aboutsummaryrefslogtreecommitdiffstats
path: root/pydis_site/apps
diff options
context:
space:
mode:
Diffstat (limited to 'pydis_site/apps')
-rw-r--r--pydis_site/apps/api/admin.py4
-rw-r--r--pydis_site/apps/api/migrations/0072_doc_allow_blank_base_url.py19
-rw-r--r--pydis_site/apps/api/models/bot/documentation_link.py1
-rw-r--r--pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md2
-rw-r--r--pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md2
-rw-r--r--pydis_site/apps/home/urls.py1
-rw-r--r--pydis_site/apps/home/views/home.py80
7 files changed, 70 insertions, 39 deletions
diff --git a/pydis_site/apps/api/admin.py b/pydis_site/apps/api/admin.py
index 449e660e..2aca38a1 100644
--- a/pydis_site/apps/api/admin.py
+++ b/pydis_site/apps/api/admin.py
@@ -48,8 +48,8 @@ class BotSettingAdmin(admin.ModelAdmin):
class DocumentationLinkAdmin(admin.ModelAdmin):
"""Admin formatting for the DocumentationLink model."""
- fields = ("package", "base_url", "inventory_url")
- list_display = ("package", "base_url", "inventory_url")
+ fields = ("package", "inventory_url", "base_url")
+ list_display = ("package", "inventory_url", "base_url")
list_editable = ("base_url", "inventory_url")
search_fields = ("package",)
diff --git a/pydis_site/apps/api/migrations/0072_doc_allow_blank_base_url.py b/pydis_site/apps/api/migrations/0072_doc_allow_blank_base_url.py
new file mode 100644
index 00000000..d4899354
--- /dev/null
+++ b/pydis_site/apps/api/migrations/0072_doc_allow_blank_base_url.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.0.14 on 2021-08-30 21:09
+
+from django.db import migrations, models
+import pydis_site.apps.api.models.bot.documentation_link
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0071_increase_message_content_4000'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='documentationlink',
+ name='base_url',
+ field=models.URLField(blank=True, help_text='The base URL from which documentation will be available for this project. Used to generate links to various symbols within this package.', validators=[pydis_site.apps.api.models.bot.documentation_link.ends_with_slash_validator]),
+ ),
+ ]
diff --git a/pydis_site/apps/api/models/bot/documentation_link.py b/pydis_site/apps/api/models/bot/documentation_link.py
index 3dcc71fc..9941907c 100644
--- a/pydis_site/apps/api/models/bot/documentation_link.py
+++ b/pydis_site/apps/api/models/bot/documentation_link.py
@@ -30,6 +30,7 @@ class DocumentationLink(ModelReprMixin, models.Model):
"The base URL from which documentation will be available for this project. "
"Used to generate links to various symbols within this package."
),
+ blank=True,
validators=(ends_with_slash_validator,)
)
inventory_url = models.URLField(
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
index 601cfa4a..068b08ae 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
@@ -97,7 +97,7 @@ The first time you run this command, it may take a few minutes while Docker down
$ docker-compose up
```
-If you get any Docker related errors, reference the [Possible Issues](./docker/possible-issues) section of the Docker page.
+If you get any Docker related errors, reference the [Possible Issues](../docker#possible-issues) section of the Docker page.
{: .notification .is-warning }
## Run on the host
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md
index 5c472eb2..2a7ef0d6 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md
@@ -32,7 +32,7 @@ Additionally, you may find the following environment variables useful during dev
| `REDIS_PASSWORD` | |
| `USE_FAKEREDIS` | If the FakeRedis module should be used. Set this to true if you don't have a Redis database setup. |
| `BOT_SENTRY_DSN` | The DSN of the sentry monitor. |
-| `TRASHCAN_EMOJI` | The emoji to use for the trashcan during paginated embeds |
+| `TRASHCAN_EMOJI` | The full emoji to use for the trashcan. Format should be like the output of `\:emoji:`. |
---
diff --git a/pydis_site/apps/home/urls.py b/pydis_site/apps/home/urls.py
index 1e2af8f3..bb77220b 100644
--- a/pydis_site/apps/home/urls.py
+++ b/pydis_site/apps/home/urls.py
@@ -7,6 +7,7 @@ app_name = 'home'
urlpatterns = [
path('', HomeView.as_view(), name='home'),
path('', include('pydis_site.apps.redirect.urls')),
+ path('', include('django_prometheus.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/home/views/home.py b/pydis_site/apps/home/views/home.py
index b3767d37..bbb4b815 100644
--- a/pydis_site/apps/home/views/home.py
+++ b/pydis_site/apps/home/views/home.py
@@ -9,7 +9,7 @@ from django.utils import timezone
from django.views import View
from pydis_site.apps.home.models import RepositoryMetadata
-from pydis_site.constants import GITHUB_TOKEN
+from pydis_site.constants import GITHUB_TOKEN, TIMEOUT_PERIOD
log = logging.getLogger(__name__)
@@ -19,7 +19,6 @@ class HomeView(View):
github_api = "https://api.github.com/users/python-discord/repos?per_page=100"
repository_cache_ttl = 3600
- headers = {"Authorization": f"token {GITHUB_TOKEN}"}
# Which of our GitHub repos should be displayed on the front page, and in which order?
repos = [
@@ -35,6 +34,16 @@ class HomeView(View):
"""Clean up stale RepositoryMetadata."""
RepositoryMetadata.objects.exclude(repo_name__in=self.repos).delete()
+ # If no token is defined (for example in local development), then
+ # it does not make sense to pass the Authorization header. More
+ # specifically, GitHub will reject any requests from us due to the
+ # invalid header. We can make a limited number of anonymous requests
+ # though, which is useful for testing.
+ if GITHUB_TOKEN:
+ self.headers = {"Authorization": f"token {GITHUB_TOKEN}"}
+ else:
+ self.headers = {}
+
def _get_api_data(self) -> Dict[str, Dict[str, str]]:
"""
Call the GitHub API and get information about our repos.
@@ -42,9 +51,16 @@ class HomeView(View):
If we're unable to get that info for any reason, return an empty dict.
"""
repo_dict = {}
-
- # Fetch the data from the GitHub API
- api_data: List[dict] = requests.get(self.github_api, headers=self.headers).json()
+ try:
+ # Fetch the data from the GitHub API
+ api_data: List[dict] = requests.get(
+ self.github_api,
+ headers=self.headers,
+ timeout=TIMEOUT_PERIOD
+ ).json()
+ except requests.exceptions.Timeout:
+ log.error("Request to fetch GitHub repository metadata for timed out!")
+ return repo_dict
# Process the API data into our dict
for repo in api_data:
@@ -74,35 +90,33 @@ class HomeView(View):
def _get_repo_data(self) -> List[RepositoryMetadata]:
"""Build a list of RepositoryMetadata objects that we can use to populate the front page."""
- database_repositories = []
-
- # First, let's see if we have any metadata cached.
- cached_data = RepositoryMetadata.objects.all()
+ # First off, load the timestamp of the least recently updated entry.
+ last_update = (
+ RepositoryMetadata.objects.values_list("last_updated", flat=True)
+ .order_by("last_updated").first()
+ )
- # If we don't, we have to create some!
- if not cached_data:
+ # If we did not retrieve any results here, we should import them!
+ if last_update is None:
# Try to get new data from the API. If it fails, we'll return an empty list.
# In this case, we simply don't display our projects on the site.
api_repositories = self._get_api_data()
# Create all the repodata records in the database.
- for api_data in api_repositories.values():
- repo_data = RepositoryMetadata(
+ return RepositoryMetadata.objects.bulk_create(
+ RepositoryMetadata(
repo_name=api_data["full_name"],
description=api_data["description"],
forks=api_data["forks_count"],
stargazers=api_data["stargazers_count"],
language=api_data["language"],
)
-
- repo_data.save()
- database_repositories.append(repo_data)
-
- return database_repositories
+ for api_data in api_repositories.values()
+ )
# If the data is stale, we should refresh it.
- if (timezone.now() - cached_data[0].last_updated).seconds > self.repository_cache_ttl:
+ if (timezone.now() - last_update).seconds > self.repository_cache_ttl:
# Try to get new data from the API. If it fails, return the cached data.
api_repositories = self._get_api_data()
@@ -110,22 +124,18 @@ class HomeView(View):
return RepositoryMetadata.objects.all()
# Update or create all RepoData objects in self.repos
- for repo_name, api_data in api_repositories.items():
- try:
- repo_data = RepositoryMetadata.objects.get(repo_name=repo_name)
- repo_data.description = api_data["description"]
- repo_data.language = api_data["language"]
- repo_data.forks = api_data["forks_count"]
- repo_data.stargazers = api_data["stargazers_count"]
- except RepositoryMetadata.DoesNotExist:
- repo_data = RepositoryMetadata(
- repo_name=api_data["full_name"],
- description=api_data["description"],
- forks=api_data["forks_count"],
- stargazers=api_data["stargazers_count"],
- language=api_data["language"],
- )
- repo_data.save()
+ database_repositories = []
+ for api_data in api_repositories.values():
+ repo_data, _created = RepositoryMetadata.objects.update_or_create(
+ repo_name=api_data["full_name"],
+ defaults={
+ 'repo_name': api_data["full_name"],
+ 'description': api_data["description"],
+ 'forks': api_data["forks_count"],
+ 'stargazers': api_data["stargazers_count"],
+ 'language': api_data["language"],
+ }
+ )
database_repositories.append(repo_data)
return database_repositories