merging telegram to main #1
76 changed files with 3148 additions and 3262 deletions
|
@ -1,5 +1,5 @@
|
|||
__all__ = ["MainModel", "get_async_engine", "get_sessions_maker", "Users", "get_user_info", "generate_url"]
|
||||
__all__ = ["MainModel", "get_async_engine", "get_sessions_maker", "TelegramUsers", "get_user_info", "generate_url"]
|
||||
|
||||
from .main import MainModel
|
||||
from .engine import get_async_engine, get_sessions_maker, generate_url
|
||||
from bozenka.database.tables.telegram import Users, get_user_info
|
||||
from bozenka.database.tables.telegram import TelegramUsers, get_user_info
|
||||
|
|
|
@ -7,7 +7,7 @@ from sqlalchemy.orm import sessionmaker
|
|||
from bozenka.database.main import MainModel
|
||||
|
||||
|
||||
class Users(MainModel):
|
||||
class TelegramUsers(MainModel):
|
||||
"""
|
||||
Telegram users table, contains:
|
||||
|
||||
|
@ -30,7 +30,7 @@ class Users(MainModel):
|
|||
return f"<User:{self.user_id}:{self.chat_id}>"
|
||||
|
||||
|
||||
class ChatSettings(MainModel):
|
||||
class TelegramChatSettings(MainModel):
|
||||
"""
|
||||
Telegram of chat settings table, contains:
|
||||
|
||||
|
@ -69,8 +69,8 @@ async def get_chat_configuration(chat_id: int, session: async_sessionmaker):
|
|||
"""
|
||||
async with session() as session:
|
||||
async with session.begin():
|
||||
(await session.execute(select(ChatSettings).where(ChatSettings.chat_id == chat_id)))
|
||||
return (await session.execute(select(ChatSettings).where(ChatSettings.chat_id == chat_id))).one_or_none()
|
||||
(await session.execute(select(TelegramChatSettings).where(TelegramChatSettings.chat_id == chat_id)))
|
||||
return (await session.execute(select(TelegramChatSettings).where(TelegramChatSettings.chat_id == chat_id))).one_or_none()
|
||||
|
||||
|
||||
async def get_chat_config_value(chat_id: int, session: async_sessionmaker, setting) -> bool:
|
||||
|
@ -83,7 +83,7 @@ async def get_chat_config_value(chat_id: int, session: async_sessionmaker, setti
|
|||
"""
|
||||
async with session() as session:
|
||||
async with session.begin():
|
||||
rows = (await session.execute(select(setting.db_name).where(ChatSettings.chat_id == chat_id))).one()
|
||||
rows = (await session.execute(select(setting).where(TelegramChatSettings.chat_id == chat_id))).one()
|
||||
return rows[0]
|
||||
|
||||
|
||||
|
@ -97,6 +97,6 @@ async def get_user_info(user_id: int, chat_id: int, session: async_sessionmaker)
|
|||
"""
|
||||
async with session() as session:
|
||||
async with session.begin():
|
||||
return (await session.execute(select(Users).where(Users.user_id == user_id and Users.chat_id == chat_id))).one_or_none()
|
||||
return (await session.execute(select(TelegramUsers).where(TelegramUsers.user_id == user_id and TelegramUsers.chat_id == chat_id))).one_or_none()
|
||||
|
||||
|
||||
|
|
3
bozenka/features/__init__.py
Normal file
3
bozenka/features/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from bozenka.features.admin import *
|
||||
from bozenka.features.user import *
|
||||
from bozenka.features.basic import *
|
5
bozenka/features/admin/__init__.py
Normal file
5
bozenka/features/admin/__init__.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
from .invite_generation import Invite
|
||||
from .moderation import Moderation
|
||||
from .msg_pins import Pins
|
||||
from .topics import Threads
|
||||
from .information import ChatInformation
|
51
bozenka/features/admin/information.py
Normal file
51
bozenka/features/admin/information.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
import logging
|
||||
|
||||
from aiogram.filters import Command
|
||||
from aiogram.types import Message
|
||||
|
||||
from bozenka.features.main import BasicFeature
|
||||
from bozenka.instances.telegram.utils.delete import delete_keyboard
|
||||
|
||||
|
||||
class ChatInformation(BasicFeature):
|
||||
"""
|
||||
Shows information about chat by sending one command.
|
||||
(Private, public, etc)
|
||||
"""
|
||||
|
||||
async def telegram_basic_chat_info_handler(msg: Message) -> None:
|
||||
"""
|
||||
Shows information about chat by command `/info`
|
||||
:param msg: Message telegram object
|
||||
:return: None
|
||||
"""
|
||||
logging.log(msg=f"Sending information about chat user_id={msg.from_user.id}",
|
||||
level=logging.INFO)
|
||||
chat = await msg.bot.get_chat(msg.chat.id)
|
||||
# Related texts
|
||||
texts = {
|
||||
"chat_types": {"group": "группой", "supergroup": "cупер группой"},
|
||||
"forum_type": {True: "форумом,", False: ", не является форумом,", None: ", не является форумом,"},
|
||||
"required_invite": {True: "требуется одобрение заявки на вступление", False: "заявка не требуется.",
|
||||
None: "заявка не требуется."},
|
||||
"hidden_members": {True: "присуствуют", False: "отсуствуют", None: "отсуствуют"},
|
||||
"isprotected": {True: "пересылать сообщения из группы можно.",
|
||||
False: "пересылать сообщения из группы нельзя.",
|
||||
None: "пересылать сообщения из группы можно."},
|
||||
}
|
||||
|
||||
await msg.answer(f"{chat.title}, {chat.get_member_count()} пользователей\n"
|
||||
f"{chat.description}\n\n"
|
||||
f"Является {texts['chat_types'][chat.type]} {texts['forum_type'][chat.is_forum]} {texts['required_invite'][chat.join_by_request]}\n"
|
||||
f"Скрытые пользователи {texts['hidden_members'][chat.has_hidden_members]}, {texts['isprotected'][chat.has_protected_content]}",
|
||||
reply_markup=delete_keyboard(admin_id=msg.from_user.id))
|
||||
|
||||
telegram_commands: dict[str: str] = {
|
||||
'info': 'Get information about chat'
|
||||
}
|
||||
telegram_cmd_avaible = True
|
||||
|
||||
# All handlers to register automaticly by bozenka
|
||||
telegram_message_handlers = [
|
||||
[telegram_basic_chat_info_handler, [Command(commands="info")]]
|
||||
]
|
93
bozenka/features/admin/invite_generation.py
Normal file
93
bozenka/features/admin/invite_generation.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
import logging
|
||||
|
||||
from aiogram.enums import ChatMemberStatus
|
||||
from aiogram.filters import Command
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
|
||||
|
||||
from bozenka.database.tables.telegram import TelegramChatSettings
|
||||
from bozenka.features.main import BasicFeature
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import RevokeCallbackData, DeleteMenu
|
||||
|
||||
|
||||
# Invite keyboard
|
||||
def invite_telegram_keyboard(invite_link: str, admin_id: int, chat_name: str) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for /invite command. Should be reworked.
|
||||
:param invite_link: Invite link to chat
|
||||
:param admin_id: User_id of telegram administrator
|
||||
:param chat_name: Name of group chat
|
||||
:return: Nothing
|
||||
"""
|
||||
invite_revoke_link = invite_link.replace("https://", "")
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text=chat_name, url=invite_link)],
|
||||
[InlineKeyboardButton(text="Отозвать 🛠️",
|
||||
callback_data=RevokeCallbackData(admin_id=admin_id, link=invite_revoke_link).pack())],
|
||||
[InlineKeyboardButton(text="Спасибо ✅",
|
||||
callback_data=DeleteMenu(user_id_clicked=str(admin_id)).pack())]])
|
||||
return kb
|
||||
|
||||
|
||||
class Invite(BasicFeature):
|
||||
"""
|
||||
A class with information about invite feature
|
||||
All codes will be here
|
||||
"""
|
||||
|
||||
async def telegram_invite_command_handler(msg: Message) -> None:
|
||||
"""
|
||||
Generating invite to group by /invite command
|
||||
:param msg: Message telegram object
|
||||
:return: None
|
||||
"""
|
||||
logging.log(msg=f"Generating invite for user_id={msg.from_user.id}",
|
||||
level=logging.INFO)
|
||||
link = await msg.chat.create_invite_link()
|
||||
|
||||
await msg.answer(
|
||||
f"<em> Держите ваше приглашение в чат, {msg.from_user.mention_html('пользователь')} 👋</em>",
|
||||
reply_markup=invite_telegram_keyboard(invite_link=str(link.invite_link), admin_id=msg.from_user.id,
|
||||
chat_name=msg.chat.full_name)
|
||||
)
|
||||
|
||||
async def telegram_revoke_callback_handler(call: CallbackQuery, callback_data: RevokeCallbackData) -> None:
|
||||
"""
|
||||
Handler of CallbackQuery, revokes link after pressing button
|
||||
:param call: CallbackQuery aioram object
|
||||
:param callback_data: RevokeCallbackData object
|
||||
:return: Nothing
|
||||
"""
|
||||
user_clicked = await call.message.chat.get_member(call.from_user.id)
|
||||
|
||||
if callback_data.admin_id != call.from_user.id and \
|
||||
user_clicked.status != ChatMemberStatus.ADMINISTRATOR and user_clicked.status == ChatMemberStatus.CREATOR:
|
||||
return
|
||||
logging.log(msg=f"Revoking link for user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
await call.message.chat.revoke_invite_link(invite_link="https://" + str(callback_data.link))
|
||||
await call.answer("Удача ✅")
|
||||
await call.message.delete()
|
||||
|
||||
"""
|
||||
Telegram feature settings
|
||||
"""
|
||||
# Telegram setting info
|
||||
telegram_setting_in_list = True
|
||||
telegram_setting_name = "Приглашения в Чат ✉"
|
||||
telegram_setting_description = "<b>Генератор приглашения в Чат ✉</b>\n" \
|
||||
"Разрешает использование комманды <code>/invite</code> в чате, для созданния приглашений.\n" \
|
||||
"Для исполнения <b>требует соответсвующих прав от пользователя и их наличие у бота.</b>"
|
||||
telegram_db_name = TelegramChatSettings.invite_generator
|
||||
telegram_category = "admin"
|
||||
# Telegram commands
|
||||
telegram_commands: dict[str: str] = {"/invite": 'Generates invite into current chat'}
|
||||
telegram_cmd_avaible = True # Is a feature have a commands
|
||||
# List of aiogram handlers
|
||||
telegram_message_handlers = [
|
||||
# Format is [Handler, [Filters]]
|
||||
[telegram_invite_command_handler, [Command(commands=["invite"])]]
|
||||
]
|
||||
telegram_callback_handlers = [
|
||||
# Format is [Handler, [Filters]]
|
||||
[telegram_revoke_callback_handler, [RevokeCallbackData.filter()]]
|
||||
]
|
607
bozenka/features/admin/moderation.py
Normal file
607
bozenka/features/admin/moderation.py
Normal file
|
@ -0,0 +1,607 @@
|
|||
import logging
|
||||
|
||||
from aiogram import F
|
||||
from aiogram.enums import ChatMemberStatus, ChatType
|
||||
from aiogram.filters import CommandObject, Command
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.database.tables.telegram import get_chat_config_value, TelegramChatSettings
|
||||
from bozenka.features.main import BasicFeature
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import UnbanData, BanData, UnmuteData, MuteData, DeleteMenu
|
||||
from bozenka.instances.telegram.filters import IsAdminFilter, BotHasPermissions, UserHasPermissions
|
||||
from bozenka.instances.telegram.utils.delete import delete_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
|
||||
|
||||
|
||||
# Ban / Unban keyboards
|
||||
def telegram_ban_user_keyboard(admin_id: int, ban_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for /ban command.
|
||||
:param admin_id: User_id of administrator in group chat
|
||||
:param ban_id: User_id of banned member
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteMenu(user_id_clicked=str(admin_id)).pack())
|
||||
], [
|
||||
InlineKeyboardButton(text="Разбанить 🛠️", callback_data=UnbanData(user_id_unban=str(ban_id),
|
||||
user_id_clicked=str(admin_id)).pack())
|
||||
]])
|
||||
return kb
|
||||
|
||||
|
||||
def telegram_unban_user_keyboard(admin_id: int, unban_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for /unban command.
|
||||
:param admin_id: User_id of administrator in group chat
|
||||
:param unban_id: User_id of unbanned member
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
print(unban_id)
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteMenu(user_id_clicked=str(admin_id)).pack())
|
||||
], [
|
||||
InlineKeyboardButton(text="Забанить 🛠️", callback_data=BanData(user_id_ban=str(unban_id),
|
||||
user_id_clicked=str(admin_id)).pack())
|
||||
]])
|
||||
return kb
|
||||
|
||||
|
||||
# Mute / Unmute keyboards
|
||||
def telegram_mute_user_keyboard(admin_id: int, mute_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for /mute command.
|
||||
:param admin_id: User_id of administrator in group chat
|
||||
:param mute_id: User_id of restricted member
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Спасибо ✅",
|
||||
callback_data=DeleteMenu(user_id_clicked=str(admin_id)).pack())],
|
||||
[InlineKeyboardButton(text="Размутить 🛠️",
|
||||
callback_data=UnmuteData(user_id_unmute=mute_id, user_id_clicked=admin_id).pack())]])
|
||||
return kb
|
||||
|
||||
|
||||
def telegram_unmute_user_keyboard(admin_id: int, unmute_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for /unmute command.
|
||||
:param admin_id: User_id of administrator in group chat
|
||||
:param unmute_id: User_id of unrestricted member
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Спасибо ✅",
|
||||
callback_data=DeleteMenu(user_id_clicked=str(admin_id)).pack())],
|
||||
[InlineKeyboardButton(text="Замутить 🛠️",
|
||||
callback_data=MuteData(user_id_mute=unmute_id, user_id_clicked=admin_id).pack())]])
|
||||
return kb
|
||||
|
||||
|
||||
class Moderation(BasicFeature):
|
||||
"""
|
||||
A class of moderation related feature
|
||||
All staff related to it will be here
|
||||
"""
|
||||
|
||||
async def telegram_ban_callback_handler(call: CallbackQuery, callback_data: BanData,
|
||||
session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
CallbackQuery handler, what bannes users after callback
|
||||
:param call: CallBackQuery telegram object
|
||||
:param callback_data: BanData object
|
||||
:param session_maker: AsyncSessionmaker object
|
||||
:return: None
|
||||
"""
|
||||
clicked_user = await call.message.chat.get_member(call.from_user.id)
|
||||
banned_user = await call.message.chat.get_member(int(callback_data.user_id_ban))
|
||||
|
||||
send_notification = await get_chat_config_value(chat_id=call.message.chat.id, session=session_maker,
|
||||
setting=TelegramChatSettings.restrict_notification)
|
||||
|
||||
if call.from_user.id != callback_data.user_id_clicked \
|
||||
and clicked_user.status not in [ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.CREATOR]:
|
||||
return
|
||||
await SolutionSimpler.inline_ban_user(call=call, data=callback_data, session=session_maker)
|
||||
|
||||
if not banned_user.is_member and banned_user.status == ChatMemberStatus.KICKED:
|
||||
await call.answer("Уже заблокирован ✅")
|
||||
else:
|
||||
await call.answer("Успешно заблокирован ✅")
|
||||
|
||||
await call.message.edit_text(
|
||||
"Удача ✅\n"
|
||||
f"{banned_user.user.mention_html('Этот пользователь')} был заблокирован {call.from_user.mention_html('этим пользователем')}.",
|
||||
reply_markup=telegram_ban_user_keyboard(admin_id=call.from_user.id, ban_id=banned_user.user.id)
|
||||
)
|
||||
|
||||
if send_notification:
|
||||
await call.message.bot.send_message(
|
||||
chat_id=banned_user.user.id,
|
||||
text=f"{banned_user.user.mention_html('Вы')} были заблокированы {call.from_user.mention_html('этим пользователем')} в чате <code>{call.message.chat.id}</code>.",
|
||||
reply_markup=delete_keyboard(admin_id=banned_user.user.id)
|
||||
)
|
||||
|
||||
logging.log(msg=f"Banned user @{banned_user.user.full_name} user_id=f{banned_user.user.id}", level=logging.INFO)
|
||||
|
||||
async def telegram_unban_callback_handler(call: CallbackQuery, callback_data: UnbanData,
|
||||
session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
CallbackQuery handler, what unbannes users after callback
|
||||
:param call: CallBackQuery telegram object
|
||||
:param callback_data: UnbanData object
|
||||
:param session_maker: AsyncSessionmaker object
|
||||
:return: None
|
||||
"""
|
||||
clicked_user = await call.message.chat.get_member(call.from_user.id)
|
||||
unbanned_user = await call.message.chat.get_member(int(callback_data.user_id_unban))
|
||||
|
||||
if call.from_user.id != callback_data.user_id_clicked \
|
||||
and clicked_user.status not in [ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.CREATOR]:
|
||||
return
|
||||
|
||||
await SolutionSimpler.inline_unban_user(call=call, data=callback_data, session=session_maker)
|
||||
|
||||
if unbanned_user.is_member and unbanned_user.status != ChatMemberStatus.KICKED:
|
||||
await call.answer("Уже разблокирован ✅")
|
||||
else:
|
||||
await call.answer("Успешно разблокирован ✅")
|
||||
await call.message.edit_text(
|
||||
"Удача ✅\n"
|
||||
f"{unbanned_user.user.mention_html('Этот пользователь')} был разблокирован {call.from_user.mention_html('этим пользователем')}.",
|
||||
reply_markup=telegram_unban_user_keyboard(admin_id=call.from_user.id, unban_id=unbanned_user.user.id)
|
||||
)
|
||||
|
||||
if await get_chat_config_value(chat_id=call.message.chat.id, session=session_maker,
|
||||
setting=TelegramChatSettings.restrict_notification):
|
||||
await call.message.bot.send_message(
|
||||
chat_id=unbanned_user.user.id,
|
||||
text=f"{unbanned_user.user.mention_html('Вы')} были разблокирован {call.from_user.mention_html('этим пользователем')} в чате <code>{call.message.chat.id}</code>.",
|
||||
reply_markup=delete_keyboard(admin_id=unbanned_user.user.id)
|
||||
)
|
||||
|
||||
logging.log(msg=f"Unbanned user @{unbanned_user.user.full_name} user_id=f{unbanned_user.user.id}",
|
||||
level=logging.INFO)
|
||||
|
||||
async def telegram_ban_cmd_handler(msg: Message, command: CommandObject, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
/ban command function, supports time and reasons.
|
||||
:param msg: Message telegram object
|
||||
:param command: Object of telegram command
|
||||
:param session_maker: Session maker object of SqlAlchemy
|
||||
:return: Nothing
|
||||
"""
|
||||
banned_user = await msg.chat.get_member(msg.reply_to_message.from_user.id)
|
||||
send_to_dm = await get_chat_config_value(chat_id=msg.chat.id, session=session_maker,
|
||||
setting=TelegramChatSettings.results_in_dm)
|
||||
send_notification = await get_chat_config_value(chat_id=msg.chat.id, session=session_maker,
|
||||
setting=TelegramChatSettings.restrict_notification)
|
||||
|
||||
where_send = {
|
||||
True: msg.from_user.id,
|
||||
False: msg.chat.id
|
||||
}
|
||||
|
||||
if banned_user.status == ChatMemberStatus.KICKED:
|
||||
await msg.bot.send_message(chat_id=where_send[send_to_dm],
|
||||
text="Ошибка ❌\n"
|
||||
"Этот пользователь уже удален из группы",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
return
|
||||
|
||||
config = await SolutionSimpler.ban_user(msg, command, session_maker)
|
||||
if config["reason"] and config["ban_time"]:
|
||||
await msg.bot.send_message(chat_id=where_send[send_to_dm],
|
||||
text="Удача ✅\n"
|
||||
f"{msg.reply_to_message.from_user.mention_html('Этот пользователь')} "
|
||||
f"был заблокирован {msg.from_user.mention_html('этим пользователем')}.\n"
|
||||
f"По причине <code>{config['reason']}</code>, до даты <code>{config['ban_time']}</code>",
|
||||
reply_markup=telegram_ban_user_keyboard(msg.from_user.id, msg.reply_to_message.from_user.id))
|
||||
if send_notification:
|
||||
await msg.bot.send_message(chat_id=banned_user.user.id,
|
||||
text="Вы "
|
||||
f"были заблокированы {msg.from_user.mention_html('этим пользователем')} в чате <code>{msg.chat.title}</code>.\n"
|
||||
f"По причине <code>{config['reason']}, до даты <code>{config['ban_time']}</code>",
|
||||
reply_markup=delete_keyboard(admin_id=banned_user.user.id))
|
||||
elif config["reason"]:
|
||||
await msg.bot.send_message(chat_id=where_send[send_to_dm],
|
||||
text="Удача ✅\n"
|
||||
f"{msg.reply_to_message.from_user.mention_html('Этот пользователь')} "
|
||||
f"был заблокирован {msg.reply_to_message.from_user.mention_html('этим пользователем')}.\n"
|
||||
f"По причине <code>{config['reason']}</code>.",
|
||||
reply_markup=telegram_ban_user_keyboard(admin_id=msg.from_user.id,
|
||||
ban_id=msg.reply_to_message.from_user.id))
|
||||
if send_notification:
|
||||
await msg.bot.send_message(chat_id=banned_user.user.id,
|
||||
text=f"Вы "
|
||||
f"были заблокированы {msg.from_user.mention_html('этим пользователем')} в чате <code>{msg.chat.title}</code>.\n"
|
||||
f"По причине <code>{config['reason']}</code>.",
|
||||
reply_markup=delete_keyboard(admin_id=banned_user.user.id))
|
||||
elif config["ban_time"]:
|
||||
await msg.bot.send_message(chat_id=where_send[send_to_dm],
|
||||
text="Удача ✅\n"
|
||||
f"{msg.reply_to_message.from_user.mention_html('Этот пользователь')} "
|
||||
f"был заблокирован {msg.from_user.mention_html('этим пользователем')}, до даты <code>{config['ban_time']}</code>",
|
||||
reply_markup=telegram_ban_user_keyboard(admin_id=msg.from_user.id,
|
||||
ban_id=msg.reply_to_message.from_user.id))
|
||||
if send_notification:
|
||||
await msg.bot.send_message(chat_id=banned_user.user.id,
|
||||
text=f"Вы "
|
||||
f"были заблокированы {msg.from_user.mention_html('этим пользователем')} в чате <code>{msg.chat.title}</code>.\n"
|
||||
f"До даты <code>{config['ban_time']}</code>.",
|
||||
reply_markup=delete_keyboard(admin_id=banned_user.user.id))
|
||||
else:
|
||||
await msg.bot.send_message(chat_id=where_send[send_to_dm],
|
||||
text="Удача ✅\n"
|
||||
f"{msg.reply_to_message.from_user.mention_html('Этот пользователь')}"
|
||||
f" был заблокирован {msg.from_user.mention_html('этим пользователем')}.",
|
||||
reply_markup=telegram_ban_user_keyboard(msg.from_user.id, msg.reply_to_message.from_user.id))
|
||||
if send_notification:
|
||||
await msg.bot.send_message(chat_id=banned_user.user.id,
|
||||
text=f"Вы "
|
||||
f"были заблокированы {msg.from_user.mention_html('этим пользователем')} в чате "
|
||||
f"<code>{msg.chat.title}</code>.\n",
|
||||
reply_markup=delete_keyboard(admin_id=banned_user.user.id))
|
||||
|
||||
async def telegram_unban_cmd_handler(msg: Message, command: CommandObject,
|
||||
session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
/unban command function
|
||||
:param msg: Message telegram object
|
||||
:param command: Object of telegram command
|
||||
:param session_maker: Session maker object of SqlAlchemy
|
||||
"""
|
||||
await SolutionSimpler.unban_user(msg, session_maker)
|
||||
|
||||
unbanned_user = await msg.chat.get_member(msg.reply_to_message.from_user.id)
|
||||
send_to_dm = await get_chat_config_value(chat_id=msg.chat.id, session=session_maker,
|
||||
setting=TelegramChatSettings.results_in_dm)
|
||||
send_notification = await get_chat_config_value(chat_id=msg.chat.id, session=session_maker,
|
||||
setting=TelegramChatSettings.restrict_notification)
|
||||
|
||||
where_send = {
|
||||
True: msg.from_user.id,
|
||||
False: msg.chat.id
|
||||
}
|
||||
|
||||
if unbanned_user.is_member and unbanned_user.status != ChatMemberStatus.KICKED:
|
||||
await msg.bot.send_message(
|
||||
chat_id=where_send[send_to_dm],
|
||||
text="Ошибка ❌\n"
|
||||
"Этот пользователь не находится в бане.",
|
||||
reply_markup=delete_keyboard(admin_id=msg.from_user.id)
|
||||
)
|
||||
return
|
||||
elif not command.text:
|
||||
await msg.bot.send_message(
|
||||
chat_id=where_send[send_to_dm],
|
||||
text="Удача ✅\n"
|
||||
f"{msg.reply_to_message.from_user.mention_html('Этот пользователь')} был разблокирован "
|
||||
f"{msg.from_user.mention_html('этим пользователем')}.\n",
|
||||
reply_markup=telegram_unban_user_keyboard(admin_id=msg.from_user.id, unban_id=msg.reply_to_message.from_user.id)
|
||||
)
|
||||
if send_notification:
|
||||
await msg.bot.send_message(
|
||||
chat_id=unbanned_user.user.id,
|
||||
text=f"{msg.reply_to_message.from_user.mention_html('Вы')} "
|
||||
f"был разблокированы {msg.from_user.mention_html('этим пользователем')} в чате <code>{msg.chat.title}</code>.\n",
|
||||
reply_markup=delete_keyboard(admin_id=unbanned_user.user.id)
|
||||
)
|
||||
else:
|
||||
await msg.bot.send_message(
|
||||
chat_id=where_send[send_to_dm],
|
||||
text="Удача ✅\n"
|
||||
f"Пользователь {msg.reply_to_message.from_user.mention_html()} был разблокирован пользователем {msg.from_user.mention_html()}.\n"
|
||||
f"По причине {CommandObject.text}.",
|
||||
reply_markup=delete_keyboard(admin_id=unbanned_user.user.id)
|
||||
)
|
||||
if send_notification:
|
||||
await msg.bot.send_message(
|
||||
chat_id=unbanned_user.user.id,
|
||||
text=f"{msg.reply_to_message.from_user.mention_html('Вы')} "
|
||||
f"был разблокированы {msg.from_user.mention_html('этим пользователем')} в чате <code>{msg.chat.title}</code>.\n"
|
||||
f"По причине <code>{CommandObject.text}</code>",
|
||||
reply_markup=delete_keyboard(admin_id=unbanned_user.user.id)
|
||||
)
|
||||
|
||||
async def telegram_mute_callback_handler(call: CallbackQuery, callback_data: MuteData,
|
||||
session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Query, what mutes users after callback
|
||||
:param call: CallBackQuery telegram object
|
||||
:param callback_data: BanData object
|
||||
:param session_maker: AsyncSessionmaker object
|
||||
:return:
|
||||
"""
|
||||
clicked_user = await call.message.chat.get_member(call.from_user.id)
|
||||
muted_user = await call.message.chat.get_member(int(callback_data.user_id_mute))
|
||||
|
||||
if call.from_user.id != callback_data.user_id_clicked \
|
||||
and clicked_user.status not in [ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.CREATOR]:
|
||||
return
|
||||
await SolutionSimpler.inline_mute_user(call=call, data=callback_data, session=session_maker)
|
||||
|
||||
if not muted_user.can_send_messages and muted_user.status == ChatMemberStatus.RESTRICTED:
|
||||
await call.answer("Уже замучен ✅")
|
||||
else:
|
||||
await call.answer("Успешно замучен ✅")
|
||||
|
||||
await call.message.edit_text(
|
||||
"Удача ✅\n"
|
||||
f"{muted_user.user.mention_html('Этот пользователь')} был замучен {call.from_user.mention_html('этим пользователем')}.",
|
||||
reply_markup=telegram_mute_user_keyboard(admin_id=call.from_user.id, mute_id=callback_data.user_id_mute)
|
||||
)
|
||||
|
||||
send_notification = await get_chat_config_value(chat_id=call.message.chat.id, session=session_maker,
|
||||
setting=TelegramChatSettings.restrict_notification)
|
||||
if send_notification:
|
||||
await call.message.bot.send_message(
|
||||
chat_id=muted_user.user.id,
|
||||
text=f"{muted_user.user.mention_html('Вы')} были замучены {call.from_user.mention_html('этим пользователем')} в чате <code>{call.message.chat.id}</code>.",
|
||||
reply_markup=delete_keyboard(admin_id=muted_user.user.id)
|
||||
)
|
||||
|
||||
logging.log(msg=f"Muted user @{muted_user.user.full_name} user_id=f{muted_user.user.id}", level=logging.INFO)
|
||||
|
||||
async def telegram_unmute_callback_handler(call: CallbackQuery, callback_data: UnmuteData,
|
||||
session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Query, what unbannes users after callback
|
||||
:param call: CallBackQuery telegram object
|
||||
:param callback_data: UnbanData object
|
||||
:param session_maker: AsyncSessionmaker object
|
||||
:return:
|
||||
"""
|
||||
clicked_user = await call.message.chat.get_member(call.from_user.id)
|
||||
unmuted_user = await call.message.chat.get_member(int(callback_data.user_id_unmute))
|
||||
if call.from_user.id != callback_data.user_id_clicked \
|
||||
and clicked_user.status not in [ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.CREATOR]:
|
||||
return
|
||||
|
||||
await SolutionSimpler.inline_unmute_user(call=call, data=callback_data, session=session_maker)
|
||||
|
||||
if unmuted_user.can_send_messages or unmuted_user.status == ChatMemberStatus.RESTRICTED:
|
||||
await call.answer("Уже размучен ✅")
|
||||
else:
|
||||
await call.answer("Успешно размучен ✅")
|
||||
await call.message.edit_text(
|
||||
"Удача ✅\n"
|
||||
f"{unmuted_user.user.mention_html('Этот пользователь')} был размучен {call.from_user.mention_html('этим пользователем')}.",
|
||||
reply_markup=telegram_unmute_user_keyboard(admin_id=call.from_user.id, unmute_id=unmuted_user.user.id)
|
||||
)
|
||||
|
||||
send_notification = await get_chat_config_value(chat_id=call.message.chat.id, session=session_maker,
|
||||
setting=TelegramChatSettings.restrict_notification)
|
||||
if send_notification:
|
||||
await call.message.bot.send_message(
|
||||
chat_id=unmuted_user.user.id,
|
||||
text=f"{unmuted_user.user.mention_html('Вы')} были размучены {call.from_user.mention_html('этим пользователем')} в чате <code>{call.message.chat.id}</code>.",
|
||||
reply_markup=delete_keyboard(admin_id=unmuted_user.user.id)
|
||||
)
|
||||
|
||||
logging.log(msg=f"Unbanned user @{unmuted_user.user.full_name} user_id=f{unmuted_user.user.id}",
|
||||
level=logging.INFO)
|
||||
|
||||
async def telegram_mute_cmd_handler(msg: Message, command: CommandObject,
|
||||
session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Handler of command /mute
|
||||
Restricts member from using chat
|
||||
:param msg: Message telegram object
|
||||
:param command: Object of telegram command
|
||||
:param session_maker: Session maker object of SqlAlchemy
|
||||
:return: Nothing
|
||||
"""
|
||||
mute_user = await msg.chat.get_member(msg.reply_to_message.from_user.id)
|
||||
|
||||
send_to_dm = await get_chat_config_value(chat_id=msg.chat.id, session=session_maker,
|
||||
setting=TelegramChatSettings.results_in_dm)
|
||||
send_notification = await get_chat_config_value(chat_id=msg.chat.id, session=session_maker,
|
||||
setting=TelegramChatSettings.restrict_notification)
|
||||
|
||||
where_send = {
|
||||
True: msg.from_user.id,
|
||||
False: msg.chat.id
|
||||
}
|
||||
|
||||
if mute_user.status == ChatMemberStatus.LEFT or mute_user.status == ChatMemberStatus.KICKED:
|
||||
return
|
||||
config = await SolutionSimpler.mute_user(msg, command, session_maker)
|
||||
if config["mute_time"] and config["reason"] != "":
|
||||
await msg.bot.send_message(
|
||||
chat_id=where_send[send_to_dm],
|
||||
text="Удача ✅\n"
|
||||
f"{msg.from_user.mention_html('Этот пользователь')} запретил писать "
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('этому пользователю')}.\n"
|
||||
f"По причине <code>{config['reason']}</code>, до даты <code>{config['mute_time']}</code>",
|
||||
reply_markup=telegram_mute_user_keyboard(msg.from_user.id, mute_user.user.id))
|
||||
if send_notification:
|
||||
await msg.bot.send_message(
|
||||
chat_id=mute_user.user.id,
|
||||
text=f"{msg.from_user.mention_html('Этот пользователь')} запретил писать "
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('вам')} в чате {msg.chat.title}.\n"
|
||||
f"По причине <code>{config['reason']}</code>, до даты <code>{config['mute_time']}</code>",
|
||||
reply_markup=delete_keyboard(admin_id=mute_user.user.id))
|
||||
|
||||
elif config["reason"] != "":
|
||||
await msg.bot.send_message(
|
||||
chat_id=where_send[send_to_dm],
|
||||
text="Удача ✅\n"
|
||||
f"{msg.from_user.mention_html('Этот пользователь')} запретил писать "
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('этому пользователю')}.\n"
|
||||
f"По причине <code>{config['reason']}</code>.",
|
||||
reply_markup=telegram_mute_user_keyboard(msg.from_user.id, mute_user.user.id))
|
||||
if send_notification:
|
||||
await msg.bot.send_message(
|
||||
chat_id=mute_user.user.id,
|
||||
text=f"{msg.from_user.mention_html('Этот пользователь')} запретил писать "
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('вам')} в чате {msg.chat.title}.\n"
|
||||
f"По причине <code>{config['reason']}</code>.",
|
||||
reply_markup=delete_keyboard(admin_id=mute_user.user.id))
|
||||
elif config["mute_time"]:
|
||||
await msg.bot.send_message(
|
||||
chat_id=where_send[send_to_dm],
|
||||
text="Удача ✅\n"
|
||||
f"{msg.from_user.mention_html('Этот пользователь')} запретил писать "
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('этому пользователю')}.\n"
|
||||
f"До даты <code>{config['mute_time']}</code>",
|
||||
reply_markup=telegram_mute_user_keyboard(msg.from_user.id, mute_user.user.id))
|
||||
if send_notification:
|
||||
await msg.bot.send_message(
|
||||
chat_id=mute_user.user.id,
|
||||
text=f"{msg.from_user.mention_html('Этот пользователь')} запретил писать "
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('вам')} в чате {msg.chat.title}.\n"
|
||||
f"До даты <code>{config['mute_time']}</code>",
|
||||
reply_markup=delete_keyboard(admin_id=mute_user.user.id))
|
||||
else:
|
||||
await msg.bot.send_message(
|
||||
chat_id=where_send[send_to_dm],
|
||||
text="Удача ✅\n"
|
||||
f"{msg.from_user.mention_html('Этот пользователь')} запретил писать "
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('этому пользователю')}.\n",
|
||||
reply_markup=telegram_mute_user_keyboard(msg.from_user.id, mute_user.user.id))
|
||||
if send_notification:
|
||||
await msg.bot.send_message(
|
||||
chat_id=mute_user.user.id,
|
||||
text=f"{msg.from_user.mention_html('Этот пользователь')} запретил писать "
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('вам')} в чате {msg.chat.title}.\n",
|
||||
reply_markup=delete_keyboard(admin_id=mute_user.user.id))
|
||||
|
||||
async def telegram_unmute_cmd_handler(msg: Message, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Handler of command /unmute
|
||||
Gives access member to send messages into chat
|
||||
:param msg: Message telegram object
|
||||
:param session_maker: Session maker object of SqlAlchemy
|
||||
:return: Nothing
|
||||
"""
|
||||
await SolutionSimpler.unmute_user(msg, session_maker)
|
||||
|
||||
send_to_dm = await get_chat_config_value(chat_id=msg.chat.id, session=session_maker,
|
||||
setting=TelegramChatSettings.results_in_dm)
|
||||
send_notification = await get_chat_config_value(chat_id=msg.chat.id, session=session_maker,
|
||||
setting=TelegramChatSettings.restrict_notification)
|
||||
|
||||
where_send = {
|
||||
True: msg.from_user.id,
|
||||
False: msg.chat.id
|
||||
}
|
||||
|
||||
await msg.bot.send_message(
|
||||
user_id=where_send[send_to_dm],
|
||||
text="Удача ✅"
|
||||
f"{msg.from_user.mention_html('Этот пользователь')} разрешил писать\n"
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('этому пользователю')}",
|
||||
reply_markup=telegram_unmute_user_keyboard(msg.from_user.id, msg.reply_to_message.from_user.id))
|
||||
if send_notification:
|
||||
await msg.bot.send_message(
|
||||
user_id=msg.reply_to_message.from_user.id,
|
||||
text=f"{msg.from_user.mention_html('Этот пользователь')} разрешил писать\n"
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('вам')}",
|
||||
reply_markup=delete_keyboard(admin_id=msg.reply_to_message.from_user.id))
|
||||
|
||||
# Help moderation telegram
|
||||
# Code part
|
||||
async def telegram_help_ban_handler(msg: Message) -> None:
|
||||
"""
|
||||
Shows help message for /ban
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("Использование:\n"
|
||||
"<pre>/ban [время блокировки] [причина блокировки]</pre>\n"
|
||||
"Ответьте на сообщение, чтобы заблокировать пользователя",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
async def telegram_help_unban_handler(msg: Message) -> None:
|
||||
"""
|
||||
Shows help message for /unban
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("Использование:\n"
|
||||
"<pre>/unban</pre>\n"
|
||||
"Ответьте на сообщение, чтобы разблокировать пользователя",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
async def telegram_help_mute_handler(msg: Message) -> None:
|
||||
"""
|
||||
Shows help message for /mute
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("Использование:\n"
|
||||
"<pre>/mute [время мута] [причина мута]</pre>\n"
|
||||
"Ответьте на сообщение, чтобы замутить пользователя",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
async def telegram_help_unmute_handler(msg: Message) -> None:
|
||||
"""
|
||||
Shows help message for /unmute
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("Использование:\n"
|
||||
"<pre>/unmute</pre>\n"
|
||||
"Ответьте на сообщение, чтобы замутить пользователя",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
telegram_setting_in_list = True
|
||||
telegram_setting_name = "Модерация чата 🕵️"
|
||||
telegram_setting_description = "<b>Модерация чата</b>🕵️\nДанная настройка включает следущие комманды:" \
|
||||
"\n<pre>/ban [время блокировки] [причина блокировки] - блокировка пользователя" \
|
||||
"\n/unban - разблокировка пользователя\n" \
|
||||
"/mute [время мута] [причина мута] - мут пользователя\n" \
|
||||
"/unmute - Размут пользователя</pre>\n" \
|
||||
"Время обозначается как:" \
|
||||
"<pre>1h - один час, " \
|
||||
"1d - один день, " \
|
||||
"1m - одна минута, " \
|
||||
"1s - одна секунда</pre>\n" \
|
||||
"Для того, " \
|
||||
"чтобы выполнить одну из комманд по отношению к пользователю, " \
|
||||
"ответьте на сообщение пользователя и используйте команду\n" \
|
||||
"Для исполнения <b>требует соответсвующих прав от пользователя и их наличие у бота.</b>"
|
||||
telegram_db_name = TelegramChatSettings.moderation
|
||||
telegram_category = "admin"
|
||||
# Telegram commands
|
||||
telegram_commands: dict[str: str] = {
|
||||
"ban": "Command to ban user in chat",
|
||||
"unban": "Command to unban user in chat",
|
||||
"mute": "Command to mute user in chat",
|
||||
"unmute": "Command to unmute user in chat",
|
||||
}
|
||||
telegram_cmd_avaible = True # Is a feature have a commands
|
||||
# All handlers
|
||||
telegram_message_handlers = [
|
||||
# Format is [Handler, [Filters]]
|
||||
[telegram_ban_cmd_handler, [Command(commands="ban"),
|
||||
IsAdminFilter(True, True), F.reply_to_message.text,
|
||||
~(F.chat.type == ChatType.PRIVATE)]],
|
||||
[telegram_unban_cmd_handler, [Command(commands="unban"),
|
||||
IsAdminFilter(True, True), F.reply_to_message.text,
|
||||
~(F.chat.type == ChatType.PRIVATE)]],
|
||||
[telegram_mute_cmd_handler, [Command(commands=["mute", "re"]),
|
||||
UserHasPermissions(["can_restrict_members"]),
|
||||
BotHasPermissions(["can_restrict_members"]), ~(F.chat.type == ChatType.PRIVATE), F.reply_to_message.text]],
|
||||
[telegram_unmute_cmd_handler, [Command(commands=["unmute"]),
|
||||
UserHasPermissions(["can_restrict_members"]),
|
||||
BotHasPermissions(["can_restrict_members"]),
|
||||
~(F.chat.type == ChatType.PRIVATE), F.reply_to_message.text]],
|
||||
[telegram_help_ban_handler,
|
||||
[Command(commands="ban"), IsAdminFilter(True, True), ~(F.chat.type == ChatType.PRIVATE)]],
|
||||
[telegram_help_unban_handler,
|
||||
[Command(commands="unban"), IsAdminFilter(True, True), ~(F.chat.type == ChatType.PRIVATE)]],
|
||||
[telegram_help_mute_handler, [Command(commands=["mute", "re"]), UserHasPermissions(["can_restrict_members"]),
|
||||
BotHasPermissions(["can_restrict_members"]), ~(F.chat.type == ChatType.PRIVATE)]],
|
||||
[telegram_help_unmute_handler,
|
||||
[Command(commands="unmute"), ~(F.chat.type == ChatType.PRIVATE), UserHasPermissions(["can_restrict_members"]),
|
||||
BotHasPermissions(["can_restrict_members"])]]
|
||||
]
|
||||
telegram_callback_handlers = [
|
||||
# Format is [Handler, [Filters]]
|
||||
[telegram_ban_callback_handler, [BanData.filter()]],
|
||||
[telegram_unban_callback_handler, [UnbanData.filter()]],
|
||||
[telegram_mute_callback_handler, [MuteData.filter()]],
|
||||
[telegram_unmute_callback_handler, [UnmuteData.filter()]]]
|
182
bozenka/features/admin/msg_pins.py
Normal file
182
bozenka/features/admin/msg_pins.py
Normal file
|
@ -0,0 +1,182 @@
|
|||
from aiogram import F
|
||||
from aiogram.enums import ChatType
|
||||
from aiogram.filters import Command
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
|
||||
|
||||
from bozenka.database.tables.telegram import TelegramChatSettings
|
||||
from bozenka.features.main import BasicFeature
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import PinMsg, UnpinMsg, DeleteMenu
|
||||
from bozenka.instances.telegram.filters import UserHasPermissions, BotHasPermissions, IsAdminFilter
|
||||
from bozenka.instances.telegram.utils.delete import delete_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
|
||||
|
||||
|
||||
# Pin / Unpin command
|
||||
def telegram_pin_msg_keyboard(user_id: int, msg_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate menu for /pin command
|
||||
:param user_id: User_id of user pinned the message
|
||||
:param msg_id: Message_id of pinned message
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Открепить сообщение 📌",
|
||||
callback_data=UnpinMsg(user_id=user_id, msg_id=msg_id).pack())],
|
||||
[InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteMenu(user_id_clicked=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
def telegram_unpin_msg_keyboard(user_id: int, msg_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate menu for /unpin command
|
||||
:param user_id: User_id of user unpinned the message
|
||||
:param msg_id: Message_id of unpinned message
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Открепить сообщение 📌",
|
||||
callback_data=PinMsg(user_id=user_id, msg_id=msg_id).pack())],
|
||||
[InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteMenu(user_id_clicked=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
class Pins(BasicFeature):
|
||||
"""
|
||||
A class of pins related commands
|
||||
All staff related to it will be here
|
||||
"""
|
||||
|
||||
async def telegram_pin_callback_handler(call: CallbackQuery, callback_data: PinMsg) -> None:
|
||||
"""
|
||||
Query, what pins message
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
if callback_data.user_id == call.from_user.id:
|
||||
return
|
||||
|
||||
await call.message.chat.pin_message(message_id=callback_data.msg_id)
|
||||
await call.message.edit_text("Удача ✅\n"
|
||||
"Сообщение было закреплено 📌",
|
||||
reply_markup=telegram_pin_msg_keyboard(user_id=call.from_user.id,
|
||||
msg_id=callback_data.msg_id))
|
||||
|
||||
async def telegram_unpin_callback_handler(call: CallbackQuery, callback_data: UnpinMsg) -> None:
|
||||
"""
|
||||
Query, what unpins message
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
if callback_data.user_id == call.from_user.id:
|
||||
return
|
||||
|
||||
await call.message.chat.pin_message(message_id=callback_data.msg_id)
|
||||
await call.message.edit_text("Удача ✅\n"
|
||||
"Сообщение было откреплено 📌",
|
||||
reply_markup=telegram_unpin_msg_keyboard(user_id=call.from_user.id,
|
||||
msg_id=callback_data.msg_id))
|
||||
|
||||
async def telegram_pin_cmd(msg: Message) -> None:
|
||||
"""
|
||||
/pin command function, pins replied command
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await SolutionSimpler.pin_msg(msg)
|
||||
await msg.answer("Удача ✅\n"
|
||||
"Сообщение было закреплено 📌",
|
||||
reply_markup=telegram_pin_msg_keyboard(msg_id=msg.reply_to_message.message_id,
|
||||
user_id=msg.from_user.id))
|
||||
|
||||
async def telegram_unpin_cmd(msg: Message) -> None:
|
||||
"""
|
||||
/unpin command function, unpins replied command
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await SolutionSimpler.unpin_msg(msg)
|
||||
await msg.answer("Удача ✅\n"
|
||||
"Сообщение было откреплено 📌",
|
||||
reply_markup=telegram_unpin_msg_keyboard(msg_id=msg.reply_to_message.message_id,
|
||||
user_id=msg.from_user.id))
|
||||
|
||||
async def telegram_unpinall_cmd(msg: Message) -> None:
|
||||
"""
|
||||
/unpin_all command function, unpins all messages in chat
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await SolutionSimpler.unpin_all_messages(msg)
|
||||
await msg.answer("Удача ✅\n"
|
||||
"Все сообщения были откреплены 📌",
|
||||
reply_markup=delete_keyboard(admin_id=msg.from_user.id))
|
||||
|
||||
async def telegram_help_pin_cmd(msg: Message) -> None:
|
||||
"""
|
||||
Shows help message for /mute
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("Использование:\n"
|
||||
"<pre>/pin</pre>\n"
|
||||
"Ответьте на сообщение, чтобы закрепить сообщение",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
async def telegramm_help_unpin_cmd(msg: Message) -> None:
|
||||
"""
|
||||
Shows help message for /mute
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("Использование:\n"
|
||||
"<pre>/unpin</pre>\n"
|
||||
"Ответьте на сообщение, чтобы открепить сообщение",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
"""
|
||||
Telegram feature settings
|
||||
"""
|
||||
# Telegram feature settings
|
||||
telegram_setting_in_list = True
|
||||
telegram_setting_name = "Закреп 📌"
|
||||
telegram_setting_description = "<b>Закреп</b>📌" \
|
||||
"\nДанная функция включает команды:" \
|
||||
"<pre>/pin - закрепляет сообщение\n" \
|
||||
"/unpin - открепляет сообщение\n" \
|
||||
"/unpin_all - открепляет все сообщения, которые видит бот</pre>\n" \
|
||||
"Для исполнения <b>требует соответсвующих прав от пользователя и их наличие у бота.</b>"
|
||||
telegram_db_name = TelegramChatSettings.pins
|
||||
telegram_category = "admin"
|
||||
# Telegram commands
|
||||
telegram_commands: dict[str: str] = {
|
||||
'pin': 'Pin fast any message in chat',
|
||||
'unpin': 'Unpin fast any message in chat',
|
||||
}
|
||||
telegram_cmd_avaible = True # Is a feature have a commands
|
||||
# Telegram Handler
|
||||
telegram_message_handlers = [
|
||||
# Format is [Handler, [Filters]]
|
||||
[telegram_pin_cmd, [Command(commands="pin"), UserHasPermissions(["can_pin_messages"]),
|
||||
BotHasPermissions(["can_pin_messages"]), F.reply_to_message,
|
||||
~(F.chat.type == ChatType.PRIVATE)]],
|
||||
[telegram_unpin_cmd, [Command(commands="unpin"), UserHasPermissions(["can_pin_messages"]),
|
||||
BotHasPermissions(["can_pin_messages"]), F.reply_to_message,
|
||||
~(F.chat.type == ChatType.PRIVATE)]],
|
||||
[telegram_unpinall_cmd, [Command(commands="unpin_all"), IsAdminFilter(True, False),
|
||||
BotHasPermissions(["can_pin_messages"]), F.reply_to_message.text,
|
||||
~(F.chat.type == ChatType.PRIVATE)]],
|
||||
[telegram_help_pin_cmd, [Command(commands="pin"), UserHasPermissions(["can_pin_messages"]),
|
||||
BotHasPermissions(["can_pin_messages"]), ~(F.chat.type == ChatType.PRIVATE)]],
|
||||
[telegramm_help_unpin_cmd, [Command(commands="unpin"), UserHasPermissions(["can_pin_messages"]),
|
||||
BotHasPermissions(["can_pin_messages"]), ~(F.chat.type == ChatType.PRIVATE)]]
|
||||
|
||||
]
|
||||
telegram_callback_handlers = [
|
||||
# Format is [Handler, [Filters]]
|
||||
[telegram_pin_callback_handler, [PinMsg.filter()]],
|
||||
[telegram_unpin_callback_handler, [UnpinMsg.filter()]]
|
||||
]
|
203
bozenka/features/admin/topics.py
Normal file
203
bozenka/features/admin/topics.py
Normal file
|
@ -0,0 +1,203 @@
|
|||
from aiogram import F
|
||||
from aiogram.enums import ChatType
|
||||
from aiogram.filters import Command
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
|
||||
|
||||
from bozenka.database.tables.telegram import TelegramChatSettings
|
||||
from bozenka.features.main import BasicFeature
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import CloseThread, OpenThread, DeleteMenu
|
||||
from bozenka.instances.telegram.filters import UserHasPermissions, BotHasPermissions
|
||||
from bozenka.instances.telegram.utils.delete import delete_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
|
||||
|
||||
|
||||
# Close / Open thread commands related keyboards
|
||||
def telegram_close_thread_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate menu for /close command
|
||||
:param user_id: User_if of member, who closed thread
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Окрыть обсуждение 🛠️", callback_data=OpenThread(user_id=user_id).pack())],
|
||||
[InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteMenu(user_id_clicked=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
def telegram_open_thread_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate menu for /open command
|
||||
:param user_id: User_if of member, who opened thread
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Закрыть обсуждение 🛠️", callback_data=CloseThread(user_id=user_id).pack())],
|
||||
[InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteMenu(user_id_clicked=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
class Threads(BasicFeature):
|
||||
"""
|
||||
A class of topics / threads related commands
|
||||
All staff related to it will be here
|
||||
"""
|
||||
|
||||
async def telegram_close_topic_cmd_handler(msg: Message) -> None:
|
||||
"""
|
||||
/close command function. Closing thread
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
config = await SolutionSimpler.close_topic(msg=msg)
|
||||
await msg.answer(config[0],
|
||||
reply_markup=telegram_close_thread_keyboard(user_id=msg.from_user.id)
|
||||
if config[1] else delete_keyboard(msg.from_user.id))
|
||||
|
||||
async def telegram_reopen_topic_cmd_handler(msg: Message) -> None:
|
||||
"""
|
||||
/open command function. Opens thread
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
config = await SolutionSimpler.open_topic(msg=msg)
|
||||
await msg.answer(config[0],
|
||||
reply_markup=telegram_open_thread_keyboard(user_id=msg.from_user.id)
|
||||
if config[1] else delete_keyboard(msg.from_user.id))
|
||||
|
||||
async def telegram_close_general_topic_cmd_handler(msg: Message) -> None:
|
||||
"""
|
||||
/close_general command function. Closes general thread
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
config = await SolutionSimpler.close_general_topic(msg=msg)
|
||||
await msg.answer(config[0],
|
||||
reply_markup=telegram_close_thread_keyboard(user_id=msg.from_user.id)
|
||||
if config[1] else delete_keyboard(msg.from_user.id))
|
||||
|
||||
async def telegram_reopen_general_topic_cmd(msg: Message) -> None:
|
||||
"""
|
||||
/open_general command function. Opens general thread
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
config = await SolutionSimpler.open_general_topic(msg=msg)
|
||||
await msg.answer(config[0],
|
||||
reply_markup=telegram_open_thread_keyboard(user_id=msg.from_user.id)
|
||||
if config[1] else delete_keyboard(msg.from_user.id))
|
||||
|
||||
async def telegram_hide_general_topic_cmd_handler(msg: Message) -> None:
|
||||
"""
|
||||
/hide_general command function. Hides general thread
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
config = await SolutionSimpler.hide_general_topic(msg=msg)
|
||||
await msg.answer(config[0],
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
async def telegram_unhide_general_topic_cmd(msg: Message) -> None:
|
||||
"""
|
||||
/show_general command function. Shows back general thread.
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
config = await SolutionSimpler.show_general_topic(msg=msg)
|
||||
await msg.answer(config[0],
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
async def telegram_close_thread_callback_handler(call: CallbackQuery, callback_data: CloseThread) -> None:
|
||||
"""
|
||||
Query, what close thread
|
||||
:param call: CallbackQuery object
|
||||
:param callback_data: ClosetThread object
|
||||
:return: None
|
||||
"""
|
||||
|
||||
if callback_data.user_id != call.from_user.id or not call.message.chat.is_forum:
|
||||
return
|
||||
config = await SolutionSimpler.close_topic(msg=call.message, call=call)
|
||||
await call.message.edit_text(
|
||||
config[0],
|
||||
reply_markup=telegram_close_thread_keyboard(user_id=call.from_user.id) if config[1] else
|
||||
delete_keyboard(admin_id=call.from_user.id)
|
||||
)
|
||||
|
||||
async def inline_open_thread(call: CallbackQuery, callback_data: OpenThread) -> None:
|
||||
"""
|
||||
Query, what opens thread
|
||||
:param call: CallbackQuery object
|
||||
:param callback_data: OpenThread
|
||||
:return: None
|
||||
"""
|
||||
|
||||
if callback_data.user_id != call.from_user.id or not call.message.chat.is_forum:
|
||||
return
|
||||
config = await SolutionSimpler.open_topic(msg=call.message, call=call)
|
||||
await call.message.edit_text(
|
||||
config[0],
|
||||
reply_markup=telegram_open_thread_keyboard(user_id=call.from_user.id) if config[1] else
|
||||
delete_keyboard(admin_id=call.from_user.id)
|
||||
)
|
||||
|
||||
"""
|
||||
Telegram feature settings
|
||||
"""
|
||||
# Telegram setting info
|
||||
|
||||
telegram_setting_in_list = True
|
||||
telegram_setting_name = "Работа с Форумом 💬"
|
||||
telegram_setting_description = "<b>Работа с Форумом</b>💬\nДанная настройка включает следущие комманды:\n" \
|
||||
"<pre>/open - открывают тему форума\n" \
|
||||
"/close - закрывают тему форума\n" \
|
||||
"/open_general - открывают основную тему форума\n" \
|
||||
"/close_general - закрывает основную тему форума\n" \
|
||||
"/hide_general - прячет основную тему форума\n" \
|
||||
"/show_general - показывает основную тему форума</pre>\n" \
|
||||
"Для исполнения <b>требует соответсвующих прав от пользователя и их наличие у бота. Также должен быть" \
|
||||
"включен форум</b>"
|
||||
telegram_db_name = TelegramChatSettings.topics
|
||||
telegram_category = "admin"
|
||||
# Telegram commands
|
||||
telegram_commands: dict[str: str] = {
|
||||
'close': 'Close fast topic (not general) in chat',
|
||||
'open': 'Open fast topic (not general) in chat',
|
||||
'hide_general': 'Hide general topic in chat',
|
||||
'show_general': 'Show general topic in chat',
|
||||
"close_general": 'Closes general topic in chat',
|
||||
"open_general": 'Opens general topic in chat',
|
||||
}
|
||||
telegram_cmd_avaible = True # Is a feature have a commands
|
||||
# All handlers
|
||||
telegram_message_handlers = [
|
||||
[telegram_close_topic_cmd_handler, [Command(commands=["close_topic", "close"]),
|
||||
UserHasPermissions(["can_manage_topics"]),
|
||||
BotHasPermissions(["can_manage_topics"]), F.chat.is_forum,
|
||||
~(F.chat.type == ChatType.PRIVATE)]],
|
||||
[telegram_reopen_topic_cmd_handler, [Command(commands=["reopen_topic", "open_topic", "open"]),
|
||||
UserHasPermissions(["can_manage_topics"]),
|
||||
BotHasPermissions(["can_manage_topics"]), F.chat.is_forum,
|
||||
~(F.chat.type == ChatType.PRIVATE)]],
|
||||
[telegram_close_general_topic_cmd_handler, [Command(commands=["close_general"]),
|
||||
UserHasPermissions(["can_manage_topics"]),
|
||||
BotHasPermissions(["can_manage_topics"]),
|
||||
F.chat.is_forum]],
|
||||
[telegram_reopen_general_topic_cmd, [Command(commands=["reopen_general", "open_general"]),
|
||||
UserHasPermissions(["can_manage_topics"]),
|
||||
BotHasPermissions(["can_manage_topics"]), F.chat.is_forum,
|
||||
~(F.chat.type == ChatType.PRIVATE)]],
|
||||
[telegram_hide_general_topic_cmd_handler, [Command(commands=["hide_general"]),
|
||||
UserHasPermissions(["can_manage_topics"]),
|
||||
BotHasPermissions(["can_manage_topics"]), F.chat.is_forum,
|
||||
~(F.chat.type == ChatType.PRIVATE)]],
|
||||
[telegram_unhide_general_topic_cmd, [Command(commands=["unhide_general", "show_general"]),
|
||||
UserHasPermissions(["can_manage_topics"]),
|
||||
BotHasPermissions(["can_manage_topics"]), F.chat.is_forum,
|
||||
~(F.chat.type == ChatType.PRIVATE)]]
|
||||
]
|
||||
telegram_callback_handlers = [
|
||||
[telegram_close_thread_callback_handler, [CloseThread.filter()]],
|
||||
[telegram_reopen_topic_cmd_handler, [OpenThread.filter()]]
|
||||
]
|
2
bozenka/features/basic/__init__.py
Normal file
2
bozenka/features/basic/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
from .setup import Setup
|
||||
from .start import Start
|
159
bozenka/features/basic/setup.py
Normal file
159
bozenka/features/basic/setup.py
Normal file
|
@ -0,0 +1,159 @@
|
|||
from aiogram import F
|
||||
from aiogram.enums import ChatType
|
||||
from aiogram.filters import Command
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from sqlalchemy import Update
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.database.tables.telegram import get_chat_config_value, TelegramChatSettings
|
||||
from bozenka.features.main import BasicFeature
|
||||
from bozenka.instances.customizable_features_list import categorized_customizable_features, text_transcription
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import SetupAction, SetupFeature, SetupCategory
|
||||
from bozenka.instances.telegram.filters import IsOwner
|
||||
|
||||
|
||||
# Setup related keyboards
|
||||
def setup_keyboard() -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate keyboard for /setup command
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardBuilder()
|
||||
|
||||
for category in categorized_customizable_features:
|
||||
kb.row(InlineKeyboardButton(text=text_transcription[category],
|
||||
callback_data=SetupCategory(category_name=category).pack()))
|
||||
|
||||
return kb.as_markup()
|
||||
|
||||
|
||||
def setup_category_keyboard(category: str) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate keyboard for one of categories
|
||||
:param category:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardBuilder()
|
||||
for setting in categorized_customizable_features[category]:
|
||||
kb.row(InlineKeyboardButton(text=setting.name,
|
||||
callback_data=SetupFeature(
|
||||
feature_index=categorized_customizable_features[category].index(setting),
|
||||
feature_category=category
|
||||
).pack()))
|
||||
return kb.as_markup()
|
||||
|
||||
|
||||
async def setup_feature_keyboard(category: str, index: int, is_enabled: bool) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate keyboard for enabling or disabling
|
||||
on of features
|
||||
:param is_enabled:
|
||||
:param category:
|
||||
:param index:
|
||||
|
||||
:return:
|
||||
"""
|
||||
|
||||
from aiogram.types import InlineKeyboardButton
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Выключить ❌", callback_data=SetupAction(action="disable",
|
||||
feature_category=category,
|
||||
feature_index=index).pack())
|
||||
if is_enabled else
|
||||
InlineKeyboardButton(text="Включить ✅", callback_data=SetupAction(action="enable",
|
||||
feature_category=category,
|
||||
feature_index=index).pack())
|
||||
], [
|
||||
InlineKeyboardButton(text="Вернуться 🔙", callback_data=SetupAction(action="back",
|
||||
feature_category=category,
|
||||
feature_index=index).pack())]])
|
||||
return kb
|
||||
|
||||
|
||||
class Setup(BasicFeature):
|
||||
"""
|
||||
A class of /setup command
|
||||
All staff related to it will be here
|
||||
"""
|
||||
|
||||
async def telegram_setup_cmd_handler(msg: Message) -> None:
|
||||
"""
|
||||
/setup telegram handler
|
||||
:param msg: Telegram message object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("Привет владелец чата 👋\n\n"
|
||||
"Настрой меня - бота так, как тебе удобно, и я буду помогать тебе в чате с определенными функциями.\n"
|
||||
"Используй меню настроек ниже, чтобы указать, какие функции, которые я умею, должен выполнять.",
|
||||
reply_markup=setup_keyboard())
|
||||
|
||||
async def telegram_setup_categories_handler(call: CallbackQuery, callback_data: SetupCategory | SetupAction) -> None:
|
||||
"""
|
||||
Query, what shows list of features to enable.
|
||||
:param call: CallbackQuery class
|
||||
:param callback_data: SetupCategory or SetupAction
|
||||
:return: None
|
||||
"""
|
||||
await call.message.edit_text(f"{text_transcription[callback_data.category_name]}\n\n"
|
||||
f"Выберите функцию, которые вы хотите настроить в данной категории у бота.",
|
||||
reply_markup=setup_category_keyboard(category=callback_data.category_name))
|
||||
|
||||
async def telegram_setup_edit_feature_handler(call: CallbackQuery, callback_data: SetupFeature, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Query, what shows menu to enable / disable feature
|
||||
:param call: CallbackQuery class
|
||||
:param callback_data: SetupFeature class
|
||||
:param session_maker: AsyncSessionMaker SqlAlchemy object
|
||||
:return: None
|
||||
"""
|
||||
is_enabled = await get_chat_config_value(
|
||||
chat_id=call.message.chat.id,
|
||||
session=session_maker,
|
||||
setting=categorized_customizable_features[callback_data.feature_category][callback_data.feature_index]
|
||||
)
|
||||
|
||||
await call.message.edit_text(
|
||||
categorized_customizable_features[callback_data.feature_category][callback_data.feature_index].telegram_setting_description,
|
||||
reply_markup=await setup_feature_keyboard(category=callback_data.feature_category,
|
||||
index=callback_data.feature_index,
|
||||
is_enabled=is_enabled))
|
||||
|
||||
async def telegram_features_edit_handler(call: CallbackQuery, callback_data: SetupAction, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Query, what shows menu to enable / disable feature
|
||||
after editing
|
||||
:param call: CallbackQuery class
|
||||
:param callback_data: SetupAction class
|
||||
:param session_maker: AsyncSessionMaker SqlAlchemy object
|
||||
:return: None
|
||||
"""
|
||||
async with session_maker() as session:
|
||||
async with session.begin():
|
||||
await session.execute(Update(TelegramChatSettings)
|
||||
.values(
|
||||
{categorized_customizable_features[callback_data.category_name][callback_data.feature_index].telegram_setting_description: callback_data.action == "enable"})
|
||||
.where(TelegramChatSettings.chat_id == call.message.chat.id))
|
||||
await call.message.edit_text(
|
||||
categorized_customizable_features[callback_data.feature_category][callback_data.feature_index].telegram_setting_description,
|
||||
reply_markup=await setup_feature_keyboard(category=callback_data.category_name,
|
||||
index=callback_data.afeature_index,
|
||||
is_enabled=callback_data.action == "enable"))
|
||||
|
||||
"""
|
||||
Telegram feature settings
|
||||
"""
|
||||
# Telegram feature settings
|
||||
telegram_setting_in_list = False
|
||||
telegram_commands = {"setup": 'Command to setup bozenka features in chat'}
|
||||
telegram_cmd_avaible = True
|
||||
telegram_category = None
|
||||
telegram_message_handlers = [
|
||||
[telegram_setup_cmd_handler, [Command(commands=["setup"]), ~(F.chat.type == ChatType.PRIVATE), IsOwner(True)]]
|
||||
]
|
||||
telegram_callback_handlers = [
|
||||
[telegram_features_edit_handler, [SetupAction.filter(F.action == "disable"), IsOwner(True)]],
|
||||
[telegram_features_edit_handler, [SetupAction.filter(F.action == "enable"), IsOwner(True)]],
|
||||
[telegram_setup_edit_feature_handler, [SetupFeature.filter(), IsOwner(True)]],
|
||||
[telegram_setup_categories_handler, [SetupAction.filter(F.action == "back"), IsOwner(True)]]
|
||||
]
|
284
bozenka/features/basic/start.py
Normal file
284
bozenka/features/basic/start.py
Normal file
|
@ -0,0 +1,284 @@
|
|||
from aiogram import F
|
||||
from aiogram.enums import ChatType
|
||||
from aiogram.filters import Command
|
||||
from aiogram.types import InlineKeyboardMarkup, Message, CallbackQuery, InlineKeyboardButton
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from bozenka.features.main import BasicFeature
|
||||
from bozenka.instances.customizable_features_list import categorized_customizable_features, text_transcription
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import HelpCategory, HelpBackCategory, HelpFeature, HelpBack
|
||||
from bozenka.features.user.text_generation import telegram_text_categories_keyboard
|
||||
from bozenka.instances.current_version import build, is_updated
|
||||
|
||||
telegram_main_menu = InlineKeyboardMarkup(
|
||||
inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Добавить в ваш групповой чат 🔌", callback_data="addtochat")],
|
||||
[InlineKeyboardButton(text="Информация об функционале бота 🔨", callback_data="functional")],
|
||||
[InlineKeyboardButton(text="Об данном проекте ℹ️", callback_data="aboutdevs")],
|
||||
[InlineKeyboardButton(text="О данном запущенном экзепляре ℹ️", callback_data="aboutbot")],
|
||||
[InlineKeyboardButton(text="Начать диалог с текстовым ИИ 🤖", callback_data="dialogai")],
|
||||
[InlineKeyboardButton(text="Начать генерацию изображений 🖼", callback_data="dialogimage")],
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
# Help related keyboards
|
||||
def main_help_keyboard() -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate keyboard for /help command
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
kb = InlineKeyboardBuilder()
|
||||
for category in categorized_customizable_features:
|
||||
kb.row(InlineKeyboardButton(text=text_transcription[category],
|
||||
callback_data=HelpCategory(category_name=category).pack()))
|
||||
|
||||
return kb.as_markup()
|
||||
|
||||
|
||||
def help_category_keyboard(category: str) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate keyboard for one of categories
|
||||
:param category: Category name
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
kb = InlineKeyboardBuilder()
|
||||
for setting in categorized_customizable_features[category]:
|
||||
kb.row(InlineKeyboardButton(text=setting.telegram_setting_name,
|
||||
callback_data=HelpFeature(
|
||||
feature_index=categorized_customizable_features[category].index(setting),
|
||||
feature_category=category
|
||||
).pack()))
|
||||
kb.row(InlineKeyboardButton(text="🔙 Назад к списку категорий",
|
||||
callback_data=HelpBack(back_to="category").pack()))
|
||||
return kb.as_markup()
|
||||
|
||||
|
||||
def help_feature_keyboard(category: str) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Just button for function of /help
|
||||
:param category: Category name
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="🔙 Назад к списку функций",
|
||||
callback_data=HelpBackCategory(category_name=category).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
class Start(BasicFeature):
|
||||
"""
|
||||
A class of /start command
|
||||
All staff related to it will be here
|
||||
"""
|
||||
|
||||
# There starting a help category of handlers
|
||||
# It's related to one of menus
|
||||
# Showing information about features, will be remade later :D
|
||||
|
||||
@staticmethod
|
||||
async def back_help_categories_handler(call: CallbackQuery, callback_data: HelpBack) -> None:
|
||||
"""
|
||||
Query, what shows list of features to get support back.
|
||||
:param call: CallbackQuery object
|
||||
:param callback_data: Helpback class
|
||||
:return: None
|
||||
"""
|
||||
await call.message.edit_text("Выберите категорию, по которой нужна помощь:",
|
||||
reply_markup=main_help_keyboard())
|
||||
await call.answer()
|
||||
|
||||
@staticmethod
|
||||
async def help_features_handler(call: CallbackQuery, callback_data: HelpCategory | HelpBackCategory) -> None:
|
||||
"""
|
||||
Handler of CallbackQuery, what shows list of features to get support.
|
||||
:param call: CallbackQuery object
|
||||
:param callback_data: HelpCategory or HelpBack class
|
||||
:return: None
|
||||
"""
|
||||
await call.message.edit_text("Выберите функцию, по которой нужна помощь",
|
||||
reply_markup=help_category_keyboard(category=callback_data.category_name))
|
||||
await call.answer()
|
||||
|
||||
@staticmethod
|
||||
async def feature_info_handler(call: CallbackQuery, callback_data: HelpFeature) -> None:
|
||||
"""
|
||||
Handler of CallbackQuery, what shows information about bozenka feature
|
||||
:param call: CallbackQuery ojbect
|
||||
:param callback_data: HelpFeature object
|
||||
:return: None
|
||||
"""
|
||||
await call.message.edit_text(
|
||||
categorized_customizable_features[callback_data.feature_category][callback_data.feature_index]. telegram_setting_description,
|
||||
reply_markup=help_feature_keyboard(category=callback_data.feature_category))
|
||||
await call.answer()
|
||||
|
||||
@staticmethod
|
||||
async def help_menu_handler(call: CallbackQuery) -> None:
|
||||
"""
|
||||
Handler of CallbackQuery, what shows menu of help
|
||||
:param call: CallbackQuery object
|
||||
:return: None
|
||||
"""
|
||||
await call.message.edit_text("Выберите категорию функций, по которой вам нужна помощь 🤖",
|
||||
reply_markup=main_help_keyboard())
|
||||
await call.answer()
|
||||
|
||||
@staticmethod
|
||||
async def add_to_menu_handler(call: CallbackQuery) -> None:
|
||||
"""
|
||||
Handler of CallbackQuery, what shows a link to add bozenka into user group chat
|
||||
:param call: CallbackQuery object
|
||||
:return: None
|
||||
"""
|
||||
# Getting bot
|
||||
me = await call.message.bot.me()
|
||||
|
||||
# Generating special keyboard
|
||||
kb = InlineKeyboardBuilder()
|
||||
kb.button(text="Добавить в ваш груповой чат 🔌",
|
||||
url="https://t.me/"
|
||||
f"{me.username}?"
|
||||
"startgroup&"
|
||||
"admin=promote_members+delete_messages+restrict_members+invite_users+pin_messages+manage_video_chats")
|
||||
kb.row(InlineKeyboardButton(text="Вернуться 🔙", callback_data="back"))
|
||||
|
||||
# Answering
|
||||
await call.message.edit_text("Чтобы добавить бозеньку в ваш групповой чат, нажмите на кнопку под сообщением:",
|
||||
reply_markup=kb.as_markup())
|
||||
await call.answer()
|
||||
|
||||
@staticmethod
|
||||
async def about_instance_callback_handler(call: CallbackQuery) -> None:
|
||||
"""
|
||||
Handler of CallbackQuery, what shows information about current running instance
|
||||
:param call: CallbackQuery object
|
||||
:return: Nothing
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Вернуться 🔙", callback_data="back")
|
||||
]])
|
||||
me = await call.message.bot.get_me()
|
||||
update_status = {False: "требуется обновление бота 🔼",
|
||||
True: "обновление не требуется, последняя версия ✅"}
|
||||
await call.message.edit_text(
|
||||
f"Информация об данном запущенном экземпляре бозеньки:\n"
|
||||
f"Аккаунт бота: {me.mention_html()}\n"
|
||||
f"Запущенная версия бота <code>{build}</code>\n",
|
||||
f"Нужно ли обновление: {update_status[is_updated]}",
|
||||
reply_markup=kb)
|
||||
await call.answer()
|
||||
|
||||
@staticmethod
|
||||
async def about_developers_handler(call: CallbackQuery) -> None:
|
||||
"""
|
||||
Handler of CallbackQuery, what shows information about bozenka & it's development
|
||||
:param call: CallbackQuery object
|
||||
:return: Nothing
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Вернуться 🔙", callback_data="back")
|
||||
]])
|
||||
await call.message.edit_text("""
|
||||
Бозенька - это мультифункциональный (в будущем кроссплатформенный) бот.\n
|
||||
Он умеет работать с групповыми чатами и готовыми нейронными сетями для генерации текста и изображений.
|
||||
Бозенька разрабатывается коммандой, которая состоит на данный момент из одного человека.\n
|
||||
Исходный код проекта\n
|
||||
Исходный код находится под лицензией GPL-3.0, исходный код проекта можно посмотреть всегда <a href="https://github.com/kittyneverdies/bozenka/">здесь</a>
|
||||
Канал с новостями разработки находится <a href="https://t.me/bozodevelopment">здесь</a>
|
||||
""", reply_markup=kb, disable_web_page_preview=True)
|
||||
|
||||
@staticmethod
|
||||
async def start_dialog_handler(call: CallbackQuery) -> None:
|
||||
"""
|
||||
Handler of CallbackQuery, what shows list of Categories, avaible to use as chatbot
|
||||
:param call: CallbackQuery object
|
||||
:return: Nothing
|
||||
"""
|
||||
await call.message.edit_text("Пожалуста, выберите сервиc / библиотеку, через которую вы будете общаться",
|
||||
reply_markup=telegram_text_categories_keyboard
|
||||
(user_id=call.from_user.id))
|
||||
|
||||
@staticmethod
|
||||
async def start_callback_handler(call: CallbackQuery) -> None:
|
||||
"""
|
||||
/start command function handler. Just back it by clicking on button.
|
||||
Shows menu and basic information about bozenka
|
||||
:param call: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await call.message.edit_text("""
|
||||
Привет 👋
|
||||
Я - бозенька, бот с открытым исходным кодом, который поможет тебе в различных задачах.
|
||||
|
||||
Вот что ты можешь сделать с помощью меню:
|
||||
• Добавить в чат: добавляет меня в групповой чат, чтобы я мог выполнять свои функции внутри него.
|
||||
• Функционал: показывает список доступных функций и команд, которые я могу выполнить.
|
||||
• О разработчиках: предоставляет информацию о команде разработчиков, которые создали и поддерживают этого бота.
|
||||
• О запущенном экземпляре: выводит информацию о текущей версии и состоянии запущенного экземпляра бота.
|
||||
• Начать диалог с ИИ: позволяет начать диалог с искусственным интеллектом, который может отвечать на вопросы и предоставлять информацию.
|
||||
• Генерация изображений: позволяет сгенерировать изображения на основе заданных параметров и промта
|
||||
|
||||
Вот нужные ссылки обо мне:
|
||||
• <a href='https://t.me/bozodevelopment'>Канал с новостями об разработке</a>
|
||||
• <a href='https://github.com/kittyneverdies/bozenka/'>Исходный код на Github</a>
|
||||
|
||||
Чтобы воспользоваться какой-либо функцией, просто нажми на соответствующую кнопку ниже.
|
||||
Если у тебя возникнут вопросы или проблемы, не стесняйся обратиться к команде разработчиков или написать в обсуждении телеграм канала.
|
||||
Удачного использования!
|
||||
""", reply_markup=telegram_main_menu, disable_web_page_preview=True)
|
||||
|
||||
@staticmethod
|
||||
async def start_cmd_handler(msg: Message) -> None:
|
||||
"""
|
||||
/start command function handler
|
||||
Shows menu and basic information about bozenka
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("""
|
||||
Привет 👋
|
||||
Я - групповой чат-бот с открытым исходным кодом, который поможет тебе в различных задачах.
|
||||
|
||||
Вот что ты можешь сделать с помощью меню:
|
||||
• Добавить в чат: добавляет меня в групповой чат, чтобы я мог выполнять свои функции внутри него.
|
||||
• Функционал: показывает список доступных функций и команд, которые я могу выполнить.
|
||||
• О разработчиках: предоставляет информацию о команде разработчиков, которые создали и поддерживают этого бота.
|
||||
• О запущенном экземпляре: выводит информацию о текущей версии и состоянии запущенного экземпляра бота.
|
||||
• Начать диалог с ИИ: позволяет начать диалог с искусственным интеллектом, который может отвечать на вопросы и предоставлять информацию.
|
||||
• Генерация изображений: позволяет сгенерировать изображения на основе заданных параметров и промта
|
||||
|
||||
Вот нужные ссылки обо мне:
|
||||
• <a href='https://github.com/kittyneverdies/bozenka/'>Исходный код на Github</a>
|
||||
|
||||
Чтобы воспользоваться какой-либо функцией, просто нажми на соответствующую кнопку ниже.
|
||||
Если у тебя возникнут вопросы или проблемы, не стесняйся обратиться к команде разработчиков или написать в обсуждении телеграм канала.
|
||||
Удачного использования!
|
||||
""", reply_markup=telegram_main_menu, disable_web_page_preview=True)
|
||||
|
||||
"""
|
||||
Telegram feature settings
|
||||
"""
|
||||
# Telegram feature settings
|
||||
telegram_setting_in_list = False
|
||||
telegram_category = None
|
||||
telegram_commands: dict[str: str] = {"start": "Command to start work with bozenka the bot"}
|
||||
telegram_cmd_avaible = True # Is a feature have a commands
|
||||
telegram_message_handlers = [
|
||||
[start_cmd_handler, [Command(commands=["start"]), F.chat.type == ChatType.PRIVATE]],
|
||||
]
|
||||
telegram_callback_handlers = [
|
||||
# Start menu
|
||||
[start_dialog_handler, [F.data == "dialogai"]],
|
||||
[add_to_menu_handler, [F.data == "addtochat"]],
|
||||
[about_developers_handler, [F.data == "aboutdevs"]],
|
||||
[about_instance_callback_handler, [F.data == "aboutbot"]],
|
||||
[start_callback_handler, [F.data == "back"]],
|
||||
# Help menu
|
||||
[help_menu_handler, [F.data == "functional"]],
|
||||
[feature_info_handler, [HelpFeature.filter()]],
|
||||
[help_features_handler, [HelpBackCategory.filter()]],
|
||||
[help_features_handler, [HelpCategory.filter()]],
|
||||
[help_menu_handler, [HelpBack.filter(F.back_to == "category")]]
|
||||
]
|
27
bozenka/features/main.py
Normal file
27
bozenka/features/main.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
class BasicFeature:
|
||||
"""
|
||||
A classic class of lineral (basic)
|
||||
feature of bozenka. IN FUTURE!
|
||||
:param telegram_setting_in_list: Does feature shows in /setup list
|
||||
"""
|
||||
telegram_setting_in_list: bool = False # Does feature shows in /setup list
|
||||
telegram_setting_name: str | None = None # Setting title in /setup command
|
||||
telegram_setting_description: str | None = None # Setting description in /setup command
|
||||
telegram_db_name = None # Name of TelegramChatSettings column will be affected
|
||||
telegram_category: str | None = None # Telegram category name, current
|
||||
# Telegram commands list of feature
|
||||
telegram_commands: dict[str: str] = {
|
||||
#
|
||||
# Format is "CommandNameHere": "Command description is here"
|
||||
#
|
||||
"example": "Its an example"
|
||||
}
|
||||
telegram_cmd_avaible = True # Does this feature have a telegram commands
|
||||
|
||||
# All handlers to register automaticly by bozenka
|
||||
telegram_message_handlers = [
|
||||
# Format is [Handler, [Filters]]
|
||||
]
|
||||
telegram_callback_handlers = [
|
||||
# Format is [Handler, [Filters]]
|
||||
]
|
3
bozenka/features/user/__init__.py
Normal file
3
bozenka/features/user/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from .image_generation import ImageGeneratrion
|
||||
from .text_generation import TextGeneratrion
|
||||
from .welcome import Welcome
|
201
bozenka/features/user/image_generation.py
Normal file
201
bozenka/features/user/image_generation.py
Normal file
|
@ -0,0 +1,201 @@
|
|||
import logging
|
||||
from typing import Callable
|
||||
|
||||
from aiogram import Dispatcher, F
|
||||
from aiogram.filters import CommandObject, Command
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import InlineKeyboardMarkup, Message, CallbackQuery, FSInputFile, InlineKeyboardButton
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.database.tables.telegram import TelegramChatSettings
|
||||
from bozenka.features.main import BasicFeature
|
||||
from bozenka.generative import image_generative_size, image_generative_categories
|
||||
from bozenka.generative.kadinsky import kadinsky_gen
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import ImageGenerationCategory, ImageGeneration, DeleteMenu, \
|
||||
GptStop
|
||||
from bozenka.instances.telegram.utils.delete import delete_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import GeneratingImages
|
||||
|
||||
|
||||
def telegram_image_response_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for image
|
||||
:param user_id: User_id of called user
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteMenu(user_id_clicked=str(user_id)).pack())],
|
||||
[InlineKeyboardButton(text="Хватит 🚫", callback_data=GptStop(user_id=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
def telegram_image_resolution_keyboard(user_id: int, category: str) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Create keyboard with list of resolution to generate image
|
||||
:param category: Category name
|
||||
:param user_id: User_id of called user
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
for size in image_generative_size:
|
||||
builder.row(InlineKeyboardButton(text=size,
|
||||
callback_data=ImageGeneration(
|
||||
user_id=user_id,
|
||||
category=category,
|
||||
size=size
|
||||
).pack()))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def telegram_image_generation_categories_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Create keyboard with list of image generation librarioes avaible in the bozenka
|
||||
:param user_id: User_id of called user
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
for category in image_generative_categories:
|
||||
builder.row(InlineKeyboardButton(text=category,
|
||||
callback_data=ImageGenerationCategory(user_id=user_id,
|
||||
category=category).pack()))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
class ImageGeneratrion(BasicFeature):
|
||||
"""
|
||||
A classic class of lineral (basic)
|
||||
feature of bozenka. IN FUTURE!
|
||||
"""
|
||||
async def telegram_select_image_size_handler(call: CallbackQuery, callback_data: ImageGenerationCategory,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what shows menu for image size to generate in
|
||||
:param call: CallbackQuery object
|
||||
:param callback_data: ImageGenerationCategory
|
||||
:param state: FSMContext aiogram object
|
||||
:return: None
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
await state.update_data(set_category=callback_data.category)
|
||||
await state.set_state(GeneratingImages.set_size)
|
||||
await call.message.edit_text("Пожалуста, выберите размер изображения 🖼",
|
||||
reply_markup=telegram_image_resolution_keyboard(user_id=call.from_user.id,
|
||||
category=callback_data.category))
|
||||
|
||||
async def telegram_end_generation_handler(call: CallbackQuery, callback_data: ImageGeneration,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what shows menu for image size to generate in
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:param state:
|
||||
:return: None
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
await state.update_data(set_size=callback_data.size)
|
||||
await state.set_state(GeneratingImages.ready_to_generate)
|
||||
await call.message.edit_text(
|
||||
f"Вы выбрали {callback_data.category} для генерации изображений в размере {callback_data.size}.\n"
|
||||
"Напишите /cancel для отмены",
|
||||
reply_markup=delete_keyboard(admin_id=call.from_user.id))
|
||||
|
||||
async def telegram_already_generating_handler(msg: Message, state: FSMContext) -> None:
|
||||
"""
|
||||
Giving response, if generating image for user right now,
|
||||
but user still asks something
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
await msg.answer(
|
||||
"Подождите пожалуйста, мы уже генерируем изображение для вас, подождите, когда мы ответим на ваш передыдущий вопрос",
|
||||
reply_markup=delete_keyboard(admin_id=msg.from_user.id))
|
||||
|
||||
async def telegram_imagine_handler(msg: Message | CallbackQuery, state: FSMContext) -> None:
|
||||
"""
|
||||
/imagine command handler, start menu
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
if await state.get_state():
|
||||
return
|
||||
|
||||
if type(msg) == CallbackQuery:
|
||||
msg = msg.message
|
||||
|
||||
await msg.answer("Пожалуста, выберите сервис / модель для генерации изображений",
|
||||
reply_markup=telegram_image_generation_categories_keyboard(user_id=msg.from_user.id))
|
||||
|
||||
async def telegram_kadinsky_generating_handler(msg: Message, state: FSMContext) -> None:
|
||||
"""
|
||||
Message handler for kandinsky to generate image by text from message
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
await state.set_state(GeneratingImages.generating)
|
||||
message = await msg.answer("Пожалуйста подождите, мы генерируем изображение ⏰\n"
|
||||
"Если что-то пойдет не так, мы вам сообщим 👌")
|
||||
data = await state.get_data()
|
||||
|
||||
try:
|
||||
|
||||
model_id = kadinsky_gen.get_model()
|
||||
width, height = data["set_size"].split("x")
|
||||
generating = kadinsky_gen.generate(model=model_id,
|
||||
prompt=msg.text,
|
||||
width=int(width),
|
||||
height=int(height))
|
||||
result = kadinsky_gen.check_generation(request_id=generating)
|
||||
|
||||
if result:
|
||||
path = kadinsky_gen.save_image(result[0], f"telegram_{msg.from_user.id}")
|
||||
photo = FSInputFile(path)
|
||||
await msg.answer_photo(photo=photo,
|
||||
caption=msg.text,
|
||||
reply_markup=telegram_image_response_keyboard(user_id=msg.from_user.id))
|
||||
await message.delete()
|
||||
else:
|
||||
await message.edit_text("Простите, произошла ошибка 😔\n"
|
||||
"Убедитесь, что севрера kadinsky работают и ваш промт не является неподобающим и неприемлимым\n"
|
||||
"Если это продолжается, пожалуйста используйте /cancel",
|
||||
reply_markup=telegram_image_response_keyboard(user_id=msg.from_user.id))
|
||||
|
||||
except Exception as ex:
|
||||
logging.log(msg=f"Get an exception for generating answer={ex}",
|
||||
level=logging.ERROR)
|
||||
finally:
|
||||
logging.log(msg=f"Generated image for user_id={msg.from_user.id} with promt",
|
||||
level=logging.INFO)
|
||||
await state.set_state(GeneratingImages.ready_to_generate)
|
||||
|
||||
"""
|
||||
Telegram feature settings
|
||||
"""
|
||||
# Telegram feature settings
|
||||
telegram_category = "user"
|
||||
telegram_db_name = TelegramChatSettings.image_generation
|
||||
telegram_commands: dict[str: str] = {'imagine': 'Starts conversation with image generative ai'}
|
||||
telegram_setting_in_list = True
|
||||
telegram_setting_name = "Генерация изображений 📸"
|
||||
telegram_setting_description = "<b>Генерация изображений </b>🤖" \
|
||||
"\nНаходится в разработке.\n" \
|
||||
"На текущий момент есть поддержка:\n" \
|
||||
"- Kadinksy\n" \
|
||||
" Следите за обновлениями 😘"
|
||||
telegram_cmd_avaible = True # Is a feature have a commands
|
||||
telegram_message_handlers = [
|
||||
[telegram_kadinsky_generating_handler, [GeneratingImages.ready_to_generate, ~Command(commands=["cancel"])]],
|
||||
[telegram_imagine_handler, [Command(commands=["imagine"])]]
|
||||
]
|
||||
telegram_callback_handlers = [
|
||||
[telegram_select_image_size_handler, [ImageGenerationCategory.filter()]],
|
||||
[telegram_end_generation_handler, [ImageGeneration.filter()]],
|
||||
[telegram_imagine_handler, [F.data == "dialogimage"]]
|
||||
]
|
805
bozenka/features/user/text_generation.py
Normal file
805
bozenka/features/user/text_generation.py
Normal file
|
@ -0,0 +1,805 @@
|
|||
import logging
|
||||
from typing import Any
|
||||
|
||||
import g4f
|
||||
from aiogram import F
|
||||
from aiogram.filters import Command
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from gpt4all import GPT4All
|
||||
|
||||
from bozenka.database.tables.telegram import TelegramChatSettings
|
||||
from bozenka.features.main import BasicFeature
|
||||
from bozenka.generative import text2text_generatiove_libraries
|
||||
from bozenka.generative.gpt4all import model_path, check
|
||||
from bozenka.generative.gpt4free import generate_gpt4free_providers, generate_gpt4free_models
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import DeleteMenu
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import Gpt4FreeProvsModelPage, Gpt4FreeProviderPage, \
|
||||
Gpt4AllSelect, Gpt4AllModel, GptCategory, Gpt4freeResult, \
|
||||
Gpt4FreeProvider, GptBackMenu, Gpt4FreeModel, Gpt4FreeCategory, Gpt4FreeModelPage, GptStop
|
||||
from bozenka.instances.telegram.utils.delete import delete_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import AnsweringGPT4Free, AnsweringGpt4All
|
||||
|
||||
|
||||
def telegram_text_categories_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Create list keyboard list of gpt libraries, available in the bot
|
||||
:param user_id: User_id of user
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
for category in text2text_generatiove_libraries:
|
||||
builder.row(InlineKeyboardButton(text=category,
|
||||
callback_data=GptCategory(user_id=str(user_id), category=category).pack()))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
# Helper
|
||||
def items_list_generator(page: int, list_of_items, count_of_items: int) -> list[Any]:
|
||||
"""
|
||||
Generate page, made for backend
|
||||
:param page: Number of page
|
||||
:param list_of_items:
|
||||
:param count_of_items:
|
||||
"""
|
||||
items = []
|
||||
required_items = [item + page * count_of_items for item in range(count_of_items)]
|
||||
for item, count in zip(list_of_items, range(0, len(list_of_items))):
|
||||
if count not in required_items:
|
||||
continue
|
||||
items.append(item)
|
||||
return items
|
||||
|
||||
|
||||
def text_response_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for response from GPT
|
||||
:param user_id:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteMenu(user_id_clicked=str(user_id)).pack())],
|
||||
[InlineKeyboardButton(text="Завершить диалог 🚫", callback_data=GptStop(user_id=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
def telegram_gpt4free_providers_keyboard(user_id: int, page: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate page of gpt providers, can be used by user.
|
||||
:param user_id:
|
||||
:param page:
|
||||
:return:
|
||||
"""
|
||||
providers = generate_gpt4free_providers()
|
||||
names = items_list_generator(page, providers, 4)
|
||||
pages = [len(providers) // 4 - 1 if page - 1 == -1 else page - 1,
|
||||
0 if page + 1 >= len(providers) // 4 else page + 1]
|
||||
generated_page = InlineKeyboardMarkup(inline_keyboard=[
|
||||
# First one provider
|
||||
[InlineKeyboardButton(text=names[0],
|
||||
callback_data=Gpt4FreeProvider(user_id=user_id, provider=names[0], page="0").pack())],
|
||||
# Second one provider
|
||||
[InlineKeyboardButton(text=names[1],
|
||||
callback_data=Gpt4FreeProvider(user_id=user_id, provider=names[1], page="0").pack())],
|
||||
# Third one provider
|
||||
[InlineKeyboardButton(text=names[2],
|
||||
callback_data=Gpt4FreeProvider(user_id=user_id, provider=names[2], page="0").pack())],
|
||||
# Fourh one provider (if exist)
|
||||
[InlineKeyboardButton(text=names[3],
|
||||
callback_data=Gpt4FreeProvider(user_id=user_id, provider=names[3],
|
||||
page="0").pack())] if len(
|
||||
names) == 4 else [],
|
||||
# Page right
|
||||
[InlineKeyboardButton(text=str(len(providers) // 4 if page == 0 else "1"),
|
||||
callback_data=Gpt4FreeProviderPage(
|
||||
page=str(len(providers) // 4 - 1 if page == 0 else "0"),
|
||||
user_id=user_id).pack()),
|
||||
|
||||
InlineKeyboardButton(text="⬅️", callback_data=Gpt4FreeProviderPage(page=pages[0], user_id=user_id).pack()),
|
||||
InlineKeyboardButton(text=str(page + 1), callback_data="gotpages"),
|
||||
# Page left
|
||||
InlineKeyboardButton(text="➡️", callback_data=Gpt4FreeProviderPage(page=pages[1], user_id=user_id).pack()),
|
||||
InlineKeyboardButton(text=str(len(providers) // 4 if page != len(providers) // 4 - 1 else "1"),
|
||||
callback_data=Gpt4FreeProviderPage(
|
||||
page=str(len(providers) // 4 - 1 if page != len(providers) // 4 - 1 else "0"),
|
||||
user_id=user_id).pack())
|
||||
],
|
||||
# Under list buttons
|
||||
[InlineKeyboardButton(text="🔙 Вернуться к категориям",
|
||||
callback_data=GptBackMenu(user_id=user_id, back_to="g4fcategory").pack())],
|
||||
[InlineKeyboardButton(text="Спасибо, не надо ❌",
|
||||
callback_data=GptStop(user_id=str(user_id)).pack())]])
|
||||
return generated_page
|
||||
|
||||
|
||||
def gpt4free_categories_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Menu of categories in Gpt4Free (Providers / Models)
|
||||
:param user_id:
|
||||
:return:
|
||||
"""
|
||||
print("!231234")
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="По моделям 🤖",
|
||||
callback_data=Gpt4FreeCategory(category="models", user_id=user_id).pack())
|
||||
], [
|
||||
InlineKeyboardButton(text="По провайдерам 🤖",
|
||||
callback_data=Gpt4FreeCategory(category="providers", user_id=user_id).pack())
|
||||
]])
|
||||
return kb
|
||||
|
||||
|
||||
def gpt4free_models_keyboard(user_id: int, page: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating list of GPT4FREE models, can be used to generate text.
|
||||
:param user_id:
|
||||
:param page:
|
||||
:return:
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
full_list = g4f.ModelUtils.convert.keys()
|
||||
models = items_list_generator(page=page, list_of_items=full_list, count_of_items=4)
|
||||
pages = [len(full_list) // 4 - 1 if page - 1 == -1 else page - 1,
|
||||
0 if page + 1 >= len(full_list) // 4 else page + 1]
|
||||
|
||||
for model in models:
|
||||
builder.row(InlineKeyboardButton(text=model,
|
||||
callback_data=Gpt4FreeModel(user_id=user_id, model=model).pack()))
|
||||
builder.row(
|
||||
# First page button
|
||||
InlineKeyboardButton(text=str(len(full_list) // 4 if page == 0 else "1"),
|
||||
callback_data=Gpt4FreeModelPage(
|
||||
page=str(len(full_list) // 4 - 1 if page == 0 else "1"),
|
||||
user_id=user_id).pack(),
|
||||
),
|
||||
# Page back button
|
||||
InlineKeyboardButton(text="⬅️",
|
||||
callback_data=Gpt4FreeModelPage(user_id=str(user_id), page=pages[0], ).pack()),
|
||||
# Count of page button
|
||||
InlineKeyboardButton(text=str(page + 1), callback_data="gotpages"),
|
||||
# Next page button
|
||||
InlineKeyboardButton(text="➡️",
|
||||
callback_data=Gpt4FreeModelPage(user_id=str(user_id), page=pages[1]).pack()),
|
||||
# Last page button
|
||||
InlineKeyboardButton(text=str(len(full_list) // 4 if page != 0 else "1"),
|
||||
callback_data=Gpt4FreeModelPage(
|
||||
page=str(len(full_list) // 4 - 1) if page != 0 else "1",
|
||||
user_id=user_id).pack(), ))
|
||||
builder.row(InlineKeyboardButton(text="🔙 Вернуться",
|
||||
callback_data=GptBackMenu(user_id=user_id, back_to="g4fcategory").pack()))
|
||||
builder.row(InlineKeyboardButton(text="Спасибо, не надо ❌",
|
||||
callback_data=GptStop(user_id=str(user_id)).pack()))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def gpt4free_models_by_provider_keyboard(user_id: int, provider: str, page: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating list of GPT4Free provider's models, can be used to generate text.
|
||||
Will be also reworked.
|
||||
:param user_id:
|
||||
:param provider:
|
||||
:param page:
|
||||
:return:
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
models = generate_gpt4free_models()
|
||||
providers = generate_gpt4free_providers()
|
||||
if provider in models:
|
||||
if providers[provider].supports_gpt_4:
|
||||
models[provider].append("")
|
||||
names = items_list_generator(page, models[provider], 4)
|
||||
for name in names:
|
||||
builder.row(InlineKeyboardButton(text=name.replace('-', ' '),
|
||||
callback_data=Gpt4freeResult(user_id=str(user_id), provider=provider,
|
||||
model=name).pack()))
|
||||
pages = [len(models[provider]) // 4 - 1 if page - 1 == -1 else page - 1,
|
||||
0 if page + 1 >= len(models[provider]) // 4 else page + 1]
|
||||
if len(models[provider]) > 4:
|
||||
builder.row(
|
||||
# First page button
|
||||
InlineKeyboardButton(text=str(len(models[provider]) // 4 if page == 0 else "1"),
|
||||
callback_data=Gpt4FreeProvsModelPage(
|
||||
page=str(len(models[provider]) // 4 - 1 if page == 0 else "1"),
|
||||
user_id=user_id,
|
||||
provider=provider).pack(),
|
||||
),
|
||||
# Page back button
|
||||
InlineKeyboardButton(text="⬅️",
|
||||
callback_data=Gpt4FreeProvsModelPage(user_id=str(user_id), page=pages[0],
|
||||
provider=provider).pack()),
|
||||
# Count of page button
|
||||
InlineKeyboardButton(text=str(page + 1), callback_data="gotpages"),
|
||||
# Next page button
|
||||
InlineKeyboardButton(text="➡️",
|
||||
callback_data=Gpt4FreeProvsModelPage(user_id=str(user_id), page=pages[1],
|
||||
provider=provider).pack()),
|
||||
# Last page button
|
||||
InlineKeyboardButton(text=str(len(models[provider]) // 4 if page != 0 else "1"),
|
||||
callback_data=Gpt4FreeProvsModelPage(
|
||||
page=str(len(models[provider]) // 4 - 1) if page != 0 else "1",
|
||||
user_id=user_id,
|
||||
provider=provider).pack(), ))
|
||||
else:
|
||||
if providers[provider].supports_gpt_4:
|
||||
builder.row(InlineKeyboardButton(text="gpt 4",
|
||||
callback_data=Gpt4freeResult(user_id=str(user_id),
|
||||
provider=provider,
|
||||
model="gpt-4").pack()))
|
||||
if providers[provider].supports_gpt_35_turbo:
|
||||
builder.row(InlineKeyboardButton(text="gpt 3.5 turbo",
|
||||
callback_data=Gpt4freeResult
|
||||
(user_id=str(user_id), provider=provider, model="gpt-3.5-turbo").pack()))
|
||||
builder.row(InlineKeyboardButton(text="🔙 Вернуться к провайдерам",
|
||||
callback_data=GptBackMenu(user_id=user_id, back_to="providers").pack()))
|
||||
builder.row(InlineKeyboardButton(text="Спасибо, не надо ❌", callback_data=GptStop(user_id=str(user_id)).pack()))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
# Gpt4All related keyboards
|
||||
def generate_gpt4all_page(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating list of GPT4All models.
|
||||
:param user_id:
|
||||
:return:
|
||||
"""
|
||||
models = GPT4All.list_models()
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
for model in models:
|
||||
builder.row(InlineKeyboardButton(
|
||||
text=model["name"],
|
||||
callback_data=Gpt4AllModel(user_id=str(user_id), index=str(models.index(model))).pack())
|
||||
)
|
||||
builder.row(InlineKeyboardButton(text="🔙 Вернуться к списку",
|
||||
callback_data=GptBackMenu(user_id=user_id, back_to="g4fcategory").pack()))
|
||||
builder.row(InlineKeyboardButton(text="Спасибо, не надо ❌",
|
||||
callback_data=GptStop(user_id=str(user_id)).pack()))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def gpt4all_model_menu(user_id: int, index: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for selection on of GPT4ALL models
|
||||
:param user_id:
|
||||
:param index:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Выбрать ✅",
|
||||
callback_data=Gpt4AllSelect(user_id=user_id, index=str(index)).pack())],
|
||||
[InlineKeyboardButton(text="🔙 Вернуться к списку",
|
||||
callback_data=GptBackMenu(user_id=user_id, back_to="g4amodels").pack())],
|
||||
[InlineKeyboardButton(text="Спасибо, не надо ❌",
|
||||
callback_data=GptStop(user_id=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
|
||||
|
||||
class TextGeneratrion(BasicFeature):
|
||||
"""
|
||||
A class, what have inside all handlers / functions
|
||||
related to text generation of bozenka
|
||||
"""
|
||||
|
||||
async def telegram_already_answering_handler(msg: Message, state: FSMContext) -> None:
|
||||
"""
|
||||
Giving response, if answering user now,
|
||||
but he still asks something
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer(
|
||||
"Подождите пожалуйста, мы уже генерируем ответ для вас, подождите, когда мы ответим на ваш передыдущий вопрос",
|
||||
reply_markup=delete_keyboard(admin_id=msg.from_user.id))
|
||||
|
||||
async def telegram_conversation_cmd_handler(msg: Message, state: FSMContext) -> None:
|
||||
"""
|
||||
/conversation command handler, start
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
if await state.get_state():
|
||||
return
|
||||
await msg.answer("Пожалуста, выберите сервис для ИИ.",
|
||||
reply_markup=telegram_text_categories_keyboard
|
||||
(user_id=msg.from_user.id))
|
||||
|
||||
async def telegram_cancel_cmd_handler(msg: Message, state: FSMContext) -> None:
|
||||
"""
|
||||
Canceling dialog with generative model
|
||||
Works on command /cancel
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
current = await state.get_state()
|
||||
if current is None:
|
||||
return
|
||||
await state.clear()
|
||||
await msg.answer("Удача ✅\n"
|
||||
"Диалог отменён!", reply_markup=delete_keyboard(admin_id=msg.from_user.id))
|
||||
|
||||
# G4F telegram category
|
||||
# All handlers and other stuff
|
||||
# All code and comments
|
||||
async def telegram_g4f_generate_handler(msg: Message, state: FSMContext) -> None:
|
||||
"""
|
||||
Generating answer if GPT4Free model and provider has been selected
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
await state.set_state(AnsweringGPT4Free.answering)
|
||||
|
||||
info = await state.get_data()
|
||||
|
||||
providers = generate_gpt4free_providers()
|
||||
reply = await msg.reply("Пожалуйста подождите, мы генерируем ответ от провайдера ⏰\n"
|
||||
"Если что-то пойдет не так, мы вам сообщим 👌")
|
||||
|
||||
current_messages = []
|
||||
if info.get("ready_to_answer"):
|
||||
for message in info["ready_to_answer"]:
|
||||
current_messages.append(message)
|
||||
|
||||
if not info.get("set_provider"):
|
||||
info["set_provider"] = None
|
||||
|
||||
current_messages.append({"role": "user", "content": msg.text})
|
||||
|
||||
response = ""
|
||||
try:
|
||||
response = await g4f.ChatCompletion.create_async(
|
||||
model=info["set_model"],
|
||||
messages=current_messages,
|
||||
provider=None if info["set_provider"] is None else providers[info["set_provider"]],
|
||||
stream=False
|
||||
)
|
||||
|
||||
except NameError or SyntaxError:
|
||||
try:
|
||||
response = g4f.ChatCompletion.create(
|
||||
model=info["set_model"],
|
||||
messages=current_messages,
|
||||
provider=None if info["set_provider"] is None else providers[info["set_provider"]],
|
||||
stream=False
|
||||
)
|
||||
except Exception as S:
|
||||
response = "Простите, произошла ошибка 😔\nЕсли это продолжается, пожалуйста используйте /cancel"
|
||||
logging.log(msg=f"Get an exception for generating answer={S}",
|
||||
level=logging.ERROR)
|
||||
except Exception as S:
|
||||
response = "Простите, произошла ошибка 😔\nЕсли это продолжается, пожалуйста используйте /cancel"
|
||||
logging.log(msg=f"Get an exception for generating answer={S}",
|
||||
level=logging.ERROR)
|
||||
finally:
|
||||
await reply.edit_text(text=response, reply_markup=text_response_keyboard(user_id=msg.from_user.id))
|
||||
current_messages.append({"role": "assistant", "content": response})
|
||||
await state.update_data(ready_to_answer=current_messages)
|
||||
await state.set_state(AnsweringGPT4Free.ready_to_answer)
|
||||
|
||||
async def telegram_instart_conversation_handler(call: CallbackQuery, callback_data: GptBackMenu,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what shows when clicking on button in /start menu
|
||||
:param call: CallbackQuery class
|
||||
:param state: FSMContext aiogram class
|
||||
:param callback_data: GptBackMenu class
|
||||
:return: Nothing
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id or await state.get_state():
|
||||
return
|
||||
await call.message.edit_text("Пожалуста, выберите сервис для ИИ.",
|
||||
reply_markup=telegram_text_categories_keyboard(user_id=call.from_user.id))
|
||||
|
||||
async def telegram_g4f_providers_handlers(call: CallbackQuery, callback_data: Gpt4FreeCategory,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what creating providers selecting menu.
|
||||
:param call: CallbackQuery class
|
||||
:param state: FSMContext aiogram class
|
||||
:param callback_data: Gpt4FreeCategory
|
||||
return: Nothing
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
logging.log(msg=f"Selected gpt4free category by user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
|
||||
await call.answer("Вы выбрали провайдеры 🤖")
|
||||
|
||||
await state.set_state(AnsweringGPT4Free.set_provider)
|
||||
await call.message.edit_text("Выберите пожалуйста одного из провайдеров 👨💻",
|
||||
reply_markup=telegram_gpt4free_providers_keyboard(user_id=call.from_user.id, page=0))
|
||||
|
||||
async def telegram_g4f_models_handler(call: CallbackQuery, callback_data: GptCategory, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what creating models selecting menu
|
||||
:param call: CallbackQuery class
|
||||
:param state: FSMContext aiogram class
|
||||
:param callback_data: GptCategory
|
||||
return: Nothing
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
await state.set_state(AnsweringGPT4Free.set_model)
|
||||
|
||||
await call.answer("Вы выбрали модели 🤖")
|
||||
|
||||
await call.message.edit_text("Выберите модель, с которой будете общаться 🤖",
|
||||
reply_markup=gpt4free_models_keyboard(user_id=call.from_user.id, page=0))
|
||||
|
||||
async def telegram_g4f_model_ready_handler(call: CallbackQuery, callback_data: Gpt4FreeModel,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what ending g4f model selecting
|
||||
:param call: CallbackQuery class
|
||||
:param callback_data: Gpt4FreeModel model
|
||||
:param state: FSMContext aiogram class
|
||||
:return: Nothing
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
await state.update_data(set_model=callback_data.model)
|
||||
await state.set_state(AnsweringGPT4Free.ready_to_answer)
|
||||
|
||||
await call.answer("Вы можете начать общаться 🤖")
|
||||
|
||||
await call.message.edit_text("Удача ✅\n"
|
||||
"Вы теперь можете спокойно вести диалог 🤖\n"
|
||||
f"Вы выбрали модель <b>{callback_data.model}</b>👾\n"
|
||||
"Чтобы прекратить общение, используйте /cancel ",
|
||||
reply_markup=delete_keyboard(admin_id=call.from_user.id))
|
||||
|
||||
async def telegram_g4f_next_model_handler(call: CallbackQuery, callback_data: Gpt4FreeModelPage,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what creating models selecting menu
|
||||
:param state: FSMContext aiogram class
|
||||
:param call: CallbackQuery class
|
||||
:param callback_data: Gpt4FreeModelPage class
|
||||
:return: None
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
await call.answer(f"Вы перелистнули на страницу {callback_data.page + 1}📄")
|
||||
|
||||
await call.message.edit_text("Выберите модель, с которой будете общаться 🤖",
|
||||
reply_markup=gpt4free_models_keyboard(user_id=call.from_user.id,
|
||||
page=callback_data.page))
|
||||
|
||||
async def telegram_g4f_category_handler(call: CallbackQuery, callback_data: GptCategory | GptBackMenu, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what creating providers selecting menu.
|
||||
:param state: FSMContext aiogram class
|
||||
:param call: CallbackQuery class
|
||||
:param callback_data: GptCategory class
|
||||
:return: None
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
logging.log(msg=f"Selected gpt4free category by user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
|
||||
if type(callback_data) == GptCategory:
|
||||
await state.update_data(set_category=callback_data.category)
|
||||
|
||||
await call.answer("Вы выбрали Gpt4Free 🤖")
|
||||
await call.message.edit_text("Выберите, по какому пункту мы будем вести диалог с нейронной сети 🤖",
|
||||
reply_markup=gpt4free_categories_keyboard(user_id=call.from_user.id))
|
||||
await call.answer("Выберите, по какому пункту мы будем вести диалог с нейронной сети 🤖")
|
||||
|
||||
async def telegram_g4f_back_provider_handler(call: CallbackQuery, callback_data: GptBackMenu,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what creating providers selecting menu.
|
||||
:param state: FSMContext aiogram class
|
||||
:param call: CallbackQuery telegram class
|
||||
:param callback_data: GptBackMenu class
|
||||
:return: None
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
logging.log(msg=f"Back to providers menu by user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
await state.set_state(AnsweringGPT4Free.set_provider)
|
||||
|
||||
await call.message.edit_text("Выберите пожалуйста одного из провайдеров 👨💻",
|
||||
reply_markup=telegram_gpt4free_providers_keyboard(page=0, user_id=callback_data.user_id))
|
||||
await call.answer("Выберите пожалуйста одного из провайдеров 👨💻")
|
||||
|
||||
async def telegram_g4f_by_provider_models(call: CallbackQuery, callback_data: Gpt4FreeProvider,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what creating models selecting menu.
|
||||
:param state: FSMContext aiogram class
|
||||
:param call: CallbackQuery telegram class
|
||||
:param callback_data: Gpt4FreeProvider Class
|
||||
:return: None
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
logging.log(msg=f"Selected gpt4free provider {callback_data.provider} by user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
|
||||
await state.update_data(set_provider=callback_data.provider)
|
||||
await state.set_state(AnsweringGPT4Free.set_model)
|
||||
|
||||
await call.message.edit_text("Выберите пожалуйста модель ИИ 👾",
|
||||
reply_markup=gpt4free_models_by_provider_keyboard(
|
||||
user_id=callback_data.user_id,
|
||||
provider=callback_data.provider,
|
||||
page=0
|
||||
))
|
||||
await call.answer("Выберите пожалуйста модель ИИ 👾")
|
||||
|
||||
async def telegram_g4f_provider_ready_handler(call: CallbackQuery, callback_data: Gpt4freeResult, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what says about getting ready to questions for ChatGPT from Gpt4Free.
|
||||
:param state: FSMContext aiogram class
|
||||
:param call: CallbackQuery telegram class
|
||||
:param callback_data: Gpt4freeResult
|
||||
:return: None
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
logging.log(msg=f"Selected gpt4free model {callback_data.model} by user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
|
||||
await state.update_data(set_model=callback_data.model)
|
||||
await state.set_state(AnsweringGPT4Free.ready_to_answer)
|
||||
|
||||
logging.log(msg=f"Loaded GPT answering status for user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
|
||||
await call.message.edit_text("Удача ✅\n"
|
||||
"Вы теперь можете спокойно вести диалог 🤖\n"
|
||||
f"Вы выбрали модель <b>{callback_data.model}</b>👾, от провайдера <b>{callback_data.provider}</b>👨💻\n"
|
||||
"Чтобы прекратить общение, используйте /cancel ",
|
||||
reply_markup=delete_keyboard(admin_id=callback_data.user_id))
|
||||
await call.answer("Вы теперь можете спокойно вести диалог 🤖")
|
||||
|
||||
async def telegram_g4f_models_by_provider_handler(call: CallbackQuery, callback_data: Gpt4FreeProvsModelPage,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what generates a next page of models for user.
|
||||
:param state: FSMContext aiogram class
|
||||
:param call: CallbackQuery telegram class
|
||||
:param callback_data: Gpt4FreeProvsModelPage
|
||||
:return: None
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
logging.log(msg=f"Changed page to {str(callback_data.page + 1)} user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
await call.message.edit_text(call.message.text,
|
||||
reply_markup=gpt4free_models_by_provider_keyboard(
|
||||
user_id=callback_data.user_id,
|
||||
provider=callback_data.provider,
|
||||
page=callback_data.page
|
||||
))
|
||||
await call.answer(f"Вы перелистали на страницу {callback_data.page + 1}📄")
|
||||
|
||||
async def telegram_next_g4f_providers_handler(call: CallbackQuery, callback_data: Gpt4FreeProviderPage,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what generates a next page of providers for user
|
||||
:param state: FSMContext aiogram class
|
||||
:param call: CallbackQuery telegram class
|
||||
:param callback_data: Gpt4FreeProviderPage class
|
||||
:return: None
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
logging.log(msg=f"Changed page to {str(callback_data.page + 1)} user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
await call.message.edit_text(call.message.text,
|
||||
reply_markup=telegram_gpt4free_providers_keyboard(user_id=callback_data.user_id,
|
||||
page=callback_data.page))
|
||||
await call.answer(f"Вы перелистнули на страницу {callback_data.page + 1}📄")
|
||||
|
||||
# G4A telegram handlers section
|
||||
# All code and commentaries here
|
||||
# All handlers here
|
||||
|
||||
async def telegram_g4a_generate_handler(msg: Message, state: FSMContext) -> None:
|
||||
"""
|
||||
Generating answer if Gpt4All has been selected
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
await state.set_state(AnsweringGpt4All.answering)
|
||||
|
||||
models = GPT4All.list_models()
|
||||
info = await state.get_data()
|
||||
answer = ""
|
||||
|
||||
main_msg = await msg.answer("Пожалуйста подождите, мы генерируем вам ответ ⏰\n"
|
||||
"Если что-то пойдет не так, мы вам сообщим 👌",
|
||||
reply_markup=text_response_keyboard(user_id=msg.from_user.id))
|
||||
|
||||
if not check(models[info["set_model"]]["filename"]):
|
||||
main_msg = await main_msg.edit_text(main_msg.text + "\nПодождите пожалуста, мы скачиваем модель...",
|
||||
reply_markup=main_msg.reply_markup)
|
||||
|
||||
try:
|
||||
# Setting Gpt4All model
|
||||
model = GPT4All(model_name=models[info['set_model']]['filename'],
|
||||
model_path=model_path,
|
||||
allow_download=True)
|
||||
# Setting our chat session if exist
|
||||
model.current_chat_session = [] if not info.get("ready_to_answer") else info["ready_to_answer"]
|
||||
# Generating answer
|
||||
with model.chat_session():
|
||||
answer = model.generate(msg.text)
|
||||
await state.update_data(ready_to_answer=model.current_chat_session)
|
||||
|
||||
except Exception as S:
|
||||
answer = "Простите, произошла ошибка 😔\nЕсли это продолжается, пожалуйста используйте /cancel"
|
||||
logging.log(msg=f"Get an exception for generating answer={S}",
|
||||
level=logging.ERROR)
|
||||
finally:
|
||||
await main_msg.edit_text(answer, reply_markup=text_response_keyboard(user_id=msg.from_user.id))
|
||||
|
||||
await state.set_state(AnsweringGpt4All.ready_to_answer)
|
||||
|
||||
async def telegram_g4a_handler(call: CallbackQuery, callback_data: GptCategory, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what shows list for gpt4all models
|
||||
:param state: FSMContext aiogram class
|
||||
:param call: CallbackQuery telegram class
|
||||
:param callback_data: GptCategory class
|
||||
:return: None
|
||||
"""
|
||||
if callback_data.user_id != call.from_user.id:
|
||||
return
|
||||
await state.set_state(AnsweringGpt4All.set_model)
|
||||
await call.message.edit_text("Выберите пожалуйста модель ИИ 👾",
|
||||
reply_markup=generate_gpt4all_page(user_id=call.from_user.id))
|
||||
|
||||
async def telegram_g4a_back_handler(call: CallbackQuery, callback_data: GptCategory, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what shows list for gpt4all models back
|
||||
:param state: FSMContext aiogram class
|
||||
:param call: CallbackQuery telegram class
|
||||
:param callback_data: GptCategory class
|
||||
:return: None
|
||||
"""
|
||||
if callback_data.user_id != call.from_user.id:
|
||||
return
|
||||
await state.set_state(AnsweringGpt4All.set_model)
|
||||
await call.message.edit_text("Выберите пожалуйста модель ИИ 👾",
|
||||
reply_markup=generate_gpt4all_page(user_id=call.from_user.id))
|
||||
|
||||
async def telegram_g4a_infomration_handler(call: CallbackQuery, callback_data: Gpt4AllModel,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what show information about clicked gpt4all model from list
|
||||
:param state: FSMContext aiogram class
|
||||
:param call: CallbackQuery telegram class
|
||||
:param callback_data: Gpt4AllModel class
|
||||
:return: None
|
||||
"""
|
||||
if callback_data.user_id != call.from_user.id:
|
||||
return
|
||||
models = GPT4All.list_models()
|
||||
name = models[callback_data.index]['name']
|
||||
await call.message.edit_text(f"{name}\n"
|
||||
f"Обученно на основе {models[callback_data.index]['parameters']} строк 👨💻",
|
||||
reply_markup=gpt4all_model_menu(user_id=call.from_user.id,
|
||||
index=callback_data.index))
|
||||
|
||||
async def telegram_g4a_end_handler(call: CallbackQuery, callback_data: Gpt4AllSelect,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what says about getting ready for question for Gpt4All model
|
||||
:param state: FSMContext aiogram class
|
||||
:param call: CallbackQuery telegram class
|
||||
:param callback_data: Gpt4AllSelect class
|
||||
:return: None
|
||||
"""
|
||||
if callback_data.user_id != call.from_user.id:
|
||||
return
|
||||
await state.update_data(set_model=callback_data.index)
|
||||
await state.set_state(AnsweringGpt4All.ready_to_answer)
|
||||
models = GPT4All.list_models()
|
||||
|
||||
await call.message.edit_text("Удача ✅\n"
|
||||
"Вы теперь можете спокойно вести диалог 🤖\n"
|
||||
f"Вы выбрали модель <b>{models[callback_data.index]['name']}</b>👾 от Gpt4All\n"
|
||||
"Чтобы прекратить общение, используйте /cancel ",
|
||||
reply_markup=delete_keyboard(admin_id=callback_data.user_id))
|
||||
|
||||
async def telegram_pages_handler(call: CallbackQuery) -> None:
|
||||
"""
|
||||
Query, made for helping purposes.
|
||||
Shows current page.
|
||||
:param call: CallbackQuery telegram class
|
||||
:return: None
|
||||
"""
|
||||
logging.log(msg=f"Showed helping info for user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
await call.answer("Здесь расположается текущая странница 📃")
|
||||
|
||||
async def telegram_stop_dialog_handler(call: CallbackQuery, callback_data: GptStop, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what stops dialog
|
||||
:param call: CallbackQuery telegram class
|
||||
:param callback_data: GptStop class
|
||||
:param state: None
|
||||
"""
|
||||
# Checking user_id of user
|
||||
if callback_data.user_id != call.from_user.id:
|
||||
return
|
||||
# Clearing state
|
||||
await state.clear()
|
||||
# Answering something
|
||||
await call.answer("Хорошо ✅")
|
||||
if await state.get_state() == AnsweringGPT4Free.ready_to_answer or await state.get_state() == AnsweringGpt4All.answering:
|
||||
await call.message.edit_text(text=call.message.text + "\n\nДиалог остановлен ✅\n",
|
||||
reply_markup=delete_keyboard(admin_id=call.from_user.id))
|
||||
else:
|
||||
await call.message.delete()
|
||||
|
||||
# Telegram feature settings
|
||||
telegram_category = "user"
|
||||
telegram_db_name = TelegramChatSettings.text_generation
|
||||
telegram_setting_in_list = True
|
||||
telegram_setting_name = "ИИ ЧатБот 🤖"
|
||||
telegram_setting_description = "<b>ИИ ЧатБот </b>🤖" \
|
||||
"\nЕсть поддержка:\n" \
|
||||
"- Моделей Gpt4All\n" \
|
||||
"- Провайдеров Gpt4Free и моделей\n" \
|
||||
"Для использования:\n" \
|
||||
"<pre>/conversations</pre>" \
|
||||
"\nНаходится в разработке, планируется в будущем. Следите за обновлениями 😘"
|
||||
telegram_commands: dict[str: str] = {
|
||||
'conversation': 'Starts conversation with text generative ai'
|
||||
}
|
||||
telegram_cmd_avaible = True # Is a feature have a commands
|
||||
telegram_message_handlers = (
|
||||
[telegram_conversation_cmd_handler, [Command(commands=["conversation"])]],
|
||||
[telegram_g4a_generate_handler, [AnsweringGpt4All.ready_to_answer, ~Command(commands=["cancel"])]],
|
||||
[telegram_g4f_generate_handler, [AnsweringGPT4Free.ready_to_answer, ~Command(commands=["cancel"])]],
|
||||
[telegram_already_answering_handler, [AnsweringGPT4Free.answering, AnsweringGpt4All.answering]]
|
||||
)
|
||||
telegram_callback_handlers = (
|
||||
# g4a
|
||||
[telegram_g4a_handler, [GptCategory.filter(F.category == "Gpt4All")]],
|
||||
[telegram_g4a_infomration_handler, [Gpt4AllModel.filter()]],
|
||||
[telegram_g4a_end_handler, [Gpt4AllSelect.filter()]],
|
||||
# g4f
|
||||
[telegram_g4f_category_handler, [GptCategory.filter(F.category == "Gpt4Free")]],
|
||||
[telegram_g4f_category_handler, [GptBackMenu.filter(F.back_to == "g4fcategory")]],
|
||||
# categories
|
||||
[telegram_g4f_models_handler, [Gpt4FreeCategory.filter(F.category == "models")]],
|
||||
[telegram_g4f_providers_handlers, [Gpt4FreeCategory.filter(F.category == "providers")]],
|
||||
# providers list
|
||||
[telegram_g4f_providers_handlers, [GptBackMenu.filter(F.back_to == "providers")]],
|
||||
[telegram_next_g4f_providers_handler, [Gpt4FreeProviderPage.filter()]],
|
||||
# models by provider list
|
||||
[telegram_g4f_models_by_provider_handler, [Gpt4FreeProvsModelPage.filter()]],
|
||||
[telegram_g4f_by_provider_models, [Gpt4FreeProvider.filter()]],
|
||||
# models list
|
||||
[telegram_g4f_next_model_handler, [Gpt4FreeModelPage.filter()]],
|
||||
# end features
|
||||
[telegram_g4f_model_ready_handler, [Gpt4FreeModel.filter()]],
|
||||
[telegram_g4f_provider_ready_handler, [Gpt4freeResult.filter()]],
|
||||
# stop talking
|
||||
[telegram_stop_dialog_handler, [GptStop.filter()]]
|
||||
)
|
74
bozenka/features/user/welcome.py
Normal file
74
bozenka/features/user/welcome.py
Normal file
|
@ -0,0 +1,74 @@
|
|||
import logging
|
||||
|
||||
from aiogram import Bot, F
|
||||
from aiogram.enums import ContentType
|
||||
from aiogram.types import Message, CallbackQuery
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.database.tables.telegram import TelegramChatSettings
|
||||
from bozenka.features.main import BasicFeature
|
||||
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
|
||||
|
||||
|
||||
class Welcome(BasicFeature):
|
||||
"""
|
||||
A class of pins related commands
|
||||
All staff related to it will be here
|
||||
"""
|
||||
|
||||
async def telegram_join_handler(msg: Message, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Message handler.
|
||||
Send welcome message, after adding new member to chat.
|
||||
Also works on adding bot to chat and sending welcome message.
|
||||
:param msg: Message telegram object
|
||||
:param session_maker: AsyncSessionmaker object
|
||||
:return: None
|
||||
"""
|
||||
for new in msg.new_chat_members:
|
||||
if new.id != msg.bot.id:
|
||||
logging.log(msg=f"Saing welcome for user_id={new.id}, chat_id={msg.chat.id}",
|
||||
level=logging.INFO)
|
||||
await msg.answer(
|
||||
f"Пользователь {new.mention_html()} переехал в конфу, благодаря {msg.from_user.mention_html()}👋",
|
||||
)
|
||||
await msg.delete()
|
||||
else:
|
||||
logging.log(msg=f"Saing welcome to administrators for chat_id={msg.chat.id}",
|
||||
level=logging.INFO)
|
||||
await msg.answer("Здраствуйте администраторы чата 👋\n"
|
||||
"Я - <b>бозенька</b>, мультифункциональный бот, разрабатываемый Bozo Developement\n"
|
||||
"Выдайте мне <b>полные права администратора</b> для моей полной работы.\n"
|
||||
"Чтобы настроить функционал, используйте /setup или кнопку под сообщением", )
|
||||
await SolutionSimpler.auto_settings(msg=msg, session=session_maker)
|
||||
|
||||
async def telegram_leave_handler(msg: Message, bot: Bot) -> None:
|
||||
"""
|
||||
Sens goodbye message, after deleting member from chat
|
||||
:param msg: Message telegram object
|
||||
:param bot: Aiogram bot object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.delete()
|
||||
if msg.from_user.id == bot.id:
|
||||
return
|
||||
logging.log(msg=f"Saing goodbye for user_id={msg.left_chat_member.id}, chat_id={msg.chat.id}",
|
||||
level=logging.INFO)
|
||||
await msg.answer(
|
||||
f"Пользователь {msg.left_chat_member.mention_html()} съехал с конфы, благодаря {msg.from_user.mention_html()}👋"
|
||||
)
|
||||
|
||||
# Telegram feature settings
|
||||
telegram_setting = TelegramChatSettings.welcome_messages
|
||||
telegram_category = "user"
|
||||
telegram_commands: dict[str: str] = {}
|
||||
telegram_setting_in_list = True
|
||||
telegram_setting_name = "Приветсвенные сообщения 👋"
|
||||
telegram_setting_description = "<b>Приветсвенные сообщения 👋</b>" \
|
||||
"\nПриветсвенные сообщения новым и ушедшим пользователям.",
|
||||
telegram_cmd_avaible = False # Is a feature have a commands
|
||||
telegram_message_handlers = [
|
||||
[telegram_leave_handler, [F.content_type == ContentType.LEFT_CHAT_MEMBER]],
|
||||
[telegram_join_handler, [F.content_type == ContentType.NEW_CHAT_MEMBERS]]
|
||||
]
|
||||
telegram_callback_handlers = []
|
|
@ -1,3 +1,6 @@
|
|||
import dataclasses
|
||||
|
||||
|
||||
|
||||
# List of text generative categories, what we support
|
||||
text_generative_categories = [
|
||||
|
@ -17,4 +20,4 @@ image_generative_size = [
|
|||
"576x1024",
|
||||
"1024x680",
|
||||
"680x1024"
|
||||
]
|
||||
]
|
||||
|
|
|
@ -4,14 +4,13 @@ import pathlib
|
|||
|
||||
model_path = os.getcwd() + "\\model\\"
|
||||
|
||||
|
||||
def check(model_filename: str) -> bool:
|
||||
"""
|
||||
Checking & downloading our gpt4all models
|
||||
Returns True if it's already downloaded
|
||||
Returns False if it's not downloaded
|
||||
:param model_filename: File name of gpt4all model
|
||||
:return:
|
||||
:return: Does it exist
|
||||
"""
|
||||
print(os.path.exists("models\\" + model_filename))
|
||||
return os.path.exists("models\\" + model_filename)
|
||||
|
|
0
bozenka/instances/__init__.py
Normal file
0
bozenka/instances/__init__.py
Normal file
6
bozenka/instances/basic_features_list.py
Normal file
6
bozenka/instances/basic_features_list.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from bozenka.features import Setup, Start
|
||||
|
||||
basic_features = [
|
||||
Setup,
|
||||
Start
|
||||
]
|
30
bozenka/instances/customizable_features_list.py
Normal file
30
bozenka/instances/customizable_features_list.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
import bozenka.features.admin
|
||||
from bozenka.features import *
|
||||
from bozenka.features.admin import *
|
||||
|
||||
customizable_features = [
|
||||
# Admin related category
|
||||
Moderation,
|
||||
Invite,
|
||||
Pins,
|
||||
Threads,
|
||||
ChatInformation,
|
||||
# User related category
|
||||
ImageGeneratrion,
|
||||
TextGeneratrion,
|
||||
Welcome,
|
||||
]
|
||||
|
||||
text_transcription = {
|
||||
"user": "Пользователи 👤",
|
||||
"admin": "Администраторы 👮♂"
|
||||
}
|
||||
|
||||
categorized_customizable_features = {}
|
||||
|
||||
for feature in customizable_features:
|
||||
if feature.telegram_setting_in_list:
|
||||
if feature.telegram_category in categorized_customizable_features.keys():
|
||||
categorized_customizable_features[feature.telegram_category].append(feature)
|
||||
else:
|
||||
categorized_customizable_features[feature.telegram_category] = [feature]
|
|
@ -1,28 +1,66 @@
|
|||
import os
|
||||
import logging
|
||||
import g4f
|
||||
import os
|
||||
|
||||
from aiogram import Dispatcher, Bot
|
||||
from aiogram.types import BotCommand
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.instances.telegram.handlers import register_handlers
|
||||
from bozenka.instances.telegram.utils.simpler import list_of_commands
|
||||
from bozenka.instances.basic_features_list import basic_features
|
||||
from bozenka.instances.customizable_features_list import customizable_features
|
||||
from bozenka.instances.telegram.queries import *
|
||||
|
||||
|
||||
async def register_all_features(list_of_features: list, dispatcher: Dispatcher, bot: Bot) -> None:
|
||||
"""
|
||||
Registers all features / handlers avaible in bozenka
|
||||
:param list_of_features: List of features
|
||||
:param dispatcher: Dispatcher aiogram class
|
||||
:param bot: Bot aiogram class
|
||||
:return: None
|
||||
"""
|
||||
cmd_list = []
|
||||
for feature in list_of_features:
|
||||
|
||||
if feature.telegram_cmd_avaible:
|
||||
for command, description in feature.telegram_commands.items():
|
||||
cmd_list.append(BotCommand(command=command, description=description))
|
||||
|
||||
for message_handler in feature.telegram_message_handlers:
|
||||
dispatcher.message.register(message_handler[0], *message_handler[1])
|
||||
|
||||
for callback_query_handler in feature.telegram_callback_handlers:
|
||||
dispatcher.callback_query.register(callback_query_handler[0], *callback_query_handler[1])
|
||||
|
||||
if not (commands := await bot.get_my_commands()):
|
||||
await bot.set_my_commands(cmd_list)
|
||||
else:
|
||||
for cmd in cmd_list:
|
||||
commands.append(cmd)
|
||||
await bot.set_my_commands(commands)
|
||||
|
||||
|
||||
async def launch_telegram_instance(session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Launches telegram bot with token from enviroment
|
||||
:param session_maker:
|
||||
:return:
|
||||
Launch bozenka telegram instance with token from enviroment
|
||||
:param session_maker: AsyncSessionMaker SqlAlchemy object
|
||||
:return: None
|
||||
"""
|
||||
logging.log(msg="-" * 50 + "TELEGRAM INSTANCE LAUNCH" + "-" * 50, level=logging.INFO)
|
||||
logging.log(msg="-" * 50 + "TELEGRAM BOZENKA INSTANCE LAUNCH" + "-" * 50, level=logging.INFO)
|
||||
|
||||
bot = Bot(token=os.getenv("tg_bot_token"), parse_mode="HTML")
|
||||
|
||||
cmd_of_bot = []
|
||||
for command in list_of_commands:
|
||||
cmd_of_bot.append(BotCommand(command=command[0], description=command[1]))
|
||||
await bot.set_my_commands(cmd_of_bot)
|
||||
|
||||
dp = Dispatcher()
|
||||
await dp.start_polling(bot, session_maker=session_maker, on_startup=[register_handlers(dp)])
|
||||
|
||||
await bot.delete_my_commands()
|
||||
|
||||
# Registering other handlers
|
||||
dp.callback_query.register(delete_callback_handler, DeleteMenu.filter())
|
||||
dp.callback_query.register(hide_menu_handler, HideMenu.filter())
|
||||
|
||||
await dp.start_polling(bot,
|
||||
session_maker=session_maker, # Pass your async_sessionmaker here, you can do dependency injection
|
||||
on_startup=[
|
||||
await register_all_features(list_of_features=customizable_features, dispatcher=dp, bot=bot),
|
||||
await register_all_features(list_of_features=basic_features, dispatcher=dp, bot=bot)
|
||||
|
||||
])
|
||||
|
|
|
@ -3,7 +3,6 @@ from aiogram.types import Message
|
|||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.database.tables.telegram import get_chat_configuration, get_chat_config_value
|
||||
from bozenka.instances.telegram.utils.simpler import list_of_features
|
||||
|
||||
|
||||
class IsSettingEnabled(Filter):
|
||||
|
@ -11,17 +10,16 @@ class IsSettingEnabled(Filter):
|
|||
Check, does chat have enabled required feature
|
||||
"""
|
||||
|
||||
def __init__(self, setting: str) -> None:
|
||||
def __init__(self, setting) -> None:
|
||||
self.setting = setting
|
||||
|
||||
async def __call__(self, msg: Message, session_maker: async_sessionmaker) -> bool:
|
||||
setting_object = None
|
||||
for key in list_of_features.items():
|
||||
for feature in list_of_features[key]:
|
||||
if feature.setting_name == self.setting:
|
||||
setting_object = feature
|
||||
else:
|
||||
continue
|
||||
"""
|
||||
Working after calling this filter
|
||||
:param msg: Message telegram boject
|
||||
:param session_maker: AsyncSessionMaker SqlAlchemy object
|
||||
:return: Is config enabled
|
||||
"""
|
||||
|
||||
return await get_chat_config_value(chat_id=msg.chat.id, session=session_maker, setting=setting_object)
|
||||
return await get_chat_config_value(chat_id=msg.chat.id, session=session_maker, setting=self.setting)
|
||||
|
178
bozenka/instances/telegram/filters/permissions.py
Normal file
178
bozenka/instances/telegram/filters/permissions.py
Normal file
|
@ -0,0 +1,178 @@
|
|||
from typing import Any
|
||||
|
||||
from aiogram.filters import Filter
|
||||
from aiogram.methods import GetChatMember
|
||||
from aiogram.types import Message, ChatPermissions, CallbackQuery
|
||||
from aiogram.enums import ChatMemberStatus, ChatType
|
||||
|
||||
from bozenka.instances.telegram.utils.delete import delete_keyboard
|
||||
|
||||
|
||||
class UserHasPermissions(Filter):
|
||||
"""
|
||||
Check, does user have permissions, what user need to work with bot.
|
||||
"""
|
||||
# List of permissions avaible to users.
|
||||
# Basic permissions for administration and user
|
||||
permissions = [
|
||||
"can_manage_chat",
|
||||
"can_delete_messages",
|
||||
"can_manage_video_chats",
|
||||
"can_restrict_members",
|
||||
"can_promote_members",
|
||||
"can_change_info",
|
||||
"can_invite_users",
|
||||
"can_post_messages",
|
||||
"can_edit_messages",
|
||||
"can_pin_messages",
|
||||
"can_manage_topics",
|
||||
"can_send_messages",
|
||||
"can_send_audios",
|
||||
"can_send_documents",
|
||||
"can_send_photos",
|
||||
"can_send_videos",
|
||||
"can_send_video_notes",
|
||||
"can_send_voice_notes",
|
||||
"can_send_polls",
|
||||
"can_send_other_messages",
|
||||
"can_add_web_page_previews",
|
||||
]
|
||||
|
||||
def __init__(self, perms: list[Any]) -> None:
|
||||
self.perms = perms
|
||||
|
||||
@staticmethod
|
||||
async def check_permissions(permission, msg: Message) -> bool:
|
||||
"""
|
||||
Checking permissions, included to user.
|
||||
:return:
|
||||
"""
|
||||
if permission.count(False) > 0 or permission.count(None) > 0:
|
||||
await msg.answer("Ошибка ❌\n"
|
||||
"У вас нет прав на использование этой комманды 🚫")
|
||||
return False
|
||||
return True
|
||||
|
||||
def generate_perms_list(self, user) -> list[Any]:
|
||||
"""
|
||||
Generates list of permissions for user.
|
||||
:param user: User telegram object
|
||||
:return: List
|
||||
"""
|
||||
permission = []
|
||||
for rule in self.perms:
|
||||
if rule in self.permissions:
|
||||
exec(f"permission.append(user.{rule})")
|
||||
return permission
|
||||
|
||||
async def __call__(self, msg: Message) -> bool:
|
||||
"""
|
||||
Working after catching a call from aiogram
|
||||
:param msg: Message telegram object
|
||||
:param self: A self object of this class
|
||||
:return: None
|
||||
"""
|
||||
user = await msg.chat.get_member(msg.from_user.id)
|
||||
if user.status != ChatMemberStatus.CREATOR:
|
||||
permission = self.generate_perms_list(user)
|
||||
else:
|
||||
permission = None
|
||||
|
||||
return True if user.status == ChatMemberStatus.CREATOR else self.check_permissions(permission, msg)
|
||||
|
||||
|
||||
class BotHasPermissions(UserHasPermissions):
|
||||
"""
|
||||
Check, does bot have permissions, what user need to work with bot.
|
||||
"""
|
||||
|
||||
async def __call__(self, msg: Message, *args, **kwargs) -> bool:
|
||||
"""
|
||||
Working after catching a call from aiogram
|
||||
:param msg: Message telegram object
|
||||
:param self: A self object of this class
|
||||
:return: None
|
||||
"""
|
||||
bot = await msg.chat.get_member(msg.chat.bot.id)
|
||||
permission = self.generate_perms_list(bot)
|
||||
return await self.check_permissions(permission, msg)
|
||||
|
||||
|
||||
class IsOwner(Filter):
|
||||
"""
|
||||
Checks, is memeber is owner of this chat
|
||||
"""
|
||||
|
||||
def __init__(self, is_admin: bool) -> None:
|
||||
"""
|
||||
Basic init class
|
||||
:param is_admin: Is admin status
|
||||
:return: Nothing
|
||||
"""
|
||||
self.is_admin = is_admin
|
||||
|
||||
async def __call__(self, msg: Message | CallbackQuery) -> bool:
|
||||
"""
|
||||
Working after catching a call from aiogram
|
||||
:param msg: Message or CallbackQuery telegram object
|
||||
:param self: A self object of this class
|
||||
:return: None
|
||||
"""
|
||||
if type(msg) is CallbackQuery:
|
||||
msg = msg.message
|
||||
user = await msg.chat.get_member(msg.from_user.id)
|
||||
if ChatMemberStatus.CREATOR != user.status:
|
||||
await msg.answer("Ошибка ❌\n"
|
||||
"У вас нет прав на использование этой комманды 🚫")
|
||||
return ChatMemberStatus.CREATOR == user.status
|
||||
|
||||
|
||||
class IsAdminFilter(Filter):
|
||||
"""
|
||||
Checks, is member of chat is admin and
|
||||
does bot have administration rights
|
||||
"""
|
||||
|
||||
def __init__(self, is_user_admin: bool, is_bot_admin: bool) -> None:
|
||||
"""
|
||||
Basic init class
|
||||
|
||||
"""
|
||||
self.is_user_admin = is_user_admin
|
||||
self.is_bot_admin = is_bot_admin
|
||||
|
||||
async def __call__(self, msg: Message) -> bool:
|
||||
"""
|
||||
Working after catching a call from aiogram
|
||||
:param msg: Message telegram object
|
||||
:param self: A self object of this class
|
||||
:return: None
|
||||
"""
|
||||
user = await msg.chat.get_member(msg.from_user.id)
|
||||
bot = await msg.chat.get_member(msg.bot.id)
|
||||
|
||||
if msg.chat.type == ChatType.PRIVATE:
|
||||
return False
|
||||
|
||||
if ChatMemberStatus.ADMINISTRATOR != user.status and ChatMemberStatus.CREATOR != user.status:
|
||||
if bot.status != ChatMemberStatus.ADMINISTRATOR:
|
||||
await msg.reply("Ошибка ❌\n"
|
||||
"У вас нет прав на использование этой комманды. \n"
|
||||
"У меня нет прав для осуществления этой комманды 🚫",
|
||||
reply_markup=delete_keyboard())
|
||||
return False
|
||||
else:
|
||||
await msg.reply("Ошибка ❌\n"
|
||||
"У вас нет прав на использование этой комманды 🚫",
|
||||
reply_markup=delete_keyboard())
|
||||
return False
|
||||
|
||||
if bot.status != ChatMemberStatus.ADMINISTRATOR:
|
||||
await msg.reply("Ошибка ❌\n"
|
||||
"У меня нет прав для осуществления этой комманды 🚫",
|
||||
reply_markup=delete_keyboard())
|
||||
return False
|
||||
|
||||
if ChatMemberStatus.CREATOR == user.status:
|
||||
return True
|
||||
return ChatMemberStatus.ADMINISTRATOR == user.status or ChatMemberStatus.CREATOR == user.status
|
|
@ -1,25 +0,0 @@
|
|||
import logging
|
||||
|
||||
from aiogram import Dispatcher
|
||||
|
||||
from bozenka.instances.telegram.handlers.chat_admin import register_admin_cmd
|
||||
from bozenka.instances.telegram.handlers.queries import register_queries
|
||||
from bozenka.instances.telegram.handlers.dev import register_dev_cmd
|
||||
from bozenka.instances.telegram.handlers.main import register_main_cmd
|
||||
from bozenka.instances.telegram.handlers.chat_user import register_user_cmd
|
||||
from bozenka.instances.telegram.utils.middleware import register_middlewares
|
||||
|
||||
|
||||
def register_handlers(dp: Dispatcher) -> None:
|
||||
"""
|
||||
Registers all handlers
|
||||
:param dp:
|
||||
:return:
|
||||
"""
|
||||
logging.log(msg="Starting registering all handlers", level=logging.INFO)
|
||||
register_dev_cmd(dp)
|
||||
register_user_cmd(dp)
|
||||
register_admin_cmd(dp)
|
||||
register_main_cmd(dp)
|
||||
register_queries(dp)
|
||||
register_middlewares(dp)
|
|
@ -1,74 +0,0 @@
|
|||
|
||||
|
||||
import logging
|
||||
|
||||
from aiogram import Router, F
|
||||
from aiogram.filters import Command
|
||||
|
||||
from bozenka.instances.telegram.handlers.chat_admin.help import *
|
||||
from bozenka.instances.telegram.handlers.chat_admin.mutes import mute, unmute
|
||||
from bozenka.instances.telegram.handlers.chat_admin.pins import pin, unpin, unpin_all
|
||||
from bozenka.instances.telegram.handlers.chat_admin.topics import *
|
||||
from bozenka.instances.telegram.handlers.chat_admin.bans import ban_command, unban_command
|
||||
from bozenka.instances.telegram.utils.filters import *
|
||||
|
||||
|
||||
def register_admin_cmd(router: Router) -> None:
|
||||
"""
|
||||
Registers all commands related to administrators in group.
|
||||
All commands there require access to some group perms.
|
||||
:param router:
|
||||
:return:
|
||||
"""
|
||||
logging.log(msg="Registering administrator commands", level=logging.INFO)
|
||||
|
||||
# Ban / Unban commands handler
|
||||
router.message.register(ban_command, Command(commands="ban"),
|
||||
IsAdminFilter(True))
|
||||
router.message.register(ban_command, Command(commands="ban"),
|
||||
IsAdminFilter(True), F.reply_to_message.text)
|
||||
router.message.register(unban_command, Command(commands="unban"),
|
||||
IsAdminFilter(True), F.reply_to_message.text)
|
||||
|
||||
# Mute / Unmute commands handler
|
||||
router.message.register(mute, Command(commands=["mute", "re"]), UserHasPermissions(["can_restrict_members"]),
|
||||
BotHasPermissions(["can_restrict_members"]))
|
||||
router.message.register(unmute, Command(commands=["unmute"]), UserHasPermissions(["can_restrict_members"]),
|
||||
BotHasPermissions(["can_restrict_members"]))
|
||||
|
||||
# Pin / Unpin / Unpinall commands handler
|
||||
router.message.register(pin, Command(commands="pin"), UserHasPermissions(["can_pin_messages"]),
|
||||
BotHasPermissions(["can_pin_messages"]), F.reply_to_message.text)
|
||||
router.message.register(unpin, Command(commands="unpin"), UserHasPermissions(["can_pin_messages"]),
|
||||
BotHasPermissions(["can_pin_messages"]), F.reply_to_message.text)
|
||||
router.message.register(unpin_all, Command(commands="unpin_all"), IsAdminFilter(True),
|
||||
BotHasPermissions(["can_pin_messages"]), F.reply_to_message.text)
|
||||
|
||||
# Topic managment handlers
|
||||
router.message.register(reopen_topic, Command(commands=["reopen_topic", "open_topic", "open"]),
|
||||
UserHasPermissions(["can_manage_topics"]),
|
||||
BotHasPermissions(["can_manage_topics"]), F.chat.is_forum)
|
||||
router.message.register(close_topic, Command(commands=["close_topic", "close"]),
|
||||
UserHasPermissions(["can_manage_topics"]),
|
||||
BotHasPermissions(["can_manage_topics"]), F.chat.is_forum)
|
||||
router.message.register(close_general_topic, Command(commands=["close_general"]),
|
||||
UserHasPermissions(["can_manage_topics"]),
|
||||
BotHasPermissions(["can_manage_topics"]), F.chat.is_forum)
|
||||
router.message.register(reopen_general_topic, Command(commands=["reopen_general", "open_general"]),
|
||||
UserHasPermissions(["can_manage_topics"]),
|
||||
BotHasPermissions(["can_manage_topics"]), F.chat.is_forum)
|
||||
router.message.register(hide_general_topic, Command(commands=["hide_general"]),
|
||||
UserHasPermissions(["can_manage_topics"]),
|
||||
BotHasPermissions(["can_manage_topics"]), F.chat.is_forum)
|
||||
router.message.register(unhide_general_topic, Command(commands=["unhide_general", "show_general"]),
|
||||
UserHasPermissions(["can_manage_topics"]),
|
||||
BotHasPermissions(["can_manage_topics"]), F.chat.is_forum)
|
||||
|
||||
# Helpig handlers
|
||||
router.message.register(help_ban, Command(commands=["ban"]))
|
||||
router.message.register(help_unban, Command(commands=["unban"]))
|
||||
router.message.register(help_mute, Command(commands=["mute"]))
|
||||
router.message.register(help_unmute, Command(commands=["mute"]))
|
||||
router.message.register(help_pin, Command(commands=["pin"]))
|
||||
router.message.register(help_unpin, Command(commands=["unpin"]))
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
from aiogram.filters import CommandObject
|
||||
from aiogram.types import Message
|
||||
from aiogram.enums import ChatMemberStatus
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.database.tables.telegram import get_chat_config_value
|
||||
from bozenka.instances.telegram.utils.keyboards import ban_keyboard, delete_keyboard
|
||||
|
||||
from bozenka.instances.telegram.utils.simpler import SolutionSimpler, ru_cmds, list_of_features
|
||||
|
||||
|
||||
async def ban_command(msg: Message, command: CommandObject, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
/ban command function, supports time and reasons.
|
||||
:param msg: Message telegram object
|
||||
:param command: Object of telegram command
|
||||
:param session_maker: Session maker object of SqlAlchemy
|
||||
:return: Nothing
|
||||
"""
|
||||
banned_user = await msg.chat.get_member(msg.reply_to_message.from_user.id)
|
||||
send_to_dm = await get_chat_config_value(chat_id=msg.chat.id, session=session_maker, setting=list_of_features["Admin"][4])
|
||||
send_notification = await get_chat_config_value(chat_id=msg.chat.id, session=session_maker, setting=list_of_features["Admin"][5])
|
||||
|
||||
where_send = {
|
||||
True: msg.from_user.id,
|
||||
False: msg.chat.id
|
||||
}
|
||||
|
||||
if banned_user.status == ChatMemberStatus.KICKED:
|
||||
await msg.bot.send_message(chat_id=where_send[send_to_dm],
|
||||
text="Ошибка ❌\n"
|
||||
"Этот пользователь уже удален из группы",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
await msg.answer()
|
||||
return
|
||||
|
||||
config = await SolutionSimpler.ban_user(msg, command, session_maker)
|
||||
if config["reason"] and config["ban_time"]:
|
||||
await msg.answer("Удача ✅\n"
|
||||
f"Пользователь {msg.reply_to_message.from_user.mention_html()} был заблокирован пользователем {msg.from_user.mention_html()}.\n"
|
||||
f"По причине {config['reason']}, до даты {config['ban_time']}",
|
||||
reply_markup=ban_keyboard(msg.from_user.id, msg.reply_to_message.from_user.id))
|
||||
elif config["reason"]:
|
||||
await msg.answer(
|
||||
"Удача ✅\n"
|
||||
f"Пользователь {msg.reply_to_message.from_user.mention_html()} был заблокирован пользователем {msg.reply_to_message.from_user.mention_html()}.\n"
|
||||
f"По причине {config['reason']}.",
|
||||
reply_markup=ban_keyboard(admin_id=msg.from_user.id, ban_id=msg.reply_to_message.from_user.id)
|
||||
)
|
||||
elif config["ban_time"]:
|
||||
await msg.answer(
|
||||
"Удача ✅\n"
|
||||
f"Пользователь {msg.reply_to_message.from_user.mention_html()} был заблокирован пользователем {msg.from_user.mention_html()}, до даты {config['ban_time']}",
|
||||
reply_markup=ban_keyboard(admin_id=msg.from_user.id, ban_id=msg.reply_to_message.from_user.id)
|
||||
)
|
||||
else:
|
||||
await msg.answer(
|
||||
"Удача ✅\n"
|
||||
f"Пользователь {msg.reply_to_message.from_user.mention_html()} был заблокирован пользователем {msg.from_user.mention_html()}.",
|
||||
reply_markup=ban_keyboard(msg.from_user.id, msg.reply_to_message.from_user.id)
|
||||
)
|
||||
|
||||
|
||||
async def unban_command(msg: Message, command: CommandObject, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
/unban command function
|
||||
:param msg: Message telegram object
|
||||
:param command: Object of telegram command
|
||||
:param session_maker: Session maker object of SqlAlchemy
|
||||
"""
|
||||
await SolutionSimpler.unban_user(msg, session_maker)
|
||||
unbanned_user = await msg.chat.get_member(msg.reply_to_message.from_user.id)
|
||||
if unbanned_user.is_member and unbanned_user.status != ChatMemberStatus.KICKED:
|
||||
await msg.answer(
|
||||
"Ошибка ❌\n"
|
||||
"Этот пользователь не находится в бане.",
|
||||
reply_markup=delete_keyboard(admin_id=msg.from_user.id)
|
||||
)
|
||||
elif not command.text:
|
||||
await msg.answer(
|
||||
"Удача ✅\n"
|
||||
f"Пользователь {msg.reply_to_message.from_user.mention_html()} был разблокирован пользователем {msg.from_user.mention_html()}.\n",
|
||||
reply_markup=ban_keyboard(admin_id=msg.from_user.id, ban_id=msg.reply_to_message.from_user.id)
|
||||
)
|
||||
else:
|
||||
await msg.answer(
|
||||
"Удача ✅\n"
|
||||
f"Пользователь {msg.reply_to_message.from_user.mention_html()} был разблокирован пользователем {msg.from_user.mention_html()}.\n"
|
||||
f"По причине {CommandObject.text}.",
|
||||
reply_markup=ban_keyboard(admin_id=msg.from_user.id, ban_id=msg.reply_to_message.from_user.id)
|
||||
)
|
||||
|
||||
|
||||
async def status_command(msg: Message, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
/status command function
|
||||
Checks is user banned and muted
|
||||
:param msg: Message telegram object
|
||||
:param session_maker: Session maker object of SqlAlchemy
|
||||
:return:
|
||||
"""
|
||||
config = await SolutionSimpler.get_status(msg, session_maker)
|
||||
msg_text = ""
|
||||
if config["is_banned"]:
|
||||
msg_text += "Находится в бане"
|
||||
if config["ban_reason"]:
|
||||
msg_text += f"по причине <code>{config['ban_reason']}</code>"
|
||||
msg_text += "🔨\n"
|
||||
if config["is_muted"]:
|
||||
msg_text += "Находится в муте"
|
||||
if config["mute_reason"]:
|
||||
msg_text += f"по причине <code>{config['mute_reason']}</code>"
|
||||
msg_text += "🤐\n"
|
||||
await msg.answer(msg_text, reply_markup=delete_keyboard(msg.from_user.id))
|
|
@ -1,76 +0,0 @@
|
|||
from aiogram.types import Message
|
||||
|
||||
from bozenka.instances.telegram.utils.keyboards import delete_keyboard
|
||||
|
||||
|
||||
async def help_ban(msg: Message) -> None:
|
||||
"""
|
||||
Shows help message for /ban
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("Использование:\n"
|
||||
"<pre>/ban [время блокировки] [причина блокировки]</pre>\n"
|
||||
"Ответьте на сообщение, чтобы заблокировать пользователя",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
|
||||
async def help_unban(msg: Message) -> None:
|
||||
"""
|
||||
Shows help message for /unban
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("Использование:\n"
|
||||
"<pre>/unban</pre>\n"
|
||||
"Ответьте на сообщение, чтобы разблокировать пользователя",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
|
||||
async def help_mute(msg: Message) -> None:
|
||||
"""
|
||||
Shows help message for /mute
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("Использование:\n"
|
||||
"<pre>/mute [время мута] [причина мута]</pre>\n"
|
||||
"Ответьте на сообщение, чтобы замутить пользователя",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
|
||||
async def help_unmute(msg: Message) -> None:
|
||||
"""
|
||||
Shows help message for /unmute
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("Использование:\n"
|
||||
"<pre>/unmute</pre>\n"
|
||||
"Ответьте на сообщение, чтобы замутить пользователя",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
|
||||
async def help_pin(msg: Message) -> None:
|
||||
"""
|
||||
Shows help message for /mute
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("Использование:\n"
|
||||
"<pre>/pin</pre>\n"
|
||||
"Ответьте на сообщение, чтобы закрепить сообщение",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
|
||||
async def help_unpin(msg: Message) -> None:
|
||||
"""
|
||||
Shows help message for /mute
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer("Использование:\n"
|
||||
"<pre>/unpin</pre>\n"
|
||||
"Ответьте на сообщение, чтобы открепить сообщение",
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
from aiogram.filters import CommandObject
|
||||
from aiogram.types import Message as Message
|
||||
from aiogram.enums import ChatMemberStatus
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
from bozenka.instances.telegram.utils.keyboards import mute_keyboard, unmute_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
|
||||
|
||||
|
||||
async def mute(msg: Message, command: CommandObject, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Handler of command /mute
|
||||
Restricts member from using chat
|
||||
:param msg: Message telegram object
|
||||
:param command: Object of telegram command
|
||||
:param session_maker: Session maker object of SqlAlchemy
|
||||
:return: Nothing
|
||||
"""
|
||||
restricting = await msg.chat.get_member(msg.reply_to_message.from_user.id)
|
||||
if restricting.status == ChatMemberStatus.LEFT or restricting.status == ChatMemberStatus.KICKED:
|
||||
return
|
||||
config = await SolutionSimpler.mute_user(msg, command, session_maker)
|
||||
if config["mute_time"] and config["reason"] != "":
|
||||
await msg.answer("Удача ✅\n"
|
||||
f"{msg.from_user.mention_html('Этот пользователь')} запретил писать "
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('этому пользователю')}.\n"
|
||||
f"По причине {config['reason']}, до даты {config['mute_time']}",
|
||||
reply_markup=mute_keyboard(msg.from_user.id, restricting.user.id))
|
||||
elif config["reason"] != "":
|
||||
await msg.answer("Удача ✅\n"
|
||||
f"{msg.from_user.mention_html('Этот пользователь')} запретил писать "
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('этому пользователю')}.\n"
|
||||
f"По причине {config['reason']}",
|
||||
reply_markup=mute_keyboard(msg.from_user.id, restricting.user.id))
|
||||
elif config["mute_time"]:
|
||||
await msg.answer("Удача ✅\n"
|
||||
f"{msg.from_user.mention_html('Этот пользователь')} запретил писать "
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('этому пользователю')}.\n"
|
||||
f"До даты {config['mute_time']}",
|
||||
reply_markup=mute_keyboard(msg.from_user.id, restricting.user.id))
|
||||
else:
|
||||
await msg.answer("Удача ✅\n"
|
||||
f"{msg.from_user.mention_html('Этот пользователь')} запретил писать "
|
||||
f"сообщения пользователю {msg.reply_to_message.from_user.mention_html()}.\n",
|
||||
reply_markup=mute_keyboard(msg.from_user.id, restricting.user.id))
|
||||
|
||||
|
||||
async def unmute(msg: Message, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Handler of command /unmute
|
||||
Gives access member to send messages into chat
|
||||
:param msg: Message telegram object
|
||||
:param session_maker: Session maker object of SqlAlchemy
|
||||
:return: Nothing
|
||||
"""
|
||||
await SolutionSimpler.unmute_user(msg, session_maker)
|
||||
await msg.answer("Удача ✅"
|
||||
f"{msg.from_user.mention_html('Этот пользователь')} разрешил писать\n"
|
||||
f"сообщения {msg.reply_to_message.from_user.mention_html('этому пользователю')}",
|
||||
reply_markup=unmute_keyboard(msg.from_user.id, msg.reply_to_message.from_user.id))
|
|
@ -1,40 +0,0 @@
|
|||
from aiogram.types import Message as Message
|
||||
from bozenka.instances.telegram.utils.keyboards import unpin_msg_keyboard, pin_msg_keyboard, delete_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
|
||||
|
||||
|
||||
async def pin(msg: Message) -> None:
|
||||
"""
|
||||
/pin command function, pins replied command
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await SolutionSimpler.pin_msg(msg)
|
||||
await msg.answer("Удача ✅\n"
|
||||
"Сообщение было закреплено 📌",
|
||||
reply_markup=pin_msg_keyboard(msg_id=msg.reply_to_message.message_id, user_id=msg.from_user.id))
|
||||
|
||||
|
||||
async def unpin(msg: Message) -> None:
|
||||
"""
|
||||
/unpin command function, unpins replied command
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await SolutionSimpler.unpin_msg(msg)
|
||||
await msg.answer("Удача ✅\n"
|
||||
"Сообщение было откреплено 📌",
|
||||
reply_markup=unpin_msg_keyboard(msg_id=msg.reply_to_message.message_id, user_id=msg.from_user.id))
|
||||
|
||||
|
||||
async def unpin_all(msg: Message) -> None:
|
||||
"""
|
||||
/unpin_all command function, unpins all messages in chat
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await SolutionSimpler.unpin_all_messages(msg)
|
||||
await msg.answer("Удача ✅\n"
|
||||
"Все сообщения были откреплены 📌",
|
||||
reply_markup=delete_keyboard(admin_id=msg.from_user.id))
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
from aiogram import Bot
|
||||
from aiogram.filters import CommandObject
|
||||
from aiogram.types import Message as Message
|
||||
from bozenka.instances.telegram.utils.keyboards import delete_keyboard, close_thread_keyboard, open_thread_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
|
||||
|
||||
|
||||
async def close_topic(msg: Message, bot: Bot) -> None:
|
||||
"""
|
||||
/close command function. Closing thread
|
||||
:param msg: Message telegram object
|
||||
:param bot: Object of telegram bot
|
||||
:return: Nothing
|
||||
"""
|
||||
config = await SolutionSimpler.close_topic(msg=msg)
|
||||
await msg.answer(config[0],
|
||||
reply_markup=close_thread_keyboard(user_id=msg.from_user.id)
|
||||
if config[1] else delete_keyboard(msg.from_user.id))
|
||||
|
||||
|
||||
async def reopen_topic(msg: Message, bot: Bot) -> None:
|
||||
"""
|
||||
/open command function. Opens thread
|
||||
:param msg: Message telegram object
|
||||
:param bot: Object of telegram bot
|
||||
:return: Nothing
|
||||
"""
|
||||
config = await SolutionSimpler.open_topic(msg=msg)
|
||||
await msg.answer(config[0],
|
||||
reply_markup=open_thread_keyboard(user_id=msg.from_user.id)
|
||||
if config[1] else delete_keyboard(msg.from_user.id))
|
||||
|
||||
|
||||
async def close_general_topic(msg: Message, bot: Bot) -> None:
|
||||
"""
|
||||
/close_general command function. Closes general thread
|
||||
:param msg: Message telegram object
|
||||
:param bot: Object of telegram bot
|
||||
:return: Nothing
|
||||
"""
|
||||
config = await SolutionSimpler.close_general_topic(msg=msg)
|
||||
await msg.answer(config[0],
|
||||
reply_markup=close_thread_keyboard(user_id=msg.from_user.id)
|
||||
if config[1] else delete_keyboard(msg.from_user.id))
|
||||
|
||||
|
||||
async def reopen_general_topic(msg: Message, bot: Bot) -> None:
|
||||
"""
|
||||
/open_general command function. Opens general thread
|
||||
:param msg: Message telegram object
|
||||
:param bot: Object of telegram bot
|
||||
:return: Nothing
|
||||
"""
|
||||
config = await SolutionSimpler.open_general_topic(msg=msg)
|
||||
await msg.answer(config[0],
|
||||
reply_markup=open_thread_keyboard(user_id=msg.from_user.id)
|
||||
if config[1] else delete_keyboard(msg.from_user.id))
|
||||
|
||||
|
||||
async def hide_general_topic(msg: Message, bot: Bot) -> None:
|
||||
"""
|
||||
/hide_general command function. Hides general thread
|
||||
:param msg: Message telegram object
|
||||
:param bot: Object of telegram bot
|
||||
:return: Nothing
|
||||
"""
|
||||
config = await SolutionSimpler.hide_general_topic(msg=msg)
|
||||
await msg.answer(config[0],
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
|
||||
async def unhide_general_topic(msg: Message, bot: Bot) -> None:
|
||||
"""
|
||||
/show_general command function. Shows back general thread.
|
||||
:param msg: Message telegram object
|
||||
:param bot: Object of telegram bot
|
||||
:return: Nothing
|
||||
"""
|
||||
config = await SolutionSimpler.show_general_topic(msg=msg)
|
||||
await msg.answer(config[0],
|
||||
reply_markup=delete_keyboard(msg.from_user.id))
|
||||
|
||||
|
||||
async def rename_topic(msg: Message, bot: Bot, command: CommandObject) -> None:
|
||||
"""
|
||||
/rename command function. Rename thread to a new name
|
||||
:param msg: Message telegram object
|
||||
:param bot: Object of telegram bot
|
||||
:param command: Object of telegram command
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.general_forum_topic_unhidden
|
||||
await bot.edit_forum_topic(name=command.text, chat_id=msg.chat.id, message_thread_id=msg.message_thread_id)
|
|
@ -1,29 +0,0 @@
|
|||
|
||||
import logging
|
||||
|
||||
from aiogram.enums import ContentType
|
||||
from aiogram.filters import Command
|
||||
from aiogram import Router, F
|
||||
|
||||
from bozenka.instances.telegram.handlers.chat_user.about import about
|
||||
from bozenka.instances.telegram.handlers.chat_user.invite import invite
|
||||
from bozenka.instances.telegram.handlers.chat_user.info import chat_info
|
||||
from bozenka.instances.telegram.handlers.chat_user.welcome import *
|
||||
|
||||
|
||||
def register_user_cmd(router: Router) -> None:
|
||||
"""
|
||||
Registers all commands related to users, and can be used by them.
|
||||
Some of them require access to some perms for bot.
|
||||
:param router:
|
||||
:return:
|
||||
"""
|
||||
logging.log(msg="Registering user commands", level=logging.INFO)
|
||||
|
||||
router.message.register(invite, Command(commands=["invite"]))
|
||||
router.message.register(about, Command(commands=["about"]))
|
||||
|
||||
router.message.register(leave, F.content_type == ContentType.LEFT_CHAT_MEMBER)
|
||||
router.message.register(join, F.content_type == ContentType.NEW_CHAT_MEMBERS)
|
||||
|
||||
router.message.register(chat_info, Command(commands=["info"]))
|
|
@ -1,19 +0,0 @@
|
|||
import logging
|
||||
|
||||
from aiogram.types import Message as Message
|
||||
from bozenka.instances.telegram.utils.keyboards import about_keyboard
|
||||
|
||||
|
||||
async def about(msg: Message):
|
||||
"""
|
||||
Sending information about bot by command `/about`
|
||||
Will be deleted by its use
|
||||
:param msg:
|
||||
:return:
|
||||
"""
|
||||
logging.log(msg=f"Sending about information for user_id={msg.from_user.id}",
|
||||
level=logging.INFO)
|
||||
await msg.answer("Кто я? 👁"
|
||||
"\nЯ - многозадачный бот, разрабатываемый Bozo Developement и всё ещё нахожусь в разработке"
|
||||
"\n(Ссылочки на нас внизу короче)☺️",
|
||||
reply_markup=about_keyboard.as_markup())
|
|
@ -1,32 +0,0 @@
|
|||
import logging
|
||||
|
||||
from aiogram.types import Message
|
||||
from bozenka.instances.telegram.utils.simpler import ru_cmds
|
||||
from bozenka.instances.telegram.utils.keyboards import delete_keyboard
|
||||
|
||||
|
||||
async def chat_info(msg: Message):
|
||||
"""
|
||||
Shows information about chat by command `/info`
|
||||
:param msg:
|
||||
:return:
|
||||
"""
|
||||
logging.log(msg=f"Sending information about chat user_id={msg.from_user.id}",
|
||||
level=logging.INFO)
|
||||
chat = await msg.bot.get_chat(msg.chat.id)
|
||||
# Related texts
|
||||
texts = {
|
||||
"chat_types": {"group": "группой", "supergroup": "cупер группой"},
|
||||
"forum_type": {True: "форумом,", False: ", не является форумом,", None: ", не является форумом,"},
|
||||
"required_invite": {True: "требуется одобрение заявки на вступление", False: "заявка не требуется.",
|
||||
None: "заявка не требуется."},
|
||||
"hidden_members": {True: "присуствуют", False: "отсуствуют", None: "отсуствуют"},
|
||||
"isprotected": {True: "пересылать сообщения из группы можно.", False: "пересылать сообщения из группы нельзя.",
|
||||
None: "пересылать сообщения из группы можно."},
|
||||
}
|
||||
|
||||
await msg.answer(f"{chat.title}\n"
|
||||
f"{chat.description}\n\n"
|
||||
f"Является {texts['chat_types'][chat.type]} {texts['forum_type'][chat.is_forum]} {texts['required_invite'][chat.join_by_request]}\n"
|
||||
f"Скрытые пользователи {texts['hidden_members'][chat.has_hidden_members]}, {texts['isprotected'][chat.has_protected_content]}",
|
||||
reply_markup=delete_keyboard(admin_id=msg.from_user.id))
|
|
@ -1,22 +0,0 @@
|
|||
import logging
|
||||
|
||||
from aiogram.types import Message
|
||||
from bozenka.instances.telegram.utils.keyboards import invite_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import ru_cmds
|
||||
|
||||
|
||||
async def invite(msg: Message):
|
||||
"""
|
||||
Generating invite to group by /invite command
|
||||
:param msg:
|
||||
:return:
|
||||
"""
|
||||
logging.log(msg=f"Generating invite for user_id={msg.from_user.id}",
|
||||
level=logging.INFO)
|
||||
link = await msg.chat.create_invite_link()
|
||||
print(link.invite_link[0])
|
||||
await msg.answer(
|
||||
ru_cmds["invite_generation"].replace("user", msg.from_user.mention_html(ru_cmds["sir"])),
|
||||
reply_markup=invite_keyboard(link=str(link.invite_link), admin_id=msg.from_user.id, chat_name=msg.chat.full_name)
|
||||
)
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
import logging
|
||||
|
||||
from aiogram import Bot
|
||||
from aiogram.types import Message as Message
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
|
||||
|
||||
|
||||
async def join(msg: Message, session_maker: async_sessionmaker):
|
||||
"""
|
||||
Send welcome message, after adding new member to chat.
|
||||
Also works on adding bot to chat and sending welcome message.
|
||||
:param msg:
|
||||
:param session_maker:
|
||||
:return:
|
||||
"""
|
||||
for new in msg.new_chat_members:
|
||||
if new.id != msg.bot.id:
|
||||
logging.log(msg=f"Saing welcome for user_id={new.id}, chat_id={msg.chat.id}",
|
||||
level=logging.INFO)
|
||||
await msg.answer(
|
||||
f"Пользователь {new.mention_html()} переехал в конфу, благодаря {msg.from_user.mention_html()}👋",
|
||||
)
|
||||
await msg.delete()
|
||||
else:
|
||||
logging.log(msg=f"Saing welcome to administrators for chat_id={msg.chat.id}",
|
||||
level=logging.INFO)
|
||||
await msg.answer("Здраствуйте администраторы чата 👋\n"
|
||||
"Я - <b>бозенька</b>, мультифункциональный бот, разрабатываемый Bozo Developement\n"
|
||||
"Выдайте мне <b>полные права администратора</b> для моей полной работы.\n"
|
||||
"Чтобы настроить функционал, используйте /setup или кнопку под сообщением", )
|
||||
await SolutionSimpler.auto_settings(msg=msg, session=session_maker)
|
||||
|
||||
|
||||
async def leave(msg: Message, bot: Bot):
|
||||
"""
|
||||
Sens goodbye message, after deleting member from chat
|
||||
:param msg:
|
||||
:param bot:
|
||||
:return:
|
||||
"""
|
||||
await msg.delete()
|
||||
if msg.from_user.id == bot.id:
|
||||
return
|
||||
logging.log(msg=f"Saing goodbye for user_id={msg.left_chat_member.id}, chat_id={msg.chat.id}",
|
||||
level=logging.INFO)
|
||||
await msg.answer(
|
||||
f"Пользователь {msg.left_chat_member.mention_html()} съехал с конфы, благодаря {msg.from_user.mention_html()}👋"
|
||||
)
|
|
@ -1,31 +0,0 @@
|
|||
import logging
|
||||
|
||||
from aiogram.filters import Command
|
||||
|
||||
from bozenka.instances.telegram.handlers.dev.hello import hi, testing
|
||||
from bozenka.instances.telegram.handlers.dev.text_generation import *
|
||||
from bozenka.instances.telegram.handlers.dev.image_generation import *
|
||||
|
||||
from bozenka.instances.telegram.utils.simpler import AnsweringGPT4Free, AnsweringGpt4All, GeneratingImages
|
||||
from aiogram import Router
|
||||
|
||||
|
||||
def register_dev_cmd(router: Router) -> None:
|
||||
"""
|
||||
Registering testing commands in development or planned in future and need much time to realise it.
|
||||
Don't need any special perms in group.
|
||||
:param router:
|
||||
:return:
|
||||
"""
|
||||
logging.log(msg="Registering developer commands", level=logging.INFO)
|
||||
router.message.register(hi, Command(commands=["hi", "welcome", "sup", "wassup", "hello", "priv",
|
||||
"privet", "хай", "прив", "привет", "ку"]))
|
||||
router.message.register(start_dialog_cmd, Command(commands=["conversation"]))
|
||||
router.message.register(g4f_generate_answer, AnsweringGPT4Free.ready_to_answer, ~Command(commands=["cancel"]))
|
||||
router.message.register(already_answering, AnsweringGpt4All.answering, ~Command(commands=["cancel"]))
|
||||
router.message.register(already_answering, AnsweringGPT4Free.answering, ~Command(commands=["cancel"]))
|
||||
router.message.register(g4a_generate_answer, AnsweringGpt4All.ready_to_answer, ~Command(commands=["cancel"]))
|
||||
router.message.register(kadinsky_generating_images, GeneratingImages.ready_to_generate, ~Command(commands=["cancel"]))
|
||||
router.message.register(start_imagine_cmd, Command(commands=["imagine"]))
|
||||
router.message.register(cancel_answering, Command(commands=["cancel"]))
|
||||
router.message.register(testing, Command(commands=["testingtest"]))
|
|
@ -1,28 +0,0 @@
|
|||
from aiogram import Bot
|
||||
from aiogram.filters import CommandObject
|
||||
from aiogram.types import Message as Message, User, Chat
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.instances.telegram.utils.keyboards import delete_keyboard
|
||||
|
||||
|
||||
async def hi(msg: Message):
|
||||
"""
|
||||
Test command, sending welcome message.
|
||||
Made for testing bot working status.
|
||||
:param msg:
|
||||
:return:
|
||||
"""
|
||||
await msg.answer(
|
||||
f"Привет, {msg.from_user.mention_html('')} 👋",
|
||||
reply_markup=delete_keyboard(msg.from_user.id)
|
||||
)
|
||||
|
||||
|
||||
async def testing(msg: Message, session_maker: async_sessionmaker, command: CommandObject, user: User, target: User, chat: Chat, bot: Bot):
|
||||
print(user.full_name)
|
||||
print(target.full_name)
|
||||
print(msg)
|
||||
print(command.args)
|
||||
print(command.mention)
|
||||
print(command.command)
|
|
@ -1,101 +0,0 @@
|
|||
import logging
|
||||
import os
|
||||
|
||||
import g4f
|
||||
import base64
|
||||
from gpt4all import GPT4All
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import Message as Message, FSInputFile
|
||||
|
||||
from bozenka.generative.kadinsky import kadinsky_gen
|
||||
from bozenka.instances.telegram.utils.keyboards import gpt_categories_keyboard, delete_keyboard, text_response_keyboard, \
|
||||
image_generation_keyboard, image_response_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import AnsweringGpt4All, \
|
||||
AnsweringGPT4Free, GeneratingImages
|
||||
from bozenka.generative.gpt4free import generate_gpt4free_providers
|
||||
|
||||
|
||||
async def already_generating(msg: Message, state: FSMContext):
|
||||
"""
|
||||
Giving response, if generating image for user right now,
|
||||
but user still asks something
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
await msg.answer(
|
||||
"Подождите пожалуйста, мы уже генерируем изображение для вас, подождите, когда мы ответим на ваш передыдущий вопрос",
|
||||
reply_markup=delete_keyboard(admin_id=msg.from_user.id))
|
||||
|
||||
|
||||
async def start_imagine_cmd(msg: Message, state: FSMContext):
|
||||
"""
|
||||
/iamgine command handler, start menu
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
if await state.get_state():
|
||||
return
|
||||
await msg.answer("Пожалуста, выберите сервис / модель для генерации изображений",
|
||||
reply_markup=image_generation_keyboard(user_id=msg.from_user.id))
|
||||
|
||||
|
||||
async def kadinsky_generating_images(msg: Message, state: FSMContext):
|
||||
"""
|
||||
Message handler for kandinsky to generate image by text from message
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
await state.set_state(GeneratingImages.generating)
|
||||
message = await msg.answer("Пожалуйста подождите, мы генерируем изображение ⏰\n"
|
||||
"Если что-то пойдет не так, мы вам сообщим 👌")
|
||||
data = await state.get_data()
|
||||
|
||||
try:
|
||||
|
||||
model_id = kadinsky_gen.get_model()
|
||||
width, height = data["set_size"].split("x")
|
||||
generating = kadinsky_gen.generate(model=model_id,
|
||||
prompt=msg.text,
|
||||
width=int(width),
|
||||
height=int(height))
|
||||
result = kadinsky_gen.check_generation(request_id=generating)
|
||||
|
||||
if result:
|
||||
path = kadinsky_gen.save_image(result[0], f"telegram_{msg.from_user.id}")
|
||||
photo = FSInputFile(path)
|
||||
await msg.answer_photo(photo=photo,
|
||||
caption=msg.text,
|
||||
reply_markup=image_response_keyboard(user_id=msg.from_user.id))
|
||||
await message.delete()
|
||||
else:
|
||||
await message.edit_text("Простите, произошла ошибка 😔\n"
|
||||
"Убедитесь, что севрера kadinsky работают и ваш промт не является неподобающим и неприемлимым\n"
|
||||
"Если это продолжается, пожалуйста используйте /cancel",
|
||||
reply_markup=image_response_keyboard(user_id=msg.from_user.id))
|
||||
|
||||
except Exception as ex:
|
||||
logging.log(msg=f"Get an exception for generating answer={ex}",
|
||||
level=logging.ERROR)
|
||||
finally:
|
||||
logging.log(msg=f"Generated image for user_id={msg.from_user.id} with promt",
|
||||
level=logging.INFO)
|
||||
await state.set_state(GeneratingImages.ready_to_generate)
|
||||
|
||||
|
||||
async def cancefl_answering(msg: Message, state: FSMContext):
|
||||
"""
|
||||
Canceling generating images for user
|
||||
Works on command /cancel
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
current = await state.get_state()
|
||||
if current is None:
|
||||
return
|
||||
await state.clear()
|
||||
await msg.answer("Удача ✅\n"
|
||||
"Диалог отменён!", reply_markup=delete_keyboard(admin_id=msg.from_user.id))
|
|
@ -1,156 +0,0 @@
|
|||
import logging
|
||||
import os.path
|
||||
|
||||
import g4f
|
||||
from gpt4all import GPT4All
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import Message as Message
|
||||
|
||||
from bozenka.generative.gpt4all import check, model_path
|
||||
from bozenka.instances.telegram.utils.keyboards import gpt_categories_keyboard, delete_keyboard, text_response_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import AnsweringGpt4All, \
|
||||
AnsweringGPT4Free
|
||||
from bozenka.generative.gpt4free import generate_gpt4free_providers
|
||||
|
||||
|
||||
async def already_answering(msg: Message, state: FSMContext):
|
||||
"""
|
||||
Giving response, if answering user now,
|
||||
but he still asks something
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
await msg.answer("Подождите пожалуйста, мы уже генерируем ответ для вас, подождите, когда мы ответим на ваш передыдущий вопрос",
|
||||
reply_markup=delete_keyboard(admin_id=msg.from_user.id))
|
||||
|
||||
|
||||
async def start_dialog_cmd(msg: Message, state: FSMContext):
|
||||
"""
|
||||
/conversation command handler, start
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
if await state.get_state():
|
||||
return
|
||||
await msg.answer("Пожалуста, выберите сервис для ИИ.",
|
||||
reply_markup=gpt_categories_keyboard
|
||||
(user_id=msg.from_user.id))
|
||||
|
||||
|
||||
async def cancel_answering(msg: Message, state: FSMContext):
|
||||
"""
|
||||
Canceling dialog with generative model
|
||||
Works on command /cancel
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
current = await state.get_state()
|
||||
if current is None:
|
||||
return
|
||||
await state.clear()
|
||||
await msg.answer("Удача ✅\n"
|
||||
"Диалог отменён!", reply_markup=delete_keyboard(admin_id=msg.from_user.id))
|
||||
|
||||
|
||||
async def g4a_generate_answer(msg: Message, state: FSMContext):
|
||||
"""
|
||||
Generating answer if Gpt4All has been selected
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
await state.set_state(AnsweringGpt4All.answering)
|
||||
|
||||
models = GPT4All.list_models()
|
||||
info = await state.get_data()
|
||||
answer = ""
|
||||
|
||||
main_msg = await msg.answer("Пожалуйста подождите, мы генерируем вам ответ ⏰\n"
|
||||
"Если что-то пойдет не так, мы вам сообщим 👌",
|
||||
reply_markup=text_response_keyboard(user_id=msg.from_user.id))
|
||||
|
||||
if not check(models[info["set_model"]]["filename"]):
|
||||
main_msg = await main_msg.edit_text(main_msg.text + "\nПодождите пожалуста, мы скачиваем модель...",
|
||||
reply_markup=main_msg.reply_markup)
|
||||
|
||||
try:
|
||||
# Setting Gpt4All model
|
||||
model = GPT4All(model_name=models[info['set_model']]['filename'],
|
||||
model_path=model_path,
|
||||
allow_download=True)
|
||||
# Setting our chat session if exist
|
||||
model.current_chat_session = [] if not info.get("ready_to_answer") else info["ready_to_answer"]
|
||||
# Generating answer
|
||||
with model.chat_session():
|
||||
answer = model.generate(msg.text)
|
||||
await state.update_data(ready_to_answer=model.current_chat_session)
|
||||
|
||||
except Exception as S:
|
||||
answer = "Простите, произошла ошибка 😔\nЕсли это продолжается, пожалуйста используйте /cancel"
|
||||
logging.log(msg=f"Get an exception for generating answer={S}",
|
||||
level=logging.ERROR)
|
||||
finally:
|
||||
await main_msg.edit_text(answer, reply_markup=text_response_keyboard(user_id=msg.from_user.id))
|
||||
|
||||
await state.set_state(AnsweringGpt4All.ready_to_answer)
|
||||
|
||||
|
||||
async def g4f_generate_answer(msg: Message, state: FSMContext):
|
||||
"""
|
||||
Generating answer if GPT4Free model and provider has been selected
|
||||
:param msg: Message telegram object
|
||||
:param state: FSM state of bot
|
||||
:return:
|
||||
"""
|
||||
await state.set_state(AnsweringGPT4Free.answering)
|
||||
|
||||
info = await state.get_data()
|
||||
|
||||
providers = generate_gpt4free_providers()
|
||||
reply = await msg.reply("Пожалуйста подождите, мы генерируем ответ от провайдера ⏰\n"
|
||||
"Если что-то пойдет не так, мы вам сообщим 👌")
|
||||
|
||||
current_messages = []
|
||||
if info.get("ready_to_answer"):
|
||||
for message in info["ready_to_answer"]:
|
||||
current_messages.append(message)
|
||||
|
||||
if not info.get("set_provider"):
|
||||
info["set_provider"] = None
|
||||
|
||||
current_messages.append({"role": "user", "content": msg.text})
|
||||
|
||||
response = ""
|
||||
try:
|
||||
response = await g4f.ChatCompletion.create_async(
|
||||
model=info["set_model"],
|
||||
messages=current_messages,
|
||||
provider=None if info["set_provider"] is None else providers[info["set_provider"]],
|
||||
stream=False
|
||||
)
|
||||
|
||||
except NameError or SyntaxError:
|
||||
try:
|
||||
response = g4f.ChatCompletion.create(
|
||||
model=info["set_model"],
|
||||
messages=current_messages,
|
||||
provider=None if info["set_provider"] is None else providers[info["set_provider"]],
|
||||
stream=False
|
||||
)
|
||||
except Exception as S:
|
||||
response = "Простите, произошла ошибка 😔\nЕсли это продолжается, пожалуйста используйте /cancel"
|
||||
logging.log(msg=f"Get an exception for generating answer={S}",
|
||||
level=logging.ERROR)
|
||||
except Exception as S:
|
||||
response = "Простите, произошла ошибка 😔\nЕсли это продолжается, пожалуйста используйте /cancel"
|
||||
logging.log(msg=f"Get an exception for generating answer={S}",
|
||||
level=logging.ERROR)
|
||||
finally:
|
||||
await reply.edit_text(text=response, reply_markup=text_response_keyboard(user_id=msg.from_user.id))
|
||||
current_messages.append({"role": "assistant", "content": response})
|
||||
await state.update_data(ready_to_answer=current_messages)
|
||||
await state.set_state(AnsweringGPT4Free.ready_to_answer)
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
|
||||
import logging
|
||||
|
||||
from aiogram import Router, F
|
||||
from aiogram.enums import ContentType
|
||||
from aiogram.filters import Command, CommandStart
|
||||
|
||||
from bozenka.instances.telegram.handlers.main.setup import *
|
||||
from bozenka.instances.telegram.handlers.main.start import *
|
||||
|
||||
|
||||
def register_main_cmd(router: Router) -> None:
|
||||
"""
|
||||
Registers all commands related to basic commands or main commands in bot.
|
||||
Don't require any special perms for bot in group.
|
||||
:param router:
|
||||
:return:
|
||||
"""
|
||||
logging.log(msg="Registering main related commands", level=logging.INFO)
|
||||
|
||||
# Start command handler
|
||||
router.message.register(start_cmd, Command(commands=["start"]), F.chat.type == ChatType.PRIVATE)
|
||||
|
||||
# Registering command /setup
|
||||
router.message.register(setup_cmd, Command(commands=["setup"]), ~(F.chat.type == ChatType.PRIVATE))
|
||||
|
||||
# After adding to chat handler
|
||||
router.message.register(group_adding_handler, F.content_type == ContentType.SUPERGROUP_CHAT_CREATED)
|
||||
router.message.register(group_adding_handler, F.content_type == ContentType.GROUP_CHAT_CREATED)
|
|
@ -1,31 +0,0 @@
|
|||
from aiogram.types import Message as Message
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
|
||||
from bozenka.instances.telegram.utils.keyboards import setup_keyboard
|
||||
|
||||
|
||||
async def setup_cmd(msg: Message):
|
||||
"""
|
||||
/setup handler
|
||||
:param msg:
|
||||
:param session:
|
||||
:return:
|
||||
"""
|
||||
await msg.answer("Привет владелец чата 👋\n"
|
||||
"Чтобы меня настроить, используй меню под данным сообщением",
|
||||
reply_markup=setup_keyboard())
|
||||
|
||||
|
||||
async def group_adding_handler(msg: Message, session_maker: async_sessionmaker):
|
||||
"""
|
||||
Send message after adding bozenka into group chat
|
||||
:param msg:
|
||||
:param session_maker:
|
||||
:return:
|
||||
"""
|
||||
await SolutionSimpler.auto_settings(msg=msg, session=session_maker)
|
||||
await msg.answer("Здраствуйте администраторы чата 👋\n"
|
||||
"Я - <b>бозенька</b>, мультифункциональный бот, разрабатываемый Bozo Developement\n"
|
||||
"Выдайте мне <b>полные права администратора</b> для моей полной работы, если не выдали."
|
||||
"Чтобы настроить функционал, используйте /setup или кнопку под сообщением")
|
|
@ -1,36 +0,0 @@
|
|||
from aiogram.enums import ChatType
|
||||
from aiogram.types import Message as Message
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from bozenka.instances.telegram.utils.keyboards import help_keyboard, start_keyboard
|
||||
|
||||
|
||||
async def start_cmd(msg: Message) -> None:
|
||||
"""
|
||||
/start command function handler
|
||||
Shows menu and basic information about bozenka
|
||||
:param msg: Message telegram object
|
||||
:return: Nothing
|
||||
"""
|
||||
await msg.answer(
|
||||
"""
|
||||
Привет 👋
|
||||
Я - бозенька, бот с открытым исходным кодом, который поможет тебе в различных задачах.
|
||||
|
||||
Вот что ты можешь сделать с помощью меню:
|
||||
• Добавить в чат: добавляет меня в групповой чат, чтобы я мог выполнять свои функции внутри него.
|
||||
• Функционал: показывает список доступных функций и команд, которые я могу выполнить.
|
||||
• О разработчиках: предоставляет информацию о команде разработчиков, которые создали и поддерживают этого бота.
|
||||
• О запущенном экземпляре: выводит информацию о текущей версии и состоянии запущенного экземпляра бота.
|
||||
• Начать диалог с ИИ: позволяет начать диалог с искусственным интеллектом, который может отвечать на вопросы и предоставлять информацию.
|
||||
• Генерация изображений: позволяет сгенерировать изображения на основе заданных параметров и промта
|
||||
|
||||
Вот нужные ссылки обо мне:
|
||||
• <a href='https://t.me/bozodevelopment'>Канал с новостями об разработке</a>
|
||||
• <a href='https://github.com/kittyneverdies/bozenka/'>Исходный код на Github</a>
|
||||
|
||||
Чтобы воспользоваться какой-либо функцией, просто нажми на соответствующую кнопку ниже.
|
||||
Если у тебя возникнут вопросы или проблемы, не стесняйся обратиться к команде разработчиков или написать в обсуждении телеграм канала.
|
||||
Удачного использования!
|
||||
""",
|
||||
reply_markup=start_keyboard(), disable_web_page_preview=True)
|
|
@ -1,128 +0,0 @@
|
|||
from aiogram import Router, F
|
||||
|
||||
from bozenka.instances.telegram.handlers.queries.image_generation import inline_image_size, inline_image_ready
|
||||
from bozenka.instances.telegram.handlers.queries.mute import *
|
||||
from bozenka.instances.telegram.handlers.queries.start import *
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import *
|
||||
from bozenka.instances.telegram.handlers.queries.ban import *
|
||||
from bozenka.instances.telegram.handlers.queries.pins import *
|
||||
from bozenka.instances.telegram.handlers.queries.threads import *
|
||||
from bozenka.instances.telegram.handlers.queries.delete import *
|
||||
from bozenka.instances.telegram.handlers.queries.revoke import *
|
||||
from bozenka.instances.telegram.handlers.queries.text_generation import *
|
||||
from bozenka.instances.telegram.handlers.queries.setup import *
|
||||
|
||||
|
||||
def register_queries(router: Router) -> None:
|
||||
"""
|
||||
Register all callback queries.
|
||||
:param router:
|
||||
:return:
|
||||
"""
|
||||
logging.log(msg="Registering callback queries", level=logging.INFO)
|
||||
|
||||
# Moderation
|
||||
# Ban / Unban buttons reactions
|
||||
router.callback_query.register(inline_ban, BanData.filter())
|
||||
router.callback_query.register(inline_unban, UnbanData.filter())
|
||||
|
||||
# Mute / Un,ute buttons reactions
|
||||
router.callback_query.register(inline_mute, MuteData.filter())
|
||||
router.callback_query.register(inline_unmute, UnmuteData.filter())
|
||||
|
||||
# Revoke telegram invite link button
|
||||
router.callback_query.register(inline_revoke, RevokeCallbackData.filter())
|
||||
# Delete button message reaction
|
||||
router.callback_query.register(inline_delete, DeleteCallbackData.filter())
|
||||
|
||||
# Threads (Close/Open)
|
||||
router.callback_query.register(inline_close_thread, CloseThread.filter())
|
||||
router.callback_query.register(inline_open_thread, OpenThread.filter())
|
||||
|
||||
# Pins (Pin/Unpin)
|
||||
router.callback_query.register(inline_pin_msg, PinMsg.filter())
|
||||
router.callback_query.register(inline_unpin_msg, UnpinMsg.filter())
|
||||
|
||||
# GPT Related queries
|
||||
|
||||
# Back to gpt categories
|
||||
router.callback_query.register(inline_start_gpt, GptBackMenu.filter(F.back_to == "category"))
|
||||
|
||||
# Gpt4Free menus (Providers/Models)
|
||||
router.callback_query.register(inline_g4f_categories, GptCategory.filter(F.category == "Gpt4Free"))
|
||||
router.callback_query.register(inline_g4f_categories, GptBackMenu.filter(F.back_to == "g4fcategory"))
|
||||
|
||||
router.callback_query.register(inline_g4f_provider_models, Gpt4FreeProvider.filter())
|
||||
|
||||
router.callback_query.register(inline_g4f_models, Gpt4FreeCategory.filter(F.category == "models"))
|
||||
router.callback_query.register(inline_g4f_providers, Gpt4FreeCategory.filter(F.category == "providers"))
|
||||
|
||||
router.callback_query.register(inline_g4f_model_select, Gpt4FreeModel.filter())
|
||||
router.callback_query.register(inline_g4f_next_models, Gpt4FreeModelPage.filter())
|
||||
|
||||
# Get back to menu state
|
||||
router.callback_query.register(inline_g4f_providers_back, GptBackMenu.filter(F.back_to == "providers"))
|
||||
|
||||
# Generates next pages (Providers/Models)
|
||||
router.callback_query.register(inline_next_g4f_models, Gpt4FreeProvsModelPage.filter(), flags={"rate_limit": {"rate": 5}})
|
||||
router.callback_query.register(inline_next_g4f_providers, Gpt4FreeProviderPage.filter(),
|
||||
flags={"rate_limit": {"rate": 5}})
|
||||
|
||||
# Help information (for page button under menu)
|
||||
router.callback_query.register(inline_return_pages, F.data == "gotpages")
|
||||
router.callback_query.register(inline_g4f_ready, Gpt4freeResult.filter())
|
||||
|
||||
# Image generation menu
|
||||
# Size setting
|
||||
router.callback_query.register(inline_image_size, ImageGenerationCategory.filter())
|
||||
|
||||
# Ready status
|
||||
router.callback_query.register(inline_image_ready, ImageGeneration.filter())
|
||||
|
||||
# Gpt4All menus
|
||||
# Gpt4All model menu
|
||||
router.callback_query.register(inline_g4a, GptCategory.filter(F.category == "Gpt4All"))
|
||||
|
||||
# Gpt4All back
|
||||
router.callback_query.register(inline_g4a_back, GptBackMenu.filter(F.back_to == "g4amodels"))
|
||||
|
||||
# Gpt4All selected model menu
|
||||
router.callback_query.register(inline_g4a_model, Gpt4AllModel.filter())
|
||||
router.callback_query.register(inline_g4a_select_model, Gpt4AllSelect.filter())
|
||||
|
||||
# Stop dialog button under gpt message answer
|
||||
router.callback_query.register(inline_stop_dialog, GptStop.filter())
|
||||
|
||||
# /setup command related queries
|
||||
# List of features based on category
|
||||
router.callback_query.register(inline_setup_category, SetupCategory.filter())
|
||||
|
||||
# Menu of feature to enable or disable
|
||||
router.callback_query.register(inline_edit_feature, SetupFeature.filter())
|
||||
router.callback_query.register(inline_feature_edited, SetupAction.filter(F.action == "enable"))
|
||||
router.callback_query.register(inline_feature_edited, SetupAction.filter(F.action == "disable"))
|
||||
|
||||
# Back from feature to category
|
||||
router.callback_query.register(inline_setup_category_back, SetupAction.filter(F.action == "back"))
|
||||
|
||||
# /start command related queries
|
||||
# Help of features based on category
|
||||
router.callback_query.register(inline_help_features, HelpCategory.filter())
|
||||
router.callback_query.register(inline_back_help_categories, HelpBack.filter(F.back_to == "category"))
|
||||
router.callback_query.register(inline_back_help_features, HelpBackCategory.filter())
|
||||
|
||||
# Menu to back
|
||||
router.callback_query.register(inline_help_feature, HelpFeature.filter())
|
||||
|
||||
# Back to /start
|
||||
router.callback_query.register(inline_start, F.data == "back")
|
||||
|
||||
# Categories of menu
|
||||
router.callback_query.register(inline_about_developers, F.data == "aboutdevs")
|
||||
router.callback_query.register(inline_add_to_chat, F.data == "addtochat")
|
||||
router.callback_query.register(inline_start_chatbot, F.data == "dialogai")
|
||||
router.callback_query.register(inline_help, F.data == "functional")
|
||||
router.callback_query.register(inline_about_instance, F.data == "aboutbot")
|
||||
|
||||
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
import logging
|
||||
|
||||
from aiogram import types
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import BanData, UnbanData
|
||||
from aiogram.enums import ChatMemberStatus
|
||||
|
||||
from bozenka.instances.telegram.utils.keyboards import ban_keyboard, unban_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
|
||||
|
||||
|
||||
async def inline_ban(call: types.CallbackQuery, callback_data: BanData, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Query, what bannes users after callback
|
||||
:param call: CallBackQuery telegram object
|
||||
:param callback_data: BanData object
|
||||
:param session_maker: AsyncSessionmaker object
|
||||
:return:
|
||||
"""
|
||||
clicked_user = await call.message.chat.get_member(call.from_user.id)
|
||||
banned_user = await call.message.chat.get_member(int(callback_data.user_id_ban))
|
||||
|
||||
if call.from_user.id != callback_data.user_id_clicked \
|
||||
and clicked_user.status not in [ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.CREATOR]:
|
||||
return
|
||||
await SolutionSimpler.inline_ban_user(call=call, data=callback_data, session=session_maker)
|
||||
|
||||
if not banned_user.is_member and banned_user.status == ChatMemberStatus.KICKED:
|
||||
await call.answer("Уже заблокирован ✅")
|
||||
else:
|
||||
await call.answer("Успешно заблокирован ✅")
|
||||
|
||||
await call.message.edit_text(
|
||||
"Удача ✅\n"
|
||||
f"{banned_user.user.mention_html('Этот пользователь')} был заблокирован {call.from_user.mention_html('этим пользователем')}.",
|
||||
reply_markup=ban_keyboard(admin_id=call.from_user.id, ban_id=banned_user.user.id)
|
||||
)
|
||||
logging.log(msg=f"Banned user @{banned_user.user.full_name} user_id=f{banned_user.user.id}", level=logging.INFO)
|
||||
|
||||
|
||||
async def inline_unban(call: types.CallbackQuery, callback_data: UnbanData, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Query, what unbannes users after callback
|
||||
:param call: CallBackQuery telegram object
|
||||
:param callback_data: UnbanData object
|
||||
:param session_maker: AsyncSessionmaker object
|
||||
:return:
|
||||
"""
|
||||
clicked_user = await call.message.chat.get_member(call.from_user.id)
|
||||
unbanned_user = await call.message.chat.get_member(int(callback_data.user_id_unban))
|
||||
if call.from_user.id != callback_data.user_id_clicked \
|
||||
and clicked_user.status not in [ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.CREATOR]:
|
||||
return
|
||||
|
||||
await SolutionSimpler.inline_unban_user(call=call, data=callback_data, session=session_maker)
|
||||
|
||||
if unbanned_user.is_member and unbanned_user.status != ChatMemberStatus.KICKED:
|
||||
await call.answer("Уже разблокирован ✅")
|
||||
else:
|
||||
await call.answer("Успешно разблокирован ✅")
|
||||
await call.message.edit_text(
|
||||
"Удача ✅\n"
|
||||
f"{unbanned_user.user.mention_html('Этот пользователь')} был разблокирован {call.from_user.mention_html('этим пользователем')}.",
|
||||
reply_markup=unban_keyboard(admin_id=call.from_user.id, ban_id=unbanned_user.user.id)
|
||||
)
|
||||
logging.log(msg=f"Unbanned user @{unbanned_user.user.full_name} user_id=f{unbanned_user.user.id}", level=logging.INFO)
|
|
@ -1,21 +0,0 @@
|
|||
import logging
|
||||
|
||||
from aiogram import types
|
||||
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import DeleteCallbackData
|
||||
from aiogram.enums import ChatMemberStatus
|
||||
|
||||
|
||||
async def inline_delete(call: types.CallbackQuery, callback_data: DeleteCallbackData) -> None:
|
||||
"""
|
||||
Deletes messsage, after special callback
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
user_clicked = await call.message.chat.get_member(call.from_user.id)
|
||||
if call.from_user.id == callback_data.user_id_clicked or user_clicked.status == ChatMemberStatus.ADMINISTRATOR:
|
||||
await call.answer("Хорошо ✅")
|
||||
logging.log(msg=f"Deleted message with message_id={call.message.message_id}",
|
||||
level=logging.INFO)
|
||||
await call.message.delete()
|
|
@ -1,60 +0,0 @@
|
|||
import logging
|
||||
|
||||
from aiogram import types
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from gpt4all import GPT4All
|
||||
|
||||
from bozenka.instances.telegram.utils.simpler.fsm_states import *
|
||||
|
||||
# Callbacks for GPT
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import (
|
||||
ImageGeneration,
|
||||
ImageGenerationCategory
|
||||
)
|
||||
# Keyboards for messages
|
||||
from bozenka.instances.telegram.utils.keyboards import (
|
||||
gpt4free_models_by_provider_keyboard,
|
||||
gpt4free_providers_keyboard,
|
||||
delete_keyboard, gpt_categories_keyboard, generate_gpt4all_page, gpt4all_model_menu, image_resolution_keyboard
|
||||
)
|
||||
# Simpler utlilities
|
||||
from bozenka.instances.telegram.utils.simpler import (
|
||||
AnsweringGPT4Free,
|
||||
AnsweringGpt4All,
|
||||
)
|
||||
|
||||
|
||||
async def inline_image_size(call: types.CallbackQuery, callback_data: ImageGenerationCategory, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what shows menu for image size to generate in
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:param state:
|
||||
:return:
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
await state.update_data(set_category=callback_data.category)
|
||||
await state.set_state(GeneratingImages.set_size)
|
||||
await call.message.edit_text("Пожалуста, выберите размер изображения 🖼",
|
||||
reply_markup=image_resolution_keyboard(user_id=call.from_user.id,
|
||||
category=callback_data.category))
|
||||
|
||||
|
||||
async def inline_image_ready(call: types.CallbackQuery, callback_data: ImageGeneration, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what shows menu for image size to generate in
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:param state:
|
||||
:return:
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
await state.update_data(set_size=callback_data.size)
|
||||
await state.set_state(GeneratingImages.ready_to_generate)
|
||||
await call.message.edit_text(f"Вы выбрали {callback_data.category} для генерации изображений в размере {callback_data.size}.\n"
|
||||
"Напишите /cancel для отмены",
|
||||
reply_markup=delete_keyboard(admin_id=call.from_user.id))
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
import logging
|
||||
|
||||
from aiogram import types
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import UnmuteData, MuteData
|
||||
from aiogram.enums import ChatMemberStatus
|
||||
|
||||
from bozenka.instances.telegram.utils.keyboards import ban_keyboard, unban_keyboard, mute_keyboard, unmute_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
|
||||
|
||||
|
||||
async def inline_mute(call: types.CallbackQuery, callback_data: MuteData, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Query, what mutes users after callback
|
||||
:param call: CallBackQuery telegram object
|
||||
:param callback_data: BanData object
|
||||
:param session_maker: AsyncSessionmaker object
|
||||
:return:
|
||||
"""
|
||||
clicked_user = await call.message.chat.get_member(call.from_user.id)
|
||||
muted_user = await call.message.chat.get_member(int(callback_data.user_id_mute))
|
||||
|
||||
if call.from_user.id != callback_data.user_id_clicked \
|
||||
and clicked_user.status not in [ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.CREATOR]:
|
||||
return
|
||||
await SolutionSimpler.inline_mute_user(call=call, data=callback_data, session=session_maker)
|
||||
|
||||
if not muted_user.can_send_messages and muted_user.status == ChatMemberStatus.RESTRICTED:
|
||||
await call.answer("Уже замучен ✅")
|
||||
else:
|
||||
await call.answer("Успешно замучен ✅")
|
||||
|
||||
await call.message.edit_text(
|
||||
"Удача ✅\n"
|
||||
f"{muted_user.user.mention_html('Этот пользователь')} был замучен {call.from_user.mention_html('этим пользователем')}.",
|
||||
reply_markup=mute_keyboard(admin_id=call.from_user.id, mute_id=callback_data.user_id_mute)
|
||||
)
|
||||
logging.log(msg=f"Banned user @{muted_user.user.full_name} user_id=f{muted_user.user.id}", level=logging.INFO)
|
||||
|
||||
|
||||
async def inline_unmute(call: types.CallbackQuery, callback_data: UnmuteData, session_maker: async_sessionmaker) -> None:
|
||||
"""
|
||||
Query, what unbannes users after callback
|
||||
:param call: CallBackQuery telegram object
|
||||
:param callback_data: UnbanData object
|
||||
:param session_maker: AsyncSessionmaker object
|
||||
:return:
|
||||
"""
|
||||
clicked_user = await call.message.chat.get_member(call.from_user.id)
|
||||
unmuted_user = await call.message.chat.get_member(int(callback_data.user_id_unmute))
|
||||
if call.from_user.id != callback_data.user_id_clicked \
|
||||
and clicked_user.status not in [ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.CREATOR]:
|
||||
return
|
||||
|
||||
await SolutionSimpler.inline_unmute_user(call=call, data=callback_data, session=session_maker)
|
||||
|
||||
if unmuted_user.can_send_messages or unmuted_user.status == ChatMemberStatus.RESTRICTED:
|
||||
await call.answer("Уже размучен ✅")
|
||||
else:
|
||||
await call.answer("Успешно размучен ✅")
|
||||
await call.message.edit_text(
|
||||
"Удача ✅\n"
|
||||
f"{unmuted_user.user.mention_html('Этот пользователь')} был размучен {call.from_user.mention_html('этим пользователем')}.",
|
||||
reply_markup=unmute_keyboard(admin_id=call.from_user.id, unmute_id=unmuted_user.user.id)
|
||||
)
|
||||
logging.log(msg=f"Unbanned user @{unmuted_user.user.full_name} user_id=f{unmuted_user.user.id}", level=logging.INFO)
|
|
@ -1,36 +0,0 @@
|
|||
from aiogram import types
|
||||
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import PinMsg, UnpinMsg
|
||||
from bozenka.instances.telegram.utils.keyboards import unpin_msg_keyboard, pin_msg_keyboard
|
||||
|
||||
|
||||
async def inline_pin_msg(call: types.CallbackQuery, callback_data: PinMsg) -> None:
|
||||
"""
|
||||
Query, what pins message
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
if callback_data.user_id == call.from_user.id:
|
||||
return
|
||||
|
||||
await call.message.chat.pin_message(message_id=callback_data.msg_id)
|
||||
await call.message.edit_text("Удача ✅\n"
|
||||
"Сообщение было закреплено 📌",
|
||||
reply_markup=pin_msg_keyboard(user_id=call.from_user.id, msg_id=callback_data.msg_id))
|
||||
|
||||
|
||||
async def inline_unpin_msg(call: types.CallbackQuery, callback_data: UnpinMsg) -> None:
|
||||
"""
|
||||
Query, what unpins message
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
if callback_data.user_id == call.from_user.id:
|
||||
return
|
||||
|
||||
await call.message.chat.pin_message(message_id=callback_data.msg_id)
|
||||
await call.message.edit_text("Удача ✅\n"
|
||||
"Сообщение было откреплено 📌",
|
||||
reply_markup=unpin_msg_keyboard(user_id=call.from_user.id, msg_id=callback_data.msg_id))
|
|
@ -1,24 +0,0 @@
|
|||
import logging
|
||||
|
||||
from aiogram import types
|
||||
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import RevokeCallbackData
|
||||
from aiogram.enums import ChatMemberStatus
|
||||
|
||||
from bozenka.instances.telegram.utils.simpler import ru_cmds
|
||||
|
||||
|
||||
async def inline_revoke(call: types.CallbackQuery, callback_data: RevokeCallbackData):
|
||||
"""
|
||||
Revokes invite link
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
user_clicked = await call.message.chat.get_member(call.from_user.id)
|
||||
if callback_data.admin_id == call.from_user.id or user_clicked.status == ChatMemberStatus.ADMINISTRATOR or user_clicked.status == ChatMemberStatus.CREATOR:
|
||||
logging.log(msg=f"Revoking link for user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
await call.message.chat.revoke_invite_link(invite_link="https://" + str(callback_data.link))
|
||||
await call.answer("Удача ✅")
|
||||
await call.message.delete()
|
|
@ -1,73 +0,0 @@
|
|||
from aiogram.types import CallbackQuery, Message
|
||||
from sqlalchemy import select, Update
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.database.tables.telegram import ChatSettings, get_chat_config_value
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import SetupCategory, SetupFeature, SetupAction
|
||||
from bozenka.instances.telegram.utils.keyboards import setup_category_keyboard, setup_feature_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import list_of_features
|
||||
|
||||
|
||||
async def inline_setup_category(call: CallbackQuery, callback_data: SetupCategory):
|
||||
"""
|
||||
Query, what shows list of features to enable.
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
await call.message.edit_text("Выберите настройку, которую хотите изменить",
|
||||
reply_markup=setup_category_keyboard(category=callback_data.category_name))
|
||||
|
||||
|
||||
async def inline_setup_category_back(call: CallbackQuery, callback_data: SetupAction):
|
||||
"""
|
||||
Query, what shows list of features to enable.
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
await call.message.edit_text("Выберите настройку, которую хотите изменить",
|
||||
reply_markup=setup_category_keyboard(category=callback_data.feature_category))
|
||||
|
||||
|
||||
async def inline_edit_feature(call: CallbackQuery, callback_data: SetupFeature, session_maker: async_sessionmaker):
|
||||
"""
|
||||
Query, what shows menu to enable / disable feature
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:param session_maker:
|
||||
:return:
|
||||
"""
|
||||
is_enabled = await get_chat_config_value(
|
||||
chat_id=call.message.chat.id,
|
||||
session=session_maker,
|
||||
setting=list_of_features[callback_data.feature_category][callback_data.feature_index]
|
||||
)
|
||||
|
||||
await call.message.edit_text(
|
||||
list_of_features[callback_data.feature_category][callback_data.feature_index].description,
|
||||
reply_markup=await setup_feature_keyboard(category=callback_data.feature_category,
|
||||
index=callback_data.feature_index,
|
||||
is_enabled=is_enabled))
|
||||
|
||||
|
||||
async def inline_feature_edited(call: CallbackQuery, callback_data: SetupAction, session_maker: async_sessionmaker):
|
||||
"""
|
||||
Query, what shows menu to enable / disable feature
|
||||
after editing
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:param session_maker:
|
||||
:return:
|
||||
"""
|
||||
async with session_maker() as session:
|
||||
async with session.begin():
|
||||
await session.execute(Update(ChatSettings)
|
||||
.values({list_of_features[callback_data.feature_category][callback_data.feature_index].settings_name:
|
||||
callback_data.action == "enable"})
|
||||
.where(ChatSettings.chat_id == call.message.chat.id))
|
||||
await call.message.edit_text(
|
||||
list_of_features[callback_data.feature_category][callback_data.feature_index].description,
|
||||
reply_markup=await setup_feature_keyboard(category=callback_data.feature_category,
|
||||
index=callback_data.feature_index,
|
||||
is_enabled=callback_data.action == "enable"))
|
|
@ -1,168 +0,0 @@
|
|||
import git
|
||||
|
||||
from aiogram.types import *
|
||||
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import *
|
||||
from bozenka.instances.telegram.utils.keyboards import *
|
||||
from bozenka.instances.telegram.utils.simpler import list_of_features
|
||||
from bozenka.instances.version import is_updated, build
|
||||
|
||||
|
||||
async def inline_start(call: CallbackQuery):
|
||||
"""
|
||||
Query, what shows back menu of /start
|
||||
:param call:
|
||||
:return:
|
||||
"""
|
||||
await call.message.edit_text(
|
||||
"""
|
||||
Привет 👋
|
||||
Я - бозенька, бот с открытым исходным кодом, который поможет тебе в различных задачах.
|
||||
|
||||
Вот что ты можешь сделать с помощью меню:
|
||||
• Добавить в чат: добавляет меня в групповой чат, чтобы я мог выполнять свои функции внутри него.
|
||||
• Функционал: показывает список доступных функций и команд, которые я могу выполнить.
|
||||
• О разработчиках: предоставляет информацию о команде разработчиков, которые создали и поддерживают этого бота.
|
||||
• О запущенном экземпляре: выводит информацию о текущей версии и состоянии запущенного экземпляра бота.
|
||||
• Начать диалог с ИИ: позволяет начать диалог с искусственным интеллектом, который может отвечать на вопросы и предоставлять информацию.
|
||||
• Генерация изображений: позволяет сгенерировать изображения на основе заданных параметров и промта
|
||||
|
||||
Вот нужные ссылки обо мне:
|
||||
• <a href='https://t.me/bozodevelopment'>Канал с новостями об разработке</a>
|
||||
• <a href='https://github.com/kittyneverdies/bozenka/'>Исходный код на Github</a>
|
||||
|
||||
Чтобы воспользоваться какой-либо функцией, просто нажми на соответствующую кнопку ниже.
|
||||
Если у тебя возникнут вопросы или проблемы, не стесняйся обратиться к команде разработчиков или написать в обсуждении телеграм канала.
|
||||
Удачного использования!
|
||||
""",
|
||||
reply_markup=start_keyboard(),
|
||||
disable_web_page_preview=True
|
||||
)
|
||||
|
||||
|
||||
async def inline_start_chatbot(call: CallbackQuery):
|
||||
"""
|
||||
Query, what shows list of Categories, avaible to use as chatbot
|
||||
:param call:
|
||||
:return:
|
||||
"""
|
||||
await call.message.edit_text("Пожалуста, выберите сервиc / библиотеку, через которую вы будете общаться",
|
||||
reply_markup=gpt_categories_keyboard
|
||||
(user_id=call.from_user.id))
|
||||
|
||||
|
||||
async def inline_help(call: CallbackQuery):
|
||||
"""
|
||||
Query, what shows information about bozenka and it's development
|
||||
:param call:
|
||||
:return:
|
||||
"""
|
||||
await call.message.edit_text("Выберите категорию, по которой нужна помощь:",
|
||||
reply_markup=help_keyboard())
|
||||
|
||||
|
||||
async def inline_about_developers(call: CallbackQuery):
|
||||
"""
|
||||
Query, what shows information about bozenka and it's development
|
||||
:param call:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Вернуться 🔙", callback_data="back")
|
||||
]])
|
||||
await call.message.edit_text("""
|
||||
Бозенька - это мультифункциональный (в будущем кроссплатформенный) бот.\n
|
||||
Он умеет работать с групповыми чатами и готовыми нейронными сетями для генерации текста и изображений.
|
||||
Бозенька разрабатывается коммандой, которая состоит на данный момент из одного человека.\n
|
||||
Исходный код проекта\n
|
||||
Исходный код находится под лицензией GPL-3.0, исходный код проекта можно посмотреть всегда <a href="https://github.com/kittyneverdies/bozenka/">здесь</a>
|
||||
Канал с новостями разработки находится <a href="https://t.me/bozodevelopment">здесь</a>
|
||||
""", reply_markup=kb, disable_web_page_preview=True)
|
||||
|
||||
|
||||
async def inline_about_instance(call: CallbackQuery):
|
||||
"""
|
||||
Query, what shows information about runned instance
|
||||
:param call:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Вернуться 🔙", callback_data="back")
|
||||
]])
|
||||
me = await call.message.bot.get_me()
|
||||
update_status = {False: "требуется обновление бота 🔼",
|
||||
True: "обновление не требуется, последняя версия ✅"}
|
||||
await call.message.edit_text(
|
||||
f"Информация об данном запущенном экземпляре бозеньки:\n"
|
||||
f"Аккаунт бота: {me.mention_html()}\n"
|
||||
f"Запущенная версия бота <code>{build}</code>\n",
|
||||
f"Нужно ли обновление: {update_status[is_updated]}",
|
||||
reply_markup=kb)
|
||||
|
||||
|
||||
async def inline_add_to_chat(call: CallbackQuery):
|
||||
"""
|
||||
Query, what shows a link to add bozenka into user chat
|
||||
:param call:
|
||||
:return:
|
||||
"""
|
||||
# Getting bot
|
||||
me = await call.message.bot.me()
|
||||
|
||||
# Generating special keyboard
|
||||
kb = InlineKeyboardBuilder()
|
||||
kb.button(text="Добавить в ваш груповой чат 🔌",
|
||||
url="https://t.me/"
|
||||
f"{me.username}?"
|
||||
"startgroup&"
|
||||
"admin=promote_members+delete_messages+restrict_members+invite_users+pin_messages+manage_video_chats")
|
||||
kb.row(InlineKeyboardButton(text="Вернуться 🔙", callback_data="back"))
|
||||
|
||||
# Answering
|
||||
await call.message.edit_text("Чтобы добавить бозеньку в ваш групповой чат, нажмите на кнопку под сообщением:",
|
||||
reply_markup=kb.as_markup())
|
||||
|
||||
|
||||
async def inline_help_features(call: CallbackQuery, callback_data: HelpCategory):
|
||||
"""
|
||||
Query, what shows list of features to get support.
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
await call.message.edit_text("Выберите функцию, по которой нужна помощь",
|
||||
reply_markup=help_category_keyboard(category=callback_data.category_name))
|
||||
|
||||
|
||||
async def inline_back_help_features(call: CallbackQuery, callback_data: HelpBackCategory):
|
||||
"""
|
||||
Query, what shows list of features to get support.
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
await call.message.edit_text("Выберите функцию, по которой нужна помощь",
|
||||
reply_markup=help_category_keyboard(category=callback_data.back_to_category))
|
||||
|
||||
|
||||
async def inline_back_help_categories(call: CallbackQuery, callback_data: HelpBack):
|
||||
"""
|
||||
Query, what shows list of features to get support back.
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
await call.message.edit_text("Выберите категорию, по которой нужна помощь:",
|
||||
reply_markup=help_keyboard())
|
||||
|
||||
|
||||
async def inline_help_feature(call: CallbackQuery, callback_data: HelpFeature):
|
||||
"""
|
||||
Query, what shows list of features to get support.
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
await call.message.edit_text(
|
||||
list_of_features[callback_data.feature_category][callback_data.feature_index].description,
|
||||
reply_markup=help_feature_keyboard(category=callback_data.feature_category))
|
|
@ -1,358 +0,0 @@
|
|||
import logging
|
||||
|
||||
from aiogram import types
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from gpt4all import GPT4All
|
||||
|
||||
from bozenka.instances.telegram.utils.simpler.fsm_states import *
|
||||
|
||||
# Callbacks for GPT
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import (
|
||||
GptCategory,
|
||||
Gpt4FreeProvider,
|
||||
Gpt4freeResult,
|
||||
Gpt4FreeProviderPage,
|
||||
Gpt4FreeProvsModelPage, GptStop, GptBackMenu, Gpt4AllModel, Gpt4AllSelect, Gpt4FreeCategory, Gpt4FreeModelPage,
|
||||
Gpt4FreeModel
|
||||
)
|
||||
# Keyboards for messages
|
||||
from bozenka.instances.telegram.utils.keyboards import (
|
||||
gpt4free_models_by_provider_keyboard,
|
||||
gpt4free_providers_keyboard,
|
||||
delete_keyboard, gpt_categories_keyboard, generate_gpt4all_page, gpt4all_model_menu, gpt4free_categories_keyboard,
|
||||
gpt4free_models_keyboard
|
||||
)
|
||||
# Simpler utlilities
|
||||
from bozenka.instances.telegram.utils.simpler import (
|
||||
AnsweringGPT4Free,
|
||||
AnsweringGpt4All,
|
||||
)
|
||||
|
||||
|
||||
async def inline_start_gpt(call: types.CallbackQuery, callback_data: GptBackMenu, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what shows when clicking on button in /start menu
|
||||
:param call:
|
||||
:param state:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
await call.message.edit_text("Пожалуста, выберите сервис для ИИ.",
|
||||
reply_markup=gpt_categories_keyboard(user_id=call.from_user.id))
|
||||
|
||||
|
||||
async def inline_g4f_providers(call: types.CallbackQuery, callback_data: Gpt4FreeCategory, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what creating providers selecting menu.
|
||||
:param state:
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
logging.log(msg=f"Selected gpt4free category by user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
|
||||
await call.answer("Вы выбрали провайдеры 🤖")
|
||||
|
||||
await state.set_state(AnsweringGPT4Free.set_provider)
|
||||
await call.message.edit_text("Выберите пожалуйста одного из провайдеров 👨💻",
|
||||
reply_markup=gpt4free_providers_keyboard(user_id=call.from_user.id, page=0))
|
||||
|
||||
|
||||
async def inline_g4f_models(call: types.CallbackQuery, callback_data: GptCategory, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what creating models selecting menu
|
||||
:param state:
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
await state.set_state(AnsweringGPT4Free.set_model)
|
||||
|
||||
await call.answer("Вы выбрали модели 🤖")
|
||||
|
||||
await call.message.edit_text("Выберите модель, с которой будете общаться 🤖",
|
||||
reply_markup=gpt4free_models_keyboard(user_id=call.from_user.id, page=0))
|
||||
|
||||
|
||||
async def inline_g4f_model_select(call: types.CallbackQuery, callback_data: Gpt4FreeModel, state: FSMContext):
|
||||
"""
|
||||
Query, what ending model selecting
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:param state:
|
||||
:return:
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
await state.update_data(set_model=callback_data.model)
|
||||
await state.set_state(AnsweringGPT4Free.ready_to_answer)
|
||||
|
||||
await call.answer("Вы можете начать общаться 🤖")
|
||||
|
||||
await call.message.edit_text("Удача ✅\n"
|
||||
"Вы теперь можете спокойно вести диалог 🤖\n"
|
||||
f"Вы выбрали модель <b>{callback_data.model}</b>👾\n"
|
||||
"Чтобы прекратить общение, используйте /cancel ", reply_markup=delete_keyboard(admin_id=call.from_user.id))
|
||||
|
||||
|
||||
async def inline_g4f_next_models(call: types.CallbackQuery, callback_data: Gpt4FreeModelPage, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what creating models selecting menu
|
||||
:param state:
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
await call.answer(f"Вы перелистнули на страницу {callback_data.page + 1}📄")
|
||||
|
||||
await call.message.edit_text("Выберите модель, с которой будете общаться 🤖",
|
||||
reply_markup=gpt4free_models_keyboard(user_id=call.from_user.id, page=callback_data.page))
|
||||
|
||||
|
||||
async def inline_g4f_categories(call: types.CallbackQuery, callback_data: GptCategory, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what creating providers selecting menu.
|
||||
:param state:
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
logging.log(msg=f"Selected gpt4free category by user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
|
||||
await state.update_data(set_category=callback_data.category)
|
||||
await call.answer("Вы выбрали Gpt4Free 🤖")
|
||||
await call.message.edit_text("Выберите, по какому пункту мы будем вести диалог с нейронной сети 🤖",
|
||||
reply_markup=gpt4free_categories_keyboard(user_id=call.from_user.id))
|
||||
await call.answer("Выберите, по какому пункту мы будем вести диалог с нейронной сети 🤖")
|
||||
|
||||
|
||||
async def inline_g4f_providers_back(call: types.CallbackQuery, callback_data: GptBackMenu, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what creating providers selecting menu.
|
||||
:param state:
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
logging.log(msg=f"Back to providers menu by user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
await state.set_state(AnsweringGPT4Free.set_provider)
|
||||
|
||||
await call.message.edit_text("Выберите пожалуйста одного из провайдеров 👨💻",
|
||||
reply_markup=gpt4free_providers_keyboard(page=0, user_id=callback_data.user_id))
|
||||
await call.answer("Выберите пожалуйста одного из провайдеров 👨💻")
|
||||
|
||||
|
||||
async def inline_g4f_provider_models(call: types.CallbackQuery, callback_data: Gpt4FreeProvider, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what creating models selecting menu.
|
||||
:param state:
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
logging.log(msg=f"Selected gpt4free provider {callback_data.provider} by user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
|
||||
await state.update_data(set_provider=callback_data.provider)
|
||||
await state.set_state(AnsweringGPT4Free.set_model)
|
||||
|
||||
await call.message.edit_text("Выберите пожалуйста модель ИИ 👾", reply_markup=gpt4free_models_by_provider_keyboard(
|
||||
user_id=callback_data.user_id,
|
||||
provider=callback_data.provider,
|
||||
page=0
|
||||
))
|
||||
await call.answer("Выберите пожалуйста модель ИИ 👾")
|
||||
|
||||
|
||||
async def inline_g4f_ready(call: types.CallbackQuery, callback_data: Gpt4freeResult, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what says about getting ready to questions for ChatGPT from Gpt4Free.
|
||||
:param state:
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
|
||||
logging.log(msg=f"Selected gpt4free model {callback_data.model} by user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
|
||||
await state.update_data(set_model=callback_data.model)
|
||||
await state.set_state(AnsweringGPT4Free.ready_to_answer)
|
||||
|
||||
logging.log(msg=f"Loaded GPT answering status for user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
|
||||
await call.message.edit_text("Удача ✅\n"
|
||||
"Вы теперь можете спокойно вести диалог 🤖\n"
|
||||
f"Вы выбрали модель <b>{callback_data.model}</b>👾, от провайдера <b>{callback_data.provider}</b>👨💻\n"
|
||||
"Чтобы прекратить общение, используйте /cancel ",
|
||||
reply_markup=delete_keyboard(admin_id=callback_data.user_id))
|
||||
await call.answer("Вы теперь можете спокойно вести диалог 🤖")
|
||||
|
||||
|
||||
async def inline_g4a(call: types.CallbackQuery, callback_data: GptCategory, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what shows list for gpt4all models
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:param state:
|
||||
:return:
|
||||
"""
|
||||
if callback_data.user_id != call.from_user.id:
|
||||
return
|
||||
await state.set_state(AnsweringGpt4All.set_model)
|
||||
await call.message.edit_text("Выберите пожалуйста модель ИИ 👾",
|
||||
reply_markup=generate_gpt4all_page(user_id=call.from_user.id))
|
||||
|
||||
|
||||
async def inline_g4a_back(call: types.CallbackQuery, callback_data: GptCategory, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what shows list for gpt4all models back
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:param state:
|
||||
:return:
|
||||
"""
|
||||
if callback_data.user_id != call.from_user.id:
|
||||
return
|
||||
await state.set_state(AnsweringGpt4All.set_model)
|
||||
await call.message.edit_text("Выберите пожалуйста модель ИИ 👾",
|
||||
reply_markup=generate_gpt4all_page(user_id=call.from_user.id))
|
||||
|
||||
|
||||
async def inline_g4a_model(call: types.CallbackQuery, callback_data: Gpt4AllModel, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what show information about clicked gpt4all model from list
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:param state:
|
||||
:return:
|
||||
"""
|
||||
if callback_data.user_id != call.from_user.id:
|
||||
return
|
||||
models = GPT4All.list_models()
|
||||
name = models[callback_data.index]['name']
|
||||
await call.message.edit_text(f"{name}\n"
|
||||
f"Обученно на основе {models[callback_data.index]['parameters']} строк 👨💻",
|
||||
reply_markup=gpt4all_model_menu(user_id=call.from_user.id, index=callback_data.index))
|
||||
|
||||
|
||||
async def inline_g4a_select_model(call: types.CallbackQuery, callback_data: Gpt4AllSelect, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what says about getting ready for question for Gpt4All model
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:param state:
|
||||
:return:
|
||||
"""
|
||||
if callback_data.user_id != call.from_user.id:
|
||||
return
|
||||
await state.update_data(set_model=callback_data.index)
|
||||
await state.set_state(AnsweringGpt4All.ready_to_answer)
|
||||
models = GPT4All.list_models()
|
||||
|
||||
await call.message.edit_text("Удача ✅\n"
|
||||
"Вы теперь можете спокойно вести диалог 🤖\n"
|
||||
f"Вы выбрали модель <b>{models[callback_data.index]['name']}</b>👾 от Gpt4All\n"
|
||||
"Чтобы прекратить общение, используйте /cancel ",
|
||||
reply_markup=delete_keyboard(admin_id=callback_data.user_id))
|
||||
|
||||
|
||||
async def inline_next_g4f_providers(call: types.CallbackQuery, callback_data: Gpt4FreeProviderPage,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what generates a next page of providers for user
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:param state:
|
||||
:return:
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
logging.log(msg=f"Changed page to {str(callback_data.page + 1)} user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
await call.message.edit_text(call.message.text,
|
||||
reply_markup=gpt4free_providers_keyboard(user_id=callback_data.user_id,
|
||||
page=callback_data.page))
|
||||
await call.answer(f"Вы перелистнули на страницу {callback_data.page + 1}📄")
|
||||
|
||||
|
||||
async def inline_next_g4f_models(call: types.CallbackQuery, callback_data: Gpt4FreeProvsModelPage,
|
||||
state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what generates a next page of models for user.
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:param state:
|
||||
:return:
|
||||
"""
|
||||
if call.from_user.id != callback_data.user_id:
|
||||
return
|
||||
logging.log(msg=f"Changed page to {str(callback_data.page + 1)} user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
await call.message.edit_text(call.message.text,
|
||||
reply_markup=gpt4free_models_by_provider_keyboard(
|
||||
user_id=callback_data.user_id,
|
||||
provider=callback_data.provider,
|
||||
page=callback_data.page
|
||||
))
|
||||
await call.answer(f"Вы перелистали на страницу {callback_data.page + 1}📄")
|
||||
|
||||
|
||||
async def inline_return_pages(call: types.CallbackQuery) -> None:
|
||||
"""
|
||||
Query, made for helping purposes.
|
||||
Shows current page.
|
||||
:param call:
|
||||
:return:
|
||||
"""
|
||||
logging.log(msg=f"Showed helping info for user_id={call.from_user.id}",
|
||||
level=logging.INFO)
|
||||
await call.answer("Здесь расположается текущая странница 📃")
|
||||
|
||||
|
||||
async def inline_stop_dialog(call: types.CallbackQuery, callback_data: GptStop, state: FSMContext) -> None:
|
||||
"""
|
||||
Query, what stops dialog
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:param state:
|
||||
"""
|
||||
# Checking user_id of user
|
||||
if callback_data.user_id != call.from_user.id:
|
||||
return
|
||||
# Clearing state
|
||||
await state.clear()
|
||||
# Answering something
|
||||
await call.answer("Хорошо ✅")
|
||||
if await state.get_state() == AnsweringGPT4Free.ready_to_answer or await state.get_state() == AnsweringGpt4All.answering:
|
||||
await call.message.edit_text(text=call.message.text + "\n\nДиалог остановлен ✅\n",
|
||||
reply_markup=delete_keyboard(admin_id=call.from_user.id))
|
||||
else:
|
||||
await call.message.delete()
|
|
@ -1,41 +0,0 @@
|
|||
from aiogram import types
|
||||
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import CloseThread, OpenThread
|
||||
from bozenka.instances.telegram.utils.keyboards import open_thread_keyboard, close_thread_keyboard, delete_keyboard
|
||||
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
|
||||
|
||||
|
||||
async def inline_close_thread(call: types.CallbackQuery, callback_data: CloseThread) -> None:
|
||||
"""
|
||||
Query, what close thread
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
|
||||
if callback_data.user_id != call.from_user.id or not call.message.chat.is_forum:
|
||||
return
|
||||
config = await SolutionSimpler.close_topic(msg=call.message, call=call)
|
||||
await call.message.edit_text(
|
||||
config[0],
|
||||
reply_markup=close_thread_keyboard(user_id=call.from_user.id) if config[1] else
|
||||
delete_keyboard(admin_id=call.from_user.id)
|
||||
)
|
||||
|
||||
|
||||
async def inline_open_thread(call: types.CallbackQuery, callback_data: OpenThread) -> None:
|
||||
"""
|
||||
Query, what opens thread
|
||||
:param call:
|
||||
:param callback_data:
|
||||
:return:
|
||||
"""
|
||||
|
||||
if callback_data.user_id != call.from_user.id or not call.message.chat.is_forum:
|
||||
return
|
||||
config = await SolutionSimpler.open_topic(msg=call.message, call=call)
|
||||
await call.message.edit_text(
|
||||
config[0],
|
||||
reply_markup=open_thread_keyboard(user_id=call.from_user.id) if config[1] else
|
||||
delete_keyboard(admin_id=call.from_user.id)
|
||||
)
|
|
@ -1,10 +1,6 @@
|
|||
import logging
|
||||
|
||||
from aiogram import Router, Dispatcher
|
||||
|
||||
from bozenka.instances.telegram.utils.middleware.antiflood import MessageThrottlingMiddleware, \
|
||||
CallbackThrottlingMiddleware
|
||||
from bozenka.instances.telegram.utils.middleware.retry import RetryMessageMiddleware, RetryCallbackMiddleware
|
||||
from aiogram import Dispatcher
|
||||
|
||||
|
||||
def register_middlewares(dp: Dispatcher) -> None:
|
||||
|
@ -16,8 +12,13 @@ def register_middlewares(dp: Dispatcher) -> None:
|
|||
logging.log(msg=f"Registering middlewares of bot", level=logging.INFO)
|
||||
|
||||
# Throttling middlewares
|
||||
dp.message.middleware.register(MessageThrottlingMiddleware)
|
||||
|
||||
"""
|
||||
dp.message.middleware(CounterMiddleware)
|
||||
dp.callback_query.middleware(CallbackThrottlingMiddleware)
|
||||
# Retry middlewares
|
||||
"""
|
||||
"""
|
||||
dp.error.middleware(RetryMessageMiddleware)
|
||||
dp.error.middleware(RetryCallbackMiddleware)
|
||||
"""
|
|
@ -5,6 +5,22 @@ from aiogram.types import Update, Message, CallbackQuery
|
|||
from cachetools import TTLCache
|
||||
|
||||
|
||||
class CounterMiddleware(BaseMiddleware):
|
||||
def __init__(self) -> None:
|
||||
self.counter = 0
|
||||
|
||||
async def __call__(
|
||||
self,
|
||||
handler: Callable[[Message, Dict[str, Any]], Awaitable[Any]],
|
||||
event: Message,
|
||||
data: Dict[str, Any],
|
||||
**kwargs: Any
|
||||
) -> Any:
|
||||
self.counter += 1
|
||||
print(self.counter)
|
||||
return await handler(event, data)
|
||||
|
||||
|
||||
class MessageThrottlingMiddleware(BaseMiddleware):
|
||||
"""
|
||||
This middleware is skidded from public codes
|
8
bozenka/instances/telegram/middleware/retry.py
Normal file
8
bozenka/instances/telegram/middleware/retry.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
import time
|
||||
from typing import Callable, Dict, Awaitable, Any
|
||||
|
||||
from aiogram import BaseMiddleware
|
||||
from aiogram.exceptions import TelegramRetryAfter
|
||||
from aiogram.types import Message, ErrorEvent, Update, CallbackQuery
|
||||
|
||||
|
1
bozenka/instances/telegram/queries/__init__.py
Normal file
1
bozenka/instances/telegram/queries/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
from .menu import *
|
39
bozenka/instances/telegram/queries/menu.py
Normal file
39
bozenka/instances/telegram/queries/menu.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
import logging
|
||||
|
||||
from aiogram import types
|
||||
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import DeleteMenu
|
||||
from aiogram.enums import ChatMemberStatus
|
||||
|
||||
from bozenka.instances.telegram.utils.callbacks_factory.menu_controler import HideMenu
|
||||
|
||||
|
||||
async def delete_callback_handler(call: types.CallbackQuery, callback_data: DeleteMenu) -> None:
|
||||
"""
|
||||
Deletes messsage, after special callback
|
||||
:param call: CallbackQuery telegram object
|
||||
:param callback_data: DeleteMenu object
|
||||
:return: None
|
||||
"""
|
||||
user_clicked = await call.message.chat.get_member(call.from_user.id)
|
||||
if call.from_user.id == callback_data.user_id_clicked or user_clicked.status == ChatMemberStatus.ADMINISTRATOR:
|
||||
await call.answer("Хорошо ✅")
|
||||
logging.log(msg=f"Deleted message with message_id={call.message.message_id}",
|
||||
level=logging.INFO)
|
||||
await call.message.delete()
|
||||
|
||||
|
||||
async def hide_menu_handler(call: types.CallbackQuery, callback_data: HideMenu):
|
||||
"""
|
||||
Hide InlineKeyboard, after special callback
|
||||
:param call: CallbackQuery telegram object
|
||||
:param callback_data: HideMenu object
|
||||
:return: None
|
||||
"""
|
||||
user_clicked = await call.message.chat.get_member(call.from_user.id)
|
||||
if call.from_user.id == callback_data.user_id_clicked or user_clicked.status == ChatMemberStatus.ADMINISTRATOR:
|
||||
await call.answer("Хорошо ✅")
|
||||
logging.log(msg=f"Hide inline keyboard message with message_id={call.message.message_id}",
|
||||
level=logging.INFO)
|
||||
await call.message.edit_text(call.message.text, reply_markup=None)
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
from .admin import *
|
||||
from .delete import DeleteCallbackData
|
||||
from .administration import *
|
||||
from .menu_controler import DeleteMenu
|
||||
from .text_generation import *
|
||||
from .setup import *
|
||||
from .start import *
|
||||
from .basic_functional import *
|
||||
from .img_generation import *
|
||||
|
|
|
@ -5,6 +5,7 @@ from aiogram.filters.callback_data import CallbackData
|
|||
class BanData(CallbackData, prefix="ban"):
|
||||
"""
|
||||
Callback with information to ban user
|
||||
and handle clicking on button ban
|
||||
"""
|
||||
user_id_ban: int
|
||||
user_id_clicked: int
|
||||
|
@ -13,6 +14,7 @@ class BanData(CallbackData, prefix="ban"):
|
|||
class UnbanData(CallbackData, prefix="unban"):
|
||||
"""
|
||||
Callback with information to unban user
|
||||
and handle clicking on button unban
|
||||
"""
|
||||
user_id_unban: int
|
||||
user_id_clicked: int
|
||||
|
@ -22,6 +24,7 @@ class UnbanData(CallbackData, prefix="unban"):
|
|||
class MuteData(CallbackData, prefix="mute"):
|
||||
"""
|
||||
Callback with information to mute user
|
||||
and handle clicking on button unmute
|
||||
"""
|
||||
user_id_mute: int
|
||||
user_id_clicked: int
|
|
@ -28,7 +28,7 @@ class SetupAction(CallbackData, prefix="sa"):
|
|||
Callback with information to do with a feature
|
||||
"""
|
||||
action: str
|
||||
feature_category: str
|
||||
category_name: str
|
||||
feature_index: int
|
||||
|
||||
|
||||
|
@ -39,3 +39,33 @@ class SetupEditFeature(CallbackData, prefix="sef"):
|
|||
enable: bool
|
||||
feature_index: int
|
||||
feature_category: str
|
||||
|
||||
|
||||
class HelpCategory(CallbackData, prefix="hc"):
|
||||
"""
|
||||
Callback data of help categories
|
||||
"""
|
||||
category_name: str
|
||||
|
||||
|
||||
class HelpFeature(CallbackData, prefix="hf"):
|
||||
"""
|
||||
Callback data of features category
|
||||
"""
|
||||
feature_index: int
|
||||
feature_category: str
|
||||
|
||||
|
||||
class HelpBack(CallbackData, prefix="hb"):
|
||||
"""
|
||||
Callback data to back to categories in help menu
|
||||
"""
|
||||
back_to: str
|
||||
|
||||
|
||||
class HelpBackCategory(CallbackData, prefix="hbc"):
|
||||
"""
|
||||
Callback data to back to list of features in one
|
||||
of categories in menu
|
||||
"""
|
||||
category_name: str
|
|
@ -1,8 +0,0 @@
|
|||
from aiogram.filters.callback_data import CallbackData
|
||||
|
||||
|
||||
class DeleteCallbackData(CallbackData, prefix="delete"):
|
||||
"""
|
||||
Callback with information to delete message
|
||||
"""
|
||||
user_id_clicked: int
|
|
@ -0,0 +1,15 @@
|
|||
from aiogram.filters.callback_data import CallbackData
|
||||
|
||||
|
||||
class DeleteMenu(CallbackData, prefix="delete"):
|
||||
"""
|
||||
Callback with information to delete message
|
||||
"""
|
||||
user_id_clicked: int
|
||||
|
||||
|
||||
class HideMenu(CallbackData, prefix="hide"):
|
||||
"""
|
||||
Callback with information to hide message
|
||||
"""
|
||||
user_id_clicked: int
|
|
@ -1,38 +0,0 @@
|
|||
from aiogram.filters.callback_data import CallbackData
|
||||
|
||||
|
||||
class HelpCategory(CallbackData, prefix="hc"):
|
||||
"""
|
||||
Callback data of help categories
|
||||
"""
|
||||
category_name: str
|
||||
|
||||
|
||||
class HelpFeature(CallbackData, prefix="hf"):
|
||||
"""
|
||||
Callback data of features category
|
||||
"""
|
||||
feature_index: int
|
||||
feature_category: str
|
||||
|
||||
|
||||
class HelpBack(CallbackData, prefix="hb"):
|
||||
"""
|
||||
Callback data to back to categories in help menu
|
||||
"""
|
||||
back_to: str
|
||||
|
||||
|
||||
class HelpBackCategory(CallbackData, prefix="hbc"):
|
||||
"""
|
||||
Callback data to back to list of features in one
|
||||
of categories in menu
|
||||
"""
|
||||
back_to_category: str
|
||||
|
||||
|
||||
class BackStart(CallbackData, prefix="start"):
|
||||
"""
|
||||
Callback data to back to /start
|
||||
"""
|
||||
pass
|
16
bozenka/instances/telegram/utils/delete.py
Normal file
16
bozenka/instances/telegram/utils/delete.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import *
|
||||
|
||||
|
||||
def delete_keyboard(admin_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Basic keyboard for all messages from bot.
|
||||
By pressing this button, message from bot will get deleted.
|
||||
:param admin_id: User_id of user to work with this
|
||||
:return: None
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Спасибо, удали сообщение ✅", callback_data=DeleteMenu(user_id_clicked=str(admin_id)).pack())
|
||||
]])
|
||||
return kb
|
|
@ -1,104 +0,0 @@
|
|||
from typing import Any
|
||||
|
||||
from aiogram.filters import Filter
|
||||
from aiogram.types import Message, ChatPermissions
|
||||
from aiogram.enums import ChatMemberStatus
|
||||
from bozenka.instances.telegram.utils.simpler import ru_cmds
|
||||
|
||||
|
||||
class UserHasPermissions(Filter):
|
||||
"""
|
||||
Check, does user have permissions, what user need to work with bot.
|
||||
"""
|
||||
# List of permissions avaible to users.
|
||||
# Basic permissions for administration and user
|
||||
permissions = [
|
||||
"can_manage_chat",
|
||||
"can_delete_messages",
|
||||
"can_manage_video_chats",
|
||||
"can_restrict_members",
|
||||
"can_promote_members",
|
||||
"can_change_info",
|
||||
"can_invite_users",
|
||||
"can_post_messages",
|
||||
"can_edit_messages",
|
||||
"can_pin_messages",
|
||||
"can_manage_topics",
|
||||
"can_send_messages",
|
||||
"can_send_audios",
|
||||
"can_send_documents",
|
||||
"can_send_photos",
|
||||
"can_send_videos",
|
||||
"can_send_video_notes",
|
||||
"can_send_voice_notes",
|
||||
"can_send_polls",
|
||||
"can_send_other_messages",
|
||||
"can_add_web_page_previews",
|
||||
]
|
||||
|
||||
def __init__(self, perms: list[Any]) -> None:
|
||||
self.perms = perms
|
||||
|
||||
async def check_permissions(self, permission, msg: Message) -> bool:
|
||||
"""
|
||||
Checking permissions, included to user.
|
||||
:return:
|
||||
"""
|
||||
if permission.count(False) > 0 or permission.count(None) > 0:
|
||||
await msg.answer("Ошибка ❌\n"
|
||||
"У вас нет прав на использование этой комманды 🚫")
|
||||
return False
|
||||
return True
|
||||
|
||||
def generate_perms_list(self, user) -> list[Any]:
|
||||
"""
|
||||
Generates list of permissions, included to user
|
||||
:param user:
|
||||
:return:
|
||||
"""
|
||||
permission = []
|
||||
for rule in self.perms:
|
||||
if rule in permission:
|
||||
exec(f"permission.append(user.{rule})")
|
||||
return permission
|
||||
|
||||
async def __call__(self, msg: Message) -> bool:
|
||||
user = await msg.chat.get_member(msg.from_user.id)
|
||||
permission = self.generate_perms_list(user)
|
||||
return True if user.status == ChatMemberStatus.CREATOR else self.check_permissions(permission, msg)
|
||||
|
||||
|
||||
class BotHasPermissions(UserHasPermissions):
|
||||
"""
|
||||
Check, does bot have permissions, what user need to work with bot.
|
||||
"""
|
||||
async def __call__(self, msg: Message, *args, **kwargs):
|
||||
bot = await msg.chat.get_member(msg.chat.bot.id)
|
||||
permission = self.generate_perms_list(bot)
|
||||
return self.check_permissions(permission, msg)
|
||||
|
||||
|
||||
class IsOwner(Filter):
|
||||
"""
|
||||
Checks, is User are owner of chat
|
||||
"""
|
||||
def __init__(self, is_admin: bool) -> None:
|
||||
self.is_admin = is_admin
|
||||
|
||||
async def __call__(self, msg: Message) -> bool:
|
||||
user = await msg.chat.get_member(msg.from_user.id)
|
||||
if ChatMemberStatus.CREATOR != user.status:
|
||||
await msg.answer(ru_cmds["no-perms"])
|
||||
return ChatMemberStatus.CREATOR == user.status
|
||||
|
||||
|
||||
class IsAdminFilter(Filter):
|
||||
def __init__(self, is_admin: bool) -> None:
|
||||
self.is_admin = is_admin
|
||||
|
||||
async def __call__(self, msg: Message) -> bool:
|
||||
user = await msg.chat.get_member(msg.from_user.id)
|
||||
if ChatMemberStatus.CREATOR == user.status:
|
||||
return True
|
||||
return ChatMemberStatus.ADMINISTRATOR == user.status
|
||||
|
|
@ -1 +0,0 @@
|
|||
from .inline import *
|
|
@ -1,613 +0,0 @@
|
|||
import g4f
|
||||
import gpt4all
|
||||
|
||||
from typing import Any
|
||||
|
||||
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from gpt4all import GPT4All
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.database.tables.telegram import get_chat_config_value
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import *
|
||||
from bozenka.instances.telegram.utils.simpler.lists_of_content import generate_list_of_features
|
||||
from bozenka.generative.gpt4free import generate_gpt4free_models, generate_gpt4free_providers
|
||||
from bozenka.generative import text_generative_categories, image_generative_categories, image_generative_size
|
||||
|
||||
"""
|
||||
File, contains inline keyboard & menus and their work.
|
||||
Right now only on Russian language, multi-language planning soon.
|
||||
"""
|
||||
|
||||
|
||||
def start_keyboard() -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate keyboard for /start command
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(
|
||||
inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Добавить в ваш групповой чат 🔌", callback_data="addtochat")],
|
||||
[InlineKeyboardButton(text="Информация об функционале бота 🔨", callback_data="functional")],
|
||||
[InlineKeyboardButton(text="Об данном проекте ℹ️", callback_data="aboutdevs")],
|
||||
[InlineKeyboardButton(text="О данном запущенном экзепляре ℹ️", callback_data="aboutbot")],
|
||||
[InlineKeyboardButton(text="Начать диалог с текстовым ИИ 🤖", callback_data="dialogai")],
|
||||
[InlineKeyboardButton(text="Начать генерацию изображений 🖼", callback_data="dialogimage")],
|
||||
]
|
||||
)
|
||||
return kb
|
||||
|
||||
|
||||
# Help related keyboards
|
||||
def help_keyboard() -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate keyboard for /help command
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Администраторы 👮♂",
|
||||
callback_data=HelpCategory(category_name="Admins").pack())],
|
||||
[InlineKeyboardButton(text="Пользователи 👤",
|
||||
callback_data=HelpCategory(category_name="Members").pack())],
|
||||
[InlineKeyboardButton(text="В разработке 👨💻",
|
||||
callback_data=HelpCategory(category_name="Devs").pack())],
|
||||
[InlineKeyboardButton(text="Вернуться 🔙", callback_data="back")]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
def help_category_keyboard(category: str) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate keyboard for one of categories
|
||||
:param category:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardBuilder()
|
||||
list_of_features = generate_list_of_features(category)
|
||||
for setting in list_of_features:
|
||||
kb.row(InlineKeyboardButton(text=setting.name,
|
||||
callback_data=HelpFeature(
|
||||
feature_index=list_of_features.index(setting),
|
||||
feature_category=category
|
||||
).pack()))
|
||||
kb.row(InlineKeyboardButton(text="🔙 Назад к категориям",
|
||||
callback_data=HelpBack(back_to="category").pack()))
|
||||
return kb.as_markup()
|
||||
|
||||
|
||||
def help_feature_keyboard(category: str) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Just button for function of /help
|
||||
:param category:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="🔙 Назад к функциям",
|
||||
callback_data=HelpBackCategory(back_to_category=category).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
# Setup related keyboards
|
||||
def setup_keyboard() -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate keyboard for /setup command
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardBuilder()
|
||||
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Администраторы 👮♂",
|
||||
callback_data=SetupCategory(category_name="Admins").pack())],
|
||||
[InlineKeyboardButton(text="Пользователи 👤",
|
||||
callback_data=SetupCategory(category_name="Members").pack())],
|
||||
[InlineKeyboardButton(text="В разработке 👨💻",
|
||||
callback_data=SetupCategory(category_name="Devs").pack())]])
|
||||
return kb
|
||||
|
||||
|
||||
def setup_category_keyboard(category: str) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate keyboard for one of categories
|
||||
:param category:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardBuilder()
|
||||
list_of_features = generate_list_of_features(category)
|
||||
for setting in list_of_features:
|
||||
kb.row(InlineKeyboardButton(text=setting.name,
|
||||
callback_data=SetupFeature(
|
||||
feature_index=list_of_features.index(setting),
|
||||
feature_category=category
|
||||
).pack()))
|
||||
return kb.as_markup()
|
||||
|
||||
|
||||
async def setup_feature_keyboard(category: str, index: int, is_enabled: bool) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate keyboard for enabling or disabling
|
||||
on of features
|
||||
:param is_enabled:
|
||||
:param category:
|
||||
:param index:
|
||||
|
||||
:return:
|
||||
"""
|
||||
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Выключить ❌", callback_data=SetupAction(action="disable",
|
||||
feature_category=category,
|
||||
feature_index=index).pack())
|
||||
if is_enabled else
|
||||
InlineKeyboardButton(text="Включить ✅", callback_data=SetupAction(action="enable",
|
||||
feature_category=category,
|
||||
feature_index=index).pack())
|
||||
], [
|
||||
InlineKeyboardButton(text="Вернуться 🔙", callback_data=SetupAction(action="back",
|
||||
feature_category=category,
|
||||
feature_index=index).pack())]])
|
||||
return kb
|
||||
|
||||
|
||||
def delete_keyboard(admin_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Basic keyboard for all messages from bot.
|
||||
By pressing this button, message from bot will get deleted.
|
||||
:param admin_id:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteCallbackData(user_id_clicked=str(admin_id)).pack())
|
||||
]])
|
||||
return kb
|
||||
|
||||
|
||||
def image_resolution_keyboard(user_id: int, category: str) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Create keyboard with list of resolution to generate image
|
||||
:param user_id:
|
||||
:param category:
|
||||
:return:
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
for size in image_generative_size:
|
||||
builder.row(InlineKeyboardButton(text=size,
|
||||
callback_data=ImageGeneration(
|
||||
user_id=user_id,
|
||||
category=category,
|
||||
size=size
|
||||
).pack()))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def image_generation_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Create keyboard with list of image generation librarioes avaible in the bot
|
||||
:param user_id:
|
||||
:return:
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
for category in image_generative_categories:
|
||||
builder.row(InlineKeyboardButton(text=category,
|
||||
callback_data=ImageGenerationCategory(user_id=user_id,
|
||||
category=category).pack()))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
# LLM / GPT related keyboards
|
||||
# GPT CATEGORIES
|
||||
def gpt_categories_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Create list keyboard list of gpt libraries, available in the bot
|
||||
:param user_id:
|
||||
:return: InlineKeyboardMarkup
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
for category in text_generative_categories:
|
||||
builder.row(InlineKeyboardButton(text=category,
|
||||
callback_data=GptCategory(user_id=str(user_id), category=category).pack()))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
# Helper
|
||||
def items_list_generator(page: int, list_of_items, count_of_items: int) -> list[Any]:
|
||||
"""
|
||||
Generate page, made for backend
|
||||
:param page:
|
||||
:param list_of_items:
|
||||
:param count_of_items:
|
||||
"""
|
||||
items = []
|
||||
required_items = [item + page * count_of_items for item in range(count_of_items)]
|
||||
for item, count in zip(list_of_items, range(0, len(list_of_items))):
|
||||
if count not in required_items:
|
||||
continue
|
||||
items.append(item)
|
||||
return items
|
||||
|
||||
|
||||
def gpt4free_providers_keyboard(user_id: int, page: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate page of gpt providers, can be used by user.
|
||||
:param user_id:
|
||||
:param page:
|
||||
:return:
|
||||
"""
|
||||
providers = generate_gpt4free_providers()
|
||||
names = items_list_generator(page, providers, 4)
|
||||
pages = [len(providers) // 4 - 1 if page - 1 == -1 else page - 1,
|
||||
0 if page + 1 >= len(providers) // 4 else page + 1]
|
||||
generated_page = InlineKeyboardMarkup(inline_keyboard=[
|
||||
# First one provider
|
||||
[InlineKeyboardButton(text=names[0],
|
||||
callback_data=Gpt4FreeProvider(user_id=user_id, provider=names[0], page="0").pack())],
|
||||
# Second one provider
|
||||
[InlineKeyboardButton(text=names[1],
|
||||
callback_data=Gpt4FreeProvider(user_id=user_id, provider=names[1], page="0").pack())],
|
||||
# Third one provider
|
||||
[InlineKeyboardButton(text=names[2],
|
||||
callback_data=Gpt4FreeProvider(user_id=user_id, provider=names[2], page="0").pack())],
|
||||
# Fourh one provider (if exist)
|
||||
[InlineKeyboardButton(text=names[3],
|
||||
callback_data=Gpt4FreeProvider(user_id=user_id, provider=names[3],
|
||||
page="0").pack())] if len(
|
||||
names) == 4 else [],
|
||||
# Page right
|
||||
[InlineKeyboardButton(text=str(len(providers) // 4 if page == 0 else "1"),
|
||||
callback_data=Gpt4FreeProviderPage(
|
||||
page=str(len(providers) // 4 - 1 if page == 0 else "0"),
|
||||
user_id=user_id).pack()),
|
||||
|
||||
InlineKeyboardButton(text="⬅️", callback_data=Gpt4FreeProviderPage(page=pages[0], user_id=user_id).pack()),
|
||||
InlineKeyboardButton(text=str(page + 1), callback_data="gotpages"),
|
||||
# Page left
|
||||
InlineKeyboardButton(text="➡️", callback_data=Gpt4FreeProviderPage(page=pages[1], user_id=user_id).pack()),
|
||||
InlineKeyboardButton(text=str(len(providers) // 4 if page != len(providers) // 4 - 1 else "1"),
|
||||
callback_data=Gpt4FreeProviderPage(
|
||||
page=str(len(providers) // 4 - 1 if page != len(providers) // 4 - 1 else "0"),
|
||||
user_id=user_id).pack())
|
||||
],
|
||||
# Under list buttons
|
||||
[InlineKeyboardButton(text="🔙 Вернуться к категориям",
|
||||
callback_data=GptBackMenu(user_id=user_id, back_to="g4fcategory").pack())],
|
||||
[InlineKeyboardButton(text="Спасибо, не надо ❌",
|
||||
callback_data=GptStop(user_id=str(user_id)).pack())]])
|
||||
return generated_page
|
||||
|
||||
|
||||
def gpt4free_categories_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Menu of categories in Gpt4Free (Providers / Models)
|
||||
:param user_id:
|
||||
:return:
|
||||
"""
|
||||
print("!231234")
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="По моделям 🤖",
|
||||
callback_data=Gpt4FreeCategory(category="models", user_id=user_id).pack())
|
||||
], [
|
||||
InlineKeyboardButton(text="По провайдерам 🤖",
|
||||
callback_data=Gpt4FreeCategory(category="providers", user_id=user_id).pack())
|
||||
]])
|
||||
return kb
|
||||
|
||||
|
||||
def gpt4free_models_keyboard(user_id: int, page: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating list of GPT4FREE models, can be used to generate text.
|
||||
:param user_id:
|
||||
:param page:
|
||||
:return:
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
full_list = g4f.ModelUtils.convert.keys()
|
||||
models = items_list_generator(page=page, list_of_items=full_list, count_of_items=4)
|
||||
pages = [len(full_list) // 4 - 1 if page - 1 == -1 else page - 1,
|
||||
0 if page + 1 >= len(full_list) // 4 else page + 1]
|
||||
|
||||
for model in models:
|
||||
builder.row(InlineKeyboardButton(text=model,
|
||||
callback_data=Gpt4FreeModel(user_id=user_id, model=model).pack()))
|
||||
builder.row(
|
||||
# First page button
|
||||
InlineKeyboardButton(text=str(len(full_list) // 4 if page == 0 else "1"),
|
||||
callback_data=Gpt4FreeModelPage(
|
||||
page=str(len(full_list) // 4 - 1 if page == 0 else "1"),
|
||||
user_id=user_id).pack(),
|
||||
),
|
||||
# Page back button
|
||||
InlineKeyboardButton(text="⬅️",
|
||||
callback_data=Gpt4FreeModelPage(user_id=str(user_id), page=pages[0], ).pack()),
|
||||
# Count of page button
|
||||
InlineKeyboardButton(text=str(page + 1), callback_data="gotpages"),
|
||||
# Next page button
|
||||
InlineKeyboardButton(text="➡️",
|
||||
callback_data=Gpt4FreeModelPage(user_id=str(user_id), page=pages[1]).pack()),
|
||||
# Last page button
|
||||
InlineKeyboardButton(text=str(len(full_list) // 4 if page != 0 else "1"),
|
||||
callback_data=Gpt4FreeModelPage(
|
||||
page=str(len(full_list) // 4 - 1) if page != 0 else "1",
|
||||
user_id=user_id).pack(), ))
|
||||
builder.row(InlineKeyboardButton(text="🔙 Вернуться",
|
||||
callback_data=GptBackMenu(user_id=user_id, back_to="g4fcategory").pack()))
|
||||
builder.row(InlineKeyboardButton(text="Спасибо, не надо ❌",
|
||||
callback_data=GptStop(user_id=str(user_id)).pack()))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def gpt4free_models_by_provider_keyboard(user_id: int, provider: str, page: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating list of GPT4Free provider's models, can be used to generate text.
|
||||
Will be also reworked.
|
||||
:param user_id:
|
||||
:param provider:
|
||||
:param page:
|
||||
:return:
|
||||
"""
|
||||
builder = InlineKeyboardBuilder()
|
||||
models = generate_gpt4free_models()
|
||||
providers = generate_gpt4free_providers()
|
||||
if provider in models:
|
||||
if providers[provider].supports_gpt_4:
|
||||
models[provider].append("")
|
||||
names = items_list_generator(page, models[provider], 4)
|
||||
for name in names:
|
||||
builder.row(InlineKeyboardButton(text=name.replace('-', ' '),
|
||||
callback_data=Gpt4freeResult(user_id=str(user_id), provider=provider,
|
||||
model=name).pack()))
|
||||
pages = [len(models[provider]) // 4 - 1 if page - 1 == -1 else page - 1,
|
||||
0 if page + 1 >= len(models[provider]) // 4 else page + 1]
|
||||
if len(models[provider]) > 4:
|
||||
builder.row(
|
||||
# First page button
|
||||
InlineKeyboardButton(text=str(len(models[provider]) // 4 if page == 0 else "1"),
|
||||
callback_data=Gpt4FreeProvsModelPage(
|
||||
page=str(len(models[provider]) // 4 - 1 if page == 0 else "1"),
|
||||
user_id=user_id,
|
||||
provider=provider).pack(),
|
||||
),
|
||||
# Page back button
|
||||
InlineKeyboardButton(text="⬅️",
|
||||
callback_data=Gpt4FreeProvsModelPage(user_id=str(user_id), page=pages[0],
|
||||
provider=provider).pack()),
|
||||
# Count of page button
|
||||
InlineKeyboardButton(text=str(page + 1), callback_data="gotpages"),
|
||||
# Next page button
|
||||
InlineKeyboardButton(text="➡️",
|
||||
callback_data=Gpt4FreeProvsModelPage(user_id=str(user_id), page=pages[1],
|
||||
provider=provider).pack()),
|
||||
# Last page button
|
||||
InlineKeyboardButton(text=str(len(models[provider]) // 4 if page != 0 else "1"),
|
||||
callback_data=Gpt4FreeProvsModelPage(
|
||||
page=str(len(models[provider]) // 4 - 1) if page != 0 else "1",
|
||||
user_id=user_id,
|
||||
provider=provider).pack(), ))
|
||||
else:
|
||||
if providers[provider].supports_gpt_4:
|
||||
builder.row(InlineKeyboardButton(text="gpt 4",
|
||||
callback_data=Gpt4freeResult(user_id=str(user_id),
|
||||
provider=provider,
|
||||
model="gpt-4").pack()))
|
||||
if providers[provider].supports_gpt_35_turbo:
|
||||
builder.row(InlineKeyboardButton(text="gpt 3.5 turbo",
|
||||
callback_data=Gpt4freeResult
|
||||
(user_id=str(user_id), provider=provider, model="gpt-3.5-turbo").pack()))
|
||||
builder.row(InlineKeyboardButton(text="🔙 Вернуться к провайдерам",
|
||||
callback_data=GptBackMenu(user_id=user_id, back_to="providers").pack()))
|
||||
builder.row(InlineKeyboardButton(text="Спасибо, не надо ❌", callback_data=GptStop(user_id=str(user_id)).pack()))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
# Gpt4All related keyboards
|
||||
def generate_gpt4all_page(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating list of GPT4All models.
|
||||
:param user_id:
|
||||
:return:
|
||||
"""
|
||||
models = GPT4All.list_models()
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
for model in models:
|
||||
builder.row(InlineKeyboardButton(
|
||||
text=model["name"],
|
||||
callback_data=Gpt4AllModel(user_id=str(user_id), index=str(models.index(model))).pack())
|
||||
)
|
||||
builder.row(InlineKeyboardButton(text="🔙 Вернуться к списку",
|
||||
callback_data=GptBackMenu(user_id=user_id, back_to="category").pack()))
|
||||
builder.row(InlineKeyboardButton(text="Спасибо, не надо ❌",
|
||||
callback_data=GptStop(user_id=str(user_id)).pack()))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def gpt4all_model_menu(user_id: int, index: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for selection on of GPT4ALL models
|
||||
:param user_id:
|
||||
:param index:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Выбрать ✅",
|
||||
callback_data=Gpt4AllSelect(user_id=user_id, index=str(index)).pack())],
|
||||
[InlineKeyboardButton(text="🔙 Вернуться к списку",
|
||||
callback_data=GptBackMenu(user_id=user_id, back_to="g4amodels").pack())],
|
||||
[InlineKeyboardButton(text="Спасибо, не надо ❌",
|
||||
callback_data=GptStop(user_id=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
# Universal response from GPT / LLM keyboard
|
||||
def text_response_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for response from GPT
|
||||
:param user_id:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteCallbackData(user_id_clicked=str(user_id)).pack())],
|
||||
[InlineKeyboardButton(text="Завершить диалог 🚫", callback_data=GptStop(user_id=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
def image_response_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for image
|
||||
:param user_id:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteCallbackData(user_id_clicked=str(user_id)).pack())],
|
||||
[InlineKeyboardButton(text="Хватит 🚫", callback_data=GptStop(user_id=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
# Admin related keyboards
|
||||
# Ban / Unban keyboards
|
||||
def ban_keyboard(admin_id: int, ban_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for /ban command.
|
||||
:param admin_id:
|
||||
:param ban_id:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteCallbackData(user_id_clicked=str(admin_id)).pack())
|
||||
], [
|
||||
InlineKeyboardButton(text="Разбанить 🛠️", callback_data=UnbanData(user_id_unban=str(ban_id),
|
||||
user_id_clicked=str(admin_id)).pack())
|
||||
]])
|
||||
return kb
|
||||
|
||||
|
||||
def unban_keyboard(admin_id: int, ban_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for /unban command.
|
||||
:param admin_id:
|
||||
:param ban_id:
|
||||
:return:
|
||||
"""
|
||||
print(ban_id)
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteCallbackData(user_id_clicked=str(admin_id)).pack())
|
||||
], [
|
||||
InlineKeyboardButton(text="Забанить 🛠️", callback_data=BanData(user_id_ban=str(ban_id),
|
||||
user_id_clicked=str(admin_id)).pack())
|
||||
]])
|
||||
return kb
|
||||
|
||||
|
||||
# Mute / Unmute keyboards
|
||||
def mute_keyboard(admin_id: int, mute_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for /mute command.
|
||||
:param admin_id:
|
||||
:param mute_id:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Спасибо ✅",
|
||||
callback_data=DeleteCallbackData(user_id_clicked=str(admin_id)).pack())],
|
||||
[InlineKeyboardButton(text="Размутить 🛠️",
|
||||
callback_data=UnmuteData(user_id_unmute=mute_id, user_id_clicked=admin_id).pack())]])
|
||||
return kb
|
||||
|
||||
|
||||
def unmute_keyboard(admin_id: int, unmute_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for /unmute command.
|
||||
:param admin_id:
|
||||
:param unmute_id:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Спасибо ✅",
|
||||
callback_data=DeleteCallbackData(user_id_clicked=str(admin_id)).pack())],
|
||||
[InlineKeyboardButton(text="Замутить 🛠️",
|
||||
callback_data=MuteData(user_id_mute=unmute_id, user_id_clicked=admin_id).pack())]])
|
||||
return kb
|
||||
|
||||
|
||||
# Invite keyboard
|
||||
def invite_keyboard(link: str, admin_id: int, chat_name: str) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generating menu for /invite command. Should be reworked.
|
||||
:param link:
|
||||
:param admin_id:
|
||||
:param chat_name:
|
||||
:return:
|
||||
"""
|
||||
link = link.replace("https://", "")
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[[
|
||||
InlineKeyboardButton(text=chat_name, url=link)],
|
||||
[InlineKeyboardButton(text="Отозвать 🛠️",
|
||||
callback_data=RevokeCallbackData(admin_id=admin_id, link=link).pack())],
|
||||
[InlineKeyboardButton(text="Спасибо ✅",
|
||||
callback_data=DeleteCallbackData(user_id_clicked=str(admin_id)).pack())]])
|
||||
return kb
|
||||
|
||||
|
||||
# Close / Open thread commands related keyboards
|
||||
def close_thread_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate menu for /close command
|
||||
:param user_id:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Окрыть обсуждение 🛠️", callback_data=OpenThread(user_id=user_id).pack())],
|
||||
[InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteCallbackData(user_id_clicked=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
def open_thread_keyboard(user_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate menu for /open command
|
||||
:param user_id:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Закрыть обсуждение 🛠️", callback_data=CloseThread(user_id=user_id).pack())],
|
||||
[InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteCallbackData(user_id_clicked=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
# Pin / Unpin command
|
||||
def pin_msg_keyboard(user_id: int, msg_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate menu for /pin command
|
||||
:param user_id:
|
||||
:param msg_id:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Открепить сообщение 📌",
|
||||
callback_data=UnpinMsg(user_id=user_id, msg_id=msg_id).pack())],
|
||||
[InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteCallbackData(user_id_clicked=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
def unpin_msg_keyboard(user_id: int, msg_id: int) -> InlineKeyboardMarkup:
|
||||
"""
|
||||
Generate menu for /unpin command
|
||||
:param user_id:
|
||||
:param msg_id:
|
||||
:return:
|
||||
"""
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Открепить сообщение 📌",
|
||||
callback_data=PinMsg(user_id=user_id, msg_id=msg_id).pack())],
|
||||
[InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteCallbackData(user_id_clicked=str(user_id)).pack())]
|
||||
])
|
||||
return kb
|
||||
|
||||
|
||||
about_keyboard = InlineKeyboardBuilder()
|
||||
about_keyboard.button(
|
||||
text="Bozo Development", url="https://t.me/BozoDevelopment"
|
||||
)
|
|
@ -1,36 +0,0 @@
|
|||
import time
|
||||
from typing import Callable, Dict, Awaitable, Any
|
||||
|
||||
from aiogram import BaseMiddleware
|
||||
from aiogram.exceptions import TelegramRetryAfter
|
||||
from aiogram.types import Message, ErrorEvent, Update, CallbackQuery
|
||||
|
||||
|
||||
class RetryMessageMiddleware(BaseMiddleware):
|
||||
"""
|
||||
Protects from user don't get update by message
|
||||
"""
|
||||
|
||||
async def __call__(
|
||||
self,
|
||||
handler: Callable[[Message, Dict[str, Any]], Awaitable[Any]],
|
||||
event: ErrorEvent[TelegramRetryAfter, Update],
|
||||
data: Dict[str, Any]
|
||||
) -> Any:
|
||||
time.sleep(event.exception.retry_after)
|
||||
return await handler(event.update.message, data)
|
||||
|
||||
|
||||
class RetryCallbackMiddleware(BaseMiddleware):
|
||||
"""
|
||||
Protects from user don't get update by callbackquery
|
||||
"""
|
||||
|
||||
async def __call__(
|
||||
self,
|
||||
handler: Callable[[CallbackQuery, Dict[str, Any]], Awaitable[Any]],
|
||||
event: ErrorEvent[TelegramRetryAfter, Update],
|
||||
data: Dict[str, Any]
|
||||
) -> Any:
|
||||
time.sleep(event.exception.retry_after)
|
||||
return await handler(event.update.callback_query, data)
|
|
@ -1,6 +1,2 @@
|
|||
from .solution_simpler import SolutionSimpler
|
||||
from .lists_of_content import *
|
||||
from .fsm_states import *
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,301 +0,0 @@
|
|||
from dataclasses import dataclass
|
||||
from typing import List, Any
|
||||
|
||||
import g4f
|
||||
from g4f import Provider
|
||||
from g4f.Provider import RetryProvider
|
||||
from varname import nameof
|
||||
|
||||
from bozenka.database.tables.telegram import ChatSettings
|
||||
|
||||
|
||||
@dataclass
|
||||
class BaseFeature:
|
||||
"""
|
||||
Basic class of Feature.
|
||||
Have inside desription, name, callback name,
|
||||
"""
|
||||
name: str
|
||||
description: str
|
||||
callback_name: str
|
||||
settings_name: str
|
||||
db_name: Any
|
||||
|
||||
|
||||
@dataclass
|
||||
class BaseCategory:
|
||||
"""
|
||||
Basic class of Feature category
|
||||
Have inside category name, callbackname
|
||||
"""
|
||||
name: str
|
||||
callback_name: str
|
||||
|
||||
|
||||
# List of categories, avaible in bot
|
||||
list_of_categories = [
|
||||
BaseCategory(name="Администраторы 👮♂", callback_name="Admins"),
|
||||
BaseCategory(name="Пользователи 👤", callback_name="Members"),
|
||||
BaseCategory(name="В разработке 👨💻", callback_name="Devs")
|
||||
]
|
||||
|
||||
# List of features, avaible in bot
|
||||
list_of_features = {
|
||||
"Admins": [
|
||||
BaseFeature(
|
||||
name="Закреп 📌",
|
||||
description="<b>Закреп</b>📌"
|
||||
"\nДанная функция включает команды:"
|
||||
"<pre>/pin - закрепляет сообщение\n"
|
||||
"/unpin - открепляет сообщение\n"
|
||||
"/unpin_all - открепляет все сообщения, которые видит бот</pre>\n"
|
||||
"Для исполнения <b>требует соответсвующих прав от пользователя и их наличие у бота.</b>",
|
||||
callback_name="pins",
|
||||
settings_name="pins",
|
||||
db_name=ChatSettings.pins
|
||||
),
|
||||
BaseFeature(
|
||||
name="Модерация чата 🕵️",
|
||||
description="<b>Модерация чата</b>🕵️\nДанная настройка включает следущие комманды:"
|
||||
"\n<pre>/ban [время блокировки] [причина блокировки] - блокировка пользователя"
|
||||
"\n/unban - разблокировка пользователя\n"
|
||||
"/mute [время мута] [причина мута] - мут пользователя\n"
|
||||
"/unmute - Размут пользователя</pre>\n"
|
||||
"Время обозначается как:"
|
||||
"<pre>1h - один час, "
|
||||
"1d - один день, "
|
||||
"1m - одна минута, "
|
||||
"1s - одна секунда</pre>\n"
|
||||
"Для того, "
|
||||
"чтобы выполнить одну из комманд по отношению к пользователю, "
|
||||
"ответьте на сообщение пользователя и используйте команду\n"
|
||||
"Для исполнения <b>требует соответсвующих прав от пользователя и их наличие у бота.</b>",
|
||||
callback_name="moderation",
|
||||
settings_name="moderation",
|
||||
db_name=ChatSettings.moderation
|
||||
),
|
||||
BaseFeature(
|
||||
name="Работа с Форумом 💬",
|
||||
description="<b>Работа с Форумом</b>💬\nДанная настройка включает следущие комманды:\n"
|
||||
"<pre>/open - открывают тему форума\n"
|
||||
"/close - закрывают тему форума\n"
|
||||
"/open_general - открывают основную тему форума\n"
|
||||
"/close_general - закрывает основную тему форума\n"
|
||||
"/hide_general - прячет основную тему форума\n"
|
||||
"/show_general - показывает основную тему форума</pre>\n"
|
||||
"Для исполнения <b>требует соответсвующих прав от пользователя и их наличие у бота. Также должен быть"
|
||||
"включен форум</b>",
|
||||
callback_name="topics",
|
||||
settings_name="topics",
|
||||
db_name=ChatSettings.topics
|
||||
),
|
||||
BaseFeature(
|
||||
name="Приглашения в Чат ✉",
|
||||
description="<b>Генератор приглашения в Чат ✉</b>\n"
|
||||
"Разрешает использование комманды /invite в чате, для созданния приглашений.\n"
|
||||
"Для исполнения <b>требует соответсвующих прав от пользователя и их наличие у бота.</b>",
|
||||
callback_name="invites",
|
||||
settings_name="invite_generator",
|
||||
db_name=ChatSettings.invite_generator
|
||||
),
|
||||
BaseFeature(
|
||||
name="Результаты в лс ✉",
|
||||
description="<b>Результаты в личных сообщениях ✉</b>\n"
|
||||
"Отправляет все результаты команд модерации в личные сообщения пользователя\n"
|
||||
"Никаких особых прав у бота не требует.",
|
||||
callback_name="results_in_dm",
|
||||
settings_name="results_in_dm",
|
||||
db_name=ChatSettings.results_in_dm
|
||||
),
|
||||
BaseFeature(
|
||||
name="Оповещение об ограничении 🗯",
|
||||
description="<b>Оповещение об ограничении 🗯</b>\n"
|
||||
"Отправляет оповещение пользователю об его муте, бане\n"
|
||||
"Никаких особых прав у бота не требует.",
|
||||
callback_name="restrict_notification",
|
||||
settings_name="restrict_notification",
|
||||
db_name=ChatSettings.restrict_notification
|
||||
)
|
||||
],
|
||||
"Members": [
|
||||
BaseFeature(
|
||||
name="Приветсвенные сообщения 👋",
|
||||
description="<b>Приветсвенные сообщения 👋</b>"
|
||||
"\nПриветсвенные сообщения новым и ушедшим пользователям.",
|
||||
callback_name="welcome",
|
||||
settings_name="welcome_messages",
|
||||
db_name=ChatSettings.welcome_messages
|
||||
),
|
||||
BaseFeature(
|
||||
name="Оповещение о муте 📬",
|
||||
description="<b>Оповещение о муте 📬</b>"
|
||||
"\nОповещает пользователя в личных сообщениях, что тот был: замучен, размучен, забанен, разбанен",
|
||||
callback_name="notify",
|
||||
settings_name="restrict_notification",
|
||||
db_name=ChatSettings.restrict_notification
|
||||
)
|
||||
],
|
||||
"Devs": [
|
||||
BaseFeature(
|
||||
name="Функция Привет 👋",
|
||||
description="<b>Функция `Привет` </b>👋"
|
||||
"\nБот будет отвечать на комманды "
|
||||
"/hi, /hello, /privet и т.п., отвечая приветсвием на сообщение пользователя.",
|
||||
callback_name="hi",
|
||||
settings_name="hi_command",
|
||||
db_name=ChatSettings.hi_command
|
||||
),
|
||||
BaseFeature(
|
||||
name="ИИ ЧатБот 🤖",
|
||||
description="<b>ИИ ЧатБот </b>🤖"
|
||||
"\nЕсть поддержка:\n"
|
||||
"- Моделей Gpt4All\n"
|
||||
"- Провайдеров Gpt4Free и моделей\n"
|
||||
"Для использования:\n"
|
||||
"<pre>/conversations</pre>"
|
||||
"\nНаходится в разработке, планируется в будущем. Следите за обновлениями 😘",
|
||||
callback_name="gtm",
|
||||
settings_name="gpt_conversations",
|
||||
db_name=ChatSettings.text_generation
|
||||
),
|
||||
BaseFeature(
|
||||
name="Генерация изображений 📸",
|
||||
description="<b>Генерация изображений </b>🤖"
|
||||
"\nНаходится в разработке, планируется в будущем. Следите за обновлениями 😘",
|
||||
callback_name="gpm",
|
||||
settings_name="123",
|
||||
db_name=ChatSettings.image_generation
|
||||
)
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
|
||||
def generate_list_of_features(category: str) -> list[BaseFeature]:
|
||||
"""
|
||||
Generates list of features avaible at some category
|
||||
made for future auto translate
|
||||
:param category:
|
||||
:return:
|
||||
"""
|
||||
return list_of_features[category]
|
||||
|
||||
|
||||
ru_cmds = {
|
||||
# /info command translation
|
||||
"info": "Информация об чате с названием nameofchathere"
|
||||
"descr\n"
|
||||
"Является chattype isforum requiredinvite\n"
|
||||
"Скрытые участники ishiddenmembers, isprotected",
|
||||
"chat_types": {"group": "группой", "supergroup": "cупер группой"},
|
||||
"forum_type": {True: "и форумом,", False: ", не является форумом,", None: ", не является форумом,"},
|
||||
"required_invite": {True: "требуется одобрение заявки на вступление", False: "заявка не требуется.",
|
||||
None: "заявка не требуется."},
|
||||
"hidden_members": {True: "присуствуют", False: "отсуствуют", None: "отсуствуют"},
|
||||
"isprotected": {True: "пересылать сообщения из группы можно.", False: "пересылать сообщения из группы нельзя.",
|
||||
None: "пересылать сообщения из группы можно."},
|
||||
# /hi command translation
|
||||
"hi": "Привет, user 👋",
|
||||
"user": "пользователь",
|
||||
# /invite command translation
|
||||
"invite_generation": "<em> Держите ваше приглашение в чат, user 👋</em>",
|
||||
"sir": "сэр",
|
||||
# Ban cases
|
||||
"ban_1": "Удача ✅\n"
|
||||
"Пользователь banned был заблокирован пользователем admin.\n"
|
||||
"По причине ban_reason, до даты ban_time",
|
||||
"ban_2": "Удача ✅\n"
|
||||
"Пользователь banned был заблокирован пользователем admin.\n"
|
||||
"По причине ban_reason.",
|
||||
"ban_3": "Удача ✅\n"
|
||||
"Пользователь banned был заблокирован пользователем admin.",
|
||||
"ban_4": "Удача ✅\n"
|
||||
"Пользователь banned был заблокирован пользователем admin, до даты ban_time.\n",
|
||||
"ban_success": "Успешно заблокирован ✅",
|
||||
# Unban cases
|
||||
"unban_1": "Удача ✅\n"
|
||||
"Пользователь unbanned был разблокирован пользователем admin.\n"
|
||||
"По причине reason.",
|
||||
"unban_2": "Удача ✅\n"
|
||||
"Пользователь unbanned был разблокирован пользователем admin.",
|
||||
"unban_3": "Ошибка ❌\n"
|
||||
"Этот пользователь не находится в бане.",
|
||||
"unban_success": "Успешно разблокирован ✅",
|
||||
# Work with topic
|
||||
"topic_closed": "Удача ✅\n"
|
||||
"Пользователь user закрыл данное обсуждение.",
|
||||
"open_topic": "Удача ✅\n"
|
||||
"Пользователь user открыл данное обсуждение.",
|
||||
"close_general": "Удача ✅\n"
|
||||
"Пользователь user закрыл основное обсуждение",
|
||||
"open_general": "Удача ✅\n"
|
||||
"Пользователь user открыл основное обсуждение",
|
||||
"hide_general": "Удача ✅\n"
|
||||
"Пользователь user скрыл основное обсуждение",
|
||||
"show_general": "Удача ✅\n"
|
||||
f"Пользователь user раскрыл основное обсуждение",
|
||||
"topic_renamed": "Удача ✅\n"
|
||||
f"Пользователь user переименовал обсуждение <pre>originalthreadname</pre>",
|
||||
# GPT cases
|
||||
"generate_answer": "Пожалуйста подождите, ответ генерируется ⏰",
|
||||
"select_provider": "Выберите пожалуйста одного из провайдеров 👨💻",
|
||||
"select_provider_message": "Выберите пожалуйста одного из провайдеров 👨💻",
|
||||
"help_notification": "Это текущая странница 📃",
|
||||
"select_provider_page": "Пожалуйста, выберите одного из провайдеров 👨💻\n"
|
||||
"Ваша текущая страница это pagecount📄",
|
||||
"moved_page": "Перенесли на страницу pagecount📄",
|
||||
"finish_gpt4all_message": "Удача ✅\n"
|
||||
"Вы теперь можете спокойно вести диалог 🤖\n"
|
||||
"Чтобы прекратить общение, используйте /cancel",
|
||||
"finish_gptfree_message": "Удача ✅\n"
|
||||
"Вы теперь можете спокойно вести диалог 🤖\n"
|
||||
"Вы выбрали модель <pre>modelname</pre>👾, от провайдера <pre>providername</pre>👨💻\n"
|
||||
"Чтобы прекратить общение, используйте /cancel ",
|
||||
"finish_gpt": "Вы теперь можете спокойно вести диалог 🤖",
|
||||
"select_model_message": "Выберите пожалуйста модель ИИ 👾",
|
||||
"select_model": "Выберите пожалуйста модель ИИ 👾",
|
||||
# No Permission translation
|
||||
"no_perms": "Ошибка ❌"
|
||||
"У вас нет прав на использование этой комманды 🚫",
|
||||
# After adding bot into group message text
|
||||
"after_adding": "Здраствуйте администраторы чата 👋\n"
|
||||
"Я - <b>бозенька</b>, мультифункциональный бот, разрабатываемый Bozo Developement\n"
|
||||
"Выдайте мне <b>полные права администратора</b> для моей полной работы."
|
||||
"Чтобы настроить функционал, используйте /setup или кнопку под сообщением",
|
||||
# Success
|
||||
"success": "Удача ✅"
|
||||
|
||||
}
|
||||
|
||||
list_of_commands = {
|
||||
# Main commands
|
||||
("start", "Command to start work with bozenka the bot"),
|
||||
('setup', 'Command to setup bozenka features in chat'),
|
||||
# Moderation commands
|
||||
("ban", "Command to ban user in chat"),
|
||||
('unban', 'Command to unban user in chat'),
|
||||
('mute', 'Command to mute user in chat'),
|
||||
('unmute', 'Command to unmute user in chat'),
|
||||
# Work with pins
|
||||
('pin', 'Pin fast any message in chat'),
|
||||
('unpin', 'Unpin fast any message in chat'),
|
||||
# Close / open topics
|
||||
('close', 'Close fast topic (not general) in chat'),
|
||||
('open', 'Open fast topic (not general) in chat'),
|
||||
('hide_general', 'Hide general topic in chat'),
|
||||
('show_general', 'Show general topic in chat'),
|
||||
("close_general", 'Closes general topic in chat'),
|
||||
("open_general", 'Opens general topic in chat'),
|
||||
# AI related
|
||||
('conversation', 'Starts conversation with text generative ai'),
|
||||
('imagine', 'Starts conversation with image generative ai'), \
|
||||
# Basic features
|
||||
('invite', 'Generates invite into current chat'),
|
||||
('about', 'Sends information about bozenka'),
|
||||
('hi', 'Sends test welcome message'),
|
||||
('info', 'Get information about chat')
|
||||
}
|
||||
|
||||
translations = {
|
||||
"ru": ru_cmds,
|
||||
}
|
|
@ -12,8 +12,8 @@ from aiogram.types import ChatPermissions, CallbackQuery
|
|||
from sqlalchemy import Update
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
from bozenka.database import get_user_info, Users
|
||||
from bozenka.database.tables.telegram import get_chat_configuration, ChatSettings
|
||||
from bozenka.database import get_user_info, TelegramUsers
|
||||
from bozenka.database.tables.telegram import get_chat_configuration, TelegramChatSettings
|
||||
from bozenka.instances.telegram.utils.callbacks_factory import BanData, UnbanData, MuteData, UnmuteData
|
||||
|
||||
|
||||
|
@ -59,7 +59,7 @@ class SolutionSimpler:
|
|||
return
|
||||
finally:
|
||||
if not await get_user_info(user_id=data.user_id_ban, chat_id=call.message.chat.id, session=session):
|
||||
new_user = Users(
|
||||
new_user = TelegramUsers(
|
||||
user_id=data.user_id_ban,
|
||||
chat_id=call.message.chat.id,
|
||||
is_banned=True,
|
||||
|
@ -74,9 +74,9 @@ class SolutionSimpler:
|
|||
async with session() as session:
|
||||
async with session.begin():
|
||||
await session.execute(
|
||||
Update(Users)
|
||||
Update(TelegramUsers)
|
||||
.values(is_banned=True, ban_reason=None)
|
||||
.where(Users.user_id == data.user_id_ban and Users.chat_id == call.message.chat.id))
|
||||
.where(TelegramUsers.user_id == data.user_id_ban and TelegramUsers.chat_id == call.message.chat.id))
|
||||
|
||||
@staticmethod
|
||||
async def ban_user(msg: types.Message, cmd: CommandObject, session: async_sessionmaker) -> dict[str, None | str | bool]:
|
||||
|
@ -125,7 +125,7 @@ class SolutionSimpler:
|
|||
return config
|
||||
finally:
|
||||
if not await get_user_info(user_id=msg.reply_to_message.from_user.id, chat_id=msg.chat.id, session=session):
|
||||
new_user = Users(
|
||||
new_user = TelegramUsers(
|
||||
user_id=msg.reply_to_message.from_user.id,
|
||||
chat_id=msg.chat.id,
|
||||
is_banned=True,
|
||||
|
@ -140,9 +140,9 @@ class SolutionSimpler:
|
|||
async with session() as session:
|
||||
async with session.begin():
|
||||
await session.execute(
|
||||
Update(Users)
|
||||
Update(TelegramUsers)
|
||||
.values(is_banned=True, ban_reason=None if config["reason"] == "" else config["reason"])
|
||||
.where(Users.user_id == msg.reply_to_message.from_user.id and Users.chat_id == msg.chat.id))
|
||||
.where(TelegramUsers.user_id == msg.reply_to_message.from_user.id and TelegramUsers.chat_id == msg.chat.id))
|
||||
return config
|
||||
|
||||
@staticmethod
|
||||
|
@ -158,9 +158,9 @@ class SolutionSimpler:
|
|||
async with session() as session:
|
||||
async with session.begin():
|
||||
await session.execute(
|
||||
Update(Users)
|
||||
Update(TelegramUsers)
|
||||
.values(is_banned=False, ban_reason=None)
|
||||
.where(Users.user_id == data.user_id_unban and Users.chat_id == call.message.chat.id)
|
||||
.where(TelegramUsers.user_id == data.user_id_unban and TelegramUsers.chat_id == call.message.chat.id)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
@ -179,9 +179,9 @@ class SolutionSimpler:
|
|||
async with session() as session:
|
||||
async with session.begin():
|
||||
await session.execute(
|
||||
Update(Users)
|
||||
Update(TelegramUsers)
|
||||
.values(is_banned=False, ban_reason=None)
|
||||
.where(Users.user_id == msg.from_user.id and Users.chat_id == msg.chat.id)
|
||||
.where(TelegramUsers.user_id == msg.from_user.id and TelegramUsers.chat_id == msg.chat.id)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
@ -227,7 +227,7 @@ class SolutionSimpler:
|
|||
if info is None:
|
||||
print("TTTTT")
|
||||
print(info)
|
||||
new_user = Users(
|
||||
new_user = TelegramUsers(
|
||||
user_id=data.user_id_mute,
|
||||
chat_id=call.message.chat.id,
|
||||
is_banned=None,
|
||||
|
@ -242,9 +242,9 @@ class SolutionSimpler:
|
|||
async with session() as session:
|
||||
async with session.begin():
|
||||
await session.execute(
|
||||
Update(Users)
|
||||
Update(TelegramUsers)
|
||||
.values(is_muted=True, mute_reason=None)
|
||||
.where(Users.user_id == data.user_id_mute and Users.chat_id == call.message.chat.id))
|
||||
.where(TelegramUsers.user_id == data.user_id_mute and TelegramUsers.chat_id == call.message.chat.id))
|
||||
|
||||
@staticmethod
|
||||
async def mute_user(msg: types.Message, cmd: CommandObject, session: async_sessionmaker) -> dict[str, None | str | bool]:
|
||||
|
@ -282,7 +282,7 @@ class SolutionSimpler:
|
|||
level=logging.INFO)
|
||||
finally:
|
||||
if not await get_user_info(user_id=msg.reply_to_message.from_user.id, chat_id=msg.chat.id, session=session):
|
||||
new_user = Users(
|
||||
new_user = TelegramUsers(
|
||||
user_id=msg.reply_to_message.from_user.id,
|
||||
chat_id=msg.chat.id,
|
||||
is_banned=None,
|
||||
|
@ -297,9 +297,9 @@ class SolutionSimpler:
|
|||
async with session() as session:
|
||||
async with session.begin():
|
||||
await session.execute(
|
||||
Update(Users)
|
||||
Update(TelegramUsers)
|
||||
.values(is_muted=True, mute_reason=None if config["reason"] == "" else config["reason"])
|
||||
.where(Users.user_id == msg.reply_to_message.from_user.id and Users.chat_id == msg.chat.id))
|
||||
.where(TelegramUsers.user_id == msg.reply_to_message.from_user.id and TelegramUsers.chat_id == msg.chat.id))
|
||||
return config
|
||||
|
||||
@staticmethod
|
||||
|
@ -318,9 +318,9 @@ class SolutionSimpler:
|
|||
async with session() as session:
|
||||
async with session.begin():
|
||||
await session.execute(
|
||||
Update(Users)
|
||||
Update(TelegramUsers)
|
||||
.values(is_muted=False, mute_reason=None, )
|
||||
.where(Users.user_id == data.user_id_unmute and Users.chat_id == call.message.chat.id)
|
||||
.where(TelegramUsers.user_id == data.user_id_unmute and TelegramUsers.chat_id == call.message.chat.id)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
@ -341,9 +341,9 @@ class SolutionSimpler:
|
|||
async with session() as session:
|
||||
async with session.begin():
|
||||
await session.execute(
|
||||
Update(Users)
|
||||
Update(TelegramUsers)
|
||||
.values(is_muted=False, mute_reason=None, )
|
||||
.where(Users.user_id == msg.from_user.id and Users.chat_id == msg.chat.id)
|
||||
.where(TelegramUsers.user_id == msg.from_user.id and TelegramUsers.chat_id == msg.chat.id)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
@ -411,7 +411,7 @@ class SolutionSimpler:
|
|||
chat_data = await get_chat_configuration(msg.chat.id, session)
|
||||
print(chat_data)
|
||||
if not chat_data:
|
||||
new_chat_data = ChatSettings(chat_id=msg.chat.id)
|
||||
new_chat_data = TelegramChatSettings(chat_id=msg.chat.id)
|
||||
async with session() as session:
|
||||
async with session.begin():
|
||||
await session.merge(new_chat_data)
|
||||
|
|
Loading…
Reference in a new issue