← Back to Skills Marketplace
producedbysavant

Studio Booking Manager

by SAVANT · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ✓ Security Clean
57
Downloads
0
Stars
0
Active Installs
1
Versions
Install in OpenClaw
/install studio-booking
Description
Automates recording studio bookings via Telegram, managing slots, payments, cross-selling, notifications, and client history.
README (SKILL.md)

Studio Booking

Скилл для автоматизации бронирования студии звукозаписи через Telegram-бота.

Когда использовать

  • Пользователь хочет забронировать студию (дата, время, длительность)
  • Администратор управляет бронями (создание, отмена, перенос)
  • Клиент спрашивает свободные слоты, цены, услуги
  • Нужно сгенерировать ссылку на оплату через TelegaPay
  • Требуется крос-сейл дополнительных услуг (звукорежиссёр, мастеринг, сессионный музыкант)
  • Клиент спрашивает статус своей брони или историю посещений

Инструкции

1. Квалификация лида

Перед началом бронирования определи тип клиента:

Новый клиент:

  • Уточни: тип проекта (запись трека, сведение, мастеринг, репетиция)
  • Бюджет и предпочтительное время
  • Запроси контакт для подтверждения (если не указан)
  • Предложи экскурсию по студии перед бронированием

Постоянный клиент:

  • Приветствуй по имени, напомни о прошлом проекте
  • Спроси, нужна ли та же конфигурация (микрофоны, оборудование)
  • Предложи скидку за лояльность (если >5 броней)

2. Проверка слотов

Используй следующий SQL-шаблон для проверки доступности слота:

SELECT s.id, s.start_time, s.end_time, s.price
FROM slots s
WHERE s.date = :date
  AND s.is_available = 1
  AND s.id NOT IN (
    SELECT b.slot_id FROM bookings b
    WHERE b.status IN ('pending', 'confirmed', 'paid')
      AND b.cancelled_at IS NULL
  )
  AND (
    CAST(strftime('%s', s.start_time) AS INTEGER) >= CAST(strftime('%s', :time_from) AS INTEGER)
  )
ORDER BY s.start_time;

Параметры:

  • :date — дата в формате YYYY-MM-DD
  • :time_from — минимальное время начала (например 10:00)

Если слотов нет — предложи соседние даты (±3 дня).

3. Создание бронирования

SAGA-паттерн из 5 шагов:

STEPS = [
    ("validate_slot", lambda: check_slot_available(db, slot_id)),
    ("create_booking", lambda: create_booking_record(db, user_id, slot_id, service_id)),
    ("hold_payment", lambda: hold_invoice(payment, booking_id, amount)),
    ("send_confirmation", lambda: send_booking_notification(bot, chat_id, booking_id)),
    ("notify_admin", lambda: notify_admin_new_booking(bot, admin_chat_id, booking_id)),
]

COMPENSATIONS = {
    "validate_slot": None,
    "create_booking": lambda: delete_booking_record(db, booking_id),
    "hold_payment": lambda: cancel_invoice(payment, invoice_id),
    "send_confirmation": lambda: True,
    "notify_admin": lambda: True,
}

Каждый шаг должен иметь timeout 30 секунд. Компенсации запускаются в обратном порядке при фейле любого шага.

4. TelegaPay — генерация ссылки на оплату

import hashlib
import hmac
import json
from urllib.parse import urlencode


def generate_telegapay_link(
    amount: int,
    order_id: str,
    description: str,
    secret_key: str,
    shop_id: str,
    callback_url: str,
    user_phone: str = "",
    expires_in: int = 3600,
) -> str:
    payload = {
        "amount": str(amount),
        "order_id": order_id,
        "description": description,
        "shop_id": shop_id,
        "callback_url": callback_url,
        "expires_in": str(expires_in),
    }
    if user_phone:
        payload["phone"] = user_phone

    sign_str = json.dumps(payload, separators=(",", ":"), sort_keys=True)
    signature = hmac.new(
        secret_key.encode(), sign_str.encode(), hashlib.sha256
    ).hexdigest()
    payload["signature"] = signature
    return f"https://telegapay.com/pay?{urlencode(payload)}"

