Handling captcha itself
This commit is contained in:
		
							
								
								
									
										36
									
								
								src/db.go
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								src/db.go
									
									
									
									
									
								
							@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user