update info route
This commit is contained in:
parent
231ea8149d
commit
e17bb267fe
@ -6,38 +6,40 @@ import { ServerlessEventObject, ServerlessFunctionSignature } from "@twilio-labs
|
||||
import { TwilioContext } from "../../../types/TwilioContext";
|
||||
import { createDynaBridgeClient } from "../../../utils/ddb";
|
||||
import { DoorStatus } from "../../../types/DoorStatus";
|
||||
import { getDoorConfigID } from "../../../schema/DoorConfig";
|
||||
import { DoorConfigSchema, getDoorConfigID } from "../../../schema/DoorConfig";
|
||||
import { getDoorAliasID } from "../../../schema/DoorAlias";
|
||||
import { getLockStatusID, isLockOpen } from "../../../schema/LockStatus";
|
||||
import { withMetrics } from "../../../common/DoormanHandler";
|
||||
import { z } from "zod";
|
||||
import { UserAgentHeader } from "../../../utils/blockUserAgent";
|
||||
import { setResponseJson } from "../../../utils/responseUtils";
|
||||
|
||||
export interface InfoRequest extends ServerlessEventObject {
|
||||
door?: string;
|
||||
buzzer?: string;
|
||||
export const InfoRequestSchema = z.object({
|
||||
door: z.string().optional(),
|
||||
buzzer: z.string().optional(),
|
||||
})
|
||||
.partial()
|
||||
.refine(data => data.buzzer || data.door, 'Buzzer or door must be provided');
|
||||
|
||||
// TODO: change these to be multiple
|
||||
discordUser: string;
|
||||
msg: string;
|
||||
json: string;
|
||||
}
|
||||
export type InfoRequest = z.infer<typeof InfoRequestSchema>;
|
||||
export interface InfoRequestTwilio extends ServerlessEventObject<InfoRequest, UserAgentHeader> { };
|
||||
|
||||
export interface InfoResponseClient {
|
||||
buzzer: string;
|
||||
door: string;
|
||||
pressKey: string;
|
||||
fallbackNumbers: string[];
|
||||
discordUsers: string[];
|
||||
}
|
||||
export const InfoResponseClientSchema = DoorConfigSchema
|
||||
.omit({ PK: true, SK: true, pin: true })
|
||||
.extend({ door: z.string() });
|
||||
|
||||
export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequest> = async function(context, event, callback) {
|
||||
export type InfoResponseClient = z.infer<typeof InfoResponseClientSchema>;
|
||||
|
||||
export const InfoResponseUISchema = InfoResponseClientSchema.extend({ id: z.string(), status: z.nativeEnum(DoorStatus) });
|
||||
|
||||
export type InfoResponseUI = z.infer<typeof InfoResponseUISchema>;
|
||||
|
||||
export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequestTwilio> = withMetrics("info", async (context, event, callback, metricsRegistry) => {
|
||||
const response = new Twilio.Response();
|
||||
const req = InfoRequestSchema.parse(event);
|
||||
|
||||
let door = event.door;
|
||||
const buzzer = event.buzzer?.slice(-10);
|
||||
|
||||
if (!door && !buzzer) {
|
||||
response.setStatusCode(400);
|
||||
return callback(null, response);
|
||||
}
|
||||
let door = req.door;
|
||||
const buzzer = req.buzzer?.slice(-10);
|
||||
|
||||
const db = createDynaBridgeClient(context);
|
||||
|
||||
@ -45,10 +47,9 @@ export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequest> =
|
||||
door = await db.entities.doorAlias.findById(getDoorAliasID(buzzer))
|
||||
.then(async (alias) => {
|
||||
if (!alias) {
|
||||
response
|
||||
.setStatusCode(404)
|
||||
.appendHeader('Content-Type', 'application/json')
|
||||
.setBody({ err: "This buzzer is not registered" });
|
||||
setResponseJson(response, 404, {
|
||||
err: "This buzzer is not registered",
|
||||
});
|
||||
return undefined;
|
||||
}
|
||||
return alias.name;
|
||||
@ -59,42 +60,32 @@ export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequest> =
|
||||
const config = await db.entities.doorConfig.findById(getDoorConfigID(door));
|
||||
|
||||
if (!config) {
|
||||
response
|
||||
.setStatusCode(404)
|
||||
.appendHeader('Content-Type', 'application/json')
|
||||
.setBody({ err: "This buzzer is not registered properly" });
|
||||
setResponseJson(response, 404, {
|
||||
err: "This buzzer is not registered",
|
||||
});
|
||||
} else {
|
||||
if (buzzer) {
|
||||
// respond to twilio CLIENT
|
||||
response
|
||||
.setStatusCode(200)
|
||||
.appendHeader('Content-Type', 'application/json')
|
||||
.setBody({
|
||||
buzzer,
|
||||
door,
|
||||
fallbackNumbers: config.fallbackNumbers,
|
||||
pressKey: config.pressKey,
|
||||
discordUsers: config.discordUsers,
|
||||
});
|
||||
const body: InfoResponseClient = InfoResponseClientSchema.parse({
|
||||
...config,
|
||||
buzzer,
|
||||
door,
|
||||
});
|
||||
|
||||
setResponseJson(response, 200, body);
|
||||
} else {
|
||||
const lock = await db.entities.lockStatus.findById(getLockStatusID(door));
|
||||
const status = isLockOpen(lock) ? DoorStatus.OPEN: DoorStatus.CLOSED;
|
||||
|
||||
const body: InfoResponseUI = InfoResponseUISchema.parse({
|
||||
...config,
|
||||
id: door,
|
||||
door,
|
||||
status,
|
||||
})
|
||||
|
||||
// respond to UI
|
||||
response
|
||||
.setStatusCode(200)
|
||||
.appendHeader('Content-Type', 'application/json')
|
||||
.setBody({
|
||||
id: door,
|
||||
timeout: config.timeout,
|
||||
buzzer: config.buzzer,
|
||||
status,
|
||||
buzzerCode: config.buzzerCode,
|
||||
fallbackNumbers: config.fallbackNumbers,
|
||||
pressKey: config.pressKey,
|
||||
discordUsers: config.discordUsers,
|
||||
greeting: config.greeting || "",
|
||||
});
|
||||
setResponseJson(response, 200, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -104,4 +95,4 @@ export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequest> =
|
||||
db.ddbClient.destroy();
|
||||
|
||||
return callback(null, response);
|
||||
};
|
||||
});
|
||||
@ -5,6 +5,7 @@ import { AuthComponent, IAuthMode } from "../components/AuthComponent";
|
||||
import OtpInput from 'react-otp-input';
|
||||
import { CountdownBar } from "../components/CountdownBar";
|
||||
import { DoorResponse } from "../types/DoorResponse";
|
||||
import { fetchUrlEncoded } from "../helpers/FetchHelper";
|
||||
|
||||
export async function loader({ params, request }: any) {
|
||||
const door = new URL(request.url).searchParams.get('door');
|
||||
@ -13,7 +14,9 @@ export async function loader({ params, request }: any) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const response = await fetch(`/api/door/info?door=${door}`).then(res => res.json());
|
||||
const response = await fetchUrlEncoded('/api/door/info', {
|
||||
door,
|
||||
}).then(res => res.json());
|
||||
|
||||
console.log(response);
|
||||
|
||||
@ -70,7 +73,9 @@ export function DoorPage() {
|
||||
}
|
||||
|
||||
const timer = setInterval(async () => {
|
||||
const response = await fetch(`/api/door/info?door=${door}`).then(res => res.json());
|
||||
const response = await fetchUrlEncoded('/api/door/info', {
|
||||
door,
|
||||
}).then(res => res.json());
|
||||
|
||||
// polling assumes that the door was opened and whatever closed it was the buzzer system...
|
||||
// ie. state transition from OPEN to CLOSED before timeout means that twilio opened the door
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user