Browse Source

Adhere to TS and Markdown Style Guidelines (#46)

* Update package.json

* Adhere to Markdown and TS Style Guidelines

* Adhere to ESLint

* Some more edits to adhere to the ESLint standard

* style: modify slightly to adhere to ESLint spec

Co-authored-by: Piyush Acharya <acharyapiyush1@outlook.com>

Co-authored-by: Abheek <abheekd@protonmail.com>
pull/48/head
Piyush Acharya 2 years ago
committed by GitHub
parent
commit
b0763f7524
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 110
      .eslintrc.json
  2. 2
      .github/CODE_OF_CONDUCT.md
  3. 16
      .github/CONTRIBUTING.md
  4. 16
      .github/workflows/codeql.yml
  5. 10
      .github/workflows/eslint.yml
  6. 4
      .github/workflows/release.yml
  7. 27
      README.md
  8. 26
      docker-compose.yml
  9. 2
      package.json
  10. 4
      src/commands/about.ts
  11. 3
      src/commands/help.ts
  12. 21
      src/commands/rounds.ts
  13. 7
      src/commands/score.ts
  14. 30
      src/commands/settings.ts
  15. 6
      src/commands/top.ts
  16. 43
      src/commands/train.ts
  17. 18
      src/deploy-commands.js
  18. 14
      src/helpers/db.ts
  19. 21
      src/helpers/util/pagination.ts
  20. 203
      tsconfig.json

110
.eslintrc.json

@ -10,44 +10,110 @@
"node": true,
"es6": true
},
"ignorePatterns": ["src/deploy-commands.js"],
"ignorePatterns": [
"src/deploy-commands.js"
],
"rules": {
"arrow-spacing": ["error", { "before": true, "after": true }],
"brace-style": ["error", "stroustrup", { "allowSingleLine": true }],
"comma-dangle": ["error", "always-multiline"],
"arrow-spacing": [
"error",
{
"before": true,
"after": true
}
],
"brace-style": [
"error",
"stroustrup",
{
"allowSingleLine": true
}
],
"comma-dangle": [
"error",
"always-multiline"
],
"comma-spacing": "error",
"comma-style": "error",
"curly": ["error", "multi-line", "consistent"],
"dot-location": ["error", "property"],
"curly": [
"error",
"multi-line",
"consistent"
],
"dot-location": [
"error",
"property"
],
"handle-callback-err": "off",
"indent": ["error", "tab"],
"indent": [
"error",
"tab"
],
"keyword-spacing": "error",
"max-nested-callbacks": ["error", { "max": 4 }],
"max-statements-per-line": ["error", { "max": 2 }],
"max-nested-callbacks": [
"error",
{
"max": 4
}
],
"max-statements-per-line": [
"error",
{
"max": 2
}
],
"no-console": "off",
"no-empty-function": "error",
"no-floating-decimal": "error",
"no-lonely-if": "error",
"no-multi-spaces": "error",
"no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }],
"no-shadow": ["error", { "allow": ["err", "resolve", "reject"] }],
"no-trailing-spaces": ["error"],
"no-multiple-empty-lines": [
"error",
{
"max": 2,
"maxEOF": 1,
"maxBOF": 0
}
],
"no-shadow": [
"error",
{
"allow": [
"err",
"resolve",
"reject"
]
}
],
"no-trailing-spaces": [
"error"
],
"no-var": "error",
"object-curly-spacing": ["error", "always"],
"object-curly-spacing": [
"error",
"always"
],
"prefer-const": "error",
"quotes": ["error", "single"],
"semi": ["error", "always"],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
],
"space-before-blocks": "error",
"space-before-function-paren": ["error", {
"anonymous": "never",
"named": "never",
"asyncArrow": "always"
}],
"space-before-function-paren": [
"error",
{
"anonymous": "never",
"named": "never",
"asyncArrow": "always"
}
],
"space-in-parens": "error",
"space-infix-ops": "error",
"space-unary-ops": "error",
"spaced-comment": "error",
"yoda": "error"
}
}
}

