Security fixes (#32)

* Generic Object Injection Sink

* (fix) "Character" is not defined.

* added eslint

* improve code quality, use refactored function

* (fix) eslint jest

* "Character" is not defined

* removed unused file Compare.js

* (fix) PointsUsed is not defined

* (fix) eslint moans jsconfig

* turn off "no-prototype-builtins"

* push code coverage
This commit is contained in:
2021-05-01 20:13:15 +02:00
committed by GitHub
parent 63bd06e92f
commit d45e4faad6
20 changed files with 413 additions and 261 deletions

75
.eslintrc.json Normal file
View File

@ -0,0 +1,75 @@
{
"parserOptions": {
"ecmaVersion": 10,
"sourceType": "script",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"constructor-super": 2,
"for-direction": 2,
"getter-return": 2,
"no-async-promise-executor": 2,
"no-case-declarations": 2,
"no-class-assign": 2,
"no-compare-neg-zero": 2,
"no-cond-assign": 2,
"no-const-assign": 2,
"no-constant-condition": 2,
"no-control-regex": 2,
"no-debugger": 2,
"no-delete-var": 2,
"no-dupe-args": 2,
"no-dupe-class-members": 2,
"no-dupe-else-if": 2,
"no-dupe-keys": 2,
"no-duplicate-case": 2,
"no-empty": 2,
"no-empty-character-class": 2,
"no-empty-pattern": 2,
"no-ex-assign": 2,
"no-extra-boolean-cast": 2,
"no-extra-semi": 2,
"no-fallthrough": 2,
"no-func-assign": 2,
"no-global-assign": 2,
"no-import-assign": 2,
"no-inner-declarations": 2,
"no-invalid-regexp": 2,
"no-irregular-whitespace": 2,
"no-misleading-character-class": 2,
"no-mixed-spaces-and-tabs": 2,
"no-new-symbol": 2,
"no-obj-calls": 2,
"no-octal": 2,
"no-prototype-builtins": 0,
"no-redeclare": 2,
"no-regex-spaces": 2,
"no-self-assign": 2,
"no-setter-return": 2,
"no-shadow-restricted-names": 2,
"no-sparse-arrays": 2,
"no-this-before-super": 2,
"no-undef": 2,
"no-unexpected-multiline": 2,
"no-unreachable": 2,
"no-unsafe-finally": 2,
"no-unsafe-negation": 2,
"no-unused-labels": 2,
"no-unused-vars": 2,
"no-useless-catch": 2,
"no-useless-escape": 2,
"no-with": 2,
"require-yield": 2,
"use-isnan": 2,
"valid-typeof": 2
},
"env": {
"node": true,
"jest": true,
"commonjs": true,
"es2017": true
},
"extends": ["prettier"]
}

View File

@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.x, 14.x, 15.x]
node-version: [15.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v2
@ -30,6 +30,10 @@ jobs:
- run: npm ci
- run: npm run build --if-present
- run: npm test
- name: Run codacy-coverage-reporter
uses: codacy/codacy-coverage-reporter-action@v1
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
deploy:

View File

@ -1,6 +1,6 @@
# DSA Discord Bot
![GitHub package.json version](https://img.shields.io/github/package-json/v/TobenderZephyr/dsabot?style=flat-square) ![node-current](https://img.shields.io/node/v/discord.js?style=flat-square) ![GitHub last commit](https://img.shields.io/github/last-commit/TobenderZephyr/dsabot?style=flat-square) ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/TobenderZephyr/dsabot-docker/Build%20Image%20on%20Push/main?label=docker%20image&style=flat-square) ![Docker Pulls](https://img.shields.io/docker/pulls/tobenderzephyr/dsabot) [![CodeQL](https://github.com/TobenderZephyr/dsabot/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/TobenderZephyr/dsabot/actions/workflows/codeql-analysis.yml)
![GitHub package.json version](https://img.shields.io/github/package-json/v/TobenderZephyr/dsabot?style=flat-square) ![node-current](https://img.shields.io/node/v/discord.js?style=flat-square) ![GitHub last commit](https://img.shields.io/github/last-commit/TobenderZephyr/dsabot?style=flat-square) ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/TobenderZephyr/dsabot-docker/Build%20Image%20on%20Push/main?label=docker%20image&style=flat-square) ![Docker Pulls](https://img.shields.io/docker/pulls/tobenderzephyr/dsabot) [![CodeQL](https://github.com/TobenderZephyr/dsabot/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/TobenderZephyr/dsabot/actions/workflows/codeql-analysis.yml) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/565f705cf4a8403387b55c559a7bf5bc)](https://www.codacy.com/gh/TobenderZephyr/dsabot/dashboard?utm_source=github.com&utm_medium=referral&utm_content=TobenderZephyr/dsabot&utm_campaign=Badge_Grade)
This Project is a fork of LucaSchwan/dsa-bot.

View File

@ -139,7 +139,7 @@ it('should abort with a message: no entry found', () => {
};
const handleAttack = rewireUtils.__get__('handleAttack');
//expect(handleAttack(err)).toThrowError();
expect(handleAttack(null, [], { message: message })).toEqual(
expect(handleAttack([], { message: message })).toEqual(
'Sorry, für dich habe ich leider keinen Eintrag 😥'
);
});
@ -152,7 +152,7 @@ it('should abort with a message: No such weapon', () => {
};
const handleAttack = rewireUtils.__get__('handleAttack');
const args = [''];
expect(handleAttack(null, [{ character: {} }], { message: message, args: args })).toEqual(
expect(handleAttack([{ character: {} }], { message: message, args: args })).toEqual(
'Diese Waffe gibt es nicht.'
);
});
@ -178,9 +178,9 @@ it('complete run with melee weapon', () => {
};
const handleAttack = rewireUtils.__get__('handleAttack');
const args = ['messer'];
expect(
handleAttack(null, [{ character: character }], { message: message, args: args })
).toEqual(expect.any(String));
expect(handleAttack([{ character: character }], { message: message, args: args })).toEqual(
expect.any(String)
);
});
it('complete run with ranged weapon', () => {
@ -204,7 +204,7 @@ it('complete run with ranged weapon', () => {
};
const handleAttack = rewireUtils.__get__('handleAttack');
const args = ['langbogen'];
expect(
handleAttack(null, [{ character: character }], { message: message, args: args })
).toEqual(expect.any(String));
expect(handleAttack([{ character: character }], { message: message, args: args })).toEqual(
expect.any(String)
);
});

View File

@ -17,8 +17,17 @@ const TestValues = [
[13, 5],
[14, 5],
[15, 5],
[16, 6],
[17, 6],
[18, 6],
[19, 6],
[20, 6],
];
test.each(TestValues)('Retrieving Quality for %s', (input, output) => {
expect(CalculateQuality(input)).toBe(output);
});
it('should return 1 without input', () => {
expect(CalculateQuality()).toBe(1);
});

View File

@ -4,3 +4,7 @@ const { Capitalize } = require('@dsabot/Capitalize');
it('should capitalize the first letter.', () => {
expect(Capitalize('mother')).toBe('Mother');
});
it('should capitalize without any word given', () => {
expect(Capitalize()).toBe('None');
});

View File

@ -7,3 +7,13 @@ it('turn any number into a string', () => {
expect(f(0)).toBe('0');
expect(f(-1)).toBe('-1');
});
it('should return a string', () => {
const obj = {
Attributes: [8, 8, 8],
Throws: [7, 7, 7],
PointsUsed: [0, 0, 0],
Bonus: 0,
};
expect(CreateResultTable(obj)).toEqual(expect.any(String));
});

View File

@ -13,16 +13,21 @@ module.exports = {
async exec(message, args) {
try {
db.find({ user: message.author.tag }, (err, docs) =>
handleAttack(err, docs, { message: message, args: args })
);
db.find({ user: message.author.tag }, (err, docs) => {
if (err) {
message.reply(findMessage('ERROR'));
throw new Error(err);
}
handleAttack(docs, { message: message, args: args });
});
} catch (e) {
message.reply(findMessage('ERROR'));
throw e;
}
},
};
function handleAttack(err, docs, { message: message, args: args }) {
function handleAttack(docs, { message: message, args: args }) {
if (docs.length === 0) {
return message.reply(findMessage('NOENTRY'));
}

View File

@ -1,96 +1,116 @@
const globals = require('../globals');
const { CountOccurences } = require('@dsabot/CountOccurences');
const { findMessage } = require('@dsabot/findMessage');
const { CountOccurences } = require('@dsabot/CountOccurences');
const Random = require('random');
const db = globals.db;
module.exports = {
name: 'attribute',
description: '',
aliases: ['ap', 'ep'],
usage: '<Eigenschaft> / <Eigenschaftswert>',
needs_args: true,
async exec(message, args) {
try {
let Attribute;
let AttributeName;
let Level = 8;
await db.find({
user: message.author.tag,
}, async (err, docs) => {
name: 'attribute',
description: '',
aliases: ['ap', 'ep'],
usage: '<Eigenschaft> / <Eigenschaftswert>',
needs_args: true,
async exec(message, args) {
let Attribute;
let AttributeName;
let Level = 8;
await db.find(
{
user: message.author.tag,
},
async (err, docs) => {
// user calls with text, let's look him up in the database.
if (isNaN(args[0])) {
Attribute = HandleNamedAttributes({
Character: docs[0].character,
args: args,
});
AttributeName = Attribute.Name;
Level = Attribute.Level;
} else {
Level = args[0];
}
Random.use(message.author.tag);
// user calls with text, let's look him up in the database.
if (isNaN(args[0])) {
Attribute = HandleNamedAttributes({
Character: docs[0].character,
args: args
});
AttributeName = Attribute.Name;
Level = Attribute.Level;
} else {
Level = args[0];
}
Random.use(message.author.tag);
const dice = [];
dice.push(Random.int(1, 20));
if (dice[0] == 1 || dice[0] == 20) {
dice.push(Random.int(1, 20));
}
// handle crits
if (CountOccurences(dice, 1) == 2) {
message.reply('Du hast einen kritischen Erfolg erzielt (' + dice.join(', ') + ')! 🎉🥳🎆');
return;
} else if (CountOccurences(dice, 20) == 2) {
message.reply('Du hast einen Patzer (' + dice.join(', ') + ')! 😭 Viel Erfolg beim nächsten mal!');
return;
}
if ((dice.length == 2 && dice[0] != 20 && dice[1] <= Level) || (dice.length == 1 && dice[0] <= Level)) {
if (AttributeName) {
message.reply('Du hast die Probe auf ' + AttributeName + ' (Stufe ' + Level + ') bestanden.\n' +
'Deine 🎲: ' + dice.join(', '));
} else {
message.reply('Du hast die Probe (Stufe ' + Level + ') bestanden.\n' +
'Deine 🎲: ' + dice.join(', '));
}
} else if (AttributeName) {
message.reply('Du hast die Probe auf ' + AttributeName + ' (Stufe ' + Level + ') leider nicht bestanden 😢.\n' +
'Deine 🎲: ' + dice.join(', '));
} else {
message.reply('Du hast die Probe (Stufe ' + Level + ') leider nicht bestanden 😢.\n' +
'Deine 🎲: ' + dice.join(', '));
}
});
} catch (e) {
throw e;
}
},
const dice = [];
dice.push(Random.int(1, 20));
if (dice[0] === 1 || dice[0] === 20) {
dice.push(Random.int(1, 20));
}
// handle crits
if (CountOccurences(dice, 1) === 2) {
message.reply(
`Du hast einen kritischen Erfolg erzielt (${dice.join(', ')})! 🎉🥳🎆`
);
return;
} else if (CountOccurences(dice, 20) === 2) {
message.reply(
'Du hast einen Patzer (' +
dice.join(', ') +
')! 😭 Viel Erfolg beim nächsten mal!'
);
return;
}
if (
(dice.length == 2 && dice[0] != 20 && dice[1] <= Level) ||
(dice.length == 1 && dice[0] <= Level)
) {
if (AttributeName) {
message.reply(
'Du hast die Probe auf ' +
AttributeName +
' (Stufe ' +
Level +
') bestanden.\n' +
'Deine 🎲: ' +
dice.join(', ')
);
} else {
message.reply(
'Du hast die Probe (Stufe ' +
Level +
') bestanden.\n' +
'Deine 🎲: ' +
dice.join(', ')
);
}
} else if (AttributeName) {
message.reply(
'Du hast die Probe auf ' +
AttributeName +
' (Stufe ' +
Level +
') leider nicht bestanden 😢.\n' +
'Deine 🎲: ' +
dice.join(', ')
);
} else {
message.reply(
`Du hast die Probe (Stufe ${Level}) leider nicht bestanden 😢.\nDeine 🎲: ${dice.join(
', '
)}`
);
}
}
);
},
};
const HandleCrits = (dice) => {
function HandleNamedAttributes({ Character: Character = [], args: args = [] } = {}) {
let Attribute = getAttribute(args[0]);
let Level = getAttributeLevel(Character, Attribute) || 8;
};
return {
Name: Attribute.name,
Level: Level,
};
}
const HandleNamedAttributes = ({Character: Character = [], args: args = []} = {}) => {
function getAttributeLevel(Character = {}, Attribute = {}) {
return Character.attributes.find(attribute => attribute.id === Attribute.id).level;
}
let Attributes = globals.Werte;
let Level = 8; // This is the minimum attributes value.
let AttributeName;
let AttributeId;
if (args[0].length == 2) {
AttributeId = Attributes.find(attribute => attribute.kuerzel === args[0].toUpperCase()).id;
} else {
AttributeId = args[0].toLowerCase() ||
Attributes.find(attribute => attribute.name.toLowerCase() === args[0].toLowerCase()).id;
}
Level = Character.attributes.find(attribute => attribute.id === AttributeId).level;
AttributeName = Attributes.find(attribute => attribute.id === AttributeId).name;
return {
Name: AttributeName,
Level: Level
};
};
function getAttribute(attribute = '') {
return attribute.length === 2
? globals.Werte.find(a => a.kuerzel === attribute.toUpperCase())
: globals.Werte.find(a => a.name.toLowerCase() === attribute.toLowerCase());
}

View File

@ -16,7 +16,7 @@ module.exports = {
if (docs.length === 0) {
return message.reply(findMessage('NOENTRY'));
}
Character = docs[0].character;
const Character = docs[0].character;
if (!Character.hasOwnProperty('chants')) return message.reply(findMessage('NO_CHANTS'));
if (args.length === 0) {
const Embed = new Discord.MessageEmbed()

View File

@ -1,17 +1,21 @@
const { findMessage }= require('@dsabot/findMessage');
const { findMessage } = require('@dsabot/findMessage');
const globals = require('../globals');
const db = globals.db;
module.exports = {
name: 'remove',
description: 'Löscht deinen Charakter aus der Datenbank. Sinnvoll, wenn du mir eine neue zusenden möchtest.',
aliases: [],
usage: '',
needs_args: false,
async exec(message, args) {
db.remove({
user: message.author.tag,
}, {}, function(err, numRemoved) {
return message.reply(findMessage('DELETED_DATA'));
});
},
};
name: 'remove',
description:
'Löscht deinen Charakter aus der Datenbank. Sinnvoll, wenn du mir eine neue zusenden möchtest.',
aliases: [],
usage: '',
needs_args: false,
// eslint-disable-next-line no-unused-vars
async exec(message, args) {
db.remove({ user: message.author.tag }, err => {
if (err) {
message.reply(findMessage('ERROR'));
throw new Error(err);
}
return message.reply(findMessage('DELETED_DATA'));
});
},
};

View File

@ -2,40 +2,48 @@
const globals = require('../globals');
const Discord = require('discord.js');
const db = globals.db;
const { findMessage }= require('@dsabot/findMessage');
const { findMessage } = require('@dsabot/findMessage');
module.exports = {
name: 'show',
description: '',
aliases: [],
usage: '',
needs_args: false,
name: 'show',
description: '',
aliases: [],
usage: '',
needs_args: false,
async exec(message, args) {
try {
db.find({
user: message.author.tag,
}, function(err, docs) {
if (docs.length === 0) {
return message.reply(findMessage('NOENTRY'));
}
else {
const Character = docs[0].character;
let Gender;
if (Character.sex == 'female') { Gender = '♀️'; }
else { Gender = '♂️'; }
const Reply = new Discord.MessageEmbed();
Reply.setColor('#0099ff');
Reply.setTitle(`${Gender} ${Character.name}`);
Reply.setDescription(`${Character.age} Jahre, ${Character.race}/${Character.culture}`);
Reply.addField(Character.professionname, Character.xp.startinglevel);
message.reply( Reply );
}
});
}
catch (e) {
throw e;
}
},
};
// eslint-disable-next-line no-unused-vars
async exec(message, args) {
try {
db.find(
{
user: message.author.tag,
},
function (err, docs) {
if (docs.length === 0) {
return message.reply(findMessage('NOENTRY'));
} else {
const Character = docs[0].character;
let Gender;
if (Character.sex == 'female') {
Gender = '♀️';
} else {
Gender = '♂️';
}
const Reply = new Discord.MessageEmbed();
Reply.setColor('#0099ff');
Reply.setTitle(`${Gender} ${Character.name}`);
Reply.setDescription(
`${Character.age} Jahre, ${Character.race}/${Character.culture}`
);
Reply.addField(Character.professionname, Character.xp.startinglevel);
message.reply(Reply);
}
}
);
} catch (e) {
message.reply(findMessage('ERROR'));
throw e;
}
},
};

View File

@ -16,7 +16,7 @@ module.exports = {
if (docs.length === 0) {
return message.reply(findMessage('NOENTRY'));
}
Character = docs[0].character;
const Character = docs[0].character;
if (!Character.hasOwnProperty('spells')) return message.reply(findMessage('NO_SPELLS'));
if (args.length === 0) {
const Embed = new Discord.MessageEmbed()
@ -52,6 +52,8 @@ const ReplySpell = (Spell = {}) => {
const createSpellList = (Character = {}) => {
if (!Character || !Character.hasOwnProperty('spells')) return;
let SpellList = [];
Character.spells.forEach(spell => SpellList.push(getSpell({ Character: Character, spell_name: spell.id })));
Character.spells.forEach(spell =>
SpellList.push(getSpell({ Character: Character, spell_name: spell.id }))
);
return SpellList.filter(value => value !== undefined); //?+
};

View File

@ -1,85 +1,64 @@
// eslint-disable-next-line no-unused-vars
const Random = require('random');
const globals = require('../globals');
const Discord = require('discord.js');
const { roll } = require('@dsabot/Roll');
const { findMessage }= require('@dsabot/findMessage');
const { findMessage } = require('@dsabot/findMessage');
const { CompareResults } = require('@dsabot/CompareResults');
module.exports = {
name: 'tp',
description: 'Du machst eine Fertigkeitsprobe.\n' +
' Es werden drei Würfel auf deine Eigenschaftswerte geworfen. Hast du Boni auf dein Talent und/oder' +
' ist der Wurf erleichtert oder erschwert, wird dies in die Berechnung einbezogen.',
aliases: ['talentprobe'],
usage: '<Eigenschaftswert1> <Eigenschaftswert2> <Eigenschaftswert3> [<Fertigkeitswert>] [<-Erschwernis> / <+Erleichterung>]',
needs_args: true,
name: 'tp',
description:
'Du machst eine Fertigkeitsprobe.\n' +
' Es werden drei Würfel auf deine Eigenschaftswerte geworfen. Hast du Boni auf dein Talent und/oder' +
' ist der Wurf erleichtert oder erschwert, wird dies in die Berechnung einbezogen.',
aliases: ['talentprobe'],
usage:
'<Eigenschaftswert1> <Eigenschaftswert2> <Eigenschaftswert3> [<Fertigkeitswert>] [<-Erschwernis> / <+Erleichterung>]',
needs_args: true,
async exec(message, args) {
async exec(message, args) {
if (isNaN(args[0])) {
return message.reply(findMessage('WRONG_ARGUMENTS'));
}
if(isNaN(args[0])) {
return message.reply(findMessage('WRONG_ARGUMENTS'));
}
let Bonus = parseInt(args[3]) || 0;
let Erschwernis = parseInt(args[4]) || 0;
//Random.use(message.author.tag);
//const dice = [];
let bonus = 0;
let bonus_orig = 0;
let erschwernis = 0;
if (args[3]) {
bonus_orig = parseInt(args[3]);
bonus = bonus_orig;
}
if (args[4]) {
erschwernis = parseInt(args[4]);
}
/*for (let i = 1; i <= 3; i++) {
roll.push(Random.int(1, 20));
}*/
const dice = roll(3,20,message.author.tag).dice;
const dice = roll(3, 20, message.author.tag).dice;
let ok = 0;
let patzer = 0;
let crit = 0;
for (let i = 0; i < 3; i++) {
if (Math.floor(parseInt(args[i]) + parseInt(erschwernis)) >= dice[i]) {
ok++;
} else if (
Math.floor(parseInt(args[i]) + parseInt(bonus) + parseInt(erschwernis)) >= dice[i]) {
ok++;
bonus = bonus - (dice[i] - parseInt(erschwernis) - parseInt(args[i]));
}
if (dice[i] == 1) {crit++;}
if (dice[i] == 20) {patzer++;}
}
const {
Passed: Passed,
CriticalHit: CriticalHit,
Fumbles: Fumbles,
PointsRemaining: PointsRemaining} = CompareResults(dice, [args[0], args[1], args[2]], Bonus, Erschwernis);
const Reply = new Discord.MessageEmbed();
Reply.setTitle(`${findMessage('ROLL')} ${dice.join(', ')}.`);
if (patzer >= 2) {
Reply.setColor('#900c3f');
Reply.addFields({
name: findMessage('TITLE_CRIT_FAILURE'),
value: findMessage('MSG_CRIT_FAILURE'),
inline: false
});
} else if (crit >= 2) {
Reply.setColor('#1E8449');
Reply.addFields({
name: findMessage('TITLE_CRIT_SUCCESS'),
value: findMessage('MSG_CRIT_SUCCESS'),
inline: false
});
} else if (ok < 3) {
Reply.addFields({
name: findMessage('TITLE_FAILURE'),
value: 'Nur ' + ok + '/3 Proben erfolgreich. 😪',
inline: false
});
} else {
Reply.addFields({
name: findMessage('TITLE_SUCCESS'),
value: ok + '/3 Proben erfolgreich. Dein Bonus: ' + bonus + '/' + bonus_orig + '.',
inline: false
});
}
message.reply(Reply);
}
};
const Reply = new Discord.MessageEmbed();
Reply.setTitle(`${findMessage('ROLL')} ${dice.join(', ')}.`);
if (Fumbles >= 2) {
Reply.setColor('#900c3f');
Reply.addFields({
name: findMessage('TITLE_CRIT_FAILURE'),
value: findMessage('MSG_CRIT_FAILURE'),
inline: false,
});
} else if (CriticalHit >= 2) {
Reply.setColor('#1E8449');
Reply.addFields({
name: findMessage('TITLE_CRIT_SUCCESS'),
value: findMessage('MSG_CRIT_SUCCESS'),
inline: false,
});
} else if (Passed < 3) {
Reply.addFields({
name: findMessage('TITLE_FAILURE'),
value: `${Passed ? `Nur ${Passed}/3 Proben` : `Keine Probe`} erfolgreich. 😪`,
inline: false,
});
} else {
Reply.addFields({
name: findMessage('TITLE_SUCCESS'),
value: `${Passed}/3 Proben erfolgreich. Dein Bonus: ${PointsRemaining}/${Bonus}`,
inline: false,
});
}
message.reply(Reply);
},
};

View File

@ -1,15 +1,9 @@
const CalculateQuality = (PointsAvailable = 0) => {
if (PointsAvailable <= 3)
return 1;
else if (PointsAvailable > 3 && PointsAvailable <= 6)
return 2;
else if (PointsAvailable > 6 && PointsAvailable <= 9)
return 3;
else if (PointsAvailable > 9 && PointsAvailable <= 12)
return 4;
else if (PointsAvailable > 12 && PointsAvailable <= 15)
return 5;
else if (PointsAvailable > 15)
return 6;
if (PointsAvailable <= 3) return 1;
else if (PointsAvailable > 3 && PointsAvailable <= 6) return 2;
else if (PointsAvailable > 6 && PointsAvailable <= 9) return 3;
else if (PointsAvailable > 9 && PointsAvailable <= 12) return 4;
else if (PointsAvailable > 12 && PointsAvailable <= 15) return 5;
else return 6;
};
module.exports = { CalculateQuality };

View File

@ -1,6 +0,0 @@
const Compare = () => {
return { result };
};
module.exports = { Compare };

View File

@ -18,28 +18,28 @@ const CompareResults = (
let CriticalHit = 0;
let AllPointsUsed = [];
for (let i = 0; i < Throws.length; i++) {
Throws.forEach((Throw, key) => {
let PointsUsed = 0;
if (Math.floor(AttributeLevels[i] + Bonus) >= Throws[i]) {
let AttributeLevel = AttributeLevels.find((v, k) => key === k);
if (Math.floor(AttributeLevel + Bonus) >= Throw) {
Passed++;
} else if (Math.floor(AttributeLevels[i] + PointsRemaining + Bonus) >= Throws[i]) {
} else if (Math.floor(AttributeLevel + PointsRemaining + Bonus) >= Throw) {
Passed++;
PointsUsed = Throws[i] - Bonus - AttributeLevels[i];
PointsUsed = Throw - Bonus - AttributeLevel;
PointsRemaining -= PointsUsed;
} else {
// We need to use all our points, so that next die/dice
// would not return a 'Passed'.
PointsUsed = PointsRemaining;
PointsRemaining -= PointsUsed;
}
if (Throws[i] == 1) {
if (Throw === 1) {
CriticalHit++;
}
if (Throws[i] == 20) {
if (Throw === 20) {
Fumbles++;
}
AllPointsUsed.push(PointsUsed);
}
});
return {
Passed: Passed,
CriticalHit: CriticalHit,

View File

@ -7,10 +7,10 @@
"@data/*": ["./data/*"],
"@Commands/*": ["./commands/*"],
"@Lib/*": ["./lib/*"]
},
}
},
"exclude": ["node_modules"],
"typeAcquisition": {
"exclude": [ "dotenv", "source-map" ]
},
}
"exclude": ["dotenv", "source-map"]
}
}

45
package-lock.json generated
View File

@ -1,11 +1,11 @@
{
"name": "dsabot",
"version": "1.5.0",
"version": "1.5.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.5.0",
"version": "1.5.2",
"license": "ISC",
"dependencies": {
"discord.js": "^12.5.3",
@ -17,6 +17,8 @@
},
"devDependencies": {
"@types/jest": "^26.0.23",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.8.0",
"jest": "^26.6.3",
"rewire": "^5.0.0"
}
@ -2027,6 +2029,21 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint-config-prettier": {
"version": "6.8.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.8.0.tgz",
"integrity": "sha512-aq4M7mjjVregZ2l45O9qz6Mv6f5zVMl/IqfmUL8hNOoDAzVKYMhYPJytbqE/lPIVO1iMDXIFqjiEE59BfJZpZw==",
"dev": true,
"dependencies": {
"get-stdin": "^6.0.0"
},
"bin": {
"eslint-config-prettier-check": "bin/cli.js"
},
"peerDependencies": {
"eslint": ">=3.14.1"
}
},
"node_modules/eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@ -2857,6 +2874,15 @@
"node": ">=8.0.0"
}
},
"node_modules/get-stdin": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
"integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
@ -8924,6 +8950,15 @@
}
}
},
"eslint-config-prettier": {
"version": "6.8.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.8.0.tgz",
"integrity": "sha512-aq4M7mjjVregZ2l45O9qz6Mv6f5zVMl/IqfmUL8hNOoDAzVKYMhYPJytbqE/lPIVO1iMDXIFqjiEE59BfJZpZw==",
"dev": true,
"requires": {
"get-stdin": "^6.0.0"
}
},
"eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@ -9423,6 +9458,12 @@
"integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
"dev": true
},
"get-stdin": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
"integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
"dev": true
},
"get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",

View File

@ -6,7 +6,7 @@
"scripts": {
"lint": "eslint commands/",
"start": "node index.js",
"test": "jest"
"test": "jest --collectCoverage"
},
"_moduleAliases": {
"@dsabot": "functions",
@ -26,6 +26,8 @@
},
"devDependencies": {
"@types/jest": "^26.0.23",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.8.0",
"jest": "^26.6.3",
"rewire": "^5.0.0"
},
@ -35,6 +37,7 @@
"**/*.{js,jsx}",
"!**/node_modules/**",
"!**/vendor/**"
]
],
"coverageDirectory": "coverage"
}
}