1
1
import { ApplicationCommandOptionType , ApplicationCommandType , Colors } from 'discord.js' ;
2
- import fetch from 'node-fetch' ;
3
- import { slashCommand , slashCommandStructure , makeEmbed , Logger , makeLines } from '../../lib' ;
2
+ import { Request } from 'node-fetch' ;
3
+ import { z , ZodError } from 'zod' ;
4
+ import { AVWXRunwaySchema , AVWXStation , AVWXStationSchema , fetchData , Logger , makeEmbed , makeLines , slashCommand , slashCommandStructure } from '../../lib' ;
5
+
6
+ type Runway = z . infer < typeof AVWXRunwaySchema > ;
4
7
5
8
const data = slashCommandStructure ( {
6
9
name : 'station' ,
@@ -22,6 +25,12 @@ const noQueryEmbed = makeEmbed({
22
25
color : Colors . Red ,
23
26
} ) ;
24
27
28
+ const errorEmbed = ( error : string ) => makeEmbed ( {
29
+ title : 'Station Error' ,
30
+ description : error ,
31
+ color : Colors . Red ,
32
+ } ) ;
33
+
25
34
export default slashCommand ( data , async ( { interaction } ) => {
26
35
await interaction . deferReply ( ) ;
27
36
@@ -40,54 +49,44 @@ export default slashCommand(data, async ({ interaction }) => {
40
49
41
50
if ( ! icao ) return interaction . editReply ( { embeds : [ noQueryEmbed ] } ) ;
42
51
52
+ let station : AVWXStation ;
43
53
try {
44
- const stationReport : any = await fetch ( `https://avwx.rest/api/station/${ icao } ` , {
54
+ station = await fetchData < AVWXStation > ( new Request ( `https://avwx.rest/api/station/${ icao } ` , {
45
55
method : 'GET' ,
46
56
headers : { Authorization : stationToken } ,
47
- } ) . then ( ( res ) => res . json ( ) ) ;
48
-
49
- if ( stationReport . error ) {
50
- const invalidEmbed = makeEmbed ( {
51
- title : `Station Error | ${ icao . toUpperCase ( ) } ` ,
52
- description : stationReport . error ,
53
- color : Colors . Red ,
54
- } ) ;
55
- return interaction . editReply ( { embeds : [ invalidEmbed ] } ) ;
57
+ } ) , AVWXStationSchema ) ;
58
+ } catch ( e ) {
59
+ if ( e instanceof ZodError ) {
60
+ return interaction . editReply ( { embeds : [ errorEmbed ( 'The API returned unknown data.' ) ] } ) ;
56
61
}
62
+ Logger . error ( `Error while fetching station info from AVWX: ${ e } ` ) ;
63
+ return interaction . editReply ( { embeds : [ errorEmbed ( `An error occurred while fetching the station information for ${ icao . toUpperCase ( ) } .` ) ] } ) ;
64
+ }
57
65
58
- const runwayIdents = stationReport . runways . map ( ( runways : any ) => `**${ runways . ident1 } /${ runways . ident2 } :** `
59
- + `${ runways . length_ft } ft x ${ runways . width_ft } ft / `
60
- + `${ Math . round ( runways . length_ft * 0.3048 ) } m x ${ Math . round ( runways . width_ft * 0.3048 ) } m` ) ;
66
+ const runwayIdents = station . runways ? station . runways . map ( ( runways : Runway ) => `**${ runways . ident1 } /${ runways . ident2 } :** `
67
+ + `${ runways . length_ft } ft x ${ runways . width_ft } ft / `
68
+ + `${ Math . round ( runways . length_ft * 0.3048 ) } m x ${ Math . round ( runways . width_ft * 0.3048 ) } m` ) : null ;
61
69
62
- const stationEmbed = makeEmbed ( {
63
- title : `Station Info | ${ stationReport . icao } ` ,
64
- description : makeLines ( [
65
- '**Station Information:**' ,
66
- `**Name:** ${ stationReport . name } ` ,
67
- `**Country:** ${ stationReport . country } ` ,
68
- `**City:** ${ stationReport . city } ` ,
69
- `**Latitude:** ${ stationReport . latitude } °` ,
70
- `**Longitude:** ${ stationReport . longitude } °` ,
71
- `**Elevation:** ${ stationReport . elevation_m } m/${ stationReport . elevation_ft } ft` ,
72
- '' ,
73
- '**Runways (Ident1/Ident2: Length x Width):**' ,
74
- `${ runwayIdents . toString ( ) . replace ( / , / g, '\n' ) } ` ,
75
- '' ,
76
- `**Type:** ${ stationReport . type . replace ( / _ / g, ' ' ) } ` ,
77
- `**Website:** ${ stationReport . website } ` ,
78
- `**Wiki:** ${ stationReport . wiki } ` ,
79
- ] ) ,
80
- footer : { text : 'Due to limitations of the API, not all links may be up to date at all times.' } ,
81
- } ) ;
70
+ const stationEmbed = makeEmbed ( {
71
+ title : `Station Info | ${ station . icao } ` ,
72
+ description : makeLines ( [
73
+ '**Station Information:**' ,
74
+ `**Name:** ${ station . name } ` ,
75
+ `**Country:** ${ station . country } ` ,
76
+ `**City:** ${ station . city } ` ,
77
+ `**Latitude:** ${ station . latitude } °` ,
78
+ `**Longitude:** ${ station . longitude } °` ,
79
+ `**Elevation:** ${ station . elevation_m } m/${ station . elevation_ft } ft` ,
80
+ '' ,
81
+ '**Runways (Length x Width):**' ,
82
+ `${ runwayIdents ? runwayIdents . toString ( ) . replace ( / , / g, '\n' ) : 'N/A' } ` ,
83
+ '' ,
84
+ `**Type:** ${ station . type . replace ( / _ / g, ' ' ) } ` ,
85
+ `**Website:** ${ station . website ?? 'N/A' } ` ,
86
+ `**Wiki:** ${ station . wiki ?? 'N/A' } ` ,
87
+ ] ) ,
88
+ footer : { text : 'Due to limitations of the API, not all links may be up to date at all times.' } ,
89
+ } ) ;
82
90
83
- return interaction . editReply ( { embeds : [ stationEmbed ] } ) ;
84
- } catch ( error ) {
85
- Logger . error ( 'station:' , error ) ;
86
- const fetchErrorEmbed = makeEmbed ( {
87
- title : 'Station Error | Fetch Error' ,
88
- description : 'There was an error fetching the station report. Please try again later.' ,
89
- color : Colors . Red ,
90
- } ) ;
91
- return interaction . editReply ( { embeds : [ fetchErrorEmbed ] } ) ;
92
- }
91
+ return interaction . editReply ( { embeds : [ stationEmbed ] } ) ;
93
92
} ) ;
0 commit comments