agent-messenger 2.7.0 → 2.9.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 (553) 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 -12
  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 +4 -2
  15. package/dist/src/platforms/channeltalk/commands/snapshot.d.ts.map +1 -1
  16. package/dist/src/platforms/channeltalk/commands/snapshot.js +86 -31
  17. package/dist/src/platforms/channeltalk/commands/snapshot.js.map +1 -1
  18. package/dist/src/platforms/channeltalk/ensure-auth.d.ts.map +1 -1
  19. package/dist/src/platforms/channeltalk/ensure-auth.js.map +1 -1
  20. package/dist/src/platforms/channeltalk/token-extractor.d.ts +9 -23
  21. package/dist/src/platforms/channeltalk/token-extractor.d.ts.map +1 -1
  22. package/dist/src/platforms/channeltalk/token-extractor.js +109 -341
  23. package/dist/src/platforms/channeltalk/token-extractor.js.map +1 -1
  24. package/dist/src/platforms/channeltalkbot/client.d.ts +1 -1
  25. package/dist/src/platforms/channeltalkbot/client.d.ts.map +1 -1
  26. package/dist/src/platforms/channeltalkbot/client.js +4 -4
  27. package/dist/src/platforms/channeltalkbot/client.js.map +1 -1
  28. package/dist/src/platforms/channeltalkbot/commands/auth.d.ts.map +1 -1
  29. package/dist/src/platforms/channeltalkbot/commands/auth.js +4 -1
  30. package/dist/src/platforms/channeltalkbot/commands/auth.js.map +1 -1
  31. package/dist/src/platforms/channeltalkbot/commands/shared.d.ts.map +1 -1
  32. package/dist/src/platforms/channeltalkbot/commands/shared.js.map +1 -1
  33. package/dist/src/platforms/channeltalkbot/commands/snapshot.d.ts +3 -1
  34. package/dist/src/platforms/channeltalkbot/commands/snapshot.d.ts.map +1 -1
  35. package/dist/src/platforms/channeltalkbot/commands/snapshot.js +110 -60
  36. package/dist/src/platforms/channeltalkbot/commands/snapshot.js.map +1 -1
  37. package/dist/src/platforms/discord/commands/auth.js.map +1 -1
  38. package/dist/src/platforms/discord/commands/snapshot.d.ts +1 -0
  39. package/dist/src/platforms/discord/commands/snapshot.d.ts.map +1 -1
  40. package/dist/src/platforms/discord/commands/snapshot.js +48 -34
  41. package/dist/src/platforms/discord/commands/snapshot.js.map +1 -1
  42. package/dist/src/platforms/discord/commands/whoami.d.ts.map +1 -1
  43. package/dist/src/platforms/discord/commands/whoami.js.map +1 -1
  44. package/dist/src/platforms/discord/token-extractor.d.ts +2 -10
  45. package/dist/src/platforms/discord/token-extractor.d.ts.map +1 -1
  46. package/dist/src/platforms/discord/token-extractor.js +38 -172
  47. package/dist/src/platforms/discord/token-extractor.js.map +1 -1
  48. package/dist/src/platforms/discordbot/client.d.ts.map +1 -1
  49. package/dist/src/platforms/discordbot/client.js.map +1 -1
  50. package/dist/src/platforms/discordbot/commands/snapshot.d.ts +2 -0
  51. package/dist/src/platforms/discordbot/commands/snapshot.d.ts.map +1 -1
  52. package/dist/src/platforms/discordbot/commands/snapshot.js +46 -34
  53. package/dist/src/platforms/discordbot/commands/snapshot.js.map +1 -1
  54. package/dist/src/platforms/instagram/cli.d.ts.map +1 -1
  55. package/dist/src/platforms/instagram/cli.js +1 -4
  56. package/dist/src/platforms/instagram/cli.js.map +1 -1
  57. package/dist/src/platforms/instagram/client.d.ts.map +1 -1
  58. package/dist/src/platforms/instagram/client.js +8 -7
  59. package/dist/src/platforms/instagram/client.js.map +1 -1
  60. package/dist/src/platforms/instagram/commands/auth.d.ts.map +1 -1
  61. package/dist/src/platforms/instagram/commands/auth.js.map +1 -1
  62. package/dist/src/platforms/instagram/commands/chat.d.ts.map +1 -1
  63. package/dist/src/platforms/instagram/commands/chat.js.map +1 -1
  64. package/dist/src/platforms/instagram/commands/message.d.ts.map +1 -1
  65. package/dist/src/platforms/instagram/commands/message.js.map +1 -1
  66. package/dist/src/platforms/instagram/commands/shared.d.ts.map +1 -1
  67. package/dist/src/platforms/instagram/commands/shared.js.map +1 -1
  68. package/dist/src/platforms/instagram/credential-manager.d.ts.map +1 -1
  69. package/dist/src/platforms/instagram/credential-manager.js +1 -1
  70. package/dist/src/platforms/instagram/credential-manager.js.map +1 -1
  71. package/dist/src/platforms/instagram/ensure-auth.d.ts.map +1 -1
  72. package/dist/src/platforms/instagram/ensure-auth.js.map +1 -1
  73. package/dist/src/platforms/instagram/token-extractor.d.ts +7 -19
  74. package/dist/src/platforms/instagram/token-extractor.d.ts.map +1 -1
  75. package/dist/src/platforms/instagram/token-extractor.js +44 -270
  76. package/dist/src/platforms/instagram/token-extractor.js.map +1 -1
  77. package/dist/src/platforms/instagram/types.d.ts.map +1 -1
  78. package/dist/src/platforms/instagram/types.js +4 -2
  79. package/dist/src/platforms/instagram/types.js.map +1 -1
  80. package/dist/src/platforms/kakaotalk/auth/kakao-login.d.ts.map +1 -1
  81. package/dist/src/platforms/kakaotalk/auth/kakao-login.js +18 -4
  82. package/dist/src/platforms/kakaotalk/auth/kakao-login.js.map +1 -1
  83. package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
  84. package/dist/src/platforms/kakaotalk/client.js +3 -3
  85. package/dist/src/platforms/kakaotalk/client.js.map +1 -1
  86. package/dist/src/platforms/kakaotalk/commands/auth.d.ts.map +1 -1
  87. package/dist/src/platforms/kakaotalk/commands/auth.js +15 -9
  88. package/dist/src/platforms/kakaotalk/commands/auth.js.map +1 -1
  89. package/dist/src/platforms/kakaotalk/commands/shared.d.ts.map +1 -1
  90. package/dist/src/platforms/kakaotalk/commands/shared.js.map +1 -1
  91. package/dist/src/platforms/kakaotalk/protocol/connection.d.ts.map +1 -1
  92. package/dist/src/platforms/kakaotalk/protocol/connection.js.map +1 -1
  93. package/dist/src/platforms/kakaotalk/protocol/crypto.js +1 -1
  94. package/dist/src/platforms/kakaotalk/protocol/crypto.js.map +1 -1
  95. package/dist/src/platforms/kakaotalk/protocol/session.d.ts.map +1 -1
  96. package/dist/src/platforms/kakaotalk/protocol/session.js +1 -3
  97. package/dist/src/platforms/kakaotalk/protocol/session.js.map +1 -1
  98. package/dist/src/platforms/kakaotalk/token-extractor.js +5 -2
  99. package/dist/src/platforms/kakaotalk/token-extractor.js.map +1 -1
  100. package/dist/src/platforms/kakaotalk/types.d.ts.map +1 -1
  101. package/dist/src/platforms/kakaotalk/types.js +4 -2
  102. package/dist/src/platforms/kakaotalk/types.js.map +1 -1
  103. package/dist/src/platforms/line/cli.d.ts.map +1 -1
  104. package/dist/src/platforms/line/cli.js +1 -4
  105. package/dist/src/platforms/line/cli.js.map +1 -1
  106. package/dist/src/platforms/line/client.d.ts.map +1 -1
  107. package/dist/src/platforms/line/client.js +5 -13
  108. package/dist/src/platforms/line/client.js.map +1 -1
  109. package/dist/src/platforms/line/commands/chat.d.ts.map +1 -1
  110. package/dist/src/platforms/line/commands/chat.js.map +1 -1
  111. package/dist/src/platforms/line/commands/message.d.ts.map +1 -1
  112. package/dist/src/platforms/line/commands/message.js.map +1 -1
  113. package/dist/src/platforms/line/listener.js +1 -1
  114. package/dist/src/platforms/line/listener.js.map +1 -1
  115. package/dist/src/platforms/slack/cli.d.ts.map +1 -1
  116. package/dist/src/platforms/slack/cli.js.map +1 -1
  117. package/dist/src/platforms/slack/client-mappers.d.ts +14 -0
  118. package/dist/src/platforms/slack/client-mappers.d.ts.map +1 -0
  119. package/dist/src/platforms/slack/client-mappers.js +245 -0
  120. package/dist/src/platforms/slack/client-mappers.js.map +1 -0
  121. package/dist/src/platforms/slack/client.d.ts +0 -1
  122. package/dist/src/platforms/slack/client.d.ts.map +1 -1
  123. package/dist/src/platforms/slack/client.js +41 -455
  124. package/dist/src/platforms/slack/client.js.map +1 -1
  125. package/dist/src/platforms/slack/commands/channel.d.ts.map +1 -1
  126. package/dist/src/platforms/slack/commands/channel.js.map +1 -1
  127. package/dist/src/platforms/slack/commands/emoji.d.ts.map +1 -1
  128. package/dist/src/platforms/slack/commands/emoji.js +1 -3
  129. package/dist/src/platforms/slack/commands/emoji.js.map +1 -1
  130. package/dist/src/platforms/slack/commands/message.d.ts.map +1 -1
  131. package/dist/src/platforms/slack/commands/message.js.map +1 -1
  132. package/dist/src/platforms/slack/commands/reminder.d.ts.map +1 -1
  133. package/dist/src/platforms/slack/commands/reminder.js.map +1 -1
  134. package/dist/src/platforms/slack/commands/snapshot.d.ts.map +1 -1
  135. package/dist/src/platforms/slack/commands/snapshot.js +75 -55
  136. package/dist/src/platforms/slack/commands/snapshot.js.map +1 -1
  137. package/dist/src/platforms/slack/commands/user.d.ts.map +1 -1
  138. package/dist/src/platforms/slack/commands/user.js.map +1 -1
  139. package/dist/src/platforms/slack/commands/usergroup.d.ts.map +1 -1
  140. package/dist/src/platforms/slack/commands/usergroup.js.map +1 -1
  141. package/dist/src/platforms/slack/commands/whoami.d.ts.map +1 -1
  142. package/dist/src/platforms/slack/commands/whoami.js.map +1 -1
  143. package/dist/src/platforms/slack/token-extractor.d.ts +2 -6
  144. package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
  145. package/dist/src/platforms/slack/token-extractor.js +35 -229
  146. package/dist/src/platforms/slack/token-extractor.js.map +1 -1
  147. package/dist/src/platforms/slackbot/cli.d.ts.map +1 -1
  148. package/dist/src/platforms/slackbot/cli.js +1 -1
  149. package/dist/src/platforms/slackbot/cli.js.map +1 -1
  150. package/dist/src/platforms/teams/client.d.ts.map +1 -1
  151. package/dist/src/platforms/teams/client.js +1 -1
  152. package/dist/src/platforms/teams/client.js.map +1 -1
  153. package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
  154. package/dist/src/platforms/teams/commands/auth.js +4 -1
  155. package/dist/src/platforms/teams/commands/auth.js.map +1 -1
  156. package/dist/src/platforms/teams/commands/snapshot.d.ts +1 -0
  157. package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -1
  158. package/dist/src/platforms/teams/commands/snapshot.js +44 -31
  159. package/dist/src/platforms/teams/commands/snapshot.js.map +1 -1
  160. package/dist/src/platforms/teams/commands/whoami.d.ts.map +1 -1
  161. package/dist/src/platforms/teams/commands/whoami.js.map +1 -1
  162. package/dist/src/platforms/teams/token-extractor.d.ts +6 -18
  163. package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
  164. package/dist/src/platforms/teams/token-extractor.js +71 -324
  165. package/dist/src/platforms/teams/token-extractor.js.map +1 -1
  166. package/dist/src/platforms/telegram/cli.d.ts.map +1 -1
  167. package/dist/src/platforms/telegram/cli.js +1 -4
  168. package/dist/src/platforms/telegram/cli.js.map +1 -1
  169. package/dist/src/platforms/telegram/client.d.ts.map +1 -1
  170. package/dist/src/platforms/telegram/client.js.map +1 -1
  171. package/dist/src/platforms/telegram/commands/auth.d.ts.map +1 -1
  172. package/dist/src/platforms/telegram/commands/auth.js +1 -1
  173. package/dist/src/platforms/telegram/commands/auth.js.map +1 -1
  174. package/dist/src/platforms/telegram/commands/chat.d.ts.map +1 -1
  175. package/dist/src/platforms/telegram/commands/chat.js.map +1 -1
  176. package/dist/src/platforms/telegram/commands/message.d.ts.map +1 -1
  177. package/dist/src/platforms/telegram/commands/message.js.map +1 -1
  178. package/dist/src/platforms/telegram/commands/whoami.js +1 -1
  179. package/dist/src/platforms/telegram/commands/whoami.js.map +1 -1
  180. package/dist/src/platforms/telegram/credential-manager.d.ts.map +1 -1
  181. package/dist/src/platforms/telegram/credential-manager.js +6 -2
  182. package/dist/src/platforms/telegram/credential-manager.js.map +1 -1
  183. package/dist/src/platforms/telegram/my-telegram-org.js.map +1 -1
  184. package/dist/src/platforms/webex/cli.d.ts.map +1 -1
  185. package/dist/src/platforms/webex/cli.js +1 -4
  186. package/dist/src/platforms/webex/cli.js.map +1 -1
  187. package/dist/src/platforms/webex/client.d.ts.map +1 -1
  188. package/dist/src/platforms/webex/client.js +3 -7
  189. package/dist/src/platforms/webex/client.js.map +1 -1
  190. package/dist/src/platforms/webex/commands/auth.d.ts.map +1 -1
  191. package/dist/src/platforms/webex/commands/auth.js +1 -3
  192. package/dist/src/platforms/webex/commands/auth.js.map +1 -1
  193. package/dist/src/platforms/webex/commands/member.d.ts.map +1 -1
  194. package/dist/src/platforms/webex/commands/member.js +1 -3
  195. package/dist/src/platforms/webex/commands/member.js.map +1 -1
  196. package/dist/src/platforms/webex/commands/message.d.ts.map +1 -1
  197. package/dist/src/platforms/webex/commands/message.js.map +1 -1
  198. package/dist/src/platforms/webex/commands/snapshot.d.ts +1 -0
  199. package/dist/src/platforms/webex/commands/snapshot.d.ts.map +1 -1
  200. package/dist/src/platforms/webex/commands/snapshot.js +14 -7
  201. package/dist/src/platforms/webex/commands/snapshot.js.map +1 -1
  202. package/dist/src/platforms/webex/commands/space.d.ts.map +1 -1
  203. package/dist/src/platforms/webex/commands/space.js.map +1 -1
  204. package/dist/src/platforms/webex/commands/whoami.d.ts.map +1 -1
  205. package/dist/src/platforms/webex/commands/whoami.js.map +1 -1
  206. package/dist/src/platforms/webex/credential-manager.d.ts.map +1 -1
  207. package/dist/src/platforms/webex/credential-manager.js.map +1 -1
  208. package/dist/src/platforms/webex/ensure-auth.d.ts.map +1 -1
  209. package/dist/src/platforms/webex/ensure-auth.js +1 -3
  210. package/dist/src/platforms/webex/ensure-auth.js.map +1 -1
  211. package/dist/src/platforms/webex/index.d.ts +1 -1
  212. package/dist/src/platforms/webex/index.d.ts.map +1 -1
  213. package/dist/src/platforms/webex/index.js.map +1 -1
  214. package/dist/src/platforms/webex/markdown-to-html.js.map +1 -1
  215. package/dist/src/platforms/webex/token-extractor.d.ts.map +1 -1
  216. package/dist/src/platforms/webex/token-extractor.js +5 -14
  217. package/dist/src/platforms/webex/token-extractor.js.map +1 -1
  218. package/dist/src/platforms/wechatbot/client.d.ts.map +1 -1
  219. package/dist/src/platforms/wechatbot/client.js.map +1 -1
  220. package/dist/src/platforms/wechatbot/commands/message.d.ts.map +1 -1
  221. package/dist/src/platforms/wechatbot/commands/message.js.map +1 -1
  222. package/dist/src/platforms/whatsapp/cli.d.ts.map +1 -1
  223. package/dist/src/platforms/whatsapp/cli.js +1 -4
  224. package/dist/src/platforms/whatsapp/cli.js.map +1 -1
  225. package/dist/src/platforms/whatsapp/commands/chat.d.ts.map +1 -1
  226. package/dist/src/platforms/whatsapp/commands/chat.js.map +1 -1
  227. package/dist/src/platforms/whatsapp/commands/message.d.ts.map +1 -1
  228. package/dist/src/platforms/whatsapp/commands/message.js.map +1 -1
  229. package/dist/src/platforms/whatsapp/commands/shared.d.ts.map +1 -1
  230. package/dist/src/platforms/whatsapp/commands/shared.js.map +1 -1
  231. package/dist/src/platforms/whatsapp/credential-manager.d.ts.map +1 -1
  232. package/dist/src/platforms/whatsapp/credential-manager.js +1 -1
  233. package/dist/src/platforms/whatsapp/credential-manager.js.map +1 -1
  234. package/dist/src/platforms/whatsapp/ensure-auth.d.ts.map +1 -1
  235. package/dist/src/platforms/whatsapp/ensure-auth.js.map +1 -1
  236. package/dist/src/platforms/whatsappbot/client.d.ts.map +1 -1
  237. package/dist/src/platforms/whatsappbot/client.js +2 -2
  238. package/dist/src/platforms/whatsappbot/client.js.map +1 -1
  239. package/dist/src/platforms/whatsappbot/commands/auth.d.ts.map +1 -1
  240. package/dist/src/platforms/whatsappbot/commands/auth.js +4 -1
  241. package/dist/src/platforms/whatsappbot/commands/auth.js.map +1 -1
  242. package/dist/src/platforms/whatsappbot/commands/message.d.ts.map +1 -1
  243. package/dist/src/platforms/whatsappbot/commands/message.js.map +1 -1
  244. package/dist/src/platforms/whatsappbot/commands/shared.d.ts.map +1 -1
  245. package/dist/src/platforms/whatsappbot/commands/shared.js.map +1 -1
  246. package/dist/src/shared/chromium/browsers.d.ts +7 -0
  247. package/dist/src/shared/chromium/browsers.d.ts.map +1 -0
  248. package/dist/src/shared/chromium/browsers.js +89 -0
  249. package/dist/src/shared/chromium/browsers.js.map +1 -0
  250. package/dist/src/shared/chromium/cookie-reader.d.ts +20 -0
  251. package/dist/src/shared/chromium/cookie-reader.d.ts.map +1 -0
  252. package/dist/src/shared/chromium/cookie-reader.js +99 -0
  253. package/dist/src/shared/chromium/cookie-reader.js.map +1 -0
  254. package/dist/src/shared/chromium/decryptor.d.ts +42 -0
  255. package/dist/src/shared/chromium/decryptor.d.ts.map +1 -0
  256. package/dist/src/shared/chromium/decryptor.js +205 -0
  257. package/dist/src/shared/chromium/decryptor.js.map +1 -0
  258. package/dist/src/shared/chromium/index.d.ts +6 -0
  259. package/dist/src/shared/chromium/index.d.ts.map +1 -0
  260. package/dist/src/shared/chromium/index.js +4 -0
  261. package/dist/src/shared/chromium/index.js.map +1 -0
  262. package/dist/src/shared/chromium/types.d.ts +11 -0
  263. package/dist/src/shared/chromium/types.d.ts.map +1 -0
  264. package/dist/src/shared/chromium/types.js +2 -0
  265. package/dist/src/shared/chromium/types.js.map +1 -0
  266. package/dist/src/shared/utils/derived-key-cache.d.ts +1 -1
  267. package/dist/src/shared/utils/derived-key-cache.d.ts.map +1 -1
  268. package/dist/src/shared/utils/linux-keyring.js +4 -1
  269. package/dist/src/shared/utils/linux-keyring.js.map +1 -1
  270. package/dist/src/tui/adapters/kakaotalk-adapter.d.ts.map +1 -1
  271. package/dist/src/tui/adapters/kakaotalk-adapter.js +6 -1
  272. package/dist/src/tui/adapters/kakaotalk-adapter.js.map +1 -1
  273. package/dist/src/tui/adapters/telegram-adapter.js +1 -1
  274. package/dist/src/tui/adapters/telegram-adapter.js.map +1 -1
  275. package/dist/src/tui/adapters/webex-adapter.js +1 -1
  276. package/dist/src/tui/adapters/webex-adapter.js.map +1 -1
  277. package/dist/src/tui/app.d.ts.map +1 -1
  278. package/dist/src/tui/app.js +112 -23
  279. package/dist/src/tui/app.js.map +1 -1
  280. package/dist/src/tui/utils.d.ts.map +1 -1
  281. package/dist/src/tui/utils.js +11 -13
  282. package/dist/src/tui/utils.js.map +1 -1
  283. package/dist/src/tui/views/channel-picker.d.ts.map +1 -1
  284. package/dist/src/tui/views/channel-picker.js.map +1 -1
  285. package/dist/src/tui/views/workspace-picker.d.ts.map +1 -1
  286. package/dist/src/tui/views/workspace-picker.js.map +1 -1
  287. package/docs/content/docs/agent-skills.mdx +0 -10
  288. package/docs/content/docs/cli/channeltalk.mdx +42 -30
  289. package/docs/content/docs/cli/channeltalkbot.mdx +23 -13
  290. package/docs/content/docs/cli/discord.mdx +23 -7
  291. package/docs/content/docs/cli/discordbot.mdx +23 -7
  292. package/docs/content/docs/cli/instagram.mdx +4 -4
  293. package/docs/content/docs/cli/kakaotalk.mdx +9 -8
  294. package/docs/content/docs/cli/line.mdx +14 -14
  295. package/docs/content/docs/cli/slack.mdx +24 -7
  296. package/docs/content/docs/cli/teams.mdx +24 -8
  297. package/docs/content/docs/cli/webex.mdx +34 -21
  298. package/docs/content/docs/cli/wechatbot.mdx +12 -11
  299. package/docs/content/docs/cli/whatsapp.mdx +5 -4
  300. package/docs/content/docs/cli/whatsappbot.mdx +11 -11
  301. package/docs/content/docs/index.mdx +7 -7
  302. package/docs/content/docs/meta.json +1 -9
  303. package/docs/content/docs/sdk/channeltalk.mdx +5 -6
  304. package/docs/content/docs/sdk/channeltalkbot.mdx +6 -12
  305. package/docs/content/docs/sdk/discord.mdx +36 -43
  306. package/docs/content/docs/sdk/instagram.mdx +18 -18
  307. package/docs/content/docs/sdk/kakaotalk.mdx +27 -18
  308. package/docs/content/docs/sdk/line.mdx +8 -13
  309. package/docs/content/docs/sdk/meta.json +14 -1
  310. package/docs/content/docs/sdk/slack.mdx +36 -42
  311. package/docs/content/docs/sdk/teams.mdx +2 -8
  312. package/docs/content/docs/sdk/webex.mdx +2 -12
  313. package/docs/content/docs/sdk/wechatbot.mdx +1 -5
  314. package/docs/content/docs/sdk/whatsapp.mdx +10 -19
  315. package/docs/content/docs/sdk/whatsappbot.mdx +2 -10
  316. package/docs/content/docs/tui.mdx +23 -23
  317. package/docs/src/app/page.tsx +353 -108
  318. package/e2e/channeltalkbot.e2e.test.ts +1 -5
  319. package/e2e/config.ts +6 -2
  320. package/package.json +59 -58
  321. package/scripts/prepublish.ts +1 -3
  322. package/skills/agent-channeltalk/SKILL.md +19 -9
  323. package/skills/agent-channeltalk/references/common-patterns.md +10 -9
  324. package/skills/agent-channeltalkbot/SKILL.md +19 -9
  325. package/skills/agent-channeltalkbot/references/common-patterns.md +10 -9
  326. package/skills/agent-discord/SKILL.md +18 -9
  327. package/skills/agent-discord/references/common-patterns.md +8 -7
  328. package/skills/agent-discordbot/SKILL.md +18 -9
  329. package/skills/agent-instagram/SKILL.md +1 -1
  330. package/skills/agent-kakaotalk/SKILL.md +1 -1
  331. package/skills/agent-line/SKILL.md +1 -1
  332. package/skills/agent-slack/SKILL.md +19 -10
  333. package/skills/agent-slack/references/common-patterns.md +4 -7
  334. package/skills/agent-slackbot/SKILL.md +1 -1
  335. package/skills/agent-teams/SKILL.md +18 -9
  336. package/skills/agent-teams/references/common-patterns.md +9 -7
  337. package/skills/agent-telegram/SKILL.md +1 -1
  338. package/skills/agent-webex/SKILL.md +13 -4
  339. package/skills/agent-webex/references/common-patterns.md +8 -2
  340. package/skills/agent-wechatbot/SKILL.md +1 -1
  341. package/skills/agent-whatsapp/SKILL.md +1 -1
  342. package/skills/agent-whatsappbot/SKILL.md +1 -1
  343. package/src/platforms/channeltalk/client.test.ts +116 -29
  344. package/src/platforms/channeltalk/client.ts +26 -6
  345. package/src/platforms/channeltalk/commands/auth.test.ts +5 -5
  346. package/src/platforms/channeltalk/commands/auth.ts +19 -5
  347. package/src/platforms/channeltalk/commands/message.test.ts +2 -6
  348. package/src/platforms/channeltalk/commands/message.ts +5 -1
  349. package/src/platforms/channeltalk/commands/snapshot.test.ts +77 -30
  350. package/src/platforms/channeltalk/commands/snapshot.ts +112 -34
  351. package/src/platforms/channeltalk/ensure-auth.test.ts +20 -17
  352. package/src/platforms/channeltalk/ensure-auth.ts +6 -7
  353. package/src/platforms/channeltalk/index.ts +0 -1
  354. package/src/platforms/channeltalk/token-extractor.test.ts +33 -25
  355. package/src/platforms/channeltalk/token-extractor.ts +120 -372
  356. package/src/platforms/channeltalkbot/client.test.ts +1 -3
  357. package/src/platforms/channeltalkbot/client.ts +39 -13
  358. package/src/platforms/channeltalkbot/commands/auth.test.ts +3 -1
  359. package/src/platforms/channeltalkbot/commands/auth.ts +4 -1
  360. package/src/platforms/channeltalkbot/commands/bot.test.ts +13 -5
  361. package/src/platforms/channeltalkbot/commands/message.test.ts +12 -6
  362. package/src/platforms/channeltalkbot/commands/shared.ts +6 -2
  363. package/src/platforms/channeltalkbot/commands/snapshot.test.ts +43 -13
  364. package/src/platforms/channeltalkbot/commands/snapshot.ts +131 -64
  365. package/src/platforms/channeltalkbot/credential-manager.test.ts +1 -1
  366. package/src/platforms/channeltalkbot/index.test.ts +0 -2
  367. package/src/platforms/channeltalkbot/index.ts +0 -1
  368. package/src/platforms/discord/commands/auth.test.ts +6 -4
  369. package/src/platforms/discord/commands/auth.ts +14 -14
  370. package/src/platforms/discord/commands/snapshot.test.ts +1 -1
  371. package/src/platforms/discord/commands/snapshot.ts +58 -42
  372. package/src/platforms/discord/commands/whoami.test.ts +2 -4
  373. package/src/platforms/discord/commands/whoami.ts +2 -0
  374. package/src/platforms/discord/ensure-auth.test.ts +5 -3
  375. package/src/platforms/discord/index.ts +0 -1
  376. package/src/platforms/discord/listener.test.ts +7 -1
  377. package/src/platforms/discord/token-extractor.test.ts +18 -12
  378. package/src/platforms/discord/token-extractor.ts +46 -190
  379. package/src/platforms/discordbot/client.ts +1 -4
  380. package/src/platforms/discordbot/commands/auth.test.ts +3 -1
  381. package/src/platforms/discordbot/commands/channel.test.ts +3 -1
  382. package/src/platforms/discordbot/commands/message.test.ts +3 -1
  383. package/src/platforms/discordbot/commands/server.test.ts +3 -1
  384. package/src/platforms/discordbot/commands/snapshot.test.ts +43 -19
  385. package/src/platforms/discordbot/commands/snapshot.ts +54 -37
  386. package/src/platforms/discordbot/commands/thread.test.ts +3 -1
  387. package/src/platforms/discordbot/commands/user.test.ts +3 -1
  388. package/src/platforms/instagram/cli.ts +1 -4
  389. package/src/platforms/instagram/client.test.ts +3 -8
  390. package/src/platforms/instagram/client.ts +39 -34
  391. package/src/platforms/instagram/commands/auth.test.ts +13 -12
  392. package/src/platforms/instagram/commands/auth.ts +136 -71
  393. package/src/platforms/instagram/commands/chat.test.ts +21 -24
  394. package/src/platforms/instagram/commands/chat.ts +2 -0
  395. package/src/platforms/instagram/commands/message.test.ts +29 -24
  396. package/src/platforms/instagram/commands/message.ts +3 -4
  397. package/src/platforms/instagram/commands/shared.ts +2 -5
  398. package/src/platforms/instagram/commands/whoami.test.ts +4 -6
  399. package/src/platforms/instagram/credential-manager.ts +2 -6
  400. package/src/platforms/instagram/ensure-auth.test.ts +1 -4
  401. package/src/platforms/instagram/ensure-auth.ts +6 -3
  402. package/src/platforms/instagram/listener.test.ts +7 -3
  403. package/src/platforms/instagram/token-extractor.test.ts +4 -16
  404. package/src/platforms/instagram/token-extractor.ts +55 -309
  405. package/src/platforms/instagram/types.test.ts +2 -6
  406. package/src/platforms/instagram/types.ts +4 -2
  407. package/src/platforms/kakaotalk/auth/kakao-login.ts +30 -8
  408. package/src/platforms/kakaotalk/client.test.ts +37 -25
  409. package/src/platforms/kakaotalk/client.ts +23 -12
  410. package/src/platforms/kakaotalk/commands/auth.test.ts +6 -18
  411. package/src/platforms/kakaotalk/commands/auth.ts +101 -47
  412. package/src/platforms/kakaotalk/commands/chat.test.ts +8 -11
  413. package/src/platforms/kakaotalk/commands/message.test.ts +15 -24
  414. package/src/platforms/kakaotalk/commands/shared.ts +1 -0
  415. package/src/platforms/kakaotalk/commands/whoami.test.ts +6 -10
  416. package/src/platforms/kakaotalk/credential-manager.test.ts +1 -4
  417. package/src/platforms/kakaotalk/index.test.ts +1 -0
  418. package/src/platforms/kakaotalk/index.ts +0 -2
  419. package/src/platforms/kakaotalk/listener.test.ts +7 -1
  420. package/src/platforms/kakaotalk/protocol/connection.ts +4 -1
  421. package/src/platforms/kakaotalk/protocol/crypto.ts +1 -1
  422. package/src/platforms/kakaotalk/protocol/session.ts +12 -6
  423. package/src/platforms/kakaotalk/token-extractor.ts +5 -5
  424. package/src/platforms/kakaotalk/types.ts +8 -7
  425. package/src/platforms/line/cli.ts +1 -4
  426. package/src/platforms/line/client.ts +12 -20
  427. package/src/platforms/line/commands/auth.test.ts +2 -1
  428. package/src/platforms/line/commands/chat.test.ts +2 -1
  429. package/src/platforms/line/commands/chat.ts +1 -4
  430. package/src/platforms/line/commands/friend.test.ts +2 -1
  431. package/src/platforms/line/commands/message.test.ts +2 -1
  432. package/src/platforms/line/commands/message.ts +2 -9
  433. package/src/platforms/line/commands/whoami.test.ts +2 -1
  434. package/src/platforms/line/credential-manager.test.ts +1 -2
  435. package/src/platforms/line/index.test.ts +1 -0
  436. package/src/platforms/line/listener.ts +1 -1
  437. package/src/platforms/line/types.test.ts +1 -0
  438. package/src/platforms/slack/cli.ts +3 -1
  439. package/src/platforms/slack/client-mappers.ts +297 -0
  440. package/src/platforms/slack/client.test.ts +532 -17
  441. package/src/platforms/slack/client.ts +69 -458
  442. package/src/platforms/slack/commands/channel.ts +1 -4
  443. package/src/platforms/slack/commands/emoji.test.ts +6 -4
  444. package/src/platforms/slack/commands/emoji.ts +20 -22
  445. package/src/platforms/slack/commands/message.ts +6 -1
  446. package/src/platforms/slack/commands/pin.test.ts +14 -12
  447. package/src/platforms/slack/commands/reminder.ts +7 -6
  448. package/src/platforms/slack/commands/snapshot.test.ts +63 -8
  449. package/src/platforms/slack/commands/snapshot.ts +98 -66
  450. package/src/platforms/slack/commands/user.ts +6 -1
  451. package/src/platforms/slack/commands/usergroup.test.ts +3 -3
  452. package/src/platforms/slack/commands/usergroup.ts +10 -7
  453. package/src/platforms/slack/commands/whoami.test.ts +1 -1
  454. package/src/platforms/slack/commands/whoami.ts +2 -0
  455. package/src/platforms/slack/index.ts +0 -2
  456. package/src/platforms/slack/listener.test.ts +1 -0
  457. package/src/platforms/slack/token-extractor.test.ts +7 -12
  458. package/src/platforms/slack/token-extractor.ts +47 -255
  459. package/src/platforms/slackbot/cli.ts +8 -1
  460. package/src/platforms/slackbot/commands/auth.test.ts +3 -1
  461. package/src/platforms/teams/client.ts +1 -1
  462. package/src/platforms/teams/commands/auth.test.ts +1 -1
  463. package/src/platforms/teams/commands/auth.ts +4 -1
  464. package/src/platforms/teams/commands/snapshot.test.ts +1 -1
  465. package/src/platforms/teams/commands/snapshot.ts +53 -38
  466. package/src/platforms/teams/commands/whoami.test.ts +2 -4
  467. package/src/platforms/teams/commands/whoami.ts +2 -0
  468. package/src/platforms/teams/index.ts +0 -1
  469. package/src/platforms/teams/token-extractor.ts +82 -350
  470. package/src/platforms/telegram/app-config.test.ts +1 -0
  471. package/src/platforms/telegram/chat-utils.test.ts +5 -1
  472. package/src/platforms/telegram/cli.ts +2 -4
  473. package/src/platforms/telegram/client.test.ts +16 -3
  474. package/src/platforms/telegram/client.ts +14 -4
  475. package/src/platforms/telegram/commands/auth.test.ts +1 -0
  476. package/src/platforms/telegram/commands/auth.ts +3 -4
  477. package/src/platforms/telegram/commands/chat.test.ts +2 -5
  478. package/src/platforms/telegram/commands/chat.ts +1 -0
  479. package/src/platforms/telegram/commands/message.test.ts +2 -5
  480. package/src/platforms/telegram/commands/message.ts +1 -0
  481. package/src/platforms/telegram/commands/shared.test.ts +1 -0
  482. package/src/platforms/telegram/commands/whoami.test.ts +5 -7
  483. package/src/platforms/telegram/commands/whoami.ts +1 -1
  484. package/src/platforms/telegram/credential-manager.test.ts +1 -0
  485. package/src/platforms/telegram/credential-manager.ts +11 -2
  486. package/src/platforms/telegram/my-telegram-org.ts +6 -2
  487. package/src/platforms/telegram/types.test.ts +1 -0
  488. package/src/platforms/webex/app-config.test.ts +1 -0
  489. package/src/platforms/webex/cli.ts +1 -4
  490. package/src/platforms/webex/client.test.ts +4 -12
  491. package/src/platforms/webex/client.ts +14 -52
  492. package/src/platforms/webex/commands/auth.test.ts +7 -1
  493. package/src/platforms/webex/commands/auth.ts +12 -15
  494. package/src/platforms/webex/commands/member.test.ts +1 -3
  495. package/src/platforms/webex/commands/member.ts +14 -19
  496. package/src/platforms/webex/commands/message.ts +4 -15
  497. package/src/platforms/webex/commands/snapshot.test.ts +42 -4
  498. package/src/platforms/webex/commands/snapshot.ts +19 -11
  499. package/src/platforms/webex/commands/space.test.ts +3 -3
  500. package/src/platforms/webex/commands/space.ts +2 -9
  501. package/src/platforms/webex/commands/whoami.test.ts +12 -5
  502. package/src/platforms/webex/commands/whoami.ts +2 -0
  503. package/src/platforms/webex/credential-manager.ts +11 -2
  504. package/src/platforms/webex/ensure-auth.ts +1 -3
  505. package/src/platforms/webex/index.ts +1 -7
  506. package/src/platforms/webex/markdown-to-html.test.ts +6 -18
  507. package/src/platforms/webex/markdown-to-html.ts +8 -8
  508. package/src/platforms/webex/token-extractor.ts +6 -29
  509. package/src/platforms/wechatbot/client.test.ts +6 -2
  510. package/src/platforms/wechatbot/client.ts +6 -1
  511. package/src/platforms/wechatbot/commands/auth.test.ts +3 -7
  512. package/src/platforms/wechatbot/commands/message.test.ts +1 -4
  513. package/src/platforms/wechatbot/commands/message.ts +5 -1
  514. package/src/platforms/wechatbot/commands/template.test.ts +1 -4
  515. package/src/platforms/wechatbot/commands/user.test.ts +2 -7
  516. package/src/platforms/whatsapp/cli.ts +1 -4
  517. package/src/platforms/whatsapp/commands/auth.test.ts +19 -22
  518. package/src/platforms/whatsapp/commands/chat.test.ts +21 -24
  519. package/src/platforms/whatsapp/commands/chat.ts +2 -0
  520. package/src/platforms/whatsapp/commands/message.test.ts +22 -24
  521. package/src/platforms/whatsapp/commands/message.ts +3 -5
  522. package/src/platforms/whatsapp/commands/shared.ts +2 -5
  523. package/src/platforms/whatsapp/commands/whoami.test.ts +2 -2
  524. package/src/platforms/whatsapp/credential-manager.ts +2 -6
  525. package/src/platforms/whatsapp/ensure-auth.test.ts +1 -4
  526. package/src/platforms/whatsapp/ensure-auth.ts +14 -6
  527. package/src/platforms/whatsapp/index.ts +0 -2
  528. package/src/platforms/whatsappbot/client.test.ts +13 -7
  529. package/src/platforms/whatsappbot/client.ts +18 -4
  530. package/src/platforms/whatsappbot/commands/auth.ts +4 -1
  531. package/src/platforms/whatsappbot/commands/message.test.ts +12 -2
  532. package/src/platforms/whatsappbot/commands/message.ts +16 -3
  533. package/src/platforms/whatsappbot/commands/shared.ts +3 -1
  534. package/src/platforms/whatsappbot/commands/whoami.test.ts +1 -3
  535. package/src/platforms/whatsappbot/index.ts +0 -2
  536. package/src/shared/chromium/browsers.test.ts +274 -0
  537. package/src/shared/chromium/browsers.ts +86 -0
  538. package/src/shared/chromium/cookie-reader.test.ts +274 -0
  539. package/src/shared/chromium/cookie-reader.ts +111 -0
  540. package/src/shared/chromium/decryptor.test.ts +449 -0
  541. package/src/shared/chromium/decryptor.ts +227 -0
  542. package/src/shared/chromium/index.ts +11 -0
  543. package/src/shared/chromium/types.ts +11 -0
  544. package/src/shared/utils/derived-key-cache.ts +1 -1
  545. package/src/shared/utils/linux-keyring.ts +4 -4
  546. package/src/tui/adapters/kakaotalk-adapter.ts +6 -1
  547. package/src/tui/adapters/telegram-adapter.ts +1 -1
  548. package/src/tui/adapters/webex-adapter.ts +1 -1
  549. package/src/tui/app.ts +149 -59
  550. package/src/tui/utils.test.ts +144 -145
  551. package/src/tui/utils.ts +27 -29
  552. package/src/tui/views/channel-picker.ts +1 -1
  553. package/src/tui/views/workspace-picker.ts +1 -1
