diff options
Diffstat (limited to 'vendor/go.mau.fi/whatsmeow/send.go')
-rw-r--r-- | vendor/go.mau.fi/whatsmeow/send.go | 133 |
1 files changed, 113 insertions, 20 deletions
diff --git a/vendor/go.mau.fi/whatsmeow/send.go b/vendor/go.mau.fi/whatsmeow/send.go index 2647d917..ab754f8f 100644 --- a/vendor/go.mau.fi/whatsmeow/send.go +++ b/vendor/go.mau.fi/whatsmeow/send.go @@ -34,8 +34,8 @@ import ( // GenerateMessageID generates a random string that can be used as a message ID on WhatsApp. // -// msgID := whatsmeow.GenerateMessageID() -// cli.SendMessage(context.Background(), targetJID, msgID, &waProto.Message{...}) +// msgID := whatsmeow.GenerateMessageID() +// cli.SendMessage(context.Background(), targetJID, msgID, &waProto.Message{...}) func GenerateMessageID() types.MessageID { id := make([]byte, 8) _, err := rand.Read(id) @@ -80,9 +80,10 @@ type SendResponse struct { // // The message itself can contain anything you want (within the protobuf schema). // e.g. for a simple text message, use the Conversation field: -// cli.SendMessage(context.Background(), targetJID, "", &waProto.Message{ -// Conversation: proto.String("Hello, World!"), -// }) +// +// cli.SendMessage(context.Background(), targetJID, "", &waProto.Message{ +// Conversation: proto.String("Hello, World!"), +// }) // // Things like replies, mentioning users and the "forwarded" flag are stored in ContextInfo, // which can be put in ExtendedTextMessage and any of the media message types. @@ -114,6 +115,14 @@ func (cli *Client) SendMessage(ctx context.Context, to types.JID, id types.Messa if !isPeerMessage { cli.addRecentMessage(to, id, message) } + if message.GetMessageContextInfo().GetMessageSecret() != nil { + err = cli.Store.MsgSecrets.PutMessageSecret(to, *cli.Store.ID, id, message.GetMessageContextInfo().GetMessageSecret()) + if err != nil { + cli.Log.Warnf("Failed to store message secret key for outgoing message %s: %v", id, err) + } else { + cli.Log.Debugf("Stored message secret key for outgoing message %s", id) + } + } var phash string var data []byte switch to.Server { @@ -163,21 +172,68 @@ func (cli *Client) SendMessage(ctx context.Context, to types.JID, id types.Messa } // RevokeMessage deletes the given message from everyone in the chat. -// You can only revoke your own messages, and if the message is too old, then other users will ignore the deletion. // // This method will wait for the server to acknowledge the revocation message before returning. // The return value is the timestamp of the message from the server. +// +// Deprecated: This method is deprecated in favor of BuildRevoke func (cli *Client) RevokeMessage(chat types.JID, id types.MessageID) (SendResponse, error) { - return cli.SendMessage(context.TODO(), chat, "", &waProto.Message{ + return cli.SendMessage(context.TODO(), chat, "", cli.BuildRevoke(chat, types.EmptyJID, id)) +} + +// BuildRevoke builds a message revocation message using the given variables. +// The built message can be sent normally using Client.SendMessage. +// +// To revoke your own messages, pass your JID or an empty JID as the second parameter (sender). +// +// resp, err := cli.SendMessage(context.Background(), chat, "", cli.BuildRevoke(chat, types.EmptyJID, originalMessageID) +// +// To revoke someone else's messages when you are group admin, pass the message sender's JID as the second parameter. +// +// resp, err := cli.SendMessage(context.Background(), chat, "", cli.BuildRevoke(chat, senderJID, originalMessageID) +func (cli *Client) BuildRevoke(chat, sender types.JID, id types.MessageID) *waProto.Message { + key := &waProto.MessageKey{ + FromMe: proto.Bool(true), + Id: proto.String(id), + RemoteJid: proto.String(chat.String()), + } + if !sender.IsEmpty() && sender.User != cli.Store.ID.User { + key.FromMe = proto.Bool(false) + if chat.Server != types.DefaultUserServer { + key.Participant = proto.String(sender.ToNonAD().String()) + } + } + return &waProto.Message{ ProtocolMessage: &waProto.ProtocolMessage{ Type: waProto.ProtocolMessage_REVOKE.Enum(), - Key: &waProto.MessageKey{ - FromMe: proto.Bool(true), - Id: proto.String(id), - RemoteJid: proto.String(chat.String()), + Key: key, + }, + } +} + +// BuildEdit builds a message edit message using the given variables. +// The built message can be sent normally using Client.SendMessage. +// +// resp, err := cli.SendMessage(context.Background(), chat, "", cli.BuildEdit(chat, originalMessageID, &waProto.Message{ +// Conversation: proto.String("edited message"), +// }) +func (cli *Client) BuildEdit(chat types.JID, id types.MessageID, newContent *waProto.Message) *waProto.Message { + return &waProto.Message{ + EditedMessage: &waProto.FutureProofMessage{ + Message: &waProto.Message{ + ProtocolMessage: &waProto.ProtocolMessage{ + Key: &waProto.MessageKey{ + FromMe: proto.Bool(true), + Id: proto.String(id), + RemoteJid: proto.String(chat.String()), + }, + Type: waProto.ProtocolMessage_MESSAGE_EDIT.Enum(), + EditedMessage: newContent, + TimestampMs: proto.Int64(time.Now().UnixMilli()), + }, }, }, - }) + } } const ( @@ -362,10 +418,16 @@ func getTypeFromMessage(msg *waProto.Message) string { switch { case msg.ViewOnceMessage != nil: return getTypeFromMessage(msg.ViewOnceMessage.Message) + case msg.ViewOnceMessageV2 != nil: + return getTypeFromMessage(msg.ViewOnceMessageV2.Message) case msg.EphemeralMessage != nil: return getTypeFromMessage(msg.EphemeralMessage.Message) + case msg.DocumentWithCaptionMessage != nil: + return getTypeFromMessage(msg.DocumentWithCaptionMessage.Message) case msg.ReactionMessage != nil: return "reaction" + case msg.PollCreationMessage != nil, msg.PollUpdateMessage != nil: + return "poll" case msg.Conversation != nil, msg.ExtendedTextMessage != nil, msg.ProtocolMessage != nil: return "text" //TODO this requires setting mediatype in the enc nodes @@ -376,17 +438,36 @@ func getTypeFromMessage(msg *waProto.Message) string { } } +const ( + EditAttributeEmpty = "" + EditAttributeMessageEdit = "1" + EditAttributeSenderRevoke = "7" + EditAttributeAdminRevoke = "8" +) + +const RemoveReactionText = "" + func getEditAttribute(msg *waProto.Message) string { - if msg.ProtocolMessage != nil && msg.GetProtocolMessage().GetType() == waProto.ProtocolMessage_REVOKE && msg.GetProtocolMessage().GetKey() != nil { - if msg.GetProtocolMessage().GetKey().GetFromMe() { - return "7" - } else { - return "8" + switch { + case msg.ProtocolMessage != nil && msg.ProtocolMessage.GetKey() != nil: + switch msg.ProtocolMessage.GetType() { + case waProto.ProtocolMessage_REVOKE: + if msg.ProtocolMessage.GetKey().GetFromMe() { + return EditAttributeSenderRevoke + } else { + return EditAttributeAdminRevoke + } + case waProto.ProtocolMessage_MESSAGE_EDIT: + if msg.EditedMessage != nil { + return EditAttributeMessageEdit + } } - } else if msg.ReactionMessage != nil && msg.ReactionMessage.GetText() == "" { - return "7" + case msg.ReactionMessage != nil && msg.ReactionMessage.GetText() == RemoveReactionText: + return EditAttributeSenderRevoke + case msg.KeepInChatMessage != nil && msg.KeepInChatMessage.GetKey().GetFromMe() && msg.KeepInChatMessage.GetKeepType() == waProto.KeepType_UNDO_KEEP_FOR_ALL: + return EditAttributeSenderRevoke } - return "" + return EditAttributeEmpty } func (cli *Client) preparePeerMessageNode(to types.JID, id types.MessageID, message *waProto.Message, timings *MessageDebugTimings) (*waBinary.Node, error) { @@ -450,6 +531,18 @@ func (cli *Client) prepareMessageNode(ctx context.Context, to types.JID, id type if includeIdentity { content = append(content, cli.makeDeviceIdentityNode()) } + if attrs["type"] == "poll" { + pollType := "creation" + if message.PollUpdateMessage != nil { + pollType = "vote" + } + content = append(content, waBinary.Node{ + Tag: "meta", + Attrs: waBinary.Attrs{ + "polltype": pollType, + }, + }) + } return &waBinary.Node{ Tag: "message", Attrs: attrs, |