Thumbnail

rani/matterbridge.git

Clone URL: https://git.buni.party/rani/matterbridge.git

commit 6e09da6ce2cf17ace693cb1f1242e3059e96feb0 Author: selfhoster1312 <selfhoster1312@kl.netlib.re> Date: Thu Dec 11 15:50:17 2025 +0000 whatsapp: Deprecate broken legacy bridge diff --git a/bridge/whatsapp/handlers.go b/bridge/whatsapp/handlers.go deleted file mode 100644 index e0c6faa..0000000 --- a/bridge/whatsapp/handlers.go +++ /dev/null @@ -1382 +00 @@ -// nolint:goconst -package bwhatsapp - -import ( - "fmt" - "mime" - "strings" - "time" - - "github.com/Rhymen/go-whatsapp" - "github.com/jpillora/backoff" - "github.com/matterbridge-org/matterbridge/bridge/config" - "github.com/matterbridge-org/matterbridge/bridge/helper" -) - -/* -Implement handling messages coming from WhatsApp -Check: -- https://github.com/Rhymen/go-whatsapp#add-message-handlers -- https://github.com/Rhymen/go-whatsapp/blob/master/handler.go -- https://github.com/tulir/mautrix-whatsapp/tree/master/whatsapp-ext for more advanced command handling -*/ - -// HandleError received from WhatsApp -func (b *Bwhatsapp) HandleError(err error) { - // ignore received invalid data errors. https://github.com/42wim/matterbridge/issues/843 - // ignore tag 174 errors. https://github.com/42wim/matterbridge/issues/1094 - if strings.Contains(err.Error(), "error processing data: received invalid data") || - strings.Contains(err.Error(), "invalid string with tag 174") { - return - } - - switch err.(type) { - case *whatsapp.ErrConnectionClosed, *whatsapp.ErrConnectionFailed: - b.reconnect(err) - default: - switch err { - case whatsapp.ErrConnectionTimeout: - b.reconnect(err) - default: - b.Log.Errorf("%v", err) - } - } -} - -func (b *Bwhatsapp) reconnect(err error) { - bf := &backoff.Backoff{ - Min: time.Second, - Max: 5 * time.Minute, - Jitter: true, - } - - for { - d := bf.Duration() - - b.Log.Errorf("Connection failed, underlying error: %v", err) - b.Log.Infof("Waiting %s...", d) - - time.Sleep(d) - - b.Log.Info("Reconnecting...") - - err := b.conn.Restore() - if err == nil { - bf.Reset() - b.startedAt = uint64(time.Now().Unix()) - - return - } - } -} - -// HandleTextMessage sent from WhatsApp, relay it to the brige -func (b *Bwhatsapp) HandleTextMessage(message whatsapp.TextMessage) { - if message.Info.FromMe { - return - } - // whatsapp sends last messages to show context , cut them - if message.Info.Timestamp < b.startedAt { - return - } - - groupJID := message.Info.RemoteJid - senderJID := message.Info.SenderJid - - if len(senderJID) == 0 { - if message.Info.Source != nil && message.Info.Source.Participant != nil { - senderJID = *message.Info.Source.Participant - } - } - - // translate sender's JID to the nicest username we can get - senderName := b.getSenderName(senderJID) - if senderName == "" { - senderName = "Someone" // don't expose telephone number - } - - extText := message.Info.Source.Message.ExtendedTextMessage - if extText != nil && extText.ContextInfo != nil && extText.ContextInfo.MentionedJid != nil { - // handle user mentions - for _, mentionedJID := range extText.ContextInfo.MentionedJid { - numberAndSuffix := strings.SplitN(mentionedJID, "@", 2) - - // mentions comes as telephone numbers and we don't want to expose it to other bridges - // replace it with something more meaninful to others - mention := b.getSenderNotify(numberAndSuffix[0] + "@s.whatsapp.net") - if mention == "" { - mention = "someone" - } - - message.Text = strings.Replace(message.Text, "@"+numberAndSuffix[0], "@"+mention, 1) - } - } - - rmsg := config.Message{ - UserID: senderJID, - Username: senderName, - Text: message.Text, - Channel: groupJID, - Account: b.Account, - Protocol: b.Protocol, - Extra: make(map[string][]interface{}), - // ParentID: TODO, // TODO handle thread replies // map from Info.QuotedMessageID string - ID: message.Info.Id, - } - - if avatarURL, exists := b.userAvatars[senderJID]; exists { - rmsg.Avatar = avatarURL - } - - b.Log.Debugf("<= Sending message from %s on %s to gateway", senderJID, b.Account) - b.Log.Debugf("<= Message is %#v", rmsg) - - b.Remote <- rmsg -} - -// HandleImageMessage sent from WhatsApp, relay it to the brige -// nolint:funlen -func (b *Bwhatsapp) HandleImageMessage(message whatsapp.ImageMessage) { - if message.Info.FromMe || message.Info.Timestamp < b.startedAt { - return - } - - senderJID := message.Info.SenderJid - if len(message.Info.SenderJid) == 0 && message.Info.Source != nil && message.Info.Source.Participant != nil { - senderJID = *message.Info.Source.Participant - } - - senderName := b.getSenderName(message.Info.SenderJid) - if senderName == "" { - senderName = "Someone" // don't expose telephone number - } - - rmsg := config.Message{ - UserID: senderJID, - Username: senderName, - Channel: message.Info.RemoteJid, - Account: b.Account, - Protocol: b.Protocol, - Extra: make(map[string][]interface{}), - ID: message.Info.Id, - } - - if avatarURL, exists := b.userAvatars[senderJID]; exists { - rmsg.Avatar = avatarURL - } - - fileExt, err := mime.ExtensionsByType(message.Type) - if err != nil { - b.Log.Errorf("Mimetype detection error: %s", err) - - return - } - - // rename .jfif to .jpg https://github.com/42wim/matterbridge/issues/1292 - if fileExt[0] == ".jfif" { - fileExt[0] = ".jpg" - } - - // rename .jpe to .jpg https://github.com/42wim/matterbridge/issues/1463 - if fileExt[0] == ".jpe" { - fileExt[0] = ".jpg" - } - - filename := fmt.Sprintf("%v%v", message.Info.Id, fileExt[0]) - - b.Log.Debugf("Trying to download %s with type %s", filename, message.Type) - - data, err := message.Download() - if err != nil { - b.Log.Errorf("Download image failed: %s", err) - - return - } - - // Move file to bridge storage - helper.HandleDownloadData(b.Log, &rmsg, filename, message.Caption, "", &data, b.General) - - b.Log.Debugf("<= Sending message from %s on %s to gateway", senderJID, b.Account) - b.Log.Debugf("<= Message is %#v", rmsg) - - b.Remote <- rmsg -} - -// HandleVideoMessage downloads video messages -func (b *Bwhatsapp) HandleVideoMessage(message whatsapp.VideoMessage) { - if message.Info.FromMe || message.Info.Timestamp < b.startedAt { - return - } - - senderJID := message.Info.SenderJid - if len(message.Info.SenderJid) == 0 && message.Info.Source != nil && message.Info.Source.Participant != nil { - senderJID = *message.Info.Source.Participant - } - - senderName := b.getSenderName(message.Info.SenderJid) - if senderName == "" { - senderName = "Someone" // don't expose telephone number - } - - rmsg := config.Message{ - UserID: senderJID, - Username: senderName, - Channel: message.Info.RemoteJid, - Account: b.Account, - Protocol: b.Protocol, - Extra: make(map[string][]interface{}), - ID: message.Info.Id, - } - - if avatarURL, exists := b.userAvatars[senderJID]; exists { - rmsg.Avatar = avatarURL - } - - fileExt, err := mime.ExtensionsByType(message.Type) - if err != nil { - b.Log.Errorf("Mimetype detection error: %s", err) - - return - } - - if len(fileExt) == 0 { - fileExt = append(fileExt, ".mp4") - } - - filename := fmt.Sprintf("%v%v", message.Info.Id, fileExt[0]) - - b.Log.Debugf("Trying to download %s with size %#v and type %s", filename, message.Length, message.Type) - - data, err := message.Download() - if err != nil { - b.Log.Errorf("Download video failed: %s", err) - - return - } - - // Move file to bridge storage - helper.HandleDownloadData(b.Log, &rmsg, filename, message.Caption, "", &data, b.General) - - b.Log.Debugf("<= Sending message from %s on %s to gateway", senderJID, b.Account) - b.Log.Debugf("<= Message is %#v", rmsg) - - b.Remote <- rmsg -} - -// HandleAudioMessage downloads audio messages -func (b *Bwhatsapp) HandleAudioMessage(message whatsapp.AudioMessage) { - if message.Info.FromMe || message.Info.Timestamp < b.startedAt { - return - } - - senderJID := message.Info.SenderJid - if len(message.Info.SenderJid) == 0 && message.Info.Source != nil && message.Info.Source.Participant != nil { - senderJID = *message.Info.Source.Participant - } - - senderName := b.getSenderName(message.Info.SenderJid) - if senderName == "" { - senderName = "Someone" // don't expose telephone number - } - - rmsg := config.Message{ - UserID: senderJID, - Username: senderName, - Channel: message.Info.RemoteJid, - Account: b.Account, - Protocol: b.Protocol, - Extra: make(map[string][]interface{}), - ID: message.Info.Id, - } - - if avatarURL, exists := b.userAvatars[senderJID]; exists { - rmsg.Avatar = avatarURL - } - - fileExt, err := mime.ExtensionsByType(message.Type) - if err != nil { - b.Log.Errorf("Mimetype detection error: %s", err) - - return - } - - if len(fileExt) == 0 { - fileExt = append(fileExt, ".ogg") - } - - filename := fmt.Sprintf("%v%v", message.Info.Id, fileExt[0]) - - b.Log.Debugf("Trying to download %s with size %#v and type %s", filename, message.Length, message.Type) - - data, err := message.Download() - if err != nil { - b.Log.Errorf("Download audio failed: %s", err) - - return - } - - // Move file to bridge storage - helper.HandleDownloadData(b.Log, &rmsg, filename, "audio message", "", &data, b.General) - - b.Log.Debugf("<= Sending message from %s on %s to gateway", senderJID, b.Account) - b.Log.Debugf("<= Message is %#v", rmsg) - - b.Remote <- rmsg -} - -// HandleDocumentMessage downloads documents -func (b *Bwhatsapp) HandleDocumentMessage(message whatsapp.DocumentMessage) { - if message.Info.FromMe || message.Info.Timestamp < b.startedAt { - return - } - - senderJID := message.Info.SenderJid - if len(message.Info.SenderJid) == 0 && message.Info.Source != nil && message.Info.Source.Participant != nil { - senderJID = *message.Info.Source.Participant - } - - senderName := b.getSenderName(message.Info.SenderJid) - if senderName == "" { - senderName = "Someone" // don't expose telephone number - } - - rmsg := config.Message{ - UserID: senderJID, - Username: senderName, - Channel: message.Info.RemoteJid, - Account: b.Account, - Protocol: b.Protocol, - Extra: make(map[string][]interface{}), - ID: message.Info.Id, - } - - if avatarURL, exists := b.userAvatars[senderJID]; exists { - rmsg.Avatar = avatarURL - } - - fileExt, err := mime.ExtensionsByType(message.Type) - if err != nil { - b.Log.Errorf("Mimetype detection error: %s", err) - - return - } - - filename := fmt.Sprintf("%v", message.FileName) - - b.Log.Debugf("Trying to download %s with extension %s and type %s", filename, fileExt, message.Type) - - data, err := message.Download() - if err != nil { - b.Log.Errorf("Download document message failed: %s", err) - - return - } - - // Move file to bridge storage - helper.HandleDownloadData(b.Log, &rmsg, filename, "document", "", &data, b.General) - - b.Log.Debugf("<= Sending message from %s on %s to gateway", senderJID, b.Account) - b.Log.Debugf("<= Message is %#v", rmsg) - - b.Remote <- rmsg -} diff --git a/bridge/whatsapp/helpers.go b/bridge/whatsapp/helpers.go deleted file mode 100644 index 9d39d36..0000000 --- a/bridge/whatsapp/helpers.go +++ /dev/null @@ -1162 +00 @@ -package bwhatsapp - -import ( - "encoding/gob" - "encoding/json" - "errors" - "fmt" - "os" - "strings" - - qrcodeTerminal "github.com/Baozisoftware/qrcode-terminal-go" - "github.com/Rhymen/go-whatsapp" -) - -type ProfilePicInfo struct { - URL string `json:"eurl"` - Tag string `json:"tag"` - Status int16 `json:"status"` -} - -func qrFromTerminal(invert bool) chan string { - qr := make(chan string) - - go func() { - terminal := qrcodeTerminal.New() - - if invert { - terminal = qrcodeTerminal.New2(qrcodeTerminal.ConsoleColors.BrightWhite, qrcodeTerminal.ConsoleColors.BrightBlack, qrcodeTerminal.QRCodeRecoveryLevels.Medium) - } - - terminal.Get(<-qr).Print() - }() - - return qr -} - -func (b *Bwhatsapp) readSession() (whatsapp.Session, error) { - session := whatsapp.Session{} - sessionFile := b.Config.GetString(sessionFile) - - if sessionFile == "" { - return session, errors.New("if you won't set SessionFile then you will need to scan QR code on every restart") - } - - file, err := os.Open(sessionFile) - if err != nil { - return session, err - } - - defer file.Close() - - decoder := gob.NewDecoder(file) - - return session, decoder.Decode(&session) -} - -func (b *Bwhatsapp) writeSession(session whatsapp.Session) error { - sessionFile := b.Config.GetString(sessionFile) - - if sessionFile == "" { - // we already sent a warning while starting the bridge, so let's be quiet here - return nil - } - - file, err := os.Create(sessionFile) - if err != nil { - return err - } - - defer file.Close() - - encoder := gob.NewEncoder(file) - - return encoder.Encode(session) -} - -func (b *Bwhatsapp) restoreSession() (*whatsapp.Session, error) { - session, err := b.readSession() - if err != nil { - b.Log.Warn(err.Error()) - } - - b.Log.Debugln("Restoring WhatsApp session..") - - session, err = b.conn.RestoreWithSession(session) - if err != nil { - // restore session connection timed out (I couldn't get over it without logging in again) - return nil, errors.New("failed to restore session: " + err.Error()) - } - - b.Log.Debugln("Session restored successfully!") - - return &session, nil -} - -func (b *Bwhatsapp) getSenderName(senderJid string) string { - if sender, exists := b.users[senderJid]; exists { - if sender.Name != "" { - return sender.Name - } - // if user is not in phone contacts - // it is the most obvious scenario unless you sync your phone contacts with some remote updated source - // users can change it in their WhatsApp settings -> profile -> click on Avatar - if sender.Notify != "" { - return sender.Notify - } - - if sender.Short != "" { - return sender.Short - } - } - - // try to reload this contact - if _, err := b.conn.Contacts(); err != nil { - b.Log.Errorf("error on update of contacts: %v", err) - } - - if contact, exists := b.conn.Store.Contacts[senderJid]; exists { - // Add it to the user map - b.users[senderJid] = contact - - if contact.Name != "" { - return contact.Name - } - // if user is not in phone contacts - // same as above - return contact.Notify - } - - return "" -} - -func (b *Bwhatsapp) getSenderNotify(senderJid string) string { - if sender, exists := b.users[senderJid]; exists { - return sender.Notify - } - - return "" -} - -func (b *Bwhatsapp) GetProfilePicThumb(jid string) (*ProfilePicInfo, error) { - data, err := b.conn.GetProfilePicThumb(jid) - if err != nil { - return nil, fmt.Errorf("failed to get avatar: %v", err) - } - - content := <-data - info := &ProfilePicInfo{} - - err = json.Unmarshal([]byte(content), info) - if err != nil { - return info, fmt.Errorf("failed to unmarshal avatar info: %v", err) - } - - return info, nil -} - -func isGroupJid(identifier string) bool { - return strings.HasSuffix(identifier, "@g.us") || - strings.HasSuffix(identifier, "@temp") || - strings.HasSuffix(identifier, "@broadcast") -} diff --git a/bridge/whatsapp/whatsapp.go b/bridge/whatsapp/whatsapp.go deleted file mode 100644 index 447fad0..0000000 --- a/bridge/whatsapp/whatsapp.go +++ /dev/null @@ -1341 +00 @@ -package bwhatsapp - -import ( - "bytes" - "crypto/rand" - "encoding/hex" - "errors" - "fmt" - "mime" - "os" - "path/filepath" - "strings" - "time" - - "github.com/Rhymen/go-whatsapp" - "github.com/matterbridge-org/matterbridge/bridge" - "github.com/matterbridge-org/matterbridge/bridge/config" -) - -const ( - // Account config parameters - cfgNumber = "Number" - qrOnWhiteTerminal = "QrOnWhiteTerminal" - sessionFile = "SessionFile" -) - -// Bwhatsapp Bridge structure keeping all the information needed for relying -type Bwhatsapp struct { - *bridge.Config - - session *whatsapp.Session - conn *whatsapp.Conn - startedAt uint64 - - users map[string]whatsapp.Contact - userAvatars map[string]string -} - -// New Create a new WhatsApp bridge. This will be called for each [whatsapp.<server>] entry you have in the config file -func New(cfg *bridge.Config) bridge.Bridger { - number := cfg.GetString(cfgNumber) - - cfg.Log.Warn("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - cfg.Log.Warn("This bridge is deprecated and not supported anymore. Use the new multidevice whatsapp bridge") - cfg.Log.Warn("See https://github.com/42wim/matterbridge#building-with-whatsapp-beta-multidevice-support for more info") - cfg.Log.Warn("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - - if number == "" { - cfg.Log.Fatalf("Missing configuration for WhatsApp bridge: Number") - } - - b := &Bwhatsapp{ - Config: cfg, - - users: make(map[string]whatsapp.Contact), - userAvatars: make(map[string]string), - } - - return b -} - -// Connect to WhatsApp. Required implementation of the Bridger interface -func (b *Bwhatsapp) Connect() error { - number := b.GetString(cfgNumber) - if number == "" { - return errors.New("whatsapp's telephone number need to be configured") - } - - b.Log.Debugln("Connecting to WhatsApp..") - conn, err := whatsapp.NewConn(20 * time.Second) - if err != nil { - return errors.New("failed to connect to WhatsApp: " + err.Error()) - } - - b.conn = conn - - b.conn.AddHandler(b) - b.Log.Debugln("WhatsApp connection successful") - - // load existing session in order to keep it between restarts - b.session, err = b.restoreSession() - if err != nil { - b.Log.Warn(err.Error()) - } - - // login to a new session - if b.session == nil { - if err = b.Login(); err != nil { - return err - } - } - - b.startedAt = uint64(time.Now().Unix()) - - _, err = b.conn.Contacts() - if err != nil { - return fmt.Errorf("error on update of contacts: %v", err) - } - - // see https://github.com/Rhymen/go-whatsapp/issues/137#issuecomment-480316013 - for len(b.conn.Store.Contacts) == 0 { - b.conn.Contacts() // nolint:errcheck - - <-time.After(1 * time.Second) - } - - // map all the users - for id, contact := range b.conn.Store.Contacts { - if !isGroupJid(id) && id != "status@broadcast" { - // it is user - b.users[id] = contact - } - } - - // get user avatar asynchronously - go func() { - b.Log.Debug("Getting user avatars..") - - for jid := range b.users { - info, err := b.GetProfilePicThumb(jid) - if err != nil { - b.Log.Warnf("Could not get profile photo of %s: %v", jid, err) - } else { - b.Lock() - b.userAvatars[jid] = info.URL - b.Unlock() - } - } - - b.Log.Debug("Finished getting avatars..") - }() - - return nil -} - -// Login to WhatsApp creating a new session. This will require to scan a QR code on your mobile device -func (b *Bwhatsapp) Login() error { - b.Log.Debugln("Logging in..") - - invert := b.GetBool(qrOnWhiteTerminal) // false is the default - qrChan := qrFromTerminal(invert) - - session, err := b.conn.Login(qrChan) - if err != nil { - b.Log.Warnln("Failed to log in:", err) - - return err - } - - b.session = &session - - b.Log.Infof("Logged into session: %#v", session) - b.Log.Infof("Connection: %#v", b.conn) - - err = b.writeSession(session) - if err != nil { - fmt.Fprintf(os.Stderr, "error saving session: %v\n", err) - } - - return nil -} - -// Disconnect is called while reconnecting to the bridge -// Required implementation of the Bridger interface -func (b *Bwhatsapp) Disconnect() error { - // We could Logout, but that would close the session completely and would require a new QR code scan - // https://github.com/Rhymen/go-whatsapp/blob/c31092027237441cffba1b9cb148eadf7c83c3d2/session.go#L377-L381 - return nil -} - -// JoinChannel Join a WhatsApp group specified in gateway config as channel='number-id@g.us' or channel='Channel name' -// Required implementation of the Bridger interface -// https://github.com/42wim/matterbridge/blob/2cfd880cdb0df29771bf8f31df8d990ab897889d/bridge/bridge.go#L11-L16 -func (b *Bwhatsapp) JoinChannel(channel config.ChannelInfo) error { - byJid := isGroupJid(channel.Name) - - // see https://github.com/Rhymen/go-whatsapp/issues/137#issuecomment-480316013 - for len(b.conn.Store.Contacts) == 0 { - b.conn.Contacts() // nolint:errcheck - <-time.After(1 * time.Second) - } - - // verify if we are member of the given group - if byJid { - // channel.Name specifies static group jID, not the name - if _, exists := b.conn.Store.Contacts[channel.Name]; !exists { - return fmt.Errorf("account doesn't belong to group with jid %s", channel.Name) - } - - return nil - } - - // channel.Name specifies group name that might change, warn about it - var jids []string - for id, contact := range b.conn.Store.Contacts { - if isGroupJid(id) && contact.Name == channel.Name { - jids = append(jids, id) - } - } - - switch len(jids) { - case 0: - // didn't match any group - print out possibilites - for id, contact := range b.conn.Store.Contacts { - if isGroupJid(id) { - b.Log.Infof("%s %s", contact.Jid, contact.Name) - } - } - - return fmt.Errorf("please specify group's JID from the list above instead of the name '%s'", channel.Name) - case 1: - return fmt.Errorf("group name might change. Please configure gateway with channel=\"%v\" instead of channel=\"%v\"", jids[0], channel.Name) - default: - return fmt.Errorf("there is more than one group with name '%s'. Please specify one of JIDs as channel name: %v", channel.Name, jids) - } -} - -// Post a document message from the bridge to WhatsApp -func (b *Bwhatsapp) PostDocumentMessage(msg config.Message, filetype string) (string, error) { - fi := msg.Extra["file"][0].(config.FileInfo) - - // Post document message - message := whatsapp.DocumentMessage{ - Info: whatsapp.MessageInfo{ - RemoteJid: msg.Channel, - }, - Title: fi.Name, - FileName: fi.Name, - Type: filetype, - Content: bytes.NewReader(*fi.Data), - } - - b.Log.Debugf("=> Sending %#v", msg) - - // create message ID - // TODO follow and act if https://github.com/Rhymen/go-whatsapp/issues/101 implemented - idBytes := make([]byte, 10) - if _, err := rand.Read(idBytes); err != nil { - b.Log.Warn(err.Error()) - } - - message.Info.Id = strings.ToUpper(hex.EncodeToString(idBytes)) - _, err := b.conn.Send(message) - - return message.Info.Id, err -} - -// Post an image message from the bridge to WhatsApp -// Handle, for sure image/jpeg, image/png and image/gif MIME types -func (b *Bwhatsapp) PostImageMessage(msg config.Message, filetype string) (string, error) { - fi := msg.Extra["file"][0].(config.FileInfo) - - // Post image message - message := whatsapp.ImageMessage{ - Info: whatsapp.MessageInfo{ - RemoteJid: msg.Channel, - }, - Type: filetype, - Caption: msg.Username + fi.Comment, - Content: bytes.NewReader(*fi.Data), - } - - b.Log.Debugf("=> Sending %#v", msg) - - // create message ID - // TODO follow and act if https://github.com/Rhymen/go-whatsapp/issues/101 implemented - idBytes := make([]byte, 10) - if _, err := rand.Read(idBytes); err != nil { - b.Log.Warn(err.Error()) - } - - message.Info.Id = strings.ToUpper(hex.EncodeToString(idBytes)) - _, err := b.conn.Send(message) - - return message.Info.Id, err -} - -// Send a message from the bridge to WhatsApp -// Required implementation of the Bridger interface -// https://github.com/42wim/matterbridge/blob/2cfd880cdb0df29771bf8f31df8d990ab897889d/bridge/bridge.go#L11-L16 -func (b *Bwhatsapp) Send(msg config.Message) (string, error) { - b.Log.Debugf("=> Receiving %#v", msg) - - // Delete message - if msg.Event == config.EventMsgDelete { - if msg.ID == "" { - // No message ID in case action is executed on a message sent before the bridge was started - // and then the bridge cache doesn't have this message ID mapped - return "", nil - } - - _, err := b.conn.RevokeMessage(msg.Channel, msg.ID, true) - - return "", err - } - - // Edit message - if msg.ID != "" { - b.Log.Debugf("updating message with id %s", msg.ID) - - if b.GetString("editsuffix") != "" { - msg.Text += b.GetString("EditSuffix") - } else { - msg.Text += " (edited)" - } - } - - // Handle Upload a file - if msg.Extra["file"] != nil { - fi := msg.Extra["file"][0].(config.FileInfo) - filetype := mime.TypeByExtension(filepath.Ext(fi.Name)) - - b.Log.Debugf("Extra file is %#v", filetype) - - // TODO: add different types - // TODO: add webp conversion - switch filetype { - case "image/jpeg", "image/png", "image/gif": - return b.PostImageMessage(msg, filetype) - default: - return b.PostDocumentMessage(msg, filetype) - } - } - - // Post text message - message := whatsapp.TextMessage{ - Info: whatsapp.MessageInfo{ - RemoteJid: msg.Channel, // which equals to group id - }, - Text: msg.Username + msg.Text, - } - - b.Log.Debugf("=> Sending %#v", msg) - - return b.conn.Send(message) -} - -// TODO do we want that? to allow login with QR code from a bridged channel? https://github.com/tulir/mautrix-whatsapp/blob/513eb18e2d59bada0dd515ee1abaaf38a3bfe3d5/commands.go#L76 -//func (b *Bwhatsapp) Command(cmd string) string { -// return "" -//} diff --git a/changelog.md b/changelog.md index 64a71e8..3909dda 100644 --- a/changelog.md +++ b/changelog.md @@ -116 +117 @@   - steam protocol has changed profoundly   - keybase has been removed because we don't have a maintainer for it. See [issue #9](https://github.com/matterbridge-org/matterbridge/issues/9) + - whatsapp backend has been deprecated in favor of whatsappmulti. See [issue #32](https://github.com/matterbridge-org/matterbridge/issues/32)  - xmpp: Initial replies/edits support has been removed, because it was incorrect ([#12](https://github.com/matterbridge-org/matterbridge/pull/12))  - Go required version is now v1.24   diff --git a/gateway/bridgemap/bwhatsapp.go b/gateway/bridgemap/bwhatsapp.go deleted file mode 100644 index 42dfb2d..0000000 --- a/gateway/bridgemap/bwhatsapp.go +++ /dev/null @@ -112 +00 @@ -//go:build !nowhatsapp && !whatsappmulti -// +build !nowhatsapp,!whatsappmulti - -package bridgemap - -import ( - bwhatsapp "github.com/matterbridge-org/matterbridge/bridge/whatsapp" -) - -func init() { - FullMap["whatsapp"] = bwhatsapp.New -} diff --git a/go.mod b/go.mod index a0fd38d..2e3c1e9 100644 --- a/go.mod +++ b/go.mod @@ -19 +17 @@  module github.com/matterbridge-org/matterbridge    require ( - github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f   github.com/Benau/tgsconverter v0.0.0-20210809170556-99f4a4f6337f - github.com/Rhymen/go-whatsapp v0.1.2-0.20211102134409-31a2e740845c   github.com/SevereCloud/vksdk/v2 v2.17.0   github.com/bwmarrin/discordgo v0.28.1   github.com/d5/tengo/v2 v2.17.0 @@ -1137 +1116 @@ require (   github.com/sagikazarmark/slog-shim v0.1.0 // indirect   github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4 // indirect   github.com/sizeofint/webpanimation v0.0.0-20210809145948-1d2b32119882 // indirect - github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 // indirect   github.com/sourcegraph/conc v0.3.0 // indirect   github.com/spf13/afero v1.11.0 // indirect   github.com/spf13/cast v1.6.0 // indirect diff --git a/go.sum b/go.sum index 56400c0..9654a0e 100644 --- a/go.sum +++ b/go.sum @@ -98 +96 @@ dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D  filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=  filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=  git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f h1:2dk3eOnYllh+wUOuDhOoC2vUVoJF/5z478ryJ+wzEII= -github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f/go.mod h1:4a58ifQTEe2uwwsaqbh3i2un5/CBPg+At/qHpt18Tmk=  github.com/Benau/go_rlottie v0.0.0-20210807002906-98c1b2421989 h1:+wrfJITuBoQOE6ST4k3c4EortNVQXVhfAbwt0M/j0+Y=  github.com/Benau/go_rlottie v0.0.0-20210807002906-98c1b2421989/go.mod h1:aDWSWjsayFyGTvHZH3v4ijGXEBe51xcEkAK+NUWeOeo=  github.com/Benau/tgsconverter v0.0.0-20210809170556-99f4a4f6337f h1:aUkwZDEMJIGRcWlSDifSLoKG37UCOH/DPeG52/xwois= @@ -208 +186 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7Oputl  github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=  github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo=  github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= -github.com/Rhymen/go-whatsapp v0.1.2-0.20211102134409-31a2e740845c h1:4mIZQXKYBymQ9coA82nNyG/CjicMNLBZ8cPVrhNUM3g= -github.com/Rhymen/go-whatsapp v0.1.2-0.20211102134409-31a2e740845c/go.mod h1:DNSFRLFDFIqm2+0aJzSOVfn25020vldM4SRqz6YtLgI=  github.com/SevereCloud/vksdk/v2 v2.17.0 h1:Wll63JSuBTdE0L7+V/PMn9PyhLrWSWIjX76XpWbXTFw=  github.com/SevereCloud/vksdk/v2 v2.17.0/go.mod h1:y3q3XAdqnQ2Wf0B+Wi7qNdqJc5ZZsz4ve+DoSQsrChk=  github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM= @@ -507 +466 @@ github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp  github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=  github.com/bwmarrin/discordgo v0.28.1 h1:gXsuo2GBO7NbR6uqmrrBDplPUx2T3nzu775q/Rd1aG4=  github.com/bwmarrin/discordgo v0.28.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=  github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=  github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=  github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= @@ -708 +656 @@ github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a h1:  github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a/go.mod h1:emQhSYTXqB0xxjLITTw4EaWZ+8IIQYw+kx9GqNUKdLg=  github.com/elliotchance/orderedmap/v3 v3.1.0 h1:j4DJ5ObEmMBt/lcwIecKcoRxIQUEnw0L804lXYDt/pg=  github.com/elliotchance/orderedmap/v3 v3.1.0/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=  github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=  github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=  github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= @@ -10323 +9612 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb  github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=  github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=  github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=  github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=  github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=  github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2 h1:yEt5djSYb4iNtmV9iJGVday+i4e9u6Mrn5iP64HH5QM=  github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=  github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=  github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=  github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=  github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=  github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= @@ -1417 +1236 @@ github.com/gopackage/ddp v0.0.3/go.mod h1:3hUXYG6C/6JsoxKsQaK7st09+GP9RZBFPzyAlU  github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=  github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E=  github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=  github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=  github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=  github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -3027 +2836 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI  github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=  github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=  github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=  github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=  github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=  github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -3638 +3436 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ  github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=  github.com/sizeofint/webpanimation v0.0.0-20210809145948-1d2b32119882 h1:A7o8tOERTtpD/poS+2VoassCjXpjHn916luXbf5QKD0=  github.com/sizeofint/webpanimation v0.0.0-20210809145948-1d2b32119882/go.mod h1:5IwJoz9Pw7JsrCN4/skkxUtSWT7myuUPLhCgv6Q5vvQ= -github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 h1:lpEzuenPuO1XNTeikEmvqYFcU37GVLl8SRNblzyvGBE= -github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=  github.com/slack-go/slack v0.17.3 h1:zV5qO3Q+WJAQ/XwbGfNFrRMaJ5T/naqaonyPV/1TP4g=  github.com/slack-go/slack v0.17.3/go.mod h1:X+UqOufi3LYQHDnMG1vxf0J8asC6+WllXrVrhl8/Prk=  github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= @@ -4717 +4496 @@ golang.org/x/image v0.19.0/go.mod h1:y0zrRqlQRWQ5PXaYCOMLTW2fpsxZ8Qh9I/ohnInJEys  golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=  golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=  golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=  golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=  golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=  golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= @@ -4837 +4606 @@ golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73r  golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=  golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=  golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=  golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=  golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=  golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -5568 +5326 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm  golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=  golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=  golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=  golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=  golang.org/x/tools v0.0.0-20200529172331-a64b76657301/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=  golang.org/x/tools v0.0.0-20200731060945-b5fad4ed8dd6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= @@ -58026 +55414 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA  google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=  google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=  google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=  google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade h1:oCRSWfwGXQsqlVdErcyTt4A93Y8fo0/9D4b1gnI++qo=  google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=  google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=  google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=  google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=  google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=  google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=  google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=  google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=  google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=  gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -6267 +5886 @@ grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJd  honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=  honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=  honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=  layeh.com/gopus v0.0.0-20161224163843-0ebf989153aa/go.mod h1:AOef7vHz0+v4sWwJnr0jSyHiX/1NgsMoaxl+rEPz/I0=  layeh.com/gumble v0.0.0-20221205141517-d1df60a3cc14 h1:wY8eeq7DpM5iAugNbFrvuhdtmN8XM1iU+Ki5YZWjukg=  layeh.com/gumble v0.0.0-20221205141517-d1df60a3cc14/go.mod h1:tWPVA9ZAfImNwabjcd9uDE+Mtz0Hfs7a7G3vxrnrwyc=