chore: ruff formatting

This commit is contained in:
neoarz
2025-11-02 23:32:52 -05:00
parent 2ce2c69a87
commit 1eff6c9f53
91 changed files with 3824 additions and 2518 deletions

View File

@@ -5,7 +5,13 @@ from .signal import setup_signal_handlers
from .contributors import generate_contributors_image
__all__ = [
'ascii', 'ascii_plain', 'gradient_text', 'gradient_text_selective',
'LoggingFormatter', 'setup_logger', 'get_uptime', 'setup_signal_handlers',
'generate_contributors_image'
]
"ascii",
"ascii_plain",
"gradient_text",
"gradient_text_selective",
"LoggingFormatter",
"setup_logger",
"get_uptime",
"setup_signal_handlers",
"generate_contributors_image",
]

View File

@@ -3,9 +3,11 @@
import math
def gradient_text(text, start_color, end_color):
def rgb_interp(start, end, t):
return tuple(int(start[i] + (end[i] - start[i]) * t) for i in range(3))
lines = text.splitlines()
gradient_lines = []
total_chars = sum(len(line) for line in lines if line.strip())
@@ -23,24 +25,27 @@ def gradient_text(text, start_color, end_color):
gradient_lines.append(colored_line)
return "\n".join(gradient_lines)
def gradient_text_selective(text, start_color, end_color, gradient_word, white_prefix=""):
def gradient_text_selective(
text, start_color, end_color, gradient_word, white_prefix=""
):
def rgb_interp(start, end, t):
return tuple(int(start[i] + (end[i] - start[i]) * t) for i in range(3))
lines = text.splitlines()
result_lines = []
for line in lines:
if gradient_word in line and white_prefix in line:
prefix_start = line.find(white_prefix)
word_start = line.find(gradient_word)
if prefix_start != -1 and word_start != -1:
before_prefix = line[:prefix_start]
prefix_part = line[prefix_start:word_start]
word_part = gradient_word
after_word = line[word_start + len(gradient_word):]
after_word = line[word_start + len(gradient_word) :]
colored_before = ""
total_chars = sum(1 for char in before_prefix if char.strip())
idx = 0
@@ -52,9 +57,9 @@ def gradient_text_selective(text, start_color, end_color, gradient_word, white_p
idx += 1
else:
colored_before += char
white_prefix_colored = f"\033[38;2;255;255;255m{prefix_part}\033[0m"
colored_word = ""
word_chars = [char for char in word_part if char.strip()]
for i, char in enumerate(word_part):
@@ -64,8 +69,10 @@ def gradient_text_selective(text, start_color, end_color, gradient_word, white_p
colored_word += f"\033[38;2;{r};{g};{b}m{char}\033[0m"
else:
colored_word += char
result_lines.append(colored_before + white_prefix_colored + colored_word + after_word)
result_lines.append(
colored_before + white_prefix_colored + colored_word + after_word
)
else:
colored_line = ""
total_chars = sum(1 for char in line if char.strip())
@@ -92,7 +99,7 @@ def gradient_text_selective(text, start_color, end_color, gradient_word, white_p
else:
colored_line += char
result_lines.append(colored_line)
return "\n".join(result_lines)
@@ -105,8 +112,8 @@ _ascii_art = """
╚══════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝
"""
_start_rgb = (88, 101, 242)
_end_rgb = (114, 137, 218)
_start_rgb = (88, 101, 242)
_end_rgb = (114, 137, 218)
ascii = gradient_text_selective(_ascii_art, _start_rgb, _end_rgb, "neoarz", "Made by ")

View File

@@ -1,15 +1,17 @@
import os
from discord.ext import commands
def get_owner_friend_ids():
owner_friends = os.getenv("OWNER_FRIENDS", "")
if not owner_friends.strip():
return []
return [int(id.strip()) for id in owner_friends.split(",") if id.strip().isdigit()]
def is_owner_or_friend():
async def predicate(ctx):
owner_friend_ids = get_owner_friend_ids()
return ctx.author.id in owner_friend_ids or await ctx.bot.is_owner(ctx.author)
return commands.check(predicate)
return commands.check(predicate)

View File

@@ -8,32 +8,32 @@ 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"
"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':
if response.headers.get("X-RateLimit-Remaining") == "0":
break
return contributors
@@ -41,65 +41,66 @@ 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):
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
return buffer

View File

@@ -37,12 +37,14 @@ def setup_logger():
console_handler = logging.StreamHandler()
console_handler.setFormatter(LoggingFormatter())
log_file_path = os.getenv("LOG_FILE", "logs/discord.log")
log_dir = os.path.dirname(log_file_path)
if log_dir:
os.makedirs(log_dir, exist_ok=True)
file_handler = logging.FileHandler(filename=log_file_path, encoding="utf-8", mode="w")
file_handler = logging.FileHandler(
filename=log_file_path, encoding="utf-8", mode="w"
)
file_handler_formatter = logging.Formatter(
"[{asctime}] [{levelname:<8}] {name}: {message}", "%Y-%m-%d %H:%M:%S", style="{"
)
@@ -50,5 +52,5 @@ def setup_logger():
logger.addHandler(console_handler)
logger.addHandler(file_handler)
return logger

View File

@@ -8,6 +8,6 @@ def setup_signal_handlers(bot):
if bot.loop and not bot.loop.is_closed():
asyncio.create_task(bot.close())
bot.loop.call_soon_threadsafe(bot.loop.stop)
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)

View File

@@ -7,7 +7,7 @@ def get_uptime(start_time: float) -> str:
hours = (uptime_seconds % 86400) // 3600
minutes = (uptime_seconds % 3600) // 60
seconds = uptime_seconds % 60
if days > 0:
return f"{days}d {hours}h {minutes}m {seconds}s"
elif hours > 0: