package main import ( "fmt" "os" "os/signal" "strings" "time" "github.com/bwmarrin/discordgo" ) var WaitingLength = 1 * time.Hour // user data type WaitingUser struct { ID string Username string AddedAt time.Time EndAt time.Time Timer *time.Timer } func NewWaitingUser(id, username string, timer *time.Timer) WaitingUser { return WaitingUser{ ID: id, Username: username, AddedAt: time.Now(), EndAt: time.Now().Add(WaitingLength), Timer: timer, } } func (wu *WaitingUser) UpdateTimer() { wu.Timer.Reset(WaitingLength) wu.EndAt = time.Now().Add(WaitingLength) } var WaitingUsersList []WaitingUser func lookupWaitingUserIndex(userID string) int { for i := range WaitingUsersList { if WaitingUsersList[i].ID == userID { return i } } return -1 } func main() { discordToken := os.Getenv("DISCORD_TOKEN") discordChannelId := os.Getenv("DISCORD_CHANNEL_ID") discord, err := discordgo.New("Bot " + discordToken) if err != nil { panic(err) } discord.AddHandler(func(s *discordgo.Session, r *discordgo.Ready) { fmt.Println("Bot is now running. Press CTRL+C to exit.") }) discord.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) { if i.Type == discordgo.InteractionApplicationCommand { if i.ChannelID != discordChannelId { s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: "コマンドを使うチャンネルを間違ってますよ。", }, }) } roles, _ := s.GuildRoles(i.GuildID) var discordWaintingRoleId string for _, role := range roles { if role.Name == "WAITING" { discordWaintingRoleId = role.ID } } fmt.Println("GuildId: ", i.GuildID, " User ID: ", i.Member.User.ID, " Role ID: ", discordWaintingRoleId) switch i.ApplicationCommandData().Name { case "waitlistadd": // Handle addwait command // check if user is already in the waiting list index := lookupWaitingUserIndex(i.Member.User.ID) if index == -1 { //not in waiting list err2 := discord.GuildMemberRoleAdd(i.GuildID, i.Member.User.ID, discordWaintingRoleId) if err2 != nil { panic(err2) } timer := time.AfterFunc(WaitingLength, func() { discord.GuildMemberRoleRemove(i.GuildID, i.Member.User.ID, discordWaintingRoleId) index := lookupWaitingUserIndex(i.Member.User.ID) if index != -1 { WaitingUsersList = append(WaitingUsersList[:index], WaitingUsersList[index+1:]...) } }) WaitingUsersList = append(WaitingUsersList, NewWaitingUser(i.Member.User.ID, i.Member.User.Username, timer)) s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: i.Member.User.Username + " を待機リストに追加しました。", }, }) } else { // User is already in the waiting list, extend their waiting time WaitingUsersList[index].UpdateTimer() s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: i.Member.User.Username + " の待機時間を延長しました。", }, }) } case "waitlistshow": // Handle waitlistshow command var waitingUsersStr []string for _, user := range WaitingUsersList { waitingUsersStr = append(waitingUsersStr, user.Username+" ("+user.EndAt.Format("15:04")+"まで)") } s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: "Waiting list: " + strings.Join(waitingUsersStr, ", "), }, }) case "waitlistremove": // Handle waitlistremove command userID := i.ApplicationCommandData().GetOption("user").UserValue(s).ID userName := i.ApplicationCommandData().GetOption("user").UserValue(s).Username discord.GuildMemberRoleRemove(i.GuildID, userID, discordWaintingRoleId) index := lookupWaitingUserIndex(userID) if index != -1 { WaitingUsersList = append(WaitingUsersList[:index], WaitingUsersList[index+1:]...) s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: userName + " を待機リストから削除しました。", }, }) } else { s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: userName + " は待機リストにいません。", }, }) } case "waitlistremoveall": // Handle waitlistremoveall command for _, user := range WaitingUsersList { discord.GuildMemberRoleRemove(i.GuildID, user.ID, discordWaintingRoleId) user.Timer.Stop() } WaitingUsersList = nil s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: "全員を待機リストから削除しました。", }, }) } } }) openErr := discord.Open() if openErr != nil { panic(openErr) } // define command to wait discord.ApplicationCommandCreate(discord.State.User.ID, "", &discordgo.ApplicationCommand{ Name: "waitlistadd", Description: "待機リストに自分を追加する", Options: []*discordgo.ApplicationCommandOption{}, }) discord.ApplicationCommandCreate(discord.State.User.ID, "", &discordgo.ApplicationCommand{ Name: "waitlistshow", Description: "待機リストを表示する", Options: []*discordgo.ApplicationCommandOption{}, }) discord.ApplicationCommandCreate(discord.State.User.ID, "", &discordgo.ApplicationCommand{ Name: "waitlistremove", Description: "待機リストからユーザーを削除する", Options: []*discordgo.ApplicationCommandOption{ { Name: "user", Description: "待機リストから削除するユーザー", Type: discordgo.ApplicationCommandOptionUser, Required: true, }, }, }) discord.ApplicationCommandCreate(discord.State.User.ID, "", &discordgo.ApplicationCommand{ Name: "waitlistremoveall", Description: "待機リストから全員を削除する", Options: []*discordgo.ApplicationCommandOption{}, }) stop := make(chan os.Signal, 1) signal.Notify(stop, os.Interrupt) fmt.Println("Press Ctrl+C to exit") <-stop }