Merge branch 'v2_functions'
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -6,6 +6,7 @@ from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from sqlalchemy import select, and_
|
||||
|
||||
from src.filters.case_insensitive import CaseInsensitiveCommand
|
||||
from src.core.database import async_session_maker
|
||||
from src.core.registration_services import AccountService, WinnerNotificationService, RegistrationService
|
||||
from src.core.services import UserService, LotteryService, ParticipationService
|
||||
@@ -22,19 +23,19 @@ class AddAccountStates(StatesGroup):
|
||||
choosing_lottery = State()
|
||||
|
||||
|
||||
@router.message(Command("cancel"))
|
||||
@router.message(CaseInsensitiveCommand("cancel"))
|
||||
@admin_only
|
||||
async def cancel_command(message: Message, state: FSMContext):
|
||||
"""Отменить текущую операцию и сбросить состояние"""
|
||||
"""Отменить текущую операцию и сбросить состояние (регистронезависимо)"""
|
||||
await state.clear()
|
||||
await message.answer("✅ Состояние сброшено. Все операции отменены.")
|
||||
|
||||
|
||||
@router.message(Command("add_account"))
|
||||
@router.message(CaseInsensitiveCommand("add_account"))
|
||||
@admin_only
|
||||
async def add_account_command(message: Message, state: FSMContext):
|
||||
"""
|
||||
Добавить счет пользователю по клубной карте
|
||||
Добавить счет пользователю по клубной карте (регистронезависимо)
|
||||
Формат: /add_account <club_card> <account_number>
|
||||
Или: /add_account (затем вводить данные построчно)
|
||||
"""
|
||||
@@ -434,11 +435,11 @@ async def skip_lottery_add(callback: CallbackQuery, state: FSMContext):
|
||||
await state.clear()
|
||||
|
||||
|
||||
@router.message(Command("remove_account"))
|
||||
@router.message(CaseInsensitiveCommand("remove_account"))
|
||||
@admin_only
|
||||
async def remove_account_command(message: Message):
|
||||
"""
|
||||
Деактивировать счет(а)
|
||||
Деактивировать счет(а) (регистронезависимо)
|
||||
Формат: /remove_account <account_number1> [account_number2] [account_number3] ...
|
||||
Можно указать несколько счетов через пробел для массового удаления
|
||||
"""
|
||||
@@ -504,11 +505,11 @@ async def remove_account_command(message: Message):
|
||||
await message.answer(f"❌ Критическая ошибка: {str(e)}")
|
||||
|
||||
|
||||
@router.message(Command("verify_winner"))
|
||||
@router.message(CaseInsensitiveCommand("verify_winner"))
|
||||
@admin_only
|
||||
async def verify_winner_command(message: Message):
|
||||
"""
|
||||
Подтвердить выигрыш по коду верификации
|
||||
Подтвердить выигрыш по коду верификации (регистронезависимо)
|
||||
Формат: /verify_winner <verification_code> <lottery_id>
|
||||
Пример: /verify_winner AB12CD34 1
|
||||
"""
|
||||
@@ -595,11 +596,11 @@ async def verify_winner_command(message: Message):
|
||||
await message.answer(f"❌ Ошибка: {str(e)}")
|
||||
|
||||
|
||||
@router.message(Command("winner_status"))
|
||||
@router.message(CaseInsensitiveCommand("winner_status"))
|
||||
@admin_only
|
||||
async def winner_status_command(message: Message):
|
||||
"""
|
||||
Показать статус всех победителей розыгрыша
|
||||
Показать статус всех победителей розыгрыша (регистронезависимо)
|
||||
Формат: /winner_status <lottery_id>
|
||||
"""
|
||||
|
||||
@@ -668,11 +669,11 @@ async def winner_status_command(message: Message):
|
||||
await message.answer(f"❌ Ошибка: {str(e)}")
|
||||
|
||||
|
||||
@router.message(Command("user_info"))
|
||||
@router.message(CaseInsensitiveCommand("user_info"))
|
||||
@admin_only
|
||||
async def user_info_command(message: Message):
|
||||
"""
|
||||
Показать информацию о пользователе
|
||||
Показать информацию о пользователе (регистронезависимо)
|
||||
Формат: /user_info <club_card>
|
||||
"""
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKe
|
||||
from aiogram.filters import Command
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from src.filters.case_insensitive import CaseInsensitiveCommand
|
||||
from src.core.chat_services import (
|
||||
ChatSettingsService,
|
||||
BanService,
|
||||
@@ -29,10 +30,10 @@ def get_chat_mode_keyboard() -> InlineKeyboardMarkup:
|
||||
])
|
||||
|
||||
|
||||
@router.message(Command("chat_mode"))
|
||||
@router.message(CaseInsensitiveCommand("chat_mode"))
|
||||
@admin_only
|
||||
async def cmd_chat_mode(message: Message):
|
||||
"""Команда управления режимом чата"""
|
||||
"""Команда управления режимом чата (регистронезависимо)"""
|
||||
|
||||
async with async_session_maker() as session:
|
||||
settings = await ChatSettingsService.get_or_create_settings(session)
|
||||
@@ -68,10 +69,10 @@ async def process_chat_mode(callback: CallbackQuery):
|
||||
await callback.answer("✅ Режим изменен")
|
||||
|
||||
|
||||
@router.message(Command("set_forward"))
|
||||
@router.message(CaseInsensitiveCommand("set_forward"))
|
||||
@admin_only
|
||||
async def cmd_set_forward(message: Message):
|
||||
"""Установить ID канала для пересылки"""
|
||||
"""Установить ID канала для пересылки (регистронезависимо)"""
|
||||
|
||||
args = message.text.split(maxsplit=1)
|
||||
if len(args) < 2:
|
||||
@@ -100,10 +101,10 @@ async def cmd_set_forward(message: Message):
|
||||
)
|
||||
|
||||
|
||||
@router.message(Command("global_ban"))
|
||||
@router.message(CaseInsensitiveCommand("global_ban"))
|
||||
@admin_only
|
||||
async def cmd_global_ban(message: Message):
|
||||
"""Включить/выключить глобальный бан чата"""
|
||||
"""Включить/выключить глобальный бан чата (регистронезависимо)"""
|
||||
|
||||
async with async_session_maker() as session:
|
||||
settings = await ChatSettingsService.get_or_create_settings(session)
|
||||
@@ -126,10 +127,10 @@ async def cmd_global_ban(message: Message):
|
||||
)
|
||||
|
||||
|
||||
@router.message(Command("ban"))
|
||||
@router.message(CaseInsensitiveCommand("ban"))
|
||||
@admin_only
|
||||
async def cmd_ban(message: Message):
|
||||
"""Забанить пользователя"""
|
||||
"""Забанить пользователя (регистронезависимо)"""
|
||||
|
||||
# Проверяем является ли это ответом на сообщение
|
||||
if message.reply_to_message:
|
||||
@@ -191,10 +192,10 @@ async def cmd_ban(message: Message):
|
||||
)
|
||||
|
||||
|
||||
@router.message(Command("unban"))
|
||||
@router.message(CaseInsensitiveCommand("unban"))
|
||||
@admin_only
|
||||
async def cmd_unban(message: Message):
|
||||
"""Разбанить пользователя"""
|
||||
"""Разбанить пользователя (регистронезависимо)"""
|
||||
|
||||
# Проверяем является ли это ответом на сообщение
|
||||
if message.reply_to_message:
|
||||
@@ -232,10 +233,10 @@ async def cmd_unban(message: Message):
|
||||
await message.answer("❌ Пользователь не был забанен")
|
||||
|
||||
|
||||
@router.message(Command("banlist"))
|
||||
@router.message(CaseInsensitiveCommand("banlist"))
|
||||
@admin_only
|
||||
async def cmd_banlist(message: Message):
|
||||
"""Показать список забаненных пользователей"""
|
||||
"""Показать список заблокированных пользователей (регистронезависимо)"""
|
||||
|
||||
async with async_session_maker() as session:
|
||||
banned_users = await BanService.get_banned_users(session, active_only=True)
|
||||
@@ -262,10 +263,10 @@ async def cmd_banlist(message: Message):
|
||||
await message.answer(text, parse_mode="HTML")
|
||||
|
||||
|
||||
@router.message(Command("delete_msg"))
|
||||
@router.message(CaseInsensitiveCommand("delete_msg"))
|
||||
@admin_only
|
||||
async def cmd_delete_message(message: Message):
|
||||
"""Удалить сообщение из чата (пометить как удаленное)"""
|
||||
"""Удалить сообщение из чата (пометить как удаленное) (регистронезависимо)"""
|
||||
|
||||
if not message.reply_to_message:
|
||||
await message.answer(
|
||||
@@ -329,10 +330,10 @@ async def cmd_delete_message(message: Message):
|
||||
await message.answer("❌ Не удалось удалить сообщение")
|
||||
|
||||
|
||||
@router.message(Command("chat_stats"))
|
||||
@router.message(CaseInsensitiveCommand("chat_stats"))
|
||||
@admin_only
|
||||
async def cmd_chat_stats(message: Message):
|
||||
"""Статистика чата"""
|
||||
"""Статистика чата (регистронезависимо)"""
|
||||
|
||||
async with async_session_maker() as session:
|
||||
settings = await ChatSettingsService.get_or_create_settings(session)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,8 @@ from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKe
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from aiogram.filters import StateFilter, Command
|
||||
|
||||
from src.filters.case_insensitive import CaseInsensitiveCommand
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
import asyncio
|
||||
from typing import List, Dict, Optional, Set, Any
|
||||
@@ -43,9 +45,9 @@ def _contains_account_numbers(text: str) -> bool:
|
||||
router = Router(name='chat_router')
|
||||
|
||||
|
||||
@router.message(Command("chat"))
|
||||
@router.message(CaseInsensitiveCommand("chat"))
|
||||
async def enter_chat_command(message: Message, state: FSMContext):
|
||||
"""Войти в режим чата через команду /chat"""
|
||||
"""Войти в режим чата через команду /chat (регистронезависимо)"""
|
||||
await enter_chat(message, state)
|
||||
|
||||
|
||||
@@ -58,6 +60,8 @@ async def enter_chat_callback(callback: CallbackQuery, state: FSMContext):
|
||||
|
||||
async def enter_chat(message: Message, state: FSMContext):
|
||||
"""Общая функция входа в чат"""
|
||||
from src.utils.keyboards import get_chat_reply_keyboard
|
||||
|
||||
await state.set_state(ChatStates.in_chat)
|
||||
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||
@@ -65,19 +69,28 @@ async def enter_chat(message: Message, state: FSMContext):
|
||||
[InlineKeyboardButton(text="🏠 В главное меню", callback_data="back_to_main")]
|
||||
])
|
||||
|
||||
# Обычная клавиатура для чата
|
||||
reply_keyboard = get_chat_reply_keyboard()
|
||||
|
||||
await message.answer(
|
||||
"💬 <b>Вы вошли в режим чата</b>\n\n"
|
||||
"Теперь все ваши сообщения будут рассылаться участникам.\n"
|
||||
"Вы можете отправлять текст, фото, видео, документы и стикеры.\n\n"
|
||||
"Для выхода нажмите кнопку ниже или отправьте /exit",
|
||||
reply_markup=keyboard,
|
||||
reply_markup=reply_keyboard, # Обычная клавиатура
|
||||
parse_mode="HTML"
|
||||
)
|
||||
|
||||
# Inline клавиатура отдельным сообщением
|
||||
await message.answer(
|
||||
"Выберите действие:",
|
||||
reply_markup=keyboard
|
||||
)
|
||||
|
||||
|
||||
@router.message(Command("exit"), StateFilter(ChatStates.in_chat))
|
||||
@router.message(CaseInsensitiveCommand("exit"), StateFilter(ChatStates.in_chat))
|
||||
async def exit_chat_command(message: Message, state: FSMContext):
|
||||
"""Выйти из режима чата через команду /exit"""
|
||||
"""Выйти из режима чата через команду /exit (регистронезависимо)"""
|
||||
await exit_chat(message, state)
|
||||
|
||||
|
||||
@@ -90,19 +103,71 @@ async def exit_chat_callback(callback: CallbackQuery, state: FSMContext):
|
||||
|
||||
async def exit_chat(message: Message, state: FSMContext):
|
||||
"""Общая функция выхода из чата"""
|
||||
from src.utils.keyboards import get_main_reply_keyboard
|
||||
from src.core.config import ADMIN_IDS
|
||||
from src.core.services import UserService
|
||||
from src.core.database import async_session_maker
|
||||
|
||||
await state.clear()
|
||||
|
||||
# Получаем информацию о пользователе
|
||||
async with async_session_maker() as session:
|
||||
user = await UserService.get_user_by_telegram_id(session, message.from_user.id)
|
||||
is_registered = user.is_registered if user else False
|
||||
is_admin_user = message.from_user.id in ADMIN_IDS
|
||||
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="💬 Войти в чат", callback_data="enter_chat")],
|
||||
[InlineKeyboardButton(text="🏠 В главное меню", callback_data="back_to_main")]
|
||||
])
|
||||
|
||||
# Обычная клавиатура
|
||||
reply_keyboard = get_main_reply_keyboard(is_admin=is_admin_user, is_registered=is_registered)
|
||||
|
||||
await message.answer(
|
||||
"✅ <b>Вы вышли из режима чата</b>\n\n"
|
||||
"Ваши сообщения больше не будут рассылаться.",
|
||||
reply_markup=keyboard,
|
||||
reply_markup=reply_keyboard, # Обычная клавиатура
|
||||
parse_mode="HTML"
|
||||
)
|
||||
|
||||
# Inline клавиатура отдельным сообщением
|
||||
await message.answer(
|
||||
"Выберите действие:",
|
||||
reply_markup=keyboard
|
||||
)
|
||||
|
||||
|
||||
@router.message(StateFilter(ChatStates.in_chat), F.text)
|
||||
async def check_exit_keywords(message: Message, state: FSMContext):
|
||||
"""Проверка на ключевые слова для выхода из чата"""
|
||||
text = message.text.strip().lower()
|
||||
|
||||
# Проверяем ключевые слова для выхода
|
||||
exit_keywords = ['/start', 'start', 'старт', '/exit']
|
||||
|
||||
if text in exit_keywords:
|
||||
if text in ['/start', 'start', 'старт']:
|
||||
# Выходим из чата и показываем главное меню
|
||||
await state.clear()
|
||||
|
||||
from src.components.ui import UserUI
|
||||
keyboard = UserUI.get_main_menu_keyboard(message.from_user.id)
|
||||
|
||||
await message.answer(
|
||||
"🏠 <b>Главное меню</b>\n\n"
|
||||
"Вы вышли из режима чата.",
|
||||
reply_markup=keyboard,
|
||||
parse_mode="HTML"
|
||||
)
|
||||
return # Не обрабатываем дальше
|
||||
else:
|
||||
# Для /exit просто выходим
|
||||
await exit_chat(message, state)
|
||||
return
|
||||
|
||||
# Если не ключевое слово, пропускаем дальше для обработки как обычное сообщение чата
|
||||
# Остальная логика обработки сообщений чата будет ниже
|
||||
|
||||
|
||||
# Настройки для планировщика рассылки
|
||||
|
||||
225
src/handlers/help_handlers.py
Normal file
225
src/handlers/help_handlers.py
Normal file
@@ -0,0 +1,225 @@
|
||||
"""Обработчики справки и помощи пользователям"""
|
||||
from aiogram import Router, F
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
|
||||
from aiogram.filters import Command
|
||||
from src.core.config import ADMIN_IDS
|
||||
|
||||
from src.filters.case_insensitive import CaseInsensitiveCommand
|
||||
|
||||
|
||||
def is_admin(user_id: int) -> bool:
|
||||
"""Проверка является ли пользователь админом"""
|
||||
return user_id in ADMIN_IDS
|
||||
|
||||
|
||||
router = Router(name='help_router')
|
||||
|
||||
|
||||
def get_help_menu_keyboard() -> InlineKeyboardMarkup:
|
||||
"""Клавиатура меню справки"""
|
||||
buttons = [
|
||||
[InlineKeyboardButton(text="📝 Регистрация", callback_data="help_registration")],
|
||||
[InlineKeyboardButton(text="🎰 Участие в розыгрышах", callback_data="help_lottery")],
|
||||
[InlineKeyboardButton(text="💬 Чат", callback_data="help_chat")],
|
||||
[InlineKeyboardButton(text="⚙️ Команды", callback_data="help_commands")],
|
||||
[InlineKeyboardButton(text="🏠 В главное меню", callback_data="back_to_main")]
|
||||
]
|
||||
return InlineKeyboardMarkup(inline_keyboard=buttons)
|
||||
|
||||
|
||||
def get_back_to_help_keyboard() -> InlineKeyboardMarkup:
|
||||
"""Клавиатура возврата к справке"""
|
||||
buttons = [
|
||||
[InlineKeyboardButton(text="◀️ Назад к справке", callback_data="help_main")],
|
||||
[InlineKeyboardButton(text="🏠 В главное меню", callback_data="back_to_main")]
|
||||
]
|
||||
return InlineKeyboardMarkup(inline_keyboard=buttons)
|
||||
|
||||
|
||||
@router.message(CaseInsensitiveCommand("help"))
|
||||
async def help_command(message: Message):
|
||||
"""Показать справку по команде /help (регистронезависимо)"""
|
||||
await show_help_main(message)
|
||||
|
||||
|
||||
@router.callback_query(F.data == "help_main")
|
||||
async def help_main_callback(callback: CallbackQuery):
|
||||
"""Показать главное меню справки"""
|
||||
await callback.answer()
|
||||
await show_help_main(callback.message, edit=True)
|
||||
|
||||
|
||||
async def show_help_main(message: Message, edit: bool = False):
|
||||
"""Показать главное меню справки"""
|
||||
text = (
|
||||
"❓ <b>Справка по работе с ботом</b>\n\n"
|
||||
"Выберите интересующий вас раздел:\n\n"
|
||||
"📝 <b>Регистрация</b> - как зарегистрироваться в системе\n"
|
||||
"🎰 <b>Участие в розыгрышах</b> - как участвовать и выигрывать\n"
|
||||
"💬 <b>Чат</b> - общение с другими участниками\n"
|
||||
"⚙️ <b>Команды</b> - список доступных команд"
|
||||
)
|
||||
|
||||
keyboard = get_help_menu_keyboard()
|
||||
|
||||
if edit:
|
||||
try:
|
||||
await message.edit_text(text, reply_markup=keyboard, parse_mode="HTML")
|
||||
except:
|
||||
await message.answer(text, reply_markup=keyboard, parse_mode="HTML")
|
||||
else:
|
||||
await message.answer(text, reply_markup=keyboard, parse_mode="HTML")
|
||||
|
||||
|
||||
@router.callback_query(F.data == "help_registration")
|
||||
async def help_registration(callback: CallbackQuery):
|
||||
"""Справка по регистрации"""
|
||||
await callback.answer()
|
||||
|
||||
text = (
|
||||
"📝 <b>Регистрация в системе</b>\n\n"
|
||||
"<b>Как зарегистрироваться:</b>\n\n"
|
||||
"1️⃣ Откройте главное меню и выберите <i>\"Регистрация\"</i>\n\n"
|
||||
"2️⃣ Введите ваши данные:\n"
|
||||
" • Имя и фамилию\n"
|
||||
" • Номер телефона\n"
|
||||
" • Номер клубной карты (если есть)\n\n"
|
||||
"3️⃣ Ожидайте подтверждения от администратора\n\n"
|
||||
"4️⃣ После одобрения вам станут доступны все функции бота:\n"
|
||||
" ✅ Участие в розыгрышах\n"
|
||||
" ✅ Доступ к чату\n"
|
||||
" ✅ Получение уведомлений\n\n"
|
||||
"💡 <b>Важно!</b>\n"
|
||||
"Указывайте корректные данные - они проверяются администратором.\n\n"
|
||||
"Статус вашей регистрации можно проверить в главном меню."
|
||||
)
|
||||
|
||||
keyboard = get_back_to_help_keyboard()
|
||||
|
||||
try:
|
||||
await callback.message.edit_text(text, reply_markup=keyboard, parse_mode="HTML")
|
||||
except:
|
||||
await callback.message.answer(text, reply_markup=keyboard, parse_mode="HTML")
|
||||
|
||||
|
||||
@router.callback_query(F.data == "help_lottery")
|
||||
async def help_lottery(callback: CallbackQuery):
|
||||
"""Справка по розыгрышам"""
|
||||
await callback.answer()
|
||||
|
||||
text = (
|
||||
"🎰 <b>Участие в розыгрышах</b>\n\n"
|
||||
"<b>Как принять участие:</b>\n\n"
|
||||
"1️⃣ Убедитесь, что вы зарегистрированы\n\n"
|
||||
"2️⃣ Дождитесь объявления нового розыгрыша\n"
|
||||
" • Уведомления приходят всем участникам\n"
|
||||
" • Розыгрыши проводятся регулярно\n\n"
|
||||
"3️⃣ В описании розыгрыша будет указано:\n"
|
||||
" 📝 Название и описание приза\n"
|
||||
" 👥 Количество победителей\n"
|
||||
" 📅 Дата и время проведения\n\n"
|
||||
"4️⃣ Когда придет время:\n"
|
||||
" • Администратор проведет розыгрыш\n"
|
||||
" • Победители определяются случайным образом\n"
|
||||
" • Всем участникам придет уведомление о результатах\n\n"
|
||||
"🏆 <b>Если вы выиграли:</b>\n"
|
||||
" • Вы получите личное уведомление\n"
|
||||
" • Информация о получении приза будет в сообщении\n"
|
||||
" • Следуйте инструкциям администратора\n\n"
|
||||
"💡 <b>Совет:</b> Включите уведомления бота, чтобы не пропустить розыгрыш!"
|
||||
)
|
||||
|
||||
keyboard = get_back_to_help_keyboard()
|
||||
|
||||
try:
|
||||
await callback.message.edit_text(text, reply_markup=keyboard, parse_mode="HTML")
|
||||
except:
|
||||
await callback.message.answer(text, reply_markup=keyboard, parse_mode="HTML")
|
||||
|
||||
|
||||
@router.callback_query(F.data == "help_chat")
|
||||
async def help_chat(callback: CallbackQuery):
|
||||
"""Справка по чату"""
|
||||
await callback.answer()
|
||||
|
||||
text = (
|
||||
"💬 <b>Чат участников</b>\n\n"
|
||||
"<b>Как пользоваться чатом:</b>\n\n"
|
||||
"1️⃣ <b>Вход в чат:</b>\n"
|
||||
" • Откройте главное меню\n"
|
||||
" • Выберите <i>\"Войти в чат\"</i>\n"
|
||||
" • Или отправьте команду <code>/chat</code>\n\n"
|
||||
"2️⃣ <b>Отправка сообщений:</b>\n"
|
||||
" • Пишите как обычно в Telegram\n"
|
||||
" • Ваши сообщения увидят все участники\n"
|
||||
" • Можно отправлять:\n"
|
||||
" 📝 Текст\n"
|
||||
" 🖼 Фото и видео\n"
|
||||
" 📎 Документы\n"
|
||||
" 😊 Стикеры\n\n"
|
||||
"3️⃣ <b>Выход из чата:</b>\n"
|
||||
" • Нажмите кнопку <i>\"Выйти из чата\"</i>\n"
|
||||
" • Или отправьте команду <code>/exit</code>\n"
|
||||
" • Или напишите <code>старт</code> / <code>start</code> / <code>/start</code>\n\n"
|
||||
"⚠️ <b>Правила чата:</b>\n"
|
||||
" • Будьте вежливы с другими участниками\n"
|
||||
" • Не спамьте сообщениями\n"
|
||||
" • Запрещены оскорбления и реклама\n"
|
||||
" • Администратор может заблокировать за нарушения\n\n"
|
||||
"💡 <b>Подсказка:</b>\n"
|
||||
"Если вы отправляете 20+ сообщений, они рассылаются пакетами с небольшой задержкой."
|
||||
)
|
||||
|
||||
keyboard = get_back_to_help_keyboard()
|
||||
|
||||
try:
|
||||
await callback.message.edit_text(text, reply_markup=keyboard, parse_mode="HTML")
|
||||
except:
|
||||
await callback.message.answer(text, reply_markup=keyboard, parse_mode="HTML")
|
||||
|
||||
|
||||
@router.callback_query(F.data == "help_commands")
|
||||
async def help_commands(callback: CallbackQuery):
|
||||
"""Справка по командам"""
|
||||
await callback.answer()
|
||||
|
||||
user_id = callback.from_user.id
|
||||
is_user_admin = is_admin(user_id)
|
||||
|
||||
text = (
|
||||
"⚙️ <b>Список команд бота</b>\n\n"
|
||||
"<b>Основные команды:</b>\n\n"
|
||||
"🏠 <code>/start</code> - Главное меню\n"
|
||||
"❓ <code>/help</code> - Справка (это меню)\n"
|
||||
"💬 <code>/chat</code> - Войти в чат\n"
|
||||
"🚪 <code>/exit</code> - Выйти из чата\n\n"
|
||||
"<b>Как использовать:</b>\n\n"
|
||||
"• Отправьте команду в чат с ботом\n"
|
||||
"• Начните команду с символа /\n"
|
||||
"• Можно также использовать кнопки в меню\n\n"
|
||||
)
|
||||
|
||||
if is_user_admin:
|
||||
text += (
|
||||
"👑 <b>Команды администратора:</b>\n\n"
|
||||
"🔧 <code>/admin</code> - Панель администратора\n"
|
||||
"📊 Управление розыгрышами\n"
|
||||
"👥 Управление пользователями\n"
|
||||
"📢 Массовые рассылки\n"
|
||||
"⚙️ Настройки системы\n\n"
|
||||
)
|
||||
|
||||
text += (
|
||||
"💡 <b>Полезные советы:</b>\n\n"
|
||||
"• Включите уведомления для получения важных сообщений\n"
|
||||
"• Используйте кнопки - это быстрее команд\n"
|
||||
"• В чате пишите <code>старт</code> чтобы вернуться в меню\n"
|
||||
"• Регулярно проверяйте бота на наличие новых розыгрышей"
|
||||
)
|
||||
|
||||
keyboard = get_back_to_help_keyboard()
|
||||
|
||||
try:
|
||||
await callback.message.edit_text(text, reply_markup=keyboard, parse_mode="HTML")
|
||||
except:
|
||||
await callback.message.answer(text, reply_markup=keyboard, parse_mode="HTML")
|
||||
@@ -6,6 +6,7 @@ from aiogram import Router, F, Bot
|
||||
from aiogram.types import Message, CallbackQuery
|
||||
from aiogram.filters import Command
|
||||
|
||||
from src.filters.case_insensitive import CaseInsensitiveCommand
|
||||
from ..core.config import ADMIN_IDS
|
||||
from ..core.database import async_session_maker
|
||||
from ..core.chat_services import ChatMessageService
|
||||
@@ -21,10 +22,10 @@ def is_admin(user_id: int) -> bool:
|
||||
return user_id in ADMIN_IDS
|
||||
|
||||
|
||||
@message_admin_router.message(Command("delete"))
|
||||
@message_admin_router.message(CaseInsensitiveCommand("delete"))
|
||||
async def delete_replied_message(message: Message):
|
||||
"""
|
||||
Удаление сообщения по команде /delete
|
||||
Удаление сообщения по команде /delete (регистронезависимо)
|
||||
Работает только если команда является ответом на сообщение бота
|
||||
"""
|
||||
if not is_admin(message.from_user.id):
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
from aiogram import Router, F
|
||||
from aiogram.filters import Command, StateFilter
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
|
||||
|
||||
from src.filters.case_insensitive import CaseInsensitiveCommand
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@@ -28,10 +30,10 @@ def is_admin(user_id: int) -> bool:
|
||||
return user_id in ADMIN_IDS
|
||||
|
||||
|
||||
@router.message(Command("chat"))
|
||||
@router.message(CaseInsensitiveCommand("chat"))
|
||||
async def show_chat_menu(message: Message, state: FSMContext):
|
||||
"""
|
||||
Главное меню чата
|
||||
Главное меню чата (регистронезависимо)
|
||||
/chat - показать меню с опциями общения
|
||||
"""
|
||||
# Очищаем состояние при входе в меню (выход из диалога)
|
||||
|
||||
@@ -6,6 +6,7 @@ from sqlalchemy import select, and_
|
||||
from datetime import datetime, timezone, timedelta
|
||||
import random
|
||||
|
||||
from src.filters.case_insensitive import CaseInsensitiveCommand
|
||||
from src.core.database import async_session_maker
|
||||
from src.core.registration_services import AccountService, WinnerNotificationService
|
||||
from src.core.services import LotteryService
|
||||
@@ -17,11 +18,11 @@ from src.core.permissions import admin_only
|
||||
router = Router()
|
||||
|
||||
|
||||
@router.message(Command("check_unclaimed"))
|
||||
@router.message(CaseInsensitiveCommand("check_unclaimed"))
|
||||
@admin_only
|
||||
async def check_unclaimed_winners(message: Message):
|
||||
"""
|
||||
Проверить неподтвержденные выигрыши (более 24 часов)
|
||||
Проверить неподтвержденные выигрыши (более 24 часов) (регистронезависимо)
|
||||
Формат: /check_unclaimed <lottery_id>
|
||||
"""
|
||||
|
||||
@@ -118,11 +119,11 @@ async def check_unclaimed_winners(message: Message):
|
||||
await message.answer(f"❌ Ошибка: {str(e)}")
|
||||
|
||||
|
||||
@router.message(Command("redraw"))
|
||||
@router.message(CaseInsensitiveCommand("redraw"))
|
||||
@admin_only
|
||||
async def redraw_lottery(message: Message):
|
||||
"""
|
||||
Переиграть розыгрыш для неподтвержденных выигрышей
|
||||
Переиграть розыгрыш для неподтвержденных выигрышей (регистронезависимо)
|
||||
Формат: /redraw <lottery_id>
|
||||
"""
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
from aiogram import Router, F
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from aiogram.filters import Command, StateFilter
|
||||
|
||||
from src.filters.case_insensitive import CaseInsensitiveCommand
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
import logging
|
||||
|
||||
@@ -7,6 +7,7 @@ from aiogram import Router, F
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from aiogram.filters import Command
|
||||
|
||||
from src.filters.case_insensitive import CaseInsensitiveCommand
|
||||
from src.core.config import ADMIN_IDS
|
||||
from src.core.permissions import is_admin
|
||||
|
||||
@@ -14,9 +15,9 @@ from src.core.permissions import is_admin
|
||||
test_router = Router()
|
||||
|
||||
|
||||
@test_router.message(Command("test_start"))
|
||||
@test_router.message(CaseInsensitiveCommand("test_start"))
|
||||
async def cmd_test_start(message: Message):
|
||||
"""Тестовая команда /test_start"""
|
||||
"""Тестовая команда /test_start (регистронезависимо)"""
|
||||
user_id = message.from_user.id
|
||||
first_name = message.from_user.first_name
|
||||
is_admin_user = is_admin(user_id)
|
||||
@@ -47,9 +48,9 @@ async def cmd_test_start(message: Message):
|
||||
)
|
||||
|
||||
|
||||
@test_router.message(Command("test_admin"))
|
||||
@test_router.message(CaseInsensitiveCommand("test_admin"))
|
||||
async def cmd_test_admin(message: Message):
|
||||
"""Тестовая команда /test_admin"""
|
||||
"""Тестовая команда /test_admin (регистронезависимо)"""
|
||||
if not is_admin(message.from_user.id):
|
||||
await message.answer("❌ У вас нет прав для выполнения этой команды")
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user