@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,109 @@
1
+ import { Snowflake } from '../common/snowflake.js';
2
+
3
+ /**
4
+ * Route builder helpers for REST API.
5
+ * All routes are relative to /v1
6
+ */
7
+ export const Routes = {
8
+ // Channels
9
+ channel: (id: Snowflake) => `/channels/${id}` as const,
10
+ channelMessages: (id: Snowflake) => `/channels/${id}/messages` as const,
11
+ channelMessage: (channelId: Snowflake, messageId: Snowflake) =>
12
+ `/channels/${channelId}/messages/${messageId}` as const,
13
+ channelMessageReactions: (channelId: Snowflake, messageId: Snowflake) =>
14
+ `/channels/${channelId}/messages/${messageId}/reactions` as const,
15
+ channelMessageReaction: (channelId: Snowflake, messageId: Snowflake, emoji: string) =>
16
+ `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}` as const,
17
+ channelPins: (id: Snowflake) => `/channels/${id}/messages/pins` as const,
18
+ /** Use channelPinMessage for PUT/DELETE pin operations. */
19
+ channelPin: (channelId: Snowflake, messageId: Snowflake) =>
20
+ `/channels/${channelId}/messages/pins/${messageId}` as const,
21
+ /** Pin/unpin: PUT or DELETE /channels/{id}/pins/{messageId}. Use for pin and unpin operations. */
22
+ channelPinMessage: (channelId: Snowflake, messageId: Snowflake) =>
23
+ `/channels/${channelId}/pins/${messageId}` as const,
24
+ channelBulkDelete: (id: Snowflake) => `/channels/${id}/messages/bulk-delete` as const,
25
+ channelWebhooks: (id: Snowflake) => `/channels/${id}/webhooks` as const,
26
+ channelTyping: (id: Snowflake) => `/channels/${id}/typing` as const,
27
+ channelInvites: (id: Snowflake) => `/channels/${id}/invites` as const,
28
+ channelPermission: (channelId: Snowflake, overwriteId: Snowflake) =>
29
+ `/channels/${channelId}/permissions/${overwriteId}` as const,
30
+ channelRecipient: (channelId: Snowflake, userId: Snowflake) =>
31
+ `/channels/${channelId}/recipients/${userId}` as const,
32
+ channelMessageAttachment: (channelId: Snowflake, messageId: Snowflake, attachmentId: Snowflake) =>
33
+ `/channels/${channelId}/messages/${messageId}/attachments/${attachmentId}` as const,
34
+
35
+ // Guilds
36
+ guilds: () => '/guilds' as const,
37
+ guild: (id: Snowflake) => `/guilds/${id}` as const,
38
+ guildDelete: (guildId: Snowflake) => `/guilds/${guildId}/delete` as const,
39
+ guildVanityUrl: (guildId: Snowflake) => `/guilds/${guildId}/vanity-url` as const,
40
+ guildTextChannelFlexibleNames: (guildId: Snowflake) =>
41
+ `/guilds/${guildId}/text-channel-flexible-names` as const,
42
+ guildDetachedBanner: (guildId: Snowflake) => `/guilds/${guildId}/detached-banner` as const,
43
+ guildDisallowUnclaimedAccounts: (guildId: Snowflake) =>
44
+ `/guilds/${guildId}/disallow-unclaimed-accounts` as const,
45
+ guildTransferOwnership: (guildId: Snowflake) => `/guilds/${guildId}/transfer-ownership` as const,
46
+ guildRolesHoistPositions: (guildId: Snowflake) =>
47
+ `/guilds/${guildId}/roles/hoist-positions` as const,
48
+ guildEmojisBulk: (guildId: Snowflake) => `/guilds/${guildId}/emojis/bulk` as const,
49
+ guildStickersBulk: (guildId: Snowflake) => `/guilds/${guildId}/stickers/bulk` as const,
50
+ guildChannels: (id: Snowflake) => `/guilds/${id}/channels` as const,
51
+ guildMembers: (id: Snowflake) => `/guilds/${id}/members` as const,
52
+ guildMember: (guildId: Snowflake, userId: Snowflake) =>
53
+ `/guilds/${guildId}/members/${userId}` as const,
54
+ guildMemberRole: (guildId: Snowflake, userId: Snowflake, roleId: Snowflake) =>
55
+ `/guilds/${guildId}/members/${userId}/roles/${roleId}` as const,
56
+ guildRoles: (id: Snowflake) => `/guilds/${id}/roles` as const,
57
+ guildRole: (guildId: Snowflake, roleId: Snowflake) =>
58
+ `/guilds/${guildId}/roles/${roleId}` as const,
59
+ guildBans: (id: Snowflake) => `/guilds/${id}/bans` as const,
60
+ guildBan: (guildId: Snowflake, userId: Snowflake) => `/guilds/${guildId}/bans/${userId}` as const,
61
+ guildInvites: (id: Snowflake) => `/guilds/${id}/invites` as const,
62
+ invite: (code: string) => `/invites/${encodeURIComponent(code)}` as const,
63
+ guildAuditLogs: (id: Snowflake) => `/guilds/${id}/audit-logs` as const,
64
+ guildEmojis: (id: Snowflake) => `/guilds/${id}/emojis` as const,
65
+ guildEmoji: (guildId: Snowflake, emojiId: Snowflake) =>
66
+ `/guilds/${guildId}/emojis/${emojiId}` as const,
67
+ guildStickers: (id: Snowflake) => `/guilds/${id}/stickers` as const,
68
+ guildSticker: (guildId: Snowflake, stickerId: Snowflake) =>
69
+ `/guilds/${guildId}/stickers/${stickerId}` as const,
70
+ guildWebhooks: (id: Snowflake) => `/guilds/${id}/webhooks` as const,
71
+ webhook: (id: Snowflake) => `/webhooks/${id}` as const,
72
+ webhookExecute: (id: Snowflake, token: string) => `/webhooks/${id}/${token}` as const,
73
+ webhookMessage: (id: Snowflake, token: string, messageId: Snowflake) =>
74
+ `/webhooks/${id}/${token}/messages/${messageId}` as const,
75
+
76
+ // Users
77
+ user: (id: Snowflake) => `/users/${id}` as const,
78
+ currentUser: () => `/users/@me` as const,
79
+ currentUserGuilds: () => `/users/@me/guilds` as const,
80
+ leaveGuild: (guildId: Snowflake) => `/users/@me/guilds/${guildId}` as const,
81
+ userMeChannels: () => `/users/@me/channels` as const,
82
+ /** GET /users/{id}/profile. Pass guildId for server-specific profile. */
83
+ userProfile: (id: Snowflake, guildId?: Snowflake): string =>
84
+ guildId ? `/users/${id}/profile?guild_id=${guildId}` : `/users/${id}/profile`,
85
+
86
+ // Instance (unauthenticated)
87
+ instanceDiscovery: () => '/.well-known/fluxer' as const,
88
+ instance: () => '/instance' as const,
89
+
90
+ // Gateway
91
+ gatewayBot: () => `/gateway/bot` as const,
92
+
93
+ // Streams (voice channel screen share preview)
94
+ streamPreview: (streamKey: string) =>
95
+ `/streams/${encodeURIComponent(streamKey)}/preview` as const,
96
+
97
+ // Application commands (slash commands)
98
+ applicationCommands: (applicationId: Snowflake) =>
99
+ `/applications/${applicationId}/commands` as const,
100
+ applicationCommand: (applicationId: Snowflake, commandId: Snowflake) =>
101
+ `/applications/${applicationId}/commands/${commandId}` as const,
102
+ interactionCallback: (interactionId: Snowflake, interactionToken: string) =>
103
+ `/interactions/${interactionId}/${interactionToken}/callback` as const,
104
+
105
+ // OAuth2 / Bot
106
+ oauth2ApplicationBot: (id: Snowflake) => `/oauth2/applications/${id}/bot` as const,
107
+ oauth2ApplicationBotResetToken: (id: Snowflake) =>
108
+ `/oauth2/applications/${id}/bot/reset-token` as const,
109
+ } as const;
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src",
6
+ "noEmit": false
7
+ },
8
+ "include": ["src/**/*"]
9
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ format: ['cjs', 'esm'],
6
+ dts: true,
7
+ splitting: false,
8
+ clean: true,
9
+ });
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ environment: 'node',
7
+ include: ['src/**/*.test.ts'],
8
+ },
9
+ });
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@erinjs/util",
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
6
+ "version": "1.2.4",
7
+ "description": "Shared utilities for @erinjs/core",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/blstmo-abandoned-us-for-the-milk/core.git",
11
+ "directory": "packages/util"
12
+ },
13
+ "bugs": "https://github.com/blstmo-abandoned-us-for-the-milk/core/issues",
14
+ "homepage": "https://github.com/blstmo-abandoned-us-for-the-milk/core#readme",
15
+ "keywords": [
16
+ "fluxer",
17
+ "util",
18
+ "snowflake",
19
+ "bitfield"
20
+ ],
21
+ "license": "Apache-2.0",
22
+ "dependencies": {
23
+ "@erinjs/types": "workspace:*"
24
+ },
25
+ "main": "./dist/index.js",
26
+ "module": "./dist/index.mjs",
27
+ "types": "./dist/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.mjs",
32
+ "require": "./dist/index.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "scripts": {
39
+ "build": "pnpm exec tsx ../../scripts/generate-emoji-shortcodes.ts && tsup",
40
+ "clean": "rm -rf dist",
41
+ "lint": "eslint src --max-warnings 0 --config ../../eslint.config.js",
42
+ "lint:fix": "eslint src --fix --config ../../eslint.config.js",
43
+ "test": "vitest run",
44
+ "test:coverage": "vitest run --coverage"
45
+ },
46
+ "devDependencies": {
47
+ "tsup": "^8.3.0",
48
+ "typescript": "^5.6.0",
49
+ "vitest": "^4.0.18"
50
+ }
51
+ }
@@ -0,0 +1,96 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { BitField } from './BitField.js';
3
+
4
+ // Minimal BitField subclass for testing
5
+ class TestBitField extends BitField<'A' | 'B' | 'C'> {
6
+ static override Flags = { A: 1n, B: 2n, C: 4n };
7
+ }
8
+
9
+ describe('BitField', () => {
10
+ it('creates with default bit 0', () => {
11
+ const bf = new TestBitField();
12
+ expect(bf.bitfield).toBe(0n);
13
+ });
14
+
15
+ it('resolves number', () => {
16
+ const bf = new TestBitField(3);
17
+ expect(bf.bitfield).toBe(3n);
18
+ });
19
+
20
+ it('resolves string flag', () => {
21
+ const bf = new TestBitField('A');
22
+ expect(bf.bitfield).toBe(1n);
23
+ });
24
+
25
+ it('resolves array of flags with OR', () => {
26
+ const bf = new TestBitField(['A', 'B']);
27
+ expect(bf.bitfield).toBe(3n); // 1 | 2
28
+ });
29
+
30
+ it('has checks single bit', () => {
31
+ const bf = new TestBitField(['A', 'B']);
32
+ expect(bf.has('A')).toBe(true);
33
+ expect(bf.has('B')).toBe(true);
34
+ expect(bf.has('C')).toBe(false);
35
+ });
36
+
37
+ it('has checks number', () => {
38
+ const bf = new TestBitField(3);
39
+ expect(bf.has(2)).toBe(true);
40
+ });
41
+
42
+ it('has requires all bits for composite checks', () => {
43
+ const bf = new TestBitField('A');
44
+ expect(bf.has(['A', 'B'])).toBe(false);
45
+ bf.add('B');
46
+ expect(bf.has(['A', 'B'])).toBe(true);
47
+ });
48
+
49
+ it('resolves numeric bigint string literal', () => {
50
+ const bf = new TestBitField('8');
51
+ expect(bf.bitfield).toBe(8n);
52
+ });
53
+
54
+ it('add sets bits', () => {
55
+ const bf = new TestBitField('A').add('B');
56
+ expect(bf.bitfield).toBe(3n);
57
+ });
58
+
59
+ it('remove unsets bits', () => {
60
+ const bf = new TestBitField(['A', 'B', 'C']).remove('B');
61
+ expect(bf.bitfield).toBe(5n); // A | C
62
+ });
63
+
64
+ it('serialize returns object', () => {
65
+ const bf = new TestBitField(['A', 'C']);
66
+ const s = bf.serialize();
67
+ expect(s).toEqual({ A: true, B: false, C: true });
68
+ });
69
+
70
+ it('toArray returns enabled flags', () => {
71
+ const bf = new TestBitField(['A', 'C']);
72
+ expect(bf.toArray()).toEqual(['A', 'C']);
73
+ });
74
+
75
+ it('toJSON returns serialized string', () => {
76
+ const bf = new TestBitField(5);
77
+ expect(bf.toJSON()).toBe('5');
78
+ });
79
+
80
+ it('equals compares bitfields', () => {
81
+ const a = new TestBitField(['A', 'B']);
82
+ const b = new TestBitField(3);
83
+ const c = new TestBitField('A');
84
+ expect(a.equals(b)).toBe(true);
85
+ expect(a.equals(c)).toBe(false);
86
+ });
87
+
88
+ it('freeze returns frozen instance', () => {
89
+ const bf = new TestBitField('A').freeze();
90
+ expect(Object.isFrozen(bf)).toBe(true);
91
+ });
92
+
93
+ it('throws for invalid flag string', () => {
94
+ expect(() => new TestBitField('Invalid' as 'A')).toThrow(RangeError);
95
+ });
96
+ });
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Data structure that allows efficient storage of multiple flags (bits) in a single number.
3
+ *
4
+ * Note: JavaScript bitwise operations (|, &, ^, <<, >>) operate on 32-bit signed integers.
5
+ * Flags with values exceeding 2^30 may exhibit unexpected behavior. For permission-style
6
+ * bitfields with more than 30 bits, consider using BigInt-based implementations.
7
+ */
8
+ export type BitFieldResolvable<S extends string> =
9
+ | S
10
+ | bigint
11
+ | number
12
+ | BitField<S>
13
+ | (S | number | bigint | BitField<S>)[];
14
+
15
+ export class BitField<S extends string> {
16
+ static Flags: Record<string, bigint> = {};
17
+ defaultBit = 0;
18
+ bitfield: bigint;
19
+
20
+ constructor(bits: BitFieldResolvable<S> = 0) {
21
+ this.bitfield = (this.constructor as typeof BitField).resolve(bits);
22
+ }
23
+
24
+ get [Symbol.toStringTag](): string {
25
+ return `BitField${this.bitfield}`;
26
+ }
27
+
28
+ static resolve<S extends string>(bits: BitFieldResolvable<S>): bigint {
29
+ if (typeof bits === 'number' && bits >= 0) return BigInt(bits);
30
+ if (typeof bits === 'bigint' && bits >= 0n) return bits;
31
+ if (bits instanceof BitField) return bits.bitfield;
32
+ if (Array.isArray(bits))
33
+ return bits.map((b) => this.resolve(b)).reduce((a, b) => BigInt(a) | BigInt(b), 0n);
34
+ if (typeof bits === 'string') {
35
+ // If the string matches a known flag name, return its bigint value
36
+ if (bits in this.Flags) {
37
+ return this.Flags[bits as S];
38
+ }
39
+
40
+ // Otherwise, try to interpret the string as a valid non-negative bigint literal
41
+ try {
42
+ const value = BigInt(bits);
43
+ if (value >= 0n) return value;
44
+ } catch {
45
+ // fall through to error below
46
+ }
47
+ }
48
+ throw new RangeError(`Invalid bitfield flag or number: ${bits}`);
49
+ }
50
+
51
+ has(bit: BitFieldResolvable<S>): boolean {
52
+ bit = (this.constructor as typeof BitField).resolve(bit);
53
+ return (this.bitfield & bit) === bit;
54
+ }
55
+
56
+ add(...bits: BitFieldResolvable<S>[]): this {
57
+ let total = 0n;
58
+ for (const bit of bits) {
59
+ total |= (this.constructor as typeof BitField).resolve(bit);
60
+ }
61
+ this.bitfield |= total;
62
+ return this;
63
+ }
64
+
65
+ remove(...bits: BitFieldResolvable<S>[]): this {
66
+ let total = 0n;
67
+ for (const bit of bits) {
68
+ total |= (this.constructor as typeof BitField).resolve(bit);
69
+ }
70
+ this.bitfield &= ~total;
71
+ return this;
72
+ }
73
+
74
+ serialize(): Record<S, boolean> {
75
+ const Flags = (this.constructor as typeof BitField).Flags as Record<S, bigint>;
76
+ const serialized: Record<string, boolean> = {};
77
+ for (const [key, value] of Object.entries(Flags) as [S, bigint][]) {
78
+ serialized[key as string] = (this.bitfield & value) === value;
79
+ }
80
+ return serialized as Record<S, boolean>;
81
+ }
82
+
83
+ toArray(): S[] {
84
+ const Flags = (this.constructor as typeof BitField).Flags as Record<S, bigint>;
85
+ return (Object.entries(Flags) as [S, bigint][])
86
+ .filter(([, value]) => (this.bitfield & value) === value)
87
+ .map(([key]) => key);
88
+ }
89
+
90
+ toJSON() {
91
+ return this.bitfield.toString();
92
+ }
93
+
94
+ valueOf() {
95
+ return this.bitfield.toString();
96
+ }
97
+
98
+ equals(bitfield: BitField<S>): boolean {
99
+ return this.bitfield === bitfield.bitfield;
100
+ }
101
+
102
+ freeze(): Readonly<BitField<S>> {
103
+ return Object.freeze(this);
104
+ }
105
+ }
@@ -0,0 +1,42 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { MessageFlagsBitField, MessageFlagsBits } from './MessageFlagsBitField.js';
3
+
4
+ describe('MessageFlagsBitField', () => {
5
+ it('creates with default 0', () => {
6
+ const bf = new MessageFlagsBitField();
7
+ expect(bf.bitfield).toBe(0n);
8
+ });
9
+
10
+ it('has checks SuppressEmbeds', () => {
11
+ const bf = new MessageFlagsBitField([MessageFlagsBits.SuppressEmbeds]);
12
+ expect(bf.has(MessageFlagsBits.SuppressEmbeds)).toBe(true);
13
+ expect(bf.has(MessageFlagsBits.VoiceMessage)).toBe(false);
14
+ });
15
+
16
+ it('add and remove', () => {
17
+ const bf = new MessageFlagsBitField()
18
+ .add(MessageFlagsBits.SuppressEmbeds)
19
+ .add(MessageFlagsBits.SuppressNotifications);
20
+ expect(bf.has(MessageFlagsBits.SuppressEmbeds)).toBe(true);
21
+ bf.remove(MessageFlagsBits.SuppressEmbeds);
22
+ expect(bf.has(MessageFlagsBits.SuppressEmbeds)).toBe(false);
23
+ });
24
+
25
+ it('serialize returns flags object', () => {
26
+ const bf = new MessageFlagsBitField([MessageFlagsBits.VoiceMessage]);
27
+ const s = bf.serialize();
28
+ expect(s.VoiceMessage).toBe(true);
29
+ expect(s.SuppressEmbeds).toBe(false);
30
+ });
31
+
32
+ it('toArray returns enabled flag names', () => {
33
+ const bf = new MessageFlagsBitField([
34
+ MessageFlagsBits.CompactAttachments,
35
+ MessageFlagsBits.SuppressEmbeds,
36
+ ]);
37
+ const arr = bf.toArray();
38
+ expect(arr).toContain('CompactAttachments');
39
+ expect(arr).toContain('SuppressEmbeds');
40
+ expect(arr).toHaveLength(2);
41
+ });
42
+ });
@@ -0,0 +1,20 @@
1
+ import { BitField, type BitFieldResolvable } from './BitField.js';
2
+
3
+ /**
4
+ * Message flag bit values matching the API MessageFlags schema (openapi.json).
5
+ * Format: int32.
6
+ */
7
+ export const MessageFlagsBits = {
8
+ SuppressEmbeds: 1n << 2n, // 4
9
+ SuppressNotifications: 1n << 12n, // 4096
10
+ VoiceMessage: 1n << 13n, // 8192
11
+ CompactAttachments: 1n << 17n, // 131072
12
+ } as const;
13
+
14
+ export type MessageFlagsString = keyof typeof MessageFlagsBits;
15
+
16
+ export class MessageFlagsBitField extends BitField<MessageFlagsString> {
17
+ static override Flags = MessageFlagsBits;
18
+ }
19
+
20
+ export type MessageFlagsResolvable = BitFieldResolvable<MessageFlagsString>;
@@ -0,0 +1,79 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import {
3
+ resolvePermissionsToBitfield,
4
+ PermissionFlags,
5
+ PermissionsBitField,
6
+ } from './PermissionsBitField.js';
7
+
8
+ describe('resolvePermissionsToBitfield', () => {
9
+ it('returns string as-is when it looks like a number', () => {
10
+ expect(resolvePermissionsToBitfield('2048')).toBe('2048');
11
+ expect(resolvePermissionsToBitfield('8933636165185')).toBe('8933636165185');
12
+ });
13
+
14
+ it('resolves PermissionString to bitfield', () => {
15
+ expect(resolvePermissionsToBitfield('SendMessages')).toBe('2048');
16
+ expect(resolvePermissionsToBitfield('Administrator')).toBe('8');
17
+ });
18
+
19
+ it('resolves number to string', () => {
20
+ expect(resolvePermissionsToBitfield(2048)).toBe('2048');
21
+ expect(resolvePermissionsToBitfield(PermissionFlags.SendMessages)).toBe('2048');
22
+ });
23
+
24
+ it('resolves bigint to string', () => {
25
+ expect(resolvePermissionsToBitfield(2048n)).toBe('2048');
26
+ });
27
+
28
+ it('resolves array of permissions with OR', () => {
29
+ const result = resolvePermissionsToBitfield(['SendMessages', 'ViewChannel']);
30
+ expect(result).toBe(String(2048 | 1024)); // 3072
31
+ });
32
+
33
+ it('resolves PermissionsBitField instance', () => {
34
+ const bf = new PermissionsBitField([PermissionFlags.BanMembers]);
35
+ expect(resolvePermissionsToBitfield(bf)).toBe('4');
36
+ });
37
+
38
+ it('throws for invalid permission string', () => {
39
+ expect(() => resolvePermissionsToBitfield('InvalidPermission')).toThrow(RangeError);
40
+ });
41
+ });
42
+
43
+ describe('PermissionsBitField', () => {
44
+ it('uses the intended bit positions for high-bit permissions', () => {
45
+ expect(PermissionFlags.UseExternalStickers).toBe(1n << 37n);
46
+ expect(PermissionFlags.ModerateMembers).toBe(1n << 40n);
47
+ expect(PermissionFlags.CreateExpressions).toBe(1n << 43n);
48
+ expect(PermissionFlags.PinMessages).toBe(1n << 51n);
49
+ expect(PermissionFlags.BypassSlowmode).toBe(1n << 52n);
50
+ expect(PermissionFlags.UpdateRtcRegion).toBe(1n << 53n);
51
+ });
52
+
53
+ it('has checks single permission', () => {
54
+ const bf = new PermissionsBitField([PermissionFlags.SendMessages]);
55
+ expect(bf.has(PermissionFlags.SendMessages)).toBe(true);
56
+ expect(bf.has(PermissionFlags.BanMembers)).toBe(false);
57
+ });
58
+
59
+ it('has checks Administrator flag', () => {
60
+ const bf = new PermissionsBitField([PermissionFlags.Administrator]);
61
+ expect(bf.has(PermissionFlags.Administrator)).toBe(true);
62
+ expect(bf.has(PermissionFlags.BanMembers)).toBe(false);
63
+ });
64
+
65
+ it('toArray returns permission names', () => {
66
+ const bf = new PermissionsBitField([PermissionFlags.SendMessages, PermissionFlags.ViewChannel]);
67
+ const arr = bf.toArray();
68
+ expect(arr).toContain('SendMessages');
69
+ expect(arr).toContain('ViewChannel');
70
+ expect(arr.length).toBe(2);
71
+ });
72
+
73
+ it('serialize returns permission object', () => {
74
+ const bf = new PermissionsBitField([PermissionFlags.BanMembers]);
75
+ const s = bf.serialize();
76
+ expect(s.BanMembers).toBe(true);
77
+ expect(s.SendMessages).toBe(false);
78
+ });
79
+ });
@@ -0,0 +1,97 @@
1
+ import { BitField, type BitFieldResolvable } from './BitField.js';
2
+
3
+ /**
4
+ * Permission flags aligned with Fluxer API (fluxer_api/src/constants/Channel.ts).
5
+ * Bit positions use BigInt shifts (1n << n).
6
+ * Administrator (bit 3) implies all permissions. Guild owner bypasses role computation.
7
+ *
8
+ * @example
9
+ * if (member.permissions.has(PermissionFlags.BanMembers)) { ... }
10
+ * if (perms.has(PermissionFlags.Administrator)) { ... }
11
+ */
12
+ export const PermissionFlags = {
13
+ CreateInstantInvite: 1n << 0n,
14
+ KickMembers: 1n << 1n,
15
+ BanMembers: 1n << 2n,
16
+ Administrator: 1n << 3n,
17
+ ManageChannels: 1n << 4n,
18
+ ManageGuild: 1n << 5n,
19
+ AddReactions: 1n << 6n,
20
+ ViewAuditLog: 1n << 7n,
21
+ PrioritySpeaker: 1n << 8n,
22
+ Stream: 1n << 9n,
23
+ ViewChannel: 1n << 10n,
24
+ SendMessages: 1n << 11n,
25
+ SendTtsMessages: 1n << 12n,
26
+ ManageMessages: 1n << 13n,
27
+ EmbedLinks: 1n << 14n,
28
+ AttachFiles: 1n << 15n,
29
+ ReadMessageHistory: 1n << 16n,
30
+ MentionEveryone: 1n << 17n,
31
+ UseExternalEmojis: 1n << 18n,
32
+ Connect: 1n << 20n,
33
+ Speak: 1n << 21n,
34
+ MuteMembers: 1n << 22n,
35
+ DeafenMembers: 1n << 23n,
36
+ MoveMembers: 1n << 24n,
37
+ UseVad: 1n << 25n,
38
+ ChangeNickname: 1n << 26n,
39
+ ManageNicknames: 1n << 27n,
40
+ ManageRoles: 1n << 28n,
41
+ ManageWebhooks: 1n << 29n,
42
+ ManageEmojisAndStickers: 1n << 30n,
43
+ ManageExpressions: 1n << 30n,
44
+ UseExternalStickers: 1n << 37n,
45
+ ModerateMembers: 1n << 40n,
46
+ CreateExpressions: 1n << 43n,
47
+ PinMessages: 1n << 51n,
48
+ BypassSlowmode: 1n << 52n,
49
+ UpdateRtcRegion: 1n << 53n,
50
+ } as const;
51
+
52
+ /** BigInt OR of all permission flags. Used for guild owner override (owner has all perms). */
53
+ export const ALL_PERMISSIONS_BIGINT = Object.values(PermissionFlags).reduce((a, b) => a | b, 0n);
54
+
55
+ export type PermissionString = keyof typeof PermissionFlags;
56
+
57
+ export class PermissionsBitField extends BitField<PermissionString> {
58
+ static override Flags = PermissionFlags;
59
+ }
60
+
61
+ export type PermissionResolvable = BitFieldResolvable<PermissionString>;
62
+
63
+ /**
64
+ * Resolve permission(s) to an API bitfield string. Uses BigInt to avoid overflow for flags > 2^31.
65
+ * @param perms - Permission string (e.g. "2048"), number, PermissionString, array of permissions, or PermissionsBitField
66
+ * @returns String bitfield for API (e.g. "8933636165185")
67
+ * @example
68
+ * resolvePermissionsToBitfield('2048'); // "2048"
69
+ * resolvePermissionsToBitfield(PermissionFlags.SendMessages); // "2048"
70
+ * resolvePermissionsToBitfield(['SendMessages', 'ViewChannel']); // combined bitfield
71
+ */
72
+ export function resolvePermissionsToBitfield(perms: PermissionResolvable): string {
73
+ if (typeof perms === 'string') {
74
+ const num = Number(perms);
75
+ if (!Number.isNaN(num) && perms.trim() !== '') return perms;
76
+ const mapped = PermissionFlags[perms];
77
+ if (mapped !== undefined) return String(mapped);
78
+ throw new RangeError(`Invalid permission string: ${perms}`);
79
+ }
80
+ if (typeof perms === 'number') return String(perms);
81
+ if (typeof perms === 'bigint') return String(perms);
82
+ if (perms instanceof PermissionsBitField) return String(BigInt(perms.bitfield));
83
+ if (Array.isArray(perms)) {
84
+ let acc = 0n;
85
+ for (const p of perms) {
86
+ let v: bigint;
87
+ if (typeof p === 'number') v = BigInt(p);
88
+ else if (typeof p === 'string') {
89
+ const mapped = PermissionFlags[p];
90
+ v = mapped !== undefined ? BigInt(mapped) : BigInt(Number(p) || 0);
91
+ } else v = BigInt((p as PermissionsBitField).bitfield);
92
+ acc |= v;
93
+ }
94
+ return String(acc);
95
+ }
96
+ throw new RangeError(`Invalid permission resolvable: ${perms}`);
97
+ }