Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
247 changes: 247 additions & 0 deletions cli-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3100,6 +3100,253 @@
"modulePath": "booking/search.js",
"sourceFile": "booking/search.js"
},
{
"site": "bookmyshow",
"name": "cities",
"description": "List available cities and regions on BookMyShow",
"access": "read",
"domain": "in.bookmyshow.com",
"strategy": "cookie",
"browser": true,
"args": [
{
"name": "limit",
"type": "int",
"default": 50,
"required": false,
"help": "Max rows to return (1-300)"
}
],
"columns": [
"rank",
"code",
"name",
"region",
"isTopCity",
"sourceUrl",
"fetchedAt",
"url"
],
"type": "js",
"modulePath": "bookmyshow/cities.js",
"sourceFile": "bookmyshow/cities.js",
"navigateBefore": "https://in.bookmyshow.com"
},
{
"site": "bookmyshow",
"name": "events",
"description": "List live events (concerts, comedy, sports, plays) in a city on BookMyShow",
"access": "read",
"domain": "in.bookmyshow.com",
"strategy": "cookie",
"browser": true,
"args": [
{
"name": "city",
"type": "string",
"required": true,
"positional": true,
"help": "City slug (e.g. mumbai, delhi-ncr, bengaluru)"
},
{
"name": "category",
"type": "string",
"default": "",
"required": false,
"help": "Filter by category (e.g. music, comedy, sports, plays, workshops)"
},
{
"name": "limit",
"type": "int",
"default": 20,
"required": false,
"help": "Max rows to return (1-100)"
}
],
"columns": [
"rank",
"eventCode",
"title",
"category",
"venue",
"date",
"price",
"currency",
"language",
"sourceUrl",
"fetchedAt",
"url"
],
"type": "js",
"modulePath": "bookmyshow/events.js",
"sourceFile": "bookmyshow/events.js",
"navigateBefore": "https://in.bookmyshow.com"
},
{
"site": "bookmyshow",
"name": "movie",
"description": "Get movie details by event code from BookMyShow",
"access": "read",
"domain": "in.bookmyshow.com",
"strategy": "cookie",
"browser": true,
"args": [
{
"name": "code",
"type": "string",
"required": true,
"positional": true,
"help": "Movie event code (e.g. ET00412327)"
},
{
"name": "city",
"type": "string",
"default": "mumbai",
"required": false,
"help": "City slug for regional data (e.g. mumbai, delhi-ncr)"
}
],
"columns": [
"field",
"value"
],
"type": "js",
"modulePath": "bookmyshow/movie.js",
"sourceFile": "bookmyshow/movie.js",
"navigateBefore": "https://in.bookmyshow.com"
},
{
"site": "bookmyshow",
"name": "movies",
"description": "List currently showing movies in a city on BookMyShow",
"access": "read",
"domain": "in.bookmyshow.com",
"strategy": "cookie",
"browser": true,
"args": [
{
"name": "city",
"type": "string",
"required": true,
"positional": true,
"help": "City slug (e.g. mumbai, delhi-ncr, bengaluru)"
},
{
"name": "limit",
"type": "int",
"default": 20,
"required": false,
"help": "Max rows to return (1-100)"
}
],
"columns": [
"rank",
"eventCode",
"title",
"language",
"genre",
"certification",
"rating",
"votes",
"releaseDate",
"sourceUrl",
"fetchedAt",
"url"
],
"type": "js",
"modulePath": "bookmyshow/movies.js",
"sourceFile": "bookmyshow/movies.js",
"navigateBefore": "https://in.bookmyshow.com"
},
{
"site": "bookmyshow",
"name": "search",
"description": "Search movies, events, and venues on BookMyShow",
"access": "read",
"domain": "in.bookmyshow.com",
"strategy": "cookie",
"browser": true,
"args": [
{
"name": "query",
"type": "string",
"required": true,
"positional": true,
"help": "Search term (movie title, event name, venue, etc.)"
},
{
"name": "city",
"type": "string",
"default": "mumbai",
"required": false,
"help": "City slug for regional results (e.g. mumbai, delhi-ncr)"
},
{
"name": "limit",
"type": "int",
"default": 20,
"required": false,
"help": "Max rows to return (1-50)"
}
],
"columns": [
"rank",
"title",
"category",
"language",
"genre",
"rating",
"releaseDate",
"sourceUrl",
"fetchedAt",
"url"
],
"type": "js",
"modulePath": "bookmyshow/search.js",
"sourceFile": "bookmyshow/search.js",
"navigateBefore": "https://in.bookmyshow.com"
},
{
"site": "bookmyshow",
"name": "upcoming",
"description": "List upcoming movies in a city on BookMyShow",
"access": "read",
"domain": "in.bookmyshow.com",
"strategy": "cookie",
"browser": true,
"args": [
{
"name": "city",
"type": "string",
"required": true,
"positional": true,
"help": "City slug (e.g. mumbai, delhi-ncr, bengaluru)"
},
{
"name": "limit",
"type": "int",
"default": 20,
"required": false,
"help": "Max rows to return (1-100)"
}
],
"columns": [
"rank",
"eventCode",
"title",
"language",
"genre",
"certification",
"releaseDate",
"sourceUrl",
"fetchedAt",
"url"
],
"type": "js",
"modulePath": "bookmyshow/upcoming.js",
"sourceFile": "bookmyshow/upcoming.js",
"navigateBefore": "https://in.bookmyshow.com"
},
{
"site": "brave",
"name": "search",
Expand Down
40 changes: 40 additions & 0 deletions clis/bookmyshow/STRATEGY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# BookMyShow Adapter β€” Strategy Note

## All Commands

Strategy: COOKIE (PAGE_FETCH)
Contract: internal-unstable
Evidence:
- observed request/state: BookMyShow exposes internal JSON API endpoints at
`in.bookmyshow.com/api/movies-data/now-showing-movies/{city}`,
`in.bookmyshow.com/api/movies-data/upcoming-movies/{city}`,
`in.bookmyshow.com/api/events-data/events/{city}`,
`in.bookmyshow.com/api/search/suggest`,
`in.bookmyshow.com/api/home/regions`,
`in.bookmyshow.com/api/movies-data/movie-details/{code}/{city}`.
- auth source: None β€” endpoints are unauthenticated, but protected by
Cloudflare JS challenge. Browser session provides cf_clearance cookies.
- replay result: 200 + JSON containing target movie/event/city data when
fetched from browser context with valid Cloudflare session.

Why COOKIE (PAGE_FETCH):
- PUBLIC_API: Ruled out β€” Cloudflare returns 403 to bare Node fetch().
The JS challenge requires a real browser to solve the turnstile, then
subsequent requests within that browser context pass through.
- COOKIE via page.fetchJson(): All API calls run inside the browser page
via webcmd's page.fetchJson(), which carries credentials: 'include'.
The browser's cf_clearance cookie satisfies Cloudflare automatically.
No login or user auth is needed β€” just a live browser session.
- INTERCEPT: Not needed β€” no request signing or HMAC. The APIs accept
plain GET requests once Cloudflare is satisfied.
- UI_SELECTOR/DOM_STATE: Would require scraping DOM instead of clean JSON.
The JSON endpoints exist and work fine from browser context.

Risk:
- drift risk: MEDIUM β€” These are internal endpoints without a public contract.
BookMyShow can change response shapes, add auth, or remove endpoints without
notice. The adapter uses defensive response parsing (multiple fallback paths
for field names) to mitigate this.
- verification fixture: Adapter handles multiple known response shapes
(moviesData.BookMyShow.arrEvents, moviesData.arrEvents, arrEvents, etc.)
to absorb wrapper changes without breakage.
Loading