agent-messenger 2.7.0 → 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.
- package/.claude-plugin/plugin.json +1 -1
- package/.github/workflows/ci.yml +6 -0
- package/.oxfmtrc.json +13 -1
- package/.oxlintrc.json +10 -1
- package/README.md +1 -1
- package/dist/package.json +59 -58
- package/dist/src/platforms/channeltalk/client.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/client.js +2 -2
- package/dist/src/platforms/channeltalk/client.js.map +1 -1
- package/dist/src/platforms/channeltalk/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/commands/auth.js.map +1 -1
- package/dist/src/platforms/channeltalk/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/commands/message.js.map +1 -1
- package/dist/src/platforms/channeltalk/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/channeltalk/ensure-auth.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/ensure-auth.js.map +1 -1
- package/dist/src/platforms/channeltalk/token-extractor.d.ts +9 -23
- package/dist/src/platforms/channeltalk/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/token-extractor.js +109 -341
- package/dist/src/platforms/channeltalk/token-extractor.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/client.d.ts +1 -1
- package/dist/src/platforms/channeltalkbot/client.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/client.js +4 -4
- package/dist/src/platforms/channeltalkbot/client.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/auth.js +4 -1
- package/dist/src/platforms/channeltalkbot/commands/auth.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/shared.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/shared.js.map +1 -1
- package/dist/src/platforms/discord/commands/auth.js.map +1 -1
- package/dist/src/platforms/discord/commands/whoami.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/whoami.js.map +1 -1
- package/dist/src/platforms/discord/token-extractor.d.ts +2 -10
- package/dist/src/platforms/discord/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/discord/token-extractor.js +38 -172
- package/dist/src/platforms/discord/token-extractor.js.map +1 -1
- package/dist/src/platforms/discordbot/client.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/client.js.map +1 -1
- package/dist/src/platforms/instagram/cli.d.ts.map +1 -1
- package/dist/src/platforms/instagram/cli.js +1 -4
- package/dist/src/platforms/instagram/cli.js.map +1 -1
- package/dist/src/platforms/instagram/client.d.ts.map +1 -1
- package/dist/src/platforms/instagram/client.js +8 -7
- package/dist/src/platforms/instagram/client.js.map +1 -1
- package/dist/src/platforms/instagram/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/instagram/commands/auth.js.map +1 -1
- package/dist/src/platforms/instagram/commands/chat.d.ts.map +1 -1
- package/dist/src/platforms/instagram/commands/chat.js.map +1 -1
- package/dist/src/platforms/instagram/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/instagram/commands/message.js.map +1 -1
- package/dist/src/platforms/instagram/commands/shared.d.ts.map +1 -1
- package/dist/src/platforms/instagram/commands/shared.js.map +1 -1
- package/dist/src/platforms/instagram/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/instagram/credential-manager.js +1 -1
- package/dist/src/platforms/instagram/credential-manager.js.map +1 -1
- package/dist/src/platforms/instagram/ensure-auth.d.ts.map +1 -1
- package/dist/src/platforms/instagram/ensure-auth.js.map +1 -1
- package/dist/src/platforms/instagram/token-extractor.d.ts +7 -19
- package/dist/src/platforms/instagram/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/instagram/token-extractor.js +44 -270
- package/dist/src/platforms/instagram/token-extractor.js.map +1 -1
- package/dist/src/platforms/instagram/types.d.ts.map +1 -1
- package/dist/src/platforms/instagram/types.js +4 -2
- package/dist/src/platforms/instagram/types.js.map +1 -1
- package/dist/src/platforms/kakaotalk/auth/kakao-login.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/auth/kakao-login.js +18 -4
- package/dist/src/platforms/kakaotalk/auth/kakao-login.js.map +1 -1
- package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/client.js +3 -3
- package/dist/src/platforms/kakaotalk/client.js.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/auth.js +15 -9
- package/dist/src/platforms/kakaotalk/commands/auth.js.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/shared.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/shared.js.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/connection.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/connection.js.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/crypto.js +1 -1
- package/dist/src/platforms/kakaotalk/protocol/crypto.js.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/session.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/session.js +1 -3
- package/dist/src/platforms/kakaotalk/protocol/session.js.map +1 -1
- package/dist/src/platforms/kakaotalk/token-extractor.js +5 -2
- package/dist/src/platforms/kakaotalk/token-extractor.js.map +1 -1
- package/dist/src/platforms/kakaotalk/types.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/types.js +4 -2
- package/dist/src/platforms/kakaotalk/types.js.map +1 -1
- package/dist/src/platforms/line/cli.d.ts.map +1 -1
- package/dist/src/platforms/line/cli.js +1 -4
- package/dist/src/platforms/line/cli.js.map +1 -1
- package/dist/src/platforms/line/client.d.ts.map +1 -1
- package/dist/src/platforms/line/client.js +5 -13
- package/dist/src/platforms/line/client.js.map +1 -1
- package/dist/src/platforms/line/commands/chat.d.ts.map +1 -1
- package/dist/src/platforms/line/commands/chat.js.map +1 -1
- package/dist/src/platforms/line/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/line/commands/message.js.map +1 -1
- package/dist/src/platforms/line/listener.js +1 -1
- package/dist/src/platforms/line/listener.js.map +1 -1
- package/dist/src/platforms/slack/cli.d.ts.map +1 -1
- package/dist/src/platforms/slack/cli.js.map +1 -1
- package/dist/src/platforms/slack/client-mappers.d.ts +14 -0
- package/dist/src/platforms/slack/client-mappers.d.ts.map +1 -0
- package/dist/src/platforms/slack/client-mappers.js +245 -0
- package/dist/src/platforms/slack/client-mappers.js.map +1 -0
- package/dist/src/platforms/slack/client.d.ts +0 -1
- package/dist/src/platforms/slack/client.d.ts.map +1 -1
- package/dist/src/platforms/slack/client.js +41 -455
- package/dist/src/platforms/slack/client.js.map +1 -1
- package/dist/src/platforms/slack/commands/channel.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/channel.js.map +1 -1
- package/dist/src/platforms/slack/commands/emoji.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/emoji.js +1 -3
- package/dist/src/platforms/slack/commands/emoji.js.map +1 -1
- package/dist/src/platforms/slack/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/message.js.map +1 -1
- package/dist/src/platforms/slack/commands/reminder.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/reminder.js.map +1 -1
- package/dist/src/platforms/slack/commands/user.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/user.js.map +1 -1
- package/dist/src/platforms/slack/commands/usergroup.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/usergroup.js.map +1 -1
- package/dist/src/platforms/slack/commands/whoami.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/whoami.js.map +1 -1
- package/dist/src/platforms/slack/token-extractor.d.ts +2 -6
- package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/slack/token-extractor.js +35 -229
- package/dist/src/platforms/slack/token-extractor.js.map +1 -1
- package/dist/src/platforms/slackbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/slackbot/cli.js +1 -1
- package/dist/src/platforms/slackbot/cli.js.map +1 -1
- package/dist/src/platforms/teams/client.d.ts.map +1 -1
- package/dist/src/platforms/teams/client.js +1 -1
- package/dist/src/platforms/teams/client.js.map +1 -1
- package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/auth.js +4 -1
- package/dist/src/platforms/teams/commands/auth.js.map +1 -1
- package/dist/src/platforms/teams/commands/whoami.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/whoami.js.map +1 -1
- package/dist/src/platforms/teams/token-extractor.d.ts +6 -18
- package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/teams/token-extractor.js +71 -324
- package/dist/src/platforms/teams/token-extractor.js.map +1 -1
- package/dist/src/platforms/telegram/cli.d.ts.map +1 -1
- package/dist/src/platforms/telegram/cli.js +1 -4
- package/dist/src/platforms/telegram/cli.js.map +1 -1
- package/dist/src/platforms/telegram/client.d.ts.map +1 -1
- package/dist/src/platforms/telegram/client.js.map +1 -1
- package/dist/src/platforms/telegram/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/telegram/commands/auth.js +1 -1
- package/dist/src/platforms/telegram/commands/auth.js.map +1 -1
- package/dist/src/platforms/telegram/commands/chat.d.ts.map +1 -1
- package/dist/src/platforms/telegram/commands/chat.js.map +1 -1
- package/dist/src/platforms/telegram/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/telegram/commands/message.js.map +1 -1
- package/dist/src/platforms/telegram/commands/whoami.js +1 -1
- package/dist/src/platforms/telegram/commands/whoami.js.map +1 -1
- package/dist/src/platforms/telegram/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/telegram/credential-manager.js +6 -2
- package/dist/src/platforms/telegram/credential-manager.js.map +1 -1
- package/dist/src/platforms/telegram/my-telegram-org.js.map +1 -1
- package/dist/src/platforms/webex/cli.d.ts.map +1 -1
- package/dist/src/platforms/webex/cli.js +1 -4
- package/dist/src/platforms/webex/cli.js.map +1 -1
- package/dist/src/platforms/webex/client.d.ts.map +1 -1
- package/dist/src/platforms/webex/client.js +3 -7
- package/dist/src/platforms/webex/client.js.map +1 -1
- package/dist/src/platforms/webex/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/auth.js +1 -3
- package/dist/src/platforms/webex/commands/auth.js.map +1 -1
- package/dist/src/platforms/webex/commands/member.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/member.js +1 -3
- package/dist/src/platforms/webex/commands/member.js.map +1 -1
- package/dist/src/platforms/webex/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/message.js.map +1 -1
- package/dist/src/platforms/webex/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/webex/commands/space.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/space.js.map +1 -1
- package/dist/src/platforms/webex/commands/whoami.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/whoami.js.map +1 -1
- package/dist/src/platforms/webex/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/webex/credential-manager.js.map +1 -1
- package/dist/src/platforms/webex/ensure-auth.d.ts.map +1 -1
- package/dist/src/platforms/webex/ensure-auth.js +1 -3
- package/dist/src/platforms/webex/ensure-auth.js.map +1 -1
- package/dist/src/platforms/webex/index.d.ts +1 -1
- package/dist/src/platforms/webex/index.d.ts.map +1 -1
- package/dist/src/platforms/webex/index.js.map +1 -1
- package/dist/src/platforms/webex/markdown-to-html.js.map +1 -1
- package/dist/src/platforms/webex/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/webex/token-extractor.js +5 -14
- package/dist/src/platforms/webex/token-extractor.js.map +1 -1
- package/dist/src/platforms/wechatbot/client.d.ts.map +1 -1
- package/dist/src/platforms/wechatbot/client.js.map +1 -1
- package/dist/src/platforms/wechatbot/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/wechatbot/commands/message.js.map +1 -1
- package/dist/src/platforms/whatsapp/cli.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/cli.js +1 -4
- package/dist/src/platforms/whatsapp/cli.js.map +1 -1
- package/dist/src/platforms/whatsapp/commands/chat.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/commands/chat.js.map +1 -1
- package/dist/src/platforms/whatsapp/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/commands/message.js.map +1 -1
- package/dist/src/platforms/whatsapp/commands/shared.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/commands/shared.js.map +1 -1
- package/dist/src/platforms/whatsapp/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/credential-manager.js +1 -1
- package/dist/src/platforms/whatsapp/credential-manager.js.map +1 -1
- package/dist/src/platforms/whatsapp/ensure-auth.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/ensure-auth.js.map +1 -1
- package/dist/src/platforms/whatsappbot/client.d.ts.map +1 -1
- package/dist/src/platforms/whatsappbot/client.js +2 -2
- package/dist/src/platforms/whatsappbot/client.js.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/auth.js +4 -1
- package/dist/src/platforms/whatsappbot/commands/auth.js.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/message.js.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/shared.d.ts.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/shared.js.map +1 -1
- package/dist/src/shared/chromium/browsers.d.ts +7 -0
- package/dist/src/shared/chromium/browsers.d.ts.map +1 -0
- package/dist/src/shared/chromium/browsers.js +89 -0
- package/dist/src/shared/chromium/browsers.js.map +1 -0
- package/dist/src/shared/chromium/cookie-reader.d.ts +20 -0
- package/dist/src/shared/chromium/cookie-reader.d.ts.map +1 -0
- package/dist/src/shared/chromium/cookie-reader.js +99 -0
- package/dist/src/shared/chromium/cookie-reader.js.map +1 -0
- package/dist/src/shared/chromium/decryptor.d.ts +42 -0
- package/dist/src/shared/chromium/decryptor.d.ts.map +1 -0
- package/dist/src/shared/chromium/decryptor.js +205 -0
- package/dist/src/shared/chromium/decryptor.js.map +1 -0
- package/dist/src/shared/chromium/index.d.ts +6 -0
- package/dist/src/shared/chromium/index.d.ts.map +1 -0
- package/dist/src/shared/chromium/index.js +4 -0
- package/dist/src/shared/chromium/index.js.map +1 -0
- package/dist/src/shared/chromium/types.d.ts +11 -0
- package/dist/src/shared/chromium/types.d.ts.map +1 -0
- package/dist/src/shared/chromium/types.js +2 -0
- package/dist/src/shared/chromium/types.js.map +1 -0
- package/dist/src/shared/utils/derived-key-cache.d.ts +1 -1
- package/dist/src/shared/utils/derived-key-cache.d.ts.map +1 -1
- package/dist/src/shared/utils/linux-keyring.js +4 -1
- package/dist/src/shared/utils/linux-keyring.js.map +1 -1
- package/dist/src/tui/adapters/kakaotalk-adapter.d.ts.map +1 -1
- package/dist/src/tui/adapters/kakaotalk-adapter.js +6 -1
- package/dist/src/tui/adapters/kakaotalk-adapter.js.map +1 -1
- package/dist/src/tui/adapters/telegram-adapter.js +1 -1
- package/dist/src/tui/adapters/telegram-adapter.js.map +1 -1
- package/dist/src/tui/adapters/webex-adapter.js +1 -1
- package/dist/src/tui/adapters/webex-adapter.js.map +1 -1
- package/dist/src/tui/app.d.ts.map +1 -1
- package/dist/src/tui/app.js +112 -23
- package/dist/src/tui/app.js.map +1 -1
- package/dist/src/tui/utils.d.ts.map +1 -1
- package/dist/src/tui/utils.js +11 -13
- package/dist/src/tui/utils.js.map +1 -1
- package/dist/src/tui/views/channel-picker.d.ts.map +1 -1
- package/dist/src/tui/views/channel-picker.js.map +1 -1
- package/dist/src/tui/views/workspace-picker.d.ts.map +1 -1
- package/dist/src/tui/views/workspace-picker.js.map +1 -1
- package/docs/content/docs/cli/channeltalk.mdx +24 -22
- package/docs/content/docs/cli/channeltalkbot.mdx +7 -7
- package/docs/content/docs/cli/instagram.mdx +4 -4
- package/docs/content/docs/cli/kakaotalk.mdx +9 -8
- package/docs/content/docs/cli/line.mdx +14 -14
- package/docs/content/docs/cli/webex.mdx +19 -19
- package/docs/content/docs/cli/wechatbot.mdx +12 -11
- package/docs/content/docs/cli/whatsapp.mdx +5 -4
- package/docs/content/docs/cli/whatsappbot.mdx +11 -11
- package/docs/content/docs/index.mdx +7 -7
- package/docs/content/docs/meta.json +1 -9
- package/docs/content/docs/sdk/channeltalk.mdx +5 -6
- package/docs/content/docs/sdk/channeltalkbot.mdx +6 -12
- package/docs/content/docs/sdk/discord.mdx +36 -43
- package/docs/content/docs/sdk/instagram.mdx +18 -18
- package/docs/content/docs/sdk/kakaotalk.mdx +27 -18
- package/docs/content/docs/sdk/line.mdx +8 -13
- package/docs/content/docs/sdk/meta.json +14 -1
- package/docs/content/docs/sdk/slack.mdx +36 -42
- package/docs/content/docs/sdk/teams.mdx +2 -8
- package/docs/content/docs/sdk/webex.mdx +2 -12
- package/docs/content/docs/sdk/wechatbot.mdx +1 -5
- package/docs/content/docs/sdk/whatsapp.mdx +10 -19
- package/docs/content/docs/sdk/whatsappbot.mdx +2 -10
- package/docs/content/docs/tui.mdx +23 -23
- package/docs/src/app/page.tsx +353 -108
- package/e2e/channeltalkbot.e2e.test.ts +1 -5
- package/e2e/config.ts +6 -2
- package/package.json +59 -58
- package/scripts/prepublish.ts +1 -3
- package/skills/agent-channeltalk/SKILL.md +1 -1
- package/skills/agent-channeltalkbot/SKILL.md +1 -1
- package/skills/agent-discord/SKILL.md +1 -1
- package/skills/agent-discordbot/SKILL.md +1 -1
- package/skills/agent-instagram/SKILL.md +1 -1
- package/skills/agent-kakaotalk/SKILL.md +1 -1
- package/skills/agent-line/SKILL.md +1 -1
- package/skills/agent-slack/SKILL.md +1 -1
- package/skills/agent-slackbot/SKILL.md +1 -1
- package/skills/agent-teams/SKILL.md +1 -1
- package/skills/agent-telegram/SKILL.md +1 -1
- package/skills/agent-webex/SKILL.md +1 -1
- package/skills/agent-wechatbot/SKILL.md +1 -1
- package/skills/agent-whatsapp/SKILL.md +1 -1
- package/skills/agent-whatsappbot/SKILL.md +1 -1
- package/src/platforms/channeltalk/client.test.ts +116 -29
- package/src/platforms/channeltalk/client.ts +26 -6
- package/src/platforms/channeltalk/commands/auth.test.ts +5 -5
- package/src/platforms/channeltalk/commands/auth.ts +19 -5
- package/src/platforms/channeltalk/commands/message.test.ts +2 -6
- package/src/platforms/channeltalk/commands/message.ts +5 -1
- package/src/platforms/channeltalk/commands/snapshot.test.ts +19 -4
- package/src/platforms/channeltalk/commands/snapshot.ts +5 -1
- package/src/platforms/channeltalk/ensure-auth.test.ts +20 -17
- package/src/platforms/channeltalk/ensure-auth.ts +6 -7
- package/src/platforms/channeltalk/index.ts +0 -1
- package/src/platforms/channeltalk/token-extractor.test.ts +33 -25
- package/src/platforms/channeltalk/token-extractor.ts +120 -372
- package/src/platforms/channeltalkbot/client.test.ts +1 -3
- package/src/platforms/channeltalkbot/client.ts +39 -13
- package/src/platforms/channeltalkbot/commands/auth.test.ts +3 -1
- package/src/platforms/channeltalkbot/commands/auth.ts +4 -1
- package/src/platforms/channeltalkbot/commands/bot.test.ts +13 -5
- package/src/platforms/channeltalkbot/commands/message.test.ts +12 -6
- package/src/platforms/channeltalkbot/commands/shared.ts +6 -2
- package/src/platforms/channeltalkbot/commands/snapshot.test.ts +17 -5
- package/src/platforms/channeltalkbot/credential-manager.test.ts +1 -1
- package/src/platforms/channeltalkbot/index.test.ts +0 -2
- package/src/platforms/channeltalkbot/index.ts +0 -1
- package/src/platforms/discord/commands/auth.test.ts +6 -4
- package/src/platforms/discord/commands/auth.ts +14 -14
- package/src/platforms/discord/commands/whoami.test.ts +2 -4
- package/src/platforms/discord/commands/whoami.ts +2 -0
- package/src/platforms/discord/ensure-auth.test.ts +5 -3
- package/src/platforms/discord/index.ts +0 -1
- package/src/platforms/discord/listener.test.ts +7 -1
- package/src/platforms/discord/token-extractor.test.ts +18 -12
- package/src/platforms/discord/token-extractor.ts +46 -190
- package/src/platforms/discordbot/client.ts +1 -4
- package/src/platforms/discordbot/commands/auth.test.ts +3 -1
- package/src/platforms/discordbot/commands/channel.test.ts +3 -1
- package/src/platforms/discordbot/commands/message.test.ts +3 -1
- package/src/platforms/discordbot/commands/server.test.ts +3 -1
- package/src/platforms/discordbot/commands/snapshot.test.ts +3 -1
- package/src/platforms/discordbot/commands/thread.test.ts +3 -1
- package/src/platforms/discordbot/commands/user.test.ts +3 -1
- package/src/platforms/instagram/cli.ts +1 -4
- package/src/platforms/instagram/client.test.ts +3 -8
- package/src/platforms/instagram/client.ts +39 -34
- package/src/platforms/instagram/commands/auth.test.ts +13 -12
- package/src/platforms/instagram/commands/auth.ts +136 -71
- package/src/platforms/instagram/commands/chat.test.ts +21 -24
- package/src/platforms/instagram/commands/chat.ts +2 -0
- package/src/platforms/instagram/commands/message.test.ts +29 -24
- package/src/platforms/instagram/commands/message.ts +3 -4
- package/src/platforms/instagram/commands/shared.ts +2 -5
- package/src/platforms/instagram/commands/whoami.test.ts +4 -6
- package/src/platforms/instagram/credential-manager.ts +2 -6
- package/src/platforms/instagram/ensure-auth.test.ts +1 -4
- package/src/platforms/instagram/ensure-auth.ts +6 -3
- package/src/platforms/instagram/listener.test.ts +7 -3
- package/src/platforms/instagram/token-extractor.test.ts +4 -16
- package/src/platforms/instagram/token-extractor.ts +55 -309
- package/src/platforms/instagram/types.test.ts +2 -6
- package/src/platforms/instagram/types.ts +4 -2
- package/src/platforms/kakaotalk/auth/kakao-login.ts +30 -8
- package/src/platforms/kakaotalk/client.test.ts +37 -25
- package/src/platforms/kakaotalk/client.ts +23 -12
- package/src/platforms/kakaotalk/commands/auth.test.ts +6 -18
- package/src/platforms/kakaotalk/commands/auth.ts +101 -47
- package/src/platforms/kakaotalk/commands/chat.test.ts +8 -11
- package/src/platforms/kakaotalk/commands/message.test.ts +15 -24
- package/src/platforms/kakaotalk/commands/shared.ts +1 -0
- package/src/platforms/kakaotalk/commands/whoami.test.ts +6 -10
- package/src/platforms/kakaotalk/credential-manager.test.ts +1 -4
- package/src/platforms/kakaotalk/index.test.ts +1 -0
- package/src/platforms/kakaotalk/index.ts +0 -2
- package/src/platforms/kakaotalk/listener.test.ts +7 -1
- package/src/platforms/kakaotalk/protocol/connection.ts +4 -1
- package/src/platforms/kakaotalk/protocol/crypto.ts +1 -1
- package/src/platforms/kakaotalk/protocol/session.ts +12 -6
- package/src/platforms/kakaotalk/token-extractor.ts +5 -5
- package/src/platforms/kakaotalk/types.ts +8 -7
- package/src/platforms/line/cli.ts +1 -4
- package/src/platforms/line/client.ts +12 -20
- package/src/platforms/line/commands/auth.test.ts +2 -1
- package/src/platforms/line/commands/chat.test.ts +2 -1
- package/src/platforms/line/commands/chat.ts +1 -4
- package/src/platforms/line/commands/friend.test.ts +2 -1
- package/src/platforms/line/commands/message.test.ts +2 -1
- package/src/platforms/line/commands/message.ts +2 -9
- package/src/platforms/line/commands/whoami.test.ts +2 -1
- package/src/platforms/line/credential-manager.test.ts +1 -2
- package/src/platforms/line/index.test.ts +1 -0
- package/src/platforms/line/listener.ts +1 -1
- package/src/platforms/line/types.test.ts +1 -0
- package/src/platforms/slack/cli.ts +3 -1
- package/src/platforms/slack/client-mappers.ts +297 -0
- package/src/platforms/slack/client.test.ts +532 -17
- package/src/platforms/slack/client.ts +69 -458
- package/src/platforms/slack/commands/channel.ts +1 -4
- package/src/platforms/slack/commands/emoji.test.ts +6 -4
- package/src/platforms/slack/commands/emoji.ts +20 -22
- package/src/platforms/slack/commands/message.ts +6 -1
- package/src/platforms/slack/commands/pin.test.ts +14 -12
- package/src/platforms/slack/commands/reminder.ts +7 -6
- package/src/platforms/slack/commands/user.ts +6 -1
- package/src/platforms/slack/commands/usergroup.test.ts +3 -3
- package/src/platforms/slack/commands/usergroup.ts +10 -7
- package/src/platforms/slack/commands/whoami.test.ts +1 -1
- package/src/platforms/slack/commands/whoami.ts +2 -0
- package/src/platforms/slack/index.ts +0 -2
- package/src/platforms/slack/listener.test.ts +1 -0
- package/src/platforms/slack/token-extractor.test.ts +7 -12
- package/src/platforms/slack/token-extractor.ts +47 -255
- package/src/platforms/slackbot/cli.ts +8 -1
- package/src/platforms/slackbot/commands/auth.test.ts +3 -1
- package/src/platforms/teams/client.ts +1 -1
- package/src/platforms/teams/commands/auth.test.ts +1 -1
- package/src/platforms/teams/commands/auth.ts +4 -1
- package/src/platforms/teams/commands/whoami.test.ts +2 -4
- package/src/platforms/teams/commands/whoami.ts +2 -0
- package/src/platforms/teams/index.ts +0 -1
- package/src/platforms/teams/token-extractor.ts +82 -350
- package/src/platforms/telegram/app-config.test.ts +1 -0
- package/src/platforms/telegram/chat-utils.test.ts +5 -1
- package/src/platforms/telegram/cli.ts +2 -4
- package/src/platforms/telegram/client.test.ts +16 -3
- package/src/platforms/telegram/client.ts +14 -4
- package/src/platforms/telegram/commands/auth.test.ts +1 -0
- package/src/platforms/telegram/commands/auth.ts +3 -4
- package/src/platforms/telegram/commands/chat.test.ts +2 -5
- package/src/platforms/telegram/commands/chat.ts +1 -0
- package/src/platforms/telegram/commands/message.test.ts +2 -5
- package/src/platforms/telegram/commands/message.ts +1 -0
- package/src/platforms/telegram/commands/shared.test.ts +1 -0
- package/src/platforms/telegram/commands/whoami.test.ts +5 -7
- package/src/platforms/telegram/commands/whoami.ts +1 -1
- package/src/platforms/telegram/credential-manager.test.ts +1 -0
- package/src/platforms/telegram/credential-manager.ts +11 -2
- package/src/platforms/telegram/my-telegram-org.ts +6 -2
- package/src/platforms/telegram/types.test.ts +1 -0
- package/src/platforms/webex/app-config.test.ts +1 -0
- package/src/platforms/webex/cli.ts +1 -4
- package/src/platforms/webex/client.test.ts +4 -12
- package/src/platforms/webex/client.ts +14 -52
- package/src/platforms/webex/commands/auth.test.ts +7 -1
- package/src/platforms/webex/commands/auth.ts +12 -15
- package/src/platforms/webex/commands/member.test.ts +1 -3
- package/src/platforms/webex/commands/member.ts +14 -19
- package/src/platforms/webex/commands/message.ts +4 -15
- package/src/platforms/webex/commands/snapshot.test.ts +28 -3
- package/src/platforms/webex/commands/snapshot.ts +3 -3
- package/src/platforms/webex/commands/space.test.ts +3 -3
- package/src/platforms/webex/commands/space.ts +2 -9
- package/src/platforms/webex/commands/whoami.test.ts +12 -5
- package/src/platforms/webex/commands/whoami.ts +2 -0
- package/src/platforms/webex/credential-manager.ts +11 -2
- package/src/platforms/webex/ensure-auth.ts +1 -3
- package/src/platforms/webex/index.ts +1 -7
- package/src/platforms/webex/markdown-to-html.test.ts +6 -18
- package/src/platforms/webex/markdown-to-html.ts +8 -8
- package/src/platforms/webex/token-extractor.ts +6 -29
- package/src/platforms/wechatbot/client.test.ts +6 -2
- package/src/platforms/wechatbot/client.ts +6 -1
- package/src/platforms/wechatbot/commands/auth.test.ts +3 -7
- package/src/platforms/wechatbot/commands/message.test.ts +1 -4
- package/src/platforms/wechatbot/commands/message.ts +5 -1
- package/src/platforms/wechatbot/commands/template.test.ts +1 -4
- package/src/platforms/wechatbot/commands/user.test.ts +2 -7
- package/src/platforms/whatsapp/cli.ts +1 -4
- package/src/platforms/whatsapp/commands/auth.test.ts +19 -22
- package/src/platforms/whatsapp/commands/chat.test.ts +21 -24
- package/src/platforms/whatsapp/commands/chat.ts +2 -0
- package/src/platforms/whatsapp/commands/message.test.ts +22 -24
- package/src/platforms/whatsapp/commands/message.ts +3 -5
- package/src/platforms/whatsapp/commands/shared.ts +2 -5
- package/src/platforms/whatsapp/commands/whoami.test.ts +2 -2
- package/src/platforms/whatsapp/credential-manager.ts +2 -6
- package/src/platforms/whatsapp/ensure-auth.test.ts +1 -4
- package/src/platforms/whatsapp/ensure-auth.ts +14 -6
- package/src/platforms/whatsapp/index.ts +0 -2
- package/src/platforms/whatsappbot/client.test.ts +13 -7
- package/src/platforms/whatsappbot/client.ts +18 -4
- package/src/platforms/whatsappbot/commands/auth.ts +4 -1
- package/src/platforms/whatsappbot/commands/message.test.ts +12 -2
- package/src/platforms/whatsappbot/commands/message.ts +16 -3
- package/src/platforms/whatsappbot/commands/shared.ts +3 -1
- package/src/platforms/whatsappbot/commands/whoami.test.ts +1 -3
- package/src/platforms/whatsappbot/index.ts +0 -2
- package/src/shared/chromium/browsers.test.ts +274 -0
- package/src/shared/chromium/browsers.ts +86 -0
- package/src/shared/chromium/cookie-reader.test.ts +274 -0
- package/src/shared/chromium/cookie-reader.ts +111 -0
- package/src/shared/chromium/decryptor.test.ts +449 -0
- package/src/shared/chromium/decryptor.ts +227 -0
- package/src/shared/chromium/index.ts +11 -0
- package/src/shared/chromium/types.ts +11 -0
- package/src/shared/utils/derived-key-cache.ts +1 -1
- package/src/shared/utils/linux-keyring.ts +4 -4
- package/src/tui/adapters/kakaotalk-adapter.ts +6 -1
- package/src/tui/adapters/telegram-adapter.ts +1 -1
- package/src/tui/adapters/webex-adapter.ts +1 -1
- package/src/tui/app.ts +149 -59
- package/src/tui/utils.test.ts +144 -145
- package/src/tui/utils.ts +27 -29
- package/src/tui/views/channel-picker.ts +1 -1
- package/src/tui/views/workspace-picker.ts +1 -1
|
@@ -1,76 +1,39 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { homedir
|
|
2
|
+
import { pbkdf2Sync } from 'node:crypto'
|
|
3
|
+
import { existsSync } from 'node:fs'
|
|
4
|
+
import { homedir } from 'node:os'
|
|
5
5
|
import { join } from 'node:path'
|
|
6
6
|
|
|
7
|
+
import {
|
|
8
|
+
BROWSER_KEYCHAIN_VARIANTS,
|
|
9
|
+
CHROMIUM_BROWSERS,
|
|
10
|
+
ChromiumCookieDecryptor,
|
|
11
|
+
ChromiumCookieReader,
|
|
12
|
+
discoverBrowserProfileDirs,
|
|
13
|
+
findLocalStatePath,
|
|
14
|
+
getBrowserBasePath,
|
|
15
|
+
} from '@/shared/chromium'
|
|
16
|
+
import type { KeychainVariant } from '@/shared/chromium'
|
|
17
|
+
|
|
7
18
|
import type { ExtractedChannelToken } from './types'
|
|
8
19
|
|
|
9
20
|
type CookieRow = { name: string; value: string; encrypted_value: Uint8Array | Buffer }
|
|
10
21
|
|
|
11
|
-
|
|
12
|
-
name
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface KeychainVariant {
|
|
19
|
-
service: string
|
|
20
|
-
account: string
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const BROWSERS: BrowserConfig[] = [
|
|
24
|
-
{
|
|
25
|
-
name: 'Chrome',
|
|
26
|
-
darwin: join('Google', 'Chrome'),
|
|
27
|
-
linux: 'google-chrome',
|
|
28
|
-
win32: join('Google', 'Chrome', 'User Data'),
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
name: 'Chrome Canary',
|
|
32
|
-
darwin: join('Google', 'Chrome Canary'),
|
|
33
|
-
linux: 'google-chrome-unstable',
|
|
34
|
-
win32: join('Google', 'Chrome SxS', 'User Data'),
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
name: 'Edge',
|
|
38
|
-
darwin: 'Microsoft Edge',
|
|
39
|
-
linux: 'microsoft-edge',
|
|
40
|
-
win32: join('Microsoft', 'Edge', 'User Data'),
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
name: 'Arc',
|
|
44
|
-
darwin: join('Arc', 'User Data'),
|
|
45
|
-
linux: '',
|
|
46
|
-
win32: join('Arc', 'User Data'),
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
name: 'Brave',
|
|
50
|
-
darwin: join('BraveSoftware', 'Brave-Browser'),
|
|
51
|
-
linux: join('BraveSoftware', 'Brave-Browser'),
|
|
52
|
-
win32: join('BraveSoftware', 'Brave-Browser', 'User Data'),
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
name: 'Vivaldi',
|
|
56
|
-
darwin: 'Vivaldi',
|
|
57
|
-
linux: 'vivaldi',
|
|
58
|
-
win32: join('Vivaldi', 'User Data'),
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: 'Chromium',
|
|
62
|
-
darwin: 'Chromium',
|
|
63
|
-
linux: 'chromium',
|
|
64
|
-
win32: join('Chromium', 'User Data'),
|
|
65
|
-
},
|
|
66
|
-
]
|
|
22
|
+
const COOKIE_QUERY = `
|
|
23
|
+
SELECT name, value, encrypted_value FROM cookies
|
|
24
|
+
WHERE name IN ('x-account', 'ch-session-1', 'ch-session')
|
|
25
|
+
AND host_key LIKE '%.channel.io%'
|
|
26
|
+
`
|
|
67
27
|
|
|
68
28
|
export class ChannelTokenExtractor {
|
|
69
29
|
private platform: NodeJS.Platform
|
|
70
|
-
private
|
|
30
|
+
private decryptor: ChromiumCookieDecryptor
|
|
31
|
+
private cookieReader: ChromiumCookieReader
|
|
71
32
|
|
|
72
33
|
constructor(platform?: NodeJS.Platform) {
|
|
73
34
|
this.platform = platform ?? process.platform
|
|
35
|
+
this.cookieReader = new ChromiumCookieReader()
|
|
36
|
+
this.decryptor = new ChromiumCookieDecryptor({ platform: this.platform })
|
|
74
37
|
}
|
|
75
38
|
|
|
76
39
|
getAppDataDir(): string | null {
|
|
@@ -118,22 +81,14 @@ export class ChannelTokenExtractor {
|
|
|
118
81
|
}
|
|
119
82
|
}
|
|
120
83
|
|
|
121
|
-
private getLocalStatePath(): string | null {
|
|
122
|
-
const appDir = this.getAppDataDir()
|
|
123
|
-
if (!appDir) return null
|
|
124
|
-
const localStatePath = join(appDir, 'Local State')
|
|
125
|
-
return existsSync(localStatePath) ? localStatePath : null
|
|
126
|
-
}
|
|
127
|
-
|
|
128
84
|
getBrowserCookiesPaths(): string[] {
|
|
129
85
|
const paths: string[] = []
|
|
130
86
|
|
|
131
|
-
for (const browser of
|
|
132
|
-
const browserBase =
|
|
87
|
+
for (const browser of CHROMIUM_BROWSERS) {
|
|
88
|
+
const browserBase = getBrowserBasePath(browser, this.platform)
|
|
133
89
|
if (!browserBase) continue
|
|
134
90
|
|
|
135
|
-
const
|
|
136
|
-
for (const profileDir of profileDirs) {
|
|
91
|
+
for (const profileDir of discoverBrowserProfileDirs(browserBase)) {
|
|
137
92
|
paths.push(join(profileDir, 'Cookies'))
|
|
138
93
|
paths.push(join(profileDir, 'Network', 'Cookies'))
|
|
139
94
|
}
|
|
@@ -142,70 +97,8 @@ export class ChannelTokenExtractor {
|
|
|
142
97
|
return paths
|
|
143
98
|
}
|
|
144
99
|
|
|
145
|
-
private getBrowserBasePath(browser: BrowserConfig): string | null {
|
|
146
|
-
let relative: string
|
|
147
|
-
|
|
148
|
-
switch (this.platform) {
|
|
149
|
-
case 'darwin':
|
|
150
|
-
relative = browser.darwin
|
|
151
|
-
if (!relative) return null
|
|
152
|
-
return join(homedir(), 'Library', 'Application Support', relative)
|
|
153
|
-
case 'linux':
|
|
154
|
-
relative = browser.linux
|
|
155
|
-
if (!relative) return null
|
|
156
|
-
return join(homedir(), '.config', relative)
|
|
157
|
-
case 'win32':
|
|
158
|
-
relative = browser.win32
|
|
159
|
-
if (!relative) return null
|
|
160
|
-
return join(
|
|
161
|
-
process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local'),
|
|
162
|
-
relative,
|
|
163
|
-
)
|
|
164
|
-
default:
|
|
165
|
-
return null
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
private discoverProfileDirs(browserBase: string): string[] {
|
|
170
|
-
const dirs: string[] = []
|
|
171
|
-
|
|
172
|
-
dirs.push(join(browserBase, 'Default'))
|
|
173
|
-
|
|
174
|
-
if (!existsSync(browserBase)) return dirs
|
|
175
|
-
|
|
176
|
-
try {
|
|
177
|
-
const entries = readdirSync(browserBase, { withFileTypes: true })
|
|
178
|
-
for (const entry of entries) {
|
|
179
|
-
if (!entry.isDirectory()) continue
|
|
180
|
-
if (!/^Profile \d+$/i.test(entry.name)) continue
|
|
181
|
-
dirs.push(join(browserBase, entry.name))
|
|
182
|
-
}
|
|
183
|
-
} catch {}
|
|
184
|
-
|
|
185
|
-
return dirs
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
private findLocalStateForCookiePath(cookiePath: string): string | null {
|
|
189
|
-
const parts = cookiePath.split(/[/\\]/)
|
|
190
|
-
for (let levels = 2; levels <= 4; levels++) {
|
|
191
|
-
if (parts.length < levels) break
|
|
192
|
-
const base = parts.slice(0, parts.length - levels).join('/')
|
|
193
|
-
const candidate = join(base, 'Local State')
|
|
194
|
-
if (existsSync(candidate)) return candidate
|
|
195
|
-
}
|
|
196
|
-
return null
|
|
197
|
-
}
|
|
198
|
-
|
|
199
100
|
getKeychainVariants(): KeychainVariant[] {
|
|
200
|
-
return
|
|
201
|
-
{ service: 'Chrome Safe Storage', account: 'Chrome' },
|
|
202
|
-
{ service: 'Chrome Canary Safe Storage', account: 'Chrome Canary' },
|
|
203
|
-
{ service: 'Microsoft Edge Safe Storage', account: 'Microsoft Edge' },
|
|
204
|
-
{ service: 'Arc Safe Storage', account: 'Arc' },
|
|
205
|
-
{ service: 'Brave Safe Storage', account: 'Brave' },
|
|
206
|
-
{ service: 'Vivaldi Safe Storage', account: 'Vivaldi' },
|
|
207
|
-
{ service: 'Chromium Safe Storage', account: 'Chromium' },
|
|
208
|
-
]
|
|
101
|
+
return BROWSER_KEYCHAIN_VARIANTS
|
|
209
102
|
}
|
|
210
103
|
|
|
211
104
|
async extract(): Promise<ExtractedChannelToken[]> {
|
|
@@ -228,299 +121,154 @@ export class ChannelTokenExtractor {
|
|
|
228
121
|
return results
|
|
229
122
|
}
|
|
230
123
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const cookiePaths = this.getBrowserCookiesPaths()
|
|
234
|
-
|
|
235
|
-
for (const cookiePath of cookiePaths) {
|
|
236
|
-
if (!existsSync(cookiePath)) continue
|
|
237
|
-
const result = await this.extractFromBrowserCookiePath(cookiePath)
|
|
238
|
-
if (result) results.push(result)
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
return results
|
|
124
|
+
decryptDPAPI(encryptedBlob: Buffer): Buffer | null {
|
|
125
|
+
return this.decryptor.decryptDPAPI(encryptedBlob)
|
|
242
126
|
}
|
|
243
127
|
|
|
244
|
-
private
|
|
245
|
-
|
|
246
|
-
|
|
128
|
+
private execSecurityCommand(service: string, account: string): string | null {
|
|
129
|
+
try {
|
|
130
|
+
const safeService = service.replace(/"/g, '\\"')
|
|
131
|
+
const safeAccount = account.replace(/"/g, '\\"')
|
|
132
|
+
return (
|
|
133
|
+
execSync(`security find-generic-password -s "${safeService}" -a "${safeAccount}" -w 2>/dev/null`, {
|
|
134
|
+
encoding: 'utf8',
|
|
135
|
+
}).trim() || null
|
|
136
|
+
)
|
|
137
|
+
} catch {
|
|
247
138
|
return null
|
|
248
139
|
}
|
|
140
|
+
}
|
|
249
141
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
142
|
+
private decryptBrowserCookie(encrypted: Buffer, cookiePath: string): string | null {
|
|
143
|
+
const prefix = encrypted.length > 3 ? encrypted.subarray(0, 3).toString('utf8') : ''
|
|
144
|
+
|
|
145
|
+
if (prefix === 'v10' || prefix === 'v11') {
|
|
146
|
+
if (this.platform === 'darwin') {
|
|
147
|
+
for (const variant of BROWSER_KEYCHAIN_VARIANTS) {
|
|
148
|
+
const password = this.execSecurityCommand(variant.service, variant.account)
|
|
149
|
+
if (!password) continue
|
|
150
|
+
const key = pbkdf2Sync(password, 'saltysalt', 1003, 16, 'sha1')
|
|
151
|
+
const buf = this.decryptor.decryptAESCBCRaw(encrypted, key)
|
|
152
|
+
if (buf) return ChromiumCookieDecryptor.stripIntegrityHash(buf).toString('utf8')
|
|
153
|
+
}
|
|
154
|
+
return null
|
|
155
|
+
}
|
|
255
156
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
this.
|
|
259
|
-
|
|
157
|
+
if (this.platform === 'linux') {
|
|
158
|
+
const key = pbkdf2Sync('peanuts', 'saltysalt', 1, 16, 'sha1')
|
|
159
|
+
const buf = this.decryptor.decryptAESCBCRaw(encrypted, key)
|
|
160
|
+
if (buf) return ChromiumCookieDecryptor.stripIntegrityHash(buf).toString('utf8')
|
|
161
|
+
return null
|
|
162
|
+
}
|
|
260
163
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
if (existsSync(tempPath)) {
|
|
267
|
-
unlinkSync(tempPath)
|
|
268
|
-
}
|
|
269
|
-
} catch {
|
|
270
|
-
/* temp file cleanup failure is non-critical */
|
|
164
|
+
if (this.platform === 'win32') {
|
|
165
|
+
const localStatePath = findLocalStatePath(cookiePath) ?? undefined
|
|
166
|
+
const buf = this.decryptor.decryptWindowsCookieRaw(encrypted, localStatePath)
|
|
167
|
+
if (buf) return ChromiumCookieDecryptor.stripIntegrityHash(buf).toString('utf8')
|
|
168
|
+
return null
|
|
271
169
|
}
|
|
272
170
|
}
|
|
171
|
+
|
|
172
|
+
return null
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private getLocalStatePath(): string | null {
|
|
176
|
+
const appDir = this.getAppDataDir()
|
|
177
|
+
if (!appDir) return null
|
|
178
|
+
const localStatePath = join(appDir, 'Local State')
|
|
179
|
+
return existsSync(localStatePath) ? localStatePath : null
|
|
273
180
|
}
|
|
274
181
|
|
|
275
|
-
private async
|
|
182
|
+
private async extractAllFromBrowserPaths(): Promise<ExtractedChannelToken[]> {
|
|
183
|
+
const results: ExtractedChannelToken[] = []
|
|
276
184
|
const cookiePaths = this.getBrowserCookiesPaths()
|
|
277
185
|
|
|
278
186
|
for (const cookiePath of cookiePaths) {
|
|
279
187
|
if (!existsSync(cookiePath)) continue
|
|
280
|
-
|
|
281
188
|
const result = await this.extractFromBrowserCookiePath(cookiePath)
|
|
282
|
-
if (result)
|
|
189
|
+
if (result) results.push(result)
|
|
283
190
|
}
|
|
284
191
|
|
|
285
|
-
return
|
|
192
|
+
return results
|
|
286
193
|
}
|
|
287
194
|
|
|
288
|
-
private async
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
try {
|
|
292
|
-
copyFileSync(cookiePath, tempPath)
|
|
293
|
-
const rows = await this.queryCookieDB(tempPath)
|
|
294
|
-
|
|
295
|
-
const accountCookie = this.getBrowserCookieValue(rows, 'x-account', cookiePath)
|
|
296
|
-
const sessionCookie =
|
|
297
|
-
this.getBrowserCookieValue(rows, 'ch-session-1', cookiePath) ??
|
|
298
|
-
this.getBrowserCookieValue(rows, 'ch-session', cookiePath)
|
|
299
|
-
|
|
300
|
-
return accountCookie ? { accountCookie, sessionCookie } : null
|
|
301
|
-
} catch {
|
|
195
|
+
private async extractFromDesktopApp(): Promise<ExtractedChannelToken | null> {
|
|
196
|
+
const cookiesPath = this.getCookiesPath()
|
|
197
|
+
if (!cookiesPath) {
|
|
302
198
|
return null
|
|
303
|
-
} finally {
|
|
304
|
-
try {
|
|
305
|
-
if (existsSync(tempPath)) {
|
|
306
|
-
unlinkSync(tempPath)
|
|
307
|
-
}
|
|
308
|
-
} catch {
|
|
309
|
-
/* temp file cleanup failure is non-critical */
|
|
310
|
-
}
|
|
311
199
|
}
|
|
312
|
-
}
|
|
313
200
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
SELECT name, value, encrypted_value FROM cookies
|
|
317
|
-
WHERE name IN ('x-account', 'ch-session-1', 'ch-session')
|
|
318
|
-
AND host_key LIKE '%.channel.io%'
|
|
319
|
-
`
|
|
320
|
-
|
|
321
|
-
if (typeof globalThis.Bun !== 'undefined') {
|
|
322
|
-
return await (async () => {
|
|
323
|
-
const { Database } = await import('bun:sqlite')
|
|
324
|
-
const db = new Database(dbPath, { readonly: true })
|
|
325
|
-
const result = db.query(sql).all() as CookieRow[]
|
|
326
|
-
db.close()
|
|
327
|
-
return result
|
|
328
|
-
})()
|
|
329
|
-
}
|
|
201
|
+
const rows = await this.cookieReader.queryAll<CookieRow>(cookiesPath, COOKIE_QUERY)
|
|
202
|
+
if (rows.length === 0) return null
|
|
330
203
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const result = db.prepare(sql).all() as CookieRow[]
|
|
337
|
-
db.close()
|
|
338
|
-
return result
|
|
339
|
-
})()
|
|
340
|
-
}
|
|
204
|
+
const localStatePath = this.getLocalStatePath() ?? undefined
|
|
205
|
+
const accountCookie = this.getDesktopCookieValue(rows, 'x-account', localStatePath)
|
|
206
|
+
const sessionCookie =
|
|
207
|
+
this.getDesktopCookieValue(rows, 'ch-session-1', localStatePath) ??
|
|
208
|
+
this.getDesktopCookieValue(rows, 'ch-session', localStatePath)
|
|
341
209
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
if (!row) return undefined
|
|
210
|
+
return accountCookie ? { accountCookie, sessionCookie } : null
|
|
211
|
+
}
|
|
345
212
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
213
|
+
private async extractFromBrowserCookiePath(cookiePath: string): Promise<ExtractedChannelToken | null> {
|
|
214
|
+
const rows = await this.cookieReader.queryAll<CookieRow>(cookiePath, COOKIE_QUERY)
|
|
215
|
+
if (rows.length === 0) return null
|
|
349
216
|
|
|
350
|
-
const
|
|
351
|
-
|
|
217
|
+
const localStatePath = findLocalStatePath(cookiePath) ?? undefined
|
|
218
|
+
const accountCookie = this.getBrowserCookieValue(rows, 'x-account', localStatePath)
|
|
219
|
+
const sessionCookie =
|
|
220
|
+
this.getBrowserCookieValue(rows, 'ch-session-1', localStatePath) ??
|
|
221
|
+
this.getBrowserCookieValue(rows, 'ch-session', localStatePath)
|
|
352
222
|
|
|
353
|
-
return
|
|
223
|
+
return accountCookie ? { accountCookie, sessionCookie } : null
|
|
354
224
|
}
|
|
355
225
|
|
|
356
|
-
private
|
|
357
|
-
const row = rows.find((
|
|
226
|
+
private getDesktopCookieValue(rows: CookieRow[], name: string, localStatePath?: string): string | undefined {
|
|
227
|
+
const row = rows.find((candidate) => candidate.name === name)
|
|
358
228
|
if (!row) return undefined
|
|
359
229
|
|
|
360
230
|
if (row.value && row.value.length > 0) {
|
|
361
231
|
return row.value
|
|
362
232
|
}
|
|
363
233
|
|
|
364
|
-
const
|
|
365
|
-
if (
|
|
366
|
-
|
|
367
|
-
return this.decryptBrowserCookie(encrypted, dbPath) ?? undefined
|
|
368
|
-
}
|
|
234
|
+
const encryptedValue = Buffer.from(row.encrypted_value)
|
|
235
|
+
if (encryptedValue.length === 0) return undefined
|
|
369
236
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
return encryptedValue.toString('utf8')
|
|
237
|
+
if (this.platform === 'win32' && localStatePath && this.decryptor.isEncryptedValue(encryptedValue)) {
|
|
238
|
+
return this.decryptDesktopWindowsCookie(encryptedValue, localStatePath) ?? undefined
|
|
373
239
|
}
|
|
374
240
|
|
|
375
|
-
|
|
376
|
-
return this.decryptWindowsCookie(encryptedValue)
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
return null
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
private decryptBrowserCookie(encryptedValue: Buffer, dbPath: string): string | null {
|
|
383
|
-
if (!this.isEncryptedValue(encryptedValue)) {
|
|
384
|
-
return encryptedValue.toString('utf8')
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
if (this.platform === 'win32') {
|
|
388
|
-
const localStatePath = this.findLocalStateForCookiePath(dbPath)
|
|
389
|
-
return this.decryptWindowsCookie(encryptedValue, localStatePath ?? undefined)
|
|
390
|
-
} else if (this.platform === 'darwin') {
|
|
391
|
-
return this.decryptMacCookie(encryptedValue)
|
|
392
|
-
} else if (this.platform === 'linux') {
|
|
393
|
-
return this.decryptLinuxCookie(encryptedValue)
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
return null
|
|
241
|
+
return this.decryptor.decryptCookie(encryptedValue, localStatePath) ?? undefined
|
|
397
242
|
}
|
|
398
243
|
|
|
399
|
-
private
|
|
400
|
-
if (!value || value.length < 4) return false
|
|
401
|
-
const prefix = value.subarray(0, 3).toString('utf8')
|
|
402
|
-
return prefix === 'v10' || prefix === 'v11'
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
private decryptWindowsCookie(encryptedData: Buffer, localStatePath?: string): string | null {
|
|
244
|
+
private decryptDesktopWindowsCookie(encryptedData: Buffer, localStatePath: string): string | null {
|
|
406
245
|
try {
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
const localState = JSON.parse(readFileSync(statePath, 'utf8'))
|
|
246
|
+
const { readFileSync } = require('node:fs') as typeof import('node:fs')
|
|
247
|
+
const localState = JSON.parse(readFileSync(localStatePath, 'utf8'))
|
|
411
248
|
const encryptedKey = Buffer.from(localState.os_crypt.encrypted_key, 'base64')
|
|
412
|
-
|
|
413
249
|
const dpapiBlobKey = encryptedKey.subarray(5)
|
|
414
250
|
const masterKey = this.decryptDPAPI(dpapiBlobKey)
|
|
415
251
|
if (!masterKey) return null
|
|
416
|
-
|
|
417
|
-
return this.decryptAESGCM(encryptedData, masterKey)
|
|
252
|
+
return this.decryptor.decryptAESGCM(encryptedData, masterKey)
|
|
418
253
|
} catch {
|
|
419
254
|
return null
|
|
420
255
|
}
|
|
421
256
|
}
|
|
422
257
|
|
|
423
|
-
private
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if (decrypted) return decrypted
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
for (const variant of this.getKeychainVariants()) {
|
|
430
|
-
const password = this.execSecurityCommand(variant.service, variant.account)
|
|
431
|
-
if (!password) continue
|
|
432
|
-
|
|
433
|
-
const key = pbkdf2Sync(password, 'saltysalt', 1003, 16, 'sha1')
|
|
434
|
-
const decrypted = this.decryptAESCBC(encryptedData, key)
|
|
435
|
-
if (decrypted) {
|
|
436
|
-
this.cachedKey = key
|
|
437
|
-
return decrypted
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
return null
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
private decryptLinuxCookie(encryptedData: Buffer): string | null {
|
|
445
|
-
const key = pbkdf2Sync('peanuts', 'saltysalt', 1, 16, 'sha1')
|
|
446
|
-
return this.decryptAESCBC(encryptedData, key)
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
private execSecurityCommand(service: string, account: string): string | null {
|
|
450
|
-
try {
|
|
451
|
-
const safeService = service.replace(/"/g, '\\"')
|
|
452
|
-
const safeAccount = account.replace(/"/g, '\\"')
|
|
453
|
-
const result = execSync(
|
|
454
|
-
`security find-generic-password -s "${safeService}" -a "${safeAccount}" -w 2>/dev/null`,
|
|
455
|
-
{ encoding: 'utf8' },
|
|
456
|
-
)
|
|
457
|
-
return result.trim() || null
|
|
458
|
-
} catch {
|
|
459
|
-
return null
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
private decryptAESCBC(encryptedData: Buffer, key: Buffer): string | null {
|
|
464
|
-
try {
|
|
465
|
-
const ciphertext = encryptedData.subarray(3)
|
|
466
|
-
const iv = Buffer.alloc(16, 0x20)
|
|
467
|
-
|
|
468
|
-
const decipher = createDecipheriv('aes-128-cbc', key, iv)
|
|
469
|
-
decipher.setAutoPadding(true)
|
|
470
|
-
|
|
471
|
-
const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])
|
|
472
|
-
|
|
473
|
-
// Chromium v130+ integrity hash: 32-byte non-printable prefix
|
|
474
|
-
if (decrypted.length > 32) {
|
|
475
|
-
const hasNonPrintablePrefix = decrypted.subarray(0, 32).some((b) => b < 0x20 || b > 0x7e)
|
|
476
|
-
if (hasNonPrintablePrefix) {
|
|
477
|
-
return decrypted.subarray(32).toString('utf8')
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
return decrypted.toString('utf8')
|
|
482
|
-
} catch {
|
|
483
|
-
return null
|
|
484
|
-
}
|
|
485
|
-
}
|
|
258
|
+
private getBrowserCookieValue(rows: CookieRow[], name: string, localStatePath?: string): string | undefined {
|
|
259
|
+
const row = rows.find((candidate) => candidate.name === name)
|
|
260
|
+
if (!row) return undefined
|
|
486
261
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
try {
|
|
490
|
-
const b64 = encryptedBlob.toString('base64')
|
|
491
|
-
const psScript = [
|
|
492
|
-
'Add-Type -AssemblyName System.Security',
|
|
493
|
-
`$bytes = [Convert]::FromBase64String('${b64}')`,
|
|
494
|
-
'$decrypted = [Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, [Security.Cryptography.DataProtectionScope]::CurrentUser)',
|
|
495
|
-
'[Convert]::ToBase64String($decrypted)',
|
|
496
|
-
].join('; ')
|
|
497
|
-
|
|
498
|
-
const result = execSync(`powershell -NoProfile -NonInteractive -Command "${psScript}"`, {
|
|
499
|
-
encoding: 'utf8',
|
|
500
|
-
timeout: 10000,
|
|
501
|
-
})
|
|
502
|
-
return Buffer.from(result.trim(), 'base64')
|
|
503
|
-
} catch {
|
|
504
|
-
return null
|
|
262
|
+
if (row.value && row.value.length > 0) {
|
|
263
|
+
return row.value
|
|
505
264
|
}
|
|
506
|
-
}
|
|
507
265
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
// Format: v10 (3 bytes) + IV (12 bytes) + ciphertext + auth tag (16 bytes)
|
|
511
|
-
if (encryptedData.length < 3 + 12 + 16) return null
|
|
512
|
-
|
|
513
|
-
const iv = encryptedData.subarray(3, 15)
|
|
514
|
-
const authTag = encryptedData.subarray(-16)
|
|
515
|
-
const ciphertext = encryptedData.subarray(15, -16)
|
|
266
|
+
const encryptedValue = Buffer.from(row.encrypted_value)
|
|
267
|
+
if (encryptedValue.length === 0) return undefined
|
|
516
268
|
|
|
517
|
-
|
|
518
|
-
|
|
269
|
+
const buf = this.decryptor.decryptCookieRaw(encryptedValue, localStatePath)
|
|
270
|
+
if (!buf) return undefined
|
|
519
271
|
|
|
520
|
-
|
|
521
|
-
return decrypted.toString('utf8')
|
|
522
|
-
} catch {
|
|
523
|
-
return null
|
|
524
|
-
}
|
|
272
|
+
return ChromiumCookieDecryptor.stripIntegrityHash(buf).toString('utf8')
|
|
525
273
|
}
|
|
526
274
|
}
|
|
@@ -141,9 +141,7 @@ describe('ChannelBotClient', () => {
|
|
|
141
141
|
})
|
|
142
142
|
|
|
143
143
|
test('wrapTextInBlocks returns a single text block with value', () => {
|
|
144
|
-
expect(ChannelBotClient.wrapTextInBlocks('Hello world')).toEqual([
|
|
145
|
-
{ type: 'text', value: 'Hello world' },
|
|
146
|
-
])
|
|
144
|
+
expect(ChannelBotClient.wrapTextInBlocks('Hello world')).toEqual([{ type: 'text', value: 'Hello world' }])
|
|
147
145
|
})
|
|
148
146
|
|
|
149
147
|
test('sendUserChatMessage includes botName in query string', async () => {
|