dcbot/internal/discord/command_group.go
Dawid Wysokiński aec3a3736d
All checks were successful
continuous-integration/drone/push Build is passing
feat: add new commands - group set channel-losses/channel-gains (#13)
Reviewed-on: #13
2022-10-11 05:05:35 +00:00

431 lines
12 KiB
Go

package discord
import (
"context"
"fmt"
"time"
"gitea.dwysokinski.me/twhelp/dcbot/internal/domain"
"github.com/bwmarrin/discordgo"
)
type groupCommand struct {
svc GroupService
client TWHelpClient
}
func (c *groupCommand) name() string {
return "group"
}
func (c *groupCommand) register(s *discordgo.Session) error {
if err := c.create(s); err != nil {
return err
}
s.AddHandler(c.handle)
return nil
}
func (c *groupCommand) create(s *discordgo.Session) error {
versionChoices, err := c.getVersionChoices()
if err != nil {
return err
}
var perm int64 = discordgo.PermissionAdministrator
_, err = s.ApplicationCommandCreate(s.State.User.ID, "", &discordgo.ApplicationCommand{
Name: c.name(),
Description: "Manages monitor groups on this server",
DefaultMemberPermissions: &perm,
Options: []*discordgo.ApplicationCommandOption{
{
Name: "create",
Description: "Creates a new monitor group",
Type: discordgo.ApplicationCommandOptionSubCommand,
Options: []*discordgo.ApplicationCommandOption{
{
Name: "version",
Description: "e.g. www.tribalwars.net, www.plemiona.pl",
Type: discordgo.ApplicationCommandOptionString,
Choices: versionChoices,
Required: true,
},
{
Name: "server",
Description: "Tribal Wars server (e.g. en115, pl170)",
Type: discordgo.ApplicationCommandOptionString,
Required: true,
},
{
Name: "channel-gains",
Description: "Specifies on which channel notifications of gained villages will appear",
Type: discordgo.ApplicationCommandOptionChannel,
ChannelTypes: []discordgo.ChannelType{
discordgo.ChannelTypeGuildText,
},
Required: false,
},
{
Name: "channel-losses",
Description: "Specifies on which channel notifications of lost villages will appear",
Type: discordgo.ApplicationCommandOptionChannel,
ChannelTypes: []discordgo.ChannelType{
discordgo.ChannelTypeGuildText,
},
Required: false,
},
},
},
{
Name: "list",
Description: "Lists all created groups",
Type: discordgo.ApplicationCommandOptionSubCommand,
},
{
Name: "set",
Description: "Sets various properties in a group configuration",
Type: discordgo.ApplicationCommandOptionSubCommandGroup,
Options: []*discordgo.ApplicationCommandOption{
{
Name: "server",
Description: "Sets a Tribal Wars server for a group",
Type: discordgo.ApplicationCommandOptionSubCommand,
Options: []*discordgo.ApplicationCommandOption{
{
Name: "group",
Description: "Group ID",
Type: discordgo.ApplicationCommandOptionString,
Required: true,
},
{
Name: "version",
Description: "e.g. www.tribalwars.net, www.plemiona.pl",
Type: discordgo.ApplicationCommandOptionString,
Choices: versionChoices,
Required: true,
},
{
Name: "server",
Description: "Tribal Wars server (e.g. en115, pl170)",
Type: discordgo.ApplicationCommandOptionString,
Required: true,
},
},
},
{
Name: "channel-gains",
Description: "Specifies on which channel notifications of gained villages will appear",
Type: discordgo.ApplicationCommandOptionSubCommand,
Options: []*discordgo.ApplicationCommandOption{
{
Name: "group",
Description: "Group ID",
Type: discordgo.ApplicationCommandOptionString,
Required: true,
},
{
Name: "channel",
Description: "Channel",
Type: discordgo.ApplicationCommandOptionChannel,
ChannelTypes: []discordgo.ChannelType{
discordgo.ChannelTypeGuildText,
},
Required: true,
},
},
},
{
Name: "channel-losses",
Description: "Specifies on which channel notifications of lost villages will appear",
Type: discordgo.ApplicationCommandOptionSubCommand,
Options: []*discordgo.ApplicationCommandOption{
{
Name: "group",
Description: "Group ID",
Type: discordgo.ApplicationCommandOptionString,
Required: true,
},
{
Name: "channel",
Description: "Channel ID",
Type: discordgo.ApplicationCommandOptionChannel,
ChannelTypes: []discordgo.ChannelType{
discordgo.ChannelTypeGuildText,
},
Required: true,
},
},
},
},
},
},
})
if err != nil {
return fmt.Errorf("s.ApplicationCommandCreate: %w", err)
}
return nil
}
func (c *groupCommand) getVersionChoices() ([]*discordgo.ApplicationCommandOptionChoice, error) {
versions, err := c.client.ListVersions(context.Background())
if err != nil {
return nil, fmt.Errorf("TWHelpClient.ListVersions: %w", err)
}
versionChoices := make([]*discordgo.ApplicationCommandOptionChoice, 0, len(versions))
for _, v := range versions {
versionChoices = append(versionChoices, &discordgo.ApplicationCommandOptionChoice{
Name: v.Host,
Value: v.Code,
})
}
return versionChoices, nil
}
func (c *groupCommand) 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 "set":
c.handleSet(s, i)
return
default:
}
}
func (c *groupCommand) handleCreate(s *discordgo.Session, i *discordgo.InteractionCreate) {
ctx := context.Background()
version := ""
server := ""
channelGains := ""
channelLosses := ""
for _, opt := range i.ApplicationCommandData().Options[0].Options {
if opt == nil {
continue
}
switch opt.Name {
case "version":
version = opt.StringValue()
case "server":
server = opt.StringValue()
case "channel-gains":
channelGains = opt.ChannelValue(s).ID
case "channel-losses":
channelLosses = opt.ChannelValue(s).ID
}
}
params, err := domain.NewCreateGroupParams(
i.GuildID,
version,
server,
channelGains,
channelLosses,
)
if err != nil {
_ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: messageFromError(err),
},
})
return
}
group, err := c.svc.Create(ctx, params)
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: "group has been successfully created (ID=" + group.ID + ")",
},
})
}
func (c *groupCommand) handleList(s *discordgo.Session, i *discordgo.InteractionCreate) {
ctx := context.Background()
groups, err := c.svc.List(ctx, domain.ListGroupsParams{
ServerIDs: []string{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: "Group list",
Description: buildGroupListDescription(groups),
Timestamp: time.Now().Format(time.RFC3339),
},
},
},
})
}
func (c *groupCommand) handleSet(s *discordgo.Session, i *discordgo.InteractionCreate) {
switch i.ApplicationCommandData().Options[0].Options[0].Name {
case "server":
c.handleSetServer(s, i)
return
case "channel-gains":
c.handleSetChannelGains(s, i)
return
case "channel-losses":
c.handleSetChannelLosses(s, i)
return
default:
}
}
func (c *groupCommand) handleSetServer(s *discordgo.Session, i *discordgo.InteractionCreate) {
ctx := context.Background()
group := ""
version := ""
server := ""
for _, opt := range i.ApplicationCommandData().Options[0].Options[0].Options {
if opt == nil {
continue
}
switch opt.Name {
case "group":
group = opt.StringValue()
case "version":
version = opt.StringValue()
case "server":
server = opt.StringValue()
}
}
_, err := c.svc.SetTWServer(ctx, group, version, server)
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: "group has been successfully updated",
},
})
}
func (c *groupCommand) handleSetChannelGains(s *discordgo.Session, i *discordgo.InteractionCreate) {
ctx := context.Background()
group := ""
channel := ""
for _, opt := range i.ApplicationCommandData().Options[0].Options[0].Options {
if opt == nil {
continue
}
switch opt.Name {
case "group":
group = opt.StringValue()
case "channel":
channel = opt.ChannelValue(s).ID
}
}
_, err := c.svc.SetChannelGains(ctx, group, channel)
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: "group has been successfully updated",
},
})
}
func (c *groupCommand) handleSetChannelLosses(s *discordgo.Session, i *discordgo.InteractionCreate) {
ctx := context.Background()
group := ""
channel := ""
for _, opt := range i.ApplicationCommandData().Options[0].Options[0].Options {
if opt == nil {
continue
}
switch opt.Name {
case "group":
group = opt.StringValue()
case "channel":
channel = opt.ChannelValue(s).ID
}
}
_, err := c.svc.SetChannelLosses(ctx, group, channel)
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: "group has been successfully updated",
},
})
}
func buildGroupListDescription(groups []domain.Group) string {
description := "**ID** - **Version** - **Server**"
for i, g := range groups {
description += fmt.Sprintf("\n%d. %s - %s - %s", i+1, g.ID, g.VersionCode, g.ServerKey)
}
return description
}