2024-12-18 11:08:21 -04:00

168 lines
4.8 KiB
Go

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()
}