Новый сервис: Telegram бот – напоминалка

Представляю новый сервис – напоминалку. Это бот для telegram, который поможет вам не забывать о важных делах и событиях. Распределите дела/встречи/события по нужным дням, настройте напоминания, в заданный день они появятся в вашем мессенджере.

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

Если будут какие-то пожелания по доработке сервиса, не стесняйтесь, оставляйте ваши комментарии. Если что-то будет действительно стоящее – сделаю. Сервис абсолютно бесплатный, никакой рекламы и нем не будет.

Логи Apache и текст в UTF-8

Заметил одну интересную вещь с логами приложений на php. Если приложение использует вывод отладочной информации в error_log, то в логах php-fpm все сообщения в UTF-8 нормально отображаются. В логах Apache же вместо слова “Ошибка:” будет написано что-то вроде “\xd0\x9e\xd1\x88\xd0\xb8\xd0\xb1\xd0\xba\xd0\xb0:”, что читать совершенно неудобно.

Это совершенно нормальное поведение для apache версии 2.0.49+, там весь вывод в логи экранируют от подозрительных символов. Эту фишку можно отключить, если пересобрать apache с опцией CFLAGS=”-DAP_UNSAFE_ERROR_LOG_UNESCAPED”, но это неудобно – хотелось бы, чтобы была возможность читать логи без танцев с бубном. В результате родился скрипт, декодирующий подобные последовательности символов в нормальные строки в UTF-8:

#!/bin/sh
if [[ $# -eq 0 ]] ; then
    echo "Usage: $0 apache_log_file_name"
    echo "Символы utf8 будут декодированы из вида \\xd0\\xa3\\xd0\\xbf\\xd1\\x80\\xd0\\xb0 в нормальные символы UTF-8"
    exit 0
fi

if [[ $# -eq 1 ]] ; then
    /usr/bin/tail -f "$1" | while read -r line; do echo -e "$line"; done;
fi

Новый сервис: проверка решения геометрических задач

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

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

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

Правда, тут есть нюанс. В HTML5 для рисования предусмотрен тег canvas, в котором координаты X идут слева направо (как и в школьной тетради); а вот координаты Y в нем отсчитываются сверху вниз (зеркально по отношению к обычному рисунку в тетради). Если кто-то решит перенести получившийся чертеж в тетрадь, необходимо учесть эту особенность отображения.

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

Slack for Linux и SOCKS proxy

Доблестный РКН уже достал блокировать все подряд. Telegram как работал, так и работает; а вот Slack рабочий отвалился. Разработчики Slack почему-то не предусмотрели опции настройки сети в моем клиенте ( версия 3.1.1 ), однако он вполне себе умеет работать с прокси, просто он берет его настройки из переменных окружения. Просто оставлю это здесь:

$ cat start_slack.sh

#!/bin/sh
export SOCKS_SERVER=127.0.0.1:5678
/usr/bin/slack

Восстановление случайно удаленного файла в ext4

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

Нашел шикарнейшую утилиту для восстановления файлов — extundelete версии 0.2.4. Скачал исходники, собрал и попробовал восстановить результат работы за весь день. Надо сказать, что у меня система установлена на разделе /dev/sda1 (смонтирована в корень), а домашние директории пользователей находятся на /dev/sda4 и монтируются в /home.

Порядок восстановления файла такой:

# umount /dev/sda4

# /ramdisk/extundelete-0.2.4/src/extundelete --restore-file "usename/projects" -o /ramdisk /dev/sda4

В выводе было видно, что в usename/projects есть удаленные файлы. Inode = 3670592 . Теперь файл можно восстановить:

# /ramdisk/extundelete-0.2.4/src/extundelete --inode 3670592 --restore-file=usename/projects/myproject/mymodule.pl /dev/sda4

Successfully restored file  usename/projects/myproject/mymodule.pl

Файл оказался сохранен в /ramdisk/RECOVERED_FILES/username/projects/myproject/mymodule.pl Осталось только смонтировать /home и перекинуть файл обратно.

Про странные вещи в мире программирования.

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

Многие базы данных корректно работают с датами. Если взять дату — 31.12.2017, и отнять от нее один месяц, то должна получиться дата — 30.11.2017:

db=# select '2017-12-31'::timestamp - interval '1 month' new_date;
      new_date       
---------------------
 2017-11-30 00:00:00
(1 строка)
MariaDB [(none)]> select '2017-12-31' - interval 1 month new_date;
+------------+
| new_date   |
+------------+
| 2017-11-30 |
+------------+
1 row in set (0.00 sec)

Но php почему-то считает иначе:

$dt = date_create("2017-12-31");
$dt->modify("-1 month");
echo $dt->format('Y-m-d')."\n";

2017-12-01

Интересно то, что разработчики php не считают такое поведение багом, а особенностью реализации алгоритма работы с датами.

Синхронизация времени на разных серверах

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

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

telnet 10.11.12.105 80
Trying 127.0.0.1...
Connected to 10.11.12.105.
Escape character is '^]'.
GET / HTTP/1.0

HTTP/1.0 200 OK
Date: Mon, 14 Sep 2017 19:43:59 GMT
Connection: close
Content-Type: text/html; charset=UTF-8
Content-Length: 1496
….

Само тело ответа нас не интересует, нам достаточно знать время. Его можно распарсить и при наличии рутовых прав можно установить локально часы в полученное значение времени. Команда выглядит так:

root# date -s "$(curl -sD - 10.11.12.105 | grep -E '^[[:space:]]*[dD]ate:' | sed 's/^[[:space:]]*[dD]ate:[[:space:]]*//' | head -1l | awk '{print $1, $3, $2,  $5 ,"GMT", $4 }' | sed 's/,//')"

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

ssh root@10.11.12.102 date --utc $(date --utc "+%m%d%H%M%Y.%S")

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

Новый сервис: онлайн форматирование JSON

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

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

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

В качестве теста можно использовать строку JSON, например, такую:

{"data":[{"t1":"John","t2":"Doe"},{"t1":"Anna","t2":"Smith" },{"t1":"Peter" ,"t2":"Jones"}]}

На выходе будет удобно читаемый JSON:

{
   "data" : [
      {
         "t2" : "Doe",
         "t1" : "John"
      },
      {
         "t2" : "Smith",
         "t1" : "Anna"
      },
      {
         "t2" : "Jones",
         "t1" : "Peter"
      }
   ]
}

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

OpenSuSe 13.1, ноутбук с видеокартой Nvidia и старые игры в wine

Так получилось, что ранее я ругал карты ATI Radeon здесь, тут и там. И для разнообразия у меня появился ноутбук Lenovo Z560 с карточкой Nvidia на борту. Пропиетарные дрова с сайта Nvidia ставятся без проблем, все работает хорошо — за исключением одного маленького нюанса.

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

> xrandr -q
Screen 0: minimum 8 x 8, current 1366 x 768, maximum 8192 x 8192
VGA-0 disconnected (normal left inverted right x axis y axis)
LVDS-0 connected primary 1366x768+0+0 (normal left inverted right x axis y axis) 344mm x 194mm
   1366x768       60.0*+   50.0  
HDMI-0 disconnected (normal left inverted right x axis y axis)

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

> xrandr --q1
 SZ:    Pixels          Physical       Refresh
*0   1366 x 768    ( 340mm x 191mm )  *50   51  
 1   1280 x 720    ( 318mm x 179mm )   52  
 2   1024 x 768    ( 254mm x 191mm )   53  
 3    800 x 600    ( 199mm x 149mm )   54  
 4    640 x 480    ( 159mm x 119mm )   55  
Current rotation - normal
Current reflection - none
Rotations possible - normal left inverted right 
Reflections possible - X Axis Y Axis

Если надо кодить, или править документ какой-нибудь, то проблемы это не вызывает. Но если решил порубиться в старую игрушку с древним разрешением экрана (например, 640×480), то игра вполне себе может ругаться на разрешение экрана. Например, у меня fallout не запускался, и появлялось сообщение Error initializing video mode 640×480, и в консоли при этом был виден текст ошибки такого вот содержания:

err:x11settings:X11DRV_ChangeDisplaySettingsEx No matching mode found 640x480x8 @0! (XRandR 1.2)

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

> cat setres.sh
#!/bin/bash
RESOLUTION=$1
nvidia-settings --assign CurrentMetaMode="LVDS-0: nvidia-auto-select @$RESOLUTION +0 +0 {ViewPortIn=$RESOLUTION, ViewPortOut=$RESOLUTION}"

Второй скрипт собственно меняет разрешение экрана на правильное, запускает fallout в десктопе со «правильным» разрешением экрана, ну и возвращает настройки разрешения обратно по завершении игры:

> cat fallout1.sh
#!/bin/sh
cd /home/username/.wine/drive_c/Program Files/GOG.com/Fallout
/usr/local/bin/setres.sh 640x480
wine explorer /desktop=foo,640x480 falloutw.exe
/usr/local/bin/setres.sh 1366x768
cd $HOME

Смена разрешения на 640×480 — необязательный шаг, и если его не сделать, можно играть в оконном режиме. А вот для полноэкранного режима без смены разрешения не обойтись.

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

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

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

Так получилось, что рядом с домом у нас есть офис налоговой, который относится к другому району. А офис нашей налоговой находится дальше раз в 20. Покумекав немного, я решил пойти в ближайшую налоговую в гости, благо при регистрации было четко сказано — пароль в личный кабинет можно получить в любом отделении ФНС (кроме некоторых). Зашел туда, и там случился фейл номер 2 — оказывается, у налоговых органов нет единой базы, и им пришлось вручную вбивать мою заявку на доступ в личный кабинет. Что в общем-то вызвала некую бурю относительно праведного гнева со стороны местных сотрудников ФНС. Но с горем пополам они все же доступ мне сделали.

Окрыленный успехом, я добежал до компьютера и залогинился в личный кабинет. Но не тут-то было — он оказался ПУСТОЙ, с нулем ценной для меня информации. Личный кабинет формируется в течение 3-х РАБОЧИХ дней, и судя по скорости внесения данных туда, они попадают в личный кабинет путем ручного вноса доблестных сотрудников ФНС.

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

Онлайн оплата налогов в настоящий момент лишь обладателям счетов в одном из 15 банков, среди которых я знаю только Сбер. Но так как с филиалом ада на земле я сотрудничать отказался, и этот чудный инструмент по онлайн оплате налогов для меня оказался БЕСПОЛЕЗЕН.

Еще один непонятный момент мне не понравился. Оказывается, мне нельзя заплатить налоги за супругу или за кого-то еще. Этот запрет явным образом прописан в личном кабинете (в виде вот такого текста): «При списании денежных средств с Вашего счета в банке в уплату налогов, сборов за других физических лиц их обязанность не будет признана исполненной!». Просто все для людей сделано, и для их удобства — просто нет слов.

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