Код на салфетке
2.22K subscribers
746 photos
14 videos
2 files
788 links
Канал для тех, кому интересно программирование на Python и не только.

Сайт: https://pressanybutton.ru/
Чат: https://t.iss.one/+Li2vbxfWo0Q4ZDk6
Заметки автора: @writeanynotes

Реклама и взаимопиар: @Murzyev1995
Сотрудничество и др.: @proDreams
Download Telegram
Создадим функцию get_path, получающую аргумент code.
В теле функции создадим переменную response и получим в неё ответ на запрос. Запрос будет отправлять при помощи метода requests.get(), в параметры которого передадим API_URL + f'get-file/?code={code}'.
В случае, если получим от API данные, тогда возвращаем из функции ответ в виде JSON.
Если же данных не будет(значит, что файла с таким кодом нет), вернём None.
import requests

API_URL = 'https://127.0.0.1:8000/bot/'


def get_path(code):
response = requests.get(API_URL + f"get-file/?code={code}")
if response:
return response.json()
return None

И для уверенности, что всё работает можно прямо здесь и протестировать.
После функции напишем print(get_path(0)), запустим Django в отдельном окне IDE и запустим наш скрипт. В выводе терминала должны получить JSON, похожий на питоновский словарь.
{'title': 'Тестовый файл', 'file_path': 'C:\\Users\\proDream\\PycharmProjects\\pressanybutton\\pressanybutton\\media\\post_files\\68.zip'}

Отлично. API отрабатывает. Удалим принт, что бы при вызове функции не было лишних вызовов.

Подготовим всё необходимое к следующему посту.
В этом же пакете utils создадим файл statesform.py и commands.py. В файле statesform.py мы будем хранить группы состояний для машины состояний. В файле commands.py будет список команд бота, которые будут отображаться в виде кнопки меню у пользователя.

Давайте сразу пропишем будущие команды, пусть их пока и нет. Откроем файл commands.py и напишем асинхронную функцию set_commands в аргументы которой будет передаваться экземпляр класса Bot.
В теле функции создадим переменную commands и присвоим ей список. В списке будут находиться объекты класса BotCommand, в параметры которого передаётся команда и описание. Ниже запустим метод, присваивающий написанный ранее список команд нашему боту.
from aiogram import Bot
from aiogram.types import BotCommand, BotCommandScopeDefault


async def set_commands(bot: Bot):
commands = [
BotCommand(
command='start',
description='Начало работы'
),
BotCommand(
command='get_file',
description='Получить материалы'
),
BotCommand(
command='about',
description='Информация о боте'
)
]

await bot.set_my_commands(commands, BotCommandScopeDefault())
Откроем файл events.py в пакете handlers. В функции start_bot перед отправкой сообщения добавим добавление команд в меню:
from botlogic.utils.commands import set_commands


async def start_bot():
await set_commands(bot)
await bot.send_message(Secrets.admin_id, start_bot_msg())

В следующем посте начнём писать команду get_file.

Файлы к посту, можно получить в боте по коду: 733286
Пост на сайте.
Поддержать канал.

#aiogram #python #api #json #команды #меню
👍2
AIOgram3 8.1 Команда отправки файла

Работы много, по этому без лишних слов, приступим!

В пакете handlers создадим файл send_file.py и откроем его. Так же сразу откроем файл main.py, views.py и statesform.py. В основном работать будем в send_file.py, но другие три тоже будут нужны.

В файле send_file.py создадим асинхронную функцию send_file_start, в качестве аргументов она будет получать объект типа Message и FSMContext.
FSMContext - это асинхронный контекст, который хранит информацию о текущем состоянии пользователя во время работы Telegram-бота. Он предоставляет функции для переключения между состояниями, сохранения и извлечения данных, а также другие операции, связанные с управлением состояниями.
👍3
Перейдём в views.py и создадим функцию send_file_start_msg, возвращающую строку с сообщением для пользователя.
def send_file_start_msg():
return """Для получения файла с дополнительными материалами к посту,
пожалуйста введите код из поста."""

Теперь перейдём в файл statesform.py и создадим класс SendFileSteps унаследованный от StatesGroup.
Пропишем первое поле, он же шаг в машине состояний.
from aiogram.fsm.state import StatesGroup, State


