/ca89e3d6bf40dfce26
Created 7 months ago...
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
FONTS_DIR = "fonts"
QUOTE_FONT = os.path.join(FONTS_DIR, "NudMotoya Maru W55 W2b.tff")
AUTHOR_NAME_FONT = os.path.join(FONTS_DIR, "Lato-LightItalic")
AUTHOR_USERNAME_FONT = os.path.join(FONTS_DIR, "Muller Narrow Light")
FOOTER_FONT = os.path.join(FONTS_DIR, "NudMotoya Maru W55 W2b.tff")
QUOTE_FONT_SIZE = 120
AUTHOR_NAME_FONT_SIZE = 45
AUTHOR_USERNAME_FONT_SIZE = 35
FOOTER_FONT_SIZE = 18
IMAGE_WIDTH = 800
IMAGE_HEIGHT = 450
PFP_SIZE = (400, 450)
FOOTER_TEXT = "LTC"
async def create_gradient_overlay(width, height):
overlay = Image.new("RGBA", (width, height), (0, 0, 0, 0))
draw = ImageDraw.Draw(overlay)
for x in range(width):
alpha = int(255 * (x / width))
draw.line([(x, 0), (x, height)], fill=(0, 0, 0, alpha))
return overlay
async def wrap_text(text, font, max_width):
words = text.split()
lines = []
current_line = []
for word in words:
current_line.append(word)
text_width = font.getbbox(' '.join(current_line))[2]
if text_width > max_width:
if len(current_line) == 1:
lines.append(current_line[0])
current_line = []
else:
current_line.pop()
lines.append(' '.join(current_line))
current_line = [word]
if current_line:
lines.append(' '.join(current_line))
return '\n'.join(lines)
async def fetch_avatar(avatar_url):
async with aiohttp.ClientSession() as session:
async with session.get(avatar_url) as response:
return await response.read()
async def generate_quote_image(text, display_name, username, avatar_url):
image = Image.new("RGBA", (IMAGE_WIDTH, IMAGE_HEIGHT), "black")
avatar_data = await fetch_avatar(avatar_url)
avatar = Image.open(BytesIO(avatar_data)).convert("L")
avatar = avatar.resize(PFP_SIZE, Image.Resampling.LANCZOS)
image.paste(avatar, (0, 0))
gradient = await create_gradient_overlay(*PFP_SIZE)
image.paste(gradient, (0, 0), gradient)
draw = ImageDraw.Draw(image)
try:
font_quote = ImageFont.truetype(QUOTE_FONT, QUOTE_FONT_SIZE)
font_author = ImageFont.truetype(AUTHOR_NAME_FONT, AUTHOR_NAME_FONT_SIZE)
font_username = ImageFont.truetype(AUTHOR_USERNAME_FONT, AUTHOR_USERNAME_FONT_SIZE)
font_footer = ImageFont.truetype(FOOTER_FONT, FOOTER_FONT_SIZE)
except OSError:
font_quote = ImageFont.load_default()
font_author = ImageFont.load_default()
font_username = ImageFont.load_default()
font_footer = ImageFont.load_default()
quote_x = 450
quote_y = IMAGE_HEIGHT // 2 - 150
max_width = IMAGE_WIDTH - quote_x - 50
wrapped_text = await wrap_text(text, font_quote, max_width)
draw.text((quote_x, quote_y), wrapped_text, fill="white", font=font_quote)
author_y = quote_y + 120
draw.text((quote_x, author_y), f"- {display_name}", fill="white", font=font_author)
username_y = author_y + 50
draw.text((quote_x, username_y), f"@{username}", fill="rgba(255,255,255,180)", font=font_username)
footer_x = IMAGE_WIDTH - 20
footer_y = IMAGE_HEIGHT - 20
draw.text((footer_x, footer_y), FOOTER_TEXT, fill="white", font=font_footer, anchor="rb")
return image
@bot.command()
async def quote(ctx):
if not ctx.message.reference:
await ctx.send("Please reply to a message to generate a quote.")
return
replied_message = await ctx.channel.fetch_message(ctx.message.reference.message_id)
text = replied_message.content
author = replied_message.author
avatar_url = author.avatar.url if author.avatar else author.default_avatar.url
image = await generate_quote_image(text, author.display_name, author.name, avatar_url)
buffer = BytesIO()
image.save(buffer, format="PNG")
buffer.seek(0)
await ctx.send(file=discord.File(buffer, "quote.png"))