• Добро пожаловать на сайт - wlux.net!

    FAQ по форуму

    1. Все сообщения до группы местный проходят модерацию от 1 минуты до 24 часа

    2. Сообщения учитываються в следующих разделах: Читать

    3.Что-бы скачать вложение нужно 2 сообщения.

    4.Личные переписки работают только с Администрацией форума

    5. Запрещено: Просить скрытый текст , спам, реклама, скам, ддос, кардинг и другая чернуха, нарушать любые законы РФ/СНГ = бан аккаунта

    6. Внимание! Мы не удаляем аккаунты с форума! Будьте внимательны ДО регистрации! Как удалить аккаунт на форуме?!

    5.Не понимаю, как и что тут работает у вас?!Как создавать темы, писать сообщения, как получать реакции. Почему не засчитывает сообщения. Все ответы здесь

This is a mobile optimized page that loads fast, if you want to load the real page, click this text.

python Гайд Создаём Telegram бота на Python + Aiogram

Оффлайн

wlux.net

Где волчьи уши, там волчьи зубы.
Команда форума
LV
7
 
20.06.2022
23 868
218
36
Награды
10
Пол
Муж.

Репутация:

  • Автор темы
  • Администратор
  • Модератор
  • Команда форума
  • #1


Постараюсь объяснить основные аспекты создания бота в Telegram на Python с поддержкой библиотеки Aiogram.

1. Создаём необходимые файлы

Создаём папку с названием нашего Бота, в ней три файла: main.py , keyboard.py , config.py
Открываем эти файлы в любом текстовом редакторе ( я использую Sublime, ибо удобно переключаться между файлами + дизайн ).



2. Импорт модулей и компонентов
Устанавливаем библиотеку с помощью pip в консоли
Код:
pip install -U aiogram

Импортируем необходимое
Код:
# -*- coding: utf8 -*-
################################################################################################################################
from aiogram import Bot, types
from aiogram.utils import executor
from aiogram.dispatcher import Dispatcher
from aiogram.types import ReplyKeyboardRemove, ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton
import asyncio
#################################################################################################################################

######################################################################
from aiogram.dispatcher import FSMContext                            ## ТО, ЧЕГО ВЫ ЖДАЛИ - FSM
from aiogram.dispatcher.filters import Command                        ## ТО, ЧЕГО ВЫ ЖДАЛИ - FSM
from aiogram.contrib.fsm_storage.memory import MemoryStorage        ## ТО, ЧЕГО ВЫ ЖДАЛИ - FSM
from aiogram.dispatcher.filters.state import StatesGroup, State        ## ТО, ЧЕГО ВЫ ЖДАЛИ - FSM
######################################################################

######################
import config        ## ИМПОРТИРУЕМ ДАННЫЕ ИЗ ФАЙЛОВ config.py
import keyboard        ## ИМПОРТИРУЕМ ДАННЫЕ ИЗ ФАЙЛОВ keyboard.py
######################

import logging # ПРОСТО ВЫВОДИТ В КОНСОЛЬ ИНФОРМАЦИЮ, КОГДА БОТ ЗАПУСТИТСЯ

Подключаем токен нашего Бота
Код:
storage = MemoryStorage() # FOR FSM
bot = Bot(token=config.botkey, parse_mode=types.ParseMode.HTML)
dp = Dispatcher(bot, storage=storage)

logging.basicConfig(format=u'%(filename)s [LINE:%(lineno)d] #%(levelname)-8s [%(asctime)s]  %(message)s',
                    level=logging.INFO,
                    )

Попутно с этим заходим в config.py и прописываем наш ключ с BotFather :
Код:
Попутно с этим заходим в config.py и прописываем наш ключ с BotFather :
Важно! Не забывайте сохранять все действия в файле CTRL+S

3. Первая команда, альтернативная замена БД и обычные кнопки


Перед тем как начать с команды старт, надо добавить кнопки, которые будут появляться при вводе команды.
Открываем keyboard.py и пишем такие строки, в начале импортируя библиотеку.

Код:
from aiogram import Bot, types
from aiogram.types import ReplyKeyboardRemove, ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton

######################################################
start = types.ReplyKeyboardMarkup(resize_keyboard=True) # СОЗДАЕМ ВООБЩЕ ОСНОВУ ДЛЯ КНОПОК

info = types.KeyboardButton("Информация")            # ДОБАВЛЯЕМ КНОПКУ ИНФОРМАЦИИ
stats = types.KeyboardButton("Статистика")            # ДОБАВЛЯЕМ КНОПКУ СТАТИСТИКИ

start.add(stats, info) #ДОБАВЛЯЕМ ИХ В БОТА

