From 14d13fd44468e66067434e8a855f57fb5cb65132 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 23 Sep 2024 16:35:46 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- auth.py | 2 +- handlers/__pycache__/balance.cpython-310.pyc | Bin 555 -> 555 bytes handlers/__pycache__/keys.cpython-310.pyc | Bin 9040 -> 9019 bytes handlers/__pycache__/pay.cpython-310.pyc | Bin 8628 -> 8628 bytes handlers/__pycache__/profile.cpython-310.pyc | Bin 2355 -> 2347 bytes handlers/__pycache__/start.cpython-310.pyc | Bin 5250 -> 4878 bytes handlers/profile.py | 29 +++-- handlers/solo_pic.png | Bin 0 -> 1740 bytes handlers/start.py | 129 ++++++++----------- key_management.py | 62 +++++---- 10 files changed, 111 insertions(+), 111 deletions(-) create mode 100644 handlers/solo_pic.png diff --git a/auth.py b/auth.py index b1740a8b..20960890 100644 --- a/auth.py +++ b/auth.py @@ -2,7 +2,7 @@ import json import requests -from config import GET_INBOUNDS_URL, API_URL +from config import API_URL, GET_INBOUNDS_URL session = None diff --git a/handlers/__pycache__/balance.cpython-310.pyc b/handlers/__pycache__/balance.cpython-310.pyc index 3100575b4b5ac805eb908d3f52c4bf73a76b1b54..4d200150259312613dc487303ba803fce3ebe8f0 100644 GIT binary patch delta 152 zcmZ3@vYLfEpO=@50SN4P-%aG!431(*VMt-hVa#QUV#;NXVrFDWWol-KVo7CLz?#CG z!qUR9kTHcdl{t$ojVXmKg}sHPnK6nzg)x{xlj9}G96wE_TWmr3r6s9Fw^&Om3sQ?W xwwp4_awcZx7Z>JamZaWd2Qt%(5_5}~fXa)QfyCsSj2>JZ3<8X7Ogv0ti~yrgBzyn> delta 152 zcmZ3@vYLfEpO=@50SNvceld|-GdPzqiZPcdiiwdSg&~D0hdGKlm8qE_iY1k00c#3# z3QG&aLdF!a(Brl@xQAVd)b9|g!o0k{D28T;79;-2v{f#zy~?&|8j<{N?Onrf~4R$#f7 zS{r^g7;+DG&+P|Aw+M)7UF43k(bpxKr9(aR2Iw%;AC%WH%~8_Ry5No}I+CJ!YAZUf zXdy+5bX3ubqNNlq)3M&Zw5}>Vp28JcRhw&y)>3qWPAWP<9Xi!R?j*%c)R_J$r`5oT zMZK8Cn*mF*GE(Np-fi*TSPpk$7A1Q8u+2IR;00VAha|Ha#)1-|V=-H4`I~Gz=HJ1w z?p|v)@84Oz&W~Y=zlUjl6+eP}{|nyFketYs=xZ!)ZA3c1VO#?9ZPx(E^Pc$*7W%W+ zAI(-GYaj}DBh1f}Ia?Pyqgff|WH5PHa`;nn1Pgq9tX$z5Zh1FP@hPqNWUn48tON66xyw59ME(ng3>3 zTHKQsYJ#2E3)-sCO1dV(kE_pwNmzRUUsdJK#6PWeidE!GQ`v20AtS9x9LAo%(qXM| zn|2~1ajMW%Q&}k);ZJ71iCoPyAHn3fKHo&*zvyU!;m1=DT@;Ik6R8$to~R*0VtSk5 zdgKL>)TuOy=Iz8AgSnYfVhp~#8XbRLce3&vd8=NB@lSQXFe@}Rvak&~oC6z5{KDDk E6J0XhMgRZ+ delta 964 zcmZvaJ#5oJ6vzF}A90%4B+W;gG-=Z!hDdD(7|KwjR;ns7w4er5$pS@g?%JlQUwD-u)*D>2ozyU|9f}8|9kiByEn@pm#x6E zh7|rB$G&X7J+jIx%b+M&!Qd&57?B4)a*(e&Du}u2X};!YGS)oZ*B#wA97E1^FXo$$ z>BpV8oEzRz=R#M8ac{^^I0=8)83u)@2a1y+nP*u%gcFC#bHGW0c5<5tTi8C-4#3Gv zdTxNGa9Yw4Nrwk$24^K5l{9xoyMIdO@rc9)iAM*L3%Dq0QPQyiTEb;X$M86wI8>Yx zhMH2Xd=`IhwTdD=+}|Uu$XE;7A)!@>)QuqI>n3(t8`8`|6Q~O8J(SrG$S*|p;?m01 z)%x|tT5bK>+7eI5d%;$7x87-n+w}$|nCym4*K1V~jq^Ps3loooq~7qFoUmzhAMD;M z)K#s7!1^W$8`~7IIpZ>DFZK)oo867Qg!x{<{HCR($?Thg4%J!7noS{|NvDO(3ei}l zGRmm+3Fg@i`w{H)PHh+ZE@_ZfjonV&fgScP)qqZKCjAr5iQ=>-#1bN|6HN-SxkNE? zk2J(z`R{gNwrg~_t#y&P#T>J9O?bj)(o?<1xl=Xqx3bQT3R#dX4t5k{9|{k7)~(_( zobxWr9#qS;%7-ZCHiIqd`u(~pU!uZCbs@3|em_EY!)=lN{-($> j&dzv$s;p~nJKSbZr@V|f0aHmq5>ot4LKc#&bbjJD*d*eK diff --git a/handlers/__pycache__/pay.cpython-310.pyc b/handlers/__pycache__/pay.cpython-310.pyc index 8cf0dcc0314b7f3cc24099965415699984628c85..70f5d749c396e961cdbf1faffc0d37b516a75b3f 100644 GIT binary patch delta 767 zcmZvaJxmlq6vy|?-hS`i2ls)%-N6ZgoG}%p@=KfA9C+n|Ybzx#PK@9R#kHtl8kK z`S~!I+QS;r2x7nyMqI}_NUgIJH?X13DQ0pDTinLB(gt(5i(T$vPid3++{eB;TP)yd zoaPyvQQBr%p2ImlfCqRU=atW41zyBO&?ws1a8R1ph)cW!jd;{P{8ri1*N4dfHJT}s zCxwI5KHw2rIvOHHl0DEq0LjrSqC^H2QC7r_YltB-tcZ#tMy?^sq@swbBC6ssIMzi6 z!C>UJzFuo0GEOEGb(6r7R-gPWXSh&DJ#(?$iD}d`;_VH(DNbQZe1++hzTA#Q3f-y( zt2AyrrQ3~_cBd8h(wz+w#zS3D@+8}?+av^2h|Dvhe(h>ztT z3Hz*)0XXZvs6K(q#{JPnI1@8t6L+Gmgzs75T6;ALd4y!PE?xNx*K~7}Pp`CFG2M!z zlz2ZjIA=)6lu&R9sgXwKPnS_gM$IIxxwaa~UmVG6_UvS$;c~c1#p&3j@M_yRTg!qE P*<|}D3kC4S>)PmlE#<=& delta 732 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 GVf+{RBSg#q diff --git a/handlers/__pycache__/start.cpython-310.pyc b/handlers/__pycache__/start.cpython-310.pyc index 63472a324a77a9a5aca15b29e0bfc86132ff731e..c844f7d6f4ee913bf97a75d68e89e97743f80b17 100644 GIT binary patch literal 4878 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 literal 5250 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 K0g>tJ7ykj7ua?CC diff --git a/handlers/profile.py b/handlers/profile.py index dcb421c5..954699d7 100644 --- a/handlers/profile.py +++ b/handlers/profile.py @@ -6,6 +6,7 @@ from aiogram.fsm.state import State, StatesGroup from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup from database import get_balance, get_key_count +from bot import bot # Импортируем объект bot router = Router() @@ -15,6 +16,7 @@ class ReplenishBalanceState(StatesGroup): async def process_callback_view_profile(callback_query: types.CallbackQuery, state: FSMContext): tg_id = callback_query.from_user.id + username = callback_query.from_user.full_name # Получаем имя пользователя try: # Получаем количество ключей @@ -26,38 +28,43 @@ async def process_callback_view_profile(callback_query: types.CallbackQuery, sta balance = 0 # По умолчанию 0, если баланс неизвестен profile_message = ( - f"Профиль пользователя\n\n" + f"Профиль: {username}\n\n" f"🔹 ID: {tg_id}\n" - f"🔹 Количество ключей: {key_count}\n" f"🔹 Баланс: {balance} RUB\n" - f"🔹 Дата регистрации: {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')}\n" + f"🔹 Количество ключей: {key_count}\n" ) - # Кнопки для действий в профиле - button_create_key = InlineKeyboardButton(text='Создать ключ', callback_data='create_key') - button_view_keys = InlineKeyboardButton(text='Мои ключи', callback_data='view_keys') - button_replenish_balance = InlineKeyboardButton(text='Пополнить баланс', callback_data='replenish_balance') + # Кнопки для действий в профиле с добавленными смайликами + button_create_key = InlineKeyboardButton(text='🔑 Создать ключ', callback_data='create_key') + button_view_keys = InlineKeyboardButton(text='🔐 Мои ключи', callback_data='view_keys') + button_replenish_balance = InlineKeyboardButton(text='💳 Пополнить баланс', callback_data='replenish_balance') button_back = InlineKeyboardButton(text='⬅️ Назад', callback_data='back_to_menu') # Добавляем кнопку "Назад" keyboard = InlineKeyboardMarkup(inline_keyboard=[ - [button_create_key], # Добавляем кнопку "Создать ключ" + [button_create_key], [button_view_keys], [button_replenish_balance], - [button_back] # Добавляем кнопку "Назад" в клавиатуру + [button_back] ]) except Exception as e: profile_message = f"❗️ Ошибка при получении данных профиля: {e}" keyboard = None - # Редактируем существующее сообщение, а не отправляем новое - await callback_query.message.edit_text( + # Удаляем текущее сообщение + await callback_query.message.delete() + + # Отправляем новое сообщение с профилем через bot + await bot.send_message( + chat_id=tg_id, # ID чата, куда отправляем сообщение text=profile_message, parse_mode='HTML', reply_markup=keyboard ) + await callback_query.answer() @router.callback_query(lambda c: c.data == 'view_profile') async def view_profile_handler(callback_query: types.CallbackQuery, state: FSMContext): await process_callback_view_profile(callback_query, state) + diff --git a/handlers/solo_pic.png b/handlers/solo_pic.png new file mode 100644 index 0000000000000000000000000000000000000000..484f1bdc73ce9f94c7158e394f5080da08e70381 GIT binary patch literal 1740 zcmbVNYd8}M7@kCOzm)4}QmNcFcEV6D&81U@h{~Dz{W}iW72( z6B9xXGS|7ar5yK>*kNNF=kNJ>zUO(r_j$kP`}O{K-!u<*7X?{uSpWc_;O2VKYoELJ zVIw2Gzx#cPpY78@vZI@~%>LY#2~XYETG4R7=&J;DbZiI-1;F45Q798~7zu^Kld**8 zRmqm~`%k7gZ@*|K5-KDbN5F%;aZ#xKBLKiIW!HerA)o;|yN=xqG6$POL0}6Q!~zDk zw$=ae5CD)q;dar%`&J?UQxNt#NB7XTs`NY{U2f0=WI3ZRtGk>cn!c-jR!XCCy4BnN z*I=ar4r64&32pxEca}FQ@iD5pgZA((<8!3PtZn#MqP#HVVbS#ELD!z6&m5@Vn9@=a zpOv+MOjR8gt@`R-D`TSIlU4VoBy~VoRFe5#Oj^xKI&!OegZUF3kg2E82DCe%f>c|U zJ*aH%LY#5^hO2_lcr3uE&|ia7mqGT~2%5@qh9_qzF#bbG88OxGH1N2(EF(3!O+U2s zf65Mt^QdP50BxxEQnC@E$GidS{=hXTv*;6 zl6L9vX>Ho05r-E65~4xZ*zE_b@hRACo(t-H!c4^qSKYu&aiw-t-~j6kdo|2$48BR1 z%PTGNd5F;bV^w3bo_Vyyx}Uv0E^o-vDW#ALJ`LC2Bp;b$ z>2{^L%9Q52f4(d#e<0eN!16g56-vZ`KE{w$tZ}?OC|+&V{i!4c&);su-b`t{!vLh> z8Tg<_P6m`rgzvcjc)%EXEi^kT=gjP@qeyYn$HnO4g|8_!Sz6~CiE9^#IO=-kZqWK- z(-daD$=6SZpkZ|+15Ex+07vXu;yS73y$E5YS^e0{qYtiVIu{3Inr!zP%7@L#1^7kQ z)QyGy=O6^tE}VwmybsB|GHl?-*A1@+)EwGfp|1s_QJNH5p-Fb3F1pgDqo!Z!i&S>| ze1%XMJP#5yLql87RZmE;?fHRnSp;fo)S1X9q^dNwk!h#{AXoKl1^2nQb7f9gWc8(a zIz!bgd81nzy?4#AF~H%&Jp;XfC1fKffy|0ObWf?Cn>Tq2{6i8re&WI<>>UI8%$g)E zcZNCMMTC0(fvm-QM8vfuJ6mOJyql1il!zbsm?v@<8U&cwZ0*|MGy!#S*VyS)A_D(% zyrXHh90h%%r)owxD|;$y@&4n#^F1&BGD%cB96A1l7u5FLvbG-SxR9gmSoMB-k*6I9 z-2Pe7zc~0*toZ~2q@)IAQL9j4)x4!2X}jcq+E-D3Tyb_EjKj%oHptx+=< zuBuQCEN+t^-aGG3ww;;9R8;az1_{5%LaO?@V~;}#i0ZniH2w<*=LAp!1U+|dWz&ob zJ=NJ;=B6GIGrFpd+_LI#r5npdeedRWZJ?12*D-b8;W0EaWo0?Y>Y9J0`+bYec4&?r z1Qy~nq+2?a6OIl~x5$Xn8UHy~O~Whte$_|^)uMNo%cI(JI<3c+*asC140C$>_@UfO zSx638Siyg*`f4@AKIxEkV-tlhXB?m%{$~s};c;5$yn?(rt!xX+-#sB~S literal 0 HcmV?d00001 diff --git a/handlers/start.py b/handlers/start.py index c59fe02c..6aa6d43c 100644 --- a/handlers/start.py +++ b/handlers/start.py @@ -3,8 +3,9 @@ from aiogram.filters import Command from aiogram.fsm.context import FSMContext from aiogram.fsm.state import State, StatesGroup from aiogram.types import (CallbackQuery, InlineKeyboardButton, - InlineKeyboardMarkup, KeyboardButton, Message, - ReplyKeyboardMarkup) + InlineKeyboardMarkup, Message) +from aiogram.types import BufferedInputFile +import os from bot import bot from config import ADMIN_ID, CHANNEL_URL @@ -14,37 +15,52 @@ router = Router() class FeedbackState(StatesGroup): waiting_for_feedback = State() -async def start_command(message: types.Message): +async def send_welcome_message(chat_id: int): + # Новый текст приветствия welcome_text = ( - "*Добро пожаловать в наш сервис!*\n\n" - "Вы можете воспользоваться следующими функциями:\n\n" - "🔑 *Создать ключ для подключения VPN* - Получите уникальный ключ для доступа к VPN.\n" - "📅 *Узнать дату окончания ключа* - Проверьте, когда истекает срок действия вашего ключа.\n" - "👤 *Просмотреть ваш профиль* - Получите информацию о вашем аккаунте и балансе.\n\n" - "Нажмите на соответствующую кнопку ниже, чтобы начать!" + "*SoloNet -- ваш провайдер в бесцензурный интернет!*\n\n" + "Получите высокую скорость и самый безопасный протокол VPN, " + "который работает даже в Китае." ) - button_view_profile = InlineKeyboardButton(text='👤 Мой профиль', callback_data='view_profile') - button_about_vpn = InlineKeyboardButton(text='🔒 О VPN', callback_data='about_vpn') - button_feedback = InlineKeyboardButton(text='📝 Обратная связь', callback_data='feedback') - button_channel = InlineKeyboardButton(text='📢 Наш канал', url=CHANNEL_URL) + # Путь к изображению + image_path = os.path.join(os.path.dirname(__file__), 'solo_pic.png') + # Проверка существования файла + if not os.path.isfile(image_path): + await bot.send_message(chat_id, "Файл изображения не найден.") + return + + # Создаем клавиатуру inline_keyboard = InlineKeyboardMarkup(inline_keyboard=[ - [button_view_profile], - [button_about_vpn], - [button_feedback], - [button_channel] + [InlineKeyboardButton(text='👤 Мой профиль', callback_data='view_profile')], + [InlineKeyboardButton(text='🔒 О VPN', callback_data='about_vpn')], + [InlineKeyboardButton(text='📝 Обратная связь', callback_data='feedback')], + [InlineKeyboardButton(text='📢 Наш канал', url=CHANNEL_URL)] ]) - await message.bot.send_message( - chat_id=message.chat.id, - text=welcome_text, - parse_mode='Markdown', - reply_markup=inline_keyboard - ) + # Используем BufferedInputFile для отправки изображения + with open(image_path, 'rb') as image_from_buffer: + await bot.send_photo( + chat_id, + BufferedInputFile( + image_from_buffer.read(), + filename="solo_pic.png" + ), + caption=welcome_text, + parse_mode='Markdown', + reply_markup=inline_keyboard + ) + +@router.message(Command('start')) +async def start_command(message: Message): + await send_welcome_message(message.chat.id) @router.callback_query(lambda c: c.data == 'about_vpn') async def handle_about_vpn(callback_query: CallbackQuery): + # Удаляем сообщение главного меню + await callback_query.message.delete() + info_message = ( "*О VPN*\n\n" "Мы используем VLESS для обеспечения безопасного и надежного подключения к интернету. " @@ -52,69 +68,39 @@ async def handle_about_vpn(callback_query: CallbackQuery): "Этот ключ необходим для использования нашего VPN-сервиса." ) - # Кнопка "Назад" button_back = InlineKeyboardButton(text='⬅️ Назад', callback_data='back_to_menu') + inline_keyboard_back = InlineKeyboardMarkup(inline_keyboard=[[button_back]]) - # Обновлённая клавиатура с кнопкой "Назад" - inline_keyboard_back = InlineKeyboardMarkup(inline_keyboard=[ - [button_back] - ]) - - await callback_query.message.edit_text( + await callback_query.message.answer( info_message, parse_mode='Markdown', - reply_markup=inline_keyboard_back # Добавление клавиатуры с кнопкой "Назад" + reply_markup=inline_keyboard_back ) await callback_query.answer() @router.callback_query(lambda c: c.data == 'back_to_menu') async def handle_back_to_menu(callback_query: CallbackQuery): - welcome_text = ( - "*Добро пожаловать в наш сервис!*\n\n" - "Вы можете воспользоваться следующими функциями:\n\n" - "🔑 *Создать ключ для подключения VPN* - Получите уникальный ключ для доступа к VPN.\n" - "📅 *Узнать дату окончания ключа* - Проверьте, когда истекает срок действия вашего ключа.\n" - "👤 *Просмотреть ваш профиль* - Получите информацию о вашем аккаунте и балансе.\n\n" - "Нажмите на соответствующую кнопку ниже, чтобы начать!" - ) - - button_view_profile = InlineKeyboardButton(text='👤 Мой профиль', callback_data='view_profile') - button_about_vpn = InlineKeyboardButton(text='🔒 О VPN', callback_data='about_vpn') - button_feedback = InlineKeyboardButton(text='📝 Обратная связь', callback_data='feedback') - button_channel = InlineKeyboardButton(text='📢 Наш канал', url=CHANNEL_URL) - - inline_keyboard = InlineKeyboardMarkup(inline_keyboard=[ - [button_view_profile], - [button_about_vpn], - [button_feedback], - [button_channel] - ]) - - # Редактирование сообщения на главное меню - await callback_query.message.edit_text( - welcome_text, - parse_mode='Markdown', - reply_markup=inline_keyboard - ) + # Удаляем текущее сообщение + await callback_query.message.delete() + + # Отправляем приветственное сообщение + await send_welcome_message(callback_query.from_user.id) await callback_query.answer() @router.callback_query(lambda c: c.data == 'feedback') async def handle_feedback(callback_query: CallbackQuery, state: FSMContext): + # Удаляем сообщение главного меню + await callback_query.message.delete() + feedback_text = "Напишите нам, если у вас возникли трудности с подключением, есть отзыв или предложение. @pocomacho" - # Кнопка "Назад" button_back = InlineKeyboardButton(text='⬅️ Назад', callback_data='back_to_menu') + inline_keyboard_back = InlineKeyboardMarkup(inline_keyboard=[[button_back]]) - # Обновлённая клавиатура с кнопкой "Назад" - inline_keyboard_back = InlineKeyboardMarkup(inline_keyboard=[ - [button_back] - ]) - - # Редактирование сообщения с кнопкой "Назад" - await callback_query.message.edit_text( + await callback_query.message.answer( feedback_text, parse_mode='Markdown', - reply_markup=inline_keyboard_back # Клавиатура с кнопкой "Назад" + reply_markup=inline_keyboard_back ) await state.set_state(FeedbackState.waiting_for_feedback) @@ -130,17 +116,12 @@ async def receive_feedback(message: types.Message, state: FSMContext): f"Обратная связь от пользователя {user_id}:\n\n" f"{message.text}" ) - + try: await bot.send_message(ADMIN_ID, feedback_message) await message.answer("Спасибо за ваше сообщение! Мы свяжемся с вами, если это будет необходимо.") except Exception as e: await message.answer("Произошла ошибка при отправке вашего сообщения.") print(f"Ошибка при отправке обратной связи: {e}") # Логирование ошибок - - await state.clear() -# Пример обработки команды старт -@router.message(Command('start')) -async def cmd_start(message: Message): - await start_command(message) \ No newline at end of file + await state.clear() diff --git a/key_management.py b/key_management.py index dafd6dc6..44feb0bf 100644 --- a/key_management.py +++ b/key_management.py @@ -45,7 +45,7 @@ async def process_callback_create_key(callback_query: CallbackQuery, state: FSMC if trial_status == 1: await callback_query.message.edit_text( - "У вас уже был пробный ключ. Вы можете создать новый за 100 рублей. " + "У вас уже был пробный ключ. Новый стоит 100 рублей и сразу на месяц. \n\n" "Хотите продолжить?", reply_markup=InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton(text='Да, создать новый ключ', callback_data='confirm_create_new_key')], @@ -68,11 +68,15 @@ async def confirm_create_new_key(callback_query: CallbackQuery, state: FSMContex if balance < 100: replenish_button = InlineKeyboardButton(text='Перейти в профиль', callback_data='view_profile') keyboard = InlineKeyboardMarkup(inline_keyboard=[[replenish_button]]) - await callback_query.message.edit_text("Недостаточно средств на балансе для создания нового ключа.", reply_markup=keyboard) + await callback_query.message.edit_text( + "❗️ Недостаточно средств на балансе для создания нового ключа. " + "Пожалуйста, пополните баланс.", + reply_markup=keyboard + ) await state.clear() return - await callback_query.message.edit_text("Пожалуйста, выберите имя для вашего нового ключа:") + await callback_query.message.edit_text("🔑 Пожалуйста, выберите имя для вашего нового ключа:") await state.set_state(Form.waiting_for_key_name) await state.update_data(creating_new_key=True) @@ -112,8 +116,8 @@ async def handle_key_name_input(message: Message, state: FSMContext): key_name = sanitize_key_name(message.text) if not key_name: - await message.bot.send_message(tg_id, "Назовите профиль на английском языке.") - return # Прерываем выполнение функции + await message.bot.send_message(tg_id, "📝 Пожалуйста, назовите профиль на английском языке.") + return data = await state.get_data() creating_new_key = data.get('creating_new_key', False) @@ -122,28 +126,32 @@ async def handle_key_name_input(message: Message, state: FSMContext): client_id = str(uuid.uuid4()) email = key_name.lower() current_time = datetime.utcnow() - expiry_time = int((current_time + timedelta(days=1)).timestamp() * 1000) + expiry_time = None - if creating_new_key: - # Проверяем, занято ли имя ключа - conn = await asyncpg.connect(DATABASE_URL) - try: - existing_key = await conn.fetchrow('SELECT * FROM keys WHERE email = $1', email) - if existing_key: - await message.bot.send_message(tg_id, "Это имя уже занято. Пожалуйста, выберите другое имя.") - return # Прерываем выполнение функции - finally: - await conn.close() + # Получаем статус пробного ключа из базы данных + conn = await asyncpg.connect(DATABASE_URL) + try: + existing_connection = await conn.fetchrow('SELECT trial FROM connections WHERE tg_id = $1', tg_id) + finally: + await conn.close() + trial_status = existing_connection['trial'] if existing_connection else 0 + + if trial_status == 0: + # Создаем пробный ключ на 1 день + expiry_time = int((current_time + timedelta(days=1)).timestamp() * 1000) + else: + # Проверяем баланс перед созданием нового ключа balance = await get_balance(tg_id) if balance < 100: replenish_button = InlineKeyboardButton(text='Перейти в профиль', callback_data='view_profile') keyboard = InlineKeyboardMarkup(inline_keyboard=[[replenish_button]]) - await message.bot.send_message(tg_id, "Недостаточно средств на балансе для создания нового ключа.", reply_markup=keyboard) + await message.bot.send_message(tg_id, "❗️ Недостаточно средств на балансе для создания нового ключа.", reply_markup=keyboard) await state.clear() return - + await update_balance(tg_id, -100) + expiry_time = int((current_time + timedelta(days=30)).timestamp() * 1000) try: add_client(session, client_id, email, tg_id, limit_ip=1, total_gb=0, expiry_time=expiry_time, enable=True, flow="xtls-rprx-vision") @@ -165,32 +173,36 @@ async def handle_key_name_input(message: Message, state: FSMContext): await store_key(tg_id, client_id, email, expiry_time, connection_link) keyboard = InlineKeyboardMarkup(inline_keyboard=[ - [InlineKeyboardButton(text='Инструкции по использованию', callback_data='instructions')], - [InlineKeyboardButton(text='Перейти в профиль', callback_data='view_profile')] + [InlineKeyboardButton(text='📖 Инструкции по использованию', callback_data='instructions')], + [InlineKeyboardButton(text='🔙 Перейти в профиль', callback_data='view_profile')] ]) - key_message = f"Ключ создан:\n
{connection_link}
" + key_message = ( + "✅ Ключ успешно создан:\n" + f"
{connection_link}
" + ) await message.bot.send_message(tg_id, key_message, parse_mode="HTML", reply_markup=keyboard) except Exception as e: - await message.bot.send_message(tg_id, f"Ошибка при создании ключа: {e}") + await message.bot.send_message(tg_id, f"❌ Ошибка при создании ключа: {e}") await state.clear() + @dp.callback_query(F.data == 'instructions') async def handle_instructions(callback_query: CallbackQuery): instructions_message = ( - "*Инструкции по использованию вашего ключа:*\n\n" + "*📋 Инструкции по использованию вашего ключа:*\n\n" "1. Скачайте приложение для вашего устройства:\n" " - Для Android: [V2Ray](https://play.google.com/store/apps/details?id=com.v2ray.ang&hl=ru&pli=1)\n" " - Для iPhone: [Streisand](https://apps.apple.com/ru/app/streisand/id6450534064)\n\n" "2. Скопируйте предоставленный ключ, который вы получили ранее.\n" "3. Откройте приложение и нажмите на плюсик сверху справа.\n" "4. Выберите 'Вставить из буфера обмена' для добавления ключа.\n\n" - "Если у вас возникнут вопросы, не стесняйтесь обращаться в поддержку." + "💬 Если у вас возникнут вопросы, не стесняйтесь обращаться в поддержку." ) - back_button = InlineKeyboardButton(text='Назад', callback_data='back_to_main') + back_button = InlineKeyboardButton(text='🔙 Назад', callback_data='back_to_main') keyboard = InlineKeyboardMarkup(inline_keyboard=[[back_button]]) await callback_query.message.edit_text(instructions_message, parse_mode='Markdown', reply_markup=keyboard)