modified: .env
modified: bot.db modified: db/db.go modified: handlers/webhook.go modified: services/whatsapp.go
This commit is contained in:
@@ -1,17 +1,38 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"whatsapp-bot/db"
|
||||
"whatsapp-bot/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Meta verification
|
||||
func VerifyWebhook(c *gin.Context) {
|
||||
challenge := c.Query("hub.challenge")
|
||||
token := c.Query("hub.verify_token")
|
||||
// Structs to parse incoming WhatsApp Webhook JSON
|
||||
type WebhookPayload struct {
|
||||
Entry []struct {
|
||||
Changes []struct {
|
||||
Value struct {
|
||||
Messages []struct {
|
||||
From string `json:"from"`
|
||||
Text struct {
|
||||
Body string `json:"body"`
|
||||
} `json:"text"`
|
||||
Type string `json:"type"`
|
||||
} `json:"messages"`
|
||||
} `json:"value"`
|
||||
} `json:"changes"`
|
||||
} `json:"entry"`
|
||||
}
|
||||
|
||||
if token == "YOUR_SECRET_TOKEN" {
|
||||
// VerifyWebhook (Keep this as is)
|
||||
func VerifyWebhook(c *gin.Context) {
|
||||
mode := c.Query("hub.mode")
|
||||
token := c.Query("hub.verify_token")
|
||||
challenge := c.Query("hub.challenge")
|
||||
|
||||
if mode == "subscribe" && token == "YOUR_SECRET_TOKEN" { // CHANGE THIS to match your Meta setup
|
||||
c.String(http.StatusOK, challenge)
|
||||
} else {
|
||||
c.Status(http.StatusForbidden)
|
||||
@@ -19,7 +40,61 @@ func VerifyWebhook(c *gin.Context) {
|
||||
}
|
||||
|
||||
func HandleMessage(c *gin.Context) {
|
||||
// You should bind your WhatsApp types here
|
||||
// go services.Process(...)
|
||||
c.Status(http.StatusOK)
|
||||
var payload WebhookPayload
|
||||
if err := c.BindJSON(&payload); err != nil {
|
||||
// WhatsApp sends other events (statuses) that might not match. Ignore errors.
|
||||
c.Status(200)
|
||||
return
|
||||
}
|
||||
|
||||
// 1. Loop through messages (usually just one)
|
||||
for _, entry := range payload.Entry {
|
||||
for _, change := range entry.Changes {
|
||||
for _, msg := range change.Value.Messages {
|
||||
|
||||
// We only handle text for now
|
||||
if msg.Type != "text" {
|
||||
continue
|
||||
}
|
||||
|
||||
userPhone := msg.From
|
||||
userText := msg.Text.Body
|
||||
|
||||
fmt.Printf("📩 Received from %s: %s\n", userPhone, userText)
|
||||
|
||||
// 2. Identify the Chat Logic
|
||||
chatID := db.GetOrCreateChatByPhone(userPhone)
|
||||
|
||||
// 3. Save User Message
|
||||
db.Conn.Exec("INSERT INTO messages (chat_id, role, content) VALUES (?, 'user', ?)", chatID, userText)
|
||||
|
||||
// 4. Get AI Response
|
||||
// Fetch history
|
||||
rows, _ := db.Conn.Query("SELECT role, content FROM messages WHERE chat_id = ? ORDER BY created_at ASC", chatID)
|
||||
var history []services.Message
|
||||
for rows.Next() {
|
||||
var m services.Message
|
||||
rows.Scan(&m.Role, &m.Content)
|
||||
history = append(history, m)
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
// Call AI (We don't need the stream callback here, just the final string)
|
||||
aiResponse, _ := services.StreamAIResponse(history, func(chunk string) {
|
||||
// We can't stream to WhatsApp, so we do nothing here.
|
||||
})
|
||||
|
||||
// 5. Save & Send Response
|
||||
if aiResponse != "" {
|
||||
db.Conn.Exec("INSERT INTO messages (chat_id, role, content) VALUES (?, 'assistant', ?)", chatID, aiResponse)
|
||||
err := services.SendWhatsAppMessage(userPhone, aiResponse)
|
||||
if err != nil {
|
||||
fmt.Println("❌ Error sending to WhatsApp:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.Status(200)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user