Skip to content
This repository has been archived by the owner on Dec 9, 2022. It is now read-only.

Commit

Permalink
Misc Cleanup (#441)
Browse files Browse the repository at this point in the history
* ⚡ Validation improvements

* ✨ Add update history work
  • Loading branch information
Jasper Mayone authored Jul 5, 2022
1 parent 9d7eb01 commit 50cc301
Show file tree
Hide file tree
Showing 14 changed files with 192 additions and 8 deletions.
19 changes: 15 additions & 4 deletions src/commands/subcommands/fun/handleJoke.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ import axios from "axios";
import { MessageEmbed } from "discord.js";

import { CommandHandler } from "../../../interfaces/commands/CommandHandler";
import { Joke } from "../../../interfaces/commands/fun/Joke";
import { errorEmbedGenerator } from "../../../modules/errorEmbedGenerator";
import { heptagramErrorHandler } from "../../../modules/heptagramErrorHandler";

/**
* Generates an embed with a random joke
* Generates an embed with a random joke.
*
* @param Heptagram
* @param interaction
*/
export const handleJoke: CommandHandler = async (
Heptagram,
interaction
): Promise<void> => {
try {
const jokeResponse = await axios.get<string>(
const joke = await axios.get<Joke>(
`https://api.heptagrambotproject.com/v4/jokes`,
{
headers: {
Expand All @@ -22,13 +26,20 @@ export const handleJoke: CommandHandler = async (
}
);

if (!joke.data || joke.status !== 200) {
await interaction.editReply({
content: "Something went wrong while fetching a joke.",
});
return;
}

const embed = new MessageEmbed()
.setColor(Heptagram.colors.default)
.setTitle("Here is a random joke for you!")
.setDescription(jokeResponse.data)
.setDescription(joke.data.joke)
.setTimestamp()
.setFooter({
text: `This command uses our first party API! Find out more about it at https://heptagrambotproject.com/api`,
text: `This command uses our first party API!`,
iconURL: `${Heptagram.user?.avatarURL()}`,
});

Expand Down
19 changes: 15 additions & 4 deletions src/commands/subcommands/fun/handleQuote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ import axios from "axios";
import { MessageEmbed } from "discord.js";

import { CommandHandler } from "../../../interfaces/commands/CommandHandler";
import { Quote } from "../../../interfaces/commands/fun/Quote";
import { errorEmbedGenerator } from "../../../modules/errorEmbedGenerator";
import { heptagramErrorHandler } from "../../../modules/heptagramErrorHandler";

/**
* Generates an embed with a random quote
* Generates an embed with a random quote.
*
* @param Heptagram
* @param interaction
*/
export const handleQuote: CommandHandler = async (
Heptagram,
interaction
): Promise<void> => {
try {
const quoteResponse = await axios.get<string>(
const quote = await axios.get<Quote>(
`https://api.heptagrambotproject.com/v4/quotes`,
{
headers: {
Expand All @@ -22,13 +26,20 @@ export const handleQuote: CommandHandler = async (
}
);

if (!quote.data || quote.status !== 200) {
await interaction.editReply({
content: "Something went wrong while fetching a quote.",
});
return;
}

const embed = new MessageEmbed()
.setColor(Heptagram.colors.default)
.setTitle("Here is a random quote for you!")
.setDescription(quoteResponse.data)
.setDescription(`"${quote.data.quote}"\n-- ${quote.data.author}`)
.setTimestamp()
.setFooter({
text: `This command uses our first party API! Find out more about it at https://heptagrambotproject.com/api`,
text: `This command uses our first party API!`,
iconURL: `${Heptagram.user?.avatarURL()}`,
});

Expand Down
8 changes: 8 additions & 0 deletions src/commands/subcommands/moderation/handleBan.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { Interaction } from "discord.js";

import { CommandHandler } from "../../../interfaces/commands/CommandHandler";
import { updateHistory } from "../../../modules/commands/moderation/updateHistory";
import { errorEmbedGenerator } from "../../../modules/errorEmbedGenerator";
import { heptagramErrorHandler } from "../../../modules/heptagramErrorHandler";
import { customSubstring } from "../../../utils/customSubstring";

/**
* Bans the `target` user for the provided `reason`, assuming the caller has permissions.
* Also deletes the `target`'s messages from the last 24 hours.
*
* @param {Heptagram} Heptagram Heptagram's discord instance.
* @param {Interaction} interaction The interaction object.
*/
export const handleBan: CommandHandler = async (Heptagram, interaction) => {
try {
Expand Down Expand Up @@ -69,6 +75,8 @@ export const handleBan: CommandHandler = async (Heptagram, interaction) => {
return;
}

await updateHistory(Heptagram, "ban", target.id, guild.id);

await targetMember.ban({
reason: customSubstring(reason, 1000),
days: prune,
Expand Down
8 changes: 8 additions & 0 deletions src/commands/subcommands/moderation/handleKick.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { Interaction } from "discord.js";

import { CommandHandler } from "../../../interfaces/commands/CommandHandler";
import { updateHistory } from "../../../modules/commands/moderation/updateHistory";
import { errorEmbedGenerator } from "../../../modules/errorEmbedGenerator";
import { heptagramErrorHandler } from "../../../modules/heptagramErrorHandler";
import { customSubstring } from "../../../utils/customSubstring";

/**
* Provided the caller has permission, kicks the `target` user from the guild
* for the given `reason`.
*
* @param {Heptagram} Heptagram Heptagram's discord instance.
* @param {Interaction} interaction The interaction object.
*/
export const handleKick: CommandHandler = async (Heptagram, interaction) => {
try {
Expand Down Expand Up @@ -61,6 +67,8 @@ export const handleKick: CommandHandler = async (Heptagram, interaction) => {
return;
}

await updateHistory(Heptagram, "kick", target.id, guild.id);

await targetMember.kick(customSubstring(reason, 1000));

await interaction.editReply({ content: "Kicked " + target.tag });
Expand Down
8 changes: 8 additions & 0 deletions src/commands/subcommands/moderation/handleMute.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { Interaction } from "discord.js";

import { CommandHandler } from "../../../interfaces/commands/CommandHandler";
import { updateHistory } from "../../../modules/commands/moderation/updateHistory";
import { errorEmbedGenerator } from "../../../modules/errorEmbedGenerator";
import { heptagramErrorHandler } from "../../../modules/heptagramErrorHandler";
import { calculateMilliseconds } from "../../../utils/calculateMilliseconds";

/**
* If the server has configured a muted role, applies that role to the `target`
* user for the given `reason`.
*
* @param {Heptagram} Heptagram Heptagram's discord instance.
* @param {Interaction} interaction The interaction object.
*/
export const handleMute: CommandHandler = async (Heptagram, interaction) => {
try {
Expand Down Expand Up @@ -73,6 +79,8 @@ export const handleMute: CommandHandler = async (Heptagram, interaction) => {

const targetUser = await guild.members.fetch(target.id);

await updateHistory(Heptagram, "mute", target.id, guild.id);

await targetUser.timeout(durationMilliseconds, reason);

await interaction.editReply({
Expand Down
8 changes: 8 additions & 0 deletions src/commands/subcommands/moderation/handleUnmute.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { Interaction } from "discord.js";

import { CommandHandler } from "../../../interfaces/commands/CommandHandler";
import { updateHistory } from "../../../modules/commands/moderation/updateHistory";
import { errorEmbedGenerator } from "../../../modules/errorEmbedGenerator";
import { heptagramErrorHandler } from "../../../modules/heptagramErrorHandler";

/**
* If the server has configured a muted role, removes it from the `target` for the
* given `reason`.
*
* @param {Heptagram} Heptagram Heptagram's discord instance.
* @param {Interaction} interaction The interaction object.
*/
export const handleUnmute: CommandHandler = async (Heptagram, interaction) => {
try {
Expand Down Expand Up @@ -54,6 +60,8 @@ export const handleUnmute: CommandHandler = async (Heptagram, interaction) => {

const targetUser = await guild.members.fetch(target.id);

await updateHistory(Heptagram, "unmute", target.id, guild.id);

await targetUser.timeout(null, reason);

await interaction.editReply({
Expand Down
9 changes: 9 additions & 0 deletions src/commands/subcommands/moderation/handleWarn.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { Interaction } from "discord.js";

import { CommandHandler } from "../../../interfaces/commands/CommandHandler";
import { Heptagram } from "../../../interfaces/Heptagram";
import { updateHistory } from "../../../modules/commands/moderation/updateHistory";
import { errorEmbedGenerator } from "../../../modules/errorEmbedGenerator";
import { heptagramErrorHandler } from "../../../modules/heptagramErrorHandler";

/**
* Issues a warning to the `target` user, and adds it to the server's warning count.
* Logs the `reason`.
*
* @param {Heptagram} Heptagram Heptagram's discord instance.
* @param {Interaction} interaction The interaction object.
*/
export const handleWarn: CommandHandler = async (Heptagram, interaction) => {
try {
Expand Down Expand Up @@ -54,6 +61,8 @@ export const handleWarn: CommandHandler = async (Heptagram, interaction) => {
return;
}

await updateHistory(Heptagram, "warn", target.id, guild.id);

await interaction.editReply({
content: "Warned " + target.tag + " for " + reason,
});
Expand Down
15 changes: 15 additions & 0 deletions src/database/models/HistoryModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { model, Schema } from "mongoose";

import { History } from "../../interfaces/database/History";

export const HistorySchema = new Schema({
serverId: String,
userId: String,
bans: Number,
kicks: Number,
mutes: Number,
unmutes: Number,
warns: Number,
});

export default model<History>("history", HistorySchema);
8 changes: 8 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import { createServer } from "./server/serve";
import { validateEnv } from "./utils/validateEnv";
import { validateNode } from "./utils/validateNode";

/**
* This is the entry point for Heptagram's process. This will log the boot process,
* call the necessary helpers to prepare Heptagram, and then log in to Discord.
*/
void (async () => {
heptagramLogHandler.log("info", "Starting bot...");

Expand Down Expand Up @@ -53,6 +57,10 @@ void (async () => {

Heptagram.debugHook = new WebhookClient({ url: Heptagram.configs.whUrl });

/**
* Fallthrough error handlers. These fire in rare cases where something throws
* in a way that our standard catch block cannot see it.
*/
process.on("unhandledRejection", async (error: Error) => {
await heptagramErrorHandler(Heptagram, "Unhandled Rejection Error", error);
await heptagramLogHandler.log("error", error);
Expand Down
5 changes: 5 additions & 0 deletions src/interfaces/commands/fun/Joke.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface Joke {
id: string;
joke: string;
dateUploaded: Date;
}
6 changes: 6 additions & 0 deletions src/interfaces/commands/fun/Quote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface Quote {
id: string;
quote: string;
author: string;
dateUploaded: Date;
}
1 change: 1 addition & 0 deletions src/interfaces/commands/moderation/ModerationActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type ModerationActions = "ban" | "kick" | "mute" | "unmute" | "warn";
21 changes: 21 additions & 0 deletions src/interfaces/database/History.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Document } from "mongoose";

export interface History extends Document {
serverId: string;
userId: string;
bans: number;
kicks: number;
mutes: number;
unmutes: number;
warns: number;
}

export const testHistory: Omit<History, keyof Document> = {
serverId: "123",
userId: "123",
bans: 0,
kicks: 0,
mutes: 0,
unmutes: 0,
warns: 0,
};
65 changes: 65 additions & 0 deletions src/modules/commands/moderation/updateHistory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import HistoryModel from "../../../database/models/HistoryModel";
import { ModerationActions } from "../../../interfaces/commands/moderation/ModerationActions";
import { Heptagram } from "../../../interfaces/Heptagram";
import { heptagramErrorHandler } from "../../../modules/heptagramErrorHandler";

/**
* Saves a count of the user's moderation actions.
*
* @param {Heptagram} Heptagram Heptagram's Discord instance.
* @param {ModerationActions} action The action taken against the user.
* @param {string} userId The ID of the user being moderated.
* @param {string} guildId The ID of the guild the moderation occurred in.
*/
export const updateHistory = async (
Heptagram: Heptagram,
action: ModerationActions,
userId: string,
guildId: string
) => {
try {
const userRecord =
(await HistoryModel.findOne({
serverId: guildId,
userId: userId,
})) ||
(await HistoryModel.create({
serverId: guildId,
userId: userId,
bans: 0,
kicks: 0,
mutes: 0,
unmutes: 0,
warns: 0,
}));

switch (action) {
case "kick":
userRecord.kicks++;
break;
case "ban":
userRecord.bans++;
break;
case "mute":
userRecord.mutes++;
break;
case "unmute":
userRecord.unmutes++;
break;
case "warn":
userRecord.warns++;
break;
default:
break;
}

await userRecord.save();
} catch (err) {
await heptagramErrorHandler(
Heptagram,
"update moderation history",
err,
guildId
);
}
};

0 comments on commit 50cc301

Please sign in to comment.