Загрузка...

ТГ бот для приема заявок python

Тема в разделе Python создана пользователем foksi777 2 мар 2025. (поднята 9 мар 2025) 329 просмотров

  1. foksi777
    foksi777 Автор темы 2 мар 2025 8 22 окт 2022
    Тг бот для приема заявок.
    Для использования замените BOT_TOKEN на свой токен, admin Id на свой id и при надобности измените вопросы в самом коде

    Python
    import asyncio
    import logging
    import json

    from aiogram import Bot, Dispatcher, types, F
    from aiogram.filters import CommandStart, Command
    from aiogram.fsm.context import FSMContext
    from aiogram.fsm.state import State, StatesGroup
    from aiogram.types import ReplyKeyboardRemove, InlineKeyboardButton, InlineKeyboardMarkup
    from aiogram.exceptions import TelegramForbiddenError
    from aiogram.client.default import DefaultBotProperties

    # Замените на свой токен и ID администратора
    BOT_TOKEN = "7916714809:AAGMeW8m8irrP0UDewrJn1ITEFH4TEJD1NY"
    ADMIN_ID = [URL='https://lolz.live/tel:1364958631']1364958631[/URL]
    AUTHORIZED_USERS_FILE = "authorized_users.json" # Fixed filename


    logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
    log = logging.getLogger(__name__)

    try:
    with open(AUTHORIZED_USERS_FILE, "r") as f:
    AUTHORIZED_USERS = set(json.load(f))
    log.info(f"Loaded AUTHORIZED_USERS from {AUTHORIZED_USERS_FILE}: {AUTHORIZED_USERS}")
    except FileNotFoundError:
    AUTHORIZED_USERS = set()
    log.warning(f"{AUTHORIZED_USERS_FILE} not found. Starting with an empty AUTHORIZED_USERS list.")
    except json.JSONDecodeError:
    AUTHORIZED_USERS = set()
    log.error(f"Error decoding JSON in {AUTHORIZED_USERS_FILE}. Starting with an empty AUTHORIZED_USERS list.")

    # Создаем бота и диспетчер
    bot_properties = DefaultBotProperties(parse_mode="HTML")
    bot = Bot(token=BOT_TOKEN, default=bot_properties)
    dp = Dispatcher()

    class UserForm(StatesGroup):
    reason = State()
    experience = State()
    time_commitment = State()


    @dp.message(Command("admin"), F.from_user.id == ADMIN_ID)
    async def admin_command(message: types.Message):
    log.info(f"Администратор {message.from_user.id} вызвал команду /admin")
    await message.answer("Привет, администратор! Какие будут указания?")

    @dp.message(Command("admin"))
    async def not_admin(message: types.Message):
    await message.reply("Вы не являетесь администратором!")

    @dp.message(CommandStart())
    async def start_command(message: types.Message, state: FSMContext):
    user_id = message.from_user.id
    log.info(f"Пользователь {user_id} запустил бота")

    if user_id in AUTHORIZED_USERS:
    log.info(f"Пользователь {user_id} имеет полный доступ.")
    await message.answer("ℹ <i>Информация <b>Vors Team</b></i> \n\n<b> Проценты профитов</b>")
    await state.clear() # очистить на всякий случай
    else:
    log.info(f"Пользователь {user_id} начинает заполнение анкеты.")
    await state.clear()
    keyboard = InlineKeyboardMarkup(inline_keyboard=[
    [
    InlineKeyboardButton(text="Да", callback_data="start_yes"),
    InlineKeyboardButton(text="Нет", callback_data="start_no"),
    ]
    ])
    text = "Привет мой дорогой друг!<b>\n\nДля вступления в нашу команду, я задам тебе пару вопросов, на которые ты должен ответить честно \n\nСогласен?</b>"
    await message.answer(text, reply_markup=keyboard)

    @dp.callback_query(lambda query: query.data in ("start_yes", "start_no"))
    async def handle_start_callback(callback: types.CallbackQuery, state: FSMContext):
    if callback.data == "start_yes":
    log.info(f"Пользователь {callback.from_user.id} нажал 'Да'")
    await callback.message.answer("<b>⚡Почему именно наша команда?</b>", reply_markup=ReplyKeyboardRemove())
    await state.set_state(UserForm.reason)
    else:
    log.info(f"Пользователь {callback.from_user.id} нажал 'Нет'")
    await callback.message.answer("Увы, но тебе не сюда, бро.", reply_markup=ReplyKeyboardRemove())

    @dp.message(UserForm.reason)
    async def process_reason(message: types.Message, state: FSMContext):
    log.info(f"Пользователь {message.from_user.id} ввел причину")
    await state.update_data(reason=message.text)
    await message.answer("<b>⚡Ваш опыт работы?</b>", reply_markup=ReplyKeyboardRemove())
    await state.set_state(UserForm.experience)

    @dp.message(UserForm.experience)
    async def process_experience(message: types.Message, state: FSMContext):
    log.info(f"Пользователь {message.from_user.id} ввел опыт")
    await state.update_data(experience=message.text)
    await message.answer("<b>⚡Сколько времени будете уделять работе?</b>", reply_markup=ReplyKeyboardRemove())
    await state.set_state(UserForm.time_commitment)

    @dp.message(UserForm.time_commitment)
    async def process_time_commitment(message: types.Message, state: FSMContext):
    log.info(f"Пользователь {message.from_user.id} ввел время")
    await state.update_data(time_commitment=message.text)
    await show_summary_and_buttons(message, state)

    async def show_summary_and_buttons(message: types.Message, state: FSMContext):
    log.info(f"Формирование и отправка сводки пользователю {message.from_user.id}")
    data = await state.get_data()
    summary = (
    "Пожалуйста, проверьте введенные данные:\n"
    f"<b>⚡Почему именно наша команда?</b>: {data.get('reason', 'Не указано')}\n" # HTML
    f"<b>⚡Ваш опыт работы?</b>: {data.get('experience', 'Не указано')}\n" # HTML
    f"<b>⚡Сколько времени будете уделять работе?</b>: {data.get('time_commitment', 'Не указано')}\n"
    )
    keyboard = InlineKeyboardMarkup(inline_keyboard=[
    [
    InlineKeyboardButton(text="Принять", callback_data="accept"),
    InlineKeyboardButton(text="Отказаться", callback_data="decline"),
    ]
    ])
    try:
    log.info(f"Попытка отправки сообщения: {summary}")
    sent_message = await message.answer(summary, reply_markup=keyboard)
    log.info(f"Сообщение с кнопками отправлено, ID: {sent_message.message_id}")
    await state.update_data(last_message_id=sent_message.message_id)
    except Exception as e:
    log.exception(f"Ошибка при отправке сообщения с кнопками: {e}, Тип ошибки: {type(e)}")
    log.info("show_summary_and_buttons завершена")

    @dp.callback_query(lambda query: query.data in ("accept", "decline"))
    async def process_callback(callback: types.CallbackQuery, state: FSMContext):
    log.info(f"Callback запрос получен: {callback.data}")
    await callback.answer()

    if callback.data == "accept":
    log.info(f"Пользователь {callback.from_user.id} нажал 'Принять'")
    try:
    await bot.send_message(callback.from_user.id, " Отлично, твоя заявка отправлена администратору.")
    except TelegramForbiddenError:
    log.error(f"Пользователь {callback.from_user.id} заблокировал бота.")
    elif callback.data == "decline":
    log.info(f"Пользователь {callback.from_user.id} нажал 'Отказаться'")
    try:
    await bot.send_message(callback.from_user.id, "Ваша заявка отклонена. Пожалуйста, попробуйте еще раз.")
    except TelegramForbiddenError:
    log.error(f"Пользователь {callback.from_user.id} заблокировал бота.")

    await callback.message.delete_reply_markup()
    user_id = callback.from_user.id
    data = await state.get_data()
    await state.clear()

    await send_to_admin(callback.message, data, user_id)

    async def send_to_admin(message: types.Message, data, user_id):
    log.info(f"Отправка заявки администратору...")
    admin_message = (
    "Новая заявка:\n"
    f"Имя пользователя: {message.from_user.full_name}\n"
    f"ID пользователя: {message.from_user.id}\n"
    f"<b>⚡Почему именно наша команда?</b>: {data.get('reason', 'Не указано')}\n" # HTML
    f"<b>⚡Ваш опыт работы?</b>: {data.get('experience', 'Не указано')}\n" # HTML
    f"<b>⚡Сколько времени будете уделять работе?</b>: {data.get('time_commitment', 'Не указано')}\n" # HTML
    )

    admin_keyboard = InlineKeyboardMarkup(inline_keyboard=[
    [
    InlineKeyboardButton(text="Принять", callback_data=f"admin_accept:{user_id}"),
    InlineKeyboardButton(text="Отказать", callback_data=f"admin_decline:{user_id}"),
    ]
    ])
    try:
    await bot.send_message(ADMIN_ID, admin_message, reply_markup=admin_keyboard)
    log.info(f"Заявка успешно отправлена администратору: {admin_message}")
    except Exception as e:
    log.exception(f"Ошибка при отправке заявки администратору: {e}")

    @dp.callback_query(lambda query: query.data.startswith("admin_"))
    async def process_admin_callback(callback: types.CallbackQuery):
    action, user_id = callback.data.split(":")
    user_id = int(user_id)
    log.info(f"Администратор нажал {action} для пользователя {user_id}")

    if action == "admin_accept":
    try:
    await bot.send_message(user_id, "Администратор одобрил твою заявку! Пропишите /start")
    await callback.answer("Заявка принята")
    AUTHORIZED_USERS.add(user_id) # добавляем пользователя в список
    log.info(f"Пользователь {user_id} добавлен в AUTHORIZED_USERS")

    try:
    with open(AUTHORIZED_USERS_FILE, "w") as f:
    json.dump(list(AUTHORIZED_USERS), f)
    log.info(f"Saved AUTHORIZED_USERS to {AUTHORIZED_USERS_FILE}")
    except Exception as e:
    log.exception(f"Error saving AUTHORIZED_USERS to {AUTHORIZED_USERS_FILE}: {e}")

    except TelegramForbiddenError:
    log.error(f"Не удалось отправить сообщение пользователю {user_id}, он заблокировал бота")
    await callback.answer(f"Не удалось отправить сообщение пользователю {user_id}, он заблокировал бота")
    except Exception as e:
    log.exception(f"Ошибка при отправке сообщения пользователю {user_id}: {e}")
    await callback.answer("Произошла ошибка")

    elif action == "admin_decline":
    try:
    await bot.send_message(user_id, "Администратор отклонил вашу заявку. Пожалуйста, попробуйте еще раз.")
    await callback.answer("Заявка отклонена")
    except TelegramForbiddenError:
    log.error(f"Не удалось отправить сообщение пользователю {user_id}, он заблокировал бота")
    await callback.answer(f"Не удалось отправить сообщение пользователю {user_id}, он заблокировал бота")
    except Exception as e:
    log.exception(f"Ошибка при отправке сообщения пользователю {user_id}: {e}")
    await callback.answer("Произошла ошибка")
    else:
    await callback.answer("Неизвестное действие администратора")

    # Запуск бота
    async def main():
    try:
    await dp.start_polling(bot)
    finally:
    await bot.session.close()

    if __name__ == "__main__":
    asyncio.run(main())
    Буду рад, если оцените мою работу!
     
  2. MaltoBone
    MaltoBone 2 мар 2025 1 14 сен 2024
    Щас будет немного душно (я нихуя не профессионал, так что :falling: )

    1. Текст нельзя хранить в таком "сыром" виде, так как это загромождает код. Лучше либо хранить его в json-файле, либо ухитряться как-то ещё
    2. Всякие токены и прочие х, которые никто не должен видеть люд, лучше хранить в переменных среды (в файле .env короче), либо в файлах .ini
    3. При выборе языка разметки принято (почему-то, я сам хз с хуя) использовать MarkDownV2
    4. У тя повторяются обработчики TelegramForbiddenError на случай, если пользователь блокает бота, что загромождает код. Я бы на твоём месте сделал чекер через middleware

    Вердикт: Я приебался с нихуя, а так код годно написал чат гптшник
     
    2 мар 2025 Изменено
    1. K1p1k
      MaltoBone,
      Кто сказал?
      Там косяков много
      6 мар 2025 Изменено
    2. MaltoBone
      K1p1k, сказало сообщество, по поводу косяков хз:hmm:
      Сам лично html использую при форматировании текста, но кучу раз слышал претензии на этот счёт в свой адрес
  3. shimichi
    shimichi 2 мар 2025 скамлю на кальяны дарксайд 121 16 окт 2019
    точнее работу чата гпт ?)
     
    1. foksi777 Автор темы
      shimichi, не, гпт только скелет
  4. zxcFlezyi
    zxcFlezyi 2 мар 2025 65 26 окт 2024
    годно, возьму на вооружение

    за старание накину симп
     
  5. ФРУТС
    ФРУТС 2 мар 2025 <3 jenna ortega E> 544 7 фев 2023
    реальНО?За такое симпатии кидают?

    я в шоках..
     
  6. coolcool99
    coolcool99 2 мар 2025 Заблокирован(а) 751 14 мар 2024
    молю юзай json или secrets для токена
     
    1. Посмотреть предыдущие комментарии (1)
    2. coolcool99
      coolcool99, или конфиг хз но не мейн
Top
Загрузка...