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

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

Реклама и взаимопиар: @Murzyev1995
Сотрудничество и др.: @proDreams
Download Telegram
Получение сертификата.
Запускаем PowerShell от имени администратора. Это важно! Иначе сертификат невозможно будет сгенерировать!

И вводим следующую команду: certbot certonly --authenticator manual --preferred-challenges dns

Параметры команды:
- certonly - указывает, что мы хотим получить только сертификат.
- --authenticator manual - указывает, что мы в ручном режиме предоставим доказательства владения доменом.
- --preferred-challenges dns - указывает, что в качестве подтверждения будет использоваться TXT-запись в DNS домена.

Выполняем. Далее нас попросят ввести домен или домены через пробел или запятую, к которым будет относиться сертификат. Принято вводить две версии домена, с www и без. Также я дополнительно введу и почтовый поддомен. Выходит такая строка: pressanybutton.ru www.pressanybutton.ru mail.pressanybutton.ru.

Внимание! Есть ещё второй вариант добавления неограниченного количества поддоменов в сертификат. Для этого указываем два домена: domain.ru и *.domain.ru. Это упростит получение сертификата, если у вас несколько поддоменов.
Однако, стоит отметить, что данный способ не указан в документации, гарантировать его работу не могу.

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

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

На примере mail.pressanybutton.ru:
Хост: _acme-challenge.mail.pressanybutton.ru.
Значение: QkUdVKpxx1jbCin6Yf64l5IaKgJEYrgIG0iYYbNFTj4

Поскольку у меня три домена введено, то и три записи надо создать. На примере одной из них в панели управления TimeWeb:
Необходимо создать TXT-запись.
Выбираем раздел "Домены", там необходимый домен, затем вкладку "DNS".
Нажимаем на кнопку "Добавить запись" и выбираем "TXT".
В разделе Хост выбираем "Ввести вручную" и вводим _acme-challenge.mail.
В поле значение вводим: QkUdVKpxx1jbCin6Yf64l5IaKgJEYrgIG0iYYbNFTj4.

И так делаем, пока не дойдём до последнего домена. Когда создадите запись для последнего домена, не спешите нажимать Enter. DNS-записи могут обновляться достаточно долго, до 24-х часов. Отслеживать добавилась запись к домену или нет, можно по ссылке указанной в тексте под кодом значения. Перейдя по ней, можно увидеть, есть запись у домена или ещё нет. Если есть, убедитесь, что и для других указанных доменов она тоже присутствует, нажимайте Enter.
Также стоит отметить, что до появления записи в DNS, терминал следует держать открытым, иначе придётся всё проделывать заново.

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

В последнем сообщении будет указано расположение файлов и дата окончания действия.

Пути расположения файлов:
Сертификат: C:\Certbot\archive\pressanybutton.ru\fullchain.pem
Приватный ключ: C:\Certbot\archive\pressanybutton.ru\privkey.pem
В директории так же будет ещё два других сертификата, но их применение только в специализированных ситуациях. В качестве сертификата используйте только fullchain.pem.

Поздравляю! Теперь у вас есть действующий сертификат для сайта, сроком на 3 месяца.

Файлы к посту, можно получить в боте по коду: 395898
Пост на сайте.
Поддержать канал.
👍2
Код на салфетке
Получение сертификата. Запускаем PowerShell от имени администратора. Это важно! Иначе сертификат невозможно будет сгенерировать! И вводим следующую команду: certbot certonly --authenticator manual --preferred-challenges dns Параметры команды: - certonly…
Дополнение к посту.

После небольшого спора о способе указания поддоменов в сертификат и проверке этого способа, в текст поста было добавлено следующее дополнение:

Внимание! Есть ещё второй вариант добавления неограниченного количества поддоменов в сертификат. Для этого указываем два домена: domain.ru и *.domain.ru. Это упростит получение сертификата, если у вас несколько поддоменов.
Однако, стоит отметить, что данный способ не указан в документации, гарантировать его работу не могу.


Присоединяйтесь к чату, у нас весело и иногда интересно 😉
👍2
Сегодня ровно 14 месяцев с начала обучения по годовой программе в GeekBrains.

Я выкладывал пост на 12й месяц, а про 13й забыл. Исправляюсь)

Обучение: тринадцатый месяц⁠⁠
Обучение: четырнадцатый месяц⁠⁠

😊Буду рад лайкам подпискам и вот этому всему)
🔥8
Приветствую!

Каналу уже три месяца!

За это время:
- Вышло 59 постов
- На канал подписалось 197 человек (как много!)
- В чате 32 участника и там постоянно, что-то творится

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

Хочу поблагодарить вас за то, что читаете, оставляете комментарии и общаетесь в чате.

Также особая благодарность поддерживающим на Boosty:
- Юрий Гаврилович за донат и подписку
- Сергей за донат
- Кристина за донат

Дальше больше и надеюсь лучше)
Спасибо!
🔥7
Docker 5.1 Почтовый сервер на Docker Mailserver - настройка домена

В посте "Django 12. Настройка отправки почты", я описывал как в Django можно настроить отправку почты используя обычный почтовый ящик и упоминал про возможность отправлять почту от имени домена используя специальные сервисы.

Поскольку меня не устраивали эти варианты, я начал изучать вопрос поднятия своего сервера для отправки/получения почты.

Решений нашлось не мало, от сборки своего сервера с нужными компонентами, до готовых комбайнов.
Сборка своего, даже из готовых компонентов, достаточно нетривиальная задача, требующая массу времени и знаний в этой области, оставим это Dev-ops инженерам и администраторам.
Выбор пал на готовые решения, но и тут не всё так просто. Есть масса вариантов, от совсем простеньких, до комбайнов, включающих в себя массу модулей и возможностей. Тут уже стоит исходить из потребностей, требуемых возможностей и, что немаловажно из системных требований решения. Поскольку в ресурсах я ограничен двумя Гигабайтами оперативной памяти на моём сервере, я выбрал в качестве почтового сервера - Docker Mailserver.


Окружение.
Действия в данном посте подразумевают, что у вас имеется домен и доступ к управлению DNS-записями.
В следующем посте понадобится VPS-сервер и действующий SSL-сертификат.

Могу порекомендовать два хостинга:
- HSHP - достаточно дешевые сервера в Германии, отлично подойдут для тестов или, например, настроить собственный VPN.
- TimeWeb Cloud - наверное, самый надёжный хостинг из всех, что я пробовал. Также тут удобно приобретать или подключать свои домены.
(Ссылки реферальные - вам не сложно, а мне приятно, спасибо.)

Используемый сервер:
- CPU: 1x 3.3ГГц
- RAM: 2Гб
- SSD: 20Гб NVMe
- OS: Debian 12


Docker Mailserver.
Docker Mail Server, или DMS, представляет собой готовый к работе полнофункциональный, но простой почтовый сервер.

Ключевые особенности:
- Поддерживает протоколы SMTP, IMAP, POP3 и LDAP.
- Используются только файлы конфигурации, без базы данных SQL.
- Поддержка антиспам фильтра SpamAssassin и антивируса ClamAV.


Настройка домена.
Начнём с подготовки домена для правильной работы с почтой.

Нам необходимо добавить шесть записей к домену, а именно: MX, A, PTR, DKIM, DMARC, SPF.
Вернее пять, поскольку DKIM-запись будем добавлять на этапе запуска сервера.

Для почты будем использовать поддомен mail.<имя_домена>. В моём случае это - mail.pressanybutton.ru, он же будет далее по тексту.
Необходимо его создать.

Все примеры будут на основе панели управления хостинга TimeWeb



PTR.
PTR (Pointer) - обратная запись ресурсов DNS. Она связывает IP-адрес с доменным именем, позволяя определить, какому домену принадлежит IP-адрес отправителя электронной почты.

Чаще всего данную запись нельзя установить из панели управления. Если такая возможность отсутствует у вашего хостинг-провайдера, то для установки вам необходимо обратиться в службу поддержки.

Установка на TimeWeb:
Открываем страницу "Облачные серверы" и выбираем vps, на котором будет располагаться почтовый сервер.
Выбираем вкладку "Сеть".
Там внизу находим IP-адрес сервера и нажимаем на шестерёнку. На открывшейся странице указываем доменное имя для почты.

MX.
MX (Mail eXchanger) - это записи ресурсов DNS, которые определяют серверы, принимающие почту для конкретного домена. MX-запись содержит приоритет и доменное имя сервера, который будет использоваться для обработки почты. Чем меньше числовое значение приоритета, тем выше приоритет сервера.

Установить запись можно в настройках DNS вашего хостинг-провайдера или у регистратора домена.

Запись должна быть вида: 10 mail.pressanybutton.ru.
Где 10 - это приоритет, а mail.pressanybutton.ru - почтовый домен.

Установка на TimeWeb(если домен приобретён или делегирован на сервера TimeWeb):
Открываем раздел "Домены". Выбираем нужный домен и переходим на вкладку DNS.
Если имеются mx-записи, удаляем. Затем нажимаем кнопку "Добавить запись" и выбираем MX.
Выбираем службу "Другое" и прописываем приоритет и почтовый домен.

То же самое делаем для поддомена.
A.
A (Address) - запись ресурсов DNS, которая сопоставляет доменное имя с его IP-адресом. Она используется для определения местоположения сервера, на котором находится сайт или почтовый сервер.

Также прописываем и для поддомена.

Установка такая же как и для предыдущего пункта.
Отличия лишь в том, что мы выбираем вместо mx-записи - a-запись. В значении указываем IP-адрес сервера.

Для поддомена в TimeWeb, А-запись не создаём, запись будет создана автоматически.

DMARC.
DMARC (Domain-based Message Authentication, Reporting and Conformance) - стандарт, который позволяет доменам определять политики обработки сообщений, отправленных с поддельных адресов электронной почты. DMARC включает в себя три компонента: аутентификацию, отчетность и соответствие.

Необходимо создать TXT-запись.

Хост: _dmarc.pressanybutton.ru
Значение: v=DMARC1; p=quarantine; sp=quarantine; fo=0; adkim=r; aspf=r; pct=100; rf=afrf; ri=86400; rua=mailto:[email protected]; ruf=mailto:[email protected]

Изменить адреса почты на ваши.

Установка на TimeWeb:
В том же разделе, что и ранее выбираем "Добавить запись" - "TXT".
В пункте "Хост" выбираем "Ввести вручную" и вводим _dmarc
Значение вводим такое же, что указано выше.

SPF.
SPF (Sender Policy Framework) - механизм, который помогает определить, является ли домен, указанный в поле “от”, авторизованным для отправки электронной почты от имени этого домена. SPF-запись в DNS содержит список серверов, которые авторизованы для отправки почты от имени домена.

Необходимо отредактировать имеющуюся TXT-запись с spf-записью или добавить новую TXT-запись.

Если TXT-записи с spf нет:
Хостом выбираем основной домен pressanybutton.ru.
В поле значение вводим: v=spf1 mx ~all

Если TXT-запись с spf есть:
Смотрим, что записано в поле значение, если там нет mx, добавляем через пробел после v=spf1, также если там нет ~all, то добавляем через пробел в самый конец.
У меня имелась запись: v=spf1 include:_spf.timeweb.ru ~all
Новая стала выглядеть так: v=spf1 mx include:_spf.timeweb.ru ~all

Установка на TimeWeb:
Так же как и в предыдущем пункте, только выбираем хостом основной домен и всё.

На этом подготовка домена закончена. В следующем посте будем запускать и настраивать сервер.

Файлы к посту, можно получить в боте по коду: 284512
Пост на сайте.
Поддержать канал.
🔥1
Тут меня вчера озадачили.

Поступило предложение, организовать к новому году "Тайного Санту". Кто не знает, что это - погуглите) Вопрос: хотели бы вы в этом поучаствовать?
Anonymous Poll
34%
Да! С удовольствием)
38%
Выглядит интересно, но я только посмотреть
3%
Нет, плохая идея
25%
Вам делать совсем нечего?
Docker 5.2 Почтовый сервер на Docker Mailserver - настройка и запуск

В прошлом посте мы подготовили домен для работы с почтой, в этом мы запустим почтовый сервер.

Запускать почтовый сервер будем в Docker-контейнере. Если у вас не установлен Docker, то почитать об установке можно в посте "Docker 2.2 Установка Docker на Linux".

Стоит отметить, что в этом посте не будет всеобъемлющей настройки почтового сервера. Я расскажу как запустить "минимальную конфигурацию", чтобы можно было пользоваться.
Полный перечень конфигураций и возможностей можно найти в официальной документации: https://docker-mailserver.github.io/docker-mailserver/latest/
Напомню используемое окружение:
Действия в данном посте подразумевают, что у вас имеется VPS сервер, настроенный домен и действующий SSL-сертификат.

Могу порекомендовать два хостинга:
- HSHP - достаточно дешевые сервера в Германии, отлично подойдут для тестов или скажем настроить собственный VPN.
- TimeWeb Cloud - наверное самый надёжный хостинг из всех, что я пробовал. Так же тут удобно приобретать или подключать свои домены.
(Ссылки реферальные - вам не сложно, а мне приятно, спасибо.)

Используемый сервер:
- CPU: 1x 3.3ГГц
- RAM: 2Гб
- SSD: 20Гб NVMe
- OS: Debian 12


Файл Docker Compose и конфигурация переменных окружения

Подключаемся по SSH к серверу и переходим в удобную для работы директорию.
Далее выполняем команду mkdir dms для создания директории в которой будут находиться конфигурационные файлы почтового сервера. Название директории можете изменить по желанию.

Переходим в директорию, выполнив команду cd dms.

Необходимо скачать два файла: compose.yaml и mailserver.env.
В первом находится конфигурация Docker Compose сервиса, а во втором параметры переменных окружения, определяющих настройки почтового сервера.

Для этого выполняем две команды:
wget "https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master/compose.yaml"
wget "https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master/mailserver.env"


Также, вы можете найти эти файлы в архиве с материалами к посту.


Редактирование файла compose.yaml.
Откроем файл выполнив команду nano compose.yaml и изменим следующие параметры:
- hostname - в этом параметре прописываем почтовый домен, в моём случае это mail.pressanybutton.ru
- volumes - в этом параметре описываются локальные директории подключаемые в контейнере. Добавим две строчки в этот параметр:
- ./docker-data/dms/rspamd/:/etc/rspamd/override.d/
- ./docker-data/dms/custom-certs/:/tmp/dms/custom-certs/:ro


Готово. Нажимаем CTRL+S для сохранения, затем CTRL+X для выхода.


Редактирование файла mailserver.env.
Откроем файл выполнив команду nano mailserver.env и изменим следующие параметры:
- POSTMASTER_ADDRESS - данный параметр определяет почту администратора. Указываем почту по вашему желанию, например, у меня это - [email protected]
- TZ - указывает на временную зону. Указываем подходящий вам часовой пояс, например, Europe/Moscow
- ENABLE_OPENDKIM, ENABLE_OPENDMARC, ENABLE_POLICYD_SPF и ENABLE_AMAVIS - эти параметры выставляем на 0, поскольку за это будет отвечать Rspamd
- ENABLE_CLAMAV - параметр, отвечающий за работу антивируса ClamAV. Включать его или нет, выбирать вам, поскольку он достаточно сильно нагружает сервер и исходить нужно из имеющихся ресурсов и потребностей.
- ENABLE_RSPAMD - параметр, отвечающий за работу Rspamd. Устанавливаем здесь 1 для включения. Он необходим нам для работы DKIM, о котором чуть дальше. Rspamd — это высокопроизводительный сервер обработки почты с открытым исходным кодом. Он предназначен для фильтрации спама и вирусов, а также для ускорения обработки почты.
- SMTP_ONLY - параметр, переключающий почтовый сервер в только SMTP-сервер. В таком режиме он сможет только отправлять почту.
- SSL_TYPE - параметр, определяющий какой тип SSL-сертификата будет использоваться. Выставляем manual.
- SSL_CERT_PATH - путь до сертификата. Указываем /tmp/dms/custom-certs/cert.crt
- SSL_KEY_PATH - путь до ключа. Указываем /tmp/dms/custom-certs/privkey.key
- ENABLE_SPAMASSASSIN - параметр, отвечающий за работу Spam Assassin. Включайте по желанию и имеющимся ресурсам.

Готово. Нажимаем CTRL+S для сохранения, затем CTRL+X для выхода.
Сертификаты.
Выполните следующую команду:
mkdir docker-data && cd docker-data && mkdir dms && cd dms && mkdir custom-certs && cd custom-certs


В итоге должны создаться три директории и мы окажемся в директории custom-certs.
В эту директорию необходимо поместить сертификат и ключ с теми же именами, что прописывали ранее в конфигурационном файле.

Первый запуск.
Для запуска возвращаемся в основную директорию dms где находится файл compose.yaml и выполняем команду docker compose up. Если всё указано верно, сервер запустится и начнёт работу, но необходимы ещё настройки.

Откройте второй терминал и подключитесь к серверу.
Нам необходимо создать почтовый ящик. Для этого выполняем команду docker exec -ti mailserver setup email add <ADDRESS> <PASSWORD>. Где mailserver - имя контейнера, если вы не меняли его в файле compose.yaml, то оно будет mailserver.

После этого необходимо добавить псевдоним главного почтового адреса, выполнив команду docker exec -ti mailserver setup alias add [email protected] [email protected]. Первой почтой указываем почту, прописанную в файле mailserver.env, вторым можете указать удобную для вас почту на другом домене или ранее созданную почту.


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

DKIM (DomainKeys Identified Mail) - метод аутентификации электронной почты, который добавляет цифровую подпись в сообщение. Это помогает подтвердить, что сообщение пришло от предполагаемого отправителя.

Всё в том же втором терминале выполняем следующую команду: docker exec -ti mailserver setup config dkim

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

В моём случае хост: mail._domainkey
Значение: v=DKIM1; k=rsa; p=MIIB.........

После этого возвращаемся в терминал и из директории dms, в которой файл compose.yaml, переходим в директорию docker-data/dms/rspamd там создаём файл dkim_signing.conf выполнив команду touch dkim_signing.conf.

Затем открываем его выполнив команду nano dkim_signing.conf и вставляем следующий текст:
# documentation: https://rspamd.com/doc/modules/dkim_signing.html

enabled = true;

sign_authenticated = true;
sign_local = true;

use_domain = "header";
use_redis = false; # don't change unless Redis also provides the DKIM keys
use_esld = true;

check_pubkey = true; # you wan't to use this in the beginning

domain {
pressanybutton.ru {
path = "/tmp/docker-mailserver/rspamd/dkim/rsa-2048-mail-pressanybutton.ru.private.txt";
selector = "mail";
}
}


В разделе domain указываем ваш домен, ниже в строке путь rsa-2048-mail-pressanybutton.ru.private.txt меняем на название файла находящегося по пути dms/docker-data/dms/config/rspamd/dkim

Готово. Нажимаем CTRL+S для сохранения, затем CTRL+X для выхода.

Завершение настройки.
Переходим в первый терминал с запущенным сервером и нажимаем CTRL+C для остановки. Далее на всякий случай удаляем контейнер, если он не удалился после остановки docker rm mailserver.

И запускаем снова, в этот раз в фоне(хотя можно и не в фоне, чтобы убедиться, что проблем нет) выполнив команду docker composer up -d.
Подключение к почте и проверка.
Для подключения к почте, можно воспользоваться программой Thunderbird. Скачать можно на сайте: https://www.thunderbird.net/ru/
Выбираем подключить существующую почту, вводим имя, адрес почты и пароль. Программа найдёт конфигурацию самостоятельно и подключится к серверу.

Далее открываем сайт https://www.mail-tester.com/ , копируем указанную почту и отправляем на неё письмо, желательно с осмысленной темой и содержимым. Затем на сайте нажимаем кнопку под адресом. Спустя несколько секунд должна отобразиться оценка и будут указаны ошибки, если что-то было неправильно настроено. Но, если всё делали в точности, должно быть 10/10!

Также, можете отправить письмо себе на разные ящики и замучить тестами друзей 🙂


Настройка Django.
Изначально с этого всё и началось, что нужен был почтовый сервер для отправки почты с сайта.
Откроем файл settings.py и найдём настройки почтового сервера, а если их не было, вписываем следующие:
EMAIL_HOST = 'mail.pressanybutton.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_HOST вписываем ваш почтовый домен.
В поле EMAIL_HOST_USER вписываем почтовый адрес.
В поле EMAIL_HOST_PASSWORD вписываем пароль от почтового адреса.

Готово! Теперь Django отправляет почту от имени нашего домена через наш почтовый сервер!

Провозился с этим постом конечно долго, в процессе было уйма ошибок и попыток понять, как работает современная почтовая система со всеми их защитами от спама.
На самом деле, в этом посте только базовая настройка, сам Docker Mailserver весьма функционален и у него много возможностей, но настройка всего требует времени и знаний. Я постарался описать так, что бы "сделал и оно работает", а настройка под конкретные ситуации, уже на пользователе.

Файлы к посту, можно получить в боте по коду: 245646
Пост на сайте.
Поддержать канал.
🔥2
Как быстро вы ловите себя на мысли, что допустили ошибку при написании кода? (до выполнения и её проявления)
Anonymous Poll
11%
Довольно быстро, сразу исправляю
8%
Есть ощущение, что что-то не так, но не ищу причину
61%
Замечаю после запуска и пересмотра кода
19%
Замечаю только при её проявлении
Django 30. Рефакторинг и допущенные ошибки

Ошибки - неотъемлемая часть программирования. Как ни старайся, всё равно допустишь ошибки, которые по началу сочтёшь мелкими и незначительными, а по факту они соберутся в "снежный ком".

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

В этом посте я проведу небольшой рефакторинг, а вернее даже, реорганизацию своего кода (и чуть-чуть скреплю это "костылями" и "синей изолентой").


Директория с шаблонами.
Начнём с простого. Сейчас есть всего одно приложение blog и директория с шаблонами находится в нём, но в будущем (и как следовало бы, в прошлом) будет несколько приложений. Каждое будет отвечать за свою область и у всех будут свои шаблоны. Делать в каждом приложении свою директорию с шаблонами не очень красиво, удобнее всё собрать в одном месте.
🔥3
К слову, это даже было предусмотрено. Изначально в посте по первоначальной настройке, мы добавили в параметр TEMPLATES строку - 'DIRS': [BASE_DIR / 'templates'],.

Решение проще некуда. Достаточно просто вынести директорию templates из директории приложения в директорию уровнем выше, где находится файл manage.py.

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


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

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


Разделение на приложения.
Добрались до главной ошибки.

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

Моя ошибка заключается в том, что я блог и API уместил в одном приложении блога. Это не критичная ошибка, всё работает, однако это создаёт проблему навигации по коду. Код разрастается, состоит из блоков для разных задач.

Для исправления этой ситуации, я создам новое приложение api_app и перенесу в него всё, что связано с API. И всё бы ничего, но у меня есть несколько моделей и они содержат данные в БД. Простого способа перенести модель из приложения в приложение с сохранением данных в новой таблице я не нашёл. Однако есть один, весьма простой, но "костыльный" способ.

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


Создание нового приложения.
Создадим новое приложение api_app выполнив команду python manage.py startapp api_app.

Переходим сразу в settings.py и добавляем новое приложение в INSTALLED_APPS.

И создадим файл urls.py в директории приложения api_app.


Перенос моделей и файлов.
Далее необходимо перенести всё связанное с API из приложения blog в приложение api_app.

Начнём с модели. Полностью вырезаем код необходимых моделей и переносим его в файл models.py в новом приложении.
Проверяем, не осталось ли каких-либо связей в других моделях относительно перенесённых. Если остались, правим импорты.

Затем в класс Meta перенесённых моделей добавляем новый пункт app_label и указываем имя старого приложения.
Таким образом код у нас находится в новом приложении, но модель считается моделью старого приложения и таблицы БД не будут перезаписаны. Если у вас нет данных в БД, пометку делать не нужно.

Далее переносим из файла admin.py связанные классы. Правим импорты.

Переносим файлы api.py и serializers.py. Правим импорты.

Переносим URL-паттерны для API из файла urls.py в новое приложение. Правим импорты и переходим в файл urls.py, находящийся в директории проекта. Добавляем новый паттерн path('api/', include('api_app.urls', namespace='api_app')),.

Применяем миграции. Результатом должно быть отсутствие новых миграций.

Готово. Всё должно работать, как и раньше.

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

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

Файлы к посту, можно получить в боте по коду: 919633
Пост на сайте.
Поддержать канал.
🔥2
Cpp FreeGPT WebUI - Бесплатный GPT на вашем сервере

FreeGPT мёртв, да здравствует FreeGPT!

Сегодня, благодаря комментариям на канале, выяснилось, что FreeGPT, о котором я писал ранее прекращает свою работу.
Добавил об этом пометку и сообщение автора в посте "Бесплатный Chat-GPT4 на вашем ПК или сервере".

Заинтересовался вопросом, нет ли альтернатив и, как оказалось альтернатива есть.

Встречайте Cpp FreeGPT WebUI.

Написан на C++. Использует GPT4Free API и WebUI от ChatGPT Clone.

Доступны вариации моделей Chat GPT 3.5 Turbo и Chat GPT 4 (насчёт четвёрки не уверен, скорее всего та же тройка).

Ссылка на GitHub проекта: https://github.com/fantasy-peak/cpp-freegpt-webui#cpp-freegpt-webui

Единственный минус данного решения - установка либо на Linux, либо в Docker-контейнере.

А остальное, вы все прекрасно знаете. Приступим к установке.
Установка на Linux.

1. Клонируем репозиторий выполнив команду:
git clone https://github.com/fantasy-peak/cpp-freegpt-webui.git


2. Проверьте установленную версию пакета g++. Необходима версия g++ >= 13.1.0 (GCC).
3. Установите xmake, выполнив следующие команды:
wget https://github.com/xmake-io/xmake/releases/download/v2.8.2/xmake-v2.8.2.xz.run
chmod 777 xmake-v2.8.2.xz.run
./xmake-v2.8.2.xz.run
source ~/.xmake/profile


4. Установите libcurl-impersonate:
# ubuntu
apt-get install libcurl4-openssl-dev

# centos7
yum install libcurl-devel.x86_64

wget https://github.com/lwthiker/curl-impersonate/releases/download/v0.5.4/libcurl-impersonate-v0.5.4.x86_64-linux-gnu.tar.gz
sudo mv libcurl-impersonate-v0.5.4.x86_64-linux-gnu.tar.gz /usr/lib64
cd /usr/lib64
sudo tar -xvf libcurl-impersonate-v0.5.4.x86_64-linux-gnu.tar.gz
export LD_LIBRARY_PATH=/usr/lib64:$LD_LIBRARY_PATH
export LIBRARY_PATH=/usr/lib64:$LIBRARY_PATH


5. Компиляция:
git clone https://github.com/fantasy-peak/cpp-freegpt-webui.git
cd cpp-freegpt-webui
xmake build -v -y
xmake install -o .
cd bin
./cpp-freegpt-webui ../cfg/cpp-free-gpt.yml


6. После всех манипуляций, чат будет доступен в браузере по ссылке: https://127.0.0.1:8858/chat.


Запуск в Docker-контейнере.

1. Скачиваем актуальную версию образа, выполнив команду:
docker pull fantasypeak/freegpt:latest


2. Запускаем контейнер:
docker run -p 8858:8858 --name freegpt -d fantasypeak/freegpt:latest


3. Чат будет доступен в браузере по ссылке: https://127.0.0.1:8858/chat.

Завершение.
Запускал в Docker-контейнере на Windows и VPS-сервере. Работает без нареканий

Пост на сайте.
Поддержать канал.
🔥2
AIOgram3 12. Добавление бота в чат

Telegram-боты могут работать не только 1 на 1 с пользователем, но и с целыми чатами.

Вот и в чате канала появилась необходимость в боте, а именно в следующем функционале:
1. Приветствие новых пользователей чата.
2. Удаление сообщений, содержащих мат (уж простите, но чат публичное место и если без мата не обойтись, то лучше промолчать).
3. Погода. Да, погода. Уж не знаю на кой ляд она сдалась, но раз просят - надо делать.

И, что самое удобное, бот будет действовать на комментарии к постам на канале.
Добавление бота в чат.
Начнём с самого начала, а именно с добавления бота в чат.

