Skip to content
This repository has been archived by the owner on Jan 1, 2023. It is now read-only.

Commit

Permalink
Api update
Browse files Browse the repository at this point in the history
Postback action handler
Dynamic WebHook
Button Template Message
Generic Template Message
  • Loading branch information
panichmaxim committed May 3, 2016
1 parent 494b974 commit eb0e72a
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 20 deletions.
2 changes: 2 additions & 0 deletions actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ const (
// DeliveryAction means that the event was a previous recipient reading their respective
// messages.
DeliveryAction
// PostBackAction represents post call back
PostBackAction
)
12 changes: 12 additions & 0 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ type Delivery struct {
Seq int `json:"seq"`
}

// PostBack represents postback callback
type PostBack struct {
// Sender is who the message was sent from.
Sender Sender `json:"-"`
// Recipient is who the message was sent to.
Recipient Recipient `json:"-"`
// Time is when the message was sent.
Time time.Time `json:"-"`
// PostBack ID
Payload string `json:"payload"`
}

// Watermark is the RawWatermark timestamp rendered as a time.Time.
func (d Delivery) Watermark() time.Time {
return time.Unix(d.RawWatermark, 0)
Expand Down
54 changes: 34 additions & 20 deletions messenger.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ import (
)

const (
// WebhookURL is where the Messenger client should listen for webhook events.
WebhookURL = "/webhook"

// 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>
ProfileURL = "https://graph.facebook.com/v2.6/"
Expand All @@ -26,6 +23,8 @@ type Options struct {
VerifyToken string
// Token is the access token of the Facebook page to send messages from.
Token string
// WebhookURL is where the Messenger client should listen for webhook events.
WebhookURL string
}

// MessageHandler is a handler used for responding to a message containing text.
Expand All @@ -34,11 +33,15 @@ type MessageHandler func(Message, *Response)
// DeliveryHandler is a handler used for responding to a read receipt.
type DeliveryHandler func(Delivery, *Response)

// PostBackHandler is a handler used postback callbacks.
type PostBackHandler func(PostBack, *Response)

// Messenger is the client which manages communication with the Messenger Platform API.
type Messenger struct {
mux *http.ServeMux
messageHandlers []MessageHandler
deliveryHandlers []DeliveryHandler
postBackHandlers []PostBackHandler
token string
verifyHandler func(http.ResponseWriter, *http.Request)
}
Expand All @@ -51,7 +54,7 @@ func New(mo Options) *Messenger {
}

m.verifyHandler = newVerifyHandler(mo.VerifyToken)
m.mux.HandleFunc(WebhookURL, m.handle)
m.mux.HandleFunc(mo.WebhookURL, m.handle)

return m
}
Expand All @@ -68,6 +71,11 @@ func (m *Messenger) HandleDelivery(f DeliveryHandler) {
m.deliveryHandlers = append(m.deliveryHandlers, f)
}

// HandlePostBack adds a new PostBackHandler to the Messenger
func (m *Messenger) HandlePostBack(f PostBackHandler) {
m.postBackHandlers = append(m.postBackHandlers, f)
}

// Handler returns the Messenger in HTTP client form.
func (m *Messenger) Handler() http.Handler {
return m.mux
Expand Down Expand Up @@ -106,7 +114,6 @@ func (m *Messenger) handle(w http.ResponseWriter, r *http.Request) {
err := json.NewDecoder(r.Body).Decode(&rec)
if err != nil {
fmt.Println(err)

fmt.Fprintln(w, `{status: 'not ok'}`)
return
}
Expand Down Expand Up @@ -136,19 +143,26 @@ func (m *Messenger) dispatch(r Receive) {
}

switch a {
case TextAction:
for _, f := range m.messageHandlers {
message := *info.Message
message.Sender = info.Sender
message.Recipient = info.Recipient
message.Time = time.Unix(info.Timestamp, 0)

f(message, resp)
}
case DeliveryAction:
for _, f := range m.deliveryHandlers {
f(*info.Delivery, resp)
}
case TextAction:
for _, f := range m.messageHandlers {
message := *info.Message
message.Sender = info.Sender
message.Recipient = info.Recipient
message.Time = time.Unix(info.Timestamp, 0)
f(message, resp)
}
case DeliveryAction:
for _, f := range m.deliveryHandlers {
f(*info.Delivery, resp)
}
case PostBackAction:
for _, f := range m.postBackHandlers {
message := *info.PostBack
message.Sender = info.Sender
message.Recipient = info.Recipient
message.Time = time.Unix(info.Timestamp, 0)
f(message, resp)
}
}
}
}
Expand All @@ -160,8 +174,9 @@ func (m *Messenger) classify(info MessageInfo, e Entry) Action {
return TextAction
} else if info.Delivery != nil {
return DeliveryAction
} else if info.PostBack != nil {
return PostBackAction
}

return UnknownAction
}

