mirror of
https://github.com/neoarz/Syntrel.git
synced 2025-12-25 03:40:11 +01:00
feat(botinfo): contributors!!!
This commit is contained in:
105
utils/contributors.py
Normal file
105
utils/contributors.py
Normal file
@@ -0,0 +1,105 @@
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user