diff --git a/.gitignore b/.gitignore
index 63ad009..1633564 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,9 @@ node_modules/
config.json
auth.json
test.js
-/.idea/
\ No newline at end of file
+/.idea/
+
+api/**/*
+api/
+.idea/**/*
+/man.js
\ No newline at end of file
diff --git a/.idea/Natsuki.iml b/.idea/Natsuki.iml
index d007bc1..0c1c525 100644
--- a/.idea/Natsuki.iml
+++ b/.idea/Natsuki.iml
@@ -5,6 +5,8 @@
+
+
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 8cf679b..cc3f0f3 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,15 +4,24 @@
-
+
+
-
+
+
+
+
+
@@ -24,6 +33,9 @@
+
+
+
@@ -47,22 +59,87 @@
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -79,6 +156,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
1640148826800
@@ -108,7 +206,119 @@
1640214318896
-
+
+ 1642539309483
+
+
+
+ 1642539309483
+
+
+ 1642551387709
+
+
+
+ 1642551387709
+
+
+ 1642551629134
+
+
+
+ 1642551629134
+
+
+ 1642560099716
+
+
+
+ 1642560099716
+
+
+ 1642707545761
+
+
+
+ 1642707545761
+
+
+ 1642708137867
+
+
+
+ 1642708137867
+
+
+ 1644449776897
+
+
+
+ 1644449776897
+
+
+ 1644454927810
+
+
+
+ 1644454927810
+
+
+ 1644454968528
+
+
+
+ 1644454968528
+
+
+ 1645501776749
+
+
+
+ 1645501776749
+
+
+ 1645649572924
+
+
+
+ 1645649572924
+
+
+ 1645650089290
+
+
+
+ 1645650089290
+
+
+ 1645660453432
+
+
+
+ 1645660453432
+
+
+ 1645679244004
+
+
+
+ 1645679244004
+
+
+ 1647787801198
+
+
+
+ 1647787801198
+
+
+ 1647788334624
+
+
+
+ 1647788334624
+
+
@@ -132,6 +342,22 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bot.js b/bot.js
index 2edc42d..f9a100d 100644
--- a/bot.js
+++ b/bot.js
@@ -1,19 +1,20 @@
const Discord = require('discord.js');
-
+const spinnies = require('dreidels');
+const gs = require('gradient-string');
const chalk = require('chalk');
const ora = require('ora');
const mongoose = require('mongoose');
const readline = require('readline');
-const {SlashCommand} = require('./util/slash');
const {SlashManager} = require('./util/slashmanager');
-const {SlashCommandBuilder} = require('@discordjs/builders');
const {Tag} = require('./util/tag');
const {TagFilter} = require('./util/tagfilter');
+const wait = require('./util/wait');
const flags = Discord.Intents.FLAGS;
let fl = []; Object.keys(flags).forEach(flag => fl.push(flags[flag]));
let client = new Discord.Client({intents: fl, partials: ["CHANNEL", "REACTION", "MESSAGE"]});
+let botReadyResolver;
client.misc = {
savers: ['497598953206841375', '480535078150340609', '468903364533420074'],
@@ -34,8 +35,12 @@ client.misc = {
hasLevelRoles: [],
disabledChannels: new Map()
},
- chests: [],
chestsTimeout: new Map(),
+ chests: {
+ enabled: [],
+ timeout: new Map(),
+ waiting: new Map()
+ },
monit: {},
monitEnabled: [],
inVC: [],
@@ -47,7 +52,13 @@ client.misc = {
animeID: new Discord.Collection(),
charsNum: 0,
charsLove: new Discord.Collection(),
- monners: {}
+ monners: {},
+ lastMonners: {},
+ monnersNames: new Map(),
+ spin: new spinnies(),
+ rp: new Map(),
+ returnToSleep: new Map(),
+ marriageRequests: new Discord.Collection()
},
loggers: {},
rl: readline.createInterface({input: process.stdin, output: process.stdout}),
@@ -57,14 +68,36 @@ client.misc = {
dev: false,
logs: 'normal',
lightstartup: false,
- ignorecmds: []
- }
+ ignorecmds: [],
+ gradients: false,
+ spinners: false
+ },
+ botFinished: new Promise(r => {botReadyResolver = r;}),
+ fullyReady: false
};
-//const config = require('./config.js');
-const auth = require('./auth.json');
-//client.config = config;
+
+
+let waitAmount = 1000 * 10;
+function testConnection() {
+ return new Promise(async r => {
+ require('dns').lookup('www.google.com', async e => {
+ if (e) {
+ await wait(waitAmount);
+ waitAmount *= 2;
+ await testConnection();
+ r();
+ }
+ else {r();}
+ })
+ });
+}
+
+
+
+
+const auth = require('./auth.json');
async function init() {
const cliargs = new TagFilter([
@@ -72,7 +105,9 @@ async function init() {
new Tag(['dev', 'd', 'development', 'test'], 'dev', 'toggle'),
new Tag(['logs', 'l', 'loglevel', 'll'], 'logs', 'append'),
new Tag(['lightstart', 'lightstartup', 'ls'], 'lightstartup', 'toggle'),
- new Tag(['i', 'ignore', 'icmd', 'ignorecmd'], 'ignorecmds', 'listAppend')
+ new Tag(['i', 'ignore', 'icmd', 'ignorecmd'], 'ignorecmds', 'listAppend'),
+ new Tag(['g', 'gradient', 'gradients'], 'gradients', 'toggle'),
+ new Tag(['s', 'sp', 'spinners', 'spin'], 'spinners', 'toggle')
]).test(process.argv.slice(2).join(" "));
if (Object.keys(cliargs).length) {
@@ -93,10 +128,6 @@ async function init() {
client.misc.startupNoConnect = new Date();
client.config = auth;
- client.slash = new SlashManager(client).setTestServer('691122844339404800').importCommands().init();
- client.slash.register();
- client = client.slash.client;
-
let mloginsp = ora(chalk.magentaBright('Connecting to Mongo client...')).start();
let pmcc = new Date().getTime();
const config = client.config;
@@ -116,25 +147,56 @@ async function init() {
mloginsp.stop(); mloginsp.clear();
}
+ client.developers = ["330547934951112705", "673477059904929802"];
+
+ client.utils = {};
+ client.utils.s = num => num === 1 ? '' : 's';
+ client.utils.as = (num, text) => `${text}${client.utils.s(num)}`;
+ client.utils.an = (text, caps) => `${caps ? 'A' : 'a'}${['a', 'e', 'i', 'o', 'u'].includes(text.toLowerCase().trim().slice(0, 1)) ? 'n' : ''} ${text}`;
+ client.utils.c = (text, a=true) => `${text.slice(0, 1).toUpperCase()}${a ? text.slice(1).toLowerCase() : text.slice(1)}`;
+ client.utils.ca = (text, a=true) => text.split(/\s+/gm).map(t => client.utils.c(t, a)).join(" ");
+ client.utils.sm = (mpr, ago=true) => `${mpr.years ? `${mpr.years} year${client.utils.s(mpr.years)} ` : ''}${mpr.months ? `${mpr.months} month${client.utils.s(mpr.months)} ` : ''}${mpr.days} day${client.utils.s(mpr.days)}${ago ? ' ago' : ''}`;
+ client.utils.p = (text) => text.endsWith('s') ? "'" : "'s";
+ client.utils.ps = (text) => `${text}${client.utils.p(text)}`;
+
['commands', 'aliases', 'executables'].forEach(x => client[x] = new Discord.Collection());
client.responses = {triggers: [], commands: new Discord.Collection()};
+ let iters = ['command', 'event', 'response'];
+ if (client.misc.config.spinners) {
+ console.log('');
+ client.misc.cache.spinLog = [];
+ iters.map(i => `Loading ${i.slice(0, 1).toUpperCase()}${i.slice(1)}s`)
+ .map(i => client.misc.config.gradients ? gs.instagram(i) : chalk.blue(i))
+ .forEach((i, ind) => client.misc.cache.spin.add(iters[ind], {text: i}));
+ }
- ['command', 'event', 'response'].forEach(x => require(`./handle/${x}`)(client));
- if (!client.misc.config.nocli) {require('./handle/console')(client);}
+ for (let i = 0; i < iters.length; i++) {let x = iters[i]; await require(`./handle/${x}`)(client);}
+ const spl = client.misc.config.spinners ? (i) => client.misc.cache.spinLog.push(i) : (i) => console.log(i);
+ spl(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Getting Slash Commands...')}\n`);
+ client.slash = new SlashManager(client)
+ .setTestServer('691122844339404800')
+ .importCommands(false, undefined, (cmd) => spl(`${chalk.gray('[LOAD]')} >> ${chalk.blueBright('Loaded Slash Command')} ${chalk.white(cmd.name)}`))
+ .init();
+ if (client.misc.config.dev) {await client.slash.devRegister();}
+ else {await client.slash.register();}
+ client = client.slash.client;
+ spl(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Loaded all Slash Commands')}`);
- client.developers = ["330547934951112705", "673477059904929802"];
- client.utils = {};
+ if (client.misc.config.spinners) {
+ client.misc.cache.spinLog.forEach(log => console.log(log));
+ }
+ if (!client.misc.config.nocli) {require('./handle/console')(client);}
client.utils.logch = async () => {return client.guilds.cache.get('762707532417335296').channels.cache.get('762732961753595915');};
- client.utils.s = num => num === 1 ? '' : 's';
- client.utils.as = (num, text) => `${text}${client.utils.s(num)}`;
- client.utils.an = (text, caps) => `${caps ? 'A' : 'a'}${['a', 'e', 'i', 'o'].includes(text.toLowerCase().trim().slice(0, 1)) ? 'n' : ''} ${text}`;
client.guildconfig = {};
client.guildconfig.prefixes = new Map();
client.guildconfig.logs = new Map();
+ botReadyResolver(0);
+
await require('./util/wait')(5000);
if (!client.misc.readied) {client.misc.forcedReady = true; await require('./events/ready')(client);}
}
-init().then(() => {});
\ No newline at end of file
+
+testConnection().then(() => init());
\ No newline at end of file
diff --git a/commands/anime/anime.js b/commands/anime/anime.js
index 772c3ac..110a504 100644
--- a/commands/anime/anime.js
+++ b/commands/anime/anime.js
@@ -35,7 +35,6 @@ module.exports = {
queue = true;
}
options = new TagFilter([
- new Tag(['ask', 'question'], 'ask', 'toggle'),
new Tag(['title', 't', 'name', 'n'], 'name', 'append'),
new Tag(['japname', 'japanesename', 'jn'], 'japname', 'append'),
new Tag(['description', 'desc', 'd', 'plot', 'p'], 'plot', 'append'),
@@ -78,7 +77,7 @@ module.exports = {
dmch = mesg.channel;
options.name = await ask(mesg, "What is the anime's name? Make sure to use proper capitalization and spelling. This applies to the rest of the questions I'll ask you.", 60000, true); if (!options.name) {return;}
- if (options.name.length > 75) {clearDM(); return dmch.send("The anime name can't be more than 75 characters!");}
+ if (options.name.length > (queue ? 75 : 250)) {clearDM(); return dmch.send(`The anime name can't be more than ${queue ? 75 : 250} characters!`);}
options.plot = await ask(mesg, "How would you describe the anime? Give a very brief description of things like its plot, main characters, and setting.", 240000, true); if (!options.plot) {return clearDM();}
if (options.plot.length > 500) {clearDM(); return dmch.send("Oi! I said give a \"very brief\" description of the anime!");}
@@ -96,14 +95,13 @@ module.exports = {
options.publishers = options.publishers.split(/,\s+/gm);
if (options.publishers.length > 5) {clearDM(); return dmch.send("No way there were actually that many publishers...");}
- options.airStartDate = await ask(mesg, "When did the anime start? Please format this as \"Month Day, Year\" - e.g. January 1, 2021", 120000, true); if (!options.airStartDate) {return clearDM();}
- options.airEndDate = await ask(mesg, "When did the anime end? If the anime never ended, you can say \"N/A\"", 120000, true); if (!options.airEndDate) {return clearDM();}
- options.lastUpdate = await ask(mesg, "When was the last time a new episode was released for the anime?", 120000, true); if (!options.lastUpdate) {return clearDM();}
-
options.isComplete = await ask(mesg, "Is the anime completed? (If the most recent season has finished, you may only say \"no\" if the next season is *confirmed* by the *studio or publishers* or the next season is in the works.", 60000, true); if (!options.isComplete) {return clearDM();}
if (!['y', 'yes', 'ye', 'n', 'no'].includes(options.isComplete.trim().toLowerCase())) {clearDM(); return dmch.send("You must specify yes or no! Please try again.");}
options.isComplete = ['y', 'yes', 'ye'].includes(options.isComplete.trim().toLowerCase());
+ //options.airStartDate = await ask(mesg, "When did the anime start? Please format this as \"Month Day, Year\" - e.g. January 1, 2021", 120000, true); if (!options.airStartDate) {return clearDM();}
+ //if (options.isComplete) {options.airEndDate = await ask(mesg, "When did the anime end?", 120000, true); if (!options.airEndDate) {return clearDM();}}
+
options.seasons = await ask(mesg, "How many seasons does the anime have? Please don't include spinoffs. (Gun Gale Online spinoff doesn't count as a Sword Art Online season.)", 120000, true); if (!options.seasons) {return clearDM();}
if (isNaN(options.seasons) || Number(options.seasons < 1)) {clearDM(); return dmch.send("You either didn't give a number, or it was < 1.");}
options.seasons = Number(options.seasons);
@@ -154,11 +152,11 @@ module.exports = {
.addField('Info', `**Name:** ${options.name}\n**Japanese Name:** ${options.japname}\n\n**Publishers:** ${foptions.publishers}\n**Studios:** ${foptions.studios}`)
.addField('Description', options.plot)
.addField('Length', `**# of Seasons:** ${options.seasons}\n**# of Episodes:** ${options.episodes}`)
- .addField('Airing', `**Began:** ${options.airStartDate}\n**Ended:** ${options.isComplete ? options.airEndDate : 'This anime is still airing!'}`)
- .addField('Other', `**Genre(s):** ${foptions.genres}\n**Tags:** ${foptions.tags}\n**Characters:** ${foptions.characters}\n**Stream this at:** ${foptions.streamAt}`)
+ //.addField('Airing', `**Began:** ${options.airStartDate}\n**Ended:** ${options.isComplete ? options.airEndDate : 'This anime is still airing!'}`)
+ .addField('Other', `**Genre(s):** ${foptions.genres}\n**Characters:** ${foptions.characters}\n**Stream this at:** ${foptions.streamAt}`)
.setColor("c375f0")
.setImage(options.thumbnail)
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp();
try {
am = await dmch.send({embeds: [amEmbed]});
@@ -177,8 +175,8 @@ module.exports = {
client.misc.cache.animeID.set(options.id, options.name);
}
else {amEmbed.addField("ID", options.id);}
- amEmbed.setAuthor({name: !queue ? "Anime Added" : "Anime Submitted", iconURL: message.author.avatarURL()});
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({embeds: [amEmbed]}));
+ amEmbed.setAuthor({name: !queue ? "Anime Added" : "Anime Submitted", iconURL: message.author.displayAvatarURL()});
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177823630762014').send({embeds: [amEmbed]}));
if (!queue) {options.queued = false;}
await new AniData(options).save();
return message.author.send(`Your anime has been ${!queue ? "added" : "submitted"}`);
@@ -191,6 +189,75 @@ module.exports = {
return;
}
+ if (['e', 'edit'].includes(args[0].toLowerCase())) {
+ args.shift();
+ let tu = await UserData.findOne({uid: message.author.id});
+ if (!tu || !tu.staff) {return await message.channel.send("Since you aren't a Natsuki Staff member, you can't edit anime.");}
+ if (!args.length) {return message.channel.send("You have to provide tags to edit anime with.");}
+ options = new TagFilter([
+ new Tag(['title', 't', 'name', 'n'], 'name', 'append'),
+ new Tag(['rn', 'rename'], 'rename', 'append'),
+ new Tag(['japname', 'japanesename', 'jn'], 'japname', 'append'),
+ new Tag(['description', 'desc', 'd', 'plot', 'p'], 'plot', 'append'),
+ new Tag(['pub', 'pubs', 'publishers', 'publisher', 'pb'], 'publishers', 'listAppend'),
+ new Tag(['stud', 's', 'studio', 'studs', 'studios'], 'studios', 'listAppend'),
+ new Tag(['began', 'airstart', 'as'], 'airStartDate', 'append'),
+ new Tag(['ended', 'airend', 'ae'], 'airEndDate', 'append'),
+ new Tag(['iscomplete', 'completed', 'ic'], 'isComplete', 'toggle'),
+ new Tag(['seasons', 'sns'], 'seasons', 'append'),
+ new Tag(['episodes', 'es'], 'episodes', 'append'),
+ new Tag(['genres', 'g'], 'genres', 'listAppend'),
+ new Tag(['tags', 'ta', 'tgs', 'tg', 'tag'], 'tags', 'listAppend'),
+ new Tag(['streams', 'streamat', 'sa'], 'streamAt', 'listAppend'),
+ new Tag(['img', 'thumb', 'thumbnail', 'image'], 'thumbnail', 'append')
+ ]).test(args.join(' '));
+ if (!options.name) {
+ let tempani = await ask(message, "What anime would you like to edit?", 60000, false, true);
+ if (!tempani) {return;}
+ options.name = tempani.split(/\s+/g);
+ }
+ let asr = await ans(message, client, options.name.toLowerCase(), -700, 0);
+ let fn;
+ if (asr === 0) {
+ return message.channel.send("That search returned no results! Try again?");
+ } else if (asr instanceof Pagination) {
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
+ await asr.message.react('✅');
+ let noticeDel = await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
+ let arc;
+ try {arc = await asr.message.awaitReactions({filter: (r) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
+ catch {return message.reply("Looks like you didn't find the anime you were looking for.");}
+ collected = arc.first().emoji.name;
+ if (collected === '✅') {
+ fn = client.misc.cache.anime.get(asr.getCurrentPage().title.trim());
+ await asr.stop();
+ await asr.message.delete().catch(() => {});
+ await noticeDel.delete().catch(() => {});
+ }
+ else {return message.reply("Looks like you didn't find the anime you were looking for.");}
+ } else {fn = asr.id;}
+ let ani = await AniData.findOne({id: fn});
+ if (!ani) {return message.channel.send("\\*Head scratching* that anime seems to have vanished into thin air. Try again or go yell at my devs.");}
+ Object.keys(options).forEach(o => {if (![undefined, null].includes(options[o]) && o !== 'name') {
+ if (o === 'japname') {
+ client.misc.cache.anime.delete(ani.japname);
+ client.misc.cache.anime.set(options.japname, ani.id);
+ }
+ if (Array.isArray(options[o])) {options[o].forEach(i => ani[o].push(i));}
+ else {ani[o] = options[o];}
+ ani.markModified(o);
+ if (o === 'rename') {
+ delete ani.rename;
+ client.misc.cache.animeID.set(ani.id, options.rename);
+ client.misc.cache.anime.delete(ani.name);
+ client.misc.cache.anime.set(options.rename, ani.id);
+ ani.name = options.rename;
+ }
+ }});
+ ani.save();
+ return message.channel.send('Anime updated.');
+ }
+
if (['s', 'search'].includes(args[0].trim().toLowerCase())) {
args.shift();
if (!args[0]) {
@@ -202,7 +269,7 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
} else {
await message.channel.send({embeds: [asr.embed]});
}
@@ -220,7 +287,7 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
} else {
await message.channel.send({embeds: [asr.embed]});
}
@@ -238,6 +305,35 @@ module.exports = {
.catch(() => {return message.reply("It seems that submission wasn't deleted for some reason. \*insert head scratching*");});
}
+ if (['accept', 'approve'].includes(args[0].toLowerCase())) {
+ let tu = await UserData.findOne({uid: message.author.id});
+ if (!tu || !tu.staff) {await message.channel.send("Since you aren't a Natsuki Staff member, you can't accept anime submissions!");}
+ let tr = await AniData.findOne({id: args[1].toLowerCase()});
+ if (!tr) {return message.reply("That anime submission doesn't seem to exist!");}
+ if (tr.queued !== true) {return message.reply("That anime was already accepted, so you can't accept it again...");}
+ tr.queued = false;
+ return await tr.save()
+ .then(() => {
+ client.misc.cache.anime.set(ani.japname.normalize("NFD").replace(/[\u0300-\u036f]/g, ""), ani.id);
+ client.misc.cache.anime.set(ani.name.normalize("NFD").replace(/[\u0300-\u036f]/g, ""), ani.id);
+ if (ani.altNames) {ani.altNames.forEach(altName => client.misc.cache.anime.set(altName, ani.id));}
+ client.misc.cache.animeID.set(ani.id, ani.name.normalize("NFD").replace(/[\u0300-\u036f]/g, ""));
+ client.misc.cache.animeLove.set(ani.id, ani.watchers);
+ client.misc.cache.animeNum++;
+ client.guilds.cache.get('762707532417335296').channels.cache.get('932177823630762014').send({embeds: [new Discord.MessageEmbed()
+ .setTitle(`Anime Accepted -> ${tr.name}`)
+ .setAuthor({name: 'Anime Approved', iconURL: message.author.displayAvatarURL()})
+ .setThumbnail(tr.thumbnail)
+ .setDescription(`${tr.name} has been approved, and is now available to all Natsuki users.`)
+ .setColor('c375f0')
+ .setFooter({text: "Natsuki"})
+ .setTimestamp()
+ ]}).catch(() => {});
+ return message.channel.send("I've accepted that submission.");
+ })
+ .catch(() => {return message.reply("It seems that submission wasn't accepted for some reason. \*insert head scratching*");});
+ }
+
if (['r', 'rand', 'random', 'any'].includes(args[0].toLowerCase())) {
let asr = await ans(message, client, client.misc.cache.anime.random(), -100000);
return await message.channel.send({embeds: [asr.embed]});
@@ -245,6 +341,36 @@ module.exports = {
if (['w', 'watched'].includes(args[0].toLowerCase())) {
args.shift();
+ if (args[0] && ['v', 'view'].includes(args[0].toLowerCase())) {
+ if (mention) {args.shift();}
+ let user = mention || message.author;
+ let af = await AF.findOne({uid: user.id});
+ if (!af || !af.watched.length) {return message.channel.send(`${user.id === message.author.id ? "You haven't" : "That person hasn't"} watched any anime.`);}
+ let pages = [];
+ let pl = (Math.floor(af.watched.length / 10) + 1);
+ for (let i = 0; i < pl; i++) {
+ let s = '';
+ for (let x = 0; x < 10; x++) {
+ if (!af.watched[(i * 10) + x]) {break;}
+ s += `**${x + (i * 10) + 1}.** ${client.misc.cache.animeID.get(af.watched[(i * 10) + x])}\n`;
+ }
+ pages.push(new Discord.MessageEmbed()
+ .setAuthor({
+ name: message.guild ? message.guild.members.cache.get(user.id).displayName : user.username,
+ iconURL: message.guild ? message.guild.members.cache.get(user.id).displayAvatarURL({dynamic: true}) : user.displayAvatarURL({dynamic: true})
+ })
+ .setTitle("Finished Anime List")
+ .setDescription(s)
+ .setColor('c375f0')
+ .setTimestamp()
+ );
+ }
+ if (pages.length > 1) {
+ let pag = new Pagination(message.channel, pages, message, client, true);
+ return await pag.start({user: message.author.id, time: 60000});
+ } else {return message.channel.send({embeds: [pages[0].setFooter({text: "Natsuki"})]});}
+ }
+
if (!args[0]) {
let tempchar = await ask(message, "What anime would you like to add to your finished list?", 60000, false, true);
if (!tempchar) {return;}
@@ -255,35 +381,47 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
- await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
+ let noticeDel = await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
let arc;
try {arc = await asr.message.awaitReactions({filter: (r) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
catch {return message.reply("Looks like you didn't find the anime you were looking for.");}
collected = arc.first().emoji.name;
if (collected === '✅') {
fn = client.misc.cache.anime.get(asr.getCurrentPage().title.trim());
- asr.stop();
+ await asr.stop();
+ await asr.message.delete().catch(() => {});
+ await noticeDel.delete().catch(() => {});
}
else {return message.reply("Looks like you didn't find the anime you were looking for.");}
} else {
- await message.channel.send({embeds: [asr.embed]});
- let conf = await ask(message, "Is this the anime you meant?", 60000);
+ let preConfEmbed = await message.channel.send({embeds: [asr.embed]});
+ let conf = await ask(message, "Is this the anime you meant?", 60000, undefined, undefined, true);
if (!['y', 'yes', 'ye', 'n', 'no'].includes(conf.trim().toLowerCase())) {clearDM(); return dmch.send("You must specify yes or no! Please try again.");}
conf = ['y', 'yes', 'ye'].includes(conf.trim().toLowerCase());
+ preConfEmbed.delete().catch(() => {});
if (!conf) {return message.channel.send("Well, I've got nothing, then. If that doesn't match the anime you're looking for then I would try again with a more narrow search.");}
- fn = asr.id;}
+ fn = asr.id;
+ }
let af = await AF.findOne({uid: message.author.id}) || new AF({uid: message.author.id});
if (af.watched.includes(fn)) {return message.channel.send("Looks like that anime is already on your finished list!");}
let tfc = await AniData.findOne({id: fn});
tfc.watchers += 1;
tfc.markModified('watchers');
- tfc.save();
af.watched.push(fn);
af.markModified('watched');
+ let dw = false;
+ if (af.toWatch.includes(fn)) {
+ af.toWatch.splice(af.toWatch.indexOf(fn), 1);
+ af.markModified('toWatch');
+ tfc.listed--;
+ tfc.save();
+ dw = true;
+ }
af.save();
- return message.channel.send(`I've added **${tfc.name}** to your list of finished animes!`);
+ tfc.save();
+ return message.channel.send(`I've added **${tfc.name}** to your list of finished animes!${dw ? " I've also removed it from your watch list for you :p" : ''}`);
}
if (['nn', 'nickname', 'altname', 'nick', 'an'].includes(args[0].toLowerCase())) {
@@ -298,7 +436,7 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
let arc;
@@ -328,10 +466,10 @@ module.exports = {
ch.save();
client.misc.cache.anime.set(nn, ch.id);
}
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177814638186516').send({
embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`New Anime Alt Name ${queue ? "Submitted" : "Added"}`)
.setDescription(`For **${ch.name}** | \`${ch.id}\``)
.addField("Name", nn)
@@ -361,7 +499,7 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
let arc;
@@ -419,10 +557,10 @@ module.exports = {
ch.markModified('images');
ch.save();
}
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177850239422494').send({
embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`New Anime Image ${queue ? "Submitted" : "Added"}`)
.setDescription(`For **${ch.name}**`)
.setThumbnail(ch.thumbnail)
@@ -439,10 +577,10 @@ module.exports = {
ch.markModified('images');
ch.save();
}
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177850239422494').send({
embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`New Anime Images ${queue ? "Submitted" : "Added"}`)
.setDescription(`For **${ch.name}**`)
.addField("Images", images.map(img => `${img}\n`).join(""))
@@ -456,5 +594,68 @@ module.exports = {
}
}
}
+
+ if (['l', 'love', 'favorite', 'fav'].includes(args[0].toLowerCase())) {
+ args.shift();
+ if (!args[0]) {
+ let tempchar = await ask(message, "What anime would you like to add to your favorites list?", 60000, false, true);
+ if (!tempchar) {return;}
+ args = tempchar.split(/\s+/g);
+ }
+ let asr = await ans(message, client, args.join(" ").trim().toLowerCase(), -700, 0);
+ let fn;
+ if (asr === 0) {
+ return message.channel.send("That search returned no results! Try again?");
+ } else if (asr instanceof Pagination) {
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
+ await asr.message.react('✅');
+ let noticeDel = await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
+ let arc;
+ try {arc = await asr.message.awaitReactions({filter: (r) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
+ catch {return message.reply("Looks like you didn't find the anime you were looking for.");}
+ collected = arc.first().emoji.name;
+ if (collected === '✅') {
+ fn = client.misc.cache.chars.get(asr.getCurrentPage().title.trim());
+ await asr.stop();
+ await asr.message.delete().catch(() => {});
+ await noticeDel.delete().catch(() => {});
+ }
+ else {return message.reply("Looks like you didn't find the anime you were looking for.");}
+ } else {
+ let preConfEmbed = await message.channel.send({embeds: [asr.embed]});
+ let conf = await ask(message, "Is this the anime you meant?", 60000, undefined, undefined, true);
+ if (!['y', 'yes', 'ye', 'n', 'no'].includes(conf.trim().toLowerCase())) {clearDM(); return dmch.send("You must specify yes or no! Please try again.");}
+ conf = ['y', 'yes', 'ye'].includes(conf.trim().toLowerCase());
+ preConfEmbed.delete().catch(() => {});
+ if (!conf) {return message.channel.send("Well, I've got nothing, then. If that doesn't match the anime you're looking for then I would try again with a more narrow search.");}
+ fn = asr.id;
+ }
+ let cf = await AF.findOne({uid: message.author.id}) || new AF({uid: message.author.id});
+ if (cf.liked.includes(fn)) {return message.channel.send("Looks like that anime is already on your loved list!");}
+ let tfc = await AniData.findOne({id: fn});
+ tfc.liked += 1;
+ tfc.save();
+ cf.liked.push(fn);
+ cf.markModified('liked');
+ cf.save();
+ return message.channel.send(`I've added **${tfc.name}** to your loved/favorited anime list!`);
+ }
+
+ if (['loved', 'favorites', 'favs', 'ls', 'fs'].includes(args[0].toLowerCase())) {
+ let cf = await AF.findOne({uid: mention ? mention.id : message.author.id});
+ if (!cf || !cf.liked.length) {return message.channel.send(`Looks like ${mention ? 'they' : 'you'} haven't favorited any anime!`);}
+ let chars = cf.liked;
+ chars = chars.map(tc => client.misc.cache.animeID.get(tc));
+ let n = mention ? message.guild ? message.mentions.members.first().displayName : message.mentions.users.first().username : message.guild ? message.member.displayName : message.author.username;
+ return message.channel.send({embeds: [
+ new Discord.MessageEmbed()
+ .setAuthor({name: `${n}${n.endsWith('s') ? '' : "'s"} Favorited Anime`, iconURL: mention ? mention.displayAvatarURL() : message.author.displayAvatarURL()})
+ .setDescription(`**${chars.length} anime favorited**\n\n${chars.join(", ")}`)
+ .setColor('c375f0')
+ .setFooter({text: "Natsuki"})
+ .setTimestamp()
+ ]});
+ }
+
}
};
diff --git a/commands/anime/animeimage.js b/commands/anime/animeimage.js
index 2a6e022..146cbe5 100644
--- a/commands/anime/animeimage.js
+++ b/commands/anime/animeimage.js
@@ -37,7 +37,7 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
let arc;
@@ -95,10 +95,10 @@ module.exports = {
ch.markModified('images');
ch.save();
}
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177850239422494').send({
embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`New Anime Image ${queue ? "Submitted" : "Added"}`)
.setDescription(`For **${ch.name}**`)
.setThumbnail(ch.thumbnail)
@@ -115,10 +115,10 @@ module.exports = {
ch.markModified('images');
ch.save();
}
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177850239422494').send({
embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`New Anime Images ${queue ? "Submitted" : "Added"}`)
.setDescription(`For **${ch.name}**`)
.addField("Images", images.map(img => `${img}\n`).join(""))
diff --git a/commands/anime/animenick.js b/commands/anime/animenick.js
index 2d4b0e8..b7261a3 100644
--- a/commands/anime/animenick.js
+++ b/commands/anime/animenick.js
@@ -32,7 +32,7 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
let arc;
@@ -62,10 +62,10 @@ module.exports = {
ch.save();
client.misc.cache.anime.set(nn, ch.id);
}
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177814638186516').send({
embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`New Anime Alt Name ${queue ? "Submitted" : "Added"}`)
.setDescription(`For **${ch.name}** | \`${ch.id}\``)
.addField("Name", nn)
diff --git a/commands/anime/char.js b/commands/anime/char.js
index e9cb2a2..e5398c3 100644
--- a/commands/anime/char.js
+++ b/commands/anime/char.js
@@ -39,7 +39,6 @@ module.exports = {
queue = true;
}
options = new TagFilter([
- new Tag(['ask', 'question'], 'ask', 'toggle'),
new Tag(['name', 'n'], 'name', 'append'),
new Tag(['description', 'desc', 'p', 'personality'], 'personality', 'append'),
new Tag(['anime', 'ani', 'a'], 'anime', 'append'),
@@ -47,20 +46,21 @@ module.exports = {
new Tag(['img', 'image', 'i'], 'images', 'listAppend'),
new Tag(['loveInterest', 'dating', 'married', 'li'], 'loveInterest', 'append'),
new Tag(['gender', 'g', 'sex'], 'gender', 'append'),
- new Tag(['nickname', 'nn', 'nick'], 'nicknames', 'listAppend')
+ new Tag(['nickname', 'nn', 'nick'], 'nicknames', 'listAppend'),
+ new Tag(['force', 'f'], 'force', 'toggle')
]).test(args.slice(1).join(' '));
if (Object.keys(options).length) {
if (message.attachments.size) {
if (options.thumbnail) {
if (!options.images) {options.images = [];}
- Array.from(message.attachments.keys()).forEach(i => options.images.push(i));
+ Array.from(message.attachments.keys()).forEach(i => options.images.push(message.attachments.get(i).url));
} else {
if (!options.images) {options.images = [];}
let att = Array.from(message.attachments.keys());
if (message.attachments.size > 1) {
for (let i = 1; i < att.length; i++) {
- options.images.push(message.attachments.get(att[i].url));
+ options.images.push(message.attachments.get(att[i]).url);
}
}
options.thumbnail = message.attachments.get(att[0]).url;
@@ -83,7 +83,7 @@ module.exports = {
let asr = await ans(message, client, options.anime.trim().toLowerCase(), undefined, 0);
if (asr === 0) {return message.channel.send("That search returned no results! Try remaking the character?");}
else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
let arc;
@@ -129,7 +129,7 @@ module.exports = {
fn = options.anime;
}
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
await dmch.send("React with :white_check_mark: when you've found the anime you want!");
let arc;
@@ -189,42 +189,144 @@ module.exports = {
.addField('Other', `**Anime**: ${forceAni ? options.anime : `${aniData.name} | ${aniData.japname} | \`${aniData.id}\``}\n\n**Gender**: ${options.gender}\n`)
.setColor("c375f0")
.setImage(options.thumbnail)
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp();
- try {
- am = await dmch.send({embeds: [amEmbed]});
- await am.react('👍').catch(() => {});
- await am.react('👎').catch(() => {});
- } catch {return dmch.send(":thinking: hmmm... something went wrong there. I might not have permissions to add reactions to messages, and this could be the issue.");}
- try {
- let rc = am.createReactionCollector({filter: (r, u) => ['👍', '👎'].includes(r.emoji.name) && u.id === message.author.id, max: 1, time: 60000});
- rc.on("collect", async r => {
- if (r.emoji.name !== '👎') {
- while (true) {options.id = require('../../util/makeid')(4); if (!await Char.findOne({id: options.id})) {break;}}
- if (!queue) {
- amEmbed.addField("Reviewed", `Reviewed and submitted by <@${message.author.id}>`);
- client.misc.cache.chars.set(options.name, options.id);
- client.misc.cache.charsID.set(options.id, options.name);
+ const addChar = async () => {
+ while (true) {options.id = require('../../util/makeid')(4); if (!await Char.findOne({id: options.id})) {break;}}
+ if (!queue) {
+ amEmbed.addField("Reviewed", `Reviewed and submitted by <@${message.author.id}>`);
+ client.misc.cache.chars.set(options.name, options.id);
+ client.misc.cache.charsID.set(options.id, options.name);
+ if (options.nicknames) {options.nicknames.forEach(nn => client.misc.cache.chars.set(nn, options.id));}
+ }
+ else {amEmbed.addField("ID", options.id);}
+ amEmbed.setAuthor({name: !queue ? "Character Added" : "Character Submitted", iconURL: message.author.displayAvatarURL()});
+ if (!queue) {options.queued = false;}
+ await new Char(options).save();
+ if (aniData) {
+ aniData.characters.push(options.id);
+ aniData.markModified('characters');
+ aniData.save();
+ }
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177797705781308').send({embeds: [amEmbed]}).catch(() => {})).catch(() => {});
+ if (options.images && options.images.length) {
+ let imagesEmbed = new Discord.MessageEmbed()
+ .setAuthor({name: message.author.username, iconURL: message.author.displayAvatarURL()})
+ .setTitle(`New Image${client.utils.s(options.images.length)} ${queue ? "Submitted" : "Added"}`)
+ .setDescription(`For **${options.name}** | \`${options.id}\` from ${client.misc.cache.animeID.get(options.anime)}`)
+ .setThumbnail(options.thumbnail)
+ .setImage(options.images[0])
+ .setColor('c375f0')
+ .setTimestamp()
+ .setFooter({text: "Natsuki"})
+ if (options.images.length > 1) {imagesEmbed.addField("Images", options.images.join("\n"));}
+ client.guilds.cache.get('762707532417335296').channels.cache.get('932177850239422494').send({
+ embeds: [imagesEmbed], content: queue ? '<@330547934951112705>' : undefined
+ }).catch(() => {});
+ }
+ if (am) {am.delete().catch(() => {});}
+ return dmch.send(`Your character${options.images.length ? `, and ${options.gender === 'Male' ? 'his' : options.gender === 'Female' ? 'her' : 'their'} ${options.images.length} ${client.utils.as(options.images.length, 'image')},` : ''} has been ${!queue ? "added" : "submitted"}`);
+ };
+ if (!options.force) {
+ try {
+ am = await dmch.send({embeds: [amEmbed]});
+ await am.react('👍').catch(() => {});
+ await am.react('👎').catch(() => {});
+ } catch {return dmch.send(":thinking: hmmm... something went wrong there. I might not have permissions to add reactions to messages, and this could be the issue.");}
+ try {
+ let rc = am.createReactionCollector({filter: (r, u) => ['👍', '👎'].includes(r.emoji.name) && u.id === message.author.id, max: 1, time: 60000});
+ rc.on("collect", async r => {
+ if (r.emoji.name !== '👎') {
+ await addChar();
+ } else {
+ return dmch.send("Oh, okay. I'll discard that then!");
}
- else {amEmbed.addField("ID", options.id);}
- amEmbed.setAuthor({name: !queue ? "Character Added" : "Character Submitted", iconURL: message.author.avatarURL()});
- if (!queue) {options.queued = false;}
- await new Char(options).save();
- if (aniData) {
- aniData.characters.push(options.id);
- aniData.markModified('characters');
- aniData.save();
+ });
+ rc.on("end", collected => {if (!collected.size) {return message.author.send("Looks like you ran out of time! Try again?");}});
+ } catch {return message.author.send("Hmm... there was some kind of error when I tried to submit that character. Try again, and if it keeps not working, then go yell at my devs!");}
+ } else {await addChar();}
+ return;
+ }
+
+ if (['e', 'edit'].includes(args[0].toLowerCase())) {
+ args.shift();
+ let tu = await UserData.findOne({uid: message.author.id});
+ if (!tu || !tu.staff) {return await message.channel.send("Since you aren't a Natsuki Staff member, you can't edit characters.");}
+ if (!args.length) {return message.channel.send("You have to provide tags to edit characters with.");}
+ options = new TagFilter([
+ new Tag(['name', 'n'], 'name', 'append'),
+ new Tag(['rn', 'rename'], 'rename', 'append'),
+ new Tag(['description', 'desc', 'p', 'personality'], 'personality', 'append'),
+ //new Tag(['anime', 'ani', 'a'], 'anime', 'append'),
+ new Tag(['thumb', 'thumbnail', 't'], 'thumbnail', 'append'),
+ new Tag(['img', 'image', 'i'], 'images', 'listAppend'),
+ new Tag(['loveInterest', 'dating', 'married', 'li'], 'loveInterest', 'append'),
+ new Tag(['gender', 'g', 'sex'], 'gender', 'append'),
+ new Tag(['nickname', 'nn', 'nick'], 'nicknames', 'listAppend'),
+ new Tag(['force', 'f'], 'force', 'toggle')
+ ]).test(args.join(' '));
+ if (!options.name) {
+ let tempani = await ask(message, "What character would you like to edit?", 60000, false, true);
+ if (!tempani) {return;}
+ options.name = tempani.split(/\s+/g);
+ }
+ let asr = await chs(message, client, options.name.toLowerCase(), -700, 0);
+ let fn;
+ if (asr === 0) {
+ return message.channel.send("That search returned no results! Try again?");
+ } else if (asr instanceof Pagination) {
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
+ await asr.message.react('✅');
+ let noticeDel = await message.channel.send("React with :white_check_mark: when you've found the character you want!");
+ let arc;
+ try {arc = await asr.message.awaitReactions({filter: (r) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
+ catch {return message.reply("Looks like you didn't find the character you were looking for.");}
+ collected = arc.first().emoji.name;
+ if (collected === '✅') {
+ fn = client.misc.cache.anime.get(asr.getCurrentPage().title.trim());
+ await asr.stop();
+ await asr.message.delete().catch(() => {});
+ await noticeDel.delete().catch(() => {});
+ }
+ else {return message.reply("Looks like you didn't find the character you were looking for.");}
+ } else {fn = asr.id;}
+ let ech = await Char.findOne({id: fn});
+ if (!ech) {return message.channel.send("\\*Head scratching* that character seems to have vanished into thin air. Try again or go yell at my devs.");}
+ if (message.attachments.size) {
+ if (options.thumbnail) {
+ if (!options.images) {options.images = [];}
+ Array.from(message.attachments.keys()).forEach(i => options.images.push(message.attachments.get(i).url));
+ } else {
+ if (!options.images) {options.images = [];}
+ let att = Array.from(message.attachments.keys());
+ if (message.attachments.size > 1) {
+ for (let i = 1; i < att.length; i++) {
+ options.images.push(message.attachments.get(att[i]).url);
}
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({embeds: [amEmbed]}));
- am.delete().catch(() => {});
- return dmch.send(`Your character has been ${!queue ? "added" : "submitted"}`);
- } else {
- return dmch.send("Oh, okay. I'll discard that then!");
}
- });
- rc.on("end", collected => {if (!collected.size) {return message.author.send("Looks like you ran out of time! Try again?");}});
- } catch {return message.author.send("Hmm... there was some kind of error when I tried to submit that character. Try again, and if it keeps not working, then go yell at my devs!");}
- return;
+ options.thumbnail = message.attachments.get(att[0]).url;
+ }
+ }
+ Object.keys(options).forEach(async o => {if (![undefined, null].includes(options[o]) && o !== 'name') {
+ /*if (o === 'anime') {
+ let ani = await AniData.findOne({id: ech.anime});
+ if (ani) {
+
+ }
+ }*/
+ if (Array.isArray(options[o])) {options[o].forEach(i => ech[o].push(i));}
+ else {ech[o] = options[o];}
+ ech.markModified(o);
+ if (o === 'rename') {
+ delete ech.rename;
+ client.misc.cache.charsID.set(ech.id, options.rename);
+ client.misc.cache.chars.delete(ech.name);
+ client.misc.cache.chars.set(options.rename, ech.id);
+ ech.name = options.rename;
+ }
+ }});
+ ech.save();
+ return message.channel.send('Character updated.');
}
if (['s', 'search'].includes(args[0].trim().toLowerCase())) {
@@ -238,7 +340,7 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
} else {
await message.channel.send({embeds: [asr.embed]});
}
@@ -256,7 +358,7 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
} else {
await message.channel.send({embeds: [asr.embed]});
}
@@ -266,7 +368,7 @@ module.exports = {
if (['reject'].includes(args[0].trim().toLowerCase())) {
let tu = await UserData.findOne({uid: message.author.id});
if (!tu || !tu.staff) {await message.channel.send("Since you aren't a Natsuki Staff member, you can't reject character submissions!");}
- let tr = await CharData.findOne({id: args[1].toLowerCase()});
+ let tr = await Char.findOne({id: args[1].toLowerCase()});
if (!tr) {return message.reply("That character submission doesn't seem to exist!");}
if (tr.queued !== true) {return message.reply("That character was already accepted, so you can't reject it.");}
return await CharData.deleteOne({id: args[1].toLowerCase()})
@@ -274,6 +376,43 @@ module.exports = {
.catch(() => {return message.reply("It seems that submission wasn't deleted for some reason. \*insert head scratching*");});
}
+ if (['accept', 'approve'].includes(args[0].toLowerCase())) {
+ let tu = await UserData.findOne({uid: message.author.id});
+ if (!tu || !tu.staff) {await message.channel.send("Since you aren't a Natsuki Staff member, you can't accept character submissions!");}
+ let tr = await Char.findOne({id: args[1].toLowerCase()});
+ if (!tr) {return message.reply("That character submission doesn't seem to exist!");}
+ if (tr.queued !== true) {return message.reply("That character was already accepted, so you can't accept it again...");}
+ tr.queued = false;
+ return await tr.save()
+ .then(async () => {
+ client.misc.cache.chars.set(tr.name.normalize("NFD").replace(/[\u0300-\u036f]/g, ""), tr.id);
+ tr.nicknames.forEach(nn => client.misc.cache.chars.set(nn.normalize("NFD").replace(/[\u0300-\u036f]/g, ""), tr.id));
+ client.misc.cache.charsID.set(tr.id, tr.name.normalize("NFD").replace(/[\u0300-\u036f]/g, ""));
+ client.misc.cache.charsNum++;
+ client.misc.cache.charsLove.set(char.id, char.loved);
+ client.guilds.cache.get('762707532417335296').channels.cache.get('932177797705781308').send({embeds: [new Discord.MessageEmbed()
+ .setTitle(`Character Accepted -> ${tr.name}`)
+ .setAuthor({name: 'Character Approved', iconURL: message.author.displayAvatarURL()})
+ .setThumbnail(tr.thumbnail)
+ .setDescription(`${tr.name} has been approved, and is now available to all Natsuki users.`)
+ .setColor('c375f0')
+ .setFooter({text: "Natsuki"})
+ .setTimestamp()
+ ]}).catch(() => {});
+ let ani = await AniData.findOne({id: tr.anime});
+ if (!ani) {
+ tr.queued = false;
+ tr.save();
+ return message.channel.send("I can't accept that submission for you because it doesn't have a valid anime listed. Please report this to a dev.");
+ }
+ ani.characters.push(tr.id);
+ ani.markModified('characters');
+ ani.save();
+ return message.channel.send("I've accepted that submission.");
+ })
+ .catch(() => {return message.reply("It seems that submission wasn't accepted for some reason. \*insert head scratching*");});
+ }
+
if (['r', 'rand', 'random', 'any'].includes(args[0].toLowerCase())) {
let asr = await chs(message, client, client.misc.cache.chars.random(), -100000);
return await message.channel.send({embeds: [asr.embed]});
@@ -291,23 +430,26 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
- await message.channel.send("React with :white_check_mark: when you've found the character you want!");
+ let noticeDel = await message.channel.send("React with :white_check_mark: when you've found the character you want!");
let arc;
try {arc = await asr.message.awaitReactions({filter: (r) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
catch {return message.reply("Looks like you didn't find the character you were looking for.");}
collected = arc.first().emoji.name;
if (collected === '✅') {
fn = client.misc.cache.chars.get(asr.getCurrentPage().title.trim());
- asr.stop();
+ await asr.stop();
+ await asr.message.delete().catch(() => {});
+ await noticeDel.delete().catch(() => {});
}
else {return message.reply("Looks like you didn't find the character you were looking for.");}
} else {
- await message.channel.send({embeds: [asr.embed]});
- let conf = await ask(message, "Is this the character you meant?", 60000);
+ let preConfEmbed = await message.channel.send({embeds: [asr.embed]});
+ let conf = await ask(message, "Is this the character you meant?", 60000, undefined, undefined, true);
if (!['y', 'yes', 'ye', 'n', 'no'].includes(conf.trim().toLowerCase())) {clearDM(); return dmch.send("You must specify yes or no! Please try again.");}
conf = ['y', 'yes', 'ye'].includes(conf.trim().toLowerCase());
+ preConfEmbed.delete().catch(() => {});
if (!conf) {return message.channel.send("Well, I've got nothing, then. If that doesn't match the character you're looking for then I would try again with a more narrow search.");}
fn = asr.id;
}
@@ -331,7 +473,7 @@ module.exports = {
let n = mention ? message.guild ? message.mentions.members.first().displayName : message.mentions.users.first().username : message.guild ? message.member.displayName : message.author.username;
return message.channel.send({embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: `${n}${n.endsWith('s') ? '' : "'s"} Favorited Characters`, iconURL: mention ? mention.avatarURL() : message.author.avatarURL()})
+ .setAuthor({name: `${n}${n.endsWith('s') ? '' : "'s"} Favorited Characters`, iconURL: mention ? mention.displayAvatarURL() : message.author.displayAvatarURL()})
.setDescription(`**${chars.length} character${chars.length === 1 ? '': 's'} favorited**\n\n${chars.join(", ")}`)
.setColor('c375f0')
.setFooter({text: "Natsuki"})
@@ -356,16 +498,18 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
- await message.channel.send("React with :white_check_mark: when you've found the character you want!");
+ let noticeDel = await message.channel.send("React with :white_check_mark: when you've found the character you want!");
let arc;
try {arc = await asr.message.awaitReactions({filter: (r) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
catch {return message.reply("Looks like you didn't find the character you were looking for.");}
- collected = arc.first().emoji.name;
+ let collected = arc.first().emoji.name;
if (collected === '✅') {
fn = client.misc.cache.chars.get(asr.getCurrentPage().title.trim());
- asr.stop();
+ await asr.stop();
+ await asr.message.delete().catch(() => {});
+ await noticeDel.delete().catch(() => {});
}
else {return message.reply("Looks like you didn't find the character you were looking for.");}
} else {fn = asr.id;}
@@ -381,7 +525,7 @@ module.exports = {
ch.images.push(ch.thumbnail);
let pages = ch.images.map(im => new Discord.MessageEmbed()
.setTitle(ch.name)
- .setDescription(`**Name:** ${ch.name}`)
+ .setDescription(`**Name:** ${ch.name} -> ${ch.images.length} ${client.utils.as(ch.images.length, 'image')}`)
.addField('Other', `**Anime**: ${client.misc.cache.animeID.get(ch.anime)}\n\n**Gender**: ${ch.gender}\n`)
.setColor("c375f0")
.setImage(im)
@@ -389,7 +533,7 @@ module.exports = {
if (pages.length > 1) {
let pag = new Pagination(message.channel, pages, message, client, true);
return await pag.start({user: message.author.id, time: 60000});
- } else {return message.channel.send(pages[0].setTimestamp());}
+ } else {return message.channel.send({embeds: [pages[0].setTimestamp()]});}
} else {
args.shift();
let images = [];
@@ -413,10 +557,10 @@ module.exports = {
ch.markModified('images');
ch.save();
}
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177850239422494').send({
embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`New Image ${queue ? "Submitted" : "Added"}`)
.setDescription(`For **${ch.name}** | \`${ch.id}\` from ${client.misc.cache.animeID.get(ch.anime)}`)
.setThumbnail(ch.thumbnail)
@@ -433,10 +577,10 @@ module.exports = {
ch.markModified('images');
ch.save();
}
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177850239422494').send({
embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`New Images ${queue ? "Submitted" : "Added"}`)
.setDescription(`For **${ch.name}** | \`${ch.id}\` from ${client.misc.cache.animeID.get(ch.anime)}`)
.addField("Images", images.map(img => `${img}\n`).join(""))
@@ -465,7 +609,7 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
let arc;
@@ -492,7 +636,7 @@ module.exports = {
.addField("Loved by", `**${ch.loved}** Natsuki user${ch.loved === 1 ? '' : 's'}!\n\`${prefix}char love ${ch.name}\``)
.setColor("c375f0")
.setImage(ch.thumbnail)
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
));
let pag = new Pagination(message.channel, pages, message, client, true);
@@ -502,9 +646,10 @@ module.exports = {
new Discord.MessageEmbed()
.setTitle(`${anime.name}: Characters`)
.setThumbnail(anime.thumbnail)
- .setDescription(anime.characters.map(ch => client.misc.cache.charsID.get(ch)).join(", "))
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setDescription(`**${anime.characters.length} Characters**\n` + anime.characters.map(ch => client.misc.cache.charsID.get(ch)).join(", "))
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
+ .setColor('c375f0')
]});
}
}
@@ -521,7 +666,7 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
await message.channel.send("React with :white_check_mark: when you've found the character you want!");
let arc;
@@ -550,10 +695,10 @@ module.exports = {
ch.save();
client.misc.cache.chars.set(nn, ch.id);
}
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177814638186516').send({
embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`New Character Nickname ${queue ? "Submitted" : "Added"}`)
.setDescription(`For **${ch.name}** | \`${ch.id}\` from ${client.misc.cache.animeID.get(ch.anime)}`)
.addField("Name", nn)
diff --git a/commands/anime/charimage.js b/commands/anime/charimage.js
index 0154b6e..d8916bc 100644
--- a/commands/anime/charimage.js
+++ b/commands/anime/charimage.js
@@ -37,16 +37,18 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
- await message.channel.send("React with :white_check_mark: when you've found the character you want!");
+ let noticeDel = await message.channel.send("React with :white_check_mark: when you've found the character you want!");
let arc;
try {arc = await asr.message.awaitReactions({filter: (r) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
catch {return message.reply("Looks like you didn't find the character you were looking for.");}
- collected = arc.first().emoji.name;
+ let collected = arc.first().emoji.name;
if (collected === '✅') {
fn = client.misc.cache.chars.get(asr.getCurrentPage().title.trim());
- asr.stop();
+ await asr.stop();
+ await asr.message.delete().catch(() => {});
+ await noticeDel.delete().catch(() => {});
}
else {return message.reply("Looks like you didn't find the character you were looking for.");}
} else {fn = asr.id;}
@@ -62,7 +64,7 @@ module.exports = {
ch.images.push(ch.thumbnail);
let pages = ch.images.map(im => new Discord.MessageEmbed()
.setTitle(ch.name)
- .setDescription(`**Name:** ${ch.name}`)
+ .setDescription(`**Name:** ${ch.name} -> ${ch.images.length} ${client.utils.as(ch.images.length, 'image')}`)
.addField('Other', `**Anime**: ${client.misc.cache.animeID.get(ch.anime)}\n\n**Gender**: ${ch.gender}\n`)
.setColor("c375f0")
.setImage(im)
@@ -70,7 +72,7 @@ module.exports = {
if (pages.length > 1) {
let pag = new Pagination(message.channel, pages, message, client, true);
return await pag.start({user: message.author.id, time: 60000});
- } else {return message.channel.send(pages[0].setTimestamp());}
+ } else {return message.channel.send({embeds: [pages[0].setTimestamp()]});}
} else {
args.shift();
let images = [];
@@ -94,10 +96,10 @@ module.exports = {
ch.markModified('images');
ch.save();
}
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177850239422494').send({
embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`New Image ${queue ? "Submitted" : "Added"}`)
.setDescription(`For **${ch.name}** | \`${ch.id}\` from ${client.misc.cache.animeID.get(ch.anime)}`)
.setThumbnail(ch.thumbnail)
@@ -114,10 +116,10 @@ module.exports = {
ch.markModified('images');
ch.save();
}
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177850239422494').send({
embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`New Images ${queue ? "Submitted" : "Added"}`)
.setDescription(`For **${ch.name}** | \`${ch.id}\` from ${client.misc.cache.animeID.get(ch.anime)}`)
.addField("Images", images.map(img => `${img}\n`).join(""))
diff --git a/commands/anime/charlb.js b/commands/anime/charlb.js
index b47af35..bd65e9e 100644
--- a/commands/anime/charlb.js
+++ b/commands/anime/charlb.js
@@ -22,7 +22,7 @@ module.exports = {
.map((c, i) => `${i+1}. **${client.misc.cache.charsLove.get(c)} vote${client.misc.cache.charsLove.get(c) === 1 ? '' : 's'}** -> ${client.misc.cache.charsID.get(c)}`)
.join('\n')
).setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
diff --git a/commands/anime/charnick.js b/commands/anime/charnick.js
index afb54e0..69b94a7 100644
--- a/commands/anime/charnick.js
+++ b/commands/anime/charnick.js
@@ -32,7 +32,7 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
await message.channel.send("React with :white_check_mark: when you've found the character you want!");
let arc;
@@ -61,10 +61,10 @@ module.exports = {
ch.save();
client.misc.cache.chars.set(nn, ch.id);
}
- client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('817466729293938698').send({
+ client.guilds.fetch('762707532417335296').then(g => g.channels.cache.get('932177814638186516').send({
embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`New Character Nickname ${queue ? "Submitted" : "Added"}`)
.setDescription(`For **${ch.name}** | \`${ch.id}\` from ${client.misc.cache.animeID.get(ch.anime)}`)
.addField("Name", nn)
diff --git a/commands/anime/haswatched.js b/commands/anime/haswatched.js
index b39d25d..08308d8 100644
--- a/commands/anime/haswatched.js
+++ b/commands/anime/haswatched.js
@@ -1,5 +1,3 @@
-const Discord = require('discord.js');
-
const AF = require("../../models/anifav");
const AniData = require('../../models/anime');
@@ -23,7 +21,7 @@ module.exports = {
help: "Check if you or another user has watched an anime with `{{p}}haswatched`",
async execute(message, msg, args, cmd, prefix, mention, client) {
let user;
- if (args[0] && args[0].match(/(?:<@\!?\d+>|\d+)/gm)) {
+ if (args[0] && args[0].match(/<@!?\d+>|\d+/gm)) {
user = message.guild ? (mention || client.users.cache.get(args[0])) : message.author;
if (!user) {return message.channel.send("Hmmm... for some reason I can't find the user you're looking for?");}
args.shift();
@@ -38,7 +36,7 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
let arc;
@@ -53,7 +51,7 @@ module.exports = {
} else {fn = asr.id;}
let ani = await AniData.findOne({id: fn});
let af = await AF.findOne({uid: user.id});
- if (!af || !af.watched.includes(fn)) {return message.channel.send(`${user.id === message.author.id ? "You haven't" : "That person hasn't"} watched **${ani.name}**.`);}
+ if (!af || !af.watched.includes(fn)) {return message.channel.send(`${user.id === message.author.id ? "You haven't" : "That person hasn't"} watched **${ani.name}**${af && af.toWatch.includes(fn) ? `, *but* it is on ${user.id === message.author.id ? "your" : "their"} watch list` : ''}.`);}
else {return message.channel.send(`${user.id === message.author.id ? "You have" : "That person has"} watched **${ani.name}**.`);}
}
};
\ No newline at end of file
diff --git a/commands/anime/highvalue.js b/commands/anime/highvalue.js
index 1548732..f24cf62 100644
--- a/commands/anime/highvalue.js
+++ b/commands/anime/highvalue.js
@@ -1,5 +1,3 @@
-const Discord = require('discord.js');
-
const UserData = require('../../models/user');
const CharData = require('../../models/char');
@@ -30,23 +28,26 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
- await message.channel.send("React with :white_check_mark: when you've found the character you want!");
+ let noticeDel = await message.channel.send("React with :white_check_mark: when you've found the character you want!");
let arc;
try {arc = await asr.message.awaitReactions({filter: (r) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
catch {return message.reply("Looks like you didn't find the character you were looking for.");}
collected = arc.first().emoji.name;
if (collected === '✅') {
fn = client.misc.cache.chars.get(asr.getCurrentPage().title.trim());
- asr.stop();
+ await asr.stop();
+ await asr.message.delete().catch(() => {});
+ await noticeDel.delete().catch(() => {});
}
else {return message.reply("Looks like you didn't find the character you were looking for.");}
} else {
- await message.channel.send({embeds: [asr.embed]});
- let conf = await ask(message, "Is this the character you meant?", 60000);
+ let preConfEmbed = await message.channel.send({embeds: [asr.embed]});
+ let conf = await ask(message, "Is this the character you meant?", 60000, undefined, undefined, true);
if (!['y', 'yes', 'ye', 'n', 'no'].includes(conf.trim().toLowerCase())) {clearDM(); return dmch.send("You must specify yes or no! Please try again.");}
conf = ['y', 'yes', 'ye'].includes(conf.trim().toLowerCase());
+ preConfEmbed.delete().catch(() => {});
if (!conf) {return message.channel.send("Well, I've got nothing, then. If that doesn't match the character you're looking for then I would try again with a more narrow search.");}
fn = asr.id;
}
diff --git a/commands/anime/listanime.js b/commands/anime/listanime.js
index 4c48260..36327f0 100644
--- a/commands/anime/listanime.js
+++ b/commands/anime/listanime.js
@@ -39,7 +39,7 @@ module.exports = {
s = `${s}${ps.join('\n')}`;
pages.push(new Discord.MessageEmbed()
.setTitle("Anime Database")
- .setThumbnail(client.user.avatarURL({size: 1024, dynamic: true, format: 'png'}))
+ .setThumbnail(client.user.displayAvatarURL({size: 1024, dynamic: true, format: 'png'}))
.setDescription(s)
.setColor('c375f0')
.setTimestamp()
diff --git a/commands/anime/loveani.js b/commands/anime/loveani.js
new file mode 100644
index 0000000..d88d41c
--- /dev/null
+++ b/commands/anime/loveani.js
@@ -0,0 +1,83 @@
+const Discord = require('discord.js');
+
+const AF = require("../../models/anifav");
+const AniData = require('../../models/anime');
+
+const ask = require('../../util/ask');
+const ans = require('../../util/anime/anisearch');
+const {Pagination} = require('../../util/pagination');
+
+module.exports = {
+ name: "loveani",
+ aliases: ['lani', 'loveanime', 'favani', 'favoriteani', 'favoriteanime', 'fa', 'favani'],
+ meta: {
+ category: 'Anime',
+ description: "Show your love for an anime",
+ syntax: '`loveani `',
+ extra: null
+ },
+ help: new Discord.MessageEmbed()
+ .setTitle("Help -> Character Favoriting")
+ .setDescription("Show your love for a character with this command. A replica of running `char love `.")
+ .addField("Syntax", "`lovechar `"),
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ if (args[0] && ['v', 'view'].includes(args[0].toLowerCase())) {
+ let cf = await AF.findOne({uid: mention ? mention.id : message.author.id});
+ if (!cf || !cf.liked.length) {return message.channel.send(`Looks like ${mention ? 'they' : 'you'} haven't favorited any anime!`);}
+ let chars = cf.liked;
+ chars = chars.map(tc => client.misc.cache.animeID.get(tc));
+ let n = mention ? message.guild ? message.mentions.members.first().displayName : message.mentions.users.first().username : message.guild ? message.member.displayName : message.author.username;
+ return message.channel.send({embeds: [
+ new Discord.MessageEmbed()
+ .setAuthor({name: `${n}${n.endsWith('s') ? '' : "'s"} Favorited Anime`, iconURL: mention ? mention.displayAvatarURL() : message.author.displayAvatarURL()})
+ .setDescription(`**${chars.length} anime favorited**\n\n${chars.join(", ")}`)
+ .setColor('c375f0')
+ .setFooter({text: "Natsuki"})
+ .setTimestamp()
+ ]});
+ } else {
+ if (!args[0]) {
+ let tempchar = await ask(message, "What anime would you like to add to your favorites list?", 60000, false, true);
+ if (!tempchar) {return;}
+ args = tempchar.split(/\s+/g);
+ }
+ let asr = await ans(message, client, args.join(" ").trim().toLowerCase(), -700, 0);
+ let fn;
+ if (asr === 0) {
+ return message.channel.send("That search returned no results! Try again?");
+ } else if (asr instanceof Pagination) {
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
+ await asr.message.react('✅');
+ let noticeDel = await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
+ let arc;
+ try {arc = await asr.message.awaitReactions({filter: (r) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
+ catch {return message.reply("Looks like you didn't find the anime you were looking for.");}
+ collected = arc.first().emoji.name;
+ if (collected === '✅') {
+ fn = client.misc.cache.chars.get(asr.getCurrentPage().title.trim());
+ await asr.stop();
+ await asr.message.delete().catch(() => {});
+ await noticeDel.delete().catch(() => {});
+ }
+ else {return message.reply("Looks like you didn't find the anime you were looking for.");}
+ } else {
+ let preConfEmbed = await message.channel.send({embeds: [asr.embed]});
+ let conf = await ask(message, "Is this the anime you meant?", 60000, undefined, undefined, true);
+ if (!['y', 'yes', 'ye', 'n', 'no'].includes(conf.trim().toLowerCase())) {clearDM(); return dmch.send("You must specify yes or no! Please try again.");}
+ conf = ['y', 'yes', 'ye'].includes(conf.trim().toLowerCase());
+ preConfEmbed.delete().catch(() => {});
+ if (!conf) {return message.channel.send("Well, I've got nothing, then. If that doesn't match the anime you're looking for then I would try again with a more narrow search.");}
+ fn = asr.id;
+ }
+ let cf = await AF.findOne({uid: message.author.id}) || new AF({uid: message.author.id});
+ if (cf.liked.includes(fn)) {return message.channel.send("Looks like that anime is already on your loved list!");}
+ let tfc = await AniData.findOne({id: fn});
+ tfc.liked += 1;
+ tfc.save();
+ cf.liked.push(fn);
+ cf.markModified('liked');
+ cf.save();
+ return message.channel.send(`I've added **${tfc.name}** to your loved/favorited anime list!`);
+ }
+ }
+};
\ No newline at end of file
diff --git a/commands/anime/lovechar.js b/commands/anime/lovechar.js
index 64a51a5..fde97f5 100644
--- a/commands/anime/lovechar.js
+++ b/commands/anime/lovechar.js
@@ -29,7 +29,7 @@ module.exports = {
let n = mention ? message.guild ? message.mentions.members.first().displayName : message.mentions.users.first().username : message.guild ? message.member.displayName : message.author.username;
return message.channel.send({embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: `${n}${n.endsWith('s') ? '' : "'s"} Favorited Characters`, iconURL: mention ? mention.avatarURL() : message.author.avatarURL()})
+ .setAuthor({name: `${n}${n.endsWith('s') ? '' : "'s"} Favorited Characters`, iconURL: mention ? mention.displayAvatarURL() : message.author.displayAvatarURL()})
.setDescription(`**${chars.length} character${chars.length === 1 ? '': 's'} favorited**\n\n${chars.join(", ")}`)
.setColor('c375f0')
.setFooter({text: "Natsuki"})
@@ -46,23 +46,26 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
- await message.channel.send("React with :white_check_mark: when you've found the character you want!");
+ let noticeDel = await message.channel.send("React with :white_check_mark: when you've found the character you want!");
let arc;
- try {arc = await asr.message.awaitReactions({filter: (r, u) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
+ try {arc = await asr.message.awaitReactions({filter: (r) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
catch {return message.reply("Looks like you didn't find the character you were looking for.");}
collected = arc.first().emoji.name;
if (collected === '✅') {
fn = client.misc.cache.chars.get(asr.getCurrentPage().title.trim());
- asr.stop();
+ await asr.stop();
+ await asr.message.delete().catch(() => {});
+ await noticeDel.delete().catch(() => {});
}
else {return message.reply("Looks like you didn't find the character you were looking for.");}
} else {
- await message.channel.send({embeds: [asr.embed]});
- let conf = await ask(message, "Is this the character you meant?", 60000);
+ let preConfEmbed = await message.channel.send({embeds: [asr.embed]});
+ let conf = await ask(message, "Is this the character you meant?", 60000, undefined, undefined, true);
if (!['y', 'yes', 'ye', 'n', 'no'].includes(conf.trim().toLowerCase())) {clearDM(); return dmch.send("You must specify yes or no! Please try again.");}
conf = ['y', 'yes', 'ye'].includes(conf.trim().toLowerCase());
+ preConfEmbed.delete().catch(() => {});
if (!conf) {return message.channel.send("Well, I've got nothing, then. If that doesn't match the character you're looking for then I would try again with a more narrow search.");}
fn = asr.id;
}
diff --git a/commands/anime/watched.js b/commands/anime/watched.js
index 1ab89bc..153c589 100644
--- a/commands/anime/watched.js
+++ b/commands/anime/watched.js
@@ -58,34 +58,46 @@ module.exports = {
if (asr === 0) {
return message.channel.send("That search returned no results! Try again?");
} else if (asr instanceof Pagination) {
- await asr.start({user: message.author.id, startPage: 1, endTime: 60000});
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
await asr.message.react('✅');
- await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
+ let noticeDel = await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
let arc;
try {arc = await asr.message.awaitReactions({filter: (r) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
catch {return message.reply("Looks like you didn't find the anime you were looking for.");}
collected = arc.first().emoji.name;
if (collected === '✅') {
fn = client.misc.cache.anime.get(asr.getCurrentPage().title.trim());
- asr.stop();
+ await asr.stop();
+ await asr.message.delete().catch(() => {});
+ await noticeDel.delete().catch(() => {});
}
else {return message.reply("Looks like you didn't find the anime you were looking for.");}
} else {
- await message.channel.send({embeds: [asr.embed]});
- let conf = await ask(message, "Is this the anime you meant?", 60000);
+ let preConfEmbed = await message.channel.send({embeds: [asr.embed]});
+ let conf = await ask(message, "Is this the anime you meant?", 60000, undefined, undefined, true);
if (!['y', 'yes', 'ye', 'n', 'no'].includes(conf.trim().toLowerCase())) {clearDM(); return dmch.send("You must specify yes or no! Please try again.");}
conf = ['y', 'yes', 'ye'].includes(conf.trim().toLowerCase());
+ preConfEmbed.delete().catch(() => {});
if (!conf) {return message.channel.send("Well, I've got nothing, then. If that doesn't match the anime you're looking for then I would try again with a more narrow search.");}
- fn = asr.id;}
+ fn = asr.id;
+ }
let af = await AF.findOne({uid: message.author.id}) || new AF({uid: message.author.id});
if (af.watched.includes(fn)) {return message.channel.send("Looks like that anime is already on your finished list!");}
let tfc = await AniData.findOne({id: fn});
tfc.watchers += 1;
tfc.markModified('watchers');
- tfc.save();
af.watched.push(fn);
af.markModified('watched');
+ let dw = false;
+ if (af.toWatch.includes(fn)) {
+ af.toWatch.splice(af.toWatch.indexOf(fn), 1);
+ af.markModified('toWatch');
+ tfc.listed--;
+ tfc.save();
+ dw = true;
+ }
af.save();
- return message.channel.send(`I've added **${tfc.name}** to your list of finished animes!`);
+ tfc.save();
+ return message.channel.send(`I've added **${tfc.name}** to your list of finished animes!${dw ? " I've also removed it from your watch list for you :p" : ''}`);
}
};
\ No newline at end of file
diff --git a/commands/anime/watchedlb.js b/commands/anime/watchedlb.js
index 4f483f2..e68166a 100644
--- a/commands/anime/watchedlb.js
+++ b/commands/anime/watchedlb.js
@@ -22,7 +22,7 @@ module.exports = {
.map((c, i) => `${i+1}. **${client.misc.cache.animeLove.get(c)} watcher${client.misc.cache.animeLove.get(c) === 1 ? '' : 's'}** -> ${client.misc.cache.animeID.get(c)}`)
.join('\n')
).setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
diff --git a/commands/anime/watchlist.js b/commands/anime/watchlist.js
new file mode 100644
index 0000000..7bb7881
--- /dev/null
+++ b/commands/anime/watchlist.js
@@ -0,0 +1,150 @@
+const Discord = require('discord.js');
+
+const AF = require("../../models/anifav");
+const AniData = require('../../models/anime');
+
+const {Pagination} = require('../../util/pagination');
+const ask = require('../../util/ask');
+const ans = require('../../util/anime/anisearch');
+
+module.exports = {
+ name: "watchlist",
+ aliases: ['wl'],
+ meta: {
+ category: 'Anime',
+ description: "Add anime to your list of animes you want to watch",
+ syntax: '`watchlist `',
+ extra: null
+ },
+ help: new Discord.MessageEmbed()
+ .setTitle("Help -> WatchList")
+ .setDescription("Add anime to your watchlist (not to be confused with \"watchedlist\"; this is your list of anime you want to watch but haven't yet. You can view your list or anothers' list as well.)")
+ .addField("Removal from List", "If you're removing an item from your list because you've *seen* the anime, please run the `watched` command instead. It will automatically remove the anime from your watchlist and place it in your watchedlist.")
+ .addField("Syntax", "`watchlist `"),
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ if (!args.length) {return message.channel.send(`Syntax: \`${prefix}watchlist \``);}
+ if (['v', 'view'].includes(args[0].toLowerCase())) {
+ if (mention) {args.shift();}
+ let user = mention || message.author;
+ let af = await AF.findOne({uid: user.id});
+ if (!af || !af.toWatch.length) {return message.channel.send(`${user.id === message.author.id ? "You don't" : "That person doesn't"} have any watchlisted anime.`);}
+ let pages = [];
+ let pl = (Math.floor(af.toWatch.length / 10) + 1);
+ for (let i = 0; i < pl; i++) {
+ let s = '';
+ for (let x = 0; x < 10; x++) {
+ if (!af.toWatch[(i * 10) + x]) {break;}
+ s += `**${x + (i * 10) + 1}.** ${client.misc.cache.animeID.get(af.toWatch[(i * 10) + x])}\n`;
+ }
+ pages.push(new Discord.MessageEmbed()
+ .setAuthor({
+ name: message.guild ? message.guild.members.cache.get(user.id).displayName : user.username,
+ iconURL: message.guild ? message.guild.members.cache.get(user.id).displayAvatarURL({dynamic: true}) : user.displayAvatarURL({dynamic: true})
+ })
+ .setTitle("Anime Watch List")
+ .setDescription(s)
+ .setColor('c375f0')
+ .setTimestamp()
+ );
+ }
+ if (pages.length > 1) {
+ let pag = new Pagination(message.channel, pages, message, client, true);
+ return await pag.start({user: message.author.id, time: 60000});
+ } else {return message.channel.send({embeds: [pages[0].setFooter({text: "Natsuki"})]});}
+ }
+
+ if (['a', 'add'].includes(args[0].toLowerCase())) {
+ args.shift();
+ if (!args[0]) {
+ let tempchar = await ask(message, "What anime would you like to add to your watch list?", 60000, false, true);
+ if (!tempchar) {return;}
+ args = tempchar.split(/\s+/g);
+ }
+ let asr = await ans(message, client, args.join(" ").trim().toLowerCase(), -700, 0);
+ let fn;
+ if (asr === 0) {
+ return message.channel.send("That search returned no results! Try again?");
+ } else if (asr instanceof Pagination) {
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
+ await asr.message.react('✅');
+ let noticeDel = await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
+ let arc;
+ try {arc = await asr.message.awaitReactions({filter: (r) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
+ catch {return message.reply("Looks like you didn't find the anime you were looking for.");}
+ collected = arc.first().emoji.name;
+ if (collected === '✅') {
+ fn = client.misc.cache.anime.get(asr.getCurrentPage().title.trim());
+ await asr.stop();
+ await asr.message.delete().catch(() => {});
+ await noticeDel.delete().catch(() => {});
+ }
+ else {return message.reply("Looks like you didn't find the anime you were looking for.");}
+ } else {
+ let preConfEmbed = await message.channel.send({embeds: [asr.embed]});
+ let conf = await ask(message, "Is this the anime you meant?", 60000, undefined, undefined, true);
+ if (!['y', 'yes', 'ye', 'n', 'no'].includes(conf.trim().toLowerCase())) {clearDM(); return dmch.send("You must specify yes or no! Please try again.");}
+ conf = ['y', 'yes', 'ye'].includes(conf.trim().toLowerCase());
+ preConfEmbed.delete().catch(() => {});
+ if (!conf) {return message.channel.send("Well, I've got nothing, then. If that doesn't match the anime you're looking for then I would try again with a more narrow search.");}
+ fn = asr.id;}
+ let af = await AF.findOne({uid: message.author.id}) || new AF({uid: message.author.id});
+ if (af.toWatch.includes(fn)) {return message.channel.send("Looks like that anime is already on your watch list!");}
+ if (af.watched.includes(fn)) {return message.channel.send("That anime is on your **watched** list already...");}
+ const tfc = await AniData.findOne({id: fn});
+ if (!tfc) {return message.channel.send("Huh... guess that anime just... vanished into thin air? I would go yell at my devs.");}
+ af.toWatch.push(fn);
+ af.markModified('toWatch');
+ af.save();
+ tfc.listed++;
+ tfc.save();
+ return message.channel.send(`I've added **${client.misc.cache.animeID.get(fn)}** to your watch list! ${[`Let me know if it's any good when you get around to it :3`, `Hope it's good!`, 'Try not to wait *too* long before you watch it.', `I've heard good things about that one.`][Math.floor(Math.random() * 4)]}`);
+ }
+
+ if (['d', 'delete', 'remove', 'r'].includes(args[0].toLowerCase())) {
+ let conf = await ask(message, "Real quick, before anything else, I have to ask: are you trying to remove an anime from your watch list because you've now watched it?", 60000);
+ if (!['y', 'yes', 'ye', 'n', 'no'].includes(conf.trim().toLowerCase())) {clearDM(); return dmch.send("You must specify yes or no! Please try again.");}
+ conf = ['y', 'yes', 'ye'].includes(conf.trim().toLowerCase());
+ if (conf) {return message.channel.send(`Good thing I asked then :brain: Please instead use the \`${prefix}watched\` command to handle removing the anime from your watch list.`);}
+ args.shift();
+ if (!args[0]) {
+ let tempchar = await ask(message, "What anime would you like to remove from your watch list?", 60000, false, true);
+ if (!tempchar) {return;}
+ args = tempchar.split(/\s+/g);
+ }
+ let asr = await ans(message, client, args.join(" ").trim().toLowerCase(), -700, 0);
+ let fn;
+ if (asr === 0) {
+ return message.channel.send("That search returned no results! Try again?");
+ } else if (asr instanceof Pagination) {
+ await asr.start({user: message.author.id, startPage: 0, endTime: 60000});
+ await asr.message.react('✅');
+ await message.channel.send("React with :white_check_mark: when you've found the anime you want!");
+ let arc;
+ try {arc = await asr.message.awaitReactions({filter: (r) => ['✅', '⏹'].includes(r.emoji.name), max: 1, errors: ['time']});}
+ catch {return message.reply("Looks like you didn't find the anime you were looking for.");}
+ collected = arc.first().emoji.name;
+ if (collected === '✅') {
+ fn = client.misc.cache.anime.get(asr.getCurrentPage().title.trim());
+ asr.stop();
+ }
+ else {return message.reply("Looks like you didn't find the anime you were looking for.");}
+ } else {
+ await message.channel.send({embeds: [asr.embed]});
+ let conf = await ask(message, "Is this the anime you meant?", 60000, undefined, undefined, true);
+ if (!['y', 'yes', 'ye', 'n', 'no'].includes(conf.trim().toLowerCase())) {clearDM(); return dmch.send("You must specify yes or no! Please try again.");}
+ conf = ['y', 'yes', 'ye'].includes(conf.trim().toLowerCase());
+ if (!conf) {return message.channel.send("Well, I've got nothing, then. If that doesn't match the anime you're looking for then I would try again with a more narrow search.");}
+ fn = asr.id;}
+ let af = await AF.findOne({uid: message.author.id}) || new AF({uid: message.author.id});
+ if (!af.toWatch.includes(fn)) {return message.channel.send("Looks like that anime isn't on your watch list!");}
+ const tfc = await AniData.findOne({id: fn});
+ if (!tfc) {return message.channel.send("Huh... guess that anime just... vanished into thin air? I would go yell at my devs.");}
+ af.toWatch.splice(af.toWatch.indexOf(fn), 1);
+ af.markModified('toWatch');
+ af.save();
+ tfc.listed--;
+ tfc.save();
+ return message.channel.send(`${['Guess it wasn\'t worth the watch after all, huh?', 'Oof. Did you lose interest? Well, either way,', 'Got it, got it.', 'Okie dokie!'][Math.floor(Math.random() * 4)]} I've removed **${client.misc.cache.animeID.get(fn)}** from your watch list.`);
+ }
+ }
+};
\ No newline at end of file
diff --git a/commands/dev/admin.js b/commands/dev/admin.js
index 957d74e..3ff4147 100644
--- a/commands/dev/admin.js
+++ b/commands/dev/admin.js
@@ -28,9 +28,9 @@ module.exports = {
else {tu.admin = false; tu.developer = false;}
tu.save();
const logemb = (act) => new Discord.MessageEmbed()
- .setAuthor({name: `Admin ${act}`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `Admin ${act}`, iconURL: message.author.displayAvatarURL()})
.setDescription("A user's Admin status was updated.")
- .setThumbnail(person.avatarURL({size: 1024}))
+ .setThumbnail(person.displayAvatarURL({size: 1024}))
.addField("Name", person.username, true)
.addField("Developer", message.author.username, true)
.setColor("e8da3a")
diff --git a/commands/dev/anipulse.js b/commands/dev/anipulse.js
new file mode 100644
index 0000000..bd28769
--- /dev/null
+++ b/commands/dev/anipulse.js
@@ -0,0 +1,83 @@
+const Discord = require('discord.js');
+
+const AniData = require("../../models/anime");
+const UserData = require('../../models/user');
+const CharData = require('../../models/char');
+
+const {Pagination} = require('../../util/pagination');
+const {Tag} = require('../../util/tag');
+const {TagFilter} = require('../../util/tagfilter');
+
+module.exports = {
+ name: "anipulse",
+ aliases: ['ap'],
+ meta: {
+ category: 'Developer',
+ description: "Get a pulse check of anime",
+ syntax: '`anipulse`',
+ extra: null
+ },
+ help: "Not much to see here!",
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ let tu = await UserData.findOne({uid: message.author.id});
+ if (!tu || !tu.staff) {return message.channel.send("You must be Natsuki staff in order to use this command.");}
+
+ let sm = await message.channel.send("One moment while I gather that information for you...");
+
+ let options = new TagFilter([
+ new Tag(['c', 'ch', 'char', 'chars', 'character', 'characters'], 'chars', 'append'),
+ new Tag(['a', 'ani', 'anime'], 'anime', 'append')
+ ]).test(args.join(" "));
+ Object.keys(options).forEach(o => {if (isNaN(Number(options[o]))) {delete options[o];}});
+
+ let ani = client.misc.cache.animeID.size;
+ let char = client.misc.cache.charsID.size;
+ let nick = Array.from(client.misc.cache.chars.keys()).filter(x => !Array.from(client.misc.cache.charsID.values()).includes(x)).length;
+
+ let charThresh = (options.chars !== undefined ? Number(options.chars) : 2);
+ let aniThresh = (options.anime !== undefined ? Number(options.anime) : 10);
+
+ let lowChars = [];
+ for await (const ani of AniData.find()) {
+ if (ani.characters.length < aniThresh) {lowChars.push(ani);}
+ }
+
+ let lowIms = [];
+ for await (const char of CharData.find()) {
+ if (char.images.length < charThresh) {lowIms.push(char);}
+ }
+
+ let pages = [new Discord.MessageEmbed()
+ .setTitle("Anime Database Pulse Check")
+ .setDescription(`**${ani}** Anime\n**${char}** Characters\n**${nick}** Nicknames`)
+ .addField(`Anime with < ${aniThresh} character${client.utils.s(aniThresh)}`, `${lowChars.length}`)
+ .addField(`Characters with < ${charThresh} extra image${client.utils.s(charThresh)}`, `${lowIms.length}`)
+ .setColor('c375f0')
+ ];
+
+ let ma = Math.floor(lowIms.length / 10);
+ for (let i = 0; i < ma; i++) {
+ if (!lowChars.slice(10 * i, Math.min((10 * i) + 10, lowChars.length)).length) {break;}
+ pages.push(new Discord.MessageEmbed()
+ .setTitle("Anime Database Pulse Check")
+ .setDescription(`**${ani}** Anime\n**${char}** Characters\n**${nick}** Nicknames`)
+ .addField(`Anime with < ${aniThresh} character${client.utils.s(aniThresh)}`, lowChars.slice(10 * i, Math.min((10 * i) + 10, lowChars.length)).filter(x=>![null,undefined].includes(x)).map((ani, y) => `${(10*i)+y+1}. ${ani.name} -> **${ani.characters.length}** Char${client.utils.s(ani.characters.length)}.`).join('\n'))
+ .setColor('c375f0')
+ );}
+
+ let mc = Math.floor(lowIms.length / 10);
+ for (let i = 0; i < mc; i++) {
+ if (!lowIms.slice(10 * i, Math.min((10 * i) + 10, lowIms.length)).length) {break;}
+ pages.push(new Discord.MessageEmbed()
+ .setTitle("Anime Database Pulse Check")
+ .setDescription(`**${ani}** Anime\n**${char}** Characters\n**${nick}** Nicknames`)
+ .addField(`Characters with < ${charThresh} extra image${client.utils.s(charThresh)}`, lowIms.slice(10 * i, Math.min((10 * i) + 10, lowIms.length)).filter(x=>![null,undefined].includes(x)).map((ch, y) => `${(10*i)+y+1}. ${ch.name} -> **${ch.images.length}** Image${client.utils.s(ch.images.length)}.`).join('\n'))
+ .setColor('c375f0')
+ );}
+
+ const pag = new Pagination(message.channel, pages, message, client, true);
+ sm.delete().catch(() => {});
+
+ return await pag.start({user: message.author.id, time: 60000});
+ }
+};
\ No newline at end of file
diff --git a/commands/dev/cachesync.js b/commands/dev/cachesync.js
new file mode 100644
index 0000000..6164b27
--- /dev/null
+++ b/commands/dev/cachesync.js
@@ -0,0 +1,23 @@
+const Discord = require('discord.js');
+
+const UserData = require('../../models/user');
+
+module.exports = {
+ name: "cachesync",
+ aliases: ['preres', 'pres'],
+ meta: {
+ category: 'Developer',
+ description: "Sync cached XP, monners, and monitor data to make client safe for a restart",
+ syntax: '`cachesync`',
+ extra: null
+ },
+ help: "Nothing to see here!",
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ const tu = await UserData.findOne({uid: message.author.id});
+ if ((!tu || !tu.developer) && !client.developers.includes(message.author.id)) {return message.channel.send("You must be a developer in order to do this!");}
+ await require('../../util/lxp/cacheloop')(client);
+ await require('../../util/vcloop')(client);
+ await require('../../util/monitorloop')(client);
+ return message.channel.send("Cache synchronized with DB!");
+ }
+};
\ No newline at end of file
diff --git a/commands/dev/developer.js b/commands/dev/developer.js
index 4d287d1..a2a1a00 100644
--- a/commands/dev/developer.js
+++ b/commands/dev/developer.js
@@ -30,9 +30,9 @@ module.exports = {
else {tu.developer = false;}
tu.save();
const logemb = (act) => new Discord.MessageEmbed()
- .setAuthor({name: `Developer ${act}`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `Developer ${act}`, iconURL: message.author.displayAvatarURL()})
.setDescription("A user's Developer status was updated.")
- .setThumbnail(person.avatarURL({size: 1024}))
+ .setThumbnail(person.displayAvatarURL({size: 1024}))
.addField("Name", person.username, true)
.addField("Developer", message.author.username, true)
.setColor("e8da3a")
diff --git a/commands/dev/eval.js b/commands/dev/eval.js
index 3960119..5ade095 100644
--- a/commands/dev/eval.js
+++ b/commands/dev/eval.js
@@ -16,6 +16,8 @@ module.exports = {
},
execute(message, msg, args, cmd, prefix, mention, client) {
try {
+ const dc = (...files) => {return files.forEach(file => {return delete require.cache[require.resolve(`../../${file}`)];});};
+
let timer = new Date().getTime();
if (!client.developers.includes(message.author.id)) {return message.channel.send("Sorry, but I've got trust issues, so only me devs can go commanding me around like that.");};
@@ -27,20 +29,20 @@ module.exports = {
if (!args.length) {return message.channel.send("Silly goose, if you want me to do something, you have to tell me what!");}
const result = new Promise((resolve) => resolve(eval(args.join(' '))));
return result.then((output) => {
- if (typeof output !== 'string') {
- output = require('util').inspect(output, {depth: 0});
- }
- output = output.replace(client.config.token, 'Client Token')
- .replace(client.config.database.password, 'Database Password')
- .replace(client.config.database.cluster, 'Database Cluster');
+ if (typeof output !== 'string') {
+ output = require('util').inspect(output, {depth: 0});
+ }
+ output = output.replace(client.config.token, 'Client Token')
+ .replace(client.config.database.password, 'Database Password')
+ .replace(client.config.database.cluster, 'Database Cluster');
- return options.silent ? null : message.channel.send({embeds: [new Discord.MessageEmbed()
- .setTitle('Client Evaluation')
- .setDescription(`\`\`\`js\n${output}\n\`\`\``)
- .setColor('c375f0')
- .setFooter({text: `Natsuki | Evaluated in ${new Date().getTime() - timer}ms`, iconURL: client.user.avatarURL()})
- .setTimestamp()]});
- }).catch(error => {return message.channel.send(`Error: \`${error}\`.`);});
+ return options.silent ? null : message.channel.send({embeds: [new Discord.MessageEmbed()
+ .setTitle('Client Evaluation')
+ .setDescription(`\`\`\`js\n${output}\n\`\`\``)
+ .setColor('c375f0')
+ .setFooter({text: `Natsuki | Evaluated in ${new Date().getTime() - timer}ms`, iconURL: client.user.displayAvatarURL()})
+ .setTimestamp()]});
+ }).catch(error => {return message.channel.send(`Error: \`${error}\`.`);});
} catch (error) {
let date = new Date; date = date.toString().slice(date.toString().search(":") - 2, date.toString().search(":") + 6);
console.error(`\n${chalk.red('[ERROR]')} >> ${chalk.yellow(`At [${date}] | Occurred while trying to run n?eval`)}`, error);
diff --git a/commands/dev/execute.js b/commands/dev/execute.js
index 94897ab..7f2811c 100644
--- a/commands/dev/execute.js
+++ b/commands/dev/execute.js
@@ -22,7 +22,7 @@ module.exports = {
.setTitle("Error")
.setDescription(`\`\`\`${error}\`\`\``)
.setColor("ff446a")
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
);
}
@@ -31,7 +31,7 @@ module.exports = {
.setTitle("Execution Successful")
.setDescription(`\`\`\`${stdout}\`\`\``)
.setColor("c375f0")
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
);
});
diff --git a/commands/dev/reload.js b/commands/dev/reload.js
index ed73ebc..00092c2 100644
--- a/commands/dev/reload.js
+++ b/commands/dev/reload.js
@@ -91,7 +91,9 @@ module.exports = {
});
if (!res) {return message.channel.send("I can't reload that command as I can't find file!");}
if (require.resolve(res) in require.cache) {delete require.cache[require.resolve(res)];}
- client.commands.set(lf, require(res));
+ const ncmd = require(res);
+ client.commands.set(lf, ncmd);
+ if (ncmd.aliases) {ncmd.aliases.forEach(alias => {if (!client.aliases.has(alias)) {client.aliases.set(alias, lf);}});}
return message.channel.send(`Reloaded command \`${lf}\` in ${new Date().getTime() - timer}ms`);
}
diff --git a/commands/dev/restart.js b/commands/dev/restart.js
new file mode 100644
index 0000000..14ac839
--- /dev/null
+++ b/commands/dev/restart.js
@@ -0,0 +1,34 @@
+const Discord = require('discord.js');
+const cp = require('child_process');
+
+module.exports = {
+ name: "restart",
+ aliases: ['res'],
+ meta: {
+ category: 'Developer',
+ description: "Fully restart Natsuki",
+ syntax: '`restart`',
+ extra: null
+ },
+ help: "Fully restarts the bot. Developer-only.",
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ if (!client.developers.includes(message.author.id)) {return message.channel.send("You must be a developer in order to do that!");}
+ try {
+ await require('../../util/lxp/cacheloop')(client);
+ await require('../../util/vcloop')(client);
+ await require('../../util/monitorloop')(client);
+ await message.channel.send("Cache synchronized with DB! Restarting...");
+ return cp.exec("pm2 restart natsuki", function(error, stdout, stderr) {
+ if (error) {
+ return message.channel.send({embeds: [new Discord.MessageEmbed()
+ .setTitle("Error")
+ .setDescription(`\`\`\`${error}\`\`\``)
+ .setColor("ff446a")
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
+ .setTimestamp()]}
+ );
+ }
+ });
+ } catch {return message.channel.send("There was an error in trying to do that!");}
+ }
+};
\ No newline at end of file
diff --git a/commands/dev/staff.js b/commands/dev/staff.js
index 088d63e..5038c52 100644
--- a/commands/dev/staff.js
+++ b/commands/dev/staff.js
@@ -28,9 +28,9 @@ module.exports = {
else {tu.staff = false; tu.admin = false; tu.developer = false;}
tu.save();
const logemb = (act) => new Discord.MessageEmbed()
- .setAuthor({name: `Staff ${act}`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `Staff ${act}`, iconURL: message.author.displayAvatarURL()})
.setDescription("A user's Staff status was updated.")
- .setThumbnail(person.avatarURL({size: 1024}))
+ .setThumbnail(person.displayAvatarURL({size: 1024}))
.addField("Name", person.username, true)
.addField("Developer", message.author.username, true)
.setColor("e8da3a")
diff --git a/commands/dev/support.js b/commands/dev/support.js
index fd423b4..4bf5f33 100644
--- a/commands/dev/support.js
+++ b/commands/dev/support.js
@@ -28,9 +28,9 @@ module.exports = {
else {tu.support = false; tu.staff = false; tu.admin = false; tu.developer = false;}
tu.save();
const logemb = (act) => new Discord.MessageEmbed()
- .setAuthor({name: `Support ${act}`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `Support ${act}`, iconURL: message.author.displayAvatarURL()})
.setDescription("A user's Support status was updated.")
- .setThumbnail(person.avatarURL({size: 1024}))
+ .setThumbnail(person.displayAvatarURL({size: 1024}))
.addField("Name", person.username, true)
.addField("Developer", message.author.username, true)
.setColor("e8da3a")
diff --git a/commands/dev/vip.js b/commands/dev/vip.js
index 356186b..652c11e 100644
--- a/commands/dev/vip.js
+++ b/commands/dev/vip.js
@@ -20,7 +20,7 @@ module.exports = {
if (!client.developers.includes(message.author.id) && !['check', 'c', 'view', 'v'].includes(args[0])) {return message.reply("Unfortunately, this is a **developer-only command**!");}
const GuildSettings = require('../../models/guild');
const logemb = (act) => new Discord.MessageEmbed()
- .setAuthor({name: `VIP Server ${act}`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `VIP Server ${act}`, iconURL: message.author.displayAvatarURL()})
.setDescription("A Server's VIP status was updated.")
.setThumbnail(message.guild.iconURL({size: 1024}))
.addField("Name", message.guild.name, true)
diff --git a/commands/fun/8ball.js b/commands/fun/8ball.js
index a39d78f..b327c3e 100644
--- a/commands/fun/8ball.js
+++ b/commands/fun/8ball.js
@@ -26,7 +26,7 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
return message.reply({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: "8ball Question", iconURL: message.author.avatarURL()})
+ .setAuthor({name: "8ball Question", iconURL: message.author.displayAvatarURL()})
.setDescription("**Question:** " + question + "\n**Answer:** " + responses[Math.floor(Math.random() * responses.length)])
.setColor("c375f0")
.setFooter({text: `Asked by ${name} | Natsuki`})
diff --git a/commands/fun/bite.js b/commands/fun/bite.js
index bef733a..ab8ed31 100644
--- a/commands/fun/bite.js
+++ b/commands/fun/bite.js
@@ -25,7 +25,7 @@ module.exports = {
if (!message.guild.members.cache.has(mention.id)) {return message.reply("That user is not in this server!");}
if (message.author.id === mention.id) {return message.reply("Ew quit tryna bite yourself, that's weird.");}
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} bites ${message.guild.members.cache.get(mention.id).displayName}`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} bites ${message.guild.members.cache.get(mention.id).displayName}`, iconURL: message.author.displayAvatarURL()})
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('d93846')
]});
@@ -33,7 +33,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new bite GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new bite GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/fun/deathnote.js b/commands/fun/deathnote.js
index 6e8f889..f08c883 100644
--- a/commands/fun/deathnote.js
+++ b/commands/fun/deathnote.js
@@ -8,17 +8,20 @@ const {TagFilter} = require('../../util/tagfilter');
const deaths = [
"watching too much anime", "an overdose of waifus", "Hypotakunemia", "trying to self-isekai",
- "Bass:tm:", "cranking the music just a little too loud", "trying to swim in lava", "an unknown cause",
+ "Bass:tm:", "cranking the music just a little too loud", "trying to swim in lava",
"Despacito", "something really cliche and unoriginal", "'shrooms",
"clicking 'I agree' without reading the Terms of Service", "alchemy", "rusty spoons",
"picking the wrong waifu", "body pillows", "fur-con", "something to do with lamb sauce",
- "grandma's cookies"
+ "grandma's cookies", "trying to get cat ears", "not reading the assembly instructions for that ikea furniture",
+ "the wrong kind of coke", "getting cancelled irl", "getting their credit card declined",
+ "finishing the last episode", "posting memes in #general", "stepping on a lego", "stubbing their toe",
+ "fork in toaster", "toasterbath", "signing this book without reading the cover", "being Kirby's dinner"
]; // a list of preset death methods that can occur
const before = [
"A name is being written...", "Someone will perish soon...", "A body is *about* to be discovered...",
- "{p} is scribbling something in their notebook...", "\*Manical laughter echoes around you*...",
- "{p} laughs maniacally..."
+ "{w} is scribbling something in their notebook...", "\*Manical laughter echoes around you*...",
+ "{w} laughs maniacally..."
]; // things it says before the response is sent
const responses = {
@@ -102,12 +105,12 @@ module.exports = {
let victim = options.victim && options.victim.length ? options.victim : message.mentions.members.first().displayName;
let killer = message.member;
- let pretext = before[Math.floor(Math.random() * before.length)].replace(/{p}/g, victim);
+ let pretext = before[Math.floor(Math.random() * before.length)].replace(/{w}/g, killer.displayName);
let note = await message.channel.send({embeds: [new Discord.MessageEmbed()
.setDescription(pretext)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
@@ -131,13 +134,13 @@ module.exports = {
}
let finalEmbed = new Discord.MessageEmbed()
- .setAuthor({name: title, iconURL: message.author.avatarURL()})
+ .setAuthor({name: title, iconURL: message.author.displayAvatarURL()})
.setDescription(`${text}${dns ? `\n\n_Their name is in your deathnote **${dns.against[mention.id] === 1 ? 'once' : `${dns.against[mention.id]} times`}.**_` : ''}`)
.setColor('c375f0')
.setFooter({text: `Natsuki${dns ? ` | ${dns.total} name${dns.total === 1 ? ' has been' : 's'} written in your deathnote!` : ''}`})
.setTimestamp();
- if (mention) {finalEmbed.setThumbnail(mention.avatarURL({size: 1024}));}
+ if (mention) {finalEmbed.setThumbnail(mention.displayAvatarURL({size: 1024}));}
return note.edit({embeds: [finalEmbed]});
}
diff --git a/commands/fun/marry.js b/commands/fun/marry.js
new file mode 100644
index 0000000..a225082
--- /dev/null
+++ b/commands/fun/marry.js
@@ -0,0 +1,88 @@
+const Discord = require('discord.js');
+
+const UserData = require('../../models/user');
+
+const ask = require("../../util/ask");
+
+module.exports = {
+ name: "marry",
+ meta: {
+ category: 'Fun',
+ description: "Marry someone to get some extra fun benefits!",
+ syntax: '`marry <@user|status|decline>`',
+ extra: null,
+ guildOnly: true
+ },
+ help: new Discord.MessageEmbed()
+ .setTitle("Help -> Marriage")
+ .setDescription("Marry another Natsuki user. They'll have to accept your marriage request for you to be able to marry them, though.")
+ .addField("Syntax", "`marry <@user|status|decline>`"),
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ if (!args.length) {return message.channel.send(`Syntax: \`${prefix}marry <@user|status|decline>\``);}
+ if (['s', 'status', 'v', 'view'].includes(args[0].toLowerCase())) {
+ const tu = await UserData.findOne({uid: message.author.id});
+ if (!tu || !tu.marriedTo) {return message.channel.send("You aren't married to anyone :(");}
+ else {return message.channel.send({embeds: [new Discord.MessageEmbed()
+ .setTitle("Marriage Status")
+ .setDescription(`<@${message.author.id}> is married to <@${tu.marriedTo}>!`)
+ .setColor('c375f0')
+ .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setTimestamp()
+ ]});}
+ } else if (['d', 'decline', 'r', 'reject'].includes(args[0].toLowerCase())) {
+ let requests = client.misc.cache.marriageRequests.filter(u => u === message.author.id);
+ if (!requests.size) {return message.channel.send("You don't have any people trying to marry you!");}
+ let ra = Array.from(requests.keys());
+ message.channel.send({embeds: [new Discord.MessageEmbed()
+ .setTitle("Current Marriage Requests")
+ .setDescription(ra.map((r, i) => `${i+1}. <@${r}>`).join("\n"))
+ .addField("Decline", "To decline someone's request, please reply with the number that corresponds to the person you'd like to decline.")
+ .setColor('c375f0')
+ .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setTimestamp()
+ ]});
+ try {
+ let res = await message.channel.awaitMessages({filter: (m) => m.author.id === message.author.id, max: 1, errors: ['time'], time: 60000});
+ res = res.first().content;
+ if (isNaN(Number(res))) {return message.channel.send("You must reply with a number!");}
+ res = Number(res);
+ if (res < 1 || res > ra.length + 1) {return message.channel.send("That number isn't in your list.");}
+ let person = ra[res-1];
+ let err = false;
+ await message.guild.members.fetch(person).catch(() => err = true);
+ if (err) {return message.channel.send("There was an error in trying to do that!");}
+ let conf = await ask(message, `Are you sure you want to decline ${client.utils.ps(message.guild.members.cache.get(person).displayName)} marriage request?`, 60000);
+ if (!conf) {return;}
+ if (!['y', 'yes', 'ye', 'sure', 'mhm'].includes(conf.toLowerCase())) {return message.channel.send("Okay, nevermind then!");}
+ client.misc.cache.marriageRequests.delete(person);
+ return message.channel.send("Request declined.");
+ } catch {return message.reply("That request timed out. Please try again.");}
+ } else {
+ if (!mention) {return message.channel.send("You have to mention the person you'd like to marry!");}
+ if (!message.guild.members.cache.has(mention.id)) {return message.channel.send("I can't find that user! Make sure they're in this server before trying to marry them, or go to a server they're in. If you're certain that person is in this server, then wait for them to come online and send a message first; that might help.");}
+ if (mention.id === client.user.id) {return message.channel.send("I'm actually already married! Well, I will be soon, to my girlfriend Tamaki. I love her very much <:NC_hearty:841489530413383712>");}
+ if (mention.bot) {return message.channel.send("Us bots aren't smart enough to respond to a marriage request and we're really too boring to wanna marry in the first place, so I'll just stop you in your tracks now.");}
+ if (mention.id === message.author.id) {return message.channel.send("ehe :sweat_smile: it doesn't work that way...");}
+ const tu = await UserData.findOne({uid: message.author.id}) || new UserData({uid: message.author.id});
+ if (tu.marriedTo) {return message.channel.send("Looks like you're already married to someone. Cheating, are we?");}
+ const ou = await UserData.findOne({uid: mention.id}) || new UserData({uid: mention.id});
+ if (ou.marriedTo) {return message.channel.send("Looks like that person is already in a relationship. Yikes, good luck with that.");}
+ if (client.misc.cache.marriageRequests.has(ou.uid) && client.misc.cache.marriageRequests.get(ou.uid) === message.author.id) {
+ tu.marriedTo = ou.uid; ou.marriedTo = tu.uid;
+ tu.markModified('marriedTo'); ou.markModified('marriedTo');
+ await tu.save(); await ou.save();
+ return message.channel.send({embeds: [new Discord.MessageEmbed()
+ .setTitle(`New Marriage!`)
+ .setDescription(`With the powers invested in me by Wubzy ~~and myself because I'm cool like that~~, I now pronounce ${message.member.displayName} and ${message.guild.members.cache.get(ou.uid).displayName} a married couple till debt and richer Discord users do you part.`)
+ .setColor('c375f0')
+ .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setTimestamp()
+ ]});
+ }
+ if (client.misc.cache.marriageRequests.has(message.author.id)) {return message.channel.send("You're already waiting on another marriage response.");}
+ if (client.misc.cache.marriageRequests.filter(u => u === ou.uid).size > 10) {return message.channel.send("*10 people are waiting on a response to marry this person. Yikes.*");}
+ client.misc.cache.marriageRequests.set(message.author.id, ou.uid);
+ return message.channel.send(`<@${ou.uid}>, you have a marriage request from ${message.member.displayName}. Send \`${prefix}marry @${message.member.displayName}\` to accept!`);
+ }
+ }
+};
\ No newline at end of file
diff --git a/commands/fun/nowplaying.js b/commands/fun/nowplaying.js
index 845aae3..b90d481 100644
--- a/commands/fun/nowplaying.js
+++ b/commands/fun/nowplaying.js
@@ -29,7 +29,7 @@ module.exports = {
stream.on('nowPlaying', t => {
clearTimeout(timeout);
message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: message.guild ? message.guild.members.cache.get(user.id) ? message.guild.members.cache.get(user.id).displayName : user.username : user.username, iconURL: user.avatarURL()})
+ .setAuthor({name: message.guild ? message.guild.members.cache.get(user.id) ? message.guild.members.cache.get(user.id).displayName : user.username : user.username, iconURL: user.displayAvatarURL()})
.setTitle(`${saves.get(user.id)} | Now Playing`)
.setDescription(`<@${user.id}> is currently listening to **${t.name}** by **${t.artist['#text']}**.\nView the song [here](${t.url}).`)
.setColor("c375f0")
diff --git a/commands/fun/rp.js b/commands/fun/rp.js
new file mode 100644
index 0000000..33f0d08
--- /dev/null
+++ b/commands/fun/rp.js
@@ -0,0 +1,181 @@
+const Discord = require('discord.js');
+
+const RP = require("../../models/rpch");
+const RPC = require('../../models/rpconfig');
+
+const {Tag} = require('../../util/tag');
+const {TagFilter} = require('../../util/tagfilter');
+const ask = require('../../util/ask');
+
+module.exports = {
+ name: "rp",
+ aliases: ['roleplay'],
+ meta: {
+ category: 'Fun',
+ description: "Add and edit characters for roleplaying",
+ syntax: '`rp `',
+ extra: null,
+ guildOnly: true
+ },
+ help: new Discord.MessageEmbed()
+ .setTitle("Help -> Roleplay Characters")
+ .setDescription("Add and edit characters to roleplay with!")
+ .addField("Syntax", "`rp `"),
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ if (!args.length) {return message.channel.send(`Syntax: \`${prefix}rp \``);}
+ if (['add', 'a', 'n', 'new'].includes(args[0].toLowerCase())) {
+ let tags = true;
+ let options = new TagFilter([
+ new Tag(['i', 'img', 'image', 'pfp', 'thumbnail', 't', 'thumb'], 'image', 'append'),
+ new Tag(['n', 'name'], 'name', 'append'),
+ new Tag(['p', 'prefix'], 'prefix', 'append')
+ ]).test(args.join(" "));
+ if (!options.image || !options.name || !options.prefix) {
+ tags = false;
+ const name = await ask(message, "What is the character's name?", 60000, false, undefined, true); if (!name) {return;}
+ if (name.length > 50) {return message.channel.send("That name is a little too long.");}
+ options.name = name;
+
+ let prefix = await ask(message, "What is the character's prefix? This is how you will use the character.", 60000, false, undefined, true); if (!prefix) {return;}
+ if (prefix.length > 8) {return message.channel.send("Your prefix should be less than 8 characters.");}
+ if (!prefix.match(/^[a-zA-Z0-9-_]+$/)) {return message.channel.send("Your prefix must contain only alphanumeric characters.");}
+ options.prefix = prefix.toLowerCase();
+
+ let imp = await message.channel.send("Please send an image for the character's profile picture. **Do not** send NSFW.");
+ try {
+ const im = await message.channel.awaitMessages({filter: m => m.author.id === message.author.id, time: 60000, max: 1, errors: ['time']});
+ imp.delete().catch(() => {});
+ if (!im.first().attachments.size) {return message.channel.send("You must directly upload an image to use for the profile picture.");}
+ options.image = im.first().attachments.first().url;
+ }
+ catch {imp.delete().catch(() => {}); return message.reply("Your character creation timed out.");}
+ } else {
+ if (options.prefix.length > 8) {return message.channel.send("Your prefix should be less than 8 characters.");}
+ if (!options.prefix.match(/^[a-zA-Z0-9-_]+$/)) {return message.channel.send("Your prefix must contain only alphanumeric characters.");}
+ }
+
+ if (!options.image.startsWith('https://cdn.discordapp.com/attachments/')) {return message.channel.send(tags ? "You must provide a cdn.discordapp.com link." : "It seems you didn't upload an image, or there was an error on my side. If the problem persists, please contact my developers.");}
+ if (options.image.length > 350) {return message.channel.send("That image URL is a little too long.");}
+
+ let rp = await RP.findOne({uid: message.author.id}) || new RP({uid: message.author.id});
+ if (rp.chars[options.prefix]) {return message.channel.send("You already have a character with that prefix. Please try again with a different prefix.");}
+ if (Object.keys(rp.chars).length >= 20) {return message.channel.send("The current maximum of characters is 20, and you've reached that maximum. Sorry!");}
+ rp.chars[options.prefix] = options;
+ rp.markModified(`chars.${options.prefix}`);
+ rp.save();
+
+ return message.channel.send(`${options.name} has been added successfully to your characters list. To use this character, you'll need to be in a channel that is RP-enabled. \`${options.prefix}: \``);
+ } else if (['list', 'l'].includes(args[0].toLowerCase())) {
+ let rp = await RP.findOne({uid: message.author.id});
+ if (!rp) {return message.channel.send("You don't have any characters made!");}
+ let n = message.member ? message.member.displayName : message.author.username;
+ return message.channel.send({embeds: [new Discord.MessageEmbed()
+ .setAuthor({name: `${n}${n.endsWith('s') ? "'" : "'s"} RP Characters`, iconURL: (message.member || message.author).displayAvatarURL({dynamic: true})})
+ .setDescription(Object.keys(rp.chars).map(ch => `\`${ch}\`: ${rp.chars[ch].name}`).join(', '))
+ .setColor('c375f0')
+ .setFooter({text: "Natsuki"})
+ .setTimestamp()
+ ]});
+ } else if (['view', 'v'].includes(args[0].toLowerCase())) {
+ let rp = await RP.findOne({uid: message.author.id});
+ if (!rp) {return message.channel.send("You don't have any characters made!");}
+ if (!args[1] || !rp.chars[args[1].toLowerCase()]) {return message.channel.send("You don't have a character with that prefix.");}
+ let ch = rp.chars[args[1]];
+ let n = message.member ? message.member.displayName : message.author.username;
+ return message.channel.send({embeds: [new Discord.MessageEmbed()
+ .setAuthor({name: `${n}${n.endsWith('s') ? "'" : "'s"} RP Character`, iconURL: (message.member || message.author).displayAvatarURL({dynamic: true})})
+ .setTitle(ch.name)
+ .setColor('c375f0')
+ .setFooter({text: "Natsuki"})
+ .setImage(ch.image)
+ .setTimestamp()
+ ]});
+ } else if (['edit', 'e'].includes(args[0].toLowerCase())) {
+ const rp = await RP.findOne({uid: message.author.id});
+ if (!rp || !Object.keys(rp.chars).length) {return message.channel.send("You don't have any characters to edit.");}
+ if (!args[1]) {return message.channel.send("You must provide the prefix of a character to edit!");}
+ if (!rp.chars[args[1].toLowerCase()]) {return message.channel.send("A character with that prefix doesn't exist.");}
+ let char = rp.chars[args[1].toLowerCase()];
+
+ if (!args[2]) {return message.channel.send(`Syntax: \`${prefix}rp edit \``);}
+
+ if (['p', 'prefix'].includes(args[2].toLowerCase())) {
+ let old = char.prefix;
+ let prefix;
+ if (!args[3]) {
+ prefix = await ask(message, "What prefix would you like to set?", 60000);
+ if (!prefix) {return;}
+ } else {prefix = args[3];}
+ prefix = prefix.toLowerCase();
+ if (prefix.length > 8) {return message.channel.send("Your prefix should be less than 8 characters.");}
+ if (!prefix.match(/^[a-zA-Z0-9-_]+$/)) {return message.channel.send("Your prefix must contain only alphanumeric characters.");}
+ if (prefix === old) {return message.channel.send("That's the same prefix you already had, silly!");}
+ char.prefix = prefix;
+ delete rp.chars[old];
+ rp.chars[prefix] = char;
+ ['chars', `chars.${old}`, `chars.${prefix}`].forEach(x => rp.markModified(x));
+ rp.save();
+ return message.channel.send("Prefix saved!");
+ } else if (['i', 'image', 'img'].includes(args[2].toLowerCase())) {
+ let image;
+ if (!args[3]) {
+ image = await ask(message, "What image would you like to set?", 60000);
+ if (!image) {return;}
+ } else {image = args[3];}
+ if (!image.startsWith('https://cdn.discordapp.com/attachments/')) {return message.channel.send("You must provide a cdn.discordapp.com link.");}
+ if (image.length > 350) {return message.channel.send("That image URL is a little too long.");}
+ rp.chars[char.prefix].image = image;
+ rp.markModified(`chars.${char.prefix}`);
+ rp.save();
+ return message.channel.send("Image saved!");
+ } else if (['n', 'name'].includes(args[2].toLowerCase())) {
+ args = args.slice(3);
+ let name;
+ if (!args[0]) {
+ name = await ask(message, "What name would you like to set?", 60000);
+ if (!name) {return;}
+ } else {name = args.join(" ");}
+ if (name.length > 50) {return message.channel.send("That name is a little too long.");}
+ rp.chars[char.prefix].name = name;
+ rp.markModified(`chars.${char.prefix}`);
+ rp.save();
+ return message.channel.send("Name saved!");
+ } else {return message.channel.send(`Invalid arg! Syntax: \`${prefix}rp edit \``);}
+ } else if (['delete', 'd'].includes(args[0].toLowerCase())) {
+ const rp = await RP.findOne({uid: message.author.id});
+ if (!rp || !Object.keys(rp.chars).length) {return message.channel.send("You don't have any characters to delete.");}
+ if (!args[1]) {return message.channel.send("You must provide the prefix of a character to delete!");}
+ if (!rp.chars[args[1].toLowerCase()]) {return message.channel.send("A character with that prefix doesn't exist.");}
+ let char = rp.chars[args[1].toLowerCase()];
+ let conf = await ask(message, `Are you sure you want to delete ${char.name}?`, 60000);
+ if (!conf) {return;}
+ if (!['yes', 'y', 'sure', 'mhm', 'ye'].includes(conf.toLowerCase())) {return message.channel.send("Okay, I won't do anything then.");}
+ delete rp.chars[char.prefix];
+ rp.markModified(`chars.${char.prefix}`);
+ rp.save();
+ return message.channel.send("I've deleted that character for you.");
+ } else if (['enable', 'en'].includes(args[0].toLowerCase())) {
+ if (!message.guild) {return message.channel.send("You must be in a server in order to enable RP character usage for a specific channel.");}
+ if (!message.member.permissionsIn(message.channel.id).has("MANAGE_WEBHOOKS")) {return message.channel.send("You must have permissions to edit webhooks here in order to do that.");}
+ if (!message.guild.me.permissions.has("MANAGE_WEBHOOKS")) {return message.channel.send("I don't have permissions to manage webhooks in this server.");}
+ if (!message.guild.me.permissionsIn(message.channel.id).has("MANAGE_WEBHOOKS")) {return message.channel.send("I don't have the permissions to edit webhooks in this channel.");}
+ const webhooks = await message.channel.fetchWebhooks();
+ if (webhooks.find(wh => wh.token)) {return message.channel.send("It would seem RP is already enabled in this channel. If it's not working in this channel, please contact my developers.");}
+ try {
+ return message.channel.createWebhook("Natsuki RP Webhook", {avatar: client.user.avatarURL({size: 2048})})
+ .then(async () => {
+ const config = await RPC.findOne({gid: message.guild.id}) || new RPC({gid: message.guild.id});
+ config.channels.push(message.channel.id);
+ config.markModified('channels');
+ if (!client.misc.cache.rp.has(message.guild.id)) {client.misc.cache.rp.set(message.guild.id, []);}
+ client.misc.cache.rp.get(message.guild.id).push(message.channel.id);
+ config.save();
+ return message.channel.send("RP features were successfully enabled in this channel.");
+ })
+ .catch(message.channel.send("There was an error doing that. Please make sure my permissions are properly set in this channel and try again. If the error persists, please contact my developers."));
+ } catch {return message.channel.send("There was an error doing that. Please make sure my permissions are properly set in this channel and try again. If the error persists, please contact my developers.");}
+ }
+
+ return message.channel.send(`Invalid arg! Syntax: \`${prefix}rp \``);
+ }
+};
\ No newline at end of file
diff --git a/commands/fun/secretsanta.js b/commands/fun/secretsanta.js
index 7fcd721..67e152a 100644
--- a/commands/fun/secretsanta.js
+++ b/commands/fun/secretsanta.js
@@ -78,11 +78,11 @@ module.exports = {
return dmch.send({embeds: [new Discord.MessageEmbed()
.setTitle("Secret Santa Created!")
.setDescription("Your Secret Santa has been completed! Have your members join by using `n?secretsanta join ` where the ID is the ID displayed below. You can start your secret santa when you have at least 3 members with `n?secretsanta start `. If someone joins that you don't want in your secret santa, use `n?secretsanta kick <@member|userID>`. If you want to also participate, just join the same way as everyone else.")
- .setThumbnail(message.author.avatarURL({size: 1024}))
+ .setThumbnail(message.author.displayAvatarURL({size: 1024}))
.addField("ID", `\`${id}\``, true)
.addField("Owner", message.author.username, true)
.setColor("01bd2f")
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
@@ -117,7 +117,7 @@ module.exports = {
.addField("Owner", o.username, true)
.addField("Members", `${tss.members ? tss.members.length : 0}`, true)
.setColor("01bd2f")
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
diff --git a/commands/fun/slap.js b/commands/fun/slap.js
index cc05d17..0057e16 100644
--- a/commands/fun/slap.js
+++ b/commands/fun/slap.js
@@ -31,7 +31,7 @@ module.exports = {
slaps.markModified(`against.${mention.id}`);
slaps.save();
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} slaps ${message.guild.members.cache.get(mention.id).displayName}`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} slaps ${message.guild.members.cache.get(mention.id).displayName}`, iconURL: message.author.displayAvatarURL()})
.setDescription(`That makes slap **#${slaps.against[mention.id]}** from you to them!`)
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('d93846')
@@ -41,7 +41,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new slap GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new slap GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/leveling/chests.js b/commands/leveling/chests.js
index 2626b49..f1320e5 100644
--- a/commands/leveling/chests.js
+++ b/commands/leveling/chests.js
@@ -22,9 +22,8 @@ module.exports = {
async execute(message, msg, args, cmd, prefix, mention, client) {
if (!message.member.permissions.has("ADMINISTRATOR")) {return message.channel.send("You must have administrator permissions in order to edit these settings.");}
if (!args.length) {args[0] = 'enable';}
-
if (['e', 'enable'].includes(args[0].toLowerCase())) {
- if (client.misc.cache.chests.includes(message.guild.id)) {return message.channel.send("This server already has chest spawning enabled.")};
+ if (client.misc.cache.chests.enabled.includes(message.guild.id)) {return message.channel.send("This server already has chest spawning enabled.")};
try {
am = await message.channel.send("Would you like to have me send chests to a specific channel?");
await am.react('👍');
@@ -43,13 +42,13 @@ module.exports = {
}
let c = new Chests({gid: message.guild.id, channel: chestCh});
c.save();
- client.misc.cache.chests.push(message.guild.id);
+ client.misc.cache.chests.enabled.push(message.guild.id);
return message.channel.send({embeds: [new Discord.MessageEmbed()
.setTitle("Chest Spawning Enabled!")
.setThumbnail(message.guild.iconURL({size: 2048}))
.setDescription(`Your server now has its chest spawning enabled! Chests will spawn in ${chestCh.length ? `<#${chestCh}>` : 'any channel'}.`)
.setColor("c375f0")
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
});
diff --git a/commands/leveling/claim.js b/commands/leveling/claim.js
new file mode 100644
index 0000000..a6d6f87
--- /dev/null
+++ b/commands/leveling/claim.js
@@ -0,0 +1,29 @@
+const Discord = require('discord.js');
+
+module.exports = {
+ name: "claim",
+ aliases: [],
+ meta: {
+ category: 'Leveling',
+ description: "Claim a chest that has spawned in the channel",
+ syntax: '`claim [specialText]`',
+ extra: null,
+ guildOnly: true
+ },
+ help: "Claim a chest that has spawned in the channel. You must be in the same channel as the chest in order to claim it.",
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ if (!client.misc.cache.chests.enabled.includes(message.guild.id)) {return message.channel.send("Chests aren't enabled in this server!");}
+ if (!client.misc.cache.chests.waiting.has(message.channel.id)) {return message.channel.send("There are no chests to claim in this channel.");}
+ if (!client.misc.cache.monners[message.author.id]) {return message.channel.send(`There was an issue on my side with claiming your chest. This happened because I don't have your ${message.misc.mn} info cached, so send a message anywhere and then try again. Sorry!`);}
+
+ let chest = client.misc.cache.chests.waiting.get(message.channel.id);
+ client.misc.cache.monners[message.author.id] += chest.amount;
+ client.misc.cache.chests.waiting.delete(message.channel.id);
+ chest.message.delete().catch(() => {});
+ return message.channel.send({embeds: [new Discord.MessageEmbed()
+ .setAuthor({name: message.member.displayName, iconURL: message.member.displayAvatarURL()})
+ .setDescription(`You've claimed ${client.utils.an(chest.rarity.name, true)} Chest with **${chest.amount} ${message.misc.mn}<:monners:926736756047495218>**`)
+ .setColor(chest.rarity.color)
+ ]}).catch(() => {});
+ }
+};
\ No newline at end of file
diff --git a/commands/leveling/daily.js b/commands/leveling/daily.js
index 17888bb..1c4459a 100644
--- a/commands/leveling/daily.js
+++ b/commands/leveling/daily.js
@@ -20,22 +20,22 @@ module.exports = {
async execute(message, msg, args, cmd, prefix, mention, client) {
let tm = await Monners.findOne({uid: message.author.id}) || new Monners({uid: message.author.id});
if (!client.misc.cache.monners[message.author.id]) {client.misc.cache.monners[message.author.id] = tm.currency;}
- if (tm.daily && tm.daily.last && ((new Date().getTime() - tm.daily.last) < (1000 * 60 * 60 * 24))) {
+ if (tm.daily && tm.daily.last && ((new Date().getTime() - tm.daily.last) < (1000 * 60 * 60 * 22))) {
return message.channel.send({embeds: [new Discord.MessageEmbed()
.setAuthor({iconURL: message.guild ? message.member.displayAvatarURL() : message.author.iconURL(), name: message.guild ? message.member.displayName : message.author.username})
- .setDescription(`Your daily is not available yet! You can claim your next daily in **${moment.preciseDiff(new Date().getTime(), tm.daily.last + (1000 * 60 * 60 * 24))}**`)
+ .setDescription(`Your daily is not available yet! You can claim your next daily in **${moment.preciseDiff(new Date().getTime(), tm.daily.last + (1000 * 60 * 60 * 22))}**`)
.setColor('c92a45')
]});
}
if (!tm.daily || !Object.keys(tm.daily).length) {tm.daily = {total: 0, last: new Date().getTime(), streak: 0};}
let streakIncrease = false;
- if (new Date().getTime() - tm.daily.last < (1000 * 60 * 60 * 36)) {
+ if (new Date().getTime() - tm.daily.last < (1000 * 60 * 60 * 47)) {
streakIncrease = true;
tm.daily.streak++
} else {tm.daily.streak = 1;}
tm.daily.total++;
tm.daily.last = new Date().getTime();
- let bonus = (75 + (tm.daily.streak * 45) + Math.floor(Math.random() * (15 + (tm.daily.streak * 2))));
+ let bonus = (75 + (tm.daily.streak * (15 + Math.floor(Math.random() * 20))) + Math.floor(Math.random() * (15 + (tm.daily.streak * 2))));
client.misc.cache.monners[message.author.id] += bonus;
tm.markModified('daily');
['streak', 'last', 'total'].forEach(x => {tm.markModified(`daily.${x}`);});
@@ -44,7 +44,7 @@ module.exports = {
.setAuthor({iconURL: message.guild ? message.member.displayAvatarURL() : message.author.iconURL(), name: message.guild ? message.member.displayName : message.author.username})
.setDescription(`You've claimed today's daily!`)
.addField("Streak", streakIncrease ? `Your streak has **increased** to **${tm.daily.streak}**` : 'Your streak has **reset** to **1**.', true)
- .addField("Bonus Monners", `<:monners:926736756047495218> ${bonus}`, true)
+ .addField(`Bonus ${message.misc.mn}`, `<:monners:926736756047495218> ${bonus}`, true)
.addField("Total Dailies Claimed", `${tm.daily.total}`)
.setColor('c375f0')
]});
diff --git a/commands/leveling/levelrole.js b/commands/leveling/levelrole.js
index 2f6cc34..a2c121c 100644
--- a/commands/leveling/levelrole.js
+++ b/commands/leveling/levelrole.js
@@ -35,7 +35,7 @@ module.exports = {
if (!role) {return message.channel.send("I can't find that role!");}
role = role.id;
let lr = await LR.findOne({gid: message.guild.id}) || new LR({gid: message.guild.id});
- if (Object.keys(lr.roles).length >= 10) {return message.channel.send("Due to data storage concerns, you can only have 10 level roles in this server. If you believe you need more, come to the support server and talk to my devs and see if they would be willing to raise this requirement for you.");}
+ if (Object.keys(lr.roles).length >= 20) {return message.channel.send("Due to data storage concerns, you can only have 20 level roles in this server. If you believe you need more, come to the support server and talk to my devs and see if they would be willing to raise this requirement for you.");}
lr.roles[level] = role;
lr.markModified(`roles.${level}`);
lr.save();
@@ -64,7 +64,7 @@ module.exports = {
.setThumbnail(message.guild.iconURL({size: 2048}))
.setDescription(s)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
diff --git a/commands/leveling/namemonners.js b/commands/leveling/namemonners.js
new file mode 100644
index 0000000..1621217
--- /dev/null
+++ b/commands/leveling/namemonners.js
@@ -0,0 +1,41 @@
+const Discord = require('discord.js');
+
+const Saves = require('../../models/saves');
+
+module.exports = {
+ name: "namemonners",
+ aliases: ['namemon', 'nm'],
+ meta: {
+ category: 'Leveling',
+ description: "Rename the currency for your server",
+ syntax: '`namemonners `',
+ extra: null,
+ guildOnly: true
+ },
+ help: new Discord.MessageEmbed()
+ .setTitle("Help -> Monners Naming")
+ .setDescription("Rename the Monners for your server. This merely a cosmetic effect. Monners gains will remain global regardless.")
+ .addField("Notice", "You must be an administrator in the server in order to edit these settings.")
+ .addField("Syntax", "`namemonners `"),
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ if (!args.length) {return message.channel.send(`Syntax: \`${prefix}namemonners \``);}
+ if (!message.member.permissions.has("ADMINISTRATOR")) {return message.channel.send("You must be an administrator in this server in order to do that.");}
+ let name = args.join(" ");
+ const names = await Saves.findOne({name: 'monnersnames'});
+ const nsaves = names.saves;
+ if (name.toLowerCase() === 'clear') {
+ nsaves.delete(message.guild.id);
+ client.misc.cache.monnersNames.delete(message.guild.id);
+ message.channel.send("I'll now refer to currency in this server as Monners again.");
+ } else {
+ if (name.length > 12) {return message.channel.send("That name is too long! Keep it short and simple.");}
+ if (name.match(//gm)) {return message.channel.send("You can't have an emoji in your monners name.");}
+ if (!name.match(/^[a-zA-Z0-9-]+$/gm)) {return message.channel.send("Your name must contain only alphanumeric characters.");}
+ nsaves.set(message.guild.id, name);
+ client.misc.cache.monnersNames.set(message.guild.id, name);
+ message.channel.send(`Cool. I'll refer to Monners in this server as "${name}" now.`);
+ }
+ names.saves = nsaves;
+ return await names.save();
+ }
+};
\ No newline at end of file
diff --git a/commands/leveling/setupleveling.js b/commands/leveling/setupleveling.js
index 0532a31..7ddf572 100644
--- a/commands/leveling/setupleveling.js
+++ b/commands/leveling/setupleveling.js
@@ -38,7 +38,7 @@ module.exports = {
.setThumbnail(message.guild.iconURL({size: 2048}))
.setDescription(`Your server now has its leveling system enabled! If you enabled level up messages, you can set the channel for that using \`${prefix}levelchannel\`.\n\nAll members of your server will now gain XP as they talk. I'm a smart cookie, so don't try spamming. It won't work. Every member can gain more XP once per minute, no matter how many messages they send in that one minute.\n\nIf you want to see your level and how much more XP you need to level up, run \`${prefix}stats\`.`)
.setColor("c375f0")
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
});
diff --git a/commands/leveling/stats.js b/commands/leveling/stats.js
index da059ca..818b6db 100644
--- a/commands/leveling/stats.js
+++ b/commands/leveling/stats.js
@@ -53,17 +53,16 @@ module.exports = {
.setDescription("View your level and XP in the server, or someone else's")
.addField("Syntax", "`stats [@user|userID]`"),
async execute(message, msg, args, cmd, prefix, mention, client) {
- if (!client.misc.cache.lxp.enabled.includes(message.guild.id)) {return message.channel.send("Your server doesn't have leveling enabled!");}
let u = args[0] ? (message.mentions.members.first() || message.guild.members.cache.get(args[0])) : message.member;
if (!u) {return message.channel.send("I can't find that user!");}
- let xp;
+ let xp; let hasXp = true;
if (!client.misc.cache.lxp.xp[message.guild.id] || !client.misc.cache.lxp.xp[message.guild.id][u.id]) {
let txp = await LXP.findOne({gid: message.guild.id});
- if (!txp) {return message.channel.send("Your server doesn't have leveling enabled!");}
- if (!txp.xp[u.id]) {return message.channel.send(`${u.id === message.author.id ? "You" : "That user"} doesn't have any leveling info available!`);}
- xp = {xp: txp.xp[u.id][0], level: txp.xp[u.id][1]};
- } else {xp = client.misc.cache.lxp.xp[message.guild.id][u.id];}
+ if (!txp) {hasXp = false;}
+ else {if (txp.xp[u.id]) {xp = {xp: txp.xp[u.id][0], level: txp.xp[u.id][1]};}}
+ } else if (hasXp) {xp = client.misc.cache.lxp.xp[message.guild.id][u.id];}
let tmoon = client.misc.cache.monners[u.id] ? {currency: client.misc.cache.monners[u.id]} : await Monners.findOne({uid: u.id});
+ if (!tmoon) {return message.channel.send("There was an error getting your level and Monners information. Try again?");}
let tcur = tmoon ? tmoon.currency : 0;
if (!message.channel.permissionsFor(message.guild.me.id).has("ATTACH_FILES")) {
return message.channel.send({embeds: [new Discord.MessageEmbed()
@@ -71,8 +70,8 @@ module.exports = {
.setDescription("Local leveling stats")
.addField("Level", `${xp.level}`, true)
.addField("XP", `**${xp.xp}** of **${Math.ceil(100 + (((xp.level / 3) ** 2) * 2))}** needed to level up`, true)
- .addField("Monners", `<:monners:926736756047495218> ${tcur}`)
- .setThumbnail(client.users.cache.get(u.id).avatarURL({size: 2048}))
+ .addField(`${message.misc.mn}`, `<:monners:926736756047495218> ${tcur}`)
+ .setThumbnail(client.users.cache.get(u.id).displayAvatarURL({size: 2048}))
.setColor("c375f0")
.setFooter({text: "Natsuki"})
.setTimestamp()
@@ -94,9 +93,9 @@ module.exports = {
ctx.fillStyle = '#ffffff';
ctx.fillText(`${u.displayName}${u.displayName.toLowerCase().endsWith('s') ? "'" : "'s"} Stats`, canvas.width / 2.8, canvas.height / 2);
- ctx.font = applyText(120, canvas, `${xp.xp} / ${Math.ceil(100 + (((xp.level / 3) ** 2) * 2))} | Level ${xp.level}`); //top text
+ ctx.font = applyText(120, canvas, xp ? `${xp.xp} / ${Math.ceil(100 + (((xp.level / 3) ** 2) * 2))} | Level ${xp.level}` : "Leveling N/A"); //top text
ctx.fillStyle = '#ffffff';
- ctx.fillText(`${xp.xp} / ${Math.ceil(100 + (((xp.level / 3) ** 2) * 2))} | Level ${xp.level}`, canvas.width / 2.8, canvas.height / 3.2);
+ ctx.fillText(xp ? `${xp.xp} / ${Math.ceil(100 + (((xp.level / 3) ** 2) * 2))} | Level ${xp.level}` : "Leveling N/A", canvas.width / 2.8, canvas.height / 3.2);
const monnersImage = await Canvas.loadImage('https://cdn.discordapp.com/emojis/926736756047495218');
ctx.drawImage(monnersImage, canvas.width / 2.8, (canvas.height / 1.53) - 11, 58, 60); //draw monners icon
@@ -104,16 +103,18 @@ module.exports = {
ctx.fillText(`${tcur}`, (canvas.width / 2.8) + 70, (canvas.height / 1.53) + 57 - 20);
ctx.fillText(` | `, (canvas.width / 2.8) + 70 + ctx.measureText(`${tcur}`).width, (canvas.height / 1.53) + 57 - 24); // draw monners amount
let monnersWidth = ctx.measureText(`${tcur} | `).width + 75; //get width of monners text and icon to account for bar size later
-
- //draw the bar borders
- ctx.strokeStyle = '#ffffff';
- ctx.strokeWidth = 6;
- roundRect(ctx, (canvas.width / 2.8) + monnersWidth, canvas.height / 1.53, canvas.width - (canvas.width / 2.8) - monnersWidth - 80, 40, 10, false, true, false);
- //set a clipping area to keep the bar filler inside the rounded borders
- roundRect(ctx, (canvas.width / 2.8) + monnersWidth, canvas.height / 1.53, canvas.width - (canvas.width / 2.8) - monnersWidth - 80, 40, 10, false, false, true);
- ctx.fillStyle = '#4aa4e0c8';
- //draw the bar filler
- ctx.fillRect((canvas.width / 2.8) + monnersWidth, canvas.height / 1.53, (xp.xp / Math.ceil(100 + (((xp.level / 3) ** 2) * 2))) * (canvas.width - (canvas.width / 2.8) - monnersWidth - 80), 40);
+
+ if (xp) {
+ //draw the bar borders
+ ctx.strokeStyle = '#ffffff';
+ ctx.strokeWidth = 6;
+ roundRect(ctx, (canvas.width / 2.8) + monnersWidth, canvas.height / 1.53, canvas.width - (canvas.width / 2.8) - monnersWidth - 80, 40, 10, false, true, false);
+ //set a clipping area to keep the bar filler inside the rounded borders
+ roundRect(ctx, (canvas.width / 2.8) + monnersWidth, canvas.height / 1.53, canvas.width - (canvas.width / 2.8) - monnersWidth - 80, 40, 10, false, false, true);
+ ctx.fillStyle = '#4aa4e0c8';
+ //draw the bar filler
+ ctx.fillRect((canvas.width / 2.8) + monnersWidth, canvas.height / 1.53, (xp.xp / Math.ceil(100 + (((xp.level / 3) ** 2) * 2))) * (canvas.width - (canvas.width / 2.8) - monnersWidth - 80), 40);
+ }
message.channel.send({files: [new Discord.MessageAttachment(canvas.toBuffer(), 'xp-stats.png')]});
}
diff --git a/commands/leveling/streak.js b/commands/leveling/streak.js
new file mode 100644
index 0000000..0b62601
--- /dev/null
+++ b/commands/leveling/streak.js
@@ -0,0 +1,26 @@
+const Discord = require('discord.js');
+
+const Monners = require("../../models/monners");
+
+module.exports = {
+ name: "streak",
+ aliases: [],
+ meta: {
+ category: 'Leveling',
+ description: "View yours or someone else's daily streak.",
+ syntax: '`streak [@user]`',
+ extra: null
+ },
+ help: "View your streak, or mention someone else to view theirs.",
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ const tm = await Monners.findOne({uid: mention ? mention.id : message.author.id});
+ return message.channel.send(tm ? {embeds: [
+ new Discord.MessageEmbed()
+ .setAuthor({name: "Daily Streak", iconURL: mention ? mention.displayAvatarURL() : message.author.displayAvatarURL()})
+ .setDescription(`${mention ? "That user's" : "Your"} streak is **${tm.daily.streak}**.`)
+ .setFooter({text: "Natsuki"})
+ .setColor("c375f0")
+ .setTimestamp()
+ ]} : `${mention ? "That user doesn't" : "You don't"} have a streak yet!`);
+ }
+};
\ No newline at end of file
diff --git a/commands/misc/ar.js b/commands/misc/ar.js
index beabbfb..e69cc13 100644
--- a/commands/misc/ar.js
+++ b/commands/misc/ar.js
@@ -72,7 +72,7 @@ module.exports = {
.setTitle("Auto-Responses in this Server")
.setDescription(string)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp();
if (mode) {embed.addField(mode === 'edit' ? "Editing" : 'Deletion', `Please say the **number** of the AR you wish to ${mode}.`);}
let r = await message.channel.send({embeds: [embed]});
diff --git a/commands/misc/avatar.js b/commands/misc/avatar.js
index e76b9cb..fa2113a 100644
--- a/commands/misc/avatar.js
+++ b/commands/misc/avatar.js
@@ -1,6 +1,8 @@
const Discord = require('discord.js');
+
const {Tag} = require('../../util/tag');
const {TagFilter} = require('../../util/tagfilter');
+const {Pagination} = require('../../util/pagination');
module.exports = {
name: "avatar",
@@ -13,21 +15,38 @@ module.exports = {
extra: null
},
async execute(message, msg, args, cmd, prefix, mention, client) {
- let member = args.length ? (mention || client.users.cache.get(args[0]) || message.author) : message.author;
+ let fail = false;
+ let member = args.length && !fail ? (mention || client.users.cache.get(args[0]) || message.author) : message.author;
+ await client.users.fetch(member.id, {force: true}).catch(() => fail = true);
+ if (message.guild) {message.guild.members.fetch(member.id, {force: true});}
let name = message.guild ? message.guild.members.cache.get(member.id).displayName : member.username;
let options = new TagFilter([
new Tag(['small', 's', 'mini', 'm'], 'small', 'toggle'),
- new Tag(['verysmall', 'vsmall', '-vs', 'xs'], 'vsmall', 'toggle')
+ new Tag(['verysmall', 'vsmall', '-vs', 'xs'], 'vsmall', 'toggle'),
+ new Tag(['g', 'global', 'user', 'u'], 'global', 'toggle'),
+ new Tag(['b', 'both'], 'both', 'toggle')
]).test(args.join(" "));
try {
- let avem = new Discord.MessageEmbed()
- .setTitle(`${name.endsWith('s') ? `${name}'` : `${name}'s`} Avatar`)
- .setImage(message.guild ? message.guild.members.cache.get(member.id).displayAvatarURL({size: options.vsmall ? 128 : options.small ? 256 : 2048, dynamic: true, format: "png"}) : member.displayAvatarURL({size: options.vsmall ? 128 : options.small ? 256 : 2048, dynamic: true, format: "png"}))
- .setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
- if (!options.vsmall) {avem.setTimestamp();}
- return message.channel.send({embeds: [avem]});
+ if (options.both && message.guild ? member.displayAvatarURL({size: 2048, dynamic: true, format: 'png'}) !== message.guild.members.cache.get(member.id).displayAvatarURL({size: 2048, dynamic: true, format: 'png'}) : false) {
+ const pag = new Pagination(message.channel, [message.guild.members, client.users]
+ .map(source => source.cache.get(member.id).displayAvatarURL({size: options.vsmall ? 128 : options.small ? 256 : 2048, dynamic: true, format: "png"}))
+ .map((avatar, index) => new Discord.MessageEmbed()
+ .setTitle(`${name.endsWith('s') ? `${name}'` : `${name}'s`} ${['Server', 'Global'][index]} Avatar`)
+ .setImage(avatar)
+ .setColor('c375f0')
+ ), message, client
+ );
+ return await pag.start({user: message.author.id, time: 60000});
+ } else {
+ let avem = new Discord.MessageEmbed()
+ .setTitle(`${name.endsWith('s') ? `${name}'` : `${name}'s`} Avatar`)
+ .setImage(message.guild ? (options.global ? client.users : message.guild.members).cache.get(member.id).displayAvatarURL({size: options.vsmall ? 128 : options.small ? 256 : 2048, dynamic: true, format: "png"}) : member.displayAvatarURL({size: options.vsmall ? 128 : options.small ? 256 : 2048, dynamic: true, format: "png"}))
+ .setColor('c375f0')
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
+ if (!options.vsmall) {avem.setTimestamp();}
+ return message.channel.send({embeds: [avem]});
+ }
} catch (e) {console.error(e); return message.reply("Hmm, there seems to have been an error while I tried to show you that user's avatar.");}
}
};
\ No newline at end of file
diff --git a/commands/misc/commands.js b/commands/misc/commands.js
index 930de10..c7ecaf5 100644
--- a/commands/misc/commands.js
+++ b/commands/misc/commands.js
@@ -17,7 +17,7 @@ module.exports = {
.setTitle("Commands")
.setDescription(`You can use \`${prefix}help\` on any command to get more help on it.`)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp();
categories.forEach(category => ce.addField(category, Array.from(client.commands.values()).filter(command => command.meta ? command.meta.category === category : category === "Uncategorized").map(cmd => `\`${cmd.name}\``).join(', ')));
return message.channel.send({embeds: [ce]});
diff --git a/commands/misc/emoji.js b/commands/misc/emoji.js
index 675317c..9b8877e 100644
--- a/commands/misc/emoji.js
+++ b/commands/misc/emoji.js
@@ -34,7 +34,7 @@ module.exports = {
.setDescription(`Name: ${spl[1] ? `\`:${spl[1]}:\`` : "Not Found"}\nID: ${spl[2].slice(0, spl[2].length - 1)}\nURL: [Here](${`https://cdn.discordapp.com/emojis/${spl[2].slice(0, spl[2].length - 1)}${spl[0].includes('a') ? '.gif' : ""}`})\nAnimated: ${spl[0].includes('a') === true}\n\nI have access: ${client.emojis.cache.has(spl[2].slice(0, spl[2].length - 1))}`)
.setColor('c375f0')
.setImage(`https://cdn.discordapp.com/emojis/${spl[2].slice(0, spl[2].length - 1)}${spl[0].includes('a') ? '.gif' : ""}`)
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp();
if (client.emojis.cache.has(spl[2].slice(0, spl[2].length - 1))) {finEm.setThumbnail(client.emojis.cache.get(spl[2].slice(0, spl[2].length - 1)).guild.iconURL({size: 1024}));}
if (client.emojis.cache.has(spl[2].slice(0, spl[2].length - 1)) && client.emojis.cache.get(spl[2].slice(0, spl[2].length - 1)).guild.members.cache.has(message.author.id) && client.emojis.cache.get(spl[2].slice(0, spl[2].length - 1)).guild.id !== (message.guild ? message.guild.id : 1)) {finEm.addField("Server", `You're in the server this emoji is from: **${client.emojis.cache.get(spl[2].slice(0, spl[2].length - 1)).guild.name}**`);}
@@ -63,7 +63,7 @@ module.exports = {
.setTitle(`Emoji Lookup Results [${(x * 20) + 1}-${(x * 20) + 20} of ${lookup.size}]`)
.setDescription(page)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
);
if (cond) {break;}
@@ -78,7 +78,7 @@ module.exports = {
.setTitle(`Emoji Lookup Results - ${lookup.size}`)
.setDescription(page)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
@@ -110,7 +110,7 @@ module.exports = {
.setDescription(`Name: ${name ? `\`:${name}:\`` : "Not Found"}\nID: ${id}\nURL: [Here](${url})\nAnimated: ${animated === true}\n\nI have access: ${access}`)
.setColor('c375f0')
.setImage(url)
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp();
if (access) {finEm.setThumbnail(client.emojis.cache.get(id).guild.iconURL({size: 1024}));}
if (access && client.emojis.cache.get(id).guild.members.cache.has(message.author.id) && client.emojis.cache.get(id).guild.id !== (message.guild ? message.guild.id : 1)) {finEm.addField("Server", `You're in the server this emoji is from: **${client.emojis.cache.get(id).guild.name}**`);}
diff --git a/commands/misc/help.js b/commands/misc/help.js
index 1755e15..d2a614b 100644
--- a/commands/misc/help.js
+++ b/commands/misc/help.js
@@ -18,7 +18,7 @@ module.exports = {
let category; for (category of Object.keys(sorted)) {
let categorySorted = [];
let current = 1;
- let currentEmbed = new Discord.MessageEmbed().setAuthor({name: "Help Menu", iconURL: message.author.avatarURL()}).setTitle(category).setDescription("React to control the menu! You can also specify a command name when doing the help command to get more info about it.").setColor("c375f0");
+ let currentEmbed = new Discord.MessageEmbed().setAuthor({name: "Help Menu", iconURL: message.author.displayAvatarURL()}).setTitle(category).setDescription("React to control the menu! You can also specify a command name when doing the help command to get more info about it.").setColor("c375f0");
let commands = Object.keys(sorted[category]);
let command; for (command of commands) {
let aliases = '';
@@ -29,7 +29,7 @@ module.exports = {
if (current === 5) {
categorySorted.push(currentEmbed);
current = 1;
- currentEmbed = new Discord.MessageEmbed().setAuthor({name: "Help Menu", iconURL: message.author.avatarURL()}).setTitle(category).setDescription("React to control the menu! You can also specify a command name when doing the help command to get more info about it.").setColor("c375f0");
+ currentEmbed = new Discord.MessageEmbed().setAuthor({name: "Help Menu", iconURL: message.author.displayAvatarURL()}).setTitle(category).setDescription("React to control the menu! You can also specify a command name when doing the help command to get more info about it.").setColor("c375f0");
}
}
if (current > 1) {categorySorted.push(currentEmbed);}
@@ -43,7 +43,7 @@ module.exports = {
.addField("Category", "What category would you like to view?\n:one: - Fun\n:two: - Utility\n:three: - Misc\n:four: - Developer\n:five: - Moderation\n:six: - Social\n:seven: - Leveling\n:eight: - Anime\n:nine: - **All**")
.setColor('c375f0')
.setFooter({text: "Natsuki | Will time out in 60 seconds."})
- .setThumbnail(client.user.avatarURL({size: 2048}))
+ .setThumbnail(client.user.displayAvatarURL({size: 2048}))
.setTimestamp()
]});
@@ -100,7 +100,7 @@ module.exports = {
if (pages.length > 1) {
let help = new Pagination(message.channel, pages, message, client, true);
return await help.start({endTime: 60000, user: message.author.id}).catch(() => {});
- } else {return message.channel.send({embeds: [pages[0].setFooter({text: "Natsuki", iconURL: client.user.avatarURL()}).setTimestamp()]}).catch(() => {});}
+ } else {return message.channel.send({embeds: [pages[0].setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()}).setTimestamp()]}).catch(() => {});}
} else {
let command;
if (client.commands.has(args[0])) {command = client.commands.get(args[0]);}
@@ -109,7 +109,7 @@ module.exports = {
return message.reply(command.help
? command.help instanceof Discord.MessageEmbed
- ? {embeds: [command.help.setFooter({text: "Natsuki | [optional]", iconURL: client.user.avatarURL()}).setColor("c375f0").setTimestamp()]}
+ ? {embeds: [command.help.setFooter({text: "Natsuki | [optional]", iconURL: client.user.displayAvatarURL()}).setColor("c375f0").setTimestamp()]}
: command.help.replace(/{{p}}/g, prefix)
: "I don't seem to have any help info available for that command."
);
diff --git a/commands/misc/info.js b/commands/misc/info.js
index 5200ee8..0bf57e4 100644
--- a/commands/misc/info.js
+++ b/commands/misc/info.js
@@ -19,8 +19,8 @@ module.exports = {
let user = await UserData.findOne({uid: message.author.id});
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: "About Me!", iconURL: client.users.cache.get(client.developers[Math.floor(Math.random() * client.developers.length)]).avatarURL()})
- .setThumbnail(client.user.avatarURL({size: 1024}))
+ .setAuthor({name: "About Me!", iconURL: client.users.cache.get(client.developers[Math.floor(Math.random() * client.developers.length)]).displayAvatarURL()})
+ .setThumbnail(client.user.displayAvatarURL({size: 1024}))
.setDescription(`I am created by WubzyGD#8766 and Slushie#1234 - a pair conveniently known as NatsukiDev - in JavaScript/Discord.js!\n\nI'm a powerful all-purpose bot with everything you could want or need, and I have my own set of unique skills that you won't find anywhere else ^^`)
.addField("Presence", `I'm currently in **${client.guilds.cache.size}** servers, and I'm watching over approximately **${client.users.cache.size}** people!`)
.addField("Restarts", `${botData.restarts}`, true)
diff --git a/commands/misc/invite.js b/commands/misc/invite.js
index f39e2b0..d1ce32b 100644
--- a/commands/misc/invite.js
+++ b/commands/misc/invite.js
@@ -13,8 +13,8 @@ module.exports = {
async execute(message, msg, args, cmd, prefix, mention, client) {
return message.channel.send({embeds: [new Discord.MessageEmbed()
.setTitle("My links!")
- .setThumbnail(client.user.avatarURL({size: 2048}))
- .setDescription("[Bot Invite](https://discord.com/oauth2/authorize?client_id=762701327431237644&scope=bot&permissions=1581116647)\n`->` Use this link to invite Natsuki to your server! This has all the required permissions in it that the I need to work, and it is not recommended that you change them. Doing so will make it so that some commands don't function properly or won't complete (I'll usually tell you when I'm missing a permission).\n\n[Support Server Invite](https://discord.gg/u9c2uD24wB)\n`->` Use this to join my support server! Here you can talk to the devs, suggest features, hang out with the community, get update alerts, report bugs/issues and get help, or just stop and say hi!")
+ .setThumbnail(client.user.displayAvatarURL({size: 2048}))
+ .setDescription("[Bot Invite](https://discord.com/api/oauth2/authorize?client_id=762701327431237644&permissions=1507482660086&scope=bot%20applications.commands)\n`->` Use this link to invite Natsuki to your server! This has all the required permissions in it that the I need to work, and it is not recommended that you change them. Doing so will make it so that some commands don't function properly or won't complete (I'll usually tell you when I'm missing a permission).\n\n[Support Server Invite](https://discord.gg/u9c2uD24wB)\n`->` Use this to join my support server! Here you can talk to the devs, suggest features, hang out with the community, get update alerts, report bugs/issues and get help, or just stop and say hi!")
.setColor("c375f0")
.setFooter({text: "Natsuki"})
.setTimestamp()
diff --git a/commands/misc/ping.js b/commands/misc/ping.js
new file mode 100644
index 0000000..6bf497a
--- /dev/null
+++ b/commands/misc/ping.js
@@ -0,0 +1,22 @@
+const Discord = require('discord.js');
+
+module.exports = {
+ name: "ping",
+ aliases: [],
+ meta: {
+ category: 'Misc',
+ description: "Find out Natsuki's latency",
+ syntax: '`ping`',
+ extra: null
+ },
+ help: "Definitely not much to see here...",
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ return message.channel.send({embeds: [new Discord.MessageEmbed()
+ .setTitle("Client Latency")
+ .setDescription(`Response Latency: \`${new Date().getTime() - message.createdTimestamp}ms\`\nAPI Latency: \`${client.ws.ping}ms\``)
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
+ .setTimestamp()
+ .setColor('c375f0')
+ ]});
+ }
+};
\ No newline at end of file
diff --git a/commands/misc/prefix.js b/commands/misc/prefix.js
index 38d0c9d..d9fa137 100644
--- a/commands/misc/prefix.js
+++ b/commands/misc/prefix.js
@@ -36,12 +36,12 @@ module.exports = {
let upm = await message.reply("sure thing!");
await require('../../util/wait')(1750);
return upm.edit({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: 'Prefix updated!', iconURL: message.author.avatarURL()})
+ .setAuthor({name: 'Prefix updated!', iconURL: message.author.displayAvatarURL()})
.setDescription(`New prefix: \`${np}\``)
.addField('Auditing Admin', `<@${message.member.id}>`, true)
.addField("Notice", "Prefixes are cached, and may take up to a minute to update.")
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
diff --git a/commands/misc/serverinfo.js b/commands/misc/serverinfo.js
index ed5ef35..a180f4e 100644
--- a/commands/misc/serverinfo.js
+++ b/commands/misc/serverinfo.js
@@ -1,5 +1,6 @@
const Discord = require("discord.js");
const moment = require('moment');
+require('moment-precise-range-plugin');
module.exports = {
name: "serverinfo",
@@ -14,18 +15,28 @@ module.exports = {
},
execute(message, msg, args, cmd, prefix, mention, client) {
let now = new Date();
- return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: "Server info", iconURL: message.author.avatarURL()})
- .setTitle(message.guild.name)
- .setThumbnail(message.guild.iconURL({size: 2048}))
- .setDescription(`Name: \`${message.guild.name}\`\n\nOwner: <@${message.guild.ownerId}>\nRegion: ${message.guild.region}\nIcon: [URL](${message.guild.iconURL({size: 2048})})`)
- .addField("Members", `${message.guild.members.cache.size}\n[${message.guild.members.cache.filter(m => !client.users.cache.get(m.id).bot).size} Humans | ${message.guild.members.cache.filter(m => client.users.cache.get(m.id).bot).size} Bots]\n\nOnline: ${message.guild.members.cache.filter(m => client.users.cache.get(m.id).presence.status === "online").size} | Idle: ${message.guild.members.cache.filter(m => client.users.cache.get(m.id).presence.status === "idle").size} | Do not Disturb: ${message.guild.members.cache.filter(m => client.users.cache.get(m.id).presence.status === "dnd").size}`)
- .addField("Channels", `${message.guild.channels.cache.size}\n[${message.guild.channels.cache.filter(ch => ch.type === "text").size} Text | ${message.guild.channels.cache.filter(ch => ch.type === "voice").size} Voice]`, true)
- .addField("Roles", `${message.guild.roles.cache.size} (you have ${message.member.roles.cache.size})\nYour highest is <@&${message.member.roles.highest.id}>`, true)
- .addField("Other Info", `Server created roughly **${moment(message.guild.createdAt).fromNow()}**\n\nYou joined ${moment(message.member.joinedAt).fromNow()} (Member for **${Math.round(((now.getTime() - new Date(message.member.joinedAt.getTime()).getTime()) / (new Date(message.guild.createdAt).getTime() - now.getTime())) * -100)}%** of server lifetime)`)
+ let tg = message.guild;
+ let text = ["GUILD_MESSAGE", "DM", "GUILD_NEWS_THREAD", "GUILD_PRIVATE_THREAD", "GUILD_PUBLIC_THREAD", "GUILD_NEWS", "GROUP_DM", "GUILD_STORE", "GUILD_TEXT"];
+ let voice = ["GUILD_VOICE", "GUILD_STAGE_VOICE"];
+ let siembed = new Discord.MessageEmbed()
+ .setAuthor({name: "Server info", iconURL: message.author.displayAvatarURL({dynamic: true})})
+ .setTitle(tg.name)
+ .setThumbnail(tg.iconURL({size: 2048, dynamic: true, format: 'png'}))
+ .setDescription(`Name: \`${tg.name}\`\n\nOwner: <@${tg.ownerId}>\nBoost Level: **${tg.premiumTier === 'NONE' ? 'None' : tg.premiumTier.slice(tg.premiumTier.length - 1, tg.premiumTier.length)}**\nIcon: [URL](${tg.iconURL({size: 2048})})${tg.banner ? ` | Banner: [URL](${tg.bannerURL({size: 4096, format: 'png'})})` : ''}${tg.splash ? ` | Splash: [URL](${tg.splashURL({size: 4096, format: 'png'})})` : ''}\nID: ${tg.id}`)
+ .addField("Channels", `${tg.channels.cache.filter(ch => ch.type !== 'GUILD_CATEGORY').size}\n[${tg.channels.cache.filter(ch => text.includes(ch.type)).size} Text | ${tg.channels.cache.filter(ch => voice.includes(ch.type)).size} Voice]`, true)
+ .addField("Roles", `${tg.roles.cache.size} (you have ${message.member.roles.cache.size}) -> ${Math.round((message.member.roles.cache.size / tg.roles.cache.size) * 100)}%\nYour highest is <@&${message.member.roles.highest.id}>`, true)
+ .addField("Members", `${tg.memberCount}\n[${tg.members.cache.filter(m => !client.users.cache.get(m.id).bot).size} Humans | ${tg.members.cache.filter(m => client.users.cache.get(m.id).bot).size} Bots]\n\nOnline: ${tg.members.cache.filter(m => m.presence && m.presence.status === "online").size} | Idle: ${tg.members.cache.filter(m => m.presence && m.presence.status === "idle").size} | Do not Disturb: ${tg.members.cache.filter(m => m.presence && m.presence.status === "dnd").size}`)
+ .addField("Emojis", `${tg.emojis.cache.size}`, true)
+ .addField("Stickers", `${tg.stickers.cache.size}`, true)
+ .addField("Other Info", `Server created **${client.utils.sm(moment.preciseDiff(Date.now(), tg.createdAt, true))}**\nYou joined ${client.utils.sm(moment.preciseDiff(Date.now(), message.member.joinedAt, true))} (Member for **${Math.round(((now.getTime() - message.member.joinedAt.getTime()) / (now.getTime() - message.guild.createdAt.getTime())) * 100)}%** of server lifetime)`)
.setColor('c375f0')
.setFooter({text: "Natsuki"})
- .setTimestamp()
- ]});
+ .setTimestamp();
+
+ if (tg.banner) {siembed.setImage(tg.bannerURL({size: 4096, format: 'png'}));}
+ else if (tg.splash) {siembed.setImage(tg.splashURL({size: 4096, format: 'png'}));}
+ if (tg.premiumTier !== 'NONE') {siembed.addField("Features", tg.features.map(f => client.utils.ca(f.replace(/_/gm, ' '))).join(", "));}
+
+ return message.channel.send({embeds: [siembed]});
}
};
\ No newline at end of file
diff --git a/commands/misc/sleeping.js b/commands/misc/sleeping.js
new file mode 100644
index 0000000..8d01607
--- /dev/null
+++ b/commands/misc/sleeping.js
@@ -0,0 +1,54 @@
+const Discord = require('discord.js');
+
+const UserData = require("../../models/user");
+
+module.exports = {
+ name: "sleeping",
+ aliases: ['asleep', 'sloopin', 'ischleep'],
+ meta: {
+ category: 'Misc',
+ description: "Set your status to tell others you're sleeping.",
+ syntax: '`sleeping`',
+ extra: null
+ },
+ help: new Discord.MessageEmbed()
+ .setTitle("Help -> Sleeping")
+ .setDescription("Use this command to set an automatically-clearing AFK status that lets people who ping you know you're asleep. Send any message to any server with Natsuki in it to clear the status.")
+ .addField("Syntax", "`sleeping`"),
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ let tu = await UserData.findOne({uid: message.author.id}) || new UserData({uid: message.author.id});
+ tu.statusclearmode = 'auto';
+ tu.statustype = 'afk';
+ tu.statusmsg = [
+ " Sleeping",
+ " Getting a good night's rest",
+ " Big sleep",
+ " \\*snore\\*"
+ ][Math.floor(Math.random() * 4)];
+ tu.statussetat = new Date();
+ let tempDate = new Date();
+ tu.statusclearat = tempDate.setHours(tempDate.getHours() + 12);
+ tu.statusSleeping = true;
+ tu.markModified("statusSleeping");
+ tu.markModified("statussetat");
+ tu.markModified("statusclearat");
+ tu.save();
+ require('../../util/cachestatus')(message.author.id, tempDate.setHours(tempDate.getHours() + 10));
+ return message.channel.send(
+ (client.misc.cache.returnToSleep.has(message.author.id) && new Date().getTime() - client.misc.cache.returnToSleep.get(message.author.id) < 600000
+ ? [
+ "Ah, well I'm glad you're getting back to sleep! Try to put the phone down and get some rest qt",
+ "Actually taking my advice and getting some sleep? You need it after all!",
+ ":D You're going back to bed! I don't wanna see you up again. You need some sleep qt ^^",
+ "Sleep is good for you! It's best uninterrupted. Get some good sleep and try not to pick up your phone again."
+ ]
+ : [
+ "Goodnight qt <:NC_wave:830704926576345119>",
+ "<:NC_hearty:841489530413383712> Have a good sleep! ^^",
+ "Sleep well. You deserve it <3 ",
+ "<:NC_nezuGUN:852735951712157698> Get good sleep coward!"
+ ]
+ )[Math.floor(Math.random() * 4)]
+ );
+ }
+};
\ No newline at end of file
diff --git a/commands/misc/supportserver.js b/commands/misc/supportserver.js
index 6710d2f..2a6125a 100644
--- a/commands/misc/supportserver.js
+++ b/commands/misc/supportserver.js
@@ -13,7 +13,7 @@ module.exports = {
async execute(message, msg, args, cmd, prefix, mention, client) {
return message.channel.send({embeds: [new Discord.MessageEmbed()
.setTitle("Sure thing!")
- .setThumbnail(client.user.avatarURL({size: 2048}))
+ .setThumbnail(client.user.displayAvatarURL({size: 2048}))
.setDescription("Join the server with [this link](https://discord.gg/u9c2uD24wB)!\n\n`->` Here you can talk to the devs, suggest features, hang out with the community, get update alerts, report bugs/issues and get help, or just stop and say hi!")
.setColor("c375f0")
.setFooter({text: "Natsuki"})
diff --git a/commands/misc/userinfo.js b/commands/misc/userinfo.js
index 54eb21b..b59f720 100644
--- a/commands/misc/userinfo.js
+++ b/commands/misc/userinfo.js
@@ -1,6 +1,7 @@
const Discord = require('discord.js');
const moment = require('moment');
-const mongoose = require('mongoose');
+require('moment-precise-range-plugin');
+
const UserData = require('../../models/user');
module.exports = {
@@ -11,35 +12,44 @@ module.exports = {
category: 'Misc',
description: "See some info about a user",
syntax: '`userinfo [@user]`',
- extra: null
+ extra: null,
+ guildOnly: true
},
async execute(message, msg, args, cmd, prefix, mention, client) {
- let person = message.guild ? mention ? message.guild.members.cache.get(mention.id) : args[0] ? message.guild.members.cache.has(args[0]) ? message.guild.members.cache.get(args[0]) : message.member : message.member : message.author;
+ let person = message.mentions.members.first() || message.guild.members.cache.get(args[0]) || message.member;
+ if (!person) {return message.channel.send("Hmmm... that doesn't seem to be a real user.");}
+ let u = await client.users.fetch(person.id, {force: true, cache: false}).catch(() => {});
+ if (!u) {return message.channel.send("There was an issue finding that user. They might not be a real user!");}
+ temp = await message.guild.members.fetch(person.id);
+ if (!temp) {return message.channel.send("There was an issue finding that user. They might not be a real user, or not one that exists in this server.");}
let name = message.guild ? person.displayName : person.username;
let tu = await UserData.findOne({uid: person.id});
let now = new Date();
let infoembed = new Discord.MessageEmbed()
.setTitle(`User Info for ${name}`)
.setDescription(`Requested by ${message.guild ? message.member.displayName : message.author.username}`)
- .setThumbnail(client.users.cache.get(person.id).avatarURL({size: 2048}))
- .addField("Account Created", `${moment(client.users.cache.get(person.id).createdAt).fromNow()}`, true)
- .addField("Bot User?", client.users.cache.get(person.id).bot ? "Is a bot" : "Is not a bot", true)
+ .setThumbnail((message.guild ? person : u).displayAvatarURL({size: 4096, dynamic: true, format: 'png'}))
+ .addField("Account Created", `${moment.preciseDiff(Date.now(), u.createdAt)} ago`, true)
+ .addField("Bot User?", u.bot ? "Is a bot" : "Is not a bot", true)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp();
if (message.guild) {
- infoembed.addField('In Server Since', `${moment(person.joinedAt).fromNow()}${!moment(person.joinedAt).fromNow().includes('days') ? ` | ${Math.floor((new Date().getTime() - person.joinedAt.getTime()) / (60 * 60 * 24 * 1000))} days` : ''}\nMember for **${Math.round(((now.getTime() - new Date(message.member.joinedAt.getTime()).getTime()) / (new Date(message.guild.createdAt).getTime() - now.getTime())) * -100)}%** of server lifetime`, false)
+ infoembed.addField('In Server Since', `${client.utils.sm(moment.preciseDiff(Date.now(), person.joinedAt, true))}${!moment(person.joinedAt).fromNow().includes('days') ? ` | ${Math.floor((new Date().getTime() - person.joinedAt.getTime()) / (60 * 60 * 24 * 1000))} days` : ''}\nMember for **${Math.round(((now.getTime() - person.joinedAt.getTime()) / (now.getTime() - message.guild.createdAt.getTime())) * 100)}%** of server lifetime`, false)
.addField('Roles', `**${person.roles.cache.size}** roles | [${person.roles.cache.size}/${message.guild.roles.cache.size}] - ${Math.round((person.roles.cache.size / message.guild.roles.cache.size) * 100)}%\nHighest: ${person.roles.highest ? `<@&${person.roles.highest.id}>` : 'No roles!'}`, true)
if (message.guild.ownerId === person.id) {infoembed.addField("Extra", "User is the server's owner!");}
else if (person.permissions.has("ADMINISTRATOR")) {infoembed.addField("Extra", "User is an admin! Watch out :eyes:");}
}
if (tu) {
- infoembed.addField('Natsuki Commands Executed', `${tu.commands}`)
- .addField('Donator?', tu.developer ? `Well, ${name} makes me work, so they're a supporter in my book!` : tu.donator ? 'Yes! They have donated or supported me in the past!' : 'No', true)
- .addField('Natsuki Staff Level', tu.developer ? 'Developer' : tu.admin ? 'Admin; Audit access to the bot' : tu.staff ? 'Staff; Support but with maintenance permissions' : tu.support ? 'Support; Answers tickets and help queries' : 'Member; Does not have a staff rank.', true);
+ infoembed.addField('Natsuki Commands Executed', `${tu.commands}`);
+ if (tu.donator || tu.developer) {infoembed.addField('Donator?', tu.developer ? `Well, ${name} makes me work, so they're a supporter in my book!` : tu.donator ? 'Yes! They have donated or supported me in the past!' : 'No', true);}
+ if (tu.staff) {infoembed.addField('Natsuki Staff Level', tu.developer ? 'Developer' : tu.admin ? 'Admin; Audit access to the bot' : tu.staff ? 'Staff; Support but with maintenance permissions' : tu.support ? 'Support; Answers tickets and help queries' : 'Member; Does not have a staff rank.', true);}
}
+
+ if (u.banner) {infoembed.setImage(u.bannerURL({size: 4096, dynamic: true, format: 'png'}));}
+
return message.channel.send({embeds: [infoembed]});
}
};
\ No newline at end of file
diff --git a/commands/moderation/autorole.js b/commands/moderation/autorole.js
index 4ee54b4..c312d54 100644
--- a/commands/moderation/autorole.js
+++ b/commands/moderation/autorole.js
@@ -28,10 +28,10 @@ module.exports = {
tg.save();
return message.channel.send(new Discord.MessageEmbed()
.setTitle("Join Role Updated")
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Role: ${tg.joinrole.length ? `<@&${tg.joinrole}>` : "None"}`)
.setColor("c375f0")
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
);
}
diff --git a/commands/moderation/checkwarnings.js b/commands/moderation/checkwarnings.js
index 77bb4bf..97daa22 100644
--- a/commands/moderation/checkwarnings.js
+++ b/commands/moderation/checkwarnings.js
@@ -39,11 +39,11 @@ module.exports = {
if (cwc === mh.warnings[user.id].length) {return message.reply("That user has no uncleared warnings.");}
return message.channel.send({embeds: [new Discord.MessageEmbed()
.setTitle("User Warnings")
- .setThumbnail(client.users.cache.get(user.id).avatarURL({size: 1024}))
+ .setThumbnail(client.users.cache.get(user.id).displayAvatarURL({size: 1024}))
.setDescription(`For ${user.displayName}`)
.addField("Warnings", ws)
.setColor("c375f0")
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
diff --git a/commands/moderation/leave.js b/commands/moderation/leave.js
index 90fe85b..4737408 100644
--- a/commands/moderation/leave.js
+++ b/commands/moderation/leave.js
@@ -41,7 +41,7 @@ module.exports = {
.setTitle("Leave Channel/Message Updated")
.setDescription(`This server's leave-notifying settings have been altered by ${message.author.tag}.\n\n**Channel**: <#${ch}>\n**Response Name**: \`${args[2].toLowerCase()}\``)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]})
}
@@ -64,7 +64,7 @@ module.exports = {
.setTitle("Leave Channel/Message Updated")
.setDescription(`This server's leave-notifying settings have been altered by ${message.author.tag}.\n\n**Channel**: None`)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
diff --git a/commands/moderation/response.js b/commands/moderation/response.js
index e8638e0..7df88b0 100644
--- a/commands/moderation/response.js
+++ b/commands/moderation/response.js
@@ -68,7 +68,7 @@ module.exports = {
.addField("Name/ID", args[1].toLowerCase(), true)
.addField("Type", tr.responses.get(args[1].toLowerCase()).embed ? "Embed" : "Message", true)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp();
if (hasBinding) {infoEmbed.addField("Server Bindings", bm);}
return message.channel.send({embeds: [infoEmbed]});
diff --git a/commands/moderation/staffrole.js b/commands/moderation/staffrole.js
index 2a20aaa..0c91921 100644
--- a/commands/moderation/staffrole.js
+++ b/commands/moderation/staffrole.js
@@ -42,12 +42,12 @@ module.exports = {
let upm = await message.reply("sure thing!");
await require('../../util/wait')(1750);
return upm.edit({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: 'Staff role updated!', iconURL: message.author.avatarURL()})
+ .setAuthor({name: 'Staff role updated!', iconURL: message.author.displayAvatarURL()})
.setDescription(`<@&${tguild.staffrole}> can now edit my settings in this server.`)
.addField('Auditing Admin', `<@${message.member.id}>`, true)
.addField('Role-Holders', `${message.guild.members.cache.filter(m => m.roles.cache.has(tguild.staffrole) && !client.users.cache.get(m.id).bot).size}+ members have this role`, true)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
diff --git a/commands/moderation/warn.js b/commands/moderation/warn.js
index 8fb3390..a481b1e 100644
--- a/commands/moderation/warn.js
+++ b/commands/moderation/warn.js
@@ -47,11 +47,11 @@ module.exports = {
if (cwc === mh.warnings[user.id].length) {return message.reply("That user has no uncleared warnings.");}
return message.channel.send({embeds: [new Discord.MessageEmbed()
.setTitle("User Warnings")
- .setThumbnail(client.users.cache.get(user.id).avatarURL({size: 1024}))
+ .setThumbnail(client.users.cache.get(user.id).displayAvatarURL({size: 1024}))
.setDescription(`For ${user.displayName}`)
.addField("Warnings", ws)
.setColor("c375f0")
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
diff --git a/commands/moderation/welcome.js b/commands/moderation/welcome.js
index ae2969b..d687c31 100644
--- a/commands/moderation/welcome.js
+++ b/commands/moderation/welcome.js
@@ -41,7 +41,7 @@ module.exports = {
.setTitle("Welcome Channel/Message Updated")
.setDescription(`This server's member-welcoming settings have been altered by ${message.author.tag}.\n\n**Channel**: <#${ch}>\n**Response Name**: \`${args[2].toLowerCase()}\``)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]})
}
@@ -64,7 +64,7 @@ module.exports = {
.setTitle("Welcome Channel/Message Updated")
.setDescription(`This server's member-welcoming settings have been altered by ${message.author.tag}.\n\n**Channel**: None`)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
diff --git a/commands/social/afk.js b/commands/social/afk.js
index 5e79512..a8e45c8 100644
--- a/commands/social/afk.js
+++ b/commands/social/afk.js
@@ -21,8 +21,8 @@ module.exports = {
? message.content.slice(prefix.length).trim().split(/ +/g)
: msg.startsWith('<@!')
? message.content.slice(4 + client.user.id.length).trim().split(/ +/g)
- : message.content.slice(3 + client.user.id.length).trim().split(/ +/g)
- .slice(2);
+ : message.content.slice(3 + client.user.id.length).trim().split(/ +/g);
+ args = args.slice(1);
if (!args.length) {return message.channel.send(`Syntax: \`${prefix}afk [clearMode] \``);}
let tu = await UserData.findOne({uid: message.author.id})
? await UserData.findOne({uid: message.author.id})
@@ -45,6 +45,6 @@ module.exports = {
tu.markModified("statusclearat");
tu.save();
require('../../util/cachestatus')(message.author.id, tempDate.setHours(tempDate.getHours() + 12));
- return message.reply(`I set your ${tu.statusclearmode === 'auto' ? 'automatically' : 'manually'}-clearing AFK message to: ${reason.trim()}`);
+ return message.channel.send(`I set your ${tu.statusclearmode === 'auto' ? 'automatically' : 'manually'}-clearing AFK message to: ${reason.trim()}`);
}
};
\ No newline at end of file
diff --git a/commands/social/angry.js b/commands/social/angry.js
index ae2210d..ea615e0 100644
--- a/commands/social/angry.js
+++ b/commands/social/angry.js
@@ -24,7 +24,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new angry GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new angry GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/bio.js b/commands/social/bio.js
index 758f254..6a064dc 100644
--- a/commands/social/bio.js
+++ b/commands/social/bio.js
@@ -23,10 +23,10 @@ module.exports = {
if (!pud || !pud.bio || !pud.bio.length) {return message.reply(person === message.author.id ? "You don't have a bio set!" : "That user has no bio for me to show you!");}
return message.channel.send({embeds: [new Discord.MessageEmbed()
.setTitle(`Bio for ${message.guild ? message.guild.members.cache.get(person).displayName : message.author.username}`)
- .setThumbnail(client.users.cache.get(person).avatarURL({size: 2048}))
+ .setThumbnail(client.users.cache.get(person).displayAvatarURL({size: 2048}))
.setDescription(pud.bio)
.setColor(pud.color && pud.color.length ? pud.color : 'c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
@@ -45,10 +45,10 @@ module.exports = {
tu.save();
return message.channel.send({embeds: [new Discord.MessageEmbed()
.setTitle(`Bio Set!`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(tu.bio)
.setColor(tu.color && tu.color.length ? tu.color : 'c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
diff --git a/commands/social/blush.js b/commands/social/blush.js
index 8580b6e..635b2ca 100644
--- a/commands/social/blush.js
+++ b/commands/social/blush.js
@@ -23,7 +23,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new sip GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new sip GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/bonk.js b/commands/social/bonk.js
index 949615c..d8c55ab 100644
--- a/commands/social/bonk.js
+++ b/commands/social/bonk.js
@@ -21,10 +21,10 @@ module.exports = {
if (!args.length) {
return message.channel.send(message.guild ? {embeds: [new Discord.MessageEmbed()
.setTitle(`${message.guild ? message.member.displayName : message.author.username} needs a good bonk!`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Give them one with \`${prefix}bonk @${message.member.displayName}\`!`)
.setColor('dda0dd')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
: "I fucking dare you to hit me."
);}
@@ -38,7 +38,7 @@ module.exports = {
bonk.markModified(`against.${mention.id}`);
bonk.save();
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} bonks ${message.guild.members.cache.get(mention.id).displayName}!...ouch! `, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} bonks ${message.guild.members.cache.get(mention.id).displayName}!...ouch! `, iconURL: message.author.displayAvatarURL()})
.setDescription(`You've bonked them **${bonk.against[mention.id] === 1 ? 'once' : `${bonk.against[mention.id]} times!`}**`)
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('dda0dd')
@@ -48,7 +48,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new bonk GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new bonk GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/creampie.js b/commands/social/creampie.js
index 21e5475..ba95e0c 100644
--- a/commands/social/creampie.js
+++ b/commands/social/creampie.js
@@ -20,10 +20,10 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
return message.channel.send(message.guild ? {embeds: [new Discord.MessageEmbed()
.setTitle(`${name} needs a creampie!`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Help with their..ahem..problem..with \`${prefix}creampie @${name}\`!`)
.setColor('fffdd0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
: "Do. Not. Touch. Me."
);}
@@ -34,7 +34,7 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
let uname = message.guild.members.cache.get(mention.id).displayName;
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} gives a massive creampie to ${message.guild.members.cache.get(mention.id).displayName}..Tasty!`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} gives a massive creampie to ${message.guild.members.cache.get(mention.id).displayName}..Tasty!`, iconURL: message.author.displayAvatarURL()})
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('fffdd0')
]});
diff --git a/commands/social/cry.js b/commands/social/cry.js
index f9276b1..57b594d 100644
--- a/commands/social/cry.js
+++ b/commands/social/cry.js
@@ -24,7 +24,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new cry GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new cry GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/dance.js b/commands/social/dance.js
index 77ab09a..be293da 100644
--- a/commands/social/dance.js
+++ b/commands/social/dance.js
@@ -24,7 +24,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new dance GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new dance GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/dnd.js b/commands/social/dnd.js
index 76e91c0..1befcb2 100644
--- a/commands/social/dnd.js
+++ b/commands/social/dnd.js
@@ -22,8 +22,8 @@ module.exports = {
? message.content.slice(prefix.length).trim().split(/ +/g)
: msg.startsWith('<@!')
? message.content.slice(4 + client.user.id.length).trim().split(/ +/g)
- : message.content.slice(3 + client.user.id.length).trim().split(/ +/g)
- .slice(2);
+ : message.content.slice(3 + client.user.id.length).trim().split(/ +/g)
+ args = args.slice(1);
let tu = await UserData.findOne({uid: message.author.id})
? await UserData.findOne({uid: message.author.id})
: new UserData({uid: message.author.id});
diff --git a/commands/social/dodge.js b/commands/social/dodge.js
index 2fbfe44..d3ed8e0 100644
--- a/commands/social/dodge.js
+++ b/commands/social/dodge.js
@@ -24,7 +24,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new smile GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new smile GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/feed.js b/commands/social/feed.js
index caf3946..d9004b0 100644
--- a/commands/social/feed.js
+++ b/commands/social/feed.js
@@ -20,10 +20,10 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
return message.channel.send(message.guild ? {embeds: [new Discord.MessageEmbed()
.setTitle(`${name} is hungry, why not feed them?`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Bless someone with some food with \`${prefix}feed @${name}\`!`)
.setColor('bb0a1e')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
: "Sorry..I'm kinda full right now."
);}
@@ -34,7 +34,7 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
let uname = message.guild.members.cache.get(mention.id).displayName;
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} feeds ${message.guild.members.cache.get(mention.id).displayName} a delicous treat!`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} feeds ${message.guild.members.cache.get(mention.id).displayName} a delicous treat!`, iconURL: message.author.displayAvatarURL()})
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('fed8b1')
]});
diff --git a/commands/social/fuck.js b/commands/social/fuck.js
index d236f1e..b308497 100644
--- a/commands/social/fuck.js
+++ b/commands/social/fuck.js
@@ -5,9 +5,12 @@ const UserData = require('../../models/user');
const VC = require('../../models/vscount');
const makeId = require('../../util/makeid');
+const {Tag} = require('../../util/tag');
+const {TagFilter} = require('../../util/tagfilter');
module.exports = {
name: "fuck",
+ aliases: ['sex', 'bang', 'rail', 'verykindlythank'],
help: "Tell others you're horny with `{{p}}fuck`, or bang someone by mentioning someone to fuck!",
meta: {
category: 'Social',
@@ -21,15 +24,16 @@ module.exports = {
if (!args.length) {
return message.channel.send(message.guild ? {embeds: [new Discord.MessageEmbed()
.setTitle(`${message.guild ? message.member.displayName : message.author.username} is horny!`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Show them some love with \`${prefix}fuck @${message.member.displayName}\`!`)
.setColor('dda0dd')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
- : "You can't bang me.......only Wubzy can."
+ : "You can't bang me....... only Wubzy can."
);}
let fuck;
- if (message.channel.nsfw) {
+ let options = new TagFilter([new Tag(['sfw', 'nonsfw', 'clean'], 'sfw', 'toggle')]).test(args.join(" "));
+ if (message.channel.nsfw && !options.sfw) {
fuck = await VC.findOne({uid: message.author.id, countOf: 'realfuck'}) || new VC({uid: message.author.id, countOf: 'realfuck'});
savess = await Saves.findOne({name: 'realfuck'}) || new Saves({name: 'realfuck'});
saves = savess.saves;
@@ -48,7 +52,7 @@ module.exports = {
fuck.markModified(`against.${mention.id}`);
fuck.save();
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} bangs ${message.guild.members.cache.get(mention.id).displayName}!...Kinky! `, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} bangs ${message.guild.members.cache.get(mention.id).displayName}!...Kinky! `, iconURL: message.author.displayAvatarURL()})
.setDescription(`You've banged them **${fuck.against[mention.id] === 1 ? 'once' : `${fuck.against[mention.id]} times!`}**`)
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('dda0dd')
@@ -58,7 +62,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new bang GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new bang GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/handhold.js b/commands/social/handhold.js
index 28a96c7..c276eb8 100644
--- a/commands/social/handhold.js
+++ b/commands/social/handhold.js
@@ -20,10 +20,10 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
return message.channel.send(message.guild ? {embeds: [new Discord.MessageEmbed()
.setTitle(`${name} is feeling a little lonely. If only someone would hold their hand...`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Let them know you love them with \`${prefix}handhold @${name}\`!`)
.setColor('328ba8')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
: "Yikes... I'm kinda germaphobic you know. Maybe try asking in a server?"
);}
@@ -34,7 +34,7 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
let uname = message.guild.members.cache.get(mention.id).displayName;
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} holds ${uname.endsWith('s') ? `${uname}'` : `${uname}'s`} hand!`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} holds ${uname.endsWith('s') ? `${uname}'` : `${uname}'s`} hand!`, iconURL: message.author.displayAvatarURL()})
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('d428a0')
]});
diff --git a/commands/social/heal.js b/commands/social/heal.js
index f27e846..e41b1d1 100644
--- a/commands/social/heal.js
+++ b/commands/social/heal.js
@@ -20,10 +20,10 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
return message.channel.send(message.guild ? {embeds: [new Discord.MessageEmbed()
.setTitle(`${name} needs healing!`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Lend them some help with \`${prefix}heal @${name}\`!`)
.setColor('ffc0cb')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
: "I am immortal, I don't need healing."
);}
@@ -34,7 +34,7 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
let uname = message.guild.members.cache.get(mention.id).displayName;
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} heals ${message.guild.members.cache.get(mention.id).displayName}!`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} heals ${message.guild.members.cache.get(mention.id).displayName}!`, iconURL: message.author.displayAvatarURL()})
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('ffc0cb')
]});
diff --git a/commands/social/hug.js b/commands/social/hug.js
index ae47c13..4b9a4ab 100644
--- a/commands/social/hug.js
+++ b/commands/social/hug.js
@@ -21,10 +21,10 @@ module.exports = {
if (!args.length) {
return message.channel.send(message.guild ? {embeds: [new Discord.MessageEmbed()
.setTitle(`${message.guild ? message.member.displayName : message.author.username} needs a hug!`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Show them some love with \`${prefix}hug @${message.member.displayName}\`!`)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
: "Sorry, but I'm a bot, and I can't hug you. Go into a server and ask for some hugs!"
);}
@@ -38,7 +38,7 @@ module.exports = {
hugs.markModified(`against.${mention.id}`);
hugs.save();
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} gives ${message.guild.members.cache.get(mention.id).displayName} a hug!`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} gives ${message.guild.members.cache.get(mention.id).displayName} a hug!`, iconURL: message.author.displayAvatarURL()})
.setDescription(`You've hugged them **${hugs.against[mention.id] === 1 ? 'once' : `${hugs.against[mention.id]} times!`}**`)
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('52c7bb')
@@ -48,7 +48,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new hug GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new hug GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/kill.js b/commands/social/kill.js
index 2d06868..eaaa5f0 100644
--- a/commands/social/kill.js
+++ b/commands/social/kill.js
@@ -20,10 +20,10 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
return message.channel.send(message.guild ? {embeds: [new Discord.MessageEmbed()
.setTitle(`${name} is feeling homicidal..watch out!`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Brutally murder someone with \`${prefix}kill @${name}\`!`)
.setColor('bb0a1e')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
: "You can't kill me..don't even try."
);}
@@ -34,7 +34,7 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
let uname = message.guild.members.cache.get(mention.id).displayName;
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} brutally murders ${message.guild.members.cache.get(mention.id).displayName}..Rest in Peace.`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} brutally murders ${message.guild.members.cache.get(mention.id).displayName}..Rest in Peace.`, iconURL: message.author.displayAvatarURL()})
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('bb0a1e')
]});
diff --git a/commands/social/kiss.js b/commands/social/kiss.js
index d7cc506..438cbbe 100644
--- a/commands/social/kiss.js
+++ b/commands/social/kiss.js
@@ -18,10 +18,10 @@ module.exports = {
if (!args.length) {
return message.channel.send(message.guild ? {embeds: [new Discord.MessageEmbed()
.setTitle(`${message.guild ? message.member.displayName : message.author.username} wants a kiss!`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Give them a little kiss with \`${prefix}kiss @${message.member.displayName}\`!`)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
: "I'm not really into that kind of thing. Maybe try asking in a server?"
);}
@@ -30,7 +30,7 @@ module.exports = {
if (!message.guild.members.cache.has(mention.id)) {return message.reply("That user is not in this server!");}
if (message.author.id === mention.id) {return message.reply("A self-kiss ought to be a little hard, don't you think?");}
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} kisses ${message.guild.members.cache.get(mention.id).displayName}`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} kisses ${message.guild.members.cache.get(mention.id).displayName}`, iconURL: message.author.displayAvatarURL()})
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('d428a0')
]});
@@ -38,7 +38,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new kiss GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new kiss GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/laugh.js b/commands/social/laugh.js
index ae42664..f260bbe 100644
--- a/commands/social/laugh.js
+++ b/commands/social/laugh.js
@@ -24,7 +24,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new laugh GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new laugh GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/pat.js b/commands/social/pat.js
index c47c0d0..e85df17 100644
--- a/commands/social/pat.js
+++ b/commands/social/pat.js
@@ -22,10 +22,10 @@ module.exports = {
if (!args.length) {
return message.channel.send(message.guild ? {embeds: [new Discord.MessageEmbed()
.setTitle(`${message.guild ? message.member.displayName : message.author.username} wants some pats!`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Give them some with \`${prefix}pat @${message.member.displayName}\`!`)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
: "Sorry, but I'm only able to pat one person, and it's not you ^^"
);}
@@ -39,7 +39,7 @@ module.exports = {
pats.markModified(`against.${mention.id}`);
pats.save();
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} pats ${message.guild.members.cache.get(mention.id).displayName}!`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} pats ${message.guild.members.cache.get(mention.id).displayName}!`, iconURL: message.author.displayAvatarURL()})
.setDescription(`You've given them **${pats.against[mention.id]}** pat${pats.against[mention.id] === 1 ? '' : 's'}!`)
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('52c7bb')
@@ -49,7 +49,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new hug GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new hug GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/run.js b/commands/social/run.js
index 2f7a9d8..33653fa 100644
--- a/commands/social/run.js
+++ b/commands/social/run.js
@@ -24,7 +24,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new running GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new running GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/simp.js b/commands/social/simp.js
index bd4530f..0dc4423 100644
--- a/commands/social/simp.js
+++ b/commands/social/simp.js
@@ -20,10 +20,10 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
return message.channel.send(message.guild ? {embeds: [new Discord.MessageEmbed()
.setTitle(`${name} is feeling lonely..maybe you should simp for them!`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Fall madly in love with someone with \`${prefix}simp @${name}\`!`)
.setColor('ffb6c1')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
: "Nobody simps for me. That's just weird. Be weird to someone else."
);}
@@ -34,7 +34,7 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
let uname = message.guild.members.cache.get(mention.id).displayName;
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} falls madly in love with ${message.guild.members.cache.get(mention.id).displayName}..what a simp.`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} falls madly in love with ${message.guild.members.cache.get(mention.id).displayName}..what a simp.`, iconURL: message.author.displayAvatarURL()})
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('ffb6c1')
]});
diff --git a/commands/social/sip.js b/commands/social/sip.js
index 52b56a9..4e7360a 100644
--- a/commands/social/sip.js
+++ b/commands/social/sip.js
@@ -23,7 +23,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new sip GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new sip GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/smile.js b/commands/social/smile.js
index b068ad2..b89b8f5 100644
--- a/commands/social/smile.js
+++ b/commands/social/smile.js
@@ -24,7 +24,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new smile GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new smile GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/snuggle.js b/commands/social/snuggle.js
index e75a2f2..fca6829 100644
--- a/commands/social/snuggle.js
+++ b/commands/social/snuggle.js
@@ -22,10 +22,10 @@ module.exports = {
if (!args.length) {
return message.channel.send(message.guild ? {embeds: [new Discord.MessageEmbed()
.setTitle(`${message.guild ? message.member.displayName : message.author.username} needs a snuggle!`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Show them some love with \`${prefix}snuggle @${message.member.displayName}\`!`)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
: "Sorry, but I'm a bot, and I can't snuggle you. Go into a server and ask for some snuggles!"
);}
@@ -39,7 +39,7 @@ module.exports = {
snuggles.markModified(`against.${mention.id}`);
snuggles.save();
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} gives ${message.guild.members.cache.get(mention.id).displayName} a snuggle!`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} gives ${message.guild.members.cache.get(mention.id).displayName} a snuggle!`, iconURL: message.author.displayAvatarURL()})
.setDescription(`You've snuggled them **${snuggles.against[mention.id] === 1 ? 'once' : `${snuggles.against[mention.id]} times!`}**`)
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('52c7bb')
@@ -49,7 +49,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new snuggle GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new snuggle GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/spank.js b/commands/social/spank.js
index 57a8761..8eac3c1 100644
--- a/commands/social/spank.js
+++ b/commands/social/spank.js
@@ -29,7 +29,7 @@ module.exports = {
spanks.markModified(`against.${mention.id}`);
spanks.save();
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} gives ${message.guild.members.cache.get(mention.id).displayName} a spank!`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} gives ${message.guild.members.cache.get(mention.id).displayName} a spank!`, iconURL: message.author.displayAvatarURL()})
.setDescription(`You've spanked them **${spanks.against[mention.id] === 1 ? 'once' : `${spanks.against[mention.id]} times!`}**`)
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('52c7bb')
@@ -39,7 +39,7 @@ module.exports = {
if (['s', 'save', 'n', 'new', 'a', 'add'].includes(args[0].toLowerCase())) {
if (!args[1]) {return message.channel.send('oi there cunt, give me a link of an image to add!');}
let tu = await UserData.findOne({uid: message.author.id});
- if ((!tu || !tu.developer) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Developer in order to add new spank GIFs.");}
+ if ((!tu || !tu.staff) && !client.misc.savers.includes(message.author.id)) {return message.reply("You must be a Natsuki Staff member in order to add new spank GIFs.");}
let e = true;
let id;
while (e === true) {id = makeId(6); if (!saves.has(id)) {e = false;}}
diff --git a/commands/social/wink.js b/commands/social/wink.js
index 9234b7e..bf8c29b 100644
--- a/commands/social/wink.js
+++ b/commands/social/wink.js
@@ -20,10 +20,10 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
return message.channel.send(message.guild ? {embeds: [new Discord.MessageEmbed()
.setTitle(`${name} is feeling flirty, maybe you should give them a wink!`)
- .setThumbnail(message.author.avatarURL({size: 2048}))
+ .setThumbnail(message.author.displayAvatarURL({size: 2048}))
.setDescription(`Give them a little wink with \`${prefix}wink @${name}\`!`)
.setColor('8a2be2')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()]}
: "W-why are you winking at me privately..do it in a server! "
);}
@@ -34,7 +34,7 @@ module.exports = {
let name = message.guild ? message.member.displayName : message.author.username;
let uname = message.guild.members.cache.get(mention.id).displayName;
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} winks at ${message.guild.members.cache.get(mention.id).displayName}!`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `${message.guild ? message.member.displayName : message.author.username} winks at ${message.guild.members.cache.get(mention.id).displayName}!`, iconURL: message.author.displayAvatarURL()})
.setImage(String(Array.from(saves.values())[Math.floor(Math.random() * saves.size)]))
.setColor('8a2be2')
]});
diff --git a/commands/utility/checklist.js b/commands/utility/checklist.js
new file mode 100644
index 0000000..d572bc5
--- /dev/null
+++ b/commands/utility/checklist.js
@@ -0,0 +1,46 @@
+const Discord = require('discord.js');
+
+const GuildLists = require("../../models/guildlist");
+const Checklists = require("../../models/checklist");
+
+const ask = require('../../util/ask');
+const makeId = require('../../util/makeid');
+
+module.exports = {
+ name: "checklist",
+ aliases: ['chl', 'list'],
+ meta: {
+ category: 'Utility',
+ description: "Create and manage checklists, which let you manage tasks for server members",
+ syntax: '`checklist `',
+ extra: null,
+ guildOnly: true
+ },
+ help: new Discord.MessageEmbed()
+ .setTitle("Help -> Checklists")
+ .setDescription("Checklists manage large goals for your server, for any purpose, and can be assigned tasks, members, and more.")
+ .addField("Creation", "Use `checklist admin` to toggle admin-locked checklist creation, making it so only admins can make checklists.")
+ .addField("Syntax", "`checklist `"),
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ if (!args.length) {return message.channel.send(`Syntax: \`${prefix}checklist \``);}
+
+ const o = args[0].toLowerCase();
+ if (['c', 'new', 'create'].includes(o)) {
+ let gl = await GuildLists.findOne({gid: message.guild.id});
+ if (gl && gl.admin && !message.member.permissions.has("ADMINISTRATOR")) {return message.channel.send("You must be a server administrator in order to make new lists!");}
+ if (gl && gl.lists.length == 15) {return message.channel.send("Your server has reached the checklist maximum of 15!");}
+ const name = await ask(message, "What would you like to call this checklist?", 60000); if (!name) {return;}
+ if (name.length > 50) {return message.channel.send("Your list's name is too long!");}
+ const desc = await ask(message, "What is the main purpose of this list?", 120000); if (!desc) {return;}
+ if (desc.length > 400) {return message.channel.send("Please shorten that description a little!");}
+ let image = null;
+ let conf = await ask(message, "Would you like to add an image to your list?", 60000); if (!conf) {return;}
+ if (['yes', 'ye', 'y', 'sure'].includes(conf.trim().toLowerCase())) {
+ image = await ask(message, `Please paste the image or a link to the image you'd like to add to your new checklist.`, 60000, false, true);
+ if (!image || !image.match(/^https:\/\/(?:[\w\-].?)+[\/\w\-%()_]+\.(?:png|jpg|jpeg|gif|webp)$/gm)) {return message.channel.send("I don't think that's an image. Try again?");}
+ }
+ if (!gl) {gl = new GuildLists({gid: message.guild.id});}
+
+ }
+ }
+};
\ No newline at end of file
diff --git a/commands/utility/choose.js b/commands/utility/choose.js
new file mode 100644
index 0000000..0a031fc
--- /dev/null
+++ b/commands/utility/choose.js
@@ -0,0 +1,30 @@
+const Discord = require('discord.js');
+
+const {Tag} = require('../../util/tag');
+const {TagFilter} = require('../../util/tagfilter');
+
+module.exports = {
+ name: "choose",
+ aliases: ['po', 'pick', 'pickone', 'chooseone'],
+ meta: {
+ category: 'Utility',
+ description: "Feeling indecisive? Have Natsuki choose for you!",
+ syntax: '`choose [option] [etc...] ` OR `choose -option option that has spaces -o another one -choice another one -o anotherrr`',
+ extra: null
+ },
+ help: new Discord.MessageEmbed()
+ .setTitle("Help -> Choosing")
+ .setDescription("Have Natsuki choose for you.")
+ .addField("Usage", "All choices are done with a space. Or, you can use tag syntax to have options with spaces")
+ .addField("Syntax", "`choose [option] [etc...] ` OR `choose -option option that has spaces -o another one -choice another one -o anotherrr`"),
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ if (!args.length) {return message.channel.send(`Syntax: \`${prefix}choose [option] [etc...] \` OR \`choose -option option that has spaces -o another one -choice another one -o anotherrr\``);}
+ const options = new TagFilter([
+ new Tag(['o', 'option', 'choice', 'c', 'ch'], 'options', 'listAppend')
+ ]).test(args.join(" "));
+ let choices = [];
+ choices = options && options.options && options.options.length ? options.options : args;
+ let prer = ["Hmmm, how about", "I pick", "I choose", "And the result is...\\*drumroll*..."];
+ return message.channel.send(`${prer[Math.floor(Math.random() * prer.length)]} "${choices[Math.floor(Math.random() * choices.length)]}"`);
+ }
+};
\ No newline at end of file
diff --git a/commands/utility/coinflip.js b/commands/utility/coinflip.js
index cf4fd04..d00bca0 100644
--- a/commands/utility/coinflip.js
+++ b/commands/utility/coinflip.js
@@ -40,7 +40,7 @@ module.exports = {
let flip = [1,2][Math.floor(Math.random() * 2)];
let coinEmbed = new Discord.MessageEmbed()
- .setAuthor({name: "Coin Flip", iconURL: message.author.avatarURL()})
+ .setAuthor({name: "Coin Flip", iconURL: message.author.displayAvatarURL()})
.setThumbnail(flip === 1 ? "https://cdn.discordapp.com/attachments/563198656241598484/655514893033799700/SmartSelect_20191214-140108_Samsung_Internet.jpg" : "https://cdn.discordapp.com/attachments/563198656241598484/655514881293811753/SmartSelect_20191214-140131_Samsung_Internet.jpg")
.setDescription(`Flipped by ${message.guild ? message.member.displayName : message.author.username}.\nThe result is **${flip === 1 ? "Heads" : "Tails"}**`)
.setFooter({text: "Natsuki"})
diff --git a/commands/utility/monitor.js b/commands/utility/monitor.js
index 0690e9c..e8c7671 100644
--- a/commands/utility/monitor.js
+++ b/commands/utility/monitor.js
@@ -58,7 +58,7 @@ module.exports = {
.setThumbnail(message.guild.iconURL({size: 1024}))
.setDescription("*These statistics have an accuracy of about 10 minutes.*")
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp();
if (thm) {emb.addField("Top Channels", chs).addField("Top Members", us);}
diff --git a/commands/utility/randnum.js b/commands/utility/randnum.js
index 6d7431f..fb155cb 100644
--- a/commands/utility/randnum.js
+++ b/commands/utility/randnum.js
@@ -44,7 +44,7 @@ module.exports = {
.setTitle(`Random Number${num.length === 1 ? '' : 's'}`)
.setDescription(res)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}
diff --git a/commands/utility/robemote.js b/commands/utility/robemote.js
index 2468b07..d4898e4 100644
--- a/commands/utility/robemote.js
+++ b/commands/utility/robemote.js
@@ -29,7 +29,7 @@ module.exports = {
rc.stop();
return message.guild.emojis.create(`https://cdn.discordapp.com/emojis/${r.emoji.id}`, r.emoji.name)
.then(e => message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: message.member.displayName, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.member.displayName, iconURL: message.author.displayAvatarURL()})
.setTitle("Emoji Created!")
.setThumbnail(`https://cdn.discordapp.com/emojis/${e.id}${e.animated ? '.gif': ''}`)
.setDescription(`Name: \`:${e.name}:\`\nID: ${e.id}\nURL: [Click Me](https://cdn.discordapp.com/emojis/${e.id})`)
@@ -61,7 +61,7 @@ module.exports = {
: args[0],
args[1] || args[0].split(':')[1]
).then(e => message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: message.member.displayName, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.member.displayName, iconURL: message.author.displayAvatarURL()})
.setTitle("Emoji Created!")
.setThumbnail(`https://cdn.discordapp.com/emojis/${e.id}${e.animated ? '.gif': ''}`)
.setDescription(`Name: \`:${e.name}:\`\nID: ${e.id}\nURL: [Click Me](https://cdn.discordapp.com/emojis/${e.id}${e.animated ? '.gif': ''})`)
diff --git a/commands/utility/task.js b/commands/utility/task.js
new file mode 100644
index 0000000..a972c07
--- /dev/null
+++ b/commands/utility/task.js
@@ -0,0 +1,23 @@
+const Discord = require('discord.js');
+
+const Tasks = require("../../models/task");
+
+module.exports = {
+ name: "task",
+ aliases: ['t'],
+ meta: {
+ category: 'Utility',
+ description: "Create and manage server-wide tasks for checklists",
+ syntax: '`task `',
+ extra: null,
+ guildOnly: true
+ },
+ help: new Discord.MessageEmbed()
+ .setTitle("Help -> Tasks")
+ .setDescription("Tasks are a subset of checklists (`checklist`). They are based server-wide and are locked to the server. Only task or checklist assignees can mark a task as complete.")
+ .addField("Syntax", "`task `"),
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ if (!args.length) {return message.channel.send(`Syntax: \`${prefix}task \``);}
+
+ }
+};
\ No newline at end of file
diff --git a/commands/utility/todo.js b/commands/utility/todo.js
index b8c774b..3a8342b 100644
--- a/commands/utility/todo.js
+++ b/commands/utility/todo.js
@@ -49,7 +49,7 @@ module.exports = {
let totalItems = 0;
Object.keys(td.lists).forEach(l => totalItems += td.lists[l].length);
return message.channel.send({content: `Your list was successfully created!`, embeds: [new Discord.MessageEmbed()
- .setAuthor({name: message.guild ? message.member.displayName : message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.guild ? message.member.displayName : message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`List Created: ${ln}`)
.setDescription(`You now have **${Object.keys(td.lists).length}** lists (including your personal list) with a total of **${totalItems} items**.`)
.addField("Managing", `-To add to your new list, use \`${prefix}todo list ${ln} add\`.\n-To view its items, use \`${prefix}todo list ${ln} view\`.\n-To delete this list, use \`${prefix}todo list delete ${ln}\`.`)
@@ -64,7 +64,7 @@ module.exports = {
let s = ``; let lists = Object.keys(td.lists);
let i; for (i = 0; i < lists.length; i++) {if (lists[i] === 'quick') {continue;} s += `**${i}**. \`${lists[i]}\` - ${td.lists[lists[i]].length} ${td.lists[lists[i]].length === 1 ? 'item' : 'items'}\n`;}
message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: message.guild ? message.member.displayName : message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.guild ? message.member.displayName : message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`Your ToDo lists`)
.setDescription(s)
.addField("Deletion", "To delete a list, please reply with the **name** of the list you'd like to delete.")
@@ -92,7 +92,7 @@ module.exports = {
let i; for (i = 0; i < lists.length; i++) {if (lists[i] === 'quick') {continue;} s += `**${i}**. \`${lists[i]}\` - ${td.lists[lists[i]].length} ${td.lists[lists[i]].length === 1 ? 'item' : 'items'}\n`;}
s += `\nPlus ${td.lists.quick.length} items in your quick list.`;
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: message.guild ? message.member.displayName : message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.guild ? message.member.displayName : message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(`Your ToDo lists`)
.setDescription(s)
.setColor("c375f0")
@@ -118,7 +118,7 @@ module.exports = {
td.markModified(`lists.${list}`);
td.save();
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: "To-Do Added!", iconURL: message.author.avatarURL()})
+ .setAuthor({name: "To-Do Added!", iconURL: message.author.displayAvatarURL()})
.setDescription(`${item}\n\`->\` In ${list === 'quick' ? "your personal quick list" : `list \`${list}\``}`)
.setColor('c375f0')
]});
@@ -157,7 +157,7 @@ module.exports = {
td.markModified(`lists.${list}`);
td.save();
let resembed = new Discord.MessageEmbed()
- .setAuthor({name: `To-Do Item${items.length > 1 ? 's' : ''} Added!`, iconURL: message.author.avatarURL()})
+ .setAuthor({name: `To-Do Item${items.length > 1 ? 's' : ''} Added!`, iconURL: message.author.displayAvatarURL()})
.setDescription(`In ${list === 'quick' ? "your personal quick list" : `list \`${list}\``}\n- ${items.join('\n- ')}`)
.setColor('c375f0');
if (reachedMax) {resembed.addField("Notice", "The list addition process was automatically stopped because your list reached the maximum limit of 25 items.");}
@@ -174,7 +174,7 @@ module.exports = {
let n = 0; let i;
for (i of td.lists[list]) {n++; s += `**${n}.** ${i}\n`;}
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: message.guild ? message.member.displayName : message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.guild ? message.member.displayName : message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(list === "quick" ? "Personal Quick List" : `List: "${list}"`)
.setDescription(s)
.setColor("c375f0")
@@ -189,7 +189,7 @@ module.exports = {
let id = ['last', 'l'].includes(args[1].toLowerCase().trim()) ? td.lists[list].length : Number(args[1]);
if (id < 1 || id > td.lists[list].length) {return message.channel.send("Your number was either below 1 or doesn't have a list item to match it.");}
return message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: message.guild ? message.member.displayName : message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.guild ? message.member.displayName : message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(list === "quick" ? "Personal Quick List" : `List "${list}"`)
.setDescription(`List item **#${id}**\n\`->\` ${td.lists[list][id-1]}`)
.setColor("c375f0")
@@ -209,7 +209,7 @@ module.exports = {
let s = '';
let n = 0; let i; for (i of td.lists[list]) {n++; s += `**${n}.** ${i}\n`;}
await message.channel.send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: message.guild ? message.member.displayName : message.author.username, iconURL: message.author.avatarURL()})
+ .setAuthor({name: message.guild ? message.member.displayName : message.author.username, iconURL: message.author.displayAvatarURL()})
.setTitle(list === "quick" ? "Personal Quick List" : `List "${list}"`)
.setDescription(s)
.addField("Deletion", "To remove an item from your list, please reply with the number of the item you no longer want on your list.")
diff --git a/events/channelCreate.js b/events/channelCreate.js
index 70a57d6..07b095d 100644
--- a/events/channelCreate.js
+++ b/events/channelCreate.js
@@ -8,7 +8,7 @@ module.exports = (client, channel) => {
.setTitle("New Channel")
.setDescription(`<#${channel.id}> || **#${channel.name}**${channel.parent && channel.parent.name ? `\nCategory: **${channel.parent.name}**` : ''}`)
.setColor('936b30')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}}
diff --git a/events/channelDelete.js b/events/channelDelete.js
index bdf482e..474096d 100644
--- a/events/channelDelete.js
+++ b/events/channelDelete.js
@@ -7,7 +7,7 @@ module.exports = (client, channel) => {
.setTitle("Channel Deleted")
.setDescription(`Name: **#${channel.name}**${channel.parent && channel.parent.name ? `\nCategory: **${channel.parent.name}**` : ''}`)
.setColor('936b30')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
]});
}}
diff --git a/events/guildCreate.js b/events/guildCreate.js
index 50c1b9a..a4eff58 100644
--- a/events/guildCreate.js
+++ b/events/guildCreate.js
@@ -15,10 +15,10 @@ module.exports = async (client, guild) => {
botData.save();
client.guilds.cache.get('762707532417335296').channels.cache.get('766031709866557471').send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: 'New Guild Added', iconURL: client.users.cache.get(guild.ownerId).avatarURL()})
+ .setAuthor({name: 'New Guild Added', iconURL: client.users.cache.get(guild.ownerId).displayAvatarURL()})
.setTitle(guild.name)
.setThumbnail(guild.iconURL({size: 2048}))
- .addField('Owner', client.users.cache.get(guild.ownerId).tag, true)
+ .addField('Owner', `${client.users.cache.get(guild.ownerId).tag}`, true)
.addField('Members', `${guild.members.cache.size}`, true)
.addField('Position', `Server #${client.guilds.cache.size}`, true)
.setColor('55ff7f')
diff --git a/events/guildDelete.js b/events/guildDelete.js
index 0a76a8a..353659f 100644
--- a/events/guildDelete.js
+++ b/events/guildDelete.js
@@ -14,11 +14,11 @@ module.exports = async (client, guild) => {
botData.save();
client.guilds.cache.get('762707532417335296').channels.cache.get('766031709866557471').send({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: 'Server Lost', iconURL: client.users.cache.get(guild.ownerId).avatarURL()})
+ .setAuthor({name: 'Server Lost', iconURL: client.users.cache.get(guild.ownerId).displayAvatarURL()})
.setTitle(guild.name)
.setThumbnail(guild.iconURL({size: 2048}))
- .addField('Owner', client.users.cache.get(guild.ownerId).tag, true)
- .addField('Members', guild.members.cache.size, true)
+ .addField('Owner', `${client.users.cache.get(guild.ownerId).tag}`, true)
+ .addField('Members', `${guild.members.cache.size}`, true)
.addField('Position', `Server #${client.guilds.cache.size + 1}`, true)
.setColor('ff5d6a')
.setFooter({text: "Natsuki"})
diff --git a/events/messageCreate.js b/events/messageCreate.js
index 957155e..a109006 100644
--- a/events/messageCreate.js
+++ b/events/messageCreate.js
@@ -8,10 +8,13 @@ const AR = require('../models/ar');
const LXP = require('../models/localxp');
const Monitors = require('../models/monitor');
const Monners = require('../models/monners');
+const RP = require('../models/rpch');
const channelTypes = ["GUILD_MESSAGE", "DM", "GUILD_NEWS_THREAD", "GUILD_PRIVATE_THREAD", "GUILD_PUBLIC_THREAD", "GUILD_NEWS", "GROUP_DM", "GUILD_STORE", "GUILD_TEXT"];
module.exports = async (client, message) => {
+ if (!client.misc.fullyReady) {return;}
+
if (message.partial) {await message.fetch();}
if (message.channel.partial) {await message.channel.fetch();}
@@ -19,11 +22,10 @@ module.exports = async (client, message) => {
if (!channelTypes.includes(message.channel.type)) {return undefined;}
- //if (message.channel.type == "text") {if (settings[message.guild.id]) {prefix = settings[message.guild.id].prefix;};};
-
if (message.guild && !message.member.permissions.has("SEND_MESSAGES")) {return undefined;}
- let prefix = message.guild ? client.guildconfig.prefixes.has(message.guild.id) ? client.guildconfig.prefixes.get(message.guild.id) !== null ? client.guildconfig.prefixes.get(message.guild.id) : 'n?' : 'n?' : 'n?';
+ let defaultPrefix = client.misc.config.dev ? 'n!' : 'n?';
+ let prefix = message.guild ? client.guildconfig.prefixes.has(message.guild.id) ? client.guildconfig.prefixes.get(message.guild.id) !== null ? client.guildconfig.prefixes.get(message.guild.id) : defaultPrefix : defaultPrefix : defaultPrefix;
let msg = message.content.toLowerCase().replace('\u200E', '');
let mention = message.mentions.users.first();
@@ -34,6 +36,8 @@ module.exports = async (client, message) => {
: message.content.slice(3 + client.user.id.length).trim().replace('\u200E', '').split(/\s+/g);
let cmd = args.shift().toLowerCase().trim();
+ message.misc = {mn: message.guild ? (client.misc.cache.monnersNames.get(message.guild.id) || 'Monners') : 'Monners'};
+
if (message.content.includes("@everyone")) {return;}
if ([`<@${client.user.id}>`, `<@!${client.user.id}>`].includes(msg)) {
@@ -48,14 +52,49 @@ module.exports = async (client, message) => {
if (tu && tu.statusmsg.length && tu.statusclearmode === 'auto') {
tu.statusmsg = '';
tu.statustype = '';
- tu.save();
require('../util/siftstatuses')(client, message.author.id, true);
- message.reply('Hey there! You asked me to clear your status when you send a message next, so I went ahead and did that for you.').then(m => {setTimeout(() => {m.delete().catch(() => {});}, 5000);}).catch(() => {});
+ message.reply(
+ tu.statusSleeping
+ ? tu.statussetat && (new Date().getTime() - tu.statussetat < 60 * 45 * 1000)
+ ? [
+ "Did you even sleep?! Well I cleared your status, but c'mon now!",
+ ">:( That was hardly even sleep.",
+ "You should really go back to bed.",
+ "Burning the midnight oil are we? Go back to bed!"
+ ][Math.floor(Math.random() *4)]
+ : [
+ "Good morning dear!",
+ "Heyo! Rise and shine!",
+ "Welcome! Hope you slept well.",
+ "Good morning awesome wonderful person. Ready to start the day?"
+ ][Math.floor(Math.random() *4)]
+ : 'Hey there! You asked me to clear your status when you send a message next, so I went ahead and did that for you.'
+ ).then(m => {setTimeout(() => {m.delete().catch(() => {});}, 5000);}).catch(() => {});
+ if (tu.statusSleeping) {
+ tu.statusSleeping = false; tu.markModified('statusSleeping');
+ if (tu.statussetat && (new Date().getTime() - tu.statussetat < 60 * 45 * 1000)) {client.misc.cache.returnToSleep.set(message.author.id, new Date().getTime());}
+ }
+ tu.save();
}});
+ if (message.guild && client.misc.cache.rp.has(message.guild.id) && client.misc.cache.rp.get(message.guild.id).includes(message.channel.id)) {
+ if (msg.match(/^\w+:/m)) {
+ const rp = await RP.findOne({uid: message.author.id});
+ if (rp && rp.chars[msg.split(':')[0]]) {
+ const webhooks = await message.channel.fetchWebhooks();
+ const webhook = await webhooks.find(wh => wh.token);
+ if (webhook) {
+ const char = rp.chars[msg.split(':')[0]];
+ webhook.send({content: message.content.slice(char.prefix.length + 1), avatarURL: char.image, username: char.name}).catch(() => {});
+ message.delete().catch(() => {});
+ }
+ }
+ }
+ }
+
if (message.guild && client.misc.cache.ar.has(message.guild.id) && client.misc.cache.ar.get(message.guild.id).includes(msg.trim()) && !(client.misc.cache.arIgnore.has(message.guild.id) && client.misc.cache.arIgnore.get(message.guild.id).includes(message.channel.id))) {
AR.findOne({gid: message.guild.id}).then(ar => {
- if (ar && ar.triggers.length && ar.triggers.includes(msg.trim())) {return message.channel.send(ar.ars[ar.triggers.indexOf(msg.trim())]).catch(() => {});}
+ if (ar && ar.triggers.length && ar.triggers.includes(msg.trim())) {return require('../util/response/filterresponse')(message.member, client, ar.ars[ar.triggers.indexOf(msg.trim())]).then(t => message.channel.send(t).catch(() => {})).catch(() => {});}
});
}
@@ -78,11 +117,22 @@ module.exports = async (client, message) => {
}
}
- //if (message.guild && client.misc.cache.chests.includes(message.guild.id)) {require('../util/lxp/spawnchest')(client, message.member, message.channel, prefix);}
+ if (message.guild && client.misc.cache.chests.enabled.includes(message.guild.id)) {require('../util/lxp/spawnchest')(client, message.member, message.channel, prefix);}
if (!client.misc.cache.monners[message.author.id]) {
let tmonners = await Monners.findOne({uid: message.author.id}) || new Monners({uid: message.author.id});
client.misc.cache.monners[message.author.id] = tmonners.currency;
+ client.misc.cache.lastMonners[message.author.id] = new Date().getTime() - (62 * 1000);
+ }
+
+ if (message.guild && client.misc.cache.lastMonners[message.author.id] && new Date().getTime() - client.misc.cache.lastMonners[message.author.id] > 60000) {
+ client.misc.cache.monners[message.author.id] += (Math.floor(
+ (client.misc.cache.lxp.xp[message.guild.id] && client.misc.cache.lxp.xp[message.guild.id][message.author.id]
+ ? client.misc.cache.lxp.xp[message.guild.id][message.member.id].level
+ : 35)
+ / 35
+ ) + 1);
+ client.misc.cache.lastMonners[message.author.id] = new Date().getTime();
}
if (message.guild && client.misc.cache.monitEnabled.includes(message.guild.id)) {
@@ -114,9 +164,8 @@ module.exports = async (client, message) => {
if (!command) {let trigger; for (trigger of client.responses.triggers) {if (await trigger[1](message, msg, args, cmd, prefix, mention, client)) {await client.responses.commands.get(trigger[0]).execute(message, msg, args, cmd, prefix, mention, client); break;}} return;}
if (message.guild && !message.channel.permissionsFor(client.user.id).has('SEND_MESSAGES')) {return message.author.send(`You tried to run the \`${command.name}\` command, but I don't seem to be able to send messages in <#${message.channel.id}>, so I can't do that!`).catch(() => {});};
- message.channel.sendTyping().catch(() => {});
+ await message.channel.sendTyping().catch(() => {});
if (!require('../util/cooldownhandler')(client, message, command)) {return;}
- await wait(500);
if (command.meta && command.meta.guildOnly && !message.guild) {return message.channel.send("You must be in a server to use this command!").catch(() => {});}
require('../util/oncommand')(message, msg, args, cmd, prefix, mention, client);
if (client.misc.loggers.cmds) {client.misc.loggers.cmds.send(`${chalk.gray("[CMDL]")} >> ${chalk.white("Command")} ${chalk.blue(command.name)} ${message.guild ? `|| ${chalk.blue("Guild ID: ")} ${chalk.blueBright(message.guild.id)}` : ''} || ${chalk.blue("User ID: ")} ${chalk.blueBright(message.author.id)}`);}
diff --git a/events/messageDelete.js b/events/messageDelete.js
index 0ed4866..1e0eb63 100644
--- a/events/messageDelete.js
+++ b/events/messageDelete.js
@@ -17,8 +17,8 @@ module.exports = async (client, message) => {
let mde = new Discord.MessageEmbed()
.setTitle('Message Deleted')
.setDescription(`Sent by <@${message.author.id}> | In <#${message.channel.id}>`)
- .setThumbnail(message.author.avatarURL({size: 1024}))
- .setColor('ecff8f').setFooter({text: "Natsuki", iconURL: client.user.avatarURL()}).setTimestamp();
+ .setThumbnail(message.author.displayAvatarURL({size: 1024}))
+ .setColor('ecff8f').setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()}).setTimestamp();
if (message.content && message.content.length) {mde.addField("Message", "`-> `" + message.content.toString());}
if (message.attachments.size) {
if (message.attachments.first().url.includes(".png") || message.attachments.first().url.includes(".jpg") || message.attachments.first().url.includes(".gif")) {/*console.log('e');*/ try {mde.setImage(message.attachments.first().url);} catch {}}
diff --git a/events/messageReactionAdd.js b/events/messageReactionAdd.js
index 2872309..2fe3bac 100644
--- a/events/messageReactionAdd.js
+++ b/events/messageReactionAdd.js
@@ -16,9 +16,9 @@ module.exports = async (client, reaction, user) => {
let starEmbed = new Discord.MessageEmbed()
.setTitle('Starred Message!')
.setDescription(`Sent by ${reaction.message.member.displayName} (<@${reaction.message.author.id}>) || Channel: ${reaction.message.channel.name} (<#${reaction.message.channel.id}>)\n[Jump to Message](${reaction.message.url})`)
- .setThumbnail(reaction.message.author.avatarURL({size: 2048}))
+ .setThumbnail(reaction.message.author.displayAvatarURL({size: 2048}))
.setColor('ebb931')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp();
if (reaction.message.content.length) {starEmbed.addField("Message", reaction.message.content);}
starEmbed
diff --git a/events/messageUpdate.js b/events/messageUpdate.js
index f0fcdad..6406f39 100644
--- a/events/messageUpdate.js
+++ b/events/messageUpdate.js
@@ -20,10 +20,10 @@ module.exports = async (client, oldM, newM) => {
let embed = new Discord.MessageEmbed()
.setTitle('Message Edited')
.setDescription(`Sent by <@${oldM.author.id}> | In <#${oldM.channel.id}> | [See Message](${oldM.url})`)
- .setThumbnail(oldM.author.avatarURL({size: 1024}))
+ .setThumbnail(oldM.author.displayAvatarURL({size: 1024}))
.addField("Old Message", "`-> `" + oldM.content.toString())
.addField("New Message", "`-> `" + newM.content.toString())
- .setColor('8034eb').setFooter({text: "Natsuki", iconURL: client.user.avatarURL()}).setTimestamp();
+ .setColor('8034eb').setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()}).setTimestamp();
if (newM.attachments.size && ['.png', '.jpg', '.gif'].includes(newM.attachments.first().url.slice(newM.attachments.first().url.length - 4, newM.attachments.first().url.length))) {embed.setImage(newM.attachments.first().url);}
oldM.guild.channels.cache.get(ts).send({embeds: [embed]}).catch(() => {});
}}
diff --git a/events/ready.js b/events/ready.js
index 63de9f4..752a590 100644
--- a/events/ready.js
+++ b/events/ready.js
@@ -5,6 +5,7 @@ const lastfm = require("lastfm");
const GuildSettings = require('../models/guild');
const BotDataSchema = require('../models/bot');
const LogData = require('../models/log');
+const Saves = require('../models/saves');
const siftStatuses = require('../util/siftstatuses');
const localXPCacheClean = require('../util/lxp/cacheloop');
@@ -16,12 +17,10 @@ let prefix = 'n?';
module.exports = async client => {
if (client.misc.readied) {return;}
client.misc.readied = true;
+ await client.misc.botFinished;
const config = client.config;
- /*let db = mongoose.connection;
- await db.guild.update({}, {"$set": {'prefix': ''}}, false, true);*/
-
console.log(`\n${chalk.green('[BOOT]')} >> [${moment().format('L LTS')}] -> ${chalk.greenBright("Connected to Discord")}.`);
let date = new Date; date = date.toString().slice(date.toString().search(":") - 2, date.toString().search(":") + 6);
console.log(`\n${chalk.gray('[INFO]')} >> ${chalk.white(`Logged in at ${date}.`)}`);
@@ -39,7 +38,11 @@ module.exports = async client => {
`${Math.ceil(Math.random() * 100)} days of trying to become a samurai`,
"with the sauce", "witch hats are >", "explosion magic is the best magic",
"with Kazuma's sanity", "please help i gave myself cat ears",
- "starting my own harem", "wor. wor never changes", "a little more UwU than necessary"
+ "starting my own harem", "wor. wor never changes", "a little more UwU than necessary",
+ "please i just want a cat girl in my life", "i'm your waifu now.",
+ "i'm in intervention for my neko addiction", "i tried to make a catgirl and broke my staff",
+ "fluffy tails = drugs", "in a dungeon without wearing my plot armor",
+ "benefits of Natsuki worship: my beautiful face"
,`in ${client.guilds.cache.size} servers`
],
"WATCHING": [
@@ -51,7 +54,9 @@ module.exports = async client => {
"The Misfit of Demon King Academy", "Akame ga Kill", "a witch explode a castle",
"Code Geass", "\"did you really think ___ would be enough to kill me?\"",
"hentacle tentai", "JIBUN WO-", "he did it... he actually made risotto",
- ""
+ "sasageyo, sasageyo, chi nto wo sasegeyo", "scientists make nekos real :3",
+ "yet another isekai don't @ me", "magical girl anime", "episode 1 of One Piece.. pain.",
+ "a white-haired dude and a goddess with some MELONS"
,`over ${client.guilds.cache.size} servers`
]
};
@@ -82,14 +87,15 @@ module.exports = async client => {
await require('../util/cache')(client);
+ let mnsaves = await Saves.findOne({name: 'monnersnames'}) || new Saves({name: 'monnersnames'});
+ client.misc.cache.monnersNames = mnsaves.saves;
+
setInterval(() => localXPCacheClean(client), 150000);
setInterval(() => monitorCacheClean(client), 150000);
setInterval(() => vcloop(client), 60000);
- let botData = await BotDataSchema.findOne({finder: 'lel'})
- ? await BotDataSchema.findOne({finder: 'lel'})
- : new BotDataSchema({
+ let botData = await BotDataSchema.findOne({finder: 'lel'}) || new BotDataSchema({
finder: 'lel',
commands: 0,
servers: 0,
@@ -98,15 +104,18 @@ module.exports = async client => {
lastRestart: new Date(),
errors_all: 0,
});
- botData.restarts = botData.restarts + 1;
- botData.lastRestart = new Date();
+ if (!client.misc.config.dev) {
+ botData.restarts = botData.restarts + 1;
+ botData.lastRestart = new Date();
+ await botData.save();
+ }
console.log(`${chalk.gray('\n[INFO]')} >> ${chalk.white(`This is restart #${botData.restarts}.`)}`);
let cms = new Date().getTime();
console.log(`${chalk.gray('\n[INFO]')} >> ${chalk.white(`Startup completed in ${cms - client.misc.startup.getTime() - (client.misc.forcedReady ? 5000 : 0)}ms (${cms - client.misc.startupNoConnect.getTime() - (client.misc.forcedReady ? 5000 : 0)}ms post-connect).`)}`);
- await botData.save();
+ client.misc.fullyReady = true;
require('../console')(client);
};
\ No newline at end of file
diff --git a/events/voiceStateUpdate.js b/events/voiceStateUpdate.js
index fdf525d..6092153 100644
--- a/events/voiceStateUpdate.js
+++ b/events/voiceStateUpdate.js
@@ -8,16 +8,16 @@ module.exports = async (client, oldState, voice) => {
if (oldState.channelId && voice.channelId) {
voice.guild.channels.cache.get(ts).send({embeds: [new Discord.MessageEmbed()
.setTitle(`Member Switched VCs`)
- .setThumbnail(client.users.cache.get(oldState.member.id).avatarURL({size: 2048, dynamic: true}))
+ .setThumbnail(client.users.cache.get(oldState.member.id).displayAvatarURL({size: 2048, dynamic: true}))
.setDescription(`Old Channel: **${oldState.channel.name}**\nNew Channel: **${voice.channel.name}**`)
- .setColor('e86b8f').setFooter({text: "Natsuki", iconURL: client.user.avatarURL()}).setTimestamp()
+ .setColor('e86b8f').setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()}).setTimestamp()
]}).catch(() => {});
} else {
voice.guild.channels.cache.get(ts).send({embeds: [new Discord.MessageEmbed()
.setTitle(`Member ${voice.channelId ? 'Joined' : 'Left'} VC`)
- .setThumbnail(client.users.cache.get(oldState.member.id).avatarURL({size: 2048, dynamic: true}))
+ .setThumbnail(client.users.cache.get(oldState.member.id).displayAvatarURL({size: 2048, dynamic: true}))
.setDescription(`Channel: **${voice.channelId ? voice.channel.name : oldState.channel.name}**`)
- .setColor('e86b8f').setFooter({text: "Natsuki", iconURL: client.user.avatarURL()}).setTimestamp()
+ .setColor('e86b8f').setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()}).setTimestamp()
]}).catch(() => {});
}
}}
diff --git a/handle/command.js b/handle/command.js
index 2cdbced..6dfd92e 100644
--- a/handle/command.js
+++ b/handle/command.js
@@ -1,35 +1,32 @@
const Discord = require('discord.js');
const fs = require('fs');
const chalk = require('chalk');
-const ora = require('ora');
+const gs = require('gradient-string');
-module.exports = client => {
- let commands = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
- let dirSet = new Map();
- fs.readdirSync('./commands').filter(file => !file.includes('.')).forEach(dir => fs.readdirSync(`./commands/${dir}`).filter(file => file.endsWith('.js')).forEach(x => {commands.push(x); dirSet.set(x, dir)}));
+let iters = ['command', 'event', 'response'];
- //console.log('');
- //let cora = ora(`${chalk.white("Loading commands into client.")} ${chalk.blue("[")}${chalk.blueBright("0")}${chalk.blue("/")}${chalk.blueBright(`${commands.length}`)}${chalk.blue("]")}`).start();
- //let num = 0;
- commands.sort();
- console.log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Getting Commands...')}\n`);
- for (let commandf of commands) {
- //num++;
- //cora.text = `${chalk.white("Loading commands into client.")} ${chalk.blue("[")}${chalk.blueBright(`${num}`)}${chalk.blue("/")}${chalk.blueBright(`${commands.length}`)}${chalk.blue("]")}`;
- if (Object.keys(require.cache).includes(require.resolve(`../commands/${dirSet.has(commandf) ? `${dirSet.get(commandf)}/`: ''}${commandf}`))) {delete require.cache[require.resolve(`../commands/${dirSet.has(commandf) ? `${dirSet.get(commandf)}/`: ''}${commandf}`)];}
- let command = require(`../commands/${dirSet.has(commandf) ? `${dirSet.get(commandf)}/`: ''}${commandf}`);
- const addCommand = (command) => {
- client.commands.set(command.name, command);
- if (command.aliases) {command.aliases.forEach(a => client.aliases.set(a, command.name));}
- console.log(`${chalk.gray('[LOAD]')} >> ${chalk.blueBright('Loaded Command')} ${chalk.white(command.name)} ${chalk.blueBright('with')} ${chalk.white(command.aliases && command.aliases.length ? command.aliases.length : 0)} ${chalk.blueBright('aliases')}`);
- };
- if (command.commands) {command.commands.forEach(cmd => addCommand(cmd));}
- else {addCommand(command);}
- }
- //cora.stop(); cora.clear();
- //console.log(`${chalk.gray('[BOOT]')} >> ${chalk.blue('Getting Commands...')}\n`);
- Array.from(client.commands.values()).forEach(command => {
- //console.log(`${chalk.gray('[LOAD]')} >> ${chalk.blueBright('Loaded Command')} ${chalk.white(command.name)} ${chalk.blueBright('with')} ${chalk.white(command.aliases && command.aliases.length ? command.aliases.length : 0)} ${chalk.blueBright('aliases')}`);
+module.exports = async client => {
+ return new Promise(resolve => {
+ let commands = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
+ let dirSet = new Map();
+ fs.readdirSync('./commands').filter(file => !file.includes('.')).forEach(dir => fs.readdirSync(`./commands/${dir}`).filter(file => file.endsWith('.js')).forEach(x => {commands.push(x); dirSet.set(x, dir)}));
+
+ commands.sort();
+ const log = client.misc.config.spinners ? (i) => client.misc.cache.spinLog.push(i) : (i) => console.log(i);
+ log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Getting Commands...')}\n`);
+ for (let commandf of commands) {
+ if (Object.keys(require.cache).includes(require.resolve(`../commands/${dirSet.has(commandf) ? `${dirSet.get(commandf)}/`: ''}${commandf}`))) {delete require.cache[require.resolve(`../commands/${dirSet.has(commandf) ? `${dirSet.get(commandf)}/`: ''}${commandf}`)];}
+ let command = require(`../commands/${dirSet.has(commandf) ? `${dirSet.get(commandf)}/`: ''}${commandf}`);
+ const addCommand = (command) => {
+ client.commands.set(command.name, command);
+ if (command.aliases) {command.aliases.forEach(a => client.aliases.set(a, command.name));}
+ log(`${chalk.gray('[LOAD]')} >> ${chalk.blueBright('Loaded Command')} ${chalk.white(command.name)} ${chalk.blueBright('with')} ${chalk.white(command.aliases && command.aliases.length ? command.aliases.length : 0)} ${chalk.blueBright('aliases')}`);
+ };
+ if (command.commands) {command.commands.forEach(cmd => addCommand(cmd));}
+ else {addCommand(command);}
+ }
+ log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Loaded all Commands')}`);
+ if (client.misc.config.spinners) {client.misc.cache.spin.success('command', {text: iters.map(i => `Loaded ${i.slice(0, 1).toUpperCase()}${i.slice(1)}s`).map(i => client.misc.config.gradients ? gs.instagram(i) : chalk.blue(i))[0]});}
+ resolve(0);
});
- console.log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Loaded all Commands')}`);
};
\ No newline at end of file
diff --git a/handle/event.js b/handle/event.js
index aeea4ce..bc72cdb 100644
--- a/handle/event.js
+++ b/handle/event.js
@@ -1,17 +1,25 @@
const fs = require('fs');
const moment = require('moment');
const chalk = require('chalk');
+const gs = require('gradient-string');
-module.exports = client => {
- let eventFilter = fs.readdirSync('./events/').filter(x => x.endsWith('.js'));
- console.log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Getting Events...')}\n`);
- for (let file of eventFilter) {
- let evtName = file.split('.')[0];
- if (Object.keys(require.cache).includes(require.resolve('../events/' + file))) {delete require.cache[require.resolve('../events/' + file)];}
- let evt = require('../events/' + file);
- client.removeAllListeners(evtName);
- client.on(evtName, evt.bind(null, client));
- console.log(`${chalk.gray('[LOAD]')} >> ${chalk.blueBright('Loaded Event')} ${chalk.white(evtName)}`);
- }
- console.log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Loaded all Events')}`);
+let iters = ['command', 'event', 'response'];
+
+module.exports = async client => {
+ return new Promise(resolve => {
+ let eventFilter = fs.readdirSync('./events/').filter(x => x.endsWith('.js'));
+ const log = client.misc.config.spinners ? (i) => client.misc.cache.spinLog.push(i) : (i) => console.log(i);
+ log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Getting Events...')}\n`);
+ for (let file of eventFilter) {
+ let evtName = file.split('.')[0];
+ if (Object.keys(require.cache).includes(require.resolve('../events/' + file))) {delete require.cache[require.resolve('../events/' + file)];}
+ let evt = require('../events/' + file);
+ client.removeAllListeners(evtName);
+ client.on(evtName, evt.bind(null, client));
+ log(`${chalk.gray('[LOAD]')} >> ${chalk.blueBright('Loaded Event')} ${chalk.white(evtName)}`);
+ }
+ log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Loaded all Events')}`);
+ if (client.misc.config.spinners) {client.misc.cache.spin.success('event', {text: iters.map(i => `Loaded ${i.slice(0, 1).toUpperCase()}${i.slice(1)}s`).map(i => client.misc.config.gradients ? gs.instagram(i) : chalk.blue(i))[1]});}
+ resolve(0);
+ });
};
\ No newline at end of file
diff --git a/handle/response.js b/handle/response.js
index a8af7d7..c255765 100644
--- a/handle/response.js
+++ b/handle/response.js
@@ -1,16 +1,24 @@
const Discord = require('discord.js');
const fs = require('fs');
const chalk = require('chalk');
+const gs = require('gradient-string');
+
+let iters = ['command', 'event', 'response'];
module.exports = client => {
- var responses = fs.readdirSync('./responses').filter(file => file.endsWith('.js'));
- console.log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Getting Responses...')}\n`);
- for (let responsef of responses) {
- if (Object.keys(require.cache).includes(require.resolve(`../responses/${responsef}`))) {delete require.cache[require.resolve(`../responses/${responsef}`)];}
- var response = require(`../responses/${responsef}`);
- client.responses.triggers.push([response.name, response.condition]);
- client.responses.commands.set(response.name, response);
- console.log(`${chalk.gray('[LOAD]')} >> ${chalk.blueBright('Loaded Response')} ${chalk.white(response.name)}`);
- }
- console.log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Loaded all Responses')}`);
+ return new Promise(resolve => {
+ var responses = fs.readdirSync('./responses').filter(file => file.endsWith('.js'));
+ const log = client.misc.config.spinners ? (i) => client.misc.cache.spinLog.push(i) : (i) => console.log(i);
+ log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Getting Responses...')}\n`);
+ for (let responsef of responses) {
+ if (Object.keys(require.cache).includes(require.resolve(`../responses/${responsef}`))) {delete require.cache[require.resolve(`../responses/${responsef}`)];}
+ var response = require(`../responses/${responsef}`);
+ client.responses.triggers.push([response.name, response.condition]);
+ client.responses.commands.set(response.name, response);
+ log(`${chalk.gray('[LOAD]')} >> ${chalk.blueBright('Loaded Response')} ${chalk.white(response.name)}`);
+ }
+ log(`\n${chalk.gray('[BOOT]')} >> ${chalk.blue('Loaded all Responses')}`);
+ if (client.misc.config.spinners) {client.misc.cache.spin.success('response', {text: iters.map(i => `Loaded ${i.slice(0, 1).toUpperCase()}${i.slice(1)}s`).map(i => client.misc.config.gradients ? gs.instagram(i) : chalk.blue(i))[2]});}
+ resolve(0);
+ });
};
\ No newline at end of file
diff --git a/models/checklist.js b/models/checklist.js
new file mode 100644
index 0000000..b0e875a
--- /dev/null
+++ b/models/checklist.js
@@ -0,0 +1,14 @@
+const mongoose = require('mongoose');
+module.exports = mongoose.model('checklist', new mongoose.Schema({
+ id: String,
+ ownerId: String,
+ name: String,
+ description: String,
+ image: String,
+ children: {type: [{
+ list: Boolean,
+ id: String
+ }], default: []},
+ archived: {type: Boolean, default: false},
+ assignees: {type: [String], default: []}
+}));
\ No newline at end of file
diff --git a/models/guildlist.js b/models/guildlist.js
new file mode 100644
index 0000000..5a96d15
--- /dev/null
+++ b/models/guildlist.js
@@ -0,0 +1,6 @@
+const mongoose = require('mongoose');
+module.exports = mongoose.model('guildlist', new mongoose.Schema({
+ gid: {type: String, unique: true},
+ lists: {type: Object, default: {}},
+ admin: {type: Boolean, default: false}
+}));
\ No newline at end of file
diff --git a/models/monnersnames.js b/models/monnersnames.js
new file mode 100644
index 0000000..e69de29
diff --git a/models/rpch.js b/models/rpch.js
new file mode 100644
index 0000000..dcf272e
--- /dev/null
+++ b/models/rpch.js
@@ -0,0 +1,10 @@
+const mongoose = require('mongoose');
+
+const RPCh = new mongoose.Schema({
+ uid: {type: String, unique: true, required: true},
+ chars: {type: Object, default: {}},
+ defaults: {type: Object, default: {}},
+ default: {type: String}
+});
+
+module.exports = mongoose.model('rpch', RPCh);
\ No newline at end of file
diff --git a/models/rpconfig.js b/models/rpconfig.js
new file mode 100644
index 0000000..ca2b955
--- /dev/null
+++ b/models/rpconfig.js
@@ -0,0 +1,8 @@
+const mongoose = require('mongoose');
+
+const s = new mongoose.Schema({
+ gid: {type: String, required: true, unique: true},
+ channels: {type: [String], default: []}
+});
+
+module.exports = mongoose.model('rpconfig', s);
\ No newline at end of file
diff --git a/models/task.js b/models/task.js
new file mode 100644
index 0000000..e69de29
diff --git a/models/user.js b/models/user.js
index 9b6f51c..e213ef9 100644
--- a/models/user.js
+++ b/models/user.js
@@ -9,6 +9,7 @@ const UserSchema = new mongoose.Schema({
statusclearat: {type: Date, default: null},
statussetat: {type: Date, default: null},
statusshowcleartime: {type: Boolean, default: true},
+ statusSleeping: Boolean,
statusshowsettime: {type: Boolean, default: true},
support: {type: Boolean, default: false},
staff: {type: Boolean, default: false},
@@ -17,7 +18,9 @@ const UserSchema = new mongoose.Schema({
blacklisted: {type: Boolean, default: false},
donator: {type: Boolean, default: false},
bio: {type: String, default: ''},
- color: {type: String, default: ''}
+ color: {type: String, default: ''},
+ msg: {type: Boolean},
+ marriedTo: {type: String}
});
module.exports = mongoose.model("user", UserSchema);
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 31c6366..3f49341 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,23 +8,28 @@
"name": "natsuki",
"version": "1.0.0",
"dependencies": {
+ "@discordjs/builders": "^0.12.0",
"@discordjs/rest": "^0.1.0-canary.0",
"@discordjs/voice": "^0.6.0",
- "canvas": "^2.8.0",
+ "canvas": "^2.9.0",
"chalk": "^4.1.0",
"cron": "^1.8.2",
"dblapi.js": "^2.4.1",
"discord-api-types": "^0.22.0",
"discord.js": "^13.5.0",
+ "dreidels": "^0.5.2",
"fuzzysort": "^1.1.4",
+ "gradient-string": "^2.0.0",
"lastfm": "^0.9.0",
"manyitems": "^1.0.2",
"moment": "^2.28.0",
"moment-precise-range-plugin": "^1.3.0",
"mongoose": "^5.10.3",
"node-fetch": "^2.6.1",
+ "node-osu": "^2.2.1",
"ora": "^5.3.0",
"swwrap": "^1.0.0",
+ "tinygradient": "^1.1.5",
"ws": "^7.4.6"
},
"engines": {
@@ -32,25 +37,24 @@
}
},
"node_modules/@discordjs/builders": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.11.0.tgz",
- "integrity": "sha512-ZTB8yJdJKrKlq44dpWkNUrAtEJEq0gqpb7ASdv4vmq6/mZal5kOv312hQ56I/vxwMre+VIkoHquNUAfnTbiYtg==",
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.12.0.tgz",
+ "integrity": "sha512-Vx2MjUZd6QVo1uS2uWt708Fd6cHWGFblAvbpL5EBO+kLl0BADmPwwvts+YJ/VfSywed6Vsk6K2cEooR/Ytjhjw==",
"dependencies": {
- "@sindresorhus/is": "^4.2.0",
- "discord-api-types": "^0.26.0",
+ "@sindresorhus/is": "^4.3.0",
+ "discord-api-types": "^0.26.1",
"ts-mixer": "^6.0.0",
"tslib": "^2.3.1",
"zod": "^3.11.6"
},
"engines": {
- "node": ">=16.0.0",
- "npm": ">=7.0.0"
+ "node": ">=16.9.0"
}
},
"node_modules/@discordjs/builders/node_modules/discord-api-types": {
- "version": "0.26.0",
- "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.0.tgz",
- "integrity": "sha512-bnUltSHpQLzTVZTMjm+iNgVhAbtm5oAKHrhtiPaZoxprbm1UtuCZCsG0yXM61NamWfeSz7xnLvgFc50YzVJ5cQ==",
+ "version": "0.26.1",
+ "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz",
+ "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ==",
"engines": {
"node": ">=12"
}
@@ -149,9 +153,9 @@
}
},
"node_modules/@sindresorhus/is": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz",
- "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==",
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz",
+ "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==",
"engines": {
"node": ">=10"
},
@@ -203,6 +207,11 @@
"node": ">= 6"
}
},
+ "node_modules/@types/tinycolor2": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/@types/tinycolor2/-/tinycolor2-1.4.3.tgz",
+ "integrity": "sha512-Kf1w9NE5HEgGxCRyIcRXR/ZYtDv0V8FVPtYHwLxl0O+maGX0erE77pQlD0gpP+/KByMZ87mOA79SjifhSB3PjQ=="
+ },
"node_modules/@types/ws": {
"version": "7.4.7",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz",
@@ -358,14 +367,26 @@
"ieee754": "^1.1.13"
}
},
+ "node_modules/call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/canvas": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.8.0.tgz",
- "integrity": "sha512-gLTi17X8WY9Cf5GZ2Yns8T5lfBOcGgFehDFb+JQwDqdOoBOcECS9ZWMEAqMSVcMYwXD659J8NyzjRY/2aE+C2Q==",
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.0.tgz",
+ "integrity": "sha512-0l93g7uxp7rMyr7H+XRQ28A3ud0dKIUTIEkUe1Dxh4rjUYN7B93+SjC3r1PDKA18xcQN87OFGgUnyw7LSgNLSQ==",
"hasInstallScript": true,
"dependencies": {
"@mapbox/node-pre-gyp": "^1.0.0",
- "nan": "^2.14.0",
+ "nan": "^2.15.0",
"simple-get": "^3.0.3"
},
"engines": {
@@ -373,15 +394,18 @@
}
},
"node_modules/chalk": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
- "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/chownr": {
@@ -443,6 +467,11 @@
"color-support": "bin.js"
}
},
+ "node_modules/colorette": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
+ "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g=="
+ },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -454,6 +483,11 @@
"node": ">= 0.8"
}
},
+ "node_modules/component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
+ },
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -464,6 +498,11 @@
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
},
+ "node_modules/cookiejar": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz",
+ "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ=="
+ },
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -574,6 +613,22 @@
"npm": ">=7.0.0"
}
},
+ "node_modules/discord.js/node_modules/@discordjs/builders": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.11.0.tgz",
+ "integrity": "sha512-ZTB8yJdJKrKlq44dpWkNUrAtEJEq0gqpb7ASdv4vmq6/mZal5kOv312hQ56I/vxwMre+VIkoHquNUAfnTbiYtg==",
+ "dependencies": {
+ "@sindresorhus/is": "^4.2.0",
+ "discord-api-types": "^0.26.0",
+ "ts-mixer": "^6.0.0",
+ "tslib": "^2.3.1",
+ "zod": "^3.11.6"
+ },
+ "engines": {
+ "node": ">=16.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
"node_modules/discord.js/node_modules/@types/ws": {
"version": "8.2.2",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz",
@@ -610,6 +665,42 @@
}
}
},
+ "node_modules/dreidels": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/dreidels/-/dreidels-0.5.2.tgz",
+ "integrity": "sha512-K8mKNQAKBdCAzDV2lPwG3xbJOZ4ETB4l2NqZmjo1viN0kThgsNXNHIsE1pq0kkysJQbguKS8WM4DKPA1ZfDxbA==",
+ "dependencies": {
+ "cli-cursor": "^3.0.0",
+ "colorette": "^1.2.1",
+ "is-observable": "^2.0.0",
+ "is-promise": "^2.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-ansi": "^5.2.0",
+ "wordwrapjs": "^4.0.0"
+ },
+ "optionalDependencies": {
+ "cli-spinners": "^2.2.0"
+ }
+ },
+ "node_modules/dreidels/node_modules/ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/dreidels/node_modules/strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dependencies": {
+ "ansi-regex": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -623,6 +714,11 @@
"node": ">=6"
}
},
+ "node_modules/fast-safe-stringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
+ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="
+ },
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
@@ -636,6 +732,15 @@
"node": ">= 6"
}
},
+ "node_modules/formidable": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz",
+ "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==",
+ "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau",
+ "funding": {
+ "url": "https://ko-fi.com/tunnckoCore/commissions"
+ }
+ },
"node_modules/fs-minipass": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
@@ -652,6 +757,11 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ },
"node_modules/fuzzysort": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/fuzzysort/-/fuzzysort-1.1.4.tgz",
@@ -676,6 +786,19 @@
"node": ">=10"
}
},
+ "node_modules/get-intrinsic": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+ "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/glob": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
@@ -695,6 +818,29 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/gradient-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/gradient-string/-/gradient-string-2.0.0.tgz",
+ "integrity": "sha512-xa+FXy1bOfJWqA4xKlKTfVXxuOwNRwvsO7Tj8oi/6Rodfgo4ENKApVOU95KxTKb7eML9E9eA2Uqq3C9LtVPM5w==",
+ "dependencies": {
+ "chalk": "^4.1.2",
+ "tinygradient": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -703,6 +849,17 @@
"node": ">=8"
}
},
+ "node_modules/has-symbols": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
+ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
@@ -771,6 +928,22 @@
"node": ">=8"
}
},
+ "node_modules/is-observable": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-2.1.0.tgz",
+ "integrity": "sha512-DailKdLb0WU+xX8K5w7VsJhapwHLZ9jjmazqCJq4X12CTgqq73TKnbRcnSLuXYPOoLQgV5IrD7ePiX/h1vnkBw==",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-promise": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
+ "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
+ },
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -850,6 +1023,25 @@
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
"optional": true
},
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/mime-db": {
"version": "1.49.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz",
@@ -1078,14 +1270,30 @@
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
},
"node_modules/node-fetch": {
- "version": "2.6.6",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz",
- "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==",
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-osu": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/node-osu/-/node-osu-2.2.1.tgz",
+ "integrity": "sha512-SM9kj+7q7j/Y5nkMSRchQi9g2RxgDQ8JjC/zds7VyzUWQPokGQW3KuiskPLHwITn3RW3V98k7Y3RB3zkLIX9jA==",
+ "dependencies": {
+ "superagent": "^5.2.1"
}
},
"node_modules/nopt": {
@@ -1121,6 +1329,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/object-inspect": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
+ "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -1227,6 +1443,20 @@
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
+ "node_modules/qs": {
+ "version": "6.10.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
+ "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -1246,6 +1476,14 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
+ "node_modules/reduce-flatten": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz",
+ "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/regexp-clone": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
@@ -1335,6 +1573,19 @@
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
+ "node_modules/side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/sift": {
"version": "13.5.2",
"resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz",
@@ -1425,6 +1676,70 @@
"node": ">=8"
}
},
+ "node_modules/superagent": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz",
+ "integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==",
+ "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .",
+ "dependencies": {
+ "component-emitter": "^1.3.0",
+ "cookiejar": "^2.1.2",
+ "debug": "^4.1.1",
+ "fast-safe-stringify": "^2.0.7",
+ "form-data": "^3.0.0",
+ "formidable": "^1.2.2",
+ "methods": "^1.1.2",
+ "mime": "^2.4.6",
+ "qs": "^6.9.4",
+ "readable-stream": "^3.6.0",
+ "semver": "^7.3.2"
+ },
+ "engines": {
+ "node": ">= 7.0.0"
+ }
+ },
+ "node_modules/superagent/node_modules/debug": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
+ "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/superagent/node_modules/form-data": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
+ "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/superagent/node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -1467,6 +1782,23 @@
"resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz",
"integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA=="
},
+ "node_modules/tinycolor2": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz",
+ "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/tinygradient": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/tinygradient/-/tinygradient-1.1.5.tgz",
+ "integrity": "sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==",
+ "dependencies": {
+ "@types/tinycolor2": "^1.4.0",
+ "tinycolor2": "^1.0.0"
+ }
+ },
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@@ -1494,6 +1826,14 @@
"node": ">=4.2.0"
}
},
+ "node_modules/typical": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz",
+ "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/underscore": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz",
@@ -1534,6 +1874,18 @@
"string-width": "^1.0.2 || 2 || 3 || 4"
}
},
+ "node_modules/wordwrapjs": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz",
+ "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==",
+ "dependencies": {
+ "reduce-flatten": "^2.0.0",
+ "typical": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -1575,21 +1927,21 @@
},
"dependencies": {
"@discordjs/builders": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.11.0.tgz",
- "integrity": "sha512-ZTB8yJdJKrKlq44dpWkNUrAtEJEq0gqpb7ASdv4vmq6/mZal5kOv312hQ56I/vxwMre+VIkoHquNUAfnTbiYtg==",
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.12.0.tgz",
+ "integrity": "sha512-Vx2MjUZd6QVo1uS2uWt708Fd6cHWGFblAvbpL5EBO+kLl0BADmPwwvts+YJ/VfSywed6Vsk6K2cEooR/Ytjhjw==",
"requires": {
- "@sindresorhus/is": "^4.2.0",
- "discord-api-types": "^0.26.0",
+ "@sindresorhus/is": "^4.3.0",
+ "discord-api-types": "^0.26.1",
"ts-mixer": "^6.0.0",
"tslib": "^2.3.1",
"zod": "^3.11.6"
},
"dependencies": {
"discord-api-types": {
- "version": "0.26.0",
- "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.0.tgz",
- "integrity": "sha512-bnUltSHpQLzTVZTMjm+iNgVhAbtm5oAKHrhtiPaZoxprbm1UtuCZCsG0yXM61NamWfeSz7xnLvgFc50YzVJ5cQ=="
+ "version": "0.26.1",
+ "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz",
+ "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ=="
}
}
},
@@ -1664,9 +2016,9 @@
"integrity": "sha512-QnzuLp+p9D7agynVub/zqlDVriDza9y3STArBhNiNBUgIX8+GL5FpQxstRfw1jDr5jkZUjcuKYAHxjIuXKdJAg=="
},
"@sindresorhus/is": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz",
- "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw=="
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz",
+ "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ=="
},
"@types/bson": {
"version": "4.0.3",
@@ -1711,6 +2063,11 @@
}
}
},
+ "@types/tinycolor2": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/@types/tinycolor2/-/tinycolor2-1.4.3.tgz",
+ "integrity": "sha512-Kf1w9NE5HEgGxCRyIcRXR/ZYtDv0V8FVPtYHwLxl0O+maGX0erE77pQlD0gpP+/KByMZ87mOA79SjifhSB3PjQ=="
+ },
"@types/ws": {
"version": "7.4.7",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz",
@@ -1841,20 +2198,29 @@
"ieee754": "^1.1.13"
}
},
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ }
+ },
"canvas": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.8.0.tgz",
- "integrity": "sha512-gLTi17X8WY9Cf5GZ2Yns8T5lfBOcGgFehDFb+JQwDqdOoBOcECS9ZWMEAqMSVcMYwXD659J8NyzjRY/2aE+C2Q==",
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.0.tgz",
+ "integrity": "sha512-0l93g7uxp7rMyr7H+XRQ28A3ud0dKIUTIEkUe1Dxh4rjUYN7B93+SjC3r1PDKA18xcQN87OFGgUnyw7LSgNLSQ==",
"requires": {
"@mapbox/node-pre-gyp": "^1.0.0",
- "nan": "^2.14.0",
+ "nan": "^2.15.0",
"simple-get": "^3.0.3"
}
},
"chalk": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
- "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -1901,6 +2267,11 @@
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="
},
+ "colorette": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
+ "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g=="
+ },
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -1909,6 +2280,11 @@
"delayed-stream": "~1.0.0"
}
},
+ "component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
+ },
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -1919,6 +2295,11 @@
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
},
+ "cookiejar": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz",
+ "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ=="
+ },
"core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -2009,6 +2390,18 @@
"ws": "^8.4.0"
},
"dependencies": {
+ "@discordjs/builders": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.11.0.tgz",
+ "integrity": "sha512-ZTB8yJdJKrKlq44dpWkNUrAtEJEq0gqpb7ASdv4vmq6/mZal5kOv312hQ56I/vxwMre+VIkoHquNUAfnTbiYtg==",
+ "requires": {
+ "@sindresorhus/is": "^4.2.0",
+ "discord-api-types": "^0.26.0",
+ "ts-mixer": "^6.0.0",
+ "tslib": "^2.3.1",
+ "zod": "^3.11.6"
+ }
+ },
"@types/ws": {
"version": "8.2.2",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz",
@@ -2030,6 +2423,36 @@
}
}
},
+ "dreidels": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/dreidels/-/dreidels-0.5.2.tgz",
+ "integrity": "sha512-K8mKNQAKBdCAzDV2lPwG3xbJOZ4ETB4l2NqZmjo1viN0kThgsNXNHIsE1pq0kkysJQbguKS8WM4DKPA1ZfDxbA==",
+ "requires": {
+ "cli-cursor": "^3.0.0",
+ "cli-spinners": "^2.2.0",
+ "colorette": "^1.2.1",
+ "is-observable": "^2.0.0",
+ "is-promise": "^2.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-ansi": "^5.2.0",
+ "wordwrapjs": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -2040,6 +2463,11 @@
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
},
+ "fast-safe-stringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
+ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="
+ },
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
@@ -2050,6 +2478,11 @@
"mime-types": "^2.1.12"
}
},
+ "formidable": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz",
+ "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ=="
+ },
"fs-minipass": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
@@ -2063,6 +2496,11 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ },
"fuzzysort": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/fuzzysort/-/fuzzysort-1.1.4.tgz",
@@ -2084,6 +2522,16 @@
"wide-align": "^1.1.2"
}
},
+ "get-intrinsic": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+ "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1"
+ }
+ },
"glob": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
@@ -2097,11 +2545,33 @@
"path-is-absolute": "^1.0.0"
}
},
+ "gradient-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/gradient-string/-/gradient-string-2.0.0.tgz",
+ "integrity": "sha512-xa+FXy1bOfJWqA4xKlKTfVXxuOwNRwvsO7Tj8oi/6Rodfgo4ENKApVOU95KxTKb7eML9E9eA2Uqq3C9LtVPM5w==",
+ "requires": {
+ "chalk": "^4.1.2",
+ "tinygradient": "^1.1.5"
+ }
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
+ "has-symbols": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
+ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
+ },
"has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
@@ -2155,6 +2625,16 @@
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
"integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="
},
+ "is-observable": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-2.1.0.tgz",
+ "integrity": "sha512-DailKdLb0WU+xX8K5w7VsJhapwHLZ9jjmazqCJq4X12CTgqq73TKnbRcnSLuXYPOoLQgV5IrD7ePiX/h1vnkBw=="
+ },
+ "is-promise": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
+ "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
+ },
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -2218,6 +2698,16 @@
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
"optional": true
},
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="
+ },
"mime-db": {
"version": "1.49.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz",
@@ -2373,13 +2863,21 @@
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
},
"node-fetch": {
- "version": "2.6.6",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz",
- "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==",
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"requires": {
"whatwg-url": "^5.0.0"
}
},
+ "node-osu": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/node-osu/-/node-osu-2.2.1.tgz",
+ "integrity": "sha512-SM9kj+7q7j/Y5nkMSRchQi9g2RxgDQ8JjC/zds7VyzUWQPokGQW3KuiskPLHwITn3RW3V98k7Y3RB3zkLIX9jA==",
+ "requires": {
+ "superagent": "^5.2.1"
+ }
+ },
"nopt": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
@@ -2404,6 +2902,11 @@
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
+ "object-inspect": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
+ "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
+ },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -2478,6 +2981,14 @@
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
+ "qs": {
+ "version": "6.10.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
+ "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
+ "requires": {
+ "side-channel": "^1.0.4"
+ }
+ },
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -2499,6 +3010,11 @@
}
}
},
+ "reduce-flatten": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz",
+ "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w=="
+ },
"regexp-clone": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
@@ -2553,6 +3069,16 @@
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
+ "side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "requires": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ }
+ },
"sift": {
"version": "13.5.2",
"resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz",
@@ -2625,6 +3151,54 @@
"ansi-regex": "^5.0.1"
}
},
+ "superagent": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz",
+ "integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==",
+ "requires": {
+ "component-emitter": "^1.3.0",
+ "cookiejar": "^2.1.2",
+ "debug": "^4.1.1",
+ "fast-safe-stringify": "^2.0.7",
+ "form-data": "^3.0.0",
+ "formidable": "^1.2.2",
+ "methods": "^1.1.2",
+ "mime": "^2.4.6",
+ "qs": "^6.9.4",
+ "readable-stream": "^3.6.0",
+ "semver": "^7.3.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
+ "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "form-data": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
+ "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -2661,6 +3235,20 @@
"resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz",
"integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA=="
},
+ "tinycolor2": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz",
+ "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA=="
+ },
+ "tinygradient": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/tinygradient/-/tinygradient-1.1.5.tgz",
+ "integrity": "sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==",
+ "requires": {
+ "@types/tinycolor2": "^1.4.0",
+ "tinycolor2": "^1.0.0"
+ }
+ },
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@@ -2681,6 +3269,11 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz",
"integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w=="
},
+ "typical": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz",
+ "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg=="
+ },
"underscore": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz",
@@ -2721,6 +3314,15 @@
"string-width": "^1.0.2 || 2 || 3 || 4"
}
},
+ "wordwrapjs": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz",
+ "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==",
+ "requires": {
+ "reduce-flatten": "^2.0.0",
+ "typical": "^5.2.0"
+ }
+ },
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
diff --git a/package.json b/package.json
index f5afab7..fb33b63 100644
--- a/package.json
+++ b/package.json
@@ -5,23 +5,28 @@
"main": "bot.js",
"author": "NatsukiDev",
"dependencies": {
+ "@discordjs/builders": "^0.12.0",
"@discordjs/rest": "^0.1.0-canary.0",
"@discordjs/voice": "^0.6.0",
- "canvas": "^2.8.0",
+ "canvas": "^2.9.0",
"chalk": "^4.1.0",
"cron": "^1.8.2",
"dblapi.js": "^2.4.1",
"discord-api-types": "^0.22.0",
"discord.js": "^13.5.0",
+ "dreidels": "^0.5.2",
"fuzzysort": "^1.1.4",
+ "gradient-string": "^2.0.0",
"lastfm": "^0.9.0",
"manyitems": "^1.0.2",
"moment": "^2.28.0",
"moment-precise-range-plugin": "^1.3.0",
"mongoose": "^5.10.3",
"node-fetch": "^2.6.1",
+ "node-osu": "^2.2.1",
"ora": "^5.3.0",
"swwrap": "^1.0.0",
+ "tinygradient": "^1.1.5",
"ws": "^7.4.6"
},
"engines": {
@@ -29,7 +34,12 @@
},
"scripts": {
"start": "node bot.js",
+ "start:pretty": "node bot.js -g -s",
"swin": "run",
- "dev": "node bot.js -dev"
+ "dev": "node bot.js -dev",
+ "dev:pretty": "node bot.js -dev -g -s",
+ "presync": "git pull origin master",
+ "sync": "git push origin master",
+ "postsync": "git push wubzy master"
}
}
diff --git a/slash/8ball.js b/slash/fun/8ball.js
similarity index 95%
rename from slash/8ball.js
rename to slash/fun/8ball.js
index b164b8a..b8063b9 100644
--- a/slash/8ball.js
+++ b/slash/fun/8ball.js
@@ -1,35 +1,35 @@
-const {SlashCommand} = require('../util/slash');
-const {SlashCommandBuilder} = require('@discordjs/builders');
-const Discord = require('discord.js');
-
-module.exports = (client) => {
- return new SlashCommand('8ball', client,
- new SlashCommandBuilder()
- .setName('8ball')
- .setDescription("Get a totally accurate and well-thought-out answer to your life's troubles.")
- .addStringOption(option => {
- return option.setName("question")
- .setDescription("Your existential crisis.")
- .setRequired(true);
- })
- .addBooleanOption(option => {
- return option.setName("send")
- .setDescription("Should I send the answer to the channel?");
- }),
-
- async (client, interaction) => {
- const responses = [
- /*Positive Responses*/ "Yes!", "I think so", "Possibly", "Certainly", "Definitely", "Absolutely", "Sure!", "Most Likely", "I believe so", "If you're asking for my honest opinion... yes"
- /*Negative Responses*/ ,"No!", "I don't think so", "Probably not", "Impossible", "Nope", "Absolutely *not*", "Nah", "Doubt it", "I don't believe so", "If you're asking for my honest opinion... no"
- /*Neutral Responses */ ,"Maybe", "I'm not sure", "I'll think about it", "Uhh Natsuki isn't here right now. I can take a message?", "I'm sure if you look deep within your heart, which is currently all over that tree, you'll find the answer", "I mean, if you think so...", "I don't have an opinion on that.", "I'll choose to remain silent."
- ];
- return await interaction.reply({embeds: [new Discord.MessageEmbed()
- .setAuthor({name: "8ball Question", iconURL: interaction.user.avatarURL()})
- .setDescription("**Question:** " + interaction.options.getString('question') + "\n**Answer:** " + responses[Math.floor(Math.random() * responses.length)])
- .setColor("c375f0")
- .setFooter({text: `Asked by ${interaction.guild ? interaction.member.displayName : interaction.user.username} | Natsuki`})
- .setTimestamp()
- ], ephemeral: !interaction.options.getBoolean("send")});
- }
- );
+const {SlashCommand} = require('../../util/slash');
+const {SlashCommandBuilder} = require('@discordjs/builders');
+const Discord = require('discord.js');
+
+module.exports = (client) => {
+ return new SlashCommand('8ball', client,
+ new SlashCommandBuilder()
+ .setName('8ball')
+ .setDescription("Get a totally accurate and well-thought-out answer to your life's troubles.")
+ .addStringOption(option => {
+ return option.setName("question")
+ .setDescription("Your existential crisis.")
+ .setRequired(true);
+ })
+ .addBooleanOption(option => {
+ return option.setName("send")
+ .setDescription("Should I send the answer to the channel?");
+ }),
+
+ async (client, interaction) => {
+ const responses = [
+ /*Positive Responses*/ "Yes!", "I think so", "Possibly", "Certainly", "Definitely", "Absolutely", "Sure!", "Most Likely", "I believe so", "If you're asking for my honest opinion... yes"
+ /*Negative Responses*/ ,"No!", "I don't think so", "Probably not", "Impossible", "Nope", "Absolutely *not*", "Nah", "Doubt it", "I don't believe so", "If you're asking for my honest opinion... no"
+ /*Neutral Responses */ ,"Maybe", "I'm not sure", "I'll think about it", "Uhh Natsuki isn't here right now. I can take a message?", "I'm sure if you look deep within your heart, which is currently all over that tree, you'll find the answer", "I mean, if you think so...", "I don't have an opinion on that.", "I'll choose to remain silent."
+ ];
+ return await interaction.reply({embeds: [new Discord.MessageEmbed()
+ .setAuthor({name: "8ball Question", iconURL: interaction.user.displayAvatarURL()})
+ .setDescription("**Question:** " + interaction.options.getString('question') + "\n**Answer:** " + responses[Math.floor(Math.random() * responses.length)])
+ .setColor("c375f0")
+ .setFooter({text: `Asked by ${interaction.guild ? interaction.member.displayName : interaction.user.username} | Natsuki`})
+ .setTimestamp()
+ ], ephemeral: !interaction.options.getBoolean("send")});
+ }
+ );
};
\ No newline at end of file
diff --git a/slash/fun/deathnote.js b/slash/fun/deathnote.js
new file mode 100644
index 0000000..9b0efd8
--- /dev/null
+++ b/slash/fun/deathnote.js
@@ -0,0 +1,132 @@
+const Discord = require('discord.js');
+const {SlashCommand} = require('../../util/slash');
+const {SlashCommandBuilder} = require('@discordjs/builders');
+
+const moment = require("moment");
+const VC = require("../../models/vscount");
+
+
+
+const deaths = [
+ "watching too much anime", "an overdose of waifus", "Hypotakunemia", "trying to self-isekai",
+ "Bass:tm:", "cranking the music just a little too loud", "trying to swim in lava",
+ "Despacito", "something really cliche and unoriginal", "'shrooms",
+ "clicking 'I agree' without reading the Terms of Service", "alchemy", "rusty spoons",
+ "picking the wrong waifu", "body pillows", "fur-con", "something to do with lamb sauce",
+ "grandma's cookies", "trying to get cat ears", "not reading the assembly instructions for that ikea furniture",
+ "the wrong kind of coke", "getting cancelled irl", "getting their credit card declined",
+ "finishing the last episode", "posting memes in #general", "stepping on a lego", "stubbing their toe",
+ "fork in toaster", "toasterbath", "signing this book without reading the cover", "being Kirby's dinner"
+]; // a list of preset death methods that can occur
+
+const before = [
+ "A name is being written...", "Someone will perish soon...", "A body is *about* to be discovered...",
+ "{w} is scribbling something in their notebook...", "\*Manical laughter echoes around you*...",
+ "{w} laughs maniacally..."
+]; // things it says before the response is sent
+
+const responses = {
+ /*an obj controlling the possible formats for the death note report*/
+ news: {
+ titles: ["Breaking News"],
+ texts: [
+ "This just in: **{p}** was found dead at **{ds}** today.\n\nAfter some investigation, the authorities ruled the cause of death to be **{c}**.",
+ "We're now live at the crime scene where it is believed that **{p}** died because of **{c}**.",
+ "Authorities are reporting what is believed to be another Kira case, where **{c}** has taken the life of **{p}**."
+ ],
+ images: [],
+ }, // a news report of the dead body
+ writes: {
+ titles: ["Something sinister just happened", "A name has been written", "Fate has been changed"],
+ texts: [
+ "With a maniacal laugh, **{w}** writes \"**{p}**\" in their Death Note. And the cause of death? They've written **{c}**.",
+ "**{w}** has sealed **{pa}** fate to die by **{c}**."
+ ],
+ images: []
+ }, // "so-and-so writes blah blah blah's name in their death note"
+ /*hasdied: {
+ texts: [],
+ images: []
+ }, // "so-and-so has died by...",
+ unserious: {
+ texts: [],
+ images: []
+ } // other methods, mainly the un-serious or joking ones */
+};
+
+
+
+module.exports = (client) => {
+ return new SlashCommand('deathnote', client,
+ new SlashCommandBuilder()
+ .setName('deathnote')
+ .setDescription("Write someone's name in the death note and see for yourself if it's the real deal...")
+ .addUserOption(option => {
+ return option.setName("victim")
+ .setDescription("The person to write in your note")
+ .setRequired(true);
+ })
+ .addStringOption(option => option
+ .setName("death-method")
+ .setDescription("Decide for yourself how you want the person to die")
+ ),
+
+ async (client, interaction, guild, prefix) => {
+ if (!guild) {return interaction.reply("Unfortunately, this is a **guild-only** command!");}
+ let user = interaction.options.getUser('victim');
+ let member = interaction.guild.members.cache.get(user.id);
+ if (!user) {return interaction.reply("Looks like you didn't provide someone to write in the deathnote!");}
+ if (user.id === interaction.user.id) {return interaction.reply("Hehe I won't let you write your own name in the notebook! Just leave it somewhere for a few days and someone else will take it. Maybe they'll write your name...");} // users can't user themselves
+ if (user.id === client.user.id) {return interaction.reply("You can't kill me! Little did you know, I'm actually a death god!");}
+ if (user.bot) {return interaction.reply("As a bot, I simply cannot let you attempt to kill another fellow bot!");}
+
+ let reptype = responses[Object.keys(responses)[Math.floor(Math.random() * Object.keys(responses).length)]]; // report type
+ let title = reptype.titles[Math.floor(Math.random() * reptype.titles.length)];
+
+ let death = interaction.options.getString('death-method') || deaths[Math.floor(Math.random() * deaths.length)]; //kill method
+ if (death.length > 750) {return interaction.reply("I'd rather you didn't try to fill the death note with a 7-page double-spaced essay in Times New Roman containing an advanced trajectory theorem on the death of your poor target.");}
+
+ let victim = member.displayName;
+ let killer = interaction.guild.members.cache.get(interaction.user.id);
+
+ let pretext = before[Math.floor(Math.random() * before.length)].replace(/{w}/g, killer.displayName);
+
+ let note = await interaction.reply({embeds: [new Discord.MessageEmbed()
+ .setDescription(pretext)
+ .setColor('c375f0')
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
+ .setTimestamp()
+ ]});
+
+ await require('../../util/wait')(2500);
+
+ let text = reptype.texts[Math.floor(Math.random() * reptype.texts.length)]
+ .replace(/{p}/g, victim) //{p} = victim
+ .replace(/{pa}/g, victim.toLowerCase().endsWith('s') ? `${victim}'` : `${victim}'s`) //{pa} = victim but with a formatted apostrophe like "WubzyGD's"
+ .replace(/{c}/g, death) // {c} = death method
+ .replace(/{w}/g, killer.displayName) // {w} = killer or writer
+ .replace(/{ds}/g, moment().format("h:mm a")); // {ds} = date small, basically just the time.
+ // Create and format the kill text
+
+ let dns;
+ if (user && user.id) {
+ dns = await VC.findOne({uid: interaction.user.id, countOf: 'dn'}) || new VC({uid: interaction.user.id, countOf: 'dn'});
+ dns.against[user.id] = dns.against[user.id] ? dns.against[user.id] + 1 : 1;
+ dns.total++;
+ dns.markModified(`against.${user.id}`);
+ dns.save();
+ }
+
+ let finalEmbed = new Discord.MessageEmbed()
+ .setAuthor({name: title, iconURL: killer.displayAvatarURL()})
+ .setDescription(`${text}${dns ? `\n\n_Their name is in your deathnote **${dns.against[user.id] === 1 ? 'once' : `${dns.against[user.id]} times`}.**_` : ''}`)
+ .setColor('c375f0')
+ .setFooter({text: `Natsuki${dns ? ` | ${dns.total} name${dns.total === 1 ? ' has been' : 's'} written in your deathnote!` : ''}`})
+ .setTimestamp();
+
+ if (user) {finalEmbed.setThumbnail(member.displayAvatarURL({size: 1024}));}
+
+ return interaction.editReply({embeds: [finalEmbed]});
+ }
+ );
+};
\ No newline at end of file
diff --git a/slash/fun/nowplaying.js.dev b/slash/fun/nowplaying.js.dev
new file mode 100644
index 0000000..1ab8ac6
--- /dev/null
+++ b/slash/fun/nowplaying.js.dev
@@ -0,0 +1,65 @@
+const Discord = require('discord.js');
+const {SlashCommand} = require('../../util/slash');
+const {SlashCommandBuilder} = require('@discordjs/builders');
+
+const Saves = require("../../models/saves");
+
+module.exports = (client) => {
+ return new SlashCommand('nowplaying', client,
+ new SlashCommandBuilder()
+ .setName('nowplaying')
+ .setDescription("Show off the music you're currently listening to through last.fm!")
+ .addBooleanOption(option => option
+ .setName("send")
+ .setDescription("Whether or not the response should be sent")
+ )
+ .addStringOption()
+ );
+};
+
+module.exports = {
+ name: "nowplaying",
+ aliases: ['np'],
+ meta: {
+ category: 'Fun',
+ description: "Show off the music you're currently listening to through last.fm!",
+ syntax: '`nowplaying [@mention]`',
+ extra: null
+ },
+ help: new Discord.MessageEmbed()
+ .setTitle("Help -> Now Playing")
+ .setDescription("Accesses last.fm's API to show off what music you're currently listening to. Use the `lfm` command for more information.")
+ .addField("Syntax", "`nowplaying [@mention]`"),
+ async execute(message, msg, args, cmd, prefix, mention, client) {
+ let savess = await Saves.findOne({name: 'lfm'}) ? await Saves.findOne({name: 'lfm'}) : new Saves({name: 'lfm'});
+ let saves = savess.saves;
+ let user = mention || message.author;
+ if (!saves.get(user.id)) {return message.channel.send(`${mention ? "That person's" : "Your"} last.fm username isn't set! ${mention ? "They" : "You"} can set it with \`${prefix}lfm set \``);}
+
+ let found = false;
+ try {
+ const glfm = function() {return new Promise(resolve => {
+ let timeout = setTimeout(() => {return resolve(undefined);}, 3000);
+ let stream = client.lfm.stream(saves.get(user.id));
+ stream.on('nowPlaying', t => {
+ clearTimeout(timeout);
+ message.channel.send({embeds: [new Discord.MessageEmbed()
+ .setAuthor({name: message.guild ? message.guild.members.cache.get(user.id) ? message.guild.members.cache.get(user.id).displayName : user.username : user.username, iconURL: user.displayAvatarURL()})
+ .setTitle(`${saves.get(user.id)} | Now Playing`)
+ .setDescription(`<@${user.id}> is currently listening to **${t.name}** by **${t.artist['#text']}**.\nView the song [here](${t.url}).`)
+ .setColor("c375f0")
+ .setThumbnail(t.image[3]['#text'])
+ .setTimestamp()
+ ]})
+ found = true;
+ stream.stop();
+ return resolve(undefined);
+ });
+ stream.start();
+ });}
+ await glfm().catch((e) => {console.error(e);});
+ } catch (e) {console.error(e);}
+
+ if (!found) {return message.channel.send(`I couldn't find what \"${saves.get(user.id)}\" is listening to. Perhaps ${!mention ? "you" : "they"}'re not listening to anything, or you got ${!mention ? "your" : "their"} name wrong?`);}
+ }
+};
\ No newline at end of file
diff --git a/slash/userinfo.js.dev b/slash/userinfo.js.dev
index d87bd27..b1cdb7d 100644
--- a/slash/userinfo.js.dev
+++ b/slash/userinfo.js.dev
@@ -31,11 +31,11 @@ module.exports = (client) => {
let infoembed = new Discord.MessageEmbed()
.setTitle(`User Info for ${name}`)
.setDescription(`Requested by ${interaction.guild ? interaction.member.displayName : interaction.user.username}`)
- .setThumbnail(client.users.cache.get(person.id).avatarURL({size: 2048}))
+ .setThumbnail(client.users.cache.get(person.id).displayAvatarURL({size: 2048}))
.addField("Account Created", moment(client.users.cache.get(person.id).createdAt).fromNow(), true)
.addField("Bot User?", client.users.cache.get(person.id).bot ? "Is a bot" : "Is not a bot", true)
.setColor('c375f0')
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp();
if (interaction.guild) {
diff --git a/util/anime/anisearch.js b/util/anime/anisearch.js
index 6845908..ef8c2ce 100644
--- a/util/anime/anisearch.js
+++ b/util/anime/anisearch.js
@@ -12,20 +12,20 @@ module.exports = async (message, client, search, threshold=-10000, type='full')
let an = ani.plot ? ani : await Ani.findOne({id: client.misc.cache.anime.get(ani)});
let rte = new Discord.MessageEmbed()
.setTitle(an.name)
- .setAuthor({name: 'Anime Search', iconURL: message.author.avatarURL()})
+ .setAuthor({name: 'Anime Search', iconURL: message.author.displayAvatarURL()})
.setDescription(`**Name:** ${an.name}\n**Japanese Name:** ${an.japname}\n\n**Publishers:** ${an.publishers.join(", ")}\n**Studios:** ${an.studios.join(", ")}`)
.setColor("c375f0")
.setImage(an.thumbnail)
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp()
if (type === 'full') {
rte
.addField('Description', an.plot)
.addField('Length', `**# of Seasons:** ${an.seasons}\n**# of Episodes:** ${an.episodes}`)
- .addField('Airing', `**Began:** ${an.airStartDate}\n**Ended:** ${an.isComplete ? an.airEndDate : 'This anime is still airing!'}`)
- .addField("Cast", `**${an.characters.length} Characters**\n${an.characters.map(char => client.misc.cache.charsID.get(char)).join(', ')}`)
- .addField('Other', `**Genre(s):** ${an.genres.join(", ")}\n**Tags:** ${an.tags.join(", ")}\n**Stream this at:** ${an.streamAt.join(", ")}${an.altNames && an.altNames.length ? `\n\n**Other names:** ${an.altNames.map(n => `\`${n}\``).join(', ')}` : ''}`)
- .addField('Love', `**Watchers**: **${an.watchers} Natsuki ${client.utils.as(an.watchers, 'user')}** have this anime on their list of finished anime!\n\`n?watched ${an.name}\``)
+ //.addField('Airing', `**Began:** ${an.airStartDate}\n**Ended:** ${an.isComplete ? an.airEndDate : 'This anime is still airing!'}`)
+ .addField("Cast", `**${an.characters.length} Characters**\n${(an.characters.length > 50 ? an.characters.slice(0, 49) : an.characters).map(char => client.misc.cache.charsID.get(char)).join(', ')}${an.characters.length > 50 ? `\n**+${an.characters.length - 50} Others**` : ''}`)
+ .addField('Other', `**Genre(s):** ${an.genres.join(", ")}\n**Stream this at:** ${an.streamAt.join(", ")}${an.altNames && an.altNames.length ? `\n\n**Other names:** ${an.altNames.map(n => `\`${n}\``).join(', ')}` : ''}`)
+ .addField('Love', `**Watchers**: **${an.watchers} Natsuki ${client.utils.as(an.watchers, 'user')}** ${an.watchers === 1 ? 'has' : "have"} this anime on their list of finished anime!\n\`n?watched ${an.name}\`\n**Watchlisted**: **${an.listed} Natsuki ${client.utils.as(an.listed, 'user')}** ${an.listed === 1 ? 'has' : "have"} this anime on their list of anime they want to watch!\n\`n?watchlist add ${an.name}\`\n**Favorited**: **${an.liked} Natsuki ${client.utils.as(an.liked, 'user')}** ${an.liked === 1 ? 'has' : "have"} this anime favorited!\n\`n?favanime ${an.name}\``)
}
da.push(an.id);
return {embed: rte, id: an.id};
diff --git a/util/anime/charsearch.js b/util/anime/charsearch.js
index 7e27262..f3aa07f 100644
--- a/util/anime/charsearch.js
+++ b/util/anime/charsearch.js
@@ -13,15 +13,16 @@ module.exports = async (message, client, search, threshold=-10000, type='full')
let cch = char.anime ? char : await Char.findOne({id: client.misc.cache.chars.get(char)});
let ani = await Ani.findOne({id: cch.anime});
let forceAni = false; if (!ani) {forceAni = true;}
+ //console.log(cch.images, cch.thumbnail);
cch.images.push(cch.thumbnail);
let rte = new Discord.MessageEmbed()
.setTitle(cch.name)
- .setAuthor({name: 'Character Search', iconURL: message.author.avatarURL()})
+ .setAuthor({name: 'Character Search', iconURL: message.author.displayAvatarURL()})
.setDescription(`**Name:** ${cch.name}`)
.addField('Other', `**Anime**: ${forceAni ? cch.anime : `${ani.name} | ${ani.japname} | \`${ani.id}\``}\n\n**Gender**: ${cch.gender}\n`)
.setColor("c375f0")
- .setImage(cch.images[Math.floor(Math.random() * (cch.images.length + 1))])
- .setFooter({text: "Natsuki", iconURL: client.user.avatarURL()})
+ .setImage(cch.images[Math.floor(Math.random() * cch.images.length)])
+ .setFooter({text: "Natsuki", iconURL: client.user.displayAvatarURL()})
.setTimestamp();
if (type === 'full') {
rte.addField("Loved by", `**${cch.loved}** Natsuki user${cch.loved === 1 ? '' : 's'}!\n\`char love ${cch.name}\``);
diff --git a/util/ask.js b/util/ask.js
index 52266bc..9487c6d 100644
--- a/util/ask.js
+++ b/util/ask.js
@@ -1,10 +1,15 @@
-module.exports = async (message, toAsk, time, nofilter, timeoutResponse) => {
+module.exports = async (message, toAsk, time, nofilter, timeoutResponse, deleteAfter) => {
let msg = await message.channel.send(toAsk);
let filter = nofilter ? () => true : m => m.author.id === message.author.id;
try {
- let collected = await msg.channel.awaitMessages({filter: filter, max: 1, errors: ['time'], time: time});
- if (collected.first().attachments.size > 0) {collected = collected.first().attachments.first().url;}
- else {collected = collected.first().content;}
+ let collectedO = await msg.channel.awaitMessages({filter: filter, max: 1, errors: ['time'], time: time});
+ let collected;
+ if (collectedO.first().attachments.size > 0) {collected = collectedO.first().attachments.first().url;}
+ else {collected = collectedO.first().content;}
+ if (deleteAfter) {
+ msg.delete().catch(() => {});
+ collectedO.first().delete().catch(() => {});
+ }
return collected;
} catch {
if (timeoutResponse) {message.reply("This question has timed out! Please try again.");}
diff --git a/util/cache.js b/util/cache.js
index 979ae29..c44de91 100644
--- a/util/cache.js
+++ b/util/cache.js
@@ -1,46 +1,52 @@
-const ora = require('ora');
+const gs = require('gradient-string');
+const spinnies = require('dreidels');
const chalk = require('chalk');
module.exports = async (client) => {
- console.log('');
- let ora_arCache = ora("Caching ARs...").start();
- await require('./cache/ar')(client);
- ora_arCache.stop(); ora_arCache.clear();
- console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.ar.size}`)} ${chalk.blueBright(`guilds with auto responses.`)}`);
-
- let ora_blCache = ora("Caching Blacklists...").start();
- await require('./cache/bl')(client);
- ora_blCache.stop(); ora_blCache.clear();
- console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.bl.guild.length}`)} ${chalk.blueBright(`guild blacklists`)}`);
- console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.bl.user.length}`)} ${chalk.blueBright(`user blacklists`)}`);
-
- let ora_lxpCache = ora("Caching Local XPs...").start();
- await require('./cache/lxp')(client);
- ora_lxpCache.stop(); ora_lxpCache.clear();
- console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.lxp.enabled.length}`)} ${chalk.blueBright(`guilds with XP enabled.`)}`);
-
- let ora_lrCache = ora("Caching Level Roles...").start();
- await require('./cache/lr')(client);
- ora_lrCache.stop(); ora_lrCache.clear();
- console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.lxp.hasLevelRoles.length}`)} ${chalk.blueBright(`guilds with Level Roles enabled.`)}`);
-
- let ora_moCache = ora("Caching Monitors...").start();
- await require('./cache/monit')(client);
- ora_moCache.stop(); ora_moCache.clear();
- console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${Object.keys(client.misc.cache.monit).length}`)} ${chalk.blueBright(`guilds with Monitors enabled.`)}`);
-
- let ora_anCache = ora("Caching Animes...").start();
- await require('./cache/anime')(client);
- ora_anCache.stop(); ora_anCache.clear();
- console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.animeNum}`)} ${chalk.blueBright(`animes into lookup registry.`)}`);
-
- let ora_chCache = ora("Caching Characters...").start();
- await require('./cache/char')(client);
- ora_chCache.stop(); ora_chCache.clear();
- console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.charsNum}`)} ${chalk.blueBright(`characters into lookup registry.`)} ${chalk.gray(`(${client.misc.cache.chars.size} // NN)`)}`);
-
- let ora_ctCache = ora("Caching Chests...").start();
- await require('./cache/chest')(client);
- ora_ctCache.stop(); ora_ctCache.clear();
- console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.chests.length}`)} ${chalk.blueBright("guilds that spawn chests.")}`);
+ return new Promise(async resolve => {
+ const loaders = [];
+ const spin = new spinnies();
+
+ console.log('');
+
+ let arCache = spin.add("ar", {text: "Caching ARs..."});
+ loaders.push(require('./cache/ar')(client, arCache));
+
+ let blCache = spin.add("bl", {text: "Caching Guild Blacklists..."});
+ let bluCache = spin.add("blu", {text: "Caching User Blacklists..."});
+ loaders.push(require('./cache/bl')(client, blCache, bluCache));
+
+ let lxpCache = spin.add("xp", {text: "Caching Local XPs..."});
+ loaders.push(require('./cache/lxp')(client, lxpCache));
+
+ let lrCache = spin.add("lr", {text: "Caching Level Roles..."});
+ loaders.push(require('./cache/lr')(client, lrCache));
+
+ let moCache = spin.add("m", {text: "Caching Monitors..."});
+ loaders.push(require('./cache/monit')(client, moCache));
+
+ let anCache = spin.add("a", {text: "Caching Animes..."});
+ loaders.push(require('./cache/anime')(client, anCache));
+
+ let chCache = spin.add("ch", {text: "Caching Characters..."});
+ loaders.push(require('./cache/char')(client, chCache));
+
+ let ctCache = spin.add("cht", {text: "Caching Chests..."});
+ loaders.push(require('./cache/chest')(client, ctCache));
+
+ let rpCache = spin.add("rp", {text: "Caching RP..."});
+ loaders.push(require('./cache/rp')(client, rpCache));
+
+ await Promise.all(loaders);
+
+ /*console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.bl.guild.length}`)} ${chalk.blueBright(`guild blacklists`)}`);
+ console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.bl.user.length}`)} ${chalk.blueBright(`user blacklists`)}`);
+ console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.lxp.enabled.length}`)} ${chalk.blueBright(`guilds with XP enabled.`)}`);
+ console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.lxp.hasLevelRoles.length}`)} ${chalk.blueBright(`guilds with Level Roles enabled.`)}`);
+ console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${Object.keys(client.misc.cache.monit).length}`)} ${chalk.blueBright(`guilds with Monitors enabled.`)}`);
+ console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.animeNum}`)} ${chalk.blueBright(`animes into lookup registry.`)}`);
+ console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.charsNum}`)} ${chalk.blueBright(`characters into lookup registry.`)} ${chalk.gray(`(${client.misc.cache.chars.size} // NN)`)}`);
+ console.log(`${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${client.misc.cache.chests.enabled.length}`)} ${chalk.blueBright("guilds that spawn chests.")}`);*/
+ resolve(0);
+ });
};
\ No newline at end of file
diff --git a/util/cache/anime.js b/util/cache/anime.js
index 2e88d48..dcb8e4b 100644
--- a/util/cache/anime.js
+++ b/util/cache/anime.js
@@ -1,21 +1,35 @@
const Discord = require('discord.js');
+const chalk = require('chalk');
const AniData = require('../../models/anime');
-module.exports = async client => {
- client.misc.cache.anime = new Discord.Collection();
- client.misc.cache.animeID = new Discord.Collection();
- client.misc.cache.animeLove = new Discord.Collection();
- client.misc.cache.animeNum = 0;
+module.exports = async (client, spinner) => {
+ return new Promise(async resolve => {
+ const st = new Date().getTime();
- for await (const ani of AniData.find()) {
- if (ani.queued !== true) {
- client.misc.cache.anime.set(ani.japname, ani.id);
- client.misc.cache.anime.set(ani.name, ani.id);
- if (ani.altNames) {ani.altNames.forEach(altName => client.misc.cache.anime.set(altName, ani.id));}
- client.misc.cache.animeID.set(ani.id, ani.name);
- client.misc.cache.animeLove.set(ani.id, ani.watchers);
- client.misc.cache.animeNum++;
+ client.misc.cache.anime = new Discord.Collection();
+ client.misc.cache.animeID = new Discord.Collection();
+ client.misc.cache.animeLove = new Discord.Collection();
+ client.misc.cache.animeNum = 0;
+ let amount = 0;
+
+ for await (const ani of AniData.find()) {
+ if (ani.queued !== true) {
+ client.misc.cache.anime.set(ani.japname.normalize("NFD").replace(/[\u0300-\u036f]/g, ""), ani.id);
+ client.misc.cache.anime.set(ani.name.normalize("NFD").replace(/[\u0300-\u036f]/g, ""), ani.id);
+ if (ani.altNames) {ani.altNames.forEach(altName => client.misc.cache.anime.set(altName, ani.id));}
+ client.misc.cache.animeID.set(ani.id, ani.name.normalize("NFD").replace(/[\u0300-\u036f]/g, ""));
+ client.misc.cache.animeLove.set(ani.id, ani.watchers);
+ client.misc.cache.animeNum++;
+ spinner.update({text: `${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${amount}`)} ${chalk.blueBright(`animes into lookup registry.`)}`});
+ amount++;
+ }
}
- }
+
+ const cacheTime = new Date().getTime() - st;
+ spinner.update({text: `${spinner.options.text.slice(0, 19).trim()} ${chalk.gray(`${cacheTime}ms >>`.padStart(8, '0').padStart(7, '0'))} ${spinner.options.text.slice(19).trim()}`});
+ spinner.status('non-spinnable');
+
+ resolve(0);
+ });
}
\ No newline at end of file
diff --git a/util/cache/ar.js b/util/cache/ar.js
index f096a75..146338e 100644
--- a/util/cache/ar.js
+++ b/util/cache/ar.js
@@ -1,11 +1,24 @@
const AR = require('../../models/ar');
+const chalk = require('chalk');
-module.exports = async client => {
- client.misc.cache.ar = new Map();
- client.misc.cache.arIgnore = new Map();
+module.exports = async (client, spinner) => {
+ return new Promise(async resolve => {
+ const st = new Date().getTime();
- for await (const ar of AR.find()) {
- client.misc.cache.ar.set(ar.gid, ar.triggers);
- if (ar.ignoreChs.length) {client.misc.cache.arIgnore.set(ar.gid, ar.ignoreChs);}
- }
+ client.misc.cache.ar = new Map();
+ client.misc.cache.arIgnore = new Map();
+ let amount = 0;
+
+ for await (const ar of AR.find()) {
+ client.misc.cache.ar.set(ar.gid, ar.triggers);
+ if (ar.ignoreChs.length) {client.misc.cache.arIgnore.set(ar.gid, ar.ignoreChs);}
+ spinner.update({text: `${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${amount}`)} ${chalk.blueBright(`guilds with auto responses.`)}`});
+ amount++;
+ }
+
+ const cacheTime = new Date().getTime() - st;
+ spinner.update({text: `${spinner.options.text.slice(0, 19).trim()} ${chalk.gray(`${cacheTime}ms >>`.padStart(8, '0').padStart(7, '0'))} ${spinner.options.text.slice(19).trim()}`});
+ spinner.status('non-spinnable');
+ resolve(0);
+ });
};
\ No newline at end of file
diff --git a/util/cache/bl.js b/util/cache/bl.js
index a74d16f..3530522 100644
--- a/util/cache/bl.js
+++ b/util/cache/bl.js
@@ -1,17 +1,40 @@
const GuildData = require('../../models/guild');
const UserData = require('../../models/user');
+const chalk = require('chalk');
-module.exports = async (client) => {
- client.misc.cache.bl = {
- guild: [],
- user: []
- };
+module.exports = async (client, spinner, spinner2) => {
+ return new Promise(async resolve => {
+ const st = new Date().getTime();
- for await (const guild of GuildData.find()) {
- if (guild.blacklisted) {client.misc.cache.bl.guild.push(guild.gid);}
- }
+ client.misc.cache.bl = {
+ guild: [],
+ user: []
+ };
+ let amount = 0;
+ let amount2 = 0;
- for await (const user of UserData.find()) {
- if (user.blackisted) {client.misc.cache.bl.user.push(user.uid);}
- }
+ for await (const guild of GuildData.find()) {
+ if (guild.blacklisted) {client.misc.cache.bl.guild.push(guild.gid); amount++;}
+ spinner.update({text: `${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${amount}`)} ${chalk.blueBright(`guild blacklists.`)}`});
+ }
+
+ spinner.update({text: `${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${amount}`)} ${chalk.blueBright(`guild blacklists.`)}`});
+ const cacheTime = new Date().getTime() - st;
+ spinner.update({text: `${spinner.options.text.slice(0, 19).trim()} ${chalk.gray(`${cacheTime}ms >>`.padStart(8, '0').padStart(7, '0'))} ${spinner.options.text.slice(19).trim()}`});
+ spinner.status('non-spinnable');
+
+ const st2 = new Date().getTime();
+
+ for await (const user of UserData.find()) {
+ if (user.blackisted) {client.misc.cache.bl.user.push(user.uid); amount2++;}
+ spinner2.update({text: `${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${amount2}`)} ${chalk.blueBright(`user blacklists.`)}`});
+ }
+
+ spinner2.update({text: `${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${amount2}`)} ${chalk.blueBright(`user blacklists.`)}`});
+ const cacheTime2 = new Date().getTime() - st2;
+ spinner2.update({text: `${spinner2.options.text.slice(0, 19).trim()} ${chalk.gray(`${cacheTime2}ms >>`.padStart(8, '0').padStart(7, '0'))} ${spinner2.options.text.slice(19).trim()}`});
+ spinner2.status('non-spinnable');
+
+ resolve(0);
+ });
};
\ No newline at end of file
diff --git a/util/cache/char.js b/util/cache/char.js
index cb4aa88..398a859 100644
--- a/util/cache/char.js
+++ b/util/cache/char.js
@@ -1,20 +1,39 @@
const Discord = require('discord.js');
+const chalk = require('chalk');
const CharData = require('../../models/char');
-module.exports = async client => {
- client.misc.cache.chars = new Discord.Collection();
- client.misc.cache.charsID = new Discord.Collection();
- client.misc.cache.charsLove = new Discord.Collection();
- client.misc.cache.charsNum = 0;
+module.exports = async (client, spinner) => {
+ return new Promise(async resolve => {
+ const st = new Date().getTime();
- for await (const char of CharData.find()) {
- if (char.queued !== true) {
- client.misc.cache.chars.set(char.name, char.id);
- char.nicknames.forEach(nn => client.misc.cache.chars.set(nn, char.id));
- client.misc.cache.charsID.set(char.id, char.name);
- client.misc.cache.charsNum++;
- client.misc.cache.charsLove.set(char.id, char.loved);
+ client.misc.cache.chars = new Discord.Collection();
+ client.misc.cache.charsID = new Discord.Collection();
+ client.misc.cache.charsLove = new Discord.Collection();
+ client.misc.cache.charsNum = 0;
+ let amount = 0;
+
+ for await (const char of CharData.find()) {
+ if (char.queued !== true) {
+ client.misc.cache.chars.set(char.name.normalize("NFD").replace(/[\u0300-\u036f]/g, ""), char.id);
+ char.nicknames.forEach(nn => client.misc.cache.chars.set(nn.normalize("NFD").replace(/[\u0300-\u036f]/g, ""), char.id));
+ client.misc.cache.charsID.set(char.id, char.name.normalize("NFD").replace(/[\u0300-\u036f]/g, ""));
+ client.misc.cache.charsNum++;
+ client.misc.cache.charsLove.set(char.id, char.loved);
+ /*let hasNull = false;
+ char.images.forEach((image, index) => {
+ if (image === null) {char.images.splice(index, 1); hasNull = true;}
+ });
+ if (hasNull) {char.markModified('images'); await char.save();}*/
+ spinner.update({text: `${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${amount}`)} ${chalk.blueBright(`characters into lookup registry.`)} ${chalk.gray(`(${client.misc.cache.chars.size} // NN)`)}`});
+ amount++;
+ }
}
- }
+
+ const cacheTime = new Date().getTime() - st;
+ spinner.update({text: `${spinner.options.text.slice(0, 19).trim()} ${chalk.gray(`${cacheTime}ms >>`.padStart(8, '0').padStart(7, '0'))} ${spinner.options.text.slice(19).trim()}`});
+ spinner.status('non-spinnable');
+
+ resolve(0);
+ });
}
\ No newline at end of file
diff --git a/util/cache/chest.js b/util/cache/chest.js
index 8e9ec65..e8037ff 100644
--- a/util/cache/chest.js
+++ b/util/cache/chest.js
@@ -1,9 +1,22 @@
const Chests = require('../../models/chests');
+const chalk = require('chalk');
-module.exports = async client => {
- client.misc.cache.chests = [];
+module.exports = async (client, spinner) => {
+ return new Promise(async resolve => {
+ const st = new Date().getTime();
- for await (const chest of Chests.find()) {
- client.misc.cache.chests.push(chest.gid);
- }
+ client.misc.cache.chests.enabled = [];
+ let amount = 0;
+
+ for await (const chest of Chests.find()) {
+ client.misc.cache.chests.enabled.push(chest.gid);
+ spinner.update({text: `${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${amount}`)} ${chalk.blueBright(`guilds that spawn chests.`)}`});
+ amount++;
+ }
+
+ const cacheTime = new Date().getTime() - st;
+ spinner.update({text: `${spinner.options.text.slice(0, 19).trim()} ${chalk.gray(`${cacheTime}ms >>`.padStart(8, '0').padStart(7, '0'))} ${spinner.options.text.slice(19).trim()}`});
+ spinner.status('non-spinnable');
+ resolve(0);
+ });
};
\ No newline at end of file
diff --git a/util/cache/lr.js b/util/cache/lr.js
index 1b0bb7b..b815cd7 100644
--- a/util/cache/lr.js
+++ b/util/cache/lr.js
@@ -1,9 +1,23 @@
const LR = require('../../models/levelroles');
+const chalk = require('chalk');
-module.exports = async client => {
- client.misc.cache.lxp.hasLevelRoles = [];
+module.exports = async (client, spinner) => {
+ return new Promise(async resolve => {
+ const st = new Date().getTime();
- for await (const lr of LR.find()) {
- client.misc.cache.lxp.hasLevelRoles.push(lr.gid);
- }
+ client.misc.cache.lxp.hasLevelRoles = [];
+ let amount = 0;
+
+ for await (const lr of LR.find()) {
+ client.misc.cache.lxp.hasLevelRoles.push(lr.gid);
+ spinner.update({text: `${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${amount}`)} ${chalk.blueBright(`guilds with Level Roles enabled.`)}`});
+ amount++;
+ }
+
+ const cacheTime = new Date().getTime() - st;
+ spinner.update({text: `${spinner.options.text.slice(0, 19).trim()} ${chalk.gray(`${cacheTime}ms >>`.padStart(8, '0').padStart(7, '0'))} ${spinner.options.text.slice(19).trim()}`});
+ spinner.status('non-spinnable');
+
+ resolve(0);
+ });
};
\ No newline at end of file
diff --git a/util/cache/lxp.js b/util/cache/lxp.js
index 754d7c2..6a0dcec 100644
--- a/util/cache/lxp.js
+++ b/util/cache/lxp.js
@@ -1,12 +1,25 @@
const LXP = require('../../models/localxp');
+const chalk = require('chalk');
-module.exports = async client => {
- client.misc.cache.lxp.enabled = [];
- client.misc.cache.lxp.disabledChannels = new Map();
- client.misc.cache.chests = new Map();
+module.exports = async (client, spinner) => {
+ return new Promise(async resolve => {
+ const st = new Date().getTime();
- for await (const xp of LXP.find()) {
- client.misc.cache.lxp.enabled.push(xp.gid);
- if (xp.noGains && xp.noGains.length) {client.misc.cache.lxp.disabledChannels.set(xp.gid, xp.noGains);}
- }
+ client.misc.cache.lxp.enabled = [];
+ client.misc.cache.lxp.disabledChannels = new Map();
+ client.misc.cache.chests.enabled = new Map();
+ let amount = 0;
+
+ for await (const xp of LXP.find()) {
+ client.misc.cache.lxp.enabled.push(xp.gid);
+ if (xp.noGains && xp.noGains.length) {client.misc.cache.lxp.disabledChannels.set(xp.gid, xp.noGains);}
+ spinner.update({text: `${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${amount}`)} ${chalk.blueBright(`guilds with XP enabled.`)}`});
+ amount++;
+ }
+
+ const cacheTime = new Date().getTime() - st;
+ spinner.update({text: `${spinner.options.text.slice(0, 19).trim()} ${chalk.gray(`${cacheTime}ms >>`.padStart(8, '0').padStart(7, '0'))} ${spinner.options.text.slice(19).trim()}`});
+ spinner.status('non-spinnable');
+ resolve(0);
+ });
};
\ No newline at end of file
diff --git a/util/cache/monit.js b/util/cache/monit.js
index 3c845e3..bf4fc23 100644
--- a/util/cache/monit.js
+++ b/util/cache/monit.js
@@ -1,15 +1,29 @@
const Monitor = require('../../models/monitor');
+const chalk = require('chalk');
-module.exports = async client => {
- client.misc.cache.monit = {};
- client.misc.cache.monitEnabled = [];
-
- for await (const tm of Monitor.find()) {
- client.misc.cache.monit[tm.gid] = {
- messages: tm.messages,
- voice: tm.voice,
- expiry: new Date()
- };
- client.misc.cache.monitEnabled.push(tm.gid);
- }
+module.exports = async (client, spinner) => {
+ return new Promise(async resolve => {
+ const st = new Date().getTime();
+
+ client.misc.cache.monit = {};
+ client.misc.cache.monitEnabled = [];
+ let amount = 0;
+
+ for await (const tm of Monitor.find()) {
+ client.misc.cache.monit[tm.gid] = {
+ messages: tm.messages,
+ voice: tm.voice,
+ expiry: new Date()
+ };
+ client.misc.cache.monitEnabled.push(tm.gid);
+ spinner.update({text: `${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${amount}`)} ${chalk.blueBright(`guilds with Monitors enabled.`)}`});
+ amount++;
+ }
+
+ const cacheTime = new Date().getTime() - st;
+ spinner.update({text: `${spinner.options.text.slice(0, 19).trim()} ${chalk.gray(`${cacheTime}ms >>`.padStart(8, '0').padStart(7, '0'))} ${spinner.options.text.slice(19).trim()}`});
+ spinner.status('non-spinnable');
+
+ resolve(0);
+ });
}
\ No newline at end of file
diff --git a/util/cache/rp.js b/util/cache/rp.js
new file mode 100644
index 0000000..924d59e
--- /dev/null
+++ b/util/cache/rp.js
@@ -0,0 +1,25 @@
+const Discord = require('discord.js');
+const chalk = require('chalk');
+
+const RPC = require('../../models/rpconfig');
+
+module.exports = async (client, spinner) => {
+ return new Promise(async resolve => {
+ const st = new Date().getTime();
+
+ client.misc.cache.rp = new Map();
+ let amount = 0;
+
+ for await (const rp of RPC.find()) {
+ client.misc.cache.rp.set(rp.gid, rp.channels);
+ spinner.update({text: `${chalk.gray('[PROC]')} >> ${chalk.blueBright(`Cached`)} ${chalk.white(`${amount}`)} ${chalk.blueBright(`guilds with RP enabled.`)}`});
+ amount++;
+ }
+
+ const cacheTime = new Date().getTime() - st;
+ spinner.update({text: `${spinner.options.text.slice(0, 19).trim()} ${chalk.gray(`${cacheTime}ms >>`.padStart(8, '0').padStart(7, '0'))} ${spinner.options.text.slice(19).trim()}`});
+ spinner.status('non-spinnable');
+
+ resolve(0);
+ });
+}
\ No newline at end of file
diff --git a/util/livepagination.d.ts b/util/livepagination.d.ts
new file mode 100644
index 0000000..a1fbb1a
--- /dev/null
+++ b/util/livepagination.d.ts
@@ -0,0 +1,18 @@
+import { TextChannel, Message, MessageEmbed, Client } from 'discord.js';
+import { Pagination } from './pagination';
+export declare class LivePagination extends Pagination {
+ knownMax: number;
+ private _onScrollAttempt;
+ constructor(channel: TextChannel, pages: MessageEmbed[], originalMessage: Message, client: Client, loopPages?: boolean, message?: Message);
+ setOnScrollAttemptHandler(func: (pagination: LivePagination, pos: number, exists: boolean, inBounds: boolean) => void): this;
+ start(options?: {
+ endTime?: number;
+ time?: number;
+ startPage?: number;
+ user?: 'any' | string;
+ }): Promise;
+ setControllers(endTime: number, user: 'any' | string): Promise;
+ setPage(page: number): Promise;
+ private static throwNoScrollAttempt;
+ set onScrollAttempt(func: (pagination: LivePagination, pos: number, exists: boolean, inBounds: boolean) => void);
+}
diff --git a/util/livepagination.js b/util/livepagination.js
new file mode 100644
index 0000000..1abd41b
--- /dev/null
+++ b/util/livepagination.js
@@ -0,0 +1,47 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.LivePagination = void 0;
+const pagination_1 = require("./pagination");
+class LivePagination extends pagination_1.Pagination {
+ constructor(channel, pages, originalMessage, client, loopPages, message) {
+ super(channel, pages, originalMessage, client, loopPages, message);
+ }
+ ;
+ setOnScrollAttemptHandler(func) {
+ this._onScrollAttempt = func;
+ return this;
+ }
+ ;
+ async start(options) {
+ if (!this._onScrollAttempt) {
+ LivePagination.throwNoScrollAttempt();
+ }
+ await super.start(options);
+ return this;
+ }
+ async setControllers(endTime, user) {
+ if (!this._onScrollAttempt) {
+ LivePagination.throwNoScrollAttempt();
+ }
+ await super.setControllers(endTime, user);
+ return this;
+ }
+ ;
+ async setPage(page) {
+ if (!this._onScrollAttempt) {
+ LivePagination.throwNoScrollAttempt();
+ }
+ this._onScrollAttempt(this, page, typeof this.pages[page] !== 'undefined' && this.pages[page] !== null, typeof this.knownMax === 'number' ? page < this.knownMax : true);
+ await super.setPage(page);
+ return this;
+ }
+ ;
+ static throwNoScrollAttempt() {
+ throw new Error("Fatal Pagination Error: You tried to start the LivePagination without setting a scrollAttemptEvent. This is necessary to allow the pagination to be built as the user scrolls. If you don't know what you're doing here, just make a Pagination instead.");
+ }
+ set onScrollAttempt(func) {
+ this._onScrollAttempt = func;
+ }
+ ;
+}
+exports.LivePagination = LivePagination;
diff --git a/util/lxp/cacheloop.js b/util/lxp/cacheloop.js
index bde7a52..b697a50 100644
--- a/util/lxp/cacheloop.js
+++ b/util/lxp/cacheloop.js
@@ -7,21 +7,28 @@ module.exports = async (client) => {
LXP.findOne({gid: gxp}).then(xp => {
if (!xp) {return;}
Object.keys(client.misc.cache.lxp.xp[gxp]).forEach(user => {
- Monners.findOne({uid: user}).then(m => {
- if (!Object.keys(client.misc.cache.monners).includes(user)) {return;}
- if (!m) {m = new Monners({uid: user});}
- m.currency = client.misc.cache.monners[user];
- m.save();
- });
xp.xp[user] = [client.misc.cache.lxp.xp[gxp][user].xp, client.misc.cache.lxp.xp[gxp][user].level];
xp.markModified(`xp.${user}`);
if (cd - client.misc.cache.lxp.xp[gxp][user].lastXP > 600000) {
delete client.misc.cache.lxp.xp[gxp][user];
- delete client.misc.cache.monners[user];
if (!Object.keys(client.misc.cache.lxp.xp[gxp]).length) {delete client.misc.cache.lxp.xp[gxp];}
}
});
- xp.save();
+ xp.save().catch(() => {});
});
+
+ Object.keys(client.misc.cache.monners).forEach(user => {
+ Monners.findOne({uid: user}).then(m => {
+ if (!Object.keys(client.misc.cache.monners).includes(user)) {return;}
+ if (isNaN(client.misc.cache.monners[user])) {return;}
+ if (!m) {m = new Monners({uid: user});}
+ m.currency = client.misc.cache.monners[user];
+ m.save().catch(() => {});
+ if (cd - client.misc.cache.lastMonners[user] > 600000) {
+ delete client.misc.cache.monners[user];
+ delete client.misc.cache.lastMonners[user];
+ }
+ });
+ })
});
};
\ No newline at end of file
diff --git a/util/lxp/gainxp.js b/util/lxp/gainxp.js
index c43ccd3..d1aa4df 100644
--- a/util/lxp/gainxp.js
+++ b/util/lxp/gainxp.js
@@ -18,7 +18,6 @@ const applyText = (canvas, text) => {
module.exports = async (client, member, channel) => {
client.misc.cache.lxp.xp[channel.guild.id][member].lastXP = new Date().getTime();
client.misc.cache.lxp.xp[channel.guild.id][member].xp += 10;
- client.misc.cache.monners[member] += (Math.floor(client.misc.cache.lxp.xp[channel.guild.id][member].level / 35) + 1);
let x = client.misc.cache.lxp.xp[channel.guild.id][member].level;
let max = Math.ceil(100 + (((x / 3) ** 2) * 2));
@@ -38,7 +37,7 @@ module.exports = async (client, member, channel) => {
client.misc.cache.monners[member] += cur;
if (ch && ch.permissionsFor(ch.guild.me.id).has('SEND_MESSAGES')) {
- if (!ch.permissionsFor(ch.guild.me.id).has('ATTACH_FILES')) {ch.send(`<:awoo:560193779764559896> <@${member}> has reached **Level ${x + 1}**, and gained **${cur}** bonus Monners<:monners:926736756047495218>! `).catch((e) => {/*console.error(e)*/});}
+ if (!ch.permissionsFor(ch.guild.me.id).has('ATTACH_FILES')) {ch.send(`<:awoo:560193779764559896> <@${member}> has reached **Level ${x + 1}**, and gained **${cur}** bonus ${client.misc.cache.monnersNames.get(channel.guild.id) || 'Monners'}<:monners:926736756047495218>! `).catch((e) => {/*console.error(e)*/});}
else {
const canvas = Canvas.createCanvas(1193, 411);
const context = canvas.getContext('2d');
@@ -55,7 +54,7 @@ module.exports = async (client, member, channel) => {
const monnersImage = await Canvas.loadImage('https://cdn.discordapp.com/emojis/926736756047495218');
context.drawImage(monnersImage, canvas.width / 2.8, canvas.height / 1.5, 58, 60);
- context.fillText(`${oldMonners} + ${cur} Bonus Monners`, (canvas.width / 2.8) + 70, (canvas.height / 1.55) + 57);
+ context.fillText(`${oldMonners} + ${cur} Bonus ${client.misc.cache.monnersNames.get(channel.guild.id) || 'Monners'}`, (canvas.width / 2.8) + 70, (canvas.height / 1.55) + 57);
context.font = applyText(canvas, `${ch.guild.members.cache.get(member).displayName}`); //center text
context.fillText(`${ch.guild.members.cache.get(member).displayName}`, canvas.width / 2.8, canvas.height / 2.7);
@@ -64,7 +63,7 @@ module.exports = async (client, member, channel) => {
context.drawImage(avatar, 40, 40, canvas.height - 80, canvas.height - 80);
ch.send({
- content: `<:awoo:560193779764559896> <@${member}> has reached **Level ${x + 1}**, and gained **${cur}** bonus Monners<:monners:926736756047495218>! `,
+ content: `<:awoo:560193779764559896> <@${member}> has reached **Level ${x + 1}**, and gained **${cur}** bonus ${client.misc.cache.monnersNames.get(channel.guild.id) || 'Monners'}<:monners:926736756047495218>! `,
files: [new Discord.MessageAttachment(canvas.toBuffer(), 'level-up.png')]
});
}
diff --git a/util/lxp/spawnchest.js b/util/lxp/spawnchest.js
index 58680f4..946d87e 100644
--- a/util/lxp/spawnchest.js
+++ b/util/lxp/spawnchest.js
@@ -4,9 +4,9 @@ const manyitems = require('manyitems');
const Discord = require('discord.js');
module.exports = async (client, member, channel, prefix) => {
- if (client.misc.cache.chestsTimeout.has(member.guild.id) && new Date().getTime() - client.misc.cache.chestsTimeout.get(member.guild.id) < (1000 * 60 * 2)) {return;}
- //let rand = Math.floor(Math.random() * 100);
- //if (rand !== 69) {return;} //decide if it even continues
+ if (client.misc.cache.chests.timeout.has(member.guild.id) && new Date().getTime() - client.misc.cache.chests.timeout.get(member.guild.id) < (1000 * 60 * 2)) {return;}
+ let rand = Math.floor(Math.random() * 100);
+ if (rand !== 69) {return;} //decide if it even continues
let tm = await Monners.findOne({uid: member.id});
let streak = tm && tm.daily ? tm.daily.streak : 0; //get streak for bonus later
@@ -57,23 +57,30 @@ module.exports = async (client, member, channel, prefix) => {
});
let streakBonus = streak !== 0 ? Math.floor((Math.floor(Math.random() * (rarity.amount * .10)) * 1.5 * streak)) : 0;
let amount = ri.calc_bubble() + streakBonus; //calculate the amount by allowing a 10% +/- variance, higher potential with higher streak, and adding another random bonus with streak
+ if (isNaN(amount)) {return;}
let chests = await Chests.findOne({gid: member.guild.id});
if (!chests) {return;}
let spawnChannel = chests.channel && chests.channel.length ? chests.channel : channel;
- client.misc.cache.chestsTimeout.set(member.guild.id, new Date().getTime());
+ client.misc.cache.chests.timeout.set(member.guild.id, new Date().getTime());
let chestEmbed = new Discord.MessageEmbed()
.setTitle(`${client.utils.an(rarity.name, true)} Chest has spawned!`)
- .setDescription(`It has **${amount} Monners<:monners:926736756047495218>**`)
- .setFooter({text: `Type \`${prefix}claim\` to claim it!`})
+ .setDescription(`It has **${amount} ${client.misc.cache.monnersNames.get(member.guild.id) || 'Monners'}<:monners:926736756047495218>**`)
+ .setFooter({text: `Type ${prefix}claim to claim it!`})
.setColor(rarity.color) //create the chest message
- if (spawnChannel === channel) {return channel.send({embeds: [chestEmbed]}).catch(() => {});}
+ if (spawnChannel === channel) {
+ return channel.send({embeds: [chestEmbed]})
+ .then(m => {client.misc.cache.chests.waiting.set(m.channel.id, {amount: amount, rarity: rarity, message: m});}) //place the chest in waiting to make it claimable
+ .catch(() => {});
+ }
else {
member.guild.channels.fetch(spawnChannel)
- .then(ch => ch.send({embeds: [chestEmbed]}).catch(() => {}))
+ .then(ch => ch.send({embeds: [chestEmbed]})
+ .then(m => {client.misc.cache.chests.waiting.set(m.channel.id, {amount: amount, rarity: rarity, message: m});})
+ .catch(() => {}))
.catch(() => {})
}
return spawnChannel.send({embeds: [chestEmbed]}); //spawn the chest
diff --git a/util/mention.js b/util/mention.js
index d0e098e..434ff48 100644
--- a/util/mention.js
+++ b/util/mention.js
@@ -14,7 +14,7 @@ module.exports = async(message, msg, args, cmd, prefix, mention, client) => {
client.misc.statusPings.get(message.guild.id).set(mention.id, new Date());
let m = await message.channel.send({embeds: [
new Discord.MessageEmbed()
- .setAuthor({name: mention.tag, iconURL: mention.avatarURL()})
+ .setAuthor({name: mention.tag, iconURL: mention.displayAvatarURL()})
.setDescription(`That user ${tu.statustype === 'dnd' ? 'wishes not to be disturbed' : 'is AFK'}. Reason: ${tu.statusmsg}.${tu.statussetat ? `\n\n(This status was set ${moment(tu.statussetat.getTime()).fromNow()})` : ''}`)
.setColor('c375f0')
]
diff --git a/util/oncommand.js b/util/oncommand.js
index efad3a6..b5218bb 100644
--- a/util/oncommand.js
+++ b/util/oncommand.js
@@ -1,25 +1,24 @@
const Discord = require('discord.js');
-const mongoose = require('mongoose');
-const chalk = require('chalk');
const UserData = require('../models/user');
module.exports = async (message, msg, args, cmd, prefix, mention, client) => {
- /*const config = client.config;
- try {
- await mongoose.connect(`mongodb+srv://${config.database.user}:${config.database.password}@${config.database.cluster}.uqyvv.mongodb.net`, {
- useFindAndModify: false, useNewUrlParser: true, dbName: 'valk', useUnifiedTopology: true
- });
- } catch (e) {
- let date = new Date; date = date.toString().slice(date.toString().search(":") - 2, date.toString().search(":") + 6);
- console.error(`\n${chalk.red('[ERROR]')} >> ${chalk.yellow(`At [${date}] | Occurred while trying to connect to Mongo Cluster`)}`, e);
- }*/
-
let botData = await require('../models/bot').findOne({finder: 'lel'});
botData.commands = botData.commands + 1;
botData.save();
- let tu = await UserData.findOne({uid: message.author.id})
- ? await UserData.findOne({uid: message.author.id})
- : new UserData({uid: message.author.id});
- tu.commands = tu.commands + 1;
- tu.save();
+ let tu = await UserData.findOne({uid: message.author.id}) || new UserData({uid: message.author.id});
+ tu.commands++;
+
+ if (tu.commands > 50 && !tu.msg) {
+ await message.author.send({embeds: [new Discord.MessageEmbed()
+ .setThumbnail(client.user.displayAvatarURL({size: 2048}))
+ .setDescription(`Hey there **${message.author.username}**! Looks like you've used my commands over **50 times**${tu.commands > 51 ? ` (${tu.commands} to be exact)` : ''}!\nI hope you're enjoying the wonderful things I have to offer, because I've enjoyed offering them to you.`)
+ .addField("What next?", "If you're enjoying what I do, you can [join my support server](https://discord.gg/u9c2uD24wB) to leave feedback and say hi to my developers. You can also consider [giving the repository a star](https://github.com/NatsukiDev/Natsuki) to show your support! I look forward to my time with you in the future <:hearty:812130944319750144>")
+ .setFooter({text: "Natsuki"})
+ .setTimestamp()
+ .setColor('c375f0')
+ ]}).catch(() => {});
+ tu.msg = true;
+ }
+
+ await tu.save();
};
\ No newline at end of file
diff --git a/util/pagination.js b/util/pagination.js
index 83322c9..11ae061 100644
--- a/util/pagination.js
+++ b/util/pagination.js
@@ -32,7 +32,7 @@ class Pagination {
}
}
await this.message.edit({ embeds: [this.pages[page]
- .setFooter({ text: `Natsuki | Page ${page + 1} of ${this.pages.length}`, iconURL: this.client.user.avatarURL() })
+ .setFooter({ text: `Natsuki | Page ${page + 1} of ${this.pages.length}`, iconURL: this.client.user.displayAvatarURL() })
.setTimestamp()]
});
this.currentPage = page;
@@ -117,8 +117,8 @@ class Pagination {
}
this.controllers.collector.stop();
let fe = this.getCurrentPage();
- fe.setDescription(`${fe.description}\n\n*This menu has ended, start a new one to interact with it!*`);
- fe.setFooter({ text: `Menu Ended${fe.footer && fe.footer.text && fe.footer.text.length ? ` | ${fe.footer.text}` : ''}`, iconURL: this.client.user.avatarURL() });
+ fe.setDescription(`${fe.description && fe.description.length ? `${fe.description}\n\n` : ''}*This menu has ended, start a new one to interact with it!*`);
+ fe.setFooter({ text: `Menu Ended${fe.footer && fe.footer.text && fe.footer.text.length ? ` | ${fe.footer.text}` : ''}`, iconURL: this.client.user.displayAvatarURL() });
await this.message.edit({ embeds: [fe] });
clearInterval(this.timeoutInterval);
return this;
diff --git a/util/response/filterresponse.js b/util/response/filterresponse.js
index cce7824..815b0a8 100644
--- a/util/response/filterresponse.js
+++ b/util/response/filterresponse.js
@@ -1,8 +1,9 @@
module.exports = async (member, client, text) => {
+ const go = await member.guild.fetchOwner();
text = text
.replace(/(?:{{member}}|{{m}})/gm, member.displayName)
.replace(/(?:{{membercount}}|{{mc}})/gm, `${member.guild.members.cache.size}`)
- .replace(/(?:{{owner}}|{{o}})/gm, member.guild.fetchOwner().then(owner => owner.displayName))
+ .replace(/(?:{{owner}}|{{o}})/gm, go.displayName)
.replace(/(?:{{ping}}|{{mp}}|{{memberping}}|{{p}})/gm, `<@${member.id}>`)
.replace(/(?:{{s}}|{{server}}|{{servername}}|{{sn}})/gm, member.guild.name)
.replace(/{{n}}/gm, '\n')
diff --git a/util/slash.d.ts b/util/slash.d.ts
index b418892..a63eba8 100644
--- a/util/slash.d.ts
+++ b/util/slash.d.ts
@@ -1,8 +1,8 @@
import { REST } from '@discordjs/rest';
import { SlashCommandBuilder } from '@discordjs/builders';
-import { Client, CommandInteraction } from 'discord.js';
+import { Client, CommandInteraction, Guild } from 'discord.js';
export declare class SlashCommand {
- response: (client: Client, interaction: CommandInteraction) => any;
+ response: (client: Client, interaction: CommandInteraction, guild: false | Guild, prefix: string) => any;
command: SlashCommandBuilder;
registerMode: RegisterMode;
enabled: boolean;
@@ -16,7 +16,7 @@ export declare class SlashCommand {
setResponse(newResponse: (client: Client, interaction: CommandInteraction) => any): SlashCommand;
disable(): Promise;
setDefaultRegisterMode(mode: RegisterMode): SlashCommand;
- respond(client: Client, interaction: CommandInteraction): Promise;
+ respond(client: Client, interaction: CommandInteraction, guild: false | Guild, prefix: string): Promise;
setCommand(newCommand: SlashCommandBuilder): SlashCommand;
}
export declare type RegisterMode = {
diff --git a/util/slash.js b/util/slash.js
index c4e2106..30fd40a 100644
--- a/util/slash.js
+++ b/util/slash.js
@@ -53,8 +53,8 @@ class SlashCommand {
return this;
}
;
- async respond(client, interaction) {
- return this.response(client, interaction);
+ async respond(client, interaction, guild, prefix) {
+ return this.response(client, interaction, guild, prefix);
}
;
setCommand(newCommand) {
diff --git a/util/slashmanager.d.ts b/util/slashmanager.d.ts
index a273946..fc1eb3b 100644
--- a/util/slashmanager.d.ts
+++ b/util/slashmanager.d.ts
@@ -21,7 +21,7 @@ export declare class SlashManager {
setAfterHandle(execute: (client: Discord.Client, interaction: Discord.CommandInteraction, success: Boolean) => any): SlashManager;
setTestServer(id: string): SlashManager;
private handle;
- importCommands(dir?: string): SlashManager;
+ importCommands(register?: boolean | RegisterMode, dir?: string, log?: (command: SlashCommand, manager: SlashManager) => void): SlashManager;
}
declare type CommandLookup = SlashCommand[] | SlashCommand | string | string[];
export {};
diff --git a/util/slashmanager.js b/util/slashmanager.js
index d4b392a..349e06e 100644
--- a/util/slashmanager.js
+++ b/util/slashmanager.js
@@ -113,22 +113,33 @@ class SlashManager {
async handle(interaction) {
this.beforeHandle(this.client, interaction);
let success = true;
+ // @ts-ignore
+ let defaultPrefix = this.client.misc.config.dev ? 'n!' : 'n?';
try {
- await this.commands[this.getCommand(interaction.commandName)].respond(this.client, interaction).catch((e) => { console.log(e); success = false; });
+ await this.commands[this.getCommand(interaction.commandName)]
+ .respond(this.client, interaction, interaction.inGuild() ? interaction.guild : false,
+ // @ts-ignore
+ interaction.inGuild() ? this.client.guildconfig.prefixes.has(interaction.guild.id) ? this.client.guildconfig.prefixes.get(interaction.guild.id) !== null ? this.client.guildconfig.prefixes.get(interaction.guild.id) : defaultPrefix : defaultPrefix : defaultPrefix).catch((e) => { console.log(e); success = false; });
}
catch (e) {
- console.log(e);
success = false;
}
this.afterHandle(this.client, interaction, success);
}
;
- importCommands(dir) {
- dir = dir || './slash';
- const commands = fs.readdirSync(dir).filter(file => file.endsWith('.js'));
- for (const command of commands) {
- this.add(require(`../${dir}/${command}`)(this.client));
- }
+ importCommands(register = false, dir = './slash', log = () => { }) {
+ const search = (toSearch) => {
+ let cdir = fs.readdirSync(toSearch);
+ const commands = cdir.filter(file => file.endsWith('.js'));
+ for (const command of commands) {
+ const slashCommand = require(`../${toSearch}/${command}`)(this.client);
+ this.add(slashCommand, register);
+ log(slashCommand, this);
+ }
+ const subdirs = cdir.filter(file => fs.lstatSync(`${toSearch}/${file}`).isDirectory());
+ subdirs.forEach(subdir => search(`${toSearch}/${subdir}`));
+ };
+ search(dir);
return this;
}
;
diff --git a/util/ts/livepagination.ts b/util/ts/livepagination.ts
new file mode 100644
index 0000000..16c21ce
--- /dev/null
+++ b/util/ts/livepagination.ts
@@ -0,0 +1,64 @@
+import {TextChannel, Message, MessageEmbed, Client, MessageReaction, ReactionCollector, DiscordAPIError} from 'discord.js';
+import {Pagination} from './pagination';
+
+export class LivePagination extends Pagination {
+
+ knownMax: number;
+
+ private _onScrollAttempt: (pagination: LivePagination, pos: number, exists: boolean, inBounds: boolean) => void;
+
+
+ constructor (channel: TextChannel, pages: MessageEmbed[], originalMessage: Message, client: Client, loopPages?: boolean, message?: Message) {
+ super(channel, pages, originalMessage, client, loopPages, message);
+ };
+
+
+
+ public setOnScrollAttemptHandler(func: (pagination: LivePagination, pos: number, exists: boolean, inBounds: boolean) => void) {
+ this._onScrollAttempt = func;
+ return this;
+ };
+
+ public async start(options?: {endTime?: number, time?: number, startPage?: number, user?: 'any' | string}): Promise {
+ if (!this._onScrollAttempt) {LivePagination.throwNoScrollAttempt();}
+ await super.start(options);
+ return this;
+ }
+
+ public async setControllers(endTime: number, user: 'any' | string): Promise {
+ if (!this._onScrollAttempt) {LivePagination.throwNoScrollAttempt();}
+ await super.setControllers(endTime, user);
+ return this;
+ };
+
+ public async setPage(page: number): Promise {
+ if (!this._onScrollAttempt) {LivePagination.throwNoScrollAttempt();}
+ this._onScrollAttempt(this, page, typeof this.pages[page] !== 'undefined' && this.pages[page] !== null, typeof this.knownMax === 'number' ? page < this.knownMax : true);
+ await super.setPage(page);
+ return this;
+ };
+
+
+ private static throwNoScrollAttempt() {
+ throw new Error("Fatal Pagination Error: You tried to start the LivePagination without setting a scrollAttemptEvent. This is necessary to allow the pagination to be built as the user scrolls. If you don't know what you're doing here, just make a Pagination instead.");
+ }
+
+
+ set onScrollAttempt(func: (pagination: LivePagination, pos: number, exists: boolean, inBounds: boolean) => void) {
+ this._onScrollAttempt = func;
+ };
+
+}
+
+
+
+interface ExtraControls {
+
+}
+
+interface ControllerData {
+ endTime: number,
+ enabled: boolean,
+ lastInteraction: Date,
+ collector: ReactionCollector
+}
\ No newline at end of file
diff --git a/util/ts/pagination.ts b/util/ts/pagination.ts
index d22968d..85ed4fd 100644
--- a/util/ts/pagination.ts
+++ b/util/ts/pagination.ts
@@ -37,7 +37,7 @@ export class Pagination {
}
await this.message.edit({embeds: [this.pages[page]
- .setFooter({text: `Natsuki | Page ${page + 1} of ${this.pages.length}`, iconURL: this.client.user.avatarURL()})
+ .setFooter({text: `Natsuki | Page ${page + 1} of ${this.pages.length}`, iconURL: this.client.user.displayAvatarURL()})
.setTimestamp()]
});
this.currentPage = page;
@@ -125,8 +125,8 @@ export class Pagination {
this.controllers.collector.stop();
let fe = this.getCurrentPage();
- fe.setDescription(`${fe.description}\n\n*This menu has ended, start a new one to interact with it!*`);
- fe.setFooter({text: `Menu Ended${fe.footer && fe.footer.text && fe.footer.text.length ? ` | ${fe.footer.text}` : ''}`, iconURL: this.client.user.avatarURL()});
+ fe.setDescription(`${fe.description && fe.description.length ? `${fe.description}\n\n` : ''}*This menu has ended, start a new one to interact with it!*`);
+ fe.setFooter({text: `Menu Ended${fe.footer && fe.footer.text && fe.footer.text.length ? ` | ${fe.footer.text}` : ''}`, iconURL: this.client.user.displayAvatarURL()});
await this.message.edit({embeds: [fe]});
clearInterval(this.timeoutInterval);
diff --git a/util/ts/slash.ts b/util/ts/slash.ts
index 476b425..7f5df80 100644
--- a/util/ts/slash.ts
+++ b/util/ts/slash.ts
@@ -1,11 +1,11 @@
import {REST} from '@discordjs/rest';
import {Routes} from 'discord-api-types/v9';
import {SlashCommandBuilder} from '@discordjs/builders';
-import {Client, CommandInteraction} from 'discord.js';
+import {Client, CommandInteraction, Guild} from 'discord.js';
export class SlashCommand {
- response: (client: Client, interaction: CommandInteraction) => any;
+ response: (client: Client, interaction: CommandInteraction, guild: false | Guild, prefix: string) => any;
command: SlashCommandBuilder;
registerMode: RegisterMode = 'global';
enabled: boolean = false;
@@ -64,8 +64,8 @@ export class SlashCommand {
return this;
};
- public async respond(client: Client, interaction: CommandInteraction): Promise {
- return this.response(client, interaction);
+ public async respond(client: Client, interaction: CommandInteraction, guild: false | Guild, prefix: string): Promise {
+ return this.response(client, interaction, guild, prefix);
};
public setCommand(newCommand: SlashCommandBuilder): SlashCommand {
diff --git a/util/ts/slashmanager.ts b/util/ts/slashmanager.ts
index 5b9fd04..2d6f3d2 100644
--- a/util/ts/slashmanager.ts
+++ b/util/ts/slashmanager.ts
@@ -106,21 +106,35 @@ export class SlashManager {
private async handle(interaction: Discord.CommandInteraction): Promise {
this.beforeHandle(this.client, interaction);
let success = true;
+ // @ts-ignore
+ let defaultPrefix = this.client.misc.config.dev ? 'n!' : 'n?';
try {
- await this.commands[this.getCommand(interaction.commandName)].respond(this.client, interaction).catch((e) => {console.log(e); success = false;});
+ await this.commands[this.getCommand(interaction.commandName)]
+ .respond(this.client, interaction,
+ interaction.inGuild() ? interaction.guild : false,
+ // @ts-ignore
+ interaction.inGuild() ? this.client.guildconfig.prefixes.has(interaction.guild.id) ? this.client.guildconfig.prefixes.get(interaction.guild.id) !== null ? this.client.guildconfig.prefixes.get(interaction.guild.id) : defaultPrefix : defaultPrefix : defaultPrefix
+ ).catch((e) => {console.log(e); success = false;});
}
- catch (e) {console.log(e); success = false;}
+ catch (e) {success = false;}
this.afterHandle(this.client, interaction, success);
};
- public importCommands(dir?: string): SlashManager {
- dir = dir || './slash';
- const commands = fs.readdirSync(dir).filter(file => file.endsWith('.js'));
- for (const command of commands) {
- this.add(require(`../${dir}/${command}`)(this.client));
- }
+ public importCommands(register: boolean | RegisterMode = false, dir: string = './slash', log: (command: SlashCommand, manager: SlashManager) => void = () => {}): SlashManager {
+ const search = (toSearch: string): void => {
+ let cdir = fs.readdirSync(toSearch);
+ const commands = cdir.filter(file => file.endsWith('.js'));
+ for (const command of commands) {
+ const slashCommand = require(`../${toSearch}/${command}`)(this.client);
+ this.add(slashCommand, register);
+ log(slashCommand, this);
+ }
+ const subdirs = cdir.filter(file => fs.lstatSync(`${toSearch}/${file}`).isDirectory());
+ subdirs.forEach(subdir => search(`${toSearch}/${subdir}`));
+ };
+ search(dir);
return this;
};