Browse Source

Add debug endpoint for sending retry receipts

Tulir Asokan 3 years ago
parent
commit
e81acef840
3 changed files with 56 additions and 4 deletions
  1. 1 1
      go.mod
  2. 2 2
      go.sum
  3. 53 1
      provisioning.go

+ 1 - 1
go.mod

@@ -10,7 +10,7 @@ require (
 	github.com/prometheus/client_golang v1.12.2-0.20220514081015-5d584e2717ef
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
 	github.com/tidwall/gjson v1.14.1
-	go.mau.fi/whatsmeow v0.0.0-20220517155948-4947ef2b038c
+	go.mau.fi/whatsmeow v0.0.0-20220517205516-246a2007ca7f
 	golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9
 	golang.org/x/net v0.0.0-20220513224357-95641704303c
 	google.golang.org/protobuf v1.28.0

+ 2 - 2
go.sum

@@ -62,8 +62,8 @@ github.com/yuin/goldmark v1.4.12 h1:6hffw6vALvEDqJ19dOJvJKOoAOKe4NDaTqvd2sktGN0=
 github.com/yuin/goldmark v1.4.12/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.mau.fi/libsignal v0.0.0-20220425070825-c40c839ee6a0 h1:3IQF2bgAyibdo77hTejwuJe4jlypj9QaE4xCQuxrThM=
 go.mau.fi/libsignal v0.0.0-20220425070825-c40c839ee6a0/go.mod h1:kBOXTvYyDG/q1Ihgvd4J6WenGPh7wtEGvPKF6vmf5ak=
-go.mau.fi/whatsmeow v0.0.0-20220517155948-4947ef2b038c h1:DhU4/rx9u8eQNrOgrMUfKsjrn3fnsoIO5OyS+aw2kHI=
-go.mau.fi/whatsmeow v0.0.0-20220517155948-4947ef2b038c/go.mod h1:iUBgOLNaqShLrR17u0kIiRptIGFH+nbT1tRhaWBEX/c=
+go.mau.fi/whatsmeow v0.0.0-20220517205516-246a2007ca7f h1:0eo1TMJBx2pv7vNh/sPAl8bXPpn+HwrVJntuOnejMfs=
+go.mau.fi/whatsmeow v0.0.0-20220517205516-246a2007ca7f/go.mod h1:iUBgOLNaqShLrR17u0kIiRptIGFH+nbT1tRhaWBEX/c=
 golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9 h1:NUzdAbFtCJSXU20AOXgeqaUwg8Ypg4MPYmL+d+rsB5c=
 golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=

+ 53 - 1
provisioning.go

@@ -24,6 +24,7 @@ import (
 	"fmt"
 	"net"
 	"net/http"
+	"strconv"
 	"strings"
 	"time"
 
@@ -31,6 +32,7 @@ import (
 	"github.com/gorilla/websocket"
 
 	"go.mau.fi/whatsmeow/appstate"
+	waBinary "go.mau.fi/whatsmeow/binary"
 	"go.mau.fi/whatsmeow/types"
 
 	"go.mau.fi/whatsmeow"
@@ -57,7 +59,8 @@ func (prov *ProvisioningAPI) Init() {
 	r.HandleFunc("/v1/delete_session", prov.DeleteSession).Methods(http.MethodPost)
 	r.HandleFunc("/v1/disconnect", prov.Disconnect).Methods(http.MethodPost)
 	r.HandleFunc("/v1/reconnect", prov.Reconnect).Methods(http.MethodPost)
-	r.HandleFunc("/v1/sync/appstate/{name}", prov.SyncAppState).Methods(http.MethodPost)
+	r.HandleFunc("/v1/debug/appstate/{name}", prov.SyncAppState).Methods(http.MethodPost)
+	r.HandleFunc("/v1/debug/retry", prov.SendRetryReceipt).Methods(http.MethodPost)
 	r.HandleFunc("/v1/contacts", prov.ListContacts).Methods(http.MethodGet)
 	r.HandleFunc("/v1/groups", prov.ListGroups).Methods(http.MethodGet)
 	r.HandleFunc("/v1/resolve_identifier/{number}", prov.ResolveIdentifier).Methods(http.MethodGet)
@@ -183,6 +186,55 @@ func (prov *ProvisioningAPI) Reconnect(w http.ResponseWriter, r *http.Request) {
 	}
 }
 
+type debugRetryReceiptContent struct {
+	ID          types.MessageID `json:"id"`
+	From        types.JID       `json:"from"`
+	Recipient   types.JID       `json:"recipient"`
+	Participant types.JID       `json:"participant"`
+	Timestamp   int64           `json:"timestamp"`
+	Count       int             `json:"count"`
+
+	ForceIncludeIdentity bool `json:"force_include_identity"`
+}
+
+func (prov *ProvisioningAPI) SendRetryReceipt(w http.ResponseWriter, r *http.Request) {
+	var req debugRetryReceiptContent
+	user := r.Context().Value("user").(*User)
+	if user == nil || user.Client == nil {
+		jsonResponse(w, http.StatusNotFound, Error{
+			Error:   "User is not connected to WhatsApp",
+			ErrCode: "no session",
+		})
+		return
+	} else if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+		jsonResponse(w, http.StatusBadRequest, Error{
+			Error:   "Failed to parse request JSON",
+			ErrCode: "bad json",
+		})
+	} else {
+		node := &waBinary.Node{
+			Attrs: waBinary.Attrs{
+				"id":   string(req.ID),
+				"from": req.From,
+				"t":    strconv.FormatInt(req.Timestamp, 10),
+			},
+		}
+		if !req.Recipient.IsEmpty() {
+			node.Attrs["recipient"] = req.Recipient
+		}
+		if !req.Participant.IsEmpty() {
+			node.Attrs["participant"] = req.Participant
+		}
+		if req.Count > 0 {
+			node.Content = []waBinary.Node{{
+				Tag:   "enc",
+				Attrs: waBinary.Attrs{"count": strconv.Itoa(req.Count)},
+			}}
+		}
+		user.Client.DangerousInternals().SendRetryReceipt(node, req.ForceIncludeIdentity)
+	}
+}
+
 func (prov *ProvisioningAPI) SyncAppState(w http.ResponseWriter, r *http.Request) {
 	user := r.Context().Value("user").(*User)
 	if user == nil || user.Client == nil {