From 0bd76d9c7b886390d3d581e198238891d3835a99 Mon Sep 17 00:00:00 2001 From: Luther Wen Xu Date: Tue, 12 May 2020 18:18:19 +0800 Subject: [PATCH] Refactor everything Well, practically it's a rewrite. --- commands/autorole.go | 37 +++++++++++++++++++++++++++++++ commands/commands.go | 49 +++++++++++++++++++++-------------------- humanify/strings.go | 35 ----------------------------- locale.toml | 7 ------ util/embed.go | 37 +++++++++++++++++++++++++++++++ util/error.go | 7 +++++- util/magic.go | 52 ++++++++++++++++++++++++++++++++++++++------ util/perm.go | 12 +++------- 8 files changed, 154 insertions(+), 82 deletions(-) create mode 100644 commands/autorole.go delete mode 100644 humanify/strings.go delete mode 100644 locale.toml create mode 100644 util/embed.go diff --git a/commands/autorole.go b/commands/autorole.go new file mode 100644 index 0000000..42f4584 --- /dev/null +++ b/commands/autorole.go @@ -0,0 +1,37 @@ +package commands + +import ( + "github.com/bwmarrin/discordgo" + + "gitea.teamortix.com/chanbakjsd/Milen/db" + "gitea.teamortix.com/chanbakjsd/Milen/util" +) + +func handleAutorole(dg *discordgo.Session, m *discordgo.MessageCreate, arguments []string) { + if !util.HasAdmin(dg, m.Author.ID, m.ChannelID) { + util.SendErrorEmbed(dg, m.ChannelID, util.ErrRequireAdmin) + return + } + parsedMessageLink, err := util.ParseMessageLink(arguments[0]) + if err != nil { + util.SendErrorEmbed(dg, m.ChannelID, err) + return + } + emoji, err := util.ParseEmoji(arguments[1]) + if err != nil { + util.SendErrorEmbed(dg, m.ChannelID, err) + return + } + role, err := util.ParseRole(arguments[2]) + if err != nil { + util.SendErrorEmbed(dg, m.ChannelID, err) + return + } + db.CreateReactRole(parsedMessageLink.MessageID, emoji, role) + err = dg.MessageReactionAdd(parsedMessageLink.ChannelID, parsedMessageLink.MessageID, emoji) + if err != nil { + util.ReportError(dg, err) + return + } + util.SendSuccessEmbed(dg, m.ChannelID, "Autorole has been registered successfully.") +} diff --git a/commands/commands.go b/commands/commands.go index fe9e758..abb85f3 100644 --- a/commands/commands.go +++ b/commands/commands.go @@ -5,36 +5,39 @@ import ( "github.com/bwmarrin/discordgo" - "gitea.teamortix.com/chanbakjsd/Milen/db" - "gitea.teamortix.com/chanbakjsd/Milen/humanify" "gitea.teamortix.com/chanbakjsd/Milen/util" ) +type command struct { + Name string + Usage string + Processor func(*discordgo.Session, *discordgo.MessageCreate, []string) + MinimumArgument int + ExactArgument bool +} + +var commands = []command{ + command{"autorole", " ", handleAutorole, 3, true}, +} + func Event(dg *discordgo.Session, m *discordgo.MessageCreate) { if !strings.HasPrefix(m.Content, "milen ") { return } split := strings.Split(m.Content, " ") - switch split[1] { - case "autorole": - util.RequireAdmin(dg, m.Author.ID, m.ChannelID, func() { - if len(split) < 6 { - util.SendCheckError(dg, m.ChannelID, humanify.Eng.Usage.Autorole) - return - } - role := util.ParseRole(split[2]) - if role == "" { - util.SendCheckError(dg, m.ChannelID, humanify.Eng.Usage.Autorole) - return - } - emoji := util.ParseEmoji(split[5]) - db.CreateReactRole(split[4], emoji, role) - err := dg.MessageReactionAdd(split[3], split[4], emoji) - if err != nil { - util.ReportError(dg, err) - return - } - util.SendCheckError(dg, m.ChannelID, humanify.Eng.Autorole.Success) - }) + for _, v := range commands { + if split[1] != v.Name { + continue + } + if (v.ExactArgument && len(split) != v.MinimumArgument+2) || (!v.ExactArgument && len(split) < v.MinimumArgument+2) { + util.SendFailEmbed(dg, m.ChannelID, "Incorrect Usage", "Usage: `milen "+v.Name+" "+v.Usage+"`") + return + } + if len(split) == 2 { + v.Processor(dg, m, []string{}) + return + } + v.Processor(dg, m, split[2:]) + return } } diff --git a/humanify/strings.go b/humanify/strings.go deleted file mode 100644 index d2c2226..0000000 --- a/humanify/strings.go +++ /dev/null @@ -1,35 +0,0 @@ -package humanify - -import ( - "fmt" - "io/ioutil" - - "github.com/BurntSushi/toml" -) - -var Eng Locale - -type Locale struct { - NoAdmin string `toml:"no_admin"` - Usage localeUsage - Autorole localeAutorole -} - -type localeUsage struct { - Autorole string `toml:"autorole"` -} - -type localeAutorole struct { - Success string `toml:"success"` -} - -func init() { - data, err := ioutil.ReadFile("locale.toml") - if err != nil { - panic(err) - } - err = toml.Unmarshal(data, &Eng) - if err != nil { - panic(err) - } -} diff --git a/locale.toml b/locale.toml deleted file mode 100644 index 975a0c8..0000000 --- a/locale.toml +++ /dev/null @@ -1,7 +0,0 @@ -no_admin="❌ You do not have permission to use this command." - -[usage] -autorole="❌ Incorrect usage. Usage: `milen autorole `" - -[autorole] -success="✅ Auto-role registered." diff --git a/util/embed.go b/util/embed.go new file mode 100644 index 0000000..5568554 --- /dev/null +++ b/util/embed.go @@ -0,0 +1,37 @@ +package util + +import ( + "github.com/bwmarrin/discordgo" +) + +func SendSuccessEmbed(dg *discordgo.Session, channelID string, message string) { + _, err := dg.ChannelMessageSendEmbed( + channelID, + &discordgo.MessageEmbed{ + Title: "Success", + Description: message, + Color: 0x00D000, + }, + ) + if err != nil { + ReportError(dg, err) + } +} + +func SendErrorEmbed(dg *discordgo.Session, channelID string, toSend error) { + SendFailEmbed(dg, channelID, "Error", toSend.Error()) +} + +func SendFailEmbed(dg *discordgo.Session, channelID string, title string, description string) { + _, err := dg.ChannelMessageSendEmbed( + channelID, + &discordgo.MessageEmbed{ + Title: title, + Description: description, + Color: 0xD00000, + }, + ) + if err != nil { + ReportError(dg, err) + } +} diff --git a/util/error.go b/util/error.go index 5e9439f..2957325 100644 --- a/util/error.go +++ b/util/error.go @@ -1,12 +1,17 @@ package util import ( + "errors" "fmt" "runtime/debug" "github.com/bwmarrin/discordgo" ) +var ( + ErrRequireAdmin = errors.New("This command requires administrator.") +) + var ReportTarget string func ReportError(dg *discordgo.Session, toReport error) { @@ -31,7 +36,7 @@ func ReportError(dg *discordgo.Session, toReport error) { } } -func SendCheckError(dg *discordgo.Session, channelID string, message string) { +func SendMessage(dg *discordgo.Session, channelID string, message string) { _, err := dg.ChannelMessageSend(channelID, message) if err != nil { ReportError(dg, err) diff --git a/util/magic.go b/util/magic.go index 12c0464..ba34d10 100644 --- a/util/magic.go +++ b/util/magic.go @@ -1,19 +1,57 @@ package util import ( + "errors" "strings" ) -func ParseRole(roleString string) string { +var ( + //Errors for ParseRole + ErrInvalidRole = errors.New("Invalid role has been provided.") + //Errors for ParseEmoji + ErrInvalidEmoji = errors.New("Invalid emoji has been provided.") + //Errors for ParseMessageLink + ErrNotValidURL = errors.New("Invalid URL has been provided (expecting message link).") + ErrNotDiscordURL = errors.New("Invalid Discord URL has been provided (expecting message link).") + ErrNotMessageURL = errors.New("Invalid Discord message link has been provided.") +) + +type ParsedMessageLink struct { + GuildID string + ChannelID string + MessageID string +} + +func ParseRole(roleString string) (string, error) { if !strings.HasPrefix(roleString, "<@&") || !strings.HasSuffix(roleString, ">") { - return "" + return "", ErrInvalidRole } - return roleString[3 : len(roleString)-1] + return roleString[3 : len(roleString)-1], nil } -func ParseEmoji(emojiString string) string { - if !strings.HasPrefix(emojiString, "<:") || !strings.HasSuffix(emojiString, ">") { - return emojiString +func ParseEmoji(emojiString string) (string, error) { + if strings.HasPrefix(emojiString, "<:") && strings.HasSuffix(emojiString, ">") { + return emojiString[2 : len(emojiString)-1], nil + } + //TODO: We assume people aren't ill-intended and everything are actually emoji for now. + //The alternative would be to keep a list of all possible emoji which is overkill. + return emojiString, nil +} + +func ParseMessageLink(messageLink string) (ParsedMessageLink, error) { + if !strings.HasPrefix(messageLink, "https://") { + return ParsedMessageLink{}, ErrNotValidURL + } + split := strings.Split(messageLink, "/") + if split[2] != "discordapp.com" && split[2] != "canary.discordapp.com" && split[2] != "ptb.discordapp.com" { + return ParsedMessageLink{}, ErrNotDiscordURL + } + if len(split) < 7 || split[3] != "channels" { + return ParsedMessageLink{}, ErrNotMessageURL } - return emojiString[2 : len(emojiString)-1] + return ParsedMessageLink{ + GuildID: split[4], + ChannelID: split[5], + MessageID: split[6], + }, nil } diff --git a/util/perm.go b/util/perm.go index 44a2a71..2dcc437 100644 --- a/util/perm.go +++ b/util/perm.go @@ -2,19 +2,13 @@ package util import ( "github.com/bwmarrin/discordgo" - - "gitea.teamortix.com/chanbakjsd/Milen/humanify" ) -func RequireAdmin(dg *discordgo.Session, userID string, channelID string, hasAdmin func()) { +func HasAdmin(dg *discordgo.Session, userID string, channelID string) bool { perm, err := dg.UserChannelPermissions(userID, channelID) if err != nil { ReportError(dg, err) - return - } - if perm&discordgo.PermissionAdministrator == 0 { - SendCheckError(dg, channelID, humanify.Eng.NoAdmin) - return + return false } - hasAdmin() + return perm&discordgo.PermissionAdministrator != 0 }