From c53eca459e9d6ce80bdb27735543a5339dda3875 Mon Sep 17 00:00:00 2001 From: Daniel Odendahl Jr Date: Mon, 5 Mar 2018 22:14:25 +0000 Subject: [PATCH] Role Management, gelbooru/danbooru/konachan --- README.md | 15 ++++++++- Xiao.js | 1 + commands/random/dick.js | 18 ++++++++++ commands/role-manage/add-open-role.js | 31 +++++++++++++++++ commands/role-manage/fix-open-roles.js | 30 +++++++++++++++++ commands/role-manage/remove-open-role.js | 32 ++++++++++++++++++ commands/role-manage/role-list.js | 24 ++++++++++++++ commands/role-manage/subscribe.js | 31 +++++++++++++++++ commands/role-manage/unsubscribe.js | 31 +++++++++++++++++ commands/search/danbooru.js | 42 ++++++++++++++++++++++++ commands/search/gelbooru.js | 42 ++++++++++++++++++++++++ commands/search/konachan.js | 38 +++++++++++++++++++++ package.json | 2 +- 13 files changed, 335 insertions(+), 2 deletions(-) create mode 100644 commands/random/dick.js create mode 100644 commands/role-manage/add-open-role.js create mode 100644 commands/role-manage/fix-open-roles.js create mode 100644 commands/role-manage/remove-open-role.js create mode 100644 commands/role-manage/role-list.js create mode 100644 commands/role-manage/subscribe.js create mode 100644 commands/role-manage/unsubscribe.js create mode 100644 commands/search/danbooru.js create mode 100644 commands/search/gelbooru.js create mode 100644 commands/search/konachan.js diff --git a/README.md b/README.md index 0a49ae6d..73a18999 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Xiao is a Discord bot coded in JavaScript with 300 commands, she is one of the most feature-filled bots out there, and formerly served over 10,000 servers with a uniquely devoted fanbase. -## Commands (273) +## Commands (283) ### Utility: * **prefix**: Shows or sets the command prefix. @@ -51,6 +51,7 @@ served over 10,000 servers with a uniquely devoted fanbase. * **chuck-norris**: Responds with a random Chuck Norris joke. * **coin**: Flips a coin. * **compliment**: Compliments a user. +* **dick**: Determines your dick size. * **discord-email-fun-fact**: Responds with a random fun fact from the Discord emails. * **dog-fact**: Responds with a random dog fact. * **dog**: Responds with a random dog image. @@ -113,9 +114,11 @@ served over 10,000 servers with a uniquely devoted fanbase. ### Search: * **bulbapedia**: Searches Bulbapedia for your query. +* **danbooru**: Responds with an image from Danbooru, with optional query. * **deviantart**: Responds with an image from a DeviantArt section, with optional query. * **dictionary**: Defines a word. * **forecast**: Responds with the seven-day forecast for a specific location. +* **gelbooru**: Responds with an image from Gelbooru, with optional query. * **giphy**: Searches Giphy for your query. * **github**: Responds with information on a GitHub repository. * **google-autofill**: Responds with a list of the Google Autofill results for a particular query. @@ -127,6 +130,7 @@ served over 10,000 servers with a uniquely devoted fanbase. * **itunes**: Searches iTunes for your query. * **jisho**: Defines a word, but with Japanese. * **kickstarter**: Searches Kickstarter for your query. +* **konachan**: Responds with an image from Konachan, with optional query. * **league-of-legends-champion**: Responds with information on a League of Legends champion. * **map**: Responds with a map of a specific location. * **mdn**: Searches MDN for your query. @@ -290,6 +294,15 @@ served over 10,000 servers with a uniquely devoted fanbase. * **roman-numeral**: Converts a number to roman numerals. * **temperature**: Converts temperatures to/from celsius, fahrenheit, or kelvin. +### Role Management: + +* **add-open-role**: Sets a role as open. +* **fix-open-roles**: Removes no longer existent roles from the open roles lists. +* **remove-open-role**: Remove a role from the open roles. +* **role-list**: Responds with all available roles to join. +* **subscribe**: Subscribes you to the specified role. +* **unsubscribe**: Unsubscribes you from the specified role. + ### Portal Messages: * **add-portal-channel**: Sets a channel to be a portal channel. diff --git a/Xiao.js b/Xiao.js index d724b38d..cd03a021 100644 --- a/Xiao.js +++ b/Xiao.js @@ -29,6 +29,7 @@ client.registry ['avatar-edit', 'Avatar Manipulation'], ['text-edit', 'Text Manipulation'], ['number-edit', 'Number Manipulation'], + ['role-manage', 'Role Management'], ['portal', 'Portal Messages'], ['other', 'Other'], ['roleplay', 'Roleplay'] diff --git a/commands/random/dick.js b/commands/random/dick.js new file mode 100644 index 00000000..5ba9e6fe --- /dev/null +++ b/commands/random/dick.js @@ -0,0 +1,18 @@ +const { Command } = require('discord.js-commando'); + +module.exports = class DickCommand extends Command { + constructor(client) { + super(client, { + name: 'dick', + aliases: ['dick-size'], + group: 'random', + memberName: 'dick', + description: 'Determines your dick size.', + nsfw: true + }); + } + + run(msg) { + return msg.say(`8${'='.repeat(Math.floor(Math.random() * 200) + 1)}D`); + } +}; diff --git a/commands/role-manage/add-open-role.js b/commands/role-manage/add-open-role.js new file mode 100644 index 00000000..f76fdbbc --- /dev/null +++ b/commands/role-manage/add-open-role.js @@ -0,0 +1,31 @@ +const { Command } = require('discord.js-commando'); + +module.exports = class AddOpenRoleCommand extends Command { + constructor(client) { + super(client, { + name: 'add-open-role', + aliases: ['set-open-role', 'open-role'], + group: 'role-manage', + memberName: 'add-open-role', + description: 'Sets a role as open.', + guildOnly: true, + userPermissions: ['MANAGE_ROLES'], + args: [ + { + key: 'role', + prompt: 'What role do you want to open?', + type: 'role' + } + ] + }); + } + + run(msg, { role }) { + if (role.id === msg.guild.defaultRole.id) return msg.reply('The everyone role is already open!'); + const roles = msg.guild.settings.get('openRoles', []); + if (roles.includes(role.id)) return msg.reply(`${role.name} is already open!`); + roles.push(role.id); + msg.guild.settings.set('openRoles', roles); + return msg.say(`${role.name} is now open!`); + } +}; diff --git a/commands/role-manage/fix-open-roles.js b/commands/role-manage/fix-open-roles.js new file mode 100644 index 00000000..54ecd53e --- /dev/null +++ b/commands/role-manage/fix-open-roles.js @@ -0,0 +1,30 @@ +const { Command } = require('discord.js-commando'); + +module.exports = class FixOpenRolesCommand extends Command { + constructor(client) { + super(client, { + name: 'fix-open-roles', + aliases: ['fix-roles'], + group: 'role-manage', + memberName: 'fix-open-roles', + description: 'Removes no longer existent roles from the open roles lists.', + ownerOnly: true + }); + } + + run(msg) { + let count = 0; + for (const guild of this.client.guilds.values()) { + const roles = guild.settings.get('openRoles', []); + if (!roles.length) continue; + for (const role of roles) { + if (guild.roles.has(role)) continue; + roles.splice(roles.indexOf(role), 1); + count++; + } + if (!roles.length) guild.settings.remove('openRoles'); + else guild.settings.set('openRoles', roles); + } + return msg.say(`Cleared **${count}** roles from the open roles lists.`); + } +}; diff --git a/commands/role-manage/remove-open-role.js b/commands/role-manage/remove-open-role.js new file mode 100644 index 00000000..ea4c9948 --- /dev/null +++ b/commands/role-manage/remove-open-role.js @@ -0,0 +1,32 @@ +const { Command } = require('discord.js-commando'); + +module.exports = class RemoveOpenRoleCommand extends Command { + constructor(client) { + super(client, { + name: 'remove-open-role', + aliases: ['delete-open-role', 'close-role'], + group: 'role-manage', + memberName: 'remove-open-role', + description: 'Remove a role from the open roles.', + guildOnly: true, + userPermissions: ['MANAGE_ROLES'], + args: [ + { + key: 'role', + prompt: 'What role do you want to close?', + type: 'role' + } + ] + }); + } + + run(msg, { role }) { + if (role.id === msg.guild.defaultRole.id) return msg.reply('The everyone role cannot be closed!'); + const roles = msg.guild.settings.get('openRoles', []); + if (!roles.includes(role.id)) return msg.reply(`${role.name} is not open!`); + roles.splice(roles.indexOf(role.id), 1); + if (!roles.length) msg.guild.settings.remove('openRoles'); + else msg.guild.settings.set('openRoles', roles); + return msg.say(`${role.name} is now closed...`); + } +}; diff --git a/commands/role-manage/role-list.js b/commands/role-manage/role-list.js new file mode 100644 index 00000000..9f667a8f --- /dev/null +++ b/commands/role-manage/role-list.js @@ -0,0 +1,24 @@ +const { Command } = require('discord.js-commando'); +const { stripIndents } = require('common-tags'); + +module.exports = class RoleListCommand extends Command { + constructor(client) { + super(client, { + name: 'role-list', + aliases: ['roles', 'open-roles'], + group: 'role-manage', + memberName: 'role-list', + description: 'Responds with all available roles to join.', + guildOnly: true + }); + } + + run(msg) { + const roles = msg.guild.settings.get('roles', []); + if (!roles.length) return msg.say('This server has no open roles...'); + return msg.say(stripIndents` + **Roles available in ${msg.guild.name}**: + ${msg.guild.roles.filter(role => roles.includes(role.id)).map(role => role.name).join('\n')} + `); + } +}; diff --git a/commands/role-manage/subscribe.js b/commands/role-manage/subscribe.js new file mode 100644 index 00000000..37393aea --- /dev/null +++ b/commands/role-manage/subscribe.js @@ -0,0 +1,31 @@ +const { Command } = require('discord.js-commando'); + +module.exports = class SubscribeCommand extends Command { + constructor(client) { + super(client, { + name: 'subscribe', + aliases: ['join'], + group: 'role-manage', + memberName: 'subscribe', + description: 'Subscribes you to the specified role.', + guildOnly: true, + clientPermissions: ['MANAGE_ROLES'], + args: [ + { + key: 'role', + prompt: 'What role do you want to subscribe to?', + type: 'role' + } + ] + }); + } + + async run(msg, { role }) { + const roles = msg.guild.settings.get('openRoles', []); + if (!roles.includes(role.id)) return msg.reply('This role is not open!'); + if (!role.editable) return msg.reply('I do not have permission to manage this role!'); + if (msg.member.roles.has(role.id)) return msg.reply('You are already a member of this role!'); + await msg.member.roles.add(role); + return msg.say(`You were added to **${role.name}**!`); + } +}; diff --git a/commands/role-manage/unsubscribe.js b/commands/role-manage/unsubscribe.js new file mode 100644 index 00000000..6d77398a --- /dev/null +++ b/commands/role-manage/unsubscribe.js @@ -0,0 +1,31 @@ +const { Command } = require('discord.js-commando'); + +module.exports = class UnsubscribeCommand extends Command { + constructor(client) { + super(client, { + name: 'unsubscribe', + aliases: ['leave'], + group: 'role-manage', + memberName: 'unsubscribe', + description: 'Unsubscribes you from the specified role.', + guildOnly: true, + clientPermissions: ['MANAGE_ROLES'], + args: [ + { + key: 'role', + prompt: 'What role do you want to unsubscribe from?', + type: 'role' + } + ] + }); + } + + async run(msg, { role }) { + const roles = msg.guild.settings.get('openRoles', []); + if (!roles.includes(role.id)) return msg.reply('This role is not open!'); + if (!role.editable) return msg.reply('I do not have permission to manage this role!'); + if (!msg.member.roles.has(role.id)) return msg.reply('You are not a member of this role!'); + await msg.member.roles.remove(role); + return msg.say(`You were removed from **${role.name}**...`); + } +}; diff --git a/commands/search/danbooru.js b/commands/search/danbooru.js new file mode 100644 index 00000000..7027003d --- /dev/null +++ b/commands/search/danbooru.js @@ -0,0 +1,42 @@ +const { Command } = require('discord.js-commando'); +const snekfetch = require('snekfetch'); + +module.exports = class DanbooruCommand extends Command { + constructor(client) { + super(client, { + name: 'danbooru', + aliases: ['danbooru-image'], + group: 'search', + memberName: 'danbooru', + description: 'Responds with an image from Danbooru, with optional query.', + nsfw: true, + args: [ + { + key: 'query', + prompt: 'What image would you like to search for?', + type: 'string', + default: '', + validate: query => { + if (!query.includes(' ')) return true; + return 'Invalid query, please only search for one tag at a time.'; + } + } + ] + }); + } + + async run(msg, { query }) { + try { + const { body } = await snekfetch + .get('https://danbooru.donmai.us/posts.json') + .query({ + tags: `${query} order:random`, + limit: 1 + }); + if (!body.length || !body[0].file_url) return msg.say('Could not find any results.'); + return msg.say(`https://danbooru.donmai.us${body[0].file_url}`); + } catch (err) { + return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); + } + } +}; diff --git a/commands/search/gelbooru.js b/commands/search/gelbooru.js new file mode 100644 index 00000000..2db5c8f7 --- /dev/null +++ b/commands/search/gelbooru.js @@ -0,0 +1,42 @@ +const { Command } = require('discord.js-commando'); +const snekfetch = require('snekfetch'); + +module.exports = class GelbooruCommand extends Command { + constructor(client) { + super(client, { + name: 'gelbooru', + aliases: ['gelbooru-image'], + group: 'search', + memberName: 'gelbooru', + description: 'Responds with an image from Gelbooru, with optional query.', + nsfw: true, + args: [ + { + key: 'query', + prompt: 'What image would you like to search for?', + type: 'string', + default: '' + } + ] + }); + } + + async run(msg, { query }) { + try { + const { body } = await snekfetch + .get('https://gelbooru.com/index.php') + .query({ + page: 'dapi', + s: 'post', + q: 'index', + json: 1, + tags: query, + limit: 200 + }); + if (!body) return msg.say('Could not find any results.'); + return msg.say(body[Math.floor(Math.random() * body.length)].file_url); + } catch (err) { + return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); + } + } +}; diff --git a/commands/search/konachan.js b/commands/search/konachan.js new file mode 100644 index 00000000..a56532d0 --- /dev/null +++ b/commands/search/konachan.js @@ -0,0 +1,38 @@ +const { Command } = require('discord.js-commando'); +const snekfetch = require('snekfetch'); + +module.exports = class KonachanCommand extends Command { + constructor(client) { + super(client, { + name: 'konachan', + aliases: ['konachan-image'], + group: 'search', + memberName: 'konachan', + description: 'Responds with an image from Konachan, with optional query.', + nsfw: true, + args: [ + { + key: 'query', + prompt: 'What image would you like to search for?', + type: 'string', + default: '' + } + ] + }); + } + + async run(msg, { query }) { + try { + const { body } = await snekfetch + .get('https://konachan.net/post.json') + .query({ + tags: `${query} order:random`, + limit: 1 + }); + if (!body.length || !body[0].file_url) return msg.say('Could not find any results.'); + return msg.say(`https:${body[0].file_url}`); + } catch (err) { + return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); + } + } +}; diff --git a/package.json b/package.json index 97072025..2a78ecc9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xiao", - "version": "66.7.0", + "version": "66.8.0", "description": "Your personal server companion.", "main": "Xiao.js", "scripts": {