Вернулись в main.py
Мы создаём бота, который может собирать статистику и делать рассылку. Значит, для начала, надо научить его записывать id пользователя, который отправил команду /start.
Для этого создаём текстовик user.txt в папке с ботом.



Начнём с команды /start

Код:
@dp.message_handler(Command("start"), state=None)

async def welcome(message):
    joinedFile = open("user.txt","r")
    joinedUsers = set ()
    for line in joinedFile:
        joinedUsers.add(line.strip())

    if not str(message.chat.id) in joinedUsers:
        joinedFile = open("user.txt","a")
        joinedFile.write(str(message.chat.id)+ "\n")
        joinedUsers.add(message.chat.id)

    await bot.send_message(message.chat.id, f"ПРИВЕТ, *{message.from_user.first_name},* БОТ РАБОТАЕТ", reply_markup=keyboard.start, parse_mode='Markdown')

Что мы сделали?
Чтобы бот работал без остановок после выполнения команд, прописываем в самом конце main.py

Код:
##############################################################
if __name__ == '__main__':
    print('Монстр пчелы запущен!')                                    # ЧТОБЫ БОТ РАБОТАЛ ВСЕГДА с выводом в начале вашего любого текста
executor.start_polling(dp)
##############################################################

Запускаем бота, через файл main.py.

Если у вас так-же - Вы всё сделали правильно, можно идти к самому боту.



Отправляем команду /start



Всё работает. Смотрим в файлик user.txt. Наш ID записался.

Важно! Кнопки не нажимаются, потому что в них ничего не добавили. Если нажмете на кнопку - выдаст ошибку в консоли ( кнопка никуда не ведёт ), но бот будет работать.

4. Оживляем обычные кнопки


Попробуем оживить кнопку "Информация" ?
Простенькие строчки, чтобы бот ответил на кнопку.

Код:
@dp.message_handler(content_types=['text'])
async def get_message(message):
    if message.text == "Информация":
        await bot.send_message(message.chat.id, text = "Информация\nБот создан специально для моих любимых девочек и мальчиков с lzt ", parse_mode='Markdown')

5. Вывод статистики (Inline-кнопки, callback_data)


Отлично. Кнопку оживили, но запускать пока что не будем. Добавим просмотр статистики, при помощи Inline-кнопки, callback_data, да еще и админку прикрутим)
Заходим в keyboard.py и пишем следующее

Код:
stats = InlineKeyboardMarkup()    # СОЗДАЁМ ОСНОВУ ДЛЯ ИНЛАЙН КНОПКИ
stats.add(InlineKeyboardButton(f'Да', callback_data = 'join')) # СОЗДАЁМ КНОПКУ И КАЛБЭК К НЕЙ
stats.add(InlineKeyboardButton(f'Нет', callback_data = 'cancle')) # СОЗДАЁМ КНОПКУ И КАЛБЭК К НЕЙ

Так же, как мы делали обычные кнопки, но оформлено по эстетики Inline-кнопки

Теперь заходим в config.py
Пишем наш ID для админки
Взять его можно с нашего файла user.txt


Код:
botkey = '1770592647:AAHrIpW5XW6jYKmB56Kg63r_2LcCK8gOKtg' # ТОКЕН С BOTFATHER
admin = 1212341234

Возвращаемся в main.py и дополняем код.
Оживляем кнопку статистика.

Код:
@dp.message_handler(content_types=['text'])
async def get_message(message):
   if message.text == "Информация":
       await bot.send_message(message.chat.id, text = "Информация\nБот создан специально для моих любимых девочек и мальчиков с lzt ", parse_mode='Markdown')


   if message.text == "Статистика":
       await bot.send_message(message.chat.id, text = "Хочешь просмотреть статистику бота?", reply_markup=keyboard.stats, parse_mode='Markdown')

Далее прописываем "Ловлю callback" и что должно при этом выполняться.
Сделаем фичу, чтобы при нажатии на "да" Бот присылал не новое сообщение, а редактировал старое (выглядит более эстетично), выводя при этом количество пользователей бота.
Нам надо посчитать все строчки ( ID ) с текстовика user.txt и вывести их количество.

Всё это выглядит вот так

Код:
@dp.callback_query_handler(text_contains='join') # МЫ ПРОПИСЫВАЛИ В КНОПКАХ КАЛЛБЭК "JOIN" ЗНАЧИТ И ТУТ МЫ ЛОВИМ "JOIN"
async def join(call: types.CallbackQuery):
   if call.message.chat.id == config.admin:
       d = sum(1 for line in open('user.txt'))
       await bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text=f'Вот статистика бота: *{d}* человек', parse_mode='Markdown')
   else:
       await bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text = "У тебя нет админки\n Куда ты полез", parse_mode='Markdown')



