// (c) Jisin0 package plugins import ( "fmt" "regexp" "strings" "github.com/Jisin0/Go-Filter-Bot/utils/config" "github.com/Jisin0/Go-Filter-Bot/utils/logger" "github.com/PaulSonOfLars/gotgbot/v2" "github.com/PaulSonOfLars/gotgbot/v2/ext" ) var cbEditPattern *regexp.Regexp = regexp.MustCompile(`edit\((.+)\)`) // AutoDelete var removed โ€” now read dynamically from DB func Start(bot *gotgbot.Bot, update *ext.Context) error { user := update.EffectiveMessage.From isNewUser := false if user != nil { isNewUser = DB.AddUserAndCheck(user.Id) } args := strings.Split(update.Message.Text, " ") if len(args) > 1 && strings.HasPrefix(args[1], "file_") { fileID := strings.TrimPrefix(args[1], "file_") SendFileByID(fileID, bot, update.Message) return nil } text := fmt.Sprintf(config.TEXT["START"], update.Message.From.FirstName, bot.FirstName) markup := gotgbot.InlineKeyboardMarkup{InlineKeyboard: config.BUTTONS["START"]} replyOpts := &gotgbot.ReplyParameters{AllowSendingWithoutReply: true} // Send with image if START_IMAGE is configured if config.StartImage != "" { imgFile := gotgbot.InputFileByID(config.StartImage) _, err := bot.SendPhoto(update.Message.Chat.Id, imgFile, &gotgbot.SendPhotoOpts{ Caption: text, ParseMode: gotgbot.ParseModeHTML, ReplyMarkup: markup, ReplyParameters: replyOpts, }) if err != nil { // Fallback to text if photo fails fmt.Printf("start: photo send failed: %v\n", err) bot.SendMessage(update.Message.Chat.Id, text, &gotgbot.SendMessageOpts{ ParseMode: gotgbot.ParseModeHTML, ReplyMarkup: markup, ReplyParameters: replyOpts, }) } } else { _, err := bot.SendMessage( update.Message.Chat.Id, text, &gotgbot.SendMessageOpts{ ParseMode: gotgbot.ParseModeHTML, ReplyMarkup: markup, ReplyParameters: replyOpts, }) if err != nil { fmt.Printf("start: %v\n", err) } } // Notify log channel for new users if isNewUser && user != nil { go logNewUser(bot, user) } return nil } func Stats(bot *gotgbot.Bot, update *ext.Context) error { markup := gotgbot.InlineKeyboardMarkup{InlineKeyboard: [][]gotgbot.InlineKeyboardButton{{{Text: "Refresh ๐Ÿ”„", CallbackData: "stats"}}}} _, err := update.EffectiveMessage.Reply(bot, DB.Stats(), &gotgbot.SendMessageOpts{ParseMode: gotgbot.ParseModeHTML, ReplyMarkup: markup}) if err != nil { fmt.Printf("stats: %v\n", err) } return nil } func GetID(bot *gotgbot.Bot, ctx *ext.Context) error { var ( text string update = ctx.Message ) if update.ReplyToMessage != nil { text += fmt.Sprintf("\nReplied to user : %v", update.ReplyToMessage.From.Id) if f := update.ReplyToMessage.ForwardOrigin; f.GetDate() != 0 { switch m := f.MergeMessageOrigin(); { case m.Chat != nil: text += fmt.Sprintf("\nForwarded from : %v", m.Chat.Id) case m.SenderChat != nil: text += fmt.Sprintf("\nForwarded from : %v", m.SenderChat.Id) case m.SenderUser != nil: text += fmt.Sprintf("\nForwarded from : %v", m.SenderUser.Id) } } } text += fmt.Sprintf("\nUser id : %v", update.From.Id) if update.Chat.Type != gotgbot.ChatTypePrivate { text += fmt.Sprintf("\nChat id : %v", update.Chat.Id) } _, err := update.Reply(bot, text, &gotgbot.SendMessageOpts{ParseMode: gotgbot.ParseModeHTML, ReplyParameters: &gotgbot.ReplyParameters{MessageId: update.MessageId}}) if err != nil { fmt.Printf("getid: %v\n", err) } return nil } func CbStats(bot *gotgbot.Bot, update *ext.Context) error { cb := update.CallbackQuery chatID := cb.Message.GetChat().Id msgID := cb.Message.GetMessageId() statsMarkup := gotgbot.InlineKeyboardMarkup{InlineKeyboard: config.BUTTONS["STATS"]} var err error origMsg, isMsg := cb.Message.(*gotgbot.Message) if isMsg && len(origMsg.Photo) > 0 { _, _, err = origMsg.EditCaption(bot, &gotgbot.EditMessageCaptionOpts{ Caption: DB.Stats(), ParseMode: gotgbot.ParseModeHTML, ReplyMarkup: statsMarkup, }) } else { _, _, err = bot.EditMessageText(DB.Stats(), &gotgbot.EditMessageTextOpts{ ChatId: chatID, MessageId: msgID, ParseMode: gotgbot.ParseModeHTML, ReplyMarkup: statsMarkup, }) if err != nil { // Fallback if EditMessageText fails (it might be a photo message but inaccessible) _, _, err = bot.EditMessageCaption(&gotgbot.EditMessageCaptionOpts{ ChatId: chatID, MessageId: msgID, Caption: DB.Stats(), ParseMode: gotgbot.ParseModeHTML, ReplyMarkup: statsMarkup, }) } } if err != nil { fmt.Printf("cbstats: %v\n", err) cb.Answer(bot, &gotgbot.AnswerCallbackQueryOpts{Text: "โš ๏ธ Could not refresh โ€” please re-run /stats", ShowAlert: true}) //nolint:errcheck return nil } cb.Answer(bot, &gotgbot.AnswerCallbackQueryOpts{Text: "๐Ÿ”„ Refreshed!"}) //nolint:errcheck return nil } func FilterHandler(b *gotgbot.Bot, ctx *ext.Context) error { // Silently ignore banned users if user := ctx.EffectiveUser; user != nil && user.Id != 0 { if DB.IsBanned(user.Id) { return nil } } // Force sub is handled inside Filter() โ€” skip duplicate check here go Filter(b, ctx) // VJ-style search with "Searching..." indicator go GFilter(b, ctx) // Manual group filters return nil } // Function to handle edit() callbacks from the Start, About and Help menus func CbEdit(bot *gotgbot.Bot, update *ext.Context) error { key := cbEditPattern.FindStringSubmatch(update.CallbackQuery.Data)[1] markup, ok := config.BUTTONS[key] if !ok { markup = [][]gotgbot.InlineKeyboardButton{{{Text: "โค Bแด€แด„แด‹", CallbackData: "edit(HELP)"}}} } var text string if key == "START" { text = fmt.Sprintf(config.TEXT["START"], update.CallbackQuery.From.FirstName, bot.FirstName) } else { text = config.TEXT[key] } editMarkup := gotgbot.InlineKeyboardMarkup{InlineKeyboard: markup} // Try to get the full message object origMsg, isMsg := update.CallbackQuery.Message.(*gotgbot.Message) // If it's a photo message (sent with START_IMAGE), edit caption if isMsg && len(origMsg.Photo) > 0 { _, _, err := origMsg.EditCaption(bot, &gotgbot.EditMessageCaptionOpts{ Caption: text, ParseMode: gotgbot.ParseModeHTML, ReplyMarkup: editMarkup, }) if err != nil { fmt.Printf("cbedit(caption): %v\n", err) } return nil } // Standard text message edit if isMsg { _, _, err := origMsg.EditText(bot, text, &gotgbot.EditMessageTextOpts{ ParseMode: gotgbot.ParseModeHTML, LinkPreviewOptions: &gotgbot.LinkPreviewOptions{IsDisabled: true}, ReplyMarkup: editMarkup, }) if err != nil { fmt.Printf("cbedit: %v\n", err) } return nil } // Fallback: use raw bot API with chat/message IDs chatID := update.CallbackQuery.Message.GetChat().Id msgID := update.CallbackQuery.Message.GetMessageId() _, _, err := bot.EditMessageText(text, &gotgbot.EditMessageTextOpts{ ChatId: chatID, MessageId: msgID, ParseMode: gotgbot.ParseModeHTML, LinkPreviewOptions: &gotgbot.LinkPreviewOptions{IsDisabled: true}, ReplyMarkup: editMarkup, }) if err != nil { // If EditText fails (e.g. message has photo), try EditCaption _, _, capErr := bot.EditMessageCaption(&gotgbot.EditMessageCaptionOpts{ ChatId: chatID, MessageId: msgID, Caption: text, ParseMode: gotgbot.ParseModeHTML, ReplyMarkup: editMarkup, }) if capErr != nil { // Both failed โ€” just update markup silently bot.EditMessageReplyMarkup(&gotgbot.EditMessageReplyMarkupOpts{ //nolint:errcheck ChatId: chatID, MessageId: msgID, ReplyMarkup: editMarkup, }) } } return nil } func About(b *gotgbot.Bot, update *ext.Context) error { _, err := update.Message.Reply(b, config.TEXT["ABOUT"], &gotgbot.SendMessageOpts{ParseMode: gotgbot.ParseModeHTML, ReplyMarkup: gotgbot.InlineKeyboardMarkup{InlineKeyboard: config.BUTTONS["ABOUT"]}}) if err != nil { fmt.Printf("about: %v\n", err) } return nil } func Help(b *gotgbot.Bot, update *ext.Context) error { _, err := update.Message.Reply(b, config.TEXT["HELP"], &gotgbot.SendMessageOpts{ParseMode: gotgbot.ParseModeHTML, ReplyMarkup: gotgbot.InlineKeyboardMarkup{InlineKeyboard: config.BUTTONS["HELP"]}}) if err != nil { fmt.Printf("help: %v\n", err) } return nil } // logNewUser sends a notification to the log channel for a new user. func logNewUser(bot *gotgbot.Bot, user *gotgbot.User) { logger.SendNewUser(bot, user) }