Remove 15 commands, patreon and bot list stuff

This commit is contained in:
Dragon Fire
2024-03-20 21:02:24 -04:00
parent 2c180f39b7
commit b58a112fc7
48 changed files with 5 additions and 1963 deletions
-76
View File
@@ -1,76 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { oneLine } = require('common-tags');
const { base64 } = require('../../util/Util');
const { FACEPLUSPLUS_KEY, FACEPLUSPLUS_SECRET } = process.env;
const emotions = ['anger', 'disgust', 'fear', 'happiness', 'neutral', 'sadness', 'surprise'];
const emotionResponse = ['angry', 'disgusted', 'afraid', 'happy', 'uncaring', 'sad', 'surprised'];
module.exports = class FaceCommand extends Command {
constructor(client) {
super(client, {
name: 'face',
group: 'analyze',
memberName: 'face',
description: 'Determines the race, gender, and age of a face.',
throttling: {
usages: 2,
duration: 30
},
credit: [
{
name: 'Face++ Cognitive Services',
url: 'https://www.faceplusplus.com/',
reason: 'Face Detection API',
reasonURL: 'https://www.faceplusplus.com/face-detection/'
}
],
args: [
{
key: 'image',
prompt: 'What face would you like to scan?',
type: 'image-or-avatar'
}
]
});
}
async run(msg, { image }) {
try {
const face = await this.detect(image);
if (!face) return msg.reply('There are no faces in this image.');
if (face === 'size') return msg.reply('This image is too large.');
const pronoun = face.gender.value === 'Male' ? 'He' : 'She';
const emotion = emotionResponse[emotions.indexOf(
emotions.slice(0).sort((a, b) => face.emotion[b] - face.emotion[a])[0]
)];
const smile = face.smile.value > face.smile.threshold;
const beautyScore = face.gender.value === 'Male' ? face.beauty.female_score : face.beauty.male_score;
return msg.reply(oneLine`
I think this is a photo of a ${face.age.value} year old ${face.gender.value.toLowerCase()}.
${pronoun} appears to be ${emotion}, and is ${smile ? 'smiling' : 'not smiling'}. I give this
face a ${Math.round(beautyScore)} on the 1-100 beauty scale.
${beautyScore > 50 ? beautyScore > 70 ? beautyScore > 90 ? 'Hot!' : 'Not bad.' : 'Not _too_ ugly.' : 'Uggggly!'}
`);
} catch (err) {
if (err.status === 400) return msg.reply('There are no faces in this image.');
if (err.status === 403) return msg.reply('Hold your horses! The command is overloaded! Try again soon.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async detect(image) {
const imgData = await request.get(image);
if (Buffer.byteLength(imgData.body) >= 2e+6) return 'size';
const { body } = await request
.post('https://api-us.faceplusplus.com/facepp/v3/detect')
.attach('image_base64', base64(imgData.body))
.query({
api_key: FACEPLUSPLUS_KEY,
api_secret: FACEPLUSPLUS_SECRET,
return_attributes: 'gender,age,smiling,emotion,ethnicity,beauty'
});
if (!body.faces || !body.faces.length) return null;
return body.faces[0].attributes;
}
};
+1 -2
View File
@@ -7,8 +7,7 @@ module.exports = class CleverbotEndCommand extends Command {
aliases: ['clevs-end', 'chat-end', 'end'],
group: 'cleverbot',
memberName: 'cleverbot-end',
description: 'Ends the current Cleverbot chat.',
patronOnly: true
description: 'Ends the current Cleverbot chat.'
});
}
-1
View File
@@ -10,7 +10,6 @@ module.exports = class CleverbotCommand extends Command {
group: 'cleverbot',
memberName: 'cleverbot',
description: 'Starts a Cleverbot conversation.',
patronOnly: true,
credit: [
{
name: 'Cleverbot',
-29
View File
@@ -1,29 +0,0 @@
const Command = require('../../framework/Command');
const Docs = require('discord.js-docs');
module.exports = class DocstCommand extends Command {
constructor(client) {
super(client, {
name: 'docs',
aliases: ['discord-js-docs', 'discord-js', 'djs', 'djs-docs'],
group: 'code',
memberName: 'docs',
description: 'Searches the discord.js docs for your query.',
clientPermissions: ['EMBED_LINKS'],
args: [
{
key: 'query',
prompt: 'What do you want to search the docs for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
const doc = await Docs.fetch('stable');
const embed = doc.resolveEmbed(query);
if (!embed) return msg.say('Could not find any results.');
return msg.embed(embed);
}
};
-94
View File
@@ -1,94 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { createCanvas, loadImage } = require('canvas');
const path = require('path');
const { base64 } = require('../../util/Util');
const { FACEPLUSPLUS_KEY, FACEPLUSPLUS_SECRET } = process.env;
module.exports = class AnimeEyesCommand extends Command {
constructor(client) {
super(client, {
name: 'anime-eyes',
aliases: ['ani-eyes', 'manga-eyes'],
group: 'edit-face',
memberName: 'anime-eyes',
description: 'Draws anime eyes onto the faces in an image.',
throttling: {
usages: 2,
duration: 60
},
credit: [
{
name: 'Face++ Cognitive Services',
url: 'https://www.faceplusplus.com/',
reason: 'Face Detection API',
reasonURL: 'https://www.faceplusplus.com/face-detection/'
}
],
args: [
{
key: 'image',
prompt: 'What face would you like to scan?',
type: 'image-or-avatar'
}
]
});
}
async run(msg, { image }) {
const leftEye = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'anime-eyes', 'left.png'));
const rightEye = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'anime-eyes', 'right.png'));
const imgData = await request.get(image);
try {
const faces = await this.detect(imgData);
if (!faces) return msg.reply('There are no faces in this image.');
if (faces === 'size') return msg.reply('This image is too large.');
const base = await loadImage(imgData.body);
const canvas = createCanvas(base.width, base.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(base, 0, 0);
for (const face of faces) {
const landmarks = face.landmark;
const leftWidth = landmarks.left_eye_right_corner.x - landmarks.left_eye_left_corner.x;
const leftRatio = leftWidth / leftEye.width;
const leftHeight = leftEye.height * leftRatio;
ctx.drawImage(
leftEye,
landmarks.left_eye_left_corner.x - (leftWidth * 0.25),
landmarks.left_eye_left_corner.y - (leftHeight / 2) - (leftHeight * 0.25),
leftWidth * 1.5,
leftHeight * 1.5
);
const rightWidth = landmarks.right_eye_right_corner.x - landmarks.right_eye_left_corner.x;
const rightRatio = rightWidth / rightEye.width;
const rightHeight = rightEye.height * rightRatio;
ctx.drawImage(
rightEye,
landmarks.right_eye_left_corner.x - (rightWidth * 0.25),
landmarks.right_eye_left_corner.y - (rightHeight / 2) - (rightHeight * 0.25),
rightWidth * 1.5,
rightHeight * 1.5
);
}
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'anime-eyes.png' }] });
} catch (err) {
if (err.status === 400) return msg.reply('There are no faces in this image.');
if (err.status === 403) return msg.reply('Hold your horses! The command is overloaded! Try again soon.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async detect(imgData) {
if (Buffer.byteLength(imgData.body) >= 2e+6) return 'size';
const { body } = await request
.post('https://api-us.faceplusplus.com/facepp/v3/detect')
.attach('image_base64', base64(imgData.body))
.query({
api_key: FACEPLUSPLUS_KEY,
api_secret: FACEPLUSPLUS_SECRET,
return_landmark: 1
});
if (!body.faces || !body.faces.length) return null;
return body.faces;
}
};
-88
View File
@@ -1,88 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { createCanvas, loadImage } = require('canvas');
const path = require('path');
const { base64 } = require('../../util/Util');
const { FACEPLUSPLUS_KEY, FACEPLUSPLUS_SECRET } = process.env;
module.exports = class DannyDevitoCommand extends Command {
constructor(client) {
super(client, {
name: 'danny-devito',
aliases: ['devito'],
group: 'edit-face',
memberName: 'danny-devito',
description: 'Draws Danny Devito\'s face onto the faces in an image.',
throttling: {
usages: 2,
duration: 60
},
credit: [
{
name: 'Danny DeVito',
url: 'https://twitter.com/dannydevito',
reason: 'Himself'
},
{
name: 'Face++ Cognitive Services',
url: 'https://www.faceplusplus.com/',
reason: 'Face Detection API',
reasonURL: 'https://www.faceplusplus.com/face-detection/'
}
],
args: [
{
key: 'image',
prompt: 'What face would you like to scan?',
type: 'image-or-avatar'
}
]
});
}
async run(msg, { image }) {
const danny = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'danny-devito.png'));
const imgData = await request.get(image);
try {
const faces = await this.detect(imgData);
if (!faces) return msg.reply('There are no faces in this image.');
if (faces === 'size') return msg.reply('This image is too large.');
const base = await loadImage(imgData.body);
const canvas = createCanvas(base.width, base.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(base, 0, 0);
for (const face of faces) {
const landmarks = face.landmark;
const width = landmarks.contour_right1.x - landmarks.contour_left1.x;
const ratio = width / danny.width;
const height = danny.height * ratio;
ctx.drawImage(
danny,
landmarks.contour_left1.x - (width * 0.25),
landmarks.contour_left1.y - (height / 2) - (height * 0.25),
width * 1.5,
height * 1.5
);
}
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'danny-devito.png' }] });
} catch (err) {
if (err.status === 400) return msg.reply('There are no faces in this image.');
if (err.status === 403) return msg.reply('Hold your horses! The command is overloaded! Try again soon.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async detect(imgData) {
if (Buffer.byteLength(imgData.body) >= 2e+6) return 'size';
const { body } = await request
.post('https://api-us.faceplusplus.com/facepp/v3/detect')
.attach('image_base64', base64(imgData.body))
.query({
api_key: FACEPLUSPLUS_KEY,
api_secret: FACEPLUSPLUS_SECRET,
return_landmark: 1
});
if (!body.faces || !body.faces.length) return null;
return body.faces;
}
};
-102
View File
@@ -1,102 +0,0 @@
const Command = require('../../framework/Command');
const { GuildEmoji } = require('discord.js');
const request = require('node-superfetch');
const { createCanvas, loadImage } = require('canvas');
const twemoji = require('twemoji-parser');
const { base64 } = require('../../util/Util');
const { FACEPLUSPLUS_KEY, FACEPLUSPLUS_SECRET } = process.env;
module.exports = class EmojiFaceCommand extends Command {
constructor(client) {
super(client, {
name: 'emoji-face',
aliases: ['emoji-f', 'e-face'],
group: 'edit-face',
memberName: 'emoji-face',
description: 'Draws an emoji onto the faces in an image.',
throttling: {
usages: 2,
duration: 60
},
credit: [
{
name: 'Face++ Cognitive Services',
url: 'https://www.faceplusplus.com/',
reason: 'Face Detection API',
reasonURL: 'https://www.faceplusplus.com/face-detection/'
}
],
args: [
{
key: 'emoji',
prompt: 'What emoji do you want to draw?',
type: 'default-emoji|custom-emoji'
},
{
key: 'image',
prompt: 'What face would you like to scan?',
type: 'image-or-avatar'
}
]
});
}
async run(msg, { emoji, image }) {
let emojiURL;
if (emoji instanceof GuildEmoji) {
emojiURL = emoji.url;
} else {
const parsed = twemoji.parse(emoji);
if (!parsed.length || !parsed[0].url) return msg.reply('This emoji is not yet supported.');
emojiURL = parsed[0].url;
}
const emojiData = await request.get(emojiURL);
const emojiImg = await loadImage(emojiData.body);
if (emojiURL.endsWith('svg')) {
emojiImg.width *= 4;
emojiImg.height *= 4;
}
const imgData = await request.get(image);
try {
const faces = await this.detect(imgData);
if (!faces) return msg.reply('There are no faces in this image.');
if (faces === 'size') return msg.reply('This image is too large.');
const base = await loadImage(imgData.body);
const canvas = createCanvas(base.width, base.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(base, 0, 0);
for (const face of faces) {
const landmarks = face.landmark;
const width = landmarks.contour_right1.x - landmarks.contour_left1.x;
const ratio = width / emojiImg.width;
const height = emojiImg.height * ratio;
ctx.drawImage(
emojiImg,
landmarks.contour_left1.x - (width * 0.25),
landmarks.contour_left1.y - (height / 2) - (height * 0.25),
width * 1.5,
height * 1.5
);
}
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'emoji-face.png' }] });
} catch (err) {
if (err.status === 400) return msg.reply('There are no faces in this image.');
if (err.status === 403) return msg.reply('Hold your horses! The command is overloaded! Try again soon.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async detect(imgData) {
if (Buffer.byteLength(imgData.body) >= 2e+6) return 'size';
const { body } = await request
.post('https://api-us.faceplusplus.com/facepp/v3/detect')
.attach('image_base64', base64(imgData.body))
.query({
api_key: FACEPLUSPLUS_KEY,
api_secret: FACEPLUSPLUS_SECRET,
return_landmark: 1
});
if (!body.faces || !body.faces.length) return null;
return body.faces;
}
};
-92
View File
@@ -1,92 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { createCanvas, loadImage } = require('canvas');
const path = require('path');
const { base64 } = require('../../util/Util');
const { FACEPLUSPLUS_KEY, FACEPLUSPLUS_SECRET } = process.env;
module.exports = class EyesCommand extends Command {
constructor(client) {
super(client, {
name: 'eyes',
group: 'edit-face',
memberName: 'eyes',
description: 'Draws emoji eyes onto the faces in an image.',
throttling: {
usages: 2,
duration: 60
},
credit: [
{
name: 'Face++ Cognitive Services',
url: 'https://www.faceplusplus.com/',
reason: 'Face Detection API',
reasonURL: 'https://www.faceplusplus.com/face-detection/'
}
],
args: [
{
key: 'image',
prompt: 'What face would you like to scan?',
type: 'image-or-avatar'
}
]
});
}
async run(msg, { image }) {
const eyes = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'eyes.png'));
const imgData = await request.get(image);
try {
const faces = await this.detect(imgData);
if (!faces) return msg.reply('There are no faces in this image.');
if (faces === 'size') return msg.reply('This image is too large.');
const base = await loadImage(imgData.body);
const canvas = createCanvas(base.width, base.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(base, 0, 0);
for (const face of faces) {
const landmarks = face.landmark;
const leftWidth = landmarks.left_eye_right_corner.x - landmarks.left_eye_left_corner.x;
const leftRatio = leftWidth / eyes.width;
const leftHeight = eyes.height * leftRatio;
ctx.drawImage(
eyes,
landmarks.left_eye_left_corner.x - (leftWidth / 2),
landmarks.left_eye_left_corner.y - (leftHeight / 2) - (leftHeight / 2),
leftWidth * 2,
leftHeight * 2
);
const rightWidth = landmarks.right_eye_right_corner.x - landmarks.right_eye_left_corner.x;
const rightRatio = rightWidth / eyes.width;
const rightHeight = eyes.height * rightRatio;
ctx.drawImage(
eyes,
landmarks.right_eye_left_corner.x - (rightWidth / 2),
landmarks.right_eye_left_corner.y - (rightHeight / 2) - (rightHeight / 2),
rightWidth * 2,
rightHeight * 2
);
}
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'eyes.png' }] });
} catch (err) {
if (err.status === 400) return msg.reply('There are no faces in this image.');
if (err.status === 403) return msg.reply('Hold your horses! The command is overloaded! Try again soon.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async detect(imgData) {
if (Buffer.byteLength(imgData.body) >= 2e+6) return 'size';
const { body } = await request
.post('https://api-us.faceplusplus.com/facepp/v3/detect')
.attach('image_base64', base64(imgData.body))
.query({
api_key: FACEPLUSPLUS_KEY,
api_secret: FACEPLUSPLUS_SECRET,
return_landmark: 1
});
if (!body.faces || !body.faces.length) return null;
return body.faces;
}
};
-143
View File
@@ -1,143 +0,0 @@
const Command = require('../../framework/Command');
const { MessageActionRow, MessageButton } = require('discord.js');
const { stripIndents } = require('common-tags');
const { Util: { escapeMarkdown } } = require('discord.js');
const path = require('path');
const fs = require('fs');
const { readFile } = require('fs/promises');
const stories = fs.readdirSync(path.join(__dirname, '..', '..', 'assets', 'txt', 'kino'))
.map(story => story.slice(3).replace('.txt', ''));
module.exports = class KinoCommand extends Command {
constructor(client) {
super(client, {
name: 'kino',
aliases: ['kino-journey', 'kinos-journey', 'kino\'s-journey'],
group: 'other',
memberName: 'kino',
description: 'Read various Kino\'s Journey fan stories by dragonfire535.',
details: stripIndents`
**Stories:**
\`\`\`
${stories.map((story, i) => `${i.toString().padStart(2, '0')}. ${story}`).join('\n')}
\`\`\`
`,
credit: [
{
name: 'Kino\'s Journey',
url: 'https://kinonotabi.com/',
reason: 'Original Concept'
}
],
args: [
{
key: 'story',
prompt: stripIndents`
What story do you want to read? You can type the number or the name.
\`\`\`
${stories.map((story, i) => `${i.toString().padStart(2, '0')}. ${story}`).join('\n')}
\`\`\`
`,
type: 'string',
validate: choice => {
if (stories.some(story => choice.toLowerCase() === story.toLowerCase())) return true;
const num = Number.parseInt(choice, 10);
return Boolean(stories[num]);
},
parse: choice => {
if (stories.some(story => choice.toLowerCase() === story.toLowerCase())) {
return choice.toLowerCase();
}
const num = Number.parseInt(choice, 10);
return stories[num].toLowerCase();
}
}
]
});
}
async run(msg, { story }) {
const storyData = await this.generateStory(story);
let i = 0;
let end = false;
const row = new MessageActionRow();
row.addComponents(
new MessageButton().setCustomId('prev').setLabel('Prev').setStyle('PRIMARY').setDisabled(true),
new MessageButton().setCustomId('next').setLabel('Next').setStyle('PRIMARY'),
new MessageButton().setCustomId('end').setLabel('End').setStyle('DANGER')
);
const initialMsg = await msg.say(stripIndents`
Welcome to Kino's Journey!
Press the "Next" button to go to the next page, and "Prev" to go back.
Press "End" at any time to stop reading.
`, { components: [row] });
const filter = res => res.user.id === msg.author.id;
const initialInteractions = await initialMsg.awaitMessageComponent({
filter,
max: 1,
time: 15000
});
if (!initialInteractions.size) return initialMsg.edit('Maybe next time!', { components: [] });
let choice = initialInteractions.first();
if (choice.customId === 'end') return choice.update('Maybe next time!', { components: [] });
while (!end) {
if (i === 0) {
row.components[0].setDisabled(true);
} else {
row.components[0].setDisabled(false);
}
const line = storyData[i];
if (!line) {
end = true;
break;
}
await choice.update(stripIndents`
**Page ${i + 1}/${storyData.length}**
${escapeMarkdown(line.trim())}
`, { components: [row] });
const interactions = await initialMsg.awaitMessageComponent({
filter,
max: 1,
time: 120000
});
if (!interactions.size) break;
choice = interactions.first();
if (choice.customId === 'next') {
i++;
} else if (choice.customId === 'prev') {
i--;
} else if (choice.customId === 'end') {
break;
} else {
return initialMsg.edit('Maybe next time!', { components: [] });
}
}
return choice.update('Thank you for reading this chapter of Kino\'s Journey!', { components: [] });
}
async generateStory(file) {
const filename = stories.find(story => story.toLowerCase() === file);
const num = stories.indexOf(filename).toString().padStart(2, '0');
const story = await readFile(path.join(__dirname, '..', '..', 'assets', 'txt', 'kino', `${num} ${filename}.txt`), {
encoding: 'utf8'
});
const chunks = [];
let currentChunk = '';
for (const paragraph of story.split('\n\n')) {
if (paragraph === '***' && currentChunk) {
chunks.push(currentChunk);
currentChunk = '***\n\n';
continue;
}
currentChunk += paragraph;
currentChunk += '\n\n';
if (currentChunk.length > 1000) {
chunks.push(currentChunk);
currentChunk = '';
}
}
chunks.push(currentChunk);
return chunks;
}
};
-3
View File
@@ -40,9 +40,6 @@ module.exports = class ClocCommand extends Command {
[
'--json',
'--exclude-dir=node_modules',
'--read-lang-def',
path.join(__dirname, '..', '..', 'assets', 'txt', 'txt_definition.txt'),
'--force-lang=TXT,txt',
path.join(__dirname, '..', '..')
]
);
-38
View File
@@ -1,38 +0,0 @@
const Command = require('../../framework/Command');
const { stripIndents } = require('common-tags');
module.exports = class DonateCommand extends Command {
constructor(client) {
super(client, {
name: 'donate',
aliases: ['paypal', 'patreon'],
group: 'util-public',
memberName: 'donate',
description: 'Responds with the bot\'s donation links.',
guarded: true,
credit: [
{
name: 'PayPal',
url: 'https://www.paypal.com/us/home',
reason: 'Donation Gathering'
},
{
name: 'Patreon',
url: 'https://www.patreon.com/',
reason: 'Donation Gathering'
}
]
});
}
run(msg) {
if (this.client.patreon.patrons.includes(msg.author.id)) {
return msg.say('🎉 You are already a patron. Enjoy your rewards!');
}
return msg.say(stripIndents`
Contribute to development!
<https://www.patreon.com/xiaodiscord>
<https://paypal.me/dragonfire535>
`);
}
};
+3 -2
View File
@@ -11,7 +11,7 @@ module.exports = class InfoCommand extends Command {
constructor(client) {
super(client, {
name: 'info',
aliases: ['stats', 'uptime'],
aliases: ['stats', 'uptime', 'prefix', 'invite'],
group: 'util-public',
memberName: 'info',
description: 'Responds with detailed bot information.',
@@ -22,6 +22,7 @@ module.exports = class InfoCommand extends Command {
run(msg) {
const invite = this.client.generateInvite({ permissions: ['ADMINISTRATOR'], scopes: ['bot'] });
const prefix = msg.guild ? msg.guild.commandPrefix : this.client.commandPrefix;
const embed = new MessageEmbed()
.setColor(0x00AE86)
.setFooter(copyright.join('\n'))
@@ -31,7 +32,7 @@ module.exports = class InfoCommand extends Command {
.addField(' Home Server',
this.client.options.invite ? embedURL('Invite', this.client.options.invite) : 'None', true)
.addField(' Invite', embedURL('Add Me', invite), true)
.addField(' Donate', embedURL('Patreon', 'https://www.patreon.com/xiaodiscord'), true)
.addField(' Prefix', prefix || 'None', true)
.addField(' Memory Usage', `${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)}MB`, true)
.addField(' Uptime', moment.duration(this.client.uptime).format('d:hh:mm:ss'), true)
.addField(' Version', `v${version}`, true)
-26
View File
@@ -1,26 +0,0 @@
const Command = require('../../framework/Command');
const { stripIndents } = require('common-tags');
const permissions = require('../../assets/json/permissions');
module.exports = class InviteCommand extends Command {
constructor(client) {
super(client, {
name: 'invite',
group: 'util-public',
memberName: 'invite',
description: 'Responds with the bot\'s invite links.',
guarded: true
});
}
async run(msg) {
const invite = await this.client.generateInvite({ permissions });
return msg.say(stripIndents`
Invite me using this link:
<${invite}>
Join my home server for support and announcements:
${this.client.options.invite || 'Coming soon...'}
`);
}
};
-18
View File
@@ -1,18 +0,0 @@
const Command = require('../../framework/Command');
module.exports = class PrefixCommand extends Command {
constructor(client) {
super(client, {
name: 'prefix',
group: 'util-public',
memberName: 'prefix',
description: 'Responds with the bot\'s command prefix.',
guarded: true
});
}
run(msg) {
const prefix = msg.guild ? msg.guild.commandPrefix : this.client.commandPrefix;
return msg.reply(prefix ? `The command prefix is \`${prefix}\`.` : 'There is no command prefix.');
}
};
-29
View File
@@ -1,29 +0,0 @@
const Command = require('../../framework/Command');
module.exports = class ForcePatronCommand extends Command {
constructor(client) {
super(client, {
name: 'force-patron',
group: 'util',
memberName: 'force-patron',
description: 'Allows a user to use patron-only commands.',
details: 'Only the bot owner(s) may use this command.',
ownerOnly: true,
guarded: true,
args: [
{
key: 'target',
prompt: 'Who do you want to allow? Use the ID.',
type: 'string'
}
]
});
}
run(msg, { target }) {
if (this.client.patreon.isPatron(target)) return msg.say(`💸 \`${target}\` is already a patron.`);
this.client.patreon.forced.push(target);
this.client.patreon.exportForced();
return msg.say(`💸 Allowed \`${target}\` to use patron-only commands.`);
}
};
-30
View File
@@ -1,30 +0,0 @@
const Command = require('../../framework/Command');
const { removeFromArray } = require('../../util/Util');
module.exports = class UnforcePatronCommand extends Command {
constructor(client) {
super(client, {
name: 'unforce-patron',
group: 'util',
memberName: 'unforce-patron',
description: 'Disallows a user from using patron-only commands.',
details: 'Only the bot owner(s) may use this command.',
ownerOnly: true,
guarded: true,
args: [
{
key: 'target',
prompt: 'Who do you want to disallow? Use the ID.',
type: 'string'
}
]
});
}
run(msg, { target }) {
if (!this.client.patreon.isPatron(target)) return msg.say(`💸 \`${target}\` is not a patron.`);
removeFromArray(this.client.patreon.forced, target);
this.client.patreon.exportForced();
return msg.say(`💸 Disallowed \`${target}\` from using patron-only commands.`);
}
};
-33
View File
@@ -1,33 +0,0 @@
const Command = require('../../framework/Command');
module.exports = class WebhookCommand extends Command {
constructor(client) {
super(client, {
name: 'webhook',
aliases: ['rin', 'rin-say'],
group: 'util',
memberName: 'webhook',
description: 'Posts a message to the webhook defined in the bot owner\'s `process.env`.',
details: 'Only the bot owner(s) may use this command.',
ownerOnly: true,
clientPermissions: ['MANAGE_MESSAGES'],
args: [
{
key: 'content',
prompt: 'What text would you like the webhook to say?',
type: 'string'
}
]
});
}
async run(msg, { content }) {
try {
if (msg.guild && msg.deletable) await msg.delete();
await this.client.webhook.send(content);
return null;
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-141
View File
@@ -1,141 +0,0 @@
const Command = require('../../framework/Command');
const path = require('path');
const { list, reactIfAble } = require('../../util/Util');
const sounds = require('../../assets/json/soundboard');
const soundsChoice = sounds.map(sound => sound[sound.length - 1].replace(/\.mp3$/, ''));
module.exports = class SoundboardCommand extends Command {
constructor(client) {
super(client, {
name: 'soundboard',
aliases: ['sound'],
group: 'voice',
memberName: 'soundboard',
description: 'Plays a sound in a voice channel.',
details: `**Sounds:** ${soundsChoice.join(', ')}`,
guildOnly: true,
throttling: {
usages: 2,
duration: 10
},
userPermissions: ['CONNECT', 'SPEAK'],
credit: [
{
name: '07th Expansion',
url: 'http://07th-expansion.net/',
reason: 'Nipah Sound'
},
{
name: 'UncleKornicob',
url: 'http://soundbible.com/',
reason: 'Alarm Sound',
reasonURL: 'http://soundbible.com/1787-Annoying-Alarm-Clock.html'
},
{
name: 'Mike Koenig',
url: 'http://soundbible.com/',
reason: 'Rooster Sound',
reasonURL: 'http://soundbible.com/1218-Rooster-Crow.html'
},
{
name: 'Mike Koenig',
url: 'http://soundbible.com/',
reason: 'Cow Sound',
reasonURL: 'http://soundbible.com/1778-Cow-Moo.html'
},
{
name: 'Cam Martinez',
url: 'http://soundbible.com/',
reason: 'Car Crash Sound',
reasonURL: 'http://soundbible.com/1757-Car-Brake-Crash.html'
},
{
name: 'Orange Free Sounds',
url: 'http://www.orangefreesounds.com/',
reason: 'Dun Dun Dun Sound',
reasonURL: 'http://www.orangefreesounds.com/dun-dun-dun-sound-effect-brass/'
},
{
name: 'Apple',
url: 'https://www.apple.com/',
reason: 'Cat Sound'
},
{
name: 'GRSites',
url: 'http://www.grsites.com/',
reason: 'Laugh Track Sound',
reasonURL: 'http://www.grsites.com/archive/sounds/category/8/'
},
{
name: 'Jeopardy',
url: 'https://www.jeopardy.com/',
reason: 'Jeopardy Sound'
},
{
name: '4Kids',
url: 'https://www.4kidsentertainmentinc.com/',
reason: 'Who\'s That Pokémon Sound'
},
{
name: 'Over the Green Fields',
url: 'https://asianwiki.com/Over_the_Green_Fields',
reason: 'Sad Violin Sound'
},
{
name: 'Valve',
url: 'https://www.valvesoftware.com/en/',
reasonURL: 'http://www.thinkwithportals.com/',
reason: 'Slow Clap Sound'
},
{
name: 'Microsoft',
url: 'https://www.microsoft.com/en-us',
reason: 'Windows Start Up and Windows Error Sounds'
},
{
name: 'Star Wars',
url: 'https://www.starwars.com/',
reason: 'Hello There Sound'
},
{
name: 'Rockstar Games',
url: 'https://www.rockstargames.com/',
reason: 'Here We Go Again Sound'
},
{
name: 'KONOSUBA -God\'s blessing on this wonderful world!',
url: 'http://konosuba.com/',
reason: 'Explosion Sound'
}
],
args: [
{
key: 'sound',
prompt: `What sound do you want to play? Either ${list(soundsChoice, 'or')}.`,
type: 'string',
validate: sound => {
const choice = sound.toLowerCase().replaceAll(' ', '-');
if (soundsChoice.includes(choice)) return true;
return `You provided an invalid sound. Please choose either ${list(soundsChoice, 'or')}.`;
},
parse: sound => {
const choice = sound.toLowerCase().replaceAll(' ', '-');
return sounds.find(snd => snd.includes(`${choice}.mp3`));
}
}
]
});
}
async run(msg, { sound }) {
const connection = this.client.dispatchers.get(msg.guild.id);
if (!connection) {
const usage = this.client.registry.commands.get('join').usage();
return msg.reply(`I am not in a voice channel. Use ${usage} to fix that!`);
}
if (!connection.canPlay) return msg.reply('I am already playing audio in this server.');
connection.play(path.join(__dirname, '..', '..', 'assets', 'sounds', ...sound));
await reactIfAble(msg, this.client.user, '🔉');
return null;
}
};
-71
View File
@@ -1,71 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { Readable } = require('stream');
const { list, reactIfAble } = require('../../util/Util');
const voices = require('../../assets/json/vocodes');
const { LOADING_EMOJI_ID } = process.env;
module.exports = class VocodesCommand extends Command {
constructor(client) {
super(client, {
name: 'vocodes',
aliases: ['vocode'],
group: 'voice',
memberName: 'vocodes',
description: 'Speak text like a variety of famous figures.',
details: `**Voices:** ${Object.keys(voices).join(', ')}`,
guildOnly: true,
throttling: {
usages: 2,
duration: 30
},
userPermissions: ['CONNECT', 'SPEAK'],
credit: [
{
name: 'Vocodes',
url: 'https://vo.codes/',
reason: 'API'
}
],
args: [
{
key: 'voice',
prompt: `What voice do you want to use? Either ${list(Object.keys(voices), 'or')}.`,
type: 'string',
oneOf: Object.keys(voices),
parse: voice => voices[voice.toLowerCase()]
},
{
key: 'text',
prompt: 'What text do you want to say?',
type: 'string',
max: 500
}
]
});
}
async run(msg, { voice, text }) {
const connection = this.client.dispatchers.get(msg.guild.id);
if (!connection) {
const usage = this.client.registry.commands.get('join').usage();
return msg.reply(`I am not in a voice channel. Use ${usage} to fix that!`);
}
if (!connection.canPlay) return msg.reply('I am already playing audio in this server.');
try {
await reactIfAble(msg, this.client.user, LOADING_EMOJI_ID, '💬');
const { body } = await request
.post('https://mumble.stream/speak_spectrogram')
.send({
speaker: voice,
text
});
connection.play(Readable.from([Buffer.from(body.audio_base64, 'base64')]));
await reactIfAble(msg, this.client.user, '🔉');
return null;
} catch (err) {
await reactIfAble(msg, this.client.user, '⚠️');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};