diff --git a/BOTLIST.md b/legacy/BOTLIST.md similarity index 100% rename from BOTLIST.md rename to legacy/BOTLIST.md diff --git a/src/discord.js b/src/discord.js index f20cdcb..899a37a 100644 --- a/src/discord.js +++ b/src/discord.js @@ -35,8 +35,8 @@ module.exports.setup = async function() }); // settup events - Events.setup(); - Commands.registerCommands(); + await Events.setup(); + await Commands.registerCommands(); this.bot.connect(); } diff --git a/src/discordcommands.js b/src/discordcommands.js index 7c0d2ce..8f187ec 100644 --- a/src/discordcommands.js +++ b/src/discordcommands.js @@ -1,5 +1,6 @@ const Logger = require('./logger.js'); const Database = require('./database.js'); + const Discord = require('./discord.js'); const DiscordHelpers = require('./discordhelpers.js'); const DiscordEmbed = require('./discordembedbuilder.js'); @@ -26,9 +27,6 @@ module.exports.registerCommands = async function() { GuildsAndPrefixs[guild.id] = guild.prefix; } - - console.log(GuildsAndPrefixs); - } module.exports.newMessage = async function(message) @@ -56,12 +54,6 @@ module.exports.newMessage = async function(message) } } - // THIS IS JUST FOR TESTING - let content = {}; - content.embed = new DiscordEmbed({title:message.content}).GetSendableObject - let logchannel = (await Database.FetchGuild(message.guildID)).logchannel; - Discord.bot.createMessage(logchannel, content); - const msg = message.content.split(' '); // does the message start with the prefix diff --git a/src/discordembedbuilder.js b/src/discordembedbuilder.js index 3cd640d..d633615 100644 --- a/src/discordembedbuilder.js +++ b/src/discordembedbuilder.js @@ -1,39 +1,184 @@ - -// Discord embed bulilder seeing as eris doesn't specify that -// the webserver and thus the thing will be written in go(?) -// regardless, this just builds embeds and im not sure why -// im defining webserver behaviour here +// https://github.com/Fuechschen/eris-embed-builder/blob/master/lib/RichEmbed.js +// MIT License class RichEmbed { - - constructor(e) - { - // defines that it's a richembed - // which is all i'll be supporting - // because nothing else is really needed lol + /** + * The embed object to create new embeds easily. + * @constructor + */ + constructor(data = {}) { + this._title = data.title; this._type = 'rich'; + this._description = data.description; + this._url = data.url; + this._timestamp = data.timestamp; + this._colour = data.colour; - e.title ? this._title = e.title : this._title = 'Title Undefined'; + this._footer = data.footer; + this._image = data.image; + this._thumbnail = data.thumbnail; + this._video = data.video; + this._provider = data.provider; + this._author = data.author; + this._fields = data.fields || []; + if (this._title && this._title.length > 256) throw new Error('The _title should not be longer than 265 characters.'); + if (this._description && this._description.length > 2048) throw new Error('The description should not be longer than 265 characters.'); + if (this._colour && (this._colour < 0 || this._colour > 0xFFFFFF)) throw new Error('Colour must be a valid HEX-Colour for HTML or be an integer within 0 - 16777215'); + if (this._colour && isNaN(this._colour)) throw new Error('Could not convert colour to number.'); + if (this._footer && this._footer.text.length > 2048) throw new Error('A footer may not be longer than 2048 characters'); + if (this._fields.length >= 25) throw new Error('You cannot add more than 25 fields.'); + for (let f of this._fields) { + if (f.name.length > 256) throw new Error('A field name may not be longer than 256 characters.'); + if (f.value.length > 1024) throw new Error('A field value may not be longer than 1024 characters.'); + } } - get GetSendableObject() - { + /** + * Set the _title of the embed. + * @param {String} title + * @return {RichEmbed} + */ + title(title) { + if (title.length > 256) throw new Error('The _title should not be longer than 265 characters.'); + this._title = title; + return this; + } + + /** + * Set the description of the embed. + * @param {String} description + * @return {RichEmbed} + */ + description(description) { + if (description.length > 2048) throw new Error('The description should not be longer than 265 characters.'); + this._description = description; + return this; + } + + /** + * Set the url of the embed. + * @param {String} url + * @return {RichEmbed} + */ + url(url) { + this._url = url; + return this; + } + + /** + * Set the colour of the embed. + * @param {String/Number} colour + * @return {RichEmbed} + */ + colour(colour) { + let base = 10; + if (typeof colour === 'string' && colour.startsWith('#')) { + colour = colour.replace('#', ''); + base = 16; + } + colour = parseInt(colour, base); + if (colour < 0 || colour > 0xFFFFFF) throw new Error('Colour must be a valid HEX-colour for HTML or be an integer within 0 - 16777215'); + else if (colour && isNaN(colour)) throw new Error('Could not convert colour to number.'); + this._colour = colour; + return this; + } + + /** + * Set the author of the embed. + * @param {String} name The author name. + * @param {String} [icon_url] The icon url, only http-urls will work. + * @param {String} [url] The author-url. + * @return {RichEmbed} + */ + author(name, icon_url, url) { + this._author = {name, icon_url, url}; + return this; + } + + /** + * Set the timestamp of the embed. + * @param {Date} timestamp + * @return {RichEmbed} + */ + timestamp(timestamp = new Date()) { + this._timestamp = timestamp; + return this; + } + + /** + * Add a field to an embed. + * @param {String} name + * @param {String} value + * @param {Boolean} inline + * @return {RichEmbed} + */ + field(name, value, inline = false) { + if (this._fields.length >= 25) throw new Error('You cannot add more than 25 fields.'); + if (name.length > 256) throw new Error('A field name may not be longer than 256 characters.'); + if (value.length > 1024) throw new Error('A field value may not be longer than 1024 characters.'); + this._fields.push({name, value, inline}); + return this; + } + + /** + * Set the embed thumbnail. + * @param {String} url The image url. + * @param {Object} [options] + * @param {Number} [options.height] The image height. + * @param {Number} [options.width] The image width. + * @return {RichEmbed} + */ + thumbnail(url, options = {}) { + this._thumbnail = {url, height: options.height, width: options.width}; + return this; + } + + /** + * Set the embed image. + * @param {String} url The image url. + * @param {Object} [options] + * @param {Number} [options.height] The image height. + * @param {Number} [options.width] The image width. + * @return {RichEmbed} + */ + image(url, options = {}) { + this._image = {url, height: options.height, width: options.width}; + return this; + } + + /** + * Set the embed footer. + * @param {String} text Text which should be in the footer. + * @param {String} [icon_url] The icon-url for the footer + * @return {RichEmbed} + */ + footer(text, icon_url) { + if (text.length > 2048) throw new Error('A footer may not be longer than 2048 characters'); + this._footer = {text, icon_url}; + return this; + } + + /** + * Returns the final embed. + * @return {Embed} + */ + get sendable() { return { title: this._title, type: this._type, - description: "BRUH", - // url: this._url, - // timestamp: this._timestamp, - // color: this._color, - // footer: this._footer, - // image: this._image, - // thumbnail: this._thumbnail, - // video: this._video, - // provider: this._provider, - // author: this._author, - // fields: this._fields - } + description: this._description, + url: this._url, + timestamp: this._timestamp, + color: this._colour, + footer: this._footer, + image: this._image, + thumbnail: this._thumbnail, + video: this._video, + provider: this._provider, + author: this._author, + fields: this._fields + }; } } diff --git a/src/discordevents.js b/src/discordevents.js index b1fbdd1..f2a664f 100644 --- a/src/discordevents.js +++ b/src/discordevents.js @@ -1,14 +1,23 @@ const Logger = require('./logger.js'); -const Discord = require('./discord.js'); +const Database = require('./database.js'); const Commands = require('./discordcommands.js'); +const Discord = require('./discord.js'); +const DiscordHelpers = require('./discordhelpers.js'); +const DiscordEmbed = require('./discordembedbuilder.js'); + +const Eris = require('eris'); + + +let GuildsAndLogChannels = []; + module.exports.setup = async function() { Logger.info('Setting up discord listeners'); Discord.bot.on('channelCreate', async (channel) => {ChannelCreate(channel)}); Discord.bot.on('channelDelete', async (channel) => {ChannelDelete(channel)}); - Discord.bot.on('channelPinUpdate', async (channel, timestamp, oldtimestamp) => {ChannelPinUpdate()}); + Discord.bot.on('channelPinUpdate', async (channel, timestamp, oldtimestamp) => {ChannelPinUpdate(channel, timestamp, oldtimestamp)}); Discord.bot.on('channelUpdate', async (channel, oldchannel) => {}); Discord.bot.on('guildBanAdd', async (guild, user) => {}); Discord.bot.on('guildBanRemove', async (guild, user) => {}); @@ -42,8 +51,95 @@ module.exports.setup = async function() Discord.bot.on('warn', async (message, id) => {}); Discord.bot.on('error', async (error, id) => {}); Discord.bot.on('disconnect', async (options) => {}); + + // settup log channel cache + const guilds = await Database.FetchAllGuilds(); + + for (guild of guilds) + { + GuildsAndLogChannels[guild.id] = guild.logchannel; + } } // Handlers +async function GetLogChannel(guildID) +{ + // if there's aready a fallback channel - need to add a clause to update + // this if the guild's log channel is changed during runtime which is likely + if (GuildsAndLogChannels[guildID] != -1) return GuildsAndLogChannels[guildID]; + // if there's no log channel check if the database has been updated + if (GuildsAndLogChannels[guildID] == -1) + { + const guild = await Database.FetchGuild(guildID); + return guild == -1 ? -1 : guild.logchannel; + } +} +// Richembed defines +// update: blue #328fA8 +// delete / leave: red #E0532B +// create / join: green #42A832 +// everything else: yellow #A84C32 +// customisable features in the future? + +async function ChannelCreate(channel) +{ + if (!channel.guild) return; + const FallbackChannel = await GetLogChannel(channel.guild.id) + if (FallbackChannel == -1) return; + + const Type = channel.type == 0 ? 'Text' : 'Voice'; + + let embed = new DiscordEmbed({ + title: `${Type} Channel Created`, + fields: [ + { name: 'Name', value: channel.mention, inline: true }, + { name: 'Parent Catagory', value: DiscordHelpers.GetGuildCatatory(channel.guild, channel.parentID).name, inline: true } + ], + timestamp: new Date(), + footer: { text: `ID: ${channel.id}` } + }) + + embed.colour('#42A832'); + embed.url('https://logori.xyz') + + Discord.bot.createMessage(FallbackChannel, {embed: embed.sendable}); + +} + +async function ChannelDelete(channel) +{ + if (!channel.guild) return; + const FallbackChannel = await GetLogChannel(channel.guild.id) + if (FallbackChannel == -1) return; + + const Type = channel.type == 0 ? 'Text' : 'Voice'; + + let embed = new DiscordEmbed({ + title: `${Type} Channel Deleted`, + fields: [ + { name: 'Name', value: channel.name, inline: true }, + { name: 'Parent Catagory', value: DiscordHelpers.GetGuildCatatory(channel.guild, channel.parentID).name, inline: true } + ], + timestamp: new Date(), + footer: { text: `ID: ${channel.id}` } + }) + + embed.colour('#E0532B'); + embed.url('https://logori.xyz') + + Discord.bot.createMessage(FallbackChannel, {embed: embed.sendable}); +} + +async function ChannelPinUpdate(channel, timestamp, oldtimestamp) +{ + if (!channel.guild) return; + const FallbackChannel = await GetLogChannel(channel.guild.id) + if (FallbackChannel == -1) return; + + let pins = await channel.getPins(); + + console.log(pins); + +} diff --git a/src/discordhelpers.js b/src/discordhelpers.js index 1872cd7..ede3470 100644 --- a/src/discordhelpers.js +++ b/src/discordhelpers.js @@ -1,6 +1,3 @@ -const Eris = require('eris'); -module.exports.IsUserAdmin = function (member) -{ - return member.permission.has('administrator') || member.id == process.env.BOT_OWNER; -} +module.exports.IsUserAdmin = (member) => member.permission.has('administrator') || member.id == process.env.BOT_OWNER; +module.exports.GetGuildCatatory = (guild, catid) => guild.channels.find(c => c.id == catid);