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 // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next'; import type { NextApiRequest, NextApiResponse } from 'next';
import { getDistance } from '@/location'; import { getDistance } from '@/location';
import { env } from '@/env/server.mjs'; import { env } from '@/env/server.mjs';
import monitorAsync from '@/monitor'; import monitorAsync from '@/monitor';
import { sendNotification } from '@/notify';
import { fetchConfiguration, checkIdentifier, markIdentifier } from '@/db';
type ResponseData = { type ResponseData = {
diff: number; diff: number;
inRange: boolean; 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 = { const center = {
latitude: env.CENTER_LATITUDE, latitude: env.CENTER_LATITUDE,
@@ -22,28 +33,64 @@ export default async function handler(
) { ) {
if (req.query.key != env.API_KEY) { if (req.query.key != env.API_KEY) {
// auth failed // auth failed
res.status(401).json({ status: 'Unauthorized' }); res.status(401).json({ status: 'unauthorized' });
return; return;
} }
async function innerFunction() { async function innerFunction(): Promise<ResponseStatus> {
const diff = await getDistance(); const now = new Date();
// auth passed
res.setHeader( const config = await fetchConfiguration({
'Cache-Control', times: [
`max-age=0, s-maxage=${env.EDGE_CACHE_TIME_SECONDS}, stale-while-revalidate` {
); time: '03:13',
res maxLate: '00:10',
.status(200) days: [
.json({ diff, inRange: diff < env.MAX_DISTANCE, status: 'Success' }); '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 { try {
let result;
if (process.env.NODE_ENV === 'production') if (process.env.NODE_ENV === 'production')
await monitorAsync(innerFunction); result = await monitorAsync(innerFunction);
else await innerFunction(); else result = await innerFunction();
res.status(200).json({ status: result });
} catch (e) { } catch (e) {
console.error(e); console.error(e);
res.status(500).json({ status: 'Error' }); res.status(500).json({ status: 'error' });
} }
} }