From 6b3761d98e583fa6fea7e0c450781d8b527c5b79 Mon Sep 17 00:00:00 2001 From: Luther Wen Xu Date: Wed, 9 Oct 2019 22:13:59 +0800 Subject: [PATCH] go: Implement invite code creation It is now possible to create invite code using '!invite ' --- GoBot/.gitignore | 1 + GoBot/db.go | 68 ++++++++++++++++++++++++++++++++++++++++++++ GoBot/go.mod | 5 +++- GoBot/go.sum | 2 ++ GoBot/invite.go | 52 +++++++++++++++++++++++++++++++++ GoBot/main.go | 2 ++ GoBot/messageUtil.go | 40 ++++++++++++++++++++++++++ 7 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 GoBot/db.go create mode 100644 GoBot/invite.go create mode 100644 GoBot/messageUtil.go diff --git a/GoBot/.gitignore b/GoBot/.gitignore index c8266e8..a9e32c7 100644 --- a/GoBot/.gitignore +++ b/GoBot/.gitignore @@ -1 +1,2 @@ token.txt +terraocean.db diff --git a/GoBot/db.go b/GoBot/db.go new file mode 100644 index 0000000..fd65d25 --- /dev/null +++ b/GoBot/db.go @@ -0,0 +1,68 @@ +package main + +import ( + "database/sql" + "errors" + + //Import this driver to be used by the SQL package. + _ "github.com/mattn/go-sqlite3" +) + +var db *sql.DB + +var errNotFound = errors.New("db: the requested entry was not found") +var errAlreadyExists = errors.New("db: attempting to write to an entry that already exists") +var errInviteUsed = errors.New("db: the requested invite has already been used") + +func init() { + var err error + db, err = sql.Open("sqlite3", "terraocean.db") + if err != nil { + panic(err) + } + _, err = db.Exec("CREATE TABLE IF NOT EXISTS invite (code TEXT, owner TEXT, used BOOLEAN)") + if err != nil { + panic(err) + } +} + +func getInviteOwner(inviteCode string) (string, error) { + rows, err := db.Query("SELECT owner, used FROM invite WHERE code=?", inviteCode) + if err != nil { + return "", err + } + if rows.Next() { + var owner string + var used bool + err := rows.Scan(&owner, &used) + if err != nil { + return "", err + } + if used { + return "", errInviteUsed + } + return owner, nil + } + return "", errNotFound +} + +func setInviteOwner(inviteCode, owner string) error { + _, err := getInviteOwner(inviteCode) + if err == nil { + return errAlreadyExists + } + if err != errNotFound { + return err + } + _, err = db.Exec("INSERT INTO invite(code, owner, used) VALUES(?,?,?)", inviteCode, owner, false) + return err +} + +func useInvite(inviteCode string) error { + owner, err := getInviteOwner(inviteCode) + if err != nil { + return err + } + _, err = db.Exec("REPLACE INTO invite(code, owner, used) VALUES(?,?,?)", inviteCode, owner, true) + return err +} diff --git a/GoBot/go.mod b/GoBot/go.mod index 9a73011..eb8cbb5 100644 --- a/GoBot/go.mod +++ b/GoBot/go.mod @@ -2,4 +2,7 @@ module TerraOceanBot go 1.13 -require github.com/bwmarrin/discordgo v0.19.0 +require ( + github.com/bwmarrin/discordgo v0.19.0 + github.com/mattn/go-sqlite3 v1.11.0 +) diff --git a/GoBot/go.sum b/GoBot/go.sum index ef56b25..3f062d8 100644 --- a/GoBot/go.sum +++ b/GoBot/go.sum @@ -2,5 +2,7 @@ github.com/bwmarrin/discordgo v0.19.0 h1:kMED/DB0NR1QhRcalb85w0Cu3Ep2OrGAqZH1R5a github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q= +github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/GoBot/invite.go b/GoBot/invite.go new file mode 100644 index 0000000..af84e45 --- /dev/null +++ b/GoBot/invite.go @@ -0,0 +1,52 @@ +package main + +import "github.com/bwmarrin/discordgo" + +func createInvite(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, "指令的使用方法是`!invite <你所要设置的验证码>`.\nUsage: `!invite `") + return + } + if len(command) > 2 { + s.ChannelMessageSend(m.ChannelID, "所提供的验证码不得有任何空格。\nThe provided validation code cannot contain any spaces.") + return + } + + err := setInviteOwner(command[1], m.Author.ID) + switch err { + case errAlreadyExists: + owner, _ := getInviteOwner(command[1]) + if owner == m.Author.ID { + s.ChannelMessageSend( + m.ChannelID, + "这个验证码归你所有,它仍然未被使用。请把它告诉你要邀请的人。\nThis validation code belongs to you. Please give it to the person you want to invite.", + ) + return + } + s.ChannelMessageSend( + m.ChannelID, + "这个验证码已被其他会员注册。请使用别的验证码。\nThis validation code is already registered. Please try another one.", + ) + case errInviteUsed: + s.ChannelMessageSend( + m.ChannelID, + "这个验证码已被使用。请使用别的验证码。\nThis validation code has already been used. Please try another one.", + ) + case nil: + s.ChannelMessageSend( + m.ChannelID, + "这个验证码现在属于你了。请好好保管并把它交给你要邀请的人。\nThis validation code now belongs to you! Pass it on to the person you want to invite.", + ) + default: + s.ChannelMessageSend( + m.ChannelID, + "不明错误已发生,请把这个错误信息发在群里。\nAn unknown error has occurred. Please pass this error message on.\n"+err.Error(), + ) + } +} diff --git a/GoBot/main.go b/GoBot/main.go index a1e4626..ddf4728 100644 --- a/GoBot/main.go +++ b/GoBot/main.go @@ -41,5 +41,7 @@ func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { sendAs(s, m, command) case "!editas": editAs(s, m, command) + case "!invite": + createInvite(s, m, command) } } diff --git a/GoBot/messageUtil.go b/GoBot/messageUtil.go new file mode 100644 index 0000000..fb4c911 --- /dev/null +++ b/GoBot/messageUtil.go @@ -0,0 +1,40 @@ +package main + +import "github.com/bwmarrin/discordgo" + +const guildID = "626424729234046987" +const memberRoleID = "626434632614805526" + +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 +}