{"id":27369925,"url":"https://github.com/carlos-bonfim26/chatbot_js","last_synced_at":"2026-04-30T15:31:05.271Z","repository":{"id":287640195,"uuid":"964811183","full_name":"Carlos-bonfim26/ChatBot_JS","owner":"Carlos-bonfim26","description":"🤖 ChatBot com API Gemini – Um assistente inteligente que conversa com você, entende mensagens com imagens e até responde com estilo! 💬 Digite, envie, adicione emojis 😄 ou imagens 🖼️ e veja o bot responder com a tecnologia da IA do Google (Gemini).","archived":false,"fork":false,"pushed_at":"2025-04-13T01:30:26.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-13T02:25:34.533Z","etag":null,"topics":["api","chatbot","css","gemini-api","google-gemini-api","html","javascript"],"latest_commit_sha":null,"homepage":"https://carlos-bonfim26.github.io/ChatBot_JS/","language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Carlos-bonfim26.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-11T20:34:40.000Z","updated_at":"2025-04-13T01:32:42.000Z","dependencies_parsed_at":"2025-04-13T02:25:36.846Z","dependency_job_id":"a1b994c2-77c9-4ce9-9c8d-cc4e49016448","html_url":"https://github.com/Carlos-bonfim26/ChatBot_JS","commit_stats":null,"previous_names":["carlos-bonfim26/chatbot_js"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Carlos-bonfim26%2FChatBot_JS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Carlos-bonfim26%2FChatBot_JS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Carlos-bonfim26%2FChatBot_JS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Carlos-bonfim26%2FChatBot_JS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Carlos-bonfim26","download_url":"https://codeload.github.com/Carlos-bonfim26/ChatBot_JS/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248681497,"owners_count":21144700,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","chatbot","css","gemini-api","google-gemini-api","html","javascript"],"created_at":"2025-04-13T08:11:37.134Z","updated_at":"2026-04-30T15:31:05.238Z","avatar_url":"https://github.com/Carlos-bonfim26.png","language":"CSS","funding_links":[],"categories":[],"sub_categories":[],"readme":"[GEMINI_BADGE]:https://img.shields.io/badge/Google%20Gemini-8E75B2?style=for-the-badge\u0026logo=googlegemini\u0026logoColor=white\n[CSS_BADGE]:https://img.shields.io/badge/CSS3-1572B6?style=for-the-badge\u0026logo=css3\u0026logoColor=white\n[HTML_BADGE]:https://img.shields.io/badge/HTML5-E34F26?style=for-the-badge\u0026logo=html5\u0026logoColor=white\n[JAVASCRIPT_BADGE]:https://img.shields.io/badge/JavaScript-323330?style=for-the-badge\u0026logo=javascript\u0026logoColor=F7DF1E\n# ChatBot\n\n![HTML][HTML_BADGE]\n![CSS][CSS_BADGE]\n![JAVASCRIPT][JAVASCRIPT_BADGE]\n![GEMINI][GEMINI_BADGE]\n\n## Inspiração\n\nO projeto não é originalmente meu, apenas alguns ajustos para o meu código, mas o original desse [vídeo](https://youtu.be/B21G6tUI4L0?si=h4Tgu4C1vjv0M1TU) do canal [CodingNepal.](https://www.youtube.com/@CodingNepal)\n\n## por que fiz? \n\nApenas para testar minhas habilidades e ver aumentar meu aprendizado sobre javascript e aplicação de API.\n\n## API usada\n\nutilizei a API do Google Gemini, mas especificadamente a parte de geração de texto, aqui o link da documentação [https://ai.google.dev/gemini-api/docs?hl=pt-br](https://ai.google.dev/gemini-api/docs?hl=pt-br)\n\n## Indo ao Código 💻\n\nO HTML e o CSS eu não irei explicar, apenas algumas funções do Javascript, inclusive texte o chatbot por favor: [https://carlos-bonfim26.github.io/ChatBot_JS/](https://carlos-bonfim26.github.io/ChatBot_JS/)\n\n### 🔁 Ciclo da Mensagem\n\n1. Usuário digita e envia a mensagem (com ou sem imagem);\n2. A mensagem é exibida no chat;\n3. O bot simula um carregamento (\"pensando...\");\n4. A requisição é feita para a API Gemini;\n5. A resposta gerada é exibida no chat;\n6. O histórico da conversa é salvo para manter o contexto.\n\n## 📌 Principais Funções\n\n### Geração da resposta\n\nEssa é a principal função para o funcionamento da API, tendo as requisições, tratamento de erros, salvamento de contexto, como vem dizendo nos próprios comentários, sendo uma função complexa e nada génerica.\n\n```bash\n\nconst generateBotResponse = async (incomingMessageDiv)=\u003e{\nconst messageElement = incomingMessageDiv.querySelector('.messageBot .textMessage');\nchatHistory.push({\n    //para manter o contexto da conversa puxa informações das mensagens anteriores com o usuário\n    role: \"user\",\n    parts: [{text: userData.message}, ...(userData.file.data? [{inline_data: userData.file}]: [])]\n})\n\n    //api requisição de opções\nconst requestOptions = {\n    method: 'POST',\n    Headers: {\n        \"Content-Type\": \"application/json\"},\n    body: JSON.stringify({\n        contents:chatHistory\n    })\n} \ntry {\n   const response = await fetch(API_URL, requestOptions ) \n   const data = await response.json();\n   if(!response.ok) throw new Error(data.error.message);\n\n\n//extração da resposta do bot para texto na tela\n   const apiResponseText = data.candidates[0].content.parts[0].text.replace(/\\*\\*(.*?)\\*\\*/g, \"$1\").trim();\n   messageElement.innerHTML = apiResponseText;\n\n   //puxa as informações da API\n   chatHistory.push({\n    role: \"model\",\n    parts: [{text: apiResponseText}]\n})\n} catch (error) {\n    //tratamento de erro\n    console.log(error);\n    messageElement.innerText = \"Desculpe mas ouve um erro na requisição, tente novamente mais tarde!\";\n    messageElement.style.color = \"red\";\n} finally{\n    //reseta e tira a foto bo bot\n    userData.file = {};\n    incomingMessageDiv.classList.remove('thinking-indicator');\n    chatBody.scrollTo({top: chatBody.scrollHeight, behavior: \"smooth\"});\n}\n}\n\n```\n\n### User data e váriaveis da API\n\nuse o link e a sua chave pessoal, o meu não funcionará no seu código, ele será fornecida lá no mesmo documento da documentação da API\n\n``` bash\n\nconst userData ={\n    message :null,\n    file:{\n        data:null,\n        mime_type:null,\n    }\n}\n\nconst chatHistory = [];\n\n//variaveis para a API, use o link e a sua chave pessoal, o meu não funcionará no seu código\nconst API_KEY = \"AIzaSyCKuk2AnaOgcCvS1zd2g-xwNtNwUQRHLxs\";\nconst API_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${API_KEY}`\n\n```\n### Criação de Elementos\n\nA criação dos blocos de mensagem é via JS sendo necessário os parâmetros de conteúdo para fornecer a mensagem e as classes para diferencias de uma mensagem do usuário e do chat\n\n``` bash\n\nconst createMessageElement = (content, ...classes) =\u003e {\nconst div = document.createElement('div');\ndiv.classList.add(\"message\", classes);\nif(div.classList.contains(\"messageBot\")){\n    const roboBot = document.createElement('div');\n    roboBot.classList.add('robochat');\n    roboBot.innerHTML = `\u003ci class=\"fa-solid fa-robot\"\u003e\u003c/i\u003e` \n    div.appendChild(roboBot);\n}\nconst text = document.createElement('div');\ntext.classList.add('textMessage');\ntext.innerHTML = content;\n\ndiv.appendChild(text);\n\nreturn div;\n}\n\n```\n\n## 📤 Enviar Imagens\n\nUma das partes essencias para o envio de imagens na aplicaçao está aqui\n\n``` bash\n\nconst handleOutgoingMessage = (e) =\u003e{\n    e.preventDefault();\n   userData.message = inputUser.value.trim();\n    inputUser.value = \"\";\n    fileUploadWrapper.classList.remove('file-uploaded');\n\n    // enviar imagens\n    const messageContent = `\n  ${userData.message}\n  ${userData.file.data ? `\u003cimg src=\"data:${userData.file.mime_type};base64,${userData.file.data}\" alt=\"file\" class=\"imgFileUChat\" /\u003e` : \"\"}\n`; \n// a função continua...\n\n```\n## ✍️ enviar mensagem\n\n### via enter \n\n``` bash\n\ninputUser.addEventListener('keydown', (e)=\u003e{\nconst userMsg = e.target.value.trim();\nif(e.key === 'Enter' \u0026\u0026 userMsg ){\n    handleOutgoingMessage(e);\n}\n\n})\n```\n### via input/button\n``` bash\n\nfileInput.addEventListener('change', ()=\u003e{\n    const file = fileInput.files[0];\n    if(!file) return;\n\n    const reader = new FileReader();\n    reader.onload = (e) =\u003e {\n\nfileUploadWrapper.querySelector('img').src = e.target.result;\n\nfileUploadWrapper.classList.add('file-uploaded');\nconst base64String = e.target.result.split(',')[1];\n\n        userData.file ={\n            data:base64String,\n            mime_type:file.type\n        }\n\n        fileInput.value= \"\";\n    }\n  console.log(\"arquivo enviado\", userData.file);\n    reader.readAsDataURL(file);\n})\n\n```\n\n### ❌ Cancelar mensagem\n\n``` bash\nfileCancelButton.addEventListener('click', ()=\u003e{\n\n    userData.file ={};\n    fileUploadWrapper.classList.remove('file-uploaded');\n})\n```\n\n### 😊 enviar emoji\n\n``` bash\n\nconst picker = new EmojiMart.Picker({\ntheme: \"light\",\nskinTonePosition: \"none\",\npreviewPosition: \"none\",\nonEmojiSelect:(emoji) =\u003e{\n    const{selectionStart: start, selectionEnd: end} = inputUser;\n    inputUser.setRangeText(emoji.native, start, end, \"end\");\n    inputUser.focus();\n},\nonClickOutside: (e)=\u003e{\n    if(e.target.id == \"emoji-btn\"){\n        document.body.classList.toggle('emoji-open');\n    }else{\n        document.body.classList.remove('emoji-open');\n    }\n}\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlos-bonfim26%2Fchatbot_js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcarlos-bonfim26%2Fchatbot_js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlos-bonfim26%2Fchatbot_js/lists"}