Обновить
64K+

PHP *

Скриптовый язык общего назначения

67,89
Рейтинг
Сначала показывать
Порог рейтинга

BITCORD: лёгкий Android-мессенджер с собственной криптоэкономикой и мини-приложениями. Ищу разработчиков

Несколько месяцев разрабатываю собственный мессенджер под рабочим названием BITCORD. Ссылка на статью с полным описанием: https://habr.com/ru/articles/1052088/

Что такое BITCORD (если лень читать статью):

  • Нативный Android-клиент весом 3.5 МБ.

  • Backend на .NET Core 8, endpoint за Cloudflare Tunnel.

  • Вход через Google-аккаунт (без номера телефона, СМС, QR-кода).

  • Сеть открытая: любой может зайти и создавать каналы без жёсткой модерации и без ограничений по тематике.

  • Исходники закрыты.

Внутри уже есть:

  • каналы с поддержкой фото и видео

  • чаты (сквозное шифрование);

  • видеозвонки WebRTC:

  • пользовательские боты;

  • базовая поддержка крипто-транзакций (сеть Arbitrum);

  • возможность встраивать лёгкие веб-приложения (мини-игры и утилиты).

Цель - сделать мессенджер, в котором можно не только общаться, но и запускать небольшие приложения прямо внутри клиента, без установки дополнительных APK. Конкурентное преимущество - размер приложения всего 3.5 Mb при достойном функционале.

Предложение для разработчиков мини-приложений

Ищу авторов лёгких браузерных игр и утилит, которые готовы разместить свои проекты внутри BITCORD.

Что вы получаете:

  • Готовую аудиторию пользователей мессенджера.

  • Возможность монетизации через внутреннюю валюту.

  • Простую интеграцию: ваше приложение хостится на моём сервере.

Технические требования к мини-приложению

  1. Формат

    • Архив .zip с готовым фронтендом.

    • В корне обязателен index.html (php).

    • Все пути относительные.

    • Размер несжатых файлов — до 5 МБ.

  2. Стек

    • HTML5 + CSS3 + JS (ES6+).

    • Допустимы лёгкие фреймворки (Phaser, Three.js и т.п.).

    • Никаких внешних WebSocket/API для критической логики. Всё должно работать offline внутри WebView.

    • Прогресс можно сохранять через локальный SQLite (ваша база данных).

  3. Финансы и безопасность

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

    • Все начисления/списания токенов — только через централизованный API мессенджера.

  4. UI/UX

    • Адаптив под вертикальную ориентацию смартфонов.

    • Управление только тач-скрином.

    • Обязательна кнопка отключения звука.

Если интересно — пишите в профиль или в сам мессенджер на @joker. Готов обсудить условия и дать доступ к тестовой среде.

Спасибо за внимание. Буду рад конструктивной критике и вопросам по теме.

ссылка на скачивание: https://apkpure.com/bitcord/com.digci.link



Теги:
-2
Комментарии0

Можно ли быстро актуализировать старые PHPUnit-тесты под новые версии пакета?

Краткий ответ: да, но есть нюансы.

На Хабре незаслуженно мало статей про инструмент Rector, и даже в них совсем вскользь упоминается, что у инструмента есть отдельный функционал для актуализации PHPUnit-тестов, написанных под разные версии пакета. Причем если раньше, этот функционал был в виде отдельного пакета rector-phpunit, то на сегодня (для версии 2.6.3) этот функционал уже входит в состав основного пакета.

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

Как шло обновление:
- установили пакет rector/rector
- обновили пакет phpunit
- сделали файл конфига rector.php в котором прописали наборы правил
- запустили сначала в режиме vendor/bin/rector process --dry-run. Увидели, что аннотации @dataProvider не мигрировали в атрибуты #[DataProvider], а сами методы, на которые указывают dataProvider не стали статическими (требования PHPUint 10+).
Добавили необходимые правила в конфиг rector.php и в при первом приближении всё сработало как нужно:

<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;

return RectorConfig::configure()
    // Путь к директории с тестами
    ->withPaths([
        __DIR__ . '/tests',
    ])
    // Включаем синтаксис PHP 8.4
    ->withPhpSets(php84: true)
    // Правила берем для версии phpunit из composer.json
    ->withComposerBased(
        phpunit: true
    )
    // Общие наборы правил для улучшения качества тестов
    ->withPreparedSets(
        phpunitCodeQuality: true
    )
    // Явно запускаем встроенное правило миграции аннотаций PHPUnit в атрибуты
    ->withAttributesSets(
        phpunit: true
    );

