Compare commits
53 changed files with 1746 additions and 3436 deletions
7
.github/dependabot.yml
vendored
7
.github/dependabot.yml
vendored
|
|
@ -1,7 +0,0 @@
|
||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "npm" # See documentation for possible values
|
|
||||||
directory: "/" # Location of package manifests
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
|
|
||||||
5
.github/workflows/CI.yml
vendored
5
.github/workflows/CI.yml
vendored
|
|
@ -2,9 +2,6 @@ name: CI
|
||||||
|
|
||||||
on: [push]
|
on: [push]
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
CI:
|
CI:
|
||||||
runs-on: node
|
runs-on: node
|
||||||
|
|
@ -16,6 +13,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
node-version: 'latest'
|
node-version: 'latest'
|
||||||
- name: install dependencies
|
- name: install dependencies
|
||||||
run: npm ci
|
run: npm install
|
||||||
- name: run tests
|
- name: run tests
|
||||||
run: npm test
|
run: npm test
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
# discord_bot
|
# discord_bot
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
A modular discord bot written in javascript, using the [discord.js](https://discord.js.org) library.
|
A modular discord bot written in javascript, using the [discord.js](https://discord.js.org) library.
|
||||||
|
|
||||||
This is my second attempt at making a discord bot.
|
This is my second attempt at making a discord bot.
|
||||||
|
|
@ -27,9 +24,11 @@ You can also change the global prefix.
|
||||||
You should enter you discord user id, so you can use the admin commands.
|
You should enter you discord user id, so you can use the admin commands.
|
||||||
Every time you want to change something in this file, you have to restart the bot.
|
Every time you want to change something in this file, you have to restart the bot.
|
||||||
|
|
||||||
If the config is ever changed, you need to either delete it and repeat the steps above or take a look at the util/createInitialConfig.js file.
|
If the config is ever changed, you need to either delete it and repeat the steps above or take a look at the util/createInitialConfig.js file
|
||||||
|
|
||||||
|
Netload is a feature that enables the ability to upload .js files via discord to the bot.
|
||||||
|
If you want this feature, you have to enable it in ./data/config.json.
|
||||||
|
|
||||||
## Known issues
|
## Known issues
|
||||||
|
|
||||||
See [issues](https://github.com/SileNce5k/discord_bot/issues?q=is%3Aopen+is%3Aissue+label%3Abug)
|
None at the moment.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'exampleName', // Keep it to one word
|
name: 'exampleName', // Keep it to one word
|
||||||
description: 'example description',
|
description: 'example description',
|
||||||
execute({message}) {
|
execute({message}) { //parameters you can use for netload: message, args, client, prefix
|
||||||
//code
|
//code
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
const calculateReloaded = require("../../util/calculateReloaded.js");
|
const calculateReloaded = require("../../util/calculateReloaded.js");
|
||||||
|
const reloadNetModules = require("../../util/reloadNetModules.js");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'reload',
|
name: 'reload',
|
||||||
|
|
@ -8,6 +9,7 @@ module.exports = {
|
||||||
|
|
||||||
let reloadCommands = require("../../util/reloadCommands.js")
|
let reloadCommands = require("../../util/reloadCommands.js")
|
||||||
let beforeSize = client.commands.size;
|
let beforeSize = client.commands.size;
|
||||||
|
reloadNetModules(client)
|
||||||
reloadCommands(client)
|
reloadCommands(client)
|
||||||
let sendText = calculateReloaded(beforeSize, client)
|
let sendText = calculateReloaded(beforeSize, client)
|
||||||
message.channel.send(sendText)
|
message.channel.send(sendText)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
const savePresence = require("../../util/savePresence");
|
|
||||||
const setPresence = require("../../util/setPresence");
|
const setPresence = require("../../util/setPresence");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
@ -11,20 +10,12 @@ module.exports = {
|
||||||
,"Updates once a minute if custom variables are used."
|
,"Updates once a minute if custom variables are used."
|
||||||
,""
|
,""
|
||||||
,"Custom Variables:"
|
,"Custom Variables:"
|
||||||
,"${guilds},${prefix},${uptime},{members}"],
|
,"${guilds},${prefix},${uptime}"],
|
||||||
admin: true,
|
admin: true,
|
||||||
execute({message, client, args, prefix}) {
|
execute({message, client, args, globalPrefix}) {
|
||||||
let forceUpdate = false;
|
const savePresence = require("../../util/savePresence");
|
||||||
if(args.length > 1 && args[0] === "force") {
|
|
||||||
forceUpdate = true;
|
|
||||||
args.shift();
|
|
||||||
}
|
|
||||||
if(args.length < 1){
|
|
||||||
message.channel.send(`You need at least two arguments for this command, see \`${prefix}help setpresence\``)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let presenceType = args[0].toLocaleUpperCase();
|
let presenceType = args[0].toLocaleUpperCase();
|
||||||
let sendText = "Presence has been set.";
|
let sendText = "Updated presence";
|
||||||
|
|
||||||
switch (presenceType) {
|
switch (presenceType) {
|
||||||
case "PLAY":
|
case "PLAY":
|
||||||
|
|
@ -55,11 +46,8 @@ module.exports = {
|
||||||
const firstArg = args[0].length + 1;
|
const firstArg = args[0].length + 1;
|
||||||
let temp = args.join(" ");
|
let temp = args.join(" ");
|
||||||
let presenceText = temp.slice(firstArg, temp.length)
|
let presenceText = temp.slice(firstArg, temp.length)
|
||||||
|
setPresence({presenceText: presenceText,presenceType: presenceType, client: client, globalPrefix: globalPrefix});
|
||||||
savePresence(presenceType, presenceText, client);
|
savePresence(presenceType, presenceText, client);
|
||||||
if(forceUpdate)
|
|
||||||
setPresence({presenceText, presenceType, client})
|
|
||||||
else
|
|
||||||
sendText = `${sendText} It will update <t:${Math.floor((client.lastPresenceUpdate + 60000) / 1000)}:R>`
|
|
||||||
}
|
}
|
||||||
message.channel.send(sendText);
|
message.channel.send(sendText);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
const calculateReloaded = require("../../util/calculateReloaded");
|
const calculateReloaded = require("../../util/calculateReloaded");
|
||||||
const executeCommand = require("../../util/executeCommand");
|
|
||||||
const reloadCommands = require("../../util/reloadCommands");
|
const reloadCommands = require("../../util/reloadCommands");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
@ -28,12 +27,10 @@ module.exports = {
|
||||||
let commitCount = stdout.split(/\r\n|\r|\n/).length - 1
|
let commitCount = stdout.split(/\r\n|\r|\n/).length - 1
|
||||||
sendText = `${sendText}\n\nLatest commits (${commitCount}):\n${stdout}`
|
sendText = `${sendText}\n\nLatest commits (${commitCount}):\n${stdout}`
|
||||||
if(sendText.length >= 2000){
|
if(sendText.length >= 2000){
|
||||||
sendText = sendText.slice(1955)
|
sendText.slice(1955)
|
||||||
sendText = `${sendText}\n... Message is too long to show everything`
|
sendText = `${sendText}\n... Message is too long to show everything`
|
||||||
}
|
}
|
||||||
message.channel.send(sendText)
|
message.channel.send(sendText)
|
||||||
const githash = executeCommand(`git`, ["rev-parse", "--short", "HEAD"]);
|
|
||||||
client.githash = githash.error ? "N/A" : githash.output;
|
|
||||||
if (err) console.log(stderr)
|
if (err) console.log(stderr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
const sqlite3 = require('sqlite3').verbose();
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'whitelist',
|
|
||||||
description: 'Whitelist a command in a specific server, or for a user.',
|
|
||||||
admin: true,
|
|
||||||
async execute({message, args, prefix, client}) {
|
|
||||||
if(args.length < 3){
|
|
||||||
message.channel.send(`You need to supply the command and guild that you want to whitelist\n\`${prefix}whitelist <user|guild> <command> <user_id|guild_id>\``);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let option = args[0];
|
|
||||||
let command = args[1];
|
|
||||||
let guildOrUser = args[2];
|
|
||||||
|
|
||||||
if(option === "guild" || option === "server"){
|
|
||||||
if(guildOrUser === "this") guildOrUser = message.guild.id;
|
|
||||||
const whitelistedCommands = client.whitelist.guild.get(guildOrUser);
|
|
||||||
if(whitelistedCommands && whitelistedCommands.includes(command)){
|
|
||||||
message.channel.send("Command is already whitelisted in that server.")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO: First check if the bot has access to that guild before whitelisting.
|
|
||||||
const databasePath = 'data/database.db'
|
|
||||||
const db = new sqlite3.Database(databasePath)
|
|
||||||
let err = false;
|
|
||||||
await new Promise((resolve, reject)=>{
|
|
||||||
db.run(`INSERT INTO guild_whitelist (
|
|
||||||
guildId,
|
|
||||||
command,
|
|
||||||
dateAdded
|
|
||||||
) VALUES (?, ?, ?)`,
|
|
||||||
[
|
|
||||||
guildOrUser,
|
|
||||||
command,
|
|
||||||
new Date().getTime()
|
|
||||||
], function (error) {
|
|
||||||
if (error) {
|
|
||||||
console.error(error);
|
|
||||||
err = true;
|
|
||||||
resolve();
|
|
||||||
}else{
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
db.close();
|
|
||||||
if(!err){
|
|
||||||
if(whitelistedCommands){
|
|
||||||
whitelistedCommands.push(command);
|
|
||||||
client.whitelist.guild.set(guildOrUser, whitelistedCommands);
|
|
||||||
}else {
|
|
||||||
client.whitelist.guild.set(guildOrUser, command);
|
|
||||||
}
|
|
||||||
message.channel.send(`"${command}" has been whitelisted in that server.`)
|
|
||||||
|
|
||||||
} else message.channel.send("Could not whitelist the server with that command. Check the logs.")
|
|
||||||
return;
|
|
||||||
}else if (option === "user"){
|
|
||||||
const whitelistedCommands = client.whitelist.user.get(guildOrUser);
|
|
||||||
if(whitelistedCommands && whitelistedCommands.includes(command)){
|
|
||||||
message.channel.send("Command is already whitelisted for that user.")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const databasePath = 'data/database.db'
|
|
||||||
const db = new sqlite3.Database(databasePath)
|
|
||||||
let err = false;
|
|
||||||
await new Promise((resolve, reject)=>{
|
|
||||||
db.run(`INSERT INTO user_whitelist (
|
|
||||||
userId,
|
|
||||||
command,
|
|
||||||
dateAdded
|
|
||||||
) VALUES (?, ?, ?)`,
|
|
||||||
[
|
|
||||||
guildOrUser,
|
|
||||||
command,
|
|
||||||
new Date().getTime()
|
|
||||||
], function (error) {
|
|
||||||
if (error) {
|
|
||||||
console.error(error);
|
|
||||||
err = true;
|
|
||||||
resolve();
|
|
||||||
}else{
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
db.close();
|
|
||||||
if(!err){
|
|
||||||
if(whitelistedCommands){
|
|
||||||
whitelistedCommands.push(command);
|
|
||||||
client.whitelist.user.set(guildOrUser, whitelistedCommands);
|
|
||||||
}else {
|
|
||||||
client.whitelist.user.set(guildOrUser, command);
|
|
||||||
}
|
|
||||||
message.channel.send(`"${command}" has been whitelisted for ${guildOrUser}.`)
|
|
||||||
|
|
||||||
} else message.channel.send("Could not whitelist the server with that command. Check the logs.")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: Add ability to remove server from whitelist.
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
const {EmbedBuilder} = require('discord.js');
|
const {EmbedBuilder} = require('discord.js');
|
||||||
const getCreationDate = require('../../util/getCreationDate');
|
const getCreationDate = require('../../util/getCreationDate');
|
||||||
const getGuildInfo = require('../../util/getGuildInfo');
|
const getGuildCount = require('../../util/getGuildCount');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -8,28 +8,15 @@ module.exports = {
|
||||||
name: 'botinfo',
|
name: 'botinfo',
|
||||||
description: 'Shows information about the bot',
|
description: 'Shows information about the bot',
|
||||||
execute({message, client, prefix}) {
|
execute({message, client, prefix}) {
|
||||||
let guildInfo = getGuildInfo(client)
|
let guildCount = getGuildCount(client)
|
||||||
let descriptionArr = [`Name: ${client.user.username}`,
|
|
||||||
`Prefix: ${prefix}`,
|
|
||||||
`Total Servers: ${guildInfo.guildCount}`,
|
|
||||||
`Total Members: ${guildInfo.totalMembers} (${guildInfo.uniqueMemberCount} unique)`,
|
|
||||||
`Total Commands: ${client.commands.size}`,
|
|
||||||
`Creation Date: ${getCreationDate(client)}`,
|
|
||||||
`Source: [Click Here](https://github.com/SileNce5k/discord_bot)`,
|
|
||||||
`Current Version: ${client.githash}`
|
|
||||||
]
|
|
||||||
|
|
||||||
let description = "";
|
|
||||||
descriptionArr.forEach(desc => {
|
|
||||||
description += `${desc}\n`;
|
|
||||||
})
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setColor(15780145)
|
.setColor(15780145)
|
||||||
.setTitle("Information about bot")
|
.setTitle("Information about bot")
|
||||||
.setTimestamp()
|
.setTimestamp()
|
||||||
.setAuthor({name: client.user.username, iconURL: client.user.avatarURL({ format: 'png', dynamic: true, size: 2048 })})
|
.setAuthor({name: client.user.username, iconURL: client.user.avatarURL({ format: 'png', dynamic: true, size: 2048 })})
|
||||||
.setDescription(description)
|
.addFields({
|
||||||
|
name: "General info", value: `Name: ${client.user.username}\nPrefix: ${prefix}\nTotal Servers: ${guildCount}\nTotal Commands: ${client.commands.size}\nCreation Date: ${getCreationDate(client)}\nSource: [Click Here](https://github.com/SileNce5k/discord_bot)`,
|
||||||
|
},)
|
||||||
|
|
||||||
message.channel.send({embeds :[embed]})
|
message.channel.send({embeds :[embed]})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ module.exports = {
|
||||||
description: 'Returns guild names',
|
description: 'Returns guild names',
|
||||||
admin: true,
|
admin: true,
|
||||||
execute({message, client}) {
|
execute({message, client}) {
|
||||||
let guildNames = client.guilds.cache
|
let guildNames = "";
|
||||||
.sort((a, b) => b.memberCount - a.memberCount)
|
client.guilds.cache.each(guild => {
|
||||||
.map(guild => `${guild.name} (${guild.memberCount} members)`)
|
guildNames = guildNames + guild.name + "\n";
|
||||||
.join("\n");
|
});
|
||||||
message.channel.send(guildNames)
|
message.channel.send(guildNames)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -8,19 +8,26 @@ module.exports = {
|
||||||
description: 'List all available commands.',
|
description: 'List all available commands.',
|
||||||
moreHelp: ["Examples:","`<prefix>help [optional_page]` will return help with a small description for each command",
|
moreHelp: ["Examples:","`<prefix>help [optional_page]` will return help with a small description for each command",
|
||||||
"`<prefix>help <another_command>` will return help with a more descriptive description",
|
"`<prefix>help <another_command>` will return help with a more descriptive description",
|
||||||
"The descriptive description isn't available on all commands"
|
"The descriptive description isn't available on all commands",
|
||||||
|
"`<prefix>help netmodules` to display help for netmodules"
|
||||||
],
|
],
|
||||||
execute({ message, args, prefix, client }) {
|
execute({ message, args, prefix, client }) {
|
||||||
let commands = ""
|
let commands = ""
|
||||||
let commandFiles = getSubdirFiles('commands/')
|
let commandFiles = getSubdirFiles('commands/')
|
||||||
|
let x = false;
|
||||||
let fieldName = `Page [[page]]/${Math.round(client.commands.size / 10)}`;
|
let fieldName = `Page [[page]]/${Math.round(client.commands.size / 10)}`;
|
||||||
let iteration = 0;
|
let iteration = 0;
|
||||||
let num_in_args = false;
|
let num_in_args = false;
|
||||||
let added_commands = 0;
|
let added_commands = 0;
|
||||||
let page = -1;
|
let page = -1;
|
||||||
|
if (args[0] == "netmodules") {
|
||||||
|
commandFiles = fs.readdirSync('../../netload').filter(file => file.endsWith('.js'));
|
||||||
|
if (commandFiles.length == 0) {
|
||||||
|
message.channel.send("There are no netmodules currently loaded.")
|
||||||
|
x = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}else if(!isNaN(parseInt(args[0])) && parseInt(args[0])){
|
||||||
if(!isNaN(parseInt(args[0])) && parseInt(args[0])){
|
|
||||||
num_in_args = true;
|
num_in_args = true;
|
||||||
iteration = ( parseInt(args[0]) - 1) * 10;
|
iteration = ( parseInt(args[0]) - 1) * 10;
|
||||||
page = Math.round(parseInt(args[0]))
|
page = Math.round(parseInt(args[0]))
|
||||||
|
|
@ -31,6 +38,7 @@ module.exports = {
|
||||||
fieldName = fieldName.replace("[[page]]", page);
|
fieldName = fieldName.replace("[[page]]", page);
|
||||||
const max_commands = iteration + 10;
|
const max_commands = iteration + 10;
|
||||||
|
|
||||||
|
if (x) return;
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setColor(15780145)
|
.setColor(15780145)
|
||||||
|
|
@ -58,7 +66,6 @@ module.exports = {
|
||||||
start++;
|
start++;
|
||||||
}
|
}
|
||||||
}else if(args[0] === command.name){
|
}else if(args[0] === command.name){
|
||||||
fieldName = "Description";
|
|
||||||
commands = commands + `${prefix}${command.name}\n`
|
commands = commands + `${prefix}${command.name}\n`
|
||||||
embed.setTitle(command.name.charAt(0).toUpperCase() + command.name.slice(1))
|
embed.setTitle(command.name.charAt(0).toUpperCase() + command.name.slice(1))
|
||||||
if(command.moreHelp){
|
if(command.moreHelp){
|
||||||
|
|
@ -66,6 +73,7 @@ module.exports = {
|
||||||
commands = commands + `${element}\n`
|
commands = commands + `${element}\n`
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
fieldName = "Description";
|
||||||
commands = commands + `${command.description}`;
|
commands = commands + `${command.description}`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
// Code is taken from https://github.com/stphnduvall/mcstatus/blob/master/src/index.ts
|
|
||||||
// and converted to pure js.
|
|
||||||
|
|
||||||
const net = require('net')
|
|
||||||
const { EmbedBuilder } = require('discord.js');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'mc',
|
|
||||||
description: 'get minecraft server information',
|
|
||||||
hidden: true,
|
|
||||||
needsWhitelist: true,
|
|
||||||
async execute({ message, args }) {
|
|
||||||
let host = "";
|
|
||||||
let port = 25565;
|
|
||||||
if (args[0]) host = args[0];
|
|
||||||
|
|
||||||
if (host.includes(":")) {
|
|
||||||
port = host.replace(/.+(?:\:)/g, "");
|
|
||||||
host = host.match(/.+(?:\:)/g, "")[0].replace(":", "");
|
|
||||||
}
|
|
||||||
if(host === "") return message.channel.send("No host provided")
|
|
||||||
let info = await getMinecraftServerInfo(host, port);
|
|
||||||
if (info) {
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
embed.setColor("#ee7939")
|
|
||||||
embed.setTimestamp()
|
|
||||||
embed.addFields(
|
|
||||||
{ name: "ping", value: info.ping.toString(), inline: false },
|
|
||||||
{ name: "Player Count", value: info.playercount.toString(), inline: false },
|
|
||||||
{ name: "Max Players", value: info.maxPlayers.toString(), inline: false },
|
|
||||||
{ name: "MOTD", value: info.motd, inline: false },
|
|
||||||
)
|
|
||||||
|
|
||||||
message.channel.send({ embeds: [embed] });
|
|
||||||
} else {
|
|
||||||
message.channel.send("Something went wrong\nThe minecraft server is likely not reachable from the discord bot")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function getMinecraftServerInfo(host, port = 25565) {
|
|
||||||
let serverInfo = {
|
|
||||||
ping: undefined,
|
|
||||||
maxPlayers: undefined,
|
|
||||||
version: undefined,
|
|
||||||
playercount: undefined,
|
|
||||||
motd: undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
let startTime = new Date();
|
|
||||||
let data;
|
|
||||||
let ping;
|
|
||||||
serverInfo = await new Promise((resolve) => {
|
|
||||||
const client = net.connect({ host, port }, () => {
|
|
||||||
ping = Math.round(new Date().getMilliseconds() - startTime.getMilliseconds());
|
|
||||||
|
|
||||||
let buff = Buffer.from([0xFE, 0x01]);
|
|
||||||
client.write(buff);
|
|
||||||
|
|
||||||
})
|
|
||||||
let error = false;
|
|
||||||
client.on('data', (d) => {
|
|
||||||
data = d.toString()
|
|
||||||
client.destroy();
|
|
||||||
|
|
||||||
})
|
|
||||||
client.once('error', (error) => {
|
|
||||||
console.error(error)
|
|
||||||
error = true;
|
|
||||||
})
|
|
||||||
client.once('connectionAttemptFailed', (ip) => {
|
|
||||||
console.error("in attempt failed")
|
|
||||||
error = true;
|
|
||||||
})
|
|
||||||
|
|
||||||
client.once('connectionAttemptTimeout', (ip) => {
|
|
||||||
console.error("in attempt timeout")
|
|
||||||
error = true;
|
|
||||||
})
|
|
||||||
client.on('close', () => {
|
|
||||||
if (!error) {
|
|
||||||
let _serverInfo = data?.split('\x00\x00\x00');
|
|
||||||
|
|
||||||
if (!_serverInfo) {
|
|
||||||
console.log("Something went wrong.")
|
|
||||||
resolve(serverInfo)
|
|
||||||
}
|
|
||||||
serverInfo.version = _serverInfo[2].replace(/\u0000/g, '')
|
|
||||||
serverInfo.motd = _serverInfo[3].replace(/\u0000/g, '')
|
|
||||||
serverInfo.playercount = Number(_serverInfo[4].replace(/\u0000/g, ''))
|
|
||||||
serverInfo.maxPlayers = Number(_serverInfo[5].replace(/\u0000/g, ''))
|
|
||||||
serverInfo.ping = Number(ping)
|
|
||||||
resolve(serverInfo)
|
|
||||||
} else {
|
|
||||||
resolve(0)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return serverInfo
|
|
||||||
}
|
|
||||||
|
|
@ -16,9 +16,9 @@ module.exports = {
|
||||||
let user = message.guild.members.cache.get(info);
|
let user = message.guild.members.cache.get(info);
|
||||||
let guildPfp = user.avatarURL({format: 'png', dynamic: true, size: 4096});
|
let guildPfp = user.avatarURL({format: 'png', dynamic: true, size: 4096});
|
||||||
let globalPfp = user.user.avatarURL({format: 'png', dynamic: true, size: 4096});
|
let globalPfp = user.user.avatarURL({format: 'png', dynamic: true, size: 4096});
|
||||||
let sendText = `${globalPfp}`;
|
let sendText = `Global pfp:\n${globalPfp}`;
|
||||||
if(guildPfp != null){
|
if(guildPfp != null){
|
||||||
sendText = `Global pfp${sendText}\nGuild pfp:\n${guildPfp}`;
|
sendText = `${sendText}\nGuild pfp:\n${guildPfp}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
message.channel.send(sendText)
|
message.channel.send(sendText)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ module.exports = {
|
||||||
{name: "Server Name", value: message.guild.name, inline: false},
|
{name: "Server Name", value: message.guild.name, inline: false},
|
||||||
{name: "Created", value: convertDateToISOString(message.guild.createdAt), inline: false},
|
{name: "Created", value: convertDateToISOString(message.guild.createdAt), inline: false},
|
||||||
{name: "Members", value: message.guild.memberCount.toString(), inline: false},
|
{name: "Members", value: message.guild.memberCount.toString(), inline: false},
|
||||||
{name: "Channels", value: message.guild.channels.channelCountWithoutThreads.toString(), inline: false},
|
|
||||||
|
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const parseMS = require('../../util/parseMS')
|
const parseMS = require('parse-ms')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'uptime',
|
name: 'uptime',
|
||||||
|
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
const path = require('path');
|
|
||||||
const fs = require('fs')
|
|
||||||
|
|
||||||
const executeCommand = require('../../util/executeCommand');
|
|
||||||
module.exports = {
|
|
||||||
name: 'dl',
|
|
||||||
description: 'Download a video',
|
|
||||||
moreHelp: [
|
|
||||||
"Usage: <prefix>dl <url>"
|
|
||||||
],
|
|
||||||
async execute({message, args}) {
|
|
||||||
const downloadsDir = path.resolve(process.cwd(), 'data', 'downloads', Date.now().toString());
|
|
||||||
const cookieFilepath = path.resolve(process.cwd(), 'data', 'cookies.txt')
|
|
||||||
if(!fs.existsSync(cookieFilepath)) {
|
|
||||||
message.channel.send("Some dependencies are needed for the command to work properly. Please let the bot's owner know.")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fs.mkdirSync(downloadsDir, {recursive: true});
|
|
||||||
|
|
||||||
let url;
|
|
||||||
|
|
||||||
if(args.length > 0){
|
|
||||||
if(args[0].charAt(0) === '<' && args[0].charAt(args[0].length - 1) === '>'){
|
|
||||||
args[0] = args[0].slice(1, args[0].length - 1)
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
url = new URL(args[0]);
|
|
||||||
url = url.href;
|
|
||||||
} catch (error) {
|
|
||||||
this.cleanUp(downloadsDir);
|
|
||||||
message.channel.send("Could not parse the provided argument as a URL.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.cleanUp(downloadsDir);
|
|
||||||
return message.channel.send("You have to provide a URL in an argument.")
|
|
||||||
}
|
|
||||||
|
|
||||||
const originalMessage = await message.channel.send("Downloading video...")
|
|
||||||
|
|
||||||
if(executeCommand("yt-dlp", [url, "-P", downloadsDir, "--cookies", cookieFilepath]).error){
|
|
||||||
originalMessage.edit("An error occurred when downloading the video.");
|
|
||||||
this.cleanUp(downloadsDir);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let files = fs.readdirSync(downloadsDir);
|
|
||||||
if(files.length < 1) {
|
|
||||||
this.cleanUp(downloadsDir);
|
|
||||||
originalMessage.edit("Something went wrong when downloading the video.")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const filename = files[0];
|
|
||||||
|
|
||||||
await originalMessage.edit({
|
|
||||||
content: null,
|
|
||||||
files: [{
|
|
||||||
attachment: path.resolve(downloadsDir, filename)
|
|
||||||
}]})
|
|
||||||
|
|
||||||
this.cleanUp(downloadsDir);
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
cleanUp(downloadsDir){
|
|
||||||
fs.rmSync(downloadsDir, {force: true, recursive: true});
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -4,12 +4,6 @@ const getCurrentCover = require("../../util/lastfm/getCurrentCover");
|
||||||
const getTopTracks = require("../../util/lastfm/getTopTracks");
|
const getTopTracks = require("../../util/lastfm/getTopTracks");
|
||||||
const help = require("../info/help");
|
const help = require("../info/help");
|
||||||
const parseMention = require("../../util/parseMention");
|
const parseMention = require("../../util/parseMention");
|
||||||
const roast = require("../../util/lastfm/roast");
|
|
||||||
const getTopArtists = require("../../util/lastfm/getTopArtists");
|
|
||||||
const getTopAlbums = require("../../util/lastfm/getTopAlbums");
|
|
||||||
const {EmbedBuilder} = require('discord.js');
|
|
||||||
const getNickname = require('../../util/getNickname');
|
|
||||||
const isWhitelisted = require("../../util/isWhitelisted");
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'fm',
|
name: 'fm',
|
||||||
description: 'Last fm commands. See `<prefix>help fm` for more info.',
|
description: 'Last fm commands. See `<prefix>help fm` for more info.',
|
||||||
|
|
@ -17,11 +11,8 @@ module.exports = {
|
||||||
"They behave the same (for example: `<prefix>fmtt` and `<prefix>fm tt`)",
|
"They behave the same (for example: `<prefix>fmtt` and `<prefix>fm tt`)",
|
||||||
"Set username: `<prefix>fmset <lastfm_username>`",
|
"Set username: `<prefix>fmset <lastfm_username>`",
|
||||||
"Get current scrobble: `<prefix>fm`",
|
"Get current scrobble: `<prefix>fm`",
|
||||||
"Get top artists `<prefix>fmas`",
|
|
||||||
"Get top albums: `<prefix>fmabl`",
|
|
||||||
"Get top tracks: `<prefix>fmtt`",
|
"Get top tracks: `<prefix>fmtt`",
|
||||||
"Get album cover for current scrobble: `<prefix>fmcover`",
|
"Get album cover for current scrobble: `<prefix>fmcover`",
|
||||||
"Get a roast from an LLM using your top artists and albums: `<prefix>fmroast`"
|
|
||||||
],
|
],
|
||||||
async execute({ message, args, prefix, client }) {
|
async execute({ message, args, prefix, client }) {
|
||||||
let sendText = {text: "Something went wrong.", embed: null};
|
let sendText = {text: "Something went wrong.", embed: null};
|
||||||
|
|
@ -37,46 +28,9 @@ module.exports = {
|
||||||
args.shift();
|
args.shift();
|
||||||
sendText = await getTopTracks(message.author.id, args, message.guild);
|
sendText = await getTopTracks(message.author.id, args, message.guild);
|
||||||
break;
|
break;
|
||||||
case "topalbums":
|
|
||||||
case "topalbum":
|
|
||||||
case "abl":
|
|
||||||
args.shift();
|
|
||||||
sendText = await getTopAlbums(message.author.id, args, message.guild)
|
|
||||||
break;
|
|
||||||
case "topartists":
|
|
||||||
case "topartist":
|
|
||||||
case "ta":
|
|
||||||
case "as":
|
|
||||||
args.shift();
|
|
||||||
sendText = await getTopArtists(message.author.id, args, message.guild);
|
|
||||||
break;
|
|
||||||
case "cover":
|
case "cover":
|
||||||
sendText = await getCurrentCover(message.author.id, message.guild);
|
sendText = await getCurrentCover(message.author.id, message.guild);
|
||||||
break;
|
break;
|
||||||
case "roast":
|
|
||||||
const commandName = "fmroast"
|
|
||||||
if(!isWhitelisted.isWhitelisted(commandName, client.whitelist, message.guild.id, message.author.id, isWhitelisted.whitelistTypes.EITHER)) {
|
|
||||||
message.channel.send("fmroast has not been whitelisted for you or this server.")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let topArtists = await getTopArtists(message.author.id, ["yearly"], message.guild, true);
|
|
||||||
let topAlbums = await getTopAlbums(message.author.id, ["yearly"], message.guild, true);
|
|
||||||
message.channel.sendTyping();
|
|
||||||
let result = await roast(topArtists, topAlbums);
|
|
||||||
|
|
||||||
let parse = parseMention(message.author.id, message.guild)
|
|
||||||
let user = message.guild.members.cache.get(parse);
|
|
||||||
let nickname = getNickname(user, message.guild)
|
|
||||||
if (nickname == null) {
|
|
||||||
nickname = user.user.username;
|
|
||||||
}
|
|
||||||
const possesive = nickname.at(nickname.length - 1) === "s" ? "'" : "'s"
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setAuthor({name: `${nickname}${possesive} AI roast`, iconURL: user.user.avatarURL({ dynamic: true, size: 4096 })})
|
|
||||||
.setColor(15780145)
|
|
||||||
.setDescription(result);
|
|
||||||
sendText.embed = embed;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
sendText.text = `${args[0]} is not a valid subcommand.\nSee \`${prefix}help fm\` for more info.`;
|
sendText.text = `${args[0]} is not a valid subcommand.\nSee \`${prefix}help fm\` for more info.`;
|
||||||
break;
|
break;
|
||||||
|
|
@ -87,13 +41,11 @@ module.exports = {
|
||||||
if(sendText.embed != null){
|
if(sendText.embed != null){
|
||||||
let parse = parseMention(message.author.id, message.guild)
|
let parse = parseMention(message.author.id, message.guild)
|
||||||
let user = message.guild.members.cache.get(parse);
|
let user = message.guild.members.cache.get(parse);
|
||||||
if(!sendText.embed.data.color){
|
let roleColor = 15788778;
|
||||||
let roleColor = 15788778;
|
if (user.roles.color) {
|
||||||
if (user.roles.color) {
|
roleColor = user.roles.color.color;
|
||||||
roleColor = user.roles.color.color;
|
|
||||||
}
|
|
||||||
sendText.embed.setColor(roleColor);
|
|
||||||
}
|
}
|
||||||
|
sendText.embed.setColor(roleColor);
|
||||||
message.channel.send({embeds :[sendText.embed]})
|
message.channel.send({embeds :[sendText.embed]})
|
||||||
}else{
|
}else{
|
||||||
message.channel.send(sendText.text.replaceAll("<prefix>", prefix));
|
message.channel.send(sendText.text.replaceAll("<prefix>", prefix));
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'ig',
|
|
||||||
description: 'Replaces Instagram links with kkinstagram and deletes the original message',
|
|
||||||
execute({message, args}) {
|
|
||||||
const noUrlErr = "You need to provide an Instagram link to use this command."
|
|
||||||
if(args.length < 1) {
|
|
||||||
message.channel.send(noUrlErr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let replacedLink = "";
|
|
||||||
const regex = /(?<=\/)(instagram)\.com/g
|
|
||||||
if(args[0].startsWith("https://") || args[0].startsWith("http://")){
|
|
||||||
replacedLink = args[0].replace(regex, "kkinstagram.com");
|
|
||||||
}
|
|
||||||
if(replacedLink.length === 0 || args[0] === replacedLink){
|
|
||||||
message.channel.send(noUrlErr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
message.channel.send(replacedLink);
|
|
||||||
try{
|
|
||||||
message.delete()
|
|
||||||
}catch(err){
|
|
||||||
console.error(`${this.name}: An error occurred while trying to delete the original message.`)
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
77
commands/misc/netload.js
Normal file
77
commands/misc/netload.js
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
const https = require('https');
|
||||||
|
const fs = require('fs')
|
||||||
|
const netloadDir = "../../netload"
|
||||||
|
const validUrl = require('valid-url');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: 'netload',
|
||||||
|
description: 'Load a module from the internet',
|
||||||
|
moreHelp: ["Examples:",
|
||||||
|
"Either provide a link to the module, or upload it",
|
||||||
|
"To get an example of how your module should look like, do:",
|
||||||
|
"<prefix>netload example",
|
||||||
|
"You have to be whitelisted to use this command.",
|
||||||
|
"The bot operator also has to have this enabled in the config."
|
||||||
|
],
|
||||||
|
execute({ message, args, prefix, client, owners }) {
|
||||||
|
if (!fs.existsSync('./data/netmoduleWhitelist.json')) {
|
||||||
|
fs.writeFileSync('./data/netmoduleWhitelist.json', "[]")
|
||||||
|
}
|
||||||
|
let json = fs.readFileSync('./data/netmoduleWhitelist.json', 'utf8');
|
||||||
|
let whitelist = JSON.parse(json)
|
||||||
|
if (json.indexOf(message.author.id.toString()) == -1) {
|
||||||
|
message.channel.send("You do not have permissions to use this command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args[0] == "whitelist" && owners.indexOf(message.author.id.toString()) >= 0) {
|
||||||
|
whitelist.push(args[1])
|
||||||
|
fs.writeFileSync("./data/netmoduleWhitelist.json", JSON.stringify(whitelist, null, 4))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!args[0] && message.attachments.size == 0) {
|
||||||
|
message.channel.send(`You have to either specify a url or upload a file via the command.\nTo get an example file, execute \`${prefix}netload example\``)
|
||||||
|
return;
|
||||||
|
|
||||||
|
} if (args[0] == "example") {
|
||||||
|
|
||||||
|
let example = fs.readFileSync('commands/.example')
|
||||||
|
|
||||||
|
message.channel.send(`\`\`\`js\n${example}\n\`\`\``)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let url, fileName;
|
||||||
|
if (message.attachments.size > 0) {
|
||||||
|
url = message.attachments.first().url
|
||||||
|
fileName = message.attachments.first().name
|
||||||
|
} else {
|
||||||
|
url = args[0]
|
||||||
|
if (!validUrl.isUri(url)) {
|
||||||
|
message.channel.send("This does not look like a valid url")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fileName = args[0].split("/")[args[0].split("/").length - 1]
|
||||||
|
}
|
||||||
|
if (fs.existsSync(`${netloadDir}/${fileName}`)) {
|
||||||
|
message.channel.send(`A module with this filename(${fileName}) already exists.`)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
https.get(url, (res) => {
|
||||||
|
res.on('data', (d) => {
|
||||||
|
fs.writeFileSync(`${netloadDir}/${fileName}`, d);
|
||||||
|
reloadNetModules(client);
|
||||||
|
});
|
||||||
|
|
||||||
|
}).on('error', (e) => {
|
||||||
|
message.channel.send("Error download file.");
|
||||||
|
console.log(e)
|
||||||
|
});
|
||||||
|
|
||||||
|
let reloadNetModules = require('../util/reloadNetModules');
|
||||||
|
reloadNetModules(client)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -1,11 +1,7 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'ping',
|
name: 'ping',
|
||||||
description: 'Just ping.',
|
description: 'Just ping.',
|
||||||
async execute({message, client}) {
|
execute({message, client}) {
|
||||||
let apiLatency = client.ws.ping;
|
message.channel.send(`Pong.\n${client.ws.ping}ms`)
|
||||||
const time = process.hrtime.bigint();
|
|
||||||
let initialMessage = await message.channel.send(`Pong.`)
|
|
||||||
const diff = Number(process.hrtime.bigint() - time) * 1e-6;
|
|
||||||
initialMessage.edit(`Pong.\nAPI latency: ${apiLatency} ms\nMessage latency: ${diff.toFixed(0)} ms.`);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue