From 5e0ea4731e510609e8dcd5af3c428440ed6943cb Mon Sep 17 00:00:00 2001 From: Samuel Fichna Date: Tue, 15 May 2018 13:26:04 +0200 Subject: [PATCH] Complete the rewrite to TypeScript closes #20, closes #23 :sunglasses: --- src/app.js | 152 ------------------------------------- src/cmd/help.js | 39 ---------- src/cmd/link.js | 64 ---------------- src/cmd/links.js | 93 ----------------------- src/cmd/ping.js | 9 --- src/cmd/stop.js | 16 ---- ts-src/app.ts | 7 +- ts-src/class-cmd/Help.ts | 2 - ts-src/class-cmd/Link.ts | 68 +++++++++++++++++ ts-src/class-cmd/Links.ts | 94 +++++++++++++++++++++++ ts-src/class-cmd/Uptime.ts | 29 +++++++ ts-src/cmd/help.ts | 34 --------- ts-src/cmd/link.ts | 61 --------------- ts-src/cmd/links.ts | 87 --------------------- ts-src/cmd/ping.ts | 9 --- ts-src/cmd/stop.ts | 16 ---- 16 files changed, 192 insertions(+), 588 deletions(-) delete mode 100644 src/app.js delete mode 100644 src/cmd/help.js delete mode 100644 src/cmd/link.js delete mode 100644 src/cmd/links.js delete mode 100644 src/cmd/ping.js delete mode 100644 src/cmd/stop.js create mode 100644 ts-src/class-cmd/Link.ts create mode 100644 ts-src/class-cmd/Links.ts create mode 100644 ts-src/class-cmd/Uptime.ts delete mode 100644 ts-src/cmd/help.ts delete mode 100644 ts-src/cmd/link.ts delete mode 100644 ts-src/cmd/links.ts delete mode 100644 ts-src/cmd/ping.ts delete mode 100644 ts-src/cmd/stop.ts diff --git a/src/app.js b/src/app.js deleted file mode 100644 index 91cf5e8..0000000 --- a/src/app.js +++ /dev/null @@ -1,152 +0,0 @@ -const winston = require('winston'); -winston.add(winston.transports.File, { filename: "edge.log" }); -winston.level = 'info'; //TODO: set to info in production - -global.winston = winston; - -winston.info('Starting E-D-G-E...'); - -const path = require('path'); -const fs = require('fs'); -let config = null; -const Discord = require('discord.js'); -const client = new Discord.Client(); -const admin = require('firebase-admin'); -const Permissions = require("discord.js/src/util/Permissions"); - -let serviceAccount = null; - -try { - // noinspection JSFileReferences - serviceAccount = require('../run/serviceAccountKey.json'); -} catch (e) { - winston.error('Could not load serviceAccountKey.json, is it there? Is it readable?'); - process.exit(0); -} - -/* -Try to load the config file, if it does not exist create one from template and save it - */ -try { - // noinspection JSFileReferences - config = require('../run/config.json'); -} catch (e) { - let filePath = path.join(process.cwd(), './run/config.json'); - if (fs.existsSync(filePath)) { - winston.info('Failed to load the config.json file ' + filePath); - winston.error(e); - process.exit(0); - } - winston.info('No config file found, creating a template.'); - config = { - "discord": { - "token": "MY_BOT_USER_TOKEN", - "prefix": "MY_PREFIX", - "owner": "MY_SNOWFLAKE_ID" - }, - "firebase": { - "databaseURL": "https://MY_PROJECT_NAME.firebaseio.com" - }, - "email": { - "hostnameBlacklist": [ - "example.com" - ], - "ownerEmail": "admin@example.com", - "from": "\"E-D-G-E\" ", - "to": "testing@example.com, testing2@example.com", - "smtp": { - "host": "smtp.MY_SMTP_SERVICE.TLD", - "port": 587, - "secure": false, - "auth": { - "user": "MY_SMTP_USER", - "pass": "MY_SMTP_PASSWORD" - } - } - } - }; - - winston.debug('Creating config.json'); - try { - fs.writeFileSync(filePath, JSON.stringify(config, null, "\t")); - } catch(error) { - winston.error('Failed to create config file! Most probably missing permissions.'); - process.exit(0); - //winston.error(error); - } - - winston.info('Please edit ', filePath, ' and restart the app.'); //avoid type conversion by using commas instead of concat. - process.exit(0); -} - -/* FIREBASE */ -admin.initializeApp({ - credential: admin.credential.cert(serviceAccount), - databaseURL: config.firebase.databaseURL -}); -const database = admin.firestore(); -/* END FIREBASE */ - -// dynamic command dir -const cmdFiles = fs.readdirSync('./src/cmd'); - -let commands = new Discord.Collection(); -for (const file of cmdFiles) { - let cmd = require(`./cmd/${file}`); - commands.set(cmd.name, cmd); -} - -const refs = { - "config": config, - "client": client, - "database": database, - "commands": commands -}; - -// events -client.on('ready', () => { - winston.info("E-D-G-E ready!"); -}); - -client.on('message', msg => { - if (!msg.content.startsWith(config.discord.prefix) || msg.author.bot) return; - - // parses command arguments - const args = msg.content.slice(config.discord.prefix.length).split(/ +/); - const command = args.shift().toLowerCase(); - - if (!commands.has(command)) { - winston.debug('User ', msg.author.username, ' tried to execute non-existing command'); - msg.reply('requested command was not found!'); - return; - } - - try { - let cmd = commands.get(command); - - winston.debug('command type: ' + cmd['type']); - - switch(cmd['type']) { - case 2: - msg.author.id === refs.config.discord.owner ? cmd.execute(refs, msg, args) : msg.reply('you are not authorized to use this command!'); - break; - case 1: - (msg.author.id === refs.config.discord.owner || msg.member ? msg.member.hasPermission(Permissions.FLAGS.MANAGE_MESSAGES, false, true, true) : false) ? cmd.execute(refs, msg, args) : msg.reply('you are not authorized to use this command!'); - break; - default: - cmd.execute(refs, msg, args); - } - - } catch (error) { - winston.error('An error occurred while executing command!'); - winston.error(error); - msg.reply('an error has occurred, please notify bot developers.'); - } -}); - -// start -client.login(config.discord.token).catch(err => { - winston.info('******EDIT CONFIG.JSON TO CONTINUE******'); - winston.error(err); - process.exit(0); -}); diff --git a/src/cmd/help.js b/src/cmd/help.js deleted file mode 100644 index 8af97c6..0000000 --- a/src/cmd/help.js +++ /dev/null @@ -1,39 +0,0 @@ -/* Author: D3add3d */ - -const Permissions = require("discord.js/src/util/Permissions"); -module.exports = { - name: 'help', - description: 'Lists all commands', - type: 0, - execute(refs, msg, args) { - - let type = ''; - - if(msg.author.id === refs.config.discord.owner) { - type = 2; //owner - } else if(msg.member ? msg.member.hasPermission(Permissions.FLAGS.MANAGE_MESSAGES, false, true, true) : false) { - type = 1; //mod - } else { - type = 0; //regular - } - - global.winston.debug('type: ' + type); - - let helpString = "```\nCommands available for you:\n"; - refs.commands.forEach((value, key, map) => { - global.winston.debug('key: ' + key); - if(type >= value['type']) { - helpString = helpString.concat('\n', refs.config.discord.prefix, value['name'], ' -- ', value['description'], ' (', value['type'], ')'); - } - }); - if(type > 0) { - helpString = helpString.concat('\n\nWho can run these commands: 0 - anyone; 1 - moderator; 2 - owner'); - } - helpString = helpString.concat('\n```'); - msg.author.createDM().then(chan => { - chan.send(helpString); - }, () => { - msg.reply(helpString); - }); - } -}; \ No newline at end of file diff --git a/src/cmd/link.js b/src/cmd/link.js deleted file mode 100644 index 14dfcae..0000000 --- a/src/cmd/link.js +++ /dev/null @@ -1,64 +0,0 @@ -/*Author: D3add3d */ - -const validUrl = require('valid-url'); -const urlExists = require('url-exists-deep'); - -module.exports = { - name: 'link', - description: 'Checks and adds link to the database', - type: 0, - execute(refs, msg, args) { - global.winston.debug('Link command executed', args[0]); - if (validUrl.isUri(args[0])) { - global.winston.debug('Link is a valid URI'); - - let url = new URL(args[0]); - if(refs.config.email.hostnameBlacklist.includes(url.hostname)) { - msg.reply('that hostname is blacklisted!'); - global.winston.info('User ' + msg.author.username + ' tried to add blacklisted link!'); - return; - } - - // noinspection JSUnresolvedFunction - urlExists(args[0]).then(function (response) { - global.winston.debug('HTTP/S response returned for link'); - if (response) { - global.winston.debug('200 code response for link'); - let collectionRef = refs.database.collection('links'); - global.winston.debug('Querying database for existing link...'); - collectionRef.where('link', '==', args[0]).get().then(snapshot => { - let doesExist = false; - snapshot.forEach(doc => { - if (doc.exists) doesExist = true; - }); - if (doesExist) { - global.winston.debug('Link already exists'); - msg.reply('duplicate link, not adding.'); - } else { - global.winston.debug('Link does not exist, adding to database'); - msg.reply('adding link!'); - collectionRef.add({ - 'link': args[0], - 'timestamp': Date.now(), - 'seen': false, - 'user': msg.author.username - }); - } - }); - } else { - global.winston.debug('Server responded but link is not reachable, ignoring'); - msg.reply('given URL does not exist on that server!'); - } - }).catch(error => { - global.winston.debug('Server not found, ignoring link'); - msg.reply('given URI is pointing to a server that does not exist!'); - }); - - - } else { - global.winston.debug("Not an URI, ignoring"); - msg.reply('that link is not a valid URI!'); - } - } - -}; \ No newline at end of file diff --git a/src/cmd/links.js b/src/cmd/links.js deleted file mode 100644 index 5c5b4a7..0000000 --- a/src/cmd/links.js +++ /dev/null @@ -1,93 +0,0 @@ -/* Author: D3ad3dd */ - -const nodemailer = require('nodemailer'); - -module.exports = { - name: "links", - description: "`send`s or `list`s links that have not yet been sent", - type: 1, - execute(refs, msg, args) { - global.winston.info('links executed by',msg.author.username); - let content = ""; - - if(args[0] === 'send') { - - refs.database.collection('links').where('seen', '==', false).get().then(snapshot => { - winston.debug('Snapshot size :' + snapshot.size); - winston.debug('Snapshot empty:' + snapshot.empty); - if (!snapshot.empty) { - snapshot.forEach(doc => { - let data = doc.data(); - let tmp = data.user + ',' + data.link + '\n'; - content = content + tmp; - refs.database.collection('links').doc(doc.id).update({"seen": true}); - }); - - /* NODEMAILER START */ - let transporter = nodemailer.createTransport({ - host: refs.config.email.smtp.host, - port: refs.config.email.smtp.port, - secure: refs.config.email.smtp.secure, - auth: { - user: refs.config.email.smtp.auth.user, - pass: refs.config.email.smtp.auth.pass - } - }); - - // setup email data with unicode symbols - let mailOptions = { - from: refs.config.email.from, // sender address - to: refs.config.email.to, // list of receivers //links@n-o-d-e.net - subject: '[E-D-G-E] <' + new Date().toDateString() + '> Collection of links from the N-O-D-E community Discord server', // Subject line - text: 'Hello,\nI am E-D-G-E, a bot on the N-O-D-E community unofficial Discord server.\nThe attachment contains a list of links submitted by the members of N-O-D-E community unofficial Discord server.\nIf the list contains any hostnames that slipped my filter(e.g. NSFW content) please contact an administrator(' + refs.config.email.ownerEmail + ') listing the hostnames you want filtered in the e-mail and the bot administrator will add them to the blacklist, thanks!\n\n - Beep-boop-boop, E-D-G-E\n\n\n(This e-mail was sent because command "sendlinks" was executed by \' + msg.author.username +\' on Discord, the user was authorized by snowflake ID: \' + msg.author.id +\')\'', // plain text body - html: 'Hello,
I am E-D-G-E, a bot on the N-O-D-E community unofficial Discord server.
The attachment contains a list of links submitted by the members of N-O-D-E community unofficial Discord server.
If the list contains any hostnames that slipped my filter(e.g. NSFW content) please contact an administrator(' + refs.config.email.ownerEmail + ') listing the hostnames you want filtered in the e-mail and the bot administrator will add them to the blacklist, thanks!

- Beep-boop-boop, E-D-G-E


(This e-mail was sent because command "sendlinks" was executed by ' + msg.author.username + ' on Discord, the user was authorized by snowflake ID: ' + msg.author.id + ')', // html body - attachments: [ - { - filename: 'links-' + new Date().toDateString() + '.csv', - content: content, - contentType: 'text/plain' - } - ] - }; - - // send mail with defined transport object - transporter.sendMail(mailOptions, (error, info) => { - if (error) { - winston.error('Unable to send e-mail'); - msg.reply('I was unable to send the e-mail, please contact my developers and administrator.'); - return winston.error(error); - } - - winston.info('Sendlinks executed successfully!') - msg.reply('links sent!'); - }); - /* NODEMAILER END */ - - } else { - winston.info('Snapshot empty, not sending.') - msg.reply('there is nothing to send.') - } - }); - } else if(args[0] === 'list') { - refs.database.collection('links').where('seen', '==', false).get().then(snapshot => { - winston.debug('Snapshot size :' + snapshot.size); - winston.debug('Snapshot empty:' + snapshot.empty); - if (!snapshot.empty) { - snapshot.forEach(doc => { - let data = doc.data(); - let tmp = data.user + ': ' + data.link + '\n'; - content = content + tmp; - }); - - content = 'Links:\n' + content; - msg.channel.send(content); - } else { - msg.channel.send('There are no links in the database waiting to be sent.'); - } - }); - } else { - msg.reply('invalid or missing argument!'); - } - } - -}; \ No newline at end of file diff --git a/src/cmd/ping.js b/src/cmd/ping.js deleted file mode 100644 index 4496099..0000000 --- a/src/cmd/ping.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - name: 'ping', - description: 'Ping-Pong command', - type: 0, - execute(refs, msg, args) { - global.winston.debug('Ping command executed'); - msg.channel.send('Pong'); - } -}; diff --git a/src/cmd/stop.js b/src/cmd/stop.js deleted file mode 100644 index 6e914f0..0000000 --- a/src/cmd/stop.js +++ /dev/null @@ -1,16 +0,0 @@ -/* Author: D3add3d */ - -module.exports = { - name: 'stop', - description: 'Stops the bot', - type: 2, - execute(refs, msg, args) { - global.winston.debug('Stop command executed by: ', msg.author.username); - msg.channel.send('Stopping.'); - global.winston.info('Stopping.'); - setTimeout(() => { - refs.client.destroy(); - process.exit(0) - }, 1000); - } -}; \ No newline at end of file diff --git a/ts-src/app.ts b/ts-src/app.ts index 6eecf0c..1a0f997 100644 --- a/ts-src/app.ts +++ b/ts-src/app.ts @@ -117,7 +117,7 @@ async function loadCommands() } /* END COMMANDS */ -loadCommands().then(() => { +loadCommands().then(() => { //only continue after commands have been loaded /* DISCORD.JS */ client = new Discord.Client(); refs = { @@ -136,9 +136,6 @@ client.on("message", msg => { // parses command arguments let args = msg.content.slice(config.discord.prefix.length).split(/ +/); let command = args.shift().toLowerCase(); - - winston.debug(commands); - if (!commands.has(command)) { winston.debug("User", msg.author.username, "tried to execute non-existing command"); msg.reply("requested command was not found!").then(() => { @@ -150,9 +147,7 @@ client.on("message", msg => { } try { let cmd = commands.get(command); - winston.debug("command type: " + cmd["type"]); - switch(cmd["type"]) { case 2: msg.author.id === refs.config.discord.owner ? cmd.execute(refs, msg, args) : msg.reply("you are not authorized to use this command!"); diff --git a/ts-src/class-cmd/Help.ts b/ts-src/class-cmd/Help.ts index 165e00b..b44b14c 100644 --- a/ts-src/class-cmd/Help.ts +++ b/ts-src/class-cmd/Help.ts @@ -7,13 +7,11 @@ export default class Help implements ICommand { readonly description: string; readonly name: string; readonly type: number; - constructor() { this.description = "Lists all commands"; this.name = "help"; this.type = 0; } - execute(refs: object, msg: Discord.Message, args: Array) { let type = 0; if(msg.author.id === refs["config"].discord.owner) { diff --git a/ts-src/class-cmd/Link.ts b/ts-src/class-cmd/Link.ts new file mode 100644 index 0000000..050bb31 --- /dev/null +++ b/ts-src/class-cmd/Link.ts @@ -0,0 +1,68 @@ +/* Author: D3add3d */ + +import * as validUrl from "valid-url"; +import * as urlExists from "url-exists-deep"; +import * as Discord from "discord.js"; +import {ICommand} from "../ICommand"; + +export default class Link implements ICommand { + readonly description: string; + readonly name: string; + readonly type: number; + constructor() { + this.description = "Checks and adds link to the database"; + this.name = "link"; + this.type = 0; + } + execute(refs: object, msg: Discord.Message, args: Array) { + refs["winston"].debug("Link command executed by:", msg.author.username, " ", args[0]); + if (validUrl.isUri(args[0])) { + refs["winston"].debug("Link is a valid URI"); + let url = new URL(args[0]); + if(refs["config"].email.hostnameBlacklist.includes(url.hostname)) { + msg.reply("that hostname is blacklisted!").catch(() => { refs["winston"].error("Unable to send reply!") }); + refs["winston"].info("User ", msg.author.username, " tried to add blacklisted link!"); + return; + } + urlExists(args[0]).then(function (response) { + refs["winston"].debug("HTTP/S response returned for link"); + if (response) { + refs["winston"].debug("200 code response for link"); + let collectionRef = refs["database"].collection("links"); + refs["winston"].debug("Querying database for existing link..."); + collectionRef.where("link", "==", args[0]).get().then(snapshot => { + let doesExist = false; + snapshot.forEach(doc => { + if (doc.exists) doesExist = true; + }); + if (doesExist) { + refs["winston"].debug("Link already exists"); + msg.reply("duplicate link, not adding.").catch(() => { refs["winston"].error("Unable to send reply!") }); + } else { + refs["winston"].debug("Link does not exist, adding to database"); + msg.reply("adding link!").catch(() => { refs["winston"].error("Unable to send reply!") }); + collectionRef.add({ + "link": args[0], + "timestamp": Date.now(), + "seen": false, + "user": msg.author.username + }); + } + }, () => { + refs["winston"].error("Firebase error checking for duplicate links!"); + }); + } else { + refs["winston"].debug("Server responded but link is not reachable, ignoring"); + msg.reply("given URL does not exist on that server!").catch(() => { refs["winston"].error("Unable to send reply!") }); + } + }).catch(() => { + refs["winston"].debug("Server not found, ignoring link"); + msg.reply("given URI is pointing to a server that does not exist!").catch(() => { refs["winston"].error("Unable to send reply!") }); + }); + } else { + refs["winston"].debug("Not an URI, ignoring"); + msg.reply("that link is not a valid URI!").catch(() => { refs["winston"].error("Unable to send reply!") }); + } + } + +} \ No newline at end of file diff --git a/ts-src/class-cmd/Links.ts b/ts-src/class-cmd/Links.ts new file mode 100644 index 0000000..7f3f876 --- /dev/null +++ b/ts-src/class-cmd/Links.ts @@ -0,0 +1,94 @@ +/* Author: D3add3d */ + +import {ICommand} from "../ICommand"; +import * as Discord from "discord.js"; +import * as nodemailer from "nodemailer"; + +export default class Links implements ICommand { + readonly description: string; + readonly name: string; + readonly type: number; + constructor() { + this.description = "`send`s or `list`s links that have not yet been sent"; + this.name = "links"; + this.type = 1; + } + execute(refs: object, msg: Discord.Message, args: Array) { + refs["winston"].info("Links executed by:",msg.author.username); + let content = ""; + if(args[0] === "send") { + refs["database"].collection("links").where("seen", "==", false).get().then(snapshot => { + refs["winston"].debug("Snapshot size :" + snapshot.size); + refs["winston"].debug("Snapshot empty:" + snapshot.empty); + if (!snapshot.empty) { + snapshot.forEach(doc => { + let data = doc.data(); + let tmp = data.user + "," + data.link + "\n"; + content = content + tmp; + refs["database"].collection("links").doc(doc.id).update({"seen": true}); + }); + /* NODEMAILER START */ + let transporter = nodemailer.createTransport({ + host: refs["config"].email.smtp.host, + port: refs["config"].email.smtp.port, + secure: refs["config"].email.smtp.secure, + auth: { + user: refs["config"].email.smtp.auth.user, + pass: refs["config"].email.smtp.auth.pass + } + }); + // setup email data with unicode symbols + let mailOptions = { + from: refs["config"].email.from, // sender address + to: refs["config"].email.to, // list of receivers //links@n-o-d-e.net + subject: '[E-D-G-E] <' + new Date().toDateString() + '> Collection of links from the N-O-D-E community Discord server', // Subject line + text: "Hello,\nI am E-D-G-E, a bot on the N-O-D-E community unofficial Discord server.\nThe attachment contains a list of links submitted by the members of N-O-D-E community unofficial Discord server.\nIf the list contains any hostnames that slipped my filter(e.g. NSFW content) please contact an administrator(" + refs["config"].email.ownerEmail + ") listing the hostnames you want filtered in the e-mail and the bot administrator will add them to the blacklist, thanks!\n\n - Beep-boop-boop, E-D-G-E\n\n\n(This e-mail was sent because command \"sendlinks\" was executed by " + msg.author.username + " on Discord, the user was authorized by snowflake ID: " + msg.author.id + ")", // plain text body + html: "Hello,
I am E-D-G-E, a bot on the N-O-D-E community unofficial Discord server.
The attachment contains a list of links submitted by the members of N-O-D-E community unofficial Discord server.
If the list contains any hostnames that slipped my filter(e.g. NSFW content) please contact an administrator(" + refs["config"].email.ownerEmail + ") listing the hostnames you want filtered in the e-mail and the bot administrator will add them to the blacklist, thanks!

