This repository has been archived on 2022-10-02. You can view files and clone it, but cannot push or open issues or pull requests.
dcbot-old/cron/handler.go

321 lines
9.0 KiB
Go

package cron
import (
"context"
"fmt"
"time"
"github.com/tribalwarshelp/shared/tw"
"github.com/nicksnyder/go-i18n/v2/i18n"
"github.com/tribalwarshelp/dcbot/message"
"github.com/pkg/errors"
"github.com/tribalwarshelp/shared/mode"
shared_models "github.com/tribalwarshelp/shared/models"
"github.com/tribalwarshelp/dcbot/discord"
"github.com/tribalwarshelp/dcbot/group"
"github.com/tribalwarshelp/dcbot/models"
"github.com/tribalwarshelp/dcbot/observation"
"github.com/tribalwarshelp/dcbot/server"
"github.com/tribalwarshelp/dcbot/utils"
"github.com/tribalwarshelp/golang-sdk/sdk"
)
type handler struct {
lastEnnoblementAt map[string]time.Time
serverRepo server.Repository
observationRepo observation.Repository
groupRepo group.Repository
discord *discord.Session
api *sdk.SDK
status string
}
func (h *handler) loadEnnoblements(servers []string) (map[string]ennoblements, error) {
m := make(map[string]ennoblements)
if len(servers) == 0 {
return m, nil
}
query := ""
for _, server := range servers {
lastEnnoblementAt, ok := h.lastEnnoblementAt[server]
if !ok {
lastEnnoblementAt = time.Now().Add(-1 * time.Minute)
h.lastEnnoblementAt[server] = lastEnnoblementAt
}
if mode.Get() == mode.DevelopmentMode {
lastEnnoblementAt = time.Now().Add(-1 * time.Hour * 2)
}
lastEnnoblementAtJSON, err := lastEnnoblementAt.MarshalJSON()
if err != nil {
continue
}
query += fmt.Sprintf(`
%s: ennoblements(server: "%s", filter: { ennobledAtGT: %s }) {
items {
%s
ennobledAt
}
}
`, server,
server,
string(lastEnnoblementAtJSON),
sdk.EnnoblementInclude{
NewOwner: true,
Village: true,
NewOwnerInclude: sdk.PlayerInclude{
Tribe: true,
},
OldOwner: true,
OldOwnerInclude: sdk.PlayerInclude{
Tribe: true,
},
}.String())
}
resp := make(map[string]*sdk.EnnoblementList)
if err := h.api.Post(fmt.Sprintf(`query { %s }`, query), &resp); err != nil {
return m, errors.Wrap(err, "loadEnnoblements")
}
for server, singleServerResp := range resp {
if singleServerResp == nil {
continue
}
m[server] = ennoblements(singleServerResp.Items)
lastEnnoblement := m[server].getLastEnnoblement()
if lastEnnoblement != nil {
h.lastEnnoblementAt[server] = lastEnnoblement.EnnobledAt
}
}
return m, nil
}
func (h *handler) loadVersions(servers []string) ([]*shared_models.Version, error) {
versionCodes := []shared_models.VersionCode{}
cache := make(map[shared_models.VersionCode]bool)
for _, server := range servers {
languageTag := tw.VersionCodeFromServerKey(server)
if languageTag.IsValid() && !cache[languageTag] {
cache[languageTag] = true
versionCodes = append(versionCodes, languageTag)
}
}
if len(versionCodes) == 0 {
return []*shared_models.Version{}, nil
}
versionList, err := h.api.Version.Browse(0, 0, []string{"code ASC"}, &shared_models.VersionFilter{
Code: versionCodes,
})
if err != nil {
return nil, errors.Wrap(err, "cannot load versions")
}
return versionList.Items, nil
}
func (h *handler) checkEnnoblements() {
servers, err := h.observationRepo.FetchServers(context.Background())
if err != nil {
log.Errorln("checkEnnoblements:", err.Error())
return
}
log.
WithField("servers", servers).
Info("checkEnnoblements: loaded servers")
groups, total, err := h.groupRepo.Fetch(context.Background(), nil)
if err != nil {
log.Errorln("checkEnnoblements:", err.Error())
return
}
log.
WithField("numberOfGroups", total).
Info("checkEnnoblements: loaded groups")
versions, err := h.loadVersions(servers)
if err != nil {
log.Errorln("checkEnnoblements:", err)
return
}
log.
WithField("numberOfVersions", len(versions)).
Info("checkEnnoblements: loaded versions")
ennoblementsByServerKey, err := h.loadEnnoblements(servers)
if err != nil {
log.Errorln("checkEnnoblements:", err)
}
log.Info("checkEnnoblements: loaded ennoblements")
for _, group := range groups {
if group.ConqueredVillagesChannelID == "" && group.LostVillagesChannelID == "" {
continue
}
localizer := message.NewLocalizer(group.Server.Lang)
lostVillagesMsg := &discord.MessageEmbed{}
conqueredVillagesMsg := &discord.MessageEmbed{}
for _, observation := range group.Observations {
ennoblements, ok := ennoblementsByServerKey[observation.Server]
version := utils.FindVersionByCode(versions, tw.VersionCodeFromServerKey(observation.Server))
if ok && version != nil && version.Host != "" {
if group.LostVillagesChannelID != "" {
for _, ennoblement := range ennoblements.getLostVillagesByTribe(observation.TribeID) {
if !utils.IsPlayerTribeNil(ennoblement.NewOwner) &&
group.Observations.Contains(observation.Server, ennoblement.NewOwner.Tribe.ID) {
continue
}
newMsgDataConfig := newMessageConfig{
host: version.Host,
server: observation.Server,
ennoblement: ennoblement,
t: messageTypeLost,
localizer: localizer,
}
lostVillagesMsg.Append(newMessage(newMsgDataConfig).String())
}
}
if group.ConqueredVillagesChannelID != "" {
for _, ennoblement := range ennoblements.getConqueredVillagesByTribe(observation.TribeID, group.ShowInternals) {
isInTheSameGroup := !utils.IsPlayerTribeNil(ennoblement.OldOwner) &&
group.Observations.Contains(observation.Server, ennoblement.OldOwner.Tribe.ID)
if (!group.ShowInternals && isInTheSameGroup) ||
(!group.ShowEnnobledBarbarians && isBarbarian(ennoblement.OldOwner)) {
continue
}
newMsgDataConfig := newMessageConfig{
host: version.Host,
server: observation.Server,
ennoblement: ennoblement,
t: messageTypeConquer,
localizer: localizer,
}
conqueredVillagesMsg.Append(newMessage(newMsgDataConfig).String())
}
}
}
}
timestamp := time.Now().Format(time.RFC3339)
if group.ConqueredVillagesChannelID != "" && !conqueredVillagesMsg.IsEmpty() {
title := localizer.MustLocalize(&i18n.LocalizeConfig{
MessageID: message.CronConqueredVillagesTitle,
DefaultMessage: message.FallbackMsg(message.CronConqueredVillagesTitle,
"Conquered villages"),
})
go h.discord.SendEmbed(group.ConqueredVillagesChannelID,
discord.
NewEmbed().
SetTitle(title).
SetColor(colorConqueredVillages).
SetFields(conqueredVillagesMsg.ToMessageEmbedFields()).
SetTimestamp(timestamp).
MessageEmbed)
}
if group.LostVillagesChannelID != "" && !lostVillagesMsg.IsEmpty() {
title := localizer.MustLocalize(&i18n.LocalizeConfig{
MessageID: message.CronLostVillagesTitle,
DefaultMessage: message.FallbackMsg(message.CronLostVillagesTitle,
"Lost villages"),
})
go h.discord.SendEmbed(group.LostVillagesChannelID,
discord.
NewEmbed().
SetTitle(title).
SetColor(colorLostVillages).
SetFields(lostVillagesMsg.ToMessageEmbedFields()).
SetTimestamp(timestamp).
MessageEmbed)
}
}
}
func (h *handler) checkBotServers() {
servers, total, err := h.serverRepo.Fetch(context.Background(), nil)
if err != nil {
log.Error("checkBotServers: " + err.Error())
return
}
log.
WithField("numberOfServers", total).
Info("checkBotServers: loaded servers")
idsToDelete := []string{}
for _, server := range servers {
if isGuildMember, _ := h.discord.IsGuildMember(server.ID); !isGuildMember {
idsToDelete = append(idsToDelete, server.ID)
}
}
if len(idsToDelete) > 0 {
deleted, err := h.serverRepo.Delete(context.Background(), &models.ServerFilter{
ID: idsToDelete,
})
if err != nil {
log.Error("checkBotServers: " + err.Error())
} else {
log.
WithField("numberOfDeletedServers", len(deleted)).
Info("checkBotServers: deleted servers")
}
}
}
func (h *handler) deleteClosedTribalWarsServers() {
servers, err := h.observationRepo.FetchServers(context.Background())
if err != nil {
log.Error("deleteClosedTribalWarsServers: " + err.Error())
return
}
log.
WithField("servers", servers).
Info("deleteClosedTribalWarsServers: loaded servers")
list, err := h.api.Server.Browse(0, 0, []string{"key ASC"}, &shared_models.ServerFilter{
Key: servers,
Status: []shared_models.ServerStatus{shared_models.ServerStatusClosed},
}, nil)
if err != nil {
log.Errorln("deleteClosedTribalWarsServers: " + err.Error())
return
}
if list == nil || list.Items == nil {
return
}
keys := []string{}
for _, server := range list.Items {
keys = append(keys, server.Key)
}
if len(keys) > 0 {
deleted, err := h.observationRepo.Delete(context.Background(), &models.ObservationFilter{
Server: keys,
})
if err != nil {
log.Errorln("deleteClosedTribalWarsServers: " + err.Error())
} else {
log.
WithField("numberOfDeletedObservations", len(deleted)).
Infof("deleteClosedTribalWarsServers: deleted observations")
}
}
}
func (h *handler) updateBotStatus() {
if err := h.discord.UpdateStatus(h.status); err != nil {
log.Error("updateBotStatus: " + err.Error())
}
}