flarecord 0.0.2 → 0.0.3

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/README.md CHANGED
@@ -8,29 +8,13 @@ discord gateway client for cloudflare workers. built with typescript and optimiz
8
8
  npm install flarecord
9
9
  ```
10
10
 
11
- ## using source files directly
12
-
13
- if you encounter bundling issues with the compiled version, you can import directly from the source files:
11
+ ## import
14
12
 
15
13
  ```typescript
16
- // import from source (recommended for cloudflare workers)
17
- import { DiscordClient, GatewayIntents, MessageHelper } from "flarecord/src";
18
-
19
- // or import specific modules
20
- import { DiscordClient } from "flarecord/src/core/client";
21
- import { MessageHelper } from "flarecord/src/utils/message-helper";
14
+ import { DiscordClient, GatewayIntents, MessageHelper } from "flarecord";
22
15
  ```
23
16
 
24
- **when to use source files:**
25
- - cloudflare workers projects (handles typescript natively)
26
- - when you need to avoid bundling issues
27
- - when you want to use the latest source code
28
-
29
- **when to use compiled version:**
30
- - standard node.js projects
31
- - when you prefer pre-compiled javascript
32
-
33
- the source files are included in the npm package, so both options work without additional configuration.
17
+ flarecord uses source files by default for cloudflare workers.
34
18
 
35
19
  ## how it works
36
20
 
@@ -55,7 +39,6 @@ the library handles all the complexity of the discord gateway protocol automatic
55
39
  - interaction events
56
40
  - all discord gateway events
57
41
  - typescript support
58
- - discord.js compatible builders (embeds, buttons, etc)
59
42
 
60
43
  ## example
61
44
 
@@ -143,7 +126,7 @@ available intents: GUILDS, GUILD_MEMBERS, GUILD_MODERATION, GUILD_EMOJIS_AND_STI
143
126
  use `MessageHelper` to send messages, embeds, buttons, and more:
144
127
 
145
128
  ```typescript
146
- import { MessageHelper, EmbedBuilder, ButtonBuilder, ActionRowBuilder, ButtonStyle } from "flarecord";
129
+ import { MessageHelper } from "flarecord";
147
130
 
148
131
  const helper = new MessageHelper(token);
149
132
 
@@ -151,18 +134,24 @@ const helper = new MessageHelper(token);
151
134
  await helper.send(channelId, "hello!");
152
135
 
153
136
  // send embed
154
- const embed = new EmbedBuilder()
155
- .setTitle("title")
156
- .setDescription("description")
157
- .setColor(0x00ff00);
137
+ const embed = {
138
+ title: "title",
139
+ description: "description",
140
+ color: 0x00ff00,
141
+ };
158
142
  await helper.send(channelId, embed);
159
143
 
160
144
  // send button
161
- const button = new ButtonBuilder()
162
- .setCustomId("button_id")
163
- .setLabel("click me")
164
- .setStyle(ButtonStyle.Primary);
165
- const row = new ActionRowBuilder().addComponents(button);
145
+ const button = {
146
+ type: 2,
147
+ style: 1,
148
+ custom_id: "button_id",
149
+ label: "click me",
150
+ };
151
+ const row = {
152
+ type: 1,
153
+ components: [button],
154
+ };
166
155
  await helper.send(channelId, row);
167
156
 
168
157
  // reply to message
package/dist/index.d.ts CHANGED
@@ -10,5 +10,4 @@ export { Logger, LogLevel, createLogger } from "./utils/logger";
10
10
  export type { GatewayPayload, HelloData, IdentifyData, ResumeData, ReadyData, GatewayState, GatewayConfig, MessageData, } from "./types";
11
11
  export { GatewayOpcode, GatewayEvent, GatewayIntents, WebSocketCloseCode, RESUMEABLE_CLOSE_CODES, GATEWAY_BASE_URL, GATEWAY_VERSION, GATEWAY_ENCODING, DEFAULT_RECONNECT_DELAYS, WEBSOCKET_READY_STATE_OPEN, DEFAULT_STORAGE_KEY, DEFAULT_MAX_RECONNECT_ATTEMPTS, } from "./types/constants";
