go: Implement '!trust' command

master
Luther Wen Xu 2019-10-11 22:29:07 +07:00
parent 80f2d9c220
commit a8fbc2390f
Signed by untrusted user: chanbakjsd
GPG Key ID: B7D77E3E9D102B70
6 changed files with 198 additions and 25 deletions

@ -1,16 +1,19 @@
package main
import (
"errors"
"fmt"
"strings"
"github.com/bwmarrin/discordgo"
)
const guildID = "626424729234046987"
const memberRoleID = "626434632614805526"
const auditChannel = "631789849929711627"
var errMemberNotFound = errors.New("messageutil: the requested member was not found")
func enforceDM(s *discordgo.Session, m *discordgo.MessageCreate) bool {
if m.GuildID != "" {
//This command can only be used in DM to protect the invite creator.
@ -62,3 +65,66 @@ func auditLog(s *discordgo.Session, message string) {
fmt.Println(err)
}
}
func getMemberFromUserFriendlyName(s *discordgo.Session, user string) (*discordgo.Member, error) {
allMembers, err := getAllMembers(s)
if err != nil {
return nil, err
}
if strings.HasPrefix(user, "@") {
user = strings.TrimPrefix(user, "@")
} else if strings.HasSuffix(user, ">") {
if strings.HasPrefix(user, "<@!") {
user = strings.TrimSuffix(strings.TrimPrefix(user, "<@!"), ">")
} else if strings.HasPrefix(user, "<@") {
user = strings.TrimSuffix(strings.TrimPrefix(user, "<@"), ">")
}
}
if strings.ContainsRune(user, '#') {
list := strings.Split(user, "#")
username := strings.Join(list[:len(list)-1], "#")
discriminator := list[len(list)-1]
for _, v := range allMembers {
if v.User.Username == username && v.User.Discriminator == discriminator {
return v, nil
}
}
}
for _, v := range allMembers {
if v.User.ID == user {
return v, nil
}
}
for _, v := range allMembers {
if v.Nick == user {
return v, nil
}
}
for _, v := range allMembers {
if v.User.Username == user {
return v, nil
}
}
return nil, errMemberNotFound
}
func getAllMembers(s *discordgo.Session) ([]*discordgo.Member, error) {
initial, err := s.GuildMembers(guildID, "", 1000)
if err != nil {
return nil, err
}
next := initial[len(initial)-1].User.ID
for next != "" {
nextArray, err := s.GuildMembers(guildID, next, 1000)
if err != nil {
return nil, err
}
if len(nextArray) == 0 {
next = ""
} else {
next = nextArray[len(nextArray)-1].User.ID
initial = append(initial, nextArray...)
}
}
return initial, nil
}

@ -0,0 +1,102 @@
package main
import (
"fmt"
"strings"
"github.com/bwmarrin/discordgo"
)
var trustMessage = make(map[string]string)
func changeTrust(s *discordgo.Session, m *discordgo.MessageCreate, command []string) {
if !enforceDM(s, m) {
return
}
if !membersOnly(s, m) {
return
}
if len(command) < 2 {
s.ChannelMessageSend(m.ChannelID, "指令的使用方法是`!trust <你要改信任度的人>`.\nUsage: `!trust <the user>`")
return
}
member, err := getMemberFromUserFriendlyName(s, strings.SplitN(m.Content, " ", 2)[1])
if err == errMemberNotFound {
s.ChannelMessageSend(m.ChannelID, "无法找到您所要求的玩家。\nCannot find the requested player.")
return
}
if err != nil {
auditLog(s, fmt.Sprintf("Error while processing change trust request for <@%s>: %s", m.Author.ID, err.Error()))
return
}
message, err := s.ChannelMessageSendEmbed(
m.ChannelID,
createTrustEmbed(member.User.Username+"#"+member.User.Discriminator, member.Nick),
)
if err != nil {
auditLog(s, fmt.Sprintf("Error while sending change trust request for <@%s>: %s", m.Author.ID, err.Error()))
return
}
trustMessage[message.ID] = member.User.ID
s.MessageReactionAdd(m.ChannelID, message.ID, emojiOne)
s.MessageReactionAdd(m.ChannelID, message.ID, emojiTwo)
s.MessageReactionAdd(m.ChannelID, message.ID, emojiThree)
s.MessageReactionAdd(m.ChannelID, message.ID, emojiFour)
s.MessageReactionAdd(m.ChannelID, message.ID, emojiFive)
s.MessageReactionAdd(m.ChannelID, message.ID, emojiCheck)
}
func createTrustEmbed(username, nick string) *discordgo.MessageEmbed {
embed := newEmbed().SetColour(0x00FFFF).SetTitle("更新玩家评分Update Player Score").AddField("ID", username)
if nick != "" {
embed.AddField("昵称Nickname", nick)
}
embed.AddField("提醒Reminder", "你一个月只能更换对一个玩家的评分一次。You can only change your trust towards a player once every month.")
return embed.Build()
}
func checkForTrustUpdate(s *discordgo.Session, r *discordgo.MessageReactionAdd) {
if r.UserID == s.State.User.ID {
return
}
target, ok := trustMessage[r.MessageID]
if !ok {
return
}
var value int
switch r.Emoji.Name {
case emojiOne:
value = 1
case emojiTwo:
value = 2
case emojiThree:
value = 3
case emojiFour:
value = 4
case emojiFive:
value = 5
case emojiCheck:
value = nuclearOptionVote
default:
auditLog(s, "Reaction "+r.Emoji.Name+" was added to trust message ID "+r.MessageID)
return
}
err := updateTrust(r.UserID, target, value)
if err == errRecentlyChanged {
s.ChannelMessageSend(r.ChannelID, "你在一个月内有设定过该名玩家的分数。你这次的更动没有被记录。\nYou have changed your score for this player within the last month. Your change was not recorded.")
return
}
if err != nil {
auditLog(s, fmt.Sprintf("Error while changing the trust value for <@%s> with target <@%s>: %s", r.UserID, target, err.Error()))
return
}
s.ChannelMessageSend(r.ChannelID, "已改变你给这名玩家的分数已被记录。\nThe score for this player has been updated.")
}

@ -31,7 +31,7 @@ func init() {
if err != nil {
panic(err)
}
_, err = db.Exec("CREATE TABLE IF NOT EXISTS trustVote (sourceUser INTEGER, targetUser INTEGER, trust INTEGER, UNIQUE(sourceUser, targetUser))")
_, err = db.Exec("CREATE TABLE IF NOT EXISTS trustVote (sourceUser INTEGER, targetUser INTEGER, lastUpdated TIMEDATE, trust INTEGER, UNIQUE(sourceUser, targetUser))")
if err != nil {
panic(err)
}

@ -1,8 +1,11 @@
package main
import "errors"
import (
"errors"
"time"
)
var errForceRejectionOnApprovedPerson = errors.New("db: attempt to force reject a user that is already approved")
var errRecentlyChanged = errors.New("db: attempt to change the trust for a user twice in a month")
func getTrustVote(targetID string) ([]int, error) {
rows, err := db.Query("SELECT trust FROM trustVote WHERE targetUser=?", targetID)
@ -21,3 +24,23 @@ func getTrustVote(targetID string) ([]int, error) {
return array, nil
}
func updateTrust(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
}
}
rows.Close()
_, err = db.Exec("REPLACE INTO trustVote(sourceUser,targetUser,lastUpdated,trust) VALUES(?,?,?,?)", sourceID, targetID, time.Now(), voteValue)
return err
}

@ -22,6 +22,7 @@ func main() {
dg.AddHandler(messageCreate)
dg.AddHandler(checkForVote)
dg.AddHandler(checkForTrustUpdate)
if err := dg.Open(); err != nil {
panic(err)
@ -54,5 +55,7 @@ func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
editAs(s, m, command)
case "!invite":
createInvite(s, m, command)
case "!trust":
changeTrust(s, m, command)
}
}

@ -35,24 +35,3 @@ func getTotalTrust(s *discordgo.Session) (float64, error) {
}
return total, nil
}
func getAllMembers(s *discordgo.Session) ([]*discordgo.Member, error) {
initial, err := s.GuildMembers(guildID, "", 1000)
if err != nil {
return nil, err
}
next := initial[len(initial)-1].User.ID
for next != "" {
nextArray, err := s.GuildMembers(guildID, next, 1000)
if err != nil {
return nil, err
}
if len(nextArray) == 0 {
next = ""
} else {
next = nextArray[len(nextArray)-1].User.ID
initial = append(initial, nextArray...)
}
}
return initial, nil
}