Skip to content

Commit a52f8a8

Browse files
authored
Merge branch 'main' into fix/chat
2 parents ef8e9ad + 431f6fe commit a52f8a8

File tree

4 files changed

+84
-26
lines changed

4 files changed

+84
-26
lines changed

poetry.lock

Lines changed: 7 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ django-allauth = "^0.61.1"
1414
beautifulsoup4 = "^4.13.3"
1515
django-email-obfuscator = "^0.1.5"
1616
django-gravatar2 = "^1.4.5"
17-
django-import-export = "^4.3.5"
17+
django-import-export = "^4.3.7"
1818
django-annoying = "^0.10.7"
1919
dj-rest-auth = "^5.0.2"
2020
user-agents = "^2.2.0"
@@ -40,7 +40,7 @@ django-mdeditor = "^0.1.20"
4040
django-tz-detect = "^0.4.0"
4141
django-star-ratings = "^0.9.2"
4242
django-environ = "^0.12.0"
43-
django-simple-captcha = "^0.6.1"
43+
django-simple-captcha = "^0.6.2"
4444
django-filter = "^24.3"
4545
pillow = "^10.4.0"
4646
sentry-sdk = "^2.22.0"

website/management/commands/fetch_contributors.py

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import time
2+
from urllib.parse import urlparse
23

34
import requests
45
from django.conf import settings
@@ -20,6 +21,7 @@ def add_arguments(self, parser):
2021

2122
def handle(self, *args, **kwargs):
2223
project_id = kwargs.get("project_id")
24+
2325
if not project_id:
2426
self.stdout.write(self.style.ERROR("Please provide a project ID using --project_id"))
2527
return
@@ -30,27 +32,62 @@ def handle(self, *args, **kwargs):
3032
self.stdout.write(self.style.ERROR(f"Project with ID {project_id} does not exist"))
3133
return
3234

35+
repo = None
36+
37+
if not hasattr(project, "url"):
38+
self.stdout.write(self.style.ERROR(f"Project {project.name} does not have a URL attribute"))
39+
return
40+
41+
if not project.url:
42+
self.stdout.write(self.style.ERROR(f"Project {project.name} has an empty URL"))
43+
return
44+
45+
try:
46+
parsed_url = urlparse(project.url.strip())
47+
48+
if parsed_url.netloc == "github.com":
49+
repo_path = parsed_url.path.strip("/")
50+
if repo_path and repo_path.count("/") == 1:
51+
repo = repo_path
52+
else:
53+
self.stdout.write(
54+
self.style.ERROR(f"Invalid GitHub repository format: {parsed_url.path}. Expected 'owner/repo'")
55+
)
56+
return
57+
else:
58+
self.stdout.write(self.style.ERROR(f"Project URL is not a GitHub repository URL: {project.url}"))
59+
return
60+
except Exception as e:
61+
self.stdout.write(self.style.ERROR(f"Error parsing URL {project.url}: {str(e)}"))
62+
return
63+
64+
if not repo:
65+
self.stdout.write(self.style.ERROR("Could not extract valid GitHub repository information"))
66+
return
67+
3368
headers = {
3469
"Authorization": f"token {settings.GITHUB_TOKEN}",
3570
"Content-Type": "application/json",
3671
}
3772

38-
owner_repo = project.github_url.rstrip("/").split("/")[-2:]
39-
repo_name = f"{owner_repo[0]}/{owner_repo[1]}"
4073
contributors = []
4174

4275
# Fetch contributors
4376
page = 1
4477
while True:
45-
url = f"https://api.github.com/repos/{repo_name}/contributors?per_page=100&page={page}"
78+
url = f"https://api.github.com/repos/{repo}/contributors?per_page=100&page={page}"
79+
self.stdout.write(self.style.SUCCESS(f"Fetching from: {url}"))
80+
4681
response = requests.get(url, headers=headers)
4782

4883
if response.status_code != 200:
4984
self.stdout.write(
50-
self.style.WARNING(
51-
f"Failed to fetch contributors for {repo_name} page {page}: {response.status_code}"
52-
)
85+
self.style.WARNING(f"Failed to fetch contributors for {repo} page {page}: {response.status_code}")
5386
)
87+
if response.status_code == 404:
88+
self.stdout.write(self.style.ERROR(f"Repository '{repo}' not found. Please check the project URL."))
89+
elif response.status_code == 403:
90+
self.stdout.write(self.style.ERROR("API rate limit exceeded or authentication issue."))
5491
break
5592

5693
contributors_data = response.json()
@@ -59,30 +96,53 @@ def handle(self, *args, **kwargs):
5996

6097
for c in contributors_data:
6198
try:
99+
name = str(c["login"])[:255]
100+
github_url = str(c["html_url"])[:255]
101+
avatar_url = str(c["avatar_url"])[:255]
102+
62103
contributor, created = Contributor.objects.get_or_create(
63104
github_id=c["id"],
64105
defaults={
65-
"name": c["login"],
66-
"github_url": c["html_url"],
67-
"avatar_url": c["avatar_url"],
68-
"contributor_type": c["type"],
106+
"name": name,
107+
"github_url": github_url,
108+
"avatar_url": avatar_url,
109+
"contributor_type": str(c["type"])[:255],
69110
"contributions": c["contributions"],
70111
},
71112
)
113+
114+
if not created:
115+
contributor.contributions = c["contributions"]
116+
contributor.save()
117+
72118
contributors.append(contributor)
119+
120+
if created:
121+
self.stdout.write(f"Created new contributor: {name}")
122+
else:
123+
self.stdout.write(f"Updated existing contributor: {name}")
124+
73125
except MultipleObjectsReturned:
126+
self.stdout.write(self.style.WARNING(f"Multiple records found for {c['login']}"))
74127
contributor = Contributor.objects.filter(github_id=c["id"]).first()
75128
contributors.append(contributor)
129+
except Exception as e:
130+
self.stdout.write(self.style.ERROR(f"Error processing contributor {c['login']}: {str(e)}"))
76131

77132
if "next" not in response.links:
78133
break
79134

80135
page += 1
81-
# Respect GitHub's rate limits
82136
time.sleep(1)
83137

84-
project.contributors.set(contributors)
85-
project.contributor_count = len(contributors)
86-
project.save()
138+
# Link contributors to project
139+
if hasattr(project, "contributors"):
140+
project.contributors.set(contributors)
141+
self.stdout.write(f"Set {len(contributors)} contributors for project {project.name}")
142+
143+
if hasattr(project, "contributor_count"):
144+
project.contributor_count = len(contributors)
145+
project.save()
146+
self.stdout.write(f"Updated contributor count to {len(contributors)}")
87147

88148
self.stdout.write(self.style.SUCCESS(f"Successfully fetched contributors for project {project.name}"))

website/templates/projects/repo_detail.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -998,8 +998,7 @@ <h3 class="font-medium text-gray-900 group-hover:text-red-600 transition-colors"
998998
row.innerHTML = `
999999
<td class="px-4 py-4 whitespace-nowrap">
10001000
<div class="flex items-center">
1001-
<img class="h-8 w-8 rounded-full" width="20" height="20"
1002-
src="${stat.contributor.avatar_url}" alt="${stat.contributor.name}">
1001+
<img class="h-8 w-8 rounded-full" width="20" height="20" src="${stat.contributor.avatar_url}" alt="${stat.contributor.name}">
10031002
<div class="ml-3">
10041003
<div class="text-sm font-medium text-gray-900">${stat.contributor.name}</div>
10051004
<div class="text-sm text-gray-500">@${stat.contributor.github_id}</div>

0 commit comments

Comments
 (0)