Skip to content

Commit b6c70a8

Browse files
migrate simbrief cmd to zod
1 parent 4353aef commit b6c70a8

File tree

10 files changed

+125
-76
lines changed

10 files changed

+125
-76
lines changed

src/commands/utils/simbriefData.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { ApplicationCommandOptionType, ApplicationCommandType, Colors } from 'discord.js';
22
import moment from 'moment';
3-
import { slashCommand, makeEmbed, makeLines, slashCommandStructure } from '../../lib';
3+
import { Request } from 'node-fetch';
4+
import { ZodError } from 'zod';
5+
import { slashCommand, makeEmbed, makeLines, slashCommandStructure, SimbriefFlightPlan, fetchData, SimbriefFlightPlanSchema } from '../../lib';
46

57
const data = slashCommandStructure({
68
name: 'simbrief-data',
@@ -40,9 +42,9 @@ const simbriefdatarequestEmbed = makeEmbed({
4042
]),
4143
});
4244

43-
const errorEmbed = (errorMessage: any) => makeEmbed({
45+
const errorEmbed = (errorMessage: string) => makeEmbed({
4446
title: 'SimBrief Error',
45-
description: makeLines(['SimBrief data could not be read.', errorMessage]),
47+
description: errorMessage,
4648
color: Colors.Red,
4749
});
4850

@@ -53,10 +55,10 @@ const simbriefIdMismatchEmbed = (enteredId: any, flightplanId: any) => makeEmbed
5355
]),
5456
});
5557