@dp.callback_query_handler(text_contains='cancle') # МЫ ПРОПИСЫВАЛИ В КНОПКАХ КАЛЛБЭК "cancle" ЗНАЧИТ И ТУТ МЫ ЛОВИМ "cancle"
async def cancle(call: types.CallbackQuery):
   await bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text= "Ты вернулся В главное меню. Жми опять кнопки", parse_mode='Markdown')

Зачем f перед кавычками?
У нас есть значение d которое содержит в себе количество строк. f-строки вступают в дело, чтобы помочь с форматированием.
Грубо говоря без f нашу несчастную d посчитают за текст.

Пора запускать бота.
Жмем "Статистика"






Эти же действия, но без админки



Нажали "Информация"



6. Рассылка пользователям бота (+ отправка фотографии)

Делаем рассылку пользователям. Решил сделать так, чтобы с текстом отправлялась еще и фотка.
Скидываем фотку в нашу папку с ботом. Переименовываем её во что-то красивое.

Код:
@dp.message_handler(commands=['rassilka'])
async def rassilka(message):
   if message.chat.id == config.admin:
       await bot.send_message(message.chat.id, f"*Рассылка началась \nБот оповестит когда рассылку закончит*", parse_mode='Markdown')
       receive_users, block_users = 0, 0
       joinedFile = open ("user.txt", "r")
       jionedUsers = set ()
       for line in joinedFile:
           jionedUsers.add(line.strip())
       joinedFile.close()
       for user in jionedUsers:
           try:
               await bot.send_photo(user, open('lzt.jpg', 'rb'), message.text[message.text.find(' '):])
               receive_users += 1
           except:
               block_users += 1
           await asyncio.sleep(0.4)
       await bot.send_message(message.chat.id, f"*Рассылка была завершена *\n"
                                                             f"получили сообщение: *{receive_users}*\n"
                                                             f"заблокировали бота: *{block_users}*", parse_mode='Markdown')

Важно! Вставляем этот код сразу же после хэндлера со стартом.
Проверяйте какого фотка типа. У меня это jpg, поэтому я и пишу в коде .jpg


Коротко про код :


Запускаем бота и проверяем.




7. FSM


Приступим.
Создаём наши "БД" два файла в папку с ботом: link.txt и

Пожалуйста, войдите или зерегистрируйтесь, чтобы увидеть скрытый текст.

в них будут храниться наши ответы.
Переходим в main.py Я поместил код для этого выше старта, ибо всё, что связанно с FMS и State лучше писать в начале, дабы посреди основного кода он не отвлекал)

Прописываем State-группу. Называем её meinfo.


Код:
class meinfo(StatesGroup):   
    Q1 = State()
    Q2 = State()

Теперь пишем, когда же бот начнет слушать наши ответы.

Код:
class meinfo(StatesGroup):
   Q1 = State()
   Q2 = State()

@dp.message_handler(Command("me"), state=None)       # Создаем команду /me для админа.
async def enter_meinfo(message: types.Message):
   if message.chat.id == config.admin:         
       await message.answer("начинаем настройку.\n"       # Бот спрашивает ссылку
                        "№1 Введите линк на ваш профиль")

       await meinfo.Q1.set()                                   # и начинает ждать наш ответ.
@dp.message_handler(state=meinfo.Q1)                               # Как только бот получит ответ, вот это выполнится
async def answer_q1(message: types.Message, state: FSMContext):
   answer = message.text
   await state.update_data(answer1=answer)                           # тут же он записывает наш ответ (наш линк)

   await message.answer("Линк сохранён. \n"
                        "№2 Введите текст.")
   await meinfo.Q2.set()                                   # дальше ждёт пока мы введем текст


@dp.message_handler(state=meinfo.Q2)                   # Текст пришел а значит переходим к этому шагу
async def answer_q1(message: types.Message, state: FSMContext):
   answer = message.text
   await state.update_data(answer2=answer)               # опять же он записывает второй ответ

   await message.answer("Текст сохранён.")

   data = await state.get_data()               #
   answer1 = data.get("answer1")               # тут он сует ответы в переменную, чтобы сохранить их в "БД" и вывести в след. сообщении
   answer2 = data.get("answer2")               #

   joinedFile = open("link.txt","w", encoding="utf-8")       # Вносим в "БД" encoding="utf-8" НУЖЕН ДЛЯ ТОГО, ЧТОБЫ ЗАПИСЫВАЛИСЬ СМАЙЛИКИ
   joinedFile.write(str(answer1))
   joinedFile = open("text.txt","w", encoding="utf-8")       # Вносим в "БД" encoding="utf-8" НУЖЕН ДЛЯ ТОГО, ЧТОБЫ ЗАПИСЫВАЛИСЬ СМАЙЛИКИ
   joinedFile.write(str(answer2))

   await message.answer(f'Ваша ссылка на профиль : {answer1}\nВаш текст:\n{answer2}')   # Ну и выводим линк с текстом который бот записал

   await state.finish()

