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,9 +1,17 @@
|
|
|
1
1
|
import { execSync, spawn } from 'node:child_process'
|
|
2
|
-
import {
|
|
2
|
+
import { pbkdf2Sync } from 'node:crypto'
|
|
3
3
|
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
4
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
|
+
discoverBrowserProfileDirs,
|
|
12
|
+
getBrowserBasePath,
|
|
13
|
+
} from '@/shared/chromium'
|
|
14
|
+
import type { KeychainVariant } from '@/shared/chromium'
|
|
7
15
|
import { DerivedKeyCache } from '@/shared/utils/derived-key-cache'
|
|
8
16
|
import { lookupLinuxKeyringPassword } from '@/shared/utils/linux-keyring'
|
|
9
17
|
|
|
@@ -13,11 +21,6 @@ export interface ExtractedDiscordToken {
|
|
|
13
21
|
|
|
14
22
|
export type DiscordVariant = 'stable' | 'canary' | 'ptb'
|
|
15
23
|
|
|
16
|
-
interface KeychainVariant {
|
|
17
|
-
service: string
|
|
18
|
-
account: string
|
|
19
|
-
}
|
|
20
|
-
|
|
21
24
|
interface CDPTarget {
|
|
22
25
|
id: string
|
|
23
26
|
type: string
|
|
@@ -34,13 +37,6 @@ interface CDPMessage {
|
|
|
34
37
|
error?: { code: number; message: string }
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
interface BrowserConfig {
|
|
38
|
-
name: string
|
|
39
|
-
darwin: string
|
|
40
|
-
linux: string
|
|
41
|
-
win32: string
|
|
42
|
-
}
|
|
43
|
-
|
|
44
40
|
const TOKEN_REGEX = /[\w-]{24,}\.[\w-]{6}\.[\w-]{25,110}/
|
|
45
41
|
const MFA_TOKEN_REGEX = /mfa\.[\w-]{84}/
|
|
46
42
|
const ENCRYPTED_PREFIX = 'dQw4w9WgXcQ:'
|
|
@@ -62,49 +58,13 @@ const DISCORD_APP_PATHS: Record<DiscordVariant, { darwin: string }> = {
|
|
|
62
58
|
ptb: { darwin: '/Applications/Discord PTB.app/Contents/MacOS/Discord PTB' },
|
|
63
59
|
}
|
|
64
60
|
|
|
65
|
-
const
|
|
66
|
-
{
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
name: 'Chrome Canary',
|
|
74
|
-
darwin: join('Google', 'Chrome Canary'),
|
|
75
|
-
linux: 'google-chrome-unstable',
|
|
76
|
-
win32: join('Google', 'Chrome SxS', 'User Data'),
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
name: 'Edge',
|
|
80
|
-
darwin: 'Microsoft Edge',
|
|
81
|
-
linux: 'microsoft-edge',
|
|
82
|
-
win32: join('Microsoft', 'Edge', 'User Data'),
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
name: 'Arc',
|
|
86
|
-
darwin: join('Arc', 'User Data'),
|
|
87
|
-
linux: '',
|
|
88
|
-
win32: join('Arc', 'User Data'),
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
name: 'Brave',
|
|
92
|
-
darwin: join('BraveSoftware', 'Brave-Browser'),
|
|
93
|
-
linux: join('BraveSoftware', 'Brave-Browser'),
|
|
94
|
-
win32: join('BraveSoftware', 'Brave-Browser', 'User Data'),
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
name: 'Vivaldi',
|
|
98
|
-
darwin: 'Vivaldi',
|
|
99
|
-
linux: 'vivaldi',
|
|
100
|
-
win32: join('Vivaldi', 'User Data'),
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'Chromium',
|
|
104
|
-
darwin: 'Chromium',
|
|
105
|
-
linux: 'chromium',
|
|
106
|
-
win32: join('Chromium', 'User Data'),
|
|
107
|
-
},
|
|
61
|
+
const DISCORD_APP_KEYCHAIN_VARIANTS: KeychainVariant[] = [
|
|
62
|
+
{ service: 'discord Safe Storage', account: 'discord Key' },
|
|
63
|
+
{ service: 'discordcanary Safe Storage', account: 'discordcanary Key' },
|
|
64
|
+
{ service: 'discordptb Safe Storage', account: 'discordptb Key' },
|
|
65
|
+
{ service: 'Discord Safe Storage', account: 'Discord' },
|
|
66
|
+
{ service: 'Discord Canary Safe Storage', account: 'Discord Canary' },
|
|
67
|
+
{ service: 'Discord PTB Safe Storage', account: 'Discord PTB' },
|
|
108
68
|
]
|
|
109
69
|
|
|
110
70
|
export class DiscordTokenExtractor {
|
|
@@ -113,12 +73,20 @@ export class DiscordTokenExtractor {
|
|
|
113
73
|
private killWait: number
|
|
114
74
|
private keyCache: DerivedKeyCache
|
|
115
75
|
private cachedKey: Buffer | null = null
|
|
76
|
+
private decryptor: ChromiumCookieDecryptor
|
|
116
77
|
|
|
117
78
|
constructor(platform?: NodeJS.Platform, startupWait?: number, killWait?: number, keyCache?: DerivedKeyCache) {
|
|
118
79
|
this.platform = platform ?? process.platform
|
|
119
80
|
this.startupWait = startupWait ?? DISCORD_STARTUP_WAIT
|
|
120
81
|
this.killWait = killWait ?? 1000
|
|
121
82
|
this.keyCache = keyCache ?? new DerivedKeyCache()
|
|
83
|
+
this.decryptor = new ChromiumCookieDecryptor({
|
|
84
|
+
platform: this.platform,
|
|
85
|
+
appKeychainVariants: DISCORD_APP_KEYCHAIN_VARIANTS,
|
|
86
|
+
keyCache: this.keyCache,
|
|
87
|
+
keyCachePlatform: 'discord',
|
|
88
|
+
linuxKeyringAppNames: ['discord', 'Discord'],
|
|
89
|
+
})
|
|
122
90
|
}
|
|
123
91
|
|
|
124
92
|
getDiscordDirs(): string[] {
|
|
@@ -147,11 +115,11 @@ export class DiscordTokenExtractor {
|
|
|
147
115
|
getBrowserLevelDBDirs(): string[] {
|
|
148
116
|
const dirs: string[] = []
|
|
149
117
|
|
|
150
|
-
for (const browser of
|
|
151
|
-
const browserBase =
|
|
118
|
+
for (const browser of CHROMIUM_BROWSERS) {
|
|
119
|
+
const browserBase = getBrowserBasePath(browser, this.platform)
|
|
152
120
|
if (!browserBase) continue
|
|
153
121
|
|
|
154
|
-
const profileDirs =
|
|
122
|
+
const profileDirs = discoverBrowserProfileDirs(browserBase)
|
|
155
123
|
for (const profileDir of profileDirs) {
|
|
156
124
|
dirs.push(join(profileDir, 'Local Storage', 'leveldb'))
|
|
157
125
|
}
|
|
@@ -160,49 +128,6 @@ export class DiscordTokenExtractor {
|
|
|
160
128
|
return dirs
|
|
161
129
|
}
|
|
162
130
|
|
|
163
|
-
private getBrowserBasePath(browser: BrowserConfig): string | null {
|
|
164
|
-
let relative: string
|
|
165
|
-
|
|
166
|
-
switch (this.platform) {
|
|
167
|
-
case 'darwin':
|
|
168
|
-
relative = browser.darwin
|
|
169
|
-
if (!relative) return null
|
|
170
|
-
return join(homedir(), 'Library', 'Application Support', relative)
|
|
171
|
-
case 'linux':
|
|
172
|
-
relative = browser.linux
|
|
173
|
-
if (!relative) return null
|
|
174
|
-
return join(homedir(), '.config', relative)
|
|
175
|
-
case 'win32':
|
|
176
|
-
relative = browser.win32
|
|
177
|
-
if (!relative) return null
|
|
178
|
-
return join(
|
|
179
|
-
process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local'),
|
|
180
|
-
relative,
|
|
181
|
-
)
|
|
182
|
-
default:
|
|
183
|
-
return null
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
private discoverProfileDirs(browserBase: string): string[] {
|
|
188
|
-
const dirs: string[] = []
|
|
189
|
-
|
|
190
|
-
dirs.push(join(browserBase, 'Default'))
|
|
191
|
-
|
|
192
|
-
if (!existsSync(browserBase)) return dirs
|
|
193
|
-
|
|
194
|
-
try {
|
|
195
|
-
const entries = readdirSync(browserBase, { withFileTypes: true })
|
|
196
|
-
for (const entry of entries) {
|
|
197
|
-
if (!entry.isDirectory()) continue
|
|
198
|
-
if (!/^Profile \d+$/i.test(entry.name)) continue
|
|
199
|
-
dirs.push(join(browserBase, entry.name))
|
|
200
|
-
}
|
|
201
|
-
} catch {}
|
|
202
|
-
|
|
203
|
-
return dirs
|
|
204
|
-
}
|
|
205
|
-
|
|
206
131
|
private findBrowserBaseDirForPath(path: string): string | null {
|
|
207
132
|
const parts = path.split(/[/\\]/)
|
|
208
133
|
for (let levels = 2; levels <= 5; levels++) {
|
|
@@ -214,24 +139,7 @@ export class DiscordTokenExtractor {
|
|
|
214
139
|
}
|
|
215
140
|
|
|
216
141
|
getKeychainVariants(): KeychainVariant[] {
|
|
217
|
-
return [
|
|
218
|
-
// Modern Discord (lowercase)
|
|
219
|
-
{ service: 'discord Safe Storage', account: 'discord Key' },
|
|
220
|
-
{ service: 'discordcanary Safe Storage', account: 'discordcanary Key' },
|
|
221
|
-
{ service: 'discordptb Safe Storage', account: 'discordptb Key' },
|
|
222
|
-
// Legacy Discord (capitalized)
|
|
223
|
-
{ service: 'Discord Safe Storage', account: 'Discord' },
|
|
224
|
-
{ service: 'Discord Canary Safe Storage', account: 'Discord Canary' },
|
|
225
|
-
{ service: 'Discord PTB Safe Storage', account: 'Discord PTB' },
|
|
226
|
-
// Browser keychain entries for fallback
|
|
227
|
-
{ service: 'Chrome Safe Storage', account: 'Chrome' },
|
|
228
|
-
{ service: 'Chrome Canary Safe Storage', account: 'Chrome Canary' },
|
|
229
|
-
{ service: 'Microsoft Edge Safe Storage', account: 'Microsoft Edge' },
|
|
230
|
-
{ service: 'Arc Safe Storage', account: 'Arc' },
|
|
231
|
-
{ service: 'Brave Safe Storage', account: 'Brave' },
|
|
232
|
-
{ service: 'Vivaldi Safe Storage', account: 'Vivaldi' },
|
|
233
|
-
{ service: 'Chromium Safe Storage', account: 'Chromium' },
|
|
234
|
-
]
|
|
142
|
+
return [...DISCORD_APP_KEYCHAIN_VARIANTS, ...BROWSER_KEYCHAIN_VARIANTS]
|
|
235
143
|
}
|
|
236
144
|
|
|
237
145
|
getVariantFromPath(path: string): DiscordVariant {
|
|
@@ -283,6 +191,8 @@ export class DiscordTokenExtractor {
|
|
|
283
191
|
private async loadCachedKey(): Promise<void> {
|
|
284
192
|
if (this.platform !== 'darwin') return
|
|
285
193
|
|
|
194
|
+
await this.decryptor.loadCachedKey()
|
|
195
|
+
|
|
286
196
|
const cached = await this.keyCache.get('discord')
|
|
287
197
|
if (cached) {
|
|
288
198
|
this.cachedKey = cached
|
|
@@ -290,7 +200,7 @@ export class DiscordTokenExtractor {
|
|
|
290
200
|
}
|
|
291
201
|
|
|
292
202
|
async clearKeyCache(): Promise<void> {
|
|
293
|
-
await this.
|
|
203
|
+
await this.decryptor.clearKeyCache()
|
|
294
204
|
this.cachedKey = null
|
|
295
205
|
}
|
|
296
206
|
|
|
@@ -445,27 +355,10 @@ export class DiscordTokenExtractor {
|
|
|
445
355
|
const encryptedKey = Buffer.from(localState.os_crypt.encrypted_key, 'base64')
|
|
446
356
|
|
|
447
357
|
const dpapiBlobKey = encryptedKey.subarray(5)
|
|
448
|
-
const masterKey = this.decryptDPAPI(dpapiBlobKey)
|
|
358
|
+
const masterKey = this.decryptor.decryptDPAPI(dpapiBlobKey)
|
|
449
359
|
if (!masterKey) return null
|
|
450
360
|
|
|
451
|
-
return this.decryptAESGCM(encryptedData, masterKey)
|
|
452
|
-
} catch {
|
|
453
|
-
return null
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
private decryptDPAPI(encryptedBlob: Buffer): Buffer | null {
|
|
458
|
-
try {
|
|
459
|
-
const b64 = encryptedBlob.toString('base64')
|
|
460
|
-
const psScript = `
|
|
461
|
-
Add-Type -AssemblyName System.Security
|
|
462
|
-
$bytes = [Convert]::FromBase64String('${b64}')
|
|
463
|
-
$decrypted = [Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, 'CurrentUser')
|
|
464
|
-
[Convert]::ToBase64String($decrypted)
|
|
465
|
-
`.replace(/\n/g, ' ')
|
|
466
|
-
|
|
467
|
-
const result = execSync(`powershell -Command "${psScript}"`, { encoding: 'utf8' })
|
|
468
|
-
return Buffer.from(result.trim(), 'base64')
|
|
361
|
+
return this.decryptor.decryptAESGCM(encryptedData, masterKey)
|
|
469
362
|
} catch {
|
|
470
363
|
return null
|
|
471
364
|
}
|
|
@@ -473,7 +366,7 @@ export class DiscordTokenExtractor {
|
|
|
473
366
|
|
|
474
367
|
private decryptMacToken(encryptedData: Buffer, discordDir: string): string | null {
|
|
475
368
|
if (this.cachedKey) {
|
|
476
|
-
const decrypted = this.decryptAESCBC(encryptedData, this.cachedKey)
|
|
369
|
+
const decrypted = this.decryptor.decryptAESCBC(encryptedData, this.cachedKey)
|
|
477
370
|
if (decrypted && this.isValidToken(decrypted)) return decrypted
|
|
478
371
|
}
|
|
479
372
|
|
|
@@ -500,7 +393,7 @@ export class DiscordTokenExtractor {
|
|
|
500
393
|
).trim()
|
|
501
394
|
|
|
502
395
|
const key = pbkdf2Sync(password, 'saltysalt', 1003, 16, 'sha1')
|
|
503
|
-
const decrypted = this.decryptAESCBC(encryptedData, key)
|
|
396
|
+
const decrypted = this.decryptor.decryptAESCBC(encryptedData, key)
|
|
504
397
|
if (decrypted && this.isValidToken(decrypted)) {
|
|
505
398
|
this.cachedKey = key
|
|
506
399
|
this.keyCache.set('discord', key).catch(() => {})
|
|
@@ -514,63 +407,26 @@ export class DiscordTokenExtractor {
|
|
|
514
407
|
|
|
515
408
|
private decryptLinuxToken(encryptedData: Buffer): string | null {
|
|
516
409
|
const prefix = encryptedData.subarray(0, 3).toString()
|
|
410
|
+
|
|
517
411
|
if (prefix === 'v11') {
|
|
518
|
-
const
|
|
519
|
-
|
|
412
|
+
for (const appName of ['discord', 'Discord']) {
|
|
413
|
+
try {
|
|
414
|
+
const keyringPassword = this.getLinuxKeyringPassword(appName)
|
|
415
|
+
const key = pbkdf2Sync(keyringPassword, 'saltysalt', 1, 16, 'sha1')
|
|
416
|
+
const decrypted = this.decryptor.decryptAESCBC(encryptedData, key)
|
|
417
|
+
if (decrypted) return decrypted
|
|
418
|
+
} catch {}
|
|
419
|
+
}
|
|
520
420
|
}
|
|
521
|
-
|
|
421
|
+
|
|
522
422
|
const key = pbkdf2Sync('peanuts', 'saltysalt', 1, 16, 'sha1')
|
|
523
|
-
return this.decryptAESCBC(encryptedData, key)
|
|
423
|
+
return this.decryptor.decryptAESCBC(encryptedData, key)
|
|
524
424
|
}
|
|
525
425
|
|
|
526
426
|
private getLinuxKeyringPassword(appName: string): string {
|
|
527
427
|
return lookupLinuxKeyringPassword(appName)
|
|
528
428
|
}
|
|
529
429
|
|
|
530
|
-
private decryptV11LinuxToken(encryptedData: Buffer): string | null {
|
|
531
|
-
const appNames = ['discord', 'Discord']
|
|
532
|
-
for (const appName of appNames) {
|
|
533
|
-
try {
|
|
534
|
-
const keyringPassword = this.getLinuxKeyringPassword(appName)
|
|
535
|
-
const key = pbkdf2Sync(keyringPassword, 'saltysalt', 1, 16, 'sha1')
|
|
536
|
-
const result = this.decryptAESCBC(encryptedData, key)
|
|
537
|
-
if (result) return result
|
|
538
|
-
} catch {}
|
|
539
|
-
}
|
|
540
|
-
return null
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
private decryptAESCBC(encryptedData: Buffer, key: Buffer): string | null {
|
|
544
|
-
try {
|
|
545
|
-
const ciphertext = encryptedData.subarray(3)
|
|
546
|
-
const iv = Buffer.alloc(16, 0x20)
|
|
547
|
-
|
|
548
|
-
const decipher = createDecipheriv('aes-128-cbc', key, iv)
|
|
549
|
-
decipher.setAutoPadding(true)
|
|
550
|
-
|
|
551
|
-
const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])
|
|
552
|
-
return decrypted.toString('utf8')
|
|
553
|
-
} catch {
|
|
554
|
-
return null
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
private decryptAESGCM(encryptedData: Buffer, key: Buffer): string | null {
|
|
559
|
-
try {
|
|
560
|
-
const iv = encryptedData.subarray(3, 15)
|
|
561
|
-
const authTag = encryptedData.subarray(-16)
|
|
562
|
-
const ciphertext = encryptedData.subarray(15, -16)
|
|
563
|
-
|
|
564
|
-
const decipher = createDecipheriv('aes-256-gcm', key, iv)
|
|
565
|
-
decipher.setAuthTag(authTag)
|
|
566
|
-
|
|
567
|
-
const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])
|
|
568
|
-
return decrypted.toString('utf8')
|
|
569
|
-
} catch {
|
|
570
|
-
return null
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
430
|
async isDiscordRunning(variant?: DiscordVariant): Promise<boolean> {
|
|
575
431
|
const variants = variant ? [variant] : (['stable', 'canary', 'ptb'] as DiscordVariant[])
|
|
576
432
|
|
|
@@ -31,10 +31,7 @@ export class DiscordBotClient {
|
|
|
31
31
|
const credManager = new DiscordBotCredentialManager()
|
|
32
32
|
const creds = await credManager.getCredentials()
|
|
33
33
|
if (!creds?.token) {
|
|
34
|
-
throw new DiscordBotError(
|
|
35
|
-
'No Discord bot credentials found. Run "auth set <token>" first.',
|
|
36
|
-
'no_credentials',
|
|
37
|
-
)
|
|
34
|
+
throw new DiscordBotError('No Discord bot credentials found. Run "auth set <token>" first.', 'no_credentials')
|
|
38
35
|
}
|
|
39
36
|
return this.login({ token: creds.token })
|
|
40
37
|
}
|
|
@@ -21,7 +21,9 @@ const mockListGuilds = mock(() =>
|
|
|
21
21
|
|
|
22
22
|
mock.module('../client', () => ({
|
|
23
23
|
DiscordBotClient: class MockDiscordBotClient {
|
|
24
|
-
async login(_credentials?: any) {
|
|
24
|
+
async login(_credentials?: any) {
|
|
25
|
+
return this
|
|
26
|
+
}
|
|
25
27
|
testAuth = mockTestAuth
|
|
26
28
|
listGuilds = mockListGuilds
|
|
27
29
|
},
|
|
@@ -31,7 +31,9 @@ const mockResolveChannel = mock((_guildId: string, channel: string) => {
|
|
|
31
31
|
|
|
32
32
|
mock.module('../client', () => ({
|
|
33
33
|
DiscordBotClient: class MockDiscordBotClient {
|
|
34
|
-
async login(_credentials?: any) {
|
|
34
|
+
async login(_credentials?: any) {
|
|
35
|
+
return this
|
|
36
|
+
}
|
|
35
37
|
listChannels = mockListChannels
|
|
36
38
|
getChannel = mockGetChannel
|
|
37
39
|
resolveChannel = mockResolveChannel
|
|
@@ -68,7 +68,9 @@ const mockResolveChannel = mock((_guildId: string, channel: string) => {
|
|
|
68
68
|
|
|
69
69
|
mock.module('../client', () => ({
|
|
70
70
|
DiscordBotClient: class MockDiscordBotClient {
|
|
71
|
-
async login(_credentials?: any) {
|
|
71
|
+
async login(_credentials?: any) {
|
|
72
|
+
return this
|
|
73
|
+
}
|
|
72
74
|
sendMessage = mockSendMessage
|
|
73
75
|
getMessages = mockGetMessages
|
|
74
76
|
getMessage = mockGetMessage
|
|
@@ -22,7 +22,9 @@ const mockGetGuild = mock((guildId: string) =>
|
|
|
22
22
|
|
|
23
23
|
mock.module('../client', () => ({
|
|
24
24
|
DiscordBotClient: class MockDiscordBotClient {
|
|
25
|
-
async login(_credentials?: any) {
|
|
25
|
+
async login(_credentials?: any) {
|
|
26
|
+
return this
|
|
27
|
+
}
|
|
26
28
|
listGuilds = mockListGuilds
|
|
27
29
|
getGuild = mockGetGuild
|
|
28
30
|
},
|
|
@@ -41,7 +41,9 @@ const mockListUsers = mock((_guildId: string) =>
|
|
|
41
41
|
|
|
42
42
|
mock.module('../client', () => ({
|
|
43
43
|
DiscordBotClient: class MockDiscordBotClient {
|
|
44
|
-
async login(_credentials?: any) {
|
|
44
|
+
async login(_credentials?: any) {
|
|
45
|
+
return this
|
|
46
|
+
}
|
|
45
47
|
listChannels = mockListChannels
|
|
46
48
|
getMessages = mockGetMessages
|
|
47
49
|
listUsers = mockListUsers
|
|
@@ -29,7 +29,9 @@ const mockResolveChannel = mock((_guildId: string, channel: string) => {
|
|
|
29
29
|
|
|
30
30
|
mock.module('../client', () => ({
|
|
31
31
|
DiscordBotClient: class MockDiscordBotClient {
|
|
32
|
-
async login(_credentials?: any) {
|
|
32
|
+
async login(_credentials?: any) {
|
|
33
|
+
return this
|
|
34
|
+
}
|
|
33
35
|
createThread = mockCreateThread
|
|
34
36
|
archiveThread = mockArchiveThread
|
|
35
37
|
resolveChannel = mockResolveChannel
|
|
@@ -28,7 +28,9 @@ const mockGetUser = mock((userId: string) => {
|
|
|
28
28
|
|
|
29
29
|
mock.module('../client', () => ({
|
|
30
30
|
DiscordBotClient: class MockDiscordBotClient {
|
|
31
|
-
async login(_credentials?: any) {
|
|
31
|
+
async login(_credentials?: any) {
|
|
32
|
+
return this
|
|
33
|
+
}
|
|
32
34
|
listUsers = mockListUsers
|
|
33
35
|
getUser = mockGetUser
|
|
34
36
|
},
|
|
@@ -18,10 +18,7 @@ function isAuthCommand(command: CommandType): boolean {
|
|
|
18
18
|
|
|
19
19
|
const program = new Command()
|
|
20
20
|
|
|
21
|
-
program
|
|
22
|
-
.name('agent-instagram')
|
|
23
|
-
.description('CLI tool for Instagram DMs via private mobile API')
|
|
24
|
-
.version(pkg.version)
|
|
21
|
+
program.name('agent-instagram').description('CLI tool for Instagram DMs via private mobile API').version(pkg.version)
|
|
25
22
|
|
|
26
23
|
program.hook('preAction', async (_thisCommand, actionCommand) => {
|
|
27
24
|
if (isAuthCommand(actionCommand)) return
|
|
@@ -104,8 +104,7 @@ describe('InstagramClient', () => {
|
|
|
104
104
|
const mockManager = {
|
|
105
105
|
getAccount: () =>
|
|
106
106
|
Promise.resolve({ account_id: 'testuser', username: 'testuser', created_at: '', updated_at: '' }),
|
|
107
|
-
ensureAccountPaths: () =>
|
|
108
|
-
Promise.resolve({ account_dir: testDir, session_path: sessionPath }),
|
|
107
|
+
ensureAccountPaths: () => Promise.resolve({ account_dir: testDir, session_path: sessionPath }),
|
|
109
108
|
} as any
|
|
110
109
|
|
|
111
110
|
const client = new InstagramClient(mockManager)
|
|
@@ -124,9 +123,7 @@ describe('InstagramClient', () => {
|
|
|
124
123
|
headers: {},
|
|
125
124
|
}),
|
|
126
125
|
)
|
|
127
|
-
fetchResponses.push(
|
|
128
|
-
jsonResponse({ status: 'ok', logged_in_user: { pk: '99' } }),
|
|
129
|
-
)
|
|
126
|
+
fetchResponses.push(jsonResponse({ status: 'ok', logged_in_user: { pk: '99' } }))
|
|
130
127
|
|
|
131
128
|
const client = new InstagramClient()
|
|
132
129
|
const before = Math.floor(Date.now() / 1000)
|
|
@@ -155,9 +152,7 @@ describe('InstagramClient', () => {
|
|
|
155
152
|
}),
|
|
156
153
|
}),
|
|
157
154
|
)
|
|
158
|
-
fetchResponses.push(
|
|
159
|
-
jsonResponse({ status: 'ok', logged_in_user: { pk: '99' } }),
|
|
160
|
-
)
|
|
155
|
+
fetchResponses.push(jsonResponse({ status: 'ok', logged_in_user: { pk: '99' } }))
|
|
161
156
|
|
|
162
157
|
const client = new InstagramClient()
|
|
163
158
|
const before = Math.floor(Date.now() / 1000)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { constants, createCipheriv, publicEncrypt, randomBytes, randomUUID } from 'node:crypto'
|
|
2
2
|
import { existsSync } from 'node:fs'
|
|
3
3
|
import { mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
4
|
+
|
|
4
5
|
import { InstagramCredentialManager } from './credential-manager'
|
|
5
6
|
import {
|
|
6
7
|
InstagramError,
|
|
@@ -164,11 +165,7 @@ export class InstagramClient {
|
|
|
164
165
|
return { userId: this.userId ?? '' }
|
|
165
166
|
}
|
|
166
167
|
|
|
167
|
-
async twoFactorLogin(
|
|
168
|
-
username: string,
|
|
169
|
-
code: string,
|
|
170
|
-
twoFactorIdentifier: string,
|
|
171
|
-
): Promise<{ userId: string }> {
|
|
168
|
+
async twoFactorLogin(username: string, code: string, twoFactorIdentifier: string): Promise<{ userId: string }> {
|
|
172
169
|
const { status, data } = await this.request('POST', '/accounts/two_factor_login/', {
|
|
173
170
|
username,
|
|
174
171
|
verification_code: code,
|
|
@@ -193,7 +190,10 @@ export class InstagramClient {
|
|
|
193
190
|
): Promise<{ contactPoint: string; stepName: string }> {
|
|
194
191
|
this.ensureSession()
|
|
195
192
|
|
|
196
|
-
const { data: getData } = await this.request(
|
|
193
|
+
const { data: getData } = await this.request(
|
|
194
|
+
'GET',
|
|
195
|
+
`${apiPath}?guid=${this.session!.device.uuid}&device_id=${this.session!.device.android_device_id}`,
|
|
196
|
+
)
|
|
197
197
|
const stepName = (getData['step_name'] as string) ?? ''
|
|
198
198
|
|
|
199
199
|
const choice = method === 'sms' ? '0' : '1'
|
|
@@ -210,10 +210,7 @@ export class InstagramClient {
|
|
|
210
210
|
return { contactPoint, stepName: resultStep }
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
async challengeSubmitCode(
|
|
214
|
-
apiPath: string,
|
|
215
|
-
code: string,
|
|
216
|
-
): Promise<{ userId: string }> {
|
|
213
|
+
async challengeSubmitCode(apiPath: string, code: string): Promise<{ userId: string }> {
|
|
217
214
|
this.ensureSession()
|
|
218
215
|
|
|
219
216
|
const { status, data } = await this.request('POST', apiPath, {
|
|
@@ -304,9 +301,7 @@ export class InstagramClient {
|
|
|
304
301
|
async searchChats(query: string, limit = 20): Promise<InstagramChatSummary[]> {
|
|
305
302
|
const allChats = await this.listChats(Math.max(limit, 50))
|
|
306
303
|
const lower = query.toLowerCase()
|
|
307
|
-
return allChats
|
|
308
|
-
.filter((c) => c.name.toLowerCase().includes(lower) || c.id.includes(query))
|
|
309
|
-
.slice(0, limit)
|
|
304
|
+
return allChats.filter((c) => c.name.toLowerCase().includes(lower) || c.id.includes(query)).slice(0, limit)
|
|
310
305
|
}
|
|
311
306
|
|
|
312
307
|
async searchMessages(
|
|
@@ -410,7 +405,12 @@ export class InstagramClient {
|
|
|
410
405
|
return this.userId
|
|
411
406
|
}
|
|
412
407
|
|
|
413
|
-
async getProfile(): Promise<{
|
|
408
|
+
async getProfile(): Promise<{
|
|
409
|
+
user_id: string
|
|
410
|
+
username: string
|
|
411
|
+
full_name: string | null
|
|
412
|
+
profile_pic_url: string | null
|
|
413
|
+
}> {
|
|
414
414
|
if (!this.userId) {
|
|
415
415
|
throw new InstagramError('Not authenticated. Call login() first.', 'not_authenticated')
|
|
416
416
|
}
|
|
@@ -441,17 +441,16 @@ export class InstagramClient {
|
|
|
441
441
|
const keyIdHeader = response.headers.get('ig-set-password-encryption-key-id')
|
|
442
442
|
|
|
443
443
|
if (pubKeyHeader && keyIdHeader) {
|
|
444
|
-
this.debugLog?.(
|
|
444
|
+
this.debugLog?.(
|
|
445
|
+
`encryption key_id=${keyIdHeader} pub_key_length=${pubKeyHeader.length} pub_key_prefix=${pubKeyHeader.substring(0, 40)}...`,
|
|
446
|
+
)
|
|
445
447
|
return { keyId: keyIdHeader, publicKey: pubKeyHeader }
|
|
446
448
|
}
|
|
447
449
|
|
|
448
450
|
return null
|
|
449
451
|
}
|
|
450
452
|
|
|
451
|
-
private encryptPassword(
|
|
452
|
-
password: string,
|
|
453
|
-
key: { keyId: string; publicKey: string },
|
|
454
|
-
): string {
|
|
453
|
+
private encryptPassword(password: string, key: { keyId: string; publicKey: string }): string {
|
|
455
454
|
const timestamp = Math.floor(Date.now() / 1000).toString()
|
|
456
455
|
const passwordBytes = Buffer.from(password, 'utf-8')
|
|
457
456
|
|
|
@@ -463,21 +462,24 @@ export class InstagramClient {
|
|
|
463
462
|
const tag = cipher.getAuthTag()
|
|
464
463
|
|
|
465
464
|
const pubKeyPem = Buffer.from(key.publicKey, 'base64').toString('utf-8')
|
|
466
|
-
const rsaEncrypted = publicEncrypt(
|
|
467
|
-
{ key: pubKeyPem, padding: constants.RSA_PKCS1_PADDING },
|
|
468
|
-
aesKey,
|
|
469
|
-
)
|
|
465
|
+
const rsaEncrypted = publicEncrypt({ key: pubKeyPem, padding: constants.RSA_PKCS1_PADDING }, aesKey)
|
|
470
466
|
|
|
471
467
|
// Wire format: version(1) | keyId(1) | iv(12) | rsaLen(2 LE) | rsaEncrypted | tag(16) | aesEncrypted
|
|
472
468
|
const keyIdNum = Number.parseInt(key.keyId, 10)
|
|
473
469
|
const buf = Buffer.alloc(1 + 1 + 12 + 2 + rsaEncrypted.length + 16 + encrypted.length)
|
|
474
470
|
let offset = 0
|
|
475
|
-
buf.writeUInt8(1, offset)
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
471
|
+
buf.writeUInt8(1, offset)
|
|
472
|
+
offset += 1
|
|
473
|
+
buf.writeUInt8(keyIdNum, offset)
|
|
474
|
+
offset += 1
|
|
475
|
+
iv.copy(buf, offset)
|
|
476
|
+
offset += 12
|
|
477
|
+
buf.writeUInt16LE(rsaEncrypted.length, offset)
|
|
478
|
+
offset += 2
|
|
479
|
+
rsaEncrypted.copy(buf, offset)
|
|
480
|
+
offset += rsaEncrypted.length
|
|
481
|
+
tag.copy(buf, offset)
|
|
482
|
+
offset += 16
|
|
481
483
|
encrypted.copy(buf, offset)
|
|
482
484
|
|
|
483
485
|
return `#PWD_INSTAGRAM:4:${timestamp}:${buf.toString('base64')}`
|
|
@@ -532,7 +534,7 @@ export class InstagramClient {
|
|
|
532
534
|
'X-IG-Connection-Type': 'WIFI',
|
|
533
535
|
'X-IG-Timezone-Offset': String(new Date().getTimezoneOffset() * -60),
|
|
534
536
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
535
|
-
|
|
537
|
+
Accept: '*/*',
|
|
536
538
|
'Accept-Language': 'en-US,en;q=0.9',
|
|
537
539
|
}
|
|
538
540
|
|
|
@@ -606,7 +608,6 @@ export class InstagramClient {
|
|
|
606
608
|
if (this.session) {
|
|
607
609
|
this.session.user_id = this.userId ?? undefined
|
|
608
610
|
this.session.cookies = this.serializeCookies()
|
|
609
|
-
|
|
610
611
|
}
|
|
611
612
|
|
|
612
613
|
await this.saveSession()
|
|
@@ -634,9 +635,13 @@ export class InstagramClient {
|
|
|
634
635
|
const items = (thread['items'] ?? []) as Array<Record<string, unknown>>
|
|
635
636
|
const lastItem = items[0]
|
|
636
637
|
|
|
637
|
-
const name =
|
|
638
|
-
|
|
639
|
-
|
|
638
|
+
const name =
|
|
639
|
+
threadTitle ||
|
|
640
|
+
users
|
|
641
|
+
.map((u) => (u['full_name'] as string) || (u['username'] as string) || '')
|
|
642
|
+
.filter(Boolean)
|
|
643
|
+
.join(', ') ||
|
|
644
|
+
threadId
|
|
640
645
|
|
|
641
646
|
return {
|
|
642
647
|
id: threadId,
|