Expand All @@ -172,7 +187,6 @@ func newVerifyHandler(token string) func(w http.ResponseWriter, r *http.Request)
fmt.Fprintln(w, r.FormValue("hub.challenge"))
return
}

fmt.Fprintln(w, "Incorrect verify token.")
}
}
2 changes: 2 additions & 0 deletions receiving.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ type MessageInfo struct {
// Delivery is the contents of a message if it is a DeliveryAction.
// Nil if it is not a DeliveryAction.
Delivery *Delivery `json:"delivery"`

PostBack *PostBack `json:"postback"`
}

// Sender is who the message was sent from.
Expand Down
122 changes: 122 additions & 0 deletions response.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,85 @@ func (r *Response) Image(im image.Image) error {
return nil
}

func (r *Response) ButtonTemplate(text string, buttons *[]StructuredMessageButton) error {
m := SendStructuredMessage {
Recipient: r.to,
Message: StructuredMessageData {
Attachment: StructuredMessageAttachment {
Type: "template",
Payload: StructuredMessagePayload {
TemplateType: "button",
Text: text,
Buttons: buttons,
Elements: nil,
},
},
},
}

fmt.Println(m)

data, err := json.Marshal(m)
if err != nil {
return nil
}

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)
fmt.Println(resp)
defer resp.Body.Close()

return err
}

func (r *Response) GenericTemplate(text string, elements *[]StructuredMessageElement) error {
m := SendStructuredMessage {
Recipient: r.to,
Message: StructuredMessageData {
Attachment: StructuredMessageAttachment {
Type: "template",
Payload: StructuredMessagePayload {
TemplateType: "generic",
Buttons: nil,
Elements: elements,
},
},
},
}

fmt.Println(m)

data, err := json.Marshal(m)
if err != nil {
return nil
}

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)
fmt.Println(resp)
defer resp.Body.Close()

return err
}

// SendMessage is the information sent in an API request to Facebook.
type SendMessage struct {
Recipient Recipient `json:"recipient"`
Expand All @@ -107,3 +186,46 @@ type SendMessage struct {
type MessageData struct {
Text string `json:"text,omitempty"`
}

// SendStructuredMessage is a structured message template
type SendStructuredMessage struct {
Recipient Recipient `json:"recipient"`
Message StructuredMessageData `json:"message"`
}

type StructuredMessageData struct {
Attachment StructuredMessageAttachment `json:"attachment"`
}

type StructuredMessageAttachment struct {
// Template allways
Type string `json:"type"`
// Payload is the information for the file which was sent in the attachment.
Payload StructuredMessagePayload `json:"payload"`
}

type StructuredMessagePayload struct {
// button, generic, receipt
TemplateType string `json:"template_type"`
Text string `json:"text,omitempty"`
Elements *[]StructuredMessageElement `json:"elements,omitempty"`
Buttons *[]StructuredMessageButton `json:"buttons,omitempty"`
}

// StructuredMessageElement - Generic Template
type StructuredMessageElement struct {
Title string `json:"title"`
ImageURL string `json:"image_url"`
Subtitle string `json:"subtitle"`
Buttons []StructuredMessageButton `json:"buttons"`
}

// StructuredMessageButton - Button Template
type StructuredMessageButton struct {
Type string `json:"type"`
URL string `json:"url"`
Title string `json:"title"`
}



0 comments on commit eb0e72a

Please sign in to comment.