,

23 ноября, 2024

DeFi. Что такое децентрализованные финансы

Всем привет! Сегодня хочу рассказать о технологии, которая меня заинтересовала — децентрализованные финансы (DeFi).

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

  1. Зависимость от посредников
    Деньги и данные приходится доверять банкам, брокерам и другим организациям, что несет риски утраты средств из-за ошибок, злоупотреблений или банкротства.
  2. Ограниченный доступ
    Некоторые регионы остаются отрезанными от финансовых услуг из-за слабой инфраструктуры или высоких требований со стороны учреждений.
  3. Высокие комиссии
    Централизованные учреждения часто берут значительные комиссии за переводы, обслуживание счетов и другие операции.
  4. Контроль со стороны третьих лиц
    Банки и другие организации могут устанавливать лимиты, замораживать счета или накладывать ограничения.
  5. Уязвимость для кибератак
    Централизация делает крупные финансовые структуры привлекательными для хакеров.

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

Что такое DeFi

DeFi (Decentralized Finance) — это один из самых горячих трендов в мире блокчейнов и криптовалют. На русском языке термин переводится как «децентрализованные финансы», что дает намек на его суть. DeFi — это финансовые услуги, которые работают без посредников, таких как банки, используя блокчейн и смарт-контракты.

Основные принципы DeFi

  1. Децентрализация: Вместо того чтобы полагаться на банки или другие учреждения, все операции происходят в блокчейне. Это устраняет необходимость в посредниках.
  2. Прозрачность: Любой пользователь может проверить транзакции в сети, что обеспечивает высокую степень доверия.
  3. Доступность: DeFi-платформы открыты для всех. Нужен только интернет и криптовалютный кошелек.
  4. Автоматизация: Используются смарт-контракты, которые автоматически выполняют условия сделки.

Основные направления применения DeFi

  1. Децентрализованные биржи (DEX)
    Это платформы для обмена криптовалют, такие как Uniswap или SushiSwap. В отличие от традиционных бирж, здесь нет центрального органа управления. Сделки заключаются напрямую между пользователями.
  2. Кредитование и займы
    DeFi позволяет брать и давать займы без участия банков. Пример платформы — Aave. Кредиторы могут зарабатывать проценты, а заемщики использовать свои криптоактивы как залог.
  3. Доходное фермерство (Yield Farming)
    Пользователи предоставляют ликвидность (свои активы) для работы протоколов и получают за это вознаграждение.
  4. Стейблкоины
    DeFi активно использует стейблкоины, такие как USDT, DAI и USDC, которые привязаны к стоимости фиатных валют, что снижает волатильность.
  5. Страхование
    В DeFi существуют платформы, которые предоставляют услуги страхования, такие как Nexus Mutual. Они защищают пользователей от финансовых рисков, например, хакерских атак.
  6. Токенизация активов
    DeFi позволяет токенизировать реальные активы, такие как недвижимость, акции или драгоценные металлы, делая их доступными для торговли.

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

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

, ,

10 ноября, 2024

Что такое стейблкоины и зачем они вообще нужны?

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

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

Какие бывают стейблкоины?

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

1. Фиатные стейблкоины

Это самые популярные стейблкоины, например USDT (Tether), USDC (USD Coin) и BUSD (Binance USD). Такие монеты обеспечены реальными деньгами на банковском счёте или ликвидными активами. Один USDT или USDC всегда должен быть равен одному доллару, потому что за ним лежит настоящий доллар или его эквивалент. Фирмы, которые выпускают такие стейблкоины, должны регулярно доказывать наличие резервов для поддержания доверия.

2. Криптообеспеченные стейблкоины

Эти стейблкоины обеспечены криптовалютами. Самый известный пример — DAI от проекта MakerDAO. В отличие от USDT или USDC, здесь используется алгоритм и резерв криптовалюты (чаще всего ETH) для обеспечения курса. Поскольку криптовалюта нестабильна, такие стейблкоины часто имеют избыточное обеспечение — то есть на каждый доллар DAI приходится больше одного доллара в крипте, чтобы компенсировать возможные колебания.

3. Алгоритмические стейблкоины

Здесь ситуация интереснее. Эти стейблкоины вообще не имеют реального обеспечения, а удерживают курс с помощью алгоритмов и смарт-контрактов. Примеры: UST (Terra), FRAX. Механизм такой: если цена монеты падает ниже доллара, алгоритм сжигает часть монет, уменьшая их предложение и повышая цену. Если цена выше доллара, выпускаются новые монеты, снижая курс. Однако такие модели несут риск, так как устойчивость зависит только от алгоритма и спроса на рынке.

Стейблкоины в программном коде

Если рассмотреть стейблкоин с точки зрения кода, то это смарт-контракт, который выполняет разные функции по управлению выпуском и сжиганием монет. Наиболее распространённый стандарт для создания таких токенов на Ethereum — это ERC-20, который поддерживает базовые функции для создания и передачи токенов. Однако у стейблкоинов есть и уникальные особенности, которые добавляются к стандарту.

Вот базовый пример смарт-контракта стейблкоина на Solidity:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract StableCoin is ERC20, Ownable {
    constructor() ERC20("MyStableCoin", "MSC") {
        _mint(msg.sender, 1000000 * 10 ** decimals());
    }

    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }

    function burn(uint256 amount) public {
        _burn(msg.sender, amount);
    }
}

Что здесь происходит?

  • ERC20 — мы используем стандарт ERC-20, который предоставляет функции для работы с токенами: transfer, balanceOf, allowance и другие.
  • Ownable — это модификатор, который даёт владельцу контракта (обычно компании-эмитенту) возможность управлять ключевыми функциями. Например, только владелец может «минтить» (выпускать) новые токены.
  • mint — функция для выпуска новых токенов. В фиатных стейблкоинах такие функции используются, когда компания пополняет резервы.
  • burn — функция для сжигания токенов, если их нужно вывести из обращения.

Этот код — очень базовый пример. На практике контракты стейблкоинов гораздо сложнее, включают управление резервами, автоматическое регулирование курса и часто проходят аудиты безопасности. Также они могут включать функции «заморозки» или блокировки счетов, что может использоваться для соблюдения законодательства.

Стейблкоины — это важная часть криптоиндустрии, мост между волатильной криптой и стабильным фиатом. Они удобны для трейдинга, хранения средств и даже для международных переводов, так как транзакции могут быть намного дешевле и быстрее, чем в традиционных банках. С технической стороны стейблкоин — это токен со стандартным функционалом ERC-20, но с добавлением функций для поддержания курса и управления резервами.

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

, ,

9 ноября, 2024

Что такое Solidity и для чего используется

Что такое Solidity и зачем он вообще нужен?

