Browse Source

Add OnTyping support and a usage example. Resolves #1

master
Jason Chu 6 years ago
parent
commit
a2b2306933
  1. 3
      README.md
  2. 2
      consts.go
  3. 98
      examples/repeat.go
  4. 27
      listen.go
  5. 2
      send.go

3
README.md

@ -5,5 +5,8 @@
A Go (golang) package that allows you to interact with Facebook chat/Messenger using
an unofficial API ported from [github.com/Schmavery/facebook-chat-api](https://github.com/Schmavery/facebook-chat-api).
## Usage
See the [/examples](/examples) directory for example usage.
## License
messenger is licensed under the MIT license which can be found [here](/LICENSE).

2
consts.go

@ -21,7 +21,7 @@ const (
syncURL = "https://www.facebook.com/notifications/sync/?"
profileURL = "https://www.facebook.com/chat/user_info/"
allProfileURL = "https://www.facebook.com/chat/user_info_all"
userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"
userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36"
formURLEncoded = "application/x-www-form-urlencoded"
loggedOutError = 1357001
)

98
examples/repeat.go

@ -0,0 +1,98 @@
// This is an example of a Facebook messenger chat bot which repeats
// messages it receives. It also persist sessions by saving sessions
// to a file.
// The email and password used is taken from the environment variables
// FBEMAIL and FBPASS.
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"time"
"github.com/1lann/messenger"
)
const sessionFile = "session_data"
var s *messenger.Session
func main() {
s = messenger.NewSession()
login()
err := s.ConnectToChat()
if err != nil {
fmt.Println("Failed to connect to chat:", err)
return
}
fmt.Println("Connected to chat")
// Save the session file every minute. The use of saved session prevents
// Facebook from flagging your bot as suspicious for having to re-log so
// often, and also makes it faster to test your bot as it doesn't need to
// log in again every time.
go func() {
ticker := time.Tick(time.Minute)
for range ticker {
saveSession()
}
}()
s.OnMessage(func(msg *messenger.Message) {
fmt.Println("Received \"" + msg.Body + "\" from " + msg.FromUserID)
resp := s.NewMessageWithThread(msg.Thread)
resp.Body = "You said: " + msg.Body
_, err := s.SendMessage(resp)
if err != nil {
fmt.Println("Failed to send message:", err)
}
})
fmt.Println("Waiting for messages...")
s.Listen()
}
func login() {
sessionData, err := ioutil.ReadFile(sessionFile)
if os.IsNotExist(err) {
fmt.Println("No session file, logging in...")
err = s.Login(os.Getenv("FBEMAIL"), os.Getenv("FBPASS"))
if err != nil {
fmt.Println("Failed to login:", err)
os.Exit(1)
}
return
}
err = s.RestoreSession(sessionData)
if err != nil {
log.Println("Failed to restore session, logging in...")
err = s.Login(os.Getenv("FBEMAIL"), os.Getenv("FBPASS"))
if err != nil {
fmt.Println("Failed to login:", err)
os.Exit(1)
}
return
}
}
func saveSession() {
data, err := s.DumpSession()
if err != nil {
fmt.Println("Failed to save session:", err)
return
}
err = ioutil.WriteFile(sessionFile, data, 0644)
if err != nil {
fmt.Println("Failed to write session to file:", err)
}
}

27
listen.go

@ -32,6 +32,7 @@ type listener struct {
onMessage func(msg *Message)
onRead func(thread Thread, userID string)
onTyping func(thread Thread, userID string, typing bool)
onError func(err error)
processedThreadMessages map[string][]string
@ -84,6 +85,10 @@ func (s *Session) checkListeners() {
if s.l.onRead == nil {
s.l.onRead = func(thread Thread, userID string) {}
}
if s.l.onTyping == nil {
s.l.onTyping = func(thread Thread, userID string, typing bool) {}
}
}
// OnMessage sets the handler for when a message is received.
@ -103,6 +108,11 @@ func (s *Session) OnError(handler func(err error)) {
s.l.onError = handler
}
// OnTyping sets the handler when someone starts typing.
func (s *Session) OnTyping(handler func(thread Thread, userID string, typing bool)) {
s.l.onTyping = handler
}
// Close stops and returns all listeners on the session.
func (s *Session) Close() error {
s.l.closed <- true
@ -238,8 +248,9 @@ func (s *Session) processPull(resp pullResponse) {
s.handleDeltaMessage(msg.Delta.Body, msg.Delta.Metadata)
} else if msg.Type == "messaging" {
if msg.Event == "read_receipt" {
from := strconv.FormatInt(msg.Reader, 10)
thread := Thread{
ThreadID: strconv.FormatInt(msg.Reader, 10),
ThreadID: from,
IsGroup: false,
}
if msg.ThreadID != 0 {
@ -247,8 +258,20 @@ func (s *Session) processPull(resp pullResponse) {
thread.IsGroup = true
}
go s.l.onRead(thread, strconv.FormatInt(msg.Reader, 10))
go s.l.onRead(thread, from)
}
} else if msg.Type == "typ" {
from := strconv.FormatInt(msg.From, 10)
thread := Thread{
ThreadID: from,
IsGroup: false,
}
if msg.ThreadID != 0 {
thread.ThreadID = strconv.FormatInt(msg.ThreadID, 10)
thread.IsGroup = true
}
go s.l.onTyping(thread, from, msg.St > 0)
}
}
}

2
send.go

@ -39,7 +39,7 @@ type sendResponse struct {
}
// SendMessage sends the message to the session. Only the Thread, Body and
// Attachments fields are used for sending.
// Attachments fields are used for sending. The message ID and error is returned.
//
// TODO: Sending does not support attachments yet.
func (s *Session) SendMessage(msg *Message) (string, error) {

Loading…
Cancel
Save