kickerbot_ng/src/handlers.go

396 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"bytes"
"context"
"database/sql"
"errors"
"fmt"
"log"
"strconv"
"strings"
"time"
"github.com/go-telegram/bot"
"github.com/go-telegram/bot/models"
)
func defaultHandler(ctx context.Context, b *bot.Bot, update *models.Update) {
// b.SendMessage(ctx, &bot.SendMessageParams{
// ChatID: update.Message.Chat.ID,
// Text: "hello!",
// })
if update.Message != nil {
log.Println(update.Message.Text)
}
log.Println(*update)
}
func registerChat(ctx context.Context, b *bot.Bot, update *models.Update) {
msg := update.Message
log.Println("registering", msg.Chat.ID)
m, err := FetchMemberFromChat(ctx, b, msg.Chat.ID, msg.From.ID)
if err == nil {
if !IsMemberAdmin(*m) {
log.Println("register: user is not admin")
return
}
args := strings.Split(msg.Text, " ")
if len(args) == 1 {
log.Println("register: there's no code")
return
}
if !UseActivation(args[1]) {
log.Println("register: wrong code: ", args[1])
return
}
if err := ActivateChat(msg.Chat.ID, msg.MessageThreadID); err != nil {
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,
})
if err == nil {
err := DeleteAfterSeconds(msg.Chat.ID, sent.ID, 60)
if err != nil {
log.Println("register: failed to add to delete", err)
}
}
} else {
log.Println("register: error", err)
}
}
func unregisterChat(ctx context.Context, b *bot.Bot, update *models.Update) {
msg := update.Message
log.Println("unregistering", msg.Chat.ID)
m, err := FetchMemberFromChat(ctx, b, msg.Chat.ID, msg.From.ID)
if err == nil {
if !IsMemberAdmin(*m) {
log.Println("register: user is not admin")
return
}
b.DeleteMessage(ctx, &bot.DeleteMessageParams{
ChatID: msg.Chat.ID,
MessageID: msg.ID,
})
db.Exec("update chats set active = 0 where id = $1", msg.Chat.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 {
log.Println("register: failed to add to delete", err)
}
}
} else {
log.Println("register: error", err)
}
}
var NewUserTemplate = `
Приветствую тебя, *%s*\!
Ты не можешь писать ничего в данном чате, пока не пройдешь капчу, которую я тебе пришлю в личку\.
Нужно только нажать на кнопку ниже\.
`
func handleNewJoined(ctx context.Context, b *bot.Bot, u *models.Update) {
var chat Chat
err := db.Get(&chat, "select * from chats where id = $1 and active = 1", u.Message.Chat.ID)
if err != nil {
log.Println("can't get chat for new joined: ", err)
}
for _, user := range u.Message.NewChatMembers {
text := fmt.Sprintf(NewUserTemplate, Mention(user.FirstName, user.ID))
msg, err := b.SendMessage(ctx, &bot.SendMessageParams{
ChatID: chat.Id,
MessageThreadID: int(chat.Topic),
Text: text,
ParseMode: models.ParseModeMarkdown,
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"},
},
},
},
})
if err != nil {
log.Println("Can't send message: ", err, "\n", text)
}
_, err = db.Exec(`INSERT INTO captchas (user_id, chat_id, message_id) values ($1, $2, $3)`, user.ID, u.Message.Chat.ID, msg.ID)
if err != nil {
log.Println("newusers: can't add to db: ", err)
return
}
_, err = b.RestrictChatMember(ctx, &bot.RestrictChatMemberParams{
ChatID: u.Message.Chat.ID,
UserID: user.ID,
Permissions: &models.ChatPermissions{
CanSendMessages: false,
CanSendAudios: false,
CanSendDocuments: false,
CanSendPhotos: false,
CanSendVideos: false,
CanSendVideoNotes: false,
CanSendVoiceNotes: false,
CanSendPolls: false,
CanSendOtherMessages: false,
CanAddWebPagePreviews: false,
CanChangeInfo: false,
CanInviteUsers: false,
CanPinMessages: false,
CanManageTopics: false,
},
})
if err != nil {
log.Println("Can't restrict new user: ", err)
}
}
}
func banUser(ctx context.Context, b *bot.Bot, u *models.Update) {
msg := u.Message
if msg.ReplyToMessage == nil {
newMsg, err := b.SendMessage(ctx, &bot.SendMessageParams{
Text: "Хочешь себя забанить? 🙃",
ReplyParameters: &models.ReplyParameters{
ChatID: msg.Chat.ID,
MessageID: msg.ID,
},
})
if err == nil {
AddMessageToDelete(MessageToDelete{MessageId: msg.ID, ChatId: msg.Chat.ID, DeleteDate: time.Now().Add(10 * time.Second).Unix()})
AddMessageToDelete(MessageToDelete{MessageId: newMsg.ID, ChatId: msg.Chat.ID, DeleteDate: time.Now().Add(10 * time.Second).Unix()})
}
return
}
reply := msg.ReplyToMessage
chatID := msg.Chat.ID
sender := msg.From
banned := reply.From
log.Println("banning user", banned.FirstName, "from", msg.Chat.ID)
m, err := FetchMemberFromChat(ctx, b, chatID, sender.ID)
if err == nil {
if !IsMemberAdmin(*m) {
log.Println("register: user is not admin")
return
}
text := reply.Text
if text == "" {
text = reply.Caption
}
reason := ""
days := 0
args := strings.SplitN(msg.Text, " ", 2)
if len(args) > 1 {
num, err := strconv.Atoi(args[1])
if err != nil {
reason = args[1]
} else {
if days > 0 {
days = num
}
if len(args) > 2 {
reason = args[2]
}
}
}
unbanDate := time.Now().Add(time.Duration(days) * time.Hour * 24).Unix()
b.DeleteMessage(ctx, &bot.DeleteMessageParams{
ChatID: msg.Chat.ID,
MessageID: msg.ID,
})
_, err := b.BanChatMember(ctx, &bot.BanChatMemberParams{
ChatID: chatID,
UserID: banned.ID,
UntilDate: int(unbanDate),
})
if err != nil {
log.Println("can't ban user: ", err)
return
}
newText := "Пользователь *%s* был забанен %s\\."
daysText := "навсегда"
if days > 0 {
daysText = fmt.Sprintf("на %d %s", days, pluralRu(days, "день", "дня", "дней"))
}
sent, err := b.SendMessage(ctx, &bot.SendMessageParams{
ChatID: msg.Chat.ID,
Text: fmt.Sprintf(newText, Mention(banned.FirstName, banned.ID), daysText),
MessageThreadID: msg.MessageThreadID,
})
db.Exec(
"insert into bans (chat_id, user_id, text, reason, ban_date, unban_date) values ($1, $2, $3, $4, $5, $6)",
chatID, banned.ID, text, reason, time.Now().Unix(), unbanDate,
)
if err == nil {
err := DeleteAfterSeconds(msg.Chat.ID, sent.ID, 60)
if err != nil {
log.Println("register: failed to add to delete", err)
}
}
} else {
log.Println("register: error", err)
}
}
var NewCaptchaTemplate = `
*%s*, тебе необходимо пройти капчу для чата *%s*\.
Для этого посмотри на картинку, найди логотип движка, который относится к вышеуказанному чату, а потом введи сюда код, который расположен над или под ним\.
Время у тебя неограничено, я буду ждать\!
`
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: "В чате, откуда ты пришёл, у тебя нет активных капч. Приходи в другой раз.",
ChatID: u.Message.Chat.ID,
})
return
}
} else {
err = db.Get(&captcha, `select * from captchas where user_id = $1 and correct_answer != ''`, userID)
if err != nil {
b.SendMessage(ctx, &bot.SendMessageParams{
Text: "У тебя нет активных капч ни в одном чате. Приходи в другой раз.",
ChatID: u.Message.Chat.ID,
})
return
}
}
type UserChatCaptcha struct {
Id int64 `db:"id"`
UserID int64 `db:"user_id"`
UserName string `db:"user_name"`
ChatID int64 `db:"chat_id"`
ChatName string `db:"chat_name"`
}
var userchat UserChatCaptcha
err = db.Get(&userchat, `
SELECT U.id AS user_id, C.id as chat_id, U.name as user_name, C.name as chat_name
FROM captchas
JOIN users AS U ON U.id = captchas.user_id
JOIN chats AS C ON C.id = captchas.chat_id
WHERE captchas.id = $1`, captcha.Id)
if err != nil {
log.Println("Can't get user and chat names: ", err)
}
if captcha.CorrectAnswer == "" {
img, answer := GenCaptcha()
captcha.CorrectAnswer = answer
if _, err := b.SendPhoto(ctx, &bot.SendPhotoParams{
Caption: fmt.Sprintf(NewCaptchaTemplate, userchat.UserName, userchat.ChatName),
Photo: &models.InputFileUpload{Filename: "captcha.png", Data: bytes.NewReader(img)},
ChatID: u.Message.Chat.ID,
ParseMode: models.ParseModeMarkdown,
}); err != nil {
log.Println("can't send private captcha: ", err)
}
_, err = db.NamedExec("update captchas set correct_answer = :correct_answer where id = :id", captcha)
if err != nil {
log.Println("Can't update captcha:", err)
}
} else {
b.SendMessage(ctx, &bot.SendMessageParams{
Text: fmt.Sprintf("Я тебе уже выдавал капчу для %d", captcha.ChatID),
ChatID: u.Message.Chat.ID,
})
}
}
func handlePrivateCaptcha(ctx context.Context, b *bot.Bot, u *models.Update) {
msg := u.Message
captcha := Captcha{}
err := db.Get(&captcha, "select * from captchas 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
text := ""
if msg.Text != captcha.CorrectAnswer {
text = "That's the wrong answer. Try again in 1 hour."
ban_minutes = 60
}
if ban_minutes > 0 {
b.SendMessage(ctx, &bot.SendMessageParams{ChatID: msg.From.ID, Text: text})
_, err := db.Exec("update captchas set blocked_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)
}
log.Println("Deleting message: ", captcha.ChatID, captcha.MessageID)
result, err := b.DeleteMessage(ctx, &bot.DeleteMessageParams{
ChatID: captcha.ChatID,
MessageID: captcha.MessageID,
})
log.Println("Deleting message:", result, err)
db.Exec("delete from captchas where id = $1", captcha.Id)
b.SendMessage(ctx, &bot.SendMessageParams{
Text: "Капча решена! Поздравляю! Теперь можешь вернуться в чат, я вернул тебе возможность отправлять там сообщения.\n\nСоветую ознакомиться с местными правилами, прежде чем что-либо писать!",
ChatID: msg.From.ID,
})
}