summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/Rhymen/go-whatsapp/chat_history.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/Rhymen/go-whatsapp/chat_history.go')
-rw-r--r--vendor/github.com/Rhymen/go-whatsapp/chat_history.go183
1 files changed, 183 insertions, 0 deletions
diff --git a/vendor/github.com/Rhymen/go-whatsapp/chat_history.go b/vendor/github.com/Rhymen/go-whatsapp/chat_history.go
new file mode 100644
index 00000000..55c7ae63
--- /dev/null
+++ b/vendor/github.com/Rhymen/go-whatsapp/chat_history.go
@@ -0,0 +1,183 @@
+package whatsapp
+
+import (
+ "github.com/Rhymen/go-whatsapp/binary"
+ "github.com/Rhymen/go-whatsapp/binary/proto"
+ "log"
+ "strconv"
+ "time"
+)
+
+type MessageOffsetInfo struct {
+ FirstMessageId string
+ FirstMessageOwner bool
+}
+
+func decodeMessages(n *binary.Node) []*proto.WebMessageInfo {
+
+ var messages = make([]*proto.WebMessageInfo, 0)
+
+ if n == nil || n.Attributes == nil || n.Content == nil {
+ return messages
+ }
+
+ for _, msg := range n.Content.([]interface{}) {
+ switch msg.(type) {
+ case *proto.WebMessageInfo:
+ messages = append(messages, msg.(*proto.WebMessageInfo))
+ default:
+ log.Println("decodeMessages: Non WebMessage encountered")
+ }
+ }
+
+ return messages
+}
+
+// LoadChatMessages is useful to "scroll" messages, loading by count at a time
+// if handlers == nil the func will use default handlers
+// if after == true LoadChatMessages will load messages after the specified messageId, otherwise it will return
+// message before the messageId
+func (wac *Conn) LoadChatMessages(jid string, count int, messageId string, owner bool, after bool, handlers ...Handler) error {
+ if count <= 0 {
+ return nil
+ }
+
+ if handlers == nil {
+ handlers = wac.handler
+ }
+
+ kind := "before"
+ if after {
+ kind = "after"
+ }
+
+ node, err := wac.query("message", jid, messageId, kind,
+ strconv.FormatBool(owner), "", count, 0)
+
+ if err != nil {
+ wac.handleWithCustomHandlers(err, handlers)
+ return err
+ }
+
+ for _, msg := range decodeMessages(node) {
+ wac.handleWithCustomHandlers(ParseProtoMessage(msg), handlers)
+ wac.handleWithCustomHandlers(msg, handlers)
+ }
+ return nil
+
+}
+
+// LoadFullChatHistory loads full chat history for the given jid
+// chunkSize = how many messages to load with one query; if handlers == nil the func will use default handlers;
+// pauseBetweenQueries = how much time to sleep between queries
+func (wac *Conn) LoadFullChatHistory(jid string, chunkSize int,
+ pauseBetweenQueries time.Duration, handlers ...Handler) {
+ if chunkSize <= 0 {
+ return
+ }
+
+ if handlers == nil {
+ handlers = wac.handler
+ }
+
+ beforeMsg := ""
+ beforeMsgIsOwner := true
+
+ for {
+ node, err := wac.query("message", jid, beforeMsg, "before",
+ strconv.FormatBool(beforeMsgIsOwner), "", chunkSize, 0)
+
+ if err != nil {
+ wac.handleWithCustomHandlers(err, handlers)
+ } else {
+
+ msgs := decodeMessages(node)
+ for _, msg := range msgs {
+ wac.handleWithCustomHandlers(ParseProtoMessage(msg), handlers)
+ wac.handleWithCustomHandlers(msg, handlers)
+ }
+
+ if len(msgs) == 0 {
+ break
+ }
+
+ beforeMsg = *msgs[0].Key.Id
+ beforeMsgIsOwner = msgs[0].Key.FromMe != nil && *msgs[0].Key.FromMe
+ }
+
+ <-time.After(pauseBetweenQueries)
+
+ }
+
+}
+
+// LoadFullChatHistoryAfter loads all messages after the specified messageId
+// useful to "catch up" with the message history after some specified message
+func (wac *Conn) LoadFullChatHistoryAfter(jid string, messageId string, chunkSize int,
+ pauseBetweenQueries time.Duration, handlers ...Handler) {
+
+ if chunkSize <= 0 {
+ return
+ }
+
+ if handlers == nil {
+ handlers = wac.handler
+ }
+
+ msgOwner := true
+ prevNotFound := false
+
+ for {
+ node, err := wac.query("message", jid, messageId, "after",
+ strconv.FormatBool(msgOwner), "", chunkSize, 0)
+
+ if err != nil {
+
+ // Whatsapp will return 404 status when there is wrong owner flag on the requested message id
+ if err == ErrServerRespondedWith404 {
+
+ // this will detect two consecutive "not found" errors.
+ // this is done to prevent infinite loop when wrong message id supplied
+ if prevNotFound {
+ log.Println("LoadFullChatHistoryAfter: could not retrieve any messages, wrong message id?")
+ return
+ }
+ prevNotFound = true
+
+ // try to reverse the owner flag and retry
+ if msgOwner {
+ // reverse initial msgOwner value and retry
+ msgOwner = false
+
+ <-time.After(time.Second)
+ continue
+ }
+
+ }
+
+ // if the error isn't a 404 error, pass it to the error handler
+ wac.handleWithCustomHandlers(err, handlers)
+ } else {
+
+ msgs := decodeMessages(node)
+ for _, msg := range msgs {
+ wac.handleWithCustomHandlers(ParseProtoMessage(msg), handlers)
+ wac.handleWithCustomHandlers(msg, handlers)
+ }
+
+ if len(msgs) != chunkSize {
+ break
+ }
+
+ messageId = *msgs[0].Key.Id
+ msgOwner = msgs[0].Key.FromMe != nil && *msgs[0].Key.FromMe
+ }
+
+ // message was found
+ prevNotFound = false
+
+ <-time.After(pauseBetweenQueries)
+
+ }
+
+}