127 lines
3.0 KiB
Go
127 lines
3.0 KiB
Go
|
package discord
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
"gitea.dwysokinski.me/twhelp/dcbot/internal/domain"
|
||
|
"github.com/bwmarrin/discordgo"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
executeMonitorsJobTimeout = 2 * time.Minute
|
||
|
colorGreen = 0x00ff00
|
||
|
colorRed = 0xff0000
|
||
|
)
|
||
|
|
||
|
type executeMonitorsJob struct {
|
||
|
s *discordgo.Session
|
||
|
svc MonitorService
|
||
|
}
|
||
|
|
||
|
func (e *executeMonitorsJob) Run() {
|
||
|
ctx, cancel := context.WithTimeout(context.Background(), executeMonitorsJobTimeout)
|
||
|
defer cancel()
|
||
|
|
||
|
notifications, err := e.svc.Execute(ctx)
|
||
|
if err != nil {
|
||
|
// TODO: log this error
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var wg sync.WaitGroup
|
||
|
|
||
|
for ch, embeds := range ennoblementNotificationsToEmbeds(notifications) {
|
||
|
wg.Add(1)
|
||
|
|
||
|
go func(ch string, embeds []*discordgo.MessageEmbed) {
|
||
|
defer wg.Done()
|
||
|
for _, embed := range embeds {
|
||
|
_, _ = e.s.ChannelMessageSendEmbed(ch, embed)
|
||
|
}
|
||
|
}(ch, embeds)
|
||
|
}
|
||
|
|
||
|
wg.Wait()
|
||
|
}
|
||
|
|
||
|
func ennoblementNotificationsToEmbeds(ns []domain.EnnoblementNotification) map[string][]*discordgo.MessageEmbed {
|
||
|
m := make(map[string]map[domain.EnnoblementNotificationType][]*discordgo.MessageEmbed)
|
||
|
timestamp := formatTimestamp(time.Now())
|
||
|
for _, n := range ns {
|
||
|
if _, ok := m[n.ChannelID]; !ok {
|
||
|
m[n.ChannelID] = make(map[domain.EnnoblementNotificationType][]*discordgo.MessageEmbed)
|
||
|
}
|
||
|
|
||
|
embeds := m[n.ChannelID][n.Type]
|
||
|
|
||
|
str := buildEnnoblementNotificationDescription(n)
|
||
|
if l := len(embeds); l == 0 || len(embeds[l-1].Description)+len(str) > embedDescriptionCharLimit {
|
||
|
embeds = append(embeds, &discordgo.MessageEmbed{
|
||
|
Color: ennoblementNotificationTypeToColor(n.Type),
|
||
|
Type: discordgo.EmbedTypeRich,
|
||
|
Timestamp: timestamp,
|
||
|
})
|
||
|
}
|
||
|
if len(embeds[len(embeds)-1].Description) > 0 {
|
||
|
str = "\n" + str
|
||
|
}
|
||
|
embeds[len(embeds)-1].Description += str
|
||
|
|
||
|
m[n.ChannelID][n.Type] = embeds
|
||
|
}
|
||
|
|
||
|
res := make(map[string][]*discordgo.MessageEmbed, len(m))
|
||
|
for ch, innerMap := range m {
|
||
|
cnt := 0
|
||
|
for _, embeds := range innerMap {
|
||
|
cnt += len(embeds)
|
||
|
}
|
||
|
|
||
|
res[ch] = make([]*discordgo.MessageEmbed, 0, cnt)
|
||
|
for _, embeds := range innerMap {
|
||
|
res[ch] = append(res[ch], embeds...)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return res
|
||
|
}
|
||
|
|
||
|
func buildEnnoblementNotificationDescription(n domain.EnnoblementNotification) string {
|
||
|
return fmt.Sprintf(
|
||
|
"%s has taken %s (Old owner: %s)",
|
||
|
nullPlayerMetaToMarkdown(n.Ennoblement.NewOwner),
|
||
|
buildLink(n.Ennoblement.Village.FullName, n.Ennoblement.Village.ProfileURL),
|
||
|
nullPlayerMetaToMarkdown(n.Ennoblement.OldOwner),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func nullPlayerMetaToMarkdown(p domain.NullPlayerMeta) string {
|
||
|
if !p.Valid {
|
||
|
return "Barbarians"
|
||
|
}
|
||
|
|
||
|
tag := p.Player.Tribe.Tribe.Tag
|
||
|
if tag == "" {
|
||
|
tag = "-"
|
||
|
}
|
||
|
|
||
|
return buildLink(p.Player.Name, p.Player.ProfileURL) +
|
||
|
" [" +
|
||
|
buildLink(tag, p.Player.Tribe.Tribe.ProfileURL) +
|
||
|
"]"
|
||
|
}
|
||
|
|
||
|
func ennoblementNotificationTypeToColor(t domain.EnnoblementNotificationType) int {
|
||
|
switch t {
|
||
|
case domain.EnnoblementNotificationTypeGain:
|
||
|
return colorGreen
|
||
|
case domain.EnnoblementNotificationTypeLoss:
|
||
|
fallthrough
|
||
|
default:
|
||
|
return colorRed
|
||
|
}
|
||
|
}
|