refactor + fix добавление проекта
This commit is contained in:
@@ -14,15 +14,40 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
var emptyKeyboard = echotron.InlineKeyboardMarkup{
|
||||
InlineKeyboard: [][]echotron.InlineKeyboardButton{},
|
||||
}
|
||||
|
||||
type exec struct {
|
||||
handled bool // Событие обработано, дальше не идём
|
||||
transitioned bool // Был SetState
|
||||
}
|
||||
|
||||
var botUsername string
|
||||
var botUsernameOnce sync.Once
|
||||
|
||||
func SetBotUsername(username string) { botUsername = username }
|
||||
|
||||
func BotUsername() string { return botUsername }
|
||||
|
||||
func ensureBotUsername(api echotron.API) {
|
||||
if botUsername != "" {
|
||||
return
|
||||
}
|
||||
botUsernameOnce.Do(func() {
|
||||
me, err := api.GetMe()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("GetMe failed, bot username will be empty")
|
||||
return
|
||||
}
|
||||
if me.Result != nil {
|
||||
botUsername = me.Result.Username
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
type lastRender struct {
|
||||
textHash string
|
||||
kbHash string
|
||||
isMedia bool
|
||||
}
|
||||
|
||||
type Bot struct {
|
||||
echotron.API
|
||||
mu sync.Mutex
|
||||
@@ -30,10 +55,8 @@ type Bot struct {
|
||||
exec *exec
|
||||
CurrentState State
|
||||
Session *Session
|
||||
LastMessageID int // ID последнего сообщения с inline кнопками
|
||||
LastMessageIsMedia bool // True if LastMessageID points to media message
|
||||
LastMessageTextHash string // Hash for last text/caption
|
||||
LastMessageKBHash string // Hash for last inline keyboard
|
||||
LastMessageID int // ID последнего сообщения с inline кнопками
|
||||
lastRender lastRender
|
||||
commandRouter func(cmd string) State // Роутер для команд (например, /start, /help)
|
||||
globalCallbackRouter func(callbackData string) State // Роутер для глобальных callbacks из уведомлений
|
||||
Backend *backend.Client
|
||||
@@ -53,9 +76,12 @@ func NewBot(chatID int64, token string, commandRouter func(string) State, backen
|
||||
panic("bot: backendClient cannot be nil")
|
||||
}
|
||||
|
||||
api := echotron.NewAPI(token)
|
||||
ensureBotUsername(api)
|
||||
|
||||
return &Bot{
|
||||
ChatID: chatID,
|
||||
API: echotron.NewAPI(token),
|
||||
API: api,
|
||||
Session: &Session{},
|
||||
commandRouter: commandRouter,
|
||||
Backend: backendClient,
|
||||
@@ -140,7 +166,7 @@ func (b *Bot) Render(text string, keyboard echotron.InlineKeyboardMarkup, mode R
|
||||
}
|
||||
|
||||
func (b *Bot) SetLastMessageIsMedia(isMedia bool) {
|
||||
b.LastMessageIsMedia = isMedia
|
||||
b.lastRender.isMedia = isMedia
|
||||
}
|
||||
|
||||
func (b *Bot) DownloadFileBytes(fileID string) ([]byte, error) {
|
||||
@@ -175,9 +201,9 @@ func (b *Bot) SendNew(text string, keyboard echotron.InlineKeyboardMarkup) {
|
||||
}
|
||||
|
||||
b.LastMessageID = res.Result.ID
|
||||
b.LastMessageIsMedia = false
|
||||
b.LastMessageTextHash = hashString(text)
|
||||
b.LastMessageKBHash = keyboardHash(keyboard)
|
||||
b.lastRender.isMedia = false
|
||||
b.lastRender.textHash = hashString(text)
|
||||
b.lastRender.kbHash = keyboardHash(keyboard)
|
||||
log.Info().Int("new_last_msg_id", b.LastMessageID).Msg("Updated LastMessageID in SendNew")
|
||||
}
|
||||
|
||||
@@ -194,8 +220,8 @@ func (b *Bot) Edit(text string, keyboard echotron.InlineKeyboardMarkup) {
|
||||
newTextHash := hashString(text)
|
||||
newKBHash := keyboardHash(keyboard)
|
||||
|
||||
textChanged := newTextHash != b.LastMessageTextHash
|
||||
kbChanged := newKBHash != b.LastMessageKBHash
|
||||
textChanged := newTextHash != b.lastRender.textHash
|
||||
kbChanged := newKBHash != b.lastRender.kbHash
|
||||
|
||||
if !textChanged && !kbChanged {
|
||||
log.Info().Msg("Edit skipped: message not modified")
|
||||
@@ -205,7 +231,7 @@ func (b *Bot) Edit(text string, keyboard echotron.InlineKeyboardMarkup) {
|
||||
var err error
|
||||
msgID := echotron.NewMessageID(b.ChatID, b.LastMessageID)
|
||||
|
||||
if b.LastMessageIsMedia {
|
||||
if b.lastRender.isMedia {
|
||||
_, err = b.EditMessageCaption(msgID, &echotron.MessageCaptionOptions{Caption: text, ParseMode: echotron.HTML, ReplyMarkup: keyboard})
|
||||
} else {
|
||||
_, err = b.EditMessageText(text, msgID, &echotron.MessageTextOptions{ReplyMarkup: keyboard, ParseMode: echotron.HTML})
|
||||
@@ -213,10 +239,10 @@ func (b *Bot) Edit(text string, keyboard echotron.InlineKeyboardMarkup) {
|
||||
|
||||
if err == nil {
|
||||
if textChanged {
|
||||
b.LastMessageTextHash = newTextHash
|
||||
b.lastRender.textHash = newTextHash
|
||||
}
|
||||
if kbChanged {
|
||||
b.LastMessageKBHash = newKBHash
|
||||
b.lastRender.kbHash = newKBHash
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -225,7 +251,7 @@ func (b *Bot) Edit(text string, keyboard echotron.InlineKeyboardMarkup) {
|
||||
case strings.Contains(err.Error(), "message is not modified"):
|
||||
log.Err(err).Msg("EditMessageText ignored: message is not modified")
|
||||
case strings.Contains(err.Error(), "no text in the message to edit"):
|
||||
b.LastMessageIsMedia = true
|
||||
b.lastRender.isMedia = true
|
||||
log.Err(err).Msg("EditMessageText ignored: message has no text")
|
||||
default:
|
||||
log.Error().Err(err).Msg("EditMessageText")
|
||||
@@ -284,7 +310,10 @@ func (b *Bot) Update(u *echotron.Update) {
|
||||
|
||||
err := b.GetOrCreateJWT(u)
|
||||
if err != nil || b.Session.JWT == "" {
|
||||
b.SendNew("❌ Ошибка авторизации. Попробуйте /start", emptyKeyboard)
|
||||
b.Edit(
|
||||
"❌ Ошибка авторизации",
|
||||
echotron.InlineKeyboardMarkup{InlineKeyboard: [][]echotron.InlineKeyboardButton{{{Text: "↻ Обновить", CallbackData: "refresh"}}}},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -307,11 +336,11 @@ func (b *Bot) Update(u *echotron.Update) {
|
||||
case "/start login":
|
||||
b.SetState(b.commandRouter("/start login"), NewMessage)
|
||||
return
|
||||
default:
|
||||
b.CurrentState.HandleMessage(b, u)
|
||||
if e.handled || e.transitioned {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
b.CurrentState.HandleMessage(b, u)
|
||||
if e.handled || e.transitioned {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,11 +348,17 @@ func (b *Bot) Update(u *echotron.Update) {
|
||||
if u.CallbackQuery != nil {
|
||||
b.cleanupCallbackUI(u)
|
||||
|
||||
if u.CallbackQuery.Data == "empty" {
|
||||
switch u.CallbackQuery.Data {
|
||||
case "empty":
|
||||
return
|
||||
case "refresh":
|
||||
if b.CurrentState != nil {
|
||||
b.CurrentState.Enter(b, EditMessage)
|
||||
e.handled = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Глобальные callbacks (из уведомлений)
|
||||
if newState := b.globalCallbackRouter(u.CallbackQuery.Data); newState != nil {
|
||||
b.SetState(newState, NewMessage)
|
||||
return
|
||||
@@ -358,6 +393,9 @@ func (b *Bot) Update(u *echotron.Update) {
|
||||
}
|
||||
|
||||
func (b *Bot) cleanupKeyboard(messageID int) {
|
||||
var emptyKeyboard = echotron.InlineKeyboardMarkup{
|
||||
InlineKeyboard: [][]echotron.InlineKeyboardButton{},
|
||||
}
|
||||
_, err := b.EditMessageReplyMarkup(
|
||||
echotron.NewMessageID(b.ChatID, messageID),
|
||||
&echotron.MessageReplyMarkupOptions{ReplyMarkup: emptyKeyboard},
|
||||
|
||||
Reference in New Issue
Block a user