Compare commits

..

No commits in common. "master" and "next-akairo" have entirely different histories.

46 changed files with 236 additions and 648 deletions

View file

@ -1,11 +1,6 @@
# Woomy # Woomy
Woomy is a all-purpose discord bot built off the [guidebot](https://github.com/AnIdiotsGuide/guidebot) base and coded in node.js using discord.js. Woomy is a all-purpose discord bot built off the [guidebot](https://github.com/AnIdiotsGuide/guidebot) base and coded in node.js using discord.js.
# Notice
Woomy v1 (this repository) is currently only being maintained. Bugs and issues will be fixed if they come up, but no new features will be added. Pull requests that add new features to Woomy should instead be contributed to the version 2 codebase, found [here](https://github.com/woomyware/v2).
When Woomy v2 is released, Woomy v1 will no longer be maintained.
# How to use # How to use
The easiest way to use Woomy is to invite it to your server with [this link.](https://discord.com/oauth2/authorize?client_id=435961704145485835&permissions=2134240503&scope=bot) It is hosted 24/7 and automatically updates itself when a new release is made available, making sure you always get the newest features. The easiest way to use Woomy is to invite it to your server with [this link.](https://discord.com/oauth2/authorize?client_id=435961704145485835&permissions=2134240503&scope=bot) It is hosted 24/7 and automatically updates itself when a new release is made available, making sure you always get the newest features.

View file

@ -12,12 +12,10 @@ const config = {
"token": "", // Your bot's token. "token": "", // Your bot's token.
"devtoken": "", // (optional) another token, meant for a bot used for development "devtoken": "", // (optional) another token, meant for a bot used for development
"dblkey": "", // (optional) top.gg key, sends bot statistics to top.gg. You do not need this. "dblkey": "", // (optional) top.gg key, sends bot statistics to top.gg. You do not need this.
"sentry": "",
"server": "",
// Configurable API endpoints // Configurable API endpoints
endpoints: { endpoints: {
invidious: '' invidious: 'https://invidio.us/api/'
}, },
// Default per-server settings // Default per-server settings

View file

@ -6,17 +6,8 @@ const Discord = require('discord.js');
const { promisify } = require('util'); const { promisify } = require('util');
const readdir = promisify(require('fs').readdir); const readdir = promisify(require('fs').readdir);
const Enmap = require('enmap'); const Enmap = require('enmap');
const sentry = require('@sentry/node');
const chalk = require('chalk'); const chalk = require('chalk');
const client = new Discord.Client({ ws: { intents: [ const client = new Discord.Client();
'GUILDS',
'GUILD_MEMBERS',
'GUILD_EMOJIS',
'GUILD_VOICE_STATES',
'GUILD_MESSAGES',
'DIRECT_MESSAGES',
'GUILD_MESSAGE_REACTIONS',
]}});
try { try {
client.config = require('./config'); client.config = require('./config');
@ -56,10 +47,6 @@ if(client.config.devmodeEnabled == true && process.env['USER'] != 'container') {
const DBL = require("dblapi.js"); const DBL = require("dblapi.js");
const dblapi = new DBL(client.config.dblkey, client); const dblapi = new DBL(client.config.dblkey, client);
}; };
if(client.config.sentry.length > 0) {
sentry.init({ dsn: client.config.sentry });
};
}; };
client.commands = new Enmap(); client.commands = new Enmap();
@ -103,10 +90,4 @@ const init = async () => {
}; };
}; };
process.on('SIGINT', function(){ init();
client.logger.info("Disconnecting...")
client.destroy();
process.exit();
});
init();

View file

@ -4,28 +4,28 @@
"description": "Woomy is a all-purpose discord bot built off the guidebot base and coded in node.js using discord.js.", "description": "Woomy is a all-purpose discord bot built off the guidebot base and coded in node.js using discord.js.",
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"@discordjs/opus": "^0.6.0", "@discordjs/opus": "^0.2.1",
"@sentry/node": "^6.12.0", "better-sqlite3": "^5.4.1",
"better-sqlite3": "^7.4.0", "chalk": "^4.0.0",
"chalk": "^4.1.1", "dblapi.js": "^2.3.1",
"dblapi.js": "^2.4.1", "discord.js": "^12.0.2",
"discord-paginator.js": "git+https://gitdab.com/embee/discord-paginator.js", "enmap": "^5.2.4",
"discord.js": "^12.5.3", "garfield": "^1.1.2",
"enmap": "^5.8.5",
"ffmpeg-static": "^4.3.0",
"hastebin-gen": "^2.0.5", "hastebin-gen": "^2.0.5",
"moment": "^2.29.1", "moment": "^2.24.0",
"moment-duration-format": "^2.3.2", "moment-duration-format": "^2.3.2",
"nekos.life": "^2.0.5", "nekos.life": "^2.0.5",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.0",
"pretty-ms": "^7.0.1", "prism-media": "^1.2.1",
"randomcolor": "^0.6.2", "randomcolor": "^0.5.4",
"relevant-urban": "^2.0.0", "relevant-urban": "^2.0.0",
"request": "^2.88.2",
"to-zalgo": "^1.0.1", "to-zalgo": "^1.0.1",
"urban": "^0.3.2", "urban": "^0.3.2",
"weather-js": "^2.0.0", "weather-js": "^2.0.0",
"ytdl-core": "^4.9.1" "ytdl-core-discord": "^1.2.0"
}, },
"devDependencies": {},
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },

View file

@ -15,19 +15,19 @@
"If I'm not back again this time tomorrow", "If I'm not back again this time tomorrow",
"Carry on, carry on as if nothing really matters", "Carry on, carry on as if nothing really matters",
"Too late, my time has come", "Too late, my time has come",
"Sends shivers down my spine, body's aching all the time", "sends shivers down my spine, body's aching all the time",
"Goodbye, everybody, I've got to go", "Goodbye, everybody, I've got to go",
"Gotta leave you all behind and face the truth", "Gotta leave you all behind and face the truth",
"Mama, ooh, (Anyway the wind blows)", "Mama, ooh, (Anyway the wind blows)",
"I don't wanna die", "I don't wanna die",
"I sometimes wish I'd never been born at all", "I sometimes wish I'd never been born at all",
"I see a little silhouetto of a man", "i see a little silhouetto of a man",
"Scaramouche! Scaramouche! will you do the Fandango?", "Scaramouche! Scaramouche! will you do the Fandango?",
"Thunderbolt and lightning, very, very fright'ning me", "Thunderbolt and lightning, very, very fright'ning me",
"(Galileo) Galileo, (Galileo) Galileo, Galileo Figaro magnifico", "(Galileo) Galileo, (Galileo) Galileo, Galileo Figaro magnifico",
"I'm just a poor boy, nobody loves me", "I'm just a poor boy, nobody loves me",
"He's just a poor boy from a poor family", "He's just a poor boy from a poor family",
"Spare him his life from this monstrosity", "spare him his life from this monstrosity",
"Easy come, easy go, will you not let me go?", "Easy come, easy go, will you not let me go?",
"Bismillah! No, we will not let you go", "Bismillah! No, we will not let you go",
"(Let him go!) Bismillah! We will not let you go", "(Let him go!) Bismillah! We will not let you go",
@ -35,17 +35,17 @@
"(Let me go) Will not let you go", "(Let me go) Will not let you go",
"(Let me go) Will not let you go", "(Let me go) Will not let you go",
"(Let me go) Ah", "(Let me go) Ah",
"No, no, no, no, no, no, no", "no, no, no, no, no, no, no",
"(Oh mamma mia, mamma mia) Mamma mia, let me go", "(Oh mamma mia, mamma mia) Mamma mia, let me go",
"Beelzebub has the devil put aside for me, for me, for me!", "Beelzebub has the devil put aside for me, for me, for me!",
"So you think you can stone me and spit in my eye?", "So you think you can stone me and spit in my eye?",
"So you think you can love me and leave me to die?", "so you think you can love me and leave me to die?",
"Oh baby, can't do this to me, baby!", "Oh baby, can't do this to me, baby!",
"Just gotta get out, just gotta get right outta here!", "Just gotta get out, just gotta get right outta here!",
"Nothing really matters, anyone can see", "Nothing really matters, anyone can see",
"Nothing really matters", "nothing really matters",
"Nothing really matters, to me", "Nothing really matters, to me",
"Any way the wind blows" "any way the wind blows"
], ],
"creeper": [ "creeper": [

View file

@ -7,7 +7,7 @@ exports.run = async (client, message, [action, ...member]) => {
if(!action) { if(!action) {
return message.channel.send( return message.channel.send(
`<:error:466995152976871434> You didn't tell me if I was meant to add or remove someone from the blocklist! Usage: \`${client.commands.get(`blocklist`).help.usage}\`` `<:error:466995152976871434> You didn't tell me if I was meant to add or remove someone from the blacklist! Usage: \`${client.commands.get(`blacklist`).help.usage}\``
) )
} }
@ -15,7 +15,7 @@ exports.run = async (client, message, [action, ...member]) => {
if(!member) { if(!member) {
return message.channel.send( return message.channel.send(
`<:error:466995152976871434> You didn't tell me who to add to the blocklist! Usage: \`${client.commands.get(`blocklist`).help.usage}\`` `<:error:466995152976871434> You didn't tell me who to blacklist! Usage: \`${client.commands.get(`blacklist`).help.usage}\``
); );
}; };
@ -41,18 +41,18 @@ exports.run = async (client, message, [action, ...member]) => {
}; };
if (user.id === message.guild.owner.id) { if (user.id === message.guild.owner.id) {
return message.channel.send("<:error:466995152976871434> You can't add the owner to the blocklist!") return message.channel.send("<:error:466995152976871434> You can't blacklist the owner!")
}; };
let admin = message.guild.member(message.author) let admin = message.guild.member(message.author)
if (user.roles.highest.position >= admin.roles.highest.position && admin.user.id !== message.guild.ownerID) { if (user.roles.highest.position >= admin.roles.highest.position && admin.user.id !== message.guild.ownerID) {
return message.channel.send( return message.channel.send(
`<:error:466995152976871434> You can't add people higher ranked than yourself to the blocklist!` `<:error:466995152976871434> You can't blacklist people higher ranked than yourself!`
); );
}; };
if(user.id === message.member.id) { if(user.id === message.member.id) {
return message.channel.send('<:error:466995152976871434> You can\'t add yourself to the blocklist!'); return message.channel.send('<:error:466995152976871434> You can\'t blacklist yourself!');
}; };
let blacklisted = false; let blacklisted = false;
@ -65,13 +65,13 @@ exports.run = async (client, message, [action, ...member]) => {
}); });
if(blacklisted == true) { if(blacklisted == true) {
return message.channel.send('<:error:466995152976871434> This person is already on the blocklist!'); return message.channel.send('<:error:466995152976871434> This person has already been blacklisted!');
}; };
}; };
client.settings.push(message.guild.id, user.id, "blacklisted") client.settings.push(message.guild.id, user.id, "blacklisted")
return message.channel.send(`<:success:466995111885144095> Added \`${user.user.tag}\` to the blocklist.`) return message.channel.send(`<:success:466995111885144095> Blacklisted \`${user.user.tag}\``)
}; };
@ -99,26 +99,26 @@ exports.run = async (client, message, [action, ...member]) => {
}); });
if(blacklisted != true) { if(blacklisted != true) {
return message.channel.send('<:error:466995152976871434> This user isn\'t on the blocklist!'); return message.channel.send('<:error:466995152976871434> This user isn\'t blacklisted!');
}; };
client.settings.remove(message.guild.id, user.id, "blacklisted") client.settings.remove(message.guild.id, user.id, "blacklisted")
return message.channel.send(`<:success:466995111885144095> Removed \`${user.user.tag}\` from the blocklist.`) return message.channel.send(`<:success:466995111885144095> Removed \`${user.user.tag}\` from the blacklist.`)
}; };
}; };
exports.conf = { exports.conf = {
enabled: true, enabled: true,
guildOnly: true, guildOnly: true,
aliases: ['bl'], aliases: [],
permLevel: "Administrator", permLevel: "Administrator",
requiredPerms: [] requiredPerms: []
}; };
exports.help = { exports.help = {
name: "blocklist", name: "blacklist",
category: "Moderation", category: "Moderation",
description: "Allows you to configure Woomy's blocklist. Users on the blocklist cannot use commands.", description: "Allows you to configure Woomy's blacklist. Blacklisted users cannot use commands.",
usage: "blocklist [add/remove] [member]" usage: "blacklist [add/remove] [member]"
}; };

View file

@ -1,46 +1,42 @@
var allowed = ["+", "-", "*", "/", "(", ")", " "]; var allowed = ["+", "-", "*", "/", "(", ")", " "];
exports.run = (client, message, args) => { exports.run = (client, message, args) => {
let exercise = args.join(" "); let exercise = args.join(" ");
if (!exercise) { if (!exercise) {
return message.channel.send( return message.channel.send(
`<:error:466995152976871434> No equation provided. Usage :\`${client.commands.get(`calculate`).help.usage}\`` `<:error:466995152976871434> No equation provided. Usage :\`${client.commands.get(`calculate`).help.usage}\``
); );
} }
for (var i = 0; i < exercise.length; i++) {
let c = exercise.charAt(i);
let found = allowed.find((element) => element === c);
if(c == "0") found = true;
if(!(Number(c) || found))
{
return message.channel.send(
`<:error:466995152976871434> Invalid equation. Please use \`*\` for multiplication and \`/\` for division!`
);
}
}
let result = (new Function( 'return ' + exercise )());
try { message.channel.send(`\`RESULT:\`\n\`\`\`${result}\`\`\``);
for (var i = 0; i < exercise.length; i++) { };
let c = exercise.charAt(i);
let found = allowed.find((element) => element === c);
if(c == "0") found = true;
if(!(Number(c) || found))
{
return message.channel.send(
`<:error:466995152976871434> Invalid equation. Please use \`*\` for multiplication and \`/\` for division!`
);
}
}
let result = (new Function( 'return ' + exercise )());
message.channel.send(`\`RESULT:\`\n\`\`\`${result}\`\`\``) exports.conf = {
} catch (err) { enabled: true,
message.channel.send('<:error:466995152976871434> Malformed input.') guildOnly: false,
} aliases: ["calc", "math"],
}; permLevel: "User",
requiredPerms: []
};
exports.conf = { exports.help = {
enabled: true, name: "calculate",
guildOnly: false, category: "Utility",
aliases: ["calc", "math"], description: "Solves basic mathematical equations.",
permLevel: "User", usage: "calculate [equation]"
requiredPerms: [] };
};
exports.help = {
name: "calculate",
category: "Utility",
description: "Solves basic mathematical equations.",
usage: "calculate [equation]"
};

