feat: leveling system
This commit is contained in:
@@ -14,6 +14,7 @@ var AllCommands = []*discordgo.ApplicationCommand{
|
|||||||
cmdlevel.LevelConfigCommand,
|
cmdlevel.LevelConfigCommand,
|
||||||
cmdlevel.RankCommand,
|
cmdlevel.RankCommand,
|
||||||
cmdlevel.LeaderboardCommand,
|
cmdlevel.LeaderboardCommand,
|
||||||
|
cmdlevel.RewardsCommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
var handlers = map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){
|
var handlers = map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){
|
||||||
@@ -22,6 +23,7 @@ var handlers = map[string]func(s *discordgo.Session, i *discordgo.InteractionCre
|
|||||||
"slvl": cmdlevel.HandleLevelConfig,
|
"slvl": cmdlevel.HandleLevelConfig,
|
||||||
"rank": cmdlevel.HandleRank,
|
"rank": cmdlevel.HandleRank,
|
||||||
"leaderboard": cmdlevel.HandleLeaderboard,
|
"leaderboard": cmdlevel.HandleLeaderboard,
|
||||||
|
"rewards": cmdlevel.HandleRewards,
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleInteraction(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
func HandleInteraction(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package level
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"velox-bot/internal/db/services"
|
||||||
|
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func respondEphemeral(s *discordgo.Session, i *discordgo.InteractionCreate, msg string) {
|
||||||
|
_ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||||
|
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||||
|
Data: &discordgo.InteractionResponseData{
|
||||||
|
Content: msg,
|
||||||
|
Flags: discordgo.MessageFlagsEphemeral,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireGuild(s *discordgo.Session, i *discordgo.InteractionCreate) bool {
|
||||||
|
if i.GuildID == "" {
|
||||||
|
respondEphemeral(s, i, "This command can only be used in a server.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireManageGuild(s *discordgo.Session, i *discordgo.InteractionCreate) bool {
|
||||||
|
if i.Member == nil || (i.Member.Permissions&discordgo.PermissionManageGuild) == 0 {
|
||||||
|
respondEphemeral(s, i, "You don't have permission to manage leveling settings.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireLevelServices(s *discordgo.Session, i *discordgo.InteractionCreate) bool {
|
||||||
|
if services.Global == nil || services.Global.Level == nil || services.Global.LevelSettings == nil {
|
||||||
|
respondEphemeral(s, i, "Leveling service is not available.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireLevelSettingsService(s *discordgo.Session, i *discordgo.InteractionCreate) bool {
|
||||||
|
if services.Global == nil || services.Global.LevelSettings == nil {
|
||||||
|
respondEphemeral(s, i, "Leveling service is not available.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGuildID(s *discordgo.Session, i *discordgo.InteractionCreate) (int64, bool) {
|
||||||
|
guildID, err := strconv.ParseInt(i.GuildID, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
respondEphemeral(s, i, "Invalid guild ID.")
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return guildID, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireLevelSystemEnabled(s *discordgo.Session, i *discordgo.InteractionCreate) bool {
|
||||||
|
if !requireLevelSettingsService(s, i) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
guildID, ok := parseGuildID(s, i)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
enabled, err := services.Global.LevelSettings.IsLevelSystemEnabled(context.Background(), guildID)
|
||||||
|
if err != nil {
|
||||||
|
respondEphemeral(s, i, "Failed to load leveling settings.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !enabled {
|
||||||
|
respondEphemeral(s, i, "Leveling system is disabled on this server. Use /slvl toggle to enable it.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func subcommandOptionMap(i *discordgo.InteractionCreate) map[string]*discordgo.ApplicationCommandInteractionDataOption {
|
||||||
|
data := i.ApplicationCommandData()
|
||||||
|
if len(data.Options) == 0 {
|
||||||
|
return map[string]*discordgo.ApplicationCommandInteractionDataOption{}
|
||||||
|
}
|
||||||
|
opts := data.Options[0].Options
|
||||||
|
m := make(map[string]*discordgo.ApplicationCommandInteractionDataOption, len(opts))
|
||||||
|
for _, opt := range opts {
|
||||||
|
m[opt.Name] = opt
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
@@ -30,15 +30,18 @@ var LeaderboardCommand = &discordgo.ApplicationCommand{
|
|||||||
Description: "Top 10 levels in this server",
|
Description: "Top 10 levels in this server",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var RewardsCommand = &discordgo.ApplicationCommand{
|
||||||
|
Name: "rewards",
|
||||||
|
Description: "View level rewards in this server",
|
||||||
|
}
|
||||||
|
|
||||||
func HandleRank(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
func HandleRank(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||||
if services.Global == nil || services.Global.Level == nil {
|
if !requireLevelServices(s, i) {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
return
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
}
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Leveling service is not available.",
|
if i.GuildID != "" && !requireLevelSystemEnabled(s, i) {
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
respondEphemeral(s, i, "Leveling system is disabled on this server.")
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,18 +61,20 @@ func HandleRank(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guildID, err := strconv.ParseInt(i.GuildID, 10, 64)
|
guildID, ok := parseGuildID(s, i)
|
||||||
if err != nil {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userID, err := strconv.ParseInt(target.ID, 10, 64)
|
userID, err := strconv.ParseInt(target.ID, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
respondEphemeral(s, i, "Invalid user ID.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
lvl, err := services.Global.Level.GetLevel(ctx, guildID, userID)
|
lvl, err := services.Global.Level.GetLevel(ctx, guildID, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
respondEphemeral(s, i, "Failed to load level.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,13 +89,7 @@ func HandleRank(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|||||||
Avatar: avatarURL,
|
Avatar: avatarURL,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Failed to render rank card.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Failed to render rank card.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,61 +107,31 @@ func HandleRank(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleLeaderboard(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
func HandleLeaderboard(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||||
if i.GuildID == "" {
|
if !requireGuild(s, i) {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "This command can only be used in a server.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if services.Global == nil || services.Global.Level == nil {
|
if !requireLevelServices(s, i) {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Leveling service is not available.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guildID, err := strconv.ParseInt(i.GuildID, 10, 64)
|
guildID, ok := parseGuildID(s, i)
|
||||||
if err != nil {
|
if !ok {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Invalid guild ID.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
if !requireLevelSystemEnabled(s, i) {
|
||||||
|
return
|
||||||
|
}
|
||||||
top, err := services.Global.Level.TopLevels(ctx, guildID, 10)
|
top, err := services.Global.Level.TopLevels(ctx, guildID, 10)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Failed to load leaderboard.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Failed to load leaderboard.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(top) == 0 {
|
if len(top) == 0 {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "No leaderboard data yet.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "No leaderboard data yet.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,3 +163,56 @@ func HandleLeaderboard(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HandleRewards(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||||
|
if !requireGuild(s, i) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !requireLevelSettingsService(s, i) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guildID, ok := parseGuildID(s, i)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
if !requireLevelSystemEnabled(s, i) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rewards, err := services.Global.LevelSettings.ListRoleRewards(ctx, guildID, 25)
|
||||||
|
if err != nil {
|
||||||
|
respondEphemeral(s, i, "Failed to load rewards.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rewards) == 0 {
|
||||||
|
respondEphemeral(s, i, "No rewards configured yet.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fields := make([]*discordgo.MessageEmbedField, 0, len(rewards))
|
||||||
|
for _, r := range rewards {
|
||||||
|
fields = append(fields, &discordgo.MessageEmbedField{
|
||||||
|
Name: fmt.Sprintf("Level %d", r.Level),
|
||||||
|
Value: fmt.Sprintf("<@&%d>", r.RoleID),
|
||||||
|
Inline: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
embed := &discordgo.MessageEmbed{
|
||||||
|
Title: "Level Rewards",
|
||||||
|
Description: "Roles granted when you reach a level.",
|
||||||
|
Fields: fields,
|
||||||
|
Color: 0xF59E0B,
|
||||||
|
}
|
||||||
|
|
||||||
|
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||||
|
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||||
|
Data: &discordgo.InteractionResponseData{
|
||||||
|
Embeds: []*discordgo.MessageEmbed{embed},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -102,63 +102,29 @@ func HandleLevelConfig(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|||||||
case "set-reward":
|
case "set-reward":
|
||||||
HandleLevelSetReward(s, i)
|
HandleLevelSetReward(s, i)
|
||||||
default:
|
default:
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Invalid subcommand.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Invalid subcommand.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleLevelToggle(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
func HandleLevelToggle(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||||
// Basic permission check: require Manage Guild permission
|
if !requireManageGuild(s, i) {
|
||||||
if i.Member == nil || (i.Member.Permissions&discordgo.PermissionManageGuild) == 0 {
|
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "You don't have permission to manage leveling settings.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if services.Global == nil || services.Global.LevelSettings == nil {
|
if !requireLevelSettingsService(s, i) {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Leveling service is not available.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
guildID, err := strconv.ParseInt(i.GuildID, 10, 64)
|
guildID, ok := parseGuildID(s, i)
|
||||||
if err != nil {
|
if !ok {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Invalid guild ID.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
enabled, err := services.Global.LevelSettings.ToggleLevelSystem(ctx, guildID)
|
enabled, err := services.Global.LevelSettings.ToggleLevelSystem(ctx, guildID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Failed to toggle leveling system.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Failed to toggle leveling system.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,294 +133,131 @@ func HandleLevelToggle(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|||||||
status = "enabled"
|
status = "enabled"
|
||||||
}
|
}
|
||||||
|
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Leveling system "+status+" for this server.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Leveling system " + status + " for this server.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleLevelSet(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
func HandleLevelSet(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||||
// Basic permission check: require Manage Guild permission
|
if !requireManageGuild(s, i) || !requireLevelSystemEnabled(s, i) {
|
||||||
if i.Member == nil || (i.Member.Permissions&discordgo.PermissionManageGuild) == 0 {
|
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "You don't have permission to manage leveling settings.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the leveling service is available
|
|
||||||
if services.Global == nil || services.Global.Level == nil {
|
if services.Global == nil || services.Global.Level == nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Leveling service is not available.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Leveling service is not available.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data := i.ApplicationCommandData()
|
optMap := subcommandOptionMap(i)
|
||||||
optMap := make(map[string]*discordgo.ApplicationCommandInteractionDataOption, len(data.Options[0].Options))
|
|
||||||
for _, opt := range data.Options[0].Options {
|
|
||||||
optMap[opt.Name] = opt
|
|
||||||
}
|
|
||||||
|
|
||||||
userOpt, ok := optMap["user"]
|
userOpt, ok := optMap["user"]
|
||||||
if !ok {
|
if !ok {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Missing user option.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Missing user option.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
levelOpt, ok := optMap["level"]
|
levelOpt, ok := optMap["level"]
|
||||||
if !ok {
|
if !ok {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Missing level option.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Missing level option.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
targetUser := userOpt.UserValue(s)
|
targetUser := userOpt.UserValue(s)
|
||||||
if targetUser == nil {
|
if targetUser == nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Invalid user.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Invalid user.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent setting bots (including ourselves)
|
// prevent setting bots (including ourselves)
|
||||||
if targetUser.Bot {
|
if targetUser.Bot {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "You can't set a bot's level.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "You can't set a bot's level.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
newLevel := int(levelOpt.IntValue())
|
newLevel := int(levelOpt.IntValue())
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
guildID, err := strconv.ParseInt(i.GuildID, 10, 64)
|
guildID, ok := parseGuildID(s, i)
|
||||||
if err != nil {
|
if !ok {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Invalid guild ID.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userID, err := strconv.ParseInt(targetUser.ID, 10, 64)
|
userID, err := strconv.ParseInt(targetUser.ID, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Invalid user ID.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Invalid user ID.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = services.Global.Level.SetLevel(ctx, guildID, userID, newLevel)
|
err = services.Global.Level.SetLevel(ctx, guildID, userID, newLevel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Failed to set level.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Failed to set level.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Level set to "+strconv.Itoa(newLevel)+" for "+targetUser.Mention()+".")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Level set to " + strconv.Itoa(newLevel) + " for " + targetUser.Mention() + ".",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleLevelSetChannel(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
func HandleLevelSetChannel(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||||
// Basic permission check: require Manage Guild permission
|
if !requireManageGuild(s, i) || !requireLevelSystemEnabled(s, i) {
|
||||||
if i.Member == nil || (i.Member.Permissions&discordgo.PermissionManageGuild) == 0 {
|
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "You don't have permission to manage leveling settings.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the leveling service is available
|
if !requireLevelSettingsService(s, i) {
|
||||||
if services.Global == nil || services.Global.Level == nil {
|
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Leveling service is not available.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guildID, err := strconv.ParseInt(i.GuildID, 10, 64)
|
guildID, ok := parseGuildID(s, i)
|
||||||
if err != nil {
|
if !ok {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Invalid guild ID.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data := i.ApplicationCommandData()
|
optMap := subcommandOptionMap(i)
|
||||||
optMap := make(map[string]*discordgo.ApplicationCommandInteractionDataOption, len(data.Options[0].Options))
|
|
||||||
for _, opt := range data.Options[0].Options {
|
|
||||||
optMap[opt.Name] = opt
|
|
||||||
}
|
|
||||||
|
|
||||||
channelOpt, ok := optMap["channel"]
|
channelOpt, ok := optMap["channel"]
|
||||||
if !ok {
|
if !ok {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Missing channel option.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Missing channel option.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
channelID := channelOpt.ChannelValue(s)
|
channelID := channelOpt.ChannelValue(s)
|
||||||
if channelID == nil {
|
if channelID == nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Invalid channel.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Invalid channel.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
channelIDInt, err := strconv.ParseInt(channelID.ID, 10, 64)
|
channelIDInt, err := strconv.ParseInt(channelID.ID, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Invalid channel ID.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Invalid channel ID.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = services.Global.LevelSettings.SetLevelUpChannel(ctx, guildID, channelIDInt)
|
err = services.Global.LevelSettings.SetLevelUpChannel(ctx, guildID, channelIDInt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Failed to set level up channel.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
return
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Failed to set level up channel.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Level up channel set to "+channelID.Mention()+".")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Level up channel set to " + channelID.Mention() + ".",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleLevelSetMessage(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
func HandleLevelSetMessage(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||||
// Basic permission check: require Manage Guild permission
|
if !requireManageGuild(s, i) || !requireLevelSystemEnabled(s, i) {
|
||||||
if i.Member == nil || (i.Member.Permissions&discordgo.PermissionManageGuild) == 0 {
|
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "You don't have permission to manage leveling settings.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the leveling service is available
|
if !requireLevelSettingsService(s, i) {
|
||||||
if services.Global == nil || services.Global.Level == nil {
|
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Leveling service is not available.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guildID, err := strconv.ParseInt(i.GuildID, 10, 64)
|
guildID, ok := parseGuildID(s, i)
|
||||||
if err != nil {
|
if !ok {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Invalid guild ID.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data := i.ApplicationCommandData()
|
optMap := subcommandOptionMap(i)
|
||||||
optMap := make(map[string]*discordgo.ApplicationCommandInteractionDataOption, len(data.Options[0].Options))
|
|
||||||
for _, opt := range data.Options[0].Options {
|
|
||||||
optMap[opt.Name] = opt
|
|
||||||
}
|
|
||||||
|
|
||||||
messageOpt, ok := optMap["message"]
|
messageOpt, ok := optMap["message"]
|
||||||
if !ok {
|
if !ok {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Missing message option.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Missing message option.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,134 +267,60 @@ func HandleLevelSetMessage(s *discordgo.Session, i *discordgo.InteractionCreate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
err = services.Global.LevelSettings.SetLevelUpMessage(ctx, guildID, message)
|
err := services.Global.LevelSettings.SetLevelUpMessage(ctx, guildID, message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Failed to set level up message.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
return
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Failed to set level up channel.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Level up message set.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Level up message set to " + message + ".",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleLevelSetReward(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
func HandleLevelSetReward(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||||
// Basic permission check: require Manage Guild permission
|
if !requireManageGuild(s, i) || !requireLevelSystemEnabled(s, i) {
|
||||||
if i.Member == nil || (i.Member.Permissions&discordgo.PermissionManageGuild) == 0 {
|
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "You don't have permission to manage leveling settings.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the leveling service is available
|
if !requireLevelSettingsService(s, i) {
|
||||||
if services.Global == nil || services.Global.LevelSettings == nil {
|
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Leveling service is not available.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guildID, err := strconv.ParseInt(i.GuildID, 10, 64)
|
guildID, ok := parseGuildID(s, i)
|
||||||
if err != nil {
|
if !ok {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Invalid guild ID.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data := i.ApplicationCommandData()
|
optMap := subcommandOptionMap(i)
|
||||||
optMap := make(map[string]*discordgo.ApplicationCommandInteractionDataOption, len(data.Options[0].Options))
|
|
||||||
for _, opt := range data.Options[0].Options {
|
|
||||||
optMap[opt.Name] = opt
|
|
||||||
}
|
|
||||||
|
|
||||||
levelOpt, ok := optMap["level"]
|
levelOpt, ok := optMap["level"]
|
||||||
if !ok {
|
if !ok {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Missing level option.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Missing level option.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
roleOpt, ok := optMap["role"]
|
roleOpt, ok := optMap["role"]
|
||||||
if !ok {
|
if !ok {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Missing role option.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Missing role option.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
level := int(levelOpt.IntValue())
|
level := int(levelOpt.IntValue())
|
||||||
role := roleOpt.RoleValue(s, i.GuildID)
|
role := roleOpt.RoleValue(s, i.GuildID)
|
||||||
if role == nil {
|
if role == nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Invalid role.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Invalid role.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
roleID, err := strconv.ParseInt(role.ID, 10, 64)
|
roleID, err := strconv.ParseInt(role.ID, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Invalid role ID.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Invalid role ID.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
if err := services.Global.LevelSettings.SetRoleRewardForLevel(ctx, guildID, level, roleID); err != nil {
|
if err := services.Global.LevelSettings.SetRoleRewardForLevel(ctx, guildID, level, roleID); err != nil {
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Failed to set reward.")
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Failed to set reward.",
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
respondEphemeral(s, i, "Reward set: level "+strconv.Itoa(level)+" -> "+role.Mention())
|
||||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
||||||
Data: &discordgo.InteractionResponseData{
|
|
||||||
Content: "Reward set: level " + strconv.Itoa(level) + " -> " + role.Mention(),
|
|
||||||
Flags: discordgo.MessageFlagsEphemeral,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,9 +56,9 @@ func (r *Repo) UpsertLevel(ctx context.Context, lvl *Level) error {
|
|||||||
func (r *Repo) SetLevel(ctx context.Context, guildID, userID int64, level int) error {
|
func (r *Repo) SetLevel(ctx context.Context, guildID, userID int64, level int) error {
|
||||||
const q = `
|
const q = `
|
||||||
INSERT INTO levels (guild, user_id, level, xp)
|
INSERT INTO levels (guild, user_id, level, xp)
|
||||||
VALUES ($1, $2, $3, 99)
|
VALUES ($1, $2, $3, 0)
|
||||||
ON CONFLICT (guild, user_id)
|
ON CONFLICT (guild, user_id)
|
||||||
DO UPDATE SET level = EXCLUDED.level, xp = 99
|
DO UPDATE SET level = EXCLUDED.level, xp = 0
|
||||||
`
|
`
|
||||||
_, err := r.db.ExecContext(ctx, q, guildID, userID, level)
|
_, err := r.db.ExecContext(ctx, q, guildID, userID, level)
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ type Repo struct {
|
|||||||
db *sql.DB
|
db *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LevelReward struct {
|
||||||
|
GuildID int64
|
||||||
|
Level int
|
||||||
|
RoleID int64
|
||||||
|
}
|
||||||
|
|
||||||
func NewRepo(db *sql.DB) *Repo {
|
func NewRepo(db *sql.DB) *Repo {
|
||||||
return &Repo{db: db}
|
return &Repo{db: db}
|
||||||
}
|
}
|
||||||
@@ -95,6 +101,34 @@ func (r *Repo) SetRoleRewardForLevel(ctx context.Context, guildID int64, level i
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Repo) ListRoleRewards(ctx context.Context, guildID int64, limit int) ([]*LevelReward, error) {
|
||||||
|
const q = `
|
||||||
|
SELECT levelreq, role
|
||||||
|
FROM levelrewards
|
||||||
|
WHERE guild_id = $1
|
||||||
|
ORDER BY levelreq ASC
|
||||||
|
LIMIT $2
|
||||||
|
`
|
||||||
|
rows, err := r.db.QueryContext(ctx, q, guildID, limit)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
out := make([]*LevelReward, 0, limit)
|
||||||
|
for rows.Next() {
|
||||||
|
rw := &LevelReward{GuildID: guildID}
|
||||||
|
if err := rows.Scan(&rw.Level, &rw.RoleID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out = append(out, rw)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Repo) SetLevelUpChannel(ctx context.Context, guildID int64, channelID int64) error {
|
func (r *Repo) SetLevelUpChannel(ctx context.Context, guildID int64, channelID int64) error {
|
||||||
const q = `
|
const q = `
|
||||||
INSERT INTO levelup (guild_id, levelup_channel_id)
|
INSERT INTO levelup (guild_id, levelup_channel_id)
|
||||||
|
|||||||
@@ -47,3 +47,11 @@ func (s *Service) GetLevelUpMessage(ctx context.Context, guildID int64) (string,
|
|||||||
func (s *Service) SetRoleRewardForLevel(ctx context.Context, guildID int64, level int, roleID int64) error {
|
func (s *Service) SetRoleRewardForLevel(ctx context.Context, guildID int64, level int, roleID int64) error {
|
||||||
return s.settings.SetRoleRewardForLevel(ctx, guildID, level, roleID)
|
return s.settings.SetRoleRewardForLevel(ctx, guildID, level, roleID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) ListRoleRewards(ctx context.Context, guildID int64, limit int) ([]*settingsrepo.LevelReward, error) {
|
||||||
|
return s.settings.ListRoleRewards(ctx, guildID, limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) IsLevelSystemEnabled(ctx context.Context, guildID int64) (bool, error) {
|
||||||
|
return s.settings.IsLevelSystemEnabled(ctx, guildID)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
|
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
|
||||||
Reference in New Issue
Block a user