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

CLI for .env #516

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
101 changes: 55 additions & 46 deletions bot.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,56 @@
require("dotenv").config();
require("module-alias/register");

// register extenders
require("@helpers/extenders/Message");
require("@helpers/extenders/Guild");
require("@helpers/extenders/GuildChannel");

const { checkForUpdates } = require("@helpers/BotUtils");
const { initializeMongoose } = require("@src/database/mongoose");
const { BotClient } = require("@src/structures");
const { validateConfiguration } = require("@helpers/Validator");

validateConfiguration();

// initialize client
const client = new BotClient();
client.loadCommands("src/commands");
client.loadContexts("src/contexts");
client.loadEvents("src/events");

// find unhandled promise rejections
process.on("unhandledRejection", (err) => client.logger.error(`Unhandled exception`, err));

(async () => {
// check for updates
await checkForUpdates();

// start the dashboard
if (client.config.DASHBOARD.enabled) {
client.logger.log("Launching dashboard");
try {
const { launch } = require("@root/dashboard/app");

// let the dashboard initialize the database
await launch(client);
} catch (ex) {
client.logger.error("Failed to launch dashboard", ex);
const fs = require("fs");
const { generateEnvFile } = require("./scripts/setup");

// Check if .env file exists
if (!fs.existsSync(".env")) {
generateEnvFile();
} else {
// .env file exists, proceed with dotenv config
require("dotenv").config();
require("module-alias/register");

// Register extenders
require("@helpers/extenders/Message");
require("@helpers/extenders/Guild");
require("@helpers/extenders/GuildChannel");

const { checkForUpdates } = require("@helpers/BotUtils");
const { initializeMongoose } = require("@src/database/mongoose");
const { BotClient } = require("@src/structures");
const { validateConfiguration } = require("@helpers/Validator");

validateConfiguration();

// Initialize client
const client = new BotClient();
client.loadCommands("src/commands");
client.loadContexts("src/contexts");
client.loadEvents("src/events");

// Find unhandled promise rejections
process.on("unhandledRejection", (err) => client.logger.error(`Unhandled exception`, err));

(async () => {
// Check for updates
await checkForUpdates();

// Start the dashboard
if (client.config.DASHBOARD.enabled) {
client.logger.log("Launching dashboard");
try {
const { launch } = require("@root/dashboard/app");

// Let the dashboard initialize the database
await launch(client);
} catch (ex) {
client.logger.error("Failed to launch dashboard", ex);
}
} else {
// Initialize the database
await initializeMongoose();
}
} else {
// initialize the database
await initializeMongoose();
}

// start the client
await client.login(process.env.BOT_TOKEN);
})();

// Start the client
await client.login(process.env.BOT_TOKEN);
})();
}
147 changes: 147 additions & 0 deletions scripts/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
const readline = require("readline");
const fs = require("fs");

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

function generateEnvFile () {
console.log("Welcome to the Strange Bot setup!\n");
console.log(
"Here are some tutorials to get you started:\nMongoDB connection URL: https://www.youtube.com/watch?v=nv38zCeFBHg\nBot Token: https://www.youtube.com/watch?v=aI4OmIbkJH8\nWebhook URL: https://www.youtube.com/watch?v=fKksxz2Gdnc\nBot Secret: https://support.heateor.com/discord-client-id-discord-client-secret/\nWeatherstack API Key: https://weatherstack.com/signup/free\nStrange API Key: https://strangeapi.hostz.me/dashboard\nSpotify Client ID and Secret: https://www.youtube.com/watch?v=WHugvJ0YR5I\n"
);
console.log("Please provide the following information (* means required) - right click in the console to paste:\n");

let envData = {};

function askDatabaseUrl () {
rl.question("Enter your MongoDB connection URL*: ", (dbUrl) => {
const mongoUrlRegex = /^mongodb\+srv:\/\//;
if (mongoUrlRegex.test(dbUrl)) {
envData["MONGO_CONNECTION"] = dbUrl;
askBotToken();
} else {
console.log("Invalid MongoDB URL format. Please enter a valid MongoDB URL. Tutorials are above.");
askDatabaseUrl();
}
});
}

function askBotToken () {
rl.question("Enter your bot token*: ", (botToken) => {
if (botToken.trim().length >= 40) {
envData["BOT_TOKEN"] = botToken;
askWebhookErrors();
} else {
console.log("Invalid bot token. Please enter a valid token. Tutorials are above.");
askBotToken();
}
});
}

function askWebhookErrors () {
rl.question("Enter the Webhook URL for error logs: ", (errLogs) => {
const webhookUrlRegex = /^https:\/\/discord\.com\/api\/webhooks/;
if (webhookUrlRegex.test(errLogs)) {
envData["ERROR_LOGS"] = errLogs;
askWebhookJoinLeave();
} else {
console.log("Invalid Webhook URL format. Please enter a valid Webhook URL. Tutorials are above.");
askWebhookErrors();
}
});
}

function askWebhookJoinLeave () {
rl.question("Enter the Webhook URL for join/leave logs: ", (joinLeaveLogs) => {
const webhookUrlRegex = /^https:\/\/discord\.com\/api\/webhooks/;
if (webhookUrlRegex.test(joinLeaveLogs)) {
envData["JOIN_LEAVE_LOGS"] = joinLeaveLogs;
askBotSecret();
} else {
console.log("Invalid Webhook URL format. Please enter a valid Webhook URL. Tutorials are above.");
askWebhookJoinLeave();
}
});
}

function askBotSecret () {
rl.question("Enter your bot secret - Required for dashboard: ", (botSecret) => {
if (botSecret.trim().length >= 20) {
envData["BOT_SECRET"] = botSecret;
askWeatherstackApiKey();
} else {
console.log("Bot secret is not valid. Please enter a valid secret. Tutorials are above.");
askBotSecret();
}
});
}

function askWeatherstackApiKey () {
rl.question("Enter your Weatherstack API key - Required for Weather Command: ", (weatherStackKey) => {
if (weatherStackKey.trim().length >= 20) {
envData["WEATHERSTACK_KEY"] = weatherStackKey;
askStrangeApiKey();
} else {
console.log("Weatherstack API key is not valid. Please enter a valid key. Tutorials are above.");
askWeatherstackApiKey();
}
});
}

function askStrangeApiKey () {
rl.question("Enter your Strange API key - Required for image commands: ", (strangeApiKey) => {
if (strangeApiKey.trim().length >= 30) {
envData["STRANGE_API_KEY"] = strangeApiKey;
askSpotifyClientId();
} else {
console.log("Strange API key must be valid. Please enter a valid key. Tutorials are above.");
askStrangeApiKey();
}
});
}

function askSpotifyClientId () {
rl.question("Enter your Spotify Client ID - Required for Spotify Support: ", (spotifyClientId) => {
if (spotifyClientId.trim().length >= 25) {
envData["SPOTIFY_CLIENT_ID"] = spotifyClientId;
askSpotifyClientSecret();
} else {
console.log(
"Spotify Client ID must be at least 25 characters long. Please enter a valid ID. Tutorials are above."
);
askSpotifyClientId();
}
});
}

function askSpotifyClientSecret () {
rl.question("Enter your Spotify Client Secret - Required for Spotify Support: ", (spotifyClientSecret) => {
if (spotifyClientSecret.trim().length >= 25) {
envData["SPOTIFY_CLIENT_SECRET"] = spotifyClientSecret;
writeEnvFile();
} else {
console.log("Spotify Client Secret is not valid. Please enter a valid Secret. Tutorials are above.");
askSpotifyClientSecret();
}
});
}

function writeEnvFile () {
fs.writeFileSync(
".env",
Object.entries(envData)
.map(([key, value]) => `${key}=${value}`)
.join("\n")
);
console.log("Setup success!");
rl.close();
}

askDatabaseUrl();
}

module.exports = {
generateEnvFile,
};