class SendFileSteps(StatesGroup):
get_code_from_user = State()

Вернёмся в send_file.py и в теле функции напишем отправку сообщения пользователю и переход к следующему шагу.
from aiogram.fsm.context import FSMContext
from aiogram.types import Message

from botlogic import views
from botlogic.utils.statesform import SendFileSteps


async def send_file_start(message: Message, state: FSMContext):
await message.answer(views.send_file_start_msg())
await state.set_state(SendFileSteps.get_code_from_user)

Перейдём в файл main.py и после обработки событий запуска/остановки, зарегистрируем функцию на обработку команды get_file:
from aiogram.filters import Command  

from botlogic.handlers import send_file


dp.message.register(send_file.send_file_start, Command(commands='get_file'))
При регистрации функции echo, мы не указывали второго параметра, поскольку нам надо было обрабатывать все входящие сообщения. Здесь мы указали вторым параметром объект класса Command, являющийся фильтром.

Первый шаг готов. Что тут происходит? При вызове команды, запускается машина состояний, тем самым все вводимые команды будут проигнорированы, а сообщения будут обработаны так, как этого требует логика.
После того как запустилась машина, пользователю отправляется сообщение, о необходимости ввести код и до тех пор, пока пользователь не отправит сообщение, перехода на следующий шаг не будет. Когда пользователь отправит сообщение, машина сменит состояние на следующую функцию.

Файлы к посту, можно получить в боте по коду: 523628
Пост на сайте.
Поддержать канал.

#aiogram #python #команды #меню #регистрация
AIOgram3 8.2 Команда отправки файла, продолжение

Продолжим с того, на чём остановились.
В файле send_file.py напишем вторую асинхронную функцию send_file_get_data, она так же принимает объект Message и FSMContext.
В
предыдущей функции send_file_start мы получили от пользователя код файла, теперь необходимо выполнить запрос данных по API.
Делаем проверку на введённые данные, если там не только цифры, то отправляем пользователю сообщение, что код неверный и повторно ожидаем ввода. Пропишем сообщение в файле views.py в функции send_file_wrong_input.
Если формат верный, то в блоке if отправляем сообщение из функции send_file_please_wait во views.py, что запрос выполняется.
Здесь же, в блоке if, создаём переменную data и выполняем функцию get_path из файла api_actions.py, передавая в неё текст сообщения от пользователя.
Далее у нас снова проверка, в этот раз на содержимое переменной data, если она пустая, то отправляем пользователю сообщение, что файл не найден и нужно попробовать снова.
Если же в переменной data есть необходимые данные, то создаём переменную file и присваиваем ей объект класса FSInputFile, в параметры которого, передаём путь до файла полученный из переменной data.
Удаляем предыдущее сообщение о выполнении запроса и отправляем файл.
В метод отправки файла передаём chat_id, переменную с путём до файла и подпись к файлу из функции file_caption в файле views.py.
А потом закрываем машину состояний.

Код:
from aiogram.fsm.context import FSMContext
from aiogram.types import Message, FSInputFile

from botlogic import views
from botlogic.settings import bot
from botlogic.utils import api_actions

async def send_file_get_data(message: Message, state: FSMContext):
if message.text.isdigit():
await message.answer(views.send_file_please_wait())
data = api_actions.get_path(message.text)
if data:
file = FSInputFile(path=data['file_path'])
await bot.delete_message(message.chat.id, message.message_id + 1)
await bot.send_document(message.chat.id, document=file, caption=views.file_caption(data['title']))
await state.clear()
else:
await message.answer(views.send_file_not_found())
else:
await message.answer(views.send_file_wrong_input())

Осталось зарегистрировать в файле main.py:
    dp.message.register(send_file.send_file_get_data, SendFileSteps.get_code_from_user)

Можем проверять. Запустим Django в отдельном окне и запустим бота.
Перейдя в бота напишем нашу команду /get_file и в ответ на запрос код файла 0.
И бот в ответ пришлёт файл.

Надеюсь, что и у вас всё заработало как надо, если же нет, пишите вопросы и проблемы с которыми вы столкнулись в комментариях.

Файлы к посту, можно получить в боте по коду: 715723
Пост на сайте.
Поддержать канал.

