Changelog:

- /start finished
- started codding /setup database
- too much refactors
- started codding image generation
- reverted changes for /ban recode
This commit is contained in:
kittyneverdies 2023-12-30 14:52:36 +03:00
parent 3ee2844ffc
commit 3fc4432e42
30 changed files with 580 additions and 289 deletions

View File

@ -2,7 +2,7 @@
[alembic]
# path to migration scripts
script_location = bozenka/db/migrate
script_location = bozenka/database/migrate
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
# Uncomment the line below if you want the files to be prepended with date and time

View File

@ -13,6 +13,8 @@ def launch_instances() -> None:
:return:
"""
logging.log(msg="Setting up g4f logging!", level=logging.INFO)
logging.basicConfig(level=logging.INFO)
logging.log(msg="Setting up logging!", level=logging.INFO)
g4f.logging = True
db_url = generate_url()

View File

@ -22,7 +22,7 @@ if config.config_file_name is not None:
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
target_metadata = bozenka.db.main.MainModel.metadata
target_metadata = bozenka.database.main.MainModel.metadata
# other values from the config, defined by the needs of env.py,
# can be acquired:

View File

@ -1,6 +1,7 @@
import asyncio
from typing import Tuple, Any
from sqlalchemy import Column, Integer, VARCHAR, Boolean, Text, select, BigInteger, Row
from sqlalchemy import Column, Integer, VARCHAR, Boolean, Text, select, BigInteger, Row, inspect
from sqlalchemy.ext.asyncio import async_sessionmaker
from sqlalchemy.orm import sessionmaker
from bozenka.database.main import MainModel
@ -65,9 +66,32 @@ async def get_settings(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()
async def get_setting(chat_id: int, session: async_sessionmaker, setting: str) -> bool:
"""
Return setting by sessionmaker and chat_id
:param chat_id: id of telegram chat
:param session: sessionmaker from dispatcher
:param setting: string setting what we need to get
:return:
"""
async with session() as session:
async with session.begin():
rows = (await session.execute(select(ChatSettings).where(ChatSettings.chat_id == chat_id))).one().__dict__
for r in rows:
print(r.__dict__)
print("!@#1221312321312312313")
print(rows)
for i in rows:
print("+")
print(i)
async def get_user(user_id: int, chat_id: int, session: async_sessionmaker) -> Row[tuple[Any, ...] | Any] | None:
"""
Return user with sessionmaker by user_id and chat_id.

View File

@ -1,6 +1,19 @@
# List of generative categories, what we support
# List of text generative categories, what we support
text_generative_categories = [
"Gpt4Free",
"Gpt4All",
]
# List of image generative categories, what we support
image_generative_categories = [
"Kadinsky"
]
image_generative_size = [
"1024x1024",
"1024x576",
"576x1024",
"1024x680",
"680x1024"
]

View File

