package helpers import ( "context" "fmt" "log/slog" "slices" "strconv" "strings" "git.maximotejeda.com/maximo/telegram-base-bot/config" "git.maximotejeda.com/maximo/telegram-base-bot/internal/ports" "github.com/go-telegram/bot" "github.com/go-telegram/bot/models" ) func IsUserRegistered() {} func IsUserAuthorized() {} func GetPendingAuthRequest() {} func CreatePendingAuthRequest() {} func DeletePendingAuthRequest() {} func BanUSer() {} func UnBanUser() {} func Authenticate(ctx context.Context, log *slog.Logger, b *bot.Bot, update *models.Update, uSVC ports.UserService) bool { var ( user models.User ) // select user if update.CallbackQuery != nil { user = update.CallbackQuery.From } else { if update.MessageReaction != nil { return true } user = *update.Message.From } // bot name bn, _ := b.GetMe(ctx) switch IsUserAdmin(user.ID) { case true: // theres an user env admin // check if user exist on db _, err := uSVC.Get(user.ID) if err != nil { log.Error("geting user", "error", err) log.Debug("user seems to not exists") if strings.Contains(err.Error(), "sql: no rows in result set") { // if user does not exist create it _, err := uSVC.Create(&user) log.Debug("creating user") if err != nil { log.Error("creating new user for admnin", "err", err) } // add bot to user list _, err = uSVC.AddBot(user.ID, bn.Username) if err != nil { log.Error("Adding bot to admin user list", "err", err) } } } return true case false: // user is not admin and need to be authorized // check if user is on db _, err := uSVC.Get(user.ID) if err != nil { // user need auth log.Error("user not in db, authorization from an admin is required", "error", err) // add user to manage it if strings.Contains(err.Error(), "sql: no rows in result set") { // check if theres an access request from the same user and bot _, err := uSVC.Create(&user) if err != nil { log.Error("creating new user", "user", user.ID, "error", err) } // create access request _, err = uSVC.CreateAccessRequest(user.ID, bn.Username) if err != nil { log.Error("creating access request for ", "user", user.ID, "error", err) } } } else { bots, err := uSVC.GetBots(user.ID) if err != nil { log.Error("checking bots on user access") } switch HasUserAccess(bots, bn.Username) { case true: return true case false: // check for banned user buser, err := uSVC.GetAllBannedUsers(bn.Username) if err != nil { log.Error("error querying banned user") } for _, u := range buser.GetBans() { if u.TgbId == user.ID { b.SendMessage(ctx, &bot.SendMessageParams{ ChatID: u.TgbId, Text: "user access is restricted, please ask for permission", },) return false } } ac, err := uSVC.GetAccessRequest(user.ID) acl := []string{} for _, val := range ac.Access { acl = append(acl, val.BotName) } if slices.Contains(acl, bn.Username) { // create access request log.Info("Access Request found returning early", "user", user.ID, "error", err) return false } else { // create one _, err = uSVC.CreateAccessRequest(user.ID, bn.Username) if err != nil { log.Error("creating access request", "err", err) } } } } } // get all admins userL, _ := GetAdminFromEnv() // send a mesage to all admins for _, adm := range userL { param := GenerateAccessRequestMessage(user, adm, b, update) b.SendMessage(ctx, param) } return false } // GetAdminFromEnv // will get an env variable that is a list of tgbID comma separated // if the user trying to enter is admin auth the user func GetAdminFromEnv() (adminList []int64, errList []error) { adminsStrList := config.GetAdminsList() list := strings.Split(adminsStrList, ",") adminList = []int64{} errList = []error{} for _, item := range list { adm, err := strconv.ParseInt(item, 10, 64) if err != nil { err = fmt.Errorf("parsing tgb admin id: %s\n err: %w", item, err) fmt.Println(err) errList = append(errList, err) continue } adminList = append(adminList, adm) } return } // IsUserAdmin // check if userID is admin on bot func IsUserAdmin(userID int64) bool { userL, errl := GetAdminFromEnv() if len(errl) > 0 { fmt.Printf("error no admin in var %v", errl) } return slices.Contains(userL, userID) } func HasUserAccess(bots []string, botName string) bool { return slices.Contains(bots, botName) } func GenerateAccessRequestMessage(up models.User, adm int64, b *bot.Bot, update *models.Update) *bot.SendMessageParams { txt := fmt.Sprintf(`User %s is requesting access ID: %d FirstName: %s LastName: %s ChatID: %d `, up.Username, up.ID, up.FirstName, up.LastName, up.ID) msg := &bot.SendMessageParams{ ChatID: adm, Text: txt, } bn, _ := b.GetMe(context.Background()) kbd := &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{ { {Text: "Grant", CallbackData: fmt.Sprintf("operation=grant&userID=%d&bot=%s", up.ID, bn.Username)}, {Text: "Deny", CallbackData: fmt.Sprintf("operation=deny&userID=%d&bot=%s", up.ID, bn.Username)}, }, { {Text: "Ignore", CallbackData: fmt.Sprintf("operation=ignore&userID=%d&bot=%s", up.ID, bn.Username)}, }, }, } msg.ReplyMarkup = kbd return msg }