'text required'])); } $safe = preg_replace('/[^a-zA-Z0-9]/', '_', substr($text, 0, 20)); $fname = "qr_{$safe}_" . substr(md5($text), 0, 6) . ".png"; $path = $outDir . $fname; $escaped = escapeshellarg($text); shell_exec("python3 -c \" import qrcode from PIL import Image qr = qrcode.QRCode(version=1, box_size=10, border=4, error_correction=qrcode.constants.ERROR_CORRECT_H) qr.add_data($escaped) qr.make(fit=True) img = qr.make_image(fill_color='#7c3aed', back_color='white') img.save('$path') \""); if (file_exists($path)) { echo json_encode(['success' => true, 'url' => "/wevia-ia/downloads/$fname", 'type' => 'qrcode']); } else { echo json_encode(['error' => 'QR génération failed']); } break; // ─── AI IMAGE GENERATION (Cloudflare Workers AI) ─── case 'image': $prompt = $_POST['prompt'] ?? $_GET['prompt'] ?? ''; if (empty($prompt)) { die(json_encode(['error' => 'prompt required'])); } // Try CF Workers AI first $cfAccount = ''; // Need account ID $cfToken = defined('CF_KEY') ? CF_KEY : ''; // Fallback: Use Groq/Cerebras to generate an SVG illustration $ch = curl_init('https://api.groq.com/openai/v1/chat/completions'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, CURLOPT_CONNECTTIMEOUT => 3, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . GROQ_KEY], CURLOPT_POSTFIELDS => json_encode([ 'model' => 'llama-3.3-70b-versatile', 'messages' => [ ['role' => 'system', 'content' => 'Tu es un illustrateur SVG expert. Genere UNIQUEMENT du code SVG (pas de texte avant/apres). Le SVG doit avoir viewBox="0 0 800 600", des formes geometriques, des degrades, des couleurs professionnelles. Cree une illustration detaillee et artistique.'], ['role' => 'user', 'content' => "Cree une illustration SVG pour: $prompt"] ], 'max_tokens' => 2000, 'temperature' => 0.8 ]) ]); $r = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($code == 200 && $r) { $d = json_decode($r, true); $svg = trim($d['choices'][0]['message']['content'] ?? ''); // Extract SVG if wrapped in code block if (preg_match('/```(?:svg)?\s*(.*?)```/s', $svg, $m)) $svg = trim($m[1]); if (strpos($svg, ''; file_put_contents($outDir . $fname, $html); echo json_encode(['success' => true, 'url' => "/wevia-ia/downloads/$fname", 'type' => 'svg_illustration', 'provider' => 'WEVIA ImageGen']); } else { // Fallback to picsum $seed = substr(md5($prompt), 0, 10); echo json_encode(['success' => true, 'url' => "https://picsum.photos/seed/$seed/1024/768", 'type' => 'photo', 'provider' => 'picsum']); } } else { echo json_encode(['error' => 'Image génération failed']); } break; // ─── URL SHORTENER ─── case 'shorten': $url = $_POST['url'] ?? $_GET['url'] ?? ''; if (empty($url) || !filter_var($url, FILTER_VALIDATE_URL)) { die(json_encode(['error' => 'valid URL required'])); } $code = substr(md5($url . time()), 0, 6); $shortDir = '/var/www/html/s/'; if (!is_dir($shortDir)) mkdir($shortDir, 0755, true); file_put_contents($shortDir . $code . '.php', " true, 'short_url' => $shortUrl, 'original' => $url]); break; // ─── IMAGE COMPRESS ─── case 'compress': if (empty($_FILES['image'])) { die(json_encode(['error' => 'image file required'])); } $tmp = $_FILES['image']['tmp_name']; $fname = 'comp_' . substr(md5(time()), 0, 8) . '.jpg'; $path = $outDir . $fname; $quality = intval($_POST['quality'] ?? 75); shell_exec("python3 -c \" from PIL import Image img = Image.open('$tmp') img = img.convert('RGB') img.save('$path', 'JPEG', quality=$quality, optimize=True) \""); if (file_exists($path)) { $origSize = filesize($tmp); $newSize = filesize($path); $ratio = round((1 - $newSize/$origSize) * 100); echo json_encode(['success' => true, 'url' => "/wevia-ia/downloads/$fname", 'original_size' => $origSize, 'compressed_size' => $newSize, 'reduction' => "$ratio%"]); } else { echo json_encode(['error' => 'Compression failed']); } break; // ─── STATUS ─── case 'status': default: echo json_encode([ 'service' => 'WEVIA Tools Hub', 'version' => '1.0', 'tools' => [ 'qrcode' => ['status' => 'live', 'method' => 'POST/GET', 'params' => 'text', 'output' => 'PNG'], 'image' => ['status' => 'live', 'method' => 'POST/GET', 'params' => 'prompt', 'output' => 'SVG/PNG'], 'shorten' => ['status' => 'live', 'method' => 'POST/GET', 'params' => 'url', 'output' => 'short URL'], 'compress' => ['status' => 'live', 'method' => 'POST', 'params' => 'image file + quality', 'output' => 'JPEG'], ], 'replaces' => 'ToolFK (12 tools)', 'advantage' => 'No Cloudflare, no auth, instant response' ]); break; }