Ban method. Needs testing.
This commit is contained in:
		@ -4,6 +4,7 @@ import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/go-telegram/bot"
 | 
			
		||||
@ -37,7 +38,7 @@ func FetchMemberFromChat(ctx context.Context, b *bot.Bot, chatID int64, userID i
 | 
			
		||||
	return b.GetChatMember(ctx, &bot.GetChatMemberParams{ChatID: chatID, UserID: userID})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func IsAdmin(member models.ChatMember) bool {
 | 
			
		||||
func IsMemberAdmin(member models.ChatMember) bool {
 | 
			
		||||
	return member.Administrator != nil || member.Owner != nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -59,3 +60,20 @@ func Mention(name string, id int64) string {
 | 
			
		||||
	text := fmt.Sprintf("[%s](tg://user?id=%d)", bot.EscapeMarkdown(name), id)
 | 
			
		||||
	return text
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										27
									
								
								src/db.go
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								src/db.go
									
									
									
									
									
								
							@ -38,15 +38,26 @@ name TEXT NOT NULL,
 | 
			
		||||
username TEXT DEFAULT ''
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
create table if not exists admins
 | 
			
		||||
(
 | 
			
		||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
 | 
			
		||||
user_id INTEGER NOT NULL,
 | 
			
		||||
chat_id INTEGER NOT NULL,
 | 
			
		||||
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
 | 
			
		||||
FOREIGN KEY (chat_id) REFERENCES chats (id) ON DELETE CASCADE
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
create table if not exists bans
 | 
			
		||||
(
 | 
			
		||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
 | 
			
		||||
chat_id INTEGER,
 | 
			
		||||
user_id INTEGER,
 | 
			
		||||
reason TEXT NOT NULL,
 | 
			
		||||
chat_id INTEGER NOT NULL,
 | 
			
		||||
user_id INTEGER NOT NULL,
 | 
			
		||||
text TEXT DEFAULT '',
 | 
			
		||||
reason TEXT DEFAULT '',
 | 
			
		||||
ban_date INTEGER NOT NULL,
 | 
			
		||||
unban_date INTEGER DEFAULT 0,
 | 
			
		||||
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
 | 
			
		||||
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
 | 
			
		||||
FOREIGN KEY (chat_id) REFERENCES chats (id) ON DELETE CASCADE
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
create table if not exists captchas
 | 
			
		||||
@ -62,7 +73,7 @@ FOREIGN KEY (chat_id) REFERENCES chats (id) ON DELETE CASCADE
 | 
			
		||||
)
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
type ChatSchema struct {
 | 
			
		||||
type Chat struct {
 | 
			
		||||
	Id       int64  `json:"id" db:"id"`
 | 
			
		||||
	Name     string `json:"name" db:"name"`
 | 
			
		||||
	Username string `json:"username" db:"username"`
 | 
			
		||||
@ -104,7 +115,7 @@ func InitDb() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewChat(chat ChatSchema) error {
 | 
			
		||||
func NewChat(chat Chat) error {
 | 
			
		||||
	_, err := db.NamedExec(`insert into chats (id, name, username, topic, active) values (:id, :name, :username, :topic, :active)`, chat)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
@ -128,8 +139,8 @@ func IsChatActive(id int64) bool {
 | 
			
		||||
	return active
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetChatById(id int64) (ChatSchema, error) {
 | 
			
		||||
	c := ChatSchema{}
 | 
			
		||||
func GetChatById(id int64) (Chat, error) {
 | 
			
		||||
	c := Chat{}
 | 
			
		||||
	err := db.Get(&c, `select * from chats where id = $1`, id)
 | 
			
		||||
	return c, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,7 @@ func registerChat(ctx context.Context, b *bot.Bot, update *models.Update) {
 | 
			
		||||
	log.Println("registering", msg.Chat.ID)
 | 
			
		||||
	m, err := FetchMemberFromChat(ctx, b, msg.Chat.ID, msg.From.ID)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		if !IsAdmin(*m) {
 | 
			
		||||
		if !IsMemberAdmin(*m) {
 | 
			
		||||
			log.Println("register: user is not admin")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
@ -72,7 +72,7 @@ func unregisterChat(ctx context.Context, b *bot.Bot, update *models.Update) {
 | 
			
		||||
	log.Println("unregistering", msg.Chat.ID)
 | 
			
		||||
	m, err := FetchMemberFromChat(ctx, b, msg.Chat.ID, msg.From.ID)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		if !IsAdmin(*m) {
 | 
			
		||||
		if !IsMemberAdmin(*m) {
 | 
			
		||||
			log.Println("register: user is not admin")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
@ -105,7 +105,7 @@ var NewUserTemplate = `
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
func handleNewJoined(ctx context.Context, b *bot.Bot, u *models.Update) {
 | 
			
		||||
	var chat ChatSchema
 | 
			
		||||
	var chat Chat
 | 
			
		||||
	err := db.Get(&chat, "select * from chats where id = $1 and active = 1", u.Message.Chat.ID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println("can't get chat for new joined: ", err)
 | 
			
		||||
@ -160,6 +160,89 @@ func handleNewJoined(ctx context.Context, b *bot.Bot, u *models.Update) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func banUser(ctx context.Context, b *bot.Bot, u *models.Update) {
 | 
			
		||||
	msg := u.Message
 | 
			
		||||
	if msg.ReplyToMessage == nil {
 | 
			
		||||
		newMsg, err := b.SendMessage(ctx, &bot.SendMessageParams{
 | 
			
		||||
			Text: "Хочешь себя забанить? 🙃",
 | 
			
		||||
			ReplyParameters: &models.ReplyParameters{
 | 
			
		||||
				ChatID:    msg.Chat.ID,
 | 
			
		||||
				MessageID: msg.ID,
 | 
			
		||||
			},
 | 
			
		||||
		})
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			AddMessageToDelete(MessageToDelete{MessageId: msg.ID, ChatId: msg.Chat.ID, DeleteDate: time.Now().Add(10 * time.Second).Unix()})
 | 
			
		||||
			AddMessageToDelete(MessageToDelete{MessageId: newMsg.ID, ChatId: msg.Chat.ID, DeleteDate: time.Now().Add(10 * time.Second).Unix()})
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	reply := msg.ReplyToMessage
 | 
			
		||||
	chatID := msg.Chat.ID
 | 
			
		||||
	sender := msg.From
 | 
			
		||||
	banned := reply.From
 | 
			
		||||
	log.Println("banning user", banned.FirstName, "from", msg.Chat.ID)
 | 
			
		||||
	m, err := FetchMemberFromChat(ctx, b, chatID, sender.ID)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		if !IsMemberAdmin(*m) {
 | 
			
		||||
			log.Println("register: user is not admin")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		text := reply.Text
 | 
			
		||||
		if text == "" {
 | 
			
		||||
			text = reply.Caption
 | 
			
		||||
		}
 | 
			
		||||
		reason := ""
 | 
			
		||||
		days := 0
 | 
			
		||||
		args := strings.SplitN(msg.Text, " ", 2)
 | 
			
		||||
		if len(args) > 1 {
 | 
			
		||||
			num, err := strconv.Atoi(args[1])
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				reason = args[1]
 | 
			
		||||
			} else {
 | 
			
		||||
				if days > 0 {
 | 
			
		||||
					days = num
 | 
			
		||||
				}
 | 
			
		||||
				if len(args) > 2 {
 | 
			
		||||
					reason = args[2]
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		unbanDate := time.Now().Add(time.Duration(days) * time.Hour * 24).Unix()
 | 
			
		||||
		b.DeleteMessage(ctx, &bot.DeleteMessageParams{
 | 
			
		||||
			ChatID:    msg.Chat.ID,
 | 
			
		||||
			MessageID: msg.ID,
 | 
			
		||||
		})
 | 
			
		||||
		_, err := b.BanChatMember(ctx, &bot.BanChatMemberParams{
 | 
			
		||||
			ChatID:    chatID,
 | 
			
		||||
			UserID:    banned.ID,
 | 
			
		||||
			UntilDate: int(unbanDate),
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Println("can't ban user: ", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		newText := "Пользователь *%s* был забанен %s\\."
 | 
			
		||||
		daysText := "навсегда"
 | 
			
		||||
		if days > 0 {
 | 
			
		||||
			daysText = fmt.Sprintf("на %d %s", days, pluralRu(days, "день", "дня", "дней"))
 | 
			
		||||
		}
 | 
			
		||||
		sent, err := b.SendMessage(ctx, &bot.SendMessageParams{
 | 
			
		||||
			ChatID:          msg.Chat.ID,
 | 
			
		||||
			Text:            fmt.Sprintf(newText, Mention(banned.FirstName, banned.ID), daysText),
 | 
			
		||||
			MessageThreadID: msg.MessageThreadID,
 | 
			
		||||
		})
 | 
			
		||||
		db.Exec(
 | 
			
		||||
			"insert into bans (chat_id, user_id, text, reason, ban_date, unban_date) values ($1, $2, $3, $4, $5, $6)",
 | 
			
		||||
			chatID, banned.ID, text, reason, time.Now().Unix(), unbanDate,
 | 
			
		||||
		)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			err := DeleteAfterSeconds(msg.Chat.ID, sent.ID, 60)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("register: failed to add to delete", err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		log.Println("register: error", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user