Successfully adding portals to groupme space

This commit is contained in:
Brandon Watson 2023-09-14 22:35:20 -05:00
parent 5c231cbaba
commit 1cb9710188
3 changed files with 163 additions and 215 deletions

View File

@ -53,7 +53,7 @@ func NewFayeClient(logger log.Logger) *FayeClient {
fc := &FayeClient{wray.NewFayeClient(groupme.PushServer)}
fc.SetLogger(fayeLogger{logger.Sub("FayeClient")})
fc.AddExtension(&AuthExt{})
fc.AddExtension(fc.FayeClient)
//fc.AddExtension(fc.FayeClient)
return fc
}

152
portal.go
View File

@ -149,8 +149,6 @@ func (portal *Portal) SyncDM(user *User, dm *groupme.Chat) {
}
if len(portal.MXID) == 0 {
// "" for overall user not related to one group
puppet := portal.bridge.GetPuppetByGMID(portal.Key.GMID)
meta, err := portal.bridge.StateStore.TryGetMember("", puppet.MXID)
if err {
@ -190,10 +188,6 @@ func (portal *Portal) SyncDM(user *User, dm *groupme.Chat) {
portal.ensureUserInvited(user)
}
//if portal.IsPrivateChat() {
// return
//}
update := false
update = portal.updateMetadata(user) || update
@ -710,9 +704,6 @@ func (portal *Portal) handleAttachment(intent *appservice.IntentAPI, attachment
Info: &event.FileInfo{
Size: len(data),
MimeType: mime,
//Width: width,
//Height: height,
//Duration: int(msg.length),
},
}
if content.File != nil {
@ -749,9 +740,6 @@ func (portal *Portal) handleAttachment(intent *appservice.IntentAPI, attachment
Info: &event.FileInfo{
Size: len(data),
MimeType: fmime,
//Width: width,
//Height: height,
//Duration: int(msg.length),
},
}
if content.File != nil {
@ -924,6 +912,26 @@ func (portal *Portal) createMatrixRoom(user *User) error {
Content: event.Content{Parsed: bridgeInfo},
StateKey: &bridgeInfoStateKey,
}}
spaceIDStr := user.SpaceId
initialState = append(initialState, &event.Event{
Type: event.StateSpaceParent,
StateKey: &spaceIDStr,
Content: event.Content{Parsed: &event.SpaceParentEventContent{
Via: []string{portal.bridge.AS.HomeserverDomain},
Canonical: true,
}},
})
initialState = append(initialState, &event.Event{
Type: event.StateJoinRules,
Content: event.Content{Parsed: &event.JoinRulesEventContent{
JoinRule: event.JoinRuleRestricted,
Allow: []event.JoinRuleAllow{{
RoomID: id.RoomID(user.SpaceId),
Type: event.JoinRuleAllowRoomMembership,
}},
}},
})
if !portal.AvatarURL.IsEmpty() {
initialState = append(initialState, &event.Event{
Type: event.StateRoomAvatar,
@ -977,6 +985,8 @@ func (portal *Portal) createMatrixRoom(user *User) error {
portal.bridge.StateStore.SetMembership(portal.MXID, user, event.MembershipInvite)
}
user.addPortalToSpace(portal)
return nil
}
@ -1069,12 +1079,6 @@ func (portal *Portal) ensureMXIDInvited(mxid id.UserID) {
}
func (portal *Portal) ensureUserInvited(user *User) bool {
portal.userMXIDAction(user, portal.ensureMXIDInvited)
customPuppet := portal.bridge.GetPuppetByCustomMXID(user.MXID)
if customPuppet != nil && customPuppet.CustomIntent() != nil {
_ = customPuppet.CustomIntent().EnsureJoined(portal.MXID)
}
return user.ensureInvited(portal.MainIntent(), portal.MXID, portal.IsPrivateChat())
}
@ -1146,89 +1150,6 @@ func (portal *Portal) sendMessage(intent *appservice.IntentAPI, eventType event.
}
}
// func (portal *Portal) handleReaction(msgID groupme.ID, ppl []groupme.ID) {
// reactions := portal.bridge.DB.Reaction.GetByGMID(msgID)
// newLikes := newReactions(reactions, ppl)
// removeLikes := oldReactions(reactions, ppl)
// var eventID id.EventID
// if len(newLikes) > 0 {
// message := portal.bridge.DB.Message.GetByGMID(portal.Key, msgID)
// if message == nil {
// portal.log.Errorln("Received reaction for unknown message", msgID)
// return
// }
// eventID = message.MXID
// }
// for _, jid := range newLikes {
// intent := portal.getReactionIntent(jid)
// resp, err := portal.sendReaction(intent, eventID, "❤")
// if err != nil {
// portal.log.Errorln("Something wrong with sending reaction", msgID, jid, err)
// continue
// }
// newReaction := portal.bridge.DB.Reaction.New()
// newReaction.MXID = resp.EventID
// newReaction.MessageJID = msgID
// newReaction.MessageMXID = eventID
// newReaction.PuppetJID = jid
// newReaction.Insert()
// }
// for _, reaction := range removeLikes {
// if len(reaction.Puppet.JID) == 0 {
// portal.log.Warnln("Reaction user state wrong", reaction.MXID, msgID)
// continue
// }
// intent := portal.getReactionIntent(reaction.PuppetJID)
// _, err := intent.RedactEvent(portal.MXID, reaction.MXID)
// if err != nil {
// portal.log.Errorln("Something wrong with reaction redaction", reaction.MXID)
// continue
// }
// reaction.Delete()
// }
// }
// func oldReactions(a []*database.Reaction, b []string) (ans []*database.Reaction) {
// for _, i := range a {
// flag := false
// for _, j := range b {
// if i.PuppetJID == j {
// flag = true
// break
// }
// }
// if !flag {
// ans = append(ans, i)
// }
// }
// return
// }
// func newReactions(a []*database.Reaction, b []string) (ans []string) {
// for _, j := range b {
// flag := false
// for _, i := range a {
// if i.GMID == j {
// flag = true
// break
// }
// }
// if !flag {
// ans = append(ans, j)
// }
// }
// return
// }
func (portal *Portal) sendMediaBridgeFailure(source *User, intent *appservice.IntentAPI, message groupme.Message, bridgeErr error) {
portal.log.Errorfln("Failed to bridge media for %s: %v", message.UserID.String(), bridgeErr)
resp, err := portal.sendMessage(intent, event.EventMessage, &event.MessageEventContent{
@ -1290,36 +1211,12 @@ func (portal *Portal) convertMatrixMessage(sender *User, evt *event.Event) ([]*g
return nil, sender
}
//ts := uint64(evt.Timestamp / 1000)
//status := waProto.WebMessageInfo_ERROR
//fromMe := true
// info := &waProto.WebMessageInfo{
// Key: &waProto.MessageKey{
// FromMe: &fromMe,
// Id: makeMessageID(),
// RemoteJid: &portal.Key.JID,
// },
// MessageTimestamp: &ts,
// Message: &waProto.Message{},
// Status: &status,
// }
//
info := groupme.Message{
GroupID: groupme.ID(portal.Key.String()),
ConversationID: groupme.ID(portal.Key.String()),
ChatID: groupme.ID(portal.Key.String()),
RecipientID: groupme.ID(portal.Key.GMID),
}
replyToID := content.GetReplyTo()
if len(replyToID) > 0 {
// content.RemoveReplyFallback()
// msg := portal.bridge.DB.Message.GetByMXID(replyToID)
// if msg != nil && msg.Content != nil {
// ctxInfo.StanzaId = &msg.JID
// ctxInfo.Participant = &msg.Sender
// ctxInfo.QuotedMessage = msg.Content
// }
}
relaybotFormatted := false
if evt.Type == event.EventSticker {
@ -1488,11 +1385,6 @@ func (portal *Portal) syncParticipants(group *groupme.Group) {
}
expectedLevel := 0
// if participant.IsSuperAdmin {
// expectedLevel = 95
// } else if participant.IsAdmin {
// expectedLevel = 50
// }
changed = levels.EnsureUserLevel(puppet.MXID, expectedLevel) || changed
if user != nil {
changed = levels.EnsureUserLevel(user.MXID, expectedLevel) || changed

224
user.go
View File

@ -56,7 +56,7 @@ type User struct {
Client *groupmeext.Client
ConnectionErrors int
CommunityID string
SpaceId string
ChatList map[groupme.ID]*groupme.Chat
GroupList map[groupme.ID]*groupme.Group
@ -90,6 +90,8 @@ type Chat struct {
type ChatList []Chat
var connectWaitGroup = sync.WaitGroup{}
func (cl ChatList) Len() int {
return len(cl)
}
@ -152,53 +154,7 @@ func (user *User) GetIGhost() bridge.Ghost {
}
func (user *User) GetSpaceRoom() id.RoomID {
if !user.bridge.Config.Bridge.PersonalFilteringSpaces {
return ""
}
if len(user.SpaceRoom) == 0 {
user.spaceCreateLock.Lock()
defer user.spaceCreateLock.Unlock()
if len(user.SpaceRoom) > 0 {
return user.SpaceRoom
}
resp, err := user.bridge.Bot.CreateRoom(&mautrix.ReqCreateRoom{
Visibility: "private",
Name: "GroupMe",
Topic: "Your GroupMe bridged chats",
InitialState: []*event.Event{{
Type: event.StateRoomAvatar,
Content: event.Content{
Parsed: &event.RoomAvatarEventContent{
URL: user.bridge.Config.AppService.Bot.ParsedAvatar,
},
},
}},
CreationContent: map[string]interface{}{
"type": event.RoomTypeSpace,
},
PowerLevelOverride: &event.PowerLevelsEventContent{
Users: map[id.UserID]int{
user.bridge.Bot.UserID: 9001,
user.MXID: 50,
},
},
})
if err != nil {
user.log.Errorln("Failed to auto-create space room:", err)
} else {
user.SpaceRoom = resp.RoomID
user.Update()
user.ensureInvited(user.bridge.Bot, user.SpaceRoom, false)
}
} else if !user.spaceMembershipChecked && !user.bridge.StateStore.IsInRoom(user.SpaceRoom, user.MXID) {
user.ensureInvited(user.bridge.Bot, user.SpaceRoom, false)
}
user.spaceMembershipChecked = true
return user.SpaceRoom
return user.getSpaceRoom(&user.SpaceRoom, "GroupMe", "Your GroupMe bridged chats", "")
}
func (user *User) GetManagementRoom() id.RoomID {
@ -288,6 +244,7 @@ func (user *User) PostLogin() {
}
func (user *User) Connect() bool {
user.SpaceId = "GroupMe"
if user.Conn != nil {
return true
} else if len(user.Token) == 0 {
@ -627,27 +584,19 @@ func (user *User) sendMarkdownBridgeAlert(formatString string, args ...interface
}
func (user *User) postConnPing() bool {
//user.log.Debugln("Making post-connection ping")
//err := user.Conn.AdminTest()
//if err != nil {
// user.log.Errorfln("Post-connection ping failed: %v. Disconnecting and then reconnecting after a second", err)
// sess, disconnectErr := user.Conn.Disconnect()
// if disconnectErr != nil {
// user.log.Warnln("Error while disconnecting after failed post-connection ping:", disconnectErr)
// } else {
// user.Session = &sess
// }
// user.bridge.Metrics.TrackDisconnection(user.MXID)
// go func() {
// time.Sleep(1 * time.Second)
// user.tryReconnect(fmt.Sprintf("Post-connection ping failed: %v", err))
// }()
// return false
//} else {
// user.log.Debugln("Post-connection ping OK")
// return true
//}
return true
user.log.Debugln("Making post-connection ping")
if !user.Conn.Connected() {
user.log.Errorfln("Post-connection ping failed: %v. Disconnecting and then reconnecting after a second")
user.bridge.Metrics.TrackDisconnection(user.MXID)
go func() {
time.Sleep(1 * time.Second)
user.Connect()
}()
return false
} else {
user.log.Debugln("Post-connection ping OK")
return true
}
}
func (user *User) intPostLogin() {
@ -670,17 +619,12 @@ func (user *User) intPostLogin() {
select {
case <-user.chatListReceived:
user.log.Debugln("Chat list receive confirmation received in PostLogin")
case <-time.After(time.Duration(1000 /**user.bridge.Config.Bridge.ChatListWait**/) * time.Second):
case <-time.After(time.Duration(10000 /**user.bridge.Config.Bridge.ChatListWait**/) * time.Second):
user.log.Warnln("Timed out waiting for chat list to arrive!")
user.postConnPing()
return
}
if !user.postConnPing() {
user.log.Debugln("Post-connection ping failed, unlocking processing of incoming messages.")
return
}
user.log.Debugln("Waiting for portal sync complete confirmation")
select {
case <-user.syncPortalsDone:
@ -719,17 +663,16 @@ func (user *User) syncPortals(createAll bool) {
}
//for _, chat := range chats {
//var inSpace, ok bool
//if inSpace, ok = existingKeys[chat.Portal.Key]; !ok || !inCommunity {
// inCommunity = user.addPortalToCommunity(chat.Portal)
// if chat.Portal.IsPrivateChat() {
// puppet := user.bridge.GetPuppetByGMID(chat.Portal.Key.GMID)
// user.ad.addPuppetToCommunity(puppet)
// if user.IsInSpace(chat.Portal.Key) {
// user.MarkInSpace(chat.Portal.Key)
// if chat.Portal.IsPrivateChat() {
// user.addPortalToSpace(chat.Portal)
// }
// }
//
// portalKeys = append(portalKeys, chat.Portal.Key)
//}
//portalKeys = append(portalKeys, chat.Portal.Key)
//}
//user.log.Infoln("Read chat list, updating user-portal mapping")
user.log.Infoln("Read chat list, updating user-portal mapping")
err := user.SetPortalKeys(portalKeys)
if err != nil {
@ -773,6 +716,47 @@ func (user *User) syncPortals(createAll bool) {
}
}
func (user *User) addPuppetToSpace(puppet *Puppet) bool {
bot := user.bridge.Bot
url := bot.BuildURL(mautrix.ClientURLPath{"groups", user.SpaceId, "admin", "users", "invite", puppet.MXID})
blankReqBody := map[string]interface{}{}
_, err := bot.MakeRequest(http.MethodPut, url, &blankReqBody, nil)
if err != nil {
user.log.Warnfln("Failed to invite %s to %s: %v", puppet.MXID, user.SpaceId, err)
return false
}
reqBody := map[string]map[string]string{
"m.visibility": {
"type": "private",
},
}
url = bot.BuildURLWithQuery(mautrix.ClientURLPath{"groups", user.SpaceId, "self", "accept_invite"}, map[string]string{
"user_id": puppet.MXID.String(),
})
_, err = bot.MakeRequest(http.MethodPut, url, &reqBody, nil)
if err != nil {
user.log.Warnfln("Failed to join %s as %s: %v", user.SpaceId, puppet.MXID, err)
return false
}
user.log.Debugln("Added", puppet.MXID, "to", user.SpaceId)
return true
}
func (user *User) addPortalToSpace(portal *Portal) bool {
if portal.MXID == "" {
return false
}
_, err := user.bridge.Bot.SendStateEvent(user.GetSpaceRoom(), event.StateSpaceChild, portal.MXID.String(), &event.SpaceChildEventContent{
Via: []string{user.bridge.AS.HomeserverDomain},
})
if err != nil {
user.log.Errorln("Failed to add portal space. RoomId: ", portal.MXID.String())
return false
} else {
return true
}
}
func (user *User) getDirectChats() map[id.UserID][]id.RoomID {
res := make(map[id.UserID][]id.RoomID)
privateChats := user.bridge.DB.Portal.FindPrivateChats(user.GMID)
@ -784,6 +768,78 @@ func (user *User) getDirectChats() map[id.UserID][]id.RoomID {
return res
}
func (user *User) getSpaceRoom(ptr *id.RoomID, name, topic string, parent id.RoomID) id.RoomID {
if len(*ptr) > 0 {
return *ptr
}
user.spaceCreateLock.Lock()
defer user.spaceCreateLock.Unlock()
if len(*ptr) > 0 {
return *ptr
}
initialState := []*event.Event{{
Type: event.StateRoomAvatar,
Content: event.Content{
Parsed: &event.RoomAvatarEventContent{
URL: user.bridge.Config.AppService.Bot.ParsedAvatar,
},
},
}}
if parent != "" {
parentIDStr := parent.String()
initialState = append(initialState, &event.Event{
Type: event.StateSpaceParent,
StateKey: &parentIDStr,
Content: event.Content{
Parsed: &event.SpaceParentEventContent{
Canonical: true,
Via: []string{user.bridge.AS.HomeserverDomain},
},
},
})
}
resp, err := user.bridge.Bot.CreateRoom(&mautrix.ReqCreateRoom{
Visibility: "private",
Name: name,
Topic: topic,
InitialState: initialState,
CreationContent: map[string]interface{}{
"type": event.RoomTypeSpace,
},
PowerLevelOverride: &event.PowerLevelsEventContent{
Users: map[id.UserID]int{
user.bridge.Bot.UserID: 9001,
user.MXID: 50,
},
},
})
if err != nil {
user.log.Errorln("Failed to auto-create space room", err)
} else {
*ptr = resp.RoomID
user.Update()
user.ensureInvited(user.bridge.Bot, resp.RoomID, true)
//if parent != "" {
// _, err = user.bridge.Bot.SendStateEvent(parent, event.StateSpaceChild, resp.RoomID.String(), &event.SpaceChildEventContent{
// Via: []string{user.bridge.AS.HomeserverDomain},
// Order: " 0000",
// })
// if err != nil {
// user.log.Error().Err(err).
// Str("created_space_id", resp.RoomID.String()).
// Str("parent_space_id", parent.String()).
// Msg("Failed to add created space room to parent space")
// }
//}
}
return *ptr
}
func (user *User) updateAvatar(gmdi groupme.ID, avatarID *string, avatarURL *id.ContentURI, avatarSet *bool,
log log.Logger, intent *appservice.IntentAPI) bool {
return false