Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: generic wrapper for JSON APIs #70

Draft
wants to merge 36 commits into
base: staging
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
759758a
add fetchData
ExampleWasTaken Jun 25, 2024
c15b315
add vatsim-event endpoint types
ExampleWasTaken Jun 25, 2024
211579d
add util type guards
ExampleWasTaken Jun 25, 2024
684ca62
migrate vatsim events to the new api wrapper
ExampleWasTaken Jun 25, 2024
7ab2383
add vatsim data endpoint types
ExampleWasTaken Jun 25, 2024
bd67559
add zod library
ExampleWasTaken Jul 1, 2024
bd0b412
partial vatsim port to zod
ExampleWasTaken Jul 1, 2024
0f7ec61
migrate vatsim observer to zod
ExampleWasTaken Jul 2, 2024
992c700
add missing flight plan type export
ExampleWasTaken Jul 2, 2024
81b9045
migrate vatsim pilot to zod
ExampleWasTaken Jul 2, 2024
7b37d6e
migrate vatsim stats to zod
ExampleWasTaken Jul 2, 2024
7062fc0
fix lint in vatsim
ExampleWasTaken Jul 2, 2024
5e2a3b7
migrate vatsimEvents
ExampleWasTaken Jul 2, 2024
33e3219
improve var naming
ExampleWasTaken Jul 2, 2024
7a0c89b
refactor fetchData
ExampleWasTaken Jul 2, 2024
31c2ea3
remove any ewww
ExampleWasTaken Jul 2, 2024
540557a
migrate taf cmd to zod
ExampleWasTaken Jul 3, 2024
0bffea0
migrate metar cmd to zod
ExampleWasTaken Jul 3, 2024
5c1299b
add disclaimer comments to taf and metar schemas
ExampleWasTaken Jul 3, 2024
f24dd5c
migrate simbrief cmd to zod
ExampleWasTaken Jul 3, 2024
50d08dc
migrate wolfram alpha cmd to zod
ExampleWasTaken Jul 3, 2024
0044d3c
fix zod error being thrown incorrectly while fetching data
ExampleWasTaken Jul 3, 2024
d1a8704
add folder structure to zod schema directory
ExampleWasTaken Jul 3, 2024
c841fea
migrate station cmd to zod
ExampleWasTaken Jul 4, 2024
698074e
migrate live-flight cmd to zod
ExampleWasTaken Jul 4, 2024
eae9c22
rename fetchData to fetchForeignAPI
ExampleWasTaken Jul 4, 2024
03adb0d
improve fetchForeignAPI zod error logging
ExampleWasTaken Jul 4, 2024
c01ad7a
allow string and url when fetching from foreign apis
ExampleWasTaken Jul 4, 2024
6647032
use string instead of request object for foreign apis
ExampleWasTaken Jul 4, 2024
0b2de9e
add changelog
ExampleWasTaken Jul 28, 2024
a5b363e
self review
ExampleWasTaken Jul 4, 2024
aa84fa9
update simbrief zod schema
ExampleWasTaken Aug 8, 2024
7e46e6b
remove console
ExampleWasTaken Aug 26, 2024
e4eca0d
Merge branch 'staging' into feat/generic-api-wrapper
ExampleWasTaken Oct 27, 2024
256b6db
update changelog
ExampleWasTaken Oct 27, 2024
777c5b6
Merge branch 'staging' into feat/generic-api-wrapper
ExampleWasTaken Nov 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
migrate vatsim observer to zod
ExampleWasTaken committed Aug 8, 2024

Verified

This commit was signed with the committer’s verified signature.
ExampleWasTaken ExampleWasTaken
commit 0f7ec6184cc60d78c8527fe849915289ba931b15
10 changes: 5 additions & 5 deletions src/commands/utils/vatsim/functions/vatsimControllers.ts
Original file line number Diff line number Diff line change
@@ -36,9 +36,9 @@ const controllersListEmbedFields = (callsign: string, frequency: string, logon:
});
}

