Merge development into master (#5)

* fixing typos

* merge Dynamic commands (#3)

* Update README.md

* Update README.md

* fixing typos

* dynamically read new commands inside folder.

* eslint, update package.json due to moving files

Co-authored-by: Marcus Netz <marcus.netz@godyo.com>

* fix talent checking on empty arguments list

* Origin/message embed (#4)

* add first embedded message on tp.js

* move db from message commands

* fix missing arguments list, add need_args

* add global Message Replies.

* add more global Message Replies.

* more embedded messages. fixing string

* missing comma

* adding a few more strings on talents.

Co-authored-by: Marcus Netz <marcus.netz@godyo.com>

* fixing creating from json file

* bugfix: db not defined

* possible  fix for nonworking talent?

* fix double msg

* fix: aliases are now being used

* change: show command displays now some character attributes

* added various aliases to commands, added global strings.

Co-authored-by: Marcus Netz <marcus.netz@godyo.com>
This commit is contained in:
2020-12-16 08:53:09 +01:00
committed by GitHub
parent 0ac4fe4d04
commit c179bdd0e0
32 changed files with 710 additions and 655 deletions

View File

@ -18,15 +18,17 @@ Send the user a simple command list with things to do.
This command can be used to roll dice. To use it one has to put in the number of dice to use as the *x* and the number of sides as the *y* in between those Numbers stands W/D which simply means dice(D) or the german word "Würfel" (W). Theoretically it doesn't matter what Letter is in between but for roleplay gamers this should feel natural.
ie `!roll 3w20`
### !heads
Throw a coin. Heads or Tails?
## Tracking System
As this Bot should help with tracking your character, simply attach your .tda file in a private message.
As this Bot should help with tracking your character, simply attach your .tdc file in a private message.
### !ep / !ap [Value]
Probes on your attributes.
Rolls 1 dice and compares it with the given value. Rolls another, if returned number is 1 or 20.
Rolls 1 die and compares it with the given value. Rolls another, if returned number is 1 or 20.
ie `!ep 11`
@ -39,7 +41,7 @@ ie. `!ep Mut` or `!ep KK`
Returns the current level of the desired skill.
### !talent [skillname] ([-Disadvantages/+Advantages])
Rolls 3 dice and compares the results with your current level of character attributes including your bonus on that particular skill.
Rolls 3 dice and compares the results of each with your current level of character attributes including your bonus on that particular skill.
`caution`: It does not yet make use of any benefits or disadvantages your character has (at the moment).
ie. `!talent klettern -2`
@ -53,7 +55,7 @@ Sends the User a list of talents to use on the `!talent` command.
### !tp [attribute1] [attribute2] [attribute3] ([bonus] [-Disadvantage/+Advantages])
This command also rolls 3 dice and compares their values with entered arguments.
This one is better suited for people, who did not provide a `.tda`-File or if one of the other numerous Advantages and/or Disadvantages need to be considered aswell.
This one is better suited for people, who did not provide a `.tdc`-File or if one of the other numerous Advantages and/or Disadvantages need to be taken into account.
Roll with no Bonus:
`!tp 11 11 13`

17
commands/HeadsOrTails.js Normal file
View File

@ -0,0 +1,17 @@
const globals = require('../globals');
const Random = require('random');
module.exports = {
name: 'kopf',
description: 'Wirf eine Münze. Kopf oder Zahl?',
aliases: ['zahl', 'heads', 'tails'],
usage: '',
needs_args: false,
async exec(message, args) {
Random.use(message.author.tag);
const coin = Random.int(0, 1);
message.reply('Die Münze bleibt auf **' + globals.Coin[coin] + '** liegen.');
},
};

48
commands/add.js Normal file
View File

@ -0,0 +1,48 @@
const globals = require('../globals')
const db = globals.db
module.exports = {
name: 'add',
description: '',
aliases: [],
usage: '',
needs_args: true,
async exec(message, args) {
try {
console.log(message.author.tag + ': ' + args);
if (!isNaN(args[0])) {
message.reply(args[1]);
console.log('1: ' + args[1] + ', 2: ' + args[2]);
const money = ['gold', 'silver', 'bronce', 'iron', 'hp'];
db.find({
user: message.author.tag,
}, function(err, docs) {
gold = docs[0].gold;
silver = docs[0].silver;
bronce = docs[0].bronce;
iron = docs[0].iron;
hp = docs[0].hp;
});
db.update({
user: message.author.tag,
}, {
gold: gold,
silver: silver,
bronce: bronce,
iron: iron,
hp: hp,
}, function(err, docs) {
if (!docs.length > 0) {
message.reply('Sorry, Für dich habe ich keinen Eintrag 😥');
return;
}
message.reply(`ich habe ${args[2]} zu ${args[1]} hinzugefügt.`);
});
}
}
catch (e) {
throw e;
}
},
};

86
commands/attribute.js Normal file
View File

@ -0,0 +1,86 @@
const globals = require('../globals');
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 level = 8;
let attributename;
await db.find({
user: message.author.tag,
}, async function(err, docs) {
// user calls with text. need to gather info from database
if (isNaN(args[0])) {
if (!docs.length > 0) {
message.reply(globals.Replies.find(r => r.id === 'NOENTRY').string);
return;
}
else {
// try to get id of short formatted attributes.
if (args[0].length == 2) {
for (const i in globals.Werte) {
if (globals.Werte[i].kuerzel == args[0].toUpperCase()) {
attributename = globals.Werte[i].id;
}
}
}
else {
attributename = args[0].toLowerCase();
}
for (const i in docs[0].character.attributes) {
if (docs[0].character.attributes[i].id == attributename) level = docs[0].character.attributes[i].level;
}
}
}
else {
level = args[0];
}
Random.use(message.author.tag);
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
const dice = [];
dice.push(Random.int(1, 20));
if (dice[0] == 1 || dice[0] == 20) {
dice.push(Random.int(1, 20));
}
// handle crits
if (countOccurrences(dice, 1) == 2) {
message.reply('Du hast einen kritischen Erfolg erzielt (' + dice.join(', ') + ')! 🎉🥳🎆');
return;
}
else if (countOccurrences(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;
}
},
};

68
commands/help.js Normal file
View File

@ -0,0 +1,68 @@
const Discord = require('discord.js');
const cmdprefix = process.env.CMDPREFIX || '!';
module.exports = {
name: 'help',
description: '',
aliases: ['hilfe'],
usage: '',
needs_args: false,
async exec(message, args) {
const Help = new Discord.MessageEmbed()
.setColor('#0099ff')
.setTitle('Hilfe')
.setDescription('Das sind die Befehle, die du verwenden kannst.\n' +
'Werte in Klammern müssen nicht mit angegeben werden.')
.addFields({
name: cmdprefix + 'kopf',
value: 'Wirf eine Münze. Kopf oder Zahl?',
inline: false,
}, {
name: cmdprefix + 'roll <Anzahl> W <Augenzahl>',
value: 'Lass die Würfel rollen. Benötigt wird die Anzahl sowie die Augenzahl auf den Würfeln.',
inline: false,
}, {
name: cmdprefix + 'ep/ap <Eigenschaftswert>',
value: ' Du machst eine Eigenschaftsprobe / Attributprobe.\n' +
' Du würfelst mit einem W20 auf deinen Eigenschaftswert.\n' +
' Bei einer 1 oder 20 wird der Bestätigungswurf ausgeführt.',
inline: false,
}, {
name: cmdprefix + 'tp/fp <Eigenschaftswert1> <Eigenschaftswert2> <Eigenschaftswert3> (Fertigkeitswert) (+Erleichtert/-Erschwert)',
value: ' 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.',
inline: false,
}, {
name: cmdprefix + 'talents',
value: ' Du erhälst eine Liste mit den Talentnamen, die du für ' +
cmdprefix + 'talent/' + cmdprefix + 'skill nutzen kannst.',
inline: false,
}, {
name: '\u200B',
value: '\u200B',
}, {
name: '\u200B',
value: 'Wenn du mir deine .tdc Datei zusendest, kannst du folgendes nutzen:',
}, {
name: cmdprefix + 'ep/ap [Klugheit] oder ' + cmdprefix + 'ep/ap [FF]',
value: 'siehe oben. Du brauchst deinen Wert nicht wissen.',
inline: false,
}, {
name: cmdprefix + 'talent <Talentname> (+Erleichtert/-Erschwert)',
value: 'siehe tp. Allerdings musst du deine Werte nicht wissen.',
inline: false,
}, {
name: cmdprefix + 'skill <Talentname>',
value: 'Zeigt dir deinen Fertigkeitswert im jeweiligen Talent.',
inline: false,
}, {
name: cmdprefix + 'remove',
value: 'Löscht deinen Charakter aus der Datenbank. Sinnvoll, wenn du mir eine neue zusenden möchtest.',
inline: false,
});
message.author.send(Help);
},
};

16
commands/remove.js Normal file
View File

@ -0,0 +1,16 @@
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) {
message.reply(globals.Replies.find(x => x.id === 'DELETED_DATA').string);
});
},
};

