package kicker import ( "context" "fmt" "kickerbot/db" "log" "regexp" "strconv" "strings" "time" "git.nefrace.ru/nefrace/tongo" "github.com/NicoNex/echotron/v3" ) var Client *tongo.Database type bot struct { chatID int64 CaptchaTopic int64 Me *echotron.User echotron.API } func (b *bot) Update(update *echotron.Update) { if update.Message != nil { if len(update.Message.NewChatMembers) != 0 { for _, user := range update.Message.NewChatMembers { if user.ID == b.Me.ID { botAdded(b, update) } } userJoined(b, update) return } if update.Message.LeftChatMember != nil { userLeft(b, update) return } if update.Message.Text != "" || update.Message.Caption != "" { if update.Message.Text == "" { update.Message.Text = update.Message.Caption } res, err := b.GetChatMember(update.ChatID(), update.Message.From.ID) if err != nil { log.Println("Kicker 44: can't get user member: ", err) return } if res.Result.Status == "administrator" || res.Result.Status == "creator" { if update.Message.Text == "/settopic" { setTopic(b, update) return } if update.Message.Text == "/admin" { setAdminTopic(b, update, true) return } if update.Message.Text == "/unadmin" { setAdminTopic(b, update, false) return } if strings.HasPrefix(update.Message.Text, "/mute") { muteUser(b, update) return } if strings.HasPrefix(update.Message.Text, "/ban") { banUser(b, update) return } } } checkCaptcha(b, update) checkAdminTopics(b, update) } if update.ChatMember != nil { m := update.ChatMember.NewChatMember if m.Status == "kicked" { userBanned(b, update) return } } } // Базовая структура для бота type Kicker struct { Token string Dispatcher *echotron.Dispatcher } 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, 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{} } } CaptchaTopic := chat.TopicId result := &bot{ chatID, CaptchaTopic, nil, echotron.NewAPI(b.Token), } log.Println("New bot created with CaptchaTopic", result.CaptchaTopic) me, err := result.GetMe() if err != nil { log.Println(err) } result.Me = me.Result return result } // Initialize bot with token func (b *Kicker) Init() error { dsp := echotron.NewDispatcher(b.Token, b.NewBot) b.Dispatcher = dsp return nil } func (b *Kicker) Start() error { 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 { var replacer *strings.Replacer if parseMode == echotron.HTML { replacer = strings.NewReplacer("<", "<", ">", ">", "&", "&") } else if parseMode == echotron.Markdown { replacer = strings.NewReplacer("_", "\\_", "*", "\\*", "`", "\\`", "[", "\\[") } else if parseMode == echotron.MarkdownV2 { replacer = strings.NewReplacer( "_", "\\_", "*", "\\*", "[", "\\[", "]", "\\]", "(", "\\(", ")", "\\)", "~", "\\~", "`", "\\`", ">", "\\>", "#", "\\#", "+", "\\+", "-", "\\-", "=", "\\=", "|", "\\|", "{", "\\{", "}", "\\}", ".", "\\.", "!", "\\!", ) } else { return "" } return replacer.Replace(text) } func waitAndDelete(b *echotron.API, message *echotron.Message, t time.Duration) { time.Sleep(t) 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 { text := fmt.Sprintf("[%s](tg://user?id=%d)", EscapeMd2(name), id) log.Println(text) return text } func UserMention(u *echotron.User) string { return Mention(u.FirstName, u.ID) } func UserMentionDB(u *db.User) string { return Mention(u.FirstName, u.UserId) } func MentionWithData(u *echotron.User) string { userid := strconv.FormatInt(u.ID, 10) username := u.Username userstr := fmt.Sprintf("userid: `%v`", userid) if username != "" { userstr += fmt.Sprintf(", username: @%s", u.Username) } return fmt.Sprintf("*%s* \\(%s\\)", UserMention(u), userstr) } func MentionWithDataDB(u *db.User) string { userid := strconv.FormatInt(u.UserId, 10) username := u.Username userstr := fmt.Sprintf("userid: `%v`", userid) if username != "" { userstr += fmt.Sprintf(", username: @%s", u.Username) } return fmt.Sprintf("*%s* \\(%s\\)", UserMentionDB(u), userstr) } func pluralRu(n int, single string, double string, five string) string { switch n { case 10, 11, 12, 13, 14, 15, 16, 17, 18, 19: return five default: s := []rune(strconv.Itoa(n)) switch s[len(s)-1] { case '1': return single case '2', '3', '4': return double default: return five } } } func transformChatID(id int64) int64 { return -id - 1000000000000 }