Но и после этих инструкций не все методы dataProvider стали статическими. Основные причины были в следующем:
- использование $this в методах dataProvider
- коллизии из-за последовательности выполнения правил рефакторинга в Rector

Что помогло исправить ситуацию:
1. повторный запуск vendor/bin/rector process позволил правилам повторно пройтись по уже исправленным файлам и доделать изменения
2. использование ссылки на текущий объект в методах dataProvider плохая практика, от неё отказались

Теги:
+3
Комментарии0

Совет по Joomla: Как сделать ссылки на списки сущностей Joomla с фильтрацией?

Стандартная форма фильтрации в админке Joomlа
Стандартная форма фильтрации в админке Joomlа

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

Например:

  • разработчик хочет дать ссылку на плагин для быстрого перехода к настройкам;

  • разработчик хочет в документации для контент-менеджера дать ссылку на нужные модули, плагины, о которых идёт речь;

Админка Joomla поддерживает фильтры в URL-адресе, а названия GET-параметров для фильтрации можно посмотреть в названиях полей фильтров админки.

Например, в списке плагинов поле фильтра:

  • выбор состояния - filter[enabled]=1 или 0

  • выбор типа (группа плагинов) - filter[folder]={название группы плагина, например content или system}

  • element плагина (уникальное систеное имя) - filter[element]={element}

  • уровень доступа, с которым работает плагин - filter[access]={числовой-код-уровня-доступа}

  • строка поиска - filter[search]={любой%20текст%20для%20поиска}

Таким образом, чтобы дать ссылку на свой плагин в админке можно сделать следующий url:

https://your-joomla-site.ru/administrator/index.php?option=com_plugins&view=plugins&filter[element]=wtotpravkapochtaru&filter[folder]=system

Аналогичным образом работает список модулей, контактов, материалов и т.д. Найти имена параметров можно либо в HTML-коде страницы, либо в XML-форме опций фильтра нужного компонента. Для списка плагинов используется компонент com_plugins, а форма фильтра лежит в administrator/components/com_plugins/forms/filter_plugins.xml. Для списка материалов Joomla - в administrator/components/com_content/forms/filter_articles.xml. Другие компоненты - ищем по анналогии.

Чат русскоязычного Joomla-сообщества в Telegram и в Max.

Теги:
+3
Комментарии0

API Т‑Банка и сертификаты Минцифры: как использовать без установки на сервере

У меня есть Tg-бот, в нём я подключил оплату через платёжные ссылки Т-Банка. В какой-то момент ссылки перестали создаваться, в логах ошибка:
SSL certificate OpenSSL verify result: self-signed certificate in certificate chain (19)

Причина: Т и другие российские банки стали переходить на отечественные сертификаты, ибо зарубежные удостоверяющие центры стали отзывать свои сертификаты.

Варианты действий:

  1. Подключить другую платёжку, которая (пока) не импортозаместила сертификаты.

  2. Установить сертификаты на сервер (инструкция).
    Вам потребуется определённая степень доверия родному государству.
    На виртуальном хостинге так и вовсе может быть невозможно.

  3. Собрать свою цепочку из сертификатов и использовать её только при запросах к API российских банков.
    Подходит для виртуального хостинга.

Третьему варианту меня научила нейронка, вот порядок действий:

  1. Скачать сертификаты.

  2. Распаковать два архива и загрузить на сервер вот эти файлы:
    russian_trusted_root_ca_pem.crt
    russian_trusted_sub_ca_pem.crt
    russian_trusted_sub_ca_2024_pem.crt

  3. На сервере (у меня Ubuntu) скачать набор сертификатов от Mozilla:

    curl -fsSL -o cacert.pem https://curl.se/ca/cacert.pem
  4. Собрать объединённую цепочку:

    cat \
       cacert.pem \
       russian_trusted_root_ca_pem.crt \
       russian_trusted_sub_ca_pem.crt \
       russian_trusted_sub_ca_2024_pem.crt \
       > ru-ca-bundle.pem
  5. Проверить, что работает:

    curl -v --cacert ru-ca-bundle.pem https://mddc.tbank.ru/
  6. Посмотреть сроки действия сертификатов:

    openssl x509 -in russian_trusted_root_ca_pem.crt -noout -subject -issuer -dates
    openssl x509 -in russian_trusted_sub_ca_pem.crt -noout -subject -issuer -dates
    openssl x509 -in russian_trusted_sub_ca_2024_pem.crt -noout -subject -issuer -dates
  7. Выбрать минимальную из дат и поставить себе напоминалку, чтобы обновить их.

  8. Добавить использование этой цепочки в коде запросов к российским банкам.
    У меня на php это выглядит так:

    $caBundlePath = __DIR__ . '/ru-ca-bundle.pem';
    if (!is_readable($caBundlePath)) {
        myerror("Tinkoff CA bundle is not readable", ['path' => $caBundlePath]);
        return false;
    }
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => TINKOFF_INIT_URL,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $postDataJson,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'Content-Length: ' . strlen($postDataJson),
        ],
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2,
        CURLOPT_CAINFO => $caBundlePath,
    ]);
    
    $output = curl_exec($ch);

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

