From 15a27af994e886fd8fc117882d0535bc66f4b3b6 Mon Sep 17 00:00:00 2001 From: nefrace Date: Tue, 14 Feb 2023 00:50:21 +0300 Subject: [PATCH 01/18] Moved to Tongo wrapper --- db/structs.go | 39 ++++++++++++++++-------- go.mod | 1 + go.sum | 2 ++ kicker/handlers.go | 76 +++++++++++++++++++++++++--------------------- kicker/kicker.go | 34 +++++++++++++-------- kicker/tasks.go | 51 +++++++++++++++++++++---------- main.go | 10 ++++-- 7 files changed, 133 insertions(+), 80 deletions(-) diff --git a/db/structs.go b/db/structs.go index 683728c..baa6308 100644 --- a/db/structs.go +++ b/db/structs.go @@ -1,20 +1,33 @@ package db +import ( + "time" + + "git.nefrace.ru/nefrace/tongo" +) + type Chat struct { - Id int64 - Title string - TopicId int64 `bson:"topic_id"` + tongo.Item `bson:",inline"` + ChatId int64 + Title string + TopicId int64 `bson:"topic_id"` } +func (Chat) Coll() string { return "chats" } + type User struct { - Id int64 - ChatId int64 `bson:"chat_id"` - Username string `bson:"username"` - FirstName string `bson:"first_name"` - LastName string `bson:"last_name"` - CorrectAnswer int8 `bson:"correct_answer"` - CaptchaMessage int `bson:"captcha_message"` - IsBanned bool `bson:"is_banned"` - DateJoined int64 `bson:"date_joined"` - JoinedMessage int `bson:"joined_message"` + tongo.Item `bson:",inline"` + UserId int64 `bson:"user_id"` + ChatId int64 `bson:"chat_id"` + Username string `bson:"username"` + FirstName string `bson:"first_name"` + LastName string `bson:"last_name"` + CorrectAnswer int8 `bson:"correct_answer"` + CaptchaMessage int `bson:"captcha_message"` + IsBanned bool `bson:"is_banned"` + DateJoined time.Time `bson:"date_joined"` + JoinedMessage int `bson:"joined_message"` + LastNotification time.Time `bson:"last_notification"` } + +func (User) Coll() string { return "users" } diff --git a/go.mod b/go.mod index 5103c96..20a9c4c 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( ) require ( + git.nefrace.ru/nefrace/tongo v0.0.0-20230124201743-e58da1b7d030 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/klauspost/compress v1.15.13 // indirect diff --git a/go.sum b/go.sum index 9d3c077..a73ddf2 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +git.nefrace.ru/nefrace/tongo v0.0.0-20230124201743-e58da1b7d030 h1:s/T9bu8B/JQihx7HVj0Z7MG+veTAV97vEvNGfak+Wxo= +git.nefrace.ru/nefrace/tongo v0.0.0-20230124201743-e58da1b7d030/go.mod h1:I6AwXVmI+xC2kZ4TriUXK2Jchni1MZfiQQ4IWQBwC88= github.com/NicoNex/echotron/v3 v3.21.0 h1:6YDSYA/AGlPxWoUdOIRrBvUZ0RhRa2W4taS4eSrbdXw= github.com/NicoNex/echotron/v3 v3.21.0/go.mod h1:LpP5IyHw0y+DZUZMBgXEDAF9O8feXrQu7w7nlJzzoZI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/kicker/handlers.go b/kicker/handlers.go index f87250b..8de4654 100644 --- a/kicker/handlers.go +++ b/kicker/handlers.go @@ -9,11 +9,11 @@ import ( "strconv" "time" - tb "github.com/NicoNex/echotron/v3" - "go.mongodb.org/mongo-driver/bson" + "git.nefrace.ru/nefrace/tongo" + "github.com/NicoNex/echotron/v3" ) -func userJoined(b *bot, update *tb.Update) error { +func userJoined(b *bot, update *echotron.Update) error { captcha := captchagen.GenCaptcha() _, err := b.DeleteMessage(update.Message.Chat.ID, update.Message.ID) if err != nil { @@ -22,11 +22,13 @@ func userJoined(b *bot, update *tb.Update) error { bytes, err := captcha.ToBytes() if err != nil { log.Printf("Error creating captcha bytes: %v", bytes) - b.SendMessage("Не могу создать капчу, @nefrace, проверь логи.", update.Message.From.ID, &tb.MessageOptions{MessageThreadID: update.Message.ThreadID}) + b.SendMessage("Не могу создать капчу, @nefrace, проверь логи.", update.Message.From.ID, &echotron.MessageOptions{MessageThreadID: update.Message.ThreadID}) } message := update.Message + store := tongo.NewStore[db.User](Client) user := db.User{ - Id: message.From.ID, + Item: tongo.NewID(), + UserId: message.From.ID, Username: message.From.Username, FirstName: message.From.FirstName, LastName: message.From.LastName, @@ -34,52 +36,51 @@ func userJoined(b *bot, update *tb.Update) error { ChatId: message.Chat.ID, JoinedMessage: message.ID, CorrectAnswer: int8(captcha.CorrectAnswer), - DateJoined: time.Now().Unix(), + DateJoined: time.Now(), } - user.CorrectAnswer = int8(captcha.CorrectAnswer) - d := db.GetDatabase() + // user.CorrectAnswer = int8(captcha.CorrectAnswer) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() log.Print(user) - msg := fmt.Sprintf("Приветствую тебя, *[%s](tg://user?id=%d)*\\!\nДля подтверждения, что ты человек, выбери логотип движка, которому посвящен данный чат, и отправь его номер сюда\\.\n*_Я дам тебе две минуты на это\\._*", EscapeText(tb.MarkdownV2, user.FirstName), user.Id) - options := tb.PhotoOptions{ + msg := fmt.Sprintf("Приветствую тебя, *[%s](tg://user?id=%d)*\\!\nДля подтверждения, что ты человек, выбери логотип движка, которому посвящен данный чат, и отправь его номер сюда\\.\n*_Я дам тебе десять минут на это\\._*", EscapeText(echotron.MarkdownV2, user.FirstName), user.Id) + options := echotron.PhotoOptions{ Caption: msg, - ParseMode: tb.MarkdownV2, + ParseMode: echotron.MarkdownV2, } if message.Chat.IsForum { options.MessageThreadID = int(b.CaptchaTopic) } - result, err := b.SendPhoto(tb.NewInputFileBytes("logos.png", *bytes), message.Chat.ID, &options) + result, err := b.SendPhoto(echotron.NewInputFileBytes("logos.png", *bytes), message.Chat.ID, &options) if err != nil { return err } user.CaptchaMessage = result.Result.ID - - d.NewUser(ctx, user) + store.InsertOne(ctx, &user) return nil } -func userLeft(b *bot, update *tb.Update) error { +func userLeft(b *bot, update *echotron.Update) error { message := update.Message sender := message.From - d := db.GetDatabase() + store := tongo.NewStore[db.User](Client) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() - if user, err := d.GetUser(ctx, db.User{Id: sender.ID, ChatId: message.Chat.ID}); err == nil { - d.RemoveUser(ctx, user) + if user, err := store.GetOne(ctx, tongo.E("user_id", sender.ID), tongo.E("chat_id", message.Chat.ID)); err == nil { //d.GetUser(ctx, db.User{UserId: sender.ID, ChatId: message.Chat.ID}); err == nil { + store.DeleteByID(ctx, user.Id) b.DeleteMessage(message.Chat.ID, message.ID) b.DeleteMessage(message.Chat.ID, user.CaptchaMessage) } return nil } -func checkCaptcha(b *bot, update *tb.Update) error { +func checkCaptcha(b *bot, update *echotron.Update) error { message := update.Message sender := message.From + store := tongo.NewStore[db.User](Client) d := db.GetDatabase() ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() - if user, err := d.GetUser(ctx, db.User{Id: sender.ID, ChatId: message.Chat.ID}); err == nil { + if user, err := store.GetOne(ctx, tongo.E("user_id", sender.ID), tongo.E("chat_id", message.Chat.ID)); err == nil { //d.GetUser(ctx, db.User{UserId: sender.ID, ChatId: message.Chat.ID}); err == nil { if message.Chat.IsForum { chat, err := d.GetChat(ctx, message.Chat.ID) if err != nil { @@ -87,6 +88,9 @@ func checkCaptcha(b *bot, update *tb.Update) error { } if message.ThreadID != int(chat.TopicId) { b.DeleteMessage(message.Chat.ID, message.ID) + text := fmt.Sprintf("*[%s](tg://user?id=%d)*, сначала пройди капчу\\!", user.FirstName, user.UserId) + res, _ := b.SendMessage(text, message.Chat.ID, &echotron.MessageOptions{ParseMode: echotron.MarkdownV2, MessageThreadID: message.ThreadID}) + go waitAndDelete(&b.API, res.Result, 30*time.Second) return nil } } @@ -95,13 +99,13 @@ func checkCaptcha(b *bot, update *tb.Update) error { solved := false if num, err := strconv.Atoi(guess); err == nil { if num == int(user.CorrectAnswer) { - _ = d.RemoveUser(ctx, user) + _ = store.DeleteByID(ctx, user.Id) solved = true b.DeleteMessage(message.Chat.ID, message.ID) b.DeleteMessage(message.Chat.ID, user.CaptchaMessage) - msg := fmt.Sprintf("*[%s](tg://user?id=%d)* только что успешно прошёл капчу\\!", EscapeText(tb.MarkdownV2, user.FirstName), user.Id) - options := tb.MessageOptions{ - ParseMode: tb.MarkdownV2, + msg := fmt.Sprintf("*[%s](tg://user?id=%d)* только что успешно прошёл капчу\\!", EscapeText(echotron.MarkdownV2, user.FirstName), user.Id) + options := echotron.MessageOptions{ + ParseMode: echotron.MarkdownV2, } if message.Chat.IsForum { options.MessageThreadID = int(b.CaptchaTopic) @@ -110,8 +114,9 @@ func checkCaptcha(b *bot, update *tb.Update) error { if err != nil { log.Printf("Can't send welcome message: %s", err) } - time.Sleep(time.Second * 10) - _, err = b.DeleteMessage(message.Chat.ID, res.Result.ID) + go waitAndDelete(&b.API, res.Result, 10*time.Second) + // time.Sleep(time.Second * 10) + // _, err = b.DeleteMessage(message.Chat.ID, res.Result.ID) if err != nil { log.Printf("Can't delete welcome message: %s", err) } @@ -122,16 +127,16 @@ func checkCaptcha(b *bot, update *tb.Update) error { b.DeleteMessage(message.Chat.ID, user.CaptchaMessage) b.DeleteMessage(message.Chat.ID, user.JoinedMessage) b.BanChatMember(message.Chat.ID, sender.ID, nil) - _ = d.RemoveUser(ctx, user) + _ = store.DeleteByID(ctx, user.Id) } } return nil } -func botAdded(b *bot, update *tb.Update) error { +func botAdded(b *bot, update *echotron.Update) error { m := update.Message chat := db.Chat{ - Id: m.Chat.ID, + ChatId: m.Chat.ID, Title: m.Chat.Title, TopicId: 0, } @@ -145,22 +150,23 @@ func botAdded(b *bot, update *tb.Update) error { return nil } -func setTopic(b *bot, update *tb.Update) error { +func setTopic(b *bot, update *echotron.Update) error { m := update.Message - d := db.GetDatabase() ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - chat, err := d.GetChat(ctx, m.Chat.ID) + store := tongo.NewStore[db.Chat](Client) + chat, err := store.GetOne(ctx, tongo.E("chat_id", m.Chat.ID)) if err != nil { return err } - upd := bson.D{{Key: "$set", Value: bson.D{{Key: "topic_id", Value: m.ThreadID}}}} + chat.TopicId = int64(m.ThreadID) + // upd := bson.D{{Key: "$set", Value: bson.D{{Key: "topic_id", Value: m.ThreadID}}}} b.CaptchaTopic = int64(m.ThreadID) - err = d.UpdateChat(ctx, chat, upd) + err = store.ReplaceItem(ctx, *chat, false) if err != nil { return err } b.DeleteMessage(m.Chat.ID, m.ID) - b.SendMessage("Данный топик выбран в качестве проверочного для пользователей", m.Chat.ID, &tb.MessageOptions{MessageThreadID: m.ThreadID}) + b.SendMessage("Данный топик выбран в качестве проверочного для пользователей", m.Chat.ID, &echotron.MessageOptions{MessageThreadID: m.ThreadID}) return nil } diff --git a/kicker/kicker.go b/kicker/kicker.go index 10d5452..915d074 100644 --- a/kicker/kicker.go +++ b/kicker/kicker.go @@ -7,17 +7,20 @@ import ( "strings" "time" - tb "github.com/NicoNex/echotron/v3" + "git.nefrace.ru/nefrace/tongo" + "github.com/NicoNex/echotron/v3" ) +var Client *tongo.Database + type bot struct { chatID int64 CaptchaTopic int64 - Me *tb.User - tb.API + Me *echotron.User + echotron.API } -func (b *bot) Update(update *tb.Update) { +func (b *bot) Update(update *echotron.Update) { if update.Message != nil { if len(update.Message.NewChatMembers) != 0 { for _, user := range update.Message.NewChatMembers { @@ -45,15 +48,15 @@ func (b *bot) Update(update *tb.Update) { // Базовая структура для бота type Kicker struct { Token string - Dispatcher *tb.Dispatcher + Dispatcher *echotron.Dispatcher } -func (b *Kicker) NewBot(chatID int64) tb.Bot { +func (b *Kicker) NewBot(chatID int64) echotron.Bot { d := db.GetDatabase() ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() chat := db.Chat{ - Id: chatID, + ChatId: chatID, Title: "", TopicId: 0, } @@ -68,7 +71,7 @@ func (b *Kicker) NewBot(chatID int64) tb.Bot { chatID, CaptchaTopic, nil, - tb.NewAPI(b.Token), + echotron.NewAPI(b.Token), } me, err := result.GetMe() if err != nil { @@ -81,7 +84,7 @@ func (b *Kicker) NewBot(chatID int64) tb.Bot { // Initialize bot with token func (b *Kicker) Init() error { - dsp := tb.NewDispatcher(b.Token, b.NewBot) + dsp := echotron.NewDispatcher(b.Token, b.NewBot) b.Dispatcher = dsp return nil } @@ -90,14 +93,14 @@ func (b *Kicker) Start() error { return b.Dispatcher.Poll() } -func EscapeText(parseMode tb.ParseMode, text string) string { +func EscapeText(parseMode echotron.ParseMode, text string) string { var replacer *strings.Replacer - if parseMode == tb.HTML { + if parseMode == echotron.HTML { replacer = strings.NewReplacer("<", "<", ">", ">", "&", "&") - } else if parseMode == tb.Markdown { + } else if parseMode == echotron.Markdown { replacer = strings.NewReplacer("_", "\\_", "*", "\\*", "`", "\\`", "[", "\\[") - } else if parseMode == tb.MarkdownV2 { + } else if parseMode == echotron.MarkdownV2 { replacer = strings.NewReplacer( "_", "\\_", "*", "\\*", "[", "\\[", "]", "\\]", "(", "\\(", ")", "\\)", "~", "\\~", "`", "\\`", ">", "\\>", @@ -110,3 +113,8 @@ func EscapeText(parseMode tb.ParseMode, text string) string { return replacer.Replace(text) } + +func waitAndDelete(b *echotron.API, message *echotron.Message, t time.Duration) { + time.Sleep(t) + b.DeleteMessage(message.Chat.ID, message.ID) +} diff --git a/kicker/tasks.go b/kicker/tasks.go index 305d6a2..f84dab1 100644 --- a/kicker/tasks.go +++ b/kicker/tasks.go @@ -2,37 +2,32 @@ package kicker import ( "context" + "fmt" "kickerbot/db" "log" "time" - tb "github.com/NicoNex/echotron/v3" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" + "git.nefrace.ru/nefrace/tongo" + "github.com/NicoNex/echotron/v3" ) type TaskBot struct { Token string - tb.API + echotron.API } -func TaskKickOldUsers(b *tb.API) { - d := db.GetDatabase() -// log.Print("STARTING KICKING TASK") +func TaskKickOldUsers(b *echotron.API) { ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() - now := time.Now().Unix() - old := now - 120 - filter := bson.D{ - primitive.E{Key: "date_joined", Value: bson.D{bson.E{Key: "$lt", Value: old}}}, - } - users, err := d.GetUsers(ctx, filter) + now := time.Now() + old := now.Add(-10 * time.Minute) + store := tongo.NewStore[db.User](Client) + users, err := store.GetMany(ctx, tongo.E("date_joined", tongo.D(tongo.E("$lt", old)))) if err != nil { log.Printf("Error in deleting task: %v", err) } for _, user := range users { - - _, err := b.BanChatMember(user.ChatId, user.Id, &tb.BanOptions{RevokeMessages: true}) + _, err := b.BanChatMember(user.ChatId, user.UserId, &echotron.BanOptions{RevokeMessages: true}) if err != nil { log.Println("User was not banned: ", err) continue @@ -40,6 +35,30 @@ func TaskKickOldUsers(b *tb.API) { log.Printf("User %s was banned", user.Id) b.DeleteMessage(user.ChatId, user.CaptchaMessage) b.DeleteMessage(user.ChatId, user.JoinedMessage) - d.RemoveUser(ctx, user) + store.DeleteByID(ctx, user.Id) + } +} + +func TaskNotifyUsers(b *echotron.API) { + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + store := tongo.NewStore[db.User](Client) + chatStore := tongo.NewStore[db.Chat](Client) + users, _ := store.GetMany(ctx) + for _, user := range users { + if time.Since(user.LastNotification) > 2*time.Minute { + user.LastNotification = time.Now() + text := fmt.Sprintf("*[%s](tg://user?id=%d)*, напоминаю, что тебе необходимо пройти капчу\\!", EscapeText(echotron.MarkdownV2, user.FirstName), user.Id) + store.ReplaceItem(ctx, *user, false) + chat, err := chatStore.GetOne(ctx, tongo.E("chat_id", user.ChatId)) + if err != nil { + log.Printf("Can't get chat from user: %s", err) + } + res, err := b.SendMessage(text, user.ChatId, &echotron.MessageOptions{MessageThreadID: int(chat.TopicId), ParseMode: echotron.MarkdownV2}) + if err != nil { + log.Printf("Can't send notification to user: %s", err) + } + go waitAndDelete(b, res.Result, 2*time.Minute) + } } } diff --git a/main.go b/main.go index 6e01275..fb56ec0 100644 --- a/main.go +++ b/main.go @@ -2,17 +2,19 @@ package main import ( "kickerbot/captchagen" - "kickerbot/db" "kickerbot/kicker" "log" "os" "time" + "git.nefrace.ru/nefrace/tongo" "github.com/NicoNex/echotron/v3" "github.com/go-co-op/gocron" "github.com/joho/godotenv" ) +var client *tongo.Database + func main() { err := godotenv.Load() captchagen.Init() @@ -23,10 +25,12 @@ func main() { if !exists { log.Fatal("no token specified") } - _, dberr := db.Init(os.Getenv("MONGO_URI")) - if dberr != nil { + client, err = tongo.NewConnection(os.Getenv("MONGO_URI"), "godotkicker") + // _, dberr := db.Init(os.Getenv("MONGO_URI")) + if err != nil { log.Fatal(err) } + kicker.Client = client Bot := kicker.Kicker{Token: token} Bot.Init() -- 2.40.1 From 765be0673bbb4364afa2f486e993a5327fc975c4 Mon Sep 17 00:00:00 2001 From: nefrace Date: Tue, 14 Feb 2023 00:56:18 +0300 Subject: [PATCH 02/18] added notify task --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index fb56ec0..8378b84 100644 --- a/main.go +++ b/main.go @@ -37,6 +37,7 @@ func main() { scheduler := gocron.NewScheduler(time.UTC) tasker := echotron.NewAPI(token) scheduler.Every(30).Seconds().Do(func() { kicker.TaskKickOldUsers(&tasker) }) + scheduler.Every(30).Seconds().Do(func() { kicker.TaskNotifyUsers(&tasker) }) scheduler.StartAsync() Bot.Start() } -- 2.40.1 From 7fba6ddb93c580fc603e9910866da28b28c8ec0d Mon Sep 17 00:00:00 2001 From: nefrace Date: Tue, 14 Feb 2023 01:15:00 +0300 Subject: [PATCH 03/18] Fixed NewBot routine --- kicker/kicker.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kicker/kicker.go b/kicker/kicker.go index 915d074..a2c2906 100644 --- a/kicker/kicker.go +++ b/kicker/kicker.go @@ -52,20 +52,20 @@ type Kicker struct { } func (b *Kicker) NewBot(chatID int64) echotron.Bot { - d := db.GetDatabase() + store := tongo.NewStore[db.Chat](Client) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() chat := db.Chat{ + Item: tongo.NewID(), ChatId: chatID, Title: "", TopicId: 0, } - if !d.ChatExists(ctx, chat) { - if err := d.NewChat(ctx, chat); err != nil { + if _, err := store.GetOne(ctx, tongo.E("chat_id", chatID)); err != nil { + if _, err := store.InsertOne(ctx, &chat); err != nil { return &bot{} } } - chat, _ = d.GetChat(ctx, chatID) CaptchaTopic := chat.TopicId result := &bot{ chatID, -- 2.40.1 From 7ac170ce04e9e354059bd0392b88570f549cfdbc Mon Sep 17 00:00:00 2001 From: nefrace Date: Tue, 14 Feb 2023 01:20:21 +0300 Subject: [PATCH 04/18] Fixes in notifyTask --- kicker/tasks.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kicker/tasks.go b/kicker/tasks.go index f84dab1..687bbd3 100644 --- a/kicker/tasks.go +++ b/kicker/tasks.go @@ -51,10 +51,14 @@ func TaskNotifyUsers(b *echotron.API) { text := fmt.Sprintf("*[%s](tg://user?id=%d)*, напоминаю, что тебе необходимо пройти капчу\\!", EscapeText(echotron.MarkdownV2, user.FirstName), user.Id) store.ReplaceItem(ctx, *user, false) chat, err := chatStore.GetOne(ctx, tongo.E("chat_id", user.ChatId)) + topic := 0 if err != nil { log.Printf("Can't get chat from user: %s", err) + return + } else { + topic = int(chat.TopicId) } - res, err := b.SendMessage(text, user.ChatId, &echotron.MessageOptions{MessageThreadID: int(chat.TopicId), ParseMode: echotron.MarkdownV2}) + res, err := b.SendMessage(text, user.ChatId, &echotron.MessageOptions{MessageThreadID: topic, ParseMode: echotron.MarkdownV2}) if err != nil { log.Printf("Can't send notification to user: %s", err) } -- 2.40.1 From 8f661d68a1d9bd4f8c9daab77d0aedbde6843a0a Mon Sep 17 00:00:00 2001 From: nefrace Date: Tue, 14 Feb 2023 01:21:44 +0300 Subject: [PATCH 05/18] Fixed field chat_id --- db/structs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/structs.go b/db/structs.go index baa6308..e426f6d 100644 --- a/db/structs.go +++ b/db/structs.go @@ -8,7 +8,7 @@ import ( type Chat struct { tongo.Item `bson:",inline"` - ChatId int64 + ChatId int64 `bson:"chat_id"` Title string TopicId int64 `bson:"topic_id"` } -- 2.40.1 From 23d4e9893e10466f279a875828993cba7ec56cb9 Mon Sep 17 00:00:00 2001 From: nefrace Date: Tue, 14 Feb 2023 10:49:39 +0300 Subject: [PATCH 06/18] Fixed getting chat from checkCaptcha --- kicker/handlers.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kicker/handlers.go b/kicker/handlers.go index 8de4654..663de8a 100644 --- a/kicker/handlers.go +++ b/kicker/handlers.go @@ -77,12 +77,13 @@ func checkCaptcha(b *bot, update *echotron.Update) error { message := update.Message sender := message.From store := tongo.NewStore[db.User](Client) - d := db.GetDatabase() + chatStore := tongo.NewStore[db.Chat](Client) + // d := db.GetDatabase() ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() if user, err := store.GetOne(ctx, tongo.E("user_id", sender.ID), tongo.E("chat_id", message.Chat.ID)); err == nil { //d.GetUser(ctx, db.User{UserId: sender.ID, ChatId: message.Chat.ID}); err == nil { if message.Chat.IsForum { - chat, err := d.GetChat(ctx, message.Chat.ID) + chat, err := chatStore.GetOne(ctx, tongo.E("chat_id", message.Chat.ID)) if err != nil { return err } -- 2.40.1 From 75454a3233b96b5aa2f081ce1435e5634829510f Mon Sep 17 00:00:00 2001 From: nefrace Date: Tue, 14 Feb 2023 11:07:45 +0300 Subject: [PATCH 07/18] Fixed botAdded --- kicker/handlers.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/kicker/handlers.go b/kicker/handlers.go index 663de8a..bce4ff1 100644 --- a/kicker/handlers.go +++ b/kicker/handlers.go @@ -91,7 +91,7 @@ func checkCaptcha(b *bot, update *echotron.Update) error { b.DeleteMessage(message.Chat.ID, message.ID) text := fmt.Sprintf("*[%s](tg://user?id=%d)*, сначала пройди капчу\\!", user.FirstName, user.UserId) res, _ := b.SendMessage(text, message.Chat.ID, &echotron.MessageOptions{ParseMode: echotron.MarkdownV2, MessageThreadID: message.ThreadID}) - go waitAndDelete(&b.API, res.Result, 30*time.Second) + go waitAndDelete(&b.API, res.Result, 10*time.Second) return nil } } @@ -136,15 +136,20 @@ func checkCaptcha(b *bot, update *echotron.Update) error { func botAdded(b *bot, update *echotron.Update) error { m := update.Message - chat := db.Chat{ - ChatId: m.Chat.ID, - Title: m.Chat.Title, - TopicId: 0, - } + store := tongo.NewStore[db.Chat](Client) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - d := db.GetDatabase() - err := d.NewChat(ctx, chat) + chat, err := store.GetOne(ctx, tongo.E("chat_id", m.Chat.ID)) + if err != nil { + chat = &db.Chat{ + Item: tongo.NewID(), + ChatId: m.Chat.ID, + Title: m.Chat.Title, + TopicId: 0, + } + } + + _, err = store.InsertOne(ctx, chat) if err != nil { log.Print(err) } -- 2.40.1 From 1c4a0adb61647523afe0684efdac5afe32e61107 Mon Sep 17 00:00:00 2001 From: nefrace Date: Tue, 14 Feb 2023 11:16:17 +0300 Subject: [PATCH 08/18] Fixed NewBot --- kicker/kicker.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/kicker/kicker.go b/kicker/kicker.go index a2c2906..385930e 100644 --- a/kicker/kicker.go +++ b/kicker/kicker.go @@ -55,14 +55,16 @@ func (b *Kicker) NewBot(chatID int64) echotron.Bot { store := tongo.NewStore[db.Chat](Client) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - chat := db.Chat{ - Item: tongo.NewID(), - ChatId: chatID, - Title: "", - TopicId: 0, - } - if _, err := store.GetOne(ctx, tongo.E("chat_id", chatID)); err != nil { - if _, err := store.InsertOne(ctx, &chat); err != nil { + + chat, err := store.GetOne(ctx, tongo.E("chat_id", chatID)) + if err != nil { + chat = &db.Chat{ + Item: tongo.NewID(), + ChatId: chatID, + Title: "", + TopicId: 0, + } + if _, err := store.InsertOne(ctx, chat); err != nil { return &bot{} } } -- 2.40.1 From bb0862ba8b3fec6f48d7027478893bcb2244b90a Mon Sep 17 00:00:00 2001 From: nefrace Date: Tue, 14 Feb 2023 11:17:01 +0300 Subject: [PATCH 09/18] fix 2 --- kicker/kicker.go | 1 + 1 file changed, 1 insertion(+) diff --git a/kicker/kicker.go b/kicker/kicker.go index 385930e..2cacb06 100644 --- a/kicker/kicker.go +++ b/kicker/kicker.go @@ -75,6 +75,7 @@ func (b *Kicker) NewBot(chatID int64) echotron.Bot { nil, echotron.NewAPI(b.Token), } + log.Println("New bot created with CaptchaTopic", result.CaptchaTopic) me, err := result.GetMe() if err != nil { log.Println(err) -- 2.40.1 From e1c7b560495a039caf395eecaa19e2f975ee14c2 Mon Sep 17 00:00:00 2001 From: nefrace Date: Tue, 14 Feb 2023 11:20:43 +0300 Subject: [PATCH 10/18] Replaced User.Id with User.UserId in mentions --- kicker/handlers.go | 4 ++-- kicker/tasks.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kicker/handlers.go b/kicker/handlers.go index bce4ff1..529b451 100644 --- a/kicker/handlers.go +++ b/kicker/handlers.go @@ -42,7 +42,7 @@ func userJoined(b *bot, update *echotron.Update) error { ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() log.Print(user) - msg := fmt.Sprintf("Приветствую тебя, *[%s](tg://user?id=%d)*\\!\nДля подтверждения, что ты человек, выбери логотип движка, которому посвящен данный чат, и отправь его номер сюда\\.\n*_Я дам тебе десять минут на это\\._*", EscapeText(echotron.MarkdownV2, user.FirstName), user.Id) + msg := fmt.Sprintf("Приветствую тебя, *[%s](tg://user?id=%d)*\\!\nДля подтверждения, что ты человек, выбери логотип движка, которому посвящен данный чат, и отправь его номер сюда\\.\n*_Я дам тебе десять минут на это\\._*", EscapeText(echotron.MarkdownV2, user.FirstName), user.UserId) options := echotron.PhotoOptions{ Caption: msg, ParseMode: echotron.MarkdownV2, @@ -104,7 +104,7 @@ func checkCaptcha(b *bot, update *echotron.Update) error { solved = true b.DeleteMessage(message.Chat.ID, message.ID) b.DeleteMessage(message.Chat.ID, user.CaptchaMessage) - msg := fmt.Sprintf("*[%s](tg://user?id=%d)* только что успешно прошёл капчу\\!", EscapeText(echotron.MarkdownV2, user.FirstName), user.Id) + msg := fmt.Sprintf("*[%s](tg://user?id=%d)* только что успешно прошёл капчу\\!", EscapeText(echotron.MarkdownV2, user.FirstName), user.UserId) options := echotron.MessageOptions{ ParseMode: echotron.MarkdownV2, } diff --git a/kicker/tasks.go b/kicker/tasks.go index 687bbd3..535adc6 100644 --- a/kicker/tasks.go +++ b/kicker/tasks.go @@ -32,7 +32,7 @@ func TaskKickOldUsers(b *echotron.API) { log.Println("User was not banned: ", err) continue } - log.Printf("User %s was banned", user.Id) + log.Printf("User %s was banned", user.FirstName) b.DeleteMessage(user.ChatId, user.CaptchaMessage) b.DeleteMessage(user.ChatId, user.JoinedMessage) store.DeleteByID(ctx, user.Id) @@ -48,7 +48,7 @@ func TaskNotifyUsers(b *echotron.API) { for _, user := range users { if time.Since(user.LastNotification) > 2*time.Minute { user.LastNotification = time.Now() - text := fmt.Sprintf("*[%s](tg://user?id=%d)*, напоминаю, что тебе необходимо пройти капчу\\!", EscapeText(echotron.MarkdownV2, user.FirstName), user.Id) + text := fmt.Sprintf("*[%s](tg://user?id=%d)*, напоминаю, что тебе необходимо пройти капчу\\!", EscapeText(echotron.MarkdownV2, user.FirstName), user.UserId) store.ReplaceItem(ctx, *user, false) chat, err := chatStore.GetOne(ctx, tongo.E("chat_id", user.ChatId)) topic := 0 -- 2.40.1 From de4200c1505b08e08a36c23daf763853c9ce02b2 Mon Sep 17 00:00:00 2001 From: nefrace Date: Tue, 14 Feb 2023 11:28:46 +0300 Subject: [PATCH 11/18] Fixed Notification time --- kicker/handlers.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/kicker/handlers.go b/kicker/handlers.go index 529b451..a702fb2 100644 --- a/kicker/handlers.go +++ b/kicker/handlers.go @@ -27,16 +27,17 @@ func userJoined(b *bot, update *echotron.Update) error { message := update.Message store := tongo.NewStore[db.User](Client) user := db.User{ - Item: tongo.NewID(), - UserId: message.From.ID, - Username: message.From.Username, - FirstName: message.From.FirstName, - LastName: message.From.LastName, - IsBanned: false, - ChatId: message.Chat.ID, - JoinedMessage: message.ID, - CorrectAnswer: int8(captcha.CorrectAnswer), - DateJoined: time.Now(), + Item: tongo.NewID(), + UserId: message.From.ID, + Username: message.From.Username, + FirstName: message.From.FirstName, + LastName: message.From.LastName, + IsBanned: false, + ChatId: message.Chat.ID, + JoinedMessage: message.ID, + CorrectAnswer: int8(captcha.CorrectAnswer), + DateJoined: time.Now(), + LastNotification: time.Now(), } // user.CorrectAnswer = int8(captcha.CorrectAnswer) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) -- 2.40.1 From 09cf1dcea87ccae19de7f86a1070a27e43d43bca Mon Sep 17 00:00:00 2001 From: nefrace Date: Wed, 15 Feb 2023 00:02:37 +0300 Subject: [PATCH 12/18] removed comma --- kicker/tasks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kicker/tasks.go b/kicker/tasks.go index 535adc6..52dcf80 100644 --- a/kicker/tasks.go +++ b/kicker/tasks.go @@ -48,7 +48,7 @@ func TaskNotifyUsers(b *echotron.API) { for _, user := range users { if time.Since(user.LastNotification) > 2*time.Minute { user.LastNotification = time.Now() - text := fmt.Sprintf("*[%s](tg://user?id=%d)*, напоминаю, что тебе необходимо пройти капчу\\!", EscapeText(echotron.MarkdownV2, user.FirstName), user.UserId) + text := fmt.Sprintf("*[%s](tg://user?id=%d)* напоминаю, что тебе необходимо пройти капчу\\!", EscapeText(echotron.MarkdownV2, user.FirstName), user.UserId) store.ReplaceItem(ctx, *user, false) chat, err := chatStore.GetOne(ctx, tongo.E("chat_id", user.ChatId)) topic := 0 -- 2.40.1 From c2b2d7c7b7856cc9600a068bcdab6390e5bc9a2f Mon Sep 17 00:00:00 2001 From: nefrace Date: Wed, 15 Feb 2023 00:04:35 +0300 Subject: [PATCH 13/18] returned comma --- kicker/tasks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kicker/tasks.go b/kicker/tasks.go index 52dcf80..535adc6 100644 --- a/kicker/tasks.go +++ b/kicker/tasks.go @@ -48,7 +48,7 @@ func TaskNotifyUsers(b *echotron.API) { for _, user := range users { if time.Since(user.LastNotification) > 2*time.Minute { user.LastNotification = time.Now() - text := fmt.Sprintf("*[%s](tg://user?id=%d)* напоминаю, что тебе необходимо пройти капчу\\!", EscapeText(echotron.MarkdownV2, user.FirstName), user.UserId) + text := fmt.Sprintf("*[%s](tg://user?id=%d)*, напоминаю, что тебе необходимо пройти капчу\\!", EscapeText(echotron.MarkdownV2, user.FirstName), user.UserId) store.ReplaceItem(ctx, *user, false) chat, err := chatStore.GetOne(ctx, tongo.E("chat_id", user.ChatId)) topic := 0 -- 2.40.1 From ebb8d3ca93fa37e2d7d85db3389658f9ec2d1d6f Mon Sep 17 00:00:00 2001 From: nefrace Date: Wed, 6 Sep 2023 22:26:53 +0300 Subject: [PATCH 14/18] Modified Compose --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 120b496..97d96fc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,7 +15,7 @@ services: env_file: - mongo.env ports: - - 127.0.0.1:28002:27017 + - ${HOST}:28003:27017 volumes: - mongodata:/data/db - mongoconfig:/data/configdb @@ -24,7 +24,7 @@ services: image: mongo-express restart: always ports: - - 127.0.0.1:8088:8081 + - ${HOST}:8090:8081 env_file: - mongo.env -- 2.40.1 From e1319a951d42265e1412f95e8acb20c7c2adca46 Mon Sep 17 00:00:00 2001 From: Nefrace Date: Thu, 7 Sep 2023 01:10:30 +0300 Subject: [PATCH 15/18] Update, new mentions, fixed captcha icons Y-pos --- captchagen/captchagen.go | 4 +- db/structs.go | 4 +- go.mod | 28 ++++++------ go.sum | 93 +++++++++++++++++++++------------------- kicker/handlers.go | 13 +++--- kicker/kicker.go | 30 ++++++++++++- kicker/tasks.go | 6 +-- 7 files changed, 108 insertions(+), 70 deletions(-) diff --git a/captchagen/captchagen.go b/captchagen/captchagen.go index c6d0a87..e5293d3 100644 --- a/captchagen/captchagen.go +++ b/captchagen/captchagen.go @@ -10,7 +10,6 @@ import ( "log" "math/rand" "strings" - "time" "github.com/fogleman/gg" ) @@ -55,13 +54,12 @@ func initImage() *gg.Context { // а правильный вариант возвращается вместе с итоговой картинкой func GenCaptcha() Captcha { dc := initImage() - rand.Seed(time.Now().UnixNano()) rand.Shuffle(len(Logos), func(i, j int) { Logos[i], Logos[j] = Logos[j], Logos[i] }) // Перемешиваем логотипы rand.Shuffle(len(XPositions), func(i, j int) { XPositions[i], XPositions[j] = XPositions[j], XPositions[i] }) // И позиции correct_answer := 0 for i, logo := range Logos { x := XPositions[i] - y := rand.Intn(ImageHeight - logo.Image.Bounds().Dy() - 30) + y := rand.Intn(ImageHeight - logo.Image.Bounds().Dy() - 70) dc.DrawImage(logo.Image, x, y) if logo.IsCorrect { correct_answer = i + 1 diff --git a/db/structs.go b/db/structs.go index e426f6d..b10b2a9 100644 --- a/db/structs.go +++ b/db/structs.go @@ -10,7 +10,8 @@ type Chat struct { tongo.Item `bson:",inline"` ChatId int64 `bson:"chat_id"` Title string - TopicId int64 `bson:"topic_id"` + TopicId int64 `bson:"topic_id"` + Greet string `bson:"greet"` } func (Chat) Coll() string { return "chats" } @@ -25,6 +26,7 @@ type User struct { CorrectAnswer int8 `bson:"correct_answer"` CaptchaMessage int `bson:"captcha_message"` IsBanned bool `bson:"is_banned"` + IsJoined bool `bson:"is_joined"` DateJoined time.Time `bson:"date_joined"` JoinedMessage int `bson:"joined_message"` LastNotification time.Time `bson:"last_notification"` diff --git a/go.mod b/go.mod index 20a9c4c..87908c0 100644 --- a/go.mod +++ b/go.mod @@ -3,27 +3,31 @@ module kickerbot go 1.19 require ( - github.com/NicoNex/echotron/v3 v3.21.0 + github.com/NicoNex/echotron/v3 v3.26.1 github.com/fogleman/gg v1.3.0 - github.com/go-co-op/gocron v1.18.0 - github.com/joho/godotenv v1.4.0 - go.mongodb.org/mongo-driver v1.11.1 + github.com/go-co-op/gocron v1.33.1 + github.com/joho/godotenv v1.5.1 + go.mongodb.org/mongo-driver v1.12.1 ) require ( - git.nefrace.ru/nefrace/tongo v0.0.0-20230124201743-e58da1b7d030 + github.com/google/uuid v1.3.1 // indirect + go.uber.org/atomic v1.11.0 // indirect +) + +require ( + git.nefrace.ru/nefrace/tongo v0.0.0-20230604223535-44cc124fb18a github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/klauspost/compress v1.15.13 // indirect - github.com/montanaflynn/stats v0.6.6 // indirect - github.com/pkg/errors v0.9.1 // indirect + github.com/klauspost/compress v1.16.7 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect - golang.org/x/crypto v0.4.0 // indirect - golang.org/x/image v0.2.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/text v0.5.0 // indirect + golang.org/x/crypto v0.13.0 // indirect + golang.org/x/image v0.12.0 // indirect + golang.org/x/sync v0.3.0 // indirect + golang.org/x/text v0.13.0 // indirect ) diff --git a/go.sum b/go.sum index a73ddf2..86dccdf 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,15 @@ -git.nefrace.ru/nefrace/tongo v0.0.0-20230124201743-e58da1b7d030 h1:s/T9bu8B/JQihx7HVj0Z7MG+veTAV97vEvNGfak+Wxo= -git.nefrace.ru/nefrace/tongo v0.0.0-20230124201743-e58da1b7d030/go.mod h1:I6AwXVmI+xC2kZ4TriUXK2Jchni1MZfiQQ4IWQBwC88= -github.com/NicoNex/echotron/v3 v3.21.0 h1:6YDSYA/AGlPxWoUdOIRrBvUZ0RhRa2W4taS4eSrbdXw= -github.com/NicoNex/echotron/v3 v3.21.0/go.mod h1:LpP5IyHw0y+DZUZMBgXEDAF9O8feXrQu7w7nlJzzoZI= +git.nefrace.ru/nefrace/tongo v0.0.0-20230604223535-44cc124fb18a h1:rzWY7QiyuOMxTl6oMqkh2xi6m4KmNO2edZi8idmB57I= +git.nefrace.ru/nefrace/tongo v0.0.0-20230604223535-44cc124fb18a/go.mod h1:QfvcElrkpZQAXeDzEEVh9fbViVFYS/ZOsn8Zvu6cTcg= +github.com/NicoNex/echotron/v3 v3.26.1 h1:2I+jwvrMsbot+Di39Ro3k3XSiPJTtTh+fFOOiG4RzZI= +github.com/NicoNex/echotron/v3 v3.26.1/go.mod h1:LpP5IyHw0y+DZUZMBgXEDAF9O8feXrQu7w7nlJzzoZI= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/go-co-op/gocron v1.18.0 h1:SxTyJ5xnSN4byCq7b10LmmszFdxQlSQJod8s3gbnXxA= -github.com/go-co-op/gocron v1.18.0/go.mod h1:sD/a0Aadtw5CpflUJ/lpP9Vfdk979Wl1Sg33HPHg0FY= +github.com/go-co-op/gocron v1.33.1 h1:wjX+Dg6Ae29a/f9BSQjY1Rl+jflTpW9aDyMqseCj78c= +github.com/go-co-op/gocron v1.33.1/go.mod h1:NLi+bkm4rRSy1F8U7iacZOz0xPseMoIOnvabGoSe/no= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -16,73 +17,73 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= -github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.15.13 h1:NFn1Wr8cfnenSJSA46lLq4wHCcBzKTSjnBIexDMMOV0= -github.com/klauspost/compress v1.15.13/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/montanaflynn/stats v0.6.6 h1:Duep6KMIDpY4Yo11iFsvyqJDyfzLF9+sndUKT+v64GQ= -github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE= -go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= -go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8= -go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= +go.mongodb.org/mongo-driver v1.12.1 h1:nLkghSU8fQNaK7oUmDhQFsnrtcoNy7Z6LVFKsEecqgE= +go.mongodb.org/mongo-driver v1.12.1/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8= -golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= -golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk= -golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c= -golang.org/x/image v0.2.0 h1:/DcQ0w3VHKCC5p0/P2B0JpAZ9Z++V2KOo2fyU89CXBQ= -golang.org/x/image v0.2.0/go.mod h1:la7oBXb9w3YFjBqaAwtynVioc1ZvOnNteUNrifGNmAI= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ= +golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -90,25 +91,29 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/kicker/handlers.go b/kicker/handlers.go index a702fb2..ef16289 100644 --- a/kicker/handlers.go +++ b/kicker/handlers.go @@ -22,7 +22,7 @@ func userJoined(b *bot, update *echotron.Update) error { bytes, err := captcha.ToBytes() if err != nil { log.Printf("Error creating captcha bytes: %v", bytes) - b.SendMessage("Не могу создать капчу, @nefrace, проверь логи.", update.Message.From.ID, &echotron.MessageOptions{MessageThreadID: update.Message.ThreadID}) + b.SendMessage("Не могу создать капчу, @nefrace, проверь логи.", update.Message.From.ID, &echotron.MessageOptions{MessageThreadID: int64(update.Message.ThreadID)}) } message := update.Message store := tongo.NewStore[db.User](Client) @@ -33,6 +33,7 @@ func userJoined(b *bot, update *echotron.Update) error { FirstName: message.From.FirstName, LastName: message.From.LastName, IsBanned: false, + IsJoined: false, ChatId: message.Chat.ID, JoinedMessage: message.ID, CorrectAnswer: int8(captcha.CorrectAnswer), @@ -90,8 +91,8 @@ func checkCaptcha(b *bot, update *echotron.Update) error { } if message.ThreadID != int(chat.TopicId) { b.DeleteMessage(message.Chat.ID, message.ID) - text := fmt.Sprintf("*[%s](tg://user?id=%d)*, сначала пройди капчу\\!", user.FirstName, user.UserId) - res, _ := b.SendMessage(text, message.Chat.ID, &echotron.MessageOptions{ParseMode: echotron.MarkdownV2, MessageThreadID: message.ThreadID}) + text := fmt.Sprintf("*%s*, сначала пройди капчу\\!", UserMention(sender)) + res, _ := b.SendMessage(text, message.Chat.ID, &echotron.MessageOptions{ParseMode: echotron.MarkdownV2, MessageThreadID: int64(message.ThreadID)}) go waitAndDelete(&b.API, res.Result, 10*time.Second) return nil } @@ -105,12 +106,12 @@ func checkCaptcha(b *bot, update *echotron.Update) error { solved = true b.DeleteMessage(message.Chat.ID, message.ID) b.DeleteMessage(message.Chat.ID, user.CaptchaMessage) - msg := fmt.Sprintf("*[%s](tg://user?id=%d)* только что успешно прошёл капчу\\!", EscapeText(echotron.MarkdownV2, user.FirstName), user.UserId) + msg := fmt.Sprintf("Капча успешно пройдена пользователем *%s*", UserMention(sender)) options := echotron.MessageOptions{ ParseMode: echotron.MarkdownV2, } if message.Chat.IsForum { - options.MessageThreadID = int(b.CaptchaTopic) + options.MessageThreadID = b.CaptchaTopic } res, err := b.SendMessage(msg, message.Chat.ID, &options) if err != nil { @@ -174,6 +175,6 @@ func setTopic(b *bot, update *echotron.Update) error { return err } b.DeleteMessage(m.Chat.ID, m.ID) - b.SendMessage("Данный топик выбран в качестве проверочного для пользователей", m.Chat.ID, &echotron.MessageOptions{MessageThreadID: m.ThreadID}) + b.SendMessage("Данный топик выбран в качестве проверочного для пользователей", m.Chat.ID, &echotron.MessageOptions{MessageThreadID: int64(m.ThreadID)}) return nil } diff --git a/kicker/kicker.go b/kicker/kicker.go index 2cacb06..476f6ec 100644 --- a/kicker/kicker.go +++ b/kicker/kicker.go @@ -2,8 +2,10 @@ package kicker import ( "context" + "fmt" "kickerbot/db" "log" + "regexp" "strings" "time" @@ -119,5 +121,31 @@ func EscapeText(parseMode echotron.ParseMode, text string) string { func waitAndDelete(b *echotron.API, message *echotron.Message, t time.Duration) { time.Sleep(t) - b.DeleteMessage(message.Chat.ID, message.ID) + if _, err := b.DeleteMessage(message.Chat.ID, message.ID); err != nil { + log.Printf("Can't delay-delete message: %v", err) + } +} + +func MentionUser(user *echotron.User) string { + return fmt.Sprintf("[%s](tg://user?id=%d)", EscapeText(echotron.MarkdownV2, user.FirstName), user.ID) +} + +var chars = []string{"_", "\\*", "\\[", "\\]", "\\(", "\\)", "~", "`", ">", "#", "\\+", "\\-", "=", "|", "{", "}", "\\.", "!"} +var r = strings.Join(chars, "") +var reg = regexp.MustCompile("[" + r + "]+") + +func EscapeMd2(s string) string { + return reg.ReplaceAllString(s, "\\$0") +} + +func Mention(name string, id int64) string { + return fmt.Sprintf("[%s](tg://user?id=%d)", EscapeMd2(name), id) +} + +func UserMention(u *echotron.User) string { + return Mention(u.FirstName, u.ID) +} + +func UserMentionDB(u *db.User) string { + return Mention(u.FirstName, u.UserId) } diff --git a/kicker/tasks.go b/kicker/tasks.go index 535adc6..2e14f39 100644 --- a/kicker/tasks.go +++ b/kicker/tasks.go @@ -48,15 +48,15 @@ func TaskNotifyUsers(b *echotron.API) { for _, user := range users { if time.Since(user.LastNotification) > 2*time.Minute { user.LastNotification = time.Now() - text := fmt.Sprintf("*[%s](tg://user?id=%d)*, напоминаю, что тебе необходимо пройти капчу\\!", EscapeText(echotron.MarkdownV2, user.FirstName), user.UserId) + text := fmt.Sprintf("*%s*, напоминаю, что тебе необходимо пройти капчу\\!", UserMentionDB(user)) store.ReplaceItem(ctx, *user, false) chat, err := chatStore.GetOne(ctx, tongo.E("chat_id", user.ChatId)) - topic := 0 + var topic int64 = 0 if err != nil { log.Printf("Can't get chat from user: %s", err) return } else { - topic = int(chat.TopicId) + topic = chat.TopicId } res, err := b.SendMessage(text, user.ChatId, &echotron.MessageOptions{MessageThreadID: topic, ParseMode: echotron.MarkdownV2}) if err != nil { -- 2.40.1 From 635f27f5ed5d981018b4ea027af6bca8435fe9bf Mon Sep 17 00:00:00 2001 From: Nefrace Date: Sat, 9 Sep 2023 01:45:47 +0300 Subject: [PATCH 16/18] Not deleting users --- captchagen/captchagen.go | 4 ++-- db/structs.go | 1 + kicker/handlers.go | 16 +++++++++------- kicker/tasks.go | 8 +++----- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/captchagen/captchagen.go b/captchagen/captchagen.go index e5293d3..f313755 100644 --- a/captchagen/captchagen.go +++ b/captchagen/captchagen.go @@ -6,9 +6,9 @@ import ( "image" "image/color" "image/png" - "io/ioutil" "log" "math/rand" + "os" "strings" "github.com/fogleman/gg" @@ -104,7 +104,7 @@ func (captcha *Captcha) ToBytes() (*[]byte, error) { // Логотипы читаются из папки /assets рядом с исполняемым файлом. // Принимается формат .png, логотип, представляющий правильный ответ называется godot.png func Init() error { - files, err := ioutil.ReadDir("./assets") + files, err := os.ReadDir("./assets") if err != nil { return err } diff --git a/db/structs.go b/db/structs.go index b10b2a9..67e8b5c 100644 --- a/db/structs.go +++ b/db/structs.go @@ -30,6 +30,7 @@ type User struct { DateJoined time.Time `bson:"date_joined"` JoinedMessage int `bson:"joined_message"` LastNotification time.Time `bson:"last_notification"` + Warnings int `bson:"warnings"` } func (User) Coll() string { return "users" } diff --git a/kicker/handlers.go b/kicker/handlers.go index ef16289..982c893 100644 --- a/kicker/handlers.go +++ b/kicker/handlers.go @@ -15,10 +15,10 @@ import ( func userJoined(b *bot, update *echotron.Update) error { captcha := captchagen.GenCaptcha() - _, err := b.DeleteMessage(update.Message.Chat.ID, update.Message.ID) - if err != nil { - log.Printf("Can't delete message: %v", err) - } + // _, err := b.DeleteMessage(update.Message.Chat.ID, update.Message.ID) + // if err != nil { + // log.Printf("Can't delete message: %v", err) + // } bytes, err := captcha.ToBytes() if err != nil { log.Printf("Error creating captcha bytes: %v", bytes) @@ -67,7 +67,7 @@ func userLeft(b *bot, update *echotron.Update) error { store := tongo.NewStore[db.User](Client) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() - if user, err := store.GetOne(ctx, tongo.E("user_id", sender.ID), tongo.E("chat_id", message.Chat.ID)); err == nil { //d.GetUser(ctx, db.User{UserId: sender.ID, ChatId: message.Chat.ID}); err == nil { + if user, err := store.GetOne(ctx, tongo.E("user_id", sender.ID), tongo.E("chat_id", message.Chat.ID), tongo.E("is_joined", false), tongo.E("is_banned", false)); err == nil { //d.GetUser(ctx, db.User{UserId: sender.ID, ChatId: message.Chat.ID}); err == nil { store.DeleteByID(ctx, user.Id) b.DeleteMessage(message.Chat.ID, message.ID) b.DeleteMessage(message.Chat.ID, user.CaptchaMessage) @@ -102,7 +102,8 @@ func checkCaptcha(b *bot, update *echotron.Update) error { solved := false if num, err := strconv.Atoi(guess); err == nil { if num == int(user.CorrectAnswer) { - _ = store.DeleteByID(ctx, user.Id) + user.IsJoined = true + store.ReplaceItem(ctx, *user, true) solved = true b.DeleteMessage(message.Chat.ID, message.ID) b.DeleteMessage(message.Chat.ID, user.CaptchaMessage) @@ -130,7 +131,8 @@ func checkCaptcha(b *bot, update *echotron.Update) error { b.DeleteMessage(message.Chat.ID, user.CaptchaMessage) b.DeleteMessage(message.Chat.ID, user.JoinedMessage) b.BanChatMember(message.Chat.ID, sender.ID, nil) - _ = store.DeleteByID(ctx, user.Id) + user.IsBanned = true + store.ReplaceItem(ctx, *user, true) } } return nil diff --git a/kicker/tasks.go b/kicker/tasks.go index 2e14f39..b0d7408 100644 --- a/kicker/tasks.go +++ b/kicker/tasks.go @@ -22,7 +22,7 @@ func TaskKickOldUsers(b *echotron.API) { now := time.Now() old := now.Add(-10 * time.Minute) store := tongo.NewStore[db.User](Client) - users, err := store.GetMany(ctx, tongo.E("date_joined", tongo.D(tongo.E("$lt", old)))) + users, err := store.GetMany(ctx, tongo.E("date_joined", tongo.D(tongo.E("$lt", old))), tongo.E("is_joined", false), tongo.E("is_banned", false)) if err != nil { log.Printf("Error in deleting task: %v", err) } @@ -33,9 +33,7 @@ func TaskKickOldUsers(b *echotron.API) { continue } log.Printf("User %s was banned", user.FirstName) - b.DeleteMessage(user.ChatId, user.CaptchaMessage) - b.DeleteMessage(user.ChatId, user.JoinedMessage) - store.DeleteByID(ctx, user.Id) + user.IsBanned = true } } @@ -44,7 +42,7 @@ func TaskNotifyUsers(b *echotron.API) { defer cancel() store := tongo.NewStore[db.User](Client) chatStore := tongo.NewStore[db.Chat](Client) - users, _ := store.GetMany(ctx) + users, _ := store.GetMany(ctx, tongo.E("is_joined", false), tongo.E("is_banned", false)) for _, user := range users { if time.Since(user.LastNotification) > 2*time.Minute { user.LastNotification = time.Now() -- 2.40.1 From 9533b43b987566511c13d8bce6ee02279ec68357 Mon Sep 17 00:00:00 2001 From: Nefrace Date: Sun, 10 Sep 2023 02:48:59 +0300 Subject: [PATCH 17/18] Greetings, storage of joined users --- captchagen/captchagen.go | 4 +- db/structs.go | 1 - kicker/handlers.go | 97 +++++++++++++++++++++++++++------------- kicker/kicker.go | 17 ++++++- kicker/tasks.go | 8 ++-- 5 files changed, 89 insertions(+), 38 deletions(-) diff --git a/captchagen/captchagen.go b/captchagen/captchagen.go index f313755..051484b 100644 --- a/captchagen/captchagen.go +++ b/captchagen/captchagen.go @@ -52,7 +52,7 @@ func initImage() *gg.Context { // На пустое изображение наносятся логотипы из списка, предварительно перемешанного. // К изображениям также добавляются порядковые номера (начиная с 1 вместо 0), // а правильный вариант возвращается вместе с итоговой картинкой -func GenCaptcha() Captcha { +func GenCaptcha() *Captcha { dc := initImage() rand.Shuffle(len(Logos), func(i, j int) { Logos[i], Logos[j] = Logos[j], Logos[i] }) // Перемешиваем логотипы rand.Shuffle(len(XPositions), func(i, j int) { XPositions[i], XPositions[j] = XPositions[j], XPositions[i] }) // И позиции @@ -76,7 +76,7 @@ func GenCaptcha() Captcha { CorrectAnswer: correct_answer, } - return captcha + return &captcha } func (captcha *Captcha) ToReader() *bytes.Reader { diff --git a/db/structs.go b/db/structs.go index 67e8b5c..1e6f9c4 100644 --- a/db/structs.go +++ b/db/structs.go @@ -25,7 +25,6 @@ type User struct { LastName string `bson:"last_name"` CorrectAnswer int8 `bson:"correct_answer"` CaptchaMessage int `bson:"captcha_message"` - IsBanned bool `bson:"is_banned"` IsJoined bool `bson:"is_joined"` DateJoined time.Time `bson:"date_joined"` JoinedMessage int `bson:"joined_message"` diff --git a/kicker/handlers.go b/kicker/handlers.go index 982c893..1c5b009 100644 --- a/kicker/handlers.go +++ b/kicker/handlers.go @@ -2,6 +2,7 @@ package kicker import ( "context" + "errors" "fmt" "kickerbot/captchagen" "kickerbot/db" @@ -11,10 +12,40 @@ import ( "git.nefrace.ru/nefrace/tongo" "github.com/NicoNex/echotron/v3" + "go.mongodb.org/mongo-driver/mongo" ) func userJoined(b *bot, update *echotron.Update) error { - captcha := captchagen.GenCaptcha() + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + store := tongo.NewStore[db.User](Client) + usr := update.Message.NewChatMembers[0] + message := update.Message + user, err := store.GetOne(ctx, tongo.E("chat_id", update.ChatID()), tongo.E("user_id", usr.ID)) + var captcha *captchagen.Captcha + if err != nil { + if errors.Is(err, mongo.ErrNoDocuments) { + captcha = captchagen.GenCaptcha() + user = &db.User{ + Item: tongo.NewID(), + UserId: usr.ID, + Username: usr.Username, + FirstName: usr.FirstName, + LastName: usr.LastName, + IsJoined: false, + ChatId: message.Chat.ID, + JoinedMessage: message.ID, + CorrectAnswer: int8(captcha.CorrectAnswer), + DateJoined: time.Now(), + LastNotification: time.Now(), + } + } else { + log.Printf("Can't find user: %v", err) + } + } + if captcha == nil { + return nil + } // _, err := b.DeleteMessage(update.Message.Chat.ID, update.Message.ID) // if err != nil { // log.Printf("Can't delete message: %v", err) @@ -22,27 +53,10 @@ func userJoined(b *bot, update *echotron.Update) error { bytes, err := captcha.ToBytes() if err != nil { log.Printf("Error creating captcha bytes: %v", bytes) - b.SendMessage("Не могу создать капчу, @nefrace, проверь логи.", update.Message.From.ID, &echotron.MessageOptions{MessageThreadID: int64(update.Message.ThreadID)}) - } - message := update.Message - store := tongo.NewStore[db.User](Client) - user := db.User{ - Item: tongo.NewID(), - UserId: message.From.ID, - Username: message.From.Username, - FirstName: message.From.FirstName, - LastName: message.From.LastName, - IsBanned: false, - IsJoined: false, - ChatId: message.Chat.ID, - JoinedMessage: message.ID, - CorrectAnswer: int8(captcha.CorrectAnswer), - DateJoined: time.Now(), - LastNotification: time.Now(), + b.SendMessage("Не могу создать капчу, @nefrace, проверь логи.", update.Message.Chat.ID, &echotron.MessageOptions{MessageThreadID: int64(update.Message.ThreadID)}) } + // user.CorrectAnswer = int8(captcha.CorrectAnswer) - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) - defer cancel() log.Print(user) msg := fmt.Sprintf("Приветствую тебя, *[%s](tg://user?id=%d)*\\!\nДля подтверждения, что ты человек, выбери логотип движка, которому посвящен данный чат, и отправь его номер сюда\\.\n*_Я дам тебе десять минут на это\\._*", EscapeText(echotron.MarkdownV2, user.FirstName), user.UserId) options := echotron.PhotoOptions{ @@ -57,7 +71,7 @@ func userJoined(b *bot, update *echotron.Update) error { return err } user.CaptchaMessage = result.Result.ID - store.InsertOne(ctx, &user) + store.InsertOne(ctx, user) return nil } @@ -67,7 +81,7 @@ func userLeft(b *bot, update *echotron.Update) error { store := tongo.NewStore[db.User](Client) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() - if user, err := store.GetOne(ctx, tongo.E("user_id", sender.ID), tongo.E("chat_id", message.Chat.ID), tongo.E("is_joined", false), tongo.E("is_banned", false)); err == nil { //d.GetUser(ctx, db.User{UserId: sender.ID, ChatId: message.Chat.ID}); err == nil { + if user, err := store.GetOne(ctx, tongo.E("user_id", sender.ID), tongo.E("chat_id", message.Chat.ID), tongo.E("is_joined", false)); err == nil { //d.GetUser(ctx, db.User{UserId: sender.ID, ChatId: message.Chat.ID}); err == nil { store.DeleteByID(ctx, user.Id) b.DeleteMessage(message.Chat.ID, message.ID) b.DeleteMessage(message.Chat.ID, user.CaptchaMessage) @@ -75,6 +89,19 @@ func userLeft(b *bot, update *echotron.Update) error { return nil } +func userBanned(b *bot, update *echotron.Update) error { + m := update.ChatMember + c := m.Chat + u := m.NewChatMember.User + store := tongo.NewStore[db.User](Client) + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + if user, err := store.GetOne(ctx, tongo.E("user_id", u.ID), tongo.E("chat_id", c.ID)); err == nil { //d.GetUser(ctx, db.User{UserId: sender.ID, ChatId: message.Chat.ID}); err == nil { + store.DeleteByID(ctx, user.Id) + } + return nil +} + func checkCaptcha(b *bot, update *echotron.Update) error { message := update.Message sender := message.From @@ -83,12 +110,12 @@ func checkCaptcha(b *bot, update *echotron.Update) error { // d := db.GetDatabase() ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() - if user, err := store.GetOne(ctx, tongo.E("user_id", sender.ID), tongo.E("chat_id", message.Chat.ID)); err == nil { //d.GetUser(ctx, db.User{UserId: sender.ID, ChatId: message.Chat.ID}); err == nil { + if user, err := store.GetOne(ctx, tongo.E("user_id", sender.ID), tongo.E("chat_id", message.Chat.ID), tongo.E("is_joined", false)); err == nil { //d.GetUser(ctx, db.User{UserId: sender.ID, ChatId: message.Chat.ID}); err == nil { + chat, err := chatStore.GetOne(ctx, tongo.E("chat_id", message.Chat.ID)) + if err != nil { + return err + } if message.Chat.IsForum { - chat, err := chatStore.GetOne(ctx, tongo.E("chat_id", message.Chat.ID)) - if err != nil { - return err - } if message.ThreadID != int(chat.TopicId) { b.DeleteMessage(message.Chat.ID, message.ID) text := fmt.Sprintf("*%s*, сначала пройди капчу\\!", UserMention(sender)) @@ -108,6 +135,11 @@ func checkCaptcha(b *bot, update *echotron.Update) error { b.DeleteMessage(message.Chat.ID, message.ID) b.DeleteMessage(message.Chat.ID, user.CaptchaMessage) msg := fmt.Sprintf("Капча успешно пройдена пользователем *%s*", UserMention(sender)) + timeout := 10 * time.Second + if chat.Greet != "" { + msg = fmt.Sprintf(chat.Greet, UserMention(sender)) + timeout = 2 * time.Minute + } options := echotron.MessageOptions{ ParseMode: echotron.MarkdownV2, } @@ -118,7 +150,7 @@ func checkCaptcha(b *bot, update *echotron.Update) error { if err != nil { log.Printf("Can't send welcome message: %s", err) } - go waitAndDelete(&b.API, res.Result, 10*time.Second) + go waitAndDelete(&b.API, res.Result, timeout*time.Second) // time.Sleep(time.Second * 10) // _, err = b.DeleteMessage(message.Chat.ID, res.Result.ID) if err != nil { @@ -131,8 +163,7 @@ func checkCaptcha(b *bot, update *echotron.Update) error { b.DeleteMessage(message.Chat.ID, user.CaptchaMessage) b.DeleteMessage(message.Chat.ID, user.JoinedMessage) b.BanChatMember(message.Chat.ID, sender.ID, nil) - user.IsBanned = true - store.ReplaceItem(ctx, *user, true) + store.DeleteByID(ctx, user.Id) } } return nil @@ -162,6 +193,12 @@ func botAdded(b *bot, update *echotron.Update) error { func setTopic(b *bot, update *echotron.Update) error { m := update.Message + if res, err := b.GetChatMember(m.Chat.ID, m.From.ID); err == nil { + m := res.Result + if !(m.Status == "administrator" || m.Status == "creator") { + return nil + } + } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() store := tongo.NewStore[db.Chat](Client) diff --git a/kicker/kicker.go b/kicker/kicker.go index 476f6ec..78379ff 100644 --- a/kicker/kicker.go +++ b/kicker/kicker.go @@ -45,6 +45,13 @@ func (b *bot) Update(update *echotron.Update) { checkCaptcha(b, update) } } + if update.ChatMember != nil { + m := update.ChatMember.NewChatMember + if m.Status == "kicked" { + userBanned(b, update) + return + } + } } // Базовая структура для бота @@ -95,7 +102,15 @@ func (b *Kicker) Init() error { } func (b *Kicker) Start() error { - return b.Dispatcher.Poll() + return b.Dispatcher.PollOptions(true, echotron.UpdateOptions{ + Timeout: 120, + AllowedUpdates: []echotron.UpdateType{ + echotron.MessageUpdate, + echotron.ChatMemberUpdate, + echotron.MyChatMemberUpdate, + echotron.CallbackQueryUpdate, + }, + }) } func EscapeText(parseMode echotron.ParseMode, text string) string { diff --git a/kicker/tasks.go b/kicker/tasks.go index b0d7408..18619e1 100644 --- a/kicker/tasks.go +++ b/kicker/tasks.go @@ -22,7 +22,7 @@ func TaskKickOldUsers(b *echotron.API) { now := time.Now() old := now.Add(-10 * time.Minute) store := tongo.NewStore[db.User](Client) - users, err := store.GetMany(ctx, tongo.E("date_joined", tongo.D(tongo.E("$lt", old))), tongo.E("is_joined", false), tongo.E("is_banned", false)) + users, err := store.GetMany(ctx, tongo.E("date_joined", tongo.D(tongo.E("$lt", old))), tongo.E("is_joined", false)) if err != nil { log.Printf("Error in deleting task: %v", err) } @@ -33,7 +33,7 @@ func TaskKickOldUsers(b *echotron.API) { continue } log.Printf("User %s was banned", user.FirstName) - user.IsBanned = true + store.DeleteByID(ctx, user.Id) } } @@ -42,7 +42,7 @@ func TaskNotifyUsers(b *echotron.API) { defer cancel() store := tongo.NewStore[db.User](Client) chatStore := tongo.NewStore[db.Chat](Client) - users, _ := store.GetMany(ctx, tongo.E("is_joined", false), tongo.E("is_banned", false)) + users, _ := store.GetMany(ctx, tongo.E("is_joined", false)) for _, user := range users { if time.Since(user.LastNotification) > 2*time.Minute { user.LastNotification = time.Now() @@ -56,7 +56,7 @@ func TaskNotifyUsers(b *echotron.API) { } else { topic = chat.TopicId } - res, err := b.SendMessage(text, user.ChatId, &echotron.MessageOptions{MessageThreadID: topic, ParseMode: echotron.MarkdownV2}) + res, err := b.SendMessage(text, user.ChatId, &echotron.MessageOptions{MessageThreadID: topic, ParseMode: echotron.MarkdownV2, ReplyToMessageID: user.CaptchaMessage}) if err != nil { log.Printf("Can't send notification to user: %s", err) } -- 2.40.1 From b631b4423a8830086724a42e465d56077e5fd501 Mon Sep 17 00:00:00 2001 From: Nefrace Date: Sun, 10 Sep 2023 13:08:53 +0300 Subject: [PATCH 18/18] Fixed captcha greeting --- kicker/handlers.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/kicker/handlers.go b/kicker/handlers.go index 1c5b009..8bcabff 100644 --- a/kicker/handlers.go +++ b/kicker/handlers.go @@ -55,10 +55,7 @@ func userJoined(b *bot, update *echotron.Update) error { log.Printf("Error creating captcha bytes: %v", bytes) b.SendMessage("Не могу создать капчу, @nefrace, проверь логи.", update.Message.Chat.ID, &echotron.MessageOptions{MessageThreadID: int64(update.Message.ThreadID)}) } - - // user.CorrectAnswer = int8(captcha.CorrectAnswer) - log.Print(user) - msg := fmt.Sprintf("Приветствую тебя, *[%s](tg://user?id=%d)*\\!\nДля подтверждения, что ты человек, выбери логотип движка, которому посвящен данный чат, и отправь его номер сюда\\.\n*_Я дам тебе десять минут на это\\._*", EscapeText(echotron.MarkdownV2, user.FirstName), user.UserId) + msg := fmt.Sprintf("Приветствую тебя, *%s*\\!\nДля подтверждения, что ты человек, выбери логотип движка, которому посвящен данный чат, и отправь его номер сюда\\.\n*_Я дам тебе десять минут на это\\._*", UserMention(usr)) options := echotron.PhotoOptions{ Caption: msg, ParseMode: echotron.MarkdownV2, @@ -110,7 +107,12 @@ func checkCaptcha(b *bot, update *echotron.Update) error { // d := db.GetDatabase() ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() - if user, err := store.GetOne(ctx, tongo.E("user_id", sender.ID), tongo.E("chat_id", message.Chat.ID), tongo.E("is_joined", false)); err == nil { //d.GetUser(ctx, db.User{UserId: sender.ID, ChatId: message.Chat.ID}); err == nil { + + if user, err := store.GetOne(ctx, + tongo.E("user_id", sender.ID), + tongo.E("chat_id", message.Chat.ID), + tongo.E("is_joined", false), + ); err == nil { //d.GetUser(ctx, db.User{UserId: sender.ID, ChatId: message.Chat.ID}); err == nil { chat, err := chatStore.GetOne(ctx, tongo.E("chat_id", message.Chat.ID)) if err != nil { return err -- 2.40.1