Big refactor updates, fixes & fixes

- Big code refactor
- Gpt4All fixes
- Some changes
- Added /start basic functions
This commit is contained in:
kittyneverdies 2023-12-18 17:43:41 +03:00
parent 0d08c1a7c5
commit 1bebfe5ba4
70 changed files with 518 additions and 227 deletions

View File

@ -4,7 +4,7 @@ import logging
import g4f
from bozenka.instances.telegram import launch_telegram_instance
from bozenka.db import generate_url, get_async_engine, get_sessions_maker
from bozenka.database import generate_url, get_async_engine, get_sessions_maker
def launch_instances() -> None:

View File

@ -0,0 +1,5 @@
__all__ = ["MainModel", "get_async_engine", "get_sessions_maker", "Users", "get_user", "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

View File

@ -7,27 +7,14 @@ from sqlalchemy.orm import sessionmaker
def get_async_engine(url: URL | str) -> AsyncEngine:
"""
Creates AsyncEngine
Creates AsyncEngine, it needs to create async
session maker by get_sessions_maker()
:param url:
:return:
"""
return create_async_engine(url=url, echo=True, pool_pre_ping=True)
@DeprecationWarning
async def schemas(engine: AsyncEngine, metadata) -> None:
"""
Commiting all changes & create databases
:param engine:
:param metadata:
:return:
"""
"""
async with engine.begin() as connect:
await connect.run_sync(metadata.create_all)
"""
def get_sessions_maker(engine: AsyncEngine) -> async_sessionmaker:
"""
Creates SessionMaker (Async!)

View File

@ -7,7 +7,7 @@ from sqlalchemy.ext.asyncio import async_engine_from_config
from alembic import context
import bozenka.db.main
import bozenka.database.main
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.

View File

@ -3,7 +3,7 @@ from typing import Tuple, Any
from sqlalchemy import Column, Integer, VARCHAR, Boolean, Text, select, BigInteger, Row
from sqlalchemy.ext.asyncio import async_sessionmaker
from sqlalchemy.orm import sessionmaker
from bozenka.db.main import MainModel
from bozenka.database.main import MainModel
class Users(MainModel):
@ -56,17 +56,16 @@ class ChatSettings(MainModel):
# openai_token = Column(Text)
async def get_settings(user_id: int, chat_id: int, session: async_sessionmaker):
async def get_settings(chat_id: int, session: async_sessionmaker):
"""
Return settings with sessionmaker by chat_id
:param user_id:
:param chat_id:
:param session:
:param chat_id: id of telegram chat
:param session: sessionmaker from dispatcher
:return:
"""
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(ChatSettings).where(ChatSettings.chat_id == chat_id))).one_or_none()
async def get_user(user_id: int, chat_id: int, session: async_sessionmaker) -> Row[tuple[Any, ...] | Any] | None:

View File

@ -1,5 +0,0 @@
__all__ = ["MainModel", "get_async_engine", "get_sessions_maker", "schemas", "Users", "get_user", "generate_url"]
from .main import MainModel
from .engine import get_async_engine, get_sessions_maker, schemas, generate_url
from bozenka.db.tables.telegram import Users, get_user

View File

@ -0,0 +1,6 @@
# List of generative categories, what we support
text_generative_categories = [
"Gpt4Free",
"Gpt4All",
]

View File

@ -0,0 +1,12 @@
import os
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:
:return:
"""
return os.path.exists("models\\" + model_filename)

View File

@ -0,0 +1,40 @@
import g4f
from g4f.Provider import RetryProvider
from varname import nameof
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

View File

@ -5,7 +5,7 @@ from aiogram import Dispatcher, Bot
from aiogram.types import BotCommand
from sqlalchemy.ext.asyncio import async_sessionmaker
from bozenka.instances.telegram.cmds import register_handlers
from bozenka.instances.telegram.handlers import register_handlers
from bozenka.instances.telegram.utils.simpler import list_of_commands

View File

@ -1,45 +0,0 @@
from aiogram.types import Message as Message
from bozenka.instances.telegram.utils.keyboards import start_keyboard
async def start_cmd(msg: Message):
"""
/start command function
:param msg:
:return:
"""
await msg.answer(
'Привет, пользователь, я - Бозенька 👋\n'
'Я мультизадачный телеграм бот, разрабатываемый Bozo Developement\n'
f'Выберите, что будете делать, {msg.from_user.mention_html()}',
reply_markup=start_keyboard.as_markup()
)
async def features_list(msg: Message):
"""
Shows features list from reply keyboard
:param msg:
:return:
"""
await msg.answer("List will be soon")
async def about_devs(msg: Message):
"""
Shows info about devs from reply keyboard
:param msg:
:return:
"""
await msg.answer("Info about developers will be added soon")
async def add_to_chat(msg: Message):
"""
Sends link for adding bot into chat
:param msg:
:return:
"""
await msg.answer("Will be soon")

View File

@ -2,11 +2,11 @@ import logging
from aiogram import Dispatcher
from bozenka.instances.telegram.cmds.admin import register_admin_cmd
from bozenka.instances.telegram.queries import register_queries
from bozenka.instances.telegram.cmds.dev import register_dev_cmd
from bozenka.instances.telegram.cmds.main import register_main_cmd
from bozenka.instances.telegram.cmds.user import register_user_cmd
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

View File

@ -5,10 +5,11 @@ import logging
from aiogram import Router, F
from aiogram.filters import Command
from bozenka.instances.telegram.cmds.admin.mutes import mute, unmute
from bozenka.instances.telegram.cmds.admin.pins import pin, unpin, unpin_all
from bozenka.instances.telegram.cmds.admin.topics import *
from bozenka.instances.telegram.cmds.admin.bans import ban, unban
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.utils.filters import (
IsAdminFilter,
UserHasPermissions, BotHasPermissions
@ -23,6 +24,13 @@ def register_admin_cmd(router: Router) -> None:
:return:
"""
logging.log(msg="Registering administrator commands", level=logging.INFO)
# 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"]))
# Ban / Unban commands handler
router.message.register(ban, Command(commands="ban"),
IsAdminFilter(True), F.reply_to_message.text)

View File

@ -0,0 +1,70 @@
from aiogram.types import Message
from bozenka.instances.telegram.utils.keyboards import delete_keyboard
async def help_ban(msg: Message):
"""
Shows help message for /ban
:param msg:
"""
await msg.answer("Использование:\n"
"<pre>/ban [время блокировки] [причина блокировки]</pre>\n"
"Ответьте на сообщение, чтобы заблокировать пользователя",
reply_markup=delete_keyboard(msg.from_user.id))
async def help_unban(msg: Message):
"""
Shows help message for /unban
:param msg:
"""
await msg.answer("Использование:\n"
"<pre>/unban</pre>\n"
"Ответьте на сообщение, чтобы разблокировать пользователя",
reply_markup=delete_keyboard(msg.from_user.id))
async def help_mute(msg: Message):
"""
Shows help message for /mute
:param msg:
"""
await msg.answer("Использование:\n"
"<pre>/mute [время мута] [причина мута]</pre>\n"
"Ответьте на сообщение, чтобы замутить пользователя",
reply_markup=delete_keyboard(msg.from_user.id))
async def help_unmute(msg: Message):
"""
Shows help message for /unmute
:param msg:
"""
await msg.answer("Использование:\n"
"<pre>/unmute</pre>\n"
"Ответьте на сообщение, чтобы замутить пользователя",
reply_markup=delete_keyboard(msg.from_user.id))
async def help_pin(msg: Message):
"""
Shows help message for /mute
:param msg:
"""
await msg.answer("Использование:\n"
"<pre>/pin</pre>\n"
"Ответьте на сообщение, чтобы закрепить сообщение",
reply_markup=delete_keyboard(msg.from_user.id))
async def help_unpin(msg: Message):
"""
Shows help message for /mute
:param msg:
"""
await msg.answer("Использование:\n"
"<pre>/unpin</pre>\n"
"Ответьте на сообщение, чтобы открепить сообщение",
reply_markup=delete_keyboard(msg.from_user.id))

View File

@ -6,10 +6,10 @@ from aiogram.enums import ContentType
from aiogram.filters import Command
from aiogram import Router, F
from bozenka.instances.telegram.cmds.user.about import about
from bozenka.instances.telegram.cmds.user.invite import invite
from bozenka.instances.telegram.cmds.user.info import chat_info
from bozenka.instances.telegram.cmds.user.welcome import *
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:

View File

@ -4,8 +4,8 @@ import logging
from aiogram.filters import Command
from bozenka.instances.telegram.cmds.dev.hello import hi, testing
from bozenka.instances.telegram.cmds.dev.ai import *
from bozenka.instances.telegram.handlers.dev.hello import hi, testing
from bozenka.instances.telegram.handlers.dev.ai import *
from bozenka.instances.telegram.utils.simpler import AnsweringGPT4Free, AnsweringGpt4All
from aiogram import Router
@ -20,7 +20,7 @@ def register_dev_cmd(router: Router) -> None:
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_gpt_cmd, Command(commands=["conversation"]))
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"]))

View File

@ -5,6 +5,8 @@ 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
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, \
AnsweringGPT4Free
@ -12,7 +14,8 @@ from bozenka.instances.telegram.utils.simpler import generate_gpt4free_providers
async def already_answering(msg: Message, state: FSMContext):
"""
Giving response, if we already responsing it
Giving response, if answering user now,
but he still asks something
:param msg:
:param state:
:return:
@ -21,7 +24,7 @@ async def already_answering(msg: Message, state: FSMContext):
reply_markup=delete_keyboard(admin_id=msg.from_user.id))
async def start_gpt_cmd(msg: Message, state: FSMContext):
async def start_dialog_cmd(msg: Message, state: FSMContext):
"""
/conversation command handler, start
:param msg:
@ -37,7 +40,8 @@ async def start_gpt_cmd(msg: Message, state: FSMContext):
async def cancel_answering(msg: Message, state: FSMContext):
"""
Canceling dialog with ChatGPT
Canceling dialog with generative model
Works on command /cancel
:param msg:
:param state:
:return:
@ -67,15 +71,14 @@ async def g4a_generate_answer(msg: Message, state: FSMContext):
"Если что-то пойдет не так, мы вам сообщим 👌",
reply_markup=response_keyboard(user_id=msg.from_user.id))
if not os.path.exists(
"D:\\Files\\Documents\\GitHub\\Bozenka\\bozenka\\gpt\\gpt4all\\models\\" + models[info["set_model"]][
"filename"]):
main_msg = await main_msg.edit_text(main_msg + "\nПодождите пожалуста, мы скачиваем модель...")
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="D:\\Files\\Documents\\GitHub\\Bozenka\\bozenka\\gpt\\gpt4all\\models\\",
model_path="/bozenka/generative\\gpt4all\\models\\",
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"]

