From c4c6c4faa3fbd3d985bdca7e262714f22cc36982 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=9F=D0=B0=D0=B2=D0=B5=D0=BB?= <pashok9825@gmail.com>
Date: Fri, 4 Jun 2021 14:42:12 +0300
Subject: [PATCH] ability to specify send api version

---
 messenger.go | 41 +++++++++++++++++++++++++++--------------
 response.go  | 17 ++++++++++-------
 2 files changed, 37 insertions(+), 21 deletions(-)

diff --git a/messenger.go b/messenger.go
index e97abaa..52d6a7f 100644
--- a/messenger.go
+++ b/messenger.go
@@ -48,6 +48,8 @@ type Options struct {
 	WebhookURL string
 	// Mux is shared mux between several Messenger objects
 	Mux *http.ServeMux
+	// SendAPIVersion is a Send API version
+	SendAPIVersion string
 }
 
 // MessageHandler is a handler used for responding to a message containing text.
@@ -86,6 +88,7 @@ type Messenger struct {
 	verifyHandler          func(http.ResponseWriter, *http.Request)
 	verify                 bool
 	appSecret              string
+	sendAPIVersion         string
 }
 
 // New creates a new Messenger. You pass in Options in order to affect settings.
@@ -95,16 +98,21 @@ func New(mo Options) *Messenger {
 	}
 
 	m := &Messenger{
-		mux:       mo.Mux,
-		token:     mo.Token,
-		verify:    mo.Verify,
-		appSecret: mo.AppSecret,
+		mux:            mo.Mux,
+		token:          mo.Token,
+		verify:         mo.Verify,
+		appSecret:      mo.AppSecret,
+		sendAPIVersion: mo.SendAPIVersion,
 	}
 
 	if mo.WebhookURL == "" {
 		mo.WebhookURL = "/"
 	}
 
+	if m.sendAPIVersion == "" {
+		m.sendAPIVersion = DefaultSendAPIVersion
+	}
+
 	m.verifyHandler = newVerifyHandler(mo.VerifyToken)
 	m.mux.HandleFunc(mo.WebhookURL, m.handle)
 
@@ -366,8 +374,9 @@ func (m *Messenger) dispatch(r Receive) {
 			}
 
 			resp := &Response{
-				to:    Recipient{info.Sender.ID},
-				token: m.token,
+				to:             Recipient{info.Sender.ID},
+				token:          m.token,
+				sendAPIVersion: m.sendAPIVersion,
 			}
 
 			switch a {
@@ -427,8 +436,9 @@ func (m *Messenger) dispatch(r Receive) {
 // Response returns new Response object.
 func (m *Messenger) Response(to int64) *Response {
 	return &Response{
-		to:    Recipient{to},
-		token: m.token,
+		to:             Recipient{to},
+		token:          m.token,
+		sendAPIVersion: m.sendAPIVersion,
 	}
 }
 
@@ -440,8 +450,9 @@ func (m *Messenger) Send(to Recipient, message string, messagingType MessagingTy
 // SendGeneralMessage will send the GenericTemplate message.
 func (m *Messenger) SendGeneralMessage(to Recipient, elements *[]StructuredMessageElement, messagingType MessagingType, metadata string, tags ...string) (QueryResponse, error) {
 	r := &Response{
-		token: m.token,
-		to:    to,
+		token:          m.token,
+		to:             to,
+		sendAPIVersion: m.sendAPIVersion,
 	}
 	return r.GenericTemplate(elements, messagingType, metadata, tags...)
 }
@@ -449,8 +460,9 @@ func (m *Messenger) SendGeneralMessage(to Recipient, elements *[]StructuredMessa
 // SendWithReplies sends a textual message to a user, but gives them the option of numerous quick response options.
 func (m *Messenger) SendWithReplies(to Recipient, message string, replies []QuickReply, messagingType MessagingType, metadata string, tags ...string) (QueryResponse, error) {
 	response := &Response{
-		token: m.token,
-		to:    to,
+		token:          m.token,
+		to:             to,
+		sendAPIVersion: m.sendAPIVersion,
 	}
 
 	return response.TextWithReplies(message, replies, messagingType, metadata, tags...)
@@ -459,8 +471,9 @@ func (m *Messenger) SendWithReplies(to Recipient, message string, replies []Quic
 // Attachment sends an image, sound, video or a regular file to a given recipient.
 func (m *Messenger) Attachment(to Recipient, dataType AttachmentType, url string, messagingType MessagingType, metadata string, tags ...string) (QueryResponse, error) {
 	response := &Response{
-		token: m.token,
-		to:    to,
+		token:          m.token,
+		to:             to,
+		sendAPIVersion: m.sendAPIVersion,
 	}
 
 	return response.Attachment(dataType, url, messagingType, metadata, tags...)
diff --git a/response.go b/response.go
index 3f57ba9..a606f4f 100644
--- a/response.go
+++ b/response.go
@@ -23,10 +23,12 @@ type TopElementStyle string
 type ImageAspectRatio string
 
 const (
+	// DefaultSendAPIVersion is a default Send API version
+	DefaultSendAPIVersion = "v2.11"
 	// SendMessageURL is API endpoint for sending messages.
-	SendMessageURL = "https://graph.facebook.com/v2.11/me/messages"
+	SendMessageURL = "https://graph.facebook.com/%s/me/messages"
 	// ThreadControlURL is the API endpoint for passing thread control.
-	ThreadControlURL = "https://graph.facebook.com/v2.6/me/pass_thread_control"
+	ThreadControlURL = "https://graph.facebook.com/%s/me/pass_thread_control"
 	// InboxPageID is managed by facebook for secondary pass to inbox features: https://developers.facebook.com/docs/messenger-platform/handover-protocol/pass-thread-control
 	InboxPageID = 263902037430900
 
@@ -110,8 +112,9 @@ func getFacebookQueryResponse(r io.Reader) (QueryResponse, error) {
 
 // Response is used for responding to events with messages.
 type Response struct {
-	token string
-	to    Recipient
+	token          string
+	to             Recipient
+	sendAPIVersion string
 }
 
 // SetToken is for using DispatchMessage from outside.
@@ -249,7 +252,7 @@ func (r *Response) AttachmentData(dataType AttachmentType, filename string, file
 	multipartWriter.WriteField("recipient", fmt.Sprintf(`{"id":"%v"}`, r.to.ID))
 	multipartWriter.WriteField("message", fmt.Sprintf(`{"attachment":{"type":"%v", "payload":{}}}`, dataType))
 
-	req, err := http.NewRequest("POST", SendMessageURL, &body)
+	req, err := http.NewRequest("POST", fmt.Sprintf(SendMessageURL, r.sendAPIVersion), &body)
 	if err != nil {
 		return qr, err
 	}
@@ -365,7 +368,7 @@ func (r *Response) DispatchMessage(m interface{}) (QueryResponse, error) {
 		return res, err
 	}
 
-	req, err := http.NewRequest("POST", SendMessageURL, bytes.NewBuffer(data))
+	req, err := http.NewRequest("POST", fmt.Sprintf(SendMessageURL, r.sendAPIVersion), bytes.NewBuffer(data))
 	if err != nil {
 		return res, err
 	}
@@ -397,7 +400,7 @@ func (r *Response) PassThreadToInbox() error {
 		return err
 	}
 
-	req, err := http.NewRequest("POST", ThreadControlURL, bytes.NewBuffer(data))
+	req, err := http.NewRequest("POST", fmt.Sprintf(ThreadControlURL, r.sendAPIVersion), bytes.NewBuffer(data))
 	if err != nil {
 		return err
 	}