package main import ( "context" "sync" "time" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" ) type messageData struct { key string messID int chatID int64 data interface{} timer *time.Timer } type messageStorage struct { m sync.Mutex messages []*messageData } func NewMessageStorage() *messageStorage { return &messageStorage{ messages: make([]*messageData, 0, 20), } } func deleteMessageFromTelegram(ctx context.Context, messID int, chatID int64) { botApi := getBotApi(ctx) _, err := botApi.DeleteMessage(tgbotapi.DeleteMessageConfig{ MessageID: messID, ChatID: chatID, }) if err != nil { getLogger(ctx).Error(err) } } func (ms *messageStorage) run(ctx context.Context) { <-ctx.Done() ms.m.Lock() defer ms.m.Unlock() for _, m := range ms.messages { deleteMessageFromTelegram(ctx, m.messID, m.chatID) } ms.messages = ms.messages[:] } func (ms *messageStorage) runTimeCleaner(ctx context.Context, md *messageData, d time.Duration) { if d <= 0 { md.timer = nil return } t := time.NewTimer(d) md.timer = t go func() { <-t.C ms.m.Lock() defer ms.m.Unlock() if md.timer == t { for i, m := range ms.messages { if m == md { deleteMessageFromTelegram(ctx, m.messID, m.chatID) ms.messages = append(ms.messages[:i], ms.messages[i+1:]...) return } } } }() } type messageChanger func(interface{}) (string, interface{}) func (ms *messageStorage) apply(ctx context.Context, key string, d time.Duration, mc messageChanger) error { ms.m.Lock() defer ms.m.Unlock() botApi := getBotApi(ctx) cfg := getConfig(ctx) for _, md := range ms.messages { if md.key == key { text, data := mc(md.data) mess := tgbotapi.NewEditMessageText(md.chatID, md.messID, text) mess.ParseMode = tgbotapi.ModeMarkdown _, err := botApi.Send(mess) if err != nil { return err } md.data = data ms.runTimeCleaner(ctx, md, d) return nil } } text, data := mc(nil) mess := tgbotapi.NewMessage(cfg.ChatID, text) mess.ParseMode = tgbotapi.ModeMarkdown m, err := botApi.Send(mess) if err != nil { return err } md := &messageData{ key: key, messID: m.MessageID, chatID: cfg.ChatID, data: data, } ms.messages = append(ms.messages, md) ms.runTimeCleaner(ctx, md, d) return nil }