if (atis) {
if (atis && atis.text_atis) {
fields.push({
name: `ATIS - Code: ${atis.atis_code}`,
name: `ATIS - ${atis.atis_code ? atis.atis_code : 'N/A'}`,
value: atis.text_atis.join('\n'),
inline: false,
});
@@ -59,13 +59,13 @@ export async function handleVatsimControllers(interaction: ChatInputCommandInter
const controllers = vatsimData.controllers.filter((controller) => controller.facility > 0 && controller.callsign.includes(callsignSearch));
controllers.sort((a, b) => b.facility - a.facility);

const fields: EmbedField[] = controllers.map((controller) => {
const fields = controllers.map((controller) => {
const { callsign, frequency, logon_time } = controller;
const rating = vatsimData.ratings.find((rating) => rating.id === controller.rating);
const atis = vatsimData.atis.find((atis) => atis.cid === controller.cid);

return controllersListEmbedFields(callsign, frequency, handleLocaleDateTimeString(new Date(logon_time)), rating, atis);
}).splice(0, 5).flat();
}).splice(0, 5);

return interaction.reply({ embeds: [listEmbed('Controllers & ATIS', fields, controllers.length, fields.length, callsignSearch)] });
return interaction.editReply({ embeds: [listEmbed('Controllers & ATIS', fields.flat(), controllers.length, fields.length, callsignSearch)] });
}
48 changes: 15 additions & 33 deletions src/commands/utils/vatsim/functions/vatsimObservers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChatInputCommandInteraction, EmbedField } from 'discord.js';
import { makeEmbed } from '../../../../lib';
import { Rating, VatsimData, makeEmbed } from '../../../../lib';

/* eslint-disable camelcase */

@@ -9,7 +9,7 @@ const listEmbed = (type: string, fields: EmbedField[], totalCount: number, shown
fields,
});

