rates/backend/services/direct_profiles/guestline.py
jtricerolph e05054172f Add Rate Monitor app — Booking.com + direct booking engine competitor rates
Combines Booking.com Playwright scraper (from forecasting), direct booking
engine scraper (ported from laptop-archive/guestline-monitor), and Newbook
own-hotel rates into one focused tool. Four views: Bookability, Market View
(with price index badges + direct rate sub-rows), Direct Rates (per-competitor
room breakdown, min-stay flags, hotel config/discovery), Rate Analysis
(advance purchase curve, DOW chart, rate timeline, comparison table).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 12:06:30 +00:00

49 lines
2.1 KiB
Python

import re
from datetime import date, timedelta
from .base import BaseProfile
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Accept": "application/json",
}
class GuestlineProfile(BaseProfile):
name = "guestline"
label = "Guestline"
required_params = [
{"key": "hotel_id", "label": "Hotel ID", "help": "e.g. THREEWAYS — from the booking URL ?hotel= parameter"},
{"key": "collection_id", "label": "Collection ID", "help": "e.g. MT — the path segment before /availability in the booking URL"},
]
@classmethod
def detect(cls, url: str) -> dict | None:
# Matches: https://booking.eu.guestline.app/MT/availability?hotel=THREEWAYS
m = re.search(r'booking\.(?:eu\.)?guestline\.app/([^/?\s]+)/availability\?hotel=([^&\s]+)', url)
if m:
return {"collection_id": m.group(1), "hotel_id": m.group(2)}
return None
async def fetch_arrival_dates(self, client, params: dict) -> list[str]:
hotel_id = params["hotel_id"]
today = date.today()
url = f"https://booking.eu.guestline.app/api/availabilities/{hotel_id}/arrivals"
r = await client.get(url, params={
"month": today.month, "year": today.year,
"adults": 2, "children": 0, "count": 12,
}, headers=HEADERS, timeout=20)
r.raise_for_status()
return [a["date"] for a in r.json().get("arrivals", [])]
async def fetch_night_rates(self, client, params: dict, arrival: str, nights: int = 1) -> list[dict]:
hotel_id = params["hotel_id"]
collection_id = params.get("collection_id", "MT")
dep = (date.fromisoformat(arrival) + timedelta(days=nights)).isoformat()
url = f"https://booking.eu.guestline.app/api/availabilities/{collection_id}/{hotel_id}/enhanced"
r = await client.get(url, params={
"arrival": arrival, "departure": dep, "adults": 2, "children": 0,
}, headers=HEADERS, timeout=20)
if r.status_code == 404:
return []
r.raise_for_status()
return r.json().get("availabilities", {}).get("rooms", [])