Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 24 additions & 18 deletions internal/bot/bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ type Bot struct {
b *tele.Bot

// Кнопки
editBtn *tele.Btn
chooseBtn *tele.Btn
returnBtn *tele.Btn
refreshBtn *tele.Btn
pushBtn *tele.Btn
letAheadBtn *tele.Btn
popBtn *tele.Btn
clearBtn *tele.Btn
removeBtn *tele.Btn
editBtn *tele.Btn
chooseBtn *tele.Btn
returnBtn *tele.Btn
refreshBtn *tele.Btn
pushBtn *tele.Btn
pushPriorityBtn *tele.Btn
letAheadBtn *tele.Btn
popBtn *tele.Btn
clearBtn *tele.Btn
removeBtn *tele.Btn

// Менюшки
startMenu *tele.ReplyMarkup
Expand Down Expand Up @@ -65,6 +66,7 @@ func New(
returnBtn := markup.Data("Назад", "return")
refreshBtn := markup.Data("Обновить", "update")
pushBtn := markup.Data("Записаться", "push")
pushPriorityBtn := markup.Data("Записаться на место", "push-priority")
popBtn := markup.Data("Позвать на сдачу", "pop")
clearBtn := markup.Data("Очистить очередь", "clear")
letAheadBtn := markup.Data("Пропустить в очереди", "let-ahead")
Expand All @@ -81,6 +83,7 @@ func New(
subjectMenu.Inline(
markup.Row(returnBtn, refreshBtn),
markup.Row(pushBtn),
markup.Row(pushPriorityBtn),
markup.Row(letAheadBtn),
markup.Row(removeBtn),
)
Expand All @@ -90,6 +93,7 @@ func New(
subjectAdminMenu.Inline(
markup.Row(returnBtn, refreshBtn),
markup.Row(pushBtn),
markup.Row(pushPriorityBtn),
markup.Row(letAheadBtn),
markup.Row(removeBtn),
markup.Row(popBtn),
Expand All @@ -99,15 +103,16 @@ func New(
return &Bot{
b: b,

editBtn: &editBtn,
chooseBtn: &chooseBtn,
returnBtn: &returnBtn,
refreshBtn: &refreshBtn,
pushBtn: &pushBtn,
letAheadBtn: &letAheadBtn,
popBtn: &popBtn,
clearBtn: &clearBtn,
removeBtn: &removeBtn,
editBtn: &editBtn,
chooseBtn: &chooseBtn,
returnBtn: &returnBtn,
refreshBtn: &refreshBtn,
pushBtn: &pushBtn,
pushPriorityBtn: &pushPriorityBtn,
letAheadBtn: &letAheadBtn,
popBtn: &popBtn,
clearBtn: &clearBtn,
removeBtn: &removeBtn,

startMenu: startMenu,
subjectMenu: subjectMenu,
Expand Down Expand Up @@ -162,6 +167,7 @@ func (b *Bot) Register(
// Требует получить очередь из кеша
authorized.Handle(b.refreshBtn, handlers.Refresh, middlewares.GetQueue)
authorized.Handle(b.pushBtn, handlers.Push, middlewares.GetQueue)
authorized.Handle(b.pushPriorityBtn, handlers.PushPriority, middlewares.GetQueue)
authorized.Handle(b.letAheadBtn, handlers.LetAhead, middlewares.GetQueue)
authorized.Handle(b.removeBtn, handlers.Remove, middlewares.GetQueue)
authorized.Handle(b.popBtn, handlers.Pop, middlewares.GetQueue)
Expand Down
62 changes: 55 additions & 7 deletions internal/handlers/bot/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,58 @@ func (b *Bot) Push(c telebot.Context) error {
return b.showSubject(c, queue, entry)
}

// Пушает в очередь с указанием на конкретное место
func (b *Bot) PushPriority(c telebot.Context) error {
queue := c.Get("queue").(models.Queue)

entry := models.QueueEntry{
ChatID: fmt.Sprint(c.Chat().ID),
}

// Пробуем пока не получится встать в очередь
getPos:
if err := c.Send("Введите на какую позицию в очереди хотите встать"); err != nil {
return nil
}

// Получаем от пользователя ввод числа
if err := b.dialogue(c, func(ch <-chan string, c telebot.Context) error {
for pos := range ch {
if posInt, err := strconv.Atoi(pos); err == nil && posInt > 0 {
entry.Position = posInt
break
}

if err := c.Send("Невозможно привести к числу или неверное число, попробуйте снова"); err != nil {
return nil
}
}
return nil
}); err != nil {
return err
}

err := b.queueService.Push(b.ctx, queue, entry)
if err != nil {
if errors.Is(err, services.ErrAlreadyInQueue) {
return c.Send("Вы уже в очереди")
}
if errors.Is(err, services.ErrPlaceTaken) {
// Если место занято продолжаем цикл, пока пользователь не введёт
// доступную позицию в очереди
err = c.Send("Место уже занято")
if err != nil {
return err
}
goto getPos
}

return err
}

return b.showSubject(c, queue, entry)
}

// Попает из очереди
func (b *Bot) Pop(c telebot.Context) error {
queue := c.Get("queue").(models.Queue)
Expand Down Expand Up @@ -97,7 +149,6 @@ func (b *Bot) Pop(c telebot.Context) error {
// Пропускает следующего в очереди
func (b *Bot) LetAhead(c telebot.Context) error {
queue := c.Get("queue").(models.Queue)

entry := models.QueueEntry{
ChatID: fmt.Sprint(c.Chat().ID),
}
Expand All @@ -107,9 +158,6 @@ func (b *Bot) LetAhead(c telebot.Context) error {
if errors.Is(err, services.ErrNotFound) {
return c.Send("Вы не записаны в очередь")
}
if errors.Is(err, services.ErrQueueEnd) {
return c.Send("Вы последний в очереди")
}
return err
}

Expand Down Expand Up @@ -254,7 +302,7 @@ func (b *Bot) showSubject(
sb.WriteString("\nОчередь пуста")
} else if err == nil {
// Находим имена пользователей
for i, entry := range entries {
for _, entry := range entries {
chatID, err := strconv.ParseInt(entry.ChatID, 10, 64)
if err != nil {
return err
Expand All @@ -267,9 +315,9 @@ func (b *Bot) showSubject(

// Если это текущий пользователь, то выделяем жирным для видимости
if chatID == c.Chat().ID {
fmt.Fprintf(&sb, "\n*%3d. %s*", i+1, user.Name)
fmt.Fprintf(&sb, "\n*%3d. %s*", entry.Position, user.Name)
} else {
fmt.Fprintf(&sb, "\n%3d. %s", i+1, user.Name)
fmt.Fprintf(&sb, "\n%3d. %s", entry.Position, user.Name)
}
}

Expand Down
5 changes: 2 additions & 3 deletions internal/handlers/bot/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func (b *Bot) getUser(c tele.Context) (models.User, error) {
}

// Читаем оставшиеся данные
err = b.dialogue(c, func(ch <-chan string, c tele.Context) error {
if err = b.dialogue(c, func(ch <-chan string, c tele.Context) error {
var err error

menu.Reply(
Expand Down Expand Up @@ -165,8 +165,7 @@ func (b *Bot) getUser(c tele.Context) (models.User, error) {
}

return nil
})
if err != nil {
}); err != nil {
return models.User{}, err
}

Expand Down
1 change: 1 addition & 0 deletions internal/interfaces/bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type BotHandlers interface {
ChooseSubjectButton(telebot.Context) error
Refresh(telebot.Context) error
Push(telebot.Context) error
PushPriority(telebot.Context) error
Pop(telebot.Context) error
LetAhead(telebot.Context) error
Clear(telebot.Context) error
Expand Down
12 changes: 11 additions & 1 deletion internal/models/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package models
import (
"fmt"
"strings"

"github.com/redis/go-redis/v9"
)

type Queue struct {
Expand All @@ -23,5 +25,13 @@ func (q *Queue) Key() string {
}

type QueueEntry struct {
ChatID string
Position int
ChatID string
}

func (e *QueueEntry) ToRedis() redis.Z {
return redis.Z{
Score: float64(e.Position),
Member: e.ChatID,
}
}
2 changes: 1 addition & 1 deletion internal/repositories/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ import "errors"
var (
ErrNotFound = errors.New("resource not found")
ErrAlreadyInQueue = errors.New("user already in queue")
ErrCacheMiss = errors.New("cache miss")
ErrPlaceTaken = errors.New("place in queue already taken")
)
2 changes: 1 addition & 1 deletion internal/repositories/redis/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (s *Storage) Get(
val, err := s.cl.Get(ctx, key).Result()
if err != nil {
if errors.Is(err, redis.Nil) {
return "", fmt.Errorf("%s: %w", op, repositories.ErrCacheMiss)
return "", fmt.Errorf("%s: %w", op, repositories.ErrNotFound)
}

return "", fmt.Errorf("%s: %w", op, err)
Expand Down
Loading