Запускаем проверяем.
Вводим команду /me



Всё работает и сохранилось в нашу "БД" текстовики link.txt и text.txt
Теперь создаём кнопку "Разработчик"
В keyboard.py добавляем к основным кнопкам еще одну.
Я ее не записал через запятую, а опустил ниже, чтобы она была одна снизу двух других кнопок.

Код:
from aiogram import Bot, types
from aiogram.types import ReplyKeyboardRemove, ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton

######################################################
start = types.ReplyKeyboardMarkup(resize_keyboard=True) # СОЗДАЕМ ВООБЩЕ ОСНОВУ ДЛЯ КНОПОК

info = types.KeyboardButton("Информация")           # ДОБАВЛЯЕМ КНОПКУ ИНФОРМАЦИИ
stats = types.KeyboardButton("Статистика")           # ДОБАВЛЯЕМ КНОПКУ СТАТИСТИКИ
razrab = types.KeyboardButton("Разработчик")           # ДОБАВЛЯЕМ КНОПКУ РАЗРАБОТЧИК

start.add(stats, info) #ДОБАВЛЯЕМ ИХ В БОТА
start.add(razrab)
######################################################
######################################################

stats = InlineKeyboardMarkup()   # СОЗДАЁМ ОСНОВУ ДЛЯ ИНЛАЙН КНОПКИ
stats.add(InlineKeyboardButton(f'Да', callback_data = 'join')) # СОЗДАЁМ КНОПКУ И КАЛБЭК К НЕЙ
stats.add(InlineKeyboardButton(f'Нет', callback_data = 'cancle')) # СОЗДАЁМ КНОПКУ И КАЛБЭК К НЕЙ

######################################################

В main.py, где @dp.message_handler(content_types=['text'])
Прописываем следующее

Код:
@dp.message_handler(content_types=['text'])
async def get_message(message):
   if message.text == "Информация":
       await bot.send_message(message.chat.id, text = "Информация\nБот создан специально для моих любимых девочек и мальчиков с lzt ", parse_mode='Markdown')


   if message.text == "Статистика":
       await bot.send_message(message.chat.id, text = "Хочешь просмотреть статистику бота?", reply_markup=keyboard.stats, parse_mode='Markdown')

   if message.text == "Разработчик":
       link1 = open('link.txt', encoding="utf-8") # Вытаскиваем с нашей "БД" инфу, помещаем в переменную и выводим её
       link = link1.read()

       text1 = open('text.txt', encoding="utf-8") # Вытаскиваем с нашей "БД" инфу, помещаем в переменную и выводим её
       text = text1.read()

       await bot.send_message(message.chat.id, text = f"Создатель: {link}\n{text}", parse_mode='Markdown')

Запускаем, проверяем. Прописываем /start заново, чтобы новая кнопка появилась.



Отлично. Всё работает. Если сменить опять данные через /me, то при нажатии на "Разработчик" будут уже другие ваши текст и ссылка.
 
F Оффлайн

flxsh

Участник
LV
0
 
16.03.2024
2
0
6
28

Репутация:

классный гайд, все понравилось
 
Оффлайн

inoken

Участник
LV
2
 
18.03.2024
2
0
25
Награды
2
19

Репутация:

Классный гайд, спасибо большое хы
 
H Оффлайн

Honest_im

Участник
LV
0
 
19.03.2024
2
0
5
20

Репутация:

Как-то сложно всё. Рановато такое для новичка в python.
 
E Оффлайн

er1s

Участник
LV
2
 
19.03.2024
2
0
11
Награды
2
25

Репутация:

для новичков самое то
 
Оффлайн

grreeeuuu

Местный
Участник
LV
2
 
18.01.2024
55
0
31
Награды
3
Пол
Жен.

Репутация:

очень хороший гайд, всё по полочке разложил. моя благодарность)
 
Оффлайн

tyrboflai

Участник
LV
0
 
11.10.2024
1
0
7
Награды
1
39

Репутация:

Подскажите как Импортируем необходимое
?
 
K Оффлайн

kotriffiquoge-2043

Участник
LV
0
 
16.10.2024
9
0
6
Пол
Муж.

Репутация:

Не хватает пункта с получением токена от BotFather, или хотя бы ссылки на гайд.

Если кто-то застрял на получении токена -

Пожалуйста, войдите или зерегистрируйтесь, чтобы увидеть скрытый текст.

.
 

Поиск по форуму

Похожие темы:

Данный сайт использует cookie. Вы должны принять их для продолжения использования. Узнать больше....