agent-messenger 2.4.0 → 2.5.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/release.yml +0 -12
- package/README.md +3 -3
- package/dist/package.json +1 -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.map +1 -1
- package/dist/src/platforms/kakaotalk/client.js +173 -21
- package/dist/src/platforms/kakaotalk/client.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/protocol/session.d.ts +4 -2
- package/dist/src/platforms/kakaotalk/protocol/session.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/session.js +25 -6
- 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 +12 -0
- package/dist/src/platforms/kakaotalk/types.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/types.js +6 -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/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 +24 -0
- 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/package.json +1 -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 +14 -8
- package/skills/agent-kakaotalk/references/common-patterns.md +1 -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 +204 -24
- 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/protocol/session.ts +27 -7
- package/src/platforms/kakaotalk/protocol/types.ts +9 -0
- package/src/platforms/kakaotalk/types.ts +12 -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/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
|
@@ -2,7 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
agent-whatsapp uses
|
|
5
|
+
agent-whatsapp uses [Baileys](https://github.com/WhiskeySockets/Baileys) to authenticate via QR code or pairing code. The CLI registers as a companion (linked) device, so your phone session is never affected. Each command connects on demand and disconnects when done.
|
|
6
|
+
|
|
7
|
+
## QR Code Login
|
|
8
|
+
|
|
9
|
+
### How It Works
|
|
10
|
+
|
|
11
|
+
1. The CLI generates a QR code and displays it in the terminal (and opens it in the browser)
|
|
12
|
+
2. You scan the QR code with WhatsApp on your phone: Settings > Linked Devices > Link a Device
|
|
13
|
+
3. Session credentials are stored locally for future commands
|
|
14
|
+
|
|
15
|
+
### Starting Login
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
agent-whatsapp auth login --qr
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
In interactive mode, a QR code is rendered in the terminal and opened in the browser. In non-interactive mode, JSON output is emitted:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{"next_action":"scan_qr","qr_url":"...","qr_html_path":"/tmp/whatsapp-qr-....html","message":"Scan with WhatsApp on your phone"}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
After scanning:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{"authenticated":true,"account_id":"qr-default"}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### QR Code Refresh
|
|
34
|
+
|
|
35
|
+
Baileys emits a new QR code every ~20 seconds. The terminal QR updates automatically. The browser tab is only opened once. If the QR expires after ~2 minutes, run `auth login --qr` again.
|
|
6
36
|
|
|
7
37
|
## Pairing Code Login
|
|
8
38
|
|
|
@@ -10,8 +40,8 @@ agent-whatsapp uses pairing code authentication via [Baileys](https://github.com
|
|
|
10
40
|
|
|
11
41
|
1. You provide your phone number in international format (e.g. `+1234567890`)
|
|
12
42
|
2. The CLI generates a numeric pairing code and displays it
|
|
13
|
-
3. You enter the code on your phone: WhatsApp > Settings > Linked Devices > Link
|
|
14
|
-
4. The CLI
|
|
43
|
+
3. You enter the code on your phone: WhatsApp > Settings > Linked Devices > Link with phone number
|
|
44
|
+
4. The CLI waits until you confirm on your phone
|
|
15
45
|
5. Session credentials are stored locally for future commands
|
|
16
46
|
|
|
17
47
|
### Starting Login
|
|
@@ -34,7 +64,7 @@ After confirmation on your phone:
|
|
|
34
64
|
|
|
35
65
|
### Login Failures
|
|
36
66
|
|
|
37
|
-
If the pairing code expires (typically after 60 seconds), run `auth login
|
|
67
|
+
If the pairing code expires (typically after 60 seconds), run `auth login --phone <number>` again for a fresh code. If your phone isn't connected to the internet, the pairing will time out.
|
|
38
68
|
|
|
39
69
|
## Multi-Account Management
|
|
40
70
|
|
|
@@ -121,7 +151,7 @@ Output when not authenticated:
|
|
|
121
151
|
|
|
122
152
|
```json
|
|
123
153
|
{
|
|
124
|
-
"error": "No WhatsApp account
|
|
154
|
+
"error": "No WhatsApp account configured. Run \"auth login --qr\" or \"auth login --phone <phone-number>\" first."
|
|
125
155
|
}
|
|
126
156
|
```
|
|
127
157
|
|
|
@@ -163,7 +193,7 @@ If commands start failing with auth errors:
|
|
|
163
193
|
agent-whatsapp auth status
|
|
164
194
|
|
|
165
195
|
# Re-link if needed
|
|
166
|
-
agent-whatsapp auth login --
|
|
196
|
+
agent-whatsapp auth login --qr
|
|
167
197
|
|
|
168
198
|
# Verify it worked
|
|
169
199
|
agent-whatsapp auth status
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agent-whatsappbot
|
|
3
3
|
description: Interact with WhatsApp using Cloud API credentials - send messages, manage templates
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.5.0
|
|
5
5
|
allowed-tools: Bash(agent-whatsappbot:*)
|
|
6
6
|
metadata:
|
|
7
7
|
openclaw:
|
|
@@ -169,6 +169,15 @@ agent-whatsappbot auth remove <account-id>
|
|
|
169
169
|
agent-whatsappbot auth clear
|
|
170
170
|
```
|
|
171
171
|
|
|
172
|
+
### Whoami Command
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# Show current authenticated bot
|
|
176
|
+
agent-whatsappbot whoami
|
|
177
|
+
agent-whatsappbot whoami --pretty
|
|
178
|
+
agent-whatsappbot whoami --account <account-id>
|
|
179
|
+
```
|
|
180
|
+
|
|
172
181
|
### Message Commands
|
|
173
182
|
|
|
174
183
|
```bash
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
createManagerCommand,
|
|
13
13
|
createMessageCommand,
|
|
14
14
|
createSnapshotCommand,
|
|
15
|
+
createWhoamiCommand,
|
|
15
16
|
} from './commands'
|
|
16
17
|
import { ensureChannelAuth } from './ensure-auth'
|
|
17
18
|
|
|
@@ -45,6 +46,7 @@ program.addCommand(createGroupCommand())
|
|
|
45
46
|
program.addCommand(createManagerCommand())
|
|
46
47
|
program.addCommand(createBotCommand())
|
|
47
48
|
program.addCommand(createSnapshotCommand())
|
|
49
|
+
program.addCommand(createWhoamiCommand())
|
|
48
50
|
|
|
49
51
|
program.parseAsync(process.argv)
|
|
50
52
|
|
|
@@ -5,3 +5,4 @@ export { createGroupCommand, groupCommand } from './group'
|
|
|
5
5
|
export { createManagerCommand, managerCommand } from './manager'
|
|
6
6
|
export { createMessageCommand, messageCommand } from './message'
|
|
7
7
|
export { createSnapshotCommand, snapshotCommand } from './snapshot'
|
|
8
|
+
export { createWhoamiCommand, whoamiCommand } from './whoami'
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, mock, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
const mockGetAccount = mock(() =>
|
|
4
|
+
Promise.resolve({
|
|
5
|
+
id: 'account-1',
|
|
6
|
+
name: 'Test User',
|
|
7
|
+
email: 'test@example.com',
|
|
8
|
+
emailVerified: true,
|
|
9
|
+
language: 'en',
|
|
10
|
+
country: 'US',
|
|
11
|
+
createdAt: 1700000000000,
|
|
12
|
+
}),
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
mock.module('./shared', () => ({
|
|
16
|
+
getClient: async () => ({
|
|
17
|
+
getAccount: mockGetAccount,
|
|
18
|
+
}),
|
|
19
|
+
getCurrentWorkspaceId: async () => 'ws-1',
|
|
20
|
+
}))
|
|
21
|
+
|
|
22
|
+
import { whoamiAction } from './whoami'
|
|
23
|
+
|
|
24
|
+
describe('whoami command', () => {
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
mockGetAccount.mockReset()
|
|
27
|
+
mockGetAccount.mockImplementation(() =>
|
|
28
|
+
Promise.resolve({
|
|
29
|
+
id: 'account-1',
|
|
30
|
+
name: 'Test User',
|
|
31
|
+
email: 'test@example.com',
|
|
32
|
+
emailVerified: true,
|
|
33
|
+
language: 'en',
|
|
34
|
+
country: 'US',
|
|
35
|
+
createdAt: 1700000000000,
|
|
36
|
+
}),
|
|
37
|
+
)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('whoamiAction returns account info', async () => {
|
|
41
|
+
const result = await whoamiAction({})
|
|
42
|
+
|
|
43
|
+
expect(mockGetAccount).toHaveBeenCalled()
|
|
44
|
+
expect(result.account).toEqual({
|
|
45
|
+
id: 'account-1',
|
|
46
|
+
name: 'Test User',
|
|
47
|
+
email: 'test@example.com',
|
|
48
|
+
email_verified: true,
|
|
49
|
+
language: 'en',
|
|
50
|
+
country: 'US',
|
|
51
|
+
created_at: 1700000000000,
|
|
52
|
+
})
|
|
53
|
+
expect(result.error).toBeUndefined()
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
test('whoamiAction returns error when getAccount fails', async () => {
|
|
57
|
+
mockGetAccount.mockImplementation(() => Promise.reject(new Error('Not authenticated')))
|
|
58
|
+
|
|
59
|
+
const result = await whoamiAction({})
|
|
60
|
+
|
|
61
|
+
expect(result.error).toBe('Not authenticated')
|
|
62
|
+
expect(result.account).toBeUndefined()
|
|
63
|
+
})
|
|
64
|
+
})
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
|
|
3
|
+
import { formatOutput } from '@/shared/utils/output'
|
|
4
|
+
|
|
5
|
+
import { getClient } from './shared'
|
|
6
|
+
|
|
7
|
+
interface ActionOptions {
|
|
8
|
+
workspace?: string
|
|
9
|
+
pretty?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface WhoamiResult {
|
|
13
|
+
account?: {
|
|
14
|
+
id: string
|
|
15
|
+
name: string
|
|
16
|
+
email: string
|
|
17
|
+
email_verified: boolean
|
|
18
|
+
language: string
|
|
19
|
+
country: string
|
|
20
|
+
created_at: number
|
|
21
|
+
}
|
|
22
|
+
error?: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function whoamiAction(options: ActionOptions = {}): Promise<WhoamiResult> {
|
|
26
|
+
try {
|
|
27
|
+
const client = await getClient(options)
|
|
28
|
+
const account = await client.getAccount()
|
|
29
|
+
return {
|
|
30
|
+
account: {
|
|
31
|
+
id: account.id,
|
|
32
|
+
name: account.name,
|
|
33
|
+
email: account.email,
|
|
34
|
+
email_verified: account.emailVerified,
|
|
35
|
+
language: account.language,
|
|
36
|
+
country: account.country,
|
|
37
|
+
created_at: account.createdAt,
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
} catch (error) {
|
|
41
|
+
return { error: (error as Error).message }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function cliOutput(result: WhoamiResult, pretty?: boolean): void {
|
|
46
|
+
console.log(formatOutput(result, pretty))
|
|
47
|
+
if (result.error) {
|
|
48
|
+
process.exit(1)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function createWhoamiCommand(): Command {
|
|
53
|
+
return new Command('whoami')
|
|
54
|
+
.description('Show current authenticated user')
|
|
55
|
+
.option('--workspace <id>', 'Workspace ID')
|
|
56
|
+
.option('--pretty', 'Pretty print JSON output')
|
|
57
|
+
.action(async (opts: ActionOptions) => {
|
|
58
|
+
cliOutput(await whoamiAction(opts), opts.pretty)
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const whoamiCommand = createWhoamiCommand()
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
managerCommand,
|
|
12
12
|
messageCommand,
|
|
13
13
|
snapshotCommand,
|
|
14
|
+
whoamiCommand,
|
|
14
15
|
} from './commands/index'
|
|
15
16
|
|
|
16
17
|
const program = new Command()
|
|
@@ -24,6 +25,7 @@ program
|
|
|
24
25
|
.option('--bot <name>', 'Bot name to use for sending messages')
|
|
25
26
|
|
|
26
27
|
program.addCommand(authCommand)
|
|
28
|
+
program.addCommand(whoamiCommand)
|
|
27
29
|
program.addCommand(messageCommand)
|
|
28
30
|
program.addCommand(chatCommand)
|
|
29
31
|
program.addCommand(groupCommand)
|
|
@@ -0,0 +1,104 @@
|
|
|
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 mockGetChannel = mock(() =>
|
|
8
|
+
Promise.resolve({
|
|
9
|
+
id: 'channel-id-123',
|
|
10
|
+
name: 'Test Channel',
|
|
11
|
+
homepageUrl: 'https://test.channel.io',
|
|
12
|
+
description: 'Test channel description',
|
|
13
|
+
}),
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
mock.module('../client', () => ({
|
|
17
|
+
ChannelBotClient: class MockChannelBotClient {
|
|
18
|
+
async login(_credentials?: { accessKey: string; accessSecret: string }) {
|
|
19
|
+
return this
|
|
20
|
+
}
|
|
21
|
+
getChannel = mockGetChannel
|
|
22
|
+
},
|
|
23
|
+
}))
|
|
24
|
+
|
|
25
|
+
import { ChannelBotCredentialManager } from '../credential-manager'
|
|
26
|
+
import { whoamiAction } from './whoami'
|
|
27
|
+
|
|
28
|
+
describe('whoami command', () => {
|
|
29
|
+
let tempDir: string
|
|
30
|
+
let originalEnv: NodeJS.ProcessEnv
|
|
31
|
+
|
|
32
|
+
beforeEach(async () => {
|
|
33
|
+
tempDir = join(tmpdir(), `channeltalkbot-whoami-test-${Date.now()}`)
|
|
34
|
+
await mkdir(tempDir, { recursive: true })
|
|
35
|
+
originalEnv = { ...process.env }
|
|
36
|
+
delete process.env.E2E_CHANNELBOT_ACCESS_KEY
|
|
37
|
+
delete process.env.E2E_CHANNELBOT_ACCESS_SECRET
|
|
38
|
+
mockGetChannel.mockClear()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
if (existsSync(tempDir)) {
|
|
43
|
+
rmSync(tempDir, { recursive: true })
|
|
44
|
+
}
|
|
45
|
+
process.env = originalEnv
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('returns channel info for current workspace', async () => {
|
|
49
|
+
const manager = new ChannelBotCredentialManager(tempDir)
|
|
50
|
+
await manager.setCredentials({
|
|
51
|
+
workspace_id: 'workspace1',
|
|
52
|
+
workspace_name: 'Test Workspace',
|
|
53
|
+
access_key: 'key123',
|
|
54
|
+
access_secret: 'secret123',
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const result = await whoamiAction({ _credManager: manager })
|
|
58
|
+
|
|
59
|
+
expect(result.id).toBe('channel-id-123')
|
|
60
|
+
expect(result.name).toBe('Test Channel')
|
|
61
|
+
expect(result.homepage_url).toBe('https://test.channel.io')
|
|
62
|
+
expect(result.description).toBe('Test channel description')
|
|
63
|
+
expect(result.error).toBeUndefined()
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test('returns channel info for specific --workspace', async () => {
|
|
67
|
+
const manager = new ChannelBotCredentialManager(tempDir)
|
|
68
|
+
await manager.setCredentials({
|
|
69
|
+
workspace_id: 'workspace1',
|
|
70
|
+
workspace_name: 'Workspace 1',
|
|
71
|
+
access_key: 'key1',
|
|
72
|
+
access_secret: 'secret1',
|
|
73
|
+
})
|
|
74
|
+
await manager.setCredentials({
|
|
75
|
+
workspace_id: 'workspace2',
|
|
76
|
+
workspace_name: 'Workspace 2',
|
|
77
|
+
access_key: 'key2',
|
|
78
|
+
access_secret: 'secret2',
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
const result = await whoamiAction({ workspace: 'workspace1', _credManager: manager })
|
|
82
|
+
|
|
83
|
+
expect(result.id).toBe('channel-id-123')
|
|
84
|
+
expect(result.name).toBe('Test Channel')
|
|
85
|
+
expect(mockGetChannel).toHaveBeenCalledTimes(1)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
test('returns error when client throws', async () => {
|
|
89
|
+
mockGetChannel.mockImplementationOnce(() => Promise.reject(new Error('API Error')))
|
|
90
|
+
|
|
91
|
+
const manager = new ChannelBotCredentialManager(tempDir)
|
|
92
|
+
await manager.setCredentials({
|
|
93
|
+
workspace_id: 'workspace1',
|
|
94
|
+
workspace_name: 'Test Workspace',
|
|
95
|
+
access_key: 'key123',
|
|
96
|
+
access_secret: 'secret123',
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
const result = await whoamiAction({ _credManager: manager })
|
|
100
|
+
|
|
101
|
+
expect(result.error).toBeDefined()
|
|
102
|
+
expect(result.error).toContain('API Error')
|
|
103
|
+
})
|
|
104
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
|
|
3
|
+
import { formatOutput } from '@/shared/utils/output'
|
|
4
|
+
|
|
5
|
+
import type { WorkspaceOption } from './shared'
|
|
6
|
+
import { getClient } from './shared'
|
|
7
|
+
|
|
8
|
+
interface WhoamiResult {
|
|
9
|
+
id?: string
|
|
10
|
+
name?: string
|
|
11
|
+
homepage_url?: string
|
|
12
|
+
description?: string
|
|
13
|
+
error?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function whoamiAction(options: WorkspaceOption): Promise<WhoamiResult> {
|
|
17
|
+
try {
|
|
18
|
+
const client = await getClient(options)
|
|
19
|
+
const channel = await client.getChannel()
|
|
20
|
+
return {
|
|
21
|
+
id: channel.id,
|
|
22
|
+
name: channel.name,
|
|
23
|
+
homepage_url: channel.homepageUrl,
|
|
24
|
+
description: channel.description,
|
|
25
|
+
}
|
|
26
|
+
} catch (error) {
|
|
27
|
+
return { error: (error as Error).message }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function cliOutput(result: WhoamiResult, pretty?: boolean): void {
|
|
32
|
+
console.log(formatOutput(result, pretty))
|
|
33
|
+
if (result.error) process.exit(1)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const whoamiCommand = new Command('whoami')
|
|
37
|
+
.description('Show current authenticated bot')
|
|
38
|
+
.option('--workspace <id>', 'Workspace ID to use')
|
|
39
|
+
.option('--pretty', 'Pretty print JSON output')
|
|
40
|
+
.action(async (opts: WorkspaceOption) => {
|
|
41
|
+
cliOutput(await whoamiAction(opts), opts.pretty)
|
|
42
|
+
})
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
snapshotCommand,
|
|
21
21
|
threadCommand,
|
|
22
22
|
userCommand,
|
|
23
|
+
whoamiCommand,
|
|
23
24
|
} from './commands'
|
|
24
25
|
import { ensureDiscordAuth } from './ensure-auth'
|
|
25
26
|
|
|
@@ -60,6 +61,7 @@ program.addCommand(reactionCommand)
|
|
|
60
61
|
program.addCommand(snapshotCommand)
|
|
61
62
|
program.addCommand(threadCommand)
|
|
62
63
|
program.addCommand(userCommand)
|
|
64
|
+
program.addCommand(whoamiCommand)
|
|
63
65
|
|
|
64
66
|
program.parse(process.argv)
|
|
65
67
|
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { afterEach, beforeEach, expect, spyOn, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
import { DiscordClient } from '@/platforms/discord/client'
|
|
4
|
+
import { DiscordCredentialManager } from '@/platforms/discord/credential-manager'
|
|
5
|
+
import { whoamiAction, whoamiCommand } from '@/platforms/discord/commands/whoami'
|
|
6
|
+
|
|
7
|
+
let credManagerSpy: ReturnType<typeof spyOn>
|
|
8
|
+
let clientTestAuthSpy: ReturnType<typeof spyOn>
|
|
9
|
+
let consoleLogSpy: ReturnType<typeof spyOn>
|
|
10
|
+
let processExitSpy: ReturnType<typeof spyOn>
|
|
11
|
+
|
|
12
|
+
const mockConfig = {
|
|
13
|
+
token: 'test-discord-token',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const mockUser = {
|
|
17
|
+
id: 'user123',
|
|
18
|
+
username: 'testuser',
|
|
19
|
+
global_name: 'Test User',
|
|
20
|
+
avatar: 'avatar_hash',
|
|
21
|
+
bot: false,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
credManagerSpy = spyOn(DiscordCredentialManager.prototype, 'load').mockResolvedValue(mockConfig)
|
|
26
|
+
clientTestAuthSpy = spyOn(DiscordClient.prototype, 'testAuth').mockResolvedValue(mockUser)
|
|
27
|
+
consoleLogSpy = spyOn(console, 'log').mockImplementation(() => {})
|
|
28
|
+
processExitSpy = spyOn(process, 'exit').mockImplementation((_code?: number) => undefined as never)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
credManagerSpy?.mockRestore()
|
|
33
|
+
clientTestAuthSpy?.mockRestore()
|
|
34
|
+
consoleLogSpy?.mockRestore()
|
|
35
|
+
processExitSpy?.mockRestore()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('whoami command is defined with correct name and description', () => {
|
|
39
|
+
expect(whoamiCommand).toBeDefined()
|
|
40
|
+
expect(whoamiCommand.name()).toBe('whoami')
|
|
41
|
+
expect(whoamiCommand.description()).toBe('Show current authenticated user')
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('whoami command has --pretty option', () => {
|
|
45
|
+
const options = whoamiCommand.options
|
|
46
|
+
const hasPretty = options.some((opt: { long?: string }) => opt.long === '--pretty')
|
|
47
|
+
expect(hasPretty).toBe(true)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('whoami outputs expected user fields', async () => {
|
|
51
|
+
await whoamiAction({})
|
|
52
|
+
|
|
53
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
54
|
+
JSON.stringify({
|
|
55
|
+
id: 'user123',
|
|
56
|
+
username: 'testuser',
|
|
57
|
+
global_name: 'Test User',
|
|
58
|
+
avatar: 'avatar_hash',
|
|
59
|
+
bot: false,
|
|
60
|
+
}),
|
|
61
|
+
)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test('whoami outputs pretty-printed JSON when pretty is true', async () => {
|
|
65
|
+
await whoamiAction({ pretty: true })
|
|
66
|
+
|
|
67
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
68
|
+
JSON.stringify(
|
|
69
|
+
{
|
|
70
|
+
id: 'user123',
|
|
71
|
+
username: 'testuser',
|
|
72
|
+
global_name: 'Test User',
|
|
73
|
+
avatar: 'avatar_hash',
|
|
74
|
+
bot: false,
|
|
75
|
+
},
|
|
76
|
+
null,
|
|
77
|
+
2,
|
|
78
|
+
),
|
|
79
|
+
)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
test('whoami exits with error when not authenticated', async () => {
|
|
83
|
+
credManagerSpy.mockResolvedValue({ token: undefined })
|
|
84
|
+
|
|
85
|
+
await whoamiAction({})
|
|
86
|
+
|
|
87
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
88
|
+
JSON.stringify({ error: 'Not authenticated. Run "auth extract" first.' }),
|
|
89
|
+
)
|
|
90
|
+
expect(processExitSpy).toHaveBeenCalledWith(1)
|
|
91
|
+
})
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { handleError } from '@/shared/utils/error-handler'
|
|
3
|
+
import { formatOutput } from '@/shared/utils/output'
|
|
4
|
+
import { DiscordClient } from '../client'
|
|
5
|
+
import { DiscordCredentialManager } from '../credential-manager'
|
|
6
|
+
|
|
7
|
+
export async function whoamiAction(options: { pretty?: boolean }): Promise<void> {
|
|
8
|
+
try {
|
|
9
|
+
const credManager = new DiscordCredentialManager()
|
|
10
|
+
const config = await credManager.load()
|
|
11
|
+
|
|
12
|
+
if (!config.token) {
|
|
13
|
+
console.log(formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty))
|
|
14
|
+
return process.exit(1)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const client = await new DiscordClient().login({ token: config.token })
|
|
18
|
+
const user = await client.testAuth()
|
|
19
|
+
|
|
20
|
+
const output = {
|
|
21
|
+
id: user.id,
|
|
22
|
+
username: user.username,
|
|
23
|
+
global_name: user.global_name,
|
|
24
|
+
avatar: user.avatar,
|
|
25
|
+
bot: user.bot,
|
|
26
|
+
}
|
|
27
|
+
console.log(formatOutput(output, options.pretty))
|
|
28
|
+
} catch (error) {
|
|
29
|
+
handleError(error as Error)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const whoamiCommand = new Command('whoami')
|
|
34
|
+
.description('Show current authenticated user')
|
|
35
|
+
.option('--pretty', 'Pretty print JSON output')
|
|
36
|
+
.action(whoamiAction)
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
snapshotCommand,
|
|
14
14
|
threadCommand,
|
|
15
15
|
userCommand,
|
|
16
|
+
whoamiCommand,
|
|
16
17
|
} from './commands/index'
|
|
17
18
|
|
|
18
19
|
const program = new Command()
|
|
@@ -25,6 +26,7 @@ program
|
|
|
25
26
|
.option('--server <id>', 'Server ID to use')
|
|
26
27
|
|
|
27
28
|
program.addCommand(authCommand)
|
|
29
|
+
program.addCommand(whoamiCommand)
|
|
28
30
|
program.addCommand(serverCommand)
|
|
29
31
|
program.addCommand(messageCommand)
|
|
30
32
|
program.addCommand(channelCommand)
|
|
@@ -0,0 +1,96 @@
|
|
|
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 mockTestAuth = mock(() =>
|
|
8
|
+
Promise.resolve({
|
|
9
|
+
id: 'bot-user-id',
|
|
10
|
+
username: 'testbot',
|
|
11
|
+
global_name: 'Test Bot',
|
|
12
|
+
avatar: 'avatar123',
|
|
13
|
+
bot: true,
|
|
14
|
+
}),
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
mock.module('../client', () => ({
|
|
18
|
+
DiscordBotClient: class MockDiscordBotClient {
|
|
19
|
+
async login(_credentials?: any) {
|
|
20
|
+
return this
|
|
21
|
+
}
|
|
22
|
+
testAuth = mockTestAuth
|
|
23
|
+
},
|
|
24
|
+
}))
|
|
25
|
+
|
|
26
|
+
import { DiscordBotCredentialManager } from '../credential-manager'
|
|
27
|
+
import { whoamiAction } from './whoami'
|
|
28
|
+
|
|
29
|
+
describe('whoami command', () => {
|
|
30
|
+
let tempDir: string
|
|
31
|
+
let originalEnv: NodeJS.ProcessEnv
|
|
32
|
+
|
|
33
|
+
beforeEach(async () => {
|
|
34
|
+
tempDir = join(tmpdir(), `discordbot-whoami-test-${Date.now()}`)
|
|
35
|
+
await mkdir(tempDir, { recursive: true })
|
|
36
|
+
originalEnv = { ...process.env }
|
|
37
|
+
delete process.env.E2E_DISCORDBOT_TOKEN
|
|
38
|
+
mockTestAuth.mockClear()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
if (existsSync(tempDir)) {
|
|
43
|
+
rmSync(tempDir, { recursive: true })
|
|
44
|
+
}
|
|
45
|
+
process.env = originalEnv
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('returns auth info for current bot', async () => {
|
|
49
|
+
const manager = new DiscordBotCredentialManager(tempDir)
|
|
50
|
+
await manager.setCredentials({
|
|
51
|
+
token: 'bot-token-123',
|
|
52
|
+
bot_id: 'bot1',
|
|
53
|
+
bot_name: 'Test Bot',
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const result = await whoamiAction({ _credManager: manager })
|
|
57
|
+
|
|
58
|
+
expect(result.id).toBe('bot-user-id')
|
|
59
|
+
expect(result.username).toBe('testbot')
|
|
60
|
+
expect(result.global_name).toBe('Test Bot')
|
|
61
|
+
expect(result.avatar).toBe('avatar123')
|
|
62
|
+
expect(result.bot).toBe(true)
|
|
63
|
+
expect(result.error).toBeUndefined()
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test('returns auth info for specific --bot', async () => {
|
|
67
|
+
const manager = new DiscordBotCredentialManager(tempDir)
|
|
68
|
+
await manager.setCredentials({
|
|
69
|
+
token: 'bot-token-123',
|
|
70
|
+
bot_id: 'deploy',
|
|
71
|
+
bot_name: 'Deploy Bot',
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
const result = await whoamiAction({ bot: 'deploy', _credManager: manager })
|
|
75
|
+
|
|
76
|
+
expect(result.id).toBe('bot-user-id')
|
|
77
|
+
expect(result.username).toBe('testbot')
|
|
78
|
+
expect(mockTestAuth).toHaveBeenCalledTimes(1)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test('returns error when client throws', async () => {
|
|
82
|
+
mockTestAuth.mockImplementationOnce(() => Promise.reject(new Error('API Error')))
|
|
83
|
+
|
|
84
|
+
const manager = new DiscordBotCredentialManager(tempDir)
|
|
85
|
+
await manager.setCredentials({
|
|
86
|
+
token: 'bot-token-123',
|
|
87
|
+
bot_id: 'bot1',
|
|
88
|
+
bot_name: 'Test Bot',
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
const result = await whoamiAction({ _credManager: manager })
|
|
92
|
+
|
|
93
|
+
expect(result.error).toBeDefined()
|
|
94
|
+
expect(result.error).toContain('API Error')
|
|
95
|
+
})
|
|
96
|
+
})
|