package bot import ( "context" "gitlab.com/etke.cc/go/mxidwc" "maunium.net/go/mautrix" "maunium.net/go/mautrix/event" ) func (b *Bot) initSync() { b.lp.SetJoinPermit(b.joinPermit) b.lp.OnEventType( event.StateMember, func(_ mautrix.EventSource, evt *event.Event) { go b.onMembership(evt) }, ) b.lp.OnEventType( event.EventMessage, func(_ mautrix.EventSource, evt *event.Event) { go b.onMessage(evt) }) b.lp.OnEventType( event.EventEncrypted, func(_ mautrix.EventSource, evt *event.Event) { go b.onEncryptedMessage(evt) }) } // joinPermit is called by linkpearl when processing "invite" events and deciding if rooms should be auto-joined or not func (b *Bot) joinPermit(evt *event.Event) bool { if !mxidwc.Match(evt.Sender.String(), b.allowedUsers) { b.log.Debug("Rejecting room invitation from unallowed user: %s", evt.Sender) return false } return true } func (b *Bot) onMembership(evt *event.Event) { ctx := newContext(evt) evtType := evt.Content.AsMember().Membership if evtType == event.MembershipJoin && evt.Sender == b.lp.GetClient().UserID { b.onBotJoin(ctx) return } if evtType == event.MembershipBan || evtType == event.MembershipLeave && evt.Sender != b.lp.GetClient().UserID { b.onLeave(ctx) } // Potentially handle other membership events in the future } func (b *Bot) onMessage(evt *event.Event) { // ignore own messages if evt.Sender == b.lp.GetClient().UserID { return } ctx := newContext(evt) b.handle(ctx) } func (b *Bot) onEncryptedMessage(evt *event.Event) { // ignore own messages if evt.Sender == b.lp.GetClient().UserID { return } ctx := newContext(evt) decrypted, err := b.lp.GetMachine().DecryptMegolmEvent(evt) if err != nil { b.Error(ctx, evt.RoomID, "cannot decrypt a message: %v", err) return } ctx = eventToContext(ctx, decrypted) b.handle(ctx) } // onBotJoin handles the "bot joined the room" event func (b *Bot) onBotJoin(ctx context.Context) { evt := eventFromContext(ctx) // Workaround for membership=join events which are delivered to us twice, // as described in this bug report: https://github.com/matrix-org/synapse/issues/9768 _, ok := b.handledMembershipEvents.LoadOrStore(evt.ID, true) if ok { b.log.Info("Suppressing already handled event %s", evt.ID) return } b.sendIntroduction(ctx, evt.RoomID) b.sendHelp(ctx) } func (b *Bot) onLeave(ctx context.Context) { evt := eventFromContext(ctx) _, ok := b.handledMembershipEvents.LoadOrStore(evt.ID, true) if ok { b.log.Info("Suppressing already handled event %s", evt.ID) return } members := b.lp.GetStore().GetRoomMembers(evt.RoomID) count := len(members) if count == 1 && members[0] == b.lp.GetClient().UserID { b.log.Info("no more users left in the %s room", evt.RoomID) b.runStop(ctx) _, err := b.lp.GetClient().LeaveRoom(evt.RoomID) if err != nil { b.Error(ctx, evt.RoomID, "cannot leave empty room: %v", err) } } }