diff options
Diffstat (limited to 'pydis_site/apps/home/views/home.py')
-rw-r--r-- | pydis_site/apps/home/views/home.py | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/pydis_site/apps/home/views/home.py b/pydis_site/apps/home/views/home.py new file mode 100644 index 00000000..e4daf380 --- /dev/null +++ b/pydis_site/apps/home/views/home.py @@ -0,0 +1,115 @@ +from typing import Dict, List + +import requests +from django.core.handlers.wsgi import WSGIRequest +from django.http import HttpResponse +from django.shortcuts import render +from django.utils import timezone +from django.views import View + +from pydis_site.apps.home.models import RepositoryMetadata + + +class HomeView(View): + """The main landing page for the website.""" + + github_api = "https://api.github.com/users/python-discord/repos" + repository_cache_ttl = 600 + + # Which of our GitHub repos should be displayed on the front page, and in which order? + repos = [ + "python-discord/site", + "python-discord/bot", + "python-discord/snekbox", + "python-discord/seasonalbot", + "python-discord/django-simple-bulma", + "python-discord/django-crispy-bulma", + ] + + def _get_api_data(self) -> Dict[str, Dict[str, str]]: + """Call the GitHub API and get information about our repos.""" + + repo_dict = {repo_name: {} for repo_name in self.repos} + + # Fetch the data from the GitHub API + api_data = requests.get(self.github_api) + api_data = api_data.json() + + # Process the API data into our dict + for repo in api_data: + full_name = repo["full_name"] + + if full_name in self.repos: + repo_dict[full_name] = { + "full_name": repo["full_name"], + "description": repo["description"], + "language": repo["language"], + "forks_count": repo["forks_count"], + "stargazers_count": repo["stargazers_count"], + } + return repo_dict + + def _get_repo_data(self) -> List[RepositoryMetadata]: + """Build a list of RepositoryMetadata objects that we can use to populate the front page.""" + + # Try to get site data from the cache + try: + repo_data = RepositoryMetadata.objects.get(repo_name="python-discord/site") + + # If the data is stale, we should refresh it. + if (timezone.now() - repo_data.last_updated).seconds > self.repository_cache_ttl: + + # Get new data from API + api_repositories = self._get_api_data() + database_repositories = [] + + # 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.append(repo_data) + return database_repositories + + # Otherwise, if the data is fresher than 2 minutes old, we should just return it. + else: + return RepositoryMetadata.objects.all() + + # If this is raised, the database has no repodata at all, we will create them all. + except RepositoryMetadata.DoesNotExist: + + # Get new data from API + api_repositories = self._get_api_data() + database_repositories = [] + + # Create all the repodata records in the database. + for api_data in api_repositories.values(): + 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.append(repo_data) + + return database_repositories + + def get(self, request: WSGIRequest) -> HttpResponse: + """Collect repo data and render the homepage view""" + + repo_data = self._get_repo_data() + return render(request, "home/index.html", {"repo_data": repo_data}) |