Files
smoothschedule/frontend/public/plugin-logos/generate_icons.py
poduck cfc1b36ada feat: Add SMTP settings and collapsible email configuration UI
- Add SMTP fields to TicketEmailSettings model (host, port, TLS/SSL, credentials, from email/name)
- Update serializers with SMTP fields and is_smtp_configured flag
- Add TicketEmailTestSmtpView for testing SMTP connections
- Update frontend API types and hooks for SMTP settings
- Add collapsible IMAP and SMTP configuration sections with "Configured" badges
- Fix TypeScript errors in mockData.ts (missing required fields, type mismatches)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 18:28:29 -05:00

144 lines
6.1 KiB
Python

#!/usr/bin/env python3
"""
Generate plugin icons using Gemini 2.5 Flash Image API.
Based on: https://ai.google.dev/gemini-api/docs/image-generation
"""
from google import genai
from PIL import Image
import os
import time
# API Key
client = genai.Client(api_key="AIzaSyBF3_KnttSerq2BK2CaRKSTJHN8BoXp6Hw")
OUTPUT_DIR = os.path.dirname(os.path.abspath(__file__))
# Plugin configurations with improved prompts
plugins = [
{
'filename': 'daily-appointment-summary.png',
'prompt': '''Generate a professional app icon, 512x512 pixels, square with rounded corners.
Style: Modern gradient background transitioning from deep indigo (#4338ca) to vibrant blue (#3b82f6).
Central element: A stylized white clipboard or document with 3 horizontal lines representing a list, and a small clock or sun symbol in the top right corner indicating "daily".
Design principles: Minimalist, clean lines, no text, suitable for a scheduling/calendar application. The icon should be instantly recognizable as "daily summary" or "daily report" at small sizes like 32x32.'''
},
{
'filename': 'no-show-tracker.png',
'prompt': '''Generate a professional app icon, 512x512 pixels, square with rounded corners.
Style: Modern gradient background from deep red (#b91c1c) to coral red (#ef4444).
Central element: A white calendar or appointment card with a prominent empty circle or "absent" symbol - perhaps a chair silhouette with a question mark, or a clock with a slash through it indicating a missed appointment.
Design principles: Minimalist, clean lines, no text. The icon should clearly communicate "missed" or "no-show" at a glance. Professional warning aesthetic without being alarming.'''
},
{
'filename': 'birthday-greetings.png',
'prompt': '''Generate a professional app icon, 512x512 pixels, square with rounded corners.
Style: Modern gradient background from magenta (#c026d3) to pink (#ec4899).
Central element: A white birthday cake with 2-3 simple candles, or a wrapped gift box with a ribbon bow. Add subtle confetti dots or small stars around it for a celebratory feel.
Design principles: Minimalist, cheerful but professional, clean lines, no text. Should feel warm and celebratory while still fitting a business application aesthetic.'''
},
{
'filename': 'monthly-revenue-report.png',
'prompt': '''Generate a professional app icon, 512x512 pixels, square with rounded corners.
Style: Modern gradient background from emerald green (#059669) to teal (#14b8a6).
Central element: A white line chart showing an upward trend with 3-4 data points connected by lines, or ascending bar chart with dollar sign integrated subtly. The graph should clearly show growth/success.
Design principles: Minimalist, professional finance/analytics aesthetic, clean lines, no text. Should instantly communicate "revenue" and "growth" at small sizes.'''
},
{
'filename': 'appointment-reminder-24hr.png',
'prompt': '''Generate a professional app icon, 512x512 pixels, square with rounded corners.
Style: Modern gradient background from amber (#d97706) to orange (#f97316).
Central element: A white notification bell with a small circular badge, combined with a "24" numeral or a clock face showing time. The bell should be the primary focus with the time element secondary.
Design principles: Minimalist, attention-grabbing but professional, clean lines, no text except possibly "24". Should clearly indicate "reminder" and "advance notice" at small sizes.'''
},
{
'filename': 'inactive-customer-reengagement.png',
'prompt': '''Generate a professional app icon, 512x512 pixels, square with rounded corners.
Style: Modern gradient background from violet (#7c3aed) to purple (#a855f7).
Central element: A white person silhouette or user icon with a curved "return" arrow circling back to them, or a magnet symbol attracting a small person icon. Should convey "bringing customers back".
Design principles: Minimalist, warm and welcoming professional aesthetic, clean lines, no text. Should communicate "re-engagement" or "win back" at a glance.'''
}
]
def generate_logo(prompt: str, filename: str) -> bool:
"""Generate a logo using Gemini 2.5 Flash Image (per official docs)"""
print(f"\nGenerating {filename}...")
try:
# Using the exact format from Google's documentation
response = client.models.generate_content(
model='gemini-2.5-flash-image',
contents=[prompt],
)
# Process response per docs
for part in response.parts:
if part.inline_data is not None:
# Get the raw image data and convert to PIL
from io import BytesIO
image_data = part.inline_data.data
pil_image = Image.open(BytesIO(image_data))
# Resize to 256x256 for consistency
if pil_image.size != (256, 256):
pil_image = pil_image.resize((256, 256), Image.Resampling.LANCZOS)
output_path = os.path.join(OUTPUT_DIR, filename)
pil_image.save(output_path, 'PNG')
print(f" ✓ Saved: {output_path}")
return True
elif part.text is not None:
print(f" Model text: {part.text[:100]}...")
print(" ✗ No image in response")
return False
except Exception as e:
error_msg = str(e)
if "RESOURCE_EXHAUSTED" in error_msg or "quota" in error_msg.lower():
print(f" ✗ Quota exceeded - try again later")
else:
print(f" ✗ Error: {type(e).__name__}: {error_msg[:300]}")
return False
def main():
print("=" * 60)
print("Generating Plugin Icons with Gemini 2.5 Flash Image")
print("=" * 60)
success_count = 0
for i, plugin in enumerate(plugins):
if i > 0:
print("\nWaiting 5 seconds...")
time.sleep(5)
if generate_logo(plugin['prompt'], plugin['filename']):
success_count += 1
print("\n" + "=" * 60)
print(f"Complete: {success_count}/{len(plugins)} icons generated")
print("=" * 60)
if __name__ == "__main__":
main()