agent-messenger 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 (394) hide show
  1. package/.claude/commands/release.md +92 -0
  2. package/.claude-plugin/README.md +144 -0
  3. package/.claude-plugin/marketplace.json +37 -0
  4. package/.claude-plugin/plugin.json +17 -0
  5. package/.github/workflows/ci.yml +30 -0
  6. package/CLAUDE.md +106 -0
  7. package/CONTRIBUTING.md +131 -0
  8. package/README.md +140 -0
  9. package/biome.json +34 -0
  10. package/bun.lock +252 -0
  11. package/dist/cli.d.ts +5 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +21 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/commands/auth.d.ts +3 -0
  16. package/dist/commands/auth.d.ts.map +1 -0
  17. package/dist/commands/auth.js +140 -0
  18. package/dist/commands/auth.js.map +1 -0
  19. package/dist/commands/channel.d.ts +3 -0
  20. package/dist/commands/channel.d.ts.map +1 -0
  21. package/dist/commands/channel.js +118 -0
  22. package/dist/commands/channel.js.map +1 -0
  23. package/dist/commands/file.d.ts +3 -0
  24. package/dist/commands/file.d.ts.map +1 -0
  25. package/dist/commands/file.js +113 -0
  26. package/dist/commands/file.js.map +1 -0
  27. package/dist/commands/index.d.ts +9 -0
  28. package/dist/commands/index.d.ts.map +1 -0
  29. package/dist/commands/index.js +9 -0
  30. package/dist/commands/index.js.map +1 -0
  31. package/dist/commands/message.d.ts +3 -0
  32. package/dist/commands/message.d.ts.map +1 -0
  33. package/dist/commands/message.js +214 -0
  34. package/dist/commands/message.js.map +1 -0
  35. package/dist/commands/reaction.d.ts +3 -0
  36. package/dist/commands/reaction.d.ts.map +1 -0
  37. package/dist/commands/reaction.js +100 -0
  38. package/dist/commands/reaction.js.map +1 -0
  39. package/dist/commands/snapshot.d.ts +3 -0
  40. package/dist/commands/snapshot.d.ts.map +1 -0
  41. package/dist/commands/snapshot.js +88 -0
  42. package/dist/commands/snapshot.js.map +1 -0
  43. package/dist/commands/user.d.ts +3 -0
  44. package/dist/commands/user.d.ts.map +1 -0
  45. package/dist/commands/user.js +96 -0
  46. package/dist/commands/user.js.map +1 -0
  47. package/dist/commands/workspace.d.ts +3 -0
  48. package/dist/commands/workspace.d.ts.map +1 -0
  49. package/dist/commands/workspace.js +89 -0
  50. package/dist/commands/workspace.js.map +1 -0
  51. package/dist/lib/credential-manager.d.ts +13 -0
  52. package/dist/lib/credential-manager.d.ts.map +1 -0
  53. package/dist/lib/credential-manager.js +58 -0
  54. package/dist/lib/credential-manager.js.map +1 -0
  55. package/dist/lib/index.d.ts +3 -0
  56. package/dist/lib/index.d.ts.map +1 -0
  57. package/dist/lib/index.js +3 -0
  58. package/dist/lib/index.js.map +1 -0
  59. package/dist/lib/ref-manager.d.ts +26 -0
  60. package/dist/lib/ref-manager.d.ts.map +1 -0
  61. package/dist/lib/ref-manager.js +92 -0
  62. package/dist/lib/ref-manager.js.map +1 -0
  63. package/dist/lib/slack-client.d.ts +37 -0
  64. package/dist/lib/slack-client.d.ts.map +1 -0
  65. package/dist/lib/slack-client.js +379 -0
  66. package/dist/lib/slack-client.js.map +1 -0
  67. package/dist/lib/token-extractor.d.ts +28 -0
  68. package/dist/lib/token-extractor.d.ts.map +1 -0
  69. package/dist/lib/token-extractor.js +401 -0
  70. package/dist/lib/token-extractor.js.map +1 -0
  71. package/dist/package.json +37 -0
  72. package/dist/src/cli.d.ts +5 -0
  73. package/dist/src/cli.d.ts.map +1 -0
  74. package/dist/src/cli.js +22 -0
  75. package/dist/src/cli.js.map +1 -0
  76. package/dist/src/platforms/discord/cli.d.ts +5 -0
  77. package/dist/src/platforms/discord/cli.d.ts.map +1 -0
  78. package/dist/src/platforms/discord/cli.js +22 -0
  79. package/dist/src/platforms/discord/cli.js.map +1 -0
  80. package/dist/src/platforms/discord/client.d.ts +34 -0
  81. package/dist/src/platforms/discord/client.d.ts.map +1 -0
  82. package/dist/src/platforms/discord/client.js +187 -0
  83. package/dist/src/platforms/discord/client.js.map +1 -0
  84. package/dist/src/platforms/discord/client.test.d.ts +2 -0
  85. package/dist/src/platforms/discord/client.test.d.ts.map +1 -0
  86. package/dist/src/platforms/discord/client.test.js +367 -0
  87. package/dist/src/platforms/discord/client.test.js.map +1 -0
  88. package/dist/src/platforms/discord/commands/auth.d.ts +13 -0
  89. package/dist/src/platforms/discord/commands/auth.d.ts.map +1 -0
  90. package/dist/src/platforms/discord/commands/auth.js +155 -0
  91. package/dist/src/platforms/discord/commands/auth.js.map +1 -0
  92. package/dist/src/platforms/discord/commands/auth.test.d.ts +2 -0
  93. package/dist/src/platforms/discord/commands/auth.test.d.ts.map +1 -0
  94. package/dist/src/platforms/discord/commands/auth.test.js +65 -0
  95. package/dist/src/platforms/discord/commands/auth.test.js.map +1 -0
  96. package/dist/src/platforms/discord/commands/channel.d.ts +13 -0
  97. package/dist/src/platforms/discord/commands/channel.d.ts.map +1 -0
  98. package/dist/src/platforms/discord/commands/channel.js +99 -0
  99. package/dist/src/platforms/discord/commands/channel.js.map +1 -0
  100. package/dist/src/platforms/discord/commands/channel.test.d.ts +2 -0
  101. package/dist/src/platforms/discord/commands/channel.test.d.ts.map +1 -0
  102. package/dist/src/platforms/discord/commands/channel.test.js +136 -0
  103. package/dist/src/platforms/discord/commands/channel.test.js.map +1 -0
  104. package/dist/src/platforms/discord/commands/file.d.ts +13 -0
  105. package/dist/src/platforms/discord/commands/file.d.ts.map +1 -0
  106. package/dist/src/platforms/discord/commands/file.js +99 -0
  107. package/dist/src/platforms/discord/commands/file.js.map +1 -0
  108. package/dist/src/platforms/discord/commands/file.test.d.ts +2 -0
  109. package/dist/src/platforms/discord/commands/file.test.d.ts.map +1 -0
  110. package/dist/src/platforms/discord/commands/file.test.js +83 -0
  111. package/dist/src/platforms/discord/commands/file.test.js.map +1 -0
  112. package/dist/src/platforms/discord/commands/guild.d.ts +15 -0
  113. package/dist/src/platforms/discord/commands/guild.d.ts.map +1 -0
  114. package/dist/src/platforms/discord/commands/guild.js +102 -0
  115. package/dist/src/platforms/discord/commands/guild.js.map +1 -0
  116. package/dist/src/platforms/discord/commands/guild.test.d.ts +2 -0
  117. package/dist/src/platforms/discord/commands/guild.test.d.ts.map +1 -0
  118. package/dist/src/platforms/discord/commands/guild.test.js +100 -0
  119. package/dist/src/platforms/discord/commands/guild.test.js.map +1 -0
  120. package/dist/src/platforms/discord/commands/index.d.ts +9 -0
  121. package/dist/src/platforms/discord/commands/index.d.ts.map +1 -0
  122. package/dist/src/platforms/discord/commands/index.js +9 -0
  123. package/dist/src/platforms/discord/commands/index.js.map +1 -0
  124. package/dist/src/platforms/discord/commands/message.d.ts +17 -0
  125. package/dist/src/platforms/discord/commands/message.d.ts.map +1 -0
  126. package/dist/src/platforms/discord/commands/message.js +131 -0
  127. package/dist/src/platforms/discord/commands/message.js.map +1 -0
  128. package/dist/src/platforms/discord/commands/message.test.d.ts +2 -0
  129. package/dist/src/platforms/discord/commands/message.test.d.ts.map +1 -0
  130. package/dist/src/platforms/discord/commands/message.test.js +91 -0
  131. package/dist/src/platforms/discord/commands/message.test.js.map +1 -0
  132. package/dist/src/platforms/discord/commands/reaction.d.ts +12 -0
  133. package/dist/src/platforms/discord/commands/reaction.d.ts.map +1 -0
  134. package/dist/src/platforms/discord/commands/reaction.js +99 -0
  135. package/dist/src/platforms/discord/commands/reaction.js.map +1 -0
  136. package/dist/src/platforms/discord/commands/reaction.test.d.ts +2 -0
  137. package/dist/src/platforms/discord/commands/reaction.test.d.ts.map +1 -0
  138. package/dist/src/platforms/discord/commands/reaction.test.js +115 -0
  139. package/dist/src/platforms/discord/commands/reaction.test.js.map +1 -0
  140. package/dist/src/platforms/discord/commands/snapshot.d.ts +9 -0
  141. package/dist/src/platforms/discord/commands/snapshot.d.ts.map +1 -0
  142. package/dist/src/platforms/discord/commands/snapshot.js +80 -0
  143. package/dist/src/platforms/discord/commands/snapshot.js.map +1 -0
  144. package/dist/src/platforms/discord/commands/snapshot.test.d.ts +2 -0
  145. package/dist/src/platforms/discord/commands/snapshot.test.d.ts.map +1 -0
  146. package/dist/src/platforms/discord/commands/snapshot.test.js +25 -0
  147. package/dist/src/platforms/discord/commands/snapshot.test.js.map +1 -0
  148. package/dist/src/platforms/discord/commands/user.d.ts +3 -0
  149. package/dist/src/platforms/discord/commands/user.d.ts.map +1 -0
  150. package/dist/src/platforms/discord/commands/user.js +94 -0
  151. package/dist/src/platforms/discord/commands/user.js.map +1 -0
  152. package/dist/src/platforms/discord/commands/user.test.d.ts +2 -0
  153. package/dist/src/platforms/discord/commands/user.test.d.ts.map +1 -0
  154. package/dist/src/platforms/discord/commands/user.test.js +103 -0
  155. package/dist/src/platforms/discord/commands/user.test.js.map +1 -0
  156. package/dist/src/platforms/discord/credential-manager.d.ts +33 -0
  157. package/dist/src/platforms/discord/credential-manager.d.ts.map +1 -0
  158. package/dist/src/platforms/discord/credential-manager.js +73 -0
  159. package/dist/src/platforms/discord/credential-manager.js.map +1 -0
  160. package/dist/src/platforms/discord/credential-manager.test.d.ts +2 -0
  161. package/dist/src/platforms/discord/credential-manager.test.d.ts.map +1 -0
  162. package/dist/src/platforms/discord/credential-manager.test.js +136 -0
  163. package/dist/src/platforms/discord/credential-manager.test.js.map +1 -0
  164. package/dist/src/platforms/discord/token-extractor.d.ts +55 -0
  165. package/dist/src/platforms/discord/token-extractor.d.ts.map +1 -0
  166. package/dist/src/platforms/discord/token-extractor.js +462 -0
  167. package/dist/src/platforms/discord/token-extractor.js.map +1 -0
  168. package/dist/src/platforms/discord/token-extractor.test.d.ts +2 -0
  169. package/dist/src/platforms/discord/token-extractor.test.d.ts.map +1 -0
  170. package/dist/src/platforms/discord/token-extractor.test.js +789 -0
  171. package/dist/src/platforms/discord/token-extractor.test.js.map +1 -0
  172. package/dist/src/platforms/discord/types.d.ts +251 -0
  173. package/dist/src/platforms/discord/types.d.ts.map +1 -0
  174. package/dist/src/platforms/discord/types.js +74 -0
  175. package/dist/src/platforms/discord/types.js.map +1 -0
  176. package/dist/src/platforms/discord/types.test.d.ts +2 -0
  177. package/dist/src/platforms/discord/types.test.d.ts.map +1 -0
  178. package/dist/src/platforms/discord/types.test.js +211 -0
  179. package/dist/src/platforms/discord/types.test.js.map +1 -0
  180. package/dist/src/platforms/slack/cli.d.ts +5 -0
  181. package/dist/src/platforms/slack/cli.d.ts.map +1 -0
  182. package/dist/src/platforms/slack/cli.js +22 -0
  183. package/dist/src/platforms/slack/cli.js.map +1 -0
  184. package/dist/src/platforms/slack/client.d.ts +47 -0
  185. package/dist/src/platforms/slack/client.d.ts.map +1 -0
  186. package/dist/src/platforms/slack/client.js +412 -0
  187. package/dist/src/platforms/slack/client.js.map +1 -0
  188. package/dist/src/platforms/slack/commands/auth.d.ts +3 -0
  189. package/dist/src/platforms/slack/commands/auth.d.ts.map +1 -0
  190. package/dist/src/platforms/slack/commands/auth.js +156 -0
  191. package/dist/src/platforms/slack/commands/auth.js.map +1 -0
  192. package/dist/src/platforms/slack/commands/channel.d.ts +3 -0
  193. package/dist/src/platforms/slack/commands/channel.d.ts.map +1 -0
  194. package/dist/src/platforms/slack/commands/channel.js +118 -0
  195. package/dist/src/platforms/slack/commands/channel.js.map +1 -0
  196. package/dist/src/platforms/slack/commands/file.d.ts +3 -0
  197. package/dist/src/platforms/slack/commands/file.d.ts.map +1 -0
  198. package/dist/src/platforms/slack/commands/file.js +113 -0
  199. package/dist/src/platforms/slack/commands/file.js.map +1 -0
  200. package/dist/src/platforms/slack/commands/index.d.ts +9 -0
  201. package/dist/src/platforms/slack/commands/index.d.ts.map +1 -0
  202. package/dist/src/platforms/slack/commands/index.js +9 -0
  203. package/dist/src/platforms/slack/commands/index.js.map +1 -0
  204. package/dist/src/platforms/slack/commands/message.d.ts +3 -0
  205. package/dist/src/platforms/slack/commands/message.d.ts.map +1 -0
  206. package/dist/src/platforms/slack/commands/message.js +263 -0
  207. package/dist/src/platforms/slack/commands/message.js.map +1 -0
  208. package/dist/src/platforms/slack/commands/reaction.d.ts +3 -0
  209. package/dist/src/platforms/slack/commands/reaction.d.ts.map +1 -0
  210. package/dist/src/platforms/slack/commands/reaction.js +100 -0
  211. package/dist/src/platforms/slack/commands/reaction.js.map +1 -0
  212. package/dist/src/platforms/slack/commands/snapshot.d.ts +3 -0
  213. package/dist/src/platforms/slack/commands/snapshot.d.ts.map +1 -0
  214. package/dist/src/platforms/slack/commands/snapshot.js +87 -0
  215. package/dist/src/platforms/slack/commands/snapshot.js.map +1 -0
  216. package/dist/src/platforms/slack/commands/user.d.ts +3 -0
  217. package/dist/src/platforms/slack/commands/user.d.ts.map +1 -0
  218. package/dist/src/platforms/slack/commands/user.js +96 -0
  219. package/dist/src/platforms/slack/commands/user.js.map +1 -0
  220. package/dist/src/platforms/slack/commands/workspace.d.ts +3 -0
  221. package/dist/src/platforms/slack/commands/workspace.d.ts.map +1 -0
  222. package/dist/src/platforms/slack/commands/workspace.js +89 -0
  223. package/dist/src/platforms/slack/commands/workspace.js.map +1 -0
  224. package/dist/src/platforms/slack/credential-manager.d.ts +13 -0
  225. package/dist/src/platforms/slack/credential-manager.d.ts.map +1 -0
  226. package/dist/src/platforms/slack/credential-manager.js +58 -0
  227. package/dist/src/platforms/slack/credential-manager.js.map +1 -0
  228. package/dist/src/platforms/slack/index.d.ts +3 -0
  229. package/dist/src/platforms/slack/index.d.ts.map +1 -0
  230. package/dist/src/platforms/slack/index.js +3 -0
  231. package/dist/src/platforms/slack/index.js.map +1 -0
  232. package/dist/src/platforms/slack/token-extractor.d.ts +28 -0
  233. package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -0
  234. package/dist/src/platforms/slack/token-extractor.js +401 -0
  235. package/dist/src/platforms/slack/token-extractor.js.map +1 -0
  236. package/dist/src/platforms/slack/types.d.ts +369 -0
  237. package/dist/src/platforms/slack/types.d.ts.map +1 -0
  238. package/dist/src/platforms/slack/types.js +92 -0
  239. package/dist/src/platforms/slack/types.js.map +1 -0
  240. package/dist/src/shared/utils/concurrency.d.ts +2 -0
  241. package/dist/src/shared/utils/concurrency.d.ts.map +1 -0
  242. package/dist/src/shared/utils/concurrency.js +14 -0
  243. package/dist/src/shared/utils/concurrency.js.map +1 -0
  244. package/dist/src/shared/utils/concurrency.test.d.ts +2 -0
  245. package/dist/src/shared/utils/concurrency.test.d.ts.map +1 -0
  246. package/dist/src/shared/utils/concurrency.test.js +39 -0
  247. package/dist/src/shared/utils/concurrency.test.js.map +1 -0
  248. package/dist/src/shared/utils/error-handler.d.ts +2 -0
  249. package/dist/src/shared/utils/error-handler.d.ts.map +1 -0
  250. package/dist/src/shared/utils/error-handler.js +5 -0
  251. package/dist/src/shared/utils/error-handler.js.map +1 -0
  252. package/dist/src/shared/utils/output.d.ts +2 -0
  253. package/dist/src/shared/utils/output.d.ts.map +1 -0
  254. package/dist/src/shared/utils/output.js +4 -0
  255. package/dist/src/shared/utils/output.js.map +1 -0
  256. package/dist/tests/cli.test.d.ts +2 -0
  257. package/dist/tests/cli.test.d.ts.map +1 -0
  258. package/dist/tests/cli.test.js +83 -0
  259. package/dist/tests/cli.test.js.map +1 -0
  260. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/CURRENT +1 -0
  261. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOCK +0 -0
  262. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG +3 -0
  263. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG.old +1 -0
  264. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/MANIFEST-000004 +0 -0
  265. package/dist/tests/commands/auth.test.d.ts +2 -0
  266. package/dist/tests/commands/auth.test.d.ts.map +1 -0
  267. package/dist/tests/commands/auth.test.js +304 -0
  268. package/dist/tests/commands/auth.test.js.map +1 -0
  269. package/dist/tests/commands/channel.test.d.ts +2 -0
  270. package/dist/tests/commands/channel.test.d.ts.map +1 -0
  271. package/dist/tests/commands/channel.test.js +166 -0
  272. package/dist/tests/commands/channel.test.js.map +1 -0
  273. package/dist/tests/commands/file.test.d.ts +2 -0
  274. package/dist/tests/commands/file.test.d.ts.map +1 -0
  275. package/dist/tests/commands/file.test.js +175 -0
  276. package/dist/tests/commands/file.test.js.map +1 -0
  277. package/dist/tests/commands/message.test.d.ts +2 -0
  278. package/dist/tests/commands/message.test.d.ts.map +1 -0
  279. package/dist/tests/commands/message.test.js +293 -0
  280. package/dist/tests/commands/message.test.js.map +1 -0
  281. package/dist/tests/commands/reaction.test.d.ts +2 -0
  282. package/dist/tests/commands/reaction.test.d.ts.map +1 -0
  283. package/dist/tests/commands/reaction.test.js +84 -0
  284. package/dist/tests/commands/reaction.test.js.map +1 -0
  285. package/dist/tests/commands/snapshot.test.d.ts +2 -0
  286. package/dist/tests/commands/snapshot.test.d.ts.map +1 -0
  287. package/dist/tests/commands/snapshot.test.js +280 -0
  288. package/dist/tests/commands/snapshot.test.js.map +1 -0
  289. package/dist/tests/commands/user.test.d.ts +2 -0
  290. package/dist/tests/commands/user.test.d.ts.map +1 -0
  291. package/dist/tests/commands/user.test.js +117 -0
  292. package/dist/tests/commands/user.test.js.map +1 -0
  293. package/dist/tests/commands/workspace.test.d.ts +2 -0
  294. package/dist/tests/commands/workspace.test.d.ts.map +1 -0
  295. package/dist/tests/commands/workspace.test.js +453 -0
  296. package/dist/tests/commands/workspace.test.js.map +1 -0
  297. package/dist/tests/credential-manager.test.d.ts +2 -0
  298. package/dist/tests/credential-manager.test.d.ts.map +1 -0
  299. package/dist/tests/credential-manager.test.js +199 -0
  300. package/dist/tests/credential-manager.test.js.map +1 -0
  301. package/dist/tests/slack-client.test.d.ts +2 -0
  302. package/dist/tests/slack-client.test.d.ts.map +1 -0
  303. package/dist/tests/slack-client.test.js +741 -0
  304. package/dist/tests/slack-client.test.js.map +1 -0
  305. package/dist/tests/types.test.d.ts +2 -0
  306. package/dist/tests/types.test.d.ts.map +1 -0
  307. package/dist/tests/types.test.js +215 -0
  308. package/dist/tests/types.test.js.map +1 -0
  309. package/dist/types/index.d.ts +369 -0
  310. package/dist/types/index.d.ts.map +1 -0
  311. package/dist/types/index.js +92 -0
  312. package/dist/types/index.js.map +1 -0
  313. package/dist/utils/error-handler.d.ts +2 -0
  314. package/dist/utils/error-handler.d.ts.map +1 -0
  315. package/dist/utils/error-handler.js +5 -0
  316. package/dist/utils/error-handler.js.map +1 -0
  317. package/dist/utils/output.d.ts +2 -0
  318. package/dist/utils/output.d.ts.map +1 -0
  319. package/dist/utils/output.js +4 -0
  320. package/dist/utils/output.js.map +1 -0
  321. package/docs/discord.md +182 -0
  322. package/docs/slack.md +160 -0
  323. package/package.json +37 -0
  324. package/skills/agent-discord/SKILL.md +273 -0
  325. package/skills/agent-discord/references/authentication.md +294 -0
  326. package/skills/agent-discord/references/common-patterns.md +455 -0
  327. package/skills/agent-discord/templates/guild-summary.sh +167 -0
  328. package/skills/agent-discord/templates/monitor-channel.sh +180 -0
  329. package/skills/agent-discord/templates/post-message.sh +173 -0
  330. package/skills/agent-slack/SKILL.md +268 -0
  331. package/skills/agent-slack/references/authentication.md +332 -0
  332. package/skills/agent-slack/references/common-patterns.md +527 -0
  333. package/skills/agent-slack/templates/monitor-channel.sh +186 -0
  334. package/skills/agent-slack/templates/post-message.sh +130 -0
  335. package/skills/agent-slack/templates/workspace-summary.sh +149 -0
  336. package/src/cli.ts +29 -0
  337. package/src/platforms/discord/cli.ts +36 -0
  338. package/src/platforms/discord/client.test.ts +456 -0
  339. package/src/platforms/discord/client.ts +281 -0
  340. package/src/platforms/discord/commands/auth.test.ts +72 -0
  341. package/src/platforms/discord/commands/auth.ts +206 -0
  342. package/src/platforms/discord/commands/channel.test.ts +153 -0
  343. package/src/platforms/discord/commands/channel.ts +127 -0
  344. package/src/platforms/discord/commands/file.test.ts +98 -0
  345. package/src/platforms/discord/commands/file.ts +134 -0
  346. package/src/platforms/discord/commands/guild.test.ts +117 -0
  347. package/src/platforms/discord/commands/guild.ts +129 -0
  348. package/src/platforms/discord/commands/index.ts +8 -0
  349. package/src/platforms/discord/commands/message.test.ts +107 -0
  350. package/src/platforms/discord/commands/message.ts +182 -0
  351. package/src/platforms/discord/commands/reaction.test.ts +123 -0
  352. package/src/platforms/discord/commands/reaction.ts +156 -0
  353. package/src/platforms/discord/commands/snapshot.test.ts +29 -0
  354. package/src/platforms/discord/commands/snapshot.ts +104 -0
  355. package/src/platforms/discord/commands/user.test.ts +115 -0
  356. package/src/platforms/discord/commands/user.ts +124 -0
  357. package/src/platforms/discord/credential-manager.test.ts +173 -0
  358. package/src/platforms/discord/credential-manager.ts +95 -0
  359. package/src/platforms/discord/token-extractor.test.ts +918 -0
  360. package/src/platforms/discord/token-extractor.ts +549 -0
  361. package/src/platforms/discord/types.test.ts +245 -0
  362. package/src/platforms/discord/types.ts +158 -0
  363. package/src/platforms/slack/cli.ts +36 -0
  364. package/src/platforms/slack/client.ts +466 -0
  365. package/src/platforms/slack/commands/auth.ts +211 -0
  366. package/src/platforms/slack/commands/channel.ts +158 -0
  367. package/src/platforms/slack/commands/file.ts +153 -0
  368. package/src/platforms/slack/commands/index.ts +8 -0
  369. package/src/platforms/slack/commands/message.ts +369 -0
  370. package/src/platforms/slack/commands/reaction.ts +166 -0
  371. package/src/platforms/slack/commands/snapshot.ts +114 -0
  372. package/src/platforms/slack/commands/user.ts +110 -0
  373. package/src/platforms/slack/commands/workspace.ts +111 -0
  374. package/src/platforms/slack/credential-manager.ts +74 -0
  375. package/src/platforms/slack/index.ts +2 -0
  376. package/src/platforms/slack/token-extractor.ts +496 -0
  377. package/src/platforms/slack/types.ts +193 -0
  378. package/src/shared/utils/concurrency.test.ts +53 -0
  379. package/src/shared/utils/concurrency.ts +20 -0
  380. package/src/shared/utils/error-handler.ts +4 -0
  381. package/src/shared/utils/output.ts +3 -0
  382. package/tests/cli.test.ts +94 -0
  383. package/tests/commands/auth.test.ts +383 -0
  384. package/tests/commands/channel.test.ts +185 -0
  385. package/tests/commands/file.test.ts +204 -0
  386. package/tests/commands/message.test.ts +344 -0
  387. package/tests/commands/reaction.test.ts +101 -0
  388. package/tests/commands/snapshot.test.ts +308 -0
  389. package/tests/commands/user.test.ts +138 -0
  390. package/tests/commands/workspace.test.ts +528 -0
  391. package/tests/credential-manager.test.ts +241 -0
  392. package/tests/slack-client.test.ts +916 -0
  393. package/tests/types.test.ts +241 -0
  394. package/tsconfig.json +36 -0
