@erinjs/core 1.0.0 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (394) hide show
  1. package/{core/LICENSE → LICENSE} +203 -203
  2. package/README.md +46 -0
  3. package/dist/index.d.mts +2084 -0
  4. package/dist/index.d.ts +2084 -0
  5. package/dist/index.js +3867 -0
  6. package/dist/index.mjs +3809 -0
  7. package/package.json +50 -15
  8. package/core/.changeset/README.md +0 -8
  9. package/core/.changeset/community-bootstrap-release.md +0 -17
  10. package/core/.changeset/config.json +0 -11
  11. package/core/.changeset/no-changelog.js +0 -16
  12. package/core/.changeset/pre.json +0 -17
  13. package/core/.editorconfig +0 -13
  14. package/core/.gitattributes +0 -2
  15. package/core/.github/CODE_OF_CONDUCT.md +0 -23
  16. package/core/.github/FUNDING.yml +0 -7
  17. package/core/.github/ISSUE_TEMPLATE/bug_report.md +0 -31
  18. package/core/.github/ISSUE_TEMPLATE/feature_request.md +0 -23
  19. package/core/.github/PULL_REQUEST_TEMPLATE.md +0 -16
  20. package/core/.github/dependabot.yml +0 -16
  21. package/core/.github/workflows/autoapp.yml +0 -16
  22. package/core/.github/workflows/ci.yml +0 -187
  23. package/core/.github/workflows/codeql.yml +0 -30
  24. package/core/.github/workflows/deploy-docs.yml +0 -54
  25. package/core/.github/workflows/publish.yml +0 -43
  26. package/core/.lintstagedrc.json +0 -4
  27. package/core/.nvmrc +0 -1
  28. package/core/.prettierignore +0 -8
  29. package/core/.prettierrc +0 -11
  30. package/core/CONTRIBUTING.md +0 -70
  31. package/core/README.md +0 -61
  32. package/core/SECURITY.md +0 -21
  33. package/core/apps/docs/index.html +0 -28
  34. package/core/apps/docs/middleware.ts +0 -21
  35. package/core/apps/docs/package.json +0 -33
  36. package/core/apps/docs/public/@flux.png +0 -0
  37. package/core/apps/docs/public/docs/latest/guides.json +0 -1420
  38. package/core/apps/docs/public/docs/latest/main.json +0 -14981
  39. package/core/apps/docs/public/docs/latest/rag-index.json +0 -1
  40. package/core/apps/docs/public/docs/v1.0.5/guides.json +0 -226
  41. package/core/apps/docs/public/docs/v1.0.5/main.json +0 -7920
  42. package/core/apps/docs/public/docs/v1.0.6/guides.json +0 -226
  43. package/core/apps/docs/public/docs/v1.0.6/main.json +0 -7920
  44. package/core/apps/docs/public/docs/v1.0.7/guides.json +0 -259
  45. package/core/apps/docs/public/docs/v1.0.7/main.json +0 -8652
  46. package/core/apps/docs/public/docs/v1.0.8/guides.json +0 -313
  47. package/core/apps/docs/public/docs/v1.0.8/main.json +0 -9618
  48. package/core/apps/docs/public/docs/v1.0.9/guides.json +0 -319
  49. package/core/apps/docs/public/docs/v1.0.9/main.json +0 -10694
  50. package/core/apps/docs/public/docs/v1.1.0/guides.json +0 -589
  51. package/core/apps/docs/public/docs/v1.1.0/main.json +0 -12576
  52. package/core/apps/docs/public/docs/v1.1.2/guides.json +0 -650
  53. package/core/apps/docs/public/docs/v1.1.2/main.json +0 -13239
  54. package/core/apps/docs/public/docs/v1.1.3/guides.json +0 -650
  55. package/core/apps/docs/public/docs/v1.1.3/main.json +0 -13239
  56. package/core/apps/docs/public/docs/v1.1.4/guides.json +0 -708
  57. package/core/apps/docs/public/docs/v1.1.4/main.json +0 -13231
  58. package/core/apps/docs/public/docs/v1.1.5/guides.json +0 -1035
  59. package/core/apps/docs/public/docs/v1.1.5/main.json +0 -13838
  60. package/core/apps/docs/public/docs/v1.1.6/guides.json +0 -1041
  61. package/core/apps/docs/public/docs/v1.1.6/main.json +0 -14313
  62. package/core/apps/docs/public/docs/v1.1.8/guides.json +0 -1047
  63. package/core/apps/docs/public/docs/v1.1.8/main.json +0 -14421
  64. package/core/apps/docs/public/docs/v1.1.9/guides.json +0 -1047
  65. package/core/apps/docs/public/docs/v1.1.9/main.json +0 -14421
  66. package/core/apps/docs/public/docs/v1.2.0/guides.json +0 -1212
  67. package/core/apps/docs/public/docs/v1.2.0/main.json +0 -14663
  68. package/core/apps/docs/public/docs/v1.2.1/guides.json +0 -1293
  69. package/core/apps/docs/public/docs/v1.2.1/main.json +0 -14828
  70. package/core/apps/docs/public/docs/v1.2.2/guides.json +0 -1293
  71. package/core/apps/docs/public/docs/v1.2.2/main.json +0 -15025
  72. package/core/apps/docs/public/docs/v1.2.3/guides.json +0 -1420
  73. package/core/apps/docs/public/docs/v1.2.3/main.json +0 -14954
  74. package/core/apps/docs/public/docs/v1.2.4/guides.json +0 -1420
  75. package/core/apps/docs/public/docs/v1.2.4/main.json +0 -14981
  76. package/core/apps/docs/public/docs/versions.json +0 -24
  77. package/core/apps/docs/public/flux.png +0 -0
  78. package/core/apps/docs/public/locales/en.json +0 -50
  79. package/core/apps/docs/public/locales/guides-en.json +0 -512
  80. package/core/apps/docs/public/robots.txt +0 -4
  81. package/core/apps/docs/public/sitemap.xml +0 -33
  82. package/core/apps/docs/src/App.vue +0 -538
  83. package/core/apps/docs/src/components/ApiCategorySection.vue +0 -42
  84. package/core/apps/docs/src/components/ApiDiscordCompat.vue +0 -65
  85. package/core/apps/docs/src/components/ApiEndpointCard.vue +0 -313
  86. package/core/apps/docs/src/components/ApiSchemaBlock.vue +0 -131
  87. package/core/apps/docs/src/components/CodeBlock.vue +0 -177
  88. package/core/apps/docs/src/components/CommunityCallout.vue +0 -90
  89. package/core/apps/docs/src/components/ConstructorSection.vue +0 -82
  90. package/core/apps/docs/src/components/DocDescription.vue +0 -40
  91. package/core/apps/docs/src/components/FluxerLogo.vue +0 -3
  92. package/core/apps/docs/src/components/Footer.vue +0 -106
  93. package/core/apps/docs/src/components/GuideCodeBlock.vue +0 -102
  94. package/core/apps/docs/src/components/GuideDiscordCompat.vue +0 -77
  95. package/core/apps/docs/src/components/GuideDiscordCompatCallout.vue +0 -83
  96. package/core/apps/docs/src/components/GuideTable.vue +0 -77
  97. package/core/apps/docs/src/components/GuideTip.vue +0 -38
  98. package/core/apps/docs/src/components/MethodsSection.vue +0 -195
  99. package/core/apps/docs/src/components/ParamsTable.vue +0 -70
  100. package/core/apps/docs/src/components/PropertiesSection.vue +0 -143
  101. package/core/apps/docs/src/components/SearchBar.vue +0 -76
  102. package/core/apps/docs/src/components/SearchModal.vue +0 -361
  103. package/core/apps/docs/src/components/SidebarNav.vue +0 -225
  104. package/core/apps/docs/src/components/SponsorBanner.vue +0 -153
  105. package/core/apps/docs/src/components/TypeSignature.vue +0 -187
  106. package/core/apps/docs/src/components/VersionPicker.vue +0 -191
  107. package/core/apps/docs/src/composables/useSearchIndex.ts +0 -144
  108. package/core/apps/docs/src/composables/useVersionedPath.ts +0 -20
  109. package/core/apps/docs/src/data/apiEndpoints.ts +0 -1073
  110. package/core/apps/docs/src/data/changelog.ts +0 -717
  111. package/core/apps/docs/src/data/guides.ts +0 -2362
  112. package/core/apps/docs/src/env.d.ts +0 -7
  113. package/core/apps/docs/src/locales/guides-en.json +0 -512
  114. package/core/apps/docs/src/main.ts +0 -27
  115. package/core/apps/docs/src/pages/ApiReferenceLayout.vue +0 -175
  116. package/core/apps/docs/src/pages/ApiReferencePage.vue +0 -128
  117. package/core/apps/docs/src/pages/Changelog.vue +0 -288
  118. package/core/apps/docs/src/pages/ClassPage.vue +0 -319
  119. package/core/apps/docs/src/pages/ClassesList.vue +0 -100
  120. package/core/apps/docs/src/pages/DocsLayout.vue +0 -127
  121. package/core/apps/docs/src/pages/GuidePage.vue +0 -279
  122. package/core/apps/docs/src/pages/GuidesIndex.vue +0 -166
  123. package/core/apps/docs/src/pages/GuidesLayout.vue +0 -245
  124. package/core/apps/docs/src/pages/Home.vue +0 -125
  125. package/core/apps/docs/src/pages/NotFound.vue +0 -57
  126. package/core/apps/docs/src/pages/TypedefPage.vue +0 -230
  127. package/core/apps/docs/src/pages/TypedefsList.vue +0 -168
  128. package/core/apps/docs/src/pages/VersionLayout.vue +0 -15
  129. package/core/apps/docs/src/router.ts +0 -73
  130. package/core/apps/docs/src/stores/docs.ts +0 -54
  131. package/core/apps/docs/src/stores/guides.ts +0 -53
  132. package/core/apps/docs/src/stores/version.ts +0 -67
  133. package/core/apps/docs/src/styles/main.css +0 -278
  134. package/core/apps/docs/src/styles/prism.css +0 -95
  135. package/core/apps/docs/src/types/doc-schema.ts +0 -112
  136. package/core/apps/docs/tsconfig.json +0 -17
  137. package/core/apps/docs/tsconfig.node.json +0 -10
  138. package/core/apps/docs/vite.config.d.ts +0 -2
  139. package/core/apps/docs/vite.config.js +0 -26
  140. package/core/apps/docs/vite.config.ts +0 -28
  141. package/core/apps/docs-vitepress/.vitepress/config.ts +0 -141
  142. package/core/apps/docs-vitepress/api-data/latest/main.json +0 -15035
  143. package/core/apps/docs-vitepress/api-data/v1.2.4/main.json +0 -15035
  144. package/core/apps/docs-vitepress/api-data/versions.json +0 -6
  145. package/core/apps/docs-vitepress/index.md +0 -15
  146. package/core/apps/docs-vitepress/package-lock.json +0 -2924
  147. package/core/apps/docs-vitepress/package.json +0 -20
  148. package/core/apps/docs-vitepress/public/CNAME +0 -1
  149. package/core/apps/docs-vitepress/scripts/generate-api.ts +0 -243
  150. package/core/apps/docs-vitepress/scripts/migrate-guides.ts +0 -129
  151. package/core/apps/docs-vitepress/tsconfig.json +0 -11
  152. package/core/apps/docs-vitepress/v/latest/guides/attachments-by-url.md +0 -57
  153. package/core/apps/docs-vitepress/v/latest/guides/attachments.md +0 -62
  154. package/core/apps/docs-vitepress/v/latest/guides/basic-bot.md +0 -49
  155. package/core/apps/docs-vitepress/v/latest/guides/channels.md +0 -180
  156. package/core/apps/docs-vitepress/v/latest/guides/deprecated-apis.md +0 -58
  157. package/core/apps/docs-vitepress/v/latest/guides/discord-js-compatibility.md +0 -42
  158. package/core/apps/docs-vitepress/v/latest/guides/editing-embeds.md +0 -65
  159. package/core/apps/docs-vitepress/v/latest/guides/embed-media.md +0 -87
  160. package/core/apps/docs-vitepress/v/latest/guides/embeds.md +0 -166
  161. package/core/apps/docs-vitepress/v/latest/guides/emojis.md +0 -77
  162. package/core/apps/docs-vitepress/v/latest/guides/events.md +0 -202
  163. package/core/apps/docs-vitepress/v/latest/guides/gifs.md +0 -47
  164. package/core/apps/docs-vitepress/v/latest/guides/installation.md +0 -10
  165. package/core/apps/docs-vitepress/v/latest/guides/moderation.md +0 -89
  166. package/core/apps/docs-vitepress/v/latest/guides/permissions.md +0 -130
  167. package/core/apps/docs-vitepress/v/latest/guides/prefix-commands.md +0 -41
  168. package/core/apps/docs-vitepress/v/latest/guides/profile-urls.md +0 -58
  169. package/core/apps/docs-vitepress/v/latest/guides/reactions.md +0 -69
  170. package/core/apps/docs-vitepress/v/latest/guides/roles.md +0 -130
  171. package/core/apps/docs-vitepress/v/latest/guides/sending-without-reply.md +0 -172
  172. package/core/apps/docs-vitepress/v/latest/guides/voice.md +0 -109
  173. package/core/apps/docs-vitepress/v/latest/guides/wait-for-guilds.md +0 -37
  174. package/core/apps/docs-vitepress/v/latest/guides/webhook-attachments-embeds.md +0 -73
  175. package/core/apps/docs-vitepress/v/latest/guides/webhooks.md +0 -131
  176. package/core/eslint.config.js +0 -80
  177. package/core/examples/.env.example +0 -22
  178. package/core/examples/README.md +0 -68
  179. package/core/examples/first-steps-bot.js +0 -118
  180. package/core/examples/minimal-bot.js +0 -17
  181. package/core/examples/moderation-bot.js +0 -209
  182. package/core/examples/package.json +0 -14
  183. package/core/examples/ping-bot.js +0 -1146
  184. package/core/examples/reaction-bot.js +0 -70
  185. package/core/examples/reaction-roles-bot.js +0 -140
  186. package/core/examples/webhook-bot.js +0 -239
  187. package/core/flux.png +0 -0
  188. package/core/package.json +0 -78
  189. package/core/packages/builders/package.json +0 -51
  190. package/core/packages/builders/src/index.ts +0 -13
  191. package/core/packages/builders/src/messages/AttachmentBuilder.test.ts +0 -79
  192. package/core/packages/builders/src/messages/AttachmentBuilder.ts +0 -69
  193. package/core/packages/builders/src/messages/EmbedBuilder.test.ts +0 -266
  194. package/core/packages/builders/src/messages/EmbedBuilder.ts +0 -239
  195. package/core/packages/builders/src/messages/MessagePayload.test.ts +0 -118
  196. package/core/packages/builders/src/messages/MessagePayload.ts +0 -122
  197. package/core/packages/builders/tsconfig.json +0 -9
  198. package/core/packages/builders/tsup.config.ts +0 -9
  199. package/core/packages/builders/vitest.config.ts +0 -9
  200. package/core/packages/collection/package.json +0 -47
  201. package/core/packages/collection/src/Collection.test.ts +0 -232
  202. package/core/packages/collection/src/Collection.ts +0 -196
  203. package/core/packages/collection/src/index.ts +0 -1
  204. package/core/packages/collection/tsconfig.json +0 -9
  205. package/core/packages/collection/tsup.config.ts +0 -9
  206. package/core/packages/collection/vitest.config.ts +0 -9
  207. package/core/packages/docgen/package.json +0 -26
  208. package/core/packages/docgen/src/extract.ts +0 -262
  209. package/core/packages/docgen/src/formatType.ts +0 -24
  210. package/core/packages/docgen/src/index.ts +0 -103
  211. package/core/packages/docgen/src/schema.ts +0 -100
  212. package/core/packages/docgen/src/visitor.ts +0 -147
  213. package/core/packages/docgen/tsconfig.json +0 -9
  214. package/core/packages/docgen/tsup.config.ts +0 -9
  215. package/core/packages/fluxer-core/README.md +0 -26
  216. package/core/packages/fluxer-core/package.json +0 -60
  217. package/core/packages/fluxer-core/src/client/ChannelManager.ts +0 -143
  218. package/core/packages/fluxer-core/src/client/Client.gateway.test.ts +0 -84
  219. package/core/packages/fluxer-core/src/client/Client.resolveEmoji.test.ts +0 -45
  220. package/core/packages/fluxer-core/src/client/Client.ts +0 -558
  221. package/core/packages/fluxer-core/src/client/ClientUser.ts +0 -40
  222. package/core/packages/fluxer-core/src/client/EventHandlerRegistry.ts +0 -469
  223. package/core/packages/fluxer-core/src/client/GuildManager.ts +0 -79
  224. package/core/packages/fluxer-core/src/client/GuildMemberManager.ts +0 -91
  225. package/core/packages/fluxer-core/src/client/MessageManager.ts +0 -58
  226. package/core/packages/fluxer-core/src/client/UsersManager.ts +0 -122
  227. package/core/packages/fluxer-core/src/errors/ErrorCodes.test.ts +0 -19
  228. package/core/packages/fluxer-core/src/errors/ErrorCodes.ts +0 -12
  229. package/core/packages/fluxer-core/src/errors/FluxerError.test.ts +0 -32
  230. package/core/packages/fluxer-core/src/errors/FluxerError.ts +0 -15
  231. package/core/packages/fluxer-core/src/index.ts +0 -85
  232. package/core/packages/fluxer-core/src/structures/Base.ts +0 -7
  233. package/core/packages/fluxer-core/src/structures/Channel.ts +0 -508
  234. package/core/packages/fluxer-core/src/structures/Guild.test.ts +0 -189
  235. package/core/packages/fluxer-core/src/structures/Guild.ts +0 -734
  236. package/core/packages/fluxer-core/src/structures/GuildBan.ts +0 -35
  237. package/core/packages/fluxer-core/src/structures/GuildEmoji.ts +0 -57
  238. package/core/packages/fluxer-core/src/structures/GuildMember.test.ts +0 -203
  239. package/core/packages/fluxer-core/src/structures/GuildMember.ts +0 -213
  240. package/core/packages/fluxer-core/src/structures/GuildMemberRoleManager.ts +0 -121
  241. package/core/packages/fluxer-core/src/structures/GuildSticker.ts +0 -56
  242. package/core/packages/fluxer-core/src/structures/Invite.test.ts +0 -103
  243. package/core/packages/fluxer-core/src/structures/Invite.ts +0 -121
  244. package/core/packages/fluxer-core/src/structures/Message.test.ts +0 -109
  245. package/core/packages/fluxer-core/src/structures/Message.ts +0 -397
  246. package/core/packages/fluxer-core/src/structures/MessageReaction.ts +0 -72
  247. package/core/packages/fluxer-core/src/structures/PartialMessage.ts +0 -12
  248. package/core/packages/fluxer-core/src/structures/Role.test.ts +0 -77
  249. package/core/packages/fluxer-core/src/structures/Role.ts +0 -112
  250. package/core/packages/fluxer-core/src/structures/User.test.ts +0 -110
  251. package/core/packages/fluxer-core/src/structures/User.ts +0 -109
  252. package/core/packages/fluxer-core/src/structures/Webhook.test.ts +0 -109
  253. package/core/packages/fluxer-core/src/structures/Webhook.ts +0 -258
  254. package/core/packages/fluxer-core/src/util/Constants.test.ts +0 -16
  255. package/core/packages/fluxer-core/src/util/Constants.ts +0 -7
  256. package/core/packages/fluxer-core/src/util/Events.ts +0 -46
  257. package/core/packages/fluxer-core/src/util/MessageCollector.ts +0 -87
  258. package/core/packages/fluxer-core/src/util/Options.ts +0 -33
  259. package/core/packages/fluxer-core/src/util/ReactionCollector.ts +0 -116
  260. package/core/packages/fluxer-core/src/util/cdn.test.ts +0 -108
  261. package/core/packages/fluxer-core/src/util/cdn.ts +0 -130
  262. package/core/packages/fluxer-core/src/util/guildUtils.ts +0 -33
  263. package/core/packages/fluxer-core/src/util/messageUtils.test.ts +0 -74
  264. package/core/packages/fluxer-core/src/util/messageUtils.ts +0 -119
  265. package/core/packages/fluxer-core/src/util/permissions.test.ts +0 -95
  266. package/core/packages/fluxer-core/src/util/permissions.ts +0 -43
  267. package/core/packages/fluxer-core/tsconfig.json +0 -9
  268. package/core/packages/fluxer-core/tsup.config.ts +0 -9
  269. package/core/packages/fluxer-core/vitest.config.ts +0 -9
  270. package/core/packages/rest/package.json +0 -52
  271. package/core/packages/rest/src/REST.test.ts +0 -64
  272. package/core/packages/rest/src/REST.ts +0 -90
  273. package/core/packages/rest/src/RateLimitManager.test.ts +0 -71
  274. package/core/packages/rest/src/RateLimitManager.ts +0 -60
  275. package/core/packages/rest/src/RequestManager.test.ts +0 -87
  276. package/core/packages/rest/src/RequestManager.ts +0 -172
  277. package/core/packages/rest/src/errors/FluxerAPIError.test.ts +0 -57
  278. package/core/packages/rest/src/errors/FluxerAPIError.ts +0 -21
  279. package/core/packages/rest/src/errors/HTTPError.test.ts +0 -55
  280. package/core/packages/rest/src/errors/HTTPError.ts +0 -25
  281. package/core/packages/rest/src/errors/RateLimitError.test.ts +0 -41
  282. package/core/packages/rest/src/errors/RateLimitError.ts +0 -15
  283. package/core/packages/rest/src/errors/index.ts +0 -3
  284. package/core/packages/rest/src/index.ts +0 -6
  285. package/core/packages/rest/src/utils/constants.test.ts +0 -31
  286. package/core/packages/rest/src/utils/constants.ts +0 -5
  287. package/core/packages/rest/src/utils/files.test.ts +0 -37
  288. package/core/packages/rest/src/utils/files.ts +0 -75
  289. package/core/packages/rest/tsconfig.json +0 -9
  290. package/core/packages/rest/tsup.config.ts +0 -9
  291. package/core/packages/rest/vitest.config.ts +0 -9
  292. package/core/packages/types/package.json +0 -46
  293. package/core/packages/types/src/api/ban.ts +0 -8
  294. package/core/packages/types/src/api/channel.ts +0 -65
  295. package/core/packages/types/src/api/embed.ts +0 -82
  296. package/core/packages/types/src/api/emoji.ts +0 -12
  297. package/core/packages/types/src/api/errors.ts +0 -68
  298. package/core/packages/types/src/api/gateway.ts +0 -14
  299. package/core/packages/types/src/api/guild.ts +0 -123
  300. package/core/packages/types/src/api/index.ts +0 -15
  301. package/core/packages/types/src/api/instance.ts +0 -32
  302. package/core/packages/types/src/api/interaction.ts +0 -26
  303. package/core/packages/types/src/api/invite.ts +0 -28
  304. package/core/packages/types/src/api/message.ts +0 -140
  305. package/core/packages/types/src/api/role.ts +0 -41
  306. package/core/packages/types/src/api/sticker.ts +0 -14
  307. package/core/packages/types/src/api/user.ts +0 -79
  308. package/core/packages/types/src/api/webhook.ts +0 -41
  309. package/core/packages/types/src/common/index.ts +0 -1
  310. package/core/packages/types/src/common/snowflake.test.ts +0 -9
  311. package/core/packages/types/src/common/snowflake.ts +0 -8
  312. package/core/packages/types/src/gateway/events.ts +0 -189
  313. package/core/packages/types/src/gateway/index.ts +0 -3
  314. package/core/packages/types/src/gateway/opcodes.ts +0 -17
  315. package/core/packages/types/src/gateway/payloads.ts +0 -481
  316. package/core/packages/types/src/index.ts +0 -4
  317. package/core/packages/types/src/rest/index.ts +0 -1
  318. package/core/packages/types/src/rest/routes.test.ts +0 -169
  319. package/core/packages/types/src/rest/routes.ts +0 -109
  320. package/core/packages/types/tsconfig.json +0 -9
  321. package/core/packages/types/tsup.config.ts +0 -9
  322. package/core/packages/types/vitest.config.ts +0 -9
  323. package/core/packages/util/package.json +0 -51
  324. package/core/packages/util/src/BitField.test.ts +0 -96
  325. package/core/packages/util/src/BitField.ts +0 -105
  326. package/core/packages/util/src/MessageFlagsBitField.test.ts +0 -42
  327. package/core/packages/util/src/MessageFlagsBitField.ts +0 -20
  328. package/core/packages/util/src/PermissionsBitField.test.ts +0 -79
  329. package/core/packages/util/src/PermissionsBitField.ts +0 -97
  330. package/core/packages/util/src/SnowflakeUtil.test.ts +0 -69
  331. package/core/packages/util/src/SnowflakeUtil.ts +0 -65
  332. package/core/packages/util/src/UserFlagsBitField.test.ts +0 -39
  333. package/core/packages/util/src/UserFlagsBitField.ts +0 -48
  334. package/core/packages/util/src/deprecation.test.ts +0 -44
  335. package/core/packages/util/src/deprecation.ts +0 -28
  336. package/core/packages/util/src/emojiShortcodes.generated.ts +0 -5
  337. package/core/packages/util/src/emojiShortcodes.test.ts +0 -41
  338. package/core/packages/util/src/emojiShortcodes.ts +0 -22
  339. package/core/packages/util/src/formatters.test.ts +0 -65
  340. package/core/packages/util/src/formatters.ts +0 -35
  341. package/core/packages/util/src/index.ts +0 -34
  342. package/core/packages/util/src/resolvers.test.ts +0 -198
  343. package/core/packages/util/src/resolvers.ts +0 -127
  344. package/core/packages/util/src/tenorUtils.test.ts +0 -75
  345. package/core/packages/util/src/tenorUtils.ts +0 -86
  346. package/core/packages/util/tsconfig.json +0 -9
  347. package/core/packages/util/tsup.config.ts +0 -9
  348. package/core/packages/util/vitest.config.ts +0 -9
  349. package/core/packages/voice/README.md +0 -42
  350. package/core/packages/voice/package.json +0 -67
  351. package/core/packages/voice/src/LiveKitRtcConnection.receive.test.ts +0 -24
  352. package/core/packages/voice/src/LiveKitRtcConnection.ts +0 -1767
  353. package/core/packages/voice/src/VoiceConnection.ts +0 -413
  354. package/core/packages/voice/src/VoiceManager.receive.test.ts +0 -61
  355. package/core/packages/voice/src/VoiceManager.test.ts +0 -44
  356. package/core/packages/voice/src/VoiceManager.ts +0 -503
  357. package/core/packages/voice/src/exports.test.ts +0 -38
  358. package/core/packages/voice/src/index.ts +0 -51
  359. package/core/packages/voice/src/livekit.test.ts +0 -48
  360. package/core/packages/voice/src/livekit.ts +0 -33
  361. package/core/packages/voice/src/mp4box.d.ts +0 -32
  362. package/core/packages/voice/src/opusUtils.test.ts +0 -29
  363. package/core/packages/voice/src/opusUtils.ts +0 -86
  364. package/core/packages/voice/src/streamPreviewPlaceholder.test.ts +0 -16
  365. package/core/packages/voice/src/streamPreviewPlaceholder.ts +0 -8
  366. package/core/packages/voice/src/ws.d.ts +0 -1
  367. package/core/packages/voice/tsconfig.json +0 -5
  368. package/core/packages/voice/tsup.config.ts +0 -10
  369. package/core/packages/voice/vitest.config.ts +0 -9
  370. package/core/packages/ws/package.json +0 -52
  371. package/core/packages/ws/src/WebSocketManager.ts +0 -130
  372. package/core/packages/ws/src/WebSocketShard.ts +0 -296
  373. package/core/packages/ws/src/index.ts +0 -12
  374. package/core/packages/ws/src/utils/constants.test.ts +0 -46
  375. package/core/packages/ws/src/utils/constants.ts +0 -22
  376. package/core/packages/ws/src/utils/getWebSocket.ts +0 -55
  377. package/core/packages/ws/src/ws.d.ts +0 -10
  378. package/core/packages/ws/tsconfig.json +0 -9
  379. package/core/packages/ws/tsup.config.ts +0 -9
  380. package/core/pnpm-lock.yaml +0 -7033
  381. package/core/pnpm-workspace.yaml +0 -4
  382. package/core/scripts/generate-ai-rag.ts +0 -240
  383. package/core/scripts/generate-docs.ts +0 -143
  384. package/core/scripts/generate-emoji-shortcodes.ts +0 -58
  385. package/core/scripts/generate-types.ts +0 -6
  386. package/core/scripts/publish-ordered.js +0 -63
  387. package/core/scripts/test-cjs-require.mjs +0 -43
  388. package/core/scripts/test-esm-imports.mjs +0 -42
  389. package/core/scripts/test-package-exports.mjs +0 -98
  390. package/core/scripts/test-smoke.mjs +0 -103
  391. package/core/tsconfig.json +0 -18
  392. package/core/turbo.json +0 -30
  393. package/core/vitest.config.ts +0 -17
  394. package/core/wrangler.jsonc +0 -9