12
12
  export { DEFAULT_IDENTIFY_PROPERTIES } from "./types";
13
- export { EmbedBuilder, ActionRowBuilder, ButtonBuilder, StringSelectMenuBuilder, UserSelectMenuBuilder, RoleSelectMenuBuilder, ChannelSelectMenuBuilder, MentionableSelectMenuBuilder, ModalBuilder, TextInputBuilder, AttachmentBuilder, SlashCommandBuilder, ContextMenuCommandBuilder, SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder, SlashCommandOptionsOnlyBuilder, SlashCommandBooleanOption, SlashCommandChannelOption, SlashCommandIntegerOption, SlashCommandMentionableOption, SlashCommandNumberOption, SlashCommandRoleOption, SlashCommandStringOption, SlashCommandUserOption, REST, Routes, Colors, PermissionFlagsBits, GatewayIntentBits, Events, ActivityType, ChannelType, MessageType, InteractionType, ApplicationCommandType, ButtonStyle, TextInputStyle, ComponentType, Locale, type APIEmbed, type APIEmbedField, type APIButtonComponent, type APIActionRowComponent, type APIMessageComponent, type RESTPostAPIChannelMessageJSONBody, type RESTPostAPIChannelMessageResult, type APIInteractionResponse, type APIMessage, type APIUser, type APIGuild, type APIChannel, type APIInteraction, type APIChatInputApplicationCommandInteraction, type APIMessageApplicationCommandInteraction, type APIUserApplicationCommandInteraction, type APIMessageComponentInteraction, type APIModalSubmitInteraction, } from "discord.js";
14
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEhE,YAAY,EACV,cAAc,EACd,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,YAAY,EACZ,aAAa,EACb,WAAW,GACZ,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EACnB,8BAA8B,GAC/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAEtD,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,EAC5B,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,yBAAyB,EACzB,6BAA6B,EAC7B,kCAAkC,EAClC,8BAA8B,EAC9B,yBAAyB,EACzB,yBAAyB,EACzB,yBAAyB,EACzB,6BAA6B,EAC7B,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,EACtB,IAAI,EACJ,MAAM,EACN,MAAM,EACN,mBAAmB,EACnB,iBAAiB,EACjB,MAAM,EACN,YAAY,EACZ,WAAW,EACX,WAAW,EACX,eAAe,EACf,sBAAsB,EACtB,WAAW,EACX,cAAc,EACd,aAAa,EACb,MAAM,EACN,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,iCAAiC,EACtC,KAAK,+BAA+B,EACpC,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,yCAAyC,EAC9C,KAAK,uCAAuC,EAC5C,KAAK,oCAAoC,EACzC,KAAK,8BAA8B,EACnC,KAAK,yBAAyB,GAC/B,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEhE,YAAY,EACV,cAAc,EACd,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,YAAY,EACZ,aAAa,EACb,WAAW,GACZ,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EACnB,8BAA8B,GAC/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -9,5 +9,4 @@ export { SessionManager } from "./utils/session";
9
9
  export { Logger, LogLevel, createLogger } from "./utils/logger";
10
10
  export { GatewayOpcode, GatewayEvent, GatewayIntents, WebSocketCloseCode, RESUMEABLE_CLOSE_CODES, GATEWAY_BASE_URL, GATEWAY_VERSION, GATEWAY_ENCODING, DEFAULT_RECONNECT_DELAYS, WEBSOCKET_READY_STATE_OPEN, DEFAULT_STORAGE_KEY, DEFAULT_MAX_RECONNECT_ATTEMPTS, } from "./types/constants";
11
11
  export { DEFAULT_IDENTIFY_PROPERTIES } from "./types";
