revbot.js 0.0.3 → 0.0.4

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,46 @@ 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
+ if (Array.isArray(content.attachments)) {
2593
+ const promises = content.attachments.map((att) => __async(this, null, function* () {
2594
+ const data = new import_form_data.default();
2595
+ if (typeof att === "string") {
2596
+ const readableStream = yield import_axios.default.get(att, {
2597
+ responseType: "stream"
2598
+ });
2599
+ data.append("file", readableStream.data, {
2600
+ filename: att.split("/").pop()
2601
+ });
2602
+ }
2603
+ if (att instanceof import_stream.Readable) {
2604
+ data.append("file", att);
2605
+ }
2606
+ if (att instanceof import_node_buffer.File) {
2607
+ const buffer = Buffer.from(yield att.arrayBuffer());
2608
+ data.append("file", buffer, { filename: att.name });
2609
+ }
2610
+ yield this.client.cdn.post("/attachments", data).then((attachment) => {
2611
+ const { id } = attachment;
2612
+ attachments.push(id);
2613
+ });
2614
+ }));
2615
+ yield Promise.all(promises);
2616
+ }
2617
+ const resp = yield this.client.api.post(
2586
2618
  `/channels/${this.channel.id}/messages`,
2587
2619
  {
2588
- body: __spreadProps(__spreadValues({}, content), { nonce: UUID.generate() })
2620
+ body: __spreadProps(__spreadValues({}, content), { attachments, nonce: UUID.generate() })
2589
2621
  }
2590
2622
  );
2591
- return this._add(data);
2623
+ return this._add(resp);
2592
2624
  });
2593
2625
  }
2594
2626
  /**
@@ -3002,7 +3034,12 @@ var ServerMemberManager = class extends BaseManager {
3002
3034
  var import_node_events = require("events");
3003
3035
 
3004
3036
  // src/rest/restClient.ts
3005
- var import_axios = __toESM(require("axios"));
3037
+ var import_axios2 = __toESM(require("axios"));
3038
+
3039
+ // package.json
3040
+ var version = "0.0.4";
3041
+
3042
+ // src/rest/restClient.ts
3006
3043
  var RestClient = class {
3007
3044
  constructor(client3) {
3008
3045
  this.client = client3;
@@ -3025,10 +3062,11 @@ var RestClient = class {
3025
3062
  params: query,
3026
3063
  data: body == null ? void 0 : body.body,
3027
3064
  headers: {
3028
- "X-Bot-Token": this.client.token
3065
+ "X-Bot-Token": this.client.token,
3066
+ "User-Agent": `RevBot.js/${version}`
3029
3067
  }
3030
3068
  };
3031
- const response = yield (0, import_axios.default)(config);
3069
+ const response = yield (0, import_axios2.default)(config);
3032
3070
  return response.data;
3033
3071
  } catch (error) {
3034
3072
  console.error("API call failed:", error);
@@ -3096,6 +3134,58 @@ var RestClient = class {
3096
3134
  }
3097
3135
  };
3098
3136
 
3137
+ // src/rest/CDNClient.ts
3138
+ var import_axios3 = __toESM(require("axios"));
3139
+ var CDNClient = class {
3140
+ constructor(client3) {
3141
+ this.client = client3;
3142
+ }
3143
+ /**
3144
+ * Helper function to handle API requests.
3145
+ * @param method The HTTP method (GET, POST, PATCH, PUT, DELETE).
3146
+ * @param url The URL for the request.
3147
+ * @param body The request body (if applicable).
3148
+ * @param query Query parameters (if applicable).
3149
+ * @returns The API response.
3150
+ */
3151
+ request(method, url, data, query) {
3152
+ return __async(this, null, function* () {
3153
+ try {
3154
+ if (!this.client.token) throw new Error("Token is required");
3155
+ const config = {
3156
+ method,
3157
+ url: `${cdnUrl}${url}`,
3158
+ params: query,
3159
+ data,
3160
+ maxBodyLength: Infinity,
3161
+ headers: __spreadValues({
3162
+ "X-Bot-Token": this.client.token,
3163
+ "Content-Type": "multipart/form-data",
3164
+ "User-Agent": `RevBot.js/${version}`
3165
+ }, data.getHeaders())
3166
+ };
3167
+ const response = yield (0, import_axios3.default)(config);
3168
+ return response.data;
3169
+ } catch (error) {
3170
+ console.error("API call failed:", error);
3171
+ throw error;
3172
+ }
3173
+ });
3174
+ }
3175
+ /**
3176
+ * POST request.
3177
+ * @param url The URL for the request.
3178
+ * @param data The request body.
3179
+ * @param query Query parameters (if applicable).
3180
+ * @returns The API response.
3181
+ */
3182
+ post(url, data) {
3183
+ return __async(this, null, function* () {
3184
+ return this.request("POST", url, data);
3185
+ });
3186
+ }
3187
+ };
3188
+
3099
3189
  // src/client/baseClient.ts
3100
3190
  var _token;
