<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>Блоги: заметки с тегом проекти</title>
<link>https://blogengine.ru/blogs/tags/proekti/</link>
<description>Автоматически собираемая лента заметок, написанных в блогах на Эгее</description>
<author></author>
<language>ru</language>
<generator>Aegea 11.0 (v4079e)</generator>

<itunes:subtitle>Автоматически собираемая лента заметок, написанных в блогах на Эгее</itunes:subtitle>
<itunes:image href="" />
<itunes:explicit>no</itunes:explicit>

<item>
<title>Как я делал бота для Facebook workplace</title>
<guid isPermaLink="false">119851</guid>
<link>https://stefaniuk.website/all/create-workplace-messenger-bot/</link>
<pubDate>Tue, 26 Nov 2019 19:22:26 +0500</pubDate>
<author>Bohdan Stefaniuk</author>
<comments>https://stefaniuk.website/all/create-workplace-messenger-bot/</comments>
<description>
&lt;p&gt;&lt;a href="https://stefaniuk.website/"&gt;Bohdan Stefaniuk&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Дали мне задачу: написать бота для мессенджера workplace, с помощью которого можно получать уведомления из нашей CRM и управлять разными вещами. Расскажу о разных интересных вещах с которыми я столкнулся. Бота писал с помощью ASP.NET Core Web API.&lt;/p&gt;
&lt;h2&gt;Вебхуки&lt;/h2&gt;
&lt;p&gt;Для того чтобы бот мог обрабатывать запросы и сообщения от Facebook нам надо настроить вебхуки. Webhook — механизм оповещения системы о событиях. Для того чтобы Facebook принял наш хук, он должен обрабатывать как GET так и POST запросы.&lt;/p&gt;
&lt;p class="note"&gt;&lt;a href="https://developers.facebook.com/docs/messenger-platform/getting-started/webhook-setup"&gt;Подробнее о Webhook в официальной документации&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GET запрос служит для валидации работы нашего эндпоинта. POST принимает данные связанные с активностью пользователя, будь то нажатие на кнопки или другая активность.&lt;/p&gt;
&lt;p class="cut-button"&gt;Показать код метода-обработчика GET запроса&lt;/p&gt;
&lt;div class="cut-content"&gt;&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;public IActionResult Receive( [FromQuery(Name = &amp;quot;hub.mode&amp;quot;)] string mode, 
    [FromQuery(Name = &amp;quot;hub.challenge&amp;quot;)] string challenge, 
    [FromQuery(Name = &amp;quot;hub.verify_token&amp;quot;)] string verifyToken)
{ 
   if (string.IsNullOrEmpty(verifyToken)) { 
       return Unauthorized(); 
    }  
    if (verifyToken.Equals(FacebookEnvironment.FacebookVToken)) { 
        return Ok(challenge); 
    } 
    return Unauthorized(); 
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;В качестве verify_token используется токен, который мы указали при регистрации нашего хука.&lt;/p&gt;
&lt;/div&gt;&lt;p class="cut-button"&gt;Показать код метода-обработчика POST запроса&lt;/p&gt;
&lt;div class="cut-content"&gt;&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;public async Task&amp;lt;IActionResult&amp;gt; Receive([FromBody]FbResponse response = null)
{
    if (response is null) {
        return BadRequest();
    }

    if (response.Object != &amp;quot;page&amp;quot;) {
        return Ok();
    }

    foreach (var entry in response.Entries) {
        foreach (var message in entry.Messaging) {
            await PrepareMessageAsync(message);
        }
    }
    return Ok(&amp;quot;EVENT_RECEIVED&amp;quot;);
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;Авторизация запросов Facebook&lt;/h2&gt;
&lt;p&gt;Для авторизации Facebook использует специальный http заголовок (X-Hub-Signature), в нем он передает некую сигнатуру с помощью которой мы можем авторизовать запрос. Для того чтобы добавить такую функциональность в наш контроллер, добавим фильтр.&lt;/p&gt;
&lt;p class="cut-button"&gt;Пример кода, для проверки подписи&lt;/p&gt;
&lt;div class="cut-content"&gt;&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;private const string Sha1Prefix = &amp;quot;sha1=&amp;quot;;

public static bool Validate(string signature, string contentString) {
    if (!signature.StartsWith(Sha1Prefix, StringComparison.OrdinalIgnoreCase)) {
        return false;
    }
    var secret = Encoding.ASCII.GetBytes(FacebookEnvironment.AppSecret);
    var signatureWithoutPrefix = signature.Substring(Sha1Prefix.Length);
    var content = Encoding.ASCII.GetBytes(contentString);
    return GetIsHashValid(secret, signatureWithoutPrefix, content);
}

private static bool GetIsHashValid(byte[] secret, string signature, byte[] content) {
    using var hmac = new HMACSHA1(secret);
    var hash = hmac.ComputeHash(content);
    var hashString = ToHexString(hash);
    return hashString.Equals(signature);
}

private static string ToHexString(IReadOnlyCollection&amp;lt;byte&amp;gt; bytes)
{
    var builder = new StringBuilder(bytes.Count * 2);
    foreach (var b in bytes)
    {
        builder.AppendFormat(&amp;quot;{0:x2}&amp;quot;, b);
    }

    return builder.ToString();
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;Тестирование бота&lt;/h2&gt;
&lt;p class="note-md"&gt;&lt;a href="http://winitpro.ru/index.php/2017/11/03/ustanovka-besplatnogo-ssl-sertifikata-lets-encrypt-na-iis-v-windows-server-2012-r2/"&gt;Как установить letsencrypt сертификат для IIS&lt;/a&gt;. Если же вы используете связку в виде ubuntu и nginx вам подойдет &lt;a href="https://www.digitalocean.com/community/tutorials/nginx-let-s-encrypt-ubuntu-18-04-ru"&gt;эта инструкция&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Для тестирования нужно развернуть бот на сервере, который смотрит в мир. Также необходимо чтобы у сервера было доменное имя и валидный SSL сертификат. В моем случае, в качестве сервера выступала машина на винде, так как другой внутри нашей сети не было. Как мне показалось захостить приложение написанное на .NET Core намного проще под Ubuntu + nginx нежели под Windows + IIS. В качестве поставщика сертификатов выбрал letsencrypt, так как они предоставляют бесплатный сертификат на 3 месяца, с возможностью дальнейшего обновления.&lt;/p&gt;
</description>
</item>

<item>
<title>Эгея Power-Ups</title>
<guid isPermaLink="false">119849</guid>
<link>https://stefaniuk.website/all/e2-power-ups/</link>
<pubDate>Mon, 25 Nov 2019 19:30:51 +0500</pubDate>
<author>Bohdan Stefaniuk</author>
<comments>https://stefaniuk.website/all/e2-power-ups/</comments>
<description>
&lt;p&gt;&lt;a href="https://stefaniuk.website/"&gt;Bohdan Stefaniuk&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Решил опубликовать несколько своих доработок, которые добавляют в движок новые функции. Вы можете их свободно использовать в любых ваших целях.&lt;/p&gt;
&lt;h2&gt;Список улучшений&lt;/h2&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Кнопка «подробнее» или кат внутри заметок&lt;/li&gt;
&lt;li&gt;Заметки на полях&lt;/li&gt;
&lt;li&gt;Хайлайты&lt;/li&gt;
&lt;li&gt;Мини галерея&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Кнопка «подробнее» или кат&lt;/h2&gt;
&lt;p&gt;Когда пишешь статью и у тебя много исходников, удобно их скрыть под кат, чтобы они не увеличивали размер статьи не отвлекали от текста. Для этого добавил поддержку катов внутри заметок. Для этого нужно сделать 2 вещи:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Пометить текст, который будет выступать в качестве кнопки: .cut-button Название кнопки.&lt;/li&gt;
&lt;li&gt;Следующим элементов разместить блок div с классом cut-content и в него поместить нужный контент для скрытия.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Как это выглядит в коде:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;.cut-button Два лучших вопроса для собеседования
&amp;lt;div class=&amp;quot;cut-content&amp;quot;&amp;gt;
Как бы вы описали идеального кандидата на эту должность?
Как вы будете судить, хорош ли я в том, что потребуется от меня через 1-3 месяца?
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Как это работает&lt;/p&gt;
&lt;p class="cut-button"&gt;Два лучших вопроса для собеседования&lt;/p&gt;
&lt;div class="cut-content"&gt;&lt;p&gt;Как бы вы описали идеального кандидата на эту должность?&lt;br /&gt;
Как вы будете судить, хорош ли я в том, что потребуется от меня через 1-3 месяца?&lt;/p&gt;
&lt;/div&gt;&lt;h2&gt;Стилизация в виде карточке&lt;/h2&gt;
&lt;p&gt;Если необходимо выделить какой-то блок текста в заметке можно использовать хайлайты. Для этого достаточно обернуть текст, который хотите выделить в div с классом highlight.&lt;/p&gt;
&lt;p&gt;Как выглядит в коде:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;&amp;lt;div class=&amp;quot;highlight&amp;quot;&amp;gt;
Как бы вы описали идеального кандидата на эту должность?
Как вы будете судить, хорош ли я в том, что потребуется от меня через 1-3 месяца?
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Как работает&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;p&gt;Как бы вы описали идеального кандидата на эту должность?&lt;br /&gt;
Как вы будете судить, хорош ли я в том, что потребуется от меня через 1-3 месяца?&lt;/p&gt;
&lt;/div&gt;&lt;h2&gt;Заметки на полях&lt;/h2&gt;
&lt;p class="note"&gt;Блог с реализацией заметок: &lt;a href="http://mopsicus.ru/all/aegea-field-notes/"&gt;&lt;a href="http://mopsicus.ru"&gt;http://mopsicus.ru&lt;/a&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Эту функциональность я подсмотрел в другом блоге и решил перенести в свой. Пригодится, когда нужно указать ссылку на ресурс по теме или просто примечание. Также добавил возможность указывать тип заметки. По умолчанию заметка не занимает отдельный абзац в тексте.&lt;/p&gt;
&lt;p&gt;Как выглядит в коде:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;.note Блог с реализацией заметок:  ((http://mopsicus.ru/all/aegea-field-notes/ http://mopsicus.ru)).
.note-md Блог с реализацией заметок: ((http://mopsicus.ru/all/aegea-field-notes/ http://mopsicus.ru)).&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Как выглядит на мобиле:&lt;/p&gt;
&lt;div class="category-block"&gt;&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/large-notes-on-mobile.jpg" width="300" height="165" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Во всю ширину экрана.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="category-block"&gt;&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/original-notes-on-mobile.jpg" width="300" height="165" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Обтекаемый текст.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;b&gt;Мини галерея&lt;/b&gt;&lt;br /&gt;
Можно вывести несколько изображений в ряд. Пока что это реализовано тольк для 3 и 4 картинок. В будущем планирую добавить возможность открывать изображение на весь экран.&lt;/p&gt;
&lt;p&gt;Как выглядит в коде:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;&amp;lt;div class=&amp;quot;card-gallery card-gallery-4&amp;quot;&amp;gt;
    &amp;lt;!-- Список ссылок на изображения --&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;div class=&amp;quot;card-gallery card-gallery-3&amp;quot;&amp;gt;
    &amp;lt;!-- Список ссылок на изображения --&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Как выглядит на страницу&lt;/p&gt;
&lt;div class="card-gallery card-gallery-4"&gt;&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/card-gallery-preview.jpg" width="450" height="327" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/card-gallery-preview.jpg" width="450" height="327" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/card-gallery-preview.jpg" width="450" height="327" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/card-gallery-preview.jpg" width="450" height="327" alt="" /&gt;
&lt;/div&gt;
&lt;div&gt;&lt;div class="card-gallery card-gallery-3"&gt;&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/card-gallery-preview.jpg" width="450" height="327" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/card-gallery-preview.jpg" width="450" height="327" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/card-gallery-preview.jpg" width="450" height="327" alt="" /&gt;
&lt;/div&gt;
&lt;div&gt;&lt;h2&gt;Где скачать?&lt;/h2&gt;
&lt;p&gt;Все исходники выложил на &lt;a href="https://github.com/teamkiller7112/e2-power-ups"&gt;github&lt;/a&gt;. Там же вы найдете инструкцию по установке.&lt;/p&gt;
&lt;h2&gt;PS&lt;/h2&gt;
&lt;p&gt;Если у вас есть предложения, оставляйте их в комментариях, а лучше в issue на github-е. Как будет время, займусь реализацией предложений.&lt;/p&gt;
&lt;style&gt;
	.category-block { width: 28%;  display: inline-block; vertical-align: top; margin-right: 1%; margin-bottom: 20px;}
@media (max-width: 700px) {
	.category-block { width: 100%; margin-right: unset;}
}
&lt;/style&gt;
</description>
</item>

<item>
<title>Первый проект</title>
<guid isPermaLink="false">119835</guid>
<link>https://stefaniuk.website/all/first-project/</link>
<pubDate>Thu, 27 Jun 2019 12:53:18 +0500</pubDate>
<author>Bohdan Stefaniuk</author>
<comments>https://stefaniuk.website/all/first-project/</comments>
<description>
&lt;p&gt;&lt;a href="https://stefaniuk.website/"&gt;Bohdan Stefaniuk&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Нашел в старой переписке скриншоты игры, которую я делал когда только изучал программирование на C#. Игру делал на Unity в сеттинге сталкера. Дальше одной локации и простенького управления не зашло. Жаль что видео не сохранились.&lt;/p&gt;
&lt;p&gt;Это был 2014 год.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/Q-uvwDZyHSk.jpg" width="1000" height="562" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/_PBCIo2m35Y.jpg" width="853" height="417" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/cmHa72tOn80.jpg" width="869" height="507" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/DOvFs8xlGKQ.jpg" width="1000" height="504" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/pBN-yhOJ8Pg.jpg" width="1000" height="506" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/vI-KS-BCHDs.jpg" width="1000" height="492" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/zkkjTZuP9Q0.jpg" width="1000" height="481" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Также пробовал моделировать в 3ds Max.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/rD6sM_gp1bM.jpg" width="1000" height="1000" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://stefaniuk.website/pictures/TYDws_mfX00.jpg" width="1000" height="1000" alt="" /&gt;
&lt;/div&gt;
</description>
</item>


</channel>
</rss>