@magicyan/discord 1.4.10 → 1.5.0

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.
Files changed (52) hide show
  1. package/dist/functions/components/buttons.cjs +10 -1
  2. package/dist/functions/components/buttons.mjs +10 -1
  3. package/dist/functions/components/components.cjs +3 -6
  4. package/dist/functions/components/components.mjs +3 -6
  5. package/dist/functions/components/container.cjs +71 -66
  6. package/dist/functions/components/container.mjs +72 -68
  7. package/dist/functions/components/file.cjs +3 -5
  8. package/dist/functions/components/file.mjs +4 -6
  9. package/dist/functions/components/gallery.cjs +4 -7
  10. package/dist/functions/components/gallery.mjs +4 -7
  11. package/dist/functions/embeds/assets.cjs +4 -4
  12. package/dist/functions/embeds/assets.mjs +4 -4
  13. package/dist/functions/message.cjs +16 -6
  14. package/dist/functions/message.mjs +15 -6
  15. package/dist/functions/modals.cjs +8 -0
  16. package/dist/functions/modals.mjs +9 -2
  17. package/dist/guards/attachment.cjs +7 -1
  18. package/dist/guards/attachment.mjs +7 -1
  19. package/dist/guards/components/button.cjs +10 -0
  20. package/dist/guards/components/button.mjs +8 -0
  21. package/dist/guards/components/container.cjs +10 -0
  22. package/dist/guards/components/container.mjs +8 -0
  23. package/dist/guards/components/gallery.cjs +14 -0
  24. package/dist/guards/components/gallery.mjs +11 -0
  25. package/dist/guards/components/modal.cjs +10 -0
  26. package/dist/guards/components/modal.mjs +8 -0
  27. package/dist/guards/components/row.cjs +18 -0
  28. package/dist/guards/components/row.mjs +16 -0
  29. package/dist/guards/components/section.cjs +10 -0
  30. package/dist/guards/components/section.mjs +8 -0
  31. package/dist/guards/components/selectmenu.cjs +30 -0
  32. package/dist/guards/components/selectmenu.mjs +23 -0
  33. package/dist/guards/components/separator.cjs +10 -0
  34. package/dist/guards/components/separator.mjs +8 -0
  35. package/dist/guards/components/textdisplay.cjs +10 -0
  36. package/dist/guards/components/textdisplay.mjs +8 -0
  37. package/dist/guards/components/textinput.cjs +10 -0
  38. package/dist/guards/components/textinput.mjs +8 -0
  39. package/dist/guards/message.cjs +17 -0
  40. package/dist/guards/message.mjs +15 -0
  41. package/dist/guards/utils.cjs +9 -0
  42. package/dist/guards/utils.mjs +7 -0
  43. package/dist/index.cjs +72 -45
  44. package/dist/index.d.cts +817 -474
  45. package/dist/index.d.mts +817 -474
  46. package/dist/index.d.ts +817 -474
  47. package/dist/index.mjs +29 -20
  48. package/package.json +1 -1
  49. package/dist/guards/button.cjs +0 -9
  50. package/dist/guards/button.mjs +0 -7
  51. package/dist/guards/selectmenu.cjs +0 -9
  52. package/dist/guards/selectmenu.mjs +0 -7
@@ -3,7 +3,16 @@
3
3
  const discord_js = require('discord.js');
4
4
  const row = require('./row.cjs');
5
5
 
6
- function createLinkButton(data) {
6
+ function createLinkButton(data, label, emoji) {
7
+ if (typeof data === "string") {
8
+ label ?? (label = data);
9
+ return new discord_js.ButtonBuilder({
10
+ style: discord_js.ButtonStyle.Link,
11
+ label,
12
+ url: data,
13
+ emoji
14
+ });
15
+ }
7
16
  data.label ?? (data.label = data.url);
8
17
  return new discord_js.ButtonBuilder({ style: discord_js.ButtonStyle.Link, ...data });
9
18
  }
@@ -1,7 +1,16 @@
1
1
  import { ButtonBuilder, ButtonStyle } from 'discord.js';
2
2
  import { createRow } from './row.mjs';
3
3
 
4
- function createLinkButton(data) {
4
+ function createLinkButton(data, label, emoji) {
5
+ if (typeof data === "string") {
6
+ label ?? (label = data);
7
+ return new ButtonBuilder({
8
+ style: ButtonStyle.Link,
9
+ label,
10
+ url: data,
11
+ emoji
12
+ });
13
+ }
5
14
  data.label ?? (data.label = data.url);
6
15
  return new ButtonBuilder({ style: ButtonStyle.Link, ...data });
7
16
  }
@@ -1,21 +1,18 @@
1
1
  'use strict';
2
2
 
3
+ const core = require('@magicyan/core');
3
4
  const attachment = require('../../guards/attachment.cjs');
4
- const button = require('../../guards/button.cjs');
5
- const selectmenu = require('../../guards/selectmenu.cjs');
5
+ const button = require('../../guards/components/button.cjs');
6
+ const selectmenu = require('../../guards/components/selectmenu.cjs');
6
7
  const gallery = require('./gallery.cjs');
7
8
  const row = require('./row.cjs');
8
9
  const text = require('./text.cjs');
9
- const core = require('@magicyan/core');
10
10
 
11
11
  function createComponents(...data) {
12
12
  return data.flat().filter((value) => core.isDefined(value)).filter((value) => typeof value !== "boolean").map((component) => {
13
13
  if (typeof component === "string") {
14
14
  return text.createTextDisplay(component);
15
15
  }
16
- if (Array.isArray(component)) {
17
- return row.createRow(...component);
18
- }
19
16
  if (selectmenu.isAnySelectMenuBuilder(component)) {
20
17
  return row.createRow(component);
21
18
  }
@@ -1,19 +1,16 @@
1
+ import { isDefined } from '@magicyan/core';
1
2
  import { isAttachment } from '../../guards/attachment.mjs';
2
- import { isButtonBuilder } from '../../guards/button.mjs';
3
- import { isAnySelectMenuBuilder } from '../../guards/selectmenu.mjs';
3
+ import { isButtonBuilder } from '../../guards/components/button.mjs';
4
+ import { isAnySelectMenuBuilder } from '../../guards/components/selectmenu.mjs';
4
5
  import { createMediaGallery } from './gallery.mjs';
5
6
  import { createRow } from './row.mjs';
6
7
  import { createTextDisplay } from './text.mjs';
7
- import { isDefined } from '@magicyan/core';
8
8
 
9
9
  function createComponents(...data) {
10
10
  return data.flat().filter((value) => isDefined(value)).filter((value) => typeof value !== "boolean").map((component) => {
11
11
  if (typeof component === "string") {
12
12
  return createTextDisplay(component);
13
13
  }
14
- if (Array.isArray(component)) {
15
- return createRow(...component);
16
- }
17
14
  if (isAnySelectMenuBuilder(component)) {
18
15
  return createRow(component);
19
16
  }
@@ -1,79 +1,84 @@
1
1
  'use strict';
2
2
 
3
+ const core = require('@magicyan/core');
3
4
  const discord_js = require('discord.js');
4
- const attachment = require('../../guards/attachment.cjs');
5
- const selectmenu = require('../../guards/selectmenu.cjs');
6
- const gallery = require('./gallery.cjs');
7
- const row = require('./row.cjs');
8
- const text = require('./text.cjs');
5
+ const components = require('./components.cjs');
6
+ const message = require('../../guards/message.cjs');
9
7
 
10
- function createContainer(data, ...items) {
11
- const container = new discord_js.ContainerBuilder();
12
- const addComponent = (component) => {
13
- if (!component)
14
- return;
15
- if (typeof component === "string") {
16
- container.addTextDisplayComponents(
17
- text.createTextDisplay(component)
18
- );
19
- }
20
- if (component instanceof discord_js.TextDisplayBuilder) {
21
- container.addTextDisplayComponents(
22
- component
23
- );
24
- }
25
- if (component instanceof discord_js.ActionRowBuilder) {
26
- container.addActionRowComponents(component);
27
- }
28
- if (Array.isArray(component)) {
29
- container.addActionRowComponents(
30
- row.createRow(...component)
8
+ class ContainerPlusBuilder extends discord_js.ContainerBuilder {
9
+ constructor(data) {
10
+ const constructorData = core.isDefined(data?.from) ? message.isMessage(data.from) ? data.from.components.filter((v) => v.type === discord_js.ComponentType.Container).at(data.fromIndex ?? 0)?.toJSON() ?? {} : data.from.toJSON() : {};
11
+ if (core.isDefined(data?.accentColor)) {
12
+ constructorData.accent_color = discord_js.resolveColor(
13
+ data.accentColor
31
14
  );
32
15
  }
33
- if (selectmenu.isAnySelectMenuBuilder(component) || component instanceof discord_js.ButtonBuilder) {
34
- container.addActionRowComponents(
35
- row.createRow(component)
16
+ super(constructorData);
17
+ if (core.isDefined(data?.components) && data.components.length >= 1) {
18
+ this.spliceComponents(
19
+ 0,
20
+ 0,
21
+ ...components.createComponents(data.components)
36
22
  );
37
23
  }
38
- if (component instanceof discord_js.SectionBuilder) {
39
- container.addSectionComponents(component);
40
- }
41
- if (component instanceof discord_js.FileBuilder) {
42
- container.addFileComponents(component);
43
- }
44
- if (component instanceof discord_js.MediaGalleryBuilder) {
45
- container.addMediaGalleryComponents(component);
46
- }
47
- if (attachment.isAttachment(component)) {
48
- container.addMediaGalleryComponents(
49
- gallery.createMediaGallery(component)
50
- );
51
- }
52
- if (component instanceof discord_js.SeparatorBuilder) {
53
- container.addSeparatorComponents(component);
54
- }
55
- };
56
- const setColor = (color) => {
57
- container.setAccentColor(
58
- discord_js.resolveColor(color)
59
- );
60
- };
61
- const isContainerData = (value) => typeof value === "object" && "components" in value && Array.isArray(value.components);
24
+ }
25
+ /**
26
+ * Sets the accent color of the container.
27
+ *
28
+ * If a color is provided, it resolves and sets the accent color accordingly.
29
+ * If no color or `null` is provided, it clears the accent color.
30
+ *
31
+ * @param color - The color to set as the accent color, or `null` to clear it.
32
+ * @returns The current instance for chaining.
33
+ *
34
+ * @example
35
+ * container.setColor("#ff0000"); // Sets the accent color to red.
36
+ * container.setColor(null); // Clears the accent color.
37
+ */
38
+ setColor(color) {
39
+ return core.isDefined(color) ? this.setAccentColor(discord_js.resolveColor(color)) : this.setAccentColor();
40
+ }
41
+ /**
42
+ * Replaces or removes a component at the specified index in the container.
43
+ *
44
+ * If `data` is provided, it replaces the component at the given index with the new component(s).
45
+ * If `null` is provided, it removes the component at that index.
46
+ *
47
+ * @param index - The index of the component to replace or remove.
48
+ * @param data - The new component data to set, or `null` to remove the component.
49
+ * @returns The current instance for chaining.
50
+ *
51
+ * @example
52
+ * container.setComponent(0, new ButtonBuilder({ label: "Click" }));
53
+ * container.setComponent(1, null); // Removes the component at index 1.
54
+ */
55
+ setComponent(index, data) {
56
+ const args = [index, 1];
57
+ if (core.isDefined(data))
58
+ args.push(...components.createComponents(data));
59
+ return this.spliceComponents(...args);
60
+ }
61
+ componentAt(index, type) {
62
+ return core.isDefined(type) ? this.components.filter((builder) => builder.data.type === type).at(index) : this.components.at(index);
63
+ }
64
+ }
65
+ function createContainer(data, ...items) {
66
+ const isContainerData = (value) => typeof value === "object" && core.isDefined(value) && !Array.isArray(value);
62
67
  if (isContainerData(data)) {
63
- if (data.accentColor)
64
- setColor(data.accentColor);
65
- if (data.spoiler !== void 0)
66
- container.setSpoiler(data.spoiler);
67
- if (data.id !== void 0)
68
- container.setId(data.id);
69
- for (const component of data.components)
70
- addComponent(component);
71
- return container;
68
+ const { array, from } = data;
69
+ if (array) {
70
+ if (message.isMessage(from)) {
71
+ return from.components.filter((c) => c.type === discord_js.ComponentType.Container).map((component) => new ContainerPlusBuilder({ from: component }));
72
+ }
73
+ return [new ContainerPlusBuilder(data)];
74
+ }
75
+ return new ContainerPlusBuilder(data);
72
76
  }
73
- setColor(data);
74
- for (const component of items.flat())
75
- addComponent(component);
76
- return container;
77
+ return new ContainerPlusBuilder({
78
+ accentColor: data,
79
+ components: items.flat()
80
+ });
77
81
  }
78
82
 
83
+ exports.ContainerPlusBuilder = ContainerPlusBuilder;
79
84
  exports.createContainer = createContainer;
@@ -1,77 +1,81 @@
1
- import { ContainerBuilder, TextDisplayBuilder, ActionRowBuilder, ButtonBuilder, SectionBuilder, FileBuilder, MediaGalleryBuilder, SeparatorBuilder, resolveColor } from 'discord.js';
2
- import { isAttachment } from '../../guards/attachment.mjs';
3
- import { isAnySelectMenuBuilder } from '../../guards/selectmenu.mjs';
4
- import { createMediaGallery } from './gallery.mjs';
5
- import { createRow } from './row.mjs';
6
- import { createTextDisplay } from './text.mjs';
1
+ import { isDefined } from '@magicyan/core';
2
+ import { ContainerBuilder, ComponentType, resolveColor } from 'discord.js';
3
+ import { createComponents } from './components.mjs';
4
+ import { isMessage } from '../../guards/message.mjs';
7
5
 
8
- function createContainer(data, ...items) {
9
- const container = new ContainerBuilder();
10
- const addComponent = (component) => {
11
- if (!component)
12
- return;
13
- if (typeof component === "string") {
14
- container.addTextDisplayComponents(
15
- createTextDisplay(component)
16
- );
17
- }
18
- if (component instanceof TextDisplayBuilder) {
19
- container.addTextDisplayComponents(
20
- component
21
- );
22
- }
23
- if (component instanceof ActionRowBuilder) {
24
- container.addActionRowComponents(component);
25
- }
26
- if (Array.isArray(component)) {
27
- container.addActionRowComponents(
28
- createRow(...component)
6
+ class ContainerPlusBuilder extends ContainerBuilder {
7
+ constructor(data) {
8
+ const constructorData = isDefined(data?.from) ? isMessage(data.from) ? data.from.components.filter((v) => v.type === ComponentType.Container).at(data.fromIndex ?? 0)?.toJSON() ?? {} : data.from.toJSON() : {};
9
+ if (isDefined(data?.accentColor)) {
10
+ constructorData.accent_color = resolveColor(
11
+ data.accentColor
29
12
  );
30
13
  }
31
- if (isAnySelectMenuBuilder(component) || component instanceof ButtonBuilder) {
32
- container.addActionRowComponents(
33
- createRow(component)
14
+ super(constructorData);
15
+ if (isDefined(data?.components) && data.components.length >= 1) {
16
+ this.spliceComponents(
17
+ 0,
18
+ 0,
19
+ ...createComponents(data.components)
34
20
  );
35
21
  }
36
- if (component instanceof SectionBuilder) {
37
- container.addSectionComponents(component);
38
- }
39
- if (component instanceof FileBuilder) {
40
- container.addFileComponents(component);
41
- }
42
- if (component instanceof MediaGalleryBuilder) {
43
- container.addMediaGalleryComponents(component);
44
- }
45
- if (isAttachment(component)) {
46
- container.addMediaGalleryComponents(
47
- createMediaGallery(component)
48
- );
49
- }
50
- if (component instanceof SeparatorBuilder) {
51
- container.addSeparatorComponents(component);
52
- }
53
- };
54
- const setColor = (color) => {
55
- container.setAccentColor(
56
- resolveColor(color)
57
- );
58
- };
59
- const isContainerData = (value) => typeof value === "object" && "components" in value && Array.isArray(value.components);
22
+ }
23
+ /**
24
+ * Sets the accent color of the container.
25
+ *
26
+ * If a color is provided, it resolves and sets the accent color accordingly.
27
+ * If no color or `null` is provided, it clears the accent color.
28
+ *
29
+ * @param color - The color to set as the accent color, or `null` to clear it.
30
+ * @returns The current instance for chaining.
31
+ *
32
+ * @example
33
+ * container.setColor("#ff0000"); // Sets the accent color to red.
34
+ * container.setColor(null); // Clears the accent color.
35
+ */
36
+ setColor(color) {
37
+ return isDefined(color) ? this.setAccentColor(resolveColor(color)) : this.setAccentColor();
38
+ }
39
+ /**
40
+ * Replaces or removes a component at the specified index in the container.
41
+ *
42
+ * If `data` is provided, it replaces the component at the given index with the new component(s).
43
+ * If `null` is provided, it removes the component at that index.
44
+ *
45
+ * @param index - The index of the component to replace or remove.
46
+ * @param data - The new component data to set, or `null` to remove the component.
47
+ * @returns The current instance for chaining.
48
+ *
49
+ * @example
50
+ * container.setComponent(0, new ButtonBuilder({ label: "Click" }));
51
+ * container.setComponent(1, null); // Removes the component at index 1.
52
+ */
53
+ setComponent(index, data) {
54
+ const args = [index, 1];
55
+ if (isDefined(data))
56
+ args.push(...createComponents(data));
57
+ return this.spliceComponents(...args);
58
+ }
59
+ componentAt(index, type) {
60
+ return isDefined(type) ? this.components.filter((builder) => builder.data.type === type).at(index) : this.components.at(index);
61
+ }
62
+ }
63
+ function createContainer(data, ...items) {
64
+ const isContainerData = (value) => typeof value === "object" && isDefined(value) && !Array.isArray(value);
60
65
  if (isContainerData(data)) {
61
- if (data.accentColor)
62
- setColor(data.accentColor);
63
- if (data.spoiler !== void 0)
64
- container.setSpoiler(data.spoiler);
65
- if (data.id !== void 0)
66
- container.setId(data.id);
67
- for (const component of data.components)
68
- addComponent(component);
69
- return container;
66
+ const { array, from } = data;
67
+ if (array) {
68
+ if (isMessage(from)) {
69
+ return from.components.filter((c) => c.type === ComponentType.Container).map((component) => new ContainerPlusBuilder({ from: component }));
70
+ }
71
+ return [new ContainerPlusBuilder(data)];
72
+ }
73
+ return new ContainerPlusBuilder(data);
70
74
  }
71
- setColor(data);
72
- for (const component of items.flat())
73
- addComponent(component);
74
- return container;
75
+ return new ContainerPlusBuilder({
76
+ accentColor: data,
77
+ components: items.flat()
78
+ });
75
79
  }
76
80
 
77
- export { createContainer };
81
+ export { ContainerPlusBuilder, createContainer };
@@ -1,16 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  const discord_js = require('discord.js');
4
+ const attachment = require('../../guards/attachment.cjs');
4
5
 
5
6
  function createFile(source, options = {}) {
6
7
  const prefix = "attachment://";
7
- const url = source instanceof discord_js.AttachmentBuilder || source instanceof discord_js.Attachment ? `${prefix}${source.name}` : source;
8
+ const url = attachment.isAttachment(source) ? `${prefix}${source.name}` : source;
8
9
  return new discord_js.FileBuilder({
9
10
  spoiler: options.spoiler,
10
- file: {
11
- ...options,
12
- url
13
- }
11
+ file: { ...options, url }
14
12
  });
15
13
  }
16
14
 
@@ -1,14 +1,12 @@
1
- import { AttachmentBuilder, Attachment, FileBuilder } from 'discord.js';
1
+ import { FileBuilder } from 'discord.js';
2
+ import { isAttachment } from '../../guards/attachment.mjs';
2
3
 
3
4
  function createFile(source, options = {}) {
4
5
  const prefix = "attachment://";
5
- const url = source instanceof AttachmentBuilder || source instanceof Attachment ? `${prefix}${source.name}` : source;
6
+ const url = isAttachment(source) ? `${prefix}${source.name}` : source;
6
7
  return new FileBuilder({
7
8
  spoiler: options.spoiler,
8
- file: {
9
- ...options,
10
- url
11
- }
9
+ file: { ...options, url }
12
10
  });
13
11
  }
14
12
 
@@ -2,20 +2,17 @@
2
2
 
3
3
  const discord_js = require('discord.js');
4
4
  const attachment = require('../../guards/attachment.cjs');
5
+ const core = require('@magicyan/core');
5
6
 
6
7
  function createMediaGallery(...items) {
7
8
  const gallery = new discord_js.MediaGalleryBuilder();
8
- for (const item of items) {
9
+ for (const item of items.flat().filter(core.isDefined)) {
9
10
  if (typeof item === "string") {
10
- gallery.addItems({
11
- media: { url: item }
12
- });
11
+ gallery.addItems({ media: { url: item } });
13
12
  continue;
14
13
  }
15
14
  if (attachment.isAttachment(item)) {
16
- gallery.addItems({
17
- media: { url: `attachment://${item.name}` }
18
- });
15
+ gallery.addItems({ media: { url: `attachment://${item.name}` } });
19
16
  continue;
20
17
  }
21
18
  gallery.addItems(item);
@@ -1,19 +1,16 @@
1
1
  import { MediaGalleryBuilder } from 'discord.js';
2
2
  import { isAttachment } from '../../guards/attachment.mjs';
3
+ import { isDefined } from '@magicyan/core';
3
4
 
4
5
  function createMediaGallery(...items) {
5
6
  const gallery = new MediaGalleryBuilder();
6
- for (const item of items) {
7
+ for (const item of items.flat().filter(isDefined)) {
7
8
  if (typeof item === "string") {
8
- gallery.addItems({
9
- media: { url: item }
10
- });
9
+ gallery.addItems({ media: { url: item } });
11
10
  continue;
12
11
  }
13
12
  if (isAttachment(item)) {
14
- gallery.addItems({
15
- media: { url: `attachment://${item.name}` }
16
- });
13
+ gallery.addItems({ media: { url: `attachment://${item.name}` } });
17
14
  continue;
18
15
  }
19
16
  gallery.addItems(item);
@@ -1,15 +1,15 @@
1
1
  'use strict';
2
2
 
3
- const discord_js = require('discord.js');
3
+ const attachment = require('../../guards/attachment.cjs');
4
4
 
5
5
  function createEmbedAsset(source, options = {}) {
6
- if (source instanceof discord_js.Attachment || source instanceof discord_js.AttachmentBuilder) {
6
+ if (attachment.isAttachment(source)) {
7
7
  return { url: `attachment://${source.name}`, ...options };
8
8
  }
9
9
  if (source && typeof source === "object" && "url" in source) {
10
- return Object.assign(source, options);
10
+ return { ...source, ...options };
11
11
  }
12
- return source ? Object.assign({ url: source }, options) : void 0;
12
+ return source ? { url: source, ...options } : void 0;
13
13
  }
14
14
 
15
15
  exports.createEmbedAsset = createEmbedAsset;
@@ -1,13 +1,13 @@
1
- import { Attachment, AttachmentBuilder } from 'discord.js';
1
+ import { isAttachment } from '../../guards/attachment.mjs';
2
2
 
3
3
  function createEmbedAsset(source, options = {}) {
4
- if (source instanceof Attachment || source instanceof AttachmentBuilder) {
4
+ if (isAttachment(source)) {
5
5
  return { url: `attachment://${source.name}`, ...options };
6
6
  }
7
7
  if (source && typeof source === "object" && "url" in source) {
8
- return Object.assign(source, options);
8
+ return { ...source, ...options };
9
9
  }
10
- return source ? Object.assign({ url: source }, options) : void 0;
10
+ return source ? { url: source, ...options } : void 0;
11
11
  }
12
12
 
13
13
  export { createEmbedAsset };
@@ -40,13 +40,23 @@ function findMessage(channel) {
40
40
  }
41
41
  };
42
42
  }
43
- function getMessageUrlInfo(url) {
44
- const regex = new RegExp(/^https:\/\/discord\.com\/channels\/\d+\/\d+\/\d+$/);
45
- if (!regex.test(url))
43
+ function getMessageURLInfo(url) {
44
+ const match = url.match(/^https:\/\/discord\.com\/channels\/(\d+)\/(\d+)\/(\d+)$/);
45
+ if (!match)
46
46
  return {};
47
- const [messageId, channelId, guildId] = url.split("/").reverse();
48
- return { messageId, channelId, guildId };
47
+ const [_, guildId, channelId, messageId] = match;
48
+ return { guildId, channelId, messageId };
49
+ }
50
+ async function fetchMessageFromURL(gc, url) {
51
+ const { messageId, channelId } = getMessageURLInfo(url);
52
+ if (!messageId)
53
+ return null;
54
+ const channel = await gc.channels.fetch(channelId).catch(() => null);
55
+ if (!channel || !("messages" in channel))
56
+ return null;
57
+ return channel.messages.fetch(messageId).catch(() => null);
49
58
  }
50
59
 
60
+ exports.fetchMessageFromURL = fetchMessageFromURL;
51
61
  exports.findMessage = findMessage;
52
- exports.getMessageUrlInfo = getMessageUrlInfo;
62
+ exports.getMessageURLInfo = getMessageURLInfo;
@@ -38,12 +38,21 @@ function findMessage(channel) {
38
38
  }
39
39
  };
40
40
  }
41
- function getMessageUrlInfo(url) {
42
- const regex = new RegExp(/^https:\/\/discord\.com\/channels\/\d+\/\d+\/\d+$/);
43
- if (!regex.test(url))
41
+ function getMessageURLInfo(url) {
42
+ const match = url.match(/^https:\/\/discord\.com\/channels\/(\d+)\/(\d+)\/(\d+)$/);
43
+ if (!match)
44
44
  return {};
45
- const [messageId, channelId, guildId] = url.split("/").reverse();
46
- return { messageId, channelId, guildId };
45
+ const [_, guildId, channelId, messageId] = match;
46
+ return { guildId, channelId, messageId };
47
+ }
48
+ async function fetchMessageFromURL(gc, url) {
49
+ const { messageId, channelId } = getMessageURLInfo(url);
50
+ if (!messageId)
51
+ return null;
52
+ const channel = await gc.channels.fetch(channelId).catch(() => null);
53
+ if (!channel || !("messages" in channel))
54
+ return null;
55
+ return channel.messages.fetch(messageId).catch(() => null);
47
56
  }
48
57
 
49
- export { findMessage, getMessageUrlInfo };
58
+ export { fetchMessageFromURL, findMessage, getMessageURLInfo };
@@ -17,7 +17,15 @@ function modalFieldsToRecord(fields) {
17
17
  const modalFields = fields instanceof discord_js.ModalSubmitInteraction ? fields.fields.fields : "fields" in fields ? fields.fields : fields;
18
18
  return modalFields.reduce(reduceFunction, {});
19
19
  }
20
+ function createModal(data) {
21
+ return new discord_js.ModalBuilder({
22
+ title: data.title ?? data.customId,
23
+ customId: data.customId,
24
+ components: createModalFields(data.components)
25
+ });
26
+ }
20
27
 
28
+ exports.createModal = createModal;
21
29
  exports.createModalFields = createModalFields;
22
30
  exports.createModalInput = createModalInput;
23
31
  exports.modalFieldsToRecord = modalFieldsToRecord;
@@ -1,4 +1,4 @@
1
- import { TextInputStyle, TextInputBuilder, ModalSubmitInteraction } from 'discord.js';
1
+ import { TextInputStyle, TextInputBuilder, ModalSubmitInteraction, ModalBuilder } from 'discord.js';
2
2
  import { createRow } from './components/row.mjs';
3
3
 
4
4
  function createModalInput(data) {
@@ -15,5 +15,12 @@ function modalFieldsToRecord(fields) {
15
15
  const modalFields = fields instanceof ModalSubmitInteraction ? fields.fields.fields : "fields" in fields ? fields.fields : fields;
16
16
  return modalFields.reduce(reduceFunction, {});
17
17
  }
18
+ function createModal(data) {
19
+ return new ModalBuilder({
20
+ title: data.title ?? data.customId,
21
+ customId: data.customId,
22
+ components: createModalFields(data.components)
23
+ });
24
+ }
18
25
 
19
- export { createModalFields, createModalInput, modalFieldsToRecord };
26
+ export { createModal, createModalFields, createModalInput, modalFieldsToRecord };
@@ -1,9 +1,15 @@
1
1
  'use strict';
2
2
 
3
3
  const discord_js = require('discord.js');
4
+ const utils = require('./utils.cjs');
4
5
 
5
6
  function isAttachment(value) {
6
- return value instanceof discord_js.Attachment || value instanceof discord_js.AttachmentBuilder;
7
+ return value instanceof discord_js.Attachment || value instanceof discord_js.AttachmentBuilder || utils.hasConstructor(value) && [
8
+ discord_js.Attachment.name,
9
+ discord_js.AttachmentBuilder.name
10
+ ].some(
11
+ (name) => name === value.constructor.name
12
+ );
7
13
  }
8
14
 
9
15
  exports.isAttachment = isAttachment;
@@ -1,7 +1,13 @@
1
1
  import { Attachment, AttachmentBuilder } from 'discord.js';
2
+ import { hasConstructor } from './utils.mjs';
2
3
 
3
4
  function isAttachment(value) {
4
- return value instanceof Attachment || value instanceof AttachmentBuilder;
5
+ return value instanceof Attachment || value instanceof AttachmentBuilder || hasConstructor(value) && [
6
+ Attachment.name,
7
+ AttachmentBuilder.name
8
+ ].some(
9
+ (name) => name === value.constructor.name
10
+ );
5
11
  }
6
12
 
7
13
  export { isAttachment };