package query import ( "fmt" "log/slog" "strconv" "strings" "sync" "time" "git.maximotejeda.com/maximo/cedulados-bot/internal/application/auth" "git.maximotejeda.com/maximo/cedulados-bot/internal/ports" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" ) var ChatPool *sync.Pool type Query struct { bot *tgbotapi.BotAPI update *tgbotapi.Update msg *tgbotapi.MessageConfig delMSG *tgbotapi.DeleteMessageConfig log *slog.Logger ce ports.CeduladosService uSVC ports.UserService } // NewMessage // Factory for query handler func NewQuery(bot *tgbotapi.BotAPI, update *tgbotapi.Update, cSVC ports.CeduladosService, user ports.UserService) *Query { if ChatPool == nil { ChatPool = &sync.Pool{ New: func() any { return &Query{} }, } for i := 0; i < 20; i++ { ChatPool.Put(ChatPool.New()) } } log := slog.Default() log = log.With("function", "Query", "chat", update.CallbackQuery.From.ID, "userid", update.CallbackQuery.From.ID, "username", update.CallbackQuery.From.UserName) query := ChatPool.Get().(*Query) query.update = update query.bot = bot query.log = log query.ce = cSVC query.uSVC = user return query } // Empty // Returns pointer to pool func (q *Query) Empty() { q.update = nil q.msg = nil q.log = nil q.ce = nil q.uSVC = nil ChatPool.Put(q) } // Send // Process message sending to bot func (q *Query) Send() { defer q.Empty() q.bot.Send(q.msg) if q.delMSG != nil { q.bot.Send(q.delMSG) } } func (q *Query) Handler(){ msg := tgbotapi.NewMessage(q.update.CallbackQuery.From.ID, "") delMSG := tgbotapi.NewDeleteMessage(q.update.CallbackQuery.From.ID, q.update.CallbackQuery.Message.MessageID) text := "" q.msg = &msg q.delMSG = &delMSG data := q.update.CallbackQuery.Data dataList := strings.Split(data, "&") dataMap := map[string]string{} for _, val := range dataList{ subData := strings.Split(val, "=") dataMap[subData[0]] = subData[1] } userSTR := dataMap["userID"] userID, err := strconv.ParseInt(userSTR, 10, 64) if err != nil { text = fmt.Sprintf("could not parse int %s", userSTR) q.log.Error("could not parse id", "userID", userSTR) return } switch dataMap["operation"]{ case "grant": // grant user access to a bot if !auth.IsUserAdmin(q.update.CallbackQuery.From.ID){ text = "only admin can execute this command" }else{ q.log.Info("inside grant") _, err := q.uSVC.GrantAccess(userID, dataMap["bot"]) if err != nil { q.log.Error("granting access to bot", "user", userID, "bot", dataMap["bot"]) text = fmt.Sprintf("ERROR: grant user access: %s", err) }else { text = fmt.Sprintf("granted access to user %s to bot %s", userSTR, dataMap["bot"]) go func (){ userMsg := tgbotapi.NewMessage(userID, "Granted access permissions!!") q.bot.Send(userMsg) }() } } case "deny": if !auth.IsUserAdmin(q.update.CallbackQuery.From.ID){ text = "only admin can execute this command" }else{ // deny user access to a bot _, err := q.uSVC.BanUser(userID, time.Now().Add(24 * 365 * time.Hour).Unix(), dataMap["bot"]) if err != nil { q.log.Error("baning user", "user", userID, "bot", dataMap["bot"]) text = fmt.Sprintf("ERROR: banning user: %s", err) }else { text = fmt.Sprintf("user banned user: %s, bot: %s", userSTR, dataMap["bot"]) } } case "ignore": text = fmt.Sprintf("user request ignored user: %s", userSTR) // ignore user access request case "ban": if !auth.IsUserAdmin(q.update.CallbackQuery.From.ID){ text = "only admin can execute this command" }else{ _, err := q.uSVC.BanUser(userID, time.Now().Add(24 * 365 * time.Hour).Unix(), dataMap["bot"]) if err != nil { q.log.Error("baning user", "user", userID, "bot", dataMap["bot"]) text = fmt.Sprintf("ERROR: banning user: %s", err) }else{ text = fmt.Sprintf("baned user: %s, bot: %s", userSTR, dataMap["bot"]) } // TODO: ext = fmt.Sprintf("user banned user: %s, bot: %s", userSTR, dataMap["bot"]) } case "unban": if !auth.IsUserAdmin(q.update.CallbackQuery.From.ID){ text = "only admin can execute this command" }else{ _, err := q.uSVC.UnBanUser(userID, dataMap["bot"]) if err != nil { q.log.Error("baning user", "user", userID, "bot", dataMap["bot"]) text = fmt.Sprintf("ERROR: unbanning user: %s", err) }else { text = fmt.Sprintf("user banned user: %s, bot: %s", userSTR, dataMap["bot"]) } } case "delete": if !auth.IsUserAdmin(q.update.CallbackQuery.From.ID){ text = "only admin can execute this command" }else{ _, err := q.uSVC.DeleteBot(userID, q.bot.Self.UserName) if err != nil { q.log.Error("baning user", "user", userID, "bot", dataMap["bot"]) text = fmt.Sprintf("ERROR: deleted user: %s from bot %s", err, q.bot.Self.UserName) }else { text = fmt.Sprintf("user deleted user: %s, bot: %s", userSTR, dataMap["bot"]) } } } q.msg.Text = text q.Send() }