mirror of
https://gitflic.ru/project/maks1ms/ocab.git
synced 2024-12-23 16:23:01 +03:00
Открытое бета тестирование + фиксы первого дня
This commit is contained in:
parent
370ac7d02b
commit
9d89aee578
3
.gitignore
vendored
3
.gitignore
vendored
@ -6,4 +6,5 @@ env
|
||||
venv
|
||||
__pycache__
|
||||
OCAB.db
|
||||
paths.json
|
||||
src/paths.json
|
||||
src/core/config.yaml
|
21
src/core/example_config.yaml
Normal file
21
src/core/example_config.yaml
Normal file
@ -0,0 +1,21 @@
|
||||
TELEGRAM:
|
||||
TOKEN: xxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
APPROVED_CHAT_ID: "-123456789 | -012345678"
|
||||
ADMINCHATID: -12345678
|
||||
DEFAULT_CHAT_TAG: "@alt_gnome_chat"
|
||||
CHECK_BOT: True
|
||||
|
||||
YANDEXGPT:
|
||||
TOKEN: xxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
TOKEN_FOR_REQUEST: 8000
|
||||
TOKEN_FOR_ANSWER: 2000
|
||||
CATALOGID: xxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
PROMPT: "Ты чат-бот ..."
|
||||
STARTWORD: "Бот| Бот, | бот | бот,"
|
||||
INWORD: "помогите | не работает"
|
||||
|
||||
ROLES:
|
||||
ADMIN: 2
|
||||
MODERATOR: 1
|
||||
USER: 0
|
||||
BOT: 3
|
24
src/core/logger.py
Normal file
24
src/core/logger.py
Normal file
@ -0,0 +1,24 @@
|
||||
import os
|
||||
import time
|
||||
|
||||
async def check_log_file():
|
||||
# Проверка наличия файла для логов в формате log-dd-mm-yyyy.log
|
||||
# Если файл существует, то pass
|
||||
# Если файл не существует, то создаём его. файл лежит в директории src.core.log
|
||||
current_data = time.strftime("%d-%m-%Y")
|
||||
log_file = os.path.join(os.path.dirname(__file__), "log/", f"log-{current_data}.log")
|
||||
if not os.path.exists(log_file):
|
||||
with open(log_file, 'w') as file:
|
||||
file.write("Log file created\n")
|
||||
file.close()
|
||||
else:
|
||||
pass
|
||||
|
||||
async def log(message):
|
||||
await check_log_file()
|
||||
current_data = time.strftime("%d-%m-%Y")
|
||||
log_file = os.path.join(os.path.dirname(__file__), "log/", f"log-{current_data}.log")
|
||||
# print(log_file)
|
||||
with open(log_file, 'a') as file:
|
||||
file.write(f"{time.strftime('%H:%M:%S')} {message}\n")
|
||||
file.close()
|
@ -1,7 +1,10 @@
|
||||
from aiogram import Dispatcher
|
||||
from aiogram import Dispatcher, Router, F, Bot
|
||||
from aiogram.types import Message
|
||||
|
||||
from src.modules.standard.info.routers import router as info_router
|
||||
from src.modules.standard.admin.routers import router as admin_router
|
||||
from src.modules.external.yandexgpt.routers import router as yandexgpt_router
|
||||
from src.modules.standard.message_processing.message_api import router as process_message
|
||||
from src.modules.standard.welcome.routers import router as welcome_router
|
||||
|
||||
|
||||
async def include_routers(dp: Dispatcher):
|
||||
@ -9,5 +12,7 @@ async def include_routers(dp: Dispatcher):
|
||||
Подключение роутеров в бота
|
||||
dp.include_router()
|
||||
"""
|
||||
dp.include_router(yandexgpt_router)
|
||||
dp.include_router(info_router)
|
||||
dp.include_router(admin_router)
|
||||
dp.include_router(process_message)
|
||||
|
10
src/modules/external/yandexgpt/handlers.py
vendored
10
src/modules/external/yandexgpt/handlers.py
vendored
@ -2,12 +2,18 @@ from aiogram import Bot
|
||||
from aiogram.types import Message
|
||||
from src.modules.external.yandexgpt.yandexgpt import *
|
||||
from src.modules.standard.config.config import get_yandexgpt_token, get_yandexgpt_catalog_id, get_yandexgpt_prompt
|
||||
from src.modules.standard.database.db_api import add_message
|
||||
from src.core.logger import log
|
||||
import asyncio
|
||||
|
||||
|
||||
async def answer_to_message(message: Message, bot: Bot):
|
||||
# print("answer_to_message")
|
||||
await log("answer_to_message")
|
||||
yagpt = YandexGPT(get_yandexgpt_token(), get_yandexgpt_catalog_id())
|
||||
text = message.text
|
||||
prompt = get_yandexgpt_prompt()
|
||||
response = await yagpt.async_yandexgpt(system_prompt=prompt, input_messages=text)
|
||||
await message.reply(response, parse_mode="Markdown")
|
||||
# response = await yagpt.async_yandexgpt(system_prompt=prompt, input_messages=text)
|
||||
response = await yagpt.yandexgpt_request(chat_id = message.chat.id, message_id = message.message_id, type = "yandexgpt")
|
||||
reply = await message.reply(response, parse_mode="Markdown")
|
||||
add_message(reply, message_ai_model="yandexgpt")
|
||||
|
2
src/modules/external/yandexgpt/routers.py
vendored
2
src/modules/external/yandexgpt/routers.py
vendored
@ -3,5 +3,5 @@ from aiogram import Router, F
|
||||
from src.modules.external.yandexgpt.handlers import answer_to_message
|
||||
|
||||
router = Router()
|
||||
# Если сообщение содержит в начале текст "Гномик" или "гномик", то вызывается функция answer_to_message
|
||||
# Если сообщение содержит в начале текст "Гномик" или "гномик" или отвечает на сообщение бота, то вызывается функция answer_to_message
|
||||
router.message.register(answer_to_message, F.text.startswith("Гномик") | F.text.startswith("гномик"))
|
89
src/modules/external/yandexgpt/yandexgpt.py
vendored
89
src/modules/external/yandexgpt/yandexgpt.py
vendored
@ -2,6 +2,7 @@ import requests
|
||||
import json
|
||||
import asyncio
|
||||
import aiohttp
|
||||
from src.core.logger import log
|
||||
|
||||
from ...standard.database import *
|
||||
from ...standard.config.config import *
|
||||
@ -23,28 +24,44 @@ class YandexGPT:
|
||||
self.token = token
|
||||
self.catalog_id = catalog_id
|
||||
|
||||
async def async_token_check(self, messages, gpt, max_tokens, del_msg_id=1):
|
||||
url = "https://llm.api.cloud.yandex.net/foundationModels/v1/tokenize"
|
||||
while True:
|
||||
text = ""
|
||||
for message in messages:
|
||||
text += message["text"]
|
||||
try:
|
||||
response = requests.post(url, json={"model": gpt, "text": text})
|
||||
except Exception as e: # TODO: Переделать обработку ошибок
|
||||
print(e)
|
||||
continue
|
||||
if int(response.text) < max_tokens - 2000:
|
||||
break
|
||||
else:
|
||||
messages.pop(del_msg_id)
|
||||
return messages
|
||||
|
||||
async def async_request(self, url, headers, prompt) -> dict:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(url, headers=headers, json=prompt) as response:
|
||||
return await response.json()
|
||||
|
||||
async def async_token_check(self, messages, gpt, max_tokens, stream, temperature, del_msg_id=1):
|
||||
url = "https://llm.api.cloud.yandex.net/foundationModels/v1/tokenizeCompletion"
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Api-Key {self.token}"
|
||||
}
|
||||
answer_token = get_yandexgpt_token_for_answer()
|
||||
while True:
|
||||
try:
|
||||
request = {
|
||||
"modelUri": gpt,
|
||||
"completionOptions": {
|
||||
"stream": stream,
|
||||
"temperature": temperature,
|
||||
"maxTokens": max_tokens
|
||||
},
|
||||
"messages": messages
|
||||
}
|
||||
response = await self.async_request(url=url, headers=headers, prompt=request)
|
||||
except Exception as e: # TODO: Переделать обработку ошибок
|
||||
# print(e)
|
||||
await log(f"Error: {e}")
|
||||
|
||||
continue
|
||||
if int(len(response["tokens"])) < (max_tokens - answer_token):
|
||||
break
|
||||
else:
|
||||
try:
|
||||
messages.pop(del_msg_id)
|
||||
except IndexError:
|
||||
Exception("IndexError: list index out of range")
|
||||
return messages
|
||||
|
||||
async def async_yandexgpt_lite(self, system_prompt, input_messages, stream=False, temperature=0.6, max_tokens=8000):
|
||||
url = "https://llm.api.cloud.yandex.net/foundationModels/v1/completion"
|
||||
gpt = f"gpt://{self.catalog_id}/yandexgpt-lite/latest"
|
||||
@ -71,7 +88,14 @@ class YandexGPT:
|
||||
response = requests.post(url, headers=headers, json=prompt).text
|
||||
return json.loads(response)["result"]["alternatives"][0]["message"]["text"]
|
||||
|
||||
async def async_yandexgpt(self, system_prompt, input_messages, stream=False, temperature=0.6, max_tokens=8000):
|
||||
async def async_yandexgpt(
|
||||
self,
|
||||
system_prompt,
|
||||
input_messages,
|
||||
stream=False,
|
||||
temperature=0.6,
|
||||
max_tokens=get_yandexgpt_token_for_request()
|
||||
):
|
||||
url = "https://llm.api.cloud.yandex.net/foundationModels/v1/completion"
|
||||
gpt = f"gpt://{self.catalog_id}/yandexgpt/latest"
|
||||
headers = {
|
||||
@ -79,13 +103,14 @@ class YandexGPT:
|
||||
"Authorization": f"Api-Key {self.token}"
|
||||
}
|
||||
|
||||
messages = [{"role": "system", "text": system_prompt}]
|
||||
messages.append({"role": "user", "text": input_messages})
|
||||
# for message in input_messages:
|
||||
# messages.append(message)
|
||||
# messages = await self.async_token_check(messages, gpt, max_tokens)
|
||||
messages = []
|
||||
messages.append({"role": "system", "text": system_prompt})
|
||||
for message in input_messages:
|
||||
messages.append(message)
|
||||
|
||||
prompt = {
|
||||
messages = await self.async_token_check(messages, gpt, max_tokens, stream, temperature)
|
||||
|
||||
request = {
|
||||
"modelUri": gpt,
|
||||
"completionOptions": {
|
||||
"stream": stream,
|
||||
@ -94,7 +119,7 @@ class YandexGPT:
|
||||
},
|
||||
"messages": messages
|
||||
}
|
||||
response = await self.async_request(url=url, headers=headers, prompt=prompt)
|
||||
response = await self.async_request(url=url, headers=headers, prompt=request)
|
||||
return response["result"]["alternatives"][0]["message"]["text"]
|
||||
|
||||
|
||||
@ -153,21 +178,21 @@ class YandexGPT:
|
||||
# TODO: Сделать функцию Vision
|
||||
return 0
|
||||
|
||||
async def collect_messages(self, message_id, chat_id, start_message_id):
|
||||
async def collect_messages(self, message_id, chat_id):
|
||||
messages = []
|
||||
# Собираем цепочку сообщений в формате: [{"role": "user", "text": "<Имя_пользователя>: Привет!"},
|
||||
# {"role": "assistant", "text": "Привет!"}]
|
||||
while True:
|
||||
message = db_api.get_message_text(chat_id, message_id)
|
||||
if db_api.get_message_ai_model(chat_id, start_message_id) != None:
|
||||
if db_api.get_message_ai_model(chat_id, message_id) != None:
|
||||
messages.append({"role": "assistant", "text": message})
|
||||
else:
|
||||
sender_name = db_api.get_user_name(db_api.get_message_sender_id(chat_id, start_message_id))
|
||||
sender_name = db_api.get_user_name(db_api.get_message_sender_id(chat_id, message_id))
|
||||
messages.append({"role": "user", "text": sender_name + ": " + message})
|
||||
message_id = db_api.get_message_answer_to_message_id(chat_id, message_id)
|
||||
message_id = db_api.get_answer_to_message_id(chat_id, message_id)
|
||||
if message_id is None:
|
||||
break
|
||||
return messages.reverse()
|
||||
return list(reversed(messages))
|
||||
|
||||
async def collecting_messages_for_history(self, start_message_id, end_message_id, chat_id):
|
||||
messages = []
|
||||
@ -195,11 +220,13 @@ class YandexGPT:
|
||||
stream=False, temperature=0.6, max_tokens=8000
|
||||
)
|
||||
elif type == "yandexgpt":
|
||||
# print("yandexgpt_request")
|
||||
await log("yandexgpt_request")
|
||||
messages = await self.collect_messages(message_id, chat_id)
|
||||
return await self.async_yandexgpt(
|
||||
system_prompt=get_yandexgpt_prompt(),
|
||||
input_messages=messages,
|
||||
stream=False, temperature=0.6, max_tokens=8000
|
||||
stream=False, temperature=0.6, max_tokens=get_yandexgpt_token_for_request()
|
||||
)
|
||||
elif type == "yandexgpt-translate":
|
||||
return await self.async_yandexgpt_translate(
|
||||
|
@ -1,5 +1,7 @@
|
||||
from aiogram import Bot
|
||||
from aiogram.types import Message
|
||||
from src.modules.standard.config.config import get_default_chat_tag
|
||||
import time
|
||||
|
||||
|
||||
async def delete_message(message: Message, bot: Bot):
|
||||
@ -11,3 +13,34 @@ async def error_access(message: Message, bot: Bot):
|
||||
|
||||
async def get_chat_id(message: Message, bot: Bot):
|
||||
await message.reply(f"ID данного чата: `{message.chat.id}`", parse_mode="MarkdownV2")
|
||||
|
||||
async def chat_not_in_approve_list(message: Message, bot: Bot):
|
||||
await message.reply(
|
||||
f"Бот недоступен в данном чате, пожалуйста,"
|
||||
f" обратитесь к администратору для добавления чата в список доступных или перейдите в чат "
|
||||
f"{get_default_chat_tag()}"
|
||||
)
|
||||
await get_chat_id(message, bot)
|
||||
|
||||
async def mute_user(chat_id: int, user_id: int, time: int, bot: Bot):
|
||||
# *, can_send_messages: bool | None = None, can_send_audios: bool | None = None, can_send_documents: bool | None = None, can_send_photos: bool | None = None, can_send_videos: bool | None = None, can_send_video_notes: bool | None = None, can_send_voice_notes: bool | None = None, can_send_polls: bool | None = None, can_send_other_messages: bool | None = None, can_add_web_page_previews: bool | None = None, can_change_info: bool | None = None, can_invite_users: bool | None = None, can_pin_messages: bool | None = None, can_manage_topics: bool | None = None, **extra_data: Any)
|
||||
|
||||
mutePermissions = {
|
||||
"can_send_messages": False,
|
||||
"can_send_audios": False,
|
||||
"can_send_documents": False,
|
||||
"can_send_photos": False,
|
||||
"can_send_videos": False,
|
||||
"can_send_video_notes": False,
|
||||
"can_send_voice_notes": False,
|
||||
"can_send_polls": False,
|
||||
"can_send_other_messages": False,
|
||||
"can_add_web_page_previews": False,
|
||||
"can_change_info": False,
|
||||
"can_invite_users": False,
|
||||
"can_pin_messages": False,
|
||||
"can_manage_topics": False
|
||||
}
|
||||
end_time = time + int(time.time())
|
||||
await bot.restrict_chat_member(chat_id, user_id, until_date=end_time, **mutePermissions)
|
||||
|
||||
|
@ -1,9 +1,13 @@
|
||||
from aiogram import Router, F
|
||||
|
||||
from src.modules.standard.admin.handlers import delete_message, error_access, get_chat_id
|
||||
from src.modules.standard.filters.admin import ChatModerOrAdminFilter
|
||||
from src.modules.standard.admin.handlers import delete_message, error_access, get_chat_id, chat_not_in_approve_list
|
||||
from src.modules.standard.filters.filters import ChatModerOrAdminFilter, ChatNotInApproveFilter
|
||||
|
||||
router = Router()
|
||||
|
||||
# Если сообщение содержит какой либо текст и выполняется фильтр ChatNotInApproveFilter, то вызывается функция chat_not_in_approve_list
|
||||
router.message.register(chat_not_in_approve_list, ChatNotInApproveFilter(), F.text)
|
||||
|
||||
router.message.register(get_chat_id, ChatModerOrAdminFilter(), F.text == '/chatID')
|
||||
|
||||
router.message.register(delete_message, ChatModerOrAdminFilter(), F.text == '/rm')
|
||||
|
@ -17,6 +17,20 @@ config = get_config()
|
||||
def get_telegram_token() -> str:
|
||||
return config["TELEGRAM"]["TOKEN"]
|
||||
|
||||
def get_telegram_check_bot() -> bool:
|
||||
return config["TELEGRAM"]["CHECK_BOT"]
|
||||
|
||||
def get_aproved_chat_id() -> list:
|
||||
# Возваращем сплитованный список id чатов в формате int
|
||||
return [int(chat_id) for chat_id in config["TELEGRAM"]["APPROVED_CHAT_ID"].split(" | ")]
|
||||
|
||||
def get_user_role_name(role_number) -> dict:
|
||||
# Возвращаем название роли пользвателя по номеру роли, если такой роли нет, возвращаем неизвестно
|
||||
return config["ROLES"].get(role_number, "Неизвестно")
|
||||
|
||||
def get_default_chat_tag() -> str:
|
||||
return config["TELEGRAM"]["DEFAULT_CHAT_TAG"]
|
||||
|
||||
def get_yandexgpt_token() -> str:
|
||||
return config["YANDEXGPT"]["TOKEN"]
|
||||
|
||||
@ -26,7 +40,21 @@ def get_yandexgpt_catalog_id() -> str:
|
||||
def get_yandexgpt_prompt() -> str:
|
||||
return config["YANDEXGPT"]["PROMPT"]
|
||||
|
||||
def get_yandexgpt_start_words() -> list:
|
||||
return config["YANDEXGPT"]["STARTWORD"].split(" | ")
|
||||
|
||||
def get_yandexgpt_in_words() -> list:
|
||||
return config["YANDEXGPT"]["INWORD"].split(" | ")
|
||||
|
||||
def get_yandexgpt_token_for_request() -> int:
|
||||
return config["YANDEXGPT"]["TOKEN_FOR_REQUEST"]
|
||||
|
||||
def get_yandexgpt_token_for_answer() -> int:
|
||||
return config["YANDEXGPT"]["TOKEN_FOR_ANSWER"]
|
||||
|
||||
def get_access_rights() -> dict:
|
||||
return get_config()["ACCESS_RIGHTS"]
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,6 +6,7 @@ from .models.chat_stats import ChatStats
|
||||
from ....service import paths
|
||||
from ..exceptions.module_exceptions import MissingModuleName, NotExpectedModuleName
|
||||
import peewee as pw
|
||||
from aiogram.types import Message
|
||||
|
||||
|
||||
def connect_database(is_test: bool = False, module: str | None = None):
|
||||
@ -39,7 +40,7 @@ def add_chat(chat_id, chat_name, chat_type=10, chat_stats=0):
|
||||
chat, created = Chats.get_or_create(id=chat_id, defaults={
|
||||
'chat_name': chat_name,
|
||||
'chat_type': chat_type,
|
||||
'chat_stats': chat_stats,
|
||||
'chat_all_stat': chat_stats,
|
||||
})
|
||||
if not created:
|
||||
# Обновить существующий чат, если он уже существует
|
||||
@ -49,7 +50,12 @@ def add_chat(chat_id, chat_name, chat_type=10, chat_stats=0):
|
||||
chat.save()
|
||||
|
||||
|
||||
def add_user(user_id, user_name, user_tag=None, user_role=0, user_stats=0, user_rep=0):
|
||||
def add_user(user_id, user_first_name, user_last_name=None, user_tag=None, user_role=0, user_stats=0, user_rep=0):
|
||||
if user_last_name is None:
|
||||
user_name = user_first_name
|
||||
else:
|
||||
user_name = user_first_name + " " + user_last_name
|
||||
|
||||
user, created = Users.get_or_create(id=user_id, defaults={
|
||||
'user_tag': user_tag,
|
||||
'user_name': user_name,
|
||||
@ -67,15 +73,18 @@ def add_user(user_id, user_name, user_tag=None, user_role=0, user_stats=0, user_
|
||||
user.save()
|
||||
|
||||
|
||||
def add_message(message_chat_id, message_id, message_sender_id, message_text, answer_to_message_id=None,
|
||||
message_ai_model=None):
|
||||
def add_message(message: Message, message_ai_model=None):
|
||||
if message.reply_to_message:
|
||||
answer_to_message_id = message.reply_to_message.message_id
|
||||
else:
|
||||
answer_to_message_id = None
|
||||
Messages.create(
|
||||
message_chat_id=message_chat_id,
|
||||
message_id=message_id,
|
||||
message_sender_id=message_sender_id,
|
||||
message_chat_id=message.chat.id,
|
||||
message_id=message.message_id,
|
||||
message_sender_id=message.from_user.id,
|
||||
answer_to_message_id=answer_to_message_id,
|
||||
message_ai_model=message_ai_model,
|
||||
message_text=message_text
|
||||
message_text=message.text
|
||||
)
|
||||
|
||||
|
||||
@ -127,6 +136,10 @@ def get_user_tag(user_id):
|
||||
user = Users.get_or_none(Users.id == user_id)
|
||||
return user.user_tag if user else None
|
||||
|
||||
def get_user_id(user_tag):
|
||||
user = Users.get_or_none(Users.user_tag == user_tag)
|
||||
return user.id if user else None
|
||||
|
||||
|
||||
def get_user_name(user_id):
|
||||
user = Users.get_or_none(Users.id == user_id)
|
||||
@ -148,7 +161,11 @@ def get_user_rep(user_id):
|
||||
return user.user_rep if user else None
|
||||
|
||||
|
||||
def change_user_name(user_id, new_user_name):
|
||||
def change_user_name(user_id, user_first_name, user_last_name=None):
|
||||
if user_last_name is None:
|
||||
new_user_name = user_first_name
|
||||
else:
|
||||
new_user_name = user_first_name + " " + user_last_name
|
||||
query = Users.update(user_name=new_user_name).where(Users.id == user_id)
|
||||
query.execute()
|
||||
|
||||
|
@ -1,13 +0,0 @@
|
||||
from aiogram.filters import BaseFilter
|
||||
from aiogram.types import Message
|
||||
from aiogram import Bot
|
||||
|
||||
from src.modules.standard.roles.roles import Roles
|
||||
|
||||
class ChatModerOrAdminFilter(BaseFilter):
|
||||
async def __call__(self, message: Message, bot: Bot) -> bool:
|
||||
user_id = message.from_user.id
|
||||
roles = Roles()
|
||||
admins = await bot.get_chat_administrators(message.chat.id)
|
||||
return await roles.check_admin_permission(user_id) or \
|
||||
await roles.check_moderator_permission(user_id) or any(user_id == admin.user.id for admin in admins)
|
29
src/modules/standard/filters/filters.py
Normal file
29
src/modules/standard/filters/filters.py
Normal file
@ -0,0 +1,29 @@
|
||||
from aiogram.filters import BaseFilter
|
||||
from aiogram.types import Message
|
||||
from aiogram import Bot
|
||||
|
||||
from src.modules.standard.roles.roles import Roles
|
||||
from src.modules.standard.config.config import get_aproved_chat_id
|
||||
from src.core.logger import log
|
||||
|
||||
class ChatModerOrAdminFilter(BaseFilter):
|
||||
async def __call__(self, message: Message, bot: Bot) -> bool:
|
||||
user_id = message.from_user.id
|
||||
roles = Roles()
|
||||
admins = await bot.get_chat_administrators(message.chat.id)
|
||||
return await roles.check_admin_permission(user_id) or \
|
||||
await roles.check_moderator_permission(user_id) or any(user_id == admin.user.id for admin in admins)
|
||||
|
||||
class ChatNotInApproveFilter(BaseFilter):
|
||||
async def __call__(self, message: Message, bot: Bot) -> bool:
|
||||
# print("chat_check")
|
||||
await log("chat_check")
|
||||
chat_id = message.chat.id
|
||||
if chat_id in get_aproved_chat_id():
|
||||
# print(f"Chat in approve list: {chat_id}")
|
||||
await log(f"Chat in approve list: {chat_id}")
|
||||
return False
|
||||
else:
|
||||
# print(f"Chat not in approve list: {chat_id}")
|
||||
await log(f"Chat not in approve list: {chat_id}")
|
||||
return True
|
0
src/modules/standard/info/__init__.py
Normal file
0
src/modules/standard/info/__init__.py
Normal file
60
src/modules/standard/info/handlers.py
Normal file
60
src/modules/standard/info/handlers.py
Normal file
@ -0,0 +1,60 @@
|
||||
from aiogram import Bot
|
||||
from aiogram.types import Message
|
||||
from src.modules.standard.config.config import get_user_role_name
|
||||
from src.modules.standard.roles.roles import Roles
|
||||
from src.modules.standard.database.db_api import *
|
||||
from src.core.logger import log
|
||||
|
||||
async def get_info_answer_by_id(message: Message, bot: Bot, user_id: int):
|
||||
if get_message_ai_model(message.chat.id, message.message_id) is not None:
|
||||
await message.reply("Это сообщение было сгенерировано ботом используя модель: " + get_message_ai_model(message.chat.id, message.message_id))
|
||||
elif user_id == bot.id:
|
||||
await message.reply("Это сообщение было отправлено ботом")
|
||||
elif get_user(user_id) is None:
|
||||
await message.reply("Пользователь не найден")
|
||||
# print(get_user(user_id))
|
||||
await log(f"Пользователь не найден: {user_id}, {get_user(user_id)}")
|
||||
else:
|
||||
roles = Roles()
|
||||
answer = (
|
||||
f"Пользователь: {get_user_name(user_id)}\n"
|
||||
f"Роль: {await roles.get_role_name(role_id=get_user_role(user_id))}\n"
|
||||
f"Тег: @{get_user_tag(user_id)}\n"
|
||||
f"Кол-во сообщений: {get_user_all_stats(user_id)}\n"
|
||||
f"Репутация: {get_user_rep(user_id)}"
|
||||
)
|
||||
await message.reply(answer)
|
||||
|
||||
|
||||
async def get_user_info(message: Message, bot: Bot):
|
||||
# Проверяем содержимое сообщения, если содержит вторым элементом тег пользователя, то выводим информацию о нем
|
||||
# Если сообщение отвечает на другое сообщение, то выводим информацию о пользователе, на чье сообщение был ответ
|
||||
# Если это бот то выводим информацию что это бот и какая модель yandexgpt используется
|
||||
try:
|
||||
if len(message.text.split()) > 1 and message.text.split()[1].startswith("@"):
|
||||
user_tag = message.text.split()[1][1:]
|
||||
user_id = get_user_id(user_tag)
|
||||
if user_id:
|
||||
await get_info_answer_by_id(message, bot, user_id)
|
||||
else:
|
||||
await message.reply(f"Пользователь с тегом @{user_tag} не найден")
|
||||
elif message.reply_to_message:
|
||||
user_id = message.reply_to_message.from_user.id
|
||||
await get_info_answer_by_id(message, bot, user_id)
|
||||
else:
|
||||
await get_info_answer_by_id(message, bot, message.from_user.id)
|
||||
except Exception as e:
|
||||
await message.reply("В вашем запросе что-то пошло не так,"
|
||||
" попробуйте запросить информацию о пользователе по его тегу или ответив на его сообщение")
|
||||
# print(e)
|
||||
await log(e)
|
||||
|
||||
async def get_chat_info(message: Message, bot: Bot):
|
||||
answer = (
|
||||
f"*Название чата:* {message.chat.title}\n"
|
||||
f"*ID чата:* `{message.chat.id}`\n \n"
|
||||
f"*Суммарное количество сообщений в чате:* {get_chat_all_stat(message.chat.id)}\n"
|
||||
f"*Количество пользователей в чате:* {await bot.get_chat_member_count(message.chat.id)}\n"
|
||||
f"*Количество администраторов в чате:* {len(await bot.get_chat_administrators(message.chat.id))}"
|
||||
)
|
||||
await message.reply(answer, parse_mode="MarkdownV2")
|
8
src/modules/standard/info/routers.py
Normal file
8
src/modules/standard/info/routers.py
Normal file
@ -0,0 +1,8 @@
|
||||
from aiogram import Router, F
|
||||
|
||||
from src.modules.standard.info.handlers import get_user_info, get_chat_info
|
||||
|
||||
router = Router()
|
||||
|
||||
router.message.register(get_user_info, F.text.startswith("/info") == True)
|
||||
router.message.register(get_chat_info, F.text.startswith("/chatinfo") == True)
|
0
src/modules/standard/message_processing/__init__.py
Normal file
0
src/modules/standard/message_processing/__init__.py
Normal file
99
src/modules/standard/message_processing/message_api.py
Normal file
99
src/modules/standard/message_processing/message_api.py
Normal file
@ -0,0 +1,99 @@
|
||||
from aiogram import Router, F, Bot, types
|
||||
|
||||
from src.modules.external.yandexgpt.handlers import answer_to_message
|
||||
from src.modules.standard.database.db_api import *
|
||||
from src.modules.standard.config.config import get_yandexgpt_start_words, get_yandexgpt_in_words, get_aproved_chat_id
|
||||
from src.core.logger import log
|
||||
|
||||
|
||||
async def chat_check(message: types.Message):
|
||||
# Проверка наличия id чата в базе данных чатов
|
||||
# Если чата нет в базе данных, то проверяем его в наличии в конфиге и если он там есть то добавляем его в БД
|
||||
# Если чат есть в базе данных, то pass
|
||||
if get_chat(message.chat.id) is None:
|
||||
if message.chat.id in get_aproved_chat_id():
|
||||
# print(f"Chat in approve list: {message.chat.id} {message.chat.title}")
|
||||
await log(f"Chat in approve list: {message.chat.id} {message.chat.title}")
|
||||
add_chat(message.chat.id, message.chat.title)
|
||||
# print(f"Chat added: {message.chat.id} {message.chat.title}")
|
||||
await log(f"Chat added: {message.chat.id} {message.chat.title}")
|
||||
else:
|
||||
# print(f"Chat not in approve list: {message.chat.id} {message.chat.title}")
|
||||
await log(f"Chat not in approve list: {message.chat.id} {message.chat.title}")
|
||||
pass
|
||||
else:
|
||||
# Проверяем обновление названия чата
|
||||
chat = get_chat(message.chat.id)
|
||||
if chat.chat_name != message.chat.title:
|
||||
chat.chat_name = message.chat.title
|
||||
chat.save()
|
||||
# print(f"Chat updated: {message.chat.id} {message.chat.title}")
|
||||
await log(f"Chat updated: {message.chat.id} {message.chat.title}")
|
||||
else:
|
||||
# print(f"Chat already exists: {message.chat.id} {message.chat.title}")
|
||||
await log(f"Chat already exists: {message.chat.id} {message.chat.title}")
|
||||
pass
|
||||
|
||||
async def user_check(message: types.Message):
|
||||
# Проверка наличия id пользователя в базе данных пользователей
|
||||
# Если пользователя нет в базе данных, то добавляем его
|
||||
# Если пользователь есть в базе данных, то pass
|
||||
current_user_name = ""
|
||||
if message.from_user.last_name is None:
|
||||
current_user_name = message.from_user.first_name
|
||||
else:
|
||||
current_user_name = message.from_user.first_name + " " + message.from_user.last_name
|
||||
|
||||
if get_user(message.from_user.id) is None:
|
||||
add_user(message.from_user.id,
|
||||
message.from_user.first_name, message.from_user.last_name,
|
||||
message.from_user.username)
|
||||
# print(f"User added: {message.from_user.id} {message.from_user.first_name} {message.from_user.last_name}")
|
||||
await log(f"User added: {message.from_user.id} {current_user_name}")
|
||||
else:
|
||||
# print(f"User already exists: {message.from_user.id} {message.from_user.first_name} {message.from_user.last_name} {message.from_user.username}")
|
||||
await log(f"User already exists: {message.from_user.id} {current_user_name} {message.from_user.username}")
|
||||
# Проверяем обновление имени пользователя
|
||||
if get_user_name(message.from_user.id) != current_user_name:
|
||||
change_user_name(message.from_user.id, current_user_name)
|
||||
# print(f"User updated: {message.from_user.id} {message.from_user.first_name} {message.from_user.last_name}")
|
||||
await log(f"User name updated: {message.from_user.id} {current_user_name}")
|
||||
# Проверяем обновление username пользователя
|
||||
if get_user_tag(message.from_user.id) != message.from_user.username:
|
||||
change_user_tag(message.from_user.id, message.from_user.username)
|
||||
# print(f"User updated: {message.from_user.id} {message.from_user.username}")
|
||||
await log(f"User tag updated: {message.from_user.id} {message.from_user.username}")
|
||||
pass
|
||||
|
||||
async def add_stats(message: types.Message):
|
||||
# Добавляем пользователю и чату статистику
|
||||
update_chat_all_stat(message.chat.id)
|
||||
update_user_all_stat(message.from_user.id)
|
||||
|
||||
|
||||
async def message_processing(message: types.Message, bot: Bot):
|
||||
await chat_check(message)
|
||||
await user_check(message)
|
||||
await add_stats(message)
|
||||
|
||||
add_message(message)
|
||||
# Если сообщение в начале содержит слово из списка или внутри сообщения содержится слово из списка или сообщение отвечает на сообщение бота
|
||||
|
||||
if ((message.text.split(" ")[0] in get_yandexgpt_start_words())
|
||||
or (any(word in message.text for word in get_yandexgpt_in_words()))):
|
||||
# print("message_processing")
|
||||
await log("message_processing")
|
||||
await answer_to_message(message, bot)
|
||||
|
||||
elif message.reply_to_message is not None:
|
||||
if message.reply_to_message.from_user.is_bot:
|
||||
# print("message_processing")
|
||||
await log("message_processing")
|
||||
await answer_to_message(message, bot)
|
||||
|
||||
|
||||
|
||||
|
||||
router = Router()
|
||||
# Если сообщение содержит текст то вызывается функция message_processing
|
||||
router.message.register(message_processing, F.text)
|
@ -45,69 +45,31 @@ class Moderation:
|
||||
async def ban_user(self, chat_id, user_id, bot: aiogram.Bot):
|
||||
await bot.ban_chat_member(chat_id, user_id)
|
||||
|
||||
async def mute_user(self, message, chat_id, user_id, bot: aiogram.Bot, time=0):
|
||||
# Проверка что отправитель является администратором чата
|
||||
# Проверяем мин
|
||||
try:
|
||||
if check_admin_permission(message.from_user.id):
|
||||
# Проверка отвечает ли сообщение на другое сообщение
|
||||
if message.reply_to_message is not None:
|
||||
time = message.text.split(' ')[1]
|
||||
# получаем id отправителя сообщение на которое отвечает message
|
||||
target_id = message.reply_to_message.from_user.id
|
||||
target_name = \
|
||||
cursor.execute("SELECT user_name FROM user_list WHERE user_id = ?", (target_id,)).fetchone()[0]
|
||||
# Проверка, что человек пользователь
|
||||
if cursor.execute("SELECT user_role FROM user_list WHERE user_id = ?", (target_id,)).fetchone()[
|
||||
0] == 0:
|
||||
# ограничения прав пользователя по отправке сообщений на time секунд
|
||||
time_sec = await time_to_seconds(message.text.split(' ')[1])
|
||||
if time_sec <= 30 or time_sec >= 31536000:
|
||||
await message.reply("Время мута должно быть больше 30 секунд и меньше 365 дней")
|
||||
return
|
||||
date_string = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
date_time = datetime.datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S")
|
||||
unix_time = int(mktime(date_time.timetuple()))
|
||||
await bot.restrict_chat_member(message.chat.id, target_id, until_date=unix_time + time_sec,
|
||||
permissions=types.ChatPermissions(can_send_messages=False))
|
||||
await message.reply(
|
||||
f"Пользователь {target_name} замьючен на {await short_time_to_time(time)}")
|
||||
else:
|
||||
await message.reply(
|
||||
f"Пользователь [{target_name}](tg://user?id={target_id}) является {await get_role(target_id)} и не может быть замьючен",
|
||||
parse_mode='Markdown')
|
||||
return
|
||||
else:
|
||||
target_tag = message.text.split(' ')[1]
|
||||
target_tag = target_tag[1:]
|
||||
target_id = int(
|
||||
cursor.execute("SELECT user_id FROM user_list WHERE user_name = ?", (target_tag,)).fetchone()[
|
||||
0])
|
||||
target_name = \
|
||||
cursor.execute("SELECT user_name FROM user_list WHERE user_id = ?", (target_id,)).fetchone()[0]
|
||||
# ограничения прав пользователя по отправке сообщений на time секунд
|
||||
time_mute = message.text.split(' ')[2]
|
||||
|
||||
if cursor.execute("SELECT user_role FROM user_list WHERE user_id = ?", (target_id,)).fetchone()[
|
||||
0] == 0:
|
||||
# ограничения прав пользователя по отправке сообщений на time секунд
|
||||
time_sec = await time_to_seconds(message.text.split(' ')[2])
|
||||
if time_sec <= 30 or time_sec >= 31536000:
|
||||
await message.reply("Время мута должно быть больше 30 секунд и меньше 365 дней")
|
||||
return
|
||||
date_string = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
date_time = datetime.datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S")
|
||||
unix_time = int(mktime(date_time.timetuple()))
|
||||
await bot.restrict_chat_member(message.chat.id, target_id, until_date=unix_time + time_sec,
|
||||
permissions=types.ChatPermissions(can_send_messages=False))
|
||||
await message.reply(
|
||||
f"Пользователь {target_name} замьючен на {await short_time_to_time(time_mute)}.")
|
||||
else:
|
||||
await message.reply(
|
||||
f"Пользователь [{target_name}](tg://user?id={target_id}) является {await get_role(target_id)} и не может быть замьючен",
|
||||
parse_mode="Markdown")
|
||||
return
|
||||
except:
|
||||
await message.reply("Ошибка данных. Возможно пользователь ещё ничего не написал.")
|
||||
async def mute_user(chat_id, user_id, time, bot: aiogram.Bot):
|
||||
mutePermissions = {
|
||||
"can_send_messages": False,
|
||||
"can_send_audios": False,
|
||||
"can_send_documents": False,
|
||||
"can_send_photos": False,
|
||||
"can_send_videos": False,
|
||||
"can_send_video_notes": False,
|
||||
"can_send_voice_notes": False,
|
||||
"can_send_polls": False,
|
||||
"can_send_other_messages": False,
|
||||
"can_add_web_page_previews": False,
|
||||
"can_change_info": False,
|
||||
"can_invite_users": False,
|
||||
"can_pin_messages": False,
|
||||
"can_manage_topics": False
|
||||
}
|
||||
end_time = time + int(time.time())
|
||||
await bot.restrict_chat_member(chat_id, user_id, until_date=end_time, **mutePermissions)
|
||||
|
||||
|
||||
async def unmute_user(chat_id, user_id, bot: aiogram.Bot):
|
||||
await bot.restrict_chat_member(chat_id, user_id, use_independent_chat_permissions=True)
|
||||
|
||||
async def ban_user(chat_id, user_id, bot: aiogram.Bot):
|
||||
await bot.ban_chat_member(chat_id, user_id)
|
||||
|
||||
|
||||
|
74
src/modules/standard/welcome/handlers.py
Normal file
74
src/modules/standard/welcome/handlers.py
Normal file
@ -0,0 +1,74 @@
|
||||
from aiogram import Bot
|
||||
from aiogram.types import Message
|
||||
from src.modules.standard.config.config import get_telegram_check_bot
|
||||
from src.modules.standard.roles.roles import Roles
|
||||
from src.modules.standard.database.db_api import *
|
||||
from src.modules.standard.moderation.moderation import mute_user, unmute_user, ban_user
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from aiogram.types import inline_keyboard_button as types
|
||||
import random, asyncio
|
||||
from threading import Thread
|
||||
|
||||
async def create_math_task():
|
||||
first_number = random.randint(1, 100)
|
||||
second_number = random.randint(1, 100)
|
||||
answer = first_number + second_number
|
||||
fake_answers = []
|
||||
for i in range(3):
|
||||
diff = random.randint(1, 10)
|
||||
diff_sign = random.choice(["+", "-"])
|
||||
fake_answers.append(answer + diff if diff_sign == "+" else answer - diff)
|
||||
fake_answers.append(answer)
|
||||
random.shuffle(fake_answers)
|
||||
return [answer, first_number, second_number, fake_answers]
|
||||
|
||||
async def ban_user_timer(chat_id: int, user_id: int, time: int, bot: Bot):
|
||||
await asyncio.sleep(time)
|
||||
if get_user(user_id) is not None:
|
||||
pass
|
||||
else:
|
||||
await ban_user()
|
||||
|
||||
|
||||
|
||||
|
||||
async def check_new_user(message: Message, bot: Bot):
|
||||
print("check_new_user")
|
||||
if get_telegram_check_bot():
|
||||
# Проверяем наличие пользователя в базе данных
|
||||
|
||||
if get_user(message.from_user.id) is None:
|
||||
# Выдаём пользователю ограничение на отправку сообщений на 3 минуты
|
||||
ban_task = Thread(target=ban_user_timer, args=(message.chat.id, message.from_user.id, 180, bot))
|
||||
ban_task.start()
|
||||
# Создаём задачу с отложенным выполнением на 3 минуты
|
||||
|
||||
math_task = await create_math_task()
|
||||
text = f"{math_task[1]} + {math_task[2]}"
|
||||
builder = InlineKeyboardBuilder()
|
||||
for answer in math_task[3]:
|
||||
if answer == math_task[0]:
|
||||
builder.add(types.InlineKeyboardButton(
|
||||
text=answer,
|
||||
callback_data=f"check_math_task_true")
|
||||
)
|
||||
else:
|
||||
builder.add(types.InlineKeyboardButton(
|
||||
text=answer,
|
||||
callback_data=f"check_math_task_false")
|
||||
)
|
||||
await message.reply(
|
||||
f"Приветствую, {message.from_user.first_name}!\n"
|
||||
f"Для продолжения работы с ботом, пожалуйста, решите математический пример в течении 3х минут:\n"
|
||||
f"*{text}*",
|
||||
reply_markup=builder.as_markup()
|
||||
)
|
||||
|
||||
|
||||
async def math_task_true(message: Message, bot: Bot):
|
||||
await message.reply(f"Верно! Добро пожаловать в чат {message.from_user.first_name}")
|
||||
await unmute_user(message.chat.id, message.from_user.id, bot)
|
||||
add_user(message.from_user.id,
|
||||
message.from_user.first_name + ' ' + message.from_user.last_name,
|
||||
message.from_user.username)
|
||||
pass
|
10
src/modules/standard/welcome/routers.py
Normal file
10
src/modules/standard/welcome/routers.py
Normal file
@ -0,0 +1,10 @@
|
||||
from aiogram import Router, F
|
||||
|
||||
from src.modules.standard.welcome.handlers import check_new_user
|
||||
|
||||
router = Router()
|
||||
|
||||
# Если в чат пришел новый пользователь
|
||||
router.message.register(check_new_user, F.new_chat_members.exists())
|
||||
# Ловин колбеки от кнопок с callback_data=f"check_math_task_true"
|
||||
router.callback_query.register(check_new_user, F.callback_data == "check_math_task_true")
|
Loading…
Reference in New Issue
Block a user