Skip to content

Commit

Permalink
リーダーボードを実装 (#130)
Browse files Browse the repository at this point in the history
Signed-off-by: ikafly144 <support@sabafly.net>
  • Loading branch information
ikafly144 authored Aug 22, 2023
1 parent affdb2a commit 640fdf1
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 12 deletions.
7 changes: 6 additions & 1 deletion bot/commands/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,12 @@ func configLevelImportMee6CommandHandler(b *botlib.Bot[*client.Client]) handler.
for page := 0; true; page++ {
c, err := http.Get(fmt.Sprintf("%s?page=%d", url, page))
if err != nil || c.StatusCode != http.StatusOK {
_, _ = event.Client().Rest().UpdateInteractionResponse(event.ApplicationID(), event.Token(), discord.NewMessageUpdateBuilder().SetContent(fmt.Sprintf("# FAILED\r```| STATUS CODE | %d\r| RESPONSE | %v```", c.StatusCode, err)).Build())
switch c.StatusCode {
case http.StatusUnauthorized:
_, _ = event.Client().Rest().UpdateInteractionResponse(event.ApplicationID(), event.Token(), discord.NewMessageUpdateBuilder().SetContent(fmt.Sprintf("# FAILED\r```| STATUS CODE | %d\r| RESPONSE | %v```%s", c.StatusCode, err, translate.Message(event.Locale(), "config_import_mee6_result_unauthorized", translate.WithTemplate(map[string]any{"GuildID": *event.GuildID()})))).Build())
default:
_, _ = event.Client().Rest().UpdateInteractionResponse(event.ApplicationID(), event.Token(), discord.NewMessageUpdateBuilder().SetContent(fmt.Sprintf("# FAILED\r```| STATUS CODE | %d\r| RESPONSE | %v```", c.StatusCode, err)).Build())
}
return err
}
var leaderboard db.Mee6LeaderBoard
Expand Down
99 changes: 89 additions & 10 deletions bot/commands/level.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package commands
import (
"fmt"
"math/big"
"slices"

"github.com/disgoorg/json"
"github.com/disgoorg/snowflake/v2"
"github.com/sabafly/disgo/discord"
"github.com/sabafly/disgo/events"
"github.com/sabafly/gobot/bot/client"
Expand Down Expand Up @@ -54,26 +57,31 @@ func Level(b *botlib.Bot[*client.Client]) handler.Command {
},
},
discord.ApplicationCommandOptionSubCommand{
Name: "rank",
Description: "get the user rank",
Name: "leaderboard",
Description: "show guild member leaderboard",
Options: []discord.ApplicationCommandOption{
discord.ApplicationCommandOptionBool{
Name: "all-list",
Description: "get all of rank list",
Required: false,
discord.ApplicationCommandOptionInt{
Name: "page",
Description: "page number",
MinValue: json.Ptr(1),
},
},
},
discord.ApplicationCommandOptionSubCommand{
Name: "point",
Description: "show yourself point",
},
},
},
Checks: map[string]handler.Check[*events.ApplicationCommandInteractionCreate]{
"user/move": b.Self.CheckCommandPermission(b, "user.level.manage", discord.PermissionManageGuild),
"user/reset": b.Self.CheckCommandPermission(b, "user.level.manage", discord.PermissionManageGuild),
},
CommandHandlers: map[string]handler.CommandHandler{
"user/move": levelUserMoveCommandHandler(b),
"user/reset": levelUserResetCommandHandler(b),
"rank": levelRankCommandHandler(b),
"user/move": levelUserMoveCommandHandler(b),
"user/reset": levelUserResetCommandHandler(b),
"point": levelPointCommandHandler(b),
"leaderboard": levelLeaderBoard(b),
},
}
}
Expand Down Expand Up @@ -160,7 +168,7 @@ func levelUserResetCommandHandler(b *botlib.Bot[*client.Client]) handler.Command
}
}

