Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attachment type #1358

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions esm.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default function (token, options) {

export const {
ApplicationCommand,
Attachment,
AutocompleteInteraction,
Base,
Bucket,
Expand Down
40 changes: 23 additions & 17 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ declare namespace Eris {

// Application Commands
type ApplicationCommandOptions = ApplicationCommandOptionsSubCommand | ApplicationCommandOptionsSubCommandGroup | ApplicationCommandOptionsWithValue;
type ApplicationCommandOptionsAttachment = ApplicationCommandOption<Constants["ApplicationCommandOptionTypes"]["ATTACHMENT"]>;
type ApplicationCommandOptionsBoolean = ApplicationCommandOption<Constants["ApplicationCommandOptionTypes"]["BOOLEAN"]>;
type ApplicationCommandOptionsChannel = ApplicationCommandOption<Constants["ApplicationCommandOptionTypes"]["CHANNEL"]>;
type ApplicationCommandOptionsInteger = ApplicationCommandOptionsIntegerWithAutocomplete | ApplicationCommandOptionsIntegerWithoutAutocomplete | ApplicationCommandOptionsIntegerWithMinMax;
Expand All @@ -37,7 +38,7 @@ declare namespace Eris {
type ApplicationCommandOptionsStringWithAutocomplete = Omit<ApplicationCommandOptionWithChoices<Constants["ApplicationCommandOptionTypes"]["STRING"]>, "choices"> & AutocompleteEnabled;
type ApplicationCommandOptionsStringWithoutAutocomplete = Omit<ApplicationCommandOptionWithChoices<Constants["ApplicationCommandOptionTypes"]["STRING"]>, "autocomplete"> & AutocompleteDisabled;
type ApplicationCommandOptionsUser = ApplicationCommandOption<Constants["ApplicationCommandOptionTypes"]["USER"]>;
type ApplicationCommandOptionsWithValue = ApplicationCommandOptionsString | ApplicationCommandOptionsInteger | ApplicationCommandOptionsBoolean | ApplicationCommandOptionsUser | ApplicationCommandOptionsChannel | ApplicationCommandOptionsRole | ApplicationCommandOptionsMentionable | ApplicationCommandOptionsNumber;
type ApplicationCommandOptionsWithValue = ApplicationCommandOptionsString | ApplicationCommandOptionsInteger | ApplicationCommandOptionsBoolean | ApplicationCommandOptionsUser | ApplicationCommandOptionsChannel | ApplicationCommandOptionsRole | ApplicationCommandOptionsMentionable | ApplicationCommandOptionsNumber | ApplicationCommandOptionsAttachment;
type ApplicationCommandPermissionTypes = Constants["ApplicationCommandPermissionTypes"][keyof Constants["ApplicationCommandPermissionTypes"]];
type ApplicationCommandTypes = Constants["ApplicationCommandTypes"][keyof Constants["ApplicationCommandTypes"]];
type ModalSubmitInteractionDataComponent = ModalSubmitInteractionDataTextInputComponent;
Expand Down Expand Up @@ -136,6 +137,7 @@ declare namespace Eris {
type InteractionContent = Pick<WebhookPayload, "content" | "embeds" | "allowedMentions" | "tts" | "flags" | "components" | "poll">;
type InteractionContentEdit = Pick<WebhookPayload, "content" | "embeds" | "allowedMentions" | "components">;
type InteractionDataOptions = InteractionDataOptionsSubCommand | InteractionDataOptionsSubCommandGroup | InteractionDataOptionsWithValue;
type InteractionDataOptionsAttachment = InteractionDataOptionWithValue<Constants["ApplicationCommandOptionTypes"]["ATTACHMENT"], string>;
type InteractionDataOptionsBoolean = InteractionDataOptionWithValue<Constants["ApplicationCommandOptionTypes"]["BOOLEAN"], boolean>;
type InteractionDataOptionsChannel = InteractionDataOptionWithValue<Constants["ApplicationCommandOptionTypes"]["CHANNEL"], string>;
type InteractionDataOptionsInteger = InteractionDataOptionWithValue<Constants["ApplicationCommandOptionTypes"]["INTEGER"], number>;
Expand All @@ -144,7 +146,7 @@ declare namespace Eris {
type InteractionDataOptionsRole = InteractionDataOptionWithValue<Constants["ApplicationCommandOptionTypes"]["ROLE"], string>;
type InteractionDataOptionsString = InteractionDataOptionWithValue<Constants["ApplicationCommandOptionTypes"]["STRING"], string>;
type InteractionDataOptionsUser = InteractionDataOptionWithValue<Constants["ApplicationCommandOptionTypes"]["USER"], string>;
type InteractionDataOptionsWithValue = InteractionDataOptionsString | InteractionDataOptionsInteger | InteractionDataOptionsBoolean | InteractionDataOptionsUser | InteractionDataOptionsChannel | InteractionDataOptionsRole | InteractionDataOptionsMentionable | InteractionDataOptionsNumber;
type InteractionDataOptionsWithValue = InteractionDataOptionsString | InteractionDataOptionsInteger | InteractionDataOptionsBoolean | InteractionDataOptionsUser | InteractionDataOptionsChannel | InteractionDataOptionsRole | InteractionDataOptionsMentionable | InteractionDataOptionsNumber | InteractionDataOptionsAttachment;
type InteractionResponseTypes = Constants["InteractionResponseTypes"][keyof Constants["InteractionResponseTypes"]];
type InteractionTypes = Constants["InteractionTypes"][keyof Constants["InteractionTypes"]];
type LocaleStrings = Constants["Locales"][keyof Constants["Locales"]];
Expand Down Expand Up @@ -1515,20 +1517,6 @@ declare namespace Eris {
roles?: boolean | string[];
users?: boolean | string[];
}
interface Attachment extends PartialAttachment {
content_type?: string;
duration_secs?: number;
ephemeral?: boolean;
filename: string;
flags?: number;
height?: number;
id: string;
proxy_url: string;
size: number;
url: string;
waveform?: string;
width?: number;
}
interface ButtonBase {
disabled?: boolean;
emoji?: Partial<PartialEmoji>;
Expand Down Expand Up @@ -2042,6 +2030,24 @@ declare namespace Eris {
edit(options: ApplicationCommandEditOptions<T, U>): Promise<ApplicationCommand<T, U>>;
}

export class Attachment extends Base {
contentType?: string;
description?: string;
durationSeconds?: number;
ephemeral?: boolean;
filename: string;
flags?: number;
height?: number;
id: string;
proxyURL: string;
size: number;
title?: string;
url: string;
waveform?: string;
width?: number;
constructor(data: BaseData);
}

class Base implements SimpleJSON {
createdAt: number;
id: string;
Expand Down Expand Up @@ -3072,7 +3078,7 @@ declare namespace Eris {
activity?: MessageActivity;
application?: MessageApplication;
applicationID?: string;
attachments: Attachment[];
attachments: Collection<Attachment>;
author: User;
channel: T;
channelMentions: string[];
Expand Down
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ function Eris(token, options) {
}

Eris.ApplicationCommand = require("./lib/structures/ApplicationCommand");
Eris.Attachment = require("./lib/structures/Attachment");
Eris.AutocompleteInteraction = require("./lib/structures/AutocompleteInteraction");
Eris.Base = require("./lib/structures/Base");
Eris.Bucket = require("./lib/util/Bucket");
Expand Down
1 change: 1 addition & 0 deletions lib/Constants.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default interface Constants {
ROLE: 8;
MENTIONABLE: 9;
NUMBER: 10;
ATTACHMENT: 11;
};
ApplicationCommandPermissionTypes: {
ROLE: 1;
Expand Down
80 changes: 80 additions & 0 deletions lib/structures/Attachment.js
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like some of these properties can be modified

Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"use strict";

const Base = require("./Base");

/**
* Represents an attachment
* @prop {String?} contentType The attachment's media type
* @prop {String?} description The description for the file (max 1024 characters)
* @prop {Number?} durationSeconds The duration of the audio file (currently for voice messages)
* @prop {Boolean?} ephemeral Whether the attachment is ephemeral
* @prop {String} filename The name of file attached
* @prop {Number?} flags The attachment flags combined as a bitfield
* @prop {Number?} height The height of file (if image)
* @prop {String} id The attachment ID
* @prop {String} proxyURL The proxy URL of the attachment
* @prop {Number} size The size of the file in bytes
* @prop {String?} title The title of the file
* @prop {String} url The source URL of the file
* @prop {String?} waveform The base64 encoded bytearray representing a sampled waveform (currently for voice messages)
* @prop {Number?} width The width of file (if image)
*/
class Attachment extends Base {
constructor(data) {
super(data.id);

this.filename = data.filename;
this.proxyURL = data.proxy_url;
this.size = data.size;
this.url = data.url;

if (data.content_type !== undefined) {
this.contentType = data.content_type;
}
if (data.description !== undefined) {
this.description = data.description;
}
if (data.duration_secs !== undefined) {
this.durationSeconds = data.duration_secs;
}
if (data.ephemeral !== undefined) {
this.ephemeral = data.ephemeral;
}
if (data.flags !== undefined) {
this.flags = data.flags;
}
if (data.height !== undefined) {
this.height = data.height;
}
if (data.title !== undefined) {
this.title = data.title;
}
if (data.waveform !== undefined) {
this.waveform = data.waveform;
}
if (data.width !== undefined) {
this.width = data.width;
}
}

toJSON(props = []) {
return super.toJSON([
"contentType",
"description",
"durationSeconds",
"ephemeral",
"filename",
"flags",
"height",
"proxyURL",
"size",
"title",
"url",
"waveform",
"width",
...props,
]);
}
}

module.exports = Attachment;
2 changes: 1 addition & 1 deletion lib/structures/AutocompleteInteraction.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const { InteractionResponseTypes } = require("../Constants");
* @prop {Boolean?} data.options[].focused Whether or not the option is focused
* @prop {String} data.options[].name The name of the Application Command option
* @prop {Array<Object>?} data.options[].options The run Application Command options (Mutually exclusive with value)
* @prop {Number} data.options[].type Command option type, 1-10
* @prop {Number} data.options[].type Command option type, 1-11
* @prop {(String | Number | Boolean)?} data.options[].value The value of the run Application Command (Mutually exclusive with options)
* @prop {String?} data.target_id The ID the of user or message targetted by a context menu command
* @prop {Number} data.type The [command type](https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-types)
Expand Down
43 changes: 26 additions & 17 deletions lib/structures/CommandInteraction.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const User = require("./User");
const Role = require("./Role");
const Channel = require("./Channel");
const Message = require("./Message");
const Attachment = require("./Attachment");
const Collection = require("../util/Collection");
const Permission = require("./Permission");

Expand All @@ -22,7 +23,7 @@ const { InteractionResponseTypes } = require("../Constants");
* @prop {Array<Object>?} data.options The run Application Command options
* @prop {String} data.options[].name The name of the Application Command option
* @prop {Array<Object>?} data.options[].options The run Application Command options (Mutually exclusive with value)
* @prop {Number} data.options[].type Command option type, 1-10
* @prop {Number} data.options[].type Command option type, 1-11
* @prop {(String | Number | Boolean)?} data.options[].value The value of the run Application Command (Mutually exclusive with options)
* @prop {String?} data.target_id The ID the of user or message targetted by a context menu command
* @prop {Number} data.type The [command type](https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-types)
Expand All @@ -48,50 +49,58 @@ class CommandInteraction extends Interaction {
if (data.data.resolved !== undefined) {
// Users
if (data.data.resolved.users !== undefined) {
const usermap = new Collection(User);
const userMap = new Collection(User);
Object.entries(data.data.resolved.users).forEach(([id, user]) => {
usermap.set(id, this._client.users.update(user, client));
userMap.set(id, this._client.users.update(user, client));
});
this.data.resolved.users = usermap;
this.data.resolved.users = userMap;
}
// Members
if (data.data.resolved.members !== undefined) {
const membermap = new Collection(Member);
const memberMap = new Collection(Member);
Object.entries(data.data.resolved.members).forEach(([id, member]) => {
member.id = id;
member.user = { id };
if (this.channel.guild) {
membermap.set(id, this.channel.guild.members.update(member, this.channel.guild));
memberMap.set(id, this.channel.guild.members.update(member, this.channel.guild));
} else {
const guild = this._client.guilds.get(data.guild_id);
membermap.set(id, guild.members.update(member, guild));
memberMap.set(id, guild.members.update(member, guild));
}
});
this.data.resolved.members = membermap;
this.data.resolved.members = memberMap;
}
// Roles
if (data.data.resolved.roles !== undefined) {
const rolemap = new Collection(Role);
const roleMap = new Collection(Role);
Object.entries(data.data.resolved.roles).forEach(([id, role]) => {
rolemap.set(id, new Role(role, this._client));
roleMap.set(id, new Role(role, this._client));
});
this.data.resolved.roles = rolemap;
this.data.resolved.roles = roleMap;
}
// Channels
if (data.data.resolved.channels !== undefined) {
const channelmap = new Collection(Channel);
const channelMap = new Collection(Channel);
Object.entries(data.data.resolved.channels).forEach(([id, channel]) => {
channelmap.set(id, new Channel(channel, this._client));
channelMap.set(id, new Channel(channel, this._client));
});
this.data.resolved.channels = channelmap;
this.data.resolved.channels = channelMap;
}
// Messages
if (data.data.resolved.messages !== undefined) {
const messagemap = new Collection(Message);
const messageMap = new Collection(Message);
Object.entries(data.data.resolved.messages).forEach(([id, message]) => {
messagemap.set(id, new Message(message, this._client));
messageMap.set(id, new Message(message, this._client));
});
this.data.resolved.messages = messagemap;
this.data.resolved.messages = messageMap;
}
// Attachments
if (data.data.resolved.attachments !== undefined) {
const attachmentMap = new Collection(Attachment);
Object.entries(data.data.resolved.attachments).forEach(([id, attachment]) => {
attachmentMap.set(id, new Attachment(attachment));
});
this.data.resolved.attachments = attachmentMap;
}
}

Expand Down
22 changes: 19 additions & 3 deletions lib/structures/Message.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const Base = require("./Base");
const Endpoints = require("../rest/Endpoints");
const { MessageFlags } = require("../Constants");
const User = require("./User");
const Attachment = require("./Attachment");
const Collection = require("../util/Collection");

/**
* Represents a message
Expand Down Expand Up @@ -61,6 +63,7 @@ class Message extends Base {
super(data.id);
this._client = client;
this.type = data.type || 0;
this.attachments = new Collection(Attachment);
this.timestamp = Date.parse(data.timestamp);
this.channel = this._client.getChannel(data.channel_id) || {
id: data.channel_id,
Expand Down Expand Up @@ -166,6 +169,12 @@ class Message extends Base {
this.member = null;
}

if (data.attachments) {
for (const attachment of data.attachments) {
this.attachments.add(attachment, this);
Copy link
Collaborator

@bsian03 bsian03 Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be able to update/delete, or overwrite completely

}
}

this.update(data, client);
}

Expand Down Expand Up @@ -194,14 +203,21 @@ class Message extends Base {
if (data.pinned !== undefined) {
this.pinned = !!data.pinned;
}
if (data.edited_timestamp != undefined) {
if (data.edited_timestamp !== undefined) {
this.editedTimestamp = Date.parse(data.edited_timestamp);
}
if (data.tts !== undefined) {
this.tts = data.tts;
}
if (data.attachments !== undefined) {
this.attachments = data.attachments;
if (data.attachments) {
for (const id of this.attachments.keys()) {
if (!data.attachments.some((attachment) => attachment.id === id)) {
this.attachments.delete(id);
}
}
for (const attachment of data.attachments) {
this.attachments.update(attachment, this);
}
}
if (data.embeds !== undefined) {
this.embeds = data.embeds;
Expand Down