package discord import ( "context" "fmt" "time" "gitea.dwysokinski.me/twhelp/dcbot/internal/domain" "github.com/bwmarrin/discordgo" ) const ( tribeTagMaxLength = 10 ) type monitorCommand struct { svc MonitorService } func (c *monitorCommand) name() string { return "monitor" } func (c *monitorCommand) register(s *discordgo.Session) error { if err := c.create(s); err != nil { return err } s.AddHandler(c.handle) return nil } func (c *monitorCommand) create(s *discordgo.Session) error { var perm int64 = discordgo.PermissionAdministrator _, err := s.ApplicationCommandCreate(s.State.User.ID, "", &discordgo.ApplicationCommand{ Name: c.name(), Description: "Manages monitors", DefaultMemberPermissions: &perm, Options: []*discordgo.ApplicationCommandOption{ { Name: "create", Description: "Creates a new monitor", Type: discordgo.ApplicationCommandOptionSubCommand, Options: []*discordgo.ApplicationCommandOption{ { Name: "group", Description: "Group ID", Type: discordgo.ApplicationCommandOptionString, Required: true, }, { Name: "tag", Description: "Tribe tag", Type: discordgo.ApplicationCommandOptionString, Required: true, MaxLength: tribeTagMaxLength, }, }, }, { Name: "list", Description: "Lists all monitors associated with a particular group", Type: discordgo.ApplicationCommandOptionSubCommand, Options: []*discordgo.ApplicationCommandOption{ { Name: "group", Description: "Group ID", Type: discordgo.ApplicationCommandOptionString, Required: true, }, }, }, { Name: "delete", Description: "Deletes a monitor", Type: discordgo.ApplicationCommandOptionSubCommand, Options: []*discordgo.ApplicationCommandOption{ { Name: "monitor", Description: "Monitor ID", Type: discordgo.ApplicationCommandOptionString, Required: true, }, }, }, }, }) if err != nil { return fmt.Errorf("s.ApplicationCommandCreate: %w", err) } return nil } func (c *monitorCommand) handle(s *discordgo.Session, i *discordgo.InteractionCreate) { cmdData := i.ApplicationCommandData() if cmdData.Name != c.name() { return } switch cmdData.Options[0].Name { case "create": c.handleCreate(s, i) return case "list": c.handleList(s, i) return case "delete": c.handleDelete(s, i) return default: } } func (c *monitorCommand) handleCreate(s *discordgo.Session, i *discordgo.InteractionCreate) { ctx := context.Background() group := "" tag := "" for _, opt := range i.ApplicationCommandData().Options[0].Options { if opt == nil { continue } switch opt.Name { case "group": group = opt.StringValue() case "tag": tag = opt.StringValue() } } monitor, err := c.svc.Create(ctx, group, i.GuildID, tag) if err != nil { _ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: messageFromError(err), }, }) return } _ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: "monitor has been successfully created (ID=" + monitor.ID + ")", }, }) } func (c *monitorCommand) handleList(s *discordgo.Session, i *discordgo.InteractionCreate) { ctx := context.Background() group := i.ApplicationCommandData().Options[0].Options[0].StringValue() monitors, err := c.svc.List(ctx, group, i.GuildID) if err != nil { _ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: messageFromError(err), }, }) return } _ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Embeds: []*discordgo.MessageEmbed{ { Type: discordgo.EmbedTypeRich, Title: "Monitor list", Description: buildMonitorListDescription(monitors), Timestamp: formatTimestamp(time.Now()), }, }, }, }) } func (c *monitorCommand) handleDelete(s *discordgo.Session, i *discordgo.InteractionCreate) { ctx := context.Background() monitor := i.ApplicationCommandData().Options[0].Options[0].StringValue() if err := c.svc.Delete(ctx, monitor, i.GuildID); err != nil { _ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: messageFromError(err), }, }) return } _ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: "monitor has been successfully deleted", }, }) } func buildMonitorListDescription(monitors []domain.MonitorWithTribe) string { description := "**ID** - **Tribe**" for i, m := range monitors { description += fmt.Sprintf("\n%d. %s - %s", i+1, m.ID, buildLink(m.Tribe.Tag, m.Tribe.ProfileURL)) } return description }