Веб-браузер для терминала с поддержкой javascript
Обнаружил любопытный проект: веб-браузер для терминала с поддержкой css и javascript. Называется Chawan. Управляется vim-подобными хоткеями.
После установки доступно две команды: cha и mancha. Первая собственно веб-браузер, а вторая - просмотрщик man-страниц. Последний позволяет переходить по ссылкам между man-страницами что очень удобно. Запускается командой:
Ну а собственно браузер запускается командой:
Качать отсюда: https://chawan.net/
Обнаружил любопытный проект: веб-браузер для терминала с поддержкой css и javascript. Называется Chawan. Управляется vim-подобными хоткеями.
После установки доступно две команды: cha и mancha. Первая собственно веб-браузер, а вторая - просмотрщик man-страниц. Последний позволяет переходить по ссылкам между man-страницами что очень удобно. Запускается командой:
mancha bash
Ну а собственно браузер запускается командой:
cha https://proverka.ru
Качать отсюда: https://chawan.net/
👍2
Нашёл недоработку на госуслугах
Недоработка некритичная но на самом виду. В разделе профиля "сим-карты" есть две вкладки: "Личные номера" и "Корпоративные номера". Если сделать активной вкладку "Корпоративные номера" и нажать "Обновить данные" то после обновления информации содержимое вкладок будет перепутано.
Нашёл случайно. Куда репортить - не знаю. Есть целая "Платформа обратной связи". Но туда не пускают без подтверждённой записи госуслуг и обращение привязывается к региону. Возможно это и оно, но интересно что делать если не можешь авторизоваться или бага не имеет привязки к региону)
Недоработка некритичная но на самом виду. В разделе профиля "сим-карты" есть две вкладки: "Личные номера" и "Корпоративные номера". Если сделать активной вкладку "Корпоративные номера" и нажать "Обновить данные" то после обновления информации содержимое вкладок будет перепутано.
Нашёл случайно. Куда репортить - не знаю. Есть целая "Платформа обратной связи". Но туда не пускают без подтверждённой записи госуслуг и обращение привязывается к региону. Возможно это и оно, но интересно что делать если не можешь авторизоваться или бага не имеет привязки к региону)
Продолжаем разработку бота и миниприложения для национального мессенджера
На платформе "Макс для бизнеса" в настройках бота есть галочка: "Добавление в групповые чаты". При виде этой галочки сразу появляются различные идеи: от ведения логов чата, до всяких викторин. Что же на практике?
А на практике вот что: если галочку включить то бота можно добавить в групповой чат. Сразу после добавления боту на вебхук прилетает уведомление с типом BotAddedToChatUpdate и всё. Сообщения из чата боту на вебхук не приходят! Даже если явно упоминать бота в чате.
А ещё отправка сообщений. если вы отправляете сообщение конкретному пользователю то пишете так:
Но если вам надо отправить сообщение в групповой чат то писать надо уже так:
Идентификаторы пользователей и чатов это две разные сущности. И они не пересекаются. После Telegram, в котором любой чат, хоть одиночный, хоть групповой, хоть вообще канал - одно и тоже. Несколько не привычно.
P.S. А при удалении бота из группового чата ему прилетает сообщение с типом BotRemovedFromChatUpdate. И на этом всё.
На платформе "Макс для бизнеса" в настройках бота есть галочка: "Добавление в групповые чаты". При виде этой галочки сразу появляются различные идеи: от ведения логов чата, до всяких викторин. Что же на практике?
А на практике вот что: если галочку включить то бота можно добавить в групповой чат. Сразу после добавления боту на вебхук прилетает уведомление с типом BotAddedToChatUpdate и всё. Сообщения из чата боту на вебхук не приходят! Даже если явно упоминать бота в чате.
А ещё отправка сообщений. если вы отправляете сообщение конкретному пользователю то пишете так:
message := maxbot.NewMessage().
SetFormat(schemes.Markdown).
SetUser(userId).
SetText(someText)
err := r.apiClient.Messages.Send(ctx, message)
Но если вам надо отправить сообщение в групповой чат то писать надо уже так:
message := maxbot.NewMessage().
SetFormat(schemes.Markdown).
SetChat(charId).
SetText(someText)
err := r.apiClient.Messages.Send(ctx, message)
Идентификаторы пользователей и чатов это две разные сущности. И они не пересекаются. После Telegram, в котором любой чат, хоть одиночный, хоть групповой, хоть вообще канал - одно и тоже. Несколько не привычно.
P.S. А при удалении бота из группового чата ему прилетает сообщение с типом BotRemovedFromChatUpdate. И на этом всё.
А мы продолжаем изучать отечественные платформы
Чуть ранее я писал что настроил трансляцию из TG-канала в "Дзен" используя дзеновский "Синхробот".
Вчера этот "Синхробот" порадовал меня сообщением:
Общение с техподдержкой Дзена привело к следующему:
Как говорил Карлсон: "Спокойствие, только спокойствие..."
UPD: Этот пост тоже не прошёл проверку синхробота. По той же причине.
Чуть ранее я писал что настроил трансляцию из TG-канала в "Дзен" используя дзеновский "Синхробот".
Вчера этот "Синхробот" порадовал меня сообщением:
Ваш пост https://t.me/ylsoftware/181 содержит рекламную метку и не будет опубликован.
Общение с техподдержкой Дзена привело к следующему:
Чтобы переносить подобные материалы, вы можете удалить фрагмент «userId» из поста или отредактировать (например, «user Id»). Затем в Дзене откройте перенесенный пост и поменяйте текст на корректный. В Telegram тоже можно вернуть изначальный текст.
Как говорил Карлсон: "Спокойствие, только спокойствие..."
UPD: Этот пост тоже не прошёл проверку синхробота. По той же причине.
Firefox здорового человека
Есть такой браузер - Midori. Несколько лет назад он был перезапущен и практически полностью переписан. Результат мне очень нравится: Интерфейс напоминает Google Chrome, но со множеством своих довольно полезных и удобных фишек.
При этом под капотом движок Gecko (как в Firefox), работает Firefox Sync, есть поддержка Web Extensions (предлагается ставить расширения из каталога Mozilla Addons) и тем оформления.
Есть сборки под Windows и различные дистрибутивы Linux. Имеется версия для Android и обещают версию для iOS. Исходные тексты так же доступны. Вобщем как минимум стоит попробовать.
Брать тут: https://astian.org/midori-browser/
Есть такой браузер - Midori. Несколько лет назад он был перезапущен и практически полностью переписан. Результат мне очень нравится: Интерфейс напоминает Google Chrome, но со множеством своих довольно полезных и удобных фишек.
При этом под капотом движок Gecko (как в Firefox), работает Firefox Sync, есть поддержка Web Extensions (предлагается ставить расширения из каталога Mozilla Addons) и тем оформления.
Есть сборки под Windows и различные дистрибутивы Linux. Имеется версия для Android и обещают версию для iOS. Исходные тексты так же доступны. Вобщем как минимум стоит попробовать.
Брать тут: https://astian.org/midori-browser/
👍2
Почему я практически перестал писать про администрирование
Я много лет администрировал всякие разные железки. В основном на Linux, но были и FreeBSD и Solaris. И одновременно программировал, но всё больше как хобби. Потом я стал сразу на работе и писать код и администрировать сервера. В какой-то момент я оказался лидом сразу нескольких команд. Предсказуемо результат от этого хромал и нужно было что-то решать.
В итоге в 2018-м году очень удачно сложились обстоятельства и я передал руководство devops молодому, но очень достойному парню, на руководство мобильной разработкой нашли хорошего человека, и я полностью сосредоточился на деятельности R&D-отдела.
Сейчас я пишу код на Go/PHP/Perl для задач R&D. С devops дружу, но в их работу стараюсь не лезть. Теперь уже администрирование из профессии превратилось в хобби.
Хочу писать про программирование, но солидная часть работы покрыта NDA. А то, про что можно писать, в большинстве своём не интересно.
Я много лет администрировал всякие разные железки. В основном на Linux, но были и FreeBSD и Solaris. И одновременно программировал, но всё больше как хобби. Потом я стал сразу на работе и писать код и администрировать сервера. В какой-то момент я оказался лидом сразу нескольких команд. Предсказуемо результат от этого хромал и нужно было что-то решать.
В итоге в 2018-м году очень удачно сложились обстоятельства и я передал руководство devops молодому, но очень достойному парню, на руководство мобильной разработкой нашли хорошего человека, и я полностью сосредоточился на деятельности R&D-отдела.
Сейчас я пишу код на Go/PHP/Perl для задач R&D. С devops дружу, но в их работу стараюсь не лезть. Теперь уже администрирование из профессии превратилось в хобби.
Хочу писать про программирование, но солидная часть работы покрыта NDA. А то, про что можно писать, в большинстве своём не интересно.
На работе стали использовать термин "навайбкодил" вместо "наговнякал". Параллельно придумали термин "наGOвнякал". Это если навайбкодил на Go)
😁3
Про не совсем очевидное
Была у нас задача: где-то в Европе стоит сервер, который обрабатывает запросы. Вплоть до 500 rps. И результат обработки каждого запроса (около 1000 байт) надо писать в БД, но БД в США. Связь между континентами хоть и редко, но всё же теряется.
Первым делом придумали писать результаты в RabbitMQ, и потом их вычитывать. Если потерялась связь то данные не потеряются, а просто подгрузятся с задержкой.
Канал между локациями гигабитный и пинг около 40мс. Что могло пойти не так? Данные в очереди копились быстрее чем мы их вычитывали. Да, 1000 байт на скорости в 1 гигабит/с действительно передаётся "со свистом", но тут начинает влиять задержка. При 40мс по вполне очевидным причинам не получится вычитывать данные со скоростью больше 25rps.
В качестве решения написали сервис, который крутился на том же сервере в Европе, вычитывал данные из очереди, группировал их в пачки до 1000 штук и эти пачки складывал в соседнюю очередь. А сервер в США уже вычитывал и обрабатывал эти пачки.
Решение работает уже более десяти лет. А пакетный режим в RabbitMQ так и не появился.
Была у нас задача: где-то в Европе стоит сервер, который обрабатывает запросы. Вплоть до 500 rps. И результат обработки каждого запроса (около 1000 байт) надо писать в БД, но БД в США. Связь между континентами хоть и редко, но всё же теряется.
Первым делом придумали писать результаты в RabbitMQ, и потом их вычитывать. Если потерялась связь то данные не потеряются, а просто подгрузятся с задержкой.
Канал между локациями гигабитный и пинг около 40мс. Что могло пойти не так? Данные в очереди копились быстрее чем мы их вычитывали. Да, 1000 байт на скорости в 1 гигабит/с действительно передаётся "со свистом", но тут начинает влиять задержка. При 40мс по вполне очевидным причинам не получится вычитывать данные со скоростью больше 25rps.
В качестве решения написали сервис, который крутился на том же сервере в Европе, вычитывал данные из очереди, группировал их в пачки до 1000 штук и эти пачки складывал в соседнюю очередь. А сервер в США уже вычитывал и обрабатывал эти пачки.
Решение работает уже более десяти лет. А пакетный режим в RabbitMQ так и не появился.
Кросплатформенная разработка
По работе понадобился небольшой инструмент чтобы дёргать кое-какое внутреннее API, пока не завезли нормальную интеграцию со всей остальной системой. Навайбкодил на Go с использованием Fyne.io. Получилось лучше чем ожидал.
Писал вобщем-то под десктоп, но раз у Fyne есть поддержка сборки под мобилки, то почему бы и нет? Собрал под Android. Из особенностей: для сборки используется NDK, и значит результат не на всякой аппаратной платформе будет работать. Но собирается сразу под armeabi-v7a, arm64-v8a, x86 и x86_64. Т.е. основные аппаратные платформы поддерживаются.
Выглядит на мобилке не очень, но в принципе кнопочки нажимаются, текст вводится, а большего и не надо. Для внутренних нужд точно сойдёт.
Если кому-то интересно то могу рассказать подробнее про разработку с Go/Fyne.
По работе понадобился небольшой инструмент чтобы дёргать кое-какое внутреннее API, пока не завезли нормальную интеграцию со всей остальной системой. Навайбкодил на Go с использованием Fyne.io. Получилось лучше чем ожидал.
Писал вобщем-то под десктоп, но раз у Fyne есть поддержка сборки под мобилки, то почему бы и нет? Собрал под Android. Из особенностей: для сборки используется NDK, и значит результат не на всякой аппаратной платформе будет работать. Но собирается сразу под armeabi-v7a, arm64-v8a, x86 и x86_64. Т.е. основные аппаратные платформы поддерживаются.
Выглядит на мобилке не очень, но в принципе кнопочки нажимаются, текст вводится, а большего и не надо. Для внутренних нужд точно сойдёт.
Если кому-то интересно то могу рассказать подробнее про разработку с Go/Fyne.
👍1
goKeeperViewer
Когда-то давно у меня появился ноутбук с Windows и процессором Qualcomm. До сих пор это довольно интересная штука: длительная работа от батареи, встроенный модем и недостаток нативного софта. Последний факт побудил меня набросать просмотрищик файлов keepass (хранилище паролей). Писал на Go + Fyne.io.
Инструмент свою функцию выполняет: файлы открывает, в том числе с поддержкой ключевых файлов. Код немного жутковат, но это был мой первый опыт с Fyne. Т.е. проект одновременно выполнял ещё и учебную функцию. Из минусов: нет поддержки аттачей. Хотя возможно и это когда-нибудь реализую если будет потребность.
Если кому-то вдруг надо то исходники тут: https://github.com/moose-kazan/goKeeperViewer
Когда-то давно у меня появился ноутбук с Windows и процессором Qualcomm. До сих пор это довольно интересная штука: длительная работа от батареи, встроенный модем и недостаток нативного софта. Последний факт побудил меня набросать просмотрищик файлов keepass (хранилище паролей). Писал на Go + Fyne.io.
Инструмент свою функцию выполняет: файлы открывает, в том числе с поддержкой ключевых файлов. Код немного жутковат, но это был мой первый опыт с Fyne. Т.е. проект одновременно выполнял ещё и учебную функцию. Из минусов: нет поддержки аттачей. Хотя возможно и это когда-нибудь реализую если будет потребность.
Если кому-то вдруг надо то исходники тут: https://github.com/moose-kazan/goKeeperViewer
❤1
OpenGL: стандарт, но есть нюансы
OpenGL хороший стандарт, который развивается уже несколько десятилетий и поддерживается многими современными системами. Тем интереснее было узнать что Windows из коробки этот самый OpenGL не поддерживает.
Microsoft продвигает DirectX. И всем кому нужна графика на Windows предлагается использовать именно этот API. Однако поставщики драйверов видеокарт поставляют вместе с драйверами свою реализацию OpenGL. Как минимум это касается Intel, AMD и NVIDIA. Ну т.е. фактически на большинстве современных компьютеров с Windows поддержка OpenGL всё же есть, но благодаря вендорам видеокарт.
Интереснее стало когда начали появляться ноутбуки с arm64-процессорами: оказалось что Qualcomm для своих графических ускорителей предоставляет драйвера без поддержки OpenGL. Подозреваю что проблема может так же присутствовать на устройствах с процессорами Zhaoxin, но проверить у меня нет возможности.
Учитывая что многие открытые проект используют именно API OpenGL вырисовывается проблема. В качестве решения Microsoft предоставляет "OpenCL and OpenGL Compatibility pack", который можно найти тут: https://apps.microsoft.com/detail/9nqpsl29bfff
OpenGL хороший стандарт, который развивается уже несколько десятилетий и поддерживается многими современными системами. Тем интереснее было узнать что Windows из коробки этот самый OpenGL не поддерживает.
Microsoft продвигает DirectX. И всем кому нужна графика на Windows предлагается использовать именно этот API. Однако поставщики драйверов видеокарт поставляют вместе с драйверами свою реализацию OpenGL. Как минимум это касается Intel, AMD и NVIDIA. Ну т.е. фактически на большинстве современных компьютеров с Windows поддержка OpenGL всё же есть, но благодаря вендорам видеокарт.
Интереснее стало когда начали появляться ноутбуки с arm64-процессорами: оказалось что Qualcomm для своих графических ускорителей предоставляет драйвера без поддержки OpenGL. Подозреваю что проблема может так же присутствовать на устройствах с процессорами Zhaoxin, но проверить у меня нет возможности.
Учитывая что многие открытые проект используют именно API OpenGL вырисовывается проблема. В качестве решения Microsoft предоставляет "OpenCL and OpenGL Compatibility pack", который можно найти тут: https://apps.microsoft.com/detail/9nqpsl29bfff
Ещё одна история из жизни
Лет эдак пятнадцать назад был у нас большой и интересный проект. Одного только оборудования было полторы 42U-стойки. Сервера были соединены между собой в локальную сеть через пару гигабитных коммутаторов.
И вот моему коллеге дали текстовый файлик размером около мегабайта. Задача стояла простая: на каждый запрос выбирать несколько случайных строк из файла и отображть их в одной из колонок на странице.
Я дико не люблю чтение из файлов. На то есть причины и сейчас не о них. Важно что помятуя об этом коллега придумал гениальное (на первый взгляд) решение: закинуть файл в memcached, брать его оттуда, выбирать случайные строки и отображать их. И снова вопрос: что же могло тут пойти не так?
Между бэкендами и memcached-сервером гигабитный линк. Нетрудно посчитать что 1 мегабайт по гигабитному линку передаётся около 8мс. И значит хитрый план работает только до ~120rps. У нас же было в зависимости от времени суток от ~100 (ночью) до ~350rps в вечернем пике.
Товарищ выкатил правки, посмотрел что всё работает и пошёл спать. Утром мы проснулись от того что "всё сломалось". Просто потому что ночью на 100rps хитрый план со скрипом, но работал, а утром уже при ~140rps всё встало колом.
Такие дела...
Лет эдак пятнадцать назад был у нас большой и интересный проект. Одного только оборудования было полторы 42U-стойки. Сервера были соединены между собой в локальную сеть через пару гигабитных коммутаторов.
И вот моему коллеге дали текстовый файлик размером около мегабайта. Задача стояла простая: на каждый запрос выбирать несколько случайных строк из файла и отображть их в одной из колонок на странице.
Я дико не люблю чтение из файлов. На то есть причины и сейчас не о них. Важно что помятуя об этом коллега придумал гениальное (на первый взгляд) решение: закинуть файл в memcached, брать его оттуда, выбирать случайные строки и отображать их. И снова вопрос: что же могло тут пойти не так?
Между бэкендами и memcached-сервером гигабитный линк. Нетрудно посчитать что 1 мегабайт по гигабитному линку передаётся около 8мс. И значит хитрый план работает только до ~120rps. У нас же было в зависимости от времени суток от ~100 (ночью) до ~350rps в вечернем пике.
Товарищ выкатил правки, посмотрел что всё работает и пошёл спать. Утром мы проснулись от того что "всё сломалось". Просто потому что ночью на 100rps хитрый план со скрипом, но работал, а утром уже при ~140rps всё встало колом.
Такие дела...
Немного рукоделия
Есть у меня RepkaPi4 с eMMC в оригинальном корпусе. Штука крутая, но 64GB eMMC для домашнего сервера мне показалось мало. В качестве решения я в единственный USB3 подключил внешний SSD. Работает, но захотелось добавить немного жёсткости конструкции.
В гараже лежали обрезки поликарбоната. В кладовке - детский металлический конструктор. Поликарбонат лучше резать специальным станком, но в его отсутствие я использовал электролобзик. Неизбежную неровность немного подправил дремелем. Всё равно не идеально, но если не присматриваться то сойдёт)
Опыт такая штука, которая появляется сразу после того как была нужна. И тут тоже: понимание как лучше делать пришло уже после того как я закончил сборку. Получилось не совсем то что я изначально планировал, но результатом доволен.
В корпуе есть место под второй накопитель (правда не понятно куда его подключать). Ну или можно разместить модем или ТВ-тюнер. Вобщем судя по всему вариант не финальный и будут новые ревизии.
Есть у меня RepkaPi4 с eMMC в оригинальном корпусе. Штука крутая, но 64GB eMMC для домашнего сервера мне показалось мало. В качестве решения я в единственный USB3 подключил внешний SSD. Работает, но захотелось добавить немного жёсткости конструкции.
В гараже лежали обрезки поликарбоната. В кладовке - детский металлический конструктор. Поликарбонат лучше резать специальным станком, но в его отсутствие я использовал электролобзик. Неизбежную неровность немного подправил дремелем. Всё равно не идеально, но если не присматриваться то сойдёт)
Опыт такая штука, которая появляется сразу после того как была нужна. И тут тоже: понимание как лучше делать пришло уже после того как я закончил сборку. Получилось не совсем то что я изначально планировал, но результатом доволен.
В корпуе есть место под второй накопитель (правда не понятно куда его подключать). Ну или можно разместить модем или ТВ-тюнер. Вобщем судя по всему вариант не финальный и будут новые ревизии.
👍2
Немного про электронные книги
Тут в канале @fbreader опубликован пост, в котором сообщается о прекращении интеграции c Литрес в FBReader и об отсутствии в FBReader поддержки FB3.
Я тут немного удивлён. Считал всегда FBReader довольно продвинутой читалкой с поддержкой всех форматов, которые только можно вспомнить.
Тем приятнее становится о того что мой Qt Book Reader этот самый FB3 поддерживает)
Тут в канале @fbreader опубликован пост, в котором сообщается о прекращении интеграции c Литрес в FBReader и об отсутствии в FBReader поддержки FB3.
Я тут немного удивлён. Считал всегда FBReader довольно продвинутой читалкой с поддержкой всех форматов, которые только можно вспомнить.
Тем приятнее становится о того что мой Qt Book Reader этот самый FB3 поддерживает)
❤2
От подписчиков
Простое но интересное дополнение написал один из читателей канала. Создано для Firefox, но я проверил - в Midori тоже работает. Объединяет вкладки в группы на основе домена. Домены с www и без оного считаются равными. Выглядит удобно.
Для интересующихся подробности тут: https://neonxp.ru/posts/2026-02-01-grouper/
Простое но интересное дополнение написал один из читателей канала. Создано для Firefox, но я проверил - в Midori тоже работает. Объединяет вкладки в группы на основе домена. Домены с www и без оного считаются равными. Выглядит удобно.
Для интересующихся подробности тут: https://neonxp.ru/posts/2026-02-01-grouper/
👍2
docker и docker-compose
Довольно давно существует очень удобная штука: docker-compose. Позволяет буквально в одном файле описать сразу несколько контейнеров, сетей и томов. По сути упаковать целое приложение со всеми сервисами и быстро и легко запустить.
С некоторых пор есть плагин для docker, который позволяет вместо docker-compose использовать просто docker (команда compose). Плагин и оригинальная утилита развиваются параллельно и умудряются вносить путаницу.
В Ubuntu 24.04+ пакет docker-compose виртуальный и предоставляется пакетом docker-compose-v2, который так же содержит плагин для docker. И вот тут начинается моя боль. Есть у меня вот такой фрагмент в docker-compose.yml:
В Ubuntu 24.04 "docker compose" переваривает этот фрагмент нормально, а вот "docker-compose" радует меня ошибкой:
Ну а чтобы мне было не скучно в Debian 13 пакет docker-compose не виртуальный, а вполне себе нормальный и так же предоставляет плагин для docker. И при этом и утилита и плагин работают одинаково.
Потратил несколько часов чтобы понять почему на машине с Debian работает, а с Ubuntu - нет.
Довольно давно существует очень удобная штука: docker-compose. Позволяет буквально в одном файле описать сразу несколько контейнеров, сетей и томов. По сути упаковать целое приложение со всеми сервисами и быстро и легко запустить.
С некоторых пор есть плагин для docker, который позволяет вместо docker-compose использовать просто docker (команда compose). Плагин и оригинальная утилита развиваются параллельно и умудряются вносить путаницу.
В Ubuntu 24.04+ пакет docker-compose виртуальный и предоставляется пакетом docker-compose-v2, который так же содержит плагин для docker. И вот тут начинается моя боль. Есть у меня вот такой фрагмент в docker-compose.yml:
env_file:
- path: config.env
required: true
- path: override.env
required: false
В Ubuntu 24.04 "docker compose" переваривает этот фрагмент нормально, а вот "docker-compose" радует меня ошибкой:
ERROR: The Compose file './docker-compose.yml' is invalid because:
services.bot.env_file contains {"path": "config.env", "required": true}, which is an invalid type, it should be a string
Ну а чтобы мне было не скучно в Debian 13 пакет docker-compose не виртуальный, а вполне себе нормальный и так же предоставляет плагин для docker. И при этом и утилита и плагин работают одинаково.
Потратил несколько часов чтобы понять почему на машине с Debian работает, а с Ubuntu - нет.
😱1