Files
ticket-monitoring/src/config.js
T
Aculix Technologies 00e6852863 ci: publish multi-arch image to GHCR; move status port to 4733
GitHub Actions builds linux/amd64 and linux/arm64 on every push to main and
pushes a single :latest tag to ghcr.io, so the container can be run without
cloning or building. Tests gate the publish step.
2026-08-14 14:36:18 +05:30

63 lines
2.2 KiB
JavaScript

// Configuration is read entirely from environment variables (see .env.example).
// Load a .env file with Node's built-in flag: node --env-file-if-exists=.env src/index.js
function required(name) {
const v = process.env[name];
if (!v) throw new Error(`${name} is required — copy .env.example to .env and fill it in`);
return v;
}
const num = (name, fallback) => {
const v = process.env[name];
if (v === undefined || v === "") return fallback;
const n = Number(v);
if (Number.isNaN(n)) throw new Error(`${name} must be a number, got "${v}"`);
return n;
};
export function loadConfig() {
const targetDate = required("TARGET_DATE");
if (!/^\d{4}-\d{2}-\d{2}$/.test(targetDate)) {
throw new Error(`TARGET_DATE must be YYYY-MM-DD, got "${targetDate}"`);
}
const tzOffsetMinutes = num("TZ_OFFSET_MINUTES", 330);
// Retire at local midnight following the target date, unless overridden.
const expiryUtc = process.env.EXPIRY_UTC ||
new Date(Date.parse(`${targetDate}T00:00:00Z`) + 86400000 - tzOffsetMinutes * 60000).toISOString();
return {
// what to watch
movieCode: required("MOVIE_CODE"),
contentId: required("CONTENT_ID"),
cityKey: required("CITY_KEY"),
lat: required("LAT"),
lng: required("LNG"),
targetDate,
cinemaId: process.env.CINEMA_ID || "", // empty = any cinema
formatTag: process.env.FORMAT_TAG ?? "imax_2d", // empty + empty match = any format
formatMatch: process.env.FORMAT_MATCH ?? "IMAX",
formatLabel: process.env.FORMAT_LABEL || "IMAX",
bookingUrl: process.env.BOOKING_URL || "",
// notifications
ntfyUrl: (process.env.NTFY_URL || "https://ntfy.sh").replace(/\/+$/, ""),
ntfyTopic: required("NTFY_TOPIC"),
ntfyToken: process.env.NTFY_TOKEN || "",
// behaviour
intervalMs: num("CHECK_INTERVAL_SECONDS", 60) * 1000,
failureThreshold: num("FAILURE_THRESHOLD", 6),
tzOffsetMinutes,
heartbeatHour: num("HEARTBEAT_HOUR", 9), // -1 disables the daily heartbeat
currency: process.env.CURRENCY || "₹",
expiryUtc,
// runtime
statePath: process.env.STATE_PATH || "./state.json",
port: num("PORT", 4733),
proxyUrl: process.env.PROXY_URL || "",
dispatcher: null, // set by attachProxy() when PROXY_URL is present
};
}