View file

@ -5,9 +5,6 @@ exports.run = async (bot, message, args) => {
fetch('https://catfact.ninja/facts') fetch('https://catfact.ninja/facts')
.then(res => res.json()) .then(res => res.json())
.then(json => message.channel.send(`__**Did you know?**__\n${json.data[0].fact}`)) .then(json => message.channel.send(`__**Did you know?**__\n${json.data[0].fact}`))
.catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
});
} catch(err) { } catch(err) {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
}; };

View file

@ -1,4 +1,15 @@
exports.run = (client, message, args) => { exports.run = (client, message, args) => {
if(!args[0]) {
return message.channel.send(
`<:error:466995152976871434> Invalid choice. Usage: \`${client.commands.get(`flip`).help.usage}\``
);
};
if(args[0].toLowerCase() != "heads" && args[0].toLowerCase() != "tails") {
return message.channel.send(
`<:error:466995152976871434> Invalid choice. Usage: \`${client.commands.get(`flip`).help.usage}\``
);
};
var coin = [ var coin = [
"Heads!", "Heads!",
"Tails!" "Tails!"
@ -20,5 +31,5 @@ exports.help = {
name: "coinflip", name: "coinflip",
category: "Fun", category: "Fun",
description: "Flips a coin!", description: "Flips a coin!",
usage: "coinflip" usage: "coinflip [heads/tails]"
}; };

View file

@ -12,7 +12,7 @@ exports.run = async (client, message, args, level) => {
embed = new Discord.MessageEmbed(); embed = new Discord.MessageEmbed();
embed.setTitle(colour) embed.setTitle(colour)
embed.setColor(colour); embed.setColor(colour);
embed.setImage(`https://fakeimg.pl/256x256/${colour.replace("#", "")}/?text=%20`); embed.setImage("https://api.alexflipnote.xyz/colour/image/" + colour.replace("#", ""));
message.channel.send(embed) message.channel.send(embed)
}; };

View file

@ -4,10 +4,7 @@ exports.run = async (bot, message, args) => {
try{ try{
fetch('https://dog-api.kinduff.com/api/facts') fetch('https://dog-api.kinduff.com/api/facts')
.then(res => res.json()) .then(res => res.json())
.then(json => message.channel.send(`__**Did you know?**__\n ${json.facts[0]}`)) .then(json => message.channel.send(`__**Did you know?**__\n ${json.facts[0]}`));
.catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
});
} catch(err) { } catch(err) {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
}; };

View file

@ -2,68 +2,23 @@ const { getGuild } = require('../modules/music')
module.exports.run = async (client, message, args, level) =>{ module.exports.run = async (client, message, args, level) =>{
guild = getGuild(message.guild.id) guild = getGuild(message.guild.id)
const lvl = client.config.permLevels.find(l => l.level === level) guild.queue = []
guild.playing = false
guild.paused = false
guild.skippers = []
if (lvl.level >= 1) { if (guild.dispatcher) {
guild.queue = [] guild.dispatcher.end('silent')
guild.playing = false
guild.paused = false
guild.skippers = []
guild.fixers = []
guild.channel = null
if (guild.dispatcher) {
guild.dispatcher.end('silent')
}
guild.fixers = []
message.channel.send(
'<:success:466995111885144095> Music has been fixed!'
)
return
} }
const vc = message.guild.members.cache.get(client.user.id).voice.channel message.channel.send('<:success:466995111885144095> Music has been fixed (hopefully)')
if (guild.fixers.indexOf(message.author.id) === -1) {
guild.fixers.push(message.author.id)
if (guild.fixers.length >= Math.ceil(vc.members.filter(member => !member.user.bot).size / 2)) {
guild.queue = []
guild.playing = false
guild.paused = false
guild.skippers = []
guild.fixers = []
guild.channel = null
if (guild.dispatcher) {
guild.dispatcher.end('silent')
}
guild.fixers = []
message.channel.send(
'<:success:466995111885144095> Music has been fixed!'
)
} else {
message.channel.send(
`<:success:466995111885144095> Your vote has been acknowledged! **${guild.fixers.length + '/' + Math.ceil(vc.members.filter(member => !member.user.bot).size / 2)}**`
)
};
} else {
message.channel.send(
'<:denied:466995195150336020> You cannot vote twice!'
)
}
} }
exports.conf = { exports.conf = {
enabled: true, enabled: true,
guildOnly: true, guildOnly: true,
aliases: [], aliases: [],
permLevel: "User", permLevel: "Moderator",
requiredPerms: [] requiredPerms: []
}; };

View file

@ -10,8 +10,6 @@ exports.run = (client, message) => {
skip(message.guild, 'skip') skip(message.guild, 'skip')
guild.skippers = []
message.channel.send('<:success:466995111885144095> Song skipped.') message.channel.send('<:success:466995111885144095> Song skipped.')
}; };

30
src/commands/foxgirl.js Normal file
View file

@ -0,0 +1,30 @@
const API = require('nekos.life');
const {sfw} = new API();
exports.run = async (client, message) => {
message.channel.startTyping();
try {
sfw.foxGirl().then((json) => {
message.channel.send(json.url)
message.channel.stopTyping();
});
} catch (err) {
client.logger.error("foxgirl.js: " + err);
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`)
message.channel.stopTyping();
};
};
exports.conf = {
enabled: false,
guildOnly: false,
aliases: [],
permLevel: "User",
requiredPerms: ["EMBED_LINKS"]
};
exports.help = {
name: "foxgirl",
category: "Image",
description: "Sends you pictures of fox girls.",
usage: "foxgirl"
};

View file

@ -1,26 +1,8 @@
const fetch = require("node-fetch") const garfield = require("garfield");
const { MessageEmbed } = require('discord.js')
exports.run = async (client, message) => { exports.run = async (client, message) => {
message.channel.startTyping(); message.channel.send({ files: [garfield.random()] }).catch(() => message.channel.send(
try { "<:error:466995152976871434> API didn't respond, try again in a few seconds."
fetch('https://garfield-comics.glitch.me/~SRoMG/?date=xxxx') ));
.then(res => res.json())
.then(json => {
const embed = new MessageEmbed()
.setTitle(`${json.data.name} (No. ${json.data.number})`)
.setColor(client.embedColour(message))
.setURL('https://www.mezzacotta.net/garfield/?comic=' + json.data.number)
.setImage(json.data.image.src);
message.channel.send(embed)
})
.catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
});
message.channel.stopTyping();
} catch (err) {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`)
message.channel.stopTyping();
};
}; };
exports.conf = { exports.conf = {

View file

@ -4,10 +4,7 @@ exports.run = async (client, message) => {
try { try {
fetch('http://inspirobot.me/api?generate=true') fetch('http://inspirobot.me/api?generate=true')
.then(res => res.text()) .then(res => res.text())
.then(body => message.channel.send({files: [new Discord.MessageAttachment(body)]})) .then(body => message.channel.send({files: [new Discord.MessageAttachment(body)]}));
.catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
});
message.channel.stopTyping(); message.channel.stopTyping();
} catch (err) { } catch (err) {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`) message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`)

View file

@ -1,31 +0,0 @@
const fetch = require("node-fetch")
exports.run = async (client, message, args) => {
message.channel.startTyping();
try{
fetch(`https://purrbot.site/api/img/sfw/kitsune/img/`)
.then(res => res.json())
.then(json => message.channel.send(json.link))
.catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
});
message.channel.stopTyping();
} catch(err) {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
message.channel.stopTyping();
};
};
exports.conf = {
enabled: false,
guildOnly: false,
aliases: ['foxgirl'],
permLevel: "User",
requiredPerms: ["EMBED_LINKS"]
};
exports.help = {
name: "kitsune",
category: "Image",
description: "Sends you cute wholesome pictures of foxgirls.",
usage: "kitsune"
};

