commit f87b057b856f540e40409319735e1972c0309523 Author: cangui Date: Tue May 6 18:16:42 2025 +0200 first diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..64af1af --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM golang:1.20-alpine AS builder +WORKDIR /app + +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . +RUN CGO_ENABLED=0 GOOS=linux go build -o sender main.go + +FROM alpine:latest +WORKDIR /root/ +COPY --from=builder /app/sender . +COPY public ./public + +EXPOSE 3000 +CMD ["./sender"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..c64d411 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +version: '3.8' +services: + whatsapp-sender: + build: . + container_name: whatsapp_sender + ports: + - "3000:3000" + volumes: + - ./public:/root/public:ro + environment: + - PORT=3000 + restart: unless-stopped diff --git a/main.go b/main.go new file mode 100644 index 0000000..b6cdf93 --- /dev/null +++ b/main.go @@ -0,0 +1,120 @@ +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 +} diff --git a/public/login.html b/public/login.html new file mode 100644 index 0000000..03a27b7 --- /dev/null +++ b/public/login.html @@ -0,0 +1,12 @@ + + + + + WhatsApp QR Login + + +

Scan QR to Login

+

Connect to WhatsApp Web from this device.

+

QR will show in terminal output.

+ + diff --git a/public/logo-merlo-cs-FR.jpg b/public/logo-merlo-cs-FR.jpg new file mode 100644 index 0000000..416892e Binary files /dev/null and b/public/logo-merlo-cs-FR.jpg differ