fbmsgr

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 12, 2018 License: BSD-2-Clause Imports: 25 Imported by: 2

README

fbmsgr

Reverse engineering Facebook Messenger.

Tags

This is a fork of unixpickle/fbmsgr which contains a modified Session struct with an exposed http.Client, so that its cookies may be read by other packages.

Original README:

This is a wrapper around Facebook Messenger's internal AJAX protocol. This wrapper could be used for any number of cool things, such as:

  • Tracking your friends' Messenger activity.
  • Analyzing your conversations (e.g. keywords analysis)
  • Automating "Away" messages
  • Creating chat bots

Current status

Currently, the API is fairly reliable and can perform a bunch of basic functionalities. Here is a list of supported features (it may lag slightly behind the master branch):

  • Send textual messages to people or groups
  • Send attachments to people or groups
  • Receive messages with or without attachments
  • Send read receipts
  • Receive events for incoming messages
  • Receive events for friend "Last Active" updates
  • Set chat text colors (to arbitrary RGB colors)
  • List a user's threads.
  • List messages in a thread.
  • Send and receive typing events
  • Delete messages

TODOs

  • Support emojis in threads (i.e. the like button)
  • In FullActionLog, remove all duplicates, incase two messages have the same timestamp.
  • Emoji/sticker transmission
  • Modifying chat preferences (emoji, nicknames, etc.)
  • View pending message requests
  • Create new group chats

License

This is under a BSD 2-clause license. See LICENSE.

Documentation

Overview

Package fbmsgr provides an API for interacting with Facebook Messenger.

Authentication

The first step is to create a new Messenger session. Do this as follows, replacing "USER" and "PASS" with your Facebook login credentials:

sess, err := fbmsgr.Auth("USER", "PASS")
if err != nil {
    // Handle login failure.
}

Once you are done with a session you have allocated, you should call Close() on it to clear any resources (e.g. goroutines) that it is using.

Sending messages

When sending a message, you specify a receiver by their FBID. The receiver may be another user, or it may be a group. For most methods related to message sending, there is one version of the method for a user and one for a group:

sess.SendText("USER_FBID", "what's up?")
sess.SendGroupText("GROUP_FBID", "what's up?")

To send or retract a typing notification, you might do:

sess.SendTyping("USER_FBID", true) // typing
sess.SendTyping("USER_FBID", false) // stopped typing
sess.SendGroupTyping("GROUP_FBID", true)

To send an attachment such as an image or a video, you can do the following:

f, err := os.Open("/path/to/image.png")
if err != nil {
    // Handle failure.
}
defer f.Close()
upload, err := sess.Upload("image.png", f)
if err != nil {
    // Handle failure.
}
_, err = sess.SendAttachment("USER_ID", upload)
// or sess.SendGroupAttachment("GROUP_ID", upload)
if err != nil {
    // Handle failure.
}

Events

It is easy to receive events such as incoming messages using the ReadEvent method:

for {
    x, err := sess.ReadEvent()
    if err != nil {
        // Handle error.
    }
    if msg, ok := x.(fbmsgr.MessageEvent); ok {
        if msg.SenderFBID == sess.FBID() {
            // It is a message that we sent.
            // This allows us to see messages we send
            // from a different device.
            continue
        }
        fmt.Println("received message:", msg)
        if msg.GroupThread != "" {
            sess.SendReadReceipt(msg.GroupThread)
        } else {
            sess.SendReadReceipt(msg.OtherUser)
        }
    } else if typ, ok := x.(fbmsgr.TypingEvent); ok {
        fmt.Println("user is typing:", typ)
    } else if del, ok := x.(fbmsgr.DeleteMessageEvent); ok {
        fmt.Println("we deleted a message:", del)
    }
}

With the EventStream API, you can get more fine-grained control over how you receive events. For example, you can read the next minute's worth of events like so:

stream := sess.EventStream()
defer stream.Close()
timeout := time.After(time.Minute)
for {
    select {
    case evt := <-stream.Chan():
        // Process event here.
    case <-timeout:
        return
    }
}

You can also create multiple EventStreams and read from different streams in different places.

Listing threads

To list the threads (conversations) a user is in, you can use the Threads method to fetch a subset of threads at a time. You can also use the AllThreads method to fetch all the threads at once.

Index

Constants

View Source
const (
	AudioAttachmentType         = "audio"
	ImageAttachmentType         = "photo"
	AnimatedImageAttachmentType = "animated_image"
	StickerAttachmentType       = "sticker"
	FileAttachmentType          = "file"
	VideoAttachmentType         = "video"
)

These are attachment type IDs used by Messenger.

