Compare commits

..
Author SHA1 Message Date
c6ef14ee70
Fix verbose flag not working
All checks were successful
CI / CI (push) Successful in 1m25s
2025-06-21 15:40:16 +02:00
e68bb41960
Fix typo 2025-06-21 15:35:26 +02:00
a6060cdbfb
Use execFileSync instead of execSync to prevent command injection
All checks were successful
CI / CI (push) Successful in 1m24s
and add verbose flag
2025-06-21 15:30:18 +02:00
6293010b6c
Fix command injection vulnerability by using a command array
All checks were successful
CI / CI (push) Successful in 1m25s
2025-06-21 14:25:43 +02:00
f4ffcbebde
Use Date.now()
All checks were successful
CI / CI (push) Successful in 1m25s
2025-06-21 13:55:18 +02:00
2073a46715
Fix file check 2025-06-21 13:54:45 +02:00
27fc1c55bf
Edit the text to nothing
All checks were successful
CI / CI (push) Successful in 1m24s
2025-06-21 13:40:03 +02:00
8314be972f
Slice first character of the argument
All checks were successful
CI / CI (push) Successful in 1m26s
2025-06-21 13:35:58 +02:00
ad73a83514
Send an inital message when downloading begins & check for cookies file
All checks were successful
CI / CI (push) Successful in 1m26s
2025-06-21 13:31:59 +02:00
40052ac85d
Improve error messages
All checks were successful
CI / CI (push) Successful in 1m25s
2025-06-18 00:37:03 +02:00
09eee1a0ca
Add support for prepending URL with '<' and appending with '>' 2025-06-18 00:36:32 +02:00
340727ae60
dl: Add cookie file
All checks were successful
CI / CI (push) Successful in 1m24s
2025-06-18 00:14:10 +02:00
0a35549666
dl: fix error check
All checks were successful
CI / CI (push) Successful in 1m25s
2025-06-17 02:24:49 +02:00
9d0eb60b81
Improve dl command
All checks were successful
CI / CI (push) Successful in 1m24s
2025-06-17 02:21:31 +02:00
d27c1bad55
Add initial dl command
All checks were successful
CI / CI (push) Successful in 1m24s
2025-06-17 01:55:20 +02:00
23 changed files with 1140 additions and 1819 deletions

View file

@ -16,6 +16,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

View file

@ -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)
}) })
} }

View file

@ -12,11 +12,10 @@ module.exports = {
let descriptionArr = [`Name: ${client.user.username}`, let descriptionArr = [`Name: ${client.user.username}`,
`Prefix: ${prefix}`, `Prefix: ${prefix}`,
`Total Servers: ${guildInfo.guildCount}`, `Total Servers: ${guildInfo.guildCount}`,
`Total Members: ${guildInfo.totalMembers} (${guildInfo.uniqueMemberCount} unique)`, `Total Members: ${guildInfo.totalMembers}`,
`Total Commands: ${client.commands.size}`, `Total Commands: ${client.commands.size}`,
`Creation Date: ${getCreationDate(client)}`, `Creation Date: ${getCreationDate(client)}`,
`Source: [Click Here](https://github.com/SileNce5k/discord_bot)`, `Source: [Click Here](https://github.com/SileNce5k/discord_bot)`
`Current Version: ${client.githash}`
] ]
let description = ""; let description = "";

View file

@ -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
}

View file

@ -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)

View file

@ -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},
]) ])

View file

@ -1,7 +1,7 @@
const { execFileSync } = require('child_process');
const path = require('path'); const path = require('path');
const fs = require('fs') const fs = require('fs')
const executeCommand = require('../../util/executeCommand');
module.exports = { module.exports = {
name: 'dl', name: 'dl',
description: 'Download a video', description: 'Download a video',
@ -38,7 +38,7 @@ module.exports = {
const originalMessage = await message.channel.send("Downloading video...") const originalMessage = await message.channel.send("Downloading video...")
if(executeCommand("yt-dlp", [url, "-P", downloadsDir, "--cookies", cookieFilepath]).error){ if(this.executeCommand("yt-dlp", [url, "-P", downloadsDir, "--cookies", cookieFilepath]).error){
originalMessage.edit("An error occurred when downloading the video."); originalMessage.edit("An error occurred when downloading the video.");
this.cleanUp(downloadsDir); this.cleanUp(downloadsDir);
return; return;
@ -68,4 +68,18 @@ module.exports = {
fs.rmSync(downloadsDir, {force: true, recursive: true}); fs.rmSync(downloadsDir, {force: true, recursive: true});
}, },
executeCommand(command, commandArgs, verbose=false) {
if (typeof command !== 'string' || !Array.isArray(commandArgs)) return { error: true };
console.log("Executing:", command, commandArgs.join(" "));
try {
const output = execFileSync(command, commandArgs, {encoding: 'utf8'})
if (output.length != 0 && verbose)
console.log(output)
} catch (error) {
console.error(`Error executing ${command} command:`, error);
return { error: true };
}
return { error: false };
},
} }

View file

@ -87,13 +87,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));

