{"repo": "asley/chhs-testing", "files": {"modules/ChatBot/moduleFunctions.php": {"5eacf702b1d14d58114e1990619ea4913b19ff59": {"t": 1785745766.0855227, "n": 21952, "h": "6781a141c0d264fc", "c": ".\n*/\n\nuse Gibbon\\Domain\\System\\SettingGateway;\nuse Gibbon\\Forms\\Form;\nuse Gibbon\\Services\\Format as GibbonFormat;\nuse Gibbon\\Domain\\System\\ModuleGateway;\nuse Gibbon\\Domain\\DataSet;\nuse Gibbon\\Tables\\DataTable;\n\n// Include Gibbon core functions\nrequire_once __DIR__ . '/../../functions.php';\n\n/**\n * Get a setting value by scope\n * @param PDO $connection2 The database connection\n * @param string $scope The setting scope\n * @param string $name The setting name\n * @return string The setting value\n */\nfunction getSettingByScope($connection2, $scope, $name) {\n try {\n $sql = \"SELECT value FROM gibbonSetting WHERE scope=:scope AND name=:name\";\n $result = $connection2->prepare($sql);\n $result->execute(['scope' => $scope, 'name' => $name]);\n if ($result->rowCount() == 1) {\n $row = $result->fetch();\n return $row['value'];\n }\n } catch (PDOException $e) {\n return '';\n }\n return '';\n}\n\n/**\n * Check if a file is a valid PDF\n * @param string $file The file path\n * @return bool Whether the file is a valid PDF\n */\nfunction isValidPDF($file) {\n if (empty($file)) return false;\n \n // Check file extension\n $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));\n if ($extension !== 'pdf') return false;\n \n // Check file mime type\n $finfo = finfo_open(FILEINFO_MIME_TYPE);\n $mimeType = finfo_file($finfo, $file);\n finfo_close($finfo);\n \n return $mimeType === 'application/pdf';\n}\n\n/**\n * Extract text from PDF file\n * @param string $pdfFile The PDF file path\n * @return string The extracted text\n */\nfunction extractTextFromPDF($pdfFile) {\n if (!isValidPDF($pdfFile)) {\n throw new Exception('Invalid PDF file');\n }\n \n // Create temporary files\n $tempPdf = tempnam(sys_get_temp_dir(), 'pdf_');\n $tempTxt = tempnam(sys_get_temp_dir(), 'txt_');\n \n try {\n // Copy PDF to temp location\n if (!copy($pdfFile, $tempPdf)) {\n throw new Exception('Failed to copy PDF file');\n }\n \n // Convert PDF to text\n exec(\"pdftotext '{$tempPdf}' '{$tempTxt}' 2>&1\", $output, $returnVar);\n \n if ($returnVar !== 0) {\n throw new Exception('Failed to convert PDF: ' . implode(\"\\n\", $output));\n }\n \n // Read converted text\n $text = file_get_contents($tempTxt);\n \n return $text;\n \n } finally {\n // Clean up temp files\n if (file_exists($tempPdf)) unlink($tempPdf);\n if (file_exists($tempTxt)) unlink($tempTxt);\n }\n}\n\n/**\n * Store the API key securely\n * @param PDO $connection2 The database connection\n * @param string $apiKey The API key to store\n * @return bool Whether the operation was successful\n */\nfunction storeAPIKey($connection2, $apiKey) {\n try {\n $sql = \"INSERT INTO gibbonSetting (scope, name, nameDisplay, description, value) \n VALUES ('ChatBot', 'deepseek_api_key', 'DeepSeek API Key', 'API key for DeepSeek integration', :apiKey)\n ON DUPLICATE KEY UPDATE value = :apiKey\";\n \n $result = $connection2->prepare($sql);\n return $result->execute(['apiKey' => $apiKey]);\n } catch (PDOException $e) {\n error_log('Error storing API key: ' . $e->getMessage());\n return false;\n }\n}\n\n/**\n * Get the API key securely\n * @param PDO $connection2 The database connection\n * @return string The API key\n */\nfunction getSecureAPIKey($connection2) {\n try {\n $sql = \"SELECT value FROM gibbonSetting WHERE scope='ChatBot' AND name='deepseek_api_key'\";\n $result = $connection2->prepare($sql);\n $result->execute();\n if ($result->rowCount() == 1) {\n $row = $result->fetch();\n return $row['value'];\n }\n } catch (PDOException $e) {\n return '';\n }\n return '';\n}\n\n/**\n * Get student assessment data\n * @param PDO $connection2 The database connection\n * @param int $studentID The student ID\n * @return array The assessment data\n */\nfunction getStudentAssessmentData($connection2, $studentID) {\n try {\n $sql = \"SELECT \n ia.name as assessment_name,\n iac.attainmentValue,\n iac.effortValue,\n iac.comment as teacher_feedback,\n c.name as course_name\n FROM gibbonInternalAssessmentEntry iac\n JOIN gibbonInternalAssessmentColumn ia ON (ia.gibbonInternalAssessmentColumnID=iac.gibbonInternalAssessmentColumnID)\n JOIN gibbonCourse c ON (c.gibbonCourseID=ia.gibbonCourseID)\n WHERE iac.gibbonPersonID=:studentID\n ORDER BY ia.timestampCreated DESC\";\n \n $result = $connection2->prepare($sql);\n $result->execute(['studentID' => $studentID]);\n return $result->fetchAll(PDO::FETCH_ASSOC);\n } catch (Exception $e) {\n error_log('Error getting student assessment data: ' . $e->getMessage());\n return [];\n }\n}\n\n/**\n * Make a secure call to the OpenAI API\n * \n * @param string $apiKey\n * @param array $data\n * @return array|null\n */\nfunction callOpenAIAPI($apiKey, $data) {\n try {\n // Initialize cURL session\n $ch = curl_init('https://api.openai.com/v1/chat/completions');\n \n // Set cURL options\n curl_setopt_array($ch, [\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_POST => true,\n CURLOPT_HTTPHEADER => [\n 'Content-Type: application/json',\n 'Authorization: Bearer ' . $apiKey\n ],\n CURLOPT_POSTFIELDS => json_encode($data),\n CURLOPT_SSL_VERIFYPEER => true, // Verify SSL certificate\n CURLOPT_SSL_VERIFYHOST => 2, // Verify hostname\n CURLOPT_CONNECTTIMEOUT => 10, // Connection timeout\n CURLOPT_TIMEOUT => 30, // Response timeout\n CURLOPT_PROTOCOLS => CURLPROTO_HTTPS, // Only allow HTTPS\n ]);\n \n // Execute request\n $response = curl_exec($ch);\n $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n \n // Check for errors\n if ($httpCode !== 200) {\n error_log('OpenAI API error: HTTP ' . $httpCode);\n error_log('Response: ' . $response);\n return null;\n }\n \n // Close cURL session\n curl_close($ch);\n \n // Parse and return response\n return json_decode($response, true);\n \n } catch (Exception $e) {\n error_log('Error calling OpenAI API: ' . $e->getMessage());\n return null;\n }\n}\n\n// Only declare if not already defined\nif (!function_exists('isActionAccessible')) {\n /**\n * Check if a user has access to a specific action\n * @param mixed $guid The global unique identifier\n * @param PDO $connection2 The database connection\n * @param string $address The action address to check\n * @return bool Whether the user has access\n */\n function isActionAccessible($guid, $connection2, $address) {\n try {\n $data = array('gibbonRoleID' => $_SESSION[$guid]['gibbonRoleIDCurrent'], 'address' => $address);\n $sql = \"SELECT DISTINCT gibbonAction.gibbonActionID \n FROM gibbonAction \n JOIN gibbonPermission ON (gibbonAction.gibbonActionID=gibbonPermission.gibbonActionID) \n WHERE (gibbonPermission.gibbonRoleID=:gibbonRoleID AND gibbonAction.URLList LIKE CONCAT('%', :address, '%'))\";\n $result = $connection2->prepare($sql);\n $result->execute($data);\n return ($result->rowCount() > 0);\n } catch (PDOException $e) {\n return false;\n }\n }\n}\n\n/**\n * Helper functions for the ChatBot module\n */\n\n/**\n * Check if a user has access to the ChatBot module\n *\n * @param string $guid\n * @param PDO $connection2\n * @return bool\n */\nfunction chatbotCheckAccess($guid, $connection2) {\n return isActionAccessible($guid, $connection2, '/modules/ChatBot/chatbot.php');\n}\n\n/**\n * Get the DeepSeek API key from settings\n *\n * @param SettingGateway $settingGateway\n * @return string|null\n */\nfunction chatbotGetApiKey($settingGateway) {\n return $settingGateway->getSettingByScope('ChatBot', 'deepseek_api_key');\n}\n\n/**\n * Format chat messages for display\n *\n * @param array $messages\n * @return string\n */\nfunction chatbotFormatMessages($messages) {\n $output = '';\n foreach ($messages as $message) {\n $type = $message['type'];\n $content = $message['content'];\n $output .= \"
\";\n }\n return $output;\n}\n\n/**\n * Validate chat message\n *\n * @param string $message\n * @return bool\n */\nfunction chatbotValidateMessage($message) {\n return !empty(trim($message));\n}\n\n/**\n * Sanitize chat message\n *\n * @param string $message\n * @return string\n */\nfunction chatbotSanitizeMessage($message) {\n return strip_tags(trim($message));\n}\n\n/**\n * Store AI recommendations for a student\n * @param PDO $connection2 The database connection\n * @param int $gibbonPersonID The student ID\n * @param int $gibbonCourseClassID The course class ID\n * @param int $assessmentID The assessment ID\n * @param string $recommendation The AI recommendation\n * @return bool Whether the operation was successful\n */\nfunction storeRecommendation($connection2, $gibbonPersonID, $gibbonCourseClassID, $assessmentID, $recommendation) {\n try {\n $sql = \"INSERT INTO gibbonChatBotRecommendations \n (gibbonPersonID, gibbonCourseClassID, assessmentID, recommendation) \n VALUES \n (:gibbonPersonID, :gibbonCourseClassID, :assessmentID, :recommendation)\";\n \n $result = $connection2->prepare($sql);\n return $result->execute([\n 'gibbonPersonID' => $gibbonPersonID,\n 'gibbonCourseClassID' => $gibbonCourseClassID,\n 'assessmentID' => $assessmentID,\n 'recommendation' => $recommendation\n ]);\n } catch (PDOException $e) {\n error_log('Error storing recommendation: ' . $e->getMessage());\n return false;\n }\n}\n\n/**\n * Get AI recommendations for a student\n * @param PDO $connection2 The database connection\n * @param int $gibbonPersonID The student ID\n * @return array The recommendations\n */\nfunction getStudentRecommendations($connection2, $gibbonPersonID) {\n try {\n $sql = \"SELECT r.*, \n ia.name as assessment_name,\n c.name as course_name\n FROM gibbonChatBotRecommendations r\n JOIN gibbonInternalAssessment ia ON (ia.gibbonInternalAssessmentID = r.assessmentID)\n JOIN gibbonCourseClass cc ON (cc.gibbonCourseClassID = r.gibbonCourseClassID)\n JOIN gibbonCourse c ON (c.gibbonCourseID = cc.gibbonCourseID)\n WHERE r.gibbonPersonID = :gibbonPersonID\n ORDER BY r.timestamp DESC\";\n \n $result = $connection2->prepare($sql);\n $result->execute(['gibbonPersonID' => $gibbonPersonID]);\n return $result->fetchAll(PDO::FETCH_ASSOC);\n } catch (PDOException $e) {\n error_log('Error getting student recommendations: ' . $e->getMessage());\n return [];\n }\n}\n\n/**\n * Add training data to the ChatBot\n * @param PDO $connection2 The database connection\n * @param string $question The question\n * @param string $answer The answer\n * @param int $createdBy The user ID who created the entry\n * @param string|null $category The category (optional)\n * @return bool Whether the operation was successful\n */\nfunction addTrainingData($connection2, $question, $answer, $createdBy, $category = null) {\n try {\n $sql = \"INSERT INTO gibbonChatBotTraining \n (question, answer, category, created_by) \n VALUES \n (:question, :answer, :category, :created_by)\";\n \n $result = $connection2->prepare($sql);\n return $result->execute([\n 'question' => $question,\n 'answer' => $answer,\n 'category' => $category,\n 'created_by' => $createdBy\n ]);\n } catch (PDOException $e) {\n error_log('Error adding training data: ' . $e->getMessage());\n return false;\n }\n}\n\n/**\n * Get training data for the ChatBot\n * @param PDO $connection2 The database connection\n * @param string $category Optional category filter\n * @return array The training data\n */\nfunction getTrainingData($connection2, $category = null) {\n try {\n $sql = \"SELECT * FROM gibbonChatBotTraining\";\n $params = [];\n \n if ($category) {\n $sql .= \" WHERE category = :category\";\n $params['category'] = $category;\n }\n \n $sql .= \" ORDER BY timestampCreated DESC\";\n \n $result = $connection2->prepare($sql);\n $result->execute($params);\n return $result->fetchAll(PDO::FETCH_ASSOC);\n } catch (PDOException $e) {\n error_log('Error getting training data: ' . $e->getMessage());\n return [];\n }\n}\n\n/**\n * Delete training data\n * @param PDO $connection2 The database connection\n * @param int $id The training data ID\n * @return bool Whether the operation was successful\n */\nfunction deleteTrainingData($connection2, $id) {\n try {\n $sql = \"DELETE FROM gibbonChatBotTraining WHERE gibbonChatBotTrainingID = :id\";\n $result = $connection2->prepare($sql);\n return $result->execute(['id' => $id]);\n } catch (PDOException $e) {\n error_log('Error deleting training data: ' . $e->getMessage());\n return false;\n }\n}\n\n/**\n * Generate AI recommendations based on assessment data\n * @param array $assessment The assessment data\n * @param string $apiKey The DeepSeek API key\n * @return string|null The AI recommendation\n */\nfunction generateAssessmentRecommendation($assessment, $apiKey) {\n try {\n $prompt = \"Based on the following assessment data:\\n\";\n $prompt .= \"Subject: {$assessment['subject']}\\n\";\n $prompt .= \"Grade: {$assessment['grade']}\\n\";\n $prompt .= \"Teacher Feedback: {$assessment['feedback']}\\n\\n\";\n $prompt .= \"Please provide specific, actionable recommendations for improvement in this subject. Consider:\\n\";\n $prompt .= \"1. Study strategies\\n\";\n $prompt .= \"2. Practice exercises\\n\";\n $prompt .= \"3. Additional resources\\n\";\n $prompt .= \"4. Areas needing focus based on the assessment\\n\";\n $prompt .= \"5. Time management suggestions\";\n \n $data = [\n 'model' => 'deepseek-v4-flash',\n 'messages' => [\n [\n 'role' => 'system',\n 'content' => 'You are an educational AI assistant providing specific, actionable recommendations for academic improvement based on assessment data and teacher feedback.'\n ],\n [\n 'role' => 'user',\n 'content' => $prompt\n ]\n ],\n 'max_tokens' => 500\n ];\n \n $ch = curl_init();\n curl_setopt($ch, CURLOPT_URL, 'https://api.deepseek.com/v1/chat/completions');\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n curl_setopt($ch, CURLOPT_POST, true);\n curl_setopt($ch, CURLOPT_HTTPHEADER, [\n 'Content-Type: application/json',\n 'Authorization: Bearer ' . $apiKey\n ]);\n \n curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));\n \n $response = curl_exec($ch);\n $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n curl_close($ch);\n \n if ($httpCode === 200) {\n $result = json_decode($response, true);\n return $result['choices'][0]['message']['content'];\n }\n } catch (Exception $e) {\n error_log('Error generating assessment recommendation: ' . $e->getMessage());\n }\n \n return null;\n}\n\n/**\n * Get student performance metrics\n * @param int $gibbonPersonID\n * @return string HTML output of performance metrics\n */\nfunction getStudentPerformanceMetrics($gibbonPersonID) {\n global $pdo;\n \n try {\n // Get assessment data\n $data = getStudentAssessmentData($gibbonPersonID);\n \n // Calculate metrics\n $metrics = [\n 'average_attainment' => calculateAverageAttainment($data),\n 'progress_indicators' => analyzeProgressTrends($data),\n 'subject_breakdown' => getSubjectPerformance($data)\n ];\n \n // Generate HTML output\n $output = '' . __('Ask me anything about your coursework. I\\'m here to help you learn!') . '
';\n echo '';\n echo '' . __('Ask me anything about your coursework. I\\'m here to help you learn!') . '
';\n echo '';\n echo '' . __('Ask me anything about your coursework. I\\'m here to help you learn!') . '
';\n echo '';\n echo '' . __('Ask me anything about your coursework. I\\'m here to help you learn!') . '
';\n echo '';\n echo '' . __('Ask me anything about your coursework. I\\'m here to help you learn!') . '
';\n echo '';\n echo '' . __('Ask me anything about your coursework. I\\'m here to help you learn!') . '
';\n echo '';\n echo '' . __('Ask me anything about your coursework. I\\'m here to help you learn!') . '
';\n echo '';\n echo '\";\n echo \"Current ChatBot Settings:\\n\";\n foreach ($settings as $setting) {\n echo \"- {$setting['name']}: \" . (empty($setting['value']) ? 'Not set' : 'Set') . \"\\n\";\n echo \" Description: {$setting['description']}\\n\";\n }\n echo \"\";\n \n // Add link to settings page\n echo \"To update the API key, go to ChatBot Settings
\";\n \n} catch (Exception $e) {\n echo \"Error: \" . $e->getMessage() . \"\";\n echo \"Current ChatBot Settings:\\n\";\n foreach ($settings as $setting) {\n echo \"- {$setting['name']}: \" . (empty($setting['value']) ? 'Not set' : 'Set') . \"\\n\";\n echo \" Description: {$setting['description']}\\n\";\n }\n echo \"\";\n \n // Add link to settings page\n echo \"To update the API key, go to ChatBot Settings
\";\n \n} catch (Exception $e) {\n echo \"Error: \" . $e->getMessage() . \"| ' . __('Date') . ' | ';\n echo '' . __('User') . ' | ';\n echo '' . __('Action') . ' | ';\n echo '' . __('Subject') . ' | ';\n echo '
|---|---|---|---|
| ' . date('Y-m-d H:i', strtotime($row['timestamp'])) . ' | ';\n echo '' . $row['preferredName'] . ' ' . $row['surname'] . ' | ';\n echo '' . __($row['action']) . ' | ';\n echo '' . $row['subject'] . ' | ';\n echo '
' . __('No recent activity found.') . '
';\n }\n \n // Quick tools\n echo '' . __('AI system is operational.') . '
';\n } else {\n // $errorMessage = __('AI system is not responding correctly.'); // Old error message\n // if (isset($testResponse['error'])) {\n // $errorMessage .= ' Error: ' . htmlspecialchars($testResponse['error']);\n // } else if (isset($testResponse['response']['error']['message'])) {\n // $errorMessage .= ' API Error: ' . htmlspecialchars($testResponse['response']['error']['message']);\n // }\n // echo '' . $errorMessage . '
';\n $errorMessage = __('AI system is not responding correctly. Please check server logs for details.'); // Corrected error message\n echo '' . $errorMessage . '
';\n }\n } catch (Exception $e) {\n echo '' . __('AI system connection error: ') . htmlspecialchars($e->getMessage()) . '
';\n }\n }\n}"}, "030e63497fd5a0ea218107feedd91d649324421f": {"t": 1785756294.2456677, "n": 6285, "h": "e8c8b26454c957d7", "c": ".\n*/\n\nuse Gibbon\\Module\\aiTeacher\\DeepSeekAPI;\n\n// Gibbon includes\nrequire_once __DIR__ . '/../../gibbon.php';\nrequire_once __DIR__ . '/../../functions.php';\n\n// Module includes\nrequire_once __DIR__ . '/moduleFunctions.php';\n\n$page->breadcrumbs->add(__('AI Teacher Assistance'));\n\n// Check if user has access\nif (isActionAccessible($guid, $connection2, '/modules/aiTeacher/index.php') == false) {\n // Access denied\n $page->addError(__('You do not have access to this action.'));\n} else {\n // Get module settings\n $settings = getAITeacherSettings($pdo);\n \n // Check if API key is configured\n if (empty($settings['deepseek_api_key'])) {\n $page->addError(__('DeepSeek API key is not configured. Please contact your administrator.'));\n } else {\n // Display dashboard\n echo '| ' . __('Date') . ' | ';\n echo '' . __('User') . ' | ';\n echo '' . __('Action') . ' | ';\n echo '' . __('Subject') . ' | ';\n echo '
|---|---|---|---|
| ' . date('Y-m-d H:i', strtotime($row['timestamp'])) . ' | ';\n echo '' . $row['preferredName'] . ' ' . $row['surname'] . ' | ';\n echo '' . __($row['action']) . ' | ';\n echo '' . $row['subject'] . ' | ';\n echo '
' . __('No recent activity found.') . '
';\n }\n \n // Quick tools\n echo '' . __('AI system is operational.') . '
';\n } else {\n // $errorMessage = __('AI system is not responding correctly.'); // Old error message\n // if (isset($testResponse['error'])) {\n // $errorMessage .= ' Error: ' . htmlspecialchars($testResponse['error']);\n // } else if (isset($testResponse['response']['error']['message'])) {\n // $errorMessage .= ' API Error: ' . htmlspecialchars($testResponse['response']['error']['message']);\n // }\n // echo '' . $errorMessage . '
';\n $errorMessage = __('AI system is not responding correctly. Please check server logs for details.'); // Corrected error message\n echo '' . $errorMessage . '
';\n }\n } catch (Exception $e) {\n echo '' . __('AI system connection error: ') . htmlspecialchars($e->getMessage()) . '
';\n }\n }\n}"}}, "modules/ChatBot/index.php": {"5eacf702b1d14d58114e1990619ea4913b19ff59": {"t": 1785745776.9634418, "n": 1756, "h": "bae2268379ab7726", "c": "addError($session->get('strAccessDenied'));\n} else {\n // Proceed!\n $page->breadcrumbs->add('AI Teaching Assistant');\n \n // Add module CSS and JS\n $page->stylesheets->add('chatbot', 'modules/ChatBot/css/chatbot.css');\n $page->scripts->add('chatbot', 'modules/ChatBot/js/chatbot.js');\n \n // Get API key from settings\n $apiKey = getSettingByScope($connection2, 'ChatBot', 'deepseek_api_key');\n \n ?>\n❌ No API key found in the database.
\";\n echo \"Please configure the DeepSeek API key in the ChatBot settings.
\";\n } else {\n $maskedKey = substr($apiKey, 0, 4) . str_repeat('*', strlen($apiKey) - 8) . substr($apiKey, -4);\n echo \"✅ API key found in database: $maskedKey
\";\n \n // Get model name\n $modelQuery = $connection2->prepare(\"SELECT value FROM gibbonSetting WHERE scope='ChatBot' AND name='model_name'\");\n $modelQuery->execute();\n $modelResult = $modelQuery->fetch(PDO::FETCH_ASSOC);\n $model = $modelResult ? $modelResult['value'] : 'deepseek-chat';\n \n // Get max tokens\n $tokensQuery = $connection2->prepare(\"SELECT value FROM gibbonSetting WHERE scope='ChatBot' AND name='max_tokens'\");\n $tokensQuery->execute();\n $tokensResult = $tokensQuery->fetch(PDO::FETCH_ASSOC);\n $maxTokens = $tokensResult ? $tokensResult['value'] : '2000';\n \n echo \"Model: $model
\";\n echo \"Max Tokens: $maxTokens
\";\n }\n} catch (PDOException $e) {\n echo \"❌ Database Error: \" . $e->getMessage() . \"
\";\n $apiKey = '';\n}\necho \"Testing connection to DeepSeek API...
\";\n \n // Create a basic curl request to test the API key\n $ch = curl_init('https://api.deepseek.com/v1/chat/completions');\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n curl_setopt($ch, CURLOPT_POST, true);\n curl_setopt($ch, CURLOPT_HTTPHEADER, [\n 'Content-Type: application/json',\n 'Authorization: Bearer ' . $apiKey\n ]);\n \n $data = [\n 'model' => $model,\n 'messages' => [\n ['role' => 'system', 'content' => 'You are a helpful assistant.'],\n ['role' => 'user', 'content' => 'Say hello!']\n ],\n 'max_tokens' => intval($maxTokens)\n ];\n \n curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));\n curl_setopt($ch, CURLOPT_TIMEOUT, 30);\n \n $response = curl_exec($ch);\n $info = curl_getinfo($ch);\n $error = curl_error($ch);\n curl_close($ch);\n \n // Display cURL info\n echo \"\";\n echo \"HTTP Status: \" . $info['http_code'] . \"\\n\";\n echo \"Total time: \" . $info['total_time'] . \" seconds\\n\";\n echo \"Connect time: \" . $info['connect_time'] . \" seconds\\n\";\n echo \"Size download: \" . $info['size_download'] . \" bytes\\n\";\n echo \"\";\n \n if ($error) {\n echo \"
❌ API Connection Error: \" . htmlspecialchars($error) . \"
\";\n } elseif ($info['http_code'] >= 400) {\n echo \"❌ API Error: HTTP Status \" . $info['http_code'] . \"
\";\n $responseData = json_decode($response, true);\n if ($responseData && isset($responseData['error'])) {\n echo \"Error Message: \" . htmlspecialchars($responseData['error']['message']) . \"
\";\n if (isset($responseData['error']['type'])) {\n echo \"Error Type: \" . htmlspecialchars($responseData['error']['type']) . \"
\";\n }\n }\n echo \"Raw Response:
\";\n echo \"\" . htmlspecialchars($response) . \"\";\n } else {\n echo \"
✅ API Connection Successful! HTTP Status \" . $info['http_code'] . \"
\";\n $responseData = json_decode($response, true);\n if ($responseData) {\n echo \"Response received from DeepSeek API!
\";\n if (isset($responseData['choices'][0]['message']['content'])) {\n $aiResponse = $responseData['choices'][0]['message']['content'];\n echo \"AI Response:
\";\n echo \"\" . htmlspecialchars($aiResponse) . \"\";\n }\n if (isset($responseData['usage'])) {\n echo \"
Token Usage:
\";\n echo \"\";\n echo \"Prompt tokens: \" . $responseData['usage']['prompt_tokens'] . \"\\n\";\n echo \"Completion tokens: \" . $responseData['usage']['completion_tokens'] . \"\\n\";\n echo \"Total tokens: \" . $responseData['usage']['total_tokens'] . \"\\n\";\n echo \"\";\n }\n }\n }\n echo \"
This test will attempt to use the same API to send a message using JavaScript (similar to how the chatbot works).
\";\n echo \"❌ No API key found in the database.
\";\n echo \"Please configure the DeepSeek API key in the ChatBot settings.
\";\n } else {\n $maskedKey = substr($apiKey, 0, 4) . str_repeat('*', strlen($apiKey) - 8) . substr($apiKey, -4);\n echo \"✅ API key found in database: $maskedKey
\";\n \n // Get model name\n $modelQuery = $connection2->prepare(\"SELECT value FROM gibbonSetting WHERE scope='ChatBot' AND name='model_name'\");\n $modelQuery->execute();\n $modelResult = $modelQuery->fetch(PDO::FETCH_ASSOC);\n $model = $modelResult ? $modelResult['value'] : 'deepseek-chat';\n \n // Get max tokens\n $tokensQuery = $connection2->prepare(\"SELECT value FROM gibbonSetting WHERE scope='ChatBot' AND name='max_tokens'\");\n $tokensQuery->execute();\n $tokensResult = $tokensQuery->fetch(PDO::FETCH_ASSOC);\n $maxTokens = $tokensResult ? $tokensResult['value'] : '2000';\n \n echo \"Model: $model
\";\n echo \"Max Tokens: $maxTokens
\";\n }\n} catch (PDOException $e) {\n echo \"❌ Database Error: \" . $e->getMessage() . \"
\";\n $apiKey = '';\n}\necho \"Testing connection to DeepSeek API...
\";\n \n // Create a basic curl request to test the API key\n $ch = curl_init('https://api.deepseek.com/v1/chat/completions');\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n curl_setopt($ch, CURLOPT_POST, true);\n curl_setopt($ch, CURLOPT_HTTPHEADER, [\n 'Content-Type: application/json',\n 'Authorization: Bearer ' . $apiKey\n ]);\n \n $data = [\n 'model' => $model,\n 'messages' => [\n ['role' => 'system', 'content' => 'You are a helpful assistant.'],\n ['role' => 'user', 'content' => 'Say hello!']\n ],\n 'max_tokens' => intval($maxTokens)\n ];\n \n curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));\n curl_setopt($ch, CURLOPT_TIMEOUT, 30);\n \n $response = curl_exec($ch);\n $info = curl_getinfo($ch);\n $error = curl_error($ch);\n curl_close($ch);\n \n // Display cURL info\n echo \"\";\n echo \"HTTP Status: \" . $info['http_code'] . \"\\n\";\n echo \"Total time: \" . $info['total_time'] . \" seconds\\n\";\n echo \"Connect time: \" . $info['connect_time'] . \" seconds\\n\";\n echo \"Size download: \" . $info['size_download'] . \" bytes\\n\";\n echo \"\";\n \n if ($error) {\n echo \"
❌ API Connection Error: \" . htmlspecialchars($error) . \"
\";\n } elseif ($info['http_code'] >= 400) {\n echo \"❌ API Error: HTTP Status \" . $info['http_code'] . \"
\";\n $responseData = json_decode($response, true);\n if ($responseData && isset($responseData['error'])) {\n echo \"Error Message: \" . htmlspecialchars($responseData['error']['message']) . \"
\";\n if (isset($responseData['error']['type'])) {\n echo \"Error Type: \" . htmlspecialchars($responseData['error']['type']) . \"
\";\n }\n }\n echo \"Raw Response:
\";\n echo \"\" . htmlspecialchars($response) . \"\";\n } else {\n echo \"
✅ API Connection Successful! HTTP Status \" . $info['http_code'] . \"
\";\n $responseData = json_decode($response, true);\n if ($responseData) {\n echo \"Response received from DeepSeek API!
\";\n if (isset($responseData['choices'][0]['message']['content'])) {\n $aiResponse = $responseData['choices'][0]['message']['content'];\n echo \"AI Response:
\";\n echo \"\" . htmlspecialchars($aiResponse) . \"\";\n }\n if (isset($responseData['usage'])) {\n echo \"
Token Usage:
\";\n echo \"\";\n echo \"Prompt tokens: \" . $responseData['usage']['prompt_tokens'] . \"\\n\";\n echo \"Completion tokens: \" . $responseData['usage']['completion_tokens'] . \"\\n\";\n echo \"Total tokens: \" . $responseData['usage']['total_tokens'] . \"\\n\";\n echo \"\";\n }\n }\n }\n echo \"
This test will attempt to use the same API to send a message using JavaScript (similar to how the chatbot works).
\";\n echo \"| ' . __('Student') . ' | ';\n echo '' . __('Course') . ' | ';\n echo '' . __('Score') . ' | ';\n echo '' . __('AI Recommendation') . ' | ';\n echo '
|---|---|---|---|
| ' . $studentName . ' | ';\n echo '' . $courseName . ' | ';\n echo '' . $score . ' | ';\n echo '';\n echo '';\n echo '';\n echo ' | ';\n echo '
' . __('Please select a course to view students.') . '
';\n }\n} // Closing brace for the isActionAccessible check"}, "030e63497fd5a0ea218107feedd91d649324421f": {"t": 1785756301.1779785, "n": 10762, "h": "8bca3e2420c62479", "c": ".\n*/\n\n// Gibbon includes\nrequire_once __DIR__ . '/../../gibbon.php';\nrequire_once __DIR__ . '/../../functions.php';\n\n// Initialize PDO connection\nglobal $pdo;\nif (!isset($pdo)) {\n $pdo = $connection2 ?? new PDO($dsn, $username, $password);\n}\n\n// Module includes\nrequire_once __DIR__ . '/moduleFunctions.php';\nrequire_once __DIR__ . '/src/DeepSeekAPI.php';\n\n$page->breadcrumbs->add(__('AI Teacher Assistance'), 'index.php');\n$page->breadcrumbs->add(__('Assessment Analysis'));\n\n// Check if user has access\nif (isActionAccessible($guid, $connection2, '/modules/aiTeacher/assessment_analysis.php') == false) {\n // Access denied\n $page->addError(__('You do not have access to this action.'));\n} else {\n // Get module settings\n $settings = getAITeacherSettings($pdo);\n $aiEnabled = !empty($settings['deepseek_api_key']);\n $threshold = isset($_GET['threshold']) ? intval($_GET['threshold']) : 60;\n $selectedCourse = $_GET['course'] ?? '';\n $selectedAssessmentName = $_GET['assessment_name'] ?? ''; // New: Get selected assessment name\n\n // Get list of courses\n $courses = $pdo->executeQuery([], \"SELECT gibbonCourseID, name FROM gibbonCourse ORDER BY name\");\n\n // New: Get list of distinct assessment names\n $assessmentNamesResult = $pdo->executeQuery([], \"SELECT DISTINCT name FROM gibbonInternalAssessmentColumn WHERE name IS NOT NULL AND name <> '' ORDER BY name ASC\");\n $assessmentNames = $assessmentNamesResult->fetchAll(\\PDO::FETCH_COLUMN);\n\n\n // Add some CSS for better visibility\n echo <<| ' . __('Student') . ' | ';\n echo '' . __('Course') . ' | ';\n echo '' . __('Score') . ' | ';\n echo '' . __('AI Recommendation') . ' | ';\n echo '
|---|---|---|---|
| ' . $studentName . ' | ';\n echo '' . $courseName . ' | ';\n echo '' . $score . ' | ';\n echo '';\n echo '';\n echo '';\n echo ' | ';\n echo '
' . __('Please select a course to view students.') . '
';\n }\n} // Closing brace for the isActionAccessible check"}}, "modules/ChatBot/manifest.php": {"5eacf702b1d14d58114e1990619ea4913b19ff59": {"t": 1785745791.6899595, "n": 10090, "h": "c3d9401b445c4b16", "c": ".\n*/\n\n// Basic variables\n$name = 'ChatBot';\n$description = 'AI-powered teaching assistant for teachers';\n$entryURL = 'chatbot.php';\n$type = 'Additional';\n$category = 'Learn';\n$version = '1.0.00';\n$author = 'Asley Smith';\n$url = '';\n\n// Module tables\n$moduleTables = array();\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotFeedback` (\n `id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `user_message` text NOT NULL,\n `ai_response` text NOT NULL,\n `feedback_type` enum('like','dislike') NOT NULL,\n `feedback_text` text,\n `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotTraining` (\n `gibbonChatBotTrainingID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `question` text NOT NULL,\n `answer` text NOT NULL,\n `approved` tinyint(1) NOT NULL DEFAULT '0',\n `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (`gibbonChatBotTrainingID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotCourseMaterials` (\n `gibbonChatBotCourseMaterialsID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `title` varchar(255) NOT NULL,\n `type` varchar(50) NOT NULL,\n `description` text NULL,\n `filePath` varchar(255) NULL,\n `gibbonCourseID` int(8) unsigned zerofill NOT NULL,\n `gibbonSchoolYearID` int(3) unsigned zerofill NOT NULL,\n `dateAdded` date NOT NULL,\n `gibbonPersonIDCreator` int(10) unsigned zerofill NOT NULL,\n PRIMARY KEY (`gibbonChatBotCourseMaterialsID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotStudentProgress` (\n `gibbonChatBotStudentProgressID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `gibbonPersonID` int(10) unsigned zerofill NOT NULL,\n `gibbonCourseID` int(8) unsigned zerofill NOT NULL,\n `gibbonSchoolYearID` int(3) unsigned zerofill NOT NULL,\n `progress` decimal(5,2) NOT NULL DEFAULT '0.00',\n `lastActivity` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`gibbonChatBotStudentProgressID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotStudentAnalytics` (\n `gibbonChatBotStudentAnalyticsID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `gibbonPersonID` int(10) unsigned zerofill NOT NULL,\n `gibbonCourseID` int(8) unsigned zerofill NOT NULL,\n `gibbonSchoolYearID` int(3) unsigned zerofill NOT NULL,\n `analyticsData` text NOT NULL,\n `dateGenerated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (`gibbonChatBotStudentAnalyticsID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotInterventions` (\n `gibbonChatBotInterventionsID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `gibbonPersonID` int(10) unsigned zerofill NOT NULL,\n `gibbonCourseID` int(8) unsigned zerofill NOT NULL,\n `gibbonSchoolYearID` int(3) unsigned zerofill NOT NULL,\n `interventionType` varchar(50) NOT NULL,\n `description` text NOT NULL,\n `status` enum('Active','Completed','Cancelled') NOT NULL DEFAULT 'Active',\n `dateCreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n `dateModified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`gibbonChatBotInterventionsID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n// Module settings\n$gibbonSetting = array();\n$gibbonSetting[] = \"INSERT INTO gibbonSetting (scope, name, nameDisplay, description, value) VALUES ('ChatBot', 'deepseek_api_key', 'DeepSeek API Key', 'API key for DeepSeek AI service', '');\";\n$gibbonSetting[] = \"INSERT INTO gibbonSetting (scope, name, nameDisplay, description, value) VALUES ('ChatBot', 'model_name', 'Model Name', 'DeepSeek model name', 'deepseek-v4-flash');\";\n$gibbonSetting[] = \"INSERT INTO gibbonSetting (scope, name, nameDisplay, description, value) VALUES ('ChatBot', 'max_tokens', 'Max Tokens', 'Maximum number of tokens to generate in responses', '4000');\";\n\n// Action rows\n$actionRows = array();\n\n$actionRows[] = [\n 'name' => 'AI Teaching Assistant',\n 'precedence' => '0',\n 'category' => 'Learning',\n 'description' => 'Access the AI teaching assistant',\n 'URLList' => 'chatbot.php',\n 'entryURL' => 'chatbot.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'Y',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'Y',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'View Student Assessments',\n 'precedence' => '1',\n 'category' => 'Learning',\n 'description' => 'View and analyze student assessment data',\n 'URLList' => 'assessment_integration.php',\n 'entryURL' => 'assessment_integration.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Manage Training',\n 'precedence' => '2',\n 'category' => 'Admin',\n 'description' => 'Manage ChatBot training data',\n 'URLList' => 'training.php,upload.php',\n 'entryURL' => 'training.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Manage ChatBot',\n 'precedence' => '3',\n 'category' => 'Admin',\n 'description' => 'Configure ChatBot settings',\n 'URLList' => 'settings.php',\n 'entryURL' => 'settings.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'N',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'N',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Learning Management',\n 'precedence' => '4',\n 'category' => 'Learning',\n 'description' => 'Manage learning resources and content',\n 'URLList' => 'learning_management.php,learning_management_addProcess.php,learning_management_edit.php,learning_management_delete.php',\n 'entryURL' => 'learning_management.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'AI Learning & Feedback Analytics',\n 'precedence' => '5',\n 'category' => 'Admin',\n 'description' => 'View and analyze ChatBot feedback and AI learning data',\n 'URLList' => 'ai_learning.php',\n 'entryURL' => 'ai_learning.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Feedback Analytics',\n 'precedence' => '6',\n 'category' => 'Admin',\n 'description' => 'View and analyze ChatBot feedback data',\n 'URLList' => 'feedback.php,api/feedback.php',\n 'entryURL' => 'feedback.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Check Feedback Database',\n 'precedence' => '7',\n 'category' => 'Admin',\n 'description' => 'Check and verify ChatBot feedback database status',\n 'URLList' => 'db_check_feedback.php',\n 'entryURL' => 'db_check_feedback.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n// Return module configuration\nreturn [\n 'name' => $name,\n 'version' => $version,\n 'description' => $description,\n 'author' => $author,\n 'url' => $url,\n 'entryURL' => $entryURL,\n 'type' => $type,\n 'category' => $category,\n 'tables' => $moduleTables,\n 'gibbonSettings' => $gibbonSetting,\n 'actionRows' => $actionRows\n];\n"}, "228065060bc341b101409b1b5a4415a502b48a3a": {"t": 1785756293.9305758, "n": 10090, "h": "c3d9401b445c4b16", "c": ".\n*/\n\n// Basic variables\n$name = 'ChatBot';\n$description = 'AI-powered teaching assistant for teachers';\n$entryURL = 'chatbot.php';\n$type = 'Additional';\n$category = 'Learn';\n$version = '1.0.00';\n$author = 'Asley Smith';\n$url = '';\n\n// Module tables\n$moduleTables = array();\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotFeedback` (\n `id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `user_message` text NOT NULL,\n `ai_response` text NOT NULL,\n `feedback_type` enum('like','dislike') NOT NULL,\n `feedback_text` text,\n `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotTraining` (\n `gibbonChatBotTrainingID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `question` text NOT NULL,\n `answer` text NOT NULL,\n `approved` tinyint(1) NOT NULL DEFAULT '0',\n `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (`gibbonChatBotTrainingID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotCourseMaterials` (\n `gibbonChatBotCourseMaterialsID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `title` varchar(255) NOT NULL,\n `type` varchar(50) NOT NULL,\n `description` text NULL,\n `filePath` varchar(255) NULL,\n `gibbonCourseID` int(8) unsigned zerofill NOT NULL,\n `gibbonSchoolYearID` int(3) unsigned zerofill NOT NULL,\n `dateAdded` date NOT NULL,\n `gibbonPersonIDCreator` int(10) unsigned zerofill NOT NULL,\n PRIMARY KEY (`gibbonChatBotCourseMaterialsID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotStudentProgress` (\n `gibbonChatBotStudentProgressID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `gibbonPersonID` int(10) unsigned zerofill NOT NULL,\n `gibbonCourseID` int(8) unsigned zerofill NOT NULL,\n `gibbonSchoolYearID` int(3) unsigned zerofill NOT NULL,\n `progress` decimal(5,2) NOT NULL DEFAULT '0.00',\n `lastActivity` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`gibbonChatBotStudentProgressID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotStudentAnalytics` (\n `gibbonChatBotStudentAnalyticsID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `gibbonPersonID` int(10) unsigned zerofill NOT NULL,\n `gibbonCourseID` int(8) unsigned zerofill NOT NULL,\n `gibbonSchoolYearID` int(3) unsigned zerofill NOT NULL,\n `analyticsData` text NOT NULL,\n `dateGenerated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (`gibbonChatBotStudentAnalyticsID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotInterventions` (\n `gibbonChatBotInterventionsID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `gibbonPersonID` int(10) unsigned zerofill NOT NULL,\n `gibbonCourseID` int(8) unsigned zerofill NOT NULL,\n `gibbonSchoolYearID` int(3) unsigned zerofill NOT NULL,\n `interventionType` varchar(50) NOT NULL,\n `description` text NOT NULL,\n `status` enum('Active','Completed','Cancelled') NOT NULL DEFAULT 'Active',\n `dateCreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n `dateModified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`gibbonChatBotInterventionsID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n// Module settings\n$gibbonSetting = array();\n$gibbonSetting[] = \"INSERT INTO gibbonSetting (scope, name, nameDisplay, description, value) VALUES ('ChatBot', 'deepseek_api_key', 'DeepSeek API Key', 'API key for DeepSeek AI service', '');\";\n$gibbonSetting[] = \"INSERT INTO gibbonSetting (scope, name, nameDisplay, description, value) VALUES ('ChatBot', 'model_name', 'Model Name', 'DeepSeek model name', 'deepseek-v4-flash');\";\n$gibbonSetting[] = \"INSERT INTO gibbonSetting (scope, name, nameDisplay, description, value) VALUES ('ChatBot', 'max_tokens', 'Max Tokens', 'Maximum number of tokens to generate in responses', '4000');\";\n\n// Action rows\n$actionRows = array();\n\n$actionRows[] = [\n 'name' => 'AI Teaching Assistant',\n 'precedence' => '0',\n 'category' => 'Learning',\n 'description' => 'Access the AI teaching assistant',\n 'URLList' => 'chatbot.php',\n 'entryURL' => 'chatbot.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'Y',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'Y',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'View Student Assessments',\n 'precedence' => '1',\n 'category' => 'Learning',\n 'description' => 'View and analyze student assessment data',\n 'URLList' => 'assessment_integration.php',\n 'entryURL' => 'assessment_integration.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Manage Training',\n 'precedence' => '2',\n 'category' => 'Admin',\n 'description' => 'Manage ChatBot training data',\n 'URLList' => 'training.php,upload.php',\n 'entryURL' => 'training.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Manage ChatBot',\n 'precedence' => '3',\n 'category' => 'Admin',\n 'description' => 'Configure ChatBot settings',\n 'URLList' => 'settings.php',\n 'entryURL' => 'settings.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'N',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'N',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Learning Management',\n 'precedence' => '4',\n 'category' => 'Learning',\n 'description' => 'Manage learning resources and content',\n 'URLList' => 'learning_management.php,learning_management_addProcess.php,learning_management_edit.php,learning_management_delete.php',\n 'entryURL' => 'learning_management.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'AI Learning & Feedback Analytics',\n 'precedence' => '5',\n 'category' => 'Admin',\n 'description' => 'View and analyze ChatBot feedback and AI learning data',\n 'URLList' => 'ai_learning.php',\n 'entryURL' => 'ai_learning.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Feedback Analytics',\n 'precedence' => '6',\n 'category' => 'Admin',\n 'description' => 'View and analyze ChatBot feedback data',\n 'URLList' => 'feedback.php,api/feedback.php',\n 'entryURL' => 'feedback.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Check Feedback Database',\n 'precedence' => '7',\n 'category' => 'Admin',\n 'description' => 'Check and verify ChatBot feedback database status',\n 'URLList' => 'db_check_feedback.php',\n 'entryURL' => 'db_check_feedback.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n// Return module configuration\nreturn [\n 'name' => $name,\n 'version' => $version,\n 'description' => $description,\n 'author' => $author,\n 'url' => $url,\n 'entryURL' => $entryURL,\n 'type' => $type,\n 'category' => $category,\n 'tables' => $moduleTables,\n 'gibbonSettings' => $gibbonSetting,\n 'actionRows' => $actionRows\n];\n"}, "030e63497fd5a0ea218107feedd91d649324421f": {"t": 1785756297.511358, "n": 10108, "h": "209bb5889c501a41", "c": ".\n*/\n\n// Basic variables\n$name = 'ChatBot';\n$description = 'AI-powered teaching assistant for teachers';\n$entryURL = 'chatbot.php';\n$type = 'Additional';\n$category = 'Learn';\n$version = '1.0.00';\n$author = 'Asley Smith';\n$url = '';\n\n// Module tables\n$moduleTables = array();\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotFeedback` (\n `id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `user_message` text NOT NULL,\n `ai_response` text NOT NULL,\n `feedback_type` enum('like','dislike') NOT NULL,\n `feedback_text` text,\n `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotTraining` (\n `gibbonChatBotTrainingID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `question` text NOT NULL,\n `answer` text NOT NULL,\n `approved` tinyint(1) NOT NULL DEFAULT '0',\n `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (`gibbonChatBotTrainingID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotCourseMaterials` (\n `gibbonChatBotCourseMaterialsID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `title` varchar(255) NOT NULL,\n `type` varchar(50) NOT NULL,\n `description` text NULL,\n `filePath` varchar(255) NULL,\n `gibbonCourseID` int(8) unsigned zerofill NOT NULL,\n `gibbonSchoolYearID` int(3) unsigned zerofill NOT NULL,\n `dateAdded` date NOT NULL,\n `gibbonPersonIDCreator` int(10) unsigned zerofill NOT NULL,\n PRIMARY KEY (`gibbonChatBotCourseMaterialsID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotStudentProgress` (\n `gibbonChatBotStudentProgressID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `gibbonPersonID` int(10) unsigned zerofill NOT NULL,\n `gibbonCourseID` int(8) unsigned zerofill NOT NULL,\n `gibbonSchoolYearID` int(3) unsigned zerofill NOT NULL,\n `progress` decimal(5,2) NOT NULL DEFAULT '0.00',\n `lastActivity` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`gibbonChatBotStudentProgressID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotStudentAnalytics` (\n `gibbonChatBotStudentAnalyticsID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `gibbonPersonID` int(10) unsigned zerofill NOT NULL,\n `gibbonCourseID` int(8) unsigned zerofill NOT NULL,\n `gibbonSchoolYearID` int(3) unsigned zerofill NOT NULL,\n `analyticsData` text NOT NULL,\n `dateGenerated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (`gibbonChatBotStudentAnalyticsID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n$moduleTables[] = \"\nCREATE TABLE `gibbonChatBotInterventions` (\n `gibbonChatBotInterventionsID` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,\n `gibbonPersonID` int(10) unsigned zerofill NOT NULL,\n `gibbonCourseID` int(8) unsigned zerofill NOT NULL,\n `gibbonSchoolYearID` int(3) unsigned zerofill NOT NULL,\n `interventionType` varchar(50) NOT NULL,\n `description` text NOT NULL,\n `status` enum('Active','Completed','Cancelled') NOT NULL DEFAULT 'Active',\n `dateCreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n `dateModified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`gibbonChatBotInterventionsID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n// Module settings\n$gibbonSetting = array();\n$gibbonSetting[] = \"INSERT INTO gibbonSetting (scope, name, nameDisplay, description, value) VALUES ('ChatBot', 'deepseek_api_key', 'DeepSeek API Key', 'API key for DeepSeek AI service', '');\";\n$gibbonSetting[] = \"INSERT INTO gibbonSetting (scope, name, nameDisplay, description, value) VALUES ('ChatBot', 'model_name', 'Model Name', 'DeepSeek model name (e.g., deepseek-chat)', 'deepseek-chat');\";\n$gibbonSetting[] = \"INSERT INTO gibbonSetting (scope, name, nameDisplay, description, value) VALUES ('ChatBot', 'max_tokens', 'Max Tokens', 'Maximum number of tokens to generate in responses', '4000');\";\n\n// Action rows\n$actionRows = array();\n\n$actionRows[] = [\n 'name' => 'AI Teaching Assistant',\n 'precedence' => '0',\n 'category' => 'Learning',\n 'description' => 'Access the AI teaching assistant',\n 'URLList' => 'chatbot.php',\n 'entryURL' => 'chatbot.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'Y',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'Y',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'View Student Assessments',\n 'precedence' => '1',\n 'category' => 'Learning',\n 'description' => 'View and analyze student assessment data',\n 'URLList' => 'assessment_integration.php',\n 'entryURL' => 'assessment_integration.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Manage Training',\n 'precedence' => '2',\n 'category' => 'Admin',\n 'description' => 'Manage ChatBot training data',\n 'URLList' => 'training.php,upload.php',\n 'entryURL' => 'training.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Manage ChatBot',\n 'precedence' => '3',\n 'category' => 'Admin',\n 'description' => 'Configure ChatBot settings',\n 'URLList' => 'settings.php',\n 'entryURL' => 'settings.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'N',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'N',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Learning Management',\n 'precedence' => '4',\n 'category' => 'Learning',\n 'description' => 'Manage learning resources and content',\n 'URLList' => 'learning_management.php,learning_management_addProcess.php,learning_management_edit.php,learning_management_delete.php',\n 'entryURL' => 'learning_management.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'AI Learning & Feedback Analytics',\n 'precedence' => '5',\n 'category' => 'Admin',\n 'description' => 'View and analyze ChatBot feedback and AI learning data',\n 'URLList' => 'ai_learning.php',\n 'entryURL' => 'ai_learning.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Feedback Analytics',\n 'precedence' => '6',\n 'category' => 'Admin',\n 'description' => 'View and analyze ChatBot feedback data',\n 'URLList' => 'feedback.php,api/feedback.php',\n 'entryURL' => 'feedback.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n$actionRows[] = [\n 'name' => 'Check Feedback Database',\n 'precedence' => '7',\n 'category' => 'Admin',\n 'description' => 'Check and verify ChatBot feedback database status',\n 'URLList' => 'db_check_feedback.php',\n 'entryURL' => 'db_check_feedback.php',\n 'defaultPermissionAdmin' => 'Y',\n 'defaultPermissionTeacher' => 'Y',\n 'defaultPermissionStudent' => 'N',\n 'defaultPermissionParent' => 'N',\n 'defaultPermissionSupport' => 'Y',\n 'categoryPermissionStaff' => 'Y',\n 'categoryPermissionStudent' => 'N',\n 'categoryPermissionParent' => 'N',\n 'categoryPermissionOther' => 'N'\n];\n\n// Return module configuration\nreturn [\n 'name' => $name,\n 'version' => $version,\n 'description' => $description,\n 'author' => $author,\n 'url' => $url,\n 'entryURL' => $entryURL,\n 'type' => $type,\n 'category' => $category,\n 'tables' => $moduleTables,\n 'gibbonSettings' => $gibbonSetting,\n 'actionRows' => $actionRows\n];\n"}}, "modules/ChatBot/simple_api_test.php": {"5eacf702b1d14d58114e1990619ea4913b19ff59": {"t": 1785745793.53718, "n": 7183, "h": "0889cbc57bdce8a3", "c": ".\n*/\n\n// Module includes\nrequire_once '../../gibbon.php';\n\n// Check if core Gibbon functions are available\nif (!function_exists('__') || !function_exists('isActionAccessible')) {\n die('Fatal Error: Gibbon core functions not loaded');\n}\n\n// Import required classes\nuse Gibbon\\Domain\\System\\SettingGateway;\nuse Gibbon\\View\\Page;\n\n// Basic initialization\nif (!isset($container)) {\n die('Fatal Error: Gibbon container not initialized');\n}\n\nif (!isset($guid) || !isset($connection2)) {\n die('Fatal Error: Gibbon core variables not initialized');\n}\n\n// Setup routes - moved outside try block to ensure it's available in catch blocks\n$page = new Page($container, ['address' => $_GET['q'] ?? '']);\n\nif (!$page instanceof Page) {\n die('Fatal Error: Failed to initialize Page object');\n}\n\ntry {\n // Check access\n if (!isActionAccessible($guid, $connection2, '/modules/ChatBot/simple_api_test.php')) {\n // Access denied\n $page->addWarning(__('You do not have access to this action.'));\n return;\n }\n\n // Get session\n $session = $container->get('session');\n\n // Set page breadcrumb\n $page->breadcrumbs\n ->add(__('ChatBot'), 'chatbot.php')\n ->add(__('API Test'));\n\n // Get the API key from settings\n try {\n $settingGateway = $container->get(SettingGateway::class);\n $apiKey = $settingGateway->getSettingByScope('ChatBot', 'deepseek_api_key');\n } catch (Exception $e) {\n $page->addError('Failed to load API key: ' . $e->getMessage());\n return;\n }\n} catch (Exception $e) {\n die('Fatal Error: ' . $e->getMessage());\n}\n\n// Add CSS\necho \"\";\n\n// Page title\necho \"