From 8d546920cd8e44ae3f1e4adf612489ec41c81e67 Mon Sep 17 00:00:00 2001 From: Ayomide Onigbinde Date: Sun, 30 Dec 2018 13:37:18 +0100 Subject: [PATCH 1/8] change the default user profile fields; fix minor typo --- message.go | 2 +- messenger.go | 10 ++++------ profile.go | 1 + 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/message.go b/message.go index 30a913c..9948504 100644 --- a/message.go +++ b/message.go @@ -2,7 +2,7 @@ package messenger import "time" -// Message represents a Facebook messenge message. +// Message represents a Facebook messenger message. type Message struct { // Sender is who the message was sent from. Sender Sender `json:"-"` diff --git a/messenger.go b/messenger.go index 8f39017..4bde940 100644 --- a/messenger.go +++ b/messenger.go @@ -26,8 +26,8 @@ const ( ) var ( - // NOTE: If you change this slice you should update the comment on the ProfileByID function below too. - defaultProfileFields = []string{"first_name", "last_name", "profile_pic", "locale", "timezone", "gender"} + // NOTE: If you change this slice you should update the comment on the ProfileByID function below too. + defaultProfileFields = []string{"name", "first_name", "last_name", "profile_pic"} ) // Options are the settings used when creating a Messenger client. @@ -156,14 +156,12 @@ func (m *Messenger) Handler() http.Handler { // ProfileByID retrieves the Facebook user profile associated with that ID // when no profile fields are specified it uses some sane defaults. -// +// // These default fields are: +// - Name // - First name // - Last name // - Profile picture -// - Locale -// - Timezone -// - Gender func (m *Messenger) ProfileByID(id int64, profileFields ...string) (Profile, error) { p := Profile{} url := fmt.Sprintf("%v%v", ProfileURL, id) diff --git a/profile.go b/profile.go index 002edb7..de3bbbc 100644 --- a/profile.go +++ b/profile.go @@ -2,6 +2,7 @@ package messenger // Profile is the public information of a Facebook user type Profile struct { + Name string `json:"name"` FirstName string `json:"first_name"` LastName string `json:"last_name"` ProfilePicURL string `json:"profile_pic"` From 69e49429453ffa5748dd4d1effffbf59141b605c Mon Sep 17 00:00:00 2001 From: Ayomide Onigbinde Date: Sun, 30 Dec 2018 18:59:42 +0100 Subject: [PATCH 2/8] allow the use of a config file instead of manually pasting configs --- examples/basic/bot.config.yml | 5 ++++ examples/basic/main.go | 10 ++++---- parser.go | 45 +++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 examples/basic/bot.config.yml create mode 100644 parser.go diff --git a/examples/basic/bot.config.yml b/examples/basic/bot.config.yml new file mode 100644 index 0000000..f867ca7 --- /dev/null +++ b/examples/basic/bot.config.yml @@ -0,0 +1,5 @@ +verify_token: +access_token: +app_secret: + +# other configs can be added as necessary. For example, the webhook URL and host. diff --git a/examples/basic/main.go b/examples/basic/main.go index f86d6e0..c8cf836 100644 --- a/examples/basic/main.go +++ b/examples/basic/main.go @@ -8,16 +8,18 @@ import ( "os" "time" + msgs "github.com/messenger" "github.com/paked/messenger" ) +var vt, acct, appsc = msgs.GetTokens() var ( - verifyToken = flag.String("verify-token", "mad-skrilla", "The token used to verify facebook (required)") + verifyToken = flag.String("verify-token", vt, "The token used to verify facebook (required)") verify = flag.Bool("should-verify", false, "Whether or not the app should verify itself") - pageToken = flag.String("page-token", "not skrilla", "The token that is used to verify the page on facebook") - appSecret = flag.String("app-secret", "", "The app secret from the facebook developer portal (required)") + pageToken = flag.String("page-token", acct, "The token that is used to verify the page on facebook") + appSecret = flag.String("app-secret", appsc, "The app secret from the facebook developer portal (required)") host = flag.String("host", "localhost", "The host used to serve the messenger bot") - port = flag.Int("port", 8080, "The port used to serve the messenger bot") + port = flag.Int("port", 5000, "The port used to serve the messenger bot") ) func main() { diff --git a/parser.go b/parser.go new file mode 100644 index 0000000..9d8c52d --- /dev/null +++ b/parser.go @@ -0,0 +1,45 @@ +package messenger + +import ( + "io/ioutil" + "log" + "os" + "path/filepath" + + "gopkg.in/yaml.v2" +) + +//Config is the struct for the configuration file +type Config struct { + VerifyToken string `yaml:"verify_token"` + AccessToken string `yaml:"access_token"` + AppSecret string `yaml:"app_secret"` +} + +//ReadYml parses the config yml file and format into the Config struct +func (x *Config) ReadYml() *Config { + configFile, err := filepath.Abs("./bot.config.yml") + if err != nil { + log.Printf("ERROR READING THE CONFIG FILE: %s", err) + } + + yamlFile, err := ioutil.ReadFile(configFile) + + if err != nil { + log.Println("Could not find the config file. Please make sure it is created", err) + os.Exit(-1) + } + + yaml.Unmarshal(yamlFile, &x) + + return x +} + +//GetTokens returns the verifytoken, accesstoken and the appsecret from the config file +func GetTokens() (string, string, string) { + var c Config + + configObj := c.ReadYml() + verifyToken, accessToken, appSecret := configObj.VerifyToken, configObj.AccessToken, configObj.AppSecret + return verifyToken, accessToken, appSecret +} From f1076a12b67e802701e90f43efae87a792da3bf2 Mon Sep 17 00:00:00 2001 From: Ayomide Onigbinde Date: Mon, 31 Dec 2018 02:16:01 +0100 Subject: [PATCH 3/8] fix import path causing travis failed build --- examples/basic/main.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/basic/main.go b/examples/basic/main.go index c8cf836..e17bc37 100644 --- a/examples/basic/main.go +++ b/examples/basic/main.go @@ -7,12 +7,10 @@ import ( "net/http" "os" "time" - - msgs "github.com/messenger" "github.com/paked/messenger" ) -var vt, acct, appsc = msgs.GetTokens() +var vt, acct, appsc = messenger.GetTokens() var ( verifyToken = flag.String("verify-token", vt, "The token used to verify facebook (required)") verify = flag.Bool("should-verify", false, "Whether or not the app should verify itself") From 61add2ce3d9b7b8bda68daa5efea7c303ae9e4b0 Mon Sep 17 00:00:00 2001 From: Ayomide Onigbinde Date: Wed, 2 Jan 2019 20:12:05 +0100 Subject: [PATCH 4/8] reverted PR 51; fixed persistent menu typo --- examples/basic/bot.config.yml | 5 ---- examples/basic/main.go | 10 ++++---- messenger.go | 2 +- parser.go | 45 ----------------------------------- 4 files changed, 6 insertions(+), 56 deletions(-) delete mode 100644 examples/basic/bot.config.yml delete mode 100644 parser.go diff --git a/examples/basic/bot.config.yml b/examples/basic/bot.config.yml deleted file mode 100644 index f867ca7..0000000 --- a/examples/basic/bot.config.yml +++ /dev/null @@ -1,5 +0,0 @@ -verify_token: -access_token: -app_secret: - -# other configs can be added as necessary. For example, the webhook URL and host. diff --git a/examples/basic/main.go b/examples/basic/main.go index e17bc37..f86d6e0 100644 --- a/examples/basic/main.go +++ b/examples/basic/main.go @@ -7,17 +7,17 @@ import ( "net/http" "os" "time" + "github.com/paked/messenger" ) -var vt, acct, appsc = messenger.GetTokens() var ( - verifyToken = flag.String("verify-token", vt, "The token used to verify facebook (required)") + verifyToken = flag.String("verify-token", "mad-skrilla", "The token used to verify facebook (required)") verify = flag.Bool("should-verify", false, "Whether or not the app should verify itself") - pageToken = flag.String("page-token", acct, "The token that is used to verify the page on facebook") - appSecret = flag.String("app-secret", appsc, "The app secret from the facebook developer portal (required)") + pageToken = flag.String("page-token", "not skrilla", "The token that is used to verify the page on facebook") + appSecret = flag.String("app-secret", "", "The app secret from the facebook developer portal (required)") host = flag.String("host", "localhost", "The host used to serve the messenger bot") - port = flag.Int("port", 5000, "The port used to serve the messenger bot") + port = flag.Int("port", 8080, "The port used to serve the messenger bot") ) func main() { diff --git a/messenger.go b/messenger.go index 4bde940..251c240 100644 --- a/messenger.go +++ b/messenger.go @@ -240,7 +240,7 @@ func (m *Messenger) GreetingSetting(text string) error { return checkFacebookError(resp.Body) } -// CallToActionsSetting sends settings for Get Started or Persist Menu +// CallToActionsSetting sends settings for Get Started or Persistent Menu func (m *Messenger) CallToActionsSetting(state string, actions []CallToActionsItem) error { d := CallToActionsSetting{ SettingType: "call_to_actions", diff --git a/parser.go b/parser.go deleted file mode 100644 index 9d8c52d..0000000 --- a/parser.go +++ /dev/null @@ -1,45 +0,0 @@ -package messenger - -import ( - "io/ioutil" - "log" - "os" - "path/filepath" - - "gopkg.in/yaml.v2" -) - -//Config is the struct for the configuration file -type Config struct { - VerifyToken string `yaml:"verify_token"` - AccessToken string `yaml:"access_token"` - AppSecret string `yaml:"app_secret"` -} - -//ReadYml parses the config yml file and format into the Config struct -func (x *Config) ReadYml() *Config { - configFile, err := filepath.Abs("./bot.config.yml") - if err != nil { - log.Printf("ERROR READING THE CONFIG FILE: %s", err) - } - - yamlFile, err := ioutil.ReadFile(configFile) - - if err != nil { - log.Println("Could not find the config file. Please make sure it is created", err) - os.Exit(-1) - } - - yaml.Unmarshal(yamlFile, &x) - - return x -} - -//GetTokens returns the verifytoken, accesstoken and the appsecret from the config file -func GetTokens() (string, string, string) { - var c Config - - configObj := c.ReadYml() - verifyToken, accessToken, appSecret := configObj.VerifyToken, configObj.AccessToken, configObj.AppSecret - return verifyToken, accessToken, appSecret -} From 92e06df4a970ad0fd4f70e2ad67d6255c78170de Mon Sep 17 00:00:00 2001 From: Ayomide Onigbinde Date: Thu, 3 Jan 2019 17:06:29 +0100 Subject: [PATCH 5/8] remove default profile field --- messenger.go | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/messenger.go b/messenger.go index 251c240..70203e5 100644 --- a/messenger.go +++ b/messenger.go @@ -5,6 +5,7 @@ import ( "crypto/hmac" "crypto/sha1" "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -25,11 +26,6 @@ const ( MessengerProfileURL = "https://graph.facebook.com/v2.6/me/messenger_profile" ) -var ( - // NOTE: If you change this slice you should update the comment on the ProfileByID function below too. - defaultProfileFields = []string{"name", "first_name", "last_name", "profile_pic"} -) - // Options are the settings used when creating a Messenger client. type Options struct { // Verify sets whether or not to be in the "verify" mode. Used for @@ -155,14 +151,7 @@ func (m *Messenger) Handler() http.Handler { } // ProfileByID retrieves the Facebook user profile associated with that ID -// when no profile fields are specified it uses some sane defaults. -// -// These default fields are: -// - Name -// - First name -// - Last name -// - Profile picture -func (m *Messenger) ProfileByID(id int64, profileFields ...string) (Profile, error) { +func (m *Messenger) ProfileByID(id int64, profileFields []string) (Profile, error) { p := Profile{} url := fmt.Sprintf("%v%v", ProfileURL, id) @@ -172,7 +161,7 @@ func (m *Messenger) ProfileByID(id int64, profileFields ...string) (Profile, err } if len(profileFields) == 0 { - profileFields = defaultProfileFields + return p, errors.New("Profile field cannot be empty") } fields := strings.Join(profileFields, ",") From 2543a5afbbcdea2b11425d81d3242f592cc3e835 Mon Sep 17 00:00:00 2001 From: Ayomide Onigbinde Date: Thu, 3 Jan 2019 17:40:18 +0100 Subject: [PATCH 6/8] added profile field to examples to fix failing builds --- examples/basic/main.go | 6 +++++- examples/extension/main.go | 7 ++++++- examples/linked-account/main.go | 5 +++++ messenger.go | 10 +++++++++- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/examples/basic/main.go b/examples/basic/main.go index f86d6e0..8ba35ea 100644 --- a/examples/basic/main.go +++ b/examples/basic/main.go @@ -11,6 +11,10 @@ import ( "github.com/paked/messenger" ) +//profileField is a slice of strings of the user profile field the developer wants access +var ( + profileField = []string{"name", "first_name", "last_name", "profile_pic"} +) var ( verifyToken = flag.String("verify-token", "mad-skrilla", "The token used to verify facebook (required)") verify = flag.Bool("should-verify", false, "Whether or not the app should verify itself") @@ -43,7 +47,7 @@ func main() { client.HandleMessage(func(m messenger.Message, r *messenger.Response) { fmt.Printf("%v (Sent, %v)\n", m.Text, m.Time.Format(time.UnixDate)) - p, err := client.ProfileByID(m.Sender.ID) + p, err := client.ProfileByID(m.Sender.ID, profileField) if err != nil { fmt.Println("Something went wrong!", err) } diff --git a/examples/extension/main.go b/examples/extension/main.go index 679d1c3..e469c4f 100644 --- a/examples/extension/main.go +++ b/examples/extension/main.go @@ -11,6 +11,11 @@ import ( "github.com/paked/messenger" ) +//profileField is a slice of strings of the user profile field the developer wants access +var ( + profileField = []string{"name", "first_name", "last_name", "profile_pic"} +) + var ( serverURL = flag.String("serverURL", "", "The server (webview) URL, must be https (required)") verifyToken = flag.String("verify-token", "mad-skrilla", "The token used to verify facebook (required)") @@ -52,7 +57,7 @@ func main() { client.HandleMessage(func(m messenger.Message, r *messenger.Response) { fmt.Printf("%v (Sent, %v)\n", m.Text, m.Time.Format(time.UnixDate)) - p, err := client.ProfileByID(m.Sender.ID) + p, err := client.ProfileByID(m.Sender.ID, profileField) if err != nil { fmt.Println("Something went wrong!", err) } diff --git a/examples/linked-account/main.go b/examples/linked-account/main.go index cfde079..1e216f7 100644 --- a/examples/linked-account/main.go +++ b/examples/linked-account/main.go @@ -14,6 +14,11 @@ import ( "github.com/paked/messenger" ) +//profileField is a slice of strings of the user profile field the developer wants access +var ( + profileField = []string{"name", "first_name", "last_name", "profile_pic"} +) + const ( webhooksPath = "/webhooks" loginPath = "/signin" diff --git a/messenger.go b/messenger.go index 70203e5..a388b5c 100644 --- a/messenger.go +++ b/messenger.go @@ -150,7 +150,15 @@ func (m *Messenger) Handler() http.Handler { return m.mux } -// ProfileByID retrieves the Facebook user profile associated with that ID +// ProfileByID retrieves the Facebook user profile associated with that ID. +// According to the messenger docs: https://developers.facebook.com/docs/messenger-platform/identity/user-profile, +// Developers must ask for access except for some fields that are accessible without permissions. +// +// These fields are +// - Name +// - First Name +// - Last Name +// - Profile Picture func (m *Messenger) ProfileByID(id int64, profileFields []string) (Profile, error) { p := Profile{} url := fmt.Sprintf("%v%v", ProfileURL, id) From 830f72e96e9c626e7f60baaaa599fca502b7d945 Mon Sep 17 00:00:00 2001 From: Ayomide Onigbinde Date: Thu, 3 Jan 2019 17:48:36 +0100 Subject: [PATCH 7/8] fix failed build --- examples/linked-account/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/linked-account/main.go b/examples/linked-account/main.go index 1e216f7..23a6113 100644 --- a/examples/linked-account/main.go +++ b/examples/linked-account/main.go @@ -59,7 +59,7 @@ func main() { client.HandleMessage(func(m messenger.Message, r *messenger.Response) { log.Printf("%v (Sent, %v)\n", m.Text, m.Time.Format(time.UnixDate)) - p, err := client.ProfileByID(m.Sender.ID) + p, err := client.ProfileByID(m.Sender.ID, profileField) if err != nil { log.Println("Failed to fetch user profile:", err) } From 51846268a9aa8ea12acf5431aab6e84d7f9a07ba Mon Sep 17 00:00:00 2001 From: Ayomide Onigbinde Date: Fri, 4 Jan 2019 10:22:09 +0100 Subject: [PATCH 8/8] cleanup for PR #51 --- examples/basic/main.go | 6 +----- examples/extension/main.go | 7 +------ examples/linked-account/main.go | 7 +------ messenger.go | 7 +------ 4 files changed, 4 insertions(+), 23 deletions(-) diff --git a/examples/basic/main.go b/examples/basic/main.go index 8ba35ea..da4c263 100644 --- a/examples/basic/main.go +++ b/examples/basic/main.go @@ -11,10 +11,6 @@ import ( "github.com/paked/messenger" ) -//profileField is a slice of strings of the user profile field the developer wants access -var ( - profileField = []string{"name", "first_name", "last_name", "profile_pic"} -) var ( verifyToken = flag.String("verify-token", "mad-skrilla", "The token used to verify facebook (required)") verify = flag.Bool("should-verify", false, "Whether or not the app should verify itself") @@ -47,7 +43,7 @@ func main() { client.HandleMessage(func(m messenger.Message, r *messenger.Response) { fmt.Printf("%v (Sent, %v)\n", m.Text, m.Time.Format(time.UnixDate)) - p, err := client.ProfileByID(m.Sender.ID, profileField) + p, err := client.ProfileByID(m.Sender.ID, []string{"name", "first_name", "last_name", "profile_pic"}) if err != nil { fmt.Println("Something went wrong!", err) } diff --git a/examples/extension/main.go b/examples/extension/main.go index e469c4f..5f772f0 100644 --- a/examples/extension/main.go +++ b/examples/extension/main.go @@ -11,11 +11,6 @@ import ( "github.com/paked/messenger" ) -//profileField is a slice of strings of the user profile field the developer wants access -var ( - profileField = []string{"name", "first_name", "last_name", "profile_pic"} -) - var ( serverURL = flag.String("serverURL", "", "The server (webview) URL, must be https (required)") verifyToken = flag.String("verify-token", "mad-skrilla", "The token used to verify facebook (required)") @@ -57,7 +52,7 @@ func main() { client.HandleMessage(func(m messenger.Message, r *messenger.Response) { fmt.Printf("%v (Sent, %v)\n", m.Text, m.Time.Format(time.UnixDate)) - p, err := client.ProfileByID(m.Sender.ID, profileField) + p, err := client.ProfileByID(m.Sender.ID, []string{"name", "first_name", "last_name", "profile_pic"}) if err != nil { fmt.Println("Something went wrong!", err) } diff --git a/examples/linked-account/main.go b/examples/linked-account/main.go index 23a6113..7bb9dc6 100644 --- a/examples/linked-account/main.go +++ b/examples/linked-account/main.go @@ -14,11 +14,6 @@ import ( "github.com/paked/messenger" ) -//profileField is a slice of strings of the user profile field the developer wants access -var ( - profileField = []string{"name", "first_name", "last_name", "profile_pic"} -) - const ( webhooksPath = "/webhooks" loginPath = "/signin" @@ -59,7 +54,7 @@ func main() { client.HandleMessage(func(m messenger.Message, r *messenger.Response) { log.Printf("%v (Sent, %v)\n", m.Text, m.Time.Format(time.UnixDate)) - p, err := client.ProfileByID(m.Sender.ID, profileField) + p, err := client.ProfileByID(m.Sender.ID, []string{"name", "first_name", "last_name", "profile_pic"}) if err != nil { log.Println("Failed to fetch user profile:", err) } diff --git a/messenger.go b/messenger.go index a388b5c..67f43c3 100644 --- a/messenger.go +++ b/messenger.go @@ -5,7 +5,6 @@ import ( "crypto/hmac" "crypto/sha1" "encoding/json" - "errors" "fmt" "io/ioutil" "net/http" @@ -154,7 +153,7 @@ func (m *Messenger) Handler() http.Handler { // According to the messenger docs: https://developers.facebook.com/docs/messenger-platform/identity/user-profile, // Developers must ask for access except for some fields that are accessible without permissions. // -// These fields are +// At the time of writing (2019-01-04), these fields are // - Name // - First Name // - Last Name @@ -168,10 +167,6 @@ func (m *Messenger) ProfileByID(id int64, profileFields []string) (Profile, erro return p, err } - if len(profileFields) == 0 { - return p, errors.New("Profile field cannot be empty") - } - fields := strings.Join(profileFields, ",") req.URL.RawQuery = "fields=" + fields + "&access_token=" + m.token