go: Refactor vote*.go

master
Luther Wen Xu 2019-10-12 23:33:06 +07:00
parent 4619ad1c23
commit 38580f8910
Signed by untrusted user: chanbakjsd
GPG Key ID: B7D77E3E9D102B70
10 changed files with 222 additions and 169 deletions

@ -35,4 +35,8 @@ func init() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
_, err = db.Exec("CREATE TABLE IF NOT EXISTS minecraftUsername (discordId INTEGER, minecraftUsername TEXT, UNIQUE(discordId), UNIQUE(minecraftUsername))")
if err != nil {
panic(err)
}
} }

@ -5,4 +5,5 @@ const MemberRoleID = "626434632614805526"
const AuditChannel = "631789849929711627" const AuditChannel = "631789849929711627"
const VoteChannel = "627164246056239104" const VoteChannel = "627164246056239104"
const AnnounceCustomChannel = "627165467269922864" const AnnounceCustomChannel = "627165467269922864"
const AnnounceInviteChannel = "627165467269922864"
const VoteSuggestionChannel = "627164561644191744" const VoteSuggestionChannel = "627164561644191744"

@ -32,6 +32,27 @@ const ErrorVoteSuggestionNotEnoughInfo = "请提供更多资料。\nPlease provi
const ErrorVoteSuggestionTooLong = "你投票的内容过长了。请使用少过500个字符。\nYour vote is too long. Please use a maximum of 500 characters." const ErrorVoteSuggestionTooLong = "你投票的内容过长了。请使用少过500个字符。\nYour vote is too long. Please use a maximum of 500 characters."
const ErrorVoteSuggestionUnknownType = "未知投票种类Unknown Vote Type: %s" 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== //==Commands==
const SendAsUsage = "!sendas <频道ID> <信息>\n!sendas <channel ID> <message>" const SendAsUsage = "!sendas <频道ID> <信息>\n!sendas <channel ID> <message>"
const SendAsSuccessfulDescription = "成功发送该信息。\nSent the message successfully." const SendAsSuccessfulDescription = "成功发送该信息。\nSent the message successfully."

@ -1,6 +1,10 @@
package modules package modules
import "github.com/bwmarrin/discordgo" import (
"github.com/bwmarrin/discordgo"
"TerraOceanBot/discord/config"
)
type embed struct { type embed struct {
*discordgo.MessageEmbed *discordgo.MessageEmbed
@ -54,6 +58,13 @@ func (e *embed) AddInlineField(name, value string) *embed {
return e 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 { func (e *embed) Build() *discordgo.MessageEmbed {
return e.MessageEmbed return e.MessageEmbed
} }
@ -70,3 +81,7 @@ func (e *embed) SendPM(s *discordgo.Session, userID string) {
} }
e.Send(s, channel.ID) e.Send(s, channel.ID)
} }
func (e *embed) Edit(s *discordgo.Session, channelID, messageID string) {
s.ChannelMessageEditEmbed(channelID, messageID, e.Build())
}

@ -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)) auditInfo(s, fmt.Sprintf("Vote ID %d has been created by <@%s>.", id, r.UserID))
s.ChannelMessageEdit(config.VoteChannel, msg.ID, "") 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, emojiX)
s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiOne) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiOne)
s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiTwo) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiTwo)

@ -1,18 +1,9 @@
package modules package modules
import ( import "github.com/bwmarrin/discordgo"
"fmt"
"strconv"
"strings"
"github.com/bwmarrin/discordgo"
"TerraOceanBot/db"
"TerraOceanBot/discord/config"
)
type voteType struct { 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) ResultHandler func(s *discordgo.Session, id int, name string, isPositive bool)
} }
@ -26,141 +17,3 @@ var voteTypes = map[string]voteType{
ResultHandler: handleInviteResult, 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))
}

@ -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)
}

@ -12,18 +12,22 @@ import (
"TerraOceanBot/discord/config" "TerraOceanBot/discord/config"
) )
const announceInviteChannel = "627165467269922864" func createInviteEmbed(id int, name string) *embed {
func createInviteEmbed(id int, name string) *discordgo.MessageEmbed {
list := strings.SplitN(name, ":", 2) 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) { func handleInviteResult(s *discordgo.Session, id int, name string, isPositive bool) {
list := strings.SplitN(name, ":", 2)
if !isPositive { if !isPositive {
initNewEmbed(config.EntryVoteRejectNotificationTitle, config.EntryVoteRejectNotificationContent, config.ErrorColour).
SendPM(s, list[0])
return return
} }
member, err := backend.GetMemberFromUserFriendlyName(s, strings.SplitN(name, ":", 2)[0]) member, err := backend.GetMemberFromUserFriendlyName(s, list[0])
if err != nil { if err != nil {
auditError(s, "", err) auditError(s, "", err)
return return
@ -33,7 +37,11 @@ func handleInviteResult(s *discordgo.Session, id int, name string, isPositive bo
auditError(s, "", err) auditError(s, "", err)
return 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) choices, err := db.GetAllVoteChoices(id)
if err != nil { if err != nil {
auditError(s, "", err) auditError(s, "", err)

@ -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)
}
}

@ -32,7 +32,7 @@ func ListenToVoteFinishes(s *discordgo.Session) {
voteType, _ := db.GetVoteType(v.VoteID) voteType, _ := db.GetVoteType(v.VoteID)
voteName, _ := db.GetVoteName(v.VoteID) voteName, _ := db.GetVoteName(v.VoteID)
messageID, _ := db.GetMessageIDFromVote(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) voteTypes[voteType].ResultHandler(s, v.VoteID, voteName, v.IsPositive)
} }
toAnnounceResultList = toAnnounceResultList[:0] toAnnounceResultList = toAnnounceResultList[:0]
@ -106,14 +106,3 @@ func checkForVoteResult(s *discordgo.Session, id int) {
voteMutex.Unlock() 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
}