В чате с ботом открываем его профиль.
Там выбираем пункт "Добавить в группу". В открывшемся списке выбираем необходимую группу.

Бот добавлен, но он не имеет доступа к сообщениям. Он будет работать, если к нему напрямую обращаться по команде, а остальные сообщения он не будет видеть. Это не позволит ему проверять сообщения, а также не позволит работать машине состояний, если будет несколько уровней взаимодействия.

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

Готово. Бот добавлен в группу и может читать сообщения.


Получение идентификатора чата.
Для взаимодействия бота с чатом, разграничением функционала и корректной работы, необходимо знать ID-чата.

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

Воспользуемся простым.

Открываем чат с ботом https://t.iss.one/userinfobot
Сразу после запуска он покажет ваш Telegram-ID, но нам необходим ID-чата.

Переходим в чат и пишем сообщение от имени чата. Затем выделяем сообщение и пересылаем его в ранее упомянутого бота.

В ответ он пришлёт идентификатор чата начинающийся со знака -. Всё верно, Идентификаторы пользователей - целое число, а идентификаторы чатов и каналов - отрицательное.

Отлично. Теперь у вас есть идентификатор вашего чата.


Доработка кода бота.
Разобравшись с формальностями, перейдём к коду. Откроем файл settings.py.

У нас есть Dataclass Secrests в котором мы храним важные для работы бота данные, а именно токен и идентификатор администратора.

Добавим новую строчку:
group_id: int = -12345


Вместо -12345 вставляем идентификатор вашего чата.


Меню для чата.
На данный момент в моём боте есть четыре команды:
- start - Начало работы
- get_file - Получение файла с материалами
- help - Помощь по доступным командам
- about - Информация о боте

Однако, в чате в первых двух командах нет необходимости. Я хочу, чтобы они были доступны только из бота и их не было видно в меню чата.

Для этого откроем файл commands.py.
В теле функции set_commands находится список commands, определяющий меню бота. Его мы не трогаем.
Ниже до команды await bot.set_my_commands создаём новый список commands_chat и вписываем туда, по аналогии со списком выше, команды доступные в чате.

У меня на данный момент это две команды:
- help - Помощь по доступным командам
- about - Информация о боте

Ниже, под await bot.set_my_commands добавляем ещё одну такую же строчку. Изменив первый аргумент на новый список, а во втором прописав BotCommandScopeChat(chat_id=Secrets.group_id). Так мы определяем, что меню будет доступно в конкретном чате.

Новая строка:
from botlogic.settings import Secrets

await bot.set_my_commands(commands_chat, BotCommandScopeChat(chat_id=Secrets.group_id))


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

Ограничение существующих команд.
Теперь необходимо ограничить существующие команды от выполнения в чате. Это необходимо сделать, поскольку команду можно написать и не открывая меню и если команда там не указана, не значит, что она не может быть выполнена.

Откроем файл send_file.py и в самое начало функции send_file_start добавим условие:
from botlogic.settings import Secrets

if message.chat.id != Secrets.group_id:


Получится вот так:
async def send_file_start(message: Message, state: FSMContext):  
if message.chat.id != Secrets.group_id:
await message.answer(views.send_file_start_msg())
await state.set_state(SendFileSteps.get_code_from_user)


Во второй функции нет необходимости в проверке, поскольку в неё не попасть без первой.
Далее откроем файл simple.py и добавим такое же условие к функции start_command.

Функция about_command у меня универсальна, оставляем как есть.

Функция help_command выводит текст со списком доступных команд, следовательно, необходимо сделать две текстовые функции в файле views.py.
Сперва добавим условие, как и раньше, ниже прописываем else и повторяем команду с сообщением, изменив название функции, например, на help_chat_message.

Получается вот так:
async def help_command(message: Message):  
if message.chat.id != Secrets.group_id:
await message.answer(views.help_message())
else:
await message.answer(views.help_chat_message())


Переходим во views.py и создаём функцию, возвращающую текст с новым списком команд.


Завершение.
Готово. Бот подготовлен к работе в чате. В следующем посте начнём делать самую востребованную функцию.
Всё правильно, это погода.

Файлы к посту, можно получить в боте по коду: 385736
Пост на сайте.
Поддержать канал.
Классика..
👍2😱1