Documentation(Message, User, Member) (#61)

* feat(doc): add documentation for Message and refactor ReactionResolvable
* feat(doc): add documentation and coverage for User
* feat(doc): add documentation for Member which closes #20
This commit is contained in:
Yuzu 2022-07-18 00:29:41 +00:00 committed by GitHub
parent 604a1c9aaa
commit 94852eae76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 279 additions and 28 deletions

View File

@ -10,9 +10,8 @@ import User from "./User.ts";
import * as Routes from "../Routes.ts"; import * as Routes from "../Routes.ts";
/** /**
* Represents a guild member
* TODO: add a `guild` property somehow
* @link https://discord.com/developers/docs/resources/guild#guild-member-object * @link https://discord.com/developers/docs/resources/guild#guild-member-object
* Represents a guild member
*/ */
export class Member implements Model { export class Member implements Model {
constructor(session: Session, data: DiscordMemberWithUser, guildId: Snowflake) { constructor(session: Session, data: DiscordMemberWithUser, guildId: Snowflake) {
@ -21,6 +20,7 @@ export class Member implements Model {
this.guildId = guildId; this.guildId = guildId;
this.avatarHash = data.avatar ? Util.iconHashToBigInt(data.avatar) : undefined; this.avatarHash = data.avatar ? Util.iconHashToBigInt(data.avatar) : undefined;
this.nickname = data.nick ? data.nick : undefined; this.nickname = data.nick ? data.nick : undefined;
this.premiumSince = data.premium_since ? Number.parseInt(data.premium_since) : undefined;
this.joinedTimestamp = Number.parseInt(data.joined_at); this.joinedTimestamp = Number.parseInt(data.joined_at);
this.roles = data.roles; this.roles = data.roles;
this.deaf = !!data.deaf; this.deaf = !!data.deaf;
@ -31,16 +31,40 @@ export class Member implements Model {
: undefined; : undefined;
} }
/** the session that instantiated this member */
readonly session: Session; readonly session: Session;
/** the user this guild member represents */
user: User; user: User;
/** the choosen guild id */
guildId: Snowflake; guildId: Snowflake;
/** the member's guild avatar hash optimized as a bigint */
avatarHash?: bigint; avatarHash?: bigint;
/** this user's guild nickname */
nickname?: string; nickname?: string;
/** when the user started boosting the guild */
premiumSince?: number;
/** when the user joined the guild */
joinedTimestamp: number; joinedTimestamp: number;
/** array of role object ids */
roles: Snowflake[]; roles: Snowflake[];
/** whether the user is deafened in voice channels */
deaf: boolean; deaf: boolean;
/** whether the user is muted in voice channels */
mute: boolean; mute: boolean;
/** whether the user has not yet passed the guild's Membership Screening requirements */
pending: boolean; pending: boolean;
/** when the user's timeout will expire and the user will be able to communicate in the guild again, null or a time in the past if the user is not timed out */
communicationDisabledUntilTimestamp?: number; communicationDisabledUntilTimestamp?: number;
/** shorthand to User.id */ /** shorthand to User.id */
@ -48,30 +72,36 @@ export class Member implements Model {
return this.user.id; return this.user.id;
} }
/** gets the nickname or the username */
get nicknameOrUsername(): string { get nicknameOrUsername(): string {
return this.nickname ?? this.user.username; return this.nickname ?? this.user.username;
} }
/** gets the joinedAt timestamp as a Date */
get joinedAt(): Date { get joinedAt(): Date {
return new Date(this.joinedTimestamp); return new Date(this.joinedTimestamp);
} }
/** bans a member from this guild and delete previous messages sent by the member */
async ban(options: CreateGuildBan): Promise<Member> { async ban(options: CreateGuildBan): Promise<Member> {
await Guild.prototype.banMember.call({ id: this.guildId, session: this.session }, this.user.id, options); await Guild.prototype.banMember.call({ id: this.guildId, session: this.session }, this.user.id, options);
return this; return this;
} }
/** 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);
return this; return this;
} }
/** unbans a member from this guild */
async unban(): Promise<void> { async unban(): Promise<void> {
await Guild.prototype.unbanMember.call({ id: this.guildId, session: this.session }, this.user.id); await Guild.prototype.unbanMember.call({ id: this.guildId, session: this.session }, this.user.id);
} }
/** edits member's nickname, roles, etc */
async edit(options: ModifyGuildMember): Promise<Member> { async edit(options: ModifyGuildMember): Promise<Member> {
const member = await Guild.prototype.editMember.call( const member = await Guild.prototype.editMember.call(
{ id: this.guildId, session: this.session }, { id: this.guildId, session: this.session },
@ -82,10 +112,12 @@ export class Member implements Model {
return member; return member;
} }
/** adds a role to this member */
async addRole(roleId: Snowflake, options: { reason?: string } = {}): Promise<void> { async addRole(roleId: Snowflake, options: { 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, options);
} }
/** removes a role from this member */
async removeRole(roleId: Snowflake, options: { reason?: string } = {}): Promise<void> { async removeRole(roleId: Snowflake, options: { reason?: string } = {}): Promise<void> {
await Guild.prototype.removeRole.call( await Guild.prototype.removeRole.call(
{ id: this.guildId, session: this.session }, { id: this.guildId, session: this.session },
@ -95,7 +127,7 @@ export class Member implements Model {
); );
} }
/** gets the user's avatar */ /** 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: { format?: ImageFormat; size?: ImageSize } = { size: 128 }): string {
let url: string; let url: string;

View File

@ -10,17 +10,21 @@ import type {
MessageActivityTypes, MessageActivityTypes,
MessageTypes, MessageTypes,
} from "../../discordeno/mod.ts"; } from "../../discordeno/mod.ts";
import type { Channel } from "./channels.ts";
import type { Component } from "./components/Component.ts"; import type { Component } from "./components/Component.ts";
import type { GetReactions } from "../Routes.ts"; import type { GetReactions } from "../Routes.ts";
import type { MessageInteraction } from "./interactions/InteractionFactory.ts";
import { MessageFlags } from "../Util.ts"; import { MessageFlags } from "../Util.ts";
import { Snowflake } from "../Snowflake.ts"; import { Snowflake } from "../Snowflake.ts";
import { ThreadChannel } from "./channels.ts"; import { ChannelFactory, ThreadChannel } from "./channels.ts";
import Util from "../Util.ts"; import Util from "../Util.ts";
import User from "./User.ts"; import User from "./User.ts";
import Member from "./Member.ts"; import Member from "./Member.ts";
import Attachment from "./Attachment.ts"; import Attachment from "./Attachment.ts";
import ComponentFactory from "./components/ComponentFactory.ts"; import ComponentFactory from "./components/ComponentFactory.ts";
import MessageReaction from "./MessageReaction.ts"; import MessageReaction from "./MessageReaction.ts";
import Application, { NewTeam } from "./Application.ts";
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";
@ -34,6 +38,10 @@ export interface AllowedMentions {
users?: Snowflake[]; users?: Snowflake[];
} }
/**
* @link https://github.com/denoland/deno_doc/blob/main/lib/types.d.ts
* channelId is optional when creating a reply, but will always be present when receiving an event/response that includes this data model.
* */
export interface CreateMessageReference { export interface CreateMessageReference {
messageId: Snowflake; messageId: Snowflake;
channelId?: Snowflake; channelId?: Snowflake;
@ -43,6 +51,7 @@ export interface CreateMessageReference {
/** /**
* @link https://discord.com/developers/docs/resources/channel#create-message-json-params * @link https://discord.com/developers/docs/resources/channel#create-message-json-params
* Posts a message to a guild text or DM channel. Returns a message object. Fires a Message Create Gateway event.
*/ */
export interface CreateMessage { export interface CreateMessage {
embeds?: DiscordEmbed[]; embeds?: DiscordEmbed[];
@ -56,16 +65,24 @@ export interface CreateMessage {
/** /**
* @link https://discord.com/developers/docs/resources/channel#edit-message-json-params * @link https://discord.com/developers/docs/resources/channel#edit-message-json-params
* Edit a previously sent message.
* Returns a {@link Message} object. Fires a Message Update Gateway event.
*/ */
export interface EditMessage extends Partial<CreateMessage> { export interface EditMessage extends Partial<CreateMessage> {
flags?: MessageFlags; flags?: MessageFlags;
} }
export type ReactionResolvable = string | { /**
* Represents a guild or unicode {@link Emoji}
*/
export type EmojiResolvable = string | {
name: string; name: string;
id: Snowflake; id: Snowflake;
}; };
/**
* A partial {@link User} to represent the author of a message sent by a webhook
* */
export interface WebhookAuthor { export interface WebhookAuthor {
id: string; id: string;
username: string; username: string;
@ -74,8 +91,8 @@ export interface WebhookAuthor {
} }
/** /**
* Represents a message
* @link https://discord.com/developers/docs/resources/channel#message-object * @link https://discord.com/developers/docs/resources/channel#message-object
* Represents a message
*/ */
export class Message implements Model { export class Message implements Model {
constructor(session: Session, data: DiscordMessage) { constructor(session: Session, data: DiscordMessage) {
@ -87,6 +104,12 @@ export class Message implements Model {
this.guildId = data.guild_id; this.guildId = data.guild_id;
this.applicationId = data.application_id; this.applicationId = data.application_id;
this.mentions = {
users: data.mentions?.map((user) => new User(session, user)) ?? [],
roleIds: data.mention_roles ?? [],
channels: data.mention_channels?.map((channel) => ChannelFactory.from(session, channel)) ?? [],
}
if (!data.webhook_id) { if (!data.webhook_id) {
this.author = new User(session, data.author); this.author = new User(session, data.author);
} }
@ -105,6 +128,10 @@ export class Message implements Model {
this.attachments = data.attachments.map((attachment) => new Attachment(session, attachment)); this.attachments = data.attachments.map((attachment) => new Attachment(session, attachment));
this.embeds = data.embeds; this.embeds = data.embeds;
if (data.interaction) {
this.interaction = InteractionFactory.fromMessage(session, data.interaction, data.guild_id);
}
if (data.thread && data.guild_id) { if (data.thread && data.guild_id) {
this.thread = new ThreadChannel(session, data.thread, data.guild_id); this.thread = new ThreadChannel(session, data.thread, data.guild_id);
} }
@ -142,69 +169,173 @@ export class Message implements Model {
}; };
}); });
} }
if (data.application) {
const application: Partial<Application> = {
id: data.application.id,
icon: data.application.icon ? data.application.icon : undefined,
name: data.application.name,
guildId: data.application.guild_id,
flags: data.application.flags,
botPublic: data.application.bot_public,
owner: data.application.owner ? new User(session, data.application.owner as DiscordUser) : undefined,
botRequireCodeGrant: data.application.bot_require_code_grant,
coverImage: data.application.cover_image,
customInstallURL: data.application.custom_install_url,
description: data.application.description,
installParams: data.application.install_params,
tags: data.application.tags,
verifyKey: data.application.verify_key,
team: data.application.team ? NewTeam(session, data.application.team) : undefined,
primarySkuId: data.application.primary_sku_id,
privacyPolicyURL: data.application.privacy_policy_url,
rpcOrigins: data.application.rpc_origins,
slug: data.application.slug,
};
Object.setPrototypeOf(application, Application.prototype);
this.application = application;
}
} }
/** Reference to the client that instantiated this Message */
readonly session: Session; readonly session: Session;
/** id of the message */
readonly id: Snowflake; readonly id: Snowflake;
/** type of message */
type: MessageTypes; type: MessageTypes;
/** id of the channel the message was sent in */
channelId: Snowflake; channelId: Snowflake;
/** id of the guild the message was sent in, this should exist on MESSAGE_CREATE and MESSAGE_UPDATE events */
guildId?: Snowflake; guildId?: Snowflake;
/** if the message is an Interaction or application-owned webhook, this is the id of the application */
applicationId?: Snowflake; applicationId?: Snowflake;
/** mentions if any */
mentions: {
/** users specifically mentioned in the message */
users: User[];
/** roles specifically mentioned in this message */
roleIds: Snowflake[];
/** channels specifically mentioned in the message */
channels: Channel[];
};
/** sent if the message is a response to an Interaction */
interaction?: MessageInteraction;
/** the author of this message, this field is **not** sent on webhook messages */
author!: User; author!: User;
/** message flags combined as a bitfield */
flags?: MessageFlags; flags?: MessageFlags;
/** whether this message is pinned */
pinned: boolean; pinned: boolean;
/** whether this was a TTS message */
tts: boolean; tts: boolean;
/** contents of the message */
content: string; content: string;
/** used for validating a message was sent */
nonce?: string | number; nonce?: string | number;
/** whether this message mentions everyone */
mentionEveryone: boolean; mentionEveryone: boolean;
/** when this message was sent */
timestamp: number; timestamp: number;
/** when this message was edited */
editedTimestamp?: number; editedTimestamp?: number;
/**
* sent if the message contains stickers
* **this contains sticker items not stickers**
*/
stickers?: StickerItem[]; stickers?: StickerItem[];
/** reactions to the message */
reactions: MessageReaction[]; reactions: MessageReaction[];
/** any attached files */
attachments: Attachment[]; attachments: Attachment[];
/** any embedded content */
embeds: DiscordEmbed[]; embeds: DiscordEmbed[];
/** member properties for this message's author */
member?: Member; member?: Member;
/** the thread that was started from this message, includes {@link ThreadMember} */
thread?: ThreadChannel; thread?: ThreadChannel;
/** sent if the message contains components like buttons, action rows, or other interactive components */
components: Component[]; components: Component[];
/** if the message is generated by a webhook, this is the webhook's author data */
webhook?: WebhookAuthor; webhook?: WebhookAuthor;
/** sent with Rich Presence-related chat embeds */
application?: Partial<Application>;
/** sent with Rich Presence-related chat embeds */
activity?: { activity?: {
partyId?: Snowflake; partyId?: Snowflake;
type: MessageActivityTypes; type: MessageActivityTypes;
}; };
/** gets the timestamp of this message, this does not requires the timestamp field */
get createdTimestamp(): number { get createdTimestamp(): number {
return Snowflake.snowflakeToTimestamp(this.id); return Snowflake.snowflakeToTimestamp(this.id);
} }
/** gets the timestamp of this message as a Date */
get createdAt(): Date { get createdAt(): Date {
return new Date(this.createdTimestamp); return new Date(this.createdTimestamp);
} }
/** gets the timestamp of this message (sent by the API) */
get sentAt(): Date { get sentAt(): Date {
return new Date(this.timestamp); return new Date(this.timestamp);
} }
/** gets the edited timestamp as a Date */
get editedAt(): Date | undefined { get editedAt(): Date | undefined {
return this.editedTimestamp ? new Date(this.editedTimestamp) : undefined; return this.editedTimestamp ? new Date(this.editedTimestamp) : undefined;
} }
/** whether this message was edited */
get edited(): number | undefined { get edited(): number | undefined {
return this.editedTimestamp; return this.editedTimestamp;
} }
/** gets the url of the message that points to the message */
get url(): string { get url(): string {
return `https://discord.com/channels/${this.guildId ?? "@me"}/${this.channelId}/${this.id}`; return `https://discord.com/channels/${this.guildId ?? "@me"}/${this.channelId}/${this.id}`;
} }
/** Compatibility with Discordeno */ /**
* Compatibility with Discordeno
* same as Message.author.bot
*/
get isBot(): boolean { get isBot(): boolean {
return this.author.bot; return this.author.bot;
} }
/**
* Pins this message
* */
async pin(): Promise<void> { async pin(): Promise<void> {
await this.session.rest.runMethod<undefined>( await this.session.rest.runMethod<undefined>(
this.session.rest, this.session.rest,
@ -213,6 +344,9 @@ export class Message implements Model {
); );
} }
/**
* Unpins this message
* */
async unpin(): Promise<void> { async unpin(): Promise<void> {
await this.session.rest.runMethod<undefined>( await this.session.rest.runMethod<undefined>(
this.session.rest, this.session.rest,
@ -243,6 +377,7 @@ export class Message implements Model {
return message; return message;
} }
/** edits the current message flags to supress its embeds */
async suppressEmbeds(suppress: true): Promise<Message>; async suppressEmbeds(suppress: true): Promise<Message>;
async suppressEmbeds(suppress: false): Promise<Message | undefined>; async suppressEmbeds(suppress: false): Promise<Message | undefined>;
async suppressEmbeds(suppress = true) { async suppressEmbeds(suppress = true) {
@ -255,6 +390,7 @@ export class Message implements Model {
return message; return message;
} }
/** deletes this message */
async delete({ reason }: { reason: string }): Promise<Message> { async delete({ reason }: { reason: string }): Promise<Message> {
await this.session.rest.runMethod<undefined>( await this.session.rest.runMethod<undefined>(
this.session.rest, this.session.rest,
@ -266,7 +402,7 @@ export class Message implements Model {
return this; return this;
} }
/** Replies directly in the channel the message was sent */ /** Replies directly in the channel where the message was sent */
async reply(options: CreateMessage): Promise<Message> { async reply(options: CreateMessage): Promise<Message> {
const message = await this.session.rest.runMethod<DiscordMessage>( const message = await this.session.rest.runMethod<DiscordMessage>(
this.session.rest, this.session.rest,
@ -298,14 +434,13 @@ export class Message implements Model {
return new Message(this.session, message); return new Message(this.session, message);
} }
/** /** alias for Message.addReaction */
* alias for Message.addReaction
*/
get react() { get react() {
return this.addReaction; return this.addReaction;
} }
async addReaction(reaction: ReactionResolvable): Promise<void> { /** adds a Reaction */
async addReaction(reaction: EmojiResolvable): Promise<void> {
const r = typeof reaction === "string" ? reaction : `${reaction.name}:${reaction.id}`; const r = typeof reaction === "string" ? reaction : `${reaction.name}:${reaction.id}`;
await this.session.rest.runMethod<undefined>( await this.session.rest.runMethod<undefined>(
@ -316,7 +451,8 @@ export class Message implements Model {
); );
} }
async removeReaction(reaction: ReactionResolvable, options?: { userId: Snowflake }): Promise<void> { /** removes a reaction from someone */
async removeReaction(reaction: EmojiResolvable, options?: { userId: Snowflake }): Promise<void> {
const r = typeof reaction === "string" ? reaction : `${reaction.name}:${reaction.id}`; const r = typeof reaction === "string" ? reaction : `${reaction.name}:${reaction.id}`;
await this.session.rest.runMethod<undefined>( await this.session.rest.runMethod<undefined>(
@ -335,8 +471,9 @@ export class Message implements Model {
/** /**
* Get users who reacted with this emoji * Get users who reacted with this emoji
* not recommended since the cache handles reactions already
*/ */
async fetchReactions(reaction: ReactionResolvable, options?: GetReactions): Promise<User[]> { async fetchReactions(reaction: EmojiResolvable, options?: GetReactions): Promise<User[]> {
const r = typeof reaction === "string" ? reaction : `${reaction.name}:${reaction.id}`; const r = typeof reaction === "string" ? reaction : `${reaction.name}:${reaction.id}`;
const users = await this.session.rest.runMethod<DiscordUser[]>( const users = await this.session.rest.runMethod<DiscordUser[]>(
@ -348,7 +485,10 @@ export class Message implements Model {
return users.map((user) => new User(this.session, user)); return users.map((user) => new User(this.session, user));
} }
async removeReactionEmoji(reaction: ReactionResolvable): Promise<void> { /**
* same as Message.removeReaction but removes using a unicode emoji
* */
async removeReactionEmoji(reaction: EmojiResolvable): Promise<void> {
const r = typeof reaction === "string" ? reaction : `${reaction.name}:${reaction.id}`; const r = typeof reaction === "string" ? reaction : `${reaction.name}:${reaction.id}`;
await this.session.rest.runMethod<undefined>( await this.session.rest.runMethod<undefined>(
@ -358,6 +498,7 @@ export class Message implements Model {
); );
} }
/** nukes every reaction on the message */
async nukeReactions(): Promise<void> { async nukeReactions(): Promise<void> {
await this.session.rest.runMethod<undefined>( await this.session.rest.runMethod<undefined>(
this.session.rest, this.session.rest,
@ -366,6 +507,7 @@ export class Message implements Model {
); );
} }
/** publishes/crossposts a message to all followers */
async crosspost(): Promise<Message> { async crosspost(): Promise<Message> {
const message = await this.session.rest.runMethod<DiscordMessage>( const message = await this.session.rest.runMethod<DiscordMessage>(
this.session.rest, this.session.rest,
@ -376,6 +518,7 @@ export class Message implements Model {
return new Message(this.session, message); return new Message(this.session, message);
} }
/** fetches this message, meant to be used with Function.call since its redundant */
async fetch(): Promise<(Message | undefined)> { async fetch(): Promise<(Message | undefined)> {
const message = await this.session.rest.runMethod<DiscordMessage>( const message = await this.session.rest.runMethod<DiscordMessage>(
this.session.rest, this.session.rest,
@ -388,9 +531,7 @@ export class Message implements Model {
return new Message(this.session, message); return new Message(this.session, message);
} }
/* /** alias of Message.crosspost */
* alias of Message.crosspost
* */
get publish() { get publish() {
return this.crosspost; return this.crosspost;
} }

View File

@ -1,14 +1,14 @@
import type { Model } from "./Base.ts"; 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 { DiscordUser } from "../../discordeno/mod.ts"; import type { DiscordUser, UserFlags, PremiumTypes } from "../../discordeno/mod.ts";
import type { ImageFormat, ImageSize } from "../Util.ts"; 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";
/** /**
* Represents a user
* @link https://discord.com/developers/docs/resources/user#user-object * @link https://discord.com/developers/docs/resources/user#user-object
* Represents a user
*/ */
export class User implements Model { export class User implements Model {
constructor(session: Session, data: DiscordUser) { constructor(session: Session, data: DiscordUser) {
@ -21,25 +21,72 @@ export class User implements Model {
this.accentColor = data.accent_color; this.accentColor = data.accent_color;
this.bot = !!data.bot; this.bot = !!data.bot;
this.system = !!data.system; this.system = !!data.system;
this.banner = data.banner; this.banner = data.banner ? Util.iconHashToBigInt(data.banner) : undefined;
this.mfaEnabled = !!data.mfa_enabled;
this.locale = data.locale;
this.email = data.email ? data.email : undefined;
this.verified = data.verified;
this.flags = data.flags;
} }
/** the session that instantiated this User */
readonly session: Session; readonly session: Session;
/** the user's id */
readonly id: Snowflake; readonly id: Snowflake;
/** the user's username, not unique across the platform */
username: string; username: string;
/** the user's 4-digit discord-tag */
discriminator: string; discriminator: string;
/** the user's avatar hash optimized as a bigint */
avatarHash?: bigint; avatarHash?: bigint;
/** the user's banner color encoded as an integer representation of hexadecimal color code */
accentColor?: number; accentColor?: number;
/** whether the user belongs to an OAuth2 application */
bot: boolean; bot: boolean;
/** whether the user is an Official Discord System user (part of the urgent message system) */
system: boolean; system: boolean;
banner?: string;
/** the user's banner hash optimized as a bigint */
banner?: bigint;
/** whether the user has two factor enabled on their account */
mfaEnabled: boolean;
/** the user's chosen language option */
locale?: string;
/** the user's email */
email?: string;
/** the flags on a user's account */
flags?: UserFlags;
/** whether the email on this account has been verified */
verified?: boolean;
/** the type of Nitro subscription on a user's account */
premiumType?: PremiumTypes;
/** the public flags on a user's account */
publicFlags?: UserFlags;
/** gets the user's username#discriminator */ /** gets the user's username#discriminator */
get tag(): string { get tag(): string {
return `${this.username}#${this.discriminator}}`; return `${this.username}#${this.discriminator}}`;
} }
/** fetches this user */
fetch() {
return this.session.fetchUser(this.id);
}
/** gets the user's avatar */ /** gets the user's avatar */
avatarURL(options: { format?: ImageFormat; size?: ImageSize } = { size: 128 }): string { avatarURL(options: { format?: ImageFormat; size?: ImageSize } = { size: 128 }): string {
let url: string; let url: string;

View File

@ -25,7 +25,7 @@ import { urlToBase64 } from "../util/urlToBase64.ts";
/** Classes and routes */ /** Classes and routes */
import * as Routes from "../Routes.ts"; import * as Routes from "../Routes.ts";
import Message, { CreateMessage, EditMessage, ReactionResolvable } from "./Message.ts"; import Message, { CreateMessage, EditMessage, EmojiResolvable } from "./Message.ts";
import Invite from "./Invite.ts"; import Invite from "./Invite.ts";
import Webhook from "./Webhook.ts"; import Webhook from "./Webhook.ts";
import User from "./User.ts"; import User from "./User.ts";
@ -225,7 +225,7 @@ export class TextChannel {
await Message.prototype.unpin.call({ id: messageId, channelId: this.id, session: this.session }); await Message.prototype.unpin.call({ id: messageId, channelId: this.id, session: this.session });
} }
async addReaction(messageId: Snowflake, reaction: ReactionResolvable): Promise<void> { async addReaction(messageId: Snowflake, reaction: EmojiResolvable): Promise<void> {
await Message.prototype.addReaction.call( await Message.prototype.addReaction.call(
{ channelId: this.id, id: messageId, session: this.session }, { channelId: this.id, id: messageId, session: this.session },
reaction, reaction,
@ -234,7 +234,7 @@ export class TextChannel {
async removeReaction( async removeReaction(
messageId: Snowflake, messageId: Snowflake,
reaction: ReactionResolvable, reaction: EmojiResolvable,
options?: { userId: Snowflake }, options?: { userId: Snowflake },
): Promise<void> { ): Promise<void> {
await Message.prototype.removeReaction.call( await Message.prototype.removeReaction.call(
@ -244,7 +244,7 @@ export class TextChannel {
); );
} }
async removeReactionEmoji(messageId: Snowflake, reaction: ReactionResolvable): Promise<void> { async removeReactionEmoji(messageId: Snowflake, reaction: EmojiResolvable): Promise<void> {
await Message.prototype.removeReactionEmoji.call( await Message.prototype.removeReactionEmoji.call(
{ channelId: this.id, id: messageId, session: this.session }, { channelId: this.id, id: messageId, session: this.session },
reaction, reaction,
@ -257,7 +257,7 @@ export class TextChannel {
async fetchReactions( async fetchReactions(
messageId: Snowflake, messageId: Snowflake,
reaction: ReactionResolvable, reaction: EmojiResolvable,
options?: Routes.GetReactions, options?: Routes.GetReactions,
): Promise<User[]> { ): Promise<User[]> {
const users = await Message.prototype.fetchReactions.call( const users = await Message.prototype.fetchReactions.call(

View File

@ -1,12 +1,31 @@
import type { Session } from "../../Session.ts"; import type { Session } from "../../Session.ts";
import type { DiscordInteraction } from "../../../discordeno/mod.ts"; import type { Snowflake } from "../../Snowflake.ts";
import type { DiscordInteraction, DiscordMessageInteraction } from "../../../discordeno/mod.ts";
import { InteractionTypes } from "../../../discordeno/mod.ts"; import { InteractionTypes } from "../../../discordeno/mod.ts";
import User from "../User.ts";
import Member from "../Member.ts";
import CommandInteraction from "./CommandInteraction.ts"; import CommandInteraction from "./CommandInteraction.ts";
import ComponentInteraction from "./ComponentInteraction.ts"; import ComponentInteraction from "./ComponentInteraction.ts";
import PingInteraction from "./PingInteraction.ts"; import PingInteraction from "./PingInteraction.ts";
import AutoCompleteInteraction from "./AutoCompleteInteraction.ts"; import AutoCompleteInteraction from "./AutoCompleteInteraction.ts";
import ModalSubmitInteraction from "./ModalSubmitInteraction.ts"; import ModalSubmitInteraction from "./ModalSubmitInteraction.ts";
/**
* @link https://discord.com/developers/docs/interactions/receiving-and-responding#message-interaction-object-message-interaction-structure
* */
export interface MessageInteraction {
/** id of the interaction */
id: Snowflake;
/** type of interaction */
type: InteractionTypes
/** name of the application command, including subcommands and subcommand groups */
name: string
/** user who invoked the interaction */
user: User;
/** member who invoked the interaction in the guild */
member?: Partial<Member>;
}
export type Interaction = export type Interaction =
| CommandInteraction | CommandInteraction
| ComponentInteraction | ComponentInteraction
@ -29,6 +48,18 @@ export class InteractionFactory {
return new ModalSubmitInteraction(session, interaction); return new ModalSubmitInteraction(session, interaction);
} }
} }
static fromMessage(session: Session, interaction: DiscordMessageInteraction, _guildId?: Snowflake): MessageInteraction {
const obj = {
id: interaction.id,
type: interaction.type,
name: interaction.name,
user: new User(session, interaction.user),
// TODO: Parse member somehow with the guild id passed in message
};
return obj;
}
} }
export default InteractionFactory; export default InteractionFactory;