Scaffolding for new captcha type
This commit is contained in:
parent
aadc6e8a03
commit
beeafa141a
|
@ -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") {
|
||||||
|
|
Loading…
Reference in New Issue