diff --git a/envvars.go b/envvars.go index 16185a2..dece52c 100644 --- a/envvars.go +++ b/envvars.go @@ -21,6 +21,7 @@ var ( TelegramOrganizeMessagePatternStr = logic.EscSeqReplacer.Replace(envvars.String("TELEGRAM_ORGANIZE_MESSAGE_PATTERN", `Download finished{{range .}}\n{{.Anime.Title.UserPreferred}} episode {{.Episode}}{{end}}`)) TelegramOrganizeMessagePattern = template.Must(template.New("TELEGRAM_ORGANIZE_MESSAGE_PATTERN").Parse(TelegramOrganizeMessagePatternStr)) TelegramOrganizeMessageSendCondition = envvars.ObjectSlice("TELEGRAM_ORGANIZE_MESSAGE_SEND_CONDITION", ",", []SendCondition{SendConditionAlways}, SendConditionFromString) + TelegramOrganizeMessageSendInterval = envvars.Duration("TELEGRAM_ORGANIZE_MESSAGE_SEND_INTERVAL", 0) Uid = envvars.Object("UID", 1000, func(s string) (int, error) { if uid, err := strconv.Atoi(s); err == nil { diff --git a/handle_file.go b/handle_file.go index b7424e0..b144dfe 100644 --- a/handle_file.go +++ b/handle_file.go @@ -86,7 +86,7 @@ func HandleParsedFile(w io.Writer, parsedFile *model.ParsedFile) { } func OrganizeAnimeEpisode(w io.Writer, parsedFile *model.ParsedFile) error { - SendTelegramAnimeEpMessage(TelegramOrganizeMessagePattern, parsedFile.AnimeEpisode()) + PrepareTelegramAnimeEpMessage(parsedFile.AnimeEpisode()) start := time.Now() diff --git a/telegram.go b/telegram.go index e41a69b..9640f51 100644 --- a/telegram.go +++ b/telegram.go @@ -2,9 +2,8 @@ package main import ( "context" - "fmt" "strings" - "text/template" + "time" "git.milar.in/milarin/adverr" "git.milar.in/milarin/anilist" @@ -16,6 +15,7 @@ import ( ) var TelegramBot *tgbotapi.BotAPI +var AnimeEpisodeMessageChannel = make(chan model.AnimeEpisode, 1000) func InitTelegramBot() error { if TelegramBotToken != "" && TelegramChatID != 0 { @@ -25,9 +25,44 @@ func InitTelegramBot() error { } TelegramBot = bot } + go SendMessagePeriodically() return nil } +func SendMessagePeriodically() { + var messagesPerInterval <-chan []model.AnimeEpisode + + if TelegramOrganizeMessageSendInterval > 0 { + lastCycle := time.Now().Truncate(TelegramOrganizeMessageSendInterval) + nextCycle := lastCycle.Add(TelegramOrganizeMessageSendInterval) + time.Sleep(time.Until(nextCycle)) + sendAllQueuedAnimeEpisodes() + + grouperFunc := func(current []model.AnimeEpisode, value model.AnimeEpisode) []model.AnimeEpisode { + return append(current, value) + } + messagesPerInterval = channel.GroupByTime(AnimeEpisodeMessageChannel, TelegramOrganizeMessageSendInterval, grouperFunc) + } else { + mapperFunc := func(value model.AnimeEpisode) []model.AnimeEpisode { + return []model.AnimeEpisode{value} + } + messagesPerInterval = channel.MapSuccessive(AnimeEpisodeMessageChannel, mapperFunc) + } + + for animeEpisodes := range messagesPerInterval { + sendTelegramAnimeEpMessage(animeEpisodes) + } +} + +func sendAllQueuedAnimeEpisodes() { + queuedEpisodeAmount := len(AnimeEpisodeMessageChannel) + animeEpisodes := make([]model.AnimeEpisode, 0, queuedEpisodeAmount) + for i := 0; i < queuedEpisodeAmount; i++ { + animeEpisodes = append(animeEpisodes, <-AnimeEpisodeMessageChannel) + } + sendTelegramAnimeEpMessage(animeEpisodes) +} + func SendTelegramMessage(text string) { if TelegramBot == nil { return @@ -40,23 +75,26 @@ func SendTelegramMessage(text string) { } } -func SendTelegramAnimeEpMessage(messagePattern *template.Template, animeEp model.AnimeEpisode) { +func PrepareTelegramAnimeEpMessage(animeEp model.AnimeEpisode) { shouldSendMessage, err := CheckSendConditions(animeEp) if err != nil { adverr.Println(adverr.Wrap("could not check telegram message send conditions", err)) } - fmt.Println("shouldSendMessage:", shouldSendMessage) - if !shouldSendMessage { - fmt.Println("do not send message") return } - fmt.Println("send message") + AnimeEpisodeMessageChannel <- animeEp +} + +func sendTelegramAnimeEpMessage(animeEpisodes []model.AnimeEpisode) { + if len(animeEpisodes) == 0 { + return + } b := new(strings.Builder) - if err := messagePattern.Execute(b, []model.AnimeEpisode{animeEp}); err != nil { + if err := TelegramOrganizeMessagePattern.Execute(b, animeEpisodes); err != nil { adverr.Println(adverr.Wrap("could not send telegram message", err)) } @@ -69,25 +107,18 @@ func CheckSendConditions(animeEp model.AnimeEpisode) (bool, error) { return false, err } - fmt.Println("listEntry:", listEntry) - for _, sendCondition := range AllSendConditions { // check if user configured current sendCondition if !slices.Contains(TelegramOrganizeMessageSendCondition, sendCondition) { - fmt.Println("condition not configured", sendCondition) continue } // check if current sendCondition applies for given anime episode if sendCondition.ShouldSend(animeEp, listEntry) { - fmt.Println("condition applies", sendCondition) return true, nil } - - fmt.Println("condition does not apply", sendCondition) } - fmt.Println("no condition applies") return false, nil }