unbot/features/dictionary.go
2026-06-01 18:37:01 +02:00

206 lines
5.8 KiB
Go

package features
import (
"fmt"
"strings"
"github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/disgoorg/snowflake/v2"
"github.com/elisiei/unbot/db"
)
type Dictionary struct {
db *db.DB
config DictionaryConfig
}
type DictionaryConfig struct {
Enabled bool
}
func NewDictionary(database *db.DB, enabled bool) *Dictionary {
return &Dictionary{db: database, config: DictionaryConfig{Enabled: enabled}}
}
func (d *Dictionary) Command() discord.SlashCommandCreate {
return discord.SlashCommandCreate{
Name: "dict",
Description: "Urban dictionary for the server",
Options: []discord.ApplicationCommandOption{
discord.ApplicationCommandOptionSubCommand{
Name: "add",
Description: "Add a definition",
Options: []discord.ApplicationCommandOption{
discord.ApplicationCommandOptionString{
Name: "word",
Description: "The word to define",
Required: true,
},
discord.ApplicationCommandOptionString{
Name: "definition",
Description: "The definition",
Required: true,
},
},
},
discord.ApplicationCommandOptionSubCommand{
Name: "get",
Description: "Get a definition",
Options: []discord.ApplicationCommandOption{
discord.ApplicationCommandOptionString{
Name: "word",
Description: "The word to look up",
Required: true,
Autocomplete: true,
},
},
},
discord.ApplicationCommandOptionSubCommand{
Name: "remove",
Description: "Remove your definition",
Options: []discord.ApplicationCommandOption{
discord.ApplicationCommandOptionString{
Name: "word",
Description: "The word to remove",
Required: true,
},
},
},
discord.ApplicationCommandOptionSubCommand{
Name: "list",
Description: "List all defined words",
},
},
}
}
func (d *Dictionary) HandleAutocomplete(e *events.AutocompleteInteractionCreate) {
focused := e.Data.Focused()
input := strings.ToLower(focused.String())
allWords, err := d.db.ListWords()
if err != nil {
return
}
var choices []discord.AutocompleteChoice
for _, w := range allWords {
if strings.HasPrefix(strings.ToLower(w.Word), input) {
if len(choices) >= 25 {
break
}
choices = append(choices, discord.AutocompleteChoiceString{
Name: w.Word,
Value: w.Word,
})
}
}
e.AutocompleteResult(choices)
}
func (d *Dictionary) HandleAdd(e *events.ApplicationCommandInteractionCreate) {
data := e.SlashCommandInteractionData()
word := strings.ToLower(strings.TrimSpace(data.String("word")))
definition := strings.TrimSpace(data.String("definition"))
if word == "" || definition == "" {
e.CreateMessage(discord.NewMessageCreate().WithContent("Word and definition cannot be empty.").WithEphemeral(true))
return
}
err := d.db.AddDefinition(word, definition, e.User().ID.String())
if err != nil {
e.CreateMessage(discord.NewMessageCreate().WithContent("Failed to save definition.").WithEphemeral(true))
return
}
e.CreateMessage(discord.NewMessageCreate().WithContent(fmt.Sprintf("Added definition for **%s**", word)))
}
func (d *Dictionary) HandleGet(e *events.ApplicationCommandInteractionCreate) {
data := e.SlashCommandInteractionData()
word := strings.ToLower(strings.TrimSpace(data.String("word")))
entry, err := d.db.GetDefinition(word)
if err != nil {
e.CreateMessage(discord.NewMessageCreate().WithContent("Failed to look up definition.").WithEphemeral(true))
return
}
if entry == nil {
e.CreateMessage(discord.NewMessageCreate().WithContent(fmt.Sprintf("No definition found for **%s**", word)).WithEphemeral(true))
return
}
var footerText string
authorID, parseErr := snowflake.Parse(entry.AuthorID)
if parseErr == nil && authorID != 0 {
footerText = "Added by <@" + authorID.String() + ">"
}
embed := discord.Embed{
Title: entry.Word,
Description: entry.Definition,
Color: 0x00AE86,
Fields: []discord.EmbedField{
{Name: "Rating", Value: fmt.Sprintf("👍 %d | 👎 %d", entry.Upvotes, entry.Downvotes), Inline: new(true)},
},
Footer: &discord.EmbedFooter{Text: footerText},
}
e.CreateMessage(discord.NewMessageCreate().AddEmbeds(embed))
}
func (d *Dictionary) HandleRemove(e *events.ApplicationCommandInteractionCreate) {
data := e.SlashCommandInteractionData()
word := strings.ToLower(strings.TrimSpace(data.String("word")))
entry, err := d.db.GetDefinition(word)
if err != nil {
e.CreateMessage(discord.NewMessageCreate().WithContent("Failed to look up definition.").WithEphemeral(true))
return
}
if entry == nil {
e.CreateMessage(discord.NewMessageCreate().WithContent(fmt.Sprintf("No definition found for **%s**", word)).WithEphemeral(true))
return
}
if entry.AuthorID != e.User().ID.String() {
e.CreateMessage(discord.NewMessageCreate().WithContent("You can only remove your own definitions.").WithEphemeral(true))
return
}
if err := d.db.RemoveDefinition(word); err != nil {
e.CreateMessage(discord.NewMessageCreate().WithContent("Failed to remove definition.").WithEphemeral(true))
return
}
e.CreateMessage(discord.NewMessageCreate().WithContent(fmt.Sprintf("Removed definition for **%s**", word)))
}
func (d *Dictionary) HandleList(e *events.ApplicationCommandInteractionCreate) {
words, err := d.db.ListWords()
if err != nil {
e.CreateMessage(discord.NewMessageCreate().WithContent("Failed to list words.").WithEphemeral(true))
return
}
if len(words) == 0 {
e.CreateMessage(discord.NewMessageCreate().WithContent("No words defined yet.").WithEphemeral(true))
return
}
var sb strings.Builder
for i, w := range words {
if i > 0 {
sb.WriteString(", ")
}
fmt.Fprintf(&sb, "**%s**", w.Word)
if i >= 50 {
sb.WriteString("...")
break
}
}
e.CreateMessage(discord.NewMessageCreate().WithContent(fmt.Sprintf("Defined words (%d): %s", len(words), sb.String())))
}