#aiogram #python #команды #меню #fsm #машина_состояний
👍1
Поправка к посту Django 8 Первая модель.

Как верно подметил Кирилл в чате, если сделать несколько файлов с одинаковым кодом, то при запросе, вылетит ошибка, поскольку мы ищем только один файл с указанным кодом, а на деле их несколько.

Для исправления этого, необходимо в коде модели, в поле code добавить параметр unique=True.
    code = models.IntegerField(default=0,
verbose_name='Код файла',
unique=True)

И применить миграции:
python manage.py makemigrations

python manage.py migrate
👍1
Приветствую.

Пообщавшись в чате с подписчиками, понял, какие интересные и разнообразные личности подписаны на канал и мне стало интересно, откуда вы пришли.
Anonymous Poll
48%
Учусь в GeekBrains 😐
3%
Я с пикабу! 🥳
14%
Нашёл в интернете 🧐
24%
Сам же пригласил 😂
10%
Не скажу 😉
Django 12. Настройка отправки почты

Для большинства сайтов важно иметь возможность отправлять письма пользователям, будь то письмо для сброса пароля или информационная рассылка.

В Django встроен функционал по отправке, однако ему всё же требуется почтовый сервер для отправки почты.

И тут возможны несколько вариантов:
1. Почта будет отправляться через почтовые сервисы, такие как Яндекс, Google или Mail.ru. В таком случае, адрес с которого отправляются письма, будет вида: <название_сайта@gmail.com>, <название_сайта@yandex.ru> или любой другой почтовой службы. Плюс этого способа в том, что он бесплатен и прост в реализации. Минусом конечно же является то, что пользователь вашего сайта, будет получать письмо не от вашего домена, а от сервиса.
👍1
2. Приобрести почтовый сервис для домена. Такая услуга есть и у Яндекса и у Mail.ru и у большинства хостинг провайдеров. В таком случае, у вас будет почтовый адрес вида <info@ваш_домен>. Этот вариант куда привлекательнее, предыдущего. Пользователь будет видеть домен сайта в письме и это положительно скажется. Минусом же является то, что всё стоит денег.
3. Поднять собственный почтовый сервер на VPS. Этот способ позволит контролировать всё, что касается почты и ограничен лишь мощностью сервера и его дисковым пространством. Он достаточно сложен в исполнении, но при этом гарантирует независимость.
Третий вариант отложим на будущее, возможно я напишу, как развернуть свой почтовый сервер.
Остаются первые два пункта, в целом, в плане настроек Django они одинаковые.

Приступим.
Откроем файл settings.py и в самом конце добавим следующий код:
# Настройка почты
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

EMAIL_HOST = 'smtp.yandex.ru'
EMAIL_PORT = 465
EMAIL_HOST_USER = ""
EMAIL_HOST_PASSWORD = ""
EMAIL_USE_TLS = False
EMAIL_USE_SSL = True
SERVER_EMAIL = EMAIL_HOST_USER
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

Разберём по порядку:
- EMAIL_BACKEND - тут мы указываем, какой модуль будет отвечать за отправку почты. Выбираем стандартный для работы по протоколу SMTP.
- EMAIL_HOST - тут мы указываем почтовый сервер. В примере выше, это сервер Яндекс почты, для Gmail это smtp.gmail.com, для других сервисов сервер исходящей почты обычно прописан в справке.
- EMAIL_PORT - порт для подключения к серверу. Обычно это 465, но может и отличаться, читайте справку к интересующему вас серверу.
- EMAIL_HOST_USER и EMAIL_HOST_PASSWORD - в этих полях определяется логин и пароль для подключения к почтовому серверу. Обратите внимание, в качестве логина, передаётся полностью адрес электронной почты!
- EMAIL_USE_TLS и EMAIL_USE_SSL - два параметра определяющих какой тип шифрования используется. Используемый тип, смотрите в справке к почтовому серверу. Обратите внимание, что только один из параметров может быть True, второй обязательно должен быть False!
- И последние два параметра, определяют настройки адреса с которого будет исходить почта.

На этом настройка почты закончена. Ничего сложного, не правда ли? Осталось протестировать, этим займёмся в следующем посте.

Файлы к посту, можно получить в боте по коду: 202223
Пост на сайте.
Поддержать канал.

