fix(types): Literal Types (#77)

* fix(Message): delete() params

* feat: fetches guilds items

* fix(types): literal types

* fix
This commit is contained in:
Marcos Susaña 2022-07-21 03:49:52 -04:00 committed by GitHub
parent e2d7993182
commit 08b8df41fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 158 additions and 101 deletions

View File

@ -37,6 +37,14 @@ export type DiscordRawEventHandler = (shard: Shard, data: DiscordGatewayPayload)
// INTERACTIONS // INTERACTIONS
export type CreateApplicationCommands = CreateApplicationCommand | CreateContextApplicationCommand;
export type UpsertDataApplicationCommands =
| AtLeastOne<CreateApplicationCommand>
| AtLeastOne<CreateContextApplicationCommand>;
export type LastCreateApplicationCommands =
| AtLeastOne<CreateContextApplicationCommand>
| AtLeastOne<CreateApplicationCommand>;
/** /**
* @link https://discord.com/developers/docs/interactions/application-commands#endpoints-json-params * @link https://discord.com/developers/docs/interactions/application-commands#endpoints-json-params
*/ */
@ -133,7 +141,7 @@ export class Session extends EventEmitter {
this.#applicationId = id; this.#applicationId = id;
} }
get applicationId() { get applicationId(): Snowflake {
return this.#applicationId!; return this.#applicationId!;
} }
@ -141,7 +149,7 @@ export class Session extends EventEmitter {
this.#botId = id; this.#botId = id;
} }
get botId() { get botId(): Snowflake {
return this.#botId; return this.#botId;
} }
@ -273,7 +281,7 @@ export class Session extends EventEmitter {
} }
createApplicationCommand( createApplicationCommand(
options: CreateApplicationCommand | CreateContextApplicationCommand, options: CreateApplicationCommands,
guildId?: Snowflake, guildId?: Snowflake,
): Promise<DiscordApplicationCommand> { ): Promise<DiscordApplicationCommand> {
return this.rest.runMethod<DiscordApplicationCommand>( return this.rest.runMethod<DiscordApplicationCommand>(
@ -368,7 +376,7 @@ export class Session extends EventEmitter {
upsertApplicationCommand( upsertApplicationCommand(
id: Snowflake, id: Snowflake,
options: AtLeastOne<CreateApplicationCommand> | AtLeastOne<CreateContextApplicationCommand>, options: UpsertDataApplicationCommands,
guildId?: Snowflake, guildId?: Snowflake,
): Promise<DiscordApplicationCommand> { ): Promise<DiscordApplicationCommand> {
return this.rest.runMethod<DiscordApplicationCommand>( return this.rest.runMethod<DiscordApplicationCommand>(
@ -392,7 +400,7 @@ export class Session extends EventEmitter {
} }
upsertApplicationCommands( upsertApplicationCommands(
options: Array<UpsertApplicationCommands | CreateContextApplicationCommand>, options: UpsertDataApplicationCommands[],
guildId?: Snowflake, guildId?: Snowflake,
): Promise<DiscordApplicationCommand[]> { ): Promise<DiscordApplicationCommand[]> {
return this.rest.runMethod<DiscordApplicationCommand[]>( return this.rest.runMethod<DiscordApplicationCommand[]>(
@ -428,7 +436,7 @@ export class Session extends EventEmitter {
} }
// deno-fmt-ignore // deno-fmt-ignore
isContextApplicationCommand(cmd: AtLeastOne<CreateContextApplicationCommand> | AtLeastOne<CreateApplicationCommand>): cmd is AtLeastOne<CreateContextApplicationCommand> { isContextApplicationCommand(cmd: LastCreateApplicationCommands): cmd is AtLeastOne<CreateContextApplicationCommand> {
return cmd.type === ApplicationCommandTypes.Message || cmd.type === ApplicationCommandTypes.User; return cmd.type === ApplicationCommandTypes.Message || cmd.type === ApplicationCommandTypes.User;
} }

View File

@ -6,7 +6,7 @@ export const DiscordEpoch = 14200704e5;
/** utilities for Snowflakes */ /** utilities for Snowflakes */
export const Snowflake = { export const Snowflake = {
snowflakeToTimestamp(id: Snowflake) { snowflakeToTimestamp(id: Snowflake): number {
return (Number(id) >> 22) + DiscordEpoch; return (Number(id) >> 22) + DiscordEpoch;
}, },
}; };

View File

@ -71,15 +71,15 @@ export type ImageSize = 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096;
* Utility functions * Utility functions
*/ */
export class Util { export class Util {
static formatImageURL(url: string, size: ImageSize = 128, format?: ImageFormat) { static formatImageURL(url: string, size: ImageSize = 128, format?: ImageFormat): string {
return `${url}.${format || (url.includes('/a_') ? 'gif' : 'jpg')}?size=${size}`; return `${url}.${format || (url.includes('/a_') ? 'gif' : 'jpg')}?size=${size}`;
} }
static iconHashToBigInt(hash: string) { static iconHashToBigInt(hash: string): bigint {
return BigInt('0x' + (hash.startsWith('a_') ? `a${hash.substring(2)}` : `b${hash}`)); return BigInt('0x' + (hash.startsWith('a_') ? `a${hash.substring(2)}` : `b${hash}`));
} }
static iconBigintToHash(icon: bigint) { static iconBigintToHash(icon: bigint): string {
const hash: string = icon.toString(16); const hash: string = icon.toString(16);
return hash.startsWith('a') ? `a_${hash.substring(1)}` : hash.substring(1); return hash.startsWith('a') ? `a_${hash.substring(1)}` : hash.substring(1);

View File

@ -35,8 +35,8 @@ export class GuildEmoji extends Emoji implements Model {
return emoji; return emoji;
} }
async delete({ reason }: { reason?: string } = {}): Promise<GuildEmoji> { async delete(reason?: string): Promise<GuildEmoji> {
await Guild.prototype.deleteEmoji.call({ id: this.guildId, session: this.session }, this.id, { reason }); await Guild.prototype.deleteEmoji.call({ id: this.guildId, session: this.session }, this.id, reason);
return this; return this;
} }

View File

@ -4,6 +4,8 @@ import type { Session } from '../Session.ts';
import type { DiscordIntegration, IntegrationExpireBehaviors } from '../../discordeno/mod.ts'; import type { DiscordIntegration, IntegrationExpireBehaviors } from '../../discordeno/mod.ts';
import User from './User.ts'; import User from './User.ts';
export type IntegrationTypes = 'twitch' | 'youtube' | 'discord';
export interface IntegrationAccount { export interface IntegrationAccount {
id: Snowflake; id: Snowflake;
name: string; name: string;
@ -58,7 +60,7 @@ export class Integration implements Model {
guildId?: Snowflake; guildId?: Snowflake;
name: string; name: string;
type: 'twitch' | 'youtube' | 'discord'; type: IntegrationTypes;
enabled?: boolean; enabled?: boolean;
syncing?: boolean; syncing?: boolean;
roleId?: string; roleId?: string;

View File

@ -2,11 +2,10 @@ import type { Model } from './Base.ts';
import type { Snowflake } from '../Snowflake.ts'; import type { Snowflake } from '../Snowflake.ts';
import type { Session } from '../Session.ts'; import type { Session } from '../Session.ts';
import type { DiscordMemberWithUser } from '../../discordeno/mod.ts'; import type { DiscordMemberWithUser } from '../../discordeno/mod.ts';
import type { ImageFormat, ImageSize } from '../Util.ts';
import type { CreateGuildBan, ModifyGuildMember } from './guilds.ts'; import type { CreateGuildBan, ModifyGuildMember } from './guilds.ts';
import { Guild } from './guilds.ts'; import { Guild } from './guilds.ts';
import Util from '../Util.ts'; import Util from '../Util.ts';
import User from './User.ts'; import { avatarOptions, User } from './User.ts';
import * as Routes from '../Routes.ts'; import * as Routes from '../Routes.ts';
/** /**
@ -91,7 +90,11 @@ export class Member implements Model {
/** kicks a member from this guild */ /** kicks a member from this guild */
async kick(options: { reason?: string }): Promise<Member> { async kick(options: { reason?: string }): Promise<Member> {
await Guild.prototype.kickMember.call({ id: this.guildId, session: this.session }, this.user.id, options); await Guild.prototype.kickMember.call(
{ id: this.guildId, session: this.session },
this.user.id,
options.reason,
);
return this; return this;
} }
@ -113,8 +116,8 @@ export class Member implements Model {
} }
/** adds a role to this member */ /** adds a role to this member */
async addRole(roleId: Snowflake, options: { reason?: string } = {}): Promise<void> { async addRole(roleId: Snowflake, reason?: string): Promise<void> {
await Guild.prototype.addRole.call({ id: this.guildId, session: this.session }, this.user.id, roleId, options); await Guild.prototype.addRole.call({ id: this.guildId, session: this.session }, this.user.id, roleId, reason);
} }
/** removes a role from this member */ /** removes a role from this member */
@ -123,16 +126,16 @@ export class Member implements Model {
{ id: this.guildId, session: this.session }, { id: this.guildId, session: this.session },
this.user.id, this.user.id,
roleId, roleId,
options, options.reason,
); );
} }
/** gets the members's guild avatar, not to be confused with Member.user.avatarURL() */ /** gets the members's guild avatar, not to be confused with Member.user.avatarURL() */
avatarURL(options: { format?: ImageFormat; size?: ImageSize } = { size: 128 }): string { avatarURL(options: avatarOptions): string {
let url: string; let url: string;
if (this.user.bot) { if (this.user.bot) {
return this.user.avatarURL(); return this.user.avatarURL(options);
} }
if (!this.avatarHash) { if (!this.avatarHash) {
@ -141,7 +144,7 @@ export class Member implements Model {
url = Routes.USER_AVATAR(this.user.id, Util.iconBigintToHash(this.avatarHash)); url = Routes.USER_AVATAR(this.user.id, Util.iconBigintToHash(this.avatarHash));
} }
return Util.formatImageURL(url, options.size, options.format); return Util.formatImageURL(url, options.size ?? 128, options.format);
} }
toString(): string { toString(): string {

View File

@ -28,6 +28,18 @@ import InteractionFactory from './interactions/InteractionFactory.ts';
import * as Routes from '../Routes.ts'; import * as Routes from '../Routes.ts';
import { StickerItem } from './Sticker.ts'; import { StickerItem } from './Sticker.ts';
export type GuildMessage = Message & { guildId: Snowflake };
export type WebhookMessage = Message & {
author: Partial<User>;
webhook: WebhookAuthor;
member: undefined;
};
export interface MessageActivity {
partyId?: Snowflake;
type: MessageActivityTypes;
}
/** /**
* @link https://discord.com/developers/docs/resources/channel#allowed-mentions-object * @link https://discord.com/developers/docs/resources/channel#allowed-mentions-object
*/ */
@ -290,10 +302,7 @@ export class Message implements Model {
application?: Partial<Application>; application?: Partial<Application>;
/** sent with Rich Presence-related chat embeds */ /** sent with Rich Presence-related chat embeds */
activity?: { activity?: MessageActivity;
partyId?: Snowflake;
type: MessageActivityTypes;
};
/** gets the timestamp of this message, this does not requires the timestamp field */ /** gets the timestamp of this message, this does not requires the timestamp field */
get createdTimestamp(): number { get createdTimestamp(): number {
@ -537,12 +546,12 @@ export class Message implements Model {
} }
/** wheter the message comes from a guild **/ /** wheter the message comes from a guild **/
inGuild(): this is Message & { guildId: Snowflake } { inGuild(): this is GuildMessage {
return !!this.guildId; return !!this.guildId;
} }
/** wheter the messages comes from a Webhook */ /** wheter the messages comes from a Webhook */
isWebhookMessage(): this is Message & { author: Partial<User>; webhook: WebhookAuthor; member: undefined } { isWebhookMessage(): this is WebhookMessage {
return !!this.webhook; return !!this.webhook;
} }
} }

View File

@ -6,7 +6,7 @@ import Member from './Member.ts';
/** /**
* Represents when a new reaction was added to a message. * Represents when a new reaction was added to a message.
* @link https://discord.com/developers/docs/topics/gateway#message-reaction-add * @link https://discord.com/developers/docs/topics/gateway#message-reaction-add
* */ */
export interface MessageReactionAdd { export interface MessageReactionAdd {
userId: string; userId: string;
channelId: string; channelId: string;
@ -30,7 +30,7 @@ export type MessageReactionRemove = Omit<MessageReactionAdd, 'member'>;
* @see {@link MessageReactionAdd} * @see {@link MessageReactionAdd}
* @link https://discord.com/developers/docs/topics/gateway#message-reaction-remove-all * @link https://discord.com/developers/docs/topics/gateway#message-reaction-remove-all
*/ */
export type MessageReactionRemoveAll = Pick<MessageReactionAdd, 'channelId' | 'messageId' | 'guildId'> export type MessageReactionRemoveAll = Pick<MessageReactionAdd, 'channelId' | 'messageId' | 'guildId'>;
/** /**
* Represents when a reaction-emoji was removed from a message. * Represents when a reaction-emoji was removed from a message.

View File

@ -56,12 +56,12 @@ export class Role implements Model {
return role; return role;
} }
async add(memberId: Snowflake, options: { reason?: string } = {}): Promise<void> { async add(memberId: Snowflake, reason?: string): Promise<void> {
await Guild.prototype.addRole.call({ id: this.guildId, session: this.session }, memberId, this.id, options); await Guild.prototype.addRole.call({ id: this.guildId, session: this.session }, memberId, this.id, reason);
} }
async remove(memberId: Snowflake, options: { reason?: string } = {}): Promise<void> { async remove(memberId: Snowflake, reason?: string): Promise<void> {
await Guild.prototype.removeRole.call({ id: this.guildId, session: this.session }, memberId, this.id, options); await Guild.prototype.removeRole.call({ id: this.guildId, session: this.session }, memberId, this.id, reason);
} }
toString(): string { toString(): string {

View File

@ -15,6 +15,11 @@ export enum PrivacyLevels {
GuildOnly = 2, GuildOnly = 2,
} }
export type stageEditOptions = {
topic?: string;
privacy?: PrivacyLevels;
};
export class StageInstance implements Model { export class StageInstance implements Model {
constructor(session: Session, data: DiscordStageInstanceB) { constructor(session: Session, data: DiscordStageInstanceB) {
this.session = session; this.session = session;
@ -39,14 +44,14 @@ export class StageInstance implements Model {
discoverableDisabled: boolean; discoverableDisabled: boolean;
guildScheduledEventId: Snowflake; guildScheduledEventId: Snowflake;
async edit(options: { topic?: string; privacyLevel?: PrivacyLevels }): Promise<StageInstance> { async edit(options: stageEditOptions): Promise<StageInstance> {
const stageInstance = await this.session.rest.runMethod<DiscordStageInstanceB>( const stageInstance = await this.session.rest.runMethod<DiscordStageInstanceB>(
this.session.rest, this.session.rest,
'PATCH', 'PATCH',
Routes.STAGE_INSTANCE(this.id), Routes.STAGE_INSTANCE(this.id),
{ {
topic: options.topic, topic: options.topic,
privacy_level: options.privacyLevel, privacy_level: options.privacy,
}, },
); );

View File

@ -7,7 +7,7 @@ import * as Routes from '../Routes.ts';
/** /**
* A member that comes from a thread * A member that comes from a thread
* @link https://discord.com/developers/docs/resources/channel#thread-member-object * @link https://discord.com/developers/docs/resources/channel#thread-member-object
* * */ * **/
export class ThreadMember implements Model { export class ThreadMember implements Model {
constructor(session: Session, data: DiscordThreadMember) { constructor(session: Session, data: DiscordThreadMember) {
this.session = session; this.session = session;
@ -25,19 +25,19 @@ export class ThreadMember implements Model {
return this.id; return this.id;
} }
async quitThread(memberId: Snowflake = this.session.botId): Promise<void> { async quitThread(memberId?: Snowflake): Promise<void> {
await this.session.rest.runMethod<undefined>( await this.session.rest.runMethod<undefined>(
this.session.rest, this.session.rest,
'DELETE', 'DELETE',
Routes.THREAD_USER(this.id, memberId), Routes.THREAD_USER(this.id, memberId ?? this.session.botId),
); );
} }
async fetchMember(memberId: Snowflake = this.session.botId): Promise<ThreadMember> { async fetchMember(memberId?: Snowflake): Promise<ThreadMember> {
const member = await this.session.rest.runMethod<DiscordThreadMember>( const member = await this.session.rest.runMethod<DiscordThreadMember>(
this.session.rest, this.session.rest,
'GET', 'GET',
Routes.THREAD_USER(this.id, memberId), Routes.THREAD_USER(this.id, memberId ?? this.session.botId),
); );
return new ThreadMember(this.session, member); return new ThreadMember(this.session, member);

View File

@ -6,6 +6,11 @@ import type { ImageFormat, ImageSize } from '../Util.ts';
import Util from '../Util.ts'; import Util from '../Util.ts';
import * as Routes from '../Routes.ts'; import * as Routes from '../Routes.ts';
export type avatarOptions = {
format?: ImageFormat;
size?: ImageSize;
};
/** /**
* @link https://discord.com/developers/docs/resources/user#user-object * @link https://discord.com/developers/docs/resources/user#user-object
* Represents a user * Represents a user
@ -88,7 +93,7 @@ export class User implements Model {
} }
/** gets the user's avatar */ /** gets the user's avatar */
avatarURL(options: { format?: ImageFormat; size?: ImageSize } = { size: 128 }): string { avatarURL(options: avatarOptions): string {
let url: string; let url: string;
if (!this.avatarHash) { if (!this.avatarHash) {
@ -97,7 +102,7 @@ export class User implements Model {
url = Routes.USER_AVATAR(this.id, Util.iconBigintToHash(this.avatarHash)); url = Routes.USER_AVATAR(this.id, Util.iconBigintToHash(this.avatarHash));
} }
return Util.formatImageURL(url, options.size, options.format); return Util.formatImageURL(url, options.size ?? 128, options.format);
} }
toString(): string { toString(): string {

View File

@ -17,6 +17,10 @@ import User from './User.ts';
import Message from './Message.ts'; import Message from './Message.ts';
import * as Routes from '../Routes.ts'; import * as Routes from '../Routes.ts';
export type executeWebhookOptions = WebhookOptions & CreateMessage & { avatarUrl?: string; username?: string };
export type editMessageWithThread = EditWebhookMessage & { threadId?: Snowflake };
/** /**
* @link https://discord.com/developers/docs/resources/webhook#edit-webhook-message-jsonform-params * @link https://discord.com/developers/docs/resources/webhook#edit-webhook-message-jsonform-params
*/ */
@ -68,7 +72,7 @@ export class Webhook implements Model {
user?: User; user?: User;
async execute( async execute(
options?: WebhookOptions & CreateMessage & { avatarUrl?: string; username?: string }, options?: executeWebhookOptions,
): Promise<(Message | undefined)> { ): Promise<(Message | undefined)> {
if (!this.token) { if (!this.token) {
return; return;
@ -110,7 +114,7 @@ export class Webhook implements Model {
return new Webhook(this.session, message); return new Webhook(this.session, message);
} }
async fetchMessage(messageId: Snowflake, options?: { threadId?: Snowflake }): Promise<Message | undefined> { async fetchMessage(messageId: Snowflake, threadId?: Snowflake): Promise<Message | undefined> {
if (!this.token) { if (!this.token) {
return; return;
} }
@ -118,13 +122,13 @@ export class Webhook implements Model {
const message = await this.session.rest.runMethod<DiscordMessage>( const message = await this.session.rest.runMethod<DiscordMessage>(
this.session.rest, this.session.rest,
'GET', 'GET',
Routes.WEBHOOK_MESSAGE(this.id, this.token, messageId, options), Routes.WEBHOOK_MESSAGE(this.id, this.token, messageId, { threadId }),
); );
return new Message(this.session, message); return new Message(this.session, message);
} }
async deleteMessage(messageId: Snowflake, options?: { threadId?: Snowflake }): Promise<void> { async deleteMessage(messageId: Snowflake, threadId?: Snowflake): Promise<void> {
if (!this.token) { if (!this.token) {
throw new Error('No token found'); throw new Error('No token found');
} }
@ -132,13 +136,13 @@ export class Webhook implements Model {
await this.session.rest.runMethod<undefined>( await this.session.rest.runMethod<undefined>(
this.session.rest, this.session.rest,
'DELETE', 'DELETE',
Routes.WEBHOOK_MESSAGE(this.id, this.token, messageId, options), Routes.WEBHOOK_MESSAGE(this.id, this.token, messageId, { threadId }),
); );
} }
async editMessage( async editMessage(
messageId?: Snowflake, messageId?: Snowflake,
options?: EditWebhookMessage & { threadId?: Snowflake }, options?: editMessageWithThread,
): Promise<Message> { ): Promise<Message> {
if (!this.token) { if (!this.token) {
throw new Error('No token found'); throw new Error('No token found');

View File

@ -1,7 +1,7 @@
import { DiscordGuildWidget } from "../../api-types/discord.ts"; import { DiscordGuildWidget } from '../../api-types/discord.ts';
import { Session } from "../Session.ts"; import { Session } from '../Session.ts';
import { Snowflake } from "../Snowflake.ts"; import { Snowflake } from '../Snowflake.ts';
import { Model } from "./Base.ts"; import { Model } from './Base.ts';
import { PartialChannel } from './channels.ts'; import { PartialChannel } from './channels.ts';
export interface WidgetMember { export interface WidgetMember {
@ -19,17 +19,16 @@ export class Widget implements Model {
this.name = data.name; this.name = data.name;
this.instantInvite = data.instant_invite; this.instantInvite = data.instant_invite;
this.channels = data.channels; this.channels = data.channels;
this.members = data.members.map(x => { this.members = data.members.map((x) => {
return { return {
id: x.id, id: x.id,
username: x.username, username: x.username,
avatar: x.avatar, avatar: x.avatar,
status: x.status, status: x.status,
avatarURL: x.avatar_url avatarURL: x.avatar_url,
} };
}); });
this.presenceCount = data.presence_count; this.presenceCount = data.presence_count;
} }
session: Session; session: Session;
id: Snowflake; id: Snowflake;

View File

@ -58,6 +58,8 @@ export abstract class ApplicationCommandBuilder implements CreateApplicationComm
} }
} }
export type MessageApplicationCommandBuilderJSON = { name: string; type: ApplicationCommandTypes.Message };
export class MessageApplicationCommandBuilder { export class MessageApplicationCommandBuilder {
type: ApplicationCommandTypes; type: ApplicationCommandTypes;
name?: string; name?: string;
@ -73,7 +75,7 @@ export class MessageApplicationCommandBuilder {
return (this.name = name), this; return (this.name = name), this;
} }
toJSON(): { name: string; type: ApplicationCommandTypes.Message } { toJSON(): MessageApplicationCommandBuilderJSON {
if (!this.name) throw new TypeError('Propety \'name\' is required'); if (!this.name) throw new TypeError('Propety \'name\' is required');
return { return {

View File

@ -1,6 +1,6 @@
import type { Session } from '../../Session.ts'; import type { Session } from '../../Session.ts';
import type { DiscordComponent, DiscordInputTextComponent } from '../../../discordeno/mod.ts'; import type { DiscordComponent, DiscordInputTextComponent } from '../../../discordeno/mod.ts';
import type { ActionRowComponent, Component } from './Component.ts'; import type { ActionRowComponent, ComponentsWithoutRow } from './Component.ts';
import { ButtonStyles, MessageComponentTypes } from '../../../discordeno/mod.ts'; import { ButtonStyles, MessageComponentTypes } from '../../../discordeno/mod.ts';
import BaseComponent from './Component.ts'; import BaseComponent from './Component.ts';
import Button from './ButtonComponent.ts'; import Button from './ButtonComponent.ts';
@ -33,7 +33,7 @@ export class ActionRow extends BaseComponent implements ActionRowComponent {
readonly session: Session; readonly session: Session;
override type: MessageComponentTypes.ActionRow; override type: MessageComponentTypes.ActionRow;
components: Array<Exclude<Component, ActionRowComponent>>; components: ComponentsWithoutRow[];
} }
export default ActionRow; export default ActionRow;

View File

@ -1,6 +1,6 @@
import type { Session } from '../../Session.ts'; import type { Session } from '../../Session.ts';
import type { ButtonStyles, DiscordComponent } from '../../../discordeno/mod.ts'; import type { DiscordComponent } from '../../../discordeno/mod.ts';
import type { ButtonComponent } from './Component.ts'; import type { ButtonComponent, ClassicButton } from './Component.ts';
import { MessageComponentTypes } from '../../../discordeno/mod.ts'; import { MessageComponentTypes } from '../../../discordeno/mod.ts';
import BaseComponent from './Component.ts'; import BaseComponent from './Component.ts';
import Emoji from '../Emoji.ts'; import Emoji from '../Emoji.ts';
@ -13,7 +13,7 @@ export class Button extends BaseComponent implements ButtonComponent {
this.type = data.type as MessageComponentTypes.Button; this.type = data.type as MessageComponentTypes.Button;
this.customId = data.custom_id; this.customId = data.custom_id;
this.label = data.label; this.label = data.label;
this.style = data.style as number; this.style = data.style as ClassicButton;
this.disabled = data.disabled; this.disabled = data.disabled;
if (data.emoji) { if (data.emoji) {
@ -25,7 +25,7 @@ export class Button extends BaseComponent implements ButtonComponent {
override type: MessageComponentTypes.Button; override type: MessageComponentTypes.Button;
customId?: string; customId?: string;
label?: string; label?: string;
style: ButtonStyles.Primary | ButtonStyles.Secondary | ButtonStyles.Success | ButtonStyles.Danger; style: ClassicButton;
disabled?: boolean; disabled?: boolean;
emoji?: Emoji; emoji?: Emoji;
} }

View File

@ -40,9 +40,13 @@ export type Component =
| TextInputComponent; | TextInputComponent;
/** Button Component */ /** Button Component */
export type ClassicButton = Exclude<ButtonStyles, ButtonStyles.Link>;
export type ComponentsWithoutRow = Exclude<Component, ActionRowComponent>;
export interface ButtonComponent { export interface ButtonComponent {
type: MessageComponentTypes.Button; type: MessageComponentTypes.Button;
style: ButtonStyles.Primary | ButtonStyles.Secondary | ButtonStyles.Success | ButtonStyles.Danger; style: ClassicButton;
label?: string; label?: string;
emoji?: Emoji; emoji?: Emoji;
customId?: string; customId?: string;

View File

@ -6,6 +6,7 @@ import type {
DiscordBan, DiscordBan,
DiscordEmoji, DiscordEmoji,
DiscordGuild, DiscordGuild,
DiscordGuildPreview,
DiscordGuildWidget, DiscordGuildWidget,
DiscordGuildWidgetSettings, DiscordGuildWidgetSettings,
DiscordInvite, DiscordInvite,
@ -21,7 +22,6 @@ import type {
SystemChannelFlags, SystemChannelFlags,
VerificationLevels, VerificationLevels,
VideoQualityModes, VideoQualityModes,
DiscordGuildPreview
} from '../../discordeno/mod.ts'; } from '../../discordeno/mod.ts';
import type { ImageFormat, ImageSize } from '../Util.ts'; import type { ImageFormat, ImageSize } from '../Util.ts';
import { GuildFeatures, PremiumTiers } from '../../discordeno/mod.ts'; import { GuildFeatures, PremiumTiers } from '../../discordeno/mod.ts';
@ -228,11 +228,11 @@ export class GuildPreview implements Model {
this.iconHash = data.icon ? Util.iconHashToBigInt(data.icon) : undefined; this.iconHash = data.icon ? Util.iconHashToBigInt(data.icon) : undefined;
this.splashHash = data.splash ? Util.iconHashToBigInt(data.splash) : undefined; this.splashHash = data.splash ? Util.iconHashToBigInt(data.splash) : undefined;
this.discoverySplashHash = data.discovery_splash ? Util.iconHashToBigInt(data.discovery_splash) : undefined; this.discoverySplashHash = data.discovery_splash ? Util.iconHashToBigInt(data.discovery_splash) : undefined;
this.emojis = data.emojis.map(x => new GuildEmoji(this.session, x, this.id)); this.emojis = data.emojis.map((x) => new GuildEmoji(this.session, x, this.id));
this.features = data.features; this.features = data.features;
this.approximateMemberCount = data.approximate_member_count; this.approximateMemberCount = data.approximate_member_count;
this.approximatePresenceCount = data.approximate_presence_count; this.approximatePresenceCount = data.approximate_presence_count;
this.stickers = data.stickers.map(x => new Sticker(this.session, x)); this.stickers = data.stickers.map((x) => new Sticker(this.session, x));
} }
session: Session; session: Session;
/** guild id */ /** guild id */
@ -256,7 +256,14 @@ export class GuildPreview implements Model {
stickers: Sticker[]; stickers: Sticker[];
} }
/** Guild */ // Guild
/** Maximun custom guild emojis per level */
export type maximunEmojis = 50 | 100 | 150 | 250;
/** Maximun custom guild stickers per level */
export type maximunStickers = 5 | 15 | 30 | 60;
export type editBotNickOptions = { nick: string | null; reason?: string };
export interface CreateRole { export interface CreateRole {
name?: string; name?: string;
color?: number; color?: number;
@ -541,7 +548,7 @@ export class Guild extends BaseGuild implements Model {
/** /**
* Returns the maximum number of emoji slots * Returns the maximum number of emoji slots
*/ */
get maxEmojis(): 50 | 100 | 150 | 250 { get maxEmojis(): maximunEmojis {
switch (this.premiumTier) { switch (this.premiumTier) {
case 1: case 1:
return 100; return 100;
@ -557,7 +564,7 @@ export class Guild extends BaseGuild implements Model {
/** /**
* Returns the maximum number of custom sticker slots * Returns the maximum number of custom sticker slots
*/ */
get maxStickers(): 5 | 15 | 30 | 60 { get maxStickers(): maximunStickers {
switch (this.premiumTier) { switch (this.premiumTier) {
case 1: case 1:
return 15; return 15;
@ -574,7 +581,7 @@ export class Guild extends BaseGuild implements Model {
* edits the bot's nickname in the guild. * edits the bot's nickname in the guild.
* 'null' would reset the nickname. * 'null' would reset the nickname.
*/ */
async editBotNickname(options: { nick: string | null; reason?: string }): Promise<(string | undefined)> { async editBotNickname(options: editBotNickOptions): Promise<(string | undefined)> {
const result = await this.session.rest.runMethod<{ nick?: string } | undefined>( const result = await this.session.rest.runMethod<{ nick?: string } | undefined>(
this.session.rest, this.session.rest,
'PATCH', 'PATCH',
@ -612,7 +619,7 @@ export class Guild extends BaseGuild implements Model {
* @param id - The id of the emoji to delete. * @param id - The id of the emoji to delete.
* @param reason - The reason for deleting the emoji. * @param reason - The reason for deleting the emoji.
*/ */
async deleteEmoji(id: Snowflake, { reason }: { reason?: string } = {}): Promise<void> { async deleteEmoji(id: Snowflake, reason?: string): Promise<void> {
await this.session.rest.runMethod<undefined>( await this.session.rest.runMethod<undefined>(
this.session.rest, this.session.rest,
'DELETE', 'DELETE',
@ -711,7 +718,7 @@ export class Guild extends BaseGuild implements Model {
* @param roleId - The id of the role to add. * @param roleId - The id of the role to add.
* @param reason - The reason for adding the role to the member. * @param reason - The reason for adding the role to the member.
*/ */
async addRole(memberId: Snowflake, roleId: Snowflake, { reason }: { reason?: string } = {}): Promise<void> { async addRole(memberId: Snowflake, roleId: Snowflake, reason?: string): Promise<void> {
await this.session.rest.runMethod<undefined>( await this.session.rest.runMethod<undefined>(
this.session.rest, this.session.rest,
'PUT', 'PUT',
@ -726,7 +733,7 @@ export class Guild extends BaseGuild implements Model {
* @param roleId - The id of the role to remove. * @param roleId - The id of the role to remove.
* @param reason - The reason for removing the role from the member. * @param reason - The reason for removing the role from the member.
*/ */
async removeRole(memberId: Snowflake, roleId: Snowflake, { reason }: { reason?: string } = {}): Promise<void> { async removeRole(memberId: Snowflake, roleId: Snowflake, reason?: string): Promise<void> {
await this.session.rest.runMethod<undefined>( await this.session.rest.runMethod<undefined>(
this.session.rest, this.session.rest,
'DELETE', 'DELETE',
@ -823,7 +830,7 @@ export class Guild extends BaseGuild implements Model {
* @param memberId - The id of the member to kick. * @param memberId - The id of the member to kick.
* @param reason - The reason for kicking the member. * @param reason - The reason for kicking the member.
*/ */
async kickMember(memberId: Snowflake, { reason }: { reason?: string }): Promise<void> { async kickMember(memberId: Snowflake, reason?: string): Promise<void> {
await this.session.rest.runMethod<undefined>( await this.session.rest.runMethod<undefined>(
this.session.rest, this.session.rest,
'DELETE', 'DELETE',
@ -1157,10 +1164,13 @@ export class Guild extends BaseGuild implements Model {
* @returns Resolves a Guild Preview object * @returns Resolves a Guild Preview object
*/ */
async fetchGuildPreview(): Promise<GuildPreview> { async fetchGuildPreview(): Promise<GuildPreview> {
const preview = await this.session.rest.runMethod<DiscordGuildPreview>(this.session.rest, 'GET', Routes.GUILD_PREVIEW(this.id)); const preview = await this.session.rest.runMethod<DiscordGuildPreview>(
this.session.rest,
'GET',
Routes.GUILD_PREVIEW(this.id),
);
return new GuildPreview(this.session, preview); return new GuildPreview(this.session, preview);
} }
} }
export default Guild; export default Guild;

View File

@ -18,6 +18,9 @@ import Permsisions from '../Permissions.ts';
import Webhook from '../Webhook.ts'; import Webhook from '../Webhook.ts';
import * as Routes from '../../Routes.ts'; import * as Routes from '../../Routes.ts';
export type InteractionResponseWith = { with: InteractionApplicationCommandCallbackData };
export type InteractionResponseWithData = InteractionResponse | InteractionResponseWith;
/** /**
* @link https://discord.com/developers/docs/interactions/slash-commands#interaction-response * @link https://discord.com/developers/docs/interactions/slash-commands#interaction-response
*/ */
@ -185,25 +188,25 @@ export abstract class BaseInteraction implements Model {
return message; return message;
} }
async deleteFollowUp(messageId: Snowflake, options?: { threadId?: Snowflake }): Promise<void> { async deleteFollowUp(messageId: Snowflake, threadId?: Snowflake): Promise<void> {
await Webhook.prototype.deleteMessage.call( await Webhook.prototype.deleteMessage.call(
{ {
id: this.session.applicationId, id: this.session.applicationId,
token: this.token, token: this.token,
}, },
messageId, messageId,
options, threadId,
); );
} }
async fetchFollowUp(messageId: Snowflake, options?: { threadId?: Snowflake }): Promise<Message | undefined> { async fetchFollowUp(messageId: Snowflake, threadId?: Snowflake): Promise<Message | undefined> {
const message = await Webhook.prototype.fetchMessage.call( const message = await Webhook.prototype.fetchMessage.call(
{ {
id: this.session.applicationId, id: this.session.applicationId,
token: this.token, token: this.token,
}, },
messageId, messageId,
options, threadId,
); );
return message; return message;
@ -213,9 +216,9 @@ export abstract class BaseInteraction implements Model {
// deno-fmt-ignore // deno-fmt-ignore
async respond(resp: InteractionResponse): Promise<Message | undefined>; async respond(resp: InteractionResponse): Promise<Message | undefined>;
async respond(resp: { with: InteractionApplicationCommandCallbackData }): Promise<Message | undefined>; async respond(resp: InteractionResponseWith): Promise<Message | undefined>;
async respond( async respond(
resp: InteractionResponse | { with: InteractionApplicationCommandCallbackData }, resp: InteractionResponseWithData,
): Promise<Message | undefined> { ): Promise<Message | undefined> {
const options = 'with' in resp ? resp.with : resp.data; const options = 'with' in resp ? resp.with : resp.data;
const type = 'type' in resp ? resp.type : InteractionResponseTypes.ChannelMessageWithSource; const type = 'type' in resp ? resp.type : InteractionResponseTypes.ChannelMessageWithSource;

View File

@ -15,6 +15,14 @@ import Member from '../Member.ts';
import Message from '../Message.ts'; import Message from '../Message.ts';
import Role from '../Role.ts'; import Role from '../Role.ts';
export interface CommandInteractionDataResolved {
users: Map<Snowflake, User>;
members: Map<Snowflake, Member>;
roles: Map<Snowflake, Role>;
attachments: Map<Snowflake, Attachment>;
messages: Map<Snowflake, Message>;
}
export class CommandInteraction extends BaseInteraction implements Model { export class CommandInteraction extends BaseInteraction implements Model {
constructor(session: Session, data: DiscordInteraction) { constructor(session: Session, data: DiscordInteraction) {
super(session, data); super(session, data);
@ -69,13 +77,7 @@ export class CommandInteraction extends BaseInteraction implements Model {
commandName: string; commandName: string;
commandType: ApplicationCommandTypes; commandType: ApplicationCommandTypes;
commandGuildId?: Snowflake; commandGuildId?: Snowflake;
resolved: { resolved: CommandInteractionDataResolved;
users: Map<Snowflake, User>;
members: Map<Snowflake, Member>;
roles: Map<Snowflake, Role>;
attachments: Map<Snowflake, Attachment>;
messages: Map<Snowflake, Message>;
};
options: CommandInteractionOptionResolver; options: CommandInteractionOptionResolver;
} }

View File

@ -10,6 +10,8 @@ import type {
import BaseInteraction from './BaseInteraction.ts'; import BaseInteraction from './BaseInteraction.ts';
import Message from '../Message.ts'; import Message from '../Message.ts';
export type ModalInMessage = ModalSubmitInteraction & { message: Message };
export class ModalSubmitInteraction extends BaseInteraction implements Model { export class ModalSubmitInteraction extends BaseInteraction implements Model {
constructor(session: Session, data: DiscordInteraction) { constructor(session: Session, data: DiscordInteraction) {
super(session, data); super(session, data);
@ -46,7 +48,7 @@ export class ModalSubmitInteraction extends BaseInteraction implements Model {
}; };
} }
inMessage(): this is ModalSubmitInteraction & { message: Message } { inMessage(): this is ModalInMessage {
return !!this.message; return !!this.message;
} }
} }

View File

@ -75,4 +75,3 @@ export function enableCache(session: Session): SessionCache {
return cache; return cache;
} }