feat(bot): added eval and connected mongodb

This commit is contained in:
Rauf 2020-01-19 13:55:35 -05:00
parent a62c0e3b78
commit 2e3e0bbe0a
11 changed files with 256 additions and 11 deletions

78
package-lock.json generated
View File

@ -96,12 +96,29 @@
"defer-to-connect": "^1.0.1"
}
},
"@types/bson": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.1.tgz",
"integrity": "sha512-K6VAEdLVJFBxKp8m5cRTbUfeZpuSvOuLKJLrgw9ANIXo00RiyGzgH4BKWWR4F520gV4tWmxG7q9sKQRVDuzrBw==",
"requires": {
"@types/node": "*"
}
},
"@types/color-name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
"dev": true
},
"@types/mongodb": {
"version": "3.3.14",
"resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.3.14.tgz",
"integrity": "sha512-Ie0Fjoifm/TPY2rNOgixzhNSjDgxgR0dMKQk9XqUXHnkfuw26SpbMXjwECfxSnEdG1bH6bIlpLIK7HvGHQhzqg==",
"requires": {
"@types/bson": "*",
"@types/node": "*"
}
},
"@types/node": {
"version": "10.17.13",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.13.tgz",
@ -111,6 +128,7 @@
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz",
"integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==",
"dev": true,
"requires": {
"@types/node": "*"
}
@ -327,6 +345,11 @@
"concat-map": "0.0.1"
}
},
"bson": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.3.tgz",
"integrity": "sha512-TdiJxMVnodVS7r0BdL42y/pqC9cL2iKynVwA0Ho3qbsQYr428veL3l7BQyuqiw+Q5SqqoT0m4srSY/BlZ9AxXg=="
},
"builtin-modules": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
@ -1147,6 +1170,12 @@
"integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=",
"dev": true
},
"memory-pager": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
"optional": true
},
"meow": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz",
@ -1223,6 +1252,17 @@
"minimist": "0.0.8"
}
},
"mongodb": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.4.1.tgz",
"integrity": "sha512-juqt5/Z42J4DcE7tG7UdVaTKmUC6zinF4yioPfpeOSNBieWSK6qCY+0tfGQcHLKrauWPDdMZVROHJOa8q2pWsA==",
"requires": {
"bson": "^1.1.1",
"require_optional": "^1.0.1",
"safe-buffer": "^5.1.2",
"saslprep": "^1.0.0"
}
},
"mute-stream": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
@ -1511,6 +1551,15 @@
"rc": "^1.2.8"
}
},
"require_optional": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
"integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
"requires": {
"resolve-from": "^2.0.0",
"semver": "^5.1.0"
}
},
"resolve": {
"version": "1.14.2",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.2.tgz",
@ -1520,6 +1569,11 @@
"path-parse": "^1.0.6"
}
},
"resolve-from": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
"integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c="
},
"responselike": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
@ -1569,8 +1623,7 @@
"safe-buffer": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
"dev": true
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
},
"safer-buffer": {
"version": "2.1.2",
@ -1578,11 +1631,19 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
},
"saslprep": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
"optional": true,
"requires": {
"sparse-bitfield": "^3.0.3"
}
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
},
"semver-diff": {
"version": "2.1.0",
@ -1619,6 +1680,15 @@
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
"dev": true
},
"sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
"optional": true,
"requires": {
"memory-pager": "^1.0.2"
}
},
"spdx-correct": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",

View File

@ -23,6 +23,8 @@
"posttest": "npm.cmd run check"
},
"dependencies": {
"discord.js": "github:discordjs/discord.js"
"@types/mongodb": "^3.3.14",
"discord.js": "github:discordjs/discord.js",
"mongodb": "^3.4.1"
}
}

View File

@ -1,9 +1,20 @@
import { Client, ClientOptions, Collection } from 'discord.js';
import { Plugin } from './plugins/Plugin';
import { Database } from './util/Database';
import { name, url } from './config/mongodb';
export class PluginClient extends Client {
plugins!: Collection<string, Plugin>;
db: Database;
constructor(options?: ClientOptions) {
super(options);
this.db = new Database({
name,
url,
MongoOptions: {
useNewUrlParser: true,
useUnifiedTopology: true,
},
});
}
}

View File

@ -6,10 +6,10 @@ export function calcUserLevel(user: GuildMember, guild: Guild) {
return 5;
}
if (user.id === guild.ownerID) {
return 4;
return 3;
}
if (user.permissions.has('ADMINISTRATOR', true)) {
return 3;
return 2;
}
return 0;
}

View File

