-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
268 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
// MAX MUTE TIME 2419200000 | ||
import { | ||
ChatInputCommandInteraction, | ||
SlashCommandBuilder, | ||
PermissionFlagsBits, | ||
ActionRowBuilder, | ||
ButtonBuilder, | ||
EmbedBuilder, | ||
ButtonStyle | ||
} from 'discord.js'; | ||
import Infraction, { getUserInfractions } from '../functions/Infraction'; | ||
|
||
export const data = new SlashCommandBuilder() | ||
.setName('user') | ||
.setDescription('Manage Users') | ||
.addSubcommand((subcommand) => | ||
subcommand | ||
.setName('info') | ||
.setDescription('Get info of a user') | ||
.addUserOption((option) => option.setName('user').setDescription('The user to get info').setRequired(true)) | ||
) | ||
.addSubcommand((subcommand) => | ||
subcommand | ||
.setName('infractions') | ||
.setDescription('Get user Infractions') | ||
.addUserOption((option) => option.setName('user').setDescription('The user to get infractions').setRequired(true)) | ||
) | ||
.addSubcommand((subcommand) => | ||
subcommand | ||
.setName('warn') | ||
.setDescription('Warn a user') | ||
.addUserOption((option) => option.setName('user').setDescription('The user to warn').setRequired(true)) | ||
.addStringOption((option) => | ||
option.setName('reason').setDescription('The reason for the warn').setRequired(false) | ||
) | ||
) | ||
.addSubcommand((subcommand) => | ||
subcommand | ||
.setName('kick') | ||
.setDescription('Kick a user') | ||
.addUserOption((option) => option.setName('user').setDescription('The user to kick').setRequired(true)) | ||
.addStringOption((option) => | ||
option.setName('reason').setDescription('The reason for the kick').setRequired(false) | ||
) | ||
) | ||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages) | ||
.setDMPermission(false); | ||
|
||
export async function execute(interaction: ChatInputCommandInteraction): Promise<void> { | ||
try { | ||
if (!interaction.guild) return; | ||
const subCommand = interaction.options.getSubcommand(); | ||
const commandUser = interaction.options.getUser('user'); | ||
if (!commandUser) { | ||
await interaction.reply({ content: 'Please provide a valid user', ephemeral: true }); | ||
return; | ||
} | ||
const user = await interaction.guild.members.fetch(commandUser.id); | ||
if (!user) { | ||
await interaction.reply({ content: 'Please provide a valid user', ephemeral: true }); | ||
return; | ||
} | ||
switch (subCommand) { | ||
case 'info': { | ||
const embed = new EmbedBuilder() | ||
.setTitle('User Infomation') | ||
.setTimestamp() | ||
.setColor(0xff8c00) | ||
.setDescription( | ||
`<@${user.id}>\n\nBot: ${user.user.bot}\nID: ${user.id}\n Created: <t:${ | ||
user.user.createdTimestamp | ||
}:F> (<t:${user.user.createdTimestamp}:R>)\nJoined: <t:${ | ||
user.joinedTimestamp | ||
}:F> (<t:${user.joinedTimestamp}:R>)\nRoles: ${user.roles.cache.map((role) => `<@&${role.id}>`)}` | ||
); | ||
await interaction.reply({ | ||
embeds: [embed], | ||
components: [ | ||
new ActionRowBuilder<ButtonBuilder>().addComponents( | ||
new ButtonBuilder().setCustomId(`logs.${user.id}`).setLabel('view logs').setStyle(ButtonStyle.Secondary), | ||
new ButtonBuilder().setCustomId(`kick.${user.id}`).setLabel('kick').setStyle(ButtonStyle.Danger), | ||
new ButtonBuilder().setCustomId(`ban.${user.id}`).setLabel('ban').setStyle(ButtonStyle.Danger) | ||
) | ||
], | ||
ephemeral: true | ||
}); | ||
await interaction.reply({ content: `<@${user.id}> has been warned`, ephemeral: true }); | ||
} | ||
case 'infractions': { | ||
const userInfractions = await getUserInfractions(commandUser.id); | ||
if (!userInfractions.success) { | ||
await interaction.reply({ content: userInfractions.info, ephemeral: true }); | ||
return; | ||
} | ||
const embed = new EmbedBuilder() | ||
.setTitle('User Infractions') | ||
.setDescription( | ||
`${userInfractions.info}\n\n${userInfractions.infractions | ||
?.map((infraction) => infraction.toString()) | ||
.join('\n\n')}` | ||
) | ||
.setColor(0xff8c00) | ||
.setTimestamp(); | ||
await interaction.reply({ embeds: [embed], ephemeral: true }); | ||
} | ||
case 'warn': { | ||
const reason = interaction.options.getString('reason') || 'No reason provided'; | ||
new Infraction({ | ||
automatic: false, | ||
reason: reason, | ||
type: 'WARN', | ||
user: { id: commandUser.id, staff: false, bot: commandUser.bot }, | ||
staff: { id: interaction.user.id, staff: true, bot: interaction.user.bot } | ||
}) | ||
.log() | ||
.save(); | ||
await interaction.reply({ content: `<@${commandUser.id}> has been warned`, ephemeral: true }); | ||
} | ||
case 'kick': { | ||
const reason = interaction.options.getString('reason') || 'No reason provided'; | ||
new Infraction({ | ||
automatic: false, | ||
reason: reason, | ||
type: 'KICK', | ||
user: { id: commandUser.id, staff: false, bot: commandUser.bot }, | ||
staff: { id: interaction.user.id, staff: true, bot: interaction.user.bot } | ||
}) | ||
.log() | ||
.save(); | ||
await interaction.reply({ content: `<@${commandUser.id}> has been kicked`, ephemeral: true }); | ||
} | ||
default: { | ||
await interaction.reply({ content: 'Invalid subcommand Please provide a valid subcommand', ephemeral: true }); | ||
} | ||
} | ||
} catch (error) { | ||
console.log(error); | ||
if (interaction.replied || interaction.deferred) { | ||
await interaction.followUp({ content: 'Something went wrong. Please try again later.', ephemeral: true }); | ||
return; | ||
} | ||
await interaction.reply({ content: 'Something went wrong. Please try again later.', ephemeral: true }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { ChannelType } from 'discord.js'; | ||
import { infractionLogchannel } from '../../config.json'; | ||
import { model, Schema } from 'mongoose'; | ||
|
||
export interface InfractionUser { | ||
id: string; | ||
staff: boolean; | ||
bot: boolean; | ||
} | ||
|
||
export type InfractionType = 'EVENT' | 'WARN' | 'KICK' | 'BAN'; | ||
|
||
export interface InfractionInfomation { | ||
automatic: boolean; | ||
reason: string; | ||
type: InfractionType; | ||
user: InfractionUser; | ||
staff: InfractionUser; | ||
} | ||
|
||
const InteractionUserSchema = new Schema({ id: String, staff: Boolean, bot: Boolean }); | ||
const InfractionSchema = new Schema({ | ||
automatic: Boolean, | ||
reason: String, | ||
type: String, | ||
user: InteractionUserSchema, | ||
staff: InteractionUserSchema | ||
}); | ||
const InfractionModel = model('infraction', InfractionSchema); | ||
|
||
class Infraction { | ||
private infraction: InfractionInfomation; | ||
constructor(infraction: InfractionInfomation) { | ||
this.infraction = infraction; | ||
} | ||
public save() { | ||
return new InfractionModel({ | ||
automatic: this.infraction.automatic, | ||
reason: this.infraction.reason, | ||
type: this.infraction.type, | ||
user: this.infraction.user, | ||
staff: this.infraction.staff | ||
}).save(); | ||
} | ||
public setAutomatic(automatic: boolean): this { | ||
this.infraction.automatic = automatic; | ||
return this; | ||
} | ||
public setReason(reason: string): this { | ||
this.infraction.reason = reason; | ||
return this; | ||
} | ||
public setType(type: InfractionType): this { | ||
this.infraction.type = type; | ||
return this; | ||
} | ||
public setUser(user: InfractionUser): this { | ||
this.infraction.user = user; | ||
return this; | ||
} | ||
public setStaff(staff: InfractionUser): this { | ||
this.infraction.staff = staff; | ||
return this; | ||
} | ||
public getInfraction(): InfractionInfomation { | ||
return this.infraction; | ||
} | ||
public getReason(): string { | ||
return this.infraction.reason; | ||
} | ||
public getType(): InfractionType { | ||
return this.infraction.type; | ||
} | ||
public getUser(): InfractionUser { | ||
return this.infraction.user; | ||
} | ||
public getStaff(): InfractionUser | null { | ||
return this.infraction.staff; | ||
} | ||
public isAutomatic(): boolean { | ||
return this.infraction.automatic; | ||
} | ||
public toString(): string { | ||
return `Infraction: ${this.infraction.reason}\nAutomatic: ${this.infraction.automatic ? 'Yes' : 'No'}\nUser: <@${ | ||
this.infraction.user.id | ||
}>\nStaff: ${this.infraction.staff ? `<@${this.infraction.staff.id}>` : 'None'}`; | ||
} | ||
public log(): this { | ||
const channel = guild.channels.cache.get(infractionLogchannel); | ||
if (!channel || channel.type !== ChannelType.GuildText) return this; | ||
channel.send(this.toString()); | ||
return this; | ||
} | ||
} | ||
export interface InfractionReturn { | ||
success: boolean; | ||
info: string; | ||
infraction?: Infraction; | ||
infractions?: Infraction[]; | ||
} | ||
export async function getUserInfractions(id: string): Promise<InfractionReturn> { | ||
const userInfractions = await InfractionModel.find({ 'user.id': id }); | ||
if (!userInfractions) return { success: false, info: 'No infractions found' }; | ||
const foundInfraction: Infraction[] = []; | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-expect-error | ||
userInfractions.forEach((infraction) => foundInfraction.push(new Infraction(infraction))); | ||
return { success: true, info: `User has ${foundInfraction.length} infractions`, infractions: foundInfraction }; | ||
} | ||
export default Infraction; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters