first
This commit is contained in:
commit
f87b057b85
16
Dockerfile
Normal file
16
Dockerfile
Normal file
@ -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"]
|
||||||
12
docker-compose.yml
Normal file
12
docker-compose.yml
Normal file
@ -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
|
||||||
120
main.go
Normal file
120
main.go
Normal file
@ -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
|
||||||
|
}
|
||||||
12
public/login.html
Normal file
12
public/login.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>WhatsApp QR Login</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Scan QR to Login</h1>
|
||||||
|
<p>Connect to WhatsApp Web from this device.</p>
|
||||||
|
<p>QR will show in terminal output.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
public/logo-merlo-cs-FR.jpg
Normal file
BIN
public/logo-merlo-cs-FR.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Loading…
Reference in New Issue
Block a user