149 lines
3.5 KiB
Go
149 lines
3.5 KiB
Go
|
package discord
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
"twdcbot/models"
|
||
|
"twdcbot/server"
|
||
|
"twdcbot/tribe"
|
||
|
|
||
|
"github.com/bwmarrin/discordgo"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
TribesPerServer = 10
|
||
|
)
|
||
|
|
||
|
type SessionConfig struct {
|
||
|
Token string
|
||
|
CommandPrefix string
|
||
|
Status string
|
||
|
ServerRepository server.Repository
|
||
|
TribeRepository tribe.Repository
|
||
|
}
|
||
|
|
||
|
type Session struct {
|
||
|
dg *discordgo.Session
|
||
|
cfg SessionConfig
|
||
|
}
|
||
|
|
||
|
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.dg.AddHandler(s.handleNewMessage)
|
||
|
|
||
|
err := s.dg.Open()
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("error opening ws connection: %s", err.Error())
|
||
|
}
|
||
|
|
||
|
if err := s.dg.UpdateStatus(0, s.cfg.Status); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (s *Session) handleNewMessage(_ *discordgo.Session, m *discordgo.MessageCreate) {
|
||
|
if m.Author.ID == s.dg.State.User.ID || m.Author.Bot || m.GuildID == "" {
|
||
|
return
|
||
|
}
|
||
|
if has, err := s.MemberHasPermission(m.GuildID, m.Author.ID, discordgo.PermissionAdministrator); err != nil || !has {
|
||
|
return
|
||
|
}
|
||
|
splitted := strings.Split(m.Content, " ")
|
||
|
argsLength := len(splitted) - 1
|
||
|
args := splitted[1 : argsLength+1]
|
||
|
switch splitted[0] {
|
||
|
case HelpCommand.WithPrefix(s.cfg.CommandPrefix):
|
||
|
if argsLength == 0 {
|
||
|
s.sendHelpMessage(m.Author.Mention(), m.ChannelID)
|
||
|
} else {
|
||
|
s.sendUnknownCommandError(m.Author.Mention(), m.ChannelID, args...)
|
||
|
}
|
||
|
break
|
||
|
case AddCommand.WithPrefix(s.cfg.CommandPrefix):
|
||
|
if argsLength > 2 {
|
||
|
s.sendUnknownCommandError(m.Author.Mention(), m.ChannelID, splitted[3:argsLength+1]...)
|
||
|
return
|
||
|
} else if argsLength < 2 {
|
||
|
s.sendMessage(m.ChannelID, m.Author.Mention()+` tw!add [świat] [id_plemienia]`)
|
||
|
return
|
||
|
}
|
||
|
s.handleAddCommand(m, args...)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *Session) handleAddCommand(m *discordgo.MessageCreate, args ...string) {
|
||
|
world := args[0]
|
||
|
id, err := strconv.Atoi(args[1])
|
||
|
if err != nil {
|
||
|
s.sendMessage(m.ChannelID, m.Author.Mention()+` tw!add [świat] [id_plemienia]`)
|
||
|
return
|
||
|
}
|
||
|
server := &models.Server{
|
||
|
ID: m.GuildID,
|
||
|
}
|
||
|
err = s.cfg.ServerRepository.Store(context.Background(), server)
|
||
|
if err != nil {
|
||
|
s.sendMessage(m.ChannelID, m.Author.Mention()+` Nie udało się dodać plemienia do obserwowanych.`)
|
||
|
return
|
||
|
}
|
||
|
if len(server.Tribes) >= TribesPerServer {
|
||
|
s.sendMessage(m.ChannelID, m.Author.Mention()+fmt.Sprintf(` Osiągnięto limit plemion (%d/%d).`, TribesPerServer, TribesPerServer))
|
||
|
return
|
||
|
}
|
||
|
log.Println(world, id, server.Tribes)
|
||
|
err = s.cfg.TribeRepository.Store(context.Background(), &models.Tribe{
|
||
|
World: world,
|
||
|
TribeID: id,
|
||
|
ServerID: server.ID,
|
||
|
})
|
||
|
if err != nil {
|
||
|
s.sendMessage(m.ChannelID, m.Author.Mention()+` Nie udało się dodać plemienia do obserwowanych.`)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *Session) Close() error {
|
||
|
return s.dg.Close()
|
||
|
}
|
||
|
|
||
|
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
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 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
|
||
|
}
|