diff --git a/GoBot/db/db.go b/GoBot/db/db.go index 41e3356..6672a4a 100644 --- a/GoBot/db/db.go +++ b/GoBot/db/db.go @@ -35,4 +35,8 @@ func init() { if err != nil { panic(err) } + _, err = db.Exec("CREATE TABLE IF NOT EXISTS minecraftUsername (discordId INTEGER, minecraftUsername TEXT, UNIQUE(discordId), UNIQUE(minecraftUsername))") + if err != nil { + panic(err) + } } diff --git a/GoBot/discord/config/discordID.go b/GoBot/discord/config/discordID.go index ba50a63..9fd25c0 100644 --- a/GoBot/discord/config/discordID.go +++ b/GoBot/discord/config/discordID.go @@ -5,4 +5,5 @@ const MemberRoleID = "626434632614805526" const AuditChannel = "631789849929711627" const VoteChannel = "627164246056239104" const AnnounceCustomChannel = "627165467269922864" +const AnnounceInviteChannel = "627165467269922864" const VoteSuggestionChannel = "627164561644191744" diff --git a/GoBot/discord/config/translate.go b/GoBot/discord/config/translate.go index c6bccdf..d0f42b9 100644 --- a/GoBot/discord/config/translate.go +++ b/GoBot/discord/config/translate.go @@ -32,6 +32,27 @@ const ErrorVoteSuggestionNotEnoughInfo = "请提供更多资料。\nPlease provi const ErrorVoteSuggestionTooLong = "你投票的内容过长了。请使用少过500个字符。\nYour vote is too long. Please use a maximum of 500 characters." const ErrorVoteSuggestionUnknownType = "未知投票种类Unknown Vote Type: %s" +const CustomVoteTitle = "自定义投票Custom Vote" +const CustomVoteColour = 0x00F0F0 +const CustomVoteVoteID = "投票编号Vote ID" +const CustomVoteContent = "投票内容Content" + +const EntryVoteTitle = "加入申请Entry Application" +const EntryVoteColour = 0x808000 +const EntryVoteVoteID = "投票编号Vote ID" +const EntryVoteApplicant = "申请者Applicant" +const EntryVoteReason = "加入原因Provided Reason for Entry" + +const VotePassTitle = "投票通过 Vote Passed" +const VotePassColour = 0x00F000 +const VoteRejectTitle = "投票不通过 Vote Rejected" +const VoteRejectColour = 0xF00000 + +const EntryVoteRejectNotificationTitle = "抱歉……Sorry..." +const EntryVoteRejectNotificationContent = "你加入的提案最终被拒绝了。请提升你和伺服器中的成员的关系后再次申请加入。\nThe application entry you recently sent was rejected. You must strengthen your relationship with server members before trying again." +const EntryVoteSuccessWelcomeTitle = "欢迎!Welcome!" +const EntryVoteSuccessWelcomeDescription = "欢迎进入伺服器,<@%s>。Welcome to our server, <@%s>!" + //==Commands== const SendAsUsage = "!sendas <频道ID> <信息>\n!sendas " const SendAsSuccessfulDescription = "成功发送该信息。\nSent the message successfully." diff --git a/GoBot/discord/modules/embed.go b/GoBot/discord/modules/embed.go index 4a52bbf..55d30b1 100644 --- a/GoBot/discord/modules/embed.go +++ b/GoBot/discord/modules/embed.go @@ -1,6 +1,10 @@ package modules -import "github.com/bwmarrin/discordgo" +import ( + "github.com/bwmarrin/discordgo" + + "TerraOceanBot/discord/config" +) type embed struct { *discordgo.MessageEmbed @@ -54,6 +58,13 @@ func (e *embed) AddInlineField(name, value string) *embed { return e } +func (e *embed) UpdateVoteStatus(isPositive bool) *embed { + if isPositive { + return e.SetColour(config.VotePassColour).SetTitle(config.VotePassTitle) + } + return e.SetColour(config.VoteRejectColour).SetTitle(config.VoteRejectTitle) +} + func (e *embed) Build() *discordgo.MessageEmbed { return e.MessageEmbed } @@ -70,3 +81,7 @@ func (e *embed) SendPM(s *discordgo.Session, userID string) { } e.Send(s, channel.ID) } + +func (e *embed) Edit(s *discordgo.Session, channelID, messageID string) { + s.ChannelMessageEditEmbed(channelID, messageID, e.Build()) +} diff --git a/GoBot/discord/modules/invite.go b/GoBot/discord/modules/invite.go index 0b96ebf..404ce1c 100644 --- a/GoBot/discord/modules/invite.go +++ b/GoBot/discord/modules/invite.go @@ -167,7 +167,7 @@ func CheckForInvite(s *discordgo.Session, r *discordgo.MessageReactionAdd) { } auditInfo(s, fmt.Sprintf("Vote ID %d has been created by <@%s>.", id, r.UserID)) s.ChannelMessageEdit(config.VoteChannel, msg.ID, "") - s.ChannelMessageEditEmbed(config.VoteChannel, msg.ID, createInviteEmbed(id, invite.User+":"+invite.Reason)) + createInviteEmbed(id, invite.User+":"+invite.Reason).Edit(s, config.VoteChannel, msg.ID) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiX) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiOne) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiTwo) diff --git a/GoBot/discord/modules/vote.go b/GoBot/discord/modules/vote.go index 7c4a08d..0d85ce0 100644 --- a/GoBot/discord/modules/vote.go +++ b/GoBot/discord/modules/vote.go @@ -1,18 +1,9 @@ package modules -import ( - "fmt" - "strconv" - "strings" - - "github.com/bwmarrin/discordgo" - - "TerraOceanBot/db" - "TerraOceanBot/discord/config" -) +import "github.com/bwmarrin/discordgo" type voteType struct { - EmbedBuilder func(id int, name string) *discordgo.MessageEmbed + EmbedBuilder func(id int, name string) *embed ResultHandler func(s *discordgo.Session, id int, name string, isPositive bool) } @@ -26,141 +17,3 @@ var voteTypes = map[string]voteType{ ResultHandler: handleInviteResult, }, } - -const ( - emojiOne = "1⃣" - emojiTwo = "2⃣" - emojiThree = "3⃣" - emojiFour = "4⃣" - emojiFive = "5⃣" - emojiCheck = "✅" - emojiX = "❌" -) - -func CheckForVote(s *discordgo.Session, r *discordgo.MessageReactionAdd) { - if r.UserID == s.State.User.ID { - return - } - voteID, err := db.GetVoteFromMessageID(r.MessageID) - if err == db.ErrNotFound { - return - } - if err != nil { - auditError(s, r.ChannelID, err) - return - } - - s.MessageReactionRemove(r.ChannelID, r.MessageID, r.Emoji.Name, r.UserID) - - var value int - switch r.Emoji.Name { - case emojiX: - value = db.ForceRejectionVote - case emojiOne: - value = 1 - case emojiTwo: - value = 2 - case emojiThree: - value = 3 - case emojiFour: - value = 4 - case emojiFive: - value = 5 - case emojiCheck: - value = db.NuclearOptionVote - default: - auditInfo(s, "Reaction "+r.Emoji.Name+" was added to vote #"+strconv.Itoa(voteID)) - return - } - - err = db.UpdateVote(voteID, r.UserID, value) - - if err == db.ErrForceRejectionVoteReuse { - initNewEmbed(config.VoteErrorTitle, config.ErrorForceRejectionReuse, config.ErrorColour). - SendPM(s, r.UserID) - return - } - if err == db.ErrVoteIsOver { - initNewEmbed(config.VoteErrorTitle, config.ErrorVoteHasEnded, config.ErrorColour). - SendPM(s, r.UserID) - return - } - - var voteName string - if err == nil { - voteName, err = db.GetVoteName(voteID) - } - - if err != nil { - auditErrorPM(s, r.UserID, err) - return - } - - initNewEmbed(config.VoteSuccessfulTitle, "", config.SuccessColour). - AddField(config.VoteSuccessfulVoteID, strconv.Itoa(voteID)). - AddField(config.VoteSuccessfulVoteName, voteName). - AddField(config.VoteSuccessfulDetectedVote, r.Emoji.Name). - SendPM(s, r.UserID) - auditInfo(s, fmt.Sprintf("<@%s> has chosen %s for vote ID %d.", r.UserID, r.Emoji.Name, voteID)) - - checkForVoteResult(s, voteID) -} - -//TODO Replace with a command. -func VoteSuggestion(s *discordgo.Session, m *discordgo.MessageCreate) { - s.ChannelMessageDelete(m.ChannelID, m.ID) - - args := strings.SplitN(m.Content, " ", 2) - if len(args) == 1 { - initNewEmbed( - config.VoteSuggestionErrorTitle, - config.ErrorVoteSuggestionNotEnoughInfo+config.VoteSuggestionNote, - config.ErrorColour, - ).SendPM(s, m.Author.ID) - return - } - if len(args[1]) > 500 { - initNewEmbed( - config.VoteSuggestionErrorTitle, - config.ErrorVoteSuggestionTooLong+config.VoteSuggestionNote, - config.ErrorColour, - ).SendPM(s, m.Author.ID) - return - } - - switch args[0] { - case "custom": - msg, err := s.ChannelMessageSend(config.VoteChannel, "正在准备新的一个投票…… Preparing for the next vote...") - if err != nil { - auditErrorPM(s, m.Author.ID, err) - return - } - id, err := db.CreateCustomVote(msg.ID, args[1]) - if err != nil { - auditErrorPM(s, m.Author.ID, err) - return - } - auditInfo(s, fmt.Sprintf("Vote ID %d has been created by <@%s>.", id, m.Author.ID)) - s.ChannelMessageEdit(config.VoteChannel, msg.ID, "") - s.ChannelMessageEditEmbed(config.VoteChannel, msg.ID, createCustomEmbed(id, args[1])) - s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiOne) - s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiTwo) - s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiThree) - s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiFour) - s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiFive) - default: - initNewEmbed( - config.VoteSuggestionErrorTitle, - fmt.Sprintf(config.ErrorVoteSuggestionUnknownType, args[1])+config.VoteSuggestionNote, - config.ErrorColour, - ).SendPM(s, m.Author.ID) - } -} - -func createCustomEmbed(id int, name string) *discordgo.MessageEmbed { - return newEmbed().SetColour(0x00FFFF).SetTitle("自定义投票Custom Vote").AddField("ID", strconv.Itoa(id)).AddField("内容Content", name).Build() -} - -func announceCustomResult(s *discordgo.Session, id int, name string, isPositive bool) { - s.ChannelMessageSendEmbed(config.AnnounceCustomChannel, showVoteStatus(createCustomEmbed(id, name), isPositive)) -} diff --git a/GoBot/discord/modules/vote_custom.go b/GoBot/discord/modules/vote_custom.go new file mode 100644 index 0000000..494c1c4 --- /dev/null +++ b/GoBot/discord/modules/vote_custom.go @@ -0,0 +1,20 @@ +package modules + +import ( + "strconv" + + "github.com/bwmarrin/discordgo" + + "TerraOceanBot/discord/config" +) + +func createCustomEmbed(id int, name string) *embed { + return initNewEmbed(config.CustomVoteTitle, "", config.CustomVoteColour). + AddField(config.CustomVoteVoteID, strconv.Itoa(id)). + AddField(config.CustomVoteContent, name) +} + +func announceCustomResult(s *discordgo.Session, id int, name string, isPositive bool) { + createCustomEmbed(id, name).UpdateVoteStatus(isPositive). + Send(s, config.AnnounceCustomChannel) +} diff --git a/GoBot/discord/modules/vote_invite.go b/GoBot/discord/modules/vote_invite.go index c107ac0..842c0c3 100644 --- a/GoBot/discord/modules/vote_invite.go +++ b/GoBot/discord/modules/vote_invite.go @@ -12,18 +12,22 @@ import ( "TerraOceanBot/discord/config" ) -const announceInviteChannel = "627165467269922864" - -func createInviteEmbed(id int, name string) *discordgo.MessageEmbed { +func createInviteEmbed(id int, name string) *embed { list := strings.SplitN(name, ":", 2) - return newEmbed().SetColour(0x00FFFF).SetTitle("加入申请Entry Application").AddField("ID", strconv.Itoa(id)).AddField("加入者Applicant", "<@"+list[0]+">").AddField("提供原因Provided Reason", list[1]).Build() + return initNewEmbed(config.EntryVoteTitle, "", config.EntryVoteColour). + AddField(config.EntryVoteVoteID, strconv.Itoa(id)). + AddField(config.EntryVoteApplicant, "<@"+list[0]+">"). + AddField(config.EntryVoteReason, list[1]) } func handleInviteResult(s *discordgo.Session, id int, name string, isPositive bool) { + list := strings.SplitN(name, ":", 2) if !isPositive { + initNewEmbed(config.EntryVoteRejectNotificationTitle, config.EntryVoteRejectNotificationContent, config.ErrorColour). + SendPM(s, list[0]) return } - member, err := backend.GetMemberFromUserFriendlyName(s, strings.SplitN(name, ":", 2)[0]) + member, err := backend.GetMemberFromUserFriendlyName(s, list[0]) if err != nil { auditError(s, "", err) return @@ -33,7 +37,11 @@ func handleInviteResult(s *discordgo.Session, id int, name string, isPositive bo auditError(s, "", err) return } - s.ChannelMessageSend(announceInviteChannel, fmt.Sprintf("欢迎<@%s>的加入!Welcome <@%s> to this server!", member.User.ID, member.User.ID)) + initNewEmbed( + config.EntryVoteSuccessWelcomeTitle, + fmt.Sprintf(config.EntryVoteSuccessWelcomeDescription, member.User.ID, member.User.ID), + config.SuccessColour, + ).Send(s, config.AnnounceInviteChannel) choices, err := db.GetAllVoteChoices(id) if err != nil { auditError(s, "", err) diff --git a/GoBot/discord/modules/vote_listener.go b/GoBot/discord/modules/vote_listener.go new file mode 100644 index 0000000..7174a45 --- /dev/null +++ b/GoBot/discord/modules/vote_listener.go @@ -0,0 +1,142 @@ +package modules + +import ( + "fmt" + "strconv" + "strings" + + "github.com/bwmarrin/discordgo" + + "TerraOceanBot/db" + "TerraOceanBot/discord/config" +) + +const ( + emojiOne = "1⃣" + emojiTwo = "2⃣" + emojiThree = "3⃣" + emojiFour = "4⃣" + emojiFive = "5⃣" + emojiCheck = "✅" + emojiX = "❌" +) + +func CheckForVote(s *discordgo.Session, r *discordgo.MessageReactionAdd) { + if r.UserID == s.State.User.ID { + return + } + voteID, err := db.GetVoteFromMessageID(r.MessageID) + if err == db.ErrNotFound { + return + } + if err != nil { + auditError(s, r.ChannelID, err) + return + } + + s.MessageReactionRemove(r.ChannelID, r.MessageID, r.Emoji.Name, r.UserID) + + var value int + switch r.Emoji.Name { + case emojiX: + value = db.ForceRejectionVote + case emojiOne: + value = 1 + case emojiTwo: + value = 2 + case emojiThree: + value = 3 + case emojiFour: + value = 4 + case emojiFive: + value = 5 + case emojiCheck: + value = db.NuclearOptionVote + default: + auditInfo(s, "Reaction "+r.Emoji.Name+" was added to vote #"+strconv.Itoa(voteID)) + return + } + + err = db.UpdateVote(voteID, r.UserID, value) + + if err == db.ErrForceRejectionVoteReuse { + initNewEmbed(config.VoteErrorTitle, config.ErrorForceRejectionReuse, config.ErrorColour). + SendPM(s, r.UserID) + return + } + if err == db.ErrVoteIsOver { + initNewEmbed(config.VoteErrorTitle, config.ErrorVoteHasEnded, config.ErrorColour). + SendPM(s, r.UserID) + return + } + + var voteName string + if err == nil { + voteName, err = db.GetVoteName(voteID) + } + + if err != nil { + auditErrorPM(s, r.UserID, err) + return + } + + initNewEmbed(config.VoteSuccessfulTitle, "", config.SuccessColour). + AddField(config.VoteSuccessfulVoteID, strconv.Itoa(voteID)). + AddField(config.VoteSuccessfulVoteName, voteName). + AddField(config.VoteSuccessfulDetectedVote, r.Emoji.Name). + SendPM(s, r.UserID) + auditInfo(s, fmt.Sprintf("<@%s> has chosen %s for vote ID %d.", r.UserID, r.Emoji.Name, voteID)) + + checkForVoteResult(s, voteID) +} + +//TODO Replace with a command. +func VoteSuggestion(s *discordgo.Session, m *discordgo.MessageCreate) { + s.ChannelMessageDelete(m.ChannelID, m.ID) + + args := strings.SplitN(m.Content, " ", 2) + if len(args) == 1 { + initNewEmbed( + config.VoteSuggestionErrorTitle, + config.ErrorVoteSuggestionNotEnoughInfo+config.VoteSuggestionNote, + config.ErrorColour, + ).SendPM(s, m.Author.ID) + return + } + if len(args[1]) > 500 { + initNewEmbed( + config.VoteSuggestionErrorTitle, + config.ErrorVoteSuggestionTooLong+config.VoteSuggestionNote, + config.ErrorColour, + ).SendPM(s, m.Author.ID) + return + } + + switch args[0] { + case "custom": + msg, err := s.ChannelMessageSend(config.VoteChannel, "正在准备新的一个投票…… Preparing for the next vote...") + if err != nil { + auditErrorPM(s, m.Author.ID, err) + return + } + id, err := db.CreateCustomVote(msg.ID, args[1]) + if err != nil { + auditErrorPM(s, m.Author.ID, err) + return + } + auditInfo(s, fmt.Sprintf("Vote ID %d has been created by <@%s>.", id, m.Author.ID)) + s.ChannelMessageEdit(config.VoteChannel, msg.ID, "") + createCustomEmbed(id, args[1]).Edit(s, config.VoteChannel, msg.ID) + s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiOne) + s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiTwo) + s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiThree) + s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiFour) + s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiFive) + default: + initNewEmbed( + config.VoteSuggestionErrorTitle, + fmt.Sprintf(config.ErrorVoteSuggestionUnknownType, args[1])+config.VoteSuggestionNote, + config.ErrorColour, + ).SendPM(s, m.Author.ID) + } +} diff --git a/GoBot/discord/modules/vote_result.go b/GoBot/discord/modules/vote_result.go index 2a34755..3e7fa01 100644 --- a/GoBot/discord/modules/vote_result.go +++ b/GoBot/discord/modules/vote_result.go @@ -32,7 +32,7 @@ func ListenToVoteFinishes(s *discordgo.Session) { voteType, _ := db.GetVoteType(v.VoteID) voteName, _ := db.GetVoteName(v.VoteID) messageID, _ := db.GetMessageIDFromVote(v.VoteID) - s.ChannelMessageEditEmbed(config.VoteChannel, messageID, showVoteStatus(voteTypes[voteType].EmbedBuilder(v.VoteID, voteName), v.IsPositive)) + voteTypes[voteType].EmbedBuilder(v.VoteID, voteName).UpdateVoteStatus(v.IsPositive).Edit(s, config.VoteChannel, messageID) voteTypes[voteType].ResultHandler(s, v.VoteID, voteName, v.IsPositive) } toAnnounceResultList = toAnnounceResultList[:0] @@ -106,14 +106,3 @@ func checkForVoteResult(s *discordgo.Session, id int) { voteMutex.Unlock() } } - -func showVoteStatus(embed *discordgo.MessageEmbed, isPositive bool) *discordgo.MessageEmbed { - if isPositive { - embed.Color = 0x00F000 - embed.Title = "投票通过 Vote Passed" - } else { - embed.Color = 0xF00000 - embed.Title = "投票不通过 Vote Rejected" - } - return embed -}