2
.github/CODE_OF_CONDUCT.md

@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within

16
.github/CONTRIBUTING.md

@ -1,22 +1,32 @@
# Contributing
## Cloning for Contribution
To set up the development environment to make changes to the code, clone the repo, install dependencies, and run it directly with `node` as Docker doesn't expose as much.
To set up the development environment to make changes to the code, clone the repo, install dependencies, and run it
directly with `node` as Docker doesn't expose as much.
## Making Changes
To edit the code please keep a few things in mind:
1. Be able to explain changes you make; they should be legible and understandable.
2. Please try to abide by ESLint's rules, setting up ESLint is quite easy to do and not too difficult to follow.
## Testing Your Code
For testing, make sure to set up the prerequisites:
1. MongoDB: have a MongoDB server set up.
2. Environment Variables: take a look at the `docker-compose.yml` for examples.
Once that's done, you can run `yarn tsc` or `npx tsc` to build to JavaScript in the `built` directory. Here you'll find `deploy-commands.js` which you need to deploy the slash commands, and `index.js` which you can run to start the bot.
Once that's done, you can run `yarn tsc` or `npx tsc` to build to JavaScript in the `built` directory. Here you'll
find `deploy-commands.js` which you need to deploy the slash commands, and `index.js` which you can run to start the
bot.
## Submitting Your Contribution
Creating a PR is easy enough and there are plenty of tutorials to do so. When contributing, please make sure to highlight and explain your change, with any import information additionally included.
Creating a PR is easy enough and there are plenty of tutorials to do so. When contributing, please make sure to
highlight and explain your change, with any import information additionally included.
---

16
.github/workflows/codeql.yml

@ -13,13 +13,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Checkout repository
uses: actions/checkout@v2
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: 'javascript'
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: 'javascript'
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

10
.github/workflows/eslint.yml

@ -11,8 +11,8 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install modules
run: yarn
- name: Run ESLint
run: yarn run lint
- uses: actions/checkout@v2
- name: Install modules
run: yarn
- name: Run ESLint
run: yarn run lint

4
.github/workflows/release.yml

@ -23,7 +23,7 @@ jobs:
uses: docker/metadata-action@v3
with:
images: adawesomeguy/awesomescibo
- name: Build and push
uses: docker/build-push-action@v2
with:
@ -51,7 +51,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:

27
README.md