Теги:
+11
Комментарии2

Как я устал от бардака в «Избранном» Telegram и за два вечера запилил бесплатную интерактивную доску (без регистраций и СМС)

Всем привет!

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

Думаю, у многих из вас Telegram давно превратился в помойку из сотен каналов. Полезные статьи, гайды, рецепты, мемы, рабочие задачи — всё это мы обычно скидываем в «Избранное» (Saved Messages). И что происходит дальше? Правильно, «Избранное» превращается в черную дыру. Найти там что-то через неделю — это квест уровня «Индиана Джонс».

Особенно сильно у меня подгорало, когда я листал ленту с телефона в метро, находил сложный чек-лист или рабочую инструкцию, пересылал в «Избранное», а вечером открывал комп и... тратил кучу времени просто на то, чтобы откопать этот пост в каше из мемов и рабочих чатов. Выполнять задачи с экрана телефона — ад, а структурировать это в самом Telegram невозможно.

Мне это надоело. Я хотел простой инструмент: нашел на смартфоне -> скинул боту -> открыл на компе в виде красивых карточек. Посмотрел готовые сервисы — везде просят регистрацию, привязку карт, вылезает реклама или ограничения на 10 постов.

В итоге я психанул, выделил два вечера и написал свой костыль, который неожиданно превратился в отличный инструмент — TG-drop.ru.

Как я это устроил (без заумной архитектуры)

Система работает на связке «бот + база данных + веб-интерфейс». Всё гениальное просто:

  1. Вы листаете Telegram на телефоне и видите важный пост (гайд, чек-лист, статью).

  2. Пересылаете его моему боту. Бот мгновенно подхватывает его и сохраняет в изолированную таблицу.

  3. Вечером вы садитесь за ПК, открываете сайт, вводите свой Telegram ID (он нужен только как ключ, чтобы сайт понял, чьи посты показать) — и перед вами удобная интерактивная доска.

Почему это удобнее, чем просто Telegram?

Я делал проект для себя, поэтому сразу вырезал всё, что меня бесит в современном вебе:

  • Никаких регистраций вообще. Никаких вводов почты, подтверждений по SMS и придумывания паролей «с одной заглавной буквой и спецсимволом». Ввел ID — работаешь.

  • Живой поиск и фильтры. Когда постов становится много, вы можете искать по ключевым словам прямо в браузере. Всё фильтруется на лету, без перезагрузки страниц.

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

  • Конфиденциальность. Ваши посты подгружаются динамически. Никто другой вашу доску не увидит.

Кому это пригодится?

Изначально я думал о ребятах из крипты (охотники за Airdrop, тестнеты, DeFi-инвесторы), которым нужно по пунктам выполнять сложные активности с ПК, найдя их в мобильном телефоне.

Но в процессе понял, что штука закроет боли многих:

  • Контент-мейкеров и исследователей: собирать выжимки, инсайты и референсы в одном месте.

  • Студентов: скидывать материалы для курсовых и дипломов, чтобы потом структурировать на десктопе.

  • Да и вообще всех, кто использует Telegram как базу знаний и устал от хаоса в «Избранном».

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

Буду рад здоровой критике в комментариях! Чего вам не хватает в таком функционале? Что стоит добавить в первую очередь?

Теги:
Всего голосов 1: ↑1 и ↓0+3
Комментарии13

Как связать контейнеры Nginx и PHP в Docker Compose, чтобы Nginx мог проксировать запросы?

Допустим, вы пытаетесь развернуть связку из веб-сервера и PHP. Контейнеры поднимаются, но веб-сервер выдает ошибку сети и не может достучаться до PHP-бэкенда. Разберемся, что нужно прописать в конфиге Nginx, чтобы они увидели друг друга.

Чаще всего подобная проблема возникает из-за того, что контейнеры изолированы друг от друга на сетевом уровне, либо в конфигурационном файле веб-сервера некорректно указан адрес целевого хоста. В экосистеме Docker Compose встроенный DNS-сервер автоматически сопоставляет имена сервисов с их внутренними IP-адресами. Поэтому не нужно прописывать статические IP — достаточно правильно использовать имена, заданные в манифесте. 

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

Чтобы Nginx мог передавать запросы PHP-FPM, необходимо:

  • убедиться, что оба контейнера находятся в одной сети (app_network),

  • указать в конфигурации Nginx правильный адрес PHP-контейнера (в нашем примере это php:9000, где php — имя сервиса в docker-compose.yml).

Шаг 1: Проверка манифеста docker-compose.yml

Убедитесь, что для обоих сервисов явно выделена одна общая сеть. Пример корректной структуры:

version: '3.8'
services:
  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - "80:80"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/html:/var/www/html
    depends_on:
      - php
    networks:
      - app_network

  php:
    image: php:8.2-fpm
    container_name: php
    volumes:
      - ./php:/var/www/html
    networks:
      - app_network

networks:
  app_network:
    driver: bridge

Шаг 2: Настройка конфигурации Nginx

В блоке location, отвечающем за обработку PHP-скриптов, в директиве fastcgi_pass вместо 127.0.0.1 или localhost необходимо подставить имя сервиса PHP из файла конфигурации:

server {
    listen 80;
    server_name localhost;

    root /var/www/html;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass php:9000;  # Связь с PHP-контейнером
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

Директива depends_on в блоке Nginx гарантирует, что веб-сервер не начнет стартовать раньше, чем поднимется контейнер с PHP. Это предотвратит падение Nginx при первичном запуске окружения, если он не сможет сразу разрешить DNS-имя php.

Если вы хотите глубже разобраться в сетевых механизмах, управлении volumes и оркестрации контейнеров, читайте наш полный материал: Docker Compose и основы работы с контейнерами.

Теги:
Всего голосов 6: ↑6 и ↓0+11
Комментарии0

Фронтенд для души, бэкенд для людей!

Мастер по разводу холивар
Мастер по разводу холивар

Были приняты меры погрузиться под воду дабы показать серьезность моих намерений в данной щепетильной теме.

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

Бэкенд наоборот поддерживает порядок и структурность. Меньше экспериментов и больше проверенных решений, самое то для "сделал работу - пошел спокойно домой".

Теги:
Всего голосов 5: ↑3 и ↓2+3
Комментарии2

Большинство объяснений машинного обучения начинаются с нейронов, весов или градиентного спуска. Но есть одна деталь, без которой вся эта конструкция вообще не работает.

Откуда модель вообще узнаёт, что ошиблась? Именно с этого, как мне кажется, и стоит начинать изучение машинного обучения. В новой части книги я попытался объяснить это максимально просто и без фраз вроде "нейросеть сама обучается". Разбираем, что такое ошибка, почему она превращается в loss-функцию, зачем вообще нужны MSE и Log Loss, и как несколько строк математики становятся тем самым сигналом, который заставляет модель становиться лучше. Loss-функции являются центральным механизмом обучения современных моделей машинного обучения.

Если давно хотели понять, что происходит "под капотом" современных AI-моделей – буду рад, если почитаете.

📖 https://apphp.gitbook.io/ai-dlya-php-razrabotchikov-intuitivno-i-na-praktike/chast-ii.-obuchenie-kak-optimizaciya/2.1-oshibka-loss-funkcii-i-zachem-oni-nuzhny

Теги:
Всего голосов 2: ↑2 и ↓0+4
Комментарии0

За свою карьеру я успел попробовать Java, Python и ещё кучу всяких языков.

У каждого есть свои сильные стороны, ни один из них нельзя назвать "лучшим" для всех задач. Но заметил одну забавную вещь: спустя какое-то время я снова возвращаюсь к PHP.

Наверное, потому что за много лет он стал для меня чем-то вроде дома. Открыл проект – и всё такое родное )). Не нужно перестраивать мышление, вспоминать особенности экосистемы или синтаксиса.

В общем, в какой-то момент эта мысль показалась настолько забавной, что я решил сделать небольшую музыкальную пародию на известную песню (старый хит 70х) – только про PHP и разработчиков, которые "ушли, но вернулись".

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

🎬 Видео: https://youtu.be/SoqAP4gSDac

Звучит знакомо?

Теги:
Всего голосов 5: ↑5 и ↓0+9
Комментарии2

WT Max v.0.2.0. - библиотека для интеграции с Joomla

Обновление Joomla-библиотеки для API мессенджера MAX с системным плагином для настроек и диагностики подключения. Библиотека предназначена для разработчиков.

