Compare commits
10 Commits
2517d0cb37
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 0fc68e9bd8 | |||
| 50b98be6d3 | |||
| 30d4eeea40 | |||
| f0c5e19870 | |||
| c0abf72041 | |||
| 780002b35f | |||
| 1dae50a918 | |||
| f4f563c530 | |||
| ff20bbef2c | |||
| c5c733d14c |
@@ -1,122 +1,56 @@
|
|||||||
package autocomplete
|
package autocomplete
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"cmp"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"sync"
|
||||||
"unicode"
|
|
||||||
"unicode/utf8"
|
"github.com/junegunn/fzf/src/algo"
|
||||||
|
"github.com/junegunn/fzf/src/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Set is an autocomplete set.
|
// Set is an autocomplete set.
|
||||||
type Set struct {
|
type Set[V any] struct {
|
||||||
mask []uint64
|
keys []util.Chars
|
||||||
keys [][]string
|
vals []V
|
||||||
vals [][]string
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
test [2]uint64
|
|
||||||
idxs [256]byte
|
|
||||||
)
|
|
||||||
|
|
||||||
const careset = " 0123456789abcdefghijklmnopqrstuvwxyz.!'"
|
|
||||||
|
|
||||||
// Certify the size of careset at compile time.
|
|
||||||
// It must be no larger than 64.
|
|
||||||
var _ [0]struct{} = [len(careset) - 40]struct{}{}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Construct the test and idxs maps.
|
|
||||||
for i, c := range []byte(careset) {
|
|
||||||
if c < 64 {
|
|
||||||
test[0] |= 1 << c
|
|
||||||
} else {
|
|
||||||
test[1] |= 1 << (c - 64)
|
|
||||||
}
|
|
||||||
idxs[c] = byte(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func normalize(s string) string {
|
|
||||||
s = strings.Map(func(c rune) rune {
|
|
||||||
c = unicode.ToLower(c)
|
|
||||||
// TODO(zeph): map latin letters with diacritics to their not-diacritic
|
|
||||||
// characters; e.g. 2* pasta's unique Corazón ☆ Ardiente should have
|
|
||||||
// ó mapped to o. for now, we just special-case it.
|
|
||||||
if c == 'ó' {
|
|
||||||
c = 'o'
|
|
||||||
}
|
|
||||||
return c
|
|
||||||
}, s)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func filter(s string) (r uint64) {
|
|
||||||
for _, c := range s {
|
|
||||||
if c > 0x7f {
|
|
||||||
// Skip non-ASCII characters.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if test[byte(c)/64]>>(byte(c)%64)&1 == 0 {
|
|
||||||
// Not in the care set.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
r |= 1 << idxs[byte(c)]
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add associates a value with a key in the autocomplete set.
|
// Add associates a value with a key in the autocomplete set.
|
||||||
// The behavior is undefined if the key already has a value.
|
// The behavior is undefined if the key already has a value.
|
||||||
func (s *Set) Add(key, val string) {
|
func (s *Set[V]) Add(key string, val V) {
|
||||||
key = normalize(key)
|
k := util.ToChars([]byte(key))
|
||||||
m := filter(key)
|
i, _ := slices.BinarySearchFunc(s.keys, k, func(a, b util.Chars) int {
|
||||||
i, ok := slices.BinarySearch(s.mask, m)
|
return bytes.Compare(a.Bytes(), b.Bytes())
|
||||||
if !ok {
|
})
|
||||||
s.mask = slices.Insert(s.mask, i, m)
|
s.keys = slices.Insert(s.keys, i, k)
|
||||||
s.keys = slices.Insert(s.keys, i, nil)
|
s.vals = slices.Insert(s.vals, i, val)
|
||||||
s.vals = slices.Insert(s.vals, i, nil)
|
|
||||||
}
|
|
||||||
j, _ := slices.BinarySearch(s.keys[i], key)
|
|
||||||
s.keys[i] = slices.Insert(s.keys[i], j, key)
|
|
||||||
s.vals[i] = slices.Insert(s.vals[i], j, val)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find appends to r all values in the set with keys that key matches.
|
// Find appends to r all values in the set with keys that key matches.
|
||||||
func (s *Set) Find(r []string, key string) []string {
|
func (s *Set[V]) Find(r []V, key string) []V {
|
||||||
key = normalize(key)
|
initFzf()
|
||||||
m := filter(key)
|
var (
|
||||||
for i, v := range s.mask {
|
p = []rune(key)
|
||||||
if m&v != m {
|
|
||||||
|
got []V
|
||||||
|
t []algo.Result
|
||||||
|
slab util.Slab
|
||||||
|
)
|
||||||
|
for i := range s.keys {
|
||||||
|
res, _ := algo.FuzzyMatchV2(false, true, true, &s.keys[i], p, false, &slab)
|
||||||
|
if res.Score <= 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for j, k := range s.keys[i] {
|
j, _ := slices.BinarySearchFunc(t, res, func(a, b algo.Result) int { return -cmp.Compare(a.Score, b.Score) })
|
||||||
if inorder(key, k) {
|
// Insert after all other matches with the same score for stability.
|
||||||
r = append(r, s.vals[i][j])
|
for j < len(t) && t[j].Score == res.Score {
|
||||||
}
|
j++
|
||||||
}
|
}
|
||||||
|
t = slices.Insert(t, j, res)
|
||||||
|
got = slices.Insert(got, j, s.vals[i])
|
||||||
}
|
}
|
||||||
return r
|
return append(r, got...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// inorder checks whether each character in a appears in the same relative order in b.
|
var initFzf = sync.OnceFunc(func() { algo.Init("default") })
|
||||||
func inorder(a, b string) bool {
|
|
||||||
for _, c := range a {
|
|
||||||
k := strings.IndexRune(b, c)
|
|
||||||
if k < 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
_, l := utf8.DecodeRuneInString(b[k:])
|
|
||||||
b = b[k+l:]
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Metrics gets the number of buckets in the autocomplete set and the length
|
|
||||||
// of the longest bucket.
|
|
||||||
func (s *Set) Metrics() (buckets, longest int) {
|
|
||||||
for _, b := range s.keys {
|
|
||||||
longest = max(longest, len(b))
|
|
||||||
}
|
|
||||||
return len(s.keys), longest
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ func TestAutocomplete(t *testing.T) {
|
|||||||
search: "o",
|
search: "o",
|
||||||
want: these("bocchi", "ryo"),
|
want: these("bocchi", "ryo"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "unrelated",
|
||||||
|
add: these("bocchi", "ryo", "nijika", "kita"),
|
||||||
|
search: "x",
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "map",
|
name: "map",
|
||||||
add: these("Corazón ☆ Ardiente"),
|
add: these("Corazón ☆ Ardiente"),
|
||||||
@@ -49,7 +55,7 @@ func TestAutocomplete(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(c.name, func(t *testing.T) {
|
||||||
var set autocomplete.Set
|
var set autocomplete.Set[string]
|
||||||
for _, s := range c.add {
|
for _, s := range c.add {
|
||||||
set.Add(s, s)
|
set.Add(s, s)
|
||||||
}
|
}
|
||||||
|
|||||||
7
go.mod
7
go.mod
@@ -1,10 +1,11 @@
|
|||||||
module git.sunturtle.xyz/zephyr/horsebot
|
module git.sunturtle.xyz/zephyr/horsebot
|
||||||
|
|
||||||
go 1.25.6
|
go 1.25.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.sunturtle.xyz/zephyr/horse v0.0.0-20260123040553-4bfb06b6826f
|
git.sunturtle.xyz/zephyr/horse v0.0.0-20260210125822-b55e1bc200a1
|
||||||
github.com/disgoorg/disgo v0.19.0-rc.15
|
github.com/disgoorg/disgo v0.19.0-rc.15
|
||||||
|
github.com/junegunn/fzf v0.67.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -13,6 +14,8 @@ require (
|
|||||||
github.com/disgoorg/snowflake/v2 v2.0.3 // indirect
|
github.com/disgoorg/snowflake/v2 v2.0.3 // indirect
|
||||||
github.com/gorilla/websocket v1.5.3 // indirect
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
github.com/klauspost/compress v1.18.2 // indirect
|
github.com/klauspost/compress v1.18.2 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad // indirect
|
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad // indirect
|
||||||
golang.org/x/crypto v0.46.0 // indirect
|
golang.org/x/crypto v0.46.0 // indirect
|
||||||
golang.org/x/sys v0.39.0 // indirect
|
golang.org/x/sys v0.39.0 // indirect
|
||||||
|
|||||||
11
go.sum
11
go.sum
@@ -1,5 +1,5 @@
|
|||||||
git.sunturtle.xyz/zephyr/horse v0.0.0-20260123040553-4bfb06b6826f h1:S287bkj7whgs5NY0u3ih4Ggy+2LTrnfHY3K/smfv9dU=
|
git.sunturtle.xyz/zephyr/horse v0.0.0-20260210125822-b55e1bc200a1 h1:nIk5Mis384wx/ndMa/3zSr1omkWK8rg4I/Z46BCAIe8=
|
||||||
git.sunturtle.xyz/zephyr/horse v0.0.0-20260123040553-4bfb06b6826f/go.mod h1:qGXO/93EfCOI1oGSLqrRkPDF/EAdsgLNZJjRKx+i4Lk=
|
git.sunturtle.xyz/zephyr/horse v0.0.0-20260210125822-b55e1bc200a1/go.mod h1:qGXO/93EfCOI1oGSLqrRkPDF/EAdsgLNZJjRKx+i4Lk=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/disgoorg/disgo v0.19.0-rc.15 h1:x0NsV2gcbdjwuztsg2wYXw76p1Cpc8f6ByDrkPcfQtU=
|
github.com/disgoorg/disgo v0.19.0-rc.15 h1:x0NsV2gcbdjwuztsg2wYXw76p1Cpc8f6ByDrkPcfQtU=
|
||||||
@@ -12,16 +12,23 @@ github.com/disgoorg/snowflake/v2 v2.0.3 h1:3B+PpFjr7j4ad7oeJu4RlQ+nYOTadsKapJIzg
|
|||||||
github.com/disgoorg/snowflake/v2 v2.0.3/go.mod h1:W6r7NUA7DwfZLwr00km6G4UnZ0zcoLBRufhkFWgAc4c=
|
github.com/disgoorg/snowflake/v2 v2.0.3/go.mod h1:W6r7NUA7DwfZLwr00km6G4UnZ0zcoLBRufhkFWgAc4c=
|
||||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/junegunn/fzf v0.67.0 h1:naiOdIkV5/ZCfHgKQIV/f5YDWowl95G6yyOQqW8FeSo=
|
||||||
|
github.com/junegunn/fzf v0.67.0/go.mod h1:xlXX2/rmsccKQUnr9QOXPDi5DyV9cM0UjKy/huScBeE=
|
||||||
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
|
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
|
||||||
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad h1:qIQkSlF5vAUHxEmTbaqt1hkJ/t6skqEGYiMag343ucI=
|
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad h1:qIQkSlF5vAUHxEmTbaqt1hkJ/t6skqEGYiMag343ucI=
|
||||||
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s=
|
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||||
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|||||||
13
main.go
13
main.go
@@ -109,13 +109,6 @@ func main() {
|
|||||||
stop()
|
stop()
|
||||||
}
|
}
|
||||||
slog.Info("ready")
|
slog.Info("ready")
|
||||||
go func() {
|
|
||||||
// Preload autocomplete in a separate goroutine.
|
|
||||||
slog.Info("begin computing skill autocomplete")
|
|
||||||
set := skillGlobalAuto()
|
|
||||||
buckets, longest := set.Metrics()
|
|
||||||
slog.Info("done computing skill autocomplete", slog.Int("buckets", buckets), slog.Int("longest", longest))
|
|
||||||
}()
|
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
stop()
|
stop()
|
||||||
|
|
||||||
@@ -170,11 +163,7 @@ func skillHandler(data discord.SlashCommandInteractionData, e *handler.CommandEv
|
|||||||
func skillAutocomplete(e *handler.AutocompleteEvent) error {
|
func skillAutocomplete(e *handler.AutocompleteEvent) error {
|
||||||
q := e.Data.String("query")
|
q := e.Data.String("query")
|
||||||
opts := skillGlobalAuto().Find(nil, q)
|
opts := skillGlobalAuto().Find(nil, q)
|
||||||
r := make([]discord.AutocompleteChoice, min(len(opts), 25))
|
return e.AutocompleteResult(opts[:min(len(opts), 25)])
|
||||||
for i, k := range opts[:min(len(opts), len(r))] {
|
|
||||||
r[i] = discord.AutocompleteChoiceString{Name: k, Value: k}
|
|
||||||
}
|
|
||||||
return e.AutocompleteResult(r)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func skillButton(data discord.ButtonInteractionData, e *handler.ComponentEvent) error {
|
func skillButton(data discord.ButtonInteractionData, e *handler.ComponentEvent) error {
|
||||||
|
|||||||
27
skill.go
27
skill.go
@@ -18,13 +18,25 @@ func RenderSkill(id horse.SkillID, all map[horse.SkillID]horse.Skill, groups map
|
|||||||
}
|
}
|
||||||
|
|
||||||
thumburl := fmt.Sprintf("https://gametora.com/images/umamusume/skill_icons/utx_ico_skill_%d.png", s.IconID)
|
thumburl := fmt.Sprintf("https://gametora.com/images/umamusume/skill_icons/utx_ico_skill_%d.png", s.IconID)
|
||||||
r := discord.NewContainer(discord.NewSection(discord.NewTextDisplayf("## %s\n%s", s.Name, s.Description)).WithAccessory(discord.NewThumbnail(thumburl)))
|
top := "## " + s.Name
|
||||||
|
if s.UniqueOwner != "" {
|
||||||
|
top += "\n-# " + s.UniqueOwner
|
||||||
|
}
|
||||||
|
r := discord.NewContainer(
|
||||||
|
discord.NewSection(
|
||||||
|
discord.NewTextDisplay(top),
|
||||||
|
discord.NewTextDisplay(s.Description),
|
||||||
|
).WithAccessory(discord.NewThumbnail(thumburl)),
|
||||||
|
)
|
||||||
var skilltype string
|
var skilltype string
|
||||||
switch {
|
switch {
|
||||||
case s.Rarity == 3, s.Rarity == 4, s.Rarity == 5:
|
case s.Rarity == 3, s.Rarity == 4, s.Rarity == 5:
|
||||||
// unique of various star levels
|
// unique of various star levels
|
||||||
r.AccentColor = 0xaca4d4
|
r.AccentColor = 0xaca4d4
|
||||||
skilltype = "Unique Skill"
|
skilltype = "Unique Skill"
|
||||||
|
case s.UniqueOwner != "":
|
||||||
|
r.AccentColor = 0xcccccc
|
||||||
|
skilltype = "Inherited Unique"
|
||||||
case s.Rarity == 2:
|
case s.Rarity == 2:
|
||||||
// rare (gold)
|
// rare (gold)
|
||||||
r.AccentColor = 0xd7c25b
|
r.AccentColor = 0xd7c25b
|
||||||
@@ -118,11 +130,18 @@ func isDebuff(s horse.Skill) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var skillGlobalAuto = sync.OnceValue(func() *autocomplete.Set {
|
var skillGlobalAuto = sync.OnceValue(func() *autocomplete.Set[discord.AutocompleteChoice] {
|
||||||
var set autocomplete.Set
|
var set autocomplete.Set[discord.AutocompleteChoice]
|
||||||
for _, id := range global.OrderedSkills {
|
for _, id := range global.OrderedSkills {
|
||||||
s := global.AllSkills[id]
|
s := global.AllSkills[id]
|
||||||
set.Add(s.Name, s.Name)
|
set.Add(s.Name, discord.AutocompleteChoiceString{Name: s.Name, Value: s.Name})
|
||||||
|
if s.UniqueOwner != "" {
|
||||||
|
if s.Rarity >= 3 {
|
||||||
|
set.Add(s.UniqueOwner, discord.AutocompleteChoiceString{Name: "Unique: " + s.UniqueOwner, Value: s.Name})
|
||||||
|
} else {
|
||||||
|
set.Add(s.UniqueOwner, discord.AutocompleteChoiceString{Name: "Inherited unique: " + s.UniqueOwner, Value: s.Name})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return &set
|
return &set
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user