diff --git a/bot/command.go b/bot/command.go index f25c809..bf900e7 100644 --- a/bot/command.go +++ b/bot/command.go @@ -11,103 +11,91 @@ import ( "gitlab.com/etke.cc/postmoogle/utils" ) -type sanitizerFunc func(string) string - -type commandDefinition struct { - key string - description string - isOption bool -} - -type commandList []commandDefinition - -func (c commandList) get(key string) (*commandDefinition, bool) { - for _, command := range c { - if command.key == key { - return &command, true - } - } - return nil, false -} - -var ( - commands = commandList{ - // special commands - { - key: "help", - description: "Show this help message", - }, - { - key: "stop", - description: "Disable bridge for the room and clear all configuration", - }, - - // options commands - { - key: optionMailbox, - description: "Get or set mailbox of the room", - isOption: true, - }, - { - key: optionOwner, - description: "Get or set owner of the room", - isOption: true, - }, - { - key: optionNoSender, - description: fmt.Sprintf( - "Get or set `%s` of the room (`true` - hide email sender; `false` - show email sender)", - optionNoSender, - ), - isOption: true, - }, - { - key: optionNoSubject, - description: fmt.Sprintf( - "Get or set `%s` of the room (`true` - hide email subject; `false` - show email subject)", - optionNoSubject, - ), - isOption: true, - }, - { - key: optionNoHTML, - description: fmt.Sprintf( - "Get or set `%s` of the room (`true` - ignore HTML in email; `false` - parse HTML in emails)", - optionNoHTML, - ), - isOption: true, - }, - { - key: optionNoThreads, - description: fmt.Sprintf( - "Get or set `%s` of the room (`true` - ignore email threads; `false` - convert email threads into matrix threads)", - optionNoThreads, - ), - isOption: true, - }, - { - key: optionNoFiles, - description: fmt.Sprintf( - "Get or set `%s` of the room (`true` - ignore email attachments; `false` - upload email attachments)", - optionNoFiles, - ), - isOption: true, - }, - } - - // sanitizers is map of option name => sanitizer function - sanitizers = map[string]sanitizerFunc{ - optionMailbox: utils.Mailbox, - optionNoSender: utils.SanitizeBoolString, - optionNoSubject: utils.SanitizeBoolString, - optionNoHTML: utils.SanitizeBoolString, - optionNoThreads: utils.SanitizeBoolString, - optionNoFiles: utils.SanitizeBoolString, +type ( + command struct { + key string + description string + sanitizer func(string) string } + commandList []command ) -func (b *Bot) handleCommand(ctx context.Context, evt *event.Event, command []string) { - if _, ok := commands.get(command[0]); !ok { +func (c commandList) get(key string) *command { + for _, cmd := range c { + if cmd.key == key { + return &cmd + } + } + return nil +} + +var commands = commandList{ + // special commands + { + key: "help", + description: "Show this help message", + }, + { + key: "stop", + description: "Disable bridge for the room and clear all configuration", + }, + {}, // delimiter + // options commands + { + key: optionMailbox, + description: "Get or set mailbox of the room", + sanitizer: utils.Mailbox, + }, + { + key: optionOwner, + description: "Get or set owner of the room", + sanitizer: func(s string) string { return s }, + }, + {}, // delimiter + { + key: optionNoSender, + description: fmt.Sprintf( + "Get or set `%s` of the room (`true` - hide email sender; `false` - show email sender)", + optionNoSender, + ), + sanitizer: utils.SanitizeBoolString, + }, + { + key: optionNoSubject, + description: fmt.Sprintf( + "Get or set `%s` of the room (`true` - hide email subject; `false` - show email subject)", + optionNoSubject, + ), + sanitizer: utils.SanitizeBoolString, + }, + { + key: optionNoHTML, + description: fmt.Sprintf( + "Get or set `%s` of the room (`true` - ignore HTML in email; `false` - parse HTML in emails)", + optionNoHTML, + ), + sanitizer: utils.SanitizeBoolString, + }, + { + key: optionNoThreads, + description: fmt.Sprintf( + "Get or set `%s` of the room (`true` - ignore email threads; `false` - convert email threads into matrix threads)", + optionNoThreads, + ), + sanitizer: utils.SanitizeBoolString, + }, + { + key: optionNoFiles, + description: fmt.Sprintf( + "Get or set `%s` of the room (`true` - ignore email attachments; `false` - upload email attachments)", + optionNoFiles, + ), + sanitizer: utils.SanitizeBoolString, + }, +} + +func (b *Bot) handleCommand(ctx context.Context, evt *event.Event, commandSlice []string) { + if cmd := commands.get(commandSlice[0]); cmd == nil { return } @@ -116,13 +104,13 @@ func (b *Bot) handleCommand(ctx context.Context, evt *event.Event, command []str return } - switch command[0] { + switch commandSlice[0] { case "help": b.sendHelp(ctx, evt.RoomID) case "stop": b.runStop(ctx, true) default: - b.handleOption(ctx, command) + b.handleOption(ctx, commandSlice) } } @@ -162,33 +150,42 @@ func (b *Bot) sendIntroduction(ctx context.Context, roomID id.RoomID) { func (b *Bot) sendHelp(ctx context.Context, roomID id.RoomID) { evt := eventFromContext(ctx) - settings, settingsErr := b.getSettings(evt.RoomID) - if settingsErr != nil { - b.Error(ctx, evt.RoomID, settingsErr.Error()) + cfg, serr := b.getSettings(evt.RoomID) + if serr != nil { + b.log.Error("cannot retrieve settings: %v", serr) } var msg strings.Builder msg.WriteString("The following commands are supported:\n\n") - for _, command := range commands { + for _, cmd := range commands { + if cmd.key == "" { + msg.WriteString("\n---\n") + continue + } msg.WriteString("* **`") msg.WriteString(b.prefix) msg.WriteString(" ") - msg.WriteString(command.key) + msg.WriteString(cmd.key) msg.WriteString("`**") - - if command.isOption && settingsErr == nil { - value := settings.Get(command.key) - - if value == "" { - msg.WriteString(" (currently not set)") - } else { - msg.WriteString(fmt.Sprintf(" (currently `%v`)", b.formatOptionValue(command.key, value))) + value := cfg.Get(cmd.key) + if cmd.sanitizer != nil { + switch value != "" { + case false: + msg.WriteString("(currently not set)") + case true: + msg.WriteString("(currently `") + msg.WriteString(value) + if cmd.key == optionMailbox { + msg.WriteString("@") + msg.WriteString(b.domain) + } + msg.WriteString("`)") } } msg.WriteString(" - ") - msg.WriteString(command.description) + msg.WriteString(cmd.description) msg.WriteString("\n") } @@ -225,12 +222,12 @@ func (b *Bot) runStop(ctx context.Context, checkAllowed bool) { b.Notice(ctx, evt.RoomID, "mailbox has been disabled") } -func (b *Bot) handleOption(ctx context.Context, command []string) { - if len(command) == 1 { - b.getOption(ctx, command[0]) +func (b *Bot) handleOption(ctx context.Context, cmd []string) { + if len(cmd) == 1 { + b.getOption(ctx, cmd[0]) return } - b.setOption(ctx, command[0], command[1]) + b.setOption(ctx, cmd[0], cmd[1]) } func (b *Bot) getOption(ctx context.Context, name string) { @@ -247,24 +244,24 @@ func (b *Bot) getOption(ctx context.Context, name string) { return } - b.Notice(ctx, evt.RoomID, fmt.Sprintf( - "`%s` of this room is `%s`", - name, - b.formatOptionValue(name, value), - )) + if name == optionMailbox { + value = value + "@" + b.domain + } + + b.Notice(ctx, evt.RoomID, fmt.Sprintf("`%s` of this room is `%s`", name, value)) } func (b *Bot) setOption(ctx context.Context, name, value string) { - sanitizer, ok := sanitizers[name] - if ok { - value = sanitizer(value) + cmd := commands.get(name) + if cmd != nil { + value = cmd.sanitizer(value) } evt := eventFromContext(ctx) if name == optionMailbox { existingID, ok := b.GetMapping(value) if ok && existingID != "" && existingID != evt.RoomID { - b.Notice(ctx, evt.RoomID, fmt.Sprintf("Mailbox `%s` already taken, kupo", b.formatOptionValue(name, value))) + b.Notice(ctx, evt.RoomID, fmt.Sprintf("Mailbox `%s@%s` already taken, kupo", value, b.domain)) return } } @@ -283,7 +280,7 @@ func (b *Bot) setOption(ctx context.Context, name, value string) { cfg.Set(name, value) if name == optionMailbox { cfg.Set(optionOwner, evt.Sender.String()) - b.rooms.Store(b.formatOptionValue(name, value), evt.RoomID) + b.rooms.Store(value, evt.RoomID) } err = b.setSettings(evt.RoomID, cfg) @@ -292,9 +289,9 @@ func (b *Bot) setOption(ctx context.Context, name, value string) { return } - b.Notice(ctx, evt.RoomID, fmt.Sprintf( - "`%s` of this room set to `%s`", - name, - b.formatOptionValue(name, value), - )) + if name == optionMailbox { + value = value + "@" + b.domain + } + + b.Notice(ctx, evt.RoomID, fmt.Sprintf("`%s` of this room set to `%s`", name, value)) } diff --git a/bot/message.go b/bot/message.go index 9cdf2f1..48d8063 100644 --- a/bot/message.go +++ b/bot/message.go @@ -13,10 +13,10 @@ func (b *Bot) handle(ctx context.Context) { return } message := strings.TrimSpace(content.Body) - command := b.parseCommand(message) - if command == nil { + cmd := b.parseCommand(message) + if cmd == nil { return } - b.handleCommand(ctx, evt, command) + b.handleCommand(ctx, evt, cmd) } diff --git a/bot/settings.go b/bot/settings.go index 66032a0..d1f7f2e 100644 --- a/bot/settings.go +++ b/bot/settings.go @@ -1,7 +1,6 @@ package bot import ( - "fmt" "strconv" "strings" @@ -36,13 +35,7 @@ func (s settings) Allowed(noowner bool, userID id.UserID) bool { // Get option func (s settings) Get(key string) string { - value := s[strings.ToLower(strings.TrimSpace(key))] - - sanitizer, ok := sanitizers[key] - if ok { - return sanitizer(value) - } - return value + return s[strings.ToLower(strings.TrimSpace(key))] } func (s settings) Mailbox() string { @@ -119,15 +112,3 @@ func (b *Bot) getSettings(roomID id.RoomID) (settings, error) { func (b *Bot) setSettings(roomID id.RoomID, cfg settings) error { return b.lp.GetClient().SetRoomAccountData(roomID, settingskey, cfg) } - -func (b *Bot) formatOptionValue(name string, value string) string { - if value == "" { - return value - } - - if name == optionMailbox { - value = fmt.Sprintf("%s@%s", value, b.domain) - } - - return value -}