package handlers import ( "context" "gralias/models" "strconv" "sync" "time" ) type roomTimer struct { ticker *time.Ticker done chan bool } var ( timers = make(map[string]*roomTimer) mu sync.Mutex ) func StartTurnTimer(roomID string, duration time.Duration) { mu.Lock() defer mu.Unlock() if _, exists := timers[roomID]; exists { return // Timer already running } ticker := time.NewTicker(1 * time.Second) done := make(chan bool) timers[roomID] = &roomTimer{ticker: ticker, done: done} go func() { settings, err := repo.SettingsGetByRoomID(context.Background(), roomID) if err != nil { log.Error("failed to get settings by room id", "error", err) StopTurnTimer(roomID) return } for { select { case <-done: return case <-ticker.C: if settings.TurnSecondsLeft <= 0 { log.Info("turn time is over", "room_id", roomID) room, err := repo.RoomGetByID(context.Background(), roomID) if err != nil { log.Error("failed to get room by id", "error", err) StopTurnTimer(roomID) return } room.ChangeTurn() room.MimeDone = false if err := repo.RoomUpdate(context.Background(), room); err != nil { log.Error("failed to save room", "error", err) } notify(models.NotifyTurnTimerPrefix+room.ID, strconv.FormatUint(uint64(room.Settings.TurnSecondsLeft), 10)) notifyBotIfNeeded(room) StopTurnTimer(roomID) return } settings.TurnSecondsLeft-- if err := repo.SettingsUpdate(context.Background(), settings); err != nil { log.Error("failed to update settings", "error", err) } notify(models.NotifyRoomUpdatePrefix+roomID, "") } } }() } func StopTurnTimer(roomID string) { mu.Lock() defer mu.Unlock() if timer, exists := timers[roomID]; exists { timer.ticker.Stop() close(timer.done) delete(timers, roomID) } }