// ============================================ // NOUVELLES FONCTIONS POUR LE SYSTÈME DE TOKENS // ============================================ // Fonction pour sauvegarder un message AVEC les informations de tokens function saveMessageWithTokens($conversation_id, $role, $content, $tokens_data = []) { try { $pdo = getDatabaseConnection(); if (!$pdo) return false; // Extraire les données de tokens $tokens_input = $tokens_data['tokens_input'] ?? 0; $tokens_output = $tokens_data['tokens_output'] ?? 0; $tokens_total = $tokens_data['tokens_total'] ?? 0; $model_used = $tokens_data['model'] ?? 'unknown'; $ai_mode = $tokens_data['ai_mode'] ?? 'standard'; $credits_used = $tokens_data['credits_used'] ?? 0; // Insérer le message avec les infos de tokens $stmt = $pdo->prepare(" INSERT INTO ai_messages ( conversation_id, role, content, tokens_input, tokens_output, tokens_used, model_used, credits_cost, created_at ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW()) "); $stmt->execute([ $conversation_id, $role, $content, $tokens_input, $tokens_output, $tokens_total, $model_used, $credits_used ]); $message_id = $pdo->lastInsertId(); // Mettre à jour les totaux de la conversation $stmt = $pdo->prepare(" UPDATE ai_conversations SET total_tokens = total_tokens + ?, total_cost_credits = total_cost_credits + ?, updated_at = NOW() WHERE id = ? "); $stmt->execute([$tokens_total, $credits_used, $conversation_id]); return $message_id; } catch (Exception $e) { error_log("Erreur saveMessageWithTokens: " . $e->getMessage()); return false; } } // Fonction pour décompter les crédits de l'utilisateur function deductUserCredits($user_id, $credits_to_deduct) { try { $pdo = getDatabaseConnection(); if (!$pdo) return false; // Récupérer les crédits actuels $stmt = $pdo->prepare("SELECT credits_ia, abonnement FROM users WHERE id = ?"); $stmt->execute([$user_id]); $user = $stmt->fetch(PDO::FETCH_ASSOC); if (!$user) return false; $current_credits = (int)$user['credits_ia']; $new_credits = max(0, $current_credits - $credits_to_deduct); // Mettre à jour les crédits $stmt = $pdo->prepare("UPDATE users SET credits_ia = ?, credits_utilises = credits_utilises + ? WHERE id = ?"); $stmt->execute([$new_credits, $credits_to_deduct, $user_id]); // Logger la transaction error_log("User $user_id: Crédits décomptés: $credits_to_deduct (Restants: $new_credits)"); return [ 'success' => true, 'credits_remaining' => $new_credits, 'credits_deducted' => $credits_to_deduct ]; } catch (Exception $e) { error_log("Erreur deductUserCredits: " . $e->getMessage()); return false; } } // Fonction pour vérifier si l'utilisateur a assez de crédits function checkUserHasCredits($user_id, $estimated_credits = 10) { try { $pdo = getDatabaseConnection(); if (!$pdo) return true; // En cas d'erreur, on laisse passer $stmt = $pdo->prepare("SELECT credits_ia FROM users WHERE id = ?"); $stmt->execute([$user_id]); $user = $stmt->fetch(PDO::FETCH_ASSOC); if (!$user) return false; $current_credits = (int)$user['credits_ia']; return $current_credits >= $estimated_credits; } catch (Exception $e) { error_log("Erreur checkUserHasCredits: " . $e->getMessage()); return true; // En cas d'erreur, on laisse passer } } // Fonction pour obtenir le webhook selon le mode IA function getWebhookForMode($ai_mode) { $webhooks = [ 'eco' => $_ENV['N8N_WEBHOOK_URL_ECO'] ?? '', 'standard' => $_ENV['N8N_WEBHOOK_URL_STANDARD'] ?? '', 'pro' => $_ENV['N8N_WEBHOOK_URL_PRO'] ?? '', 'ultra' => $_ENV['N8N_WEBHOOK_URL_ULTRA'] ?? '' ]; return $webhooks[$ai_mode] ?? $webhooks['standard']; } // Fonction pour vérifier si l'utilisateur peut utiliser ce mode function canUseMode($subscription_type, $ai_mode) { $subscription_lower = strtolower($subscription_type); // Modes disponibles selon l'abonnement $access_map = [ 'gratuit' => [], 'découverte' => [], 'standard' => ['eco', 'standard'], 'pro' => ['eco', 'standard', 'pro'], 'pro+' => ['eco', 'standard', 'pro'], 'ultra' => ['eco', 'standard', 'pro', 'ultra'] ]; $allowed_modes = $access_map[$subscription_lower] ?? []; return in_array($ai_mode, $allowed_modes); }