@ -6,7 +6,16 @@ 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:
:param model_filename: File name of gpt4all model
:return:
"""
return os.path.exists("models\\" + model_filename)
def get_model_path(model_filename: str) -> str:
"""
Just returning path of our gpt4all models.
:param model_filename: File name of gpt4all model
:return:
"""
return os.curdir + "models\\" + model_filename

View File

@ -1,4 +1,5 @@
import g4f
import g4f.Provider
from g4f.Provider import RetryProvider
from varname import nameof
@ -8,15 +9,9 @@ def generate_gpt4free_providers():
Generates list of g4f providers
:return:
"""
provider = {}
for prov in g4f.Provider.__all__:
if prov != "BaseProvider" and prov != "AsyncProvider" and prov != "RetryProvider":
exec(f"provider['{prov}']=g4f.Provider.{prov}")
result = {}
for check in provider:
if provider[check].working:
result[check] = provider[check]
return result
return {prov: g4f.Provider.ProviderUtils.convert[prov] for prov in g4f.Provider.__all__
if prov != "BaseProvider" and prov != "AsyncProvider" and prov != "RetryProvider" and
g4f.Provider.ProviderUtils.convert[prov].working}
def generate_gpt4free_models():
@ -25,16 +20,17 @@ def generate_gpt4free_models():
:return:
"""
models = {}
for model, model_name in g4f.models.ModelUtils.convert.items(), g4f.models.ModelUtils.convert.keys():
for model_name, model in g4f.models.ModelUtils.convert.items():
if type(model.best_provider) is RetryProvider:
for pr in model.best_provider.providers:
if pr in models:
models[nameof(pr)].append(model_name)
if pr.__name__ in models:
models[pr.__name__].append(model_name)
else:
models[nameof(pr)] = [model_name]
models[pr.__name__] = [model_name]
else:
if nameof(model.best_provider) in models:
models[nameof(model.best_provider)].append(model_name)
if model.best_provider.__name__ in models:
models[model.best_provider.__name__].append(model_name)
else:
models[nameof(model.best_provider)] = [model_name]
models[model.best_provider.__name__] = [model_name]
print(models)
return models

View File

@ -0,0 +1,50 @@
import json
import time
import requests
class Kadinsky:
"""
Kadinsky class from their documentation.
"""
def __init__(self, url, api_key, secret_key):
self.URL = url
self.AUTH_HEADERS = {
'X-Key': f'Key {api_key}',
'X-Secret': f'Secret {secret_key}',
}
def get_model(self):
response = requests.get(self.URL + 'key/api/v1/models', headers=self.AUTH_HEADERS)
data = response.json()
return data[0]['id']
def generate(self, prompt, model, images=1, width=1024, height=1024):
params = {
"type": "GENERATE",
"numImages": images,
"width": width,
"height": height,
"generateParams": {
"query": f"{prompt}"
}
}
data = {
'model_id': (None, model),
'params': (None, json.dumps(params), 'application/json')
}
response = requests.post(self.URL + 'key/api/v1/text2image/run', headers=self.AUTH_HEADERS, files=data)
data = response.json()
return data['uuid']
def check_generation(self, request_id, attempts=10, delay=10):
while attempts > 0:
response = requests.get(self.URL + 'key/api/v1/text2image/status/' + request_id, headers=self.AUTH_HEADERS)
data = response.json()
if data['status'] == 'DONE':
return data['images']
attempts -= 1
time.sleep(delay)

View File

@ -12,11 +12,10 @@ from bozenka.instances.telegram.utils.simpler import list_of_commands
async def launch_telegram_instance(session_maker: async_sessionmaker) -> None:
"""
Launches telegram bot with token from enviroment
:param session_maker:
:return:
"""
logging.basicConfig(level=logging.INFO)
logging.log(msg="Setting up logging!", level=logging.INFO)
g4f.logging = True
logging.log(msg="-" * 50 + "TELEGRAM INSTANCE LAUNCH" + "-" * 50, level=logging.INFO)
bot = Bot(token=os.getenv("tg_bot_token"), parse_mode="HTML")

View File

@ -9,7 +9,7 @@ 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, unban
from bozenka.instances.telegram.handlers.chat_admin.bans import ban_command, unban_command
from bozenka.instances.telegram.utils.filters import *
@ -29,11 +29,11 @@ def register_admin_cmd(router: Router) -> None:
router.message.register(help_pin, Command(commands=["pin"]))
router.message.register(help_unpin, Command(commands=["unpin"]))
# Ban / Unban commands handler
router.message.register(ban, Command(commands="ban"),
router.message.register(ban_command, Command(commands="ban"),
IsAdminFilter(True))
router.message.register(ban, Command(commands="ban"),
router.message.register(ban_command, Command(commands="ban"),
IsAdminFilter(True), F.reply_to_message.text)
router.message.register(unban, Command(commands="unban"),
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"]),

View File

@ -8,7 +8,7 @@ from bozenka.instances.telegram.utils.keyboards import ban_keyboard, delete_keyb
from bozenka.instances.telegram.utils.simpler import SolutionSimpler, ru_cmds
async def ban(msg: Message, command: CommandObject, session_maker: async_sessionmaker):
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
@ -25,68 +25,23 @@ async def ban(msg: Message, command: CommandObject, session_maker: async_session
config = await SolutionSimpler.ban_user(msg, command, session_maker)
if config["reason"] and config["ban_time"]:
if mentions := [entity for entity in msg.entities if entity.type == 'mention']:
mentions_list = ""
for mention in mentions:
mentions_list += f"{mention.user.mention_html()} "
if msg.reply_to_message.from_user:
mentions_list += f"{msg.reply_to_message.from_user.mention_html()} "
await msg.answer("Удача ✅\n"
f"Пользователи {mentions_list}были заблокирован пользователем {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))
else:
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))
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"]:
if mentions := [entity for entity in msg.entities if entity.type == 'mention']:
mentions_list = ""
for mention in mentions:
mentions_list += f"{mention.user.mention_html()} "
if msg.reply_to_message.from_user:
mentions_list += f"{msg.reply_to_message.from_user.mention_html()} "
await msg.answer(
"Удача ✅\n"
f"Пользователи {mentions_list}были заблокирован пользователем {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)
)
else:
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)
)
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"]:
if mentions := [entity for entity in msg.entities if entity.type == 'mention']:
mentions_list = ""
for mention in mentions:
mentions_list += f"{mention.user.mention_html()} "
if msg.reply_to_message.from_user:
mentions_list += f"{msg.reply_to_message.from_user.mention_html()} "
await msg.answer(
"Удача ✅\n"
f"Пользователи {msg.reply_to_message.from_user.mention_html()}были заблокирован пользователем {msg.from_user.mention_html()}\n"
f"До даты {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()}, до даты {config['ban_time']}",
reply_markup=ban_keyboard(admin_id=msg.from_user.id, ban_id=msg.reply_to_message.from_user.id)
)
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"
@ -95,7 +50,7 @@ async def ban(msg: Message, command: CommandObject, session_maker: async_session
)
async def unban(msg: Message, command: CommandObject, session_maker: async_sessionmaker):
async def unban_command(msg: Message, command: CommandObject, session_maker: async_sessionmaker) -> None:
"""
/unban command function
:param msg: Message telegram object
@ -125,13 +80,12 @@ async def unban(msg: Message, command: CommandObject, session_maker: async_sessi
)
async def status(msg: Message, session_maker: async_sessionmaker):
async def status_command(msg: Message, session_maker: async_sessionmaker) -> None:
"""
/status command function
Checks is user banned and muted
:param msg:
:param command:
:param session_maker:
:param msg: Message telegram object
:param session_maker: Session maker object of SqlAlchemy
:return:
"""
config = await SolutionSimpler.get_status(msg, session_maker)

