diff --git a/tools/setup/generate_integration_bots_avatars.py b/tools/setup/generate_integration_bots_avatars.py old mode 100644 new mode 100755 index c31a3903cd..4167d07f8b --- a/tools/setup/generate_integration_bots_avatars.py +++ b/tools/setup/generate_integration_bots_avatars.py @@ -2,8 +2,6 @@ import os import sys -import tempfile -from typing import Optional ZULIP_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) if ZULIP_PATH not in sys.path: @@ -11,7 +9,21 @@ if ZULIP_PATH not in sys.path: from scripts.lib.setup_path import setup_path setup_path() +os.environ["DJANGO_SETTINGS_MODULE"] = "zproject.settings" +import django + +django.setup() + +import tempfile +from typing import Optional + +import io import cairosvg +from PIL import Image + +from zerver.lib.upload import resize_avatar, DEFAULT_AVATAR_SIZE +from zerver.lib.integrations import Integration, WEBHOOK_INTEGRATIONS +from zerver.lib.storage import static_path def create_png_from_svg(svg_path: str, destination_dir: Optional[str]=None) -> str: png_name = os.path.splitext(os.path.basename(svg_path))[0] + '.png' @@ -20,3 +32,44 @@ def create_png_from_svg(svg_path: str, destination_dir: Optional[str]=None) -> s png_path = os.path.join(destination_dir, png_name) cairosvg.svg2png(url=svg_path, write_to=png_path) return png_path + +def create_square_image(png: bytes) -> bytes: + img = Image.open(io.BytesIO(png)) + if img.height == img.width: + return png + + size = max(img.height, img.width) + new_img = Image.new("RGBA", (size, size), color=None) + padding = int(abs(img.height - img.width) / 2) + position = (0, padding) if img.height < img.width else (padding, 0) + new_img.paste(img, position) + out = io.BytesIO() + new_img.save(out, format='png') + return out.getvalue() + +def create_integration_bot_avatar(logo_path: str) -> None: + if logo_path.endswith('.svg'): + avatar = cairosvg.svg2png( + url=logo_path, output_width=DEFAULT_AVATAR_SIZE, output_height=DEFAULT_AVATAR_SIZE) + else: + with open(logo_path, 'rb') as f: + image = f.read() + square_image = create_square_image(image) + avatar = resize_avatar(square_image) + + name = os.path.splitext(os.path.basename(logo_path))[0] + bot_avatar_path = os.path.join( + ZULIP_PATH, 'static', Integration.DEFAULT_BOT_AVATAR_PATH.format(name=name)) + os.makedirs(os.path.dirname(bot_avatar_path), exist_ok=True) + with open(bot_avatar_path, 'wb') as f: + f.write(avatar) + +def generate_integration_bots_avatars() -> None: + for webhook in WEBHOOK_INTEGRATIONS: + logo_path = webhook.get_logo_path() + if not logo_path: + continue + create_integration_bot_avatar(static_path(logo_path)) + +if __name__ == '__main__': + generate_integration_bots_avatars() diff --git a/zerver/lib/integrations.py b/zerver/lib/integrations.py index c931b856a0..2a60f25832 100644 --- a/zerver/lib/integrations.py +++ b/zerver/lib/integrations.py @@ -49,6 +49,7 @@ CATEGORIES: Dict[str, str] = { class Integration: DEFAULT_LOGO_STATIC_PATH_PNG = 'images/integrations/logos/{name}.png' DEFAULT_LOGO_STATIC_PATH_SVG = 'images/integrations/logos/{name}.svg' + DEFAULT_BOT_AVATAR_PATH = 'images/integrations/bot_avatars/{name}.png' def __init__(self, name: str, client_name: str, categories: List[str], logo: Optional[str]=None, secondary_line_text: Optional[str]=None,