3101
3191
  var BaseClient = class extends import_node_events.EventEmitter {
@@ -3112,6 +3202,7 @@ var BaseClient = class extends import_node_events.EventEmitter {
3112
3202
  this.bot = true;
3113
3203
  this.options = __spreadValues({}, options);
3114
3204
  this.api = new RestClient(this);
3205
+ this.cdn = new CDNClient(this);
3115
3206
  }
3116
3207
  /**
3117
3208
  * Emits a debug message.
@@ -4123,6 +4214,7 @@ var client2 = class extends BaseClient {
4123
4214
  VoiceChannel,
4124
4215
  WSEvents,
4125
4216
  apiUrl,
4217
+ cdnUrl,
4126
4218
  client,
4127
4219
  wsUrl
4128
4220
  });
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,46 @@ 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
+ if (Array.isArray(content.attachments)) {
2520
+ const promises = content.attachments.map((att) => __async(this, null, function* () {
2521
+ const data = new FormData();
2522
+ if (typeof att === "string") {
2523
+ const readableStream = yield axios.get(att, {
2524
+ responseType: "stream"
2525
+ });
2526
+ data.append("file", readableStream.data, {
2527
+ filename: att.split("/").pop()
2528
+ });
2529
+ }
2530
+ if (att instanceof Readable) {
2531
+ data.append("file", att);
2532
+ }
2533
+ if (att instanceof File) {
2534
+ const buffer = Buffer.from(yield att.arrayBuffer());
2535
+ data.append("file", buffer, { filename: att.name });
2536
+ }
2537
+ yield this.client.cdn.post("/attachments", data).then((attachment) => {
2538
+ const { id } = attachment;
2539
+ attachments.push(id);
2540
+ });
2541
+ }));
2542
+ yield Promise.all(promises);
2543
+ }
2544
+ const resp = yield this.client.api.post(
2514
2545
  `/channels/${this.channel.id}/messages`,
2515
2546
  {
2516
- body: __spreadProps(__spreadValues({}, content), { nonce: UUID.generate() })
2547
+ body: __spreadProps(__spreadValues({}, content), { attachments, nonce: UUID.generate() })
2517
2548
  }
2518
2549
  );
2519
- return this._add(data);
2550
+ return this._add(resp);
2520
2551
  });
2521
2552
  }
2522
2553
  /**
@@ -2930,7 +2961,12 @@ var ServerMemberManager = class extends BaseManager {
2930
2961
  import { EventEmitter } from "node:events";
2931
2962
 
2932
2963
  // src/rest/restClient.ts
2933
- import axios from "axios";
2964
+ import axios2 from "axios";
2965
+
2966
+ // package.json
2967
+ var version = "0.0.4";
2968
+
2969
+ // src/rest/restClient.ts
2934
2970
  var RestClient = class {
2935
2971
  constructor(client3) {
2936
2972
  this.client = client3;
@@ -2953,10 +2989,11 @@ var RestClient = class {
2953
2989
  params: query,
2954
2990
  data: body == null ? void 0 : body.body,
2955
2991
  headers: {
2956
- "X-Bot-Token": this.client.token
2992
+ "X-Bot-Token": this.client.token,
2993
+ "User-Agent": `RevBot.js/${version}`
2957
2994
  }
2958
2995
  };
2959
- const response = yield axios(config);
2996
+ const response = yield axios2(config);
2960
2997
  return response.data;
2961
2998
  } catch (error) {
2962
2999
  console.error("API call failed:", error);
@@ -3024,6 +3061,58 @@ var RestClient = class {
3024
3061
  }
3025
3062
  };
3026
3063
 
3064
+ // src/rest/CDNClient.ts
3065
+ import axios3 from "axios";
3066
+ var CDNClient = class {
3067
+ constructor(client3) {
3068
+ this.client = client3;
3069
+ }
3070
+ /**
3071
+ * Helper function to handle API requests.
3072
+ * @param method The HTTP method (GET, POST, PATCH, PUT, DELETE).
3073
+ * @param url The URL for the request.
3074
+ * @param body The request body (if applicable).
3075
+ * @param query Query parameters (if applicable).
3076
+ * @returns The API response.
3077
+ */
3078
+ request(method, url, data, query) {
3079
+ return __async(this, null, function* () {
3080
+ try {
3081
+ if (!this.client.token) throw new Error("Token is required");
3082
+ const config = {
3083
+ method,
3084
+ url: `${cdnUrl}${url}`,
3085
+ params: query,
3086
+ data,
3087
+ maxBodyLength: Infinity,
3088
+ headers: __spreadValues({
3089
+ "X-Bot-Token": this.client.token,
3090
+ "Content-Type": "multipart/form-data",
3091
+ "User-Agent": `RevBot.js/${version}`
3092
+ }, data.getHeaders())
3093
+ };
3094
+ const response = yield axios3(config);
3095
+ return response.data;
3096
+ } catch (error) {
3097
+ console.error("API call failed:", error);
3098
+ throw error;
3099
+ }
3100
+ });
3101
+ }
3102
+ /**
3103
+ * POST request.
3104
+ * @param url The URL for the request.
3105
+ * @param data The request body.
3106
+ * @param query Query parameters (if applicable).
3107
+ * @returns The API response.
3108
+ */
3109
+ post(url, data) {
3110
+ return __async(this, null, function* () {
3111
+ return this.request("POST", url, data);
3112
+ });
3113
+ }
3114
+ };
3115
+
3027
3116
  // src/client/baseClient.ts
3028
3117
  var _token;
3029
3118
  var BaseClient = class extends EventEmitter {
@@ -3040,6 +3129,7 @@ var BaseClient = class extends EventEmitter {
3040
3129
  this.bot = true;
3041
3130
  this.options = __spreadValues({}, options);
3042
3131
  this.api = new RestClient(this);
3132
+ this.cdn = new CDNClient(this);
3043
3133
  }
3044
3134
  /**
3045
3135
  * Emits a debug message.
@@ -4050,6 +4140,7 @@ export {
4050
4140
  VoiceChannel,
4051
4141
  WSEvents,
4052
4142
  apiUrl,
4143
+ cdnUrl,
4053
4144
  client2 as client,
4054
4145
  wsUrl
4055
4146
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "revbot.js",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
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",
@@ -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
  },