Solidity — это язык программирования, созданный специально для разработки смарт-контрактов на блокчейне Ethereum. Если ты когда-нибудь хотел создать свою крипту, сделать децентрализованное приложение (dApp) или написать контракт, который сам выполняет условия, как только они наступят, то Solidity — это твой инструмент. На этом языке пишутся «самоисполняющиеся» контракты, которые потом живут в блокчейне, то есть никто их не может изменить или удалить, и они автоматически выполняют всё, что в них прописано.

Где применяется Solidity?

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

  • Binance Smart Chain,
  • Polygon,
  • Avalanche,
  • Fantom.

Эти блокчейны поддерживают виртуальную машину Ethereum (EVM), которая выполняет контракты, написанные на Solidity. Вот несколько популярных применений Solidity:

  • Токены: Можешь создать свою криптовалюту, например, на стандартном шаблоне ERC-20. Это именно те «монетки», которыми торгуют на биржах.
  • NFT: Уникальные цифровые активы (например, произведения искусства или предметы коллекционирования) тоже создаются на Solidity, часто с использованием стандарта ERC-721.
  • Децентрализованные финансы (DeFi): Можно писать контракты для кредитования, ставок, торговли и других финансовых операций без посредников.
  • DAO: Децентрализованные автономные организации, в которых решения принимаются на основе смарт-контрактов и голосования участников.
  • Игры и децентрализованные приложения (dApps): Контракты на Solidity управляют логикой игр и других приложений, где нужен блокчейн.

Как работает Solidity и с чего начать?

Solidity компилируется в байт-код, который понимает EVM. То есть, мы пишем код на Solidity, компилируем его, и после этого он становится «понятен» блокчейну. Если хочешь начать, тебе понадобится среда разработки, которая поддерживает Solidity, например:

  1. Remix — бесплатный веб-инструмент, созданный для Solidity-разработки. Он работает прямо в браузере и идеально подходит для старта.
  2. Truffle и Hardhat — фреймворки для локальной разработки, тестирования и развертывания контрактов. Они дают больше возможностей, чем Remix, и больше подходят для продвинутых проектов.
  3. MetaMask — кошелёк для взаимодействия с блокчейном Ethereum, который пригодится для тестирования и развертывания контрактов.

Основы синтаксиса Solidity

Solidity напоминает C++ и JavaScript, так что если ты знаком с этими языками, разобраться будет проще. Давай начнём с простейшего примера контракта.

Простой контракт: «Привет, мир!»

Вот минимальный код, который создаёт контракт, хранящий одну строку:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract HelloWorld {
    string public greeting = "Hello, World!";
}
  • pragma solidity ^0.8.0; — указывает версию Solidity (в данном случае 0.8 и выше).
  • contract HelloWorld — объявляем контракт с именем HelloWorld.
  • string public greeting — создаём переменную greeting, доступную всем (она публичная), и сразу присваиваем ей значение "Hello, World!".

Запустив этот контракт, ты сможешь увидеть строку "Hello, World!", просто вызвав переменную greeting.

Пример контракта для хранения чисел

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

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SimpleStorage {
    uint256 private storedData;

    // Функция для записи значения
    function set(uint256 x) public {
        storedData = x;
    }

    // Функция для чтения значения
    function get() public view returns (uint256) {
        return storedData;
    }
}

Этот контракт хранит значение и позволяет его записывать и считывать. Основные моменты:

  • uint256 private storedData; — переменная storedData для хранения числа, которая доступна только внутри контракта.
  • set(uint256 x) — функция для записи значения в storedData.
  • get() — функция для получения текущего значения storedData.

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

Пример контракта для создания простого токена

А вот пример создания базового токена на стандартном шаблоне ERC-20. ERC-20 — это стандарт для токенов, которые могут передаваться и торговаться. В реальной жизни можно добавлять дополнительные функции, но вот базовый пример:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MyToken is ERC20 {
    constructor() ERC20("MyToken", "MTK") {
        _mint(msg.sender, 1000 * 10 ** decimals());
    }
}
  • Мы подключаем библиотеку OpenZeppelin, чтобы не писать всё с нуля. Она предоставляет готовые стандарты, включая ERC-20.
  • constructor — это специальная функция, которая выполняется один раз при создании контракта. Здесь мы называем токен MyToken с символом MTK.
  • _mint(msg.sender, 1000 * 10 ** decimals()); — создаёт 1000 токенов и отправляет их на кошелёк создателя.

Запустив этот контракт, ты получишь свои токены прямо на кошелёк! Их можно передавать, использовать в других dApps, или даже листить на бирже (при выполнении дополнительных условий).

Советы для работы с Solidity

  1. Начинай с простых контрактов: Это поможет понять, как работает блокчейн и какие функции обязательны.
  2. Используй тестовые сети: Разворачивай контракты в тестовых сетях (например, Rinkeby или Ropsten), чтобы не тратить настоящие деньги.
  3. Будь осторожен с безопасностью: Ошибки в смарт-контрактах могут привести к уязвимостям. Изучай лучшие практики, такие как использование библиотеки OpenZeppelin, и обязательно проверяй код перед запуском.
  4. Тестируй код: Перед тем как контракт развернётся в реальной сети, обязательно протестируй его на различных сценариях.

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

Если тебе так же интересна разработка под Solidity и все что связано с блокчейном, смарт-контрактами и разработкой под web3, то обязательно пиши мне в телегу, нам будет что обсудить!

, ,

8 ноября, 2024

Что такое смарт контракт и с чем его едят :)

Что такое смарт-контракт и как он работает?

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

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

Как устроен смарт-контракт?

Смарт-контракт размещается в блокчейне — это значит, что он доступен всем, его нельзя подделать, и он всегда будет работать так, как было задумано. Как только условия выполняются, контракт автоматически совершает действия. Стороны могут быть уверены, что никто не вмешается и не изменит условия после запуска контракта.

Пример смарт-контракта на Solidity

Solidity — это популярный язык программирования для создания смарт-контрактов на платформе Ethereum. Если вы хотите попробовать написать свой смарт-контракт, вот простой пример:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SimpleStorage {
    uint256 private storedData;

    // Сохраняем значение
    function set(uint256 x) public {
        storedData = x;
    }

    // Получаем значение
    function get() public view returns (uint256) {
        return storedData;
    }
}

Что тут происходит:

  • pragma solidity ^0.8.0; — это версия Solidity, которая гарантирует, что код будет совместим с текущей версией.
  • uint256 private storedData; — переменная, которая хранит число. Она приватная, так что доступна только из этого контракта.
  • set(uint256 x) — функция, которая позволяет записать значение в переменную.
  • get() — функция, возвращающая значение storedData, просто читает данные.

В этом контракте всё просто: мы можем задать какое-то число и потом получить его. Такой код можно развернуть в блокчейне, и он всегда будет там работать так, как запрограммировано.

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

, , ,

7 ноября, 2024

Устанавливаем Shadowsocks на свой сервер

Для начала стоит объяснить, что такое Shadowsocks и для чего он может быть полезен.

Иногда вы можете оказаться в сети с ограничениями, где фильтруется интернет-трафик, и доступ к определённым ресурсам блокируется. Такие ограничения могут встречаться, например, в корпоративной сети на работе. Если вам необходимо обойти такие блокировки и получить доступ к нужным сайтам, на помощь может прийти инструмент под названием Shadowsocks. По сути, это прокси-сервер, который использует протокол SOCKS5 для передачи данных.

Протокол SOCKS5 позволяет создать зашифрованное соединение и направлять трафик через него, делая его менее заметным для фильтров и блокировок. В этой статье я расскажу, как быстро развернуть свой прокси-сервер с использованием Shadowsocks. Чем-то это напоминает создание шифрованного тоннеля через ssh.

Для начала вам необходим свой сервер. Если у вас еще нет своего сервера, то переходите по ссылке и зарегистрируйте его. Хостинг дает сутки на тестирование, поэтому можно проверить как работает тот же sadownsocks, например.

После того как у вас появился свой сервер, необходимо установить shadowsocks
это легко сделать при помощи нескольких команд:

$ sudo apt update
$ sudo apt install shadowsocks-libev

Теперь нужно создать основной файл с настройками shadowsocks. Поэтому создаем в /etc/shadowsocks-libev файл config.json со следующем содержимым:

{
    "server": "[server]",
    "server_port": "[server_port]",
    "password":"[password]",
    "mode":"tcp_and_udp",
    "timeout": 300,
    "local_port": "[local_port]",
    "method": "xchacha20-ietf-poly1305",
    "fast_open": true,
    "nameserver": "8.8.8.8"
}

server — ip адрес сервера
server_port — сервер порт через который будет создан тоннель ( замените на свой )
password — пароль подключения ( замените на свой )
method — метод шифрования ( если не уверены, то лучше оставить такой как в примере )
local_port — порт на локальной машине через который будет проходить зашифрованный трафик

Если у вас на сервере установлен файрвол, то необходимо открыть порт, который был указан в настройках:

$ sudo ufw allow [server_port]
$ sudo ufw reload

Теперь можно запустить shadowsocks:

$ sudo systemctl restart shadowsocks-libev

После этого на сервере все готово и можно приступать к настройке клиентской части.

Для того, чтобы запустить зашифрованный socks5 на вашей локальной машине потребуется установить Shadowsocks клиент. Вот несколько вариантов для разных систем:

Windows

  1. Shadowsocks for Windows — Официальный клиент с графическим интерфейсом.
  2. ShadowsocksR — Модифицированная версия Shadowsocks, поддерживающая дополнительные шифрования и функции.
  3. Outline — Простой в использовании клиент, который также поддерживает Shadowsocks и удобен для новичков.

macOS

  1. ShadowsocksX-NG — Популярный клиент для macOS с поддержкой Shadowsocks и дополнительными функциями.
  2. Outline — Также доступен для macOS, позволяет легко подключаться к Shadowsocks-серверам.

Linux

  1. Shadowsocks-libev — Лёгкий клиент для Linux, поддерживающий командную строку и простой в настройке.
  2. Outline — Клиент с графическим интерфейсом, доступный для нескольких версий Linux.
  3. Shadowsocks-qt5 — Версия с графическим интерфейсом, подходящая для пользователей, предпочитающих GUI.

Android

  1. Shadowsocks for Android — Официальное приложение для Android с поддержкой настроек и переключений.
  2. ShadowsocksR Android — Вариант с дополнительными настройками и функциями.
  3. Outline — Отличный вариант для пользователей, которые хотят быстро подключиться без сложных настроек.

iOS

Outline — Простое и удобное приложение, особенно для начинающих.

Shadowrocket — Один из самых популярных и мощных клиентов для iOS, поддерживает Shadowsocks и другие протоколы.

Potatso Lite — Поддерживает Shadowsocks и имеет удобный интерфейс.

Выбираем подходащий клиент и настраиваем соединение в нем для сервера на который поставили shadwonsocks

После установки соединения SOCKS5 будет доступен на локальной машине на порту local_port который ранее мы указали в настройках shadownsock на сервере

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

,

19 октября, 2024

Пишем крестики нолики на javascript :)

Ради развлечения решил вспомнить немного JS и вот что в итоге получилось! Простая игра на Javascript — крестики нолики

Вот шаблон html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <link rel="stylesheet" href="x0.css">
    <script src="x0.js"></script>
</head>
<body>
<div class="status"></div>
<div class="gamespace"></div>
</body>
</html>

Код стилей x0.css

.gamespace .row * {
    box-sizing: border-box;
}
.gamespace .row {
    display: flex;
    flex-wrap: wrap;
}
.gamespace .col {
    width: 33%;
    position: relative;
    overflow: hidden;
    border: 3px solid #000;
}
.gamespace .col:after {
    content: "";
    padding-top: 100%;
    float: left;
}
.gamespace .item {
    position: absolute;
    width: 100%;
    height: 100%;
    display: flex;
    flex-flow: column;
    align-items: center;
    justify-content: center;
    color: #000;
    font-size: 8em;
}
.gamespace {
    width: 30%;
    margin: 0 auto;
}
.status {
    text-align: center;
    font-size: 2em;
}

И собственно сама бизнес логика приложения