View file

@ -1,31 +0,0 @@
const identities = require ("../../resources/other/identities.json");
exports.run = async (client, message, args) => {
if (!args[0]) {
return message.channel.send("Missing arguments, please provide me with a query!")
}
const query = args.join("+")
let link = ("https://lmgtfy.com/?q=" + query)
if (message.flags.includes('d')) {
link = "https://lmgtfy.com/?q=" + query + "&pp=1&s=d"
}
message.channel.send(link)
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User",
requiredPerms: []
};
exports.help = {
name: "lmgtfy",
category: "Fun",
description: "For when you need to remind someone search engines exist..",
usage: "lmgtfy <question>"
};

View file

@ -1,7 +1,7 @@
exports.run = (client, message, args) => { exports.run = (client, message, args) => {
if (!args[0]) if (!args[0])
return message.channel.send( return message.channel.send(
`<:error:466995152976871434> No username provided. Usage: \`${client.commands.get(`msearch`).help.usage}\`` `<:error:466995152976871434> No username provided. Usage: \`${client.commands.get(``).help.usage}\``
); );
var mlist = ""; var mlist = "";
var count = 0; var count = 0;

View file

@ -1,16 +1,15 @@
const fetch = require("node-fetch") const API = require('nekos.life');
exports.run = async (client, message, args) => { const {sfw} = new API();
exports.run = async (client, message) => {
message.channel.startTyping(); message.channel.startTyping();
try{ try {
fetch(`https://purrbot.site/api/img/sfw/neko/img/`) sfw.neko().then((json) => {
.then(res => res.json()) message.channel.send(json.url);
.then(json => message.channel.send(json.link))
.catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
});
message.channel.stopTyping(); message.channel.stopTyping();
} catch(err) { });
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); } catch (err) {
client.logger.error("neko.js: " + err);
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`)
message.channel.stopTyping(); message.channel.stopTyping();
}; };
}; };
@ -26,6 +25,6 @@ exports.conf = {
exports.help = { exports.help = {
name: "neko", name: "neko",
category: "Image", category: "Image",
description: "Sends you cute wholesome pictures of catgirls.", description: "Sends you pictures of catgirls.",
usage: "neko" usage: "neko"
}; };

View file

@ -1,22 +1,21 @@
const fetch = require("node-fetch") const API = require('nekos.life');
exports.run = async (client, message, args) => { const {sfw} = new API();
exports.run = async (client, message) => {
message.channel.startTyping(); message.channel.startTyping();
try{ try {
fetch(`https://purrbot.site/api/img/sfw/neko/gif/`) sfw.nekoGif().then((json) => {
.then(res => res.json()) message.channel.send(json.url);
.then(json => message.channel.send(json.link))
.catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
});
message.channel.stopTyping(); message.channel.stopTyping();
} catch(err) { });
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); } catch (err) {
client.logger.error("nekogif.js: " + err);
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`)
message.channel.stopTyping(); message.channel.stopTyping();
}; };
}; };
exports.conf = { exports.conf = {
enabled: false, enabled: false,
guildOnly: false, guildOnly: false,
aliases: ["catgirlgif"], aliases: ["catgirlgif"],
permLevel: "User", permLevel: "User",

View file

@ -17,7 +17,7 @@ exports.run = async (client, message) => {
const embed = new MessageEmbed() const embed = new MessageEmbed()
embed.setTitle('Now playing') embed.setTitle('Now playing')
embed.setThumbnail(client.config.endpoints.invidious + s.video.videoThumbnails[1].url) embed.setThumbnail(s.video.videoThumbnails[1].url)
embed.setColor(client.embedColour(message)) embed.setColor(client.embedColour(message))
embed.setDescription(`**[${s.video.title}](https://www.youtube.com/watch?v=${s.video.videoId})**`) embed.setDescription(`**[${s.video.title}](https://www.youtube.com/watch?v=${s.video.videoId})**`)
embed.addField('Channel:', s.video.author, true) embed.addField('Channel:', s.video.author, true)

View file

@ -21,5 +21,5 @@ exports.help = {
name: "play", name: "play",
category: "Music", category: "Music",
description: 'Plays the song you request, or adds it to the queue.', description: 'Plays the song you request, or adds it to the queue.',
usage: 'play [song]', usage: 'playnext [song]',
}; };

View file

@ -1,48 +0,0 @@
// Copyright 2020 Emily J. / mudkipscience and contributors. Subject to the AGPLv3 license.
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: 'User',
requiredPerms: ['ATTACH_FILES'],
}
exports.help = {
name: 'pride',
category: 'Fun',
description: 'Adds a pride flag ring to your avatar. Available flags are lesbian, gay, bisexual, pansexual, trans, asexual, aromantic and ally.',
usage: '`pride [flag]` - Adds a pride flag overlay to your avatar.\n`pride -g [flag]` - Adds a pride flag gradient on your avatar.',
}
const url = 'https://demirramon.com/gen/pride.png'
const Discord = require('discord.js')
exports.run = (client, message, args) => {
const flag = args[0]
if (!flag) {
return message.channel.send('<:error:466995152976871434> Missing argument, the `flag` argument is required!')
}
const available = ['lesbian', 'gay', 'bisexual', 'pansexual', 'trans', 'asexual', 'aromantic', 'ally']
if (!available.includes(flag.toLowerCase())) {
return message.channel.send(`<:error:466995152976871434> This flag isn't available, sorry ;~;\nAvailable flags: \`${available.join('`, `')}\``)
}
let gradient = 'false'
if (message.flags.includes('g')) {
gradient = 'true'
}
message.channel.startTyping()
const params = `image=${message.author.avatarURL({ format: 'png', size: 2048 })}&flag=${flag.toLowerCase()}&full=true&gradient=${gradient}&background=false&fit=true&v=2019-08-07`
try {
message.channel.stopTyping()
message.channel.send({ files: [new Discord.MessageAttachment(url + '?' + params)] })
} catch (err) {
message.channel.stopTyping()
message.channel.send(`<:error:466995152976871434> Error when generating image: \`${err}\``)
}
}

View file

@ -3,25 +3,19 @@ exports.run = async (client, message, args) => {
return message.channel.send( return message.channel.send(
`<:error:466995152976871434> What am I meant to rate? Usage: \`${client.commands.get(`rate`).help.usage}\`` `<:error:466995152976871434> What am I meant to rate? Usage: \`${client.commands.get(`rate`).help.usage}\``
); );
var rating = [
var rating = [ "0/10",
"0/10", "1/10",
"1/10", "2/10",
"2/10", "3/10",
"3/10", "4/10",
"4/10", "5/10",
"5/10", "6/10",
"6/10", "7/10",
"7/10", "8/10",
"8/10", "9/10",
"9/10", "10/10"
"10/10" ];
];
if (message.content.includes("@everyone") || message.content.includes("@here") || message.content.includes("<@&")) {
return message.channel.send('>:(');
};
let mess = rating.random(); let mess = rating.random();
message.channel.send(`<:star:618393201501536258> I give ${args.join(" ")} a **${mess}**`); message.channel.send(`<:star:618393201501536258> I give ${args.join(" ")} a **${mess}**`);
}; };

View file

@ -1,21 +1,14 @@
const fetch = require('node-fetch'); exports.run = async (client, message) => {// eslint-disable-line no-unused-vars
exports.run = (client, message) => {// eslint-disable-line no-unused-vars
// This actually shuts down the bot, you'll need to use something like pm2 to get it to restart // This actually shuts down the bot, you'll need to use something like pm2 to get it to restart
message.channel.send("<:reboot:467216876938985482> Restarting..."); await message.channel.send("<:reboot:467216876938985482> Restarting...");
client.destroy();
require("util").promisify(setTimeout);
fetch('https://gamecp.apex.to/api/client/servers/1fc76afa-9a4d-497b-983a-a898795ab5b5/power', { client.commands.forEach( async cmd => {
method: 'post', await client.unloadCommand(cmd);
body: JSON.stringify({ 'signal': 'restart' }),
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${client.config.server}` }
}).catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
}); });
process.exit();
}; };
exports.conf = { exports.conf = {

View file

@ -6,9 +6,6 @@ exports.run = (client, message) => {
fetch('http://mityurl.com/y/yKsQ/r', { redirect: 'follow' }) fetch('http://mityurl.com/y/yKsQ/r', { redirect: 'follow' })
.then(res => res) .then(res => res)
.then(res => message.channel.send(`>:] ${res.url}`)) .then(res => message.channel.send(`>:] ${res.url}`))
.catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
});
} catch(err) { } catch(err) {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
}; };

View file

@ -1,77 +0,0 @@
const Discord = require("discord.js");
const BasePaginator = require('discord-paginator.js');
const fetch = require('node-fetch');
const prettifyMiliseconds = require('pretty-ms');
exports.run = async (client, message, args) =>{
fetch('https://splatoon2.ink/data/coop-schedules.json', { headers: { 'User-Agent': client.config.userAgent }})
.then(res => res.json())
.then(json => {
fetch('https://splatoon2.ink/data/timeline.json', { headers: { 'User-Agent': client.config.userAgent }})
.then(timelineRes => timelineRes.json())
.then(timelineJson => {
const embeds = [];
if ((json.details[0].start_time * 1000) > Date.now() === true) {
embeds.push(
new Discord.MessageEmbed()
.setTitle('Upcoming Salmon Run')
.setColor(client.embedColour(message))
.setImage('https://splatoon2.ink/assets/splatnet/'+json.details[0].stage.image)
.addField('Map', json.details[0].stage.name, true)
.setFooter(`Page 1/2 | Starting in ${prettifyMiliseconds(json.details[0].start_time * 1000 - Date.now(), { secondsDecimalDigits: 0 })} | Data provided by splatoon2.ink`)
);
} else {
embeds.push(
new Discord.MessageEmbed()
.setTitle('Current Salmon Run')
.setColor(client.embedColour(message))
.setThumbnail('https://splatoon2.ink/assets/splatnet'+timelineJson.coop.reward_gear.gear.image)
.setImage('https://splatoon2.ink/assets/splatnet/'+json.details[0].stage.image)
.addField('Map', json.details[0].stage.name, true)
.addField('Reward Gear', timelineJson.coop.reward_gear.gear.name, true)
.addField('Weapons', json.details[0].weapons[0].weapon.name+', '+json.details[0].weapons[1].weapon.name+', '+json.details[0].weapons[2].weapon.name+', '+json.details[0].weapons[3].weapon.name)
.setFooter(`Page 1/2 | Ending in ${prettifyMiliseconds((json.details[0].end_time * 1000) - Date.now(), { secondsDecimalDigits: 0 })} | Data provided by splatoon2.ink`)
);
}
embeds.push(
new Discord.MessageEmbed()
.setTitle('Upcoming Salmon Run')
.setColor(client.embedColour(message))
.setImage('https://splatoon2.ink/assets/splatnet/'+json.details[1].stage.image)
.addField('Map', json.details[1].stage.name, true)
.addField('Weapons', json.details[1].weapons[1].weapon.name+', '+json.details[1].weapons[1].weapon.name+', '+json.details[1].weapons[2].weapon.name+', '+json.details[1].weapons[3].weapon.name)
.setFooter(`Page 2/2 | Starting in ${prettifyMiliseconds(json.details[1].start_time * 1000 - Date.now(), { secondsDecimalDigits: 0 })} | Data provided by splatoon2.ink`)
);
const Paginator = new BasePaginator({
pages: embeds,
timeout: 120000,
filter: (reaction, user) => user.id == message.author.id //to filter the reaction collector
})
Paginator.spawn(message.channel)
});
})
.catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
});
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User",
requiredPerms: []
};
exports.help = {
name: "salmonrun",
category: "Splatoon",
description: "Get current map, weapons and gear for salmon run.",
usage: "salmonrun"
};

View file

@ -4,8 +4,8 @@ exports.run = (client, message, args, level) => {
`<:error:466995152976871434> No message provided. Usage: \`${client.commands.get(`echo`).help.usage}\`` `<:error:466995152976871434> No message provided. Usage: \`${client.commands.get(`echo`).help.usage}\``
); );
}; };
if (message.content.includes("@everyone") || message.content.includes("@here") || message.content.includes("<@&")) { if (message.content.includes("@everyone")) {
return message.channel.send('>:('); return message.channel.send(message.author);
}; };
message.delete().catch(O_o => {}); message.delete().catch(O_o => {});

View file

@ -80,7 +80,7 @@ exports.run = async (client, message, args) => {
embed.setAuthor("Settings for: " + message.guild.name, message.guild.iconURL({dynamic: true})) embed.setAuthor("Settings for: " + message.guild.name, message.guild.iconURL({dynamic: true}))
embed.setColor(message.guild.member(client.user).displayHexColor) embed.setColor(message.guild.member(client.user).displayHexColor)
embed.setDescription("You can edit these settings using the commands in the 'configure' section of the help command.") embed.setDescription("You can edit these settings using the commands in the 'configure' section of the help command.")
embed.addFields({ name: "General:", value: `Prefix: \`${prefix}\`\nChat logging: ${chatChan}\nMod logging: ${modChan}\nRaid mode: ${raidMode}\nJoin/leave channel: ${greetChan}\nWelcome message: ${welcomeMessage}\nLeave message: ${leaveMessage}`, inline: true}, {name: "Roles:", value: `Moderator: ${modRole}\nAdministrator: ${adminRole}\nMuted: ${mutedRole}\nBlocklist: ${blacklist}\nAutorole: ${autorole}`, inline: true}) embed.addFields({ name: "General:", value: `Prefix: \`${prefix}\`\nChat logging: ${chatChan}\nMod logging: ${modChan}\nRaid mode: ${raidMode}\nJoin/leave channel: ${greetChan}\nWelcome message: ${welcomeMessage}\nLeave message: ${leaveMessage}`, inline: true}, {name: "Roles:", value: `Moderator: ${modRole}\nAdministrator: ${adminRole}\nMuted: ${mutedRole}\nBlacklisted: ${blacklist}\nAutorole: ${autorole}`, inline: true})
message.channel.send(embed) message.channel.send(embed)
}; };

