Ban method. Needs testing.

This commit is contained in:
Nefrace 2024-08-06 00:04:45 +03:00
parent 0e19fb532b
commit cb030a60d1
3 changed files with 124 additions and 12 deletions

View File

@ -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
}
}
}

View File

@ -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
}

View File

@ -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)
}
}