diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index be6c62d..ee720fa 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -16,6 +16,6 @@ jobs: with: node-version: 'latest' - name: install dependencies - run: npm ci + run: npm install - name: run tests - run: npm test + run: npm test \ No newline at end of file diff --git a/commands/admin/setPresence.js b/commands/admin/setPresence.js index 5dbfd51..bd6fe5f 100644 --- a/commands/admin/setPresence.js +++ b/commands/admin/setPresence.js @@ -1,4 +1,3 @@ -const savePresence = require("../../util/savePresence"); const setPresence = require("../../util/setPresence"); module.exports = { @@ -11,20 +10,12 @@ module.exports = { ,"Updates once a minute if custom variables are used." ,"" ,"Custom Variables:" - ,"${guilds},${prefix},${uptime},{members}"], + ,"${guilds},${prefix},${uptime}"], admin: true, - execute({message, client, args, prefix}) { - let forceUpdate = false; - 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; - } + execute({message, client, args, globalPrefix}) { + const savePresence = require("../../util/savePresence"); let presenceType = args[0].toLocaleUpperCase(); - let sendText = "Presence has been set."; + let sendText = "Updated presence"; switch (presenceType) { case "PLAY": @@ -55,11 +46,8 @@ module.exports = { const firstArg = args[0].length + 1; let temp = args.join(" "); let presenceText = temp.slice(firstArg, temp.length) + setPresence({presenceText: presenceText,presenceType: presenceType, client: client, globalPrefix: globalPrefix}); savePresence(presenceType, presenceText, client); - if(forceUpdate) - setPresence({presenceText, presenceType, client}) - else - sendText = `${sendText} It will update ` } message.channel.send(sendText); diff --git a/commands/admin/update.js b/commands/admin/update.js index 7c9a75f..7de9db0 100644 --- a/commands/admin/update.js +++ b/commands/admin/update.js @@ -1,5 +1,4 @@ const calculateReloaded = require("../../util/calculateReloaded"); -const executeCommand = require("../../util/executeCommand"); const reloadCommands = require("../../util/reloadCommands"); module.exports = { @@ -28,12 +27,10 @@ module.exports = { let commitCount = stdout.split(/\r\n|\r|\n/).length - 1 sendText = `${sendText}\n\nLatest commits (${commitCount}):\n${stdout}` if(sendText.length >= 2000){ - sendText = sendText.slice(1955) + sendText.slice(1955) sendText = `${sendText}\n... Message is too long to show everything` } 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) }) } diff --git a/commands/info/botinfo.js b/commands/info/botinfo.js index b806459..a746075 100644 --- a/commands/info/botinfo.js +++ b/commands/info/botinfo.js @@ -12,11 +12,10 @@ module.exports = { let descriptionArr = [`Name: ${client.user.username}`, `Prefix: ${prefix}`, `Total Servers: ${guildInfo.guildCount}`, - `Total Members: ${guildInfo.totalMembers} (${guildInfo.uniqueMemberCount} unique)`, + `Total Members: ${guildInfo.totalMembers}`, `Total Commands: ${client.commands.size}`, `Creation Date: ${getCreationDate(client)}`, - `Source: [Click Here](https://github.com/SileNce5k/discord_bot)`, - `Current Version: ${client.githash}` + `Source [Click Here](https://github.com/SileNce5k/discord_bot)` ] let description = ""; diff --git a/commands/info/guilds.js b/commands/info/guilds.js index 480fdda..bed7e5b 100644 --- a/commands/info/guilds.js +++ b/commands/info/guilds.js @@ -3,10 +3,10 @@ module.exports = { description: 'Returns guild names', admin: true, execute({message, client}) { - let guildNames = client.guilds.cache - .sort((a, b) => b.memberCount - a.memberCount) - .map(guild => `${guild.name} (${guild.memberCount} members)`) - .join("\n"); + let guildNames = ""; + client.guilds.cache.each(guild => { + guildNames = `${guildNames}${guild.name} (${guild.memberCount} members)\n` + }); message.channel.send(guildNames) } }; \ No newline at end of file diff --git a/commands/info/mc.js b/commands/info/mc.js deleted file mode 100644 index dac751b..0000000 --- a/commands/info/mc.js +++ /dev/null @@ -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 -} diff --git a/commands/info/pfp.js b/commands/info/pfp.js index dd76507..68a4640 100644 --- a/commands/info/pfp.js +++ b/commands/info/pfp.js @@ -16,9 +16,9 @@ module.exports = { let user = message.guild.members.cache.get(info); let guildPfp = 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){ - sendText = `Global pfp${sendText}\nGuild pfp:\n${guildPfp}`; + sendText = `${sendText}\nGuild pfp:\n${guildPfp}`; } message.channel.send(sendText) diff --git a/commands/info/serverinfo.js b/commands/info/serverinfo.js index 1f329de..1526c32 100644 --- a/commands/info/serverinfo.js +++ b/commands/info/serverinfo.js @@ -15,7 +15,6 @@ module.exports = { {name: "Server Name", value: message.guild.name, inline: false}, {name: "Created", value: convertDateToISOString(message.guild.createdAt), inline: false}, {name: "Members", value: message.guild.memberCount.toString(), inline: false}, - {name: "Channels", value: message.guild.channels.channelCountWithoutThreads.toString(), inline: false}, ]) diff --git a/commands/misc/dl.js b/commands/misc/dl.js deleted file mode 100644 index 13d95df..0000000 --- a/commands/misc/dl.js +++ /dev/null @@ -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: dl " - ], - 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}); - }, - -} diff --git a/commands/misc/fm.js b/commands/misc/fm.js index e259f4c..8d07401 100644 --- a/commands/misc/fm.js +++ b/commands/misc/fm.js @@ -17,8 +17,6 @@ module.exports = { "They behave the same (for example: `fmtt` and `fm tt`)", "Set username: `fmset `", "Get current scrobble: `fm`", - "Get top artists `fmas`", - "Get top albums: `fmabl`", "Get top tracks: `fmtt`", "Get album cover for current scrobble: `fmcover`", "Get a roast from an LLM using your top artists and albums: `fmroast`" @@ -37,19 +35,6 @@ module.exports = { args.shift(); sendText = await getTopTracks(message.author.id, args, message.guild); 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": sendText = await getCurrentCover(message.author.id, message.guild); break; @@ -87,13 +72,11 @@ module.exports = { if(sendText.embed != null){ let parse = parseMention(message.author.id, message.guild) let user = message.guild.members.cache.get(parse); - if(!sendText.embed.data.color){ - let roleColor = 15788778; - if (user.roles.color) { - roleColor = user.roles.color.color; - } - sendText.embed.setColor(roleColor); + let roleColor = 15788778; + if (user.roles.color) { + roleColor = user.roles.color.color; } + sendText.embed.setColor(roleColor); message.channel.send({embeds :[sendText.embed]}) }else{ message.channel.send(sendText.text.replaceAll("", prefix)); diff --git a/commands/misc/ig.js b/commands/misc/ig.js deleted file mode 100644 index 21268b7..0000000 --- a/commands/misc/ig.js +++ /dev/null @@ -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); - } - } -}; \ No newline at end of file diff --git a/commands/misc/prefix.js b/commands/misc/prefix.js index 954c834..19ec7d1 100644 --- a/commands/misc/prefix.js +++ b/commands/misc/prefix.js @@ -1,11 +1,10 @@ const setServerPrefix = require("../../util/setServerPrefix"); -const { PermissionsBitField } = require('discord.js'); module.exports = { name: 'prefix', description: 'Change the prefix of the bot in this server.', execute({ message, client, args, prefix }) { - if (!message.member.permissions.has(PermissionsBitField.Flags.ManageGuild)) { + if (!message.member.permissions.has('MANAGE_GUILD')) { message.channel.send("You do not have sufficient permissions(MANAGE_GUILD) to change the prefix of this server.") return; } diff --git a/commands/misc/say.js b/commands/misc/say.js index 2995f6a..e8ca4e6 100644 --- a/commands/misc/say.js +++ b/commands/misc/say.js @@ -1,7 +1,6 @@ module.exports = { name: 'say', description: 'Repeats arguments', - admin: true, execute({message, args}) { if(args.length == 0) diff --git a/commands/misc/tdoss.js b/commands/misc/tdoss.js index f5430fe..6738dfa 100644 --- a/commands/misc/tdoss.js +++ b/commands/misc/tdoss.js @@ -3,7 +3,7 @@ const fs = require('fs'); const path = require('path'); const { writeFile } = require('node:fs/promises') const { Readable } = require('node:stream') -const executeCommand = require('../../util/executeCommand'); + module.exports = { name: 'tdoss', @@ -60,8 +60,8 @@ module.exports = { } - const commandArgs = [tdossTemplate, "(", `${directory}/input.png`, "-resize", "800x800^", "-gravity", "center", "-extent", "1000x1000", ")", "-compose", "dst-over", "-composite", `${directory}/tdoss_result.png`] - if (executeCommand("magick", commandArgs).error === true) { + const command = `magick ${tdossTemplate} \\( ${directory}/input.png -resize 800x800^ -gravity center -extent 1000x1000 \\) -compose dst-over -composite ${directory}/tdoss_result.png`; + if (this.executeCommand(command).error === true) { message.channel.send("Something went wrong during image manipulation.\nTry again and if it keeps happening, contact the owner of the bot.") fs.rmSync(`${directory}`, {recursive: true}) return @@ -75,6 +75,20 @@ module.exports = { await message.channel.send({files: [final_image]}) fs.rmSync(`${directory}`, {recursive: true}) }, + + + executeCommand(command) { + console.log("Executing:", command) + try { + const output = execSync(command, { encoding: 'utf-8' }) + if (output.length != 0) + console.log(output) + } catch (error) { + console.error(`Error executing ${command.split(" ")[0]} command:`, error); + return { error: true }; + } + return { error: false }; + }, // https://stackoverflow.com/a/77210219 async downloadImage(url, path) { let res; diff --git a/commands/misc/timer.js b/commands/misc/timer.js index 522a9aa..746689b 100644 --- a/commands/misc/timer.js +++ b/commands/misc/timer.js @@ -4,11 +4,11 @@ const parseTime = require('../../util/timer/parseTime'); const showTimer = require('../../util/timer/showTimer'); module.exports = { name: "timer", - description: "Set a timer for a date or time duration.", + description: "Set a timer for a time in minutes.", moreHelp: ["Usage:" ,"`timer [add|create] `" ,"`timer