Handling captcha itself

This commit is contained in:
Nefrace 2024-07-28 23:01:58 +03:00
parent beeafa141a
commit 587b98eb7e
3 changed files with 98 additions and 23 deletions

View File

@ -10,41 +10,42 @@ var schema = `
create table if not exists chats create table if not exists chats
( (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
name TEXT, name TEXT NOT NULL,
username TEXT, username TEXT DEFAULT '',
topic INTEGER, topic INTEGER DEFAULT 0,
active INTEGER active INTEGER DEFAULT 0
); );
create table if not exists activations create table if not exists activations
( (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
code TEXT code TEXT NOT NULL
); );
create table if not exists messagesToDelete create table if not exists messagesToDelete
( (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
message_id INTEGER, message_id INTEGER NOT NULL,
chat_id INTEGER, chat_id INTEGER NOT NULL,
delete_date INTEGER, delete_date INTEGER NOT NULL,
tries INTEGER tries INTEGER DEFAULT 0
); );
create table if not exists users create table if not exists users
( (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
name TEXT, name TEXT NOT NULL,
username TEXT username TEXT DEFAULT ''
); );
create table if not exists bans create table if not exists bans
( (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
chat_id INTEGER,
user_id INTEGER, user_id INTEGER,
reason TEXT, reason TEXT NOT NULL,
ban_date INTEGER, ban_date INTEGER NOT NULL,
unban_date INTEGER, unban_date INTEGER DEFAULT 0,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
); );
@ -54,8 +55,10 @@ id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER, user_id INTEGER,
chat_id INTEGER, chat_id INTEGER,
message_id INTEGER, message_id INTEGER,
correct_answer INTEGER, correct_answer INTEGER DEFAULT 0,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE 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"` ChatID int64 `db:"chat_id"`
MessageID int `db:"message_id"` MessageID int `db:"message_id"`
CorrectAnswer int `db:"correct_answer"` CorrectAnswer int `db:"correct_answer"`
BlockedUntil int64 `db:"blocked_until"`
} }
var db *sqlx.DB var db *sqlx.DB

View File

@ -8,6 +8,7 @@ import (
"log" "log"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/go-telegram/bot" "github.com/go-telegram/bot"
"github.com/go-telegram/bot/models" "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) log.Println("Error activating chat: ", err)
return return
} }
b.DeleteMessage(ctx, &bot.DeleteMessageParams{ChatID: msg.Chat.ID, MessageID: msg.ID}) b.DeleteMessage(ctx, &bot.DeleteMessageParams{
sent, err := b.SendMessage(ctx, &bot.SendMessageParams{ChatID: msg.Chat.ID, Text: "Чат зарегистрирован", MessageThreadID: msg.MessageThreadID}) 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 { if err == nil {
err := DeleteAfterSeconds(msg.Chat.ID, sent.ID, 60) err := DeleteAfterSeconds(msg.Chat.ID, sent.ID, 60)
if err != nil { 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) { func handleNewJoined(ctx context.Context, b *bot.Bot, u *models.Update) {
for _, user := range u.Message.NewChatMembers { 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) msg, _ := b.SendMessage(ctx, &bot.SendMessageParams{
if err != nil {
log.Println("newusers: can't add to db: ", err)
}
b.SendMessage(ctx, &bot.SendMessageParams{
ChatID: u.Message.Chat.ID, ChatID: u.Message.Chat.ID,
Text: "Check the capthca!", Text: "Check the capthca!",
ReplyMarkup: models.InlineKeyboardMarkup{ 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})
}

View File

@ -42,6 +42,9 @@ func main() {
b.RegisterHandlerMatchFunc(func(update *models.Update) bool { b.RegisterHandlerMatchFunc(func(update *models.Update) bool {
return update.Message != nil && update.Message.Chat.Type == "private" && strings.HasPrefix(update.Message.Text, "/start") return update.Message != nil && update.Message.Chat.Type == "private" && strings.HasPrefix(update.Message.Text, "/start")
}, handlePrivateStartCaptcha) }, 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) go timedTask(ctx, b)