Tul xxx Tul
User / IP
:
216.73.216.159
Host / Server
:
45.84.207.204 / aircan.me
System
:
Linux lt-bnk-web1726.main-hosting.eu 5.14.0-611.36.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Mar 3 11:23:52 EST 2026 x86_64
Command
|
Upload
|
Create
Mass Deface
|
Jumping
|
Symlink
|
Reverse Shell
Ping
|
Port Scan
|
DNS Lookup
|
Whois
|
Header
|
cURL
:
/
home
/
u931257429
/
domains
/
aircan.me
/
public_html
/
progressgym
/
modules
/
kanban
/
Viewing: actions.php
<?php /** * Ocean Board actions. * Trello-inspired board/list/card API with Groq Llama 3.3 organization. */ session_start(); header('Content-Type: application/json; charset=utf-8'); require_once __DIR__ . '/../../config/database.php'; require_once __DIR__ . '/../../config/openrouter.php'; require_once __DIR__ . '/ocean_helpers.php'; if (empty($_SESSION['user_id'])) { echo json_encode(['success' => false, 'error' => 'No autorizado']); exit; } $db = getDB(); $uid = (int) $_SESSION['user_id']; $duo = getDuoId(); $action = $_POST['action'] ?? ''; try { oceanEnsureSchema($db); oceanMigrateLegacyBoards($db, $uid, $duo); } catch (Throwable $e) { oceanJsonResponse(['success' => false, 'error' => 'No se pudo preparar Ocean Board: ' . $e->getMessage()]); } function oceanJsonResponse(array $payload, int $status = 200): void { http_response_code($status); echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } function oceanPostString(string $key, int $max = 5000): string { $value = trim((string) ($_POST[$key] ?? '')); return mb_substr($value, 0, $max); } function oceanPostInt(string $key): int { return (int) ($_POST[$key] ?? 0); } function oceanLabelsFromPost(): array { $labelsRaw = oceanPostString('labels', 500); if ($labelsRaw === '') { return []; } $labels = preg_split('/[,;\n]+/', $labelsRaw); $labels = array_map(static fn($label) => trim($label), $labels ?: []); $labels = array_values(array_filter($labels, static fn($label) => $label !== '')); return array_slice($labels, 0, 8); } function oceanChecklistFromPost(): array { $raw = oceanPostString('checklist', 3000); if ($raw === '') { return []; } $items = preg_split('/\r\n|\r|\n/', $raw); $items = array_map(static fn($item) => trim($item), $items ?: []); $items = array_values(array_filter($items, static fn($item) => $item !== '')); return array_slice($items, 0, 20); } function oceanValidDueDate(string $date): ?string { if ($date === '') { return null; } $parsed = DateTime::createFromFormat('Y-m-d', $date); return $parsed ? $parsed->format('Y-m-d') : null; } function oceanAssertBoard(PDO $db, int $uid, int $duo, int $boardId): array { $stmt = $db->prepare("SELECT * FROM ocean_boards WHERE id = ? AND user_id = ? AND duo_id = ?"); $stmt->execute([$boardId, $uid, $duo]); $board = $stmt->fetch(PDO::FETCH_ASSOC); if (!$board) { oceanJsonResponse(['success' => false, 'error' => 'Tablero no encontrado.'], 404); } return $board; } function oceanAssertList(PDO $db, int $uid, int $duo, int $listId): array { $stmt = $db->prepare(" SELECT l.*, b.user_id, b.duo_id FROM ocean_lists l JOIN ocean_boards b ON b.id = l.board_id WHERE l.id = ? AND b.user_id = ? AND b.duo_id = ? "); $stmt->execute([$listId, $uid, $duo]); $list = $stmt->fetch(PDO::FETCH_ASSOC); if (!$list) { oceanJsonResponse(['success' => false, 'error' => 'Lista no encontrada.'], 404); } return $list; } function oceanAssertCard(PDO $db, int $uid, int $duo, int $cardId): array { $stmt = $db->prepare(" SELECT c.*, b.user_id, b.duo_id FROM ocean_cards c JOIN ocean_boards b ON b.id = c.board_id WHERE c.id = ? AND b.user_id = ? AND b.duo_id = ? AND c.is_archived = 0 "); $stmt->execute([$cardId, $uid, $duo]); $card = $stmt->fetch(PDO::FETCH_ASSOC); if (!$card) { oceanJsonResponse(['success' => false, 'error' => 'Tarjeta no encontrada.'], 404); } return $card; } function oceanBoardPayload(PDO $db, int $uid, int $duo, int $boardId): array { $state = oceanBuildState($db, $uid, $duo, $boardId); return [ 'success' => true, 'state' => $state ]; } function oceanCallGroq(string $systemPrompt, string $userPrompt): string { $apiKey = defined('GROQ_API_KEY') && GROQ_API_KEY ? GROQ_API_KEY : (defined('GROQ_API_KEY_TWO') ? GROQ_API_KEY_TWO : ''); if ($apiKey === '') { throw new RuntimeException('Falta GROQ_API_KEY en config/openrouter.php.'); } $payload = [ 'model' => 'llama-3.3-70b-versatile', 'messages' => [ ['role' => 'system', 'content' => $systemPrompt], ['role' => 'user', 'content' => $userPrompt] ], 'temperature' => 0.25, 'response_format' => ['type' => 'json_object'] ]; $ch = curl_init('https://api.groq.com/openai/v1/chat/completions'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Authorization: Bearer ' . $apiKey ], CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), CURLOPT_SSL_VERIFYPEER => false, CURLOPT_TIMEOUT => 45 ]); $response = curl_exec($ch); $error = curl_error($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($error) { throw new RuntimeException('No se pudo conectar con el motor de IA: ' . $error); } $decoded = json_decode((string) $response, true); if ($status >= 400) { throw new RuntimeException($decoded['error']['message'] ?? "El motor de IA devolvio HTTP {$status}."); } return (string) ($decoded['choices'][0]['message']['content'] ?? ''); } function oceanCleanJson(string $raw): array { $raw = trim($raw); if (preg_match('/```json(.*?)```/is', $raw, $match)) { $raw = trim($match[1]); } else { $start = strpos($raw, '{'); $end = strrpos($raw, '}'); if ($start !== false && $end !== false) { $raw = substr($raw, $start, $end - $start + 1); } } $data = json_decode($raw, true); if (!is_array($data)) { throw new RuntimeException('La IA no devolvio JSON valido.'); } return $data; } function oceanFindOrCreateList(PDO $db, int $boardId, string $title): int { $title = trim($title); if ($title === '') { $title = 'Por hacer'; } $stmt = $db->prepare("SELECT id FROM ocean_lists WHERE board_id = ? AND LOWER(title) = LOWER(?) LIMIT 1"); $stmt->execute([$boardId, $title]); $existing = $stmt->fetchColumn(); if ($existing) { return (int) $existing; } $orderStmt = $db->prepare("SELECT COALESCE(MAX(list_order), 0) + 1 FROM ocean_lists WHERE board_id = ?"); $orderStmt->execute([$boardId]); $order = (int) $orderStmt->fetchColumn(); $insert = $db->prepare("INSERT INTO ocean_lists (board_id, title, list_order) VALUES (?, ?, ?)"); $insert->execute([$boardId, mb_substr($title, 0, 140), $order]); return (int) $db->lastInsertId(); } function oceanNextCardOrder(PDO $db, int $listId): int { $stmt = $db->prepare("SELECT COALESCE(MAX(card_order), 0) + 1 FROM ocean_cards WHERE list_id = ? AND is_archived = 0"); $stmt->execute([$listId]); return (int) $stmt->fetchColumn(); } function oceanInsertCard(PDO $db, int $boardId, int $listId, array $card, ?int $position = null): int { $title = trim((string) ($card['title'] ?? 'Nueva tarjeta')); if ($title === '') { $title = 'Nueva tarjeta'; } $labels = $card['labels'] ?? []; if (!is_array($labels)) { $labels = []; } $checklist = $card['checklist'] ?? []; if (!is_array($checklist)) { $checklist = []; } $dueDate = null; if (!empty($card['due_date'])) { $dueDate = oceanValidDueDate((string) $card['due_date']); } elseif (isset($card['due_in_days']) && is_numeric($card['due_in_days'])) { $days = max(0, min(365, (int) $card['due_in_days'])); $dueDate = (new DateTime())->modify("+{$days} days")->format('Y-m-d'); } $stmt = $db->prepare(" INSERT INTO ocean_cards (board_id, list_id, title, description, labels_json, checklist_json, due_date, priority, card_order, ai_notes) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "); $stmt->execute([ $boardId, $listId, mb_substr($title, 0, 220), (string) ($card['description'] ?? ''), oceanJsonEncode(array_slice(array_values($labels), 0, 8)), oceanJsonEncode(array_slice(array_values($checklist), 0, 20)), $dueDate, mb_substr((string) ($card['priority'] ?? 'media'), 0, 20), $position ?? oceanNextCardOrder($db, $listId), (string) ($card['ai_notes'] ?? '') ]); return (int) $db->lastInsertId(); } function oceanBoardDigest(array $active): array { $digest = []; foreach (($active['lists'] ?? []) as $list) { $cards = []; foreach (($list['cards'] ?? []) as $card) { $cards[] = [ 'id' => (int) $card['id'], 'title' => $card['title'], 'description' => $card['description'], 'priority' => $card['priority'], 'labels' => $card['labels'] ?? [], 'due_date' => $card['due_date'] ]; } $digest[] = [ 'list_id' => (int) $list['id'], 'list_title' => $list['title'], 'cards' => $cards ]; } return $digest; } function oceanDeleteEmptyLists(PDO $db, int $boardId): int { $stmt = $db->prepare(" DELETE l FROM ocean_lists l LEFT JOIN ocean_cards c ON c.list_id = l.id AND c.is_archived = 0 WHERE l.board_id = ? AND c.id IS NULL "); $stmt->execute([$boardId]); return $stmt->rowCount(); } try { if ($action === 'fetch_board') { $boardId = oceanPostInt('board_id'); oceanJsonResponse(oceanBoardPayload($db, $uid, $duo, $boardId)); } if ($action === 'create_board') { $title = oceanPostString('title', 180); $description = oceanPostString('description', 2000); if ($title === '') { oceanJsonResponse(['success' => false, 'error' => 'El tablero necesita nombre.']); } $boardId = oceanCreateBoardWithLists($db, $uid, $duo, $title, $description); oceanJsonResponse(oceanBoardPayload($db, $uid, $duo, $boardId)); } if ($action === 'update_board') { $boardId = oceanPostInt('board_id'); oceanAssertBoard($db, $uid, $duo, $boardId); $title = oceanPostString('title', 180); $description = oceanPostString('description', 2000); if ($title === '') { oceanJsonResponse(['success' => false, 'error' => 'El tablero necesita nombre.']); } $stmt = $db->prepare("UPDATE ocean_boards SET title = ?, description = ?, updated_at = NOW() WHERE id = ?"); $stmt->execute([$title, $description, $boardId]); oceanCreateActivity($db, $boardId, $uid, 'board_updated', 'Tablero actualizado'); oceanJsonResponse(oceanBoardPayload($db, $uid, $duo, $boardId)); } if ($action === 'delete_board') { $boardId = oceanPostInt('board_id'); oceanAssertBoard($db, $uid, $duo, $boardId); $db->beginTransaction(); $db->prepare("DELETE FROM ocean_cards WHERE board_id = ?")->execute([$boardId]); $db->prepare("DELETE FROM ocean_lists WHERE board_id = ?")->execute([$boardId]); $db->prepare("DELETE FROM ocean_activity WHERE board_id = ?")->execute([$boardId]); $db->prepare("DELETE FROM ocean_boards WHERE id = ?")->execute([$boardId]); $db->commit(); $state = oceanBuildState($db, $uid, $duo, 0); oceanJsonResponse(['success' => true, 'state' => $state]); } if ($action === 'create_list') { $boardId = oceanPostInt('board_id'); oceanAssertBoard($db, $uid, $duo, $boardId); $title = oceanPostString('title', 140); if ($title === '') { oceanJsonResponse(['success' => false, 'error' => 'La lista necesita nombre.']); } oceanFindOrCreateList($db, $boardId, $title); oceanCreateActivity($db, $boardId, $uid, 'list_created', "Lista {$title} creada"); oceanTouchBoard($db, $boardId); oceanJsonResponse(oceanBoardPayload($db, $uid, $duo, $boardId)); } if ($action === 'update_list') { $listId = oceanPostInt('list_id'); $list = oceanAssertList($db, $uid, $duo, $listId); $title = oceanPostString('title', 140); if ($title === '') { oceanJsonResponse(['success' => false, 'error' => 'La lista necesita nombre.']); } $stmt = $db->prepare("UPDATE ocean_lists SET title = ?, updated_at = NOW() WHERE id = ?"); $stmt->execute([$title, $listId]); oceanCreateActivity($db, (int) $list['board_id'], $uid, 'list_updated', "Lista renombrada a {$title}"); oceanTouchBoard($db, (int) $list['board_id']); oceanJsonResponse(oceanBoardPayload($db, $uid, $duo, (int) $list['board_id'])); } if ($action === 'delete_list') { $listId = oceanPostInt('list_id'); $list = oceanAssertList($db, $uid, $duo, $listId); $db->beginTransaction(); $db->prepare("DELETE FROM ocean_cards WHERE list_id = ?")->execute([$listId]); $db->prepare("DELETE FROM ocean_lists WHERE id = ?")->execute([$listId]); $db->commit(); oceanCreateActivity($db, (int) $list['board_id'], $uid, 'list_deleted', "Lista {$list['title']} eliminada"); oceanTouchBoard($db, (int) $list['board_id']); oceanJsonResponse(oceanBoardPayload($db, $uid, $duo, (int) $list['board_id'])); } if ($action === 'create_card') { $listId = oceanPostInt('list_id'); $list = oceanAssertList($db, $uid, $duo, $listId); $title = oceanPostString('title', 220); if ($title === '') { oceanJsonResponse(['success' => false, 'error' => 'La tarjeta necesita titulo.']); } oceanInsertCard($db, (int) $list['board_id'], $listId, [ 'title' => $title, 'description' => oceanPostString('description', 8000), 'labels' => oceanLabelsFromPost(), 'checklist' => oceanChecklistFromPost(), 'due_date' => oceanPostString('due_date', 10), 'priority' => oceanPostString('priority', 20) ]); oceanCreateActivity($db, (int) $list['board_id'], $uid, 'card_created', "Tarjeta {$title} creada"); oceanTouchBoard($db, (int) $list['board_id']); oceanJsonResponse(oceanBoardPayload($db, $uid, $duo, (int) $list['board_id'])); } if ($action === 'update_card') { $cardId = oceanPostInt('card_id'); $card = oceanAssertCard($db, $uid, $duo, $cardId); $title = oceanPostString('title', 220); if ($title === '') { oceanJsonResponse(['success' => false, 'error' => 'La tarjeta necesita titulo.']); } $targetListId = oceanPostInt('list_id') ?: (int) $card['list_id']; $list = oceanAssertList($db, $uid, $duo, $targetListId); if ((int) $list['board_id'] !== (int) $card['board_id']) { oceanJsonResponse(['success' => false, 'error' => 'La lista no pertenece al tablero.']); } $stmt = $db->prepare(" UPDATE ocean_cards SET list_id = ?, title = ?, description = ?, labels_json = ?, checklist_json = ?, due_date = ?, priority = ?, updated_at = NOW() WHERE id = ? "); $stmt->execute([ $targetListId, $title, oceanPostString('description', 8000), oceanJsonEncode(oceanLabelsFromPost()), oceanJsonEncode(oceanChecklistFromPost()), oceanValidDueDate(oceanPostString('due_date', 10)), oceanPostString('priority', 20) ?: 'media', $cardId ]); oceanCreateActivity($db, (int) $card['board_id'], $uid, 'card_updated', "Tarjeta {$title} actualizada"); oceanTouchBoard($db, (int) $card['board_id']); oceanJsonResponse(oceanBoardPayload($db, $uid, $duo, (int) $card['board_id'])); } if ($action === 'delete_card') { $cardId = oceanPostInt('card_id'); $card = oceanAssertCard($db, $uid, $duo, $cardId); $stmt = $db->prepare("UPDATE ocean_cards SET is_archived = 1, updated_at = NOW() WHERE id = ?"); $stmt->execute([$cardId]); oceanCreateActivity($db, (int) $card['board_id'], $uid, 'card_archived', "Tarjeta {$card['title']} archivada"); oceanTouchBoard($db, (int) $card['board_id']); oceanJsonResponse(oceanBoardPayload($db, $uid, $duo, (int) $card['board_id'])); } if ($action === 'move_card') { $cardId = oceanPostInt('card_id'); $targetListId = oceanPostInt('target_list_id'); $orderedIds = oceanJsonDecode($_POST['ordered_ids'] ?? '', []); $card = oceanAssertCard($db, $uid, $duo, $cardId); $list = oceanAssertList($db, $uid, $duo, $targetListId); if ((int) $list['board_id'] !== (int) $card['board_id']) { oceanJsonResponse(['success' => false, 'error' => 'Movimiento invalido.']); } $stmt = $db->prepare("UPDATE ocean_cards SET list_id = ?, updated_at = NOW() WHERE id = ?"); $stmt->execute([$targetListId, $cardId]); $order = 1; $updateOrder = $db->prepare("UPDATE ocean_cards SET card_order = ? WHERE id = ? AND list_id = ? AND board_id = ?"); foreach ($orderedIds as $orderedId) { $updateOrder->execute([$order, (int) $orderedId, $targetListId, (int) $card['board_id']]); $order++; } oceanTouchBoard($db, (int) $card['board_id']); oceanJsonResponse(['success' => true]); } if ($action === 'ai_plan_board') { $boardId = oceanPostInt('board_id'); $board = oceanAssertBoard($db, $uid, $duo, $boardId); $objective = oceanPostString('objective', 3000); $context = oceanPostString('context', 4000); if ($objective === '') { oceanJsonResponse(['success' => false, 'error' => 'Escribe el objetivo para la IA.']); } $system = "Eres un organizador experto estilo Trello para desarrollo personal. Convierte objetivos en listas y tarjetas accionables. Responde solo JSON valido, sin markdown. Usa espanol claro."; $userPrompt = "Tablero: {$board['title']}\nDescripcion: {$board['description']}\nObjetivo del usuario: {$objective}\nContexto: {$context}\n\nDevuelve este JSON exacto:\n{\n \"summary\": \"resumen breve del plan\",\n \"lists\": [\"Bandeja\", \"Por hacer\", \"En curso\", \"En revision\", \"Hecho\"],\n \"cards\": [\n {\n \"list\": \"Por hacer\",\n \"title\": \"titulo accionable\",\n \"description\": \"descripcion breve\",\n \"priority\": \"alta|media|baja\",\n \"labels\": [\"etiqueta\"],\n \"checklist\": [\"paso verificable\"],\n \"due_in_days\": 2\n }\n ]\n}\nReglas: 6 a 18 tarjetas, maximo 5 listas, titulos cortos, nada generico, pasos verificables."; $ai = oceanCleanJson(oceanCallGroq($system, $userPrompt)); $lists = $ai['lists'] ?? oceanDefaultLists(); if (!is_array($lists) || empty($lists)) { $lists = oceanDefaultLists(); } $createdCards = 0; $db->beginTransaction(); $db->prepare("DELETE FROM ocean_cards WHERE board_id = ?")->execute([$boardId]); $db->prepare("DELETE FROM ocean_lists WHERE board_id = ?")->execute([$boardId]); foreach (array_slice($lists, 0, 5) as $listTitle) { oceanFindOrCreateList($db, $boardId, (string) $listTitle); } foreach (array_slice(($ai['cards'] ?? []), 0, 24) as $cardData) { if (!is_array($cardData)) { continue; } $listId = oceanFindOrCreateList($db, $boardId, (string) ($cardData['list'] ?? 'Por hacer')); oceanInsertCard($db, $boardId, $listId, $cardData); $createdCards++; } $deletedEmptyLists = $createdCards > 0 ? oceanDeleteEmptyLists($db, $boardId) : 0; $stmt = $db->prepare("UPDATE ocean_boards SET ai_summary = ?, updated_at = NOW() WHERE id = ?"); $stmt->execute([mb_substr((string) ($ai['summary'] ?? 'Plan generado con Llama 3.3'), 0, 2000), $boardId]); oceanCreateActivity($db, $boardId, $uid, 'ai_plan', "Llama 3.3 reemplazo el tablero con {$createdCards} tarjetas"); if ($deletedEmptyLists > 0) { oceanCreateActivity($db, $boardId, $uid, 'ai_cleanup', "Se limpiaron {$deletedEmptyLists} listas vacias"); } $db->commit(); oceanJsonResponse(oceanBoardPayload($db, $uid, $duo, $boardId) + [ 'message' => "Llama 3.3 reemplazo el tablero con {$createdCards} tarjetas." ]); } if ($action === 'ai_reorganize_board') { $boardId = oceanPostInt('board_id'); oceanAssertBoard($db, $uid, $duo, $boardId); $active = oceanFetchBoard($db, $uid, $duo, $boardId); if (!$active) { oceanJsonResponse(['success' => false, 'error' => 'Tablero no encontrado.']); } $digest = oceanBoardDigest($active); $system = "Eres un operador de tableros tipo Trello. Reorganiza tarjetas para que el flujo sea claro, priorizado y ejecutable. Responde solo JSON valido."; $userPrompt = "Tablero actual en JSON:\n" . json_encode($digest, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n\nDevuelve este JSON:\n{\n \"summary\": \"diagnostico breve\",\n \"moves\": [\n {\"card_id\": 123, \"target_list\": \"Por hacer\", \"priority\": \"alta|media|baja\", \"labels\": [\"enfoque\"], \"reason\": \"motivo breve\"}\n ],\n \"next_best_cards\": [123, 456]\n}\nReglas: mueve solo si mejora claridad, respeta IDs existentes, no inventes IDs, maximo 12 movimientos."; $ai = oceanCleanJson(oceanCallGroq($system, $userPrompt)); $moves = is_array($ai['moves'] ?? null) ? $ai['moves'] : []; $applied = 0; $db->beginTransaction(); foreach (array_slice($moves, 0, 12) as $move) { if (!is_array($move) || empty($move['card_id'])) { continue; } $cardId = (int) $move['card_id']; $stmtCard = $db->prepare("SELECT id FROM ocean_cards WHERE id = ? AND board_id = ? AND is_archived = 0"); $stmtCard->execute([$cardId, $boardId]); if (!$stmtCard->fetchColumn()) { continue; } $targetListId = oceanFindOrCreateList($db, $boardId, (string) ($move['target_list'] ?? 'Por hacer')); $stmtUpdate = $db->prepare(" UPDATE ocean_cards SET list_id = ?, priority = ?, labels_json = ?, ai_notes = ?, card_order = ?, updated_at = NOW() WHERE id = ? AND board_id = ? "); $labels = is_array($move['labels'] ?? null) ? $move['labels'] : []; $stmtUpdate->execute([ $targetListId, mb_substr((string) ($move['priority'] ?? 'media'), 0, 20), oceanJsonEncode(array_slice($labels, 0, 8)), mb_substr((string) ($move['reason'] ?? ''), 0, 1000), oceanNextCardOrder($db, $targetListId), $cardId, $boardId ]); $applied++; } $deletedEmptyLists = $applied > 0 ? oceanDeleteEmptyLists($db, $boardId) : 0; $stmt = $db->prepare("UPDATE ocean_boards SET ai_summary = ?, updated_at = NOW() WHERE id = ?"); $stmt->execute([mb_substr((string) ($ai['summary'] ?? 'Tablero reorganizado con Llama 3.3'), 0, 2000), $boardId]); oceanCreateActivity($db, $boardId, $uid, 'ai_reorganize', "Llama 3.3 aplico {$applied} movimientos"); if ($deletedEmptyLists > 0) { oceanCreateActivity($db, $boardId, $uid, 'ai_cleanup', "Se limpiaron {$deletedEmptyLists} listas vacias"); } $db->commit(); oceanJsonResponse(oceanBoardPayload($db, $uid, $duo, $boardId) + [ 'message' => "Llama 3.3 aplico {$applied} ajustes." ]); } oceanJsonResponse(['success' => false, 'error' => 'Accion invalida.'], 400); } catch (Throwable $e) { if ($db->inTransaction()) { $db->rollBack(); } oceanJsonResponse(['success' => false, 'error' => $e->getMessage()], 500); }
Coded With 💗 by
0x6ick