56-
const simbriefEmbed = (flightplan: any) => makeEmbed({
58+
const simbriefEmbed = (flightplan: SimbriefFlightPlan) => makeEmbed({
5759
title: 'SimBrief Data',
5860
description: makeLines([
59-
`**Generated at**: ${moment(flightplan.params.time_generated * 1000).format('DD.MM.YYYY, HH:mm:ss')}`,
61+
`**Generated at**: ${moment(Number.parseInt(flightplan.params.time_generated) * 1000).format('DD.MM.YYYY, HH:mm:ss')}`,
6062
`**AirFrame**: ${flightplan.aircraft.name} ${flightplan.aircraft.internal_id} ${(flightplan.aircraft.internal_id === FBW_AIRFRAME_ID) ? '(provided by FBW)' : ''}`,
6163
`**AIRAC Cycle**: ${flightplan.params.airac}`,
6264
`**Origin**: ${flightplan.origin.icao_code}`,
@@ -71,23 +73,32 @@ export default slashCommand(data, async ({ interaction }) => {
7173
return interaction.reply({ embeds: [simbriefdatarequestEmbed] });
7274
}
7375

76+
await interaction.deferReply();
77+
7478
if (interaction.options.getSubcommand() === 'retrieve') {
7579
const simbriefId = interaction.options.getString('pilot_id');
76-
if (!simbriefId) return interaction.reply({ content: 'Invalid pilot ID!', ephemeral: true });
80+
if (!simbriefId) return interaction.editReply({ content: 'Invalid pilot ID!' });
7781

78-
const flightplan = await fetch(`https://www.simbrief.com/api/xml.fetcher.php?json=1&userid=${simbriefId}&username=${simbriefId}`).then((res) => res.json());
82+
let flightplan: SimbriefFlightPlan;
83+
try {
84+
flightplan = await fetchData<SimbriefFlightPlan>(new Request(`https://www.simbrief.com/api/xml.fetcher.php?json=1&userid=${simbriefId}&username=${simbriefId}`), SimbriefFlightPlanSchema);
85+
} catch (e) {
86+
if (e instanceof ZodError) {
87+
return interaction.editReply({ embeds: [errorEmbed('The API returned unknown data.')] });
88+
}
89+
return interaction.editReply({ embeds: [errorEmbed('An error occurred while fetching the SimBrief flightplan.')] });
90+
}
7991

8092
if (flightplan.fetch.status !== 'Success') {
81-
interaction.reply({ embeds: [errorEmbed(flightplan.fetch.status)], ephemeral: true });
82-
return Promise.resolve();
93+
return interaction.editReply({ embeds: [errorEmbed(flightplan.fetch.status)] });
8394
}
8495

8596
if (!simbriefId.match(/\D/) && simbriefId !== flightplan.params.user_id) {
86-
interaction.reply({ embeds: [simbriefIdMismatchEmbed(simbriefId, flightplan.params.user_id)] });
97+
return interaction.editReply({ embeds: [simbriefIdMismatchEmbed(simbriefId, flightplan.params.user_id)] });
8798
}
88-
interaction.reply({ embeds: [simbriefEmbed(flightplan)] });
8999

90-
return Promise.resolve();
100+
return interaction.editReply({ embeds: [simbriefEmbed(flightplan)] });
91101
}
92-
return Promise.resolve();
102+
103+
return interaction.editReply({ content: 'Unknown subcommand.' });
93104
});

src/commands/utils/vatsim/functions/vatsimControllers.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { ChatInputCommandInteraction, EmbedField } from 'discord.js';
2-
import { Atis, Rating, VatsimData, makeEmbed } from '../../../../lib';
2+
import { z } from 'zod';
3+
import { VatsimAtisSchema, VatsimRatingSchema, VatsimData, makeEmbed } from '../../../../lib';
4+
5+
type Atis = z.infer<typeof VatsimAtisSchema>;
6+
type Rating = z.infer<typeof VatsimRatingSchema>;
37

48
/* eslint-disable camelcase */
59

src/commands/utils/vatsim/functions/vatsimObservers.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { ChatInputCommandInteraction, EmbedField } from 'discord.js';
2-
import { Rating, VatsimData, makeEmbed } from '../../../../lib';
2+
import { z } from 'zod';
3+
import { VatsimRatingSchema, VatsimData, makeEmbed } from '../../../../lib';
4+
5+
type Rating = z.infer<typeof VatsimRatingSchema>;
36

47
/* eslint-disable camelcase */
58

src/commands/utils/vatsim/functions/vatsimPilots.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { ChatInputCommandInteraction, EmbedField } from 'discord.js';
2-
import { FlightPlan, PilotRating, VatsimData, makeEmbed } from '../../../../lib';
2+
import { z } from 'zod';
3+
import { VatsimFlightPlanSchema, VatsimPilotRatingSchema, VatsimData, makeEmbed } from '../../../../lib';
4+
5+
type PilotRating = z.infer<typeof VatsimPilotRatingSchema>;
6+
type FlightPlan = z.infer<typeof VatsimFlightPlanSchema>;
37

48
/* eslint-disable camelcase */
59

src/lib/apis/zodSchemas/metarSchemas.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
import { z } from 'zod';
22

3-
export const TimeSchema = z.object({ dt: z.string().datetime() });
3+
export const MetarTimeSchema = z.object({ dt: z.string().datetime() });
44

5-
export const WindDirectionSchema = z.object({ repr: z.string() });
5+
export const MetarWindDirectionSchema = z.object({ repr: z.string() });
66

7-
export const WindSpeedSchema = z.object({ repr: z.string() });
7+
export const MetarWindSpeedSchema = z.object({ repr: z.string() });
88

9-
export const VisibilitySchema = z.object({ repr: z.string() });
9+
export const MetarVisibilitySchema = z.object({ repr: z.string() });
1010

11-
export const TemperatureSchema = z.object({ repr: z.string() });
11+
export const MetarTemperatureSchema = z.object({ repr: z.string() });
1212

13-
export const DewpointSchema = z.object({ repr: z.string() });
13+
export const MetarDewpointSchema = z.object({ repr: z.string() });
1414

15-
export const AltimeterSchema = z.object({ value: z.number() });
15+
export const MetarAltimeterSchema = z.object({ value: z.number() });
1616

17-
export const UnitsSchema = z.object({
17+
export const MetarUnitsSchema = z.object({
1818
accumulation: z.string(),
1919
altimeter: z.string(),
2020
altitude: z.string(),
@@ -29,15 +29,15 @@ export const UnitsSchema = z.object({
2929
export const MetarSchema = z.object({
3030
station: z.string(),
3131
raw: z.string(),
32-
time: TimeSchema,
33-
wind_direction: WindDirectionSchema,
34-
wind_speed: WindSpeedSchema,
35-
visibility: VisibilitySchema,
36-
temperature: TemperatureSchema,
37-
dewpoint: DewpointSchema,
38-
altimeter: AltimeterSchema,
32+
time: MetarTimeSchema,
33+
wind_direction: MetarWindDirectionSchema,
34+
wind_speed: MetarWindSpeedSchema,
35+
visibility: MetarVisibilitySchema,
36+
temperature: MetarTemperatureSchema,
37+
dewpoint: MetarDewpointSchema,
38+
altimeter: MetarAltimeterSchema,
3939
flight_rules: z.string(),
40-
units: UnitsSchema,
40+
units: MetarUnitsSchema,
4141
});
4242

4343
/**
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { z } from 'zod';
2+
3+
const FetchSchema = z.object({ status: z.string() });
4+
5+
const ParamsSchema = z.object({
6+
user_id: z.string(),
7+
time_generated: z.string(),
8+
airac: z.string(),
9+
});
10+
11+
const AircraftSchema = z.object({
12+
name: z.string(),
13+
internal_id: z.string(),
14+
});
15+
16+
const OriginSchema = z.object({ icao_code: z.string() });
17+
18+
const DestinationSchema = z.object({ icao_code: z.string() });
19+
20+
const GeneralSchema = z.object({ route: z.string() });
21+
22+
/**
23+
* This schema only contains currently used fields. If you wish to use other fields returned by the API add them in this file.
24+
*/
25+
export const SimbriefFlightPlanSchema = z.object({
26+
fetch: FetchSchema,
27+
params: ParamsSchema,
28+
aircraft: AircraftSchema,
29+
origin: OriginSchema,
30+
destination: DestinationSchema,
31+
general: GeneralSchema,
32+
});
33+
34+
/**
35+
* This type only contains currently used fields. If you wish to use other fields returned by the API add them in this file.
36+
*/
37+
export type SimbriefFlightPlan = z.infer<typeof SimbriefFlightPlanSchema>;

src/lib/apis/zodSchemas/tafSchemas.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { z } from 'zod';
22

3-
export const ForecastSchema = z.object({ raw: z.string() });
3+
export const TafForecastSchema = z.object({ raw: z.string() });
44

55
/**
66
* This schema only contains currently used fields. If you wish to use other fields returned by the API add them in this file.
77
*/
88
export const TafSchema = z.object({
99
raw: z.string(),
1010
station: z.string(),
11-
forecast: z.array(ForecastSchema),
11+
forecast: z.array(TafForecastSchema),
1212
});
1313
/**
1414
* This type only contains currently used fields. If you wish to use other fields returned by the API add them in this file.

src/lib/apis/zodSchemas/vatsimDataSchemas.ts

Lines changed: 23 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
import { z } from 'zod';
22

3-
const MilitaryRatingSchema = z.object({
3+
export const VatsimMilitaryRatingSchema = z.object({
44
id: z.number(),
55
short_name: z.string(),
66
long_name: z.string(),
77
});
88

9-
const PilotRatingSchema = z.object({
9+
export const VatsimPilotRatingSchema = z.object({
1010
id: z.number(),
1111
short_name: z.string(),
1212
long_name: z.string(),
1313
});
1414

15-
const RatingSchema = z.object({
15+
export const VatsimRatingSchema = z.object({
1616
id: z.number(),
1717
short: z.string(),
1818
long: z.string(),
1919
});
2020

21-
const FacilitySchema = z.object({
21+
export const VatsimFacilitySchema = z.object({
2222
id: z.number(),
2323
short: z.string(),
2424
long: z.string(),
2525
});
2626

27-
const FlightPlanSchema = z.object({
27+
export const VatsimFlightPlanSchema = z.object({
2828
flight_rules: z.enum(['I', 'V']),
2929
aircraft: z.string(),
3030
aircraft_faa: z.string(),
@@ -41,15 +41,15 @@ const FlightPlanSchema = z.object({
4141
assigned_transponder: z.string(),
4242
});
4343

44-
const PrefileSchema = z.object({
44+
export const VatsimPrefileSchema = z.object({
4545
cid: z.number(),
4646
name: z.string(),
4747
callsign: z.string(),
48-
flight_plan: FlightPlanSchema,
48+
flight_plan: VatsimFlightPlanSchema,
4949
last_updated: z.string(),
5050
});
5151

52-
const ServerSchema = z.object({
52+
export const VatsimServerSchema = z.object({
5353
ident: z.string(),
5454
hostname_or_ip: z.string(),
5555
location: z.string(),
@@ -62,7 +62,7 @@ const ServerSchema = z.object({
6262
is_sweatbox: z.boolean(),
6363
});
6464

65-
const AtisSchema = z.object({
65+
export const VatsimAtisSchema = z.object({
6666
cid: z.number(),
6767
name: z.string(),
6868
callsign: z.string(),
@@ -77,7 +77,7 @@ const AtisSchema = z.object({
7777
logon_time: z.string(),
7878
});
7979

80-
const ControllerSchema = z.object({
80+
export const VatsimControllerSchema = z.object({
8181
cid: z.number(),
8282
name: z.string(),
8383
callsign: z.string(),
@@ -91,7 +91,7 @@ const ControllerSchema = z.object({
9191
logon_time: z.string(),
9292
});
9393

94-
const PilotSchema = z.object({
94+
export const VatsimPilotSchema = z.object({
9595
cid: z.number(),
9696
name: z.string(),
9797
callsign: z.string(),
@@ -106,12 +106,12 @@ const PilotSchema = z.object({
106106
heading: z.number(),
107107
qnh_i_hg: z.number(),
108108
qnh_mb: z.number(),
109-
flight_plan: z.nullable(FlightPlanSchema),
109+
flight_plan: z.nullable(VatsimFlightPlanSchema),
110110
logon_time: z.string(),
111111
last_updated: z.string(),
112112
});
113113

114-
const GeneralSchema = z.object({
114+
export const VatsimGeneralSchema = z.object({
115115
version: z.number(),
116116
/**
117117
* @deprecated
@@ -131,27 +131,16 @@ const GeneralSchema = z.object({
131131
* @see https://vatsim.dev/api/data-api/get-network-data
132132
*/
133133
export const VatsimDataSchema = z.object({
134-
general: GeneralSchema,
135-
pilots: z.array(PilotSchema),
136-
controllers: z.array(ControllerSchema),
137-
atis: z.array(AtisSchema),
138-
servers: z.array(ServerSchema),
139-
prefiles: z.array(PrefileSchema),
140-
facilities: z.array(FacilitySchema),
141-
ratings: z.array(RatingSchema),
142-
pilot_ratings: z.array(PilotRatingSchema),
143-
military_ratings: z.array(MilitaryRatingSchema),
134+
general: VatsimGeneralSchema,
135+
pilots: z.array(VatsimPilotSchema),
136+
controllers: z.array(VatsimControllerSchema),
137+
atis: z.array(VatsimAtisSchema),
138+
servers: z.array(VatsimServerSchema),
139+
prefiles: z.array(VatsimPrefileSchema),
140+
facilities: z.array(VatsimFacilitySchema),
141+
ratings: z.array(VatsimRatingSchema),
142+
pilot_ratings: z.array(VatsimPilotRatingSchema),
143+
military_ratings: z.array(VatsimMilitaryRatingSchema),
144144
});
145145

146146
export type VatsimData = z.infer<typeof VatsimDataSchema>;
147-
export type General = z.infer<typeof GeneralSchema>;
148-
export type Pilot = z.infer<typeof PilotSchema>;
149-
export type Controller = z.infer<typeof ControllerSchema>;
150-
export type Atis = z.infer<typeof AtisSchema>;
151-
export type Server = z.infer<typeof ServerSchema>;
152-
export type Prefiles = z.infer<typeof PrefileSchema>;
153-
export type FlightPlan = z.infer<typeof FlightPlanSchema>;
154-
export type Facility = z.infer<typeof FacilitySchema>;
155-
export type Rating = z.infer<typeof RatingSchema>;
156-
export type PilotRating = z.infer<typeof PilotRatingSchema>;
157-
export type MilitaryRating = z.infer<typeof MilitaryRatingSchema>;
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
import { z } from 'zod';
22

3-
export const OrganiserSchema = z.object({
3+
export const VatsimOrganiserSchema = z.object({
44
region: z.nullable(z.string()),
55
division: z.nullable(z.string()),
66
subdivision: z.nullable(z.string()),
77
organised_by_vatsim: z.boolean(),
88
});
99

10-
export const AirportSchema = z.object({ icao: z.string() });
10+
export const VatsimAirportSchema = z.object({ icao: z.string() });
1111

12-
export const RouteSchema = z.object({
12+
export const VatsimRouteSchema = z.object({
1313
departure: z.string(),
1414
arrival: z.string(),
1515
route: z.string(),
1616
});
1717

18-
export const DataSchema = z.object({
18+
export const VatsimEventsDataSchema = z.object({
1919
id: z.number(),
2020
type: z.enum(['Event', 'Controller Examination', 'VASOPS Event']),
2121
name: z.string(),
2222
link: z.string(),
23-
organisers: z.array(OrganiserSchema),
24-
airports: z.array(AirportSchema),
25-
routes: z.array(RouteSchema),
23+
organisers: z.array(VatsimOrganiserSchema),
24+
airports: z.array(VatsimAirportSchema),
25+
routes: z.array(VatsimRouteSchema),
2626
start_time: z.string(),
2727
end_time: z.string(),
2828
short_description: z.string(),
@@ -33,6 +33,6 @@ export const DataSchema = z.object({
3333
/**
3434
* @see https://vatsim.dev/api/events-api/1.0.0/list-events
3535
*/
36-
export const VatsimEventsSchema = z.object({ data: z.array(DataSchema) });
36+
export const VatsimEventsSchema = z.object({ data: z.array(VatsimEventsDataSchema) });
3737

3838
export type VatsimEvents = z.infer<typeof VatsimEventsSchema>;

src/lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ export * from './apis/fetchData';
2727
export * from './apis/zodSchemas/vatsimEventsSchemas';
2828
export * from './apis/zodSchemas/vatsimDataSchemas';
2929
export * from './apis/zodSchemas/tafSchemas';
30+
export * from './apis/zodSchemas/simbriefSchemas';

0 commit comments

Comments
 (0)