forked from MirrorHub/mautrix-whatsapp
Implement joining groups and checking invite links
This commit is contained in:
parent
1f91eacc10
commit
1e5d5c1a3e
5 changed files with 73 additions and 48 deletions
61
commands.go
61
commands.go
|
@ -130,7 +130,7 @@ func (handler *CommandHandler) CommandMux(ce *CommandEvent) {
|
||||||
handler.CommandLogout(ce)
|
handler.CommandLogout(ce)
|
||||||
case "toggle":
|
case "toggle":
|
||||||
handler.CommandToggle(ce)
|
handler.CommandToggle(ce)
|
||||||
case "set-relay", "unset-relay", "login-matrix", "sync", "list", "open", "pm", "invite-link", "join", "create":
|
case "set-relay", "unset-relay", "login-matrix", "sync", "list", "open", "pm", "invite-link", "check-invite", "join", "create":
|
||||||
if !ce.User.HasSession() {
|
if !ce.User.HasSession() {
|
||||||
ce.Reply("You are not logged in. Use the `login` command to log into WhatsApp.")
|
ce.Reply("You are not logged in. Use the `login` command to log into WhatsApp.")
|
||||||
return
|
return
|
||||||
|
@ -154,6 +154,8 @@ func (handler *CommandHandler) CommandMux(ce *CommandEvent) {
|
||||||
handler.CommandPM(ce)
|
handler.CommandPM(ce)
|
||||||
case "invite-link":
|
case "invite-link":
|
||||||
handler.CommandInviteLink(ce)
|
handler.CommandInviteLink(ce)
|
||||||
|
case "check-invite":
|
||||||
|
handler.CommandCheckInvite(ce)
|
||||||
case "join":
|
case "join":
|
||||||
handler.CommandJoin(ce)
|
handler.CommandJoin(ce)
|
||||||
case "create":
|
case "create":
|
||||||
|
@ -223,25 +225,44 @@ func (handler *CommandHandler) CommandVersion(ce *CommandEvent) {
|
||||||
ce.Reply(fmt.Sprintf("[%s](%s) %s (%s)", Name, URL, linkifiedVersion, BuildTime))
|
ce.Reply(fmt.Sprintf("[%s](%s) %s (%s)", Name, URL, linkifiedVersion, BuildTime))
|
||||||
}
|
}
|
||||||
|
|
||||||
const cmdInviteLinkHelp = `invite-link - Get an invite link to the current group chat.`
|
const cmdInviteLinkHelp = `invite-link [--reset] - Get an invite link to the current group chat, optionally regenerating the link and revoking the old link.`
|
||||||
|
|
||||||
func (handler *CommandHandler) CommandInviteLink(ce *CommandEvent) {
|
func (handler *CommandHandler) CommandInviteLink(ce *CommandEvent) {
|
||||||
|
reset := len(ce.Args) > 0 && strings.ToLower(ce.Args[0]) == "--reset"
|
||||||
if ce.Portal == nil {
|
if ce.Portal == nil {
|
||||||
ce.Reply("Not a portal room")
|
ce.Reply("Not a portal room")
|
||||||
} else if ce.Portal.IsPrivateChat() {
|
} else if ce.Portal.IsPrivateChat() {
|
||||||
ce.Reply("Can't get invite link to private chat")
|
ce.Reply("Can't get invite link to private chat")
|
||||||
} else if ce.Portal.IsBroadcastList() {
|
} else if ce.Portal.IsBroadcastList() {
|
||||||
ce.Reply("Can't get invite link to broadcast list")
|
ce.Reply("Can't get invite link to broadcast list")
|
||||||
} else if link, err := ce.User.Client.GetGroupInviteLink(ce.Portal.Key.JID); err != nil {
|
} else if link, err := ce.User.Client.GetGroupInviteLink(ce.Portal.Key.JID, reset); err != nil {
|
||||||
ce.Reply("Failed to get invite link: %v", err)
|
ce.Reply("Failed to get invite link: %v", err)
|
||||||
} else {
|
} else {
|
||||||
ce.Reply(link)
|
ce.Reply(link)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const cmdJoinHelp = `join <invite link> - Join a group chat with an invite link.`
|
const cmdCheckInviteHelp = `check-invite <invite link> - Resolve an invite link and check which group it points at.`
|
||||||
const inviteLinkPrefix = "https://chat.whatsapp.com/"
|
const inviteLinkPrefix = "https://chat.whatsapp.com/"
|
||||||
|
|
||||||
|
func (handler *CommandHandler) CommandCheckInvite(ce *CommandEvent) {
|
||||||
|
if len(ce.Args) == 0 {
|
||||||
|
ce.Reply("**Usage:** `join <invite link>`")
|
||||||
|
return
|
||||||
|
} else if len(ce.Args[0]) <= len(inviteLinkPrefix) || ce.Args[0][:len(inviteLinkPrefix)] != inviteLinkPrefix {
|
||||||
|
ce.Reply("That doesn't look like a WhatsApp invite link")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
group, err := ce.User.Client.GetGroupInfoFromLink(ce.Args[0])
|
||||||
|
if err != nil {
|
||||||
|
ce.Reply("Failed to get group info: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ce.Reply("That invite link points at %s (`%s`)", group.Name, group.JID)
|
||||||
|
}
|
||||||
|
|
||||||
|
const cmdJoinHelp = `join <invite link> - Join a group chat with an invite link.`
|
||||||
|
|
||||||
func (handler *CommandHandler) CommandJoin(ce *CommandEvent) {
|
func (handler *CommandHandler) CommandJoin(ce *CommandEvent) {
|
||||||
if len(ce.Args) == 0 {
|
if len(ce.Args) == 0 {
|
||||||
ce.Reply("**Usage:** `join <invite link>`")
|
ce.Reply("**Usage:** `join <invite link>`")
|
||||||
|
@ -251,28 +272,13 @@ func (handler *CommandHandler) CommandJoin(ce *CommandEvent) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ce.Reply("Not yet implemented")
|
jid, err := ce.User.Client.JoinGroupViaLink(ce.Args[0])
|
||||||
// TODO reimplement
|
if err != nil {
|
||||||
//jid, err := ce.User.Conn.GroupAcceptInviteCode(ce.Args[0][len(inviteLinkPrefix):])
|
ce.Reply("Failed to join group: %v", err)
|
||||||
//if err != nil {
|
return
|
||||||
// ce.Reply("Failed to join group: %v", err)
|
}
|
||||||
// return
|
handler.log.Debugln("%s successfully joined group %s", ce.User.MXID, jid)
|
||||||
//}
|
ce.Reply("Successfully joined group `%s`, the portal should be created momentarily", jid)
|
||||||
//
|
|
||||||
//handler.log.Debugln("%s successfully joined group %s", ce.User.MXID, jid)
|
|
||||||
//portal := handler.bridge.GetPortalByJID(database.GroupPortalKey(jid))
|
|
||||||
//if len(portal.MXID) > 0 {
|
|
||||||
// portal.Sync(ce.User, whatsapp.Contact{JID: portal.Key.JID})
|
|
||||||
// ce.Reply("Successfully joined group \"%s\" and synced portal room: [%s](https://matrix.to/#/%s)", portal.Name, portal.Name, portal.MXID)
|
|
||||||
//} else {
|
|
||||||
// err = portal.CreateMatrixRoom(ce.User)
|
|
||||||
// if err != nil {
|
|
||||||
// ce.Reply("Failed to create portal room: %v", err)
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ce.Reply("Successfully joined group \"%s\" and created portal room: [%s](https://matrix.to/#/%s)", portal.Name, portal.Name, portal.MXID)
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const cmdCreateHelp = `create - Create a group chat.`
|
const cmdCreateHelp = `create - Create a group chat.`
|
||||||
|
@ -625,6 +631,7 @@ func (handler *CommandHandler) CommandHelp(ce *CommandEvent) {
|
||||||
cmdPrefix + cmdOpenHelp,
|
cmdPrefix + cmdOpenHelp,
|
||||||
cmdPrefix + cmdPMHelp,
|
cmdPrefix + cmdPMHelp,
|
||||||
cmdPrefix + cmdInviteLinkHelp,
|
cmdPrefix + cmdInviteLinkHelp,
|
||||||
|
cmdPrefix + cmdCheckInviteHelp,
|
||||||
cmdPrefix + cmdJoinHelp,
|
cmdPrefix + cmdJoinHelp,
|
||||||
cmdPrefix + cmdCreateHelp,
|
cmdPrefix + cmdCreateHelp,
|
||||||
cmdPrefix + cmdSetPowerLevelHelp,
|
cmdPrefix + cmdSetPowerLevelHelp,
|
||||||
|
@ -873,7 +880,7 @@ func (handler *CommandHandler) CommandPM(ce *CommandEvent) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = portal.CreateMatrixRoom(user)
|
err = portal.CreateMatrixRoom(user, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ce.Reply("Failed to create portal room: %v", err)
|
ce.Reply("Failed to create portal room: %v", err)
|
||||||
return
|
return
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -8,7 +8,7 @@ require (
|
||||||
github.com/mattn/go-sqlite3 v1.14.9
|
github.com/mattn/go-sqlite3 v1.14.9
|
||||||
github.com/prometheus/client_golang v1.11.0
|
github.com/prometheus/client_golang v1.11.0
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||||
go.mau.fi/whatsmeow v0.0.0-20211031131127-03a69c3e343b
|
go.mau.fi/whatsmeow v0.0.0-20211031175440-39cd01efeed7
|
||||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
|
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
|
||||||
google.golang.org/protobuf v1.27.1
|
google.golang.org/protobuf v1.27.1
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -139,8 +139,8 @@ github.com/tidwall/sjson v1.2.3 h1:5+deguEhHSEjmuICXZ21uSSsXotWMA0orU783+Z7Cp8=
|
||||||
github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs=
|
github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs=
|
||||||
go.mau.fi/libsignal v0.0.0-20211024113310-f9fc6a1855f2 h1:xpQTMgJGGaF+c8jV/LA/FVXAPJxZbSAGeflOc+Ly6uQ=
|
go.mau.fi/libsignal v0.0.0-20211024113310-f9fc6a1855f2 h1:xpQTMgJGGaF+c8jV/LA/FVXAPJxZbSAGeflOc+Ly6uQ=
|
||||||
go.mau.fi/libsignal v0.0.0-20211024113310-f9fc6a1855f2/go.mod h1:3XlVlwOfp8f9Wri+C1D4ORqgUsN4ZvunJOoPjQMBhos=
|
go.mau.fi/libsignal v0.0.0-20211024113310-f9fc6a1855f2/go.mod h1:3XlVlwOfp8f9Wri+C1D4ORqgUsN4ZvunJOoPjQMBhos=
|
||||||
go.mau.fi/whatsmeow v0.0.0-20211031131127-03a69c3e343b h1:GvVBHYS4iBduhXtsPsnqJtrt8BP1OqYp6OdZqYtt/xY=
|
go.mau.fi/whatsmeow v0.0.0-20211031175440-39cd01efeed7 h1:AxqjTj5ejuTUGrpG21Ot/dIjY946OjveZM08SACeDhw=
|
||||||
go.mau.fi/whatsmeow v0.0.0-20211031131127-03a69c3e343b/go.mod h1:ODEmmqeUn9eBDQHFc1S902YA3YFLtmaBujYRRFl53jI=
|
go.mau.fi/whatsmeow v0.0.0-20211031175440-39cd01efeed7/go.mod h1:ODEmmqeUn9eBDQHFc1S902YA3YFLtmaBujYRRFl53jI=
|
||||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
|
38
portal.go
38
portal.go
|
@ -201,7 +201,7 @@ func (portal *Portal) handleMessageLoop() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
portal.log.Debugln("Creating Matrix room from incoming message")
|
portal.log.Debugln("Creating Matrix room from incoming message")
|
||||||
err := portal.CreateMatrixRoom(msg.source)
|
err := portal.CreateMatrixRoom(msg.source, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
portal.log.Errorln("Failed to create portal room:", err)
|
portal.log.Errorln("Failed to create portal room:", err)
|
||||||
continue
|
continue
|
||||||
|
@ -533,7 +533,7 @@ func (portal *Portal) SyncParticipants(source *User, metadata *types.GroupInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedLevel := 0
|
expectedLevel := 0
|
||||||
if participant.JID == metadata.OwnerJID {
|
if participant.JID == metadata.OwnerJID || participant.IsSuperAdmin {
|
||||||
expectedLevel = 95
|
expectedLevel = 95
|
||||||
} else if participant.IsAdmin {
|
} else if participant.IsAdmin {
|
||||||
expectedLevel = 50
|
expectedLevel = 50
|
||||||
|
@ -737,11 +737,11 @@ func (portal *Portal) ensureUserInvited(user *User) (ok bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (portal *Portal) Sync(user *User) bool {
|
func (portal *Portal) Sync(user *User, groupInfo *types.GroupInfo) bool {
|
||||||
portal.log.Infoln("Syncing portal for", user.MXID)
|
portal.log.Infoln("Syncing portal for", user.MXID)
|
||||||
|
|
||||||
if len(portal.MXID) == 0 {
|
if len(portal.MXID) == 0 {
|
||||||
err := portal.CreateMatrixRoom(user)
|
err := portal.CreateMatrixRoom(user, groupInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
portal.log.Errorln("Failed to create portal room:", err)
|
portal.log.Errorln("Failed to create portal room:", err)
|
||||||
return false
|
return false
|
||||||
|
@ -1197,7 +1197,7 @@ var BackfillDummyStateEvent = event.Type{Type: "fi.mau.dummy.blank_backfill_stat
|
||||||
var BackfillEndDummyEvent = event.Type{Type: "fi.mau.dummy.backfill_end", Class: event.MessageEventType}
|
var BackfillEndDummyEvent = event.Type{Type: "fi.mau.dummy.backfill_end", Class: event.MessageEventType}
|
||||||
var ForwardBackfillDummyEvent = event.Type{Type: "fi.mau.dummy.pre_forward_backfill", Class: event.MessageEventType}
|
var ForwardBackfillDummyEvent = event.Type{Type: "fi.mau.dummy.pre_forward_backfill", Class: event.MessageEventType}
|
||||||
|
|
||||||
func (portal *Portal) CreateMatrixRoom(user *User) error {
|
func (portal *Portal) CreateMatrixRoom(user *User, groupInfo *types.GroupInfo) error {
|
||||||
portal.roomCreateLock.Lock()
|
portal.roomCreateLock.Lock()
|
||||||
defer portal.roomCreateLock.Unlock()
|
defer portal.roomCreateLock.Unlock()
|
||||||
if len(portal.MXID) > 0 {
|
if len(portal.MXID) > 0 {
|
||||||
|
@ -1211,7 +1211,6 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
|
||||||
|
|
||||||
portal.log.Infoln("Creating Matrix room. Info source:", user.MXID)
|
portal.log.Infoln("Creating Matrix room. Info source:", user.MXID)
|
||||||
|
|
||||||
var metadata *types.GroupInfo
|
|
||||||
//var broadcastMetadata *types.BroadcastListInfo
|
//var broadcastMetadata *types.BroadcastListInfo
|
||||||
if portal.IsPrivateChat() {
|
if portal.IsPrivateChat() {
|
||||||
puppet := portal.bridge.GetPuppetByJID(portal.Key.JID)
|
puppet := portal.bridge.GetPuppetByJID(portal.Key.JID)
|
||||||
|
@ -1249,11 +1248,16 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
|
||||||
portal.log.Debugln("Broadcast list is not yet supported, not creating room after all")
|
portal.log.Debugln("Broadcast list is not yet supported, not creating room after all")
|
||||||
return fmt.Errorf("broadcast list bridging is currently not supported")
|
return fmt.Errorf("broadcast list bridging is currently not supported")
|
||||||
} else {
|
} else {
|
||||||
var err error
|
if groupInfo == nil {
|
||||||
metadata, err = user.Client.GetGroupInfo(portal.Key.JID)
|
var err error
|
||||||
if err == nil {
|
groupInfo, err = user.Client.GetGroupInfo(portal.Key.JID)
|
||||||
portal.Name = metadata.Name
|
if err != nil {
|
||||||
portal.Topic = metadata.Topic
|
portal.log.Warnfln("Failed to get group info through %s: %v", user.JID, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if groupInfo != nil {
|
||||||
|
portal.Name = groupInfo.Name
|
||||||
|
portal.Topic = groupInfo.Topic
|
||||||
}
|
}
|
||||||
portal.UpdateAvatar(user, types.EmptyJID, false)
|
portal.UpdateAvatar(user, types.EmptyJID, false)
|
||||||
}
|
}
|
||||||
|
@ -1325,13 +1329,13 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
|
||||||
portal.ensureUserInvited(user)
|
portal.ensureUserInvited(user)
|
||||||
user.syncChatDoublePuppetDetails(portal, true)
|
user.syncChatDoublePuppetDetails(portal, true)
|
||||||
|
|
||||||
if metadata != nil {
|
if groupInfo != nil {
|
||||||
portal.SyncParticipants(user, metadata)
|
portal.SyncParticipants(user, groupInfo)
|
||||||
if metadata.IsAnnounce {
|
if groupInfo.IsAnnounce {
|
||||||
portal.RestrictMessageSending(metadata.IsAnnounce)
|
portal.RestrictMessageSending(groupInfo.IsAnnounce)
|
||||||
}
|
}
|
||||||
if metadata.IsLocked {
|
if groupInfo.IsLocked {
|
||||||
portal.RestrictMetadataChanges(metadata.IsLocked)
|
portal.RestrictMetadataChanges(groupInfo.IsLocked)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if broadcastMetadata != nil {
|
//if broadcastMetadata != nil {
|
||||||
|
|
16
user.go
16
user.go
|
@ -376,7 +376,7 @@ func (user *User) handleHistorySync(evt *waProto.HistorySync) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
user.log.Debugln("Creating portal for", portal.Key.JID, "as part of history sync handling")
|
user.log.Debugln("Creating portal for", portal.Key.JID, "as part of history sync handling")
|
||||||
err = portal.CreateMatrixRoom(user)
|
err = portal.CreateMatrixRoom(user, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
user.log.Warnfln("Failed to create room for %s during backfill: %v", portal.Key.JID, err)
|
user.log.Warnfln("Failed to create room for %s during backfill: %v", portal.Key.JID, err)
|
||||||
continue
|
continue
|
||||||
|
@ -444,6 +444,8 @@ func (user *User) HandleEvent(event interface{}) {
|
||||||
go user.syncPuppet(v.JID)
|
go user.syncPuppet(v.JID)
|
||||||
case *events.GroupInfo:
|
case *events.GroupInfo:
|
||||||
go user.handleGroupUpdate(v)
|
go user.handleGroupUpdate(v)
|
||||||
|
case *events.JoinedGroup:
|
||||||
|
go user.handleGroupCreate(v)
|
||||||
case *events.Picture:
|
case *events.Picture:
|
||||||
go user.handlePictureUpdate(v)
|
go user.handlePictureUpdate(v)
|
||||||
case *events.Receipt:
|
case *events.Receipt:
|
||||||
|
@ -754,6 +756,18 @@ func (user *User) markSelfReadFull(portal *Portal) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (user *User) handleGroupCreate(evt *events.JoinedGroup) {
|
||||||
|
portal := user.GetPortalByJID(evt.JID)
|
||||||
|
if len(portal.MXID) == 0 {
|
||||||
|
err := portal.CreateMatrixRoom(user, &evt.GroupInfo)
|
||||||
|
if err != nil {
|
||||||
|
user.log.Errorln("Failed to create Matrix room after join notification: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
portal.Sync(user, &evt.GroupInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (user *User) handleGroupUpdate(evt *events.GroupInfo) {
|
func (user *User) handleGroupUpdate(evt *events.GroupInfo) {
|
||||||
portal := user.GetPortalByJID(evt.JID)
|
portal := user.GetPortalByJID(evt.JID)
|
||||||
if portal == nil || len(portal.MXID) == 0 {
|
if portal == nil || len(portal.MXID) == 0 {
|
||||||
|
|
Loading…
Reference in a new issue