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
|
@@ -72,7 +72,7 @@ export class KakaoTalkListener {
|
|
|
72
72
|
if (!this.running) return
|
|
73
73
|
|
|
74
74
|
try {
|
|
75
|
-
const { oauthToken, userId, deviceUuid } = this.client.getCredentials()
|
|
75
|
+
const { oauthToken, userId, deviceUuid, deviceType } = this.client.getCredentials()
|
|
76
76
|
if (!this.running) return
|
|
77
77
|
|
|
78
78
|
this.userId = userId
|
|
@@ -88,7 +88,7 @@ export class KakaoTalkListener {
|
|
|
88
88
|
}
|
|
89
89
|
})
|
|
90
90
|
|
|
91
|
-
await session.login(oauthToken, userId, deviceUuid)
|
|
91
|
+
await session.login(oauthToken, userId, deviceUuid, undefined, deviceType)
|
|
92
92
|
|
|
93
93
|
if (!this.running) {
|
|
94
94
|
session.close()
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Protocol constants for KakaoTalk LOCO.
|
|
2
2
|
// See protocol/NOTICE.md for attribution of protocol knowledge.
|
|
3
3
|
|
|
4
|
+
import type { KakaoDeviceType } from '../types'
|
|
5
|
+
|
|
4
6
|
// LOCO RSA public key (PKCS#1 DER, base64). RSA-2048, e=3.
|
|
5
7
|
// Source: openkakao (MIT) — extracted from KakaoTalk macOS binary.
|
|
6
8
|
export const LOCO_RSA_PUBLIC_KEY_DER_B64 =
|
|
@@ -17,8 +19,17 @@ export const BOOKING_PORT = 443
|
|
|
17
19
|
export const CHECKIN_HOST = 'ticket-loco.kakao.com'
|
|
18
20
|
export const CHECKIN_PORT = 995
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
// PC slot identity — platform-aware: 'win' on Windows, 'mac' on macOS
|
|
23
|
+
const PC_APP_VERSION = '26.2.0'
|
|
24
|
+
const PC_OS: string = process.platform === 'win32' ? 'win' : 'mac'
|
|
25
|
+
export const PC_OS_NAME: string = process.platform === 'win32' ? 'Windows' : 'macOS'
|
|
26
|
+
|
|
27
|
+
// Android (tablet slot) identity — must match the Android sub-device agent
|
|
28
|
+
// used in auth/kakao-login.ts so the server sees a consistent tablet session.
|
|
29
|
+
const ANDROID_APP_VERSION = '25.9.2'
|
|
30
|
+
const ANDROID_OS = 'android'
|
|
31
|
+
|
|
32
|
+
// dtype: 2 = sub-device, 1 = main device (ref: node-kakao config.ts)
|
|
22
33
|
export const DTYPE = 2
|
|
23
34
|
export const MCCMNC = '99999'
|
|
24
35
|
export const LANG = 'ko'
|
|
@@ -26,3 +37,16 @@ export const COUNTRY_ISO = 'KR'
|
|
|
26
37
|
export const PROTOCOL_VERSION = '1'
|
|
27
38
|
|
|
28
39
|
export const PING_INTERVAL_MS = 300_000
|
|
40
|
+
|
|
41
|
+
export interface LocoDeviceConfig {
|
|
42
|
+
os: string
|
|
43
|
+
appVersion: string
|
|
44
|
+
useSub: boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function getLocoDeviceConfig(deviceType: KakaoDeviceType): LocoDeviceConfig {
|
|
48
|
+
if (deviceType === 'tablet') {
|
|
49
|
+
return { os: ANDROID_OS, appVersion: ANDROID_APP_VERSION, useSub: true }
|
|
50
|
+
}
|
|
51
|
+
return { os: PC_OS, appVersion: PC_APP_VERSION, useSub: false }
|
|
52
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Binary, Long } from 'bson'
|
|
2
2
|
|
|
3
|
+
import type { KakaoDeviceType } from '../types'
|
|
4
|
+
|
|
3
5
|
import {
|
|
4
|
-
APP_VERSION,
|
|
5
6
|
BOOKING_HOST,
|
|
6
7
|
BOOKING_PORT,
|
|
7
8
|
CHECKIN_HOST,
|
|
@@ -12,18 +13,23 @@ import {
|
|
|
12
13
|
MCCMNC,
|
|
13
14
|
PING_INTERVAL_MS,
|
|
14
15
|
PROTOCOL_VERSION,
|
|
16
|
+
getLocoDeviceConfig,
|
|
15
17
|
} from './config'
|
|
16
18
|
import { LocoConnection } from './connection'
|
|
17
|
-
import type { BookingResponse, CheckinResponse, LoginListResponse, LocoPacket } from './types'
|
|
19
|
+
import type { BookingResponse, CheckinResponse, LoginListResponse, LocoPacket, SyncState } from './types'
|
|
18
20
|
|
|
19
21
|
export class LocoSession {
|
|
20
22
|
private connection: LocoConnection | null = null
|
|
21
23
|
private pingTimer: ReturnType<typeof setInterval> | null = null
|
|
22
24
|
private pushHandler: ((packet: LocoPacket) => void) | null = null
|
|
23
25
|
private closeHandler: (() => void) | null = null
|
|
26
|
+
private deviceType: KakaoDeviceType = 'tablet'
|
|
27
|
+
|
|
28
|
+
async login(oauthToken: string, userId: string, deviceUuid: string, syncState?: SyncState, deviceType?: KakaoDeviceType): Promise<LoginListResponse> {
|
|
29
|
+
this.deviceType = deviceType ?? 'tablet'
|
|
30
|
+
const deviceConfig = getLocoDeviceConfig(this.deviceType)
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
const { host, port } = await this.bookAndCheckin(userId)
|
|
32
|
+
const { host, port } = await this.bookAndCheckin(userId, deviceConfig)
|
|
27
33
|
|
|
28
34
|
this.connection = new LocoConnection()
|
|
29
35
|
await this.connection.connectSecure(host, port)
|
|
@@ -35,21 +41,28 @@ export class LocoSession {
|
|
|
35
41
|
this.connection.onClose(this.closeHandler)
|
|
36
42
|
}
|
|
37
43
|
|
|
44
|
+
const chatIds = syncState?.chatIds.map((id) => new Long(id.low, id.high)) ?? []
|
|
45
|
+
const maxIds = syncState?.maxIds.map((id) => new Long(id.low, id.high)) ?? []
|
|
46
|
+
const lastTokenId = syncState
|
|
47
|
+
? new Long(syncState.lastTokenId.low, syncState.lastTokenId.high)
|
|
48
|
+
: Long.fromNumber(0)
|
|
49
|
+
const lbk = syncState?.lbk ?? 0
|
|
50
|
+
|
|
38
51
|
const response = await this.connection.sendPacket('LOGINLIST', {
|
|
39
|
-
appVer:
|
|
52
|
+
appVer: deviceConfig.appVersion,
|
|
40
53
|
prtVer: PROTOCOL_VERSION,
|
|
41
|
-
os:
|
|
54
|
+
os: deviceConfig.os,
|
|
42
55
|
lang: LANG,
|
|
43
56
|
dtype: DTYPE,
|
|
44
57
|
duuid: deviceUuid,
|
|
45
58
|
oauthToken,
|
|
46
59
|
ntype: 0,
|
|
47
60
|
MCCMNC: MCCMNC,
|
|
48
|
-
revision: 0,
|
|
49
|
-
chatIds
|
|
50
|
-
maxIds
|
|
51
|
-
lastTokenId
|
|
52
|
-
lbk
|
|
61
|
+
revision: syncState?.revision ?? 0,
|
|
62
|
+
chatIds,
|
|
63
|
+
maxIds,
|
|
64
|
+
lastTokenId,
|
|
65
|
+
lbk,
|
|
53
66
|
rp: new Binary(Buffer.from([0x00, 0x00, 0xff, 0xff, 0x00, 0x00])),
|
|
54
67
|
bg: false,
|
|
55
68
|
})
|
|
@@ -58,12 +71,12 @@ export class LocoSession {
|
|
|
58
71
|
return response.body as unknown as LoginListResponse
|
|
59
72
|
}
|
|
60
73
|
|
|
61
|
-
private async bookAndCheckin(userId: string): Promise<{ host: string; port: number }> {
|
|
74
|
+
private async bookAndCheckin(userId: string, deviceConfig: { os: string; appVersion: string; useSub: boolean }): Promise<{ host: string; port: number }> {
|
|
62
75
|
const bookingConn = new LocoConnection()
|
|
63
76
|
await bookingConn.connectTls(BOOKING_HOST, BOOKING_PORT)
|
|
64
77
|
|
|
65
78
|
const bookingResponse = await bookingConn.sendPacket('GETCONF', {
|
|
66
|
-
os:
|
|
79
|
+
os: deviceConfig.os,
|
|
67
80
|
model: '',
|
|
68
81
|
})
|
|
69
82
|
bookingConn.close()
|
|
@@ -79,13 +92,13 @@ export class LocoSession {
|
|
|
79
92
|
|
|
80
93
|
const checkinResponse = await checkinConn.sendPacket('CHECKIN', {
|
|
81
94
|
userId: Number(userId),
|
|
82
|
-
os:
|
|
95
|
+
os: deviceConfig.os,
|
|
83
96
|
ntype: 0,
|
|
84
|
-
appVer:
|
|
97
|
+
appVer: deviceConfig.appVersion,
|
|
85
98
|
MCCMNC: MCCMNC,
|
|
86
99
|
lang: LANG,
|
|
87
100
|
countryISO: COUNTRY_ISO,
|
|
88
|
-
useSub:
|
|
101
|
+
useSub: deviceConfig.useSub,
|
|
89
102
|
})
|
|
90
103
|
checkinConn.close()
|
|
91
104
|
|
|
@@ -117,6 +130,19 @@ export class LocoSession {
|
|
|
117
130
|
})
|
|
118
131
|
}
|
|
119
132
|
|
|
133
|
+
async getChatLogs(chatIds: Long[], sinces: Long[]): Promise<LocoPacket> {
|
|
134
|
+
if (!this.connection) throw new Error('Not connected')
|
|
135
|
+
return this.connection.sendPacket('MCHATLOGS', {
|
|
136
|
+
chatIds,
|
|
137
|
+
sinces,
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async getChatInfo(chatId: Long): Promise<LocoPacket> {
|
|
142
|
+
if (!this.connection) throw new Error('Not connected')
|
|
143
|
+
return this.connection.sendPacket('CHATONROOM', { chatId })
|
|
144
|
+
}
|
|
145
|
+
|
|
120
146
|
async getChatList(lastTokenId?: Long, lastChatId?: Long): Promise<LocoPacket> {
|
|
121
147
|
if (!this.connection) throw new Error('Not connected')
|
|
122
148
|
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
|
|
@@ -11,6 +11,8 @@ export interface ExtractedKakaoToken {
|
|
|
11
11
|
login_form_body?: string
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
export type KakaoAuthMethod = 'login' | 'extract'
|
|
15
|
+
|
|
14
16
|
export interface KakaoAccountCredentials {
|
|
15
17
|
account_id: string
|
|
16
18
|
oauth_token: string
|
|
@@ -18,6 +20,7 @@ export interface KakaoAccountCredentials {
|
|
|
18
20
|
refresh_token?: string
|
|
19
21
|
device_uuid: string
|
|
20
22
|
device_type: KakaoDeviceType
|
|
23
|
+
auth_method?: KakaoAuthMethod
|
|
21
24
|
created_at: string
|
|
22
25
|
updated_at: string
|
|
23
26
|
}
|
|
@@ -130,8 +133,14 @@ export interface KakaoProfile {
|
|
|
130
133
|
nickname: string
|
|
131
134
|
profile_image_url: string | null
|
|
132
135
|
original_profile_image_url: string | null
|
|
136
|
+
background_image_url?: string | null
|
|
137
|
+
original_background_image_url?: string | null
|
|
138
|
+
fullname?: string | null
|
|
133
139
|
status_message: string | null
|
|
134
140
|
account_display_id: string | null
|
|
141
|
+
account_email?: string | null
|
|
142
|
+
pstn_number?: string | null
|
|
143
|
+
email_verified?: boolean | null
|
|
135
144
|
}
|
|
136
145
|
|
|
137
146
|
export const KakaoProfileSchema = z.object({
|
|
@@ -139,8 +148,14 @@ export const KakaoProfileSchema = z.object({
|
|
|
139
148
|
nickname: z.string(),
|
|
140
149
|
profile_image_url: z.string().nullable(),
|
|
141
150
|
original_profile_image_url: z.string().nullable(),
|
|
151
|
+
background_image_url: z.string().nullable().optional(),
|
|
152
|
+
original_background_image_url: z.string().nullable().optional(),
|
|
153
|
+
fullname: z.string().nullable().optional(),
|
|
142
154
|
status_message: z.string().nullable(),
|
|
143
155
|
account_display_id: z.string().nullable(),
|
|
156
|
+
account_email: z.string().nullable().optional(),
|
|
157
|
+
pstn_number: z.string().nullable().optional(),
|
|
158
|
+
email_verified: z.boolean().nullable().optional(),
|
|
144
159
|
})
|
|
145
160
|
|
|
146
161
|
export const KakaoAccountCredentialsSchema = z.object({
|
|
@@ -150,6 +165,7 @@ export const KakaoAccountCredentialsSchema = z.object({
|
|
|
150
165
|
refresh_token: z.string().optional(),
|
|
151
166
|
device_uuid: z.string(),
|
|
152
167
|
device_type: z.enum(['pc', 'tablet']),
|
|
168
|
+
auth_method: z.enum(['login', 'extract']).optional(),
|
|
153
169
|
created_at: z.string(),
|
|
154
170
|
updated_at: z.string(),
|
|
155
171
|
})
|
|
@@ -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
|
+
})
|