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
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
import { Command } from 'commander'
|
|
4
4
|
|
|
5
5
|
import pkg from '../../../package.json' with { type: 'json' }
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
authCommand,
|
|
8
|
+
channelCommand,
|
|
9
|
+
messageCommand,
|
|
10
|
+
reactionCommand,
|
|
11
|
+
userCommand,
|
|
12
|
+
whoamiCommand,
|
|
13
|
+
} from './commands/index'
|
|
7
14
|
|
|
8
15
|
const program = new Command()
|
|
9
16
|
|
|
@@ -17,7 +17,9 @@ const mockTestAuth = mock(() =>
|
|
|
17
17
|
|
|
18
18
|
mock.module('../client', () => ({
|
|
19
19
|
SlackBotClient: class MockSlackBotClient {
|
|
20
|
-
async login(_credentials?: any) {
|
|
20
|
+
async login(_credentials?: any) {
|
|
21
|
+
return this
|
|
22
|
+
}
|
|
21
23
|
testAuth = mockTestAuth
|
|
22
24
|
},
|
|
23
25
|
}))
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises'
|
|
2
2
|
import { basename } from 'node:path'
|
|
3
3
|
|
|
4
|
+
import { TeamsCredentialManager } from './credential-manager'
|
|
4
5
|
import type { TeamsChannel, TeamsFile, TeamsMessage, TeamsTeam, TeamsUser } from './types'
|
|
5
6
|
import { TeamsError } from './types'
|
|
6
|
-
import { TeamsCredentialManager } from './credential-manager'
|
|
7
7
|
|
|
8
8
|
interface RateLimitBucket {
|
|
9
9
|
remaining: number
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { afterEach, beforeEach, expect, spyOn, test } from 'bun:test'
|
|
2
2
|
|
|
3
|
-
import { getNoTeamsTokenFoundMessage } from './auth'
|
|
4
3
|
import { TeamsClient } from '../client'
|
|
5
4
|
import { TeamsCredentialManager } from '../credential-manager'
|
|
6
5
|
import { TeamsTokenExtractor } from '../token-extractor'
|
|
6
|
+
import { getNoTeamsTokenFoundMessage } from './auth'
|
|
7
7
|
|
|
8
8
|
let extractorExtractSpy: ReturnType<typeof spyOn>
|
|
9
9
|
let clientTestAuthSpy: ReturnType<typeof spyOn>
|
|
@@ -292,7 +292,10 @@ export async function statusAction(options: { pretty?: boolean }): Promise<void>
|
|
|
292
292
|
|
|
293
293
|
if (!isExpired) {
|
|
294
294
|
try {
|
|
295
|
-
const client = await new TeamsClient().login({
|
|
295
|
+
const client = await new TeamsClient().login({
|
|
296
|
+
token: account.token,
|
|
297
|
+
tokenExpiresAt: account.token_expires_at ?? undefined,
|
|
298
|
+
})
|
|
296
299
|
const authInfo = await client.testAuth()
|
|
297
300
|
displayName = authInfo.displayName
|
|
298
301
|
valid = true
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { afterEach, beforeEach, expect, spyOn, test } from 'bun:test'
|
|
2
2
|
|
|
3
3
|
import { TeamsClient } from '@/platforms/teams/client'
|
|
4
|
-
import { TeamsCredentialManager } from '@/platforms/teams/credential-manager'
|
|
5
4
|
import { whoamiAction, whoamiCommand } from '@/platforms/teams/commands/whoami'
|
|
5
|
+
import { TeamsCredentialManager } from '@/platforms/teams/credential-manager'
|
|
6
6
|
|
|
7
7
|
let credManagerSpy: ReturnType<typeof spyOn>
|
|
8
8
|
let clientTestAuthSpy: ReturnType<typeof spyOn>
|
|
@@ -76,8 +76,6 @@ test('whoami exits with error when not authenticated', async () => {
|
|
|
76
76
|
|
|
77
77
|
await whoamiAction({})
|
|
78
78
|
|
|
79
|
-
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
80
|
-
JSON.stringify({ error: 'Not authenticated. Run "auth extract" first.' }),
|
|
81
|
-
)
|
|
79
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(JSON.stringify({ error: 'Not authenticated. Run "auth extract" first.' }))
|
|
82
80
|
expect(processExitSpy).toHaveBeenCalledWith(1)
|
|
83
81
|
})
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { createRequire } from 'node:module'
|
|
5
|
-
import { homedir, tmpdir } from 'node:os'
|
|
2
|
+
import { existsSync } from 'node:fs'
|
|
3
|
+
import { homedir } from 'node:os'
|
|
6
4
|
import { join } from 'node:path'
|
|
7
5
|
|
|
6
|
+
import {
|
|
7
|
+
BROWSER_KEYCHAIN_VARIANTS,
|
|
8
|
+
CHROMIUM_BROWSERS,
|
|
9
|
+
ChromiumCookieDecryptor,
|
|
10
|
+
ChromiumCookieReader,
|
|
11
|
+
discoverBrowserProfileDirs,
|
|
12
|
+
findLocalStatePath,
|
|
13
|
+
getBrowserBasePath,
|
|
14
|
+
} from '@/shared/chromium'
|
|
15
|
+
import type { KeychainVariant } from '@/shared/chromium'
|
|
8
16
|
import { DerivedKeyCache } from '@/shared/utils/derived-key-cache'
|
|
9
17
|
|
|
10
18
|
import type { TeamsAccountType } from './types'
|
|
11
19
|
|
|
12
|
-
const require = createRequire(import.meta.url)
|
|
13
|
-
|
|
14
20
|
export interface ExtractedTeamsToken {
|
|
15
21
|
token: string
|
|
16
22
|
accountType: TeamsAccountType
|
|
@@ -21,18 +27,6 @@ interface TeamsCookiePath {
|
|
|
21
27
|
accountType: TeamsAccountType
|
|
22
28
|
}
|
|
23
29
|
|
|
24
|
-
interface KeychainVariant {
|
|
25
|
-
service: string
|
|
26
|
-
account: string
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface BrowserConfig {
|
|
30
|
-
name: string
|
|
31
|
-
darwin: string
|
|
32
|
-
linux: string
|
|
33
|
-
win32: string
|
|
34
|
-
}
|
|
35
|
-
|
|
36
30
|
const TEAMS_PROCESS_NAMES: Record<string, string> = {
|
|
37
31
|
darwin: 'Microsoft Teams',
|
|
38
32
|
win32: 'Teams.exe',
|
|
@@ -48,59 +42,31 @@ const TEAMS_HOST_PATTERNS = [
|
|
|
48
42
|
'.microsoft.com',
|
|
49
43
|
]
|
|
50
44
|
|
|
51
|
-
const
|
|
52
|
-
{
|
|
53
|
-
name: 'Chrome',
|
|
54
|
-
darwin: join('Google', 'Chrome'),
|
|
55
|
-
linux: 'google-chrome',
|
|
56
|
-
win32: join('Google', 'Chrome', 'User Data'),
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
name: 'Chrome Canary',
|
|
60
|
-
darwin: join('Google', 'Chrome Canary'),
|
|
61
|
-
linux: 'google-chrome-unstable',
|
|
62
|
-
win32: join('Google', 'Chrome SxS', 'User Data'),
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
name: 'Edge',
|
|
66
|
-
darwin: 'Microsoft Edge',
|
|
67
|
-
linux: 'microsoft-edge',
|
|
68
|
-
win32: join('Microsoft', 'Edge', 'User Data'),
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: 'Arc',
|
|
72
|
-
darwin: join('Arc', 'User Data'),
|
|
73
|
-
linux: '',
|
|
74
|
-
win32: join('Arc', 'User Data'),
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
name: 'Brave',
|
|
78
|
-
darwin: join('BraveSoftware', 'Brave-Browser'),
|
|
79
|
-
linux: join('BraveSoftware', 'Brave-Browser'),
|
|
80
|
-
win32: join('BraveSoftware', 'Brave-Browser', 'User Data'),
|
|
81
|
-
},
|
|
45
|
+
const TEAMS_KEYCHAIN_VARIANTS: KeychainVariant[] = [
|
|
46
|
+
{ service: 'Microsoft Teams Safe Storage', account: 'Microsoft Teams' },
|
|
82
47
|
{
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
linux: 'vivaldi',
|
|
86
|
-
win32: join('Vivaldi', 'User Data'),
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
name: 'Chromium',
|
|
90
|
-
darwin: 'Chromium',
|
|
91
|
-
linux: 'chromium',
|
|
92
|
-
win32: join('Chromium', 'User Data'),
|
|
48
|
+
service: 'Microsoft Teams (work or school) Safe Storage',
|
|
49
|
+
account: 'Microsoft Teams (work or school)',
|
|
93
50
|
},
|
|
51
|
+
{ service: 'Teams Safe Storage', account: 'Teams' },
|
|
94
52
|
]
|
|
95
53
|
|
|
96
54
|
export class TeamsTokenExtractor {
|
|
97
55
|
private platform: NodeJS.Platform
|
|
98
|
-
private
|
|
99
|
-
private
|
|
56
|
+
private decryptor: ChromiumCookieDecryptor
|
|
57
|
+
private cookieReader: ChromiumCookieReader
|
|
100
58
|
|
|
101
59
|
constructor(platform?: NodeJS.Platform, keyCache?: DerivedKeyCache) {
|
|
102
60
|
this.platform = platform ?? process.platform
|
|
103
|
-
|
|
61
|
+
|
|
62
|
+
const resolvedKeyCache = keyCache ?? new DerivedKeyCache()
|
|
63
|
+
this.decryptor = new ChromiumCookieDecryptor({
|
|
64
|
+
platform: this.platform,
|
|
65
|
+
appKeychainVariants: TEAMS_KEYCHAIN_VARIANTS,
|
|
66
|
+
keyCache: resolvedKeyCache,
|
|
67
|
+
keyCachePlatform: 'teams',
|
|
68
|
+
})
|
|
69
|
+
this.cookieReader = new ChromiumCookieReader()
|
|
104
70
|
}
|
|
105
71
|
|
|
106
72
|
getDesktopCookiesPaths(): TeamsCookiePath[] {
|
|
@@ -162,12 +128,11 @@ export class TeamsTokenExtractor {
|
|
|
162
128
|
getBrowserCookiesPaths(): TeamsCookiePath[] {
|
|
163
129
|
const paths: TeamsCookiePath[] = []
|
|
164
130
|
|
|
165
|
-
for (const browser of
|
|
166
|
-
const browserBase =
|
|
131
|
+
for (const browser of CHROMIUM_BROWSERS) {
|
|
132
|
+
const browserBase = getBrowserBasePath(browser, this.platform)
|
|
167
133
|
if (!browserBase) continue
|
|
168
134
|
|
|
169
|
-
const
|
|
170
|
-
for (const profileDir of profileDirs) {
|
|
135
|
+
for (const profileDir of discoverBrowserProfileDirs(browserBase)) {
|
|
171
136
|
paths.push({ path: join(profileDir, 'Cookies'), accountType: 'work' })
|
|
172
137
|
paths.push({ path: join(profileDir, 'Network', 'Cookies'), accountType: 'work' })
|
|
173
138
|
}
|
|
@@ -177,63 +142,7 @@ export class TeamsTokenExtractor {
|
|
|
177
142
|
}
|
|
178
143
|
|
|
179
144
|
getTeamsCookiesPaths(): TeamsCookiePath[] {
|
|
180
|
-
|
|
181
|
-
const browserPaths = this.getBrowserCookiesPaths()
|
|
182
|
-
return [...desktopPaths, ...browserPaths]
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
private getBrowserBasePath(browser: BrowserConfig): string | null {
|
|
186
|
-
let relative: string
|
|
187
|
-
|
|
188
|
-
switch (this.platform) {
|
|
189
|
-
case 'darwin':
|
|
190
|
-
relative = browser.darwin
|
|
191
|
-
if (!relative) return null
|
|
192
|
-
return join(homedir(), 'Library', 'Application Support', relative)
|
|
193
|
-
case 'linux':
|
|
194
|
-
relative = browser.linux
|
|
195
|
-
if (!relative) return null
|
|
196
|
-
return join(homedir(), '.config', relative)
|
|
197
|
-
case 'win32':
|
|
198
|
-
relative = browser.win32
|
|
199
|
-
if (!relative) return null
|
|
200
|
-
return join(
|
|
201
|
-
process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local'),
|
|
202
|
-
relative,
|
|
203
|
-
)
|
|
204
|
-
default:
|
|
205
|
-
return null
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
private discoverProfileDirs(browserBase: string): string[] {
|
|
210
|
-
const dirs: string[] = []
|
|
211
|
-
|
|
212
|
-
dirs.push(join(browserBase, 'Default'))
|
|
213
|
-
|
|
214
|
-
if (!existsSync(browserBase)) return dirs
|
|
215
|
-
|
|
216
|
-
try {
|
|
217
|
-
const entries = readdirSync(browserBase, { withFileTypes: true })
|
|
218
|
-
for (const entry of entries) {
|
|
219
|
-
if (!entry.isDirectory()) continue
|
|
220
|
-
if (!/^Profile \d+$/i.test(entry.name)) continue
|
|
221
|
-
dirs.push(join(browserBase, entry.name))
|
|
222
|
-
}
|
|
223
|
-
} catch {}
|
|
224
|
-
|
|
225
|
-
return dirs
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
private findLocalStateForCookiePath(cookiePath: string): string | null {
|
|
229
|
-
const parts = cookiePath.split(/[/\\]/)
|
|
230
|
-
for (let levels = 2; levels <= 4; levels++) {
|
|
231
|
-
if (parts.length < levels) break
|
|
232
|
-
const base = parts.slice(0, parts.length - levels).join('/')
|
|
233
|
-
const candidate = join(base, 'Local State')
|
|
234
|
-
if (existsSync(candidate)) return candidate
|
|
235
|
-
}
|
|
236
|
-
return null
|
|
145
|
+
return [...this.getDesktopCookiesPaths(), ...this.getBrowserCookiesPaths()]
|
|
237
146
|
}
|
|
238
147
|
|
|
239
148
|
getLocalStatePath(): string {
|
|
@@ -264,65 +173,33 @@ export class TeamsTokenExtractor {
|
|
|
264
173
|
}
|
|
265
174
|
|
|
266
175
|
getKeychainVariants(): KeychainVariant[] {
|
|
267
|
-
return [
|
|
268
|
-
// Teams-specific keychain entries
|
|
269
|
-
{ service: 'Microsoft Teams Safe Storage', account: 'Microsoft Teams' },
|
|
270
|
-
{
|
|
271
|
-
service: 'Microsoft Teams (work or school) Safe Storage',
|
|
272
|
-
account: 'Microsoft Teams (work or school)',
|
|
273
|
-
},
|
|
274
|
-
{ service: 'Microsoft Edge Safe Storage', account: 'Microsoft Edge' },
|
|
275
|
-
{ service: 'Teams Safe Storage', account: 'Teams' },
|
|
276
|
-
// Browser keychain entries for fallback
|
|
277
|
-
{ service: 'Chrome Safe Storage', account: 'Chrome' },
|
|
278
|
-
{ service: 'Chrome Canary Safe Storage', account: 'Chrome Canary' },
|
|
279
|
-
{ service: 'Arc Safe Storage', account: 'Arc' },
|
|
280
|
-
{ service: 'Brave Safe Storage', account: 'Brave' },
|
|
281
|
-
{ service: 'Vivaldi Safe Storage', account: 'Vivaldi' },
|
|
282
|
-
{ service: 'Chromium Safe Storage', account: 'Chromium' },
|
|
283
|
-
]
|
|
176
|
+
return [...TEAMS_KEYCHAIN_VARIANTS, ...BROWSER_KEYCHAIN_VARIANTS]
|
|
284
177
|
}
|
|
285
178
|
|
|
286
179
|
isValidSkypeToken(token: string): boolean {
|
|
287
180
|
if (!token || token.length === 0) return false
|
|
288
|
-
// Skype tokens are typically JWT format or long base64 strings (50+ chars)
|
|
289
181
|
return token.length >= 50
|
|
290
182
|
}
|
|
291
183
|
|
|
292
184
|
isEncryptedValue(value: Buffer): boolean {
|
|
293
|
-
|
|
294
|
-
const prefix = value.subarray(0, 3).toString('utf8')
|
|
295
|
-
return prefix === 'v10' || prefix === 'v11'
|
|
185
|
+
return this.decryptor.isEncryptedValue(value)
|
|
296
186
|
}
|
|
297
187
|
|
|
298
188
|
async extract(): Promise<ExtractedTeamsToken[]> {
|
|
299
|
-
await this.loadCachedKey()
|
|
189
|
+
await this.decryptor.loadCachedKey()
|
|
300
190
|
return this.extractFromCookiesDB()
|
|
301
191
|
}
|
|
302
192
|
|
|
303
|
-
private async loadCachedKey(): Promise<void> {
|
|
304
|
-
if (this.platform !== 'darwin') return
|
|
305
|
-
|
|
306
|
-
const cached = await this.keyCache.get('teams')
|
|
307
|
-
if (cached) {
|
|
308
|
-
this.cachedKey = cached
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
193
|
async clearKeyCache(): Promise<void> {
|
|
313
|
-
await this.
|
|
314
|
-
this.cachedKey = null
|
|
194
|
+
await this.decryptor.clearKeyCache()
|
|
315
195
|
}
|
|
316
196
|
|
|
317
197
|
private async extractFromCookiesDB(): Promise<ExtractedTeamsToken[]> {
|
|
318
|
-
const cookiePaths = this.getTeamsCookiesPaths()
|
|
319
198
|
const results: ExtractedTeamsToken[] = []
|
|
320
199
|
const seenAccountTypes = new Set<TeamsAccountType>()
|
|
321
200
|
|
|
322
|
-
for (const { path: dbPath, accountType } of
|
|
323
|
-
if (!dbPath || !existsSync(dbPath)) continue
|
|
324
|
-
// Skip fallback paths if we already have a token for this account type
|
|
325
|
-
if (seenAccountTypes.has(accountType)) continue
|
|
201
|
+
for (const { path: dbPath, accountType } of this.getTeamsCookiesPaths()) {
|
|
202
|
+
if (!dbPath || !existsSync(dbPath) || seenAccountTypes.has(accountType)) continue
|
|
326
203
|
|
|
327
204
|
const token = await this.copyAndExtract(dbPath)
|
|
328
205
|
if (token && this.isValidSkypeToken(token)) {
|
|
@@ -335,37 +212,18 @@ export class TeamsTokenExtractor {
|
|
|
335
212
|
}
|
|
336
213
|
|
|
337
214
|
private async copyAndExtract(dbPath: string): Promise<string | null> {
|
|
338
|
-
|
|
215
|
+
let tempPath = dbPath
|
|
339
216
|
|
|
340
217
|
try {
|
|
341
|
-
this.copyDatabaseToTemp(dbPath,
|
|
342
|
-
// For Windows: find the Local State relative to the cookie path so browser cookies
|
|
343
|
-
// use the browser's own Local State instead of the Teams app Local State.
|
|
218
|
+
tempPath = this.copyDatabaseToTemp(dbPath, dbPath)
|
|
344
219
|
const localStatePath =
|
|
345
|
-
this.platform === 'win32'
|
|
346
|
-
? (this.findLocalStateForCookiePath(dbPath) ?? this.getLocalStatePath())
|
|
347
|
-
: undefined
|
|
348
|
-
const token = await this.extractFromSQLite(tempPath, localStatePath)
|
|
349
|
-
this.cleanupTempFile(tempPath)
|
|
350
|
-
return token
|
|
351
|
-
} catch {
|
|
352
|
-
this.cleanupTempFile(tempPath)
|
|
353
|
-
return null
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
private copyDatabaseToTemp(sourcePath: string, destPath: string): string {
|
|
358
|
-
copyFileSync(sourcePath, destPath)
|
|
359
|
-
return destPath
|
|
360
|
-
}
|
|
220
|
+
this.platform === 'win32' ? (findLocalStatePath(dbPath) ?? this.getLocalStatePath()) : undefined
|
|
361
221
|
|
|
362
|
-
|
|
363
|
-
try {
|
|
364
|
-
if (existsSync(tempPath)) {
|
|
365
|
-
unlinkSync(tempPath)
|
|
366
|
-
}
|
|
222
|
+
return await this.extractFromSQLite(tempPath, localStatePath)
|
|
367
223
|
} catch {
|
|
368
|
-
|
|
224
|
+
return null
|
|
225
|
+
} finally {
|
|
226
|
+
this.cleanupTempFile(tempPath)
|
|
369
227
|
}
|
|
370
228
|
}
|
|
371
229
|
|
|
@@ -382,25 +240,14 @@ export class TeamsTokenExtractor {
|
|
|
382
240
|
|
|
383
241
|
type CookieRow = { encrypted_value?: Uint8Array | Buffer } | null
|
|
384
242
|
|
|
385
|
-
|
|
386
|
-
if (
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
const db = new Database(dbPath, { readonly: true })
|
|
394
|
-
row = db.prepare(sql).get() as CookieRow
|
|
395
|
-
db.close()
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
if (row?.encrypted_value) {
|
|
399
|
-
const decrypted = this.decryptCookie(Buffer.from(row.encrypted_value), localStatePath)
|
|
400
|
-
if (decrypted && this.isValidSkypeToken(decrypted)) {
|
|
401
|
-
return decrypted
|
|
402
|
-
}
|
|
403
|
-
}
|
|
243
|
+
const row = await this.cookieReader.queryFirst<CookieRow>(dbPath, sql)
|
|
244
|
+
if (!row?.encrypted_value) continue
|
|
245
|
+
|
|
246
|
+
const decryptedBuf = this.decryptor.decryptCookieRaw(Buffer.from(row.encrypted_value), localStatePath)
|
|
247
|
+
if (!decryptedBuf) continue
|
|
248
|
+
|
|
249
|
+
const token = this.postProcessDecrypted(decryptedBuf)
|
|
250
|
+
if (this.isValidSkypeToken(token)) return token
|
|
404
251
|
}
|
|
405
252
|
|
|
406
253
|
return null
|
|
@@ -409,85 +256,33 @@ export class TeamsTokenExtractor {
|
|
|
409
256
|
}
|
|
410
257
|
}
|
|
411
258
|
|
|
412
|
-
private
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
return encryptedValue.toString('utf8')
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
if (this.platform === 'win32') {
|
|
419
|
-
return this.decryptWindowsCookie(encryptedValue, localStatePath)
|
|
420
|
-
} else if (this.platform === 'darwin') {
|
|
421
|
-
return this.decryptMacCookie(encryptedValue)
|
|
422
|
-
} else if (this.platform === 'linux') {
|
|
423
|
-
return this.decryptLinuxCookie(encryptedValue)
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
return null
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
private decryptWindowsCookie(encryptedData: Buffer, localStatePath?: string): string | null {
|
|
430
|
-
try {
|
|
431
|
-
const statePath = localStatePath ?? this.getLocalStatePath()
|
|
432
|
-
if (!existsSync(statePath)) return null
|
|
259
|
+
private postProcessDecrypted(raw: Buffer): string {
|
|
260
|
+
const stripped = ChromiumCookieDecryptor.stripIntegrityHash(raw)
|
|
261
|
+
if (stripped !== raw) return stripped.toString('utf8')
|
|
433
262
|
|
|
434
|
-
|
|
435
|
-
const encryptedKey = Buffer.from(localState.os_crypt.encrypted_key, 'base64')
|
|
263
|
+
const str = raw.toString('utf8')
|
|
436
264
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
const masterKey = this.decryptDPAPI(dpapiBlobKey)
|
|
440
|
-
if (!masterKey) return null
|
|
265
|
+
const jwtStart = str.indexOf('eyJ')
|
|
266
|
+
if (jwtStart > 0 && jwtStart <= 32) return str.substring(jwtStart)
|
|
441
267
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
268
|
+
if (str.length > 32) {
|
|
269
|
+
const possibleToken = str.substring(32)
|
|
270
|
+
if (possibleToken.length > 50 && /^[A-Za-z0-9._-]+$/.test(possibleToken.substring(0, 50))) {
|
|
271
|
+
return possibleToken
|
|
272
|
+
}
|
|
445
273
|
}
|
|
446
|
-
}
|
|
447
274
|
|
|
448
|
-
|
|
449
|
-
try {
|
|
450
|
-
const b64 = encryptedBlob.toString('base64')
|
|
451
|
-
const psScript = `
|
|
452
|
-
Add-Type -AssemblyName System.Security
|
|
453
|
-
$bytes = [Convert]::FromBase64String('${b64}')
|
|
454
|
-
$decrypted = [Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, 'CurrentUser')
|
|
455
|
-
[Convert]::ToBase64String($decrypted)
|
|
456
|
-
`.replace(/\n/g, ' ')
|
|
457
|
-
|
|
458
|
-
const result = execSync(`powershell -Command "${psScript}"`, { encoding: 'utf8' })
|
|
459
|
-
return Buffer.from(result.trim(), 'base64')
|
|
460
|
-
} catch {
|
|
461
|
-
return null
|
|
462
|
-
}
|
|
275
|
+
return str
|
|
463
276
|
}
|
|
464
277
|
|
|
465
|
-
private
|
|
466
|
-
|
|
467
|
-
const decrypted = this.decryptAESCBC(encryptedData, this.cachedKey)
|
|
468
|
-
if (decrypted) return decrypted
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
for (const variant of this.getKeychainVariants()) {
|
|
472
|
-
const password = this.execSecurityCommand(variant.service, variant.account)
|
|
473
|
-
if (!password) continue
|
|
474
|
-
|
|
475
|
-
const key = pbkdf2Sync(password, 'saltysalt', 1003, 16, 'sha1')
|
|
476
|
-
const decrypted = this.decryptAESCBC(encryptedData, key)
|
|
477
|
-
if (decrypted) {
|
|
478
|
-
this.cachedKey = key
|
|
479
|
-
this.keyCache.set('teams', key).catch(() => {})
|
|
480
|
-
return decrypted
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
return null
|
|
278
|
+
private copyDatabaseToTemp(sourcePath: string, _destPath: string): string {
|
|
279
|
+
return sourcePath
|
|
485
280
|
}
|
|
486
281
|
|
|
487
|
-
private
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
return this.
|
|
282
|
+
private cleanupTempFile(_tempPath: string): void {}
|
|
283
|
+
|
|
284
|
+
private decryptAESGCM(encryptedData: Buffer, key: Buffer): string | null {
|
|
285
|
+
return this.decryptor.decryptAESGCM(encryptedData, key)
|
|
491
286
|
}
|
|
492
287
|
|
|
493
288
|
private getKeychainPassword(): string | null {
|
|
@@ -495,88 +290,25 @@ export class TeamsTokenExtractor {
|
|
|
495
290
|
const password = this.execSecurityCommand(variant.service, variant.account)
|
|
496
291
|
if (password) return password
|
|
497
292
|
}
|
|
293
|
+
|
|
498
294
|
return null
|
|
499
295
|
}
|
|
500
296
|
|
|
501
297
|
private execSecurityCommand(service: string, account: string): string | null {
|
|
502
298
|
try {
|
|
503
|
-
// Escape double quotes in service/account to prevent command injection
|
|
504
299
|
const safeService = service.replace(/"/g, '\\"')
|
|
505
300
|
const safeAccount = account.replace(/"/g, '\\"')
|
|
506
|
-
const result = execSync(
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
)
|
|
510
|
-
return result.trim()
|
|
511
|
-
} catch {
|
|
512
|
-
return null
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
private decryptAESCBC(encryptedData: Buffer, key: Buffer): string | null {
|
|
517
|
-
try {
|
|
518
|
-
const ciphertext = encryptedData.subarray(3)
|
|
519
|
-
const iv = Buffer.alloc(16, 0x20)
|
|
520
|
-
|
|
521
|
-
const decipher = createDecipheriv('aes-128-cbc', key, iv)
|
|
522
|
-
decipher.setAutoPadding(true)
|
|
523
|
-
|
|
524
|
-
const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])
|
|
525
|
-
|
|
526
|
-
// Chromium v130+ prepends a 32-byte integrity hash before the actual cookie value.
|
|
527
|
-
// Detect by checking if the first bytes contain non-printable characters.
|
|
528
|
-
if (decrypted.length > 32) {
|
|
529
|
-
const hasNonPrintablePrefix = decrypted.subarray(0, 32).some((b) => b < 0x20 || b > 0x7e)
|
|
530
|
-
if (hasNonPrintablePrefix) {
|
|
531
|
-
return decrypted.subarray(32).toString('utf8')
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
const decryptedStr = decrypted.toString('utf8')
|
|
536
|
-
|
|
537
|
-
// Chromium v24+ prepends a 32-byte integrity hash before the actual value
|
|
538
|
-
// Look for JWT token start (eyJ) or other token patterns
|
|
539
|
-
const jwtStart = decryptedStr.indexOf('eyJ')
|
|
540
|
-
if (jwtStart > 0 && jwtStart <= 32) {
|
|
541
|
-
return decryptedStr.substring(jwtStart)
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
// If no JWT prefix found but decryption succeeded, check if first 32 bytes are garbage
|
|
545
|
-
if (decrypted.length > 32) {
|
|
546
|
-
const possibleToken = decryptedStr.substring(32)
|
|
547
|
-
if (possibleToken.length > 50 && /^[A-Za-z0-9._-]+$/.test(possibleToken.substring(0, 50))) {
|
|
548
|
-
return possibleToken
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
return decryptedStr
|
|
553
|
-
} catch {
|
|
554
|
-
return null
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
private decryptAESGCM(encryptedData: Buffer, key: Buffer): string | null {
|
|
559
|
-
try {
|
|
560
|
-
// Format: v10 (3 bytes) + IV (12 bytes) + ciphertext + auth tag (16 bytes)
|
|
561
|
-
if (encryptedData.length < 3 + 12 + 16) return null
|
|
562
|
-
|
|
563
|
-
const iv = encryptedData.subarray(3, 15)
|
|
564
|
-
const authTag = encryptedData.subarray(-16)
|
|
565
|
-
const ciphertext = encryptedData.subarray(15, -16)
|
|
566
|
-
|
|
567
|
-
const decipher = createDecipheriv('aes-256-gcm', key, iv)
|
|
568
|
-
decipher.setAuthTag(authTag)
|
|
569
|
-
|
|
570
|
-
const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])
|
|
571
|
-
return decrypted.toString('utf8')
|
|
301
|
+
const result = execSync(`security find-generic-password -s "${safeService}" -a "${safeAccount}" -w 2>/dev/null`, {
|
|
302
|
+
encoding: 'utf8',
|
|
303
|
+
})
|
|
304
|
+
return result.trim() || null
|
|
572
305
|
} catch {
|
|
573
306
|
return null
|
|
574
307
|
}
|
|
575
308
|
}
|
|
576
309
|
|
|
577
310
|
async isTeamsRunning(): Promise<boolean> {
|
|
578
|
-
|
|
579
|
-
return this.checkProcessRunning(processName)
|
|
311
|
+
return this.checkProcessRunning(this.getProcessName())
|
|
580
312
|
}
|
|
581
313
|
|
|
582
314
|
private getProcessName(): string {
|
|
@@ -590,12 +322,12 @@ export class TeamsTokenExtractor {
|
|
|
590
322
|
encoding: 'utf8',
|
|
591
323
|
})
|
|
592
324
|
return result.toLowerCase().includes(processName.toLowerCase())
|
|
593
|
-
} else {
|
|
594
|
-
const result = execSync(`pgrep -f "${processName}" 2>/dev/null || true`, {
|
|
595
|
-
encoding: 'utf8',
|
|
596
|
-
})
|
|
597
|
-
return result.trim().length > 0
|
|
598
325
|
}
|
|
326
|
+
|
|
327
|
+
const result = execSync(`pgrep -f "${processName}" 2>/dev/null || true`, {
|
|
328
|
+
encoding: 'utf8',
|
|
329
|
+
})
|
|
330
|
+
return result.trim().length > 0
|
|
599
331
|
} catch {
|
|
600
332
|
return false
|
|
601
333
|
}
|