Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…into main
  • Loading branch information
saiteja-madha committed Sep 21, 2021
2 parents 9f89656 + 6f255f2 commit 5a87919
Show file tree
Hide file tree
Showing 45 changed files with 1,178 additions and 118 deletions.
5 changes: 4 additions & 1 deletion .prettierrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
"trailingComma": "es5",
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": false,
"printWidth": 120
"printWidth": 120,
"bracketSpacing": true,
"arrowParens": "always"
}
3 changes: 3 additions & 0 deletions config-sample.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ module.exports = {
IMAGE_API: "https://discord-js-image-manipulation.herokuapp.com", // Image commands won't work without this
WEATHERSTACK_KEY: "", // https://weatherstack.com/
},
MISCELLANEOUS: {
DAILY_COINS: 100, // coins to be received by daily command
},
/* Bot Embed Colors */
EMBED_COLORS: {
BOT_EMBED: "#068ADD",
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
"url": "saiteja-madha/discord-js-bot"
},
"dependencies": {
"@discordjs/opus": "^0.5.3",
"ascii-table": "0.0.9",
"axios": "^0.21.1",
"btoa": "^1.2.1",
"country-language": "^0.1.7",
"discord-player": "^5.1.0",
"discord.js": "^13.1.0",
"ejs": "^3.1.6",
"express": "^4.17.1",
Expand Down
77 changes: 77 additions & 0 deletions src/commands/admin/maxwarn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
const { Command } = require("@src/structures");
const { maxWarnings, maxWarnAction } = require("@schemas/guild-schema");
const { Message } = require("discord.js");
const { getRoleByName } = require("@utils/guildUtils");

module.exports = class MaxWarn extends Command {
constructor(client) {
super(client, {
name: "maxwarn",
description: "set max warnings configuration",
command: {
enabled: true,
minArgsCount: 1,
subcommands: [
{
trigger: "limit <number>",
description: "set max warnings a member can receive before taking an action",
},
{
trigger: "action <MUTE|KICK|BAN>",
description: "set action to performed after receiving maximum warnings",
},
],
category: "ADMIN",
userPermissions: ["ADMINISTRATOR"],
},
});
}

/**
* @param {Message} message
* @param {string[]} args
*/
async messageRun(message, args, invoke, prefix) {
const input = args[0].toUpperCase();

// Limit configuration
if (input === "LIMIT") {
const max = args[1];
if (isNaN(max) || Number.parseInt(max) < 1)
return message.reply("Max Warnings must be a valid number greater than 0");

await maxWarnings(message.guildId, max);
message.channel.send(`Configuration saved! Maximum warnings is set to ${max}`);
}

// Action
else if (input === "ACTION") {
const action = args[1]?.toUpperCase();

if (!action) message.reply("Please choose an action. Action can be `Mute`/`Kick`/`Ban`");
if (!["MUTE", "KICK", "BAN"].includes(action))
return message.reply("Not a valid action. Action can be `Mute`/`Kick`/`Ban`");

if (action === "MUTE") {
let mutedRole = getRoleByName(message.guild, "muted");
if (!mutedRole) {
return message.reply(`Muted role doesn't exist in this guild. Use \`${prefix}mute setup\` to create one`);
}

if (!mutedRole.editable) {
return message.reply(
"I do not have permission to move members to `Muted` role. Is that role below my highest role?"
);
}
}

await maxWarnAction(message.guildId, action);
message.channel.send(`Configuration saved! Max Warnings action is set to ${action}`);
}

// send usage
else {
return this.sendUsage(message.channel, prefix, invoke, "Incorrect Arguments");
}
}
};
1 change: 1 addition & 0 deletions src/commands/admin/xpsystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = class XPSystem extends Command {
enabled: true,
usage: "<ON|OFF>",
minArgsCount: 1,
aliases: ["xptracking"],
category: "ADMIN",
userPermissions: ["ADMINISTRATOR"],
},
Expand Down
4 changes: 2 additions & 2 deletions src/commands/automod/automod.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ module.exports = class Automod extends Command {
},
{
trigger: "action <MUTE|KICK|BAN>",
description: "set automod action to performed after maximum strikes",
description: "set action to be performed after receiving maximum strikes",
},
{
trigger: "debug <ON|OFF>",
Expand Down Expand Up @@ -107,7 +107,7 @@ async function setAction(message, args, prefix) {
if (action === "MUTE") {
let mutedRole = getRoleByName(message.guild, "muted");
if (!mutedRole) {
return await message.reply(`Muted role doesn't exist in this guild. Use \`${prefix}mute setup\` to create one`);
return message.reply(`Muted role doesn't exist in this guild. Use \`${prefix}mute setup\` to create one`);
}

if (!mutedRole.editable) {
Expand Down
6 changes: 3 additions & 3 deletions src/commands/economy/daily.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { Command } = require("@src/structures");
const { MessageEmbed, Message } = require("discord.js");
const { getUser, updateDailyStreak } = require("@schemas/user-schema");
const { EMBED_COLORS, EMOJIS } = require("@root/config.js");
const { EMBED_COLORS, EMOJIS, MISCELLANEOUS } = require("@root/config.js");
const { diffHours, getRemainingTime } = require("@utils/miscUtils");

module.exports = class DailyCommand extends Command {
Expand Down Expand Up @@ -39,13 +39,13 @@ module.exports = class DailyCommand extends Command {
else streak = 0;
}

const updated = await updateDailyStreak(member.id, 1000, streak);
const updated = await updateDailyStreak(member.id, MISCELLANEOUS.DAILY_COINS, streak);

const embed = new MessageEmbed()
.setColor(EMBED_COLORS.BOT_EMBED)
.setAuthor(member.displayName, member.user.displayAvatarURL())
.setDescription(
`You got 1000${EMOJIS.CURRENCY} as your daily reward\n` +
`You got ${MISCELLANEOUS.DAILY_COINS}${EMOJIS.CURRENCY} as your daily reward\n` +
`**Updated Balance:** ${updated?.coins || 0}${EMOJIS.CURRENCY}`
);

Expand Down
22 changes: 21 additions & 1 deletion src/commands/info/avatar.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
const { Command } = require("@src/structures");
const { MessageEmbed, Message, CommandInteraction, CommandInteractionOptionResolver } = require("discord.js");
const {
MessageEmbed,
Message,
CommandInteraction,
CommandInteractionOptionResolver,
ContextMenuInteraction,
} = require("discord.js");
const { EMOJIS, EMBED_COLORS } = require("@root/config.js");
const { resolveMember } = require("@utils/guildUtils");

Expand All @@ -8,6 +14,7 @@ module.exports = class AvatarCommand extends Command {
super(client, {
name: "avatar",
description: "displays avatar information about the user",
cooldown: 5,
command: {
enabled: true,
usage: "[@member|id]",
Expand All @@ -25,6 +32,10 @@ module.exports = class AvatarCommand extends Command {
},
],
},
contextMenu: {
enabled: true,
type: "USER",
},
});
}

Expand All @@ -48,6 +59,15 @@ module.exports = class AvatarCommand extends Command {
const embed = buildEmbed(target);
interaction.followUp({ embeds: [embed] });
}

/**
* @param {ContextMenuInteraction} interaction
*/
async contextRun(interaction) {
const user = await interaction.client.users.fetch(interaction.targetId);
const embed = buildEmbed(user);
interaction.followUp({ embeds: [embed] });
}
};

const buildEmbed = (user) => {
Expand Down
43 changes: 43 additions & 0 deletions src/commands/info/emoji-info.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const { Command } = require("@src/structures");
const { Message, Util, MessageEmbed } = require("discord.js");

module.exports = class EmojiInfo extends Command {
constructor(client) {
super(client, {
name: "emojiinfo",
description: "shows info about an emoji",
command: {
enabled: true,
usage: "<emoji>",
minArgsCount: 1,
aliases: ["emoji"],
category: "INFORMATION",
},
slashCommand: {
enabled: false,
},
});
}

/**
* @param {Message} message
* @param {string[]} args
*/
async messageRun(message, args) {
const emoji = args[0];
let custom = Util.parseEmoji(emoji);
if (!custom.id) return message.channel.send("This is not a valid guild emoji");

let url = `https://cdn.discordapp.com/emojis/${custom.id}.${custom.animated ? "gif?v=1" : "png"}`;

const embed = new MessageEmbed()
.setColor(this.client.config.EMBED_COLORS.BOT_EMBED)
.setAuthor("Emoji Info")
.setDescription(
`**Id:** ${custom.id}\n` + `**Name:** ${custom.name}\n` + `**Animated:** ${custom.animated ? "Yes" : "No"}`
)
.setImage(url);

return message.channel.send({ embeds: [embed] });
}
};
69 changes: 69 additions & 0 deletions src/commands/info/profile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
const { Command } = require("@src/structures");
const { Message, MessageEmbed, ContextMenuInteraction } = require("discord.js");
const { EMBED_COLORS, EMOJIS } = require("@root/config");
const { getProfile } = require("@schemas/profile-schema");
const { getSettings } = require("@schemas/guild-schema");
const { resolveMember } = require("@utils/guildUtils");
const { getUser } = require("@schemas/user-schema");

module.exports = class Profile extends Command {
constructor(client) {
super(client, {
name: "profile",
description: "shows members profile",
cooldown: 5,
command: {
enabled: true,
category: "INFORMATION",
},
contextMenu: {
enabled: true,
type: "USER",
},
});
}

/**
* @param {Message} message
* @param {string[]} args
*/
async messageRun(message, args) {
const target = (await resolveMember(message, args[0])) || message.member;
const embed = await buildEmbed(message.guild, target);
message.channel.send({ embeds: [embed] });
}

/**
* @param {ContextMenuInteraction} interaction
*/
async contextRun(interaction) {
const target = (await interaction.guild.members.fetch(interaction.targetId)) || interaction.member;
const embed = await buildEmbed(interaction.guild, target);
interaction.followUp({ embeds: [embed] });
}
};

const buildEmbed = async (guild, target) => {
const { user } = target;
const settings = await getSettings(guild);
const profile = await getProfile(guild.id, user.id);
const userData = await getUser(user.id);

return new MessageEmbed()
.setThumbnail(user.displayAvatarURL())
.setColor(EMBED_COLORS.BOT_EMBED)
.addField("User Tag", user.tag, true)
.addField("ID", user.id, true)
.addField("Discord Registered", user.createdAt.toDateString(), false)
.addField("Cash", `${userData?.coins || 0} ${EMOJIS.CURRENCY}`, true)
.addField("Bank", `${userData?.bank || 0} ${EMOJIS.CURRENCY}`, true)
.addField("Net Worth", `${(userData?.coins || 0) + (userData?.bank || 0)}${EMOJIS.CURRENCY}`, true)
.addField("Messages*", `${settings.ranking.enabled ? (profile?.messages || 0) + " " : "Not Tracked"}`, true)
.addField("XP*", `${settings.ranking.enabled ? (profile?.xp || 0) + " " : "Not Tracked"}`, true)
.addField("Level*", `${settings.ranking.enabled ? (profile?.level || 0) + " " : "Not Tracked"}`, true)
.addField("Strikes*", (profile?.strikes || 0) + " ", true)
.addField("Warnings*", (profile?.warnings || 0) + " ", true)
.addField("Reputation", `${userData?.reputation?.received || 0}`, true)
.addField("Avatar-URL", user.displayAvatarURL({ format: "png" }))
.setFooter("Fields marked (*) are guild specific");
};
63 changes: 63 additions & 0 deletions src/commands/info/rank.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const { Command } = require("@src/structures");
const { Message, MessageAttachment } = require("discord.js");
const { API, EMBED_COLORS } = require("@root/config");
const { getProfile, getTop100 } = require("@schemas/profile-schema");
const { downloadImage } = require("@utils/httpUtils");
const { getSettings } = require("@schemas/guild-schema");
const { resolveMember } = require("@utils/guildUtils");

module.exports = class Rank extends Command {
constructor(client) {
super(client, {
name: "rank",
description: "shows members rank in this server",
cooldown: 5,
command: {
enabled: true,
category: "INFORMATION",
},
});
}

/**
* @param {Message} message
* @param {string[]} args
*/
async messageRun(message, args) {
const target = (await resolveMember(message, args[0])) || message.member;
const { user } = target;

const settings = await getSettings(message.guild);
if (!settings.ranking.enabled) return message.channel.send("Ranking is disabled on this server");

const profile = await getProfile(message.guildId, user.id);
if (!profile) return message.channel.send(`${user.tag} is not ranked yet!`);

const lb = await getTop100(message.guildId);
let pos = -1;
lb.forEach((doc, i) => {
if (doc.member_id == target.id) {
pos = i + 1;
}
});

const xpNeeded = profile.level * profile.level * 100;

const url = new URL(`${API.IMAGE_API}/utils/rank-card`);
url.searchParams.append("name", user.username);
url.searchParams.append("discriminator", user.discriminator);
url.searchParams.append("avatar", user.displayAvatarURL({ format: "png", size: 128 }));
url.searchParams.append("currentxp", profile.xp);
url.searchParams.append("reqxp", xpNeeded);
url.searchParams.append("level", profile.level);
url.searchParams.append("barcolor", EMBED_COLORS.BOT_EMBED);
url.searchParams.append("status", message.member.presence.status.toString());
if (pos !== -1) url.searchParams.append("rank", pos);

const rankCard = await downloadImage(url.href);
if (!rankCard) return message.reply("Failed to generate rank-card");

const attachment = new MessageAttachment(rankCard, "rank.png");
message.channel.send({ files: [attachment] });
}
};
2 changes: 1 addition & 1 deletion src/commands/info/userinfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ module.exports = class UserInfo extends Command {
],
},
contextMenu: {
enabled: true,
enabled: false,
type: "USER",
},
});
Expand Down
Loading

0 comments on commit 5a87919

Please sign in to comment.