dcbot/internal/discord/job_execute_monitors.go
Dawid Wysokiński eec0909c78
All checks were successful
continuous-integration/drone/push Build is passing
feat: notifications (#25)
Reviewed-on: #25
2022-10-27 09:56:40 +00:00

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
}
}