package telegram import ( "jannex/telegram-bot-manager/modules/cache" "jannex/telegram-bot-manager/modules/database" "jannex/telegram-bot-manager/modules/logger" "jannex/telegram-bot-manager/modules/structs" "jannex/telegram-bot-manager/modules/utils" "regexp" "strings" "time" "git.ex.umbach.dev/Alex/roese-utils/rslogger" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" "github.com/rs/zerolog/log" ) var bot *tgbotapi.BotAPI func InitBot() { var err error bot, err = tgbotapi.NewBotAPI("6450280279:AAGxXdPv_YwRtl_pXIqYojqOecBrEjn3fJo") if err != nil { logger.AddSystemLog(rslogger.LogTypeError, "Failed to initialize Telegram bot, err: %v", err.Error()) log.Fatal().Err(err).Msgf("Failed to initialize Telegram bot, err: %v", err.Error()) } //bot.Debug = false logger.AddSystemLog(rslogger.LogTypeInfo, "Bot connected as %s", bot.Self.UserName) go IncomingMessagesHandler() } func IncomingMessagesHandler() { updateConfig := tgbotapi.NewUpdate(0) updateConfig.Timeout = 60 updates, err := bot.GetUpdatesChan(updateConfig) if err != nil { logger.AddSystemLog(rslogger.LogTypeError, "Failed to get updates from Telegram bot, err: %v", err.Error()) log.Fatal().Err(err).Msgf("Failed to get updates from Telegram bot, err: %v", err.Error()) } for update := range updates { if update.Message == nil { continue } chatID := update.Message.Chat.ID text := update.Message.Text if text == "" { continue } regStart := regexp.MustCompile(`/start`) regHelp := regexp.MustCompile(`/help`) regVerify := regexp.MustCompile(`/verify (\w+)`) regVerifyMatches := regVerify.FindStringSubmatch(text) regUnsubscribe := regexp.MustCompile(`/unsubscribe`) regFilter := regexp.MustCompile(`/filter`) regFilterWithArgs := regexp.MustCompile(`/filter (.+)`) regFilterMatches := regFilterWithArgs.FindStringSubmatch(text) var replyMessage string if regStart.MatchString(text) || regHelp.MatchString(text) { // command /start or /help replyMessage = "Welcome!\n\n" + "Type /verify to start receiving notifications. The code can be found in the user profile on the dashboard.\n\n" + "Type /unsubscribe to stop receiving notifications.\n\n" + "Type /filter to filter notifications. Filter can be: success, info, warning, error. For example: /filter info,warning,error will filter all notifications except success.\n\n" + "Type /filter to get your current filter." SendNotification(chatID, replyMessage) logger.AddSystemLog(rslogger.LogTypeInfo, "Received command %s from user: %s %s", text, update.Message.From.FirstName, update.Message.From.LastName) } else if len(regVerifyMatches) == 2 { // command /verify code := regVerifyMatches[1] if len(code) != utils.VerifyCodeLength { logger.AddSystemLog(rslogger.LogTypeWarning, "Received code with wrong length from user: %s %s. Message: %s", update.Message.From.FirstName, update.Message.From.LastName, code) continue } var tempVerify structs.TempVerifyCode var ok bool if tempVerify, ok = cache.GetTempVerifyByCode(code); !ok { // code not found in cache logger.AddSystemLog(rslogger.LogTypeWarning, "Received code which was not found in cache from user: %s %s. Message: %s", update.Message.From.FirstName, update.Message.From.LastName, code) replyMessage = "The code you entered is invalid. Please check the code and try again." } else { // code found in cache var foundVerifiedUser structs.VerifiedUser database.DB.Where("chat_id = ?", update.Message.From.ID).First(&foundVerifiedUser) if foundVerifiedUser.UserId != "" { // user already verified replyMessage = "You have already verified your account. You will continue to receive notifications. Type /unsubscribe to stop receiving notifications." logger.AddSystemLog(rslogger.LogTypeWarning, "User: %s %s has tried to verify his account with code %s, but has already verified his account", update.Message.From.FirstName, update.Message.From.LastName, code) } else { // user not verified replyMessage = "You have successfully verified your account. You will now receive notifications. Type /unsubscribe to stop receiving notifications." database.DB.Create(&structs.VerifiedUser{ UserId: tempVerify.UserId, ChatId: update.Message.From.ID, Filter: utils.NotificationTypeError, CreatedAt: time.Now(), }) logger.AddSystemLog(rslogger.LogTypeInfo, "User: %s %s has subscribed to receive notifications", update.Message.From.FirstName, update.Message.From.LastName) } cache.RemoveTempVerifyCode(tempVerify.UserId) } SendNotification(chatID, replyMessage) } else if regUnsubscribe.MatchString(text) { // command /unsubscribe res := database.DB.Delete(&structs.VerifiedUser{}, "chat_id = ?", update.Message.From.ID) if res.Error != nil { logger.AddSystemLog(rslogger.LogTypeError, "Failed to delete verified user from database, err: %v", res.Error.Error()) continue } if res.RowsAffected == 0 { logger.AddSystemLog(rslogger.LogTypeWarning, "User: %s %s has tried to unsubscribe from receiving notifications, but has not been verified", update.Message.From.FirstName, update.Message.From.LastName) replyMessage = "You have not been verified yet. Type /verify to start receiving notifications. The code can be found in the user profile on the dashboard." } else { logger.AddSystemLog(rslogger.LogTypeInfo, "User: %s %s has unsubscribed from receiving notifications", update.Message.From.FirstName, update.Message.From.LastName) replyMessage = "You have unsubscribed from receiving notifications. Type /verify to start receiving notifications again. The code can be found in the user profile on the dashboard." } SendNotification(chatID, replyMessage) } else if len(regFilterMatches) == 2 { // command /filter setFilter(chatID, update, text, regFilterMatches) } else if regFilter.MatchString(text) { // command /filter var foundVerifiedUser structs.VerifiedUser database.DB.Where("chat_id = ?", update.Message.From.ID).First(&foundVerifiedUser) if foundVerifiedUser.UserId == "" { logger.AddSystemLog(rslogger.LogTypeWarning, "User: %s %s has tried to get filter, but has not been verified", update.Message.From.FirstName, update.Message.From.LastName) SendNotification(chatID, "You have not been verified yet. Type /verify to start receiving notifications. The code can be found in the user profile on the dashboard.") } else { formattedFilters := utils.GetFormattedFilters(foundVerifiedUser.Filter) logger.AddSystemLog(rslogger.LogTypeInfo, "User: %s %s has requested filter, current filter: %s", update.Message.From.FirstName, update.Message.From.LastName, formattedFilters) SendNotification(chatID, "Your current filter is: "+formattedFilters) } } else { logger.AddSystemLog(rslogger.LogTypeWarning, "Received unknown message: %s from user: %s %s", text, update.Message.From.FirstName, update.Message.From.LastName) } } } func SendNotification(chatId int64, message string) { msg := tgbotapi.NewMessage(chatId, message) if _, err := bot.Send(msg); err != nil { logger.AddSystemLog(rslogger.LogTypeError, "Failed to send notification to chatId %v message: %s, err: %v", chatId, message, err.Error()) } } func setFilter(chatID int64, update tgbotapi.Update, text string, regFilterMatches []string) { logger.AddSystemLog(rslogger.LogTypeInfo, "Received filter message: %s from user: %s %s", text, update.Message.From.FirstName, update.Message.From.LastName) filter := regFilterMatches[1] filterValues := strings.Split(filter, ",") for _, v := range filterValues { switch v { case utils.NotificationTypeSuccess, utils.NotificationTypeInfoString, utils.NotificationTypeWarningString, utils.NotificationTypeErrorString: continue default: logger.AddSystemLog(rslogger.LogTypeWarning, "Received unknown filter value: %s from user: %s %s", v, update.Message.From.FirstName, update.Message.From.LastName) SendNotification(chatID, "You have entered an invalid filter value. Filter can be: success, info, warning, error. For example: /filter info,warning,error will filter all notifications except success.") return } } var filteredValues []string var filteredTextValues []string for _, v := range filterValues { switch v { case utils.NotificationTypeSuccessString: filteredValues = append(filteredValues, utils.NotificationTypeSuccess) filteredTextValues = append(filteredTextValues, utils.NotificationTypeSuccessString) case utils.NotificationTypeInfoString: filteredValues = append(filteredValues, utils.NotificationTypeInfo) filteredTextValues = append(filteredTextValues, utils.NotificationTypeInfoString) case utils.NotificationTypeWarningString: filteredValues = append(filteredValues, utils.NotificationTypeWarning) filteredTextValues = append(filteredTextValues, utils.NotificationTypeWarningString) case utils.NotificationTypeErrorString: filteredValues = append(filteredValues, utils.NotificationTypeError) filteredTextValues = append(filteredTextValues, utils.NotificationTypeErrorString) } } var foundVerifiedUser structs.VerifiedUser database.DB.Where("chat_id = ?", update.Message.From.ID).First(&foundVerifiedUser) if foundVerifiedUser.UserId == "" { logger.AddSystemLog(rslogger.LogTypeWarning, "User: %s %s has tried to set filter, but has not been verified", update.Message.From.FirstName, update.Message.From.LastName) SendNotification(chatID, "You have not been verified yet. Type /verify to start receiving notifications. The code can be found in the user profile on the dashboard.") return } filter = strings.Join(filteredValues, ",") database.DB.Model(&structs.VerifiedUser{}). Where("chat_id = ?", update.Message.From.ID). Updates(structs.VerifiedUser{Filter: filter}) formattedFilteredTextValues := strings.Join(filteredTextValues, ", ") logger.AddSystemLog(rslogger.LogTypeInfo, "User: %s %s has set filter to %s (%s)", update.Message.From.FirstName, update.Message.From.LastName, filter, formattedFilteredTextValues) SendNotification(chatID, "You have successfully set filter to "+formattedFilteredTextValues+". You will now only receive notifications with the selected filter.") }