import os import uuid import requests from flask import Flask, request, send_file from PIL import Image, ImageDraw, ImageFont from io import BytesIO app = Flask(__name__) # Ensure temp directory exists TEMP_DIR = "temp" os.makedirs(TEMP_DIR, exist_ok=True) def load_font(font_path, size): """Load a font or fallback to default Arial.""" try: return ImageFont.truetype(font_path, size) except IOError: return ImageFont.truetype("arial.ttf", size) @app.route('/api') def generate_profile(): # Get query parameters name = request.args.get('name', 'Unknown') rank = request.args.get('rank', 'Unranked') balance = request.args.get('balance', '0') next_rank = request.args.get('next_rank', 'Unknown') pfp_url = request.args.get('pfp', None) # Load background image try: bg = Image.open("bg.png").convert("RGBA") # Ensure transparency support except IOError: return "Error: Background image 'bg.png' not found.", 500 draw = ImageDraw.Draw(bg) W, H = bg.size # Get background dimensions # Load fonts font_large = load_font("font.ttf", 45) # Name font_medium = load_font("font.ttf", 35) # Rank, Balance font_small = load_font("font.ttf", 30) # Next Rank # Profile picture settings pfp_size = 170 pfp_x = 50 # Align profile picture to the left pfp_y = 50 pfp_path = os.path.join(TEMP_DIR, f"pfp_{uuid.uuid4().hex}.png") # Load profile picture try: if pfp_url: response = requests.get(pfp_url, timeout=5) if response.status_code == 200: pfp = Image.open(BytesIO(response.content)).convert("RGBA") else: raise ValueError("Invalid profile picture URL") else: pfp = Image.open("fallback.png").convert("RGBA") # Resize profile picture pfp = pfp.resize((pfp_size, pfp_size), Image.LANCZOS) # Create circular mask mask = Image.new("L", (pfp_size, pfp_size), 0) draw_mask = ImageDraw.Draw(mask) draw_mask.ellipse((0, 0, pfp_size, pfp_size), fill=255) # Create a white border border_size = 8 border = Image.new("RGBA", (pfp_size + border_size, pfp_size + border_size), (255, 255, 255, 255)) border_mask = Image.new("L", (pfp_size + border_size, pfp_size + border_size), 0) border_draw = ImageDraw.Draw(border_mask) border_draw.ellipse((0, 0, pfp_size + border_size, pfp_size + border_size), fill=255) border.paste(pfp, (border_size // 2, border_size // 2), mask) # Paste profile picture with border bg.paste(border, (pfp_x - border_size // 2, pfp_y - border_size // 2), border_mask) except Exception as e: print(f"Error loading profile picture: {e}") # Define text positions text_x = pfp_x + pfp_size + 30 # Start text next to profile picture text_y_start = pfp_y + 30 text_spacing = 60 text_color = (255, 255, 255) # Function to handle text resizing for long names def fit_text(text, max_width, base_font): font = base_font while draw.textlength(text, font=font) > max_width and font.size > 20: font = load_font("font.ttf", font.size - 2) return font # Adjust name font size dynamically name_font = fit_text(name, W - text_x - 50, font_large) # Draw aligned text draw.text((text_x, text_y_start), name, font=name_font, fill=text_color) draw.text((text_x, text_y_start + text_spacing), f"Rank: {rank}", font=font_medium, fill=text_color) draw.text((text_x, text_y_start + 2 * text_spacing), f"Balance: {balance}", font=font_medium, fill=text_color) draw.text((text_x, text_y_start + 3 * text_spacing), f"Next Rank: {next_rank}", font=font_small, fill=text_color) # Save final image output_path = os.path.join(TEMP_DIR, f"profile_{uuid.uuid4().hex}.png") bg.save(output_path) # Send and delete image response = send_file(output_path, mimetype='image/png') # Cleanup saved files if os.path.exists(output_path): os.remove(output_path) if os.path.exists(pfp_path): os.remove(pfp_path) return response if __name__ == '__main__': app.run(host='0.0.0.0', port=7860, debug=True)