From bea515cb3421f899436b7eb76bd19d9626ec83d1 Mon Sep 17 00:00:00 2001 From: iskanye Date: Mon, 16 Feb 2026 11:21:39 +0300 Subject: [PATCH 1/7] feat: profile redesign --- internal/handlers/bot/users.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/internal/handlers/bot/users.go b/internal/handlers/bot/users.go index 7ca7394..d88893d 100644 --- a/internal/handlers/bot/users.go +++ b/internal/handlers/bot/users.go @@ -175,14 +175,21 @@ func (b *Bot) getUser(c tele.Context) (models.User, error) { // Функция отображения профиля func (b *Bot) showProfile(c tele.Context, user models.User) error { - profile := fmt.Sprintf( - "Группа: %s\nФИО: %s\nПрава админа: %t", - user.Group, user.Name, user.QueueAccess, + var profileStr strings.Builder + fmt.Fprintf( + &profileStr, + "ФИО: %s\nГруппа: %s\nДоступ к очереди: ", + user.Name, user.Group, ) + if user.QueueAccess { + profileStr.WriteString("✔️") + } else { + profileStr.WriteString("✖️") + } if msg, ok := c.Get("msg").(tele.Editable); ok { - _, err := c.Bot().Edit(msg, profile, b.startMenu) + _, err := c.Bot().Edit(msg, profileStr.String(), b.startMenu) return err } else { - return c.Send(profile, b.startMenu) + return c.Send(profileStr.String(), b.startMenu) } } From b7883c8293a6c23c56e4af4b3f67a310b796a794 Mon Sep 17 00:00:00 2001 From: iskanye Date: Tue, 17 Feb 2026 14:17:35 +0300 Subject: [PATCH 2/7] feat: queue redesign --- internal/handlers/bot/queue.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/handlers/bot/queue.go b/internal/handlers/bot/queue.go index ecb96ce..c9a2aa5 100644 --- a/internal/handlers/bot/queue.go +++ b/internal/handlers/bot/queue.go @@ -236,7 +236,7 @@ func (b *Bot) showSubject( entries, err := b.queueService.Range(b.ctx, queue) if errors.Is(err, services.ErrNotFound) { - sb.WriteString("\nОчередь не создана") + sb.WriteString("\nОчередь пуста") } else if err == nil { // Находим имена пользователей for i, entry := range entries { @@ -250,7 +250,7 @@ func (b *Bot) showSubject( return err } - sb.WriteString(fmt.Sprintf("\n%3d. %s", i+1, user.Name)) + fmt.Fprintf(&sb, "\n%3d. %s", i+1, user.Name) } // Находим позицию текущего пользователя From 7f4b8959bc3c688f33ee93f044d298478dcaccc3 Mon Sep 17 00:00:00 2001 From: iskanye Date: Tue, 17 Feb 2026 14:23:22 +0300 Subject: [PATCH 3/7] feat: queue list emoji --- internal/handlers/bot/queue.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/handlers/bot/queue.go b/internal/handlers/bot/queue.go index c9a2aa5..ab76778 100644 --- a/internal/handlers/bot/queue.go +++ b/internal/handlers/bot/queue.go @@ -147,9 +147,9 @@ func (b *Bot) ChooseSubject(c telebot.Context) error { // Проверяем, есть ли уже очередь по этому предмету _, err := b.queueService.Range(b.ctx, queue) if err == nil { - btnText.WriteString("✅ ") + btnText.WriteString("🟩 ") } else if errors.Is(err, services.ErrNotFound) { - btnText.WriteString("❌ ") + btnText.WriteString("🟥 ") } btnText.WriteString(subjects[i]) From f5e1787956908856dbbb607ca24ef6ccdc754b3e Mon Sep 17 00:00:00 2001 From: iskanye Date: Tue, 17 Feb 2026 15:10:03 +0300 Subject: [PATCH 4/7] feat: queue len --- .gitignore | 3 ++- internal/handlers/bot/queue.go | 8 +++----- internal/interfaces/services.go | 5 +++++ internal/services/queue/queue.go | 31 +++++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 1b37fe0..59bfdc9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .env -*.exe \ No newline at end of file +*.exe +mockery diff --git a/internal/handlers/bot/queue.go b/internal/handlers/bot/queue.go index ab76778..0d4063c 100644 --- a/internal/handlers/bot/queue.go +++ b/internal/handlers/bot/queue.go @@ -145,11 +145,9 @@ func (b *Bot) ChooseSubject(c telebot.Context) error { } // Проверяем, есть ли уже очередь по этому предмету - _, err := b.queueService.Range(b.ctx, queue) + length, err := b.queueService.Len(b.ctx, queue) if err == nil { - btnText.WriteString("🟩 ") - } else if errors.Is(err, services.ErrNotFound) { - btnText.WriteString("🟥 ") + fmt.Fprintf(&btnText, "(Чел. в очереди: %d)", length) } btnText.WriteString(subjects[i]) @@ -232,7 +230,7 @@ func (b *Bot) showSubject( entry models.QueueEntry, ) error { var sb strings.Builder - sb.WriteString("Очередь " + queue.Key()) + sb.WriteString(queue.Key()) entries, err := b.queueService.Range(b.ctx, queue) if errors.Is(err, services.ErrNotFound) { diff --git a/internal/interfaces/services.go b/internal/interfaces/services.go index 845edfc..76fccf6 100644 --- a/internal/interfaces/services.go +++ b/internal/interfaces/services.go @@ -61,6 +61,11 @@ type QueueService interface { queue models.Queue, entry models.QueueEntry, ) error + // Получает длину очереди + Len( + ctx context.Context, + queue models.Queue, + ) (int64, error) } // Сервис пользователей diff --git a/internal/services/queue/queue.go b/internal/services/queue/queue.go index 3671cc8..3e0b6ff 100644 --- a/internal/services/queue/queue.go +++ b/internal/services/queue/queue.go @@ -296,3 +296,34 @@ func (q *Queue) Remove( return nil } + +func (q *Queue) Len( + ctx context.Context, + queue models.Queue, +) (int64, error) { + const op = "queue.Len" + + log := q.log.With( + slog.String("op", op), + slog.String("queue_group", queue.Group), + slog.String("queue_subject", queue.Subject), + ) + + log.Info("Trying to get queue length") + + length, err := q.queueLength.Len(ctx, queue) + if err != nil { + log.Error("Failed to get queue length", + slog.String("err", err.Error()), + ) + + if errors.Is(err, repositories.ErrNotFound) { + return 0, fmt.Errorf("%s: %w", op, services.ErrNotFound) + } + return 0, fmt.Errorf("%s: %w", op, err) + } + + log.Info("Successfully got") + + return length, nil +} From 1f51c90306ae4226f95081be54dbb3b44a4957ea Mon Sep 17 00:00:00 2001 From: iskanye Date: Wed, 18 Feb 2026 00:25:21 +0300 Subject: [PATCH 5/7] feat: squares on inline buttons --- internal/handlers/bot/queue.go | 9 +++++++-- internal/repositories/redis/queue.go | 3 --- internal/services/queue/queue.go | 3 --- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/internal/handlers/bot/queue.go b/internal/handlers/bot/queue.go index 0d4063c..8a2fad4 100644 --- a/internal/handlers/bot/queue.go +++ b/internal/handlers/bot/queue.go @@ -146,8 +146,13 @@ func (b *Bot) ChooseSubject(c telebot.Context) error { // Проверяем, есть ли уже очередь по этому предмету length, err := b.queueService.Len(b.ctx, queue) - if err == nil { - fmt.Fprintf(&btnText, "(Чел. в очереди: %d)", length) + if err != nil { + return err + } + if length != 0 { + fmt.Fprintf(&btnText, "🟩 (Чел. в очереди: %d) ", length) + } else { + btnText.WriteString("🟥 (Нет очереди) ") } btnText.WriteString(subjects[i]) diff --git a/internal/repositories/redis/queue.go b/internal/repositories/redis/queue.go index 687bae8..6bffe9b 100644 --- a/internal/repositories/redis/queue.go +++ b/internal/repositories/redis/queue.go @@ -123,9 +123,6 @@ func (s *Storage) Len( len, err := s.cl.LLen(ctx, queue.Key()).Result() if err != nil { - if errors.Is(err, redis.Nil) { - return 0, fmt.Errorf("%s: %w", op, repositories.ErrNotFound) - } return 0, fmt.Errorf("%s: %w", op, err) } diff --git a/internal/services/queue/queue.go b/internal/services/queue/queue.go index 3e0b6ff..2cddf50 100644 --- a/internal/services/queue/queue.go +++ b/internal/services/queue/queue.go @@ -317,9 +317,6 @@ func (q *Queue) Len( slog.String("err", err.Error()), ) - if errors.Is(err, repositories.ErrNotFound) { - return 0, fmt.Errorf("%s: %w", op, services.ErrNotFound) - } return 0, fmt.Errorf("%s: %w", op, err) } From aede88b23679ebff7c48e016ea7d5ef7446ce38f Mon Sep 17 00:00:00 2001 From: iskanye Date: Wed, 18 Feb 2026 18:39:44 +0300 Subject: [PATCH 6/7] feat: bold text on current user in queue --- internal/handlers/bot/queue.go | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/internal/handlers/bot/queue.go b/internal/handlers/bot/queue.go index 8a2fad4..00406a8 100644 --- a/internal/handlers/bot/queue.go +++ b/internal/handlers/bot/queue.go @@ -150,11 +150,18 @@ func (b *Bot) ChooseSubject(c telebot.Context) error { return err } if length != 0 { - fmt.Fprintf(&btnText, "🟩 (Чел. в очереди: %d) ", length) + fmt.Fprintf(&btnText, "🟩 (В очереди: %d) ", length) } else { - btnText.WriteString("🟥 (Нет очереди) ") + btnText.WriteString("🟥 (Очереди нет) ") + } + + // Обрезаем слишком длинное название дисциплины + subjectSlice := []rune(subjects[i]) + if len(subjectSlice) >= 25 { + btnText.WriteString(string(subjectSlice[:22]) + "...") + } else { + btnText.WriteString(subjects[i]) } - btnText.WriteString(subjects[i]) btns[i] = subjectMarkup.Data(btnText.String(), b.subjectBtnUnique, data) btnText.Reset() @@ -253,20 +260,24 @@ func (b *Bot) showSubject( return err } - fmt.Fprintf(&sb, "\n%3d. %s", i+1, user.Name) + // Если это текущий пользователь, то выделяем жирным для видимости + if chatID == c.Chat().ID { + fmt.Fprintf(&sb, "\n*%3d. %s*", i+1, user.Name) + } else { + fmt.Fprintf(&sb, "\n%3d. %s", i+1, user.Name) + } } // Находим позицию текущего пользователя pos, err := b.queueService.Pos(b.ctx, queue, entry) - msgText := fmt.Sprintf("\nВаша текущая позиция в очереди - %d", pos) - if errors.Is(err, services.ErrNotFound) { - msgText = "\nВы не записаны в очередь" - } else if err != nil { + if err == nil { + fmt.Fprintf(&sb, "\nВы %d в очереди", pos) + } else if errors.Is(err, services.ErrNotFound) { + sb.WriteString("\nВы не записаны в очередь") + } else { return err } - - sb.WriteString(msgText) } else { return err } @@ -276,7 +287,7 @@ func (b *Bot) showSubject( menu = b.subjectAdminMenu } - err = c.Edit(sb.String(), menu) + err = c.Edit(sb.String(), menu, telebot.ModeMarkdown) if err != nil && !errors.Is(err, telebot.ErrSameMessageContent) { return err } From 81fc335e8cbca77495a99a28a36ce0c62ca1369b Mon Sep 17 00:00:00 2001 From: iskanye Date: Fri, 20 Feb 2026 11:50:01 +0300 Subject: [PATCH 7/7] feat: show if user in queue --- internal/handlers/bot/queue.go | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/internal/handlers/bot/queue.go b/internal/handlers/bot/queue.go index 00406a8..ea96bbd 100644 --- a/internal/handlers/bot/queue.go +++ b/internal/handlers/bot/queue.go @@ -118,7 +118,12 @@ func (b *Bot) LetAhead(c telebot.Context) error { // Выбрать предмет func (b *Bot) ChooseSubject(c telebot.Context) error { + // Данные о пользователе user := c.Get("user").(models.User) + entry := models.QueueEntry{ + ChatID: fmt.Sprint(c.Chat().ID), + } + groups, err := b.scheduleService.GetGroups(b.ctx, user.Group) if err != nil { return err @@ -144,24 +149,28 @@ func (b *Bot) ChooseSubject(c telebot.Context) error { Subject: data, } + // Проверяем находится ли в данной очереди человек + _, err := b.queueService.Pos(b.ctx, queue, entry) + if errors.Is(err, services.ErrNotFound) { + btnText.WriteRune('🟥') + } else if err == nil { + btnText.WriteRune('🟩') + } else { + return err + } + // Проверяем, есть ли уже очередь по этому предмету length, err := b.queueService.Len(b.ctx, queue) if err != nil { return err } - if length != 0 { - fmt.Fprintf(&btnText, "🟩 (В очереди: %d) ", length) - } else { - btnText.WriteString("🟥 (Очереди нет) ") - } - // Обрезаем слишком длинное название дисциплины - subjectSlice := []rune(subjects[i]) - if len(subjectSlice) >= 25 { - btnText.WriteString(string(subjectSlice[:22]) + "...") + if length != 0 { + fmt.Fprintf(&btnText, " (%d чел.) ", length) } else { - btnText.WriteString(subjects[i]) + btnText.WriteString(" (Пусто) ") } + btnText.WriteString(subjects[i]) btns[i] = subjectMarkup.Data(btnText.String(), b.subjectBtnUnique, data) btnText.Reset() @@ -187,10 +196,6 @@ func (b *Bot) ChooseSubject(c telebot.Context) error { Subject: subject, } - entry := models.QueueEntry{ - ChatID: fmt.Sprint(c.Chat().ID), - } - err = b.queueService.SaveToCache(b.ctx, c.Chat().ID, queue) if err != nil { return err