diff --git a/GoBot/discord/config/translate.go b/GoBot/discord/config/translate.go new file mode 100644 index 0000000..46e5ce4 --- /dev/null +++ b/GoBot/discord/config/translate.go @@ -0,0 +1,25 @@ +package config + +//==Message Util== +const UsageTitle = "使用方法Command Usage" +const UsageColour = 0xF00000 +const ErrorStack = "纠错信息Debug Info" +const SuccessTitle = "成功Success" +const SuccessColour = 0x00E000 + +//==Commands== +const SendAsUsage = "!sendas <频道ID> <信息>\n!sendas " +const SendAsSuccessfulDescription = "成功发送该信息。\nSent the message successfully." +const SendAsSuccessfulMessageID = "Discord编号 // Discord ID" + +const EditAsUsage = "!editas <频道ID> <信息ID> <信息>\n!editas " +const EditAsSuccessfulDescription = "成功编辑该信息。\nEdited the message successfully." + +//VTL is view trust level +const VTLColour = 0xE0E000 +const VTLSingleUserTitle = "<@%s>的信誉分 <@%s>'s Trust Score" +const VTLSingleUserValue = "分数 Trust Score" +const VTLSingleUserServerTotal = "伺服器总分 Server Total" +const VTLSingleUserPercentage = "百分比 Percentage" +const VTLGlobalTitle = "伺服器信誉分报告 Server Trust Score Report" +const VTLGlobalFieldFormat = "%.1f/%.1f (%.2f%%)" diff --git a/GoBot/discord/modules/admin.go b/GoBot/discord/modules/admin.go index 0b54fd4..d070cda 100644 --- a/GoBot/discord/modules/admin.go +++ b/GoBot/discord/modules/admin.go @@ -2,86 +2,99 @@ package modules import ( "fmt" - "strings" "github.com/bwmarrin/discordgo" "TerraOceanBot/discord/backend" + "TerraOceanBot/discord/config" ) //adminID is my Discord user ID (chanbakjsd#7968). const adminID = "218983355746746369" -func sendAs(s *discordgo.Session, m *discordgo.MessageCreate, command []string) { - if m.Author.ID != adminID { - return - } - if len(command) < 3 { - return - } - message := strings.SplitN(m.Content, " ", 3) - msg, err := s.ChannelMessageSend(message[1], message[2]) - if err != nil { - s.ChannelMessageSend(m.ChannelID, err.Error()) +func adminOnly(passOn CommandHandler) CommandHandler { + return func(s *discordgo.Session, m *discordgo.MessageCreate, command []string) { + if m.Author.ID != adminID { + return + } + passOn(s, m, command) } - s.ChannelMessageSend(m.ChannelID, "The message has been sent. Discord ID: "+msg.ID) } -func editAs(s *discordgo.Session, m *discordgo.MessageCreate, command []string) { - if m.Author.ID != adminID { - return - } - if len(command) < 4 { - return - } - message := strings.SplitN(m.Content, " ", 4) - _, err := s.ChannelMessageEdit(message[1], message[2], message[3]) - if err != nil { - s.ChannelMessageSend(m.ChannelID, err.Error()) - } - s.ChannelMessageSend(m.ChannelID, "The message has been edited.") -} +var sendAs = adminOnly(enforceArgumentCount(config.SendAsUsage, 3, + //!sendas + func(s *discordgo.Session, m *discordgo.MessageCreate, command []string) { + msg, err := s.ChannelMessageSend(command[1], command[2]) + if err != nil { + sendError(s, m.ChannelID, err) + return + } + initNewEmbed(config.SuccessTitle, config.SendAsSuccessfulDescription, config.SuccessColour). + AddField(config.SendAsSuccessfulMessageID, msg.ID). + Send(s, m.ChannelID) + }, +)) -func viewTrustLevel(s *discordgo.Session, m *discordgo.MessageCreate, command []string) { - if m.Author.ID != adminID { - return - } +var editAs = adminOnly(enforceArgumentCount(config.EditAsUsage, 4, + //!editas + func(s *discordgo.Session, m *discordgo.MessageCreate, command []string) { + _, err := s.ChannelMessageEdit(command[1], command[2], command[3]) + if err != nil { + sendError(s, m.ChannelID, err) + return + } + initNewEmbed(config.SuccessTitle, config.EditAsSuccessfulDescription, config.SuccessColour). + Send(s, m.ChannelID) + }, +)) + +var viewTrustLevel = adminOnly(func(s *discordgo.Session, m *discordgo.MessageCreate, command []string) { if len(command) > 1 { value, err := backend.GetTrust(s, command[1]) if err != nil { - s.ChannelMessageSend(m.ChannelID, err.Error()) + sendError(s, m.ChannelID, err) return } total, err := backend.GetTotalTrust(s) if err != nil { - s.ChannelMessageSend(m.ChannelID, err.Error()) + sendError(s, m.ChannelID, err) return } - s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("Trust level is %.1f/%.1f (%.2f%%) for user <@%d>.", value, total, value/total*100, command[1])) + newEmbed().SetColour(config.VTLColour). + SetTitle(fmt.Sprintf(config.VTLSingleUserTitle, command[1], command[1])). + AddField(config.VTLSingleUserValue, formatFloat(value, 1)). + AddField(config.VTLSingleUserServerTotal, formatFloat(total, 1)). + AddField(config.VTLSingleUserPercentage, formatFloat(value/total*100, 2)). + Send(s, m.ChannelID) return } total, err := backend.GetTotalTrust(s) if err != nil { - s.ChannelMessageSend(m.ChannelID, err.Error()) + sendError(s, m.ChannelID, err) return } - message := "" members, err := backend.GetAllMembers(s) if err != nil { - s.ChannelMessageSend(m.ChannelID, err.Error()) + sendError(s, m.ChannelID, err) return } + + //Generate message + message := newEmbed().SetColour(config.VTLColour).SetTitle(config.VTLGlobalTitle) for _, v := range members { value, err := backend.GetTrust(s, v.User.ID) if err == backend.ErrNotMember { continue } if err != nil { - s.ChannelMessageSend(m.ChannelID, err.Error()) + sendError(s, m.ChannelID, err) return } - message += fmt.Sprintf("%s#%s - %.1f/%.1f (%.2f%%)\n", v.User.Username, v.User.Discriminator, value, total, value/total*100) + message.AddInlineField( + v.User.Username+"#"+v.User.Discriminator, + fmt.Sprintf(config.VTLGlobalFieldFormat, value, total, value/total*100), + ) } - s.ChannelMessageSend(m.ChannelID, message) -} + message.Send(s, m.ChannelID) +}) diff --git a/GoBot/discord/modules/commands.go b/GoBot/discord/modules/commands.go index 86d8f31..3d3f610 100644 --- a/GoBot/discord/modules/commands.go +++ b/GoBot/discord/modules/commands.go @@ -2,9 +2,10 @@ package modules import "github.com/bwmarrin/discordgo" +type CommandHandler func(s *discordgo.Session, m *discordgo.MessageCreate, commands []string) type Command struct { Name string - Handler func(s *discordgo.Session, m *discordgo.MessageCreate, commands []string) + Handler CommandHandler } var Commands = []Command{ diff --git a/GoBot/discord/modules/embed.go b/GoBot/discord/modules/embed.go index 251c960..46bc794 100644 --- a/GoBot/discord/modules/embed.go +++ b/GoBot/discord/modules/embed.go @@ -10,9 +10,15 @@ func newEmbed() *embed { return &embed{&discordgo.MessageEmbed{}} } -func (e *embed) Errorify() *embed { +func initNewEmbed(title, description string, colour int) *embed { + return newEmbed().SetTitle(title).SetDescription(description).SetColour(colour) +} + +func initNewErrorEmbed(description string) *embed { + e := newEmbed() e.Color = 0xE00000 e.Title = "发生错误!An error has occurred!" + e.Description = description return e } @@ -39,6 +45,19 @@ func (e *embed) AddField(name, value string) *embed { return e } +func (e *embed) AddInlineField(name, value string) *embed { + e.Fields = append(e.Fields, &discordgo.MessageEmbedField{ + Name: name, + Value: value, + Inline: true, + }) + return e +} + func (e *embed) Build() *discordgo.MessageEmbed { return e.MessageEmbed } + +func (e *embed) Send(s *discordgo.Session, channelID string) { + s.ChannelMessageSendEmbed(channelID, e.Build()) +} diff --git a/GoBot/discord/modules/messageutil.go b/GoBot/discord/modules/messageutil.go index 1367279..dde7ff3 100644 --- a/GoBot/discord/modules/messageutil.go +++ b/GoBot/discord/modules/messageutil.go @@ -2,6 +2,9 @@ package modules import ( "fmt" + "runtime" + "strconv" + "strings" "github.com/bwmarrin/discordgo" @@ -76,3 +79,31 @@ func auditLog(s *discordgo.Session, message string) { fmt.Println(err) } } + +func enforceArgumentCount(usage string, count int, passOn CommandHandler) CommandHandler { + return func(s *discordgo.Session, m *discordgo.MessageCreate, command []string) { + if len(command) < count { + s.ChannelMessageSendEmbed( + m.ChannelID, + newEmbed().SetTitle(config.UsageTitle).SetDescription(usage).SetColour(config.UsageColour).Build(), + ) + return + } + command[count-1] = strings.Join(command[count-1:], " ") + passOn(s, m, command[:count]) + } +} + +func sendError(s *discordgo.Session, channelID string, err error) { + stackCache := make([]byte, 512) + count := runtime.Stack(stackCache, false) + stack := string(stackCache[:count]) + if count == 512 { + stack += "..." + } + initNewErrorEmbed(err.Error()).AddField(config.ErrorStack, stack).Send(s, channelID) +} + +func formatFloat(n float64, precision int) string { + return strconv.FormatFloat(n, 'f', precision, 64) +}