├── .env.example ├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── index.js ├── package.json ├── prompt_template.js └── replies.js /.env.example: -------------------------------------------------------------------------------- 1 | GEMINI_API_KEY=your_api_key_here 2 | GREETING_IMAGE_URL=https://contoh.jpg 3 | PAYMENT_IMAGE_URL=https://contoh.jpg -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .env -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Wimboro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 📲 WhatsApp Chatbot with Gemini AI & Time API 2 | 3 | This is a **WhatsApp chatbot** that integrates **Google Gemini AI**, **whatsapp-web.js**, and **timeapi.io** to provide intelligent responses, handle customer inquiries, and display real-time Jakarta time. 4 | 5 | --- 6 | 7 | ## 🚀 Features 8 | 9 | ✅ **AI-Powered Responses** – Uses **Google Gemini AI** for smart replies. 10 | ✅ **WhatsApp Automation** – Built with **whatsapp-web.js**. 11 | ✅ **Real-Time Time API** – Fetches **current time in Jakarta (GMT+7)** from **timeapi.io**. 12 | ✅ **Automated Customer Support** – Handles FAQs, greetings, and payments. 13 | ✅ **Dynamic Image URLs** – Stores greeting and payment image URLs in **.env**. 14 | 15 | --- 16 | 17 | ## 🛠️ Installation 18 | 19 | ### 1️⃣ **Clone the Repository** 20 | ```bash 21 | git clone https://github.com/wimboro/wa-bot-Gemini-AI.git 22 | cd wa-bot-Gemini-AI 23 | ``` 24 | 25 | ### 2️⃣ **Install Dependencies** 26 | ```bash 27 | npm install 28 | ``` 29 | 30 | ### 3️⃣ **Setup `.env` File** 31 | Create a `.env` file and add: 32 | ```env 33 | GEMINI_API_KEY=your_gemini_api_key 34 | GREETING_IMAGE_URL=https://your-image-url.com/greeting.jpg 35 | PAYMENT_IMAGE_URL=https://your-image-url.com/payment.jpg 36 | ``` 37 | 38 | ### 4️⃣ **Configure `replies.js`** 39 | Edit `replies.js` to customize bot responses: 40 | 41 | ```javascript 42 | module.exports = { 43 | greetingsCaption: "Your custom greeting caption here.", 44 | paymentCaption: "" 45 | }, 46 | stopMessage: "Bot berhenti. Ketik \"lanjut\" untuk melanjutkan.", 47 | continueMessage: "Bot telah dilanjutkan. Bagaimana saya bisa membantu Anda?", 48 | continuePrompt: "Anda terhubung dengan asisten otomatis. Ketik \"stop\" untuk berhenti atau abaikan untuk melanjutkan.", 49 | defaultMessage: "Maaf, saya tidak mengerti pertanyaan Anda. Silakan coba lagi atau hubungi customer service kami.", 50 | optionResponses: { 51 | 1: "", 52 | 2: "", 53 | 3: "", 54 | 4: "", 55 | 5: "" 56 | } 57 | }; 58 | ``` 59 | 60 | ### 5️⃣ **Customize `prompt_template.js`** 61 | Edit `prompt_template.js` to customize AI prompt behavior: 62 | 63 | ```javascript 64 | const emeteraiPromptTemplate = ` 65 | 66 | Current Date & Time: {current_time} 67 | 68 | User question: {user_question} 69 | 70 | Your response: 71 | `; 72 | 73 | module.exports = emeteraiPromptTemplate; 74 | ``` 75 | 76 | ### 6️⃣ **Run the Bot** 77 | ```bash 78 | node index.js 79 | ``` 80 | Scan the QR code displayed in the terminal to authenticate your WhatsApp. 81 | 82 | --- 83 | 84 | ## 📌 Usage 85 | 86 | ### 🔹 **Basic Commands** 87 | - `halo`, `assalamualaikum`, `selamat` → Sends a greeting with an image. 88 | - `pembayaran`, `bayar` → Sends a payment QR code. 89 | - `bantuan` → Displays available options. 90 | - `stop` → Stops bot responses. 91 | - `lanjut` → Resumes bot responses. 92 | 93 | ### 🔹 **AI-Powered Responses** 94 | - The bot uses **Google Gemini AI** to generate responses for general questions about **E-meterai**. 95 | - If a user asks for the current time, the bot fetches the **real-time Jakarta time (GMT+7)** from **timeapi.io** and responds accordingly. 96 | 97 | --- 98 | 99 | ## 🔧 Project Structure 100 | 101 | ``` 102 | 📂 wa-bot-Gemini-AI/ 103 | │── 📜 index.js # Main bot logic 104 | │── 📜 replies.js # Predefined bot responses 105 | │── 📜 prompt_template.js # AI prompt structure 106 | │── 📜 .env # API keys and configurations 107 | │── 📜 package.json # Node.js dependencies 108 | │── 📜 README.md # Project documentation 109 | ``` 110 | 111 | --- 112 | 113 | ## 🔥 Dependencies 114 | 115 | - [whatsapp-web.js](https://github.com/pedroslopez/whatsapp-web.js) – WhatsApp automation 116 | - [dotenv](https://www.npmjs.com/package/dotenv) – Manages environment variables 117 | - [axios](https://www.npmjs.com/package/axios) – Handles HTTP requests (for **timeapi.io**) 118 | - [GoogleGenerativeAI](https://www.npmjs.com/package/@google/generative-ai) – Gemini AI integration 119 | - [qrcode-terminal](https://www.npmjs.com/package/qrcode-terminal) – Displays QR code in terminal 120 | 121 | --- 122 | 123 | ## 🤝 Contributing 124 | 125 | 1. Fork this repository. 126 | 2. Create a new branch: `git checkout -b feature-branch`. 127 | 3. Commit changes: `git commit -m "Added a new feature"`. 128 | 4. Push your branch: `git push origin feature-branch`. 129 | 5. Open a Pull Request. 130 | 131 | --- 132 | 133 | ## 📜 License 134 | 135 | This project is licensed under the **MIT License**. 136 | 137 | --- 138 | 139 | ## 📞 Contact 140 | 141 | 📧 Email: wgp.pra@gmail.com 142 | 🐦 Twitter: [@galasaktii](https://twitter.com/galasaktii) 143 | 📌 GitHub: [wimboro](https://github.com/wimboro) 144 | 145 | --- -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const axios = require('axios'); 3 | const { Client, LocalAuth, MessageMedia } = require('whatsapp-web.js'); 4 | const qrcode = require('qrcode-terminal'); 5 | const { GoogleGenerativeAI } = require("@google/generative-ai"); 6 | const replies = require('./replies'); 7 | const emeteraiPromptTemplate = require('./prompt_template'); 8 | 9 | const GEMINI_API_KEY = process.env.GEMINI_API_KEY; 10 | const GREETING_IMAGE_URL = process.env.GREETING_IMAGE_URL; 11 | const PAYMENT_IMAGE_URL = process.env.PAYMENT_IMAGE_URL; 12 | 13 | const genAI = new GoogleGenerativeAI(GEMINI_API_KEY); 14 | 15 | const client = new Client({ 16 | authStrategy: new LocalAuth(), 17 | puppeteer: { args: ['--no-sandbox'] } 18 | }); 19 | 20 | const userStates = {}; 21 | 22 | // ✅ Function to get the current time using timeapi.io 23 | async function getCurrentTime() { 24 | try { 25 | const response = await axios.get('https://timeapi.io/api/Time/current/zone?timeZone=Asia/Jakarta'); 26 | const { date, time } = response.data; 27 | return `${date} ${time}`; // Format: "YYYY-MM-DD HH:mm:ss" 28 | } catch (error) { 29 | console.error('Error fetching current time:', error); 30 | return 'Unable to fetch time.'; 31 | } 32 | } 33 | 34 | // Generate AI response using Gemini with current time from API 35 | async function getGeminiResponse(userQuestion) { 36 | try { 37 | const currentTime = await getCurrentTime(); 38 | 39 | const fullPrompt = emeteraiPromptTemplate 40 | .replace('{user_question}', userQuestion) 41 | .replace('{current_time}', currentTime); 42 | 43 | const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flash' }); 44 | const result = await model.generateContent(fullPrompt); 45 | 46 | return result.response.text(); 47 | } catch (error) { 48 | console.error('Error generating AI response:', error); 49 | return null; 50 | } 51 | } 52 | 53 | client.on('qr', qr => qrcode.generate(qr, { small: true })); 54 | client.on('ready', () => console.log('✅ Client ready!')); 55 | 56 | client.on('message', async message => { 57 | if (!message.from.includes('@c.us')) return; 58 | 59 | const text = message.body.toLowerCase(); 60 | const userId = message.from; 61 | 62 | if (!userStates[userId]) userStates[userId] = { active: true }; 63 | 64 | if (text === 'stop') { 65 | userStates[userId].active = false; 66 | return client.sendMessage(userId, replies.stopMessage); 67 | } 68 | 69 | if (text === 'lanjut') { 70 | userStates[userId].active = true; 71 | return client.sendMessage(userId, replies.continueMessage); 72 | } 73 | 74 | if (!userStates[userId].active) return; 75 | 76 | if (['halo', 'selamat', 'assalamualaikum'].some(greet => text.includes(greet))) { 77 | const media = await MessageMedia.fromUrl(GREETING_IMAGE_URL); 78 | return client.sendMessage(userId, media, { caption: replies.greetingsCaption }); 79 | } 80 | 81 | if (['pembayaran', 'bayar'].some(pay => text.includes(pay))) { 82 | const paymentMedia = await MessageMedia.fromUrl(PAYMENT_IMAGE_URL); 83 | return client.sendMessage(userId, paymentMedia, { caption: replies.paymentCaption }); 84 | } 85 | 86 | if (!isNaN(text) && text >= 1 && text <= 6) { 87 | if (parseInt(text) === 6) { 88 | const paymentMedia = await MessageMedia.fromUrl(PAYMENT_IMAGE_URL); 89 | return client.sendMessage(userId, paymentMedia, { caption: replies.paymentCaption }); 90 | } else { 91 | return client.sendMessage(userId, replies.optionResponses[parseInt(text)]); 92 | } 93 | } 94 | 95 | if (text === 'bantuan') { 96 | return client.sendMessage(userId, replies.options); 97 | } 98 | 99 | const aiResponse = await getGeminiResponse(message.body); 100 | if (aiResponse && aiResponse.length > 10) { 101 | await client.sendMessage(userId, aiResponse); 102 | } else { 103 | await client.sendMessage(userId, replies.defaultMessage); 104 | } 105 | 106 | if (userStates[userId].active) { 107 | await client.sendMessage(userId, replies.continuePrompt); 108 | } 109 | }); 110 | 111 | client.initialize(); 112 | 113 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wa-bot-gemini-ai", 3 | "version": "1.2.0", 4 | "description": "Bot WA AI", 5 | "keywords": [ 6 | "WhatsApp", 7 | "AI", 8 | "bot" 9 | ], 10 | "homepage": "https://github.com/wimboro/wa-bot-Gemini-AI#readme", 11 | "bugs": { 12 | "url": "https://github.com/wimboro/wa-bot-Gemini-AI/issues" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/wimboro/wa-bot-Gemini-AI.git" 17 | }, 18 | "license": "ISC", 19 | "author": "wimboro", 20 | "type": "commonjs", 21 | "main": "index.js", 22 | "scripts": { 23 | "test": "echo \"Error: no test specified\" && exit 1" 24 | }, 25 | "dependencies": { 26 | "whatsapp-web.js": "*", 27 | "qrcode-terminal": "*", 28 | "@google/generative-ai": "*", 29 | "dotenv": "*", 30 | "axios": "*" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /prompt_template.js: -------------------------------------------------------------------------------- 1 | // prompt_template.js 2 | 3 | const emeteraiPromptTemplate = `Anda adalah perwakilan layanan pelanggan dengan nama toko Hidden Glam untuk berjualan jasa pembubuhan E-meterai, layanan meterai elektronik. Berikut adalah beberapa poin penting tentang produk kami: 4 | 5 | Current time: {current_time} 6 | 7 | - Toko buka dari pukul 7 pagi hingga 5 sore dan istirahat pada pukul 12.00-13.00, diluar jam tersebut toko libur. 8 | - E-meterai adalah meterai elektronik yang digunakan untuk dokumen resmi. 9 | - Harga bervariasi tergantung pada jenis dan jumlah, saat ini ditetapkan pada Rp. 17.000 per meterai. 10 | - Tidak ada situs web yang tersedia kecuali shopee dan WhatsApp. 11 | - Mengucapkan sama-sama sebagai rasa kepedulian jika pelanggan bilang terimakasih. 12 | - Dokumen harus sudah final sebelum diberikan E-meterai karena tidak bisa diedit, dikompres, digabungkan, atau dipisah setelahnya. 13 | - Ukuran dokumen yang disarankan adalah antara 100-500kb dalam format PDF. 14 | - E-meterai harus ditempatkan di sebelah kiri tanda tangan dan tidak boleh tumpang tindih. 15 | - Waktu pengerjaan diperkirakan 5-120 menit tergantung pada antrian. 16 | - Pembayaran dapat dilakukan melalui QRIS melalui berbagai aplikasi perbankan mobile dan dompet elektronik. 17 | - Tidak menggunakan Bold formatting 18 | 19 | Dari point tersebut, Jawablah pertanyaan pelanggan berikut ini dalam Bahasa Indonesia 20 | User question: {user_question} 21 | 22 | Your response: 23 | `; 24 | 25 | module.exports = emeteraiPromptTemplate; 26 | 27 | -------------------------------------------------------------------------------- /replies.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | greetingsCaption: `Selamat datang di Hidden Glam, toko online terpercaya untuk solusi digital Anda! Di sini, kami menyediakan produk unggulan seperti Emeterai, VPS, dan RDP. Untuk memudahkan pencarian, ketik "Bantuan" kapan saja untuk menampilkan opsi-opsi yang tersedia.`, 3 | paymentCaption: `Berikut adalah metode pembayaran yang dapat Anda gunakan. Silakan scan QR code ini untuk melakukan pembayaran.`, 4 | 5 | options: `Pilih opsi: 6 | 1. Info E-meterai 7 | 2. Pembayaran 8 | 9 | Ketik nomor opsi.`, 10 | 11 | faq: { 12 | "apa itu e-meterai": "E-meterai: cap elektronik untuk dokumen resmi.", 13 | "bagaimana cara membeli": "Beli E-meterai via situs kami atau layanan pelanggan.", 14 | "harga": "Harga E-meterai bervariasi. Hubungi kami untuk harga terbaru.", 15 | "waktu pengiriman": "Pengiriman E-meterai: 2-3 hari kerja.", 16 | "kebijakan pengembalian": "Jaminan uang kembali 30 hari jika tidak puas." 17 | }, 18 | 19 | stopMessage: "Bot berhenti. Ketik \"lanjut\" untuk melanjutkan.", 20 | continueMessage: "Bot telah dilanjutkan. Bagaimana saya bisa membantu Anda?", 21 | continuePrompt: "Anda terhubung dengan asisten otomatis, Apakah Anda ingin melanjutkan? Ketik \"stop\" untuk menghentikan dan berbicara dengan admin atau abaikan untuk melanjutkan.", 22 | defaultMessage: "Maaf, saya tidak mengerti pertanyaan Anda. Silakan coba lagi atau hubungi customer service kami.", 23 | 24 | optionResponses: { 25 | "1": "E-meterai: electronic stamp for official docs.", 26 | "2": "Silakan lakukan pembayaran menggunakan QR code yang telah kami kirimkan." 27 | } 28 | }; 29 | 30 | --------------------------------------------------------------------------------