1
0
mirror of synced 2024-11-29 00:26:12 +03:00

* Added ability to set greeting setting, get started setting and persistent menu setting

* Added IsEcho in Message which is indicator of own messages
* Added QuickReply in Message for sending of quick reply buttons with message
* Added mux parameter in Messenger constructor. It is useful when single go app processes the several bots
* Added Messenger.SenderAction which allows to show writing and reading status
* Added Messenger.GreetingSetting and Messenger.CallToActionsSetting which allow to set the bot settings
* Fixed bug with nil returning instead of error object
This commit is contained in:
Ilyas Salikhov 2016-09-08 10:55:48 +03:00
parent 500eec9f3b
commit f7a3ef787f
5 changed files with 155 additions and 11 deletions

View File

@ -10,6 +10,8 @@ type Message struct {
Recipient Recipient `json:"-"` Recipient Recipient `json:"-"`
// Time is when the message was sent. // Time is when the message was sent.
Time time.Time `json:"-"` Time time.Time `json:"-"`
// Message is mine
IsEcho bool `json:"is_echo,omitempty"`
// Mid is the ID of the message. // Mid is the ID of the message.
Mid string `json:"mid"` Mid string `json:"mid"`
// Seq is order the message was sent in relation to other messages. // Seq is order the message was sent in relation to other messages.
@ -19,6 +21,8 @@ type Message struct {
// Attachments is the information about the attachments which were sent // Attachments is the information about the attachments which were sent
// with the message. // with the message.
Attachments []Attachment `json:"attachments"` Attachments []Attachment `json:"attachments"`
// Selected quick reply
QuickReply *QuickReply `json:"quick_reply,omitempty"`
} }
// Delivery represents a the event fired when Facebook delivers a message to the // Delivery represents a the event fired when Facebook delivers a message to the

View File

