mirror of
https://github.com/neoarz/Syntrel.git
synced 2025-12-25 03:40:11 +01:00
106 lines
2.5 KiB
Python
106 lines
2.5 KiB
Python
from io import BytesIO
|
|
from math import ceil
|
|
|
|
import requests
|
|
from PIL import Image
|
|
|
|
|
|
def fetch_contributors(owner, repo):
|
|
contributors = []
|
|
page = 1
|
|
|
|
while True:
|
|
url = f"https://api.github.com/repos/{owner}/{repo}/contributors"
|
|
params = {"page": page, "per_page": 100}
|
|
|
|
headers = {
|
|
"User-Agent": "github-contributors-graph",
|
|
"Accept": "application/vnd.github.v3+json"
|
|
}
|
|
|
|
response = requests.get(url, headers=headers, params=params)
|
|
|
|
if not response.ok:
|
|
return []
|
|
|
|
data = response.json()
|
|
|
|
if not data:
|
|
break
|
|
|
|
contributors.extend(data)
|
|
page += 1
|
|
|
|
if response.headers.get('X-RateLimit-Remaining') == '0':
|
|
break
|
|
|
|
return contributors
|
|
|
|
|
|
def download_avatar(avatar_url, size):
|
|
try:
|
|
if "avatars.githubusercontent.com" in avatar_url:
|
|
avatar_url = f"{avatar_url}?s={size}"
|
|
|
|
response = requests.get(avatar_url, timeout=10)
|
|
|
|
if not response.ok:
|
|
return None
|
|
|
|
img = Image.open(BytesIO(response.content))
|
|
|
|
if img.size != (size, size):
|
|
img = img.resize((size, size), Image.Resampling.LANCZOS)
|
|
|
|
return img
|
|
|
|
except Exception:
|
|
return None
|
|
|
|
|
|
def generate_contributors_image(owner="neoarz", repo="syntrel", size=64, images_per_row=20):
|
|
contributors = fetch_contributors(owner, repo)
|
|
|
|
if not contributors:
|
|
return None
|
|
|
|
images = []
|
|
|
|
for contributor in contributors:
|
|
avatar_url = contributor.get("avatar_url")
|
|
|
|
if not avatar_url:
|
|
continue
|
|
|
|
img = download_avatar(avatar_url, size)
|
|
|
|
if img is None:
|
|
continue
|
|
|
|
images.append(img)
|
|
|
|
if not images:
|
|
return None
|
|
|
|
actual_images_per_row = min(len(images), images_per_row)
|
|
width = size * actual_images_per_row
|
|
row_count = ceil(len(images) / images_per_row)
|
|
height = size * row_count
|
|
|
|
canvas = Image.new("RGB", (width, height), color="black")
|
|
|
|
for idx, img in enumerate(images):
|
|
col = idx % images_per_row
|
|
row = idx // images_per_row
|
|
x = col * size
|
|
y = row * size
|
|
|
|
canvas.paste(img, (x, y))
|
|
|
|
buffer = BytesIO()
|
|
canvas.save(buffer, "PNG")
|
|
buffer.seek(0)
|
|
|
|
return buffer
|
|
|