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