@ -1,6 +1,7 @@
package messenger package messenger
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
@ -11,6 +12,8 @@ const (
// ProfileURL is the API endpoint used for retrieving profiles. // ProfileURL is the API endpoint used for retrieving profiles.
// Used in the form: https://graph.facebook.com/v2.6/<USER_ID>?fields=first_name,last_name,profile_pic&access_token=<PAGE_ACCESS_TOKEN> // Used in the form: https://graph.facebook.com/v2.6/<USER_ID>?fields=first_name,last_name,profile_pic&access_token=<PAGE_ACCESS_TOKEN>
ProfileURL = "https://graph.facebook.com/v2.6/" ProfileURL = "https://graph.facebook.com/v2.6/"
// SendSettingsURL is API endpoint for saving settings.
SendSettingsURL = "https://graph.facebook.com/v2.6/me/thread_settings"
) )
// Options are the settings used when creating a Messenger client. // Options are the settings used when creating a Messenger client.
@ -25,6 +28,8 @@ type Options struct {
Token string Token string
// WebhookURL is where the Messenger client should listen for webhook events. Leaving the string blank implies a path of "/". // WebhookURL is where the Messenger client should listen for webhook events. Leaving the string blank implies a path of "/".
WebhookURL string WebhookURL string
// Mux is shared mux between several Messenger objects
Mux *http.ServeMux
} }
// MessageHandler is a handler used for responding to a message containing text. // MessageHandler is a handler used for responding to a message containing text.
@ -52,8 +57,12 @@ type Messenger struct {
// New creates a new Messenger. You pass in Options in order to affect settings. // New creates a new Messenger. You pass in Options in order to affect settings.
func New(mo Options) *Messenger { func New(mo Options) *Messenger {
if mo.Mux == nil {
mo.Mux = http.NewServeMux()
}
m := &Messenger{ m := &Messenger{
mux: http.NewServeMux(), mux: mo.Mux,
token: mo.Token, token: mo.Token,
} }
@ -116,6 +125,65 @@ func (m *Messenger) ProfileByID(id int64) (Profile, error) {
return p, err return p, err
} }
// GreetingSetting sends settings for greeting
func (m *Messenger) GreetingSetting(text string) error {
d := GreetingSetting{
SettingType: "greeting",
Greeting: GreetingInfo{
Text: text,
},
}
data, err := json.Marshal(d)
if err != nil {
return err
}
req, err := http.NewRequest("POST", SendSettingsURL, bytes.NewBuffer(data))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.URL.RawQuery = "access_token=" + m.token
client := &http.Client{}
resp, err := client.Do(req)
defer resp.Body.Close()
return err
}
// CallToActionsSetting sends settings for Get Started or Persist Menu
func (m *Messenger) CallToActionsSetting(state string, actions []CallToActionsItem) error {
d := CallToActionsSetting{
SettingType: "call_to_actions",
ThreadState: state,
CallToActions: actions,
}
data, err := json.Marshal(d)
if err != nil {
return err
}
req, err := http.NewRequest("POST", SendSettingsURL, bytes.NewBuffer(data))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.URL.RawQuery = "access_token=" + m.token
client := &http.Client{}
resp, err := client.Do(req)
defer resp.Body.Close()
return err
}
// handle is the internal HTTP handler for the webhooks. // handle is the internal HTTP handler for the webhooks.
func (m *Messenger) handle(w http.ResponseWriter, r *http.Request) { func (m *Messenger) handle(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" { if r.Method == "GET" {
@ -186,6 +254,14 @@ 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,
}
}
// classify determines what type of message a webhook event is. // classify determines what type of message a webhook event is.
func (m *Messenger) classify(info MessageInfo, e Entry) Action { func (m *Messenger) classify(info MessageInfo, e Entry) Action {
if info.Message != nil { if info.Message != nil {

View File

@ -60,9 +60,9 @@ type Attachment struct {
// QuickReply is a file which used in a message. // QuickReply is a file which used in a message.
type QuickReply struct { type QuickReply struct {
// ContentType is the type of reply // ContentType is the type of reply
ContentType string `json:"content_type"` ContentType string `json:"content_type,omitempty"`
// Title is the reply title // Title is the reply title
Title string `json:"title"` Title string `json:"title,omitempty"`
// Payload is the reply information // Payload is the reply information
Payload string `json:"payload"` Payload string `json:"payload"`
} }

View File

@ -39,7 +39,7 @@ func (r *Response) TextWithReplies(message string, replies []QuickReply) error {
data, err := json.Marshal(m) data, err := json.Marshal(m)
if err != nil { if err != nil {
return nil return err
} }
req, err := http.NewRequest("POST", SendMessageURL, bytes.NewBuffer(data)) req, err := http.NewRequest("POST", SendMessageURL, bytes.NewBuffer(data))
@ -122,7 +122,7 @@ func (r *Response) ButtonTemplate(text string, buttons *[]StructuredMessageButto
data, err := json.Marshal(m) data, err := json.Marshal(m)
if err != nil { if err != nil {
return nil return err
} }
req, err := http.NewRequest("POST", SendMessageURL, bytes.NewBuffer(data)) req, err := http.NewRequest("POST", SendMessageURL, bytes.NewBuffer(data))
@ -142,7 +142,7 @@ func (r *Response) ButtonTemplate(text string, buttons *[]StructuredMessageButto
} }
// GenericTemplate is a message which allows for structural elements to be sent // GenericTemplate is a message which allows for structural elements to be sent
func (r *Response) GenericTemplate(text string, elements *[]StructuredMessageElement) error { func (r *Response) GenericTemplate(elements *[]StructuredMessageElement) error {
m := SendStructuredMessage{ m := SendStructuredMessage{
Recipient: r.to, Recipient: r.to,
Message: StructuredMessageData{ Message: StructuredMessageData{
@ -159,7 +159,35 @@ func (r *Response) GenericTemplate(text string, elements *[]StructuredMessageEle
data, err := json.Marshal(m) data, err := json.Marshal(m)
if err != nil { if err != nil {
return nil return err
}
req, err := http.NewRequest("POST", SendMessageURL, bytes.NewBuffer(data))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.URL.RawQuery = "access_token=" + r.token
client := &http.Client{}
resp, err := client.Do(req)
defer resp.Body.Close()
return err
}
// SenderAction sends a info about sender action
func (r *Response) SenderAction(action string) error {
m := SendSenderAction{
Recipient: r.to,
SenderAction: action,
}
data, err := json.Marshal(m)
if err != nil {
return err
} }
req, err := http.NewRequest("POST", SendMessageURL, bytes.NewBuffer(data)) req, err := http.NewRequest("POST", SendMessageURL, bytes.NewBuffer(data))
@ -212,23 +240,32 @@ type StructuredMessageAttachment struct {
// StructuredMessagePayload is the actual payload of an attachment // StructuredMessagePayload is the actual payload of an attachment
type StructuredMessagePayload struct { type StructuredMessagePayload struct {
// TemplateType must be button, generic or receipt // TemplateType must be button, generic or receipt
TemplateType string `json:"template_type"` TemplateType string `json:"template_type,omitempty"`
Text string `json:"text,omitempty"` Text string `json:"text,omitempty"`
Elements *[]StructuredMessageElement `json:"elements,omitempty"` Elements *[]StructuredMessageElement `json:"elements,omitempty"`
Buttons *[]StructuredMessageButton `json:"buttons,omitempty"` Buttons *[]StructuredMessageButton `json:"buttons,omitempty"`
Url string `json:"url,omitempty"`
} }
// StructuredMessageElement is a response containing structural elements // StructuredMessageElement is a response containing structural elements
type StructuredMessageElement struct { type StructuredMessageElement struct {
Title string `json:"title"` Title string `json:"title"`
ImageURL string `json:"image_url"` ImageURL string `json:"image_url"`
ItemURL string `json:"item_url"`
Subtitle string `json:"subtitle"` Subtitle string `json:"subtitle"`
Buttons []StructuredMessageButton `json:"buttons"` Buttons []StructuredMessageButton `json:"buttons"`
} }
// StructuredMessageButton is a response containing buttons // StructuredMessageButton is a response containing buttons
type StructuredMessageButton struct { type StructuredMessageButton struct {
Type string `json:"type"` Type string `json:"type"`
URL string `json:"url"` URL string `json:"url,omitempty"`
Title string `json:"title"` Title string `json:"title"`
Payload string `json:"payload,omitempty"`
}
// SendSenderAction is the information about sender action
type SendSenderAction struct {
Recipient Recipient `json:"recipient"`
SenderAction string `json:"sender_action"`
} }

27
settings.go Normal file
View File

@ -0,0 +1,27 @@
package messenger
// GreetingSetting is the setting for greeting message
type GreetingSetting struct {
SettingType string `json:"setting_type"`
Greeting GreetingInfo `json:"greeting"`
}
// GreetingInfo contains greeting message
type GreetingInfo struct {
Text string `json:"text"`
}
// CallToActionsSetting is the settings for Get Started and Persist Menu
type CallToActionsSetting struct {
SettingType string `json:"setting_type"`
ThreadState string `json:"thread_state"`
CallToActions []CallToActionsItem `json:"call_to_actions"`
}
// CallToActionsItem contains Get Started button or item of Persist Menu
type CallToActionsItem struct {
Type string `json:"type,omitempty"`
Title string `json:"title,omitempty"`
Payload string `json:"payload,omitempty"`
URL string `json:"url,omitempty"`
}