function escapeHtml(text) {
const tempElement = document.createElement('div');
tempElement.textContent = text;
return tempElement.innerHTML;
}
function unescapeHtml(html) {
const tempElement = document.createElement('div');
tempElement.innerHTML = html;
return tempElement.textContent;
}
document.addEventListener('DOMContentLoaded', () => {
const messageInput = document.getElementById('message-input');
const sendButton = document.getElementById('send-button');
const chatMessages = document.getElementById('chat-messages');
const apiKey = 'AIzaSyCfpz9Ll9A5vuyEUKNq0IhbcZ8sTHX8yS8';
const apiUrl = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=' + apiKey;
const SYSTEM_INSTRUCTION = `Ты — UnixMini, чат-бот, разработанный UnixAI. Ты являешься вежливым, профессиональным и полезным помощником для пользователей.
Твои Цели:
1. Понимание и решение задач: Внимательно анализируй запросы пользователей и предоставляй точные, полные и полезные ответы. Если запрос неоднозначен, задавай уточняющие вопросы.
2. Поддержка и упрощение процессов: Помогай пользователям решать задачи, предоставляя необходимую информацию, инструкции и рекомендации. Стремись упрощать сложные вопросы, делая их более понятными.
3. Вежливость и профессионализм: Всегда общайся вежливо и дружелюбно. Поддерживай нейтральную позицию в обсуждениях и избегай обсуждения чувствительных тем.
4. Точность и ясность: Предоставляй информацию в ясной, точной и понятной форме. Избегай использования жаргона и сложных терминов без пояснений.
5. Ограничения:
Не обсуждай темы, которые носят 18+ характер, являются оскорбительными или вызывают споры.
Если запрос выходит за рамки твоей компетенции, вежливо уведомляй об этом и предлагай пользователю сменить тему.
Не распространяй ложную или вводящую в заблуждение информацию.
Формат ответов:
Форматируй текст в MarkdownV2.
Используй * для выделения *жирного шрифта*.
Используй \\n для переноса строки.
Используй \`\`\`language для выделения \`кода\` с указанием языка.
Стремись к лаконичности, но не за счет ясности и точности.
В конце каждого ответа ставь смайлик 😊.
Обратная связь:
Если необходимо, спрашивай у пользователя дополнительную информацию.
Помни, что твоя цель — быть удобным и полезным помощником, который экономит время и упрощает жизнь пользователя.
Помни, что ты был разработан и обучен UnixAI.`;
let chatHistory = [];
const MAX_HISTORY_LENGTH = 5;
let isSending = false;
sendButton.addEventListener('click', () => {
if (isSending) {
return;
}
const messageText = messageInput.value.trim();
if (messageText) {
addMessage('user', messageText);
messageInput.value = '';
sendToGemini(messageText);
}
});
messageInput.addEventListener('keypress', (event) => {
if (event.key === 'Enter') {
sendButton.click()
event.preventDefault()
}
});
function addMessage(sender, message) {
const messageElement = document.createElement('div');
messageElement.classList.add('message');
if (sender === 'user') {
messageElement.classList.add('user-message');
messageElement.textContent = message;
}
if (sender === 'ai') {
messageElement.innerHTML = ``;
}
chatMessages.appendChild(messageElement);
setTimeout(() => {
messageElement.classList.add('show')
}, 10);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
async function sendToGemini(message) {
isSending = true;
sendButton.disabled = true;
addMessage('ai', '');
chatHistory.push({ role: 'user', parts: [{ text: message }] });
if (chatHistory.length > MAX_HISTORY_LENGTH) {
chatHistory.shift();
}
try {
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
contents: [
{
parts: [{ text: SYSTEM_INSTRUCTION }],
role: "user"
},
...chatHistory,
],
}),
});
if (!response.ok) {
const errorData = await response.json();
console.error('Gemini API Error:', errorData);
let errorMessage = `Произошла ошибка при обращении к серверу.`;
if (errorData && errorData.error && errorData.error.message) {
errorMessage += ` Причина: ${errorData.error.message}`;
}
const lastAiMessage = chatMessages.lastElementChild;
if (lastAiMessage) {
lastAiMessage.querySelector('.message-text').textContent = errorMessage;
lastAiMessage.querySelector('.typing-indicator').remove()
}
return;
}
const data = await response.json();
console.log(data);
const aiResponse = data.candidates[0].content.parts[0].text;
chatHistory.push({ role: 'model', parts: [{ text: aiResponse }] });
if (chatHistory.length > MAX_HISTORY_LENGTH) {
chatHistory.shift();
}
const formattedResponse = formatMarkdown(aiResponse);
const lastAiMessage = chatMessages.lastElementChild;
if(lastAiMessage) {
lastAiMessage.querySelector('.message-text').innerHTML = formattedResponse;
lastAiMessage.querySelector('.typing-indicator').remove()
}
}
catch (error) {
console.error('Error sending to Gemini:', error);
const lastAiMessage = chatMessages.lastElementChild;
if (lastAiMessage) {
lastAiMessage.querySelector('.message-text').textContent = 'Произошла ошибка при обращении к серверу';
lastAiMessage.querySelector('.typing-indicator').remove()
}
} finally {
isSending = false;
sendButton.disabled = false;
}
}
function formatMarkdown(text) {
const escapedText = escapeHtml(text);
const formattedText = escapedText.replace(/\*(.*?)\*/g, '$1')
.replace(/\\n/g, '
')
.replace(/```(\w+)?\n?(.*?)```/gs, (match, language, code) => {
const lang = language ? language.trim() : 'code';
const unescapedCode = unescapeHtml(code);
return `
`; }); return formattedText; } chatMessages.addEventListener('click', (event) => { if (event.target.closest('.copy-button')) { const button = event.target.closest('.copy-button'); const codeElement = button.previousElementSibling; const code = codeElement.textContent; navigator.clipboard.writeText(code) .then(() => { button.classList.add('copied'); setTimeout(() => { button.classList.remove('copied'); }, 2000); }) .catch(err => { console.error('Не удалось скопировать текст: ', err); button.textContent = 'Ошибка'; setTimeout(() => { }, 2000); }); } }); hljs.highlightAll(); });${lang}${escapeHtml(unescapedCode.trim())}