@@ -1,13 +1,17 @@
1
1
  import { execSync } from 'node:child_process'
2
- import { createDecipheriv, pbkdf2Sync } from 'node:crypto'
3
- import { copyFileSync, existsSync, readFileSync, readdirSync, unlinkSync } from 'node:fs'
4
- import { createRequire } from 'node:module'
5
- import { homedir, tmpdir } from 'node:os'
2
+ import { existsSync } from 'node:fs'
6
3
  import { join } from 'node:path'
7
4
 
8
- import { DerivedKeyCache } from '@/shared/utils/derived-key-cache'
9
-
10
- const require = createRequire(import.meta.url)
5
+ import {
6
+ BROWSER_KEYCHAIN_VARIANTS,
7
+ CHROMIUM_BROWSERS,
8
+ ChromiumCookieDecryptor,
9
+ ChromiumCookieReader,
10
+ discoverBrowserProfileDirs,
11
+ findLocalStatePath,
12
+ getBrowserBasePath,
13
+ } from '@/shared/chromium'
14
+ import type { KeychainVariant } from '@/shared/chromium'
11
15
 
12
16
  export interface ExtractedInstagramCookies {
13
17
  sessionid: string
@@ -18,95 +22,30 @@ export interface ExtractedInstagramCookies {
18
22
  rur?: string
19
23
  }
20
24
 
21
- interface BrowserConfig {
22
- name: string
23
- darwin: string
24
- linux: string
25
- win32: string
26
- localStateDarwin?: string
27
- localStateLinux?: string
28
- localStateWin32?: string
29
- }
30
-
31
- interface KeychainVariant {
32
- service: string
33
- account: string
34
- }
35
-
36
- const BROWSERS: BrowserConfig[] = [
37
- {
38
- name: 'Chrome',
39
- darwin: join('Google', 'Chrome'),
40
- linux: 'google-chrome',
41
- win32: join('Google', 'Chrome', 'User Data'),
42
- },
43
- {
44
- name: 'Chrome Canary',
45
- darwin: join('Google', 'Chrome Canary'),
46
- linux: 'google-chrome-unstable',
47
- win32: join('Google', 'Chrome SxS', 'User Data'),
48
- },
49
- {
50
- name: 'Edge',
51
- darwin: 'Microsoft Edge',
52
- linux: 'microsoft-edge',
53
- win32: join('Microsoft', 'Edge', 'User Data'),
54
- },
55
- {
56
- name: 'Arc',
57
- darwin: join('Arc', 'User Data'),
58
- linux: '',
59
- win32: join('Arc', 'User Data'),
60
- },
61
- {
62
- name: 'Brave',
63
- darwin: join('BraveSoftware', 'Brave-Browser'),
64
- linux: join('BraveSoftware', 'Brave-Browser'),
65
- win32: join('BraveSoftware', 'Brave-Browser', 'User Data'),
66
- },
67
- {
68
- name: 'Vivaldi',
69
- darwin: 'Vivaldi',
70
- linux: 'vivaldi',
71
- win32: join('Vivaldi', 'User Data'),
72
- },
73
- {
74
- name: 'Chromium',
75
- darwin: 'Chromium',
76
- linux: 'chromium',
77
- win32: join('Chromium', 'User Data'),
78
- },
79
- ]
80
-
81
25
  const INSTAGRAM_HOST_KEYS = ['.instagram.com', 'www.instagram.com', 'i.instagram.com']
82
26
  const INSTAGRAM_COOKIE_NAMES = ['sessionid', 'ds_user_id', 'csrftoken', 'mid', 'ig_did', 'rur']
83
27
 
84
28
  export class InstagramTokenExtractor {
85
29
  private platform: NodeJS.Platform
86
30
  private debugLog: ((message: string) => void) | null
87
- private cachedKey: Buffer | null = null
31
+ private decryptor: ChromiumCookieDecryptor
32
+ private cookieReader: ChromiumCookieReader
88
33
 
89
- constructor(
90
- platform?: NodeJS.Platform,
91
- debugLog?: (message: string) => void,
92
- _keyCache?: DerivedKeyCache,
93
- ) {
34
+ constructor(platform?: NodeJS.Platform, debugLog?: (message: string) => void) {
94
35
  this.platform = platform ?? process.platform
95
36
  this.debugLog = debugLog ?? null
96
- }
97
-
98
- private debug(message: string): void {
99
- this.debugLog?.(message)
37
+ this.decryptor = new ChromiumCookieDecryptor({ platform: this.platform })
38
+ this.cookieReader = new ChromiumCookieReader()
100
39
  }
101
40
 
102
41
  getBrowserCookiesPaths(): string[] {
103
42
  const paths: string[] = []
104
43
 
105
- for (const browser of BROWSERS) {
106
- const browserBase = this.getBrowserBasePath(browser)
44
+ for (const browser of CHROMIUM_BROWSERS) {
45
+ const browserBase = getBrowserBasePath(browser, this.platform)
107
46
  if (!browserBase) continue
108
47
 
109
- const profileDirs = this.discoverProfileDirs(browserBase)
48
+ const profileDirs = discoverBrowserProfileDirs(browserBase)
110
49
  for (const profileDir of profileDirs) {
111
50
  paths.push(join(profileDir, 'Cookies'))
112
51
  paths.push(join(profileDir, 'Network', 'Cookies'))
@@ -119,8 +58,8 @@ export class InstagramTokenExtractor {
119
58
  getLocalStatePaths(): string[] {
120
59
  const paths: string[] = []
121
60
 
122
- for (const browser of BROWSERS) {
123
- const browserBase = this.getBrowserBasePath(browser)
61
+ for (const browser of CHROMIUM_BROWSERS) {
62
+ const browserBase = getBrowserBasePath(browser, this.platform)
124
63
  if (!browserBase) continue
125
64
 
126
65
  paths.push(join(browserBase, 'Local State'))
@@ -129,65 +68,12 @@ export class InstagramTokenExtractor {
129
68
  return paths
130
69
  }
131
70
 
132
- private getBrowserBasePath(browser: BrowserConfig): string | null {
133
- let relative: string
134
-
135
- switch (this.platform) {
136
- case 'darwin':
137
- relative = browser.darwin
138
- if (!relative) return null
139
- return join(homedir(), 'Library', 'Application Support', relative)
140
- case 'linux':
141
- relative = browser.linux
142
- if (!relative) return null
143
- return join(homedir(), '.config', relative)
144
- case 'win32':
145
- relative = browser.win32
146
- if (!relative) return null
147
- return join(
148
- process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local'),
149
- relative,
150
- )
151
- default:
152
- return null
153
- }
154
- }
155
-
156
- private discoverProfileDirs(browserBase: string): string[] {
157
- const dirs: string[] = []
158
-
159
- dirs.push(join(browserBase, 'Default'))
160
-
161
- if (!existsSync(browserBase)) return dirs
162
-
163
- try {
164
- const entries = readdirSync(browserBase, { withFileTypes: true })
165
- for (const entry of entries) {
166
- if (!entry.isDirectory()) continue
167
- if (!/^Profile \d+$/i.test(entry.name)) continue
168
- dirs.push(join(browserBase, entry.name))
169
- }
170
- } catch {}
171
-
172
- return dirs
173
- }
174
-
175
71
  getKeychainVariants(): KeychainVariant[] {
176
- return [
177
- { service: 'Chrome Safe Storage', account: 'Chrome' },
178
- { service: 'Chrome Canary Safe Storage', account: 'Chrome Canary' },
179
- { service: 'Microsoft Edge Safe Storage', account: 'Microsoft Edge' },
180
- { service: 'Arc Safe Storage', account: 'Arc' },
181
- { service: 'Brave Safe Storage', account: 'Brave' },
182
- { service: 'Vivaldi Safe Storage', account: 'Vivaldi' },
183
- { service: 'Chromium Safe Storage', account: 'Chromium' },
184
- ]
72
+ return BROWSER_KEYCHAIN_VARIANTS
185
73
  }
186
74
 
187
75
  isEncryptedValue(value: Buffer): boolean {
188
- if (!value || value.length < 4) return false
189
- const prefix = value.subarray(0, 3).toString('utf8')
190
- return prefix === 'v10' || prefix === 'v11'
76
+ return this.decryptor.isEncryptedValue(value)
191
77
  }
192
78
 
193
79
  isValidSessionId(sessionid: string): boolean {
@@ -219,39 +105,30 @@ export class InstagramTokenExtractor {
219
105
  return results
220
106
  }
221
107
 
108
+ private debug(message: string): void {
109
+ this.debugLog?.(message)
110
+ }
111
+
222
112
  private async copyAndExtract(dbPath: string): Promise<ExtractedInstagramCookies | null> {
223
- const tempPath = join(tmpdir(), `instagram-cookies-${Date.now()}`)
113
+ let tempPath = dbPath
224
114
 
225
115
  try {
226
- this.copyDatabaseToTemp(dbPath, tempPath)
227
- const cookies = await this.extractFromSQLite(tempPath, dbPath)
228
- this.cleanupTempFile(tempPath)
229
- return cookies
116
+ tempPath = this.copyDatabaseToTemp(dbPath, dbPath)
117
+ return await this.extractFromSQLite(tempPath, dbPath)
230
118
  } catch {
231
- this.cleanupTempFile(tempPath)
232
119
  return null
120
+ } finally {
121
+ this.cleanupTempFile(tempPath)
233
122
  }
234
123
  }
235
124
 
236
- private copyDatabaseToTemp(sourcePath: string, destPath: string): string {
237
- copyFileSync(sourcePath, destPath)
238
- return destPath
125
+ private copyDatabaseToTemp(sourcePath: string, _destPath: string): string {
126
+ return sourcePath
239
127
  }
240
128
 
241
- private cleanupTempFile(tempPath: string): void {
242
- try {
243
- if (existsSync(tempPath)) {
244
- unlinkSync(tempPath)
245
- }
246
- } catch {
247
- // Ignore cleanup errors
248
- }
249
- }
129
+ private cleanupTempFile(_tempPath: string): void {}
250
130
 
251
- private async extractFromSQLite(
252
- dbPath: string,
253
- originalPath: string,
254
- ): Promise<ExtractedInstagramCookies | null> {
131
+ private async extractFromSQLite(dbPath: string, originalPath: string): Promise<ExtractedInstagramCookies | null> {
255
132
  try {
256
133
  const placeholders = INSTAGRAM_HOST_KEYS.map(() => '?').join(', ')
257
134
  const sql = `
@@ -262,18 +139,8 @@ export class InstagramTokenExtractor {
262
139
 
263
140
  type CookieRow = { name: string; value?: string; encrypted_value?: Uint8Array | Buffer }
264
141
 
265
- let rows: CookieRow[]
266
- if (typeof globalThis.Bun !== 'undefined') {
267
- const { Database } = require('bun:sqlite')
268
- const db = new Database(dbPath, { readonly: true })
269
- rows = db.query(sql).all(...INSTAGRAM_HOST_KEYS) as CookieRow[]
270
- db.close()
271
- } else {
272
- const Database = require('better-sqlite3')
273
- const db = new Database(dbPath, { readonly: true })
274
- rows = db.prepare(sql).all(...INSTAGRAM_HOST_KEYS) as CookieRow[]
275
- db.close()
276
- }
142
+ const rows = await this.cookieReader.queryAll<CookieRow>(dbPath, sql, INSTAGRAM_HOST_KEYS)
143
+ const localStatePath = findLocalStatePath(originalPath) ?? undefined
277
144
 
278
145
  const cookieMap: Record<string, string> = {}
279
146
  for (const row of rows) {
@@ -281,14 +148,14 @@ export class InstagramTokenExtractor {
281
148
 
282
149
  let value = ''
283
150
  if (row.encrypted_value && row.encrypted_value.length > 0) {
284
- const encBuf = Buffer.from(row.encrypted_value)
285
- if (this.isEncryptedValue(encBuf)) {
286
- const decrypted = this.decryptCookie(encBuf, originalPath)
287
- if (decrypted) {
288
- value = decrypted
151
+ const encryptedValue = Buffer.from(row.encrypted_value)
152
+ if (this.decryptor.isEncryptedValue(encryptedValue)) {
153
+ const decryptedBuf = this.decryptor.decryptCookieRaw(encryptedValue, localStatePath)
154
+ if (decryptedBuf) {
155
+ value = ChromiumCookieDecryptor.stripIntegrityHash(decryptedBuf).toString('utf8')
289
156
  }
290
157
  } else {
291
- value = encBuf.toString('utf8')
158
+ value = encryptedValue.toString('utf8')
292
159
  }
293
160
  } else if (row.value) {
294
161
  value = row.value
@@ -323,91 +190,14 @@ export class InstagramTokenExtractor {
323
190
  }
324
191
  }
325
192
 
326
- private decryptCookie(encryptedValue: Buffer, dbPath: string): string | null {
327
- if (!this.isEncryptedValue(encryptedValue)) {
328
- return encryptedValue.toString('utf8')
329
- }
330
-
331
- if (this.platform === 'win32') {
332
- return this.decryptWindowsCookie(encryptedValue, dbPath)
333
- } else if (this.platform === 'darwin') {
334
- return this.decryptMacCookie(encryptedValue)
335
- } else if (this.platform === 'linux') {
336
- return this.decryptLinuxCookie(encryptedValue)
337
- }
338
-
339
- return null
340
- }
341
-
342
- private decryptWindowsCookie(encryptedData: Buffer, dbPath: string): string | null {
343
- try {
344
- const localStatePath = this.findLocalStateForCookiePath(dbPath)
345
- if (!localStatePath || !existsSync(localStatePath)) return null
346
-
347
- const localState = JSON.parse(readFileSync(localStatePath, 'utf8'))
348
- const encryptedKey = Buffer.from(localState.os_crypt.encrypted_key, 'base64')
349
- const dpapiBlobKey = encryptedKey.subarray(5)
350
- const masterKey = this.decryptDPAPI(dpapiBlobKey)
351
- if (!masterKey) return null
352
-
353
- return this.decryptAESGCM(encryptedData, masterKey)
354
- } catch {
355
- return null
356
- }
357
- }
358
-
359
- private findLocalStateForCookiePath(cookiePath: string): string | null {
360
- const parts = cookiePath.split(/[/\\]/)
361
- for (let levels = 2; levels <= 4; levels++) {
362
- if (parts.length < levels) break
363
- const base = parts.slice(0, parts.length - levels).join('/')
364
- const candidate = join(base, 'Local State')
365
- if (existsSync(candidate)) return candidate
366
- }
367
- return null
368
- }
369
-
370
- private decryptDPAPI(encryptedBlob: Buffer): Buffer | null {
371
- try {
372
- const b64 = encryptedBlob.toString('base64')
373
- const psScript = `
374
- Add-Type -AssemblyName System.Security
375
- $bytes = [Convert]::FromBase64String('${b64}')
376
- $decrypted = [Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, 'CurrentUser')
377
- [Convert]::ToBase64String($decrypted)
378
- `.replace(/\n/g, ' ')
379
-
380
- const result = execSync(`powershell -Command "${psScript}"`, { encoding: 'utf8' })
381
- return Buffer.from(result.trim(), 'base64')
382
- } catch {
383
- return null
384
- }
385
- }
386
-
387
- private decryptMacCookie(encryptedData: Buffer): string | null {
388
- if (this.cachedKey) {
389
- const decrypted = this.decryptAESCBC(encryptedData, this.cachedKey)
390
- if (decrypted) return decrypted
391
- }
392
-
393
- for (const variant of this.getKeychainVariants()) {
394
- const password = this.execSecurityCommand(variant.service, variant.account)
395
- if (!password) continue
396
-
397
- const key = pbkdf2Sync(password, 'saltysalt', 1003, 16, 'sha1')
398
- const decrypted = this.decryptAESCBC(encryptedData, key)
399
- if (decrypted) {
400
- this.cachedKey = key
401
- return decrypted
402
- }
403
- }
404
-
405
- return null
193
+ private decryptAESCBC(encryptedData: Buffer, key: Buffer): string | null {
194
+ const buf = this.decryptor.decryptAESCBCRaw(encryptedData, key)
195
+ if (!buf) return null
196
+ return ChromiumCookieDecryptor.stripIntegrityHash(buf).toString('utf8')
406
197
  }
407
198
 
408
- private decryptLinuxCookie(encryptedData: Buffer): string | null {
409
- const key = pbkdf2Sync('peanuts', 'saltysalt', 1, 16, 'sha1')
410
- return this.decryptAESCBC(encryptedData, key)
199
+ private decryptAESGCM(encryptedData: Buffer, key: Buffer): string | null {
200
+ return this.decryptor.decryptAESGCM(encryptedData, key)
411
201
  }
412
202
 
413
203
  private getKeychainPassword(): string | null {
@@ -415,6 +205,7 @@ export class InstagramTokenExtractor {
415
205
  const password = this.execSecurityCommand(variant.service, variant.account)
416
206
  if (password) return password
417
207
  }
208
+
418
209
  return null
419
210
  }
420
211
 
@@ -422,55 +213,10 @@ export class InstagramTokenExtractor {
422
213
  try {
423
214
  const safeService = service.replace(/"/g, '\\"')
424
215
  const safeAccount = account.replace(/"/g, '\\"')
425
- const result = execSync(
426
- `security find-generic-password -s "${safeService}" -a "${safeAccount}" -w 2>/dev/null`,
427
- { encoding: 'utf8' },
428
- )
429
- return result.trim()
430
- } catch {
431
- return null
432
- }
433
- }
434
-
435
- private decryptAESCBC(encryptedData: Buffer, key: Buffer): string | null {
436
- try {
437
- const ciphertext = encryptedData.subarray(3)
438
- const iv = Buffer.alloc(16, 0x20)
439
-
440
- const decipher = createDecipheriv('aes-128-cbc', key, iv)
441
- decipher.setAutoPadding(true)
442
-
443
- const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])
444
-
445
- // Chromium v130+ prepends a 32-byte integrity hash before the actual cookie value.
446
- // Detect by checking if the first bytes contain non-printable characters.
447
- if (decrypted.length > 32) {
448
- const hasNonPrintablePrefix = decrypted.subarray(0, 32).some((b) => b < 0x20 || b > 0x7e)
449
- if (hasNonPrintablePrefix) {
450
- return decrypted.subarray(32).toString('utf8')
451
- }
452
- }
453
-
454
- return decrypted.toString('utf8')
455
- } catch {
456
- return null
457
- }
458
- }
459
-
460
- private decryptAESGCM(encryptedData: Buffer, key: Buffer): string | null {
461
- try {
462
- // Format: v10 (3 bytes) + IV (12 bytes) + ciphertext + auth tag (16 bytes)
463
- if (encryptedData.length < 3 + 12 + 16) return null
464
-
465
- const iv = encryptedData.subarray(3, 15)
466
- const authTag = encryptedData.subarray(-16)
467
- const ciphertext = encryptedData.subarray(15, -16)
468
-
469
- const decipher = createDecipheriv('aes-256-gcm', key, iv)
470
- decipher.setAuthTag(authTag)
471
-
472
- const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])
473
- return decrypted.toString('utf8')
216
+ const result = execSync(`security find-generic-password -s "${safeService}" -a "${safeAccount}" -w 2>/dev/null`, {
217
+ encoding: 'utf8',
218
+ })
219
+ return result.trim() || null
474
220
  } catch {
475
221
  return null
476
222
  }
@@ -1,10 +1,6 @@
1
1
  import { describe, expect, it } from 'bun:test'
2
- import {
3
- InstagramError,
4
- createAccountId,
5
- extractMessageText,
6
- getMessageType,
7
- } from './types'
2
+
3
+ import { InstagramError, createAccountId, extractMessageText, getMessageType } from './types'
8
4
 
9
5
  describe('createAccountId', () => {
10
6
  it('normalizes plain username', () => {
@@ -83,8 +83,10 @@ export function getMessageType(item: Record<string, unknown>): string {
83
83
  switch (itemType) {
84
84
  case 'clip':
85
85
  case 'felix_share':
86
- case 'reel_share': return 'reel_share'
87
- default: return itemType
86
+ case 'reel_share':
87
+ return 'reel_share'
88
+ default:
89
+ return itemType
88
90
  }
89
91
  }
90
92
 
@@ -28,7 +28,7 @@ function computeXVC(email: string): string {
28
28
  function buildHeaders(email: string): Record<string, string> {
29
29
  return {
30
30
  'Content-Type': 'application/x-www-form-urlencoded',
31
- 'A': ANDROID_AGENT,
31
+ A: ANDROID_AGENT,
32
32
  'User-Agent': ANDROID_USER_AGENT,
33
33
  'Accept-Language': 'ko',
34
34
  'X-VC': computeXVC(email),
@@ -112,9 +112,10 @@ export async function attemptLogin(
112
112
  return {
113
113
  authenticated: false,
114
114
  error: 'bad_credentials',
115
- message: typeof data.message === 'string'
116
- ? `Login failed: ${data.message}`
117
- : 'Login failed: incorrect email or password.',
115
+ message:
116
+ typeof data.message === 'string'
117
+ ? `Login failed: ${data.message}`
118
+ : 'Login failed: incorrect email or password.',
118
119
  }
119
120
  }
120
121
 
@@ -155,7 +156,11 @@ export async function requestPasscode(email: string, password: string, deviceUui
155
156
  })
156
157
 
157
158
  if (!response.ok) {
158
- return { authenticated: false, error: 'passcode_request_failed', message: `HTTP ${response.status} from passcode endpoint` }
159
+ return {
160
+ authenticated: false,
161
+ error: 'passcode_request_failed',
162
+ message: `HTTP ${response.status} from passcode endpoint`,
163
+ }
159
164
  }
160
165
 
161
166
  const data = (await response.json()) as { status?: number; passcode?: string; remainingSeconds?: number }
@@ -202,7 +207,11 @@ export async function registerDevice(
202
207
  })
203
208
 
204
209
  if (!response.ok) {
205
- return { authenticated: false, error: 'registration_failed', message: `HTTP ${response.status} from register endpoint` }
210
+ return {
211
+ authenticated: false,
212
+ error: 'registration_failed',
213
+ message: `HTTP ${response.status} from register endpoint`,
214
+ }
206
215
  }
207
216
 
208
217
  const data = (await response.json()) as {
@@ -248,7 +257,14 @@ export async function loginFlow(options: {
248
257
  const forced = options.force ?? false
249
258
 
250
259
  // Step 1: Try login (forced:false for tablet-first safe attempt)
251
- const loginResult = await attemptLogin(options.email, options.password, deviceUuid, deviceType, forced, options.debugLog)
260
+ const loginResult = await attemptLogin(
261
+ options.email,
262
+ options.password,
263
+ deviceUuid,
264
+ deviceType,
265
+ forced,
266
+ options.debugLog,
267
+ )
252
268
 
253
269
  if (loginResult.authenticated) {
254
270
  return loginResult
@@ -261,7 +277,13 @@ export async function loginFlow(options: {
261
277
  if (passcodeResult.error) {
262
278
  return {
263
279
  ...passcodeResult,
264
- credentials: { access_token: '', refresh_token: '', user_id: '', device_uuid: deviceUuid, device_type: deviceType },
280
+ credentials: {
281
+ access_token: '',
282
+ refresh_token: '',
283
+ user_id: '',
284
+ device_uuid: deviceUuid,
285
+ device_type: deviceType,
286
+ },
265
287
  }
266
288
  }
267
289
 
@@ -478,17 +478,23 @@ describe('KakaoTalkClient', () => {
478
478
 
479
479
  test('returns profile data on success', async () => {
480
480
  mockFetch
481
- .mockResolvedValueOnce(makeJsonResponse({
482
- profile: {
483
- nickName: 'Test User',
484
- profileImageUrl: 'https://example.com/profile.jpg',
485
- originalProfileImageUrl: 'https://example.com/original.jpg',
486
- statusMessage: 'Hello world',
487
- },
488
- }))
481
+ .mockResolvedValueOnce(
482
+ makeJsonResponse({
483
+ profile: {
484
+ nickName: 'Test User',
485
+ profileImageUrl: 'https://example.com/profile.jpg',
486
+ originalProfileImageUrl: 'https://example.com/original.jpg',
487
+ statusMessage: 'Hello world',
488
+ },
489
+ }),
490
+ )
489
491
  .mockResolvedValueOnce(makeJsonResponse({ accountDisplayId: 'testuser123' }))
490
492
 
491
- const client = await new KakaoTalkClient().login({ oauthToken: 'mytoken', userId: 'user42', deviceUuid: 'device1' })
493
+ const client = await new KakaoTalkClient().login({
494
+ oauthToken: 'mytoken',
495
+ userId: 'user42',
496
+ deviceUuid: 'device1',
497
+ })
492
498
  const profile = await client.getProfile()
493
499
 
494
500
  expect(profile.user_id).toBe('user42')
@@ -517,7 +523,11 @@ describe('KakaoTalkClient', () => {
517
523
  .mockResolvedValueOnce(makeJsonResponse({}, 401))
518
524
  .mockResolvedValueOnce(makeJsonResponse({ accountDisplayId: null }))
519
525
 
520
- const client = await new KakaoTalkClient().login({ oauthToken: 'mytoken', userId: 'user42', deviceUuid: 'device1' })
526
+ const client = await new KakaoTalkClient().login({
527
+ oauthToken: 'mytoken',
528
+ userId: 'user42',
529
+ deviceUuid: 'device1',
530
+ })
521
531
  try {
522
532
  await client.getProfile()
523
533
  expect.unreachable('should have thrown')
@@ -531,17 +541,23 @@ describe('KakaoTalkClient', () => {
531
541
 
532
542
  test('returns null account_display_id when more_settings request fails', async () => {
533
543
  mockFetch
534
- .mockResolvedValueOnce(makeJsonResponse({
535
- profile: {
536
- nickName: 'Test User',
537
- profileImageUrl: null,
538
- originalProfileImageUrl: null,
539
- statusMessage: null,
540
- },
541
- }))
544
+ .mockResolvedValueOnce(
545
+ makeJsonResponse({
546
+ profile: {
547
+ nickName: 'Test User',
548
+ profileImageUrl: null,
549
+ originalProfileImageUrl: null,
550
+ statusMessage: null,
551
+ },
552
+ }),
553
+ )
542
554
  .mockResolvedValueOnce(makeJsonResponse({}, 500))
543
555
 
544
- const client = await new KakaoTalkClient().login({ oauthToken: 'mytoken', userId: 'user42', deviceUuid: 'device1' })
556
+ const client = await new KakaoTalkClient().login({
557
+ oauthToken: 'mytoken',
558
+ userId: 'user42',
559
+ deviceUuid: 'device1',
560
+ })
545
561
  const profile = await client.getProfile()
546
562
 
547
563
  expect(profile.user_id).toBe('user42')
@@ -582,9 +598,7 @@ describe('KakaoTalkClient', () => {
582
598
 
583
599
  test('concurrent calls share a single login', async () => {
584
600
  // Make login take some time
585
- mockLogin.mockImplementation(
586
- () => new Promise((resolve) => setTimeout(() => resolve(DEFAULT_LOGIN_RESULT), 50)),
587
- )
601
+ mockLogin.mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve(DEFAULT_LOGIN_RESULT), 50)))
588
602
  mockGetChatLogs.mockResolvedValue({
589
603
  body: { status: 0, chatLogs: [], eof: true },
590
604
  })
@@ -598,9 +612,7 @@ describe('KakaoTalkClient', () => {
598
612
  })
599
613
 
600
614
  test('retries login after failure', async () => {
601
- mockLogin
602
- .mockRejectedValueOnce(new Error('Connection refused'))
603
- .mockResolvedValueOnce(DEFAULT_LOGIN_RESULT)
615
+ mockLogin.mockRejectedValueOnce(new Error('Connection refused')).mockResolvedValueOnce(DEFAULT_LOGIN_RESULT)
604
616
 
605
617
  const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
606
618