Skip to main content

Evgeny Kuznetsov

Суслик, suka, — личность…

4 min read

Ни для кого не секрет, что я пишу и поддерживаю апплет для панели уведомлений (или как вы там system tray переводите), управляющий MateBook-специфичными функциями. Ну, то есть если вы этим интересовались — вы в курсе. Но вам пофиг, поэтому — нет. Это нормально.

Вот тоже загадка: апплет работает (ну, должен работать… вроде бы…) на любых MateBook'ах, где есть Linux. При этом звёзд на GitHub у него почти на порядок меньше, чем у моего же гайда по установке Linux на MateBook 13! Это с учётом того, что на апплет есть ссылки и со страницы гайда, и даже со страницы драйвера для MateBook'ов. Да что там, у гайда больше звёзд, чем у драйвера! На секудночку: гайд по одной модели, драйвер поддерживает не меньше четырёх; драйвер для полноценной жизни на MateBook необходим, при этом у гайда звёзд больше… Это к вопросу о смысле кармадрочерства как концепции и логике «лайкающих» на гитхабе, да.

Ладно, Тьма с ними, со звёздами. Апплет у меня.

Я его, кстати, на Go пишу. Не, я в курсе, что Go для этого не очень предназначен, но мне нравится писать на Go. Работает, опять же… В конце концов, простите за откровенность, на Цэ-плюс-плюсе я бы такое не осилил. А так — вот, есть апплет. Работает даже. Ну, такое…

Мне Go очень нравится. Я как раз пока такие вещи пишу, заодно язык изучаю. На той неделе, вот, окончательно интерфейсы вкурил. Страшная сила — эти интерфейсы в Go, не вдруг въедешь, если до этого почти исключительно на bash да на basic (да, у меня тяжёлое детство было). Зато как врубишься — ну прямо восемь стволов и всё небо в попугаях! Сколько раз в ООП тыкался — нет, от лукавого все эти ихние наследования! А тут прям именно такой полиморфизм, как надо. Шоб работало, и шоб голову не сломать при проектировании простой программки на сотню строк. Вот прям нравится!

А ещё мне очень Test Driven Development заходит, в который Go хорошо умеет. Ну, то есть как — хорошо… Умеет, из коробки, очень прилично. Но у меня вот тут затык вышел.

Апплет мой, он же с драйвером непосредственно через файловую систему взаимодействует; и даже не только через os, а прям вот таки через ioutil. И никак не возьму я в толк: вот как мне это тестить?!

Не, afero — отличная вещь, согласен, но мне не нужна абстракция файловой системы насмерть, у меня область применения — как раз только и исключительно локальная ФС. Ну и если без зависимости не обойтись — я бы предпочёл что попроще, у меня маленький апплет для трея, а не промышленная CRM же. А делать mock файловой системы, да со всеми нужными ответами и поддержкой ioutil — я ж нарушусь, разве нет?

Понимаете, у меня задача-то — проще некуда! Апплет при инициализации должен потыкать в разные места в /sys/ и понять, с какой конфигурацией он работает, и там куча вариантов (и будет ещё больше), и очень хочется под это запилить нормальный table-driven test. Потому что

если тебе вдруг захотелось отладочной информации в консоли — здесь нужен тест, а не дебаг!

Это очень правильная мысль. Верная даже, только не помню, чья. Поэтому мне всего только надо — сделать так, чтобы для тестов симулировались разные варианты состояний в /sys/. Мне не нужно в кросс-платформенность, всё равно у меня чисто линуксовая заморочка. Мне не нужны возможности в перспективе заменить файловую систему на облако. Мне просто нужно для go test получить «песочницу» файловой системы с абсолютными путями — хоть в памяти, хоть в tmpFS, хоть на диске, хоть как.

Я реально себе сегодня всё правое полушарие об это сломал, и полинтерета обгуглил. То ли лыжи не едут…

очень озадаченный суслик

Картинка хамски попячена из презентации Francesc Campoy Flores.

Evgeny Kuznetsov

Ох, покатаемся завтра…

1 min read

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

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

Evgeny Kuznetsov

Раньше как-то получалось уходить в отпуск без «хвостов» по работе; что называется, «на свободу — с чистой совестью». Сейчас, за день с небольшим до отпуска, никак не могу взять в толк: как же это у меня выходило?!

Evgeny Kuznetsov

O'zbekiston

2 min read

Если соберётесь в Узбекистан, стоит иметь в виду несколько вещей.

Берите с собой Visa или наличные доллары. Про существование евро здесь в целом знают, но больше теоретически. MasterCard обслуживает единственный банк во всей стране, и банкомат вы будете искать очень долго.

Не меняйте на местную валюту (и не снимайте в банкомате) больше денег, чем реально планируете потратить. Обменять местные деньги обратно на сколько-нибудь конвертируемую валюту — целая история, и сделать её успешной у нас, например, так и не вышло.

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

На внутренних авиарейсах нельзя возить зажигалки — вообще никакие. Вообще, досмотр при посадке на общественный транспорт дальнего следования (что наземный, что воздушный) очень дотошный и не всегда логичный в смысле запрета отдельных предметов. Аэропорт имени Бен-Гуриона отдыхает…

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

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

внутри мавзолея Тимура (Тамерлана)

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

Evgeny Kuznetsov

Google Library API — отличная штука! (Нет.)

2 min read

Чем дальше в лес, тем злее дятлы…

Мало того, что Google Library API не желает отдавать файлы с фотографиями в исходном виде (о чём я уже писал); там вообще весь API работает, как Ктулху на душу положит, в зависимости от фазы Луны, положения планет и настроения Дискордии.

Вот, например mediaItems.list — в документации всё чётко, просто и понятно: вкидываем token страницы и желаемый размер, получаем список с описаниями объектов; если объектов больше, чем наш желаемый размер страницы, получаем ещё token для следующей страницы. Нормально? Более чем!

Вот только в реальности при запросе с указанным размером страницы в 100 можно запросто получить ответ с тремя (!!!) объектами и token'ом следующей страницы. На которой будет 62 объекта. А на следующей — 15. Да, чаще будут страницы по сотне (если библиотека достаточно большая), но далеко не всегда. Бывают страницы вообще без объектов, в смысле в JSON вообще не будет поля "mediaItems"

Но это-то ладно, на то и программист, чтобы предусмотреть и обработать любой мусор на входе. Но некоторые объекты вообще не попадают в выдачу… Ну, то есть в документации написано, что в выдаче будут все объекты, кроме тех, что в архиве или в корзине. Вот есть в веб-интерфейсе Google Фото фотография, не в архиве, не в корзине — а в выдаче её нет. Вообще нет как объекта. И ошибок нет. Ну, потому что нефиг, не нужна тебе через API эта фотография.

Шоб у вас в Google такая система доступа в туалеты для сотрудников была, какой вы API состряпали!

визуализация работоспособности Google Library APIPhoto by Alistair MacRobert on Unsplash

Evgeny Kuznetsov

Go — очень клёвый и удобный язык, но иногда его молодость всё-таки даёт о себе знать… 33 строки конфига для Travis CI, из них 30 реально выстраданы… https://github.com/nekr0z/gphotosync/blob/master/.travis.yml

Evgeny Kuznetsov

gphotosync

1 min read

Сам себя не похвалишь — так и будешь ходить, как оплёванный…

Я всё-таки сделал то, о чём писал, причём и библиотеку форкнул, и приложение починил, доработал и выложил на GitHub. Вроде даже под OS X и Windows должно работать (хотя я не проверял).

Вот я молодец! (Произносится с интонацией Хлудова в исполнении Виктора Добронравова).

Evgeny Kuznetsov

Мишель Уэльбек: «Покорность»

2 min read

Французских авторов я читаю очень мало: всё-таки недолюбливаю переводную литературу, а языком этим не владею совсем. Тем больше впечатлений; «Soumission» («Покорность» в переводе Марии Зониной) Мишеля Уэльбека (Michel Houellebecq).

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

Я, пожалуй, этого автора ещё почитаю. Хорошие литераторы — вообще редкость, а уж среди фантастов… А уж среди авторов социальной фантастики ближнего прицела… А литератор он действительно прекрасный, настолько, что само фантдопущение отходит далеко на десятый план, и набрасывается на читателя уже после переворота последней страницы. Кстати, если у вас есть друг, который ценит литературу но не любит фантастики, а вы давно мечтали найти фантастическую книжку, которая ему понравится — так вот это именно она.

Настоятельно рекомендую!

Обложка книги

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

Evgeny Kuznetsov

Google Фото: конец прекрасной эпохи

4 min read

В Google есть добрая традиция закрывать полезные сервисы или ломать удобные вещи; интернет-общественность давно ждёт, когда же они, наконец, объявят о закрытии Gmail… Но Gmail пока живёт, а вот Google Фото решили сломать.

Раньше ж как было у меня, например: все фото с телефона автомагически летят в Google Фото в исходном качестве, а старый ноутбук в шкафу, пафосно называемый «сервер», регулярно бэкапит весь Google Диск (в том числе папку с Google Фото), и добавляет всю эту радость в инкрементные бэкапы. Фото не теряются, всё зарезервировано, красота и благорастворение, я ради этого даже гуглу денег давал за дополнительное место. Теперь всё, кончилась простая жизнь.

GooglePhoto by Arthur Osipyan on Unsplash

Теперь Google Диск будет отдельно, а Google Фото — отдельно. И называется это «мы упростили синхронизацию». Новые фотографии в бэкап не попадут. Куда податься бедному крестьянину?

Во-первых, если уж что в Google попало, то это всегда можно из Google достать: да здравствует Takeout! Вот только Google страшно не любит, когда из него что-то достают, поэтому автоматизировать Takeout нельзя. А бэкап вручную — это всё равно, что без бэкапа вовсе. Поэтому думаем дальше…

Во-вторых, есть же Library API, через который можно тыкаться прямо в Google Фото. Начинаем тыкаться, видим грустную картину: файлы в исходном виде через API не получить, от картинки отрезается половина метаданных (например, информация о координатах места съёмки) и отдаётся отдельно в JSON.

Вывод: как посредник при бэкапах Google Фото теперь бесполезен. Ну что ж, горит дом — гори и баня! Раз такие дела, нет больше смысла платить гуглу за дополнительное место, можно грузить фотографии и видео в Google Фото со сжатием, всё равно бэкапить их теперь надо другим путём.

Кстати, а каким?

без бэкапа никудаPhoto by Markus Spiske on Unsplash

Отправная точка есть: тот самый бэкап директории Google Фото из Google Диска. Копируем в отдельную директорию (потому что из Диска это дело в перспективе надо удалять, чтобы место не занимало). Теперь надо сделать, чтобы туда же добавлялись новые фото, сделанные на телефон. Благо, есть Syncthing: настраиваем папку, куда камера телефона складывает фото и видео, на «только отправить», делимся ей с «сервером», на «сервере» ставим в режим «только получить», чтобы при удалении файлов из этой директории они на телефоне не удалялись. Не забываем, что Syncthing на Android любит электричество, поэтому пусть он работает только при зарядке телефона.

Теперь хорошо бы в cron поставить задачу перемещать из этой директории файлы в наш фото/видеоархив. Правда, в архиве они у нас рассортированы по директориям по годам и месяцам (это удобно, и так было в Google Диске), но это не проблема, мы ведь линуксоиды-туксоводы — бери bash и действуй! В телефоне (в отличие от Google Диска, кстати) mtime файла будет совпадать с временем создания, поэтому пишем несложный скрипт и сажаем его в cron. Одной проблемой меньше.

Правда, вторая проблема осталась: надо как-то забирать из Google Фото фотографии, накиданные родственниками и друзьями в общие альбомы. Вообще Google Фото стоит пользоваться хотя бы ради одного этого: поехали куда-то толпой, создали общий альбом, каждый туда забросил, что наснимал — времена «а кто снимал, когда на море ходили? Вася, не у тебя на фотике? когда скинешь?» прошли навсегда, и вспоминаются как страшный сон. Хорошо бы и это всё в бэкап, как было до гугловского «упрощения».

Пока, правда, новые фотографии в Диск ещё добавляются, так что пока — временно — можно поставить в cron что-то примерно такое:

50 23 * * * /bin/cp -pnr /mnt/ext/GoogleDrive/Google\ Фото/"$(/bin/date -d "week ago" +\%Y/\%m)" /mnt/ext/photo/"$(/bin/date -d "week ago" +\%Y/)"
55 23 * * * /bin/cp -pnr /mnt/ext/GoogleDrive/Google\ Фото/"$(/bin/date +\%Y/\%m)" /mnt/ext/photo/"$(/bin/date +\%Y/)"
10 22 * * 6 /bin/cp -pnr /mnt/ext/GoogleDrive/Google\ Фото/* /mnt/ext/photo/

(Фишка с "week ago" — это чтоб плавно проходить стыки месяцев и годов.)

А вот что делать, когда «упрощение» вступит в силу?..

Нет, понятно, что делать: писать софтину, которая будет по REST API забирать эти файлы из Google Фото напрямую. Для этого придётся, например, форкнуть Go-библиотеку, которую Google сначала выложил, а потом убрал, но Git всё помнит, поэтому по require google.golang.org/api v0.0.0-20181221000618-65a46cafb132 её можно подтянуть. Она неполноценная (например, она не поддерживает для mediaItem свойство filename, хотя для этого достаточно добавить ровно одну строчку), поэтому надо форкать (и потом, очевидно, поддерживать). Потом, имея эту библиотеку, можно слегка допилить обработку ошибок в явно заброшенном проекте, для чего его, очевидно, тоже придётся форкнуть. На всё это нужно время и вдохновение; одна надежда — что кто-то соберётся всё это сделать раньше, чем они будут у меня.

кодить может каждыйPhoto by Adi Goldstein on Unsplash

Надежда эта, правда, совсем призрачная.

Evgeny Kuznetsov

Got an email from @Fastmail regarding the issue (https://evgenykuznetsov.org/2019/felt-like-giving-fastmail-a-try-got) that didn't allow me to register. Well, not from them, actually, but from their automated system. It is awesome:
"Well, your message to support was not delivered to humans, because you first need to 'complete the support system' (wtf?), and to do that you need to log in, which you can't do because your registration wasn't completed, so basically screw you, you're not welcome in our 'customers first' universe!"
Well, I suppose it's a good thing my registration failed. Wouldn't want to trust this company with my email anyway...