View File

@ -2,14 +2,17 @@ import logging
from aiogram import Bot
from aiogram.types import Message as Message
from bozenka.instances.telegram.utils.simpler import ru_cmds
from sqlalchemy.ext.asyncio import async_sessionmaker
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
async def join(msg: Message):
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:
@ -17,13 +20,17 @@ async def join(msg: Message):
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()}👋",
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(ru_cmds["after_adding"])
await msg.delete()
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):
@ -41,4 +48,3 @@ async def leave(msg: Message, bot: Bot):
await msg.answer(
f"Пользователь {msg.left_chat_member.mention_html()} съехал с конфы, благодаря {msg.from_user.mention_html()}👋"
)

View File

@ -8,16 +8,17 @@ from aiogram.types import Message as Message
from bozenka.generative.gpt4all import check
from bozenka.instances.telegram.utils.keyboards import gpt_categories_keyboard, delete_keyboard, response_keyboard
from bozenka.instances.telegram.utils.simpler import generate_gpt4free_providers, ru_cmds, AnsweringGpt4All, \
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:
:param state:
:param msg: Message telegram object
:param state: FSM state of bot
:return:
"""
await msg.answer("Подождите пожалуйста, мы уже генерируем ответ для вас, подождите, когда мы ответим на ваш передыдущий вопрос",
@ -27,8 +28,8 @@ async def already_answering(msg: Message, state: FSMContext):
async def start_dialog_cmd(msg: Message, state: FSMContext):
"""
/conversation command handler, start
:param msg:
:param state:
:param msg: Message telegram object
:param state: FSM state of bot
:return:
"""
if await state.get_state():
@ -42,8 +43,8 @@ async def cancel_answering(msg: Message, state: FSMContext):
"""
Canceling dialog with generative model
Works on command /cancel
:param msg:
:param state:
:param msg: Message telegram object
:param state: FSM state of bot
:return:
"""
current = await state.get_state()
@ -57,8 +58,8 @@ async def cancel_answering(msg: Message, state: FSMContext):
async def g4a_generate_answer(msg: Message, state: FSMContext):
"""
Generating answer if Gpt4All has been selected
:param msg:
:param state:
:param msg: Message telegram object
:param state: FSM state of bot
:return:
"""
await state.set_state(AnsweringGpt4All.answering)
@ -100,8 +101,8 @@ async def g4a_generate_answer(msg: Message, state: FSMContext):
async def g4f_generate_answer(msg: Message, state: FSMContext):
"""
Generating answer if GPT4Free model and provider has been selected
:param msg:
:param state:
:param msg: Message telegram object
:param state: FSM state of bot
:return:
"""
await state.set_state(AnsweringGPT4Free.answering)
@ -126,7 +127,8 @@ async def g4f_generate_answer(msg: Message, state: FSMContext):
provider=providers[info["set_provider"]],
stream=False
)
except NameError:
except NameError or SyntaxError:
try:
response = g4f.ChatCompletion.create(
model=info["set_model"],
@ -152,6 +154,6 @@ async def g4f_generate_answer(msg: Message, state: FSMContext):
async def generate_image(msg: Message):
"""
Image generation, planned in future
:param msg:
:param msg: Message telegram object
"""
pass

View File

@ -18,13 +18,13 @@ def register_main_cmd(router: Router) -> None:
: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)
# Routes handler
router.message.register(add_to_chat, F.text == "Добавить в чат 🔌", F.chat.type == ChatType.PRIVATE)
router.message.register(features_list, F.text == "Функционал 🔨", F.chat.type == ChatType.PRIVATE)
# router.message.register(start_cmd, CommandStart)
router.message.register(setup_cmd, Command(commands=["setup"]))
# Registering command /setup
router.message.register(setup_cmd, Command(commands=["setup"]), ~(F.chat.type == ChatType.PRIVATE))
# After adding to chat handler
router.message.register(after_adding, F.content_type == ContentType.SUPERGROUP_CHAT_CREATED)
router.message.register(after_adding, F.content_type == ContentType.GROUP_CHAT_CREATED)
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)

View File

@ -1,4 +1,6 @@
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
@ -7,6 +9,7 @@ async def setup_cmd(msg: Message):
"""
/setup handler
:param msg:
:param session:
:return:
"""
await msg.answer("Привет владелец чата 👋\n"
@ -14,12 +17,14 @@ async def setup_cmd(msg: Message):
reply_markup=setup_keyboard())
async def after_adding(msg: Message):
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> для моей полной работы, если не выдали."

View File

@ -2,7 +2,7 @@ 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 start_keyboard_builder, help_keyboard
from bozenka.instances.telegram.utils.keyboards import start_keyboard_builder, help_keyboard, start_keyboard
async def start_cmd(msg: Message):
@ -15,47 +15,5 @@ async def start_cmd(msg: Message):
'Привет, пользователь, я - Бозенька 👋\n'
'Я мультизадачный телеграм (в будущем кросс-платформенный) бот с открытым исходным кодом, разрабатываемый <b>Bozo Developement</b>\n'
f'Выберите, что будете делать, {msg.from_user.mention_html(name="пользователь")}.',
reply_markup=start_keyboard_builder.as_markup(one_time_keyboard=True, resize_keyboard=True)
reply_markup=start_keyboard()
)
async def features_list(msg: Message):
"""
Shows features list from reply keyboard
:param msg:
:return:
"""
await msg.answer("Выберите категорию, по которой нужна помощь:",
reply_markup=help_keyboard())
async def about_devs(msg: Message):
"""
Shows info about devs from reply keyboard
:param msg:
:return:
"""
await msg.answer("Бозеьнка разработавается коммандой, состаящей из одного человека.\n"
"Исходный код находится под лицензией <b>GPL-3.0</b>. Исходный код проекта всегда будет открыт и доступен.\n"
"Исходный код проекта всегда можно найти тут: https://github.com/kittyneverdies/bozenka/")
await msg.delete()
async def add_to_chat(msg: Message):
"""
Sends link for adding bot into chat
:param msg:
:return:
"""
# Getting bot
me = await msg.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")
# Answering
await msg.answer("Чтобы добавить бозеньку в чат, нажмите на кнопку под сообщением:",
reply_markup=kb.as_markup())
await msg.delete()

View File

@ -1,16 +1,13 @@
__all__ = ["ban", "delete", "gpt"]
from aiogram import Router, F
from bozenka.instances.telegram.handlers.queries.start import inline_help_features, inline_help_feature, \
inline_back_help_categories, inline_back_help_features
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.gpt import *
from bozenka.instances.telegram.handlers.queries.text_generation import *
from bozenka.instances.telegram.handlers.queries.setup import *
@ -77,16 +74,34 @@ def register_queries(router: Router) -> None:
# /setup command related queries
# List of features based on category
router.callback_query.register(inline_setup_features, SetupCategory.filter())
router.callback_query.register(inline_setup_category, SetupCategory.filter())
# Menu of feature to enable or disable
router.callback_query.register(inline_feature, SetupFeature.filter())
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")

View File

@ -0,0 +1,27 @@
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,
Gpt4FreeModelPage, GptStop, GptBackMenu, Gpt4AllModel, Gpt4AllSelect
)
# Keyboards for messages
from bozenka.instances.telegram.utils.keyboards import (
gpt4free_models_keyboard,
gpt4free_providers_keyboard,
delete_keyboard, gpt_categories_keyboard, generate_gpt4all_page, gpt4all_model_menu
)
# Simpler utlilities
from bozenka.instances.telegram.utils.simpler import (
AnsweringGPT4Free,
AnsweringGpt4All,
)

View File

@ -1,11 +1,14 @@
from aiogram.types import *
from aiogram.types import CallbackQuery, Message
from sqlalchemy import select, Update
from sqlalchemy.ext.asyncio import async_sessionmaker
from bozenka.instances.telegram.utils.callbacks_factory import SetupCategory, SetupFeature
from bozenka.instances.telegram.utils.keyboards import setup_category_keyboard
from bozenka.database.tables.telegram import ChatSettings
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_features(call: CallbackQuery, callback_data: SetupCategory):
async def inline_setup_category(call: CallbackQuery, callback_data: SetupCategory):
"""
Query, what shows list of features to enable.
:param call:
@ -16,7 +19,7 @@ async def inline_setup_features(call: CallbackQuery, callback_data: SetupCategor
reply_markup=setup_category_keyboard(category=callback_data.category_name))
async def inline_setup_features_back(call: CallbackQuery, callback_data: SetupCategory):
async def inline_setup_category_back(call: CallbackQuery, callback_data: SetupAction):
"""
Query, what shows list of features to enable.
:param call:
@ -24,16 +27,40 @@ async def inline_setup_features_back(call: CallbackQuery, callback_data: SetupCa
:return:
"""
await call.message.edit_text("Выберите настройку, которую хотите изменить",
reply_markup=setup_category_keyboard(category=callback_data.category_name))
reply_markup=setup_category_keyboard(category=callback_data.feature_category))
async def inline_feature(call: CallbackQuery, callback_data: SetupFeature):
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:
"""
await call.message.edit_text(list_of_features[callback_data.feature_category][callback_data.feature_index].description)
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,
session=session_maker, msg=call.message))
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,
session=session, msg=call.message))

View File

@ -5,6 +5,82 @@ from bozenka.instances.telegram.utils.keyboards import *
from bozenka.instances.telegram.utils.simpler import list_of_features
async def inline_start(call: CallbackQuery):
"""
Query, what shows back menu of /start
:param call:
:return:
"""
await call.message.edit_text(
'Привет, пользователь, я - Бозенька 👋\n'
'Я мультизадачный телеграм (в будущем кросс-платформенный) бот с открытым исходным кодом, разрабатываемый <b>Bozo Developement</b>\n'
f'Выберите, что будете делать, {call.from_user.mention_html(name="пользователь")}.',
reply_markup=start_keyboard()
)
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:
"""
kb = InlineKeyboardMarkup(inline_keyboard=[[
]])
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"
"Бозеьнка разработавается коммандой, состаящей из одного человека, сам проект был изначально для развития моих навыков в Python\n"
"Исходный код находится под лицензией <b>GPL-3.0</b>. Исходный код проекта всегда будет открыт и доступен.\n"
"Исходный код проекта всегда можно найти по этой ссылке: https://github.com/kittyneverdies/bozenka/\n"
"Исходный код бота для телеграма можно найти по этой ссылке: https://github.com/kittyneverdies/bozenka/branch/telegram",
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.
@ -45,5 +121,6 @@ async def inline_help_feature(call: CallbackQuery, callback_data: HelpFeature):
: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))
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))

