Merge pull request #221 from VermiumSifell/dev

Setup & Fix better logging &  Grammar
This commit is contained in:
Axel Olausson Holtenäs 2022-04-14 04:07:07 +02:00 committed by GitHub
commit 81974128bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
67 changed files with 1623 additions and 1581 deletions

View file

@ -8,12 +8,13 @@ import logger from "@logger";
import { url } from "@config/database";
export default async () => {
await mongoose
.connect(url)
?.then(async () => {
logger.info("Successfully connected to MongoDB!");
})
?.catch(async () => {
logger.error("Error whilst connecting to MongoDB!");
});
mongoose.connect(url).then(async (connection: any) => {
logger?.info(`Connected to database: ${connection.connection.name}`);
});
mongoose.connection.on("error", (error: any) => {
logger?.error(error);
});
mongoose.connection.on("warn", (warning: any) => {
logger?.warn(warning);
});
};

View file

@ -4,12 +4,15 @@ import { Guild } from "discord.js";
// Dependencies
import updatePresence from "@helpers/updatePresence";
import fetchGuild from "@helpers/fetchGuild";
import logger from "@logger";
export default {
name: "guildCreate",
async execute(guild: Guild) {
const { client } = guild;
logger?.verbose(`Added to guild: ${guild.name} (${guild.id})`);
await fetchGuild(guild);
await updatePresence(client);
},

View file

@ -4,12 +4,15 @@ import { Guild } from "discord.js";
// Dependencies
import updatePresence from "@helpers/updatePresence";
import dropGuild from "@helpers/dropGuild";
import logger from "@logger";
export default {
name: "guildDelete",
async execute(guild: Guild) {
const { client } = guild;
logger?.verbose(`Deleted from guild: ${guild.name} (${guild.id})`);
await dropGuild(guild);
await updatePresence(client);
},

View file

@ -4,12 +4,17 @@ import { GuildMember } from "discord.js";
// Dependencies
import updatePresence from "@helpers/updatePresence";
import fetchUser from "@helpers/fetchUser";
import logger from "@logger";
export default {
name: "guildMemberAdd",
async execute(member: GuildMember) {
const { client, user, guild } = member;
logger?.verbose(
`New member: ${user.tag} (${user.id}) added to guild: ${guild.name} (${guild.id})`
);
await fetchUser(user, guild);
await updatePresence(client);
},

View file

@ -4,12 +4,17 @@ import { GuildMember } from "discord.js";
// Dependencies
import updatePresence from "@helpers/updatePresence";
import dropUser from "@helpers/dropUser";
import logger from "@logger";
export default {
name: "guildMemberRemove",
async execute(member: GuildMember) {
const { client, user, guild } = member;
logger?.verbose(
`Removed member: ${user.tag} (${user.id}) from guild: ${guild.name} (${guild.id})`
);
await dropUser(user, guild);
await updatePresence(client);
},

View file

@ -5,8 +5,6 @@ import logger from "@logger";
import { errorColor, footerText, footerIcon } from "@config/embed";
import guildSchema from "@schemas/guild";
export default async (interaction: CommandInteraction) => {
if (!interaction.isCommand()) return;
@ -15,39 +13,24 @@ export default async (interaction: CommandInteraction) => {
const currentCommand = client.commands.get(commandName);
if (!currentCommand) return;
// If command do not exist
// Create guild if it does not exist already
await guildSchema.findOne(
{ guildId: guild?.id },
{ new: true, upsert: true }
);
// Defer reply
await interaction.deferReply({ ephemeral: true });
await currentCommand
.execute(interaction)
.then(async () => {
return logger.debug(
`Guild: ${guild?.id} (${guild?.name}) User: ${user?.tag} executed ${commandName}`
return logger?.verbose(
`Command: ${commandName} executed in guild: ${guild?.name} (${guild?.id}) by user: ${user?.tag} (${user?.id})`
);
})
.catch(async (error: any) => {
console.log(error);
logger.error(
`Guild: ${guild?.id} (${guild?.name}) User: ${user?.tag} There was an error executing the command: ${commandName}`
);
logger.error(error);
logger?.error(error);
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("Error")
.setDescription(
`There was an error executing the command: **${currentCommand.data.name}**.`
`There was an error executing the command: **${currentCommand?.data?.name}**.`
)
.setColor(errorColor)
.setTimestamp(new Date())

View file

@ -3,10 +3,17 @@ import { CommandInteraction } from "discord.js";
// Dependencies
import isCommand from "@root/events/interactionCreate/components/isCommand";
import logger from "@logger";
export default {
name: "interactionCreate",
async execute(interaction: CommandInteraction) {
const { guild, id } = interaction;
logger?.verbose(
`New interaction: ${id} in guild: ${guild?.name} (${guild?.id})`
);
await isCommand(interaction);
},
};

View file

@ -1,31 +1,44 @@
import counters from "../../../database/schemas/counter";
import { Message } from "discord.js";
import logger from "@logger";
import counterSchema from "@schemas/counter";
export default async (message: Message) => {
const { guild, channel, content } = message;
// Get counter object
const counter = await counters.findOne({
if (channel?.type !== "GUILD_TEXT") return;
const counter = await counterSchema.findOne({
guildId: guild?.id,
channelId: channel.id,
});
// If counter for the message channel
if (counter) {
// If message content is not strictly the same as counter word
if (content !== counter.word) {
// Delete the message
await message.delete();
} else {
// Add 1 to the counter object
await counters.findOneAndUpdate(
{
guildId: guild?.id,
channelId: channel.id,
},
{ $inc: { counter: 1 } }
);
}
if (counter === null) return;
logger?.verbose(
`Channel: ${channel.name} (${channel.id}) is an active counter channel`
);
if (content !== counter.word) {
logger?.verbose(`Message: ${content} is not the counter word`);
return message.delete();
}
logger?.verbose(`Message: ${content} is the counter word`);
await counterSchema
.findOneAndUpdate(
{
guildId: guild?.id,
channelId: channel.id,
},
{ $inc: { counter: 1 } }
)
.then(async () => {
logger?.verbose(`Counter incremented`);
})
.catch(async () => {
logger?.error(`Failed to increment counter`);
});
};

View file

@ -2,69 +2,50 @@ import logger from "../../../logger";
import timeouts from "../../../database/schemas/timeout";
import { Message } from "discord.js";
export default async (guildDB: any, userDB: any, message: Message) => {
const { guild, author, channel, content } = message;
const { guild, author, content } = message;
// If message length is below guild minimum length
if (content.length < guildDB.credits.minimumLength) return;
// Check if user has a timeout
const isTimeout = await timeouts.findOne({
guildId: guild?.id,
userId: author?.id,
timeoutId: "2022-03-15-17-42",
});
if (isTimeout) {
return logger?.verbose(
`User: ${author?.tag} (${author?.id}) in guild: ${guild?.name} (${guild?.id}) is on timeout for credits`
);
}
userDB.credits += guildDB.credits.rate;
await userDB
.save()
.then(async () => {
return logger?.verbose(
`User: ${author?.tag} (${author?.id}) in guild: ${guild?.name} (${guild?.id})credits incremented`
);
})
.catch(async (error: any) => {
return logger?.error(error);
});
await timeouts.create({
guildId: guild?.id,
userId: author.id,
timeoutId: "2022-03-15-17-42",
});
// If user is not on timeout
if (!isTimeout) {
// Add credits to user
setTimeout(async () => {
logger?.verbose(
`User: ${author?.tag} (${author?.id}) in guild: ${guild?.name} (${guild?.id}) timeout removed for points`
);
userDB.credits += guildDB.credits.rate;
await userDB
.save()
.then(async () => {
// Send debug message
await logger.debug(
`Guild: ${guild?.id} User: ${author.id} Channel: ${channel.id} credits add ${guildDB.credits.rate} balance: ${userDB.credits}`
);
})
.catch(async (e: any) => {
// Send error message
await logger.error(e);
});
// Create a timeout for the user
await timeouts.create({
await timeouts.deleteOne({
guildId: guild?.id,
userId: author.id,
userId: author?.id,
timeoutId: "2022-03-15-17-42",
});
setTimeout(async () => {
// Send debug message
await logger.debug(
`Guild: ${guild?.id} User: ${author.id} Channel: ${
channel.id
} has not talked within last ${
guildDB.credits.timeout / 1000
} seconds, credits can be given`
);
// When timeout is out, remove it from the database
await timeouts.deleteOne({
guildId: guild?.id,
userId: author.id,
timeoutId: "2022-03-15-17-42",
});
}, guildDB.credits.timeout);
} else {
// Send debug message
await logger.debug(
`Guild: ${guild?.id} User: ${author.id} Channel: ${
channel.id
} has talked within last ${
guildDB.credits.timeout / 1000
} seconds, no credits given`
);
}
}, guildDB.credits.timeout);
};

View file

@ -3,68 +3,50 @@ import timeouts from "../../../database/schemas/timeout";
import { Message } from "discord.js";
export default async (guildDB: any, userDB: any, message: Message) => {
const { author, guild, channel, content } = message;
const { author, guild, content } = message;
// If message length is below guild minimum length
if (content.length < guildDB.points.minimumLength) return;
// Check if user has a timeout
const isTimeout = await timeouts.findOne({
guildId: guild?.id,
userId: author.id,
timeoutId: "2022-03-15-17-41",
});
// If user is not on timeout
if (!isTimeout) {
// Add points to user
userDB.points += guildDB.points.rate;
if (isTimeout) {
return logger?.verbose(
`User: ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id}) is on timeout for points`
);
}
await userDB
.save()
.then(async () => {
// Send debug message
await logger.debug(
`Guild: ${guild?.id} User: ${author.id} Channel: ${channel.id} points add: ${guildDB.points.rate} balance: ${userDB.points}`
);
})
.catch(async (e: any) => {
// Send error message
await logger.error(e);
});
userDB.points += guildDB.points.rate;
// Create a timeout for the user
await timeouts.create({
await userDB
.save()
.then(async () => {
return logger?.verbose(
`User: ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id}) points incremented`
);
})
.catch(async (error: any) => {
logger?.error(error);
});
await timeouts.create({
guildId: guild?.id,
userId: author.id,
timeoutId: "2022-03-15-17-41",
});
setTimeout(async () => {
logger?.verbose(
`User: ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id}) timeout removed for points`
);
await timeouts.deleteOne({
guildId: guild?.id,
userId: author.id,
timeoutId: "2022-03-15-17-41",
});
setTimeout(async () => {
// Send debug message
await logger.debug(
`Guild: ${guild?.id} User: ${author.id} Channel: ${
channel.id
} has not talked within last ${
guildDB.points.timeout / 1000
} seconds, points can be given`
);
// When timeout is out, remove it from the database
await timeouts.deleteOne({
guildId: guild?.id,
userId: author.id,
timeoutId: "2022-03-15-17-41",
});
}, guildDB.points.timeout);
} else {
// Send debug message
await logger.debug(
`Guild: ${guild?.id} User: ${author.id} Channel: ${
channel.id
} has talked within last ${
guildDB.points.timeout / 1000
} seconds, no points given`
);
}
}, guildDB.points.timeout);
};

View file

@ -1,18 +1,21 @@
// Dependencies
import { Message } from "discord.js";
import logger from "../../logger";
import logger from "@logger";
// Modules
import counter from "./modules/counter";
export default {
name: "messageUpdate",
async execute(oldMessage: Message, newMessage: Message) {
const { author } = newMessage;
async execute(_oldMessage: Message, newMessage: Message) {
const { author, guild } = newMessage;
logger.debug({ oldMessage, newMessage });
logger?.verbose(
`Message update event fired by ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id})`
);
if (author?.bot) return;
if (author?.bot)
return logger?.verbose(`Message update event fired by bot`);
await counter(newMessage);
},

View file

@ -2,8 +2,8 @@
import { Message } from "discord.js";
// Models
import counterSchema from "../../../database/schemas/counter";
import logger from "../../../logger";
import counterSchema from "@schemas/counter";
import logger from "@logger";
export default async (message: Message) => {
const { guild, channel, author, content } = message;
@ -13,16 +13,23 @@ export default async (message: Message) => {
channelId: channel?.id,
});
if (counter === null) return;
if (counter === null)
return logger?.verbose(
`No counter found for guild: ${guild?.name} (${guild?.id})`
);
const { word } = counter;
if (content === word) return;
if (content === word)
return logger?.verbose(
`User: ${author?.tag} (${author?.id}) in guild: ${guild?.name} (${guild?.id}) said the counter word: ${word}`
);
await message
?.delete()
?.then(async () => {
await channel?.send(`${author} said **${word}**.`);
logger?.verbose(`${author} said ${word} in ${channel}`);
})
?.catch(async (error) => {
logger.error(new Error(error));
?.catch(async (error: any) => {
logger?.error(error);
});
};

View file

@ -11,14 +11,16 @@ export default {
name: "ready",
once: true,
async execute(client: Client) {
logger.info(`Successfully logged into discord user: ${client?.user?.tag}!`);
logger?.info(`${client.user?.tag} (${client.user?.id}) is ready`);
await updatePresence(client);
await devMode(client);
await deployCommands();
const guilds = client.guilds.cache;
guilds.map(async (guild) => {
logger.debug({ name: guild.name, members: guild.memberCount });
client?.guilds?.cache?.forEach((guild) => {
logger?.info(
`${client.user?.tag} (${client.user?.id}) is in guild: ${guild.name} (${guild.id})`
);
});
},
};

View file

@ -8,7 +8,7 @@ export default async (client: Client) => {
fs.readdir("./src/plugins", async (error: any, plugins: any) => {
if (error) {
return logger?.error(new Error(error));
return logger?.error(`Error reading plugins: ${error}`);
}
await Promise.all(
@ -19,9 +19,8 @@ export default async (client: Client) => {
plugin?.default?.data?.name,
plugin?.default
);
logger?.debug(
`Successfully loaded plugin: ${plugin?.default?.data?.name} from ${plugin.default?.metadata?.author}`
);
logger?.verbose(`Loaded plugin: ${pluginName}`);
})
);
});

View file

@ -21,9 +21,7 @@ export default async () => {
pluginList.push(plugin.default.data.toJSON());
logger?.debug(
`Successfully deployed plugin: ${plugin?.default?.data?.name} from ${plugin.default?.metadata?.author}`
);
logger?.verbose(`Loaded plugin: ${pluginName} for deployment`);
})
);
@ -34,7 +32,7 @@ export default async () => {
body: pluginList,
})
.then(async () => {
logger.info("Successfully registered application commands.");
logger?.info(`Successfully deployed plugins to Discord`);
})
.catch(async (err: any) => {
logger.error(err);
@ -46,7 +44,7 @@ export default async () => {
body: pluginList,
})
.then(async () =>
logger.info("Successfully registered guild application commands.")
logger?.info(`Successfully deployed guild plugins to Discord`)
)
.catch(async (err: any) => {
logger.error(err);

View file

@ -1,5 +1,6 @@
import fs from "fs"; // fs
import { Client } from "discord.js"; // discord.js
import logger from "@logger";
export default async (client: Client) => {
const eventFiles = fs.readdirSync("./src/events");
@ -10,10 +11,12 @@ export default async (client: Client) => {
client.once(event.default.name, (...args) =>
event.default.execute(...args)
);
logger?.verbose(`Loaded event: ${event.default.name}`);
} else {
client.on(event.default.name, (...args) =>
event.default.execute(...args)
);
logger?.verbose(`Loaded event: ${event.default.name}`);
}
}
};

View file

@ -1,24 +0,0 @@
// TODO This file will make sure that all guilds always has at least one entry in all collections with "guildId"
import apis from "../database/schemas/api";
import guilds from "../database/schemas/guild";
import logger from "../logger";
import { Guild } from "discord.js";
export default async (guild: Guild) => {
const api = await apis.findOne({ guildId: guild.id });
const guildData = await guilds.findOne({ guildId: guild.id });
if (!api) {
apis.create({ guildId: guild.id });
logger.debug(`Guild: ${guild.id} added api collection`);
} else {
logger.debug(`Guild: ${guild.id} already in api collection`);
}
if (!guildData) {
guilds.create({ guildId: guild.id });
logger.debug(`Guild: ${guild.id} added guild collection`);
} else {
logger.debug(`Guild: ${guild.id} already in guild collection`);
}
};

View file

@ -1,34 +0,0 @@
import users from "../database/schemas/user";
import logger from "../logger";
import { Guild, User } from "discord.js";
export default async (user: User, guild: Guild) => {
const userData = await users.findOne({ userId: user.id, guildId: guild.id });
if (!userData) {
users
.create({ userId: user.id, guildId: guild.id })
.then(async () => {
await logger.debug(`User: ${user.id} added user collection`);
})
.catch(async (e) => {
await logger.error(
`User: ${user.id} failed to added user collection ${e}`
);
});
} else {
logger.debug(`User: ${user.id} already in user collection`);
}
// HOW TO ITERATE
//
// const guilds = client.guilds.cache;
// await guilds.map(async (guild) => {
// await guild.members.fetch().then(async (members) => {
// await members.forEach(async (member) => {
// const { user } = member;
// dbMemberFix(user, guild);
// });
// });
// await dbGuildFix(guild);
// });
};

View file

@ -8,8 +8,12 @@ import { devMode, guildId } from "@config/other";
export default async (client: Client) => {
if (!devMode) {
client?.application?.commands?.set([], guildId).then(async () => {
logger.verbose(`Removed all guild based commands from ${guildId}`);
return client?.application?.commands?.set([], guildId).then(async () => {
return logger?.verbose(
`Development commands disabled for guild: ${guildId}`
);
});
}
return logger?.verbose(`Development commands enabled for guild: ${guildId}`);
};

View file

@ -1,61 +1,74 @@
import guilds from "../database/schemas/guild";
import users from "../database/schemas/user";
import apis from "../database/schemas/api";
import counters from "../database/schemas/counter";
import shopRoles from "../database/schemas/shopRole";
import timeouts from "../database/schemas/timeout";
import guildSchema from "@schemas/guild";
import userSchema from "@schemas/user";
import apiSchema from "@schemas/api";
import counterSchema from "@schemas/counter";
import shopRoleSchema from "@schemas/shopRole";
import timeoutSchema from "@schemas/timeout";
import logger from "../logger";
import logger from "@logger";
import { Guild } from "discord.js";
export default async (guild: Guild) => {
guilds
await guildSchema
.deleteMany({ guildId: guild.id })
.then(async () => {
logger.debug(`Successfully deleted guild: ${guild.id}`);
return logger?.verbose(`Deleted guild: ${guild.id}`);
})
.catch(async (e) => {
logger.error(`Failed to delete guild: ${guild.id} ${e}`);
.catch(async (error) => {
logger?.error(`Error deleting guild: ${guild.id} - ${error}`);
});
users
await userSchema
.deleteMany({ guildId: guild.id })
.then(async () => {
logger.debug(`Successfully deleted guild: ${guild.id}'s users`);
logger?.verbose(`Deleted users for guild: ${guild.id} from database`);
})
.catch(async (e) => {
logger.error(`Failed to delete guild: ${guild.id}'s users ${e}`);
.catch(async (error) => {
logger?.error(`Error deleting users for guild: ${guild.id} - ${error}`);
});
apis
await apiSchema
.deleteMany({ guildId: guild.id })
.then(async () => {
logger.debug(`Successfully deleted guild: ${guild.id}'s apis`);
logger?.verbose(`Deleted apis for guild: ${guild.id} from database`);
})
.catch(async (e) => {
logger.error(`Failed to delete guild: ${guild.id}'s apis ${e}`);
.catch(async (error) => {
logger?.error(`Error deleting apis for guild: ${guild.id} - ${error}`);
});
counters
await counterSchema
.deleteMany({ guildId: guild.id })
.then(async () => {
logger.debug(`Successfully deleted guild: ${guild.id}'s counters`);
logger?.verbose(`Deleted counters for guild: ${guild.id} from database`);
})
.catch(async (e) => {
logger.error(`Failed to delete guild: ${guild.id}'s counters ${e}`);
.catch(async (error) => {
logger?.error(
`Error deleting counters for guild: ${guild.id} - ${error}`
);
});
shopRoles
await shopRoleSchema
.deleteMany({ guildId: guild.id })
.then(async () => {
logger.debug(`Successfully deleted guild: ${guild.id}'s shop roles`);
logger?.verbose(
`Deleted shop roles for guild: ${guild.id} from database`
);
})
.catch(async (e) => {
logger.error(`Failed to delete guild: ${guild.id}'s shop roles ${e}`);
.catch(async (error) => {
logger?.error(
`Error deleting shop roles for guild: ${guild.id} - ${error}`
);
});
timeouts
await timeoutSchema
.deleteMany({ guildId: guild.id })
.then(async () => {
logger.debug(`Successfully deleted guild: ${guild.id}'s timeouts`);
logger?.verbose(`Deleted timeouts for guild: ${guild.id} from database`);
})
.catch(async (e) => {
logger.error(`Failed to delete guild: ${guild.id}'s timeouts ${e}`);
.catch(async (error) => {
logger?.error(
`Error deleting timeouts for guild: ${guild.id} - ${error}`
);
});
};

View file

@ -1,13 +1,18 @@
import users from "../database/schemas/user";
import userSchema from "@schemas/user";
import logger from "../logger";
import logger from "@logger";
import { Guild, User } from "discord.js";
export default async (user: User, guild: Guild) => {
await users
await userSchema
.deleteOne({ userId: user?.id, guildId: guild?.id })
.then(async () =>
logger.debug(`Guild: ${guild?.id} User: ${user?.id} deleted successfully`)
);
.then(async () => {
logger?.verbose(`Deleted user: ${user?.id} from guild: ${guild?.id}`);
})
.catch(async (error) => {
logger?.error(
`Error deleting user: ${user?.id} from guild: ${guild?.id} - ${error}`
);
});
};

View file

@ -2,10 +2,10 @@
import { Guild } from "discord.js";
// Models
import guildSchema from "../database/schemas/guild";
import guildSchema from "@schemas/guild";
// Handlers
import logger from "../logger";
import logger from "@logger";
// Function
export default async (guild: Guild) => {
@ -16,12 +16,10 @@ export default async (guild: Guild) => {
await newGuildObj
.save()
.then(async () => {
logger.debug(
`Guild: ${guild.id} has successfully been added to the database.`
);
logger?.verbose(`Created guild: ${guild.id}`);
})
.catch(async (err: any) => {
logger.error(err);
.catch(async (error) => {
logger?.error(`Error creating guild: ${guild.id} - ${error}`);
});
return newGuildObj;

View file

@ -2,10 +2,10 @@
import { Guild, User } from "discord.js";
// Models
import userSchema from "../database/schemas/user";
import userSchema from "@schemas/user";
// Handlers
import logger from "../logger";
import logger from "@logger";
// Function
export default async (user: User, guild: Guild) => {
@ -22,12 +22,12 @@ export default async (user: User, guild: Guild) => {
await newUserObj
.save()
.then(async () => {
logger.debug(
`Member: ${user.id} has successfully been added to the database.`
);
logger?.verbose(`Created user: ${user.id} for guild: ${guild.id}`);
})
.catch(async (err: any) => {
logger.error(err);
.catch(async (error) => {
logger?.error(
`Error creating user: ${user.id} for guild: ${guild.id} - ${error}`
);
});
return newUserObj;

View file

@ -1,3 +0,0 @@
import pluralize from "./pluralize";
export default { pluralize };

View file

@ -1,2 +1,7 @@
export default (count: number, noun: string, suffix?: string) =>
`${count} ${noun}${count !== 1 ? suffix || "s" : ""}`;
import logger from "@root/logger";
export default (count: number, noun: string, suffix?: string) => {
const result = `${count} ${noun}${count !== 1 ? suffix || "s" : ""}`;
logger?.verbose(`Pluralized ${count} to ${result}`);
return result;
};

View file

@ -18,22 +18,22 @@ export default async function saveUser(data: any, data2: any) {
); // 100 - 1000 random Number generator
data.save((_: any) =>
_
? logger.error(
? logger?.error(
`ERROR Occurred while saving data (saveUser) \n${"=".repeat(
50
)}\n${`${_}\n${"=".repeat(50)}`}`
)
: "No Error"
: logger?.verbose(`Saved user: ${data.id} (saveUser)`)
);
if (data2) {
data2.save((_: any) =>
_
? logger.error(
? logger?.error(
`ERROR Occurred while saving data (saveUser) \n${"=".repeat(
50
)}\n${`${_}\n${"=".repeat(50)}`}`
)
: "No Error"
: logger?.verbose(`Saved user: ${data2.id} (saveUser)`)
);
}
},

View file

@ -1,5 +1,8 @@
import logger from "@logger";
export default function sleep(milliseconds: any) {
return new Promise((resolve) => {
setTimeout(resolve, milliseconds);
logger?.verbose(`Sleeping for ${milliseconds} milliseconds`);
});
}

View file

@ -1,13 +1,14 @@
// Dependencies
import { Client } from "discord.js";
import logger from "@logger";
// Function
export default async (client: Client) => {
// Set client status
const status = `${client?.guilds?.cache?.size} guilds.`;
client?.user?.setPresence({
activities: [
{ type: "WATCHING", name: `${client?.guilds?.cache?.size} guilds` },
],
activities: [{ type: "WATCHING", name: status }],
status: "online",
});
logger?.verbose(`Updated client presence to: ${status}`);
};

View file

@ -1,135 +1,143 @@
import i18next from "i18next";
import logger from "@logger";
export default async () => {
await i18next.init({
lng: "en", // if you're using a language detector, do not define the lng option
// debug: true,
fallbackLng: "en",
resources: {
en: {
general: { not_available: "Not Available" },
commands: {
credits: {
general: {
credits_one: "{{count}} credit",
credits_other: "{{count}} credits",
await i18next
.init({
lng: "en", // if you're using a language detector, do not define the lng option
// debug: true,
fallbackLng: "en",
resources: {
en: {
general: { not_available: "Not Available" },
commands: {
credits: {
general: {
credits_one: "{{count}} credit",
credits_other: "{{count}} credits",
},
addons: {
balance: { embed: { title: "Credits" } },
gift: { embed: { title: "Gift" } },
},
},
addons: {
balance: { embed: { title: "Credits" } },
gift: { embed: { title: "Gift" } },
},
},
reputation: {
addons: {
give: {
version01: {
embed: {
title: ":medal: Reputation",
description:
"You have given reputation within the last day, you can not repute now!",
reputation: {
addons: {
give: {
version01: {
embed: {
title: ":medal: Reputation",
description:
"You have given reputation within the last day, you can not repute now!",
},
},
},
version02: {
embed: {
title: ":medal: Reputation",
description:
"You have given {{user}} a {{type}} reputation!",
version02: {
embed: {
title: ":medal: Reputation",
description:
"You have given {{user}} a {{type}} reputation!",
},
},
},
version03: {
embed: {
title: ":medal: Reputation",
description: "You can not repute yourself.",
version03: {
embed: {
title: ":medal: Reputation",
description: "You can not repute yourself.",
},
},
},
},
},
},
profile: {
addons: {
view: {
embed: {
title: "Profile",
reputation: "Reputation (Global)",
level: "Level (Guild)",
points: "Points (Guild)",
credits: "Credits (Guild)",
language_code: "Language Code (Global)",
profile: {
addons: {
view: {
embed: {
title: "Profile",
reputation: "Reputation (Global)",
level: "Level (Guild)",
points: "Points (Guild)",
credits: "Credits (Guild)",
language_code: "Language Code (Global)",
},
},
},
settings: {
embed: {
title: "Profile",
description: "Following settings is set",
fields: { language: "Language" },
settings: {
embed: {
title: "Profile",
description: "Following settings is set",
fields: { language: "Language" },
},
},
},
},
},
},
},
sv: {
general: { not_available: "Otillgänglig" },
commands: {
credits: {
general: {
credits_one: "{{count}} krona",
credits_other: "{{count}} kronor",
sv: {
general: { not_available: "Otillgänglig" },
commands: {
credits: {
general: {
credits_one: "{{count}} krona",
credits_other: "{{count}} kronor",
},
addons: {
balance: { embed: { title: "Krediter" } },
gift: { embed: { title: "Gåva" } },
},
},
addons: {
balance: { embed: { title: "Krediter" } },
gift: { embed: { title: "Gåva" } },
},
},
reputation: {
addons: {
give: {
version01: {
embed: {
title: ":medal: Omdöme",
description:
"Du har redan gett omdöme inom den senaste dagen, du kan inte ge ett omdöme just nu!",
reputation: {
addons: {
give: {
version01: {
embed: {
title: ":medal: Omdöme",
description:
"Du har redan gett omdöme inom den senaste dagen, du kan inte ge ett omdöme just nu!",
},
},
},
version02: {
embed: {
title: ":medal: Omdöme",
description: "Du har gett {{user}} ett {{type}} omdöme!",
version02: {
embed: {
title: ":medal: Omdöme",
description: "Du har gett {{user}} ett {{type}} omdöme!",
},
},
},
version03: {
embed: {
title: ":medal: Omdöme",
description: "Du kan inte ge dig själv ett omdöme.",
version03: {
embed: {
title: ":medal: Omdöme",
description: "Du kan inte ge dig själv ett omdöme.",
},
},
},
},
},
},
profile: {
addons: {
view: {
embed: {
title: "Profil",
reputation: "Omdöme (Globalt)",
level: "Nivå (Server)",
points: "Poäng (Server)",
credits: "Krediter (Server)",
language_code: "Språkkod (Globalt)",
profile: {
addons: {
view: {
embed: {
title: "Profil",
reputation: "Omdöme (Globalt)",
level: "Nivå (Server)",
points: "Poäng (Server)",
credits: "Krediter (Server)",
language_code: "Språkkod (Globalt)",
},
},
},
settings: {
embed: {
title: "Profil",
description: "Följande inställningar är satta",
fields: { language: "Språk" },
settings: {
embed: {
title: "Profil",
description: "Följande inställningar är satta",
fields: { language: "Språk" },
},
},
},
},
},
},
},
},
});
})
.then(async () => {
logger?.verbose(`i18next initialized`);
})
.catch(async (error) => {
logger?.error(`i18next failed to initialize: ${error}`);
});
};

View file

@ -2,19 +2,24 @@
import { CommandInteraction } from "discord.js";
import { SlashCommandBuilder } from "@discordjs/builders";
import logger from "@logger";
import modules from "@root/plugins/counters/modules";
export default {
metadata: { author: "Zyner" },
data: new SlashCommandBuilder()
.setName("counters")
.setDescription("Manage counters.")
.setDescription("View guild counters")
.addSubcommand(modules.view.data),
async execute(interaction: CommandInteraction) {
const { options } = interaction;
if (options?.getSubcommand() === "view") {
logger?.verbose(`Executing view subcommand`);
return modules.view.execute(interaction);
}
logger?.verbose(`Unknown subcommand ${options?.getSubcommand()}`);
},
};

View file

@ -17,11 +17,13 @@ export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("view")
.setDescription("View a counter's count.")
.setDescription(`View a guild counter`)
.addChannelOption((option) =>
option
.setName("channel")
.setDescription("The counter channel you want to view.")
.setDescription(
`The channel that contains the counter you want to view`
)
.setRequired(true)
.addChannelType(ChannelType.GuildText as number)
);
@ -41,7 +43,7 @@ export default {
embeds: [
new MessageEmbed()
.setTitle("[:1234:] Counters (View)")
.setDescription(`${discordChannel} is not a counting channel!`)
.setDescription(`No counter found for channel ${discordChannel}!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({
@ -57,7 +59,7 @@ export default {
new MessageEmbed()
.setTitle("[:1234:] Counters (View)")
.setDescription(
`${discordChannel} is currently at number ${counter?.counter}.`
`Viewing counter for channel ${discordChannel} with count ${counter.counter}.`
)
.setTimestamp(new Date())
.setColor(successColor)

View file

@ -2,6 +2,8 @@
import { SlashCommandBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js";
import logger from "@logger";
// Modules
import modules from "@root/plugins/credits/modules";
@ -18,19 +20,25 @@ export default {
const { options } = interaction;
if (options?.getSubcommand() === "balance") {
logger?.verbose(`Executing balance subcommand`);
return modules.balance.execute(interaction);
}
if (options?.getSubcommand() === "gift") {
logger?.verbose(`Executing gift subcommand`);
return modules.gift.execute(interaction);
}
if (options?.getSubcommand() === "top") {
logger?.verbose(`Executing top command`);
return modules.top.execute(interaction);
}
if (options?.getSubcommand() === "work") {
logger?.verbose(`Executing work command`);
return modules.work.execute(interaction);
}
logger?.verbose(`Unknown subcommand ${options?.getSubcommand()}`);
},
};

View file

@ -2,6 +2,8 @@
import { CommandInteraction, MessageEmbed } from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import logger from "@logger";
// Configurations
import {
errorColor,
@ -19,13 +21,13 @@ export default {
return (
command
.setName("balance")
.setDescription("Check a user's balance.")
.setDescription(`View a user's balance`)
// User
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user whose balance you want to check.")
.setDescription(`The user whose balance you want to view`)
)
);
},
@ -35,11 +37,13 @@ export default {
const discordUser = options?.getUser("user");
if (guild === null) {
logger?.verbose(`Guild is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Balance)")
.setDescription(`We can not find your guild!`)
.setDescription(`You can only use this command in a guild!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -50,13 +54,13 @@ export default {
const userObj = await fetchUser(discordUser || user, guild);
if (userObj === null) {
logger?.verbose(`User not found`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Balance)")
.setDescription(
`We can not find ${discordUser || "you"} in our database!`
)
.setDescription(`Could not find user ${discordUser || user}`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -65,15 +69,14 @@ export default {
}
if (userObj.credits === null) {
logger?.verbose(`User has no credits`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Balance)")
.setDescription(
`We can not find credits for ${
discordUser || "you"
} in our database!`
)
.setDescription(`${userObj} has no credits!`)
.setDescription(`${discordUser || user} has no credits!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -81,15 +84,17 @@ export default {
});
}
logger?.verbose(`Found user ${discordUser || user}`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Balance)")
.setDescription(
`${discordUser || "You"} have ${pluralize(
`${userObj} has ${userObj.credits} ${pluralize(
userObj.credits,
"credit"
)}.`
`credit`
)}!`
)
.setTimestamp(new Date())
.setColor(successColor)

View file

@ -10,14 +10,13 @@ import {
} from "@config/embed";
// Handlers
import logger from "../../../../logger";
import logger from "@logger";
// Helpers
import saveUser from "../../../../helpers/saveUser";
import pluralize from "../../../../helpers/pluralize";
import saveUser from "@helpers/saveUser";
// Models
import fetchUser from "../../../../helpers/fetchUser";
import fetchUser from "@helpers/fetchUser";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
@ -25,17 +24,17 @@ export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("gift")
.setDescription("Gift someone credits from your credits.")
.setDescription(`Gift a user credits`)
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user you want to pay.")
.setDescription("The user you want to gift credits to.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will pay.")
.setDescription("The amount of credits you want to gift.")
.setRequired(true)
)
.addStringOption((option) =>
@ -50,6 +49,8 @@ export default {
const optionReason = options?.getString("reason");
if (guild === null) {
logger?.verbose(`Guild is null`);
return interaction.editReply({
embeds: [
new MessageEmbed()
@ -63,6 +64,8 @@ export default {
}
if (optionUser === null) {
logger?.verbose(`User not found`);
return interaction.editReply({
embeds: [
new MessageEmbed()
@ -82,6 +85,8 @@ export default {
const toUserDB = await fetchUser(optionUser, guild);
if (fromUserDB === null) {
logger?.verbose(`User not found`);
return interaction.editReply({
embeds: [
new MessageEmbed()
@ -97,6 +102,8 @@ export default {
}
if (toUserDB === null) {
logger?.verbose(`User not found`);
return interaction.editReply({
embeds: [
new MessageEmbed()
@ -113,6 +120,8 @@ export default {
// If receiver is same as sender
if (optionUser?.id === user?.id) {
logger?.verbose(`User is same as sender`);
return interaction.editReply({
embeds: [
new MessageEmbed()
@ -127,6 +136,8 @@ export default {
// If amount is null
if (optionAmount === null) {
logger?.verbose(`Amount is null`);
return interaction.editReply({
embeds: [
new MessageEmbed()
@ -141,6 +152,8 @@ export default {
// If amount is zero or below
if (optionAmount <= 0) {
logger?.verbose(`Amount is zero or below`);
return interaction.editReply({
embeds: [
new MessageEmbed()
@ -155,6 +168,8 @@ export default {
// If user has below gifting amount
if (fromUserDB?.credits < optionAmount) {
logger?.verbose(`User has below gifting amount`);
return interaction.editReply({
embeds: [
new MessageEmbed()
@ -171,6 +186,8 @@ export default {
// If toUserDB has no credits
if (toUserDB === null) {
logger?.verbose(`User has no credits`);
return interaction.editReply({
embeds: [
new MessageEmbed()
@ -203,28 +220,23 @@ export default {
new MessageEmbed()
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(
`You received ${pluralize(
optionAmount,
"credit"
)} from ${user}${
`You have received ${optionAmount} credits from ${
user?.tag
} with reason ${
optionReason ? ` with reason: ${optionReason}` : ""
}. Your new credits is ${pluralize(
toUserDB?.credits,
"credit"
)}.`
}!`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
})
.catch(async () =>
logger.debug(`Can not send DM to user ${optionUser?.id}`)
.catch(async (error) =>
logger?.error(`[Gift] Error sending DM to user: ${error}`)
);
// Send debug message
logger.debug(
`Guild: ${guild?.id} User: ${user?.id} gift sent from: ${user?.id} to: ${optionUser?.id}`
logger?.verbose(
`[Gift] Successfully gifted ${optionAmount} credits to ${optionUser?.tag}`
);
return interaction.editReply({
@ -232,12 +244,7 @@ export default {
new MessageEmbed()
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(
`You sent ${pluralize(optionAmount, "credit")} to ${optionUser}${
optionReason ? ` with reason: ${optionReason}` : ""
}. Your new credits is ${pluralize(
fromUserDB?.credits,
"credit"
)}.`
`Successfully gifted ${optionAmount} credits to ${optionUser?.tag}!`
)
.setTimestamp(new Date())
.setColor(successColor)

View file

@ -12,7 +12,7 @@ import pluralize from "@helpers/pluralize";
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command.setName("top").setDescription("Check the top balance.");
return command.setName("top").setDescription(`View the top users`);
},
execute: async (interaction: CommandInteraction) => {
// Get all users in the guild
@ -29,19 +29,16 @@ export default {
// Create entry object
const entry = (x: any, index: number) =>
`**Top ${index + 1}** - <@${x?.userId}> ${pluralize(
x?.credits,
"credit"
)}`;
`${index + 1}. <@${x?.userId}> - ${pluralize(x?.credits, "credit")}`;
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Top)")
.setDescription(
`Below are the top ten.
`Top 10 users with the most credits.
${topTen?.map((x, index) => entry(x, index))?.join("\n")}`
${topTen.map(entry).join("\n")}`
)
.setTimestamp(new Date())
.setColor(successColor)

View file

@ -13,13 +13,12 @@ import logger from "@logger";
import timeoutSchema from "@schemas/timeout";
// Helpers
import pluralize from "@helpers/pluralize";
import fetchUser from "@helpers/fetchUser";
import fetchGuild from "@helpers/fetchGuild";
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command.setName("work").setDescription("Work for credits.");
return command.setName("work").setDescription(`Work to earn credits`);
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
@ -35,77 +34,22 @@ export default {
timeoutId: "2022-03-15-19-16",
});
if (guild === null) return;
if (guild === null) {
return logger?.verbose(`Guild is null`);
}
const guildDB = await fetchGuild(guild);
// If user is not on timeout
if (!isTimeout) {
const creditsEarned = chance.integer({
min: 0,
max: guildDB?.credits?.workRate,
});
const userDB = await fetchUser(user, guild);
if (userDB === null) return;
userDB.credits += creditsEarned;
await userDB?.save()?.then(async () => {
logger?.debug(`Credits added to user: ${user?.id}`);
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Work)")
.setDescription(
`You have earned ${pluralize(creditsEarned, "credit")}.`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
});
// Create a timeout for the user
await timeoutSchema?.create({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-03-15-19-16",
});
setTimeout(async () => {
logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} has not worked within the last ${
guildDB?.credits?.workTimeout / 1000
} seconds, work can be done`
);
// When timeout is out, remove it from the database
await timeoutSchema?.deleteOne({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-03-15-19-16",
});
}, guildDB?.credits?.workTimeout);
} else {
// Send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has worked within last day, no work can be done`
);
if (isTimeout) {
logger?.verbose(`User ${user?.id} is on timeout`);
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Work)")
.setDescription(
`You have worked within the last ${
guildDB?.credits?.workTimeout / 1000
} seconds, you can not work now!`
`You can not work while on timeout, please wait ${guildDB?.credits.workTimeout} seconds.`
)
.setTimestamp(new Date())
.setColor(successColor)
@ -113,5 +57,53 @@ export default {
],
});
}
const creditsEarned = chance.integer({
min: 0,
max: guildDB?.credits?.workRate,
});
const userDB = await fetchUser(user, guild);
if (userDB === null) {
return logger?.verbose(`User not found`);
}
userDB.credits += creditsEarned;
await userDB?.save()?.then(async () => {
logger?.verbose(
`User ${userDB?.userId} worked and earned ${creditsEarned} credits`
);
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Work)")
.setDescription(`You worked and earned ${creditsEarned} credits`)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
});
// Create a timeout for the user
await timeoutSchema?.create({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-03-15-19-16",
});
setTimeout(async () => {
logger?.verbose(`Removing timeout for user ${user?.id}`);
// When timeout is out, remove it from the database
await timeoutSchema?.deleteOne({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-03-15-19-16",
});
}, guildDB?.credits?.workTimeout);
},
};

View file

@ -2,6 +2,8 @@
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js";
import logger from "@logger";
// Modules
import moduleCreate from "./modules/create";
import moduleDelete from "./modules/delete";
@ -11,7 +13,7 @@ export default {
data: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("counters")
.setDescription("Manage your guild's counters.")
.setDescription("Manage guild counters.")
.addSubcommand(moduleCreate.data)
.addSubcommand(moduleDelete.data);
},
@ -19,11 +21,17 @@ export default {
const { options } = interaction;
if (options?.getSubcommand() === "create") {
logger?.verbose(`Executing create subcommand`);
return moduleCreate.execute(interaction);
}
if (options?.getSubcommand() === "delete") {
logger?.verbose(`Executing delete subcommand`);
return moduleDelete.execute(interaction);
}
logger?.verbose(`Unknown subcommand ${options?.getSubcommand()}`);
},
};

View file

@ -15,7 +15,7 @@ import {
import logger from "@logger";
// Models
import counterSchema from "../../../../../../database/schemas/counter";
import counterSchema from "@schemas/counter";
// Function
export default {
@ -26,24 +26,24 @@ export default {
.addChannelOption((option) =>
option
.setName("channel")
.setDescription("The channel you want to add a counter to.")
.setDescription("The channel to send the counter to.")
.setRequired(true)
.addChannelType(ChannelType.GuildText as number)
)
.addStringOption((option) =>
option
.setName("word")
.setDescription("The word you want to count.")
.setDescription("The word to use for the counter.")
.setRequired(true)
)
.addNumberOption((option) =>
option
.setName("start")
.setDescription("The count that the counter will start at.")
.setDescription("The starting value of the counter.")
);
},
execute: async (interaction: CommandInteraction) => {
const { options, guild, user } = interaction;
const { options, guild } = interaction;
const discordChannel = options?.getChannel("channel");
const countingWord = options?.getString("word");
@ -59,9 +59,7 @@ export default {
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Counters (Create)")
.setDescription(
`${discordChannel} is already a counting channel, currently it's counting ${counter.word}!`
)
.setDescription(`A counter already exists for this channel.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -77,19 +75,13 @@ export default {
counter: startValue || 0,
})
.then(async () => {
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} added ${discordChannel?.id} as a counter using word "${countingWord}" for counting.`
);
logger?.verbose(`Created counter`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Counters (Create)")
.setDescription(
`${discordChannel} is now counting when hearing word ${countingWord} and it starts at number ${
startValue || 0
}.`
)
.setDescription(`Created counter for ${discordChannel}`)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),

View file

@ -13,7 +13,7 @@ import {
import logger from "@logger";
// Models
import counterSchema from "../../../../../../database/schemas/counter";
import counterSchema from "@schemas/counter";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { ChannelType } from "discord-api-types/v10";
@ -22,17 +22,17 @@ export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("delete")
.setDescription("Delete a counter from your guild.")
.setDescription(`Delete a counter from your guild.`)
.addChannelOption((option) =>
option
.setName("channel")
.setDescription("The channel that you want to delete a counter from.")
.setDescription("The channel to delete the counter from.")
.setRequired(true)
.addChannelType(ChannelType.GuildText as number)
);
},
execute: async (interaction: CommandInteraction) => {
const { options, guild, user } = interaction;
const { options, guild } = interaction;
const discordChannel = options?.getChannel("channel");
@ -42,11 +42,13 @@ export default {
});
if (counter === null) {
logger?.verbose(`Counter is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Counters (Delete)")
.setDescription(`${discordChannel} is not a counting channel!`)
.setDescription(`The counter for this channel does not exist.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -60,22 +62,21 @@ export default {
channelId: discordChannel?.id,
})
?.then(async () => {
logger?.verbose(`Counter deleted`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Counters (Delete)")
.setDescription(
`${discordChannel} is no longer an counting channel.`
)
.setDescription(`The counter for this channel has been deleted.`)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
})
.catch(async (error) => {
logger?.error(`Error deleting counter: ${error}`);
});
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} removed ${discordChannel?.id} as a counter.`
);
},
};

View file

@ -2,6 +2,8 @@
import { CommandInteraction } from "discord.js";
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
import logger from "@logger";
// Modules
import moduleGive from "./modules/give";
import moduleSet from "./modules/set";
@ -13,7 +15,7 @@ export default {
data: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("credits")
.setDescription("Manage guild member's credits.")
.setDescription("Manage the credits of a user.")
.addSubcommand(moduleGive.data)
.addSubcommand(moduleSet.data)
.addSubcommand(moduleTake.data)
@ -23,19 +25,29 @@ export default {
const { options } = interaction;
if (options?.getSubcommand() === "give") {
logger?.verbose(`Executing give subcommand`);
return moduleGive.execute(interaction);
}
if (options?.getSubcommand() === "set") {
logger?.verbose(`Executing set subcommand`);
return moduleSet.execute(interaction);
}
if (options?.getSubcommand() === "take") {
logger?.verbose(`Executing take subcommand`);
return moduleTake.execute(interaction);
}
if (options?.getSubcommand() === "transfer") {
logger?.verbose(`Executing transfer subcommand`);
return moduleTransfer.execute(interaction);
}
logger?.verbose(`No subcommand found`);
},
};

View file

@ -24,34 +24,36 @@ export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("give")
.setDescription("Give credits to a user")
.setDescription("Give credits to a user.")
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user you want to pay.")
.setDescription("The user to give credits to.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will pay.")
.setDescription(`The amount of credits to give.`)
.setRequired(true)
);
},
execute: async (interaction: CommandInteraction) => {
// Destructure
const { guild, user, options } = interaction;
const { guild, options } = interaction;
const discordReceiver = options?.getUser("user");
const creditAmount = options?.getInteger("amount");
// If amount option is null
if (creditAmount === null) {
logger?.verbose(`Amount is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(`We could not read your requested amount!`)
.setDescription(`You must provide an amount.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -61,11 +63,13 @@ export default {
// If amount is zero or below
if (creditAmount <= 0) {
logger?.verbose(`Amount is zero or below`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(`You can not give zero credits or below!`)
.setDescription(`You must provide an amount greater than zero.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -74,11 +78,13 @@ export default {
}
if (discordReceiver === null) {
logger?.verbose(`Discord receiver is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(`We could not read receiver user!`)
.setDescription(`You must provide a user.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -86,11 +92,13 @@ export default {
});
}
if (guild === null) {
logger?.verbose(`Guild is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(`We could not read your guild!`)
.setDescription(`You must be in a guild.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -101,13 +109,13 @@ export default {
const toUser = await fetchUser(discordReceiver, guild);
if (toUser === null) {
logger?.verbose(`To user is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(
`We could not read your receiver user from our database!`
)
.setDescription(`The user you provided could not be found.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -120,9 +128,7 @@ export default {
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(
`We could not find credits for ${discordReceiver} in our database!`
)
.setDescription(`The user you provided does not have any credits.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -135,21 +141,14 @@ export default {
// Save toUser
await toUser?.save()?.then(async () => {
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} gave ${
discordReceiver?.id
} ${pluralize(creditAmount, "credit")}.`
);
logger?.verbose(`Saved toUser`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(
`We have given ${discordReceiver}, ${pluralize(
creditAmount,
"credit"
)}.`
`Successfully gave ${pluralize(creditAmount, "credit")}`
)
.setTimestamp(new Date())
.setColor(successColor)

View file

@ -13,7 +13,6 @@ import {
import logger from "@logger";
// Helpers
import pluralize from "@helpers/pluralize";
// Models
import fetchUser from "@helpers/fetchUser";
@ -24,33 +23,35 @@ export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("set")
.setDescription("Set credits to a user")
.setDescription("Set the amount of credits a user has.")
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user you want to set credits on.")
.setDescription("The user to set the amount of credits for.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will set.")
.setDescription(`The amount of credits to set.`)
.setRequired(true)
);
},
execute: async (interaction: CommandInteraction) => {
const { options, user, guild } = interaction;
const { options, guild } = interaction;
const discordUser = options.getUser("user");
const creditAmount = options.getInteger("amount");
// If amount is null
if (creditAmount === null) {
logger?.verbose(`Amount is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(`We could not read your requested amount!`)
.setDescription(`You must provide an amount.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -59,11 +60,13 @@ export default {
}
if (discordUser === null) {
logger?.verbose(`User is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(`We could not read your requested user!`)
.setDescription(`You must provide a user.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -71,11 +74,13 @@ export default {
});
}
if (guild === null) {
logger?.verbose(`Guild is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(`We could not read your guild!`)
.setDescription(`You must provide a guild.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -88,13 +93,13 @@ export default {
// If toUser does not exist
if (toUser === null) {
logger?.verbose(`User does not exist`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(
`We could not read your requested user from our database!`
)
.setDescription(`The user you provided does not exist.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -104,13 +109,13 @@ export default {
// If toUser.credits does not exist
if (toUser?.credits === null) {
logger?.verbose(`User does not have any credits`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(
`We could not find credits for ${discordUser} in our database!`
)
.setDescription(`The user you provided does not have any credits.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -123,21 +128,14 @@ export default {
// Save toUser
await toUser?.save()?.then(async () => {
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} set ${
discordUser?.id
} to ${pluralize(creditAmount, "credit")}.`
);
logger?.verbose(`Saved user`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(
`We have set ${discordUser} to ${pluralize(
creditAmount,
"credit"
)}.`
`Set **${discordUser}**'s credits to **${creditAmount}**.`
)
.setTimestamp(new Date())
.setColor(successColor)

View file

@ -24,23 +24,23 @@ export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("take")
.setDescription("Take credits from a user")
.setDescription("Take credits from a user.")
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user you want to take credits from.")
.setDescription("The user to take credits from.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will take.")
.setDescription(`The amount of credits to take.`)
.setRequired(true)
);
},
execute: async (interaction: CommandInteraction) => {
// Destructure
const { guild, user, options } = interaction;
const { guild, options } = interaction;
// User option
const optionUser = options?.getUser("user");
@ -50,11 +50,13 @@ export default {
// If amount is null
if (optionAmount === null) {
logger?.verbose(`Amount is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(`We could not read your requested amount!`)
.setDescription(`You must provide an amount.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -64,11 +66,13 @@ export default {
// If amount is zero or below
if (optionAmount <= 0) {
logger?.verbose(`Amount is zero or below`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(`We could not take zero credits or below!`)
.setDescription(`You must provide an amount greater than zero.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -77,11 +81,13 @@ export default {
}
if (optionUser === null) {
logger?.verbose(`Discord receiver is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(`We could not read your requested user!`)
.setDescription(`You must provide a user.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -89,11 +95,13 @@ export default {
});
}
if (guild === null) {
logger?.verbose(`Guild is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(`We could not read your guild!`)
.setDescription(`You must be in a guild.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -106,13 +114,13 @@ export default {
// If toUser does not exist
if (toUser === null) {
logger?.verbose(`ToUser is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(
`We could not read your requested user from our database!`
)
.setDescription(`The user you provided does not exist.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -122,13 +130,13 @@ export default {
// If toUser.credits does not exist
if (toUser?.credits === null) {
logger?.verbose(`ToUser.credits is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(
`We could not find credits for ${optionUser} in our database!`
)
.setDescription(`The user you provided does not have credits.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -141,21 +149,14 @@ export default {
// Save toUser
await toUser?.save()?.then(async () => {
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} set ${
optionUser?.id
} to ${pluralize(optionAmount, "credit")}.`
);
logger?.verbose(`Saved toUser`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(
`We have taken ${pluralize(
optionAmount,
"credit"
)} from ${optionUser}.`
`Took ${pluralize(optionAmount, "credit")} from ${optionUser}.`
)
.setTimestamp(new Date())
.setColor(successColor)

View file

@ -13,7 +13,6 @@ import {
import logger from "@logger";
// Helpers
import pluralize from "@helpers/pluralize";
import saveUser from "@helpers/saveUser";
// Models
@ -25,29 +24,29 @@ export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("transfer")
.setDescription("Transfer credits from a user to another user.")
.setDescription("Transfer credits from one user to another.")
.addUserOption((option) =>
option
.setName("from")
.setDescription("The user you want to take credits from.")
.setDescription("The user to transfer credits from.")
.setRequired(true)
)
.addUserOption((option) =>
option
.setName("to")
.setDescription("The user you want to give credits to.")
.setDescription("The user to transfer credits to.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will transfer.")
.setDescription(`The amount of credits to transfer.`)
.setRequired(true)
);
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
const { guild, options, user } = interaction;
const { guild, options } = interaction;
// Get options
const optionFromUser = options?.getUser("from");
@ -56,11 +55,13 @@ export default {
// If amount is null
if (optionAmount === null) {
logger?.verbose(`Amount is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(`We could not read your requested amount!`)
.setDescription(`You must provide an amount.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -69,11 +70,13 @@ export default {
}
if (guild === null) {
logger?.verbose(`Guild is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(`We could not read your guild!`)
.setDescription(`You must be in a guild.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -81,11 +84,13 @@ export default {
});
}
if (optionFromUser === null) {
logger?.verbose(`From user is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(`We could not read your requested from user!`)
.setDescription(`You must provide a user to transfer from.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -93,11 +98,13 @@ export default {
});
}
if (optionToUser === null) {
logger?.verbose(`To user is null`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(`We could not read your requested to user!`)
.setDescription(`You must provide a user to transfer to.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -113,12 +120,14 @@ export default {
// If toUser does not exist
if (fromUser === null) {
logger?.verbose(`From user does not exist`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(
`We could not read your requested from user from our database!`
`The user you provided to transfer from does not exist.`
)
.setTimestamp(new Date())
.setColor(errorColor)
@ -129,12 +138,14 @@ export default {
// If toUser.credits does not exist
if (!fromUser?.credits) {
logger?.verbose(`From user does not have credits`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(
`We could not find credits for ${optionFromUser} in our database!`
`The user you provided to transfer from does not have credits.`
)
.setTimestamp(new Date())
.setColor(errorColor)
@ -145,12 +156,14 @@ export default {
// If toUser does not exist
if (toUser === null) {
logger?.verbose(`To user does not exist`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(
`We could not read your requested to user from our database!`
`The user you provided to transfer to does not exist.`
)
.setTimestamp(new Date())
.setColor(errorColor)
@ -161,12 +174,14 @@ export default {
// If toUser.credits does not exist
if (toUser?.credits === null) {
logger?.verbose(`To user does not have credits`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(
`We could not find credits for ${optionToUser} in our database!`
`The user you provided to transfer to does not have credits.`
)
.setTimestamp(new Date())
.setColor(errorColor)
@ -183,23 +198,13 @@ export default {
// Save users
await saveUser(fromUser, toUser)?.then(async () => {
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} transferred ${pluralize(
optionAmount,
"credit"
)} from ${optionFromUser?.id} to ${optionToUser?.id}.`
);
logger?.verbose(`Saved users`);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(
`We have sent ${pluralize(
optionAmount,
"credit"
)} from ${optionFromUser} to ${optionToUser}.`
)
.setDescription(`Transferred ${optionAmount} credits.`)
.addFields(
{
name: `${optionFromUser?.username} Balance`,

View file

@ -8,13 +8,14 @@ import { errorColor, footerText, footerIcon } from "@config/embed";
// Groups
import credits from "./groups/credits";
import counters from "./groups/counters";
import logger from "@logger";
// Function
export default {
metadata: { author: "Zyner" },
data: new SlashCommandBuilder()
.setName("manage")
.setDescription("Manage your guild.")
.setDescription("Manage the bot.")
.addSubcommandGroup(counters.data)
.addSubcommandGroup(credits.data),
@ -28,7 +29,7 @@ export default {
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage")
.setDescription(`You do not have permission to manage this!`)
.setDescription(`You do not have the permission to manage the bot.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
@ -37,11 +38,17 @@ export default {
}
if (options?.getSubcommandGroup() === "credits") {
logger?.verbose(`Subcommand group is credits`);
return credits.execute(interaction);
}
if (options?.getSubcommandGroup() === "counters") {
logger?.verbose(`Subcommand group is counters`);
return counters.execute(interaction);
}
logger?.verbose(`Subcommand group is not credits or counters`);
},
};

View file

@ -6,7 +6,7 @@ import { CommandInteraction } from "discord.js";
import view from "./modules/view";
// Handlers
import logger from "../../logger";
import logger from "@logger";
// Function
export default {
@ -25,20 +25,14 @@ export default {
)
),
async execute(interaction: CommandInteraction) {
// Destructure
const { options, guild, user, commandName } = interaction;
const { options } = interaction;
// Module - View
if (options?.getSubcommand() === "view") {
// Execute Module - View
logger?.verbose(`Executing view subcommand`);
return view(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
logger?.verbose(`No subcommand found`);
},
};

View file

@ -7,6 +7,8 @@ import { successColor, footerText, footerIcon } from "@config/embed";
// Models
import fetchUser from "@helpers/fetchUser";
import logger from "@logger";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure
@ -20,7 +22,9 @@ export default async (interaction: CommandInteraction) => {
`${target ? target?.id : user?.id}`
);
if (guild === null) return;
if (guild === null) {
return logger?.verbose(`Guild is null`);
}
// User Information
const userObj = await fetchUser(discordUser, guild);

View file

@ -13,41 +13,17 @@ export default {
metadata: { author: "Zyner" },
data: new SlashCommandBuilder()
.setName("reputation")
.setDescription("Give reputation.")
.addSubcommand((subcommand) =>
subcommand
.setName("give")
.setDescription("Give reputation to a user")
.addUserOption((option) =>
option
.setName("target")
.setDescription("The user you want to repute.")
.setRequired(true)
)
.addStringOption((option) =>
option
.setName("type")
.setDescription("What type of reputation you want to repute")
.setRequired(true)
.addChoice("Positive", "positive")
.addChoice("Negative", "negative")
)
),
.setDescription("Manage reputation.")
.addSubcommand(give.data),
async execute(interaction: CommandInteraction) {
// Destructure
const { options, guild, user, commandName } = interaction;
const { options } = interaction;
// Module - Give
if (options?.getSubcommand() === "give") {
// Execute Module - Give
await give(interaction);
logger?.verbose(`Executing give subcommand`);
await give.execute(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
logger?.verbose(`No subcommand found`);
},
};

View file

@ -17,123 +17,145 @@ import logger from "@logger";
// Models
import timeoutSchema from "@schemas/timeout";
import fetchUser from "@helpers/fetchUser";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure
const { options, user, guild } = interaction;
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("give")
.setDescription("Give reputation to a user")
.addUserOption((option) =>
option
.setName("target")
.setDescription("The user you want to repute.")
.setRequired(true)
)
.addStringOption((option) =>
option
.setName("type")
.setDescription("What type of reputation you want to repute")
.setRequired(true)
.addChoice("Positive", "positive")
.addChoice("Negative", "negative")
);
},
execute: async (interaction: CommandInteraction) => {
// Destructure
const { options, user, guild } = interaction;
// Target option
const optionTarget = options?.getUser("target");
// Target option
const optionTarget = options?.getUser("target");
// Type information
const optionType = options?.getString("type");
// Type information
const optionType = options?.getString("type");
if (guild === null) return;
if (guild === null) {
return logger?.verbose(`Guild is null`);
}
// User information
const userObj = await fetchUser(user, guild);
// User information
const userObj = await fetchUser(user, guild);
if (userObj === null) return;
if (userObj === null) {
return logger?.verbose(`User is null`);
}
// Check if user has a timeout
const isTimeout = await timeoutSchema?.findOne({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-04-10-16-42",
});
// Check if user has a timeout
const isTimeout = await timeoutSchema?.findOne({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-04-10-16-42",
});
// If user is not on timeout
if (isTimeout) {
logger?.verbose(`User is on timeout`);
return interaction?.editReply({
embeds: [
{
title: ":loudspeaker: Reputation [Give]",
description: `You cannot give reputation while on timeout, please wait ${timeout} seconds.`,
timestamp: new Date(),
color: errorColor,
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
}
// If user is not on timeout
if (!isTimeout) {
// Do not allow self reputation
if (optionTarget?.id === user?.id) {
// Embed object
const embed = {
title: ":loudspeaker: Reputation [Give]",
description: "You can not repute yourself.",
timestamp: new Date(),
color: errorColor,
footer: {
iconURL: footerIcon,
text: footerText,
},
};
logger?.verbose(`User is trying to give reputation to self`);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
return interaction?.editReply({
embeds: [
{
title: ":loudspeaker: Reputation [Give]",
description: `You cannot give reputation to yourself.`,
timestamp: new Date(),
color: errorColor,
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
}
// If type is positive
if (optionType === "positive") {
logger?.verbose(`User is giving positive reputation`);
userObj.reputation += 1;
}
// If type is negative
else if (optionType === "negative") {
logger?.verbose(`User is giving negative reputation`);
userObj.reputation -= 1;
}
// Save user
await userObj?.save()?.then(async () => {
// Embed object
const embed = {
title: ":loudspeaker: Reputation [Give]",
description: `You have given ${optionTarget} a ${optionType} reputation!`,
timestamp: new Date(),
color: successColor,
footer: {
iconURL: footerIcon,
text: footerText,
},
};
logger?.verbose(`User reputation has been updated`);
// Log debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has given ${optionTarget?.id} a ${optionType} reputation.`
);
// Create a timeout for the user
await timeoutSchema?.create({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-04-10-16-42",
});
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
return interaction?.editReply({
embeds: [
{
title: ":loudspeaker: Reputation [Give]",
description: `You have given reputation to ${optionTarget}`,
timestamp: new Date(),
color: successColor,
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
});
setTimeout(async () => {
// send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has not repute within last ${timeout} seconds, reputation can be given`
);
logger?.verbose(`Removing timeout`);
// When timeout is out, remove it from the database
await timeoutSchema?.deleteOne({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-04-10-16-42",
});
}, timeout);
} else {
// Create embed object
const embed = {
title: ":loudspeaker: Reputation [Give]",
description: `You have given reputation within the last ${timeout} seconds, you can not repute now!`,
timestamp: new Date(),
color: errorColor,
footer: {
iconURL: footerIcon,
text: footerText,
},
};
// Log debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has repute within last ${timeout} seconds, no reputation can be given`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
},
};

View file

@ -5,7 +5,7 @@ import { Permissions, CommandInteraction } from "discord.js";
import { errorColor, footerText, footerIcon } from "@config/embed";
// Handlers
import logger from "../../../logger";
import logger from "@logger";
// Modules
import pterodactyl from "./modules/pterodactyl";
@ -18,57 +18,49 @@ export default {
data: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("guild")
.setDescription("Manage guild settings.")
.setDescription("Guild settings.")
.addSubcommand(pterodactyl.data)
.addSubcommand(credits.data)
.addSubcommand(points.data);
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
const { memberPermissions, options, commandName, user, guild } =
interaction;
const { memberPermissions, options } = interaction;
// Check permission
if (!memberPermissions?.has(Permissions?.FLAGS?.MANAGE_GUILD)) {
// Create embed object
const embed = {
title: ":tools: Settings - Guild",
color: errorColor,
description: "You do not have permission to manage this!",
timestamp: new Date(),
footer: {
iconURL: footerIcon as string,
text: footerText as string,
},
};
logger?.verbose(`User does not have permission to execute command.`);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
return interaction?.editReply({
embeds: [
{
title: ":tools: Settings - Guild",
color: errorColor,
description: "You do not have permission to use this command.",
timestamp: new Date(),
footer: {
iconURL: footerIcon as string,
text: footerText as string,
},
},
],
});
}
// Module - Pterodactyl
if (options?.getSubcommand() === "pterodactyl") {
// Execute Module - Pterodactyl
logger?.verbose(`Executing pterodactyl subcommand`);
return pterodactyl.execute(interaction);
}
} else if (options?.getSubcommand() === "credits") {
logger?.verbose(`Executing credits subcommand`);
// Module - Credits
else if (options?.getSubcommand() === "credits") {
// Execute Module - Credits
return credits.execute(interaction);
}
} else if (options?.getSubcommand() === "points") {
logger?.verbose(`Executing points subcommand`);
// Module - Points
else if (options?.getSubcommand() === "points") {
// Execute Module - Points
return points.execute(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
logger?.verbose(`No subcommand found`);
},
};

View file

@ -16,7 +16,7 @@ export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("credits")
.setDescription("Credits")
.setDescription(`Credits`)
.addBooleanOption((option) =>
option.setName("status").setDescription("Should credits be enabled?")
)
@ -36,17 +36,17 @@ export default {
.addNumberOption((option) =>
option
.setName("work-timeout")
.setDescription("Timeout between work schedules (milliseconds).")
.setDescription("Timeout between work schedules (seconds).")
)
.addNumberOption((option) =>
option
.setName("timeout")
.setDescription("Timeout between earning credits (milliseconds).")
.setDescription("Timeout between earning credits (seconds).")
);
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
const { guild, user, options } = interaction;
const { guild, options } = interaction;
// Get options
const status = options?.getBoolean("status");
@ -61,7 +61,9 @@ export default {
guildId: guild?.id,
});
if (guildDB === null) return;
if (guildDB === null) {
return logger?.verbose(`Guild is null`);
}
// Modify values
guildDB.credits.status =
@ -78,57 +80,54 @@ export default {
// Save guild
await guildDB?.save()?.then(async () => {
// Embed object
const embed = {
title: ":tools: Settings - Guild [Credits]",
description: "Following settings is set!",
color: successColor,
fields: [
logger?.verbose(`Guild saved`);
return interaction?.editReply({
embeds: [
{
name: "🤖 Status",
value: `${guildDB?.credits?.status}`,
inline: true,
},
{
name: "📈 Rate",
value: `${guildDB?.credits?.rate}`,
inline: true,
},
{
name: "📈 Work Rate",
value: `${guildDB?.credits?.workRate}`,
inline: true,
},
{
name: "🔨 Minimum Length",
value: `${guildDB?.credits?.minimumLength}`,
inline: true,
},
{
name: "⏰ Timeout",
value: `${guildDB?.credits?.timeout}`,
inline: true,
},
{
name: "⏰ Work Timeout",
value: `${guildDB?.credits?.workTimeout}`,
inline: true,
title: ":tools: Settings - Guild [Credits]",
description: `Credits settings updated.`,
color: successColor,
fields: [
{
name: "🤖 Status",
value: `${guildDB?.credits?.status}`,
inline: true,
},
{
name: "📈 Rate",
value: `${guildDB?.credits?.rate}`,
inline: true,
},
{
name: "📈 Work Rate",
value: `${guildDB?.credits?.workRate}`,
inline: true,
},
{
name: "🔨 Minimum Length",
value: `${guildDB?.credits?.minimumLength}`,
inline: true,
},
{
name: "⏰ Timeout",
value: `${guildDB?.credits?.timeout}`,
inline: true,
},
{
name: "⏰ Work Timeout",
value: `${guildDB?.credits?.workTimeout}`,
inline: true,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
// Send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user.id} has changed credit details.`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
});
});
},
};

View file

@ -5,10 +5,10 @@ import { CommandInteraction } from "discord.js";
import { successColor, footerText, footerIcon } from "@config/embed";
// Handlers
import logger from "../../../../logger";
import logger from "@logger";
// Models
import guildSchema from "../../../../database/schemas/guild";
import guildSchema from "@schemas/guild";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
@ -36,7 +36,7 @@ export default {
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
const { options, guild, user } = interaction;
const { options, guild } = interaction;
// Get options
const status = options?.getBoolean("status");
@ -49,7 +49,9 @@ export default {
guildId: guild?.id,
});
if (guildDB === null) return;
if (guildDB === null) {
return logger?.verbose(`Guild not found in database.`);
}
// Modify values
guildDB.points.status = status !== null ? status : guildDB?.points?.status;
@ -61,47 +63,44 @@ export default {
// Save guild
await guildDB?.save()?.then(async () => {
// Create embed object
const embed = {
title: ":hammer: Settings - Guild [Points]",
description: "Following settings is set!",
color: successColor,
fields: [
logger?.verbose(`Guild points updated.`);
return interaction?.editReply({
embeds: [
{
name: "🤖 Status",
value: `${guildDB?.points?.status}`,
inline: true,
},
{
name: "📈 Rate",
value: `${guildDB?.points?.rate}`,
inline: true,
},
{
name: "🔨 Minimum Length",
value: `${guildDB?.points?.minimumLength}`,
inline: true,
},
{
name: "⏰ Timeout",
value: `${guildDB?.points?.timeout}`,
inline: true,
title: ":hammer: Settings - Guild [Points]",
description: `Points settings updated.`,
color: successColor,
fields: [
{
name: "🤖 Status",
value: `${guildDB?.points?.status}`,
inline: true,
},
{
name: "📈 Rate",
value: `${guildDB?.points?.rate}`,
inline: true,
},
{
name: "🔨 Minimum Length",
value: `${guildDB?.points?.minimumLength}`,
inline: true,
},
{
name: "⏰ Timeout",
value: `${guildDB?.points?.timeout}`,
inline: true,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
// Send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has changed credit details.`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
});
});
},
};

View file

@ -5,11 +5,11 @@ import { CommandInteraction } from "discord.js";
import { successColor, footerText, footerIcon } from "@config/embed";
// Handlers
import logger from "../../../../logger";
import logger from "@logger";
// Models
import apiSchema from "../../../../database/schemas/api";
import encryption from "../../../../handlers/encryption";
import apiSchema from "@schemas/api";
import encryption from "@handlers/encryption";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
@ -19,18 +19,21 @@ export default {
.setName("pterodactyl")
.setDescription("Controlpanel.gg")
.addStringOption((option) =>
option.setName("url").setDescription("The api url").setRequired(true)
option
.setName("url")
.setDescription(`Controlpanel.gg URL`)
.setRequired(true)
)
.addStringOption((option) =>
option
.setName("token")
.setDescription("The api token")
.setDescription(`Controlpanel.gg Token`)
.setRequired(true)
);
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
const { options, guild, user } = interaction;
const { options, guild } = interaction;
// Get options
const url = options?.getString("url");
@ -44,25 +47,22 @@ export default {
{ new: true, upsert: true }
)
.then(async () => {
// Embed object
const embed = {
title: ":hammer: Settings - Guild [Pterodactyl]",
color: successColor,
description: "Pterodactyl settings is saved!",
timestamp: new Date(),
footer: {
iconURL: footerIcon as string,
text: footerText as string,
},
};
logger?.verbose(`Updated API credentials.`);
// Send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has changed api credentials.`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
return interaction?.editReply({
embeds: [
{
title: ":hammer: Settings - Guild [Pterodactyl]",
color: successColor,
description: `Successfully updated API credentials.`,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
});
},
};

View file

@ -7,7 +7,7 @@ import guildGroup from "./guild";
import userGroup from "./user";
// Handlers
import logger from "../../logger";
import logger from "@logger";
// Function
export default {
@ -19,25 +19,20 @@ export default {
.addSubcommandGroup(userGroup.data),
async execute(interaction: CommandInteraction) {
// Destructure
const { options, commandName, user, guild } = interaction;
const { options } = interaction;
// Group - Guild
if (options.getSubcommandGroup() === "guild") {
// Execute Group - Guild
await guildGroup.execute(interaction);
}
// Group - User
else if (options.getSubcommandGroup() === "user") {
// Execute Group - User
await userGroup.execute(interaction);
logger.verbose(`Executing guild subcommand`);
return guildGroup.execute(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
if (options.getSubcommandGroup() === "user") {
logger.verbose(`Executing user subcommand`);
return userGroup.execute(interaction);
}
logger.verbose(`No subcommand group found`);
},
};

View file

@ -3,7 +3,7 @@ import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js";
// Handlers
import logger from "../../../logger";
import logger from "@logger";
// Modules
import appearance from "./modules/appearance";
@ -13,35 +13,29 @@ export default {
data: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("user")
.setDescription("Manage user settings.")
.setDescription("User settings.")
.addSubcommand((command) =>
command
.setName("appearance")
.setDescription("Manage your appearance")
.setDescription("User appearance settings.")
.addStringOption((option) =>
option
.setName("language")
.setDescription("Configure your language")
.setDescription("Set the language.")
.addChoice("English", "en")
.addChoice("Swedish", "sv")
)
);
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
const { guild, user, options, commandName } = interaction;
const { options } = interaction;
// Module - Appearance
if (options?.getSubcommand() === "appearance") {
// Execute Module - Appearance
logger?.verbose(`Executing appearance subcommand`);
await appearance(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
logger?.verbose(`No subcommand found`);
},
};

View file

@ -5,10 +5,10 @@ import { CommandInteraction } from "discord.js";
import { successColor, footerText, footerIcon } from "@config/embed";
// Handlers
import logger from "../../../../logger";
import logger from "@logger";
// Models
import fetchUser from "../../../../helpers/fetchUser";
import fetchUser from "@helpers/fetchUser";
// Function
export default async (interaction: CommandInteraction) => {
@ -18,43 +18,44 @@ export default async (interaction: CommandInteraction) => {
// Get options
const language = options?.getString("language");
if (guild === null) return;
if (guild === null) {
return logger?.verbose(`Guild is null`);
}
// Get user object
const userDB = await fetchUser(user, guild);
if (userDB === null) return;
if (userDB === null) {
return logger?.verbose(`User is null`);
}
// Modify values
userDB.language = language !== null ? language : userDB?.language;
// Save guild
await userDB?.save()?.then(async () => {
// Embed object
const embed = {
title: ":hammer: Settings - User [Appearance]",
description: "Following settings is set!",
color: successColor,
fields: [
logger?.verbose(`Updated user language.`);
return interaction?.editReply({
embeds: [
{
name: "🏳️‍🌈 Language",
value: `${userDB?.language}`,
inline: true,
title: ":hammer: Settings - User [Appearance]",
description: "Successfully updated user settings.",
color: successColor,
fields: [
{
name: "🏳️‍🌈 Language",
value: `${userDB?.language}`,
inline: true,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
// Send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has changed appearance settings.`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
});
});
};

View file

@ -16,70 +16,24 @@ export default {
metadata: { author: "Zyner" },
data: new SlashCommandBuilder()
.setName("shop")
.setDescription("Purchase some items using your credits.")
.addSubcommand((subcommand) =>
subcommand
.setName("pterodactyl")
.setDescription("Buy pterodactyl power.")
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("How much credits you want to withdraw.")
)
)
.addSubcommandGroup((group) =>
group
.setName("roles")
.setDescription("Manage custom roles.")
.addSubcommand((command) =>
command
.setName("buy")
.setDescription("Buy a custom role")
.addStringOption((option) =>
option
.setName("name")
.setDescription("Name of the role you wish to purchase.")
)
.addStringOption((option) =>
option
.setName("color")
.setDescription(
"Color of the role you wish to purchase (For example RED or BLUE or GREEN)."
)
)
)
.addSubcommand((command) =>
command
.setName("cancel")
.setDescription("Cancel a custom role")
.addRoleOption((option) =>
option
.setName("role")
.setDescription("Name of the role you wish to cancel.")
)
)
),
.setDescription("Shop for credits and custom roles.")
.addSubcommand(pterodactyl.data)
.addSubcommandGroup(roles.data),
async execute(interaction: CommandInteraction) {
// Destructure
const { options, commandName, user, guild } = interaction;
const { options } = interaction;
// Module - Pterodactyl
if (options?.getSubcommand() === "pterodactyl") {
// Execute Module - Pterodactyl
return pterodactyl(interaction);
logger.verbose(`Executing pterodactyl subcommand`);
return pterodactyl.execute(interaction);
}
// Group - Roles
else if (options?.getSubcommandGroup() === "roles") {
// Execute Group - Roles
return roles(interaction);
if (options?.getSubcommandGroup() === "roles") {
logger?.verbose(`Subcommand group is roles`);
return roles.execute(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
logger?.verbose(`No subcommand found.`);
},
};

View file

@ -21,225 +21,261 @@ import pluralize from "@helpers/pluralize";
// Models
import apiSchema from "@schemas/api";
import fetchUser from "@helpers/fetchUser";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
export default async (interaction: CommandInteraction) => {
const { options, guild, user, client } = interaction;
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("pterodactyl")
.setDescription("Buy pterodactyl power.")
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("How much credits you want to withdraw.")
);
},
execute: async (interaction: CommandInteraction) => {
const { options, guild, user, client } = interaction;
// Get options
const optionAmount = options?.getInteger("amount");
// Get options
const optionAmount = options?.getInteger("amount");
// If amount is null
if (optionAmount === null) {
// Embed object
const embed = {
title: ":dollar: Credits [Gift]",
description: "We could not read your requested amount.",
color: errorColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
// If amount is null
if (optionAmount === null) {
logger?.verbose(`Amount is null.`);
// Send interaction reply
return interaction?.editReply({ embeds: [embed] });
}
if (guild === null) return;
// Get user object
const userDB = await fetchUser(user, guild);
if (userDB === null) return;
// Get DM user object
const dmUser = client?.users?.cache?.get(user?.id);
// Stop if amount or user credits is below 100
if ((optionAmount || userDB?.credits) < 100) {
const embed = {
title: ":shopping_cart: Shop [Pterodactyl]",
description: `You **can't** withdraw for __Pterodactyl__ below **100**.`,
color: errorColor,
fields: [
{
name: "Your balance",
value: `${pluralize(userDB?.credits, "credit")}`,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
return interaction?.editReply({ embeds: [embed] });
}
// Stop if amount or user credits is above 1.000.000
if ((optionAmount || userDB?.credits) > 1000000) {
const embed = {
title: ":shopping_cart: Shop [Pterodactyl]",
description: `You **can't** withdraw for __Pterodactyl__ above **1.000.000**.`,
color: errorColor,
fields: [
{
name: "Your balance",
value: `${pluralize(userDB?.credits, "credit")}`,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
return interaction?.editReply({ embeds: [embed] });
}
// Stop if user credits is below amount
if (userDB?.credits < optionAmount) {
const embed = {
title: ":shopping_cart: Shop [Pterodactyl]",
description: `You have **insufficient** credits.`,
color: errorColor,
fields: [
{
name: "Your balance",
value: `${pluralize(userDB?.credits, "credit")}`,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
return interaction?.editReply({ embeds: [embed] });
}
// Generate a unique voucher for the user
const code = uuidv4();
// Get api object
const apiCredentials = await apiSchema?.findOne({
guildId: guild?.id,
});
// Create a api instance
const api = axios?.create({
baseURL: apiCredentials?.url,
headers: {
Authorization: `Bearer ${encryption.decrypt(apiCredentials?.token)}`,
},
});
// Get shop URL
const shopUrl = apiCredentials?.url?.replace("/api", "/store");
// Make API request
await api
// Make a post request to the API
?.post("vouchers", {
uses: 1,
code,
credits: optionAmount || userDB?.credits,
memo: `${interaction?.createdTimestamp} - ${interaction?.user?.id}`,
})
// If successful
?.then(async () => {
// Create DM embed object
const dmEmbed = {
title: ":shopping_cart: Shop [Pterodactyl]",
description: `Redeem this voucher [here](${shopUrl})!`,
fields: [
{ name: "Code", value: `${code}`, inline: true },
return interaction?.editReply({
embeds: [
{
name: "Credits",
value: `${optionAmount || userDB?.credits}`,
inline: true,
},
],
color: successColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
// Create interaction embed object
const interactionEmbed = {
title: ":shopping_cart: Shop [Pterodactyl]",
description: "I have sent you the code in DM!",
color: successColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
// Withdraw amount from user credits
userDB.credits -= optionAmount || userDB?.credits;
// Save new credits
await userDB
?.save()
// If successful
?.then(async () => {
// Send debug message
logger?.debug(
`User: ${user?.username} redeemed: ${pluralize(
optionAmount,
"credit"
)}`
);
// Send DM message
await dmUser?.send({ embeds: [dmEmbed] });
// Send interaction reply
await interaction?.editReply({
embeds: [interactionEmbed],
});
})
// If error occurs
.catch(async (e: any) => {
logger?.error(e);
const embed = {
title: ":shopping_cart: Shop [Pterodactyl]",
description:
"Something went wrong while saving your credits, please try again later.",
title: ":dollar: Credits [Gift]",
description: "We could not read your requested amount.",
color: errorColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
return interaction?.editReply({ embeds: [embed] });
});
})
},
],
});
}
// If error occurs
.catch(async (e) => {
logger?.error(e);
const embed = {
title: ":shopping_cart: Shop [Pterodactyl]",
description: "Something went wrong, please try again later.",
color: errorColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
return interaction?.editReply({ embeds: [embed] });
if (guild === null) {
return logger?.verbose(`Guild is null`);
}
// Get user object
const userDB = await fetchUser(user, guild);
if (userDB === null) {
return logger?.verbose(`User is null`);
}
// Get DM user object
const dmUser = client?.users?.cache?.get(user?.id);
// Stop if amount or user credits is below 100
if ((optionAmount || userDB?.credits) < 100) {
logger?.verbose(`Amount or user credits is below 100.`);
return interaction?.editReply({
embeds: [
{
title: ":shopping_cart: Shop [Pterodactyl]",
description: `You **can't** withdraw for __Pterodactyl__ below **100**.`,
color: errorColor,
fields: [
{
name: "Your balance",
value: `${pluralize(userDB?.credits, "credit")}`,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
}
// Stop if amount or user credits is above 1.000.000
if ((optionAmount || userDB?.credits) > 1000000) {
logger?.verbose(`Amount or user credits is above 1.000.000.`);
return interaction?.editReply({
embeds: [
{
title: ":shopping_cart: Shop [Pterodactyl]",
description:
"You **can't** withdraw for __Pterodactyl__ above **1.000.000**.",
color: errorColor,
fields: [
{
name: "Your balance",
value: `${pluralize(userDB?.credits, "credit")}`,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
}
// Stop if user credits is below amount
if (userDB?.credits < optionAmount) {
logger?.verbose(`User credits is below amount.`);
return interaction?.editReply({
embeds: [
{
title: ":shopping_cart: Shop [Pterodactyl]",
description: `You have **insufficient** credits.`,
color: errorColor,
fields: [
{
name: "Your balance",
value: `${pluralize(userDB?.credits, "credit")}`,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
}
// Generate a unique voucher for the user
const code = uuidv4();
// Get api object
const apiCredentials = await apiSchema?.findOne({
guildId: guild?.id,
});
// Create a api instance
const api = axios?.create({
baseURL: apiCredentials?.url,
headers: {
Authorization: `Bearer ${encryption.decrypt(apiCredentials?.token)}`,
},
});
// Get shop URL
const shopUrl = apiCredentials?.url?.replace("/api", "/store");
// Make API request
await api
// Make a post request to the API
?.post("vouchers", {
uses: 1,
code,
credits: optionAmount || userDB?.credits,
memo: `${interaction?.createdTimestamp} - ${interaction?.user?.id}`,
})
// If successful
?.then(async () => {
logger?.verbose(`Successfully created voucher.`);
// Withdraw amount from user credits
userDB.credits -= optionAmount || userDB?.credits;
// Save new credits
await userDB
?.save()
// If successful
?.then(async () => {
logger?.verbose(`Successfully saved new credits.`);
await dmUser?.send({
embeds: [
{
title: ":shopping_cart: Shop [Pterodactyl]",
description: `Redeem this voucher [here](${shopUrl})!`,
fields: [
{ name: "Code", value: `${code}`, inline: true },
{
name: "Credits",
value: `${optionAmount || userDB?.credits}`,
inline: true,
},
],
color: successColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
return interaction?.editReply({
embeds: [
{
title: ":shopping_cart: Shop [Pterodactyl]",
description: "I have sent you the code in DM!",
color: successColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
})
// If error occurs
.catch(async (error) => {
logger?.verbose(`Error saving new credits. - ${error}`);
return interaction?.editReply({
embeds: [
{
title: ":shopping_cart: Shop [Pterodactyl]",
description: "Something went wrong.",
color: errorColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
});
})
// If error occurs
.catch(async (error: any) => {
logger?.verbose(`Error creating voucher. - ${error}`);
return interaction?.editReply({
embeds: [
{
title: ":shopping_cart: Shop [Pterodactyl]",
description: "Something went wrong.",
color: errorColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
});
},
};

View file

@ -1,4 +1,5 @@
// Dependencies
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js";
// Handlers
@ -9,26 +10,27 @@ import buy from "./modules/buy";
import cancel from "./modules/cancel";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure member
const { options, commandName, guild, user } = interaction;
export default {
data: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("roles")
.setDescription("Shop for custom roles.")
.addSubcommand(buy.data)
.addSubcommand(cancel.data);
},
execute: async (interaction: CommandInteraction) => {
const { options } = interaction;
// Module - Buy
if (options?.getSubcommand() === "buy") {
// Execute Module - Buy
await buy(interaction);
}
if (options?.getSubcommand() === "buy") {
logger.verbose(`Executing buy subcommand`);
// Module - Cancel
if (options?.getSubcommand() === "cancel") {
// Execute Module - Cancel
await cancel(interaction);
}
await buy.execute(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
if (options?.getSubcommand() === "cancel") {
logger.verbose(`Executing cancel subcommand`);
await cancel.execute(interaction);
}
},
};

View file

@ -16,88 +16,126 @@ import {
import shopRolesSchema from "@schemas/shopRole";
import guildSchema from "@schemas/guild";
import logger from "@logger";
// Helpers
import pluralize from "@helpers/pluralize";
import fetchUser from "@helpers/fetchUser";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
export default async (interaction: CommandInteraction) => {
const { options, guild, user, member } = interaction;
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("buy")
.setDescription("Buy a custom role.")
.addStringOption((option) =>
option
.setName("name")
.setDescription("Name of the role you wish to buy.")
)
.addStringOption((option) =>
option
.setName("color")
.setDescription("Color of the role you wish to buy.")
);
},
execute: async (interaction: CommandInteraction) => {
const { options, guild, user, member } = interaction;
const optionName = options?.getString("name");
const optionColor = options?.getString("color");
const optionName = options?.getString("name");
const optionColor = options?.getString("color");
// If amount is null
if (optionName === null) {
// Embed object
const embed = {
title: ":dollar: Shop - Roles [Buy]",
description: "We could not read your requested name.",
color: errorColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
// If amount is null
if (optionName === null) {
logger?.verbose(`Name is null.`);
// Send interaction reply
return interaction?.editReply({ embeds: [embed] });
}
await guild?.roles
.create({
name: optionName,
color: optionColor as ColorResolvable,
reason: `${user?.id} bought from shop`,
})
.then(async (role) => {
// Get guild object
const guildDB = await guildSchema?.findOne({
guildId: guild?.id,
});
const userDB = await fetchUser(user, guild);
if (userDB === null) return;
if (guildDB === null) return;
if (guildDB.shop === null) return;
const { pricePerHour } = guildDB.shop.roles;
userDB.credits -= pricePerHour;
await userDB?.save();
await shopRolesSchema?.create({
roleId: role?.id,
userId: user?.id,
guildId: guild?.id,
pricePerHour,
lastPayed: new Date(),
});
await (member?.roles as GuildMemberRoleManager)?.add(role?.id);
const embed = {
title: ":shopping_cart: Shop - Roles [Buy]",
description: `You have bought ${role?.name} for ${guildDB?.shop?.roles?.pricePerHour} per hour.`,
color: successColor,
fields: [
return interaction?.editReply({
embeds: [
{
name: "Your balance",
value: `${pluralize(userDB?.credits, "credit")}`,
title: ":dollar: Shop - Roles [Buy]",
description: "We could not read your requested name.",
color: errorColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
return interaction?.editReply({
embeds: [embed],
});
})
.catch(console.error);
}
await guild?.roles
.create({
name: optionName,
color: optionColor as ColorResolvable,
reason: `${user?.id} bought from shop`,
})
.then(async (role) => {
// Get guild object
const guildDB = await guildSchema?.findOne({
guildId: guild?.id,
});
const userDB = await fetchUser(user, guild);
if (userDB === null) {
return logger?.verbose(`User is null`);
}
if (guildDB === null) {
return logger?.verbose(`Guild is null`);
}
if (guildDB.shop === null) {
return logger?.verbose(`Shop is null`);
}
const { pricePerHour } = guildDB.shop.roles;
userDB.credits -= pricePerHour;
await userDB?.save();
await shopRolesSchema?.create({
roleId: role?.id,
userId: user?.id,
guildId: guild?.id,
pricePerHour,
lastPayed: new Date(),
});
await (member?.roles as GuildMemberRoleManager)?.add(role?.id);
logger?.verbose(`Role ${role?.name} was bought by ${user?.tag}`);
return interaction?.editReply({
embeds: [
{
title: ":shopping_cart: Shop - Roles [Buy]",
description: `You bought **${optionName}** for **${pluralize(
pricePerHour,
"credit"
)}**.`,
color: successColor,
fields: [
{
name: "Your balance",
value: `${pluralize(userDB?.credits, "credit")}`,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
})
.catch(async (error) => {
return logger?.verbose(`Role could not be created. ${error}`);
});
},
};

View file

@ -11,41 +11,55 @@ import {
// Models
import shopRolesSchema from "@schemas/shopRole";
import logger from "@logger";
// Helpers
import pluralize from "@helpers/pluralize";
import fetchUser from "@helpers/fetchUser";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
export default async (interaction: CommandInteraction) => {
const { options, guild, user, member } = interaction;
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("cancel")
.setDescription("Cancel a purchase.")
.addRoleOption((option) =>
option.setName("role").setDescription("Role you wish to cancel.")
);
},
execute: async (interaction: CommandInteraction) => {
const { options, guild, user, member } = interaction;
const optionRole = options.getRole("role");
const optionRole = options.getRole("role");
// If amount is null
if (optionRole === null) {
// Embed object
const embed = {
title: ":dollar: Shop - Roles [Cancel]",
description: "We could not read your requested role.",
color: errorColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
if (optionRole === null) {
logger?.verbose(`Role is null.`);
// Send interaction reply
return interaction?.editReply({ embeds: [embed] });
}
return interaction?.editReply({
embeds: [
{
title: ":dollar: Shop - Roles [Cancel]",
description: "We could not read your requested role.",
color: errorColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
}
const roleExist = await shopRolesSchema?.findOne({
guildId: guild?.id,
userId: user?.id,
roleId: optionRole?.id,
});
const roleExist = await shopRolesSchema?.findOne({
guildId: guild?.id,
userId: user?.id,
roleId: optionRole?.id,
});
if (roleExist === null) return;
if (roleExist) {
await (member?.roles as GuildMemberRoleManager)?.remove(optionRole?.id);
await guild?.roles
@ -53,7 +67,9 @@ export default async (interaction: CommandInteraction) => {
.then(async () => {
const userDB = await fetchUser(user, guild);
if (userDB === null) return;
if (userDB === null) {
return logger?.verbose(`User is null`);
}
await shopRolesSchema?.deleteOne({
roleId: optionRole?.id,
@ -61,26 +77,29 @@ export default async (interaction: CommandInteraction) => {
guildId: guild?.id,
});
const embed = {
title: ":shopping_cart: Shop - Roles [Cancel]",
description: `You have canceled ${optionRole.name}.`,
color: successColor,
fields: [
return interaction?.editReply({
embeds: [
{
name: "Your balance",
value: `${pluralize(userDB?.credits, "credit")}`,
title: ":shopping_cart: Shop - Roles [Cancel]",
description: `You have canceled ${optionRole.name}.`,
color: successColor,
fields: [
{
name: "Your balance",
value: `${pluralize(userDB?.credits, "credit")}`,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
return interaction?.editReply({
embeds: [embed],
});
})
.catch(console.error);
}
.catch(async (error) => {
return logger?.verbose(`Role could not be deleted. ${error}`);
});
},
};

View file

@ -16,50 +16,30 @@ export default {
data: new SlashCommandBuilder()
.setName("utilities")
.setDescription("Common utilities.")
.addSubcommand((subcommand) =>
subcommand
.setName("lookup")
.setDescription(
"Lookup a domain or ip. (Request sent over HTTP, proceed with caution!)"
)
.addStringOption((option) =>
option
.setName("query")
.setDescription("The query you want to look up.")
.setRequired(true)
)
)
.addSubcommand((subcommand) =>
subcommand.setName("about").setDescription("About this bot!)")
)
.addSubcommand((subcommand) =>
subcommand.setName("stats").setDescription("Check bot statistics!)")
),
.addSubcommand(lookup.data)
.addSubcommand(about.data)
.addSubcommand(stats.data),
async execute(interaction: CommandInteraction) {
// Destructure
const { options, guild, user, commandName } = interaction;
const { options } = interaction;
// Module - Lookup
if (options?.getSubcommand() === "lookup") {
// Execute Module - Lookup
return lookup(interaction);
}
// Module - About
else if (options?.getSubcommand() === "about") {
// Execute Module - About
return about(interaction);
}
// Module - Stats
else if (options?.getSubcommand() === "stats") {
// Execute Module - Stats
return stats(interaction);
logger.verbose(`Executing lookup subcommand`);
return lookup.execute(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
if (options?.getSubcommand() === "about") {
logger.verbose(`Executing about subcommand`);
return about.execute(interaction);
}
if (options?.getSubcommand() === "stats") {
logger.verbose(`Executing stats subcommand`);
return stats.execute(interaction);
}
logger.verbose(`No subcommand found.`);
},
};

View file

@ -5,22 +5,28 @@ import { CommandInteraction } from "discord.js";
import { successColor, footerText, footerIcon } from "@config/embed";
import { hosterName, hosterUrl } from "@config/other";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
export default async (interaction: CommandInteraction) => {
const interactionEmbed = {
title: ":hammer: Utilities [About]",
description: `This bot is hosted by ${
hosterUrl ? `[${hosterName}](${hosterUrl})` : `${hosterName}`
}, the bot is developed by [Zyner](https://github.com/ZynerOrg)!
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command.setName("about").setDescription("About this bot!)");
},
execute: async (interaction: CommandInteraction) => {
const interactionEmbed = {
title: ":hammer: Utilities [About]",
description: `This bot is hosted by ${
hosterUrl ? `[${hosterName}](${hosterUrl})` : `${hosterName}`
}, the bot is developed by [Zyner](https://github.com/ZynerOrg)!
If you are interested in contributing, then just [fork it](https://github.com/ZynerOrg/xyter) yourself, we :heart: Open Source.`,
color: successColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
interaction?.editReply({ embeds: [interactionEmbed] });
color: successColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
interaction?.editReply({ embeds: [interactionEmbed] });
},
};

View file

@ -10,108 +10,125 @@ import {
footerIcon,
} from "@config/embed";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Handlers
import logger from "../../../logger";
import logger from "@logger";
// Function
export default async (interaction: CommandInteraction) => {
const { options } = interaction;
// Get lookup query
const query = options?.getString("query");
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("lookup")
.setDescription(
"Lookup a domain or ip. (Request sent over HTTP, proceed with caution!)"
)
.addStringOption((option) =>
option
.setName("query")
.setDescription("The query you want to look up.")
.setRequired(true)
);
},
execute: async (interaction: CommandInteraction) => {
const { options } = interaction;
// Get lookup query
const query = options?.getString("query");
// Make API request
await axios
// Make a get request
?.get(`http://ip-api.com/json/${query}`)
// Make API request
await axios
// Make a get request
?.get(`http://ip-api.com/json/${query}`)
// If successful
?.then(async (res) => {
// If query failed
if (res?.data?.status === "fail") {
// Create embed object
const embed = {
title: ":hammer: Utilities - Lookup",
description: `${res?.data?.message}: ${res?.data?.query}`,
color: errorColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
// If successful
?.then(async (res) => {
// If query failed
if (res?.data?.status === "fail") {
// Create embed object
const embed = {
title: ":hammer: Utilities - Lookup",
description: `${res?.data?.message}: ${res?.data?.query}`,
color: errorColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
// Send interaction reply
await interaction?.editReply({ embeds: [embed] });
}
// Send interaction reply
await interaction?.editReply({ embeds: [embed] });
}
// If query is successful
else if (res?.data?.status === "success") {
// Create embed object
const embed = {
title: ":hammer: Utilities - Lookup",
fields: [
{
name: "AS",
value: `${res?.data?.as || "Not available"}`,
// If query is successful
else if (res?.data?.status === "success") {
// Create embed object
const embed = {
title: ":hammer: Utilities - Lookup",
fields: [
{
name: "AS",
value: `${res?.data?.as || "Not available"}`,
},
{
name: "Country",
value: `${res?.data?.country || "Not available"}`,
},
{
name: "Country Code",
value: `${res?.data?.countryCode || "Not available"}`,
},
{
name: "Region",
value: `${res?.data?.region || "Not available"}`,
},
{
name: "Region Name",
value: `${res?.data?.regionName || "Not available"}`,
},
{
name: "City",
value: `${res?.data?.city || "Not available"}`,
},
{
name: "ZIP Code",
value: `${res?.data?.zip || "Not available"}`,
},
{
name: "Latitude",
value: `${res?.data?.lat || "Not available"}`,
},
{
name: "Longitude",
value: `${res?.data?.lon || "Not available"}`,
},
{
name: "Timezone",
value: `${res?.data?.timezone || "Not available"}`,
},
{
name: "ISP",
value: `${res?.data?.isp || "Not available"}`,
},
{
name: "Organization",
value: `${res?.data?.org || "Not available"}`,
},
],
color: successColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
{
name: "Country",
value: `${res?.data?.country || "Not available"}`,
},
{
name: "Country Code",
value: `${res?.data?.countryCode || "Not available"}`,
},
{
name: "Region",
value: `${res?.data?.region || "Not available"}`,
},
{
name: "Region Name",
value: `${res?.data?.regionName || "Not available"}`,
},
{
name: "City",
value: `${res?.data?.city || "Not available"}`,
},
{
name: "ZIP Code",
value: `${res?.data?.zip || "Not available"}`,
},
{
name: "Latitude",
value: `${res?.data?.lat || "Not available"}`,
},
{
name: "Longitude",
value: `${res?.data?.lon || "Not available"}`,
},
{
name: "Timezone",
value: `${res?.data?.timezone || "Not available"}`,
},
{
name: "ISP",
value: `${res?.data?.isp || "Not available"}`,
},
{
name: "Organization",
value: `${res?.data?.org || "Not available"}`,
},
],
color: successColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
};
// Send interaction reply
await interaction?.editReply({ embeds: [embed] });
}
})
.catch(async (e) => {
logger?.error(e);
});
// Send interaction reply
await interaction?.editReply({ embeds: [embed] });
}
})
.catch(async (e) => {
logger?.error(e);
});
},
};

View file

@ -1,57 +1,63 @@
import { successColor, footerText, footerIcon } from "@config/embed";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js";
export default async (interaction: CommandInteraction) => {
const { client } = interaction;
if (client?.uptime === null) return;
let totalSeconds = client?.uptime / 1000;
const days = Math?.floor(totalSeconds / 86400);
totalSeconds %= 86400;
const hours = Math?.floor(totalSeconds / 3600);
totalSeconds %= 3600;
const minutes = Math?.floor(totalSeconds / 60);
const seconds = Math?.floor(totalSeconds % 60);
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command.setName("stats").setDescription("Check bot statistics!)");
},
execute: async (interaction: CommandInteraction) => {
const { client } = interaction;
if (client?.uptime === null) return;
let totalSeconds = client?.uptime / 1000;
const days = Math?.floor(totalSeconds / 86400);
totalSeconds %= 86400;
const hours = Math?.floor(totalSeconds / 3600);
totalSeconds %= 3600;
const minutes = Math?.floor(totalSeconds / 60);
const seconds = Math?.floor(totalSeconds % 60);
const uptime = `${days} days, ${hours} hours, ${minutes} minutes and ${seconds} seconds`;
const uptime = `${days} days, ${hours} hours, ${minutes} minutes and ${seconds} seconds`;
const interactionEmbed = {
title: ":hammer: Utilities - Stats",
description: "Below you can see a list of statistics about the bot.",
fields: [
{
name: "⏰ Latency",
value: `${Date?.now() - interaction?.createdTimestamp} ms`,
inline: true,
const interactionEmbed = {
title: ":hammer: Utilities - Stats",
description: "Below you can see a list of statistics about the bot.",
fields: [
{
name: "⏰ Latency",
value: `${Date?.now() - interaction?.createdTimestamp} ms`,
inline: true,
},
{
name: "⏰ API Latency",
value: `${Math?.round(client?.ws?.ping)} ms`,
inline: true,
},
{
name: "⏰ Uptime",
value: `${uptime}`,
inline: false,
},
{
name: "📈 Guilds",
value: `${client?.guilds?.cache?.size}`,
inline: true,
},
{
name: "📈 Users (non-unique)",
value: `${client?.guilds?.cache?.reduce(
(acc, guild) => acc + guild?.memberCount,
0
)}`,
inline: true,
},
],
color: successColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
{
name: "⏰ API Latency",
value: `${Math?.round(client?.ws?.ping)} ms`,
inline: true,
},
{
name: "⏰ Uptime",
value: `${uptime}`,
inline: false,
},
{
name: "📈 Guilds",
value: `${client?.guilds?.cache?.size}`,
inline: true,
},
{
name: "📈 Users (non-unique)",
value: `${client?.guilds?.cache?.reduce(
(acc, guild) => acc + guild?.memberCount,
0
)}`,
inline: true,
},
],
color: successColor,
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
interaction?.editReply({ embeds: [interactionEmbed] });
};
interaction?.editReply({ embeds: [interactionEmbed] });
},
};

View file

@ -11,8 +11,7 @@ export default async (client: Client) => {
const expression = "*/5 * * * *";
schedule.scheduleJob(expression, async () => {
logger.verbose(`Checking schedules! (${expression})`);
logger?.verbose("Running shop roles job.");
await shopRoles(client);
});
logger.info("Successfully started schedule engine!");
};

View file

@ -16,11 +16,7 @@ export default async (client: Client) => {
const oneHourAfterPayed = payed?.setHours(payed?.getHours() + 1);
if (new Date() > new Date(oneHourAfterPayed)) {
logger.debug(
`Role: ${shopRole?.roleId} Expires: ${
new Date() < new Date(oneHourAfterPayed)
} Last Payed: ${shopRole?.lastPayed}`
);
logger?.verbose(`Shop role ${shopRole?.name} is expired.`);
// Get guild object
const guild = await guildSchema?.findOne({
@ -43,8 +39,11 @@ export default async (client: Client) => {
shopRoleSchema
?.deleteOne({ _id: shopRole?._id })
?.then(async () =>
logger?.debug(`Removed ${shopRole?._id} from collection.`)
);
logger?.verbose(`Shop role ${shopRole?.roleId} was deleted.`)
)
.catch(async (error) => {
return logger?.error(error);
});
return rMember?.roles?.remove(`${shopRole?.roleId}`);
}