import os import uuid from flask import Flask, request, send_file from PIL import Image, ImageDraw, ImageFont app = Flask(__name__) # Ensure temp directory exists TEMP_DIR = "temp" os.makedirs(TEMP_DIR, exist_ok=True) # Available images PFP_OPTIONS = {str(i): f"pfp{i}.png" for i in range(1, 6)} BG_OPTIONS = {str(i): f"bg{i}.png" for i in range(1, 4)} # Load fonts safely def load_font(font_path, size): try: return ImageFont.truetype(font_path, size) except IOError: return ImageFont.load_default() @app.route('/api') def generate_profile(): """ Generate a profile card with user details and a chosen profile picture & background. """ # 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_choice = request.args.get('pfp', '1') bg_choice = request.args.get('bg', '1') # Validate and load background bg_path = BG_OPTIONS.get(bg_choice, "bg1.png") if not os.path.exists(bg_path): return f"Error: Background '{bg_choice}' not found.", 400 bg = Image.open(bg_path).convert("RGBA") 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 pfp_y = 80 # Adjusted to align better # Validate and load profile picture pfp_path = PFP_OPTIONS.get(pfp_choice, "pfp1.png") if not os.path.exists(pfp_path): return f"Error: Profile picture '{pfp_choice}' not found.", 400 pfp = Image.open(pfp_path).convert("RGBA") # Resize and mask the profile picture (circular crop) pfp = pfp.resize((pfp_size, pfp_size), Image.LANCZOS) mask = Image.new("L", (pfp_size, pfp_size), 0) mask_draw = ImageDraw.Draw(mask) mask_draw.ellipse((0, 0, pfp_size, pfp_size), fill=255) # Create a circular profile picture circular_pfp = Image.new("RGBA", (pfp_size, pfp_size), (0, 0, 0, 0)) circular_pfp.paste(pfp, (0, 0), mask) # Create a white border border_size = 10 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(circular_pfp, (border_size // 2, border_size // 2), mask) # Paste profile picture onto background bg.paste(border, (pfp_x - border_size // 2, pfp_y - border_size // 2), border_mask) # **TEXT POSITIONING** name_x = pfp_x + pfp_size + 40 # Name beside profile picture name_y = pfp_y + (pfp_size // 3) # Align vertically with profile picture text_color = (255, 255, 255) # Function to resize text dynamically 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 max_text_width = W - name_x - 50 name_font = fit_text(name, max_text_width, font_large) # **Draw name beside profile picture** draw.text((name_x, name_y), name, font=name_font, fill=text_color) # **Other details BELOW profile picture** info_x = pfp_x info_y = pfp_y + pfp_size + 70 # Below the profile picture text_spacing = 45 # Space between text lines draw.text((info_x, info_y), f"Rank: {rank}", font=font_medium, fill=text_color) draw.text((info_x, info_y + text_spacing), f"Balance: {balance}", font=font_medium, fill=text_color) draw.text((info_x, info_y + 2 * 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 image response = send_file(output_path, mimetype='image/png') # Cleanup saved files if os.path.exists(output_path): os.remove(output_path) return response if __name__ == '__main__': app.run(host='0.0.0.0', port=7860, debug=True)