View file

@ -12,15 +12,11 @@ exports.run = async (client, message, args) => {
] ]
if (!args[0]) { if (!args[0]) {
return message.channel.send( return message.channel.send(client.userError(exports, 'Missing argument, the `name1` argument is required!'))
`<:error:466995152976871434> No message provided. Usage: \`${client.commands.get(`ship`).help.usage}\``
);
} }
if (!args[1]) { if (!args[1]) {
return message.channel.send( return message.channel.send(client.userError(exports, 'Missing argument, the `name2` argument is required!'))
`<:error:466995152976871434> No message provided. Usage: \`${client.commands.get(`ship`).help.usage}\``
);
} }
const firstName = args[0] const firstName = args[0]

View file

@ -19,8 +19,6 @@ exports.run = (client, message, args, level) => {
if (guild.queue[0].requestedBy.id === message.author.id) { if (guild.queue[0].requestedBy.id === message.author.id) {
skip(message.guild, 'skip') skip(message.guild, 'skip')
guild.skippers = []
message.channel.send( message.channel.send(
'<:success:466995111885144095> Song has been skipped by the user who requested it.' '<:success:466995111885144095> Song has been skipped by the user who requested it.'
) )
@ -34,8 +32,6 @@ exports.run = (client, message, args, level) => {
if (guild.skippers.length >= Math.ceil(vc.members.filter(member => !member.user.bot).size / 2)) { if (guild.skippers.length >= Math.ceil(vc.members.filter(member => !member.user.bot).size / 2)) {
skip(message.guild, 'skip') skip(message.guild, 'skip')
guild.skippers = []
message.channel.send( message.channel.send(
'<:skip:467216735356059660> Song skipped.' '<:skip:467216735356059660> Song skipped.'
) )

View file

@ -15,12 +15,8 @@ exports.run = async (client, message, args) => {
const s = guild.queue[songID] const s = guild.queue[songID]
if (!s) {
return message.channel.send('<:error:466995152976871434> No song was found in the position you specified.')
}
const embed = new MessageEmbed() const embed = new MessageEmbed()
embed.setThumbnail(client.config.endpoints.invidious + s.video.videoThumbnails[1].url) embed.setThumbnail(s.video.videoThumbnails[1].url)
embed.setColor(client.embedColour(message)) embed.setColor(client.embedColour(message))
embed.setDescription(`**[${s.video.title}](https://www.youtube.com/watch?v=${s.video.videoId})**`) embed.setDescription(`**[${s.video.title}](https://www.youtube.com/watch?v=${s.video.videoId})**`)
embed.addField('Channel:', s.video.author, true) embed.addField('Channel:', s.video.author, true)

View file

@ -1,53 +0,0 @@
const Discord = require("discord.js");
const BasePaginator = require('discord-paginator.js');
const fetch = require('node-fetch');
const prettifyMiliseconds = require('pretty-ms');
exports.run = async (client, message, args) =>{
fetch('https://splatoon2.ink//data/merchandises.json', { headers: { 'User-Agent': client.config.userAgent }})
.then(res => res.json())
.then(json => {
const embeds = [];
for ( let i = 0; i < json.merchandises.length; i++ ) {
const embed = new Discord.MessageEmbed()
.setTitle(json.merchandises[i].gear.name)
.setThumbnail('https://splatoon2.ink/assets/splatnet' + json.merchandises[i].gear.image)
.setColor(client.embedColour(message))
.addField('Price', (json.merchandises[i].price).toString(), true)
.addField('Brand', json.merchandises[i].gear.brand.name, true)
.addField('Ability Slots', (json.merchandises[i].gear.rarity + 1).toString(), true)
.addField('Main Ability', json.merchandises[i].skill.name, true)
.addField('Common Ability', json.merchandises[i].gear.brand.frequent_skill.name, true)
.setFooter(`Page ${i+1}/${json.merchandises.length} | Out of stock in ${prettifyMiliseconds(json.merchandises[i].end_time * 1000 - Date.now())} | Data provided by splatoon2.ink`);
embeds.push(embed);
}
const Paginator = new BasePaginator({
pages: embeds,
timeout: 120000,
filter: (reaction, user) => user.id == message.author.id //to filter the reaction collector
})
Paginator.spawn(message.channel)
})
.catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
});
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User",
requiredPerms: []
};
exports.help = {
name: "splatnet",
category: "Splatoon",
description: "See what is currently on offer in the splatnet shop.",
usage: "splatnet"
};

View file

@ -1,60 +0,0 @@
const Discord = require("discord.js");
const BasePaginator = require('discord-paginator.js');
const fetch = require('node-fetch');
const prettifyMiliseconds = require('pretty-ms');
exports.run = async (client, message, args) =>{
fetch('https://splatoon2.ink/data/schedules.json', { headers: { 'User-Agent': client.config.userAgent }})
.then(res => res.json())
.then(json => {
const embeds = [
new Discord.MessageEmbed()
.setTitle('Current Splatoon 2 Maps')
.setColor(client.embedColour(message))
.addField('<:turf_war:814651383911153692> Turf War', `${json.regular[0].stage_a.name}\n${json.regular[0].stage_b.name}`, true)
.addField(`<:ranked:814651402479468544> Ranked: ${json.gachi[0].rule.name}`, `${json.gachi[0].stage_a.name}\n${json.gachi[0].stage_b.name}`, true)
.addField(`<:league:814651415409590363> League: ${json.league[0].rule.name}`, `${json.league[0].stage_a.name}\n${json.league[0].stage_b.name}`, true)
.setFooter(`Page 1/${json.regular.length} | Maps changing in ${prettifyMiliseconds(json.league[0].end_time * 1000 - Date.now(), { secondsDecimalDigits: 0 })} | Data provided by splatoon2.ink`)
];
for ( let i = 1; i < json.regular.length; i++ ) {
embeds.push(
new Discord.MessageEmbed()
.setTitle('Upcoming Splatoon 2 Maps')
.setColor(client.embedColour(message))
.addField('<:turf_war:814651383911153692> Turf War', `${json.regular[i].stage_a.name}\n${json.regular[i].stage_b.name}`, true)
.addField(`<:ranked:814651402479468544> Ranked: ${json.gachi[i].rule.name}`, `${json.gachi[i].stage_a.name}\n${json.gachi[i].stage_b.name}`, true)
.addField(`<:league:814651415409590363> League: ${json.league[i].rule.name}`, `${json.league[i].stage_a.name}\n${json.league[i].stage_b.name}`, true)
.setFooter(`Page ${i+1}/${json.regular.length} | Available in ${prettifyMiliseconds(json.league[i].start_time * 1000 - Date.now(), { secondsDecimalDigits: 0 })} | Data provided by splatoon2.ink`)
);
}
const Paginator = new BasePaginator({
pages: embeds,
timeout: 120000,
filter: (reaction, user) => user.id == message.author.id //to filter the reaction collector
})
Paginator.spawn(message.channel)
})
.catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
});
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: ['splatoonmodes'],
permLevel: "User",
requiredPerms: []
};
exports.help = {
name: "splatoonmaps",
category: "Splatoon",
description: "Get current and upcoming maps and modes for regular, ranked and league battles.",
usage: "splatoonmaps"
};

View file

@ -11,8 +11,6 @@ exports.run = async (client, message) => {
guild.playing = false guild.playing = false
guild.paused = false guild.paused = false
guild.skippers = [] guild.skippers = []
guild.fixers = []
guild.channel = null
message.channel.send('<:success:466995111885144095> Playback stopped!') message.channel.send('<:success:466995111885144095> Playback stopped!')
}; };

View file

@ -1,8 +1,8 @@
const Discord = require("discord.js"); const Discord = require("discord.js");
const coolPeople = require('../../resources/other/coolpeople.json') const coolPeople = require('../../resources/other/coolpeople.json')
exports.run = (client, message, args) => { exports.run = (client, message, args) => {
var user, guild, createdAt, avurl, tag, id; var user, guild, status, createdAt, avurl, tag, id;
var nick = "", roles = "", badges = ""; var nick = "", roles = "", presence = "", badges = "";
var coolPerson = false; var coolPerson = false;
var friendos = coolPeople.coolPeople; var friendos = coolPeople.coolPeople;
@ -74,10 +74,41 @@ exports.run = (client, message, args) => {
createdAt = user.createdAt; createdAt = user.createdAt;
}; };
if(user.presence.status == "online") {
status = `online <:status_online:685462758023626762>`
};
if(user.presence.status == "idle") {
status = `idle <:status_idle:685462771529154561>`
};
if(user.presence.status == "dnd") {
status = `do not disturb <:status_dnd:685462782963220495>`
};
if(user.presence.status == "offline") {
status = `offline <:status_offline:685462758229016633>`
};
if(user.presence.activities[0]) {
presence = "\n• **Presence:** ";
if(user.presence.activities[0].type == "PLAYING") {
presence += `Playing ${user.presence.activities[0].name}`;
};
if(user.presence.activities[0].type == "STREAMING") {
presence += `Streaming ${user.presence.activities[0].name}`;
};
if(user.presence.activities[0].type == "CUSTOM_STATUS") {
presence += `${user.presence.activities[0].state}`;
};
};
embed = new Discord.MessageEmbed(); embed = new Discord.MessageEmbed();
embed.setTitle(tag); embed.setTitle(tag);
embed.setThumbnail(avurl); embed.setThumbnail(avurl);
embed.setDescription(`${badges}• **ID:** ${id}${nick}${guild}\n• **Account created:** ${createdAt}`) embed.setDescription(`${badges}• **ID:** ${id}${nick}\n• **Status:** ${status}${presence}${guild}\n• **Account created:** ${createdAt}`)
embed.setColor(colour); embed.setColor(colour);
message.channel.send(embed); message.channel.send(embed);
}; };

View file

@ -1,31 +0,0 @@
const fetch = require("node-fetch")
exports.run = async (client, message, args) => {
message.channel.startTyping();
try{
fetch(`https://purrbot.site/api/img/sfw/tail/gif/`)
.then(res => res.json())
.then(json => message.channel.send(json.link))
.catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
});
message.channel.stopTyping();
} catch(err) {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
message.channel.stopTyping();
};
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User",
requiredPerms: ["EMBED_LINKS"]
};
exports.help = {
name: "wag",
category: "Image",
description: "Wag the tail :3",
usage: "wag"
};

