From 805598338e74f22e42b7cf241224845c6b20aac7 Mon Sep 17 00:00:00 2001 From: kylepokorski <68132697+kylepokorski@users.noreply.github.com> Date: Tue, 21 Jan 2025 13:33:57 -0800 Subject: [PATCH 01/10] matching main --- eod/msgs.go | 57 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/eod/msgs.go b/eod/msgs.go index 92414347..590fef09 100644 --- a/eod/msgs.go +++ b/eod/msgs.go @@ -48,7 +48,7 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { } b.elements.Hint(c, []any{val, nil}) - case "cat": + case "cat", "c": if !b.base.CheckCtx(c, "cat") { return } @@ -149,18 +149,63 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { if !b.base.CheckCtx(c, "sign") { return } - parts := strings.SplitN(content, "|", 2) - if len(parts) != 2 { - c.Respond(sevcord.NewMessage("Invalid format! " + types.RedCircle)) + parts := strings.SplitN(content, "|", 3) + if len(parts) != 3 { + c.Respond(sevcord.NewMessage("Use `!sign [e/c/q]|[element/category/query name]|`! " + types.RedCircle)) + return + } + // check for signing element/category/query + switch parts[0] { + case "e", "element": + b.elements.MsgSignCmd(c, strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])) + + case "c", "cat", "category": + b.categories.SignCmd(c, []any{strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])}) + + case "q", "query": + b.queries.SignCmd(c, []any{strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])}) + + default: + c.Respond(sevcord.NewMessage("Use `!sign [e/c/q]|[element/category/query name]|`! " + types.RedCircle)) + } + case "col", "color", "colour": + if !b.base.CheckCtx(c, "color") { + return + } + // check part amount + parts := strings.SplitN(content, "|", 3) + if len(parts) != 3 { + c.Respond(sevcord.NewMessage("Use `!color [e/c/q]|[element/category/query name]|`! " + types.RedCircle)) return } - b.elements.MsgSignCmd(c, strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])) + // check for coloring element/category/query + switch parts[0] { + case "e", "element": + id, ok := b.getElementId(c, parts[1]) + if !ok { + return + } + b.elements.ColorCmd(c, []any{id, strings.TrimSpace(parts[2])}) + case "c", "cat", "category": + b.categories.ColorCmd(c, []any{strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])}) + + case "q", "query": + b.queries.ColorCmd(c, []any{strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])}) + + default: + c.Respond(sevcord.NewMessage("Use `!color [e/c/q]|[element/category/query name]|`! " + types.RedCircle)) + } case "n", "next": if !b.base.CheckCtx(c, "next") { return } - b.elements.Next(c, []any{nil}) + val := any(nil) + part := strings.TrimSpace(content) + if part != "" { + val = any(part) + } + b.elements.Next(c, []any{val}) case "img", "image": if !b.base.CheckCtx(c, "image") { From 4afd4d4a2aee071a63f58a67cb4f8f2b8f48176b Mon Sep 17 00:00:00 2001 From: kylepokorski <68132697+kylepokorski@users.noreply.github.com> Date: Wed, 22 Jan 2025 00:52:17 -0800 Subject: [PATCH 02/10] More Configuration + cat colors+images Adding cat colors and images. Adding vote icons and progress icons as part of configuration --- .gitignore | 9 ++++++++- eod/base/base.go | 2 ++ eod/base/config.go | 21 +++++++++++++++++++++ eod/elements/hint.go | 10 ++++++++-- eod/pages/categories.go | 32 +++++++++++++++++++++++++++----- eod/pages/inv.go | 11 +++++++++-- eod/pages/products.go | 11 +++++++++-- eod/pages/queries.go | 10 ++++++++-- eod/polls/handle.go | 36 ++++++++++++++++++++++++++---------- eod/polls/make.go | 12 ++++++++++-- eod/types/types.go | 4 ++-- 11 files changed, 130 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index e1a75d90..4cb63496 100644 --- a/.gitignore +++ b/.gitignore @@ -69,4 +69,11 @@ run/bsharp/token.txt # Added by cargo /target -output.log \ No newline at end of file +output.log +run/eod/__debug_bin2487916788 +run/eod/main.go +run/eod/main.go +run/eod/main.go +run/eod/main.go +run/eod/main.go +/run/eod diff --git a/eod/base/base.go b/eod/base/base.go index e62992c0..5f550f84 100644 --- a/eod/base/base.go +++ b/eod/base/base.go @@ -32,6 +32,8 @@ func (b *Base) Init() { sevcord.NewSlashCommand("votecnt", "Configure the minimum number of votes!", b.ConfigVoteCnt, sevcord.NewOption("count", "The new vote count!", sevcord.OptionKindInt, true)), sevcord.NewSlashCommand("pollcnt", "Configure the maximum number of polls!", b.ConfigPollCnt, sevcord.NewOption("count", "The new poll count!", sevcord.OptionKindInt, true)), sevcord.NewSlashCommand("playchannels", "Configure the channels in which users can combine elements!", b.ConfigPlayChannels), + sevcord.NewSlashCommand("voteicons", "Configure the emojis used for voting!", b.ConfigVoteIcons, sevcord.NewOption("upvote", "The new upvote emoji!", sevcord.OptionKindString, true), sevcord.NewOption("downvote", "The new downvote emoji!", sevcord.OptionKindString, true)), + sevcord.NewSlashCommand("progressicons", "Configure the emojis for progress!", b.ConfigProgIcons, sevcord.NewOption("positive", "The positive progress emoji!", sevcord.OptionKindString, true), sevcord.NewOption("negative", "The negative progress emoji!", sevcord.OptionKindString, true)), ).RequirePermissions(discordgo.PermissionManageChannels)) b.s.AddSelectHandler("config_play", b.ConfigPlayChannelsHandler) } diff --git a/eod/base/config.go b/eod/base/config.go index 04f153dc..9dc8aba9 100644 --- a/eod/base/config.go +++ b/eod/base/config.go @@ -69,7 +69,28 @@ func (b *Base) ConfigPlayChannels(c sevcord.Ctx, opts []any) { )) b.configNewsMessage(c, "Changed Config - **Play Channels**") } +func (b *Base) ConfigVoteIcons(c sevcord.Ctx, opts []any) { + c.Acknowledge() + _, err := b.db.Exec("UPDATE config SET voteicons=$1 WHERE guild =$2", pq.Array(opts), c.Guild()) + if err != nil { + b.Error(c, err) + return + } + c.Respond(sevcord.NewMessage("Successfully updated voting emojis!")) + b.configNewsMessage(c, "Change Config - **Vote Icons**") +} +func (b *Base) ConfigProgIcons(c sevcord.Ctx, opts []any) { + c.Acknowledge() + _, err := b.db.Exec("UPDATE config SET progicons=$1 WHERE guild =$2", pq.Array(opts), c.Guild()) + if err != nil { + b.Error(c, err) + return + } + c.Respond(sevcord.NewMessage("Successfully updated progress emojis!")) + b.configNewsMessage(c, "Change Config - **Progress Icons**") + +} func (b *Base) ConfigPlayChannelsHandler(c sevcord.Ctx, params string, opts []string) { c.Acknowledge() diff --git a/eod/elements/hint.go b/eod/elements/hint.go index 5b4bf1cf..e75339ea 100644 --- a/eod/elements/hint.go +++ b/eod/elements/hint.go @@ -155,15 +155,21 @@ func (e *Elements) HintHandler(c sevcord.Ctx, params string) { return } + var progress pq.StringArray + err = e.db.QueryRow("SELECT progicons FROM config WHERE guild=$1", c.Guild()).Scan(&progress) + if err != nil { + e.base.Error(c, err) + return + } // Create message description := &strings.Builder{} for _, item := range items { // Emoji if item.Cont { - description.WriteString(types.Check) + description.WriteString(progress[0]) } else { - description.WriteString(types.NoCheck) + description.WriteString(progress[1]) } description.WriteString(" ") diff --git a/eod/pages/categories.go b/eod/pages/categories.go index c3215d55..037ad64a 100644 --- a/eod/pages/categories.go +++ b/eod/pages/categories.go @@ -9,6 +9,7 @@ import ( "github.com/Nv7-Github/Nv7Haven/eod/types" "github.com/Nv7-Github/sevcord/v2" "github.com/dustin/go-humanize" + "github.com/lib/pq" ) var catListSorts = []sevcord.Choice{ @@ -53,11 +54,17 @@ func (p *Pages) CatListHandler(c sevcord.Ctx, params string) { return } + var progress pq.StringArray + err = p.db.QueryRow("SELECT progicons FROM config WHERE guild=$1", c.Guild()).Scan(&progress) + if err != nil { + p.base.Error(c, err) + return + } // Description desc := &strings.Builder{} for _, v := range cats { if v.Length == v.InvIntersect { - fmt.Fprintf(desc, "%s %s\n", v.Name, types.Check) + fmt.Fprintf(desc, "%s %s\n", v.Name, progress[0]) } else { fmt.Fprintf(desc, "%s (%s%%)\n", v.Name, humanize.FormatFloat("", float64(v.InvIntersect)/float64(v.Length)*100)) } @@ -116,22 +123,37 @@ func (p *Pages) CatHandler(c sevcord.Ctx, params string) { } // Description + var progress pq.StringArray + err = p.db.QueryRow("SELECT progicons FROM config WHERE guild=$1", c.Guild()).Scan(&progress) + if err != nil { + p.base.Error(c, err) + return + } desc := &strings.Builder{} for _, v := range items { if v.Cont { - fmt.Fprintf(desc, "%s %s\n", v.Name, types.Check) + fmt.Fprintf(desc, "%s %s\n", v.Name, progress[0]) } else { - fmt.Fprintf(desc, "%s %s\n", v.Name, types.NoCheck) + fmt.Fprintf(desc, "%s %s\n", v.Name, progress[1]) } } + //get color and image + var color int + var img string + err = p.db.QueryRow("SELECT color,image FROM categories WHERE guild=$1", c.Guild()).Scan(&color, &img) + if err != nil || color == 0 { + color = 10181046 //Purple + } // Create embed := sevcord.NewEmbed(). Title(fmt.Sprintf("%s (%s, %s%%)", parts[4], humanize.Comma(int64(cnt)), humanize.FormatFloat("", float64(common)/float64(cnt)*100))). Description(desc.String()). Footer(fmt.Sprintf("Page %d/%d", page+1, pagecnt), ""). - Color(10181046) // Purple - + Color(color) + if err == nil { + embed = embed.Thumbnail(img) + } c.Respond(sevcord.NewMessage(""). AddEmbed(embed). AddComponentRow(PageSwitchBtns("cat", fmt.Sprintf("%s|%s|%d|%s", parts[1], parts[2], page, parts[4]))...), diff --git a/eod/pages/inv.go b/eod/pages/inv.go index 6f5de3ba..2472359d 100644 --- a/eod/pages/inv.go +++ b/eod/pages/inv.go @@ -10,6 +10,7 @@ import ( "github.com/Nv7-Github/sevcord/v2" "github.com/bwmarrin/discordgo" "github.com/dustin/go-humanize" + "github.com/lib/pq" ) // Params: prevnext|user|sort|page @@ -58,13 +59,19 @@ func (p *Pages) InvHandler(c sevcord.Ctx, params string) { } // Make description + var progress pq.StringArray + err = p.db.QueryRow("SELECT progicons FROM config WHERE guild=$1", c.Guild()).Scan(&progress) + if err != nil { + p.base.Error(c, err) + return + } desc := &strings.Builder{} for _, v := range inv { if c.Author().User.ID != parts[1] { if v.Cont { - fmt.Fprintf(desc, "%s %s\n", v.Name, types.Check) + fmt.Fprintf(desc, "%s %s\n", v.Name, progress[0]) } else { - fmt.Fprintf(desc, "%s %s\n", v.Name, types.NoCheck) + fmt.Fprintf(desc, "%s %s\n", v.Name, progress[1]) } } else { fmt.Fprintf(desc, "%s\n", v.Name) diff --git a/eod/pages/products.go b/eod/pages/products.go index 3dab9f61..f9557565 100644 --- a/eod/pages/products.go +++ b/eod/pages/products.go @@ -9,6 +9,7 @@ import ( "github.com/Nv7-Github/Nv7Haven/eod/types" "github.com/Nv7-Github/sevcord/v2" "github.com/dustin/go-humanize" + "github.com/lib/pq" ) // Params: prevnext|elem|sort|page @@ -42,12 +43,18 @@ func (p *Pages) ProductsHandler(c sevcord.Ctx, params string) { } // Make description + var progress pq.StringArray + err = p.db.QueryRow("SELECT progicons FROM config WHERE guild=$1", c.Guild()).Scan(&progress) + if err != nil { + p.base.Error(c, err) + return + } desc := &strings.Builder{} for _, v := range items { if v.Cont { - fmt.Fprintf(desc, "%s %s\n", v.Name, types.Check) + fmt.Fprintf(desc, "%s %s\n", v.Name, progress[0]) } else { - fmt.Fprintf(desc, "%s %s\n", v.Name, types.NoCheck) + fmt.Fprintf(desc, "%s %s\n", v.Name, progress[1]) } } diff --git a/eod/pages/queries.go b/eod/pages/queries.go index a01a2988..db99d838 100644 --- a/eod/pages/queries.go +++ b/eod/pages/queries.go @@ -136,12 +136,18 @@ func (p *Pages) QueryHandler(c sevcord.Ctx, params string) { } // Description + var progress pq.StringArray + err = p.db.QueryRow("SELECT progicons FROM config WHERE guild=$1", c.Guild()).Scan(&progress) + if err != nil { + p.base.Error(c, err) + return + } desc := &strings.Builder{} for _, v := range items { if v.Cont { - fmt.Fprintf(desc, "%s %s\n", v.Name, types.Check) + fmt.Fprintf(desc, "%s %s\n", v.Name, progress[0]) } else { - fmt.Fprintf(desc, "%s %s\n", v.Name, types.NoCheck) + fmt.Fprintf(desc, "%s %s\n", v.Name, progress[1]) } } diff --git a/eod/polls/handle.go b/eod/polls/handle.go index f54b7409..ec836bcc 100644 --- a/eod/polls/handle.go +++ b/eod/polls/handle.go @@ -6,22 +6,29 @@ import ( "github.com/Nv7-Github/Nv7Haven/eod/types" "github.com/bwmarrin/discordgo" + "github.com/lib/pq" ) -const UpArrow = "⬆️" -const DownArrow = "⬇️" - func (b *Polls) reactionHandler(s *discordgo.Session, r *discordgo.MessageReactionAdd) { + + var votereactions pq.StringArray + //index 0 is upvote, index 1 is downvote + + err := b.db.QueryRow("SELECT voteicons FROM config WHERE guild=$1", r.GuildID).Scan(&votereactions) + if err != nil { + return + + } if r.UserID == s.State.User.ID { return } - if r.Emoji.Name != UpArrow && r.Emoji.Name != DownArrow { + if r.Emoji.Name != votereactions[0] && r.Emoji.Name != votereactions[1] { return } // Get poll & vote cnt var p types.Poll - err := b.db.Get(&p, "SELECT * FROM polls WHERE guild=$1 AND message=$2", r.GuildID, r.MessageID) + err = b.db.Get(&p, "SELECT * FROM polls WHERE guild=$1 AND message=$2", r.GuildID, r.MessageID) if err != nil { if err != sql.ErrNoRows { log.Println("poll fetch err", err) @@ -36,7 +43,7 @@ func (b *Polls) reactionHandler(s *discordgo.Session, r *discordgo.MessageReacti } // User trying to delete? - if r.UserID == p.Creator && r.Emoji.Name == DownArrow { + if r.UserID == p.Creator && r.Emoji.Name == votereactions[1] { b.deletePoll(&p, s) return } @@ -48,7 +55,7 @@ func (b *Polls) reactionHandler(s *discordgo.Session, r *discordgo.MessageReacti } // Handle - if r.Emoji.Name == UpArrow { + if r.Emoji.Name == votereactions[0] { p.Upvotes++ } else { p.Downvotes++ @@ -66,16 +73,25 @@ func (b *Polls) reactionHandler(s *discordgo.Session, r *discordgo.MessageReacti } func (b *Polls) unReactionHandler(s *discordgo.Session, r *discordgo.MessageReactionRemove) { + var votereactions pq.StringArray + //index 0 is upvote, index 1 is downvote + + err := b.db.QueryRow("SELECT voteicons FROM config WHERE guild=$1", r.GuildID).Scan(&votereactions) + if err != nil { + return + + } + if r.UserID == s.State.User.ID { return } - if r.Emoji.Name != UpArrow && r.Emoji.Name != DownArrow { + if r.Emoji.Name != votereactions[0] && r.Emoji.Name != votereactions[1] { return } // Get poll & vote cnt var p types.Poll - err := b.db.Get(&p, "SELECT * FROM polls WHERE guild=$1 AND message=$2", r.GuildID, r.MessageID) + err = b.db.Get(&p, "SELECT * FROM polls WHERE guild=$1 AND message=$2", r.GuildID, r.MessageID) if err != nil { return } @@ -92,7 +108,7 @@ func (b *Polls) unReactionHandler(s *discordgo.Session, r *discordgo.MessageReac } // Handle - if r.Emoji.Name == UpArrow { + if r.Emoji.Name == votereactions[0] { p.Upvotes-- } else { p.Downvotes-- diff --git a/eod/polls/make.go b/eod/polls/make.go index 394b106f..a58351d6 100644 --- a/eod/polls/make.go +++ b/eod/polls/make.go @@ -8,6 +8,7 @@ import ( "github.com/Nv7-Github/Nv7Haven/eod/types" "github.com/Nv7-Github/sevcord/v2" "github.com/bwmarrin/discordgo" + "github.com/lib/pq" ) func (b *Polls) CreatePoll(c sevcord.Ctx, p *types.Poll) types.Resp { @@ -54,11 +55,18 @@ func (b *Polls) CreatePoll(c sevcord.Ctx, p *types.Poll) types.Resp { p.Message = msg.ID // Add reactions - err = dg.MessageReactionAdd(p.Channel, msg.ID, UpArrow) + var votereactions pq.StringArray + + err = b.db.QueryRow("SELECT voteicons FROM config WHERE guild=$1", c.Guild()).Scan(&votereactions) + if err != nil { + return types.Error(err) + + } + err = dg.MessageReactionAdd(p.Channel, msg.ID, votereactions[0]) if err != nil { return types.Error(err) } - err = dg.MessageReactionAdd(p.Channel, msg.ID, DownArrow) + err = dg.MessageReactionAdd(p.Channel, msg.ID, votereactions[1]) if err != nil { return types.Error(err) } diff --git a/eod/types/types.go b/eod/types/types.go index b8b72f6a..3c3737a4 100644 --- a/eod/types/types.go +++ b/eod/types/types.go @@ -74,6 +74,8 @@ type Config struct { VoteCnt int `db:"votecnt"` PollCnt int `db:"pollcnt"` PlayChannels pq.StringArray `db:"play"` + VoteIcons pq.StringArray `db:"voteicons"` + ProgIcons pq.StringArray `db:"progicons"` } type ServerMem struct { @@ -246,6 +248,4 @@ type CombCache struct { // Consts const RedCircle = "🔴" -const Check = "<:eodCheck:765333533362225222>" -const NoCheck = "❌" const MaxComboLength = 21 From e7672fc10d0a1779d492461b7e4cd5b3828e227a Mon Sep 17 00:00:00 2001 From: kylepokorski <68132697+kylepokorski@users.noreply.github.com> Date: Wed, 22 Jan 2025 03:38:35 -0800 Subject: [PATCH 03/10] Fix category image+color fix category image+color --- eod/pages/categories.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/eod/pages/categories.go b/eod/pages/categories.go index 037ad64a..21c030e1 100644 --- a/eod/pages/categories.go +++ b/eod/pages/categories.go @@ -141,7 +141,8 @@ func (p *Pages) CatHandler(c sevcord.Ctx, params string) { //get color and image var color int var img string - err = p.db.QueryRow("SELECT color,image FROM categories WHERE guild=$1", c.Guild()).Scan(&color, &img) + err = p.db.QueryRow("SELECT color, image FROM categories WHERE name=$1 AND guild=$2", parts[len(parts)-1], c.Guild()).Scan(&color, &img) + if err != nil || color == 0 { color = 10181046 //Purple } From f946895f5f4ada252f7f1b3fb9633cdd866d8229 Mon Sep 17 00:00:00 2001 From: kylepokorski <68132697+kylepokorski@users.noreply.github.com> Date: Wed, 22 Jan 2025 19:18:18 -0800 Subject: [PATCH 04/10] Query+Hint changes Making queries have color+image Making hint be able to use ID of elements --- eod/msgs.go | 9 ++++++++- eod/pages/queries.go | 13 +++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/eod/msgs.go b/eod/msgs.go index 590fef09..770fb6e5 100644 --- a/eod/msgs.go +++ b/eod/msgs.go @@ -18,11 +18,18 @@ var seps = []string{ func (b *Bot) getElementId(c sevcord.Ctx, val string) (int64, bool) { var id int64 - err := b.db.QueryRow("SELECT id FROM elements WHERE LOWER(name)=$1 AND guild=$2", strings.ToLower(strings.TrimSpace(val)), c.Guild()).Scan(&id) + var err error + id, err = strconv.ParseInt(strings.Trim(strings.TrimSpace(val), "#"), 10, 64) + if err == nil { + err = b.db.QueryRow("SELECT id FROM elements WHERE id=$1 AND guild=$2", strings.ToLower(strings.TrimLeft(strings.TrimSpace(val), "#")), c.Guild()).Scan(&id) + } else { + err = b.db.QueryRow("SELECT id FROM elements WHERE LOWER(name)=$1 AND guild=$2", strings.ToLower(strings.TrimSpace(val)), c.Guild()).Scan(&id) + } if err != nil { b.base.Error(c, err, "Element **"+val+"** doesn't exist!") return 0, false } + return id, true } diff --git a/eod/pages/queries.go b/eod/pages/queries.go index db99d838..edd20446 100644 --- a/eod/pages/queries.go +++ b/eod/pages/queries.go @@ -150,14 +150,23 @@ func (p *Pages) QueryHandler(c sevcord.Ctx, params string) { fmt.Fprintf(desc, "%s %s\n", v.Name, progress[1]) } } + var img string + var color int + err = p.db.QueryRow("SELECT color,image FROM queries WHERE name=$1 AND guild =$2", parts[len(parts)-1], c.Guild()).Scan(&color, &img) + + if err != nil || color == 0 { + color = 10181046 // Purple + } // Create embed := sevcord.NewEmbed(). Title(fmt.Sprintf("%s (%s, %s%%)", parts[4], humanize.Comma(int64(cnt)), humanize.FormatFloat("", float64(common)/float64(cnt)*100))). Description(desc.String()). Footer(fmt.Sprintf("Page %d/%d", page+1, pagecnt), ""). - Color(10181046) // Purple - + Color(color) + if err == nil { + embed = embed.Thumbnail(img) + } c.Respond(sevcord.NewMessage(""). AddEmbed(embed). AddComponentRow(PageSwitchBtns("query", fmt.Sprintf("%s|%s|%d|%s", parts[1], parts[2], page, parts[4]))...), From f79ef3b7ded99a296df8a5c05ab520efd703d09c Mon Sep 17 00:00:00 2001 From: kylepokorski <68132697+kylepokorski@users.noreply.github.com> Date: Thu, 23 Jan 2025 16:14:54 -0800 Subject: [PATCH 05/10] !ac and !rc multiple nonexistent elements + no duplicate nonexistent elements Adding showing multiple nonexistent elements in !ac/!rc. Making it so duplicate entries don't appear in !ac/rc or combinations --- eod/elements/combo.go | 3 ++- eod/msgs.go | 42 +++++++++++++++++++++++++++++++----------- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/eod/elements/combo.go b/eod/elements/combo.go index 0f2b620c..79519e3d 100644 --- a/eod/elements/combo.go +++ b/eod/elements/combo.go @@ -3,6 +3,7 @@ package elements import ( "database/sql" "fmt" + "slices" "sort" "strconv" "strings" @@ -65,7 +66,7 @@ func (e *Elements) Combine(c sevcord.Ctx, elemVals []string) { dontExist := make([]string, 0) for _, v := range elemVals { _, exists := exist[strings.ToLower(v)] - if !exists { + if !exists && !slices.Contains(dontExist, "**"+v+"**") { dontExist = append(dontExist, "**"+v+"**") } } diff --git a/eod/msgs.go b/eod/msgs.go index 770fb6e5..d8439ca0 100644 --- a/eod/msgs.go +++ b/eod/msgs.go @@ -2,6 +2,7 @@ package eod import ( "fmt" + "slices" "strconv" "strings" @@ -16,7 +17,15 @@ var seps = []string{ "plus", } -func (b *Bot) getElementId(c sevcord.Ctx, val string) (int64, bool) { +func makeListResp(start, join, end string, vals []string) string { + if len(vals) == 2 { + return fmt.Sprintf("%s %s %s %s%s %s", start, vals[0], join, vals[1], end, types.RedCircle) + } else if len(vals) > 2 { + return fmt.Sprintf("%s %s, %s %s%s %s", start, strings.Join(vals[:len(vals)-1], ", "), join, vals[len(vals)-1], end, types.RedCircle) + } + return "" +} +func (b *Bot) getElementId(c sevcord.Ctx, val string, showerr bool) (int64, bool) { var id int64 var err error id, err = strconv.ParseInt(strings.Trim(strings.TrimSpace(val), "#"), 10, 64) @@ -25,8 +34,10 @@ func (b *Bot) getElementId(c sevcord.Ctx, val string) (int64, bool) { } else { err = b.db.QueryRow("SELECT id FROM elements WHERE LOWER(name)=$1 AND guild=$2", strings.ToLower(strings.TrimSpace(val)), c.Guild()).Scan(&id) } - if err != nil { - b.base.Error(c, err, "Element **"+val+"** doesn't exist!") + if err != nil && showerr { + b.base.Error(c, err, "Element **"+val+"** doesn't exist! "+types.RedCircle) + return 0, false + } else if err != nil && !showerr { return 0, false } @@ -47,7 +58,7 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { } val := any(nil) if content != "" { - v, ok := b.getElementId(c, content) + v, ok := b.getElementId(c, content, true) if !ok { return } @@ -98,7 +109,7 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { if !b.base.CheckCtx(c, "products") { return } - id, ok := b.getElementId(c, content) + id, ok := b.getElementId(c, content, true) if !ok { return } @@ -119,24 +130,33 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { c.Respond(sevcord.NewMessage("Invalid format! " + types.RedCircle)) return } + dontExist := make([]string, 0) els := make([]int, 0) added := false for sep := range seps { if strings.Contains(parts[1], seps[sep]) { vals := strings.Split(parts[1], seps[sep]) for _, val := range vals { - id, ok := b.getElementId(c, val) - if !ok { - return + id, ok := b.getElementId(c, val, false) + if !ok && !slices.Contains(dontExist, "**"+val+"**") { + dontExist = append(dontExist, "**"+val+"**") } els = append(els, int(id)) } - added = true break } } + if len(dontExist) == 0 { + added = true + } else if len(dontExist) == 1 { + c.Respond(sevcord.NewMessage("Element **" + dontExist[0] + "** doesn't exist!")) + return + } else { + c.Respond(sevcord.NewMessage(makeListResp("Elements", "and", " don't exist!", dontExist))) + return + } if !added { - id, ok := b.getElementId(c, parts[1]) + id, ok := b.getElementId(c, parts[1], true) if !ok { return } @@ -188,7 +208,7 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { // check for coloring element/category/query switch parts[0] { case "e", "element": - id, ok := b.getElementId(c, parts[1]) + id, ok := b.getElementId(c, parts[1], true) if !ok { return } From 390ed7f4920f46f41dba7325d25ad8cd75da0720 Mon Sep 17 00:00:00 2001 From: kylepokorski <68132697+kylepokorski@users.noreply.github.com> Date: Sat, 25 Jan 2025 17:20:02 -0800 Subject: [PATCH 06/10] Adding !hq/!hintquery, and !lb sort text commands Adding !hintquery/!hq. Adding lb sorts as text command, Removing "plus" as a element separator. Making color/image/sign commands case insensitive. Fixing !ac giving "Invalid format" when it shouldn't (this was introduced in my last commit) Matching main --- eod/categories/infoedit.go | 35 +++++++++++++++++++++++++ eod/msgs.go | 52 +++++++++++++++++++++++++++++++------- eod/queries/edit.go | 35 +++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 9 deletions(-) diff --git a/eod/categories/infoedit.go b/eod/categories/infoedit.go index 9f68f8cc..6d79b5e1 100644 --- a/eod/categories/infoedit.go +++ b/eod/categories/infoedit.go @@ -1,6 +1,7 @@ package categories import ( + "database/sql" "fmt" "strconv" "strings" @@ -70,6 +71,40 @@ func (c *Categories) SignCmd(ctx sevcord.Ctx, opts []any) { }).Input(sevcord.NewModalInput("New Comment", "None", sevcord.ModalInputStyleParagraph, 2400))) } +func (c *Categories) MsgSignCmd(ctx sevcord.Ctx, cat string, mark string) { + ctx.Acknowledge() + + var name string + var old string + err := c.db.QueryRow("SELECT name, comment FROM categories WHERE LOWER(name)=$1 AND guild=$2", strings.ToLower(cat), ctx.Guild()).Scan(&name, &old) + if err != nil { + if err == sql.ErrNoRows { + ctx.Respond(sevcord.NewMessage("Element **" + cat + "** doesn't exist! " + types.RedCircle)) + return + } else { + c.base.Error(ctx, err) + return + } + } + + // Make poll + res := c.polls.CreatePoll(ctx, &types.Poll{ + Kind: types.PollKindCatComment, + Data: types.PgData{ + "cat": name, + "new": mark, + "old": old, + }, + }) + if !res.Ok { + ctx.Respond(res.Response()) + return + } + + // Respond + ctx.Respond(sevcord.NewMessage(fmt.Sprintf("Suggested a note for **%s** 🖋️", name))) +} + func (c *Categories) ColorCmd(ctx sevcord.Ctx, opts []any) { ctx.Acknowledge() diff --git a/eod/msgs.go b/eod/msgs.go index d8439ca0..0b51b019 100644 --- a/eod/msgs.go +++ b/eod/msgs.go @@ -14,7 +14,6 @@ var seps = []string{ "\n", "+", ",", - "plus", } func makeListResp(start, join, end string, vals []string) string { @@ -65,7 +64,11 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { val = any(v) } b.elements.Hint(c, []any{val, nil}) - + case "hq", "hintquery": + if !b.base.CheckCtx(c, "hint") { + return + } + b.elements.Hint(c, []any{nil, content}) case "cat", "c": if !b.base.CheckCtx(c, "cat") { return @@ -103,7 +106,37 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { if !b.base.CheckCtx(c, "lb") { return } - b.pages.Lb(c, []any{nil, nil, nil}) + parts := strings.Split(content, " ") + Lbsort := "" + switch strings.ToLower(parts[0]) { + case "made": + Lbsort = "made" + case "imaged", "img": + Lbsort = "img" + case "votes": + Lbsort = "voted" + case "signed": + Lbsort = "signed" + case "colored", "colour", "coloured", "color": + Lbsort = "color" + case "catsigned": + Lbsort = "catsigned" + case "catimg", "catimage": + Lbsort = "catimg" + case "catcolor": + Lbsort = "catcolor" + case "querysigned": + Lbsort = "querysigned" + case "queryimage", "queryimg": + Lbsort = "queryimg" + case "querycolor": + Lbsort = "querycolor" + case "found", "": + Lbsort = "found" + default: + Lbsort = "found" + } + b.pages.Lb(c, []any{Lbsort, nil, nil}) case "p", "products": if !b.base.CheckCtx(c, "products") { @@ -147,7 +180,7 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { } } if len(dontExist) == 0 { - added = true + } else if len(dontExist) == 1 { c.Respond(sevcord.NewMessage("Element **" + dontExist[0] + "** doesn't exist!")) return @@ -161,6 +194,7 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { return } els = append(els, int(id)) + added = true } if len(els) == 0 { c.Respond(sevcord.NewMessage("Invalid format! " + types.RedCircle)) @@ -182,15 +216,15 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { return } // check for signing element/category/query - switch parts[0] { + switch strings.ToLower(strings.TrimSpace(parts[0])) { case "e", "element": b.elements.MsgSignCmd(c, strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])) case "c", "cat", "category": - b.categories.SignCmd(c, []any{strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])}) + b.categories.MsgSignCmd(c, strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])) case "q", "query": - b.queries.SignCmd(c, []any{strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])}) + b.queries.MsgSignCmd(c, strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])) default: c.Respond(sevcord.NewMessage("Use `!sign [e/c/q]|[element/category/query name]|`! " + types.RedCircle)) @@ -206,7 +240,7 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { return } // check for coloring element/category/query - switch parts[0] { + switch strings.ToLower(strings.TrimSpace(parts[0])) { case "e", "element": id, ok := b.getElementId(c, parts[1], true) if !ok { @@ -264,7 +298,7 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { } // Run command - switch parts[0] { + switch strings.ToLower(parts[0]) { case "e", "element": // Get ID var id int diff --git a/eod/queries/edit.go b/eod/queries/edit.go index 6e9fddf3..2707968d 100644 --- a/eod/queries/edit.go +++ b/eod/queries/edit.go @@ -1,6 +1,7 @@ package queries import ( + "database/sql" "fmt" "strconv" "strings" @@ -70,6 +71,40 @@ func (q *Queries) SignCmd(ctx sevcord.Ctx, opts []any) { }).Input(sevcord.NewModalInput("New Comment", "None", sevcord.ModalInputStyleParagraph, 2400))) } +func (q *Queries) MsgSignCmd(ctx sevcord.Ctx, query string, mark string) { + ctx.Acknowledge() + + var name string + var old string + err := q.db.QueryRow("SELECT name, comment FROM queries WHERE LOWER(name)=$1 AND guild=$2", strings.ToLower(query), ctx.Guild()).Scan(&name, &old) + if err != nil { + if err == sql.ErrNoRows { + ctx.Respond(sevcord.NewMessage("Query **" + query + "** doesn't exist! " + types.RedCircle)) + return + } else { + q.base.Error(ctx, err) + return + } + } + + // Make poll + res := q.polls.CreatePoll(ctx, &types.Poll{ + Kind: types.PollKindQueryComment, + Data: types.PgData{ + "query": name, + "new": mark, + "old": old, + }, + }) + if !res.Ok { + ctx.Respond(res.Response()) + return + } + + // Respond + ctx.Respond(sevcord.NewMessage(fmt.Sprintf("Suggested a note for **%s** 🖋️", name))) +} + func (q *Queries) ColorCmd(ctx sevcord.Ctx, opts []any) { ctx.Acknowledge() From 6ff0252004a4f7ad37139e1a1677dd8e2b76ab1e Mon Sep 17 00:00:00 2001 From: kylepokorski <68132697+kylepokorski@users.noreply.github.com> Date: Sun, 26 Jan 2025 06:09:46 -0800 Subject: [PATCH 07/10] Adding info category and info query text commands Adding info category and info query text commands. There are several variations of the names --- eod/msgs.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/eod/msgs.go b/eod/msgs.go index 0b51b019..9bc4afbf 100644 --- a/eod/msgs.go +++ b/eod/msgs.go @@ -69,6 +69,10 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { return } b.elements.Hint(c, []any{nil, content}) + case "ic", "ci", "infocategory", "infocat", "catinfo", "categoryinfo": + b.categories.Info(c, []any{content}) + case "iq", "qi", "infoquery", "queryinfo": + b.queries.Info(c, []any{content}) case "cat", "c": if !b.base.CheckCtx(c, "cat") { return From 1bb8370c876a045bc863ac5036bcae282c200918 Mon Sep 17 00:00:00 2001 From: kylepokorski <68132697+kylepokorski@users.noreply.github.com> Date: Sun, 26 Jan 2025 14:32:06 -0800 Subject: [PATCH 08/10] Update msgs.go Making empty !cat/!query show cat/query list --- eod/msgs.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/eod/msgs.go b/eod/msgs.go index 9bc4afbf..ae738fb1 100644 --- a/eod/msgs.go +++ b/eod/msgs.go @@ -77,7 +77,11 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { if !b.base.CheckCtx(c, "cat") { return } - b.pages.Cat(c, []any{any(content), nil}) + if content != "" { + b.pages.Cat(c, []any{any(content), nil}) + } else { + b.pages.CatList(c, []any{"name"}) + } case "inv": if !b.base.CheckCtx(c, "inv") { @@ -156,7 +160,11 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { if !b.base.CheckCtx(c, "query") { return } - b.pages.Query(c, []any{any(content), nil}) + if content != "" { + b.pages.Query(c, []any{any(content), nil}) + } else { + b.pages.QueryList(c, []any{"name"}) + } case "ac", "rc": if !b.base.CheckCtx(c, "cat") { From 307e4e29d0d01d64395272fa040caf7c4f0ff763 Mon Sep 17 00:00:00 2001 From: kylepokorski <68132697+kylepokorski@users.noreply.github.com> Date: Sun, 26 Jan 2025 18:46:24 -0800 Subject: [PATCH 09/10] Customization Making vote emojis and the emojis used for checking ownership (progressicons) be customizable. Making combination limit also customizable (doesn't work yet with /idea) --- eod/base/base.go | 1 + eod/base/config.go | 10 ++++ eod/elements/combo.go | 15 +++-- eod/init.go | 2 +- eod/msgs.go | 124 +++++++++------------------------------- eod/pages/categories.go | 14 +---- eod/pages/queries.go | 13 +---- eod/types/types.go | 2 +- 8 files changed, 50 insertions(+), 131 deletions(-) diff --git a/eod/base/base.go b/eod/base/base.go index 5f550f84..1fa30073 100644 --- a/eod/base/base.go +++ b/eod/base/base.go @@ -34,6 +34,7 @@ func (b *Base) Init() { sevcord.NewSlashCommand("playchannels", "Configure the channels in which users can combine elements!", b.ConfigPlayChannels), sevcord.NewSlashCommand("voteicons", "Configure the emojis used for voting!", b.ConfigVoteIcons, sevcord.NewOption("upvote", "The new upvote emoji!", sevcord.OptionKindString, true), sevcord.NewOption("downvote", "The new downvote emoji!", sevcord.OptionKindString, true)), sevcord.NewSlashCommand("progressicons", "Configure the emojis for progress!", b.ConfigProgIcons, sevcord.NewOption("positive", "The positive progress emoji!", sevcord.OptionKindString, true), sevcord.NewOption("negative", "The negative progress emoji!", sevcord.OptionKindString, true)), + sevcord.NewSlashCommand("combolength", "Configure the maximum number of elements in a combination!", b.ConfigComboLength, sevcord.NewOption("count", "The new maximum combination length!", sevcord.OptionKindInt, true)), ).RequirePermissions(discordgo.PermissionManageChannels)) b.s.AddSelectHandler("config_play", b.ConfigPlayChannelsHandler) } diff --git a/eod/base/config.go b/eod/base/config.go index 9dc8aba9..85066b25 100644 --- a/eod/base/config.go +++ b/eod/base/config.go @@ -91,6 +91,16 @@ func (b *Base) ConfigProgIcons(c sevcord.Ctx, opts []any) { b.configNewsMessage(c, "Change Config - **Progress Icons**") } +func (b *Base) ConfigComboLength(c sevcord.Ctx, opts []any) { + c.Acknowledge() + _, err := b.db.Exec("Update config SET combolength=$1 WHERE guild=$2", opts[0], c.Guild()) + if err != nil { + b.Error(c, err) + return + } + c.Respond(sevcord.NewMessage("Successfully updated maximum combination limit!")) + b.configNewsMessage(c, "Change Config - **Combination Limit**") +} func (b *Base) ConfigPlayChannelsHandler(c sevcord.Ctx, params string, opts []string) { c.Acknowledge() diff --git a/eod/elements/combo.go b/eod/elements/combo.go index 79519e3d..8b1e1170 100644 --- a/eod/elements/combo.go +++ b/eod/elements/combo.go @@ -3,7 +3,6 @@ package elements import ( "database/sql" "fmt" - "slices" "sort" "strconv" "strings" @@ -33,9 +32,13 @@ type comboRes struct { func (e *Elements) Combine(c sevcord.Ctx, elemVals []string) { c.Acknowledge() e.base.IncrementCommandStat(c, "combine") - - if len(elemVals) > types.MaxComboLength { - c.Respond(sevcord.NewMessage(fmt.Sprintf("You can only combine up to %d elements! "+types.RedCircle, types.MaxComboLength))) + var comboLimit int + err := e.db.QueryRow("SELECT combolength FROM config WHERE guild=$1", c.Guild()).Scan(&comboLimit) + if err != nil { + comboLimit = types.DefaultMaxComboLength + } + if len(elemVals) > comboLimit { + c.Respond(sevcord.NewMessage(fmt.Sprintf("You can only combine up to %d elements! "+types.RedCircle, comboLimit))) return } if len(elemVals) < 2 { @@ -52,7 +55,7 @@ func (e *Elements) Combine(c sevcord.Ctx, elemVals []string) { // Get status of everything (exists, whether you have it, etc.) var res []comboRes - err := e.db.Select(&res, `SELECT id, name, id=ANY(SELECT UNNEST(inv) FROM inventories WHERE guild=$1 AND "user"=$2) cont FROM elements WHERE guild=$1 AND LOWER(name)=ANY($3)`, c.Guild(), c.Author().User.ID, pq.Array(lowered)) + err = e.db.Select(&res, `SELECT id, name, id=ANY(SELECT UNNEST(inv) FROM inventories WHERE guild=$1 AND "user"=$2) cont FROM elements WHERE guild=$1 AND LOWER(name)=ANY($3)`, c.Guild(), c.Author().User.ID, pq.Array(lowered)) if err != nil { e.base.Error(c, err) return @@ -66,7 +69,7 @@ func (e *Elements) Combine(c sevcord.Ctx, elemVals []string) { dontExist := make([]string, 0) for _, v := range elemVals { _, exists := exist[strings.ToLower(v)] - if !exists && !slices.Contains(dontExist, "**"+v+"**") { + if !exists { dontExist = append(dontExist, "**"+v+"**") } } diff --git a/eod/init.go b/eod/init.go index ff3aec2a..4f83ddec 100644 --- a/eod/init.go +++ b/eod/init.go @@ -262,7 +262,7 @@ func (b *Bot) Init() { sevcord.NewOption("query", "A query to select the elements in the idea to be made from!", sevcord.OptionKindString, false). AutoComplete(b.queries.Autocomplete), sevcord.NewOption("count", "The number of elements to include in the idea!", sevcord.OptionKindInt, false). - MinMax(2, types.MaxComboLength), + MinMax(2, types.DefaultMaxComboLength), )) b.s.AddButtonHandler("idea", b.elements.IdeaHandler) b.s.RegisterSlashCommand(sevcord.NewSlashCommand("uncheese", "Delete the lowest tree size combo for elements!", b.elements.Uncheese, sevcord.NewOption("query", "A query to select the elements from!", sevcord.OptionKindString, false). diff --git a/eod/msgs.go b/eod/msgs.go index ae738fb1..64e8fd7e 100644 --- a/eod/msgs.go +++ b/eod/msgs.go @@ -2,7 +2,6 @@ package eod import ( "fmt" - "slices" "strconv" "strings" @@ -14,32 +13,16 @@ var seps = []string{ "\n", "+", ",", + "plus", } -func makeListResp(start, join, end string, vals []string) string { - if len(vals) == 2 { - return fmt.Sprintf("%s %s %s %s%s %s", start, vals[0], join, vals[1], end, types.RedCircle) - } else if len(vals) > 2 { - return fmt.Sprintf("%s %s, %s %s%s %s", start, strings.Join(vals[:len(vals)-1], ", "), join, vals[len(vals)-1], end, types.RedCircle) - } - return "" -} -func (b *Bot) getElementId(c sevcord.Ctx, val string, showerr bool) (int64, bool) { +func (b *Bot) getElementId(c sevcord.Ctx, val string) (int64, bool) { var id int64 - var err error - id, err = strconv.ParseInt(strings.Trim(strings.TrimSpace(val), "#"), 10, 64) - if err == nil { - err = b.db.QueryRow("SELECT id FROM elements WHERE id=$1 AND guild=$2", strings.ToLower(strings.TrimLeft(strings.TrimSpace(val), "#")), c.Guild()).Scan(&id) - } else { - err = b.db.QueryRow("SELECT id FROM elements WHERE LOWER(name)=$1 AND guild=$2", strings.ToLower(strings.TrimSpace(val)), c.Guild()).Scan(&id) - } - if err != nil && showerr { - b.base.Error(c, err, "Element **"+val+"** doesn't exist! "+types.RedCircle) - return 0, false - } else if err != nil && !showerr { + err := b.db.QueryRow("SELECT id FROM elements WHERE LOWER(name)=$1 AND guild=$2", strings.ToLower(strings.TrimSpace(val)), c.Guild()).Scan(&id) + if err != nil { + b.base.Error(c, err, "Element **"+val+"** doesn't exist!") return 0, false } - return id, true } @@ -57,32 +40,18 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { } val := any(nil) if content != "" { - v, ok := b.getElementId(c, content, true) + v, ok := b.getElementId(c, content) if !ok { return } val = any(v) } b.elements.Hint(c, []any{val, nil}) - case "hq", "hintquery": - if !b.base.CheckCtx(c, "hint") { - return - } - b.elements.Hint(c, []any{nil, content}) - case "ic", "ci", "infocategory", "infocat", "catinfo", "categoryinfo": - b.categories.Info(c, []any{content}) - case "iq", "qi", "infoquery", "queryinfo": - b.queries.Info(c, []any{content}) case "cat", "c": if !b.base.CheckCtx(c, "cat") { return } - if content != "" { - b.pages.Cat(c, []any{any(content), nil}) - } else { - b.pages.CatList(c, []any{"name"}) - } - + b.pages.Cat(c, []any{any(content), nil}) case "inv": if !b.base.CheckCtx(c, "inv") { return @@ -114,43 +83,12 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { if !b.base.CheckCtx(c, "lb") { return } - parts := strings.Split(content, " ") - Lbsort := "" - switch strings.ToLower(parts[0]) { - case "made": - Lbsort = "made" - case "imaged", "img": - Lbsort = "img" - case "votes": - Lbsort = "voted" - case "signed": - Lbsort = "signed" - case "colored", "colour", "coloured", "color": - Lbsort = "color" - case "catsigned": - Lbsort = "catsigned" - case "catimg", "catimage": - Lbsort = "catimg" - case "catcolor": - Lbsort = "catcolor" - case "querysigned": - Lbsort = "querysigned" - case "queryimage", "queryimg": - Lbsort = "queryimg" - case "querycolor": - Lbsort = "querycolor" - case "found", "": - Lbsort = "found" - default: - Lbsort = "found" - } - b.pages.Lb(c, []any{Lbsort, nil, nil}) - + b.pages.Lb(c, []any{nil, nil, nil}) case "p", "products": if !b.base.CheckCtx(c, "products") { return } - id, ok := b.getElementId(c, content, true) + id, ok := b.getElementId(c, content) if !ok { return } @@ -160,12 +98,6 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { if !b.base.CheckCtx(c, "query") { return } - if content != "" { - b.pages.Query(c, []any{any(content), nil}) - } else { - b.pages.QueryList(c, []any{"name"}) - } - case "ac", "rc": if !b.base.CheckCtx(c, "cat") { return @@ -175,38 +107,28 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { c.Respond(sevcord.NewMessage("Invalid format! " + types.RedCircle)) return } - dontExist := make([]string, 0) els := make([]int, 0) added := false for sep := range seps { if strings.Contains(parts[1], seps[sep]) { vals := strings.Split(parts[1], seps[sep]) for _, val := range vals { - id, ok := b.getElementId(c, val, false) - if !ok && !slices.Contains(dontExist, "**"+val+"**") { - dontExist = append(dontExist, "**"+val+"**") + id, ok := b.getElementId(c, val) + if !ok { + return } els = append(els, int(id)) } + added = true break } } - if len(dontExist) == 0 { - - } else if len(dontExist) == 1 { - c.Respond(sevcord.NewMessage("Element **" + dontExist[0] + "** doesn't exist!")) - return - } else { - c.Respond(sevcord.NewMessage(makeListResp("Elements", "and", " don't exist!", dontExist))) - return - } if !added { - id, ok := b.getElementId(c, parts[1], true) + id, ok := b.getElementId(c, parts[1]) if !ok { return } els = append(els, int(id)) - added = true } if len(els) == 0 { c.Respond(sevcord.NewMessage("Invalid format! " + types.RedCircle)) @@ -228,7 +150,7 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { return } // check for signing element/category/query - switch strings.ToLower(strings.TrimSpace(parts[0])) { + switch strings.TrimSpace(parts[0]) { case "e", "element": b.elements.MsgSignCmd(c, strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])) @@ -252,9 +174,9 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { return } // check for coloring element/category/query - switch strings.ToLower(strings.TrimSpace(parts[0])) { + switch strings.TrimSpace(parts[0]) { case "e", "element": - id, ok := b.getElementId(c, parts[1], true) + id, ok := b.getElementId(c, parts[1]) if !ok { return } @@ -310,7 +232,7 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { } // Run command - switch strings.ToLower(parts[0]) { + switch parts[0] { case "e", "element": // Get ID var id int @@ -418,8 +340,13 @@ func (b *Bot) messageHandler(c sevcord.Ctx, content string) { c.Respond(sevcord.NewMessage("Invalid number of repeats! " + types.RedCircle)) return } - if cnt > types.MaxComboLength { - c.Respond(sevcord.NewMessage(fmt.Sprintf("You can only combine up to %d elements! "+types.RedCircle, types.MaxComboLength))) + var comboLength int + err = b.db.QueryRow("SELECT combolength FROM config WHERE guild=$1", c.Guild()).Scan(&comboLength) + if err != nil { + comboLength = types.DefaultMaxComboLength + } + if cnt > comboLength { + c.Respond(sevcord.NewMessage(fmt.Sprintf("You can only combine up to %d elements! "+types.RedCircle, comboLength))) return } if cnt < 2 { @@ -431,6 +358,7 @@ func (b *Bot) messageHandler(c sevcord.Ctx, content string) { for i := 0; i < cnt; i++ { inps = append(inps, strings.TrimSpace(parts[1])) } + b.elements.Combine(c, inps) return } else { diff --git a/eod/pages/categories.go b/eod/pages/categories.go index 21c030e1..c7c1a367 100644 --- a/eod/pages/categories.go +++ b/eod/pages/categories.go @@ -137,24 +137,12 @@ func (p *Pages) CatHandler(c sevcord.Ctx, params string) { fmt.Fprintf(desc, "%s %s\n", v.Name, progress[1]) } } - - //get color and image - var color int - var img string - err = p.db.QueryRow("SELECT color, image FROM categories WHERE name=$1 AND guild=$2", parts[len(parts)-1], c.Guild()).Scan(&color, &img) - - if err != nil || color == 0 { - color = 10181046 //Purple - } // Create embed := sevcord.NewEmbed(). Title(fmt.Sprintf("%s (%s, %s%%)", parts[4], humanize.Comma(int64(cnt)), humanize.FormatFloat("", float64(common)/float64(cnt)*100))). Description(desc.String()). Footer(fmt.Sprintf("Page %d/%d", page+1, pagecnt), ""). - Color(color) - if err == nil { - embed = embed.Thumbnail(img) - } + Color(10181046) //Purple c.Respond(sevcord.NewMessage(""). AddEmbed(embed). AddComponentRow(PageSwitchBtns("cat", fmt.Sprintf("%s|%s|%d|%s", parts[1], parts[2], page, parts[4]))...), diff --git a/eod/pages/queries.go b/eod/pages/queries.go index edd20446..e745e835 100644 --- a/eod/pages/queries.go +++ b/eod/pages/queries.go @@ -150,23 +150,12 @@ func (p *Pages) QueryHandler(c sevcord.Ctx, params string) { fmt.Fprintf(desc, "%s %s\n", v.Name, progress[1]) } } - var img string - var color int - err = p.db.QueryRow("SELECT color,image FROM queries WHERE name=$1 AND guild =$2", parts[len(parts)-1], c.Guild()).Scan(&color, &img) - - if err != nil || color == 0 { - color = 10181046 // Purple - } - // Create embed := sevcord.NewEmbed(). Title(fmt.Sprintf("%s (%s, %s%%)", parts[4], humanize.Comma(int64(cnt)), humanize.FormatFloat("", float64(common)/float64(cnt)*100))). Description(desc.String()). Footer(fmt.Sprintf("Page %d/%d", page+1, pagecnt), ""). - Color(color) - if err == nil { - embed = embed.Thumbnail(img) - } + Color(10181046) //Purple c.Respond(sevcord.NewMessage(""). AddEmbed(embed). AddComponentRow(PageSwitchBtns("query", fmt.Sprintf("%s|%s|%d|%s", parts[1], parts[2], page, parts[4]))...), diff --git a/eod/types/types.go b/eod/types/types.go index 3c3737a4..22f527ba 100644 --- a/eod/types/types.go +++ b/eod/types/types.go @@ -248,4 +248,4 @@ type CombCache struct { // Consts const RedCircle = "🔴" -const MaxComboLength = 21 +const DefaultMaxComboLength = 21 From a8ca98b0633252fc84a04119126e558aded5b45d Mon Sep 17 00:00:00 2001 From: kylepokorski <68132697+kylepokorski@users.noreply.github.com> Date: Mon, 17 Feb 2025 16:21:56 -0800 Subject: [PATCH 10/10] Adding more caching Adding more caching (caching the config settings) This is not fully used yet --- eod/base/config.go | 17 ++++++++++++++++ eod/base/mem.go | 47 +++++++++++++++++++++++++++++++++++++++++++ eod/base/util.go | 25 ++++++++++++++++++----- eod/elements/combo.go | 10 ++++++++- eod/msgs.go | 7 ++++++- eod/types/types.go | 2 ++ 6 files changed, 101 insertions(+), 7 deletions(-) diff --git a/eod/base/config.go b/eod/base/config.go index 85066b25..0af09702 100644 --- a/eod/base/config.go +++ b/eod/base/config.go @@ -5,6 +5,7 @@ import ( "log" "strings" + "github.com/Nv7-Github/Nv7Haven/eod/types" "github.com/Nv7-Github/sevcord/v2" "github.com/bwmarrin/discordgo" "github.com/lib/pq" @@ -32,6 +33,10 @@ func (b *Base) configChannel(c sevcord.Ctx, field string, value any, message str return } + var config types.Config + b.db.Get(&config, "SELECT * FROM config WHERE guild=$1", c.Guild()) + b.SaveConfigCache(c, config) + c.Respond(sevcord.NewMessage(fmt.Sprintf("Successfully updated %s!", message))) b.configNewsMessage(c, fmt.Sprintf("Changed Config - **%s**", strings.Title(message))) } @@ -67,6 +72,9 @@ func (b *Base) ConfigPlayChannels(c sevcord.Ctx, opts []any) { ChannelMenuFilter(discordgo.ChannelTypeGuildText). SetRange(0, 25), )) + var config types.Config + b.db.Get(&config, "SELECT * FROM config WHERE guild=$1", c.Guild()) + b.SaveConfigCache(c, config) b.configNewsMessage(c, "Changed Config - **Play Channels**") } func (b *Base) ConfigVoteIcons(c sevcord.Ctx, opts []any) { @@ -77,6 +85,9 @@ func (b *Base) ConfigVoteIcons(c sevcord.Ctx, opts []any) { b.Error(c, err) return } + var config types.Config + b.db.Get(&config, "SELECT * FROM config WHERE guild=$1", c.Guild()) + b.SaveConfigCache(c, config) c.Respond(sevcord.NewMessage("Successfully updated voting emojis!")) b.configNewsMessage(c, "Change Config - **Vote Icons**") } @@ -87,6 +98,9 @@ func (b *Base) ConfigProgIcons(c sevcord.Ctx, opts []any) { b.Error(c, err) return } + var config types.Config + b.db.Get(&config, "SELECT * FROM config WHERE guild=$1", c.Guild()) + b.SaveConfigCache(c, config) c.Respond(sevcord.NewMessage("Successfully updated progress emojis!")) b.configNewsMessage(c, "Change Config - **Progress Icons**") @@ -98,6 +112,9 @@ func (b *Base) ConfigComboLength(c sevcord.Ctx, opts []any) { b.Error(c, err) return } + var config types.Config + b.db.Get(&config, "SELECT * FROM config WHERE guild=$1", c.Guild()) + b.SaveConfigCache(c, config) c.Respond(sevcord.NewMessage("Successfully updated maximum combination limit!")) b.configNewsMessage(c, "Change Config - **Combination Limit**") } diff --git a/eod/base/mem.go b/eod/base/mem.go index 51b7d42c..62f9d70e 100644 --- a/eod/base/mem.go +++ b/eod/base/mem.go @@ -7,6 +7,26 @@ import ( "github.com/Nv7-Github/sevcord/v2" ) +func (b *Base) getMemGuild(guild string) *types.ServerMem { + b.lock.RLock() + v, exists := b.mem[guild] + b.lock.RUnlock() + if exists { + return v + } + + v = &types.ServerMem{ + CombCache: make(map[string]types.CombCache), + CommandStatsTODO: make(map[string]int), + ConfigCache: make(map[string]types.Config), + } + + b.lock.Lock() + b.mem[guild] = v + b.lock.Unlock() + + return v +} func (b *Base) getMem(c sevcord.Ctx) *types.ServerMem { b.lock.RLock() v, exists := b.mem[c.Guild()] @@ -18,6 +38,7 @@ func (b *Base) getMem(c sevcord.Ctx) *types.ServerMem { v = &types.ServerMem{ CombCache: make(map[string]types.CombCache), CommandStatsTODO: make(map[string]int), + ConfigCache: make(map[string]types.Config), } b.lock.Lock() @@ -26,6 +47,32 @@ func (b *Base) getMem(c sevcord.Ctx) *types.ServerMem { return v } +func (b *Base) SaveConfigCacheGuild(guild string, config types.Config) { + + mem := b.getMemGuild(guild) + mem.Lock() + mem.ConfigCache[guild] = config + mem.Unlock() +} +func (b *Base) SaveConfigCache(c sevcord.Ctx, config types.Config) { + + mem := b.getMem(c) + mem.Lock() + mem.ConfigCache[c.Guild()] = config + mem.Unlock() +} + +func (b *Base) GetConfigCache(c sevcord.Ctx) (types.Config, types.Resp) { + + mem := b.getMem(c) + mem.RLock() + v, exists := mem.ConfigCache[c.Guild()] + mem.RUnlock() + if exists { + return v, types.Ok() + } + return types.Config{}, types.Fail("Invalid config") +} func (b *Base) SaveCombCache(c sevcord.Ctx, comb types.CombCache) { mem := b.getMem(c) diff --git a/eod/base/util.go b/eod/base/util.go index 75c4aab4..1d775d5d 100644 --- a/eod/base/util.go +++ b/eod/base/util.go @@ -3,6 +3,7 @@ package base import ( "database/sql" "log" + "slices" "github.com/Nv7-Github/Nv7Haven/eod/types" "github.com/Nv7-Github/sevcord/v2" @@ -29,13 +30,27 @@ func (b *Base) Error(ctx sevcord.Ctx, err error, config ...string) { func (b *Base) IsPlayChannel(c sevcord.Ctx) bool { // Check if play channel - var cnt bool - err := b.db.QueryRow(`SELECT $1=ANY(play) FROM config WHERE guild=$2`, c.Channel(), c.Guild()).Scan(&cnt) - if err != nil { - log.Println("Play channel error", err) + config, resp := b.GetConfigCache(c) + + if !resp.Ok { + err := b.db.Get(&config, `SELECT * FROM config WHERE guild=$1`, c.Guild()) + if err != nil { + log.Println("Config error", err) + return false + } + + } + var playchannels []string + playchannels = append(playchannels, config.PlayChannels...) + if len(playchannels) == 0 { + log.Println("Play channel error") return false } - return cnt + if slices.Contains(playchannels, c.Channel()) { + return true + } + return false + } func (b *Base) PageLength(ctx sevcord.Ctx) int { diff --git a/eod/elements/combo.go b/eod/elements/combo.go index 8b1e1170..bbd734d6 100644 --- a/eod/elements/combo.go +++ b/eod/elements/combo.go @@ -32,11 +32,19 @@ type comboRes struct { func (e *Elements) Combine(c sevcord.Ctx, elemVals []string) { c.Acknowledge() e.base.IncrementCommandStat(c, "combine") + var comboLimit int - err := e.db.QueryRow("SELECT combolength FROM config WHERE guild=$1", c.Guild()).Scan(&comboLimit) + var err error + config, rsp := e.base.GetConfigCache(c) + if !rsp.Ok { + err = e.db.Select(&config, "SELECT * FROM config WHERE guild=$1", c.Guild()) + } if err != nil { comboLimit = types.DefaultMaxComboLength + } else { + comboLimit = config.ComboLength } + if len(elemVals) > comboLimit { c.Respond(sevcord.NewMessage(fmt.Sprintf("You can only combine up to %d elements! "+types.RedCircle, comboLimit))) return diff --git a/eod/msgs.go b/eod/msgs.go index 64e8fd7e..97ef3cbb 100644 --- a/eod/msgs.go +++ b/eod/msgs.go @@ -341,9 +341,14 @@ func (b *Bot) messageHandler(c sevcord.Ctx, content string) { return } var comboLength int - err = b.db.QueryRow("SELECT combolength FROM config WHERE guild=$1", c.Guild()).Scan(&comboLength) + config, rsp := b.base.GetConfigCache(c) + if !rsp.Ok { + err = b.db.Select(&config, "SELECT * FROM config WHERE guild=$1", c.Guild()) + } if err != nil { comboLength = types.DefaultMaxComboLength + } else { + comboLength = config.ComboLength } if cnt > comboLength { c.Respond(sevcord.NewMessage(fmt.Sprintf("You can only combine up to %d elements! "+types.RedCircle, comboLength))) diff --git a/eod/types/types.go b/eod/types/types.go index 22f527ba..63dcdd67 100644 --- a/eod/types/types.go +++ b/eod/types/types.go @@ -76,6 +76,7 @@ type Config struct { PlayChannels pq.StringArray `db:"play"` VoteIcons pq.StringArray `db:"voteicons"` ProgIcons pq.StringArray `db:"progicons"` + ComboLength int `db:"combolength"` } type ServerMem struct { @@ -84,6 +85,7 @@ type ServerMem struct { CommandStatsTODO map[string]int CommandStatsTODOCnt int + ConfigCache map[string]Config //map[guildID]Config } // Polls