Files
splawaitbot/main.go

211 lines
6.7 KiB
Go

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
}