36
commands/roll.js Normal file
View File

@ -0,0 +1,36 @@
// eslint-disable-next-line no-unused-vars
const globals = require('../globals');
const Random = require('random');
module.exports = {
name: 'roll',
description: 'Lass die Würfel rollen. Benötigt wird die Anzahl sowie die Augenzahl auf den Würfeln.',
aliases: ['r'],
usage: '<Anzahl> w <Augenzahl>',
needs_args: true,
async exec(message, args) {
Random.use(message.author.tag);
let msg;
let arguments = args.join('');
arguments = arguments.split(globals.DiceRegex);
if (arguments.length == 2) {
const numberOfDice = parseInt(arguments[0]);
const diceValues = parseInt(arguments[1]);
console.log(diceValues)
const roll = [];
for (let i = 0; i < numberOfDice; i++) {
const a = Random.int(1, diceValues);
roll.push(a);
}
if (numberOfDice == 1) {
msg = 'n';
}
else {
msg = ' ' + numberOfDice;
}
message.reply('Das sind deine Ergebnisse für deine' + msg + ' ' + diceValues + '-seitigen 🎲: ' + roll.join(', ') + '.');
}
},
};

39
commands/show.js Normal file
View File

@ -0,0 +1,39 @@
// eslint-disable-next-line no-unused-vars
const globals = require('../globals')
const Discord = require('discord.js')
const db = globals.db
module.exports = {
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(globals.Replies.find(r => r.id === 'NOENTRY').string);
}
else {
let gender
if (docs[0].character.sex == 'female') { gender = '♀️' }
else { gender = '♂️' }
const Reply = new Discord.MessageEmbed()
Reply.setColor('#0099ff')
Reply.setTitle(gender + ' ' + docs[0].character.name)
Reply.setDescription(docs[0].character.age + ' Jahre, ' + docs[0].character.race + '/' + docs[0].character.culture)
Reply.addField(docs[0].character.professionname, docs[0].character.xp.startinglevel)
message.reply( Reply );
}
});
}
catch (e) {
throw e;
}
},
};

