agent-messenger 2.6.3 → 2.8.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 (515) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.github/workflows/ci.yml +6 -0
  3. package/.oxfmtrc.json +13 -1
  4. package/.oxlintrc.json +10 -1
  5. package/README.md +1 -1
  6. package/dist/package.json +59 -58
  7. package/dist/src/platforms/channeltalk/client.d.ts.map +1 -1
  8. package/dist/src/platforms/channeltalk/client.js +2 -2
  9. package/dist/src/platforms/channeltalk/client.js.map +1 -1
  10. package/dist/src/platforms/channeltalk/commands/auth.d.ts.map +1 -1
  11. package/dist/src/platforms/channeltalk/commands/auth.js.map +1 -1
  12. package/dist/src/platforms/channeltalk/commands/message.d.ts.map +1 -1
  13. package/dist/src/platforms/channeltalk/commands/message.js.map +1 -1
  14. package/dist/src/platforms/channeltalk/commands/snapshot.d.ts.map +1 -1
  15. package/dist/src/platforms/channeltalk/commands/snapshot.js.map +1 -1
  16. package/dist/src/platforms/channeltalk/ensure-auth.d.ts.map +1 -1
  17. package/dist/src/platforms/channeltalk/ensure-auth.js.map +1 -1
  18. package/dist/src/platforms/channeltalk/token-extractor.d.ts +9 -23
  19. package/dist/src/platforms/channeltalk/token-extractor.d.ts.map +1 -1
  20. package/dist/src/platforms/channeltalk/token-extractor.js +109 -341
  21. package/dist/src/platforms/channeltalk/token-extractor.js.map +1 -1
  22. package/dist/src/platforms/channeltalkbot/client.d.ts +1 -1
  23. package/dist/src/platforms/channeltalkbot/client.d.ts.map +1 -1
  24. package/dist/src/platforms/channeltalkbot/client.js +4 -4
  25. package/dist/src/platforms/channeltalkbot/client.js.map +1 -1
  26. package/dist/src/platforms/channeltalkbot/commands/auth.d.ts.map +1 -1
  27. package/dist/src/platforms/channeltalkbot/commands/auth.js +4 -1
  28. package/dist/src/platforms/channeltalkbot/commands/auth.js.map +1 -1
  29. package/dist/src/platforms/channeltalkbot/commands/shared.d.ts.map +1 -1
  30. package/dist/src/platforms/channeltalkbot/commands/shared.js.map +1 -1
  31. package/dist/src/platforms/discord/commands/auth.js.map +1 -1
  32. package/dist/src/platforms/discord/commands/whoami.d.ts.map +1 -1
  33. package/dist/src/platforms/discord/commands/whoami.js.map +1 -1
  34. package/dist/src/platforms/discord/token-extractor.d.ts +2 -10
  35. package/dist/src/platforms/discord/token-extractor.d.ts.map +1 -1
  36. package/dist/src/platforms/discord/token-extractor.js +38 -172
  37. package/dist/src/platforms/discord/token-extractor.js.map +1 -1
  38. package/dist/src/platforms/discordbot/client.d.ts.map +1 -1
  39. package/dist/src/platforms/discordbot/client.js.map +1 -1
  40. package/dist/src/platforms/instagram/cli.d.ts.map +1 -1
  41. package/dist/src/platforms/instagram/cli.js +1 -4
  42. package/dist/src/platforms/instagram/cli.js.map +1 -1
  43. package/dist/src/platforms/instagram/client.d.ts.map +1 -1
  44. package/dist/src/platforms/instagram/client.js +8 -7
  45. package/dist/src/platforms/instagram/client.js.map +1 -1
  46. package/dist/src/platforms/instagram/commands/auth.d.ts.map +1 -1
  47. package/dist/src/platforms/instagram/commands/auth.js.map +1 -1
  48. package/dist/src/platforms/instagram/commands/chat.d.ts.map +1 -1
  49. package/dist/src/platforms/instagram/commands/chat.js.map +1 -1
  50. package/dist/src/platforms/instagram/commands/message.d.ts.map +1 -1
  51. package/dist/src/platforms/instagram/commands/message.js.map +1 -1
  52. package/dist/src/platforms/instagram/commands/shared.d.ts.map +1 -1
  53. package/dist/src/platforms/instagram/commands/shared.js.map +1 -1
  54. package/dist/src/platforms/instagram/credential-manager.d.ts.map +1 -1
  55. package/dist/src/platforms/instagram/credential-manager.js +1 -1
  56. package/dist/src/platforms/instagram/credential-manager.js.map +1 -1
  57. package/dist/src/platforms/instagram/ensure-auth.d.ts.map +1 -1
  58. package/dist/src/platforms/instagram/ensure-auth.js.map +1 -1
  59. package/dist/src/platforms/instagram/token-extractor.d.ts +7 -19
  60. package/dist/src/platforms/instagram/token-extractor.d.ts.map +1 -1
  61. package/dist/src/platforms/instagram/token-extractor.js +44 -270
  62. package/dist/src/platforms/instagram/token-extractor.js.map +1 -1
  63. package/dist/src/platforms/instagram/types.d.ts.map +1 -1
  64. package/dist/src/platforms/instagram/types.js +4 -2
  65. package/dist/src/platforms/instagram/types.js.map +1 -1
  66. package/dist/src/platforms/kakaotalk/auth/kakao-login.d.ts.map +1 -1
  67. package/dist/src/platforms/kakaotalk/auth/kakao-login.js +18 -4
  68. package/dist/src/platforms/kakaotalk/auth/kakao-login.js.map +1 -1
  69. package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
  70. package/dist/src/platforms/kakaotalk/client.js +3 -3
  71. package/dist/src/platforms/kakaotalk/client.js.map +1 -1
  72. package/dist/src/platforms/kakaotalk/commands/auth.d.ts.map +1 -1
  73. package/dist/src/platforms/kakaotalk/commands/auth.js +15 -9
  74. package/dist/src/platforms/kakaotalk/commands/auth.js.map +1 -1
  75. package/dist/src/platforms/kakaotalk/commands/shared.d.ts.map +1 -1
  76. package/dist/src/platforms/kakaotalk/commands/shared.js.map +1 -1
  77. package/dist/src/platforms/kakaotalk/protocol/connection.d.ts.map +1 -1
  78. package/dist/src/platforms/kakaotalk/protocol/connection.js.map +1 -1
  79. package/dist/src/platforms/kakaotalk/protocol/crypto.js +1 -1
  80. package/dist/src/platforms/kakaotalk/protocol/crypto.js.map +1 -1
  81. package/dist/src/platforms/kakaotalk/protocol/session.d.ts.map +1 -1
  82. package/dist/src/platforms/kakaotalk/protocol/session.js +1 -3
  83. package/dist/src/platforms/kakaotalk/protocol/session.js.map +1 -1
  84. package/dist/src/platforms/kakaotalk/token-extractor.js +5 -2
  85. package/dist/src/platforms/kakaotalk/token-extractor.js.map +1 -1
  86. package/dist/src/platforms/kakaotalk/types.d.ts.map +1 -1
  87. package/dist/src/platforms/kakaotalk/types.js +4 -2
  88. package/dist/src/platforms/kakaotalk/types.js.map +1 -1
  89. package/dist/src/platforms/line/cli.d.ts.map +1 -1
  90. package/dist/src/platforms/line/cli.js +1 -4
  91. package/dist/src/platforms/line/cli.js.map +1 -1
  92. package/dist/src/platforms/line/client.d.ts.map +1 -1
  93. package/dist/src/platforms/line/client.js +5 -13
  94. package/dist/src/platforms/line/client.js.map +1 -1
  95. package/dist/src/platforms/line/commands/chat.d.ts.map +1 -1
  96. package/dist/src/platforms/line/commands/chat.js.map +1 -1
  97. package/dist/src/platforms/line/commands/message.d.ts.map +1 -1
  98. package/dist/src/platforms/line/commands/message.js.map +1 -1
  99. package/dist/src/platforms/line/listener.js +1 -1
  100. package/dist/src/platforms/line/listener.js.map +1 -1
  101. package/dist/src/platforms/slack/cli.d.ts.map +1 -1
  102. package/dist/src/platforms/slack/cli.js.map +1 -1
  103. package/dist/src/platforms/slack/client-mappers.d.ts +14 -0
  104. package/dist/src/platforms/slack/client-mappers.d.ts.map +1 -0
  105. package/dist/src/platforms/slack/client-mappers.js +245 -0
  106. package/dist/src/platforms/slack/client-mappers.js.map +1 -0
  107. package/dist/src/platforms/slack/client.d.ts +0 -1
  108. package/dist/src/platforms/slack/client.d.ts.map +1 -1
  109. package/dist/src/platforms/slack/client.js +41 -455
  110. package/dist/src/platforms/slack/client.js.map +1 -1
  111. package/dist/src/platforms/slack/commands/channel.d.ts.map +1 -1
  112. package/dist/src/platforms/slack/commands/channel.js.map +1 -1
  113. package/dist/src/platforms/slack/commands/emoji.d.ts.map +1 -1
  114. package/dist/src/platforms/slack/commands/emoji.js +1 -3
  115. package/dist/src/platforms/slack/commands/emoji.js.map +1 -1
  116. package/dist/src/platforms/slack/commands/message.d.ts.map +1 -1
  117. package/dist/src/platforms/slack/commands/message.js.map +1 -1
  118. package/dist/src/platforms/slack/commands/reminder.d.ts.map +1 -1
  119. package/dist/src/platforms/slack/commands/reminder.js.map +1 -1
  120. package/dist/src/platforms/slack/commands/user.d.ts.map +1 -1
  121. package/dist/src/platforms/slack/commands/user.js.map +1 -1
  122. package/dist/src/platforms/slack/commands/usergroup.d.ts.map +1 -1
  123. package/dist/src/platforms/slack/commands/usergroup.js.map +1 -1
  124. package/dist/src/platforms/slack/commands/whoami.d.ts.map +1 -1
  125. package/dist/src/platforms/slack/commands/whoami.js.map +1 -1
  126. package/dist/src/platforms/slack/token-extractor.d.ts +2 -6
  127. package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
  128. package/dist/src/platforms/slack/token-extractor.js +35 -229
  129. package/dist/src/platforms/slack/token-extractor.js.map +1 -1
  130. package/dist/src/platforms/slackbot/cli.d.ts.map +1 -1
  131. package/dist/src/platforms/slackbot/cli.js +1 -1
  132. package/dist/src/platforms/slackbot/cli.js.map +1 -1
  133. package/dist/src/platforms/teams/client.d.ts.map +1 -1
  134. package/dist/src/platforms/teams/client.js +1 -1
  135. package/dist/src/platforms/teams/client.js.map +1 -1
  136. package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
  137. package/dist/src/platforms/teams/commands/auth.js +4 -1
  138. package/dist/src/platforms/teams/commands/auth.js.map +1 -1
  139. package/dist/src/platforms/teams/commands/whoami.d.ts.map +1 -1
  140. package/dist/src/platforms/teams/commands/whoami.js.map +1 -1
  141. package/dist/src/platforms/teams/token-extractor.d.ts +6 -18
  142. package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
  143. package/dist/src/platforms/teams/token-extractor.js +71 -324
  144. package/dist/src/platforms/teams/token-extractor.js.map +1 -1
  145. package/dist/src/platforms/telegram/cli.d.ts.map +1 -1
  146. package/dist/src/platforms/telegram/cli.js +1 -4
  147. package/dist/src/platforms/telegram/cli.js.map +1 -1
  148. package/dist/src/platforms/telegram/client.d.ts.map +1 -1
  149. package/dist/src/platforms/telegram/client.js.map +1 -1
  150. package/dist/src/platforms/telegram/commands/auth.d.ts.map +1 -1
  151. package/dist/src/platforms/telegram/commands/auth.js +1 -1
  152. package/dist/src/platforms/telegram/commands/auth.js.map +1 -1
  153. package/dist/src/platforms/telegram/commands/chat.d.ts.map +1 -1
  154. package/dist/src/platforms/telegram/commands/chat.js.map +1 -1
  155. package/dist/src/platforms/telegram/commands/message.d.ts.map +1 -1
  156. package/dist/src/platforms/telegram/commands/message.js.map +1 -1
  157. package/dist/src/platforms/telegram/commands/whoami.js +1 -1
  158. package/dist/src/platforms/telegram/commands/whoami.js.map +1 -1
  159. package/dist/src/platforms/telegram/credential-manager.d.ts.map +1 -1
  160. package/dist/src/platforms/telegram/credential-manager.js +6 -2
  161. package/dist/src/platforms/telegram/credential-manager.js.map +1 -1
  162. package/dist/src/platforms/telegram/my-telegram-org.js.map +1 -1
  163. package/dist/src/platforms/webex/cli.d.ts.map +1 -1
  164. package/dist/src/platforms/webex/cli.js +1 -4
  165. package/dist/src/platforms/webex/cli.js.map +1 -1
  166. package/dist/src/platforms/webex/client.d.ts.map +1 -1
  167. package/dist/src/platforms/webex/client.js +19 -15
  168. package/dist/src/platforms/webex/client.js.map +1 -1
  169. package/dist/src/platforms/webex/commands/auth.d.ts.map +1 -1
  170. package/dist/src/platforms/webex/commands/auth.js +1 -3
  171. package/dist/src/platforms/webex/commands/auth.js.map +1 -1
  172. package/dist/src/platforms/webex/commands/member.d.ts.map +1 -1
  173. package/dist/src/platforms/webex/commands/member.js +1 -3
  174. package/dist/src/platforms/webex/commands/member.js.map +1 -1
  175. package/dist/src/platforms/webex/commands/message.d.ts.map +1 -1
  176. package/dist/src/platforms/webex/commands/message.js.map +1 -1
  177. package/dist/src/platforms/webex/commands/snapshot.d.ts.map +1 -1
  178. package/dist/src/platforms/webex/commands/snapshot.js.map +1 -1
  179. package/dist/src/platforms/webex/commands/space.d.ts.map +1 -1
  180. package/dist/src/platforms/webex/commands/space.js.map +1 -1
  181. package/dist/src/platforms/webex/commands/whoami.d.ts.map +1 -1
  182. package/dist/src/platforms/webex/commands/whoami.js.map +1 -1
  183. package/dist/src/platforms/webex/credential-manager.d.ts.map +1 -1
  184. package/dist/src/platforms/webex/credential-manager.js.map +1 -1
  185. package/dist/src/platforms/webex/ensure-auth.d.ts.map +1 -1
  186. package/dist/src/platforms/webex/ensure-auth.js +1 -3
  187. package/dist/src/platforms/webex/ensure-auth.js.map +1 -1
  188. package/dist/src/platforms/webex/index.d.ts +1 -1
  189. package/dist/src/platforms/webex/index.d.ts.map +1 -1
  190. package/dist/src/platforms/webex/index.js.map +1 -1
  191. package/dist/src/platforms/webex/markdown-to-html.d.ts +3 -0
  192. package/dist/src/platforms/webex/markdown-to-html.d.ts.map +1 -0
  193. package/dist/src/platforms/webex/markdown-to-html.js +161 -0
  194. package/dist/src/platforms/webex/markdown-to-html.js.map +1 -0
  195. package/dist/src/platforms/webex/token-extractor.d.ts.map +1 -1
  196. package/dist/src/platforms/webex/token-extractor.js +5 -14
  197. package/dist/src/platforms/webex/token-extractor.js.map +1 -1
  198. package/dist/src/platforms/wechatbot/client.d.ts.map +1 -1
  199. package/dist/src/platforms/wechatbot/client.js.map +1 -1
  200. package/dist/src/platforms/wechatbot/commands/message.d.ts.map +1 -1
  201. package/dist/src/platforms/wechatbot/commands/message.js.map +1 -1
  202. package/dist/src/platforms/whatsapp/cli.d.ts.map +1 -1
  203. package/dist/src/platforms/whatsapp/cli.js +1 -4
  204. package/dist/src/platforms/whatsapp/cli.js.map +1 -1
  205. package/dist/src/platforms/whatsapp/commands/chat.d.ts.map +1 -1
  206. package/dist/src/platforms/whatsapp/commands/chat.js.map +1 -1
  207. package/dist/src/platforms/whatsapp/commands/message.d.ts.map +1 -1
  208. package/dist/src/platforms/whatsapp/commands/message.js.map +1 -1
  209. package/dist/src/platforms/whatsapp/commands/shared.d.ts.map +1 -1
  210. package/dist/src/platforms/whatsapp/commands/shared.js.map +1 -1
  211. package/dist/src/platforms/whatsapp/credential-manager.d.ts.map +1 -1
  212. package/dist/src/platforms/whatsapp/credential-manager.js +1 -1
  213. package/dist/src/platforms/whatsapp/credential-manager.js.map +1 -1
  214. package/dist/src/platforms/whatsapp/ensure-auth.d.ts.map +1 -1
  215. package/dist/src/platforms/whatsapp/ensure-auth.js.map +1 -1
  216. package/dist/src/platforms/whatsappbot/client.d.ts.map +1 -1
  217. package/dist/src/platforms/whatsappbot/client.js +2 -2
  218. package/dist/src/platforms/whatsappbot/client.js.map +1 -1
  219. package/dist/src/platforms/whatsappbot/commands/auth.d.ts.map +1 -1
  220. package/dist/src/platforms/whatsappbot/commands/auth.js +4 -1
  221. package/dist/src/platforms/whatsappbot/commands/auth.js.map +1 -1
  222. package/dist/src/platforms/whatsappbot/commands/message.d.ts.map +1 -1
  223. package/dist/src/platforms/whatsappbot/commands/message.js.map +1 -1
  224. package/dist/src/platforms/whatsappbot/commands/shared.d.ts.map +1 -1
  225. package/dist/src/platforms/whatsappbot/commands/shared.js.map +1 -1
  226. package/dist/src/shared/chromium/browsers.d.ts +7 -0
  227. package/dist/src/shared/chromium/browsers.d.ts.map +1 -0
  228. package/dist/src/shared/chromium/browsers.js +89 -0
  229. package/dist/src/shared/chromium/browsers.js.map +1 -0
  230. package/dist/src/shared/chromium/cookie-reader.d.ts +20 -0
  231. package/dist/src/shared/chromium/cookie-reader.d.ts.map +1 -0
  232. package/dist/src/shared/chromium/cookie-reader.js +99 -0
  233. package/dist/src/shared/chromium/cookie-reader.js.map +1 -0
  234. package/dist/src/shared/chromium/decryptor.d.ts +42 -0
  235. package/dist/src/shared/chromium/decryptor.d.ts.map +1 -0
  236. package/dist/src/shared/chromium/decryptor.js +205 -0
  237. package/dist/src/shared/chromium/decryptor.js.map +1 -0
  238. package/dist/src/shared/chromium/index.d.ts +6 -0
  239. package/dist/src/shared/chromium/index.d.ts.map +1 -0
  240. package/dist/src/shared/chromium/index.js +4 -0
  241. package/dist/src/shared/chromium/index.js.map +1 -0
  242. package/dist/src/shared/chromium/types.d.ts +11 -0
  243. package/dist/src/shared/chromium/types.d.ts.map +1 -0
  244. package/dist/src/shared/chromium/types.js +2 -0
  245. package/dist/src/shared/chromium/types.js.map +1 -0
  246. package/dist/src/shared/utils/derived-key-cache.d.ts +1 -1
  247. package/dist/src/shared/utils/derived-key-cache.d.ts.map +1 -1
  248. package/dist/src/shared/utils/linux-keyring.js +4 -1
  249. package/dist/src/shared/utils/linux-keyring.js.map +1 -1
  250. package/dist/src/tui/adapters/kakaotalk-adapter.d.ts.map +1 -1
  251. package/dist/src/tui/adapters/kakaotalk-adapter.js +6 -1
  252. package/dist/src/tui/adapters/kakaotalk-adapter.js.map +1 -1
  253. package/dist/src/tui/adapters/telegram-adapter.js +1 -1
  254. package/dist/src/tui/adapters/telegram-adapter.js.map +1 -1
  255. package/dist/src/tui/adapters/webex-adapter.js +1 -1
  256. package/dist/src/tui/adapters/webex-adapter.js.map +1 -1
  257. package/dist/src/tui/app.d.ts.map +1 -1
  258. package/dist/src/tui/app.js +112 -23
  259. package/dist/src/tui/app.js.map +1 -1
  260. package/dist/src/tui/utils.d.ts.map +1 -1
  261. package/dist/src/tui/utils.js +11 -13
  262. package/dist/src/tui/utils.js.map +1 -1
  263. package/dist/src/tui/views/channel-picker.d.ts.map +1 -1
  264. package/dist/src/tui/views/channel-picker.js.map +1 -1
  265. package/dist/src/tui/views/workspace-picker.d.ts.map +1 -1
  266. package/dist/src/tui/views/workspace-picker.js.map +1 -1
  267. package/docs/content/docs/cli/channeltalk.mdx +24 -22
  268. package/docs/content/docs/cli/channeltalkbot.mdx +7 -7
  269. package/docs/content/docs/cli/instagram.mdx +4 -4
  270. package/docs/content/docs/cli/kakaotalk.mdx +9 -8
  271. package/docs/content/docs/cli/line.mdx +14 -14
  272. package/docs/content/docs/cli/webex.mdx +19 -19
  273. package/docs/content/docs/cli/wechatbot.mdx +12 -11
  274. package/docs/content/docs/cli/whatsapp.mdx +5 -4
  275. package/docs/content/docs/cli/whatsappbot.mdx +11 -11
  276. package/docs/content/docs/index.mdx +7 -7
  277. package/docs/content/docs/meta.json +1 -9
  278. package/docs/content/docs/sdk/channeltalk.mdx +5 -6
  279. package/docs/content/docs/sdk/channeltalkbot.mdx +6 -12
  280. package/docs/content/docs/sdk/discord.mdx +36 -43
  281. package/docs/content/docs/sdk/instagram.mdx +18 -18
  282. package/docs/content/docs/sdk/kakaotalk.mdx +27 -18
  283. package/docs/content/docs/sdk/line.mdx +8 -13
  284. package/docs/content/docs/sdk/meta.json +14 -1
  285. package/docs/content/docs/sdk/slack.mdx +36 -42
  286. package/docs/content/docs/sdk/teams.mdx +2 -8
  287. package/docs/content/docs/sdk/webex.mdx +2 -12
  288. package/docs/content/docs/sdk/wechatbot.mdx +1 -5
  289. package/docs/content/docs/sdk/whatsapp.mdx +10 -19
  290. package/docs/content/docs/sdk/whatsappbot.mdx +2 -10
  291. package/docs/content/docs/tui.mdx +23 -23
  292. package/docs/src/app/page.tsx +353 -108
  293. package/e2e/channeltalkbot.e2e.test.ts +1 -5
  294. package/e2e/config.ts +6 -2
  295. package/package.json +59 -58
  296. package/scripts/prepublish.ts +1 -3
  297. package/skills/agent-channeltalk/SKILL.md +1 -1
  298. package/skills/agent-channeltalkbot/SKILL.md +1 -1
  299. package/skills/agent-discord/SKILL.md +1 -1
  300. package/skills/agent-discordbot/SKILL.md +1 -1
  301. package/skills/agent-instagram/SKILL.md +1 -1
  302. package/skills/agent-kakaotalk/SKILL.md +1 -1
  303. package/skills/agent-line/SKILL.md +1 -1
  304. package/skills/agent-slack/SKILL.md +1 -1
  305. package/skills/agent-slackbot/SKILL.md +1 -1
  306. package/skills/agent-teams/SKILL.md +1 -1
  307. package/skills/agent-telegram/SKILL.md +1 -1
  308. package/skills/agent-webex/SKILL.md +1 -1
  309. package/skills/agent-wechatbot/SKILL.md +1 -1
  310. package/skills/agent-whatsapp/SKILL.md +1 -1
  311. package/skills/agent-whatsappbot/SKILL.md +1 -1
  312. package/src/platforms/channeltalk/client.test.ts +116 -29
  313. package/src/platforms/channeltalk/client.ts +26 -6
  314. package/src/platforms/channeltalk/commands/auth.test.ts +5 -5
  315. package/src/platforms/channeltalk/commands/auth.ts +19 -5
  316. package/src/platforms/channeltalk/commands/message.test.ts +2 -6
  317. package/src/platforms/channeltalk/commands/message.ts +5 -1
  318. package/src/platforms/channeltalk/commands/snapshot.test.ts +19 -4
  319. package/src/platforms/channeltalk/commands/snapshot.ts +5 -1
  320. package/src/platforms/channeltalk/ensure-auth.test.ts +20 -17
  321. package/src/platforms/channeltalk/ensure-auth.ts +6 -7
  322. package/src/platforms/channeltalk/index.ts +0 -1
  323. package/src/platforms/channeltalk/token-extractor.test.ts +33 -25
  324. package/src/platforms/channeltalk/token-extractor.ts +120 -372
  325. package/src/platforms/channeltalkbot/client.test.ts +1 -3
  326. package/src/platforms/channeltalkbot/client.ts +39 -13
  327. package/src/platforms/channeltalkbot/commands/auth.test.ts +3 -1
  328. package/src/platforms/channeltalkbot/commands/auth.ts +4 -1
  329. package/src/platforms/channeltalkbot/commands/bot.test.ts +13 -5
  330. package/src/platforms/channeltalkbot/commands/message.test.ts +12 -6
  331. package/src/platforms/channeltalkbot/commands/shared.ts +6 -2
  332. package/src/platforms/channeltalkbot/commands/snapshot.test.ts +17 -5
  333. package/src/platforms/channeltalkbot/credential-manager.test.ts +1 -1
  334. package/src/platforms/channeltalkbot/index.test.ts +0 -2
  335. package/src/platforms/channeltalkbot/index.ts +0 -1
  336. package/src/platforms/discord/commands/auth.test.ts +6 -4
  337. package/src/platforms/discord/commands/auth.ts +14 -14
  338. package/src/platforms/discord/commands/whoami.test.ts +2 -4
  339. package/src/platforms/discord/commands/whoami.ts +2 -0
  340. package/src/platforms/discord/ensure-auth.test.ts +5 -3
  341. package/src/platforms/discord/index.ts +0 -1
  342. package/src/platforms/discord/listener.test.ts +7 -1
  343. package/src/platforms/discord/token-extractor.test.ts +18 -12
  344. package/src/platforms/discord/token-extractor.ts +46 -190
  345. package/src/platforms/discordbot/client.ts +1 -4
  346. package/src/platforms/discordbot/commands/auth.test.ts +3 -1
  347. package/src/platforms/discordbot/commands/channel.test.ts +3 -1
  348. package/src/platforms/discordbot/commands/message.test.ts +3 -1
  349. package/src/platforms/discordbot/commands/server.test.ts +3 -1
  350. package/src/platforms/discordbot/commands/snapshot.test.ts +3 -1
  351. package/src/platforms/discordbot/commands/thread.test.ts +3 -1
  352. package/src/platforms/discordbot/commands/user.test.ts +3 -1
  353. package/src/platforms/instagram/cli.ts +1 -4
  354. package/src/platforms/instagram/client.test.ts +3 -8
  355. package/src/platforms/instagram/client.ts +39 -34
  356. package/src/platforms/instagram/commands/auth.test.ts +13 -12
  357. package/src/platforms/instagram/commands/auth.ts +136 -71
  358. package/src/platforms/instagram/commands/chat.test.ts +21 -24
  359. package/src/platforms/instagram/commands/chat.ts +2 -0
  360. package/src/platforms/instagram/commands/message.test.ts +29 -24
  361. package/src/platforms/instagram/commands/message.ts +3 -4
  362. package/src/platforms/instagram/commands/shared.ts +2 -5
  363. package/src/platforms/instagram/commands/whoami.test.ts +4 -6
  364. package/src/platforms/instagram/credential-manager.ts +2 -6
  365. package/src/platforms/instagram/ensure-auth.test.ts +1 -4
  366. package/src/platforms/instagram/ensure-auth.ts +6 -3
  367. package/src/platforms/instagram/listener.test.ts +7 -3
  368. package/src/platforms/instagram/token-extractor.test.ts +4 -16
  369. package/src/platforms/instagram/token-extractor.ts +55 -309
  370. package/src/platforms/instagram/types.test.ts +2 -6
  371. package/src/platforms/instagram/types.ts +4 -2
  372. package/src/platforms/kakaotalk/auth/kakao-login.ts +30 -8
  373. package/src/platforms/kakaotalk/client.test.ts +37 -25
  374. package/src/platforms/kakaotalk/client.ts +23 -12
  375. package/src/platforms/kakaotalk/commands/auth.test.ts +6 -18
  376. package/src/platforms/kakaotalk/commands/auth.ts +101 -47
  377. package/src/platforms/kakaotalk/commands/chat.test.ts +8 -11
  378. package/src/platforms/kakaotalk/commands/message.test.ts +15 -24
  379. package/src/platforms/kakaotalk/commands/shared.ts +1 -0
  380. package/src/platforms/kakaotalk/commands/whoami.test.ts +6 -10
  381. package/src/platforms/kakaotalk/credential-manager.test.ts +1 -4
  382. package/src/platforms/kakaotalk/index.test.ts +1 -0
  383. package/src/platforms/kakaotalk/index.ts +0 -2
  384. package/src/platforms/kakaotalk/listener.test.ts +7 -1
  385. package/src/platforms/kakaotalk/protocol/connection.ts +4 -1
  386. package/src/platforms/kakaotalk/protocol/crypto.ts +1 -1
  387. package/src/platforms/kakaotalk/protocol/session.ts +12 -6
  388. package/src/platforms/kakaotalk/token-extractor.ts +5 -5
  389. package/src/platforms/kakaotalk/types.ts +8 -7
  390. package/src/platforms/line/cli.ts +1 -4
  391. package/src/platforms/line/client.ts +12 -20
  392. package/src/platforms/line/commands/auth.test.ts +2 -1
  393. package/src/platforms/line/commands/chat.test.ts +2 -1
  394. package/src/platforms/line/commands/chat.ts +1 -4
  395. package/src/platforms/line/commands/friend.test.ts +2 -1
  396. package/src/platforms/line/commands/message.test.ts +2 -1
  397. package/src/platforms/line/commands/message.ts +2 -9
  398. package/src/platforms/line/commands/whoami.test.ts +2 -1
  399. package/src/platforms/line/credential-manager.test.ts +1 -2
  400. package/src/platforms/line/index.test.ts +1 -0
  401. package/src/platforms/line/listener.ts +1 -1
  402. package/src/platforms/line/types.test.ts +1 -0
  403. package/src/platforms/slack/cli.ts +3 -1
  404. package/src/platforms/slack/client-mappers.ts +297 -0
  405. package/src/platforms/slack/client.test.ts +532 -17
  406. package/src/platforms/slack/client.ts +69 -458
  407. package/src/platforms/slack/commands/channel.ts +1 -4
  408. package/src/platforms/slack/commands/emoji.test.ts +6 -4
  409. package/src/platforms/slack/commands/emoji.ts +20 -22
  410. package/src/platforms/slack/commands/message.ts +6 -1
  411. package/src/platforms/slack/commands/pin.test.ts +14 -12
  412. package/src/platforms/slack/commands/reminder.ts +7 -6
  413. package/src/platforms/slack/commands/user.ts +6 -1
  414. package/src/platforms/slack/commands/usergroup.test.ts +3 -3
  415. package/src/platforms/slack/commands/usergroup.ts +10 -7
  416. package/src/platforms/slack/commands/whoami.test.ts +1 -1
  417. package/src/platforms/slack/commands/whoami.ts +2 -0
  418. package/src/platforms/slack/index.ts +0 -2
  419. package/src/platforms/slack/listener.test.ts +1 -0
  420. package/src/platforms/slack/token-extractor.test.ts +7 -12
  421. package/src/platforms/slack/token-extractor.ts +47 -255
  422. package/src/platforms/slackbot/cli.ts +8 -1
  423. package/src/platforms/slackbot/commands/auth.test.ts +3 -1
  424. package/src/platforms/teams/client.ts +1 -1
  425. package/src/platforms/teams/commands/auth.test.ts +1 -1
  426. package/src/platforms/teams/commands/auth.ts +4 -1
  427. package/src/platforms/teams/commands/whoami.test.ts +2 -4
  428. package/src/platforms/teams/commands/whoami.ts +2 -0
  429. package/src/platforms/teams/index.ts +0 -1
  430. package/src/platforms/teams/token-extractor.ts +82 -350
  431. package/src/platforms/telegram/app-config.test.ts +1 -0
  432. package/src/platforms/telegram/chat-utils.test.ts +5 -1
  433. package/src/platforms/telegram/cli.ts +2 -4
  434. package/src/platforms/telegram/client.test.ts +16 -3
  435. package/src/platforms/telegram/client.ts +14 -4
  436. package/src/platforms/telegram/commands/auth.test.ts +1 -0
  437. package/src/platforms/telegram/commands/auth.ts +3 -4
  438. package/src/platforms/telegram/commands/chat.test.ts +2 -5
  439. package/src/platforms/telegram/commands/chat.ts +1 -0
  440. package/src/platforms/telegram/commands/message.test.ts +2 -5
  441. package/src/platforms/telegram/commands/message.ts +1 -0
  442. package/src/platforms/telegram/commands/shared.test.ts +1 -0
  443. package/src/platforms/telegram/commands/whoami.test.ts +5 -7
  444. package/src/platforms/telegram/commands/whoami.ts +1 -1
  445. package/src/platforms/telegram/credential-manager.test.ts +1 -0
  446. package/src/platforms/telegram/credential-manager.ts +11 -2
  447. package/src/platforms/telegram/my-telegram-org.ts +6 -2
  448. package/src/platforms/telegram/types.test.ts +1 -0
  449. package/src/platforms/webex/app-config.test.ts +1 -0
  450. package/src/platforms/webex/cli.ts +1 -4
  451. package/src/platforms/webex/client.test.ts +39 -12
  452. package/src/platforms/webex/client.ts +30 -61
  453. package/src/platforms/webex/commands/auth.test.ts +7 -1
  454. package/src/platforms/webex/commands/auth.ts +12 -15
  455. package/src/platforms/webex/commands/member.test.ts +1 -3
  456. package/src/platforms/webex/commands/member.ts +14 -19
  457. package/src/platforms/webex/commands/message.ts +4 -15
  458. package/src/platforms/webex/commands/snapshot.test.ts +28 -3
  459. package/src/platforms/webex/commands/snapshot.ts +3 -3
  460. package/src/platforms/webex/commands/space.test.ts +3 -3
  461. package/src/platforms/webex/commands/space.ts +2 -9
  462. package/src/platforms/webex/commands/whoami.test.ts +12 -5
  463. package/src/platforms/webex/commands/whoami.ts +2 -0
  464. package/src/platforms/webex/credential-manager.ts +11 -2
  465. package/src/platforms/webex/ensure-auth.ts +1 -3
  466. package/src/platforms/webex/index.ts +1 -7
  467. package/src/platforms/webex/markdown-to-html.test.ts +141 -0
  468. package/src/platforms/webex/markdown-to-html.ts +194 -0
  469. package/src/platforms/webex/token-extractor.ts +6 -29
  470. package/src/platforms/wechatbot/cli.ts +0 -0
  471. package/src/platforms/wechatbot/client.test.ts +6 -2
  472. package/src/platforms/wechatbot/client.ts +6 -1
  473. package/src/platforms/wechatbot/commands/auth.test.ts +3 -7
  474. package/src/platforms/wechatbot/commands/message.test.ts +1 -4
  475. package/src/platforms/wechatbot/commands/message.ts +5 -1
  476. package/src/platforms/wechatbot/commands/template.test.ts +1 -4
  477. package/src/platforms/wechatbot/commands/user.test.ts +2 -7
  478. package/src/platforms/whatsapp/cli.ts +1 -4
  479. package/src/platforms/whatsapp/commands/auth.test.ts +19 -22
  480. package/src/platforms/whatsapp/commands/chat.test.ts +21 -24
  481. package/src/platforms/whatsapp/commands/chat.ts +2 -0
  482. package/src/platforms/whatsapp/commands/message.test.ts +22 -24
  483. package/src/platforms/whatsapp/commands/message.ts +3 -5
  484. package/src/platforms/whatsapp/commands/shared.ts +2 -5
  485. package/src/platforms/whatsapp/commands/whoami.test.ts +2 -2
  486. package/src/platforms/whatsapp/credential-manager.ts +2 -6
  487. package/src/platforms/whatsapp/ensure-auth.test.ts +1 -4
  488. package/src/platforms/whatsapp/ensure-auth.ts +14 -6
  489. package/src/platforms/whatsapp/index.ts +0 -2
  490. package/src/platforms/whatsappbot/client.test.ts +13 -7
  491. package/src/platforms/whatsappbot/client.ts +18 -4
  492. package/src/platforms/whatsappbot/commands/auth.ts +4 -1
  493. package/src/platforms/whatsappbot/commands/message.test.ts +12 -2
  494. package/src/platforms/whatsappbot/commands/message.ts +16 -3
  495. package/src/platforms/whatsappbot/commands/shared.ts +3 -1
  496. package/src/platforms/whatsappbot/commands/whoami.test.ts +1 -3
  497. package/src/platforms/whatsappbot/index.ts +0 -2
  498. package/src/shared/chromium/browsers.test.ts +274 -0
  499. package/src/shared/chromium/browsers.ts +86 -0
  500. package/src/shared/chromium/cookie-reader.test.ts +274 -0
  501. package/src/shared/chromium/cookie-reader.ts +111 -0
  502. package/src/shared/chromium/decryptor.test.ts +449 -0
  503. package/src/shared/chromium/decryptor.ts +227 -0
  504. package/src/shared/chromium/index.ts +11 -0
  505. package/src/shared/chromium/types.ts +11 -0
  506. package/src/shared/utils/derived-key-cache.ts +1 -1
  507. package/src/shared/utils/linux-keyring.ts +4 -4
  508. package/src/tui/adapters/kakaotalk-adapter.ts +6 -1
  509. package/src/tui/adapters/telegram-adapter.ts +1 -1
  510. package/src/tui/adapters/webex-adapter.ts +1 -1
  511. package/src/tui/app.ts +149 -59
  512. package/src/tui/utils.test.ts +144 -145
  513. package/src/tui/utils.ts +27 -29
  514. package/src/tui/views/channel-picker.ts +1 -1
  515. package/src/tui/views/workspace-picker.ts +1 -1
