mirror of
https://github.com/kemayo/leech
synced 2025-12-15 12:56:41 +01:00
107 lines
3.3 KiB
Python
107 lines
3.3 KiB
Python
# Basically the same as cover.py with some minor differences
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
from io import BytesIO
|
|
import textwrap
|
|
import requests
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def make_image(
|
|
message: str,
|
|
width=600,
|
|
height=300,
|
|
fontname="Helvetica",
|
|
font_size=40,
|
|
bg_color=(0, 0, 0),
|
|
textcolor=(255, 255, 255),
|
|
wrap_at=30
|
|
):
|
|
"""
|
|
This function should only be called if get_image_from_url() fails
|
|
"""
|
|
img = Image.new("RGBA", (width, height), bg_color)
|
|
draw = ImageDraw.Draw(img)
|
|
|
|
message = textwrap.fill(message, wrap_at)
|
|
|
|
font = _safe_font(fontname, size=font_size)
|
|
message_size = draw.textsize(message, font=font)
|
|
draw_text_outlined(
|
|
draw, ((width - message_size[0]) / 2, 100), message, textcolor, font=font)
|
|
# draw.text(((width - title_size[0]) / 2, 100), title, textcolor, font=font)
|
|
|
|
output = BytesIO()
|
|
img.save(output, "PNG")
|
|
output.name = 'cover.png'
|
|
# writing left the cursor at the end of the file, so reset it
|
|
output.seek(0)
|
|
return output
|
|
|
|
|
|
def get_image_from_url(url: str):
|
|
"""
|
|
Basically the same as make_cover_from_url()
|
|
"""
|
|
try:
|
|
if url.startswith("https://www.filepicker.io/api/"):
|
|
logger.warning("Filepicker.io image detected, converting to Fiction.live image. This might fail.")
|
|
url = f"https://cdn3.fiction.live/fp/{url.split('/')[-1]}?&quality=95"
|
|
img = requests.Session().get(url)
|
|
logger.info("Downloading image from " + url)
|
|
cover = BytesIO(img.content)
|
|
|
|
img_format = Image.open(cover).format
|
|
# The `Image.open` read a few bytes from the stream to work out the
|
|
# format, so reset it:
|
|
cover.seek(0)
|
|
|
|
if img_format != "PNG":
|
|
cover = _convert_to_png(cover)
|
|
except Exception as e:
|
|
logger.info("Encountered an error downloading cover: " + str(e))
|
|
cover = make_image("There was a problem downloading this image.")
|
|
|
|
return cover
|
|
|
|
|
|
def _convert_to_png(image_bytestream):
|
|
png_image = BytesIO()
|
|
Image.open(image_bytestream).save(png_image, format="PNG")
|
|
png_image.name = 'cover.png'
|
|
png_image.seek(0)
|
|
|
|
return png_image
|
|
|
|
|
|
def _safe_font(preferred, *args, **kwargs):
|
|
for font in (preferred, "Helvetica", "FreeSans", "Arial"):
|
|
try:
|
|
return ImageFont.truetype(*args, font=font, **kwargs)
|
|
except IOError:
|
|
pass
|
|
|
|
# This is pretty terrible, but it'll work regardless of what fonts the
|
|
# system has. Worst issue: can't set the size.
|
|
return ImageFont.load_default()
|
|
|
|
|
|
def draw_text_outlined(draw, xy, text, fill=None, font=None, anchor=None):
|
|
x, y = xy
|
|
|
|
# Outline
|
|
draw.text((x - 1, y), text=text, fill=(0, 0, 0), font=font, anchor=anchor)
|
|
draw.text((x + 1, y), text=text, fill=(0, 0, 0), font=font, anchor=anchor)
|
|
draw.text((x, y - 1), text=text, fill=(0, 0, 0), font=font, anchor=anchor)
|
|
draw.text((x, y + 1), text=text, fill=(0, 0, 0), font=font, anchor=anchor)
|
|
|
|
# Fill
|
|
draw.text(xy, text=text, fill=fill, font=font, anchor=anchor)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
f = make_image(
|
|
'Test of a Title which is quite long and will require multiple lines')
|
|
with open('output.png', 'wb') as out:
|
|
out.write(f.read())
|