implement skill search by name or id
This commit is contained in:
135
main.go
Normal file
135
main.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"flag"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.sunturtle.xyz/zephyr/horse/horse"
|
||||
"git.sunturtle.xyz/zephyr/horse/horse/global"
|
||||
"github.com/disgoorg/disgo"
|
||||
"github.com/disgoorg/disgo/bot"
|
||||
"github.com/disgoorg/disgo/discord"
|
||||
"github.com/disgoorg/disgo/handler"
|
||||
"github.com/disgoorg/disgo/handler/middleware"
|
||||
"github.com/disgoorg/disgo/rest"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var (
|
||||
appID string
|
||||
pubkey string
|
||||
tokenFile string
|
||||
)
|
||||
flag.StringVar(&appID, "id", "", "Discord application ID")
|
||||
flag.StringVar(&pubkey, "key", "", "Discord public key")
|
||||
flag.StringVar(&tokenFile, "token", "", "`file` containing the Discord bot token")
|
||||
flag.Parse()
|
||||
|
||||
token, err := os.ReadFile(tokenFile)
|
||||
if err != nil {
|
||||
slog.Error("reading token", slog.Any("err", err))
|
||||
os.Exit(1)
|
||||
}
|
||||
token = bytes.TrimSuffix(token, []byte{'\n'})
|
||||
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||
|
||||
r := handler.New()
|
||||
r.DefaultContext(func() context.Context { return ctx })
|
||||
r.Use(middleware.Go)
|
||||
r.Use(middleware.Logger)
|
||||
r.Route("/skill", func(r handler.Router) {
|
||||
r.SlashCommand("/", skillHandler)
|
||||
r.Autocomplete("/", skillAutocomplete)
|
||||
// TODO(zeph): button handler
|
||||
})
|
||||
|
||||
slog.Info("connect", slog.String("disgo", disgo.Version))
|
||||
client, err := disgo.New(string(token), bot.WithDefaultGateway(), bot.WithEventListeners(r))
|
||||
if err != nil {
|
||||
slog.Error("building bot", slog.Any("err", err))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := handler.SyncCommands(client, commands, nil, rest.WithCtx(ctx)); err != nil {
|
||||
slog.Error("syncing commands", slog.Any("err", err))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := client.OpenGateway(ctx); err != nil {
|
||||
slog.Error("opening gateway", slog.Any("err", err))
|
||||
stop()
|
||||
}
|
||||
slog.Info("running")
|
||||
<-ctx.Done()
|
||||
stop()
|
||||
|
||||
ctx, stop = context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer stop()
|
||||
client.Close(ctx)
|
||||
}
|
||||
|
||||
var commands = []discord.ApplicationCommandCreate{
|
||||
discord.SlashCommandCreate{
|
||||
Name: "skill",
|
||||
Description: "Umamusume skill data",
|
||||
Options: []discord.ApplicationCommandOption{
|
||||
discord.ApplicationCommandOptionString{
|
||||
Name: "query",
|
||||
Description: "Skill name or ID",
|
||||
Required: true,
|
||||
Autocomplete: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func skillHandler(data discord.SlashCommandInteractionData, e *handler.CommandEvent) error {
|
||||
q := data.String("query")
|
||||
id, err := strconv.ParseInt(q, 10, 32)
|
||||
var s horse.Skill
|
||||
if err == nil {
|
||||
// note inverted condition; this is when we have an id
|
||||
s = global.AllSkills[horse.SkillID(id)]
|
||||
}
|
||||
if s.ID == 0 {
|
||||
// Either we weren't given a number or the number doesn't match any skill ID.
|
||||
id, ok := global.SkillNameToID[q]
|
||||
if !ok {
|
||||
// No such skill.
|
||||
m := discord.MessageCreate{
|
||||
Content: "No such skill.",
|
||||
Flags: discord.MessageFlagEphemeral,
|
||||
}
|
||||
return e.CreateMessage(m)
|
||||
}
|
||||
s = global.AllSkills[id]
|
||||
}
|
||||
// TODO(zeph): search conditions and effects, give a list
|
||||
m := discord.MessageCreate{
|
||||
Components: []discord.LayoutComponent{RenderSkill(s)},
|
||||
Flags: discord.MessageFlagIsComponentsV2,
|
||||
}
|
||||
return e.CreateMessage(m)
|
||||
}
|
||||
|
||||
func skillAutocomplete(e *handler.AutocompleteEvent) error {
|
||||
q := strings.ToLower(e.Data.String("query"))
|
||||
r := make([]discord.AutocompleteChoice, 0, 25)
|
||||
for k, _ := range global.SkillNameToID {
|
||||
if strings.HasPrefix(strings.ToLower(k), q) {
|
||||
r = append(r, discord.AutocompleteChoiceString{Name: k, Value: k})
|
||||
if len(r) == cap(r) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return e.AutocompleteResult(r)
|
||||
}
|
||||
Reference in New Issue
Block a user