mirror of
https://github.com/Lilac-Rose/Lacie.git
synced 2026-08-23 17:24:09 -05:00
embed stuff, and made it so listfonts shows an image so users know what the fonts look like
This commit is contained in:
@@ -61,8 +61,14 @@ class EmbedColor(commands.Cog):
|
||||
db.commit()
|
||||
db.close()
|
||||
|
||||
await interaction.response.send_message(f"Your embed color has been set to `{hex_color}`")
|
||||
embed = discord.Embed(
|
||||
title="✅ Embed Color Updated",
|
||||
description=f"Your embed color has been set to `{hex_color}`.\nHere's how it looks!",
|
||||
color=discord.Color(int(hex_color[1:], 16))
|
||||
)
|
||||
|
||||
await interaction.response.send_message(embed=embed)
|
||||
|
||||
@embed_group.command(name="view", description="View your current embed color")
|
||||
async def view_color(self, interaction: discord.Interaction):
|
||||
color = self.get_user_color(interaction.user)
|
||||
|
||||
@@ -24,7 +24,7 @@ class Profiles(commands.Cog):
|
||||
self.bot = bot
|
||||
setup_db()
|
||||
|
||||
@app_commands.command(name="listfonts", description="List all avaliable fonts for profiles.")
|
||||
@app_commands.command(name="listfonts", description="List all available fonts with a visual preview.")
|
||||
async def list_fonts_cmd(self, interaction: discord.Interaction):
|
||||
await interaction.response.defer(thinking=True)
|
||||
|
||||
@@ -32,7 +32,66 @@ class Profiles(commands.Cog):
|
||||
if not fonts:
|
||||
await interaction.followup.send("No fonts found in the fonts folder.")
|
||||
return
|
||||
await interaction.followup.send("**Avaliable Fonts:**\n" + "\n".join(f"- `{f}`" for f in fonts))
|
||||
|
||||
async def generate_font_preview():
|
||||
def _generate():
|
||||
font_sample_text = "The quick brown fox jumps over the lazy dog"
|
||||
margin = 40
|
||||
spacing = 90
|
||||
img_width = 1600
|
||||
img_height = max(400, len(fonts) * spacing + 60)
|
||||
img = Image.new("RGB", (img_width, img_height), "#1e1e1e")
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
y = margin
|
||||
for name in fonts:
|
||||
font_path_ttf = os.path.join(FONTS_PATH, f"{name}.ttf")
|
||||
font_path_otf = os.path.join(FONTS_PATH, f"{name}.otf")
|
||||
|
||||
try:
|
||||
if os.path.exists(font_path_ttf):
|
||||
preview_font = ImageFont.truetype(font_path_ttf, 36)
|
||||
elif os.path.exists(font_path_otf):
|
||||
preview_font = ImageFont.truetype(font_path_otf, 36)
|
||||
else:
|
||||
preview_font = ImageFont.load_default()
|
||||
except Exception:
|
||||
preview_font = ImageFont.load_default()
|
||||
|
||||
# Slightly smaller font name for balance
|
||||
try:
|
||||
if os.path.exists(font_path_ttf):
|
||||
name_font = ImageFont.truetype(font_path_ttf, 32)
|
||||
elif os.path.exists(font_path_otf):
|
||||
name_font = ImageFont.truetype(font_path_otf, 32)
|
||||
else:
|
||||
name_font = ImageFont.load_default()
|
||||
except Exception:
|
||||
name_font = ImageFont.load_default()
|
||||
|
||||
# Draw font name in lilac-blue
|
||||
draw.text((margin, y), f"{name}:", font=name_font, fill="#7289DA")
|
||||
|
||||
# Draw preview text with more horizontal space
|
||||
draw.text((350, y), font_sample_text, font=preview_font, fill="#FFFFFF")
|
||||
|
||||
# Optional divider line for clarity
|
||||
draw.line([(margin, y + spacing - 15), (img_width - margin, y + spacing - 15)], fill="#2f3136", width=2)
|
||||
|
||||
y += spacing
|
||||
|
||||
buffer = io.BytesIO()
|
||||
img.save(buffer, format="PNG")
|
||||
buffer.seek(0)
|
||||
return buffer
|
||||
|
||||
return await asyncio.to_thread(_generate)
|
||||
|
||||
buffer = await generate_font_preview()
|
||||
await interaction.followup.send(
|
||||
content="Here are all available fonts:",
|
||||
file=discord.File(buffer, "font_preview.png")
|
||||
)
|
||||
|
||||
@app_commands.command(name="setprofile", description="Set your profile information.")
|
||||
@app_commands.describe(
|
||||
@@ -45,16 +104,7 @@ class Profiles(commands.Cog):
|
||||
birthday="Your birthday (MM-DD)",
|
||||
font_name="Font to use (see /listfonts)"
|
||||
)
|
||||
async def setprofile(self, interaction: discord.Interaction,
|
||||
pronouns: str = None,
|
||||
about_me: str = None,
|
||||
fav_color: str = None,
|
||||
bg_color: str = None,
|
||||
fav_game: str = None,
|
||||
fav_artist: str = None,
|
||||
birthday: str = None,
|
||||
font_name: str = None):
|
||||
|
||||
async def setprofile(self, interaction: discord.Interaction, pronouns: str = None, about_me: str = None, fav_color: str = None, bg_color: str = None, fav_game: str = None, fav_artist: str = None, birthday: str = None, font_name: str = None):
|
||||
# Defer the response to show "thinking"
|
||||
await interaction.response.defer(thinking=True)
|
||||
|
||||
@@ -76,7 +126,7 @@ class Profiles(commands.Cog):
|
||||
|
||||
db = get_db()
|
||||
cursor = db.cursor()
|
||||
|
||||
|
||||
# Build update query dynamically to only update provided fields
|
||||
update_fields = []
|
||||
values = []
|
||||
@@ -126,10 +176,10 @@ class Profiles(commands.Cog):
|
||||
placeholders = ["?"] * len(fields)
|
||||
query = f"INSERT INTO profiles ({', '.join(fields)}) VALUES ({', '.join(placeholders)})"
|
||||
cursor.execute(query, [interaction.user.id] + values)
|
||||
|
||||
|
||||
db.commit()
|
||||
db.close()
|
||||
|
||||
|
||||
await interaction.followup.send("Your profile has been saved!")
|
||||
|
||||
@app_commands.command(name="profile", description="View your or another user's profile.")
|
||||
@@ -138,22 +188,22 @@ class Profiles(commands.Cog):
|
||||
await interaction.response.defer(thinking=True)
|
||||
|
||||
member = member or interaction.user
|
||||
|
||||
|
||||
db = get_db()
|
||||
cursor = db.cursor()
|
||||
cursor.execute("SELECT * FROM profiles WHERE user_id=?", (member.id,))
|
||||
row = cursor.fetchone()
|
||||
db.close()
|
||||
|
||||
|
||||
if not row:
|
||||
await interaction.followup.send("This user hasn't set up a profile yet. Use /setprofile to add information to your profile")
|
||||
return
|
||||
|
||||
_, pronouns, about_me, fav_color, bg_color, fav_game, fav_artist, birthday, font_name = row
|
||||
|
||||
|
||||
avatar_asset = member.display_avatar.with_size(256)
|
||||
avatar_bytes = await avatar_asset.read()
|
||||
|
||||
|
||||
def generate_image():
|
||||
try:
|
||||
if font_name:
|
||||
@@ -181,7 +231,7 @@ class Profiles(commands.Cog):
|
||||
font = ImageFont.load_default()
|
||||
font_bold = ImageFont.load_default()
|
||||
font_label = ImageFont.load_default()
|
||||
|
||||
|
||||
img_width, img_height = 1000, 550
|
||||
|
||||
# Parse background color - only accept hex with #
|
||||
@@ -205,7 +255,7 @@ class Profiles(commands.Cog):
|
||||
radius=20,
|
||||
fill=(40, 45, 52, 200)
|
||||
)
|
||||
|
||||
|
||||
# Avatar setup - centered in left panel
|
||||
avatar_size = 200
|
||||
panel_center = panel_left_x + panel_left_width // 2
|
||||
@@ -215,23 +265,21 @@ class Profiles(commands.Cog):
|
||||
# Draw glowing border around avatar
|
||||
for offset in range(3):
|
||||
draw.rounded_rectangle(
|
||||
[(avatar_x - 6 - offset, avatar_y - 6 - offset),
|
||||
[(avatar_x - 6 - offset, avatar_y - 6 - offset),
|
||||
(avatar_x + avatar_size + 6 + offset, avatar_y + avatar_size + 6 + offset)],
|
||||
radius=15,
|
||||
outline=(88, 101, 242, 100 - offset * 30),
|
||||
width=2
|
||||
)
|
||||
|
||||
|
||||
# Paste avatar with rounded corners
|
||||
avatar = Image.open(io.BytesIO(avatar_bytes)).convert("RGBA")
|
||||
avatar = avatar.resize((avatar_size, avatar_size))
|
||||
|
||||
mask = Image.new('L', (avatar_size, avatar_size), 0)
|
||||
mask_draw = ImageDraw.Draw(mask)
|
||||
mask_draw.rounded_rectangle([(0, 0), (avatar_size, avatar_size)], radius=12, fill=255)
|
||||
|
||||
img.paste(avatar, (avatar_x, avatar_y), mask)
|
||||
|
||||
|
||||
# Draw username with shadow effect - centered in panel with dynamic sizing
|
||||
username_y = avatar_y + avatar_size + 25
|
||||
|
||||
@@ -267,34 +315,52 @@ class Profiles(commands.Cog):
|
||||
|
||||
if text_width <= max_username_width:
|
||||
break
|
||||
|
||||
|
||||
username_font_size -= 2
|
||||
|
||||
# Shadow
|
||||
draw.text((panel_center + 2, username_y + 2), member.display_name,
|
||||
fill=(0, 0, 0, 100), font=username_font, anchor="mt")
|
||||
draw.text((panel_center + 2, username_y + 2), member.display_name, fill=(0, 0, 0, 100), font=username_font, anchor="mt")
|
||||
# Main text
|
||||
draw.text((panel_center, username_y), member.display_name,
|
||||
fill="#FFFFFF", font=username_font, anchor="mt")
|
||||
draw.text((panel_center, username_y), member.display_name, fill="#FFFFFF", font=username_font, anchor="mt")
|
||||
|
||||
# Draw pronouns below username if available - centered in panel
|
||||
# Draw pronouns below username if available - centered in panel with wrapping
|
||||
current_y = username_y + 40
|
||||
if pronouns:
|
||||
draw.text((panel_center, current_y), pronouns,
|
||||
fill="#B9BBBE", font=font, anchor="mt")
|
||||
current_y += 35
|
||||
# Wrap pronouns text to fit panel width
|
||||
max_pronouns_width = panel_left_width - 20 # Leave some padding
|
||||
words = pronouns.split()
|
||||
line = ""
|
||||
|
||||
for word in words:
|
||||
test_line = f"{line} {word}".strip()
|
||||
bbox = draw.textbbox((0, 0), test_line, font=font)
|
||||
line_width = bbox[2] - bbox[0]
|
||||
|
||||
if line_width <= max_pronouns_width:
|
||||
line = test_line
|
||||
else:
|
||||
if line:
|
||||
draw.text((panel_center, current_y), line, fill="#B9BBBE", font=font, anchor="mt")
|
||||
current_y += 25 # Move to next line
|
||||
line = word
|
||||
|
||||
# Draw any remaining text
|
||||
if line:
|
||||
draw.text((panel_center, current_y), line, fill="#B9BBBE", font=font, anchor="mt")
|
||||
|
||||
current_y += 35 # Space before roles
|
||||
|
||||
# Draw roles below pronouns
|
||||
roles = [role for role in member.roles if role.name != "@everyone"]
|
||||
if roles:
|
||||
# Sort roles by position (highest first, like Discord does)
|
||||
roles.sort(key=lambda r: r.position, reverse=True)
|
||||
|
||||
# Limit to top 5 roles to avoid overflow
|
||||
display_roles = roles[:5]
|
||||
|
||||
role_y = current_y
|
||||
role_font_size = 14
|
||||
|
||||
try:
|
||||
if font_name:
|
||||
font_path_ttf = os.path.join(FONTS_PATH, f"{font_name}.ttf")
|
||||
@@ -317,10 +383,9 @@ class Profiles(commands.Cog):
|
||||
|
||||
# Draw role name centered
|
||||
role_text = f"• {role.name}"
|
||||
draw.text((panel_center, role_y), role_text,
|
||||
fill=role_color, font=role_font, anchor="mt")
|
||||
draw.text((panel_center, role_y), role_text, fill=role_color, font=role_font, anchor="mt")
|
||||
role_y += 22
|
||||
|
||||
|
||||
# Right side panel
|
||||
panel_x = 360
|
||||
panel_y = 50
|
||||
@@ -332,10 +397,10 @@ class Profiles(commands.Cog):
|
||||
radius=20,
|
||||
fill=(40, 45, 52, 150)
|
||||
)
|
||||
|
||||
|
||||
line_spacing = 50
|
||||
max_text_width = panel_width - 60
|
||||
|
||||
|
||||
fields = [
|
||||
("Favorite Color", fav_color),
|
||||
("Favorite Game", fav_game),
|
||||
@@ -343,7 +408,7 @@ class Profiles(commands.Cog):
|
||||
("Birthday", birthday),
|
||||
("About Me", about_me)
|
||||
]
|
||||
|
||||
|
||||
for label, value in fields:
|
||||
if value:
|
||||
if label == "About Me":
|
||||
@@ -359,10 +424,12 @@ class Profiles(commands.Cog):
|
||||
words = value.split()
|
||||
line = ""
|
||||
first_line = True
|
||||
|
||||
for word in words:
|
||||
test_line = f"{line} {word}".strip()
|
||||
bbox = draw.textbbox((0, 0), test_line, font=font)
|
||||
line_width = bbox[2] - bbox[0]
|
||||
|
||||
available_width = max_text_width - (label_width if first_line else 0)
|
||||
|
||||
if line_width <= available_width:
|
||||
@@ -374,9 +441,11 @@ class Profiles(commands.Cog):
|
||||
first_line = False
|
||||
value_x = panel_x
|
||||
line = word
|
||||
|
||||
if line:
|
||||
draw.text((value_x if first_line else panel_x, panel_y), line, fill="#FFFFFF", font=font)
|
||||
panel_y += line_spacing
|
||||
|
||||
panel_y += line_spacing
|
||||
else:
|
||||
# Draw label and value on same line
|
||||
draw.text((panel_x, panel_y), f"{label}: ", fill="#7289DA", font=font_label)
|
||||
@@ -387,13 +456,14 @@ class Profiles(commands.Cog):
|
||||
|
||||
# Draw value right after label
|
||||
draw.text((panel_x + label_width, panel_y), str(value), fill="#FFFFFF", font=font)
|
||||
|
||||
panel_y += line_spacing
|
||||
|
||||
|
||||
buffer = io.BytesIO()
|
||||
img.save(buffer, format="PNG")
|
||||
buffer.seek(0)
|
||||
return buffer
|
||||
|
||||
|
||||
buffer = await asyncio.to_thread(generate_image)
|
||||
await interaction.followup.send(file=discord.File(buffer, "profile.png"))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user