- 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>
200 lines
6.3 KiB
Python
200 lines
6.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Generate plugin icons using Google Gemini API.
|
|
|
|
Usage:
|
|
export GOOGLE_API_KEY="your-api-key"
|
|
python generate_plugin_icons.py
|
|
|
|
The icons will be saved to smoothschedule/static/plugin-logos/
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# Check for API key first
|
|
GOOGLE_API_KEY = os.environ.get('GOOGLE_API_KEY')
|
|
if not GOOGLE_API_KEY:
|
|
print("Error: GOOGLE_API_KEY environment variable not set")
|
|
print("Get your API key from: https://aistudio.google.com/app/apikey")
|
|
sys.exit(1)
|
|
|
|
try:
|
|
from google import genai
|
|
from google.genai import types
|
|
except ImportError:
|
|
print("Error: google-genai package not installed")
|
|
print("Install with: pip install google-genai")
|
|
sys.exit(1)
|
|
|
|
try:
|
|
from PIL import Image
|
|
except ImportError:
|
|
print("Error: Pillow package not installed")
|
|
print("Install with: pip install Pillow")
|
|
sys.exit(1)
|
|
|
|
|
|
# Plugin definitions with icon generation prompts
|
|
PLUGINS = [
|
|
{
|
|
'slug': 'daily-appointment-summary',
|
|
'name': 'Daily Appointment Summary Email',
|
|
'prompt': '''Create a minimalist, modern app icon for a "Daily Appointment Summary" plugin.
|
|
The icon should feature:
|
|
- A calendar or schedule symbol with check marks
|
|
- An email envelope element
|
|
- Clean, flat design style
|
|
- Purple/blue gradient color scheme
|
|
- Professional business aesthetic
|
|
- Square format with rounded corners
|
|
- No text, pure iconography
|
|
Size: 256x256 pixels, suitable for app store or dashboard display.'''
|
|
},
|
|
{
|
|
'slug': 'no-show-tracker',
|
|
'name': 'No-Show Customer Tracker',
|
|
'prompt': '''Create a minimalist, modern app icon for a "No-Show Tracker" plugin.
|
|
The icon should feature:
|
|
- A calendar with an X mark or empty chair symbol
|
|
- Alert/warning element
|
|
- Clean, flat design style
|
|
- Orange/red accent colors with neutral background
|
|
- Professional business aesthetic
|
|
- Square format with rounded corners
|
|
- No text, pure iconography
|
|
Size: 256x256 pixels, suitable for app store or dashboard display.'''
|
|
},
|
|
{
|
|
'slug': 'birthday-greetings',
|
|
'name': 'Birthday Greeting Campaign',
|
|
'prompt': '''Create a minimalist, modern app icon for a "Birthday Greetings" plugin.
|
|
The icon should feature:
|
|
- A birthday cake or gift box symbol
|
|
- A small heart or celebration element
|
|
- Clean, flat design style
|
|
- Pink/magenta warm color scheme
|
|
- Friendly, celebratory aesthetic
|
|
- Square format with rounded corners
|
|
- No text, pure iconography
|
|
Size: 256x256 pixels, suitable for app store or dashboard display.'''
|
|
},
|
|
{
|
|
'slug': 'monthly-revenue-report',
|
|
'name': 'Monthly Revenue Report',
|
|
'prompt': '''Create a minimalist, modern app icon for a "Monthly Revenue Report" plugin.
|
|
The icon should feature:
|
|
- A bar chart or line graph going upward
|
|
- A dollar sign or currency symbol
|
|
- Clean, flat design style
|
|
- Green money-themed color scheme
|
|
- Professional business/finance aesthetic
|
|
- Square format with rounded corners
|
|
- No text, pure iconography
|
|
Size: 256x256 pixels, suitable for app store or dashboard display.'''
|
|
},
|
|
{
|
|
'slug': 'appointment-reminder-24hr',
|
|
'name': 'Appointment Reminder (24hr)',
|
|
'prompt': '''Create a minimalist, modern app icon for an "Appointment Reminder" plugin.
|
|
The icon should feature:
|
|
- A bell or notification symbol
|
|
- A clock showing 24 hours or time element
|
|
- Clean, flat design style
|
|
- Blue/teal professional color scheme
|
|
- Urgent but friendly aesthetic
|
|
- Square format with rounded corners
|
|
- No text, pure iconography
|
|
Size: 256x256 pixels, suitable for app store or dashboard display.'''
|
|
},
|
|
{
|
|
'slug': 'inactive-customer-reengagement',
|
|
'name': 'Inactive Customer Re-engagement',
|
|
'prompt': '''Create a minimalist, modern app icon for a "Customer Re-engagement" plugin.
|
|
The icon should feature:
|
|
- A person silhouette with a returning arrow
|
|
- A magnet or heart symbol for attraction
|
|
- Clean, flat design style
|
|
- Warm orange/coral color scheme
|
|
- Welcoming, inviting aesthetic
|
|
- Square format with rounded corners
|
|
- No text, pure iconography
|
|
Size: 256x256 pixels, suitable for app store or dashboard display.'''
|
|
},
|
|
]
|
|
|
|
|
|
def generate_icon(client, plugin: dict, output_dir: Path) -> bool:
|
|
"""Generate an icon for a single plugin."""
|
|
slug = plugin['slug']
|
|
name = plugin['name']
|
|
prompt = plugin['prompt']
|
|
|
|
output_path = output_dir / f"{slug}.png"
|
|
|
|
print(f"\nGenerating icon for: {name}")
|
|
print(f" Output: {output_path}")
|
|
|
|
try:
|
|
response = client.models.generate_content(
|
|
model="gemini-2.5-flash-image",
|
|
contents=[prompt],
|
|
)
|
|
|
|
# Extract and save image from response
|
|
for part in response.parts:
|
|
if part.inline_data is not None:
|
|
image = part.as_image()
|
|
|
|
# Resize to 256x256 if needed
|
|
if image.size != (256, 256):
|
|
image = image.resize((256, 256), Image.Resampling.LANCZOS)
|
|
|
|
image.save(output_path, "PNG")
|
|
print(f" Success! Saved to {output_path}")
|
|
return True
|
|
elif part.text is not None:
|
|
print(f" Model response: {part.text[:200]}...")
|
|
|
|
print(f" Warning: No image generated for {name}")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f" Error generating icon for {name}: {e}")
|
|
return False
|
|
|
|
|
|
def main():
|
|
# Setup output directory
|
|
script_dir = Path(__file__).parent
|
|
project_root = script_dir.parent
|
|
output_dir = project_root / "static" / "plugin-logos"
|
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
print(f"Output directory: {output_dir}")
|
|
print(f"Generating {len(PLUGINS)} plugin icons using Gemini API...")
|
|
|
|
# Initialize Gemini client
|
|
client = genai.Client(api_key=GOOGLE_API_KEY)
|
|
|
|
# Generate icons
|
|
success_count = 0
|
|
for plugin in PLUGINS:
|
|
if generate_icon(client, plugin, output_dir):
|
|
success_count += 1
|
|
|
|
print(f"\n{'='*50}")
|
|
print(f"Generated {success_count}/{len(PLUGINS)} icons successfully")
|
|
print(f"Icons saved to: {output_dir}")
|
|
|
|
if success_count > 0:
|
|
print("\nNext steps:")
|
|
print("1. Review the generated icons")
|
|
print("2. Update the plugin logo_url paths in seed_platform_plugins.py")
|
|
print("3. Configure Django static files to serve from /static/plugin-logos/")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|