Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
bc497c7dea |
|||
|
d7b8e706b8 |
|||
|
7791fa5654 |
|||
|
9796e9245a |
|||
|
62b8ebb4cf |
|||
|
62fbb445e2 |
|||
|
1f48a896a5 |
|||
|
94d1b0f297 |
|||
|
cafcc007c1 |
|||
|
af4c42009c |
|||
|
f1f9e3aaa3 |
|||
|
4aaf72e4b4 |
|||
|
69872ba0d1 |
|||
|
7dab688298 |
|||
|
|
3ee2a80201 |
||
|
8655f279f9 |
|||
|
aa10d6bc27 |
|||
|
3d674f12e0 |
|||
|
0a8df28a94 |
|||
|
|
f78f4648d0 |
||
|
|
7f0029d9f9 |
||
|
|
681eca87e0 |
||
|
|
914aceeb44 |
||
|
|
dc7b49d255 |
||
|
|
c1d942e204 |
||
|
|
c53b707163 |
||
|
|
9dcc7adab4 |
||
|
1de446aede |
|||
|
|
94467bd57e |
||
|
|
be0091546f |
||
|
6ce4ca6fb8 |
|||
|
a891b37a31 |
|||
|
e79d2a7a7e |
|||
|
24e019e34f |
|||
|
9c4a57a098 |
|||
|
723f14405a |
|||
|
b9e0b6abd3 |
|||
|
28cc7d6f15 |
|||
|
4f0e948a84 |
|||
|
9611046393 |
|||
|
bbaf2205ad |
|||
|
08b52216a9 |
|||
|
|
4d42609f89 |
||
|
f55b54eb49 |
|||
|
|
18c2d9dc18 |
||
|
|
600173771e |
||
|
|
6c514b7396 |
||
|
|
ee21f4d75f |
||
|
|
561925a18e |
||
|
47dba48c76 |
|||
|
e92210e856 |
|||
|
ba99719c20 |
|||
|
69c7fd8d53 |
|||
|
8b2314ef1c |
|||
|
e5f4295281 |
|||
|
15749b1a9f |
|||
|
cf41d58b47 |
|||
|
ddb7cb128f |
|||
|
e06c6640b7 |
|||
|
ac03b9d136 |
|||
|
15fb1d544f |
|||
|
f14eff3f9c |
|||
|
ed77c2aaf1 |
|||
|
c74f323c1b |
|||
|
be8d9660ba |
|||
|
9ac900bc4d |
|||
|
6592f25882 |
|||
|
4f57499cca |
|||
|
9cb5ea22cb |
33 changed files with 2806 additions and 1437 deletions
2
.github/workflows/CI.yml
vendored
2
.github/workflows/CI.yml
vendored
|
|
@ -16,6 +16,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
node-version: 'latest'
|
node-version: 'latest'
|
||||||
- name: install dependencies
|
- name: install dependencies
|
||||||
run: npm install
|
run: npm ci
|
||||||
- name: run tests
|
- name: run tests
|
||||||
run: npm test
|
run: npm test
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
const savePresence = require("../../util/savePresence");
|
||||||
const setPresence = require("../../util/setPresence");
|
const setPresence = require("../../util/setPresence");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
@ -10,12 +11,20 @@ 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}"],
|
,"${guilds},${prefix},${uptime},{members}"],
|
||||||
admin: true,
|
admin: true,
|
||||||
execute({message, client, args, globalPrefix}) {
|
execute({message, client, args, prefix}) {
|
||||||
const savePresence = require("../../util/savePresence");
|
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;
|
||||||
|
}
|
||||||
let presenceType = args[0].toLocaleUpperCase();
|
let presenceType = args[0].toLocaleUpperCase();
|
||||||
let sendText = "Updated presence";
|
let sendText = "Presence has been set.";
|
||||||
|
|
||||||
switch (presenceType) {
|
switch (presenceType) {
|
||||||
case "PLAY":
|
case "PLAY":
|
||||||
|
|
@ -46,8 +55,11 @@ 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,4 +1,5 @@
|
||||||
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 = {
|
||||||
|
|
@ -27,10 +28,12 @@ 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.slice(1955)
|
sendText = 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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,11 @@ 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}`,
|
`Total Members: ${guildInfo.totalMembers} (${guildInfo.uniqueMemberCount} unique)`,
|
||||||
`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 = "";
|
||||||
|
|
|
||||||
|
|
@ -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 = "";
|
let guildNames = client.guilds.cache
|
||||||
client.guilds.cache.each(guild => {
|
.sort((a, b) => b.memberCount - a.memberCount)
|
||||||
guildNames = `${guildNames}${guild.name} (${guild.memberCount} members)\n`
|
.map(guild => `${guild.name} (${guild.memberCount} members)`)
|
||||||
});
|
.join("\n");
|
||||||
message.channel.send(guildNames)
|
message.channel.send(guildNames)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
103
commands/info/mc.js
Normal file
103
commands/info/mc.js
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
// 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 = `Global pfp:\n${globalPfp}`;
|
let sendText = `${globalPfp}`;
|
||||||
if(guildPfp != null){
|
if(guildPfp != null){
|
||||||
sendText = `${sendText}\nGuild pfp:\n${guildPfp}`;
|
sendText = `Global pfp${sendText}\nGuild pfp:\n${guildPfp}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
message.channel.send(sendText)
|
message.channel.send(sendText)
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ 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},
|
||||||
|
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
|
||||||
71
commands/misc/dl.js
Normal file
71
commands/misc/dl.js
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
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});
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,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`"
|
"Get a roast from an LLM using your top artists and albums: `<prefix>fmroast`"
|
||||||
|
|
@ -35,6 +37,19 @@ 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;
|
||||||
|
|
@ -72,11 +87,13 @@ 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));
|
||||||
|
|
|
||||||
28
commands/misc/ig.js
Normal file
28
commands/misc/ig.js
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
const setServerPrefix = require("../../util/setServerPrefix");
|
const setServerPrefix = require("../../util/setServerPrefix");
|
||||||
|
const { PermissionsBitField } = require('discord.js');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'prefix',
|
name: 'prefix',
|
||||||
description: 'Change the prefix of the bot in this server.',
|
description: 'Change the prefix of the bot in this server.',
|
||||||
execute({ message, client, args, prefix }) {
|
execute({ message, client, args, prefix }) {
|
||||||
if (!message.member.permissions.has('MANAGE_GUILD')) {
|
if (!message.member.permissions.has(PermissionsBitField.Flags.ManageGuild)) {
|
||||||
message.channel.send("You do not have sufficient permissions(MANAGE_GUILD) to change the prefix of this server.")
|
message.channel.send("You do not have sufficient permissions(MANAGE_GUILD) to change the prefix of this server.")
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -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 command = `magick ${tdossTemplate} \\( ${directory}/input.png -resize 800x800^ -gravity center -extent 1000x1000 \\) -compose dst-over -composite ${directory}/tdoss_result.png`;
|
const commandArgs = [tdossTemplate, "(", `${directory}/input.png`, "-resize", "800x800^", "-gravity", "center", "-extent", "1000x1000", ")", "-compose", "dst-over", "-composite", `${directory}/tdoss_result.png`]
|
||||||
if (this.executeCommand(command).error === true) {
|
if (executeCommand("magick", commandArgs).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,20 +75,6 @@ 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;
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ const parseTime = require('../../util/timer/parseTime');
|
||||||
const showTimer = require('../../util/timer/showTimer');
|
const showTimer = require('../../util/timer/showTimer');
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: "timer",
|
name: "timer",
|
||||||
description: "Set a timer for a time in minutes.",
|
description: "Set a timer for a date or time duration.",
|
||||||
moreHelp: ["Usage:"
|
moreHelp: ["Usage:"
|
||||||
,"`<prefix>timer [add|create] <time_in_minutes> <message_to_send>`"
|
,"`<prefix>timer [add|create] <time_in_minutes> <message_to_send>`"
|
||||||
,"`<prefix>timer <time>(d|h|m|s|t) <message_to_send>`"
|
,"`<prefix>timer <time>(d|h|m|s|t) <message_to_send>`"
|
||||||
,"`<prefix>timer <time_in_minutes> <message_to_send>`"
|
,"`<prefix>timer <future_date> <message_to_send>`"
|
||||||
,"`<prefix>timer edit <timer_id> <new_time_in_minutes> <new_message_to_send>` (not implemented)"
|
,"`<prefix>timer edit <timer_id> <new_time_in_minutes> <new_message_to_send>` (not implemented)"
|
||||||
,"`<prefix>timer [delete|remove] <timer_id>`"
|
,"`<prefix>timer [delete|remove] <timer_id>`"
|
||||||
,"`<prefix>timer show <timer_id>`"
|
,"`<prefix>timer show <timer_id>`"
|
||||||
|
|
@ -18,7 +18,8 @@ module.exports = {
|
||||||
switch (args[0]) {
|
switch (args[0]) {
|
||||||
case "add":
|
case "add":
|
||||||
case "create":
|
case "create":
|
||||||
sendText = await createTimer(message, args, false);
|
args.shift()
|
||||||
|
sendText = await createTimer(message, args);
|
||||||
break;
|
break;
|
||||||
case "edit":
|
case "edit":
|
||||||
sendText = "not implemented yet"
|
sendText = "not implemented yet"
|
||||||
|
|
@ -37,8 +38,8 @@ module.exports = {
|
||||||
sendText = "Please specify a time, and a message to send after the timer has finished";
|
sendText = "Please specify a time, and a message to send after the timer has finished";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!isNaN(parseTime(args[0], Math.floor(new Date() / 1000))))
|
if(!isNaN(parseTime(args[0], Math.floor(new Date() / 1000))) || !isNaN(Date.parse(args[0])))
|
||||||
sendText = await createTimer(message, args, true);
|
sendText = await createTimer(message, args);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
message.channel.send(sendText);
|
message.channel.send(sendText);
|
||||||
|
|
|
||||||
28
commands/misc/x.js
Normal file
28
commands/misc/x.js
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
3360
package-lock.json
generated
3360
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -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.19.3",
|
"discord.js": "^14.21.0",
|
||||||
"dotenv": "^16.5.0",
|
"dotenv": "^17.2.1",
|
||||||
"seedrandom": "^3.0.5",
|
"seedrandom": "^3.0.5",
|
||||||
"sqlite3": "^5.1.6"
|
"sqlite3": "^5.1.6"
|
||||||
},
|
},
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
"author": "SileNce5k",
|
"author": "SileNce5k",
|
||||||
"license": "UNLICENSE",
|
"license": "UNLICENSE",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^30.0.0",
|
||||||
"jest": "^29.7.0"
|
"jest": "^30.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
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();
|
||||||
|
|
@ -48,11 +49,16 @@ client.whitelist = {
|
||||||
guild: new Collection(),
|
guild: new Collection(),
|
||||||
user: new Collection()
|
user: new Collection()
|
||||||
}
|
}
|
||||||
|
process.env.TZ = "UTC";
|
||||||
|
|
||||||
createAndLoadWhitelistTable(client.whitelist);
|
createAndLoadWhitelistTable(client.whitelist);
|
||||||
|
|
||||||
client.settings.set("presenceType", presenceType);
|
client.settings.set("presenceType", presenceType);
|
||||||
client.settings.set("presenceText", presenceText);
|
client.settings.set("presenceText", presenceText);
|
||||||
|
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');
|
||||||
|
|
@ -73,7 +79,7 @@ client.once('disconnect', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('messageCreate', async message => {
|
client.on('messageCreate', async message => {
|
||||||
onMessage(client, owners, message, globalPrefix);
|
onMessage(client, owners, message);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
const isWhitelisted = require('../util/isWhitelisted')
|
const isWhitelisted = require('../util/isWhitelisted')
|
||||||
module.exports = function(client, owners, message, globalPrefix){
|
module.exports = function(client, owners, message){
|
||||||
let prefix = globalPrefix;
|
let prefix = client.settings.get("globalPrefix");
|
||||||
let serverPrefix = client.serverPrefixes.get(message.guild.id);
|
let serverPrefix = client.serverPrefixes.get(message.guild.id);
|
||||||
if (serverPrefix) {
|
if (serverPrefix) {
|
||||||
prefix = serverPrefix;
|
prefix = serverPrefix;
|
||||||
|
|
@ -27,8 +27,8 @@ module.exports = function(client, owners, message, globalPrefix){
|
||||||
}
|
}
|
||||||
if (command.admin && owners.indexOf(message.author.id.toString()) == -1) return;
|
if (command.admin && owners.indexOf(message.author.id.toString()) == -1) return;
|
||||||
try {
|
try {
|
||||||
command.execute({ message: message, args: args, client: client, prefix: prefix, owners: owners, globalPrefix: globalPrefix})
|
|
||||||
console.log(`${message.author.username}(id: ${message.author.id}) executed ${command.name} with '${args}' as arguments`)
|
console.log(`${message.author.username}(id: ${message.author.id}) executed ${command.name} with '${args}' as arguments`)
|
||||||
|
command.execute({ message: message, args: args, client: client, prefix: prefix, owners: owners})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
let divider = "------------------------"
|
let divider = "------------------------"
|
||||||
console.log(divider)
|
console.log(divider)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,15 @@ const checkTimer = require('../util/timer/checkTimer');
|
||||||
const updatePresence = require('../util/updatePresence');
|
const updatePresence = require('../util/updatePresence');
|
||||||
|
|
||||||
module.exports = function(client, enableLoginMessage, loginChannel, loginMessage) {
|
module.exports = function(client, enableLoginMessage, loginChannel, loginMessage) {
|
||||||
|
|
||||||
updatePresence(client)
|
updatePresence(client)
|
||||||
|
client.lastPresenceUpdate = Date.now()
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
updatePresence(client)
|
||||||
|
client.lastPresenceUpdate = Date.now()
|
||||||
|
}, 60 * 1000);
|
||||||
|
|
||||||
console.log('Ready!');
|
console.log('Ready!');
|
||||||
if (enableLoginMessage === true)
|
if (enableLoginMessage === true)
|
||||||
try{
|
try{
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
15
util/executeCommand.js
Normal file
15
util/executeCommand.js
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
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};
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,16 @@
|
||||||
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 => {
|
||||||
return {guildCount: guildCount, totalMembers: totalMembers};
|
if(!uniqueMembers.has(member.id)){
|
||||||
|
uniqueMembers.set(member.id, true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const uniqueMemberCount = uniqueMembers.size;
|
||||||
|
return {guildCount, totalMembers, uniqueMemberCount};
|
||||||
}
|
}
|
||||||
|
|
@ -2,6 +2,11 @@ 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) {
|
||||||
|
|
@ -58,10 +63,22 @@ 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(15780145)
|
.setColor(color)
|
||||||
.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}`
|
||||||
},)
|
},)
|
||||||
|
|
@ -71,8 +88,31 @@ module.exports = async function (userID, guild) {
|
||||||
},)
|
},)
|
||||||
}
|
}
|
||||||
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};
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,8 @@ 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 => {
|
||||||
for(let i = 0; i < 10; i++){
|
const maxIterations = data.topalbums.album.length >= 10 ? 10 : data.topalbums.album.length;
|
||||||
|
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;
|
||||||
|
|
@ -93,27 +94,24 @@ module.exports = async function (userID, option, guild, compatibility=false) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
// .setAuthor({name: `Top ${duration} albums for ${nickname}`, iconURL: user.user.avatarURL({ dynamic: true, size: 4096 })})
|
.setAuthor({name: `Top ${duration} albums for ${nickname}`, iconURL: user.user.avatarURL({ dynamic: true, size: 4096 })})
|
||||||
// .setThumbnail(albums[0].cover)
|
.setColor(15780145)
|
||||||
// .setColor(15780145)
|
let albumInfo = "";
|
||||||
// let tracksInfo = "";
|
for(let i = 0; i < albums.length; i++){
|
||||||
// for(let i = 0; i < albums.length; i++){
|
let pluralCharacter = albums[i].playcount > 1 ? 's' : '';
|
||||||
// let pluralCharacter = albums[i].playcount > 1 ? 's' : '';
|
let album = `${i}. **${albums[i].artist}** - ${albums[i].name} - *${albums[i].playcount} play${pluralCharacter}*`;
|
||||||
// let track = `${i}. **${albums[i].artist}** - ${albums[i].song} - *${albums[i].playcount} play${pluralCharacter}*`;
|
if(i < albums.length - 1){
|
||||||
// if(i < albums.length - 1){
|
albumInfo += `${album}\n`;
|
||||||
// tracksInfo += `${track}\n`;
|
}else{
|
||||||
// }else{
|
albumInfo += `${album}`;
|
||||||
// tracksInfo += `${track}`;
|
}
|
||||||
// }
|
}
|
||||||
// }
|
embed.setDescription(albumInfo);
|
||||||
// embed.addFields({
|
sendText.embed = embed;
|
||||||
// name: ` `, value: `${tracksInfo}`
|
if(compatibility)
|
||||||
// },)
|
|
||||||
// sendText.embed = embed;
|
|
||||||
// if(compatibility)
|
|
||||||
return albums;
|
return albums;
|
||||||
// else
|
else
|
||||||
// return sendText;
|
return sendText;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -77,7 +77,8 @@ 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 => {
|
||||||
for(let i = 0; i < 10; i++){
|
const maxIterations = data.topartists.artist.length >= 10 ? 10 : data.topartists.artist.length;
|
||||||
|
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;
|
||||||
|
|
@ -92,27 +93,24 @@ module.exports = async function (userID, option, guild, compatibility=false) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
// .setAuthor({name: `Top ${duration} tracks for ${nickname}`, iconURL: user.user.avatarURL({ dynamic: true, size: 4096 })})
|
.setAuthor({name: `Top ${duration} artists for ${nickname}`, iconURL: user.user.avatarURL({ dynamic: true, size: 4096 })})
|
||||||
// .setThumbnail(tracks[0].cover)
|
.setColor(15780145)
|
||||||
// .setColor(15780145)
|
let artistsInfo = "";
|
||||||
// let tracksInfo = "";
|
for(let i = 0; i < artists.length; i++){
|
||||||
// for(let i = 0; i < tracks.length; i++){
|
let pluralCharacter = artists[i].playcount > 1 ? 's' : '';
|
||||||
// let pluralCharacter = tracks[i].playcount > 1 ? 's' : '';
|
let track = `${i}. **${artists[i].name}** - *${artists[i].playcount} play${pluralCharacter}*`;
|
||||||
// let track = `${i}. **${tracks[i].artist}** - ${tracks[i].song} - *${tracks[i].playcount} play${pluralCharacter}*`;
|
if(i < artists.length - 1){
|
||||||
// if(i < tracks.length - 1){
|
artistsInfo += `${track}\n`;
|
||||||
// tracksInfo += `${track}\n`;
|
}else{
|
||||||
// }else{
|
artistsInfo += `${track}`;
|
||||||
// tracksInfo += `${track}`;
|
}
|
||||||
// }
|
}
|
||||||
// }
|
embed.setDescription(artistsInfo);
|
||||||
// embed.addFields({
|
sendText.embed = embed;
|
||||||
// name: ` `, value: `${tracksInfo}`
|
if(compatibility)
|
||||||
// },)
|
|
||||||
// sendText.embed = embed;
|
|
||||||
// if(compatibility)
|
|
||||||
return artists;
|
return artists;
|
||||||
// else
|
else
|
||||||
// return sendText;
|
return sendText;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +78,8 @@ 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 => {
|
||||||
for(let i = 0; i < 10; i++){
|
const maxIterations = data.toptracks.track.length >= 10 ? 10 : data.toptracks.track.length;
|
||||||
|
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;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ const getGuildInfo = require("./getGuildInfo")
|
||||||
const parseMS = require('./parseMS');
|
const parseMS = require('./parseMS');
|
||||||
const convertDateToISOString = require('./convertDateToISOString')
|
const convertDateToISOString = require('./convertDateToISOString')
|
||||||
module.exports = function ({presenceText, presenceType, client}) {
|
module.exports = function ({presenceText, presenceType, client}) {
|
||||||
const {globalPrefix} = require ('../data/config.json')
|
const globalPrefix = client.settings.get("globalPrefix")
|
||||||
let guildCount = getGuildInfo(client).guildCount
|
const guildInfo = getGuildInfo(client);
|
||||||
let uptime = parseMS(client.uptime);
|
let uptime = parseMS(client.uptime);
|
||||||
let uptimeFormat = "";
|
let uptimeFormat = "";
|
||||||
let uptimeSingularOrPlural;
|
let uptimeSingularOrPlural;
|
||||||
|
|
@ -18,10 +18,23 @@ module.exports = function ({presenceText, presenceType, client}) {
|
||||||
uptimeFormat = `less than a minute`
|
uptimeFormat = `less than a minute`
|
||||||
}
|
}
|
||||||
|
|
||||||
let regex = [/\${guilds}/g,/\${prefix}/g,/\${uptime}/g];
|
let presenceVariables = {
|
||||||
let replaceValue = [guildCount, globalPrefix, uptimeFormat];
|
guilds: guildInfo.guildCount,
|
||||||
for(let i = 0; i < regex.length; i++){
|
prefix: globalPrefix,
|
||||||
presenceText = presenceText.replace(regex[i], replaceValue[i]);
|
uptime: uptimeFormat,
|
||||||
|
members: guildInfo.totalMembers,
|
||||||
|
uniqueMembers: guildInfo.uniqueMemberCount
|
||||||
|
}
|
||||||
|
|
||||||
|
const regex = /(?<=\${)(.*?)(?=})/g;
|
||||||
|
const matches = presenceText.match(regex);
|
||||||
|
|
||||||
|
if(matches){
|
||||||
|
matches.forEach(match => {
|
||||||
|
if(presenceVariables[match]){
|
||||||
|
presenceText = presenceText.replace(`\${${match}}`, presenceVariables[match]);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,26 @@
|
||||||
const fs = require('fs');
|
|
||||||
const parseTime = require('./parseTime');
|
const parseTime = require('./parseTime');
|
||||||
|
const timeUntil = require('./timeUntil');
|
||||||
const sqlite3 = require('sqlite3').verbose();
|
const sqlite3 = require('sqlite3').verbose();
|
||||||
module.exports = async function (message, args, compatibility) {
|
module.exports = async function (message, args) {
|
||||||
const databasePath = 'data/database.db'
|
const databasePath = 'data/database.db'
|
||||||
if (args.length < 2)
|
if (args.length < 2)
|
||||||
return message.channel.send("Please specify a time, and a message to send after the timer has finished");
|
return "Please specify a time, and a message to send after the timer has finished";
|
||||||
let currentUnixTime = Math.floor(new Date() / 1000);
|
let currentUnixTime = Math.floor(new Date() / 1000);
|
||||||
let timeInSeconds = compatibility ? parseTime(args[0], currentUnixTime) : parseTime(args[1], currentUnixTime);
|
|
||||||
if (isNaN(timeInSeconds)) {
|
let timeInSeconds;
|
||||||
return message.channel.send("Please specify a time, and a message to send after the timer has finished")
|
if(!isNaN(Date.parse(args[0])) && isNaN(parseTime(args[0], currentUnixTime))){
|
||||||
|
timeInSeconds = timeUntil(args[0]).totalInSeconds;
|
||||||
|
if(timeInSeconds < 0){
|
||||||
|
return "The date must not be in the past."
|
||||||
}
|
}
|
||||||
let customMessage = compatibility ? args.slice(1).join(" ") : args.slice(2).join(" ");
|
}else {
|
||||||
let reminderTime = currentUnixTime + timeInSeconds
|
timeInSeconds = parseTime(args[0], currentUnixTime);
|
||||||
|
}
|
||||||
|
if (isNaN(timeInSeconds)) {
|
||||||
|
return "Please specify a time, and a message to send after the timer has finished"
|
||||||
|
}
|
||||||
|
const customMessage = args.slice(1).join(" ")
|
||||||
|
const reminderTime = currentUnixTime + timeInSeconds
|
||||||
let newTimerID;
|
let newTimerID;
|
||||||
const db = new sqlite3.Database(databasePath)
|
const db = new sqlite3.Database(databasePath)
|
||||||
let sendText = await new Promise((resolve, reject)=>{
|
let sendText = await new Promise((resolve, reject)=>{
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
module.exports = function(time, currentUnixTime){
|
module.exports = function(time, currentUnixTime){
|
||||||
let timeInSeconds = parseFloat(time.slice(0, time.length - 1))
|
let timeInSeconds = parseFloat(time)
|
||||||
let letter = time.slice(time.length - 1)
|
const letterCount = time.length - timeInSeconds.toString().length;
|
||||||
if(!isNaN(letter)) return parseFloat(time) * 60;
|
const letter = time.slice(time.length - letterCount);
|
||||||
switch (letter.toUpperCase()) {
|
switch (letter.toUpperCase()) {
|
||||||
case "H":
|
case "H":
|
||||||
timeInSeconds = timeInSeconds * 3_600;
|
timeInSeconds = timeInSeconds * 3_600;
|
||||||
|
|
@ -14,7 +14,8 @@ module.exports = function(time, currentUnixTime){
|
||||||
case "D":
|
case "D":
|
||||||
timeInSeconds = timeInSeconds * 86_400;
|
timeInSeconds = timeInSeconds * 86_400;
|
||||||
break;
|
break;
|
||||||
case "T": // TODO: Make it so that I can have multiple letters per case, so that "TS" would work here.
|
case "TS": // Unix timestamp
|
||||||
|
case "T":
|
||||||
timeInSeconds = timeInSeconds - currentUnixTime;
|
timeInSeconds = timeInSeconds - currentUnixTime;
|
||||||
break;
|
break;
|
||||||
case "W":
|
case "W":
|
||||||
|
|
@ -22,17 +23,6 @@ module.exports = function(time, currentUnixTime){
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
timeInSeconds = NaN;
|
timeInSeconds = NaN;
|
||||||
if(time.includes(':'))
|
|
||||||
timeInSeconds = getTime(time, currentUnixTime);
|
|
||||||
}
|
}
|
||||||
return timeInSeconds;
|
return timeInSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function getTime(time, currentUnixTime) {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return timeInSeconds;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
20
util/timer/timeUntil.js
Normal file
20
util/timer/timeUntil.js
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
module.exports = function(targetTime) {
|
||||||
|
const countDownDate = new Date(targetTime).getTime();
|
||||||
|
const now = new Date().getTime();
|
||||||
|
|
||||||
|
const distance = countDownDate - now;
|
||||||
|
let days = Math.floor(distance / (1000 * 60 * 60 * 24));
|
||||||
|
let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||||||
|
let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
|
||||||
|
let seconds = Math.floor((distance % (1000 * 60)) / 1000);
|
||||||
|
|
||||||
|
if (seconds < 0) { // Due to how the math above works, if the input time is in the past, the time will be off by 1.
|
||||||
|
days = days + 1;
|
||||||
|
hours = hours + 1;
|
||||||
|
minutes = minutes + 1;
|
||||||
|
seconds = seconds + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalInSeconds = (days * 24 * 60 * 60) + (hours * 60 * 60) + (minutes * 60) + seconds;
|
||||||
|
return { days, hours, minutes, seconds, totalInSeconds };
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,8 @@
|
||||||
const setPresence = require('./setPresence')
|
const setPresence = require('./setPresence')
|
||||||
|
|
||||||
module.exports = function (client) {
|
module.exports = function (client) {
|
||||||
const updatePresence = require('./updatePresence')
|
|
||||||
let presenceText = client.settings.get("presenceText")
|
let presenceText = client.settings.get("presenceText")
|
||||||
let presenceType = client.settings.get("presenceType")
|
let presenceType = client.settings.get("presenceType")
|
||||||
|
|
||||||
if(presenceText.includes("${guilds}") || presenceText.includes("${prefix}") || presenceText.includes("${uptime}")) {
|
|
||||||
setPresence({presenceText: presenceText, presenceType: presenceType, client: client});
|
setPresence({presenceText: presenceText, presenceType: presenceType, client: client});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
setTimeout(updatePresence, 60000, client)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue