@erinjs/core 1.0.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 (389) hide show
  1. package/core/.changeset/README.md +8 -0
  2. package/core/.changeset/community-bootstrap-release.md +17 -0
  3. package/core/.changeset/config.json +11 -0
  4. package/core/.changeset/no-changelog.js +16 -0
  5. package/core/.changeset/pre.json +17 -0
  6. package/core/.editorconfig +13 -0
  7. package/core/.gitattributes +2 -0
  8. package/core/.github/CODE_OF_CONDUCT.md +23 -0
  9. package/core/.github/FUNDING.yml +7 -0
  10. package/core/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
  11. package/core/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
  12. package/core/.github/PULL_REQUEST_TEMPLATE.md +16 -0
  13. package/core/.github/dependabot.yml +16 -0
  14. package/core/.github/workflows/autoapp.yml +16 -0
  15. package/core/.github/workflows/ci.yml +187 -0
  16. package/core/.github/workflows/codeql.yml +30 -0
  17. package/core/.github/workflows/deploy-docs.yml +54 -0
  18. package/core/.github/workflows/publish.yml +43 -0
  19. package/core/.lintstagedrc.json +4 -0
  20. package/core/.nvmrc +1 -0
  21. package/core/.prettierignore +8 -0
  22. package/core/.prettierrc +11 -0
  23. package/core/CONTRIBUTING.md +70 -0
  24. package/core/LICENSE +203 -0
  25. package/core/README.md +61 -0
  26. package/core/SECURITY.md +21 -0
  27. package/core/apps/docs/index.html +28 -0
  28. package/core/apps/docs/middleware.ts +21 -0
  29. package/core/apps/docs/package.json +33 -0
  30. package/core/apps/docs/public/@flux.png +0 -0
  31. package/core/apps/docs/public/docs/latest/guides.json +1420 -0
  32. package/core/apps/docs/public/docs/latest/main.json +14981 -0
  33. package/core/apps/docs/public/docs/latest/rag-index.json +1 -0
  34. package/core/apps/docs/public/docs/v1.0.5/guides.json +226 -0
  35. package/core/apps/docs/public/docs/v1.0.5/main.json +7920 -0
  36. package/core/apps/docs/public/docs/v1.0.6/guides.json +226 -0
  37. package/core/apps/docs/public/docs/v1.0.6/main.json +7920 -0
  38. package/core/apps/docs/public/docs/v1.0.7/guides.json +259 -0
  39. package/core/apps/docs/public/docs/v1.0.7/main.json +8652 -0
  40. package/core/apps/docs/public/docs/v1.0.8/guides.json +313 -0
  41. package/core/apps/docs/public/docs/v1.0.8/main.json +9618 -0
  42. package/core/apps/docs/public/docs/v1.0.9/guides.json +319 -0
  43. package/core/apps/docs/public/docs/v1.0.9/main.json +10694 -0
  44. package/core/apps/docs/public/docs/v1.1.0/guides.json +589 -0
  45. package/core/apps/docs/public/docs/v1.1.0/main.json +12576 -0
  46. package/core/apps/docs/public/docs/v1.1.2/guides.json +650 -0
  47. package/core/apps/docs/public/docs/v1.1.2/main.json +13239 -0
  48. package/core/apps/docs/public/docs/v1.1.3/guides.json +650 -0
  49. package/core/apps/docs/public/docs/v1.1.3/main.json +13239 -0
  50. package/core/apps/docs/public/docs/v1.1.4/guides.json +708 -0
  51. package/core/apps/docs/public/docs/v1.1.4/main.json +13231 -0
  52. package/core/apps/docs/public/docs/v1.1.5/guides.json +1035 -0
  53. package/core/apps/docs/public/docs/v1.1.5/main.json +13838 -0
  54. package/core/apps/docs/public/docs/v1.1.6/guides.json +1041 -0
  55. package/core/apps/docs/public/docs/v1.1.6/main.json +14313 -0
  56. package/core/apps/docs/public/docs/v1.1.8/guides.json +1047 -0
  57. package/core/apps/docs/public/docs/v1.1.8/main.json +14421 -0
  58. package/core/apps/docs/public/docs/v1.1.9/guides.json +1047 -0
  59. package/core/apps/docs/public/docs/v1.1.9/main.json +14421 -0
  60. package/core/apps/docs/public/docs/v1.2.0/guides.json +1212 -0
  61. package/core/apps/docs/public/docs/v1.2.0/main.json +14663 -0
  62. package/core/apps/docs/public/docs/v1.2.1/guides.json +1293 -0
  63. package/core/apps/docs/public/docs/v1.2.1/main.json +14828 -0
  64. package/core/apps/docs/public/docs/v1.2.2/guides.json +1293 -0
  65. package/core/apps/docs/public/docs/v1.2.2/main.json +15025 -0
  66. package/core/apps/docs/public/docs/v1.2.3/guides.json +1420 -0
  67. package/core/apps/docs/public/docs/v1.2.3/main.json +14954 -0
  68. package/core/apps/docs/public/docs/v1.2.4/guides.json +1420 -0
  69. package/core/apps/docs/public/docs/v1.2.4/main.json +14981 -0
  70. package/core/apps/docs/public/docs/versions.json +24 -0
  71. package/core/apps/docs/public/flux.png +0 -0
  72. package/core/apps/docs/public/locales/en.json +50 -0
  73. package/core/apps/docs/public/locales/guides-en.json +512 -0
  74. package/core/apps/docs/public/robots.txt +4 -0
  75. package/core/apps/docs/public/sitemap.xml +33 -0
  76. package/core/apps/docs/src/App.vue +538 -0
  77. package/core/apps/docs/src/components/ApiCategorySection.vue +42 -0
  78. package/core/apps/docs/src/components/ApiDiscordCompat.vue +65 -0
  79. package/core/apps/docs/src/components/ApiEndpointCard.vue +313 -0
  80. package/core/apps/docs/src/components/ApiSchemaBlock.vue +131 -0
  81. package/core/apps/docs/src/components/CodeBlock.vue +177 -0
  82. package/core/apps/docs/src/components/CommunityCallout.vue +90 -0
  83. package/core/apps/docs/src/components/ConstructorSection.vue +82 -0
  84. package/core/apps/docs/src/components/DocDescription.vue +40 -0
  85. package/core/apps/docs/src/components/FluxerLogo.vue +3 -0
  86. package/core/apps/docs/src/components/Footer.vue +106 -0
  87. package/core/apps/docs/src/components/GuideCodeBlock.vue +102 -0
  88. package/core/apps/docs/src/components/GuideDiscordCompat.vue +77 -0
  89. package/core/apps/docs/src/components/GuideDiscordCompatCallout.vue +83 -0
  90. package/core/apps/docs/src/components/GuideTable.vue +77 -0
  91. package/core/apps/docs/src/components/GuideTip.vue +38 -0
  92. package/core/apps/docs/src/components/MethodsSection.vue +195 -0
  93. package/core/apps/docs/src/components/ParamsTable.vue +70 -0
  94. package/core/apps/docs/src/components/PropertiesSection.vue +143 -0
  95. package/core/apps/docs/src/components/SearchBar.vue +76 -0
  96. package/core/apps/docs/src/components/SearchModal.vue +361 -0
  97. package/core/apps/docs/src/components/SidebarNav.vue +225 -0
  98. package/core/apps/docs/src/components/SponsorBanner.vue +153 -0
  99. package/core/apps/docs/src/components/TypeSignature.vue +187 -0
  100. package/core/apps/docs/src/components/VersionPicker.vue +191 -0
  101. package/core/apps/docs/src/composables/useSearchIndex.ts +144 -0
  102. package/core/apps/docs/src/composables/useVersionedPath.ts +20 -0
  103. package/core/apps/docs/src/data/apiEndpoints.ts +1073 -0
  104. package/core/apps/docs/src/data/changelog.ts +717 -0
  105. package/core/apps/docs/src/data/guides.ts +2362 -0
  106. package/core/apps/docs/src/env.d.ts +7 -0
  107. package/core/apps/docs/src/locales/guides-en.json +512 -0
  108. package/core/apps/docs/src/main.ts +27 -0
  109. package/core/apps/docs/src/pages/ApiReferenceLayout.vue +175 -0
  110. package/core/apps/docs/src/pages/ApiReferencePage.vue +128 -0
  111. package/core/apps/docs/src/pages/Changelog.vue +288 -0
  112. package/core/apps/docs/src/pages/ClassPage.vue +319 -0
  113. package/core/apps/docs/src/pages/ClassesList.vue +100 -0
  114. package/core/apps/docs/src/pages/DocsLayout.vue +127 -0
  115. package/core/apps/docs/src/pages/GuidePage.vue +279 -0
  116. package/core/apps/docs/src/pages/GuidesIndex.vue +166 -0
  117. package/core/apps/docs/src/pages/GuidesLayout.vue +245 -0
  118. package/core/apps/docs/src/pages/Home.vue +125 -0
  119. package/core/apps/docs/src/pages/NotFound.vue +57 -0
  120. package/core/apps/docs/src/pages/TypedefPage.vue +230 -0
  121. package/core/apps/docs/src/pages/TypedefsList.vue +168 -0
  122. package/core/apps/docs/src/pages/VersionLayout.vue +15 -0
  123. package/core/apps/docs/src/router.ts +73 -0
  124. package/core/apps/docs/src/stores/docs.ts +54 -0
  125. package/core/apps/docs/src/stores/guides.ts +53 -0
  126. package/core/apps/docs/src/stores/version.ts +67 -0
  127. package/core/apps/docs/src/styles/main.css +278 -0
  128. package/core/apps/docs/src/styles/prism.css +95 -0
  129. package/core/apps/docs/src/types/doc-schema.ts +112 -0
  130. package/core/apps/docs/tsconfig.json +17 -0
  131. package/core/apps/docs/tsconfig.node.json +10 -0
  132. package/core/apps/docs/vite.config.d.ts +2 -0
  133. package/core/apps/docs/vite.config.js +26 -0
  134. package/core/apps/docs/vite.config.ts +28 -0
  135. package/core/apps/docs-vitepress/.vitepress/config.ts +141 -0
  136. package/core/apps/docs-vitepress/api-data/latest/main.json +15035 -0
  137. package/core/apps/docs-vitepress/api-data/v1.2.4/main.json +15035 -0
  138. package/core/apps/docs-vitepress/api-data/versions.json +6 -0
  139. package/core/apps/docs-vitepress/index.md +15 -0
  140. package/core/apps/docs-vitepress/package-lock.json +2924 -0
  141. package/core/apps/docs-vitepress/package.json +20 -0
  142. package/core/apps/docs-vitepress/public/CNAME +1 -0
  143. package/core/apps/docs-vitepress/scripts/generate-api.ts +243 -0
  144. package/core/apps/docs-vitepress/scripts/migrate-guides.ts +129 -0
  145. package/core/apps/docs-vitepress/tsconfig.json +11 -0
  146. package/core/apps/docs-vitepress/v/latest/guides/attachments-by-url.md +57 -0
  147. package/core/apps/docs-vitepress/v/latest/guides/attachments.md +62 -0
  148. package/core/apps/docs-vitepress/v/latest/guides/basic-bot.md +49 -0
  149. package/core/apps/docs-vitepress/v/latest/guides/channels.md +180 -0
  150. package/core/apps/docs-vitepress/v/latest/guides/deprecated-apis.md +58 -0
  151. package/core/apps/docs-vitepress/v/latest/guides/discord-js-compatibility.md +42 -0
  152. package/core/apps/docs-vitepress/v/latest/guides/editing-embeds.md +65 -0
  153. package/core/apps/docs-vitepress/v/latest/guides/embed-media.md +87 -0
  154. package/core/apps/docs-vitepress/v/latest/guides/embeds.md +166 -0
  155. package/core/apps/docs-vitepress/v/latest/guides/emojis.md +77 -0
  156. package/core/apps/docs-vitepress/v/latest/guides/events.md +202 -0
  157. package/core/apps/docs-vitepress/v/latest/guides/gifs.md +47 -0
  158. package/core/apps/docs-vitepress/v/latest/guides/installation.md +10 -0
  159. package/core/apps/docs-vitepress/v/latest/guides/moderation.md +89 -0
  160. package/core/apps/docs-vitepress/v/latest/guides/permissions.md +130 -0
  161. package/core/apps/docs-vitepress/v/latest/guides/prefix-commands.md +41 -0
  162. package/core/apps/docs-vitepress/v/latest/guides/profile-urls.md +58 -0
  163. package/core/apps/docs-vitepress/v/latest/guides/reactions.md +69 -0
  164. package/core/apps/docs-vitepress/v/latest/guides/roles.md +130 -0
  165. package/core/apps/docs-vitepress/v/latest/guides/sending-without-reply.md +172 -0
  166. package/core/apps/docs-vitepress/v/latest/guides/voice.md +109 -0
  167. package/core/apps/docs-vitepress/v/latest/guides/wait-for-guilds.md +37 -0
  168. package/core/apps/docs-vitepress/v/latest/guides/webhook-attachments-embeds.md +73 -0
  169. package/core/apps/docs-vitepress/v/latest/guides/webhooks.md +131 -0
  170. package/core/eslint.config.js +80 -0
  171. package/core/examples/.env.example +22 -0
  172. package/core/examples/README.md +68 -0
  173. package/core/examples/first-steps-bot.js +118 -0
  174. package/core/examples/minimal-bot.js +17 -0
  175. package/core/examples/moderation-bot.js +209 -0
  176. package/core/examples/package.json +14 -0
  177. package/core/examples/ping-bot.js +1146 -0
  178. package/core/examples/reaction-bot.js +70 -0
  179. package/core/examples/reaction-roles-bot.js +140 -0
  180. package/core/examples/webhook-bot.js +239 -0
  181. package/core/flux.png +0 -0
  182. package/core/package.json +78 -0
  183. package/core/packages/builders/package.json +51 -0
  184. package/core/packages/builders/src/index.ts +13 -0
  185. package/core/packages/builders/src/messages/AttachmentBuilder.test.ts +79 -0
  186. package/core/packages/builders/src/messages/AttachmentBuilder.ts +69 -0
  187. package/core/packages/builders/src/messages/EmbedBuilder.test.ts +266 -0
  188. package/core/packages/builders/src/messages/EmbedBuilder.ts +239 -0
  189. package/core/packages/builders/src/messages/MessagePayload.test.ts +118 -0
  190. package/core/packages/builders/src/messages/MessagePayload.ts +122 -0
  191. package/core/packages/builders/tsconfig.json +9 -0
  192. package/core/packages/builders/tsup.config.ts +9 -0
  193. package/core/packages/builders/vitest.config.ts +9 -0
  194. package/core/packages/collection/package.json +47 -0
  195. package/core/packages/collection/src/Collection.test.ts +232 -0
  196. package/core/packages/collection/src/Collection.ts +196 -0
  197. package/core/packages/collection/src/index.ts +1 -0
  198. package/core/packages/collection/tsconfig.json +9 -0
  199. package/core/packages/collection/tsup.config.ts +9 -0
  200. package/core/packages/collection/vitest.config.ts +9 -0
  201. package/core/packages/docgen/package.json +26 -0
  202. package/core/packages/docgen/src/extract.ts +262 -0
  203. package/core/packages/docgen/src/formatType.ts +24 -0
  204. package/core/packages/docgen/src/index.ts +103 -0
  205. package/core/packages/docgen/src/schema.ts +100 -0
  206. package/core/packages/docgen/src/visitor.ts +147 -0
  207. package/core/packages/docgen/tsconfig.json +9 -0
  208. package/core/packages/docgen/tsup.config.ts +9 -0
  209. package/core/packages/fluxer-core/README.md +26 -0
  210. package/core/packages/fluxer-core/package.json +60 -0
  211. package/core/packages/fluxer-core/src/client/ChannelManager.ts +143 -0
  212. package/core/packages/fluxer-core/src/client/Client.gateway.test.ts +84 -0
  213. package/core/packages/fluxer-core/src/client/Client.resolveEmoji.test.ts +45 -0
  214. package/core/packages/fluxer-core/src/client/Client.ts +558 -0
  215. package/core/packages/fluxer-core/src/client/ClientUser.ts +40 -0
  216. package/core/packages/fluxer-core/src/client/EventHandlerRegistry.ts +469 -0
  217. package/core/packages/fluxer-core/src/client/GuildManager.ts +79 -0
  218. package/core/packages/fluxer-core/src/client/GuildMemberManager.ts +91 -0
  219. package/core/packages/fluxer-core/src/client/MessageManager.ts +58 -0
  220. package/core/packages/fluxer-core/src/client/UsersManager.ts +122 -0
  221. package/core/packages/fluxer-core/src/errors/ErrorCodes.test.ts +19 -0
  222. package/core/packages/fluxer-core/src/errors/ErrorCodes.ts +12 -0
  223. package/core/packages/fluxer-core/src/errors/FluxerError.test.ts +32 -0
  224. package/core/packages/fluxer-core/src/errors/FluxerError.ts +15 -0
  225. package/core/packages/fluxer-core/src/index.ts +85 -0
  226. package/core/packages/fluxer-core/src/structures/Base.ts +7 -0
  227. package/core/packages/fluxer-core/src/structures/Channel.ts +508 -0
  228. package/core/packages/fluxer-core/src/structures/Guild.test.ts +189 -0
  229. package/core/packages/fluxer-core/src/structures/Guild.ts +734 -0
  230. package/core/packages/fluxer-core/src/structures/GuildBan.ts +35 -0
  231. package/core/packages/fluxer-core/src/structures/GuildEmoji.ts +57 -0
  232. package/core/packages/fluxer-core/src/structures/GuildMember.test.ts +203 -0
  233. package/core/packages/fluxer-core/src/structures/GuildMember.ts +213 -0
  234. package/core/packages/fluxer-core/src/structures/GuildMemberRoleManager.ts +121 -0
  235. package/core/packages/fluxer-core/src/structures/GuildSticker.ts +56 -0
  236. package/core/packages/fluxer-core/src/structures/Invite.test.ts +103 -0
  237. package/core/packages/fluxer-core/src/structures/Invite.ts +121 -0
  238. package/core/packages/fluxer-core/src/structures/Message.test.ts +109 -0
  239. package/core/packages/fluxer-core/src/structures/Message.ts +397 -0
  240. package/core/packages/fluxer-core/src/structures/MessageReaction.ts +72 -0
  241. package/core/packages/fluxer-core/src/structures/PartialMessage.ts +12 -0
  242. package/core/packages/fluxer-core/src/structures/Role.test.ts +77 -0
  243. package/core/packages/fluxer-core/src/structures/Role.ts +112 -0
  244. package/core/packages/fluxer-core/src/structures/User.test.ts +110 -0
  245. package/core/packages/fluxer-core/src/structures/User.ts +109 -0
  246. package/core/packages/fluxer-core/src/structures/Webhook.test.ts +109 -0
  247. package/core/packages/fluxer-core/src/structures/Webhook.ts +258 -0
  248. package/core/packages/fluxer-core/src/util/Constants.test.ts +16 -0
  249. package/core/packages/fluxer-core/src/util/Constants.ts +7 -0
  250. package/core/packages/fluxer-core/src/util/Events.ts +46 -0
  251. package/core/packages/fluxer-core/src/util/MessageCollector.ts +87 -0
  252. package/core/packages/fluxer-core/src/util/Options.ts +33 -0
  253. package/core/packages/fluxer-core/src/util/ReactionCollector.ts +116 -0
  254. package/core/packages/fluxer-core/src/util/cdn.test.ts +108 -0
  255. package/core/packages/fluxer-core/src/util/cdn.ts +130 -0
  256. package/core/packages/fluxer-core/src/util/guildUtils.ts +33 -0
  257. package/core/packages/fluxer-core/src/util/messageUtils.test.ts +74 -0
  258. package/core/packages/fluxer-core/src/util/messageUtils.ts +119 -0
  259. package/core/packages/fluxer-core/src/util/permissions.test.ts +95 -0
  260. package/core/packages/fluxer-core/src/util/permissions.ts +43 -0
  261. package/core/packages/fluxer-core/tsconfig.json +9 -0
  262. package/core/packages/fluxer-core/tsup.config.ts +9 -0
  263. package/core/packages/fluxer-core/vitest.config.ts +9 -0
  264. package/core/packages/rest/package.json +52 -0
  265. package/core/packages/rest/src/REST.test.ts +64 -0
  266. package/core/packages/rest/src/REST.ts +90 -0
  267. package/core/packages/rest/src/RateLimitManager.test.ts +71 -0
  268. package/core/packages/rest/src/RateLimitManager.ts +60 -0
  269. package/core/packages/rest/src/RequestManager.test.ts +87 -0
  270. package/core/packages/rest/src/RequestManager.ts +172 -0
  271. package/core/packages/rest/src/errors/FluxerAPIError.test.ts +57 -0
  272. package/core/packages/rest/src/errors/FluxerAPIError.ts +21 -0
  273. package/core/packages/rest/src/errors/HTTPError.test.ts +55 -0
  274. package/core/packages/rest/src/errors/HTTPError.ts +25 -0
  275. package/core/packages/rest/src/errors/RateLimitError.test.ts +41 -0
  276. package/core/packages/rest/src/errors/RateLimitError.ts +15 -0
  277. package/core/packages/rest/src/errors/index.ts +3 -0
  278. package/core/packages/rest/src/index.ts +6 -0
  279. package/core/packages/rest/src/utils/constants.test.ts +31 -0
  280. package/core/packages/rest/src/utils/constants.ts +5 -0
  281. package/core/packages/rest/src/utils/files.test.ts +37 -0
  282. package/core/packages/rest/src/utils/files.ts +75 -0
  283. package/core/packages/rest/tsconfig.json +9 -0
  284. package/core/packages/rest/tsup.config.ts +9 -0
  285. package/core/packages/rest/vitest.config.ts +9 -0
  286. package/core/packages/types/package.json +46 -0
  287. package/core/packages/types/src/api/ban.ts +8 -0
  288. package/core/packages/types/src/api/channel.ts +65 -0
  289. package/core/packages/types/src/api/embed.ts +82 -0
  290. package/core/packages/types/src/api/emoji.ts +12 -0
  291. package/core/packages/types/src/api/errors.ts +68 -0
  292. package/core/packages/types/src/api/gateway.ts +14 -0
  293. package/core/packages/types/src/api/guild.ts +123 -0
  294. package/core/packages/types/src/api/index.ts +15 -0
  295. package/core/packages/types/src/api/instance.ts +32 -0
  296. package/core/packages/types/src/api/interaction.ts +26 -0
  297. package/core/packages/types/src/api/invite.ts +28 -0
  298. package/core/packages/types/src/api/message.ts +140 -0
  299. package/core/packages/types/src/api/role.ts +41 -0
  300. package/core/packages/types/src/api/sticker.ts +14 -0
  301. package/core/packages/types/src/api/user.ts +79 -0
  302. package/core/packages/types/src/api/webhook.ts +41 -0
  303. package/core/packages/types/src/common/index.ts +1 -0
  304. package/core/packages/types/src/common/snowflake.test.ts +9 -0
  305. package/core/packages/types/src/common/snowflake.ts +8 -0
  306. package/core/packages/types/src/gateway/events.ts +189 -0
  307. package/core/packages/types/src/gateway/index.ts +3 -0
  308. package/core/packages/types/src/gateway/opcodes.ts +17 -0
  309. package/core/packages/types/src/gateway/payloads.ts +481 -0
  310. package/core/packages/types/src/index.ts +4 -0
  311. package/core/packages/types/src/rest/index.ts +1 -0
  312. package/core/packages/types/src/rest/routes.test.ts +169 -0
  313. package/core/packages/types/src/rest/routes.ts +109 -0
  314. package/core/packages/types/tsconfig.json +9 -0
  315. package/core/packages/types/tsup.config.ts +9 -0
  316. package/core/packages/types/vitest.config.ts +9 -0
  317. package/core/packages/util/package.json +51 -0
  318. package/core/packages/util/src/BitField.test.ts +96 -0
  319. package/core/packages/util/src/BitField.ts +105 -0
  320. package/core/packages/util/src/MessageFlagsBitField.test.ts +42 -0
  321. package/core/packages/util/src/MessageFlagsBitField.ts +20 -0
  322. package/core/packages/util/src/PermissionsBitField.test.ts +79 -0
  323. package/core/packages/util/src/PermissionsBitField.ts +97 -0
  324. package/core/packages/util/src/SnowflakeUtil.test.ts +69 -0
  325. package/core/packages/util/src/SnowflakeUtil.ts +65 -0
  326. package/core/packages/util/src/UserFlagsBitField.test.ts +39 -0
  327. package/core/packages/util/src/UserFlagsBitField.ts +48 -0
  328. package/core/packages/util/src/deprecation.test.ts +44 -0
  329. package/core/packages/util/src/deprecation.ts +28 -0
  330. package/core/packages/util/src/emojiShortcodes.generated.ts +5 -0
  331. package/core/packages/util/src/emojiShortcodes.test.ts +41 -0
  332. package/core/packages/util/src/emojiShortcodes.ts +22 -0
  333. package/core/packages/util/src/formatters.test.ts +65 -0
  334. package/core/packages/util/src/formatters.ts +35 -0
  335. package/core/packages/util/src/index.ts +34 -0
  336. package/core/packages/util/src/resolvers.test.ts +198 -0
  337. package/core/packages/util/src/resolvers.ts +127 -0
  338. package/core/packages/util/src/tenorUtils.test.ts +75 -0
  339. package/core/packages/util/src/tenorUtils.ts +86 -0
  340. package/core/packages/util/tsconfig.json +9 -0
  341. package/core/packages/util/tsup.config.ts +9 -0
  342. package/core/packages/util/vitest.config.ts +9 -0
  343. package/core/packages/voice/README.md +42 -0
  344. package/core/packages/voice/package.json +67 -0
  345. package/core/packages/voice/src/LiveKitRtcConnection.receive.test.ts +24 -0
  346. package/core/packages/voice/src/LiveKitRtcConnection.ts +1767 -0
  347. package/core/packages/voice/src/VoiceConnection.ts +413 -0
  348. package/core/packages/voice/src/VoiceManager.receive.test.ts +61 -0
  349. package/core/packages/voice/src/VoiceManager.test.ts +44 -0
  350. package/core/packages/voice/src/VoiceManager.ts +503 -0
  351. package/core/packages/voice/src/exports.test.ts +38 -0
  352. package/core/packages/voice/src/index.ts +51 -0
  353. package/core/packages/voice/src/livekit.test.ts +48 -0
  354. package/core/packages/voice/src/livekit.ts +33 -0
  355. package/core/packages/voice/src/mp4box.d.ts +32 -0
  356. package/core/packages/voice/src/opusUtils.test.ts +29 -0
  357. package/core/packages/voice/src/opusUtils.ts +86 -0
  358. package/core/packages/voice/src/streamPreviewPlaceholder.test.ts +16 -0
  359. package/core/packages/voice/src/streamPreviewPlaceholder.ts +8 -0
  360. package/core/packages/voice/src/ws.d.ts +1 -0
  361. package/core/packages/voice/tsconfig.json +5 -0
  362. package/core/packages/voice/tsup.config.ts +10 -0
  363. package/core/packages/voice/vitest.config.ts +9 -0
  364. package/core/packages/ws/package.json +52 -0
  365. package/core/packages/ws/src/WebSocketManager.ts +130 -0
  366. package/core/packages/ws/src/WebSocketShard.ts +296 -0
  367. package/core/packages/ws/src/index.ts +12 -0
  368. package/core/packages/ws/src/utils/constants.test.ts +46 -0
  369. package/core/packages/ws/src/utils/constants.ts +22 -0
  370. package/core/packages/ws/src/utils/getWebSocket.ts +55 -0
  371. package/core/packages/ws/src/ws.d.ts +10 -0
  372. package/core/packages/ws/tsconfig.json +9 -0
  373. package/core/packages/ws/tsup.config.ts +9 -0
  374. package/core/pnpm-lock.yaml +7033 -0
  375. package/core/pnpm-workspace.yaml +4 -0
  376. package/core/scripts/generate-ai-rag.ts +240 -0
  377. package/core/scripts/generate-docs.ts +143 -0
  378. package/core/scripts/generate-emoji-shortcodes.ts +58 -0
  379. package/core/scripts/generate-types.ts +6 -0
  380. package/core/scripts/publish-ordered.js +63 -0
  381. package/core/scripts/test-cjs-require.mjs +43 -0
  382. package/core/scripts/test-esm-imports.mjs +42 -0
  383. package/core/scripts/test-package-exports.mjs +98 -0
  384. package/core/scripts/test-smoke.mjs +103 -0
  385. package/core/tsconfig.json +18 -0
  386. package/core/turbo.json +30 -0
  387. package/core/vitest.config.ts +17 -0
  388. package/core/wrangler.jsonc +9 -0
  389. package/package.json +26 -0
@@ -0,0 +1,469 @@
1
+ import { Events } from '../util/Events.js';
2
+ import {
3
+ APIMessage,
4
+ APIChannel,
5
+ APIChannelPartial,
6
+ APIGuild,
7
+ APIGuildPartial,
8
+ APIGuildMember,
9
+ APIInvite,
10
+ APIUserPartial,
11
+ APIApplicationCommandInteraction,
12
+ APIBan,
13
+ } from '@erinjs/types';
14
+ import {
15
+ GatewayMessageReactionAddDispatchData,
16
+ GatewayMessageReactionRemoveDispatchData,
17
+ GatewayMessageReactionRemoveEmojiDispatchData,
18
+ GatewayMessageReactionRemoveAllDispatchData,
19
+ GatewayVoiceStateUpdateDispatchData,
20
+ GatewayVoiceServerUpdateDispatchData,
21
+ GatewayMessageDeleteDispatchData,
22
+ GatewayMessageDeleteBulkDispatchData,
23
+ GatewayGuildBanAddDispatchData,
24
+ GatewayGuildBanRemoveDispatchData,
25
+ GatewayInviteCreateDispatchData,
26
+ GatewayInviteDeleteDispatchData,
27
+ GatewayGuildRoleCreateDispatchData,
28
+ GatewayGuildRoleUpdateDispatchData,
29
+ GatewayGuildRoleDeleteDispatchData,
30
+ GatewayTypingStartDispatchData,
31
+ GatewayUserUpdateDispatchData,
32
+ GatewayGuildMemberRemoveDispatchData,
33
+ } from '@erinjs/types';
34
+ import { Client } from './Client.js';
35
+ import { normalizeGuildPayload } from '../util/guildUtils';
36
+ import { GuildMember } from '../structures/GuildMember';
37
+ import { Message } from '../structures/Message';
38
+ import { MessageReaction } from '../structures/MessageReaction';
39
+ import { Guild } from '../structures/Guild';
40
+ import { Channel, GuildChannel } from '../structures/Channel';
41
+ import { GuildBan } from '../structures/GuildBan';
42
+ import { Role } from '../structures/Role';
43
+ import { Invite } from '../structures/Invite';
44
+ import { GuildEmoji } from '../structures/GuildEmoji';
45
+
46
+ export type DispatchHandler = (client: Client, data: unknown) => Promise<void>;
47
+
48
+ const handlers = new Map<string, DispatchHandler>();
49
+
50
+ function normalizeInviteCreatePayload(
51
+ client: Client,
52
+ payload: GatewayInviteCreateDispatchData,
53
+ ): APIInvite | null {
54
+ if (!payload?.code) return null;
55
+
56
+ const guildId = payload.guild?.id ?? payload.guild_id ?? '0';
57
+ const cachedGuild = guildId !== '0' ? client.guilds.get(guildId) : null;
58
+ const guild: APIGuildPartial = {
59
+ id: guildId,
60
+ name: payload.guild?.name ?? cachedGuild?.name ?? 'Unknown Guild',
61
+ icon: payload.guild?.icon ?? null,
62
+ banner: payload.guild?.banner ?? null,
63
+ splash: payload.guild?.splash ?? null,
64
+ features: payload.guild?.features,
65
+ };
66
+
67
+ const channelId = payload.channel?.id ?? payload.channel_id ?? '0';
68
+ const cachedChannel = channelId !== '0' ? client.channels.get(channelId) : null;
69
+ const channel: APIChannelPartial = {
70
+ id: channelId,
71
+ type: payload.channel?.type ?? cachedChannel?.type ?? 0,
72
+ name: payload.channel?.name ?? cachedChannel?.name ?? null,
73
+ icon: payload.channel?.icon ?? null,
74
+ };
75
+
76
+ return {
77
+ code: payload.code,
78
+ type: typeof payload.type === 'number' ? payload.type : 0,
79
+ guild,
80
+ channel,
81
+ inviter: payload.inviter ?? null,
82
+ member_count: payload.member_count,
83
+ presence_count: payload.presence_count,
84
+ expires_at: payload.expires_at,
85
+ temporary: payload.temporary,
86
+ created_at: payload.created_at,
87
+ uses: payload.uses,
88
+ max_uses: payload.max_uses,
89
+ max_age: payload.max_age,
90
+ };
91
+ }
92
+
93
+ handlers.set('MESSAGE_CREATE', async (client, d) => {
94
+ const data = d as APIMessage & { member?: APIGuildMember };
95
+ if (data.guild_id && data.member && data.author) {
96
+ const guild = client.guilds.get(data.guild_id);
97
+ if (guild) {
98
+ const memberData = { ...data.member, user: data.author, guild_id: data.guild_id };
99
+ const member = new GuildMember(client, memberData, guild);
100
+ guild.members.set(member.id, member);
101
+ }
102
+ }
103
+ client._addMessageToCache(data.channel_id, data);
104
+ client.emit(Events.MessageCreate, new Message(client, data));
105
+ });
106
+
107
+ handlers.set('MESSAGE_UPDATE', async (client, d) => {
108
+ const partial = d as APIMessage;
109
+ const cache = client._getMessageCache(partial.channel_id);
110
+ let oldMessage: Message | null = null;
111
+ let mergedData: APIMessage = partial;
112
+
113
+ if (cache) {
114
+ const oldData = cache.get(partial.id);
115
+ if (oldData) {
116
+ oldMessage = new Message(client, oldData);
117
+ mergedData = { ...oldData, ...partial } as APIMessage;
118
+ }
119
+ cache.set(partial.id, mergedData);
120
+ }
121
+
122
+ const newMessage = new Message(client, mergedData);
123
+ client.emit(Events.MessageUpdate, oldMessage, newMessage);
124
+ });
125
+
126
+ handlers.set('MESSAGE_DELETE', async (client, d) => {
127
+ const data = d as GatewayMessageDeleteDispatchData;
128
+ client._removeMessageFromCache(data.channel_id, data.id);
129
+ const channel = client.channels.get(data.channel_id) ?? null;
130
+ client.emit(Events.MessageDelete, {
131
+ id: data.id,
132
+ channelId: data.channel_id,
133
+ channel,
134
+ content: data.content ?? null,
135
+ authorId: data.author_id ?? null,
136
+ });
137
+ });
138
+
139
+ handlers.set('MESSAGE_REACTION_ADD', async (client, d) => {
140
+ const data = d as GatewayMessageReactionAddDispatchData;
141
+ const reaction = new MessageReaction(client, data);
142
+ const user = client.getOrCreateUser({
143
+ id: data.user_id,
144
+ username: 'Unknown',
145
+ discriminator: '0',
146
+ } as APIUserPartial);
147
+ client.emit(Events.MessageReactionAdd, reaction, user);
148
+ });
149
+
150
+ handlers.set('MESSAGE_REACTION_REMOVE', async (client, d) => {
151
+ const data = d as GatewayMessageReactionRemoveDispatchData;
152
+ const reaction = new MessageReaction(client, data);
153
+ const user = client.getOrCreateUser({
154
+ id: data.user_id,
155
+ username: 'Unknown',
156
+ discriminator: '0',
157
+ } as APIUserPartial);
158
+ client.emit(Events.MessageReactionRemove, reaction, user);
159
+ });
160
+
161
+ handlers.set('MESSAGE_REACTION_REMOVE_ALL', async (client, d) => {
162
+ client.emit(Events.MessageReactionRemoveAll, d as GatewayMessageReactionRemoveAllDispatchData);
163
+ });
164
+
165
+ handlers.set('MESSAGE_REACTION_REMOVE_EMOJI', async (client, d) => {
166
+ client.emit(
167
+ Events.MessageReactionRemoveEmoji,
168
+ d as GatewayMessageReactionRemoveEmojiDispatchData,
169
+ );
170
+ });
171
+
172
+ handlers.set('GUILD_CREATE', async (client, d) => {
173
+ const guildData = normalizeGuildPayload(d as unknown);
174
+ if (!guildData) return;
175
+ const guild = new Guild(client, guildData);
176
+ client.guilds.set(guild.id, guild);
177
+ const g = d as APIGuild & {
178
+ channels?: APIChannel[];
179
+ voice_states?: Array<{ user_id: string; channel_id: string | null }>;
180
+ members?: Array<APIGuildMember & { user: { id: string }; guild_id?: string }>;
181
+ };
182
+ for (const ch of g.channels ?? []) {
183
+ const channel = Channel.from(client, ch);
184
+ if (channel) {
185
+ client.channels.set(channel.id, channel);
186
+ guild.channels.set(channel.id, channel as GuildChannel);
187
+ }
188
+ }
189
+ for (const m of g.members ?? []) {
190
+ if (m?.user?.id) {
191
+ const memberData = { ...m, guild_id: guild.id };
192
+ const member = new GuildMember(client, memberData, guild);
193
+ guild.members.set(member.id, member);
194
+ }
195
+ }
196
+ client.emit(Events.GuildCreate, guild);
197
+ if (g.voice_states?.length) {
198
+ client.emit(Events.VoiceStatesSync, { guildId: guild.id, voiceStates: g.voice_states });
199
+ }
200
+ client._onGuildReceived(guild.id);
201
+ });
202
+
203
+ handlers.set('GUILD_UPDATE', async (client, d) => {
204
+ const guildData = normalizeGuildPayload(d as unknown);
205
+ if (!guildData) return;
206
+ const old = client.guilds.get(guildData.id);
207
+ const updated = new Guild(client, guildData);
208
+ client.guilds.set(updated.id, updated);
209
+ client.emit(Events.GuildUpdate, old ?? updated, updated);
210
+ });
211
+
212
+ handlers.set('GUILD_DELETE', async (client, d) => {
213
+ const g = d as { id: string };
214
+ const guild = client.guilds.get(g.id);
215
+ if (guild) {
216
+ client.guilds.delete(g.id);
217
+ client.emit(Events.GuildDelete, guild);
218
+ }
219
+ });
220
+
221
+ handlers.set('CHANNEL_CREATE', async (client, d) => {
222
+ const ch = Channel.from(client, d as APIChannel);
223
+ if (ch) {
224
+ client.channels.set(ch.id, ch);
225
+ if ('guildId' in ch && ch.guildId) {
226
+ const guild = client.guilds.get(ch.guildId);
227
+ if (guild) guild.channels.set(ch.id, ch as GuildChannel);
228
+ }
229
+ client.emit(Events.ChannelCreate, ch as GuildChannel);
230
+ }
231
+ });
232
+
233
+ handlers.set('CHANNEL_UPDATE', async (client, d) => {
234
+ const ch = d as APIChannel;
235
+ const oldCh = client.channels.get(ch.id);
236
+ const newCh = Channel.from(client, ch);
237
+ if (newCh) {
238
+ client.channels.set(newCh.id, newCh);
239
+ if ('guildId' in newCh && newCh.guildId) {
240
+ const guild = client.guilds.get(newCh.guildId);
241
+ if (guild) guild.channels.set(newCh.id, newCh as GuildChannel);
242
+ }
243
+ client.emit(Events.ChannelUpdate, oldCh ?? newCh, newCh);
244
+ }
245
+ });
246
+
247
+ handlers.set('CHANNEL_DELETE', async (client, d) => {
248
+ const ch = d as { id: string; guild_id?: string };
249
+ const channel = client.channels.get(ch.id);
250
+ if (channel) {
251
+ if ('guildId' in channel && channel.guildId) {
252
+ const guild = client.guilds.get(channel.guildId);
253
+ if (guild) guild.channels.delete(channel.id);
254
+ }
255
+ client.channels.delete(ch.id);
256
+ client.emit(Events.ChannelDelete, channel);
257
+ }
258
+ });
259
+
260
+ handlers.set('GUILD_MEMBER_ADD', async (client, d) => {
261
+ const data = d as APIGuildMember & { guild_id: string };
262
+ const guild = client.guilds.get(data.guild_id);
263
+ if (guild) {
264
+ const member = new GuildMember(client, data, guild);
265
+ guild.members.set(member.id, member);
266
+ client.emit(Events.GuildMemberAdd, member);
267
+ }
268
+ });
269
+
270
+ handlers.set('GUILD_MEMBER_UPDATE', async (client, d) => {
271
+ const data = d as APIGuildMember & { guild_id: string };
272
+ const guild = client.guilds.get(data.guild_id);
273
+ if (guild) {
274
+ const oldM = guild.members.get(data.user.id);
275
+ const newM = new GuildMember(client, data, guild);
276
+ guild.members.set(newM.id, newM);
277
+ client.emit(Events.GuildMemberUpdate, oldM ?? newM, newM);
278
+ }
279
+ });
280
+
281
+ handlers.set('GUILD_MEMBER_REMOVE', async (client, d) => {
282
+ const data = d as GatewayGuildMemberRemoveDispatchData;
283
+ const guild = client.guilds.get(data.guild_id);
284
+ if (!guild || !data.user?.id) return;
285
+
286
+ let member = guild.members.get(data.user.id);
287
+ if (member) {
288
+ guild.members.delete(data.user.id);
289
+ } else {
290
+ // Member was never cached (e.g. joined before bot cached guild). Build partial from payload
291
+ // so leave handlers run for all leaves, not only cached members.
292
+ const user: APIUserPartial = {
293
+ ...data.user,
294
+ id: data.user.id,
295
+ username: data.user.username ?? 'Unknown',
296
+ discriminator: data.user.discriminator ?? '0',
297
+ };
298
+ const memberData: APIGuildMember & { guild_id?: string } = {
299
+ user,
300
+ roles: [],
301
+ joined_at: new Date(0).toISOString(),
302
+ nick: null,
303
+ };
304
+ member = new GuildMember(client, memberData, guild);
305
+ }
306
+ client.emit(Events.GuildMemberRemove, member);
307
+ });
308
+
309
+ handlers.set('INTERACTION_CREATE', async (client, d) => {
310
+ client.emit(Events.InteractionCreate, d as APIApplicationCommandInteraction);
311
+ });
312
+
313
+ handlers.set('VOICE_STATE_UPDATE', async (client, d) => {
314
+ client.emit(Events.VoiceStateUpdate, d as GatewayVoiceStateUpdateDispatchData);
315
+ });
316
+
317
+ handlers.set('VOICE_SERVER_UPDATE', async (client, d) => {
318
+ client.emit(Events.VoiceServerUpdate, d as GatewayVoiceServerUpdateDispatchData);
319
+ });
320
+
321
+ handlers.set('MESSAGE_DELETE_BULK', async (client, d) => {
322
+ const data = d as GatewayMessageDeleteBulkDispatchData;
323
+ for (const id of data.ids ?? []) {
324
+ client._removeMessageFromCache(data.channel_id, id);
325
+ }
326
+ client.emit(Events.MessageDeleteBulk, data);
327
+ });
328
+
329
+ handlers.set('GUILD_BAN_ADD', async (client, d) => {
330
+ const data = d as GatewayGuildBanAddDispatchData;
331
+ const banData: APIBan & { guild_id?: string } = {
332
+ user: data.user,
333
+ reason: data.reason ?? null,
334
+ guild_id: data.guild_id,
335
+ };
336
+ const ban = new GuildBan(client, banData, data.guild_id);
337
+ client.emit(Events.GuildBanAdd, ban);
338
+ });
339
+
340
+ handlers.set('GUILD_BAN_REMOVE', async (client, d) => {
341
+ const data = d as GatewayGuildBanRemoveDispatchData;
342
+ const ban = new GuildBan(client, { ...data, reason: null }, data.guild_id);
343
+ client.emit(Events.GuildBanRemove, ban);
344
+ });
345
+
346
+ handlers.set('GUILD_EMOJIS_UPDATE', async (client, d) => {
347
+ const data = d as {
348
+ guild_id: string;
349
+ emojis: Array<{ id: string; name?: string; animated?: boolean }>;
350
+ };
351
+ const guild = client.guilds.get(data.guild_id);
352
+ if (guild) {
353
+ guild.emojis.clear();
354
+ for (const e of data.emojis ?? []) {
355
+ if (!e.id || e.name == null) continue;
356
+ guild.emojis.set(
357
+ e.id,
358
+ new GuildEmoji(
359
+ client,
360
+ { id: e.id, name: e.name, animated: e.animated ?? false, guild_id: guild.id },
361
+ guild.id,
362
+ ),
363
+ );
364
+ }
365
+ }
366
+ client.emit(Events.GuildEmojisUpdate, d);
367
+ });
368
+
369
+ handlers.set('GUILD_STICKERS_UPDATE', async (client, d) => {
370
+ client.emit(Events.GuildStickersUpdate, d);
371
+ });
372
+
373
+ handlers.set('GUILD_INTEGRATIONS_UPDATE', async (client, d) => {
374
+ client.emit(Events.GuildIntegrationsUpdate, d);
375
+ });
376
+
377
+ handlers.set('GUILD_ROLE_CREATE', async (client, d) => {
378
+ const data = d as GatewayGuildRoleCreateDispatchData;
379
+ const guild = client.guilds.get(data.guild_id);
380
+ if (guild) {
381
+ guild.roles.set(data.role.id, new Role(client, data.role, guild.id));
382
+ }
383
+ client.emit(Events.GuildRoleCreate, data);
384
+ });
385
+
386
+ handlers.set('GUILD_ROLE_UPDATE', async (client, d) => {
387
+ const data = d as GatewayGuildRoleUpdateDispatchData;
388
+ const guild = client.guilds.get(data.guild_id);
389
+ if (guild) {
390
+ const existing = guild.roles.get(data.role.id);
391
+ if (existing) {
392
+ existing._patch(data.role);
393
+ } else {
394
+ guild.roles.set(data.role.id, new Role(client, data.role, guild.id));
395
+ }
396
+ }
397
+ client.emit(Events.GuildRoleUpdate, data);
398
+ });
399
+
400
+ handlers.set('GUILD_ROLE_DELETE', async (client, d) => {
401
+ const data = d as GatewayGuildRoleDeleteDispatchData;
402
+ const guild = client.guilds.get(data.guild_id);
403
+ if (guild) guild.roles.delete(data.role_id);
404
+ client.emit(Events.GuildRoleDelete, data);
405
+ });
406
+
407
+ handlers.set('GUILD_SCHEDULED_EVENT_CREATE', async (client, d) => {
408
+ client.emit(Events.GuildScheduledEventCreate, d);
409
+ });
410
+
411
+ handlers.set('GUILD_SCHEDULED_EVENT_UPDATE', async (client, d) => {
412
+ client.emit(Events.GuildScheduledEventUpdate, d);
413
+ });
414
+
415
+ handlers.set('GUILD_SCHEDULED_EVENT_DELETE', async (client, d) => {
416
+ client.emit(Events.GuildScheduledEventDelete, d);
417
+ });
418
+
419
+ handlers.set('CHANNEL_PINS_UPDATE', async (client, d) => {
420
+ client.emit(Events.ChannelPinsUpdate, d);
421
+ });
422
+
423
+ handlers.set('INVITE_CREATE', async (client, d) => {
424
+ const data = normalizeInviteCreatePayload(client, d as GatewayInviteCreateDispatchData);
425
+ if (!data) {
426
+ client.emit(
427
+ Events.Debug,
428
+ '[Gateway] INVITE_CREATE payload had no invite code (documented as possibly empty)',
429
+ );
430
+ return;
431
+ }
432
+
433
+ client.emit(
434
+ Events.Debug,
435
+ `[Gateway] INVITE_CREATE code=${data.code} guild=${data.guild.id} channel=${data.channel.id}`,
436
+ );
437
+ client.emit(Events.InviteCreate, new Invite(client, data));
438
+ });
439
+
440
+ handlers.set('INVITE_DELETE', async (client, d) => {
441
+ client.emit(Events.InviteDelete, d as GatewayInviteDeleteDispatchData);
442
+ });
443
+
444
+ handlers.set('TYPING_START', async (client, d) => {
445
+ client.emit(Events.TypingStart, d as GatewayTypingStartDispatchData);
446
+ });
447
+
448
+ handlers.set('USER_UPDATE', async (client, d) => {
449
+ const data = d as GatewayUserUpdateDispatchData;
450
+ if (client.user?.id === data.id) {
451
+ client.user!._patch(data);
452
+ }
453
+ client.emit(Events.UserUpdate, data);
454
+ });
455
+
456
+ handlers.set('PRESENCE_UPDATE', async (client, d) => {
457
+ client.emit(Events.PresenceUpdate, d);
458
+ });
459
+
460
+ handlers.set('WEBHOOKS_UPDATE', async (client, d) => {
461
+ client.emit(Events.WebhooksUpdate, d);
462
+ });
463
+
464
+ handlers.set('RESUMED', async (client) => {
465
+ client.emit(Events.Resumed);
466
+ });
467
+
468
+ /** Registry of gateway dispatch event handlers. Add handlers via set() for extensibility. */
469
+ export const eventHandlers = handlers;
@@ -0,0 +1,79 @@
1
+ import { Collection } from '@erinjs/collection';
2
+ import { APIGuild, Routes } from '@erinjs/types';
3
+ import { Client } from './Client.js';
4
+ import { Guild } from '../structures/Guild.js';
5
+
6
+ /**
7
+ * Manages guilds with fetch.
8
+ * Extends Collection so you can use .get(), .set(), .filter(), etc.
9
+ */
10
+ export class GuildManager extends Collection<string, Guild> {
11
+ private readonly maxSize: number;
12
+
13
+ constructor(private readonly client: Client) {
14
+ super();
15
+ this.maxSize = client.options?.cache?.guilds ?? 0;
16
+ }
17
+
18
+ override set(key: string, value: Guild): this {
19
+ if (this.maxSize > 0 && this.size >= this.maxSize && !this.has(key)) {
20
+ const firstKey = this.keys().next().value;
21
+ if (firstKey !== undefined) this.delete(firstKey);
22
+ }
23
+ return super.set(key, value);
24
+ }
25
+
26
+ /**
27
+ * Get a guild from cache or fetch from the API if not present.
28
+ * Convenience helper to avoid repeating `client.guilds.get(id) ?? (await client.guilds.fetch(id))`.
29
+ * @param guildId - Snowflake of the guild
30
+ * @returns The guild, or null if not found
31
+ * @example
32
+ * const guild = await client.guilds.resolve(message.guildId);
33
+ * if (guild) console.log(guild.name);
34
+ */
35
+ async resolve(guildId: string): Promise<Guild | null> {
36
+ return this.get(guildId) ?? this.fetch(guildId);
37
+ }
38
+
39
+ /**
40
+ * Create a guild. POST /guilds.
41
+ * @param options - name (required), icon (base64), empty_features
42
+ * @returns The created guild
43
+ */
44
+ async create(options: {
45
+ name: string;
46
+ icon?: string | null;
47
+ empty_features?: boolean;
48
+ }): Promise<Guild> {
49
+ const data = await this.client.rest.post<APIGuild>(Routes.guilds(), {
50
+ body: options,
51
+ auth: true,
52
+ });
53
+ const guild = new Guild(this.client, data);
54
+ this.set(guild.id, guild);
55
+ return guild;
56
+ }
57
+
58
+ /**
59
+ * Fetch a guild by ID from the API (or return from cache if present).
60
+ * @param guildId - Snowflake of the guild
61
+ * @returns The guild, or null if not found
62
+ * @example
63
+ * const guild = await client.guilds.fetch(guildId);
64
+ * if (guild) console.log(guild.name);
65
+ */
66
+ async fetch(guildId: string): Promise<Guild | null> {
67
+ const cached = this.get(guildId);
68
+ if (cached) return cached;
69
+
70
+ try {
71
+ const data = await this.client.rest.get<APIGuild>(Routes.guild(guildId));
72
+ const guild = new Guild(this.client, data);
73
+ this.set(guild.id, guild);
74
+ return guild;
75
+ } catch {
76
+ return null;
77
+ }
78
+ }
79
+ }
@@ -0,0 +1,91 @@
1
+ import { Collection } from '@erinjs/collection';
2
+ import { APIGuildMember, Routes } from '@erinjs/types';
3
+ import { Guild } from '../structures/Guild.js';
4
+ import { GuildMember } from '../structures/GuildMember.js';
5
+
6
+ /**
7
+ * Manages guild members with a Collection-like API.
8
+ * Extends Collection so you can use .get(), .set(), .filter(), etc.
9
+ * Provides guild.members.me for Discord.js parity.
10
+ *
11
+ * @discordJsCompat https://discord.js.org/docs/packages/discord.js/main/GuildMemberManager
12
+ */
13
+ export class GuildMemberManager extends Collection<string, GuildMember> {
14
+ constructor(private readonly guild: Guild) {
15
+ super();
16
+ }
17
+
18
+ /**
19
+ * Get a guild member from cache or fetch from the API if not present.
20
+ * Convenience helper to avoid repeating `guild.members.get(userId) ?? (await guild.fetchMember(userId))`.
21
+ * @param userId - Snowflake of the user
22
+ * @returns The guild member
23
+ * @throws FluxerError with MEMBER_NOT_FOUND if user is not in the guild (404)
24
+ * @example
25
+ * const member = await guild.members.resolve(userId);
26
+ * console.log(member.displayName);
27
+ */
28
+ async resolve(userId: string): Promise<GuildMember> {
29
+ return this.get(userId) ?? this.guild.fetchMember(userId);
30
+ }
31
+
32
+ /**
33
+ * The current bot user as a GuildMember in this guild.
34
+ * Returns null if the bot's member is not cached or client.user is null.
35
+ * Use fetchMe() to load the bot's member when not cached.
36
+ *
37
+ * @discordJsCompat https://discord.js.org/docs/packages/discord.js/main/GuildMemberManager
38
+ * @example
39
+ * const perms = guild.members.me?.permissions;
40
+ * if (perms?.has(PermissionFlags.BanMembers)) { ... }
41
+ */
42
+ get me(): GuildMember | null {
43
+ const userId = this.guild.client.user?.id;
44
+ return userId ? (this.get(userId) ?? null) : null;
45
+ }
46
+
47
+ /**
48
+ * Fetch the current bot user as a GuildMember in this guild.
49
+ * Caches the result in guild.members.
50
+ *
51
+ * @throws Error if client.user is null (client not ready)
52
+ * @example
53
+ * const me = await guild.members.fetchMe();
54
+ * console.log(me.displayName);
55
+ */
56
+ async fetchMe(): Promise<GuildMember> {
57
+ const userId = this.guild.client.user?.id;
58
+ if (!userId) {
59
+ throw new Error('Cannot fetch me: client.user is null (client not ready)');
60
+ }
61
+ return this.guild.fetchMember(userId);
62
+ }
63
+
64
+ /**
65
+ * Fetch guild members with pagination. GET /guilds/{id}/members.
66
+ * @param options - limit (1-1000), after (user ID for pagination)
67
+ * @returns Array of GuildMember objects (cached in guild.members)
68
+ */
69
+ async fetch(options?: { limit?: number; after?: string }): Promise<GuildMember[]> {
70
+ const params = new URLSearchParams();
71
+ if (options?.limit != null) params.set('limit', String(options.limit));
72
+ if (options?.after) params.set('after', options.after);
73
+ const qs = params.toString();
74
+ const url = Routes.guildMembers(this.guild.id) + (qs ? `?${qs}` : '');
75
+ const data = await this.guild.client.rest.get<
76
+ APIGuildMember[] | { members?: APIGuildMember[] }
77
+ >(url, { auth: true });
78
+ const list = Array.isArray(data) ? data : (data?.members ?? []);
79
+ const members: GuildMember[] = [];
80
+ for (const m of list) {
81
+ const member = new GuildMember(
82
+ this.guild.client,
83
+ { ...m, guild_id: this.guild.id },
84
+ this.guild,
85
+ );
86
+ this.set(member.id, member);
87
+ members.push(member);
88
+ }
89
+ return members;
90
+ }
91
+ }
@@ -0,0 +1,58 @@
1
+ import { APIMessage, Routes } from '@erinjs/types';
2
+ import { FluxerAPIError, RateLimitError } from '@erinjs/rest';
3
+ import { FluxerError } from '../errors/FluxerError.js';
4
+ import { ErrorCodes } from '../errors/ErrorCodes.js';
5
+ import { Client } from './Client.js';
6
+ import { Message } from '../structures/Message';
7
+
8
+ /**
9
+ * Manages messages for a channel. Access via channel.messages.
10
+ * @example
11
+ * const message = channel.messages.get(messageId); // from cache (if enabled)
12
+ * const message = await channel.messages.fetch(messageId); // from API
13
+ * if (message) await message.edit({ content: 'Updated!' });
14
+ */
15
+ export class MessageManager {
16
+ constructor(
17
+ private readonly client: Client,
18
+ private readonly channelId: string,
19
+ ) {}
20
+
21
+ /**
22
+ * Get a message from cache. Returns undefined if not cached or caching is disabled.
23
+ * Requires options.cache.messages > 0.
24
+ * @param messageId - Snowflake of the message
25
+ */
26
+ get(messageId: string): Message | undefined {
27
+ const data = this.client._getMessageCache(this.channelId)?.get(messageId);
28
+ return data ? new Message(this.client, data) : undefined;
29
+ }
30
+
31
+ /**
32
+ * Fetch a message by ID from this channel.
33
+ * When message caching is enabled, the fetched message is added to the cache.
34
+ * @param messageId - Snowflake of the message
35
+ * @returns The message
36
+ * @throws FluxerError with MESSAGE_NOT_FOUND if the message does not exist
37
+ */
38
+ async fetch(messageId: string): Promise<Message> {
39
+ try {
40
+ const data = await this.client.rest.get<APIMessage>(
41
+ Routes.channelMessage(this.channelId, messageId),
42
+ );
43
+ this.client._addMessageToCache(this.channelId, data);
44
+ return new Message(this.client, data);
45
+ } catch (err) {
46
+ if (err instanceof RateLimitError) throw err;
47
+ if (err instanceof FluxerAPIError && err.statusCode === 404) {
48
+ throw new FluxerError(`Message ${messageId} not found in channel ${this.channelId}`, {
49
+ code: ErrorCodes.MessageNotFound,
50
+ cause: err,
51
+ });
52
+ }
53
+ throw err instanceof FluxerError
54
+ ? err
55
+ : new FluxerError(String(err), { cause: err as Error });
56
+ }
57
+ }
58
+ }