mirror of
https://github.com/Sea-Haven-Industries/seahaven-door-unlock-api.git
synced 2026-09-30 07:03:12 +00:00
87 lines
2.4 KiB
TypeScript
87 lines
2.4 KiB
TypeScript
|
|
import {
|
||
|
|
SSMClient,
|
||
|
|
GetParameterCommand,
|
||
|
|
} from "@aws-sdk/client-ssm";
|
||
|
|
|
||
|
|
const ssm = new SSMClient({});
|
||
|
|
|
||
|
|
let cachedApiKey: string | undefined;
|
||
|
|
|
||
|
|
const LOCKDOWN_PROFILES: { key: string; id: string }[] = [
|
||
|
|
{ key: "bohemia", id: "4b4a3e6b-c903-4cce-8cd6-288612bf0542" },
|
||
|
|
{ key: "ronkonkoma", id: "ff9876bc-c54f-472e-aef9-d2bffd4b7cf7" },
|
||
|
|
];
|
||
|
|
|
||
|
|
const ELEMENTS_BASE_URL = "https://api.elementssecure.com/v1";
|
||
|
|
const POLL_COUNT = 4;
|
||
|
|
const POLL_INTERVAL_MS = 15_000;
|
||
|
|
|
||
|
|
async function getSsmParam(name: string, decrypt: boolean): Promise<string> {
|
||
|
|
const res = await ssm.send(
|
||
|
|
new GetParameterCommand({ Name: name, WithDecryption: decrypt })
|
||
|
|
);
|
||
|
|
return res.Parameter!.Value!;
|
||
|
|
}
|
||
|
|
|
||
|
|
async function loadApiKey(): Promise<string> {
|
||
|
|
if (!cachedApiKey) {
|
||
|
|
cachedApiKey = await getSsmParam(process.env.ELEMENTS_API_KEY_PARAM!, true);
|
||
|
|
}
|
||
|
|
return cachedApiKey;
|
||
|
|
}
|
||
|
|
|
||
|
|
function sleep(ms: number): Promise<void> {
|
||
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||
|
|
}
|
||
|
|
|
||
|
|
async function getLockdownStatus(lockdownId: string, apiKey: string): Promise<boolean> {
|
||
|
|
const response = await fetch(`${ELEMENTS_BASE_URL}/lockdowns/${lockdownId}`, {
|
||
|
|
headers: { "api-key": apiKey },
|
||
|
|
});
|
||
|
|
|
||
|
|
if (response.status === 429) {
|
||
|
|
const retryAfter = parseInt(response.headers.get("retry-after") ?? "2", 10);
|
||
|
|
await sleep(retryAfter * 1000);
|
||
|
|
return getLockdownStatus(lockdownId, apiKey);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!response.ok) {
|
||
|
|
throw new Error(`Elements status check failed: ${response.status}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
const data = await response.json() as Record<string, unknown>;
|
||
|
|
return String(data.status).toLowerCase() === "active";
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function handler() {
|
||
|
|
let apiKey: string;
|
||
|
|
try {
|
||
|
|
apiKey = await loadApiKey();
|
||
|
|
} catch (err) {
|
||
|
|
console.error(JSON.stringify({ action: "poller_config_error", error: String(err) }));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (let i = 0; i < POLL_COUNT; i++) {
|
||
|
|
try {
|
||
|
|
const statuses = [];
|
||
|
|
for (const profile of LOCKDOWN_PROFILES) {
|
||
|
|
const active = await getLockdownStatus(profile.id, apiKey);
|
||
|
|
statuses.push({ profile: profile.key, active });
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log(JSON.stringify({
|
||
|
|
action: "poller_cycle",
|
||
|
|
iteration: i + 1,
|
||
|
|
statuses,
|
||
|
|
}));
|
||
|
|
} catch (err) {
|
||
|
|
console.error(JSON.stringify({ action: "poller_poll_error", iteration: i + 1, error: String(err) }));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (i < POLL_COUNT - 1) {
|
||
|
|
await sleep(POLL_INTERVAL_MS);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|