From 6c8d22bdec589e78417223bbca49ba430cae52bc Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 6 May 2025 18:41:05 +0200 Subject: [PATCH] up --- Dockerfile | 26 ++--- docker-compose.yml | 17 ++-- go.mod | 34 +++++++ go.sum | 90 ++++++++++++++++++ main.go | 232 +++++++++++++++++++++++++-------------------- public/login.html | 126 ++++++++++++++++++++++-- 6 files changed, 396 insertions(+), 129 deletions(-) create mode 100644 go.mod create mode 100644 go.sum diff --git a/Dockerfile b/Dockerfile index 64af1af..d4cda13 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,20 @@ -FROM golang:1.20-alpine AS builder +# Build stage +FROM golang:1.21-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 +RUN go mod init whatsapp-sender +RUN go mod tidy +RUN go build -o whatsapp-sender . + +# Runtime stage FROM alpine:latest -WORKDIR /root/ -COPY --from=builder /app/sender . -COPY public ./public -EXPOSE 3000 -CMD ["./sender"] +WORKDIR /app +COPY --from=builder /app/whatsapp-sender . +COPY --from=builder /app/public ./public + +EXPOSE 8080 + +CMD ["./whatsapp-sender"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index c64d411..deadd21 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,17 @@ version: '3.8' + services: whatsapp-sender: build: . - container_name: whatsapp_sender ports: - - "3000:3000" - volumes: - - ./public:/root/public:ro - environment: - - PORT=3000 + - "8080:8080" restart: unless-stopped + volumes: + - ./public:/app/public + environment: + - WHATSAPP_SESSION_DIR=/app/sessions + volumes: + - sessions:/app/sessions + +volumes: + sessions: \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..11660c9 --- /dev/null +++ b/go.mod @@ -0,0 +1,34 @@ +module pvnet/whatsapp + +go 1.24.0 + +require github.com/Rhymen/go-whatsapp v0.1.1 + +require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/golang/protobuf v1.5.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/mux v1.8.1 + github.com/gorilla/websocket v1.5.0 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-sqlite3 v1.14.28 + github.com/ncruces/go-strftime v0.1.9 // indirect + github.com/petermattis/goid v0.0.0-20250319124200-ccd6737f222a // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/rs/zerolog v1.34.0 // indirect + go.mau.fi/libsignal v0.1.2 // indirect + go.mau.fi/util v0.8.6 // indirect + go.mau.fi/whatsmeow v0.0.0-20250501130609-4c93ee4e6efa // indirect + golang.org/x/crypto v0.37.0 // indirect + golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect + golang.org/x/net v0.39.0 // indirect + golang.org/x/sys v0.32.0 // indirect + google.golang.org/protobuf v1.36.6 // indirect + modernc.org/libc v1.62.1 // indirect + modernc.org/mathutil v1.7.1 // indirect + modernc.org/memory v1.9.1 // indirect + modernc.org/sqlite v1.37.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..6341186 --- /dev/null +++ b/go.sum @@ -0,0 +1,90 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f/go.mod h1:4a58ifQTEe2uwwsaqbh3i2un5/CBPg+At/qHpt18Tmk= +github.com/Rhymen/go-whatsapp v0.0.0/go.mod h1:rdQr95g2C1xcOfM7QGOhza58HeI3I+tZ/bbluv7VazA= +github.com/Rhymen/go-whatsapp v0.1.1 h1:OK+bCugQcr2YjyYKeDzULqCtM50TPUFM6LvQtszKfcw= +github.com/Rhymen/go-whatsapp v0.1.1/go.mod h1:o7jjkvKnigfu432dMbQ/w4PH0Yp5u4Y6ysCNjUlcYCk= +github.com/Rhymen/go-whatsapp/examples/echo v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:zgCiQtBtZ4P4gFWvwl9aashsdwOcbb/EHOGRmSzM8ME= +github.com/Rhymen/go-whatsapp/examples/restoreSession v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:5sCUSpG616ZoSJhlt9iBNI/KXBqrVLcNUJqg7J9+8pU= +github.com/Rhymen/go-whatsapp/examples/sendImage v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:RdiyhanVEGXTam+mZ3k6Y3VDCCvXYCwReOoxGozqhHw= +github.com/Rhymen/go-whatsapp/examples/sendTextMessages v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:suwzklatySS3Q0+NCxCDh5hYfgXdQUWU1DNcxwAxStM= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A= +github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= +github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/petermattis/goid v0.0.0-20250319124200-ccd6737f222a h1:S+AGcmAESQ0pXCUNnRH7V+bOUIgkSX5qVt2cNKCrm0Q= +github.com/petermattis/goid v0.0.0-20250319124200-ccd6737f222a/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= +github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= +github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo= +go.mau.fi/libsignal v0.1.2 h1:Vs16DXWxSKyzVtI+EEXLCSy5pVWzzCzp/2eqFGvLyP0= +go.mau.fi/libsignal v0.1.2/go.mod h1:JpnLSSJptn/s1sv7I56uEMywvz8x4YzxeF5OzdPb6PE= +go.mau.fi/util v0.8.6 h1:AEK13rfgtiZJL2YsNK+W4ihhYCuukcRom8WPP/w/L54= +go.mau.fi/util v0.8.6/go.mod h1:uNB3UTXFbkpp7xL1M/WvQks90B/L4gvbLpbS0603KOE= +go.mau.fi/whatsmeow v0.0.0-20250501130609-4c93ee4e6efa h1:+bQKfMtnhX2jVoCSaneH4Ctk51IVT1K2gvjyqfFjVW0= +go.mau.fi/whatsmeow v0.0.0-20250501130609-4c93ee4e6efa/go.mod h1:NlPtoLdpX3RnltqCTCZQ6kIUfprqLirtSK1gHvwoNx0= +golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= +golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= +golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +modernc.org/libc v1.62.1 h1:s0+fv5E3FymN8eJVmnk0llBe6rOxCu/DEU+XygRbS8s= +modernc.org/libc v1.62.1/go.mod h1:iXhATfJQLjG3NWy56a6WVU73lWOcdYVxsvwCgoPljuo= +modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= +modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= +modernc.org/memory v1.9.1 h1:V/Z1solwAVmMW1yttq3nDdZPJqV1rM05Ccq6KMSZ34g= +modernc.org/memory v1.9.1/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/sqlite v1.37.0 h1:s1TMe7T3Q3ovQiK2Ouz4Jwh7dw4ZDqbebSDTlSJdfjI= +modernc.org/sqlite v1.37.0/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM= diff --git a/main.go b/main.go index b6cdf93..2e64c8b 100644 --- a/main.go +++ b/main.go @@ -1,120 +1,142 @@ package main import ( - "encoding/json" - "log" - "net/http" - "os" - "time" + "fmt" + "log" + "net/http" + "os" + "path/filepath" + "time" + "context" - whatsapp "github.com/Rhymen/go-whatsapp" - "github.com/Rhymen/go-whatsapp/binary/proto" - "github.com/Rhymen/go-whatsapp/binary/proto/text" + "github.com/gorilla/mux" + "go.mau.fi/whatsmeow" + waProto "go.mau.fi/whatsmeow/binary/proto" + "go.mau.fi/whatsmeow/store/sqlstore" + "go.mau.fi/whatsmeow/types" + "go.mau.fi/whatsmeow/types/events" + waLog "go.mau.fi/whatsmeow/util/log" + "google.golang.org/protobuf/proto" ) -type interactiveReq struct { - Phone string `json:"phone"` - Caption string `json:"caption"` - URL1 string `json:"url1"` - URL2 string `json:"url2"` -} +var client *whatsmeow.Client func main() { - wac, err := whatsapp.NewConn(20 * time.Second) - if err != nil { - log.Fatalf("Error creating connection: %v", err) - } + // Initialisation du routeur + r := mux.NewRouter() - 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") + // Routes + r.HandleFunc("/", loginHandler).Methods("GET") + r.HandleFunc("/send", sendMessageHandler).Methods("POST") + r.HandleFunc("/qr", qrHandler).Methods("GET") - http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) { - http.ServeFile(w, r, "public/login.html") - }) + // Serveur de fichiers statiques + r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("public")))) - 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 - } + // Configuration du serveur + srv := &http.Server{ + Handler: r, + Addr: "0.0.0.0:8080", + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } - 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)) + log.Println("Serveur démarré sur http://localhost:8080") + log.Fatal(srv.ListenAndServe()) } -func getBaseURL(r *http.Request) string { - scheme := "http" - if r.TLS != nil { - scheme = "https" - } - return scheme + "://" + r.Host +func loginHandler(w http.ResponseWriter, r *http.Request) { + http.ServeFile(w, r, "public/login.html") } + +func sendMessageHandler(w http.ResponseWriter, r *http.Request) { + phone := r.FormValue("phone") + message := r.FormValue("message") + + if client == nil || !client.IsConnected() { + http.Error(w, "Client WhatsApp non connecté", http.StatusBadRequest) + return + } + + recipient, err := types.ParseJID(phone) + if err != nil { + http.Error(w, "Numéro de téléphone invalide", http.StatusBadRequest) + return + } + + msg := &waProto.Message{ + Conversation: proto.String(message), + } + + _, err = client.SendMessage(context.Background(), recipient, msg) + if err != nil { + http.Error(w, fmt.Sprintf("Erreur d'envoi: %v", err), http.StatusInternalServerError) + return + } + + fmt.Fprintf(w, "Message envoyé avec succès à %s", phone) +} + +func qrHandler(w http.ResponseWriter, r *http.Request) { + // Initialisation du client WhatsApp si ce n'est pas déjà fait + if client == nil { + initWhatsAppClient(r.Context(), w) + } + + // Ici vous devriez implémenter la logique pour afficher/générer le QR code + // Ceci est un exemple simplifié + fmt.Fprint(w, "QR code endpoint - à implémenter") +} + +func initWhatsAppClient(ctx context.Context, w http.ResponseWriter) { + // Configuration du stockage + storeDir := "sessions" + if os.Getenv("WHATSAPP_SESSION_DIR") != "" { + storeDir = os.Getenv("WHATSAPP_SESSION_DIR") + } + os.MkdirAll(storeDir, os.ModePerm) + + container, err := sqlstore.New("sqlite3", "file:"+filepath.Join(storeDir, "whatsapp.db")+"?_foreign_keys=on", waLog.Noop) + if err != nil { + panic(err) + } + + deviceStore, err := container.GetFirstDevice() + if err != nil { + panic(err) + } + + client = whatsmeow.NewClient(deviceStore, waLog.Noop) + client.AddEventHandler(eventHandler) + + if client.Store.ID == nil { + // Pas de session enregistrée, besoin de s'authentifier + qrChan, _ := client.GetQRChannel(ctx) + err = client.Connect() + if err != nil { + panic(err) + } + + for evt := range qrChan { + if evt.Event == "code" { + // Afficher le QR code à l'utilisateur + fmt.Fprintf(w, "QR code: %s", evt.Code) + } else { + fmt.Fprintf(w, "Événement de connexion: %s", evt.Event) + } + } + } else { + // Déjà connecté + err = client.Connect() + if err != nil { + panic(err) + } + } +} + +func eventHandler(evt interface{}) { + switch v := evt.(type) { + case *events.Message: + fmt.Println("Message reçu de", v.Info.Sender, ":", v.Message.GetConversation()) + } +} \ No newline at end of file diff --git a/public/login.html b/public/login.html index 03a27b7..61ece9d 100644 --- a/public/login.html +++ b/public/login.html @@ -1,12 +1,124 @@ - + - - WhatsApp QR Login + + + WhatsApp Sender + -

Scan QR to Login

-

Connect to WhatsApp Web from this device.

-

QR will show in terminal output.

+
+

WhatsApp Message Sender

+ +
+

Scannez le QR code pour vous connecter à WhatsApp

+ QR Code +
+ +
+
+ + +
+ +
+ + +
+ + +
+ +
+
+ + - + \ No newline at end of file