View File

@ -4,9 +4,10 @@ import logging
from aiogram import Router, F
from aiogram.enums import ContentType
from aiogram.filters import Command
from aiogram.filters import Command, CommandStart
from bozenka.instances.telegram.cmds.main.setup import after_adding, setup_cmd
from bozenka.instances.telegram.handlers.main.setup import *
from bozenka.instances.telegram.handlers.main.start import *
def register_main_cmd(router: Router) -> None:
@ -18,6 +19,10 @@ def register_main_cmd(router: Router) -> None:
"""
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"]))
# After adding to chat handler

View File

@ -1,5 +1,5 @@
from aiogram.types import Message as Message
from bozenka.instances.telegram.utils.simpler import ru_cmds
from bozenka.instances.telegram.utils.simpler import SolutionSimpler
from bozenka.instances.telegram.utils.keyboards import setup_keyboard
@ -22,5 +22,5 @@ async def after_adding(msg: Message):
"""
await msg.answer("Здраствуйте администраторы чата 👋\n"
"Я - <b>бозенька</b>, мультифункциональный бот, разрабатываемый Bozo Developement\n"
"Выдайте мне <b>полные права администратора</b> для моей полной работы."
"Выдайте мне <b>полные права администратора</b> для моей полной работы, если не выдали."
"Чтобы настроить функционал, используйте /setup или кнопку под сообщением")

View File

@ -0,0 +1,61 @@
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
async def start_cmd(msg: Message):
"""
/start command function
:param msg:
:return:
"""
await msg.answer(
'Привет, пользователь, я - Бозенька 👋\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)
)
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

@ -2,14 +2,16 @@ __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.utils.callbacks_factory import *
from bozenka.instances.telegram.queries.ban import *
from bozenka.instances.telegram.queries.pins import *
from bozenka.instances.telegram.queries.threads import *
from bozenka.instances.telegram.queries.delete import *
from bozenka.instances.telegram.queries.revoke import *
from bozenka.instances.telegram.queries.gpt import *
from bozenka.instances.telegram.queries.setup 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.setup import *
def register_queries(router: Router) -> None:
@ -79,3 +81,12 @@ def register_queries(router: Router) -> None:
# Menu of feature to enable or disable
router.callback_query.register(inline_feature, SetupFeature.filter())
# /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())

View File

@ -123,7 +123,7 @@ async def inline_g4f_ready(call: types.CallbackQuery, callback_data: Gpt4freeRes
await call.message.edit_text("Удача ✅\n"
"Вы теперь можете спокойно вести диалог 🤖\n"
f"Вы выбрали модель <pre>{callback_data.model}</pre>👾, от провайдера <pre>{callback_data.provider}</pre>👨‍💻\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("Вы теперь можете спокойно вести диалог 🤖")
@ -192,7 +192,7 @@ async def inline_g4a_select_model(call: types.CallbackQuery, callback_data: Gpt4
await call.message.edit_text("Удача ✅\n"
"Вы теперь можете спокойно вести диалог 🤖\n"
f"Вы выбрали модель <pre>{models[callback_data.model_index]['name']}</pre>👾 от Gpt4All\n"
f"Вы выбрали модель <b>{models[callback_data.model_index]['name']}</b>👾 от Gpt4All\n"
"Чтобы прекратить общение, используйте /cancel ",
reply_markup=delete_keyboard(admin_id=callback_data.user_id))

View File

@ -0,0 +1,49 @@
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
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))

View File

@ -1,6 +1,5 @@
from .admin import *
from .delete import DeleteCallbackData
from .revoke import RevokeCallbackData
from .gpt_selector import *
from .setup import *
from .threads import *
from .start import *

View File

@ -65,3 +65,13 @@ class UnpinMsg(CallbackData, prefix='up'):
"""
user_id: int
msg_id: int
# Link revoke
class RevokeCallbackData(CallbackData, prefix="mute"):
"""
Callback with information to revoke invite link
"""
admin_id: int
link: str

View File

@ -1,6 +0,0 @@
from aiogram.filters.callback_data import CallbackData
class RevokeCallbackData(CallbackData, prefix="mute"):
admin_id: int
link: str

View File

@ -0,0 +1,38 @@
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

View File

@ -1,3 +0,0 @@
from aiogram.filters.callback_data import CallbackData

View File

@ -0,0 +1,8 @@
from aiogram.filters import Filter
class IsChatType(Filter):
"""
"""

View File

@ -1,2 +1,2 @@
from .inline import *
from .reply import start_keyboard
from .reply import start_keyboard_builder

View File

@ -7,7 +7,7 @@ from aiogram.utils.keyboard import InlineKeyboardBuilder
from gpt4all import GPT4All
from bozenka.instances.telegram.utils.callbacks_factory import *
from bozenka.instances.telegram.utils.simpler import gpt_categories, gpt4free_providers, generate_gpt4free_providers, \
from bozenka.instances.telegram.utils.simpler import gpt_categories, generate_gpt4free_models, generate_gpt4free_providers, \
generate_list_of_features
"""
@ -16,6 +16,57 @@ Right now only on Russian language, multi-language planning soon.
"""
# 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())]])
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())],
[InlineKeyboardButton(text="🔙 Назад к функциям",
callback_data=HelpBackCategory(back_to_category=category).pack())]
])
return kb
# Setup related keyboards
def setup_keyboard() -> InlineKeyboardMarkup:
"""
Generate keyboard for /setup command
@ -52,8 +103,7 @@ def setup_feature_keyboard() -> InlineKeyboardMarkup:
pass
def delete_keyboard(admin_id) -> InlineKeyboardMarkup:
def delete_keyboard(admin_id: int) -> InlineKeyboardMarkup:
"""
Basic keyboard for all messages from bot.
By pressing this button, message from bot will get deleted.
@ -94,7 +144,6 @@ def items_list_generator(page: int, list_of_items, count_of_items: int) -> list[
if count not in required_items:
continue
items.append(item)
print(items)
return items
@ -156,18 +205,22 @@ def gpt4free_models_keyboard(user_id: int, provider, page: int) -> InlineKeyboar
:param page:
"""
builder = InlineKeyboardBuilder()
if provider in gpt4free_providers:
names = items_list_generator(page, gpt4free_providers[provider], 4)
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(gpt4free_providers[provider]) // 4 - 1 if page - 1 == -1 else page - 1,
0 if page + 1 >= len(gpt4free_providers[provider]) // 4 else page + 1]
if len(gpt4free_providers[provider]) > 4:
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(gpt4free_providers[provider]) // 4 if page == 0 else "1"),
InlineKeyboardButton(text=str(len(models[provider]) // 4 if page == 0 else "1"),
callback_data=Gpt4FreeModelPage(
page=str(len(gpt4free_providers[provider]) // 4 - 1 if page == 0 else "1"),
page=str(len(models[provider]) // 4 - 1 if page == 0 else "1"),
user_id=user_id,).pack(),
),
# Page back button
@ -178,13 +231,12 @@ def gpt4free_models_keyboard(user_id: int, provider, page: int) -> InlineKeyboar
# 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(gpt4free_providers[provider]) // 4 if page != 0 else "1"),
InlineKeyboardButton(text=str(len(models[provider]) // 4 if page != 0 else "1"),
callback_data=Gpt4FreeModelPage(
page=str(len(gpt4free_providers[provider]) // 4 - 1) if page != 0 else "1",
page=str(len(models[provider]) // 4 - 1) if page != 0 else "1",
user_id=user_id,
provider=provider).pack(),))
else:
providers = generate_gpt4free_providers()
if providers[provider].supports_gpt_4:
builder.row(InlineKeyboardButton(text="gpt 4",
callback_data=Gpt4freeResult(user_id=str(user_id),

View File

@ -2,10 +2,10 @@
from aiogram.types import KeyboardButton
from aiogram.utils.keyboard import ReplyKeyboardBuilder
start_keyboard = ReplyKeyboardBuilder()
start_keyboard.row(
start_keyboard_builder = ReplyKeyboardBuilder()
start_keyboard_builder.row(
KeyboardButton(text="Добавить в чат 🔌"),
KeyboardButton(text="Функционал 🔨")
)
start_keyboard.adjust(1,2)
start_keyboard.add(KeyboardButton(text="О разработчиках "))
start_keyboard_builder.adjust(1, 2)
start_keyboard_builder.add(KeyboardButton(text="О разработчиках "))

View File

@ -8,7 +8,7 @@ from aiogram import Router, Dispatcher
def register_middlewares(dp: Dispatcher):
"""
Registering all middlewares of bot.
:param router:
:param dp:
:return:
"""
logging.log(msg=f"Registering middlewares of bot", level=logging.INFO)

View File

@ -0,0 +1 @@
# Will be added soon

View File

@ -1,5 +1,5 @@
from .solution_simpler import SolutionSimpler
from .texts import *
from .lists_of_content import *
from .states import *

View File

@ -1,7 +0,0 @@
def registrate_commands():
"""
Registrate commands for telegram automatic tips
:return:
"""
pass

View File

@ -2,6 +2,8 @@ from typing import List
import g4f
from g4f import Provider
from g4f.Provider import RetryProvider
from varname import nameof
class BaseFeature:
@ -15,58 +17,7 @@ class BaseFeature:
self.callback_name = callback_name
gpt4free_providers = {
"AItianhu": ["gpt-3.5-turbo", "gpt-4"],
"Acytoo": ["gpt-3.5-turbo"],
"AiService": ["gpt-3.5-turbo"],
"Aichat": ["gpt-3.5-turbo"],
"Ails": ["gpt-3.5-turbo"],
"Bard": ["palm"],
"Bing": ["gpt-4"],
"ChatgptAi": ["gpt-4"],
"ChatgptLogin": ["gpt-3.5-turbo"],
"DeepAi": ["gpt-3.5-turbo"],
"DfeHub": ["gpt-3.5-turbo"],
"EasyChat": ["gpt-3.5-turbo"],
"Forefront": ["gpt-3.5-turbo"],
"GetGpt": ["gpt-3.5-turbo"],
"H2o": ["falcon-40b", "falcon-7b", "llama-13b"],
"Liaobots": ["gpt-3.5-turbo", "gpt-4"],
"Lockchat": ["gpt-3.5-turbo", "gpt-4"],
"Opchatgpts": ["gpt-3.5-turbo"],
"Raycast": ["gpt-3.5-turbo", "gpt-4"],
"Theb": ["gpt-3.5-turbo"],
# Vercel, biggest part of list
"Vercel": [
"gpt-3.5-turbo",
"claude-instant-v1",
"claude-v1",
"claude-v2",
"command-light-nightly",
"command-nightly",
"gpt-neox-20b",
"oasst-sft-1-pythia-12b",
"oasst-sft-4-pythia-12b-epoch-3.5",
"santacoder",
"bloom",
"flan-t5-xxl",
"code-davinci-002",
"gpt-3.5-turbo-16k",
"gpt-3.5-turbo-16k-0613",
"gpt-4-0613",
"text-ada-001",
"text-babbage-001",
"text-curie-001",
"text-davinci-002",
"text-davinci-003",
"llama13b-v2-chat",
"llama7b-v2-chat"
],
"Wewordle": ["gpt-3.5-turbo"],
"You": ["gpt-3.5-turbo"],
"Yqcloud": ["gpt-3.5-turbo"]
}
# List of features, avaible in bozenka
list_of_features = {
"Admins": [
BaseFeature(
@ -82,15 +33,15 @@ list_of_features = {
BaseFeature(
name="Модерация чата 🕵️",
description="<b>Модерация чата</b>🕵️\nДанная настройка включает следущие комманды:"
"\n/ban [время блокировки] [причина блокировки] - блокировка пользователя"
"\n<pre>/ban [время блокировки] [причина блокировки] - блокировка пользователя"
"\n/unban - разблокировка пользователя\n"
"/mute [время мута] [причина мута] - мут пользователя "
"/unmute - Размут пользователя\n"
"/mute [время мута] [причина мута] - мут пользователя\n"
"/unmute - Размут пользователя</pre>\n"
"Время обозначается как:"
"1h - один час, "
"<pre>1h - один час, "
"1d - один день, "
"1m - одна минута, "
"1s - одна секунда\n"
"1s - одна секунда</pre>\n"
"Для того, "
"чтобы выполнить одну из комманд по отношению к пользователю, "
"ответьте на сообщение пользователя и используйте команду\n"
@ -100,12 +51,12 @@ list_of_features = {
BaseFeature(
name="Работа с Форумом 💬",
description="<b>Работа с Форумом</b>💬\nДанная настройка включает следущие комманды:\n"
"/open - открывают тему форума\n"
"<pre>/open - открывают тему форума\n"
"/close - закрывают тему форума\n"
"/open_general - открывают основную тему форума\n"
"/close_general - закрывает основную тему форума\n"
"/hide_general - прячет основную тему форума\n"
"/show_general - показывает основную тему форума\n"
"/show_general - показывает основную тему форума</pre>\n"
"Для исполнения <b>требует соответсвующих прав от пользователя и их наличие у бота. Также должен быть"
"включен форум</b>",
callback_name="topics"
@ -143,8 +94,11 @@ list_of_features = {
BaseFeature(
name="ИИ ЧатБот 🤖",
description="<b>ИИ ЧатБот </b>🤖"
"Есть поддержка провайдеров из Gpt4Free\n"
"Есть поддержка моделей Gpt4All"
"\nЕсть поддержка:\n"
"- Моделей Gpt4All\n"
"- Провайдеров Gpt4Free и моделей\n"
"Для использования:\n"
"<pre>/conversations</pre>"
"\nНаходится в разработке, планируется в будущем. Следите за обновлениями 😘",
callback_name="gtm"
),
@ -158,6 +112,13 @@ list_of_features = {
}
# List of gpt categories, avaible in bozenka now
gpt_categories = [
"Gpt4Free",
"Gpt4All",
]
def generate_list_of_features(category: str) -> list[BaseFeature]:
"""
@ -176,7 +137,7 @@ def generate_gpt4free_providers():
"""
provider = {}
for prov in g4f.Provider.__all__:
if prov != "BaseProvider":
if prov != "BaseProvider" and prov != "AsyncProvider" and prov != "RetryProvider":
exec(f"provider['{prov}']=g4f.Provider.{prov}")
result = {}
for check in provider:
@ -185,13 +146,27 @@ def generate_gpt4free_providers():
return result
gpt_categories = [
"Gpt4Free",
"Gpt4All",
"StableLM",
"H20Gpt",
"RWKV"
]
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 = {

View File

@ -12,10 +12,8 @@ from aiogram.enums import ChatMemberStatus
from aiogram.types import ChatPermissions, ChatAdministratorRights
from sqlalchemy.ext.asyncio import async_sessionmaker
from bozenka.db import get_user, Users
from bozenka.database import get_user, Users
from bozenka.database.tables.telegram import get_settings, ChatSettings
def count_time(counted_time: str) -> int:
@ -44,8 +42,10 @@ class SolutionSimpler:
Making feature 'result in your direct message' easy and cleaner to complete.
Including logging and debugging.
"""
@staticmethod
async def ban_user(msg: types.Message, cmd: CommandObject, session: async_sessionmaker) -> dict[str, None | str | bool]:
async def ban_user(msg: types.Message, cmd: CommandObject, session: async_sessionmaker) -> dict[
str, None | str | bool]:
"""
Bans user, returns config, by config you can send special message.
:param msg:
@ -261,3 +261,19 @@ class SolutionSimpler:
msg=f"Created invite into chat by @{msg.from_user.full_name} chat_id={msg.chat.id}",
level=logging.INFO)
return link.invite_link
@staticmethod
async def auto_settings(msg: types.Message, session: async_sessionmaker):
"""
Creating setting automaticly
:param msg:
:param session:
"""
chat_data = await get_settings(msg.chat.id, session)
if not chat_data:
new_chat_data = ChatSettings(chat_id=msg.chat.id)
async with session() as session:
async with session.begin():
await session.merge(new_chat_data)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 327 KiB

After

Width:  |  Height:  |  Size: 398 KiB

View File

@ -1,6 +1,7 @@
SQLAlchemy~=2.0.20
alembic~=1.12.0
nextcord~=2.6.0
g4f~=0.1.9.0
gpt4all~=1.0.8
gpt4all~=2.0.2
aiogram~=3.2.0
varname==0.12.2
g4f~=0.1.9.1

3
run.py
View File

@ -1,10 +1,11 @@
import os
import logging
import gpt4all
from bozenka import launch_instances
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
os.system("pip install -r requirements.txt")
logging.log(msg="Starting bozenka, lets go!", level=logging.INFO)
try:
launch_instances()