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
|
@@ -13,6 +13,15 @@ const mockGetProfile = mock(() =>
|
|
|
13
13
|
user_id: 'user-1',
|
|
14
14
|
nickname: 'Test User',
|
|
15
15
|
profile_image_url: 'https://example.com/avatar.jpg',
|
|
16
|
+
original_profile_image_url: 'https://example.com/avatar_orig.jpg',
|
|
17
|
+
background_image_url: 'https://example.com/bg.jpg',
|
|
18
|
+
original_background_image_url: 'https://example.com/bg_orig.jpg',
|
|
19
|
+
fullname: 'Real Name',
|
|
20
|
+
status_message: 'Hello!',
|
|
21
|
+
account_display_id: 'testuser',
|
|
22
|
+
account_email: 'test@example.com',
|
|
23
|
+
pstn_number: '+821012345678',
|
|
24
|
+
email_verified: true,
|
|
16
25
|
}),
|
|
17
26
|
)
|
|
18
27
|
|
|
@@ -24,9 +33,9 @@ mock.module('./shared', () => ({
|
|
|
24
33
|
withKakaoClient: mockWithKakaoClient,
|
|
25
34
|
}))
|
|
26
35
|
|
|
27
|
-
import {
|
|
36
|
+
import { whoamiCommand } from './whoami'
|
|
28
37
|
|
|
29
|
-
describe('
|
|
38
|
+
describe('whoami command', () => {
|
|
30
39
|
let consoleLogSpy: ReturnType<typeof mock>
|
|
31
40
|
|
|
32
41
|
beforeEach(() => {
|
|
@@ -43,6 +52,15 @@ describe('profile command', () => {
|
|
|
43
52
|
user_id: 'user-1',
|
|
44
53
|
nickname: 'Test User',
|
|
45
54
|
profile_image_url: 'https://example.com/avatar.jpg',
|
|
55
|
+
original_profile_image_url: 'https://example.com/avatar_orig.jpg',
|
|
56
|
+
background_image_url: 'https://example.com/bg.jpg',
|
|
57
|
+
original_background_image_url: 'https://example.com/bg_orig.jpg',
|
|
58
|
+
fullname: 'Real Name',
|
|
59
|
+
status_message: 'Hello!',
|
|
60
|
+
account_display_id: 'testuser',
|
|
61
|
+
account_email: 'test@example.com',
|
|
62
|
+
pstn_number: '+821012345678',
|
|
63
|
+
email_verified: true,
|
|
46
64
|
}),
|
|
47
65
|
)
|
|
48
66
|
|
|
@@ -55,7 +73,7 @@ describe('profile command', () => {
|
|
|
55
73
|
})
|
|
56
74
|
|
|
57
75
|
test('outputs profile information', async () => {
|
|
58
|
-
await
|
|
76
|
+
await whoamiCommand.parseAsync([], { from: 'user' })
|
|
59
77
|
|
|
60
78
|
expect(mockGetProfile).toHaveBeenCalled()
|
|
61
79
|
const output = JSON.parse(consoleLogSpy.mock.calls[0][0])
|
|
@@ -64,8 +82,22 @@ describe('profile command', () => {
|
|
|
64
82
|
expect(output.profile_image_url).toBe('https://example.com/avatar.jpg')
|
|
65
83
|
})
|
|
66
84
|
|
|
85
|
+
test('outputs enriched profile fields', async () => {
|
|
86
|
+
await whoamiCommand.parseAsync([], { from: 'user' })
|
|
87
|
+
|
|
88
|
+
const output = JSON.parse(consoleLogSpy.mock.calls[0][0])
|
|
89
|
+
expect(output.background_image_url).toBe('https://example.com/bg.jpg')
|
|
90
|
+
expect(output.original_background_image_url).toBe('https://example.com/bg_orig.jpg')
|
|
91
|
+
expect(output.fullname).toBe('Real Name')
|
|
92
|
+
expect(output.status_message).toBe('Hello!')
|
|
93
|
+
expect(output.account_display_id).toBe('testuser')
|
|
94
|
+
expect(output.account_email).toBe('test@example.com')
|
|
95
|
+
expect(output.pstn_number).toBe('+821012345678')
|
|
96
|
+
expect(output.email_verified).toBe(true)
|
|
97
|
+
})
|
|
98
|
+
|
|
67
99
|
test('passes account option to withKakaoClient', async () => {
|
|
68
|
-
await
|
|
100
|
+
await whoamiCommand.parseAsync(['--account', 'my-account'], { from: 'user' })
|
|
69
101
|
|
|
70
102
|
expect(mockWithKakaoClient).toHaveBeenCalledWith(
|
|
71
103
|
expect.objectContaining({ account: 'my-account' }),
|
|
@@ -74,7 +106,7 @@ describe('profile command', () => {
|
|
|
74
106
|
})
|
|
75
107
|
|
|
76
108
|
test('outputs profile with pretty flag', async () => {
|
|
77
|
-
await
|
|
109
|
+
await whoamiCommand.parseAsync(['--pretty'], { from: 'user' })
|
|
78
110
|
|
|
79
111
|
expect(mockGetProfile).toHaveBeenCalled()
|
|
80
112
|
const rawOutput = consoleLogSpy.mock.calls[0][0]
|
|
@@ -5,7 +5,7 @@ import { formatOutput } from '@/shared/utils/output'
|
|
|
5
5
|
|
|
6
6
|
import { withKakaoClient } from './shared'
|
|
7
7
|
|
|
8
|
-
async function
|
|
8
|
+
async function whoamiAction(options: { account?: string; pretty?: boolean }): Promise<void> {
|
|
9
9
|
try {
|
|
10
10
|
const profile = await withKakaoClient(options, (client) => client.getProfile())
|
|
11
11
|
console.log(formatOutput(profile, options.pretty))
|
|
@@ -14,8 +14,8 @@ async function profileAction(options: { account?: string; pretty?: boolean }): P
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export const
|
|
18
|
-
.description('Show
|
|
17
|
+
export const whoamiCommand = new Command('whoami')
|
|
18
|
+
.description('Show current authenticated user')
|
|
19
19
|
.option('--account <id>', 'Use a specific KakaoTalk account')
|
|
20
20
|
.option('--pretty', 'Pretty print JSON output')
|
|
21
|
-
.action(
|
|
21
|
+
.action(whoamiAction)
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
PROTOCOL_VERSION,
|
|
15
15
|
} from './config'
|
|
16
16
|
import { LocoConnection } from './connection'
|
|
17
|
-
import type { BookingResponse, CheckinResponse, LoginListResponse, LocoPacket } from './types'
|
|
17
|
+
import type { BookingResponse, CheckinResponse, LoginListResponse, LocoPacket, SyncState } from './types'
|
|
18
18
|
|
|
19
19
|
export class LocoSession {
|
|
20
20
|
private connection: LocoConnection | null = null
|
|
@@ -22,7 +22,7 @@ export class LocoSession {
|
|
|
22
22
|
private pushHandler: ((packet: LocoPacket) => void) | null = null
|
|
23
23
|
private closeHandler: (() => void) | null = null
|
|
24
24
|
|
|
25
|
-
async login(oauthToken: string, userId: string, deviceUuid: string): Promise<LoginListResponse> {
|
|
25
|
+
async login(oauthToken: string, userId: string, deviceUuid: string, syncState?: SyncState): Promise<LoginListResponse> {
|
|
26
26
|
const { host, port } = await this.bookAndCheckin(userId)
|
|
27
27
|
|
|
28
28
|
this.connection = new LocoConnection()
|
|
@@ -35,6 +35,13 @@ export class LocoSession {
|
|
|
35
35
|
this.connection.onClose(this.closeHandler)
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
const chatIds = syncState?.chatIds.map((id) => new Long(id.low, id.high)) ?? []
|
|
39
|
+
const maxIds = syncState?.maxIds.map((id) => new Long(id.low, id.high)) ?? []
|
|
40
|
+
const lastTokenId = syncState
|
|
41
|
+
? new Long(syncState.lastTokenId.low, syncState.lastTokenId.high)
|
|
42
|
+
: Long.fromNumber(0)
|
|
43
|
+
const lbk = syncState?.lbk ?? 0
|
|
44
|
+
|
|
38
45
|
const response = await this.connection.sendPacket('LOGINLIST', {
|
|
39
46
|
appVer: APP_VERSION,
|
|
40
47
|
prtVer: PROTOCOL_VERSION,
|
|
@@ -45,11 +52,11 @@ export class LocoSession {
|
|
|
45
52
|
oauthToken,
|
|
46
53
|
ntype: 0,
|
|
47
54
|
MCCMNC: MCCMNC,
|
|
48
|
-
revision: 0,
|
|
49
|
-
chatIds
|
|
50
|
-
maxIds
|
|
51
|
-
lastTokenId
|
|
52
|
-
lbk
|
|
55
|
+
revision: syncState?.revision ?? 0,
|
|
56
|
+
chatIds,
|
|
57
|
+
maxIds,
|
|
58
|
+
lastTokenId,
|
|
59
|
+
lbk,
|
|
53
60
|
rp: new Binary(Buffer.from([0x00, 0x00, 0xff, 0xff, 0x00, 0x00])),
|
|
54
61
|
bg: false,
|
|
55
62
|
})
|
|
@@ -117,6 +124,19 @@ export class LocoSession {
|
|
|
117
124
|
})
|
|
118
125
|
}
|
|
119
126
|
|
|
127
|
+
async getChatLogs(chatIds: Long[], sinces: Long[]): Promise<LocoPacket> {
|
|
128
|
+
if (!this.connection) throw new Error('Not connected')
|
|
129
|
+
return this.connection.sendPacket('MCHATLOGS', {
|
|
130
|
+
chatIds,
|
|
131
|
+
sinces,
|
|
132
|
+
})
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async getChatInfo(chatId: Long): Promise<LocoPacket> {
|
|
136
|
+
if (!this.connection) throw new Error('Not connected')
|
|
137
|
+
return this.connection.sendPacket('CHATONROOM', { chatId })
|
|
138
|
+
}
|
|
139
|
+
|
|
120
140
|
async getChatList(lastTokenId?: Long, lastChatId?: Long): Promise<LocoPacket> {
|
|
121
141
|
if (!this.connection) throw new Error('Not connected')
|
|
122
142
|
return this.connection.sendPacket('LCHATLIST', {
|
|
@@ -25,6 +25,15 @@ export interface ChatListResponse {
|
|
|
25
25
|
[key: string]: unknown
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
export interface SyncState {
|
|
29
|
+
version: 2
|
|
30
|
+
revision: number
|
|
31
|
+
chatIds: Array<{ low: number; high: number }>
|
|
32
|
+
maxIds: Array<{ low: number; high: number }>
|
|
33
|
+
lastTokenId: { low: number; high: number }
|
|
34
|
+
lbk: number
|
|
35
|
+
}
|
|
36
|
+
|
|
28
37
|
// LOGINLIST uses short BSON field names: c=chatId, t=type, a=activeMembers, etc.
|
|
29
38
|
export interface LoginListResponse extends ChatListResponse {
|
|
30
39
|
userId: number
|
|
@@ -130,8 +130,14 @@ export interface KakaoProfile {
|
|
|
130
130
|
nickname: string
|
|
131
131
|
profile_image_url: string | null
|
|
132
132
|
original_profile_image_url: string | null
|
|
133
|
+
background_image_url?: string | null
|
|
134
|
+
original_background_image_url?: string | null
|
|
135
|
+
fullname?: string | null
|
|
133
136
|
status_message: string | null
|
|
134
137
|
account_display_id: string | null
|
|
138
|
+
account_email?: string | null
|
|
139
|
+
pstn_number?: string | null
|
|
140
|
+
email_verified?: boolean | null
|
|
135
141
|
}
|
|
136
142
|
|
|
137
143
|
export const KakaoProfileSchema = z.object({
|
|
@@ -139,8 +145,14 @@ export const KakaoProfileSchema = z.object({
|
|
|
139
145
|
nickname: z.string(),
|
|
140
146
|
profile_image_url: z.string().nullable(),
|
|
141
147
|
original_profile_image_url: z.string().nullable(),
|
|
148
|
+
background_image_url: z.string().nullable().optional(),
|
|
149
|
+
original_background_image_url: z.string().nullable().optional(),
|
|
150
|
+
fullname: z.string().nullable().optional(),
|
|
142
151
|
status_message: z.string().nullable(),
|
|
143
152
|
account_display_id: z.string().nullable(),
|
|
153
|
+
account_email: z.string().nullable().optional(),
|
|
154
|
+
pstn_number: z.string().nullable().optional(),
|
|
155
|
+
email_verified: z.boolean().nullable().optional(),
|
|
144
156
|
})
|
|
145
157
|
|
|
146
158
|
export const KakaoAccountCredentialsSchema = z.object({
|
|
@@ -4,7 +4,7 @@ import type { Command as CommandType } from 'commander'
|
|
|
4
4
|
import { Command } from 'commander'
|
|
5
5
|
|
|
6
6
|
import pkg from '../../../package.json' with { type: 'json' }
|
|
7
|
-
import { authCommand, chatCommand, friendCommand, messageCommand,
|
|
7
|
+
import { authCommand, chatCommand, friendCommand, messageCommand, whoamiCommand } from './commands/index'
|
|
8
8
|
import { ensureLineAuth } from './ensure-auth'
|
|
9
9
|
|
|
10
10
|
function isAuthCommand(command: CommandType): boolean {
|
|
@@ -32,7 +32,7 @@ program.addCommand(authCommand)
|
|
|
32
32
|
program.addCommand(chatCommand)
|
|
33
33
|
program.addCommand(friendCommand)
|
|
34
34
|
program.addCommand(messageCommand)
|
|
35
|
-
program.addCommand(
|
|
35
|
+
program.addCommand(whoamiCommand)
|
|
36
36
|
|
|
37
37
|
program.parse(process.argv)
|
|
38
38
|
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process'
|
|
2
|
-
import { writeFileSync, unlinkSync } from 'node:fs'
|
|
3
|
-
import { tmpdir } from 'node:os'
|
|
4
|
-
import { join } from 'node:path'
|
|
5
|
-
|
|
6
1
|
import { Command } from 'commander'
|
|
7
|
-
import QRCode from 'qrcode'
|
|
8
2
|
|
|
9
3
|
import { handleError } from '@/shared/utils/error-handler'
|
|
10
4
|
import { formatOutput } from '@/shared/utils/output'
|
|
5
|
+
import { displayQR } from '@/shared/utils/qr'
|
|
11
6
|
import { info } from '@/shared/utils/stderr'
|
|
12
7
|
|
|
13
8
|
import { LineClient } from '../client'
|
|
@@ -22,34 +17,6 @@ function getDefaultDevice(): LineDevice {
|
|
|
22
17
|
return 'ANDROIDSECONDARY'
|
|
23
18
|
}
|
|
24
19
|
|
|
25
|
-
async function createQRHtmlFile(url: string): Promise<string> {
|
|
26
|
-
const svgString = await QRCode.toString(url, { type: 'svg', margin: 2 })
|
|
27
|
-
const html = `<!DOCTYPE html>
|
|
28
|
-
<html><head><meta charset="utf-8"><title>LINE QR Login</title>
|
|
29
|
-
<style>body{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;margin:0;font-family:-apple-system,system-ui,sans-serif;background:#06C755}
|
|
30
|
-
.card{background:#fff;border-radius:16px;padding:40px;text-align:center;box-shadow:0 4px 24px rgba(0,0,0,.15)}
|
|
31
|
-
h1{margin:0 0 8px;font-size:22px;color:#111}p{margin:0 0 24px;color:#666;font-size:14px}
|
|
32
|
-
svg{width:280px;height:280px}</style></head>
|
|
33
|
-
<body><div class="card"><h1>LINE Login</h1><p>Scan with the LINE mobile app</p>${svgString}</div></body></html>`
|
|
34
|
-
|
|
35
|
-
const htmlPath = join(tmpdir(), `line-qr-${Date.now()}.html`)
|
|
36
|
-
writeFileSync(htmlPath, html)
|
|
37
|
-
setTimeout(() => { try { unlinkSync(htmlPath) } catch {} }, 300_000).unref()
|
|
38
|
-
return htmlPath
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function openInBrowser(filePath: string): void {
|
|
42
|
-
try {
|
|
43
|
-
if (process.platform === 'darwin') {
|
|
44
|
-
execSync(`open "${filePath}"`, { stdio: 'ignore' })
|
|
45
|
-
} else if (process.platform === 'win32') {
|
|
46
|
-
execSync(`start "" "${filePath}"`, { stdio: 'ignore' })
|
|
47
|
-
} else {
|
|
48
|
-
execSync(`xdg-open "${filePath}"`, { stdio: 'ignore' })
|
|
49
|
-
}
|
|
50
|
-
} catch {}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
20
|
async function loginAction(options: {
|
|
54
21
|
email?: string
|
|
55
22
|
password?: string
|
|
@@ -76,18 +43,23 @@ async function loginAction(options: {
|
|
|
76
43
|
const profile = await client.getProfile()
|
|
77
44
|
const credentials = { ...tempCredentials, account_id: profile.mid, display_name: profile.display_name }
|
|
78
45
|
await credManager.setAccount(credentials)
|
|
79
|
-
console.log(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
46
|
+
console.log(
|
|
47
|
+
formatOutput(
|
|
48
|
+
{
|
|
49
|
+
authenticated: true,
|
|
50
|
+
account_id: profile.mid,
|
|
51
|
+
display_name: profile.display_name,
|
|
52
|
+
device,
|
|
53
|
+
},
|
|
54
|
+
options.pretty,
|
|
55
|
+
),
|
|
56
|
+
)
|
|
85
57
|
} else if (options.email && options.password) {
|
|
86
58
|
const result = await client.loginWithEmail({
|
|
87
59
|
email: options.email,
|
|
88
60
|
password: options.password,
|
|
89
61
|
device,
|
|
90
|
-
|
|
62
|
+
onPincode: (pin) => {
|
|
91
63
|
if (interactive) {
|
|
92
64
|
info(`\nEnter this PIN in the LINE mobile app: ${pin}\n`)
|
|
93
65
|
}
|
|
@@ -98,27 +70,14 @@ async function loginAction(options: {
|
|
|
98
70
|
const result = await client.loginWithQR({
|
|
99
71
|
device,
|
|
100
72
|
onQRUrl: async (url) => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
} catch {
|
|
110
|
-
info(`\nOpen the QR code in the browser window, or scan this URL:\n${url}\n`)
|
|
111
|
-
}
|
|
112
|
-
} else {
|
|
113
|
-
console.log(formatOutput({
|
|
114
|
-
next_action: 'scan_qr',
|
|
115
|
-
qr_url: url,
|
|
116
|
-
qr_html_path: htmlPath,
|
|
117
|
-
message: htmlPath
|
|
118
|
-
? 'QR code opened in browser. Scan with LINE mobile app to complete login.'
|
|
119
|
-
: 'QR code generated. Open qr_url to scan with LINE mobile app.',
|
|
120
|
-
}, options.pretty))
|
|
121
|
-
}
|
|
73
|
+
await displayQR(url, {
|
|
74
|
+
platform: 'LINE',
|
|
75
|
+
brandColor: '#06C755',
|
|
76
|
+
scanInstruction: 'Scan with the LINE mobile app',
|
|
77
|
+
interactive,
|
|
78
|
+
formatOutput,
|
|
79
|
+
pretty: options.pretty,
|
|
80
|
+
})
|
|
122
81
|
},
|
|
123
82
|
onPincode: (pin) => {
|
|
124
83
|
info(`\nEnter this PIN in the LINE mobile app: ${pin}\n`)
|
|
@@ -141,13 +100,18 @@ async function statusAction(options: { pretty?: boolean; account?: string }): Pr
|
|
|
141
100
|
return
|
|
142
101
|
}
|
|
143
102
|
|
|
144
|
-
console.log(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
103
|
+
console.log(
|
|
104
|
+
formatOutput(
|
|
105
|
+
{
|
|
106
|
+
account_id: account.account_id,
|
|
107
|
+
device: account.device,
|
|
108
|
+
display_name: account.display_name,
|
|
109
|
+
created_at: account.created_at,
|
|
110
|
+
updated_at: account.updated_at,
|
|
111
|
+
},
|
|
112
|
+
options.pretty,
|
|
113
|
+
),
|
|
114
|
+
)
|
|
151
115
|
} catch (error) {
|
|
152
116
|
handleError(error as Error)
|
|
153
117
|
}
|
|
@@ -196,7 +160,10 @@ export const authCommand = new Command('auth')
|
|
|
196
160
|
.option('--email <email>', 'Email address for email/password login')
|
|
197
161
|
.option('--password <password>', 'Password for email login')
|
|
198
162
|
.option('--token <token>', 'Login with existing auth token directly')
|
|
199
|
-
.option(
|
|
163
|
+
.option(
|
|
164
|
+
'--device <type>',
|
|
165
|
+
'Device type (default: ANDROIDSECONDARY). Secondary device that coexists with LINE desktop. Use DESKTOPMAC/DESKTOPWIN to replace desktop session.',
|
|
166
|
+
)
|
|
200
167
|
.option('--pretty', 'Pretty print JSON output')
|
|
201
168
|
.action(loginAction),
|
|
202
169
|
)
|
|
@@ -3,7 +3,7 @@ import { afterEach, beforeEach, expect, mock, spyOn, test } from 'bun:test'
|
|
|
3
3
|
const originalConsoleLog = console.log
|
|
4
4
|
|
|
5
5
|
import { LineClient } from '../client'
|
|
6
|
-
import {
|
|
6
|
+
import { whoamiCommand } from './whoami'
|
|
7
7
|
|
|
8
8
|
let loginSpy: ReturnType<typeof spyOn>
|
|
9
9
|
let getProfileSpy: ReturnType<typeof spyOn>
|
|
@@ -33,9 +33,9 @@ afterEach(() => {
|
|
|
33
33
|
console.log = originalConsoleLog
|
|
34
34
|
})
|
|
35
35
|
|
|
36
|
-
test('
|
|
36
|
+
test('whoami: fetches and outputs profile', async () => {
|
|
37
37
|
// when
|
|
38
|
-
await
|
|
38
|
+
await whoamiCommand.parseAsync(['node', 'whoami'])
|
|
39
39
|
|
|
40
40
|
// then
|
|
41
41
|
expect(loginSpy).toHaveBeenCalledTimes(1)
|
|
@@ -46,9 +46,9 @@ test('profile: fetches and outputs profile', async () => {
|
|
|
46
46
|
expect(output.display_name).toBe('Test User')
|
|
47
47
|
})
|
|
48
48
|
|
|
49
|
-
test('
|
|
49
|
+
test('whoami: outputs profile with all fields', async () => {
|
|
50
50
|
// when
|
|
51
|
-
await
|
|
51
|
+
await whoamiCommand.parseAsync(['node', 'whoami'])
|
|
52
52
|
|
|
53
53
|
// then
|
|
54
54
|
const output = JSON.parse(consoleLogSpy.mock.calls[0][0])
|
|
@@ -58,26 +58,26 @@ test('profile: outputs profile with all fields', async () => {
|
|
|
58
58
|
expect(output.status_message).toBeDefined()
|
|
59
59
|
})
|
|
60
60
|
|
|
61
|
-
test('
|
|
61
|
+
test('whoami: closes client after fetching profile', async () => {
|
|
62
62
|
// when
|
|
63
|
-
await
|
|
63
|
+
await whoamiCommand.parseAsync(['node', 'whoami'])
|
|
64
64
|
|
|
65
65
|
// then
|
|
66
66
|
expect(closeSpy).toHaveBeenCalledTimes(1)
|
|
67
67
|
})
|
|
68
68
|
|
|
69
|
-
test('
|
|
69
|
+
test('whoami: outputs profile with picture_url', async () => {
|
|
70
70
|
// when
|
|
71
|
-
await
|
|
71
|
+
await whoamiCommand.parseAsync(['node', 'whoami'])
|
|
72
72
|
|
|
73
73
|
// then
|
|
74
74
|
const output = JSON.parse(consoleLogSpy.mock.calls[0][0])
|
|
75
75
|
expect(output.picture_url).toBe('https://example.com/pic.jpg')
|
|
76
76
|
})
|
|
77
77
|
|
|
78
|
-
test('
|
|
78
|
+
test('whoami: outputs profile with status_message', async () => {
|
|
79
79
|
// when
|
|
80
|
-
await
|
|
80
|
+
await whoamiCommand.parseAsync(['node', 'whoami'])
|
|
81
81
|
|
|
82
82
|
// then
|
|
83
83
|
const output = JSON.parse(consoleLogSpy.mock.calls[0][0])
|
|
@@ -5,7 +5,7 @@ import { formatOutput } from '@/shared/utils/output'
|
|
|
5
5
|
|
|
6
6
|
import { LineClient } from '../client'
|
|
7
7
|
|
|
8
|
-
async function
|
|
8
|
+
async function whoamiAction(options: { pretty?: boolean }): Promise<void> {
|
|
9
9
|
let client: LineClient | undefined
|
|
10
10
|
try {
|
|
11
11
|
client = await new LineClient().login()
|
|
@@ -18,7 +18,7 @@ async function profileAction(options: { pretty?: boolean }): Promise<void> {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export const
|
|
22
|
-
.description('Show
|
|
21
|
+
export const whoamiCommand = new Command('whoami')
|
|
22
|
+
.description('Show current authenticated user')
|
|
23
23
|
.option('--pretty', 'Pretty print JSON output')
|
|
24
|
-
.action(
|
|
24
|
+
.action(whoamiAction)
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
unreadCommand,
|
|
23
23
|
userCommand,
|
|
24
24
|
usergroupCommand,
|
|
25
|
+
whoamiCommand,
|
|
25
26
|
workspaceCommand,
|
|
26
27
|
} from './commands/index'
|
|
27
28
|
import { ensureSlackAuth } from './ensure-auth'
|
|
@@ -66,6 +67,7 @@ program.addCommand(bookmarkCommand)
|
|
|
66
67
|
program.addCommand(reminderCommand)
|
|
67
68
|
program.addCommand(emojiCommand)
|
|
68
69
|
program.addCommand(usergroupCommand)
|
|
70
|
+
program.addCommand(whoamiCommand)
|
|
69
71
|
|
|
70
72
|
program.parse(process.argv)
|
|
71
73
|
|
|
@@ -15,4 +15,5 @@ export { snapshotCommand } from './snapshot'
|
|
|
15
15
|
export { unreadCommand } from './unread'
|
|
16
16
|
export { userCommand } from './user'
|
|
17
17
|
export { usergroupCommand } from './usergroup'
|
|
18
|
+
export { whoamiCommand } from './whoami'
|
|
18
19
|
export { workspaceCommand } from './workspace'
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { afterEach, beforeEach, expect, spyOn, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
import { SlackClient } from '@/platforms/slack/client'
|
|
4
|
+
import { CredentialManager } from '@/platforms/slack/credential-manager'
|
|
5
|
+
import { whoamiAction, whoamiCommand } from '@/platforms/slack/commands/whoami'
|
|
6
|
+
|
|
7
|
+
let credManagerSpy: ReturnType<typeof spyOn>
|
|
8
|
+
let clientTestAuthSpy: ReturnType<typeof spyOn>
|
|
9
|
+
let clientGetUserSpy: ReturnType<typeof spyOn>
|
|
10
|
+
let consoleLogSpy: ReturnType<typeof spyOn>
|
|
11
|
+
let processExitSpy: ReturnType<typeof spyOn>
|
|
12
|
+
|
|
13
|
+
const mockWorkspace = {
|
|
14
|
+
workspace_id: 'T123',
|
|
15
|
+
workspace_name: 'Test Workspace',
|
|
16
|
+
token: 'xoxc-test',
|
|
17
|
+
cookie: 'test-cookie',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const mockAuthInfo = {
|
|
21
|
+
user_id: 'U123',
|
|
22
|
+
team_id: 'T123',
|
|
23
|
+
user: 'alice',
|
|
24
|
+
team: 'Test Workspace',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const mockUser = {
|
|
28
|
+
id: 'U123',
|
|
29
|
+
name: 'alice',
|
|
30
|
+
real_name: 'Alice Smith',
|
|
31
|
+
is_admin: true,
|
|
32
|
+
is_owner: false,
|
|
33
|
+
is_bot: false,
|
|
34
|
+
is_app_user: false,
|
|
35
|
+
profile: {
|
|
36
|
+
email: 'alice@example.com',
|
|
37
|
+
title: 'Engineer',
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
credManagerSpy = spyOn(CredentialManager.prototype, 'getWorkspace').mockResolvedValue(mockWorkspace)
|
|
43
|
+
clientTestAuthSpy = spyOn(SlackClient.prototype, 'testAuth').mockResolvedValue(mockAuthInfo)
|
|
44
|
+
clientGetUserSpy = spyOn(SlackClient.prototype, 'getUser').mockResolvedValue(mockUser)
|
|
45
|
+
consoleLogSpy = spyOn(console, 'log').mockImplementation(() => {})
|
|
46
|
+
processExitSpy = spyOn(process, 'exit').mockImplementation((_code?: number) => undefined as never)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
afterEach(() => {
|
|
50
|
+
credManagerSpy?.mockRestore()
|
|
51
|
+
clientTestAuthSpy?.mockRestore()
|
|
52
|
+
clientGetUserSpy?.mockRestore()
|
|
53
|
+
consoleLogSpy?.mockRestore()
|
|
54
|
+
processExitSpy?.mockRestore()
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test('whoami command is defined with correct name and description', () => {
|
|
58
|
+
expect(whoamiCommand).toBeDefined()
|
|
59
|
+
expect(whoamiCommand.name()).toBe('whoami')
|
|
60
|
+
expect(whoamiCommand.description()).toBe('Show current authenticated user')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('whoami command has --pretty option', () => {
|
|
64
|
+
const options = whoamiCommand.options
|
|
65
|
+
const hasPretty = options.some((opt: { long?: string }) => opt.long === '--pretty')
|
|
66
|
+
expect(hasPretty).toBe(true)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('whoami outputs expected fields', async () => {
|
|
70
|
+
await whoamiAction({})
|
|
71
|
+
|
|
72
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
73
|
+
JSON.stringify({
|
|
74
|
+
id: 'U123',
|
|
75
|
+
name: 'alice',
|
|
76
|
+
real_name: 'Alice Smith',
|
|
77
|
+
is_admin: true,
|
|
78
|
+
is_owner: false,
|
|
79
|
+
is_bot: false,
|
|
80
|
+
is_app_user: false,
|
|
81
|
+
team_id: 'T123',
|
|
82
|
+
team: 'Test Workspace',
|
|
83
|
+
profile: {
|
|
84
|
+
email: 'alice@example.com',
|
|
85
|
+
title: 'Engineer',
|
|
86
|
+
},
|
|
87
|
+
}),
|
|
88
|
+
)
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
test('whoami outputs pretty-printed JSON when pretty is true', async () => {
|
|
92
|
+
await whoamiAction({ pretty: true })
|
|
93
|
+
|
|
94
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
95
|
+
JSON.stringify(
|
|
96
|
+
{
|
|
97
|
+
id: 'U123',
|
|
98
|
+
name: 'alice',
|
|
99
|
+
real_name: 'Alice Smith',
|
|
100
|
+
is_admin: true,
|
|
101
|
+
is_owner: false,
|
|
102
|
+
is_bot: false,
|
|
103
|
+
is_app_user: false,
|
|
104
|
+
team_id: 'T123',
|
|
105
|
+
team: 'Test Workspace',
|
|
106
|
+
profile: {
|
|
107
|
+
email: 'alice@example.com',
|
|
108
|
+
title: 'Engineer',
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
null,
|
|
112
|
+
2,
|
|
113
|
+
),
|
|
114
|
+
)
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
test('whoami exits with error when no workspace is set', async () => {
|
|
118
|
+
credManagerSpy.mockResolvedValue(null)
|
|
119
|
+
|
|
120
|
+
await whoamiAction({})
|
|
121
|
+
|
|
122
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
123
|
+
JSON.stringify({ error: 'No current workspace set. Run "auth extract" first.' }),
|
|
124
|
+
)
|
|
125
|
+
expect(processExitSpy).toHaveBeenCalledWith(1)
|
|
126
|
+
})
|