@@ -0,0 +1,549 @@
1
+ import { execSync, spawn } from 'node:child_process'
2
+ import { createDecipheriv, pbkdf2Sync } from 'node:crypto'
3
+ import { existsSync, readdirSync, readFileSync } from 'node:fs'
4
+ import { homedir } from 'node:os'
5
+ import { join } from 'node:path'
6
+
7
+ export interface ExtractedDiscordToken {
8
+ token: string
9
+ }
10
+
11
+ export type DiscordVariant = 'stable' | 'canary' | 'ptb'
12
+
13
+ interface KeychainVariant {
14
+ service: string
15
+ account: string
16
+ }
17
+
18
+ interface CDPTarget {
19
+ id: string
20
+ type: string
21
+ title: string
22
+ url: string
23
+ webSocketDebuggerUrl: string
24
+ }
25
+
26
+ interface CDPMessage {
27
+ id: number
28
+ method?: string
29
+ params?: Record<string, unknown>
30
+ result?: { result?: { value?: unknown } }
31
+ error?: { code: number; message: string }
32
+ }
33
+
34
+ const TOKEN_REGEX = /[\w-]{24}\.[\w-]{6}\.[\w-]{25,110}/
35
+ const MFA_TOKEN_REGEX = /mfa\.[\w-]{84}/
36
+ const ENCRYPTED_PREFIX = 'dQw4w9WgXcQ:'
37
+
38
+ export const CDP_PORT = 9222
39
+ export const CDP_TIMEOUT = 5000
40
+ export const DISCORD_STARTUP_WAIT = 4000
41
+ export const TOKEN_EXTRACTION_JS = `(webpackChunkdiscord_app.push([[''], {}, e => { m = []; for (let c in e.c) m.push(e.c[c]); }]), m).find(m => m?.exports?.default?.getToken !== void 0).exports.default.getToken()`
42
+
43
+ const DISCORD_PROCESS_NAMES: Record<
44
+ DiscordVariant,
45
+ { darwin: string; win32: string; linux: string }
46
+ > = {
47
+ stable: { darwin: 'Discord', win32: 'Discord.exe', linux: 'discord' },
48
+ canary: { darwin: 'Discord Canary', win32: 'DiscordCanary.exe', linux: 'discordcanary' },
49
+ ptb: { darwin: 'Discord PTB', win32: 'DiscordPTB.exe', linux: 'discordptb' },
50
+ }
51
+
52
+ const DISCORD_APP_PATHS: Record<DiscordVariant, { darwin: string }> = {
53
+ stable: { darwin: '/Applications/Discord.app/Contents/MacOS/Discord' },
54
+ canary: { darwin: '/Applications/Discord Canary.app/Contents/MacOS/Discord Canary' },
55
+ ptb: { darwin: '/Applications/Discord PTB.app/Contents/MacOS/Discord PTB' },
56
+ }
57
+
58
+ export class DiscordTokenExtractor {
59
+ private platform: NodeJS.Platform
60
+ private startupWait: number
61
+ private killWait: number
62
+
63
+ constructor(platform?: NodeJS.Platform, startupWait?: number, killWait?: number) {
64
+ this.platform = platform ?? process.platform
65
+ this.startupWait = startupWait ?? DISCORD_STARTUP_WAIT
66
+ this.killWait = killWait ?? 1000
67
+ }
68
+
69
+ getDiscordDirs(): string[] {
70
+ switch (this.platform) {
71
+ case 'darwin':
72
+ return [
73
+ join(homedir(), 'Library', 'Application Support', 'Discord'),
74
+ join(homedir(), 'Library', 'Application Support', 'discordcanary'),
75
+ join(homedir(), 'Library', 'Application Support', 'discordptb'),
76
+ ]
77
+ case 'linux':
78
+ return [
79
+ join(homedir(), '.config', 'discord'),
80
+ join(homedir(), '.config', 'discordcanary'),
81
+ join(homedir(), '.config', 'discordptb'),
82
+ ]
83
+ case 'win32': {
84
+ const appdata = process.env.APPDATA || join(homedir(), 'AppData', 'Roaming')
85
+ return [
86
+ join(appdata, 'Discord'),
87
+ join(appdata, 'discordcanary'),
88
+ join(appdata, 'discordptb'),
89
+ ]
90
+ }
91
+ default:
92
+ return []
93
+ }
94
+ }
95
+
96
+ getKeychainVariants(): KeychainVariant[] {
97
+ return [
98
+ // Modern Discord (lowercase)
99
+ { service: 'discord Safe Storage', account: 'discord Key' },
100
+ { service: 'discordcanary Safe Storage', account: 'discordcanary Key' },
101
+ { service: 'discordptb Safe Storage', account: 'discordptb Key' },
102
+ // Legacy Discord (capitalized)
103
+ { service: 'Discord Safe Storage', account: 'Discord' },
104
+ { service: 'Discord Canary Safe Storage', account: 'Discord Canary' },
105
+ { service: 'Discord PTB Safe Storage', account: 'Discord PTB' },
106
+ ]
107
+ }
108
+
109
+ getVariantFromPath(path: string): DiscordVariant {
110
+ const lowerPath = path.toLowerCase()
111
+ if (lowerPath.includes('canary')) return 'canary'
112
+ if (lowerPath.includes('ptb')) return 'ptb'
113
+ return 'stable'
114
+ }
115
+
116
+ isValidToken(token: string): boolean {
117
+ if (!token || token.length === 0) return false
118
+ return TOKEN_REGEX.test(token) || MFA_TOKEN_REGEX.test(token)
119
+ }
120
+
121
+ isEncryptedToken(token: string): boolean {
122
+ return token.startsWith(ENCRYPTED_PREFIX)
123
+ }
124
+
125
+ async extract(): Promise<ExtractedDiscordToken | null> {
126
+ const levelDbToken = await this.extractFromLevelDB()
127
+ if (levelDbToken) {
128
+ return levelDbToken
129
+ }
130
+
131
+ if (this.platform === 'darwin') {
132
+ const cdpToken = await this.tryExtractViaCDP()
133
+ if (cdpToken) {
134
+ return { token: cdpToken }
135
+ }
136
+ }
137
+
138
+ return null
139
+ }
140
+
141
+ private async tryExtractViaCDP(): Promise<string | null> {
142
+ const token = await this.extractViaCDP()
143
+ if (token) {
144
+ return token
145
+ }
146
+
147
+ for (const variant of ['stable', 'canary', 'ptb'] as DiscordVariant[]) {
148
+ try {
149
+ const appPath = this.getAppPath(variant)
150
+ if (!existsSync(appPath)) continue
151
+
152
+ await this.launchDiscordWithDebug(variant)
153
+ const extractedToken = await this.extractViaCDP()
154
+ if (extractedToken) {
155
+ return extractedToken
156
+ }
157
+ } catch {}
158
+ }
159
+
160
+ return null
161
+ }
162
+
163
+ private async extractFromLevelDB(): Promise<ExtractedDiscordToken | null> {
164
+ const dirs = this.getDiscordDirs()
165
+
166
+ for (const dir of dirs) {
167
+ if (!existsSync(dir)) continue
168
+
169
+ const token = await this.extractFromDir(dir)
170
+ if (token) {
171
+ return { token }
172
+ }
173
+ }
174
+
175
+ return null
176
+ }
177
+
178
+ private async extractFromDir(discordDir: string): Promise<string | null> {
179
+ const levelDbPath = join(discordDir, 'Local Storage', 'leveldb')
180
+
181
+ if (!existsSync(levelDbPath)) return null
182
+
183
+ const tokens = this.extractTokensFromLDBFiles(levelDbPath, discordDir)
184
+ return tokens.length > 0 ? tokens[0] : null
185
+ }
186
+
187
+ private extractTokensFromLDBFiles(dbPath: string, discordDir: string): string[] {
188
+ const tokens: string[] = []
189
+
190
+ try {
191
+ const files = readdirSync(dbPath).filter((f) => f.endsWith('.ldb') || f.endsWith('.log'))
192
+
193
+ for (const file of files) {
194
+ const filePath = join(dbPath, file)
195
+ const content = readFileSync(filePath)
196
+ const extracted = this.extractTokensFromBuffer(content, discordDir)
197
+ tokens.push(...extracted)
198
+ }
199
+ } catch {
200
+ return tokens
201
+ }
202
+
203
+ return [...new Set(tokens)]
204
+ }
205
+
206
+ private extractTokensFromBuffer(buffer: Buffer, discordDir: string): string[] {
207
+ const tokens: string[] = []
208
+ const content = buffer.toString('utf8')
209
+
210
+ const encryptedMatches = content.match(new RegExp(`${ENCRYPTED_PREFIX}[A-Za-z0-9+/=]+`, 'g'))
211
+ if (encryptedMatches) {
212
+ for (const match of encryptedMatches) {
213
+ try {
214
+ const decrypted = this.decryptToken(match, discordDir)
215
+ if (decrypted && this.isValidToken(decrypted)) {
216
+ tokens.push(decrypted)
217
+ }
218
+ } catch {}
219
+ }
220
+ }
221
+
222
+ const standardMatches = content.match(TOKEN_REGEX)
223
+ if (standardMatches) {
224
+ for (const match of standardMatches) {
225
+ if (this.isValidToken(match)) {
226
+ tokens.push(match)
227
+ }
228
+ }
229
+ }
230
+
231
+ const mfaMatches = content.match(MFA_TOKEN_REGEX)
232
+ if (mfaMatches) {
233
+ for (const match of mfaMatches) {
234
+ tokens.push(match)
235
+ }
236
+ }
237
+
238
+ return tokens
239
+ }
240
+
241
+ private decryptToken(encryptedToken: string, discordDir: string): string | null {
242
+ if (!encryptedToken.startsWith(ENCRYPTED_PREFIX)) return null
243
+
244
+ const encryptedData = Buffer.from(encryptedToken.substring(ENCRYPTED_PREFIX.length), 'base64')
245
+
246
+ if (this.platform === 'win32') {
247
+ return this.decryptWindowsToken(encryptedData, discordDir)
248
+ } else if (this.platform === 'darwin') {
249
+ return this.decryptMacToken(encryptedData, discordDir)
250
+ }
251
+
252
+ return null
253
+ }
254
+
255
+ private decryptWindowsToken(encryptedData: Buffer, discordDir: string): string | null {
256
+ try {
257
+ const localStatePath = join(discordDir, 'Local State')
258
+ if (!existsSync(localStatePath)) return null
259
+
260
+ const localState = JSON.parse(readFileSync(localStatePath, 'utf8'))
261
+ const encryptedKey = Buffer.from(localState.os_crypt.encrypted_key, 'base64')
262
+
263
+ const dpapiBlobKey = encryptedKey.subarray(5)
264
+ const masterKey = this.decryptDPAPI(dpapiBlobKey)
265
+ if (!masterKey) return null
266
+
267
+ return this.decryptAESGCM(encryptedData, masterKey)
268
+ } catch {
269
+ return null
270
+ }
271
+ }
272
+
273
+ private decryptDPAPI(encryptedBlob: Buffer): Buffer | null {
274
+ try {
275
+ const b64 = encryptedBlob.toString('base64')
276
+ const psScript = `
277
+ Add-Type -AssemblyName System.Security
278
+ $bytes = [Convert]::FromBase64String('${b64}')
279
+ $decrypted = [Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, 'CurrentUser')
280
+ [Convert]::ToBase64String($decrypted)
281
+ `.replace(/\n/g, ' ')
282
+
283
+ const result = execSync(`powershell -Command "${psScript}"`, { encoding: 'utf8' })
284
+ return Buffer.from(result.trim(), 'base64')
285
+ } catch {
286
+ return null
287
+ }
288
+ }
289
+
290
+ private decryptMacToken(encryptedData: Buffer, discordDir: string): string | null {
291
+ const variant = this.getVariantFromPath(discordDir)
292
+ const keychainVariants = this.getKeychainVariants().filter((v) => {
293
+ const lowerAccount = v.account.toLowerCase()
294
+ if (variant === 'stable') return lowerAccount === 'discord' || lowerAccount === 'discord key'
295
+ if (variant === 'canary')
296
+ return lowerAccount === 'discord canary' || lowerAccount === 'discordcanary key'
297
+ if (variant === 'ptb')
298
+ return lowerAccount === 'discord ptb' || lowerAccount === 'discordptb key'
299
+ return false
300
+ })
301
+
302
+ for (const keychainVariant of keychainVariants) {
303
+ try {
304
+ const password = execSync(
305
+ `security find-generic-password -s "${keychainVariant.service}" -a "${keychainVariant.account}" -w 2>/dev/null`,
306
+ { encoding: 'utf8' }
307
+ ).trim()
308
+
309
+ const key = pbkdf2Sync(password, 'saltysalt', 1003, 16, 'sha1')
310
+ const decrypted = this.decryptAESCBC(encryptedData, key)
311
+ if (decrypted) return decrypted
312
+ } catch {}
313
+ }
314
+
315
+ return null
316
+ }
317
+
318
+ private decryptAESCBC(encryptedData: Buffer, key: Buffer): string | null {
319
+ try {
320
+ const ciphertext = encryptedData.subarray(3)
321
+ const iv = Buffer.alloc(16, 0x20)
322
+
323
+ const decipher = createDecipheriv('aes-128-cbc', key, iv)
324
+ decipher.setAutoPadding(true)
325
+
326
+ const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])
327
+ return decrypted.toString('utf8')
328
+ } catch {
329
+ return null
330
+ }
331
+ }
332
+
333
+ private decryptAESGCM(encryptedData: Buffer, key: Buffer): string | null {
334
+ try {
335
+ const iv = encryptedData.subarray(3, 15)
336
+ const authTag = encryptedData.subarray(-16)
337
+ const ciphertext = encryptedData.subarray(15, -16)
338
+
339
+ const decipher = createDecipheriv('aes-256-gcm', key, iv)
340
+ decipher.setAuthTag(authTag)
341
+
342
+ const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])
343
+ return decrypted.toString('utf8')
344
+ } catch {
345
+ return null
346
+ }
347
+ }
348
+
349
+ async isDiscordRunning(variant?: DiscordVariant): Promise<boolean> {
350
+ const variants = variant ? [variant] : (['stable', 'canary', 'ptb'] as DiscordVariant[])
351
+
352
+ for (const v of variants) {
353
+ const processName = this.getProcessName(v)
354
+ if (this.checkProcessRunning(processName)) {
355
+ return true
356
+ }
357
+ }
358
+ return false
359
+ }
360
+
361
+ private getProcessName(variant: DiscordVariant): string {
362
+ const platformKey = this.platform as 'darwin' | 'win32' | 'linux'
363
+ return DISCORD_PROCESS_NAMES[variant][platformKey] || DISCORD_PROCESS_NAMES[variant].linux
364
+ }
365
+
366
+ private checkProcessRunning(processName: string): boolean {
367
+ try {
368
+ if (this.platform === 'win32') {
369
+ const result = execSync(`tasklist /FI "IMAGENAME eq ${processName}" 2>nul`, {
370
+ encoding: 'utf8',
371
+ })
372
+ return result.toLowerCase().includes(processName.toLowerCase())
373
+ } else {
374
+ const result = execSync(`pgrep -f "${processName}" 2>/dev/null || true`, {
375
+ encoding: 'utf8',
376
+ })
377
+ return result.trim().length > 0
378
+ }
379
+ } catch {
380
+ return false
381
+ }
382
+ }
383
+
384
+ async killDiscord(variant?: DiscordVariant): Promise<void> {
385
+ const variants = variant ? [variant] : (['stable', 'canary', 'ptb'] as DiscordVariant[])
386
+
387
+ for (const v of variants) {
388
+ const processName = this.getProcessName(v)
389
+ this.killProcess(processName)
390
+ }
391
+
392
+ await new Promise((resolve) => setTimeout(resolve, this.killWait))
393
+ }
394
+
395
+ private killProcess(processName: string): void {
396
+ try {
397
+ if (this.platform === 'win32') {
398
+ execSync(`taskkill /F /IM "${processName}" 2>nul`, { encoding: 'utf8' })
399
+ } else {
400
+ execSync(`pkill -f "${processName}" 2>/dev/null || true`, { encoding: 'utf8' })
401
+ }
402
+ } catch {}
403
+ }
404
+
405
+ async launchDiscordWithDebug(variant: DiscordVariant, port: number = CDP_PORT): Promise<void> {
406
+ const appPath = this.getAppPath(variant)
407
+
408
+ if (!existsSync(appPath)) {
409
+ throw new Error(`Discord ${variant} not found at ${appPath}`)
410
+ }
411
+
412
+ await this.killDiscord(variant)
413
+
414
+ const args = [`--remote-debugging-port=${port}`]
415
+
416
+ if (this.platform === 'darwin') {
417
+ spawn(appPath, args, {
418
+ detached: true,
419
+ stdio: 'ignore',
420
+ }).unref()
421
+ } else if (this.platform === 'win32') {
422
+ spawn(appPath, args, {
423
+ detached: true,
424
+ stdio: 'ignore',
425
+ shell: true,
426
+ }).unref()
427
+ } else {
428
+ spawn(appPath, args, {
429
+ detached: true,
430
+ stdio: 'ignore',
431
+ }).unref()
432
+ }
433
+
434
+ await new Promise((resolve) => setTimeout(resolve, this.startupWait))
435
+ }
436
+
437
+ private getAppPath(variant: DiscordVariant): string {
438
+ if (this.platform === 'darwin') {
439
+ return DISCORD_APP_PATHS[variant].darwin
440
+ } else if (this.platform === 'win32') {
441
+ const localAppData = process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local')
442
+ const appName =
443
+ variant === 'stable' ? 'Discord' : variant === 'canary' ? 'DiscordCanary' : 'DiscordPTB'
444
+ return join(localAppData, appName, 'Update.exe')
445
+ } else {
446
+ return variant === 'stable' ? 'discord' : `discord${variant}`
447
+ }
448
+ }
449
+
450
+ async discoverCDPTargets(port: number = CDP_PORT): Promise<CDPTarget[]> {
451
+ try {
452
+ const response = await fetch(`http://localhost:${port}/json`, {
453
+ signal: AbortSignal.timeout(CDP_TIMEOUT),
454
+ })
455
+ if (!response.ok) {
456
+ return []
457
+ }
458
+ return (await response.json()) as CDPTarget[]
459
+ } catch {
460
+ return []
461
+ }
462
+ }
463
+
464
+ findDiscordPageTarget(targets: CDPTarget[]): CDPTarget | null {
465
+ const discordTarget = targets.find(
466
+ (t) =>
467
+ t.type === 'page' &&
468
+ (t.url.includes('discord.com') || t.title.toLowerCase().includes('discord'))
469
+ )
470
+ return discordTarget ?? null
471
+ }
472
+
473
+ async executeJSViaCDP(webSocketUrl: string, expression: string): Promise<unknown> {
474
+ return new Promise((resolve, reject) => {
475
+ const ws = new WebSocket(webSocketUrl)
476
+ const messageId = 1
477
+ let timeoutId: ReturnType<typeof setTimeout>
478
+
479
+ const cleanup = () => {
480
+ clearTimeout(timeoutId)
481
+ ws.close()
482
+ }
483
+
484
+ timeoutId = setTimeout(() => {
485
+ cleanup()
486
+ reject(new Error('CDP execution timeout'))
487
+ }, CDP_TIMEOUT)
488
+
489
+ ws.onopen = () => {
490
+ const message: CDPMessage = {
491
+ id: messageId,
492
+ method: 'Runtime.evaluate',
493
+ params: {
494
+ expression,
495
+ returnByValue: true,
496
+ },
497
+ }
498
+ ws.send(JSON.stringify(message))
499
+ }
500
+
501
+ ws.onmessage = (event) => {
502
+ try {
503
+ const response = JSON.parse(event.data as string) as CDPMessage
504
+ if (response.id === messageId) {
505
+ cleanup()
506
+ if (response.error) {
507
+ reject(new Error(response.error.message))
508
+ } else {
509
+ resolve(response.result?.result?.value)
510
+ }
511
+ }
512
+ } catch (e) {
513
+ cleanup()
514
+ reject(e)
515
+ }
516
+ }
517
+
518
+ ws.onerror = (error) => {
519
+ cleanup()
520
+ reject(error)
521
+ }
522
+ })
523
+ }
524
+
525
+ async extractViaCDP(port: number = CDP_PORT): Promise<string | null> {
526
+ const targets = await this.discoverCDPTargets(port)
527
+ if (targets.length === 0) {
528
+ return null
529
+ }
530
+
531
+ const discordTarget = this.findDiscordPageTarget(targets)
532
+ if (!discordTarget) {
533
+ return null
534
+ }
535
+
536
+ try {
537
+ const result = await this.executeJSViaCDP(
538
+ discordTarget.webSocketDebuggerUrl,
539
+ TOKEN_EXTRACTION_JS
540
+ )
541
+ if (typeof result === 'string' && this.isValidToken(result)) {
542
+ return result
543
+ }
544
+ return null
545
+ } catch {
546
+ return null
547
+ }
548
+ }
549
+ }