2022-06-23 00:32:51 +08:00
|
|
|
/* eslint-disable no-await-in-loop */
|
|
|
|
/* eslint import/no-unresolved: 0 */
|
|
|
|
|
|
|
|
import fs from 'fs';
|
|
|
|
import { Low, JSONFile } from 'lowdb';
|
|
|
|
import crypto from 'crypto';
|
|
|
|
import enquirerPkg from 'enquirer';
|
|
|
|
|
|
|
|
const {
|
|
|
|
Select,
|
|
|
|
Confirm,
|
|
|
|
Password,
|
|
|
|
Input,
|
|
|
|
} = enquirerPkg;
|
|
|
|
|
|
|
|
// required file paths
|
|
|
|
const SessionLocation = './session.key';
|
|
|
|
const SaltLocation = './salt.key';
|
|
|
|
const AppConfigLocation = './config.json';
|
|
|
|
|
2022-08-11 22:40:43 +08:00
|
|
|
const TripLength = 10;
|
|
|
|
|
2022-06-23 00:32:51 +08:00
|
|
|
// default configuration options
|
|
|
|
const defaultConfig = {
|
|
|
|
adminTrip: '',
|
|
|
|
globalMods: [],
|
|
|
|
publicChannels: [],
|
|
|
|
permissions: [],
|
|
|
|
};
|
|
|
|
|
|
|
|
// standard / default channel list
|
|
|
|
const defaultChannels = [
|
|
|
|
'lounge',
|
|
|
|
'meta',
|
|
|
|
'math',
|
|
|
|
'physics',
|
|
|
|
'chemistry',
|
|
|
|
'technology',
|
|
|
|
'programming',
|
|
|
|
'games',
|
|
|
|
'banana',
|
|
|
|
];
|
|
|
|
|
|
|
|
// load the configuration data
|
|
|
|
const adapter = new JSONFile(AppConfigLocation);
|
|
|
|
const config = new Low(adapter);
|
|
|
|
|
|
|
|
// check for missing cert, generate if needed
|
|
|
|
const checkCert = async () => {
|
|
|
|
if (fs.existsSync(SessionLocation) === false) {
|
|
|
|
const prompt = new Confirm({
|
|
|
|
name: 'certDialogue',
|
|
|
|
message: 'Missing session key, create new?',
|
|
|
|
});
|
|
|
|
|
|
|
|
if (await prompt.run() !== false) {
|
|
|
|
const data = crypto.randomBytes(4096);
|
|
|
|
|
|
|
|
fs.writeFile(SessionLocation, data, (err) => {
|
|
|
|
if (err) throw err;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
console.log('Found existing session key.');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// check for missing or uninitialized config
|
|
|
|
const checkConfig = async () => {
|
|
|
|
await config.read();
|
|
|
|
|
|
|
|
if (config.data === null) {
|
|
|
|
config.data = defaultConfig;
|
|
|
|
await config.write();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// check for missing or uninitialized salt
|
|
|
|
const checkTripSalt = async () => {
|
|
|
|
if (fs.existsSync(SaltLocation) === false) {
|
|
|
|
const prompt = new Confirm({
|
|
|
|
name: 'overwrite',
|
|
|
|
message: 'Missing trip salt, create new?',
|
|
|
|
});
|
|
|
|
|
|
|
|
if (await prompt.run() !== false) {
|
|
|
|
const data = crypto.randomBytes(4096);
|
|
|
|
|
|
|
|
fs.writeFileSync(SaltLocation, data);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
console.log('Found existing trip salt.');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// verify config has an admin account
|
|
|
|
const checkPermissions = async () => {
|
|
|
|
if (typeof config.data.adminTrip === 'undefined' || config.data.adminTrip === '') {
|
|
|
|
const salt = fs.readFileSync(SaltLocation);
|
|
|
|
|
|
|
|
const prompt = new Password({
|
|
|
|
name: 'adminPassword',
|
|
|
|
message: 'What is your admin password?',
|
|
|
|
});
|
|
|
|
|
|
|
|
const password = await prompt.run();
|
|
|
|
|
|
|
|
const sha = crypto.createHash('sha256');
|
|
|
|
sha.update(password + salt);
|
2022-08-11 22:40:43 +08:00
|
|
|
config.data.adminTrip = sha.digest('base64').substr(0, TripLength);
|
2022-06-23 00:32:51 +08:00
|
|
|
|
|
|
|
await config.write();
|
|
|
|
} else {
|
|
|
|
console.log(`Found admin trip: ${config.data.adminTrip}`);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// prompt user for a channel name
|
|
|
|
const getChannel = async () => {
|
|
|
|
const chanPrompt = new Input({
|
|
|
|
message: 'New channel name:',
|
|
|
|
});
|
|
|
|
|
|
|
|
const chan = await chanPrompt.run();
|
|
|
|
|
|
|
|
return chan;
|
|
|
|
};
|
|
|
|
|
|
|
|
// prompt user to save standard channels or input their own
|
|
|
|
const setupChannels = async () => {
|
|
|
|
const standardMode = 'Use standard channels';
|
|
|
|
const manualMode = 'Manual input';
|
|
|
|
const modePrompt = new Select({
|
|
|
|
name: 'mode',
|
|
|
|
message: 'How would you like to setup the public channels?',
|
|
|
|
choices: [
|
|
|
|
standardMode,
|
|
|
|
manualMode,
|
|
|
|
],
|
|
|
|
});
|
|
|
|
|
|
|
|
const mode = await modePrompt.run();
|
|
|
|
|
|
|
|
if (mode === standardMode) {
|
|
|
|
config.data.publicChannels = defaultChannels;
|
|
|
|
|
|
|
|
await config.write();
|
|
|
|
} else {
|
|
|
|
const channels = [];
|
|
|
|
let newChannel = '';
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
console.log('(Leave blank to finish) Channels:', channels.join(', '));
|
|
|
|
newChannel = await getChannel();
|
|
|
|
|
|
|
|
if (newChannel === '') {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
channels.push(newChannel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
config.data.publicChannels = channels;
|
|
|
|
|
|
|
|
await config.write();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// check if pulic channels have been initialized
|
|
|
|
const checkPublicChannels = async () => {
|
|
|
|
if (typeof config.data.publicChannels === 'undefined' || config.data.publicChannels.length === 0) {
|
|
|
|
const prompt = new Confirm({
|
|
|
|
name: 'addChannels',
|
|
|
|
message: 'Missing public channels, setup now?',
|
|
|
|
});
|
|
|
|
|
|
|
|
if (await prompt.run() !== false) {
|
|
|
|
await setupChannels();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
console.log('Found existing public channels.');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// start checking
|
|
|
|
await checkCert();
|
|
|
|
await checkConfig();
|
|
|
|
await checkTripSalt();
|
|
|
|
await checkPermissions();
|
|
|
|
await checkPublicChannels();
|
|
|
|
|
|
|
|
// done!
|
|
|
|
console.log('Config completed!');
|