Files
DockerBot/handleDockerLogs.go
2026-04-13 21:42:04 +02:00

257 lines
5.3 KiB
Go

package main
import (
"context"
"errors"
"strconv"
"strings"
"fergalla.com/dockerbot/internal/apperrors"
"github.com/go-telegram/bot"
"github.com/go-telegram/bot/models"
)
func (appCtx *App) handleDockerLogs(ctx context.Context, b *bot.Bot, chatID int64, params []string) {
if len(params) == 0 {
appCtx.sendMessage(
ctx,
b,
chatID,
appCtx.T("e.container.missing_name", map[string]string{
"example": "logs",
"opts": " --tail 10",
}),
true,
nil,
)
return
}
container, tail := parseLogsParams(params)
text, keyboard, err := appCtx.renderContainerLogs(ctx, container, 0, tail)
if err != nil {
appCtx.logger.Error(
"Failed to render container logs",
"module", "Bot",
"container", container,
"tail", tail,
"error", err,
)
if errors.Is(err, apperrors.ErrContainerNotFound) {
appCtx.sendMessage(ctx, b, chatID, appCtx.T("e.container.not_found"), true, nil)
} else {
appCtx.sendMessage(ctx, b, chatID, appCtx.T("e.container.logs"), true, nil)
}
return
}
appCtx.sendMessage(ctx, b, chatID, text, true, keyboard)
}
func parseLogsParams(params []string) (container string, tail int) {
const defaultTail = 0
const maxTail = 100
if len(params) == 0 {
return "", defaultTail
}
container = params[0]
tail = defaultTail
for i := 1; i < len(params); i++ {
if params[i] == "--tail" && i+1 < len(params) {
if v, err := strconv.Atoi(params[i+1]); err == nil {
tail = v
}
i++ // saltar valor
}
}
// clamp
if tail <= 0 {
tail = defaultTail
}
if tail > maxTail {
tail = maxTail
}
return
}
func (appCtx *App) callbackDockerLogs(ctx context.Context, b *bot.Bot, update *models.Update) {
if update.CallbackQuery == nil {
return
}
cb := update.CallbackQuery
parts := strings.Split(cb.Data, ":")
if len(parts) < 2 {
return
}
container := parts[1]
pageIndex := 0
if len(parts) >= 3 {
if p, err := strconv.Atoi(parts[2]); err == nil {
pageIndex = p
}
}
tail := 0 // default
if len(parts) >= 4 {
if t, err := strconv.Atoi(parts[3]); err == nil {
tail = t
}
}
text, keyboard, err := appCtx.renderContainerLogs(ctx, container, pageIndex, tail)
if err != nil {
appCtx.logger.Error("Logs render generator failed", "error", err)
b.AnswerCallbackQuery(ctx, &bot.AnswerCallbackQueryParams{
CallbackQueryID: cb.ID,
Text: appCtx.T("e.container.logs"),
ShowAlert: true,
})
return
}
b.AnswerCallbackQuery(ctx, &bot.AnswerCallbackQueryParams{
CallbackQueryID: cb.ID,
})
_, err = b.EditMessageText(ctx, &bot.EditMessageTextParams{
ChatID: cb.Message.Message.Chat.ID,
MessageID: cb.Message.Message.ID,
Text: text,
ParseMode: "html",
ReplyMarkup: keyboard,
})
if err != nil {
appCtx.logger.Warn("Failed to render logs", "error", err)
return
}
}
func (appCtx *App) callbackDockerLogsRefresh(ctx context.Context, b *bot.Bot, update *models.Update) {
if update.CallbackQuery == nil {
return
}
cb := update.CallbackQuery
parts := strings.Split(cb.Data, ":")
if len(parts) < 2 {
return
}
container := parts[1]
pageIndex := 0
if len(parts) >= 3 {
if p, err := strconv.Atoi(parts[2]); err == nil {
pageIndex = p
}
}
tail := 0 // default
if len(parts) >= 4 {
if t, err := strconv.Atoi(parts[3]); err == nil {
tail = t
}
}
// 🎨 render logs actualizado
text, keyboard, err := appCtx.renderContainerLogs(ctx, container, pageIndex, tail)
if err != nil {
var msg string
if errors.Is(err, apperrors.ErrContainerNotFound) {
msg = appCtx.T("e.container.not_found")
} else {
msg = appCtx.T("e.container.logs")
}
b.AnswerCallbackQuery(ctx, &bot.AnswerCallbackQueryParams{
CallbackQueryID: cb.ID,
Text: msg,
ShowAlert: true,
})
return
}
// ✅ feedback UX
b.AnswerCallbackQuery(ctx, &bot.AnswerCallbackQueryParams{
CallbackQueryID: cb.ID,
Text: "🔄 " + appCtx.T("ui.updated"),
ShowAlert: false,
})
// 🔄 actualizar mensaje
_, err = b.EditMessageText(ctx, &bot.EditMessageTextParams{
ChatID: cb.Message.Message.Chat.ID,
MessageID: cb.Message.Message.ID,
Text: text,
ParseMode: "html",
ReplyMarkup: keyboard,
})
if err != nil {
appCtx.logger.Warn(
"Failed to refresh logs",
"module", "Bot",
"container", container,
"error", err,
)
return
}
}
func (appCtx *App) callbackDockerBackDetail(ctx context.Context, b *bot.Bot, update *models.Update) {
if update.CallbackQuery == nil {
return
}
cb := update.CallbackQuery
parts := strings.Split(cb.Data, ":")
if len(parts) < 2 {
return
}
container := parts[1]
pageIndex := 0
if len(parts) >= 3 {
if p, err := strconv.Atoi(parts[2]); err == nil {
pageIndex = p
}
}
text, keyboard, err := appCtx.renderContainerDetail(ctx, container, pageIndex)
if err != nil {
b.AnswerCallbackQuery(ctx, &bot.AnswerCallbackQueryParams{
CallbackQueryID: cb.ID,
Text: appCtx.T("e.container.info"),
ShowAlert: true,
})
return
}
b.AnswerCallbackQuery(ctx, &bot.AnswerCallbackQueryParams{
CallbackQueryID: cb.ID,
})
_, err = b.EditMessageText(ctx, &bot.EditMessageTextParams{
ChatID: cb.Message.Message.Chat.ID,
MessageID: cb.Message.Message.ID,
Text: text,
ParseMode: "html",
ReplyMarkup: keyboard,
})
if err != nil {
appCtx.logger.Warn("Failed to go back to detail", "error", err)
return
}
}