View file

@ -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);
}
}
};

View file

@ -1,7 +1,6 @@
module.exports = { module.exports = {
name: 'say', name: 'say',
description: 'Repeats arguments', description: 'Repeats arguments',
admin: true,
execute({message, args}) { execute({message, args}) {
if(args.length == 0) if(args.length == 0)

View file

@ -3,7 +3,7 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const { writeFile } = require('node:fs/promises') const { writeFile } = require('node:fs/promises')
const { Readable } = require('node:stream') const { Readable } = require('node:stream')
const executeCommand = require('../../util/executeCommand');
module.exports = { module.exports = {
name: 'tdoss', 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`] const command = `magick ${tdossTemplate} \\( ${directory}/input.png -resize 800x800^ -gravity center -extent 1000x1000 \\) -compose dst-over -composite ${directory}/tdoss_result.png`;
if (executeCommand("magick", commandArgs).error === true) { 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.") 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}) fs.rmSync(`${directory}`, {recursive: true})
return return
@ -75,6 +75,20 @@ module.exports = {
await message.channel.send({files: [final_image]}) await message.channel.send({files: [final_image]})
fs.rmSync(`${directory}`, {recursive: true}) 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 // https://stackoverflow.com/a/77210219
async downloadImage(url, path) { async downloadImage(url, path) {
let res; let res;

View file

@ -1,28 +0,0 @@
module.exports = {
name: 'x',
description: 'Replaces X/Twitter links with fxtwitter and deletes the original message',
execute({message, args}) {
const noUrlErr = "You need to provide an X or twitter link to use this command."
if(args.length < 1) {
message.channel.send(noUrlErr);
return;
}
let replacedLink = "";
const regex = /(?<=\/)(x|twitter)\.com/g
if(args[0].startsWith("https://") || args[0].startsWith("http://")){
replacedLink = args[0].replace(regex, "fxtwitter.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);
}
}
};

2603
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -5,8 +5,8 @@
"main": "server.js", "main": "server.js",
"dependencies": { "dependencies": {
"@zuzak/owo": "^1.14.1", "@zuzak/owo": "^1.14.1",
"discord.js": "^14.21.0", "discord.js": "^14.20.0",
"dotenv": "^17.2.1", "dotenv": "^16.5.0",
"seedrandom": "^3.0.5", "seedrandom": "^3.0.5",
"sqlite3": "^5.1.6" "sqlite3": "^5.1.6"
}, },
@ -21,6 +21,6 @@
"license": "UNLICENSE", "license": "UNLICENSE",
"devDependencies": { "devDependencies": {
"@types/jest": "^30.0.0", "@types/jest": "^30.0.0",
"jest": "^30.0.5" "jest": "^30.0.0"
} }
} }

View file

@ -1,7 +1,6 @@
const fs = require('fs'); const fs = require('fs');
const createInitialConfig = require("./util/createInitialConfig") const createInitialConfig = require("./util/createInitialConfig")
const convertJSONToSQL = require('./util/timer/convertJSONToSQL'); const convertJSONToSQL = require('./util/timer/convertJSONToSQL');
const executeCommand = require('./util/executeCommand.js');
const sqlite3 = require('sqlite3').verbose(); const sqlite3 = require('sqlite3').verbose();
if(!fs.existsSync("./data/config.json")) { if(!fs.existsSync("./data/config.json")) {
createInitialConfig(); createInitialConfig();
@ -57,9 +56,6 @@ client.settings.set("presenceType", presenceType);
client.settings.set("presenceText", presenceText); client.settings.set("presenceText", presenceText);
client.settings.set("globalPrefix", globalPrefix); client.settings.set("globalPrefix", globalPrefix);
const githash = executeCommand(`git`, ["rev-parse", "--short", "HEAD"]);
client.githash = githash.error ? "N/A" : githash.output;
const reloadCommands = require("./util/reloadCommands.js"); const reloadCommands = require("./util/reloadCommands.js");
const onMessage = require('./server/message'); const onMessage = require('./server/message');
const onReady = require('./server/ready'); const onReady = require('./server/ready');

View file

@ -0,0 +1,17 @@
const getGuildInfo = require('../util/getGuildInfo');
test("Testing getGuildCount", () => {
for(let i = 1; i < 200000; i = i+i*30 ){
let client = {guilds: {cache: new Map()}}
client.guilds.cache.each = client.guilds.cache.forEach;
for(let j = 0; j < i; j++){
client.guilds.cache.set(`num: ${j}`, j);
}
expect(getGuildInfo(client).guildCount).toBe(i);
}
})

View file

@ -1,15 +0,0 @@
const { execFileSync } = require('child_process');
module.exports = function(command, commandArgs, verbose=false) {
if (typeof command !== 'string' || !Array.isArray(commandArgs)) return { error: true };
console.log("Executing:", command, commandArgs.join(" "));
let output;
try {
output = execFileSync(command, commandArgs, {encoding: 'utf8'})
if (output.length !== 0 && verbose)
console.log(output)
} catch (error) {
console.error(`Error executing ${command} command:`, error);
return { error: true };
}
return { error: false, output};
}

View file

@ -1,16 +1,9 @@
module.exports = function(client){ module.exports = function(client){
let guildCount = 0; let guildCount = 0;
let totalMembers = 0; let totalMembers = 0;
const uniqueMembers = new Map();
client.guilds.cache.each(guild => { client.guilds.cache.each(guild => {
guildCount++ guildCount++
totalMembers += guild.memberCount; totalMembers += guild.memberCount;
guild.members.cache.each(member => {
if(!uniqueMembers.has(member.id)){
uniqueMembers.set(member.id, true);
}
})
}); });
const uniqueMemberCount = uniqueMembers.size; return {guildCount: guildCount, totalMembers: totalMembers};
return {guildCount, totalMembers, uniqueMemberCount};
} }

View file

@ -2,11 +2,6 @@ const getNickname = require("../getNickname");
const parseMention = require("../parseMention"); const parseMention = require("../parseMention");
const getFmUsername = require("./getFmUsername"); const getFmUsername = require("./getFmUsername");
const {EmbedBuilder} = require('discord.js'); const {EmbedBuilder} = require('discord.js');
const path = require('path');
const fs = require('fs');
const { writeFile } = require('node:fs/promises')
const executeCommand = require('../executeCommand');
const { Readable } = require('node:stream')
require("dotenv").config(); require("dotenv").config();
module.exports = async function (userID, guild) { module.exports = async function (userID, guild) {
@ -63,56 +58,21 @@ module.exports = async function (userID, guild) {
sendText.text = tracks.errorMsg; sendText.text = tracks.errorMsg;
return sendText; return sendText;
} }
let coverDir = path.resolve(process.cwd(), 'data', 'covers');
let color = "#C27D0E"
const directory = path.resolve(coverDir, Math.floor(new Date).toString())
fs.mkdirSync(directory, {recursive: true})
const coverFile = path.resolve(directory, "cover")
let downloadResult = await downloadImage(tracks[0].cover, coverFile);
if(downloadResult.value === ERROR_CODES.SUCCESS){
const commandArgs = [`${coverFile}.${downloadResult.ext}`, "-resize", "1x1", "txt:-"]
let res = executeCommand("magick", commandArgs);
if(!res.error) color = res.output.split("\n")[1].split(" ")[3].slice(0,7);
}
const embed = new EmbedBuilder() const embed = new EmbedBuilder()
.setAuthor({name: `Now playing - ${nickname}`, iconURL: user.user.avatarURL({ dynamic: true, size: 4096 })}) .setAuthor({name: `Now playing - ${nickname}`, iconURL: user.user.avatarURL({ dynamic: true, size: 4096 })})
.setThumbnail(tracks[0].cover) .setThumbnail(tracks[0].cover)
.setColor(color) .setColor(15780145)
.addFields({ .addFields({
name: `${isCurrentScrobble}:`, value: `${tracks[0].song}\n **${tracks[0].artist} • ** ${tracks[0].album}` name: `${isCurrentScrobble}:`, value: `${tracks[0].song}\n **${tracks[0].artist} • ** ${tracks[0].album}`
},) },)
if (isCurrentScrobble === "Current") { if (isCurrentScrobble === "Current") {
embed.addFields({ embed.addFields({
name: "Previous:", value: `${tracks[1].song}\n **${tracks[1].artist} • ** ${tracks[1].album}` name: "Previous:", value: `${tracks[1].song}\n **${tracks[1].artist} • ** ${tracks[1].album}`
},) },)
} }
sendText.embed = embed; sendText.embed = embed;
fs.rmSync(`${directory}`, {recursive: true})
} else { } else {
sendText.text = "You haven't set your last.fm username yet. Use `<prefix>fm set <lastfm_username>` to set it."; sendText.text = "You haven't set your last.fm username yet. Use `<prefix>fm set <lastfm_username>` to set it.";
} }
return sendText; return sendText;
} }
const ERROR_CODES = {
SUCCESS: 0,
HTTP_ERROR: 1,
NOT_IMAGE: 2,
FETCH_ERROR: 3
}
async function downloadImage(url, downloadPath) {
let res;
try {
res = await fetch(url);
} catch (error) {
return {value: ERROR_CODES.FETCH_ERROR, errorMessage: error.cause?.message || error.message};
}
if(!res.ok) return {value: ERROR_CODES.HTTP_ERROR, errorMessage: res.status.toString()};
const contentType = res.headers.get('content-type');
if(!contentType || !contentType.startsWith("image")) return {value: ERROR_CODES.NOT_IMAGE, errorMessage: contentType || "No content-type header"};
const fileExt = contentType.split("/")[1]
const stream = Readable.fromWeb(res.body)
await writeFile(`${downloadPath}.${fileExt}`, stream);
return {value: ERROR_CODES.SUCCESS, errorMessage: "", ext: fileExt};
}

View file

@ -77,8 +77,7 @@ module.exports = async function (userID, option, guild, compatibility=false) {
fetch(`https://ws.audioscrobbler.com/2.0/?method=user.gettopalbums&user=${lastfmUsername}&period=${option[0]}&api_key=${process.env.LAST_FM_API_KEY}&format=json`) fetch(`https://ws.audioscrobbler.com/2.0/?method=user.gettopalbums&user=${lastfmUsername}&period=${option[0]}&api_key=${process.env.LAST_FM_API_KEY}&format=json`)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
const maxIterations = data.topalbums.album.length >= 10 ? 10 : data.topalbums.album.length; for(let i = 0; i < 10; i++){
for(let i = 0; i < maxIterations; i++){
let album = {} let album = {}
let currentAlbum = data.topalbums.album[i]; let currentAlbum = data.topalbums.album[i];
album.artist = currentAlbum.artist.name; album.artist = currentAlbum.artist.name;

View file

@ -77,8 +77,7 @@ module.exports = async function (userID, option, guild, compatibility=false) {
fetch(`https://ws.audioscrobbler.com/2.0/?method=user.gettopartists&user=${lastfmUsername}&period=${option[0]}&api_key=${process.env.LAST_FM_API_KEY}&format=json`) fetch(`https://ws.audioscrobbler.com/2.0/?method=user.gettopartists&user=${lastfmUsername}&period=${option[0]}&api_key=${process.env.LAST_FM_API_KEY}&format=json`)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
const maxIterations = data.topartists.artist.length >= 10 ? 10 : data.topartists.artist.length; for(let i = 0; i < 10; i++){
for(let i = 0; i < maxIterations; i++){
let artist = {} let artist = {}
let currentArtist = data.topartists.artist[i]; let currentArtist = data.topartists.artist[i];
artist.name = currentArtist.name; artist.name = currentArtist.name;

View file

@ -78,8 +78,7 @@ module.exports = async function (userID, option, guild, compatibility=false) {
fetch(`https://ws.audioscrobbler.com/2.0/?method=user.gettoptracks&user=${lastfmUsername}&period=${option[0]}&api_key=${apiKey}&format=json`) fetch(`https://ws.audioscrobbler.com/2.0/?method=user.gettoptracks&user=${lastfmUsername}&period=${option[0]}&api_key=${apiKey}&format=json`)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
const maxIterations = data.toptracks.track.length >= 10 ? 10 : data.toptracks.track.length; for(let i = 0; i < 10; i++){
for(let i = 0; i < maxIterations; i++){
let track = {} let track = {}
let currentTrack = data.toptracks.track[i]; let currentTrack = data.toptracks.track[i];
track.artist = currentTrack.artist.name; track.artist = currentTrack.artist.name;

View file

@ -22,8 +22,7 @@ module.exports = function ({presenceText, presenceType, client}) {
guilds: guildInfo.guildCount, guilds: guildInfo.guildCount,
prefix: globalPrefix, prefix: globalPrefix,
uptime: uptimeFormat, uptime: uptimeFormat,
members: guildInfo.totalMembers, members: guildInfo.totalMembers
uniqueMembers: guildInfo.uniqueMemberCount
} }
const regex = /(?<=\${)(.*?)(?=})/g; const regex = /(?<=\${)(.*?)(?=})/g;