12
- export { EmbedBuilder, ActionRowBuilder, ButtonBuilder, StringSelectMenuBuilder, UserSelectMenuBuilder, RoleSelectMenuBuilder, ChannelSelectMenuBuilder, MentionableSelectMenuBuilder, ModalBuilder, TextInputBuilder, AttachmentBuilder, SlashCommandBuilder, ContextMenuCommandBuilder, SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder, SlashCommandBooleanOption, SlashCommandChannelOption, SlashCommandIntegerOption, SlashCommandMentionableOption, SlashCommandNumberOption, SlashCommandRoleOption, SlashCommandStringOption, SlashCommandUserOption, REST, Routes, Colors, PermissionFlagsBits, GatewayIntentBits, Events, ActivityType, ChannelType, MessageType, InteractionType, ApplicationCommandType, ButtonStyle, TextInputStyle, ComponentType, Locale, } from "discord.js";
13
12
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAA6B,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAYhE,OAAO,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EACnB,8BAA8B,GAC/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAEtD,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,EAC5B,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,yBAAyB,EACzB,6BAA6B,EAC7B,kCAAkC,EAElC,yBAAyB,EACzB,yBAAyB,EACzB,yBAAyB,EACzB,6BAA6B,EAC7B,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,EACtB,IAAI,EACJ,MAAM,EACN,MAAM,EACN,mBAAmB,EACnB,iBAAiB,EACjB,MAAM,EACN,YAAY,EACZ,WAAW,EACX,WAAW,EACX,eAAe,EACf,sBAAsB,EACtB,WAAW,EACX,cAAc,EACd,aAAa,EACb,MAAM,GAmBP,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAA6B,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAYhE,OAAO,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EACnB,8BAA8B,GAC/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC"}
@@ -1,11 +1,42 @@
1
- import { EmbedBuilder, ActionRowBuilder, type RESTPostAPIChannelMessageJSONBody } from "discord.js";
2
- type MessageContent = string | EmbedBuilder | ActionRowBuilder<never> | RESTPostAPIChannelMessageJSONBody | (EmbedBuilder | ActionRowBuilder<never>)[];
1
+ type DiscordBuilder = {
2
+ toJSON(): unknown;
3
+ };
4
+ type APIEmbed = {
5
+ title?: string;
6
+ description?: string;
7
+ color?: number;
8
+ fields?: unknown[];
9
+ [key: string]: unknown;
10
+ };
11
+ type MessageBody = {
12
+ content?: string;
13
+ embeds?: unknown[];
14
+ components?: unknown[];
15
+ message_reference?: {
16
+ message_id: string;
17
+ channel_id: string;
18
+ guild_id?: string;
19
+ };
20
+ };
21
+ type Component = {
22
+ type: number;
23
+ style?: number;
24
+ custom_id?: string;
25
+ label?: string;
26
+ components?: Component[];
27
+ [key: string]: unknown;
28
+ };
29
+ type MessageContent = string | DiscordBuilder | MessageBody | DiscordBuilder[] | APIEmbed | Component | (APIEmbed | Component)[];
3
30
  export declare class MessageHelper {
4
- private rest;
31
+ private token;
32
+ private readonly baseUrl;
5
33
  constructor(token: string);
6
34
  send(channelId: string, content: MessageContent): Promise<unknown>;
7
35
  reply(channelId: string, messageId: string, guildId: string | undefined, content: MessageContent): Promise<unknown>;
8
36
  private normalizeContent;
37
+ private isBuilder;
38
+ private isEmbedJSON;
39
+ private isComponent;
9
40
  }
10
41
  export {};
11
42
  //# sourceMappingURL=message-helper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"message-helper.d.ts","sourceRoot":"","sources":["../../src/utils/message-helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,EACZ,gBAAgB,EAChB,KAAK,iCAAiC,EAEvC,MAAM,YAAY,CAAC;AAEpB,KAAK,cAAc,GACf,MAAM,GACN,YAAY,GACZ,gBAAgB,CAAC,KAAK,CAAC,GACvB,iCAAiC,GACjC,CAAC,YAAY,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;AAa/C,qBAAa,aAAa;IACxB,OAAO,CAAC,IAAI,CAAO;gBAEP,KAAK,EAAE,MAAM;IAInB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAKlE,KAAK,CACT,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,OAAO,CAAC;IAenB,OAAO,CAAC,gBAAgB;CAwCzB"}
1
+ {"version":3,"file":"message-helper.d.ts","sourceRoot":"","sources":["../../src/utils/message-helper.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GAAG;IACpB,MAAM,IAAI,OAAO,CAAC;CACnB,CAAC;AAEF,KAAK,QAAQ,GAAG;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC;IACvB,iBAAiB,CAAC,EAAE;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAaF,KAAK,SAAS,GAAG;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,KAAK,cAAc,GACf,MAAM,GACN,cAAc,GACd,WAAW,GACX,cAAc,EAAE,GAChB,QAAQ,GACR,SAAS,GACT,CAAC,QAAQ,GAAG,SAAS,CAAC,EAAE,CAAC;AAE7B,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;gBAE7C,KAAK,EAAE,MAAM;IAInB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAmBlE,KAAK,CACT,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,OAAO,CAAC;IA2BnB,OAAO,CAAC,gBAAgB;IA0DxB,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,WAAW;CAQpB"}
@@ -1,12 +1,24 @@
1
- import { REST, Routes, EmbedBuilder, ActionRowBuilder, } from "discord.js";
2
1
  export class MessageHelper {
3
- rest;
2
+ token;
3
+ baseUrl = "https://discord.com/api/v10";
4
4
  constructor(token) {
5
- this.rest = new REST().setToken(token);
5
+ this.token = token;
6
6
  }
7
7
  async send(channelId, content) {
8
8
  const body = this.normalizeContent(content);
9
- return this.rest.post(Routes.channelMessages(channelId), { body });
9
+ const url = `${this.baseUrl}/channels/${channelId}/messages`;
10
+ const response = await fetch(url, {
11
+ method: "POST",
12
+ headers: {
13
+ Authorization: `Bot ${this.token}`,
14
+ "Content-Type": "application/json"
15
+ },
16
+ body: JSON.stringify(body)
17
+ });
18
+ if (!response.ok) {
19
+ throw new Error(`Discord API error: ${response.status} ${response.statusText}`);
20
+ }
21
+ return response.json();
10
22
  }
11
23
  async reply(channelId, messageId, guildId, content) {
12
24
  const body = this.normalizeContent(content);
@@ -15,35 +27,62 @@ export class MessageHelper {
15
27
  message_reference: {
16
28
  message_id: messageId,
17
29
  channel_id: channelId,
18
- ...(guildId && { guild_id: guildId }),
19
- },
30
+ ...guildId && { guild_id: guildId }
31
+ }
20
32
  };
21
- return this.rest.post(Routes.channelMessages(channelId), {
22
- body: replyBody,
33
+ const url = `${this.baseUrl}/channels/${channelId}/messages`;
34
+ const response = await fetch(url, {
35
+ method: "POST",
36
+ headers: {
37
+ Authorization: `Bot ${this.token}`,
38
+ "Content-Type": "application/json"
39
+ },
40
+ body: JSON.stringify(replyBody)
23
41
  });
42
+ if (!response.ok) {
43
+ throw new Error(`Discord API error: ${response.status} ${response.statusText}`);
44
+ }
45
+ return response.json();
24
46
  }
25
47
  normalizeContent(content) {
26
48
  if (typeof content === "string") {
27
49
  return { content };
28
50
  }
29
- if (content instanceof EmbedBuilder) {
30
- return { embeds: [content.toJSON()] };
31
- }
32
- if (content instanceof ActionRowBuilder) {
51
+ if (this.isBuilder(content)) {
33
52
  const json = content.toJSON();
53
+ if (this.isEmbedJSON(json)) {
54
+ return { embeds: [json] };
55
+ }
34
56
  return {
35
- components: [json],
57
+ components: [json]
36
58
  };
37
59
  }
60
+ // Handle plain embed object
61
+ if (this.isEmbedJSON(content)) {
62
+ return { embeds: [content] };
63
+ }
64
+ // Handle plain component object
65
+ if (this.isComponent(content)) {
66
+ return { components: [content] };
67
+ }
38
68
  if (Array.isArray(content)) {
39
69
  const embeds = [];
40
70
  const components = [];
41
71
  for (const item of content) {
42
- if (item instanceof EmbedBuilder) {
43
- embeds.push(item.toJSON());
72
+ if (this.isBuilder(item)) {
73
+ const json = item.toJSON();
74
+ if (this.isEmbedJSON(json)) {
75
+ embeds.push(json);
76
+ }
77
+ else {
78
+ components.push(json);
79
+ }
80
+ }
81
+ else if (this.isEmbedJSON(item)) {
82
+ embeds.push(item);
44
83
  }
45
- else if (item instanceof ActionRowBuilder) {
46
- components.push(item.toJSON());
84
+ else if (this.isComponent(item)) {
85
+ components.push(item);
47
86
  }
48
87
  }
49
88
  const result = {};
@@ -55,7 +94,29 @@ export class MessageHelper {
55
94
  }
56
95
  return result;
57
96
  }
97
+ // If we get here, content should be MessageBody
58
98
  return content;
59
99
  }
100
+ isBuilder(value) {
101
+ return (typeof value === "object" &&
102
+ value !== null &&
103
+ "toJSON" in value &&
104
+ typeof value.toJSON === "function");
105
+ }
106
+ isEmbedJSON(json) {
107
+ return (typeof json === "object" &&
108
+ json !== null &&
109
+ !("type" in json && typeof json.type === "number") &&
110
+ ("title" in json ||
111
+ "description" in json ||
112
+ "color" in json ||
113
+ "fields" in json));
114
+ }
115
+ isComponent(value) {
116
+ return (typeof value === "object" &&
117
+ value !== null &&
118
+ "type" in value &&
119
+ typeof value.type === "number");
120
+ }
60
121
  }
61
122
  //# sourceMappingURL=message-helper.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"message-helper.js","sourceRoot":"","sources":["../../src/utils/message-helper.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,YAAY,EACZ,gBAAgB,GAGjB,MAAM,YAAY,CAAC;AAoBpB,MAAM,OAAO,aAAa;IAChB,IAAI,CAAO;IAEnB,YAAY,KAAa;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAiB,EAAE,OAAuB;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,KAAK,CACT,SAAiB,EACjB,SAAiB,EACjB,OAA2B,EAC3B,OAAuB;QAEvB,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAsC;YACnD,GAAG,IAAI;YACP,iBAAiB,EAAE;gBACjB,UAAU,EAAE,SAAS;gBACrB,UAAU,EAAE,SAAS;gBACrB,GAAG,CAAC,OAAO,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;aACtC;SACF,CAAC;QACF,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE;YACvD,IAAI,EAAE,SAAS;SAChB,CAAC,CAAC;IACL,CAAC;IAEO,gBAAgB,CAAC,OAAuB;QAC9C,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,OAAO,EAAE,OAAO,EAAE,CAAC;QACrB,CAAC;QAED,IAAI,OAAO,YAAY,YAAY,EAAE,CAAC;YACpC,OAAO,EAAE,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;QACxC,CAAC;QAED,IAAI,OAAO,YAAY,gBAAgB,EAAE,CAAC;YACxC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YAC9B,OAAO;gBACL,UAAU,EAAE,CAAC,IAAI,CAAC;aACkB,CAAC;QACzC,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAe,EAAE,CAAC;YAC9B,MAAM,UAAU,GAAc,EAAE,CAAC;YAEjC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;gBAC3B,IAAI,IAAI,YAAY,YAAY,EAAE,CAAC;oBACjC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;gBAC7B,CAAC;qBAAM,IAAI,IAAI,YAAY,gBAAgB,EAAE,CAAC;oBAC5C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAA0B,EAAE,CAAC;YACzC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;YACzB,CAAC;YACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;YACjC,CAAC;YACD,OAAO,MAA2C,CAAC;QACrD,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
1
+ {"version":3,"file":"message-helper.js","sourceRoot":"","sources":["../../src/utils/message-helper.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,29 +1,11 @@
1
1
  {
2
2
  "name": "flarecord",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "discord gateway client for cloudflare workers. built with typescript and optimized for durable objects.",
5
5
  "type": "module",
6
- "main": "./src/index.ts",
7
- "types": "./src/index.ts",
8
- "source": "./src/index.ts",
9
- "exports": {
10
- ".": {
11
- "source": "./src/index.ts",
12
- "types": "./src/index.ts",
13
- "import": "./src/index.ts",
14
- "default": "./src/index.ts"
15
- },
16
- "./src": {
17
- "source": "./src/index.ts",
18
- "types": "./src/index.ts",
19
- "import": "./src/index.ts"
20
- },
21
- "./src/*": {
22
- "source": "./src/*.ts",
23
- "types": "./src/*.ts",
24
- "import": "./src/*.ts"
25
- }
26
- },
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "source": "./dist/index.js",
27
9
  "files": [
28
10
  "dist",
29
11
  "src"
@@ -55,7 +37,6 @@
55
37
  "typescript": "^5.5.2"
56
38
  },
57
39
  "dependencies": {
58
- "discord-api-types": "^0.38.37",
59
- "discord.js": "^14.25.1"
40
+ "discord-api-types": "^0.38.37"
60
41
  }
61
42
  }
package/src/index.ts CHANGED
@@ -34,63 +34,3 @@ export {
34
34
  } from "./types/constants";
35
35
  export { DEFAULT_IDENTIFY_PROPERTIES } from "./types";
36
36
 
37
- export {
38
- EmbedBuilder,
39
- ActionRowBuilder,
40
- ButtonBuilder,
41
- StringSelectMenuBuilder,
42
- UserSelectMenuBuilder,
43
- RoleSelectMenuBuilder,
44
- ChannelSelectMenuBuilder,
45
- MentionableSelectMenuBuilder,
46
- ModalBuilder,
47
- TextInputBuilder,
48
- AttachmentBuilder,
49
- SlashCommandBuilder,
50
- ContextMenuCommandBuilder,
51
- SlashCommandSubcommandBuilder,
52
- SlashCommandSubcommandGroupBuilder,
53
- SlashCommandOptionsOnlyBuilder,
54
- SlashCommandBooleanOption,
55
- SlashCommandChannelOption,
56
- SlashCommandIntegerOption,
57
- SlashCommandMentionableOption,
58
- SlashCommandNumberOption,
59
- SlashCommandRoleOption,
60
- SlashCommandStringOption,
61
- SlashCommandUserOption,
62
- REST,
63
- Routes,
64
- Colors,
65
- PermissionFlagsBits,
66
- GatewayIntentBits,
67
- Events,
68
- ActivityType,
69
- ChannelType,
70
- MessageType,
71
- InteractionType,
72
- ApplicationCommandType,
73
- ButtonStyle,
74
- TextInputStyle,
75
- ComponentType,
76
- Locale,
77
- type APIEmbed,
78
- type APIEmbedField,
79
- type APIButtonComponent,
80
- type APIActionRowComponent,
81
- type APIMessageComponent,
82
- type RESTPostAPIChannelMessageJSONBody,
83
- type RESTPostAPIChannelMessageResult,
84
- type APIInteractionResponse,
85
- type APIMessage,
86
- type APIUser,
87
- type APIGuild,
88
- type APIChannel,
89
- type APIInteraction,
90
- type APIChatInputApplicationCommandInteraction,
91
- type APIMessageApplicationCommandInteraction,
92
- type APIUserApplicationCommandInteraction,
93
- type APIMessageComponentInteraction,
94
- type APIModalSubmitInteraction,
95
- } from "discord.js";
96
-
@@ -1,20 +1,27 @@
1
- import {
2
- REST,
3
- Routes,
4
- EmbedBuilder,
5
- ActionRowBuilder,
6
- type RESTPostAPIChannelMessageJSONBody,
7
- type APIEmbed,
8
- } from "discord.js";
1
+ type DiscordBuilder = {
2
+ toJSON(): unknown;
3
+ };
9
4
 
10
- type MessageContent =
11
- | string
12
- | EmbedBuilder
13
- | ActionRowBuilder<never>
14
- | RESTPostAPIChannelMessageJSONBody
15
- | (EmbedBuilder | ActionRowBuilder<never>)[];
5
+ type APIEmbed = {
6
+ title?: string;
7
+ description?: string;
8
+ color?: number;
9
+ fields?: unknown[];
10
+ [key: string]: unknown;
11
+ };
12
+
13
+ type MessageBody = {
14
+ content?: string;
15
+ embeds?: unknown[];
16
+ components?: unknown[];
17
+ message_reference?: {
18
+ message_id: string;
19
+ channel_id: string;
20
+ guild_id?: string;
21
+ };
22
+ };
16
23
 
17
- interface NormalizedMessageBody {
24
+ type NormalizedMessageBody = {
18
25
  content?: string;
19
26
  embeds?: APIEmbed[];
20
27
  components?: unknown[];
@@ -23,18 +30,51 @@ interface NormalizedMessageBody {
23
30
  channel_id: string;
24
31
  guild_id?: string;
25
32
  };
26
- }
33
+ };
34
+
35
+ type Component = {
36
+ type: number;
37
+ style?: number;
38
+ custom_id?: string;
39
+ label?: string;
40
+ components?: Component[];
41
+ [key: string]: unknown;
42
+ };
43
+
44
+ type MessageContent =
45
+ | string
46
+ | DiscordBuilder
47
+ | MessageBody
48
+ | DiscordBuilder[]
49
+ | APIEmbed
50
+ | Component
51
+ | (APIEmbed | Component)[];
27
52
 
28
53
  export class MessageHelper {
29
- private rest: REST;
54
+ private token: string;
55
+ private readonly baseUrl = "https://discord.com/api/v10";
30
56
 
31
57
  constructor(token: string) {
32
- this.rest = new REST().setToken(token);
58
+ this.token = token;
33
59
  }
34
60
 
35
61
  async send(channelId: string, content: MessageContent): Promise<unknown> {
36
62
  const body = this.normalizeContent(content);
37
- return this.rest.post(Routes.channelMessages(channelId), { body });
63
+ const url = `${this.baseUrl}/channels/${channelId}/messages`;
64
+ const response = await fetch(url, {
65
+ method: "POST",
66
+ headers: {
67
+ Authorization: `Bot ${this.token}`,
68
+ "Content-Type": "application/json"
69
+ },
70
+ body: JSON.stringify(body)
71
+ });
72
+ if (!response.ok) {
73
+ throw new Error(
74
+ `Discord API error: ${response.status} ${response.statusText}`
75
+ );
76
+ }
77
+ return response.json();
38
78
  }
39
79
 
40
80
  async reply(
@@ -44,33 +84,52 @@ export class MessageHelper {
44
84
  content: MessageContent
45
85
  ): Promise<unknown> {
46
86
  const body = this.normalizeContent(content);
47
- const replyBody: RESTPostAPIChannelMessageJSONBody = {
87
+ const replyBody: MessageBody = {
48
88
  ...body,
49
89
  message_reference: {
50
90
  message_id: messageId,
51
91
  channel_id: channelId,
52
- ...(guildId && { guild_id: guildId }),
53
- },
92
+ ...guildId && { guild_id: guildId }
93
+ }
54
94
  };
55
- return this.rest.post(Routes.channelMessages(channelId), {
56
- body: replyBody,
95
+ const url = `${this.baseUrl}/channels/${channelId}/messages`;
96
+ const response = await fetch(url, {
97
+ method: "POST",
98
+ headers: {
99
+ Authorization: `Bot ${this.token}`,
100
+ "Content-Type": "application/json"
101
+ },
102
+ body: JSON.stringify(replyBody)
57
103
  });
104
+ if (!response.ok) {
105
+ throw new Error(
106
+ `Discord API error: ${response.status} ${response.statusText}`
107
+ );
108
+ }
109
+ return response.json();
58
110
  }
59
111
 
60
- private normalizeContent(content: MessageContent): RESTPostAPIChannelMessageJSONBody {
112
+ private normalizeContent(content: MessageContent): MessageBody {
61
113
  if (typeof content === "string") {
62
114
  return { content };
63
115
  }
64
116
 
65
- if (content instanceof EmbedBuilder) {
66
- return { embeds: [content.toJSON()] };
67
- }
68
-
69
- if (content instanceof ActionRowBuilder) {
117
+ if (this.isBuilder(content)) {
70
118
  const json = content.toJSON();
119
+ if (this.isEmbedJSON(json)) {
120
+ return { embeds: [json] };
121
+ }
71
122
  return {
72
- components: [json],
73
- } as RESTPostAPIChannelMessageJSONBody;
123
+ components: [json]
124
+ };
125
+ }
126
+
127
+ if (this.isEmbedJSON(content)) {
128
+ return { embeds: [content as APIEmbed] };
129
+ }
130
+
131
+ if (this.isComponent(content)) {
132
+ return { components: [content] };
74
133
  }
75
134
 
76
135
  if (Array.isArray(content)) {
@@ -78,10 +137,17 @@ export class MessageHelper {
78
137
  const components: unknown[] = [];
79
138
 
80
139
  for (const item of content) {
81
- if (item instanceof EmbedBuilder) {
82
- embeds.push(item.toJSON());
83
- } else if (item instanceof ActionRowBuilder) {
84
- components.push(item.toJSON());
140
+ if (this.isBuilder(item)) {
141
+ const json = item.toJSON();
142
+ if (this.isEmbedJSON(json)) {
143
+ embeds.push(json as APIEmbed);
144
+ } else {
145
+ components.push(json);
146
+ }
147
+ } else if (this.isEmbedJSON(item)) {
148
+ embeds.push(item as APIEmbed);
149
+ } else if (this.isComponent(item)) {
150
+ components.push(item);
85
151
  }
86
152
  }
87
153
 
@@ -92,9 +158,42 @@ export class MessageHelper {
92
158
  if (components.length > 0) {
93
159
  result.components = components;
94
160
  }
95
- return result as RESTPostAPIChannelMessageJSONBody;
161
+ return result;
96
162
  }
97
163
 
98
- return content;
164
+ // If we get here, content should be MessageBody
165
+ return content as MessageBody;
166
+ }
167
+
168
+ private isBuilder(value: unknown): value is DiscordBuilder {
169
+ return (
170
+ typeof value === "object" &&
171
+ value !== null &&
172
+ "toJSON" in value &&
173
+ typeof (value as { toJSON: unknown }).toJSON === "function"
174
+ );
175
+ }
176
+
177
+ private isEmbedJSON(json: unknown): boolean {
178
+ return (
179
+ typeof json === "object" &&
180
+ json !== null &&
181
+ !(
182
+ "type" in json && typeof (json as { type: unknown }).type === "number"
183
+ ) &&
184
+ ("title" in json ||
185
+ "description" in json ||
186
+ "color" in json ||
187
+ "fields" in json)
188
+ );
189
+ }
190
+
191
+ private isComponent(value: unknown): value is Component {
192
+ return (
193
+ typeof value === "object" &&
194
+ value !== null &&
195
+ "type" in value &&
196
+ typeof (value as { type: unknown }).type === "number"
197
+ );
99
198
  }
100
199
  }