generated from lucxjo/template
(#1) User reporting now complete
closes #1 Signed-off-by: Louis Hollingworth <louis@hollingworth.ch>
This commit is contained in:
parent
faca0b2fda
commit
6770bd8d35
|
@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
|
||||||
Examples of behavior that contributes to a positive environment for our
|
Examples of behavior that contributes to a positive environment for our
|
||||||
community include:
|
community include:
|
||||||
|
|
||||||
* Demonstrating empathy and kindness toward other people
|
- Demonstrating empathy and kindness toward other people
|
||||||
* Being respectful of differing opinions, viewpoints, and experiences
|
- Being respectful of differing opinions, viewpoints, and experiences
|
||||||
* Giving and gracefully accepting constructive feedback
|
- Giving and gracefully accepting constructive feedback
|
||||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
- Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
and learning from the experience
|
and learning from the experience
|
||||||
* Focusing on what is best not just for us as individuals, but for the
|
- Focusing on what is best not just for us as individuals, but for the
|
||||||
overall community
|
overall community
|
||||||
|
|
||||||
Examples of unacceptable behavior include:
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
* The use of sexualized language or imagery, and sexual attention or
|
- The use of sexualized language or imagery, and sexual attention or
|
||||||
advances of any kind
|
advances of any kind
|
||||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
- Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
* Public or private harassment
|
- Public or private harassment
|
||||||
* Publishing others' private information, such as a physical or email
|
- Publishing others' private information, such as a physical or email
|
||||||
address, without their explicit permission
|
address, without their explicit permission
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
- Other conduct which could reasonably be considered inappropriate in a
|
||||||
professional setting
|
professional setting
|
||||||
|
|
||||||
## Enforcement Responsibilities
|
## Enforcement Responsibilities
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# How to contribute
|
# How to contribute
|
||||||
|
|
||||||
<!-- TODO: Change <PROJECT_NAME> -->
|
<!-- TODO: Change <PROJECT_NAME> -->
|
||||||
|
|
||||||
Contributions to ER are highly encouraged and desired. Below are some guidelines that will help make the process as smooth as possible.
|
Contributions to ER are highly encouraged and desired. Below are some guidelines that will help make the process as smooth as possible.
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
@ -62,6 +63,7 @@ We are not infallible and as such the documentation may need corrections. Please
|
||||||
- Celebrate
|
- Celebrate
|
||||||
|
|
||||||
## DCO
|
## DCO
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Developer Certificate of Origin
|
Developer Certificate of Origin
|
||||||
Version 1.1
|
Version 1.1
|
||||||
|
@ -101,6 +103,7 @@ By making a contribution to this project, I certify that:
|
||||||
maintained indefinitely and may be redistributed consistent with
|
maintained indefinitely and may be redistributed consistent with
|
||||||
this project or the open source license(s) involved.
|
this project or the open source license(s) involved.
|
||||||
```
|
```
|
||||||
|
|
||||||
## Additional Resources
|
## Additional Resources
|
||||||
|
|
||||||
- [General GitHub documentation](https://help.github.com/)
|
- [General GitHub documentation](https://help.github.com/)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# ER - Edvin Rydburg
|
# ER - Edvin Rydburg
|
||||||
|
|
||||||
A Discord bot designed around the [Young Royals](https://discord.gg/youngroyals)
|
A Discord bot designed around the [Young Royals](https://discord.gg/youngroyals)
|
||||||
Discord guild. This bot is the first generation of what will become Klara.
|
Discord guild. This bot is the first generation of what will become Klara.
|
||||||
|
|
||||||
|
@ -6,11 +7,13 @@ The intent for this bot is as a playground for features of the future Klara bot
|
||||||
that will be written in Rust or Go.
|
that will be written in Rust or Go.
|
||||||
|
|
||||||
## Why TS/JS then Rust or Go?
|
## Why TS/JS then Rust or Go?
|
||||||
|
|
||||||
Discordx makes it extremely easy to build a bot, so while I'm figuring things
|
Discordx makes it extremely easy to build a bot, so while I'm figuring things
|
||||||
out, this will ensure that I can quickly realise what will be needed. Once what
|
out, this will ensure that I can quickly realise what will be needed. Once what
|
||||||
is needed is known, a more stable version can be made that, in Rust or Go, will
|
is needed is known, a more stable version can be made that, in Rust or Go, will
|
||||||
consume far less resources.
|
consume far less resources.
|
||||||
|
|
||||||
## Will the future Klara still be open-source?
|
## Will the future Klara still be open-source?
|
||||||
|
|
||||||
Yes! Of course! Practically everything I do is open-source, I don't believe that
|
Yes! Of course! Practically everything I do is open-source, I don't believe that
|
||||||
hiding work particularly helps anyone.
|
hiding work particularly helps anyone.
|
||||||
|
|
927
pnpm-lock.yaml
927
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
75
src/commands/admin.ts
Normal file
75
src/commands/admin.ts
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
import { ApplicationCommandOptionType, Channel, CommandInteraction, GuildMember, PermissionsBitField } from "discord.js";
|
||||||
|
import { Discord, Guard, GuardFunction, Slash, SlashGroup, SlashOption } from "discordx";
|
||||||
|
import { prisma } from "../main.js";
|
||||||
|
|
||||||
|
const AdminOnly: GuardFunction<CommandInteraction> = async (
|
||||||
|
arg,
|
||||||
|
client,
|
||||||
|
next
|
||||||
|
) => {
|
||||||
|
const argObj = arg instanceof Array ? arg[0] : arg;
|
||||||
|
const user = argObj.user as GuildMember
|
||||||
|
|
||||||
|
if (user.permissions.has(PermissionsBitField.Flags.Administrator)) await next();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Discord()
|
||||||
|
@SlashGroup({ name: "admin", description: "Admin commands" })
|
||||||
|
@SlashGroup("admin")
|
||||||
|
@Guard(AdminOnly)
|
||||||
|
class AdminCmds {
|
||||||
|
@Slash({description: "Set or get the configured channel for reports"})
|
||||||
|
async reports(
|
||||||
|
@SlashOption({
|
||||||
|
description: "Set where the reports should be sent",
|
||||||
|
name: "reports_channel",
|
||||||
|
required: false,
|
||||||
|
type: ApplicationCommandOptionType.Channel
|
||||||
|
})
|
||||||
|
channel: Channel,
|
||||||
|
interaction: CommandInteraction
|
||||||
|
) {
|
||||||
|
if (channel) {
|
||||||
|
await prisma.guild.findUnique({
|
||||||
|
where: {
|
||||||
|
id: interaction.guildId!
|
||||||
|
}
|
||||||
|
}).then(async (data) => {
|
||||||
|
if (data) {
|
||||||
|
await prisma.guild.update({
|
||||||
|
where: {
|
||||||
|
id: data.id
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
reports_channel_id: channel.id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
await prisma.guild.create({
|
||||||
|
data: {
|
||||||
|
id: interaction.guildId!,
|
||||||
|
name: interaction.guild!.name,
|
||||||
|
reports_channel_id: channel.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
interaction.reply(`<#${channel.id}> is now setup to receive reports.`)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
await prisma.guild.findUnique({
|
||||||
|
where: {
|
||||||
|
id: interaction.guildId!
|
||||||
|
}
|
||||||
|
}).then((data) => {
|
||||||
|
if (data) {
|
||||||
|
interaction.reply(`<#${data.reports_channel_id}> is currently receiving reports for this guild.`)
|
||||||
|
} else {
|
||||||
|
interaction.reply("Reports are currently disabled for this guild")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
16
src/main.ts
16
src/main.ts
|
@ -61,9 +61,9 @@ bot.on("guildCreate", (guild: Guild) => {
|
||||||
data: {
|
data: {
|
||||||
id: guild.id,
|
id: guild.id,
|
||||||
name: guild.name,
|
name: guild.name,
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
// The following syntax should be used in the commonjs environment
|
// The following syntax should be used in the commonjs environment
|
||||||
|
@ -71,7 +71,9 @@ async function run() {
|
||||||
// await importx(__dirname + "/{events,commands}/**/*.{ts,js}");
|
// await importx(__dirname + "/{events,commands}/**/*.{ts,js}");
|
||||||
|
|
||||||
// The following syntax should be used in the ECMAScript environment
|
// The following syntax should be used in the ECMAScript environment
|
||||||
await importx(`${dirname(import.meta.url)}/{events,commands,menus}/**/*.{ts,js}`);
|
await importx(
|
||||||
|
`${dirname(import.meta.url)}/{events,commands,menus}/**/*.{ts,js}`
|
||||||
|
);
|
||||||
|
|
||||||
// Let's start the bot
|
// Let's start the bot
|
||||||
if (!process.env.DISCORD_TOKEN) {
|
if (!process.env.DISCORD_TOKEN) {
|
||||||
|
@ -82,9 +84,11 @@ async function run() {
|
||||||
await bot.login(process.env.DISCORD_TOKEN);
|
await bot.login(process.env.DISCORD_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
run().then(async () => {
|
run()
|
||||||
|
.then(async () => {
|
||||||
await prisma.$disconnect();
|
await prisma.$disconnect();
|
||||||
}).catch(async (e) => {
|
})
|
||||||
|
.catch(async (e) => {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
await prisma.$disconnect();
|
await prisma.$disconnect();
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
import { ActionRowBuilder, ApplicationCommandType, Client, MessageContextMenuCommandInteraction, ModalBuilder, TextChannel, TextInputBuilder, TextInputStyle } from "discord.js";
|
import {
|
||||||
import { ContextMenu, Discord } from "discordx";
|
ActionRowBuilder,
|
||||||
|
ApplicationCommandType,
|
||||||
|
Client,
|
||||||
|
MessageContextMenuCommandInteraction,
|
||||||
|
ModalBuilder,
|
||||||
|
ModalSubmitInteraction,
|
||||||
|
TextChannel,
|
||||||
|
TextInputBuilder,
|
||||||
|
TextInputStyle,
|
||||||
|
} from "discord.js";
|
||||||
|
import { ContextMenu, Discord, ModalComponent } from "discordx";
|
||||||
import { prisma } from "../main.js";
|
import { prisma } from "../main.js";
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
|
@ -8,33 +18,40 @@ export class Report {
|
||||||
name: "Report user",
|
name: "Report user",
|
||||||
type: ApplicationCommandType.User,
|
type: ApplicationCommandType.User,
|
||||||
})
|
})
|
||||||
async reportUser(interaction: MessageContextMenuCommandInteraction, client: Client) {
|
async reportUser(
|
||||||
|
interaction: MessageContextMenuCommandInteraction,
|
||||||
|
client: Client
|
||||||
|
) {
|
||||||
if (interaction.guildId) {
|
if (interaction.guildId) {
|
||||||
let data = await prisma.guild.findUnique({
|
let data = await prisma.guild.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: interaction.guildId!
|
id: interaction.guildId!,
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
await prisma.guild.create({
|
await prisma.guild.create({
|
||||||
data: {
|
data: {
|
||||||
id: interaction.guildId!,
|
id: interaction.guildId!,
|
||||||
name: interaction.guild!.name
|
name: interaction.guild!.name,
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
data = await prisma.guild.findUnique({
|
data = await prisma.guild.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: interaction.guildId!
|
id: interaction.guildId!,
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!data!.reports_channel_id) {
|
||||||
|
interaction.reply(
|
||||||
|
"It looks like your guild hasn't set up this feature, please speak to the staff."
|
||||||
|
);
|
||||||
|
} else {
|
||||||
const modal = new ModalBuilder()
|
const modal = new ModalBuilder()
|
||||||
.setTitle("Report user")
|
.setTitle("Report user")
|
||||||
.setCustomId("report-user");
|
.setCustomId("report_user");
|
||||||
|
|
||||||
const userId = new TextInputBuilder()
|
const userId = new TextInputBuilder()
|
||||||
.setCustomId("user-id")
|
.setCustomId("user-id")
|
||||||
|
@ -49,28 +66,38 @@ export class Report {
|
||||||
|
|
||||||
modal.addComponents(
|
modal.addComponents(
|
||||||
new ActionRowBuilder<TextInputBuilder>().addComponents(userId),
|
new ActionRowBuilder<TextInputBuilder>().addComponents(userId),
|
||||||
new ActionRowBuilder<TextInputBuilder>().addComponents(reason),
|
new ActionRowBuilder<TextInputBuilder>().addComponents(reason)
|
||||||
);
|
);
|
||||||
|
|
||||||
interaction.showModal(modal).then(() => {
|
interaction.showModal(modal)
|
||||||
interaction.editReply({
|
}
|
||||||
content: "Reported user.",
|
|
||||||
});
|
|
||||||
|
|
||||||
// client.channels.fetch("channel-id").then((channel) => {
|
|
||||||
// if (channel?.isTextBased()) {
|
|
||||||
// let ct = channel as TextChannel;
|
|
||||||
// ct.send({
|
|
||||||
// content: `User <@${interaction.user.id}> reported <@${interaction.targetId}> for: ${reason.data.value ?? ""}`,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
//})
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
interaction.reply({
|
interaction.reply({
|
||||||
content: "It looks like you aren't in a guild, you can only report within guilds"
|
content:
|
||||||
})
|
"It looks like you aren't in a guild, you can only report within guilds",
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ModalComponent()
|
||||||
|
async report_user(interaction: ModalSubmitInteraction, client: Client) {
|
||||||
|
const [user_id, reason] = ['user-id', 'reason'].map((id) => interaction.fields.getTextInputValue(id))
|
||||||
|
const data = await prisma.guild.findUnique({
|
||||||
|
where: {
|
||||||
|
id: interaction.guildId!
|
||||||
|
}
|
||||||
|
})
|
||||||
|
client.channels.fetch(data!.reports_channel_id!).then((channel) => {
|
||||||
|
if (channel?.isTextBased()) {
|
||||||
|
let ct = channel as TextChannel;
|
||||||
|
ct.send({
|
||||||
|
content: `<@${interaction.user.id}> reported <@${
|
||||||
|
user_id
|
||||||
|
}> for: ${reason}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
interaction.reply({content: "Reported user.", ephemeral: true})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue