This commit is contained in:
Isaac 2022-07-21 01:25:37 +01:00
parent 98b35e3a81
commit f93d058f55
No known key found for this signature in database
GPG Key ID: F4EAABEB0FFCC06A
5 changed files with 166 additions and 8 deletions

View File

@ -9,6 +9,8 @@
"contributors:generate": "all-contributors generate",
"keygen": "node scripts/keygen",
"lint": "eslint src scripts --ext mjs --fix",
"start": "node .",
"studio": "npx prisma studio",
"test": "echo \"There's nothing to test\" && exit 1"
},
"repository": {
@ -37,7 +39,7 @@
"@fastify/cors": "^8.0.0",
"@fastify/jwt": "^5.0.1",
"@fastify/oauth2": "^5.0.0",
"@prisma/client": "^4.0.0",
"@prisma/client": "^4.1.0",
"cryptr": "^6.0.3",
"discord.js": "^14.0.2",
"dotenv": "^16.0.1",
@ -50,7 +52,7 @@
"node-dir": "^0.1.17",
"node-emoji": "^1.11.0",
"object-diffy": "^1.0.4",
"prisma": "^4.0.0",
"prisma": "^4.1.0",
"semver": "^7.3.7",
"terminal-link": "^2.1.1",
"yaml": "^1.10.2"

View File

@ -114,6 +114,8 @@ model Guild {
archive Boolean @default(true)
blocklist Json @default("[]")
categories Category[]
claimButton Boolean @default(false)
closeButton Boolean @default(false)
createdAt DateTime @default(now())
errorColour String @default("Red")
feedback Feedback[]

View File

@ -1,4 +1,8 @@
command:
buttons:
create:
emoji: '🎫'
text: 'Create a ticket'
commands:
log:
admin:
changes: 'Changes'
@ -6,16 +10,21 @@ log:
joined: '{user} {verb} {targetType}'
target:
category: 'a category'
panel: 'a panel'
question: 'a question'
settings: 'the settings'
title:
joined: '{targetType} {verb}'
target:
category: 'Category'
panel: 'Panel'
question: 'Question'
settings: 'Settings'
verb:
create: 'created'
delete: 'deleted'
update: 'updated'
ticket:
tickets:
menus:
panel:
placeholder: 'Select a ticket category'

View File

@ -5,7 +5,7 @@ const {
const { diff: getDiff } = require('object-diffy');
const exists = thing => (typeof thing === 'string' && thing.length > 0) && thing !== null && thing !== undefined;
const exists = thing => (typeof thing === 'string' && thing.length > 0) && (thing !== null && thing !== undefined);
const arrToObj = obj => {
for (const key in obj) {
@ -26,7 +26,7 @@ function makeDiff({
for (const key in diff) {
if (key === 'createdAt') continue; // object-diffy doesn't like dates
const from = exists(diff[key].from) ? `- ${String(diff[key].from).replace(/\n/g, '\\n')}\n` : '';
const to = exists(diff[key].to) ? `+ ${String(diff[key].to).replace(/\n/g, '\\n')}\n` : '';
const to = exists(diff[key].to) ? `+ ${String(diff[key].to).replace(/\n/g, '\\n')}\n` : '';
fields.push({
inline: true,
name: key,
@ -70,6 +70,10 @@ async function logAdminEvent(client, {
where: { id: guildId },
});
if (!settings.logChannel) return;
const colour = action === 'create'
? 'Green' : action === 'update'
? 'Orange' : action === 'delete'
? 'Red' : 'Default';
const getMessage = client.i18n.getLocale(settings.locale);
const i18nOptions = {
user: `<@${user.id}>`,
@ -79,7 +83,7 @@ async function logAdminEvent(client, {
if (!channel) return;
const embeds = [
new EmbedBuilder()
.setColor('Orange')
.setColor(colour)
.setAuthor({
iconURL: user.avatarURL(),
name: user.username,
@ -105,7 +109,7 @@ async function logAdminEvent(client, {
if (diff && diff.original) {
embeds.push(
new EmbedBuilder()
.setColor('Orange')
.setColor(colour)
.setTitle(getMessage('log.admin.changes'))
.setFields(makeDiff(diff)),
);

View File

@ -0,0 +1,141 @@
const {
ActionRowBuilder,
ButtonBuilder,
ButtonStyle: {
Primary,
Secondary,
},
ChannelType: { GuildText },
EmbedBuilder,
SelectMenuBuilder,
SelectMenuOptionBuilder,
} = require('discord.js');
const emoji = require('node-emoji');
const { logAdminEvent } = require('../../../../../lib/logging');
module.exports.post = fastify => ({
handler: async (req, res) => {
/** @type {import('client')} */
const client = res.context.config.client;
const guild = client.guilds.cache.get(req.params.guild);
const data = req.body;
const settings = await client.prisma.guild.findUnique({
select: {
categories: true,
footer: true,
locale: true,
primaryColour: true,
},
where: { id: guild.id },
});
const getMessage = client.i18n.getLocale(settings.locale);
const categories = settings.categories.filter(c => data.categories.includes(c.id));
if (categories.length === 0) throw new Error('No categories');
if (categories.length !== 1 && data.type === 'MESSAGE') throw new Error('Invalid number of categories for panel type');
let channel;
if (data.channel) {
channel = await client.channels.fetch(data.channel);
} else {
const allow = ['ViewChannel', 'ReadMessageHistory'];
if (data.type === 'MESSAGE') allow.push('SendMessages');
channel = await guild.channels.create({
name: 'create-a-ticket',
permissionOverwrites: [
{
allow,
deny: ['AddReactions', 'AttachFiles'],
id: guild.roles.everyone,
},
],
position: 1,
rateLimitPerUser: 15,
reason: 'New ticket panel',
type: GuildText,
});
}
const embed = new EmbedBuilder()
.setColor(settings.primaryColour)
.setTitle(data.title)
.setFooter({
iconURL: guild.iconURL(),
text: settings.footer,
});
if (data.description) embed.setDescription(data.description);
if (data.image) embed.setImage(data.image);
if (data.thumbnail) embed.setThumbnail(data.thumbnail);
if (data.type === 'MESSAGE') {
await channel.send({ embeds: [embed] });
} else {
const components = [];
if (categories.length === 1) {
components.push(
new ButtonBuilder()
.setCustomId(JSON.stringify({
action: 'createTicket',
target: categories[0].id,
}))
.setStyle(Primary)
.setLabel(getMessage('buttons.create.text'))
.setEmoji(getMessage('buttons.create.emoji')),
);
} else {
if (data.type === 'BUTTON') {
components.push(
...categories.map(category =>
new ButtonBuilder()
.setCustomId(JSON.stringify({
action: 'createTicket',
target: category.id,
}))
.setStyle(Secondary)
.setLabel(category.name)
.setEmoji(emoji.hasEmoji(category.emoji) ? emoji.get(category.emoji) : { id: category.emoji }),
),
);
} else {
components.push(
new SelectMenuBuilder()
.setCustomId('createTicket')
.setPlaceholder(getMessage('menus.panel.placeholder'))
.setOptions(
categories.map(category =>
new SelectMenuOptionBuilder()
.setValue(String(category.id))
.setLabel(category.name)
.setDescription(category.description)
.setEmoji(emoji.hasEmoji(category.emoji) ? emoji.get(category.emoji) : { id: category.emoji }),
),
),
);
}
}
await channel.send({
components: [
new ActionRowBuilder()
.setComponents(components),
],
embeds: [embed],
});
}
logAdminEvent(client, {
action: 'create',
guildId: guild.id,
target: {
id: channel.toString(),
type: 'panel',
},
userId: req.user.payload.id,
});
return true;
},
onRequest: [fastify.authenticate, fastify.isAdmin],
});