window.addEventListener('load', function () {
    window.game = {
        finishGame: false,
        cells: 3,
        players: {
            zero: {
                value: 0,
                symbol: '0',
            },
            crosse: {
                value: 1,
                symbol: 'X',
            }
        },
        activePlayer: null,
        result: [
            [null, null, null],
            [null, null, null],
            [null, null, null]
        ],
        init: function() {
            this.activePlayer = this.players.crosse;
            this.createGameSpace();
            document.querySelector('.status').innerHTML = 'Ходит игрок: ' + this.activePlayer.symbol;
        },
        createGameSpace: function() {
            let gamespace = '';
            for(let i = 0; i < this.cells; i++) {
                gamespace += this.createRow(i);
            }
            document.querySelector('.gamespace').innerHTML = gamespace;
        },
        createRow: function(i) {
            let row = document.createElement('div');
            row.classList.add('row');
            for(let j =0; j < this.cells; j++) {
                let col = document.createElement('div');
                col.classList.add('col');
                col.insertAdjacentHTML('beforeend', this.createItem(i, j));
                row.insertAdjacentHTML('beforeend', col.outerHTML);
            }

            return row.outerHTML;
        },
        createItem: function(i, j) {
            let item = document.createElement('div');
            item.classList.add('item');
            item.dataset.row = i;
            item.dataset.col = j;

            return item.outerHTML;
        },
        switchPlayer: function() {
            this.activePlayer = this.activePlayer === this.players.zero ? this.players.crosse : this.players.zero;
        },
        finish: function() {
            this.finishGame = true;
        },
        checkWin: function() {
            let isWin = false;
            loop: for (let i = 0; i < this.result.length; i++) {
                for(let j =0; j < this.result[i].length; j++) {
                    if(this.winRow(i,j) || this.winCol(i,j)) {
                        isWin = true;
                        break loop;
                    }
                }
            }
            return isWin || this.winDia();
        },
        winRow: function(row,col) {
            return null !== this.result[row][col] && this.result[row][col] === this.result[row][col+1] && this.result[row][col] === this.result[row][col+2];
        },
        winCol: function(row,col) {
            return null !== this.result[row][col] && this.result[row][col] === this.result[row+1][col] && this.result[row][col] === this.result[row+2][col];
        },
        winDia: function() {
            return this.winDia1() || this.winDia2();
        },
        winDia1: function() {
            return this.result[0][0] === this.result[1][1] && this.result[0][0]  === this.result[2][2] && null !== this.result[0][0]
        },
        winDia2: function() {
            return this.result[0][2] === this.result[1][1] && this.result[0][2] === this.result[2][0] && null !== this.result[0][2];
        },
        showWinLine: function(isWin) {
            if (this.finishGame) {
                window.game.switchPlayer();
                document.querySelector('.status').innerHTML = 'Победил: ' + this.activePlayer.symbol;
            } else {
                document.querySelector('.status').innerHTML = this.isStandoff() ? 'Ничья!' : 'Ходит игрок: ' + this.activePlayer.symbol;
            }
        },
        isStandoff: function() {
            let standoff = true;
            for(let i = 0; i < this.result.length; i++) {
                for(let j = 0; j < this.result[i].length; j++) {
                    if (null === this.result[i][j]) {
                        standoff = false;
                    }
                }
            }
            return standoff;
        }
    }
    window.game.init();
    document.querySelectorAll('.item').forEach(function (e) {
        e.addEventListener('click', function () {
            if ('' === e.innerText && !window.game.finishGame) {
                e.innerText = window.game.activePlayer.symbol;
                window.game.result[parseInt(e.dataset.row)][parseInt(e.dataset.col)] = window.game.activePlayer.value;
                window.game.switchPlayer();
                window.game.showWinLine();
                let finishGame = window.game.checkWin();
                if (finishGame) {
                    window.game.finish();
                    window.game.showWinLine();
                }
            }
        });
    });
});

Код игры можно скачать отсюда — https://github.com/wikide/x0.git

,

6 октября, 2024

Создаем систему для партнерских программ в WordPress

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

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

Открываем functions.php темы и добавляем туда что-то вроде:

add_action('init', 'register_post_types');

function register_post_types()
{
    register_post_type('partner', [
        'label' => null,
        'labels' => [
            'name' => 'Партнерки',
            'singular_name' => 'partner',
            'add_new' => 'Добавить партнерку',
            'add_new_item' => 'Добавление партнерки',
            'edit_item' => 'Редактирование пертнерки',
            'new_item' => 'Новая партнерка',
            'view_item' => 'Смотреть партнерку',
            'search_items' => 'Искать патнерку',
            'not_found' => 'Не найдено',
            'not_found_in_trash' => 'Не найдено в корзине',
            'parent_item_colon' => '',
            'menu_name' => 'Партнерка',
        ],
        'description' => '',
        'public' => true,
        'show_in_menu' => null,
        'show_in_rest' => null,
        'rest_base' => null,
        'menu_position' => null,
        'menu_icon' => null,
        'hierarchical' => false,
        'supports' => ['title', 'thumbnail'], // 'title','editor','author','thumbnail','excerpt','trackbacks','custom-fields','comments','revisions','page-attributes','post-formats'
        'taxonomies' => [],
        'has_archive' => false,
        'rewrite' => true,
        'query_var' => true,
    ]);
}

После сохранения в админке WP должен появится новый пункт ниже пунтка меню Записи с названием Партнерки. Теперь у нас есть новый зарегистрированный тип записей с минимальным набором полей ( название и изображение ) для добавления наших партнеров.

Но по-мимо изображения и название так же требуется добавления реферальной ссылки, для этого потребуется для нового типа с партнерами зарегистрировать кастомезированые поля записей, поэтому добавляем следующий код в functions.php

add_action('add_meta_boxes', 'my_extra_fields_meta_box', 1);

function my_extra_fields_meta_box()
{
    $post_type = 'partner';
    add_meta_box('extra_fields', 'Дополнительные поля', 'extra_fields_box_func', $post_type, 'normal', 'high');
}

function extra_fields_box_func($post)
{
    ?>
    <p>
        Ссылка:
        <label>
            <input style="width: 100%;" type="text" name="extra[link]"
                   value="<?= get_post_meta($post->ID, 'link', 1) ?>"/>
        </label>
    </p>
    <p>
        Комментарий:
        <textarea type="text" name="extra[description]"
                  style="width:100%; height:50px;"><?= get_post_meta($post->ID, 'description', 1) ?></textarea>
    </p>
    <p>
        Количество переходов:
        <input type="text" name="extra[count]" value="<?= get_post_meta($post->ID, 'count', 1) ?>" disabled="disabled">
    </p>
    <input type="hidden" name="extra_fields_nonce" value="<?= wp_create_nonce('extra_fields_nonce_id') ?>"/>
    <?php
}

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

Для того чтобы дополнительные поля сохранялись так же требуется добавить следующий хук

add_action('save_post', 'my_extra_fields_save_on_update', 0);

function my_extra_fields_save_on_update($post_id)
{
    // базовая проверка
    if (
        empty($_POST['extra'])
        || !wp_verify_nonce($_POST['extra_fields_nonce'], 'extra_fields_nonce_id')
        || wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)
    ) {
        return false;
    }

    $extra = $_POST['extra'];

    // Все ОК! Теперь, нужно сохранить/удалить данные

    // Очищаем все данные
    $extra = array_map('sanitize_text_field', $extra);
    foreach ($extra as $key => $value) {
        // удаляем поле если значение пустое
        if (!$value) {
            delete_post_meta($post_id, $key);
        } else {
            update_post_meta($post_id, $key, $value); // add_post_meta() работает автоматически
        }
    }

    return $post_id;
}

Админка готова! Теперь необходимо доработать шаблоны темы, чтобы партнерские программ начали выводится на сайт.

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

function get_partner_random() {
    $query = new WP_Query([]);
    $query->query([
        'post_type' => 'partner',
        'post_status' => 'publish',
        'orderby' => 'rand',
        'posts_per_page' => '1'
    ]);

    return $query->posts[0] ?? null;
}

Так как я хочу увеличивать количество переходов на 1 каждый раз при переходе по моей реферальной ссылки требуется добавить функцию проксирования партнерских ссылок. Это можно сделать довольно просто добавив следующий хук в functions.php

add_action( 'init', 'init_proxy' );

