horsebot: refactor skill server
This commit is contained in:
@@ -11,7 +11,6 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/disgoorg/disgo"
|
||||
@@ -58,13 +57,16 @@ func main() {
|
||||
}
|
||||
slog.SetDefault(slog.New(lh))
|
||||
|
||||
byID, byName, err := loadSkills(filepath.Join(dataDir, "skill.json"))
|
||||
skills, err := loadSkills(filepath.Join(dataDir, "skill.json"))
|
||||
slog.Info("loaded skills", slog.Int("count", len(skills)))
|
||||
groups, err2 := loadSkillGroups(filepath.Join(dataDir, "skill-group.json"))
|
||||
slog.Info("loaded skill groups", slog.Int("count", len(groups)))
|
||||
if err = errors.Join(err, err2); err != nil {
|
||||
slog.Error("loading data", slog.Any("err", err))
|
||||
os.Exit(1)
|
||||
}
|
||||
skillsByID, skillsByName, skillGroupMap = byID, byName, groups
|
||||
skillSrv := newSkillServer(skills, groups)
|
||||
slog.Info("skill server ready")
|
||||
|
||||
token, err := os.ReadFile(tokenFile)
|
||||
if err != nil {
|
||||
@@ -80,9 +82,9 @@ func main() {
|
||||
r.Use(middleware.Go)
|
||||
r.Use(logMiddleware)
|
||||
r.Route("/skill", func(r handler.Router) {
|
||||
r.SlashCommand("/", skillHandler)
|
||||
r.Autocomplete("/", skillAutocomplete)
|
||||
r.ButtonComponent("/{id}", skillButton)
|
||||
r.SlashCommand("/", skillSrv.slash)
|
||||
r.Autocomplete("/", skillSrv.autocomplete)
|
||||
r.ButtonComponent("/{id}", skillSrv.button)
|
||||
})
|
||||
|
||||
opts := []bot.ConfigOpt{bot.WithDefaultGateway(), bot.WithEventListeners(r)}
|
||||
@@ -145,33 +147,19 @@ var commands = []discord.ApplicationCommandCreate{
|
||||
},
|
||||
}
|
||||
|
||||
// TODO(zeph): these globals could go away, but there's a bit of ceremony to doing that
|
||||
var (
|
||||
skillsByID map[horse.SkillID]horse.Skill
|
||||
skillsByName map[string]horse.SkillID
|
||||
skillGroupMap map[horse.SkillGroupID]horse.SkillGroup
|
||||
)
|
||||
|
||||
func loadSkills(file string) (map[horse.SkillID]horse.Skill, map[string]horse.SkillID, error) {
|
||||
func loadSkills(file string) ([]horse.Skill, error) {
|
||||
b, err := os.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
var skills []horse.Skill
|
||||
if err := json.Unmarshal(b, &skills); err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
byID := make(map[horse.SkillID]horse.Skill, len(skills))
|
||||
byName := make(map[string]horse.SkillID, len(skills))
|
||||
for _, s := range skills {
|
||||
byID[s.ID] = s
|
||||
byName[s.Name] = s.ID
|
||||
}
|
||||
slog.Info("loaded skills", slog.Int("count", len(skills)))
|
||||
return byID, byName, nil
|
||||
return skills, nil
|
||||
}
|
||||
|
||||
func loadSkillGroups(file string) (map[horse.SkillGroupID]horse.SkillGroup, error) {
|
||||
func loadSkillGroups(file string) ([]horse.SkillGroup, error) {
|
||||
b, err := os.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -180,59 +168,5 @@ func loadSkillGroups(file string) (map[horse.SkillGroupID]horse.SkillGroup, erro
|
||||
if err := json.Unmarshal(b, &groups); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[horse.SkillGroupID]horse.SkillGroup, len(groups))
|
||||
for _, s := range groups {
|
||||
m[s.ID] = s
|
||||
}
|
||||
slog.Info("loaded skill groups", slog.Int("count", len(groups)))
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func skillHandler(data discord.SlashCommandInteractionData, e *handler.CommandEvent) error {
|
||||
q := data.String("query")
|
||||
id, err := strconv.ParseInt(q, 10, 32)
|
||||
if err == nil {
|
||||
// note inverted condition; this is when we have an id
|
||||
id = int64(skillsByID[horse.SkillID(id)].ID)
|
||||
}
|
||||
if id == 0 {
|
||||
// Either we weren't given a number or the number doesn't match any skill ID.
|
||||
v := skillsByName[q]
|
||||
if v == 0 {
|
||||
// No such skill.
|
||||
m := discord.MessageCreate{
|
||||
Content: "No such skill.",
|
||||
Flags: discord.MessageFlagEphemeral,
|
||||
}
|
||||
return e.CreateMessage(m)
|
||||
}
|
||||
id = int64(v)
|
||||
}
|
||||
// TODO(zeph): search conditions and effects, give a list
|
||||
m := discord.MessageCreate{
|
||||
Components: []discord.LayoutComponent{RenderSkill(horse.SkillID(id), skillsByID, skillGroupMap)},
|
||||
Flags: discord.MessageFlagIsComponentsV2,
|
||||
}
|
||||
return e.CreateMessage(m)
|
||||
}
|
||||
|
||||
func skillAutocomplete(e *handler.AutocompleteEvent) error {
|
||||
q := e.Data.String("query")
|
||||
opts := skillGlobalAuto().Find(nil, q)
|
||||
return e.AutocompleteResult(opts[:min(len(opts), 25)])
|
||||
}
|
||||
|
||||
func skillButton(data discord.ButtonInteractionData, e *handler.ComponentEvent) error {
|
||||
id, err := strconv.ParseInt(e.Vars["id"], 10, 32)
|
||||
if err != nil {
|
||||
m := discord.MessageCreate{
|
||||
Content: "That button produced an invalid skill ID. That's not supposed to happen.",
|
||||
Flags: discord.MessageFlagEphemeral,
|
||||
}
|
||||
return e.CreateMessage(m)
|
||||
}
|
||||
m := discord.MessageUpdate{
|
||||
Components: &[]discord.LayoutComponent{RenderSkill(horse.SkillID(id), skillsByID, skillGroupMap)},
|
||||
}
|
||||
return e.UpdateMessage(m)
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user