From 67772bfeb151df61fcd8fb0141ca431becf3084f Mon Sep 17 00:00:00 2001 From: Wessel T Date: Mon, 18 Feb 2019 15:11:56 +0100 Subject: [PATCH] Add tags! --- TODO.md | 15 +-- src/assets/config/colors.yml | 5 +- src/assets/config/emotes.yml | 24 ++++ src/assets/i18n/en_us/strings.yml | 25 ++++ src/assets/i18n/nl/strings.yml | 26 +++++ src/commands/Discord/Core/locale.js | 9 +- src/commands/Discord/Core/prefix.js | 20 ++-- src/commands/Discord/Information/commands.js | 52 +++++---- src/commands/Discord/Tags/tag-add.js | 109 ++++++++++++++++++ src/commands/Discord/Tags/tag-del.js | 64 ++++++++++ src/commands/Discord/Tags/tag-source.js | 40 +++++++ src/commands/Discord/Tags/tag.js | 34 ++++++ src/core/clients/Discord.js | 12 +- .../Discord/Utils/MessageCollector.js | 25 ++++ src/core/internal/Discord/schema.js | 16 +++ 15 files changed, 423 insertions(+), 53 deletions(-) create mode 100644 src/commands/Discord/Tags/tag-add.js create mode 100644 src/commands/Discord/Tags/tag-del.js create mode 100644 src/commands/Discord/Tags/tag-source.js create mode 100644 src/commands/Discord/Tags/tag.js create mode 100644 src/core/internal/Discord/Utils/MessageCollector.js diff --git a/TODO.md b/TODO.md index 98f6916..e8efdc2 100644 --- a/TODO.md +++ b/TODO.md @@ -5,14 +5,14 @@ - [x] Utility - [x] Commands - [x] Tesseract (Donator) -- [ ] Tags - - [ ] Commands - - [ ] Use +- [x] Tags + - [x] Commands + - [x] Use - [ ] Edit - [ ] Info - - [ ] Create - - [ ] Delete - - [ ] Source + - [x] Create + - [x] Delete + - [x] Source - [ ] Transfer - [ ] Moderation - [ ] Logging @@ -28,8 +28,9 @@ - [ ] Warn - [ ] Purge - [ ] Softban - - [ ] Hack(ban) + - [ ] Lockdown - [ ] Un(mute) + - [ ] Hack(ban) - [ ] Infractions ## Finished (for now): diff --git a/src/assets/config/colors.yml b/src/assets/config/colors.yml index 4013786..f2b0624 100644 --- a/src/assets/config/colors.yml +++ b/src/assets/config/colors.yml @@ -19,7 +19,10 @@ info : guild : 0x7289DA # Blurple commits : 0x7289DA # Blurple avatar : 0x02C2F33 # Dark but not black - commands: 0x02C2F33 # Dark but not black + + commands: + multi : 0x34363C # Dark + single: 0x34363C # Dark image : cat : 0x7289DA # Blurple diff --git a/src/assets/config/emotes.yml b/src/assets/config/emotes.yml index f05cfa4..a65b7c0 100644 --- a/src/assets/config/emotes.yml +++ b/src/assets/config/emotes.yml @@ -28,6 +28,30 @@ core : 6 : <:ok_hand:497396122416054287> # Updated (user) 7 : <:sad:500719642403405824> # Missing permissions (guild) +tags: + exec: <:wumpus_blob:541629681120837648> + + source: + 0 : <:wumpus_blob:541629681120837648> + 1 : <:ok_hand:497396122416054287> + + add: + 0: <:wumpus_blob:541629681120837648> # Invalid name + 1: <:ok_hand:497396122416054287> # Created + 2: <:wumpus_love:506200781549076482> + 3: <:wumpus_love:506200781549076482> + 4: <:wumpus_love:506200781549076482> + 5: <:wumpus_love:506200781549076482> + 6: + + del: + 0: <:wumpus_blob:541629681120837648> + 1: <:wumpus_blob:541629681120837648> + 2: <:wumpus_love:506200781549076482> + 3: <:wumpus_love:506200781549076482> + 4: <:wumpus_love:506200781549076482> + 5: <:wumpus_love:506200781549076482> + logs : ready: '<:spacewump:542723940997529641>' diff --git a/src/assets/i18n/en_us/strings.yml b/src/assets/i18n/en_us/strings.yml index b242a35..8acdafe 100644 --- a/src/assets/i18n/en_us/strings.yml +++ b/src/assets/i18n/en_us/strings.yml @@ -18,6 +18,7 @@ error : - 'Code = "$[err:code]"' - 'Message = "$[err:message]"' - '```' +cancelled: '$[emoji#0] This prompt has been cancelled' cooldown: '$[emoji#0] $[author:mention] **>** This command is on cooldown for **$[cooldown:left]**' votelock: - '$[emoji#0] This command is **votelocked**, upvote [**`Wump`**](https://discordbots.org/bot/318057009188438016/vote) to unlock this command/parameters (It can take up to 10 minutes to register your vote)' @@ -106,6 +107,7 @@ info: - 'Image' - 'Utility' - 'Developer' + - 'Tags' guild: fields: @@ -157,6 +159,29 @@ image: fetching: '$[emoji#0] Fetching a random image, this may take some time...' failed_cache: 'Click here if the image didn''t load properly' +tags: + exec: '$[emoji#0] No tags found matching your query' + + source: '$[emoji#1] **Here''s the source to `$[tag:name]`**: ```$[tag:content]```' + + add: + success: '$[emoji#1] Your tag (`$[tag:name]`) has been created' + invalid: '$[emoji#2] You''ve provided an invalid name for your tag (*It may already exist or it''s the name/alias of a command*)' + content: + - '$[emoji#3] What do you want your tag''s contents to be?' + - '$[emoji#4] Reply to this prompt within **30 seconds**, type `--cancel` to cancel it manually.' + name: + - '$[emoji#5] What do you want to call your tag?' + - '$[emoji#6] Reply to this prompt within **30 seconds**, type `--cancel` to cancel it manually.' + + delete: + busy: '$[emoji#1] Deleting tag `$[tag:name]`, this may take some time...' + done: '$[emoji#2] The tag `$[tag:name]` has been deleted' + perms: '$[emoji#3] You don''t have sufficient permissions to delete this tag (`TAG_OWNER` / `MANAGE_MESSAGES`)' + invalid: '$[emoji#4] No tags found matching your query' + confirm: + - '$[emoji#5] Are you sure you want to delete the tag `$[tag:name]`? **(** **Y**es **/** **N**o **)**' + - '$[emoji#6] Reply to this prompt within **30 seconds**, type `--cancel` to cancel it manually.' games: splatoon: - 'The current maps are:' diff --git a/src/assets/i18n/nl/strings.yml b/src/assets/i18n/nl/strings.yml index af17670..1e81daf 100644 --- a/src/assets/i18n/nl/strings.yml +++ b/src/assets/i18n/nl/strings.yml @@ -18,6 +18,7 @@ error : - 'Code = "$[err:code]"' - 'Bericht = "$[err:message]"' - '```' +cancelled: '$[emoji#0] Dit prompt is geannuleerd' cooldown: '$[emoji#0] $[author:mention] **>** Dit commando is op cooldown voor **$[cooldown:left]**' votelock: - '$[emoji#0] Dit commando is **votelocked**, stem voor [**`Wump`**](https://discordbots.org/bot/318057009188438016/vote) om dit commando/parameters te ontgrendelen (Het kan tot 10 minuten duren om uw stem te registreren)' @@ -106,6 +107,8 @@ info : - 'Plaatjes' - 'Overig' - 'Ontwikkelaar' + - 'Etiketten' + guild: fields: guild: @@ -156,6 +159,29 @@ info : image: fetching: '$[emoji#0] Een willekeurig plaatje aan het ophalen, dit kan enige tijd duren...' failed_cache: 'Klik hier als het plaatje niet is geladen' +tags: + exec: '$[emoji#0] Geen etiketten gevonden met uw zoekopdracht' + + source: '$[emoji#1] **Hier is de bron voor `$[tag:name]`**: ```$[tag:content]```' + + add: + success: '$[emoji#1] Uw etiket (`$[tag:name]`) is aangemaakt' + invalid: '$[emoji#2] U hebt een ongeldige naam opgegeven voor uw etiket (*deze kan al bestaan of is de naam/alias van een commando*)' + content: + - '$[emoji#3] Wat wilt u dat de inhoud van uw etiket is?' + - '$[emoji#4] Reageer op dit prompt binnen ** 30 seconden **, typ `--cancel` om het handmatig te annuleren.' + name: + - '$[emoji#5] Hoe wilt u uw etiket noemen?' + - '$[emoji#4] Reageer op dit prompt binnen ** 30 seconden **, typ `--cancel` om het handmatig te annuleren.' + + delete: + busy: '$[emoji#1] Aan het verwijderen van etiket `$[tag:name]`, dit kan enige tijd duren...' + done: '$[emoji#2] Het etiket `$[tag:name]` is successvol verwijderd' + perms: '$[emoji#3] U hebt onvoldoende machtigingen om dit etiket te verwijderen (`TAG_OWNER` / `MANAGE_MESSAGES`)' + invalid: '$[emoji#4] Geen etiketten gevonden met uw zoekopdracht' + confirm: + - '$[emoji#5] Weet u zeker dat u het etiket `$[tag:name]` wilt verwijderen? **(** **Y**es **/** **N**o **)**' # Keep yes/no as it is! + - '$[emoji#4] Reageer op dit prompt binnen ** 30 seconden **, typ `--cancel` om het handmatig te annuleren.' games: splatoon: diff --git a/src/commands/Discord/Core/locale.js b/src/commands/Discord/Core/locale.js index 5d65c63..d53a52f 100644 --- a/src/commands/Discord/Core/locale.js +++ b/src/commands/Discord/Core/locale.js @@ -34,11 +34,12 @@ module.exports = class Locale extends DiscordCommand { if (user.locale === args[0]) { return msg.channel.createMessage(this.localize(msg.author.locale['core']['locale']['dupe'], { uLocale: user.locale || 'en_us' })); } - - this.bot.m.connection.collection('dUsers').findOneAndUpdate({ 'userId': user.userId }, { $set: { locale: args[0] } }, (err) => { + + this.bot.cache.get('users').some((v, _) => { if (v['userId'] === msg.author.id) v.locale = args[0]; }); + this.bot.m.connection.collection('dUsers').findOneAndUpdate({ 'userId': msg.author.id }, { $set: { locale: args[0] } }, (err) => { if (err) throw err; }); - this.bot.cache.get('users').some((v, _) => { if (v['userId'] === msg.author.id) this.bot.cache.get('users').splice(_, 1); }); + msg.channel.createMessage(this.localize(this.bot.locales.get(args[0])['core']['locale']['changed'], { uLocale: args[0] })); } else if (args.join(' ').includes('-g') || args.join(' ').includes('--guild')) { for (let i = 0; i < args.length; i++) !this.bot.locales.has(args[i]) ? args.splice(i, 1) : undefined; @@ -47,8 +48,8 @@ module.exports = class Locale extends DiscordCommand { if (!this.bot.locales.has(args[0])) return msg.channel.createMessage(this.localize(msg.author.locale['core']['locale']['invalid'])); if (guild.locale === args[0]) return msg.channel.createMessage(this.localize(msg.author.locale['core']['locale']['gdupe'], { gLocale: guild.locale })); - this.bot.m.connection.collection('dGuilds').findOneAndUpdate({ 'guildId': guild.guildId }, { $set: { locale: args[0] } }, (err, d) => { if (err) throw err; }); this.bot.cache.get('guilds').some((v, _) => { if (v['guildId'] === msg.channel.guild.id) this.bot.cache.get('guilds').splice(_, 1); }); + this.bot.m.connection.collection('dGuilds').findOneAndUpdate({ 'guildId': msg.channel.guild.id }, { $set: { locale: args[0] } }, (err, d) => { if (err) throw err; }); msg.channel.createMessage(this.localize(msg.author.locale['core']['locale']['gchanged'], { gLocale: args[0] })); } else { return msg.channel.createMessage({ diff --git a/src/commands/Discord/Core/prefix.js b/src/commands/Discord/Core/prefix.js index 296def4..9bb84e4 100644 --- a/src/commands/Discord/Core/prefix.js +++ b/src/commands/Discord/Core/prefix.js @@ -45,15 +45,13 @@ module.exports = class Prefix extends DiscordCommand { if (user.prefix === prefix) { return msg.channel.createMessage(this.localize(msg.author.locale['core']['prefix']['dupe'], { uPrefix: user.prefix })); } + + // Update user's entry in cache + this.bot.cache.get('users').some((v, _) => { if (v['userId'] === msg.author.id) v.prefix = prefix; }); // Update document - this.bot.m.connection.collection('dUsers').findOneAndUpdate({ 'userId': user.userId }, { $set: { prefix: prefix } }, (err) => { + this.bot.m.connection.collection('dUsers').findOneAndUpdate({ 'userId': msg.author.id }, { $set: { prefix: prefix } }, (err) => { if (err) throw err; }); - // Update user's entry in cache - const entry = this.bot.cache.get('users').filter((v) => v.userId = msg.author.id)[0]; - if (entry) { - entry.prefix = prefix; - } msg.channel.createMessage(this.localize(msg.author.locale['core']['prefix']['changed'], { uPrefix: prefix })); } else if (args.join(' ').includes('-g') || args.join(' ').includes('--guild')) { @@ -68,16 +66,12 @@ module.exports = class Prefix extends DiscordCommand { if (guild.prefix === prefix) { return msg.channel.createMessage(this.localize(msg.author.locale['core']['prefix']['gdupe'], { gPrefix: guild.prefix })); } + // Update user's entry in cache + this.bot.cache.get('users').some((v, _) => { if (v['userId'] === msg.author.id) this.bot.cache.get('users').splice(_, 1); }); // Update document - this.bot.m.connection.collection('dGuilds').findOneAndUpdate({ 'guildId': guild.guildId }, { $set: { prefix: prefix } }, (err) => { + this.bot.m.connection.collection('dGuilds').findOneAndUpdate({ 'guildId': msg.channel.guild.id }, { $set: { prefix: prefix } }, (err) => { if (err) throw err; }); - // Update guild's entry in cache - const entry = this.bot.cache.get('guilds').filter((v) => v.guildId = msg.channel.guild.id)[0]; - if (entry) { - entry.prefix = prefix; - } - msg.channel.createMessage(this.localize(msg.author.locale['core']['prefix']['gchanged'], { gPrefix: prefix })); } else { return msg.channel.createMessage({ diff --git a/src/commands/Discord/Information/commands.js b/src/commands/Discord/Information/commands.js index 210dd6b..7fec835 100644 --- a/src/commands/Discord/Information/commands.js +++ b/src/commands/Discord/Information/commands.js @@ -33,41 +33,47 @@ module.exports = class Commands extends DiscordCommand { msg.channel.createMessage({ embed: { + color : this.bot.col['info']['commands']['single'], description: this.localize(msg.author.locale['info']['commands']['single'].join('\n'), { msg: msg, cmd: cmd }) } }); } else { msg.channel.createMessage({ embed: { - color : this.bot.col['info']['commands'], + color : this.bot.col['info']['commands']['multi'], thumbnail : { url: 'attachment://thumb.png' }, description: this.localize(msg.author.locale['info']['commands']['multi'].join('\n'), { msg: msg }), fields : [ - { - name : msg.author.locale['info']['commands']['fields'][1], - value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'information' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'), - inline: true - }, - { - name : msg.author.locale['info']['commands']['fields'][2], - value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'image' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'), - inline: true - }, - { - name : msg.author.locale['info']['commands']['fields'][3], - value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'utility' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'), - inline: true - }, - { - name : msg.author.locale['info']['commands']['fields'][4], - value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'developer' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'), - inline: true - }, - { + this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'core' && !v.extData.hidden).length >= 1 ? { name : msg.author.locale['info']['commands']['fields'][0], value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'core' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'), inline: true - } + } : undefined, + this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'information' && !v.extData.hidden).length >= 1 ? { + name : msg.author.locale['info']['commands']['fields'][1], + value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'information' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'), + inline: true + } : undefined, + this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'image' && !v.extData.hidden).length >= 1 ? { + name : msg.author.locale['info']['commands']['fields'][2], + value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'image' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'), + inline: true + } : undefined, + this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'utility' && !v.extData.hidden).length >= 1 ? { + name : msg.author.locale['info']['commands']['fields'][3], + value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'utility' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'), + inline: true + } : undefined, + this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'developer' && !v.extData.hidden).length >= 1 ? { + name : msg.author.locale['info']['commands']['fields'][4], + value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'developer' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'), + inline: true + } : undefined, + this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'tags' && !v.extData.hidden).length >= 1 ? { + name : msg.author.locale['info']['commands']['fields'][5], + value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'tags' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'), + inline: true + } : undefined ] } }, diff --git a/src/commands/Discord/Tags/tag-add.js b/src/commands/Discord/Tags/tag-add.js new file mode 100644 index 0000000..36d2e59 --- /dev/null +++ b/src/commands/Discord/Tags/tag-add.js @@ -0,0 +1,109 @@ +const { DiscordCommand } = require('../../../core'); + +const m = require('moment'); + +module.exports = class TagAdd extends DiscordCommand { + constructor(bot) { + super(bot, { + name : 'tag-add', + syntax : 'tag-add <...name:str> <..content:string>', + aliases : [ 'tagadd', 'addtag', 'createtag', 'tagcreate', 'maketag', 'make-tag', 'tag-create' ], + argument : [ '<...name:str>', '<..content:string>' ], + description : 'Create a tag', + + hidden : false, + enabled : true, + cooldown : 1000, + category : 'Tags', + ownerOnly : false, + guildOnly : true, + permissions : [] + }); + } + + async execute(msg, args) { + + let components = args.join(' ').split(/\|/g); + let tag = { + name : undefined, + uses : 0, + content : undefined, + creation: new Date(), + + history: [ + `TAG_CREATE:${msg.author.id}@${m(new Date()).format('DD-MM-YYYY')}` + ], + author : { + id : msg.author.id, + name : msg.author.username, + guild : msg.channel.guild.id, + discrim: msg.author.discriminator + } + }; + + // Delete all empty elements in `components` + components = components.filter((v) => { + return v.length >= 1; + }); + + try { + let mess; + + if (!components[0]) { + mess = await msg.channel.createMessage(this._localize(msg.author.locale.tags.add.name.join('\n'))); + const name = await this.bot.collector.awaitMessage(msg.channel.id, msg.author.id, 30e3); + + if (!name || name.content.toLowerCase() === '--cancel') { + return mess.edit(this._localize(msg.author.locale.cancelled)); + } + + tag.name = name.content.slice(0, 50).toLowerCase().trim(); + } else tag.name = components[0].slice(0, 50).toLowerCase().trim(); + + if (!components[1]) { + mess = mess ? await mess.edit(this._localize(msg.author.locale.tags.add.content.join('\n'))) : await msg.channel.createMessage(this._localize(msg.author.locale.tags.add.content.join('\n'))); + const content = await this.bot.collector.awaitMessage(msg.channel.id, msg.author.id, 30e3); + + if (!content || content.content.toLowerCase() === '--cancel') { + return mess.edit(this._localize(msg.author.locale.cancelled)); + } + + tag.content = content.content.slice(0, 1950).trim(); + } else { + components.shift(); + tag.content = components.join('|').slice(0, 1950).trim(); + } + + if (tag.content && tag.name && mess) { + mess.delete().catch(() => { return; }); + } + } catch(ex) { + throw ex; + } finally { + let entry = await this.bot.m.connection.collection('dTags').findOne({ name: tag.name, 'author.guild': msg.channel.guild.id }); + if (entry !== null || this.bot.cmds.filter((v) => v.extData.name === tag.name || v.extData.aliases.includes(tag.name)).length > 0) { + + return msg.channel.createMessage(this._localize(msg.author.locale.tags.add.invalid)); + } + + entry = new this.bot.schema.tag(tag); + await entry.save(); + msg.channel.createMessage(this._localize(msg.author.locale.tags.add.success, { name: tag.name.replace(/`/g, '`\u200b') })); + } + } + + _localize(msg, extData) { + if (extData) { + msg = msg.replace(/\$\[tag:name]/g, extData.name); + } + + return msg + .replace(/\$\[emoji#0]/g, this.bot.emote('tags', 'add', '0')) + .replace(/\$\[emoji#1]/g, this.bot.emote('tags', 'add', '1')) + .replace(/\$\[emoji#2]/g, this.bot.emote('tags', 'add', '2')) + .replace(/\$\[emoji#3]/g, this.bot.emote('tags', 'add', '3')) + .replace(/\$\[emoji#4]/g, this.bot.emote('tags', 'add', '4')) + .replace(/\$\[emoji#4]/g, this.bot.emote('tags', 'add', '5')) + .replace(/\$\[emoji#5]/g, this.bot.emote('tags', 'add', '6')); + } +}; \ No newline at end of file diff --git a/src/commands/Discord/Tags/tag-del.js b/src/commands/Discord/Tags/tag-del.js new file mode 100644 index 0000000..e1b339a --- /dev/null +++ b/src/commands/Discord/Tags/tag-del.js @@ -0,0 +1,64 @@ +const { DiscordCommand } = require('../../../core'); + +module.exports = class TagDel extends DiscordCommand { + constructor(bot) { + super(bot, { + name : 'tag-del', + syntax : 'tag-del <...tag:str>', + aliases : [ 'tagdel', 'deltag', 'tagdelete', 'deletetag', 'del-tag', 'tag-delete', 'delete-tag' ], + argument : [ '<...tag:str>' ], + description : 'Delete a tag', + + hidden : false, + enabled : true, + cooldown : 2500, + category : 'Tags', + ownerOnly : false, + guildOnly : true, + permissions : [] + }); + } + + async execute(msg, args) { + const tag = await this.bot.m.connection.collection('dTags').findOne({ name: args.join(' '), 'author.guild': msg.channel.guild.id }); + const perm = msg.channel.permissionsOf(msg.author.id); + + if (!tag || tag === null) { + return msg.channel.createMessage(this._localize(msg.author.locale.tags.delete.invalid)); + } + + if (!perm.has('manageMessages') && msg.author.id !== tag.author.id) { + return msg.channel.createMessage(this._localize(msg.author.locale.tags.delete.perms)); + } + + const mess = await msg.channel.createMessage(this._localize(msg.author.locale.tags.delete.confirm.join('\n'), { name: tag.name.replace(/`/g, '`\u200b') })); + const res = await this.bot.collector.awaitMessage(msg.channel.id, msg.author.id, 30e3); + + if (res && res.content.toLowerCase() === 'y' || res.content.toLowerCase() === 'ye' || res.content.toLowerCase() === 'yes') { + mess.edit(this._localize(msg.author.locale.tags.delete.busy, { name: tag.name.replace(/`/g, '`\u200b') })); + this.bot.m.connection.collection('dTags').deleteOne({ name: tag.name, 'author.guild': msg.channel.guild.id }); + if (mess) { + mess.delete().catch(() => { return; }); + } + + msg.channel.createMessage(this._localize(msg.author.locale.tags.delete.done, { name: tag.name.replace(/`/g, '`\u200b') })); + } else { + return mess.edit(this._localize(msg.author.locale.cancelled)); + } + } + + _localize(msg, extData) { + if (extData) { + msg = msg.replace(/\$\[tag:name]/g, extData.name); + } + + return msg + .replace(/\$\[emoji#0]/g, this.bot.emote('tags', 'del', '0')) + .replace(/\$\[emoji#1]/g, this.bot.emote('tags', 'del', '1')) + .replace(/\$\[emoji#2]/g, this.bot.emote('tags', 'del', '2')) + .replace(/\$\[emoji#3]/g, this.bot.emote('tags', 'del', '3')) + .replace(/\$\[emoji#4]/g, this.bot.emote('tags', 'del', '4')) + .replace(/\$\[emoji#5]/g, this.bot.emote('tags', 'del', '5')) + .replace(/\$\[emoji#6]/g, this.bot.emote('tags', 'del', '6')); + } +}; \ No newline at end of file diff --git a/src/commands/Discord/Tags/tag-source.js b/src/commands/Discord/Tags/tag-source.js new file mode 100644 index 0000000..714531d --- /dev/null +++ b/src/commands/Discord/Tags/tag-source.js @@ -0,0 +1,40 @@ +const { DiscordCommand } = require('../../../core'); + +module.exports = class TagSource extends DiscordCommand { + constructor(bot) { + super(bot, { + name : 'tag-source', + syntax : 'tag-source <...tag:str>', + aliases : [ 'tagsource', 'tagsrc', 'tag-src' ], + argument : [ '<...tag:str>' ], + description : 'Source of a tag', + + hidden : false, + enabled : true, + cooldown : 2500, + category : 'Tags', + ownerOnly : false, + guildOnly : true, + permissions : [] + }); + } + + async execute(msg, args) { + const tag = await this.bot.m.connection.collection('dTags').findOne({ name: args.join(' '), 'author.guild': msg.channel.guild.id }); + if (!tag || tag === null) { + return msg.channel.createMessage(this._localize(msg.author.locale.tags.exec)); + } + + msg.channel.createMessage(this.bot.util.shorten(this._localize(msg.author.locale.tags.source, tag), 1950)); + } + + _localize(msg, extData) { + if (extData) { + msg = msg.replace(/\$\[tag:name]/g, extData.name.replace(/`/g, '`\u200b')).replace(/\$\[tag:content]/g, extData.content.replace(/`/g, '`\u200b')); + } + + return msg + .replace(/\$\[emoji#0]/g, this.bot.emote('tags', 'source', '0')) + .replace(/\$\[emoji#1]/g, this.bot.emote('tags', 'source', '1')); + } +}; \ No newline at end of file diff --git a/src/commands/Discord/Tags/tag.js b/src/commands/Discord/Tags/tag.js new file mode 100644 index 0000000..c4c1071 --- /dev/null +++ b/src/commands/Discord/Tags/tag.js @@ -0,0 +1,34 @@ +const { DiscordCommand } = require('../../../core'); + +module.exports = class Tag extends DiscordCommand { + constructor(bot) { + super(bot, { + name : 'tag', + syntax : 'tag <...tag:str>', + aliases : [ 'show-tag', 'disp-tag' ], + argument : [ '<...tag:str>' ], + description : 'Display a tag', + + hidden : false, + enabled : true, + cooldown : 2500, + category : 'Tags', + ownerOnly : false, + guildOnly : true, + permissions : [] + }); + } + + async execute(msg, args) { + const tag = await this.bot.m.connection.collection('dTags').findOne({ name: args.join(' '), 'author.guild': msg.channel.guild.id }); + if (!tag || tag === null) { + return msg.channel.createMessage(this._localize(msg.author.locale.tags.exec)); + } + + msg.channel.createMessage(tag.content); + } + + _localize(msg) { + return msg.replace(/\$\[emoji#0]/g, this.bot.emote('tags', 'exec')); + } +}; \ No newline at end of file diff --git a/src/core/clients/Discord.js b/src/core/clients/Discord.js index 3efc8df..9fe7e96 100644 --- a/src/core/clients/Discord.js +++ b/src/core/clients/Discord.js @@ -7,11 +7,12 @@ const EventRegistry = require('../registry/Discord/Events'); const LocaleRegistry = require('../registry/Discord/Locales'); const CommandRegistry = require('../registry/Discord/Commands'); // Utilities -const Util = require('../../util/Util'); -const Schema = require('../internal/Discord/schema'); -const { cyan } = require('../../util/colors'); -const Collection = require('../../util/Collection'); -const PermissionUtil = require('../internal/Discord/Utils/PermissionUtil'); +const Util = require('../../util/Util'); +const Schema = require('../internal/Discord/schema'); +const { cyan } = require('../../util/colors'); +const Collection = require('../../util/Collection'); +const PermissionUtil = require('../internal/Discord/Utils/PermissionUtil'); +const MessageCollector = require('../internal/Discord/Utils/MessageCollector'); module.exports = class WumpDiscord extends Eris { constructor(token, options = {}) { @@ -30,6 +31,7 @@ module.exports = class WumpDiscord extends Eris { this.m = options.db; this.REST = new RESTclient(this); + this.collector = new MessageCollector(this); this.eventRegistry = new EventRegistry(this); this.localeRegistry = new LocaleRegistry(this); this.commandRegistry = new CommandRegistry(this); diff --git a/src/core/internal/Discord/Utils/MessageCollector.js b/src/core/internal/Discord/Utils/MessageCollector.js new file mode 100644 index 0000000..d630483 --- /dev/null +++ b/src/core/internal/Discord/Utils/MessageCollector.js @@ -0,0 +1,25 @@ +module.exports = class MessageCollector { + constructor(bot) { + this.collectors = {}; + bot.on('messageCreate', this.verify.bind(this)); + } + + async verify(msg) { + const collector = this.collectors[msg.channel.id + msg.author.id]; + if (collector && collector.filter(msg)) { + collector.res(msg); + } + } + + awaitMessage(channelId, userId, timeout = 30000, filter = () => true) { + return new Promise((res) => { + if (this.collectors[channelId + userId]) delete this.collectors[channelId + userId]; + + this.collectors[channelId + userId] = { + res, filter + }; + + setTimeout(res.bind(null, false), timeout); + }); + } +}; \ No newline at end of file diff --git a/src/core/internal/Discord/schema.js b/src/core/internal/Discord/schema.js index b715f1a..995c20b 100644 --- a/src/core/internal/Discord/schema.js +++ b/src/core/internal/Discord/schema.js @@ -17,7 +17,23 @@ const user = new Schema({ locale: { type: String, default: conf.discord.locale } }); +const tag = new Schema({ + name : { type: String, default: undefined }, + uses : { type: Number, default: 0 }, + content : { type: String, default: undefined }, + creation: { type: String, default: undefined }, + + history : [], + author : { + id : { type: String, default: undefined }, + name : { type: String, default: undefined }, + guild : { type: String, default: undefined }, + discrim: { type: String, default: undefined } + } +}); + module.exports = { + tag : model('dTags', tag, 'dTags'), user : model('dUsers', user, 'dUsers'), guild: model('dGuilds', guild, 'dGuilds') }; \ No newline at end of file