@ -3,6 +3,7 @@ import { Message } from 'discord.js';
import { prefix } from '../config/bot';
import { PluginClient } from '../PluginClient';
import { calcUserLevel } from '../assertions/userLevel';
import { UserDoc } from '../models/User';
function parseContent(content: string) {
const split = content.split(' ');
@ -19,7 +20,13 @@ function getCommandFromPlugin(lifeguard: PluginClient, cmdName: string) {
export const event = new Event(
'lifeguardCommandUsed',
async (lifeguard, msg: Message) => {
async (lifeguard, msg: Message, dbUser: UserDoc) => {
if (msg.author.bot) {
return;
}
if (dbUser.blacklisted) {
return;
}
const [cmdName, ...args] = parseContent(msg.content);
const cmd = getCommandFromPlugin(lifeguard, cmdName);
@ -27,7 +34,7 @@ export const event = new Event(
if (msg.member && msg.guild) {
const userLevel = calcUserLevel(msg.member, msg.guild);
if (userLevel >= cmd.options.level) {
cmd.func(lifeguard, msg, args);
cmd.func(lifeguard, msg, args, dbUser);
}
}
}

View File

@ -1,9 +1,21 @@
import { Event } from './Event';
import { Message } from 'discord.js';
import { prefix } from '../config/bot';
import { User, UserDoc } from '../models/User';
export const event = new Event('message', async (lifeguard, msg: Message) => {
let dbUser = (await lifeguard.db.users.findOne({
id: msg.author.id,
})) as UserDoc;
if (!dbUser) {
await lifeguard.db.users.insertOne(
new User({ id: msg.author.id, infractions: [] })
);
dbUser = (await lifeguard.db.users.findOne({
id: msg.author.id,
})) as UserDoc;
}
if (msg.content.startsWith(prefix)) {
lifeguard.emit('lifeguardCommandUsed', msg);
lifeguard.emit('lifeguardCommandUsed', msg, dbUser);
}
});

View File

@ -10,6 +10,11 @@ PluginLoader().then(plugins => {
lifeguard.plugins = plugins;
});
lifeguard.db
.connect()
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error(err));
lifeguard.login(token).then(() => {
if (lifeguard.user) {
console.log(

26
src/models/User.ts Normal file
View File

@ -0,0 +1,26 @@
interface UserInfraction {
action: 'Warn' | 'Mute' | 'Tempban' | 'Ban';
active: boolean;
guild: string;
id: number;
moderator: string;
reason: string;
time: Date;
}
export interface UserDoc {
blacklisted?: boolean;
id: string;
infractions: UserInfraction[];
}
export class User implements UserDoc {
blacklisted: boolean;
id: string;
infractions: UserInfraction[];
constructor(data: UserDoc) {
this.blacklisted = data.blacklisted ?? false;
this.id = data.id;
this.infractions = data.infractions;
}
}

View File

@ -1,10 +1,12 @@
import { Message, PermissionString } from 'discord.js';
import { PluginClient } from '../PluginClient';
import { UserDoc } from '../models/User';
type CommandFunction = (
lifeguard: PluginClient,
msg: Message,
args: string[]
args: string[],
dbUser: UserDoc
) => void;
interface CommandOptions {

80
src/plugins/dev/eval.ts Normal file
View File

@ -0,0 +1,80 @@
import { Command } from '../Command';
import { MessageEmbed } from 'discord.js';
import { inspect } from 'util';
import { runInNewContext } from 'vm';
function parseBlock(script: string) {
const cbr = /^(([ \t]*`{3,4})([^\n]*)([\s\S]+?)(^[ \t]*\2))/gm;
const result = cbr.exec(script);
if (result) {
return result[4];
}
return script;
}
async function run(
script: string,
ctx: object,
opts: object
): Promise<string | Error> {
try {
const result = await runInNewContext(
`(async () => { ${script} })()`,
ctx,
opts
);
if (typeof result !== 'string') {
return inspect(result);
}
return result;
} catch (err) {
return err;
}
}
function makeCodeBlock(data: string, lang?: string) {
return `\`\`\`${lang}\n${data}\n\`\`\``;
}
export const command = new Command(
'eval',
async (lifeguard, msg, args, dbUser) => {
const start = Date.now();
const script = parseBlock(args.join(' '));
const exec = await run(
script,
{
lifeguard,
msg,
MessageEmbed,
dbUser,
},
{ filename: msg.guild?.id.toString() }
);
const end = Date.now();
if (typeof exec === 'string') {
const embed = new MessageEmbed()
.addField('Input', makeCodeBlock(script, 'js'))
.addField('Output', makeCodeBlock(exec, 'js'))
.setFooter(`Script Executed in ${end - start}ms`)
.setTimestamp()
.setColor(0x7289da);
msg.channel.send(embed);
} else {
const embed = new MessageEmbed()
.addField('Input', makeCodeBlock(script, 'js'))
.addField('Output', makeCodeBlock(`${exec.name}: ${exec.message}`))
.setFooter(`Script Executed in ${end - start}ms`)
.setTimestamp()
.setColor(0x7289da);
msg.channel.send(embed);
}
},
{
level: 5,
usage: ['eval {code}'],
}
);

30
src/util/Database.ts Normal file
View File

@ -0,0 +1,30 @@
import { connect, Db, MongoClientOptions } from 'mongodb';
interface DatabaseConfig {
url: string;
name: string;
MongoOptions?: MongoClientOptions;
}
export class Database {
db!: Db;
constructor(protected config: DatabaseConfig) {}
async connect() {
const client = await connect(
this.config.url,
this.config.MongoOptions
).catch(err => {
throw err;
});
this.db = client.db(this.config.name);
}
get guilds() {
return this.db.collection('guilds');
}
get users() {
return this.db.collection('users');
}
}