View File

@ -4,7 +4,7 @@ from aiogram import types
from aiogram.fsm.context import FSMContext
from gpt4all import GPT4All
from bozenka.instances.telegram.utils.simpler.states import *
from bozenka.instances.telegram.utils.simpler.fsm_states import *
# Callbacks for GPT
from bozenka.instances.telegram.utils.callbacks_factory import (
@ -170,10 +170,10 @@ async def inline_g4a_model(call: types.CallbackQuery, callback_data: Gpt4AllMode
if callback_data.user_id != call.from_user.id:
return
models = GPT4All.list_models()
name = models[callback_data.model_index]['name']
name = models[callback_data.index]['name']
await call.message.edit_text(f"{name}\n"
f"Обученно на основе {models[callback_data.model_index]['parameters']} строк 👨‍💻",
reply_markup=gpt4all_model_menu(user_id=call.from_user.id, index=callback_data.model_index))
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:
@ -186,13 +186,13 @@ async def inline_g4a_select_model(call: types.CallbackQuery, callback_data: Gpt4
"""
if callback_data.user_id != call.from_user.id:
return
await state.update_data(set_model=callback_data.model_index)
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.model_index]['name']}</b>👾 от Gpt4All\n"
f"Вы выбрали модель <b>{models[callback_data.index]['name']}</b>👾 от Gpt4All\n"
"Чтобы прекратить общение, используйте /cancel ",
reply_markup=delete_keyboard(admin_id=callback_data.user_id))

View File

@ -1,7 +1,24 @@
from aiogram.filters.callback_data import CallbackData
class Gpt4FreeProvider(CallbackData, prefix="provider"):
class ImageGenerationCategory(CallbackData, prefix="igc"):
"""
Callback with information related to image
"""
user_id: int
category: str
class ImageGeneration(CallbackData, prefix="igc"):
"""
Callback with information related to image
"""
user_id: int
category: str
size: str
class Gpt4FreeProvider(CallbackData, prefix="g4fp"):
"""
Callback with information related to selected provider
"""
@ -48,7 +65,7 @@ class Gpt4AllModel(CallbackData, prefix="g4a"):
Callback with information to show GPT4All content
"""
user_id: int
model_index: int
index: int
class GptBackMenu(CallbackData, prefix="gbm"):
@ -64,7 +81,7 @@ class Gpt4AllSelect(CallbackData, prefix="g4s"):
Callback with information about selecting model
"""
user_id: int
model_index: int
index: int
class GptStop(CallbackData, prefix="gs"):

View File

@ -23,6 +23,15 @@ class SetupBack(CallbackData, prefix="sb"):
back_to: str
class SetupAction(CallbackData, prefix="sa"):
"""
Callback with information to do with a feature
"""
action: str
feature_category: str
feature_index: int
class SetupEditFeature(CallbackData, prefix="sef"):
"""
Callback data with information to edit status of bozenka enabled feature

View File

@ -1,2 +1,2 @@
from .permissions import *
from .message_entities import *
from .chat_setting import *

View File

@ -0,0 +1,21 @@
from aiogram.filters import Filter
from aiogram.types import Message
from sqlalchemy.ext.asyncio import async_sessionmaker
from varname.helpers import exec_code
from bozenka.database.tables.telegram import get_settings
class ChatSettingFilter(Filter):
"""
Check, does chat have enabled features
"""
def __init__(self, settings: str) -> None:
self.settings = settings
async def __call__(self, msg: Message, session: async_sessionmaker) -> bool:
chat_setting = await get_settings(chat_id=msg.chat.id, session=session)
exec_code(f'return chat_setting.{self.settings}')
return True

View File

@ -2,13 +2,16 @@ import gpt4all
from typing import Any
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
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_setting
from bozenka.instances.telegram.utils.callbacks_factory import *
from bozenka.instances.telegram.utils.simpler import gpt_categories, generate_gpt4free_models, generate_gpt4free_providers, \
generate_list_of_features
from bozenka.instances.telegram.utils.simpler 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.
@ -16,6 +19,22 @@ 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="dialogai")],
[InlineKeyboardButton(text="Генерация Изображений 🖼", callback_data="dialogimage")],
]
)
return kb
# Help related keyboards
def help_keyboard() -> InlineKeyboardMarkup:
"""
@ -28,7 +47,9 @@ def help_keyboard() -> InlineKeyboardMarkup:
[InlineKeyboardButton(text="Пользователи 👤",
callback_data=HelpCategory(category_name="Members").pack())],
[InlineKeyboardButton(text="В разработке 👨‍💻",
callback_data=HelpCategory(category_name="Devs").pack())]])
callback_data=HelpCategory(category_name="Devs").pack())],
[InlineKeyboardButton(text="Вернуться 🔙", callback_data="back")]
])
return kb
@ -72,6 +93,8 @@ 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())],
@ -99,8 +122,37 @@ def setup_category_keyboard(category: str) -> InlineKeyboardMarkup:
return kb.as_markup()
def setup_feature_keyboard() -> InlineKeyboardMarkup:
pass
async def setup_feature_keyboard(category: str, index: int, session: async_sessionmaker,
msg: Message) -> InlineKeyboardMarkup:
"""
Generate keyboard for enabling or disabling
on of features
:param category:
:param index:
:param session:
:param msg:
:return:
"""
list_of_features = generate_list_of_features(category)
is_enabled = await get_setting(
chat_id=msg.chat.id,
session=session,
setting=list_of_features[index].settings_name)
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:
@ -116,6 +168,37 @@ def delete_keyboard(admin_id: int) -> InlineKeyboardMarkup:
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:
@ -125,8 +208,9 @@ def gpt_categories_keyboard(user_id: int) -> InlineKeyboardMarkup:
:return: InlineKeyboardMarkup
"""
builder = InlineKeyboardBuilder()
for category in gpt_categories:
builder.row(InlineKeyboardButton(text=category, callback_data=GptCategory(user_id=str(user_id), category=category).pack()))
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()
@ -212,30 +296,35 @@ def gpt4free_models_keyboard(user_id: int, provider, page: int) -> InlineKeyboar
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()))
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=Gpt4FreeModelPage(
page=str(len(models[provider]) // 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], provider=provider).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], provider=provider).pack()),
# Last page button
InlineKeyboardButton(text=str(len(models[provider]) // 4 if page != 0 else "1"),
callback_data=Gpt4FreeModelPage(
page=str(len(models[provider]) // 4 - 1) if page != 0 else "1",
user_id=user_id,
provider=provider).pack(),))
# First page button
InlineKeyboardButton(text=str(len(models[provider]) // 4 if page == 0 else "1"),
callback_data=Gpt4FreeModelPage(
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=Gpt4FreeModelPage(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=Gpt4FreeModelPage(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=Gpt4FreeModelPage(
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",
@ -246,7 +335,8 @@ def gpt4free_models_keyboard(user_id: int, provider, page: int) -> InlineKeyboar
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=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()
@ -348,7 +438,8 @@ def mute_keyboard(admin_id: int, ban_id: int) -> InlineKeyboardMarkup:
:return:
"""
kb = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="Спасибо ✅", callback_data=DeleteCallbackData(user_id_clicked=str(admin_id)).pack())],
[InlineKeyboardButton(text="Спасибо ✅",
callback_data=DeleteCallbackData(user_id_clicked=str(admin_id)).pack())],
[InlineKeyboardButton(text="Размутить 🛠️",
callback_data=UnmuteData(user_id_unmute=ban_id, user_id_clicked=admin_id).pack())]])
return kb
@ -362,8 +453,10 @@ def unmute_keyboard(admin_id: int, ban_id: int) -> InlineKeyboardMarkup:
: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=ban_id, user_id_clicked=admin_id).pack())]])
[InlineKeyboardButton(text="Спасибо ✅",
callback_data=DeleteCallbackData(user_id_clicked=str(admin_id)).pack())],
[InlineKeyboardButton(text="Замутить 🛠️",
callback_data=MuteData(user_id_mute=ban_id, user_id_clicked=admin_id).pack())]])
return kb
@ -379,7 +472,8 @@ def invite_keyboard(link: str, admin_id: int, chat_name: str) -> InlineKeyboardM
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=RevokeCallbackData(admin_id=admin_id, link=link).pack())],
[InlineKeyboardButton(text="Спасибо ✅",
callback_data=DeleteCallbackData(user_id_clicked=str(admin_id)).pack())]])
return kb
@ -421,7 +515,8 @@ def pin_msg_keyboard(user_id: int, msg_id: int) -> InlineKeyboardMarkup:
:return:
"""
kb = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="Открепить сообщение 📌", callback_data=UnpinMsg(user_id=user_id, msg_id=msg_id).pack())],
[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
@ -435,7 +530,8 @@ def unpin_msg_keyboard(user_id: int, msg_id: int) -> InlineKeyboardMarkup:
:return:
"""
kb = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="Открепить сообщение 📌", callback_data=PinMsg(user_id=user_id, msg_id=msg_id).pack())],
[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

View File

@ -1,6 +1,6 @@
from .solution_simpler import SolutionSimpler
from .lists_of_content import *
from .states import *
from .fsm_states import *

View File

@ -1,3 +1,4 @@
from dataclasses import dataclass
from typing import List
import g4f
@ -6,18 +7,36 @@ from g4f.Provider import RetryProvider
from varname import nameof
@dataclass
class BaseFeature:
"""
Basic class of Feature.
Have inside desription, name, callback name,
"""
def __init__(self, name: str, description: str, callback_name: str):
self.name = name
self.description = description
self.callback_name = callback_name
name: str
description: str
callback_name: str
settings_name: str
# List of features, avaible in bozenka
@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(
@ -28,7 +47,8 @@ list_of_features = {
"/unpin - открепляет сообщение"
"/unpin_all - открепляет все сообщения, которые видит бот"
"Для исполнения <b>требует соответсвующих прав от пользователя и их наличие у бота.</b>",
callback_name="pins"
callback_name="pins",
settings_name="pins"
),
BaseFeature(
name="Модерация чата 🕵️",
@ -46,7 +66,8 @@ list_of_features = {
"чтобы выполнить одну из комманд по отношению к пользователю, "
"ответьте на сообщение пользователя и используйте команду\n"
"Для исполнения <b>требует соответсвующих прав от пользователя и их наличие у бота.</b>",
callback_name="moderation"
callback_name="moderation",
settings_name="moderation"
),
BaseFeature(
name="Работа с Форумом 💬",
@ -59,14 +80,16 @@ list_of_features = {
"/show_general - показывает основную тему форума</pre>\n"
"Для исполнения <b>требует соответсвующих прав от пользователя и их наличие у бота. Также должен быть"
"включен форум</b>",
callback_name="topics"
callback_name="topics",
settings_name="topics"
),
BaseFeature(
name="Приглашения в Чат ✉",
description="<b>Генератор приглашения в Чат ✉</b>\n"
"Разрешает использование комманды /invite в чате, для созданния приглашений.\n"
"Для исполнения <b>требует соответсвующих прав от пользователя и их наличие у бота.</b>",
callback_name="invites"
callback_name="invites",
settings_name="invite_generator"
)
],
"Members": [
@ -74,13 +97,15 @@ list_of_features = {
name="Приветсвенные сообщения 👋",
description="<b>Приветсвенные сообщения 👋</b>"
"\nПриветсвенные сообщения новым и ушедшим пользователям.",
callback_name="welcome"
callback_name="welcome",
settings_name="welcome_messages"
),
BaseFeature(
name="Оповещение о муте 📬",
description="<b>Оповещение о муте 📬</b>"
"\nОповещает пользователя в личных сообщениях, что тот был: замучен, размучен, забанен, разбанен",
callback_name="notify",
settings_name="restrict_notification"
)
],
"Devs": [
@ -89,7 +114,8 @@ list_of_features = {
description="<b>Функция `Привет` </b>👋"
"\nБот будет отвечать на комманды "
"/hi, /hello, /privet и т.п., отвечая приветсвием на сообщение пользователя.",
callback_name="hi"
callback_name="hi",
settings_name="hi_command"
),
BaseFeature(
name="ИИ ЧатБот 🤖",
@ -100,24 +126,20 @@ list_of_features = {
"Для использования:\n"
"<pre>/conversations</pre>"
"\nНаходится в разработке, планируется в будущем. Следите за обновлениями 😘",
callback_name="gtm"
callback_name="gtm",
settings_name="gpt_conversations"
),
BaseFeature(
name="Генерация изображений 📸",
description="<b>Генерация изображений </b>🤖"
"\nНаходится в разработке, планируется в будущем. Следите за обновлениями 😘",
callback_name="gpm"
callback_name="gpm",
settings_name="123"
)
]
}
# List of gpt categories, avaible in bozenka now
gpt_categories = [
"Gpt4Free",
"Gpt4All",
]
def generate_list_of_features(category: str) -> list[BaseFeature]:
@ -130,45 +152,6 @@ def generate_list_of_features(category: str) -> list[BaseFeature]:
return list_of_features[category]
def generate_gpt4free_providers():
"""
Generates list of g4f providers
:return:
"""
provider = {}
for prov in g4f.Provider.__all__:
if prov != "BaseProvider" and prov != "AsyncProvider" and prov != "RetryProvider":
exec(f"provider['{prov}']=g4f.Provider.{prov}")
result = {}
for check in provider:
if provider[check].working:
result[check] = provider[check]
return result
def generate_gpt4free_models():
"""
Generates list of g4f models
:return:
"""
models = {}
for model, model_name in g4f.models.ModelUtils.convert.items(), g4f.models.ModelUtils.convert.keys():
if type(model.best_provider) is RetryProvider:
for pr in model.best_provider.providers:
if pr in models:
models[nameof(pr)].append(model_name)
else:
models[nameof(pr)] = [model_name]
else:
if nameof(model.best_provider) in models:
models[nameof(model.best_provider)].append(model_name)
else:
models[nameof(model.best_provider)] = [model_name]
return models
en_cmds = {}
ru_cmds = {
# /info command translation
"info": "Информация об чате с названием nameofchathere"
@ -278,5 +261,4 @@ list_of_commands = {
translations = {
"ru": ru_cmds,
"en": en_cmds
}

View File

@ -205,6 +205,7 @@ class SolutionSimpler:
msg=f"Muted user @{msg.reply_to_message.from_user.full_name} id={msg.reply_to_message.from_user.id}",
level=logging.INFO)
user = await get_user(user_id=msg.from_user.id, chat_id=msg.chat.id, session=session)
user
if not user:
new_user = Users(
user_id=msg.from_user.id,
@ -311,8 +312,9 @@ class SolutionSimpler:
:param msg: Message telegram object
:param session: Object of telegram command
"""
print("123")
chat_data = await get_settings(msg.chat.id, session)
print(chat_data)
if not chat_data:
new_chat_data = ChatSettings(chat_id=msg.chat.id)
async with session() as session: