mirror of
https://github.com/roleypoly/roleypoly.git
synced 2025-06-17 09:59:10 +00:00
feat: add /pickable-roles and /pick-role basis
This commit is contained in:
parent
c2ee4f380a
commit
a4207d5713
22 changed files with 343 additions and 23 deletions
|
@ -1,5 +1,8 @@
|
|||
import { helloWorld } from '@roleypoly/interactions/handlers/interactions/hello-world';
|
||||
import { pickableRoles } from '@roleypoly/interactions/handlers/interactions/pickable-roles';
|
||||
import { roleypoly } from '@roleypoly/interactions/handlers/interactions/roleypoly';
|
||||
import { verifyRequest } from '@roleypoly/interactions/utils/interactions';
|
||||
import { somethingWentWrong } from '@roleypoly/interactions/utils/responses';
|
||||
import {
|
||||
InteractionData,
|
||||
InteractionRequest,
|
||||
|
@ -14,6 +17,8 @@ const commands: Record<
|
|||
(request: InteractionRequestCommand) => Promise<InteractionResponse>
|
||||
> = {
|
||||
'hello-world': helloWorld,
|
||||
roleypoly: roleypoly,
|
||||
'pickable-roles': pickableRoles,
|
||||
};
|
||||
|
||||
export const interactionHandler = async (request: Request): Promise<Response> => {
|
||||
|
@ -44,6 +49,7 @@ export const interactionHandler = async (request: Request): Promise<Response> =>
|
|||
const response = await handler(interaction as InteractionRequestCommand);
|
||||
return respond(response);
|
||||
} catch (e) {
|
||||
return respond({ err: 'command errored' }, { status: 500 });
|
||||
console.error(e);
|
||||
return respond(somethingWentWrong());
|
||||
}
|
||||
};
|
||||
|
|
16
packages/interactions/handlers/interactions/pick-role.ts
Normal file
16
packages/interactions/handlers/interactions/pick-role.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import {
|
||||
InteractionCallbackType,
|
||||
InteractionRequestCommand,
|
||||
InteractionResponse,
|
||||
} from '@roleypoly/types';
|
||||
|
||||
export const helloWorld = async (
|
||||
interaction: InteractionRequestCommand
|
||||
): Promise<InteractionResponse> => {
|
||||
return {
|
||||
type: InteractionCallbackType.CHANNEL_MESSAGE_WITH_SOURCE,
|
||||
data: {
|
||||
content: `Hey there, ${interaction.member?.nick || interaction.user?.username}`,
|
||||
},
|
||||
};
|
||||
};
|
|
@ -0,0 +1,58 @@
|
|||
import { getPickableRoles } from '@roleypoly/interactions/utils/api';
|
||||
import { uiPublicURI } from '@roleypoly/interactions/utils/config';
|
||||
import { mustBeInGuild } from '@roleypoly/interactions/utils/responses';
|
||||
import {
|
||||
CategoryType,
|
||||
Embed,
|
||||
InteractionCallbackType,
|
||||
InteractionFlags,
|
||||
InteractionRequestCommand,
|
||||
InteractionResponse,
|
||||
} from '@roleypoly/types';
|
||||
|
||||
export const pickableRoles = async (
|
||||
interaction: InteractionRequestCommand
|
||||
): Promise<InteractionResponse> => {
|
||||
if (!interaction.guild_id) {
|
||||
return mustBeInGuild();
|
||||
}
|
||||
|
||||
const pickableRoles = await getPickableRoles(interaction.guild_id);
|
||||
const embed: Embed = {
|
||||
color: 0xab9b9a,
|
||||
fields: [],
|
||||
title: 'You can pick any of these roles with /pick-role',
|
||||
};
|
||||
|
||||
for (let categoryName in pickableRoles) {
|
||||
const { roles, type } = pickableRoles[categoryName];
|
||||
|
||||
embed.fields.push({
|
||||
name: `${categoryName}${type === CategoryType.Single ? ' *(pick one)*' : ''}`,
|
||||
value: roles.map((role) => `<@&${role}>`).join('\n'),
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
type: InteractionCallbackType.CHANNEL_MESSAGE_WITH_SOURCE,
|
||||
data: {
|
||||
embeds: [embed],
|
||||
flags: InteractionFlags.EPHEMERAL,
|
||||
components: [
|
||||
{
|
||||
type: 1,
|
||||
components: [
|
||||
// Link to Roleypoly
|
||||
{
|
||||
type: 2,
|
||||
label: 'Pick roles on your browser',
|
||||
url: `${uiPublicURI}/s/${interaction.guild_id}`,
|
||||
style: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
};
|
28
packages/interactions/handlers/interactions/roleypoly.ts
Normal file
28
packages/interactions/handlers/interactions/roleypoly.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { uiPublicURI } from '@roleypoly/interactions/utils/config';
|
||||
import {
|
||||
InteractionCallbackType,
|
||||
InteractionFlags,
|
||||
InteractionRequestCommand,
|
||||
InteractionResponse,
|
||||
} from '@roleypoly/types';
|
||||
|
||||
export const roleypoly = async (
|
||||
interaction: InteractionRequestCommand
|
||||
): Promise<InteractionResponse> => {
|
||||
if (interaction.guild_id) {
|
||||
return {
|
||||
type: InteractionCallbackType.CHANNEL_MESSAGE_WITH_SOURCE,
|
||||
data: {
|
||||
content: `:beginner: Assign your roles here! ${uiPublicURI}/s/${interaction.guild_id}`,
|
||||
flags: InteractionFlags.EPHEMERAL,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: InteractionCallbackType.CHANNEL_MESSAGE_WITH_SOURCE,
|
||||
data: {
|
||||
content: `:beginner: Hey! I don't know what server you're in, so check out ${uiPublicURI}`,
|
||||
},
|
||||
};
|
||||
};
|
25
packages/interactions/utils/api.ts
Normal file
25
packages/interactions/utils/api.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { Category, CategorySlug } from '@roleypoly/types';
|
||||
import { apiPublicURI, interactionsSharedKey } from './config';
|
||||
|
||||
export const apiFetch = (url: string, init: RequestInit = {}) =>
|
||||
fetch(`${apiPublicURI}${url}`, {
|
||||
...init,
|
||||
headers: {
|
||||
...(init.headers || {}),
|
||||
authorization: `Shared ${interactionsSharedKey}`,
|
||||
},
|
||||
});
|
||||
|
||||
export const getPickableRoles = async (
|
||||
guildID: string
|
||||
): Promise<Record<Category['name'], CategorySlug>> => {
|
||||
const response = await apiFetch(`/interactions-pickable-roles/${guildID}`);
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(
|
||||
`API request failed to /interactions-pickable-roles, got code: ${response.status}`
|
||||
);
|
||||
}
|
||||
|
||||
return (await response.json()) as Record<Category['name'], CategorySlug>;
|
||||
};
|
|
@ -8,3 +8,4 @@ const list = (x: string) => x.split(',');
|
|||
export const uiPublicURI = safeURI(env('UI_PUBLIC_URI'));
|
||||
export const apiPublicURI = safeURI(env('API_PUBLIC_URI'));
|
||||
export const publicKey = safeURI(env('DISCORD_PUBLIC_KEY'));
|
||||
export const interactionsSharedKey = env('INTERACTIONS_SHARED_KEY');
|
||||
|
|
21
packages/interactions/utils/responses.ts
Normal file
21
packages/interactions/utils/responses.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import {
|
||||
InteractionCallbackType,
|
||||
InteractionFlags,
|
||||
InteractionResponse,
|
||||
} from '@roleypoly/types';
|
||||
|
||||
export const mustBeInGuild = (): InteractionResponse => ({
|
||||
type: InteractionCallbackType.CHANNEL_MESSAGE_WITH_SOURCE,
|
||||
data: {
|
||||
content: ':x: This command has to be used in a server.',
|
||||
flags: InteractionFlags.EPHEMERAL,
|
||||
},
|
||||
});
|
||||
|
||||
export const somethingWentWrong = (): InteractionResponse => ({
|
||||
type: InteractionCallbackType.CHANNEL_MESSAGE_WITH_SOURCE,
|
||||
data: {
|
||||
content: '<a:promareFlame:624850108667789333> Something went terribly wrong.',
|
||||
flags: InteractionFlags.EPHEMERAL,
|
||||
},
|
||||
});
|
|
@ -3,5 +3,10 @@ const reexportEnv = (keys = []) => {
|
|||
};
|
||||
|
||||
module.exports = {
|
||||
environment: reexportEnv(['DISCORD_PUBLIC_KEY', 'UI_PUBLIC_URI', 'API_PUBLIC_URI']),
|
||||
environment: reexportEnv([
|
||||
'DISCORD_PUBLIC_KEY',
|
||||
'UI_PUBLIC_URI',
|
||||
'API_PUBLIC_URI',
|
||||
'INTERACTIONS_SHARED_KEY',
|
||||
]),
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue