agent-messenger 2.4.0 → 2.6.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 +35 -0
- package/.github/workflows/release.yml +0 -12
- package/README.md +3 -3
- package/bun.lock +10 -2
- package/dist/package.json +3 -1
- package/dist/src/platforms/channeltalk/cli.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/cli.js +2 -1
- package/dist/src/platforms/channeltalk/cli.js.map +1 -1
- package/dist/src/platforms/channeltalk/commands/index.d.ts +1 -0
- package/dist/src/platforms/channeltalk/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/commands/index.js +1 -0
- package/dist/src/platforms/channeltalk/commands/index.js.map +1 -1
- package/dist/src/platforms/channeltalk/commands/whoami.d.ts +22 -0
- package/dist/src/platforms/channeltalk/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/channeltalk/commands/whoami.js +40 -0
- package/dist/src/platforms/channeltalk/commands/whoami.js.map +1 -0
- package/dist/src/platforms/channeltalkbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/cli.js +2 -1
- package/dist/src/platforms/channeltalkbot/cli.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/index.d.ts +1 -0
- package/dist/src/platforms/channeltalkbot/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/index.js +1 -0
- package/dist/src/platforms/channeltalkbot/commands/index.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/whoami.d.ts +13 -0
- package/dist/src/platforms/channeltalkbot/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/channeltalkbot/commands/whoami.js +31 -0
- package/dist/src/platforms/channeltalkbot/commands/whoami.js.map +1 -0
- package/dist/src/platforms/discord/cli.d.ts.map +1 -1
- package/dist/src/platforms/discord/cli.js +2 -1
- package/dist/src/platforms/discord/cli.js.map +1 -1
- package/dist/src/platforms/discord/commands/index.d.ts +1 -0
- package/dist/src/platforms/discord/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/index.js +1 -0
- package/dist/src/platforms/discord/commands/index.js.map +1 -1
- package/dist/src/platforms/discord/commands/whoami.d.ts +6 -0
- package/dist/src/platforms/discord/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/whoami.js +33 -0
- package/dist/src/platforms/discord/commands/whoami.js.map +1 -0
- package/dist/src/platforms/discordbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/cli.js +2 -1
- package/dist/src/platforms/discordbot/cli.js.map +1 -1
- package/dist/src/platforms/discordbot/commands/index.d.ts +1 -0
- package/dist/src/platforms/discordbot/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/commands/index.js +1 -0
- package/dist/src/platforms/discordbot/commands/index.js.map +1 -1
- package/dist/src/platforms/discordbot/commands/whoami.d.ts +14 -0
- package/dist/src/platforms/discordbot/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/discordbot/commands/whoami.js +32 -0
- package/dist/src/platforms/discordbot/commands/whoami.js.map +1 -0
- package/dist/src/platforms/instagram/cli.d.ts.map +1 -1
- package/dist/src/platforms/instagram/cli.js +2 -1
- package/dist/src/platforms/instagram/cli.js.map +1 -1
- package/dist/src/platforms/instagram/client.d.ts +6 -0
- package/dist/src/platforms/instagram/client.d.ts.map +1 -1
- package/dist/src/platforms/instagram/client.js +12 -0
- package/dist/src/platforms/instagram/client.js.map +1 -1
- package/dist/src/platforms/instagram/commands/index.d.ts +1 -0
- package/dist/src/platforms/instagram/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/instagram/commands/index.js +1 -0
- package/dist/src/platforms/instagram/commands/index.js.map +1 -1
- package/dist/src/platforms/instagram/commands/whoami.d.ts +7 -0
- package/dist/src/platforms/instagram/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/instagram/commands/whoami.js +19 -0
- package/dist/src/platforms/instagram/commands/whoami.js.map +1 -0
- package/dist/src/platforms/kakaotalk/cli.js +2 -2
- package/dist/src/platforms/kakaotalk/cli.js.map +1 -1
- package/dist/src/platforms/kakaotalk/client.d.ts +4 -1
- package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/client.js +193 -27
- 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 +24 -55
- package/dist/src/platforms/kakaotalk/commands/auth.js.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/index.d.ts +1 -1
- package/dist/src/platforms/kakaotalk/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/index.js +1 -1
- package/dist/src/platforms/kakaotalk/commands/index.js.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/whoami.d.ts +3 -0
- package/dist/src/platforms/kakaotalk/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/kakaotalk/commands/{profile.js → whoami.js} +5 -5
- package/dist/src/platforms/kakaotalk/commands/whoami.js.map +1 -0
- package/dist/src/platforms/kakaotalk/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/credential-manager.js +1 -0
- package/dist/src/platforms/kakaotalk/credential-manager.js.map +1 -1
- package/dist/src/platforms/kakaotalk/index.d.ts +1 -1
- package/dist/src/platforms/kakaotalk/index.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/index.js.map +1 -1
- package/dist/src/platforms/kakaotalk/listener.js +2 -2
- package/dist/src/platforms/kakaotalk/listener.js.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/config.d.ts +8 -2
- package/dist/src/platforms/kakaotalk/protocol/config.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/config.js +15 -2
- package/dist/src/platforms/kakaotalk/protocol/config.js.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/session.d.ts +6 -2
- package/dist/src/platforms/kakaotalk/protocol/session.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/session.js +37 -15
- package/dist/src/platforms/kakaotalk/protocol/session.js.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/types.d.ts +17 -0
- package/dist/src/platforms/kakaotalk/protocol/types.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/types.js.map +1 -1
- package/dist/src/platforms/kakaotalk/types.d.ts +22 -0
- package/dist/src/platforms/kakaotalk/types.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/types.js +7 -0
- package/dist/src/platforms/kakaotalk/types.js.map +1 -1
- package/dist/src/platforms/line/cli.js +2 -2
- package/dist/src/platforms/line/cli.js.map +1 -1
- package/dist/src/platforms/line/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/line/commands/auth.js +9 -59
- package/dist/src/platforms/line/commands/auth.js.map +1 -1
- package/dist/src/platforms/line/commands/index.d.ts +1 -1
- package/dist/src/platforms/line/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/line/commands/index.js +1 -1
- package/dist/src/platforms/line/commands/index.js.map +1 -1
- package/dist/src/platforms/line/commands/whoami.d.ts +3 -0
- package/dist/src/platforms/line/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/line/commands/{profile.js → whoami.js} +5 -5
- package/dist/src/platforms/line/commands/whoami.js.map +1 -0
- package/dist/src/platforms/slack/cli.d.ts.map +1 -1
- package/dist/src/platforms/slack/cli.js +2 -1
- package/dist/src/platforms/slack/cli.js.map +1 -1
- package/dist/src/platforms/slack/commands/index.d.ts +1 -0
- package/dist/src/platforms/slack/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/index.js +1 -0
- package/dist/src/platforms/slack/commands/index.js.map +1 -1
- package/dist/src/platforms/slack/commands/whoami.d.ts +6 -0
- package/dist/src/platforms/slack/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/slack/commands/whoami.js +39 -0
- package/dist/src/platforms/slack/commands/whoami.js.map +1 -0
- package/dist/src/platforms/slackbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/slackbot/cli.js +2 -1
- package/dist/src/platforms/slackbot/cli.js.map +1 -1
- package/dist/src/platforms/slackbot/commands/index.d.ts +1 -0
- package/dist/src/platforms/slackbot/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/slackbot/commands/index.js +1 -0
- package/dist/src/platforms/slackbot/commands/index.js.map +1 -1
- package/dist/src/platforms/slackbot/commands/whoami.d.ts +14 -0
- package/dist/src/platforms/slackbot/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/slackbot/commands/whoami.js +32 -0
- package/dist/src/platforms/slackbot/commands/whoami.js.map +1 -0
- package/dist/src/platforms/teams/cli.d.ts.map +1 -1
- package/dist/src/platforms/teams/cli.js +2 -1
- package/dist/src/platforms/teams/cli.js.map +1 -1
- package/dist/src/platforms/teams/commands/index.d.ts +1 -0
- package/dist/src/platforms/teams/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/index.js +1 -0
- package/dist/src/platforms/teams/commands/index.js.map +1 -1
- package/dist/src/platforms/teams/commands/whoami.d.ts +6 -0
- package/dist/src/platforms/teams/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/whoami.js +30 -0
- package/dist/src/platforms/teams/commands/whoami.js.map +1 -0
- package/dist/src/platforms/telegram/cli.d.ts.map +1 -1
- package/dist/src/platforms/telegram/cli.js +2 -1
- package/dist/src/platforms/telegram/cli.js.map +1 -1
- package/dist/src/platforms/telegram/commands/index.d.ts +1 -0
- package/dist/src/platforms/telegram/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/telegram/commands/index.js +1 -0
- package/dist/src/platforms/telegram/commands/index.js.map +1 -1
- package/dist/src/platforms/telegram/commands/whoami.d.ts +7 -0
- package/dist/src/platforms/telegram/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/telegram/commands/whoami.js +27 -0
- package/dist/src/platforms/telegram/commands/whoami.js.map +1 -0
- package/dist/src/platforms/webex/cli.d.ts.map +1 -1
- package/dist/src/platforms/webex/cli.js +2 -1
- package/dist/src/platforms/webex/cli.js.map +1 -1
- package/dist/src/platforms/webex/commands/index.d.ts +1 -0
- package/dist/src/platforms/webex/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/index.js +1 -0
- package/dist/src/platforms/webex/commands/index.js.map +1 -1
- package/dist/src/platforms/webex/commands/message.js +1 -1
- package/dist/src/platforms/webex/commands/message.js.map +1 -1
- package/dist/src/platforms/webex/commands/whoami.d.ts +6 -0
- package/dist/src/platforms/webex/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/webex/commands/whoami.js +30 -0
- package/dist/src/platforms/webex/commands/whoami.js.map +1 -0
- package/dist/src/platforms/wechatbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/wechatbot/cli.js +2 -1
- package/dist/src/platforms/wechatbot/cli.js.map +1 -1
- package/dist/src/platforms/wechatbot/commands/index.d.ts +1 -0
- package/dist/src/platforms/wechatbot/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/wechatbot/commands/index.js +1 -0
- package/dist/src/platforms/wechatbot/commands/index.js.map +1 -1
- package/dist/src/platforms/wechatbot/commands/whoami.d.ts +12 -0
- package/dist/src/platforms/wechatbot/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/wechatbot/commands/whoami.js +33 -0
- package/dist/src/platforms/wechatbot/commands/whoami.js.map +1 -0
- package/dist/src/platforms/whatsapp/cli.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/cli.js +2 -1
- package/dist/src/platforms/whatsapp/cli.js.map +1 -1
- package/dist/src/platforms/whatsapp/client.d.ts +8 -0
- package/dist/src/platforms/whatsapp/client.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/client.js +116 -8
- package/dist/src/platforms/whatsapp/client.js.map +1 -1
- package/dist/src/platforms/whatsapp/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/commands/auth.js +115 -45
- package/dist/src/platforms/whatsapp/commands/auth.js.map +1 -1
- package/dist/src/platforms/whatsapp/commands/index.d.ts +1 -0
- package/dist/src/platforms/whatsapp/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/commands/index.js +1 -0
- package/dist/src/platforms/whatsapp/commands/index.js.map +1 -1
- package/dist/src/platforms/whatsapp/commands/shared.js +2 -2
- package/dist/src/platforms/whatsapp/commands/shared.js.map +1 -1
- package/dist/src/platforms/whatsapp/commands/whoami.d.ts +7 -0
- package/dist/src/platforms/whatsapp/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/whatsapp/commands/whoami.js +19 -0
- package/dist/src/platforms/whatsapp/commands/whoami.js.map +1 -0
- package/dist/src/platforms/whatsapp/ensure-auth.js +2 -2
- package/dist/src/platforms/whatsapp/ensure-auth.js.map +1 -1
- package/dist/src/platforms/whatsappbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/whatsappbot/cli.js +2 -1
- package/dist/src/platforms/whatsappbot/cli.js.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/index.d.ts +1 -0
- package/dist/src/platforms/whatsappbot/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/index.js +1 -0
- package/dist/src/platforms/whatsappbot/commands/index.js.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/whoami.d.ts +17 -0
- package/dist/src/platforms/whatsappbot/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/whatsappbot/commands/whoami.js +39 -0
- package/dist/src/platforms/whatsappbot/commands/whoami.js.map +1 -0
- package/dist/src/shared/utils/qr.d.ts +15 -0
- package/dist/src/shared/utils/qr.d.ts.map +1 -0
- package/dist/src/shared/utils/qr.js +74 -0
- package/dist/src/shared/utils/qr.js.map +1 -0
- package/dist/src/tui/adapters/kakaotalk-adapter.d.ts.map +1 -1
- package/dist/src/tui/adapters/kakaotalk-adapter.js +5 -2
- package/dist/src/tui/adapters/kakaotalk-adapter.js.map +1 -1
- package/dist/src/tui/adapters/whatsapp-adapter.d.ts.map +1 -1
- package/dist/src/tui/adapters/whatsapp-adapter.js +20 -15
- package/dist/src/tui/adapters/whatsapp-adapter.js.map +1 -1
- package/docs/content/docs/cli/channeltalk.mdx +11 -0
- package/docs/content/docs/cli/channeltalkbot.mdx +9 -0
- package/docs/content/docs/cli/discord.mdx +10 -0
- package/docs/content/docs/cli/discordbot.mdx +9 -0
- package/docs/content/docs/cli/instagram.mdx +11 -0
- package/docs/content/docs/cli/kakaotalk.mdx +27 -39
- package/docs/content/docs/cli/line.mdx +4 -4
- package/docs/content/docs/cli/slack.mdx +10 -0
- package/docs/content/docs/cli/slackbot.mdx +9 -0
- package/docs/content/docs/cli/teams.mdx +10 -0
- package/docs/content/docs/cli/telegram.mdx +11 -0
- package/docs/content/docs/cli/webex.mdx +10 -0
- package/docs/content/docs/cli/wechatbot.mdx +9 -0
- package/docs/content/docs/cli/whatsapp.mdx +36 -7
- package/docs/content/docs/cli/whatsappbot.mdx +9 -0
- package/e2e/config.ts +1 -1
- package/package.json +3 -1
- package/skills/agent-channeltalk/SKILL.md +12 -1
- package/skills/agent-channeltalkbot/SKILL.md +10 -1
- package/skills/agent-discord/SKILL.md +11 -1
- package/skills/agent-discordbot/SKILL.md +10 -1
- package/skills/agent-instagram/SKILL.md +12 -1
- package/skills/agent-kakaotalk/SKILL.md +24 -70
- package/skills/agent-kakaotalk/references/authentication.md +4 -69
- package/skills/agent-kakaotalk/references/common-patterns.md +14 -1
- package/skills/agent-line/SKILL.md +5 -5
- package/skills/agent-slack/SKILL.md +11 -1
- package/skills/agent-slackbot/SKILL.md +10 -1
- package/skills/agent-teams/SKILL.md +11 -1
- package/skills/agent-telegram/SKILL.md +6 -1
- package/skills/agent-webex/SKILL.md +11 -1
- package/skills/agent-wechatbot/SKILL.md +10 -1
- package/skills/agent-whatsapp/SKILL.md +52 -15
- package/skills/agent-whatsapp/references/authentication.md +36 -6
- package/skills/agent-whatsappbot/SKILL.md +10 -1
- package/src/platforms/channeltalk/cli.ts +2 -0
- package/src/platforms/channeltalk/commands/index.ts +1 -0
- package/src/platforms/channeltalk/commands/whoami.test.ts +64 -0
- package/src/platforms/channeltalk/commands/whoami.ts +62 -0
- package/src/platforms/channeltalkbot/cli.ts +2 -0
- package/src/platforms/channeltalkbot/commands/index.ts +1 -0
- package/src/platforms/channeltalkbot/commands/whoami.test.ts +104 -0
- package/src/platforms/channeltalkbot/commands/whoami.ts +42 -0
- package/src/platforms/discord/cli.ts +2 -0
- package/src/platforms/discord/commands/index.ts +1 -0
- package/src/platforms/discord/commands/whoami.test.ts +91 -0
- package/src/platforms/discord/commands/whoami.ts +36 -0
- package/src/platforms/discordbot/cli.ts +2 -0
- package/src/platforms/discordbot/commands/index.ts +1 -0
- package/src/platforms/discordbot/commands/whoami.test.ts +96 -0
- package/src/platforms/discordbot/commands/whoami.ts +44 -0
- package/src/platforms/instagram/cli.ts +2 -1
- package/src/platforms/instagram/client.ts +13 -0
- package/src/platforms/instagram/commands/chat.test.ts +1 -5
- package/src/platforms/instagram/commands/index.ts +1 -0
- package/src/platforms/instagram/commands/message.test.ts +1 -5
- package/src/platforms/instagram/commands/whoami.test.ts +60 -0
- package/src/platforms/instagram/commands/whoami.ts +21 -0
- package/src/platforms/kakaotalk/cli.ts +2 -2
- package/src/platforms/kakaotalk/client.test.ts +25 -14
- package/src/platforms/kakaotalk/client.ts +228 -33
- package/src/platforms/kakaotalk/commands/auth.ts +22 -73
- package/src/platforms/kakaotalk/commands/index.ts +1 -1
- package/src/platforms/kakaotalk/commands/{profile.test.ts → whoami.test.ts} +37 -5
- package/src/platforms/kakaotalk/commands/{profile.ts → whoami.ts} +4 -4
- package/src/platforms/kakaotalk/credential-manager.ts +1 -0
- package/src/platforms/kakaotalk/index.ts +1 -0
- package/src/platforms/kakaotalk/listener.test.ts +2 -2
- package/src/platforms/kakaotalk/listener.ts +2 -2
- package/src/platforms/kakaotalk/protocol/config.ts +26 -2
- package/src/platforms/kakaotalk/protocol/session.ts +42 -16
- package/src/platforms/kakaotalk/protocol/types.ts +9 -0
- package/src/platforms/kakaotalk/types.ts +16 -0
- package/src/platforms/line/cli.ts +2 -2
- package/src/platforms/line/commands/auth.ts +37 -70
- package/src/platforms/line/commands/index.ts +1 -1
- package/src/platforms/line/commands/{profile.test.ts → whoami.test.ts} +11 -11
- package/src/platforms/line/commands/{profile.ts → whoami.ts} +4 -4
- package/src/platforms/slack/cli.ts +2 -0
- package/src/platforms/slack/commands/index.ts +1 -0
- package/src/platforms/slack/commands/whoami.test.ts +126 -0
- package/src/platforms/slack/commands/whoami.ts +40 -0
- package/src/platforms/slackbot/cli.ts +2 -1
- package/src/platforms/slackbot/commands/index.ts +1 -0
- package/src/platforms/slackbot/commands/whoami.test.ts +102 -0
- package/src/platforms/slackbot/commands/whoami.ts +44 -0
- package/src/platforms/teams/cli.ts +2 -0
- package/src/platforms/teams/commands/index.ts +1 -0
- package/src/platforms/teams/commands/whoami.test.ts +83 -0
- package/src/platforms/teams/commands/whoami.ts +33 -0
- package/src/platforms/telegram/cli.ts +2 -1
- package/src/platforms/telegram/commands/index.ts +1 -0
- package/src/platforms/telegram/commands/whoami.test.ts +75 -0
- package/src/platforms/telegram/commands/whoami.ts +29 -0
- package/src/platforms/webex/cli.ts +2 -1
- package/src/platforms/webex/commands/auth.test.ts +58 -46
- package/src/platforms/webex/commands/index.ts +1 -0
- package/src/platforms/webex/commands/member.test.ts +1 -5
- package/src/platforms/webex/commands/message.test.ts +1 -5
- package/src/platforms/webex/commands/message.ts +1 -1
- package/src/platforms/webex/commands/snapshot.test.ts +1 -5
- package/src/platforms/webex/commands/space.test.ts +1 -5
- package/src/platforms/webex/commands/whoami.test.ts +113 -0
- package/src/platforms/webex/commands/whoami.ts +31 -0
- package/src/platforms/webex/credential-manager.test.ts +0 -1
- package/src/platforms/wechatbot/cli.ts +2 -1
- package/src/platforms/wechatbot/commands/index.ts +1 -0
- package/src/platforms/wechatbot/commands/whoami.test.ts +109 -0
- package/src/platforms/wechatbot/commands/whoami.ts +43 -0
- package/src/platforms/whatsapp/cli.ts +2 -1
- package/src/platforms/whatsapp/client.ts +156 -24
- package/src/platforms/whatsapp/commands/auth.ts +176 -70
- package/src/platforms/whatsapp/commands/index.ts +1 -0
- package/src/platforms/whatsapp/commands/shared.ts +2 -2
- package/src/platforms/whatsapp/commands/whoami.test.ts +59 -0
- package/src/platforms/whatsapp/commands/whoami.ts +21 -0
- package/src/platforms/whatsapp/ensure-auth.ts +2 -2
- package/src/platforms/whatsappbot/cli.ts +2 -1
- package/src/platforms/whatsappbot/commands/index.ts +1 -0
- package/src/platforms/whatsappbot/commands/whoami.test.ts +100 -0
- package/src/platforms/whatsappbot/commands/whoami.ts +57 -0
- package/src/shared/utils/qr.ts +92 -0
- package/src/tui/adapters/kakaotalk-adapter.ts +5 -2
- package/src/tui/adapters/whatsapp-adapter.ts +19 -16
- package/dist/src/platforms/kakaotalk/commands/profile.d.ts +0 -3
- package/dist/src/platforms/kakaotalk/commands/profile.d.ts.map +0 -1
- package/dist/src/platforms/kakaotalk/commands/profile.js.map +0 -1
- package/dist/src/platforms/line/commands/profile.d.ts +0 -3
- package/dist/src/platforms/line/commands/profile.d.ts.map +0 -1
- package/dist/src/platforms/line/commands/profile.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect,
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, spyOn, test } from 'bun:test'
|
|
2
2
|
import * as childProcess from 'node:child_process'
|
|
3
3
|
|
|
4
4
|
import { WebexClient } from '../client'
|
|
@@ -7,7 +7,9 @@ import { loginAction, logoutAction, statusAction } from './auth'
|
|
|
7
7
|
|
|
8
8
|
describe('auth commands', () => {
|
|
9
9
|
let consoleSpy: ReturnType<typeof spyOn>
|
|
10
|
-
let
|
|
10
|
+
let consoleErrorSpy: ReturnType<typeof spyOn>
|
|
11
|
+
let execSpy: ReturnType<typeof spyOn>
|
|
12
|
+
const protoSpies: ReturnType<typeof spyOn>[] = []
|
|
11
13
|
const mockPerson = {
|
|
12
14
|
id: 'person-1',
|
|
13
15
|
displayName: 'Test User',
|
|
@@ -17,21 +19,31 @@ describe('auth commands', () => {
|
|
|
17
19
|
created: '2024-01-01T00:00:00.000Z',
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
function protoSpy<T extends object>(target: T, method: keyof T) {
|
|
23
|
+
const s = spyOn(target, method as any)
|
|
24
|
+
protoSpies.push(s)
|
|
25
|
+
return s
|
|
26
|
+
}
|
|
27
|
+
|
|
20
28
|
beforeEach(() => {
|
|
21
29
|
consoleSpy = spyOn(console, 'log').mockImplementation(() => {})
|
|
22
|
-
|
|
23
|
-
spyOn(childProcess, 'exec').mockImplementation((() => {}) as any)
|
|
30
|
+
consoleErrorSpy = spyOn(console, 'error').mockImplementation(() => {})
|
|
31
|
+
execSpy = spyOn(childProcess, 'exec').mockImplementation((() => {}) as any)
|
|
24
32
|
})
|
|
25
33
|
|
|
26
34
|
afterEach(() => {
|
|
27
|
-
|
|
35
|
+
consoleSpy.mockRestore()
|
|
36
|
+
consoleErrorSpy.mockRestore()
|
|
37
|
+
execSpy.mockRestore()
|
|
38
|
+
for (const s of protoSpies) s.mockRestore()
|
|
39
|
+
protoSpies.length = 0
|
|
28
40
|
})
|
|
29
41
|
|
|
30
42
|
describe('loginAction with --token', () => {
|
|
31
43
|
test('authenticates with provided token (bot token flow)', async () => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
|
|
45
|
+
protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
|
|
46
|
+
protoSpy(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
|
|
35
47
|
|
|
36
48
|
await loginAction({ token: 'bot-token-123', pretty: false })
|
|
37
49
|
|
|
@@ -43,9 +55,9 @@ describe('auth commands', () => {
|
|
|
43
55
|
})
|
|
44
56
|
|
|
45
57
|
test('saves tokenType as manual with expiresAt 0', async () => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const saveSpy =
|
|
58
|
+
protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
|
|
59
|
+
protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
|
|
60
|
+
const saveSpy = protoSpy(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
|
|
49
61
|
|
|
50
62
|
await loginAction({ token: 'bot-token-123', pretty: false })
|
|
51
63
|
|
|
@@ -58,7 +70,7 @@ describe('auth commands', () => {
|
|
|
58
70
|
|
|
59
71
|
describe('loginAction with --client-id and --client-secret', () => {
|
|
60
72
|
test('uses provided credentials for Device Grant flow', async () => {
|
|
61
|
-
|
|
73
|
+
protoSpy(WebexCredentialManager.prototype, 'requestDeviceCode').mockResolvedValue({
|
|
62
74
|
deviceCode: 'd',
|
|
63
75
|
userCode: 'u',
|
|
64
76
|
verificationUri: 'https://v',
|
|
@@ -66,14 +78,14 @@ describe('auth commands', () => {
|
|
|
66
78
|
expiresIn: 300,
|
|
67
79
|
interval: 0.01,
|
|
68
80
|
})
|
|
69
|
-
|
|
81
|
+
protoSpy(WebexCredentialManager.prototype, 'pollDeviceToken').mockResolvedValue({
|
|
70
82
|
accessToken: 'at',
|
|
71
83
|
refreshToken: 'rt',
|
|
72
84
|
expiresAt: Date.now() + 3600000,
|
|
73
85
|
})
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
86
|
+
protoSpy(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
|
|
87
|
+
protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
|
|
88
|
+
protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
|
|
77
89
|
|
|
78
90
|
await loginAction({ clientId: 'my-id', clientSecret: 'my-secret', pretty: false })
|
|
79
91
|
|
|
@@ -82,7 +94,7 @@ describe('auth commands', () => {
|
|
|
82
94
|
})
|
|
83
95
|
|
|
84
96
|
test('saves tokenType as oauth in config', async () => {
|
|
85
|
-
|
|
97
|
+
protoSpy(WebexCredentialManager.prototype, 'requestDeviceCode').mockResolvedValue({
|
|
86
98
|
deviceCode: 'd',
|
|
87
99
|
userCode: 'u',
|
|
88
100
|
verificationUri: 'https://v',
|
|
@@ -90,14 +102,14 @@ describe('auth commands', () => {
|
|
|
90
102
|
expiresIn: 300,
|
|
91
103
|
interval: 0.01,
|
|
92
104
|
})
|
|
93
|
-
|
|
105
|
+
protoSpy(WebexCredentialManager.prototype, 'pollDeviceToken').mockResolvedValue({
|
|
94
106
|
accessToken: 'at',
|
|
95
107
|
refreshToken: 'rt',
|
|
96
108
|
expiresAt: Date.now() + 3600000,
|
|
97
109
|
})
|
|
98
|
-
const saveSpy =
|
|
99
|
-
|
|
100
|
-
|
|
110
|
+
const saveSpy = protoSpy(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
|
|
111
|
+
protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
|
|
112
|
+
protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
|
|
101
113
|
|
|
102
114
|
await loginAction({ clientId: 'my-id', clientSecret: 'my-secret', pretty: false })
|
|
103
115
|
|
|
@@ -106,7 +118,7 @@ describe('auth commands', () => {
|
|
|
106
118
|
})
|
|
107
119
|
|
|
108
120
|
test('saves clientId and clientSecret in config', async () => {
|
|
109
|
-
|
|
121
|
+
protoSpy(WebexCredentialManager.prototype, 'requestDeviceCode').mockResolvedValue({
|
|
110
122
|
deviceCode: 'd',
|
|
111
123
|
userCode: 'u',
|
|
112
124
|
verificationUri: 'https://v',
|
|
@@ -114,18 +126,18 @@ describe('auth commands', () => {
|
|
|
114
126
|
expiresIn: 300,
|
|
115
127
|
interval: 0.01,
|
|
116
128
|
})
|
|
117
|
-
|
|
129
|
+
protoSpy(WebexCredentialManager.prototype, 'pollDeviceToken').mockResolvedValue({
|
|
118
130
|
accessToken: 'at',
|
|
119
131
|
refreshToken: 'rt',
|
|
120
132
|
expiresAt: Date.now() + 3600000,
|
|
121
133
|
})
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
134
|
+
const saveSpy = protoSpy(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
|
|
135
|
+
protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
|
|
136
|
+
protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
|
|
125
137
|
|
|
126
138
|
await loginAction({ clientId: 'my-id', clientSecret: 'my-secret', pretty: false })
|
|
127
139
|
|
|
128
|
-
const savedConfig =
|
|
140
|
+
const savedConfig = saveSpy.mock.calls[0][0] as { clientId: string; clientSecret: string }
|
|
129
141
|
expect(savedConfig.clientId).toBe('my-id')
|
|
130
142
|
expect(savedConfig.clientSecret).toBe('my-secret')
|
|
131
143
|
})
|
|
@@ -133,10 +145,10 @@ describe('auth commands', () => {
|
|
|
133
145
|
|
|
134
146
|
describe('statusAction', () => {
|
|
135
147
|
test('shows authenticated status when token is valid', async () => {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
148
|
+
protoSpy(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
|
|
149
|
+
protoSpy(WebexCredentialManager.prototype, 'getToken').mockResolvedValue('valid-token')
|
|
150
|
+
protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
|
|
151
|
+
protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
|
|
140
152
|
|
|
141
153
|
await statusAction({ pretty: false })
|
|
142
154
|
|
|
@@ -147,9 +159,9 @@ describe('auth commands', () => {
|
|
|
147
159
|
})
|
|
148
160
|
|
|
149
161
|
test('shows not authenticated when no token', async () => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const exitSpy =
|
|
162
|
+
protoSpy(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
|
|
163
|
+
protoSpy(WebexCredentialManager.prototype, 'getToken').mockResolvedValue(null)
|
|
164
|
+
const exitSpy = protoSpy(process, 'exit').mockImplementation(() => undefined as never)
|
|
153
165
|
|
|
154
166
|
await statusAction({ pretty: false })
|
|
155
167
|
|
|
@@ -160,10 +172,10 @@ describe('auth commands', () => {
|
|
|
160
172
|
})
|
|
161
173
|
|
|
162
174
|
test('shows not authenticated when token validation fails', async () => {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
175
|
+
protoSpy(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
|
|
176
|
+
protoSpy(WebexCredentialManager.prototype, 'getToken').mockResolvedValue('invalid-token')
|
|
177
|
+
protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
|
|
178
|
+
protoSpy(WebexClient.prototype, 'testAuth').mockRejectedValue(new Error('401 Unauthorized'))
|
|
167
179
|
|
|
168
180
|
await statusAction({ pretty: false })
|
|
169
181
|
|
|
@@ -173,16 +185,16 @@ describe('auth commands', () => {
|
|
|
173
185
|
})
|
|
174
186
|
|
|
175
187
|
test('loads config for stored client credentials', async () => {
|
|
176
|
-
|
|
188
|
+
protoSpy(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue({
|
|
177
189
|
accessToken: 'at',
|
|
178
190
|
refreshToken: 'rt',
|
|
179
191
|
expiresAt: Date.now() + 3600000,
|
|
180
192
|
clientId: 'stored-id',
|
|
181
193
|
clientSecret: 'stored-secret',
|
|
182
194
|
})
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
195
|
+
protoSpy(WebexCredentialManager.prototype, 'getToken').mockResolvedValue('valid-token')
|
|
196
|
+
protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
|
|
197
|
+
protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
|
|
186
198
|
|
|
187
199
|
await statusAction({ pretty: false })
|
|
188
200
|
|
|
@@ -192,12 +204,12 @@ describe('auth commands', () => {
|
|
|
192
204
|
|
|
193
205
|
describe('logoutAction', () => {
|
|
194
206
|
test('clears credentials when authenticated', async () => {
|
|
195
|
-
|
|
207
|
+
protoSpy(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue({
|
|
196
208
|
accessToken: 'token',
|
|
197
209
|
refreshToken: 'refresh',
|
|
198
210
|
expiresAt: Date.now() + 3600000,
|
|
199
211
|
})
|
|
200
|
-
const clearSpy =
|
|
212
|
+
const clearSpy = protoSpy(WebexCredentialManager.prototype, 'clearCredentials').mockResolvedValue(undefined)
|
|
201
213
|
|
|
202
214
|
await logoutAction({ pretty: false })
|
|
203
215
|
|
|
@@ -208,8 +220,8 @@ describe('auth commands', () => {
|
|
|
208
220
|
})
|
|
209
221
|
|
|
210
222
|
test('shows error when not authenticated', async () => {
|
|
211
|
-
|
|
212
|
-
const exitSpy =
|
|
223
|
+
protoSpy(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
|
|
224
|
+
const exitSpy = protoSpy(process, 'exit').mockImplementation(() => undefined as never)
|
|
213
225
|
|
|
214
226
|
await logoutAction({ pretty: false })
|
|
215
227
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from 'bun:test'
|
|
2
2
|
|
|
3
3
|
import { WebexError } from '../types'
|
|
4
4
|
|
|
@@ -42,10 +42,6 @@ mock.module('../client', () => ({
|
|
|
42
42
|
|
|
43
43
|
import { listAction } from './member'
|
|
44
44
|
|
|
45
|
-
afterAll(() => {
|
|
46
|
-
mock.restore()
|
|
47
|
-
})
|
|
48
|
-
|
|
49
45
|
describe('member commands', () => {
|
|
50
46
|
let consoleSpy: ReturnType<typeof spyOn>
|
|
51
47
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { afterEach, beforeEach, expect, mock, spyOn, test } from 'bun:test'
|
|
2
2
|
|
|
3
3
|
import { WebexError } from '../types'
|
|
4
4
|
|
|
@@ -56,10 +56,6 @@ mock.module('../client', () => ({
|
|
|
56
56
|
|
|
57
57
|
import { deleteAction, dmAction, editAction, getAction, listAction, sendAction } from './message'
|
|
58
58
|
|
|
59
|
-
afterAll(() => {
|
|
60
|
-
mock.restore()
|
|
61
|
-
})
|
|
62
|
-
|
|
63
59
|
let consoleLogSpy: ReturnType<typeof spyOn>
|
|
64
60
|
|
|
65
61
|
beforeEach(() => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from 'bun:test'
|
|
2
2
|
import { WebexError } from '../types'
|
|
3
3
|
|
|
4
4
|
const mockHandleError = mock((err: Error) => {
|
|
@@ -41,10 +41,6 @@ mock.module('../client', () => ({
|
|
|
41
41
|
|
|
42
42
|
import { snapshotAction } from './snapshot'
|
|
43
43
|
|
|
44
|
-
afterAll(() => {
|
|
45
|
-
mock.restore()
|
|
46
|
-
})
|
|
47
|
-
|
|
48
44
|
describe('snapshot command', () => {
|
|
49
45
|
let consoleSpy: ReturnType<typeof spyOn>
|
|
50
46
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from 'bun:test'
|
|
2
2
|
|
|
3
3
|
import { WebexError } from '../types'
|
|
4
4
|
|
|
@@ -54,10 +54,6 @@ mock.module('../client', () => ({
|
|
|
54
54
|
|
|
55
55
|
import { infoAction, listAction } from './space'
|
|
56
56
|
|
|
57
|
-
afterAll(() => {
|
|
58
|
-
mock.restore()
|
|
59
|
-
})
|
|
60
|
-
|
|
61
57
|
let consoleLogSpy: ReturnType<typeof spyOn>
|
|
62
58
|
|
|
63
59
|
beforeEach(() => {
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { afterEach, beforeEach, expect, spyOn, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
import * as clientModule from '../client'
|
|
4
|
+
import { WebexError } from '../types'
|
|
5
|
+
import { whoamiCommand } from './whoami'
|
|
6
|
+
|
|
7
|
+
const mockUser = {
|
|
8
|
+
id: 'person-123',
|
|
9
|
+
emails: ['test@example.com'],
|
|
10
|
+
displayName: 'Test User',
|
|
11
|
+
nickName: 'Testy',
|
|
12
|
+
firstName: 'Test',
|
|
13
|
+
lastName: 'User',
|
|
14
|
+
avatar: 'https://example.com/avatar.jpg',
|
|
15
|
+
orgId: 'org-123',
|
|
16
|
+
type: 'person' as const,
|
|
17
|
+
created: '2024-01-01T00:00:00.000Z',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const makeFakeClient = () => ({
|
|
21
|
+
login: async function (this: unknown) { return this },
|
|
22
|
+
testAuth: async () => mockUser,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
let webexClientSpy: ReturnType<typeof spyOn>
|
|
26
|
+
let consoleLogSpy: ReturnType<typeof spyOn>
|
|
27
|
+
let processExitSpy: ReturnType<typeof spyOn>
|
|
28
|
+
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
webexClientSpy = spyOn(clientModule, 'WebexClient').mockImplementation(
|
|
31
|
+
makeFakeClient as unknown as typeof clientModule.WebexClient,
|
|
32
|
+
)
|
|
33
|
+
consoleLogSpy = spyOn(console, 'log').mockImplementation(() => {})
|
|
34
|
+
processExitSpy = spyOn(process, 'exit').mockImplementation((_code?: number) => undefined as never)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
afterEach(() => {
|
|
38
|
+
webexClientSpy?.mockRestore()
|
|
39
|
+
consoleLogSpy?.mockRestore()
|
|
40
|
+
processExitSpy?.mockRestore()
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('whoami command is defined with correct name and description', () => {
|
|
44
|
+
expect(whoamiCommand).toBeDefined()
|
|
45
|
+
expect(whoamiCommand.name()).toBe('whoami')
|
|
46
|
+
expect(whoamiCommand.description()).toBe('Show current authenticated user')
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
test('whoami command has --pretty option', () => {
|
|
50
|
+
const options = whoamiCommand.options
|
|
51
|
+
const hasPretty = options.some((opt: { long?: string }) => opt.long === '--pretty')
|
|
52
|
+
expect(hasPretty).toBe(true)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('whoami calls testAuth and outputs user fields', async () => {
|
|
56
|
+
// given: authenticated webex user
|
|
57
|
+
// when: running whoami
|
|
58
|
+
await whoamiCommand.parseAsync([], { from: 'user' })
|
|
59
|
+
|
|
60
|
+
// then: outputs all expected fields
|
|
61
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
62
|
+
JSON.stringify({
|
|
63
|
+
id: 'person-123',
|
|
64
|
+
emails: ['test@example.com'],
|
|
65
|
+
displayName: 'Test User',
|
|
66
|
+
nickName: 'Testy',
|
|
67
|
+
firstName: 'Test',
|
|
68
|
+
lastName: 'User',
|
|
69
|
+
avatar: 'https://example.com/avatar.jpg',
|
|
70
|
+
orgId: 'org-123',
|
|
71
|
+
type: 'person',
|
|
72
|
+
}),
|
|
73
|
+
)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
test('whoami outputs pretty-printed JSON when --pretty flag is passed', async () => {
|
|
77
|
+
// given: authenticated webex user
|
|
78
|
+
// when: running whoami with --pretty
|
|
79
|
+
await whoamiCommand.parseAsync(['--pretty'], { from: 'user' })
|
|
80
|
+
|
|
81
|
+
// then: output is pretty-printed
|
|
82
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
83
|
+
JSON.stringify(
|
|
84
|
+
{
|
|
85
|
+
id: 'person-123',
|
|
86
|
+
emails: ['test@example.com'],
|
|
87
|
+
displayName: 'Test User',
|
|
88
|
+
nickName: 'Testy',
|
|
89
|
+
firstName: 'Test',
|
|
90
|
+
lastName: 'User',
|
|
91
|
+
avatar: 'https://example.com/avatar.jpg',
|
|
92
|
+
orgId: 'org-123',
|
|
93
|
+
type: 'person',
|
|
94
|
+
},
|
|
95
|
+
null,
|
|
96
|
+
2,
|
|
97
|
+
),
|
|
98
|
+
)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
test('whoami exits with code 1 when not authenticated', async () => {
|
|
102
|
+
// given: no credentials
|
|
103
|
+
webexClientSpy.mockImplementation(() => ({
|
|
104
|
+
login: async () => { throw new WebexError('No Webex credentials found.', 'no_credentials') },
|
|
105
|
+
testAuth: async () => mockUser,
|
|
106
|
+
}) as unknown as clientModule.WebexClient)
|
|
107
|
+
|
|
108
|
+
// when: running whoami
|
|
109
|
+
await whoamiCommand.parseAsync([], { from: 'user' })
|
|
110
|
+
|
|
111
|
+
// then: process exits with code 1
|
|
112
|
+
expect(processExitSpy).toHaveBeenCalledWith(1)
|
|
113
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { handleError } from '@/shared/utils/error-handler'
|
|
3
|
+
import { formatOutput } from '@/shared/utils/output'
|
|
4
|
+
import { WebexClient } from '../client'
|
|
5
|
+
|
|
6
|
+
export async function whoamiAction(options: { pretty?: boolean }): Promise<void> {
|
|
7
|
+
try {
|
|
8
|
+
const client = await new WebexClient().login()
|
|
9
|
+
const user = await client.testAuth()
|
|
10
|
+
|
|
11
|
+
const output = {
|
|
12
|
+
id: user.id,
|
|
13
|
+
emails: user.emails,
|
|
14
|
+
displayName: user.displayName,
|
|
15
|
+
nickName: user.nickName,
|
|
16
|
+
firstName: user.firstName,
|
|
17
|
+
lastName: user.lastName,
|
|
18
|
+
avatar: user.avatar,
|
|
19
|
+
orgId: user.orgId,
|
|
20
|
+
type: user.type,
|
|
21
|
+
}
|
|
22
|
+
console.log(formatOutput(output, options.pretty))
|
|
23
|
+
} catch (error) {
|
|
24
|
+
handleError(error as Error)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const whoamiCommand = new Command('whoami')
|
|
29
|
+
.description('Show current authenticated user')
|
|
30
|
+
.option('--pretty', 'Pretty print JSON output')
|
|
31
|
+
.action(whoamiAction)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { Command } from 'commander'
|
|
4
4
|
|
|
5
5
|
import pkg from '../../../package.json' with { type: 'json' }
|
|
6
|
-
import { authCommand, messageCommand, templateCommand, userCommand } from './commands/index'
|
|
6
|
+
import { authCommand, messageCommand, templateCommand, userCommand, whoamiCommand } from './commands/index'
|
|
7
7
|
|
|
8
8
|
const program = new Command()
|
|
9
9
|
|
|
@@ -15,6 +15,7 @@ program
|
|
|
15
15
|
.option('--account <id>', 'Account ID to use')
|
|
16
16
|
|
|
17
17
|
program.addCommand(authCommand)
|
|
18
|
+
program.addCommand(whoamiCommand)
|
|
18
19
|
program.addCommand(messageCommand)
|
|
19
20
|
program.addCommand(templateCommand)
|
|
20
21
|
program.addCommand(userCommand)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test'
|
|
2
|
+
import { existsSync, rmSync } from 'node:fs'
|
|
3
|
+
import { mkdir } from 'node:fs/promises'
|
|
4
|
+
import { tmpdir } from 'node:os'
|
|
5
|
+
import { join } from 'node:path'
|
|
6
|
+
|
|
7
|
+
const mockVerifyCredentials = mock(() => Promise.resolve(true))
|
|
8
|
+
|
|
9
|
+
mock.module('../client', () => ({
|
|
10
|
+
WeChatBotClient: class MockWeChatBotClient {
|
|
11
|
+
async login(_credentials?: { appId: string; appSecret: string }) {
|
|
12
|
+
return this
|
|
13
|
+
}
|
|
14
|
+
verifyCredentials = mockVerifyCredentials
|
|
15
|
+
},
|
|
16
|
+
}))
|
|
17
|
+
|
|
18
|
+
import { WeChatBotCredentialManager } from '../credential-manager'
|
|
19
|
+
import { whoamiAction } from './whoami'
|
|
20
|
+
|
|
21
|
+
describe('whoami command', () => {
|
|
22
|
+
let tempDir: string
|
|
23
|
+
let originalEnv: NodeJS.ProcessEnv
|
|
24
|
+
|
|
25
|
+
beforeEach(async () => {
|
|
26
|
+
tempDir = join(tmpdir(), `wechatbot-whoami-test-${Date.now()}`)
|
|
27
|
+
await mkdir(tempDir, { recursive: true })
|
|
28
|
+
originalEnv = { ...process.env }
|
|
29
|
+
delete process.env.E2E_WECHATBOT_APP_ID
|
|
30
|
+
delete process.env.E2E_WECHATBOT_APP_SECRET
|
|
31
|
+
mockVerifyCredentials.mockClear()
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
if (existsSync(tempDir)) {
|
|
36
|
+
rmSync(tempDir, { recursive: true })
|
|
37
|
+
}
|
|
38
|
+
process.env = originalEnv
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test('returns app_id, account_name, and verified status', async () => {
|
|
42
|
+
const manager = new WeChatBotCredentialManager(tempDir)
|
|
43
|
+
await manager.setCredentials({
|
|
44
|
+
app_id: 'wx1234567890',
|
|
45
|
+
app_secret: 'secret123',
|
|
46
|
+
account_name: 'Test Official Account',
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
const result = await whoamiAction({ _credManager: manager })
|
|
50
|
+
|
|
51
|
+
expect(result.app_id).toBe('wx1234567890')
|
|
52
|
+
expect(result.account_name).toBe('Test Official Account')
|
|
53
|
+
expect(result.verified).toBe(true)
|
|
54
|
+
expect(result.error).toBeUndefined()
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test('returns info for specific --account', async () => {
|
|
58
|
+
const manager = new WeChatBotCredentialManager(tempDir)
|
|
59
|
+
await manager.setCredentials({
|
|
60
|
+
app_id: 'wxAAA',
|
|
61
|
+
app_secret: 'secretA',
|
|
62
|
+
account_name: 'Account A',
|
|
63
|
+
})
|
|
64
|
+
await manager.setCredentials({
|
|
65
|
+
app_id: 'wxBBB',
|
|
66
|
+
app_secret: 'secretB',
|
|
67
|
+
account_name: 'Account B',
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
const result = await whoamiAction({ account: 'wxAAA', _credManager: manager })
|
|
71
|
+
|
|
72
|
+
expect(result.app_id).toBe('wxAAA')
|
|
73
|
+
expect(result.account_name).toBe('Account A')
|
|
74
|
+
expect(result.verified).toBe(true)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('returns verified false when credentials are invalid', async () => {
|
|
78
|
+
mockVerifyCredentials.mockImplementationOnce(() => Promise.resolve(false))
|
|
79
|
+
|
|
80
|
+
const manager = new WeChatBotCredentialManager(tempDir)
|
|
81
|
+
await manager.setCredentials({
|
|
82
|
+
app_id: 'wx1234567890',
|
|
83
|
+
app_secret: 'bad-secret',
|
|
84
|
+
account_name: 'Test Account',
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
const result = await whoamiAction({ _credManager: manager })
|
|
88
|
+
|
|
89
|
+
expect(result.app_id).toBe('wx1234567890')
|
|
90
|
+
expect(result.verified).toBe(false)
|
|
91
|
+
expect(result.error).toBeUndefined()
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test('returns error when client throws', async () => {
|
|
95
|
+
mockVerifyCredentials.mockImplementationOnce(() => Promise.reject(new Error('Network error')))
|
|
96
|
+
|
|
97
|
+
const manager = new WeChatBotCredentialManager(tempDir)
|
|
98
|
+
await manager.setCredentials({
|
|
99
|
+
app_id: 'wx1234567890',
|
|
100
|
+
app_secret: 'secret123',
|
|
101
|
+
account_name: 'Test Account',
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
const result = await whoamiAction({ _credManager: manager })
|
|
105
|
+
|
|
106
|
+
expect(result.error).toBeDefined()
|
|
107
|
+
expect(result.error).toContain('Network error')
|
|
108
|
+
})
|
|
109
|
+
})
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
|
|
3
|
+
import { formatOutput } from '@/shared/utils/output'
|
|
4
|
+
|
|
5
|
+
import { WeChatBotCredentialManager } from '../credential-manager'
|
|
6
|
+
import type { AccountOption } from './shared'
|
|
7
|
+
import { getClient } from './shared'
|
|
8
|
+
|
|
9
|
+
interface WhoamiResult {
|
|
10
|
+
app_id?: string | null
|
|
11
|
+
account_name?: string | null
|
|
12
|
+
verified?: boolean
|
|
13
|
+
error?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function whoamiAction(options: AccountOption): Promise<WhoamiResult> {
|
|
17
|
+
try {
|
|
18
|
+
const client = await getClient(options)
|
|
19
|
+
const verified = await client.verifyCredentials()
|
|
20
|
+
const credManager = options._credManager ?? new WeChatBotCredentialManager()
|
|
21
|
+
const creds = await credManager.getCredentials(options.account)
|
|
22
|
+
return {
|
|
23
|
+
app_id: creds?.app_id ?? null,
|
|
24
|
+
account_name: creds?.account_name ?? null,
|
|
25
|
+
verified,
|
|
26
|
+
}
|
|
27
|
+
} catch (error) {
|
|
28
|
+
return { error: (error as Error).message }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function cliOutput(result: WhoamiResult, pretty?: boolean): void {
|
|
33
|
+
console.log(formatOutput(result, pretty))
|
|
34
|
+
if (result.error) process.exit(1)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const whoamiCommand = new Command('whoami')
|
|
38
|
+
.description('Show current authenticated bot')
|
|
39
|
+
.option('--account <id>', 'Account ID to use')
|
|
40
|
+
.option('--pretty', 'Pretty print JSON output')
|
|
41
|
+
.action(async (opts: AccountOption) => {
|
|
42
|
+
cliOutput(await whoamiAction(opts), opts.pretty)
|
|
43
|
+
})
|