31
commands/skill.js Normal file
View File

@ -0,0 +1,31 @@
const globals = require('../globals')
const db = globals.db
module.exports = {
name: 'skill',
description: 'Zeigt dir deinen Fertigkeitswert im jeweiligen Talent.',
aliases: [],
usage: '<Fertigkeit>',
needs_args: true,
async exec(message, args) {
try {
db.find({
user: message.author.tag,
}, function(err, docs) {
if (!docs.length > 0) {
return message.reply(globals.Replies.find(r => r.id === 'NOENTRY').string);
}
else {
let level = 0;
for (i in docs[0].character.skills) {
if (docs[0].character.skills[i].id == args[0]) level = docs[0].character.skills[i].level;
}
message.reply('Du hast folgenden Talentwert in ' + args[0] + ': ' + level);
}
});
}
catch (e) {
throw e;
}
},
};

123
commands/talent.js Normal file
View File

@ -0,0 +1,123 @@
const globals = require('../globals');
const Random = require('random');
const Discord = require('discord.js')
const db = globals.db
module.exports = {
name: 'talent',
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: ['t'],
usage: '<Talent> [<-Erschwernis> / <+Erleichterung>]',
needs_args: true,
async exec(message, args) {
try {
db.find({
user: message.author.tag,
}, function(err, docs) {
if (!docs.length > 0) {
return message.reply(globals.Replies.find(r => r.id === 'NOENTRY').string);
}
if(!isNaN(args[0])) {
return message.reply(globals.Replies.find(x => x.id === 'WRONG_ARGUMENTS').string)
}
else {
Random.use(message.author.tag);
const values = [];
const roll = [];
let found = false;
let talent;
let bonus = 0;
let ok = 0;
let patzer = 0;
let crit = 0;
let erschwernis = 0
if (args[1]) {
erschwernis = parseInt(args[1]);
}
for (let i in globals.Talente) {
if (globals.Talente[i].id.toLowerCase() == args[0].toLowerCase() || globals.Talente[i].name.toLowerCase() == args[0].toLowerCase()) {
found = true;
talent = globals.Talente[i].id;
break;
}
}
if (!found) {
message.reply(globals.Replies.find(x => x.id === 'TALENT_UNKNOWN').string);
return;
}
for (let i in docs[0].character.skills) {
if (docs[0].character.skills[i].id == talent) {
bonus = docs[0].character.skills[i].level;
found = true;
}
}
const bonus_orig = bonus;
const result = globals.Talente.find(t => t.id === talent);
for (i in result.values) {
const kuerzel = globals.Werte.find(wert => wert.kuerzel === result.values[i]);
for (val in docs[0].character.attributes) {
if (docs[0].character.attributes[val].id == kuerzel.id) values.push(docs[0].character.attributes[val].level);
}
}
for (let i = 1; i <= 3; i++) {
roll.push(Random.int(1, 20));
}
// compare results
for (let i = 0; i < 3; i++) {
if (Math.floor(values[i] + parseInt(erschwernis)) >= roll[i]) {
ok++;
}
else if ((Math.floor(values[i]) + parseInt(bonus) + parseInt(erschwernis)) >= roll[i]) {
ok++;
bonus = bonus - (roll[i] - parseInt(erschwernis) - values[i]);
}
if (roll[i] == 1) crit++;
if (roll[i] == 20) patzer++;
}
const Reply = new Discord.MessageEmbed()
Reply.setTitle('Du würfelst auf das Talent ' + result.name + '.')
Reply.setDescription('Deine Werte für ' + result.values.join(', ') + ' sind ' + values.join(', ') + '. (Bonus: ' + bonus_orig + ')')
Reply.addFields({
name: 'Deine 🎲: ' + roll.join(', ') + '.',
value: '\u200B', inline: false})
if (patzer >= 2) {
Reply.setColor('#900c3f')
Reply.addFields({
name: globals.Replies.find(x => x.id === 'TITLE_CRIT_FAILURE').string,
value: globals.Replies.find(x => x.id === 'MSG_CRIT_FAILURE').string,
inline: false})
}
else if (crit >= 2) {
Reply.setColor('#1E8449')
Reply.addFields({
name: globals.Replies.find(x => x.id === 'TITLE_CRIT_SUCCESS').string,
value:globals.Replies.find(x => x.id === 'MSG_CRIT_SUCCESS').string,
inline: false})
}
else if (ok < 3) {
Reply.addFields({name: globals.Replies.find(x => x.id === 'TITLE_FAILURE').string,
value: 'nur ' + ok + '/3 Proben erfolgreich. 😪',
inline: false});
}
else {
Reply.addFields({name: globals.Replies.find(x => x.id === 'TITLE_SUCCESS').string,
value: ok + '/3 Proben erfolgreich. Dein Bonus: ' + bonus + '/' + bonus_orig + '.',
inline: false})
}
message.reply(Reply)
}
});
}
catch (e) {
throw e;
}
},
};

36
commands/talents.js Normal file
View File

@ -0,0 +1,36 @@
const globals = require('../globals');
const Discord = require('discord.js');
module.exports = {
name: 'talents',
description: '',
aliases: [],
usage: '',
needs_args: false,
async exec(message, args) {
const fields = [];
for (const i in globals.TalentKategorien) {
const ability = [];
for (const a in globals.Talente) {
if (globals.Talente[a].categoryid == i) {
ability.push(globals.Talente[a].id.charAt(0).toUpperCase() + globals.Talente[a].id.slice(1));
}
}
ability.sort();
fields.push(ability);
}
const Embed = new Discord.MessageEmbed()
.setColor('#0099ff')
.setTitle('Talentübersicht')
.setDescription('Das sind die Talente, die ich kenne:');
for (const i in fields) {
Embed.addField(globals.TalentKategorien[i], fields[i].join('\n'), true);
}
message.author.send(
Embed,
);
},
};

83
commands/tp.js Normal file
View File

@ -0,0 +1,83 @@
// eslint-disable-next-line no-unused-vars
const Random = require('random');
const globals = require('../globals')
const Discord = require('discord.js')
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,
async exec(message, args) {
if(isNaN(args[0])) {
return message.reply(globals.Replies.find(x => x.id === 'WRONG_ARGUMENTS').string)
}
Random.use(message.author.tag);
const roll = [];
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));
}
let ok = 0;
let patzer = 0;
let crit = 0;
for (let i = 0; i < 3; i++) {
if (Math.floor(parseInt(args[i]) + parseInt(erschwernis)) >= roll[i]) {
ok++;
} else if (
Math.floor(parseInt(args[i]) + parseInt(bonus) + parseInt(erschwernis)) >= roll[i]) {
ok++;
bonus = bonus - (roll[i] - parseInt(erschwernis) - parseInt(args[i]));
}
if (roll[i] == 1) crit++;
if (roll[i] == 20) patzer++;
}
const Reply = new Discord.MessageEmbed()
//Reply.setTitle('Du würfelst auf ' + args[0] + ' ' + args[1] + ' ' + args[2] + ' (Bonus: ' + bonus_orig + ')')
Reply.setTitle('Deine 🎲: ' + roll.join(', ') + '.')
if (patzer >= 2) {
Reply.setColor('#900c3f')
Reply.addFields({
name: globals.Replies.find(x => x.id === 'TITLE_CRIT_FAILURE').string,
value: globals.Replies.find(x => x.id === 'MSG_CRIT_FAILURE').string,
inline: false
})
} else if (crit >= 2) {
Reply.setColor('#1E8449')
Reply.addFields({
name: globals.Replies.find(x => x.id === 'TITLE_CRIT_SUCCESS').string,
value: globals.Replies.find(x => x.id === 'MSG_CRIT_SUCCESS').string,
inline: false
})
} else if (ok < 3) {
Reply.addFields({
name: globals.Replies.find(x => x.id === 'TITLE_FAILURE').string,
value: 'Nur ' + ok + '/3 Proben erfolgreich. 😪',
inline: false
})
} else {
Reply.addFields({
name: globals.Replies.find(x => x.id === 'TITLE_SUCCESS').string,
value: ok + '/3 Proben erfolgreich. Dein Bonus: ' + bonus + '/' + bonus_orig + '.',
inline: false
})
}
message.reply(Reply)
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,10 @@
const Discord = require('discord.js')
const Datastore = require('nedb'),
db = new Datastore({
filename: 'data/dsabot.db',
autoload: true,
});
const MessageEmbed = new Discord.MessageEmbed()
const money = [{
'GD': 'Golddukaten',
'ST': 'Silbertaler',
@ -85,4 +92,24 @@ const Talente = [
{ id: 'stoffbearbeitung', name: 'Stoffbearbeitung', values: ['KL', 'FF', 'FF'], categoryid: 4 },
];
module.exports = { Werte, Talente, Coin, TalentKategorien, DiceRegex };
const Replies = [
{ id: 'NOENTRY', string: 'Sorry, für dich habe ich leider keinen Eintrag 😥' },
{ id: 'ERROR', string: 'Irgendwas ist schief gelaufen. 🤔'},
{ id: 'WRONG_ARGUMENTS', string: 'Die Angaben sind fehlerhaft. Nutze !help um zu erfahren, wie es richtig geht.'},
{ id: 'TITLE_CRIT_FAILURE', string: 'Patzer!' },
{ id: 'TITLE_CRIT_SUCCESS', string: 'Kritischer Erfolg!'},
{ id: 'TITLE_SUCCESS', string: 'Bestanden'},
{ id: 'TITLE_FAILURE', string: 'Nicht bestanden'},
{ id: 'MSG_CRIT_FAILURE', string: 'Du hast aber auch Pech 😥'},
{ id: 'MSG_CRIT_SUCCESS', string: '🎈✨🥳'},
{ id: 'MSG_SUCCESS', string: ''},
{ id: 'MSG_FAILURE', string: ''},
{ id: 'TOO_FEW_ARGS', string: 'Du hast zu wenig Angaben gemacht. Probiere es einmal so:\n'},
{ id: 'SAVED_DATA', string: 'Ich habe deine Daten abgespeichert.'},
{ id: 'DELETED_DATA', string: 'Ich habe deine Daten entfernt.'},
{ id: 'TALENT_UNKNOWN', string: 'Das Talent ist mir unbekannt.'}
]
module.exports = { Werte, Talente, Coin, TalentKategorien, DiceRegex, Discord, MessageEmbed, db, Replies };

90
index.js Normal file
View File

@ -0,0 +1,90 @@
require('dotenv').config();
const fs = require('fs')
const fetch = require('node-fetch');
const globals = require('./globals')
const db = globals.db
const cmdprefix = process.env.CMDPREFIX || '!';
const Discord = require('discord.js');
const client = new Discord.Client();
client.commands = new Discord.Collection();
client.on('message', commandHandler);
client.login(process.env.BOT_TOKEN);
client.once('ready', () => {
console.log('Ready!');
});
const commandFiles = fs.readdirSync('./commands/').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
async function commandHandler(message) {
//console.log(`${new Date().toUTCString()} ${message.author.tag} (size: ${message.attachments.size})`);
if ((message.attachments.size > 0) && message.channel.type == 'dm' && !message.author.bot) {
try {
const response = await fetch(message.attachments.first().url);
const data = await validateJSON(response);
if (data) await CreateFromFile(message, data);
} catch (e) {
console.log(e)
return message.reply(globals.Replies.find(x => x.id === 'ERROR').string);
}
} else {
if (!message.content.startsWith(cmdprefix) || message.author.bot) {
return;
}
const args = message.content.slice(cmdprefix.length).split(' ');
const commandName = args.shift().toLowerCase();
//if (!client.commands.has(commandName)) return;
try {
const command = client.commands.get(commandName) || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
if (!command) return;
if (command.needs_args && !args.length) {
return message.reply(
globals.Replies.find(x => x.id === 'TOO_FEW_ARGS').string +
cmdprefix + commandName + ' ' + command.usage
);
} else {
command.exec(message, args);
}
} catch (e) {
message.reply(globals.Replies.find(x => x.id === 'ERROR').string)
}
}
};
function validateJSON(body) {
try {
const data = body.json();
return data;
} catch (e) {
return null;
}
}
async function CreateFromFile(message, data) {
try {
db.find({
user: message.author.tag,
}, function(err, docs) {
if (!docs.length > 0) {
db.insert({
user: message.author.tag,
gold: 0,
silver: 0,
bronce: 0,
iron: 0,
hp: 0,
character: data,
}, function(err, docs) {
message.reply(globals.Replies.find(r => r.id === 'SAVED_DATA').string);
});
}
});
}
catch (e) {
throw e;
}
}

View File

@ -4,8 +4,8 @@
"description": "",
"main": "index.js",
"scripts": {
"lint": "eslint src/",
"start": "node src/index.js"
"lint": "eslint commands/",
"start": "node index.js"
},
"author": "",
"license": "ISC",

View File

@ -1,7 +0,0 @@
const globals = require('../globals');
const Random = require('random')
module.exports = async (message, args, db) => {
Random.use(message.author.tag)
const coin = Random.int(0,1)
message.reply('Die Münze bleibt auf **' + globals.Coin[coin] + '** liegen.');
};

View File

@ -1,81 +0,0 @@
module.exports = async (message, args, db) => {
try {
console.log(message.author.tag + ': ' + args);
if (!isNaN(args[0])) {
message.reply(args[1]);
console.log('1: ' + args[1] + ', 2: ' + args[2]);
const money = ['gold', 'silver', 'bronce', 'iron', 'hp'];
if (money.indexOf(args[1].toLowerCase()) < 0) {
message.reply(
'Sorry, Aber du musst eins der folgenden Wörter angeben: ' + money.join(','),
);
return;
}
db.find({
user: message.author.tag,
}, function(err, docs) {
gold = docs[0].gold;
silver = docs[0].silver;
bronce = docs[0].bronce;
iron = docs[0].iron;
hp = docs[0].hp;
});
db.update({
user: message.author.tag,
}, {
gold: gold,
silver: silver,
bronce: bronce,
iron: iron,
hp: hp,
}, function(err, docs) {
if (!docs.length > 0) {
message.reply('Sorry, Für dich habe ich keinen Eintrag 😥');
return;
}
message.reply(`ich habe ${args[2]} zu ${args[1]} hinzugefügt.`);
});
}
}
catch (e) {
throw e;
}
};
/*
module.exports = async (message, args, db) => {
var n;
if(!isNaN(args[0]) && (args[1] === 'GD' || args[1] === 'ST' || args[1] === 'BH' || args[1] === 'EK')) {
// eslint-disable-next-line no-undef
db.query('SELECT * FROM dsageld WHERE userName = ' + '"' + message.author.tag + '"', function(err, row) { //the row is the user's data
if(row && err) {
message.reply('Es gab einen Fehler.');
}
if(typeof(row) == 'undefined') { //if the user is not in the database
message.reply('Es existiert kein Eintrag für dich füge ihn mit !create hinzu.');
} else { //if the user is in the database
if(args[1] === 'GD') {
n = parseInt(row[0].GD, 10) + parseInt(args[0], 10);
} else if(args[1] === 'ST') {
n = parseInt(row[0].ST, 10) + parseInt(args[0], 10);
} else if(args[1] === 'BH') {
n = parseInt(row[0].BH, 10) + parseInt(args[0], 10);
} else if(args[1] === 'EK') {
n = parseInt(row[0].EK, 10) + parseInt(args[0], 10);
} else if(args[1] === 'LP') {
n = parseInt(row[0].EK, 10) + parseInt(args[0], 10);
}
// eslint-disable-next-line no-undef
db.query('UPDATE dsageld SET' + '`' + args[1] + '`' + ' = (' + n + ') WHERE userName = ' + '"' + message.author.tag + '"');
// eslint-disable-next-line no-undef
db.query('SELECT * FROM dsageld WHERE userName = ' + '"' + message.author.tag + '"', function(err, row) { //the row is the user's data
message.reply(args[0] + args[1] + ' hinzugefügt, du hast: ' + row[0].GD + 'GD, ' + row[0].ST + 'ST, ' + row[0].BH + 'BH, ' + row[0].EK + 'EK, ' + row[0].LP + 'LeP.');
});
}
});
}
};
*/

View File

@ -1,83 +0,0 @@
const globals = require('../globals');
const Random = require('random')
module.exports = async (message, args, db) => {
try {
// user calls without arguments.
if (!args[0]) {
message.reply('Bitte gib mir ein Attributswert, oder das Attribut auf welches du würfeln möchtest.');
return;
}
let level = 8;
let attributename;
await db.find({
user: message.author.tag,
}, async function(err, docs) {
// user calls with text. need to gather info from database
if (isNaN(args[0])) {
if (!docs.length > 0) {
message.reply('Sorry, Für dich habe ich keinen Eintrag 😥\n' +
'Bitte gib mir den Attributswert, auf welchen du würfeln möchtest.');
return;
}
else {
// try to get id of short formatted attributes.
if (args[0].length == 2) {
for (const i in globals.Werte) {
if (globals.Werte[i].kuerzel == args[0].toUpperCase()) {
attributename = globals.Werte[i].id;
}
}
}
else {
attributename = args[0].toLowerCase();
}
for (const i in docs[0].character.attributes) {
if (docs[0].character.attributes[i].id == attributename) level = docs[0].character.attributes[i].level;
}
}
}
else {
level = args[0];
}
Random.use(message.author.tag)
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
const dice = [];
dice.push(Random.int(1,20));
if (dice[0] == 1 || dice[0] == 20) {
dice.push(Random.int(1,20));
}
// handle crits
if (countOccurrences(dice, 1) == 2) {
message.reply('Du hast einen kritischen Erfolg erzielt (' + dice.join(', ') + ')! 🎉🥳🎆');
return;
}
else if (countOccurrences(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;
}
};

View File

@ -1,22 +0,0 @@
module.exports = async (message, args, db) => {
try {
console.log(message);
db.find({
user: message.author.tag,
}, function(err, docs) {
if(!docs.length > 0) {
db.insert({ user: message.author.tag,
gold: 0,
silver: 0,
bronce: 0,
iron: 0,
hp: 0,
});
}
console.log(docs);
});
}
catch (e) {
throw e;
}
};

View File

@ -1,26 +0,0 @@
module.exports = async (message, data, db) => {
try {
console.log(message.channel);
db.find({
user: message.author.tag,
}, function(err, docs) {
if (!docs.length > 0) {
db.insert({
user: message.author.tag,
gold: 0,
silver: 0,
bronce: 0,
iron: 0,
hp: 0,
character: data,
}, function(err, docs) {
message.reply('Ich habe deine Daten abgespeichert.');
// console.log(docs[0].character.name)
});
}
});
}
catch (e) {
throw e;
}
};

View File

@ -1,60 +0,0 @@
const Discord = require('discord.js')
const cmdprefix = process.env.CMDPREFIX||'!'
module.exports = async (message, args, db) => {
const Help = new Discord.MessageEmbed()
.setColor('#0099ff')
.setTitle('Hilfe')
.setDescription('Das sind die Befehle, die du verwenden kannst.\n' +
'Werte in Klammern müssen nicht mit angegeben werden.')
.addFields({
name: cmdprefix + 'kopf',
value: 'Wirf eine Münze. Kopf oder Zahl?',
inline: false
}, {
name: cmdprefix + 'roll <Anzahl> W <Augenzahl>',
value: 'Lass die Würfel rollen. Benötigt wird die Anzahl sowie die Augenzahl auf den Würfeln.',
inline: false
}, {
name: cmdprefix + 'ep/ap <Eigenschaftswert>',
value: ' Du machst eine Eigenschaftsprobe / Attributprobe.\n' +
' Du würfelst mit einem W20 auf deinen Eigenschaftswert.\n' +
' Bei einer 1 oder 20 wird der Bestätigungswurf ausgeführt.',
inline: false
}, {
name: cmdprefix + 'tp/fp <Eigenschaftswert1> <Eigenschaftswert2> <Eigenschaftswert3> (Fertigkeitswert) (+Erleichtert/-Erschwert)',
value: ' 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.',
inline: false
}, {
name: cmdprefix + 'talents',
value: ' Du erhälst eine Liste mit den Talentnamen, die du für ' +
cmdprefix + 'talent/' + cmdprefix + 'skill nutzen kannst.',
inline: false
}, {
name: '\u200B',
value: '\u200B'
}, {
name: '\u200B',
value: 'Wenn du mir deine .tdc Datei zusendest, kannst du folgendes nutzen:'
}, {
name: cmdprefix + 'ep/ap [Klugheit] oder ' + cmdprefix + 'ep/ap [FF]',
value: 'siehe oben. Du brauchst deinen Wert nicht wissen.',
inline: false
}, {
name: cmdprefix + 'talent <Talentname> (+Erleichtert/-Erschwert)',
value: 'siehe tp. Allerdings musst du deine Werte nicht wissen.',
inline: false
}, {
name: cmdprefix + 'skill <Talentname>',
value: 'Zeigt dir deinen Fertigkeitswert im jeweiligen Talent.',
inline: false
}, {
name: cmdprefix + 'remove',
value: 'Löscht deinen Charakter aus der Datenbank. Sinnvoll, wenn du mir eine neue zusenden möchtest.',
inline: false
}
)
message.author.send(Help);
};

View File

@ -1,82 +0,0 @@
const fs = require('fs');
const fetch = require('node-fetch');
const roll = require('./roll');
const create = require('./create');
const add = require('./add');
const remove = require('./remove');
const show = require('./show');
const tp = require('./tp');
const talent = require('./talent');
const skill = require('./skill');
const createFromFile = require('./createFromFile');
const kopf = require('./HeadsOrTails');
const zahl = require('./HeadsOrTails');
const heads = require('./HeadsOrTails');
const tails = require('./HeadsOrTails');
const ep = require('./attribute');
const ap = require('./attribute');
const help = require('./help')
const talents = require('./talents')
require('dotenv').config();
const cmdprefix = process.env.CMDPREFIX || '!';
const commands = {
roll,
create,
add,
remove,
show,
skill,
tp,
talent,
talents,
kopf,
zahl,
heads,
tails,
ep,
ap,
help
};
const Datastore = require('nedb'),
db = new Datastore({
filename: 'data/dsabot.db',
autoload: true,
});
module.exports = async (message) => {
console.log(`${new Date().toUTCString()} ${message.author.tag} (size: ${message.attachments.size})`);
if ((message.attachments.size > 0) && message.channel.type == 'dm' && !message.author.bot) {
try {
const response = await fetch(message.attachments.first().url);
const data = await validateJSON(response);
if (data) createFromFile(message, data, db);
}
catch (e) {
return null;
}
}
else {
if (!message.content.startsWith(cmdprefix) || message.author.bot) return;
const args = message.content.slice(cmdprefix.length).split(' ');
const command = args.shift().toLowerCase();
if (Object.keys(commands).includes(command)) {
commands[command](message, args, db);
}
}
};
function validateJSON(body) {
try {
const data = body.json();
// if came to here, then valid
return data;
}
catch (e) {
// failed to parse
return null;
}
}

View File

View File

@ -1,6 +0,0 @@
module.exports = async (message, args, db) => {
db.remove({ user: message.author.tag }, {}, function(err, numRemoved) {
message.reply('Ich habe deine Daten gelöscht.\n' +
'Wenn dir danach ist, kannst du mir gerne wieder eine neue Datei zusenden.');
});
};

View File

@ -1,26 +0,0 @@
// eslint-disable-next-line no-unused-vars
const globals = require('../globals')
const Random = require('random')
module.exports = async (message, args, db) => {
Random.use(message.author.tag)
let msg;
let arguments = args.join('');
arguments = arguments.split(globals.DiceRegex);
if (arguments.length == 2) {
let numberOfDice = arguments[0];
const diceValues = arguments[1];
const roll = [];
for (let i = 0; i < numberOfDice; i++) {
const a = Random.int(1,diceValues);
roll.push(a);
}
if(numberOfDice == 1) { msg = 'n';}
else { msg = ' ' + numberOfDice;}
message.reply('Das sind deine Ergebnisse für deine' + msg + ' ' + diceValues + '-seitigen 🎲: ' + roll.join(', ') + '.');
}
else {
message.reply('Leider kann ich damit nichts anfangen. Bitte noch einmal so probieren:\n' +
'!roll <Anzahl> W <Augenzahl>');
}
};

View File

@ -1,23 +0,0 @@
// eslint-disable-next-line no-unused-vars
module.exports = async (message, args, db) => {
// eslint-disable-next-line no-undef
try {
console.log(message);
db.find({
user: message.author.tag,
}, function(err, docs) {
// docs is an array containing documents Mars, Earth, Jupiter If no document is
// found, docs is equal to []
if (!docs.length > 0) {message.reply('Sorry, Für dich habe ich keinen Eintrag 😥');}
else {
message.reply(
`Du besitzt folgendes:
${docs[0].silver} Silberstücke.`,
);
}
});
}
catch (e) {
throw e;
}
};

View File

@ -1,19 +0,0 @@
module.exports = async (message, args, db) => {
try {
db.find({
user: message.author.tag,
}, function(err, docs) {
if (!docs.length > 0) {message.reply('Sorry, Für dich habe ich keinen Eintrag 😥');}
else {
let level = 0;
for(i in docs[0].character.skills) {
if(docs[0].character.skills[i].id == args[0]) level = docs[0].character.skills[i].level;
}
message.reply('Du hast Folgenden Skill in ' + args[0] + ': ' + level);
}
});
}
catch (e) {
throw e;
}
};

View File

@ -1,102 +0,0 @@
const globals = require('../globals');
const Random = require('random')
module.exports = async (message, args, db) => {
try {
db.find({
user: message.author.tag,
}, function(err, docs) {
if (!docs.length > 0) {message.reply('Sorry, Für dich habe ich keinen Eintrag 😥');}
else {
if (!args){
message.reply('Sorry, du musst mir schon etwas zum prüfen geben.');
return
}
Random.use(message.author.tag)
if (args[1]) {
var erschwernis = parseInt(args[1]);
}
else {
erschwernis = 0;
}
const values = [];
const roll = [];
let found = false;
let talent
let bonus = 0;
let ok = 0;
let patzer = 0;
let crit = 0;
for (i in globals.Talente)
{
if (globals.Talente[i].id.toLowerCase() == args[0].toLowerCase()||globals.Talente[i].name.toLowerCase()==args[0].toLowerCase()) {
found=true
talent = globals.Talente[i].id
break;
}
}
if (!found) {
message.reply('Sorry, das Talent ist mir unbekannt.');
return;
}
for (i in docs[0].character.skills) {
if (docs[0].character.skills[i].id == talent) {bonus = docs[0].character.skills[i].level; found = true;}
}
const bonus_orig = bonus;
const result = globals.Talente.find(t => t.id === talent);
for (i in result.values) {
const kuerzel = globals.Werte.find(wert => wert.kuerzel === result.values[i]);
for (val in docs[0].character.attributes) {
if (docs[0].character.attributes[val].id == kuerzel.id) values.push(docs[0].character.attributes[val].level);
}
}
for (i = 1; i <= 3; i++) {
roll.push(Random.int(1,20));
}
// compare results
for (i = 0; i < 3; i++) {
if (Math.floor(values[i] + parseInt(erschwernis)) >= roll[i]) {ok++;}
else if ((Math.floor(values[i]) + parseInt(bonus) + parseInt(erschwernis)) >= roll[i]) {
ok++;
bonus = bonus - (roll[i] - parseInt(erschwernis) - values[i]);
}
if (roll[i] == 1) crit++;
if (roll[i] == 20) patzer++;
}
if (patzer >= 2) {
message.reply('Du würfelst auf das Talent ' + result.name + '.\n' +
'Deine Werte für ' + result.values.join(', ') + ' sind ' + values.join(', ') + '.\n' +
'Deine 🎲: ' + roll.join(', ') + '. Patzer! Du hast aber auch Pech 😥',
);
}
else if (crit >= 2) {
message.reply('Du würfelst auf das Talent ' + result.name + '.\n' +
'Deine Werte für ' + result.values.join(', ') + ' sind ' + values.join(', ') + '.\n' +
'Deine 🎲: ' + roll.join(', ') + '. Damit hast du einen kritischen Erfolg erzielt 🎈✨🥳',
);
}
else if (ok < 3) {
message.reply('Du würfelst auf das Talent ' + result.name + '.\n' +
'Deine Werte für ' + result.values.join(', ') + ' sind ' + values.join(', ') + '. (Bonus: ' + bonus_orig + ')\n' +
'Deine 🎲: ' + roll.join(', ') + '. Damit hast du nur ' + ok + '/3 Proben bestanden. 😪',
);
}
else {
message.reply('Du würfelst auf das Talent ' + result.name + '.\n' +
'Deine Werte für ' + result.values.join(', ') + ' sind ' + values.join(', ') + '. (Bonus: ' + bonus_orig + ')\n' +
'Das waren deine 🎲: ' + roll.join(', ') + '. Damit hast du ' + ok + '/3 Proben bestanden. Dein Bonus: ' + bonus + '/' + bonus_orig + '.',
);
}
}
});
}
catch (e) {
throw e;
}
};

View File

@ -1,26 +0,0 @@
const globals = require('../globals')
const Discord = require('discord.js')
module.exports = async (message, args, db) => {
let fields = []
for (let i in globals.TalentKategorien) {
let ability = []
for (let a in globals.Talente) {
if(globals.Talente[a].categoryid == i) {
ability.push(globals.Talente[a].id.charAt(0).toUpperCase() + globals.Talente[a].id.slice(1));
}
}
ability.sort()
fields.push(ability)
}
const Embed = new Discord.MessageEmbed()
.setColor('#0099ff')
.setTitle('Talentübersicht')
.setDescription('Das sind die Talente, die ich kenne:')
for (let i in fields) {
Embed.addField(globals.TalentKategorien[i], fields[i].join('\n'), true);
}
message.author.send(
Embed
);
};

View File

@ -1,60 +0,0 @@
// eslint-disable-next-line no-unused-vars
const Random = require('random')
module.exports = async (message, args, db) => {
if (args.length < 3) {
message.reply('Der Talentwurf funktioniert so:\n' +
'!tp Eigenschaftswert1 Eigenschaftswert2 Eigenschaftswert3 [Bonus] [Erschwernis]');
}
else {
Random.use(message.author.tag)
const roll = [];
if (args[3]) {
var bonus = parseInt(args[3]);
}
else {
bonus = 0;
}
if (args[4]) {
var erschwernis = parseInt(args[4]);
}
else {
erschwernis = 0;
}
for (i = 1; i <= 3; i++) {
roll.push(Random.int(1,20));
}
let ok = 0;
let patzer = 0;
let crit = 0;
for (i = 0; i < 3; i++) {
if (Math.floor(parseInt(args[i]) + parseInt(erschwernis)) >= roll[i]) {ok++;}
else if (
Math.floor(parseInt(args[i]) + parseInt(bonus) + parseInt(erschwernis)) >= roll[i]) {
ok++;
bonus = bonus - (roll[i] - parseInt(erschwernis) - parseInt(args[i]));
}
if (roll[i] == 1) crit++;
if (roll[i] == 20) patzer++;
}
if (patzer >= 2) {
message.reply(
'Deine 🎲: ' + roll.join(', ') + '. Patzer! Du hast aber auch Pech 😥',
);
}
else if (crit >= 2) {
message.reply(
'Deine 🎲: ' + roll.join(', ') + '. Damit hast du einen kritischen Erfolg erzielt 🎈✨🥳',
);
}
else if (ok < 3) {
message.reply(
'Deine 🎲: ' + roll.join(', ') + '. Damit hast du nur ' + ok + '/3 Proben bestanden. 😪',
);
}
else {
message.reply(
'Das waren deine 🎲: ' + roll.join(', ') + '. Damit hast du ' + ok + '/3 Proben bestanden. Dein Bonus: ' + bonus + '/' + args[3] + '.',
);
}
}
};

View File

@ -1,25 +0,0 @@
require('dotenv').config();
const Discord = require('discord.js');
const client = new Discord.Client();
const commandHandler = require('./commands');
client.on('message', commandHandler);
client.login(process.env.BOT_TOKEN);
client.once('ready', () => {
console.log('Ready!');
});
client.on('error', err => {
console.error('Error\n' + err);
process.exit(1);
});
client.on('disconnect', message => {
console.error('User Disconnected');
process.exit(1);
});
client.on('reconnecting', message => {
console.log('User Reconnecting');
});