diff --git a/scripts/30k-image.py b/scripts/30k-image.py index e69de29bb..e9db4078b 100644 --- a/scripts/30k-image.py +++ b/scripts/30k-image.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python +""" +Generate a celebratory SVG image for Aider reaching 30,000 GitHub stars. +This creates a shareable social media graphic with confetti animation. +""" + +import os +import random +import base64 +import argparse +from pathlib import Path + +# Default colors for the celebration image +AIDER_GREEN = "#14b014" +AIDER_BLUE = "#4C6EF5" +DARK_COLOR = "#212529" +LIGHT_COLOR = "#F8F9FA" +GOLD_COLOR = "#f1c40f" + +# Default dimensions for social sharing +DEFAULT_WIDTH = 1200 +DEFAULT_HEIGHT = 630 + + +def embed_font(): + """Returns base64 encoded font data for the GlassTTYVT220 font.""" + # Path to the font file + font_path = Path(__file__).parent.parent / "aider" / "website" / "assets" / "Glass_TTY_VT220.ttf" + + # If font file doesn't exist, return empty string + if not font_path.exists(): + print(f"Warning: Font file not found at {font_path}") + return "" + + # Read and encode the font file + with open(font_path, "rb") as f: + font_data = f.read() + + # Return base64 encoded font data + return base64.b64encode(font_data).decode('utf-8') + + +def generate_confetti(count=150, width=DEFAULT_WIDTH, height=DEFAULT_HEIGHT): + """Generate SVG confetti elements for the celebration.""" + confetti = [] + colors = [AIDER_GREEN, AIDER_BLUE, GOLD_COLOR, "#e74c3c", "#9b59b6", "#3498db", "#2ecc71"] + + for i in range(count): + x = random.randint(0, width) + y = random.randint(0, height) + size = random.randint(5, 15) + color = random.choice(colors) + rotation = random.randint(0, 360) + delay = random.uniform(0, 2) + duration = random.uniform(1, 3) + + # Randomly choose between rect (square), circle, and star shapes + shape_type = random.choice(["rect", "circle", "star"]) + + if shape_type == "rect": + shape = f""" + + + """ + elif shape_type == "circle": + shape = f""" + + + """ + else: # star + # Create a simple 5-point star + points = [] + for j in range(5): + angle = j * 2 * 3.14159 / 5 + x_point = x + (size * 0.5) * math.cos(angle) + y_point = y + (size * 0.5) * math.sin(angle) + points.append(f"{x_point},{y_point}") + + # Inner points of the star + inner_angle = angle + 3.14159 / 5 + inner_x = x + (size * 0.2) * math.cos(inner_angle) + inner_y = y + (size * 0.2) * math.sin(inner_angle) + points.append(f"{inner_x},{inner_y}") + + points_str = " ".join(points) + shape = f""" + + + + """ + + confetti.append(shape) + + return "\n".join(confetti) + + +def generate_celebration_svg(output_path=None, width=DEFAULT_WIDTH, height=DEFAULT_HEIGHT): + """Generate a celebratory SVG for 30K GitHub stars.""" + # Import math here to avoid the error in generate_confetti + import math + + # Font embedding + font_data = embed_font() + font_face = f""" + @font-face {{ + font-family: 'GlassTTYVT220'; + src: url(data:font/truetype;charset=utf-8;base64,{font_data}) format('truetype'); + font-weight: normal; + font-style: normal; + }} + """ if font_data else "" + + # Generate confetti elements + confetti = generate_confetti(count=150, width=width, height=height) + + # Create the SVG content + svg_content = f""" + + + + + + + + + + + + + + + + + + + + + + + + + + + + {confetti} + + + + 30,000 STARS + Thank you to our amazing community! + github.com/Aider-AI/aider + + + + + + + + + + + + + + +""" + + # Write to file if output path is specified + if output_path: + with open(output_path, 'w') as f: + f.write(svg_content) + print(f"Celebration SVG saved to {output_path}") + + return svg_content + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Generate a celebration SVG for Aider's 30K GitHub stars") + parser.add_argument('--output', '-o', type=str, default="aider-30k-stars.svg", + help="Output file path (default: aider-30k-stars.svg)") + parser.add_argument('--width', '-w', type=int, default=DEFAULT_WIDTH, + help=f"Image width in pixels (default: {DEFAULT_WIDTH})") + parser.add_argument('--height', '-ht', type=int, default=DEFAULT_HEIGHT, + help=f"Image height in pixels (default: {DEFAULT_HEIGHT})") + args = parser.parse_args() + + # Generate the SVG + generate_celebration_svg(args.output, args.width, args.height)