diff --git a/cron/cron.go b/cron/cron.go index 5f21bf3..db7b520 100644 --- a/cron/cron.go +++ b/cron/cron.go @@ -1,18 +1,13 @@ package cron import ( - "context" - "log" "time" - shared_models "github.com/tribalwarshelp/shared/models" - "github.com/tribalwarshelp/golang-sdk/sdk" "github.com/tribalwarshelp/dcbot/discord" "github.com/tribalwarshelp/dcbot/server" "github.com/tribalwarshelp/dcbot/tribe" - "github.com/tribalwarshelp/dcbot/utils" "github.com/robfig/cron/v3" ) @@ -24,151 +19,13 @@ type Config struct { API *sdk.SDK } -type handler struct { - since time.Time - serverRepo server.Repository - tribeRepo tribe.Repository - discord *discord.Session - api *sdk.SDK -} - func Attach(c *cron.Cron, cfg Config) { h := &handler{ - since: time.Now(), + since: time.Now().Add(-45 * time.Minute), serverRepo: cfg.ServerRepo, tribeRepo: cfg.TribeRepo, discord: cfg.Discord, api: cfg.API, } - c.AddFunc("@every 1m", h.checkEnnoblements) -} - -func (h *handler) loadEnnoblements(worlds []string) map[string]ennoblements { - m := make(map[string]ennoblements) - - for _, w := range worlds { - es, err := h.api.Ennoblements.Browse(w, &sdk.EnnoblementInclude{ - NewOwner: true, - Village: true, - NewOwnerInclude: sdk.PlayerInclude{ - Tribe: true, - }, - OldOwner: true, - OldOwnerInclude: sdk.PlayerInclude{ - Tribe: true, - }, - }) - if err != nil { - log.Printf("%s: %s", w, err.Error()) - continue - } - m[w] = filterEnnoblements(es, h.since) - } - - return m -} - -func (h *handler) loadLangVersions(worlds []string) map[shared_models.LanguageTag]*shared_models.LangVersion { - languageTags := []shared_models.LanguageTag{} - cache := make(map[shared_models.LanguageTag]bool) - for _, world := range worlds { - languageTag := utils.LanguageCodeFromWorldName(world) - if languageTag.IsValid() && !cache[languageTag] { - cache[languageTag] = true - languageTags = append(languageTags, languageTag) - } - } - - langVersions := make(map[shared_models.LanguageTag]*shared_models.LangVersion) - langVersionsList, err := h.api.LangVersions.Browse(&shared_models.LangVersionFilter{ - Tag: languageTags, - }) - if err == nil { - for _, langVersion := range langVersionsList.Items { - langVersions[langVersion.Tag] = langVersion - } - } else { - log.Printf("Cannot load lang versions: %s", err.Error()) - } - - return langVersions -} - -func (h *handler) checkEnnoblements() { - worlds, err := h.tribeRepo.FetchWorlds(context.Background()) - if err != nil { - log.Print("checkEnnoblements: " + err.Error()) - return - } - log.Print("checkEnnoblements: worlds: ", worlds) - - servers, total, err := h.serverRepo.Fetch(context.Background(), nil) - if err != nil { - log.Print("checkEnnoblements: " + err.Error()) - return - } - log.Print("checkEnnoblements: total number of servers: ", total) - - langVersions := h.loadLangVersions(worlds) - - data := h.loadEnnoblements(worlds) - h.since = time.Now() - log.Print("checkEnnoblements: loaded ennoblements: ", len(data)) - - for _, server := range servers { - if server.ConqueredVillagesChannelID == "" && server.LostVillagesChannelID == "" { - continue - } - for _, tribe := range server.Tribes { - es, ok := data[tribe.World] - langVersion, ok2 := langVersions[utils.LanguageCodeFromWorldName(tribe.World)] - if ok && ok2 { - if server.LostVillagesChannelID != "" { - for _, ennoblement := range es.tribeLostVillages(tribe.TribeID) { - if !isPlayerTribeNil(ennoblement.NewOwner) && - server.Tribes.Contains(tribe.World, ennoblement.NewOwner.Tribe.ID) { - continue - } - newMsgDataConfig := newMessageDataConfig{ - host: langVersion.Host, - world: tribe.World, - ennoblement: ennoblement, - timezone: langVersion.Timezone, - } - msgData := newMessageData(newMsgDataConfig) - h.discord.SendEmbed(server.LostVillagesChannelID, - discord. - NewEmbed(). - SetTitle("Stracona wioska"). - SetTimestamp(msgData.date). - AddField(msgData.world, formatMsgAboutVillageLost(msgData)). - MessageEmbed) - } - } - - if server.ConqueredVillagesChannelID != "" { - for _, ennoblement := range es.tribeConqueredVillages(tribe.TribeID) { - if !isPlayerTribeNil(ennoblement.OldOwner) && - server.Tribes.Contains(tribe.World, ennoblement.OldOwner.Tribe.ID) { - continue - } - newMsgDataConfig := newMessageDataConfig{ - host: langVersion.Host, - world: tribe.World, - ennoblement: ennoblement, - timezone: langVersion.Timezone, - } - msgData := newMessageData(newMsgDataConfig) - h.discord.SendEmbed(server.ConqueredVillagesChannelID, - discord. - NewEmbed(). - SetTitle("Podbita wioska"). - AddField(msgData.world, formatMsgAboutVillageConquest(msgData)). - SetTimestamp(msgData.date). - MessageEmbed) - } - } - } - } - } + c.AddFunc("@every 1m", h.checkLastEnnoblements) } diff --git a/cron/handler.go b/cron/handler.go new file mode 100644 index 0000000..bef28a7 --- /dev/null +++ b/cron/handler.go @@ -0,0 +1,153 @@ +package cron + +import ( + "context" + "log" + "time" + + shared_models "github.com/tribalwarshelp/shared/models" + + "github.com/tribalwarshelp/dcbot/discord" + "github.com/tribalwarshelp/dcbot/server" + "github.com/tribalwarshelp/dcbot/tribe" + "github.com/tribalwarshelp/dcbot/utils" + "github.com/tribalwarshelp/golang-sdk/sdk" +) + +type handler struct { + since time.Time + serverRepo server.Repository + tribeRepo tribe.Repository + discord *discord.Session + api *sdk.SDK +} + +func (h *handler) loadEnnoblements(worlds []string) map[string]ennoblements { + m := make(map[string]ennoblements) + + for _, w := range worlds { + es, err := h.api.Ennoblements.Browse(w, &sdk.EnnoblementInclude{ + NewOwner: true, + Village: true, + NewOwnerInclude: sdk.PlayerInclude{ + Tribe: true, + }, + OldOwner: true, + OldOwnerInclude: sdk.PlayerInclude{ + Tribe: true, + }, + }) + if err != nil { + log.Printf("%s: %s", w, err.Error()) + continue + } + m[w] = filterEnnoblements(es, h.since) + } + + return m +} + +func (h *handler) loadLangVersions(worlds []string) map[shared_models.LanguageTag]*shared_models.LangVersion { + languageTags := []shared_models.LanguageTag{} + cache := make(map[shared_models.LanguageTag]bool) + for _, world := range worlds { + languageTag := utils.LanguageCodeFromWorldName(world) + if languageTag.IsValid() && !cache[languageTag] { + cache[languageTag] = true + languageTags = append(languageTags, languageTag) + } + } + + langVersions := make(map[shared_models.LanguageTag]*shared_models.LangVersion) + langVersionsList, err := h.api.LangVersions.Browse(&shared_models.LangVersionFilter{ + Tag: languageTags, + }) + if err == nil { + for _, langVersion := range langVersionsList.Items { + langVersions[langVersion.Tag] = langVersion + } + } else { + log.Printf("Cannot load lang versions: %s", err.Error()) + } + + return langVersions +} + +func (h *handler) checkLastEnnoblements() { + worlds, err := h.tribeRepo.FetchWorlds(context.Background()) + if err != nil { + log.Print("checkLastEnnoblements: " + err.Error()) + return + } + log.Print("checkLastEnnoblements: worlds: ", worlds) + + servers, total, err := h.serverRepo.Fetch(context.Background(), nil) + if err != nil { + log.Print("checkLastEnnoblements: " + err.Error()) + return + } + log.Print("checkLastEnnoblements: total number of discord servers: ", total) + + langVersions := h.loadLangVersions(worlds) + + data := h.loadEnnoblements(worlds) + h.since = time.Now() + log.Println("checkLastEnnoblements: loaded ennoblements from", len(data), "tribalwars servers") + + for _, server := range servers { + if server.ConqueredVillagesChannelID == "" && server.LostVillagesChannelID == "" { + continue + } + for _, tribe := range server.Tribes { + es, ok := data[tribe.World] + langVersion, ok2 := langVersions[utils.LanguageCodeFromWorldName(tribe.World)] + if ok && ok2 { + if server.LostVillagesChannelID != "" { + for _, ennoblement := range es.tribeLostVillages(tribe.TribeID) { + if !isPlayerTribeNil(ennoblement.NewOwner) && + server.Tribes.Contains(tribe.World, ennoblement.NewOwner.Tribe.ID) { + continue + } + newMsgDataConfig := newMessageDataConfig{ + host: langVersion.Host, + world: tribe.World, + ennoblement: ennoblement, + timezone: langVersion.Timezone, + } + msgData := newMessageData(newMsgDataConfig) + h.discord.SendEmbed(server.LostVillagesChannelID, + discord. + NewEmbed(). + SetTitle("Stracona wioska"). + AddField(msgData.world, formatMsgAboutVillageLost(msgData)). + SetTimestamp(msgData.date). + MessageEmbed) + } + } + + if server.ConqueredVillagesChannelID != "" { + for _, ennoblement := range es.tribeConqueredVillages(tribe.TribeID) { + if !isPlayerTribeNil(ennoblement.OldOwner) && + server.Tribes.Contains(tribe.World, ennoblement.OldOwner.Tribe.ID) { + continue + } + newMsgDataConfig := newMessageDataConfig{ + host: langVersion.Host, + world: tribe.World, + ennoblement: ennoblement, + timezone: langVersion.Timezone, + } + msgData := newMessageData(newMsgDataConfig) + h.discord.SendEmbed(server.ConqueredVillagesChannelID, + discord. + NewEmbed(). + SetTitle("Podbita wioska"). + AddField(msgData.world, formatMsgAboutVillageConquest(msgData)). + SetTimestamp(msgData.date). + MessageEmbed) + } + } + } + } + } +} diff --git a/cron/message.go b/cron/message.go index ec57319..12a4c46 100644 --- a/cron/message.go +++ b/cron/message.go @@ -46,10 +46,11 @@ func newMessageData(cfg newMessageDataConfig) messageData { newOwnerTribeTag: "-", } if !isVillageNil(cfg.ennoblement.Village) { - data.village = fmt.Sprintf("%s (%d|%d)", + data.village = fmt.Sprintf("%s (%d|%d) %s", cfg.ennoblement.Village.Name, cfg.ennoblement.Village.X, - cfg.ennoblement.Village.Y) + cfg.ennoblement.Village.Y, + cfg.ennoblement.Village.Continent()) data.villageURL = utils.FormatVillageURL(cfg.world, cfg.host, cfg.ennoblement.Village.ID) } if !isPlayerNil(cfg.ennoblement.OldOwner) { diff --git a/dev.sh b/dev.sh new file mode 100755 index 0000000..16b66ca --- /dev/null +++ b/dev.sh @@ -0,0 +1,3 @@ +#!/bin/sh +export MODE=development +go run main.go \ No newline at end of file diff --git a/discord/commands.go b/discord/commands.go index a634da4..339754d 100644 --- a/discord/commands.go +++ b/discord/commands.go @@ -285,22 +285,32 @@ func (s *Session) handleAddCommand(m *discordgo.MessageCreate, args ...string) { return } + server, err := s.cfg.API.Servers.Read(world) + if err != nil || server == nil { + s.SendMessage(m.ChannelID, m.Author.Mention()+fmt.Sprintf(` świat %s jest nieobsługiwany.`, world)) + return + } + if server.Status == shared_models.ServerStatusClosed { + s.SendMessage(m.ChannelID, m.Author.Mention()+fmt.Sprintf(` świat %s jest zamknięty.`, world)) + return + } + tribe, err := s.cfg.API.Tribes.Read(world, id) if err != nil || tribe == nil { s.SendMessage(m.ChannelID, m.Author.Mention()+fmt.Sprintf(` Plemię o ID: %d nie istnieje na świecie %s.`, id, world)) return } - server := &models.Server{ + dcServer := &models.Server{ ID: m.GuildID, } - err = s.cfg.ServerRepository.Store(context.Background(), server) + err = s.cfg.ServerRepository.Store(context.Background(), dcServer) if err != nil { s.SendMessage(m.ChannelID, m.Author.Mention()+` Nie udało się dodać plemienia do obserwowanych.`) return } - if len(server.Tribes) >= TribesPerServer { + if len(dcServer.Tribes) >= TribesPerServer { s.SendMessage(m.ChannelID, m.Author.Mention()+fmt.Sprintf(` Osiągnięto limit plemion (%d/%d).`, TribesPerServer, TribesPerServer)) return } @@ -308,7 +318,7 @@ func (s *Session) handleAddCommand(m *discordgo.MessageCreate, args ...string) { err = s.cfg.TribeRepository.Store(context.Background(), &models.Tribe{ World: world, TribeID: id, - ServerID: server.ID, + ServerID: dcServer.ID, }) if err != nil { s.SendMessage(m.ChannelID, m.Author.Mention()+` Nie udało się dodać plemienia do obserwowanych.`) diff --git a/discord/discord.go b/discord/discord.go index a6b4658..0790289 100644 --- a/discord/discord.go +++ b/discord/discord.go @@ -95,6 +95,14 @@ func (s *Session) handleNewMessage(_ *discordgo.Session, m *discordgo.MessageCre } 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 a user is guild owner guild, err := s.dg.State.Guild(guildID) if err != nil { if guild, err = s.dg.Guild(guildID); err != nil { @@ -105,13 +113,6 @@ func (s *Session) memberHasPermission(guildID string, userID string, permission return true, nil } - 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 { diff --git a/discord/embed.go b/discord/embed.go index 7010efc..6ae526a 100644 --- a/discord/embed.go +++ b/discord/embed.go @@ -4,7 +4,7 @@ import "github.com/bwmarrin/discordgo" // Constants for message embed character limits const ( - discordEmbedColor = 0x00ff00 + EmbedColor = 0x00ff00 EmbedLimitTitle = 256 EmbedLimitDescription = 2048 EmbedLimitFieldValue = 1024 @@ -21,7 +21,7 @@ type Embed struct { //NewEmbed returns a new embed object func NewEmbed() *Embed { return &Embed{&discordgo.MessageEmbed{ - Color: discordEmbedColor, + Color: EmbedColor, }} } diff --git a/go.mod b/go.mod index dbf441d..2a92123 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,8 @@ require ( github.com/joho/godotenv v1.3.0 github.com/pkg/errors v0.9.1 github.com/robfig/cron/v3 v3.0.1 - github.com/tribalwarshelp/golang-sdk v0.0.0-20200604163817-64920bab73bb - github.com/tribalwarshelp/shared v0.0.0-20200604161459-deeeccf99815 + github.com/tribalwarshelp/golang-sdk v0.0.0-20200607150457-971c5e02b4df + github.com/tribalwarshelp/shared v0.0.0-20200607152914-8ab83c6d1364 golang.org/x/net v0.0.0-20200528225125-3c3fba18258b // indirect google.golang.org/protobuf v1.24.0 // indirect ) diff --git a/go.sum b/go.sum index 39fa8a5..057424f 100644 --- a/go.sum +++ b/go.sum @@ -101,8 +101,14 @@ github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYm github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= github.com/tribalwarshelp/golang-sdk v0.0.0-20200604163817-64920bab73bb h1:3arC78RszJkHTskhfPg/X4TXzlxHJFpF8FvDdFaavL8= github.com/tribalwarshelp/golang-sdk v0.0.0-20200604163817-64920bab73bb/go.mod h1:8ALIvjiYLt0RVXz8TwDTJ3X5KAHv3M7+iYF/SvcA+1A= +github.com/tribalwarshelp/golang-sdk v0.0.0-20200607150457-971c5e02b4df h1:nki0kQ7MyZnChZ7QDKyCc441rPEHBIZC8D3WWY0L+LM= +github.com/tribalwarshelp/golang-sdk v0.0.0-20200607150457-971c5e02b4df/go.mod h1:8ALIvjiYLt0RVXz8TwDTJ3X5KAHv3M7+iYF/SvcA+1A= github.com/tribalwarshelp/shared v0.0.0-20200604161459-deeeccf99815 h1:c+BTJgJyif/HDt8bRxqNaK7zQReI59ho9yWdk7a/gNo= github.com/tribalwarshelp/shared v0.0.0-20200604161459-deeeccf99815/go.mod h1:tf+2yTHasV6jAF3V2deZ9slNoCyBzC0fMdTjI7clf6Y= +github.com/tribalwarshelp/shared v0.0.0-20200607152720-fcd5cd5455a3 h1:mMarqvZbHGPTg63QxB9BTgKgYfnBx6nePywslMJ1M4s= +github.com/tribalwarshelp/shared v0.0.0-20200607152720-fcd5cd5455a3/go.mod h1:tf+2yTHasV6jAF3V2deZ9slNoCyBzC0fMdTjI7clf6Y= +github.com/tribalwarshelp/shared v0.0.0-20200607152914-8ab83c6d1364 h1:Pi3n/0FkrHrBO0oW9Lp6kRAEc4qKe7p8lohrEv4GOXE= +github.com/tribalwarshelp/shared v0.0.0-20200607152914-8ab83c6d1364/go.mod h1:tf+2yTHasV6jAF3V2deZ9slNoCyBzC0fMdTjI7clf6Y= github.com/vmihailenco/bufpool v0.1.5/go.mod h1:fL9i/PRTuS7AELqAHwSU1Zf1c70xhkhGe/cD5ud9pJk= github.com/vmihailenco/bufpool v0.1.11 h1:gOq2WmBrq0i2yW5QJ16ykccQ4wH9UyEsgLm6czKAd94= github.com/vmihailenco/bufpool v0.1.11/go.mod h1:AFf/MOy3l2CFTKbxwt0mp2MwnqjNEs5H/UxrkA5jxTQ=