Skip to content

Commit

Permalink
feat(MessageManager): extend API coverage (#4869)
Browse files Browse the repository at this point in the history
Co-authored-by: Sugden <28943913+NotSugden@users.noreply.github.com>
Co-authored-by: izexi <43889168+izexi@users.noreply.github.com>
Co-authored-by: Advaith <advaithj1@gmail.com>
  • Loading branch information
4 people committed May 10, 2021
1 parent 7ce741d commit c56c4a8
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 53 deletions.
76 changes: 76 additions & 0 deletions src/managers/MessageManager.js
Expand Up @@ -2,6 +2,7 @@

const BaseManager = require('./BaseManager');
const { TypeError } = require('../errors');
const APIMessage = require('../structures/APIMessage');
const Message = require('../structures/Message');
const Collection = require('../util/Collection');
const LimitedCollection = require('../util/LimitedCollection');
Expand Down Expand Up @@ -113,6 +114,81 @@ class MessageManager extends BaseManager {
* @returns {?Snowflake}
*/

/**
* Edits a message, even if it's not cached.
* @param {MessageResolvable} message The message to edit
* @param {MessageEditOptions} [options] The options to provide
* @returns {Promise<Message>}
*/
async edit(message, options) {
message = this.resolveID(message);
if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');

const { data } = APIMessage.create(this, options).resolveData();
const d = await this.client.api.channels[this.channel.id].messages[message].patch({ data });

if (this.cache.has(message)) {
const clone = this.cache.get(message)._clone();
clone._patch(d);
return clone;
}
return this.add(d);
}

/**
* Publishes a message in an announcement channel to all channels following it, even if it's not cached.
* @param {MessageResolvable} message The message to publish
* @returns {Promise<Message>}
*/
async crosspost(message) {
message = this.resolveID(message);
if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');

const data = await this.client.api.channels(this.channel.id).messages(message).crosspost.post();
return this.cache.get(data.id) || this.add(data);
}

/**
* Pins a message to the channel's pinned messages, even if it's not cached.
* @param {MessageResolvable} message The message to pin
* @returns {Promise<void>}
*/
async pin(message) {
message = this.resolveID(message);
if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');

await this.client.api.channels(this.channel.id).pins(message).put();
}

/**
* Unins a message from the channel's pinned messages, even if it's not cached.
* @param {MessageResolvable} message The message to unpin
* @returns {Promise<void>}
*/
async unpin(message) {
message = this.resolveID(message);
if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');

await this.client.api.channels(this.channel.id).pins(message).delete();
}

/**
* Adds a reaction to a message, even if it's not cached.
* @param {MessageResolvable} message The messag to react to
* @param {EmojiIdentifierResolvable} emoji The emoji to react with
* @returns {Promise<void>}
*/
async react(message, emoji) {
message = this.resolveID(message);
if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');

emoji = this.client.emojis.resolveIdentifier(emoji);
if (!emoji) throw new TypeError('EMOJI_TYPE', 'emoji', 'EmojiIdentifierResolvable');

// eslint-disable-next-line newline-per-chained-call
await this.client.api.channels(this.channel.id).messages(message).reactions(emoji, '@me').put();
}

/**
* Deletes a message, even if it's not cached.
* @param {MessageResolvable} message The message to delete
Expand Down
75 changes: 25 additions & 50 deletions src/structures/Message.js
Expand Up @@ -8,7 +8,7 @@ const Embed = require('./MessageEmbed');
const Mentions = require('./MessageMentions');
const ReactionCollector = require('./ReactionCollector');
const Sticker = require('./Sticker');
const { Error, TypeError } = require('../errors');
const { Error } = require('../errors');
const ReactionManager = require('../managers/ReactionManager');
const Collection = require('../util/Collection');
const { InteractionTypes, MessageTypes, SystemMessageTypes } = require('../util/Constants');
Expand Down Expand Up @@ -472,7 +472,7 @@ class Message extends Base {
}

/**
* Options that can be passed into editMessage.
* Options that can be passed into {@link Message#edit}.
* @typedef {Object} MessageEditOptions
* @property {string} [content] Content to be edited
* @property {MessageEmbed|Object} [embed] An embed to be added/edited
Expand All @@ -494,13 +494,11 @@ class Message extends Base {
* .catch(console.error);
*/
edit(content, options) {
const { data } =
content instanceof APIMessage ? content.resolveData() : APIMessage.create(this, content, options).resolveData();
return this.client.api.channels[this.channel.id].messages[this.id].patch({ data }).then(d => {
const clone = this._clone();
clone._patch(d);
return clone;
});
if (!options && typeof content === 'object' && !Array.isArray(content)) {
options = content;
content = undefined;
}
return this.channel.messages.edit(this.id, { content, ...options });
}

/**
Expand All @@ -514,47 +512,34 @@ class Message extends Base {
* .catch(console.error);
* }
*/
async crosspost() {
await this.client.api.channels(this.channel.id).messages(this.id).crosspost.post();
return this;
crosspost() {
return this.channel.messages.crosspost(this.id);
}

/**
* Pins this message to the channel's pinned messages.
* @param {Object} [options] Options for pinning
* @param {string} [options.reason] Reason for pinning
* @returns {Promise<Message>}
* @example
* // Pin a message with a reason
* message.pin({ reason: 'important' })
* // Pin a message
* message.pin()
* .then(console.log)
* .catch(console.error)
*/
pin(options) {
return this.client.api
.channels(this.channel.id)
.pins(this.id)
.put(options)
.then(() => this);
pin() {
return this.channel.messages.pin(this.id).then(() => this);
}

/**
* Unpins this message from the channel's pinned messages.
* @param {Object} [options] Options for unpinning
* @param {string} [options.reason] Reason for unpinning
* @returns {Promise<Message>}
* @example
* // Unpin a message with a reason
* message.unpin({ reason: 'no longer relevant' })
* // Unpin a message
* message.unpin()
* .then(console.log)
* .catch(console.error)
*/
unpin(options) {
return this.client.api
.channels(this.channel.id)
.pins(this.id)
.delete(options)
.then(() => this);
unpin() {
return this.channel.messages.unpin(this.id).then(() => this);
}

/**
Expand All @@ -572,24 +557,14 @@ class Message extends Base {
* .then(console.log)
* .catch(console.error);
*/
react(emoji) {
emoji = this.client.emojis.resolveIdentifier(emoji);
if (!emoji) throw new TypeError('EMOJI_TYPE');

return this.client.api
.channels(this.channel.id)
.messages(this.id)
.reactions(emoji, '@me')
.put()
.then(
() =>
this.client.actions.MessageReactionAdd.handle({
user: this.client.user,
channel: this.channel,
message: this,
emoji: Util.parseEmoji(emoji),
}).reaction,
);
async react(emoji) {
await this.channel.messages.react(this.id, emoji);
return this.client.actions.MessageReactionAdd.handle({
user: this.client.user,
channel: this.channel,
message: this,
emoji: Util.parseEmoji(emoji),
}).reaction;
}

/**
Expand Down
11 changes: 8 additions & 3 deletions typings/index.d.ts
Expand Up @@ -1144,7 +1144,7 @@ declare module 'discord.js' {
public fetchWebhook(): Promise<Webhook>;
public crosspost(): Promise<Message>;
public fetch(force?: boolean): Promise<Message>;
public pin(options?: { reason?: string }): Promise<Message>;
public pin(): Promise<Message>;
public react(emoji: EmojiIdentifierResolvable): Promise<MessageReaction>;
public removeAttachments(): Promise<Message>;
public reply(
Expand All @@ -1164,7 +1164,7 @@ declare module 'discord.js' {
public suppressEmbeds(suppress?: boolean): Promise<Message>;
public toJSON(): object;
public toString(): string;
public unpin(options?: { reason?: string }): Promise<Message>;
public unpin(): Promise<Message>;
}

export class MessageAttachment {
Expand Down Expand Up @@ -2191,14 +2191,19 @@ declare module 'discord.js' {
constructor(channel: TextChannel | DMChannel, iterable?: Iterable<any>);
public channel: TextBasedChannelFields;
public cache: Collection<Snowflake, Message>;
public crosspost(message: MessageResolvable): Promise<Message>;
public delete(message: MessageResolvable): Promise<void>;
public edit(message: MessageResolvable, options: MessageEditOptions): Promise<Message>;
public fetch(message: Snowflake, cache?: boolean, force?: boolean): Promise<Message>;
public fetch(
options?: ChannelLogsQueryOptions,
cache?: boolean,
force?: boolean,
): Promise<Collection<Snowflake, Message>>;
public fetchPinned(cache?: boolean): Promise<Collection<Snowflake, Message>>;
public delete(message: MessageResolvable): Promise<void>;
public react(message: MessageResolvable, emoji: EmojiIdentifierResolvable): Promise<void>;
public pin(message: MessageResolvable): Promise<void>;
public unpin(message: MessageResolvable): Promise<void>;
}

export class PresenceManager extends BaseManager<Snowflake, Presence, PresenceResolvable> {
Expand Down

0 comments on commit c56c4a8

Please sign in to comment.