diff options
Diffstat (limited to 'pydis_site')
| -rw-r--r-- | pydis_site/apps/home/views/home.py | 153 | 
1 files changed, 81 insertions, 72 deletions
| diff --git a/pydis_site/apps/home/views/home.py b/pydis_site/apps/home/views/home.py index e9ed0df0..ddbfc4b4 100644 --- a/pydis_site/apps/home/views/home.py +++ b/pydis_site/apps/home/views/home.py @@ -1,4 +1,3 @@ -import datetime  import logging  from typing import Dict, List @@ -31,79 +30,59 @@ class HomeView(View):      ]      def _get_api_data(self) -> Dict[str, Dict[str, str]]: -        """Call the GitHub API and get information about our repos.""" -        repo_dict: Dict[str, dict] = {repo_name: {} for repo_name in self.repos} +        """ +        Call the GitHub API and get information about our repos. + +        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).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"], -                } +            try: +                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"], +                    } +            # Something is not right about the API data we got back from GitHub. +            except (TypeError, ConnectionError, KeyError) as e: +                log.error( +                    "Unable to parse the GitHub repository metadata from response!", +                    extra={ +                        'api_data': api_data, +                        'error': e +                    } +                ) +                continue          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") +        database_repositories = [] -            # If the data is stale, we should refresh it. -            if (timezone.now() - repo_data.last_updated).seconds > self.repository_cache_ttl: +        # First, let's see if we have any metadata cached. +        cached_data = RepositoryMetadata.objects.all() -                # Try to get new data from the API. If it fails, return the cached data. -                try: -                    api_repositories = self._get_api_data() -                except (TypeError, ConnectionError): -                    return RepositoryMetadata.objects.all() -                database_repositories = [] - -                # Update or create all RepoData objects in self.repos -                for repo_name, api_data in api_repositories.items(): -                    if api_data: -                        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) -                    else: -                        log.error(f"No API data is available for {repo_name}!") -                return database_repositories - -            # Otherwise, if the data is fresher than 2 minutes old, we should just return it. -            else: -                return RepositoryMetadata.objects.all() +        # If we don't, we have to create some! +        if not cached_data: -        # If this is raised, the database has no repodata at all, we will create them all. -        except RepositoryMetadata.DoesNotExist: -            database_repositories = [] -            try: -                # Get new data from API -                api_repositories = self._get_api_data() +            # Try to get new data from the API. If it fails, 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(): +            # Create all the repodata records in the database. +            for api_data in api_repositories.values(): +                try:                      repo_data = RepositoryMetadata(                          repo_name=api_data["full_name"],                          description=api_data["description"], @@ -111,23 +90,53 @@ class HomeView(View):                          stargazers=api_data["stargazers_count"],                          language=api_data["language"],                      ) -                    repo_data.save() -                    database_repositories.append(repo_data) -            except TypeError: -                for repo_name in self.repos: -                    repo_data = RepositoryMetadata( -                        last_updated=timezone.now() - datetime.timedelta(minutes=50), -                        repo_name=repo_name, -                        description="Not available.", -                        forks=999, -                        stargazers=999, -                        language="Python", +                # This error indicates there's something not quite right about the api_data types. +                # In that case, just skip this repo. +                except TypeError: +                    log.error( +                        "Encountered a TypeError while processing RepositoryMetadata " +                        "from the GitHub API.", +                        extra=api_data                      ) -                    repo_data.save() -                    database_repositories.append(repo_data) +                    continue + +                repo_data.save() +                database_repositories.append(repo_data)              return database_repositories +        # If the data is stale, we should refresh it. +        if (timezone.now() - cached_data[0].last_updated).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() + +            if not api_repositories: +                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.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() +      def get(self, request: WSGIRequest) -> HttpResponse:          """Collect repo data and render the homepage view."""          repo_data = self._get_repo_data() | 