- Beep-boop-boop, E-D-G-E


(This e-mail was sent because command \"sendlinks\" was executed by " + msg.author.username + " on Discord, the user was authorized by snowflake ID: " + msg.author.id + ")", // html body + attachments: [ + { + filename: "links-" + new Date().toDateString() + ".csv", + content: content, + contentType: "text/plain" + } + ] + }; + // send mail with defined transport object + transporter.sendMail(mailOptions, (error, info) => { + if (error) { + refs["winston"].error("Unable to send e-mail"); + msg.reply("I was unable to send the e-mail, please contact my developers and administrator.").catch(() => { refs["winston"].error("Unable to send reply!") }); + refs["winston"].error(error); + refs["winston"].error(info); + return; + } + refs["winston"].info("Sendlinks executed successfully!"); + msg.reply("links sent!").catch(() => { refs["winston"].error("Unable to send reply!") }); + }); + /* NODEMAILER END */ + } else { + refs["winston"].info("Snapshot empty, not sending."); + msg.reply("there is nothing to send.").catch(() => { refs["winston"].error("Unable to send reply!") }); + } + }); + } else if(args[0] === "list") { + refs["database"].collection('links').where("seen", "==", false).get().then(snapshot => { + refs["winston"].debug("Snapshot size :" + snapshot.size); + refs["winston"].debug("Snapshot empty:" + snapshot.empty); + if (!snapshot.empty) { + snapshot.forEach(doc => { + let data = doc.data(); + let tmp = data.user + ": " + data.link + '\n'; + content = content + tmp; + }); + content = "Links:\n" + content; + msg.channel.send(content); + } else { + msg.channel.send("There are no links in the database waiting to be sent."); + } + }); + } else { + msg.reply("invalid or missing argument!").catch(() => { refs["winston"].error("Unable to send reply!") }); + } + } + +} \ No newline at end of file diff --git a/ts-src/class-cmd/Uptime.ts b/ts-src/class-cmd/Uptime.ts new file mode 100644 index 0000000..58a5d76 --- /dev/null +++ b/ts-src/class-cmd/Uptime.ts @@ -0,0 +1,29 @@ +/* Author: D3add3d */ + +import {ICommand} from "../ICommand"; +import * as Discord from "discord.js"; + +export default class Uptime implements ICommand { + readonly description: string; + readonly name: string; + readonly type: number; + constructor() { + this.description = "Gets the bot's uptime - replaces ping"; + this.name = "uptime"; + this.type = 0; + //test + } + execute(refs: object, msg: Discord.Message, args: Array) { + refs["winston"].debug("Uptime command executed by:", msg.author.username); + let uptime = process.uptime(); + let hours = Math.floor(uptime / 3600); + let minutes = Math.floor(uptime / 60 % 60); + let seconds = Math.floor(uptime % 60); + msg.reply("Current uptime is: " + this.pad(hours) + ":" + this.pad(minutes) + ":" + this.pad(seconds)).catch(() => { + refs["winston"].error("Unable to send reply!"); + }); + } + pad(toPad: number): string { + return (toPad < 10 ? "0" : "") + toPad; + } +} \ No newline at end of file diff --git a/ts-src/cmd/help.ts b/ts-src/cmd/help.ts deleted file mode 100644 index 2e28c68..0000000 --- a/ts-src/cmd/help.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* Author: D3add3d */ - -module.exports = { - name: "help", - description: "Lists all commands", - type: 0, - execute(refs, msg) { - let type = 0; - if(msg.author.id === refs.config.discord.owner) { - type = 2; //owner - } else if(msg.member ? msg.member.hasPermission(refs.client.Permissions.FLAGS.MANAGE_MESSAGES, false, true, true) : false) { - type = 1; //mod - } else { - type = 0; //regular - } - refs.winston.debug("type: " + type); - let helpString = "```\nCommands available for you:\n"; - refs.commands.forEach((value, key) => { - refs.winston.debug("key: " + key); - if(type >= value["type"]) { - helpString = helpString.concat("\n", refs.config.discord.prefix, value["name"], " -- ", value["description"], " (", value["type"], ")"); - } - }); - if(type > 0) { - helpString = helpString.concat("\n\nWho can run these commands: 0 - anyone; 1 - moderator; 2 - owner"); - } - helpString = helpString.concat("\n```"); - msg.author.createDM().then(chan => { - chan.send(helpString); - }, () => { - msg.reply(helpString).catch(() => { refs.winston.error("Unable to send reply!") }); - }); - } -}; \ No newline at end of file diff --git a/ts-src/cmd/link.ts b/ts-src/cmd/link.ts deleted file mode 100644 index 2b32a06..0000000 --- a/ts-src/cmd/link.ts +++ /dev/null @@ -1,61 +0,0 @@ -/*Author: D3add3d */ - -import * as validUrl from "valid-url"; -import * as urlExists from "url-exists-deep"; - -module.exports = { - name: "link", - description: "Checks and adds link to the database", - type: 0, - execute(refs, msg, args) { - refs.winston.debug("Link command executed by:", msg.author.username, " ", args[0]); - if (validUrl.isUri(args[0])) { - refs.winston.debug("Link is a valid URI"); - let url = new URL(args[0]); - if(refs.config.email.hostnameBlacklist.includes(url.hostname)) { - msg.reply("that hostname is blacklisted!").catch(() => { refs.winston.error("Unable to send reply!") }); - refs.winston.info("User ", msg.author.username, " tried to add blacklisted link!"); - return; - } - urlExists(args[0]).then(function (response) { - refs.winston.debug("HTTP/S response returned for link"); - if (response) { - refs.winston.debug("200 code response for link"); - let collectionRef = refs.database.collection("links"); - refs.winston.debug("Querying database for existing link..."); - collectionRef.where("link", "==", args[0]).get().then(snapshot => { - let doesExist = false; - snapshot.forEach(doc => { - if (doc.exists) doesExist = true; - }); - if (doesExist) { - refs.winston.debug("Link already exists"); - msg.reply("duplicate link, not adding.").catch(() => { refs.winston.error("Unable to send reply!") }); - } else { - refs.winston.debug("Link does not exist, adding to database"); - msg.reply("adding link!").catch(() => { refs.winston.error("Unable to send reply!") }); - collectionRef.add({ - "link": args[0], - "timestamp": Date.now(), - "seen": false, - "user": msg.author.username - }); - } - }, () => { - refs.winston.error("Firebase error checking for duplicate links!"); - }); - } else { - refs.winston.debug("Server responded but link is not reachable, ignoring"); - msg.reply("given URL does not exist on that server!").catch(() => { refs.winston.error("Unable to send reply!") }); - } - }).catch(() => { - refs.winston.debug("Server not found, ignoring link"); - msg.reply("given URI is pointing to a server that does not exist!").catch(() => { refs.winston.error("Unable to send reply!") }); - }); - } else { - refs.winston.debug("Not an URI, ignoring"); - msg.reply("that link is not a valid URI!").catch(() => { refs.winston.error("Unable to send reply!") }); - } - } - -}; \ No newline at end of file diff --git a/ts-src/cmd/links.ts b/ts-src/cmd/links.ts deleted file mode 100644 index 0c0947a..0000000 --- a/ts-src/cmd/links.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* Author: D3ad3dd */ - -import * as nodemailer from "nodemailer"; - -module.exports = { - name: "links", - description: "`send`s or `list`s links that have not yet been sent", - type: 1, - execute(refs, msg, args) { - refs.winston.info("Links executed by:",msg.author.username); - let content = ""; - if(args[0].equals("send")) { - refs.database.collection("links").where("seen", "==", false).get().then(snapshot => { - refs.winston.debug("Snapshot size :" + snapshot.size); - refs.winston.debug("Snapshot empty:" + snapshot.empty); - if (!snapshot.empty) { - snapshot.forEach(doc => { - let data = doc.data(); - let tmp = data.user + "," + data.link + "\n"; - content = content + tmp; - refs.database.collection("links").doc(doc.id).update({"seen": true}); - }); - /* NODEMAILER START */ - let transporter = nodemailer.createTransport({ - host: refs.config.email.smtp.host, - port: refs.config.email.smtp.port, - secure: refs.config.email.smtp.secure, - auth: { - user: refs.config.email.smtp.auth.user, - pass: refs.config.email.smtp.auth.pass - } - }); - // setup email data with unicode symbols - let mailOptions = { - from: refs.config.email.from, // sender address - to: refs.config.email.to, // list of receivers //links@n-o-d-e.net - subject: '[E-D-G-E] <' + new Date().toDateString() + '> Collection of links from the N-O-D-E community Discord server', // Subject line - text: "Hello,\nI am E-D-G-E, a bot on the N-O-D-E community unofficial Discord server.\nThe attachment contains a list of links submitted by the members of N-O-D-E community unofficial Discord server.\nIf the list contains any hostnames that slipped my filter(e.g. NSFW content) please contact an administrator(" + refs.config.email.ownerEmail + ") listing the hostnames you want filtered in the e-mail and the bot administrator will add them to the blacklist, thanks!\n\n - Beep-boop-boop, E-D-G-E\n\n\n(This e-mail was sent because command \"sendlinks\" was executed by " + msg.author.username + " on Discord, the user was authorized by snowflake ID: " + msg.author.id + ")", // plain text body - html: "Hello,
I am E-D-G-E, a bot on the N-O-D-E community unofficial Discord server.
The attachment contains a list of links submitted by the members of N-O-D-E community unofficial Discord server.
If the list contains any hostnames that slipped my filter(e.g. NSFW content) please contact an administrator(" + refs.config.email.ownerEmail + ") listing the hostnames you want filtered in the e-mail and the bot administrator will add them to the blacklist, thanks!

- Beep-boop-boop, E-D-G-E


(This e-mail was sent because command \"sendlinks\" was executed by " + msg.author.username + " on Discord, the user was authorized by snowflake ID: " + msg.author.id + ")", // html body - attachments: [ - { - filename: "links-" + new Date().toDateString() + ".csv", - content: content, - contentType: "text/plain" - } - ] - }; - // send mail with defined transport object - transporter.sendMail(mailOptions, (error, info) => { - if (error) { - refs.winston.error("Unable to send e-mail"); - msg.reply("I was unable to send the e-mail, please contact my developers and administrator.").catch(() => { refs.winston.error("Unable to send reply!") }); - refs.winston.error(error); - refs.winston.error(info); - return; - } - refs.winston.info("Sendlinks executed successfully!"); - msg.reply("links sent!").catch(() => { refs.winston.error("Unable to send reply!") }); - }); - /* NODEMAILER END */ - } else { - refs.winston.info("Snapshot empty, not sending."); - msg.reply("there is nothing to send.").catch(() => { refs.winston.error("Unable to send reply!") }); - } - }); - } else if(args[0].equals("list")) { - refs.database.collection('links').where("seen", "==", false).get().then(snapshot => { - refs.winston.debug("Snapshot size :" + snapshot.size); - refs.winston.debug("Snapshot empty:" + snapshot.empty); - if (!snapshot.empty) { - snapshot.forEach(doc => { - let data = doc.data(); - let tmp = data.user + ": " + data.link + '\n'; - content = content + tmp; - }); - content = "Links:\n" + content; - msg.channel.send(content); - } else { - msg.channel.send("There are no links in the database waiting to be sent."); - } - }); - } else { - msg.reply("invalid or missing argument!").catch(() => { refs.winston.error("Unable to send reply!") }); - } - } - -}; \ No newline at end of file diff --git a/ts-src/cmd/ping.ts b/ts-src/cmd/ping.ts deleted file mode 100644 index 4c86581..0000000 --- a/ts-src/cmd/ping.ts +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - name: "ping", - description: "Ping-Pong command", - type: 0, - execute(refs, msg) { - refs.winston.debug("Ping command executed by:", msg.author.username); - msg.channel.send("Pong"); - } -}; \ No newline at end of file diff --git a/ts-src/cmd/stop.ts b/ts-src/cmd/stop.ts deleted file mode 100644 index 2300ee7..0000000 --- a/ts-src/cmd/stop.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* Author: D3add3d */ - -module.exports = { - name: "stop", - description: "Stops the bot", - type: 2, - execute(refs, msg) { - refs.winston.debug("Stop command executed by:", msg.author.username); - msg.channel.send("Stopping."); - refs.winston.info("Stopping."); - setTimeout(() => { - refs.client.destroy(); - process.exit(0) - }, 1000); - } -};