@@ -1,41 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { getUnicodeFromShortcode, UNICODE_EMOJI_SHORTCODES } from './emojiShortcodes.js';
3
-
4
- describe('getUnicodeFromShortcode', () => {
5
- it('resolves :heart: to unicode', () => {
6
- const r = getUnicodeFromShortcode('heart');
7
- expect(r).toBeDefined();
8
- expect(typeof r).toBe('string');
9
- expect(r!.length).toBeGreaterThan(0);
10
- });
11
-
12
- it('is case-insensitive', () => {
13
- const a = getUnicodeFromShortcode('heart');
14
- const b = getUnicodeFromShortcode('HEART');
15
- const c = getUnicodeFromShortcode('Heart');
16
- expect(a).toBe(b);
17
- expect(b).toBe(c);
18
- });
19
-
20
- it('trims whitespace', () => {
21
- const r = getUnicodeFromShortcode(' heart ');
22
- expect(r).toBe(UNICODE_EMOJI_SHORTCODES['heart']);
23
- });
24
-
25
- it('returns undefined for empty or invalid', () => {
26
- expect(getUnicodeFromShortcode('')).toBeUndefined();
27
- expect(getUnicodeFromShortcode(' ')).toBeUndefined();
28
- expect(getUnicodeFromShortcode('nonexistent_emoji_xyz')).toBeUndefined();
29
- });
30
-
31
- it('returns undefined for null/undefined input', () => {
32
- expect(getUnicodeFromShortcode(null as unknown as string)).toBeUndefined();
33
- expect(getUnicodeFromShortcode(undefined as unknown as string)).toBeUndefined();
34
- });
35
-
36
- it('resolves common shortcodes', () => {
37
- expect(getUnicodeFromShortcode('thumbsup')).toBeDefined();
38
- expect(getUnicodeFromShortcode('smile')).toBeDefined();
39
- expect(getUnicodeFromShortcode('fire')).toBeDefined();
40
- });
41
- });
@@ -1,22 +0,0 @@
1
- /**
2
- * Maps Unicode emoji shortcodes (:name:) to their Unicode characters.
3
- * Used to resolve shortcodes like :arrow_backward: and :flag_ad: for message.react()
4
- * without requiring guild context. Custom emojis use guild lookup; known Unicode shortcodes
5
- * resolve here so they work in DMs and guild channels alike.
6
- *
7
- * Data is generated from Discord's emoji data (anyascii/discord-emojis).
8
- * Run: pnpm exec tsx scripts/generate-emoji-shortcodes.ts
9
- */
10
- import { UNICODE_EMOJI_SHORTCODES as SHORTCODES } from './emojiShortcodes.generated.js';
11
-
12
- export const UNICODE_EMOJI_SHORTCODES = SHORTCODES;
13
-
14
- /**
15
- * Get the Unicode character for a known shortcode name.
16
- * Case-insensitive. Returns undefined if the shortcode is not in the map.
17
- */
18
- export function getUnicodeFromShortcode(name: string): string | undefined {
19
- if (!name || typeof name !== 'string') return undefined;
20
- const key = name.toLowerCase().trim();
21
- return UNICODE_EMOJI_SHORTCODES[key];
22
- }
@@ -1,65 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { formatColor, escapeMarkdown, formatTimestamp, truncate } from './formatters.js';
3
-
4
- describe('formatColor', () => {
5
- it('formats color as hex', () => {
6
- expect(formatColor(0xff0000)).toBe('#ff0000');
7
- expect(formatColor(0)).toBe('#000000');
8
- expect(formatColor(0xffffff)).toBe('#ffffff');
9
- });
10
- });
11
-
12
- describe('escapeMarkdown', () => {
13
- it('escapes markdown characters', () => {
14
- expect(escapeMarkdown('*bold*')).toBe('\\*bold\\*');
15
- expect(escapeMarkdown('_italic_')).toBe('\\_italic\\_');
16
- });
17
- });
18
-
19
- describe('formatTimestamp', () => {
20
- it('formats timestamp', () => {
21
- const ts = 1609459200000; // 2021-01-01 00:00:00 UTC
22
- expect(formatTimestamp(ts)).toBe('<t:1609459200>');
23
- expect(formatTimestamp(ts, 'R')).toBe('<t:1609459200:R>');
24
- });
25
- });
26
-
27
- describe('truncate', () => {
28
- it('returns unchanged if under limit', () => {
29
- expect(truncate('hello', 10)).toBe('hello');
30
- });
31
-
32
- it('truncates with suffix', () => {
33
- expect(truncate('hello world', 8)).toBe('hello...');
34
- });
35
-
36
- it('uses custom suffix', () => {
37
- expect(truncate('hello world', 9, '..')).toBe('hello w..');
38
- });
39
-
40
- it('handles exact length', () => {
41
- expect(truncate('hello', 5)).toBe('hello');
42
- });
43
-
44
- it('handles length smaller than suffix', () => {
45
- expect(truncate('hi', 1, '...')).toBe('...');
46
- });
47
- });
48
-
49
- describe('escapeMarkdown edge cases', () => {
50
- it('escapes backtick', () => {
51
- expect(escapeMarkdown('`code`')).toBe('\\`code\\`');
52
- });
53
- it('escapes pipe', () => {
54
- expect(escapeMarkdown('a|b')).toBe('a\\|b');
55
- });
56
- it('escapes tilde', () => {
57
- expect(escapeMarkdown('~strikethrough~')).toBe('\\~strikethrough\\~');
58
- });
59
- });
60
-
61
- describe('formatColor edge cases', () => {
62
- it('pads short hex', () => {
63
- expect(formatColor(0x000001)).toBe('#000001');
64
- });
65
- });
@@ -1,35 +0,0 @@
1
- /**
2
- * Format a number as a hex color string.
3
- */
4
- export function formatColor(color: number): string {
5
- const hex = color.toString(16).padStart(6, '0');
6
- return `#${hex}`;
7
- }
8
-
9
- /**
10
- * Escape markdown formatting characters in a string.
11
- */
12
- export function escapeMarkdown(text: string): string {
13
- return text.replace(/([\\*_`~|])/g, '\\$1');
14
- }
15
-
16
- /**
17
- * Format a Unix timestamp for Fluxer/Discord style timestamps.
18
- * @param timestamp - Unix timestamp in seconds
19
- * @param style - t, T, d, D, f, F, R, etc.
20
- */
21
- export function formatTimestamp(
22
- timestamp: number,
23
- style?: 't' | 'T' | 'd' | 'D' | 'f' | 'F' | 'R',
24
- ): string {
25
- const suffix = style ? `:${style}` : '';
26
- return `<t:${Math.floor(timestamp / 1000)}${suffix}>`;
27
- }
28
-
29
- /**
30
- * Truncate a string to a maximum length with an optional suffix.
31
- */
32
- export function truncate(str: string, maxLength: number, suffix = '...'): string {
33
- if (str.length <= maxLength) return str;
34
- return str.slice(0, maxLength - suffix.length) + suffix;
35
- }
@@ -1,34 +0,0 @@
1
- export { BitField, type BitFieldResolvable } from './BitField.js';
2
- export { SnowflakeUtil, FLUXER_EPOCH } from './SnowflakeUtil.js';
3
- export {
4
- PermissionsBitField,
5
- PermissionFlags,
6
- ALL_PERMISSIONS_BIGINT,
7
- resolvePermissionsToBitfield,
8
- type PermissionString,
9
- type PermissionResolvable,
10
- } from './PermissionsBitField.js';
11
- export {
12
- MessageFlagsBitField,
13
- MessageFlagsBits,
14
- type MessageFlagsString,
15
- type MessageFlagsResolvable,
16
- } from './MessageFlagsBitField.js';
17
- export {
18
- UserFlagsBitField,
19
- UserFlagsBits,
20
- type UserFlagsString,
21
- type UserFlagsResolvable,
22
- } from './UserFlagsBitField.js';
23
- export { formatColor, escapeMarkdown, formatTimestamp, truncate } from './formatters.js';
24
- export {
25
- resolveColor,
26
- parseEmoji,
27
- formatEmoji,
28
- parseUserMention,
29
- parseRoleMention,
30
- parsePrefixCommand,
31
- } from './resolvers.js';
32
- export { getUnicodeFromShortcode } from './emojiShortcodes.js';
33
- export { resolveTenorToImageUrl, type TenorMediaResult } from './tenorUtils.js';
34
- export { emitDeprecationWarning } from './deprecation.js';
@@ -1,198 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import {
3
- parseEmoji,
4
- formatEmoji,
5
- parseUserMention,
6
- parseRoleMention,
7
- parsePrefixCommand,
8
- resolveColor,
9
- } from './resolvers.js';
10
-
11
- describe('parseEmoji', () => {
12
- it('returns null for null/undefined/non-string', () => {
13
- expect(parseEmoji(null as unknown as string)).toBeNull();
14
- expect(parseEmoji(undefined as unknown as string)).toBeNull();
15
- expect(parseEmoji(123 as unknown as string)).toBeNull();
16
- });
17
-
18
- it('returns null for empty or whitespace-only string', () => {
19
- expect(parseEmoji('')).toBeNull();
20
- expect(parseEmoji(' ')).toBeNull();
21
- });
22
-
23
- it('parses <:name:id> mention format', () => {
24
- const r = parseEmoji('<:custom:123456789012345678>');
25
- expect(r).toEqual({ id: '123456789012345678', name: 'custom', animated: false });
26
- });
27
-
28
- it('parses <a:name:id> animated mention format', () => {
29
- const r = parseEmoji('<a:wiggle:987654321098765432>');
30
- expect(r).toEqual({ id: '987654321098765432', name: 'wiggle', animated: true });
31
- });
32
-
33
- it('parses name:id API format', () => {
34
- const r = parseEmoji('CustomEmoji:123456789012345678');
35
- expect(r).toEqual({ id: '123456789012345678', name: 'CustomEmoji' });
36
- });
37
-
38
- it('parses :name: shortcode format (unicode or guild lookup)', () => {
39
- const r = parseEmoji(':heart:');
40
- expect(r).toEqual({ id: null, name: 'heart' });
41
- });
42
-
43
- it('parses :name: with surrounding whitespace', () => {
44
- const r = parseEmoji(' :heart: ');
45
- expect(r).toEqual({ id: null, name: 'heart' });
46
- });
47
-
48
- it('returns plain unicode as name when no pattern matches', () => {
49
- const r = parseEmoji('❤️');
50
- expect(r).toEqual({ id: null, name: '❤️' });
51
- });
52
-
53
- it('rejects name:id with short id (less than 17 digits)', () => {
54
- const r = parseEmoji('emoji:123456');
55
- expect(r?.id).toBeNull();
56
- expect(r?.name).toBe('emoji:123456'); // falls through to plain
57
- });
58
- });
59
-
60
- describe('formatEmoji', () => {
61
- it('formats custom emoji as name:id', () => {
62
- expect(formatEmoji({ id: '123456789012345678', name: 'custom' })).toBe(
63
- ':custom:123456789012345678',
64
- );
65
- });
66
-
67
- it('formats animated custom emoji with a prefix', () => {
68
- expect(formatEmoji({ id: '123456789012345678', name: 'wiggle', animated: true })).toBe(
69
- 'a:wiggle:123456789012345678',
70
- );
71
- });
72
-
73
- it('encodes unicode emoji for API (id null)', () => {
74
- const r = formatEmoji({ id: null, name: '❤' });
75
- expect(r).toBe(encodeURIComponent('❤'));
76
- });
77
- });
78
-
79
- describe('parseUserMention', () => {
80
- it('extracts user ID from <@id> mention', () => {
81
- expect(parseUserMention('<@123456789012345678>')).toBe('123456789012345678');
82
- });
83
-
84
- it('extracts user ID from <@!id> mention', () => {
85
- expect(parseUserMention('<@!123456789012345678>')).toBe('123456789012345678');
86
- });
87
-
88
- it('returns raw snowflake when valid 17–19 digits', () => {
89
- expect(parseUserMention('123456789012345678')).toBe('123456789012345678');
90
- });
91
-
92
- it('returns null for invalid formats', () => {
93
- expect(parseUserMention('<@&123>')).toBeNull();
94
- expect(parseUserMention('invalid')).toBeNull();
95
- expect(parseUserMention('')).toBeNull();
96
- });
97
-
98
- it('trims whitespace', () => {
99
- expect(parseUserMention(' <@!123456789012345678> ')).toBe('123456789012345678');
100
- });
101
- });
102
-
103
- describe('parsePrefixCommand', () => {
104
- it('parses command with no args', () => {
105
- expect(parsePrefixCommand('!ping', '!')).toEqual({ command: 'ping', args: [] });
106
- });
107
-
108
- it('parses command with args', () => {
109
- expect(parsePrefixCommand('!hello world', '!')).toEqual({ command: 'hello', args: ['world'] });
110
- expect(parsePrefixCommand('!ban 123 reason here', '!')).toEqual({
111
- command: 'ban',
112
- args: ['123', 'reason', 'here'],
113
- });
114
- });
115
-
116
- it('returns null when content does not start with prefix', () => {
117
- expect(parsePrefixCommand('hello', '!')).toBeNull();
118
- });
119
-
120
- it('returns null for prefix only with no command', () => {
121
- expect(parsePrefixCommand('!', '!')).toBeNull();
122
- expect(parsePrefixCommand('! ', '!')).toBeNull();
123
- });
124
-
125
- it('handles multiple spaces between args', () => {
126
- expect(parsePrefixCommand('!cmd a b', '!')).toEqual({
127
- command: 'cmd',
128
- args: ['a', 'b'],
129
- });
130
- });
131
-
132
- it('lowercases command', () => {
133
- expect(parsePrefixCommand('!PING', '!')).toEqual({ command: 'ping', args: [] });
134
- });
135
-
136
- it('returns null for null or non-string content', () => {
137
- expect(parsePrefixCommand(null as unknown as string, '!')).toBeNull();
138
- expect(parsePrefixCommand(123 as unknown as string, '!')).toBeNull();
139
- });
140
- });
141
-
142
- describe('parseRoleMention', () => {
143
- it('extracts role ID from valid mention', () => {
144
- expect(parseRoleMention('<@&123456789012345678>')).toBe('123456789012345678');
145
- });
146
-
147
- it('returns null for invalid formats', () => {
148
- expect(parseRoleMention('<@123>')).toBeNull();
149
- expect(parseRoleMention('@&123')).toBeNull();
150
- expect(parseRoleMention('')).toBeNull();
151
- expect(parseRoleMention(' ')).toBeNull();
152
- });
153
-
154
- it('returns null for null or non-string', () => {
155
- expect(parseRoleMention(null as unknown as string)).toBeNull();
156
- expect(parseRoleMention(undefined as unknown as string)).toBeNull();
157
- expect(parseRoleMention(123 as unknown as string)).toBeNull();
158
- });
159
-
160
- it('trims whitespace', () => {
161
- expect(parseRoleMention(' <@&123456789012345678> ')).toBe('123456789012345678');
162
- });
163
- });
164
-
165
- describe('resolveColor', () => {
166
- it('accepts valid number 0-16777215', () => {
167
- expect(resolveColor(0)).toBe(0);
168
- expect(resolveColor(0xff0000)).toBe(0xff0000);
169
- expect(resolveColor(0xffffff)).toBe(0xffffff);
170
- });
171
-
172
- it('throws for number out of range', () => {
173
- expect(() => resolveColor(-1)).toThrow(RangeError);
174
- expect(() => resolveColor(0x1000000)).toThrow(RangeError);
175
- });
176
-
177
- it('parses hex string', () => {
178
- expect(resolveColor('#ff0000')).toBe(0xff0000);
179
- expect(resolveColor('#FFFFFF')).toBe(0xffffff);
180
- expect(resolveColor('000000')).toBe(0);
181
- });
182
-
183
- it('throws for invalid hex', () => {
184
- expect(() => resolveColor('#gggggg')).toThrow(RangeError);
185
- expect(() => resolveColor('#fff')).toThrow(RangeError);
186
- });
187
-
188
- it('parses RGB array', () => {
189
- expect(resolveColor([255, 0, 0])).toBe(0xff0000);
190
- expect(resolveColor([0, 0, 0])).toBe(0);
191
- expect(resolveColor([255, 255, 255])).toBe(0xffffff);
192
- });
193
-
194
- it('throws for non-color types', () => {
195
- expect(() => resolveColor({} as unknown as number)).toThrow(TypeError);
196
- expect(() => resolveColor(true as unknown as number)).toThrow(TypeError);
197
- });
198
- });
@@ -1,127 +0,0 @@
1
- /**
2
- * Resolve a color from various input types to a number (0-16777215).
3
- */
4
- export function resolveColor(color: number | string | [number, number, number]): number {
5
- if (typeof color === 'number') {
6
- if (color < 0 || color > 0xffffff) throw new RangeError('Color must be between 0 and 16777215');
7
- return color;
8
- }
9
- if (Array.isArray(color)) {
10
- const [r, g, b] = color;
11
- return (r! << 16) | (g! << 8) | b!;
12
- }
13
- if (typeof color === 'string') {
14
- const hex = color.replace(/^#/, '');
15
- if (!/^[0-9a-fA-F]{6}$/.test(hex)) throw new RangeError('Invalid hex color');
16
- return parseInt(hex, 16);
17
- }
18
- throw new TypeError('Color must be a number, hex string, or RGB array');
19
- }
20
-
21
- /**
22
- * Parse an emoji string into id and name.
23
- * Supports: <a?:name:id> (mention), :name: (colons), name:id (API format), unicode.
24
- */
25
- export function parseEmoji(
26
- emoji: string,
27
- ): { id: string | null; name: string; animated?: boolean } | null {
28
- if (emoji == null || typeof emoji !== 'string') return null;
29
- const trimmed = emoji.trim();
30
- if (trimmed.length === 0) return null;
31
- // <a?:name:id> mention format
32
- const mention = /^<(a?):(\w+):(\d+)>$/;
33
- const mentionMatch = trimmed.match(mention);
34
- if (mentionMatch) {
35
- return {
36
- id: mentionMatch[3],
37
- name: mentionMatch[2],
38
- animated: mentionMatch[1] === 'a',
39
- };
40
- }
41
- // name:id API format (custom emoji)
42
- const nameId = /^(\w+):(\d{17,19})$/;
43
- const nameIdMatch = trimmed.match(nameId);
44
- if (nameIdMatch) {
45
- return { id: nameIdMatch[2], name: nameIdMatch[1] };
46
- }
47
- // :name: format (colons, no id - needs guild lookup)
48
- const colons = /^:(\w+):$/;
49
- const colonsMatch = trimmed.match(colons);
50
- if (colonsMatch) {
51
- return { id: null, name: colonsMatch[1] };
52
- }
53
- // Plain name (possibly unicode) - id null
54
- return { id: null, name: trimmed };
55
- }
56
-
57
- /**
58
- * Parse a user mention string or raw snowflake and extract the user ID.
59
- * Supports: <@123456789012345678>, <@!123456789012345678>, or raw 17–19 digit snowflake.
60
- * @param arg - String that may contain a user mention or raw user ID
61
- * @returns The user ID if valid, otherwise null
62
- * @example
63
- * parseUserMention('<@!123456789012345678>'); // '123456789012345678'
64
- * parseUserMention('<@123456789012345678>'); // '123456789012345678'
65
- * parseUserMention('123456789012345678'); // '123456789012345678'
66
- */
67
- export function parseUserMention(arg: string): string | null {
68
- if (arg == null || typeof arg !== 'string') return null;
69
- const trimmed = arg.trim();
70
- if (trimmed.length === 0) return null;
71
- const mentionMatch = trimmed.match(/^<@!?(\d{17,19})>$/);
72
- if (mentionMatch) return mentionMatch[1];
73
- if (/^\d{17,19}$/.test(trimmed)) return trimmed;
74
- return null;
75
- }
76
-
77
- /**
78
- * Parse prefix command content into command name and args.
79
- * Returns null if content does not start with the prefix.
80
- * @param content - Raw message content
81
- * @param prefix - Command prefix (e.g. '!')
82
- * @returns { command, args } or null
83
- * @example
84
- * parsePrefixCommand('!ping', '!'); // { command: 'ping', args: [] }
85
- * parsePrefixCommand('!hello world', '!'); // { command: 'hello', args: ['world'] }
86
- */
87
- export function parsePrefixCommand(
88
- content: string,
89
- prefix: string,
90
- ): { command: string; args: string[] } | null {
91
- if (content == null || typeof content !== 'string') return null;
92
- const trimmed = content.trim();
93
- if (!trimmed.startsWith(prefix)) return null;
94
- const rest = trimmed.slice(prefix.length).trim();
95
- if (rest.length === 0) return null;
96
- const parts = rest.split(/\s+/);
97
- const command = parts[0]?.toLowerCase() ?? '';
98
- const args = parts.slice(1);
99
- return { command, args };
100
- }
101
-
102
- /**
103
- * Parse a role mention string (e.g. <@&123456>) and extract the role ID.
104
- * @param arg - String that may contain a role mention
105
- * @returns The role ID if valid mention, otherwise null
106
- */
107
- export function parseRoleMention(arg: string): string | null {
108
- if (arg == null || typeof arg !== 'string') return null;
109
- const match = arg.trim().match(/^<@&(\d{17,19})>$/);
110
- return match?.[1] ?? null;
111
- }
112
-
113
- /**
114
- * Convert emoji to the format used in API (for reactions etc).
115
- * Custom: "name:id", Unicode: "unicode"
116
- */
117
- export function formatEmoji(emoji: {
118
- id: string | null;
119
- name: string;
120
- animated?: boolean;
121
- }): string {
122
- if (emoji.id) {
123
- const prefix = emoji.animated ? 'a' : '';
124
- return `${prefix}:${emoji.name}:${emoji.id}`;
125
- }
126
- return encodeURIComponent(emoji.name);
127
- }
@@ -1,75 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import { resolveTenorToImageUrl } from './tenorUtils.js';
3
-
4
- describe('resolveTenorToImageUrl', () => {
5
- beforeEach(() => {
6
- vi.stubGlobal(
7
- 'fetch',
8
- vi.fn((url: string) => {
9
- if (url.includes('tenor.com/view')) {
10
- const html = `<html><script class="dynamic" type="application/ld+json">
11
- {"@type":"VideoObject","contentUrl":"https://media.tenor.com/abc123/stressed.gif","thumbnailUrl":"https://media.tenor.com/abc123/stressed.png"}
12
- </script></html>`;
13
- return Promise.resolve({
14
- ok: true,
15
- text: () => Promise.resolve(html),
16
- } as Response);
17
- }
18
- if (url.includes('oembed')) {
19
- return Promise.resolve({
20
- ok: true,
21
- json: () =>
22
- Promise.resolve({
23
- thumbnail_url: 'https://media.tenor.com/xyz/stressed.png',
24
- }),
25
- } as Response);
26
- }
27
- return Promise.reject(new Error('Unexpected URL'));
28
- }),
29
- );
30
- });
31
-
32
- afterEach(() => {
33
- vi.unstubAllGlobals();
34
- });
35
-
36
- it('returns null for empty or non-tenor URL', async () => {
37
- expect(await resolveTenorToImageUrl('')).toBeNull();
38
- expect(await resolveTenorToImageUrl('https://example.com')).toBeNull();
39
- expect(await resolveTenorToImageUrl('https://giphy.com/view/123')).toBeNull();
40
- });
41
-
42
- it('resolves GIF URL from tenor view page JSON-LD', async () => {
43
- const result = await resolveTenorToImageUrl(
44
- 'https://tenor.com/view/stressed-gif-7048057395502071840',
45
- );
46
- expect(result).not.toBeNull();
47
- expect(result!.url).toContain('.gif');
48
- expect(result!.url).toContain('media.tenor.com');
49
- });
50
-
51
- it('falls back to oEmbed when page fetch fails', async () => {
52
- vi.stubGlobal(
53
- 'fetch',
54
- vi.fn((url: string) => {
55
- if (url.includes('tenor.com/view')) {
56
- return Promise.resolve({ ok: false });
57
- }
58
- if (url.includes('oembed')) {
59
- return Promise.resolve({
60
- ok: true,
61
- json: () =>
62
- Promise.resolve({
63
- thumbnail_url: 'https://media.tenor.com/fallback/image.png',
64
- }),
65
- } as Response);
66
- }
67
- return Promise.reject(new Error('Unexpected'));
68
- }),
69
- );
70
- const result = await resolveTenorToImageUrl('https://tenor.com/view/test-123');
71
- expect(result).not.toBeNull();
72
- expect(result!.url).toContain('media.tenor.com');
73
- expect(result!.url).toContain('.gif');
74
- });
75
- });
@@ -1,86 +0,0 @@
1
- import { EmbedMediaFlags } from '@erinjs/types';
2
-
3
- /** Result for embed media: url and optional flags. */
4
- export interface TenorMediaResult {
5
- url: string;
6
- flags?: number;
7
- }
8
-
9
- /**
10
- * Resolve a Tenor view URL to a direct GIF URL for use in embeds.
11
- * Embeds require GIF format (not MP4). Fetches the Tenor page for JSON-LD
12
- * or oEmbed, then derives the GIF URL from the media.tenor.com path.
13
- *
14
- * @param tenorViewUrl - Tenor view URL (e.g. https://tenor.com/view/stressed-gif-7048057395502071840)
15
- * @returns { url, flags? } for setImage/setThumbnail, or null if resolution fails
16
- * @example
17
- * const media = await resolveTenorToImageUrl('https://tenor.com/view/stressed-gif-7048057395502071840');
18
- * if (media) embed.setImage(media);
19
- */
20
- export async function resolveTenorToImageUrl(
21
- tenorViewUrl: string,
22
- ): Promise<TenorMediaResult | null> {
23
- if (!tenorViewUrl || !tenorViewUrl.includes('tenor.com')) return null;
24
-
25
- // Try page HTML + JSON-LD first
26
- try {
27
- const pageRes = await fetch(tenorViewUrl, {
28
- signal: AbortSignal.timeout(5000),
29
- headers: { 'User-Agent': 'Mozilla/5.0 (compatible; FluxerSDK/1.0)' },
30
- });
31
- if (!pageRes.ok) throw new Error('Page fetch failed');
32
- const html = await pageRes.text();
33
- const jsonLd = extractTenorJsonLd(html);
34
- const gifUrl = extractGifUrlFromJsonLd(jsonLd);
35
- if (gifUrl) {
36
- return { url: gifUrl, flags: EmbedMediaFlags.IS_ANIMATED };
37
- }
38
- } catch {
39
- // Fall through to oEmbed
40
- }
41
-
42
- // Fallback: oEmbed thumbnail, derive GIF URL (media.tenor.com/ID/name.png -> name.gif)
43
- try {
44
- const oembedUrl = `https://tenor.com/oembed?url=${encodeURIComponent(tenorViewUrl)}`;
45
- const res = await fetch(oembedUrl, { signal: AbortSignal.timeout(5000) });
46
- if (!res.ok) return null;
47
- const data = (await res.json()) as { thumbnail_url?: string };
48
- const gifUrl = deriveGifFromThumbnail(data.thumbnail_url);
49
- return gifUrl ? { url: gifUrl, flags: EmbedMediaFlags.IS_ANIMATED } : null;
50
- } catch {
51
- return null;
52
- }
53
- }
54
-
55
- /** Extract GIF URL from JSON-LD. Prefers .gif URLs; derives from thumbnail path if needed. */
56
- function extractGifUrlFromJsonLd(jsonLd: Record<string, unknown> | null): string | null {
57
- if (!jsonLd) return null;
58
- const image = jsonLd.image as Record<string, string> | undefined;
59
- const video = jsonLd.video as Record<string, string> | undefined;
60
- const thumbnailUrl = image?.thumbnailUrl ?? image?.url;
61
- const contentUrl = image?.contentUrl ?? video?.contentUrl;
62
- if (contentUrl && /\.gif($|\?)/i.test(contentUrl)) return contentUrl;
63
- if (thumbnailUrl) return deriveGifFromThumbnail(thumbnailUrl);
64
- return null;
65
- }
66
-
67
- /** Derive GIF URL from media.tenor.com thumbnail (.png -> .gif). */
68
- function deriveGifFromThumbnail(thumbUrl: string | undefined): string | null {
69
- if (!thumbUrl || !thumbUrl.includes('media.tenor.com')) return null;
70
- const gifUrl = thumbUrl.replace(/\.(png|jpg|jpeg|webp)(\?|$)/i, '.gif$2');
71
- return gifUrl !== thumbUrl ? gifUrl : null;
72
- }
73
-
74
- function extractTenorJsonLd(html: string): Record<string, unknown> | null {
75
- const re =
76
- /<script[^>]*class="dynamic"[^>]*type="application\/ld\+json"[^>]*>([\s\S]*?)<\/script>/i;
77
- const alt =
78
- /<script[^>]*type="application\/ld\+json"[^>]*class="dynamic"[^>]*>([\s\S]*?)<\/script>/i;
79
- const match = html.match(re) ?? html.match(alt);
80
- if (!match?.[1]) return null;
81
- try {
82
- return JSON.parse(match[1].trim()) as Record<string, unknown>;
83
- } catch {
84
- return null;
85
- }
86
- }