func levelRankCommandHandler(b *botlib.Bot[*client.Client]) handler.CommandHandler {
func levelPointCommandHandler(b *botlib.Bot[*client.Client]) handler.CommandHandler {
return func(event *events.ApplicationCommandInteractionCreate) error {
b.Self.UserDataLock(event.User().ID).Lock()
defer b.Self.UserDataLock(event.User().ID).Unlock()
Expand Down Expand Up @@ -214,6 +222,74 @@ func levelRankCommandHandler(b *botlib.Bot[*client.Client]) handler.CommandHandl
}
}

func levelLeaderBoard(b *botlib.Bot[*client.Client]) handler.CommandHandler {
return func(event *events.ApplicationCommandInteractionCreate) error {
b.Self.UserDataLock(event.User().ID).Lock()
defer b.Self.UserDataLock(event.User().ID).Unlock()
b.Self.GuildDataLock(*event.GuildID()).Lock()
defer b.Self.GuildDataLock(*event.GuildID()).Unlock()
gd, err := b.Self.DB.GuildData().Get(*event.GuildID())
if err != nil {
return botlib.ReturnErr(event, err)
}
type sortLevel struct {
user_id snowflake.ID
level db.UserDataLevel
}
sort_list := []sortLevel{}
for id, level := range gd.UserLevels {
sort_list = append(sort_list, sortLevel{
user_id: id,
level: level.UserDataLevel,
})
}

page_number, ok := event.SlashCommandInteractionData().OptInt("page")
if !ok || page_number < 1 {
page_number = 1
}

max_page := len(sort_list)/25 + 1

if len(sort_list) < 1 || max_page < page_number {
return botlib.ReturnErrMessage(event, "error_unavailable_page")
}

slices.SortFunc(sort_list, func(a, b sortLevel) int {
return a.level.Point.Cmp(b.level.Point)
})
slices.Reverse(sort_list)

sort_list = sort_list[25*(page_number-1) : min(25*page_number, len(sort_list))]

var text_list_string string
for i, sl := range sort_list {
text_list_string += fmt.Sprintf(
"**#%d | ** %s **XP:** `%s` **Level:** `%s`\r",
(25*(page_number-1))+(i+1), discord.UserMention(sl.user_id), sl.level.Point.String(), sl.level.Level().String(),
)
}

embed := discord.NewEmbedBuilder()
embed.SetTitlef("💬%s(%d/%d)", translate.Message(event.Locale(), "level_leader_board_category_text"), page_number, max_page)
embed.SetDescription(text_list_string)
embed.SetAuthorNamef("🏆%s", translate.Message(event.Locale(), "level_leader_board_author_text"))
if guild, ok := event.Guild(); ok && guild.Icon != nil {
embed.SetAuthorIcon(*guild.IconURL())
}
embed.Embed = botlib.SetEmbedProperties(embed.Embed)
message := discord.NewMessageCreateBuilder()
message.AddEmbeds(embed.Build())
if err := event.CreateMessage(message.Build()); err != nil {
buf, _ := json.Marshal(message.Build())
b.Logger.Debug(string(buf), len(sort_list))
return botlib.ReturnErr(event, err)
}
b.Logger.Debug(len(sort_list))
return nil
}
}

func LevelModal(b *botlib.Bot[*client.Client]) handler.Modal {
return handler.Modal{
Name: "level",
Expand All @@ -235,6 +311,9 @@ func levelModalNoticeMessageHandler(b *botlib.Bot[*client.Client]) handler.Modal
if err := b.Self.DB.GuildData().Set(gd.ID, gd); err != nil {
return botlib.ReturnErr(event, err)
}
embed := discord.NewEmbedBuilder()
embed.SetTitle(translate.Message(event.Locale(), "config_changed"))
embed.SetDescription(translate.Message(event.Locale(), "config_level_notice_message_changed"))
if err := event.DeferUpdateMessage(); err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion bot/gobot.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func Run(file_path, lang_path, gobot_path string) error {
}
cfg, err := botlib.LoadConfig(file_path)
if err != nil {
panic("failed to load config: " + err.Error())
return err
}

logger := logrus.New()
Expand Down
6 changes: 6 additions & 0 deletions lang/ja.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -286,3 +286,9 @@ message_pin_delete: "このチャンネルの固定メッセージを削除し
minecraft_status_panel_created: "ステータスパネルを作成しました"
user_changed: "ユーザー設定を変更しました"
user_set_birthday: "誕生日を {{.Date}} に設定しました"
config_import_mee6_result_unauthorized: "mee6リーダーボードがパブリックではありません。\r[設定](https://mee6.xyz/en/dashboard/{{.GuildID}}/leaderboard)からリーダーボードを公開してください。"
config_level_notice_message_changed: "レベルアップ通知のメッセージを変更しました"
level_leader_board_category_text: "テキストメッセージ"
level_leader_board_author_text: "ギルド経験値リーダーボード"
error_unavailable_page_title: "存在しないページ"
error_unavailable_page_message: "そのページは存在しません"

0 comments on commit 640fdf1

Please sign in to comment.