Book padel courts on racket.id. Use when: (1) User wants to book a padel court, (2) User mentions 'падел', 'padel', 'корт', 'racket.id', 'Blue Padel', (3) User asks about court availability or prices. Handles 90/120 min slots, multiple courts, and payment flow.
Book padel courts at racket.id with browser automation.
⛔ ЗАПРЕЩЕНО: "Нашёл один вариант — хватит"
⛔ ЗАПРЕЩЕНО: "Учитывая время, завершу поиск"
⛔ ЗАПРЕЩЕНО: "Уже есть хороший результат"
⛔ ЗАПРЕЩЕНО: Останавливаться раньше времени
✅ ПРОВЕРЬ ВСЕ 4 КЛУБА (или отметь "не открыто")
✅ ПРОВЕРЬ ВСЕ ДАТЫ из запроса
✅ СОБЕРИ ВСЕ СЛОТЫ для каждого клуба
Один вариант ≠ задача выполнена. Продолжай пока ВСЁ не проверено.
После выбора даты в календаре — ПРОВЕРЬ что выбранная дата соответствует запросу:
⚠️ Частая ошибка: путать день недели и число. "Четверг 6 февраля" невозможно если 6 февраля = пятница!
❌ ЗАПРЕЩЕНО: puppeteer, playwright, selenium, любые скрипты
✅ ТОЛЬКО: browser tool с profile="openclaw"
sessions_spawn({
task: "...",
model: "anthropic/claude-sonnet-4-5", // Sonnet для этого скилла (задача механическая с парсером)
label: "padel-booking"
})
НЕ НУЖНО кликать на каждый слот! Используй автоматический парсер.
racket-bitmask-parser.pypython3 ~/clawd/scripts/racket-bitmask-parser.py screenshot.png \
--duration 120 \ # минуты (по умолчанию 120)
--courts 2 \ # минимум кортов (по умолчанию 1)
--start-time 08:00 # время первого слота (по умолчанию 08:00)
--pretty # красивый JSON вывод
Как парсер работает:
Результат парсера (JSON):
{
"windows": [
{"start": "12:00", "end": "14:00", "courts": [1,2,5,6], "courtCount": 4},
{"start": "14:00", "end": "16:00", "courts": [2,3,5,6], "courtCount": 4}
],
"grid": {"rows": 8, "cols": 5, "totalSlots": 32},
"slots": {
"12:00": {"mask": 51, "available": [1,2,5,6], "binaryMask": "00110011"}
}
}
1. Открыть racket.id/booking
2. Выбрать дату
3. ДЛЯ КАЖДОГО КЛУБА:
a. Кликнуть на клуб (раскрыть сетку)
b. Сделать screenshot (browser screenshot)
c. Сохранить: cp ~/.openclaw/media/browser/XXX.png ~/clawd/club-N.png
d. Парсить: python3 ~/clawd/scripts/racket-bitmask-parser.py club-N.png --duration 120 --courts N
e. Кликнуть на клуб СНОВА (свернуть!) ← ВАЖНО!
f. Перейти к следующему клубу
4. Собрать результаты всех клубов
⚠️ ВАЖНО: Перед раскрытием следующего клуба — СВЕРНИ текущий! Иначе на скриншоте будут два клуба и парсер смешает данные.
Время выполнения: ~0.2-0.3 сек на скриншот (вместо минут кликов)
❌ screenshot — только для отладки ошибок
✅ snapshot — для навигации и кликов (легче, быстрее)
Правило: используй screenshot ТОЛЬКО если:
В остальных случаях — snapshot достаточно.
browser({ action: "navigate", profile: "openclaw", targetUrl: "https://racket.id/booking" })
browser({ action: "snapshot", profile: "openclaw", targetId: "..." })
browser({ action: "screenshot", profile: "openclaw", targetId: "..." })
browser({ action: "act", profile: "openclaw", targetId: "...", request: { kind: "click", ref: "e123" } })
browser({ action: "act", profile: "openclaw", targetId: "...", request: { kind: "type", ref: "e123", text: "cancel" } })
targetId — получаешь из первого navigate/screenshot, используй во всех последующих вызовах.
browser({ action: "navigate", profile: "openclaw", targetUrl: "https://racket.id/booking" })
Сохрани targetId из ответа!
browser({ action: "snapshot", profile: "openclaw", targetId: "..." })
В snapshot ищи дату в формате:
generic: "8" + generic: "Лют" = 8 февраляВ snapshot ищи: generic: "Blue Padel Kourts"
Кликни на него — появятся слоты времени.
Ищи слот с [cursor=pointer] и нужным временем (например generic: "15:00").
Кликни на него.
Внизу появится панель. Ищи: generic: "Вибрати корти" [cursor=pointer]
Кликни.
Откроется modal. Один корт уже выбран (показан в заголовке, например "Court 7"). Для ОДНОГО корта — сразу "Продовжити".
Для нескольких кортов — ИСПОЛЬЗУЙ ЧЕКБОКСЫ:
В модале есть список всех кортов. Каждый корт имеет:
Алгоритм добавления кортов:
checkbox или generic рядом с "Court N"Пример refs чекбоксов (могут меняться):
⚠️ ВАЖНО: выбирай СОСЕДНИЕ корты!
Если соседние недоступны — только тогда бери через один.
Ищи: generic: "Продовжити" [cursor=pointer]
Кликни. Откроется страница с ценой.
Ищи: generic: "Забронювати" [cursor=pointer]
Кликни.
Жди зелёную галочку: "Дякуємо за ваше бронювання!"
"Переглянути матч" или "Переглянути подію"browser({ action: "navigate", profile: "openclaw", targetUrl: "https://racket.id/" })
В snapshot ищи нужное бронирование по дате/времени. Кликни на него.
Ищи красную кнопку: "Скасувати бронювання" [cursor=pointer]
Кликни.
Появится popup с полем ввода.
browser({ action: "act", ..., request: { kind: "type", ref: "...", text: "cancel" } })
Кликни: "Підтвердити" [cursor=pointer]
1. Длительность: 120 МИНУТ (если не указано иное)
2. Использовать БЫСТРЫЙ ПОИСК ПО ШАРИКАМ (см. выше)
3. Анализировать шарики по screenshot (не кликать на каждый слот!)
4. Для каждого проверенного слота: кол-во кортов + какие именно + соседние?
5. Проверить ВСЕ клубы из списка
6. Ответ ТОЛЬКО в указанном формате (никаких вопросов/комментариев)
ТЫ НЕ МОЖЕШЬ РЕШИТЬ ЧТО "ДОСТАТОЧНО"!
❌ ЗАПРЕЩЕНО: "Нашёл один вариант — хватит"
❌ ЗАПРЕЩЕНО: "Учитывая ограничения по времени, завершу"
❌ ЗАПРЕЩЕНО: "Уже есть хороший результат"
❌ ЗАПРЕЩЕНО: Оптимизировать свою работу за счёт полноты
✅ ОБЯЗАТЕЛЬНО: Проверить ВСЕ клубы из списка
✅ ОБЯЗАТЕЛЬНО: Проверить ВСЕ запрошенные даты
✅ ОБЯЗАТЕЛЬНО: Собрать ВСЕ доступные слоты
Задача НЕ ВЫПОЛНЕНА пока:
Один найденный вариант — это НЕ причина останавливаться. Пользователь просит ПОЛНУЮ картину, чтобы выбрать лучший вариант.
Если думаешь "можно остановиться" — НЕТ, НЕЛЬЗЯ. Продолжай.
Если клуб показывает "Бронювання на цей день ще не відкрито" — отметь это.
Если пользователь просит "около 15:00" — покажи ВСЕ слоты:
Компактный формат "лента сигналов" — TOP-3 окна на клуб/день.
[1–2][5–6] вместо "Court 1,2,5,6" (группировать соседние)[3–8] если все подрядЧт, 5 фев — 3 корта на 2:00
📍 Rackets Pro Qta. da Marinha
1. 12:00–14:00 → ✅ 4к [1–2][5–6]
2. 12:30–14:30 → ✅ 4к [1–2][5–6]
3. 13:00–15:00 → ✅ 4к [2–3][5–6]
4. 13:30–15:30 → ✅ 4к [2–3][5–6]
5. 14:00–16:00 → ✅ 4к [2–3][5–6]
...
📍 Blue Padel Kourts
1. 12:00–14:00 → ✅ 6к [3–8]
📍 Zone Pro Padel
⏳ Бронирование не открыто
НЕ делай отдельные spawn'ы для поиска и бронирования — это трата токенов.
Правильный flow:
Агент уже на странице с нужной датой — не нужно заново открывать!
Sonnet может не прочитать skill или не дочитать до конца. Критические правила ДУБЛИРУЙ в task prompt!
sessions_spawn({
task: `Найди ВСЕ доступные слоты на [ДАТА], нужно [N] кортов на 2 часа.
## Алгоритм (используй bitmask parser!):
1. browser navigate → racket.id/booking
2. Выбери дату [ДАТА]
3. Для КАЖДОГО клуба:
- Кликни на клуб (раскрыть)
- browser screenshot → сохрани в ~/clawd/club-X.png
- Парсь: python3 ~/clawd/scripts/racket-bitmask-parser.py club-X.png --duration 120 --courts [N] --pretty
- Кликни на клуб СНОВА (свернуть!) ← ВАЖНО перед следующим!
4. Собери результаты
## Клубы для проверки:
- Blue Padel Kourts
- Rackets Pro Qta. da Marinha
- Zone Pro Padel
- Carcavelos Tenis & Padel
## Формат ответа:
📍 Club Name (дата):
• 12:00-14:00 → 4 корта (1,2,5,6)
• 14:00-16:00 → 3 корта (2,3,5)
Используй browser tool с profile="openclaw".`,
model: "anthropic/claude-sonnet-4-5", // Sonnet для этого скилла
label: "padel-search"
})
sessions_spawn({
task: `Забронировать 1 корт в Blue Padel на 8 февраля, 15:00.
ЧИТАЙ SKILL.md: ~/.openclaw/skills/racket-id-booking/SKILL.md
Используй ТОЛЬКО browser tool с profile="openclaw". НЕ пиши скрипты!
После бронирования отправь ссылку.`,
model: "anthropic/claude-sonnet-4-5",
label: "padel-book"
})
sessions_spawn({
task: `Забронировать 3 корта в Blue Padel на 8 февраля, 15:00, 120 мин.
ЧИТАЙ SKILL.md: ~/.openclaw/skills/racket-id-booking/SKILL.md
Используй ТОЛЬКО browser tool. Для нескольких кортов — чекбокс + popup "Додати".
После бронирования отправь ссылку.`,
model: "anthropic/claude-sonnet-4-5",
label: "padel-book-3"
})
sessions_spawn({
task: `Отменить бронирование на 8 февраля в Blue Padel.
ЧИТАЙ SKILL.md: ~/.openclaw/skills/racket-id-booking/SKILL.md
Используй ТОЛЬКО browser tool.`,
model: "anthropic/claude-sonnet-4-5",
label: "padel-cancel"
})
После КАЖДОГО действия проверяй условие успеха. Если не выполнено — СТОП, исправь, повтори.
Действие: navigate на https://racket.id/booking
Условие успеха:
targetId полученДействие: Клик на нужную дату Условие успеха:
Действие: Клик на "Blue Padel Kourts" Условие успеха:
[cursor=pointer] или серые (занятые)
Если провал:Действие: Перебор каждого слота Условие успеха для КАЖДОГО слота:
КРИТИЧЕСКИ ВАЖНО:
⛔ ЗАПРЕЩЕНО: "проверил несколько слотов"
✅ ОБЯЗАТЕЛЬНО: проверить КАЖДЫЙ слот с 08:00 до 21:00
Валидация полноты:
Условие успеха:
□ Все клубы проверены (или помечены "не открыто")
□ Все слоты (08:00-21:00) для каждого клуба проверены
□ Для каждого слота: время + кол-во кортов + номера кортов + цена
□ Длительность = 120 минут (если не указано иное)
□ Указано какие корты СОСЕДНИЕ
Если хоть один пункт не выполнен:
⛔ НЕ ОТПРАВЛЯТЬ РЕЗУЛЬТАТ
🔄 Вернуться и заполнить пробелы
Условие успеха:
Условие успеха:
Условие успеха:
Валидация соседства:
// Допустимые комбинации (примеры):
✅ [1,2], [2,3], [3,4], [4,5], [5,6], [6,7], [7,8]
✅ [1,2,3], [2,3,4], [3,4,5], [4,5,6], [5,6,7], [6,7,8]
❌ [1,3], [2,4], [1,2,4], [3,5,6]
⛔ ОБЯЗАТЕЛЬНАЯ ПРОВЕРКА ПЕРЕД CHECKOUT!
Условие успеха:
Если длительность НЕ совпадает:
⛔ НЕ ПРОДОЛЖАТЬ НА CHECKOUT!
🔄 Вернуться назад, добавить недостающие слоты
🔄 Для 120 мин нужно 4 слота по 30 мин
🔄 Для 90 мин нужно 3 слота по 30 мин
Проверка:
Правило: Если пользователь просит "2 часа" или не указал длительность → СТРОГО 120 минут. Никаких "почти 2 часа" или "1.5 часа тоже норм" — это ПРОВАЛ задачи.
Условие успеха:
Условие успеха:
Условие успеха:
После каждого шага фиксируй:
[ШАГ N] Действие: ...
[РЕЗУЛЬТАТ] ✅ Успех / ❌ Провал
[ДАННЫЕ] Что получено (время, корты, цена...)
[СЛЕДУЮЩИЙ] Переход к шагу N+1 / Повтор шага N
Пример:
[ШАГ 3] Раскрытие Blue Padel Kourts
[РЕЗУЛЬТАТ] ✅ Успех — появились 14 временных слотов
[ДАННЫЕ] Слоты: 08:00-21:00, шаг 30 мин
[СЛЕДУЮЩИЙ] Переход к шагу 4 — сбор данных по слотам
[ШАГ 4.1] Проверка слота 08:00-10:00
[РЕЗУЛЬТАТ] ✅ Успех
[ДАННЫЕ] 6 кортов: Court 1,2,3,4,5,6 (все соседние), 264 EUR
[СЛЕДУЮЩИЙ] Слот 08:30-10:30
[ШАГ 4.2] Проверка слота 08:30-10:30
[РЕЗУЛЬТАТ] ✅ Успех
[ДАННЫЕ] 5 кортов: Court 2,3,4,5,6 (все соседние), 220 EUR
...
ЕСЛИ шаг провален:
1. Логировать: "[ПРОВАЛ] Шаг N — причина"
2. Определить причину (element not found? timeout? wrong state?)
3. Корректирующее действие:
- Element not found → snapshot, найти правильный ref
- Timeout → подождать 2 сек, повторить
- Wrong state → вернуться на предыдущий шаг
4. Повторить шаг (максимум 3 попытки)
5. Если 3 провала подряд:
- screenshot для диагностики
- Сообщить пользователю с контекстом ошибки
- НЕ продолжать с неполными данными!
❌ НИКОГДА не отправлять неполные результаты поиска
❌ НИКОГДА не говорить "проверил несколько слотов"
❌ НИКОГДА не пропускать валидацию
❌ НИКОГДА не продолжать если шаг провален
❌ НИКОГДА не угадывать данные (только то что видно в snapshot)
UI racket.id показывает ДИАПАЗОН времени. Каждый слот = 30 минут.
Для 120 минут (2 часа):
Проверка: В выделенном окне должно быть 4 слота (17:00, 17:30, 18:00, 18:30 → конец 19:00)
Если UI не даёт выбрать 120 мин:
НИКОГДА не бронируй без подтверждения пользователя! Сначала покажи: дата, время, корты, цена. Жди "да/ок".
Хорошее бронирование (1 корт):
Бронирование 3 кортов:
Если больше — ищи где тратишь лишние вызовы.
# Парсить скриншот, найти окна по 2 часа с минимум 2 кортами
python3 ~/clawd/scripts/racket-bitmask-parser.py screenshot.png --duration 120 --courts 2 --pretty
# Параметры:
# --duration N минуты (по умолчанию 120)
# --courts N минимум одинаковых кортов (по умолчанию 1)
# --start-time время первого слота (по умолчанию 08:00)
# --pretty форматированный JSON
# --debug показать детали парсинга
Зависимости: pip install opencv-python numpy
# Проверить слоты
node ~/clawd/scripts/racket-id-book.js slots --club "Blue Padel" --date 2026-02-05
# Dry-run (без реального бронирования)
node ~/clawd/scripts/racket-id-book.js book --club "Blue Padel" --date 2026-02-05 --time 18:00 --dry-run
# Реальное бронирование
node ~/clawd/scripts/racket-id-book.js book --club "Blue Padel" --date 2026-02-05 --time 18:00 --court 6
Требования:
Файлы:
scripts/racket-bitmask-parser.py — 🆕 быстрый парсер скриншотов (0.2 сек)scripts/racket-id-book.js — браузерная автоматизацияscripts/racket-id-api.js — REST API (ограничен Firestore rules)~/.secrets/racket-id-tokens.json — Firebase токены