mirror of
https://github.com/arthur-pbty/xiao.git
synced 2026-06-12 08:14:47 +02:00
Split edit-image into edit-image-text
This commit is contained in:
@@ -1,89 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
const { firstUpperCase, list } = require('../../util/Util');
|
||||
const { wrapText } = require('../../util/Canvas');
|
||||
const characters = {
|
||||
phoenix: ['phoenix', 'wright', 'naruhodo', 'ryuuichi', 'ryu', 'nick'],
|
||||
edgeworth: ['miles', 'edgeworth', 'mitsurugi', 'reiji', 'edgey'],
|
||||
godot: ['godot', 'diego', 'armando', 'souryuu', 'soryu', 'kaminogi'],
|
||||
apollo: ['apollo', 'justice', 'odoroki', 'housuke', 'hosuke']
|
||||
};
|
||||
|
||||
module.exports = class AceAttorneyCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'ace-attorney',
|
||||
aliases: [
|
||||
'aa',
|
||||
'ace-attorney-dialogue',
|
||||
'aa-dialogue',
|
||||
'ace-attorney-dialog',
|
||||
'aa-dialog',
|
||||
'ace-attorney-quote',
|
||||
'aa-quote'
|
||||
],
|
||||
group: 'edit-image',
|
||||
memberName: 'ace-attorney',
|
||||
description: 'Sends a text box from Ace Attorney with the quote and character of your choice.',
|
||||
details: `**Characters:** ${Object.keys(characters).join(', ')}`,
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Capcom',
|
||||
url: 'http://www.capcom.com/us/',
|
||||
reason: 'Images, Original "Ace Attorney" Game',
|
||||
reasonURL: 'http://www.ace-attorney.com/'
|
||||
},
|
||||
{
|
||||
name: 'Enkidulga',
|
||||
url: 'https://www.dafont.com/profile.php?user=736583',
|
||||
reason: 'Ace Attorney Font',
|
||||
reasonURL: 'https://www.dafont.com/ace-attorney.font'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'character',
|
||||
prompt: `What character do you want to use? Either ${list(Object.keys(characters), 'or')}.`,
|
||||
type: 'string',
|
||||
oneOf: Object.values(characters).reduce((a, b) => a.concat(b)),
|
||||
parse: character => character.toLowerCase()
|
||||
},
|
||||
{
|
||||
key: 'quote',
|
||||
prompt: 'What should the character say?',
|
||||
type: 'string',
|
||||
max: 250
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { character, quote }) {
|
||||
let file;
|
||||
for (const [id, arr] of Object.entries(characters)) {
|
||||
if (!arr.includes(character.toLowerCase())) continue;
|
||||
file = id;
|
||||
break;
|
||||
}
|
||||
const base = await loadImage(
|
||||
path.join(__dirname, '..', '..', 'assets', 'images', 'ace-attorney', `${file}.png`)
|
||||
);
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.font = this.client.fonts.get('Ace-Attorney.ttf').toCanvasString(14);
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.fillText(firstUpperCase(character), 6, 176);
|
||||
let text = await wrapText(ctx, quote, 242);
|
||||
text = text.length > 5 ? `${text.slice(0, 5).join('\n')}...` : text.join('\n');
|
||||
ctx.fillText(text, 7, 199);
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: `ace-attorney-${character}.png` }] });
|
||||
}
|
||||
};
|
||||
@@ -1,61 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
const { shortenText } = require('../../util/Canvas');
|
||||
|
||||
module.exports = class AchievementCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'achievement',
|
||||
aliases: ['minecraft-achievement', 'achieve'],
|
||||
group: 'edit-image',
|
||||
memberName: 'achievement',
|
||||
description: 'Sends a Minecraft achievement with the text of your choice.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Mojang',
|
||||
url: 'https://www.mojang.com/',
|
||||
reason: 'Original "Minecraft" Game',
|
||||
reasonURL: 'https://www.minecraft.net/en-us/'
|
||||
},
|
||||
{
|
||||
name: 'Minecraft Achievement Generator',
|
||||
url: 'https://www.minecraftskinstealer.com/achievement/',
|
||||
reason: 'Image'
|
||||
},
|
||||
{
|
||||
name: 'Andrew Tyler',
|
||||
url: 'https://www.dafont.com/andrew-tyler.d2526',
|
||||
reason: 'Minecraftia Font',
|
||||
reasonURL: 'https://www.dafont.com/minecraftia.font'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'text',
|
||||
prompt: 'What should the text of the achievement be?',
|
||||
type: 'string',
|
||||
max: 50
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { text }) {
|
||||
const base = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'achievement.png'));
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.font = this.client.fonts.get('Minecraftia.ttf').toCanvasString(17);
|
||||
ctx.fillStyle = '#ffff00';
|
||||
ctx.fillText('Achievement Get!', 60, 40);
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fillText(shortenText(ctx, text, 230), 60, 60);
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'achievement.png' }] });
|
||||
}
|
||||
};
|
||||
@@ -1,53 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const request = require('node-superfetch');
|
||||
const { list } = require('../../util/Util');
|
||||
const products = require('../../assets/json/apple-engraving');
|
||||
|
||||
module.exports = class AppleEngravingCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'apple-engraving',
|
||||
aliases: ['apple-engrave', 'apple-e', 'a-engrave', 'a-engraving'],
|
||||
group: 'edit-image',
|
||||
memberName: 'apple-engraving',
|
||||
description: 'Engraves the text of your choice onto an Apple product.',
|
||||
details: `**Products:** ${Object.keys(products).join(', ')}`,
|
||||
credit: [
|
||||
{
|
||||
name: 'Apple',
|
||||
url: 'https://www.apple.com/',
|
||||
reason: 'API'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'product',
|
||||
prompt: `What product do you want to engrave? Either ${list(Object.keys(products), 'or')}.`,
|
||||
type: 'string',
|
||||
oneOf: Object.keys(products),
|
||||
parse: product => product.toLowerCase()
|
||||
},
|
||||
{
|
||||
key: 'text',
|
||||
prompt: 'What text do you want to engrave?',
|
||||
type: 'string'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { product, text }) {
|
||||
try {
|
||||
const { body } = await request
|
||||
.get(`https://www.apple.com/shop/preview/engrave/${products[product]}/A`)
|
||||
.query({
|
||||
th: text,
|
||||
s: 2,
|
||||
f: 'font1'
|
||||
});
|
||||
return msg.say({ files: [{ attachment: body, name: 'apple-engraving.jpg' }] });
|
||||
} catch (err) {
|
||||
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,77 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = class AxisCultSignUpCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'axis-cult-sign-up',
|
||||
aliases: ['axis-sign-up'],
|
||||
group: 'edit-image',
|
||||
memberName: 'axis-cult-sign-up',
|
||||
description: 'Sends an Axis Cult Sign-Up sheet for you. Join today!',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'cheesecakejedi',
|
||||
url: 'https://imgur.com/user/cheesecakejedi',
|
||||
reason: 'Image',
|
||||
reasonURL: 'https://imgur.com/gallery/quQTD'
|
||||
},
|
||||
{
|
||||
name: 'hbl917070',
|
||||
url: 'https://github.com/hbl917070',
|
||||
reason: 'Font',
|
||||
reasonURL: 'https://github.com/hbl917070/Konosuba-text'
|
||||
},
|
||||
{
|
||||
name: 'KONOSUBA -God\'s blessing on this wonderful world!',
|
||||
url: 'http://konosuba.com/',
|
||||
reason: 'Original Anime'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'gender',
|
||||
prompt: 'What is your gender?',
|
||||
type: 'string',
|
||||
oneOf: ['male', 'female']
|
||||
},
|
||||
{
|
||||
key: 'age',
|
||||
prompt: 'How old are you?',
|
||||
type: 'integer',
|
||||
min: 1,
|
||||
max: 10000
|
||||
},
|
||||
{
|
||||
key: 'profession',
|
||||
prompt: 'What is your profession?',
|
||||
type: 'string',
|
||||
max: 15
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { gender, age, profession }) {
|
||||
const base = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'axis-cult-sign-up.jpg'));
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.font = this.client.fonts.get('Konosuba.ttf').toCanvasString(96);
|
||||
ctx.fillText(msg.author.username, 960, 1558);
|
||||
ctx.fillText(gender, 960, 1752);
|
||||
ctx.fillText(age, 1700, 1752);
|
||||
ctx.fillText('XXX-XXX-XXXX', 960, 1960);
|
||||
ctx.fillText(profession, 960, 2169);
|
||||
ctx.fillText('Xiao', 960, 2370);
|
||||
ctx.font = this.client.fonts.get('Konosuba.ttf').toCanvasString(123);
|
||||
ctx.fillText('ERIS PADS\nHER CHEST!', 1037, 2874);
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer('image/jpeg'), name: 'axis-cult-sign-up.jpg' }] });
|
||||
}
|
||||
};
|
||||
@@ -1,65 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
const { wrapText } = require('../../util/Canvas');
|
||||
|
||||
module.exports = class CautionCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'caution',
|
||||
aliases: ['caution-sign'],
|
||||
group: 'edit-image',
|
||||
memberName: 'caution',
|
||||
description: 'Creates a caution sign with the text of your choice.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Google',
|
||||
url: 'https://www.google.com/',
|
||||
reason: 'Noto Font',
|
||||
reasonURL: 'https://www.google.com/get/noto/'
|
||||
},
|
||||
{
|
||||
name: 'Wikimedia Commons',
|
||||
url: 'https://commons.wikimedia.org/wiki/Main_Page',
|
||||
reason: 'Image',
|
||||
reasonURL: 'https://commons.wikimedia.org/wiki/File:Caution_blank.svg'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'text',
|
||||
prompt: 'What text should the caution sign say?',
|
||||
type: 'string',
|
||||
max: 500
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { text }) {
|
||||
const base = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'caution.png'));
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.font = this.client.fonts.get('Noto-Bold.ttf').toCanvasString(60);
|
||||
let fontSize = 60;
|
||||
while (ctx.measureText(text).width > 3311) {
|
||||
fontSize--;
|
||||
ctx.font = this.client.fonts.get('Noto-Bold.ttf').toCanvasString(fontSize);
|
||||
}
|
||||
const lines = await wrapText(ctx, text.toUpperCase(), 895);
|
||||
const topMost = 470 - (((fontSize * lines.length) / 2) + ((20 * (lines.length - 1)) / 2));
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const height = topMost + ((fontSize + 20) * i);
|
||||
ctx.fillText(lines[i], base.width / 2, height);
|
||||
}
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'caution.png' }] });
|
||||
}
|
||||
};
|
||||
@@ -1,69 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const moment = require('moment');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = class CertificateCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'certificate',
|
||||
aliases: ['award', 'certificate-of-excellence', 'cert', 'cert-of-excellence'],
|
||||
group: 'edit-image',
|
||||
memberName: 'certificate',
|
||||
description: 'Sends a certificate of excellence with the name and reason of your choice.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Creative Certificates',
|
||||
url: 'https://www.creativecertificates.com/',
|
||||
reason: 'Image',
|
||||
reasonURL: 'https://www.creativecertificates.com/award-certificate-templates/'
|
||||
},
|
||||
{
|
||||
name: 'Cheng Xiao',
|
||||
url: 'https://www.instagram.com/chengxiao_0715/',
|
||||
reason: 'Signature'
|
||||
},
|
||||
{
|
||||
name: 'Monotype',
|
||||
url: 'https://www.monotype.com/',
|
||||
reason: 'Old English Text MT Font',
|
||||
reasonURL: 'https://catalog.monotype.com/family/monotype/monotype-old-english-text'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'reason',
|
||||
prompt: 'What is the reason for the award?',
|
||||
type: 'string',
|
||||
max: 30
|
||||
},
|
||||
{
|
||||
key: 'name',
|
||||
prompt: 'What is the name of the person recieving the award?',
|
||||
type: 'string',
|
||||
max: 30,
|
||||
default: msg => msg.author.username
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { reason, name }) {
|
||||
const base = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'certificate.png'));
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.font = this.client.fonts.get('oldengl.ttf').toCanvasString(30);
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillText(reason, 518, 273);
|
||||
ctx.fillText(name, 518, 419);
|
||||
ctx.fillText(moment().format('MM/DD/YYYY'), 309, 503);
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'certificate.png' }] });
|
||||
}
|
||||
};
|
||||
@@ -1,70 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
const { wrapText } = require('../../util/Canvas');
|
||||
|
||||
module.exports = class ChineseRestaurantCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'chinese-restaurant',
|
||||
aliases: ['chinese-restaurant-sign', 'chinese-food-sign', 'chinese-sign'],
|
||||
group: 'edit-image',
|
||||
memberName: 'chinese-restaurant',
|
||||
description: 'Sends a Chinese restaurant sign with the text of your choice.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'ATOM.SMASHER.ORG',
|
||||
url: 'http://atom.smasher.org/',
|
||||
reason: 'Image',
|
||||
reasonURL: 'http://atom.smasher.org/chinese/'
|
||||
},
|
||||
{
|
||||
name: 'Fontsgeek',
|
||||
url: 'http://fontsgeek.com/',
|
||||
reason: 'Futura Condensed Font',
|
||||
reasonURL: 'http://fontsgeek.com/fonts/Futura-Condensed-Bold'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'text',
|
||||
prompt: 'What should the text of the sign be?',
|
||||
type: 'string'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { text }) {
|
||||
const base = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'chinese-restaurant.png'));
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.fillStyle = '#1f1f1f';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.font = this.client.fonts.get('Futura Condensed Bold.otf').toCanvasString(28);
|
||||
const lines = await wrapText(ctx, text.toUpperCase(), 340);
|
||||
if (lines.length === 1) {
|
||||
ctx.fillText(lines[0], base.width / 2, 288);
|
||||
} else if (lines.length === 2) {
|
||||
ctx.fillText(lines[0], base.width / 2, 288);
|
||||
ctx.fillText(lines[1], base.width / 2, 315);
|
||||
} else if (lines.length === 3) {
|
||||
ctx.fillText(lines[0], base.width / 2, 261);
|
||||
ctx.fillText(lines[1], base.width / 2, 288);
|
||||
ctx.fillText(lines[2], base.width / 2, 315);
|
||||
} else {
|
||||
ctx.fillText(lines[0], base.width / 2, 261);
|
||||
ctx.fillText(lines[1], base.width / 2, 288);
|
||||
ctx.fillText(lines[2], base.width / 2, 315);
|
||||
ctx.fillText(lines[3], base.width / 2, 342);
|
||||
}
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'chinese-restaurant.png' }] });
|
||||
}
|
||||
};
|
||||
@@ -1,65 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
const { wrapText } = require('../../util/Canvas');
|
||||
|
||||
module.exports = class DangerCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'danger',
|
||||
aliases: ['danger-sign'],
|
||||
group: 'edit-image',
|
||||
memberName: 'danger',
|
||||
description: 'Creates a danger sign with the text of your choice.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Google',
|
||||
url: 'https://www.google.com/',
|
||||
reason: 'Noto Font',
|
||||
reasonURL: 'https://www.google.com/get/noto/'
|
||||
},
|
||||
{
|
||||
name: 'Wikimedia Commons',
|
||||
url: 'https://commons.wikimedia.org/wiki/Main_Page',
|
||||
reason: 'Image',
|
||||
reasonURL: 'https://commons.wikimedia.org/wiki/File:Danger_blank.svg'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'text',
|
||||
prompt: 'What text should the danger sign say?',
|
||||
type: 'string',
|
||||
max: 500
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { text }) {
|
||||
const base = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'danger.png'));
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.font = this.client.fonts.get('Noto-Bold.ttf').toCanvasString(60);
|
||||
let fontSize = 60;
|
||||
while (ctx.measureText(text).width > 2520) {
|
||||
fontSize--;
|
||||
ctx.font = this.client.fonts.get('Noto-Bold.ttf').toCanvasString(fontSize);
|
||||
}
|
||||
const lines = await wrapText(ctx, text.toUpperCase(), 840);
|
||||
const topMost = 510 - (((fontSize * lines.length) / 2) + ((20 * (lines.length - 1)) / 2));
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const height = topMost + ((fontSize + 20) * i);
|
||||
ctx.fillText(lines[i], base.width / 2, height);
|
||||
}
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'danger.png' }] });
|
||||
}
|
||||
};
|
||||
@@ -1,53 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas } = require('canvas');
|
||||
const { wrapText } = require('../../util/Canvas');
|
||||
|
||||
module.exports = class FontCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'font',
|
||||
aliases: ['font-test', 'text-image', 'txt-img', 'text-img', 'txt-image'],
|
||||
group: 'edit-image',
|
||||
memberName: 'font',
|
||||
description: 'Types text in a specific font.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
args: [
|
||||
{
|
||||
key: 'font',
|
||||
prompt: 'What font do you want to use? Only fonts used in other commands are available.',
|
||||
type: 'font'
|
||||
},
|
||||
{
|
||||
key: 'text',
|
||||
prompt: 'What text do you want to type?',
|
||||
type: 'string'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { font, text }) {
|
||||
const image = await this.generateImage(font, text);
|
||||
return msg.say({ files: [{ attachment: image, name: `${font.filenameNoExt}.png` }] });
|
||||
}
|
||||
|
||||
async generateImage(font, text) {
|
||||
const canvasPre = createCanvas(1, 1);
|
||||
const ctxPre = canvasPre.getContext('2d');
|
||||
ctxPre.font = this.client.fonts.get(font.filename).toCanvasString(50);
|
||||
const len = ctxPre.measureText(text);
|
||||
const lines = await wrapText(ctxPre, text, 950);
|
||||
const canvas = createCanvas(Math.min(len.width + 50, 1000), 50 + (50 * lines.length) + (20 * lines.length));
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.font = this.client.fonts.get(font.filename).toCanvasString(50);
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.fillStyle = 'black';
|
||||
ctx.fillText(lines.join('\n'), 25, 25);
|
||||
return canvas.toBuffer();
|
||||
}
|
||||
};
|
||||
@@ -1,60 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
const { wrapText } = require('../../util/Canvas');
|
||||
|
||||
module.exports = class GandhiQuoteCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'gandhi-quote',
|
||||
aliases: ['gandhi', 'mahatma-gandhi', 'mahatma-gandhi-quote'],
|
||||
group: 'edit-image',
|
||||
memberName: 'gandhi-quote',
|
||||
description: 'Makes Mahatma Gandhi say the quote you want.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'GUST e-foundry',
|
||||
url: 'https://www.fontsquirrel.com/fonts/list/foundry/gust-e-foundry',
|
||||
reason: 'Latin Modern Roman Font',
|
||||
reasonURL: 'https://www.fontsquirrel.com/fonts/Latin-Modern-Roman'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'quote',
|
||||
prompt: 'What quote should Gandhi say?',
|
||||
type: 'string',
|
||||
max: 500
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { quote }) {
|
||||
const base = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'gandhi-quote.png'));
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.font = this.client.fonts.get('lmroman10-italic.otf').toCanvasString(50);
|
||||
ctx.fillStyle = 'white';
|
||||
let fontSize = 50;
|
||||
while (ctx.measureText(quote).width > 945) {
|
||||
fontSize--;
|
||||
ctx.font = this.client.fonts.get('lmroman10-italic.otf').toCanvasString(fontSize);
|
||||
}
|
||||
const lines = await wrapText(ctx, quote, 270);
|
||||
const topMost = 180 - (((fontSize * lines.length) / 2) + ((20 * (lines.length - 1)) / 2));
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const height = topMost + ((fontSize + 20) * i);
|
||||
ctx.fillText(lines[i], 395, height);
|
||||
}
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'gandhi-quote.png' }] });
|
||||
}
|
||||
};
|
||||
@@ -1,70 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
const { wrapText } = require('../../util/Canvas');
|
||||
|
||||
module.exports = class HighwaySignCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'highway-sign',
|
||||
aliases: ['road-sign', 'road-work-sign', 'electronic-highway-sign'],
|
||||
group: 'edit-image',
|
||||
memberName: 'highway-sign',
|
||||
description: 'Sends a highway sign sign with the text of your choice.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'ATOM.SMASHER.ORG',
|
||||
url: 'http://atom.smasher.org/',
|
||||
reason: 'Image',
|
||||
reasonURL: 'http://atom.smasher.org/construction/'
|
||||
},
|
||||
{
|
||||
name: 'Ash Pikachu Font',
|
||||
url: 'https://www.dafont.com/ashpikachu099.d2541',
|
||||
reason: 'Electronic Highway Sign Font',
|
||||
reasonURL: 'https://www.dafont.com/electronic-highway-sign.font'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'text',
|
||||
prompt: 'What should the text of the sign be?',
|
||||
type: 'string'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { text }) {
|
||||
const base = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'highway-sign.png'));
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.fillStyle = '#efe390';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.font = this.client.fonts.get('EHSMB.ttf').toCanvasString(18);
|
||||
const lines = await wrapText(ctx, text.toUpperCase(), 178);
|
||||
if (lines.length === 1) {
|
||||
ctx.fillText(lines[0], 318, 109);
|
||||
} else if (lines.length === 2) {
|
||||
ctx.fillText(lines[0], 318, 109);
|
||||
ctx.fillText(lines[1], 318, 128);
|
||||
} else if (lines.length === 3) {
|
||||
ctx.fillText(lines[0], 318, 90);
|
||||
ctx.fillText(lines[1], 318, 109);
|
||||
ctx.fillText(lines[2], 318, 128);
|
||||
} else {
|
||||
ctx.fillText(lines[0], 318, 90);
|
||||
ctx.fillText(lines[1], 318, 109);
|
||||
ctx.fillText(lines[2], 318, 128);
|
||||
ctx.fillText(lines[3], 318, 147);
|
||||
}
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'highway-sign.png' }] });
|
||||
}
|
||||
};
|
||||
@@ -1,60 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = class HollywoodStarCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'hollywood-star',
|
||||
aliases: ['hollywood', 'walk-of-fame', 'walk-of-fame-star'],
|
||||
group: 'edit-image',
|
||||
memberName: 'hollywood-star',
|
||||
description: 'Sends a Hollywood Walk of Fame star with the name of your choice.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'RedKid.Net',
|
||||
url: 'http://www.redkid.net/',
|
||||
reason: 'Image',
|
||||
reasonURL: 'http://www.redkid.net/generator/star/'
|
||||
},
|
||||
{
|
||||
name: 'Alexey Star',
|
||||
url: 'https://alexeystar.com/',
|
||||
reason: 'Hollywood Star Font',
|
||||
reasonURL: 'https://alexeystar.com/hollywood-star-font/'
|
||||
},
|
||||
{
|
||||
name: 'Hollywood Walk of Fame',
|
||||
url: 'https://walkoffame.com/',
|
||||
reason: 'Concept'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'name',
|
||||
prompt: 'What name should be on the star?',
|
||||
type: 'string',
|
||||
max: 30
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { name }) {
|
||||
const base = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'hollywood-star.png'));
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.font = this.client.fonts.get('HollywoodStar.otf').toCanvasString(28);
|
||||
ctx.fillStyle = '#fadfd4';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.fillText(name.toLowerCase(), 288, 140);
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'hollywood-star.png' }] });
|
||||
}
|
||||
};
|
||||
@@ -1,62 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas } = require('canvas');
|
||||
const { wrapText } = require('../../util/Canvas');
|
||||
|
||||
module.exports = class JeopardyQuestionCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'jeopardy-question',
|
||||
aliases: ['clue-card', 'jeopardy-clue-card', 'jeopardy-clue'],
|
||||
group: 'edit-image',
|
||||
memberName: 'jeopardy-question',
|
||||
description: 'Sends a Jeopardy Question with the text of your choice.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Jeopardy',
|
||||
url: 'https://www.jeopardy.com/',
|
||||
reason: 'Original Show'
|
||||
},
|
||||
{
|
||||
name: 'OPTIFONT',
|
||||
url: 'http://opti.netii.net/',
|
||||
reason: 'Korinna Agency Font',
|
||||
reasonURL: 'https://fontmeme.com/fonts/korinna-agency-font/'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'text',
|
||||
prompt: 'What should the text of the question be?',
|
||||
type: 'string',
|
||||
max: 500
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { text }) {
|
||||
const canvas = createCanvas(1280, 720);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.fillStyle = '#030e78';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.font = this.client.fonts.get('OPTIKorinna-Agency.otf').toCanvasString(62);
|
||||
const lines = await wrapText(ctx, text.toUpperCase(), 813);
|
||||
const topMost = (canvas.height / 2) - (((52 * lines.length) / 2) + ((20 * (lines.length - 1)) / 2));
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const height = topMost + ((52 + 20) * i);
|
||||
ctx.fillStyle = 'black';
|
||||
ctx.fillText(lines[i], (canvas.width / 2) + 6, height + 6);
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillText(lines[i], canvas.width / 2, height);
|
||||
}
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'jeopardy-question.png' }] });
|
||||
}
|
||||
};
|
||||
@@ -1,53 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = class LicensePlateCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'license-plate',
|
||||
group: 'edit-image',
|
||||
memberName: 'license-plate',
|
||||
description: 'Creates a license plate with the text of your choice.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Dave Hansen',
|
||||
url: 'https://www.fontspace.com/dave-hansen',
|
||||
reason: 'License Plate Font',
|
||||
reasonURL: 'https://www.fontspace.com/license-plate-font-f3359'
|
||||
},
|
||||
{
|
||||
name: 'Pin Clipart',
|
||||
url: 'https://www.pinclipart.com/',
|
||||
reason: 'Image',
|
||||
reasonURL: 'https://www.pinclipart.com/maxpin/bJxii/'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'text',
|
||||
prompt: 'What text should the license plate say?',
|
||||
type: 'string',
|
||||
max: 10
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { text }) {
|
||||
const base = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'license-plate.png'));
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.font = this.client.fonts.get('LicensePlate.ttf').toCanvasString(180);
|
||||
ctx.fillText(text.toUpperCase(), base.width / 2, base.height / 2, 700);
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'license-plate.png' }] });
|
||||
}
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const request = require('node-superfetch');
|
||||
const moment = require('moment');
|
||||
|
||||
module.exports = class NewspaperCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'newspaper',
|
||||
group: 'edit-image',
|
||||
memberName: 'newspaper',
|
||||
description: 'Creates a fake newspaper with the headline and body of your choice.',
|
||||
credit: [
|
||||
{
|
||||
name: 'The Newspaper Clipping Generator',
|
||||
url: 'https://www.fodey.com/generators/newspaper/snippet.asp',
|
||||
reason: 'API'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'headline',
|
||||
prompt: 'What do you want the headline to be?',
|
||||
type: 'string',
|
||||
max: 20
|
||||
},
|
||||
{
|
||||
key: 'body',
|
||||
prompt: 'What should the body of the article be?',
|
||||
type: 'string'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { headline, body }) {
|
||||
try {
|
||||
const { text } = await request
|
||||
.post('https://www.fodey.com/generators/newspaper/snippet.asp')
|
||||
.attach('name', 'The Daily Whatever')
|
||||
.attach('date', moment().format('dddd, MMMM D, YYYY'))
|
||||
.attach('headline', headline)
|
||||
.attach('text', body);
|
||||
const newspaperURL = text.match(/<img src="(https:\/\/r[0-9]+\.fodey\.com\/[0-9]+\/.+\.jpg)"/i)[1];
|
||||
return msg.say({ files: [newspaperURL] });
|
||||
} catch (err) {
|
||||
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,52 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const request = require('node-superfetch');
|
||||
|
||||
module.exports = class ShieldsIoBadgeCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'shields-io-badge',
|
||||
aliases: ['shields-io'],
|
||||
group: 'edit-image',
|
||||
memberName: 'shields-io-badge',
|
||||
description: 'Creates a badge from shields.io.',
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Shields.io',
|
||||
url: 'https://shields.io/',
|
||||
reason: 'API'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'subject',
|
||||
prompt: 'What is the subject of the badge?',
|
||||
type: 'string',
|
||||
parse: subject => encodeURIComponent(subject.replaceAll('-', '--').replaceAll('_', '__'))
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
prompt: 'What is the status of the badge?',
|
||||
type: 'string',
|
||||
parse: status => encodeURIComponent(status.replaceAll('-', '--').replaceAll('_', '__'))
|
||||
},
|
||||
{
|
||||
key: 'color',
|
||||
prompt: 'What is the color of the badge?',
|
||||
type: 'string',
|
||||
default: 'brightgreen'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { subject, status, color }) {
|
||||
try {
|
||||
const { body } = await request.get(`https://img.shields.io/badge/${subject}-${status}-${color}.png`);
|
||||
return msg.say({ files: [{ attachment: body, name: 'badge.png' }] });
|
||||
} catch (err) {
|
||||
if (err.status === 404) return msg.reply('Could not create the badge...');
|
||||
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,55 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = class SpeedLimitCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'speed-limit',
|
||||
aliases: ['speed', 'speed-limit-sign'],
|
||||
group: 'edit-image',
|
||||
memberName: 'speed-limit',
|
||||
description: 'Sends a Speed Limit sign with the limit of your choice.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'RoadTrafficSigns',
|
||||
url: 'https://www.roadtrafficsigns.com/',
|
||||
reason: 'Image',
|
||||
reasonURL: 'https://www.roadtrafficsigns.com/speed-limit-sign/speed-limit-70-sign/sku-x-r2-1-70.aspx'
|
||||
},
|
||||
{
|
||||
name: 'Ash Pikachu Font',
|
||||
url: 'https://www.dafont.com/ashpikachu099.d2541',
|
||||
reason: 'Highway Gothic Font',
|
||||
reasonURL: 'https://www.dafont.com/highway-gothic.font'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'limit',
|
||||
prompt: 'What limit should be on the sign?',
|
||||
type: 'string',
|
||||
max: 5
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { limit }) {
|
||||
const base = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'speed-limit.png'));
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.font = this.client.fonts.get('HWYGWDE.ttf').toCanvasString(360);
|
||||
ctx.fillStyle = 'black';
|
||||
ctx.fillText(limit.toUpperCase(), 313, 356, 475);
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'speed-limit.png' }] });
|
||||
}
|
||||
};
|
||||
@@ -1,72 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
const { wrapText } = require('../../util/Canvas');
|
||||
|
||||
module.exports = class SpongebobTimeCardCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'spongebob-time-card',
|
||||
aliases: ['time-card', 'sb-time-card', 'spongebob-card', 'sb-card', 'sponge-card', 'sponge-time-card'],
|
||||
group: 'edit-image',
|
||||
memberName: 'spongebob-time-card',
|
||||
description: 'Sends a Spongebob Time Card with the text of your choice.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Nickelodeon',
|
||||
url: 'https://www.nick.com/',
|
||||
reason: 'Original "Spongebob Squarepants" Show',
|
||||
reasonURL: 'https://www.nick.com/shows/spongebob-squarepants'
|
||||
},
|
||||
{
|
||||
name: 'Spongebob Fanon',
|
||||
url: 'https://spongebob-new-fanon.fandom.com/wiki/SpongeBob_Fanon_Wiki',
|
||||
reason: 'Images',
|
||||
reasonURL: 'https://spongebob-new-fanon.fandom.com/wiki/Gallery_of_Textless_Title_Cards'
|
||||
},
|
||||
{
|
||||
name: 'nauticalspongeinc',
|
||||
url: 'https://www.fontspace.com/nauticalspongeinc',
|
||||
reason: 'Spongeboytt1 Font',
|
||||
reasonURL: 'https://www.fontspace.com/spongeboytt1-font-f29761'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'text',
|
||||
prompt: 'What should the text of the time card be?',
|
||||
type: 'string',
|
||||
max: 280
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { text }) {
|
||||
const canvas = createCanvas(1920, 1080);
|
||||
const ctx = canvas.getContext('2d');
|
||||
const num = Math.floor(Math.random() * 23);
|
||||
const base = await loadImage(
|
||||
path.join(__dirname, '..', '..', 'assets', 'images', 'spongebob-time-card', `${num}.png`)
|
||||
);
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.font = this.client.fonts.get('Spongeboytt1.ttf').toCanvasString(115);
|
||||
const lines = await wrapText(ctx, text.toUpperCase(), 1800);
|
||||
const topMost = (canvas.height / 2) - (((115 * lines.length) / 2) + ((60 * (lines.length - 1)) / 2));
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const height = topMost + ((115 + 60) * i);
|
||||
ctx.fillStyle = '#ecbd3b';
|
||||
ctx.fillText(lines[i], (canvas.width / 2) + 6, height + 6);
|
||||
ctx.fillStyle = 'black';
|
||||
ctx.fillText(lines[i], canvas.width / 2, height);
|
||||
}
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'spongebob-time-card.png' }] });
|
||||
}
|
||||
};
|
||||
@@ -1,194 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const moment = require('moment');
|
||||
const request = require('node-superfetch');
|
||||
const path = require('path');
|
||||
const { base64, formatNumberK } = require('../../util/Util');
|
||||
const { wrapText } = require('../../util/Canvas');
|
||||
const { TWITTER_KEY, TWITTER_SECRET } = process.env;
|
||||
|
||||
module.exports = class TweetCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'tweet',
|
||||
aliases: ['fake-tweet', 'twitter-tweet', 'fake-twitter-tweet'],
|
||||
group: 'edit-image',
|
||||
memberName: 'tweet',
|
||||
description: 'Sends a Twitter tweet with the user and text of your choice.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Twitter',
|
||||
url: 'https://twitter.com/',
|
||||
reason: 'Image, API',
|
||||
reasonURL: 'https://developer.twitter.com/en/docs.html'
|
||||
},
|
||||
{
|
||||
name: 'Google',
|
||||
url: 'https://www.google.com/',
|
||||
reason: 'Noto Font',
|
||||
reasonURL: 'https://www.google.com/get/noto/'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'user',
|
||||
prompt: 'What user should say the tweet? Use the handle, not the name.',
|
||||
type: 'string',
|
||||
max: 15
|
||||
},
|
||||
{
|
||||
key: 'text',
|
||||
prompt: 'What should the text of the tweet be?',
|
||||
type: 'string',
|
||||
max: 280
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
this.token = null;
|
||||
}
|
||||
|
||||
async run(msg, { user, text }) {
|
||||
try {
|
||||
if (!this.token) await this.fetchToken();
|
||||
const userData = await this.fetchUser(msg, user);
|
||||
const avatar = await loadImage(userData.avatar);
|
||||
const base1 = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'tweet', 'bg-1.png'));
|
||||
const base2 = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'tweet', 'bg-2.png'));
|
||||
const canvas = createCanvas(base1.width, base1.height + base2.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.font = this.client.fonts.get('Noto-Regular.ttf').toCanvasString(23);
|
||||
const lines = await wrapText(ctx, text, 710);
|
||||
const lineBreakLen = text.split('\n').length;
|
||||
const linesLen = (23 * lines.length)
|
||||
+ (23 * (lineBreakLen - 1))
|
||||
+ (9 * (lines.length - 1))
|
||||
+ (9 * (lineBreakLen - 1));
|
||||
canvas.height += linesLen;
|
||||
const likes = Math.floor(Math.random() * 100000) + 1;
|
||||
const retweets = Math.floor(Math.random() * 100000) + 1;
|
||||
const quoteTweets = Math.floor(Math.random() * 100000) + 1;
|
||||
const replies = Math.floor(Math.random() * 100000) + 1;
|
||||
ctx.fillStyle = '#15202b';
|
||||
ctx.fillRect(0, base1.height, canvas.width, linesLen);
|
||||
ctx.drawImage(base1, 0, 0);
|
||||
const base2StartY = base1.height + linesLen;
|
||||
ctx.drawImage(base2, 0, base2StartY);
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.font = this.client.fonts.get('Noto-Bold.ttf').toCanvasString(18);
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillText(userData.name, 105, 84);
|
||||
if (userData.verified) {
|
||||
const verified = await loadImage(
|
||||
path.join(__dirname, '..', '..', 'assets', 'images', 'tweet', 'verified.png')
|
||||
);
|
||||
const nameLen = ctx.measureText(userData.name).width;
|
||||
ctx.drawImage(verified, 105 + nameLen + 4, 88, 18, 18);
|
||||
}
|
||||
ctx.font = this.client.fonts.get('Noto-Regular.ttf').toCanvasString(17);
|
||||
ctx.fillStyle = '#8899a6';
|
||||
ctx.fillText(`@${userData.screenName}`, 106, 111);
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.font = this.client.fonts.get('Noto-Regular.ttf').toCanvasString(23);
|
||||
ctx.fillText(lines.join('\n'), 32, 164);
|
||||
ctx.fillStyle = '#8899a6';
|
||||
ctx.font = this.client.fonts.get('Noto-Regular.ttf').toCanvasString(18);
|
||||
const time = moment().format('h:mm A ∙ MMMM D, YYYY ∙');
|
||||
ctx.fillText(time, 31, base2StartY + 16);
|
||||
const timeLen = ctx.measureText(time).width;
|
||||
ctx.fillStyle = '#1b95e0';
|
||||
ctx.fillText('Twitter for Xiao', 31 + timeLen + 6, base2StartY + 16);
|
||||
ctx.fillStyle = '#8899a6';
|
||||
ctx.font = this.client.fonts.get('Noto-Regular.ttf').toCanvasString(16);
|
||||
ctx.fillText(formatNumberK(replies), 87, base2StartY + 139);
|
||||
ctx.fillText(formatNumberK(likes), 509, base2StartY + 139);
|
||||
ctx.fillText(formatNumberK(retweets + quoteTweets), 300, base2StartY + 139);
|
||||
let currentLen = 31;
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.font = this.client.fonts.get('Noto-Bold.ttf').toCanvasString(18);
|
||||
ctx.fillText(formatNumberK(retweets), currentLen, base2StartY + 77);
|
||||
currentLen += ctx.measureText(formatNumberK(retweets)).width;
|
||||
currentLen += 5;
|
||||
ctx.fillStyle = '#8899a6';
|
||||
ctx.font = this.client.fonts.get('Noto-Regular.ttf').toCanvasString(18);
|
||||
ctx.fillText('Retweets', currentLen, base2StartY + 77);
|
||||
currentLen += ctx.measureText('Retweets').width;
|
||||
currentLen += 10;
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.font = this.client.fonts.get('Noto-Bold.ttf').toCanvasString(18);
|
||||
ctx.fillText(formatNumberK(quoteTweets), currentLen, base2StartY + 77);
|
||||
currentLen += ctx.measureText(formatNumberK(quoteTweets)).width;
|
||||
currentLen += 5;
|
||||
ctx.fillStyle = '#8899a6';
|
||||
ctx.font = this.client.fonts.get('Noto-Regular.ttf').toCanvasString(18);
|
||||
ctx.fillText('Quote Tweets', currentLen, base2StartY + 77);
|
||||
currentLen += ctx.measureText('Quote Tweets').width;
|
||||
currentLen += 10;
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.font = this.client.fonts.get('Noto-Bold.ttf').toCanvasString(18);
|
||||
ctx.fillText(formatNumberK(likes), currentLen, base2StartY + 77);
|
||||
currentLen += ctx.measureText(formatNumberK(likes)).width;
|
||||
currentLen += 5;
|
||||
ctx.fillStyle = '#8899a6';
|
||||
ctx.font = this.client.fonts.get('Noto-Regular.ttf').toCanvasString(18);
|
||||
ctx.fillText('Likes', currentLen, base2StartY + 77);
|
||||
ctx.beginPath();
|
||||
ctx.arc(30 + 32, 84 + 32, 32, 0, Math.PI * 2);
|
||||
ctx.closePath();
|
||||
ctx.clip();
|
||||
ctx.drawImage(avatar, 30, 84, 64, 64);
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'tweet.png' }] });
|
||||
} catch (err) {
|
||||
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
|
||||
}
|
||||
}
|
||||
|
||||
async fetchToken() {
|
||||
const { body } = await request
|
||||
.post('https://api.twitter.com/oauth2/token')
|
||||
.set({
|
||||
Authorization: `Basic ${base64(`${TWITTER_KEY}:${TWITTER_SECRET}`)}`,
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
})
|
||||
.send('grant_type=client_credentials');
|
||||
this.token = body.access_token;
|
||||
return body;
|
||||
}
|
||||
|
||||
async fetchUser(msg, user) {
|
||||
if (user.toLowerCase() === 'realdonaldtrump') {
|
||||
return {
|
||||
screenName: 'realDonaldTrump',
|
||||
name: 'Donald J. Trump',
|
||||
avatar: path.join(__dirname, '..', '..', 'assets', 'images', 'tweet', 'realdonaldtrump.jpg'),
|
||||
verified: true
|
||||
};
|
||||
}
|
||||
try {
|
||||
const { body } = await request
|
||||
.get('https://api.twitter.com/1.1/users/show.json')
|
||||
.set({ Authorization: `Bearer ${this.token}` })
|
||||
.query({ screen_name: user });
|
||||
const avatarRes = await request.get(body.profile_image_url_https.replace('_normal', '_bigger'));
|
||||
return {
|
||||
screenName: body.screen_name,
|
||||
name: body.name,
|
||||
avatar: avatarRes.body,
|
||||
verified: body.verified
|
||||
};
|
||||
} catch {
|
||||
const avatarRes = await request.get(msg.author.displayAvatarURL({ format: 'png', size: 64 }));
|
||||
return {
|
||||
screenName: msg.author.username.slice(0, 15),
|
||||
name: msg.member ? msg.member.displayName.slice(0, 50) : msg.author.username.slice(0, 50),
|
||||
avatar: avatarRes.body,
|
||||
verified: false
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,124 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
const { list } = require('../../util/Util');
|
||||
const { wrapText } = require('../../util/Canvas');
|
||||
const characters = require('../../assets/json/undertale');
|
||||
|
||||
module.exports = class UndertaleCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'undertale',
|
||||
aliases: [
|
||||
'ut',
|
||||
'undertale-dialogue',
|
||||
'ut-dialogue',
|
||||
'undertale-dialog',
|
||||
'ut-dialog',
|
||||
'undertale-quote',
|
||||
'ut-quote'
|
||||
],
|
||||
group: 'edit-image',
|
||||
memberName: 'undertale',
|
||||
description: 'Sends a text box from Undertale with the quote and character of your choice.',
|
||||
details: `**Characters:** ${characters.join(', ')}`,
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'UNDERTALE',
|
||||
url: 'https://undertale.com/',
|
||||
reason: 'Original Game'
|
||||
},
|
||||
{
|
||||
name: 'Demirramon',
|
||||
url: 'https://www.demirramon.com/',
|
||||
reason: 'Images',
|
||||
reasonURL: 'https://www.demirramon.com/en/generators/undertale_text_box_generator'
|
||||
},
|
||||
{
|
||||
name: 'Carter Sande',
|
||||
url: 'https://gitlab.com/cartr',
|
||||
reason: 'DeterminationMono, UndertaleSans, and UndertalePapyrus Fonts',
|
||||
reasonURL: 'https://gitlab.com/cartr/undertale-fonts/tree/master'
|
||||
},
|
||||
{
|
||||
name: 'Sigmath Bits',
|
||||
url: 'https://fontstruct.com/fontstructors/1280718/sigmath6',
|
||||
reason: 'Pixelated Wingdings Font',
|
||||
reasonURL: 'https://fontstruct.com/fontstructions/show/1218140/pixelated-wingdings'
|
||||
},
|
||||
{
|
||||
name: 'EarthBound Central',
|
||||
url: 'https://earthboundcentral.com/',
|
||||
reason: 'Apple Kid Font',
|
||||
reasonURL: 'https://earthboundcentral.com/2009/11/ultimate-earthbound-font-pack/'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'character',
|
||||
prompt: `What character do you want to use? Either ${list(characters, 'or')}.`,
|
||||
type: 'string',
|
||||
oneOf: characters,
|
||||
parse: character => character.toLowerCase()
|
||||
},
|
||||
{
|
||||
key: 'quote',
|
||||
prompt: 'What should the character say?',
|
||||
type: 'string',
|
||||
max: 250
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { character, quote }) {
|
||||
const base = await loadImage(
|
||||
path.join(__dirname, '..', '..', 'assets', 'images', 'undertale', `${character}.png`)
|
||||
);
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
let font = 'DeterminationMono.ttf';
|
||||
let space = -3;
|
||||
switch (character) {
|
||||
case 'sans':
|
||||
font = 'UndertaleSans.ttf';
|
||||
quote = quote.toLowerCase();
|
||||
space = -4;
|
||||
break;
|
||||
case 'papyrus':
|
||||
font = 'UndertalePapyrus.ttf';
|
||||
quote = quote.toUpperCase();
|
||||
space = -5;
|
||||
break;
|
||||
case 'napstablook':
|
||||
quote = quote.toLowerCase();
|
||||
break;
|
||||
case 'gaster':
|
||||
font = 'pixelated-wingdings.ttf';
|
||||
space = -4;
|
||||
break;
|
||||
case 'ness':
|
||||
font = 'apple_kid.ttf';
|
||||
space = -2;
|
||||
break;
|
||||
case 'temmie':
|
||||
quote = this.client.registry.commands.get('temmie').temmize(quote);
|
||||
break;
|
||||
}
|
||||
ctx.font = this.client.fonts.get(font).toCanvasString(32);
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.textBaseline = 'top';
|
||||
const text = await wrapText(ctx, quote, 385);
|
||||
const lines = text.length > 3 ? 3 : text.length;
|
||||
for (let i = 0; i < lines; i++) {
|
||||
ctx.fillText(text[i], 174, 22 + (22 * i) + (22 * i) + (space * i));
|
||||
}
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: `undertale-${character}.png` }] });
|
||||
}
|
||||
};
|
||||
@@ -1,69 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const path = require('path');
|
||||
const { wrapText } = require('../../util/Canvas');
|
||||
|
||||
module.exports = class ZeroDialogueCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'zero-dialogue',
|
||||
aliases: [
|
||||
'megaman-zero-dialogue',
|
||||
'mm-zero-dialogue',
|
||||
'zero-dialog',
|
||||
'megaman-zero-dialog',
|
||||
'mm-zero-dialog',
|
||||
'zero-quote',
|
||||
'megaman-zero-quote',
|
||||
'mm-zero-quote',
|
||||
'zero',
|
||||
'megaman-zero',
|
||||
'mm-zero'
|
||||
],
|
||||
group: 'edit-image',
|
||||
memberName: 'zero-dialogue',
|
||||
description: 'Sends a text box from Megaman Zero with the quote of your choice.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Capcom',
|
||||
url: 'http://www.capcom.com/us/',
|
||||
reason: 'Image, Original "Megaman Zero" Game',
|
||||
reasonURL: 'http://megaman.capcom.com/'
|
||||
},
|
||||
{
|
||||
name: 'Megadreamer',
|
||||
url: 'https://www.deviantart.com/megadreamer',
|
||||
reason: 'Megaman Zero Dialogue Font',
|
||||
reasonURL: 'https://www.deviantart.com/megadreamer/art/Megaman-Zero-dialog-font-513708688'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'quote',
|
||||
prompt: 'What should Zero say?',
|
||||
type: 'string',
|
||||
max: 50
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { quote }) {
|
||||
const base = await loadImage(path.join(__dirname, '..', '..', 'assets', 'images', 'zero-dialogue.png'));
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
ctx.font = this.client.fonts.get('megaman_zero_dialog.ttf').toCanvasString(42);
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.textBaseline = 'top';
|
||||
let text = await wrapText(ctx, quote, 425);
|
||||
text = text.length > 2 ? `${text.slice(0, 2).join('\n')}...` : text.join('\n');
|
||||
ctx.fillText(text, 8, 8);
|
||||
return msg.say({ files: [{ attachment: canvas.toBuffer(), name: 'zero-dialogue.png' }] });
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user