Skip to content

Commit 8c79281

Browse files
committed
Error handling in menus
A system is developed that allows capturing and displaying errors on the screen/logs if they occur during the CLI menus.
1 parent ef7b744 commit 8c79281

File tree

14 files changed

+563
-351
lines changed

14 files changed

+563
-351
lines changed

lib/menus/about.js

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,65 @@
22
import { select } from '@inquirer/prompts';
33
import { splashLogo } from 'helpbot/loaders';
44

5+
// Stores the name of the menu
6+
const menuName = new URL(import.meta.url).pathname.split('/').pop().replace('.js', '');
7+
58
// Stores the translations of the bot
6-
const locale = client.locale.lib.menus.about;
9+
const locale = client.locale.lib.menus[menuName];
710

811
// Exports a default function
9-
export default async () => {
12+
export default async (beforeError) => {
1013

11-
// Cleans the console and shows the logo
12-
process.stdout.write('\u001b[2J\u001b[0;0H');
13-
await splashLogo(client.locale.lib.loaders.splashLogo);
14+
try {
1415

15-
// Shows a default text
16-
console.log('🚧 This section is currently under development.\n');
16+
// Cleans the console and shows the logo
17+
process.stdout.write('\u001b[2J\u001b[0;0H');
18+
await splashLogo(client.locale.lib.loaders.splashLogo);
19+
20+
// Shows an error message if one occurred
21+
if (beforeError) console.log(`❌ ${locale.errorMessage}.\n`);
22+
if (beforeError && process.env.NODE_ENV !== 'production') logger.error(`${beforeError.stack}\n`);
23+
24+
// Shows a default text
25+
console.log('🚧 This section is currently under development.\n');
26+
27+
// Shows the select menu
28+
global.currentPrompt = select({
29+
message: `${locale.promptMessage}:`,
30+
choices: [
31+
{
32+
name: `↩️ ${locale.choices.return}`,
33+
value: 'return'
34+
}
35+
],
36+
});
37+
38+
// When the user selects an option
39+
global.currentPrompt.then(async (result) => {
40+
41+
// When the user selects an option
42+
switch (result) {
43+
44+
// If the user wants to go back to the main menu
45+
case 'return':
46+
47+
// Shows the main menu
48+
await client.functions.menus.main();
49+
50+
// Breaks the switch
51+
break;
52+
};
1753

18-
// Shows the select menu
19-
global.currentPrompt = select({
20-
message: `${locale.promptMessage}:`,
21-
choices: [
22-
{
23-
name: `↩️ ${locale.choices.return}`,
24-
value: 'return'
25-
}
26-
],
27-
});
54+
// When an error occurs
55+
}).catch(async (error) => {
56+
57+
// Runs this menu again, passing the error
58+
await client.functions.menus[menuName](error);
59+
});
2860

29-
// When the user selects an option
30-
global.currentPrompt.then(async (result) => {
61+
} catch (error) {
3162

32-
// When the user selects an option
33-
switch (result) {
34-
35-
// If the user wants to go back to the main menu
36-
case 'return':
37-
38-
// Shows the main menu
39-
await client.functions.menus.main();
40-
41-
// Breaks the switch
42-
break;
43-
};
44-
});
63+
// Runs this menu again, passing the error
64+
await client.functions.menus[menuName](error);
65+
};
4566
};

lib/menus/baseGuildSelection.js

Lines changed: 79 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,85 +2,107 @@
22
import inquirer from 'inquirer';
33
import { splashLogo } from 'helpbot/loaders';
44

5+
// Stores the name of the menu
6+
const menuName = new URL(import.meta.url).pathname.split('/').pop().replace('.js', '');
7+
58
// Stores the translations of the bot
6-
const locale = client.locale.lib.menus.baseGuildSelection;
9+
const locale = client.locale.lib.menus[menuName];
710

811
// Exports a default function
9-
export default async (elegibleGuilds) => {
10-
11-
// Load the Id of the base guild
12-
const baseGuildId = await client.functions.db.getConfig('system.baseGuildId');
12+
export default async (elegibleGuilds, beforeError) => {
1313

14-
// Stores the Id of the base guild
15-
let newBaseGuildId = null;
14+
try {
15+
16+
// Load the Id of the base guild
17+
const baseGuildId = await client.functions.db.getConfig('system.baseGuildId');
1618

17-
// Function to ask for the new base guild
18-
async function promptBaseGuildSelection() {
19+
// Stores the Id of the base guild
20+
let newBaseGuildId = null;
1921

20-
// Cleans the console and shows the logo
21-
process.stdout.write('\u001b[2J\u001b[0;0H');
22-
await splashLogo(client.locale.lib.loaders.splashLogo);
22+
// Function to ask for the new base guild
23+
async function promptBaseGuildSelection() {
2324

24-
// Shows the help to choose a new base guild
25-
console.log(`🧹 ${locale.promptBaseGuildSelectionHeader1}.`);
26-
console.log(`👋 ${locale.promptBaseGuildSelectionHeader2}.\n`);
25+
// Cleans the console and shows the logo
26+
process.stdout.write('\u001b[2J\u001b[0;0H');
27+
await splashLogo(client.locale.lib.loaders.splashLogo);
28+
29+
// If an error ocurred on the previous run
30+
if (beforeError) {
2731

28-
// Generates the question of the base guild selector
29-
const questions = [
30-
{
31-
type: 'list',
32-
name: 'baseGuildId',
33-
message: `${locale.selectANewBaseGuild}:`,
34-
choices: elegibleGuilds.map(guild => ({ name: `${guild.name} (${guild.id})${guild.id === baseGuildId ? ` - ${locale.alreadyConfiguredGuild}` : ''}`, value: guild })),
35-
}
36-
];
32+
// Shows the error message
33+
console.log(`❌ ${locale.errorMessage}.\n`);
34+
if (beforeError && process.env.NODE_ENV !== 'production') logger.error(`${beforeError.stack}\n`);
3735

38-
// Asks for the base guild
39-
const { baseGuildId: newBaseGuild } = await inquirer.prompt(questions);
36+
// Resets the beforeError variable
37+
beforeError = false;
38+
};
4039

41-
// If the selected base guild is different from the currently configured
42-
if (baseGuildId && newBaseGuild.id !== baseGuildId) {
40+
// Shows the help to choose a new base guild
41+
console.log(`🧹 ${locale.promptBaseGuildSelectionHeader1}.`);
42+
console.log(`👋 ${locale.promptBaseGuildSelectionHeader2}.\n`);
4343

44-
// Asks the user if is sure to change the base guild
45-
const confirmation = await inquirer.prompt([
44+
// Generates the question of the base guild selector
45+
const questions = [
4646
{
47-
type: 'input',
48-
name: 'isSure',
49-
message: `${locale.isSureToReplaceBaseGuild} (${locale.affirmativeAnswer}/${locale.negativeAnswer}):`
47+
type: 'list',
48+
name: 'baseGuildId',
49+
message: `${locale.selectANewBaseGuild}:`,
50+
choices: elegibleGuilds.map(guild => ({ name: `${guild.name} (${guild.id})${guild.id === baseGuildId ? ` - ${locale.alreadyConfiguredGuild}` : ''}`, value: guild })),
5051
}
51-
]);
52+
];
53+
54+
// Asks for the base guild
55+
const { baseGuildId: newBaseGuild } = await inquirer.prompt(questions);
56+
57+
// If the selected base guild is different from the currently configured
58+
if (baseGuildId && newBaseGuild.id !== baseGuildId) {
59+
60+
// Asks the user if is sure to change the base guild
61+
const confirmation = await inquirer.prompt([
62+
{
63+
type: 'input',
64+
name: 'isSure',
65+
message: `${locale.isSureToReplaceBaseGuild} (${locale.affirmativeAnswer}/${locale.negativeAnswer}):`
66+
}
67+
]);
68+
69+
// Returns to the selector if the user is not sure
70+
if (locale.affirmativeAnswer !== confirmation.isSure.toLowerCase()) return promptBaseGuildSelection();
71+
};
5272

53-
// Returns to the selector if the user is not sure
54-
if (locale.affirmativeAnswer !== confirmation.isSure.toLowerCase()) return promptBaseGuildSelection();
73+
// Stores the new base guild Id
74+
newBaseGuildId = newBaseGuild.id;
75+
76+
// Cleans the console and shows the logo
77+
process.stdout.write('\u001b[2J\u001b[0;0H');
78+
await splashLogo(client.locale.lib.loaders.splashLogo);
5579
};
5680

57-
// Stores the new base guild Id
58-
newBaseGuildId = newBaseGuild.id;
81+
// Runs the base guild selector
82+
await promptBaseGuildSelection();
5983

60-
// Cleans the console and shows the logo
61-
process.stdout.write('\u001b[2J\u001b[0;0H');
62-
await splashLogo(client.locale.lib.loaders.splashLogo);
63-
};
84+
// For each guild in cache
85+
for (let guild of elegibleGuilds.values()) {
6486

65-
// Runs the base guild selector
66-
await promptBaseGuildSelection();
87+
// If the guild is the new base guild, omits
88+
if (guild.id === newBaseGuildId) continue;
6789

68-
// For each guild in cache
69-
for (let guild of elegibleGuilds.values()) {
90+
// Shows through the console the guild to leave
91+
logger.debug(`${await client.functions.utils.parseLocale(locale.leavingGuild, { guild: `"${guild.name}" (${guild.id})` })} ...`);
7092

71-
// If the guild is the new base guild, omits
72-
if (guild.id === newBaseGuildId) continue;
93+
// Leaves the guild
94+
await guild.leave();
7395

74-
// Shows through the console the guild to leave
75-
logger.debug(`${await client.functions.utils.parseLocale(locale.leavingGuild, { guild: `"${guild.name}" (${guild.id})` })} ...`);
96+
// Deletes the guild from the cachedGuilds variable
97+
elegibleGuilds.delete(guild.id);
98+
};
7699

77-
// Leaves the guild
78-
await guild.leave();
100+
// Returns the new eligible guilds object
101+
return elegibleGuilds;
79102

80-
// Deletes the guild from the cachedGuilds variable
81-
elegibleGuilds.delete(guild.id);
82-
};
103+
} catch (error) {
83104

84-
// Returns the new eligible guilds object
85-
return elegibleGuilds
105+
// Runs this menu again, passing the error
106+
await client.functions.menus[menuName](elegibleGuilds, error);
107+
};
86108
};

lib/menus/configure.js

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,65 @@
22
import { select } from '@inquirer/prompts';
33
import { splashLogo } from 'helpbot/loaders';
44

5+
// Stores the name of the menu
6+
const menuName = new URL(import.meta.url).pathname.split('/').pop().replace('.js', '');
7+
58
// Stores the translations of the bot
6-
const locale = client.locale.lib.menus.configure;
9+
const locale = client.locale.lib.menus[menuName];
710

811
// Exports a default function
9-
export default async () => {
12+
export default async (beforeError) => {
1013

11-
// Cleans the console and shows the logo
12-
process.stdout.write('\u001b[2J\u001b[0;0H');
13-
await splashLogo(client.locale.lib.loaders.splashLogo);
14+
try {
1415

15-
// Shows a default text
16-
console.log('🚧 This section is currently under development.\n');
16+
// Cleans the console and shows the logo
17+
process.stdout.write('\u001b[2J\u001b[0;0H');
18+
await splashLogo(client.locale.lib.loaders.splashLogo);
19+
20+
// Shows an error message if one occurred
21+
if (beforeError) console.log(`❌ ${locale.errorMessage}.\n`);
22+
if (beforeError && process.env.NODE_ENV !== 'production') logger.error(`${beforeError.stack}\n`);
23+
24+
// Shows a default text
25+
console.log('🚧 This section is currently under development.\n');
26+
27+
// Shows the select menu
28+
global.currentPrompt = select({
29+
message: `${locale.promptMessage}:`,
30+
choices: [
31+
{
32+
name: `↩️ ${locale.choices.return}`,
33+
value: 'return'
34+
}
35+
],
36+
});
37+
38+
// When the user selects an option
39+
global.currentPrompt.then(async (result) => {
40+
41+
// When the user selects an option
42+
switch (result) {
43+
44+
// If the user wants to go back to the main menu
45+
case 'return':
46+
47+
// Shows the main menu
48+
await client.functions.menus.main();
49+
50+
// Breaks the switch
51+
break;
52+
};
1753

18-
// Shows the select menu
19-
global.currentPrompt = select({
20-
message: `${locale.promptMessage}:`,
21-
choices: [
22-
{
23-
name: `↩️ ${locale.choices.return}`,
24-
value: 'return'
25-
}
26-
],
27-
});
54+
// When an error occurs
55+
}).catch(async (error) => {
56+
57+
// Runs this menu again, passing the error
58+
await client.functions.menus[menuName](error);
59+
});
2860

29-
// When the user selects an option
30-
global.currentPrompt.then(async (result) => {
61+
} catch (error) {
3162

32-
// When the user selects an option
33-
switch (result) {
34-
35-
// If the user wants to go back to the main menu
36-
case 'return':
37-
38-
// Shows the main menu
39-
await client.functions.menus.main();
40-
41-
// Breaks the switch
42-
break;
43-
};
44-
});
63+
// Runs this menu again, passing the error
64+
await client.functions.menus[menuName](error);
65+
};
4566
};

0 commit comments

Comments
 (0)