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