Scaffolding for new captcha type
This commit is contained in:
		@ -3,6 +3,7 @@ package main
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/go-telegram/bot"
 | 
						"github.com/go-telegram/bot"
 | 
				
			||||||
	"github.com/go-telegram/bot/models"
 | 
						"github.com/go-telegram/bot/models"
 | 
				
			||||||
@ -38,3 +39,7 @@ func FetchMemberFromChat(ctx context.Context, b *bot.Bot, chatID int64, userID i
 | 
				
			|||||||
func IsAdmin(member models.ChatMember) bool {
 | 
					func IsAdmin(member models.ChatMember) bool {
 | 
				
			||||||
	return member.Administrator != nil || member.Owner != nil
 | 
						return member.Administrator != nil || member.Owner != nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func DeleteAfterSeconds(chatID int64, msgID int, seconds int) error {
 | 
				
			||||||
 | 
						return AddMessageToDelete(MessageToDelete{MessageId: msgID, ChatId: chatID, DeleteDate: time.Now().Add(time.Duration(seconds) * time.Second).Unix(), Tries: 0})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										16
									
								
								src/db.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/db.go
									
									
									
									
									
								
							@ -27,7 +27,8 @@ create table if not exists messagesToDelete
 | 
				
			|||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
 | 
					id INTEGER PRIMARY KEY AUTOINCREMENT,
 | 
				
			||||||
message_id INTEGER,
 | 
					message_id INTEGER,
 | 
				
			||||||
chat_id INTEGER,
 | 
					chat_id INTEGER,
 | 
				
			||||||
delete_date INTEGER
 | 
					delete_date INTEGER,
 | 
				
			||||||
 | 
					tries INTEGER
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
create table if not exists users
 | 
					create table if not exists users
 | 
				
			||||||
@ -71,6 +72,7 @@ type MessageToDelete struct {
 | 
				
			|||||||
	MessageId  int   `db:"message_id"`
 | 
						MessageId  int   `db:"message_id"`
 | 
				
			||||||
	ChatId     int64 `db:"chat_id"`
 | 
						ChatId     int64 `db:"chat_id"`
 | 
				
			||||||
	DeleteDate int64 `db:"delete_date"`
 | 
						DeleteDate int64 `db:"delete_date"`
 | 
				
			||||||
 | 
						Tries      int   `db:"tries"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type User struct {
 | 
					type User struct {
 | 
				
			||||||
@ -79,6 +81,14 @@ type User struct {
 | 
				
			|||||||
	Username string `db:"username"`
 | 
						Username string `db:"username"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Captcha struct {
 | 
				
			||||||
 | 
						Id            int64 `db:"id"`
 | 
				
			||||||
 | 
						UserID        int64 `db:"user_id"`
 | 
				
			||||||
 | 
						ChatID        int64 `db:"chat_id"`
 | 
				
			||||||
 | 
						MessageID     int   `db:"message_id"`
 | 
				
			||||||
 | 
						CorrectAnswer int   `db:"correct_answer"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var db *sqlx.DB
 | 
					var db *sqlx.DB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func InitDb() error {
 | 
					func InitDb() error {
 | 
				
			||||||
@ -127,7 +137,7 @@ func NewActivation(code string) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func UseActivation(code string) bool {
 | 
					func UseActivation(code string) bool {
 | 
				
			||||||
	exists := false
 | 
						exists := false
 | 
				
			||||||
	err := db.Get(&exists, `SELECT exists(SELECT 1 FROM chats WHERE code = $1);`, code)
 | 
						err := db.Get(&exists, `SELECT exists(SELECT 1 FROM activations WHERE code = $1);`, code)
 | 
				
			||||||
	if err != nil || !exists {
 | 
						if err != nil || !exists {
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -141,7 +151,7 @@ func ActivateChat(id int64) error {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func AddMessageToDelete(msg MessageToDelete) error {
 | 
					func AddMessageToDelete(msg MessageToDelete) error {
 | 
				
			||||||
	_, err := db.NamedExec(`insert into messagesToDelete (message_id, chat_id, delete_date) values (:message_id, :chat_id, :delete_date)`, msg)
 | 
						_, err := db.NamedExec(`insert into messagesToDelete (message_id, chat_id, delete_date, tries) values (:message_id, :chat_id, :delete_date, 0)`, msg)
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,9 +2,12 @@ package main
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"database/sql"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
 | 
						"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"
 | 
				
			||||||
@ -15,6 +18,9 @@ func defaultHandler(ctx context.Context, b *bot.Bot, update *models.Update) {
 | 
				
			|||||||
	// 	ChatID: update.Message.Chat.ID,
 | 
						// 	ChatID: update.Message.Chat.ID,
 | 
				
			||||||
	// 	Text:   "hello!",
 | 
						// 	Text:   "hello!",
 | 
				
			||||||
	// })
 | 
						// })
 | 
				
			||||||
 | 
						if update.Message != nil {
 | 
				
			||||||
 | 
							log.Println(update.Message.Text)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	log.Println(*update)
 | 
						log.Println(*update)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -33,7 +39,7 @@ func registerChat(ctx context.Context, b *bot.Bot, update *models.Update) {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if !UseActivation(args[1]) {
 | 
							if !UseActivation(args[1]) {
 | 
				
			||||||
			log.Println("register: wrong code")
 | 
								log.Println("register: wrong code: ", args[1])
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := ActivateChat(msg.Chat.ID); err != nil {
 | 
							if err := ActivateChat(msg.Chat.ID); err != nil {
 | 
				
			||||||
@ -43,7 +49,7 @@ func registerChat(ctx context.Context, b *bot.Bot, update *models.Update) {
 | 
				
			|||||||
		b.DeleteMessage(ctx, &bot.DeleteMessageParams{ChatID: msg.Chat.ID, MessageID: msg.ID})
 | 
							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})
 | 
							sent, err := b.SendMessage(ctx, &bot.SendMessageParams{ChatID: msg.Chat.ID, Text: "Чат зарегистрирован", MessageThreadID: msg.MessageThreadID})
 | 
				
			||||||
		if err == nil {
 | 
							if err == nil {
 | 
				
			||||||
			err := AddMessageToDelete(MessageToDelete{MessageId: sent.ID, ChatId: msg.Chat.ID, DeleteDate: time.Now().Add(1 * time.Minute).Unix()})
 | 
								err := DeleteAfterSeconds(msg.Chat.ID, sent.ID, 60)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				log.Println("register: failed to add to delete", err)
 | 
									log.Println("register: failed to add to delete", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -55,10 +61,79 @@ 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 {
 | 
				
			||||||
		log.Println(user)
 | 
							_, 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{
 | 
				
			||||||
 | 
								ChatID: u.Message.Chat.ID,
 | 
				
			||||||
 | 
								Text:   "Check the capthca!",
 | 
				
			||||||
 | 
								ReplyMarkup: models.InlineKeyboardMarkup{
 | 
				
			||||||
 | 
									InlineKeyboard: [][]models.InlineKeyboardButton{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											{URL: fmt.Sprintf("https://t.me/nefrace_php_test_bot?start=cap_%d", u.Message.Chat.ID), Text: "Check"},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func banUser(ctx context.Context, b *bot.Bot, u *models.Update) {
 | 
					func banUser(ctx context.Context, b *bot.Bot, u *models.Update) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func handlePrivateStartCaptcha(ctx context.Context, b *bot.Bot, u *models.Update) {
 | 
				
			||||||
 | 
						args := strings.Split(u.Message.Text, " ")
 | 
				
			||||||
 | 
						userID := u.Message.From.ID
 | 
				
			||||||
 | 
						chatID := 0
 | 
				
			||||||
 | 
						if len(args) > 1 {
 | 
				
			||||||
 | 
							chat_str := strings.TrimPrefix(args[1], "cap_")
 | 
				
			||||||
 | 
							id, err := strconv.Atoi(chat_str)
 | 
				
			||||||
 | 
							if err == nil {
 | 
				
			||||||
 | 
								chatID = id
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						captcha := Captcha{}
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						if chatID != 0 {
 | 
				
			||||||
 | 
							err = db.Get(&captcha, `select * from captchas where user_id = $1 and chat_id = $2`, userID, chatID)
 | 
				
			||||||
 | 
							if errors.Is(err, sql.ErrNoRows) {
 | 
				
			||||||
 | 
								b.SendMessage(ctx, &bot.SendMessageParams{
 | 
				
			||||||
 | 
									Text:   " There's no captchas for that chat you came from.",
 | 
				
			||||||
 | 
									ChatID: u.Message.Chat.ID,
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err = db.Get(&captcha, `select * from captchas where user_id = $1 and correct_answer != 0`, userID)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								b.SendMessage(ctx, &bot.SendMessageParams{
 | 
				
			||||||
 | 
									Text:   " There's no captchas for that chat you came from.",
 | 
				
			||||||
 | 
									ChatID: u.Message.Chat.ID,
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if captcha.CorrectAnswer == 0 {
 | 
				
			||||||
 | 
							captcha.CorrectAnswer = 42
 | 
				
			||||||
 | 
							msg, err := b.SendMessage(ctx, &bot.SendMessageParams{
 | 
				
			||||||
 | 
								Text:   "Get me the answer!",
 | 
				
			||||||
 | 
								ChatID: u.Message.Chat.ID,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							if err == nil {
 | 
				
			||||||
 | 
								captcha.MessageID = msg.ID
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							_, err = db.NamedExec("update captchas set correct_answer = :correct_answer, message_id = :message_id where id = :id", captcha)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Println("Can't update captcha:", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							b.SendMessage(ctx, &bot.SendMessageParams{
 | 
				
			||||||
 | 
								Text:   fmt.Sprintf("You already have captcha for chat %d", captcha.ChatID),
 | 
				
			||||||
 | 
								ChatID: u.Message.Chat.ID,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										43
									
								
								src/main.go
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								src/main.go
									
									
									
									
									
								
							@ -2,8 +2,11 @@ package main
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"os/signal"
 | 
						"os/signal"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_ "github.com/glebarez/go-sqlite"
 | 
						_ "github.com/glebarez/go-sqlite"
 | 
				
			||||||
	"github.com/go-telegram/bot"
 | 
						"github.com/go-telegram/bot"
 | 
				
			||||||
@ -36,5 +39,45 @@ func main() {
 | 
				
			|||||||
	b.RegisterHandlerMatchFunc(func(update *models.Update) bool {
 | 
						b.RegisterHandlerMatchFunc(func(update *models.Update) bool {
 | 
				
			||||||
		return update.Message != nil && len(update.Message.NewChatMembers) > 0
 | 
							return update.Message != nil && len(update.Message.NewChatMembers) > 0
 | 
				
			||||||
	}, handleNewJoined)
 | 
						}, handleNewJoined)
 | 
				
			||||||
 | 
						b.RegisterHandlerMatchFunc(func(update *models.Update) bool {
 | 
				
			||||||
 | 
							return update.Message != nil && update.Message.Chat.Type == "private" && strings.HasPrefix(update.Message.Text, "/start")
 | 
				
			||||||
 | 
						}, handlePrivateStartCaptcha)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go timedTask(ctx, b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	b.Start(ctx)
 | 
						b.Start(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func timedTask(ctx context.Context, b *bot.Bot) {
 | 
				
			||||||
 | 
						timer := time.NewTicker(time.Second * 30)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					task:
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case <-timer.C:
 | 
				
			||||||
 | 
								deleteOldMessages(ctx, b)
 | 
				
			||||||
 | 
							case <-ctx.Done():
 | 
				
			||||||
 | 
								break task
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func deleteOldMessages(ctx context.Context, b *bot.Bot) {
 | 
				
			||||||
 | 
						now := time.Now().Unix()
 | 
				
			||||||
 | 
						messages := []MessageToDelete{}
 | 
				
			||||||
 | 
						err := db.Select(&messages, `SELECT * from messagesToDelete WHERE delete_date < $1`, now)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Println("delete_old: can't get messages: ", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, message := range messages {
 | 
				
			||||||
 | 
							success, err := b.DeleteMessage(ctx, &bot.DeleteMessageParams{ChatID: message.ChatId, MessageID: message.MessageId})
 | 
				
			||||||
 | 
							if !success {
 | 
				
			||||||
 | 
								log.Println("delete_old, message wasn't deleted: ", message.MessageId, " :: ", err)
 | 
				
			||||||
 | 
								db.Exec(`UPDATE messagesToDelete set tries = tries + 1 where id = $1`, message.Id)
 | 
				
			||||||
 | 
								if message.Tries < 3 {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							db.Exec(`DELETE FROM messagesToDelete WHERE id = $1`, message.Id)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,7 @@ func checkRegistered(next bot.HandlerFunc) bot.HandlerFunc {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		chat := update.Message.Chat
 | 
							chat := update.Message.Chat
 | 
				
			||||||
		if chat.Type == "private" {
 | 
							if chat.Type == "private" {
 | 
				
			||||||
 | 
								next(ctx, b, update)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if !IsChatActive(chat.ID) && !strings.HasPrefix(update.Message.Text, "/register") {
 | 
							if !IsChatActive(chat.ID) && !strings.HasPrefix(update.Message.Text, "/register") {
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user