func (s *Session) AllThreads() (res []*ThreadInfo, err error) {
	defer essentials.AddCtxTo("fbmsgr: all threads", &err)
	var lastTime time.Time
	for {
		listing, err := s.Threads(lastTime, threadBufferSize)
		if err != nil {
			return nil, err
		}
		if len(res) > 0 && len(listing) > 0 {
			if res[len(res)-1].ThreadFBID == listing[0].ThreadFBID {
				listing = listing[1:]
			}
		}
		res = append(res, listing...)
		if len(listing) < threadBufferSize {
			break
		}
		lastTime = listing[len(listing)-1].UpdatedTime
	}
	return res, nil
}
AllThreads reads the full list of chat threads.
package fbmsgr
import (
	"strconv"
	"time"
	"github.com/unixpickle/essentials"
)
const (
	threadBufferSize = 100
	actionBufferSize = 500
)
const (
	actionLogDocID = "1547392382048831"
	threadLogDocID = "2276493972392017"
)
type ThreadInfo struct {
	ThreadFBID string
	OtherUserID *string
	Name *string
	Image *string
	Participants []*ParticipantInfo
	Snippet       string
	SnippetSender string
	UnreadCount  int
	MessageCount int
	UpdatedTime time.Time
}
type ParticipantInfo struct {
	FBID   string
	Gender string
	URL    string
	ImageSrc    string
	BigImageSrc string
	Username  string
	Name      string
	ShortName string
}
func (s *Session) Threads(timestamp time.Time, limit int) (res []*ThreadInfo, err error) {
	defer essentials.AddCtxTo("fbmsgr: threads", &err)
	var response struct {
		Viewer struct {
			MessageThreads struct {
				Nodes []*threadInfoResult `json:"nodes"`
			} `json:"message_threads"`
		} `json:"viewer"`
	}
	params := map[string]interface{}{
		"limit": limit,
		"tags":  []string{"INBOX"},
		"includeDeliveryReceipts": true,
		"includeSeqID":            false,
	}
	if timestamp.IsZero() {
		params["before"] = nil
	} else {
		params["before"] = strconv.FormatInt(timestamp.UnixNano()/1e6, 10)
	}
	if err := s.graphQLDoc(threadLogDocID, params, &response); err != nil {
		return nil, err
	}
	for _, result := range response.Viewer.MessageThreads.Nodes {
		res = append(res, result.ThreadInfo())
	}
	return
}