Расширение является Joomla-обёрткой над самостоятельным PHP Composer-пакетом Webtolk\Max, у которого так же состоялся релиз 0.2.0. PHP SDK разрабатывалось с учётом стандартов PSR и полностью не зависит от какого-либо фреймворка и/или пакета.

v.0.2.0. Что нового?

  • Подключена новая версия API-хоста: platform-api2.max.ru. Для корректной работы ваших чат-ботов и мини-приложений до 19 июля 2026 необходимо перенаправить HTTP-запросы с домена platform-api.max.ru на platform-api2.max.ru, а также добавить сертификат Минцифры в список доверенных. Как это сделать - ссылка на инструкция внизу поста. ‼️Если этого не сделать - вы получите уведомление об ошибке соединения и неверном сертификате.

  • Расширена публичная API-поверхность. Обновлены и дополнены методы для работы с чатами и сообщениями (включая новые сценарии по ссылкам на чат и выборке по query-id сообщения). Удалены устаревшие методы.

  • Обновлён набор публичных JSON-схем. Добавлены и синхронизированы схемы для новых и изменённых endpoint-ов. Эти схемы - снимки реальных ответов API Max, так как мы прекрасно знаем, что документация и реальное API может отличаться порой очень и очень значительно.

  • Обновление документации. README, стартовые руководства, референсы и описания сущностей/пэйлоадов приведены к текущему API-уровню.

Ссылки:

Теги:
Всего голосов 3: ↑2 и ↓1+3
Комментарии0

Прямая Web3-монетизация без посредников (Peer-to-Peer) для артистов на радио.

Буквально вчера закончил написание сервисного бота для коммерческих нужд в мессенджере "Concord". Основной целью проекта является автоматизация процессов публикации авторского материала на интернет-радио. Бот был создан как помощник для авторов аудиоконтента: музыкантов, продюсеров, подкастеров и т. п.

Задача была непростой. Нужно было объединить возможности мессенджера с его токеномикой и реализовать передачу медиаконтента (картинок, аудиофайлов, текстовых данных) на удаленный сервер в формате JSON. Для этого я написал серверную страницу на PHP, в которой реализовал весь необходимый API.

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

function isJpeg(string $data): bool
{
    return substr($data,0,2) === "\xFF\xD8";
}

function isMp3(string $data): bool
{
    if (substr($data,0,3)==="ID3") {
        return true;
    }

    return isset($data[1])
        &&
        ord($data[0])===0xFF
        &&
        (ord($data[1]) & 0xE0)===0xE0;
}

После получения данных нужно сразу определить что именно пришло - команда или файл:

if (preg_match('/^\/(help|bio|title|tracks|done)\b/i', $data))
{
    processCommand($db, $uuid, $data);
    exit;
}

if (isBase64($data))
{
    saveBinary($db, $uuid, $data);
    exit;
}

reply("Unknown command, please use /help.", false);

Описание профиля артиста и названия его треков передаются в текстовом виде используя специальный набор команд:

  • /help - Show this help

  • /bio text - Update artist biography

  • /tracks - Show info of all tracks

  • /title text - Update current track title

  • /pay amount - Pay for service

  • /done - Finalize current track

  • Send JPG image to update artist image

  • Send MP3 audio to update current track

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

  1. артист отправляет фото профиля

  2. артист отправляет описание профиля

  3. артист загружает трек

  4. артист отправляет описание трека

  5. артист выполняет оплату сервиса

  6. артист финализирует трек

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

МОНЕТИЗАЦИЯ

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

Таким образом, технология Web3 с использованием блокчейна позволяет оперативно выполнять оплату за предоставленный сервис без лишних трат и банковских процедур. При этом все транзакции становятся видны в блокчейне уже через несколько минут.

схема работы блокчейна
схема работы блокчейна

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

Таким образом, объединение двух разных сущностей, а именно интернет-радио с приложением для обмена сообщениями, является неким ноу-хау для оказания помощи в развитии молодых дарований. Лично для меня как для разработчика это отличный вызов и прекрасная возможность "пошевелить мозгами".

Если у вас появятся предложения, буду рад подискуссировать.

Теги:
Всего голосов 6: ↑2 и ↓40
Комментарии6

Облачный сервис с безграничными возможностями: Бот или не бот - вот в чем вопрос.

Друзьям и коллегам, привет!

Недавно опубликовал на Хабр новую статью с разбором моего Web3-мессенджера. В ней описал личный кейс: как внедрить децентрализованные Web3 технологии и монетизировать внутренние функции приложения без подключения классических платежных систем. Почитать можно здесь: https://habr.com/ru/articles/1052088/

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

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

В таких популярных приложениях как Telegram или WhatsApp, боты представляют собой отдельные сущности, которые привязываются к основному аккаунту пользователя. Кстати, вопреки расхожему мнению, один аккаунт в Telegram может создать через BotFather не безграничное число ботов, а строго до 20 штук (до 40 для Premium-пользователей).

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

пример бота реализующего сервис загрузки музыкального контента артиста на радио
пример бота реализующего сервис загрузки музыкального контента артиста на радио

Хотя при таком методе не получится создать «армию ботов» на один аккаунт. На каждого бота придется заводить новый. Но с точки зрения безопасности и чистоты архитектуры плюсы очевидны:

  • Полный контроль и безопасность окружения: бот изолирован и работает строго в рамках правил реального пользователя.

  • Защита от фишинга: это минимизирует риски мошенничества, делая бота реальным, полноценным аккаунтом, а не простой сервисной записью в базе данных.

  • Готовая монетизация: в профиле каждого пользователя уже прописаны платежные данные в виде Web3-кошелька. Соответственно, они автоматически доступны и боту, если тот реализует платные услуги.

РЕАЛИЗАЦИЯ НА БЭКЕНДЕ

Ниже упрощенный код класса реализующий передачу сообщений на Endpoint:

public async Task<string> ExecuteCommand(string cmd, string uid, string token, string url)
{
    using var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new ("Bearer", token);
    
    var body = new StringContent(JsonConvert.SerializeObject(new { data = cmd, user_id = uid }), Encoding.UTF8, "application/json");
    var res = await client.PostAsync(url, body);
    var json = JObject.Parse(await res.Content.ReadAsStringAsync());

    return json["success"]?.Value<bool>() == true 
        ? json["data"]?.ToString() 
        : $"Error: {json["error"]}";
}  

Рабочий шаблон внешнего Endpoint сервиса:

<?php
session_start();
header('Content-Type: text/html; charset=utf-8');

//AUTHENTICATION BEGIN

$allowedToken   = 'super-secret-token';
$providedToken  = '';

if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
    if (preg_match('/Bearer\s+(.+)/i', $_SERVER['HTTP_AUTHORIZATION'], $m)) {
        $providedToken = trim($m[1]);
    }
}

if (empty($providedToken) || $providedToken !== $allowedToken) {
    echo json_encode(['success' => false, 'error' => 'error token']);
    exit;
}

//AUTHENTICATION END

$rawInput = file_get_contents('php://input');
$userData = json_decode($rawInput, true); 

echo json_encode(['success' => true, 'data' => 'Bot answer: ' . $userData['data'] ?? null]);

?>

ВЫВОД

Используя описанную концепцию, можно в теории реализовать любой сервис не изменяя при этом основное приложение. Всё что нужно сделать, построить бот!

Очевидно, что для практического применения такого подхода необходимо обеспечить высокий уровень безопасности: внедрить защиту от SSRF (через валидацию URL и фильтрацию локальных хостов), настроить лимиты для предотвращения DoS-атак (проверяя размер заголовков и длину полученной строки), и так далее.

Всем успехов в разработке!

Благодарю за внимание.

Теги:
Всего голосов 2: ↑2 и ↓0+4
Комментарии0

Лучше не сохраняйте в сессии PHP объекты с защищенными или приватными свойствами, если сама сессия хранится в БД.

Оговорюсь, что не поддерживаю сохранение объектов в сессиях PHP, а пример взят из Legacy-проекта, в котором компонент рекомендованных продаж клиенту реализован в виде класса. Видимо предыдущие разработчики посчитали удобным не париться с сохранением рекомендаций в виде отдельной структуры, а сохраняли класс прямо в сессию клиента. Сами сессии хранятся в БД MySQL (тоже тема для отдельной дискуссии).

Всё это отлично работало до переезда БД на кодировку utf8mb4_general_ci. После чего начались плавающие ошибки: некоторых пользователей стало выкидывать из ПУ. Довольно быстро определили, что проблема с сессиями, чуть больше времени потребовалось, чтобы определить, что некоторые сессии внезапно становились битыми у тех клиентов, для которых срабатывал сервис подбора рекомендаций.

Немного теории. Оказалось, что PHP сохраняет свойства объектов в сессии с определенными особенностями:

  • публичные свойства `public $item` сохраняются как item

  • защищенные свойства `protected $item` сохраняются как \0*\0item

  • приватные свойства `private $item` сохраняются как \0ClassName\0item

причем \0 это нулевой байт. Главной проблемой стало то, что MySQL воспринимал этот нулевой байт как конец строки и сохранял в таблицу обрезанную строку. Сессия становилась невалидной.

Самое простое решение в данном случае изменить тип поля на BLOB, в этом случае текст корректно сохранится побайтово. По поводу вопроса, стоит ли сохранять объекты в сессию пользователя, каждый думаю решит для себя сам.

Теги:
Всего голосов 2: ↑2 и ↓0+4
Комментарии0

Ближайшие события

Ваш худший кошмар, или простой regex, который удивит даже опытных программистов.

re.match(r"^abc$", "abc\n") # python
/^abc$/.test("abc\n") // Javascript
preg_match("/^abc$/", "abc\n"); // PHP

Не читайте дальше, попробуйте угадать какой вывод будет у каждого из вариантов?

False?

True ?

Правильный ответ:

False
True
False

Живите с этим :)

Всё дело в том, что в PCRE $ означает не "конец строки", а "конец строки, или позиция перед \n в конце строки". А в ECMAScript это не так.

Лично я думал, что должно быть False, но регулярные выражения продолжают меня удивлять спустя много лет.

Правильный regex для точного совпадения с концом строки:

re.match(r"^abc\Z", "abc\n")
// javascript идеален, нечего исправлять :)
preg_match("/^abc\p/", "abc\n")

== false

Теги:
Всего голосов 10: ↑7 и ↓3+8
Комментарии3

Паттерны проектирования еще актуальны?

Вокруг все чаще говорят, что ИИ скоро будет писать код за нас. Логичный вопрос — нужны ли тогда паттерны? Зачем разбираться в паттернах GoF, если нейросеть и так сгенерирует рабочий код по описанию?

У меня ощущение обратное.

Я плотно вошел в разработку в 2019 году. Переходил из 1С в .NET. Книги по паттернам GoF у меня были, но долго лежали как «книга на полке». Казалось, они оторваны от повседневных задач. Теорию вроде понимал, но не видел, где это реально применяется.

Все поменялось, когда я стал использовать ИИ как инструмент для обучения. Просил давать задачи, искать проблемы в решениях, объяснять, почему в одном месте уместен Strategy, а в другом лучше Mediator. Через практику и обсуждение паттерны перестали быть абстракцией.

Чем проще генерировать код, тем важнее понимать его форму и границы. Иначе не ускоришь разработку, а ускоришь накопление технического долга.

Из этого и вырос мой pet-project gofinsights.com. Я делаю его тренажером по паттернам проектирования. Не просто «прочитал и забыл», а через практику, сравнение решений и постепенное распознавание типовых архитектурных ходов.

Сейчас там есть интерактивный квиз, где можно проверить базу и не перепутать Factory Method с Abstract Factory. Дальше хочу развивать проект в сторону более глубокого ИИ-разбора. Чтобы можно было не только узнавать паттерн, но и разбирать кодовые запахи, причины проблем и возможную эволюцию решений.

Как вы это видите? Паттерны проектирования все еще рабочая база для разработчика? Или с появлением ИИ они станут менее важны?

Теги:
Всего голосов 6: ↑5 и ↓1+6
Комментарии1

BloggyCms v1.0.0-rc.4

Наконец-то спустя почти год и два месяца моя CMS-ка для ведения блога получила более менее внятный релиз-кандидат, в котором ошибок осталось не так много, и в принципе система уже легко ставится на хостинг и управляется.

Дашборд системы
Дашборд системы

Впереди - куча оптимизации, например вынесение всех форм шаблона админки в контроллеры, и последующий их рендеринг через render_form(). Данные контроллеров в json и так далее.

Но - текущая версия движка с последующими обновлениями уже не сломается, как это было в первых релизных версиях.

Ну и самое главное - официальный сайт. Как оказалось - это одна из тех задач, которая весьма объемна и кропотлива - это и документация, и каталог дополнений с API для разработчиков и еще много-много чего.

Приглашаю к тестированию: https://github.com/pechoradev/BloggyCms

Также буду рад видеть новых контрибьюторов CMS.

Теги:
Всего голосов 4: ↑3 и ↓1+2
Комментарии24

Мультиязычность. Ад для разработчика.

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

И понеслась...

Процесс перевода движка
Процесс перевода движка

Это хорошо, что сейчас есть нейросети и они здорово упрощают процесс перевода. Но - по старинке все делаю вручную, каждый файл...Сначала размечаю обыкновенными дефайнами либо класс контроллера, либо шаблона, ну а потом выношу это все в соответствующие языковые папки.

Вайбкодеры меня наверняка закидали бы тапками, мол - все можно автоматизировать и перевести хоть тонну файлов за 20 минут. Но - мне это не в кайф =)

Кто хочет помочь в процессе перевода, а заодно и движок потестить - милости прошу: https://github.com/pechoradev/BloggyCms

Теги:
Всего голосов 3: ↑3 и ↓0+3
Комментарии21

Господа фрилансеры!

20 лет я жил фрилансом. Искал заказы на fl.ru, договаривался на почасовую оплату, и спокойно работал в своем темпе. Поднимал сложные проекты, немного тимлидил, рос в навыках и т.п. Казалось, так будет всегда. Начинал я с PHP 3, каши из кода, вперемешку с html. Потом писал самопальные фреймворки, ускоряющие разработку. Со временем код становился чище, я освоил yii, yii2, Laravel втянулся в solid, научился в high load и т.п

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

Так вышло, что последние 7 лет я полностью перешел на постоянных заказчиков. Просто раз в пару месяцев выставлял им счет, исходя из 1000-1500р в час потраченного времени - всех все устраивало, мне платили без лишних вопросов, доверяли на слово. Но ничто не вечно в этом мире - старые проекты себя исчерпали, и пора искать новую работу. И тут я обнаружил, что старый подход больше не работает. Fl почти умер, заказов не найти. На hh - по 500-1000 откликов к каждой вакансии. Да и не хочу я работать с 9 до 18.

Появились какие-то новые биржи, основанные на попроектной оплате (типа, вставить виджет за 1к рублей). Но так полную занятость, обеспечивающую ежемесячный доход хотя бы в 150к, не найти. Ведь на поиск заказа, обсуждение деталей, получение доступов, вкуривание в новый код и т.п. уходит целый день, и, получается, что фактическая стоимость часа - 100-200р в час. А разработку сложных проектов не оценить сразу - в процессе всегда задачи разрастаются в несколько раз.

Что делать? Как в нынешних реалиях найти работу простому кодеру, привыкшему к свободному графику и обладающему огромным "жизненным опытом"?) Чтобы просто можно было заполнить весь рабочий месяц, работать по 4-6 часов в день, без беготни по задачкам на 1-2к рублей.

P.S. в качестве пруфа, что история не выдуманная, ссылка на профиль https://www.fl.ru/users/namo/portfolio/

Теги:
Всего голосов 5: ↑4 и ↓1+5
Комментарии6

Логистическая регрессия на MNIST (0 vs 1) на PHP: простой пример

Если вам хочется не просто читать про машинное обучение, а попробовать сами – вот хороший учебный кейс.

Разбираем классическую задачу: бинарная классификация цифр (0 vs 1) на датасете MNIST (12 666 обучающих и 2 116 тестовых примеров) с помощью логистической регрессии, обученной через gradient descent. Всего 5 эпох – но результат всё равно шокирующе высокий. :)

Что тут интересного:

  • можно наглядно посмотреть, как модель работает с изображениями (в виде векторов)

  • становится понятно, где линейные модели начинают "ломаться"

  • можно посмотреть код чистой реализации на PHP и самому покопаться в коде
    – точность: 99.91%

  • и сравнить с более практичным вариантом на RubixML
    – точность: 99.95%

Это хороший переход от теории к практике: без заумных вещей, с понятной математикой и кодом.

Разбор:
https://apphp.gitbook.io/ai-for-php-developers/chast-iii.-klassifikaciya-i-veroyatnosti/logisticheskaya-regressiya/prakticheskie-keisy/mnist-binarnaya-klassifikaciya-otlichaem-0-ot-1

Примеры:
https://aiwithphp.org/books/ai-for-php-developers/examples/part-3/logistic-regression/case-0/mnist-0-1

Теги:
Всего голосов 3: ↑1 и ↓2+1
Комментарии0

Три доклада с Backend-митапа Garage Eight

> AI в travel tech — но не ради хайпа
Спикер: Глазунов Илья, backend lead в сервисе бронирования «ЖилиБыли»
YouTube | VK Видео

> Собрать LLM-стек для PHP за один вечер и не выстрелить себе в ногу
Спикер: Якимов Андрей, backend-разработчик Garage Eight
YouTube | VK Видео

> Модульная архитектура против хаоса: как ограничить контексты в большом монолите
Спикер: Русин Иван, старший разработчик группы модернизации платформы Flowwow
YouTube | VK Видео

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

Теги:
Всего голосов 5: ↑5 и ↓0+5
Комментарии0