mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-16 03:23:29 +01:00
feat: recurring scheduled events (#10447)
* feat: recurring scheduled events * fix: nullable on patch * docs: remove unnecessary parenthesis Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com> --------- Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
This commit is contained in:
@@ -7,6 +7,7 @@ const CachedManager = require('./CachedManager');
|
|||||||
const { DiscordjsTypeError, DiscordjsError, ErrorCodes } = require('../errors');
|
const { DiscordjsTypeError, DiscordjsError, ErrorCodes } = require('../errors');
|
||||||
const { GuildScheduledEvent } = require('../structures/GuildScheduledEvent');
|
const { GuildScheduledEvent } = require('../structures/GuildScheduledEvent');
|
||||||
const { resolveImage } = require('../util/DataResolver');
|
const { resolveImage } = require('../util/DataResolver');
|
||||||
|
const { _transformGuildScheduledEventRecurrenceRule } = require('../util/Transformers');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages API methods for GuildScheduledEvents and stores their cache.
|
* Manages API methods for GuildScheduledEvents and stores their cache.
|
||||||
@@ -36,6 +37,21 @@ class GuildScheduledEventManager extends CachedManager {
|
|||||||
* @typedef {Snowflake|GuildScheduledEvent} GuildScheduledEventResolvable
|
* @typedef {Snowflake|GuildScheduledEvent} GuildScheduledEventResolvable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for setting a recurrence rule for a guild scheduled event.
|
||||||
|
* @typedef {Object} GuildScheduledEventRecurrenceRuleOptions
|
||||||
|
* @property {DateResolvable} startAt The time the recurrence rule interval starts at
|
||||||
|
* @property {?DateResolvable} endAt The time the recurrence rule interval ends at
|
||||||
|
* @property {GuildScheduledEventRecurrenceRuleFrequency} frequency How often the event occurs
|
||||||
|
* @property {number} interval The spacing between the events
|
||||||
|
* @property {?GuildScheduledEventRecurrenceRuleWeekday[]} byWeekday The days within a week to recur on
|
||||||
|
* @property {?GuildScheduledEventRecurrenceRuleNWeekday[]} byNWeekday The days within a week to recur on
|
||||||
|
* @property {?GuildScheduledEventRecurrenceRuleMonth[]} byMonth The months to recur on
|
||||||
|
* @property {?number[]} byMonthDay The days within a month to recur on
|
||||||
|
* @property {?number[]} byYearDay The days within a year to recur on
|
||||||
|
* @property {?number} count The total amount of times the event is allowed to recur before stopping
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options used to create a guild scheduled event.
|
* Options used to create a guild scheduled event.
|
||||||
* @typedef {Object} GuildScheduledEventCreateOptions
|
* @typedef {Object} GuildScheduledEventCreateOptions
|
||||||
@@ -54,6 +70,8 @@ class GuildScheduledEventManager extends CachedManager {
|
|||||||
* <warn>This is required if `entityType` is {@link GuildScheduledEventEntityType.External}</warn>
|
* <warn>This is required if `entityType` is {@link GuildScheduledEventEntityType.External}</warn>
|
||||||
* @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event
|
* @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event
|
||||||
* @property {string} [reason] The reason for creating the guild scheduled event
|
* @property {string} [reason] The reason for creating the guild scheduled event
|
||||||
|
* @property {GuildScheduledEventRecurrenceRuleOptions} [recurrenceRule]
|
||||||
|
* The recurrence rule of the guild scheduled event
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,6 +99,7 @@ class GuildScheduledEventManager extends CachedManager {
|
|||||||
entityMetadata,
|
entityMetadata,
|
||||||
reason,
|
reason,
|
||||||
image,
|
image,
|
||||||
|
recurrenceRule,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
let entity_metadata, channel_id;
|
let entity_metadata, channel_id;
|
||||||
@@ -104,6 +123,7 @@ class GuildScheduledEventManager extends CachedManager {
|
|||||||
entity_type: entityType,
|
entity_type: entityType,
|
||||||
entity_metadata,
|
entity_metadata,
|
||||||
image: image && (await resolveImage(image)),
|
image: image && (await resolveImage(image)),
|
||||||
|
recurrence_rule: recurrenceRule && _transformGuildScheduledEventRecurrenceRule(recurrenceRule),
|
||||||
},
|
},
|
||||||
reason,
|
reason,
|
||||||
});
|
});
|
||||||
@@ -178,6 +198,8 @@ class GuildScheduledEventManager extends CachedManager {
|
|||||||
* {@link GuildScheduledEventEntityType.External}</warn>
|
* {@link GuildScheduledEventEntityType.External}</warn>
|
||||||
* @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event
|
* @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event
|
||||||
* @property {string} [reason] The reason for editing the guild scheduled event
|
* @property {string} [reason] The reason for editing the guild scheduled event
|
||||||
|
* @property {?GuildScheduledEventRecurrenceRuleOptions} [recurrenceRule]
|
||||||
|
* The recurrence rule of the guild scheduled event
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -203,6 +225,7 @@ class GuildScheduledEventManager extends CachedManager {
|
|||||||
entityMetadata,
|
entityMetadata,
|
||||||
reason,
|
reason,
|
||||||
image,
|
image,
|
||||||
|
recurrenceRule,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
let entity_metadata;
|
let entity_metadata;
|
||||||
@@ -224,6 +247,7 @@ class GuildScheduledEventManager extends CachedManager {
|
|||||||
status,
|
status,
|
||||||
image: image && (await resolveImage(image)),
|
image: image && (await resolveImage(image)),
|
||||||
entity_metadata,
|
entity_metadata,
|
||||||
|
recurrence_rule: recurrenceRule && _transformGuildScheduledEventRecurrenceRule(recurrenceRule),
|
||||||
},
|
},
|
||||||
reason,
|
reason,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -189,6 +189,56 @@ class GuildScheduledEvent extends Base {
|
|||||||
} else {
|
} else {
|
||||||
this.image ??= null;
|
this.image ??= null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the recurrence rule for a {@link GuildScheduledEvent}.
|
||||||
|
* @typedef {Object} GuildScheduledEventRecurrenceRule
|
||||||
|
* @property {number} startTimestamp The timestamp the recurrence rule interval starts at
|
||||||
|
* @property {Date} startAt The time the recurrence rule interval starts at
|
||||||
|
* @property {?number} endTimestamp The timestamp the recurrence rule interval ends at
|
||||||
|
* @property {?Date} endAt The time the recurrence rule interval ends at
|
||||||
|
* @property {GuildScheduledEventRecurrenceRuleFrequency} frequency How often the event occurs
|
||||||
|
* @property {number} interval The spacing between the events
|
||||||
|
* @property {?GuildScheduledEventRecurrenceRuleWeekday[]} byWeekday The days within a week to recur on
|
||||||
|
* @property {?GuildScheduledEventRecurrenceRuleNWeekday[]} byNWeekday The days within a week to recur on
|
||||||
|
* @property {?GuildScheduledEventRecurrenceRuleMonth[]} byMonth The months to recur on
|
||||||
|
* @property {?number[]} byMonthDay The days within a month to recur on
|
||||||
|
* @property {?number[]} byYearDay The days within a year to recur on
|
||||||
|
* @property {?number} count The total amount of times the event is allowed to recur before stopping
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} GuildScheduledEventRecurrenceRuleNWeekday
|
||||||
|
* @property {number} n The week to recur on
|
||||||
|
* @property {GuildScheduledEventRecurrenceRuleWeekday} day The day within the week to recur on
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ('recurrence_rule' in data) {
|
||||||
|
/**
|
||||||
|
* The recurrence rule for this scheduled event
|
||||||
|
* @type {?GuildScheduledEventRecurrenceRule}
|
||||||
|
*/
|
||||||
|
this.recurrenceRule = {
|
||||||
|
startTimestamp: Date.parse(data.recurrence_rule.start),
|
||||||
|
get startAt() {
|
||||||
|
return new Date(this.startTimestamp);
|
||||||
|
},
|
||||||
|
endTimestamp: data.recurrence_rule.end && Date.parse(data.recurrence_rule.end),
|
||||||
|
get endAt() {
|
||||||
|
return this.endTimestamp && new Date(this.endTimestamp);
|
||||||
|
},
|
||||||
|
frequency: data.recurrence_rule.frequency,
|
||||||
|
interval: data.recurrence_rule.interval,
|
||||||
|
byWeekday: data.recurrence_rule.by_weekday,
|
||||||
|
byNWeekday: data.recurrence_rule.by_n_weekday,
|
||||||
|
byMonth: data.recurrence_rule.by_month,
|
||||||
|
byMonthDay: data.recurrence_rule.by_month_day,
|
||||||
|
byYearDay: data.recurrence_rule.by_year_day,
|
||||||
|
count: data.recurrence_rule.count,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
this.recurrenceRule ??= null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -100,6 +100,11 @@
|
|||||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APIGuildMember}
|
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APIGuildMember}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @external APIGuildScheduledEventRecurrenceRule
|
||||||
|
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APIGuildScheduledEventRecurrenceRule}
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @external APIInteraction
|
* @external APIInteraction
|
||||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10#APIInteraction}
|
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10#APIInteraction}
|
||||||
@@ -390,6 +395,21 @@
|
|||||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildScheduledEventPrivacyLevel}
|
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildScheduledEventPrivacyLevel}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @external GuildScheduledEventRecurrenceRuleFrequency
|
||||||
|
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildScheduledEventRecurrenceRuleFrequency}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @external GuildScheduledEventRecurrenceRuleMonth
|
||||||
|
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildScheduledEventRecurrenceRuleMonth}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @external GuildScheduledEventRecurrenceRuleWeekday
|
||||||
|
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildScheduledEventRecurrenceRuleWeekday}
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @external GuildScheduledEventStatus
|
* @external GuildScheduledEventStatus
|
||||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildScheduledEventStatus}
|
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildScheduledEventStatus}
|
||||||
|
|||||||
@@ -54,4 +54,31 @@ function _transformAPIMessageInteractionMetadata(client, messageInteractionMetad
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { toSnakeCase, _transformAPIAutoModerationAction, _transformAPIMessageInteractionMetadata };
|
/**
|
||||||
|
* Transforms a guild scheduled event recurrence rule object to a snake-cased variant.
|
||||||
|
* @param {GuildScheduledEventRecurrenceRuleOptions} recurrenceRule The recurrence rule to transform
|
||||||
|
* @returns {APIGuildScheduledEventRecurrenceRule}
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
function _transformGuildScheduledEventRecurrenceRule(recurrenceRule) {
|
||||||
|
return {
|
||||||
|
start: new Date(recurrenceRule.startAt).toISOString(),
|
||||||
|
// eslint-disable-next-line eqeqeq
|
||||||
|
end: recurrenceRule.endAt != null ? new Date(recurrenceRule.endAt).toISOString() : recurrenceRule.endAt,
|
||||||
|
frequency: recurrenceRule.frequency,
|
||||||
|
interval: recurrenceRule.interval,
|
||||||
|
by_weekday: recurrenceRule.byWeekday,
|
||||||
|
by_n_weekday: recurrenceRule.byNWeekday,
|
||||||
|
by_month: recurrenceRule.byMonth,
|
||||||
|
by_month_day: recurrenceRule.byMonthDay,
|
||||||
|
by_year_day: recurrenceRule.byYearDay,
|
||||||
|
count: recurrenceRule.count,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
toSnakeCase,
|
||||||
|
_transformAPIAutoModerationAction,
|
||||||
|
_transformAPIMessageInteractionMetadata,
|
||||||
|
_transformGuildScheduledEventRecurrenceRule,
|
||||||
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { token } = require('./auth.js');
|
const { token, owner } = require('./auth.js');
|
||||||
const { Client } = require('../src');
|
const { Client } = require('../src');
|
||||||
const { ChannelType, GatewayIntentBits } = require('discord-api-types/v10');
|
const { ChannelType, GatewayIntentBits } = require('discord-api-types/v10');
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ const client = new Client({
|
|||||||
GatewayIntentBits.GuildMessages,
|
GatewayIntentBits.GuildMessages,
|
||||||
GatewayIntentBits.GuildMessageReactions,
|
GatewayIntentBits.GuildMessageReactions,
|
||||||
GatewayIntentBits.GuildMembers,
|
GatewayIntentBits.GuildMembers,
|
||||||
|
GatewayIntentBits.MessageContent,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -186,7 +187,7 @@ client.on('messageCreate', msg => {
|
|||||||
msg.channel.send(`\`\`\`${msg.content}\`\`\``);
|
msg.channel.send(`\`\`\`${msg.content}\`\`\``);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.content.startsWith('#eval') && msg.author.id === '66564597481480192') {
|
if (msg.content.startsWith('#eval') && msg.author.id === owner) {
|
||||||
try {
|
try {
|
||||||
const com = eval(msg.content.split(' ').slice(1).join(' '));
|
const com = eval(msg.content.split(' ').slice(1).join(' '));
|
||||||
msg.channel.send(`\`\`\`\n${com}\`\`\``);
|
msg.channel.send(`\`\`\`\n${com}\`\`\``);
|
||||||
|
|||||||
41
packages/discord.js/typings/index.d.ts
vendored
41
packages/discord.js/typings/index.d.ts
vendored
@@ -186,6 +186,9 @@ import {
|
|||||||
ReactionType,
|
ReactionType,
|
||||||
APIAuthorizingIntegrationOwnersMap,
|
APIAuthorizingIntegrationOwnersMap,
|
||||||
MessageReferenceType,
|
MessageReferenceType,
|
||||||
|
GuildScheduledEventRecurrenceRuleWeekday,
|
||||||
|
GuildScheduledEventRecurrenceRuleMonth,
|
||||||
|
GuildScheduledEventRecurrenceRuleFrequency,
|
||||||
} from 'discord-api-types/v10';
|
} from 'discord-api-types/v10';
|
||||||
import { ChildProcess } from 'node:child_process';
|
import { ChildProcess } from 'node:child_process';
|
||||||
import { EventEmitter } from 'node:events';
|
import { EventEmitter } from 'node:events';
|
||||||
@@ -1779,6 +1782,7 @@ export class GuildScheduledEvent<Status extends GuildScheduledEventStatus = Guil
|
|||||||
public entityMetadata: GuildScheduledEventEntityMetadata | null;
|
public entityMetadata: GuildScheduledEventEntityMetadata | null;
|
||||||
public userCount: number | null;
|
public userCount: number | null;
|
||||||
public creator: User | null;
|
public creator: User | null;
|
||||||
|
public recurrenceRule: GuildScheduledEventRecurrenceRule | null;
|
||||||
public get createdTimestamp(): number;
|
public get createdTimestamp(): number;
|
||||||
public get createdAt(): Date;
|
public get createdAt(): Date;
|
||||||
public get scheduledStartAt(): Date | null;
|
public get scheduledStartAt(): Date | null;
|
||||||
@@ -1817,6 +1821,26 @@ export class GuildScheduledEvent<Status extends GuildScheduledEventStatus = Guil
|
|||||||
public isScheduled(): this is GuildScheduledEvent<GuildScheduledEventStatus.Scheduled>;
|
public isScheduled(): this is GuildScheduledEvent<GuildScheduledEventStatus.Scheduled>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GuildScheduledEventRecurrenceRule {
|
||||||
|
startTimestamp: number;
|
||||||
|
get startAt(): Date;
|
||||||
|
endTimestamp: number | null;
|
||||||
|
get endAt(): Date | null;
|
||||||
|
frequency: GuildScheduledEventRecurrenceRuleFrequency;
|
||||||
|
interval: number;
|
||||||
|
byWeekday: readonly GuildScheduledEventRecurrenceRuleWeekday[] | null;
|
||||||
|
byNWeekday: readonly GuildScheduledEventRecurrenceRuleNWeekday[] | null;
|
||||||
|
byMonth: readonly GuildScheduledEventRecurrenceRuleMonth[] | null;
|
||||||
|
byMonthDay: readonly number[] | null;
|
||||||
|
byYearDay: readonly number[] | null;
|
||||||
|
count: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GuildScheduledEventRecurrenceRuleNWeekday {
|
||||||
|
n: number;
|
||||||
|
day: GuildScheduledEventRecurrenceRuleWeekday;
|
||||||
|
}
|
||||||
|
|
||||||
export class GuildTemplate extends Base {
|
export class GuildTemplate extends Base {
|
||||||
private constructor(client: Client<true>, data: RawGuildTemplateData);
|
private constructor(client: Client<true>, data: RawGuildTemplateData);
|
||||||
public createdTimestamp: number;
|
public createdTimestamp: number;
|
||||||
@@ -6167,14 +6191,29 @@ export interface GuildScheduledEventCreateOptions {
|
|||||||
entityMetadata?: GuildScheduledEventEntityMetadataOptions;
|
entityMetadata?: GuildScheduledEventEntityMetadataOptions;
|
||||||
image?: BufferResolvable | Base64Resolvable | null;
|
image?: BufferResolvable | Base64Resolvable | null;
|
||||||
reason?: string;
|
reason?: string;
|
||||||
|
recurrenceRule?: GuildScheduledEventRecurrenceRuleOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GuildScheduledEventRecurrenceRuleOptions {
|
||||||
|
startAt: DateResolvable;
|
||||||
|
endAt: DateResolvable;
|
||||||
|
frequency: GuildScheduledEventRecurrenceRuleFrequency;
|
||||||
|
interval: number;
|
||||||
|
byWeekday: readonly GuildScheduledEventRecurrenceRuleWeekday[];
|
||||||
|
byNWeekday: readonly GuildScheduledEventRecurrenceRuleNWeekday[];
|
||||||
|
byMonth: readonly GuildScheduledEventRecurrenceRuleMonth[];
|
||||||
|
byMonthDay: readonly number[];
|
||||||
|
byYearDay: readonly number[];
|
||||||
|
count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GuildScheduledEventEditOptions<
|
export interface GuildScheduledEventEditOptions<
|
||||||
Status extends GuildScheduledEventStatus,
|
Status extends GuildScheduledEventStatus,
|
||||||
AcceptableStatus extends GuildScheduledEventSetStatusArg<Status>,
|
AcceptableStatus extends GuildScheduledEventSetStatusArg<Status>,
|
||||||
> extends Omit<Partial<GuildScheduledEventCreateOptions>, 'channel'> {
|
> extends Omit<Partial<GuildScheduledEventCreateOptions>, 'channel' | 'recurrenceRule'> {
|
||||||
channel?: GuildVoiceChannelResolvable | null;
|
channel?: GuildVoiceChannelResolvable | null;
|
||||||
status?: AcceptableStatus;
|
status?: AcceptableStatus;
|
||||||
|
recurrenceRule?: GuildScheduledEventRecurrenceRuleOptions | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GuildScheduledEventEntityMetadata {
|
export interface GuildScheduledEventEntityMetadata {
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ import {
|
|||||||
ApplicationEmoji,
|
ApplicationEmoji,
|
||||||
ApplicationEmojiManager,
|
ApplicationEmojiManager,
|
||||||
StickerPack,
|
StickerPack,
|
||||||
|
GuildScheduledEventManager,
|
||||||
SendableChannels,
|
SendableChannels,
|
||||||
PollData,
|
PollData,
|
||||||
} from '.';
|
} from '.';
|
||||||
@@ -2618,3 +2619,6 @@ client.on('interactionCreate', interaction => {
|
|||||||
interaction.channel.send({ embeds: [] });
|
interaction.channel.send({ embeds: [] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
declare const guildScheduledEventManager: GuildScheduledEventManager;
|
||||||
|
await guildScheduledEventManager.edit(snowflake, { recurrenceRule: null });
|
||||||
|
|||||||
Reference in New Issue
Block a user