Я относительно редко пишу код на сравнительно низкоуровневых языках, все больше автоматизацию на PowerShell. Однако порой, когда возникает желание, ну, или, необходимость - пишу. В этот раз мне понадобилось сгенерировать классы для работы с внешними системами. Чтобы не забыть, опишу весь процесс тут.
Chrome DevTools Protocol (CDP)
Однажды захотелось странного - сделать инструмент, который бы мог собрать информацию о том, куда ломится та или иная web страница. Когда страницу открывает браузер она может делать всякое, от загрузки картинок до скачивания и исполнения скриптов, которые могут тянуть другие скрипты, которые могут тоже что-то тянуть и так до бесконечности. Так вот, очень хотелось весь этот поток событий увидеть, захватить и проанализировать. Обычно для этого хватает средств отладки самого браузера. Однако как потом эти данные обработать в автоматическом режиме, например чтобы обновить правила firewall или сделать какую-то визуализацию. Есть, конечно, всякие внешние инструменты, типа selenium или , которые, возможно умеют делать что-то подобное. Но они тащат за собой браузер, складывают все эти браузеры не известно куда и так далее и тому подобное. Хотелось чего-то более простого, и чтоб самому слишком много не писать.
В общем, выяснилось, что есть у Chromium такая штука как Chrome DevTools Protocol (CDP). Если в двух словах, то это протокол управления браузером, использующий WebSocket как транспорт. Если запустить браузер с определенными ключами, к нему можно подключиться и программно им управлять. Однако готовых библиотек под .NET, да еще чтоб без всяких излишеств типа управления браузером не нашлось, да и хотелось поэксперементировать… Есть, конечно, puppeteer, но это JavaScript, есть Microsoft Playwright, но там какой-то ужасный способ инсталляции браузеров, куда-то они ложатся.
по ходу дела выяснилось что даже сырой хромиум следит за тобой, но это уже другая история
Короче, нашелся “кодогенератор”. Казалось, чего проще, склонируй, собери, запусти и будет тебе счастье, но, как водится, что-то пошло не так. Не завелось. Пришлось поковыряться.
Среди прочего, выяснилось, что “кодогенератор” этот скачивает описание протокола из хромиума и выполняет специальный Python скрипт, который выдает json версию описания. При этом скрипт этот исполнялся в среде IronPython. Следуя новомодным тенденциям, мне пришло в голоыу заменить его на CSnakes - супер новомодную библиотеку взаимодействия между Python и .NET. Собственно почему бы и нет. Оказалось относительно просто. Заработало буквально за пару часов.
Кроме того я узнал о handlebars, движке обработки шаблонов. Кодогенератор использует его при генерации C# всего кода: как кода CDP протокола, так и менеджера сессий управления браузером.
В общем, с помощью лома, ChatGPT и такой-то матери я починил этот генератор, правда при этом сломал ему параметры командной строки, но он все равно генерит код, правда только в дефолтный путь. Для этого, правда:
- заменил в нем IronPython на CSnakes
- заменил WebSocket4Net на System.Net.WebSockets
- обновил пакеты до последних версий
- чего-то там еще делал, но уже забыл
И как результат, рабочая версия генерируемого кода, которая:
- умеет подключиться к браузеру
- посылать в него команды
- подписываться на сообщения
Почему кастомный генератор? Просто потому, что в гугле не стали заморачиваться с использованием json schema, а просто колбасят json из своего внутреннего формата, видимо. Но это не точно.
Работа с реальной JSON-схемой (но тоже не без проблем)
Второй фронт — хотелось прикрутить Vega к PowerShell. А под новые версии схем готовых классов не нашлось. Или я не нашёл.
И, то ли я недочитал документацию, то ли одно из двух — но с первого раза и схему я тоже не нашёл. Зато нашел со второго — вот тут она. С ней всё, в некотором роде, проще. Есть quicktype, который, к счастью, вполне неплохо справляется с задачей. Однако и тут не без изъяна. Прежде всего — вот в упор не понимаю, зачем все кому не лень начинают писать свои менеджеры пакетов. Чем им уже существующие не нравятся? Тем, что их делали не они?
Ну да ладно, это лирика. Собственно, что нам надо сделать — это, примерно, вот так:
npm install -g quicktype
Ну и потом
quicktype --lang cs --src-lang schema -o ./PSGraph.Vega.Extensions/VegaSpec.cs ./PSGraph.Vega.Extensions/Assets/vegaSpec.json --namespace PSGraph.Vega.Spec -t Vega
В итоге получается куча кода, которая вполне себе собирается. Но есть несколько НО. Несмотря на документацию, тул не смог подтянуть JSON-схему из URL — пришлось скачать вручную. Ну или я что-то делал не так. И, к несчастью, вот такие штуки — patternProperties — корректно не обрабатываются, из-за чего местами генерируется неверный код.
Честно говоря, я не совсем понял, чего хотят добиться этими регулярками — но они там есть. И это не работает. Разбираться в деталях в этот раз не стал, поправил руками. Может быть, как-нибудь потом разберусь.
"patternProperties": {
"^(?!interactive|name|style).+$": {
"$ref": "#/definitions/encodeEntry"
}
}
Как результат, для моих целей вполне себе заработало. Но о целях и что из этого вышло, как-нибудь в другой раз.