2021-12-03 14:30:10 +03:00
package kicker
2021-12-03 12:19:55 +03:00
import (
2021-12-06 11:46:11 +03:00
"context"
2023-09-10 02:48:59 +03:00
"errors"
2021-12-07 00:36:29 +03:00
"fmt"
2022-01-28 01:00:40 +03:00
"kickerbot/captchagen"
2021-12-06 11:46:11 +03:00
"kickerbot/db"
"log"
2022-02-02 00:37:58 +03:00
"strconv"
2023-09-13 22:33:53 +03:00
"strings"
2021-12-06 11:46:11 +03:00
"time"
2023-02-14 00:50:21 +03:00
"git.nefrace.ru/nefrace/tongo"
"github.com/NicoNex/echotron/v3"
2023-09-10 02:48:59 +03:00
"go.mongodb.org/mongo-driver/mongo"
2021-12-03 12:19:55 +03:00
)
2023-02-14 00:50:21 +03:00
func userJoined ( b * bot , update * echotron . Update ) error {
2023-09-10 02:48:59 +03:00
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
2023-09-13 23:01:58 +03:00
_ , err := b . DeleteMessage ( message . Chat . ID , message . ID )
if err != nil {
log . Printf ( "Can't delete message: %v" , err )
}
2023-09-10 02:48:59 +03:00
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
}
2022-11-09 00:45:08 +03:00
bytes , err := captcha . ToBytes ( )
if err != nil {
2022-12-12 13:23:37 +03:00
log . Printf ( "Error creating captcha bytes: %v" , bytes )
2023-09-10 02:48:59 +03:00
b . SendMessage ( "Н е могу создать капчу, @nefrace, проверь логи." , update . Message . Chat . ID , & echotron . MessageOptions { MessageThreadID : int64 ( update . Message . ThreadID ) } )
2021-12-07 00:36:29 +03:00
}
2023-09-10 13:08:53 +03:00
msg := fmt . Sprintf ( "Приветствую тебя, *%s*\\!\nДля подтверждения, что ты человек, выбери логотип движка, которому посвящен данный чат, и отправь е г о номер сюда\\.\n*_Я дам тебе десять минут на это\\._*" , UserMention ( usr ) )
2023-02-14 00:50:21 +03:00
options := echotron . PhotoOptions {
2022-11-09 00:45:08 +03:00
Caption : msg ,
2023-02-14 00:50:21 +03:00
ParseMode : echotron . MarkdownV2 ,
2022-11-09 00:45:08 +03:00
}
if message . Chat . IsForum {
options . MessageThreadID = int ( b . CaptchaTopic )
}
2023-02-14 00:50:21 +03:00
result , err := b . SendPhoto ( echotron . NewInputFileBytes ( "logos.png" , * bytes ) , message . Chat . ID , & options )
2022-02-02 00:37:58 +03:00
if err != nil {
return err
}
2022-11-09 00:45:08 +03:00
user . CaptchaMessage = result . Result . ID
2023-09-10 02:48:59 +03:00
store . InsertOne ( ctx , user )
2021-12-07 00:36:29 +03:00
return nil
}
2023-02-14 00:50:21 +03:00
func userLeft ( b * bot , update * echotron . Update ) error {
2022-11-09 00:45:08 +03:00
message := update . Message
sender := message . From
2023-02-14 00:50:21 +03:00
store := tongo . NewStore [ db . User ] ( Client )
2022-02-04 11:37:55 +03:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 15 * time . Second )
defer cancel ( )
2023-09-10 02:48:59 +03:00
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 {
2023-02-14 00:50:21 +03:00
store . DeleteByID ( ctx , user . Id )
2022-11-09 00:45:08 +03:00
b . DeleteMessage ( message . Chat . ID , message . ID )
b . DeleteMessage ( message . Chat . ID , user . CaptchaMessage )
2022-02-04 11:37:55 +03:00
}
return nil
}
2023-09-13 22:33:53 +03:00
var muted = echotron . ChatPermissions {
CanSendMessages : false ,
CanSendAudios : false ,
CanSendDocuments : false ,
CanSendPhotos : false ,
CanSendVideos : false ,
CanSendVideoNotes : false ,
CanSendVoiceNotes : false ,
CanSendPolls : false ,
CanSendOtherMessages : false ,
}
func muteUser ( b * bot , update * echotron . Update ) error {
message := update . Message
if message . ReplyToMessage == nil {
return nil
}
reply := message . ReplyToMessage
items := strings . SplitN ( message . Text , " " , 3 )
days , msg := 1 , reply . Text
var err error
if len ( items ) > 1 {
days , err = strconv . Atoi ( items [ 1 ] )
if err != nil || days < 1 {
res , _ := b . SendMessage ( "Неверно указано количество дней" , message . Chat . ID , & echotron . MessageOptions { ReplyToMessageID : message . ID } )
go waitAndDelete ( & b . API , res . Result , 10 * time . Second )
return err
}
}
if len ( items ) > 2 {
msg = fmt . Sprintf ( "%s: \"%s\"" , reply . From . FirstName , items [ 2 ] )
}
store := tongo . NewStore [ db . Mute ] ( Client )
ctx , cancel := context . WithTimeout ( context . Background ( ) , 15 * time . Second )
defer cancel ( )
until := time . Now ( ) . AddDate ( 0 , 0 , days )
_ , err = b . RestrictChatMember ( message . Chat . ID , reply . From . ID , muted , & echotron . RestrictOptions { UntilDate : int ( until . Unix ( ) ) } )
if err != nil {
b . SendMessage ( fmt . Sprintf ( "Н е могу дать молчанку юзеру: %v" , err ) , b . chatID , & echotron . MessageOptions { ReplyToMessageID : message . ID } )
return err
}
b . SendMessage (
fmt . Sprintf ( "Пользователю *%s* выдана \"молчанка\" на %d %s\\." , UserMention ( reply . From ) , days , pluralRu ( days , "день" , "дня" , "дней" ) ) ,
message . Chat . ID ,
& echotron . MessageOptions {
ParseMode : echotron . MarkdownV2 ,
MessageThreadID : int64 ( message . ThreadID ) ,
} ,
)
store . InsertOne ( ctx , & db . Mute {
Item : tongo . NewID ( ) ,
UserId : reply . From . ID ,
ChatId : message . Chat . ID ,
Message : msg ,
Date : time . Now ( ) ,
Until : until ,
MessageLink : fmt . Sprintf ( "https://t.me/c/%d/%d/%d" , transformChatID ( update . ChatID ( ) ) , message . ThreadID , message . ID ) ,
} )
return nil
}
2023-09-10 02:48:59 +03:00
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
}
2023-02-14 00:50:21 +03:00
func checkCaptcha ( b * bot , update * echotron . Update ) error {
2022-11-09 00:45:08 +03:00
message := update . Message
2022-11-09 01:23:32 +03:00
sender := message . From
2023-02-14 00:50:21 +03:00
store := tongo . NewStore [ db . User ] ( Client )
2023-02-14 10:49:39 +03:00
chatStore := tongo . NewStore [ db . Chat ] ( Client )
// d := db.GetDatabase()
2022-07-21 11:15:38 +03:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 15 * time . Second )
defer cancel ( )
2023-09-13 22:33:53 +03:00
chat , err := chatStore . GetOne ( ctx , tongo . E ( "chat_id" , message . Chat . ID ) )
if err != nil {
return err
}
2023-09-10 13:08:53 +03:00
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 {
2022-11-09 00:45:08 +03:00
if message . Chat . IsForum {
if message . ThreadID != int ( chat . TopicId ) {
b . DeleteMessage ( message . Chat . ID , message . ID )
2023-09-13 22:33:53 +03:00
text := fmt . Sprintf ( "*%s*, сначала пройди [капчу](https://t.me/c/%d/%d/%d)\\!" , UserMention ( sender ) , transformChatID ( b . chatID ) , chat . TopicId , user . CaptchaMessage )
2023-09-07 01:10:30 +03:00
res , _ := b . SendMessage ( text , message . Chat . ID , & echotron . MessageOptions { ParseMode : echotron . MarkdownV2 , MessageThreadID : int64 ( message . ThreadID ) } )
2023-02-14 11:07:45 +03:00
go waitAndDelete ( & b . API , res . Result , 10 * time . Second )
2022-11-09 00:45:08 +03:00
return nil
}
}
2022-07-21 11:15:38 +03:00
text_runes := [ ] rune ( message . Text )
guess := string ( text_runes [ 0 ] )
solved := false
if num , err := strconv . Atoi ( guess ) ; err == nil {
if num == int ( user . CorrectAnswer ) {
2023-09-09 01:45:47 +03:00
user . IsJoined = true
store . ReplaceItem ( ctx , * user , true )
2022-07-21 11:15:38 +03:00
solved = true
2022-11-09 00:45:08 +03:00
b . DeleteMessage ( message . Chat . ID , message . ID )
b . DeleteMessage ( message . Chat . ID , user . CaptchaMessage )
2023-09-07 01:10:30 +03:00
msg := fmt . Sprintf ( "Капча успешно пройдена пользователем *%s*" , UserMention ( sender ) )
2023-09-10 02:48:59 +03:00
timeout := 10 * time . Second
if chat . Greet != "" {
msg = fmt . Sprintf ( chat . Greet , UserMention ( sender ) )
timeout = 2 * time . Minute
}
2023-02-14 00:50:21 +03:00
options := echotron . MessageOptions {
ParseMode : echotron . MarkdownV2 ,
2023-01-18 22:46:25 +03:00
}
if message . Chat . IsForum {
2023-09-07 01:10:30 +03:00
options . MessageThreadID = b . CaptchaTopic
2023-01-18 22:46:25 +03:00
}
res , err := b . SendMessage ( msg , message . Chat . ID , & options )
if err != nil {
log . Printf ( "Can't send welcome message: %s" , err )
}
2023-09-10 13:31:41 +03:00
go waitAndDelete ( & b . API , res . Result , timeout )
2023-02-14 00:50:21 +03:00
// time.Sleep(time.Second * 10)
// _, err = b.DeleteMessage(message.Chat.ID, res.Result.ID)
2023-01-18 22:46:25 +03:00
if err != nil {
log . Printf ( "Can't delete welcome message: %s" , err )
}
2022-07-21 11:15:38 +03:00
}
}
if ! solved {
2022-11-09 00:45:08 +03:00
b . DeleteMessage ( message . Chat . ID , message . ID )
b . DeleteMessage ( message . Chat . ID , user . CaptchaMessage )
b . DeleteMessage ( message . Chat . ID , user . JoinedMessage )
b . BanChatMember ( message . Chat . ID , sender . ID , nil )
2023-09-10 02:48:59 +03:00
store . DeleteByID ( ctx , user . Id )
2022-07-21 11:15:38 +03:00
}
2023-09-13 22:33:53 +03:00
} else if message . Chat . IsForum && message . ThreadID == int ( chat . TopicId ) {
res , err := b . GetChatMember ( update . ChatID ( ) , sender . ID )
if err != nil {
return err
}
if res . Result . Status == "administrator" || res . Result . Status == "creator" {
return nil
}
b . DeleteMessage ( b . chatID , message . ID )
}
return nil
}
func setAdminTopic ( b * bot , update * echotron . Update , set bool ) error {
message := update . Message
chatID := update . ChatID ( )
store := tongo . NewStore [ db . AdminTopic ] ( Client )
ctx , cancel := context . WithTimeout ( context . Background ( ) , 10 * time . Second )
defer cancel ( )
topic , err := store . GetOne ( ctx , tongo . E ( "chat_id" , chatID ) , tongo . E ( "topic_id" , message . ThreadID ) )
if set {
if err != nil || topic == nil {
_ , err := store . InsertOne ( ctx , & db . AdminTopic {
Item : tongo . NewID ( ) ,
ChatId : chatID ,
TopicId : int64 ( message . ThreadID ) ,
} )
if err != nil {
log . Println ( "Can't set admintopic: " , err )
return err
}
b . SendMessage ( "Данный топик теперь только для админов." , chatID , & echotron . MessageOptions { MessageThreadID : int64 ( message . ThreadID ) } )
}
return nil
} else {
if err == nil {
if err := store . DeleteByID ( ctx , topic . Id ) ; err != nil {
log . Println ( "Can't unset admintopic: " , err )
return err
}
b . SendMessage ( "Данный топик теперь доступен всем!" , chatID , & echotron . MessageOptions { MessageThreadID : int64 ( message . ThreadID ) } )
}
}
return nil
}
func checkAdminTopics ( b * bot , update * echotron . Update ) error {
message := update . Message
chatID := update . ChatID ( )
sender := message . From
res , err := b . GetChatMember ( message . Chat . ID , sender . ID )
if err != nil {
log . Println ( "muteUser: Can't get member: " , err )
return err
}
if res . Result . Status == "administrator" || res . Result . Status == "creator" {
return nil
}
store := tongo . NewStore [ db . AdminTopic ] ( Client )
ctx , cancel := context . WithTimeout ( context . Background ( ) , 10 * time . Second )
defer cancel ( )
if _ , err := store . GetOne ( ctx , tongo . E ( "chat_id" , chatID ) , tongo . E ( "topic_id" , message . ThreadID ) ) ; err == nil {
b . DeleteMessage ( chatID , message . ID )
2022-07-21 11:15:38 +03:00
}
return nil
}
2023-02-14 00:50:21 +03:00
func botAdded ( b * bot , update * echotron . Update ) error {
2022-11-09 00:45:08 +03:00
m := update . Message
2023-02-14 11:07:45 +03:00
store := tongo . NewStore [ db . Chat ] ( Client )
2022-07-21 11:15:38 +03:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 10 * time . Second )
defer cancel ( )
2023-02-14 11:07:45 +03:00
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 )
2022-07-21 11:15:38 +03:00
if err != nil {
log . Print ( err )
}
return nil
}
2023-02-14 00:50:21 +03:00
func setTopic ( b * bot , update * echotron . Update ) error {
2022-11-09 00:45:08 +03:00
m := update . Message
ctx , cancel := context . WithTimeout ( context . Background ( ) , 5 * time . Second )
defer cancel ( )
2023-02-14 00:50:21 +03:00
store := tongo . NewStore [ db . Chat ] ( Client )
chat , err := store . GetOne ( ctx , tongo . E ( "chat_id" , m . Chat . ID ) )
2022-11-09 00:45:08 +03:00
if err != nil {
return err
}
2023-02-14 00:50:21 +03:00
chat . TopicId = int64 ( m . ThreadID )
// upd := bson.D{{Key: "$set", Value: bson.D{{Key: "topic_id", Value: m.ThreadID}}}}
2022-11-09 00:45:08 +03:00
b . CaptchaTopic = int64 ( m . ThreadID )
2023-02-14 00:50:21 +03:00
err = store . ReplaceItem ( ctx , * chat , false )
2022-11-09 00:45:08 +03:00
if err != nil {
return err
}
b . DeleteMessage ( m . Chat . ID , m . ID )
2023-09-07 01:10:30 +03:00
b . SendMessage ( "Данный топик выбран в качестве проверочного для пользователей" , m . Chat . ID , & echotron . MessageOptions { MessageThreadID : int64 ( m . ThreadID ) } )
2022-11-09 00:45:08 +03:00
return nil
2021-12-03 12:19:55 +03:00
}