Skip to content

Commit

Permalink
feat: guild onboarding (#9120)
Browse files Browse the repository at this point in the history
* feat: guild onboarding

* feat: types and /core method

* fix: route

* fix: make emoji name non-nullable

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
almeidx and kodiakhq[bot] authored Jul 7, 2023
1 parent a48d0ef commit dc73c93
Show file tree
Hide file tree
Showing 9 changed files with 393 additions and 92 deletions.
196 changes: 104 additions & 92 deletions packages/core/src/api/guild.ts
Original file line number Diff line number Diff line change
@@ -1,98 +1,99 @@
/* eslint-disable jsdoc/check-param-names */

import { makeURLSearchParams, type REST, type RawFile, type RequestData } from '@discordjs/rest';
import { Routes } from 'discord-api-types/v10';
import type {
RESTPatchAPIGuildVoiceStateCurrentMemberJSONBody,
RESTPatchAPIGuildVoiceStateCurrentMemberResult,
GuildMFALevel,
GuildWidgetStyle,
RESTGetAPIAuditLogQuery,
RESTGetAPIAuditLogResult,
RESTGetAPIAutoModerationRuleResult,
RESTGetAPIAutoModerationRulesResult,
RESTGetAPIGuildBanResult,
RESTGetAPIGuildBansQuery,
RESTGetAPIGuildBansResult,
RESTGetAPIGuildChannelsResult,
RESTGetAPIGuildEmojiResult,
RESTGetAPIGuildEmojisResult,
RESTGetAPIGuildIntegrationsResult,
RESTGetAPIGuildInvitesResult,
RESTGetAPIGuildMemberResult,
RESTGetAPIGuildMembersResult,
RESTGetAPIGuildMembersQuery,
RESTGetAPIGuildMembersSearchResult,
RESTGetAPIGuildPreviewResult,
RESTGetAPIGuildPruneCountResult,
RESTGetAPIGuildResult,
RESTGetAPIGuildRolesResult,
RESTGetAPIGuildScheduledEventQuery,
RESTGetAPIGuildScheduledEventResult,
RESTGetAPIGuildScheduledEventsQuery,
RESTGetAPIGuildScheduledEventsResult,
RESTGetAPIGuildScheduledEventUsersQuery,
RESTGetAPIGuildScheduledEventUsersResult,
RESTGetAPIGuildStickerResult,
RESTGetAPIGuildStickersResult,
RESTGetAPIGuildTemplatesResult,
RESTGetAPIGuildThreadsResult,
RESTGetAPIGuildVanityUrlResult,
RESTGetAPIGuildVoiceRegionsResult,
RESTGetAPIGuildPruneCountQuery,
RESTPostAPIGuildStickerFormDataBody,
RESTPostAPIGuildStickerResult,
RESTGetAPIGuildMembersSearchQuery,
RESTGetAPIGuildWebhooksResult,
RESTGetAPIGuildWelcomeScreenResult,
RESTGetAPIGuildWidgetImageResult,
RESTGetAPIGuildWidgetJSONResult,
RESTGetAPIGuildWidgetSettingsResult,
RESTGetAPITemplateResult,
RESTPatchAPIAutoModerationRuleJSONBody,
RESTPatchAPIAutoModerationRuleResult,
RESTPatchAPIGuildChannelPositionsJSONBody,
RESTPatchAPIGuildEmojiJSONBody,
RESTPatchAPIGuildEmojiResult,
RESTPatchAPIGuildJSONBody,
RESTPatchAPIGuildMemberJSONBody,
RESTPatchAPIGuildMemberResult,
RESTPatchAPIGuildResult,
RESTPatchAPIGuildRoleJSONBody,
RESTPatchAPIGuildRolePositionsJSONBody,
RESTPatchAPIGuildRolePositionsResult,
RESTPatchAPIGuildRoleResult,
RESTPatchAPIGuildScheduledEventJSONBody,
RESTPatchAPIGuildScheduledEventResult,
RESTPatchAPIGuildStickerJSONBody,
RESTPatchAPIGuildStickerResult,
RESTPatchAPIGuildTemplateJSONBody,
RESTPatchAPIGuildTemplateResult,
RESTPatchAPIGuildVoiceStateUserJSONBody,
RESTPatchAPIGuildWelcomeScreenJSONBody,
RESTPatchAPIGuildWelcomeScreenResult,
RESTPatchAPIGuildWidgetSettingsJSONBody,
RESTPatchAPIGuildWidgetSettingsResult,
RESTPostAPIAutoModerationRuleJSONBody,
RESTPostAPIAutoModerationRuleResult,
RESTPostAPIGuildChannelJSONBody,
RESTPostAPIGuildChannelResult,
RESTPostAPIGuildEmojiJSONBody,
RESTPostAPIGuildEmojiResult,
RESTPostAPIGuildPruneJSONBody,
RESTPostAPIGuildPruneResult,
RESTPostAPIGuildRoleJSONBody,
RESTPostAPIGuildRoleResult,
RESTPostAPIGuildScheduledEventJSONBody,
RESTPostAPIGuildScheduledEventResult,
RESTPostAPIGuildsJSONBody,
RESTPostAPIGuildsMFAResult,
RESTPostAPIGuildsResult,
RESTPostAPIGuildTemplatesJSONBody,
RESTPostAPIGuildTemplatesResult,
RESTPutAPIGuildBanJSONBody,
RESTPutAPIGuildTemplateSyncResult,
Snowflake,
import {
Routes,
type GuildMFALevel,
type GuildWidgetStyle,
type RESTGetAPIAuditLogQuery,
type RESTGetAPIAuditLogResult,
type RESTGetAPIAutoModerationRuleResult,
type RESTGetAPIAutoModerationRulesResult,
type RESTGetAPIGuildBanResult,
type RESTGetAPIGuildBansQuery,
type RESTGetAPIGuildBansResult,
type RESTGetAPIGuildChannelsResult,
type RESTGetAPIGuildEmojiResult,
type RESTGetAPIGuildEmojisResult,
type RESTGetAPIGuildIntegrationsResult,
type RESTGetAPIGuildInvitesResult,
type RESTGetAPIGuildMemberResult,
type RESTGetAPIGuildMembersQuery,
type RESTGetAPIGuildMembersResult,
type RESTGetAPIGuildMembersSearchQuery,
type RESTGetAPIGuildMembersSearchResult,
type RESTGetAPIGuildOnboardingResult,
type RESTGetAPIGuildPreviewResult,
type RESTGetAPIGuildPruneCountQuery,
type RESTGetAPIGuildPruneCountResult,
type RESTGetAPIGuildResult,
type RESTGetAPIGuildRolesResult,
type RESTGetAPIGuildScheduledEventQuery,
type RESTGetAPIGuildScheduledEventResult,
type RESTGetAPIGuildScheduledEventUsersQuery,
type RESTGetAPIGuildScheduledEventUsersResult,
type RESTGetAPIGuildScheduledEventsQuery,
type RESTGetAPIGuildScheduledEventsResult,
type RESTGetAPIGuildStickerResult,
type RESTGetAPIGuildStickersResult,
type RESTGetAPIGuildTemplatesResult,
type RESTGetAPIGuildThreadsResult,
type RESTGetAPIGuildVanityUrlResult,
type RESTGetAPIGuildVoiceRegionsResult,
type RESTGetAPIGuildWebhooksResult,
type RESTGetAPIGuildWelcomeScreenResult,
type RESTGetAPIGuildWidgetImageResult,
type RESTGetAPIGuildWidgetJSONResult,
type RESTGetAPIGuildWidgetSettingsResult,
type RESTGetAPITemplateResult,
type RESTPatchAPIAutoModerationRuleJSONBody,
type RESTPatchAPIAutoModerationRuleResult,
type RESTPatchAPIGuildChannelPositionsJSONBody,
type RESTPatchAPIGuildEmojiJSONBody,
type RESTPatchAPIGuildEmojiResult,
type RESTPatchAPIGuildJSONBody,
type RESTPatchAPIGuildMemberJSONBody,
type RESTPatchAPIGuildMemberResult,
type RESTPatchAPIGuildResult,
type RESTPatchAPIGuildRoleJSONBody,
type RESTPatchAPIGuildRolePositionsJSONBody,
type RESTPatchAPIGuildRolePositionsResult,
type RESTPatchAPIGuildRoleResult,
type RESTPatchAPIGuildScheduledEventJSONBody,
type RESTPatchAPIGuildScheduledEventResult,
type RESTPatchAPIGuildStickerJSONBody,
type RESTPatchAPIGuildStickerResult,
type RESTPatchAPIGuildTemplateJSONBody,
type RESTPatchAPIGuildTemplateResult,
type RESTPatchAPIGuildVoiceStateCurrentMemberJSONBody,
type RESTPatchAPIGuildVoiceStateCurrentMemberResult,
type RESTPatchAPIGuildVoiceStateUserJSONBody,
type RESTPatchAPIGuildWelcomeScreenJSONBody,
type RESTPatchAPIGuildWelcomeScreenResult,
type RESTPatchAPIGuildWidgetSettingsJSONBody,
type RESTPatchAPIGuildWidgetSettingsResult,
type RESTPostAPIAutoModerationRuleJSONBody,
type RESTPostAPIAutoModerationRuleResult,
type RESTPostAPIGuildChannelJSONBody,
type RESTPostAPIGuildChannelResult,
type RESTPostAPIGuildEmojiJSONBody,
type RESTPostAPIGuildEmojiResult,
type RESTPostAPIGuildPruneJSONBody,
type RESTPostAPIGuildPruneResult,
type RESTPostAPIGuildRoleJSONBody,
type RESTPostAPIGuildRoleResult,
type RESTPostAPIGuildScheduledEventJSONBody,
type RESTPostAPIGuildScheduledEventResult,
type RESTPostAPIGuildStickerFormDataBody,
type RESTPostAPIGuildStickerResult,
type RESTPostAPIGuildTemplatesJSONBody,
type RESTPostAPIGuildTemplatesResult,
type RESTPostAPIGuildsJSONBody,
type RESTPostAPIGuildsMFAResult,
type RESTPostAPIGuildsResult,
type RESTPutAPIGuildBanJSONBody,
type RESTPutAPIGuildTemplateSyncResult,
type Snowflake,
} from 'discord-api-types/v10';

export class GuildsAPI {
Expand Down Expand Up @@ -1229,4 +1230,15 @@ export class GuildsAPI {
body,
}) as Promise<RESTPatchAPIGuildVoiceStateCurrentMemberResult>;
}

/**
* Fetches a guild onboarding
*
* @see {@link https://discord.com/developers/docs/resources/guild#get-guild-onboarding}
* @param guildId - The id of the guild
* @param options - The options for fetching the guild onboarding
*/
public async getOnboarding(guildId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.guildOnboarding(guildId), { signal }) as Promise<RESTGetAPIGuildOnboardingResult>;
}
}
3 changes: 3 additions & 0 deletions packages/discord.js/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ exports.GuildBan = require('./structures/GuildBan');
exports.GuildChannel = require('./structures/GuildChannel');
exports.GuildEmoji = require('./structures/GuildEmoji');
exports.GuildMember = require('./structures/GuildMember').GuildMember;
exports.GuildOnboarding = require('./structures/GuildOnboarding').GuildOnboarding;
exports.GuildOnboardingPrompt = require('./structures/GuildOnboardingPrompt').GuildOnboardingPrompt;
exports.GuildOnboardingPromptOption = require('./structures/GuildOnboardingPromptOption').GuildOnboardingPromptOption;
exports.GuildPreview = require('./structures/GuildPreview');
exports.GuildPreviewEmoji = require('./structures/GuildPreviewEmoji');
exports.GuildScheduledEvent = require('./structures/GuildScheduledEvent').GuildScheduledEvent;
Expand Down
10 changes: 10 additions & 0 deletions packages/discord.js/src/structures/Guild.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { makeURLSearchParams } = require('@discordjs/rest');
const { ChannelType, GuildPremiumTier, Routes, GuildFeature } = require('discord-api-types/v10');
const AnonymousGuild = require('./AnonymousGuild');
const GuildAuditLogs = require('./GuildAuditLogs');
const { GuildOnboarding } = require('./GuildOnboarding');
const GuildPreview = require('./GuildPreview');
const GuildTemplate = require('./GuildTemplate');
const Integration = require('./Integration');
Expand Down Expand Up @@ -760,6 +761,15 @@ class Guild extends AnonymousGuild {
return new GuildAuditLogs(this, data);
}

/**
* Fetches the guild onboarding data for this guild.
* @returns {Promise<GuildOnboarding>}
*/
async fetchOnboarding() {
const data = await this.client.rest.get(Routes.guildOnboarding(this.id));
return new GuildOnboarding(this.client, data);
}

/**
* The data for editing a guild.
* @typedef {Object} GuildEditOptions
Expand Down
58 changes: 58 additions & 0 deletions packages/discord.js/src/structures/GuildOnboarding.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
'use strict';

const { Collection } = require('@discordjs/collection');
const Base = require('./Base');
const { GuildOnboardingPrompt } = require('./GuildOnboardingPrompt');

/**
* Represents the onboarding data of a guild.
* @extends {Base}
*/
class GuildOnboarding extends Base {
constructor(client, data) {
super(client);

/**
* The id of the guild this onboarding data is for
* @type {Snowflake}
*/
this.guildId = data.guild_id;

const guild = this.guild;

/**
* The prompts shown during onboarding and in customize community
* @type {Collection<Snowflake, GuildOnboardingPrompt>}
*/
this.prompts = data.prompts.reduce(
(prompts, prompt) => prompts.set(prompt.id, new GuildOnboardingPrompt(client, prompt, this.guildId)),
new Collection(),
);

/**
* The ids of the channels that new members get opted into automatically
* @type {Collection<Snowflake, GuildChannel>}
*/
this.defaultChannels = data.default_channel_ids.reduce(
(channels, channelId) => channels.set(channelId, guild.channels.cache.get(channelId)),
new Collection(),
);

/**
* Whether onboarding is enabled
* @type {boolean}
*/
this.enabled = data.enabled;
}

/**
* The guild this onboarding is from
* @type {Guild}
* @readonly
*/
get guild() {
return this.client.guilds.cache.get(this.guildId);
}
}

