go: Implement '!validate' command

pull/7/head
Luther Wen Xu 2019-10-12 14:40:46 +07:00
parent fa8259fb07
commit d42b8a7f5b
Signed by: chanbakjsd
GPG Key ID: B7D77E3E9D102B70
9 changed files with 222 additions and 16 deletions

@ -1,6 +1,18 @@
package main
import "github.com/bwmarrin/discordgo"
import (
"fmt"
"strings"
"github.com/bwmarrin/discordgo"
)
var pendingInviteConfirmation = make(map[string]invite)
type invite struct {
User string
Reason string
}
func createInvite(s *discordgo.Session, m *discordgo.MessageCreate, command []string) {
if !enforceDM(s, m) {
@ -50,3 +62,119 @@ func createInvite(s *discordgo.Session, m *discordgo.MessageCreate, command []st
)
}
}
func checkUseInvite(s *discordgo.Session, m *discordgo.MessageCreate, command []string) {
if !enforceDM(s, m) {
return
}
if !nonMembersOnly(s, m) {
return
}
s.ChannelMessageDelete(m.ChannelID, m.ID)
if len(command) < 3 {
sendPrivateMessage(s, m.Author.ID, "指令的使用方法是`!validate <验证码> <原因>`.\nUsage: `!validate <validation code> <reason>`")
return
}
messageSplit := strings.SplitN(m.Content, " ", 3)
inviter, err := getInviteOwner(messageSplit[1])
if err == errInviteUsed {
sendPrivateMessage(s, m.Author.ID, "该验证码已被使用过。请向验证码制造者要求新的验证码。\nThis validation code has been used before. Please request a new one.")
return
}
if err == errNotFound {
sendPrivateMessage(s, m.Author.ID, "该验证码不存在。请使用存在的验证码。\nThis validation code doesn't exist. Please use an existing one.")
return
}
if err != nil {
sendPrivateMessage(s, m.Author.ID, "错误已发生。请稍候尝试。\nAn error has occurred. Please try again later.")
auditLog(s, err.Error())
return
}
member, err := s.GuildMember(guildID, inviter)
if err != nil {
sendPrivateMessage(s, m.Author.ID, "验证码制造者不是会员。\nValidation code creator is no longer a member.")
return
}
isMember := false
for _, v := range member.Roles {
if v == memberRoleID {
isMember = true
}
}
if !isMember {
sendPrivateMessage(s, m.Author.ID, "验证码制造者不是会员。\nValidation code creator is no longer a member.")
return
}
useInvite(messageSplit[1])
channel, err := s.UserChannelCreate(inviter)
if err != nil {
sendPrivateMessage(s, m.Author.ID, "验证码制造者关闭了私信。\nValidation code creator did not enable DMs.")
return
}
msg, err := s.ChannelMessageSend(channel.ID, fmt.Sprintf("<@%s>正在尝试使用验证码%s。请问是否同意该使用", m.Author.ID, messageSplit[1]))
if err != nil {
sendPrivateMessage(s, m.Author.ID, "验证码制造者关闭了私信。\nValidation code creator did not enable DMs.")
return
}
pendingInviteConfirmation[msg.ID] = invite{
User: m.Author.ID,
Reason: messageSplit[2],
}
s.MessageReactionAdd(channel.ID, msg.ID, emojiX)
s.MessageReactionAdd(channel.ID, msg.ID, emojiCheck)
}
func checkForInvite(s *discordgo.Session, r *discordgo.MessageReactionAdd) {
if r.UserID == s.State.User.ID {
return
}
invite, ok := pendingInviteConfirmation[r.MessageID]
if !ok {
return
}
delete(pendingInviteConfirmation, r.MessageID)
switch r.Emoji.Name {
case emojiX:
s.ChannelMessageSend(r.ChannelID, "已成功拒绝该验证码的使用。为了保护你,该验证码已被无效化。\nThe use of this validation code has been rejected. This validation code has been invalidated to protect you.")
return
case emojiCheck:
default:
return
}
s.ChannelMessageSend(r.ChannelID, "已同意验证码的使用。该验证码已被无效化。\nUse of validation code accepted. This validation code has been invalidated.")
msg, err := s.ChannelMessageSend(voteChannel, "正在准备新的一个投票…… Preparing for the next vote...")
if err != nil {
sendPrivateMessage(s, r.UserID, "创造投票失败。Failed to create vote.")
auditLog(s,
fmt.Sprintf("Error occurred while creating vote for <@%s>.\n%v\nError: %s", r.UserID, *r, err.Error()),
)
return
}
id, err := createInviteVote(msg.ID, invite.User, invite.Reason)
if err != nil {
sendPrivateMessage(s, r.UserID, "创造投票失败。Failed to create vote.")
auditLog(s,
fmt.Sprintf("Error occurred while creating vote for <@%s>.\n%v\nError: %s", r.UserID, *r, err.Error()),
)
return
}
auditLog(s, fmt.Sprintf("Vote ID %d has been created by <@%s>.", id, r.UserID))
s.ChannelMessageEdit(voteChannel, msg.ID, "")
s.ChannelMessageEditEmbed(voteChannel, msg.ID, createInviteEmbed(id, invite.User+":"+invite.Reason))
s.MessageReactionAdd(voteChannel, msg.ID, emojiX)
s.MessageReactionAdd(voteChannel, msg.ID, emojiOne)
s.MessageReactionAdd(voteChannel, msg.ID, emojiTwo)
s.MessageReactionAdd(voteChannel, msg.ID, emojiThree)
s.MessageReactionAdd(voteChannel, msg.ID, emojiFour)
s.MessageReactionAdd(voteChannel, msg.ID, emojiFive)
s.MessageReactionAdd(voteChannel, msg.ID, emojiCheck)
}

@ -48,6 +48,23 @@ func membersOnly(s *discordgo.Session, m *discordgo.MessageCreate) bool {
return false
}
func nonMembersOnly(s *discordgo.Session, m *discordgo.MessageCreate) bool {
member, err := s.GuildMember(guildID, m.Author.ID)
if err != nil {
return false
}
for _, v := range member.Roles {
if v == memberRoleID {
s.ChannelMessageSend(
m.ChannelID,
m.Author.Mention()+",该指令只能被非会员使用。\n"+m.Author.Mention()+", this command can only be used by non-member.",
)
return false
}
}
return true
}
func sendPrivateMessage(s *discordgo.Session, recipient, message string) error {
channel, err := s.UserChannelCreate(recipient)
if err != nil {

@ -69,6 +69,8 @@ func checkForTrustUpdate(s *discordgo.Session, r *discordgo.MessageReactionAdd)
return
}
delete(trustMessage, r.MessageID)
var value int
switch r.Emoji.Name {
case emojiOne:

@ -18,6 +18,10 @@ var voteTypes = map[string]voteType{
EmbedBuilder: createCustomEmbed,
ResultHandler: announceCustomResult,
},
"invite": voteType{
EmbedBuilder: createInviteEmbed,
ResultHandler: handleInviteResult,
},
}
const voteChannel = "627164246056239104"

@ -25,22 +25,24 @@ func getTrustVote(targetID string) ([]int, error) {
return array, nil
}
func updateDbTrust(sourceID, targetID string, voteValue int) error {
rows, err := db.Query("SELECT lastUpdated FROM trustVote WHERE sourceUser=? AND targetUser=?", sourceID, targetID)
if err != nil {
return err
}
if rows.Next() {
//Check that it was not changed within a month.
var lastUpdated time.Time
rows.Scan(&lastUpdated)
if time.Now().Sub(lastUpdated) > 24*30*time.Hour {
rows.Close()
return errRecentlyChanged
func updateDbTrust(sourceID, targetID string, voteValue int, force bool) error {
if !force {
rows, err := db.Query("SELECT lastUpdated FROM trustVote WHERE sourceUser=? AND targetUser=?", sourceID, targetID)
if err != nil {
return err
}
if rows.Next() {
//Check that it was not changed within a month.
var lastUpdated time.Time
rows.Scan(&lastUpdated)
if time.Now().Sub(lastUpdated) > 24*30*time.Hour {
rows.Close()
return errRecentlyChanged
}
}
rows.Close()
}
rows.Close()
_, err = db.Exec("REPLACE INTO trustVote(sourceUser,targetUser,lastUpdated,trust) VALUES(?,?,?,?)", sourceID, targetID, time.Now(), voteValue)
_, err := db.Exec("REPLACE INTO trustVote(sourceUser,targetUser,lastUpdated,trust) VALUES(?,?,?,?)", sourceID, targetID, time.Now(), voteValue)
return err
}

@ -22,6 +22,15 @@ func createCustomVote(messageID, text string) (int, error) {
return int(lastID), nil
}
func createInviteVote(messageID, username, reason string) (int, error) {
result, err := db.Exec("INSERT INTO vote(messageId, name, type, finished) VALUES(?, ?, ?, ?)", messageID, username+":"+reason, "invite", false)
if err != nil {
return 0, err
}
lastID, err := result.LastInsertId()
return int(lastID), nil
}
func getVoteName(id int) (string, error) {
rows, err := db.Query("SELECT name FROM vote WHERE id=?", id)
if err != nil {

@ -23,6 +23,7 @@ func main() {
dg.AddHandler(messageCreate)
dg.AddHandler(checkForVote)
dg.AddHandler(checkForTrustUpdate)
dg.AddHandler(checkForInvite)
if err := dg.Open(); err != nil {
panic(err)
@ -57,6 +58,8 @@ func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
viewTrustLevel(s, m, command)
case "!invite":
createInvite(s, m, command)
case "!validate":
checkUseInvite(s, m, command)
case "!trust":
changeTrust(s, m, command)
}

@ -65,7 +65,7 @@ func getTotalTrust(s *discordgo.Session) (float64, error) {
}
func updateTrust(sourceID, targetID string, voteValue int) error {
err := updateDbTrust(sourceID, targetID, voteValue)
err := updateDbTrust(sourceID, targetID, voteValue, false)
if err != nil {
return err
}

@ -0,0 +1,41 @@
package main
import (
"fmt"
"strconv"
"strings"
"github.com/bwmarrin/discordgo"
)
const announceInviteChannel = "627165467269922864"
func createInviteEmbed(id int, name string) *discordgo.MessageEmbed {
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()
}
func handleInviteResult(s *discordgo.Session, id int, name string, isPositive bool) {
if !isPositive {
return
}
member, err := getMemberFromUserFriendlyName(s, strings.SplitN(name, ":", 2)[0])
if err != nil {
auditLog(s, "Error while getting member from user friendly name in invite result. "+err.Error())
return
}
err = s.GuildMemberRoleAdd(guildID, member.User.ID, memberRoleID)
if err != nil {
auditLog(s, fmt.Sprintf("Fail to give user <@%s> the member role: %s", member.User.ID, err.Error()))
return
}
s.ChannelMessageSend(announceInviteChannel, fmt.Sprintf("欢迎<@%s>的加入Welcome <@%s> to this server!", member.User.ID, member.User.ID))
choices, err := getAllVoteChoices(id)
if err != nil {
auditLog(s, "Error while pulling vote choices. "+err.Error())
return
}
for _, choice := range choices {
updateDbTrust(choice.UserID, member.User.ID, choice.Value, true)
}
}