diff --git a/.gitignore b/.gitignore index 58d4190..a849b79 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /node_modules/ -/config.json \ No newline at end of file +/config.json +/logoriDB/ \ No newline at end of file diff --git a/index.js b/index.js index 953db89..06f6bd7 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,6 @@ const configM = require('./src/configManager'); const logger = require('./src/logger'); const commandH = require('./src/commandHandler'); -// TODO: botClient.js if (!configM.loadConfig('./config.json')) { logger.error('No config file has been found in the directory, please configure the template that has been created.'); @@ -11,7 +10,10 @@ logger.log('Config loaded'); const bot = require('./src/botClient').bot; require('./src/commandLoader').load(); -logger.log('Commands loaded'); +logger.log('Modules loaded'); + +require('./src/dbEventInterface'); +logger.log('Database Loaded'); bot.on('ready', () => { logger.log(bot.user.username + '#' + bot.user.discriminator); @@ -27,6 +29,7 @@ bot.on("messageCreate", (msg) => { if (content === msg.content) return; if (msg.author.bot) return; if (msg.author === bot.user) return; + if (msg.channel.type !== 0) return; let trimmedContent = content.trim(); commandH.apply(trimmedContent, msg); }); diff --git a/package-lock.json b/package-lock.json index 797eb76..fc71985 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,14 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "requires": { + "xtend": "4.0.1" + } + }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -104,6 +112,15 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, + "deferred-leveldown": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", + "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", + "requires": { + "abstract-leveldown": "5.0.0", + "inherits": "2.0.3" + } + }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -114,6 +131,18 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" }, + "encoding-down": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz", + "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==", + "requires": { + "abstract-leveldown": "5.0.0", + "inherits": "2.0.3", + "level-codec": "9.0.0", + "level-errors": "2.0.0", + "xtend": "4.0.1" + } + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -132,11 +161,24 @@ "ws": "5.2.1" } }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "1.0.1" + } + }, "expand-template": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz", "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==" }, + "fast-future": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fast-future/-/fast-future-1.0.2.tgz", + "integrity": "sha1-hDWpqqAteSSNF9cE52JZMB2ZKAo=" + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -190,6 +232,71 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "level": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/level/-/level-4.0.0.tgz", + "integrity": "sha512-4epzCOlEcJ529NOdlAYiuiakS/kZTDdiKSBNJmE1B8bsmA+zEVwcpxyH86qJSQTpOu7SODrlaD9WgPRHLkGutA==", + "requires": { + "level-packager": "3.1.0", + "leveldown": "4.0.1", + "opencollective-postinstall": "2.0.0" + } + }, + "level-codec": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.0.tgz", + "integrity": "sha512-OIpVvjCcZNP5SdhcNupnsI1zo5Y9Vpm+k/F1gfG5kXrtctlrwanisakweJtE0uA0OpLukRfOQae+Fg0M5Debhg==" + }, + "level-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.0.tgz", + "integrity": "sha512-AmY4HCp9h3OiU19uG+3YWkdELgy05OTP/r23aNHaQKWv8DO787yZgsEuGVkoph40uwN+YdUKnANlrxSsoOaaxg==", + "requires": { + "errno": "0.1.7" + } + }, + "level-iterator-stream": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz", + "integrity": "sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig==", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "xtend": "4.0.1" + } + }, + "level-packager": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-3.1.0.tgz", + "integrity": "sha512-UxVEfK5WH0u0InR3WxTCSAroiorAGKzXWZT6i+nBjambmvINuXFUsFx2Ai3UIjUUtnyWhluv42jMlzUZCsAk9A==", + "requires": { + "encoding-down": "5.0.4", + "levelup": "3.1.0" + } + }, + "leveldown": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-4.0.1.tgz", + "integrity": "sha512-ZlBKVSsglPIPJnz4ggB8o2R0bxDxbsMzuQohbfgoFMVApyTE118DK5LNRG0cRju6rt3OkGxe0V6UYACGlq/byg==", + "requires": { + "abstract-leveldown": "5.0.0", + "bindings": "1.3.0", + "fast-future": "1.0.2", + "nan": "2.10.0", + "prebuild-install": "4.0.0" + } + }, + "levelup": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.0.tgz", + "integrity": "sha512-MVWwo204mvTeTQ/9GLfJ2CkwurMGH8dDu+cXOrdnJE6qHa4sun9xOSyFuUV8zpJJ+re8zyH47c/O0U+zth4CzA==", + "requires": { + "deferred-leveldown": "4.0.2", + "level-errors": "2.0.0", + "level-iterator-stream": "2.0.3", + "xtend": "4.0.1" + } + }, "mimic-response": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", @@ -262,6 +369,11 @@ "wrappy": "1.0.2" } }, + "opencollective-postinstall": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.0.tgz", + "integrity": "sha512-XAe80GycLe2yRGnJsUtt+EO5lk06XYRQt4kJJe53O2kJHPZJOZ+XMF/b47HW96e6LhfKVpwnXVr/s56jhV98jg==" + }, "opusscript": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/opusscript/-/opusscript-0.0.4.tgz", @@ -300,6 +412,11 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, "pump": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", diff --git a/package.json b/package.json index c0e0dc7..beb9ea9 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "dependencies": { "bufferutil": "^3.0.5", "eris": "^0.8.6", + "level": "^4.0.0", "uws": "^10.148.1" } } diff --git a/src/cmd/debug.js b/src/cmd/debug.js index e5bea02..24a39eb 100644 --- a/src/cmd/debug.js +++ b/src/cmd/debug.js @@ -7,5 +7,12 @@ exports.loadModule = function loadModule () { }); commandH.endpoint('^ping (.*)$', (match, message) => { bot.createMessage(message.channel.id, 'Pong : ' + match[1]); + let time = new Date(); + bot.once('messageCreate', (msg) => { + let ms = new Date().getTime() - time.getTime(); + if (msg.channel !== message.channel) return; + if (msg.author !== bot.user) return; + bot.createMessage(msg.channel.id, ms + ' ms'); + }); }); -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/cmd/events.js b/src/cmd/events.js new file mode 100644 index 0000000..ec6de17 --- /dev/null +++ b/src/cmd/events.js @@ -0,0 +1,6 @@ +const commandH = require('../commandHandler'); +const bot = require('../botClient').bot; + +exports.loadModule = function loadModule () { + +}; \ No newline at end of file diff --git a/src/cmd/main.js b/src/cmd/main.js new file mode 100644 index 0000000..90e75e3 --- /dev/null +++ b/src/cmd/main.js @@ -0,0 +1,72 @@ +const commandH = require('../commandHandler'); +const bot = require('../botClient').bot; +const dbEI = require('../dbEventInterface'); + +exports.loadModule = function loadModule () { + commandH.endpoint('^(?:init|set)serv$', async (match, message) => { + if (!message.member.permission.has('administrator')) return; + try { + await dbEI.initServer(message.channel.guild.id, message.channel.id); + bot.createMessage(message.channel.id, 'Server successfully set'); + } + catch(e) { + console.log(e); + bot.createMessage(message.channel.id, 'An error happened'); + } + }); + commandH.endpoint('^debugserv$', async (match, message) => { + dbEI.debugServer(message.channel.guild.id); + }); + commandH.endpoint('^set-channel(?: <#(.+?)>)?$', async (match, message) => { + let channelId = message.channel.id; + if (match[1]) { + channelId = match[1]; + } + // TODO: Check if the set channel is in this guild + dbEI.setFallbackChannel(message.channel.guild.id, channelId); + bot.createMessage(message.channel.id, 'Fallback set to that channel, all the event logging will be done there by default. A message will be sent in that channel to make sure it is correct.'); + bot.createMessage(channelId, `<@${message.author.id}>, this is now the fallback channel.`); + }); + commandH.endpoint('^event(?:-set)? (.+) msg (.+)$', async (match, message) => { + dbEI.setEventMsg(message.channel.guild.id, match[1], match[2]); + bot.createMessage(message.channel.id, 'Event message set'); + }); + commandH.endpoint('^event(?:-set)? (.+) channel(?: (?:<#(.+?)>|(fallback|f)))?$', async (match, message) => { + let channelId = message.channel.id; + if (match[2]) { + channelId = match[2]; + } + else if (match[3]) { + channelId = 'f'; + } + dbEI.setEventChannel(message.channel.guild.id, match[1], channelId); + if (channelId === 'f') { + bot.createMessage(message.channel.id, 'This event\'s channel has been set to the **fallback channel**'); + } + else { + bot.createMessage(message.channel.id, `Event channel set to <#${channelId}>. The fallback channel for that even has been overriden. To bind again the event to the fallback channel, execute \`event ${match[1]} channel fallback\``); + } + }); + commandH.endpoint('^event(-set)? (.+) (.+)$', async (match, message) => { + let newState = true; + if (match[3]) { + if (match[3] === 'enable' || match[3] === 'true') { + newState = true; + } + else if (match[3] === 'disable' || match[3] === 'false') { + newState = false; + } + else { + bot.createMessage(message.channel.id, `Invalid option, the possibilities are : \`event${match[1] ? match[1] : ''} ${match[2]} (enable|true|disable|false)\``); + return; + } + } + dbEI.setEventEnable(message.channel.guild.id, match[2], newState); + if (newState) { + bot.createMessage(message.channel.id, `Event ${match[2]} has been **enabled**`); + } + else { + bot.createMessage(message.channel.id, `Event ${match[2]} has been **disabled**`); + } + }); +}; \ No newline at end of file diff --git a/src/dbEventInterface.js b/src/dbEventInterface.js new file mode 100644 index 0000000..c7113bd --- /dev/null +++ b/src/dbEventInterface.js @@ -0,0 +1,225 @@ +const level = require('level'); +const zlib = require('zlib'); + +let db = level('./logoriDB'); // Make that path customizable + +function put(key, value) { + return new Promise((resolve, reject) => { + db.put(key, value, (err) => { + if (err) { + reject(err); + return; + } + resolve(); + }); + }); +} + +function get(key) { + return new Promise((resolve, reject) => { + db.get(key, (err, value) => { + if (err) { + reject(err); + return; + } + resolve(value); + }); + }); +} + +function deflateObj(obj) { + let text = JSON.stringify(obj); + let compressed = zlib.deflateSync(text).toString('base64'); + return compressed; +} + +function inflateObj(str) { + let bufferCompressed = new Buffer(str, 'base64'); + let text = zlib.inflateSync(bufferCompressed).toString(); + return JSON.parse(text); +} + +/* const eventsInfoDefault = { + doChannelCreate: true, + channelCreateMsg: '', + doChannelDelete: true, + channelDeleteMsg: '', + doChannelPinUpdate: true, + channelPinUpdateMsg: '', + doChannelUpdate: true, + channelUpdateMsg: '', + doGuildBanAdd: true, + guildBanAddMsg: '', + doGuildBanRemove: true, + guildBanRemoveMsg: '', + doGuildEmojisUpdate: true, + guildEmojisUpdateMsg: '', + doGuildMemberAdd: true, + guildMemberAddMsg: '', + doGuildMemberRemove: true, + guildMemberRemoveMsg: '', + doGuildMemberUpdate: true, + guildMemberUpdateMsg: '', + doGuildRoleCreate: true, + guildRoleCreateMsg: '', +}; */ + +exports.initServer = function initServer(id, cId) { + let obj = { + fallbackChannelId: cId, + eventsInfo: { + channelCreate: { + d: true, + msg: '', + c: 'f', + }, + channelDelete: { + d: true, + msg: '', + c: 'f', + }, + channelPinUpdate: { + d: true, + msg: '', + c: 'f', + }, + channelUpdate: { + d: true, + msg: '', + c: 'f', + }, + guildBanAdd: { + d: true, + msg: '', + c: 'f', + }, + guildBanRemove: { + d: true, + msg: '', + c: 'f', + }, + guildEmojisUpdate: { + d: true, + msg: '', + c: 'f', + }, + guildMemberAdd: { + d: true, + msg: '', + c: 'f', + }, + guildMemberRemove: { + d: true, + msg: '', + c: 'f', + }, + guildMemberUpdate: { + d: true, + msg: '', + c: 'f', + }, + guildRoleCreate: { + d: true, + msg: '', + c: 'f', + }, + guildRoleDelete: { + d: true, + msg: '', + c: 'f', + }, + guildRoleUpdate: { + d: true, + msg: '', + c: 'f', + }, + guildUpdate: { + d: true, + msg: '', + c: 'f', + }, + messageDelete: { + d: true, + msg: '', + c: 'f', + }, + messageReactionAdd: { + d: true, + msg: '', + c: 'f', + }, + messageReactionRemove: { + d: true, + msg: '', + c: 'f', + }, + messageUpdate: { + d: true, + msg: '', + c: 'f', + }, + presenceUpdate: { + d: true, + msg: '', + c: 'f', + }, + presenceUpdate: { + d: true, + msg: '', + c: 'f', + }, + }, + }; + return put(id, deflateObj(obj)); +}; + +exports.isAlreadyInitted = async function isAlreadyInitted (id) { + try { + await get(id); + return true; + } + catch(e) { + return false; + } +}; + +exports.debugServer = async function debugServer (id) { + console.log(inflateObj(await get(id))); +} + +exports.getEvent = async function getEvent(id, eventName) { + let serverEvents = await get(id); + let obj = inflateObj(serverEvents); + return { + fallbackChannelId: obj.fallbackChannelId, + event: obj.eventsInfo[eventName], + }; +}; + +exports.setFallbackChannel = async function setFallbackChannel(id, cId) { + let serverEvents = await get(id); + let obj = inflateObj(serverEvents); + obj.fallbackChannelId = cId; + return put(id, deflateObj(obj)); +}; + +exports.setEventMsg = async function setEventMsg(id, eventName, msg) { + let serverEvents = await get(id); + let obj = inflateObj(serverEvents); + obj.eventsInfo[eventName].msg = msg; + return put(id, deflateObj(obj)); +}; + +exports.setEventChannel = async function setEventChannel(id, eventName, cId) { + let serverEvents = await get(id); + let obj = inflateObj(serverEvents); + obj.eventsInfo[eventName].c = cId; + return put(id, deflateObj(obj)); +}; + +exports.setEventEnable = async function setEventChannel(id, eventName, state) { + let serverEvents = await get(id); + let obj = inflateObj(serverEvents); + obj.eventsInfo[eventName].d = state; + return put(id, deflateObj(obj)); +}; diff --git a/src/dbManager.js b/src/dbManager.js deleted file mode 100644 index 04779c6..0000000 --- a/src/dbManager.js +++ /dev/null @@ -1,24 +0,0 @@ -const sequelize = require('sequelize'); - -const database = new sequelize('database', 'user', 'password', { - operatorsAliases: false, - dialect: 'sqlite', - logging: false, - storage: 'logoriDB.sqlite', -}); - -const server = database.define('server', { - discordId: { - type: sequelize.STRING, - unique: true, - }, - logChannelId: sequelize.STRING, -}, { - timestamps: false, -}); - -module.exports.sync = function sync(opt) { - return database.sync(opt); -}; - -module.exports.server = server;