From 9c71cb2ce9b7a8d2bd866c986e74fde63ebd31ea Mon Sep 17 00:00:00 2001 From: Kichiyaki Date: Sun, 18 Jul 2021 09:53:19 +0200 Subject: [PATCH] add check if procTranslateCoords implements messageProcessor --- discord/coords_translation.go | 2 + discord/discord.go | 213 +------------------------------- discord/session.go | 220 ++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+), 212 deletions(-) create mode 100644 discord/session.go diff --git a/discord/coords_translation.go b/discord/coords_translation.go index 03877e8..305cfab 100644 --- a/discord/coords_translation.go +++ b/discord/coords_translation.go @@ -109,6 +109,8 @@ type procTranslateCoords struct { *Session } +var _ messageProcessor = &procTranslateCoords{} + func (p *procTranslateCoords) process(ctx *commandCtx, m *discordgo.MessageCreate) { if ctx.server.CoordsTranslation == "" { return diff --git a/discord/discord.go b/discord/discord.go index 007b523..739916a 100644 --- a/discord/discord.go +++ b/discord/discord.go @@ -1,216 +1,5 @@ package discord -import ( - "context" - "github.com/pkg/errors" - "strings" - - "github.com/sirupsen/logrus" - - "github.com/tribalwarshelp/dcbot/message" - - "github.com/tribalwarshelp/golang-sdk/sdk" - - "github.com/tribalwarshelp/dcbot/group" - "github.com/tribalwarshelp/dcbot/model" - "github.com/tribalwarshelp/dcbot/observation" - "github.com/tribalwarshelp/dcbot/server" - - "github.com/bwmarrin/discordgo" -) +import "github.com/sirupsen/logrus" var log = logrus.WithField("package", "discord") - -type SessionConfig struct { - Token string - CommandPrefix string - Status string - ServerRepository server.Repository - GroupRepository group.Repository - ObservationRepository observation.Repository - API *sdk.SDK -} - -type Session struct { - dg *discordgo.Session - cfg SessionConfig - handlers commandHandlers -} - -func New(cfg SessionConfig) (*Session, error) { - var err error - s := &Session{ - cfg: cfg, - } - s.dg, err = discordgo.New("Bot " + cfg.Token) - if err != nil { - return nil, err - } - if err := s.init(); err != nil { - return nil, err - } - return s, nil -} - -func (s *Session) init() error { - s.handlers = commandHandlers{ - &commandHelp{s}, - &commandAuthor{s}, - &commandTribe{s}, - &commandChangeLanguage{s}, - &commandAddGroup{s}, - &commandDeleteGroup{s}, - &commandGroups{s}, - &commandObserve{s}, - &commandDeleteObservation{s}, - &commandObservations{s}, - &commandConqueredVillages{s}, - &commandDisableConqueredVillages{s}, - &commandLostVillages{s}, - &commandDisableLostVillages{s}, - &commandShowEnnobledBarbarians{s}, - &commandShowInternals{s}, - &commandCoordsTranslation{s}, - &commandDisableCoordsTranslation{s}, - } - - s.dg.AddHandler(s.handleNewMessage) - - err := s.dg.Open() - if err != nil { - return errors.Wrap(err, "error opening ws connection") - } - - if err := s.UpdateStatus(s.cfg.Status); err != nil { - return err - } - - return nil -} - -func (s *Session) Close() error { - return s.dg.Close() -} - -func (s *Session) SendMessage(channelID, message string) error { - _, err := s.dg.ChannelMessageSend(channelID, message) - return err -} - -func (s *Session) SendEmbed(channelID string, e *Embed) error { - for _, fields := range splitEmbedFields(e) { - fieldsLen := len(fields) - for i := 0; i < fieldsLen; i += EmbedLimitField { - end := i + EmbedLimitField - if end > fieldsLen { - end = fieldsLen - } - e.Fields = fields[i:end] - if _, err := s.dg.ChannelMessageSendEmbed(channelID, e.MessageEmbed); err != nil { - return err - } - } - } - - return nil -} - -func (s *Session) UpdateStatus(status string) error { - if err := s.dg.UpdateStatus(0, status); err != nil { - return err - } - return nil -} - -func (s *Session) IsGuildMember(guildID string) (bool, error) { - _, err := s.dg.State.Guild(guildID) - if err != nil { - if _, err = s.dg.Guild(guildID); err != nil { - return false, err - } - } - return true, nil -} - -func (s *Session) handleNewMessage(_ *discordgo.Session, m *discordgo.MessageCreate) { - if m.Author.ID == s.dg.State.User.ID || m.Author.Bot { - return - } - - parts := strings.Split(m.Content, " ") - args := parts[1:] - svr := &model.Server{ - ID: m.GuildID, - Lang: message.GetDefaultLanguage().String(), - } - if svr.ID != "" { - if err := s.cfg.ServerRepository.Store(context.Background(), svr); err != nil { - return - } - } - ctx := &commandCtx{ - server: svr, - localizer: message.NewLocalizer(svr.Lang), - } - - h := s.handlers.find(s.cfg.CommandPrefix, parts[0]) - if h != nil { - if h.requireAdmPermissions() { - if m.GuildID == "" { - return - } - has, err := s.memberHasPermission(m.GuildID, m.Author.ID, discordgo.PermissionAdministrator) - if err != nil || !has { - return - } - } - log. - WithFields(logrus.Fields{ - "serverID": svr.ID, - "lang": svr.Lang, - "command": parts[0], - "args": args, - "authorID": m.Author.ID, - "authorUsername": m.Author.Username, - }). - Infof("handleNewMessage: Executing command %s...", parts[0]) - h.execute(ctx, m, args...) - return - } - - s.translateCoords(ctx, m) -} - -func (s *Session) memberHasPermission(guildID string, userID string, permission int) (bool, error) { - member, err := s.dg.State.Member(guildID, userID) - if err != nil { - if member, err = s.dg.GuildMember(guildID, userID); err != nil { - return false, err - } - } - - // check if user is a guild owner - guild, err := s.dg.State.Guild(guildID) - if err != nil { - if guild, err = s.dg.Guild(guildID); err != nil { - return false, err - } - } - if guild.OwnerID == userID { - return true, nil - } - - // Iterate through the role IDs stored in member.Roles - // to check permissions - for _, roleID := range member.Roles { - role, err := s.dg.State.Role(guildID, roleID) - if err != nil { - return false, err - } - if role.Permissions&permission != 0 { - return true, nil - } - } - - return false, nil -} diff --git a/discord/session.go b/discord/session.go new file mode 100644 index 0000000..136a6f1 --- /dev/null +++ b/discord/session.go @@ -0,0 +1,220 @@ +package discord + +import ( + "context" + "github.com/pkg/errors" + "strings" + + "github.com/sirupsen/logrus" + + "github.com/tribalwarshelp/dcbot/message" + + "github.com/tribalwarshelp/golang-sdk/sdk" + + "github.com/tribalwarshelp/dcbot/group" + "github.com/tribalwarshelp/dcbot/model" + "github.com/tribalwarshelp/dcbot/observation" + "github.com/tribalwarshelp/dcbot/server" + + "github.com/bwmarrin/discordgo" +) + +type SessionConfig struct { + Token string + CommandPrefix string + Status string + ServerRepository server.Repository + GroupRepository group.Repository + ObservationRepository observation.Repository + API *sdk.SDK +} + +type Session struct { + dg *discordgo.Session + cfg SessionConfig + handlers commandHandlers + messageProcessors []messageProcessor +} + +func New(cfg SessionConfig) (*Session, error) { + var err error + s := &Session{ + cfg: cfg, + } + s.dg, err = discordgo.New("Bot " + cfg.Token) + if err != nil { + return nil, err + } + if err := s.init(); err != nil { + return nil, err + } + return s, nil +} + +func (s *Session) init() error { + s.handlers = commandHandlers{ + &hndlrHelp{s}, + &hndlrAuthor{s}, + &hndlrTribe{s}, + &hndlrChangeLanguage{s}, + &hndlrAddGroup{s}, + &hndlrDeleteGroup{s}, + &hndlrGroups{s}, + &hndlrObserve{s}, + &hndlrDeleteObservation{s}, + &hndlrObservations{s}, + &hndlrConqueredVillages{s}, + &hndlrDisableConqueredVillages{s}, + &hndlrLostVillages{s}, + &hndlrDisableLostVillages{s}, + &hndlrShowEnnobledBarbarians{s}, + &hndlrShowInternals{s}, + &hndlrCoordsTranslation{s}, + &hndlrDisableCoordsTranslation{s}, + } + s.messageProcessors = []messageProcessor{ + &procTranslateCoords{s}, + } + + s.dg.AddHandler(s.handleNewMessage) + + err := s.dg.Open() + if err != nil { + return errors.Wrap(err, "error opening ws connection") + } + + if err := s.UpdateStatus(s.cfg.Status); err != nil { + return err + } + + return nil +} + +func (s *Session) Close() error { + return s.dg.Close() +} + +func (s *Session) SendMessage(channelID, message string) error { + _, err := s.dg.ChannelMessageSend(channelID, message) + return err +} + +func (s *Session) SendEmbed(channelID string, e *Embed) error { + for _, fields := range splitEmbedFields(e) { + fieldsLen := len(fields) + for i := 0; i < fieldsLen; i += EmbedLimitField { + end := i + EmbedLimitField + if end > fieldsLen { + end = fieldsLen + } + e.Fields = fields[i:end] + if _, err := s.dg.ChannelMessageSendEmbed(channelID, e.MessageEmbed); err != nil { + return err + } + } + } + + return nil +} + +func (s *Session) UpdateStatus(status string) error { + if err := s.dg.UpdateStatus(0, status); err != nil { + return err + } + return nil +} + +func (s *Session) IsGuildMember(guildID string) (bool, error) { + _, err := s.dg.State.Guild(guildID) + if err != nil { + if _, err = s.dg.Guild(guildID); err != nil { + return false, err + } + } + return true, nil +} + +func (s *Session) handleNewMessage(_ *discordgo.Session, m *discordgo.MessageCreate) { + if m.Author.ID == s.dg.State.User.ID || m.Author.Bot { + return + } + + parts := strings.Split(m.Content, " ") + args := parts[1:] + svr := &model.Server{ + ID: m.GuildID, + Lang: message.GetDefaultLanguage().String(), + } + if svr.ID != "" { + if err := s.cfg.ServerRepository.Store(context.Background(), svr); err != nil { + return + } + } + ctx := &commandCtx{ + server: svr, + localizer: message.NewLocalizer(svr.Lang), + } + + h := s.handlers.find(s.cfg.CommandPrefix, parts[0]) + if h != nil { + if h.requireAdmPermissions() { + if m.GuildID == "" { + return + } + has, err := s.memberHasPermission(m.GuildID, m.Author.ID, discordgo.PermissionAdministrator) + if err != nil || !has { + return + } + } + log. + WithFields(logrus.Fields{ + "serverID": svr.ID, + "lang": svr.Lang, + "command": parts[0], + "args": args, + "authorID": m.Author.ID, + "authorUsername": m.Author.Username, + }). + Infof(`handleNewMessage: Executing command "%s"...`, m.Content) + h.execute(ctx, m, args...) + return + } + + for _, p := range s.messageProcessors { + p.process(ctx, m) + } +} + +func (s *Session) memberHasPermission(guildID string, userID string, permission int) (bool, error) { + member, err := s.dg.State.Member(guildID, userID) + if err != nil { + if member, err = s.dg.GuildMember(guildID, userID); err != nil { + return false, err + } + } + + // check if user is a guild owner + guild, err := s.dg.State.Guild(guildID) + if err != nil { + if guild, err = s.dg.Guild(guildID); err != nil { + return false, err + } + } + if guild.OwnerID == userID { + return true, nil + } + + // Iterate through the role IDs stored in member.Roles + // to check permissions + for _, roleID := range member.Roles { + role, err := s.dg.State.Role(guildID, roleID) + if err != nil { + return false, err + } + if role.Permissions&permission != 0 { + return true, nil + } + } + + return false, nil +}