From 8e1aa5b11c3cf0dbce9392af45528e338bd8193f Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Thu, 25 Aug 2022 11:58:18 +0300 Subject: [PATCH 1/5] [WIP] Send introduction text and help after the bot joins a room This appears to work, except that the join event is triggered twice, and we send the (introduction + help) twice. --- bot/command.go | 20 ++++++++++++++++++++ bot/sync.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/bot/command.go b/bot/command.go index 99f9fac..d647958 100644 --- a/bot/command.go +++ b/bot/command.go @@ -109,6 +109,26 @@ func (b *Bot) parseCommand(message string) []string { return strings.Split(message, " ") } +func (b *Bot) sendIntroduction(ctx context.Context, roomID id.RoomID) { + span := sentry.StartSpan(ctx, "http.server", sentry.TransactionName("sendIntroduction")) + defer span.Finish() + + var msg strings.Builder + msg.WriteString("Hello!\n\n") + msg.WriteString("This is Postmoogle - a bot that bridges Email to Matrix.\n\n") + msg.WriteString(fmt.Sprintf( + "To get started, assign an email address to this room by sending a `%s %s SOME_INBOX` command.\n", + b.prefix, + optionMailbox, + )) + msg.WriteString(fmt.Sprintf( + "You will then be able to send emails to `SOME_INBOX@%s` and have them appear in this room.", + b.domain, + )) + + b.Notice(ctx, roomID, msg.String()) +} + func (b *Bot) sendHelp(ctx context.Context, roomID id.RoomID) { span := sentry.StartSpan(ctx, "http.server", sentry.TransactionName("sendHelp")) defer span.Finish() diff --git a/bot/sync.go b/bot/sync.go index 81f6b64..4cc7af6 100644 --- a/bot/sync.go +++ b/bot/sync.go @@ -9,6 +9,16 @@ import ( ) func (b *Bot) initSync() { + b.lp.OnEventType( + event.StateMember, + func(_ mautrix.EventSource, evt *event.Event) { + // Trying to debug the membership=join event being handled twice here. + eventJSON, _ := evt.MarshalJSON() + b.log.Debug(string(eventJSON)) + + go b.onMembership(evt) + }, + ) b.lp.OnEventType( event.EventMessage, func(_ mautrix.EventSource, evt *event.Event) { @@ -21,6 +31,31 @@ func (b *Bot) initSync() { }) } +func (b *Bot) onMembership(evt *event.Event) { + hub := sentry.CurrentHub().Clone() + hub.ConfigureScope(func(scope *sentry.Scope) { + scope.SetUser(sentry.User{ID: evt.Sender.String()}) + scope.SetContext("event", map[string]string{ + "id": evt.ID.String(), + "room": evt.RoomID.String(), + "sender": evt.Sender.String(), + }) + }) + + if evt.Sender == b.lp.GetClient().UserID { + // Handle membership events related to our own (bot) user first + + switch evt.Content.AsMember().Membership { + case event.MembershipJoin: + b.onBotJoin(evt, hub) + } + + return + } + + // Handle membership events related to other users +} + func (b *Bot) onMessage(evt *event.Event) { // ignore own messages if evt.Sender == b.lp.GetClient().UserID { @@ -70,3 +105,13 @@ func (b *Bot) onEncryptedMessage(evt *event.Event) { b.handle(span.Context(), decrypted) } + +// onBotJoin handles the "bot joined the room" event +func (b *Bot) onBotJoin(evt *event.Event, hub *sentry.Hub) { + ctx := sentry.SetHubOnContext(context.Background(), hub) + span := sentry.StartSpan(ctx, "http.server", sentry.TransactionName("onBotJoin")) + defer span.Finish() + + b.sendIntroduction(ctx, evt.RoomID) + b.sendHelp(ctx, evt.RoomID) +} From 236a128129f594657478e3868430871dc75f60fa Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Thu, 25 Aug 2022 20:10:43 +0300 Subject: [PATCH 2/5] Fix double membership=join event handling This fixes the problem mentioned in 8e1aa5b11c3cf0db. Turns out that it's a long-standing Synapse bug: https://github.com/matrix-org/synapse/issues/9768 --- bot/bot.go | 17 +++++++++-------- bot/sync.go | 12 ++++++++---- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/bot/bot.go b/bot/bot.go index 946d1f3..c9b37f5 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -19,14 +19,15 @@ import ( // Bot represents matrix bot type Bot struct { - noowner bool - federation bool - prefix string - domain string - rooms map[string]id.RoomID - roomsmu *sync.Mutex - log *logger.Logger - lp *linkpearl.Linkpearl + noowner bool + federation bool + prefix string + domain string + rooms map[string]id.RoomID + roomsmu *sync.Mutex + log *logger.Logger + lp *linkpearl.Linkpearl + handledEvents sync.Map } // New creates a new matrix bot diff --git a/bot/sync.go b/bot/sync.go index 4cc7af6..35efec0 100644 --- a/bot/sync.go +++ b/bot/sync.go @@ -12,10 +12,6 @@ func (b *Bot) initSync() { b.lp.OnEventType( event.StateMember, func(_ mautrix.EventSource, evt *event.Event) { - // Trying to debug the membership=join event being handled twice here. - eventJSON, _ := evt.MarshalJSON() - b.log.Debug(string(eventJSON)) - go b.onMembership(evt) }, ) @@ -108,6 +104,14 @@ func (b *Bot) onEncryptedMessage(evt *event.Event) { // onBotJoin handles the "bot joined the room" event func (b *Bot) onBotJoin(evt *event.Event, hub *sentry.Hub) { + // 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 + _, exists := b.handledEvents.LoadOrStore(evt.ID, true) + if exists { + b.log.Info("Suppressing already handled event %s", evt.ID) + return + } + ctx := sentry.SetHubOnContext(context.Background(), hub) span := sentry.StartSpan(ctx, "http.server", sentry.TransactionName("onBotJoin")) defer span.Finish() From 06856adb8662a33a4be879958f39e3e02ac5a3c2 Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Thu, 25 Aug 2022 21:38:42 +0300 Subject: [PATCH 3/5] Simplify code --- bot/bot.go | 18 +++++++++--------- bot/sync.go | 22 ++++------------------ 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/bot/bot.go b/bot/bot.go index c9b37f5..5085220 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -19,15 +19,15 @@ import ( // Bot represents matrix bot type Bot struct { - noowner bool - federation bool - prefix string - domain string - rooms map[string]id.RoomID - roomsmu *sync.Mutex - log *logger.Logger - lp *linkpearl.Linkpearl - handledEvents sync.Map + noowner bool + federation bool + prefix string + domain string + rooms map[string]id.RoomID + roomsmu *sync.Mutex + log *logger.Logger + lp *linkpearl.Linkpearl + handledJoinEvents sync.Map } // New creates a new matrix bot diff --git a/bot/sync.go b/bot/sync.go index 35efec0..16c1466 100644 --- a/bot/sync.go +++ b/bot/sync.go @@ -29,27 +29,13 @@ func (b *Bot) initSync() { func (b *Bot) onMembership(evt *event.Event) { hub := sentry.CurrentHub().Clone() - hub.ConfigureScope(func(scope *sentry.Scope) { - scope.SetUser(sentry.User{ID: evt.Sender.String()}) - scope.SetContext("event", map[string]string{ - "id": evt.ID.String(), - "room": evt.RoomID.String(), - "sender": evt.Sender.String(), - }) - }) - - if evt.Sender == b.lp.GetClient().UserID { - // Handle membership events related to our own (bot) user first - - switch evt.Content.AsMember().Membership { - case event.MembershipJoin: - b.onBotJoin(evt, hub) - } + if evt.Content.AsMember().Membership == event.MembershipJoin && evt.Sender == b.lp.GetClient().UserID { + b.onBotJoin(evt, hub) return } - // Handle membership events related to other users + // Potentially handle other membership events in the future } func (b *Bot) onMessage(evt *event.Event) { @@ -106,7 +92,7 @@ func (b *Bot) onEncryptedMessage(evt *event.Event) { func (b *Bot) onBotJoin(evt *event.Event, hub *sentry.Hub) { // 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 - _, exists := b.handledEvents.LoadOrStore(evt.ID, true) + _, exists := b.handledJoinEvents.LoadOrStore(evt.ID, true) if exists { b.log.Info("Suppressing already handled event %s", evt.ID) return From a093de51c4e7ef959a37b217a95b171f1e909295 Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Thu, 25 Aug 2022 21:41:20 +0300 Subject: [PATCH 4/5] Remove some useless sentry spans --- bot/sync.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/bot/sync.go b/bot/sync.go index 16c1466..79cf381 100644 --- a/bot/sync.go +++ b/bot/sync.go @@ -99,8 +99,6 @@ func (b *Bot) onBotJoin(evt *event.Event, hub *sentry.Hub) { } ctx := sentry.SetHubOnContext(context.Background(), hub) - span := sentry.StartSpan(ctx, "http.server", sentry.TransactionName("onBotJoin")) - defer span.Finish() b.sendIntroduction(ctx, evt.RoomID) b.sendHelp(ctx, evt.RoomID) From 8507af670ad4d32f91fe26ce19aae6399a26b0b5 Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Thu, 25 Aug 2022 21:44:06 +0300 Subject: [PATCH 5/5] exists -> ok --- bot/settings.go | 4 ++-- bot/sync.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bot/settings.go b/bot/settings.go index 01b0955..24cd418 100644 --- a/bot/settings.go +++ b/bot/settings.go @@ -39,8 +39,8 @@ func (s settings) Allowed(noowner bool, userID id.UserID) bool { func (s settings) Get(key string) string { value := s[strings.ToLower(strings.TrimSpace(key))] - sanitizer, exists := sanitizers[key] - if exists { + sanitizer, ok := sanitizers[key] + if ok { return sanitizer(value) } return value diff --git a/bot/sync.go b/bot/sync.go index 79cf381..0781a39 100644 --- a/bot/sync.go +++ b/bot/sync.go @@ -92,8 +92,8 @@ func (b *Bot) onEncryptedMessage(evt *event.Event) { func (b *Bot) onBotJoin(evt *event.Event, hub *sentry.Hub) { // 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 - _, exists := b.handledJoinEvents.LoadOrStore(evt.ID, true) - if exists { + _, ok := b.handledJoinEvents.LoadOrStore(evt.ID, true) + if ok { b.log.Info("Suppressing already handled event %s", evt.ID) return }