const observersListEmbedFields = (callsign: string, logon: string, rating: string, atis: string): EmbedField[] => {
const observersListEmbedFields = (callsign: string, logon: string, rating?: Rating): EmbedField[] => {
const fields = [
{
name: 'Callsign',
@@ -21,18 +21,13 @@ const observersListEmbedFields = (callsign: string, logon: string, rating: strin
value: `${logon}`,
inline: true,
},
{
name: 'Rating',
value: `${rating}`,
inline: true,
},
];
if (atis !== null) {
const atisTitle = 'Info';

if (rating) {
fields.push({
name: atisTitle,
value: atis,
inline: false,
name: 'Rating',
value: `${rating.short} - ${rating.long}`,
inline: true,
});
}

@@ -47,28 +42,15 @@ const handleLocaleDateTimeString = (date: Date) => date.toLocaleDateString('en-U
day: 'numeric',
});

export async function handleVatsimObservers(interaction: ChatInputCommandInteraction<'cached'>, vatsimData: any, callsignSearch: any) {
const vatsimAllObservers = vatsimData.controllers ? vatsimData.controllers.filter((controller: { facility: number; }) => controller.facility <= 0) : null;

const vatsimControllerRatings = vatsimData.ratings ? vatsimData.ratings : null;
const vatsimObservers = vatsimAllObservers ? vatsimAllObservers.filter((observer: { callsign: string | any[]; }) => observer.callsign.includes(callsignSearch)) : null;

const { keys }: ObjectConstructor = Object;

const fields: EmbedField[] = [...vatsimObservers.sort((a: { rating: number; }, b: { rating: number; }) => b.rating - a.rating)].map((vatsimObserver) => {
const { callsign, logon_time, text_atis, rating } = vatsimObserver;
const logonTime = new Date(logon_time);
const logonTimeString = handleLocaleDateTimeString(logonTime);
const ratingDetail = vatsimControllerRatings.filter((ratingInfo: { id: any; }) => ratingInfo.id === rating);
const { short, long } = ratingDetail[0];
const ratingText = `${short} - ${long}`;
const atisText = text_atis ? text_atis.join('\n') : null;
export async function handleVatsimObservers(interaction: ChatInputCommandInteraction<'cached'>, vatsimData: VatsimData, callsignSearch: string) {
const observers = vatsimData.controllers.filter((controller) => controller.facility <= 0 && controller.callsign.includes(callsignSearch));

return observersListEmbedFields(callsign, logonTimeString, ratingText, atisText);
}).slice(0, 5).flat();
const fields = observers.map((observer) => {
const { callsign, logon_time } = observer;
const rating = vatsimData.ratings.find((rating) => rating.id === observer.rating);

const totalCount = keys(vatsimObservers).length;
const shownCount = totalCount < 5 ? totalCount : 5;
return observersListEmbedFields(callsign, handleLocaleDateTimeString(new Date(logon_time)), rating);
}).splice(0, 5);

return interaction.reply({ embeds: [listEmbed('Observers', fields, totalCount, shownCount, callsignSearch)] });
return interaction.editReply({ embeds: [listEmbed('Observers', fields.flat(), observers.length, fields.length, callsignSearch)] });
}
15 changes: 10 additions & 5 deletions src/commands/utils/vatsim/vatsim.ts
Original file line number Diff line number Diff line change
@@ -87,17 +87,19 @@ const fetchErrorEmbed = (error: any) => makeEmbed({
});

export default slashCommand(data, async ({ interaction }) => {
await interaction.deferReply();

// Fetch VATSIM data
let vatsimData: VatsimData;
try {
vatsimData = await fetchData<VatsimData>(new Request('https://data.vatsim.net/v3/vatsim-data.json'), VatsimDataSchema);
} catch (e) {
if (e instanceof ZodError) {
e.issues.forEach((e) => Logger.error(`[zod Issue VATSIM Data] Code: ${e.code}, Path: ${e.path.join('.')}, Message: ${e.message}`));
return interaction.reply({ embeds: [fetchErrorEmbed('The VATSIM API returned unknown data.')] });
return interaction.editReply({ embeds: [fetchErrorEmbed('The VATSIM API returned unknown data.')] });
}

return interaction.reply({ embeds: [fetchErrorEmbed(e)], ephemeral: true });
return interaction.editReply({ embeds: [fetchErrorEmbed(e)] });
}

// Grap the callsign from the interaction
@@ -111,7 +113,7 @@ export default slashCommand(data, async ({ interaction }) => {
const regexMatches = callsign.match(regexCheck);

if (!regexMatches || !regexMatches.groups || !regexMatches.groups.callsignSearch) {
return interaction.reply({ content: 'You need to provide a valid callsign or part of a callsign to search for', ephemeral: true });
return interaction.editReply({ content: 'You need to provide a valid callsign or part of a callsign to search for.' });
}

callsignSearch = regexMatches.groups.callsignSearch;
@@ -127,17 +129,20 @@ export default slashCommand(data, async ({ interaction }) => {
break;
case 'controllers':
if (!callsignSearch) {
return interaction.reply({ content: 'You need to provide a valid callsign or part of a callsign to search for', ephemeral: true });
return interaction.editReply({ content: 'You need to provide a valid callsign or part of a callsign to search for.' });
}
return handleVatsimControllers(interaction, vatsimData, callsignSearch);
case 'pilots':
return handleVatsimPilots(interaction, vatsimData, callsignSearch);
case 'observers':
if (!callsignSearch) {
return interaction.editReply({ content: 'You need to provide a valid callsign or part of a callsign to search for.' });
}
return handleVatsimObservers(interaction, vatsimData, callsignSearch);
case 'events':
return handleVatsimEvents(interaction);

default:
return interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
return interaction.editReply({ content: 'Unknown subcommand' });
}
});
2 changes: 1 addition & 1 deletion src/lib/apis/zodSchemas/vatsimData.ts
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@ const AtisSchema = z.object({
server: z.string(),
visual_range: z.number(),
atis_code: z.nullable(z.string()),
text_atis: z.array(z.string()),
text_atis: z.nullable(z.array(z.string())),
last_updated: z.string(),
logon_time: z.string(),
});