Repository: discordjs/discord.js
File: packages/discord.js/src/structures/Message.js (JavaScript)

Code before:
   * // Filter for bulk deletable messages
   * channel.bulkDelete(messages.filter(message => message.bulkDeletable));
   */
  get bulkDeletable() {
    return (
      (this.inGuild() &&
        Date.now() - this.createdTimestamp < MaxBulkDeletableMessageAge &&
        this.deletable &&
        this.channel?.permissionsFor(this.client.user).has(PermissionFlagsBits.ManageMessages, false)) ??
      false
    );
  }

  /**
   * Whether the message is pinnable by the client user
   *
   * @type {boolean}
   * @readonly
   */
  get pinnable() {
    const { channel } = this;

    if (this.system) return false;
    if (!this.guild) return true;
    if (!channel?.viewable) return false;

    const permissions = channel?.permissionsFor(this.client.user);
    if (!permissions) return false;

    return permissions.has(PermissionFlagsBits.ReadMessageHistory | PermissionFlagsBits.PinMessages);
  }

  /**
   * Fetches the Message this crosspost/reply/pin-add references, if available to the client
   *
   * @returns {Promise<Message>}
   */
  async fetchReference() {
    if (!this.reference) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing);
    const { channelId, messageId } = this.reference;
    if (!messageId) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing);
    const channel = this.client.channels.resolve(channelId);
    if (!channel) throw new DiscordjsError(ErrorCodes.GuildChannelResolve);
    return channel.messages.fetch(messageId);
  }

  /**
   * Whether the message is crosspostable by the client user
   *
   * @type {boolean}
   * @readonly

Review comment (suggestion):
Voice channels do not support pins
```suggestion
    if (!('lastPinAt' in channel)) return false;

```

Code after:
   * // Filter for bulk deletable messages
   * channel.bulkDelete(messages.filter(message => message.bulkDeletable));
   */
  get bulkDeletable() {
    return (
      (this.inGuild() &&
        Date.now() - this.createdTimestamp < MaxBulkDeletableMessageAge &&
        this.deletable &&
        this.channel?.permissionsFor(this.client.user).has(PermissionFlagsBits.ManageMessages, false)) ??
      false
    );
  }

  /**
   * Whether the message is pinnable by the client user
   *
   * @type {boolean}
   * @readonly
   */
  get pinnable() {
    const { channel } = this;

    if (this.system) return false;
    if (!this.guild) return true;
    if (!channel || channel.isVoiceBased() || !channel.viewable) return false;

    const permissions = channel.permissionsFor(this.client.user);
    if (!permissions) return false;

    return permissions.has(PermissionFlagsBits.ReadMessageHistory | PermissionFlagsBits.PinMessages);
  }

  /**
   * Fetches the Message this crosspost/reply/pin-add references, if available to the client
   *
   * @returns {Promise<Message>}
   */
  async fetchReference() {
    if (!this.reference) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing);
    const { channelId, messageId } = this.reference;
    if (!messageId) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing);
    const channel = this.client.channels.resolve(channelId);
    if (!channel) throw new DiscordjsError(ErrorCodes.GuildChannelResolve);
    return channel.messages.fetch(messageId);
  }

  /**
   * Whether the message is crosspostable by the client user
   *
   * @type {boolean}
   * @readonly