Skip to content

Commit 6a8cbbb

Browse files
migrate wolfram alpha cmd to zod
1 parent b6c70a8 commit 6a8cbbb

File tree

3 files changed

+109
-57
lines changed

3 files changed

+109
-57
lines changed

src/commands/utils/wolframAlpha.ts

Lines changed: 58 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { ApplicationCommandOptionType, ApplicationCommandType, Colors } from 'discord.js';
2-
import { slashCommand, slashCommandStructure, makeEmbed, makeLines, Logger } from '../../lib';
2+
import { Request } from 'node-fetch';
3+
import { z, ZodError } from 'zod';
4+
import { fetchData, Logger, makeEmbed, makeLines, slashCommand, slashCommandStructure, WolframAlphaData, WolframAlphaDataSchema, WolframAlphaPodSchema, WolframAlphaSubpodSchema } from '../../lib';
5+
6+
type Pod = z.infer<typeof WolframAlphaPodSchema>;
7+
type Subpod = z.infer<typeof WolframAlphaSubpodSchema>;
38

49
const data = slashCommandStructure({
510
name: 'wolframalpha',
@@ -19,6 +24,12 @@ const noQueryEmbed = makeEmbed({
1924
color: Colors.Red,
2025
});
2126

27+
const errorEmbed = (errorMessage: string) => makeEmbed({
28+
title: 'Wolfram Alpha Error',
29+
description: errorMessage,
30+
color: Colors.Red,
31+
});
32+
2233
const WOLFRAMALPHA_API_URL = 'https://api.wolframalpha.com/v2/query?';
2334
const WOLFRAMALPHA_QUERY_URL = 'https://www.wolframalpha.com/input/?';
2435

@@ -33,12 +44,12 @@ export default slashCommand(data, async ({ interaction }) => {
3344
description: 'Wolfram Alpha token not found.',
3445
color: Colors.Red,
3546
});
36-
return interaction.followUp({ embeds: [noTokenEmbed], ephemeral: true });
47+
return interaction.editReply({ embeds: [noTokenEmbed] });
3748
}
3849

3950
const query = interaction.options.getString('query');
4051

41-
if (!query) return interaction.followUp({ embeds: [noQueryEmbed], ephemeral: true });
52+
if (!query) return interaction.editReply({ embeds: [noQueryEmbed] });
4253

4354
const params = {
4455
appid: wolframAlphaToken,
@@ -49,72 +60,62 @@ export default slashCommand(data, async ({ interaction }) => {
4960

5061
const searchParams = new URLSearchParams(params);
5162

63+
let response: WolframAlphaData;
5264
try {
53-
const response = await fetch(`${WOLFRAMALPHA_API_URL}${searchParams.toString()}`)
54-
.then((res) => res.json());
55-
56-
if (response.error) {
57-
const errorEmbed = makeEmbed({
58-
title: 'Wolfram Alpha Error',
59-
description: response.error,
60-
color: Colors.Red,
61-
});
62-
return interaction.followUp({ embeds: [errorEmbed], ephemeral: true });
65+
response = await fetchData<WolframAlphaData>(new Request(`${WOLFRAMALPHA_API_URL}${searchParams.toString()}`), WolframAlphaDataSchema);
66+
} catch (e) {
67+
if (e instanceof ZodError) {
68+
return interaction.editReply({ embeds: [errorEmbed('Wolfram Alpha returned unknown data.')] });
6369
}
70+
Logger.error(`Error while fetching from Wolfram Alpha: ${String(e)}`);
71+
return interaction.editReply({ embeds: [errorEmbed('An error occurred while fetching from Wolfram Alpha.')] });
72+
}
6473

65-
if (response.queryresult.success === true) {
66-
const podTexts: string[] = [];
67-
response.queryresult.pods.forEach((pod: any) => {
68-
if (pod.id !== 'Input' && pod.primary === true) {
69-
const results: string[] = [];
70-
pod.subpods.forEach((subpod: any) => {
71-
results.push(subpod.plaintext);
72-
});
73-
if (results.length > 0) {
74-
podTexts.push(`**${pod.title}:** \n${results.join('\n')}`);
75-
}
76-
}
77-
});
78-
if (podTexts.length > 0) {
79-
const result = podTexts.join('\n\n');
80-
const queryParams = new URLSearchParams({ i: query });
81-
82-
const waEmbed = makeEmbed({
83-
description: makeLines([
84-
`**Query:** ${query}`,
85-
'',
86-
result,
87-
'',
88-
`[Web Result](${WOLFRAMALPHA_QUERY_URL}${queryParams.toString()})`,
89-
]),
74+
if (response.queryresult.success === true) {
75+
const podTexts: string[] = [];
76+
response.queryresult.pods.forEach((pod: Pod) => {
77+
if (pod.id !== 'Input' && pod.primary === true) {
78+
const results: string[] = [];
79+
pod.subpods.forEach((subpod: Subpod) => {
80+
results.push(subpod.plaintext);
9081
});
91-
92-
return interaction.followUp({ embeds: [waEmbed] });
82+
if (results.length > 0) {
83+
podTexts.push(`**${pod.title}:** \n${results.join('\n')}`);
84+
}
9385
}
94-
const noResultsEmbed = makeEmbed({
95-
title: 'Wolfram Alpha Error | No Results',
86+
});
87+
if (podTexts.length > 0) {
88+
const result = podTexts.join('\n\n');
89+
const queryParams = new URLSearchParams({ i: query });
90+
91+
const waEmbed = makeEmbed({
9692
description: makeLines([
97-
'No results were found for your query.',
93+
`**Query:** ${query}`,
94+
'',
95+
result,
96+
'',
97+
`[Web Result](${WOLFRAMALPHA_QUERY_URL}${queryParams.toString()})`,
9898
]),
99-
color: Colors.Red,
10099
});
101-
return interaction.followUp({ embeds: [noResultsEmbed], ephemeral: true });
100+
101+
return interaction.editReply({ embeds: [waEmbed] });
102102
}
103-
const obscureQueryEmbed = makeEmbed({
104-
title: 'Wolfram Alpha Error | Could not understand query',
103+
const noResultsEmbed = makeEmbed({
104+
title: 'Wolfram Alpha Error | No Results',
105105
description: makeLines([
106-
'Wolfram Alpha could not understand your query.',
106+
'No results were found for your query.',
107107
]),
108108
color: Colors.Red,
109109
});
110-
return interaction.followUp({ embeds: [obscureQueryEmbed], ephemeral: true });
111-
} catch (e) {
112-
Logger.error('wolframalpha:', e);
113-
const fetchErrorEmbed = makeEmbed({
114-
title: 'Wolfram Alpha | Fetch Error',
115-
description: 'There was an error fetching your request. Please try again later.',
116-
color: Colors.Red,
117-
});
118-
return interaction.followUp({ embeds: [fetchErrorEmbed], ephemeral: true });
110+
return interaction.editReply({ embeds: [noResultsEmbed] });
119111
}
112+
113+
const obscureQueryEmbed = makeEmbed({
114+
title: 'Wolfram Alpha Error | Could not understand query',
115+
description: makeLines([
116+
'Wolfram Alpha could not understand your query.',
117+
]),
118+
color: Colors.Red,
119+
});
120+
return interaction.editReply({ embeds: [obscureQueryEmbed] });
120121
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { z } from 'zod';
2+
3+
export const WolframAlphaErrorSchema = z.object({
4+
code: z.number(),
5+
msg: z.string(),
6+
});
7+
8+
export const WolframAlphaSubpodSchema = z.object({
9+
title: z.string(),
10+
plaintext: z.string({ message: 'Only appears if the requested result formats include plain text.' }),
11+
});
12+
13+
export const WolframAlphaPodSchema = z.object({
14+
title: z.string(),
15+
error: z.union([z.boolean(), WolframAlphaErrorSchema]),
16+
position: z.number(),
17+
scanner: z.string(),
18+
id: z.string(),
19+
numsubpods: z.number(),
20+
primary: z.optional(z.boolean()),
21+
subpods: z.array(WolframAlphaSubpodSchema),
22+
});
23+
24+
const BaseQueryResultSchema = z.object({
25+
error: z.union([z.boolean(), WolframAlphaErrorSchema]),
26+
numpods: z.number(),
27+
version: z.string(),
28+
datatypes: z.string(),
29+
timing: z.number(),
30+
timedout: z.union([z.string(), z.number()]),
31+
parsetiming: z.number(),
32+
parsetimedout: z.boolean(),
33+
recalculate: z.string(),
34+
});
35+
36+
const SuccessQueryResultSchema = BaseQueryResultSchema.extend({
37+
success: z.literal(true),
38+
pods: z.array(WolframAlphaPodSchema),
39+
});
40+
41+
const NoSuccessQueryResultSchema = BaseQueryResultSchema.extend({ success: z.literal(false) });
42+
43+
export const WolframAlphaQueryResultSchema = z.discriminatedUnion('success', [SuccessQueryResultSchema, NoSuccessQueryResultSchema]);
44+
45+
export const WolframAlphaDataSchema = z.object({ queryresult: WolframAlphaQueryResultSchema });
46+
47+
/**
48+
* This type only includes currently used properties. If you wish to extend its functionality, add the relevant schemas in this file.
49+
*/
50+
export type WolframAlphaData = z.infer<typeof WolframAlphaDataSchema>;

src/lib/index.ts

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

0 commit comments

Comments
 (0)