diff --git a/generate_favicons.py b/generate_favicons.py new file mode 100644 index 0000000..8ada5e7 --- /dev/null +++ b/generate_favicons.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +"""Generate favicons for calls24 landing page.""" + +from PIL import Image, ImageDraw, ImageFont +import os + +COLOR_ACCENT = "#22c55e" +COLOR_WHITE = "#ffffff" +COLOR_DARK = "#0a0a0a" +COLOR_GREEN_LIGHT = "#86efac" + +OUTPUT_DIR = os.path.dirname(os.path.abspath(__file__)) +LOGOS_DIR = os.path.join(OUTPUT_DIR, "logos") + +def create_gradient_bg(img, size, color1=COLOR_DARK, color2="#111111"): + """Create dark gradient background.""" + for y in range(size): + ratio = y / size + r = int(color1[1:3], 16) + int((int(color2[1:3], 16) - int(color1[1:3], 16)) * ratio) + g = int(color1[3:5], 16) + int((int(color2[3:5], 16) - int(color1[3:5], 16)) * ratio) + b = int(color1[5:7], 16) + int((int(color2[5:7], 16) - int(color1[5:7], 16)) * ratio) + draw = ImageDraw.Draw(img) + draw.line([(0, y), (size, y)], fill=f"#{r:02x}{g:02x}{b:02x}") + +def draw_wave_icon(draw, cx, cy, size, color=COLOR_ACCENT, width=0.6): + """Draw the signature wave icon (bar chart style).""" + bar_w = size // 9 + gap = size // 12 + max_h = int(size * width) + heights = [0.35, 0.65, 1.0, 0.65, 0.35] # Wave shape + + total_w = len(heights) * bar_w + (len(heights) - 1) * gap + start_x = cx - total_w // 2 + + for i, h_ratio in enumerate(heights): + x = start_x + i * (bar_w + gap) + h = int(max_h * h_ratio) + y = cy - h // 2 + + # Semi-transparent bars + alpha = int(255 * (0.3 + 0.7 * h_ratio / 1.0)) + rgb = tuple(int(COLOR_ACCENT[i:i+2], 16) for i in (1, 3, 5)) + fill_color = f"#{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}{alpha:02x}" + draw.rectangle([x, y, x + bar_w - 1, y + h], fill=fill_color) + +def draw_wave_with_dot(draw, cx, cy, size, color=COLOR_ACCENT): + """Draw wave icon with accent dot (center bar top).""" + bar_w = size // 9 + gap = size // 12 + max_h = int(size * 0.6) + heights = [0.35, 0.65, 1.0, 0.65, 0.35] + + total_w = len(heights) * bar_w + (len(heights) - 1) * gap + start_x = cx - total_w // 2 + + # Draw bars + for i, h_ratio in enumerate(heights): + x = start_x + i * (bar_w + gap) + h = int(max_h * h_ratio) + y = cy - h // 2 + + if i == 2: # Center bar - full color + draw.rectangle([x, y, x + bar_w - 1, y + h], fill=color) + else: + alpha = int(255 * (0.3 + 0.7 * h_ratio)) + rgb = tuple(int(color[ii:ii+2], 16) for ii in (1, 3, 5)) + draw.rectangle([x, y, x + bar_w - 1, y + h], + fill=f"#{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}{alpha:02x}") + + # Dot at top of center bar + if i == 2: + dot_r = bar_w // 2 + draw.ellipse([x + bar_w//2 - dot_r, y - dot_r, + x + bar_w//2 + dot_r, y + dot_r], fill=COLOR_GREEN_LIGHT) + +def generate_favicon_ico(png_files): + """Generate ICO file from PNG files using ImageMagick.""" + png_paths = [os.path.join(LOGOS_DIR, f) for f in png_files] + ico_path = os.path.join(LOGOS_DIR, "favicon.ico") + + # Use ImageMagick to create multi-size ICO + os.system(f"convert {' '.join(png_paths)} -define icon:auto-resize=16,32,48 {ico_path} 2>/dev/null") + + if os.path.exists(ico_path): + print(f"✓ favicon.ico (from PNGs)") + else: + # Fallback: create from largest + os.system(f"convert {png_paths[-1]} -define icon:auto-resize=16,32,48 {ico_path} 2>/dev/null") + print("✓ favicon.ico (fallback)") + +def generate_png(size, filename): + """Generate PNG favicon.""" + img = Image.new("RGBA", (size, size), (0, 0, 0, 0)) + draw = ImageDraw.Draw(img) + + cx, cy = size // 2, size // 2 + + # Dark circle background with rounded corners + padding = size // 6 + draw.rounded_rectangle([padding, padding, size-padding, size-padding], + radius=size//4, fill=COLOR_DARK) + + draw_wave_with_dot(draw, cx, cy, size - size//3) + + img.save(os.path.join(LOGOS_DIR, filename)) + print(f"✓ {filename}") + +def generate_apple_touch_icon(): + """Generate Apple Touch Icon (180x180).""" + img = Image.new("RGBA", (180, 180), (0, 0, 0, 0)) + draw = ImageDraw.Draw(img) + + # Dark background + draw.rounded_rectangle([0, 0, 179, 179], radius=36, fill=COLOR_DARK) + + cx, cy = 90, 90 + draw_wave_with_dot(draw, cx, cy, 120) + + img.save(os.path.join(LOGOS_DIR, "apple-touch-icon.png")) + print("✓ apple-touch-icon.png") + +def generate_web_manifest(): + """Generate site.webmanifest.""" + manifest = { + "name": "calls24 — Анализ звонков", + "short_name": "calls24", + "description": "Автоматический анализ звонков за 24 часа", + "icons": [ + {"src": "/logos/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png"}, + {"src": "/logos/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png"}, + ], + "theme_color": "#22c55e", + "background_color": "#0a0a0a", + "display": "standalone" + } + + import json + with open(os.path.join(LOGOS_DIR, "site.webmanifest"), "w") as f: + json.dump(manifest, f, ensure_ascii=False, indent=2) + print("✓ site.webmanifest") + +# Generate all favicons +print("🎨 Generating favicons for calls24...\n") + +# Generate PNGs first +generate_png(16, "favicon-16x16.png") +generate_png(32, "favicon-32x32.png") +generate_png(192, "android-chrome-192x192.png") +generate_png(512, "android-chrome-512x512.png") +generate_apple_touch_icon() +generate_web_manifest() + +# Create ICO from PNGs +print() +generate_favicon_ico(["favicon-16x16.png", "favicon-32x32.png", "android-chrome-192x192.png"]) + +print("\n✅ All favicons generated in logos/ folder") diff --git a/index-v4.html b/index-v4.html index 68cf27e..a885f76 100644 --- a/index-v4.html +++ b/index-v4.html @@ -10,6 +10,14 @@ content="Узнайте, сколько денег теряет ваш бизнес. Анализ каждого звонка с операторами за 24 часа." /> + + + + + + + +