diff --git a/src/db.go b/src/db.go index b0885a0..937ffe9 100644 --- a/src/db.go +++ b/src/db.go @@ -10,41 +10,42 @@ var schema = ` create table if not exists chats ( id INTEGER PRIMARY KEY, -name TEXT, -username TEXT, -topic INTEGER, -active INTEGER +name TEXT NOT NULL, +username TEXT DEFAULT '', +topic INTEGER DEFAULT 0, +active INTEGER DEFAULT 0 ); create table if not exists activations ( id INTEGER PRIMARY KEY AUTOINCREMENT, -code TEXT +code TEXT NOT NULL ); create table if not exists messagesToDelete ( id INTEGER PRIMARY KEY AUTOINCREMENT, -message_id INTEGER, -chat_id INTEGER, -delete_date INTEGER, -tries INTEGER +message_id INTEGER NOT NULL, +chat_id INTEGER NOT NULL, +delete_date INTEGER NOT NULL, +tries INTEGER DEFAULT 0 ); create table if not exists users ( id INTEGER PRIMARY KEY, -name TEXT, -username TEXT +name TEXT NOT NULL, +username TEXT DEFAULT '' ); create table if not exists bans ( id INTEGER PRIMARY KEY AUTOINCREMENT, +chat_id INTEGER, user_id INTEGER, -reason TEXT, -ban_date INTEGER, -unban_date INTEGER, +reason TEXT NOT NULL, +ban_date INTEGER NOT NULL, +unban_date INTEGER DEFAULT 0, FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ); @@ -54,8 +55,10 @@ id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER, chat_id INTEGER, message_id INTEGER, -correct_answer INTEGER, -FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE +correct_answer INTEGER DEFAULT 0, +blocked_until INTEGER DEFAULT 0, +FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE, +FOREIGN KEY (chat_id) REFERENCES chats (id) ON DELETE CASCADE ) ` @@ -87,6 +90,7 @@ type Captcha struct { ChatID int64 `db:"chat_id"` MessageID int `db:"message_id"` CorrectAnswer int `db:"correct_answer"` + BlockedUntil int64 `db:"blocked_until"` } var db *sqlx.DB diff --git a/src/handlers.go b/src/handlers.go index 33f798f..c0c41a5 100644 --- a/src/handlers.go +++ b/src/handlers.go @@ -8,6 +8,7 @@ import ( "log" "strconv" "strings" + "time" "github.com/go-telegram/bot" "github.com/go-telegram/bot/models" @@ -46,8 +47,15 @@ func registerChat(ctx context.Context, b *bot.Bot, update *models.Update) { log.Println("Error activating chat: ", err) return } - b.DeleteMessage(ctx, &bot.DeleteMessageParams{ChatID: msg.Chat.ID, MessageID: msg.ID}) - sent, err := b.SendMessage(ctx, &bot.SendMessageParams{ChatID: msg.Chat.ID, Text: "Чат зарегистрирован", MessageThreadID: msg.MessageThreadID}) + b.DeleteMessage(ctx, &bot.DeleteMessageParams{ + ChatID: msg.Chat.ID, + MessageID: msg.ID, + }) + sent, err := b.SendMessage(ctx, &bot.SendMessageParams{ + ChatID: msg.Chat.ID, + Text: "Чат зарегистрирован", + MessageThreadID: msg.MessageThreadID, + }) if err == nil { err := DeleteAfterSeconds(msg.Chat.ID, sent.ID, 60) if err != nil { @@ -61,11 +69,7 @@ func registerChat(ctx context.Context, b *bot.Bot, update *models.Update) { func handleNewJoined(ctx context.Context, b *bot.Bot, u *models.Update) { for _, user := range u.Message.NewChatMembers { - _, err := db.Exec(`INSERT INTO captchas (user_id, chat_id, message_id, correct_answer) values ($1, $2, 0, 0)`, user.ID, u.Message.Chat.ID) - if err != nil { - log.Println("newusers: can't add to db: ", err) - } - b.SendMessage(ctx, &bot.SendMessageParams{ + msg, _ := b.SendMessage(ctx, &bot.SendMessageParams{ ChatID: u.Message.Chat.ID, Text: "Check the capthca!", ReplyMarkup: models.InlineKeyboardMarkup{ @@ -76,6 +80,10 @@ func handleNewJoined(ctx context.Context, b *bot.Bot, u *models.Update) { }, }, }) + _, err := db.Exec(`INSERT INTO captchas (user_id, chat_id, message_id, correct_answer, blocked_until) values ($1, $2, $3, 0, 0)`, user.ID, u.Message.Chat.ID, msg.ID) + if err != nil { + log.Println("newusers: can't add to db: ", err) + } } } @@ -137,3 +145,63 @@ func handlePrivateStartCaptcha(ctx context.Context, b *bot.Bot, u *models.Update }) } } + +func handlePrivateCaptcha(ctx context.Context, b *bot.Bot, u *models.Update) { + msg := u.Message + captcha := Captcha{} + err := db.Get(&captcha, "select * from captcha where user_id = $1 and correct_answer != 0", msg.From.ID) + + if err != nil { + log.Println("Can't solve user captcha: ", err) + return + } + + now := time.Now().Unix() + if captcha.BlockedUntil > now { + log.Println("User needs to try again next time: ", msg.From.ID, msg.From.Username, msg.From.FirstName) + return + } + + ban_minutes := 0 + num, err := strconv.Atoi(msg.Text) + if err != nil { + b.SendMessage(ctx, &bot.SendMessageParams{ChatID: msg.From.ID, Text: "That's not a number. Try again in 30 minutes."}) + ban_minutes = 30 + } + + if num != captcha.CorrectAnswer { + b.SendMessage(ctx, &bot.SendMessageParams{ChatID: msg.From.ID, Text: "That's the wrong answer. Try again in 5 hours."}) + ban_minutes = 300 + } + + if ban_minutes > 0 { + _, err := db.Exec("update captcha set banned_until = $2 where id = $1", captcha.Id, time.Now().Add(time.Minute * time.Duration(ban_minutes)).Unix()) + if err != nil { + log.Println("Can't block user from captcha: ", err) + } + return + } + + _, err = b.RestrictChatMember(ctx, &bot.RestrictChatMemberParams{ChatID: captcha.ChatID, UserID: captcha.UserID, Permissions: &models.ChatPermissions{ + CanSendMessages: true, + CanSendAudios: true, + CanSendDocuments: true, + CanSendPhotos: true, + CanSendVideos: true, + CanSendVideoNotes: true, + CanSendVoiceNotes: true, + CanSendPolls: true, + CanSendOtherMessages: true, + CanAddWebPagePreviews: true, + CanChangeInfo: true, + CanInviteUsers: true, + CanPinMessages: true, + CanManageTopics: true, + }}) + if err != nil { + log.Println("Can't unrestrict user: ", err) + } + + b.SendMessage(ctx, &bot.SendMessageParams{Text: "Captcha solved! Congrats!", ChatID: msg.From.ID}) + +} diff --git a/src/main.go b/src/main.go index 126ac83..3895d22 100644 --- a/src/main.go +++ b/src/main.go @@ -42,6 +42,9 @@ func main() { b.RegisterHandlerMatchFunc(func(update *models.Update) bool { return update.Message != nil && update.Message.Chat.Type == "private" && strings.HasPrefix(update.Message.Text, "/start") }, handlePrivateStartCaptcha) + b.RegisterHandlerMatchFunc(func(update *models.Update) bool { + return update.Message != nil && update.Message.Chat.Type == "private" && !strings.HasPrefix(update.Message.Text, "/start") + }, handlePrivateCaptcha) go timedTask(ctx, b)