View Source
const (
	BaseURL          = "https://www.messenger.com"
	SpoofedUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/20100101 Firefox/43.0"
)
View Source
const (
	SmallEmoji  EmojiSize = "small"
	MediumEmoji           = "medium"
	LargeEmoji            = "large"
)
View Source
const (
	MessageActionType = "UserMessage"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Action

type Action interface {
	// ActionType returns Messenger's internal type string
	// for the action.
	// For exampe, this might be MessageActionType.
	ActionType() string

	// ActionTime returns the timestamp of the action.
	ActionTime() time.Time

	// MessageID returns the message ID of the action.
	MessageID() string

	// AuthorFBID returns the FBID of the action's sender.
	AuthorFBID() string

	// RawFields returns the raw JSON object for the action.
	RawFields() map[string]interface{}
}

An Action is something which occurred in a thread. For example, an incoming message is an action.

type Attachment

type Attachment interface {
	// AttachmentType returns the internal type name for this
	// attachment (such as ImageAttachmentType).
	AttachmentType() string

	// URL returns the most relevant URL for the attachment.
	// For instance, this might be a download URL for a file
	// or an image URL for a sticker.
	URL() string
}

An Attachment is an abstract non-textual entity attached to a message.

type AudioAttachment

type AudioAttachment struct {
	Name     string
	AudioURL string
}

A AudioAttachment is an attachment for an audio file.

func (*AudioAttachment) AttachmentType

func (f *AudioAttachment) AttachmentType() string

AttachmentType returns the internal attachment type for file attachments.

func (*AudioAttachment) String

func (f *AudioAttachment) String() string

String returns a brief description of the attachment.

func (*AudioAttachment) URL

func (f *AudioAttachment) URL() string

URL returns the file download URL.

type BuddyEvent

type BuddyEvent struct {
	FBID       string
	LastActive time.Time
}

A BuddyEvent is an Event containing information about a buddy's updated status.

type DeleteMessageEvent

type DeleteMessageEvent struct {
	MessageIDs []string

	// If non-empty, this specifies the group chat ID.
	GroupThread string

	// If non-empty, this specifies the other user in a
	// one-on-one chat (as opposed to a group chat).
	OtherUser string
}

DeleteMessageEvent indicates that a message has been deleted.

type EmojiSize

type EmojiSize string

type Event

type Event interface{}

An Event is a notification pushed to the client by the server.

type EventStream

type EventStream struct {
	// contains filtered or unexported fields
}

An EventStream is a live stream of events.

Create an event stream using Session.EventStream(). Destroy an event stream using EventStream.Close().

func (*EventStream) Chan

func (e *EventStream) Chan() <-chan Event

Chan returns a channel of events for the stream.

The channel is closed if the stream is closed or if an error is encountered.

func (*EventStream) Close

func (e *EventStream) Close() error

Close closes the stream.

This will cause the event channel to be closed. However, the result from Error() will not be changed.

func (*EventStream) Error

func (e *EventStream) Error() error

Error returns the first error encountered while reading the stream.

type FileAttachment

type FileAttachment struct {
	Name    string
	FileURL string
}

A FileAttachment is an attachment for a raw file.

func (*FileAttachment) AttachmentType

func (f *FileAttachment) AttachmentType() string

AttachmentType returns the internal attachment type for file attachments.

func (*FileAttachment) String

func (f *FileAttachment) String() string

String returns a brief description of the attachment.

func (*FileAttachment) URL

func (f *FileAttachment) URL() string

URL returns the file download URL.

type GenericAction

type GenericAction struct {
	// RawData contains the raw JSON value of this
	// action.
	RawData map[string]interface{}
}

A GenericAction is an Action with no action-specific fields. It is used as a base class for other Actions, and when an unknown or unsupported action is encountered.

func (*GenericAction) ActionTime

func (g *GenericAction) ActionTime() time.Time

ActionTime extracts the action's timestamp.

func (*GenericAction) ActionType

func (g *GenericAction) ActionType() string

ActionType extracts the action's type.

func (*GenericAction) AuthorFBID

func (g *GenericAction) AuthorFBID() string

AuthorFBID extracts the action's sender's FBID.

func (*GenericAction) MessageID

func (g *GenericAction) MessageID() string

MessageID extracts the action's message ID.

func (*GenericAction) RawFields

func (g *GenericAction) RawFields() map[string]interface{}

RawFields returns the raw data.

func (*GenericAction) String

func (g *GenericAction) String() string

String returns a generic string representation of the action.

type ImageAttachment

type ImageAttachment struct {
	FBID   string
	Width  int
	Height int

	Animated bool

	PreviewURL    string
	PreviewWidth  int
	PreviewHeight int

	LargePreviewURL    string
	LargePreviewWidth  int
	LargePreviewHeight int

	ThumbnailURL string
	HiResURL     string
}

An ImageAttachment is an Attachment with specific info about an image.

func (*ImageAttachment) AttachmentType

func (i *ImageAttachment) AttachmentType() string

AttachmentType returns the internal attachment type for image attachments.

func (*ImageAttachment) String

func (i *ImageAttachment) String() string

String returns a brief description of the attachment.

func (*ImageAttachment) URL

func (i *ImageAttachment) URL() string

URL returns the high-resolution URL.

type MessageAction

type MessageAction struct {
	GenericAction

	Body        string
	Attachments []Attachment
}

A MessageAction is an Action for a user-sent message.

type MessageEvent

type MessageEvent struct {
	// MessageID is a unique ID used to distinguish a message
	// from others in a chat log.
	MessageID string

	// Body is the text in the message.
	// It is "" if the message contains no text.
	Body string

	// Attachments contains the message's attachments.
	Attachments []Attachment

	// SenderFBID is the fbid of the sending user.
	// This may be the current user, especially if the user
	// sent the message from a different device.
	SenderFBID string

	// If non-empty, this specifies the group chat ID.
	GroupThread string

	// If non-empty, this specifies the other user in a
	// one-on-one chat (as opposed to a group chat).
	OtherUser string
}

A MessageEvent is an Event containing a new message.

type ParticipantInfo

type ParticipantInfo struct {
	FBID   string
	Gender string
	URL    string

	ImageSrc    string
	BigImageSrc string

	Username  string
	Name      string
	ShortName string
}

ParticipantInfo stores information about a user.

type Session

type Session struct {
	Client *http.Client
	// contains filtered or unexported fields
}

A Session is an authenticated session with the messenger backend.

func Auth

func Auth(user, password string) (sess *Session, err error)

Auth creates a new Session by authenticating with the Facebook backend.

func (*Session) ActionLog

func (s *Session) ActionLog(fbid string, timestamp time.Time,
	limit int) (log []Action, err error)

ActionLog reads the contents of a thread.

The fbid parameter specifies the other user ID or the group thread ID.

The timestamp parameter specifies the timestamp of the earliest action seen from the last call to ActionLog. It may be the 0 time, in which case the most recent actions will be fetched.

The limit parameter indicates the maximum number of actions to fetch.

func (*Session) AllThreads

func (s *Session) AllThreads() (res []*ThreadInfo, err error)

AllThreads reads the full list of chat threads.

func (*Session) Close

func (s *Session) Close() error

Close cleans up the session's resources. Any running EventStreams created from this session should be closed separately.

This closes the default event stream, meaning that all ReadEvent calls will fail after Close() is finished.

func (*Session) DeleteMessage

func (s *Session) DeleteMessage(id string) (err error)

DeleteMessage deletes a message given its ID.

func (*Session) EventStream

func (s *Session) EventStream() *EventStream

EventStream creates a new EventStream for the session.

You must close the result when you are done with it.

func (*Session) FBID

func (s *Session) FBID() string

FBID returns the authenticated user's FBID.

func (*Session) FullActionLog

func (s *Session) FullActionLog(fbid string, cancel <-chan struct{}) (<-chan Action, <-chan error)

FullActionLog fetches all of the actions in a thread and returns them in reverse chronological order over a channel.

The cancel channel, if non-nil, can be closed to stop the fetch early.

The returned channels will both be closed once the fetch has completed or been cancelled. If an error is encountered during the fetch, it is sent over the (buffered) error channel and the fetch will be aborted.

func (*Session) ProfilePicture

func (s *Session) ProfilePicture(fbid string) (picURL *url.URL, err error)

ProfilePicture gets a URL to a user's profile picture.

func (*Session) ReadEvent

func (s *Session) ReadEvent() (Event, error)

ReadEvent reads the next event from a default event stream. The first call will create the default event stream.

ReadEvent is present for backward-compatibility. You should consider using the EventStream API rather than ReadEvent.

If the stream is closed or fails with an error, a nil event is returned with an error (io.EOF if the read only failed because the stream was closed).

func (*Session) SendAttachment

func (s *Session) SendAttachment(userFBID string, a *UploadResult) (mid string, err error)

SendAttachment sends an attachment to another user. For group chats, use SendGroupAttachment.

func (*Session) SendGroupAttachment

func (s *Session) SendGroupAttachment(groupFBID string, a *UploadResult) (mid string, err error)

SendGroupAttachment is like SendAttachment for groups.

func (*Session) SendGroupLike

func (s *Session) SendGroupLike(groupFBID, emoji string, size EmojiSize) (msgID string, err error)

SendGroupLike is like SendLike, but for a group thread.

func (*Session) SendGroupText

func (s *Session) SendGroupText(groupFBID, message string) (msgID string, err error)

SendGroupText is like SendText, but the message is sent to a group chat rather than to an individual.

func (*Session) SendGroupTyping

func (s *Session) SendGroupTyping(groupFBID string, typing bool) (err error)

SendGroupTyping sends a typing notification to a group.

func (*Session) SendLike

func (s *Session) SendLike(fbid, emoji string, size EmojiSize) (msgID string, err error)

SendLike is like SendText, but it sends an emoji at a given size. It is crutial that the emoji is valid and that the size is also valid. Otherwise, this can trigger a bug in the web client that essentially bricks the conversation.

func (*Session) SendReadReceipt

func (s *Session) SendReadReceipt(fbid string) (err error)

SendReadReceipt sends a read receipt to a group chat or a chat with an individual user.

func (*Session) SendText

func (s *Session) SendText(fbid, message string) (msgID string, err error)

SendText attempts to send a textual message to the user with the given fbid.

func (*Session) SendTyping

func (s *Session) SendTyping(userFBID string, typing bool) (err error)

SendTyping sends a typing notification to a user. For group chats, use SendGroupTyping.

func (*Session) SetChatColor

func (s *Session) SetChatColor(fbid, cssColor string) (err error)

SetChatColor sets the chat color in a thread or for a one-on-one chat with a user. The cssColor argument is something like "#ff7e29".

func (*Session) Threads

func (s *Session) Threads(timestamp time.Time, limit int) (res []*ThreadInfo, err error)

Threads reads a range of the user's chat threads.

The timestamp parameter specifies the timestamp of the earliest thread seen from the last call to Threads. It may be the 0 time, in which case the most recent threads will be fetched.

The limit specifies the maximum number of threads.

func (*Session) Upload

func (s *Session) Upload(filename string, file io.Reader) (res *UploadResult, err error)

Upload uploads a file to be sent as an attachment.

type StickerAttachment

type StickerAttachment struct {
	RawURL string

	StickerID int64
	PackID    int64

	SpriteURI         string
	SpriteURI2x       string
	PaddedSpriteURI   string
	PaddedSpriteURI2x string
	FrameCount        int
	FrameRate         int
	FramesPerRow      int
	FramesPerCol      int

	Width  int
	Height int
}

A StickerAttachment is an Attachment with specific info about a sticker.

func (*StickerAttachment) AttachmentType

func (s *StickerAttachment) AttachmentType() string

AttachmentType returns the internal attachment type for sticker attachments.

func (*StickerAttachment) String

func (s *StickerAttachment) String() string

String returns a brief description of the attachment.

func (*StickerAttachment) URL

func (s *StickerAttachment) URL() string

URL returns the raw URL of the sticker.

type ThreadInfo

type ThreadInfo struct {
	ThreadFBID string

	// Other user (nil for group chats).
	OtherUserID *string

	// Optional custom name for the chat.
	Name *string

	// Optional image URL.
	Image *string

	Participants []*ParticipantInfo

	Snippet       string
	SnippetSender string

	UnreadCount  int
	MessageCount int

	UpdatedTime time.Time
}

ThreadInfo stores information about a chat thread. A chat thread is facebook's internal name for a conversation (either a group chat or a 1-on-1).

type TypingEvent

type TypingEvent struct {
	// SenderFBID is the user who is typing.
	SenderFBID string

	// Typing indicates whether or not the user is typing.
	Typing bool

	// If non-empty, this specifies the group chat ID.
	GroupThread string
}

A TypingEvent indicates that a user has started or stopped typing.

type UnknownAttachment

type UnknownAttachment struct {
	Type string

	// RawData contains the attachment's JSON data.
	RawData map[string]interface{}
}

An UnknownAttachment is an Attachment of an unknown or unsupported type.

func (*UnknownAttachment) AttachmentType

func (u *UnknownAttachment) AttachmentType() string

AttachmentType returns the attachment's type. This may be "".

func (*UnknownAttachment) String

func (u *UnknownAttachment) String() string

String returns a brief description of the attachment.

func (*UnknownAttachment) URL

func (u *UnknownAttachment) URL() string

URL returns the empty string.

type UploadResult

type UploadResult struct {
	// One of the following strings will be non-nil after
	// a successful upload.
	VideoID string
	FileID  string
	AudioID string
	ImageID string
}

UploadResult is the result of uploading a file.

type VideoAttachment

type VideoAttachment struct {
	FBID     string
	Name     string
	VideoURL string

	Width  int
	Height int

	PreviewURL    string
	PreviewWidth  int
	PreviewHeight int

	LargePreviewURL    string
	LargePreviewWidth  int
	LargePreviewHeight int

	ThumbnailURL string
}

func (*VideoAttachment) AttachmentType

func (v *VideoAttachment) AttachmentType() string

AttachmentType returns the internal attachment type for video attachments.

func (*VideoAttachment) String

func (v *VideoAttachment) String() string

String returns a brief description of the attachment.

func (*VideoAttachment) URL

func (v *VideoAttachment) URL() string

URL returns the main video URL.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL