@horuzhenko/guac-adapter
v6.0.10
Published
Адаптер для взаимодействия с Apache Guacamole
Readme
b# @horuzhenko/guac-adapter
Адаптер для взаимодействия с Apache Guacamole в Node.js среде.
Возможности
- ✅ Подключение к Guacamole серверу через REST API
- ✅ Установка WebSocket соединения с guacd
- ✅ Рендеринг удаленного рабочего стола в виртуальный canvas
- ✅ Создание скриншотов в форматах PNG и WebP
- ✅ Управление сессиями подключения
- ✅ Обработка Guacamole протокола
- ✅ Интерактивный ввод:
- Движение мыши
- Клики левой, правой и средней кнопкой
- Прокрутка колесом мыши
- Комбинации клавиш (Ctrl+C, Alt+Tab и т.д.)
- Ввод текста с настраиваемыми задержками
Установка
pnpm add @horuzhenko/guac-adapterИспользование
Базовое подключение
import { GuacAdapter } from '@horuzhenko/guac-adapter';
import { ConnectParams } from '@horuzhenko/protocol';
const adapter = new GuacAdapter();
const connectParams: ConnectParams = {
auth: {
baseUrl: 'http://192.168.2.109:8080/guacamole',
token: 'your-auth-token'
},
display: {
width: 1024,
height: 768,
dpi: 96
}
};
// Подключение
const sessionInfo = await adapter.connect(connectParams);
console.log('Сессия создана:', sessionInfo.id);
// Ожидание готовности соединения
await new Promise(resolve => setTimeout(resolve, 5000));
// Создание скриншота
const screenshot = await adapter.screenshot(sessionInfo.id, {
format: 'png',
quality: 80
});
// Сохранение скриншота
const fs = require('fs');
const imageBuffer = Buffer.from(screenshot.imageBase64, 'base64');
fs.writeFileSync('screenshot.png', imageBuffer);
// Интерактивный ввод
console.log('Демонстрация интерактивного ввода...');
// Движение мыши
await adapter.move(sessionInfo.id, { x: 100, y: 100 });
// Клик левой кнопкой
await adapter.click(sessionInfo.id, { x: 100, y: 100, button: 'left' });
// Двойной клик
await adapter.click(sessionInfo.id, { x: 100, y: 100, button: 'left', count: 2 });
// Комбинация клавиш (Ctrl+Alt+T для открытия терминала)
await adapter.keyCombo(sessionInfo.id, {
keys: ['Ctrl', 'Alt', 't'],
pressDelayMs: 100
});
// Ввод текста
await adapter.typeText(sessionInfo.id, {
text: 'echo "Hello World!"',
perCharDelayMs: 50
});
// Нажатие Enter
await adapter.keyCombo(sessionInfo.id, { keys: ['Return'] });
// Прокрутка
await adapter.scroll(sessionInfo.id, { x: 400, y: 300, deltaY: -240 });
// Отключение
await adapter.disconnect(sessionInfo.id);Создание скриншотов
// PNG скриншот
const pngScreenshot = await adapter.screenshot(sessionId, {
format: 'png'
});
// WebP скриншот с настройкой качества
const webpScreenshot = await adapter.screenshot(sessionId, {
format: 'webp',
quality: 70
});API
GuacAdapter
connect(params: ConnectParams): Promise<SessionInfo>
Создает новое подключение к удаленному рабочему столу.
Параметры:
params.auth.baseUrl- URL Guacamole сервераparams.auth.token- Токен аутентификацииparams.display- Настройки дисплея (опционально)
Возвращает: Информацию о созданной сессии
screenshot(sessionId: string, options?): Promise<Screenshot>
Создает скриншот удаленного рабочего стола.
Параметры:
sessionId- Идентификатор сессииoptions.format- Формат изображения ('png' | 'webp')options.quality- Качество для WebP (1-100)
Возвращает: Объект скриншота с base64 данными
move(sessionId: string, move: MouseMove): Promise<void>
Перемещает курсор мыши в указанные координаты.
Параметры:
sessionId- Идентификатор сессииmove.x- Координата Xmove.y- Координата Y
click(sessionId: string, click: MouseClick): Promise<void>
Выполняет клик мыши в указанных координатах.
Параметры:
sessionId- Идентификатор сессииclick.x- Координата Xclick.y- Координата Yclick.button- Кнопка мыши ('left' | 'right' | 'middle')click.count- Количество кликов (опционально, по умолчанию 1)
scroll(sessionId: string, scroll: Scroll): Promise<void>
Выполняет прокрутку в указанных координатах.
Параметры:
sessionId- Идентификатор сессииscroll.x- Координата Xscroll.y- Координата Yscroll.deltaY- Величина прокрутки (положительная - вниз, отрицательная - вверх)
keyCombo(sessionId: string, combo: KeyCombo): Promise<void>
Выполняет комбинацию клавиш.
Параметры:
sessionId- Идентификатор сессииcombo.keys- Массив клавиш (['Ctrl', 'c'], ['Alt', 'Tab'])combo.pressDelayMs- Задержка между нажатиями (опционально)
typeText(sessionId: string, input: TypeText): Promise<void>
Вводит текст символ за символом.
Параметры:
sessionId- Идентификатор сессииinput.text- Текст для вводаinput.perCharDelayMs- Задержка между символами (опционально)
clipboardSet(sessionId: string, data: ClipboardSet): Promise<void>
Записывает текстовые данные в буфер обмена удаленной машины.
Параметры:
sessionId- Идентификатор сессииdata.text- Текст для записи в буфер обменаdata.mime- MIME-тип (по умолчанию 'text/plain')
Важно: Поддерживается передача только текстовых данных. Перенос файлов через буфер обмена не реализован. Стабильность синхронизации буфера обмена сильно зависит от используемого протокола (RDP работает надежнее, VNC имеет ограничения) и настроек сервера Guacamole. Возможны проблемы с кодировками при использовании VNC, так как стандарт не определяет передачу UTF-8.
clipboardGet(sessionId: string, query?: ClipboardGet): Promise<ClipboardGet>
Читает текстовые данные из буфера обмена удаленной машины.
Параметры:
sessionId- Идентификатор сессииquery.selection- Тип буфера ('CLIPBOARD' или 'PRIMARY', по умолчанию 'CLIPBOARD')
Возвращает: Объект с полями text, mime, selection
disconnect(sessionId: string): Promise<void>
Отключает сессию и освобождает ресурсы.
Работа с клавиатурой и модификаторами
Клавиши-модификаторы
Строковые псевдонимы Meta, Cmd, Win, Windows, Command преобразуются в один и тот же keysym Super_L. Guacamole-сервер и удаленная ОС сами решают, как его интерпретировать:
- На macOS: интерпретируется как ⌘ (Command)
- На Windows: интерпретируется как Win (клавиша Windows)
- На Linux: интерпретируется как Super
Важное предупреждение
⚠️ Операционная система или браузер, на которых запущен клиентский код, могут перехватывать системные комбинации клавиш (например, Alt+Tab, Cmd+Q, Ctrl+Alt+Delete). Такие комбинации могут не дойти до удаленной машины. Это является ограничением окружения, а не адаптера.
Примеры проблемных комбинаций:
Alt+Tab- переключение окон в локальной ОСCmd+Q/Alt+F4- закрытие приложенийCtrl+Alt+Delete- системные функцииWin+L- блокировка экрана Windows
Архитектура
Адаптер работает по следующей схеме:
- Аутентификация - подключение к Guacamole REST API
- WebSocket соединение - установка связи с guacd
- Протокол Guacamole - обмен инструкциями с сервером
- Canvas рендеринг - отрисовка графических команд в памяти
- Скриншоты - извлечение изображений из canvas
Требования
- Node.js >= 18.0.0
- Запущенный Apache Guacamole сервер
- Доступ к guacd (обычно порт 4822)
Тестирование
Базовые тесты
pnpm testИнтеграционные тесты
Для запуска интеграционных тестов нужен запущенный Guacamole сервер:
INTEGRATION_TESTS=true pnpm testИнтеграционные тесты:
- Подключаются к реальному Guacamole серверу
- Создают скриншоты и сохраняют их в файлы
- Проверяют полный цикл работы адаптера
Отладка
Адаптер выводит отладочную информацию в консоль с префиксом [DEBUG]. Для продакшена эти логи можно отключить.
Ограничения
- Поддерживается только VNC протокол (в текущей версии)
- Требуется предварительная настройка Guacamole сервера
- Canvas рендеринг работает только в Node.js среде
Разработка
# Сборка
pnpm build
# Тесты
pnpm test
# Разработка с автоперезагрузкой
pnpm dev