<?xml version="1.0" encoding="utf-8" standalone="no"?><feed xmlns="http://www.w3.org/2005/Atom"><title>The Rpsl Blog</title><link href="https://blog.rpsl.info/" rel="alternate"/><link href="https://blog.rpsl.info/feeds/all.atom.xml" rel="self"/><id>https://blog.rpsl.info/</id><updated>2020-09-12T20:35:50+03:00</updated><xhtml:meta content="noindex" name="robots" xmlns:xhtml="http://www.w3.org/1999/xhtml"/><entry><title>Перенос комментариев на GitHub</title><link href="https://blog.rpsl.info/2020/09/how-migrate-comments-from-disqus-to-github/" rel="alternate"/><published>2020-09-12T20:35:50+03:00</published><updated>2020-09-12T20:35:50+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2020-09-12:/2020/09/how-migrate-comments-from-disqus-to-github/</id><summary type="html">&lt;p&gt;... и отказ от Disqus.&lt;/p&gt;
&lt;p&gt;Много лет для комментариев в блоге я использовал &lt;a href="http://disqus.com/"&gt;Disqus&lt;/a&gt;. В те времена, когда я начал его использовать, выбор был не большой: Disqus, &lt;a href="https://www.intensedebate.com/"&gt;IntenseDebate&lt;/a&gt;, встроенные системы комментирования и еще пара аналогов, названия которых я уже не вспомню.&lt;/p&gt;
&lt;p&gt;Это была середина двухтысячных годов, сервисы которые загружались через javascript, позволяли писать комментарии, автоматически боролись со спамом, имели сквозную авторизацию, а еще и строили внутри себя подобие социальной сети - &lt;strong&gt;казались фантастикой&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Я уже точно не помню почему я начал использовать Disqus, вероятно из-за того что это казалось удобным, а еще он был жутко модным и устанавливался почти везде.&lt;/p&gt;
&lt;p&gt;Альтернативой ему была стандартная форма от WP, которая пропускала спам и предлагала регистрироваться в каждом блоге чтобы писать комментарии.&lt;/p&gt;
&lt;div class="callout"&gt;
    &lt;div&gt;&#129299;&lt;/div&gt;
    &lt;div class="text"&gt;Приколитесь, мы регистрировались в блогах, чтобы писать друг-другу комментарии&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;С тех пор Disqus так и жил, заменять его на стандартные комментарии от WP мне не хотелось, а после того как блог переехал на генерацию статических файлов, то внешние системы комментариев остались единственным вариантом, кроме того чтобы убрать комментарии полностью.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;... и отказ от Disqus.&lt;/p&gt;
&lt;p&gt;Много лет для комментариев в блоге я использовал &lt;a href="http://disqus.com/"&gt;Disqus&lt;/a&gt;. В те времена, когда я начал его использовать, выбор был не большой: Disqus, &lt;a href="https://www.intensedebate.com/"&gt;IntenseDebate&lt;/a&gt;, встроенные системы комментирования и еще пара аналогов, названия которых я уже не вспомню.&lt;/p&gt;
&lt;p&gt;Это была середина двухтысячных годов, сервисы которые загружались через javascript, позволяли писать комментарии, автоматически боролись со спамом, имели сквозную авторизацию, а еще и строили внутри себя подобие социальной сети - &lt;strong&gt;казались фантастикой&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Я уже точно не помню почему я начал использовать Disqus, вероятно из-за того что это казалось удобным, а еще он был жутко модным и устанавливался почти везде.&lt;/p&gt;
&lt;p&gt;Альтернативой ему была стандартная форма от WP, которая пропускала спам и предлагала регистрироваться в каждом блоге чтобы писать комментарии.&lt;/p&gt;
&lt;div class="callout"&gt;
    &lt;div&gt;&#129299;&lt;/div&gt;
    &lt;div class="text"&gt;Приколитесь, мы регистрировались в блогах, чтобы писать друг-другу комментарии&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;С тех пор Disqus так и жил, заменять его на стандартные комментарии от WP мне не хотелось, а после того как блог переехал на генерацию статических файлов, то внешние системы комментариев остались единственным вариантом, кроме того чтобы убрать комментарии полностью.&lt;/p&gt;


&lt;h2&gt;Альтернативы&lt;/h2&gt;
&lt;p&gt;Желание избавить от Disqus было всегда, но не было альтернатив на которые его можно заменить. Я периодически искал на что его можно заменить: большой список доступен на &lt;a href="https://alternativeto.net/software/disqus/"&gt;Alternativeto.net&lt;/a&gt;, иногда что-нибудь появляется на &lt;a href="https://www.producthunt.com/search?q=comments"&gt;Producthunt.com&lt;/a&gt;, раз в полгода проверял &lt;a href="https://www.google.com/search?q=comment+system+for+static+site"&gt;Google&lt;/a&gt;, там тоже иногда выдача меняется.&lt;/p&gt;
&lt;p&gt;Те системы которые выглядели красиво и функционально просили много денег за свое использование, а я не готов платить за это по 50 и более долларов в год. Бесплатные не внушали доверия, либо не отличались качеством.&lt;/p&gt;
&lt;p&gt;Есть ряд систем которые можно отнести к self-hosted решениям, но для меня они оказались не подходящими, т.к. требовали много времени на поддержку и адаптацию, либо были теми еще костылями, по сравнению с которыми даже Disqus кажется быстрым и удобным.&lt;/p&gt;
&lt;p&gt;Когда-то я смотрел на &lt;a href="https://remark42.com/"&gt;remark42&lt;/a&gt;, он по функциональности на голову выше аналогов, но в момент нашего знакомства у него не работал импорт из Disqus и не было половины документации. Я потратил несколько вечеров чтобы найти ошибки и попытаться их устранить, в итоге это ничем не закончилось и я забил на него.&lt;/p&gt;
&lt;p&gt;Во время последнего поиска альтернатив, я, в очередной раз, наткнулся на &lt;a href="https://utteranc.es/"&gt;utterances&lt;/a&gt;. Я точно видел его несколько лет назад, но тогда не стал рассматривать как возможный вариант. Хотя, возможно, я его путаю с &lt;a href="https://gitalk.github.io/"&gt;Gitalk&lt;/a&gt;?&lt;/p&gt;
&lt;h2&gt;Utterances&lt;/h2&gt;
&lt;div class="callout"&gt;
  &lt;div&gt;&#128161;&lt;/div&gt;
  &lt;div class="text"&gt;
    A lightweight comments widget built on GitHub issues. Use GitHub issues for blog comments, wiki pages and more!
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Это скрипт который делает обвязку вокруг системы комментариев которая используется на GitHub для Issues. Благодаря этому можно использовать весь функционал комментариев на сторонних сайтах.&lt;/p&gt;
&lt;p&gt;&lt;img alt="https://blog.rpsl.info/images/c96c/59a5/c96c59a5879aeb71ec85c56399d6dce8.png" src="https://blog.rpsl.info/images/c96c/59a5/c96c59a5879aeb71ec85c56399d6dce8.png"&gt;&lt;/p&gt;
&lt;p&gt;Для каждого поста заводится свой issue. Бот делает это автоматически после написания первого комментария к посту.&lt;/p&gt;
&lt;p&gt;Посты связываются с issue через название issue, поэтому их заголовок должен как-нибудь сопоставляться с постом в блоге, на выбор есть несколько правил:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Issue title contains page pathname&lt;/li&gt;
&lt;li&gt;Issue title contains page URL&lt;/li&gt;
&lt;li&gt;Issue title contains page title&lt;/li&gt;
&lt;li&gt;Issue title contains page og:title&lt;/li&gt;
&lt;li&gt;Specific issue number&lt;/li&gt;
&lt;li&gt;Issue title contains specific term&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Делая экспорт старых комментариев, я выбрал дефолтное сопоставление через &lt;code&gt;page title&lt;/code&gt;, но уже сейчас понимаю что это будет создавать проблемы. Как только &lt;code&gt;title&lt;/code&gt; у поста изменится, то придется не забыть сразу же его обновить в заголовке issue.&lt;/p&gt;
&lt;p&gt;Если бы начинал заново, то выбрал бы &lt;code&gt;Specific issue number&lt;/code&gt;, но сейчас уже не хочется все переделывать.&lt;/p&gt;
&lt;p&gt;Когда-нибудь я соберусь и проведу дополнительную миграцию, в которой каждому посту присвою уникальный идентификатор и после этого обновлю все issue.&lt;/p&gt;
&lt;h2&gt;Перенос данных&lt;/h2&gt;
&lt;p&gt;Первый же запрос вида "utterances disqus import" ведет на &lt;a href="https://github.com/utterance/utterances/issues/7"&gt;issue&lt;/a&gt;, в котором ссылаются на программу, которая может обработать файл экспорта и через API создать все issue и запостить комментарии в них.&lt;/p&gt;
&lt;p&gt;К сожалению, все комментарии будут добавлены от одного аккаунта, я локализовал предупредительный текст, который сопровождает каждый перенесенный комментарий. Думаю что этого будет достаточно.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Архивный комментарий. Был написан&lt;/em&gt; &lt;strong&gt;alice2k&lt;/strong&gt; (&lt;strong&gt;18.03.2020 07:01:41&lt;/strong&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Второй сложностью оказалось что программа импорта написана на dotnet, с которым я никогда в жизни не сталкивался. Просидев несколько часов на stackoverflow я разобрался что нужно установить и как это запустить в macOS, а в последствие упаковал её в docker контейнер.&lt;/p&gt;
&lt;p&gt;Во время переноса комментариев нашел занятный баг: после обработки приблизительно 200 поста все остальные отказывались обрабатываться и не могли пройти проверку доступности оригинального поста.&lt;/p&gt;
&lt;p&gt;В программе есть проверка, которая делает запрос к оригинальной странице с комментариями и проверяет код ответа, если он 200, то значит все хорошо, если отличается, то, значит, это комментарии к какому-то удаленному посту и импортировать их не нужно.&lt;/p&gt;
&lt;p&gt;В какой-то момент я подумал что это на сервере включается защита и пытался исправить проблему выставлением таймаутов. Когда я проверял посты с которых начинались ошибки, то они обрабатывались правильно.&lt;/p&gt;
&lt;p&gt;В итоге, оказалось, что в коде допущена ошибка и при обработке каждого поста, в свойство запроса добавляется заголовок &lt;code&gt;User-Agent&lt;/code&gt;, но добавляя новый, старые не удаляются и таким образом размер запроса начинает превышать размер который готов переварить сервер.&lt;/p&gt;
&lt;pre&gt;&lt;code class="csharp"&gt;client.DefaultRequestHeaders.Add(&amp;quot;User-Agent&amp;quot;, &amp;quot;.NET Disqus to GitHub Issue Importer&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Странно что Nginx возвращал &lt;code&gt;400 Bad Request&lt;/code&gt;, а не &lt;code&gt;413 Entity Too Large&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Алгоритм работы мигратора:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Разбирает файл &lt;a href="https://help.disqus.com/en/articles/1717164-comments-export"&gt;экспорта из Disqus&lt;/a&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;Проверяет что оригинальные страницы существуют и отдают код 200&lt;/li&gt;
&lt;li&gt;Через API GitHub создают issue и комментарии к ним, по выбранному формату&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я запускал мигратор несколько раз. В первые разы я замечал какие-то мелочи которые мне не нравились и уходил их переделывать. Раза с пятого получилось нормально. Все свои правки я оформил в виде &lt;a href="https://github.com/JuergenGutsch/disqus-to-github-issues/pull/5"&gt;PR в оригинальный репозиторий&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Поправил баг, добавил пару мелочей, добавил Dockerfile и описал в README как запускать и на что обратить внимание при запуске.&lt;/p&gt;
&lt;p&gt;Сейчас, чтобы провести миграцию, нужно клонировать к себе &lt;a href="https://github.com/Rpsl/disqus-to-github-issues"&gt;репозиторий&lt;/a&gt;, внести правки которые описаны в README и запустить мигратор&lt;/p&gt;
&lt;pre&gt;&lt;code class="shell"&gt;$ docker run --rm \
    -v &amp;lt;path to Disqus XML file on host machine&amp;gt;:/app/disqus.xml \
    disqus-to-github-issues:latest \
    run \
        /app/disqus.xml \
        &amp;lt;GitHub username&amp;gt; \
        &amp;lt;GitHub repo name&amp;gt; \
        &amp;lt;GitHub personal access token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Результат&lt;/h2&gt;
&lt;p&gt;Все имеющиеся комментарии я перенес на GitHub.&lt;/p&gt;
&lt;p&gt;Увы, они потеряли свою ветвистость и связь со своими изначальными авторами. Избежать этого было нельзя, но их не так много, чтобы сильно из-за этого переживать.&lt;/p&gt;
&lt;p&gt;Отказ от Disqus я считаю правильным шагом, который надо было сделать еще лет десять назад.&lt;/p&gt;</content><category term="09"/><category term="blog"/><category term="github"/><category term="disqus"/></entry><entry><title>Nativefier. Создание приложений из сайтов</title><link href="https://blog.rpsl.info/2020/05/nativefier-how-create-native-application/" rel="alternate"/><published>2020-05-31T09:50:02+03:00</published><updated>2020-05-31T09:50:02+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2020-05-31:/2020/05/nativefier-how-create-native-application/</id><summary type="html">&lt;p&gt;Несколько месяцев назад я открыл для себя &lt;a href="https://github.com/jiahaog/nativefier"&gt;Nativefier&lt;/a&gt; — это инструмент который позволяет создавать типовые приложения на базе electron из web-сайтов.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Electron — это фреймворк, разработанный GitHub. Позволяет разрабатывать нативные графические приложения для настольных операционных систем с помощью веб-технологий. Фреймворк включает в себя Node.js для работы с back-end и библиотеку рендеринга из Chromium&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.electronjs.org/"&gt;Сайт проекта, с примерами и документацией&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.electronjs.org/apps"&gt;Каталог приложений на базе electron&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я целенаправленно начал искать такой инструмент, когда осознал, что уже четыре года использую Safari исключительно для того чтобы держать открытым окно с метриками в Grafana. Safari, в моем случае, выступает в роли отдельного приложения, к которому можно легко получить доступ через cmd+tab&lt;/p&gt;
&lt;p&gt;&lt;img alt="macos grafana application" src="https://blog.rpsl.info/images/4b03/c34e/4b03c34eb35269067726c12bb0ada0de.png"&gt;&lt;/p&gt;
&lt;p&gt;Разбираясь какие есть сервисы для этого - обнаружилось что их множество. В основном это сайты на которых нужно отметить несколько чекбоксов, ввести название и загрузить иконку. Затем они соберут приложение, как я понял, почти у всех под капотом именно Nativefier.&lt;/p&gt;
&lt;p&gt;Если интересно и не хотите заморачиваться с установкой и сборкой, то список сервисов есть в конце статьи.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Несколько месяцев назад я открыл для себя &lt;a href="https://github.com/jiahaog/nativefier"&gt;Nativefier&lt;/a&gt; — это инструмент который позволяет создавать типовые приложения на базе electron из web-сайтов.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Electron — это фреймворк, разработанный GitHub. Позволяет разрабатывать нативные графические приложения для настольных операционных систем с помощью веб-технологий. Фреймворк включает в себя Node.js для работы с back-end и библиотеку рендеринга из Chromium&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.electronjs.org/"&gt;Сайт проекта, с примерами и документацией&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.electronjs.org/apps"&gt;Каталог приложений на базе electron&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я целенаправленно начал искать такой инструмент, когда осознал, что уже четыре года использую Safari исключительно для того чтобы держать открытым окно с метриками в Grafana. Safari, в моем случае, выступает в роли отдельного приложения, к которому можно легко получить доступ через cmd+tab&lt;/p&gt;
&lt;p&gt;&lt;img alt="macos grafana application" src="https://blog.rpsl.info/images/4b03/c34e/4b03c34eb35269067726c12bb0ada0de.png"&gt;&lt;/p&gt;
&lt;p&gt;Разбираясь какие есть сервисы для этого - обнаружилось что их множество. В основном это сайты на которых нужно отметить несколько чекбоксов, ввести название и загрузить иконку. Затем они соберут приложение, как я понял, почти у всех под капотом именно Nativefier.&lt;/p&gt;
&lt;p&gt;Если интересно и не хотите заморачиваться с установкой и сборкой, то список сервисов есть в конце статьи.&lt;/p&gt;


&lt;h3&gt;Установка&lt;/h3&gt;
&lt;p&gt;Если у вас macOS, то проще всего установить через &lt;code&gt;brew&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="bash"&gt;~ » brew info nativefier
nativefier: stable 8.0.7 (bottled)
Wrap web apps natively
https://github.com/jiahaog/nativefier
/usr/local/Cellar/nativefier/8.0.7 (7,969 files, 25.4MB) *
  Poured from bottle on 2020-04-25 at 00:18:44
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/nativefier.rb
==&amp;gt; Dependencies
Required: node ✔
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Для остальных случаев можно использовать docker&lt;/p&gt;
&lt;pre&gt;&lt;code class="bash"&gt;docker pull jiahaog/nativefier
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Для совсем экстремальных случаев, всегда можно собрать руками, либо поставить через &lt;code&gt;npm&lt;/code&gt; или &lt;code&gt;yarn&lt;/code&gt;, инструкции есть &lt;a href="https://github.com/jiahaog/nativefier"&gt;на гитхабе&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Базовая сборка&lt;/h3&gt;
&lt;p&gt;Чтобы собрать базовое приложение, достатончо указать как оно должно называться, передать аргументом какая страница должна открываться при запуске приложения.&lt;/p&gt;
&lt;p&gt;&lt;img alt="macos grafana application" src="https://blog.rpsl.info/images/ef47/a00a/ef47a00ae8e957ead765673fab3f6f79.png"&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="bash"&gt;nativefier \
    -n &amp;quot;Grafana&amp;quot; \
    -p 'osx' \
    -f -m \
    -i /path/to/icon.png \
        --internal-urls &amp;quot;https://play.grafana.org/d/*&amp;quot; \
    --single-instance \
        &amp;quot;https://play.grafana.org/d/000000012/grafana-play-home?orgId=1&amp;quot; \
    /path/to/output/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Обратите внимание на параметры:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--internal-urls "https://play.grafana.org/d/*"&lt;/code&gt; -  все ссылки попадающие под маску будут открываться внутри приложения. Все остальные будут открыты в браузере по умолчанию&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--single-instance&lt;/code&gt; - можно ли запускать несколько копий приложения&lt;/li&gt;
&lt;li&gt;Иконка была взята в &lt;a href="https://www.google.com/search?q=grafana+logo+png+transparent"&gt;поиске по картинкам&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Дополнительные улучшения&lt;/h3&gt;
&lt;p&gt;В качестве дополнительных улучшений, на macOS, можно сделать чтобы title bar приложения был спрятан и, как бы, интегрирован в него.&lt;/p&gt;
&lt;p&gt;&lt;img alt="macos grafana application" src="https://blog.rpsl.info/images/14d9/16be/14d916bef2a68dfbc3e44e8c572bc7af.jpeg"&gt;&lt;/p&gt;
&lt;p&gt;Чтобы скрыть тайтл, а кнопки контроля встроить в приложение, нужно использовать параметр&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--title-bar-style&lt;/code&gt; со значением &lt;code&gt;hiddenInset&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Дополнительную информацию можно почитать в &lt;a href="https://www.electronjs.org/docs/api/browser-window#%D0%BA%D0%BB%D0%B0%D1%81%D1%81-browserwindow"&gt;документации к Electron&lt;/a&gt; (1), &lt;a href="https://github.com/electron/electron/blob/master/docs/api/frameless-window.md#alternatives-on-macos"&gt;документации к Electron&lt;/a&gt; (2).&lt;/p&gt;
&lt;p&gt;При этом, если просто скрыть title bar, то после запуска приложения, его будет очень сложно двигать по экрану, т.к. на нем нету мест за которые его можно ухватить.&lt;/p&gt;
&lt;p&gt;Чтобы исправить это, необходимо определить элементы приложения, за которые его можно перетаскивать по экрану. Это делается с помощью css свойства &lt;code&gt;-webkit-app-region: no-drag&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Таки образом, нужно создать отдельный css файл, который мы будем внедрять в приложение на этапе сборки, через параметр &lt;code&gt;--inject&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Дополнительно информацию можно почитать в &lt;a href="https://www.electronjs.org/docs/api/frameless-window#%D1%80%D0%B5%D0%B3%D0%B8%D0%BE%D0%BD-%D0%BF%D0%B5%D1%80%D0%B5%D0%BD%D0%BE%D1%81%D0%B0-drag-and-drop"&gt;документации к Electron&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;После того как мы скрыли тайтл, элементы управления окно сползли вниз и залезли на иконку с логотипом. Чтобы сделать этот угол примыкания корректным, я внес еще несколько изменений во внедряемый стиль:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Добавил внутренний верхний отступ у логотипа&lt;/li&gt;
&lt;li&gt;Увеличил ширину бокового меню, чтобы элементы управления помещались в него&lt;/li&gt;
&lt;li&gt;Поправил правый отступ у логотипа, чтобы он выглядел более симметричного, в новой ширине колонки&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В итоге, стиль который я внедрил в приложение выглядит так:&lt;/p&gt;
&lt;pre&gt;&lt;code class="css"&gt;.sidemenu {
    padding-top: 40px;
    width: 75px !important;
}

.sidemenu__logo {
    padding-left: 20px !important;
}

.navbar {
    -webkit-app-region: drag;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;А команда для сборки приложений таким образом:&lt;/p&gt;
&lt;pre&gt;&lt;code class="bash"&gt;nativefier \
    -n &amp;quot;Grafana&amp;quot; \
    -p 'osx' \
    -f -m \
    --title-bar-style &amp;quot;hiddenInset&amp;quot; \
    --inject ./style.css \
    -i /path/to/icon.png \
    --internal-urls &amp;quot;https://play.grafana.org/d/*&amp;quot; \
    --single-instance \
    &amp;quot;https://play.grafana.org/d/000000012/grafana-play-home?orgId=1&amp;quot; \
    /path/to/output/
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;GitHub&lt;/h3&gt;
&lt;p&gt;Для удобства, я скопировал все материалы, в том числе и иконку, в отдельный gist&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/Rpsl/f76805367005c6b3f8df6dbf52b5afac"&gt;https://gist.github.com/Rpsl/f76805367005c6b3f8df6dbf52b5afac&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Сервисы для создания приложений:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://appmaker.xyz/web2desk/"&gt;https://appmaker.xyz/web2desk/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.todesktop.com/"&gt;https://www.todesktop.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://applicationize.me/"&gt;https://applicationize.me/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="05"/><category term="electron"/><category term="macos"/><category term="javascript"/></entry><entry><title>Zero Inbox. Гайд по наведению порядка в почте</title><link href="https://blog.rpsl.info/2020/03/zero-inbox/" rel="alternate"/><published>2020-03-17T11:42:39+03:00</published><updated>2020-03-17T11:42:39+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2020-03-17:/2020/03/zero-inbox/</id><summary type="html">&lt;h2&gt;Проблематика&lt;/h2&gt;
&lt;p&gt;Моему почтовому ящику на gmail много лет. Более десяти лет самостоятельного существования, а также в нем лежат архивы из других почтовых систем. Все эти годы я использовал его так как и нужно использовать умные продукты:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Не сортировал письма, так как для этого есть хороший поиск&lt;/li&gt;
&lt;li&gt;Не удалял письма с большими вложениями, так как для этого есть куча пространства&lt;/li&gt;
&lt;li&gt;Не категоризировал письма и позволял сервису обучаться на моих привычках, для автоматических эвристик&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;И это было чудесное время, пока мне не захотелось навести в нем порядок.&lt;/p&gt;
&lt;p&gt;Задача навести порядок не была самоцелью, скорее меня начало раздражать что весь inbox завален каким-то мусором: заказы из магазинов, рекламные письма, обновления от почты, все это вперемешку с периодическими дайджестами и личной перепиской.&lt;/p&gt;
&lt;p&gt;&lt;img alt="gmail inbox" src="https://blog.rpsl.info/images/3450/d54c/3450d54cbe1f5ee4a36447a82fb19b42.png"&gt;
&lt;em&gt;^^ Это не настоящий скрин моей почты. Просто картинка для превью.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Задача&lt;/h2&gt;
&lt;p&gt;Прежде чем переходить к действиям я постарался сформулировать задачу которую хочу решить, получилось следующее:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Навести порядок в Лейблах. Сгруппировать их в логические блоки, добавить нужные и удалить лишние&lt;/li&gt;
&lt;li&gt;Создать правила для автоматического присвоения ярлыков от  основных источников. Пересмотреть правила попадания в Inbox для этих правил&lt;/li&gt;
&lt;li&gt;Отписаться от лишних рассылок&lt;/li&gt;
&lt;li&gt;Удалить письма которые посчитаю мусорными&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Во втором пункте, говоря про "правила попадания в inbox", я имею ввиду, что новые письма, которые попадают под фильтры, могут сразу переходить в архив, но, при этом, остаются непрочитанными. Их не будет видно во "входящих", но к ним всегда можно вернуться. Это  удобно для различных уведомлений или дайджестов.&lt;/p&gt;
</summary><content type="html">&lt;h2&gt;Проблематика&lt;/h2&gt;
&lt;p&gt;Моему почтовому ящику на gmail много лет. Более десяти лет самостоятельного существования, а также в нем лежат архивы из других почтовых систем. Все эти годы я использовал его так как и нужно использовать умные продукты:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Не сортировал письма, так как для этого есть хороший поиск&lt;/li&gt;
&lt;li&gt;Не удалял письма с большими вложениями, так как для этого есть куча пространства&lt;/li&gt;
&lt;li&gt;Не категоризировал письма и позволял сервису обучаться на моих привычках, для автоматических эвристик&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;И это было чудесное время, пока мне не захотелось навести в нем порядок.&lt;/p&gt;
&lt;p&gt;Задача навести порядок не была самоцелью, скорее меня начало раздражать что весь inbox завален каким-то мусором: заказы из магазинов, рекламные письма, обновления от почты, все это вперемешку с периодическими дайджестами и личной перепиской.&lt;/p&gt;
&lt;p&gt;&lt;img alt="gmail inbox" src="https://blog.rpsl.info/images/3450/d54c/3450d54cbe1f5ee4a36447a82fb19b42.png"&gt;
&lt;em&gt;^^ Это не настоящий скрин моей почты. Просто картинка для превью.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Задача&lt;/h2&gt;
&lt;p&gt;Прежде чем переходить к действиям я постарался сформулировать задачу которую хочу решить, получилось следующее:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Навести порядок в Лейблах. Сгруппировать их в логические блоки, добавить нужные и удалить лишние&lt;/li&gt;
&lt;li&gt;Создать правила для автоматического присвоения ярлыков от  основных источников. Пересмотреть правила попадания в Inbox для этих правил&lt;/li&gt;
&lt;li&gt;Отписаться от лишних рассылок&lt;/li&gt;
&lt;li&gt;Удалить письма которые посчитаю мусорными&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Во втором пункте, говоря про "правила попадания в inbox", я имею ввиду, что новые письма, которые попадают под фильтры, могут сразу переходить в архив, но, при этом, остаются непрочитанными. Их не будет видно во "входящих", но к ним всегда можно вернуться. Это  удобно для различных уведомлений или дайджестов.&lt;/p&gt;


&lt;h2&gt;Наведение порядка в Лейблах&lt;/h2&gt;
&lt;p&gt;В первую очередь я создал несколько логических групп для лейблов, у меня получился такой список:&lt;/p&gt;
&lt;p&gt;&lt;img alt="gmaiil labels" src="https://blog.rpsl.info/images/8061/b6e1/8061b6e19297d99127edb90b0e2bd8ec.png"&gt;&lt;/p&gt;
&lt;p&gt;Внутри каждого из этих лейблов есть пачка sub-labels и для избежания путаницы я решил что все письма будут лежать на уровне &lt;code&gt;label/sub-label&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;На скриншоте отображена конфигурация на момент написания статьи, хотя изначально было по-другому:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Я пытался разграничить письма по доменам и хостингу в разные фильтры &lt;code&gt;Services/Domains&lt;/code&gt; &amp;amp; &lt;code&gt;Services/Hosting&lt;/code&gt;, но в процессе понял что это одинаковая сущность и нет смысла её дробить. Оставил только &lt;code&gt;Services/Hosting&lt;/code&gt;, как более общую, на мой взгляд&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Notifications/Receipts&lt;/code&gt; &amp;amp; &lt;code&gt;Notifications/Shops&lt;/code&gt;. Изначально, Receipts я заводил чтобы туда падали уведомления от различных платежных систем, такси и прочих сервисов. Уже в процессе сортировки я понял что сам путаюсь куда какое письмо относится и, вероятно, нужно эти две категории слить в одну.&lt;/p&gt;
&lt;p&gt;Уведомление от магазина "Кони и заводы": Ваш счет оплачен. Вот куда это? В магазины или в чеки? В итоге сам придумал логическую разницу - в &lt;code&gt;Receipts&lt;/code&gt; отправляется все что не привязано к магазинам, либо не является физическим предметом. Стало понятно, так и оставил.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Work/Unsorted&lt;/code&gt; &amp;amp; &lt;code&gt;Services/Anything&lt;/code&gt;. Эти лейблы появились как раз из-за того что я решил все хранить в &lt;code&gt;sub-label&lt;/code&gt; . Туда отправляются письма которые не попадают под правила кластеризации и их слишком мало чтобы выносить в отдельный ярлык&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Первый подход&lt;/h2&gt;
&lt;p&gt;В первую очередь я занялся самым простым: дайджестами, нотификациями от крупных сервисов и уведомлениями от сервисов которыми часто пользуюсь. Тут никакой автоматизации не требуется, абсолютно механическая работа. Я просто открыл две вкладки с почтой: в первой работал со списком писем, во второй настраивал фильтры и занимался сортировкой.&lt;/p&gt;
&lt;p&gt;Руки быстро привыкают к одинаковой последовательности действий и за пару часов мне удалось разобрать большой массив писем.&lt;/p&gt;
&lt;p&gt;К сожаления я не записывал прогресс чтобы поделиться подробной статистикой :(&lt;/p&gt;
&lt;p&gt;Во время этих действий я активно пользовался поиском в почте, так что рекомендую ознакомиться с документацией по фильтрам:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.google.com/mail/answer/7190"&gt;Search operators you can use with Gmail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Все входящие без лейблов &lt;a href="https://mail.google.com/mail/u/0/#search/in%3Ainbox+-has%3Auserlabels"&gt;in:inbox -has:userlabels&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Весь архив без лейблов &lt;a href="https://mail.google.com/mail/u/0/#search/-in%3Ainbox+-has%3Auserlabels"&gt;-in:inbox -has:userlabels&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Второй подход&lt;/h2&gt;
&lt;p&gt;После решения самых простых задач мне пришлось решать каким образом дальше организовать процесс.&lt;/p&gt;
&lt;p&gt;Реальность была такова, что у меня оставалось несколько десятков тысяч писем во "входящих" и отсутствие понимания как их кластеризовать.&lt;/p&gt;
&lt;p&gt;Было необхоидмо это как-нибудь автоматизировать. Я предположил что наверняка есть готовые скрипты, которые умеют подключаться по imap к почтовому ящику и делать что-нибудь. Поверхностный поиск на github навел меня на репозиторий:&lt;/p&gt;
&lt;p&gt;&#128161; &lt;a href="https://github.com/oliver006/elasticsearch-gmail"&gt;Elasticsearch For Beginners: Indexing your Gmail Inbox&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Это набор скриптов на Python 2.x (на момент действий описываемых в статье), который позволяет распарсить &lt;a href="https://en.wikipedia.org/wiki/Mbox"&gt;mbox&lt;/a&gt; формат и загрузить письма в Elasticsearch.&lt;/p&gt;
&lt;p&gt;В  &lt;a href="https://github.com/oliver006/elasticsearch-gmail/blob/ac3527d8024abfc1a99ad72d43a0680bf7aa16fc/README.md"&gt;README.md&lt;/a&gt; есть подробнейшее описание, от идеи до примеров использования.&lt;/p&gt;
&lt;p&gt;После того как письма будут загружены в хранилище — можно использовать любые агрегатные функции и строить аналитику по своему почтовому ящику.&lt;/p&gt;
&lt;h3&gt;Где взять mbox?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Если у вас Google Mail, то идете на &lt;a href="https://takeout.google.com/settings/takeout?pli=1"&gt;takeout.google.com&lt;/a&gt;, там запрашиваете выгрузку вашего почтового ящика и через несколько часов получаете готовый архив&lt;/li&gt;
&lt;li&gt;Можно поискать скрипты для выгрузки сообщений, что-нибудь в стиле &lt;a href="https://github.com/search?q=imap+to+mbox"&gt;imapbackup или imap to mbox&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Подключиться почтовым клиентом к ящику и сделать выгрузку через него - &lt;a href="https://support.apple.com/ru-ru/guide/mail/mlhlp1030/mac"&gt;Mail.app такое умеет&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;MongoDB&lt;/h3&gt;
&lt;p&gt;Поигравшись некоторое время с Elasticsearch, мне захотелось модифицировать данный скрипт под работу с MongoDB. Это связано с тем что у меня нет опыта работы с Elasticsearch и мне не хотелось заниматься его изучением, как минимум, до тех пор пока не завершен процесс уборки в ящике.&lt;/p&gt;
&lt;p&gt;Первым делом я модифицировал исходный скрипт чтобы он загружал данные в MongoDB, убедившись что концепт работает, я переписал скрипт, попутно проведя рефакторинг, обновление зависимостей и перевод на Python 3.x.&lt;/p&gt;
&lt;p&gt;&#128161; &lt;a href="https://github.com/Rpsl/mongodb-gmail"&gt;https://github.com/Rpsl/mongodb-gmail&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Скрипт умеет все что умеет его аналог, только работает с MongoDB как с основным хранилищем. После загрузки данных, используя aggregation framework, можно строить любую аналитику по вашему почтовому ящику.&lt;/p&gt;
&lt;pre&gt;&lt;code class="bash"&gt;Usage: cli.py [OPTIONS] FILENAME

  Print FILENAME.

  FILENAME path to mbox file

Options:
  --mongodb TEXT          Connection string for mongodb instance  [default:
                          mongodb://root:example@127.0.0.1]
  --db-name TEXT          MongoDB database name  [default: google-mail]
  --collection-name TEXT  MongoDB collection name  [default: mails]
  --init BOOLEAN          Force deleting and re-initializing the MongoDB
                          collection  [default: False]
  --body BOOLEAN          Will index all body content, stripped of HTML/CSS/JS
                          etc. Adds fields: &amp;quot;body&amp;quot; and &amp;quot;body_size&amp;quot;  [default:
                          False]
  --help                  Show this message and exit.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Например, чтобы сгруппировать письма во "входящих" по отправителю, нужно выполнить следующий запрос (значение в &lt;code&gt;labels&lt;/code&gt; может отличаться, в зависимости от ваших языковых настроек):&lt;/p&gt;
&lt;pre&gt;&lt;code class="javascript"&gt;db.mails.aggregate([
    { $match: { labels: { $in: ['inbox'] } } },
    { $group: { _id: &amp;quot;$from&amp;quot;, total: { $sum : 1 } } },
    { $sort : { &amp;quot;total&amp;quot;: -1 } }
])
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Результат будет в сгруппированном и отсортированном виде.&lt;/p&gt;
&lt;pre&gt;&lt;code class="json"&gt;{ &amp;quot;_id&amp;quot; : &amp;quot;****@****&amp;quot;, &amp;quot;total&amp;quot; : 3360 }
{ &amp;quot;_id&amp;quot; : &amp;quot;****@****&amp;quot;, &amp;quot;total&amp;quot; : 2240 }
{ &amp;quot;_id&amp;quot; : &amp;quot;inform@money.yandex.ru&amp;quot;, &amp;quot;total&amp;quot; : 360 }
{ &amp;quot;_id&amp;quot; : &amp;quot;****@gmail.com&amp;quot;, &amp;quot;total&amp;quot; : 342 }
{ &amp;quot;_id&amp;quot; : &amp;quot;notification@russianpost.ru&amp;quot;, &amp;quot;total&amp;quot; : 337 }
{ &amp;quot;_id&amp;quot; : &amp;quot;transaction@notice.aliexpress.com&amp;quot;, &amp;quot;total&amp;quot; : 318 }
{ &amp;quot;_id&amp;quot; : &amp;quot;gmail@rpsl.info&amp;quot;, &amp;quot;total&amp;quot; : 229 }
{ &amp;quot;_id&amp;quot; : &amp;quot;****&amp;quot;, &amp;quot;total&amp;quot; : 223 }
{ &amp;quot;_id&amp;quot; : &amp;quot;notifications@github.com&amp;quot;, &amp;quot;total&amp;quot; : 190 }
{ &amp;quot;_id&amp;quot; : &amp;quot;****&amp;quot;, &amp;quot;total&amp;quot; : 133 }
{ &amp;quot;_id&amp;quot; : &amp;quot;****&amp;quot;, &amp;quot;total&amp;quot; : 129 }
{ &amp;quot;_id&amp;quot; : &amp;quot;****&amp;quot;, &amp;quot;total&amp;quot; : 119 }
{ &amp;quot;_id&amp;quot; : &amp;quot;info@letyshops.com&amp;quot;, &amp;quot;total&amp;quot; : 115 }
{ &amp;quot;_id&amp;quot; : &amp;quot;noreply@reg.ru&amp;quot;, &amp;quot;total&amp;quot; : 104 }
{ &amp;quot;_id&amp;quot; : &amp;quot;service@paypal.com&amp;quot;, &amp;quot;total&amp;quot; : 96 }
{ &amp;quot;_id&amp;quot; : &amp;quot;****&amp;quot;, &amp;quot;total&amp;quot; : 95 }
{ &amp;quot;_id&amp;quot; : &amp;quot;noreply@habr.com&amp;quot;, &amp;quot;total&amp;quot; : 91 }
{ &amp;quot;_id&amp;quot; : &amp;quot;info@letyshops.ru&amp;quot;, &amp;quot;total&amp;quot; : 74 }
{ &amp;quot;_id&amp;quot; : &amp;quot;info@site.hh.ru&amp;quot;, &amp;quot;total&amp;quot; : 70 }
{ &amp;quot;_id&amp;quot; : &amp;quot;no-reply@taxi.yandex.ru&amp;quot;, &amp;quot;total&amp;quot; : 66 }
Type &amp;quot;it&amp;quot; for more
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Для того чтобы упростить себе жизнь и не смотреть все данные в терминале, можно экспортировать их в csv и далее работать с готовой таблицей.&lt;/p&gt;
&lt;p&gt;Для экспорта необходимо добавить параметр &lt;code&gt;$out&lt;/code&gt; к нашему запросу. Тогда он запишет результат запроса в отдельную коллекцию.&lt;/p&gt;
&lt;pre&gt;&lt;code class="javascript"&gt;db.mails.aggregate([
    { $match: { labels: { $in: ['inbox'] } } },
    { $group: { _id: &amp;quot;$from&amp;quot;, total: { $sum : 1 } } },
    { $sort: { &amp;quot;total&amp;quot;: -1 } },
    { $out: &amp;quot;export&amp;quot; }
])
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;После этого, с помощью утилиты &lt;code&gt;mongoexport&lt;/code&gt;, можно выгрузить всю коллекцию в виде csv файла.&lt;/p&gt;
&lt;pre&gt;&lt;code class="bash"&gt;mongoexport -d google-mail \
        -c export \
        -u root \
        -p example \
        --authenticationDatabase admin \
        --fields &amp;quot;_id,total&amp;quot; \
        --type=csv \
        --sort='{total:-1}' \
        -o ~/path/to/file.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Далее, отредактируем по шаблону строчки в csv, добавив ссылки на страницу с поиском по отправителю:&lt;/p&gt;
&lt;pre&gt;&lt;code class="bash"&gt;https://mail.google.com/mail/u/0/#search/from%3Atest%40example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;SQL to MongoDB Cheatsheet&lt;/h3&gt;
&lt;p&gt;&lt;img alt="sql vs mongodb cheatsheet" src="https://blog.rpsl.info/images/7727/f056/7727f056691784aea4c69fb5ae177373.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://docs.mongodb.com/manual/reference/sql-comparison/"&gt;SQL to MongoDB Mapping Chart&lt;/a&gt; - отдельно хочу порекомендовать таблицу с сопоставлением запросов на sql и в MongoDB. Может быть очень полезна, если до этого опыта работы с MongoDB не было.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Занимательный факт:&lt;/h3&gt;
&lt;p&gt;В версии python 2.7, для чтения &lt;code&gt;mbox&lt;/code&gt; файла, имеется метод &lt;code&gt;mailbox.Unixmailbox&lt;/code&gt;, а в версии 3.1 его уже нету, и предлагается использовать &lt;code&gt;mailbox.mbox&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;При этом, версия 2.7 для разбора писем используется построчное чтение, а в версии 3.1 сначала генерируется карта всех позиций (начало письма -&amp;gt; конец письма) и только после этого можно совершать навигацию по письмам.&lt;/p&gt;
&lt;p&gt;С одной стороны крутое улучшение, с другой, на моем ноутбуке и почтовом ящике размером в несколько гигабайт, каждый запуск скрипта приводил к нагрузке CPU под 100% и ожиданию в несколько минут пока он соизволит распарсить весь файл и начнет работать с ним.&lt;/p&gt;
&lt;h4&gt;Python 3.1&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://github.com/python/cpython/blob/f0fa1b2f670334f9f4b123e6ecb65c3beef979ed/Lib/mailbox.py"&gt;https://github.com/python/cpython/blob/f0fa1b2f670334f9f4b123e6ecb65c3beef979ed/Lib/mailbox.py&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="python"&gt;def _generate_toc(self):
    &amp;quot;&amp;quot;&amp;quot;Generate key-to-(start, stop) table of contents.&amp;quot;&amp;quot;&amp;quot;
    starts, stops = [], []
    self._file.seek(0)
    while True:
        line_pos = self._file.tell()
        line = self._file.readline()
        if line.startswith('From '):
            if len(stops) &amp;lt; len(starts):
                stops.append(line_pos - len(os.linesep))
            starts.append(line_pos)
        elif not line:
            stops.append(line_pos)
            break
    self._toc = dict(enumerate(zip(starts, stops)))
    self._next_key = len(self._toc)
    self._file_length = self._file.tell()
&lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;Python 2.7&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://github.com/python/cpython/blob/6a336f6484a13c01516b6bfc3b767075cc2cb4f7/Lib/mailbox.py"&gt;https://github.com/python/cpython/blob/6a336f6484a13c01516b6bfc3b767075cc2cb4f7/Lib/mailbox.py&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="python"&gt;def _search_start(self):
    while 1:
        pos = self.fp.tell()
        line = self.fp.readline()
        if not line:
            raise EOFError
        if line[:5] == 'From ' and self._isrealfromline(line):
            self.fp.seek(pos)
            return

def _search_end(self):
    self.fp.readline()      # Throw away header line
    while 1:
        pos = self.fp.tell()
        line = self.fp.readline()
        if not line:
            return
        if line[:5] == 'From ' and self._isrealfromline(line):
            self.fp.seek(pos)
            return
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&#129300; Если бы у меня был доступ к аналитике всего мира, мне было бы очень интересно посмотреть сколько энергии было потрачено в мире из-за этого изменения.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Финальный рывок&lt;/h3&gt;
&lt;p&gt;Используя механизмы разработанные во "втором подходе", мне удалось за несколько вечеров перебрать все оставшиеся письма в ящике.&lt;/p&gt;
&lt;p&gt;Если посмотреть на диаграмму распределения, то видно что у нас есть сотня-другая отправителей от которых очень много сообщений (их я разобрал в "первом подходе") и огромный хвост не системных сообщений.&lt;/p&gt;
&lt;p&gt;На масштабе не видно, там, в среднем, &amp;lt; 100 сообщений от отправителя и плавно убывает до 1.&lt;/p&gt;
&lt;p&gt;&lt;img alt="distribution" src="https://blog.rpsl.info/images/11db/c88d/11dbc88d33325b7f5a049b01f16543da.png"&gt;
&lt;em&gt;На графике отображено распределение писем. Каждая точка - это уникальный отправитель. По шкале Y отображается количество писем от этого отправителя&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Разгребание этого хвоста оказалось унылой механической работой, гораздо скучнее чем программировать. Фильтруешь по отправителю через поиск и принимаешь решение:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Не нужно. ⟶ Удалить&lt;/li&gt;
&lt;li&gt;Нужно. Можно создать фильтр на будущее. ⟶ Создаем фильтр. Проставляем лейбл. Архивируем.&lt;/li&gt;
&lt;li&gt;Нужно. Фильтр не требуется. ⟶ Проставляем лейбл. Архивируем.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Выводы&lt;/h2&gt;
&lt;p&gt;C момента завершения процесса, до написания поста прошел почти месяц, поэтому я могу поделиться взвешенными выводами.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Во-первых, теперь "Inbox" воспринимается совсем по другому. Все что в нем есть - это  незавершенные дела. Если рассылка, то нужно её прочитать или отписаться или удалить. Если переписка - то значит надо довести её до логического завершения и отправить в архив.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Во-вторых, непрочитанные письма, которые лежат вне инбокса (в архиве), больше не напрягают. У меня сейчас есть пачка рассылок которые сразу переходят в "Архив" и лежат там. Я их открываю почитать когда есть время.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;В-третьих, пока я разбирался с этим всем, я отписался от огромного количества рассылок.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="empty inbox" src="https://blog.rpsl.info/images/99b5/2f43/99b52f43f07e29066e552f4670ec82d8.png"&gt;&lt;/p&gt;
&lt;h4&gt;Занимательный факт:&lt;/h4&gt;
&lt;p&gt;По почтовым сообщениям можно видеть четкую корреляцию как месенджеры заходили в нашу жизнь. В начале 201x годов, у меня есть множество писем, где мы шарим друг-другу фотографии и различные файлы или ссылки, а потом они все пропадают, вероятно тогда мы узнали про WhatsApp.&lt;/p&gt;
&lt;h2&gt;Ха-ха. Лох.&lt;/h2&gt;
&lt;p&gt;Уже постфактум, наведя порядок в ящике и опубликовав скрипт я наткнулся на аналогичное решение написанное на Go. Самое печальное, что перед тем как переписывать на Python 3.x, я бегло посмотрел что есть в Go на тему парсинга mbox, но, в тот раз, не нашлось ничего вразумительного.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ru" dir="ltr"&gt;Про Zero Inbox начал писать пост в блог, по пути понял что в некоторых местах можно было сделать лучше. &lt;br&gt;Теперь не могу решиться: оставить как есть и добавить параграф «Ха-ха. Лох.» или сделать по нормальному, хоть и без цели, но и написать сразу об этом.&lt;/p&gt;&amp;mdash; Виктор Диктор (@Rpsl) &lt;a href="https://twitter.com/Rpsl/status/1233335809346068480?ref_src=twsrc%5Etfw"&gt;February 28, 2020&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;Предположив что придется самому разбираться с чтением и парсингом mbox формата, я не стал изучать этот вопрос и сфокусировался на Python версии.&lt;/p&gt;
&lt;p&gt;В дальнейшем, я обновил решение на Go до актуального состояния. Golang версия умеет почти все что и Python, работает в разы быстрее и я рекомендую использовать её.&lt;/p&gt;
&lt;p&gt;&#128161; &lt;a href="https://github.com/Rpsl/mboximporter"&gt;https://github.com/Rpsl/mboximporter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Рассказывать про него отдельно, в рамках этой статьи, нет смысла. Возможно, позднее удастся доработать все @todo и тогда напишу отдельным постом.&lt;/p&gt;
&lt;p&gt;&lt;img alt="shrug" src="https://blog.rpsl.info/images/8b4c/5589/8b4c558919301c66d1d0a9c789ba6113.png"&gt;&lt;/p&gt;</content><category term="03"/><category term="mail"/><category term="python"/><category term="golang"/><category term="mbox"/><category term="mongodb"/><category term="gmail"/></entry><entry><title>Накрутка рефералов или "нубский CPA"</title><link href="https://blog.rpsl.info/2019/12/newbie-cpa/" rel="alternate"/><published>2019-12-20T22:00:00+03:00</published><updated>2019-12-20T22:00:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2019-12-20:/2019/12/newbie-cpa/</id><summary type="html">&lt;p&gt;Некоторые сервисы предоставляют возможность получить доступ к своим платным услугам, за счет привлечения рефералов. В этой статье хочу поделиться самой простой техникой, которая позволит привлекать рефералов без необходимости рассылать ссылки по социальным сетям.&lt;/p&gt;
&lt;p&gt;&lt;img alt="notion" src="https://blog.rpsl.info/images/65d4/8e6d/65d48e6d9bf58e64aea1eca6849f9542.png"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://ru.wikipedia.org/wiki/Реферал"&gt;Реферал&lt;/a&gt; (или реферрал, от англ. referral — «направление») — участник партнёрской программы, зарегистрировавшийся по рекомендации другого участника. Такая схема маркетинга широко распространена в интернете и предполагает регистрацию на сайтах, предоставляющих некие услуги. В этом случае рекомендация сопровождается «реферальной ссылкой», содержащей информацию об учётной записи участника, который получит вознаграждение за привлечение новичков. Вербующего участника принято по аналогии называть «реферер» (англ. referrer).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Вводная&lt;/h3&gt;
&lt;p&gt;Началось все с того, что некоторое время назад я переехал на &lt;a href="https://notion.so"&gt;Notion&lt;/a&gt;, как на основное средство для ведения заметок. До него я много лет пользовался &lt;a href="https://evernote.com/"&gt;Evernote&lt;/a&gt;, но он совсем испортился и перестал отвечать моим потребностям, обрастая при этом дополнительными функциями. Некоторое время мне удавалось заменять его на &lt;a href="http://alternoteapp.com/ru/"&gt;Alternote&lt;/a&gt;, это такая надстройка на Evernote, срезающая все излишества, но Evernote решил поменять модель монетизации, ограничив количество устройств с которыми он будет синхронизироваться в бесплатной версии.&lt;/p&gt;
&lt;p&gt;Так началась моя миграция от одного приложения к другому. Я пробовал &lt;a href="https://bear.app/"&gt;Bear&lt;/a&gt;, но как-то не смог с ним подружиться. Долгое время сидел на &lt;a href="https://www.devontechnologies.com/apps/devonthink"&gt;DEVONthink&lt;/a&gt;, даже оплатил лицензию, но его функциональность была одновременно его достоинством и недостатком. Обилие ненужных функций компенсировалось отсутствием нужных &lt;em&gt;(я опираюсь на опыт полученный от второй версии, сейчас, вроде, вышла третья, но я её не пробовал)&lt;/em&gt;. Пробовал  &lt;a href="https://simplenote.com/"&gt;Simplenote&lt;/a&gt; и даже оставил его когда нужно что-то быстро записать, альтернатива Заметкам от Apple, но он оказался слишком скудный.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Некоторые сервисы предоставляют возможность получить доступ к своим платным услугам, за счет привлечения рефералов. В этой статье хочу поделиться самой простой техникой, которая позволит привлекать рефералов без необходимости рассылать ссылки по социальным сетям.&lt;/p&gt;
&lt;p&gt;&lt;img alt="notion" src="https://blog.rpsl.info/images/65d4/8e6d/65d48e6d9bf58e64aea1eca6849f9542.png"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://ru.wikipedia.org/wiki/Реферал"&gt;Реферал&lt;/a&gt; (или реферрал, от англ. referral — «направление») — участник партнёрской программы, зарегистрировавшийся по рекомендации другого участника. Такая схема маркетинга широко распространена в интернете и предполагает регистрацию на сайтах, предоставляющих некие услуги. В этом случае рекомендация сопровождается «реферальной ссылкой», содержащей информацию об учётной записи участника, который получит вознаграждение за привлечение новичков. Вербующего участника принято по аналогии называть «реферер» (англ. referrer).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Вводная&lt;/h3&gt;
&lt;p&gt;Началось все с того, что некоторое время назад я переехал на &lt;a href="https://notion.so"&gt;Notion&lt;/a&gt;, как на основное средство для ведения заметок. До него я много лет пользовался &lt;a href="https://evernote.com/"&gt;Evernote&lt;/a&gt;, но он совсем испортился и перестал отвечать моим потребностям, обрастая при этом дополнительными функциями. Некоторое время мне удавалось заменять его на &lt;a href="http://alternoteapp.com/ru/"&gt;Alternote&lt;/a&gt;, это такая надстройка на Evernote, срезающая все излишества, но Evernote решил поменять модель монетизации, ограничив количество устройств с которыми он будет синхронизироваться в бесплатной версии.&lt;/p&gt;
&lt;p&gt;Так началась моя миграция от одного приложения к другому. Я пробовал &lt;a href="https://bear.app/"&gt;Bear&lt;/a&gt;, но как-то не смог с ним подружиться. Долгое время сидел на &lt;a href="https://www.devontechnologies.com/apps/devonthink"&gt;DEVONthink&lt;/a&gt;, даже оплатил лицензию, но его функциональность была одновременно его достоинством и недостатком. Обилие ненужных функций компенсировалось отсутствием нужных &lt;em&gt;(я опираюсь на опыт полученный от второй версии, сейчас, вроде, вышла третья, но я её не пробовал)&lt;/em&gt;. Пробовал  &lt;a href="https://simplenote.com/"&gt;Simplenote&lt;/a&gt; и даже оставил его когда нужно что-то быстро записать, альтернатива Заметкам от Apple, но он оказался слишком скудный.&lt;/p&gt;


&lt;p&gt;Так вот, привязавшись к Notion, перенеся в него часть своих архивов, я столкнулся с ограничением бесплатного аккаунта на количество хранимых в нем данных. Тогда я включил подписку на "персональный план", который снимает ограничения. Стоит $5, при помесячной оплате + позволяет несколько месяцев не платить, т.к. за простые действия можно получить на счет некоторое количество кредитов.&lt;/p&gt;
&lt;p&gt;&lt;img alt="notion earn creadit" src="https://blog.rpsl.info/images/6210/58f3/621058f3f279d08964d7da2c4a4e745a.png"&gt;&lt;/p&gt;
&lt;p&gt;Со временем эти кредиты закончились, деньги списывались с карты, но несколько дней назад я заглянул в окно настроек и заметил что можно получить дополнительные кредиты если по моей реферальной ссылке кто-нибудь зарегистрируется.&lt;/p&gt;
&lt;p&gt;И тут я вспомнил как лет 7 назад прокачивал свой dropbox аккаунт.&lt;/p&gt;
&lt;h3&gt;О чем речь?&lt;/h3&gt;
&lt;p&gt;Способ максимально простой. Надо создать рекламное объявление и таргетировать его на   тех пользователей которые уже заинтересованы в продукте.&lt;/p&gt;
&lt;p&gt;В поисковых системах, обычно, реклама занимает первое место. На точных запросах, таких как "dropbox" или "notion", первая (рекламная) и вторая (максимально релевантная) ссылки зачастую ведут на сайт продукта. Наша задача - протолкнуть наше рекламное объявление с реферальной ссылкой на первую позицию.&lt;/p&gt;
&lt;p&gt;&lt;img alt="serp advertising places" src="https://blog.rpsl.info/images/7f8c/f560/7f8cf560aae4f8996a6cbe505396f225.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Пример выдачи по запросу "Dropbox", обратите внимание что обе ссылки ведут на сайт, но первая из них является рекламной.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Все что нам нужно сделать - это создать рекламную компанию.&lt;/p&gt;
&lt;p&gt;В качестве рекламной сети я использую &lt;a href="https://ads.google.com/"&gt;Google&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;На что нужно обратить внимание:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Не пытайтесь подобрать множество ключевых слов по которым объявление должно показываться. Помните, наша задача не рекламировать продукт, а поймать максимально "горячую" аудиторию. Достаточно указать несколько ключевых слов, в случае Notion я указал: Notion, Notion app, Notion pc, Notes, Evernote и еще несколько вариантов для теста&lt;/li&gt;
&lt;li&gt;Обязательно ограничивайте максимальную стоимость клика. Наша задача не привлечь максимальное количество пользователей, а обеспечить их поток за минимальную стоимость. Пусть рекламная сеть сама выбирает кому их показывать, если переходов не будет, то можно будет поднять ставку. Это лучше чем сжечь бюджет за час работы&lt;/li&gt;
&lt;li&gt;Если у вас мало опыта работы с рекламными сетями, то лучше делайте маленькие платежи, например, в 500р. Дело в том что статистика обсчитывается с опозданием, а при неправильном указание бюджетов их можно сжечь за пару минут. Я сам наступил на эти грабли с первым запуском - забыл поставить ограничение цены клика и слил 500р за 7 кликов, которые Google честно продал по 50-100р&lt;/li&gt;
&lt;li&gt;Используйте сегментацию трафика, чтобы ограничивать аудиторию для вашей рекламы. Мало вероятно что пенсионеры или школьники будут эффективными лидами для вас. Я постарался таргетировать рекламу на аудиторию 20-40 лет, интересующихся IT. Дополнительно, можно сделать таргетирование на регион. Рекламная сеть позволяет выбрать локацию и радиус до 500км от неё, этого достаточно чтобы сегментировать трафик на крупные города. Это зависит от целей, в моем случаем можно было не заморачиваться&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Результаты&lt;/h3&gt;
&lt;p&gt;Моя кампания длилась 4 дня, за это время я потратил 1000 рублей. Если быть честным то 1500р, но первые 500р я не хочу учитывать, т.к. сжег их из-за невнимательности.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ads stats" src="https://blog.rpsl.info/images/5b0f/4b1b/5b0f4b1bbb461d97cb0240c25bb78c1b.png"&gt;&lt;/p&gt;
&lt;p&gt;За это я получил ~2000 показов, которые принесли ~624 клика, которые принесли 40 регистраций, за которые на мой виртуальный счет упало $179. На этом моменте мне пришлось остановить кампанию, т.к. $200 это максимальная сумма виртуальных денег на один аккаунт.&lt;/p&gt;
&lt;p&gt;Итого - это почти 3 года бесплатного использования Notion на персональном плане.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ads" src="https://blog.rpsl.info/images/f8d2/94dd/f8d294dd22ca2f26939a3d35aab50256.png"&gt;&lt;/p&gt;
&lt;p&gt;Не могу сказать что это какой-то лютый навар, но, как минимум, из спортивного интереса это того стоило.&lt;/p&gt;
&lt;h3&gt;Где работает?&lt;/h3&gt;
&lt;p&gt;Как я упоминал в начале статьи, аналогичным способом я прокачивал свой dropbox. Точных условий уже не помню, но все годы его существования я просидел на бесплатном тарифе, имея около 25гб дискового пространства. Этим летом перешел на платную версию из-за их ограничений на количество устройств.&lt;/p&gt;
&lt;p&gt;Такой способ подходит под любую CPA модель продвижения, но нужно внимательно смотреть на условия за которые дается бонус. Если среди них есть что-то более сложное чем регистрация, то будьте готовы к тому что конверсия будет ниже на порядки.&lt;/p&gt;
&lt;p&gt;Например, я пытался прокачивать таким образом свой аккаунт на digitalocean, но пользы это не принесло: 70 переходов, 4 регистрации, 0 платящих.&lt;/p&gt;
&lt;p&gt;&lt;img alt="do ref stats" src="https://blog.rpsl.info/images/21a1/3e5b/21a13e5b25c29d8943071a280742f5e7.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Обратите внимание, что реклама с ключевыми словами бренда запрещена.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Важно понимать нишу в которой это может быть маржинально выгодно. В хостинге и так все перегрето и цена клика слишком большая.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Как бонус от прочтения этой статьи, вы стали понимать что такое &lt;a href="https://www.google.com/search?q=cpa+арбитраж"&gt;CPA арбитраж&lt;/a&gt;. Основная идея простая: купить трафик подешевле и перевести туда где за него платят. Например, по этой схеме работают абсолютно все кэшбэк сервисы, только они не маскируются под рекламу, а в явном виде обещают вернуть процент от покупки или фиксированную выплату, в зависимости от рекламодателя, который выплачивает деньги за приведенных клиентов.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;На десерт, есть хороший доклад от &lt;a href="https://twitter.com/bobuk"&gt;@bobuk&lt;/a&gt; про то как они делали рекламную кампанию,  сегментировали трафик и изобретали одноруких бандитов для хобби проекта. Видео от 2013 года, там почти нету про технологии, но оно полезно как пища для размышлений.&lt;/p&gt;
&lt;iframe width="100%" height="315" src="https://www.youtube-nocookie.com/embed/UapiNxeWhmw" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;</content><category term="12"/><category term="notion"/><category term="cpa"/><category term="evernote"/><category term="notes"/><category term="ads"/></entry><entry><title>Перенос mac приложений в brew</title><link href="https://blog.rpsl.info/2019/03/mac-move-apps-into-brew/" rel="alternate"/><published>2019-03-23T11:45:50+03:00</published><updated>2019-03-23T11:45:50+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2019-03-23:/2019/03/mac-move-apps-into-brew/</id><summary type="html">&lt;p&gt;Думаю что многим разработчикам, работающим в macOS, знаком &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt;. Изначально он развивался как менеджер пакетов пришедший на замену &lt;code&gt;macports&lt;/code&gt; и &lt;code&gt;fink&lt;/code&gt;, но, со временем, начал обрастать дополнениями которые поддерживаются сообществом.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Homebrew" src="https://blog.rpsl.info/images/ed3f/2015/ed3f2015cc5be55839f62e5524c62214.png"&gt;&lt;/p&gt;
&lt;p&gt;Одно из таких дополнений это &lt;code&gt;Cask&lt;/code&gt;, оно позволят работать с приложениями с закрытым исходным кодом, которые устанавливаются в систему путем перемещения в директорию &lt;code&gt;/Applications&lt;/code&gt;.
&lt;code&gt;Cask&lt;/code&gt; реализует возможность устанавливать и следить за обновлениями таких приложений как:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Google Chrome&lt;/li&gt;
&lt;li&gt;Mozilla Firefox&lt;/li&gt;
&lt;li&gt;1password&lt;/li&gt;
&lt;li&gt;Sublime Text Edit&lt;/li&gt;
&lt;li&gt;&lt;a href="https://formulae.brew.sh/cask/"&gt;И множество других&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Homebrew Cask Install" src="https://blog.rpsl.info/images/6dff/a904/6dffa9044e4f0d50e4ebcb7c3471155f.gif"&gt;&lt;/p&gt;
&lt;p&gt;После установки приложения через &lt;code&gt;Cask&lt;/code&gt; ничего не меняется. Оно будет работать также как работало до этого, будет предлагать обновления через собственные механизмы. Однако, &lt;code&gt;brew&lt;/code&gt; тоже будет отслеживать состояние приложения и обновлять его если выйдет новая версия, &lt;code&gt;brew&lt;/code&gt; создает команды запуска для терминала, если они предусмотрены и сможет удалить приложение под чистую, если это потребуется.
А еще, с его помощью, можно сделать &lt;code&gt;Brewfile&lt;/code&gt;, который позволит установить нужные приложения на новом компьютере одной командой.&lt;/p&gt;
&lt;p&gt;В какой-то момент я обратил внимание что у меня не систематизированы установленные приложения: часть установлена через &lt;code&gt;brew&lt;/code&gt;, другая часть руками и мне захотелось навести порядок в этой системе.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Думаю что многим разработчикам, работающим в macOS, знаком &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt;. Изначально он развивался как менеджер пакетов пришедший на замену &lt;code&gt;macports&lt;/code&gt; и &lt;code&gt;fink&lt;/code&gt;, но, со временем, начал обрастать дополнениями которые поддерживаются сообществом.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Homebrew" src="https://blog.rpsl.info/images/ed3f/2015/ed3f2015cc5be55839f62e5524c62214.png"&gt;&lt;/p&gt;
&lt;p&gt;Одно из таких дополнений это &lt;code&gt;Cask&lt;/code&gt;, оно позволят работать с приложениями с закрытым исходным кодом, которые устанавливаются в систему путем перемещения в директорию &lt;code&gt;/Applications&lt;/code&gt;.
&lt;code&gt;Cask&lt;/code&gt; реализует возможность устанавливать и следить за обновлениями таких приложений как:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Google Chrome&lt;/li&gt;
&lt;li&gt;Mozilla Firefox&lt;/li&gt;
&lt;li&gt;1password&lt;/li&gt;
&lt;li&gt;Sublime Text Edit&lt;/li&gt;
&lt;li&gt;&lt;a href="https://formulae.brew.sh/cask/"&gt;И множество других&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Homebrew Cask Install" src="https://blog.rpsl.info/images/6dff/a904/6dffa9044e4f0d50e4ebcb7c3471155f.gif"&gt;&lt;/p&gt;
&lt;p&gt;После установки приложения через &lt;code&gt;Cask&lt;/code&gt; ничего не меняется. Оно будет работать также как работало до этого, будет предлагать обновления через собственные механизмы. Однако, &lt;code&gt;brew&lt;/code&gt; тоже будет отслеживать состояние приложения и обновлять его если выйдет новая версия, &lt;code&gt;brew&lt;/code&gt; создает команды запуска для терминала, если они предусмотрены и сможет удалить приложение под чистую, если это потребуется.
А еще, с его помощью, можно сделать &lt;code&gt;Brewfile&lt;/code&gt;, который позволит установить нужные приложения на новом компьютере одной командой.&lt;/p&gt;
&lt;p&gt;В какой-то момент я обратил внимание что у меня не систематизированы установленные приложения: часть установлена через &lt;code&gt;brew&lt;/code&gt;, другая часть руками и мне захотелось навести порядок в этой системе.&lt;/p&gt;


&lt;h4&gt;Как перенести уже установленные приложения под управление homebrew?&lt;/h4&gt;
&lt;p&gt;Чтобы &lt;code&gt;brew&lt;/code&gt; начал отслеживать приложение оно должно быть установлено через него. План выглядит следующим образом:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Собрать список всех приложений установленных в &lt;code&gt;/Applications&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Произвести поиск в &lt;code&gt;brew&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;При наличии совпадений установить их через &lt;code&gt;homebrew&lt;/code&gt;, удалив или заменив исходное приложение&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Поиск аналогов в Homebrew&lt;/h4&gt;
&lt;p&gt;Для поиска приложений через homebrew я написал shell скрипт, который берет список всех приложений в &lt;code&gt;/Applications&lt;/code&gt; и последовательно делает поиск для каждого из них через &lt;code&gt;brew&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="bash"&gt;#!/bin/bash

FILES=&amp;quot;$(bash &amp;lt;&amp;lt;EOF
ls &amp;quot;/Applications/&amp;quot; | grep '.app' | sed -e &amp;quot;s/\.app//&amp;quot;
EOF
)&amp;quot;

IFS='
'

for line in $FILES; do
    echo &amp;quot;Searching cask for $line&amp;quot;
    brew search --casks &amp;quot;$line&amp;quot;
    sleep 3
    echo &amp;quot;&amp;quot;
done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;В первой секции скрипта мы делаем листинг директории &lt;code&gt;ls "/Applications/"&lt;/code&gt;,  фильтруем строки в которых содержится вхождение &lt;code&gt;grep '.app'&lt;/code&gt;, чтобы не смотреть на директории, и делаем замену подстроки удаляя расширение &lt;code&gt;sed -e "s/\.app//"&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Таким образом в переменную &lt;code&gt;$FILES&lt;/code&gt; у нас запишется список вида&lt;/p&gt;
&lt;pre&gt;&lt;code class="shell"&gt;1Password Angry IP Scanner App Store AppCleaner Atom Bear BetterZip BitBar Docker Dropbox ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Далее нам нужно переопределить переменную &lt;code&gt;$IFS&lt;/code&gt; на символ новой строки, в противном случае наш скрипт будет интерпретировать пробел в название приложения как разделить и мы будем искать в &lt;code&gt;brew&lt;/code&gt; не &lt;code&gt;Google Chrome&lt;/code&gt;, а сначала &lt;code&gt;Google&lt;/code&gt; и затем &lt;code&gt;Chrome&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;$IFS разделитель полей во вводимой строке (IFS -- Input Field Separator)&lt;/p&gt;
&lt;p&gt;По-умолчанию -- пробельный символ (пробел, табуляция и перевод строки), но может быть изменен, например, для разбора строк, в которых отдельные поля разделены запятыми. Обратите внимание: при составлении содержимого переменной $*, Bash использует первый символ из $IFS для разделения аргументов.
&lt;a href="https://www.opennet.ru/docs/RUS/bash_scripting_guide/c3270.html"&gt;Подробнее&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;После этого запускается цикл, в котором для каждой строки с названием нашего приложения будет произведен поиск в &lt;code&gt;brew&lt;/code&gt;. Команда &lt;code&gt;sleep 3&lt;/code&gt; нужна чтобы Github не начинал ругаться что мы делаем слишком много запросов.&lt;/p&gt;
&lt;p&gt;Я запустил этот скрипт, перенаправил вывод в файл и оставил его работать&lt;/p&gt;
&lt;pre&gt;&lt;code class="bash"&gt;./cask-finder.sh &amp;gt; casks.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;Анализ результатов&lt;/h4&gt;
&lt;p&gt;После того как скрипт закончил работать, у нас появился файл &lt;code&gt;casks.txt&lt;/code&gt; с результатами поиска приложений через &lt;code&gt;brew&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Searching cask for 1Password
==&amp;gt; Casks
1password
1password-cli
homebrew/cask-versions/1password-beta

Searching cask for Angry IP Scanner
==&amp;gt; Casks
angry-ip-scanner

Searching cask for App Store
==&amp;gt; Casks
appstore-quickview

Searching cask for AppCleaner
==&amp;gt; Casks
appcleaner

Searching cask for Atom
==&amp;gt; Formulae
atomicparsley
atomist-cli
libatomic_ops
sratom

==&amp;gt; Casks
atom
homebrew/cask-versions/atom-beta

...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Мне показалось что программировать систему которая будет все делать автоматически слишком избыточно, да и она потребует много времени для отладки, поэтому полученные результаты быстрее всего проанализировать руками.&lt;/p&gt;
&lt;p&gt;Я был очень удивлен, результатов оказалось сильно больше чем я ожидал. Примерно 50% установленных у меня приложений имеют копию в &lt;code&gt;brew&lt;/code&gt;. Переустанавливать каждое из них мне не хотелось, поэтому для принятие решение я использовал следующие критерии:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Это приложение мне нужно на всех компьютерах которыми я пользуюсь&lt;/li&gt;
&lt;li&gt;Я пользуюсь этим приложением минимум раз в месяц&lt;/li&gt;
&lt;li&gt;Мне важно чтобы оно обновлялось автоматически и было свежим&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Далее я просто пошел по списку, проверяя информацию о приложение в &lt;code&gt;brew&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~ » brew cask info 1password
1password: 7.2.5 (auto_updates)
https://1password.com/
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/1password.rb
==&amp;gt; Name
1Password
==&amp;gt; Artifacts
1Password 7.app (App)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Например, &lt;code&gt;1password&lt;/code&gt; я не стал подключать к &lt;code&gt;brew&lt;/code&gt;, т.к. в нем лежит более свежая версия чем та которой я пользуюсь. У меня куплена 6 версия, а подписочная модель в 7 версии мне не подходит.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Searching cask for AppCleaner
==&amp;gt; Casks
appcleaner
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Для &lt;code&gt;AppCleaner&lt;/code&gt; у меня была более старая версия чем предлагаемая в &lt;code&gt;brew&lt;/code&gt; и сходились все правила. Поэтому я удалил приложение из &lt;code&gt;/Applications&lt;/code&gt; и переустановил его через &lt;code&gt;brew&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="bash"&gt;cd /Applications
rm -rf ./AppCleaner
brew cask install appcleaner
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Теоретически можно было и не удалять приложение из &lt;code&gt;/Applications&lt;/code&gt;, а использовать ключ &lt;code&gt;--force&lt;/code&gt; при установке через &lt;code&gt;brew&lt;/code&gt;, но такой вариант мне показался менее надеждным, так как могут появиться баги с дублированием приложений.&lt;/p&gt;
&lt;p&gt;При удалении приложения его настройки не удалятся, они хранятся в &lt;code&gt;~/Library/Application\ Support&lt;/code&gt; и будут подхвачены новым приложением.&lt;/p&gt;
&lt;h4&gt;Заключение&lt;/h4&gt;
&lt;p&gt;Весь процесс занял у меня около одного часа времени, но теперь большая часть приложений которые мне нужны будут обновляться автоматически.&lt;/p&gt;
&lt;p&gt;К слову, для удобного обновления &lt;code&gt;brew&lt;/code&gt; я завел себе алиас и добавил его в &lt;code&gt;~/.zshrc&lt;/code&gt; &lt;/p&gt;
&lt;pre&gt;&lt;code class="bash"&gt;alias brew_update=&amp;quot;brew update &amp;amp;&amp;amp; brew upgrade &amp;amp;&amp;amp; brew cask upgrade &amp;amp;&amp;amp; brew cleanup&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;При его использование автоматически выполнятся все команды обновления, а в завершение сработает &lt;code&gt;cleanup&lt;/code&gt;, который удалят старые файлы приложений и скачанные версии. Это позволяет экономить местно на жестком диске.&lt;/p&gt;</content><category term="03"/><category term="mac"/><category term="brew"/></entry><entry><title>MikroTik автоматическое обновление листов</title><link href="https://blog.rpsl.info/2019/03/mikrotik-auto-update-address-list/" rel="alternate"/><published>2019-03-17T23:08:27+03:00</published><updated>2019-03-17T23:08:27+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2019-03-17:/2019/03/mikrotik-auto-update-address-list/</id><summary type="html">&lt;p&gt;В &lt;a href="https://blog.rpsl.info/2019/03/mikrotik-use-vpn/"&gt;прошлой статье&lt;/a&gt; мы разобрали как настроить маршрутизацию трафика через VPN, на основе &lt;code&gt;Address Lists&lt;/code&gt;. В этой статье хочется собрать информацию и способы для автоматического обновления и создания листов. &lt;/p&gt;
&lt;p&gt;Обновление листов представляет из себя выполнение shell команд, которые исполняются на Router OS. Их можно предварительно сгенерировать и выполнить на маршрутизаторе, либо выполнять сразу, в runtime, без создания отдельного файла.&lt;/p&gt;
&lt;h4&gt;Шаблон файла обновления&lt;/h4&gt;
&lt;pre&gt;&lt;code class="routeros"&gt;/ip firewall address-list
remove numbers=[find list=spotify]
add list=spotify address=104.154.127.47
add list=spotify address=78.31.8.0/21
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;В моем случае обновление листа подразумевает удаление всех правил и добавление новых. Необходимости делать точечные изменения у меня не возникало.&lt;/p&gt;
&lt;p&gt;В листе выше, мы удаляем все адреса которые присутствуют в листе &lt;code&gt;spotify&lt;/code&gt; - &lt;code&gt;remove numbers=[find list=spotify]&lt;/code&gt;. 
Затем идут команды добавления новых адресов &lt;code&gt;add list=spotify address=78.31.8.0/21&lt;/code&gt; их можно добавлять сколь угодно много, но большие обработка больших листов будет отнимать ресурсы роутера, поэтому заливать туда полный список от РКН не рекомендую.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;В &lt;a href="https://blog.rpsl.info/2019/03/mikrotik-use-vpn/"&gt;прошлой статье&lt;/a&gt; мы разобрали как настроить маршрутизацию трафика через VPN, на основе &lt;code&gt;Address Lists&lt;/code&gt;. В этой статье хочется собрать информацию и способы для автоматического обновления и создания листов. &lt;/p&gt;
&lt;p&gt;Обновление листов представляет из себя выполнение shell команд, которые исполняются на Router OS. Их можно предварительно сгенерировать и выполнить на маршрутизаторе, либо выполнять сразу, в runtime, без создания отдельного файла.&lt;/p&gt;
&lt;h4&gt;Шаблон файла обновления&lt;/h4&gt;
&lt;pre&gt;&lt;code class="routeros"&gt;/ip firewall address-list
remove numbers=[find list=spotify]
add list=spotify address=104.154.127.47
add list=spotify address=78.31.8.0/21
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;В моем случае обновление листа подразумевает удаление всех правил и добавление новых. Необходимости делать точечные изменения у меня не возникало.&lt;/p&gt;
&lt;p&gt;В листе выше, мы удаляем все адреса которые присутствуют в листе &lt;code&gt;spotify&lt;/code&gt; - &lt;code&gt;remove numbers=[find list=spotify]&lt;/code&gt;. 
Затем идут команды добавления новых адресов &lt;code&gt;add list=spotify address=78.31.8.0/21&lt;/code&gt; их можно добавлять сколь угодно много, но большие обработка больших листов будет отнимать ресурсы роутера, поэтому заливать туда полный список от РКН не рекомендую.&lt;/p&gt;


&lt;h4&gt;Обновление из сгенерированного файла&lt;/h4&gt;
&lt;p&gt;Допустим у нас есть сформированный по шаблону файл, который мы генерируем в интернете: на гитхабе или на личном сервере. Для импорта нужно создать скрипт в RouterOS который скачает и выполнит и наш файл.&lt;/p&gt;
&lt;p&gt;Для добавления через консоль:&lt;/p&gt;
&lt;pre&gt;&lt;code class="routeros"&gt;/system script
add dont-require-permissions=no name=sp_import owner=owner policy=\
    read,write,test source=&amp;quot;%тут листинг скрипта%&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Мы добавили скрипт, с минимальными правами &lt;code&gt;read,write,test&lt;/code&gt;, но набор этих прав позволит читать и записывать настройки на роутере, кроме тех которые отвечают за пользователей, поэтому нужно быть уверенным кто контролирует скрипт который будет исполнен на роутере.
&lt;em&gt;&lt;a href="https://wiki.mikrotik.com/wiki/Manual:Router_AAA#Properties"&gt;Подробнее о правах доступа&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Сам скрипт:&lt;/p&gt;
&lt;pre&gt;&lt;code class="routeros"&gt;/tool fetch url=&amp;quot;https://127.0.0.1/mikrotik_spotify_list.txt&amp;quot; dst-path=spotify.txt
:import spotify.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;В нем мы получаем с удаленного сервера сформированный листинг (см. Шаблон файла обновления), сохраняем его в файл &lt;code&gt;spotify.txt&lt;/code&gt; и выполняем этот файл.&lt;/p&gt;
&lt;p&gt;Почти готово, осталось автоматизировать.&lt;/p&gt;
&lt;pre&gt;&lt;code class="routeros"&gt;/system scheduler
add interval=2h name=update_spotify_list on-event=&amp;quot;/system script run sp_import&amp;quot; \
policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
start-date=jan/01/2019 start-time=09:00:00
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Мы добавили в планировщик задание &lt;code&gt;name=update_spotify_list&lt;/code&gt; на выполнение каждые два часа &lt;code&gt;interval=2h&lt;/code&gt;. С &lt;code&gt;policy&lt;/code&gt; тут несколько сложнее, если из планировщика выполняется другой скрипт, то нужно предоставить все права. Теоретически можно было весь листинг скрипта положить в планировщик и ограничить права, но я предпочитаю когда скрипты лежат в отдельных файлах.&lt;/p&gt;
&lt;p&gt;Итак. Мы создали скрипт, который обновляет список адресов в файрволе. Создали скрипт который скачивает этот список и добавили его в планировщик. &lt;/p&gt;
&lt;h4&gt;Обновление листа без промежуточных файлов&lt;/h4&gt;
&lt;p&gt;В вышеописанном решение все хорошо, за исключением того, что требуется где-то хостить наш список и формировать его. Как сделать тоже самое на роутере?&lt;/p&gt;
&lt;pre&gt;&lt;code class="routeros"&gt;:local ListName &amp;quot;spotify&amp;quot;
:local ListIps {&amp;quot;104.154.127.47&amp;quot;;&amp;quot;78.31.8.0/21&amp;quot;}

/ip firewall address-list remove numbers=[find list=$ListName]

:foreach v in $ListIps do={
  /ip firewall address-list add address=$v list=$ListName
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Делает все тоже самое. &lt;a href="https://wiki.mikrotik.com/wiki/Manual:Scripting"&gt;Документация по MikroTik Scripting&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Обновление листа через определение ip доменов&lt;/h4&gt;
&lt;p&gt;Пока искал ссылку на документацию по MikroTik Scripting, наткнулся на статью &lt;a href="https://habr.com/en/post/242143/"&gt;Писать скрипты для Mikrotik RouterOS — это просто&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;В ней приведен листинг скрипта, который может делать определение ip адресов доменов и формировать список из них. Весьма удобно, так как иногда бывает что сайты часто меняют свои адреса в попытках борьбы с блокировками.&lt;/p&gt;
&lt;p&gt;Для истории приведу листинг скрипта ниже, а его полный разбор с комментариями доступен в оригинальной статье.&lt;/p&gt;
&lt;p&gt;&lt;details&gt;
&lt;summary&gt;Листинг приведенный ниже оставлен для истории. Актуальный находится ниже.&lt;/summary&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="routeros"&gt;:local DNSList {&amp;quot;example.com&amp;quot;;&amp;quot;non-exist.domain.net&amp;quot;;&amp;quot;server.local&amp;quot;;&amp;quot;hostname&amp;quot;}
:local ListName &amp;quot;MyList&amp;quot;
:local DNSServers ( [ip dns get dynamic-servers], [ip dns get servers ], 8.8.8.8 )
:foreach addr in $DNSList do={
     :foreach DNSServer in $DNSServers do={
          :do {:resolve server=$DNSServer $addr} on-error={:log debug (&amp;quot;failed to resolve $addr on $DNSServer&amp;quot;)}
     }
}
/ip firewall address-list remove [find where list~$ListName]
/ip dns cache all
:foreach i in=[find type=&amp;quot;A&amp;quot;] do={
    :local bNew true
    :local cacheName [get $i name]
    :local match false
    :foreach addr in=$DNSList do={
       :if (:typeof [:find $cacheName $addr] &amp;gt;= 0) do={
           :set $match true
       }
    }
    :if ( $match ) do={
        :local tmpAddress [/ip dns cache get $i address]
        :if ( [/ip firewall address-list find ] = &amp;quot;&amp;quot;) do={
            :log debug (&amp;quot;added entry: $[/ip dns cache get $i name] IP $tmpAddress&amp;quot;)
            /ip firewall address-list add address=$tmpAddress list=$ListName comment=$cacheName
        } else={
            :foreach j in=[/ip firewall address-list find ] do={
                :if ( [/ip firewall address-list get $j address] = $tmpAddress ) do={
                    :set bNew false
                }
            }
            :if ( $bNew ) do={
                :log debug (&amp;quot;added entry: $[/ip dns cache get $i name] IP $tmpAddress&amp;quot;)
                /ip firewall address-list add address=$tmpAddress list=$ListName comment=$cacheName
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/details&gt;&lt;/p&gt;
&lt;h4&gt;Update 03.08.2020&lt;/h4&gt;
&lt;p&gt;Скрипт приведенный выше, в какой-то момент перестал работать. Я не обратил внимание когда это произошло, но, кажется, после того как я перешел на dns-over-https.&lt;/p&gt;
&lt;p&gt;Во время дебага и в попытках локализовать проблему, я переписал скрипт.&lt;/p&gt;
&lt;pre&gt;&lt;code class="routeros"&gt;:local hostnames {&amp;quot;domain1.ru&amp;quot;;&amp;quot;domain2.com&amp;quot;;&amp;quot;domain3.com&amp;quot;}
:local listname &amp;quot;vpn&amp;quot;
:local ips

/ip firewall address-list remove [find where list=$listname]

:foreach hostname in $hostnames do={
    :do {:set ips [:resolve $hostname]} on-error={:log debug (&amp;quot;failed to resolve $hostname&amp;quot;)}

    /ip firewall address-list add address=$ips list=$listname comment=$hostname
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Получилось сильно сократить код сохранив всю функциональность:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В списке &lt;code&gt;hostnames&lt;/code&gt; указываем какие домены нужно резолвить&lt;/li&gt;
&lt;li&gt;В переменную &lt;code&gt;listname&lt;/code&gt; записываем название для нашего списка, главное чтобы оно совпадало с &lt;a href="https://blog.rpsl.info/2019/03/mikrotik-use-vpn/"&gt;правилами маршрутизации&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Обратите внимание что уровень ошибок обозначен как &lt;code&gt;debug&lt;/code&gt;, это значит что он не будет сообщать обо всех ошибках в общий лог. Если необходимо, то нужно заменить его, например, на &lt;code&gt;info&lt;/code&gt;. &lt;a href="https://wiki.mikrotik.com/wiki/Manual:System/Log#Topics"&gt;Смотрите документацию&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</content><category term="03"/><category term="mikrotik"/><category term="network"/></entry><entry><title>Настройка маршрутизации трафика через VPN в RouterOS</title><link href="https://blog.rpsl.info/2019/03/mikrotik-use-vpn/" rel="alternate"/><published>2019-03-08T18:53:24+03:00</published><updated>2019-03-08T18:53:24+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2019-03-08:/2019/03/mikrotik-use-vpn/</id><summary type="html">&lt;p&gt;В качестве домашней точки доступа я использую маршрутизатор &lt;a href="https://mikrotik.com/product/hap_ac2"&gt;MikroTik hAP ac2&lt;/a&gt;. Я выбрал его из-за обилия настроек и возможности реализации таких сценариев которые недоступны его конкрурентам. &lt;/p&gt;
&lt;p&gt;&lt;img alt="mikrotik hap ac2" src="https://blog.rpsl.info/images/52e5/f921/52e5f921d308ffdacf0fb201e3c86258.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Один из таких сценариев - настройка автоматического соединение с некоторыми хостами через VPN.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Зачем это может быть нужно:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Сайт недоступен из интернета. Например, он находится в корпоративной сети&lt;/li&gt;
&lt;li&gt;Вы не хотите чтобы провайдер знал что вы посещаете данный сайт&lt;/li&gt;
&lt;li&gt;У сайта есть ограничения на доступ из вашей локации. Spotify или Telegram&lt;/li&gt;
&lt;/ul&gt;
</summary><content type="html">&lt;p&gt;В качестве домашней точки доступа я использую маршрутизатор &lt;a href="https://mikrotik.com/product/hap_ac2"&gt;MikroTik hAP ac2&lt;/a&gt;. Я выбрал его из-за обилия настроек и возможности реализации таких сценариев которые недоступны его конкрурентам. &lt;/p&gt;
&lt;p&gt;&lt;img alt="mikrotik hap ac2" src="https://blog.rpsl.info/images/52e5/f921/52e5f921d308ffdacf0fb201e3c86258.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Один из таких сценариев - настройка автоматического соединение с некоторыми хостами через VPN.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Зачем это может быть нужно:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Сайт недоступен из интернета. Например, он находится в корпоративной сети&lt;/li&gt;
&lt;li&gt;Вы не хотите чтобы провайдер знал что вы посещаете данный сайт&lt;/li&gt;
&lt;li&gt;У сайта есть ограничения на доступ из вашей локации. Spotify или Telegram&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Итак, предположим что у вас уже есть настроенный роутер, вы приобрели доступ к VPN и настроили подключение к нему.&lt;/p&gt;
&lt;p&gt;В моем случае используется сервер на &lt;a href="https://m.do.co/c/47584abe7c15"&gt;Digital Ocean&lt;/a&gt;. Для поднятия собственного vpn сервера можно использовать &lt;a href="https://www.digitalocean.com/community/projects/digitalocean-vpn-setup"&gt;установку в один клик&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;img alt="worked vpn on mikrotik" src="https://blog.rpsl.info/images/b8c1/4b98/b8c14b9817eb39ed70c9824f3223b24b.png"&gt;&lt;/p&gt;
&lt;p&gt;После настройки соединения с VPN, этот маршрут станет доступным на роутере, но трафик не будет направлен через данный интерфейс. 
Если мы хотим сделать чтобы весь трафик направлялся через VPN, для этого достаточно сделать интерфейс VPN маршрутом по умолчанию, предварительно удалив стандартный.&lt;/p&gt;
&lt;pre&gt;&lt;code class="routeros"&gt;/ip firewall nat
add action=masquerade chain=srcnat out-interface=vpn-digitalocean
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Второй вариант, как я уже писал выше, это направление через VPN трафика только до определенных заранее хостов. &lt;/p&gt;
&lt;p&gt;Для этого нам необходимо:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Создать в firewall лист адресов, трафик до которых будет маршрутизировать через VPN&lt;/li&gt;
&lt;li&gt;Добавить правило для маркировки нашего трафика определенной меткой&lt;/li&gt;
&lt;li&gt;Создать правило маршрутизации, чтобы пакеты помеченные меткой направлялись через интерфейс VPN&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Добавляем лист адресов в firewall&lt;/h4&gt;
&lt;pre&gt;&lt;code class="routeros"&gt;/ip firewall address-list
add address=104.154.127.47 list=spotify
add address=78.31.8.0/21 list=spotify
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Теперь у нас появился лист адресов, который мы назвали &lt;code&gt;spotify&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="spotify list" src="https://blog.rpsl.info/images/b8e5/e028/b8e5e0281c9fb2e1076a73e4ab970663.png"&gt;&lt;/p&gt;
&lt;h4&gt;Создаём правило маркировки трафика&lt;/h4&gt;
&lt;pre&gt;&lt;code class="routeros"&gt;/ip firewall mangle
add action=mark-routing \
chain=prerouting \
comment=&amp;quot;Mark Spotify&amp;quot; \
dst-address-list=spotify \
new-routing-mark=mark_vpn \
passthrough=no \
src-address=10.0.0.0/24
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Мы создали правило, в котором определяем все обращения к хостам из списка &lt;code&gt;spotify&lt;/code&gt; (&lt;code&gt;dst-address-list=spotify&lt;/code&gt;) и довляем к ним метку &lt;code&gt;mark_vpn&lt;/code&gt; (&lt;code&gt;new-routing-mark=mark_vpn&lt;/code&gt;). &lt;code&gt;src-address=10.0.0.0/24&lt;/code&gt; указан для маршрутизации обращений из нашей локальной сети, возможно у вас другие диапазоны, например &lt;code&gt;192.168.0.0/24&lt;/code&gt;, тогда нужно исправить.&lt;/p&gt;
&lt;p&gt;Параметр &lt;code&gt;passthrough=no&lt;/code&gt; нужен для уменьшения потребляемых ресурсов при обработке трафика, &lt;a href="https://wiki.mikrotik.com/wiki/Manual:IP/Firewall/Mangle#Marking_packets"&gt;подробнее в документации&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Для названия метки я выбрал &lt;code&gt;mark_vpn&lt;/code&gt;, это нужно для универсальности. В дальнейшем, когда появятся другие листы адресов, для них не придется создавать отдельные правила.&lt;/p&gt;
&lt;h4&gt;Настраиваем маршрутизацию маркированных пакетов&lt;/h4&gt;
&lt;pre&gt;&lt;code class="routeros"&gt;/ip firewall nat
add action=masquerade chain=srcnat out-interface=vpn-digitalocean routing-mark=mark_vpn
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Мы создали правило, которое аналогичному тому что было в "первом сценарии", за исключением того что оно обрабатывает только пакеты которые помечены специальной меткой &lt;code&gt;routing-mark=mark_vpn&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;Дополнительная информация&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.rpsl.info/2019/03/mikrotik-auto-update-address-list/"&gt;MikroTik автоматическое обновление листов&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="03"/><category term="mikrotik"/><category term="vpn"/><category term="network"/></entry><entry><title>Youcast. Просмотр youtube через подкасты</title><link href="https://blog.rpsl.info/2019/02/youcast-show-youtube-as-podcast/" rel="alternate"/><published>2019-02-26T19:18:10+03:00</published><updated>2019-02-26T19:18:10+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2019-02-26:/2019/02/youcast-show-youtube-as-podcast/</id><summary type="html">&lt;p&gt;Хочу рассказать вам еще об одном стартапе который я пилю на досуге. "Пилю" - это, конечно, громко сказано, так как проект был запущен три года назад и с тех пор почти не развивался, но обо всем по порядку.&lt;/p&gt;
&lt;p&gt;&lt;img alt="https://blog.rpsl.info/images/ca09/4191/ca09419178564de38c998d25f99247dd.jpg" src="https://blog.rpsl.info/images/ca09/4191/ca09419178564de38c998d25f99247dd.jpg"&gt;&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Хочу рассказать вам еще об одном стартапе который я пилю на досуге. "Пилю" - это, конечно, громко сказано, так как проект был запущен три года назад и с тех пор почти не развивался, но обо всем по порядку.&lt;/p&gt;
&lt;p&gt;&lt;img alt="https://blog.rpsl.info/images/ca09/4191/ca09419178564de38c998d25f99247dd.jpg" src="https://blog.rpsl.info/images/ca09/4191/ca09419178564de38c998d25f99247dd.jpg"&gt;&lt;/p&gt;


&lt;h3&gt;Причины:&lt;/h3&gt;
&lt;p&gt;Лет пять назад, когда в наш сегмент ютуба пришла монетизация и появился качественный контент, появились каналы, за которыми я стал следить на регулярной основе. Я размышлял над проблемами шаблонов использования и заметил, что часть каналов которые мне интересны я игнорирую почти постоянно. Дело в том, что формат некоторых шоу мне не подходил.  У меня не получалось смотреть эти видео сидя перед монитором.&lt;/p&gt;
&lt;p&gt;Поэтому и появилась идея что необходимо сделать инструмент, который будет конвертировать ютуб канал в подкаст ленту, которая, в свою очередь, будет скачиваться телефоном и тогда у меня будет возможность смотреть эти видео в дороге или в любой другой ситуации.&lt;/p&gt;
&lt;h3&gt;Первая версия:&lt;/h3&gt;
&lt;p&gt;Первая версия была сделана на коленке за один вечер. У меня был &lt;code&gt;yaml&lt;/code&gt; файл через который я добавлял каналы, на сервере крутился &lt;code&gt;cron&lt;/code&gt; который через &lt;code&gt;youtube api&lt;/code&gt; следил за обновлениями данных каналов и формировал &lt;code&gt;xml&lt;/code&gt; ленту подкаста.&lt;/p&gt;
&lt;p&gt;Ссылки на видео проксировались через другой микросервис, который на лету выкачивал видео с ютуба и отдавал в &lt;code&gt;stdout&lt;/code&gt;. Точно уже не вспомню, но, кажется, все это дело крутилось &lt;code&gt;bananapi&lt;/code&gt; (из которой я когда-то &lt;a href="https://blog.rpsl.info/2017/03/alarm-from-raspberry-pi/"&gt;делал онлайн радио будильник&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Сервис оказался весьма удачным и я начал уделять время тем каналам которые раньше игнорировал.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Сама механика подкастов сильно к этому располагала: настроить подкаст (канал) нужно один раз и он автоматически доставляется в телефон где видео всегда под рукой.&lt;/p&gt;
&lt;p&gt;Сейчас этим трудно кого-нибудь удивить, но на дворе был примерно 2014 год, интернет в Московском метро только появлялся, а тарифы LTE были достаточно скромными.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Вторая версия:&lt;/h3&gt;
&lt;p&gt;Около двух лет я пользовался этим скриптом написанным на коленке, но в голове варилась мысль о том что нужно сделать для него веб-интерфейс и дать возможность использовать его другим людям.&lt;/p&gt;
&lt;p&gt;Вторая версия разрабатывалась не сильно дольше первой. В качестве фреймворка был взят &lt;code&gt;Laravel&lt;/code&gt; и за неделю "кодинга по вечерам" я набросал основные пользовательские сценарии:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Регистрация по инвайтам&lt;/li&gt;
&lt;li&gt;Добавление каналов&lt;/li&gt;
&lt;li&gt;Привязка социальных сетей для авторизации&lt;/li&gt;
&lt;li&gt;Разные способы отправить ссылку на подкаст в телефон. Ссылка на почту, показ QR кода, ссылка в формате iTunes&lt;/li&gt;
&lt;li&gt;Механизмы ограничений для видео. Я не хотел чтобы летсплейщики гоняли через меня 9 часовые записи стримов в 4к&lt;/li&gt;
&lt;li&gt;Различные "сервисные" механизмы для сбора статистики и управления контентом&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;При этом я отказался от механики "проксирования" видео и теперь начал их выкачивать автоматически. В новой версии все видео, если они не попадают под ограничения, скачиваются на сервер и раздаются с него.&lt;/p&gt;
&lt;p&gt;Это позволило реализовать такие сценарии как фильтрация видео по плейлистам. Пользователь может подписаться на канал и потом выбрать за какими плейлистами следить, при этом изменения в наборе плейлистов происходят "на лету" и нет необходимости удалять или скачивать видео.&lt;/p&gt;
&lt;p&gt;Это позволило экономить на трафике и оптимизировать хранение видео. Если 10 пользователей подписаны на один канал, то видео мне нужно выкачать только 1 раз.&lt;/p&gt;
&lt;p&gt;Но, в свою очередь, это добавило проблему с тем что видео нужно хранить и это не дешевое удовольствие. В сервисе есть механизмы которые позволяют работать с различными облачными хранилищами, но, тем не менее, речь идет о сотнях гигабайт.&lt;/p&gt;
&lt;p&gt;Дополнительно были реализованы различные механизмы для самодиагностики сервиса. Так как сервис представляет из себя слепок данных из другого сервиса, то это несет в себе все риски связанные с денормализацией данных. Чтобы не разбираться с этим вручную я написал наборы скриптов которые запускаются по крону и проверяют что все связи соответсвуют тому как и должно быть:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Пользователи подписаны на каналы&lt;/li&gt;
&lt;li&gt;У каналов есть более одного подписчика&lt;/li&gt;
&lt;li&gt;Видео скачаны, имеют верные hash суммы во всех хранилищах&lt;/li&gt;
&lt;li&gt;На ютубе не появилось видео в лучшем качестве&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;И тому подобные проверки, которые сводят поддержку сервиса к минимуму.&lt;/p&gt;
&lt;p&gt;В качестве бета-пользователей я раздавал инвайты на Лепре (на тот момент она уже умирала, но еще жизнь в ней еще была) и приглашал знакомых, в обмен просил фидбэк и идеи. Так появилось примерно сотня адептов, которые помогли отловить множество багов (вы знали что на ютубе есть полностью платные каналы?) и сгенерировали бэклог на месяцы разработки.&lt;/p&gt;
&lt;h3&gt;Монетизация&lt;/h3&gt;
&lt;p&gt;Одним из мотиваторов разработки второй версии была идея о монетизации проекта. Хотя я изначально понимал что делать это будет сложно т.к. модель выглядела очень кривой.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;N каналов бесплатно - расширение за деньги. Модель ломается тем что будут регать новые аккаунты&lt;/li&gt;
&lt;li&gt;Подписочная модель, с тарифами на объем каналов. Модель ломается т.к. рынок холодный и привлекать новых адептов сложно. Плюс вся схема выглядит очень сложной, т.к. нужно руками добавлять каналы, потом настраивать подкасты, не для простого обывателя&lt;/li&gt;
&lt;li&gt;Ограничивать объем видео, например сколько угодно каналов, но видео длиннее 10 минут за подписку. Модель ломается из-за того что вне зависимости от подписки видео нужно скачивать, хранить и раздавать клиентам&lt;/li&gt;
&lt;li&gt;А еще, делать монетизацию сервиса который может быть закрыт по первому требованию Google - выглядит глупой идеей&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Стагнация&lt;/h3&gt;
&lt;p&gt;Запуск сервиса позволил закрыть те проблемы которые были катализатором для его разработки. Поэтому дальнейшие доработки из категории "важно и срочно" плавно перекочевали в категорию "хорошо бы когда-нибудь". Мне не удалось найти единомышлеников которые захотели бы войти в проект и тратить свое время на доработки, а понимание того что в любой момент это может быть закрыто по просьбе владельцев контента убивают все остатки морали.&lt;/p&gt;
&lt;p&gt;Таким образом сервис живет в состояние "заморозки" и ждет своего часа. Кажется что ютуб уже тестирует аналогичную фичу в составе Youtube Premium и как только он её реализует можно будет спокойно остановить сервера.&lt;/p&gt;</content><category term="02"/><category term="youtube"/><category term="startup"/></entry><entry><title>Идея стартапа "Рассказчик"</title><link href="https://blog.rpsl.info/2018/04/startup-story-combinator/" rel="alternate"/><published>2018-04-28T19:32:07+03:00</published><updated>2018-04-28T19:32:07+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2018-04-28:/2018/04/startup-story-combinator/</id><content type="html">&lt;p&gt;Для начала чуть-чуть контекста. Я смотрю достаточно много сериалов. Я ознакамливаюсь с большинством новинок которые обладают вменяемым описанием. К сожалению большинство из них я бросаю после нескольких серий, другие по инерции досматриваются до конца сезона на быстрой перемотке. Быстрая перемотка для меня это не ускоренное воспроизведение, а просмотр сериала с телефона, когда можно в одно касание перемотать серию на 10-20 секунд вперед. Таким образом за 25 минут в метро я умудряюсь посмотреть часовую серию проходного шоу.&lt;/p&gt;
&lt;p&gt;И вот уже много лет я мечтаю о сервисе который бы позволил не использовать быструю перемотку, а сразу собирать серию из интересных мне сюжетных линий. Самостоятельно такой проект я никак не потяну, поэтому максимум что могу сделать рассказать тут об идее. Хотя, велика вероятность, что когда-нибудь он появится, а может и уже где-нибудь существует.&lt;/p&gt;
&lt;p&gt;&lt;img alt="картинка для привлечения внимания" src="https://blog.rpsl.info/images/34d9/506a/34d9506a0171cc32d085584813923127.png"&gt;&lt;/p&gt;
&lt;p&gt;В моем видение это должен быть проект с генерируемым пользовательским контентом. На рисунке я постарался схематически изобразить как он должен выглядеть для пользователя, но внутренняя механика должна быть схожа с какой-нибудь википедией. У всех серий есть хронометраж и мы точно знаем что он не меняется, а построение большинства серий сводится к тому что это последовательный набор сцен. Значит каждую серию можно нарезать на сцены и далее эти сцены помечать различными "сюжетными линиями". Далее любой человек может самостоятельно добавлять различные сюжетные линии и голосовать за уже созданные, если хочет, разумеется. А если не хочет, то может просто выбрать популярные сюжетные линии прочитав их описание.&lt;/p&gt;
&lt;p&gt;Представьте как бы было здорово смотреть сериалы без всех этих нудных разговоров по 5 минут. Вот если из "The Walking Dead" выкинуть всю ересь про их личные взаимоотношения и получить только историю про выживание и зомби. Если из первых сезонов "Homeland" выкинуть большую часть страданий про семью Броуди, оставив только ключевые моменты и расследование Кэрри. Ну, или если вы страдает острой формой мазохизма, то наоборот собрать себе из ходячих мертвецов только сюжетную линию их личных взаимоотношений.&lt;/p&gt;
&lt;p&gt;Все зависит от вашей фантазии.&lt;/p&gt;</content><category term="04"/><category term="startup"/><category term="video"/><category term="shows"/></entry><entry><title>AdBlock блокировка лидогенераторов</title><link href="https://blog.rpsl.info/2018/02/adblock-leadgenerator-list/" rel="alternate"/><published>2018-02-24T20:15:05+03:00</published><updated>2018-02-24T20:15:05+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2018-02-24:/2018/02/adblock-leadgenerator-list/</id><content type="html">&lt;p&gt;Уже полтора года я собираю лист фильтров для AdBlock который блокирует виджеты лидогенераторы. Это та навязчивая херня которая издает разные звуки, мигает на половину страницы и предлагает оставить вам свой номер для обратного звонка от сейлов сайта.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Mega shit widget" src="https://blog.rpsl.info/images/fadd/2661/fadd2661c628d0eb67ab1b3fde447dd7.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Rpsl/adblock-leadgenerator-list"&gt;Код лежит на гитхабе&lt;/a&gt;, можно легко контрибьютить. Я добавляю в него только те системы которые встречаю самостоятельно и которые не являются разработкой конкретного сайта, т.к. гоняться за последними жизни не хватит.&lt;/p&gt;
&lt;p&gt;Для подписки можно нажать на &lt;a href="abp:subscribe?location=https%3A%2F%2Fraw.githubusercontent.com%2FRpsl%2Fadblock-leadgenerator-list%2Fmaster%2Flist%2Flist.txt&amp;amp;amp;title=Adblock%20Leadgenerator%20list"&gt;эту ссылку&lt;/a&gt;, либо добавить вручную:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;https://raw.githubusercontent.com/Rpsl/adblock-leadgenerator-list/master/list/list.txt
&lt;/code&gt;&lt;/pre&gt;</content><category term="02"/><category term="adblock"/></entry><entry><title>Борьба с телефонным спамом</title><link href="https://blog.rpsl.info/2018/02/anti-phone-spam/" rel="alternate"/><published>2018-02-24T16:07:33+03:00</published><updated>2018-02-24T16:07:33+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2018-02-24:/2018/02/anti-phone-spam/</id><summary type="html">&lt;p&gt;Свой первый телефонный номер я приобрел примерно в 2002 году, может раньше, но точно не позже. Тогда Мегафон только появился на рынке и заходил он сразу с козырей предлагая тариф "безлимит за $25". Номер я купил в ближайшей палатке и пользовался им примерно до 2012 года. Примерно в 2012 году, когда начали появляться новые форматы сим карт я с горечью осознал, что номер зарегестрирован на незнакомого мне человека и переоформить на себя его уже не получится. Я реально сделал очень много попыток, пытался договориться с сотрудниками и знакомыми которые имеют отношение к Мегафону, но все разводили руками. В какой-то момент я даже рассматривал вариант устройства на работу в салон связи, чтобы получить доступ к исправлению информации и уволиться, но там не сразу эти доступы давали, и я решил забить.&lt;/p&gt;
&lt;p&gt;&lt;img alt="spam 80 lvl" src="https://blog.rpsl.info/images/cf12/fcc0/cf12fcc04f4649b9f02d64d4b596ef81.gif"&gt;&lt;/p&gt;
&lt;p&gt;В итоге пришлось оформлять новый контракт, т.к. старая сим карта не подходила к новым телефонам, да и выглядела так что вот-вот развалится. Поэтому в момент покупки iphone 5 я купил новый номер. Старый отключать не стал и поддерживал его в живом состояние еще несколько лет, чтобы убедиться что звонки/смс/оповещения на него больше не приходят. В какой-то момент я отпустил его, да и к тому времени я им уже не пользовался.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Свой первый телефонный номер я приобрел примерно в 2002 году, может раньше, но точно не позже. Тогда Мегафон только появился на рынке и заходил он сразу с козырей предлагая тариф "безлимит за $25". Номер я купил в ближайшей палатке и пользовался им примерно до 2012 года. Примерно в 2012 году, когда начали появляться новые форматы сим карт я с горечью осознал, что номер зарегестрирован на незнакомого мне человека и переоформить на себя его уже не получится. Я реально сделал очень много попыток, пытался договориться с сотрудниками и знакомыми которые имеют отношение к Мегафону, но все разводили руками. В какой-то момент я даже рассматривал вариант устройства на работу в салон связи, чтобы получить доступ к исправлению информации и уволиться, но там не сразу эти доступы давали, и я решил забить.&lt;/p&gt;
&lt;p&gt;&lt;img alt="spam 80 lvl" src="https://blog.rpsl.info/images/cf12/fcc0/cf12fcc04f4649b9f02d64d4b596ef81.gif"&gt;&lt;/p&gt;
&lt;p&gt;В итоге пришлось оформлять новый контракт, т.к. старая сим карта не подходила к новым телефонам, да и выглядела так что вот-вот развалится. Поэтому в момент покупки iphone 5 я купил новый номер. Старый отключать не стал и поддерживал его в живом состояние еще несколько лет, чтобы убедиться что звонки/смс/оповещения на него больше не приходят. В какой-то момент я отпустил его, да и к тому времени я им уже не пользовался.&lt;/p&gt;


&lt;p&gt;Если владельцем первого номера был исключительно я, то к моменту покупки второго номера система изменилась и номера стали ходить по кругу, то есть у него были другие владельцы до меня. Благодаря этому я словил много забавных ситуаций, когда робот при звонке в банк рассказывал мне о балансе других людей, а на новый год я получал поздравления от разных людей.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Алло.&lt;/li&gt;
&lt;li&gt;Денис Павлович, все собрались, только вас ждем.&lt;/li&gt;
&lt;li&gt;Хорошо, начинайте.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Не знаю как там сложилась судьба у прошлого владельца номера, но году в 2015 мне периодически начали названивать различные банки с просьбой оплатить кредиты которые он у них брал. Первое время это было весьма культурно, мне звонили вежливые люди, интересовались как дела, я им рассказывал что они ошиблись номером, они извинялись и пропадали на несколько кварталов. Судя по всему эти кредиты перепродавались различным коллекторским агентствам погружаясь на самое дно.&lt;/p&gt;
&lt;p&gt;Таким образом к лету 2017 года я стал получать звонки и смс от всевозможных неадекватов, которые орали, хамили, не хотели ничего слушать, а для оформления отказа предлагали пройти 10 кругов ада и заполнения каких-то форм на их сайтах чтобы они перестали мне звонить. Охереть нежданчик, сходить, передать им тонну приватной информации, чтобы они тебе не звонили.&lt;/p&gt;
&lt;p&gt;В итоге я начал каждый раз вносить их номера в черный список и мне в голову пришла идея что хорошо бы сделать приложение, которое будет собирать общую базу данных для блокировки звонков и занесения номеров в черный список. Начав его проектировать я все же решил ознакомиться с тем что уже есть на рынке и, как водится, все уже давно сделали.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://itunes.apple.com/ru/app/%D0%B0%D0%BD%D1%82%D0%B8%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%82%D0%BE%D1%80-%D1%80%D0%BE%D1%81%D1%81%D0%B8%D1%8F/id1149335079?mt=8"&gt;&lt;img alt="АнтиКоллектор" src="https://blog.rpsl.info/images/0021/fd92/0021fd92768c6bb17b4e9d9e19d04362.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;После установки, оно начало отсекать все звонки и теперь иногда я получаю уведомления о том что кто-то не смог мне дозвониться.&lt;/p&gt;
&lt;p&gt;Короче, рекомендую. И нет, это не реклама.&lt;/p&gt;
&lt;p&gt;К слову, пока писал пост, вспомнил еще несколько развлечений, которые пропали из моей жизни после установки этого приложения. Мне перестали звонить продавцы билетов на различные мероприятия, дискотека 90х и прочее дно. Раньше я всегда развлекал себя оформлением у них заказов.
Тут главным было сделать серьезный голос и вести разговор в таком стиле:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Ага, ага, что за мероприятие?&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;40 билетов сможете сделать, я как раз искал где корпоратив провести. Ага, отлично, привозите завтра, в Мытищи, ул.Мира, д.7&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Адрес конечно от балды, но обязательно куда-нибудь подальше, пусть везут 40 билетов. Если ведутся сильно и говорят что они на месте, то сообщал что отъехал по делам и пусть привезут завтра.&lt;/p&gt;
&lt;p&gt;Жестко конечно, но пусть страдают.&lt;/p&gt;
&lt;p&gt;А еще раньше, когда Яндекс.Такси только появился, а конкурентов у него еще не было, то на подобный спам от таксопарков я всегда заказывал микроавтобус в Зеленоград или Железнодорожный. После того как они понимали что заказа не будет, диспетчер кричал в трубку и обещал добавить меня в их черный список. Лол, я этого и добавился.&lt;/p&gt;</content><category term="02"/><category term="phone"/><category term="sms"/><category term="ios"/><category term="apps"/></entry><entry><title>macOS: Предотвращение оглушения</title><link href="https://blog.rpsl.info/2018/02/macos-prevention-of-lound-sound/" rel="alternate"/><published>2018-02-04T18:47:26+03:00</published><updated>2018-02-04T18:47:26+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2018-02-04:/2018/02/macos-prevention-of-lound-sound/</id><content type="html">&lt;p&gt;За компьютером я сижу в наушниках. Наушники подключены к внешней звуковой карте "&lt;a href="http://ru.creative.com/p/sound-blaster/sound-blaster-omni-surround-5-1"&gt;Sound Blaster Omni&lt;/a&gt;" и в этом конфиге громкость наушников в 20% является достаточной, а громкость выше 40% процентов уже слишком громкой.&lt;/p&gt;
&lt;p&gt;&lt;img alt="когда забыл убавить громкость" src="https://blog.rpsl.info/images/8c4b/7c82/8c4b7c821b01dc25da45b0a410d958ea.jpeg"&gt;&lt;/p&gt;
&lt;p&gt;Изначально я решил этот вопрос простым скриптом &lt;code&gt;login.sh&lt;/code&gt; который выполняется при входе в систему:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/bash

osascript -e 'set volume 1'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;При входе звук сбрасывается в минимальное значение, а его делаю громче когда мне нужно. Жил я с такой системой много лет, пока не начал использвать iPad в качестве второго монитора. Для подключения iPad у меня стоит программа &lt;a href="https://www.duetdisplay.com/"&gt;Duet&lt;/a&gt; и либо с ней проблемы, либо с системой из-за переодического подключения/отключения мониторов, но, временами, громкость звука стала подниматься до 90%-100%.&lt;/p&gt;
&lt;p&gt;90% громкость в моей системе это можно наушники бросить под стол и прекрасно слышать все происходящее, абсолютно без проблем.&lt;/p&gt;
&lt;p&gt;Так вот, дабы не оглохнуть раньше времени, пришлось добавить "бота" в систему который каждые несколько секунд проверяет громкость звука и если она выше положенной, то возвращает её на допустимый уровень.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/Library/LaunchAgents/com.local.volumelevel.plist
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;!DOCTYPE plist PUBLIC &amp;quot;-//Apple//DTD PLIST 1.0//EN&amp;quot; &amp;quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;quot;&amp;gt;
&amp;lt;plist version=&amp;quot;1.0&amp;quot;&amp;gt;
&amp;lt;dict&amp;gt;
    &amp;lt;key&amp;gt;Label&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;com.local.volumelevel&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;ProgramArguments&amp;lt;/key&amp;gt;
    &amp;lt;array&amp;gt;
        &amp;lt;string&amp;gt;/usr/bin/osascript&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;-e&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;if (output volume of (get volume settings)) &amp;gt; 25 then set volume output volume 25&amp;lt;/string&amp;gt;
    &amp;lt;/array&amp;gt;
    &amp;lt;key&amp;gt;StartInterval&amp;lt;/key&amp;gt;
    &amp;lt;integer&amp;gt;10&amp;lt;/integer&amp;gt;
&amp;lt;/dict&amp;gt;
&amp;lt;/plist&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Нативный обработчик Apple Script, запускается каждые 10 секунд и выполняет команду&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (output volume of (get volume settings)) &amp;gt; 25 then set volume output volume 25
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Все. Теперь не оглохну.&lt;/p&gt;</content><category term="02"/><category term="macos"/></entry><entry><title>Будильник из Banana Pi (Raspberry Pi)</title><link href="https://blog.rpsl.info/2017/03/alarm-from-raspberry-pi/" rel="alternate"/><published>2017-03-20T21:49:44+03:00</published><updated>2017-03-20T21:49:44+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2017-03-20:/2017/03/alarm-from-raspberry-pi/</id><summary type="html">&lt;p&gt;Скопирую сюда &lt;a href="https://geektimes.ru/post/240803/"&gt;статью которую писал&lt;/a&gt; в 2014 году на geektimes, про то как я будильник из микрокомпьютера делал.
&lt;hr&gt;&lt;/p&gt;
&lt;p&gt;Несколько месяцев назад в моей голове поселилась идея, что я хочу просыпаться не просто под музыку, а под интернет-радио. “Просто куплю будильник, который это умеет” - подумал я и отложил эту мысль. Когда дело дошло до покупок, то я был сильно удивлен в связи тем, что не смог найти подходящих мне моделей в продаже. Критерии, по которым я подбирал будильник:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Уметь играть интернет-радио в качестве будильника.&lt;/li&gt;
&lt;li&gt;Работать по Wi-Fi (wpa2, “N” режим, желательно уметь без wps).&lt;/li&gt;
&lt;li&gt;Желательно уметь показывать время и работать как часы.&lt;/li&gt;
&lt;li&gt;Желательно иметь возможность настройки через телефон или компьютер.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Не могу сказать, что я требовал слишком много, т.к. обязательным требованием было только проигрывание интернет-радио, но все девайсы, которые мне встречались, были либо слишком большими, либо слишком дорогими, либо морально устаревшими.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Скопирую сюда &lt;a href="https://geektimes.ru/post/240803/"&gt;статью которую писал&lt;/a&gt; в 2014 году на geektimes, про то как я будильник из микрокомпьютера делал.
&lt;hr&gt;&lt;/p&gt;
&lt;p&gt;Несколько месяцев назад в моей голове поселилась идея, что я хочу просыпаться не просто под музыку, а под интернет-радио. “Просто куплю будильник, который это умеет” - подумал я и отложил эту мысль. Когда дело дошло до покупок, то я был сильно удивлен в связи тем, что не смог найти подходящих мне моделей в продаже. Критерии, по которым я подбирал будильник:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Уметь играть интернет-радио в качестве будильника.&lt;/li&gt;
&lt;li&gt;Работать по Wi-Fi (wpa2, “N” режим, желательно уметь без wps).&lt;/li&gt;
&lt;li&gt;Желательно уметь показывать время и работать как часы.&lt;/li&gt;
&lt;li&gt;Желательно иметь возможность настройки через телефон или компьютер.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Не могу сказать, что я требовал слишком много, т.к. обязательным требованием было только проигрывание интернет-радио, но все девайсы, которые мне встречались, были либо слишком большими, либо слишком дорогими, либо морально устаревшими.&lt;/p&gt;


&lt;p&gt;Стоит отметить, что я принципиально не рассматривал в этой схеме использование телефона в качестве проигрывателя музыки, у меня уже был такой опыт и он мне не понравился, тем более хотелось отделить эти компоненты. Я изначально не собирался держать этот проигрыватель около кровати, там, где заряжается телефон, а хотел отодвинуть его подальше, чтобы исключить возможность выключения будильника в состоянии сна.&lt;/p&gt;
&lt;p&gt;Обсудил с друзьями проблемы рынка современных будильников, они подсказали, что мне нужно использовать для этого дела любой микрокомпьютер. Идея была хорошая, ведь имея маленькую коробочку с линуксом на борту, я гарантированно смогу заставить этот девайс играть любое интернет-радио на любые колонки в доме, а вопросы его настройки — это уже дело техники.&lt;/p&gt;
&lt;h4&gt;Foxconn Banana Pi&lt;/h4&gt;
&lt;p&gt;Подбирая микрокомпьютер, я ориентировался на Raspberry Pi, но не отказывался и от его аналогов, которых сейчас появляется достаточно много. Именно так мне в руки и попал Banana Pi.&lt;/p&gt;
&lt;p&gt;&lt;img alt="banana pi" src="https://blog.rpsl.info/images/d9c7/cf5f/d9c7cf5fb133c76752a163c4a2cd01e0.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;small&gt;&lt;em&gt;Фото с сайта bananapi.org&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Banana Pi это, как заявляют производители, улучшенный и более мощный аналог Raspberry Pi, который обладает совместимым слотом для подключения модулей. Banana Pi обладает двухъядерным процессором с тактовой частотой 1GHz, гигабайтом оперативной памяти, гигабитным ethernet-портом, sata-портом для подключения внешних дисков, микрофоном, инфракрасным приемником и остальными интерфейсами, присущими каждой модели.&lt;/p&gt;
&lt;p&gt;&lt;img alt="banana pi schema" src="https://blog.rpsl.info/images/427b/24d9/427b24d99943a84bff346ee51de874c3.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;small&gt;&lt;em&gt;*На момент написания статьи производители уже представили новую плату под названием Banana PRO, которая является улучшенной версией Banana Pi.&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Banana pi поддерживает установку Lubuntu, Raspbian, Android, Bananian, OpenWrt, Fedora, ArchLinux и других linux-систем, но для перечисленных выше уже есть готовые образы, которые нужно только скачать &lt;a href="http://www.lemaker.org/resources/9-38/image_files.html"&gt;с сайта производителя&lt;/a&gt; и прожечь на карту памяти.&lt;/p&gt;
&lt;p&gt;По идее, в этом месте я должен произвести сравнительный анализ Raspberry Pi и Banana Pi, но т.к. с первым мне поработать не доводилось, то далее я расскажу о своих впечатлениях от второго.&lt;/p&gt;
&lt;p&gt;Процесс установки операционной системы не вызывает никаких сложностей, я просто скачал образ с сайта, залил его на флешку и запустил систему. Наигравшись с разными операционными системами, я остановился на Raspbian, предположив, что с ним будет меньше всего потенциальных проблем, да и различных материалов по нему достаточно. После первой загрузки с помощью raspi-config были произведены следующие настройки: отключен графический режим, sshd всегда включен, настроено wifi-подключение.&lt;/p&gt;
&lt;p&gt;Первое, с чем пришлось столкнуться — это маленькое сообщество вокруг данной платы, если для малины полно модулей, мануалов и статей, то тут приходится изучать скромную выдачу гугла и &lt;a href="http://forum.lemaker.org/forum.php"&gt;официальный форум&lt;/a&gt;, хотя форум вполне живой и основные вопросы, судя по датам, решаются быстро. Приобретение корпуса не стало проблемой, хотя я ожидал, что придется заказывать его доставку из Китая, оказалось, что запчасти уже продаются на барахолках. О совместимости с WiFi-модулями было прочитано заранее, а остальные запчасти для будильника были в любом магазине. Таким образом вместе с корпусом я приобрел usb wifi-модуль, microusb и аудиокабели.&lt;/p&gt;
&lt;p&gt;&lt;img alt="banana pi case" src="https://blog.rpsl.info/images/45ae/b103/45aeb10396c4b6bfa20953a6b00dbab4.jpg"&gt;&lt;/p&gt;
&lt;h4&gt;Будильник&lt;/h4&gt;
&lt;p&gt;Схема будильника довольно простая, устанавливаем mpd и mpc, добавляем радио, которое нам нравится, и настраиваем cron для автозапуска. В целом не обязательно использовать именно радио, я думаю, можно легко организовать сервис, который будет формировать плейлист из треков, которые вы лайкнули на soundcloud или которые присутствуют в ваших “аудиозаписях” на vk.com, но это, возможно, будет темой для следующих статей.&lt;/p&gt;
&lt;p&gt;Так получилось, что у меня дома нету отдельного музыкального центра и потребности в нем никогда не было, покупать большие колонки не хотелось, поэтому первым делом я попытался отыскать небольшое устройство, которое питается от сети и обладает аудиовходом. Не знаю, зачем, но я пошел и купил JBL OnBeat-Micro, вроде всё как хотелось, даже есть зарядка для телефона и частотный анализатор шума, который выключит динамик, если на него подается крайне тихая музыка, это очень удобно, когда колонка не гудит, а либо играет музыку, либо выключается. Радость от новой игрушки прошла спустя часа полтора, когда я обнаружил, что после получаса тишины “умные” микросхемы выключают колонку полностью и для последующего включения нужно нажать на кнопку.&lt;/p&gt;
&lt;p&gt;В итоге, избавившись от JBL, пришлось отыскать старую колонку Philips Fidelio DS3000. В ней есть аудиовход, она обладает механической кнопкой включения, довольно приятно звучит и размеры её, конечно, больше, чем у JBL, но всё равно достаточно скромные.&lt;/p&gt;
&lt;p&gt;Следующая проблема, с которой я столкнулся, это наводка на провода, видимо, Banana Pi выдает электромагнитные помехи, в результате чего колонка в состоянии покоя выдавала слишком сильный треск, это решилось заменой провода на более крупный и экранированный.&lt;/p&gt;
&lt;p&gt;Я сознательно не стал описывать, как я настраивал mpd и mpc, потому что материалов на эту тему огромное множество, и если возникнут вопросы, то я отвечу на них в комментариях.&lt;/p&gt;
&lt;h4&gt;Управление&lt;/h4&gt;
&lt;p&gt;Собранная схема работала и будила меня по утрам приятной музыкой, но нужно было решить вопрос с управлением этой системой. Для управления текущей сессией установил на телефон приложение MPoD.&lt;/p&gt;
&lt;p&gt;&lt;img alt="mpd mobile" src="https://blog.rpsl.info/images/04d6/9717/04d697177059f8565f7f96cc472f40ab.png"&gt;&lt;/p&gt;
&lt;p&gt;Оставалось только решить вопрос с управлением будильником. Изначально идей было несколько, самая первая — это поднять на Banana Pi веб-интерфейс для cron, но готовых и красивых решений сходу найти не удалось, поэтому пришлось смириться с мыслью, что и тут всё придётся делать самостоятельно. Пока я придумывал, как это сделать, то всё больше убеждался, что мне абсолютно не хочется писать веб-интерфейс для крона и устанавливать веб-сервер, поэтому ТЗ было переиграно, и конечная система должна будет работать следующим образом:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;На внешнем сервере устанавливается скрипт, который предоставляет простой интерфейс к задачам.&lt;/li&gt;
&lt;li&gt;Задачи должны формироваться простым образом из файла пресетов.&lt;/li&gt;
&lt;li&gt;Задача имеет два состояния, включена/выключена.&lt;/li&gt;
&lt;li&gt;Состояние задач отдается в виде cron-файла.&lt;/li&gt;
&lt;li&gt;На Banana Pi мы запускаем в cron скрипт, который раз в n минут будет устанавливать задачи для mpc пользователя. При этом нам не столь важно наличие интернета, т.к. даже если у нас будут неверные задания, то радио всё равно проигрываться не сможет.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В итоге за вечер я написал &lt;a href="https://github.com/Rpsl/alarm"&gt;простенький сервис&lt;/a&gt;, который отвечает всем условиям ТЗ, добавил его в избранное в мобильном телефоне, и теперь легко могу контролировать, во сколько начнет играть будильник.&lt;/p&gt;
&lt;p&gt;&lt;img alt="alarm" src="https://blog.rpsl.info/images/3352/50a2/335250a2ef5f070eba8212463f5e04cf.png"&gt;&lt;/p&gt;
&lt;p&gt;Настройки заданий хранятся в &lt;a href="https://github.com/Rpsl/alarm/blob/master/settings.yml"&gt;yml-файле&lt;/a&gt;, я решил, что мне абсолютно не нужна возможность редактировать их “на лету”, в 99% случаев я просыпаюсь в одинаковое время, а на крайний случай есть будильник в телефоне и возможность отредактировать пресеты менее, чем за пять минут.&lt;/p&gt;
&lt;h4&gt;Планы&lt;/h4&gt;
&lt;p&gt;В дальнейшем я хочу изучить вопрос с беспроводными передатчиками для аудиоканала. Попробовать сделать plex/xbmc клиент. Научить играть не только радио, а ещё и музыку из социальных сетей. Допилить сервис до возможности редактирования заданий, но это задача на самое дальнее будущее.&lt;/p&gt;
&lt;p&gt;Что касается самой платы, то я рад, что мне в руки попала именно она, а не малинка, т.к. по слухам в ближайшие пару лет обновление малины не планируется, а при почти одинаковой цене банан даёт больший запас ресурсов.&lt;/p&gt;</content><category term="03"/><category term="raspberry pi"/><category term="banana pi"/><category term="php"/></entry><entry><title>Wunder digest</title><link href="https://blog.rpsl.info/2017/03/wunder-digest/" rel="alternate"/><published>2017-03-06T19:12:33+03:00</published><updated>2017-03-06T19:12:33+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2017-03-06:/2017/03/wunder-digest/</id><summary type="html">&lt;p&gt;Для ведения личных дел я пробовал использовать различные менеджеры заданий, но всегда возвращаюсь на wunderlist. Он меня жутко раздражает своим интерфейсом и отсутствием нужных мне функций, поэтому раз в год я закипаю и пытаюсь мигрировать в другой продукт, несколько дней настраиваю все под себя, устанавливаю мобильный клиент, красиво веду задания, а потом запал проходит, я начинаю замечать недостатки и возвращаюсь туда откуда начинал.&lt;/p&gt;
&lt;p&gt;В последний раз я попытался сформулировать чего мне не хватает в wunderlist и постараться исправить эту проблему. В первую очередь мне не хватало дайджеста дел которые просрочились или запланированы на сегодня, поэтому я написал простенький скрипт, который получает из api wunderlist список дел, отбирает нужные и отправляет этот список на почту.&lt;/p&gt;
&lt;p&gt;Не могу сказать что жизнь прямо наладилась и я стал образцом продуктивности, но не забывать о важных вещах стало удобнее.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Rpsl/wundrelist-digest"&gt;&lt;img alt="wunder digest" src="/images/69e6/e356/69e6e356d6f52c093867cceba7c22953.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Rpsl/wundrelist-digest"&gt;https://github.com/Rpsl/wundrelist-digest&lt;/a&gt;&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Для ведения личных дел я пробовал использовать различные менеджеры заданий, но всегда возвращаюсь на wunderlist. Он меня жутко раздражает своим интерфейсом и отсутствием нужных мне функций, поэтому раз в год я закипаю и пытаюсь мигрировать в другой продукт, несколько дней настраиваю все под себя, устанавливаю мобильный клиент, красиво веду задания, а потом запал проходит, я начинаю замечать недостатки и возвращаюсь туда откуда начинал.&lt;/p&gt;
&lt;p&gt;В последний раз я попытался сформулировать чего мне не хватает в wunderlist и постараться исправить эту проблему. В первую очередь мне не хватало дайджеста дел которые просрочились или запланированы на сегодня, поэтому я написал простенький скрипт, который получает из api wunderlist список дел, отбирает нужные и отправляет этот список на почту.&lt;/p&gt;
&lt;p&gt;Не могу сказать что жизнь прямо наладилась и я стал образцом продуктивности, но не забывать о важных вещах стало удобнее.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Rpsl/wundrelist-digest"&gt;&lt;img alt="wunder digest" src="/images/69e6/e356/69e6e356d6f52c093867cceba7c22953.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Rpsl/wundrelist-digest"&gt;https://github.com/Rpsl/wundrelist-digest&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;Настройка достаточно простая:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В первую очередь нужно получить ключи для доступа к api, для этого идем в &lt;a href="https://developer.wunderlist.com/apps"&gt;developer.wunderlist.com&lt;/a&gt; и создаем новое приложение.&lt;/li&gt;
&lt;li&gt;Вторым шагом нужно зарегистрироваться в &lt;a href="https://www.mailgun.com/"&gt;mailgun&lt;/a&gt;, это сервис который позволяет легко отправлять почту и берет на себя все сложности с подписями писем и чтобы они не попадали в спам. На бесплатном тарифе можно отправлять несколько тысяч писем в месяц.&lt;/li&gt;
&lt;li&gt;Далее клонируем репозиторий &lt;a href="https://github.com/Rpsl/wundrelist-digest"&gt;wundrelist-digest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Выполняем &lt;code&gt;composer install&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;В директории config копируем &lt;code&gt;config.example.yml&lt;/code&gt; в &lt;code&gt;config.yml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Заполняем &lt;code&gt;config.yml&lt;/code&gt; значениями которые мы получили в прошлых шагах&lt;/li&gt;
&lt;li&gt;И наконец создаем cron задание на выполнение скрипта. &lt;code&gt;php ./cli.php digest:run&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;У меня он отправляет дела каждые день в 10:10 утра.&lt;/p&gt;</content><category term="03"/><category term="php"/><category term="service"/><category term="wunderlist"/><category term="github"/><category term="todo"/></entry><entry><title>И трех лет не прошло</title><link href="https://blog.rpsl.info/2017/02/lte-3-years/" rel="alternate"/><published>2017-02-26T21:30:34+03:00</published><updated>2017-02-26T21:30:34+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2017-02-26:/2017/02/lte-3-years/</id><summary type="html">&lt;p&gt;&lt;img alt="pelican is good" src="https://blog.rpsl.info/images/ddb2/4d93/ddb24d9338881d5d85026cdbc83ecc2a.png"&gt;&lt;/p&gt;
&lt;p&gt;Не был уверен что это когда-нибудь случится, но, иногда, от скуки, я заставлял себя реанимировать этот блог.
В данный момент я полностью отказался от wordpress и переехал на генератор статических блогов. &lt;a href="http://blog.getpelican.com/"&gt;Pelican&lt;/a&gt;, если кому интересно.&lt;/p&gt;
&lt;h3&gt;Почему не wordpress?&lt;/h3&gt;
&lt;p&gt;Это долгая история.&lt;/p&gt;
&lt;p&gt;Если начинать сначала, то этот блог был на Wordpress еще 2006 году, как раз в те времена, когда блоги уже были популярны, но LiveJournal уже начинал умирать. Несколько раз платформа менялась. Помню как-то психанул и полностью переехал на Movable Type, это такая блог платформа на перле. В ней была админка, а весь контент она так-же генерировала в статические файлы. Но Movable Type оказался ошибкой и я вернулся на Wordpress спустя некоторое время.&lt;/p&gt;
&lt;p&gt;Менялись домены, менялось оформление, блог кое-как работал.&lt;/p&gt;
&lt;p&gt;Wordpress, он ведь тоже не статичный механизм, время от времени обновляется платформа, обновляются плагины, темы обновляются, даже если его не трогаешь годами. Один плагин обновился, выполнил что-то, другой отключился, тоже обновил базу, в итоге ломается разметка, портятся ссылки, куски кода разваливаются и все выглядит не красиво.&lt;/p&gt;
&lt;p&gt;В результате не было никакого желания сюда писать, даже когда было о чем рассказать, я знал что сейчас открою, посмотрю, там все нужно чинить и легче не трогать.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;img alt="pelican is good" src="https://blog.rpsl.info/images/ddb2/4d93/ddb24d9338881d5d85026cdbc83ecc2a.png"&gt;&lt;/p&gt;
&lt;p&gt;Не был уверен что это когда-нибудь случится, но, иногда, от скуки, я заставлял себя реанимировать этот блог.
В данный момент я полностью отказался от wordpress и переехал на генератор статических блогов. &lt;a href="http://blog.getpelican.com/"&gt;Pelican&lt;/a&gt;, если кому интересно.&lt;/p&gt;
&lt;h3&gt;Почему не wordpress?&lt;/h3&gt;
&lt;p&gt;Это долгая история.&lt;/p&gt;
&lt;p&gt;Если начинать сначала, то этот блог был на Wordpress еще 2006 году, как раз в те времена, когда блоги уже были популярны, но LiveJournal уже начинал умирать. Несколько раз платформа менялась. Помню как-то психанул и полностью переехал на Movable Type, это такая блог платформа на перле. В ней была админка, а весь контент она так-же генерировала в статические файлы. Но Movable Type оказался ошибкой и я вернулся на Wordpress спустя некоторое время.&lt;/p&gt;
&lt;p&gt;Менялись домены, менялось оформление, блог кое-как работал.&lt;/p&gt;
&lt;p&gt;Wordpress, он ведь тоже не статичный механизм, время от времени обновляется платформа, обновляются плагины, темы обновляются, даже если его не трогаешь годами. Один плагин обновился, выполнил что-то, другой отключился, тоже обновил базу, в итоге ломается разметка, портятся ссылки, куски кода разваливаются и все выглядит не красиво.&lt;/p&gt;
&lt;p&gt;В результате не было никакого желания сюда писать, даже когда было о чем рассказать, я знал что сейчас открою, посмотрю, там все нужно чинить и легче не трогать.&lt;/p&gt;


&lt;h3&gt;Почему pelican?&lt;/h3&gt;
&lt;p&gt;Всё просто, я составил несколько критериев, открыл &lt;a href="https://www.staticgen.com/"&gt;StaticGen&lt;/a&gt; и начал вычеркивать все что мне не подходит.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Однозначно markdown&lt;/li&gt;
&lt;li&gt;Язык программирования который я умею&lt;/li&gt;
&lt;li&gt;Шаблонизатор который я понимаю&lt;/li&gt;
&lt;li&gt;Живое сообщество&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Таким образом я отобрал всех фаворитов и постарался детально взглянуть на каждый из них:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jekyllrb.com/"&gt;Jekyll&lt;/a&gt; и &lt;a href="http://octopress.org/"&gt;Octopress&lt;/a&gt;
 мне не подходят так как они написаны на Ruby, а у меня нету желания разбираться с Ruby.  &lt;/li&gt;
&lt;li&gt;Пробовал &lt;a href="https://hexo.io/"&gt;Hexo&lt;/a&gt;, но он написан на NodeJS. Помню полез что-то сделать т.к. криво работало отображение постов, в итоге понял что не хочу разбираться с этим callback адом.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt; хороший, очень быстрый, но весь его функционал вшит в ядро и как только понадобится сделать шаг в сторону, то начнутся проблемы. Плюс система шаблонов меня совсем не впечатлила.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Еще одним из важных факторов было какая разметка используется для написания постов. Я не про markdown, а про формат заголовков:&lt;/p&gt;
&lt;pre&gt;&lt;code class="markdown"&gt;Title: My tile
Date: 2016-07-01 14:27:34
Tags: tag1, tag2
Slug: slug
Status: draft

% content here %
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Это важно по той причине, чтобы опять не сесть на vendor lock.&lt;/p&gt;
&lt;p&gt;Поэтому я отмел и другие варианты, которые в целом казались весьма удобными.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://jigsaw.tighten.co/"&gt;jigsaw&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://themsaid.com/katana/"&gt;katana&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Вот так, в итоге остался pelican. У которого есть более-менее живое сообщество, куча различных плагинов и его разработка до сих пор продолжается.&lt;/p&gt;
&lt;p&gt;Сказать что он всем удобен? Нет. Абсолютно нет. Я с ним наступил на такое количество граблей, что хватит наполнять этот блог постами еще пару месяцев.&lt;/p&gt;
&lt;h3&gt;Ты же не пишешь? Зачем это все?&lt;/h3&gt;
&lt;p&gt;Мне хочется.&lt;/p&gt;
&lt;p&gt;Не смотря на то что сейчас есть бесконечное количество площадок где можно рассказать о чем-либо, ничто из них не может заменить личный блог. Удобный. Такой каким я хочу его видеть. Facebook, Medium, Github и другие площадки не удобный по разным причинам.&lt;/p&gt;</content><category term="02"/><category term="pelican"/><category term="blog"/></entry><entry><title>Leprosorium++</title><link href="https://blog.rpsl.info/2014/08/leprosorium/" rel="alternate"/><published>2014-08-20T10:58:00+04:00</published><updated>2014-08-20T10:58:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2014-08-20:/2014/08/leprosorium/</id><content type="html">&lt;p&gt;Некоторое время назад, примерно в мае, Jovan, Vicont и прочие веселые ребята выкатили новую версию Лепрозория и всё было замечательно, кроме отвалившихся юзерскрипт плагинов.&lt;/p&gt;
&lt;p&gt;Я очень привык к расшринию Lepra+, которое добавляет удобную кнопочки в браузер и включает в себя различные скрипты. Первым делом я полез патчить исходники, но просидев ночь понял что гораздо проще будет написать всё заново, тем более что технологии уже ушли вперед и можно сделать расшриние сразу для всех браузеров, а не ограничивать себя Google Chrome. &lt;/p&gt;
&lt;p&gt;&lt;img alt="leprosorium++" src="/images/0d77/aa58/0d77aa58449fa9ffe9a54e621e67765a.png"&gt;  &lt;/p&gt;
&lt;p&gt;С выбором платформы проблем не было, еще давно когда я работал в Корпорации ГУРУ мне довелось познакомиться с платформой &lt;a href="http://kangoextensions.com/"&gt;Kango&lt;/a&gt;, что занятно, её авторы тоже Леперы.&lt;/p&gt;
&lt;p&gt;Платформа позволяет работать с внутренним api, которое транслирует необходимые вызовы к api конкретного браузера, таким образом можно в кратчайшие сроки делать расшрирения «Кнопки», но делать специфические нативные вещи становится невозможно.&lt;/p&gt;
&lt;p&gt;Первую пригодную версию я сделал за ночь, потом еще несколько дней провел в режиме хакатона, пока фиксил баги и добавлял новые фичи, но тут нужно понимать что 99% времени ушло на адаптацию различных плагинов, а сам скелет приложения был сделан за один или два часа.&lt;/p&gt;
&lt;p&gt;В дальнейших планах было переделать страницу настроек, добавить красивые описания со скриншотами, но руки так и не дошли, а сейчас запал уже прошел и я занимаюсь только поддержкой текущего функционала.&lt;/p&gt;
&lt;p&gt;Всех энтузиастов приглашаю в репозиторий, а так же рекомендую познакомиться с Kango.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Rpsl/leprosorium/issues"&gt;https://github.com/Rpsl/leprosorium/issues&lt;/a&gt;&lt;/p&gt;</content><category term="Полезное"/><category term="browser"/><category term="javascript"/><category term="leprosorium"/></entry><entry><title>Turboloader - автоматическое скачивание сериалов</title><link href="https://blog.rpsl.info/2013/01/turboloader-avtomaticheskoe-skachivanie-serialov/" rel="alternate"/><published>2013-01-15T11:35:00+04:00</published><updated>2013-01-15T11:35:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2013-01-15:/2013/01/turboloader-avtomaticheskoe-skachivanie-serialov/</id><content type="html">&lt;p&gt;Я уже несколько раз упоминал что у меня в шкафу живет &lt;a href="http://blog.rpsl.info/?s=nas"&gt;старенький nas&lt;/a&gt;, я его использую для всего, и торренты он качает и бэкапы на него делаются и просто хранилище всякой-всячины. Так вот, уже около года он у меня и новые серии с Turbofilm.tv скачивает, раскладывает по папкам, отправляет на почту сообщение о том что серия скачалась.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Rpsl/turboload" title="Turboloader"&gt;&lt;img alt="turbofilm_m" src="/images/50f5/8f7d/50f58f7d07ea84cd3f9e9d5ac4c3f74d.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Изначально я не напрягался, а смотрел серии прямо на сайте через встроенный броузер playstation или apple tv, но бродилки там ущербные и работают совсем не так как все привыкли. &lt;/p&gt;
&lt;p&gt;После очередного апдейта на турбофильме они просто перестали логиниться, т.к. у них форма была на js и тэг &lt;code&gt;a&lt;/code&gt; был без аттрибута &lt;code&gt;href&lt;/code&gt;, хромы и файрфоксы такое кушают на ура, а эти скромники отказываются. Так как сериалы мне все равно смотреть хотелось, я решил что нужно это исправлять. Сначала пошел по пути легкого сопротивления и сделал на другом сайте простую кнопку, по нажатию которой отправлялся хитрый POST запрос и меня логинило на сайте, но все равно навигация превращалась в ад.&lt;/p&gt;
&lt;p&gt;Поэтому я решил, что будет не плохо написать простенький парсер, который раз в несколько часов будет проверять наличие серий и скачивать если таковые имеются. Про техническую реализацию я не буду сильно распинаться, все это было написано за один вечер на коленке и в условиях весьма ущербного линукса, я, вроде, спорные места отмечал комментариями.&lt;/p&gt;
&lt;p&gt;На данный момент он умеет скачивать "все ваши сериалы", скачивать только новые серии, скачивать серии только в хорошем качестве, скачивать серии с правильным языком, отмечать серию просмотренной после удачного скачивания и генерировать "правильные имена" для серий. &lt;/p&gt;
&lt;p&gt;Субтитры не делал т.к. не нуждаюсь, но при желании наверно можно прикрутить. Ну и само-собой он работает только с оплаченными аккаунтами, никакой халявы тут нету, а просто упрощение схемы.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Rpsl/turboload"&gt;Turboloader - скачать на гитхаб&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Несколько людей сообщали что им удалось его запускать на роутерах, но я подтвердить это не могу, если что пишите в комментариях.&lt;/p&gt;
&lt;p&gt;Пример конфигурации описан на гитхабе. Только я вас прошу, не ставьте проверку часто, а то нас всех выпилят и останемся без сериалов.&lt;/p&gt;</content><category term="Полезное"/><category term="nas"/><category term="php"/><category term="turbofilm"/><category term="сериалы"/></entry><entry><title>Про сервис</title><link href="https://blog.rpsl.info/2012/12/pro-servis/" rel="alternate"/><published>2012-12-06T10:39:00+04:00</published><updated>2012-12-06T10:39:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-12-06:/2012/12/pro-servis/</id><content type="html">&lt;p&gt;После участия в нескольких жарких спорах, я понял что некоторые люди вокруг меня не понимаю что значит "сервис". Ну или я не понимаю и пытаюсь всем навязать свою точку зрения, но свои размышления я изложу ниже и, как мне кажется, они вполне логичные.&lt;/p&gt;
&lt;p&gt;Не буду ходить далеко и выдумывать сложные примеры, а расскажу о том, с чем сталкиваюсь постоянно.&lt;/p&gt;
&lt;p&gt;&lt;img alt="apple product" src="/images/a010/1c97/a0101c974f2d3a03aa7bb928a43431ca.png"&gt;&lt;/p&gt;
&lt;p&gt;Вот например мне нравится мой провайдер интернета, onlime.ru. Я к нему подключился году в 2007, когда он еще не был онлаймом, а был НКС (Национальные кабельные сети) или что-то в этом духе. Мне нравится им пользоваться, честно. &lt;/p&gt;
&lt;p&gt;Они не достают меня рекламными смс и ежемесячными звонками с предложениями о подключении дополнительных услуг, в отличие от &lt;span style="text-decoration: line-through;"&gt;акадо&lt;/span&gt;. У них не бывает ремонтных работ, а если и бывают, то я этого не замечаю. &lt;/p&gt;
&lt;p&gt;Серьезно за все эти годы интернет не работал несколько раз. Мне нравится заходить в личный кабинет раз в год, узнавать что мой тарифный план устарел и за эти деньги я могу перейти на более выгодный тариф. Они сами подписали меня на программу лояльности и у меня есть куча бонусных баллов, которые я могу потратить на всякие фичи. &lt;/p&gt;
&lt;p&gt;Но самое главное в том, что они делают свою работу так, что мне не приходится думать об этом или забивать себе голову, я уверен что интернет у меня работает, а остальное мне не важно.&lt;/p&gt;
&lt;p&gt;&lt;img alt="google product" src="/images/af85/873a/af85873a8fbde2bc70248a05e5f3fd16.png"&gt;&lt;/p&gt;
&lt;p&gt;Мне нравится мой хостинг, &lt;a href="https://firstvds.ru/?from=17604"&gt;firstvds.ru&lt;/a&gt;, я знаю что они являются реcселерами от хетзнера, но мне не жалко переплачивать им чуть-чуть денег и иметь взамен возможность платить любым удобным мне способом и общаться с их сотрудниками на родном языке.&lt;/p&gt;
&lt;p&gt;Мне нравится, что когда в полночь я случайно запустил update-lilo и он попытался перепрошить загрузочный сектор на жестком диске, то я написал об этом в поддержку, они через 15 минут отреагировали на мою заявку, сами подключили KVM и под присмотром произвели тестирование и перезагрузку сервера.&lt;/p&gt;
&lt;p&gt;Я конечно мог и сам это делать, но тут я получил помощь адекватных специалистов, которые явно больше меня разбираются в вопросе и с их помощью убедился что сервер работает как нужно, может самостоятельно перезагружаться и не испытывает серьезных проблем. Разве это не замечательно?&lt;/p&gt;
&lt;p&gt;Раньше мне очень нравился Альфа-Банк, потому что они были удобными и приветливыми. Мне хотелось пользоваться их услугами и рекомендовать его друзьям. Сейчас они продолжают предоставлять отличный сервис, но как только ты сталкиваешься с их сотрудниками хочется застрелиться, потому что терпеть это невыносимо. &lt;/p&gt;
&lt;p&gt;Ну сами представьте, когда после посещения офиса и четырех звонков в службу поддержки в течение месяца они не могут изменить номер мобильного на который приходят уведомления об операциях с деньгами или смс для входа в интернет банкинг. &lt;/p&gt;
&lt;p&gt;Как можно доверять свои деньги компании которая может без спроса поменять ваш контактный email и секретное слово, а ее сотрудники обманным путем навязывают дополнительные услуги.&lt;/p&gt;
&lt;p&gt;Добавлю что вчера они, вроде как, исправили эту проблему, проблема была техническая и кто-то что-то не так у них подключил, но мы ведь понимаем, что их проблемы это их проблемы, а жизнь они портят мне.&lt;/p&gt;
&lt;p&gt;&lt;img alt="your company product" src="/images/17e2/fddc/17e2fddc98ef2ba769a7934cc14c8e84.png"&gt;&lt;/p&gt;
&lt;p&gt;Я люблю работать с paypal, т.к. у них все просто. Один раз зашел в личный кабинет, прошел несколько простых проверок и пользуйся на здоровье. Я желаю обанкротиться компании WebMoney из-за её ебучих систем авторизаций, проверок, привязок, попаболи и прочей адовой херни с которой приходится сталкиваться, я уже писал пост про это.&lt;/p&gt;
&lt;p&gt;Тут можно приводить еще очень много примеров, но смысл от этого не будет меняться.&lt;/p&gt;
&lt;p&gt;Сервис - это когда ты платишь немного денег за услуги, а взамен получаешь спокойствие и уверенность что большая часть проблем не возникнет или компания решит их самостоятельно.&lt;/p&gt;</content><category term="Заметки"/><category term="onlime"/><category term="paypal"/><category term="webmoney"/><category term="акадо"/><category term="альфабанк"/></entry><entry><title>Странности с Google Chrome</title><link href="https://blog.rpsl.info/2012/12/strannosti-s-google-chrome/" rel="alternate"/><published>2012-12-05T12:12:00+04:00</published><updated>2012-12-05T12:12:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-12-05:/2012/12/strannosti-s-google-chrome/</id><content type="html">&lt;p&gt;В последнее время замечаю, что Chrome периодически не правильно показывает страницу. Причем это явно не косяк верстки, а именно как будто видео карта глючит. Такое ломанное изображение, после совершения ajax действий над dom деревом, как только подводишь мышку к этому месту все становится хорошо. Компьютер его перерисовывает.&lt;/p&gt;
&lt;p&gt;Сделать скриншот не получается, т.к. при этом все исправляется, но я попытался изобразить на картинке как это выглядит.&lt;/p&gt;
&lt;p&gt;&lt;img alt="chrome broken" src="/images/a11f/db59/a11fdb591fb3ad0b5e842320cfe8e654.png"&gt;&lt;/p&gt;
&lt;p&gt;Еще иногда бывает что гифки не показываются. Для их запуска приходится щелкнуть рядом, что бы выделить гифку, тогда запускается. Проверял на разных сайтах и без расширений - без результата. Не знаю что с этим делать, на всякий случай воткнул на сайт такой код, success для ajax действий.&lt;/p&gt;
&lt;pre&gt;&lt;code class="javascript"&gt;$('#tab_content' ).height( $('#tab_content' ).height()+1 );
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Может сталкивался кто? Подскажите куда копать.&lt;/p&gt;</content><category term="Заметки"/><category term="javascript"/><category term="неведомая хуйня"/></entry><entry><title>Как стать "Rock Star" программистом</title><link href="https://blog.rpsl.info/2012/11/kak-stat-rock-star-programmistom/" rel="alternate"/><published>2012-11-08T07:14:00+04:00</published><updated>2012-11-08T07:14:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-11-08:/2012/11/kak-stat-rock-star-programmistom/</id><content type="html">&lt;p&gt;Вот несколько советов:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Найдите хорошего руководителя который будет критиковать ваш код, пусть он научит вас решать проблемы на собственном примере. Вы поймете что выросли, когда сможете оспорить его мнение правильными аргументами.&lt;/li&gt;
&lt;li&gt;Всегда увеличивайте сложность и масштабы проблем которые пытаетесь решать. Запомните что у большинства людей нет 20-летнего опыта, у них есть один год опыта повторяющийся 20 раз. Не становитесь таким.&lt;/li&gt;
&lt;li&gt;Заботьтесь о таких вещах как документация, имена методов и функций, покрывайте код тестами. Ваш код должен выглядеть профессионально и доступно, ведь с ним будут работать и другие люди.&lt;/li&gt;
&lt;li&gt;Изучайте все доступные библиотеки и модули, даже если они не требуются сейчас, вы все равно должны знать об их существование. Если вам приходится работать с незнакомыми компонентами — старайтесь полностью разобраться с их назначением.&lt;/li&gt;
&lt;li&gt;Если вы что-то не понимаете, то это должно стать стимулом пойти и разобраться в этом. Всегда погружайтесь глубоко.&lt;/li&gt;
&lt;li&gt;Используйте лучшую IDE для вашего языка, максимально изучите ее и выучите все хоткеи. Хорошая IDE очень сильно ускорит вас.&lt;/li&gt;
&lt;li&gt;Когда вы сталкиваетесь с новой проблемой, например вы никогда не работали с SOAP/XML, прежде чем начинать программировать почитайте что пишут в интернете на эту тему. Это поможет вам понять как другие люди решают задачи и с какими проблемами сталкиваются.&lt;/li&gt;
&lt;li&gt;Семь раз отмерь, один раз отрежь.&lt;/li&gt;
&lt;li&gt;Не забывайте что вы делаете продукт которым будут пользоваться другие. Постоянно общайтесь с заказчиками, следите за их ожиданиями, убеждайтесь что они знают чем вы занимаетесь и вы понимаете чего они хотят.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Это вольный перевод &lt;a href="http://www.quora.com/How-does-one-become-a-rockstar-developer#"&gt;этой заметки&lt;/a&gt;, просто захотелось оставить тут.&lt;/p&gt;</content><category term="Полезное"/><category term="работа"/><category term="разработка"/></entry><entry><title>Gmail Show-M.-Later</title><link href="https://blog.rpsl.info/2012/10/gmail-show-m-later/" rel="alternate"/><published>2012-10-10T11:19:00+04:00</published><updated>2012-10-10T11:19:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-10-10:/2012/10/gmail-show-m-later/</id><content type="html">&lt;p&gt;&lt;a href="https://github.com/Rpsl/Show-M-Later"&gt;&lt;img alt="Gmail Show M later" src="/images/cde2/ab93/cde2ab935b7c311fb58222e58a67843f"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Если кратко, то эта фича позволяет создать в вашем ящике ярлыки (папки),
положив письмо в которые, оно будет лежать пока не пройдет нужный срок,
а потом оно снова переместится в inbox и станет не прочитанным. Мне
такой штуки очень давно не хватало, т.к. часто приходят письма, на
которые нужно отреагировать, но в данный момент реагировать на них
возможности нету.&lt;/p&gt;
&lt;p&gt;Есть более древние варианты в галерее скриптов, Gmail Snooze например,
но они позволяют работать только с дневными интервалами и устроены таким
образом, что письмо добавленное в 23:00, в 01:00 снова окажется в
инбоксе. Поэтому я сначала модифицировал, а потом полностью переписал. В
моей реализации, письма живут более правильной жизнью.&lt;/p&gt;
&lt;p&gt;Испытательный срок длился две недели. Это только последней стабильной
версии, до этого были еще другие реализации, пробовал использоваться
Cache вместо ScriptDB, но он слишком часто терял ключи. С этой версией
проблем не возникало, пару раз, было что скрипт зависал, но я забил на
это дело, т.к. повторить ошибку мне не удалось.&lt;/p&gt;
&lt;p&gt;Касательно объемов данных. Каждому пользователю google выделяется 50мб
под ScriptDB, но может быть и больше, если у вас платный аккаунт. Что бы
упереться в размер данных, нужно будет очень постараться, поэтому до
первой проблемы, решать ее не собираюсь. Тестировал максимум на 20
активных письмах, все прошли полный цикл без ошибок. Наверно, если писем
будет больше, то возможен тайм–аут. Если столкнулись с проблемой,
пишите, буду исправлять.&lt;/p&gt;
&lt;p&gt;Инструкцию и комментарии мне писать было лень, поэтому они не сильно
подробные, но я постарался все расписать максимально доступно, в стиле
пойди сюда — кликни тут.&lt;/p&gt;
&lt;p&gt;Буду рад ответить на вопросы.&lt;br&gt;
Буду очень рад, если появится перевод на другие языки.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Rpsl/Show-M-Later"&gt;https://github.com/Rpsl/Show–M–Later&lt;/a&gt;&lt;/p&gt;</content><category term="Полезное"/><category term="gmail"/><category term="javascript"/></entry><entry><title>Nginx изменение картинки по рефереру</title><link href="https://blog.rpsl.info/2012/09/nginx-change-image-by-referer/" rel="alternate"/><published>2012-09-16T18:02:00+04:00</published><updated>2012-09-16T18:02:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-09-16:/2012/09/nginx-change-image-by-referer/</id><content type="html">&lt;p&gt;В последнее время, стало модным вместо борьбы с хотлинками, выдавать вместо ожидаемого контента несколько другой. Я это заметил на примере мем сайтов, которые при обращение к их картинкам с других сайтов, отдают эту картинку, но приделывают к ней футер с адресом сайта или подобной рекламной информацией.&lt;/p&gt;
&lt;p&gt;В целом весьма логично, если раньше все боялись за свой трафик, то теперь вопросы трафика мало кого интересуют, поэтому и приоритеты сместились в другую сторону. Хотя я видел ситуацию, когда на одном из рабочих ресурсов, образовался хотлинк канал японского трафика на 250mb/s.&lt;/p&gt;
&lt;p&gt;Попробуйте открыть это изображение в новой вкладке (убедитесь что броузер не закешировал)&lt;/p&gt;
&lt;p&gt;%раньше тут была картинка%&lt;/p&gt;
&lt;p&gt;Рассматривая разные решения, я нашел самый простой способ, делать это с помощью nginx и встроенного модуля
&lt;a href="http://nginx.org/ru/docs/http/ngx_http_referer_module.html"&gt;ngx_http_referer_module&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;test_images.conf&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="nginx"&gt;server {
        listen 80;
        server_name images.dev;
        root /www/data/test_images;

        location /test_images {
                valid_referers none blocked server_name images.dev;

                if ($invalid_referer) {
                        rewrite ^(.*)/(.*)$ /images_bad/$2 last;
                }

                rewrite ^(.*)/(.*)$ /images_ok/$2;
        }

        location /images_ok {
                internal;
                alias /www/data/images/test_images/ok;
        }

        location /images_bad {
                internal;
                alias /www/data/images/test_images/bad;
        }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Собственно механика очень простая. Мы определяем с помощью "valid_referers" список правильных доменов, можно добавить в него домены поисковиков, например, что бы при поиске картинок пользователю показывалась правильная картинка. Потом мы создаем два внутренних location, которые отвечают за показ правильных и не правильных картинок. В случае не правильного реферера, в конструкции if мы делаем редирект на локейшн с картинками, которые должны отдаваться жуликам, которые ленятся скачивать картинку на свой сервер. &lt;/p&gt;
&lt;p&gt;Ну вот, в общем и все. Осталось только позаботиться, что-бы у нас были необходимые картинки.&lt;/p&gt;
&lt;p&gt;Тут можно решать разными путями, например, при создание оригинальной картинки создавать ее "обработанный" вариант. Но мне больше нравится ленивая загрузка, которую я, когда-то давно, делал в &lt;a href="http://blog.rpsl.info/2011/03/php-kehshirovanie-kartinok-chast-vtoraya/"&gt;iCacher&lt;/a&gt;, основная идея проста: при попытке запроса "обработанной" картинки, если ее нету, управление передается скрипту, который проверяет ее оригинал и делает ее "обработанную" копию, которая отдается пользователю. &lt;/p&gt;
&lt;p&gt;При повторном обращение, запрос не дойдет до скрипта и пользователю отдастся статический файл. Таким образом мы получаем генерацию изображений по требованию. Еще можно добавить крон скрипт, который будет удалять "обработанные" картинки через 30 дней.&lt;/p&gt;
&lt;p&gt;Я не уверен, что моя реализация хороший пример и буду рад если вы ее покритикуете. Плюс, я так и не придумал как избавиться от &lt;code&gt;if&lt;/code&gt; в данном случае (вариант хранения файлов в images_ok/1/ считаю плохим).&lt;/p&gt;</content><category term="Полезное"/><category term="banners"/><category term="cache"/><category term="images"/><category term="nginx"/></entry><entry><title>Шутка дня</title><link href="https://blog.rpsl.info/2012/07/shutka-dnya/" rel="alternate"/><published>2012-07-18T06:43:00+04:00</published><updated>2012-07-18T06:43:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-07-18:/2012/07/shutka-dnya/</id><content type="html">&lt;pre&gt;&lt;code&gt;&amp;lt;!‐‐[if lte IE 7]&amp;gt; &amp;lt;style&amp;gt; * {font-family: &amp;quot;Comic Sans&amp;quot; !important;} &amp;lt;/style&amp;gt; &amp;lt;![endif]‐‐&amp;gt;
&lt;/code&gt;&lt;/pre&gt;</content><category term="Заметки"/><category term="css"/></entry><entry><title>Почему жилье дорожает</title><link href="https://blog.rpsl.info/2012/07/pochemu-zhil-e-dorozhaet/" rel="alternate"/><published>2012-07-06T06:42:00+04:00</published><updated>2012-07-06T06:42:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-07-06:/2012/07/pochemu-zhil-e-dorozhaet/</id><content type="html">&lt;p&gt;Вообще, у меня сегодня были планы рассказать вам про мои ощущения от
xhprof, что мне удалось с его помощью прооптимизировать и обругать
несколько статей в которых его пытаются использовать не правильно, но я
нашел великолепную заметку, которая показывает принципы работы нашей
экономики. Наверняка боян дикий, но мне очень понравилось и как минимум
на память я это опубликую.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Я Вам сейчас очень просто объясню, почему дома подорожали к зарплате -
бензин тут ни при чем. Допустим, мы - я, Вы и Хроноскопист летели на
самолете через Тихий океан. В пути мы втроем накушались абсента,
надебоширили, отломали дверь от туалета, и нас за это выкинули в море
через аварийный выход. По счастью, рядом с местом нашего падения
обнаружился маленький безымянный полинезийский остров. Выбравшись на
берег, мы посовещались, и решили считать его новым государством под
названием Соединенные Штаты Абсента (США).&lt;/p&gt;
&lt;p&gt;Когда нас выкидывали из самолета, то багажа нам, естественно, не
выдали. Поэтому, всех материальных и нематериальных активов у нас -
только туалетная дверь, которую Вы таки прихватили с собой. И вообще,
несмотря на абсент, Вы у нас оказались самым запасливым - в бумажнике
у Вас, совершенно случайно, обнаружилась банкнота в $100. Таким
образом, в наших США имеются нефинансовые активы - дверь, и финансовые
активы, они же денежная масса - $100. Это все наши сбережения.
Поскольку у нас больше вообще ничего нет, то можно сказать и так - у
нас есть один материальный актив - дверь, обеспеченный денежной массой
в $100. Т. е. наша дверь стоит $100.&lt;/p&gt;
&lt;p&gt;Немного протрезвев, мы решаем, что надо как-то обустраиваться. Самый
быстрый из нас оказался Хроноскопист. Он тут же объявил, что создает
банк и готов взять в рост имеющиеся у населения денежные сбережения
под 3% годовых - ну не сидится человеку без дела. Вы отдаете ему
$100, и он их записывает в блокнот в статью "Пассивы - Дипазиты".
Но я тоже не лаптем щи хлебал - зря я что ли столько времени занимаюсь
расследованием экономического мухлежа - я знаю как изъять у Вас и
дверь и $100. Я предлагаю Вам взять Ваши $100 в рост под 5% годовых.
Вырываю листик из своего блокнота и пишу на нем - "Аблегиция на $100
под 5% годовых". Вы чувствуете, что Вам поперло. Забираете деньги у
расстроенного Хроноскописта с дипазита и отдаете их мне в обмен на мою
аблегацию.&lt;/p&gt;
&lt;p&gt;Я беру Ваши $100 и кладу их на дипозит в банк обратно обрадованного
Хроноскописта.&lt;br&gt;
По хорошему, на этом можно было бы и успокоиться и пойти всем
заняться делом - пальму потрясти или за моллюсками понырять, снискать
себе хлеб насущный, так сказать. Но Вы ж знаете - я неуемный
финансовый гений, такие пустяки как кокосы и устрицы меня не
интересуют. Помыкавшись по нашему острову - 50 шагов от южного
побережья до северного, и 30 с запада на восток, я придумываю
гениальную комбинацию. Я подхожу к Вам и предлагаю на пустом месте
заработать еще 1% годовых. Взять в банке Хроноскописта кредит под 4%,
и купить у меня еще одну аблигацию под 5%. Вторую аблегацию на $100 я
тут же выписываю на блокнотном листике, и машу ею у Вас перед носом.
Недолго думая, Вы бежите в банк и берете кредит $100 под залог моей
первой аблегации на $100. Они там есть - я их туда положил на
дипазит. Вы отдаете мне заемные $100 и прячете вторую аблегацию к
себе в бумажник - теперь у Вас есть моих аблегаций на $200. А $100 я
кладу в банк - теперь у меня там $200 на дипазите. Хроноскопист аж
подпрыгивает от радости - кредитный бизнес попер.&lt;/p&gt;
&lt;p&gt;Думаете я на этом остановлюсь? Ага, сейчас - я уже выписал Вам третью
аблегацию. Бегом в банк за кредитом под залог второй аблегации. Ближе
к вечеру, набегавшись по острову с этой сотней баксов и изодрав все
листочки из блокнота на аблегации, мы имеем следующую картину. У Вас
на $5000 моих аблегаций, а у меня на $5000 дипазитов в банке.
Теперь, я чувствую, что пришло время прибрать Вашу дверь к рукам. Я
предлагаю купить ее у Вас за $100. Но Вы вредничаете - дверь-то всего
одна, и заламываете цену в $1000. Ну, $1000 так $1000 - в конце
концов у меня на депозите лежит целых $5000. Я на последнем
блокнотном листочке направляю платежное поручение Хроноскописту,
перевести $1000 с моего дипазита на Ваш, и забираю Вашу дверь.&lt;/p&gt;
&lt;p&gt;Если нашу бухгалтерию отдать американскому экономисту с гарвардским
дипломом, он сообщит нам, что наши США располагают $1000 материальных
активов в виде двери, и $10000 финансовых активов в виде аблегаций и
дипазитов. Т. е. что стоимость нашего совокупного имущества
увеличилась за день в 110 раз.&lt;/p&gt;
&lt;p&gt;Менее тонкий и образованный человек сказал бы, что мы - три дебила, у
нас как была одна дверь и $100, так и осталось, и что только
конченные дебилы могли целый день рвать листочки из блокнота, вместо
того, чтобы нарвать кокосов. Кто из них прав - решайте сами. Но
механизм относительного роста цен на дома именно такой, что в США, что
в Японии, что в России.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Полезное"/><category term="деньги"/><category term="жизнь"/></entry><entry><title>Percona Server Configuration Wizard</title><link href="https://blog.rpsl.info/2012/07/percona-server-configuration-wizard/" rel="alternate"/><published>2012-07-05T10:38:00+04:00</published><updated>2012-07-05T10:38:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-07-05:/2012/07/percona-server-configuration-wizard/</id><content type="html">&lt;p&gt;Возможность генерировать удобный конфиг для mysql прямо &lt;a href="https://tools.percona.com/"&gt;на сайте перконы&lt;/a&gt; для меня стало открытием. Есть возможность указать различные характеристики железа и роль данного сервера, а сайт постарается подобрать оптимальные настройки.&lt;/p&gt;
&lt;p&gt;&lt;img alt="percona" src="/images/80bf/635c/80bf635c97274dbdf097c04e6155555e.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Проходим небольшой тест, отвечая на вопросы и на выходе имеем подобный конфиг:&lt;/p&gt;
&lt;pre&gt;&lt;code class="conf"&gt;# Generated by Percona Configuration Wizard (http://tools.percona.com/) version REL5-20120208
# Configuration name zlo generated for gmail@rpsl.info at 2012-07-05 10:31:23

[mysql]

# CLIENT #
port                           = 3306
socket                         = /srv/mysql/mysql/mysql.sock

[mysqld]

# GENERAL #
user                           = mysql
default_storage_engine         = InnoDB
socket                         = /srv/mysql/mysql/mysql.sock
pid_file                       = /srv/mysql/mysql/mysql.pid

# MyISAM #
key_buffer_size                = 32M
myisam_recover                 = FORCE,BACKUP

# SAFETY #
max_allowed_packet             = 16M
max_connect_errors             = 1000000
skip_name_resolve
sysdate_is_now                 = 1
innodb                         = FORCE

# DATA STORAGE #
datadir                        = /srv/mysql/mysql/

# CACHES AND LIMITS #
tmp_table_size                 = 32M
max_heap_table_size            = 32M
query_cache_type               = 0
query_cache_size               = 0
max_connections                = 500
thread_cache_size              = 50
open_files_limit               = 65535
table_definition_cache         = 1024
table_open_cache               = 256

# INNODB #
innodb_flush_method            = O_DIRECT
innodb_log_files_in_group      = 2
innodb_log_file_size           = 128M
innodb_flush_log_at_trx_commit = 1
innodb_file_per_table          = 1
innodb_buffer_pool_size        = 1456M

# LOGGING #
log_error                      = /srv/mysql/mysql/mysql-error.log
log_queries_not_using_indexes  = 1
slow_query_log                 = 1
slow_query_log_file            = /srv/mysql/mysql/mysql-slow.log
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ну и в качестве бонуса, рекомендую почитать доклад "&lt;a href="http://www.percona.com/files/presentations WEBINAR2012-03-Optimizing-MySQL-Configuration.pdf"&gt;Optimizing MySQL Configuration&lt;/a&gt;" от Percona&lt;/p&gt;</content><category term="Полезное"/><category term="mysql"/><category term="percona"/></entry><entry><title>Nginx allow POST static files</title><link href="https://blog.rpsl.info/2012/07/nginx-allow-post-static-files/" rel="alternate"/><published>2012-07-03T14:10:00+04:00</published><updated>2012-07-03T14:10:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-07-03:/2012/07/nginx-allow-post-static-files/</id><content type="html">&lt;p&gt;dotZero, этим утром выложил &lt;a href="http://blog.dotzero.ru/2012/7/3/nginx-facebook-iframe/"&gt;свое решение проблемы&lt;/a&gt;, но мне оно показалось не правильным, поэтому я предлагаю свой вариант.&lt;/p&gt;
&lt;p&gt;Мое решение лучше тем, что оно не требует поднятия второго сервера на отдельном порту и вообще эстетически красивое.&lt;/p&gt;
&lt;p&gt;Кратко о проблеме:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Все знают о том что в Facebook'e есть iframe страницы, но не все знают
что Facebook эти страницы запрашивает через POST, а не через GET, как
делают все остальные. Поэтому все fb:iframe приложения запрашивая у
Nginx'а страницы в ответ будут получать ошибку:&lt;/p&gt;
&lt;p&gt;405 "Method Not Allowed"&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Вариант который предлагает dotZero выглядит примерно вот так (это я для истории и поисковых запросов оставлю):&lt;/p&gt;
&lt;pre&gt;&lt;code class="nginx"&gt;upstream fb_static {
    server localhost:8001;
}

server {
    listen       443;
    server_name  _;

    #allow_static_post on;

    error_page 405 =200 @405;

    location @405 {
        proxy_method GET;
        proxy_pass http://fb_static;
    }
}

server {
    listen 8001;
    server_name _;

    location / {
        root &amp;quot;/var/www/fb&amp;quot;;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Вариант конечно хороший и самое главное рабочий. Но давайте попробуем так:&lt;/p&gt;
&lt;pre&gt;&lt;code class="nginx"&gt;server {
    listen  80;
    server_name _;

    # Тут мы описываем поведение
    # для нашей кастомной ошибки
    error_page 405 = $uri;

    # Дефолтный location
    location / {
        access_log off;
        root    /srv/path
        try_files $uri $uri/index.html /index.php$is_args$args;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Что тут происходит? Мы складываем весь статический контент который будет запрашивать facebook в отдельную директорию, просто, для красоты. Определяем location для этой директории, который будет всегда возвращать код ошибки, например, 599. И определяем поведение для обработки этой ошибки, как попытку отдать данные по этому урлу.&lt;/p&gt;
&lt;p&gt;Вот и все, работает. Читайте мануалы.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPD:&lt;/strong&gt; вернул конфиг до состояние обработки напрямую 405 error_page, т.к. поведение описанное до этого, не совсем соответствовало реальности. 
Таким образом, после запроса файла через POST, будет выдана 405 ошибка, которая обработается в &lt;code&gt;error_page 405 = $uri&lt;/code&gt; и будет отправлена в &lt;code&gt;location /&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;То есть либо файл найдется и будет отдан, либо управление будет передано в &lt;code&gt;index.php&lt;/code&gt;.&lt;/p&gt;</content><category term="Полезное"/><category term="facebook"/><category term="nginx"/></entry><entry><title>PHP: detect UTF-8</title><link href="https://blog.rpsl.info/2012/07/php-detect-utf-8/" rel="alternate"/><published>2012-07-02T07:39:00+04:00</published><updated>2012-07-02T07:39:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-07-02:/2012/07/php-detect-utf-8/</id><content type="html">&lt;p&gt;Пару недель назад, мне кто-то доказывал, что mb_detect_encoding, работает в разы быстрее своих надуманных конкурентов. Задача простая, проверить входящую строку на принадлежность к UTF-8. Логика простая, либо UTF-8, либо нет. В повседневной жизни, обычно не приходится выбирать из зоопарка кодировок и, чаще всего, строка либо в utf8, либо в cp1251.&lt;/p&gt;
&lt;p&gt;Сделал простой синтетический тест. Прогнал определение через функцию 10000 раз. Посмотрел кто быстрее.&lt;/p&gt;
&lt;p&gt;Вариант 1, который мне нравится:&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;$s = microtime(true);

for( $i=0; $i&amp;lt;10000; $i++ )
{
    $string = 'sdf;gklaj;skdjf;sdkfls;dfjk';

    if( preg_match('//u', $string ) )
    {

    }
}

$e = microtime(true);

echo &amp;quot;\n\n&amp;quot; . $e-$s;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Средний результат выполнения скрипта на моей машине ~0.020 сек. Сравнивал я его с более правильным решением, которое выглядит так:&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;$s = microtime(true);

for( $i=0; $i&amp;lt;10000; $i++ )
{
    $string = 'sdf;gklaj;skdjf;sdkfls;dfjk';

    mb_detect_encoding( $string, array('UTF-8'), true );
}

$e = microtime(true);

echo &amp;quot;\n\n&amp;quot; . $e-$s;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Средний результат выполнения скрипта на моей машине ~0.050 сек.
После этих тестов, решил прогнать на больших объемах данных, сгенерировал текст размером 10к байт и пропустил через функции.
Для preg_match время выполнения составило ~0.120 сек, для mb_detect_encoding ~0.7 сек.
Из этих изысканий можно сделать вывод, что определение через preg_match работает в разы быстрее чем стандартные механизмы, но, вероятно, проигрывает в количестве доступых фич.&lt;/p&gt;
&lt;p&gt;На самом деле, есть еще три миллиона разных способов решить эту задачу, расскажите чем пользуетесь вы?&lt;/p&gt;</content><category term="Полезное"/><category term="php"/><category term="utf"/></entry><entry><title>Про webmoney</title><link href="https://blog.rpsl.info/2012/06/pro-webmoney/" rel="alternate"/><published>2012-06-29T07:10:00+04:00</published><updated>2012-06-29T07:10:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-06-29:/2012/06/pro-webmoney/</id><content type="html">&lt;p&gt;В прошлом посте я писал про молоток, вспомнил, что несколько месяцев
назад со мной приключилась беда. Каким то неведомы макаром, мои ключи к
киперу стали не действительными. Примерно в это же время, на одном
несуществующем сайте, появился чувак который занимает руководящую
должность в этой конторе. Он попросил всех рассказать свои &lt;em&gt;&lt;span
style="color: #ff0000;"&gt;success story&lt;/span&gt;&lt;/em&gt; про пользование системой.
Ну вот я и рассказал. Сюда перенесу на память.&lt;/p&gt;
&lt;p&gt;&lt;img alt="webmoney" src="/images/f943/d6c0/f943d6c04ee76aaa61ada62a9f04ce94.png"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Есть у меня виртуалка, живет уже много лет, в ней крутится только Win
XP и кипер класик. Апдейты там еще какие–то ставятся хз. Кроме кипера
и Google Chrome в ней вообще ничего нету используется раз в месяц для
вывода денег из sape и транзита этих денег на оплату мобильника,
инета, серверов.&lt;/p&gt;
&lt;p&gt;Нажал в сапе на вывод денег, через пару дней запускаю виртуалку, т.к.
деньги уже должны придти, ебать–колотить–супер–ошибка, вы вводите
правильный пароль от файла ключей, но не правильный пароль от
аккаунта. &lt;span style="color: #ff0000;"&gt;&lt;em&gt;Наркоман штоле сука?&lt;/em&gt;&lt;/span&gt;,
ну ок, следую инструкциям, нахожу в бэкапе файл ключей, скармливаю его
киперу — вы используете устаревший файл ключей, блядь, да вы же сами
просили его сохранить на дискету, не менял я пароли в кипере, вообще
ничего не делал кроме как получить деньги — заплатить деньги. Пиздуйте
на наш сайт, авторизуйтесь, подтвердите емаил, введи код из смс,
заполните заявку на восстановление, авторизуйтесь, введите код из смс,
сколько денег на счету? какие ваши доказательства? какой айпи? укажите
емаил? фамилия вашей кузины, пришлите нотариально заверенную сетчатку
глаза? Молодец, для подвтерждения что вы это вы загрузите сканы вашего
пасспорта. Вы наркоманы там, у меня кипер к альфе привязан, у меня
есть ебучий аттестат который я заебался получать, который гарантирует
что я это я. Заявка без документов отменена. Начианайте квэст заново.&lt;/p&gt;
&lt;p&gt;Через пару дней собрался силами и прошел этот квест снова, далее
неделя ожидания и куча ебанутых писем на почту о статусе моей заявки
"Костя из саппорта проверил ваши данные", "Дима из саппорта подтвердил
ваши данные", "Ваша заявка передана из отдела саппорта в отдел
заявок" — Нахуй мне это знать??? Мне важно что заявка получена вами и
что на нее пришел ответ. Спустя неделю получил новый файл ключей,
залогинился, снова, блядь, активируйте вашу систему, ссылка
отправленна на почту.&lt;/p&gt;
&lt;p&gt;Потом я уже почитал этот пост, решил сделать себе из кипер классик —
кипер мини, енум, клиент для мака, полтора часа попыток понять что это
и нахуй оно вообще нужно, 2000 пройденых каптч, 50 полученых смс и
ачивка "Вебмани в МакОС" получена.&lt;/p&gt;
&lt;p&gt;Спасибо. Охуеть. Сдохните.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Заметки"/><category term="webmoney"/></entry><entry><title>Молоток.ру и забота о пользователях</title><link href="https://blog.rpsl.info/2012/06/molotok-ru-i-zabota-o-pol-zovatelyah/" rel="alternate"/><published>2012-06-27T07:56:00+04:00</published><updated>2012-06-27T07:56:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-06-27:/2012/06/molotok-ru-i-zabota-o-pol-zovatelyah/</id><content type="html">&lt;p&gt;В последнее время я достаточно щепетильно отношусь к своему почтовому ящику. Я начал это делать, после того как понял, что мне в день приходит более сотни левых писем о всяких акциях, скидках, конкурсах и прочие дайджест рассылки. Я отписался от 90% сервисов которые не представляют для меня интереса и жизнь вроде наладилась, дышать стало свободнее. Только остаются некоторые уебищные сервисы, отписаться от которых - дикий квест. Молоток.ру один из таких. Не помню по какому роковому стечению обстоятельств лет 8 назад я случайно завел там аккаунт, но точно помню, что с тех пор я его больше не посещал, а вот письма со всякой херней они продолжают слать мне до сих пор.&lt;/p&gt;
&lt;p&gt;У вас кстати есть карточка от много.ру? Я ее случайно лет 10 назад завел. Прошло лет 9 как я ее потерял, но письма они продолжают слать, у них видимо не хватает мозгов додумать, что аккаунты которые не подавали активности последние 10 лет можно считать не валидными.&lt;/p&gt;
&lt;p&gt;Так вот, возвращаясь к молотку. Как меня бесит, что нельзя отписаться от рассылки в один клик. Чтобы отписаться от рассылки, нужно пройти на их сайт, войти в свой аккаунт и там настроить систему уведомлений.&lt;/p&gt;
&lt;p&gt;Ну ок, давайте попробуем так сделать. После ввода своего логина (для восстановления пароля), оказывается я должен ввести "некую" секретную фразу, которая, видимо, является вторым паролем. У меня такой нету, соответственно я должен пройти процедуру установки этой секретной фразы, несколько валидаций, только что бы отписаться от их рассылки. И что самое уебищное, то, что раздел "обратная связь", тоже, работает только с авторизованными пользователями.&lt;/p&gt;
&lt;p&gt;&lt;img alt="trololo" src="/images/999a/743b/999a743b71233d1126f695765564fee6.png"&gt;&lt;/p&gt;
&lt;p&gt;Главной мыслью этой заметки является обращение к веб мастерам. &lt;strong&gt;Пожалуйста, делайте то, что нужно пользователям, а не то, чем вы занимаетесь.&lt;/strong&gt;&lt;/p&gt;</content><category term="Заметки"/><category term="mail"/><category term="spam"/></entry><entry><title>Nginx detect mobile browser</title><link href="https://blog.rpsl.info/2012/06/nginx-detect-mobile-browser/" rel="alternate"/><published>2012-06-25T07:11:00+04:00</published><updated>2012-06-25T07:11:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-06-25:/2012/06/nginx-detect-mobile-browser/</id><content type="html">&lt;p&gt;Регулярка для Nginx&lt;/p&gt;
&lt;pre&gt;&lt;code class="nginx"&gt;set $mobile_rewrite do_not_perform;

if ($http_user_agent ~* &amp;quot;android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge|maemo|midp|mmp|netfront|opera m(ob|in)i|palm(os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino&amp;quot;) {
  set $mobile_rewrite perform;
}

if ($http_user_agent ~* &amp;quot;^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-||_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac(|\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-)&amp;quot;) {
  set $mobile_rewrite perform;
}

if ($mobile_rewrite = perform) {
  rewrite ^ http://m.site.com/ redirect;
  break;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ну и собственно &lt;a href="http://detectmobilebrowsers.com/"&gt;вот тут&lt;/a&gt; собранные подобные рецепты для различных языков и сервисов.&lt;/p&gt;</content><category term="Полезное"/><category term="mobile"/><category term="ngixn"/></entry><entry><title>7000 rps на Nginx - Achievement unlocked</title><link href="https://blog.rpsl.info/2012/06/7000-rps-na-nginx-achievement-unlocked/" rel="alternate"/><published>2012-06-03T14:48:00+04:00</published><updated>2012-06-03T14:48:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-06-03:/2012/06/7000-rps-na-nginx-achievement-unlocked/</id><content type="html">&lt;p&gt;Вчера, мой уютный сервачок подвергся очередному стресс тесту.&lt;/p&gt;
&lt;p&gt;Для тех кто не в теме, у меня тут еще живет сайт и форум &lt;a href="http://centrgroup.ru"&gt;группы CENTR&lt;/a&gt;, а вчера в Питере проходил концерт HipHop All Stars 2012. Организаторы повели себя достаточно круто и предложили всем заинтересованным смотреть прямую трансляцию с концерта. Мы стали одним из проектов, которые на главной странице разместили флеш плеер, по которому велась трансляция. Что бы людям не было скучно, подключил еще и комментарии от Вконтакте.&lt;/p&gt;
&lt;p&gt;Респект Вконтакту, в пиковые моменты комментарии в прямом эфире появлялись со скоростью 3-4 штуки в секунду. Всего за день на странице появилось примерно 15 000 комментариев.&lt;/p&gt;
&lt;p&gt;Когда я вечером зашел посмотреть модные графики, то был приятно удивлен. Пиковая нагрузка на MySQL была примерно 3000 rpm, на Nginx ~8000 rps.&lt;/p&gt;
&lt;p&gt;&lt;img alt="mysql" src="/images/f424/e13b/f424e13b883b2b8a599e61749d46b3b1.png"&gt;&lt;/p&gt;
&lt;p&gt;Cудя по логам, ни одного slow request не было, как и не было 404 и 50x страниц.&lt;/p&gt;
&lt;p&gt;Пользуясь случаем, еще раз рекламирую &lt;a href="https://firstvds.ru/?from=17604"&gt;свой хостинг&lt;/a&gt;, а тем кто станет моим рефералом обещаю оказывать всяческое содействие.&lt;/p&gt;</content><category term="Заметки"/><category term="centr"/><category term="mysql"/><category term="nginx"/></entry><entry><title>PHP Memoize</title><link href="https://blog.rpsl.info/2012/06/php-memoize/" rel="alternate"/><published>2012-06-01T11:41:00+04:00</published><updated>2012-06-01T11:41:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-06-01:/2012/06/php-memoize/</id><content type="html">&lt;p&gt;Вчера ради интереса пересматривал pecl каталог модулей для php, наткнулся на интересный модуль memoize. Вспомнил, что сам делал его реализацию на уровне php+memcached.&lt;/p&gt;
&lt;p&gt;Идея модуля крайне проста, у вас есть функция, результаты которой зависят исключительно от входных параметров, с помощью memoize можно закэшировать результаты выполнения и в последующие вызовы пересчет производиться не будет.&lt;/p&gt;
&lt;p&gt;Так же нужно понимать, что код будет выполнен только один раз, поэтому использование, например, sql запросов в ф-ции не допустимо. Недопустимо использование global и его аналогов &lt;code&gt;Static::$data&lt;/code&gt;, недопустимо использование ветвлений в зависимости от времени или окружения.&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;function my_expensive_function($x) {
    sleep(10);
    return $x . 'bar';
}

memoize('my_expensive_function');

// now calls to my_expensive_function() are cached by their arguments

echo my_expensive_function('foo'); // returns &amp;quot;foobar&amp;quot; in 10s
echo my_expensive_function('foo'); // returns &amp;quot;foobar&amp;quot; in 0.0001s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;В общем идея понятна, на уникальность никак не претендует, но свою нишу может занять. Зачем использовать свой велосипед?&lt;/p&gt;</content><category term="Заметки"/><category term="memcached"/><category term="memoize"/><category term="php"/></entry><entry><title>В уме</title><link href="https://blog.rpsl.info/2012/05/v-ume/" rel="alternate"/><published>2012-05-20T12:06:00+04:00</published><updated>2012-05-20T12:06:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-05-20:/2012/05/v-ume/</id><content type="html">&lt;p&gt;Я, вообще, редко занимаюсь рекламой софта, а тем более приложений для айфона, поэтому когда такое происходит, значит что продукт действительно хороший.&lt;/p&gt;
&lt;p&gt;&lt;img alt="v-ume" src="/images/0128/86b7/012886b773b5f93e8dd09a7c4f994d14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;В следующий раз, когда вы пройдете очередное обновление Angry Birds и полезете в AppStore в поисках новой убивалки времени, то вместо игрушек, поставьте себе это приложение. «В уме» — это сборник математических задач на устный счет. Задачи действительно интересные. И больше всего меня радует сам форм-фактор, да, это именно та игрушка с которой удобно работать, например, в транспорте. Нет нужды постоянно фокусироваться на экране, тут ничего не зависит от твоей ловкости и координации, только полезная разминка для мозгов.&lt;/p&gt;
&lt;p&gt;&lt;img alt="v-ume" src="/images/d1f4/00e6/d1f400e6c07d6e0fb523f1549e3a4a56.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="v-ume" src="/images/d5dc/36b8/d5dc36b8c9405e5d821fbfda76d20cac.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://itunes.apple.com/ru/app/v-ume/id482487701?mt=8"&gt;Ссылка в AppStore&lt;/a&gt;.&lt;/p&gt;</content><category term="Полезное"/><category term="app"/><category term="iphone"/></entry><entry><title>Варианты загрузки</title><link href="https://blog.rpsl.info/2012/05/varianty-zagruzki/" rel="alternate"/><published>2012-05-17T06:30:00+04:00</published><updated>2012-05-17T06:30:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-05-17:/2012/05/varianty-zagruzki/</id><content type="html">&lt;p&gt;Меня добивает на некоторых сайтах страницы загрузки софта. Сегодня с утра скачивал новый релиз &lt;a href="http://confluence.jetbrains.net/display/WI/Web+IDE+EAP"&gt;PhpStorm&lt;/a&gt;, обратите внимание на список.&lt;/p&gt;
&lt;p&gt;&lt;img alt="phpstorm-download" src="/images/82ee/d664/82eed664663b7d049a0e137db589d897.png"&gt;&lt;/p&gt;
&lt;p&gt;Windows, Mac OS X, Unix, ZIP. &lt;strong&gt;ZIP!&lt;/strong&gt;. Вот что там внутри? Под какую это платформу?&lt;/p&gt;
&lt;p&gt;&lt;img alt="phpstorm-download" src="/images/0101/7056/010170560cbbf87900de46e8f403f157.png"&gt;&lt;/p&gt;
&lt;p&gt;Внутри там, кстати, бинарники для windows&lt;/p&gt;</content><category term="Заметки"/><category term="design"/><category term="phpstorm"/></entry><entry><title>Вернемся к этому позже</title><link href="https://blog.rpsl.info/2012/05/vernemsya-k-e-tomu-pozzhe/" rel="alternate"/><published>2012-05-12T08:53:00+04:00</published><updated>2012-05-12T08:53:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-05-12:/2012/05/vernemsya-k-e-tomu-pozzhe/</id><content type="html">&lt;p&gt;Внезапно понял какой фичи мне не хватает в Gmail.&lt;/p&gt;
&lt;p&gt;Я очень хочу, что бы появился плагин, который позволяет отметить письмо
как "временно прочитанное". Например: приходит мне днем письмо с
напоминанием оплатить сервера или прочитать интересную статью, днем у
меня нету времени или возможности этим заниматься и к данным вещам нужно
будет вернуться вечером. Если оставить это письмо не прочитанным, чтобы
не забыть вечером на него среагировать, то оно будет целый день мешаться
на видном месте, почтовый клиент будет говорить что есть новые письма, а
иконка на айфоне будет надоедать цифрой в красном кружке. С другой
стороны, если отметить его как прочитанное, то велика вероятность забыть
о нем и оно потеряется в сотне других писем проходящих через мой ящик.&lt;/p&gt;
&lt;p&gt;Некоторые решают эту проблему с помощью хитрой системы ярлыков, другие
держат под рукой evernote или remember the milk, а мне лень отвлекаться
и делать столько действий, просто чтобы не забыть, уж лучше запомнить,
реально.&lt;/p&gt;
&lt;p&gt;Мне нужна простая кнопка, которая позволяет отметить письмо как
прочитанное, а через 6 или 12 часов сделает его снова не прочитанным, а
потом я смогу еще раз ее нажать и в итоге я не буду отвлекаться на новые
письма, никогда не потеряю их в груде других вещей и отреагирую, когда
будет время или посчитаю это нужным.&lt;/p&gt;
&lt;p&gt;Реально, эта фича спасла бы мир.&lt;/p&gt;</content><category term="Заметки"/><category term="gmail"/><category term="работа"/></entry><entry><title>Failed to validate oauth signature and token</title><link href="https://blog.rpsl.info/2012/02/failed-to-validate-oauth-signature-and-token/" rel="alternate"/><published>2012-02-07T18:05:00+04:00</published><updated>2012-02-07T18:05:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-02-07:/2012/02/failed-to-validate-oauth-signature-and-token/</id><content type="html">&lt;p&gt;На досуге, решил навоять один сервис, который тесно интегрирован с социальными сетями, в частности с твиттером. Во время работы, натолкнулся на интересную ошибку, в "некоторый момент", апи твиттера вылетает и начинает на любые запросы отдавать 401 ошибку. Не авторизован ты и все.&lt;/p&gt;
&lt;p&gt;Ну, а я чё? Я парень простой и решил идти по дебаг трейсу и разбираться в чем ошибка. Предварительно я конечно погуглил эту проблему и даже почитал автора либы которую я использую для связи с твиттером, но решений там не нашел.&lt;/p&gt;
&lt;p&gt;Тихо и не спеша, я просрал на это дело около трех вечеров, по 1-2 часа вечером выделяю на проекты. Что самое странное, апи то работало, то не работало и уловить динамику появления ошибки у меня не получалось.&lt;/p&gt;
&lt;p&gt;А решение, как обычно было рядом, проблема была в том, что я захлопывал крушку ноутбука :D Точнее так, сервисы я стараюсь сразу делать в родной среде, тобишь на линуксе, для этих делов, у меня есть virtualbox, в котором живут виртуалки с линуксом. Пока я работаю над одним сервисом, выключать виртуалки не приходится. Я их просто перетащил на другой рабочий стол и сижу себе спокойно по ssh, делаю tail -f на лог ошибок.&lt;/p&gt;
&lt;p&gt;Собственно, паттерн работы с ноутбуком, подразумевает что выключать его приходится редко, а засыпать часто. Ну и вот, после просыпания, в виртуалках время не синхронизировалось, а оставалось тем, в какой момент ноутбук засыпал. Из-за этого, при подписывание запросов, они подписывались не правильно и апи твиттера посылал меня на фиг считая жуликом.&lt;/p&gt;</content><category term="Полезное"/><category term="api"/><category term="Linux"/><category term="php"/><category term="twitter"/><category term="virtualbox"/></entry><entry><title>Про ценообразование при разработке сайтов.</title><link href="https://blog.rpsl.info/2012/01/pro-tsenoobrazovanie-pri-razrabotke-sajtov/" rel="alternate"/><published>2012-01-23T08:38:00+04:00</published><updated>2012-01-23T08:38:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-01-23:/2012/01/pro-tsenoobrazovanie-pri-razrabotke-sajtov/</id><content type="html">&lt;p&gt;Наткнулся на замечательный текст, от парня из
&lt;a href="http://owlbox.ru/"&gt;OwlBox&lt;/a&gt;. Хочу сохранить сюда на память, что бы
перечитывать когда в очередной раз мне предложат "помочь с сайтом" за
кегу пива.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Каждый раз, когда я начинал трогать мышку менее чем за 1000$ я потом
сильно жалел, не бывает "простеньких сайтов", аппетит приходит во
время еды, требования плывут, и все в рот имели итеративный подход,
если итерации сопровождаются соответствующими выплатами и этапами по
договору. Это даже с точки зрения бухгактерии не выгодно. Это нижний
порог. У хороших студий эта планка в 10 раз выше. На мой взгляд это
правильная политика. При скудном бюджете есть миллион разных способов
продвижения в интернете своих услух, не требующих сайта, работающего
на имидж или выполняющего роль инструмента продаж.&lt;br&gt;
 Если обсуждается сумма ниже 1000$ — мы друг–друга просто не поймем,
может быть кто–то другой поймет. От заказов нужно уметь оказываться.&lt;/p&gt;
&lt;p&gt;Имидж — это декларация того, что мы можем потратить приличные бабки за
хороший, годный, красивый и эффективный относительно целей заказчика
сайт. Возможны комбинации. Но ключевой момент — потратить бабки и
какие–то положительные свойства сайта. Я принципиально против того,
что унитаз, покрытый позолотой эквивалентен золотому унитазу и вообще
когда одно выдается за другое. Так как то, что король голый, как
правило, все равно очевидно. Ну если вы не являетесь говносыночком
пидораса из говноправительства, заказывающего сайт для говносколково.&lt;/p&gt;
&lt;p&gt;Средний ценник среднего проекта под ключ у меня получается в районе
$5000. Всякая верстка — это 1–15% от объема работ работы. Основной
объем падает на тестирование и удовлетворение меняющихся требований.
Пусть дизайн будет 1000$, программирование — 1000$ верстка и
изготовление графического контента — еще $1000. На пальцах — это
расклад при котором все участники процесса довольны.&lt;/p&gt;
&lt;p&gt;С огромной вероятностью стоимость проекта относительно объема работ в
итоге составит 5000–10000$ — косвенные расходы, непредвиденные
работы, тестирование, изменений, детализация требований,
дополнительные встречи с заказчиком, переговоры и т.д. Вот и
получилось x2.&lt;/p&gt;
&lt;p&gt;Если натягивается готовый шаблон на готовый движок, то все равно
внезапно окажется что у нас не два уровня иерархии разделов, а
все–таки 3, секретарша не справляется с wysywig редактором, гамма
должна быть несколько светлее, внезапно образуется еще 200 единиц
графического контента, шаблон выглядит как полное говно в IE6, которым
пользуется заказчик из–за своей внутрикорпоративной политики и т.д.&lt;/p&gt;
&lt;p&gt;Если вы не поняли — именно на это говно уйдет половина вашей работы.
Если вам заказывают сайт по вашей оценке на 10k$, но бюджет заказчика
позволяет всего лишь 7,5k$ а сам он видел что "что–то такое же"
вообще делали за штуку и считает что за такие бабки получит священный
грааль с элексиром вечной молодости, то это не клевый крупный заказ.
Это плохая мерзкая жопа в которую вы гарантированно влезете. К тому
же, с большой вероятностью, вы и объем работ оценили неправильно и он
не на 10k$, а на 15k$ или больше.&lt;/p&gt;
&lt;p&gt;Другой взгляд: если заказчик хочет хоть как–то заниматься
продвижением, то либо сам сайт или его услуги должны быть просто
замечательными, а это либо дорого либо сложно, соответственно, либо,
если, это хоть сколько ни будь конкурентный рынок и область
продвижения, стоимость продвижения будет составлять большое количество
штук баксов. Очень странно, если конечная точка, куда приходит
посетитель, будет стоит 100$&lt;/p&gt;
&lt;p&gt;Кто в итоге будет в пролете — выбирайте сами. Приведенные в качестве
примера суммы можно уменьшить или увеличить, суть при этом не очень
меняется.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Полезное"/><category term="работа"/></entry><entry><title>Picasa vs. Flickr</title><link href="https://blog.rpsl.info/2012/01/picasa-vs-flickr/" rel="alternate"/><published>2012-01-22T20:06:00+04:00</published><updated>2012-01-22T20:06:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2012-01-22:/2012/01/picasa-vs-flickr/</id><content type="html">&lt;p&gt;Опять я оказался в ситуации, когда являюсь не типичным пользователем. На
этот раз проблема коснулась фотографий. Ситуация следующая: у меня есть
оплаченный google storage на 20 или 25 гб, есть огромное колличество
фотографий в пикасе, есть много новых фотографий которые я хочу залить в
хранилища, знать что они в безопастности и иметь возмножность показывать
их друзьям и родственникам, но у меня нету возможности.&lt;/p&gt;
&lt;p&gt;Это вечная проблема, когда есть несколько сервисов и каждый из них по
своему хорош, но приятных фич из второго в нем нету.&lt;/p&gt;
&lt;p&gt;Наверно тут стоит бросить камень в сторону Aperture, которым я пользуюсь
как инструментом для обработки и каталогизации фотографий. Для меня
всегда было странно, что подобные, крупные, программы или сервисы не
делают все возможное для расширения. Да, безусловно, можно установить
PicasaUploader, который позволит загружать выбранные фотографии в
пикасу, но мне это не нравится. Я хочу, что-бы можно было нажать
кнопочку "Sync this gallery" и далее она будет автоматически
синхронизироваться с сервисом, а именно вносить изменения в фотографии
если я сделал их у себя, обновлять/удалять определенные фото ну и
остальные приятныем мелочи.&lt;/p&gt;
&lt;p&gt;Для меня не понятно, почему поддержка flickr есть из коробки, а picasa
нету.&lt;/p&gt;
&lt;p&gt;Я полез искать информацию, как написать собственны плагин, который будет
делать все что мне необходимо, думаю ну ладно, если готового нету, то за
пару вечеров напишу свой, пусть и костыль, но который будет работать.
Нет, не нашел. Может искал плохо, но все равно информации мало.&lt;/p&gt;
&lt;p&gt;К слову говоря, про Aperture, для меня остается загадкой, почему в 2012
году, они не научились делать некоторые фотографии скрытыми. Нельзя
сделать как в пикасе, отметить несколько фотографий в альбоме как
скрытые и их показ будет возможен только после ввода пароля.&lt;/p&gt;
&lt;p&gt;Что делать в итоге - не решил. Ясно, что использовать пикасу, по
определенным обстоятельствам, у меня не получится, но и пользоваться
фликром желания тоже нету. Хотя, видимо это вопрос времени и если я не
научусь делать свои плагины, то сдамся и начну переезд на фликр.&lt;/p&gt;</content><category term="Заметки"/><category term="aperture"/><category term="flickr"/><category term="picasa"/><category term="Фото"/></entry><entry><title>PHP - fastcgi_finish_request</title><link href="https://blog.rpsl.info/2011/09/php-fastcgi_finish_request/" rel="alternate"/><published>2011-09-20T07:49:00+04:00</published><updated>2011-09-20T07:49:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-09-20:/2011/09/php-fastcgi_finish_request/</id><content type="html">&lt;p&gt;А вы знаете про эту замечательную функцию?&lt;/p&gt;
&lt;p&gt;Если кратко, то используя ее можно заставить приложение отдавать контент пользователю гораздо быстрее, разделяя логику приложения на "это необходимо пользователю" и "это пользователю не очень важно". &lt;/p&gt;
&lt;p&gt;Когда php работает в fastcgi режиме, например, в популярной связке nginx+php-fcgi, у вас появляется возможность сначала посчитать все данные которые необходимы что бы отдать пользователю страницу, а уже потом, когда страница отдана и nginx отдает ее клиенту, можно выполнить все остальные действия, например отправить письма или обновить кэш или запустить некие
механизмы очистки.&lt;/p&gt;
&lt;p&gt;Нужно отдельно упомянуть, что для правильной работы, fastcgi_finish_request должен запускать после &lt;code&gt;session_write_close&lt;/code&gt; и &lt;code&gt;ob_*&lt;/code&gt; функций.&lt;/p&gt;
&lt;p&gt;Простой пример:&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;echo 'Hello word';

// В данной реализации, данные отдадутся в клиенту сразу,
// а если закомментировать вызов fastcgi_finish_request(),
// клиент будет ждать 10 секунд, до того, как получит ответ.
fastcgi_finish_request();

sleep(10);
&lt;/code&gt;&lt;/pre&gt;</content><category term="Полезное"/><category term="php"/><category term="nginx"/></entry><entry><title>9 million hits/day with 120 megs RAM</title><link href="https://blog.rpsl.info/2011/09/9-million-hits-day-with-120-megs-ram/" rel="alternate"/><published>2011-09-13T18:55:00+04:00</published><updated>2011-09-13T18:55:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-09-13:/2011/09/9-million-hits-day-with-120-megs-ram/</id><content type="html">&lt;p&gt;Оставлю у себя в закладках.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;After checking this for about 9 months, I can tell you this almost always reads that number: 300 microseconds. This is about one third the time a camera flash illuminates. That’s, well, pretty quick. When I started, my software was taking about 0.25 seconds (250 000 microseconds) to produce the front page of my website. I needed to improve performance by over 800x.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://tumbledry.org/2011/08/31/9_million_hits_day_with_120"&gt;Далее&lt;/a&gt;&lt;/p&gt;</content><category term="Полезное"/><category term="memcache"/><category term="nginx"/><category term="php"/></entry><entry><title>Node Saver</title><link href="https://blog.rpsl.info/2011/08/node-saver/" rel="alternate"/><published>2011-08-30T00:00:00+04:00</published><updated>2011-08-30T00:00:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-08-30:/2011/08/node-saver/</id><content type="html">&lt;p&gt;Примерно в марте месяце, пока мне было скучно и хотелось поиграться с MongoDB, я решил сделать свой аналог замечательного сайта &lt;a href="http://www.peeep.us/"&gt;peeep.us&lt;/a&gt;. Дело в том, что peeep.us хоть и жутко удобный, но не совсем безопастный, добавленные туда страницы потом хрен удалишь и самое ужасное, он открыт к индексации. Кстати все кто хочет почитать лепру но не имеют туда доступа могут ..., ну короче намек поняли, все как с мегафоном.&lt;/p&gt;
&lt;p&gt;&lt;img alt="save.rpsl.info" src="/images/bdfa/0e20/bdfa0e2024277d599aca335979965960.png"&gt;&lt;/p&gt;
&lt;p&gt;Первую версию, которая на момент публикации поста, живет на &lt;a href="http://save.rpsl.info"&gt;save.rpsl.info&lt;/a&gt; я написал часа за четыре, из них примерно два часа я искал у кого своровать дизайн :D&lt;/p&gt;
&lt;p&gt;После этого, я решил что связка php и mongodb для такой микрозадачи не нужна и решил переписать ее на node.js. За несколько вечеров я разобрался и сделал и то, что хотел. В конечном варианте полностью отказалася от MongoDB и заменил его на Memcached. Зачем мне тут монго? Данные я кладу на несколько дней, данных мало, заодно и решится вопрос с их очисткой, а то, что не надежно, ну и фиг с ним. Ничего ценного там хранить смысла нету, а статистика ребута memcached'a на серваке говорит о том, что если раз в полгода я и потеряю данные, то ничего страшного не произойдет.&lt;/p&gt;
&lt;p&gt;И все бы было хорошо, но я не решил главную проблему - сохранение работает только для открытых источников, как передавать страницу с сайта, которая закрыта basic auth я не придумал. У меня есть конечнонесколько идей, но проверять их мне слишком лениво. Вторая проблема в том, что мне не хочется из-за этой мелочи поднимать на боевом серваке Node.JS, в какой-то момент пробовал взять виртуалку у clodo.ru, заодно потестировать его, но тесты оказались плачевными, потом хотел у alice2k стрельнуть кусочек vds, но уехал в Испанию и снова забил на это.&lt;/p&gt;
&lt;p&gt;В итоге с марта месяца, у меня на рабочем столе лежит папка node, которую я все время хочу удалить и в последний момент вспоминаю, что этого делать не стоит. Несколько раз приходилось доставать из бэкапа.&lt;/p&gt;
&lt;p&gt;Сегодня мне захотелось ее удалить, поэтому я решил выложить сорцы на github&lt;/p&gt;
&lt;p&gt;В общем форкайте меня, все дела. &lt;a href="https://github.com/Rpsl/node-saver"&gt;https://github.com/Rpsl/node-saver&lt;/a&gt;&lt;/p&gt;</content><category term="Полезное"/><category term="memcache"/><category term="mongodb"/><category term="nodejs"/><category term="php"/></entry><entry><title>Проверка multi_query в mysqli</title><link href="https://blog.rpsl.info/2011/08/proverka-multi_query-v-mysqli/" rel="alternate"/><published>2011-08-29T08:06:00+04:00</published><updated>2011-08-29T08:06:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-08-29:/2011/08/proverka-multi_query-v-mysqli/</id><content type="html">&lt;p&gt;Увидел сегодня красивое решение проверки выполнения &lt;a href="http://php.net/manual/en/mysqli.multi-query.php"&gt;мультизапроса в mysqli&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Если кто не в курсе, то можно сформировать в одну строку кучу запросов, разделяемых точкой с запятой, а потом отдать это на выполнение. Так вот проверять ошибки можно разными способами, а можно просто в конец добавить некий абстрактный SELECT 'complete'. Это подходит для запросов типа INSERT, DELETE, UPDATE.&lt;/p&gt;
&lt;p&gt;Eще, у меня в примере указан не прямой вызов multi_query, а обертка для запросов, думаю что это и зачем вам объяснять не нужно.&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;if ( $DB()-&amp;gt;multi(&amp;quot;
    UPDATE someshit SET bla=bla-1 WHERE id='%d';
    DELETE FROM someshit WHERE category='%d';
    DELETE FROM someshit WHERE id='%d';
    SELECT 'complete';&amp;quot;,
    $id, $category, $id) != &amp;quot;complete&amp;quot; )
{
    self::$resultCode = self::DB_ERROR;
    return false;
}
self::$resultCode = self::SUCCESS;
&lt;/code&gt;&lt;/pre&gt;</content><category term="Полезное"/><category term="mysql"/><category term="php"/></entry><entry><title>Обновил NAS</title><link href="https://blog.rpsl.info/2011/08/obnovil-nas/" rel="alternate"/><published>2011-08-28T17:28:00+04:00</published><updated>2011-08-28T17:28:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-08-28:/2011/08/obnovil-nas/</id><content type="html">&lt;p&gt;&lt;img alt="nas" src="/images/fe8f/3ec0/fe8f3ec080f05fb60b1736bd0a1db727.jpeg"&gt;&lt;/p&gt;
&lt;p&gt;У меня дома, уже почти год живет &lt;a href="http://blog.rpsl.info/2010/10/byudzhetnyjj-nas/"&gt;ReadyNAS Duo&lt;/a&gt;, вчера мне было скучно и я подумал, что будет неплохо обновить его.&lt;/p&gt;
&lt;p&gt;Изначально планировал купить в него второй жесткий диск, т.к. с момента покупки, в нем живет только один seagate на полтора террабайта и бэкапам time machine, в последнее время, там очень тесно. Хотел купить второй такой-же, но почитав документацию, обнаружил, что покупка второго hdd не позволит увелить общий объем устройства, а позволит сделать только raid. Так как raid на 1.5 террабайта мне совсем не нужен, я решил отказаться от этой идеи и потом, когда будут ресурсы, купить жесткий диск от 3 террабайт.&lt;/p&gt;
&lt;p&gt;Таким образом, из возможного обновления, мне оставалась только оперативка. По спецификации, в него можно засунуть до 1гб оперативной памяти, SODIMM на 200pin. В целом, мне вполне хорошо жилось и на 256. Nas тихо стоит в шкафу, качает торренты, принимает бэкапы и ничего больше не делает, но когда кол-во активных торрентов переваливает 10-15, то веб-интерфейс начинает жутко тупить.&lt;/p&gt;
&lt;p&gt;Почитав несколько заметок и упоминаний на сайте производителя, что этому величеству не всякая память подходит, остановил свой выбор на "&lt;a href="http://market.yandex.ru/model.xml?modelid=6045125&amp;amp;hid=191211&amp;amp;text=CT12864X40B&amp;amp;srnum=3"&gt;Crucial CT12864X40B&lt;/a&gt;". 
Заказал, проехался до магазина, привез, запустил.&lt;/p&gt;
&lt;p&gt;Вообще я не ожидал сильных изменений, да и на глаз ничего нового не увидел. Работать, вроде, стал шустрее, торренты качаются, time machine стала работать быстрее, но т.к. никаких тестот я не проводил, мне кажется все эти улучшения &lt;a href="http://ru.wikipedia.org/wiki/%D0%9F%D0%BB%D0%B0%D1%86%D0%B5%D0%B1%D0%BE"&gt;эффект плацебо&lt;/a&gt;.&lt;/p&gt;</content><category term="Заметки"/><category term="nas"/><category term="netgear"/></entry><entry><title>Scrollbar и центрирование</title><link href="https://blog.rpsl.info/2011/08/scrollbar-i-centrirovanie/" rel="alternate"/><published>2011-08-15T13:45:00+04:00</published><updated>2011-08-15T13:45:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-08-15:/2011/08/scrollbar-i-centrirovanie/</id><content type="html">&lt;p&gt;Столкнулся сегодня с косяком, допустим есть однотипные страницы, на которых основной контент автоматически центрируется.&lt;/p&gt;
&lt;pre&gt;&lt;code class="css"&gt;#content {
   margin: 0 auto;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Так вот, при загрузке страницы, до момента пока основной контент еще не подгрузился, а шапка уже появилась, то scroll'a справа нету, как только контент подгружается, то сбоку появляется scrollbar и весь контент из-за этого прыгает на несколько пикселей влево. В целом этот баг можно решить, если задать основному блоку min-height, но это не универсальное решение. Тем более это может вызывать косяки, если вдруг окажется, что контента у нас на странице нету, будет большой вентум.&lt;/p&gt;
&lt;p&gt;Думали-думали, не знали что делать, в итоге решили сделать как у fb, что бы скроллбар был всегда на странице, не важно активный или нет.&lt;/p&gt;
&lt;pre&gt;&lt;code class="css"&gt;body {
   overflow-y: scroll;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Возможно это не самое лучшее решение, но гарантировано убирает проблему с прыганьем контента и избавляет от вероятности появления вентумов на странице.&lt;/p&gt;
&lt;p&gt;Может расскажите другие способы решения?&lt;/p&gt;</content><category term="Заметки"/><category term="css"/></entry><entry><title>PHP - Переворот числа</title><link href="https://blog.rpsl.info/2011/08/php-perevorot-chisla/" rel="alternate"/><published>2011-08-09T22:14:00+04:00</published><updated>2011-08-09T22:14:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-08-09:/2011/08/php-perevorot-chisla/</id><content type="html">&lt;p&gt;Видать &lt;a href="http://dotzero.ru/"&gt;dotZero&lt;/a&gt; почувствовал, что я уже устал переворачивать строки, поэтому подкинул сегодня задачу, которую я до этого не решал. Днем разбираться с ней было некогда, а вечером, решил все-таки уделить ей внимание и разобраться как это работает.&lt;/p&gt;
&lt;p&gt;Задача простая. Перевернуть любое целое число используя только математические операторы. Было 5432, должно стать 2345.&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;function reverseInt( $a )
{
    $tmp = $a;
    $return = 0;

    while( $tmp &amp;gt; 0 )
    {
        /*

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

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

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

        */

        $return = ( $return * 10 ) + ( $tmp % 10 );

        /*
        Каждый раз делим исходное число на 10, что-бы обойти каждый его разряд.
        */

        $tmp = intval( $tmp / 10 );
    }

    return $return ;
}

$foo = 123456789;

echo 'Start: ' . $foo . &amp;quot;\n&amp;quot;;

$bar = reverseInt( $foo );

echo 'End: ' . $bar . &amp;quot;\n&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Как видно, все достаточно просто, нужно просто понять как это работает. Теперь хочу найти все варианты с решением этой задачи, думаю что если сделать это с помощью битовых операций получится еще быстрее и красивее.&lt;/p&gt;</content><category term="Полезное"/><category term="php"/><category term="работа"/></entry><entry><title>Request uri в nginx</title><link href="https://blog.rpsl.info/2011/08/request-uri-v-nginx/" rel="alternate"/><published>2011-08-09T16:28:00+04:00</published><updated>2011-08-09T16:28:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-08-09:/2011/08/request-uri-v-nginx/</id><content type="html">&lt;p&gt;Второй раз натыкаюсь.&lt;/p&gt;
&lt;p&gt;В первый раз я не мог понять почему на php скрипт приходил GET запрос, хотя я отправлял POST и при этом массив был пустой, но при просмотре &lt;code&gt;php://input&lt;/code&gt; нужные мне переменные были видны.&lt;/p&gt;
&lt;p&gt;Тут ситуация была простой, но не очевидной, при запросе, я не попадал в нужный location и nginx успешно отправлял меня на @404, в следствие чего, php получал уже GET запрос.&lt;/p&gt;
&lt;p&gt;Сейчас, эта фича, помогает работать с ssi включениями, т.к. при сборе "блоков" страницы у нас есть возможность получить оригинальный URL и добраться до нужных нам GET параметров.&lt;/p&gt;
&lt;p&gt;Из доков nginx:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;$request_uri&lt;/code&gt; - эта переменная равна полному первоначальному URI вместе с аргументами;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Пример, вывод $_SERVER из подключенного ssi блока:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[QUERY_STRING] =&amp;gt; do=search&amp;amp;action=search  &lt;/li&gt;
&lt;li&gt;[REQUEST_URI] =&amp;gt; /?q=творог&amp;amp;lr=213&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Что бы получить нужный нам фэйковый $_GET, можно сделать что-нибудь типо этого:&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;parse_str( str_replace('/?', '', getenv('REQUEST_URI') ), $original_get );
&lt;/code&gt;&lt;/pre&gt;</content><category term="Заметки"/><category term="nginx"/><category term="php"/></entry><entry><title>Хитрожопые инкорпорейтед</title><link href="https://blog.rpsl.info/2011/08/khitrozhopye-inkorporejjted/" rel="alternate"/><published>2011-08-09T14:23:00+04:00</published><updated>2011-08-09T14:23:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-08-09:/2011/08/khitrozhopye-inkorporejjted/</id><content type="html">&lt;p&gt;Наткнулся сегодня на еще одно решение задачи, про переворот строки.
Вспомнил этот комикс.&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;$a = 'abcdefgh';
// Напишите здесь недостающий код,
// чтобы результатом работы скрипта
// была строка $a, повернутая наоборот
echo $a;
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class="php"&gt;$a = 'abcdefgh';
$a='hgfedcba';
echo $a;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img alt="welcome aboard" src="/images/b38c/9772/b38c97727d3bb46af322678755acb41c.png"&gt;&lt;/p&gt;</content><category term="Заметки"/><category term="php"/><category term="работа"/></entry><entry><title>Про блоги</title><link href="https://blog.rpsl.info/2011/08/pro-blogi/" rel="alternate"/><published>2011-08-03T23:48:00+04:00</published><updated>2011-08-03T23:48:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-08-03:/2011/08/pro-blogi/</id><content type="html">&lt;p&gt;Давно уже в голове крутится мысль, что современные блог движки, они
такие сухие, безидейные, не вдохновляющие. Вот тот-же самый wordpress,
есть он, у меня на нем блог работает, при этом я 100500 раз переезжал на
другие движки и пробовал вести блог на них, но все равно возвращался
обратно. Они не вдохновляют на то, что-бы в них писать. Тем на которые
можно и хочется написать много, а желания нету. Это не потому что я
такой ленивый, а потому что написать новый пост превращается в
тягомотину.&lt;/p&gt;
&lt;p&gt;Когда-то давно, когда у меня не было стандалон блога, я тусил в жж. В
2004 году в жж было интересно, а сейчас он стал убогим, политизированным
уг.&lt;/p&gt;
&lt;p&gt;Идея написать свой блог движег не покидает меня уже миллион лет, но это
такая морока, что мне не хочется этим заниматься. Читая интернеты,
обнаружил что Бирман выложил очередной релиз своего блог
&lt;a href="http://blogengine.ru"&gt;движка&lt;/a&gt;. Снаружи очень красивая, внутри какой-то
дикий пиздец творится. Я всегда был уверен, что дизайнеры не должны
заниматься программированием, а программисты дизайном ( именно поэтому,
в моем блоге, такой убогий диз ). Но учитывая, что Эгея носит еще статус
беты, я не буду выражать свое "фи", ведь если не заглядывать под капот,
то это действительно очень красивый и лаконичный продукт.&lt;/p&gt;
&lt;p&gt;Вот честно, я заинсталил его себе и даже тешил себя мыслями, что смогу
перенести свой блог туда, мол буду писать там, но две вещи меня держат:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;​1) Все ссылки на страницы моего блога поломаются, но это не проблема,
это решаемо.&lt;/p&gt;
&lt;p&gt;2) Оформление постов в данном движке происходит с помощью wiki
разметки и соответсвенно все посты едут, полез в гугл поискать
механизм который умеет конвертировать html в wiki формат, но
адекватных механизмов не нашел.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;На этом и забил.&lt;/p&gt;
&lt;p&gt;Но все же мысль избавить от Wordpress'a не дает мне покоя. Он меня жутко
достал. Он медленный. Он уродует контент. #hate, #hate.&lt;/p&gt;
&lt;p&gt;Мне тут подсказывали еще попробовать LiveStreet в качестве личного
блога. Но спасибо, я на LiveStreet сейчас веду один проект, в основном
&lt;a href="http://ihiphop.ru"&gt;клипы хип-хоп тематики&lt;/a&gt; и затрахался с ним до
глубины души. Я не знаю что в головах у авторов, но внутреннее
устройство движка это такой лютый бред. Навернуть такое кол-во ООП на
единицу кода и при этом суметь использовать все анти-паттерны
визуального оформления кода, это надо быть действительно смелым и
уверенным в себе человеком.&lt;/p&gt;
&lt;p&gt;Вот опять я всех обругал, а ведь не хотел. ((&lt;/p&gt;</content><category term="Заметки"/><category term="blog"/><category term="e2"/><category term="php"/><category term="wordpress"/></entry><entry><title>Про отображение ошибок</title><link href="https://blog.rpsl.info/2011/04/pro-otobrazhenie-oshibok/" rel="alternate"/><published>2011-04-22T22:38:00+04:00</published><updated>2011-04-22T22:38:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-04-22:/2011/04/pro-otobrazhenie-oshibok/</id><content type="html">&lt;p&gt;Меня жутко, прямо до костей, бесят люди, которые делают логику сайта такой, что в случае возникновения ошибки на сайте, тебя перебрасывает на страницу вида&lt;/p&gt;
&lt;p&gt;http://site.ru/wow/it/is/error/page/&lt;/p&gt;
&lt;p&gt;Ну реально полный кретинизм.&lt;/p&gt;
&lt;p&gt;Ок, допустим произошла ошибка, допустим база отвалилась и сайт не может нам ничего показать кроме ошибки. Ну так покажи ошибку, а не перебрасывай меня на другую страницу. Ведь у меня нет возможности обновить страницу с ошибкой через 5 минут и увидеть интересный мне контент.&lt;/p&gt;
&lt;p&gt;Прям вот ваще. Если у вас так - то я вас ненавижу.&lt;/p&gt;</content><category term="Заметки"/><category term="разработка"/></entry><entry><title>Самое простое ускорение сайта</title><link href="https://blog.rpsl.info/2011/04/samoe-prostoe-uskorenie-sajjta/" rel="alternate"/><published>2011-04-15T15:00:00+04:00</published><updated>2011-04-15T15:00:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-04-15:/2011/04/samoe-prostoe-uskorenie-sajjta/</id><content type="html">&lt;p&gt;В итернете есть куча более правильных статей на тему организации дружбы между nginx и memcache. Я же, покажу самый простой пример, который можно сделать за пять - десять минут и который поможет разгрузить основные страницы вашего сайта.&lt;/p&gt;
&lt;p&gt;Что я предлагаю ?&lt;/p&gt;
&lt;p&gt;Давайте засунем главную страницу сайта, в memcache, и настроим nginx что бы он отдавал ее прямо из memcache не обращаясь к интерпретаторам. Будем класть раз в минуту сроком жизни на 60 секунд. Стоит понимать, что данный способ нужно дорабатывать, если у вас на страницах используется динамичные данные, то есть данный способ актуален только для "гостей" сайта, благо nginx умеет работать и cookie.&lt;/p&gt;
&lt;p&gt;Пример настройки nginx'a&lt;/p&gt;
&lt;pre&gt;&lt;code class="conf"&gt;location / {

    default_type    text/html;

    if ( $request_uri = '/')
    {
        set $memcached_key &amp;quot;index_page&amp;quot;;
        memcached_pass 127.0.0.1:11211;

        error_page 404 503 = @fallback;
    }

    error_page 404 = @fallback;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Пример cron скрипта, который можно повесить на выполнение.&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;error_reporting(E_ALL);
ini_set('display_errors', 1);

if( class_exists('Memcache', FALSE))
{
    $mem = new Memcache;

    $mem-&amp;gt;connect('localhost', 11211);

    $html = file_get_contents('http://blog.rpsl.info/?asd');

    if(!empty( $html ) )
    {
        //$mem-&amp;gt;delete('index_page', 0);
        $mem-&amp;gt;set('index_page', $html, 0, 60 );

        //echo $html;
    }
}
else
{
    echo 'no memcache';
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Стоит обязательно обратить внимание, что бы запрашивая урл страницы, вы точно получали свежий ответ, т.к. возможна ситуация, когда произойдет зацикливание и ваш скрипт будет брать страницу из кэша и класть ее обратно в кэш.&lt;/p&gt;</content><category term="Полезное"/><category term="memcache"/><category term="nginx"/><category term="web"/><category term="разработка"/></entry><entry><title>Dive into Python :)</title><link href="https://blog.rpsl.info/2011/04/dive-into-python/" rel="alternate"/><published>2011-04-14T21:11:00+04:00</published><updated>2011-04-14T21:11:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-04-14:/2011/04/dive-into-python/</id><content type="html">&lt;p&gt;Шесть месяцев назад я нашёл в Интернете книжку "Dive into Python".
Странная книжка, толстая, да ещё на не русском языке. Усердно прочитал
её, методично и вдумываясь, но таки ничего и не понял. Но что–то не
отпускало меня — я пошёл на python.org и стал изучать стандартную
библиотеку, старательно, скрупулезно, от корки до корки. Гугля примеры
кода, я наткнулся на пост в блоге одного гуру, где было написано про
PEP8. То, что рассказывал этот умудрённый опытом кодер, настолько
впечатлило меня, что я словно в припадке безумия бросился зубрить эту
конвенцию по написанию питоньего кода. У меня тряслись руки, по телу
прокатывали волны возбуждения, я, можно сказать, бился в экстазе всё это
время — и теперь могу процитировать наизусть любой пункт, даже если меня
разбудить посреди глубокой ночи.&lt;/p&gt;
&lt;p&gt;Новые знания окрыляли меня, я бросился писать (что бы вы подумали?)
очередную имиджборду. Я не писал раньше имиджборд, эта была моей первой.
По пути пришлось освоить азы вёрстки на html и css, но там всё оказалось
совсем не сложно.&lt;/p&gt;
&lt;p&gt;Я плавно двигался вперёд, наращивая функционал. И знаете что? Я упёрся в
недостаток производительности. Ну, так мне показалось. Я делал замеры,
устранял места с тяжёлым кодом. Тысячи раз запускал ab, но так и не
сумел перейти порог в 300 запросов в секунду. Я как–то ожидал большего и
был немного разочарован.&lt;/p&gt;
&lt;p&gt;Гугл, снова гугл. Десятки статей и тем на форуме… Довольно быстро я
заметил, что люди часто пишут про какие–то "асинхронные веб–сервера".
Часто встречались названия Tornado и Gevent. Я прочитал про них
подробнее — и был просто ошеломлён. Как мне это раньше не приходило в
голову?! Это же, это просто гениально, чёрт меня побери!&lt;/p&gt;
&lt;p&gt;Исходники в ведро, всё переписать! Меня переполняло новое знание, поток
мыслей ровно ложился в строчки кода. Я просто не мог остановиться. Чашка
кофе… Ещё чашка… Мой небольшой кусочек софта приобретал кристальную
чистоту, я смертельно устал, но продолжал в умилении полировать его
зудящими руками, нанося последние штрихи.&lt;/p&gt;
&lt;p&gt;Пять тысяч. Я получил производительность в пять тысяч запросов в
секунду. В ту ночь я так и не смог заснуть.&lt;/p&gt;
&lt;p&gt;Увлекательнейший мир хай–лоада открылся передо мной. Позже я изучил ещё
много классных вещей типа сверх-быстрых асинхронных key–value–хранилищ,
или, например, такого необычного подхода к обработке данных, как
map–reduce.&lt;/p&gt;
&lt;p&gt;Это уже был другой я, новый, обновлённый. С незашоренным взглядом, с
жаждой новых знаний и незнакомых концепций. Я летел вперёд, оставляя за
спиной ступень за ступенью.&lt;/p&gt;
&lt;p&gt;За пол–года я сменил несколько мест работы, и моя зарплата взлетела до
умопомрачительных сумм. Сотни замечательных мест открыли передо мной
свои двери. Любые, самые изысканные девушки проявляли просто чудеса
изобретательности, чтобы находиться рядом со мной.&lt;/p&gt;
&lt;p&gt;А ещё, я никогда не забуду тот момент, когда на одной из конференций я
впервые в жизни поймал на себе завистливый взгляд. Это был взгляд
какого–то сливающегося с толпой неудачника, взгляд преисполненный
ненависти, презрения и желчного вожделения, направленного на мой Олимп.
Наверное, он всю свою никчёмную жизнь писал на каком–нибудь си–шарпе или
там на джаве, проводя долгие дни в одиночестве. И теперь начинал
подсознательно догадываться, что долгие годы безуспешно пытался
построить замок из навоза.&lt;/p&gt;</content><category term="Полезное"/><category term="python"/><category term="работа"/><category term="разработка"/></entry><entry><title>Как разрабатывают ПО для шатлов</title><link href="https://blog.rpsl.info/2011/03/kak-razrabatyvayut-po-dlya-shatlov/" rel="alternate"/><published>2011-03-26T12:48:00+03:00</published><updated>2011-03-26T12:48:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-03-26:/2011/03/kak-razrabatyvayut-po-dlya-shatlov/</id><summary type="html">&lt;p&gt;Утром кто-то в твиттере скинул ссылку на статью, рассказ о том, как разрабатывают ПО для шатлов. Для расширения кругозора полезно почитать.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;В то время, когда 120-ти тонный шаттл стоит, окруженный почти 4-мя
миллионами фунтов ракетного топлива, источая ядовитые пары, с явным
желанием бросить вызов земной гравитации; его бортовые компьютеры
получают команду. Четыре идентичных компьютера, работающие под
управлением идентичного ПО, собирают информацию из тысяч датчиков,
принимая сотни миллисекундных решений, утверждая каждое решение,
сверяясь друг с другом 250 раз в секунду. Пятый компьютер, с другим
ПО, готов взять управление на себя в случае сбоя остальных четырех.&lt;/p&gt;
&lt;p&gt;В момент времени -6.6 секунды, если давления, насосы и температуры в
норме, компьютеры дают приказ зажечь главные двигатели шаттла – каждый
из трех двигателей вспыхивает ровно через 160 миллисекунд, тонны
сверхохлажденного жидкого топлива попадают в камеры сгорания, корабль
дрожит на своей пусковой площадке, удерживаемый на земле только
креплениями. Когда главные двигатели достигают силы тяги в миллион
фунтов, их выхлопы превращаются в голубые бриллианты пламени.&lt;/p&gt;
&lt;p&gt;Тогда и только тогда, в момент времени -0 секунд, если компьютеры
убедились, что двигатели работают правильно, они дают приказ поджечь
массивные ракетные ускорители. Менее чем за секунду, они развивают
силу тяги в 6.6 миллионов фунтов. И именно в этот момент, компьютер
отдает приказ взрывчатым креплениям взорваться, и корабль весом 4.5
миллионов фунтов величественно поднимается над стартовой площадкой.&lt;/p&gt;
&lt;p&gt;Это удивительное проявление доблести оборудования. Но ни один человек
не нажимает на кнопки, чтобы это произошло, ни один астронавт не
манипулирует джойстиком, чтобы вывести шаттл на орбиту.&lt;/p&gt;
&lt;/blockquote&gt;
</summary><content type="html">&lt;p&gt;Утром кто-то в твиттере скинул ссылку на статью, рассказ о том, как разрабатывают ПО для шатлов. Для расширения кругозора полезно почитать.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;В то время, когда 120-ти тонный шаттл стоит, окруженный почти 4-мя
миллионами фунтов ракетного топлива, источая ядовитые пары, с явным
желанием бросить вызов земной гравитации; его бортовые компьютеры
получают команду. Четыре идентичных компьютера, работающие под
управлением идентичного ПО, собирают информацию из тысяч датчиков,
принимая сотни миллисекундных решений, утверждая каждое решение,
сверяясь друг с другом 250 раз в секунду. Пятый компьютер, с другим
ПО, готов взять управление на себя в случае сбоя остальных четырех.&lt;/p&gt;
&lt;p&gt;В момент времени -6.6 секунды, если давления, насосы и температуры в
норме, компьютеры дают приказ зажечь главные двигатели шаттла – каждый
из трех двигателей вспыхивает ровно через 160 миллисекунд, тонны
сверхохлажденного жидкого топлива попадают в камеры сгорания, корабль
дрожит на своей пусковой площадке, удерживаемый на земле только
креплениями. Когда главные двигатели достигают силы тяги в миллион
фунтов, их выхлопы превращаются в голубые бриллианты пламени.&lt;/p&gt;
&lt;p&gt;Тогда и только тогда, в момент времени -0 секунд, если компьютеры
убедились, что двигатели работают правильно, они дают приказ поджечь
массивные ракетные ускорители. Менее чем за секунду, они развивают
силу тяги в 6.6 миллионов фунтов. И именно в этот момент, компьютер
отдает приказ взрывчатым креплениям взорваться, и корабль весом 4.5
миллионов фунтов величественно поднимается над стартовой площадкой.&lt;/p&gt;
&lt;p&gt;Это удивительное проявление доблести оборудования. Но ни один человек
не нажимает на кнопки, чтобы это произошло, ни один астронавт не
манипулирует джойстиком, чтобы вывести шаттл на орбиту.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;p&gt;Правильная вещь – это программное обеспечение. Программное обеспечение
отдает приказы подключить основные двигатели, для того, чтобы вскоре
после того, как шаттл освободит башню, произошло поразительное вращение
фюзеляжа. ПО приглушает двигатели, чтобы корабль не разгонялся слишком
быстро. Оно отслеживает, где находится шаттл, приказывает ракетным
ускорителям отделиться, производит небольшие корректировки курса и,
спустя примерно 10 минут, направляет шаттл на орбиту на высоте более 100
миль. Когда ПО удовлетворено положением шаттла в космосе, оно
приказывает главным двигателям отключиться – наступает невесомость и все
начинает парить.&lt;/p&gt;
&lt;p&gt;Но поразителен не объем работ, который выполняет программное
обеспечение. Что действительно поражает, так это то, как хорошо это ПО
работает. Это ПО никогда не падает. Оно никогда не требует перезагрузки.
Оно не содержит ошибок. Оно совершенно, настолько совершенно, насколько
человек смог этого достичь. Посмотрите на статистику: последние три
версии этой программы – каждая по 420.000 строк кода – имели всего по
одной ошибке в каждой. Последние 11 версии этого ПО имели в сумме 17
ошибок. Коммерческие программы, подобного уровня сложности имели бы
5.000 ошибок.&lt;/p&gt;
&lt;p&gt;Это программное обеспечение – результат работы 260 женщин и мужчин,
расположенных в безымянном офисном здании, находящемся напротив
Джонсовского космического центра в городе Клир-Лэйк, штат Техас, на
юго-восток от Хьюстона. Они работают в "бортовой группе шаттла", филиале
подразделения космических систем корпорации Lockheed Martin, и их отвага
всемирно известна: группа разработки ПО для шаттлов – одна из всего
четырех организаций в мире, которая достигла 5 уровня по
правительственной шкале Института Разработки Программного обеспечения
(Software Engineering Institute – SEI) – меры сложности и надежности тех
методов, при помощи которых они делают свое дело.&lt;/p&gt;
&lt;p&gt;Группа пишет такое хорошее ПО, потому что оно должно быть таким. Каждый
раз, когда оно поджигает шаттл, от их ПО зависит оборудование,
стоимостью 4 миллиарда долларов, жизни полудюжины астронавтов и мечты
нации. Даже малейшая ошибка в космосе может иметь чудовищные последствия
– на орбите космический челнок движется со скоростью 17.500 миль в час;
ошибка при определении временного интервала всего на две трети секунды
отклонит шаттл от курса на три мили.&lt;/p&gt;
&lt;p&gt;НАСА знает, насколько хорошим должно быть ПО. Перед каждым полетом, Тед
Келлер, старший технический менеджер бортовой группы шаттла, летит во
Флориду, где он подписывает документ, удостоверяющий, что ПО не
подвергнет космический корабль опасности. Если Келлер не в состоянии
этого сделать, то формальная линия преемственности предписывает, кто
может подписать этот документ вместо него.&lt;/p&gt;
&lt;p&gt;Билл Пэйт, который разрабатывал ПО для космических полетов более 22 лет,
говорит, что группа понимает, каковы ставки. Если ПО не будет
безукоризненным, кто-то из тех людей, на встречу с которыми мы сейчас
идем, может умереть.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Программное обеспечение – это все.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В истории человечества, еще не было ничего, что было бы настолько
важным, как программное обеспечение.&lt;/p&gt;
&lt;p&gt;Фактически все – от международной валютной системы и крупных
электростанций до миксеров и микроволновых печей – работает под
управлением ПО. В офисных зданиях лифты, освещение, вода, кондиционеры
управляются ПО. В большинстве городов – светофоры. Практически любая
корреспонденция, которая чуть сложнее, чем почтовая открытка зависит от
ПО; каждый телефонный разговор и доставка каждой посылки требуют наличие
программного обеспечения.&lt;/p&gt;
&lt;p&gt;"Это подобно дошумерской цивилизации," – говорит Брэд Кокс, который
написал ПО для компьютера Стива Джобса NeXT и профессор университета
имени Джорджа Меэйсона. "Тот способ, которым мы создаем ПО – это эра
охотников и собирателей".&lt;/p&gt;
&lt;p&gt;Джон Мансон, программист и профессор информатики университета Айдахо еще
более категоричен. "Пещерное искусство" – он говорит. "Это примитив.
Считается, что мы обучаем компьютер науке. Но здесь нет науки вообще."&lt;/p&gt;
&lt;p&gt;Программное обеспечение может быть двигателем для постиндустриального
мира, но его создание остается доиндустриальным ремеслом. Согласно
исследования SEI, около 70% программистских организаций застряли на
первых двух уровнях по шкале SEI: хаос и нечто лучшее, чем хаос.
Ситуация настолько тяжелая, что некоторые пионеры программирования ушли
из компаний, подобных Микрософт, чтобы преподавать искусство создания
ПО.&lt;/p&gt;
&lt;p&gt;Марк Полк, старший член технического совета SEI говорит, что успех ПО
делает его недостатки еще более драматичными. "Мы разработали продукт,
который является невероятно сложным и невероятно мощным. Мы очень сильно
от него зависим," – говорит Полк. "К тому же все жалуются на то,
насколько оно плохое, со всеми его дефектами. Если бы вы купили
автомобиль с 5.000 дефектов, вы бы были расстроены."&lt;/p&gt;
&lt;p&gt;В этом болоте программного обеспечения, бортовая группа шаттла держится
особняком. Десять лет назад эта группа была как все. С тех пор, она
снизила количество своих ошибок на 90%.&lt;/p&gt;
&lt;p&gt;Чтобы быть настолько успешной, бортовая группа шаттла должна быть совсем
другой – полной противоположностью тем кодерам, работающими ночи
напролет и питающимися кофе с булочками, которые живут в воображении
общественности. Чтобы быть настолько успешной, эта группа должна быть
совершенно заурядной – неотличимой от любой сконцентрированной,
дисциплинированной и методично управляемой творческой фирмы.&lt;/p&gt;
&lt;p&gt;Фактически, эта группа преподает ряд уроков, которые в равной степени
применимы к программистам в частности и к производителям, в целом.
Взгляд на культуру, которой они построили, и на процесс, который они
довели до совершенства, показывает нам, каким должен быть процесс
написания ПО, если программное обеспечение собирается выполнять свои
обещания, и иллюстрирует, что практически любая коллективная операция
может ускорить процесс достижения результатов, близких к безупречным.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Программное обеспечение для взрослых&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;"Этот кошмар со скорейшим выпуском новых версий продолжается и сегодня.
Давай, давай, давай! Нам никогда этого не сделать. Я говорил уже об
этом? Почему мы всегда преуменьшаем наши планы по выпуску новых версий?
Я просто не понимаю. Приходим на работу к 9.30, уходим в 23.30. В обед –
пицца из "Домино". И три диетические Колы."&lt;/p&gt;
&lt;p&gt;Нет, это не бортовая группа шаттла. Это сценарий Дугласа Копланда, в
точности описывающий жизнь передовой софтверной компании. И это
доминирующий образ индустрии разработки программного обеспечения:
поколение исполнителей в спортивных майках с обезумевшими взглядами,
выжимающее слишком много геройского кода, за слишком малое время;
роликовые коньки и горные велосипеды, сложенные по углам; коробки из-под
пиццы и чашки, оставленные в комнате для совещаний. Это мир, ставший
известным, романтическим, даже неизбежным благодаря историям из Sun
Microsystems, Microsoft и Netscape.&lt;/p&gt;
&lt;p&gt;Но это не относится к бортовой группе шаттла. Их рабочие места – это
кабинеты, населенные конторскими служащими. Наиболее впечатляет то,
насколько заурядно они выглядят. Если не считать небольших памятных
вещей с шаттлов, вы можете подумать, что оказались в офисе любой
небольшой фирмы или правительственного учреждения. У каждого есть свой
небольшой офис, в которых есть доска, персональный компьютер,
немногочисленные личные вещи. Люди на работе носят сдержанно элегантные
вещи, аккуратные, но не бросающиеся в глаза и, естественно, чистые.&lt;/p&gt;
&lt;p&gt;Они работают с 8 до 5 – работа допоздна случается, но это, скорее,
исключение. Программисты работают напряженно, но сдержано. Многие из них
отдали годы работе либо в IBM (куда входила группа шаттла до 1994 года),
либо непосредственно в разработке программного обеспечения для шаттлов.
Они взрослые люди, у них есть супруги, дети и личная жизнь помимо их
поразительных программ.&lt;/p&gt;
&lt;p&gt;Здесь существует культура: бортовая группа шаттла производит взрослое
программное обеспечение и способ, при помощи которого оно производится,
сама также являясь взрослой. Здесь нет места сексуальности, нет места
единоличным решениям – но это будущее программного обеспечения. Когда вы
уже готовы сделать следующий шаг – писать совершенное ПО, вместо
достаточно хорошего – значит пришло время взрослеть.&lt;/p&gt;
&lt;p&gt;Тед Келлер, 48 лет, старший технический менеджер группы, выглядит и
разговаривает как директор небольшой частной средней школы. Его задачей
является убедиться, что ПО будет выпущено вовремя, со всеми его
возможностями, независимо от сложностей. Он невысокого роста, с лысиной,
немного официальный и привередливый, с качествами, которые бы успокоили
любого астронавта. Он обладает благородным чувством юмора, проявляя его
не столько с посторонними, сколько со своей командой.&lt;/p&gt;
&lt;p&gt;Это происходит на обсуждениях между членами группы и их коллегами из
НАСА. Это происходит в небольших комнатах, где находятся 22 человека и
большой проектор. Пару раз из глубины комнаты, Келлер выдает какое-то
замечание насчет сроков поставки кода или деталей какой-нибудь
спецификации и вся комната наполняется смехом.&lt;/p&gt;
&lt;p&gt;Во всем остальном, часовое совещание является честным и открытым. Такой
момент, 12 из 22 сотрудников в комнате – женщины, многие из них –
старшие менеджеры или старший технический персонал. Бортовая группа
шаттла, с ее стабильностью и профессионализмом, похоже, особенно
привлекательна для женщин-программистов.&lt;/p&gt;
&lt;p&gt;Другой момент – это порядок, детали и методические повторения. Данное
совещание, классическое мероприятие в НАСА – это репетиция практически
идентичного совещания, которое произойдет через несколько недель. Оно
состоит из прогона невероятных объемов данных и изображений – графы,
которые описывают прогресс и состояние программного обеспечения по
каждой строке. За исключением Келлеровских лирических отступлений, тон,
в целом, деловой, почти формальный, изображения – диаграммы мелькают
настолько быстро, насколько они могут восприниматься, смесь из
аббревиатур, диаграмм и графиков.&lt;/p&gt;
&lt;p&gt;То, что происходит здесь – это основная работа, которая определяет
движитель группы к совершенству – движитель, который особенно нетерпим к
единоличным решениям. В бортовой группе шаттла нет суперзвезд. Основной
подход к разработке ПО умышленно разработан таким образом, чтобы не
зависеть от конкретного человека.&lt;/p&gt;
&lt;p&gt;Точно также культура не терпит творчества, индивидуальной показухи и
признаков классической индустрии ПО. "Люди спрашивают, разве такой
процесс не душит творчество? Вы должны делать все в точности так, как
говорит руководство, и у вас есть некто, кто заглядывает вам через
плечо" – говорит Келлер. "Ответом будет – да, этот процесс действительно
душит творчество".&lt;/p&gt;
&lt;p&gt;И вот именно в этом все дело – вы не можете позволить людям быть
свободными художниками при написании кода, который управляет космическим
кораблем вместе с людьми, чьи жизни зависят от этого. Попробуйте-ка
исправить такой код, когда он уже на орбите. "Хьюстон, у нас проблемы" –
это скорее подходит для хорошего фильма; это недопустимо при написании
ПО. "Люди должны направлять свое творчество в изменение самого
процесса", – говорит Келлер – "а не в изменение программного
обеспечения".&lt;/p&gt;
&lt;p&gt;Сладкие песни обычного мира, где производится ПО, могут не устоять перед
строгой критикой, которую практикует группа. Куин Ларсон, 34 года,
проработал над ПО для шаттлов семь лет, прежде чем покинул группу и
перешел работать в Micron Technology в Бойсе, штат Айдахо,
автоматизирующую производство чипов памяти.&lt;/p&gt;
&lt;p&gt;В компании Micron Ларсон получил задачу автоматизации пил, которые
обрезают готовые подложки до необходимых размеров. Допусти ошибку в
такой программе и ты потеряешь ценные подложки.&lt;/p&gt;
&lt;p&gt;"Я сам должен был определять что и как делать", – говорит Ларсон. "Здесь
не было совещаний, здесь не велось записей". У него была полная свобода
действий, и это было настоящим ударом. C точки зрения Ларсона, культура
не была нацелена на получение качественного продукта. "Скорость там была
превыше всего", говорит он. "Инженеры говорили, что вот, мол, это наши
основные приоритеты, и нам необходимо достичь их как можно быстрее." Но
у Ларсона сложилось впечатление, что их, похоже, не особо беспокоило то,
насколько хорошо работает программное обеспечение, которое они
выпускают. "По существу, они хотели получить быстрое ПО – чтобы поскорее
вытолкнуть его за дверь."&lt;/p&gt;
&lt;p&gt;В середине августа Ларсон вернулся в группу шаттла. "Здесь работают люди
высочайшей пробы", – сказал он в свой первый рабочий день после
возвращения в Клир-Лэйк&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Процесс&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Каким образом они пишут правильную вещь?&lt;/p&gt;
&lt;p&gt;Ответ такой: все дело в процессе. Наиболее важный результат работы
группы – это не совершенное программное обеспечение, которое они пишут –
это процесс разработки, который они изобрели, который позволяет
создавать совершенное ПО.&lt;/p&gt;
&lt;p&gt;Именно процесс, который позволяет им жить нормальной жизнью,
устанавливать реальные сроки, укладываться в бюджет и выпускать ПО,
которое делает в точности то, что от него ожидают. Именно процесс,
который определяет то, что знают эти программисты, находящиеся в
пригороде Хьюстона, то, что все остальные еще только пытаются
нащупывать. Именно процесс предлагает схему для любого созидательного
предприятия, которое ищет методы для выпуска последовательного и
последовательно улучшающегося качества.&lt;/p&gt;
&lt;p&gt;Процесс может быть сведен к четырем предложениям:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Продукт хорош настолько, насколько хорош план для него.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В бортовой группе шаттла, около трети процесса по написанию ПО
происходит до того, как кто-либо напишет хоть одну строку кода. НАСА и
группа из Локхид Мартин достигают соглашения в самых подробных
описаниях, касательно всего, что новый код должен будет делать – и затем
они фиксируют достигнутые договоренности на бумаге с такой
скрупулезностью и точностью, которую обычно можно наблюдать при
ксерокопировании. Ничто в спецификациях не может быть изменено без
согласия и полного понимания с обеих сторон. И никто не изменит ни одной
сроки кода без спецификации, подробно описывающей это изменение.
Возьмем, к примеру, обновление ПО, позволяющее управлять шаттлом при
помощи спутников Системы Глобального Позиционирования (GPS). Это
изменение затрагивало всего 1.5 процента от всей программы или 6.366
строк кода. Спецификации для него занимали 2.500 страниц, том, толще,
чем телефонный справочник. Спецификации для всего программного
обеспечения в его текущем состоянии занимают 30 томов или около 40.000
страниц.&lt;/p&gt;
&lt;p&gt;"Наши требования – это практически псевдокод", говорит Уильям Претт,
который руководит этим проектом в НАСА. "Они говорят – вы должны делать
именно это, именно таким образом, в данных условиях и при данных
обстоятельствах".&lt;/p&gt;
&lt;p&gt;Такой тщательный процесс проектирования уже сам по себе достаточен для
того, чтобы обеспечить классную организацию труда, говорит Джон Мансон
из Университета Айдахо. Большинство организаций берутся даже за большие
проекты без детального планирования того, что их ПО должно делать. И,
как правило, после того, как программисты уже начали писать программу,
заказчик настоятельно требует изменить архитектуру. Результатом является
хаос, высокая стоимость разработки, где код постоянно изменяется и
содержит ошибки, даже при проектировании.&lt;/p&gt;
&lt;p&gt;"Большинство людей решают потратить свои деньги тогда, когда процесс,
казалось бы, подходит к концу", говорит Мансон. "В современной индустрии
программного обеспечения 80% затрат на разработку приходится на период,
который наступает после выпуска первой версии, – но люди поначалу не
понимают этого, и тратят время на выяснение отношений." В группе шаттла,
все делается правильно с первого раза. И никто не изменяет программное
обеспечение без изменения плана. Вот почему их ПО настолько совершено.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Лучшая работа в команде – это здоровая конкуренция.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;В группе разработчиков ПО для шаттла существуют подгруппы и субкультуры.
Но то, что в других организациях может быть собственной офисной
политикой, здесь является критической частью всего процесса.&lt;/p&gt;
&lt;p&gt;Центральная группа разделяется на две ключевые команды: разработчики –
люди, которые сидят и пишут код, и проверяющие – люди, которые пытаются
найти дефекты в коде. Обе команды отчитываются разным начальникам и
имеют прямо противоположные задачи. Группа разработки обязана выпустить
абсолютно безошибочный код, настолько безупречный, чтобы тестеры не
нашли дефектов вовсе. Группа тестирования обязана истязать этот код при
помощи сценариев полета и симуляций, чтобы обнаружить как можно больше
дефектов. Результатом является то, что Том Петерсон называет
"отношениями дружеского соперничества".&lt;/p&gt;
&lt;p&gt;"Они конкурируют между собой на предмет того, кто обнаружит ошибки",
говорит Келлер. "Иногда они грызутся, как кошки с собаками. Разработчики
хотят отловить все свои ошибки. Тестеры выходят из себя: "Эй, забейте!
Вы отнимаете наше время для тестирования программы."&lt;/p&gt;
&lt;p&gt;Разработчики даже начали проводить свои собственные ревизии кода на
заседаниях, скрупулезный анализ, который, как они надеются, расстроит
тестеров. Проверяющие, в свою очередь, утверждают, что они заслужили
такой авторитет, что некоторые ошибки обнаруживаются еще до того, как
они начинают тестирование. "С точки зрения группы тестирования", –
говорит Пэт Маклилллан, старший менеджер, – "мы осознаем, что если бы не
было независимой группы тестирования, разработчики были бы более
расслабленными. Одно только существование нашей группы заставляет их
быть более внимательными."&lt;/p&gt;
&lt;p&gt;В результате такой дружеской конкуренции группа шаттла сейчас
обнаруживает 85% ошибок до начала формального тестирования, и 99.9% до
того, как программа отправляется в НАСА.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. База данных – это фундамент программного обеспечения.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Есть программное обеспечение. Но кроме этого, существуют еще базы
данных, две громадных базы данных, энциклопедичных по полноте хранимой
информации.&lt;/p&gt;
&lt;p&gt;Одна из них – это история, собственно, кода, где каждая строчка снабжена
комментарием, говорящим о каждом случае, когда она была изменена, почему
она была изменена, когда это произошло, с какой целью это было сделано,
какие спецификации описывают это изменение. Все что происходит с
программой записывается в этой сводной истории. Родословная каждой
строчки кода, для чего и создавалась эта база данных, мгновенно доступна
каждому.&lt;/p&gt;
&lt;p&gt;Другая база данных – это база данных ошибок, является своего рода
памятником тому пути, которым прошла бортовая группа шаттла в своей
работе. Здесь содержатся все ошибки, которые были когда-либо допущены
при написании или при работе с ПО, на протяжении почти 20 лет. Для
каждой ошибки в базе данных хранятся записи о том, когда эта ошибка была
обнаружена; какой набор команд привел к ней; кто обнаружил ошибку; на
какой стадии ошибка была обнаружена – при тестировании, при тренировке
или в полете. Здесь отслеживается как ошибка проявилась в программе; как
ошибке удалось просочиться сквозь фильтры на каждой стадии поиска ошибок
– почему она не была обнаружена при проектировании? при ревизиях кода?
при тестировании? В конечном итоге база данных содержит информацию о
том, как ошибка была исправлена и не могли ли подобные ошибки
просочиться сквозь эти дыры.&lt;/p&gt;
&lt;p&gt;Группа собрала настолько большой объем данных о том, как она работает,
что были написаны программы, которые моделируют процесс написания кода.
Подобно тому как компьютер моделирует предсказания погоды, модели
кодирования предсказывают сколько ошибок следует ожидать при написании
каждой новой версии программы. И если разработчики или тестеры находят
слишком мало ошибок, то все исследуют процесс до тех пор пока реальность
и предсказания не совпадут.&lt;/p&gt;
&lt;p&gt;"Мы никогда не пускаем ничего на самотек", – говорит Претти Торнтон,
старший менеджер. – "Мы делаем прямо противоположное: мы допускаем,
чтобы все нас беспокоило."&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Мало исправить ошибку – в первую очередь, необходимо исправить все,
что позволило этой ошибке случиться.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Процесс является настолько всеобъемлющим, что он оказывается в ответе за
каждую ошибку – если есть дефект в программе, значит что-то не в порядке
с процессом написания кода, что-то что должно быть исправлено. Любая
ошибка, не обнаруженная на стадии планирования, проникла, по крайней
мере, сквозь несколько проверок. Почему так случилось? Что-то не в
порядке с ревизиями кода? Или в контрольный список следует добавить
новый пункт?&lt;/p&gt;
&lt;p&gt;Важно заметить, что группа избегает обвинять людей в ошибках. Все
обвинения берет на себя процесс – и именно процесс подвергается анализу,
чтобы определить как и почему произошла ошибка. В то же время,
ответственность является принципом команды: ни один человек не отвечает
единолично за написание или ревизию кода. "Вас не будут наказывать за
то, что вы допускаете ошибки", – говорит Маджори Сейтер, старший
сотрудник технического персонала. "Если я делаю ошибку, а другие
проверяют мою работу, значит я не одинок. Меня не будут обвинять в
этом."&lt;/p&gt;
&lt;p&gt;Тед Келлер приводит пример отдачи от такого подхода, касающийся
шаттловского дистанционного манипулятора-руки. "Мы передали наше ПО для
обучения команды шаттла", – говорит Келлер, – "что позволило астронавтам
управлять этой "рукой" и перемещать грузы. Когда "рука" оказывалась в
определенной точке, она просто переставала двигаться."&lt;/p&gt;
&lt;p&gt;Программа выходила из строя из-за программной ошибки. В то время, когда
"запястье" этой "руки" завершало полный 360-градусный поворот, из-за
ошибки в вычислениях, программа думала, что "рука" сделала больше, чем
полный поворот, чего не могло быть в принципе. Проблема заключалась в
округлении результата – обычная математическая ошибка, но она выявила
каскад других проблем.&lt;/p&gt;
&lt;p&gt;"Даже несмотря на то, что это было некритично", – говорит Келлер, – "мы
проанализировали, какие еще строки кода могли содержать точно такой же
тип дефекта." Они обнаружили восемь подобных ситуаций, где в семи из них
округление не порождало проблем. "Одна из таких ситуаций была связана с
подпрограммой, управляющей мощной антенной", – говорит Келлер. "Это была
главная антенна корабля. Если бы эта ошибка проявилась, в критический
момент могла бы прерваться связь с землей. А это уже намного серьезнее."&lt;/p&gt;
&lt;p&gt;Процесс работает таким образом, что он обнаруживает ошибки не только в
ПО. Он обнаруживает ошибки в самом себе.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Проблема только в программном обеспечении.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Бомбардировщик Б-2 не смог отправиться в свой первый полет – из-за
ошибки в ПО. Новый аэропорт Денвера открылся на несколько месяцев позже
и превысил бюджет на несколько миллионов долларов из-за проблемы в
системе управления багажом – но проблема была исключительно в ПО. Новая
ракета Европейского Космического Агентства Ариан 5 взорвалась при первом
запуске из-за маленькой ошибки в ПО. Крупные федеральные
правительственные агентства, начиная от Налоговой Службы и заканчивая
Национальной Службой Погоды, увязли в проектах, просроченных на годы и
превысивших бюджет на сотни миллионов долларов, зачастую из-за небольших
проблем с программным обеспечением. Программное обеспечение становится
все более и более повсеместным, и, следовательно, все более и более
важным, но похоже, оно не становится все более и более надежным.&lt;/p&gt;
&lt;p&gt;В то время когда остальной мир еще осваивает основы, бортовая группа
шаттла постепенно продвигается к совершенному программному обеспечению.
Естественно, у них есть масса преимуществ перед остальным миром
разработки программного обеспечения. Они разрабатывают всего лишь один
продукт: одну программу, которая управляет одним космическим кораблем.
Они знают свою программу досконально на протяжении всего времени работы
над ней. У группы только один заказчик, причем, весьма разумный. К тому
же, деньги здесь не являются ограничивающим фактором: бюджет группы
размером в 35 миллионов долларов является незначительным кусочком
НАСА’вского пирога, но в пересчете на количество строк кода это делает
группу одной из наиболее дорогостоящих организаций по разработке ПО в
США.&lt;/p&gt;
&lt;p&gt;И еще такой момент: этот процесс настолько исключительный, стремление к
совершенству настолько выражено, что это показывает что же необходимо
для достижения неизменно высоких результатов. Наиболее важные вещи,
которые делает группа шаттла, такие как: тщательное планирование
будущего ПО заранее, написание кода только после того, когда завершен
процесс проектирования, никаких изменений без изменения соответствующих
спецификаций, хранение полной и аккуратной истории кода – не являются
дорогостоящими. Это даже не относится исключительно к космической науке.
Это стандартные приемы практически в любой инженерной отрасли, за
исключением, создания программного обеспечения.&lt;/p&gt;
&lt;p&gt;На стене в комнате для конференций висит неформальный девиз бортовой
группы шаттла, отражающий сущность следования разработанному здесь
процессу: "Чем раньше ты отстанешь, тем больше у тебя времени, для того
чтобы догнать."&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Автор: Charles Fishman (fish@nando.net). Оригинал находится здесь:
http://www.fastcompany.com/online/06/writestuff.html&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Перевод:
http://kholeg.wordpress.com/2006/11/20/%D0%BE%D0%BD%D0%B8-%D0%BF%D0%B8%D1%88%D1%83%D1%82-%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D1%8C%D0%BD%D1%83%D1%8E-%D0%B2%D0%B5%D1%89%D1%8C/&lt;/em&gt;&lt;/p&gt;</content><category term="Полезное"/><category term="работа"/><category term="разработка"/></entry><entry><title>PHP Перевернуть строку без буфера</title><link href="https://blog.rpsl.info/2011/03/php-perevernut-stroku-bez-bufera/" rel="alternate"/><published>2011-03-24T15:45:00+03:00</published><updated>2011-03-24T15:45:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-03-24:/2011/03/php-perevernut-stroku-bez-bufera/</id><content type="html">&lt;p&gt;Еще один способ как перевернуть строку. Не используется дополнительный буфер, просто красивая работа с данными.&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;$str = (string) '123456789';

echo $str . &amp;quot;\n&amp;quot;;

$count = strlen( $str ) - 1  ;

for( $i=0; $i&amp;lt;=$count; $i++ )
{
    $str[ $count + $i + 1 ] = $str[ $count - $i ];
    $str[ $count - $i ] = '';
}

echo $str . &amp;quot;\n&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Результатом выполнения будет&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;123456789
987654321
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Все просто.&lt;/p&gt;</content><category term="Заметки"/><category term="php"/><category term="алгоритмы"/></entry><entry><title>Preg Match на уровне Дьявола</title><link href="https://blog.rpsl.info/2011/03/preg-match-na-urovne-dyavola/" rel="alternate"/><published>2011-03-16T22:45:00+03:00</published><updated>2011-03-16T22:45:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-03-16:/2011/03/preg-match-na-urovne-dyavola/</id><content type="html">&lt;pre&gt;&lt;code class="php"&gt;$pattern = &amp;quot;/\w{0,5}[хx]([хx\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[уy]([уy\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[ёiлeеюийя]\w{0,7}
|\w{0,6}[пp]([пp\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[iие]([iие\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[3зс]([3зс\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})
[дd]\w{0,10}|[сcs][уy]([уy\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[4чkк]\w{1,3}|\w{0,4}[bб]([bб\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})
[lл]([lл\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[yя]\w{0,10}|\w{0,8}[её][bб][лске@eыиаa][наи@йвл]\w{0,8}|\w{0,4}
[еe]([еe\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[бb]([бb\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[uу]([uу\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})
[н4ч]\w{0,4}|\w{0,4}[еeё]([еeё\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[бb]([бb\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[нn]([нn\s\!@#\$%\^&amp;amp;*+-\|\/]
{0,6})[уy]\w{0,4}|\w{0,4}[еe]([еe\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[бb]([бb\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})
[оoаa@]([оoаa@\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[тnнt]\w{0,4}|\w{0,10}[ё]([ё\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[б]\w{0,6}|\w{0,4}
[pп]([pп\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[иeеi]([иeеi\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[дd]([дd\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})
[oоаa@еeиi]([oоаa@еeиi\s\!@#\$%\^&amp;amp;*+-\|\/]{0,6})[рr]\w{0,12}/i&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Кто скажет что это?&lt;/p&gt;</content><category term="Заметки"/><category term="php"/><category term="preg_match"/></entry><entry><title>Еще немного про собеседования</title><link href="https://blog.rpsl.info/2011/03/eshhe-nemnogo-pro-sobesedovaniya/" rel="alternate"/><published>2011-03-13T17:46:00+03:00</published><updated>2011-03-13T17:46:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-03-13:/2011/03/eshhe-nemnogo-pro-sobesedovaniya/</id><content type="html">&lt;p&gt;Решил дополнить поднятую тему про собеседования и рассказать о вопросахкоторые задают чаще всего.&lt;/p&gt;
&lt;p&gt;Изначально, я хотел в этом посте написать все самые интересные вопросы и дополнить их ответами, но когда начал его писать, то понял что ответы тут не нужны. Те кому это действительно надо, сами порешают данные задачи, остальные могут просто пролистать.&lt;/p&gt;
&lt;p&gt;Первое на что хочу обратить ваше внимание, это то, что вопросы которые задают php(?) программистам, в основной своей сути имеют довольно академический характер и в жизненных циклах проектов встречаются не часто, но тем не менее, нужно уметь решать эти задачи. Это обусловленно тем, что у работодателей нету времени и желания давать вам типичные задачи, в стиле - "Напиши класс, который будет отвечать за работу с пользователями". 99 процентов всех вопросов задаются по заготовленному листку и должны быть решены на листке бумаги. Никаких IDE, никаких гуглов, никаких ответов типа "я не помню синтаксис". Если вы настроены решительно и хотите произвести хорошее впечатление, то уделите время, что бы потренироваться и чувствовать себя уверенно.&lt;/p&gt;
&lt;p&gt;Все вопросы можно разделить на три категории: PHP, MySQL(?), все остальное.&lt;/p&gt;
&lt;p&gt;Любой из этих пунктов, так же делится на две части: теория и практика. Начну пожалуй с PHP. С теоретическими вопросами, в целом, не сложно. Они почти везде одинаковые: Отличия между PHP 5.2 и 5.3, основные приципы ООП. Не частый, но вопрос с подвохом - "В каких случаях использование ООП, является убыточным?". Дальнейшие вопросы на теорию, в основном, зависят от ваших ответов, и несут цель узнать на сколько хорошо вы разбираетесь в материале о котором говорили выше.&lt;/p&gt;
&lt;p&gt;Практические вопросы, это чаще всего просьба написать некую ф-цию, которая делает какую либо хрень. Почти на каждом собеседование меня просили написать функцию которая переворачивает строку, без использования дополнительных буферов, можно попробовать схитрить и ответить что-то в стиле&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;function revert( $string ){ return strrev( $string ); } ?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Но это не cамый лучший вариант ответа. Выучите алгоритм с обращением к символом строки как к объекту массива.  &lt;/p&gt;
&lt;p&gt;Очень частые задачи, на написание рекурсивных функций или на понимание работы операторов кода.&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;$a = 10;
echo ++$a + $a++ - ++$a + $a ;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;На днях пока решал задачи, попалось интересное задание, у меня такое ни разу не спрашивали, но думаю что к такому надо быть готовым:&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;var_dump( 0123 == 123 );
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Думаю, что на счет PHP я достаточно ясно изложил типовые вопросы, если что-то осталось не понятно, то спрашивайте в комментариях.  &lt;/p&gt;
&lt;p&gt;Теоретические вопросы про MySQL или любую другую СУБД почти всегда касаются индексов и насколько вы понимаете как их использовать, в каких случаях и на что их ставить и в каких случаях индексы могут быть вредны. Обязательно спросят про различия между версиями. Поинтересуются насколько глубоко вы знаете тонкости работы СУБД и вкурсе ли вы про то, что такое тригеры, хранимые процердуры, представления.&lt;/p&gt;
&lt;p&gt;Практические задачи - это просьба нарисовать две таблицы с различными данными и просьба написать запрос, который покажет умеете ли вы использовать операторы HAVING, GROUP BY, ... etc. Обязательно знать разницу между &lt;a href="http://blog.rpsl.info/2009/07/sql-joins-vidy-tipy-razlichiya.html"&gt;JOIN запросами&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Еще часто спрашивают про верстку, про css, про javascript. Но расписывать это все не вижу смысла.&lt;/p&gt;</content><category term="Полезное"/><category term="css"/><category term="javascript"/><category term="join"/><category term="mysql"/><category term="php"/><category term="жизнь"/><category term="работа"/></entry><entry><title>Немного про собеседования</title><link href="https://blog.rpsl.info/2011/03/nemnogo-pro-sobesedovaniya/" rel="alternate"/><published>2011-03-06T13:51:00+03:00</published><updated>2011-03-06T13:51:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-03-06:/2011/03/nemnogo-pro-sobesedovaniya/</id><content type="html">&lt;p&gt;Когда в середине 2010 года я понял, что пора искать новое место, я посетил много собеседований, т.к. мне не хотелось уходить с довольно теплого места в абы куда, я метил в крупные, стабильные компании, с высокой зп, большими перспективами, туда где я буду средничком на общем фоне, что бы был стимул развиваться.&lt;/p&gt;
&lt;p&gt;В некоторые компании меня не пригласили, от некоторых я отказывался после первого посещения, в одну хорошую фирму даже позвали, но пришлось бы ездить через весь город и после доглих размышлений я отказался.&lt;/p&gt;
&lt;p&gt;Вообще собеседования, для меня стали большим мотиватором в саморазвитии. Помню как я пошел на самое первое, был уверен что я такой крутой и смогу все рассказать сходу, расскажу какие ~~крутые~~ штуки я умею делать и меня сразу возьмут. ХА ХА Лох. На первом собеседование, меня за пять минут смешали с грязью и больше всего мне хотелось провалиться сквозь землю. Когда перед тобой сидят несколько взрослых человек и задают тебе серьезные вопросы, на которые ты не знаешь как ответить, но говорить "я не знаю" считаешь не приемлемым, то разволноваться в общем не проблема.&lt;/p&gt;
&lt;p&gt;Первый вопрос, с которого было начато собеседование звучал так: "Что из себя представляют индексы (MySQL) в физическом плане". Блядь. Да я никогда в жизни не задумывался, о том, что они из себя представляют в физическом плане. Начал рассказывать про B-Tree, бла-бла-бла, но я понятие не имею что это за файлы и какая у них структура. Сказал честно, что никогда этим не интресовался, но попытался предположить как и что это. В общем был полный FAIL. Хотя думаю что даже если бы и попал в ту контору, очень быстро бы сгорел работать по китайскому календарю и тратить по два часа на общественный транспорт.&lt;/p&gt;
&lt;p&gt;В другой, на первый взгляд, не плохой конторе, меня встретили директор отдела разработок и его заместитель. Рассказали мне про контору, задавали кучу вопросов из книги про гору фудзи, все бы хорошо, но это было в двухпоточном режиме. Директор мне задавал задачи, я решал их на листочке, а его заместитель при этом активно общался со мной и мне приходилось решая задачу, общаться с ним на тему сколько шариков для тениса поместиться в боинг, сколько автомобилей и заправок для них в Москве и попытаться ответить на самый не нормальный, но не менее интересный вопрос "Как называется наша вселенная?"&lt;/p&gt;
&lt;p&gt;Собеседования я там прошел на плюс-минус, обещали перезвонить через пару дней. Не позвонили. Ну и пофиг, их офис спустя две недели переехал с филей в Крылатское, а ездить в Крылатское каждый день я бы не осилил.&lt;/p&gt;
&lt;p&gt;Кстати вот дебильное качество. Зачем HR говорят что перезвонят, но не перезванивают. Я понимаю прекрастно, что после собеседования нужен перерыв, нужно подумать, посмотреть других кандидатов, но не ужели трудно перезвонить или отписать на почту, что мол так и так, мы не готовы вас пригласить. Это деловые отношения, а в деловых отношениях, я считаю, нельзя давать обещаний и не выполнять их, либо не обещай, либо держи слово.&lt;/p&gt;
&lt;p&gt;К слову говоря, чувак из конторы, офис которой находится в жутких ебенях, зарплата серая, никаких обязательств и прочих штук, перезвонил мне и сказал что не готов пригласить меня. Хотя странно, собеседования я прошел отлично, решил все задачи, рассказал кучу интересных вещей и был уверен что даже не ловко будет, когда буду отказываться.&lt;/p&gt;
&lt;p&gt;Сейчас, пока поднимаю воспоминания, вспомнил про еще довольно странную контору. Офис - несколько этажей в довольно крупном бизнес центре. Очень крутой пакет (страховка/обеды/...), достаточно высокая зарплата на старте ( &amp;gt;80 000 ), корпоративная лицензия на PhpStorm :)))&lt;/p&gt;
&lt;p&gt;Так вот, к собеседованию я готовился почти неделю. Вызубрил все различия между версиями php и mysql, поднял все знания какие есть по паттернам программирования и мог с ходу написать кучу разных интересных штук. Выспался, пришел в отличном настроение и так нелепо обломался.&lt;/p&gt;
&lt;p&gt;Вопросы которые мне задавали, были настолько простые, что я оказался к ним не готов. Я не смог вспомнить, что различия между одинарной кавычкой не только в автопарсинге переменных, но еще и преобразование спецсимволов, запутался в &lt;strong&gt;&lt;em&gt;htmlentities&lt;/em&gt;&lt;/strong&gt; и &lt;strong&gt;&lt;em&gt;html_entity_decode&lt;/em&gt;&lt;/strong&gt; и вообще очень сильно лажал на примитивных вещах, на которые до этого никогда не обращал внимание. Было стыдно и был очень злой на себя.&lt;/p&gt;
&lt;p&gt;Вообще это не всё, есть еще много историй, возможно, потом, расскажу. Но подводя краткий итог, хочу сказать, что иногда стоит ходить на собеседования. Даже если не собираетесь уходить со своего места работы, это сильный стресс, как резкое погружение в холодную воду, которое вытаскивает тебя из рутинной обыденности и позволяет оценить свои силы. За те четыре месяца, которые прошли с моего первого собеседования, до того на котором меня пригласили, я узнал больше вещей и заполнил пробелов, чем за весь прошлый год.&lt;/p&gt;
&lt;p&gt;Ну и тем крутым, которые знают php отлично, я процитирую
&lt;a href="http://bolknote.ru/2010/10/09/~2763/#18"&gt;Bolk'a&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;От собеседований, которые я недавно проводил, у меня осталась масса листочков с заковыристыми вопросами. Например, если человек говорил, что знает PHP на 10 из 10, то я ему давал, например, такой тест:&lt;/p&gt;
&lt;p&gt;Сказать есть ли тут ошибки, если нет, то что получим и что вообще тут происходит.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class="php"&gt;var_dump((bool) print_r(${strrev('SLABOLG')} = 1, $GLOBALS[1]{1} == (unset) b&amp;quot;1&amp;quot;) == &amp;quot;00&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;</content><category term="Полезное"/><category term="mysql"/><category term="php"/><category term="жизнь"/><category term="работа"/></entry><entry><title>PHP Кэширование картинок часть вторая</title><link href="https://blog.rpsl.info/2011/03/php-kehshirovanie-kartinok-chast-vtoraya/" rel="alternate"/><published>2011-03-05T13:38:00+03:00</published><updated>2011-03-05T13:38:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2011-03-05:/2011/03/php-kehshirovanie-kartinok-chast-vtoraya/</id><content type="html">&lt;p&gt;Я уже когда-то писал про &lt;a href="http://blog.rpsl.info/2009/08/php-images-cache.html"&gt;мой способ кэшировать картинки&lt;/a&gt;, а сейчас заметил, что не выкладывал сюда переделанный варинт. &lt;/p&gt;
&lt;p&gt;Идея осталась прежней, только работа с изображениями была отдана либе http://phpthumb.gxdlabs.com/&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;/**
 * Скрипт iCacher создан что бы облечить кеширование изображений на сайте
 * и организовать лаконичную возможность генерации картинок различных размеров.
 * iCacher является т.н. роутером для http://phpthumb.gxdlabs.com/ и не будет
 * работать правильно при отсутвие данной библиотеки.
 *
 * Для правильно работы подразумевается соблюдение нескольких правил:
 *
 *  1. В папке MAIN_FOLDER хранятся оригинальные изображения.
 *  2. В папку CACHE_FOLDER будут храниться измененные изображения.
 *  3. При обращение к несуществующему файлу из папки CACHE_FOLDER происходит
 *      перенаправление на данный файл*, который в свою очередь создает
 *      необходимый файл либо возвращет 404 ошибку.
 *          * .htaccess rewrite rule:
 *              RewriteRule   ^images_folder/([0-9a-z]+)/([0-9a-z]+)/(.*)$  iCacher.php?param=$1&amp;amp;size=$2&amp;amp;file=$3 [L,QSA]
 *  4. После генерации изображений они должны быть доступны по прямому запросу.
 *  5. Для обновления миниатюр вы должны самостоятельно организовать удаление
 *      созданых скриптом файлов.
 *      В крайнем случае можно использовать GET параметр flush с любым значением.
 *
 *
 *  При необходимости создавайте собственные плагины или ф-ции обработки.
 */
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Скрипт лежит на github.com - https://github.com/Rpsl/iCacher/blob/master/iCacher.php&lt;/p&gt;
&lt;p&gt;В целом все хорошо, скрипт местами дебильный и с не логичной реализацией, но уже пол года работает на одном хайлоад проекте.&lt;/p&gt;
&lt;p&gt;Кстати, на папку с кэшироваными изображениями натравлен скрипт, который удаляет файлы созданные более 30 дней назад, что бы не скапливать мусор.&lt;/p&gt;</content><category term="Полезное"/><category term="cache"/><category term="htaccess"/><category term="images"/><category term="php"/><category term="картинки"/></entry><entry><title>C новым годом</title><link href="https://blog.rpsl.info/2010/12/novym-godom/" rel="alternate"/><published>2010-12-29T15:06:00+03:00</published><updated>2010-12-29T15:06:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2010-12-29:/2010/12/novym-godom/</id><content type="html">&lt;pre&gt;&lt;code class="perl"&gt;    ''=~(        '(?{'        .('`'        |'%')        .('['        ^'-')
    .('`'        |'!')        .('`'        |',')        .'&amp;quot;'.        '\\$'
    .'=='        .('['        ^'+')        .('`'        |'/')        .('['
    ^'+')        .'||'        .(';'        &amp;amp;'=')        .(';'        &amp;amp;'=')
    .';-'        .'-'.        '\\$'        .'=;'        .('['        ^'(')
    .('['        ^'.')        .('`'        |'&amp;quot;')        .('!'        ^'+')
   .'_\\{'      .'(\\$'      .';=('.      '\\$=|'      .&amp;quot;\|&amp;quot;.(      '`'^'.'
  ).(('`')|    '/').').'    .'\\&amp;quot;'.+(    '{'^'[').    ('`'|'&amp;quot;')    .('`'|'/'
 ).('['^'/')  .('['^'/').  ('`'|',').(  '`'|('%')).  '\\&amp;quot;.\\&amp;quot;'.(  '['^('(')).
 '\\&amp;quot;'.('['^  '#').'!!--'  .'\\$=.\\&amp;quot;'  .('{'^'[').  ('`'|'/').(  '`'|&amp;quot;\&amp;amp;&amp;quot;).(
 '{'^&amp;quot;\[&amp;quot;).(  '`'|&amp;quot;\&amp;quot;&amp;quot;).(  '`'|&amp;quot;\%&amp;quot;).(  '`'|&amp;quot;\%&amp;quot;).(  '['^(')')).  '\\&amp;quot;).\\&amp;quot;'.
 ('{'^'[').(  '`'|&amp;quot;\/&amp;quot;).(  '`'|&amp;quot;\.&amp;quot;).(  '{'^&amp;quot;\[&amp;quot;).(  '['^&amp;quot;\/&amp;quot;).(  '`'|&amp;quot;\(&amp;quot;).(
 '`'|&amp;quot;\%&amp;quot;).(  '{'^&amp;quot;\[&amp;quot;).(  '['^&amp;quot;\,&amp;quot;).(  '`'|&amp;quot;\!&amp;quot;).(  '`'|&amp;quot;\,&amp;quot;).(  '`'|(',')).
 '\\&amp;quot;\\}'.+(  '['^&amp;quot;\+&amp;quot;).(  '['^&amp;quot;\)&amp;quot;).(  '`'|&amp;quot;\)&amp;quot;).(  '`'|&amp;quot;\.&amp;quot;).(  '['^('/')).
 '+_,\\&amp;quot;,'.(  '{'^('[')).  ('\\$;!').(  '!'^&amp;quot;\+&amp;quot;).(  '{'^&amp;quot;\/&amp;quot;).(  '`'|&amp;quot;\!&amp;quot;).(
 '`'|&amp;quot;\+&amp;quot;).(  '`'|&amp;quot;\%&amp;quot;).(  '{'^&amp;quot;\[&amp;quot;).(  '`'|&amp;quot;\/&amp;quot;).(  '`'|&amp;quot;\.&amp;quot;).(  '`'|&amp;quot;\%&amp;quot;).(
 '{'^&amp;quot;\[&amp;quot;).(  '`'|&amp;quot;\$&amp;quot;).(  '`'|&amp;quot;\/&amp;quot;).(  '['^&amp;quot;\,&amp;quot;).(  '`'|('.')).  ','.(('{')^
 '[').(&amp;quot;\[&amp;quot;^  '+').(&amp;quot;\`&amp;quot;|  '!').(&amp;quot;\[&amp;quot;^  '(').(&amp;quot;\[&amp;quot;^  '(').(&amp;quot;\{&amp;quot;^  '[').(&amp;quot;\`&amp;quot;|
 ')').(&amp;quot;\[&amp;quot;^  '/').(&amp;quot;\{&amp;quot;^  '[').(&amp;quot;\`&amp;quot;|  '!').(&amp;quot;\[&amp;quot;^  ')').(&amp;quot;\`&amp;quot;|  '/').(&amp;quot;\[&amp;quot;^
 '.').(&amp;quot;\`&amp;quot;|  '.').(&amp;quot;\`&amp;quot;|  '$').&amp;quot;\,&amp;quot;.(  '!'^('+')).  '\\&amp;quot;,_,\\&amp;quot;'  .'!'.(&amp;quot;\!&amp;quot;^
 '+').(&amp;quot;\!&amp;quot;^  '+').'\\&amp;quot;'.  ('['^',').(  '`'|&amp;quot;\(&amp;quot;).(  '`'|&amp;quot;\)&amp;quot;).(  '`'|&amp;quot;\,&amp;quot;).(
 '`'|('%')).  '++\\$=&amp;quot;})'  );$:=('.')^  '~';$~='@'|  '(';$^=')'^  '[';$/='`';
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Кстати, это &lt;a href="http://99-bottles-of-beer.net/language-perl-737.html"&gt;исходный код&lt;/a&gt; на perl&lt;/p&gt;</content><category term="Заметки"/><category term="code"/><category term="perl"/><category term="source"/></entry><entry><title>Бюджетный NAS</title><link href="https://blog.rpsl.info/2010/10/byudzhetnyjj-nas/" rel="alternate"/><published>2010-10-30T16:13:00+04:00</published><updated>2010-10-30T16:13:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2010-10-30:/2010/10/byudzhetnyjj-nas/</id><summary type="html">&lt;p&gt;Уже почти месяц у меня дома живет NAS ( Network Attachment Storage ). Желание приобрести подобную игрушку появилось после того, как я устал держать включенным ноутбук для скачивания и транслирования торрентов на телек/playstation. Из первых попыток прощупывания почвы и выяснения оптимальных решений пришел к выводу, что мне нужен &lt;a href="http://www.readynas.com/?cat=3"&gt;ReadyNAS duo&lt;/a&gt; от компании Netgear.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Netgear" src="/images/2d8c/2f2e/2d8c2f2ef1cc1e5eb5fd123f75ffa34d.jpg"&gt; &lt;/p&gt;
&lt;p&gt;Кстати весьма странная ценовая политика в готовых решениях. Есть два варианта покупки:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Купить nas без жестких дисков&lt;/li&gt;
&lt;li&gt;Купить nas в комплекте с жестким диском.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Так вот, в комплекте с жестким диском на 500гб, средняя цена 10-11 тысяч рублей. Без жесткого диска устройство стоит 8 тысяч рублей, а на оставшиеся две тысячи я докупил жесткий диск на 1500гб. ???. Профит. &lt;/p&gt;
</summary><content type="html">&lt;p&gt;Уже почти месяц у меня дома живет NAS ( Network Attachment Storage ). Желание приобрести подобную игрушку появилось после того, как я устал держать включенным ноутбук для скачивания и транслирования торрентов на телек/playstation. Из первых попыток прощупывания почвы и выяснения оптимальных решений пришел к выводу, что мне нужен &lt;a href="http://www.readynas.com/?cat=3"&gt;ReadyNAS duo&lt;/a&gt; от компании Netgear.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Netgear" src="/images/2d8c/2f2e/2d8c2f2ef1cc1e5eb5fd123f75ffa34d.jpg"&gt; &lt;/p&gt;
&lt;p&gt;Кстати весьма странная ценовая политика в готовых решениях. Есть два варианта покупки:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Купить nas без жестких дисков&lt;/li&gt;
&lt;li&gt;Купить nas в комплекте с жестким диском.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Так вот, в комплекте с жестким диском на 500гб, средняя цена 10-11 тысяч рублей. Без жесткого диска устройство стоит 8 тысяч рублей, а на оставшиеся две тысячи я докупил жесткий диск на 1500гб. ???. Профит. &lt;/p&gt;


&lt;p&gt;Кроме стандартной функции, бездонной сетевой папки, в нем есть куча дополнительных плюшек.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Торрент качалка&lt;/li&gt;
&lt;li&gt;Работа в качестве медиа сервера для itunes и playstation&lt;/li&gt;
&lt;li&gt;Поддержка raid для увеличения скорости и дополнительной безопасности&lt;/li&gt;
&lt;li&gt;Возможность подключения дополнительных usb устройств&lt;/li&gt;
&lt;li&gt;Возможность устанавливать свои собственные расширения.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Установка и конфигурация прошла в три клика и не вызывала никаких проблем. Просто включил и все начало работать. Стандартную торрент качалку заменил на transmission c веб интерфейсом, из каталога расширений установил дополнение для opendns. Теперь очень удобно не имея постоянного ip всегда иметь возможность зайти через web-итерфейс и добавить пачку фильмов, которые уже скачаются к моему приходу. &lt;/p&gt;
&lt;p&gt;Собственно по поводу расширений стоит сказать отдельно, установка новых приложений выглядит как загрузка bin файла через веб интерфейс на устройство, с последующей перезагрузкой и появлением новых конфигурационных меню. &lt;/p&gt;
&lt;p&gt;Да и количество расширений вполне себе доставляет. &lt;a href="http://www.readynas.com/?cat=75"&gt;Найти&lt;/a&gt; можно в целом все, что необходимо.&lt;/p&gt;</content><category term="Полезное"/><category term="hardware"/><category term="nas"/><category term="playstation"/></entry><entry><title>seo rewrite rule</title><link href="https://blog.rpsl.info/2010/10/seo-rewrite-rule/" rel="alternate"/><published>2010-10-28T10:21:00+04:00</published><updated>2010-10-28T10:21:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2010-10-28:/2010/10/seo-rewrite-rule/</id><content type="html">&lt;p&gt;Оптимизаторы не знают что такое реврайты и эстетическая красота. А меня жутко бесит, когда в корне сайта лежит 100500 html файлов, которые очень нужны для продвижения.&lt;/p&gt;
&lt;p&gt;Приходится постоянно лечить.&lt;/p&gt;
&lt;pre&gt;&lt;code class="htaccess"&gt;RewriteRule   ^([a-z0-9_-]+).html$  static/seo_pages/$1.html [L,QSA]
&lt;/code&gt;&lt;/pre&gt;</content><category term="Полезное"/><category term="htaccess"/><category term="html"/><category term="seo"/></entry><entry><title>WordPress — gallery shorttag highslide</title><link href="https://blog.rpsl.info/2010/10/wordpress-gallery-shorttag-highslide/" rel="alternate"/><published>2010-10-13T10:32:00+04:00</published><updated>2010-10-13T10:32:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2010-10-13:/2010/10/wordpress-gallery-shorttag-highslide/</id><summary type="html">&lt;p&gt;Два примера, для решения одной и той же задачи.&lt;/p&gt;
&lt;p&gt;В первом примере полный идиотизм, во втором хорошее решение. Вот теперь вопрос, почему большая часть всех CMS работает как первый пример. ?  &lt;/p&gt;
</summary><content type="html">&lt;p&gt;Два примера, для решения одной и той же задачи.&lt;/p&gt;
&lt;p&gt;В первом примере полный идиотизм, во втором хорошее решение. Вот теперь вопрос, почему большая часть всех CMS работает как первый пример. ?  &lt;/p&gt;


&lt;p&gt;Убого:&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;add_filter('wp_get_attachment_link', 'add_rel');

/*
 * Add rel=&amp;quot;gallery-$id&amp;quot; to attachment links
 */

function add_rel ( $link )
{

    global $post;
    // a mild cheat. group by post id. the gallery_shortcode() $instance
    // static var would be better, but we can't get to it.
    $id = $post-&amp;gt;ID;

    // First, see if there's already a 'rel' attribute in the link:
    $atag = preg_match( '#&amp;lt;a \s+(.*?)(rel=([\'&amp;quot;])(.*?)\3)(.*?)&amp;gt;(.*)#i', $link, $matches );
    if ( $atag )
    {
        // Match found. Let's put Humpty Dumpty back together again:
        $quot = $matches [ 3 ];
        $relval = $quot . $matches [ 4 ] . &amp;quot; gallery-{$id}&amp;quot; . $quot;
        $before = $matches [ 1 ];
        $after = $matches [ 5 ];
        $rest = $matches [ 6 ];
        $link = &amp;quot;&amp;lt;/a&amp;gt;&amp;lt;a {$before}rel={$relval}{$after}&amp;gt;{$rest}&amp;quot;;
    }
    else
    {
        $atag = preg_match( '#&amp;lt;/a&amp;gt;&amp;lt;a \s+(.*?)&amp;gt;(.*)#i', $link, $matches );
        if ( $atag )
        {
            // This is a much simpler reassembly
            $innards = $matches [ 1 ];
            $rest = $matches [ 2 ];
            $relval = &amp;quot;gallery-{$id}&amp;quot;;
            $link = &amp;quot;&amp;lt;/a&amp;gt;&amp;lt;a {$innards} rel='{$relval}'&amp;gt;{$rest}&amp;quot;;
        }
    }
    return $link;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Нормально:&lt;/p&gt;
&lt;pre&gt;&lt;code class="javascript"&gt;function gallery_image_higslide()
{
    var gallery = $('.gallery').find('a');

    $.each( gallery, function() {
        var img = $(this).find('img');

        if( $(img).size() &amp;gt; 0 &amp;amp;&amp;amp; $(this).attr('onclick') == undefined ){
           $(this).addClass('highslide-image').click(function(){ return hs.expand(this); });
        }
    });
}

$(document).ready(function(){
    gallery_image_higslide();
});
&lt;/code&gt;&lt;/pre&gt;</content><category term="Полезное"/><category term="blog"/><category term="javascript"/><category term="jquery"/><category term="php"/><category term="wordpress"/></entry><entry><title>Варианты разные</title><link href="https://blog.rpsl.info/2010/08/varianty-raznye/" rel="alternate"/><published>2010-08-24T05:46:00+04:00</published><updated>2010-08-24T05:46:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2010-08-24:/2010/08/varianty-raznye/</id><summary type="html">&lt;p&gt;В детстве можно всегда лезть в драку, прыгать с тарзанки и гонять на велосипеде быстрее всех, ежегодно ломая себе что–нибудь. А можно обходить хулиганов стороной и вообще предпочитать телевизор. В 15 тебе будет наплевать, что у Васи был круче велосипед и все окрестные пацаны его боялись. 15 лет уже, взрослые люди, к чему этот детсад.&lt;/p&gt;
&lt;p&gt;В школе можно учиться на одни пятерки, учить химию и писать сочинения про Онегина, действительно размышляя о мотивах главных героев. А можно обойтись шаблонными фразами, домашку списать и закончить четверть как максимум без троек. В 18 лет внезапно выяснится, что с полным трояков аттестатом можно поступать хоть в МГУ, всем похуй. Школа она и есть школа, все ее заканчивают.&lt;/p&gt;
&lt;p&gt;В институте можно ходить на все лекции и семинары, записаться на три интересных спецсема, выбрать клевого научника и двигать с ним что–нибудь актуальное, тусуясь на конференциях. Можно выебать всех клевых однокурсниц, ездить в Крым автостопом, отвисая с хиппанами в Лисьей Бухте, основать митол–группу и записать альбом. А можно сидеть в интернетах и контре по ночам, пить пиво с такими же задротами, никуда не ходить, ботать экзамены в последнюю ночь и получать свой законный трояк. «Обзор существующих методов…» сойдет за тему диплома, потерять девственность по пьяни поможет подвернувшаяся каракатица а соседи по общаге сойдут за друзей.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;В детстве можно всегда лезть в драку, прыгать с тарзанки и гонять на велосипеде быстрее всех, ежегодно ломая себе что–нибудь. А можно обходить хулиганов стороной и вообще предпочитать телевизор. В 15 тебе будет наплевать, что у Васи был круче велосипед и все окрестные пацаны его боялись. 15 лет уже, взрослые люди, к чему этот детсад.&lt;/p&gt;
&lt;p&gt;В школе можно учиться на одни пятерки, учить химию и писать сочинения про Онегина, действительно размышляя о мотивах главных героев. А можно обойтись шаблонными фразами, домашку списать и закончить четверть как максимум без троек. В 18 лет внезапно выяснится, что с полным трояков аттестатом можно поступать хоть в МГУ, всем похуй. Школа она и есть школа, все ее заканчивают.&lt;/p&gt;
&lt;p&gt;В институте можно ходить на все лекции и семинары, записаться на три интересных спецсема, выбрать клевого научника и двигать с ним что–нибудь актуальное, тусуясь на конференциях. Можно выебать всех клевых однокурсниц, ездить в Крым автостопом, отвисая с хиппанами в Лисьей Бухте, основать митол–группу и записать альбом. А можно сидеть в интернетах и контре по ночам, пить пиво с такими же задротами, никуда не ходить, ботать экзамены в последнюю ночь и получать свой законный трояк. «Обзор существующих методов…» сойдет за тему диплома, потерять девственность по пьяни поможет подвернувшаяся каракатица а соседи по общаге сойдут за друзей.&lt;/p&gt;


&lt;p&gt;В 25 тебе на все это будет наплевать. Какая разница, кто там чего делал в институте, взрослые люди уже. Наука все равно в сраном говне, альбом сведен криво и стыдно даже показывать, меряться количеством баб в таком возрасте уже как–то и не принято.&lt;/p&gt;
&lt;p&gt;Можно основать свой бизнес, несколько лет тыкаясь по углам и получая опыт, о котором нигде не прочитаешь. Можно рвать задницу в офисе, доказывая, что это ты самый умный, это тебя нужно повысить и дать тебе большую машину, а то и вовсе отправить в головное отделение за бугор. Можно следить за собой, хорошо одеваться, назначать свидания, искать ту идеальную тян, с которой хочется прожить до конца.&lt;/p&gt;
&lt;p&gt;А можно стать программистом, получать хорошие деньги и кое–как отрывать задницу перед дедлайном. Ходить в застиранной майке, не бриться неделями, запивать изжогу вискарем с колой, считать всех окружающих тупым быдлом. Бабло есть, напрягаться не нужно. Какая–нибудь относительно не страшная девка неожиданно полюбит тебя и станет терпеливо ждать, когда же ты наконец слегка созреешь для семьи. Можно и жениться, от скуки.&lt;/p&gt;
&lt;p&gt;В 45 на все это будет наплевать. Мало ли, у кого там что было по молодости, сейчас кто не спился и жив тот и молодец, Чуть меньше денег, чуть больше, не важно уже, лишь бы был кто рядом. Можно расшибаться ради своей цели, идти вперед, учиться, въебывать, пока говно из ушей не польется и в конце уже добиться того, чего хотел. А можно спокойно прожить всю жизнь на отъебись, ища обходные пути и по привычке чувствовать себя крутым умным лайф–хакером.&lt;/p&gt;
&lt;p&gt;В старости всем на это похуй. Лишь бы не болело ничего.&lt;/p&gt;</content><category term="Заметки"/><category term="internet"/><category term="деньги"/><category term="жизнь"/></entry><entry><title>Кэширование MySQL - MySimpleCache</title><link href="https://blog.rpsl.info/2010/07/kehshirovanie-mysql-mysimplecache/" rel="alternate"/><published>2010-07-06T21:33:00+04:00</published><updated>2010-07-06T21:33:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2010-07-06:/2010/07/kehshirovanie-mysql-mysimplecache/</id><content type="html">&lt;p&gt;Собственно возвращаясь к прошлому посту - &lt;strong&gt;&lt;a href="http://blog.rpsl.info/2010/06/php-keshirovanie-mysql.html"&gt;PHP Кэширование MySQL&lt;/a&gt;&lt;/strong&gt;, хочу сказать спасибо всем, кто помог советами.&lt;/p&gt;
&lt;p&gt;По разным причинам, спустя несколько дней после прошлого поста, я все таки сел и написал этот велосипед. Перевел на него десяток говносайтов и наблюдал две недели за их поведением.&lt;/p&gt;
&lt;p&gt;Проблем не заметил, все работает хорошо, нагрузка на базу данных значительно упала, а это именно то, что и требовалось.&lt;/p&gt;
&lt;p&gt;Проект поселился на &lt;a href="http://github.com/Rpsl/MySimpleCache"&gt;github.com&lt;/a&gt;, маловероятно, но возможно он еще будет обновляться, так что актуальная версия всегда там. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://github.com/Rpsl/MySimpleCache"&gt;&lt;img alt="github.com" src="/images/f46b/d1c2/f46bd1c2b0cf47e3b056cefa4bb35064.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Логика работы проста. Что бы &lt;strong&gt;закэшировать MySQL&lt;/strong&gt; запрос, вы подключаете класс и делаете замену стандартных вызовов, на вызовы функций кеширования. Они являются синонимами, а значит вам нужно только перед вызовом дописать название класса.&lt;/p&gt;
&lt;p&gt;При вызове mysql_query, скрипт попытается закешировать данный запрос и либо вернет ссылку на закешированный массив, либо вернет ссылку на ресурс.&lt;/p&gt;
&lt;p&gt;Все последующие операции будут проверять является ли ссылка ресурсом и уже по обстоятельствам будут либо доставать данные из &lt;strong&gt;memcache&lt;/strong&gt;, либо получать их напрямую.&lt;/p&gt;
&lt;p&gt;Буду рад любым комментариям и повторяю еще раз, что крайне не рекомендую прикручивать этот скрипт на сайты которые чуть более серьезнее чем сателит.&lt;/p&gt;</content><category term="Полезное"/><category term="cache"/><category term="memcache"/><category term="mysimplecache"/><category term="mysql"/><category term="php"/><category term="sql"/></entry><entry><title>PHP Кеширование Mysql</title><link href="https://blog.rpsl.info/2010/06/php-keshirovanie-mysql/" rel="alternate"/><published>2010-06-27T16:04:00+04:00</published><updated>2010-06-27T16:04:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2010-06-27:/2010/06/php-keshirovanie-mysql/</id><content type="html">&lt;p&gt;&lt;img alt="mysql" src="/images/5194/74e6/519474e6a1485684b2751348ed65baf3.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPD:&lt;/strong&gt; Рабочая версия php
&lt;a href="http://blog.rpsl.info/2010/07/kehshirovanie-mysql-mysimplecache.html"&gt;MySimpleCache&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Други, мне требуется ваша помощь или совет.&lt;/p&gt;
&lt;p&gt;Такая ситуация, есть большая куча сайтов, написанных давным-давно. Они представляют из себя кучу файлов, в которых идет в перемешку php/html/sql запросы. Ни о каких современных паттернах программирования там речи нету. Переписывать эти сайты нет ни времени, ни желания, но они ужастно грузят БД.&lt;/p&gt;
&lt;p&gt;Задача добавить на эти сайты кеширование sql запросов. Переписывать их и править дело очень не благодарное и потребует кучу времени.&lt;/p&gt;
&lt;p&gt;Я поразмышлял и решил, что проще всего будет написать класс, который будет содержать в себе ф-ции синомы всех ф-ций для работы с бд.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;mysql_query&lt;br&gt;
 mysql_fetch_assoc&lt;br&gt;
 mysql_fetch_array&lt;br&gt;
 mysql_num_rows&lt;br&gt;
 mysql_result&lt;br&gt;
 ....&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Фишка в том, что они должны внутри себя пробовать кешировать запрос и либо возвращать результат запроса, либо возвращать закешированный результат.&lt;/p&gt;
&lt;p&gt;Данная идея мне кажется крутой, так как, она позволит легкой автозаменой включить кеширование на сайте и лишь потом в нужных местах его допилить.&lt;/p&gt;
&lt;p&gt;Теперь главное, я уверен что должны быть аналоги, а я пытаюсь изобрести велосипед. Возможно вы сталкивались с такими вещами и их решениями. Ну или просто можете высказать свое мнение по этому поводу. Не поленитесь, буду очень благодарен.&lt;/p&gt;</content><category term="Полезное"/><category term="cache"/><category term="memcache"/><category term="mysql"/><category term="php"/></entry><entry><title>Обфускатор Javascript</title><link href="https://blog.rpsl.info/2010/06/obfuskator-javascript/" rel="alternate"/><published>2010-06-11T21:04:00+04:00</published><updated>2010-06-11T21:04:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2010-06-11:/2010/06/obfuskator-javascript/</id><summary type="html">&lt;p&gt;На Хабре нашел ссылку на отличный инструмент для шифрования js от чужих глаз:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://utf-8.jp/public/jjencode.html"&gt;&lt;strong&gt;http://utf-8.jp/public/jjencode.html&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Например, &lt;code&gt;alert("test");&lt;/code&gt; превращается вот в такую конструкцию:&lt;/p&gt;
</summary><content type="html">&lt;p&gt;На Хабре нашел ссылку на отличный инструмент для шифрования js от чужих глаз:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://utf-8.jp/public/jjencode.html"&gt;&lt;strong&gt;http://utf-8.jp/public/jjencode.html&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Например, &lt;code&gt;alert("test");&lt;/code&gt; превращается вот в такую конструкцию:&lt;/p&gt;


&lt;pre&gt;&lt;code class="javascript"&gt;$=~[];
$={___:++$,$$$$:(![]+&amp;quot;&amp;quot;)[$],__$:++$,$_$_:(![]+&amp;quot;&amp;quot;)[$],_$_:++$,$_$$:({}+&amp;quot;&amp;quot;)[$],$$_$:($[$]+&amp;quot;&amp;quot;)[$],_$$:++$,$$$_:(!&amp;quot;&amp;quot;+&amp;quot;&amp;quot;)[$],$__:++$,$_$:++$,$$__:({}+&amp;quot;&amp;quot;)[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+&amp;quot;&amp;quot;)[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+&amp;quot;&amp;quot;)[$.__$])+((!$)+&amp;quot;&amp;quot;)[$._$$]+($.__=$.$_[$.$$_])+($.$=(!&amp;quot;&amp;quot;+&amp;quot;&amp;quot;)[$.__$])+($._=(!&amp;quot;&amp;quot;+&amp;quot;&amp;quot;)[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!&amp;quot;&amp;quot;+&amp;quot;&amp;quot;)[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+&amp;quot;&amp;quot;&amp;quot;+$.$_$_+(![]+&amp;quot;&amp;quot;)[$._$_]+$.$$$_+&amp;quot;&amp;quot;+$.__$+$.$$_+$._$_+$.__+&amp;quot;(&amp;quot;&amp;quot;+$.__+$.$$$_+&amp;quot;&amp;quot;+$.__$+$.$$_+$._$$+$.__+&amp;quot;&amp;quot;)&amp;quot;+$.$$$+$._$$+&amp;quot;&amp;quot;&amp;quot;)())();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Это полностью рабочий js-код.  &lt;/p&gt;
&lt;p&gt;Но разобрать, что именно он делает – нереально.  &lt;/p&gt;
&lt;p&gt;Юзайте для шифрования доменов редиректов и прочего.&lt;/p&gt;</content><category term="Shared"/><category term="javascript"/></entry><entry><title>Ну вот и обновились</title><link href="https://blog.rpsl.info/2010/06/nu-vot-i-obnovilis/" rel="alternate"/><published>2010-06-11T00:11:00+04:00</published><updated>2010-06-11T00:11:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2010-06-11:/2010/06/nu-vot-i-obnovilis/</id><content type="html">&lt;p&gt;&lt;img alt="blog.rpsl.info" src="/images/4a6f/5f94/4a6f5f94a6747ae13efefaab01e19887.png"&gt;&lt;/p&gt;
&lt;p&gt;Мелочей еще конечно много, но буду править и постараюсь снова начать писать.&lt;/p&gt;</content><category term="Заметки"/><category term="blog"/><category term="css"/><category term="design"/><category term="wordpress"/></entry><entry><title>Чат для vbulletin</title><link href="https://blog.rpsl.info/2010/03/chat-dlya-vbulletin/" rel="alternate"/><published>2010-03-05T11:47:00+03:00</published><updated>2010-03-05T11:47:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2010-03-05:/2010/03/chat-dlya-vbulletin/</id><content type="html">&lt;p&gt;Главное что бы было желания, все остальное уже дело техники.&lt;/p&gt;
&lt;p&gt;Очень давно я хотел сделать чатик для нашего уютного форума. Если кто-то помнит, то он даже был там очень давно, но тогда по техническим и эстетическим причинам его пришлось убрать.&lt;/p&gt;
&lt;p&gt;Несколько выходных назад я решил вернуться к этому вопросу, скачал стандартный чат для форума, но он как и все остальные подобные реализации являлся унылым говном. Это глупое окошко которое предлагается разместить после навбара или перед футером... Решение было принято моментально, а бутылка ликера добавила мне решительности.&lt;/p&gt;
&lt;p&gt;В итоге, просидев около 4 часов над сорцами чата и переделкой его стилей у нас получилась отличная консоль, которая открывается - закрывается по нажатию горячих клавиш и доступна всем зарегистрированным пользователям. Единственная проблема с которой я столкнулся - это кривое отображение в ie6, но решать её, по своим внутренним убеждениям я не собираюсь.&lt;/p&gt;
&lt;p&gt;Живой пример на &lt;a href="http://forum.centrgroup.ru"&gt;http://forum.centrgroup.ru&lt;/a&gt; (для зарегистрированных) Если кому интересна сама реализация - пишите в комменты, постараюсь рассказать.&lt;/p&gt;</content><category term="CMS"/><category term="centr"/><category term="php"/><category term="vbulletin"/><category term="форум"/></entry><entry><title>Livejournal in google reader</title><link href="https://blog.rpsl.info/2009/12/livejournal-in-google-reader/" rel="alternate"/><published>2009-12-23T16:28:00+03:00</published><updated>2009-12-23T16:28:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-12-23:/2009/12/livejournal-in-google-reader/</id><summary type="html">&lt;p&gt;&lt;img alt="livejournal" src="/images/2cf5/13ca/2cf513ca339e64a3d2ba84a7e725881f.jpg"&gt;  &lt;/p&gt;
&lt;p&gt;Давным давно, в одной далекой галактике, я сделал себе standalone блог и &lt;strong&gt;livejournal&lt;/strong&gt;, потихоньку начал пропадать из списка сайтов которые я посещаю ежедневно. Учитывая, что я читаю около пары сотен человек, то вариант захождения раз в неделю и чтения всех записей начинал сильно утомлять, т.к. трудно осилить пару сотен постов. В то же время я начал активно пользоваться &lt;strong&gt;google reader&lt;/strong&gt;'ом для чтения &lt;strong&gt;rss&lt;/strong&gt; каналов сайтов которые мне интересны.&lt;/p&gt;
&lt;p&gt;К сожалению и по не сильно понятным мне причинам, &lt;strong&gt;livejournal&lt;/strong&gt; не даёт читать френделенту через rss, но зато он позволяет подписаться на rss конкретных пользователей которые вам интересны. В то же время, в &lt;strong&gt;Google reader&lt;/strong&gt; есть возможность сортировать каналы по папкам, и если читать сразу всю папку, то получается как раз подобие френдленты. В целом всё хорошо, только этот вариант не подходит тем, у кого друзья пишут под замочные записи, но и тут тоже livejournal предусмотрел вариант аутентификации, для получения ленты с закрытыми записями.&lt;/p&gt;
&lt;p&gt;В интернете есть различные серивисы, включая pipes.yahoo.com и freemyfeed.com, которые могут выступать в роли прокси, но меня не устраивает вариант, когда мои пароли будут храниться не понятно где. Поэтому я сделал маленький прокси, которые автоматически авторизует вас для google reader'а и на выходе вы получаете полный feed ваших друзей.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;img alt="livejournal" src="/images/2cf5/13ca/2cf513ca339e64a3d2ba84a7e725881f.jpg"&gt;  &lt;/p&gt;
&lt;p&gt;Давным давно, в одной далекой галактике, я сделал себе standalone блог и &lt;strong&gt;livejournal&lt;/strong&gt;, потихоньку начал пропадать из списка сайтов которые я посещаю ежедневно. Учитывая, что я читаю около пары сотен человек, то вариант захождения раз в неделю и чтения всех записей начинал сильно утомлять, т.к. трудно осилить пару сотен постов. В то же время я начал активно пользоваться &lt;strong&gt;google reader&lt;/strong&gt;'ом для чтения &lt;strong&gt;rss&lt;/strong&gt; каналов сайтов которые мне интересны.&lt;/p&gt;
&lt;p&gt;К сожалению и по не сильно понятным мне причинам, &lt;strong&gt;livejournal&lt;/strong&gt; не даёт читать френделенту через rss, но зато он позволяет подписаться на rss конкретных пользователей которые вам интересны. В то же время, в &lt;strong&gt;Google reader&lt;/strong&gt; есть возможность сортировать каналы по папкам, и если читать сразу всю папку, то получается как раз подобие френдленты. В целом всё хорошо, только этот вариант не подходит тем, у кого друзья пишут под замочные записи, но и тут тоже livejournal предусмотрел вариант аутентификации, для получения ленты с закрытыми записями.&lt;/p&gt;
&lt;p&gt;В интернете есть различные серивисы, включая pipes.yahoo.com и freemyfeed.com, которые могут выступать в роли прокси, но меня не устраивает вариант, когда мои пароли будут храниться не понятно где. Поэтому я сделал маленький прокси, которые автоматически авторизует вас для google reader'а и на выходе вы получаете полный feed ваших друзей.&lt;/p&gt;


&lt;pre&gt;&lt;code class="php"&gt;&amp;lt;?php
    if ( !empty( $_GET [ 'feed' ] ) )
    {

        $_GET [ 'feed' ] = str_replace( '_', '-', $_GET [ 'feed' ] );

        header( &amp;quot;Content-Type: text/xml; charset=utf-8&amp;quot; );
        $ch = curl_init();
        curl_setopt( $ch, CURLOPT_URL, $_GET [ 'feed' ] . '?auth=digest' );
        curl_setopt( $ch, CURLOPT_AUTOREFERER, true );
        curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
        curl_setopt( $ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST );
        curl_setopt( $ch, CURLOPT_USERPWD, 'жжлогин:жжпароль' );
        $data = curl_exec( $ch );
        curl_close( $ch );
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;После размещения данного файла на хостинге, вам осталось только получить opml файл, ваших друзей, для добавления его в google reader.&lt;/p&gt;
&lt;p&gt;Можно воспользоваться стандартным средством livejournal: &lt;code&gt;http://www.livejournal.com/tools/opml.bml?user=username&lt;/code&gt; но, он выдаст список, который не свернется в папку автоматически, так, что если вы не знаете как отредактировать файл самостоятельно, то лучше просто воспользуйтесь другим сервисом, например этим: &lt;code&gt;http://www.hungry.com/~fn/foaf.cgi&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;После того, как вы скачаете файл, вам нужно его отредактировать, открываете и делаете автозамену (ctrl+h) c:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;xmlUrl=&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;на:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;xmlUrl=&amp;quot;http://путь до вашего скрипта?feed=
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Всё. Закончили.&lt;/p&gt;
&lt;p&gt;Теперь вам нужно зайти в google reader и импортировать этот файл, это делается в настройках (импорт/экспорт).
После первого добавления, в папке будет сплошная каша, но все новые посты начнут добавятся в нормальном порядке.&lt;/p&gt;
&lt;p&gt;Удачного чтения.&lt;/p&gt;</content><category term="Полезное"/><category term="Google"/><category term="livejournal"/><category term="php"/><category term="rss"/></entry><entry><title>Twitter it для vBulletin</title><link href="https://blog.rpsl.info/2009/11/twitter-it-dlya-vbulletin/" rel="alternate"/><published>2009-11-04T20:21:00+03:00</published><updated>2009-11-04T20:21:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-11-04:/2009/11/twitter-it-dlya-vbulletin/</id><summary type="html">&lt;p&gt;На днях, мне захотелось сделать наш форум еще более интегрированным в, не побоюсь этого слова, великую социальную сеть twitter.&lt;/p&gt;
&lt;p&gt;Сначала была идея сделать возможность автоматической отправки новых тем из выбранных разделов в некий твиттер аккаунт, потом это обдумывалось и свелось до того, что бы была возможность отправлять в твиттер ссылки на темы, но при этом не сам форум будет спамить темы, а пользователи сам должны решать за себя.&lt;/p&gt;
&lt;p&gt;Первый вариант, который был реализован, заключался в простом добавление кнопки в шаблон, которая содержит в себе необходимый URL, но как выяснилось, это вариант не очень удобен, т.к. он не будет работать с некоторыми символами, которые встречаются в тексте.&lt;/p&gt;
&lt;p&gt;В итоге я просто создал модуль который генерирует ссылку, а в шаблон добавил простую кнопку и ву-аля.&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/284c/31b5/284c31b5ea0fab411d2c93ce2e62d6d5.png"&gt;&lt;img alt="twitterit" src="/images/284c/31b5/284c31b5ea0fab411d2c93ce2e62d6d5.png"&gt;&lt;/a&gt;&lt;/p&gt;
</summary><content type="html">&lt;p&gt;На днях, мне захотелось сделать наш форум еще более интегрированным в, не побоюсь этого слова, великую социальную сеть twitter.&lt;/p&gt;
&lt;p&gt;Сначала была идея сделать возможность автоматической отправки новых тем из выбранных разделов в некий твиттер аккаунт, потом это обдумывалось и свелось до того, что бы была возможность отправлять в твиттер ссылки на темы, но при этом не сам форум будет спамить темы, а пользователи сам должны решать за себя.&lt;/p&gt;
&lt;p&gt;Первый вариант, который был реализован, заключался в простом добавление кнопки в шаблон, которая содержит в себе необходимый URL, но как выяснилось, это вариант не очень удобен, т.к. он не будет работать с некоторыми символами, которые встречаются в тексте.&lt;/p&gt;
&lt;p&gt;В итоге я просто создал модуль который генерирует ссылку, а в шаблон добавил простую кнопку и ву-аля.&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/284c/31b5/284c31b5ea0fab411d2c93ce2e62d6d5.png"&gt;&lt;img alt="twitterit" src="/images/284c/31b5/284c31b5ea0fab411d2c93ce2e62d6d5.png"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;Для начала нужно создать модуль:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Продукт - &lt;strong&gt;vBulletin&lt;/strong&gt;  &lt;/li&gt;
&lt;li&gt;Местоположение модуля - &lt;code&gt;postbit_display_complete&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Имя - &lt;strong&gt;Twitter It&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Код модуля:&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;$twitterit = $post[title].&amp;quot; http://siteurl/showthread.php?t=&amp;quot;.$thread[threadid].&amp;quot; #tag&amp;quot;;
$twitterit = iconv('WINDOWS-1251', 'UTF-8', $twitterit); // Если у вас не UTF-8
$twitterit = urlencode(htmlspecialchars_decode($twitterit));
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tag&lt;/code&gt; и &lt;code&gt;siteurl&lt;/code&gt; соответственно прописываете сами&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Теперь нам осталось добавить вывод кнопок в шаблон. По умолчанию, за вывод сообщений отвечает шаблон &lt;code&gt;postbit&lt;/code&gt; (&lt;code&gt;postbit_legacy&lt;/code&gt; - если у вас Аватарки сбоку)&lt;/p&gt;
&lt;p&gt;И добавляем в необходимое место вывод кнопки:&lt;/p&gt;
&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;a href=&amp;quot;$twitterit&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;nofollow&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;$stylevar[imgdir_button]/twitterit.gif&amp;quot; alt=&amp;quot;Twitter It!&amp;quot; border=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;If&lt;/code&gt; - мы используем для того, что бы кнопка отображалась только в первом сообщение темы.&lt;/p&gt;</content><category term="Полезное"/><category term="centr"/><category term="php"/><category term="vbulletin"/><category term="форум"/></entry><entry><title>Фотоблоги / фотоблог / фото блог</title><link href="https://blog.rpsl.info/2009/10/fotoblogi-fotoblog-foto-blog/" rel="alternate"/><published>2009-10-07T21:44:00+04:00</published><updated>2009-10-07T21:44:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-10-07:/2009/10/fotoblogi-fotoblog-foto-blog/</id><summary type="html">&lt;p&gt;Честно говоря, я очень удивлен, что у нас не очень популярны фотоблоги.
У всех есть мобильные телефоны, почти у всех они с фото камерами, у
большинства с камерами приемлемого качества. Многие используют твиттер,
почту, icq на телефоне, но мало кто делает фотографии и выкладывает их в
сеть.  &lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/wp-content/uploads/2009/10/photoblog.png"&gt;&lt;img alt="photoblog" src="/images/c4d8/a39b/c4d8a39b39b6ea715333ae4b1ec3d72e.png"&gt;&lt;/a&gt;  &lt;/p&gt;
&lt;p&gt;Сейчас я расскажу о нескольких способах организации этого дела.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Фотоблог — вебсайт, содержащий в своей основе регулярно публикуемые
фотографии, часто сопровождаемые названием снимка, датой/временем,
текстовым описанием, сведениями Exif и др. Фотоблог часто содержит
возможность добавления комментариев, выставления рейтинга и т. п.
Фотоблог может поддерживать технологию RSS или Atom.&lt;/p&gt;
&lt;p&gt;Фотоблог может быть авторским или коллективным. Встречаются мобильные
фотоблоги (сделанные с помощью фотокамер, встроенные в мобильные
телефоны). Как разновидность, появились текстовые фотоблоги (в которых
фотография заменена авторским текстовым описанием).&lt;/p&gt;
&lt;p&gt;wikipedia&lt;/p&gt;
&lt;/blockquote&gt;
</summary><content type="html">&lt;p&gt;Честно говоря, я очень удивлен, что у нас не очень популярны фотоблоги.
У всех есть мобильные телефоны, почти у всех они с фото камерами, у
большинства с камерами приемлемого качества. Многие используют твиттер,
почту, icq на телефоне, но мало кто делает фотографии и выкладывает их в
сеть.  &lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/wp-content/uploads/2009/10/photoblog.png"&gt;&lt;img alt="photoblog" src="/images/c4d8/a39b/c4d8a39b39b6ea715333ae4b1ec3d72e.png"&gt;&lt;/a&gt;  &lt;/p&gt;
&lt;p&gt;Сейчас я расскажу о нескольких способах организации этого дела.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Фотоблог — вебсайт, содержащий в своей основе регулярно публикуемые
фотографии, часто сопровождаемые названием снимка, датой/временем,
текстовым описанием, сведениями Exif и др. Фотоблог часто содержит
возможность добавления комментариев, выставления рейтинга и т. п.
Фотоблог может поддерживать технологию RSS или Atom.&lt;/p&gt;
&lt;p&gt;Фотоблог может быть авторским или коллективным. Встречаются мобильные
фотоблоги (сделанные с помощью фотокамер, встроенные в мобильные
телефоны). Как разновидность, появились текстовые фотоблоги (в которых
фотография заменена авторским текстовым описанием).&lt;/p&gt;
&lt;p&gt;wikipedia&lt;/p&gt;
&lt;/blockquote&gt;


&lt;p&gt;Что нам потребуется:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Телефон с фотокамерой и доступом в интернет&lt;/li&gt;
&lt;li&gt;Аккаунт в гугле&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Для чего нам нужен телефон думаю и так понятно, теперь вопрос про гугл. Суть в том, что для первичной публикации мы будем использовать &lt;a href="http://blogger.com"&gt;blogger.com&lt;/a&gt;. Он обладает всеми необходимыми функциями для организации блога и онлайн публикации, т.к. блоггер это один из сервисов гугла, то авторизоваться можно с помощью гугл аккаунта + все фотографии будут автоматически заливаться в галерею на &lt;a href="http://picasaweb.google.com"&gt;picasaweb.google.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Теперь два способа ведения блога:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Простой (для пользователей Sony Erricsson)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Когда вы сделали очередную фотографию, вы можете выбрать в контекстном меню пункт отправить, затем выбрать пункт "В блог". После чего фотографиия автоматически зальётся в ваш блог.&lt;/p&gt;
&lt;p&gt;Когда вы отправите первую фотографию, вам в ответ придет смс с кодом активации и адресом блога. В последующем вы сможете его поменять, на более приличный.&lt;/p&gt;
&lt;p&gt;Всё. Теперь вам осталось только фотографировать и отправлять.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Более сложный (для пользователей любых телефонов)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Блоггер в свою очередь поддерживает не только встроенное приложение, но так же получение фотографий по средствам MMS и E-mail.&lt;/p&gt;
&lt;p&gt;Отправлять каждый раз MMS как то не выгодно, поэтому я пропущу данный этап, но если вас это интересует, то все инструкции можно найти в самом блоггере - http://www.blogger.com/mobile-start.g&lt;/p&gt;
&lt;p&gt;Рассмотрим более подробно отправку почтовых сообщений.&lt;/p&gt;
&lt;p&gt;Первое, что необходимо сделать, это настроить электропочту в вашем телефоне.&lt;/p&gt;
&lt;p&gt;Затем идем в &lt;a href="http://www.blogger.com/home"&gt;блоггер&lt;/a&gt;, около вашего блога выбираем "&lt;strong&gt;настройки&lt;/strong&gt;" и редактируем пункт "Адрес отправки электронной почты (Mail2blogger)".&lt;/p&gt;
&lt;p&gt;Указав нужные нам параметры, сохраняемся и создаем в записной книге нашего телефона запись "Blogger", указав ей введенный выше email.&lt;/p&gt;
&lt;p&gt;Всё. Готово. Теперь открыв фотографию на телефоне, выбираем пункт отправить - email - выбираем нужного нам пользователя (blogger) и отправляем.&lt;/p&gt;
&lt;p&gt;В ближайшее время, я так же постараюсь привести в порядок свой сервис, который читает фотоблог и делает трансляцию фотографий в другие сети.&lt;/p&gt;
&lt;p&gt;Удачных фотосетов.&lt;/p&gt;</content><category term="Полезное"/><category term="blog"/><category term="blogger"/><category term="Google"/><category term="picasa"/><category term="sony"/><category term="Фото"/></entry><entry><title>PHP Кэширование картинок</title><link href="https://blog.rpsl.info/2009/08/php-images-cache/" rel="alternate"/><published>2009-08-27T15:05:00+04:00</published><updated>2009-08-27T15:05:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-08-27:/2009/08/php-images-cache/</id><summary type="html">&lt;p&gt;Недавно была необходимость сделать функцию &lt;strong&gt;кэширования картинок на php&lt;/strong&gt; ну я и написал простой скрипт, который отлично справляется с этой задачей.&lt;/p&gt;
&lt;p&gt;Логика работы скрипта очень простая. Он смотрит входящие параметры, проверяет есть ли картинка заданного размера и отдает её если она есть или создает в подпапке  такую картинку и отдает её.&lt;/p&gt;
&lt;p&gt;Это спасает нас от необходимости делать кучу ресайзов при загрузке картинки + это универсальный способ, который можно использовать в любом проекте.&lt;/p&gt;
&lt;p&gt;Листинг под катом.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Недавно была необходимость сделать функцию &lt;strong&gt;кэширования картинок на php&lt;/strong&gt; ну я и написал простой скрипт, который отлично справляется с этой задачей.&lt;/p&gt;
&lt;p&gt;Логика работы скрипта очень простая. Он смотрит входящие параметры, проверяет есть ли картинка заданного размера и отдает её если она есть или создает в подпапке  такую картинку и отдает её.&lt;/p&gt;
&lt;p&gt;Это спасает нас от необходимости делать кучу ресайзов при загрузке картинки + это универсальный способ, который можно использовать в любом проекте.&lt;/p&gt;
&lt;p&gt;Листинг под катом.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;images_cache.php&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;// ------ Define's --------------

$file_folder = $_SERVER['DOCUMENT_ROOT'].&amp;quot;/images&amp;quot;;
$file_image  = $_GET['image'];
$file_size   = $_GET['size'];

// ------------------------------

if(empty($file_size)){
    $file_size = 50;
}

function img_resize($src, $dest, $width, $height, $rgb = 0xFFFFFF, $quality = 100) {
    $size = getimagesize($src);

    if ($size === false) {
        return false;
    }

    $format = strtolower(substr($size['mime'], strpos($size['mime'], '/') + 1));
    $icfunc = 'imagecreatefrom'.$format;

    if (!function_exists($icfunc)) {
        return false;
    }

    $x_ratio = $width  / $size[0];
    $y_ratio = $height / $size[1];

    if ($height == 0) {

        $y_ratio = $x_ratio;
        $height  = $y_ratio * $size[1];

    } elseif ($width == 0) {

        $x_ratio = $y_ratio;
        $width   = $x_ratio * $size[0];

    }

    $ratio       = min($x_ratio, $y_ratio);
    $use_x_ratio = ($x_ratio == $ratio);

    $new_width   = $use_x_ratio  ? $width  : floor($size[0] * $ratio);
    $new_height  = !$use_x_ratio ? $height : floor($size[1] * $ratio);
    $new_left    = $use_x_ratio  ? 0 : floor(($width - $new_width)   / 2);
    $new_top     = !$use_x_ratio ? 0 : floor(($height - $new_height) / 2);

    $isrc  = $icfunc($src);
    $idest = imagecreatetruecolor($width, $height);

    imagefill($idest, 0, 0, $rgb);
    imagecopyresampled($idest, $isrc, $new_left, $new_top, 0, 0, $new_width, $new_height, $size[0], $size[1]);

    imagejpeg($idest, $dest, $quality);

    imagedestroy($isrc);
    imagedestroy($idest);

    return true;
}

$file_destination_folder = $file_folder.'/'.$file_size.'/';
$file_destination        = $file_folder.'/'.$file_size.'/'.$file_image;

if(!file_exists($file_destination)){

    if (!is_dir($file_destination_folder)) {
        if(!mkdir($file_destination_folder, 0777)){
            exit();
        }
    }

    img_resize($file_folder.'/'.$file_image, $file_destination, $file_size, 0);
}

$file_final_size = getimagesize($file_destination);

header(&amp;quot;Content-type: &amp;quot;.$file_final_size['mime']);
header('Content-Length: ' . filesize($file_destination));
readfile($file_destination);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Далее, что бы всё было красиво, нам нужно добавить запись в .htaccess, что бы наши картинки имели нормальные адреса  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;.htaccess&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="htaccess"&gt;RewriteRule   ^image/([0-9]+)/(.*)$  images_cache.php?size=$1&amp;amp;image=$2 [L,QSA]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Плюс, для оптимизации картинок, можно повесить в крон &lt;a href="http://habrahabr.ru/blogs/wordpress/42192/"&gt;shell скрипт от Александра Улизько&lt;/a&gt;.  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;images_optimize.sh&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;for file in `find . -iname &amp;quot;*.jpg&amp;quot; -or -iname &amp;quot;*.png&amp;quot; -or -iname &amp;quot;*.jpeg&amp;quot;`;do
  ext=${file##*.}
  if [ -n &amp;quot;$ext&amp;quot; ]; then
    if [ &amp;quot;$ext&amp;quot; = &amp;quot;jpg&amp;quot; ]; then
      echo &amp;quot;optimizing ${file} as jpeg file with jpegtran&amp;quot;
      jpegtran -copy none -optimize -perfect -outfile temp_abracadabra_filename.jpg $file
      mv -f temp_abracadabra_filename.jpg $file;
    fi
    if [ &amp;quot;$ext&amp;quot; = &amp;quot;jpeg&amp;quot; ]; then
      echo &amp;quot;optimizing ${file} as jpeg file with jpegtran&amp;quot;
      jpegtran -copy none -optimize -perfect -outfile temp_abracadabra_filename.jpeg $file
      mv -f temp_abracadabra_filename.jpeg $file;
    fi
    if [ &amp;quot;$ext&amp;quot; = &amp;quot;png&amp;quot; ]; then
      echo &amp;quot;optimizing ${file} as png file with pngcrush&amp;quot;
      pngcrush -rem alla -reduce -brute &amp;quot;$file&amp;quot; temp_abracadabra_filename.png;
      mv -f temp_abracadabra_filename.png $file;
    fi
  fi
done;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; &lt;a href="http://blog.rpsl.info/2011/03/php-kehshirovanie-kartinok-chast-vtoraya.html"&gt;Часть вторая&lt;/a&gt;&lt;/p&gt;</content><category term="Полезное"/><category term="bash"/><category term="images"/><category term="optimize"/><category term="php"/></entry><entry><title>SQL Joins Виды, типы, различия</title><link href="https://blog.rpsl.info/2009/07/sql-joins-vidy-tipy-razlichiya/" rel="alternate"/><published>2009-07-27T22:56:00+04:00</published><updated>2009-07-27T22:56:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-07-27:/2009/07/sql-joins-vidy-tipy-razlichiya/</id><summary type="html">&lt;p&gt;В первую очередь шпаргалка для себя, но надеюсь кому нибудь окажется полезным.&lt;/p&gt;
&lt;p&gt;Для начала оговорим, что у нас есть две таблицы: &lt;strong&gt;Table A&lt;/strong&gt; и &lt;strong&gt;Table B&lt;/strong&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;id name id name  &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;1 &lt;span style="color: red"&gt;Pirate&lt;/span&gt; 1 Rutabaga&lt;br&gt;
 2 Monkey 2 &lt;span style="color: red"&gt;Pirate&lt;/span&gt;&lt;br&gt;
 3 &lt;span style="color: red"&gt;Ninja&lt;/span&gt; 3 Darth Vader&lt;br&gt;
 4 Spaghetti 4 &lt;span style="color: red"&gt;Ninja&lt;br&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Теперь можно рассмотреть, варианты и различия возможных JOIN запросов.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Inner join&lt;/strong&gt; выведет записи, которые соответствуют  таблице A и
таблице B.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/wp-content/uploads/2009/07/join-inner.png"&gt;&lt;img alt="join-inner" src="/images/f0fc/f576/f0fcf5762a49546af7addc7d37210d80.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;SELECT * FROM TableA&lt;br&gt;
&lt;strong&gt;INNER JOIN&lt;/strong&gt; TableB&lt;br&gt;
 ON TableA.name = TableB.name&lt;/p&gt;
&lt;p&gt;id name id name  &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;1 Pirate 2 Pirate&lt;br&gt;
 3 Ninja 4 Ninja&lt;/p&gt;
&lt;/blockquote&gt;
</summary><content type="html">&lt;p&gt;В первую очередь шпаргалка для себя, но надеюсь кому нибудь окажется полезным.&lt;/p&gt;
&lt;p&gt;Для начала оговорим, что у нас есть две таблицы: &lt;strong&gt;Table A&lt;/strong&gt; и &lt;strong&gt;Table B&lt;/strong&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;id name id name  &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;1 &lt;span style="color: red"&gt;Pirate&lt;/span&gt; 1 Rutabaga&lt;br&gt;
 2 Monkey 2 &lt;span style="color: red"&gt;Pirate&lt;/span&gt;&lt;br&gt;
 3 &lt;span style="color: red"&gt;Ninja&lt;/span&gt; 3 Darth Vader&lt;br&gt;
 4 Spaghetti 4 &lt;span style="color: red"&gt;Ninja&lt;br&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Теперь можно рассмотреть, варианты и различия возможных JOIN запросов.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Inner join&lt;/strong&gt; выведет записи, которые соответствуют  таблице A и
таблице B.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/wp-content/uploads/2009/07/join-inner.png"&gt;&lt;img alt="join-inner" src="/images/f0fc/f576/f0fcf5762a49546af7addc7d37210d80.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;SELECT * FROM TableA&lt;br&gt;
&lt;strong&gt;INNER JOIN&lt;/strong&gt; TableB&lt;br&gt;
 ON TableA.name = TableB.name&lt;/p&gt;
&lt;p&gt;id name id name  &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;1 Pirate 2 Pirate&lt;br&gt;
 3 Ninja 4 Ninja&lt;/p&gt;
&lt;/blockquote&gt;


&lt;p&gt;&lt;strong&gt;Full outer join&lt;/strong&gt; выведет все записи из Таблицы A и Таблицы B, сопоставив данные из обеих таблиц, если в одной из таблиц данные отсутсвуют, то результатом для данной ячейки будет "NULL"&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/wp-content/uploads/2009/07/join-cartesian.png"&gt;&lt;img alt="join-cartesian" src="/images/23d8/945e/23d8945ee2e18072b7c11376a803b4e2.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;SELECT * FROM TableA&lt;br&gt;
&lt;strong&gt;FULL OUTER JOIN&lt;/strong&gt; TableB&lt;br&gt;
 ON TableA.name = TableB.name&lt;/p&gt;
&lt;p&gt;id name id name  &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;1 Pirate 2 Pirate&lt;br&gt;
 2 Monkey &lt;span style="color: gray"&gt;null&lt;/span&gt; &lt;span
style="color: gray"&gt;null&lt;/span&gt;&lt;br&gt;
 3 Ninja 4 Ninja&lt;br&gt;
 4 Spaghetti &lt;span style="color: gray"&gt;null&lt;/span&gt; &lt;span
style="color: gray"&gt;null&lt;/span&gt;&lt;br&gt;
 &lt;span style="color: gray"&gt;null&lt;/span&gt; &lt;span
style="color: gray"&gt;null&lt;/span&gt; 1 Rutabaga&lt;br&gt;
 &lt;span style="color: gray"&gt;null&lt;/span&gt; &lt;span
style="color: gray"&gt;null&lt;/span&gt; 3 Darth Vader&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Left outer join&lt;/strong&gt; выведет данные из Таблицы A, с сопутсвующими данными из Таблицы B. Если подходящих данных в Таблице B нету, то будет выбран "NULL"&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/wp-content/uploads/2009/07/join-left.png"&gt;&lt;img alt="join-left" src="/images/212d/04b0/212d04b068ad2bebccda3832977342c8.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;SELECT * FROM TableA&lt;br&gt;
&lt;strong&gt;LEFT OUTER JOIN&lt;/strong&gt; TableB&lt;br&gt;
 ON TableA.name = TableB.name&lt;/p&gt;
&lt;p&gt;id name id name  &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;1 Pirate 2 Pirate&lt;br&gt;
 2 Monkey &lt;span style="color: gray"&gt;null&lt;/span&gt; &lt;span
style="color: gray"&gt;null&lt;/span&gt;&lt;br&gt;
 3 Ninja 4 Ninja&lt;br&gt;
 4 Spaghetti &lt;span style="color: gray"&gt;null&lt;/span&gt; &lt;span
style="color: gray"&gt;null&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Оперируя прошлым примером, нам не составит труда достать только те
данные, которые есть в Таблице A, для этого нужно использовть &lt;strong&gt;left
outer join&lt;/strong&gt;, с исключением пустых записей из Таблицы B&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/wp-content/uploads/2009/07/join-left-outer.png"&gt;&lt;img alt="join-left-outer" src="/images/a792/174e/a792174e259db7c24ceafe9c4b2d39b7.png"&gt;&lt;/a&gt;SELECT
* FROM TableA&lt;br&gt;
 LEFT OUTER JOIN TableB&lt;br&gt;
 ON TableA.name = TableB.name&lt;br&gt;
&lt;strong&gt;WHERE TableB.id IS null&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;id name id name  &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;2 Monkey &lt;span style="color: gray"&gt;null&lt;/span&gt; &lt;span
style="color: gray"&gt;null&lt;/span&gt;&lt;br&gt;
 4 Spaghetti &lt;span style="color: gray"&gt;null&lt;/span&gt; &lt;span
style="color: gray"&gt;null&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;А если, чуть чуть усложнить задачу, то мы лего достанем данные, которые
не имеют ничего общего. Для этого нужно использовать &lt;strong&gt;full outer
join&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/wp-content/uploads/2009/07/join-outer.png"&gt;&lt;img alt="join-outer" src="/images/37ce/e565/37cee565ca6b9df943360ebe3b7a4700.png"&gt;&lt;/a&gt;SELECT
* FROM TableA&lt;br&gt;
 FULL OUTER JOIN TableB&lt;br&gt;
 ON TableA.name = TableB.name&lt;br&gt;
&lt;strong&gt;WHERE TableA.id IS null&lt;br&gt;
 OR TableB.id IS null&lt;br&gt;
&lt;/strong&gt;&lt;br&gt;
 id name id name  &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;2 Monkey &lt;span style="color: gray"&gt;null&lt;/span&gt; &lt;span
style="color: gray"&gt;null&lt;/span&gt;&lt;br&gt;
 4 Spaghetti &lt;span style="color: gray"&gt;null&lt;/span&gt; &lt;span
style="color: gray"&gt;null&lt;/span&gt;&lt;br&gt;
 &lt;span style="color: gray"&gt;null&lt;/span&gt; &lt;span
style="color: gray"&gt;null&lt;/span&gt; 1 Rutabaga&lt;br&gt;
 &lt;span style="color: gray"&gt;null&lt;/span&gt; &lt;span
style="color: gray"&gt;null&lt;/span&gt; 3 Darth Vader&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Вот собственно и всё. Всё просто.&lt;/p&gt;
&lt;p&gt;P.s. Данная статья является вольным переводом некой статьи, авторство которой мне не известно.&lt;/p&gt;</content><category term="Полезное"/><category term="join"/><category term="mysql"/><category term="sql"/></entry><entry><title>Человеческий фактор</title><link href="https://blog.rpsl.info/2009/06/chelovecheskij-faktor/" rel="alternate"/><published>2009-06-08T00:44:00+04:00</published><updated>2009-06-08T00:44:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-06-08:/2009/06/chelovecheskij-faktor/</id><summary type="html">&lt;blockquote&gt;
&lt;p&gt;Для человеческой глупости нет патча (с) Kevin Mitnick&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Последние пару месяцев просто поражают спонтанностью происшествий,
главное, что потом, когда анализируешь их становится "и смешно и
грустно". Я конечно могу и дальше списывать всё на злой рок и на дядьку
Мерфи, на которого уже ссылался несколько постов назад, но делу это не
поможет.&lt;/p&gt;
&lt;p&gt;Например последней ситуацией, которую можно назвать только как "Пиздец
подкрался незаметно", когда с утра меня разбудили звонком, в котором
сообщали что вместо сайта &lt;strong&gt;группы CENTR&lt;/strong&gt; (centrgroup.ru) открывается
страница от reg.ru сообщающая, что домен не оплачен бла-бла-бла. Сначала
подумал, что это шутка. Домены я оплачиваю вовремя, а у centr'a домены
оплачиваются когда на улице снег лежит, так что подвох. Открыл, смотрю и
правда, не работает. Резолвю, ip совсем другой.&lt;/p&gt;
&lt;p&gt;Лезу в админ панель доменов посмотреть что там, попутно звоню в суппорт
и насилую консоль что бы понять в чем дело. В голове и мысли об
уязвимости DNS пролетели, и про киберсквотеров подумал, но решение
оказалось куда проще. Некто, проебал оплату домена, на котором весят NS
(name server) и так как его стало форвардить на другой ip, то и
остальные сайты, к которым он был привязан поехали в след за ним.&lt;/p&gt;
&lt;p&gt;Благо проблему решили довольно быстро и успели как раз к 12 часовому
апу. Так, что те, у кого провайдер не косячит с обновлением dns, скорее
всего и не заметили ошибку.&lt;/p&gt;
</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;Для человеческой глупости нет патча (с) Kevin Mitnick&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Последние пару месяцев просто поражают спонтанностью происшествий,
главное, что потом, когда анализируешь их становится "и смешно и
грустно". Я конечно могу и дальше списывать всё на злой рок и на дядьку
Мерфи, на которого уже ссылался несколько постов назад, но делу это не
поможет.&lt;/p&gt;
&lt;p&gt;Например последней ситуацией, которую можно назвать только как "Пиздец
подкрался незаметно", когда с утра меня разбудили звонком, в котором
сообщали что вместо сайта &lt;strong&gt;группы CENTR&lt;/strong&gt; (centrgroup.ru) открывается
страница от reg.ru сообщающая, что домен не оплачен бла-бла-бла. Сначала
подумал, что это шутка. Домены я оплачиваю вовремя, а у centr'a домены
оплачиваются когда на улице снег лежит, так что подвох. Открыл, смотрю и
правда, не работает. Резолвю, ip совсем другой.&lt;/p&gt;
&lt;p&gt;Лезу в админ панель доменов посмотреть что там, попутно звоню в суппорт
и насилую консоль что бы понять в чем дело. В голове и мысли об
уязвимости DNS пролетели, и про киберсквотеров подумал, но решение
оказалось куда проще. Некто, проебал оплату домена, на котором весят NS
(name server) и так как его стало форвардить на другой ip, то и
остальные сайты, к которым он был привязан поехали в след за ним.&lt;/p&gt;
&lt;p&gt;Благо проблему решили довольно быстро и успели как раз к 12 часовому
апу. Так, что те, у кого провайдер не косячит с обновлением dns, скорее
всего и не заметили ошибку.&lt;/p&gt;


&lt;p&gt;Второй недавний случай - это еще одна банальная ошибка. В
какой то момент перестало работать соединение с сервером по ssh. Долго я
голову ломал что происходит. Конфиги смотрел, с разных тачек пробовал -
ничего. Бился несколько дней, пока не заметил, что ошибка была в номере
порта. В конфиге был прописан xxxy, а я как последний * пытался зайти
на xxyy.&lt;/p&gt;
&lt;p&gt;К чему это всё? Да хочу, что бы мои читатели были мудрецами и учились на
чужих ошибках. Проверяйте всё и всегда и несколько раз. Я потом как
нибудь расскажу, как ошибка в одном символе поспособствовала рассылке
35000 писем.&lt;/p&gt;</content><category term="Заметки"/><category term="centr"/><category term="dns"/><category term="админ"/><category term="жизнь"/></entry><entry><title>Грамотный backup</title><link href="https://blog.rpsl.info/2009/05/true-backup/" rel="alternate"/><published>2009-05-23T14:28:00+04:00</published><updated>2009-05-23T14:28:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-05-23:/2009/05/true-backup/</id><summary type="html">&lt;p&gt;В последнее время, всё больше и больше озадачиваюсь вопросами организации "резервного хранилища". Пока еще не делал никаких подвижек в эту сторону, а просто думаю над возможными вариантами. Сильно в эту тему тоже не углублялся, так что пост больше походит на "мысли в слух".&lt;/p&gt;
&lt;p&gt;Для начала нужно определиться, что нужно бэкапить:&lt;/p&gt;
&lt;p&gt;Необходимо:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;сайты&lt;/li&gt;
&lt;li&gt;рабочие папки (home folder) cо всех машин за которыми работаю.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Желательно:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Музыкальное хранилище.&lt;/li&gt;
&lt;li&gt;Видео хранилище. Причем под видео, я воспринимаю не только папку&lt;/li&gt;
&lt;li&gt;"Downloads", а в первую очередь накопленный почти за год архив с Creative VADO.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Из возможных решений проблемы, рассматривал несколько вариантов:&lt;br&gt;
</summary><content type="html">&lt;p&gt;В последнее время, всё больше и больше озадачиваюсь вопросами организации "резервного хранилища". Пока еще не делал никаких подвижек в эту сторону, а просто думаю над возможными вариантами. Сильно в эту тему тоже не углублялся, так что пост больше походит на "мысли в слух".&lt;/p&gt;
&lt;p&gt;Для начала нужно определиться, что нужно бэкапить:&lt;/p&gt;
&lt;p&gt;Необходимо:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;сайты&lt;/li&gt;
&lt;li&gt;рабочие папки (home folder) cо всех машин за которыми работаю.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Желательно:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Музыкальное хранилище.&lt;/li&gt;
&lt;li&gt;Видео хранилище. Причем под видео, я воспринимаю не только папку&lt;/li&gt;
&lt;li&gt;"Downloads", а в первую очередь накопленный почти за год архив с Creative VADO.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Из возможных решений проблемы, рассматривал несколько вариантов:&lt;br&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Локальный компьютер&lt;/li&gt;
&lt;li&gt;Удаленный сервер&lt;/li&gt;
&lt;li&gt;Отдельный, домашний компьютер&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;К сожалению, не один из этих вариантов мне не подходит.&lt;/p&gt;
&lt;p&gt;Локальный компьютер у мне работает не 24/7.&lt;/p&gt;
&lt;p&gt;Удаленный сервер, именно потому, что он "удаленный", а я хочу, что бы все важные мне вещи всегда были под рукой.&lt;/p&gt;
&lt;p&gt;Отдельный компьютер собирать тоже не хочется, т.к. для него нужно место, он будет шуметь, да и вообще, зачем стрелять дробью в мух.&lt;/p&gt;
&lt;p&gt;Удачно вспомнил, что около года назад, мой коллега, приобрел себе отличный кейс для hdd "Vantec NexStar LX"&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/f271/67e0/f27167e0dcc1f4ece2bcb4979e2b29b8.jpg"&gt;&lt;img alt="46101" src="/images/f271/67e0/f27167e0dcc1f4ece2bcb4979e2b29b8.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Вот его отзывы об устройстве:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Задолбал меня системник тарахтящий под столом, решил прикупить вот такую хрень. &lt;/p&gt;
&lt;p&gt;Стоит коробка размером с МАС mini и не жужжит. Через 10 минут засыпает, при вызове по ссылке включается и велком. &lt;/p&gt;
&lt;p&gt;Простой интерфейс, удаленное управление, сменный HDD на любой желаемый объём, делает проверку ежедневно диска. Надо чего залить, удалить или подкорректировать, подрубаю к компу через USB или удаленно Суперюзером захожу и вуаля. При подключение к компу напрямую по Ethernet, умеет выдавать IP по DHCP. Всего 2000руб. Я доволен!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Решил прикупить себе такой же. Благо с "реальными ip" уже дано проблем нету, и воткнуть его для доступа в интернет не проблема. Или как вариант, в целях повышения безопасности, через роутер повесить его на "нестандартный" порт.&lt;/p&gt;
&lt;p&gt;Если у вас есть опыт создания подобных, домашних, систем, то отпишитесь пожалуйста.&lt;/p&gt;</content><category term="Полезное"/><category term="backup"/><category term="device"/><category term="hdd"/><category term="internet"/><category term="Linux"/></entry><entry><title>Почему не работал centrgroup.ru</title><link href="https://blog.rpsl.info/2009/05/pochemu-ne-rabotal-centrgroupru/" rel="alternate"/><published>2009-05-15T13:48:00+04:00</published><updated>2009-05-15T13:48:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-05-15:/2009/05/pochemu-ne-rabotal-centrgroupru/</id><content type="html">&lt;p&gt;3 суток даунтайма - это не "хухры-мухры". Я конечно постарался всех подготовить, но сам не ожидал что выйдет так долго.&lt;/p&gt;
&lt;p&gt;Как все должно было быть:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;12 числа в 11:00 мы забираем сервер из старого ДЦ&lt;/li&gt;
&lt;li&gt;14:00 он уже в новом ДЦ&lt;/li&gt;
&lt;li&gt;15:00 заканчиваем с настройками, ставим в стойку и ждем когда у всех  обновятся &lt;a href="http://ru.wikipedia.org/wiki/Domain_Name_System" title="Domain Name System"&gt;DNS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Радуемся жизни&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Как все получилось на самом деле:&lt;/p&gt;
&lt;p&gt;Мы забрали сервер из ДЦ, привезли его на нашу площадку, но запускаться он категорически отказывался т.к. несколько демонов вешали его работу.&lt;/p&gt;
&lt;p&gt;Пока пытались их утихомирить, из-за неведомо-опастной-хуйни упал &lt;a href="http://ru.wikipedia.org/wiki/RAID"&gt;RAID&lt;/a&gt;. Начали танцевать с бубном и восстанавливать инфу. Промучались до 14 числа. 14 числа когда система была заново установленна, переносили весь день файлы, восстанавливали настройки хостинга и демонов.&lt;/p&gt;
&lt;p&gt;Короче пздц полный. Все эти дни проклинал дядьку &lt;a href="http://murphy-law.net.ru/"&gt;Мерфи и егозаконы&lt;/a&gt;.&lt;/p&gt;</content><category term="Заметки"/><category term="centr"/><category term="dns"/><category term="hosting"/></entry><entry><title>Автоматическое обновление wordpress</title><link href="https://blog.rpsl.info/2009/05/automatic-upgrade-wordpress/" rel="alternate"/><published>2009-05-14T00:06:00+04:00</published><updated>2009-05-14T00:06:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-05-14:/2009/05/automatic-upgrade-wordpress/</id><summary type="html">&lt;p&gt;Есть в wordpress'e такая занимательная опция, как автоматическая установка и обновление плагинов. Просит от вас только указать хост, логин и пароль для ftp sftp доступа, а далее делает всё сама. К сожалению "из коробки" эта опция заводится далеко не у всех. Если вы тоже стали одним из счастливых обладателей сообщения:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Downloading update from
http://downloads.wordpress.org/plugin/%plugin-name%.zip

Download failed.: Could not create Temporary file
Installation Failed
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;... то сделать вам нужно следующие&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Есть в wordpress'e такая занимательная опция, как автоматическая установка и обновление плагинов. Просит от вас только указать хост, логин и пароль для ftp sftp доступа, а далее делает всё сама. К сожалению "из коробки" эта опция заводится далеко не у всех. Если вы тоже стали одним из счастливых обладателей сообщения:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Downloading update from
http://downloads.wordpress.org/plugin/%plugin-name%.zip

Download failed.: Could not create Temporary file
Installation Failed
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;... то сделать вам нужно следующие&lt;/p&gt;


&lt;p&gt;Создать темповую папку для хранилища. Например wp-contents/tmp Выставить на неё права доступа 777 &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;chmod -R 0777 ./wp-contents/tmp
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Дописать в файл wp-config.php строчку:&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;define ('WP_TEMP_DIR', ABSPATH . 'wp-content/tmp');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Если у вас на сервере сильно ограниченно время выполнения скриптов и во время инсталяции выпадает ошибка, то тогда можно попробовать дописать в начало ./wp-admin/upgrade.php&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;set_time_limit(0);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Также желательно конечно завести отдельного пользвователя на ftp/sftp с ограниченными правами. &lt;/p&gt;
&lt;p&gt;Вроде все. Больше проблем возникать не должно.&lt;/p&gt;</content><category term="CMS"/><category term="php"/><category term="update"/><category term="wordpress"/></entry><entry><title>Hotkeys для wordpress</title><link href="https://blog.rpsl.info/2009/05/hotkeys-dlya-wordpress/" rel="alternate"/><published>2009-05-11T20:29:00+04:00</published><updated>2009-05-11T20:29:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-05-11:/2009/05/hotkeys-dlya-wordpress/</id><summary type="html">&lt;p&gt;В этой заметке, я расскажу как легко добавить в ваш блог поддержку hotkey's.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hotkey - это определенное сочетание клавиш, по нажатию которых происходит определенное действие. Мы уже привыкли использовать ctrl+c/ctrl+v. Тенденции развития интернета диктуют свою моду и многие уже привыкли использовать для перехода между страницами сайта сочетание "ctrl+left" или "ctrl+right"&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Для добавления этого функционала, первое что нам потребуется - плагин hotkey для библиотеки jquery.&lt;/p&gt;
&lt;p&gt;jQuery hotkey&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/js-hotkeys/"&gt;Скачать&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jshotkeys.googlepages.com/test-static-01.html"&gt;Демо&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Теперь о том, как это сделать. У нас есть два варианта:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Генерировать код в самом шаблоне с помощью встроенных функций&lt;/li&gt;
&lt;li&gt;Генерировать код "на лету", с помощью JS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я выбрал второй вариант, т.к. он мне показался более правильным, во первых мы не напрягаем шаблон лишними вызовами, и главное мы уверенны что будем получать правильные ссылки. Ведь нам нужно на главной странице листать все записи, в категории листать записи категории, а внутри поста листать посты. Таким образом, всё что нам осталось, это добавить в header шаблон (скорее всего header.php) нижеприведенный код.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;В этой заметке, я расскажу как легко добавить в ваш блог поддержку hotkey's.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hotkey - это определенное сочетание клавиш, по нажатию которых происходит определенное действие. Мы уже привыкли использовать ctrl+c/ctrl+v. Тенденции развития интернета диктуют свою моду и многие уже привыкли использовать для перехода между страницами сайта сочетание "ctrl+left" или "ctrl+right"&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Для добавления этого функционала, первое что нам потребуется - плагин hotkey для библиотеки jquery.&lt;/p&gt;
&lt;p&gt;jQuery hotkey&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/js-hotkeys/"&gt;Скачать&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jshotkeys.googlepages.com/test-static-01.html"&gt;Демо&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Теперь о том, как это сделать. У нас есть два варианта:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Генерировать код в самом шаблоне с помощью встроенных функций&lt;/li&gt;
&lt;li&gt;Генерировать код "на лету", с помощью JS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я выбрал второй вариант, т.к. он мне показался более правильным, во первых мы не напрягаем шаблон лишними вызовами, и главное мы уверенны что будем получать правильные ссылки. Ведь нам нужно на главной странице листать все записи, в категории листать записи категории, а внутри поста листать посты. Таким образом, всё что нам осталось, это добавить в header шаблон (скорее всего header.php) нижеприведенный код.&lt;/p&gt;


&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;/js/jquery.hotkeys-0.7.9.min.js&amp;quot; &amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Подразумевается, что вы уже скачали библиотеку и положили её в папку /js/ вашей темы. Также, обратите внимание, что код вызова библиотеки должен быть добавлен после вызова самого jQuery.&lt;/p&gt;
&lt;p&gt;Далее дописываем наш обработчик.&lt;/p&gt;
&lt;pre&gt;&lt;code class="javascript"&gt;jQuery(document).ready(function(){
    var nextlink = jQuery('.alignright a').attr('href');
    var prevlink = jQuery('.alignleft a').attr('href');

    if(nextlink != undefined){
        jQuery(document).bind('keydown', 'Ctrl+right', function(){
            location.href=nextlink;
        });
    }

    if(prevlink != undefined){
        jQuery(document).bind('keydown', 'Ctrl+left', function(){
            location.href=prevlink;
        });
    }

});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Теперь главное. Обратите внимание на строки где определяются ссылки.&lt;/p&gt;
&lt;pre&gt;&lt;code class="javascript"&gt;var nextlink = jQuery('.alignright a').attr('href');
var prevlink = jQuery('.alignleft a').attr('href');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;alignright и alignleft это название классов, в которых у меня генерируются ссылки на следующую и предыдущую страницу, так что вам наверняка потребуется поменять эти названия на ваши, в зависимости от используемой вами темы.&lt;/p&gt;
&lt;p&gt;Вот и всё. После проделывания данных ваш блог должен стать на ступеньку ближе к заветному "WEB 2.0".&lt;/p&gt;
&lt;p&gt;Живой пример можете посмотреть в &lt;a href="http://blog.rpsl.info"&gt;моём блоге&lt;/a&gt;, нажимая "Ctrl+Left" OR "Ctrl+Right"&lt;/p&gt;</content><category term="CMS"/><category term="blog"/><category term="javascript"/><category term="php"/><category term="web2.0"/><category term="wordpress"/></entry><entry><title>Интеграция phpbb3 с любым сайтом</title><link href="https://blog.rpsl.info/2009/04/integraciya-phpbb3-s-lyubym-sajtom/" rel="alternate"/><published>2009-04-24T14:00:00+04:00</published><updated>2009-04-24T14:00:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-04-24:/2009/04/integraciya-phpbb3-s-lyubym-sajtom/</id><summary type="html">&lt;p&gt;Не очень давно, по работе, пришлось делать &lt;strong&gt;интеграцию&lt;/strong&gt; уже имеющегося сайта, &lt;strong&gt;с форумом на системе phpBB&lt;/strong&gt; 3-ей версии.&lt;/p&gt;
&lt;p&gt;После разбора полетов и курения мануалов по работе форума, организовалась очень интересная и простая система. Если говорить о её плюсах, то она полностью независима от форума, таким образом, при обнолении движка, мы уверены что не потерям правленные нами ранее файлы и что ничего не поломается.&lt;/p&gt;
&lt;p&gt;Для того, что бы понимать зачем и как это делать, сначала я постараюсь объяснить логику работы. Из уже готовых изменений, нам нужно добавить в БД сайта, дополнительное поле, например - &lt;code&gt;user_f_id&lt;/code&gt;, в которое мы будем записывать информацию о сопоставлении профилей пользователей сайта, с профилями пользовталей форума (предполагается числовой идентификатор, &lt;code&gt;user_id&lt;/code&gt; из БД форума - таблицы &lt;code&gt;%prefix%_users&lt;/code&gt;).&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Не очень давно, по работе, пришлось делать &lt;strong&gt;интеграцию&lt;/strong&gt; уже имеющегося сайта, &lt;strong&gt;с форумом на системе phpBB&lt;/strong&gt; 3-ей версии.&lt;/p&gt;
&lt;p&gt;После разбора полетов и курения мануалов по работе форума, организовалась очень интересная и простая система. Если говорить о её плюсах, то она полностью независима от форума, таким образом, при обнолении движка, мы уверены что не потерям правленные нами ранее файлы и что ничего не поломается.&lt;/p&gt;
&lt;p&gt;Для того, что бы понимать зачем и как это делать, сначала я постараюсь объяснить логику работы. Из уже готовых изменений, нам нужно добавить в БД сайта, дополнительное поле, например - &lt;code&gt;user_f_id&lt;/code&gt;, в которое мы будем записывать информацию о сопоставлении профилей пользователей сайта, с профилями пользовталей форума (предполагается числовой идентификатор, &lt;code&gt;user_id&lt;/code&gt; из БД форума - таблицы &lt;code&gt;%prefix%_users&lt;/code&gt;).&lt;/p&gt;


&lt;ol&gt;
&lt;li&gt;Пользователь заполняет на сайте поля login и password&lt;/li&gt;
&lt;li&gt;Проверяем, заполненно ли у предпологаемого пользователя поле user_f_id&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Если заполненно, то:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Запускаем функцию авторизации пользователя через форумную БД (листинг ниже)&lt;/li&gt;
&lt;li&gt;Если пароль не подходит, то выходим. Если подходит, то ставим авторизию на сайте + авторизацию на форуме&lt;/li&gt;
&lt;li&gt;Авторизация на форуме делается путем установки кук + добавлением записи в таблицу &lt;code&gt;%prefix%_sessions&lt;/code&gt; БД форума (листинг ниже)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Если не заполнено, то:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Скрипт производит стандартные функции валидации пароля&lt;/li&gt;
&lt;li&gt;Если пароль не подходит, то выходим, если подходит, то запускаем функции установки сопоставления&lt;/li&gt;
&lt;li&gt;Создаем запись в БД форума о пользователе (таблица &lt;code&gt;%prefix%_users&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Созадем запись в БД форума о правах пользователя (таблица &lt;code&gt;%prefix%_user_group&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Заполняем в БД нашего сайта поле &lt;code&gt;user_f_id&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Собственно всё. Теперь мы имеем систему, благодаря которой уже зарегистрированные пользователи, при первом входе заведут себе новый аккаунт на форуме. По какому критерию их сравнивать (логин, почта) это уже решайте сами.&lt;/p&gt;
&lt;p&gt;Естественно нужно еще дописать функии, которые при регистрации пользователей будут создавать учетную запись на форуме. И чтобы при авторизации несуществующего пользователя на сайте, при правильном форумном логине и пароле, ему автоматически создавалась учетная запись на сайте.&lt;/p&gt;
&lt;p&gt;Листинг ф-ций, которые проверяют пароль из форумной базы:&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;// phpbb_hash($password) - Создание пароля
// phpbb_check_hash($password, $hash) - Верификация пароля

function unique_id()
{
    return substr(md5(rand().'_'.microtime().'_'.rand()), rand(0, 15), 16);
}

function _hash_gensalt_private($input, &amp;amp;$itoa64, $iteration_count_log2 = 6)
{
    if ($iteration_count_log2 &amp;lt; 4 || $iteration_count_log2 31)
    {
        $iteration_count_log2 = 8;
    }
    $output = '$H$';
    $output .= $itoa64[min($iteration_count_log2 + ((PHP_VERSION &amp;gt;= 5) ? 5 : 3), 30)];
    $output .= $_hash_encode64($input, 6, $itoa64); return $output;
}

function _hash_encode64($input, $count, &amp;amp;$itoa64)
{
    $output = '';
     $i = 0;

    do
    {
        $value = ord($input[$i++]);
         $output .= $itoa64[$value &amp;amp; 0x3f];

        if ($i &amp;lt; $count)
        {
            $value |= ord($input[$i]) &amp;lt;&amp;lt; 8;
        }

        $output .= $itoa64[($value &amp;gt;6) &amp;amp; 0x3f];

        if ($i++ &amp;gt;= $count)
        {
            break;
        }

        if ($i &amp;lt; $count)
        {
            $value |= ord($input[$i]) &amp;lt;&amp;lt; 16;
        }

        $output .= $itoa64[($value &amp;gt;12) &amp;amp; 0x3f];

        if ($i++ &amp;gt;= $count)
        {
            break;
        }

        $output .= $itoa64[($value &amp;gt;18) &amp;amp; 0x3f];
    }
     while ($i &amp;lt; $count);

    return $output;
}

function _hash_crypt_private($password, $setting, &amp;amp;$itoa64)
{
    $output = '*';
    // Check for correct hash
    if (substr($setting, 0, 3) != '$H$')
    {
        return $output;
    }
    $count_log2 = strpos($itoa64, $setting[3]);
    if ($count_log2 &amp;lt; 7 || $count_log2 30)
    {
        return $output;
    }
    $count = 1 &amp;lt;&amp;lt; $count_log2;
    $salt = substr($setting, 4, 8);
    if (strlen($salt)
    != 8)
    {
        return $output;
    }
    if (PHP_VERSION &amp;gt;= 5)
    {
        $hash = md5($salt . $password, true);
        do
        {
            $hash = md5($hash . $password, true);
        }
         while (--$count);
    }
    else
    {
        $hash = pack('H*', md5($salt . $password));
        do
        {
            $hash = pack('H*', md5($hash . $password));
        }
         while (--$count);
    }
    $output = substr($setting, 0, 12);
    $output .= $_hash_encode64($hash, 16, $itoa64);
    return $output;
}

public function phpbb_hash($password)
{
    $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    $random_state = $unique_id();
    $random = '';
    $count = 6;
    if (($fh = @fopen('/dev/urandom', 'rb')))
    {
        $random = fread($fh, $count);
         fclose($fh);
    }
    if (strlen($random) &amp;lt; $count)
    {
        $random = '';
        for ($i = 0; $i &amp;lt; $count; $i += 16)
        {
            $random_state = md5($unique_id() . $random_state);
            $random .= pack('H*', md5($random_state));
        }
         $random = substr($random, 0, $count);
    }
    $hash = $_hash_crypt_private($password, $_hash_gensalt_private($random, $itoa64), $itoa64);
    if (strlen($hash) == 34)
    {
        return $hash;
    }
    return md5($password);
}

function phpbb_check_hash($password, $hash)
{
    $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    if (strlen($hash) == 34)
    {
        return ($_hash_crypt_private($password, $hash, $itoa64) === $hash) ? true : false;
    }

    return (md5($password) === $hash) ? true : false;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Массив для добавления записи о сессии в БД форума.&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;$browser = get_browser(null, true);

$ss = array(
  'sid'          =md5(date('U').rand(0,20)),
  'user_id'      =$forum['user_id'],
  'forum_id'     ='0',
  'last_visit'   =date('U'),
  'start_time'   =date('U'),
  'session_time' =date('U')+86400,
  'session_page' ='index.php',
  'remote_ip'    =getenv('REMOTE_ADDR'),
  'browser'      =htmlspecialchars($browser['browser_name_pattern']),
  'autologin'    ='1'
);
&lt;/code&gt;&lt;/pre&gt;</content><category term="Полезное"/><category term="php"/><category term="phpbb"/><category term="форум"/></entry><entry><title>PlayStation 3 - мысли вслух</title><link href="https://blog.rpsl.info/2009/04/playstation-3-misli-v-slux-ili-luchi-v-storonu-ps3/" rel="alternate"/><published>2009-04-05T14:34:00+04:00</published><updated>2009-04-05T14:34:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-04-05:/2009/04/playstation-3-misli-v-slux-ili-luchi-v-storonu-ps3/</id><summary type="html">&lt;blockquote&gt;
&lt;p&gt;Я не сомневаюсь, что ребята из Sony гораздо лучше меня знаю как делать деньги, что нужно пользователям и т.д., но мне все таки хочется выразить свои мысли об этой игровой системе.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/2009/04/05/2477189721_57e2f2ba25.jpg"&gt;&lt;img alt="2477189721_57e2f2ba25.jpg" src="/images/0b93/a6e7/0b93a6e714b67b6fe33aef5361517661.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Начать хочется с цены, средняя по Мск ~16000 за приставку на 80гб, два джойстика &lt;strong&gt;sixaxis dualshock 3&lt;/strong&gt; и какую либо игру в подарок.&lt;/p&gt;
&lt;p&gt;Согласитесь, не маленькая. Есть более дешевые варианты, с меньшим жестким диском и отсутствием одного джойстика, но как показывает практика, если покупать &lt;strong&gt;ps3&lt;/strong&gt; не "просто что бы было", то лучше раскошелиться на нормальный вариант, чем потом докупать составляющие.&lt;/p&gt;
</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;Я не сомневаюсь, что ребята из Sony гораздо лучше меня знаю как делать деньги, что нужно пользователям и т.д., но мне все таки хочется выразить свои мысли об этой игровой системе.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/2009/04/05/2477189721_57e2f2ba25.jpg"&gt;&lt;img alt="2477189721_57e2f2ba25.jpg" src="/images/0b93/a6e7/0b93a6e714b67b6fe33aef5361517661.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Начать хочется с цены, средняя по Мск ~16000 за приставку на 80гб, два джойстика &lt;strong&gt;sixaxis dualshock 3&lt;/strong&gt; и какую либо игру в подарок.&lt;/p&gt;
&lt;p&gt;Согласитесь, не маленькая. Есть более дешевые варианты, с меньшим жестким диском и отсутствием одного джойстика, но как показывает практика, если покупать &lt;strong&gt;ps3&lt;/strong&gt; не "просто что бы было", то лучше раскошелиться на нормальный вариант, чем потом докупать составляющие.&lt;/p&gt;


&lt;p&gt;Интересно также то, что её пытаются продвигать и как домашний медиа центр. Ну а чем плохо? Blu-ray есть, видео, музыку и фото может искать по сети.&lt;/p&gt;
&lt;p&gt;Вот только, мне это кажется такой же полудохлой функцией, как и всё что в ней есть, кроме игр. Есть великолепный &lt;strong&gt;playstation store&lt;/strong&gt;, в котором можно купить игры, скачать обновления и который принимает кредитки. Странно только, что продажа фильмов доступна только под EN аккаунтом. Я честно с удовольствием покупал бы лицензионные фильмы, если бы они появлялись в их магазине. Я не думаю что у sony есть проблемы и они не могут договориться, с локальными производителями, что бы распространять кино новинки через свой сервис.&lt;/p&gt;
&lt;p&gt;Довольно печально, что они, так и не предусмотрели совместную работу с другими популярными устройствами. Я например являюсь обладателем ipod и скажу, что послушать музыку с него через ps3 является большой проблемой. Дело в том, что ps3 не умеет читать iTunesDB, а все файлы в на ipod хранятся с поломанными именами, в абсолютном рандоме и найти тот, который хочется, является большой проблемой.&lt;/p&gt;
&lt;p&gt;Было бы здорово слушать подкасты. Не лезть для этого на сайт подкаста, просто увидеть "нотифи", о том что новый подкаст загружен.&lt;/p&gt;
&lt;p&gt;Очень расстраивает отсутствие виджетов, или системы расширений. Потому что, я бы хотел иметь нормальную читалку rss через встроенную а систему, а не через google reader.&lt;/p&gt;
&lt;p&gt;Хорошо, что хоть научили дефолтный броузер отображать flash. Теперь осталось научить его рендерить страницы хотя бы на уровне ie6 =). Может толк из него и выйдет.&lt;/p&gt;
&lt;p&gt;Радует, что они предусмотрели систему загрузки другой ОС, и говорят, что умельцы сумели запустить fedora linux на ps3. В целом использую другую систему можно смело собрать отличный медиа сервер, но это еще тот геморрой, да и за такую цену, хочется иметь это из коробки.&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/NnAn3h7kTM4" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Очень интересует мнение людей, которые являются обладателями ps3, не поленитесь, отпишите.&lt;/p&gt;</content><category term="Полезное"/><category term="Linux"/><category term="PlayStation 3"/><category term="PS3"/><category term="sony"/></entry><entry><title>Google Picasa on your site</title><link href="https://blog.rpsl.info/2009/03/google-picasa-on-your-site/" rel="alternate"/><published>2009-03-26T13:48:00+03:00</published><updated>2009-03-26T13:48:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-03-26:/2009/03/google-picasa-on-your-site/</id><content type="html">&lt;p&gt;Уже давно, в &lt;a href="http://twitter.com/Rpsl"&gt;своем твиттере&lt;/a&gt;, я обещал рассказать как встроить фото галерею пикасы в свой сайт.&lt;/p&gt;
&lt;p&gt;Идея довольно простая: "Зачем изобретать велосипед, если можно использовать мотокомбайн?".&lt;/p&gt;
&lt;p&gt;Рыская по глубинам интернета, я нашел замечательный скрипт picasaViewer. Написан он на JavaScript и является плагином для mooTools.&lt;/p&gt;
&lt;p&gt;Настройки весьма простые: в файле picasaViewer.js указываем username пользователя, фото галереи которого хотим отображать.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/2009/03/26/picasa.png"&gt;&lt;img alt="picasa.png" src="/images/347b/8a72/347b8a72bfd26863e07beb142458cd92.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Из плюсов стоит отметить то, что он работает почти со всем современными броузерами и не требуют серверных мощностей для выполнения.&lt;/p&gt;
&lt;p&gt;Из минусов то, что написан он на moo и возможно, что будет конфликтовать с другими js фреймворками.&lt;/p&gt;
&lt;p&gt;Готовый пак (с slimbox дополнением), забираем с зеркала в моем блоге.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Download:
&lt;a href="http://blog.rpsl.info/2009/03/26/picasaview.zip"&gt;picasaview.zip&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Удачного использования.&lt;/p&gt;</content><category term="Полезное"/><category term="Ajax"/><category term="images"/><category term="javascript"/><category term="mootools"/><category term="photo"/><category term="picasa"/></entry><entry><title>Моvable Type 4.25</title><link href="https://blog.rpsl.info/2009/03/movable-type-425/" rel="alternate"/><published>2009-03-26T13:17:00+03:00</published><updated>2009-03-26T13:17:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-03-26:/2009/03/movable-type-425/</id><content type="html">&lt;p&gt;Обновил. Вроде всё прошло как по маслу, благо бэкапы делаются постоянно и сильно не переживал.&lt;/p&gt;
&lt;p&gt;Единственный косяк был на этапе обновления mySQL, когда MT начал ругаться:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;**undefined type: mediumtext**
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Пришлось вспоминать, как эту проблему я победил в прошлый раз, вспомнил. Просто на время обновления отключил все плагины путем переименования папки "plugins". Обновилось, включил, всё хорошо.&lt;/p&gt;
&lt;p&gt;Порадовало обновление плагинов авторизации. Теперь повесить коммент под своим ником еще проще чем раньше.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/2009/03/26/auth.png"&gt;&lt;img alt="auth.png" src="/images/dcfb/96d5/dcfb96d54f7a64dac50a970067844e53.png"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="CMS"/><category term="CMS"/><category term="movable type 2.25"/><category term="обновление movable type"/><category term="русский movable type"/></entry><entry><title>F.lux - ритмы вашего монитора</title><link href="https://blog.rpsl.info/2009/03/flux-ritmy-vashego-monitora/" rel="alternate"/><published>2009-03-18T01:17:00+03:00</published><updated>2009-03-18T01:17:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-03-18:/2009/03/flux-ritmy-vashego-monitora/</id><content type="html">&lt;p&gt;Несколько дней назад познакомился с этой программой. Она выполняет очень простую функцию, в зависимости от времени суток, меняет яркость и контрастность монитора, что бы глаза не уставали.&lt;/p&gt;
&lt;p&gt;Поработав с ней несколько суток, понимаю что это утилита из разряда &lt;strong&gt;musthave&lt;/strong&gt;, благо есть версии для всех систем.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/2009/03/18/flux-shot.png"&gt;&lt;img alt="flux-shot.png" src="/images/3ee2/eb3a/3ee2eb3a369a9daf3dd52c3fde7146f9.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Для настройки необходимо указать ваши координаты (latitude), которые можно узнать на &lt;a href="http://stereopsis.com/flux/map.html"&gt;сайте программы&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Настоятельно рекомендую всем, оссобенно тем кто много торчит перед монитором.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://stereopsis.com/flux/"&gt;F.lux Скачать&lt;/a&gt;.&lt;/p&gt;</content><category term="Полезное"/><category term="flux"/><category term="monitor"/><category term="musthave"/><category term="soft"/></entry><entry><title>Идея беслатного wifi</title><link href="https://blog.rpsl.info/2009/03/ideya-beslatnogo-wifi/" rel="alternate"/><published>2009-03-03T13:46:00+03:00</published><updated>2009-03-03T13:46:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-03-03:/2009/03/ideya-beslatnogo-wifi/</id><summary type="html">&lt;p&gt;В очередной раз, просматривая доступные сети на мобиле, задумался "Почему они все закрыты?". Закрыты они по понятным причинам, что бы всякие умники не качали через вас торренты и не тратили ваш трафик.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/2009/03/03/wifilogo.png"&gt;&lt;img alt="wifilogo.png" src="/images/8b09/388f/8b09388f45762ae4a137793221b4b05c.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Это вопрос скорее к производителям, чем к пользователям.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Вот у меня назрел вопрос, неужели так трудно, на одной точке раздавать две сети.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;В очередной раз, просматривая доступные сети на мобиле, задумался "Почему они все закрыты?". Закрыты они по понятным причинам, что бы всякие умники не качали через вас торренты и не тратили ваш трафик.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/2009/03/03/wifilogo.png"&gt;&lt;img alt="wifilogo.png" src="/images/8b09/388f/8b09388f45762ae4a137793221b4b05c.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Это вопрос скорее к производителям, чем к пользователям.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Вот у меня назрел вопрос, неужели так трудно, на одной точке раздавать две сети.&lt;/p&gt;


&lt;p&gt;Было бы очень удобно, например:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MySweetHome (закрытая)&lt;/li&gt;
&lt;li&gt;MySweetHome_Free (открытая)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Идея открытой сети довольно простая, делать шейп на скорость соединения. Например, не более 50кб/c. Обычная модемная скорость. Фильмы, музыку, видео на такой качать устанешь, но этого вполне достаточно, что бы с мобилы проверить почту, обновить рсс или посибедь в jabber/twitter.&lt;/p&gt;
&lt;p&gt;Почему такое не распространено, не знаю. Но очень хотелось бы. Это заставило бы мобильных провайдеров начать делать "адекватные" цены, на стоимость gprs.&lt;/p&gt;</content><category term="Заметки"/><category term="internet"/><category term="jabber"/><category term="nokia"/><category term="Router"/><category term="twitter"/><category term="wifi"/></entry><entry><title>Лучшее враг хорошего</title><link href="https://blog.rpsl.info/2009/02/luchshee-vrag-xoroshego/" rel="alternate"/><published>2009-02-25T14:36:00+03:00</published><updated>2009-02-25T14:36:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-02-25:/2009/02/luchshee-vrag-xoroshego/</id><summary type="html">&lt;blockquote&gt;
&lt;p&gt;Любое ваше улучшение и действие, должно в конечном счете, решать какую
либо проблему, если эта проблема к концу всех операций останется не
решенной или появятся новые, то смело можно считать, что вы зазря
потратили свое время.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/2009/02/25/Cisco-systems-GSR-small.jpg"&gt;&lt;img alt="Cisco-systems-GSR-small.jpg" src="/images/424d/e15c/424de15c58fb1139b7bcf50636ab020f.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Я хочу поделиться с вами еще одной житейской мудростью, а точнее историей, которую рассказал мне мой друг. Он очень хороший человек, специалист по офисным сетям, сейчас заканчивает ВУЗ и пишет диплом, на какую то "офисно-компьютерную" тему.&lt;/p&gt;
&lt;p&gt;Зарабатывает на жизнь тем, что работает "приходящим" администратором, в нескольких компаниях. Маленький офисные сетки, на 5 - 20 компьютеров. От вирусов там почистить, принтеры настроить, обычная рутина, ничего интересного. Единственный плюс этой работы, что на рабочем месте не нужно находиться постоянно. Когда все работает, то ездить по офисам можно только "За зарплатой", но такое обычно бывает редко и в одну контору он заезжает в среднем раз в неделю.&lt;/p&gt;
</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;Любое ваше улучшение и действие, должно в конечном счете, решать какую
либо проблему, если эта проблема к концу всех операций останется не
решенной или появятся новые, то смело можно считать, что вы зазря
потратили свое время.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://blog.rpsl.info/2009/02/25/Cisco-systems-GSR-small.jpg"&gt;&lt;img alt="Cisco-systems-GSR-small.jpg" src="/images/424d/e15c/424de15c58fb1139b7bcf50636ab020f.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Я хочу поделиться с вами еще одной житейской мудростью, а точнее историей, которую рассказал мне мой друг. Он очень хороший человек, специалист по офисным сетям, сейчас заканчивает ВУЗ и пишет диплом, на какую то "офисно-компьютерную" тему.&lt;/p&gt;
&lt;p&gt;Зарабатывает на жизнь тем, что работает "приходящим" администратором, в нескольких компаниях. Маленький офисные сетки, на 5 - 20 компьютеров. От вирусов там почистить, принтеры настроить, обычная рутина, ничего интересного. Единственный плюс этой работы, что на рабочем месте не нужно находиться постоянно. Когда все работает, то ездить по офисам можно только "За зарплатой", но такое обычно бывает редко и в одну контору он заезжает в среднем раз в неделю.&lt;/p&gt;


&lt;p&gt;Так вот, около полу года назад, "хорошие языки" порекомендовали его в очередную компанию. Пришел он, посмотрел - разруха полная. Компьютеры по возрасту его ровесники, на половине крутится загаженный виндоус 2000, про какие либо Active Directory никто никогда не слышал, про лицензионное обеспечение и говорить не стоит. Подошел к генеральному, который его собственно и пригласил и говорит, что работать тут он будет только в том случае, если они выделят бюджет на замену офисных компьютеров, благо офисные лошадки, в которые интегрировано все, что только можно, собираются за 4-5тысяч. Для офиса и прочей фигни их достаточно, а остальное и не нужно.&lt;/p&gt;
&lt;p&gt;После нескольких недель размышления, генеральный дал добро и они закупили компьютеры. Мой друг пришел в офис в пятницу вечером, просидел там до утра понедельника, сделал абсолютно все. Разграничение прав, фильтрацию трафика, удаленное управление. В общем перевел всю сеть в режим полной автономности. После одного такого "супер-штурма", он появлялся в офисе по прямой обязанности примерно раза два, ездил туда полгода только за зарплатой.&lt;/p&gt;
&lt;p&gt;Пару дней назад ему позвонили и сообщили, что в его услугах больше не нуждаются и платить не будут, т.к. нахер платить если он ничего не делает.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;После этой истории, я конечно пособолезновал ему, мол надо было сразу
много денег за настройку офиса брать, или не заниматься этой херней, а
ездить туда раз в пару недель, чистить компы от вирусов и показывать
им, что без тебя они никуда. Также о том какое начальство глупое, ведь
если админ не ездит в офис, значит он хороший админ. Но проблем, наши
разговоры не решают.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;С моралью в этой истории туго, просто в некоторых процессах, нужна не пытаться упростить всё, а выполнять монотонную работу, за которую тебе всегда будут платить, либо брать отдельно деньги за "оптимизацию" и отдельно за обслуживание.&lt;/p&gt;</content><category term="Заметки"/><category term="Active Directory"/><category term="Linux"/><category term="Microsoft"/><category term="истории"/></entry><entry><title>Найти авто инструктора</title><link href="https://blog.rpsl.info/2009/02/nayti-avto-instruktora/" rel="alternate"/><published>2009-02-13T10:07:00+03:00</published><updated>2009-02-13T10:07:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-02-13:/2009/02/nayti-avto-instruktora/</id><content type="html">&lt;p&gt;Опа опа! Чё я вижу, сегодня очередное произведение от &lt;a href="http://futurecolors.ru"&gt;FC&lt;/a&gt; увидело свет или вышло из закрытого теста в паблик.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://spokoino.ru"&gt;&lt;img alt="Спокойно.Ру - Поиск авто инструктора." src="https://blog.rpsl.info/images/d327/9bef/d3279bef09a3987a3e7fe91a17a9e42f.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;На этот раз, это стартап, социальная сеть для &lt;strong&gt;авто инструкторов&lt;/strong&gt;. Так что, если вы собираетесь в ближайшем времени идти на курсы или вы очень круто водите и хотите зарабатывать деньги давая уроки, то дорожка туда вам просто заказана.&lt;/p&gt;
&lt;p&gt;База правда еще маленькая, но проект выточен под весьма высокую нагрузку, да и толк от него будет, когда там будут сотни инструкторов, но всему своё время.&lt;/p&gt;</content><category term="Полезное"/><category term="internet"/><category term="web2.0"/><category term="автоинструктор"/></entry><entry><title>Google Disk aka GDrive</title><link href="https://blog.rpsl.info/2009/01/google-disk-aka-gdrive/" rel="alternate"/><published>2009-01-30T23:43:00+03:00</published><updated>2009-01-30T23:43:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-01-30:/2009/01/google-disk-aka-gdrive/</id><content type="html">&lt;p&gt;А тем временем. Пока космические корабли бороздят просторы вселенной и
мощщностей моего компьютера хватает что бы управлять всеми Российскими
боевыми спутниками, но их (мощщностей) мало что бы печатать красивый
текст с рюшечками, в умах людей всё больше и больше разгорается интерес
к новому сервису от гугла под кодовым именем "GDrive".&lt;/p&gt;
&lt;p&gt;&lt;span class="mt-enclosure mt-enclosure-image"
style="display: inline;"&gt;&lt;a href="http://blog.rpsl.info/assets_c/2009/01/%D0%A1%D0%BD%D0%B8%D0%BC%D0%BE%D0%BA-GDrive%20-%20%D0%9F%D0%BE%D0%B8%D1%81%D0%BA%20-%20%D0%A5%D0%B0%D0%B1%D1%80%D0%B0%D1%85%D0%B0%D0%B1%D1%80%20-%20Mozilla%20Firefox-40.html"&gt;&lt;img alt="gdrive.png" src="/images/572c/9160/572c916017c9286f7a9b46b3ea407d25.png"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Очень понравился комментарий от некого
"&lt;a href="http://tangro.habrahabr.ru/"&gt;tangro&lt;/a&gt;", который предложил свой вариант
описания сервиса:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;«Компания Google рада представить Вам еще один сервис, вышедший из
Google Labs. Сервис GDrive позволяет загружать, хранить, и скачивать с
серверов Google Ваши файлы. В рамках стандартного пользовательского
соглашения Вы можете хранить несколько (объем постоянно
увеличивается!) гигабайт данных. За определенную плату Вы можете
купить дополнительное место на сервере. Доступна интеграция с Gmail и
Google Documents. Есть API для загрузки и скачивания файлов. Есть
возможность корпоративной подписки. Есть возможность хранения файлов в
„приватном" режиме или открытия доступа к нему для других
пользователей. Компания Google не несет ответственности за содержимое
информации, загруженной на сервер пользователем. Контент, защищенный
чужими авторскими правами может быть удален без согласия
пользователя.»&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Я уже придумал около 3 вариантов его использования, сейчас рассказывать
не буду. Когда откроется, когда будет доступна лицензия, тогда и
расскажу.&lt;/p&gt;</content><category term="Заметки"/><category term="gdrive"/><category term="goodle"/><category term="habrahabr"/><category term="internet"/></entry><entry><title>Не будет у меня Agora Pro</title><link href="https://blog.rpsl.info/2009/01/ne-budet-u-menya-agora-pro/" rel="alternate"/><published>2009-01-20T09:45:00+03:00</published><updated>2009-01-20T09:45:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-01-20:/2009/01/ne-budet-u-menya-agora-pro/</id><content type="html">&lt;p&gt;Только что пришло &lt;a href="http://www.kogan.com.au/blog/2009/jan/16/kogan-agora-be-delayed/"&gt;уведомление на
почту&lt;/a&gt;.
Не знаю действительно ли они так озадачены совместимостью и удобством
пользователя, или просто проект провалился и они не собрали нужное
кол-во пред. заказов. Не суть. Все деньги будут возвращенны, всем
предлагают полюбовно разойтись.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;br&gt;
The Agora did reach a very late stage of development. Manufacturing
had commenced and it was a matter of days from being shipped to you.
However, it now seems certain the Agora in it's current form will
limit its compatibility and interoperability in the near future.&lt;/p&gt;
&lt;p&gt;One of the potential issues is the screen size and resolution. It
seems developers will be creating applications that are a higher
resolution than the Agora is currently capable of handling.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Только вот что же делать мне.?? Мне нужен нормальный телефон вместо
&lt;em&gt;&lt;span style="font-size: xx-small;"&gt;(fucked, fucked, fucked)&lt;/span&gt;&lt;/em&gt;
e71, а такого на просторах яндекс.маркета найти не удалось.&lt;/p&gt;
&lt;p&gt;Отстой&lt;/p&gt;</content><category term="Заметки"/><category term="agora"/><category term="kogan"/><category term="телефон"/></entry><entry><title>Разобрал автомат, собрал...</title><link href="https://blog.rpsl.info/2009/01/razobral-avtomat-sobral/" rel="alternate"/><published>2009-01-17T03:21:00+03:00</published><updated>2009-01-17T03:21:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-01-17:/2009/01/razobral-avtomat-sobral/</id><content type="html">&lt;p&gt;... получилась соковыжималка с ручным приводом.&lt;/p&gt;
&lt;p&gt;Еще несколько дней убил на то, что бы &lt;a href="http://blog.rpsl.info"&gt;привести МТ&lt;/a&gt; к человеческому виду. Вроде немного получается, в целом всё хорошо, натянул простенький, подрезанный откуда то, дизайн. Прикрутил пару плагинов, работает. По поводу кросспостинга в жж, курил исходники весьма долго. Реальное ощущение что плагины писал Равшан в паре с Джамшутом. В sixapart.com походу не сильно в курсе про визуальное форматирование кода.&lt;/p&gt;
&lt;p&gt;Сейчас активно занялся за написание плагинов для &lt;a href="http://plugins.movabletype.org/action-streams/"&gt;ActionStreams&lt;/a&gt;. Как только приведу их божеский вид, выкину в "паблик".&lt;/p&gt;
&lt;p&gt;Пытался запустить несколько плагинов из &lt;a href="http://code.sixapart.com/svn/mtplugins/trunk/"&gt;svn&lt;/a&gt;, но там все слишком сырое и работать отказывается. Печально.&lt;/p&gt;
&lt;p&gt;Выпил за 4 дня литровую бытылку виски и 3 литра колы. Спать ложусь когда еще темно, просыпаюсь когда уже темно.&lt;/p&gt;
&lt;p&gt;При всем при этом делаю несколько проектов по работе и пытаюсь доделать фотогаллерею для www.ugw.ru&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Кстати, ужастно интересно читать(?), скорее смотреть чужие фотоблоги. Подписался на несколько штук, смотрю на жизнь других людей, весьма интересно. Ссылки выкладывать не буду, кому надо сами найдут, очень много на vox.com.&lt;/p&gt;</content><category term="Заметки"/><category term="action streams"/><category term="CMS"/><category term="svn"/><category term="ugw"/><category term="vox"/><category term="xmlrpc"/><category term="виски"/></entry><entry><title>Цветовая идентификация</title><link href="https://blog.rpsl.info/2009/01/cvetovaya-identifikaciya/" rel="alternate"/><published>2009-01-13T00:43:00+03:00</published><updated>2009-01-13T00:43:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-01-13:/2009/01/cvetovaya-identifikaciya/</id><content type="html">&lt;p&gt;Довольно приятная идея возникла у &lt;a href="http://subz.habrahabr.ru/" title="subz"&gt;subz&lt;/a&gt; в &lt;a href="http://habrahabr.ru/blog/humour/43358.html"&gt;топике на хабрабабре&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;function get_username_html_color($username )
{
    return '#' . substr( md5($username ), 0, 6 );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Пользователь "&lt;a href="http://dreadatour.habrahabr.ru/"&gt;Dreadatour&lt;/a&gt;" сразу накидал &lt;a href="http://dreadatour.ru/username/"&gt;скрипт&lt;/a&gt; который в реал тайме отобржает ваш цвет&lt;/p&gt;
&lt;p&gt;Идея класс, обязательно куда нибудь прикручу.&lt;/p&gt;</content><category term="Полезное"/><category term="blog"/><category term="habrahabr"/><category term="php"/></entry><entry><title>Movable Type: Поигрались и хватит</title><link href="https://blog.rpsl.info/2009/01/movable-type-poigralis-i-xvatit/" rel="alternate"/><published>2009-01-13T00:43:00+03:00</published><updated>2009-01-13T00:43:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-01-13:/2009/01/movable-type-poigralis-i-xvatit/</id><summary type="html">&lt;p&gt;Четыре месяца назад, я наткнулся на это двигло и мне стало интересно, а как же оно работает? Захотелось пощупать, потрогать изнутри, пропатчить чего нибудь. Тут и господин &lt;a href="http://saahov.ru/"&gt;saahov&lt;/a&gt; нашелся очень кстати. Поставил, вот уже сколько играюсь и всё больше и больше склоняюсь к мысли, что ну его в пень.&lt;/p&gt;
&lt;p&gt;Блог, должен быть тем инструментом, который один раз настроил, поставил, дизайн нарисовал и больше проблем возникать не должно. А тут, как ни попытка копнуть глубже, так гемморой.&lt;/p&gt;
&lt;p&gt;Ладно, молчу про то, что он (MT) такой весь из себя для гиков. Просто меня он не устраивает.&lt;/p&gt;
&lt;p&gt;Не устраивает то, что на подсос всех библиотек и обработку обычного логина ему нужно почти 100мб оперативки и только на машине с более чем 500мГц на борту он перестает занимать cpu на 100%.&lt;/p&gt;
&lt;p&gt;Не утраивает довольно тупая система стилей. С шаблонами все просто великолепно, только вот со стилями проблемы и ладно то, что через css можно извратиться как хочешь и поменять местами, но ведь остальная его часть замурована. Может мне просто не хватило терпения и внимательности, но попробуйте что угодно ввести слева в строку поиска. Удивитесь. =)&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Четыре месяца назад, я наткнулся на это двигло и мне стало интересно, а как же оно работает? Захотелось пощупать, потрогать изнутри, пропатчить чего нибудь. Тут и господин &lt;a href="http://saahov.ru/"&gt;saahov&lt;/a&gt; нашелся очень кстати. Поставил, вот уже сколько играюсь и всё больше и больше склоняюсь к мысли, что ну его в пень.&lt;/p&gt;
&lt;p&gt;Блог, должен быть тем инструментом, который один раз настроил, поставил, дизайн нарисовал и больше проблем возникать не должно. А тут, как ни попытка копнуть глубже, так гемморой.&lt;/p&gt;
&lt;p&gt;Ладно, молчу про то, что он (MT) такой весь из себя для гиков. Просто меня он не устраивает.&lt;/p&gt;
&lt;p&gt;Не устраивает то, что на подсос всех библиотек и обработку обычного логина ему нужно почти 100мб оперативки и только на машине с более чем 500мГц на борту он перестает занимать cpu на 100%.&lt;/p&gt;
&lt;p&gt;Не утраивает довольно тупая система стилей. С шаблонами все просто великолепно, только вот со стилями проблемы и ладно то, что через css можно извратиться как хочешь и поменять местами, но ведь остальная его часть замурована. Может мне просто не хватило терпения и внимательности, но попробуйте что угодно ввести слева в строку поиска. Удивитесь. =)&lt;/p&gt;


&lt;p&gt;Мне не нравится весьма скудное комъюнити. Я не хочу сейчас углубляться в недры изучения это двигла и становиться одним из "Гуру MT", я хочу нормально работать и что бы это всё работало.&lt;/p&gt;
&lt;p&gt;Короче сопли-соплями, но я устал и в ближайшее время забуду эту систему, как только стану по свободнее - так сразу займусь тем, что бы уйти с неё.&lt;/p&gt;
&lt;p&gt;-Куда? -А разве так много вариантов?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Кто употреблял, то знает - перец умеет ждать.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Такие дела и с современным рынком блог платформ. Обратно на WP. Есть конечно ещё огромная куча платформ, но они либо из категории "хер проссышь как работает", либо "хер пойми как 'это' вообще работает".&lt;/p&gt;
&lt;p&gt;Короче адиос.&lt;/p&gt;</content><category term="Заметки"/><category term="CMS"/><category term="perl"/><category term="php"/><category term="wordpress"/></entry><entry><title>Нелепо вышло...</title><link href="https://blog.rpsl.info/2009/01/nelepo-vyshlo/" rel="alternate"/><published>2009-01-06T04:53:00+03:00</published><updated>2009-01-06T04:53:00+03:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2009-01-06:/2009/01/nelepo-vyshlo/</id><content type="html">&lt;p&gt;Пока подготавливал площадку для "Movable Type", вышел не приятный казус. Копаюсь в ./cgi-bin/ и делаю:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;*mkdir ./mt  
cp -r ./\* ./mt*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Наблюдаю как сервак уходит в глубокую рекурсию, и тут меня дисконектит из ssh, из ftp и на пинги отвечать он перестает.&lt;/p&gt;
&lt;p&gt;Начинаю ломить в админку у хостера, там тоже бодяга, ничего не работает. Пишу в саппорт:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;От: Виктор Викторович&lt;br&gt;
Дата: 2009-01-06 01:00:56&lt;/p&gt;
&lt;p&gt;Доброй ночи, ссылка "Перейти в VDSmanager" из https://my.ispsystem.com
не работает.&lt;br&gt;
Мой VDS повис, подскажите как ребутнуть или ребутните сами.&lt;br&gt;
Спасибо.&lt;/p&gt;
&lt;p&gt;От: Leonid Popov&lt;br&gt;
Дата: 2009-01-06 01:03:52&lt;/p&gt;
&lt;p&gt;Проблемы не с вашим VDS. На головном сервере произошёл сбой. Сейчас он
перезагружается. В течении 10 минут будет работать.&lt;br&gt;
Приносим извинения.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;И кто мне там втирал что чудес и совпадений не бывает? А?&lt;/p&gt;</content><category term="01"/></entry><entry><title>Почта на 5 минут или temp mail box</title><link href="https://blog.rpsl.info/2008/06/pochta-na-5-minut-ili-temp-mail-box/" rel="alternate"/><published>2008-06-27T22:59:00+04:00</published><updated>2008-06-27T22:59:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2008-06-27:/2008/06/pochta-na-5-minut-ili-temp-mail-box/</id><summary type="html">&lt;p&gt;Думаю знакомая ситуация, когда необходимо где то зарегистрироваться, но светить свою почту желания нету. Например что бы просто посмотреть на функционал какого нибудь сервиса, или что бы получить ссылку с форума, администрация которых любит их прятать от гостей.  &lt;/p&gt;
&lt;p&gt;Для таких случаев существует несколько почтовых сервисов, которые предоставляют "временный" почтовый ящик.  &lt;/p&gt;
&lt;p&gt;Суть заключается в том, что вы просто вводите имя ящика или сервис генерирует его вам и получаете в распоряжение mailbox в который можно получить письмо, а потом о нём забыть.  &lt;/p&gt;
&lt;p&gt;Подобные сервисы делятся на два типа, те которые просто предоставляют ящик и те которые предоставляют форвардинг на ваш email. К второму типу я отношусь скептически ибо зачем оставлять свой ящик, не известно кому, если цель всех этих действий его скрыть. Но всё таки ссылки на них приведу ведь не стоит забывать, что если вы сделали себе ящик с именем 'asd', то его кроме вас посетят ещё много-много людей.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Думаю знакомая ситуация, когда необходимо где то зарегистрироваться, но светить свою почту желания нету. Например что бы просто посмотреть на функционал какого нибудь сервиса, или что бы получить ссылку с форума, администрация которых любит их прятать от гостей.  &lt;/p&gt;
&lt;p&gt;Для таких случаев существует несколько почтовых сервисов, которые предоставляют "временный" почтовый ящик.  &lt;/p&gt;
&lt;p&gt;Суть заключается в том, что вы просто вводите имя ящика или сервис генерирует его вам и получаете в распоряжение mailbox в который можно получить письмо, а потом о нём забыть.  &lt;/p&gt;
&lt;p&gt;Подобные сервисы делятся на два типа, те которые просто предоставляют ящик и те которые предоставляют форвардинг на ваш email. К второму типу я отношусь скептически ибо зачем оставлять свой ящик, не известно кому, если цель всех этих действий его скрыть. Но всё таки ссылки на них приведу ведь не стоит забывать, что если вы сделали себе ящик с именем 'asd', то его кроме вас посетят ещё много-много людей.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Сервисы первого типа:&lt;/strong&gt;&lt;br&gt;
- http://www.temporaryinbox.com/ Имеется русский интерфейс, сам генерирует названия ящика + имеются расширения для Firefox, Opera, Internet Explorer&lt;br&gt;
- http://10minutemail.com/ Есть русский интерфейс, сам генерирует имена, ящик уничтожается через 10 минут
- http://www.pookmail.com/ Есть русский интерфейс, имена придумывать сам не умеет. Ящик живет сутки
- http://www.mailinator.com/ Русского языка я не нашел, имена генерирует сам
- http://www.mytrashmail.com/ Русского языка нету, имена сам не генерирует, но зато умеет запоминать ваш логин
- http://www.dodgeit.com/ Русского языка нету, имена придумывать не умеет, весьма скромный дизайн&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Сервисы второго типа:&lt;/strong&gt;&lt;br&gt;
- http://www.mailexpire.com/ Русского языка нету, можно выбрать время жизни ящика, от 12 часов до 3 месяцев
- http://spambox.us/ Русского языка нету, можно выбрать время жизни ящика, от 6 часов до 1 года
- http://www.jetable.org/en/index Русского языка нету, можно выбрать время жизни ящика, от 1 часа до 1 месяца&lt;/p&gt;</content><category term="Полезное"/></entry><entry><title>date.centrgroup.ru</title><link href="https://blog.rpsl.info/2008/05/datecentrgroupru/" rel="alternate"/><published>2008-05-29T14:14:00+04:00</published><updated>2008-05-29T14:14:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2008-05-29:/2008/05/datecentrgroupru/</id><content type="html">&lt;p&gt;Последние несколько дней полностью посвятил "&lt;a href="http://date.centrgroup.ru"&gt;ЦАО Календарю&lt;/a&gt;".  &lt;/p&gt;
&lt;p&gt;Знаете, как обычно это бывает, по крайней мере у меня. Пришла в голову идея, начал думать, через 20 минут сел за комп и проебался куда то на "n" часов. В итоге получилось почти то, что хотел увидеть изначально.&lt;/p&gt;
&lt;p&gt;Почему почти? Да потому что, по мере реализации в голову приходят, какие то ещё, более оригинальные решения и конечный продукт может сильно отличаться от того что было задумано.  &lt;/p&gt;
&lt;p&gt;Вот также и с календарём. Когда то давно я его сделал можно сказать на коленке, он работал и славно. Потом, из-за какой то непонятной хуйни появились лаги в виде неправильного отображения дней недели и т.п. +реализация его мне совсем перестала нравиться. В итоге за примерно 2 дня я написал полностью новый вариант, и ещё за 2 дня подправил мелкие баги.  &lt;/p&gt;
&lt;p&gt;Из новых функций стоит отметить активное использование &lt;a href="http://jquery.com/" title="jQuery is a new type of JavaScript library"&gt;Jquery&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Собственно после знакомства с ним, начал на него молиться. Кто сразу не заметил, теперь месяца можно листать по "Ctrl + Right" и "Ctrl + Left".  &lt;/p&gt;
&lt;p&gt;Осталось две незаконченные вещи:  &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Rss - вот думаю а нужен ли он вообще там? С одной стороны удобно, с
другой как то так.... Не решил ещё.  &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Версия для печати - тоже не могу решить, стоит ли она того. Тоесть как её реализовывать? Фунцию мгновенной отправки на принтер использовать не буду сто процентов, только если открывать в новом окне, на белом фоне, с красивым размещением информации на странице. Но нормальных пресс-релизов там тоже очень мало. Организаторы не могут потрудиться и прислать инфу. Ослы. Так что стоит ли её делать тоже не решил.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</content><category term="Полезное"/></entry><entry><title>Вскрытие запароленых архивов в линуксе</title><link href="https://blog.rpsl.info/2008/05/linux-how-to-crack-rar-password/" rel="alternate"/><published>2008-05-04T02:10:00+04:00</published><updated>2008-05-04T02:10:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2008-05-04:/2008/05/linux-how-to-crack-rar-password/</id><content type="html">&lt;p&gt;Бывают же такие ситуации, когда поставил пароль на архив, положил его в &lt;code&gt;/home/kladovka&lt;/code&gt; и забыл. 
Вспомнил о нём через пару лет, хочешь посмотреть что же туда прятал, а пароль вспомнить не можешь. Эх досада.  &lt;/p&gt;
&lt;p&gt;Для начала, стоит установить следующие пакеты:&lt;/p&gt;
&lt;pre&gt;&lt;code class="bash"&gt;sudo apt-get install libxml2-dev build-essential
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Теперь качаем последнею версию программы &lt;a href="http://rarcrack.sourceforge.net/" title="rar crack, взлом запароленных архивов в линуксе"&gt;rarcrack&lt;/a&gt; (на момент написания версия 0.2). 
После скачивания необходимо распаковать и собрать программу:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tar -xjf rarcrack-*.tar.bz2
cd rarcrack-*
make
sudo make install
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Готово. Использование:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rarcrack cripted_file.rar [--threads thread_num] [--type rar|zip|7z]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;После запуска, программа создаст в каталоке с архивом, .xml файл, в который будет записан текущий результат, в случае успешного подбора хороший результат и символы для подбора&lt;/p&gt;</content><category term="Полезное"/></entry><entry><title>KDE App's in Gnome</title><link href="https://blog.rpsl.info/2008/04/kde-apps-in-gnome/" rel="alternate"/><published>2008-04-27T23:39:00+04:00</published><updated>2008-04-27T23:39:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2008-04-27:/2008/04/kde-apps-in-gnome/</id><content type="html">&lt;p&gt;Возможно вы так же как и я используете некоторые приложения KDE в среде Gnome. У меня это только &lt;a href="http://amarok.kde.org/"&gt;Аmarok&lt;/a&gt; "Amarok, KDE music player", всему остальному есть достойные замены. Так вот, не знаю как с остальными, но &lt;a href="http://amarok.kde.org/"&gt;Аmarok&lt;/a&gt; отказывается воспринимать multimedia клавиши клавиатуры. &lt;/p&gt;
&lt;p&gt;Какое-то время я не обращал на это внимание: ибо обычно напихаю чего хочу в плейлист и доволен, но тут в мои руки попало 9Гб минусов (спасибо &lt;a href="http://torrents.ru"&gt;торрентс.ру&lt;/a&gt; и релизеру) и прослушивание их стало просто отвратительным. Слушать все от начало до конца это ужасно нудно, а каждый раз открывать &lt;a href="http://amarok.kde.org/"&gt;Аmarok&lt;/a&gt; и листать дальше ничем не лучше. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://google.ru"&gt;Google&lt;/a&gt; и тут в очередной раз мне помог. Качаем замечательный скрипт написанный на питоне и выполняем. Вуаля, все хоткеи работают, осталось только скопировать его в /usr/bin/ и добавить в rc.d для автозагрузки.  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.kde-apps.org/content/show.php?content=60910&amp;amp;vote=bad&amp;amp;tan=22122447"&gt;Gnome Multimedia Keys&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;&lt;a href="http://amarok.kde.org/"&gt;Amarok&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Полезное"/></entry><entry><title>Динамический favicon.ico</title><link href="https://blog.rpsl.info/2008/04/dinamicheskiy-faviconico/" rel="alternate"/><published>2008-04-26T00:24:00+04:00</published><updated>2008-04-26T00:24:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2008-04-26:/2008/04/dinamicheskiy-faviconico/</id><content type="html">&lt;p&gt;Яркий пример динамического обновления favicon это сайт "Вконтакте",
когда включаешь музыкальный плеер, иконка меняется и на ней
отображается, что в данный момент играет музыка.&lt;/p&gt;
&lt;p&gt;Основная задача этой библиотеки — это обновлять favicon через
Javascript, но есть и более серьёзная задача — дать возможность
разработчику возможность сообщать пользователю о каком-то событии в
другой вкладке браузера. Например, если в другой вкладке начала играть
музыка, вы можете сменить иконку этого таба, показывая, что началось
воспроизведение музыки (или другое событие). Или, например, если вам
надо действительно привлечь внимание пользователя, вы можете начать
анимацию иконки.&lt;/p&gt;
&lt;p&gt;Собственно примеры использования:&lt;/p&gt;
&lt;pre&gt;&lt;code class="javascript"&gt;favicon.change(&amp;quot;/icon/active.ico&amp;quot;, &amp;quot;new title&amp;quot;); // Отменить или начать анимацию иконки + смена тайтла

favicon.change(&amp;quot;/icon/active.ico&amp;quot;); // Оставить тайтл, менять только иконку

favicon.change(null, &amp;quot;new title&amp;quot;); // Оставить иконку, менять только тайтл

favicon.animate([&amp;quot;icon1.ico&amp;quot;, &amp;quot;icon2.ico&amp;quot;, …]);

favicon.animate([&amp;quot;icon1.ico&amp;quot;, &amp;quot;icon2.ico&amp;quot;, …], {delay: 500} );

favicon.scrollTitle(&amp;quot;new title&amp;quot;);

favicon.scrollTitle(&amp;quot;new title&amp;quot;, { delay: 200, gap: &amp;quot;——&amp;quot;} )

favicon.unscroll();

favicon.unanimate();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://www.ajaxify.com/run/favicon/scroll/"&gt;Scrolling Favicon Demo&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.ajaxify.com/run/favicon/scroll/favicon.js"&gt;Scrolling Favicon Library&lt;/a&gt;&lt;/p&gt;</content><category term="Полезное"/></entry><entry><title>speedtest</title><link href="https://blog.rpsl.info/2008/04/speedtest/" rel="alternate"/><published>2008-04-25T14:18:00+04:00</published><updated>2008-04-25T14:18:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2008-04-25:/2008/04/speedtest/</id><summary type="html">&lt;p&gt;Многие уже откровенно запарили своей слепой уверенностью в действенности speedtest.net, я говорю это потому, что данный ресурс является скорее развлекательным, нежели полезным. Проверим, так ли полезен speedtest? Для этого на потребуется простой набор команд, в первую очередь проверим время соединения с сервером где оно и раcположено:&lt;/p&gt;
&lt;pre&gt;&lt;code class="perl"&gt;# time GET -dax speedtest.net
LWP::UserAgent::new: ()
LWP::UserAgent::request: ()
LWP::UserAgent::send_request: GET http://speedtest.net
LWP::UserAgent::_need_proxy: Not proxied
LWP::Protocol::http::request: ()
LWP::Protocol::collect: read 524 bytes
LWP::Protocol::collect: read 1872 bytes
LWP::Protocol::collect: read 4096 bytes
LWP::Protocol::collect: read 248 bytes
LWP::Protocol::collect: read 4096 bytes
LWP::Protocol::collect: read 248 bytes
LWP::Protocol::collect: read 466 bytes
LWP::UserAgent::request: Simple response: OK
real    0m2.948s
user   0m0.185s
sys     0m0.051s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Почти три секунды у нас занимает соединение, другими словами мы тратим три секунды впусту и имеем 3 секунды отклика от сервера, где считается якобы скорость in/out, на самом то деле считается время ответа на запрос и отклик по-http.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Многие уже откровенно запарили своей слепой уверенностью в действенности speedtest.net, я говорю это потому, что данный ресурс является скорее развлекательным, нежели полезным. Проверим, так ли полезен speedtest? Для этого на потребуется простой набор команд, в первую очередь проверим время соединения с сервером где оно и раcположено:&lt;/p&gt;
&lt;pre&gt;&lt;code class="perl"&gt;# time GET -dax speedtest.net
LWP::UserAgent::new: ()
LWP::UserAgent::request: ()
LWP::UserAgent::send_request: GET http://speedtest.net
LWP::UserAgent::_need_proxy: Not proxied
LWP::Protocol::http::request: ()
LWP::Protocol::collect: read 524 bytes
LWP::Protocol::collect: read 1872 bytes
LWP::Protocol::collect: read 4096 bytes
LWP::Protocol::collect: read 248 bytes
LWP::Protocol::collect: read 4096 bytes
LWP::Protocol::collect: read 248 bytes
LWP::Protocol::collect: read 466 bytes
LWP::UserAgent::request: Simple response: OK
real    0m2.948s
user   0m0.185s
sys     0m0.051s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Почти три секунды у нас занимает соединение, другими словами мы тратим три секунды впусту и имеем 3 секунды отклика от сервера, где считается якобы скорость in/out, на самом то деле считается время ответа на запрос и отклик по-http.&lt;/p&gt;


&lt;p&gt;Посмотрим, что стоит там в качестве сервера:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# HEAD speedtest.net
200 OK
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: private, post-check=0, pre-check=0
Connection: close
Date: Mon, 21 Jan 2008 18:44:50 GMT
Pragma: no-cache
Server: Apache/2.2.3 (Debian) PHP/5.2.4-0.dotdeb.1 with Suhosin-Patch mod_ssl/2.2.3 OpenSSL/0.9.8c
Vary: Accept-Encoding
Content-Type: text/html
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Last-Modified: Mon, 21 Jan 2008 18:44:50 GMT
Client-Date: Mon, 21 Jan 2008 19:48:48 GMT
Client-Peer: 69.17.117.207:80
Client-Response-Num: 1
X-Powered-By: PHP/5.2.4-0.dotdeb.1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;даже без балансировки и кеширования....
Смотрим дальше, проверим маршрут и пустим по нему пакет для
опеределения проблем в сети&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# hping -S -T -d 1024 -H tcp -i 1 -d 1024 -m 1500 speedtest.net  -V -r -y
using rl0, addr: 192.168.0.189, MTU: 1500
HPING speedtest.net (rl0 69.17.117.207): S set, 40 headers + 1024 data bytes
hop=1 TTL 0 during transit from ip=192.168.0.1 name=UNKNOWN
hop=1 hoprtt=1.5 ms
hop=2 TTL 0 during transit from ip=79.120.123.1 name=nutshell.dubki.ru
hop=2 hoprtt=1.9 ms
hop=3 TTL 0 during transit from ip=79.120.122.41 name=merry-go-round.dubki.ru
hop=3 hoprtt=2.0 ms
hop=4 TTL 0 during transit from ip=79.120.122.51 name=nat1.dubki.ru
hop=4 hoprtt=2.1 ms
hop=5 TTL 0 during transit from ip=79.120.122.57 name=merry-go-round.dubki.ru
hop=5 hoprtt=2.0 ms
hop=6 TTL 0 during transit from ip=80.86.247.1 name=ppp-1-247.utech.ru
hop=6 hoprtt=6.0 ms
hop=7 TTL 0 during transit from ip=212.1.251.225 name=msk-r1-b7-vl-530.ti.ru
hop=7 hoprtt=50.5 ms
hop=8 TTL 0 during transit from ip=195.219.131.9 name=if-4-0-4.core1.STK-Stockholm.teleglobe.net
hop=8 hoprtt=35.2 ms
hop=9 TTL 0 during transit from ip=80.231.65.9 name=if-5-0-0.core2.FR1-Frankfurt.teleglobe.net
hop=9 hoprtt=66.9 ms
hop=10 TTL 0 during transit from ip=80.231.65.66 name=if-11-0-0.core1.PV1-Paris.teleglobe.net
hop=10 hoprtt=75.0 ms
hop=11 TTL 0 during transit from ip=195.219.215.254 name=UNKNOWN
hop=11 hoprtt=74.9 ms
hop=12 TTL 0 during transit from ip=216.6.87.25 name=if-9-0.mcore4.NQT-NewYork.teleglobe.net
hop=12 hoprtt=148.0 ms
hop=13 TTL 0 during transit from ip=216.6.86.13 name=if-4-0.mcore4.PDI-PaloAlto.teleglobe.net
hop=13 hoprtt=226.9 ms
hop=14 TTL 0 during transit from ip=216.6.86.22 name=if-10-0-0.mcore3.PDI-PaloAlto.teleglobe.net
hop=14 hoprtt=226.5 ms
hop=15 TTL 0 during transit from ip=66.110.64.5 name=if-6-0.core2.SEP-Seattle.teleglobe.net
hop=15 hoprtt=243.4 ms
hop=16 TTL 0 during transit from ip=66.110.64.10 name=ix-5-2.core2.SEP-Seattle.teleglobe.net
hop=16 hoprtt=245.0 ms
hop=17 TTL 0 during transit from ip=69.17.82.54 name=152.ge-1-3-0.sr2.sea5.speakeasy.net
hop=17 hoprtt=244.0 ms
^C
--- speedtest.net hping statistic ---
22 packets tramitted, 17 packets received, 23% packet loss
round-trip min/avg/max = 1.5/97.2/245.0 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Из вывода этой команды видно, что до той сети пакеты ходят с огромным трудом, ни о каком тесте не может быть и речи, кроме этого скорость в пределах автономной системы можно узнать только на порту маршрутизатора, куда подключен Ваш кабель или на коллекторе, на котором считается трафик.&lt;/p&gt;
&lt;p&gt;P.s. а теперь проверим скорость соединения через настоящий (!) гигабит, какая прелесть....&lt;/p&gt;
&lt;p&gt;&lt;img alt="speedtest on 1gb link" src="https://blog.rpsl.info/images/910c/cd89/910ccd89a39042a8b1df0b031f125b18.png"&gt;&lt;/p&gt;
&lt;p&gt;Одним словом стоит позвонить в саппорт и спросить реально положение дел. Однако контролировать провайдера можно и нужно, для этого есть такие вещи, как http://tools-on.net/net.shtml?3 и traceroute.org и прочее, которые выполнят обратную трассировку и покажут примерное время прохождение пакетов, а для наиболее выдающихся личностей я могу вскоре поставить коллектор-маячок, дабы сверять по нему межсегментную скорость.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://local.dubki.ru/index.php?plug=Blogs&amp;amp;action=comments&amp;amp;post_id=317"&gt;(c) Оригинал by Zingel&lt;/a&gt;&lt;/p&gt;</content><category term="Полезное"/></entry><entry><title>Легальная накрутка на torrents.ru</title><link href="https://blog.rpsl.info/2008/04/legalnaya-nakrutka-na-torrentsru/" rel="alternate"/><published>2008-04-25T00:22:00+04:00</published><updated>2008-04-25T00:22:00+04:00</updated><author><name>Rpsl</name></author><id>tag:blog.rpsl.info,2008-04-25:/2008/04/legalnaya-nakrutka-na-torrentsru/</id><summary type="html">&lt;p&gt;Не так давно на форуме &lt;a href="http://forum.asechka.ru"&gt;асечки&lt;/a&gt;, поднимали тему как накрутить себе рейтинг? То есть скачивать много, отдавать мало, но при этом держать "ratio" на высоте. Из всех вариантов перечисленных там, я не увидел ни одного достойного. Жульничать много ума не надо, а вот суметь сделать так, что бы всегда помногу раздавать скачанные файлы это уже по нашему.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Не так давно на форуме &lt;a href="http://forum.asechka.ru"&gt;асечки&lt;/a&gt;, поднимали тему как накрутить себе рейтинг? То есть скачивать много, отдавать мало, но при этом держать "ratio" на высоте. Из всех вариантов перечисленных там, я не увидел ни одного достойного. Жульничать много ума не надо, а вот суметь сделать так, что бы всегда помногу раздавать скачанные файлы это уже по нашему.&lt;/p&gt;


&lt;p&gt;И так, что бы делать террабайты отданного трафика, нам нужно:&lt;br&gt;
1) Иметь хороший канал&lt;br&gt;
2) Не заботиться о трафике&lt;br&gt;
3) Одним из первых получать новые релизы.  &lt;/p&gt;
&lt;p&gt;Если с первыми двумя пунктами у меня проблем небыло, то вот с третьим довольно туго. Сидеть и и мониторить форум - не реально. Писать программу бота тоже не очень круто. Последний вариант Rss. Так как стандартного на форуме нету, то умные люди прежде чем спрашивать всяхую хуйню на форумах и icq сначала лезут в гугл. &lt;/p&gt;
&lt;p&gt;Гугл скормил мне результаты запроса и вывел на великолепный сайт &lt;a href="http://xpoft.ru/torrents.ru/rss_settings.html"&gt;xpoft.ru&lt;/a&gt;  &lt;/p&gt;
&lt;p&gt;Этот сайт позволяет нам получать по Rss темы выбранных нами разделов. Ясно красно что я решил выбрать "Фильмы" и основывать свои опыты на нём.&lt;br&gt;
Следующей загвоздкой стала проблема генерации ленты. Так, как Rss выводится в стандартом виде, как и страница форума, то поле
&lt;code&gt;&amp;lt;link&amp;gt;&amp;lt;/link&amp;gt;&lt;/code&gt; ведёт нас не на файл торрента, а на саму тему релиза.  &lt;/p&gt;
&lt;p&gt;То что написано в теме, мне не интересно. Всё что я хочу, получать ссылки на торрент файлы одним из первых. Значит пишем парсер. Парсер я взял из старой заготовки и лишь поменял пару строк. &lt;/p&gt;
&lt;pre&gt;&lt;code class="php"&gt;&amp;lt;?php
set_time_limit(180);
$host = &amp;quot;xpoft.ru&amp;quot;;
$path = &amp;quot;/torrents.ru/rss.xml?7&amp;quot;;
function get_content($host, $path)
{
    $line = &amp;quot;&amp;quot;;
    $fo = fsockopen($host, 80, $errno, $errstr, 30);
    if (!$fo)
    {
        echo &amp;quot;no connect&amp;quot;;
    }
    else
    {
        $headers = &amp;quot;GET &amp;quot; . $path . &amp;quot; HTTP/1.1rn&amp;quot;;
        $headers .= &amp;quot;Host: &amp;quot; . $host . &amp;quot;rn&amp;quot;;
        $headers .= &amp;quot;Connection: Closernrn&amp;quot;;
        fwrite($fo, $headers);
        while (!feof($fo))
        {
            $line .= fgets($fo, 1024);
        }
        fclose($fo);
    }
    return $line;
}
$content = get_content($host, $path);
$content = explode('', $content);
$content = $content['1'];
preg_match_all(&amp;quot;(download.php?id=[0-9]{1,9})&amp;quot;, $content, $links);
echo '


Rpsl torrent l33ch3r
http://www.xpoft.ru/torrents.ru/rss_settings.html

' . date(r) . '
ru-ru
30
';
for ($i = 0;$i &amp;lt; 20;$i++)
{
    echo '';
    echo '' . rand(1, 400) . ' ' . date(r) . '';
    echo 'http://torrents.ru/forum/' . $links['0'][$i] . '';
    echo '' . rand(1, 400) . ' ' . date(r) . '';
    echo '';
}
echo '';
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ну всё. Далее дело техники. Я в виде клиента использую &lt;a href="http://deluge-torrent.org/"&gt;Deluge&lt;/a&gt;, включив в нём плагин FlexRSS и поставив в шаблон файлов для загрузки "\^" моя "ratio machine" включилась. Осталось только в настройках, все пункты поставить в положение "-1", для максимально доступной скорости загрузки и отдачи.  &lt;/p&gt;
&lt;p&gt;Хочу заметить, что для данного способа желателен довольно глубокий хард, так как кол-во файлов очень быстро его забивает. Так же отключите DHT в вашем торрент клиенте, что бы не раздавать мимо трекера. Я таким образом за чуть меньше недели сидирования сделал +300гб.  &lt;/p&gt;
&lt;p&gt;Удачи.&lt;/p&gt;</content><category term="Полезное"/></entry></feed>