@ -1,4 +1,3 @@
![logo](https://user-images.githubusercontent.com/67982792/160637166-b8c3a390-e4f9-46d1-8738-dcb2d8b9baa7.png)
<h1 align="center">AwesomeSciBo</h1>
@ -16,23 +15,35 @@
<p align="center">Open-source Discord bot that aims to aid up-and-coming Scibowlers with randomly generated (non-stock) rounds and training. It has many features, including subject-targeted training, a cross-server leaderboard, and a plethora of slash commands!</p>
## Deployment
Deploying this bot to your Discord server is relatively simple: you can add it to your own server by using [this link](https://adat.link/awesomescibo).
Deploying this bot to your Discord server is relatively simple: you can add it to your own server by
using [this link](https://adat.link/awesomescibo).
## Contributing
Please see [CONTRIBUTING.md](https://github.com/ADawesomeguy/AwesomeSciBo/blob/master/.github/CONTRIBUTING.md).
Please see [CONTRIBUTING.md](https://github.com/ADawesomeguy/AwesomeSciBo/blob/master/.github/CONTRIBUTING.md).
## Installation
There are basically two ways to install it:
### Method 1 (Node):
After cloning the repository, dependencies can be installed with `yarn` or `npm i`. The bot can then be compile to JavaScript with `yarn tsc` or `npx tsc`, and will be deployed in the `built/` directory. Finally, the bot can be run by entering said directory and running `./index.js` or `node index.js`.
### Method 1 (Node):
### Method 2 (Docker):
This bot has a Dockerfile within the repository which can be built using `docker build . -t [tag]`. Alternatively and preferably, the image can be taken from [DockerHub](https://hub.docker.com/r/adawesomeguy/awesomescibo).
After cloning the repository, dependencies can be installed with `yarn` or `npm i`. The bot can then be compile to
JavaScript with `yarn tsc` or `npx tsc`, and will be deployed in the `built/` directory. Finally, the bot can be run by
entering said directory and running `./index.js` or `node index.js`.
### Method 2 (Docker):
This bot has a Dockerfile within the repository which can be built using `docker build . -t [tag]`. Alternatively and
preferably, the image can be taken from [DockerHub](https://hub.docker.com/r/adawesomeguy/awesomescibo).
## Usage
This bot uses slash commands now :). You can just click on the bot icon after typing `/` to see a list of commands.
## Credit
The bot was made by [@ADawesomeguy](https://github.com/ADawesomeguy). However, the API was made by [@CQCumbers](https://github.com/CQCumbers). Go give [his API](https://github.com/CQCumbers/ScibowlDB) a star, he totally deserves it!
The bot was made by [@ADawesomeguy](https://github.com/ADawesomeguy). However, the API was made
by [@CQCumbers](https://github.com/CQCumbers). Go give [his API](https://github.com/CQCumbers/ScibowlDB) a star, he
totally deserves it!

26
docker-compose.yml

@ -1,17 +1,17 @@
# Use root/example as user/password credentials
version: '3.1'
services:
mongo:
image: mongo:4.4
restart: always
volumes:
- ./data:/data/db
mongo:
image: mongo:4.4
restart: always
volumes:
- ./data:/data/db
awesomescibo:
image: docker.io/adawesomeguy/awesomescibo:latest
restart: unless-stopped
environment:
MONGO_URI: "mongodb://mongo:27017/AWESOME"
TOKEN: ""
CLIENT_ID: ""
TESTING_GUILD: ""
awesomescibo:
image: docker.io/adawesomeguy/awesomescibo:latest
restart: unless-stopped
environment:
MONGO_URI: "mongodb://mongo:27017/AWESOME"
TOKEN: ""
CLIENT_ID: ""
TESTING_GUILD: ""

2
package.json

@ -31,4 +31,4 @@
"author": "Abheek Dhawan",
"license": "MIT",
"description": "A simple Discord bot that automatically generates Science Bowl rounds using the ScibowlDB API!"
}
}

4
src/commands/about.ts

@ -11,11 +11,11 @@ export const data = new SlashCommandBuilder()
.setName('about')
.setDescription('Commands regarding the creation/development of the bot');
export async function execute(interaction : CommandInteraction) {
export async function execute(interaction: CommandInteraction) {
await interaction.deferReply();
const client = interaction.client;
const embeds : MessageEmbed[] = [];
const embeds: MessageEmbed[] = [];
const contributorEmbed = new MessageEmbed().setTitle('Contributors')
.addField('Creator', '<@745063586422063214> [ADawesomeguy#3602]', true)

3
src/commands/help.ts

@ -5,7 +5,8 @@ export const data = new SlashCommandBuilder()
.setName('help')
.setDescription('Replies with a help message explaining what the bot can do');
export async function execute(interaction : CommandInteraction) {
export async function execute(interaction: CommandInteraction) {
await interaction.deferReply();
await interaction.deferReply();
const helpEmbed = new MessageEmbed()

21
src/commands/rounds.ts

@ -28,20 +28,20 @@ export const data = new SlashCommandBuilder()
return subcommand;
});
export async function execute(interaction : CommandInteraction) {
export async function execute(interaction: CommandInteraction) {
const action = interaction.options.getSubcommand();
switch (action) {
case 'generate': {
interaction.deferReply({ ephemeral: true });
let finalizedHTML = '<html><head><link rel=\'preconnect\' href=\'https://fonts.gstatic.com\'><link href=\'https://fonts.googleapis.com/css2?family=Ubuntu&display=swap\' rel=\'stylesheet\'> </head><body style=\'width: 70%; margin-left: auto; margin-right: auto;\'><h2 style=\'text-align: center; text-decoration: underline overline; padding: 7px;\'>ROUND GENERATED BY AWESOMESCIBO USING THE SCIBOWLDB API</h2>';
let tossup_question : string;
let question_category : string;
let tossup_format : string;
let tossup_answer : string;
let bonus_question : string;
let bonus_format : string;
let bonus_answer : string;
let tossup_question: string;
let question_category: string;
let tossup_format: string;
let tossup_answer: string;
let bonus_question: string;
let bonus_format: string;
let bonus_answer: string;
let htmlContent = '';
await axios.post('https://scibowldb.com/api/questions', { categories: ['BIOLOGY', 'PHYSICS', 'CHEMISTRY', 'EARTH AND SPACE', 'ASTRONOMY', 'MATH'] })
.then((response) => {
@ -72,7 +72,10 @@ export async function execute(interaction : CommandInteraction) {
log({ logger: 'rounds', content: `Saving round to DB failed: ${err}`, level: 'error' });
return;
}
interaction.followUp({ content: `Here's your round: https://api.adawesome.tech/round/${round._id.toString()}`, ephemeral: true });
interaction.followUp({
content: `Here's your round: https://api.adawesome.tech/round/${round._id.toString()}`,
ephemeral: true,
});
});
});
break;

7
src/commands/score.ts

@ -16,7 +16,7 @@ export const data = new SlashCommandBuilder()
return option;
});
export async function execute(interaction : CommandInteraction) {
export async function execute(interaction: CommandInteraction) {
const scoreEmbed = new MessageEmbed()
.setColor('#ffffff');
@ -27,7 +27,10 @@ export async function execute(interaction : CommandInteraction) {
}
if (!score) {
await interaction.reply({ content: 'Unfortunately, that user does not seem to have used AwesomeSciBo yet.', ephemeral: true });
await interaction.reply({
content: 'Unfortunately, that user does not seem to have used AwesomeSciBo yet.',
ephemeral: true,
});
return;
}

30
src/commands/settings.ts

@ -26,7 +26,7 @@ export const data = new SlashCommandBuilder()
return subcommand;
});
export async function execute(interaction : CommandInteraction) {
export async function execute(interaction: CommandInteraction) {
const action = interaction.options.getSubcommand();
switch (action) {
case 'display': {
@ -70,7 +70,11 @@ export async function execute(interaction : CommandInteraction) {
const vals = dispChoice.values;
const config = await userConfig.findById(interaction.user.id);
if (!config) {
await interaction.editReply({ content: 'You don\'t have a configuration!', embeds: [], components: [] });
await interaction.editReply({
content: 'You don\'t have a configuration!',
embeds: [],
components: [],
});
}
else if (vals.length === 1 && vals.at(0) === 'subjects') {
await interaction.editReply({
@ -138,7 +142,10 @@ export async function execute(interaction : CommandInteraction) {
.then(async lvlChoice => {
const vals = lvlChoice.values;
const levels = new Array<string>();
await userConfig.findOneAndUpdate({ _id: interaction.user.id }, { gradeLevels: vals }, { upsert: true, new: true });
await userConfig.findOneAndUpdate({ _id: interaction.user.id }, { gradeLevels: vals }, {
upsert: true,
new: true,
});
await vals.forEach(v => {
switch (v) {
case 'MS':
@ -148,7 +155,11 @@ export async function execute(interaction : CommandInteraction) {
levels.push('High School');
}
});
await interaction.editReply({ content: `Level set to: ${levels.toString().split(',').join(', ')}`, embeds: [], components: [] });
await interaction.editReply({
content: `Level set to: ${levels.toString().split(',').join(', ')}`,
embeds: [],
components: [],
});
});
}));
break;
@ -219,12 +230,19 @@ export async function execute(interaction : CommandInteraction) {
(subjectMsg as Message).awaitMessageComponent({ filter: subjectFilter, componentType: 'SELECT_MENU' })
.then(async subjectChoice => {
const vals = subjectChoice.values;
await userConfig.findOneAndUpdate({ _id: interaction.user.id }, { subjects: vals }, { upsert: true, new: true });
await userConfig.findOneAndUpdate({ _id: interaction.user.id }, { subjects: vals }, {
upsert: true,
new: true,
});
const subjects = new Array<string>();
await vals.forEach(v => {
subjects.push(v.toLowerCase().split(' ').map(w => w[0].toUpperCase() + w.substring(1)).join(' '));
});
await interaction.editReply({ content: `Subjects set to: ${subjects.toString().split(',').join(', ')}`, components: [], embeds: [] });
await interaction.editReply({
content: `Subjects set to: ${subjects.toString().split(',').join(', ')}`,
components: [],
embeds: [],
});
});
}));
break;

6
src/commands/top.ts

@ -8,7 +8,7 @@ export const data = new SlashCommandBuilder()
.setName('top')
.setDescription('Lists top ten scores across servers (server specific leaderboard WIP)');
export async function execute(interaction : CommandInteraction) {
export async function execute(interaction: CommandInteraction) {
await interaction.deferReply();
userScore
@ -21,13 +21,13 @@ export async function execute(interaction : CommandInteraction) {
}
if (obj.length < 10) {
// Need at least 10 scores for top 10
// Need at least 10 scores for top 10
return interaction.followUp(
`There are only ${obj.length} users, we need at least 10!`,
);
}
const embeds : MessageEmbed[] = [];
const embeds: MessageEmbed[] = [];
let lbMessageContent = '';
for (let i = 0; i < 10; i++) {

43
src/commands/train.ts

@ -31,7 +31,7 @@ export const data = new SlashCommandBuilder()
return option;
});
export async function execute(interaction : CommandInteraction) {
export async function execute(interaction: CommandInteraction) {
await interaction.deferReply();
const subject = interaction.options.get('subject') ? interaction.options.get('subject')?.value : null;
@ -44,23 +44,26 @@ export async function execute(interaction : CommandInteraction) {
if (!obj) {
score = 0;
const firstTimeEmbed = new MessageEmbed()
.setAuthor({ name: interaction.client.user?.tag ? interaction.client.user?.tag : '', iconURL: interaction.client.user?.displayAvatarURL() })
.setAuthor({
name: interaction.client.user?.tag ? interaction.client.user?.tag : '',
iconURL: interaction.client.user?.displayAvatarURL(),
})
.setDescription('Hey! It seems like it\'s your first time using AwesomeSciBo. Here\'s some information regarding the bot if you need it (for issues, contributions, etc.):')
.addField('Creator', '<@745063586422063214> [@abheekd#3602]')
.addField('GitHub', '[Link](https://github.com/ADawesomeguy/AwesomeSciBo) (a star couldn\'t hurt...)')
.setColor('#ffffff')
.setTimestamp();
interaction.user.send({ embeds: [firstTimeEmbed] });
}
}
else if (obj) {
score = obj.score;
}
}
else {
log({ logger: 'train', content: `Getting user score failed: ${err}`, level: 'error' });
}
});
let categoryArray : string[] = [];
let categoryArray: string[] = [];
const allCategories = ['BIOLOGY', 'PHYSICS', 'CHEMISTRY', 'EARTH AND SPACE', 'ASTRONOMY', 'MATH'];
const configCategories = await userConfig.findById(interaction.user.id);
@ -142,7 +145,7 @@ export async function execute(interaction : CommandInteraction) {
let predicted = '';
if (answerMsg?.content.toLowerCase() === tossupAnswer.toLowerCase() || answers.includes(answerMsg?.content.toUpperCase())) {
predicted = 'correct';
}
}
else {
predicted = 'incorrect';
}
@ -151,10 +154,13 @@ export async function execute(interaction : CommandInteraction) {
updateScore(true, score, authorId).then((msgToReply) =>
answerMsg?.reply(msgToReply),
);
}
}
else {
const overrideEmbed = new MessageEmbed()
.setAuthor({ name: answerMsg?.author.tag ? answerMsg.author.tag : '', iconURL: answerMsg?.author.displayAvatarURL() })
.setAuthor({
name: answerMsg?.author.tag ? answerMsg.author.tag : '',
iconURL: answerMsg?.author.displayAvatarURL(),
})
.addField('Correct answer', `\`${tossupAnswer}\``)
.setDescription('It seems your answer was incorrect. Please react with <:override:955265585086857236> to override your answer if you think you got it right.')
.setColor('#ffffff')
@ -174,7 +180,7 @@ export async function execute(interaction : CommandInteraction) {
const overrideFilter = i => {
return (
['override'].includes(i.customId) &&
i.user.id === answerMsg.author.id
i.user.id === answerMsg.author.id
);
};
overrideMsg
@ -186,8 +192,16 @@ export async function execute(interaction : CommandInteraction) {
await i.reply(msgToReply);
overrideMsg.edit({ components: [] });
});
}).catch(err => log({ logger: 'train', content: `Failed to override score: ${err}`, level: 'error' }));
}).catch(err => log({ logger: 'train', content: `Failed to send override message: ${err}`, level: 'error' }));
}).catch(err => log({
logger: 'train',
content: `Failed to override score: ${err}`,
level: 'error',
}));
}).catch(err => log({
logger: 'train',
content: `Failed to send override message: ${err}`,
level: 'error',
}));
}
interaction.editReply({ components: [sourceButton] });
}).catch(err => log({ logger: 'train', content: `${err}`, level: 'error' }));
@ -221,10 +235,13 @@ export async function execute(interaction : CommandInteraction) {
updateScore(true, score, authorId).then((msgToReply) =>
mcChoice.reply(msgToReply),
);
}
}
else {
const incorrectEmbed = new MessageEmbed()
.setAuthor({ name: interaction.user.tag, iconURL: interaction.user.displayAvatarURL() })
.setAuthor({
name: interaction.user.tag,
iconURL: interaction.user.displayAvatarURL(),
})
.addField('Correct answer', `\`${tossupAnswer}\``)
.setDescription(`It seems your answer ${mcChoice.customId.toUpperCase()} was incorrect.`)
.setColor('#ffffff')

18
src/deploy-commands.js

@ -1,20 +1,20 @@
#!/usr/bin/env node
const fs = require('node:fs');
const { REST } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v9');
const { clientId, token } = require('./helpers/env');
const {REST} = require('@discordjs/rest');
const {Routes} = require('discord-api-types/v9');
const {clientId, token} = require('./helpers/env');
const commands = [];
const commandFiles = fs.readdirSync(__dirname + '/commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`${__dirname}/commands/${file}`);
commands.push(command.data.toJSON());
const command = require(`${__dirname}/commands/${file}`);
commands.push(command.data.toJSON());
}
const rest = new REST({ version: '9' }).setToken(token);
const rest = new REST({version: '9'}).setToken(token);
rest.put(Routes.applicationCommands(clientId), { body: commands })
.then(() => console.log('Successfully registered application commands.'))
.catch(console.error);
rest.put(Routes.applicationCommands(clientId), {body: commands})
.then(() => console.log('Successfully registered application commands.'))
.catch(console.error);

14
src/helpers/db.ts

@ -3,10 +3,10 @@ import mongoose from 'mongoose';
import log from '../helpers/log';
import userScore from '../models/userScore';
export async function updateScore(isCorrect : boolean, score : number, authorId : string) {
export async function updateScore(isCorrect: boolean, score: number, authorId: string) {
if (!isCorrect) {
return `Nice try! Your score is still ${score}.`;
}
}
else {
// TODO: Error handling
const doc = await userScore.findOne({
@ -20,12 +20,12 @@ export async function updateScore(isCorrect : boolean, score : number, authorId
newUserScore.save(err => {
if (err) {
log({ logger: 'db', content: `Error creating new user ${authorId} for scoring`, level: 'error' });
}
}
else {
log({ logger: 'db', content: `Successfully created user ${authorId} for scoring`, level: 'debug' });
}
});
}
}
else {
doc.score = doc.score + 4;
doc.save();
@ -42,6 +42,10 @@ export async function connect(mongoUri) {
useNewUrlParser: true,
})
.then(() => log({ logger: 'db', content: `Connected to the database at ${mongoUri}!`, level: 'info' }))
.catch(err => log({ logger: 'db', content: `Failed to connect to the database at ${mongoUri}: ${err}`, level: 'fatal' }));
.catch(err => log({
logger: 'db',
content: `Failed to connect to the database at ${mongoUri}: ${err}`,
level: 'fatal',
}));
}

21
src/helpers/util/pagination.ts

@ -1,6 +1,6 @@
import { CommandInteraction, Message, MessageActionRow, MessageButton, MessageEmbed } from 'discord.js';
export async function paginateMessage(message : Message, embeds : MessageEmbed[]) {
export async function paginateMessage(message: Message, embeds: MessageEmbed[]) {
let index = 0;
const row = new MessageActionRow;
@ -19,7 +19,10 @@ export async function paginateMessage(message : Message, embeds : MessageEmbed[]
.then(async paginatorMessage => {
const filter = m => m.author.id === message.author.id;
const paginatorCollector = paginatorMessage.createMessageComponentCollector({ componentType: 'BUTTON', filter: filter });
const paginatorCollector = paginatorMessage.createMessageComponentCollector({
componentType: 'BUTTON',
filter: filter,
});
paginatorCollector.on('collect', async i => {
switch (i.customId) {
@ -37,7 +40,7 @@ export async function paginateMessage(message : Message, embeds : MessageEmbed[]
});
}
export async function paginateInteraction(interaction : CommandInteraction, embeds : MessageEmbed[]) {
export async function paginateInteraction(interaction: CommandInteraction, embeds: MessageEmbed[]) {
let index = 0;
const row = new MessageActionRow;
@ -52,12 +55,20 @@ export async function paginateInteraction(interaction : CommandInteraction, embe
.setStyle('SECONDARY')
);
await interaction.followUp({ content: `Page 1 of ${embeds.length}:`, embeds: [embeds[index]], components: [row], fetchReply: true })
await interaction.followUp({
content: `Page 1 of ${embeds.length}:`,
embeds: [embeds[index]],
components: [row],
fetchReply: true,
})
.then(async p => {
const paginatorMessage = p as Message;
const filter = i => i.user.id === interaction.user.id;
const paginatorCollector = paginatorMessage.createMessageComponentCollector({ componentType: 'BUTTON', filter: filter });
const paginatorCollector = paginatorMessage.createMessageComponentCollector({
componentType: 'BUTTON',
filter: filter,
});
paginatorCollector.on('collect', async i => {
switch (i.customId) {

203
tsconfig.json

@ -1,101 +1,104 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
"incremental": true, /* Enable incremental compilation */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "resolveJsonModule": true, /* Enable importing .json files */
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
"outDir": "./built", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
"incremental": true,
/* Enable incremental compilation */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2016",
/* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "commonjs",
/* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "node",
/* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "resolveJsonModule": true, /* Enable importing .json files */
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
"allowJs": true,
/* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
"outDir": "./built",
/* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true,
/* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true,
/* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true,
/* Enable all strict type-checking options. */
"noImplicitAny": false,
/* Enable error reporting for expressions and declarations with an implied `any` type.. */
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true
/* Skip type checking all .d.ts files. */
}
}
Loading…
Cancel
Save