revbot.js 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,8 @@
1
1
  import { User as User$1, FieldsUser, SystemMessage, File, Message as Message$1, Server as Server$1, FieldsServer, Role as Role$1, FieldsRole, Channel as Channel$1, Invite as Invite$1, Embed as Embed$1, SendableEmbed, Special, FieldsChannel, Member, FieldsMember, Category as Category$1, MessageSort } from 'revolt-api';
2
+ import { File as File$1 } from 'node:buffer';
3
+ import { Readable } from 'stream';
2
4
  import { EventEmitter } from 'node:events';
5
+ import FormData from 'form-data';
3
6
 
4
7
  type PartialObject = Partial<{
5
8
  _id: string;
@@ -143,6 +146,28 @@ declare class RestClient {
143
146
  delete<T>(url: string, body?: any, query?: Record<string, string | number>): Promise<T>;
144
147
  }
145
148
 
149
+ declare class CDNClient {
150
+ private readonly client;
151
+ constructor(client: BaseClient);
152
+ /**
153
+ * Helper function to handle API requests.
154
+ * @param method The HTTP method (GET, POST, PATCH, PUT, DELETE).
155
+ * @param url The URL for the request.
156
+ * @param body The request body (if applicable).
157
+ * @param query Query parameters (if applicable).
158
+ * @returns The API response.
159
+ */
160
+ private request;
161
+ /**
162
+ * POST request.
163
+ * @param url The URL for the request.
164
+ * @param data The request body.
165
+ * @param query Query parameters (if applicable).
166
+ * @returns The API response.
167
+ */
168
+ post<T>(url: string, data: FormData): Promise<T>;
169
+ }
170
+
146
171
  /**
147
172
  * Represents the events that the client can emit.
148
173
  */
@@ -249,6 +274,8 @@ declare abstract class BaseClient extends EventEmitter {
249
274
  #private;
250
275
  /** The REST client for making API requests. */
251
276
  readonly api: RestClient;
277
+ /** The CDN client for accessing media resources. */
278
+ readonly cdn: CDNClient;
252
279
  /** The options for configuring the client. */
253
280
  options: clientOptions;
254
281
  /** Whether the client is a bot. */
@@ -364,6 +391,8 @@ declare const DEFAULT_CLIENT_OPTIONS: clientOptions;
364
391
  declare const wsUrl = "wss://ws.revolt.chat?version=1&format=json";
365
392
  /** The base API URL for interacting with the Revolt API. */
366
393
  declare const apiUrl = "https://api.revolt.chat";
394
+ /** The base URL for the Revolt CDN, used for serving static assets. */
395
+ declare const cdnUrl = "https://cdn.revoltusercontent.com";
367
396
  /** The system user ID used for identifying system messages. */
368
397
  declare const SYSTEM_USER_ID: string;
369
398
 
@@ -535,6 +564,8 @@ declare class User extends Base {
535
564
  * ```
536
565
  */
537
566
  createDM(): Promise<DMChannel>;
567
+ avatarURL(): string | undefined;
568
+ displayAvatarURL(): Promise<string>;
538
569
  /**
539
570
  * Fetches the latest data for the user from the API.
540
571
  *
@@ -668,7 +699,7 @@ declare class Message extends Base {
668
699
  * @param {boolean} [mention=true] - Whether to mention the original message author.
669
700
  * @returns {Promise<Message>} A promise that resolves with the sent reply message.
670
701
  */
671
- reply(content: string, mention?: boolean): Promise<Message>;
702
+ reply(content: MessageOptions | string, mention?: boolean): Promise<Message>;
672
703
  /**
673
704
  * Edits the message.
674
705
  *
@@ -2225,7 +2256,7 @@ interface MessageReply {
2225
2256
  interface MessageOptions {
2226
2257
  content?: string;
2227
2258
  replies?: MessageReply[];
2228
- attachments?: string[];
2259
+ attachments?: Readable[] | string[] | File$1[];
2229
2260
  embeds?: MessageEmbed[];
2230
2261
  }
2231
2262
  interface MessageEditOptions {
@@ -2256,7 +2287,7 @@ declare class MessageManager extends BaseManager<Message, Message$1> {
2256
2287
  * @param content The content to send. Can be a string or an object with the following properties:
2257
2288
  * - content: The content of the message
2258
2289
  * - replies: An array of message IDs to reply to
2259
- * - attachments: An array of attachment URLs
2290
+ * - attachments: An array of attachment URLs, Files, or ReadStreams
2260
2291
  * - embeds: An array of MessageEmbed objects
2261
2292
  * @returns Promise that resolves to the sent message
2262
2293
  */
@@ -2447,4 +2478,4 @@ declare class ServerMemberManager extends BaseManager<ServerMember, Member> {
2447
2478
  resolveId(member: ServerMemberResolvable): string | null;
2448
2479
  }
2449
2480
 
2450
- export { Attachment, type BadgeString, Badges, type BadgesResolvable, Base, BaseManager, BitField, type BitFieldResolvable, Category, Channel, ChannelManager, ChannelPermissions, type ChannelPermissionsResolvable, type ChannelPermissionsString, type ChannelResolvable, ChannelTypes, type CreateChannelOptions, DEFAULT_CLIENT_OPTIONS, DEFAULT_PERMISSION_DM, DMChannel, type EditServerMemberOptions, type EditServerOptions, type Embed, type EmbedImage, type EmbedSpecial, type EmbedVideo, Emoji, Events, GroupChannel, Invite, Mentions, Message, type MessageEditOptions, MessageEmbed, MessageManager, type MessageOptions, type MessageQueryOptions, type MessageReply, type MessageResolvable, type MessageSearchOptions, NotesChannel, type Overwrite, Presence, Role, RoleManager, type RoleResolvable, SYSTEM_USER_ID, Server, ServerChannel, ServerChannelManager, type ServerChannelResolvable, ServerManager, ServerMember, ServerMemberManager, type ServerMemberResolvable, ServerPermissions, type ServerPermissionsResolvable, type ServerPermissionsString, type ServerResolvable, Status, TextChannel, UUID, User, UserManager, UserPermissions, type UserPermissionsResolvable, type UserPermissionsString, type UserResolvable, VoiceChannel, WSEvents, apiUrl, client, wsUrl };
2481
+ export { Attachment, type BadgeString, Badges, type BadgesResolvable, Base, BaseManager, BitField, type BitFieldResolvable, Category, Channel, ChannelManager, ChannelPermissions, type ChannelPermissionsResolvable, type ChannelPermissionsString, type ChannelResolvable, ChannelTypes, type CreateChannelOptions, DEFAULT_CLIENT_OPTIONS, DEFAULT_PERMISSION_DM, DMChannel, type EditServerMemberOptions, type EditServerOptions, type Embed, type EmbedImage, type EmbedSpecial, type EmbedVideo, Emoji, Events, GroupChannel, Invite, Mentions, Message, type MessageEditOptions, MessageEmbed, MessageManager, type MessageOptions, type MessageQueryOptions, type MessageReply, type MessageResolvable, type MessageSearchOptions, NotesChannel, type Overwrite, Presence, Role, RoleManager, type RoleResolvable, SYSTEM_USER_ID, Server, ServerChannel, ServerChannelManager, type ServerChannelResolvable, ServerManager, ServerMember, ServerMemberManager, type ServerMemberResolvable, ServerPermissions, type ServerPermissionsResolvable, type ServerPermissionsString, type ServerResolvable, Status, TextChannel, UUID, User, UserManager, UserPermissions, type UserPermissionsResolvable, type UserPermissionsString, type UserResolvable, VoiceChannel, WSEvents, apiUrl, cdnUrl, client, wsUrl };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  import { User as User$1, FieldsUser, SystemMessage, File, Message as Message$1, Server as Server$1, FieldsServer, Role as Role$1, FieldsRole, Channel as Channel$1, Invite as Invite$1, Embed as Embed$1, SendableEmbed, Special, FieldsChannel, Member, FieldsMember, Category as Category$1, MessageSort } from 'revolt-api';
2
+ import { File as File$1 } from 'node:buffer';
3
+ import { Readable } from 'stream';
2
4
  import { EventEmitter } from 'node:events';
5
+ import FormData from 'form-data';
3
6
 
4
7
  type PartialObject = Partial<{
5
8
  _id: string;
@@ -143,6 +146,28 @@ declare class RestClient {
143
146
  delete<T>(url: string, body?: any, query?: Record<string, string | number>): Promise<T>;
144
147
  }
145
148
 
149
+ declare class CDNClient {
150
+ private readonly client;
151
+ constructor(client: BaseClient);
152
+ /**
153
+ * Helper function to handle API requests.
154
+ * @param method The HTTP method (GET, POST, PATCH, PUT, DELETE).
155
+ * @param url The URL for the request.
156
+ * @param body The request body (if applicable).
157
+ * @param query Query parameters (if applicable).
158
+ * @returns The API response.
159
+ */
160
+ private request;
161
+ /**
162
+ * POST request.
163
+ * @param url The URL for the request.
164
+ * @param data The request body.
165
+ * @param query Query parameters (if applicable).
166
+ * @returns The API response.
167
+ */
168
+ post<T>(url: string, data: FormData): Promise<T>;
169
+ }
170
+
146
171
  /**
147
172
  * Represents the events that the client can emit.
148
173
  */
@@ -249,6 +274,8 @@ declare abstract class BaseClient extends EventEmitter {
249
274
  #private;
250
275
  /** The REST client for making API requests. */
251
276
  readonly api: RestClient;
277
+ /** The CDN client for accessing media resources. */
278
+ readonly cdn: CDNClient;
252
279
  /** The options for configuring the client. */
253
280
  options: clientOptions;
254
281
  /** Whether the client is a bot. */
@@ -364,6 +391,8 @@ declare const DEFAULT_CLIENT_OPTIONS: clientOptions;
364
391
  declare const wsUrl = "wss://ws.revolt.chat?version=1&format=json";
365
392
  /** The base API URL for interacting with the Revolt API. */
366
393
  declare const apiUrl = "https://api.revolt.chat";
394
+ /** The base URL for the Revolt CDN, used for serving static assets. */
395
+ declare const cdnUrl = "https://cdn.revoltusercontent.com";
367
396
  /** The system user ID used for identifying system messages. */
368
397
  declare const SYSTEM_USER_ID: string;
369
398
 
@@ -535,6 +564,8 @@ declare class User extends Base {
535
564
  * ```
536
565
  */
537
566
  createDM(): Promise<DMChannel>;
567
+ avatarURL(): string | undefined;
568
+ displayAvatarURL(): Promise<string>;
538
569
  /**
539
570
  * Fetches the latest data for the user from the API.
540
571
  *
@@ -668,7 +699,7 @@ declare class Message extends Base {
668
699
  * @param {boolean} [mention=true] - Whether to mention the original message author.
669
700
  * @returns {Promise<Message>} A promise that resolves with the sent reply message.
670
701
  */
671
- reply(content: string, mention?: boolean): Promise<Message>;
702
+ reply(content: MessageOptions | string, mention?: boolean): Promise<Message>;
672
703
  /**
673
704
  * Edits the message.
674
705
  *
@@ -2225,7 +2256,7 @@ interface MessageReply {
2225
2256
  interface MessageOptions {
2226
2257
  content?: string;
2227
2258
  replies?: MessageReply[];
2228
- attachments?: string[];
2259
+ attachments?: Readable[] | string[] | File$1[];
2229
2260
  embeds?: MessageEmbed[];
2230
2261
  }
2231
2262
  interface MessageEditOptions {
@@ -2256,7 +2287,7 @@ declare class MessageManager extends BaseManager<Message, Message$1> {
2256
2287
  * @param content The content to send. Can be a string or an object with the following properties:
2257
2288
  * - content: The content of the message
2258
2289
  * - replies: An array of message IDs to reply to
2259
- * - attachments: An array of attachment URLs
2290
+ * - attachments: An array of attachment URLs, Files, or ReadStreams
2260
2291
  * - embeds: An array of MessageEmbed objects
2261
2292
  * @returns Promise that resolves to the sent message
2262
2293
  */
@@ -2447,4 +2478,4 @@ declare class ServerMemberManager extends BaseManager<ServerMember, Member> {
2447
2478
  resolveId(member: ServerMemberResolvable): string | null;
2448
2479
  }
2449
2480
 
2450
- export { Attachment, type BadgeString, Badges, type BadgesResolvable, Base, BaseManager, BitField, type BitFieldResolvable, Category, Channel, ChannelManager, ChannelPermissions, type ChannelPermissionsResolvable, type ChannelPermissionsString, type ChannelResolvable, ChannelTypes, type CreateChannelOptions, DEFAULT_CLIENT_OPTIONS, DEFAULT_PERMISSION_DM, DMChannel, type EditServerMemberOptions, type EditServerOptions, type Embed, type EmbedImage, type EmbedSpecial, type EmbedVideo, Emoji, Events, GroupChannel, Invite, Mentions, Message, type MessageEditOptions, MessageEmbed, MessageManager, type MessageOptions, type MessageQueryOptions, type MessageReply, type MessageResolvable, type MessageSearchOptions, NotesChannel, type Overwrite, Presence, Role, RoleManager, type RoleResolvable, SYSTEM_USER_ID, Server, ServerChannel, ServerChannelManager, type ServerChannelResolvable, ServerManager, ServerMember, ServerMemberManager, type ServerMemberResolvable, ServerPermissions, type ServerPermissionsResolvable, type ServerPermissionsString, type ServerResolvable, Status, TextChannel, UUID, User, UserManager, UserPermissions, type UserPermissionsResolvable, type UserPermissionsString, type UserResolvable, VoiceChannel, WSEvents, apiUrl, client, wsUrl };
2481
+ export { Attachment, type BadgeString, Badges, type BadgesResolvable, Base, BaseManager, BitField, type BitFieldResolvable, Category, Channel, ChannelManager, ChannelPermissions, type ChannelPermissionsResolvable, type ChannelPermissionsString, type ChannelResolvable, ChannelTypes, type CreateChannelOptions, DEFAULT_CLIENT_OPTIONS, DEFAULT_PERMISSION_DM, DMChannel, type EditServerMemberOptions, type EditServerOptions, type Embed, type EmbedImage, type EmbedSpecial, type EmbedVideo, Emoji, Events, GroupChannel, Invite, Mentions, Message, type MessageEditOptions, MessageEmbed, MessageManager, type MessageOptions, type MessageQueryOptions, type MessageReply, type MessageResolvable, type MessageSearchOptions, NotesChannel, type Overwrite, Presence, Role, RoleManager, type RoleResolvable, SYSTEM_USER_ID, Server, ServerChannel, ServerChannelManager, type ServerChannelResolvable, ServerManager, ServerMember, ServerMemberManager, type ServerMemberResolvable, ServerPermissions, type ServerPermissionsResolvable, type ServerPermissionsString, type ServerResolvable, Status, TextChannel, UUID, User, UserManager, UserPermissions, type UserPermissionsResolvable, type UserPermissionsString, type UserResolvable, VoiceChannel, WSEvents, apiUrl, cdnUrl, client, wsUrl };
package/dist/index.js CHANGED
@@ -149,6 +149,7 @@ __export(index_exports, {
149
149
  VoiceChannel: () => VoiceChannel,
150
150
  WSEvents: () => WSEvents,
151
151
  apiUrl: () => apiUrl,
152
+ cdnUrl: () => cdnUrl,
152
153
  client: () => client2,
153
154
  wsUrl: () => wsUrl
154
155
  });
@@ -464,6 +465,7 @@ var DEFAULT_CLIENT_OPTIONS = {
464
465
  };
465
466
  var wsUrl = "wss://ws.revolt.chat?version=1&format=json";
466
467
  var apiUrl = "https://api.revolt.chat";
468
+ var cdnUrl = "https://cdn.revoltusercontent.com";
467
469
  var SYSTEM_USER_ID = "0".repeat(UUID.TIME_LENGTH + UUID.RANDOM_LENGTH);
468
470
 
469
471
  // src/utils/permissions.ts
@@ -660,21 +662,18 @@ var User = class extends Base {
660
662
  return this.client.channels._add(data);
661
663
  });
662
664
  }
663
- // avatarURL(options?: { size: number }): string | null {
664
- // return this.avatar
665
- // ? this.client.api.cdn.avatar(
666
- // this.avatar.id,
667
- // this.avatar.filename,
668
- // options?.size,
669
- // )
670
- // : null;
671
- // }
672
- // async displayAvatarURL(options?: { size: number }): Promise<string> {
673
- // const defaultAvatar = (await this.client.api.get(
674
- // `/users/${this.id}/default_avatar`,
675
- // )) as string;
676
- // return this.avatarURL(options) ?? defaultAvatar;
677
- // }
665
+ avatarURL() {
666
+ var _a, _b;
667
+ if (!((_a = this.avatar) == null ? void 0 : _a.id)) return void 0;
668
+ return `${cdnUrl}/avatars/${(_b = this.avatar) == null ? void 0 : _b.id}`;
669
+ }
670
+ displayAvatarURL() {
671
+ return __async(this, null, function* () {
672
+ var _a;
673
+ const defaultAvatar = `${cdnUrl}/users/${this.id}/default_avatar`;
674
+ return (_a = this.avatarURL()) != null ? _a : defaultAvatar;
675
+ });
676
+ }
678
677
  /**
679
678
  * Fetches the latest data for the user from the API.
680
679
  *
@@ -708,6 +707,10 @@ var Message = class extends Base {
708
707
  this.type = "TEXT";
709
708
  /** The content of the message. */
710
709
  this.content = "";
710
+ /** The ID of the channel where the message was sent. */
711
+ this.channelId = "";
712
+ /** The ID of the user who authored the message. */
713
+ this.authorId = "";
711
714
  /** An array of embeds included in the message. */
712
715
  this.embeds = [];
713
716
  /** An array of file attachments included in the message. */
@@ -863,10 +866,9 @@ var Message = class extends Base {
863
866
  * @returns {Promise<Message>} A promise that resolves with the sent reply message.
864
867
  */
865
868
  reply(content, mention = true) {
866
- return this.channel.messages.send({
867
- content,
869
+ return this.channel.messages.send(__spreadProps(__spreadValues({}, typeof content === "object" ? content : { content }), {
868
870
  replies: [{ id: this.id, mention }]
869
- });
871
+ }));
870
872
  }
871
873
  /**
872
874
  * Edits the message.
@@ -2564,6 +2566,10 @@ var UserManager = class extends BaseManager {
2564
2566
  };
2565
2567
 
2566
2568
  // src/managers/messageManager.ts
2569
+ var import_node_buffer = require("buffer");
2570
+ var import_stream = require("stream");
2571
+ var import_form_data = __toESM(require("form-data"));
2572
+ var import_axios = __toESM(require("axios"));
2567
2573
  var MessageManager = class extends BaseManager {
2568
2574
  constructor(channel) {
2569
2575
  super(channel.client);
@@ -2575,20 +2581,50 @@ var MessageManager = class extends BaseManager {
2575
2581
  * @param content The content to send. Can be a string or an object with the following properties:
2576
2582
  * - content: The content of the message
2577
2583
  * - replies: An array of message IDs to reply to
2578
- * - attachments: An array of attachment URLs
2584
+ * - attachments: An array of attachment URLs, Files, or ReadStreams
2579
2585
  * - embeds: An array of MessageEmbed objects
2580
2586
  * @returns Promise that resolves to the sent message
2581
2587
  */
2582
2588
  send(content) {
2583
2589
  return __async(this, null, function* () {
2584
2590
  if (typeof content === "string") content = { content };
2585
- const data = yield this.client.api.post(
2591
+ let attachments = [];
2592
+ let embeds = [];
2593
+ if (Array.isArray(content.attachments)) {
2594
+ const promises = content.attachments.map((att) => __async(this, null, function* () {
2595
+ const data = new import_form_data.default();
2596
+ if (typeof att === "string") {
2597
+ const readableStream = yield import_axios.default.get(att, {
2598
+ responseType: "stream"
2599
+ });
2600
+ data.append("file", readableStream.data, {
2601
+ filename: att.split("/").pop()
2602
+ });
2603
+ }
2604
+ if (att instanceof import_stream.Readable) {
2605
+ data.append("file", att);
2606
+ }
2607
+ if (att instanceof import_node_buffer.File) {
2608
+ const buffer = Buffer.from(yield att.arrayBuffer());
2609
+ data.append("file", buffer, { filename: att.name });
2610
+ }
2611
+ yield this.client.cdn.post("/attachments", data).then((attachment) => {
2612
+ const { id } = attachment;
2613
+ attachments.push(id);
2614
+ });
2615
+ }));
2616
+ yield Promise.all(promises);
2617
+ }
2618
+ if (Array.isArray(content.embeds)) {
2619
+ content.embeds.map((embed) => embeds.push(embed.toJSON()));
2620
+ }
2621
+ const resp = yield this.client.api.post(
2586
2622
  `/channels/${this.channel.id}/messages`,
2587
2623
  {
2588
- body: __spreadProps(__spreadValues({}, content), { nonce: UUID.generate() })
2624
+ body: __spreadProps(__spreadValues({}, content), { attachments, embeds, nonce: UUID.generate() })
2589
2625
  }
2590
2626
  );
2591
- return this._add(data);
2627
+ return this._add(resp);
2592
2628
  });
2593
2629
  }
2594
2630
  /**
@@ -3002,7 +3038,12 @@ var ServerMemberManager = class extends BaseManager {
3002
3038
  var import_node_events = require("events");
3003
3039
 
3004
3040
  // src/rest/restClient.ts
3005
- var import_axios = __toESM(require("axios"));
3041
+ var import_axios2 = __toESM(require("axios"));
3042
+
3043
+ // package.json
3044
+ var version = "0.0.4";
3045
+
3046
+ // src/rest/restClient.ts
3006
3047
  var RestClient = class {
3007
3048
  constructor(client3) {
3008
3049
  this.client = client3;
@@ -3025,10 +3066,11 @@ var RestClient = class {
3025
3066
  params: query,
3026
3067
  data: body == null ? void 0 : body.body,
3027
3068
  headers: {
3028
- "X-Bot-Token": this.client.token
3069
+ "X-Bot-Token": this.client.token,
3070
+ "User-Agent": `RevBot.js/${version}`
3029
3071
  }
3030
3072
  };
3031
- const response = yield (0, import_axios.default)(config);
3073
+ const response = yield (0, import_axios2.default)(config);
3032
3074
  return response.data;
3033
3075
  } catch (error) {
3034
3076
  console.error("API call failed:", error);
@@ -3096,6 +3138,58 @@ var RestClient = class {
3096
3138
  }
3097
3139
  };
3098
3140
 
3141
+ // src/rest/CDNClient.ts
3142
+ var import_axios3 = __toESM(require("axios"));
3143
+ var CDNClient = class {
3144
+ constructor(client3) {
3145
+ this.client = client3;
3146
+ }
3147
+ /**
3148
+ * Helper function to handle API requests.
3149
+ * @param method The HTTP method (GET, POST, PATCH, PUT, DELETE).
3150
+ * @param url The URL for the request.
3151
+ * @param body The request body (if applicable).
3152
+ * @param query Query parameters (if applicable).
3153
+ * @returns The API response.
3154
+ */
3155
+ request(method, url, data, query) {
3156
+ return __async(this, null, function* () {
3157
+ try {
3158
+ if (!this.client.token) throw new Error("Token is required");
3159
+ const config = {
3160
+ method,
3161
+ url: `${cdnUrl}${url}`,
3162
+ params: query,
3163
+ data,
3164
+ maxBodyLength: Infinity,
3165
+ headers: __spreadValues({
3166
+ "X-Bot-Token": this.client.token,
3167
+ "Content-Type": "multipart/form-data",
3168
+ "User-Agent": `RevBot.js/${version}`
3169
+ }, data.getHeaders())
3170
+ };
3171
+ const response = yield (0, import_axios3.default)(config);
3172
+ return response.data;
3173
+ } catch (error) {
3174
+ console.error("API call failed:", error);
3175
+ throw error;
3176
+ }
3177
+ });
3178
+ }
3179
+ /**
3180
+ * POST request.
3181
+ * @param url The URL for the request.
3182
+ * @param data The request body.
3183
+ * @param query Query parameters (if applicable).
3184
+ * @returns The API response.
3185
+ */
3186
+ post(url, data) {
3187
+ return __async(this, null, function* () {
3188
+ return this.request("POST", url, data);
3189
+ });
3190
+ }
3191
+ };
3192
+
3099
3193
  // src/client/baseClient.ts
3100
3194
  var _token;
3101
3195
  var BaseClient = class extends import_node_events.EventEmitter {
@@ -3112,6 +3206,7 @@ var BaseClient = class extends import_node_events.EventEmitter {
3112
3206
  this.bot = true;
3113
3207
  this.options = __spreadValues({}, options);
3114
3208
  this.api = new RestClient(this);
3209
+ this.cdn = new CDNClient(this);
3115
3210
  }
3116
3211
  /**
3117
3212
  * Emits a debug message.
@@ -4123,6 +4218,7 @@ var client2 = class extends BaseClient {
4123
4218
  VoiceChannel,
4124
4219
  WSEvents,
4125
4220
  apiUrl,
4221
+ cdnUrl,
4126
4222
  client,
4127
4223
  wsUrl
4128
4224
  });
package/dist/index.mjs CHANGED
@@ -392,6 +392,7 @@ var DEFAULT_CLIENT_OPTIONS = {
392
392
  };
393
393
  var wsUrl = "wss://ws.revolt.chat?version=1&format=json";
394
394
  var apiUrl = "https://api.revolt.chat";
395
+ var cdnUrl = "https://cdn.revoltusercontent.com";
395
396
  var SYSTEM_USER_ID = "0".repeat(UUID.TIME_LENGTH + UUID.RANDOM_LENGTH);
396
397
 
397
398
  // src/utils/permissions.ts
@@ -588,21 +589,18 @@ var User = class extends Base {
588
589
  return this.client.channels._add(data);
589
590
  });
590
591
  }
591
- // avatarURL(options?: { size: number }): string | null {
592
- // return this.avatar
593
- // ? this.client.api.cdn.avatar(
594
- // this.avatar.id,
595
- // this.avatar.filename,
596
- // options?.size,
597
- // )
598
- // : null;
599
- // }
600
- // async displayAvatarURL(options?: { size: number }): Promise<string> {
601
- // const defaultAvatar = (await this.client.api.get(
602
- // `/users/${this.id}/default_avatar`,
603
- // )) as string;
604
- // return this.avatarURL(options) ?? defaultAvatar;
605
- // }
592
+ avatarURL() {
593
+ var _a, _b;
594
+ if (!((_a = this.avatar) == null ? void 0 : _a.id)) return void 0;
595
+ return `${cdnUrl}/avatars/${(_b = this.avatar) == null ? void 0 : _b.id}`;
596
+ }
597
+ displayAvatarURL() {
598
+ return __async(this, null, function* () {
599
+ var _a;
600
+ const defaultAvatar = `${cdnUrl}/users/${this.id}/default_avatar`;
601
+ return (_a = this.avatarURL()) != null ? _a : defaultAvatar;
602
+ });
603
+ }
606
604
  /**
607
605
  * Fetches the latest data for the user from the API.
608
606
  *
@@ -636,6 +634,10 @@ var Message = class extends Base {
636
634
  this.type = "TEXT";
637
635
  /** The content of the message. */
638
636
  this.content = "";
637
+ /** The ID of the channel where the message was sent. */
638
+ this.channelId = "";
639
+ /** The ID of the user who authored the message. */
640
+ this.authorId = "";
639
641
  /** An array of embeds included in the message. */
640
642
  this.embeds = [];
641
643
  /** An array of file attachments included in the message. */
@@ -791,10 +793,9 @@ var Message = class extends Base {
791
793
  * @returns {Promise<Message>} A promise that resolves with the sent reply message.
792
794
  */
793
795
  reply(content, mention = true) {
794
- return this.channel.messages.send({
795
- content,
796
+ return this.channel.messages.send(__spreadProps(__spreadValues({}, typeof content === "object" ? content : { content }), {
796
797
  replies: [{ id: this.id, mention }]
797
- });
798
+ }));
798
799
  }
799
800
  /**
800
801
  * Edits the message.
@@ -2492,6 +2493,10 @@ var UserManager = class extends BaseManager {
2492
2493
  };
2493
2494
 
2494
2495
  // src/managers/messageManager.ts
2496
+ import { File } from "node:buffer";
2497
+ import { Readable } from "stream";
2498
+ import FormData from "form-data";
2499
+ import axios from "axios";
2495
2500
  var MessageManager = class extends BaseManager {
2496
2501
  constructor(channel) {
2497
2502
  super(channel.client);
@@ -2503,20 +2508,50 @@ var MessageManager = class extends BaseManager {
2503
2508
  * @param content The content to send. Can be a string or an object with the following properties:
2504
2509
  * - content: The content of the message
2505
2510
  * - replies: An array of message IDs to reply to
2506
- * - attachments: An array of attachment URLs
2511
+ * - attachments: An array of attachment URLs, Files, or ReadStreams
2507
2512
  * - embeds: An array of MessageEmbed objects
2508
2513
  * @returns Promise that resolves to the sent message
2509
2514
  */
2510
2515
  send(content) {
2511
2516
  return __async(this, null, function* () {
2512
2517
  if (typeof content === "string") content = { content };
2513
- const data = yield this.client.api.post(
2518
+ let attachments = [];
2519
+ let embeds = [];
2520
+ if (Array.isArray(content.attachments)) {
2521
+ const promises = content.attachments.map((att) => __async(this, null, function* () {
2522
+ const data = new FormData();
2523
+ if (typeof att === "string") {
2524
+ const readableStream = yield axios.get(att, {
2525
+ responseType: "stream"
2526
+ });
2527
+ data.append("file", readableStream.data, {
2528
+ filename: att.split("/").pop()
2529
+ });
2530
+ }
2531
+ if (att instanceof Readable) {
2532
+ data.append("file", att);
2533
+ }
2534
+ if (att instanceof File) {
2535
+ const buffer = Buffer.from(yield att.arrayBuffer());
2536
+ data.append("file", buffer, { filename: att.name });
2537
+ }
2538
+ yield this.client.cdn.post("/attachments", data).then((attachment) => {
2539
+ const { id } = attachment;
2540
+ attachments.push(id);
2541
+ });
2542
+ }));
2543
+ yield Promise.all(promises);
2544
+ }
2545
+ if (Array.isArray(content.embeds)) {
2546
+ content.embeds.map((embed) => embeds.push(embed.toJSON()));
2547
+ }
2548
+ const resp = yield this.client.api.post(
2514
2549
  `/channels/${this.channel.id}/messages`,
2515
2550
  {
2516
- body: __spreadProps(__spreadValues({}, content), { nonce: UUID.generate() })
2551
+ body: __spreadProps(__spreadValues({}, content), { attachments, embeds, nonce: UUID.generate() })
2517
2552
  }
2518
2553
  );
2519
- return this._add(data);
2554
+ return this._add(resp);
2520
2555
  });
2521
2556
  }
2522
2557
  /**
@@ -2930,7 +2965,12 @@ var ServerMemberManager = class extends BaseManager {
2930
2965
  import { EventEmitter } from "node:events";
2931
2966
 
2932
2967
  // src/rest/restClient.ts
2933
- import axios from "axios";
2968
+ import axios2 from "axios";
2969
+
2970
+ // package.json
2971
+ var version = "0.0.4";
2972
+
2973
+ // src/rest/restClient.ts
2934
2974
  var RestClient = class {
2935
2975
  constructor(client3) {
2936
2976
  this.client = client3;
@@ -2953,10 +2993,11 @@ var RestClient = class {
2953
2993
  params: query,
2954
2994
  data: body == null ? void 0 : body.body,
2955
2995
  headers: {
2956
- "X-Bot-Token": this.client.token
2996
+ "X-Bot-Token": this.client.token,
2997
+ "User-Agent": `RevBot.js/${version}`
2957
2998
  }
2958
2999
  };
2959
- const response = yield axios(config);
3000
+ const response = yield axios2(config);
2960
3001
  return response.data;
2961
3002
  } catch (error) {
2962
3003
  console.error("API call failed:", error);
@@ -3024,6 +3065,58 @@ var RestClient = class {
3024
3065
  }
3025
3066
  };
3026
3067
 
3068
+ // src/rest/CDNClient.ts
3069
+ import axios3 from "axios";
3070
+ var CDNClient = class {
3071
+ constructor(client3) {
3072
+ this.client = client3;
3073
+ }
3074
+ /**
3075
+ * Helper function to handle API requests.
3076
+ * @param method The HTTP method (GET, POST, PATCH, PUT, DELETE).
3077
+ * @param url The URL for the request.
3078
+ * @param body The request body (if applicable).
3079
+ * @param query Query parameters (if applicable).
3080
+ * @returns The API response.
3081
+ */
3082
+ request(method, url, data, query) {
3083
+ return __async(this, null, function* () {
3084
+ try {
3085
+ if (!this.client.token) throw new Error("Token is required");
3086
+ const config = {
3087
+ method,
3088
+ url: `${cdnUrl}${url}`,
3089
+ params: query,
3090
+ data,
3091
+ maxBodyLength: Infinity,
3092
+ headers: __spreadValues({
3093
+ "X-Bot-Token": this.client.token,
3094
+ "Content-Type": "multipart/form-data",
3095
+ "User-Agent": `RevBot.js/${version}`
3096
+ }, data.getHeaders())
3097
+ };
3098
+ const response = yield axios3(config);
3099
+ return response.data;
3100
+ } catch (error) {
3101
+ console.error("API call failed:", error);
3102
+ throw error;
3103
+ }
3104
+ });
3105
+ }
3106
+ /**
3107
+ * POST request.
3108
+ * @param url The URL for the request.
3109
+ * @param data The request body.
3110
+ * @param query Query parameters (if applicable).
3111
+ * @returns The API response.
3112
+ */
3113
+ post(url, data) {
3114
+ return __async(this, null, function* () {
3115
+ return this.request("POST", url, data);
3116
+ });
3117
+ }
3118
+ };
3119
+
3027
3120
  // src/client/baseClient.ts
3028
3121
  var _token;
3029
3122
  var BaseClient = class extends EventEmitter {
@@ -3040,6 +3133,7 @@ var BaseClient = class extends EventEmitter {
3040
3133
  this.bot = true;
3041
3134
  this.options = __spreadValues({}, options);
3042
3135
  this.api = new RestClient(this);
3136
+ this.cdn = new CDNClient(this);
3043
3137
  }
3044
3138
  /**
3045
3139
  * Emits a debug message.
@@ -4050,6 +4144,7 @@ export {
4050
4144
  VoiceChannel,
4051
4145
  WSEvents,
4052
4146
  apiUrl,
4147
+ cdnUrl,
4053
4148
  client2 as client,
4054
4149
  wsUrl
4055
4150
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "revbot.js",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "A Revolt bot client used to interact with the revolt api for Node.js, written in TypeScript.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -19,7 +19,7 @@
19
19
  ],
20
20
  "homepage": "https://jade3375.github.io/revbot.js/",
21
21
  "author": "Jade3375",
22
- "license": "MIT License",
22
+ "license": "MIT",
23
23
  "packageManager": "yarn@4.9.1",
24
24
  "devDependencies": {
25
25
  "@mxssfd/typedoc-theme": "^1.1.7",
@@ -37,6 +37,7 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "axios": "^1.9.0",
40
+ "form-data": "^4.0.2",
40
41
  "revolt-api": "^0.8.6-1",
41
42
  "ws": "^8.18.1"
42
43
  },