@@ -173,10 +173,7 @@ async function usersAction(channel: string, options: { includeBots?: boolean; pr
173
173
  }
174
174
  }
175
175
 
176
- async function createAction(
177
- name: string,
178
- options: { private?: boolean; pretty?: boolean },
179
- ): Promise<void> {
176
+ async function createAction(name: string, options: { private?: boolean; pretty?: boolean }): Promise<void> {
180
177
  try {
181
178
  const credManager = new CredentialManager()
182
179
  const workspace = await credManager.getWorkspace()
@@ -7,10 +7,12 @@ describe('Emoji Commands', () => {
7
7
 
8
8
  beforeEach(() => {
9
9
  mockClient = {
10
- listEmoji: mock(async (): Promise<Record<string, string>> => ({
11
- party_blob: 'https://example.com/party_blob.gif',
12
- cool_sunglasses: 'https://example.com/cool_sunglasses.png',
13
- })),
10
+ listEmoji: mock(
11
+ async (): Promise<Record<string, string>> => ({
12
+ party_blob: 'https://example.com/party_blob.gif',
13
+ cool_sunglasses: 'https://example.com/cool_sunglasses.png',
14
+ }),
15
+ ),
14
16
  }
15
17
  })
16
18
 
@@ -6,28 +6,26 @@ import { formatOutput } from '@/shared/utils/output'
6
6
  import { SlackClient } from '../client'
7
7
  import { CredentialManager } from '../credential-manager'
8
8
 
9
- export const emojiCommand = new Command('emoji')
10
- .description('Emoji commands')
11
- .addCommand(
12
- new Command('list')
13
- .description('List all custom emoji in workspace')
14
- .option('--pretty', 'Pretty print JSON output')
15
- .action(async (options) => {
16
- try {
17
- const credManager = new CredentialManager()
18
- const ws = await credManager.getWorkspace()
9
+ export const emojiCommand = new Command('emoji').description('Emoji commands').addCommand(
10
+ new Command('list')
11
+ .description('List all custom emoji in workspace')
12
+ .option('--pretty', 'Pretty print JSON output')
13
+ .action(async (options) => {
14
+ try {
15
+ const credManager = new CredentialManager()
16
+ const ws = await credManager.getWorkspace()
19
17
 
20
- if (!ws) {
21
- console.log(formatOutput({ error: 'No current workspace set. Run "auth extract" first.' }, options.pretty))
22
- process.exit(1)
23
- }
18
+ if (!ws) {
19
+ console.log(formatOutput({ error: 'No current workspace set. Run "auth extract" first.' }, options.pretty))
20
+ process.exit(1)
21
+ }
24
22
 
25
- const client = await new SlackClient().login({ token: ws.token, cookie: ws.cookie })
26
- const emoji = await client.listEmoji()
23
+ const client = await new SlackClient().login({ token: ws.token, cookie: ws.cookie })
24
+ const emoji = await client.listEmoji()
27
25
 
28
- console.log(formatOutput(emoji, options.pretty))
29
- } catch (error) {
30
- handleError(error as Error)
31
- }
32
- }),
33
- )
26
+ console.log(formatOutput(emoji, options.pretty))
27
+ } catch (error) {
28
+ handleError(error as Error)
29
+ }
30
+ }),
31
+ )
@@ -270,7 +270,12 @@ async function scheduleAction(
270
270
 
271
271
  const postAtTimestamp = Number(postAt)
272
272
  if (!Number.isInteger(postAtTimestamp) || postAtTimestamp <= 0) {
273
- console.log(formatOutput({ error: 'Invalid post-at value. Use a Unix timestamp in seconds (e.g. 1700000000).' }, options.pretty))
273
+ console.log(
274
+ formatOutput(
275
+ { error: 'Invalid post-at value. Use a Unix timestamp in seconds (e.g. 1700000000).' },
276
+ options.pretty,
277
+ ),
278
+ )
274
279
  process.exit(1)
275
280
  }
276
281
 
@@ -10,19 +10,21 @@ describe('Pin Commands', () => {
10
10
  mockClient = {
11
11
  pinMessage: mock(async () => {}),
12
12
  unpinMessage: mock(async () => {}),
13
- listPins: mock(async (): Promise<SlackPin[]> => [
14
- {
15
- channel: 'C001',
16
- message: {
17
- ts: '1234567890.123456',
18
- text: 'Pinned message',
19
- user: 'U001',
20
- type: 'message',
13
+ listPins: mock(
14
+ async (): Promise<SlackPin[]> => [
15
+ {
16
+ channel: 'C001',
17
+ message: {
18
+ ts: '1234567890.123456',
19
+ text: 'Pinned message',
20
+ user: 'U001',
21
+ type: 'message',
22
+ },
23
+ date_created: 1234567890,
24
+ created_by: 'U001',
21
25
  },
22
- date_created: 1234567890,
23
- created_by: 'U001',
24
- },
25
- ]),
26
+ ],
27
+ ),
26
28
  }
27
29
  })
28
30
 
@@ -6,11 +6,7 @@ import { formatOutput } from '@/shared/utils/output'
6
6
  import { SlackClient } from '../client'
7
7
  import { CredentialManager } from '../credential-manager'
8
8
 
9
- async function addAction(
10
- text: string,
11
- time: string,
12
- options: { user?: string; pretty?: boolean },
13
- ): Promise<void> {
9
+ async function addAction(text: string, time: string, options: { user?: string; pretty?: boolean }): Promise<void> {
14
10
  try {
15
11
  const credManager = new CredentialManager()
16
12
  const ws = await credManager.getWorkspace()
@@ -22,7 +18,12 @@ async function addAction(
22
18
 
23
19
  const timeValue = Number(time)
24
20
  if (!Number.isInteger(timeValue) || timeValue <= 0) {
25
- console.log(formatOutput({ error: 'Invalid time value. Use a Unix timestamp in seconds (e.g. 1700000000).' }, options.pretty))
21
+ console.log(
22
+ formatOutput(
23
+ { error: 'Invalid time value. Use a Unix timestamp in seconds (e.g. 1700000000).' },
24
+ options.pretty,
25
+ ),
26
+ )
26
27
  process.exit(1)
27
28
  }
28
29
 
@@ -174,7 +174,12 @@ export const userCommand = new Command('user')
174
174
  ? (() => {
175
175
  const ts = Number(options.expiration)
176
176
  if (!Number.isInteger(ts) || ts <= 0) {
177
- console.log(formatOutput({ error: 'Invalid --expiration value. Use a Unix timestamp in seconds.' }, options.pretty))
177
+ console.log(
178
+ formatOutput(
179
+ { error: 'Invalid --expiration value. Use a Unix timestamp in seconds.' },
180
+ options.pretty,
181
+ ),
182
+ )
178
183
  process.exit(1)
179
184
  }
180
185
  return ts
@@ -86,9 +86,9 @@ describe('Usergroup Commands', () => {
86
86
  mockClient.updateUsergroup = mock(async () => {
87
87
  throw new Error('no_such_subteam')
88
88
  })
89
- await expect(
90
- (mockClient as SlackClient).updateUsergroup('S999', { name: 'Nope' }),
91
- ).rejects.toThrow('no_such_subteam')
89
+ await expect((mockClient as SlackClient).updateUsergroup('S999', { name: 'Nope' })).rejects.toThrow(
90
+ 'no_such_subteam',
91
+ )
92
92
  })
93
93
  })
94
94
 
@@ -18,7 +18,11 @@ async function getClient(pretty?: boolean): Promise<SlackClient | null> {
18
18
  return await new SlackClient().login({ token: ws.token, cookie: ws.cookie })
19
19
  }
20
20
 
21
- async function listAction(options: { includeDisabled?: boolean; includeUsers?: boolean; pretty?: boolean }): Promise<void> {
21
+ async function listAction(options: {
22
+ includeDisabled?: boolean
23
+ includeUsers?: boolean
24
+ pretty?: boolean
25
+ }): Promise<void> {
22
26
  try {
23
27
  const client = await getClient(options.pretty)
24
28
  if (!client) return process.exit(1)
@@ -136,7 +140,10 @@ async function disableAction(usergroupId: string, options: { pretty?: boolean })
136
140
  }
137
141
  }
138
142
 
139
- async function membersAction(usergroupId: string, options: { includeDisabled?: boolean; pretty?: boolean }): Promise<void> {
143
+ async function membersAction(
144
+ usergroupId: string,
145
+ options: { includeDisabled?: boolean; pretty?: boolean },
146
+ ): Promise<void> {
140
147
  try {
141
148
  const client = await getClient(options.pretty)
142
149
  if (!client) return process.exit(1)
@@ -151,11 +158,7 @@ async function membersAction(usergroupId: string, options: { includeDisabled?: b
151
158
  }
152
159
  }
153
160
 
154
- async function membersUpdateAction(
155
- usergroupId: string,
156
- users: string,
157
- options: { pretty?: boolean },
158
- ): Promise<void> {
161
+ async function membersUpdateAction(usergroupId: string, users: string, options: { pretty?: boolean }): Promise<void> {
159
162
  try {
160
163
  const client = await getClient(options.pretty)
161
164
  if (!client) return process.exit(1)
@@ -1,8 +1,8 @@
1
1
  import { afterEach, beforeEach, expect, spyOn, test } from 'bun:test'
2
2
 
3
3
  import { SlackClient } from '@/platforms/slack/client'
4
- import { CredentialManager } from '@/platforms/slack/credential-manager'
5
4
  import { whoamiAction, whoamiCommand } from '@/platforms/slack/commands/whoami'
5
+ import { CredentialManager } from '@/platforms/slack/credential-manager'
6
6
 
7
7
  let credManagerSpy: ReturnType<typeof spyOn>
8
8
  let clientTestAuthSpy: ReturnType<typeof spyOn>
@@ -1,6 +1,8 @@
1
1
  import { Command } from 'commander'
2
+
2
3
  import { handleError } from '@/shared/utils/error-handler'
3
4
  import { formatOutput } from '@/shared/utils/output'
5
+
4
6
  import { SlackClient } from '../client'
5
7
  import { CredentialManager } from '../credential-manager'
6
8
 
@@ -43,5 +43,3 @@ export {
43
43
  WorkspaceCredentialsSchema,
44
44
  ConfigSchema,
45
45
  } from './types'
46
-
47
-
@@ -16,6 +16,7 @@ class MockWs {
16
16
  sent: string[] = []
17
17
 
18
18
  constructor(_url: string, _options?: any) {
19
+ // oxlint-disable-next-line typescript-eslint/no-this-alias
19
20
  mockWsInstance = this
20
21
  }
21
22
 
@@ -813,10 +813,7 @@ describe('TokenExtractor browser fallback', () => {
813
813
  mkdirSync(leveldbDir, { recursive: true })
814
814
  writeFileSync(join(leveldbDir, '000001.log'), `"${token}"T12345678"name":"desktop-workspace"`)
815
815
 
816
- const extractFromBrowsersSpy = spyOn(
817
- TokenExtractor.prototype as any,
818
- 'extractFromBrowsers',
819
- ).mockResolvedValue([])
816
+ const extractFromBrowsersSpy = spyOn(TokenExtractor.prototype as any, 'extractFromBrowsers').mockResolvedValue([])
820
817
 
821
818
  // when
822
819
  const extractor = new TokenExtractor('darwin', slackDir)
@@ -843,10 +840,9 @@ describe('TokenExtractor browser fallback', () => {
843
840
  cookie: '',
844
841
  }
845
842
 
846
- const extractFromBrowsersSpy = spyOn(
847
- TokenExtractor.prototype as any,
848
- 'extractFromBrowsers',
849
- ).mockResolvedValue([browserWorkspace])
843
+ const extractFromBrowsersSpy = spyOn(TokenExtractor.prototype as any, 'extractFromBrowsers').mockResolvedValue([
844
+ browserWorkspace,
845
+ ])
850
846
 
851
847
  // when
852
848
  const extractor = new TokenExtractor('darwin', slackDir)
@@ -871,10 +867,9 @@ describe('TokenExtractor browser fallback', () => {
871
867
  cookie: 'xoxd-browser-cookie',
872
868
  }
873
869
 
874
- const extractFromBrowsersSpy = spyOn(
875
- TokenExtractor.prototype as any,
876
- 'extractFromBrowsers',
877
- ).mockResolvedValue([browserWorkspace])
870
+ const extractFromBrowsersSpy = spyOn(TokenExtractor.prototype as any, 'extractFromBrowsers').mockResolvedValue([
871
+ browserWorkspace,
872
+ ])
878
873
 
879
874
  // when
880
875
  const extractor = new TokenExtractor('darwin', slackDir)
@@ -7,61 +7,16 @@ import { join } from 'node:path'
7
7
 
8
8
  import { ClassicLevel } from 'classic-level'
9
9
 
10
+ import {
11
+ CHROMIUM_BROWSERS,
12
+ ChromiumCookieDecryptor,
13
+ ChromiumCookieReader,
14
+ discoverBrowserProfileDirs,
15
+ getBrowserBasePath,
16
+ } from '@/shared/chromium'
10
17
  import { DerivedKeyCache } from '@/shared/utils/derived-key-cache'
11
18
  import { lookupLinuxKeyringPassword } from '@/shared/utils/linux-keyring'
12
19
 
13
- interface BrowserConfig {
14
- name: string
15
- darwin: string
16
- linux: string
17
- win32: string
18
- }
19
-
20
- const BROWSERS: BrowserConfig[] = [
21
- {
22
- name: 'Chrome',
23
- darwin: join('Google', 'Chrome'),
24
- linux: 'google-chrome',
25
- win32: join('Google', 'Chrome', 'User Data'),
26
- },
27
- {
28
- name: 'Chrome Canary',
29
- darwin: join('Google', 'Chrome Canary'),
30
- linux: 'google-chrome-unstable',
31
- win32: join('Google', 'Chrome SxS', 'User Data'),
32
- },
33
- {
34
- name: 'Edge',
35
- darwin: 'Microsoft Edge',
36
- linux: 'microsoft-edge',
37
- win32: join('Microsoft', 'Edge', 'User Data'),
38
- },
39
- {
40
- name: 'Arc',
41
- darwin: join('Arc', 'User Data'),
42
- linux: '',
43
- win32: join('Arc', 'User Data'),
44
- },
45
- {
46
- name: 'Brave',
47
- darwin: join('BraveSoftware', 'Brave-Browser'),
48
- linux: join('BraveSoftware', 'Brave-Browser'),
49
- win32: join('BraveSoftware', 'Brave-Browser', 'User Data'),
50
- },
51
- {
52
- name: 'Vivaldi',
53
- darwin: 'Vivaldi',
54
- linux: 'vivaldi',
55
- win32: join('Vivaldi', 'User Data'),
56
- },
57
- {
58
- name: 'Chromium',
59
- darwin: 'Chromium',
60
- linux: 'chromium',
61
- win32: join('Chromium', 'User Data'),
62
- },
63
- ]
64
-
65
20
  const require = createRequire(import.meta.url)
66
21
 
67
22
  export interface ExtractedWorkspace {
@@ -106,6 +61,8 @@ export class TokenExtractor {
106
61
  private slackDir: string
107
62
  private keyCache: DerivedKeyCache
108
63
  private debugLog: ((message: string) => void) | null
64
+ private browserDecryptor: ChromiumCookieDecryptor
65
+ private browserCookieReader: ChromiumCookieReader
109
66
 
110
67
  constructor(
111
68
  platform?: NodeJS.Platform,
@@ -122,6 +79,8 @@ export class TokenExtractor {
122
79
  this.slackDir = slackDir ?? this.getSlackDir()
123
80
  this.keyCache = keyCache ?? new DerivedKeyCache()
124
81
  this.debugLog = debugLog ?? null
82
+ this.browserDecryptor = new ChromiumCookieDecryptor({ platform: this.platform })
83
+ this.browserCookieReader = new ChromiumCookieReader()
125
84
  }
126
85
 
127
86
  private debug(message: string): void {
@@ -267,11 +226,11 @@ export class TokenExtractor {
267
226
  const results: ExtractedWorkspace[] = []
268
227
  const seenTokens = new Set<string>()
269
228
 
270
- for (const browser of BROWSERS) {
271
- const browserBase = this.getBrowserBasePath(browser)
229
+ for (const browser of CHROMIUM_BROWSERS) {
230
+ const browserBase = getBrowserBasePath(browser, this.platform)
272
231
  if (!browserBase) continue
273
232
 
274
- const profileDirs = this.discoverBrowserProfileDirs(browserBase)
233
+ const profileDirs = discoverBrowserProfileDirs(browserBase)
275
234
  for (const profileDir of profileDirs) {
276
235
  const leveldbDir = join(profileDir, 'Local Storage', 'leveldb')
277
236
  if (!existsSync(leveldbDir)) continue
@@ -303,54 +262,8 @@ export class TokenExtractor {
303
262
  return results
304
263
  }
305
264
 
306
- private getBrowserBasePath(browser: BrowserConfig): string | null {
307
- let relative: string
308
-
309
- switch (this.platform) {
310
- case 'darwin':
311
- relative = browser.darwin
312
- if (!relative) return null
313
- return join(homedir(), 'Library', 'Application Support', relative)
314
- case 'linux':
315
- relative = browser.linux
316
- if (!relative) return null
317
- return join(homedir(), '.config', relative)
318
- case 'win32':
319
- relative = browser.win32
320
- if (!relative) return null
321
- return join(
322
- process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local'),
323
- relative,
324
- )
325
- default:
326
- return null
327
- }
328
- }
329
-
330
- private discoverBrowserProfileDirs(browserBase: string): string[] {
331
- const dirs: string[] = []
332
-
333
- dirs.push(join(browserBase, 'Default'))
334
-
335
- if (!existsSync(browserBase)) return dirs
336
-
337
- try {
338
- const entries = readdirSync(browserBase, { withFileTypes: true })
339
- for (const entry of entries) {
340
- if (!entry.isDirectory()) continue
341
- if (!/^Profile \d+$/i.test(entry.name)) continue
342
- dirs.push(join(browserBase, entry.name))
343
- }
344
- } catch {}
345
-
346
- return dirs
347
- }
348
-
349
265
  private async extractCookieFromBrowserProfile(profileDir: string, browserBase: string): Promise<string> {
350
- const cookiePaths = [
351
- join(profileDir, 'Cookies'),
352
- join(profileDir, 'Network', 'Cookies'),
353
- ]
266
+ const cookiePaths = [join(profileDir, 'Cookies'), join(profileDir, 'Network', 'Cookies')]
354
267
 
355
268
  for (const cookiePath of cookiePaths) {
356
269
  if (!existsSync(cookiePath)) continue
@@ -363,166 +276,35 @@ export class TokenExtractor {
363
276
  }
364
277
 
365
278
  private async extractCookieFromBrowserSQLite(cookiesPath: string, browserBase: string): Promise<string> {
366
- const tempDbPath = join(tmpdir(), `slack-browser-cookies-${Date.now()}-${Math.random().toString(36).slice(2)}.db`)
367
-
368
- try {
369
- copyFileSync(cookiesPath, tempDbPath)
370
- } catch {
371
- return ''
279
+ const sql = `SELECT value, encrypted_value
280
+ FROM cookies
281
+ WHERE name = 'd' AND host_key LIKE '%slack.com%'
282
+ ORDER BY last_access_utc DESC
283
+ LIMIT 1`
284
+
285
+ type CookieRow = {
286
+ value?: string
287
+ encrypted_value?: Uint8Array | Buffer
372
288
  }
373
289
 
374
- try {
375
- const sql = `SELECT value, encrypted_value
376
- FROM cookies
377
- WHERE name = 'd' AND host_key LIKE '%slack.com%'
378
- ORDER BY last_access_utc DESC
379
- LIMIT 1`
290
+ const row = await this.browserCookieReader.queryFirst<CookieRow>(cookiesPath, sql)
291
+ if (!row) return ''
380
292
 
381
- type CookieRow = {
382
- value?: string
383
- encrypted_value?: Uint8Array | Buffer
384
- } | null
293
+ if (row.value?.startsWith('xoxd-')) return row.value
385
294
 
386
- let row: CookieRow
387
- if (typeof globalThis.Bun !== 'undefined') {
388
- const { Database } = require('bun:sqlite')
389
- const db = new Database(tempDbPath, { readonly: true })
390
- row = db.query(sql).get() as CookieRow
391
- db.close()
392
- } else {
393
- const Database = require('better-sqlite3')
394
- const db = new Database(tempDbPath, { readonly: true })
395
- row = db.prepare(sql).get() as CookieRow
396
- db.close()
397
- }
398
-
399
- if (!row) return ''
400
-
401
- if (row.value?.startsWith('xoxd-')) return row.value
402
-
403
- if (row.encrypted_value && row.encrypted_value.length > 0) {
404
- return this.decryptBrowserCookieForSlack(Buffer.from(row.encrypted_value), browserBase) ?? ''
405
- }
406
-
407
- return ''
408
- } catch {
409
- return ''
410
- } finally {
411
- try {
412
- rmSync(tempDbPath, { force: true })
413
- } catch {}
414
- }
415
- }
416
-
417
- private decryptBrowserCookieForSlack(encrypted: Buffer, browserBase: string): string | null {
418
- const str = encrypted.toString('utf8')
419
- if (str.startsWith('xoxd-')) return str
420
-
421
- const prefix = encrypted.length > 3 ? encrypted.subarray(0, 3).toString() : ''
422
-
423
- if (prefix === 'v10') {
424
- if (this.platform === 'win32') {
425
- return this.decryptBrowserV10CookieWindows(encrypted, browserBase)
426
- }
427
- if (this.platform === 'linux') {
428
- return this.decryptV10CookieLinux(encrypted)
429
- }
430
- return this.decryptBrowserV10CookieMac(encrypted)
431
- }
432
-
433
- if (prefix === 'v11') {
434
- if (this.platform === 'linux') {
435
- return this.decryptV11CookieLinux(encrypted)
436
- }
437
- if (this.platform === 'darwin') {
438
- return this.decryptBrowserV10CookieMac(encrypted)
439
- }
440
- }
441
-
442
- if (this.platform === 'win32' && encrypted.length > 0) {
443
- const decrypted = this.decryptDPAPI(encrypted)
295
+ if (row.encrypted_value && row.encrypted_value.length > 0) {
296
+ const localStatePath = join(browserBase, 'Local State')
297
+ const decrypted = this.browserDecryptor.decryptCookie(
298
+ Buffer.from(row.encrypted_value),
299
+ existsSync(localStatePath) ? localStatePath : undefined,
300
+ )
444
301
  if (decrypted) {
445
- const text = decrypted.toString('utf8')
446
- const match = text.match(/xoxd-[A-Za-z0-9%]+/)
447
- return match ? match[0] : null
448
- }
449
- }
450
-
451
- return null
452
- }
453
-
454
- private decryptBrowserV10CookieMac(encrypted: Buffer): string | null {
455
- const keychainVariants = [
456
- { service: 'Chrome Safe Storage', account: 'Chrome' },
457
- { service: 'Chrome Canary Safe Storage', account: 'Chrome Canary' },
458
- { service: 'Microsoft Edge Safe Storage', account: 'Microsoft Edge' },
459
- { service: 'Arc Safe Storage', account: 'Arc' },
460
- { service: 'Brave Safe Storage', account: 'Brave' },
461
- { service: 'Vivaldi Safe Storage', account: 'Vivaldi' },
462
- { service: 'Chromium Safe Storage', account: 'Chromium' },
463
- ]
464
-
465
- for (const variant of keychainVariants) {
466
- try {
467
- const password = execSync(
468
- `security find-generic-password -s "${variant.service}" -a "${variant.account}" -w 2>/dev/null`,
469
- { encoding: 'utf8' },
470
- ).trim()
471
-
472
- const key = pbkdf2Sync(password, 'saltysalt', 1003, 16, 'sha1')
473
- const result = this.decryptLinuxCookieWithKey(encrypted, key)
474
- if (result) return result
475
- } catch {}
476
- }
477
-
478
- return null
479
- }
480
-
481
- private decryptBrowserV10CookieWindows(encrypted: Buffer, browserBase: string): string | null {
482
- try {
483
- const masterKey = this.getBrowserWindowsMasterKey(browserBase)
484
- if (!masterKey) {
485
- const decrypted = this.decryptDPAPI(encrypted.subarray(3))
486
- if (!decrypted) return null
487
- const text = decrypted.toString('utf8')
488
- const match = text.match(/xoxd-[A-Za-z0-9%]+/)
489
- return match ? match[0] : null
302
+ const match = decrypted.match(/xoxd-[A-Za-z0-9%]+/)
303
+ return match ? match[0] : ''
490
304
  }
491
-
492
- const nonce = encrypted.subarray(3, 3 + 12)
493
- const ciphertextWithTag = encrypted.subarray(3 + 12)
494
- const tag = ciphertextWithTag.subarray(ciphertextWithTag.length - 16)
495
- const ciphertext = ciphertextWithTag.subarray(0, ciphertextWithTag.length - 16)
496
-
497
- const decipher = createDecipheriv('aes-256-gcm', masterKey, nonce)
498
- decipher.setAuthTag(tag)
499
- const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString('utf8')
500
-
501
- const match = decrypted.match(/xoxd-[A-Za-z0-9%]+/)
502
- return match ? match[0] : null
503
- } catch {
504
- return null
505
305
  }
506
- }
507
-
508
- private getBrowserWindowsMasterKey(browserBase: string): Buffer | null {
509
- try {
510
- const localStatePath = join(browserBase, 'Local State')
511
- if (!existsSync(localStatePath)) return null
512
-
513
- const localState = JSON.parse(readFileSync(localStatePath, 'utf8')) as {
514
- os_crypt?: { encrypted_key?: string }
515
- }
516
- const encryptedKeyB64 = localState?.os_crypt?.encrypted_key
517
- if (!encryptedKeyB64) return null
518
-
519
- const encryptedKey = Buffer.from(encryptedKeyB64, 'base64')
520
- if (encryptedKey.subarray(0, 5).toString() !== 'DPAPI') return null
521
306
 
522
- return this.decryptDPAPI(encryptedKey.subarray(5))
523
- } catch {
524
- return null
525
- }
307
+ return ''
526
308
  }
527
309
 
528
310
  private async extractTokensFromLevelDB(): Promise<TokenInfo[]> {
@@ -1157,7 +939,17 @@ export class TokenExtractor {
1157
939
  }
1158
940
 
1159
941
  private decryptV11CookieLinux(encrypted: Buffer): string | null {
1160
- const appNames = ['Slack', 'slack', 'Chrome', 'chrome', 'Chromium', 'chromium', 'Microsoft Edge', 'Brave', 'Vivaldi']
942
+ const appNames = [
943
+ 'Slack',
944
+ 'slack',
945
+ 'Chrome',
946
+ 'chrome',
947
+ 'Chromium',
948
+ 'chromium',
949
+ 'Microsoft Edge',
950
+ 'Brave',
951
+ 'Vivaldi',
952
+ ]
1161
953
  for (const appName of appNames) {
1162
954
  try {
1163
955
  const keyringPassword = this.getLinuxKeyringPassword(appName)