mirror of
https://github.com/Hessenuk/DiscordTickets.git
synced 2025-01-10 18:06:27 +02:00
Merge branch 'feat-archives'
This commit is contained in:
commit
8d0317c60e
31
src/http.js
31
src/http.js
@ -4,7 +4,7 @@ const { randomBytes } = require('crypto');
|
|||||||
const { short } = require('leeks.js');
|
const { short } = require('leeks.js');
|
||||||
const { join } = require('path');
|
const { join } = require('path');
|
||||||
const { files } = require('node-dir');
|
const { files } = require('node-dir');
|
||||||
const { PermissionsBitField } = require('discord.js');
|
const { getPrivilegeLevel } = require('./lib/users');
|
||||||
|
|
||||||
process.env.ORIGIN = process.env.HTTP_INTERNAL || process.env.HTTP_EXTERNAL;
|
process.env.ORIGIN = process.env.HTTP_INTERNAL || process.env.HTTP_EXTERNAL;
|
||||||
|
|
||||||
@ -65,6 +65,33 @@ module.exports = async client => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fastify.decorate('isMember', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const userId = req.user.id;
|
||||||
|
const guildId = req.params.guild;
|
||||||
|
const guild = client.guilds.cache.get(guildId);
|
||||||
|
if (!guild) {
|
||||||
|
return res.code(404).send({
|
||||||
|
error: 'Not Found',
|
||||||
|
message: 'The requested resource could not be found.',
|
||||||
|
statusCode: 404,
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const guildMember = await guild.members.fetch(userId);
|
||||||
|
if (!guildMember) {
|
||||||
|
return res.code(403).send({
|
||||||
|
error: 'Forbidden',
|
||||||
|
message: 'You are not permitted for this action.',
|
||||||
|
statusCode: 403,
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
res.send(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
fastify.decorate('isAdmin', async (req, res) => {
|
fastify.decorate('isAdmin', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const userId = req.user.id;
|
const userId = req.user.id;
|
||||||
@ -79,7 +106,7 @@ module.exports = async client => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
const guildMember = await guild.members.fetch(userId);
|
const guildMember = await guild.members.fetch(userId);
|
||||||
const isAdmin = guildMember?.permissions.has(PermissionsBitField.Flags.ManageGuild) || client.supers.includes(userId);
|
const isAdmin = await getPrivilegeLevel(guildMember) >= 2;
|
||||||
if (!isAdmin) {
|
if (!isAdmin) {
|
||||||
return res.code(403).send({
|
return res.code(403).send({
|
||||||
error: 'Forbidden',
|
error: 'Forbidden',
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
const { createHash } = require('crypto');
|
const { createHash } = require('crypto');
|
||||||
module.exports.md5 = str => createHash('md5').update(str).digest('hex');
|
module.exports.md5 = str => createHash('md5').update(str).digest('hex');
|
||||||
module.exports.msToMins = ms => Number((ms / 1000 / 60).toFixed(2));
|
module.exports.msToMins = ms => Number((ms / 1000 / 60).toFixed(2));
|
||||||
|
module.exports.iconURL = guildLike => guildLike.icon
|
||||||
|
? guildLike.client.rest.cdn.icon(guildLike.id, guildLike.icon)
|
||||||
|
: `https://api.dicebear.com/8.x/initials/png?seed=${encodeURIComponent(guildLike.name)}&size=96&backgroundType=gradientLinear&fontWeight=600`;
|
||||||
|
@ -46,3 +46,23 @@ module.exports.isStaff = async (guild, userId) => {
|
|||||||
const staffRoles = await client.keyv.get(`cache/guild-staff:${guild.id}`) || await updateStaffRoles(guild);
|
const staffRoles = await client.keyv.get(`cache/guild-staff:${guild.id}`) || await updateStaffRoles(guild);
|
||||||
return staffRoles.some(r => guildMember.roles.cache.has(r));
|
return staffRoles.some(r => guildMember.roles.cache.has(r));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("discord.js")} member
|
||||||
|
* @returns {Promise<number>}
|
||||||
|
* - `4` = OPERATOR (SUPER)
|
||||||
|
* - `3` = GUILD_OWNER
|
||||||
|
* - `2` = GUILD_ADMIN
|
||||||
|
* - `1` = GUILD_STAFF
|
||||||
|
* - `0` = GUILD_MEMBER
|
||||||
|
* - `-1` = NONE (NOT A MEMBER)
|
||||||
|
*/
|
||||||
|
module.exports.getPrivilegeLevel = async member => {
|
||||||
|
if (!member) return -1;
|
||||||
|
else if (member.guild.client.supers.includes(member.id)) return 4;
|
||||||
|
else if (member.guild.ownerId === member.id) return 3;
|
||||||
|
else if (member.permissions.has(PermissionsBitField.Flags.ManageGuild)) return 2;
|
||||||
|
else if (await this.isStaff(member.guild, member.id)) return 1;
|
||||||
|
else return 0;
|
||||||
|
};
|
||||||
|
@ -9,7 +9,7 @@ module.exports.delete = fastify => ({
|
|||||||
const guild = client.guilds.cache.get(req.params.guild);
|
const guild = client.guilds.cache.get(req.params.guild);
|
||||||
const categoryId = Number(req.params.category);
|
const categoryId = Number(req.params.category);
|
||||||
const original = categoryId && await client.prisma.category.findUnique({ where: { id: categoryId } });
|
const original = categoryId && await client.prisma.category.findUnique({ where: { id: categoryId } });
|
||||||
if (!original || original.guildId !== guild.id) return res.status(404).send(new Error('Not Found'));
|
if (!original || original.guildId !== guild.id) return res.status(400).send(new Error('Bad Request'));
|
||||||
const category = await client.prisma.category.delete({ where: { id: categoryId } });
|
const category = await client.prisma.category.delete({ where: { id: categoryId } });
|
||||||
|
|
||||||
await updateStaffRoles(guild);
|
await updateStaffRoles(guild);
|
||||||
@ -58,7 +58,7 @@ module.exports.get = fastify => ({
|
|||||||
where: { id: categoryId },
|
where: { id: categoryId },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!category || category.guildId !== guildId) return res.status(404).send(new Error('Not Found'));
|
if (!category || category.guildId !== guildId) return res.status(400).send(new Error('Bad Request'));
|
||||||
|
|
||||||
return category;
|
return category;
|
||||||
},
|
},
|
||||||
@ -118,7 +118,7 @@ module.exports.patch = fastify => ({
|
|||||||
where: { id: categoryId },
|
where: { id: categoryId },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!original || original.guildId !== guildId) return res.status(404).send(new Error('Not Found'));
|
if (!original || original.guildId !== guildId) return res.status(400).send(new Error('Bad Request'));
|
||||||
|
|
||||||
if (data.hasOwnProperty('id')) delete data.id;
|
if (data.hasOwnProperty('id')) delete data.id;
|
||||||
if (data.hasOwnProperty('createdAt')) delete data.createdAt;
|
if (data.hasOwnProperty('createdAt')) delete data.createdAt;
|
||||||
|
@ -9,7 +9,7 @@ module.exports.delete = fastify => ({
|
|||||||
const questionId = req.params.question;
|
const questionId = req.params.question;
|
||||||
const original = questionId && await client.prisma.question.findUnique({ where: { id: questionId } });
|
const original = questionId && await client.prisma.question.findUnique({ where: { id: questionId } });
|
||||||
const category = categoryId && await client.prisma.category.findUnique({ where: { id: categoryId } });
|
const category = categoryId && await client.prisma.category.findUnique({ where: { id: categoryId } });
|
||||||
if (original?.categoryId !== categoryId || category.guildId !== guildId) return res.status(404).send(new Error('Not Found'));
|
if (original?.categoryId !== categoryId || category.guildId !== guildId) return res.status(400).send(new Error('Bad Request'));
|
||||||
const question = await client.prisma.question.delete({ where: { id: questionId } });
|
const question = await client.prisma.question.delete({ where: { id: questionId } });
|
||||||
|
|
||||||
logAdminEvent(client, {
|
logAdminEvent(client, {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* eslint-disable no-underscore-dangle */
|
/* eslint-disable no-underscore-dangle */
|
||||||
|
const { iconURL } = require('../../../../../lib/misc');
|
||||||
const {
|
const {
|
||||||
getAvgResolutionTime,
|
getAvgResolutionTime,
|
||||||
getAvgResponseTime,
|
getAvgResponseTime,
|
||||||
@ -37,7 +38,7 @@ module.exports.get = fastify => ({
|
|||||||
cached = {
|
cached = {
|
||||||
createdAt: settings.createdAt,
|
createdAt: settings.createdAt,
|
||||||
id: guild.id,
|
id: guild.id,
|
||||||
logo: guild.iconURL(),
|
logo: iconURL(guild),
|
||||||
name: guild.name,
|
name: guild.name,
|
||||||
stats: {
|
stats: {
|
||||||
avgResolutionTime: ms(getAvgResolutionTime(closedTickets)),
|
avgResolutionTime: ms(getAvgResolutionTime(closedTickets)),
|
||||||
|
@ -8,7 +8,7 @@ module.exports.delete = fastify => ({
|
|||||||
const guildId = req.params.guild;
|
const guildId = req.params.guild;
|
||||||
const tagId = Number(req.params.tag);
|
const tagId = Number(req.params.tag);
|
||||||
const original = tagId && await client.prisma.tag.findUnique({ where: { id: tagId } });
|
const original = tagId && await client.prisma.tag.findUnique({ where: { id: tagId } });
|
||||||
if (original.guildId !== guildId) return res.status(404).send(new Error('Not Found'));
|
if (original.guildId !== guildId) return res.status(400).send(new Error('Bad Request'));
|
||||||
const tag = await client.prisma.tag.delete({ where: { id: tagId } });
|
const tag = await client.prisma.tag.delete({ where: { id: tagId } });
|
||||||
|
|
||||||
const cacheKey = `cache/guild-tags:${guildId}`;
|
const cacheKey = `cache/guild-tags:${guildId}`;
|
||||||
@ -46,7 +46,7 @@ module.exports.get = fastify => ({
|
|||||||
const tagId = Number(req.params.tag);
|
const tagId = Number(req.params.tag);
|
||||||
const tag = await client.prisma.tag.findUnique({ where: { id: tagId } });
|
const tag = await client.prisma.tag.findUnique({ where: { id: tagId } });
|
||||||
|
|
||||||
if (!tag || tag.guildId !== guildId) return res.status(404).send(new Error('Not Found'));
|
if (!tag || tag.guildId !== guildId) return res.status(400).send(new Error('Bad Request'));
|
||||||
|
|
||||||
return tag;
|
return tag;
|
||||||
},
|
},
|
||||||
@ -64,7 +64,7 @@ module.exports.patch = fastify => ({
|
|||||||
|
|
||||||
const original = req.params.tag && await client.prisma.tag.findUnique({ where: { id: tagId } });
|
const original = req.params.tag && await client.prisma.tag.findUnique({ where: { id: tagId } });
|
||||||
|
|
||||||
if (!original || original.guildId !== guildId) return res.status(404).send(new Error('Not Found'));
|
if (!original || original.guildId !== guildId) return res.status(400).send(new Error('Bad Request'));
|
||||||
|
|
||||||
if (data.hasOwnProperty('id')) delete data.id;
|
if (data.hasOwnProperty('id')) delete data.id;
|
||||||
if (data.hasOwnProperty('createdAt')) delete data.createdAt;
|
if (data.hasOwnProperty('createdAt')) delete data.createdAt;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
const { PermissionsBitField } = require('discord.js');
|
const { PermissionsBitField } = require('discord.js');
|
||||||
|
const { iconURL } = require('../../../../lib/misc');
|
||||||
|
|
||||||
module.exports.get = fastify => ({
|
module.exports.get = fastify => ({
|
||||||
handler: async (req, res) => {
|
handler: async (req, res) => {
|
||||||
@ -10,7 +11,14 @@ module.exports.get = fastify => ({
|
|||||||
.map(guild => ({
|
.map(guild => ({
|
||||||
added: client.guilds.cache.has(guild.id),
|
added: client.guilds.cache.has(guild.id),
|
||||||
id: guild.id,
|
id: guild.id,
|
||||||
logo: `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.webp`,
|
logo: iconURL(
|
||||||
|
client.guilds.cache.get(guild.id) ||
|
||||||
|
{
|
||||||
|
client,
|
||||||
|
icon: guild.icon,
|
||||||
|
id: guild.id,
|
||||||
|
},
|
||||||
|
),
|
||||||
name: guild.name,
|
name: guild.name,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
|
17
src/routes/api/guilds/[guild]/index.js
Normal file
17
src/routes/api/guilds/[guild]/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
const { getPrivilegeLevel } = require('../../../../lib/users');
|
||||||
|
const { iconURL } = require('../../../../lib/misc');
|
||||||
|
|
||||||
|
module.exports.get = fastify => ({
|
||||||
|
handler: async (req, res) => {
|
||||||
|
const { client } = req.routeOptions.config;
|
||||||
|
const guild = client.guilds.cache.get(req.params.guild);
|
||||||
|
res.send({
|
||||||
|
id: guild.id,
|
||||||
|
logo: iconURL(guild),
|
||||||
|
name: guild.name,
|
||||||
|
privilegeLevel: await getPrivilegeLevel(await guild.members.fetch(req.user.id)),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onRequest: [fastify.authenticate, fastify.isMember],
|
||||||
|
});
|
||||||
|
|
18
src/routes/api/guilds/[guild]/tickets/@me.js
Normal file
18
src/routes/api/guilds/[guild]/tickets/@me.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
module.exports.get = fastify => ({
|
||||||
|
handler: async (req, res) => {
|
||||||
|
const { client } = req.routeOptions.config;
|
||||||
|
/** @type {import("@prisma/client").PrismaClient} */
|
||||||
|
const prisma = client.prisma;
|
||||||
|
const guild = client.guilds.cache.get(req.params.guild);
|
||||||
|
res.send(
|
||||||
|
await prisma.ticket.findMany({
|
||||||
|
where: {
|
||||||
|
createdById: req.user.id,
|
||||||
|
guildId: guild.id,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onRequest: [fastify.authenticate, fastify.isMember],
|
||||||
|
});
|
||||||
|
|
25
src/routes/api/guilds/index.js
Normal file
25
src/routes/api/guilds/index.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
const { getPrivilegeLevel } = require('../../../lib/users');
|
||||||
|
const { iconURL } = require('../../../lib/misc');
|
||||||
|
|
||||||
|
module.exports.get = fastify => ({
|
||||||
|
handler: async (req, res) => {
|
||||||
|
const { client } = req.routeOptions.config;
|
||||||
|
const guilds = await (await fetch('https://discordapp.com/api/users/@me/guilds', { headers: { 'Authorization': `Bearer ${req.user.accessToken}` } })).json();
|
||||||
|
res.send(
|
||||||
|
await Promise.all(
|
||||||
|
guilds
|
||||||
|
.filter(partialGuild => client.guilds.cache.has(partialGuild.id))
|
||||||
|
.map(async partialGuild => {
|
||||||
|
const guild = client.guilds.cache.get(partialGuild.id);
|
||||||
|
return {
|
||||||
|
id: guild.id,
|
||||||
|
logo: iconURL(guild),
|
||||||
|
name: guild.name,
|
||||||
|
privilegeLevel: await getPrivilegeLevel(await guild.members.fetch(req.user.id)),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onRequest: [fastify.authenticate],
|
||||||
|
});
|
@ -19,7 +19,6 @@ module.exports.get = () => ({
|
|||||||
const token = this.jwt.sign({
|
const token = this.jwt.sign({
|
||||||
accessToken: data.access_token,
|
accessToken: data.access_token,
|
||||||
avatar: user.avatar,
|
avatar: user.avatar,
|
||||||
discriminator: user.discriminator,
|
|
||||||
expiresAt: Date.now() + (data.expires_in * 1000),
|
expiresAt: Date.now() + (data.expires_in * 1000),
|
||||||
id: user.id,
|
id: user.id,
|
||||||
locale: user.locale,
|
locale: user.locale,
|
||||||
@ -30,9 +29,16 @@ module.exports.get = () => ({
|
|||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
maxAge: data.expires_in,
|
maxAge: data.expires_in,
|
||||||
path: '/',
|
path: '/',
|
||||||
sameSite: 'Lax',
|
sameSite: 'Strict',
|
||||||
secure: false,
|
secure: false,
|
||||||
});
|
});
|
||||||
return res.redirect(redirect, 303);
|
res.header('Content-Type', 'text/html');
|
||||||
|
return res.send(`
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head><meta http-equiv="refresh" content="0; url='${redirect}'"></head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
||||||
|
`);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -18,9 +18,17 @@ module.exports.get = fastify => ({
|
|||||||
domain,
|
domain,
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
path: '/',
|
path: '/',
|
||||||
sameSite: 'Lax',
|
sameSite: 'Strict',
|
||||||
secure: false,
|
secure: false,
|
||||||
}).send('The token has been revoked.');
|
});
|
||||||
|
res.header('Content-Type', 'text/html');
|
||||||
|
return res.send(`
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head><meta http-equiv="refresh" content="0; url='/'"></head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
||||||
|
`);
|
||||||
},
|
},
|
||||||
onRequest: [fastify.authenticate],
|
onRequest: [fastify.authenticate],
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user