5. Крос-сейл матрица

Предлагай дополнительные услуги на основе выбранной основной:

Основная услуга Крос-сейл 1 Крос-сейл 2 Крос-сейл 3
Запись вокала Сведение (+40%) Мастеринг (+25%) Бэк-вокалист (+60%)
Запись инструмента Сведение (+40%) Студийный гитарист (+50%) Рейк-микрофон (+15%)
Сведение Мастеринг (+25%) Стем-рендер (+10%) Контрольный прослушивание (+5%)
Мастеринг Винтаж-пресс (+80%) Продвинутый лимитер (+30%)
Репетиция Звукорежиссёр (+35%) Запись репетиции (+50%)

Процент — наценка к базовой стоимости.

6. Управление бронями

Отмена брони:

async def cancel_booking(db, booking_id: int, reason: str = "", refund: bool = False):
    booking = await db.fetch_one(
        "SELECT * FROM bookings WHERE id = ?", (booking_id,)
    )
    if not booking:
        raise ValueError("Booking not found")

    async with db.transaction():
        await db.execute(
            "UPDATE bookings SET status = 'cancelled', cancelled_at = datetime('now'), "
            "cancel_reason = ?, refunded = ? WHERE id = ?",
            (reason, int(refund), booking_id),
        )
        if refund and booking.get("paid_at"):
            await refund_telegapay(booking["invoice_id"], booking["amount"])

        await db.execute(
            "UPDATE slots SET is_available = 1 WHERE id = ?",
            (booking["slot_id"],),
        )

Календарь занятости:

async def get_occupancy_calendar(db, year: int, month: int) -> dict:
    """Возвращает словарь {день: количество броней} за месяц."""
    rows = await db.fetch_all(
        """SELECT CAST(strftime('%d', s.date) AS INTEGER) as day, COUNT(*) as count
           FROM bookings b
           JOIN slots s ON b.slot_id = s.id
           WHERE strftime('%Y-%m', s.date) = ?
             AND b.status IN ('confirmed', 'paid')
           GROUP BY day""",
        (f"{year:04d}-{month:02d}",),
    )
    return {row["day"]: row["count"] for row in rows}

7. Клиентский трекинг

История посещений:

SELECT b.id, s.date, s.start_time, s.end_time,
       sv.name as service, b.amount,
       b.status, b.created_at
FROM bookings b
JOIN slots s ON b.slot_id = s.id
JOIN services sv ON b.service_id = sv.id
WHERE b.user_id = :user_id
  AND b.status IN ('paid', 'confirmed')
ORDER BY s.date DESC, s.start_time DESC
LIMIT 20;

Статистика клиента:

async def client_stats(db, user_id: int) -> dict:
    row = await db.fetch_one(
        """SELECT COUNT(*) as total_bookings,
                  SUM(amount) as total_spent,
                  COUNT(DISTINCT strftime('%Y-%m', s.date)) as months_active,
                  MAX(s.date) as last_visit
           FROM bookings b
           JOIN slots s ON b.slot_id = s.id
           WHERE b.user_id = ? AND b.status = 'paid'""",
        (user_id,),
    )
    return dict(row) if row else {}

8. Уведомления

  • Клиенту за 2 часа: напоминание о брони
  • Клиенту через 1 час после брони: отзыв
  • Админу: новая бронь, отмена, просрочка оплаты
  • Клиенту через 1 день: предложение повторить (снарядить крос-сейл)

9. Обработка ошибок

Ситуация Действие
Слот занят в момент оплаты Предложить альтернативный слот, отменить инвойс
TelegaPay timeout Retry 3 раза с exponential backoff (1s, 3s, 9s)
Дупликат брони (user+slot+status) Вернуть существующую бронь, не создавать новую
Дата в прошлом Отказать с сообщением "Нельзя бронировать прошлое"
Минимальное время до слота \x3C2 часов — отказать, предложить следующий день

10. Стоимость и пакеты

PRICING_RULES = {
    "base_hourly": 2500_00,
    "min_booking": 2,
    "discounts": {
        "3_hours": 0.05,
        "5_hours": 0.10,
        "night_rate": 0.80,
        "weekend": 1.15,
        "loyalty_5plus": 0.10,
    },
    "extras": {
        "engineer": 800_00,
        "mixing": 3500_00,
        "mastering": 2000_00,
        "backup_copy": 500_00,
    },
}

11. Интеграция с Telegram-ботом

async def booking_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    action, *params = query.data.split(":")
    booking_flow = BookingCoordinator(db, payment, bot)

    match action:
        case "calendar":
            await booking_flow.show_calendar(query)
        case "select_date":
            await booking_flow.show_time_slots(query, params[0])
        case "select_time":
            await booking_flow.show_services(query, params[0])
        case "select_service":
            await booking_flow.show_extras(query, params[0], params[1])
        case "confirm":
            await booking_flow.run_saga(query, params)
        case "pay":
            await booking_flow.generate_payment(query, params[0])

Референсы

  • Документация TelegaPay: https://telegapay.com/docs
  • python-telegram-bot: https://docs.python-telegram-bot.org/
  • Формат времени: HH:MM в 24-часовом формате
  • Даты: YYYY-MM-DD (ISO 8601)
  • Цены: int, минимальная единица — копейка (1 рубль = 100)
  • Часовой пояс: Europe/Moscow (UTC+3, без DST)
Usage Guidance
Before installing, confirm the bot authenticates customers and admins, limits access to booking history and spending stats, shows a privacy notice before collecting contact data, and requires explicit confirmation for payment, cancellation, and refund actions.
Capability Assessment
Purpose & Capability
The booking, slot lookup, Telegram bot, TelegaPay payment-link, cancellation, refund, notification, client history, and cross-sell guidance all fit the stated recording-studio booking purpose.
Instruction Scope
The skill asks the agent to use contact details, booking history, spending statistics, and payment state; this is broad but visible and purpose-aligned rather than hidden or unrelated.
Install Mechanism
The artifact is a single Markdown skill file with no executable installer, dependency package, startup hook, or automatic setup behavior.
Credentials
Telegram and TelegaPay API use is expected for the workflow; the artifact does not request local credential stores, broad filesystem access, or unrelated environment data.
Persistence & Privilege
The examples mutate booking records, cancel invoices, and can trigger refunds, but those actions are part of the disclosed booking-management workflow and are not presented as stealth persistence or privilege escalation.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install studio-booking
  3. After installation, invoke the skill by name or use /studio-booking
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.0
Studio-booking v1.0.0 – initial release - Automates recording studio bookings via Telegram bot - Supports slot checking, reservation, cancellation, and rescheduling - Integrates TelegaPay for payment link generation and refund handling - Includes cross-sell matrix and loyalty discounts for clients - Provides booking management tools, occupancy calendar, and client history/statistics - Built-in notification and error-handling scenarios
Metadata
Slug studio-booking
Version 1.0.0
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 1
Frequently Asked Questions

What is Studio Booking Manager?

Automates recording studio bookings via Telegram, managing slots, payments, cross-selling, notifications, and client history. It is an AI Agent Skill for Claude Code / OpenClaw, with 57 downloads so far.

How do I install Studio Booking Manager?

Run "/install studio-booking" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Studio Booking Manager free?

Yes, Studio Booking Manager is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does Studio Booking Manager support?

Studio Booking Manager is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Studio Booking Manager?

It is built and maintained by SAVANT (@producedbysavant); the current version is v1.0.0.

💬 Comments