<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Enhanced ChatGPT UI Clone with Syntax Highlighting</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/default.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
    <script>hljs.highlightAll();</script>
    <style>
    body {
        font-family: 'Söhne', 'ui-sans-serif', 'system-ui', '-apple-system', 'Segoe UI', 'Roboto', 'Ubuntu', 'Cantarell', 'Noto Sans', 'sans-serif';
        background-color: #343541;
        color: #ececf1;
    }
    @keyframes fadeIn {
        from { opacity: 0; transform: translateY(10px); }
        to { opacity: 1; transform: translateY(0); }
    }
    .message-bubble {
        animation: fadeIn 0.3s ease-out;
        max-width: 100%;
        padding: 1.5rem;
        line-height: 1.75;
        display: flex;
        align-items: flex-start;
    }
    .gpt-message { background-color: #444654; }
    .user-message { background-color: #343541; }
    .model-toggle {
        background-color: #40414f;
        color: #ececf1;
        border: 1px solid #565869;
        border-radius: 0.375rem;
        padding: 0.5rem 0.75rem;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: space-between;
        width: 180px;
        transition: background-color 0.2s;
    }
    .model-toggle:hover { background-color: #565869; }
    .model-list {
        position: absolute;
        top: 100%;
        left: 0;
        width: 180px;
        background-color: #40414f;
        border: 1px solid #565869;
        border-radius: 0.375rem;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        z-index: 10;
    }
    .model-list div {
        cursor: pointer;
        padding: 0.5rem 0.75rem;
        transition: background-color 0.2s;
    }
    .model-list div:hover { background-color: #565869; }
    #user-input {
        resize: none;
        overflow-y: hidden;
        background-color: #40414f;
        color: #ececf1;
        border-color: #565869;
    }
    #user-input::placeholder { color: #8e8ea0; }
    .send-button {
        position: absolute;
        bottom: 0.75rem;
        right: 0.75rem;
        padding: 0.25rem;
        background-color: transparent;
        border: none;
        cursor: pointer;
        opacity: 0.7;
        transition: opacity 0.2s;
    }
    .send-button:hover { opacity: 1; }
    ::-webkit-scrollbar { width: 10px; }
    ::-webkit-scrollbar-track { background: #2a2b32; }
    ::-webkit-scrollbar-thumb {
        background: #565869;
        border-radius: 5px;
    }
    ::-webkit-scrollbar-thumb:hover { background: #676980; }
    .avatar {
        width: 30px;
        height: 30px;
        border-radius: 2px;
        margin-right: 1rem;
    }
    .chat-title {
        font-size: 0.875rem;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        max-width: 100%;
    }
    .typing-indicator {
        display: inline-block;
        width: 20px;
        height: 10px;
    }
    .typing-indicator::after {
        content: '...';
        animation: typing 1s infinite;
    }
    @keyframes typing {
        0% { content: '.'; }
        33% { content: '..'; }
        66% { content: '...'; }
    }
    .sidebar-button {
        width: 100%;
        text-align: left;
        padding: 0.75rem;
        border-radius: 0.375rem;
        transition: background-color 0.2s;
    }
    .sidebar-button:hover { background-color: rgba(255, 255, 255, 0.1); }
    .logo {
        width: 32px;
        height: 32px;
        margin-right: 0.5rem;
    }
    .image-upload-button {
        cursor: pointer;
        padding: 0.25rem;
        background-color: transparent;
        border: none;
        opacity: 0.7;
        transition: opacity 0.2s;
    }
    .image-upload-button:hover { opacity: 1; }
    .uploaded-image {
        max-width: 300px;
        max-height: 300px;
        margin-top: 10px;
    }
    pre code.hljs {
        padding: 1em;
        border-radius: 0.5rem;
        margin: 0.5em 0;
    }
    </style>
</head>
<body>
<div class="flex h-screen">
    <!-- Sidebar -->
    <aside class="w-64 bg-[#202123] text-white p-4 flex flex-col">
        <div class="flex-shrink-0 mb-4">
            <button id="new-chat" class="sidebar-button flex items-center">
                <svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-3" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
                New chat
            </button>
        </div>
        <nav id="chat-list" class="flex-1 overflow-y-auto mb-4">
            <!-- Chat history will be dynamically added here -->
        </nav>
        <div class="border-t border-white/20 pt-2">
            <button id="buy-plus" class="sidebar-button flex items-center">
                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4 mr-3">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
                </svg>
                Upgrade to Plus
            </button>
            <button id="toggle-theme" class="sidebar-button flex items-center mt-2">
                <svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-3" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>
                Dark mode
            </button>
            <button id="clear-conversations" class="sidebar-button flex items-center mt-2">
                <svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-3" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>
                Clear conversations
            </button>
        </div>
        <div class="mt-4 flex items-center">
            <img src="https://i.pinimg.com/736x/7a/da/0f/7ada0f01f2d02496cf16d0161f9c9b23.jpg" alt="ChatGPT Logo" class="logo">
            <span class="font-semibold">ChatGPT</span>
        </div>
    </aside>

    <!-- Main Chat Area -->
    <main class="flex-1 flex flex-col bg-[#343541] overflow-hidden">
        <div id="chat-messages" class="flex-1 overflow-y-auto p-4"></div>

        <!-- Input and Model Selection -->
        <div class="w-full p-4 border-t border-white/20 bg-[#343541]">
            <div class="max-w-3xl mx-auto">
                <div class="flex items-center justify-between mb-3">
                    <div class="relative">
                        <button id="toggle-model" class="model-toggle">
                            <span id="model-label">1o-mini</span>
                            <svg class="h-4 w-4 text-gray-400 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>
                        </button>
                        <div id="model-list" class="model-list hidden">
                            <div data-model="1o-mini">1o-mini</div>
                        </div>
                    </div>
                </div>
                <form id="chat-form" class="relative">
                    <textarea id="user-input" class="w-full border rounded-lg p-3 pr-20 focus:outline-none focus:ring-2 focus:ring-[#10a37f]" placeholder="Send a message" rows="1"></textarea>
                    <label for="image-upload" class="image-upload-button absolute right-12 bottom-3">
                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
                            <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z"></path>
                        </svg>
                    </label>
                    <input type="file" id="image-upload" accept="image/*" class="hidden">
                    <button type="submit" class="send-button text-white absolute right-3 bottom-4">
                        <svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>
                    </button>
                </form>
                <div id="uploaded-image-container"></div>
                <p class="text-xs text-center mt-2 text-gray-400">ChatGPT can make mistakes. Consider checking important information.</p>
            </div>
        </div>
    </main>
</div>

<div id="plus-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50">
    <div class="bg-white text-black p-6 rounded-lg max-w-md">
        <h2 class="text-2xl font-bold mb-4">Upgrade to ChatGPT Plus</h2>
        <p class="mb-4">Get access to 1o-preview and other exclusive features! 🚀✨</p>
        <button id="confirm-plus" class="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600">Upgrade Now</button>
        <button id="close-modal" class="ml-2 text-gray-600 hover:text-gray-800">Cancel</button>
    </div>
</div>
<script>
    document.addEventListener('DOMContentLoaded', () => {
    hljs.highlightAll();
    const chatMessages = document.getElementById('chat-messages');
    const chatForm = document.getElementById('chat-form');
    const userInput = document.getElementById('user-input');
    const toggleModel = document.getElementById('toggle-model');
    const modelLabel = document.getElementById('model-label');
    const modelList = document.getElementById('model-list');
    const newChatButton = document.getElementById('new-chat');
    const chatList = document.getElementById('chat-list');
    const clearConversationsButton = document.getElementById('clear-conversations');
    const toggleThemeButton = document.getElementById('toggle-theme');
    const buyPlusButton = document.getElementById('buy-plus');
    const plusModal = document.getElementById('plus-modal');
    const confirmPlusButton = document.getElementById('confirm-plus');
    const closeModalButton = document.getElementById('close-modal');
    const imageUpload = document.getElementById('image-upload');
    const uploadedImageContainer = document.getElementById('uploaded-image-container');

    let currentModel = '1o-mini';
    let isPlus = false;
    let conversations = JSON.parse(localStorage.getItem('conversations')) || [];
    let currentConversationId = null;
    let uploadedImage = null;

    function addMessage(content, isUser = false) {
        const messageDiv = document.createElement('div');
        messageDiv.className = `message-bubble ${isUser ? 'user-message' : 'gpt-message'}`;
        applyHighlight(messageDiv);
        const avatar = document.createElement('img');
        avatar.className = 'avatar';
        avatar.src = isUser ? 'https://ui-avatars.com/api/?name=User&background=random' : 'https://i.pinimg.com/736x/7a/da/0f/7ada0f01f2d02496cf16d0161f9c9b23.jpg';
        avatar.alt = isUser ? 'User Avatar' : 'ChatGPT Avatar';
        
        const innerDiv = document.createElement('div');
        innerDiv.className = 'flex-1';
        
        const formattedContent = processContent(content);
        innerDiv.innerHTML = formattedContent;
        
        messageDiv.appendChild(avatar);
        messageDiv.appendChild(innerDiv);
        chatMessages.appendChild(messageDiv);
        chatMessages.scrollTop = chatMessages.scrollHeight;

        messageDiv.querySelectorAll('pre code').forEach((block) => {
        hljs.highlightBlock(block);
        applyHighlight(messageDiv);
    });

        if (currentConversationId !== null) {
            const conversation = conversations.find(c => c.id === currentConversationId);
            if (conversation) {
                conversation.messages.push({ content, isUser });
                saveConversations();
            }
        }
    }

    function processContent(content) {
    // Substituir marcadores de negrito
    content = content.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
    
    // Substituir marcadores de código inline
    content = content.replace(/`([^`]+)`/g, '<code>$1</code>');
    
    // Substituir blocos de código
    content = content.replace(/```(\w+)?\n([\s\S]*?)```/g, function(match, language, code) {
        // Escape HTML entities in the code
        code = code.replace(/&/g, '&amp;')
                   .replace(/</g, '&lt;')
                   .replace(/>/g, '&gt;')
                   .replace(/"/g, '&quot;')
                   .replace(/'/g, '&#039;');
        
        // Para HTML, usamos 'language-html' em vez de 'language-'
        const languageClass = language === 'html' ? 'language-html' : (language ? `language-${language}` : '');
        
        return `<pre><code class="${languageClass}">${code.trim()}</code></pre>`;
    });
    
    // Substituir quebras de linha
    content = content.replace(/\n/g, '<br>');
    
    return content;
}

// Função para aplicar highlight após adicionar a mensagem
function applyHighlight(messageDiv) {
    messageDiv.querySelectorAll('pre code').forEach((block) => {
        hljs.highlightBlock(block);
    });
}

    function showTypingIndicator() {
        const typingDiv = document.createElement('div');
        typingDiv.className = 'message-bubble gpt-message';
        typingDiv.innerHTML = '<img src="https://i.pinimg.com/736x/7a/da/0f/7ada0f01f2d02496cf16d0161f9c9b23.jpg" alt="ChatGPT Avatar" class="avatar"><div class="typing-indicator"></div>';
        chatMessages.appendChild(typingDiv);
        chatMessages.scrollTop = chatMessages.scrollHeight;
        return typingDiv;
    }

    async function getBotResponse(userMessage, imageData = null) {
        const response = await fetch('/generate', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                userMessage,
                model: currentModel,
                imageData
            }),
        });
        const data = await response.json();
        return data.botResponse;
    }

    function createNewChat() {
        const id = Date.now();
        const title = `New Chat ${conversations.length + 1}`;
        conversations.push({ id, title, messages: [] });
        currentConversationId = id;
        saveConversations();
        updateChatList();
        clearChatMessages();
        addMessage("Hello! I'm ChatGPT. How can I assist you today?");
    }

    function updateChatList() {
        chatList.innerHTML = '';
        conversations.forEach(conv => {
            const chatItem = document.createElement('div');
            chatItem.className = 'p-3 sidebar-button hover:bg-gray-500/10 rounded-lg cursor-pointer mb-1 chat-title';
            chatItem.textContent = conv.title;
            chatItem.dataset.id = conv.id;
            chatItem.addEventListener('click', () => loadConversation(conv.id));
            chatList.appendChild(chatItem);
        });
    }

    function loadConversation(id) {
        currentConversationId = id;
        clearChatMessages();
        const conversation = conversations.find(c => c.id === id);
        if (conversation) {
            conversation.messages.forEach(msg => addMessage(msg.content, msg.isUser));
        }
    }

    function clearChatMessages() {
        chatMessages.innerHTML = '';
    }

    function saveConversations() {
        localStorage.setItem('conversations', JSON.stringify(conversations));
    }

    chatForm.addEventListener('submit', async (e) => {
        e.preventDefault();
        const userMessage = userInput.value.trim();
        if (userMessage || uploadedImage) {
            addMessage(userMessage, true);
            if (uploadedImage) {
                const img = document.createElement('img');
                img.src = uploadedImage;
                img.className = 'uploaded-image';
                chatMessages.lastElementChild.appendChild(img);
            }
            userInput.value = '';
            adjustTextareaHeight();

            const typingIndicator = showTypingIndicator();
            const botResponse = await getBotResponse(userMessage, uploadedImage);
            typingIndicator.remove();
            addMessage(botResponse);

            uploadedImage = null;
            uploadedImageContainer.innerHTML = '';
        }
    });

    toggleModel.addEventListener('click', () => {
        modelList.classList.toggle('hidden');
    });

    modelList.addEventListener('click', (e) => {
        if (e.target.dataset.model) {
            if (e.target.dataset.model === '1o-preview' && !isPlus) {
                alert('1o-preview is only available for Plus members. Please upgrade to access this model.');
            } else {
                currentModel = e.target.dataset.model;
                modelLabel.textContent = e.target.textContent;
                modelList.classList.add('hidden');
            }
        }
    });

    function adjustTextareaHeight() {
        userInput.style.height = 'auto';
        userInput.style.height = userInput.scrollHeight + 'px';
    }

    userInput.addEventListener('input', adjustTextareaHeight);

    document.addEventListener('click', (e) => {
        if (!toggleModel.contains(e.target)) {
            modelList.classList.add('hidden');
        }
    });

    newChatButton.addEventListener('click', createNewChat);

    clearConversationsButton.addEventListener('click', () => {
        conversations = [];
        currentConversationId = null;
        saveConversations();
        updateChatList();
        clearChatMessages();
        addMessage("Conversations cleared. How can I help you today?");
    });

    buyPlusButton.addEventListener('click', () => {
        plusModal.classList.remove('hidden');
    });

    closeModalButton.addEventListener('click', () => {
        plusModal.classList.add('hidden');
    });

    confirmPlusButton.addEventListener('click', () => {
        isPlus = true;
        plusModal.classList.add('hidden');
        buyPlusButton.textContent = 'Plus Member 🌟';
        buyPlusButton.disabled = true;

        const previewOption = document.createElement('div');
        previewOption.dataset.model = '1o-preview';
        previewOption.textContent = '1o-preview';
        modelList.appendChild(previewOption);
    });

    imageUpload.addEventListener('change', (e) => {
        const file = e.target.files[0];
        if (file) {
            const reader = new FileReader();
            reader.onload = (e) => {
                uploadedImage = e.target.result;
                const img = document.createElement('img');
                img.src = uploadedImage;
                img.className = 'uploaded-image';
                uploadedImageContainer.innerHTML = '';
                uploadedImageContainer.appendChild(img);
            };
            reader.readAsDataURL(file);
        }
    });

    updateChatList();
    if (conversations.length === 0) {
        createNewChat();
    } else {
        loadConversation(conversations[conversations.length - 1].id);
    }
});
</script>
</body>
</html>

const express = require('express');
const cors = require('cors');
require('dotenv').config();
const { GoogleGenerativeAI } = require('@google/generative-ai');

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware
app.use(cors());
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'));

// Inicializa os modelos
const genAI = new GoogleGenerativeAI(process.env.API_KEY);
const modelMini = genAI.getGenerativeModel({ model: 'gemini-1.0-pro' });
const modelPreview = genAI.getGenerativeModel({ model: 'gemini-1.5-flash' });

// Rotas
app.get('/', (req, res) => {
  res.sendFile(__dirname + '/public/index.html');
});

app.get('/test', (req, res) => {
  res.sendFile(__dirname + '/public/test.html');
});

// Função para criar prompts específicos para cada modelo
function createPrompt(userMessage, model) {
  const greeting = model === '1o-preview' 
    ? "Olá! Sou seu assistente aqui para ajudar."
    : "Oi! Estou aqui para ajudar com qualquer dúvida que você tenha.";
  
  const guidelines = `
  Vou seguir estas diretrizes:
  1. Responder de forma concisa e eficaz.
  2. Evitar mencionar marcas ou entidades externas.
  3. Utilizar uma linguagem amigável e acessível.
  4. Ao criar blocos de código, sempre usar três acentos graves (''') para iniciar e fechar o bloco, seguidos pelo nome da linguagem. Por exemplo:
     Para HTML:
     '''html
     <seu-codigo-html-aqui>
     '''
     Para JavaScript:
     '''javascript
     // seu código JavaScript aqui
     '''
     Para outros tipos de código, substituir 'html' ou 'javascript' pela linguagem apropriada.
  5. Nunca usar dois acentos graves (\`\`) para blocos de código. Sempre usar três (''').
  6. Para código inline, usar um único acento grave de cada lado, como \`codigo\`.
  `;

  return `${greeting} ${guidelines}\nEntão, por favor, me conte: "${userMessage}"`;
}

// Rota para gerar resposta
app.post('/generate', async (req, res) => {
  const { userMessage, model, imageData } = req.body;

  // Verifica se a entrada é válida
  if (!userMessage && !imageData) {
    return res.status(400).json({ error: 'No input provided.' });
  }

  try {
    const selectedModel = model === '1o-preview' ? modelPreview : modelMini;
    const maxTokens = model === '1o-preview' ? 4000 : 1000;

    let parts = [{ text: createPrompt(userMessage, model) }];

    // Adiciona os dados da imagem, se disponíveis
    if (imageData) {
      parts.push({
        inlineData: {
          data: imageData.split(',')[1],
          mimeType: 'image/jpeg',
        },
      });
    }

    // Gera o conteúdo com o modelo selecionado
    const result = await selectedModel.generateContent({
      contents: [{ role: 'user', parts }],
      generationConfig: { maxOutputTokens: maxTokens },
    });

    const textResponse = result.response.text();
    res.json({ botResponse: textResponse });
  } catch (error) {
    console.error('Error generating response:', error);
    res.status(500).json({ error: 'Error generating AI response.' });
  }
});

// Inicia o servidor
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

quando vc pede para ele geerar uym codigo html fica assim
"oi
ChatGPT Avatar
Olá! Fico feliz em ajudar.
User Avatar
faz um codigo html simples
ChatGPT Avatar
``html






Olá, mundo!

Este é um parágrafo de texto simples.




``
"

ta vendo fica `` em vez de  ```, parece q ele n entende oq seria codigo mesmo codigo html e tal arruma ae.