function init_proxy() {
    if (
            isset($_GET['action']) &&
            $_GET['action'] == 'partner' &&
            isset($_GET['id']) &&
            is_numeric($_GET['id'])
    ) {
        $query = new WP_Query([]);
        $query->query([
            'post_type' => 'partner',
            'ID' => (int)$_GET['id'],
            'post_status' => 'publish',
            'posts_per_page' => '1'
        ]);
        $posts = $query->get_posts();
        if (!empty($posts[0]->ID)) {
            $count = (int)get_post_meta($posts[0]->ID, 'count', true);
            $count++;
            update_post_meta($posts[0]->ID, 'count', $count);
            header('Location: ' . get_post_meta($posts[0]->ID, 'link', true));
            exit;
        }
    }
}

Теперь уже точно можно перейти к шаблону сайта. Тут все зависит от сложности шаблона. В моем случае шаблон очень простой поэтому править потребуется не так много

Добавляем новый шаблон для партнерок:

<?php
/** @var WP_Post $partner */
$partner = get_partner_random();
?>
<?php if ($partner): ?>
<article>
    <header class="entry-header">
        <header class="entry-header">
            <h2 class="entry-title"><a href="<?php echo sprintf('/?action=partner&id=%d', $partner->ID) ?>" rel="bookmark"><?php echo $partner->post_title?></a></h2>
        </header>
        <div class="post-thumbnail">
                <a href="<?php echo sprintf('/?action=partner&id=%d', $partner->ID) ?>">
                    <?php echo get_the_post_thumbnail( $partner->ID, 'large'); ?>
                </a>
        </div><!-- .post-thumbnail -->
        <div class="nav-links">
            <div class="nav-next kc-nav-links">
                <a href="<?php echo sprintf('/?action=partner&id=%d', $partner->ID) ?>">Взглянуть →</a>
            </div>
        </div>
    </header>
</article>
<?php endif ?>

И далее добавляем логику вывода этого шаблона в index.php темы

get_template_part( 'header' );

				if ( have_posts() ) :

                    $i = 1;
					while ( have_posts() ) :

						the_post();

						get_template_part( 'content' );

						// If comments are open or we have at least one comment, load up the comment template.
						if ( comments_open() || get_comments_number() ) :
							comments_template();
						endif;

                        if ($i % 5 == 0) {
                            get_template_part( 'partner' );
                        }

                    $i++;
					endwhile;

				else :

					get_template_part( 'content', 'none' );

				endif;
				?>

В этом куске кода я скинул шаблон полностью для наглядности, но по-сути вся правка заключается в добавлении вот этой простой логики:

                        if ($i % 5 == 0) {
                            get_template_part( 'partner' );
                        }

Этот код будет отображать рандомную партнерку после каждых 5 постов

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

А если вам нужна разработка под WP или любая другая помощь по php, можете написать мне в любое время в мой телеграмм на странице профайла

, ,

14 августа, 2024

Организация автодиплоя с BitBucket в WordPress

Доработка моего блога пошла быстрее и файлики стало неудобно заливать по штучно через ssh поэтому пришло время настроить автодеплой. В своих разработках я использую чаще всего git на Bitbucket.

Сделать автодеплой для связки Bitbucket+Wordpress не состовляет большого труда. Далее в статье я покажу как это достаточно просто можно организавать.

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

$ git clone git@bitbucket.org:<repository>
$ echo 'www/wp-config.php' >> .gitignore
$ echo '.env' >> .gitignore
$ git add *
$ git push 

Теперь переходим на сервер на котором планируем осуществлять автодеплой. Нам потребуется создать публичный ключ ssh для пользователя от которого будет осуществляться автодеплой ( он же должен быть владельцем файлов сайта на сервере ). Для моего сайта таким пользователем является пользователь www-data, но у него нет shell поэтому генерацию ключей нужно будет осуществить при помощи команды sudo

$ sudo -u www-data ssh-keygen -t rsa

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

$ cat <dir_home_user_www-data>/.ssh/id_rsa.pub

Копируем в буфер обмена то что отобразилось и идем на битбакет с этим


Переходим в раздел Ключи доступа в настройках репозитория нашего сайта

Нажимаем Add key

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

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

Жамкаем на добавление веб-хука

Заполняем название веб-хука
Обязательно указываем адрес к нашему скрипту автодеплоя
Выбираем триггером PUSH событие ( наш скрипт будет вызываться когда в Битбакет будет запушены изменения ) и не забываем проставить статус активности веб-хука


Вот и все, теперь переходим к созданию скрипта деплоя.

<?php

$root_dir = realpath(exec('pwd').'/..');
$result = exec(sprintf('cd %s ; git fetch ; git pull', $root_dir));

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

Теперь мы можем выкачать репозиторий с сайтом на наш удаленный сервер.
Делаем клон рядом с нашей директорией на которую указывает настройки http сервера.
Чаще всего это /var/www

$ cd /var/www
$ sudo -u www-data git clone git@bitbucket.org:wikide/killercoder.git killercoder_git 

И переименовываем директории

$ mv killercoder killercoder_old ; mv killercoder_git killercoder

Теперь мы имеем рабочий сайт, который подключен к репозиторию
И при выполнение команды git push в ветку main будет происходить автоматический деплой на боевом сервере.

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

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

,

4 августа, 2024

Автопубликация постов WordPress в Telegram

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

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

Итак, для репоста в свой телеграм канал, нам потребуется сайт на WordPress, телеграм канал и токен бота, который потребуется получить через папу ботов телеграмма — @BotFather

Открываем @BotFather пишим ему команду

/newbot

В ответ от вас потребуется придумать и ввести имя бота и имя бота с постфексом _bot
После этого папа ботов сгенерирует для вас токен для HTTP API

Этот токен мы и будем использовать для нашей системы репостинга обновлений на сайте

после этого требуется отредактировать wp-config.php и добавить туда константу:

define( 'TELEGRAM_BOT_TOKEN', '<TOKEN>' );

<TOKEN> заменить на тот токен, который мы получили при создании нового бота через @BotFather

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

  1. Добавляем в качестве администратора нашего новорожденного бота на наш канал
  2. Публикуем тестовый пост ( который потом будет не жалко удалить )
  3. Выполняем элементарный запрос curl
    curl —location ‘https://api.telegram.org/bot<TOKEN>/getUpdates’
  4. В ответ получаем ID нашего чата, который вставляем в wp-config.php
define( 'TELEGRAM_CHANNEL_ID',  <ID_CHANNEL> );

Теперь все готово к написанию нашего основного функционала!

Открываем нашу текущую тему WordPress ( предварительно скопировав ее в новую директорию, чтобы обновления темы не затерли наши изменения ) и находим там файл functions.php, в него мы и будем вносить изменения.

В данном случае нас интересуют только новые посты, поэтому мы будем использовать событие WordPress — save_post

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

add_action( 'save_post', 'send_telegram' );

Теперь, напишем код функции send_telegram

function send_telegram( $post_id ) {
    $post = get_post($post_id);
    $is_new = $post->post_date === $post->post_modified;
    if (  !$is_new || wp_is_post_revision( $post_id ) || $post->post_status != 'publish')
        return;
    message_to_telegram( $post );
}

Эта функция выполняет проверяет является ли пост новым публичным и не ревизией поста и если эти условия выполняются, то вызывается функция message_to_telegram

function message_to_telegram($post)
{
    $url = get_permalink($post->ID);
    $text = preg_replace('/[\n\r]+/s', "\n\n", strip_tags($post->post_content));
    if (strlen($text) > 500) {
        $text = substr($text, 0, 500) . '...';
    }
    $ch = curl_init();
    $ch_post = [
        CURLOPT_URL => sprintf('https://api.telegram.org/bot%s/sendMessage', TELEGRAM_BOT_TOKEN),
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 10,
        CURLOPT_POSTFIELDS => [
            'chat_id' => TELEGRAM_CHANNEL_ID,
            'parse_mode' => 'HTML',
            'text' => sprintf("<a href=\"%s\">%s</a> %s \n\n<a href=\"%s\">Взглянуть ?</a>", $url, $post->post_title, $text, $url),
        ]
    ];

    curl_setopt_array($ch, $ch_post);
    curl_exec($ch);
}

Эта функция выполняет отправку ссылку и первые 500 символов нового поста в канал телеграм

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

А если вас интересует создание ботов телеграм или создание сайта на движке wordpress то всегда можете написать мне в телеграм.

Docker + Wordpress

, ,

31 июля, 2024

Поднимаем локально докер для WordPress

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

Когда-то давно еще во допотоные времена до ядерной войны в 18 веке лет 5 назад мы делали это при помощи вирутальной машины, которая работала через vagrant или вообще разворачивали всю экосистему локально, но сейчас времена наступили другие и появилась докеризация

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

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

Для начала создаем файл .env с таким содержимым

# префикс, который мы будем использовать для наименования контейнеров в докере
PREFIX=wp

# пароль root для локального контейнера с mysql
MYSQL_ROOT_PASSWORD=somewordpress

# название базы данных root для локального контейнера с mysql
MYSQL_DATABASE=wordpress

# имя пользователя базы данных для локального контейнера с mysql
MYSQL_USER=wordpress

# пароль пользователя базы данных для локального контейнера с mysql
MYSQL_PASSWORD=wordpress

# хоста базы данных на боевом сервере
MYSQL_REMOTE_HOST=remote_host_address

# название базы данных на боевом сервере
MYSQL_REMOTE_DATABASE=remote_wp

# имя пользователя базы данных на боевом сервере
MYSQL_REMOTE_USER=user_db_read

# пароль пользователя базы данных на боевом сервере
MYSQL_REMOTE_PASSWORD=password_db_read

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

Далее создаем docker-compose.yml

services:
  db:
    container_name: ${PREFIX}-db
    # We use a mariadb image which supports both amd64 & arm64 architecture
    image: mariadb:10.6.4-focal
    # If you really want to use MySQL, uncomment the following line
    #image: mysql:8.0.27
    command: '--default-authentication-plugin=mysql_native_password'
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
    expose:
      - 3306
      - 33060
    ports:
      - 3306:3306
      - 33060:33060
  wordpress:
    container_name: ${PREFIX}-wp
    image: wordpress:latest
    volumes:
      - ./www:/var/www/html
    ports:
      - 8082:80
    restart: always
    environment:
      - WORDPRESS_DB_HOST=db
      - WORDPRESS_DB_USER=${MYSQL_DATABASE}
      - WORDPRESS_DB_PASSWORD=${MYSQL_PASSWORD}
      - WORDPRESS_DB_NAME=${MYSQL_DATABASE}
      - WORDPRESS_DEBUG=false
volumes:
  db_data:

Это основной файл нашей докер системы при использовании которого будет запущено 2 контейнера, контейнер с базой данных mysql и контейнер с образом wordpress

Все настройки перечислять не буду ( почитаете документацию если будет кому нужно ) отмечу только то что в ports: мы биндим порты на локальную машину http будет доступен на порте 8082, а mysql на порту 3306 так же хочу отметить еще что в секции valumes: контейнера wordpress мы биндим локальную директорию ./www в которой будут хранится файлы wordpress. В нее нужно будет развенуть архив с wordpress или скопировать файлы wordpress с удаленного хостинга.

В итоге у нас получается вот такая директория проекта с файлом .env, docker-compose.yml и директорией www с файлами wordpress, если не хотите прописывать данные доступов к базе данных вручную, то перед запуском сборки докера удалите файл wp-config.php. Контейнер wordpress создаст его вручную и пропишет в него доступы из docker-compose.yml

Далее запускаем вот такую простую команду

$ docker compose up -d

Наслаждаемся процессом скачки образов и сборки контейнеров

Если вам повезло, то после этого можете зайти по адресу http://localhost:8082 откроется ваш wordpress

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

Итак, чтобы автоматзировать рутинные задачи создадим Makefile.

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

include .env
export
.DEFAULT_GOAL = help
.PHONY: help

help:
	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

up:
	@docker compose up -d

build:
	@docker compose up --build -d

down:
	@docker stop `docker ps -a -q`

shell:
	@docker exec -it $(PREFIX)-wp bash

drop-db:
	@docker exec -it $(PREFIX)-db mysql -e 'DROP DATABASE $(MYSQL_DATABASE) ; CREATE DATABASE $(MYSQL_DATABASE)' -uroot -p$(MYSQL_ROOT_PASSWORD)

sync: drop-db
	@ssh $(MYSQL_REMOTE_HOST) mysqldump -u$(MYSQL_REMOTE_USER) -p$(MYSQL_REMOTE_PASSWORD) $(MYSQL_REMOTE_DATABASE) | docker exec -i $(PREFIX)-db mysql -u$(MYSQL_USER) -p$(MYSQL_PASSWORD) $(MYSQL_DATABASE)

После этого чтобы запустить наш докер с wordpress достаточно будет ввести команду

$ make up

Для того чтобы пересобрать контейнеры

$ make down

Остановить докер

$ make down

И самая интересная команд, команда синхронизации базы данных докера с базой данных боевого сервера

$ make sync

Она удаляет полностью базу данных в докере и полностью забирает ее с боевого хостинга, после этой операции у вас в контейнере базы данных будет полная копия базы боевого сайта с wordpress

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

, ,

30 июля, 2024

Обычный SSH тоннель

Понимаю, что банальность, но пусть будет.

Часто требуется подключится к базе данных mysql боевого сервера, но порт 3306 доступен только в localhost, для решения этой тривиальной задачи нам поможет ssh тоннель.

ssh -f -N -L 3307:localhost:3306 remote_host

Теперь в вашем localhost будет доступен порт 3307 через который вы сможете подключится к базе данных mysql на боевом хосте

-f запуск в фоне 
-N не выполнять команду (без нее и -f запустить шел на удаленном хосте)
-L перенаправление портов

апдейд:

Далее для удобства можем создать алиас для этого дела, чтобы быстрее можно было создать тоннель. Вот так это будет выглядеть для zsh под MacOS

$ vim ~/.zshrc

вставляем эту строку в конце файла

<br>alias create_tonnel="ssh -f -N -L 3307:localhost:3306 remote_host"

и выходим из vim

:wq

,

29 июля, 2024

Запиливаем удобный блок донатов в WordPress

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

Сначала добавил обычный текстовый блок, но вряд ли кто-то станет выделять и копировать текст для того чтобы отправить куда-то деньги, тогда я захотел немного упросить процесс и решил подключить javascript для решения этой задачи. От поиска готового решения для WP отказался так как для такой ерунды это не целесообразно, а всевозможные расширения и специальные плагины еще и слишком ресурсоемкие, к тому же я вспомнил что Я Ж программист и решил самостоятельно на коленки сделать свое решение. Как по мне так получилось достаточно неплохо, результат можете посмотреть тут ( а заодно и воспользоваться функционалом =) )

Итак, вот код:

Добавляем в стили шаблона css

.term {
	cursor: pointer;
	color: #2f8eff;
	text-decoration: none;
	border-bottom: 1px dashed #2f8eff;
}
.term:after {
	padding-left: 3px;
	content: url('/uploads/donate/copy.svg');
	display: inline-block;
	width: 20px;
	height: 20px;
}
.tooltiped {
	position: relative;
}
.tooltiped .tooltip {
	position: absolute;
	right: 0;
	top: 0;
	visibility: hidden;
	opacity: 0;
	transition: ease 1s;
	background-color: #FFF;
	z-index: 999;
}
.tooltiped:hover .tooltip {
	position: absolute;
	top: 20px;
	visibility: visible;
	opacity: 1;
}
.tooltiped .tooltip .tooltip-content {
	max-width: 150px;
}
.tooltiped .tooltip .tooltip-content img {
	width: 200px;
}
.tooltiped .tooltip .tooltip-content,
.tooltiped .tooltip .tooltip-content a {
	color: #fff;
}
.promp {
	border-radius: 3px;
	background: rgba(47, 142, 255, 0.5);
	position: absolute;
	top: -40px;
	right: -100px;
	padding: 3px;
}

Добавляем в шаблон небольшой javascript:

    window.onload = () => {
        document.querySelectorAll(".term").forEach(function(e) {
            e.addEventListener("click", function() {
                navigator.clipboard.writeText(e.innerText).then(function() {
                    e.insertAdjacentHTML('beforebegin', '<div class="promp">скопировано</div>');
                    setTimeout(function(){
                        document.querySelectorAll(".tooltiped .promp").forEach(function(p) {
                            p.remove();
                        });
                    },1000);
                }).catch(function (error) {
                    console.error('Error:', error);
                });
            });
            e.addEventListener("mouseover", () => {
                e.insertAdjacentHTML('afterEnd', '<div class="tooltip"><div class="tooltip-content"><img src="' + e.dataset.url + '" /></div></div>');
            });
        });
    }

Ну и собственно блок с реквизитами:

<p>
    <span class="tooltiped">
        <strong>Карта ( Т-банк ):</strong> <span class="term" data-url="">5536913774062992</span><br>
    </span>
    <span class="tooltiped">
        <strong>USDT (Сеть Solana):</strong> <span class="term" data-url="/uploads/donate/USDT.jpg">HEzoskh3Gmehztu578DWFzq3PBmsoCZSVkzM25AYtCmQ</span> <br>
    </span>
    <span class="tooltiped">
        <strong>BTC:</strong> <span class="term" data-url="/uploads/donate/BTC.jpg">bc1qmnze7qda4eutpzyzjesyr05p0cf4myfrppqz2f</span><br>
    </span>
    <span class="tooltiped">
        <strong>TON:</strong> <span class="term" data-url="/uploads/donate/TON.jpg">UQC7ZauWx4qlSknEd-Ag9NEF5jXq3QT7sd8nJtWRPgWdWBj0</span><br>
    </span>
    <span class="tooltiped">
        <strong>Litecoin:</strong> <span class="term" data-url="/uploads/donate/LTC.jpg">ltc1qlphwcvh0lzmewuupjas3k2uh6d5sjdpcnxyvp0</span><br>
    </span>
    <span class="tooltiped">
        <strong>Ethereum:</strong> <span class="term" data-url="/uploads/donate/ETH.jpg">0x834C17E4bd362AAd6Ba85A665197DE3111f9b7D2</span><br>
    </span>
    <span class="tooltiped">
        <strong>DASH:</strong> <span class="term" data-url="/uploads/donate/DASH.jpg">XgkG5z3zoUATHCKWAP9W76qMTR8938J5ev</span><br>
    </span>
    <span class="tooltiped">
        <strong>XRP:</strong> <span class="term" data-url="/uploads/donate/XRP.jpg">rLnU6E5DSpWNeo2xEDfARpo2jDR1ymWRkh</span><br>
    </span>
    <span class="tooltiped">
        <strong>XLM:</strong> <span class="term" data-url="/uploads/donate/XLM.jpg">GDV3OMVJYL6LJI2HKXNBKQYYVTBQ3LY2LOX2DZVNCYPXV26JI4BZJNLX</span><br>
    </span>
    <span class="tooltiped">
        <strong>HBAR:</strong> <span class="term" data-url="/uploads/donate/HBAR.jpg">0.0.5028861</span><br>
    </span>
    <span class="tooltiped">
        <strong>Solana:</strong> <span class="term" data-url="/uploads/donate/SOL.jpg">HEzoskh3Gmehztu578DWFzq3PBmsoCZSVkzM25AYtCmQ</span><br>
    </span>
    <span class="tooltiped">
        <strong>Cardano:</strong> <span class="term" data-url="/uploads/donate/ADA.jpg">addr1v9pkq5weeqz33kc8aljul5wj4yslr8zxe6flwfan2psvquszy73dg</span>
    </span>
</p>

Готово! =)

Что такое блокчейн

,

28 июля, 2024

Что такое блокчейн

Блокчейн — это особый вид базы данных. Но в отличие от обычных баз данных, информация в блокчейне хранится не в одном месте, а в виде «цепочки блоков» на множестве компьютеров одновременно. Это делает блокчейн децентрализованным и более защищённым от изменений или взломов.

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

Область применения блокчейна:

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

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

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

Так же технология блокчейна лежит в основе новой парадигмы интернета под Web3

,

Что такое web3

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

Другими словами, web3 — это новая эра интернета, которая использует блокчейн и децентрализованные технологии для создания более прозрачного, безопасного и пользователь-ориентированного интернета. Если Web1 был статичным и информативным, а Web2 — интерактивным и социальным, то Web3 делает упор на децентрализацию и контроль пользователей над своими данными.

Уже сейчас существуют приложения и сервисы, которые успешно работают в парадигме web3, вот некоторые из них:

IPFS (InterPlanetary File System): Протокол для децентрализованного хранения и передачи данных. IPFS позволяет хранить файлы распределённо по многим компьютерам, делая их доступными и надёжными.

Ethereum Name Service (ENS): Децентрализованная система для регистрации доменных имен в блокчейне Ethereum. ENS позволяет привязывать длинные и сложные адреса кошельков к простым и запоминающимся именам.

Minds: Децентрализованная социальная сеть, которая поощряет свободу слова и приватность. Пользователи могут зарабатывать токены за создание и распространение контента.

MakerDAO: Децентрализованная автономная организация, которая управляет стейблкоином DAI. Пользователи могут заложить свои криптовалюты в смарт-контракт, чтобы создать DAI, который привязан к доллару США.

А так же множество других разнобраных сервисов и децентрализованных приложений.

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

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

31 мая, 2015

Мониторим домены

Небольшой скрипт на php для мониторинга освободившихся доменов в помощь лентяям.

<?php

$domains = array(
    'domain1.ru',
    'domain2.ru'
);

$email = 'my@email.com';

foreach($domains as $domain)
{
    $inf = check_domain($domain);
    if(!isset($inf['free-date']))
    {
        $text = 'DOMAIN ' . $domain . ' FREE';
        mail($email,$text, $text);
    }
}

function check_domain( $domain )
{
    $curl = curl_init();
    curl_setopt( $curl, CURLOPT_URL,'r01.ru/domain/whois/check-domain.php?domain=' . $domain);
    curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
    curl_setopt($curl,CURLOPT_FOLLOWLOCATION,true);
    $result = curl_exec($curl);
    $info = array();
    $infoField = array(
        'free-date',
        // 'domain','type','descr','state','nic-hdl','person','phone','fax-no','e-mail','reg-till','created','changed', 'registrar'
    );
    foreach($infoField as $field)
    {
        preg_match('#' . $field . ': (.*)#',$result,$m);
        $info[$field] = isset($m[1]) ? strip_tags($m[1]) : '';
    }
    return $info;
}

Запускать скрипт по крону, раз в 5-10 минут.

PS Письма по-умолчанию будут падать в спам.

,

9 апреля, 2014

URL без завершающих слэшей и www

Часто бывает нужно убрать www и завершающие слэши из всех URL. Данную операцию достаточно просто выполнить при помощи кода в .htaccess

#Если вы хотите, чтобы всегда был домен с www
RewriteCond %{HTTP_HOST} ^domen\.ru
RewriteRule ^(.*)$ http://www.domen.ru/$1 [R=301,L]
#Если вы хотите, чтобы всегда был домен без www
RewriteCond %{HTTP_HOST} ^www\.domen\.ru
RewriteRule ^(.*)$ http://domen.ru/$1 [R=301,L]
#Добавить завершающий слэш
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*[^/])$ $1/ [L,R=301]
#Удалить завершающий слэш
RewriteBase /
RewriteCond %{HTTP_HOST} (.*)
RewriteCond %{REQUEST_URI} /$ [NC]
RewriteRule ^(.*)(/)$ $1 [L,R=301]

12 мая, 2013

Расширение всех файлов в XML формате

Не нашел нигде список всех расширений файлов, но зато наткнулся на сайт http://open-file.ru в котором приведен весь список расширений. Решил написать небольшой скрипт, который вытянет все расширения с описаниями и типами в XML файл.

<?php

set_time_limit(0);
$url = 'http://open-file.ru';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$result = curl_exec($ch);
preg_match('~<p>(.*)</p>~',$result,$match);
preg_match_all('~<a href="(/types/.*/)">.*</a>~Us',$match[1],$match);
$extension = array();
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<extensions>';
foreach( $match[1] as $link )
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, ( $url . $link ));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    $result = curl_exec($ch);
    preg_match( '~<table>(.*)</table>~Us', $result, $table );

    $reg = array(
        '~<tr><td>.*<a href="/types/.*">(.*)</a>.*</td>',
        '<td>.*<a href="/types/.*/">(.*)</a>.*</td><td>',
        '.*<a href="/types/.*">(.*)</a>.*</td></tr>~'
    );

    preg_match_all(implode($reg),$table[1],$data);
    foreach( $data[1] as $key => $ext )
    {
        $xml .= '
            <extension>
                <name><![CDATA[' . $ext . ']]></name>
                <type><![CDATA[' . $data[2][$key] . ']]></type>
                <description><![CDATA[' . $data[3][$key] . ']]></description>
           </extension>
';
   }
}

$xml .= '</extensions>';

file_put_contents('tmp/extensions.xml' , iconv( 'cp1251', 'utf8', $xml ) );

,

17 февраля, 2013

Скрипт для отправки обновлений на почту

Для одного проекта понадобилось высылать заказчику обновления ( pack ), так как это рутинная задача, я решил написать простой скрипт на shell:

 

#!/bin/sh 

# Мыльник куда отправляем пакет с обновлениями 
EMAIL=$1 

# Директория с проектом 
PROJECT=/var/www/my_project 

# Дата ( для заголовка письма и названия файла архива с обновлением ) 
DATE=`date +%d-%m-%Y_%H-%M` 

# Название файла архива с обновлением 
TARNAME=pack_my_project_$DATE.tgz 

# Локальная директория в которой сохраняются архивы с обновлениями 
PACK=pack/$TARNAME 

# Изменения в проекте ( git ) 
CHANGE=`cd $PROJECT && git diff --stat | awk 'NF != 7 {print $1}' && cd - > /dev/null` 

# Тема письма с архивом обновления 
SUBJECT='Обновление project от $DATE' 

# Тело письма, опционально 
BODY='' 

# Создаем архив с изменениями и отправляем письмо
cd $PROJECT && \
tar czf $PACK $CHANGE > /dev/null && \
( ( echo $BODY $CHANGE ); uuencode $PACK $TARNAME ) \ 
| mail -s "Обновление project от $DATE" $EMAIL && \
cd - > /dev/null 

в .zshrc прописываем путь к директории к скрипту и ставим разрешение на выполнение файла

Отправляем:

 $ my_project_update.sh test@gmail.com 

Сообщение с паком уйдет на почту.

TODO: Мою задачу скрипт решает полностью, но его можно доработать:
1) проверка наличия параметра $1
2) проверка, что в проекте реально есть изменения

, ,

Быстрое добавление множества директорий в .gitignore

Часто в проекте есть директория uploads/ с вложениями, содержимое в которых не нуждаются в поддержки версионности, для того чтобы не утомлять себя ручным вводом каждой директории можно воспользоваться командой:

 $ ls -l uploads | awk {'print "/uploads/"$9"/*"'} > ../.gitignore 

Дело сделано, нужные директории теперь не будут включены в репозитарий.