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..1fa30073 100644 --- a/eod/base/base.go +++ b/eod/base/base.go @@ -32,6 +32,9 @@ 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)), + 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 04f153dc..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,9 +72,52 @@ 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) { + 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 + } + 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**") +} +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 + } + 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**") +} +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 + } + 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**") +} func (b *Base) ConfigPlayChannelsHandler(c sevcord.Ctx, params string, opts []string) { c.Acknowledge() 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/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/elements/combo.go b/eod/elements/combo.go index 0f2b620c..bbd734d6 100644 --- a/eod/elements/combo.go +++ b/eod/elements/combo.go @@ -33,8 +33,20 @@ 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 + 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 } if len(elemVals) < 2 { @@ -51,7 +63,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 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/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 92414347..97ef3cbb 100644 --- a/eod/msgs.go +++ b/eod/msgs.go @@ -47,13 +47,11 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { val = any(v) } b.elements.Hint(c, []any{val, nil}) - - case "cat": + case "cat", "c": if !b.base.CheckCtx(c, "cat") { return } b.pages.Cat(c, []any{any(content), nil}) - case "inv": if !b.base.CheckCtx(c, "inv") { return @@ -86,7 +84,6 @@ func (b *Bot) textCommandHandler(c sevcord.Ctx, name string, content string) { return } b.pages.Lb(c, []any{nil, nil, nil}) - case "p", "products": if !b.base.CheckCtx(c, "products") { return @@ -101,8 +98,6 @@ 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}) - case "ac", "rc": if !b.base.CheckCtx(c, "cat") { return @@ -149,18 +144,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 } - b.elements.MsgSignCmd(c, strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])) + // check for signing element/category/query + switch 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.MsgSignCmd(c, strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])) + case "q", "query": + 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)) + } + 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 + } + // check for coloring element/category/query + switch strings.TrimSpace(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") { @@ -300,8 +340,18 @@ 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 + 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))) return } if cnt < 2 { @@ -313,6 +363,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 c3215d55..c7c1a367 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,26 @@ 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]) } } - // 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(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/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..e745e835 100644 --- a/eod/pages/queries.go +++ b/eod/pages/queries.go @@ -136,22 +136,26 @@ 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]) } } - // 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(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/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/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() diff --git a/eod/types/types.go b/eod/types/types.go index b8b72f6a..63dcdd67 100644 --- a/eod/types/types.go +++ b/eod/types/types.go @@ -74,6 +74,9 @@ 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"` + ComboLength int `db:"combolength"` } type ServerMem struct { @@ -82,6 +85,7 @@ type ServerMem struct { CommandStatsTODO map[string]int CommandStatsTODOCnt int + ConfigCache map[string]Config //map[guildID]Config } // Polls @@ -246,6 +250,4 @@ type CombCache struct { // Consts const RedCircle = "🔴" -const Check = "<:eodCheck:765333533362225222>" -const NoCheck = "❌" -const MaxComboLength = 21 +const DefaultMaxComboLength = 21