diff --git a/main.py b/main.py index 108c1a6..00772a7 100644 --- a/main.py +++ b/main.py @@ -48,6 +48,9 @@ main_keyboard = InlineKeyboardMarkup(inline_keyboard=[ InlineKeyboardButton(text='Моя статистика', callback_data='stats'), InlineKeyboardButton(text='Создать заявку на вывод средств', callback_data='withdraw') ], + [ + InlineKeyboardButton(text='Мои промокоды', callback_data='promocodes') + ], ]) # Вместо загрузки из файла будем хранить кэш токенов пользователей @@ -178,6 +181,10 @@ class LinkStates(StatesGroup): class WithdrawStates(StatesGroup): waiting_for_amount = State() +class PromoCodeStates(StatesGroup): + waiting_for_description = State() + promocode_created = State() + @dp.callback_query(F.data == 'create_link') async def create_link(callback: types.CallbackQuery, state: FSMContext): sent = await callback.message.edit_text( @@ -430,6 +437,119 @@ async def paginate_stats(callback: types.CallbackQuery): await callback.message.edit_text(text, reply_markup=keyboard, parse_mode='HTML', disable_web_page_preview=True) await callback.answer() +async def get_promocodes_from_api(token: str): + headers = {"Authorization": f"Bearer {token}"} + async with aiohttp.ClientSession() as session: + async with session.get(f'{API_URL}/promocode', headers=headers) as resp: + if resp.status == 200: + return await resp.json() + return [] + +async def create_promocode_from_api(token: str): + headers = {"Authorization": f"Bearer {token}"} + async with aiohttp.ClientSession() as session: + async with session.post(f'{API_URL}/promocode/add', headers=headers) as resp: + if resp.status == 200: + return await resp.json() + return None + +@dp.callback_query(F.data == 'promocodes') +async def show_promocodes(callback: types.CallbackQuery): + tg_id = callback.from_user.id + token = user_tokens.get(tg_id) + promocodes = await get_promocodes_from_api(token) + if not promocodes: + text = 'У вас пока нет промокодов.' + else: + # Форматирование таблицы с фиксированной шириной колонок + header = f"{'Промокод':<12} | {'%':<5} | {'description':<24}" + sep = '-' * 12 + '-|-' + '-' * 5 + '-|-' + '-' * 24 + rows = [] + for p in promocodes: + promocode = str(p['promocode'])[:12] + perc = str(p['perc'])[:5] + desc = (p.get('description') or '') + if len(desc) > 24: + desc = desc[:21] + '...' + rows.append(f"{promocode:<12} | {perc:<5} | {desc:<24}") + table = '\n'.join([header, sep] + rows) + text = f"Ваши промокоды:\n
{table}"
+ keyboard = InlineKeyboardMarkup(
+ inline_keyboard=[
+ [InlineKeyboardButton(text='Создать промокод', callback_data='create_promocode')],
+ [InlineKeyboardButton(text='Назад', callback_data='back_to_main')]
+ ]
+ )
+ await callback.message.edit_text(text, reply_markup=keyboard, parse_mode='HTML')
+ await callback.answer()
+
+@dp.callback_query(F.data == 'create_promocode')
+async def create_promocode(callback: types.CallbackQuery, state: FSMContext):
+ sent = await callback.message.edit_text(
+ 'Введите описание для нового промокода:',
+ reply_markup=InlineKeyboardMarkup(
+ inline_keyboard=[[InlineKeyboardButton(text='Назад', callback_data='back_to_promocodes')]]
+ )
+ )
+ await state.set_state(PromoCodeStates.waiting_for_description)
+ await state.update_data(desc_msg_id=sent.message_id)
+ await callback.answer()
+
+@dp.callback_query(F.data == 'back_to_promocodes', PromoCodeStates.waiting_for_description)
+async def back_to_promocodes_from_create(callback: types.CallbackQuery, state: FSMContext):
+ tg_id = callback.from_user.id
+ token = user_tokens.get(tg_id)
+ promocodes = await get_promocodes_from_api(token)
+ if not promocodes:
+ text = 'У вас пока нет промокодов.'
+ else:
+ header = f"{'Промокод':<12} | % | description"
+ sep = '-' * 12 + '-|-' + '-' * 3 + '-|-' + '-' * 30
+ rows = [f"{p['promocode']:<12} | {p['perc']} | {p.get('description','')[:30]}" for p in promocodes]
+ table = '\n'.join([header, sep] + rows)
+ text = f"Ваши промокоды:\n{table}"
+ keyboard = InlineKeyboardMarkup(
+ inline_keyboard=[
+ [InlineKeyboardButton(text='Создать промокод', callback_data='create_promocode')],
+ [InlineKeyboardButton(text='Назад', callback_data='back_to_main')]
+ ]
+ )
+ await callback.message.edit_text(text, reply_markup=keyboard, parse_mode='HTML')
+ await state.clear()
+ await callback.answer()
+
+@dp.message(PromoCodeStates.waiting_for_description)
+async def process_new_promocode_description(message: types.Message, state: FSMContext):
+ description = message.text.strip()
+ tg_id = message.from_user.id
+ token = user_tokens.get(tg_id)
+ data = await state.get_data()
+ desc_msg_id = data.get('desc_msg_id')
+ if desc_msg_id:
+ try:
+ await message.bot.edit_message_reply_markup(
+ chat_id=message.chat.id,
+ message_id=desc_msg_id,
+ reply_markup=None
+ )
+ except Exception:
+ pass
+ headers = {"Authorization": f"Bearer {token}"}
+ async with aiohttp.ClientSession() as session:
+ async with session.post(f'{API_URL}/promocode/add', json={"description": description}, headers=headers) as resp:
+ if resp.status == 200:
+ data = await resp.json()
+ promocode = data.get('promocode')
+ perc = data.get('perc')
+ text = f"Промокод успешно создан!\npromocode: {promocode}\ndescription: {description}\nperc: {perc}"
+ keyboard = InlineKeyboardMarkup(
+ inline_keyboard=[[InlineKeyboardButton(text='Назад к промокодам', callback_data='promocodes')]]
+ )
+ await message.answer(text, reply_markup=keyboard, parse_mode='HTML')
+ await state.set_state(PromoCodeStates.promocode_created)
+ else:
+ await message.answer('Ошибка при создании промокода. Попробуйте еще раз.')
+
async def main():
await dp.start_polling(bot)