exports.GuildOnboarding = GuildOnboarding;
78 changes: 78 additions & 0 deletions packages/discord.js/src/structures/GuildOnboardingPrompt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
'use strict';

const { Collection } = require('@discordjs/collection');
const Base = require('./Base');
const { GuildOnboardingPromptOption } = require('./GuildOnboardingPromptOption');

/**
* Represents the data of a prompt of a guilds onboarding.
* @extends {Base}
*/
class GuildOnboardingPrompt extends Base {
constructor(client, data, guildId) {
super(client);

/**
* The id of the guild this onboarding prompt is from
* @type {Snowflake}
*/
this.guildId = guildId;

/**
* The id of the prompt
* @type {Snowflake}
*/
this.id = data.id;

/**
* The options available within the prompt
* @type {Collection<Snowflake, GuildOnboardingPromptOption>}
*/
this.options = data.options.reduce(
(options, option) => options.set(option.id, new GuildOnboardingPromptOption(client, option, guildId)),
new Collection(),
);

/**
* The title of the prompt
* @type {string}
*/
this.title = data.title;

/**
* Whether users are limited to selecting one option for the prompt
* @type {boolean}
*/
this.singleSelect = data.single_select;

/**
* Whether the prompt is required before a user completes the onboarding flow
* @type {boolean}
*/
this.required = data.required;

/**
* Whether the prompt is present in the onboarding flow.
* If `false`, the prompt will only appear in the Channels & Roles tab
* @type {boolean}
*/
this.inOnboarding = data.in_onboarding;

/**
* The type of the prompt
* @type {GuildOnboardingPromptType}
*/
this.type = data.type;
}

/**
* The guild this onboarding prompt is from
* @type {Guild}
* @readonly
*/
get guild() {
return this.client.guilds.cache.get(this.guildId);
}
}

exports.GuildOnboardingPrompt = GuildOnboardingPrompt;
Loading

0 comments on commit dc73c93

Please sign in to comment.