package main import ( "encoding/json" "log" "net/http" "os" "time" whatsapp "github.com/Rhymen/go-whatsapp" "github.com/Rhymen/go-whatsapp/binary/proto" "github.com/Rhymen/go-whatsapp/binary/proto/text" ) type interactiveReq struct { Phone string `json:"phone"` Caption string `json:"caption"` URL1 string `json:"url1"` URL2 string `json:"url2"` } func main() { wac, err := whatsapp.NewConn(20 * time.Second) if err != nil { log.Fatalf("Error creating connection: %v", err) } qrChan := make(chan string) go func() { log.Println("Scan the QR code at http://localhost:3000/login") log.Printf("QR Code: %s", <-qrChan) }() _, err = wac.Login(qrChan) if err != nil { log.Fatalf("Login failed: %v", err) } log.Println("✅ Connected to WhatsApp Web") http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "public/login.html") }) http.HandleFunc("/sendInteractive", func(w http.ResponseWriter, r *http.Request) { var req interactiveReq if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, "Invalid JSON payload", http.StatusBadRequest) return } imageUrl := getBaseURL(r) + "/static/logo-merlo-cs-FR.jpg" header := &proto.InteractiveMessage_Header{ HasMediaAttachment: proto.Bool(true), ImageMessage: &proto.ImageMessage{ Url: &imageUrl, Mimetype: proto.String("image/jpeg"), }, Media: proto.String("imageMessage"), } body := &proto.InteractiveMessage_Body{Text: &req.Caption} footer := &proto.InteractiveMessage_Footer{Text: proto.String("Pied de page")} buttons := []*proto.InteractiveMessage_ButtonParameters{ { Name: proto.String("cta_url"), ButtonParamsJson: proto.String(text.Stringify(&proto.InteractiveMessage_URLButton{ DisplayText: proto.String("📄 Proposition"), Url: &req.URL1, })), }, { Name: proto.String("cta_url"), ButtonParamsJson: proto.String(text.Stringify(&proto.InteractiveMessage_URLButton{ DisplayText: proto.String("🔧 Spécifications"), Url: &req.URL2, })), }, } nativeFlow := &proto.InteractiveMessage_NativeFlowMessage{Buttons: buttons} interactive := &proto.InteractiveMessage{ Header: header, Body: body, Footer: footer, NativeFlowMessage: nativeFlow, } wmi := &proto.WebMessageInfo{ Key: &proto.MessageKey{RemoteJid: proto.String(req.Phone + "@s.whatsapp.net")}, Message: &proto.WebMessageInfo_InteractiveMessage{InteractiveMessage: interactive}, } if _, err := wac.Send(wmi); err != nil { log.Printf("Error sending message: %v", err) http.Error(w, "Failed to send message", http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") w.Write([]byte(`{"success":true}`)) }) fs := http.FileServer(http.Dir("public")) http.Handle("/static/", http.StripPrefix("/static/", fs)) port := os.Getenv("PORT") if port == "" { port = "3002" } log.Printf("Server running on :%s", port) log.Fatal(http.ListenAndServe(":"+port, nil)) } func getBaseURL(r *http.Request) string { scheme := "http" if r.TLS != nil { scheme = "https" } return scheme + "://" + r.Host }