Refine response status, integrate configuration fetching, location checks ^& exception handling

This commit is contained in:
Xevion
2023-02-25 03:17:33 -06:00
parent ee2e51b2ad
commit d43b9eeefc

View File

@@ -1,15 +1,26 @@
import { getMatchingTime } from '@/timing';
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next';
import { getDistance } from '@/location';
import { env } from '@/env/server.mjs';
import monitorAsync from '@/monitor';
import { sendNotification } from '@/notify';
import { fetchConfiguration, checkIdentifier, markIdentifier } from '@/db';
type ResponseData = {
diff: number;
inRange: boolean;
};
type StatusData = { status: string };
type StatusData = { status: ResponseStatus };
type ResponseStatus =
| 'unauthorized'
| 'out-of-range'
| 'no-matching-time'
| 'already-notified'
| 'notified'
| 'error';
const center = {
latitude: env.CENTER_LATITUDE,
@@ -22,28 +33,64 @@ export default async function handler(
) {
if (req.query.key != env.API_KEY) {
// auth failed
res.status(401).json({ status: 'Unauthorized' });
res.status(401).json({ status: 'unauthorized' });
return;
}
async function innerFunction() {
const diff = await getDistance();
// auth passed
res.setHeader(
'Cache-Control',
`max-age=0, s-maxage=${env.EDGE_CACHE_TIME_SECONDS}, stale-while-revalidate`
);
res
.status(200)
.json({ diff, inRange: diff < env.MAX_DISTANCE, status: 'Success' });
async function innerFunction(): Promise<ResponseStatus> {
const now = new Date();
const config = await fetchConfiguration({
times: [
{
time: '03:13',
maxLate: '00:10',
days: [
'monday',
'tuesday',
'wednesday',
'thursday',
'friday',
'saturday',
'sunday'
],
name: 'B'
},
{
time: '23:26',
maxLate: '00:10',
days: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'],
name: 'A'
}
]
});
const matching = await getMatchingTime(config, now);
// No matching time - no notification to send.
if (matching == null) return 'no-matching-time';
// Check if I am in range of the center
const distanceToCenter = await getDistance();
if (distanceToCenter > 280) return 'out-of-range';
// Check if I have already been notified
if (await checkIdentifier(matching.name, now)) return 'already-notified';
// Send notification, mark
await sendNotification(`The bus is leaving soon. (${matching.name}))`);
await markIdentifier(matching.name, true, 60 * 60 * 24 * 31, now);
return 'notified';
}
try {
let result;
if (process.env.NODE_ENV === 'production')
await monitorAsync(innerFunction);
else await innerFunction();
result = await monitorAsync(innerFunction);
else result = await innerFunction();
res.status(200).json({ status: result });
} catch (e) {
console.error(e);
res.status(500).json({ status: 'Error' });
res.status(500).json({ status: 'error' });
}
}