mirror of
https://github.com/SantaSpeen/RoyaltyIT-tg-bot.git
synced 2026-02-16 02:20:42 +00:00
new_chat_member + ban + refactoring warns
This commit is contained in:
16
README.md
16
README.md
@@ -28,15 +28,13 @@ $ python3 main.py
|
|||||||
{
|
{
|
||||||
"bot_token": "BOT_TOKEN",
|
"bot_token": "BOT_TOKEN",
|
||||||
"remote_chat": -1000,
|
"remote_chat": -1000,
|
||||||
|
"new_member_message": "Привет, @%(username)-s!\nДобро пожаловать в наше IT - сообщество.\nЧтобы люди могли в будущем найти тебя, напиши вступительное сообщение о себе с хештегом %(<)-s#знакомство%(</)-s. Приятного времяпрепровождения!",
|
||||||
"static_message": {
|
"static_message": {
|
||||||
"start": {
|
"help": "Я бот, ничем не могу помочь, сорян..."
|
||||||
"allow": "private",
|
|
||||||
"msg": "Привет, я бот \"Ял\".\nДля ознакомления с возможностями - /help"
|
|
||||||
},
|
|
||||||
"help": {
|
|
||||||
"allow": "all",
|
|
||||||
"msg": "Помощь уже в пути!"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
License: MIT
|
||||||
@@ -1,14 +1,29 @@
|
|||||||
from peewee import Model, SqliteDatabase, IntegerField, DoubleField, DoesNotExist
|
from peewee import Model, SqliteDatabase, IntegerField, DoubleField, BooleanField, TextField
|
||||||
|
|
||||||
|
class BasicModel(Model):
|
||||||
|
class Meta:
|
||||||
|
database = SqliteDatabase('sqlite3.db')
|
||||||
|
|
||||||
|
|
||||||
class Users(Model):
|
class Users(BasicModel):
|
||||||
|
|
||||||
id = IntegerField(null=True)
|
id = IntegerField(null=True)
|
||||||
user_id = IntegerField()
|
user_id = IntegerField()
|
||||||
warns = IntegerField(null=True, default=0)
|
warns = IntegerField(null=True, default=0)
|
||||||
muted_until = DoubleField(null=True, default=0.0)
|
muted_until = DoubleField(null=True, default=0.0)
|
||||||
banned_until = DoubleField(null=True, default=0.0)
|
banned = BooleanField(null=True, default=False)
|
||||||
|
ban_by = IntegerField(null=True)
|
||||||
|
ban_msg = TextField(null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
table_name = 'users'
|
table_name = 'users'
|
||||||
database = SqliteDatabase('sqlite3.db')
|
|
||||||
|
|
||||||
|
class Mailing(BasicModel):
|
||||||
|
|
||||||
|
id = IntegerField(null=True)
|
||||||
|
user_id = IntegerField()
|
||||||
|
enable = BooleanField(null=True, default=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
table_name = 'mailing'
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ class Config:
|
|||||||
self.remote_chat: int = None
|
self.remote_chat: int = None
|
||||||
|
|
||||||
self.messages_object: str = None
|
self.messages_object: str = None
|
||||||
|
self.new_member_message: str = None
|
||||||
|
self.start_message: str = None
|
||||||
|
self.static_message: dict = None
|
||||||
|
|
||||||
self._read_config()
|
self._read_config()
|
||||||
|
|
||||||
@@ -34,3 +37,6 @@ class Config:
|
|||||||
self.bot_token = self.raw_config.get("bot_token")
|
self.bot_token = self.raw_config.get("bot_token")
|
||||||
self.remote_chat = self.raw_config.get("remote_chat")
|
self.remote_chat = self.raw_config.get("remote_chat")
|
||||||
self.messages_object = self.raw_config.get("messages")
|
self.messages_object = self.raw_config.get("messages")
|
||||||
|
self.new_member_message = self.raw_config.get("new_member_message")
|
||||||
|
self.start_message = self.raw_config.get("start_message")
|
||||||
|
self.static_message = self.raw_config.get("static_message")
|
||||||
|
|||||||
95
src/main.py
95
src/main.py
@@ -2,7 +2,7 @@ import logging
|
|||||||
|
|
||||||
from aiogram import Bot, types
|
from aiogram import Bot, types
|
||||||
from aiogram.dispatcher import Dispatcher
|
from aiogram.dispatcher import Dispatcher
|
||||||
from aiogram.types import ParseMode
|
from aiogram.types import ParseMode, ChatType
|
||||||
from aiogram.utils import executor
|
from aiogram.utils import executor
|
||||||
|
|
||||||
from config import Config
|
from config import Config
|
||||||
@@ -16,9 +16,18 @@ dp = Dispatcher(bot)
|
|||||||
tools = Tools(config, dp)
|
tools = Tools(config, dp)
|
||||||
|
|
||||||
|
|
||||||
|
@dp.message_handler(commands=["start"], chat_type=ChatType.PRIVATE)
|
||||||
|
async def start(msg: types.Message):
|
||||||
|
log.info(f"New message from {msg.from_user.id}(@{msg.from_user.username}) in {msg.chat.id}: '{msg.text}'")
|
||||||
|
user_id = msg.from_user.id
|
||||||
|
registered = tools.register_user(user_id)
|
||||||
|
if not registered:
|
||||||
|
await msg.reply(config.start_message)
|
||||||
|
|
||||||
|
|
||||||
@dp.message_handler(commands=['admins'])
|
@dp.message_handler(commands=['admins'])
|
||||||
async def bot_admins(msg: types.Message):
|
async def bot_admins(msg: types.Message):
|
||||||
log.info(f"New message from {msg.from_user.id}({msg.from_user.username}) in {msg.chat.id}: '{msg.text}'")
|
log.info(f"New message from {msg.from_user.id}(@{msg.from_user.username}) in {msg.chat.id}: '{msg.text}'")
|
||||||
message = "Администраторы нашего сообщества:\n%(owner)-s"
|
message = "Администраторы нашего сообщества:\n%(owner)-s"
|
||||||
admins = await tools.admins
|
admins = await tools.admins
|
||||||
i = 1
|
i = 1
|
||||||
@@ -35,9 +44,9 @@ async def bot_admins(msg: types.Message):
|
|||||||
await msg.reply(message, parse_mode=ParseMode.MARKDOWN)
|
await msg.reply(message, parse_mode=ParseMode.MARKDOWN)
|
||||||
|
|
||||||
|
|
||||||
@dp.message_handler(regexp=r"\A(?:.|\/)(?:warn|пред)", is_chat_admin=True)
|
@dp.message_handler(regexp=r"\A(?:.|\/)(?:warn|пред)", is_chat_admin=True, chat_type=ChatType.SUPERGROUP)
|
||||||
async def wanrs(msg: types.Message):
|
async def wanr(msg: types.Message):
|
||||||
log.info(f"New message from {msg.from_user.id}({msg.from_user.username}) in {msg.chat.id}: '{msg.text}'")
|
log.info(f"New message from {msg.from_user.id}(@{msg.from_user.username}) in {msg.chat.id}: '{msg.text}'")
|
||||||
reply_message = msg.reply_to_message
|
reply_message = msg.reply_to_message
|
||||||
|
|
||||||
if reply_message:
|
if reply_message:
|
||||||
@@ -50,12 +59,13 @@ async def wanrs(msg: types.Message):
|
|||||||
else:
|
else:
|
||||||
message = "Сначала надо выбрать пользователя."
|
message = "Сначала надо выбрать пользователя."
|
||||||
|
|
||||||
await msg.reply(message, parse_mode=ParseMode.MARKDOWN)
|
if message:
|
||||||
|
await msg.reply(message)
|
||||||
|
|
||||||
|
|
||||||
@dp.message_handler(regexp=r"\A(?:.|\/)(?:reset|прости)", is_chat_admin=True)
|
@dp.message_handler(regexp=r"\A(?:.|\/)(?:reset|прости)", is_chat_admin=True, chat_type=ChatType.SUPERGROUP)
|
||||||
async def unwarn(msg):
|
async def unwarn(msg: types.Message):
|
||||||
log.info(f"New message from {msg.from_user.id}({msg.from_user.username}) in {msg.chat.id}: '{msg.text}'")
|
log.info(f"New message from {msg.from_user.id}(@{msg.from_user.username}) in {msg.chat.id}: '{msg.text}'")
|
||||||
reply_message = msg.reply_to_message
|
reply_message = msg.reply_to_message
|
||||||
|
|
||||||
if reply_message:
|
if reply_message:
|
||||||
@@ -63,14 +73,77 @@ async def unwarn(msg):
|
|||||||
user_id = warn_user.id
|
user_id = warn_user.id
|
||||||
user_username = warn_user.username
|
user_username = warn_user.username
|
||||||
|
|
||||||
message = await tools.reset_warn(user_id, user_username)
|
message = tools.reset_warn(user_id, user_username)
|
||||||
else:
|
else:
|
||||||
message = "Сначала надо выбрать пользователя."
|
message = "Сначала надо выбрать пользователя."
|
||||||
|
|
||||||
await msg.reply(message, parse_mode=ParseMode.MARKDOWN)
|
await msg.reply(message, parse_mode=ParseMode.MARKDOWN)
|
||||||
|
|
||||||
|
|
||||||
tools.bind_static_messages()
|
@dp.message_handler(regexp=r"\A(?:.|\/)(?:mute|тсс)", is_chat_admin=True, chat_type=ChatType.SUPERGROUP)
|
||||||
|
async def mute(msg: types.Message):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@dp.message_handler(regexp=r"\A(?:.|\/)(?:unmute|говори)", is_chat_admin=True, chat_type=ChatType.SUPERGROUP)
|
||||||
|
async def unmute(msg: types.Message):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@dp.message_handler(regexp=r"\A(?:.|\/)(?:ban|заскамить)", is_chat_admin=True, chat_type=ChatType.SUPERGROUP)
|
||||||
|
async def ban(msg: types.Message):
|
||||||
|
reply_message = msg.reply_to_message
|
||||||
|
|
||||||
|
if reply_message:
|
||||||
|
|
||||||
|
if len(msg.text.split(" ")) > 1:
|
||||||
|
message = await tools.ban_user(msg)
|
||||||
|
|
||||||
|
else:
|
||||||
|
message = "Укажи причину бана: `/ban [причина]`"
|
||||||
|
|
||||||
|
else:
|
||||||
|
message = "Сначала надо выбрать пользователя."
|
||||||
|
|
||||||
|
if message:
|
||||||
|
await msg.reply(message, parse_mode=ParseMode.MARKDOWN)
|
||||||
|
|
||||||
|
|
||||||
|
@dp.message_handler(content_types=['new_chat_members'], chat_type=ChatType.SUPERGROUP)
|
||||||
|
async def new_chat_member(msg: types.Message):
|
||||||
|
for user in msg.new_chat_members:
|
||||||
|
user_id = user['id']
|
||||||
|
log.info(f"New member: {user['id']}(@{user['username']})")
|
||||||
|
banned, ban_msg, ban_by = tools.is_banned(user_id)
|
||||||
|
if banned:
|
||||||
|
await bot.send_message(msg.chat.id,
|
||||||
|
f"@{user['username']}, вы забанены [Администратором](tg://user?id={ban_by})\n",
|
||||||
|
parse_mode=ParseMode.MARKDOWN)
|
||||||
|
await bot.kick_chat_member(msg.chat.id, user_id)
|
||||||
|
else:
|
||||||
|
message = config.new_member_message % {
|
||||||
|
"username": user['username'],
|
||||||
|
"<": "<code>", # Start codeblock
|
||||||
|
"</": "</code>" # Close codeblock
|
||||||
|
}
|
||||||
|
await bot.send_message(msg.chat.id, message, parse_mode=ParseMode.HTML)
|
||||||
|
|
||||||
|
|
||||||
|
@dp.message_handler(content_types=['text', 'photo', 'document', 'audio', 'sticker', 'animation', 'voice', 'video_note'])
|
||||||
|
async def all_messages(msg: types.Message):
|
||||||
|
text = msg.text
|
||||||
|
user_id = msg.from_user.id
|
||||||
|
log.info(f"New message from {user_id}(@{msg.from_user.username}) in {msg.chat.id}: '{text}'; "
|
||||||
|
f"Type: {msg.content_type}")
|
||||||
|
|
||||||
|
if msg.chat.type in [ChatType.SUPERGROUP, ChatType.GROUP]: # Если сообщение пришло из группы
|
||||||
|
pass
|
||||||
|
|
||||||
|
for k, v in config.static_message.items():
|
||||||
|
if k == text[1:len(k) + 1]:
|
||||||
|
await msg.reply(config.static_message[k], parse_mode=ParseMode.MARKDOWN)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
executor.start_polling(dp)
|
executor.start_polling(dp)
|
||||||
|
|||||||
28
src/sl3.sql
28
src/sl3.sql
@@ -1,11 +1,23 @@
|
|||||||
DROP TABLE IF EXISTS `users`;
|
DROP TABLE IF EXISTS `users`;
|
||||||
|
DROP TABLE IF EXISTS `mailing`;
|
||||||
|
|
||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT
|
id INTEGER PRIMARY KEY AUTOINCREMENT
|
||||||
UNIQUE,
|
UNIQUE,
|
||||||
user_id INTEGER UNIQUE
|
user_id INTEGER UNIQUE
|
||||||
NOT NULL,
|
NOT NULL,
|
||||||
warns INTEGER DEFAULT (0),
|
warns INTEGER DEFAULT (0),
|
||||||
muted_until DOUBLE DEFAULT (0.0),
|
muted_until DOUBLE DEFAULT (0.0),
|
||||||
banned_until DOUBLE DEFAULT (0.0)
|
banned BOOLEAN DEFAULT (0),
|
||||||
);
|
ban_by INTEGER,
|
||||||
|
ban_msg TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE mailing (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT
|
||||||
|
UNIQUE,
|
||||||
|
user_id INTEGER UNIQUE
|
||||||
|
NOT NULL,
|
||||||
|
enable BOOLEAN DEFAULT (1)
|
||||||
|
);
|
||||||
|
|||||||
93
src/tools.py
93
src/tools.py
@@ -2,13 +2,12 @@ import logging
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
import aiogram
|
import aiogram
|
||||||
|
from aiogram.types import ParseMode
|
||||||
from peewee import DoesNotExist
|
from peewee import DoesNotExist
|
||||||
|
|
||||||
from SqlModels import Users
|
from SqlModels import Users, Mailing
|
||||||
from config import Config
|
from config import Config
|
||||||
|
|
||||||
static_log = logging.getLogger('static messages')
|
|
||||||
|
|
||||||
|
|
||||||
class Tools:
|
class Tools:
|
||||||
|
|
||||||
@@ -18,35 +17,13 @@ class Tools:
|
|||||||
self.dispatcher = dispatcher
|
self.dispatcher = dispatcher
|
||||||
self.__admins: dict = {}
|
self.__admins: dict = {}
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
async def __message_handler(msg: aiogram.types.Message, **kwargs):
|
|
||||||
text = msg.text
|
|
||||||
static_log.info(f"New message from {msg.from_user.id}({msg.from_user.username}) in {msg.chat.id}: '{text}'")
|
|
||||||
for k, v in kwargs['__messages__'].items():
|
|
||||||
if k.startswith(text[1:len(k)]):
|
|
||||||
allow = v['allow']
|
|
||||||
send = False
|
|
||||||
if (allow == "all") or \
|
|
||||||
(allow == "private" and msg.chat.id > 0) or \
|
|
||||||
(allow == "chat" and msg.chat.id < 0):
|
|
||||||
send = True
|
|
||||||
if send:
|
|
||||||
await msg.reply(v['msg'])
|
|
||||||
break
|
|
||||||
|
|
||||||
def bind_static_messages(self):
|
|
||||||
__messages__: dict = self.config.raw_config['static_message']
|
|
||||||
__messages_keys__ = list(__messages__.keys())
|
|
||||||
l = lambda *x: self.__message_handler(*x, __messages__=__messages__)
|
|
||||||
self.dispatcher.register_message_handler(l, commands=__messages_keys__)
|
|
||||||
|
|
||||||
async def _update_admins_list(self):
|
async def _update_admins_list(self):
|
||||||
admins = await self.dispatcher.bot.get_chat_administrators(self.config.remote_chat)
|
admins = await self.dispatcher.bot.get_chat_administrators(self.config.remote_chat)
|
||||||
ids = list()
|
ids = list()
|
||||||
for admin in admins:
|
for admin in admins:
|
||||||
ids.append(admin['user']['id'])
|
ids.append(admin['user']['id'])
|
||||||
self.__admins = {
|
self.__admins = {
|
||||||
"time": time.time()+60.0,
|
"time": time.time() + 60.0,
|
||||||
"object": {"list": admins, "ids": ids}
|
"object": {"list": admins, "ids": ids}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,31 +36,46 @@ class Tools:
|
|||||||
|
|
||||||
return self.__admins['object']
|
return self.__admins['object']
|
||||||
|
|
||||||
async def add_warn(self, user_id, user_username, chat_id):
|
@staticmethod
|
||||||
|
def get_user(user_id):
|
||||||
try:
|
try:
|
||||||
user = Users.get(Users.user_id == user_id)
|
user = Users.get(Users.user_id == user_id)
|
||||||
except DoesNotExist:
|
except DoesNotExist:
|
||||||
user = Users(user_id=user_id)
|
user = Users(user_id=user_id)
|
||||||
|
return user
|
||||||
|
|
||||||
|
async def kick_chat_member(self, chat_id, user_id):
|
||||||
|
try:
|
||||||
|
await self.dispatcher.bot.kick_chat_member(chat_id, user_id)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
await self.dispatcher.bot.send_message(chat_id,
|
||||||
|
f"Ошибка при исключении [пользователя](tg://user?id={user_id}).\n"
|
||||||
|
f"Exception: `{e}`",
|
||||||
|
parse_mode=ParseMode.MARKDOWN)
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def add_warn(self, user_id, user_username, chat_id):
|
||||||
|
user = self.get_user(user_id)
|
||||||
user.warns += 1
|
user.warns += 1
|
||||||
user.save()
|
user.save()
|
||||||
if user.warns > 3:
|
if user.warns > 3:
|
||||||
try:
|
|
||||||
await self.dispatcher.bot.kick_chat_member(chat_id, user_id)
|
if await self.kick_chat_member(chat_id, user_id):
|
||||||
message = f"@{user_username} вёл себя плохо, поэтому теперь он иключён!"
|
message = f"@{user_username} вёл себя плохо, поэтому теперь он иключён!"
|
||||||
except Exception as e:
|
else:
|
||||||
message = f"Ошибка при исключении @{user_username}.\nException: `{e}`"
|
message = None
|
||||||
|
user.warns = 0
|
||||||
|
user.save()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
message = f"@{user_username}, вы получили {user.warns} из 3 предупреждений.\nВпредь ведите себя лучше!"
|
message = f"@{user_username}, вы получили {user.warns} из 3 предупреждений.\nВпредь ведите себя лучше!"
|
||||||
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def reset_warn(cls, user_id, username):
|
def reset_warn(cls, user_id, username):
|
||||||
try:
|
user = cls.get_user(user_id)
|
||||||
user = Users.get(Users.user_id == user_id)
|
|
||||||
except DoesNotExist:
|
|
||||||
user = Users(user_id=user_id)
|
|
||||||
|
|
||||||
if user.warns == 0:
|
if user.warns == 0:
|
||||||
message = f"У пользователя @{username} нет предупреждений!"
|
message = f"У пользователя @{username} нет предупреждений!"
|
||||||
else:
|
else:
|
||||||
@@ -92,3 +84,30 @@ class Tools:
|
|||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def is_banned(cls, user_id):
|
||||||
|
user = cls.get_user(user_id)
|
||||||
|
return user.banned, user.ban_msg, user.ban_by
|
||||||
|
|
||||||
|
async def ban_user(self, msg: aiogram.types.Message):
|
||||||
|
user = self.get_user(msg.reply_to_message.from_user.id)
|
||||||
|
|
||||||
|
if await self.kick_chat_member(msg.chat.id, user.user_id):
|
||||||
|
user.banned = True
|
||||||
|
user.ban_msg = " ".join(msg.text.split(" ")[1:])
|
||||||
|
user.ban_by = msg.from_user.id
|
||||||
|
user.save()
|
||||||
|
return f"@{msg.reply_to_message.from_user.username} был забанен по причие `{user.ban_msg}`."
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def register_user(cls, user_id):
|
||||||
|
registered = False
|
||||||
|
cls.get_user(user_id).save()
|
||||||
|
try:
|
||||||
|
Mailing.get(Mailing.user_id == user_id)
|
||||||
|
registered = True
|
||||||
|
except DoesNotExist:
|
||||||
|
Mailing(user_id=user_id).save()
|
||||||
|
|
||||||
|
return registered
|
||||||
|
|||||||
Reference in New Issue
Block a user