#django #python #отправка_почты #email
👍1
Django 13. Сброс пароля

Поскольку на сайте пока ничего нет, тестировать будем в админке.
По умолчанию, в окне входа в панель администратора нет кнопки сброса пароля, но такая возможность предусмотрена.

Откроем файл urls.py в директории проекта и в список urlpatterns добавим четыре строки в начало:
from django.contrib.auth import views as auth_views

urlpatterns = [
path('admin/password_reset/', auth_views.PasswordResetView.as_view(), name='admin_password_reset'),
path('admin/password_reset/done/', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'),
path('admin/reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('admin/reset/done/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
path('admin/', admin.site.urls),
path('', include('blog.urls', namespace='blog')),
]
👍1
Обратите внимание, новые строки расположены до паттерна входа в панель администратора. Это обусловлено тем, что список читается сверху вниз и если добавить в конец списка, то наши паттерны будут игнорироваться и перекрываться основным, ведущим на страницу авторизации.

Запустим Django и перейдём на страницу авторизации, если вы уже авторизованы в панели, просто в правом верхнем углу нажмите "Выйти".
Над кнопкой входа должна появиться надпись "Забыли свой пароль или имя пользователя?".

При нажатии на неё, откроется страница ввода адреса электронной почты.
Внимание! Если вы при создании суперпользователя не ввели адрес электронной почты, то дальше ничего не получится. Необходимо зайти в панель администратора, в разделе "Пользователи" выбрать вашего пользователя и в соответствующем пункте прописать адрес вашей почты, после чего сохранить и повторить действия.

Вводим адрес электронной почты и нажимаем "Восстановить мой пароль".

На следующей странице увидим сообщение, что письмо отправлено. Перейдём в нашу почту и там уже должно быть письмо. При условии, что вы указали настройки почтового сервера из прошлого поста!

Если письмо пришло, поздравляю! Переходить по ссылке не обязательно, если только не хотите поменять пароль на другой.

Файлы к посту, можно получить в боте по коду: 469410
Пост на сайте.
Поддержать канал.

#django #python #email #сброс_пароля #админка #admin
👍1
Приветствую!

Сегодня запустил бота для канала.
Бот пока умеет совсем не много, а именно у него пока-что, всего одна задача - выдавать материалы к посту.

Для получения архива с файлами, нужно запустить бота, ввести команду /get_file и код из поста.
В ответ придёт сообщение с файлом.

Ссылка на бота: https://t.iss.one/press_any_button_bot

Вполне вероятно, что могут быть какие-либо ошибки или недочёты, если столкнулись с ними, обязательно напишите в комментариях или чате.

А так же если у вас есть интересные идеи для функционала, тоже пишите.

#Новости
Django 14. Модель пользователя бота

Продолжим добавлять функционал боту и Django. Сегодня сделаем модель для пользователя ботом. Это позволит получать статистику по использованию бота прямо в панели администратора Django.

Перейдём в файл models.py в директории приложения и по аналогии с предыдущей моделью, создадим новый класс BotUserModel.
И создадим несколько полей:
class BotUserModel(models.Model):
chat_id = models.BigIntegerField(primary_key=True)
first_name = models.CharField(max_length=50,
verbose_name='Имя')
last_name = models.CharField(max_length=50,
blank=True,
null=True,
verbose_name='Фамилия')
username = models.CharField(max_length=50,
blank=True,
null=True)
created = models.DateTimeField(auto_now_add=True,
verbose_name='Зарегистрирован')
updated = models.DateTimeField(auto_now=True,
verbose_name='Последняя активность')
Разберём, что тут новое:
- В поле chat_id, указали, что это поле является Первичным ключом. То есть, это поле уникально. И использовали поле типа BigIntegerField, поскольку значения Telegram-ID выходят за границы базового IntegerField.
- В полях last_name и username добавили два параметра. blank означает, что поле может быть пустым, а null означает, что оно может иметь значение NULL. Это обусловлено тем, что имя у пользователя Telegram обязательно к заполнению, а вот фамилия или имя пользователя - нет.
- В поле created мы присваиваем текущую, локальную дату(дату сервера). При последующем обновлении модели, это поле не будет изменяться, если конечно его не изменить намерено.
- Поле updated напротив, будет при каждом обновлении модели принимать значение текущего времени.

Добавим базового менеджера, Мета-класс и dunder-метод __str__:
    objects = models.Manager()

class Meta:
ordering = ['-updated']
verbose_name = 'Пользователь бота'
verbose_name_plural = 'Пользователи бота'

def __str__(self):
return self.first_name
В переменную objects мы поместили экземпляр класса Manager. Менеджеры, это удобный способ взаимодействия с объектами в базе данных. С помощью них получаем данные, фильтруем, создаём. В будущем мы переопределим своих менеджеров, но пока достаточно базового.
Из нового в классе Meta только пункт ordering определяющий порядок сортировки записей в базе данных. Для удобства сортировка будет по параметру updated. Обратите внимание на "-", он означает что сортировка будет в обратном порядке, то есть по убыванию, от самых новых к старым.

Перейдём в файл admin.py и зарегистрируем модель в панели администратора:
@admin.register(models.BotUserModel)
class BotUserAdmin(admin.ModelAdmin):
list_display = ('chat_id', 'first_name', 'last_name', 'username', 'created', 'updated')
search_fields = ['chat_id', 'first_name', 'username', ]
Обратит внимание! Если вы регистрировали модель не через декоратор, а через admin.site.register, то код находящийся выше, надо добавлять до строки с регистрацией!
Здесь я указал, что бы отображались все поля модели. Включил поиск по полям chat_id, first_name и username.

Теперь надо применить миграции:
python manage.py makemigrations

python manage.py migrate

Запустим Django python manage.py runserver и убедимся, что модель добавилась в панель администратора.

Файлы к посту, можно получить в боте по коду: 347837
Пост на сайте.
Поддержать канал.

#django #python #модель #бот #aiogram
👍1
Django 15. Пишем API - Добавление пользователя

Теперь давайте напишем API, обращаясь к которому мы будем создавать или обновлять пользователя.

Откроем файл api.py и создадим класс CreateBotUser и статический метод post.
В прошлый раз мы делали метод для GET запроса, в этот раз наш бот не получает, а передаёт данные по API, именно по этому нам нужен POST запрос.
class CreateBotUser(APIView):
@staticmethod
def post(request):


Далее создаём переменную usr_obj в которую мы, с помощью метода get_or_create получим объект пользователя, если пользователь с chat_id уже есть в базе, если же его нет, он будет создан и так же помещен в переменную:
        usr_obj: models.BotUserModel = models.BotUserModel.objects.get_or_create(
chat_id=request.data['chat_id'],
defaults={
'first_name': request.data['first_name'],
'last_name': request.data['last_name'],
'username': request.data['username'],
})[0]
В параметре defaults передаются значения полей, которые будут записаны, если пользователя нет.

Затем, независимо от того, был пользователь только что создан или нет, мы обновляем значение поля updated на актуальное время, вызвав сохранение объекта. И возвращаем пустой ответ со статус-кодом 200:
        usr_obj.save()
return Response(status=200)

Добавим URL-адрес для отправки запроса. Перейдём в файл urls.py и в список urlpatterns отведённый для URL-паттернов нашего API добавим строку:
# Паттерны API
urlpatterns += [
path('bot/get-file/', api.GetFilePath.as_view()),
path('bot/create-user/', api.CreateBotUser.as_view()),
]

На этом создание API закончено, теперь необходимо написать в боте отправку запроса при выполнении команды.

Файлы к посту, можно получить в боте по коду: 786103
👍1
Полезные инструменты - Бесплатный CHAT-GPT4 на вашем сервере

Приветствую.

Буквально вчера мне написал одногруппник и скинул видео. В этом видео рассказывалось о том, как запустить чат GPT у себя на пк. Само видео смотреть не стал, сразу ринулся изучать гитхаб проекта.

Страница проекта: https://github.com/ramonvc/freegpt-webui

В данном проекте собраны различные модели нейросетей. Можно выбрать как GPT-4, так и Sage или Claude.
Вся обработка происходит на сторонних серверах, мы выступаем в роли клиента.

Есть два способа использовать проект.
1. Запускать на локальном ПК.
2. Запускать в Docker-контейнере.

В обоих случаях запуск не вызывает трудностей.
Запуск на ПК.
Для запуска на своём пк, достаточно выполнить несколько действий.
1. Склонировать проект с Github:
git clone https://github.com/ramonvc/freegpt-webui.git

2. Перейти в папку проекта и запустить установку зависимостей:
cd freegpt-webui
pip install -r requirements.txt

3. Запустить скрипт:
python run.py

4. Открыть браузер и перейти по адресу https://127.0.0.1:1338.

Вот и всё. Можно пользоваться.

Запуск в Docker-контейнере.
Тут всё ещё проще.
1. Выполнить команду запуска контейнера:
docker run -p 1338:1338 -d ramonvc/freegpt-webui

2. Открыть браузер и перейти по адресу https://127.0.0.1:1338.

Минимум действий.

Я запускал у себя на сервере в контейнере. Работает отлично, результаты выдаёт относительно корректные, но более подробные что-ли, нежели боты в ТГ.
👍2🔥1
По поводу GPT у людей крайне неоднозначные мнения. И в связи с предыдущим постом, возник вопрос.
Как вы относитесь к GPT? Да и не только к GPT, но и другим подобным нейронкам.
Anonymous Poll
33%
Нравится. Использую постоянно.
37%
Хорошая штука, но пользуюсь редко.
22%
Слышал, но не использую.
4%
Скептически, лучше головой думать.
0%
Категорически против! Точка!
4%
Свой вариант расскажу в комментариях.
AIOgram3 9. Команда start

API для регистрации пользователя написано, теперь нужно сделать команду /start. Эта команда выполняется при первой инициализации бота пользователем.

Без лишних слов. Откроем файл api_actions.py в пакете utils и напишем функцию register_user для отправки данных по API. В качестве аргументов, она будет принимать следующие данные: chat_id, first_name, last_name, username.
Поскольку мы не получаем от API ничего, кроме статус-кода, создавать переменную, как в функции get_path, нет смысла. Сразу обращаемся к библиотеке requests.
В функции выше, мы отправляли GET запрос обращаясь к методу get из библиотеки requests. Сейчас нам необходимо отправить POST запрос, следовательно использовать будем метод post.
Первым параметром, как и ранее будет URL-адрес нашего API, можно взять его из предыдущей функции и изменить f-строку на URL для регистрации f"create-user/".
Вторым параметром будет ключевой параметр data, в котором создаём словарь с данными, где ключ - строка с названием переменной, а значение сама переменная.
def register_user(chat_id, first_name, last_name, username):
requests.post(API_URL + f"create-user/",
data={
'chat_id': chat_id,
'first_name': first_name,
'last_name': last_name if last_name else '',
'username': username if username else '',
})
Стоит учесть, что поля last_name и username могут быть пустыми, по этому при помощи тернарного оператора, мы присваиваем значение переменной или пустую строку.

Обработчик написан, перейдём к созданию команды. В пакете handlers создадим файл simple.py. В этом файле мы будем писать простые команды, не требующие логики, такие как /start, /help, /about.
В файле напишем асинхронную функцию start_command, принимающую аргумент message.
В теле функции сразу вызываем нашу функцию register_user из файла api_actions.py, передавая в неё необходимые данные из объекта message.

chat_id мы получаем обратившись к полю id метода chat - message.chat.id. Остальные переменные получаем из одноимённых полей метода from_user, например, message.from_user.first_name.
После вызова функции отправляем пользователю приветственное сообщение, предварительно создав функцию start_message с текстом в файле views.py.
from aiogram.types import Message

from botlogic import views
from botlogic.utils.api_actions import register_user


async def start_command(message: Message):
register_user(chat_id=message.chat.id,
first_name=message.from_user.first_name,
last_name=message.from_user.last_name,
username=message.from_user.username)
await message.answer(views.start_message())

Откроем файл main.py и зарегистрируем команду, добавив в функцию start после регистрации событий запуска/остановки, следующую строку:
from botlogic.handlers import send_file, simple

dp.message.register(simple.start_command, Command(commands='start'))


Теперь протестируем работу.
Запустим Django и перейдём в панель администратора и откроем страницу модели Пользователи бота. Должно быть пусто.
Теперь в отдельном окне запустим бота и выполним команду /start.
Если, всё прошло удачно, то обновив страницу в панели администратора, увидите свой профиль.

Файлы к посту, можно получить в боте по коду: 260142