2021-12-21 12:55:10 +01:00
|
|
|
|
import { APIApplicationCommandInteraction, APIInteractionResponse, APIMessageComponentInteraction, APIPingInteraction, InteractionResponseType, InteractionType, MessageFlags, RouteBases, Routes } from 'discord-api-types/v9';
|
2022-04-10 21:09:37 +02:00
|
|
|
|
import { isJSON } from './utils/isJson';
|
2022-04-14 11:48:02 +02:00
|
|
|
|
import { resolvePartialEmoji } from './utils/resolveEmoji';
|
2022-04-10 21:09:37 +02:00
|
|
|
|
import { verify } from './utils/verify';
|
2021-12-21 12:55:10 +01:00
|
|
|
|
|
2022-01-02 18:54:19 +01:00
|
|
|
|
const respond = (response: APIInteractionResponse) => new Response(JSON.stringify(response), {headers: {'content-type': 'application/json'}});
|
2021-12-21 12:55:10 +01:00
|
|
|
|
|
|
|
|
|
const badFormatting = (rolesMax?: boolean) => {
|
2022-01-02 18:54:19 +01:00
|
|
|
|
return respond({
|
|
|
|
|
type: InteractionResponseType.ChannelMessageWithSource,
|
|
|
|
|
data: {
|
|
|
|
|
flags: 64,
|
|
|
|
|
content: `${rolesMax ? 'You can have maximum 25 buttons. (5x5)' : 'Bad formatting, generate [here](https://xhyrom.github.io/roles-bot)'}`
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
2021-12-21 12:55:10 +01:00
|
|
|
|
|
|
|
|
|
export const handleRequest = async(request: Request): Promise<Response> => {
|
2022-01-02 18:54:19 +01:00
|
|
|
|
if (!request.headers.get('X-Signature-Ed25519') || !request.headers.get('X-Signature-Timestamp')) return Response.redirect('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
|
|
|
|
|
if (!await verify(request)) return new Response('', { status: 401 });
|
|
|
|
|
|
|
|
|
|
const interaction = await request.json() as APIPingInteraction | APIApplicationCommandInteraction | APIMessageComponentInteraction;
|
|
|
|
|
|
|
|
|
|
if (interaction.type === InteractionType.Ping)
|
|
|
|
|
return respond({
|
|
|
|
|
type: InteractionResponseType.Pong
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (interaction.type === InteractionType.ApplicationCommand && interaction.data.name === 'setup') {
|
|
|
|
|
|
|
|
|
|
if ((Number(interaction.member?.permissions) & 0x10) !== 0x10) return respond({
|
|
|
|
|
type: InteractionResponseType.ChannelMessageWithSource,
|
|
|
|
|
data: {
|
|
|
|
|
flags: 64,
|
|
|
|
|
content: 'Required permissions: `MANAGE_ROLES`'
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
const json = isJSON(interaction.data.options[0].value) ? JSON.parse(interaction.data.options[0].value) : null;
|
|
|
|
|
|
|
|
|
|
if (!json) return badFormatting();
|
|
|
|
|
|
|
|
|
|
const channelId = json.channel;
|
2022-04-14 11:48:02 +02:00
|
|
|
|
let message = json.message?.toString();
|
2022-01-02 18:54:19 +01:00
|
|
|
|
let roles = json.roles;
|
|
|
|
|
|
|
|
|
|
if (!channelId) return badFormatting();
|
2022-04-14 11:48:02 +02:00
|
|
|
|
if (!message) message = '';
|
2022-01-02 18:54:19 +01:00
|
|
|
|
if (!roles || Object.values(json.roles).filter((role: any) => role.id && role.label).length === 0 || roles.length === 0 || roles.length > 25) return badFormatting(roles.length > 25);
|
|
|
|
|
|
|
|
|
|
roles = roles.map((r: any) => {
|
|
|
|
|
const o: any = {
|
|
|
|
|
type: 2,
|
|
|
|
|
style: r.style || 2,
|
|
|
|
|
label: r.label,
|
|
|
|
|
custom_id: r.id
|
|
|
|
|
};
|
|
|
|
|
|
2022-04-10 21:09:37 +02:00
|
|
|
|
if (r.emoji) o.emoji = resolvePartialEmoji(r.emoji);
|
2022-01-02 18:54:19 +01:00
|
|
|
|
|
|
|
|
|
return o;
|
|
|
|
|
});
|
|
|
|
|
|
2022-04-08 17:58:30 +02:00
|
|
|
|
let finalComponents = [];
|
2022-01-02 18:54:19 +01:00
|
|
|
|
for (let i = 0; i <= roles.length; i += 5) {
|
|
|
|
|
const row: any = {
|
|
|
|
|
type: 1,
|
|
|
|
|
components: []
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const btnslice: any = roles.slice(i, i + 5);
|
|
|
|
|
|
|
|
|
|
for (let y = 0; y < btnslice.length; y++) row.components.push(btnslice[y]);
|
2021-12-21 12:55:10 +01:00
|
|
|
|
|
2022-01-02 18:54:19 +01:00
|
|
|
|
finalComponents.push(row);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-08 17:58:30 +02:00
|
|
|
|
finalComponents = finalComponents.filter(a => a.components.length > 0);
|
|
|
|
|
|
2022-03-11 18:19:48 +01:00
|
|
|
|
const fetched = await fetch(`${RouteBases.api}/channels/${channelId}/messages`, {
|
2022-01-02 18:54:19 +01:00
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Authorization': `Bot ${CLIENT_TOKEN}`,
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify({
|
|
|
|
|
content: message,
|
|
|
|
|
components: finalComponents
|
|
|
|
|
})
|
2022-04-14 11:48:02 +02:00
|
|
|
|
}).catch(e => e);
|
2022-01-02 18:54:19 +01:00
|
|
|
|
|
|
|
|
|
return respond({
|
|
|
|
|
type: InteractionResponseType.ChannelMessageWithSource,
|
|
|
|
|
data: {
|
|
|
|
|
flags: 64,
|
2022-04-14 11:48:02 +02:00
|
|
|
|
content: fetched?.ok ? 'Done!' : 'Error, bad channel id/missing permissions.'
|
2022-01-02 18:54:19 +01:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else if (interaction.type === InteractionType.MessageComponent) {
|
|
|
|
|
const roleId = interaction.data.custom_id;
|
|
|
|
|
const url = `${RouteBases.api}${Routes.guildMemberRole(interaction.guild_id || '', interaction.member?.user.id || '', roleId)}`;
|
|
|
|
|
|
|
|
|
|
let method = '';
|
|
|
|
|
let content = '';
|
|
|
|
|
|
|
|
|
|
if (!interaction?.member?.roles?.includes(roleId)) {
|
|
|
|
|
content = `Gave the <@&${roleId}> role!`;
|
|
|
|
|
method = 'PUT';
|
|
|
|
|
} else {
|
|
|
|
|
content = `Removed the <@&${roleId}> role!`;
|
|
|
|
|
method = 'DELETE';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await fetch(url, {
|
|
|
|
|
method: method,
|
|
|
|
|
headers: {
|
|
|
|
|
'Authorization': `Bot ${CLIENT_TOKEN}`
|
|
|
|
|
}
|
|
|
|
|
}).catch(e => e);
|
2021-12-21 12:55:10 +01:00
|
|
|
|
|
2022-01-02 18:54:19 +01:00
|
|
|
|
return respond({
|
|
|
|
|
type: InteractionResponseType.ChannelMessageWithSource,
|
|
|
|
|
data: {
|
|
|
|
|
flags: MessageFlags.Ephemeral,
|
|
|
|
|
content: content,
|
|
|
|
|
allowed_mentions: { parse: [] }
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return respond({
|
|
|
|
|
type: InteractionResponseType.ChannelMessageWithSource,
|
|
|
|
|
data: {
|
|
|
|
|
flags: MessageFlags.Ephemeral,
|
|
|
|
|
content: 'Beep boop, boop beep?'
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|