2024-10-09 20:50:46 +00:00
import csv
from aiogram . fsm . context import FSMContext
from bot . handlers . user . states import ChooseModelState , SendMessageState
import time
from db . db import *
from aiogram import Router , types , F
2024-10-06 13:29:07 +00:00
from aiogram . filters import CommandStart , Command
2024-10-09 20:50:46 +00:00
from aiogram . types import LabeledPrice , PreCheckoutQuery , InlineKeyboardButton , FSInputFile
from aiogram . utils . keyboard import InlineKeyboardBuilder
from db . db import user_exists , add_user_to_db , set_curren_model , get_temp_prompts
from bot . handlers . user . model_processing import PayCallBack , BuyCallBack , ChooseCallBack
2024-10-05 14:35:26 +00:00
from bot . handlers . user . page_processing import get_page_content
from bot . kbs . inline import PageCallBack
2024-10-09 20:50:46 +00:00
from config import shop_api_token , admins
from bot . utils . openai_tasks import get_model_suggestion_from_openai , get_answer_to_question
2024-10-05 14:35:26 +00:00
user = Router ( )
@user.message ( CommandStart ( ) )
2024-10-09 20:50:46 +00:00
async def start ( message : types . Message , state : FSMContext ) :
await state . clear ( )
# TODO
isAdded = await user_exists ( message . from_user . id )
if not isAdded :
# Извлекаем информацию о пользователе
first_name = message . from_user . first_name or " "
last_name = message . from_user . last_name or " "
user_name = message . from_user . username or " "
# Добавляем пользователя в базу данных
await add_user_to_db (
user_id = message . from_user . id ,
first_name = first_name ,
last_name = last_name ,
user_name = user_name
)
text , reply_markup = await get_page_content ( page = 0 , name = " main " , user_id = message . from_user . id )
2024-10-05 14:35:26 +00:00
await message . answer ( text , reply_markup = reply_markup )
@user.callback_query ( PageCallBack . filter ( ) )
2024-10-09 20:50:46 +00:00
async def user_pages ( callback : types . CallbackQuery , callback_data : PageCallBack , state : FSMContext ) :
await state . clear ( )
2024-10-05 14:35:26 +00:00
text , reply_markup = await get_page_content (
page = callback_data . page ,
name = callback_data . page_name ,
2024-10-09 20:50:46 +00:00
user_id = callback . from_user . id ,
2024-10-05 14:35:26 +00:00
)
await callback . message . edit_text ( text , reply_markup = reply_markup )
await callback . answer ( )
2024-10-06 13:29:07 +00:00
2024-10-09 20:50:46 +00:00
@user.callback_query ( ChooseCallBack . filter ( ) )
async def choose ( callback : types . CallbackQuery , callback_data : ChooseCallBack ) :
await set_curren_model ( user_id = callback . from_user . id , name_of_model = callback_data . name )
text , reply_markup = await get_page_content (
page = 2 ,
user_id = callback . from_user . id ,
name = ' tarif ' ,
)
await callback . message . edit_text ( text , reply_markup = reply_markup )
await callback . answer ( )
@user.message ( Command ( commands = [ ' tarif ' ] ) )
async def tarif ( message : types . Message ) :
# Получаем текст и клавиатуру для страницы тарифа
text , reply_markup = await get_page_content (
page = 2 ,
user_id = message . from_user . id , # Используем message.from_user.id вместо callback
name = ' tarif ' ,
)
# Отправляем новое сообщение с текстом и кнопками
await message . answer ( text , reply_markup = reply_markup )
@user.callback_query ( BuyCallBack . filter ( ) )
async def buy ( callback : types . CallbackQuery , callback_data : BuyCallBack ) :
kbds = InlineKeyboardBuilder ( )
buttons = [
InlineKeyboardButton ( text = " Купить " , callback_data = PayCallBack (
name = callback_data . name ,
option_of_model = callback_data . option_of_model ,
tokens = callback_data . tokens ,
amount = callback_data . amount
) . pack ( ) ) ,
InlineKeyboardButton ( text = " ⬅️Назад " , callback_data = PageCallBack ( page = 2 , page_name = " tarif " ) . pack ( ) ) ,
]
for button in buttons :
kbds . add ( button )
await callback . message . edit_text (
text = f " Модель: { callback_data . name } \n Тариф: { callback_data . option_of_model } \n Кол-ов запросов: { callback_data . tokens } \n Стоимость: { callback_data . amount } RUB " ,
reply_markup = kbds . adjust ( * ( 1 , ) ) . as_markup ( )
)
await callback . answer ( )
@user.callback_query ( PayCallBack . filter ( ) )
async def pay ( callback : types . CallbackQuery , callback_data : PayCallBack ) :
temp = await callback . message . bot . send_invoice (
2024-10-06 13:29:07 +00:00
chat_id = callback . from_user . id ,
description = f ' { callback_data . tokens } токенов за { callback_data . amount } RUB для модели { callback_data . name } ' ,
title = f ' { callback_data . option_of_model } подписка на { callback_data . name } ' ,
2024-10-09 20:50:46 +00:00
payload = f ' sub_ { callback_data . name } _ { callback . from_user . id } _ { callback_data . tokens } ' ,
# Добавляем id пользователя и количество токенов в payload
2024-10-06 13:29:07 +00:00
provider_token = shop_api_token ,
start_parameter = ' test ' ,
currency = " RUB " ,
prices = [ LabeledPrice (
label = f ' Оплата токенов для { callback_data . option_of_model } ' ,
2024-10-09 20:50:46 +00:00
amount = int ( callback_data . amount ) * 100 ,
2024-10-06 13:29:07 +00:00
) ] ,
)
2024-10-09 20:50:46 +00:00
# if temp.successful_payment is None:
# await callback.bot.send_message(chat_id=callback.from_user.id,text="Something went wrong")
2024-10-06 13:29:07 +00:00
@user.pre_checkout_query ( )
2024-10-09 20:50:46 +00:00
async def process_pre_checkout_query ( pre_checkout_query : PreCheckoutQuery ) :
2024-10-06 13:29:07 +00:00
await pre_checkout_query . answer ( ok = True )
2024-10-09 20:50:46 +00:00
# time.sleep(2)
#
# await pre_checkout_query.bot.send_message(chat_id=pre_checkout_query.from_user.id, text="Спасибо, пользутесь нашим сервисом!")
#
# text, reply_markup = await get_page_content(page=0, name="main", user_id=pre_checkout_query.from_user.id)
#
# await pre_checkout_query.bot.send_message(
# chat_id=pre_checkout_query.from_user.id,
# text=text,
# reply_markup=reply_markup,
# )
@user.message ( F . successful_payment )
async def process_payment ( message : types . Message ) :
if message . successful_payment is None :
await message . bot . send_message ( chat_id = message . from_user . id , text = " Что то пошло не так " )
return
payload_data = message . successful_payment . invoice_payload . split ( ' _ ' )
if len ( payload_data ) != 4 :
return # Н е валидный payload
model_name = payload_data [ 1 ] # Имя модели
user_id = int ( payload_data [ 2 ] ) # ID пользователя
tokens = int ( payload_data [ 3 ] ) # Количество токенов
await add_tokens_to_user ( user_id , model_name , tokens )
time . sleep ( 2 )
await message . bot . send_message ( chat_id = message . from_user . id ,
text = " Спасибо, что пользуетесь нашим сервисом! " )
await message . bot . send_message ( chat_id = message . from_user . id ,
text = " Для работы с chatGPT отправьте текст с вашим вопросом и получите на него ответ) " )
@user.message ( Command ( commands = [ " failed " ] ) )
async def process_payment ( message : types . Message ) :
await message . bot . send_message ( chat_id = message . from_user . id ,
text = " Что-то пошло не так( Попробуйте еще раз! " )
text , reply_markup = await get_page_content ( page = 0 , name = " main " , user_id = message . from_user . id )
await message . bot . send_message (
chat_id = message . from_user . id ,
text = text ,
reply_markup = reply_markup ,
)
@user.callback_query ( lambda c : c . data == ' choose ' )
async def chat_test_gpt ( callback : types . CallbackQuery , state : FSMContext ) :
kbds = InlineKeyboardBuilder ( )
kbds . add ( InlineKeyboardButton (
text = " ⬅️Назад " ,
callback_data = PageCallBack (
page = 3 ,
page_name = ' more_about_models ' ,
) . pack ( )
) )
await callback . message . edit_text ( " Вы находитесь в разделе подбора модели. Опишите ваши задачи, и я помогу выбрать модель. " , reply_markup = kbds . adjust ( * ( 1 , ) ) . as_markup ( ) )
await callback . answer ( )
await state . set_state ( ChooseModelState . choosing_model )
@user.message ( ChooseModelState . choosing_model )
async def process_model_question ( message : types . Message ) :
user_id = message . from_user . id
remaining_queries = await get_temp_prompts ( user_id = user_id )
kbds = InlineKeyboardBuilder ( )
kbds . add ( InlineKeyboardButton (
text = " ⬅️Назад " ,
callback_data = PageCallBack (
page = 3 ,
page_name = ' more_about_models '
) . pack ( )
) )
if remaining_queries > 0 :
# Обрабатываем вопрос с помощью OpenAI GPT
openai_response = await get_model_suggestion_from_openai ( message . text )
# Отправляем ответ пользователю
# await message.answer(text=f"Ответ OpenAI: {openai_response}" + f"\nО с та ло с ь {remaining_queries-1} запросов.", reply_markup=kbds.adjust(*(1,)).as_markup())
# Уменьшаем количество запросов
if " Ошибка при обращении к OpenAI " not in openai_response :
await message . answer (
text = f " Ответ OpenAI: { openai_response } " + f " \n Осталось { remaining_queries - 1 } запросов. " ,
reply_markup = kbds . adjust ( * ( 1 , ) ) . as_markup ( ) )
# await decrease_test_queries(user_id)
. . .
else :
await message . answer (
text = f " Попробуйте еще раз или чуть подождите! " )
else :
await message . answer ( text = " У вас закончились доступные запросы для подбора модели." , reply_markup = kbds . adjust ( * ( 1 , ) ) . as_markup ( ) )
@user.message ( Command ( commands = [ ' export_users ' ] ) )
async def send_csv_to_admin ( message : types . Message ) :
# Генерируем CSV файл
if message . from_user . id in admins :
users = await get_all_users ( )
# Генерируем CSV файл
with open ( ' data/users.csv ' , ' w ' , newline = ' ' , encoding = ' utf-8 ' ) as csvfile :
csvwriter = csv . writer ( csvfile , delimiter = ' ; ' , quoting = csv . QUOTE_MINIMAL )
csvwriter . writerow ( [ ' ID ' , ' First Name ' , ' Last Name ' , ' Username ' ] )
for user in users :
csvwriter . writerow ( [ user . user_id , user . first_name , user . last_name , user . user_name ] )
# Отправляем CSV файл администратору
csv_file = FSInputFile ( ' data/users.csv ' ) # Обернуть путь к файлу как InputFile
await message . answer_document ( csv_file )
@user.message ( Command ( commands = [ ' send_message_to_all ' ] ) )
async def send_messages_to_users ( message : types . Message , state : FSMContext ) :
if message . from_user . id in admins :
# Устанавливаем состояние, что бот ждет текст сообщения для рассылки
await state . set_state ( SendMessageState . waiting_for_message )
await message . answer ( " Введите сообщение для рассылки: " )
@user.message ( SendMessageState . waiting_for_message )
async def get_message_for_users ( msg : types . Message , state : FSMContext ) :
# Получаем текст сообщения для рассылки
text_to_send = msg . text
users = await get_all_users ( )
# Рассылаем сообщение всем пользователям
for user in users :
if user . user_id == msg . from_user . id :
continue
try :
await msg . bot . send_message ( chat_id = user . user_id , text = f ' Сообщение от админа: \n { text_to_send } ' )
except Exception as e :
# Логируем ошибки для недоступных пользователей
print ( f " Н е удалось отправить сообщение пользователю { user . user_id } : { e } " )
await msg . answer ( " Сообщение успешно отправлено всем пользователям. " )
# Очистить состояние после завершения рассылки
await state . clear ( )
@user.message ( ~ Command ( commands = [ " export_users " , ' send_message_to_all ' ] ) ) # Игнорируем команды
async def chatgpt_chatting ( message : types . Message ) :
user_id = message . from_user . id
db_model = await get_current_model ( user_id )
kbds = InlineKeyboardBuilder ( )
kbds . add ( InlineKeyboardButton (
text = " Выбрать тариф " ,
callback_data = PageCallBack (
page = 2 ,
page_name = ' tarif '
) . pack ( ) ) )
kbds . add ( InlineKeyboardButton (
text = " ⬅️На главную " ,
callback_data = PageCallBack (
page = 0 ,
page_name = ' main '
) . pack ( )
) )
if db_model is None :
await message . bot . send_message ( chat_id = message . from_user . id , text = " У вас еще не выбрана модель" , reply_markup = kbds . adjust ( * ( 1 , ) ) . as_markup ( ) )
models = {
' 1o ' : " o1-preview " ,
' 1o mini ' : " o1-mini " ,
' 4o ' : " gpt-4o " ,
' 4o mini ' : " gpt-4o-mini "
}
current_model = models [ db_model ]
remaining_queries = await get_current_model_tokens ( user_id = user_id , name_of_model = db_model )
if remaining_queries > 0 :
openai_response = await get_answer_to_question ( message . text , current_model )
# Уменьшаем количество запросов
if " Ошибка при обращении к OpenAI " not in openai_response :
await decrease_current_model_tokens ( user_id , name_of_model = db_model )
await message . answer ( text = f " Ответ OpenAI: { openai_response } " )
await message . answer ( text = f " Модель: { current_model } \n Осталось { remaining_queries - 1 } запросов. " ,
reply_markup = kbds . adjust ( * ( 1 , ) ) . as_markup ( ) )
else :
await message . answer (
text = f " { openai_response } " )
await message . answer (
text = f " Попробуйте еще раз или вы можете выбрать другую доступную для вас модель! " )
else :
await message . answer ( text = f " У вас закончились доступные запросы для модели { current_model } . Купите новые токены или выберете другую модель " ,
reply_markup = kbds . adjust ( * ( 1 , ) ) . as_markup ( ) )
2024-10-06 13:29:07 +00:00