diff --git a/bot/access.go b/bot/access.go index f54f66d..18208c3 100644 --- a/bot/access.go +++ b/bot/access.go @@ -1,41 +1,40 @@ package bot import ( - "fmt" + "context" "maunium.net/go/mautrix/id" "gitlab.com/etke.cc/postmoogle/utils" ) -type accessCheckerFunc func(id.UserID, id.RoomID) (bool, error) - -func (b *Bot) allowAnyone(actorID id.UserID, targetRoomID id.RoomID) (bool, error) { - return true, nil +func (b *Bot) allowAnyone(actorID id.UserID, targetRoomID id.RoomID) bool { + return true } -func (b *Bot) allowOwner(actorID id.UserID, targetRoomID id.RoomID) (bool, error) { +func (b *Bot) allowOwner(actorID id.UserID, targetRoomID id.RoomID) bool { if !utils.Match(actorID.String(), b.allowedUsers) { - return false, nil + return false } if b.noowner { - return true, nil + return true } cfg, err := b.getSettings(targetRoomID) if err != nil { - return false, fmt.Errorf("failed to retrieve settings: %v", err) + b.Error(context.Background(), targetRoomID, "failed to retrieve settings: %v", err) + return false } owner := cfg.Owner() if owner == "" { - return true, nil + return true } - return owner == actorID.String(), nil + return owner == actorID.String() } -func (b *Bot) allowAdmin(actorID id.UserID, targetRoomID id.RoomID) (bool, error) { - return utils.Match(actorID.String(), b.allowedAdmins), nil +func (b *Bot) allowAdmin(actorID id.UserID, targetRoomID id.RoomID) bool { + return utils.Match(actorID.String(), b.allowedAdmins) } diff --git a/bot/admin_command.go b/bot/admin_command.go deleted file mode 100644 index eff4bf4..0000000 --- a/bot/admin_command.go +++ /dev/null @@ -1,39 +0,0 @@ -package bot - -import ( - "context" - "fmt" - "strings" - - "maunium.net/go/mautrix/id" -) - -func (b *Bot) sendMailboxes(ctx context.Context) { - evt := eventFromContext(ctx) - - mailboxes := map[string]id.RoomID{} - - b.rooms.Range(func(mailbox any, roomID any) bool { - mailboxes[mailbox.(string)] = roomID.(id.RoomID) - return true - }) - - if len(mailboxes) == 0 { - b.Notice(ctx, evt.RoomID, "No mailboxes are managed by the bot so far, kupo!") - return - } - - var msg strings.Builder - msg.WriteString("The following mailboxes are managed by the bot:\n") - for mailbox, roomID := range mailboxes { - email := fmt.Sprintf("%s@%s", mailbox, b.domain) - msg.WriteString("* `") - msg.WriteString(email) - msg.WriteString("` - `") - msg.WriteString(roomID.String()) - msg.WriteString("`") - msg.WriteString("\n") - } - - b.Notice(ctx, evt.RoomID, msg.String()) -} diff --git a/bot/bot.go b/bot/bot.go index bcb7cb1..7c6128d 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -60,19 +60,21 @@ func New( // Error message to the log and matrix room func (b *Bot) Error(ctx context.Context, roomID id.RoomID, message string, args ...interface{}) { b.log.Error(message, args...) + err := fmt.Errorf(message, args...) - sentry.GetHubFromContext(ctx).CaptureException(fmt.Errorf(message, args...)) + sentry.GetHubFromContext(ctx).CaptureException(err) if roomID != "" { - // nolint // if something goes wrong here nobody can help... - b.lp.Send(roomID, &event.MessageEventContent{ - MsgType: event.MsgNotice, - Body: "ERROR: " + fmt.Sprintf(message, args...), - }) + b.SendError(ctx, roomID, message) } } -// Notice sends a notice message to the matrix room -func (b *Bot) Notice(ctx context.Context, roomID id.RoomID, message string) { +// SendError sends an error message to the matrix room +func (b *Bot) SendError(ctx context.Context, roomID id.RoomID, message string) { + b.SendNotice(ctx, roomID, "ERROR: "+message) +} + +// SendNotice sends a notice message to the matrix room +func (b *Bot) SendNotice(ctx context.Context, roomID id.RoomID, message string) { content := format.RenderMarkdown(message, true, true) content.MsgType = event.MsgNotice _, err := b.lp.Send(roomID, &content) diff --git a/bot/command.go b/bot/command.go index 4fc12aa..efcd7c2 100644 --- a/bot/command.go +++ b/bot/command.go @@ -19,10 +19,10 @@ const ( type ( command struct { - key string - description string - sanitizer func(string) string - accessChecker accessCheckerFunc + key string + description string + sanitizer func(string) string + allowed func(id.UserID, id.RoomID) bool } commandList []command ) @@ -40,28 +40,28 @@ func (b *Bot) buildCommandList() commandList { return commandList{ // special commands { - key: commandHelp, - description: "Show this help message", - accessChecker: b.allowAnyone, + key: commandHelp, + description: "Show this help message", + allowed: b.allowAnyone, }, { - key: commandStop, - description: "Disable bridge for the room and clear all configuration", - accessChecker: b.allowOwner, + key: commandStop, + description: "Disable bridge for the room and clear all configuration", + allowed: b.allowOwner, }, {}, // delimiter // options commands { - key: optionMailbox, - description: "Get or set mailbox of the room", - sanitizer: utils.Mailbox, - accessChecker: b.allowOwner, + key: optionMailbox, + description: "Get or set mailbox of the room", + sanitizer: utils.Mailbox, + allowed: b.allowOwner, }, { - key: optionOwner, - description: "Get or set owner of the room", - sanitizer: func(s string) string { return s }, - accessChecker: b.allowOwner, + key: optionOwner, + description: "Get or set owner of the room", + sanitizer: func(s string) string { return s }, + allowed: b.allowOwner, }, {}, // delimiter { @@ -70,8 +70,8 @@ func (b *Bot) buildCommandList() commandList { "Get or set `%s` of the room (`true` - hide email sender; `false` - show email sender)", optionNoSender, ), - sanitizer: utils.SanitizeBoolString, - accessChecker: b.allowOwner, + sanitizer: utils.SanitizeBoolString, + allowed: b.allowOwner, }, { key: optionNoSubject, @@ -79,8 +79,8 @@ func (b *Bot) buildCommandList() commandList { "Get or set `%s` of the room (`true` - hide email subject; `false` - show email subject)", optionNoSubject, ), - sanitizer: utils.SanitizeBoolString, - accessChecker: b.allowOwner, + sanitizer: utils.SanitizeBoolString, + allowed: b.allowOwner, }, { key: optionNoHTML, @@ -88,8 +88,8 @@ func (b *Bot) buildCommandList() commandList { "Get or set `%s` of the room (`true` - ignore HTML in email; `false` - parse HTML in emails)", optionNoHTML, ), - sanitizer: utils.SanitizeBoolString, - accessChecker: b.allowOwner, + sanitizer: utils.SanitizeBoolString, + allowed: b.allowOwner, }, { key: optionNoThreads, @@ -97,8 +97,8 @@ func (b *Bot) buildCommandList() commandList { "Get or set `%s` of the room (`true` - ignore email threads; `false` - convert email threads into matrix threads)", optionNoThreads, ), - sanitizer: utils.SanitizeBoolString, - accessChecker: b.allowOwner, + sanitizer: utils.SanitizeBoolString, + allowed: b.allowOwner, }, { key: optionNoFiles, @@ -106,14 +106,14 @@ func (b *Bot) buildCommandList() commandList { "Get or set `%s` of the room (`true` - ignore email attachments; `false` - upload email attachments)", optionNoFiles, ), - sanitizer: utils.SanitizeBoolString, - accessChecker: b.allowOwner, + sanitizer: utils.SanitizeBoolString, + allowed: b.allowOwner, }, {}, // delimiter { - key: commandMailboxes, - description: "Show the list of all mailboxes", - accessChecker: b.allowAdmin, + key: commandMailboxes, + description: "Show the list of all mailboxes", + allowed: b.allowAdmin, }, } } @@ -129,13 +129,8 @@ func (b *Bot) handleCommand(ctx context.Context, evt *event.Event, commandSlice return } - allowed, err := cmd.accessChecker(evt.Sender, evt.RoomID) - if err != nil { - b.Error(ctx, evt.RoomID, err.Error()) - return - } - if !allowed { - b.Notice(ctx, evt.RoomID, "not allowed to do that, kupo") + if !cmd.allowed(evt.Sender, evt.RoomID) { + b.SendNotice(ctx, evt.RoomID, "not allowed to do that, kupo") return } @@ -181,7 +176,7 @@ func (b *Bot) sendIntroduction(ctx context.Context, roomID id.RoomID) { msg.WriteString(b.domain) msg.WriteString("` and have them appear in this room.") - b.Notice(ctx, roomID, msg.String()) + b.SendNotice(ctx, roomID, msg.String()) } func (b *Bot) sendHelp(ctx context.Context, roomID id.RoomID) { @@ -226,7 +221,52 @@ func (b *Bot) sendHelp(ctx context.Context, roomID id.RoomID) { msg.WriteString("\n") } - b.Notice(ctx, roomID, msg.String()) + b.SendNotice(ctx, roomID, msg.String()) +} + +func (b *Bot) sendMailboxes(ctx context.Context) { + evt := eventFromContext(ctx) + mailboxes := map[string]id.RoomID{} + b.rooms.Range(func(key any, value any) bool { + if key == nil { + return true + } + if value == nil { + return true + } + + mailbox, ok := key.(string) + if !ok { + return true + } + roomID, ok := value.(id.RoomID) + if !ok { + return true + } + + mailboxes[mailbox] = roomID + return true + }) + + if len(mailboxes) == 0 { + b.SendNotice(ctx, evt.RoomID, "No mailboxes are managed by the bot so far, kupo!") + return + } + + var msg strings.Builder + msg.WriteString("The following mailboxes are managed by the bot:\n") + for mailbox, roomID := range mailboxes { + msg.WriteString("* `") + msg.WriteString(mailbox) + msg.WriteString("@") + msg.WriteString(b.domain) + msg.WriteString("` - `") + msg.WriteString(roomID.String()) + msg.WriteString("`") + msg.WriteString("\n") + } + + b.SendNotice(ctx, evt.RoomID, msg.String()) } func (b *Bot) runStop(ctx context.Context) { @@ -239,7 +279,7 @@ func (b *Bot) runStop(ctx context.Context) { mailbox := cfg.Get(optionMailbox) if mailbox == "" { - b.Notice(ctx, evt.RoomID, "that room is not configured yet") + b.SendNotice(ctx, evt.RoomID, "that room is not configured yet") return } @@ -251,7 +291,7 @@ func (b *Bot) runStop(ctx context.Context) { return } - b.Notice(ctx, evt.RoomID, "mailbox has been disabled") + b.SendNotice(ctx, evt.RoomID, "mailbox has been disabled") } func (b *Bot) handleOption(ctx context.Context, cmd []string) { @@ -272,7 +312,7 @@ func (b *Bot) getOption(ctx context.Context, name string) { value := cfg.Get(name) if value == "" { - b.Notice(ctx, evt.RoomID, fmt.Sprintf("`%s` is not set, kupo.", name)) + b.SendNotice(ctx, evt.RoomID, fmt.Sprintf("`%s` is not set, kupo.", name)) return } @@ -280,7 +320,7 @@ func (b *Bot) getOption(ctx context.Context, name string) { value = value + "@" + b.domain } - b.Notice(ctx, evt.RoomID, fmt.Sprintf("`%s` of this room is `%s`", name, value)) + b.SendNotice(ctx, evt.RoomID, fmt.Sprintf("`%s` of this room is `%s`", name, value)) } func (b *Bot) setOption(ctx context.Context, name, value string) { @@ -293,7 +333,7 @@ func (b *Bot) setOption(ctx context.Context, name, value string) { if name == optionMailbox { existingID, ok := b.GetMapping(value) if ok && existingID != "" && existingID != evt.RoomID { - b.Notice(ctx, evt.RoomID, fmt.Sprintf("Mailbox `%s@%s` already taken, kupo", value, b.domain)) + b.SendNotice(ctx, evt.RoomID, fmt.Sprintf("Mailbox `%s@%s` already taken, kupo", value, b.domain)) return } } @@ -326,5 +366,5 @@ func (b *Bot) setOption(ctx context.Context, name, value string) { value = value + "@" + b.domain } - b.Notice(ctx, evt.RoomID, fmt.Sprintf("`%s` of this room set to `%s`", name, value)) + b.SendNotice(ctx, evt.RoomID, fmt.Sprintf("`%s` of this room set to `%s`", name, value)) } diff --git a/config/config.go b/config/config.go index fd21239..c9e297f 100644 --- a/config/config.go +++ b/config/config.go @@ -37,8 +37,8 @@ func New() (*Config, error) { Federation: env.Bool("federation"), MaxSize: env.Int("maxsize", defaultConfig.MaxSize), StatusMsg: env.String("statusmsg", defaultConfig.StatusMsg), - Users: *userPatterns, - Admins: *adminPatterns, + Users: userPatterns, + Admins: adminPatterns, Sentry: Sentry{ DSN: env.String("sentry.dsn", defaultConfig.Sentry.DSN), }, @@ -52,7 +52,7 @@ func New() (*Config, error) { return cfg, nil } -func getUserRegexPatterns(key string) (*[]*regexp.Regexp, error) { +func getUserRegexPatterns(key string) ([]*regexp.Regexp, error) { mxidPatterns := env.Slice(key) regexPatterns, err := utils.WildcardMXIDsToRegexes(mxidPatterns) if err != nil { diff --git a/utils/user.go b/utils/user.go index 0e8c59e..130d91a 100644 --- a/utils/user.go +++ b/utils/user.go @@ -7,7 +7,7 @@ import ( ) // WildcardMXIDsToRegexes converts a list of wildcard patterns to a list of regular expressions -func WildcardMXIDsToRegexes(wildCardPatterns []string) (*[]*regexp.Regexp, error) { +func WildcardMXIDsToRegexes(wildCardPatterns []string) ([]*regexp.Regexp, error) { regexPatterns := make([]*regexp.Regexp, len(wildCardPatterns)) for idx, wildCardPattern := range wildCardPatterns { @@ -18,7 +18,7 @@ func WildcardMXIDsToRegexes(wildCardPatterns []string) (*[]*regexp.Regexp, error regexPatterns[idx] = regex } - return ®exPatterns, nil + return regexPatterns, nil } // Match tells if the given user id is allowed to use the bot, according to the given whitelist diff --git a/utils/user_test.go b/utils/user_test.go index 5068204..f59cbdb 100644 --- a/utils/user_test.go +++ b/utils/user_test.go @@ -202,7 +202,7 @@ func TestMatch(t *testing.T) { t.Error(err) } - actualResult := Match(testData.checkedValue, *allowedUserRegexes) + actualResult := Match(testData.checkedValue, allowedUserRegexes) if actualResult == testData.expectedResult { return