go: Move discord into its own package

pull/8/head
Luther Wen Xu 2019-10-12 17:45:43 +07:00
parent 9332b2688e
commit d1588fffcf
Signed by: chanbakjsd
GPG Key ID: B7D77E3E9D102B70
16 changed files with 342 additions and 264 deletions

@ -1,147 +0,0 @@
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.
s.ChannelMessageDelete(m.ChannelID, m.ID)
s.ChannelMessageSend(
m.ChannelID,
m.Author.Mention()+",这个指令只能在私信中使用。\n"+m.Author.Mention()+", this command can only be used in DM.",
)
return false
}
return true
}
func membersOnly(s *discordgo.Session, m *discordgo.MessageCreate) bool {
member, err := s.GuildMember(guildID, m.Author.ID)
if err != nil {
s.ChannelMessageSend(
m.ChannelID,
m.Author.Mention()+",请在成为会员后才使用这个指令。\n"+m.Author.Mention()+", please use this command after you become a member.",
)
return false
}
for _, v := range member.Roles {
if v == memberRoleID {
return true
}
}
s.ChannelMessageSend(
m.ChannelID,
m.Author.Mention()+",请在成为会员后才使用这个指令。\n"+m.Author.Mention()+", please use this command after you become a member.",
)
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 {
return err
}
_, err = s.ChannelMessageSend(channel.ID, message)
return err
}
func auditLog(s *discordgo.Session, message string) {
_, err := s.ChannelMessageSend(auditChannel, message)
if err != nil {
fmt.Println("==Audit Log==")
fmt.Println(message)
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,75 @@
package backend
import (
"errors"
"strings"
"github.com/bwmarrin/discordgo"
"TerraOceanBot/discord/config"
)
var ErrMemberNotFound = errors.New("discord/backend: the requested member was not found")
func GetAllMembers(s *discordgo.Session) ([]*discordgo.Member, error) {
initial, err := s.GuildMembers(config.GuildID, "", 1000)
if err != nil {
return nil, err
}
next := initial[len(initial)-1].User.ID
for next != "" {
nextArray, err := s.GuildMembers(config.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
}
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
}

@ -1,4 +1,4 @@
package main package backend
import ( import (
"errors" "errors"
@ -6,28 +6,29 @@ import (
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
"TerraOceanBot/db" "TerraOceanBot/db"
"TerraOceanBot/discord/config"
) )
var trustCache map[string]float64 var trustCache map[string]float64
var errNotMember = errors.New("trust: only members have trust value") var ErrNotMember = errors.New("trust: only members have trust value")
func getTrust(s *discordgo.Session, discordID string) (float64, error) { func GetTrust(s *discordgo.Session, discordID string) (float64, error) {
if v, ok := trustCache[discordID]; ok { if v, ok := trustCache[discordID]; ok {
return v, nil return v, nil
} }
member, err := s.GuildMember(guildID, discordID) member, err := s.GuildMember(config.GuildID, discordID)
if err != nil { if err != nil {
return 0.0, err return 0.0, err
} }
isMember := false isMember := false
for _, role := range member.Roles { for _, role := range member.Roles {
if role == memberRoleID { if role == config.MemberRoleID {
isMember = true isMember = true
} }
} }
if !isMember { if !isMember {
return 0.0, errNotMember return 0.0, ErrNotMember
} }
votes, err := db.GetTrustVote(discordID) votes, err := db.GetTrustVote(discordID)
if err != nil { if err != nil {
@ -41,8 +42,8 @@ func getTrust(s *discordgo.Session, discordID string) (float64, error) {
return total / float64(len(votes)), nil return total / float64(len(votes)), nil
} }
func getTotalTrust(s *discordgo.Session) (float64, error) { func GetTotalTrust(s *discordgo.Session) (float64, error) {
members, err := getAllMembers(s) members, err := GetAllMembers(s)
if err != nil { if err != nil {
return 0.0, err return 0.0, err
} }
@ -50,14 +51,14 @@ func getTotalTrust(s *discordgo.Session) (float64, error) {
for _, member := range members { for _, member := range members {
isMember := false isMember := false
for _, role := range member.Roles { for _, role := range member.Roles {
if role == memberRoleID { if role == config.MemberRoleID {
isMember = true isMember = true
} }
} }
if !isMember { if !isMember {
continue continue
} }
trust, err := getTrust(s, member.User.ID) trust, err := GetTrust(s, member.User.ID)
if err != nil { if err != nil {
return 0.0, err return 0.0, err
} }
@ -66,7 +67,7 @@ func getTotalTrust(s *discordgo.Session) (float64, error) {
return total, nil return total, nil
} }
func updateTrust(sourceID, targetID string, voteValue int) error { func UpdateTrust(sourceID, targetID string, voteValue int) error {
err := db.UpdateTrust(sourceID, targetID, voteValue, false) err := db.UpdateTrust(sourceID, targetID, voteValue, false)
if err != nil { if err != nil {
return err return err

@ -0,0 +1,8 @@
package config
const GuildID = "626424729234046987"
const MemberRoleID = "626434632614805526"
const AuditChannel = "631789849929711627"
const VoteChannel = "627164246056239104"
const AnnounceCustomChannel = "627165467269922864"
const VoteSuggestionChannel = "627164561644191744"

@ -0,0 +1,41 @@
package discord
import (
"fmt"
"os"
"os/signal"
"strings"
"sync"
"syscall"
"github.com/bwmarrin/discordgo"
"TerraOceanBot/discord/modules"
)
func StartBot(token string, wg *sync.WaitGroup) {
defer wg.Done()
dg, err := discordgo.New("Bot " + strings.TrimSpace(token))
if err != nil {
panic(err)
}
dg.AddHandler(ProcessCommand)
dg.AddHandler(ProcessVote)
dg.AddHandler(modules.CheckForVote)
dg.AddHandler(modules.CheckForTrustUpdate)
dg.AddHandler(modules.CheckForInvite)
if err := dg.Open(); err != nil {
panic(err)
}
fmt.Println("Bot is now running. Press CTRL-C to exit.")
go modules.ListenToVoteFinishes(dg)
sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
<-sc
dg.Close()
fmt.Println("Discordgo exited successfully.")
}

@ -0,0 +1,31 @@
package discord
import (
"strings"
"github.com/bwmarrin/discordgo"
"TerraOceanBot/discord/config"
"TerraOceanBot/discord/modules"
)
func ProcessCommand(s *discordgo.Session, m *discordgo.MessageCreate) {
if m.Author.ID == s.State.User.ID {
return
}
command := strings.Split(m.Content, " ")
for _, v := range modules.Commands {
if v.Name == command[0] {
v.Handler(s, m, command)
return
}
}
}
func ProcessVote(s *discordgo.Session, m *discordgo.MessageCreate) {
//TODO Factorize this code into a command
if m.ChannelID == config.VoteSuggestionChannel {
modules.VoteSuggestion(s, m)
}
}

@ -1,10 +1,12 @@
package main package modules
import ( import (
"fmt" "fmt"
"strings" "strings"
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
"TerraOceanBot/discord/backend"
) )
//adminID is my Discord user ID (chanbakjsd#7968). //adminID is my Discord user ID (chanbakjsd#7968).
@ -45,12 +47,12 @@ func viewTrustLevel(s *discordgo.Session, m *discordgo.MessageCreate, command []
return return
} }
if len(command) > 1 { if len(command) > 1 {
value, err := getTrust(s, command[1]) value, err := backend.GetTrust(s, command[1])
if err != nil { if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error()) s.ChannelMessageSend(m.ChannelID, err.Error())
return return
} }
total, err := getTotalTrust(s) total, err := backend.GetTotalTrust(s)
if err != nil { if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error()) s.ChannelMessageSend(m.ChannelID, err.Error())
return return
@ -59,20 +61,20 @@ func viewTrustLevel(s *discordgo.Session, m *discordgo.MessageCreate, command []
return return
} }
total, err := getTotalTrust(s) total, err := backend.GetTotalTrust(s)
if err != nil { if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error()) s.ChannelMessageSend(m.ChannelID, err.Error())
return return
} }
message := "" message := ""
members, err := getAllMembers(s) members, err := backend.GetAllMembers(s)
if err != nil { if err != nil {
s.ChannelMessageSend(m.ChannelID, err.Error()) s.ChannelMessageSend(m.ChannelID, err.Error())
return return
} }
for _, v := range members { for _, v := range members {
value, err := getTrust(s, v.User.ID) value, err := backend.GetTrust(s, v.User.ID)
if err == errNotMember { if err == backend.ErrNotMember {
continue continue
} }
if err != nil { if err != nil {

@ -0,0 +1,35 @@
package modules
import "github.com/bwmarrin/discordgo"
type Command struct {
Name string
Handler func(s *discordgo.Session, m *discordgo.MessageCreate, commands []string)
}
var Commands = []Command{
Command{
Name: "!sendas",
Handler: sendAs,
},
Command{
Name: "!editas",
Handler: editAs,
},
Command{
Name: "!peektrust",
Handler: viewTrustLevel,
},
Command{
Name: "!invite",
Handler: createInvite,
},
Command{
Name: "!validate",
Handler: checkUseInvite,
},
Command{
Name: "!trust",
Handler: changeTrust,
},
}

@ -1,4 +1,4 @@
package main package modules
import "github.com/bwmarrin/discordgo" import "github.com/bwmarrin/discordgo"

@ -1,4 +1,4 @@
package main package modules
import ( import (
"fmt" "fmt"
@ -7,6 +7,7 @@ import (
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
"TerraOceanBot/db" "TerraOceanBot/db"
"TerraOceanBot/discord/config"
) )
var pendingInviteConfirmation = make(map[string]invite) var pendingInviteConfirmation = make(map[string]invite)
@ -95,7 +96,7 @@ func checkUseInvite(s *discordgo.Session, m *discordgo.MessageCreate, command []
} }
db.UseInvite(messageSplit[1]) db.UseInvite(messageSplit[1])
member, err := s.GuildMember(guildID, inviter) member, err := s.GuildMember(config.GuildID, inviter)
if err != nil { if err != nil {
sendPrivateMessage(s, m.Author.ID, "验证码制造者不是会员。\nValidation code creator is no longer a member.") sendPrivateMessage(s, m.Author.ID, "验证码制造者不是会员。\nValidation code creator is no longer a member.")
return return
@ -103,7 +104,7 @@ func checkUseInvite(s *discordgo.Session, m *discordgo.MessageCreate, command []
isMember := false isMember := false
for _, v := range member.Roles { for _, v := range member.Roles {
if v == memberRoleID { if v == config.MemberRoleID {
isMember = true isMember = true
} }
} }
@ -131,7 +132,7 @@ func checkUseInvite(s *discordgo.Session, m *discordgo.MessageCreate, command []
sendPrivateMessage(s, m.Author.ID, "已向验证码制造者发送了请求。\nSent a request to use the validation code to its creator.") sendPrivateMessage(s, m.Author.ID, "已向验证码制造者发送了请求。\nSent a request to use the validation code to its creator.")
} }
func checkForInvite(s *discordgo.Session, r *discordgo.MessageReactionAdd) { func CheckForInvite(s *discordgo.Session, r *discordgo.MessageReactionAdd) {
if r.UserID == s.State.User.ID { if r.UserID == s.State.User.ID {
return return
} }
@ -153,7 +154,7 @@ func checkForInvite(s *discordgo.Session, r *discordgo.MessageReactionAdd) {
s.ChannelMessageSend(r.ChannelID, "已同意验证码的使用。该验证码已被无效化。\nUse of validation code accepted. This validation code has been invalidated.") 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...") msg, err := s.ChannelMessageSend(config.VoteChannel, "正在准备新的一个投票…… Preparing for the next vote...")
if err != nil { if err != nil {
sendPrivateMessage(s, r.UserID, "创造投票失败。Failed to create vote.") sendPrivateMessage(s, r.UserID, "创造投票失败。Failed to create vote.")
auditLog(s, auditLog(s,
@ -170,13 +171,13 @@ func checkForInvite(s *discordgo.Session, r *discordgo.MessageReactionAdd) {
return return
} }
auditLog(s, fmt.Sprintf("Vote ID %d has been created by <@%s>.", id, r.UserID)) auditLog(s, fmt.Sprintf("Vote ID %d has been created by <@%s>.", id, r.UserID))
s.ChannelMessageEdit(voteChannel, msg.ID, "") s.ChannelMessageEdit(config.VoteChannel, msg.ID, "")
s.ChannelMessageEditEmbed(voteChannel, msg.ID, createInviteEmbed(id, invite.User+":"+invite.Reason)) s.ChannelMessageEditEmbed(config.VoteChannel, msg.ID, createInviteEmbed(id, invite.User+":"+invite.Reason))
s.MessageReactionAdd(voteChannel, msg.ID, emojiX) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiX)
s.MessageReactionAdd(voteChannel, msg.ID, emojiOne) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiOne)
s.MessageReactionAdd(voteChannel, msg.ID, emojiTwo) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiTwo)
s.MessageReactionAdd(voteChannel, msg.ID, emojiThree) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiThree)
s.MessageReactionAdd(voteChannel, msg.ID, emojiFour) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiFour)
s.MessageReactionAdd(voteChannel, msg.ID, emojiFive) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiFive)
s.MessageReactionAdd(voteChannel, msg.ID, emojiCheck) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiCheck)
} }

@ -0,0 +1,78 @@
package modules
import (
"fmt"
"github.com/bwmarrin/discordgo"
"TerraOceanBot/discord/config"
)
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.
s.ChannelMessageDelete(m.ChannelID, m.ID)
s.ChannelMessageSend(
m.ChannelID,
m.Author.Mention()+",这个指令只能在私信中使用。\n"+m.Author.Mention()+", this command can only be used in DM.",
)
return false
}
return true
}
func membersOnly(s *discordgo.Session, m *discordgo.MessageCreate) bool {
member, err := s.GuildMember(config.GuildID, m.Author.ID)
if err != nil {
s.ChannelMessageSend(
m.ChannelID,
m.Author.Mention()+",请在成为会员后才使用这个指令。\n"+m.Author.Mention()+", please use this command after you become a member.",
)
return false
}
for _, v := range member.Roles {
if v == config.MemberRoleID {
return true
}
}
s.ChannelMessageSend(
m.ChannelID,
m.Author.Mention()+",请在成为会员后才使用这个指令。\n"+m.Author.Mention()+", please use this command after you become a member.",
)
return false
}
func nonMembersOnly(s *discordgo.Session, m *discordgo.MessageCreate) bool {
member, err := s.GuildMember(config.GuildID, m.Author.ID)
if err != nil {
return false
}
for _, v := range member.Roles {
if v == config.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 {
return err
}
_, err = s.ChannelMessageSend(channel.ID, message)
return err
}
func auditLog(s *discordgo.Session, message string) {
_, err := s.ChannelMessageSend(config.AuditChannel, message)
if err != nil {
fmt.Println("==Audit Log==")
fmt.Println(message)
fmt.Println(err)
}
}

@ -1,4 +1,4 @@
package main package modules
import ( import (
"fmt" "fmt"
@ -7,6 +7,7 @@ import (
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
"TerraOceanBot/db" "TerraOceanBot/db"
"TerraOceanBot/discord/backend"
) )
var trustMessage = make(map[string]string) var trustMessage = make(map[string]string)
@ -23,8 +24,8 @@ func changeTrust(s *discordgo.Session, m *discordgo.MessageCreate, command []str
return return
} }
member, err := getMemberFromUserFriendlyName(s, strings.SplitN(m.Content, " ", 2)[1]) member, err := backend.GetMemberFromUserFriendlyName(s, strings.SplitN(m.Content, " ", 2)[1])
if err == errMemberNotFound { if err == backend.ErrMemberNotFound {
s.ChannelMessageSend(m.ChannelID, "无法找到您所要求的玩家。\nCannot find the requested player.") s.ChannelMessageSend(m.ChannelID, "无法找到您所要求的玩家。\nCannot find the requested player.")
return return
} }
@ -61,7 +62,7 @@ func createTrustEmbed(username, nick string) *discordgo.MessageEmbed {
return embed.Build() return embed.Build()
} }
func checkForTrustUpdate(s *discordgo.Session, r *discordgo.MessageReactionAdd) { func CheckForTrustUpdate(s *discordgo.Session, r *discordgo.MessageReactionAdd) {
if r.UserID == s.State.User.ID { if r.UserID == s.State.User.ID {
return return
} }
@ -92,7 +93,7 @@ func checkForTrustUpdate(s *discordgo.Session, r *discordgo.MessageReactionAdd)
return return
} }
err := updateTrust(r.UserID, target, value) err := backend.UpdateTrust(r.UserID, target, value)
if err == db.ErrRecentlyChanged { if err == db.ErrRecentlyChanged {
s.ChannelMessageSend(r.ChannelID, "你在一个月内有设定过该名玩家的分数。你这次的更动没有被记录。\nYou have changed your score for this player within the last month. Your change was not recorded.") s.ChannelMessageSend(r.ChannelID, "你在一个月内有设定过该名玩家的分数。你这次的更动没有被记录。\nYou have changed your score for this player within the last month. Your change was not recorded.")
return return

@ -1,4 +1,4 @@
package main package modules
import ( import (
"fmt" "fmt"
@ -8,6 +8,7 @@ import (
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
"TerraOceanBot/db" "TerraOceanBot/db"
"TerraOceanBot/discord/config"
) )
type voteType struct { type voteType struct {
@ -26,9 +27,6 @@ var voteTypes = map[string]voteType{
}, },
} }
const voteChannel = "627164246056239104"
const announceCustomChannel = "627165467269922864"
const ( const (
emojiOne = "1⃣" emojiOne = "1⃣"
emojiTwo = "2⃣" emojiTwo = "2⃣"
@ -39,7 +37,7 @@ const (
emojiX = "❌" emojiX = "❌"
) )
func checkForVote(s *discordgo.Session, r *discordgo.MessageReactionAdd) { func CheckForVote(s *discordgo.Session, r *discordgo.MessageReactionAdd) {
if r.UserID == s.State.User.ID { if r.UserID == s.State.User.ID {
return return
} }
@ -105,7 +103,7 @@ func checkForVote(s *discordgo.Session, r *discordgo.MessageReactionAdd) {
checkForVoteResult(s, voteID) checkForVoteResult(s, voteID)
} }
func voteSuggestion(s *discordgo.Session, m *discordgo.MessageCreate) { func VoteSuggestion(s *discordgo.Session, m *discordgo.MessageCreate) {
s.ChannelMessageDelete(m.ChannelID, m.ID) s.ChannelMessageDelete(m.ChannelID, m.ID)
args := strings.SplitN(m.Content, " ", 2) args := strings.SplitN(m.Content, " ", 2)
@ -120,7 +118,7 @@ func voteSuggestion(s *discordgo.Session, m *discordgo.MessageCreate) {
switch args[0] { switch args[0] {
case "custom": case "custom":
msg, err := s.ChannelMessageSend(voteChannel, "正在准备新的一个投票…… Preparing for the next vote...") msg, err := s.ChannelMessageSend(config.VoteChannel, "正在准备新的一个投票…… Preparing for the next vote...")
if err != nil { if err != nil {
sendPrivateMessage(s, m.Author.ID, "创造投票失败。Failed to create vote.") sendPrivateMessage(s, m.Author.ID, "创造投票失败。Failed to create vote.")
auditLog(s, auditLog(s,
@ -137,13 +135,13 @@ func voteSuggestion(s *discordgo.Session, m *discordgo.MessageCreate) {
return return
} }
auditLog(s, fmt.Sprintf("Vote ID %d has been created by <@%s>.", id, m.Author.ID)) auditLog(s, fmt.Sprintf("Vote ID %d has been created by <@%s>.", id, m.Author.ID))
s.ChannelMessageEdit(voteChannel, msg.ID, "") s.ChannelMessageEdit(config.VoteChannel, msg.ID, "")
s.ChannelMessageEditEmbed(voteChannel, msg.ID, createCustomEmbed(id, args[1])) s.ChannelMessageEditEmbed(config.VoteChannel, msg.ID, createCustomEmbed(id, args[1]))
s.MessageReactionAdd(voteChannel, msg.ID, emojiOne) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiOne)
s.MessageReactionAdd(voteChannel, msg.ID, emojiTwo) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiTwo)
s.MessageReactionAdd(voteChannel, msg.ID, emojiThree) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiThree)
s.MessageReactionAdd(voteChannel, msg.ID, emojiFour) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiFour)
s.MessageReactionAdd(voteChannel, msg.ID, emojiFive) s.MessageReactionAdd(config.VoteChannel, msg.ID, emojiFive)
default: default:
sendPrivateMessage(s, m.Author.ID, "未知投票种类:"+args[0]+"\nUnknown vote type: "+args[0]) sendPrivateMessage(s, m.Author.ID, "未知投票种类:"+args[0]+"\nUnknown vote type: "+args[0])
} }
@ -154,5 +152,5 @@ func createCustomEmbed(id int, name string) *discordgo.MessageEmbed {
} }
func announceCustomResult(s *discordgo.Session, id int, name string, isPositive bool) { func announceCustomResult(s *discordgo.Session, id int, name string, isPositive bool) {
s.ChannelMessageSendEmbed(announceCustomChannel, showVoteStatus(createCustomEmbed(id, name), isPositive)) s.ChannelMessageSendEmbed(config.AnnounceCustomChannel, showVoteStatus(createCustomEmbed(id, name), isPositive))
} }

@ -1,4 +1,4 @@
package main package modules
import ( import (
"fmt" "fmt"
@ -8,6 +8,8 @@ import (
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
"TerraOceanBot/db" "TerraOceanBot/db"
"TerraOceanBot/discord/backend"
"TerraOceanBot/discord/config"
) )
const announceInviteChannel = "627165467269922864" const announceInviteChannel = "627165467269922864"
@ -21,12 +23,12 @@ func handleInviteResult(s *discordgo.Session, id int, name string, isPositive bo
if !isPositive { if !isPositive {
return return
} }
member, err := getMemberFromUserFriendlyName(s, strings.SplitN(name, ":", 2)[0]) member, err := backend.GetMemberFromUserFriendlyName(s, strings.SplitN(name, ":", 2)[0])
if err != nil { if err != nil {
auditLog(s, "Error while getting member from user friendly name in invite result. "+err.Error()) auditLog(s, "Error while getting member from user friendly name in invite result. "+err.Error())
return return
} }
err = s.GuildMemberRoleAdd(guildID, member.User.ID, memberRoleID) err = s.GuildMemberRoleAdd(config.GuildID, member.User.ID, config.MemberRoleID)
if err != nil { if err != nil {
auditLog(s, fmt.Sprintf("Fail to give user <@%s> the member role: %s", member.User.ID, err.Error())) auditLog(s, fmt.Sprintf("Fail to give user <@%s> the member role: %s", member.User.ID, err.Error()))
return return

@ -1,4 +1,4 @@
package main package modules
import ( import (
"fmt" "fmt"
@ -8,6 +8,8 @@ import (
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
"TerraOceanBot/db" "TerraOceanBot/db"
"TerraOceanBot/discord/backend"
"TerraOceanBot/discord/config"
) )
type confirmedResult struct { type confirmedResult struct {
@ -18,7 +20,7 @@ type confirmedResult struct {
var voteMutex sync.Mutex var voteMutex sync.Mutex
var toAnnounceResultList []confirmedResult var toAnnounceResultList []confirmedResult
func listenToVoteFinishes(s *discordgo.Session) { func ListenToVoteFinishes(s *discordgo.Session) {
for { for {
voteMutex.Lock() voteMutex.Lock()
for _, v := range toAnnounceResultList { for _, v := range toAnnounceResultList {
@ -29,7 +31,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(voteChannel, messageID, showVoteStatus(voteTypes[voteType].EmbedBuilder(v.VoteID, voteName), v.IsPositive)) s.ChannelMessageEditEmbed(config.VoteChannel, messageID, showVoteStatus(voteTypes[voteType].EmbedBuilder(v.VoteID, voteName), v.IsPositive))
voteTypes[voteType].ResultHandler(s, v.VoteID, voteName, v.IsPositive) voteTypes[voteType].ResultHandler(s, v.VoteID, voteName, v.IsPositive)
} }
toAnnounceResultList = toAnnounceResultList[:0] toAnnounceResultList = toAnnounceResultList[:0]
@ -50,7 +52,7 @@ func checkForVoteResult(s *discordgo.Session, id int) {
if vote.Value == db.ForceRejectionVote { if vote.Value == db.ForceRejectionVote {
absoluteRejectionVote = true absoluteRejectionVote = true
} }
trust, err := getTrust(s, vote.UserID) trust, err := backend.GetTrust(s, vote.UserID)
if err != nil { if err != nil {
auditLog(s, fmt.Sprintf("Error while getting vote trust for user ID %d: %s", vote.UserID, err.Error())) auditLog(s, fmt.Sprintf("Error while getting vote trust for user ID %d: %s", vote.UserID, err.Error()))
return return
@ -59,7 +61,7 @@ func checkForVoteResult(s *discordgo.Session, id int) {
totalTrust += float64(trust) totalTrust += float64(trust)
} }
totalGlobalTrust, err := getTotalTrust(s) totalGlobalTrust, err := backend.GetTotalTrust(s)
if err != nil { if err != nil {
auditLog(s, fmt.Sprintf("Error while getting total vote trust: %s", err.Error())) auditLog(s, fmt.Sprintf("Error while getting total vote trust: %s", err.Error()))
return return

@ -1,66 +1,16 @@
package main package main
import ( import (
"fmt"
"io/ioutil" "io/ioutil"
"os" "sync"
"os/signal"
"strings"
"syscall"
"github.com/bwmarrin/discordgo" "TerraOceanBot/discord"
) )
const voteSuggestionChannel = "627164561644191744"
func main() { func main() {
token, _ := ioutil.ReadFile("token.txt") token, _ := ioutil.ReadFile("token.txt")
dg, err := discordgo.New("Bot " + strings.TrimSpace(string(token))) wg := sync.WaitGroup{}
if err != nil { wg.Add(1)
panic(err) go discord.StartBot(string(token), &wg)
} wg.Wait()
dg.AddHandler(messageCreate)
dg.AddHandler(checkForVote)
dg.AddHandler(checkForTrustUpdate)
dg.AddHandler(checkForInvite)
if err := dg.Open(); err != nil {
panic(err)
}
fmt.Println("Bot is now running. Press CTRL-C to exit.")
go listenToVoteFinishes(dg)
sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
<-sc
dg.Close()
}
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
if m.Author.ID == s.State.User.ID {
return
}
if m.ChannelID == voteSuggestionChannel {
voteSuggestion(s, m)
return
}
command := strings.Split(m.Content, " ")
switch command[0] {
case "!sendas":
sendAs(s, m, command)
case "!editas":
editAs(s, m, command)
case "!peektrust":
viewTrustLevel(s, m, command)
case "!invite":
createInvite(s, m, command)
case "!validate":
checkUseInvite(s, m, command)
case "!trust":
changeTrust(s, m, command)
}
} }