Вступление
Перед тем как начать писать своего бота я пытался использовать уже существующих, но все они обладали своими недостатками. Так как я был админом русскоязычного гео-чата в Telegram мне нужно было решение которое бы справлялась с большим количеством ботов не загрязняя ленту сообщений другими сообщения о том что один пользователь заблокирован или удален
Минусы существующих ботов:
-
Большие информационные сообщения по типу: “Сообщение удалено так как …", что плохо работает там, где есть много спам ботов
-
Проверка на капчу не решает проблемы англоязычных ботов-торговцев, которые решают простую капчу и затем вставляют свое спам сообщение. Мне нужно было решение, которое оставит только русскоязычных пользователей
Решение
Решением стало написание свое бота, который задавал вопросы по типу:
@username Добро пожаловать в чат @chatname! Напишите числом сколько будет: два умножить на три, чтобы проверить, что вы не бот
Пользователю нужно ответить правильно, другие сообщения будут удаляться
Как добавить бота в чат?
Сначала вам нужно пригласить бота в чат по его никнейму: @spam_fighter_bot
Ссылка на бота: https://t.me/spam_fighter_bot
- Добавляете бота в чат:
- После этого добавляете бота как админа в настройках чата:
- Даете боту права доступа на удаление сообщений и бан пользователей:
Готово!
Код
Для работы с сообщениями в телеграм я решил использовать библиотеку 🔗tucnak/telebot с которой я уже работал раньше и которая кажется мне весьма удобной
Для начала надо настроить и запустить нового бота:
В импорты нужно добавить:
import (
tb "gopkg.in/tucnak/telebot.v2"
)
И таким образом запускается наш бот
// initialize bot
b, err := tb.NewBot(tb.Settings{
Token: "YOUR_TOKEN",
Poller: &tb.LongPoller{Timeout: 10 * time.Second},
})
if err != nil {
fmt.Printf("error while initializing bot, %v", err)
}
Для того чтобы отследить когда новый пользователь зайдет в чат, нужно добавить отлавливание этих событий:
b.Handle(tb.OnUserJoined, UserJoined(l, b, memoryStorage))
А вот так выглядит сама функция UserJoined
:
func UserJoined(l *zap.SugaredLogger, b *tb.Bot, s data.Storage) func(m *tb.Message) {
return func(m *tb.Message) {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
// generating two random small number
firstNumber := r.Intn(4) + 1
secondNumber := r.Intn(4) + 1
fistNumberInWords := ntw.IntegerToRuRu(firstNumber)
secondNumberInWords := ntw.IntegerToRuRu(secondNumber)
username := getUsername(m.Sender)
welcomeMessageText := getWelcomeMessageText(username, m.Chat.Title, fistNumberInWords, secondNumberInWords)
welcomeMessage, err := b.Send(m.Chat, welcomeMessageText)
if err != nil {
l.Error("error while sending welcome message", err)
return
}
s.Add(m.Chat, m.Sender, data.Info{WelcomeMessage: welcomeMessage, RightAnswer: firstNumber * secondNumber})
// Goroutine to delete message after 2 minutes
// and block user if he or she still in the list
go checkAndBanUser(l, b, welcomeMessage, s, m, username)
}
}
Она генерирут два случайных числа и конвертирует их в текст. Правильный ответ записывается в память. Затем в горутине ожидается 2 минуты от отправки сообщения, если пользователь так и не решил правильно ответ, то он блокируется и удаляется из чата
Вот так выглядит код для проверки ответа пользователя:
func Text(l *zap.SugaredLogger, b *tb.Bot, s data.Storage) func(m *tb.Message) {
return func(m *tb.Message) {
info, ok := s.Exist(m.Chat, m.Sender)
if !ok {
return
}
if m.Text != strconv.Itoa(info.RightAnswer) {
err := b.Delete(m)
if err != nil {
l.Errorf("error while deleting (spam) user message: %v", err)
}
return
}
// in case of correct answer:
s.Remove(m.Chat, m.Sender)
// Correct! Tell us about yourself
approveMessage, err := b.Send(m.Chat, "Верно! Расскажите нам о себе 🙂")
if err != nil {
l.Errorf("error while sending: %v", err)
}
go deleteWelcomeMessages(l, b, m, approveMessage, info.WelcomeMessage)
}
}
Итог работы бота
По итогу бот очень успешно банит других ботов, не давая им написать сообщение с рекламой. Никто не переводит сообщения на английский язык и поэтому не знает что именно нужно делать. Таким образом пока получается блокировать всех ботов, хотя раньше с другими анти-спам ботами 50% просто решали капчу и писали спам
Исходный код
Исходный код, который деплоится затем на сервер вы можете найти тут:
Вы можете предложить свои изменения и улучшения, код открытый
После мержа код автоматически деплоится в продакшен (если билд пройдет успешно)
comments powered by Disqus