View file

@ -44,7 +44,6 @@ exports.run = async (client, message, args, error) => {
message.channel.send(embed) message.channel.send(embed)
}); });
} catch(err) { } catch(err) {
message.channel.stopTyping(); // Previously wasnt here causing an issue where woomy would endlessly type.
return message.channel.send(`<:error:466995152976871434> API error: \`${err}\``) return message.channel.send(`<:error:466995152976871434> API error: \`${err}\``)
}; };
}; };

View file

@ -9,10 +9,7 @@ exports.run = async (client, message, args) => {
try{ try{
fetch(`http://yoda-api.appspot.com/api/v1/yodish?text=${encodeURIComponent(speech.toLowerCase())}`) fetch(`http://yoda-api.appspot.com/api/v1/yodish?text=${encodeURIComponent(speech.toLowerCase())}`)
.then(res => res.json()) .then(res => res.json())
.then(json => message.channel.send(json.yodish)) .then(json => message.channel.send(json.yodish));
.catch(err => {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);
});
message.channel.stopTyping(); message.channel.stopTyping();
} catch(err) { } catch(err) {
message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`); message.channel.send(`<:error:466995152976871434> An error has occurred: ${err}`);

View file

@ -1,8 +1,7 @@
const cooldown = new Set(); const cooldown = new Set();
module.exports = async (client, message) => { module.exports = async (client, message) => {
if (message.author.bot) return; if (message.author.bot) return;
if (typeof(message.content) === 'string') message.content = message.content.replace(/\u8203/g,'').replace(/\uB200/g,'').replace("\\uB200",''); // Remove zero-width characters
var settings; var settings;
if(message.guild) { if(message.guild) {
@ -171,7 +170,7 @@ module.exports = async (client, message) => {
if(message.guild && blacklisted == true) { if(message.guild && blacklisted == true) {
try { try {
return message.author.send( return message.author.send(
`<:denied:466995195150336020> You have been blocked from using commands in \`${message.guild.name}\`` `<:denied:466995195150336020> You have been blacklisted from using commands in \`${message.guild.name}\``
); );
} catch(err) { } catch(err) {
client.logger.log(err, "error") client.logger.log(err, "error")

View file

@ -3,8 +3,6 @@ const Discord = require("discord.js");
module.exports = (client, message) => { module.exports = (client, message) => {
if (message.author.bot) return; if (message.author.bot) return;
if(!message.guild) return;
const settings = (message.settings = client.getSettings(message.guild.id)); const settings = (message.settings = client.getSettings(message.guild.id));
if (settings.chatlogsChannel !== "off") { if (settings.chatlogsChannel !== "off") {

View file

@ -13,7 +13,6 @@ module.exports = (client, omsg, nmsg) => {
); );
if (channel) { if (channel) {
if (!nmsg.member) return;
let embed = new Discord.MessageEmbed(); let embed = new Discord.MessageEmbed();
embed.setColor("#fff937"); embed.setColor("#fff937");
embed.setAuthor("Message Edited!", nmsg.member.user.avatarURL({dynamic: true})); embed.setAuthor("Message Edited!", nmsg.member.user.avatarURL({dynamic: true}));
@ -30,7 +29,7 @@ module.exports = (client, omsg, nmsg) => {
return; return;
} }
embed.setDescription(`[Jump to message](https://discord.com/channels/${nmsg.guild.id}/${nmsg.channel.id}/${nmsg.id})\n• Author: ${nmsg.member} (${nmsg.member.user.id})\n• Channel: ${nmsg.channel}\n• Old message: ${omsg.content}\n• New message: ${nmsg.content}`) embed.setDescription(`• Author: ${nmsg.member} (${nmsg.member.user.id})\n• Channel: ${nmsg.channel}\n• Old message: ${omsg.content}\n• New message: ${nmsg.content}`)
try { try {
channel.send({ embed }); channel.send({ embed });
} catch (err) { } catch (err) {

View file

@ -197,6 +197,7 @@ module.exports = client => {
process.on("uncaughtException", err => { process.on("uncaughtException", err => {
const errorMsg = err.stack.replace(new RegExp(`${__dirname}/`, "g"), "./"); const errorMsg = err.stack.replace(new RegExp(`${__dirname}/`, "g"), "./");
client.logger.error(`Uncaught Exception: ${errorMsg}`); client.logger.error(`Uncaught Exception: ${errorMsg}`);
process.exit(1);
}); });
process.on("unhandledRejection", err => { process.on("unhandledRejection", err => {

View file

@ -1,6 +1,6 @@
// Copyright 2020 Emily J. / mudkipscience and contributors. Subject to the AGPLv3 license. // Copyright 2020 Emily J. / mudkipscience and contributors. Subject to the AGPLv3 license.
const ytdl = require('ytdl-core') const ytdl = require('ytdl-core-discord')
const fetch = require('node-fetch') const fetch = require('node-fetch')
const { MessageEmbed } = require('discord.js') const { MessageEmbed } = require('discord.js')
const { utc } = require('moment') const { utc } = require('moment')
@ -28,7 +28,6 @@ exports.getGuild = function (id) {
guild.paused = false guild.paused = false
guild.dispatcher = null guild.dispatcher = null
guild.skippers = [] guild.skippers = []
guild.fixers = []
exports.queue[id] = guild exports.queue[id] = guild
} }
@ -45,9 +44,9 @@ exports.getVideoByQuery = async function (client, query, message) {
try { try {
const id = await ytdl.getURLVideoID(query) const id = await ytdl.getURLVideoID(query)
res = await fetch(`${client.config.endpoints.invidious}/api/v1/videos/${id}`) res = await fetch(`${client.config.endpoints.invidious}v1/videos/${id}`)
} catch (err) { } catch (err) {
res = await fetch(`${client.config.endpoints.invidious}/api/v1/search?q=${encodeURIComponent(query)}`) res = await fetch(`${client.config.endpoints.invidious}v1/search?q=${encodeURIComponent(query)}`)
} }
const parsed = await res.json().catch(function (e) { const parsed = await res.json().catch(function (e) {
@ -69,8 +68,8 @@ exports.getVideoByQuery = async function (client, query, message) {
exports.play = async function (client, message, query, playNext, ignoreQueue) { exports.play = async function (client, message, query, playNext, ignoreQueue) {
const guild = exports.getGuild(message.guild.id) const guild = exports.getGuild(message.guild.id)
guild.message = message guild.message = message
// message.channel.startTyping() message.channel.startTyping()
if (!message.member.voice.channel && !guild.voiceChannel) { if (!message.member.voice.channel && !guild.voiceChannel) {
message.channel.stopTyping() message.channel.stopTyping()
@ -103,10 +102,8 @@ exports.play = async function (client, message, query, playNext, ignoreQueue) {
guild.playing = false guild.playing = false
guild.paused = false guild.paused = false
guild.skippers = [] guild.skippers = []
guild.fixers = []
guild.channel = null
// music not playing, something is in queue // music not playing, something is in queue
} else if ((!guild.playing || !guild.dispatcher) && guild.queue.length > 0) { } else if (!guild.playing && !guild.dispatcher && guild.queue.length > 0) {
guild.queue = [] guild.queue = []
} }
@ -195,7 +192,7 @@ exports.play = async function (client, message, query, playNext, ignoreQueue) {
const v = guild.queue[0] const v = guild.queue[0]
try { try {
guild.dispatcher = connection.play(ytdl(v.video.videoId, { type: 'opus', bitrate: 'auto' })); guild.dispatcher = connection.play(await ytdl(exports.getLinkFromID(v.video.videoId), { highWaterMark: 1024 * 1024 * 32 }), { type: 'opus' })
} catch (err) { } catch (err) {
if (playNext && playNext === true) { if (playNext && playNext === true) {
guild.queue.splice(1, 1) guild.queue.splice(1, 1)
@ -203,19 +200,14 @@ exports.play = async function (client, message, query, playNext, ignoreQueue) {
guild.queue.pop() guild.queue.pop()
} }
client.logger.error(err.stack) client.logger.error(err)
return message.channel.send(`<:error:466995152976871434> An error has occured: \n\`${err}\``) return message.channel.send(`<:error:466995152976871434> An error has occured! If this issue persists, please contact my developers with this:\n\`${err}\``)
// return message.channel.send('<:error:466995152976871434> YouTube have made changes to their site that break Woomy\'s music module. An announcement will be made in the development server when this issue is resolved.')
} }
guild.dispatcher.setVolume(0.25) guild.dispatcher.setVolume(0.25)
guild.channel.send('<:player:467216674622537748> Now playing: **' + v.video.title + '** `[' + exports.createTimestamp(v.video.lengthSeconds) + ']`') guild.channel.send('<:player:467216674622537748> Now playing: **' + v.video.title + '** `[' + exports.createTimestamp(v.video.lengthSeconds) + ']`')
// play next in queue on end // play next in queue on end
guild.dispatcher.on('error', (err) => {
console.error('[MUSIC ERROR] ' + String(err));
});
guild.dispatcher.once('finish', () => { guild.dispatcher.once('finish', () => {
guild.queue.shift() guild.queue.shift()
guild.playing = false guild.playing = false
@ -227,15 +219,13 @@ exports.play = async function (client, message, query, playNext, ignoreQueue) {
guild.playing = false guild.playing = false
guild.paused = false guild.paused = false
guild.skippers = [] guild.skippers = []
guild.fixers = []
guild.channel = null
connection.disconnect() connection.disconnect()
} }
}) })
} }
} else { } else {
return message.channel.send('failed to find the video!') return message.channel.channelsend('failed to find the video!')
} }
} }
@ -253,4 +243,4 @@ exports.skip = function (guild, reason) {
if (g.dispatcher) { if (g.dispatcher) {
g.dispatcher.end(reason) g.dispatcher.end(reason)
} }
} }

View file

@ -1,4 +1,4 @@
{ {
"number": "1.4.8", "number": "1.3.0",
"changelog": "**1.4 Changelog**\n> • Splatoon commands have been added! check current and upcoming maps and modes with `~splatoonmaps`, current and upcoming salmon run maps, weapons and reward gear with `~salmonrun` and see what gear is on offer in the splatnet shop with `~splatnet`!\n**Notes:**\n> • Music is still broken and likely will be until v2 is released. Fixing v1 would delay v2 a lot, sorry >.<" "changelog": "**1.3.0 Changelog:**\n> • Music module has been rewritten for better stability and lots more features\n> • Force disconnecting Woomy from a voice channel no longer breaks music\n> • Music should (hopefully) break less in general\n> • Existing music commands have been rewritten\n> • Added the following new commands: fixmusic, movehere, movesong, playnext, shuffle, songinfo, volume\n> • Updated ship command\n**Notes:**\n> • This will be the final major update to Woomy V1, as we are shifting our focus to Woomy V2, which is a complete rewrite."
} }