Files
ticket-monitoring/.env.example
T
Aculix Technologies 608221fe18 feat: watch BookMyShow alongside District in one process
BookMyShow sits behind Cloudflare bot management that rejects curl and Node fetch
with 403 on the TLS fingerprint alone, so no header or cookie copying helps and a
proxy makes no difference. impit performs the request with a real Chrome
fingerprint; it ships musl and arm64 binaries, so the Alpine multi-arch image is
unaffected. BMS has no 204 either: a date that is not on sale returns 200 with no
showtimeWidgets key, so 'closed' is read from the payload.

Sites now live in src/providers/, each exposing check() and extract() and returning
one normalized session shape. State is namespaced per site, so each keeps its own
dedupe and failure tracking and neither can silence the other. Alert titles name the
site. Sessions without exact seat counts render without them, which BMS needs.

Old flat District variable names still work. CI now starts the built image and runs
a real check through both providers before publishing, since a broken native binary
only fails at runtime.
2026-08-26 17:50:56 +05:30

67 lines
4.6 KiB
Bash

# Copy to .env and fill in. Every value is read from the environment, so you can set
# these directly (Docker, systemd, CI) instead of using a file.
#
# Configure District, BookMyShow, or both. Both are watched in one process, each with
# its own dedupe and failure tracking, so one site breaking never silences the other.
# ── Shared ────────────────────────────────────────────────────────────────────
TARGET_DATE=2026-09-25 # the date you are waiting for (YYYY-MM-DD)
FORMAT_LABEL=IMAX # cosmetic: how the format is named in alerts
# Subscribe to this topic in the ntfy app. Treat it as a password: anyone who knows
# it can read your alerts and publish to you. Use a long random string.
NTFY_TOPIC=change-me-to-something-random
# Public ntfy.sh works from home connections. It rate-limits shared cloud egress
# IPs with HTTP 429, so point this at your own server when hosting in the cloud.
NTFY_URL=https://ntfy.sh
# NTFY_TOKEN=tk_... # only if your server (or topic) requires auth
# ── District (district.in) ────────────────────────────────────────────────────
# Leave DISTRICT_MOVIE_CODE unset to skip District entirely.
# Read these off the movie's page URL, e.g.
# district.in/movies/the-odyssey-movie-tickets-in-ahmedabad-MV187151?frmtid=y7EZNLXN5Y
DISTRICT_MOVIE_CODE=y7EZNLXN5Y # ?frmtid= — identifies movie + language
DISTRICT_CONTENT_ID=187151 # digits after MV
DISTRICT_CITY_KEY=ahmedabad # city slug in the path
DISTRICT_LAT=23.033938956712916 # any coordinates in that city; the API needs them
DISTRICT_LNG=72.57696301365426
DISTRICT_CINEMA_ID=1032362 # empty = watch every cinema in the city
DISTRICT_FORMAT_TAG=imax_2d # session tag that counts as a match
DISTRICT_FORMAT_MATCH=IMAX # or a screen-format substring; both empty = any show
DISTRICT_BOOKING_URL=https://www.district.in/movies/the-odyssey-movie-tickets-in-ahmedabad-MV187151?frmtid=y7EZNLXN5Y&fromdate=2026-09-25
# ── BookMyShow (in.bookmyshow.com) ────────────────────────────────────────────
# Leave BMS_EVENT_CODE unset to skip BookMyShow entirely.
# From the movie URL, e.g. in.bookmyshow.com/movies/ahmedabad/avengers-endgame-encore/ET00514163
BMS_EVENT_CODE=ET00514163 # the ET... code
# BMS_REF_EVENT_CODE= # only if the URL's refEventCode differs from above
BMS_REGION_CODE=AHD # BMS region code (AHD, BANG, MUMBAI, NCR ...)
BMS_REGION_SLUG=ahmedabad # city slug in the path
BMS_LAT=23.0395677
BMS_LNG=72.5660045
BMS_VENUE_CODE=PPAM # empty = watch every cinema in the region
# BMS_LANGUAGE=hindi # only if you want one language's shows
BMS_FORMAT_MATCH=IMAX # matched against the screen format; empty = any show
BMS_BOOKING_URL=https://in.bookmyshow.com/movies/ahmedabad/avengers-endgame-encore/ET00514163
# Watch only some of the configured providers. Unset = every provider you configured.
# PROVIDERS=district,bookmyshow
# ── Behaviour ─────────────────────────────────────────────────────────────────
CHECK_INTERVAL_SECONDS=60 # how often to poll; don't go lower without good reason
FAILURE_THRESHOLD=6 # consecutive failures before the "monitor broken" alert
TZ_OFFSET_MINUTES=330 # timezone used for showtimes and dates (330 = IST)
HEARTBEAT_HOUR=9 # daily "still alive" push at this local hour; -1 disables
CURRENCY=₹
# EXPIRY_UTC= # auto: local midnight after TARGET_DATE. Override to extend.
# ── Runtime ───────────────────────────────────────────────────────────────────
STATE_PATH=./state.json # Docker image defaults this to /data/state.json
PORT=4733 # status endpoint (--loop mode only)
# Routes District checks through a SOCKS5 proxy; notifications stay direct.
# Needed on datacenter hosts, whose IPs District's WAF blocks. It does nothing for
# BookMyShow, which blocks on TLS fingerprint rather than IP (impit handles that).
# PROXY_URL=socks5://user:pass@proxy.example.net:1080