agent-messenger 1.0.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/commands/release.md +92 -0
- package/.claude-plugin/README.md +144 -0
- package/.claude-plugin/marketplace.json +37 -0
- package/.claude-plugin/plugin.json +17 -0
- package/.github/workflows/ci.yml +30 -0
- package/CLAUDE.md +106 -0
- package/CONTRIBUTING.md +131 -0
- package/README.md +140 -0
- package/biome.json +34 -0
- package/bun.lock +252 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +21 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/auth.d.ts +3 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +140 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/channel.d.ts +3 -0
- package/dist/commands/channel.d.ts.map +1 -0
- package/dist/commands/channel.js +118 -0
- package/dist/commands/channel.js.map +1 -0
- package/dist/commands/file.d.ts +3 -0
- package/dist/commands/file.d.ts.map +1 -0
- package/dist/commands/file.js +113 -0
- package/dist/commands/file.js.map +1 -0
- package/dist/commands/index.d.ts +9 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +9 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/message.d.ts +3 -0
- package/dist/commands/message.d.ts.map +1 -0
- package/dist/commands/message.js +214 -0
- package/dist/commands/message.js.map +1 -0
- package/dist/commands/reaction.d.ts +3 -0
- package/dist/commands/reaction.d.ts.map +1 -0
- package/dist/commands/reaction.js +100 -0
- package/dist/commands/reaction.js.map +1 -0
- package/dist/commands/snapshot.d.ts +3 -0
- package/dist/commands/snapshot.d.ts.map +1 -0
- package/dist/commands/snapshot.js +88 -0
- package/dist/commands/snapshot.js.map +1 -0
- package/dist/commands/user.d.ts +3 -0
- package/dist/commands/user.d.ts.map +1 -0
- package/dist/commands/user.js +96 -0
- package/dist/commands/user.js.map +1 -0
- package/dist/commands/workspace.d.ts +3 -0
- package/dist/commands/workspace.d.ts.map +1 -0
- package/dist/commands/workspace.js +89 -0
- package/dist/commands/workspace.js.map +1 -0
- package/dist/lib/credential-manager.d.ts +13 -0
- package/dist/lib/credential-manager.d.ts.map +1 -0
- package/dist/lib/credential-manager.js +58 -0
- package/dist/lib/credential-manager.js.map +1 -0
- package/dist/lib/index.d.ts +3 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +3 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/ref-manager.d.ts +26 -0
- package/dist/lib/ref-manager.d.ts.map +1 -0
- package/dist/lib/ref-manager.js +92 -0
- package/dist/lib/ref-manager.js.map +1 -0
- package/dist/lib/slack-client.d.ts +37 -0
- package/dist/lib/slack-client.d.ts.map +1 -0
- package/dist/lib/slack-client.js +379 -0
- package/dist/lib/slack-client.js.map +1 -0
- package/dist/lib/token-extractor.d.ts +28 -0
- package/dist/lib/token-extractor.d.ts.map +1 -0
- package/dist/lib/token-extractor.js +401 -0
- package/dist/lib/token-extractor.js.map +1 -0
- package/dist/package.json +37 -0
- package/dist/src/cli.d.ts +5 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +22 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/platforms/discord/cli.d.ts +5 -0
- package/dist/src/platforms/discord/cli.d.ts.map +1 -0
- package/dist/src/platforms/discord/cli.js +22 -0
- package/dist/src/platforms/discord/cli.js.map +1 -0
- package/dist/src/platforms/discord/client.d.ts +34 -0
- package/dist/src/platforms/discord/client.d.ts.map +1 -0
- package/dist/src/platforms/discord/client.js +187 -0
- package/dist/src/platforms/discord/client.js.map +1 -0
- package/dist/src/platforms/discord/client.test.d.ts +2 -0
- package/dist/src/platforms/discord/client.test.d.ts.map +1 -0
- package/dist/src/platforms/discord/client.test.js +367 -0
- package/dist/src/platforms/discord/client.test.js.map +1 -0
- package/dist/src/platforms/discord/commands/auth.d.ts +13 -0
- package/dist/src/platforms/discord/commands/auth.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/auth.js +155 -0
- package/dist/src/platforms/discord/commands/auth.js.map +1 -0
- package/dist/src/platforms/discord/commands/auth.test.d.ts +2 -0
- package/dist/src/platforms/discord/commands/auth.test.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/auth.test.js +65 -0
- package/dist/src/platforms/discord/commands/auth.test.js.map +1 -0
- package/dist/src/platforms/discord/commands/channel.d.ts +13 -0
- package/dist/src/platforms/discord/commands/channel.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/channel.js +99 -0
- package/dist/src/platforms/discord/commands/channel.js.map +1 -0
- package/dist/src/platforms/discord/commands/channel.test.d.ts +2 -0
- package/dist/src/platforms/discord/commands/channel.test.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/channel.test.js +136 -0
- package/dist/src/platforms/discord/commands/channel.test.js.map +1 -0
- package/dist/src/platforms/discord/commands/file.d.ts +13 -0
- package/dist/src/platforms/discord/commands/file.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/file.js +99 -0
- package/dist/src/platforms/discord/commands/file.js.map +1 -0
- package/dist/src/platforms/discord/commands/file.test.d.ts +2 -0
- package/dist/src/platforms/discord/commands/file.test.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/file.test.js +83 -0
- package/dist/src/platforms/discord/commands/file.test.js.map +1 -0
- package/dist/src/platforms/discord/commands/guild.d.ts +15 -0
- package/dist/src/platforms/discord/commands/guild.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/guild.js +102 -0
- package/dist/src/platforms/discord/commands/guild.js.map +1 -0
- package/dist/src/platforms/discord/commands/guild.test.d.ts +2 -0
- package/dist/src/platforms/discord/commands/guild.test.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/guild.test.js +100 -0
- package/dist/src/platforms/discord/commands/guild.test.js.map +1 -0
- package/dist/src/platforms/discord/commands/index.d.ts +9 -0
- package/dist/src/platforms/discord/commands/index.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/index.js +9 -0
- package/dist/src/platforms/discord/commands/index.js.map +1 -0
- package/dist/src/platforms/discord/commands/message.d.ts +17 -0
- package/dist/src/platforms/discord/commands/message.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/message.js +131 -0
- package/dist/src/platforms/discord/commands/message.js.map +1 -0
- package/dist/src/platforms/discord/commands/message.test.d.ts +2 -0
- package/dist/src/platforms/discord/commands/message.test.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/message.test.js +91 -0
- package/dist/src/platforms/discord/commands/message.test.js.map +1 -0
- package/dist/src/platforms/discord/commands/reaction.d.ts +12 -0
- package/dist/src/platforms/discord/commands/reaction.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/reaction.js +99 -0
- package/dist/src/platforms/discord/commands/reaction.js.map +1 -0
- package/dist/src/platforms/discord/commands/reaction.test.d.ts +2 -0
- package/dist/src/platforms/discord/commands/reaction.test.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/reaction.test.js +115 -0
- package/dist/src/platforms/discord/commands/reaction.test.js.map +1 -0
- package/dist/src/platforms/discord/commands/snapshot.d.ts +9 -0
- package/dist/src/platforms/discord/commands/snapshot.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/snapshot.js +80 -0
- package/dist/src/platforms/discord/commands/snapshot.js.map +1 -0
- package/dist/src/platforms/discord/commands/snapshot.test.d.ts +2 -0
- package/dist/src/platforms/discord/commands/snapshot.test.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/snapshot.test.js +25 -0
- package/dist/src/platforms/discord/commands/snapshot.test.js.map +1 -0
- package/dist/src/platforms/discord/commands/user.d.ts +3 -0
- package/dist/src/platforms/discord/commands/user.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/user.js +94 -0
- package/dist/src/platforms/discord/commands/user.js.map +1 -0
- package/dist/src/platforms/discord/commands/user.test.d.ts +2 -0
- package/dist/src/platforms/discord/commands/user.test.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/user.test.js +103 -0
- package/dist/src/platforms/discord/commands/user.test.js.map +1 -0
- package/dist/src/platforms/discord/credential-manager.d.ts +33 -0
- package/dist/src/platforms/discord/credential-manager.d.ts.map +1 -0
- package/dist/src/platforms/discord/credential-manager.js +73 -0
- package/dist/src/platforms/discord/credential-manager.js.map +1 -0
- package/dist/src/platforms/discord/credential-manager.test.d.ts +2 -0
- package/dist/src/platforms/discord/credential-manager.test.d.ts.map +1 -0
- package/dist/src/platforms/discord/credential-manager.test.js +136 -0
- package/dist/src/platforms/discord/credential-manager.test.js.map +1 -0
- package/dist/src/platforms/discord/token-extractor.d.ts +55 -0
- package/dist/src/platforms/discord/token-extractor.d.ts.map +1 -0
- package/dist/src/platforms/discord/token-extractor.js +462 -0
- package/dist/src/platforms/discord/token-extractor.js.map +1 -0
- package/dist/src/platforms/discord/token-extractor.test.d.ts +2 -0
- package/dist/src/platforms/discord/token-extractor.test.d.ts.map +1 -0
- package/dist/src/platforms/discord/token-extractor.test.js +789 -0
- package/dist/src/platforms/discord/token-extractor.test.js.map +1 -0
- package/dist/src/platforms/discord/types.d.ts +251 -0
- package/dist/src/platforms/discord/types.d.ts.map +1 -0
- package/dist/src/platforms/discord/types.js +74 -0
- package/dist/src/platforms/discord/types.js.map +1 -0
- package/dist/src/platforms/discord/types.test.d.ts +2 -0
- package/dist/src/platforms/discord/types.test.d.ts.map +1 -0
- package/dist/src/platforms/discord/types.test.js +211 -0
- package/dist/src/platforms/discord/types.test.js.map +1 -0
- package/dist/src/platforms/slack/cli.d.ts +5 -0
- package/dist/src/platforms/slack/cli.d.ts.map +1 -0
- package/dist/src/platforms/slack/cli.js +22 -0
- package/dist/src/platforms/slack/cli.js.map +1 -0
- package/dist/src/platforms/slack/client.d.ts +47 -0
- package/dist/src/platforms/slack/client.d.ts.map +1 -0
- package/dist/src/platforms/slack/client.js +412 -0
- package/dist/src/platforms/slack/client.js.map +1 -0
- package/dist/src/platforms/slack/commands/auth.d.ts +3 -0
- package/dist/src/platforms/slack/commands/auth.d.ts.map +1 -0
- package/dist/src/platforms/slack/commands/auth.js +156 -0
- package/dist/src/platforms/slack/commands/auth.js.map +1 -0
- package/dist/src/platforms/slack/commands/channel.d.ts +3 -0
- package/dist/src/platforms/slack/commands/channel.d.ts.map +1 -0
- package/dist/src/platforms/slack/commands/channel.js +118 -0
- package/dist/src/platforms/slack/commands/channel.js.map +1 -0
- package/dist/src/platforms/slack/commands/file.d.ts +3 -0
- package/dist/src/platforms/slack/commands/file.d.ts.map +1 -0
- package/dist/src/platforms/slack/commands/file.js +113 -0
- package/dist/src/platforms/slack/commands/file.js.map +1 -0
- package/dist/src/platforms/slack/commands/index.d.ts +9 -0
- package/dist/src/platforms/slack/commands/index.d.ts.map +1 -0
- package/dist/src/platforms/slack/commands/index.js +9 -0
- package/dist/src/platforms/slack/commands/index.js.map +1 -0
- package/dist/src/platforms/slack/commands/message.d.ts +3 -0
- package/dist/src/platforms/slack/commands/message.d.ts.map +1 -0
- package/dist/src/platforms/slack/commands/message.js +263 -0
- package/dist/src/platforms/slack/commands/message.js.map +1 -0
- package/dist/src/platforms/slack/commands/reaction.d.ts +3 -0
- package/dist/src/platforms/slack/commands/reaction.d.ts.map +1 -0
- package/dist/src/platforms/slack/commands/reaction.js +100 -0
- package/dist/src/platforms/slack/commands/reaction.js.map +1 -0
- package/dist/src/platforms/slack/commands/snapshot.d.ts +3 -0
- package/dist/src/platforms/slack/commands/snapshot.d.ts.map +1 -0
- package/dist/src/platforms/slack/commands/snapshot.js +87 -0
- package/dist/src/platforms/slack/commands/snapshot.js.map +1 -0
- package/dist/src/platforms/slack/commands/user.d.ts +3 -0
- package/dist/src/platforms/slack/commands/user.d.ts.map +1 -0
- package/dist/src/platforms/slack/commands/user.js +96 -0
- package/dist/src/platforms/slack/commands/user.js.map +1 -0
- package/dist/src/platforms/slack/commands/workspace.d.ts +3 -0
- package/dist/src/platforms/slack/commands/workspace.d.ts.map +1 -0
- package/dist/src/platforms/slack/commands/workspace.js +89 -0
- package/dist/src/platforms/slack/commands/workspace.js.map +1 -0
- package/dist/src/platforms/slack/credential-manager.d.ts +13 -0
- package/dist/src/platforms/slack/credential-manager.d.ts.map +1 -0
- package/dist/src/platforms/slack/credential-manager.js +58 -0
- package/dist/src/platforms/slack/credential-manager.js.map +1 -0
- package/dist/src/platforms/slack/index.d.ts +3 -0
- package/dist/src/platforms/slack/index.d.ts.map +1 -0
- package/dist/src/platforms/slack/index.js +3 -0
- package/dist/src/platforms/slack/index.js.map +1 -0
- package/dist/src/platforms/slack/token-extractor.d.ts +28 -0
- package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -0
- package/dist/src/platforms/slack/token-extractor.js +401 -0
- package/dist/src/platforms/slack/token-extractor.js.map +1 -0
- package/dist/src/platforms/slack/types.d.ts +369 -0
- package/dist/src/platforms/slack/types.d.ts.map +1 -0
- package/dist/src/platforms/slack/types.js +92 -0
- package/dist/src/platforms/slack/types.js.map +1 -0
- package/dist/src/shared/utils/concurrency.d.ts +2 -0
- package/dist/src/shared/utils/concurrency.d.ts.map +1 -0
- package/dist/src/shared/utils/concurrency.js +14 -0
- package/dist/src/shared/utils/concurrency.js.map +1 -0
- package/dist/src/shared/utils/concurrency.test.d.ts +2 -0
- package/dist/src/shared/utils/concurrency.test.d.ts.map +1 -0
- package/dist/src/shared/utils/concurrency.test.js +39 -0
- package/dist/src/shared/utils/concurrency.test.js.map +1 -0
- package/dist/src/shared/utils/error-handler.d.ts +2 -0
- package/dist/src/shared/utils/error-handler.d.ts.map +1 -0
- package/dist/src/shared/utils/error-handler.js +5 -0
- package/dist/src/shared/utils/error-handler.js.map +1 -0
- package/dist/src/shared/utils/output.d.ts +2 -0
- package/dist/src/shared/utils/output.d.ts.map +1 -0
- package/dist/src/shared/utils/output.js +4 -0
- package/dist/src/shared/utils/output.js.map +1 -0
- package/dist/tests/cli.test.d.ts +2 -0
- package/dist/tests/cli.test.d.ts.map +1 -0
- package/dist/tests/cli.test.js +83 -0
- package/dist/tests/cli.test.js.map +1 -0
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/CURRENT +1 -0
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOCK +0 -0
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG +3 -0
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG.old +1 -0
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/MANIFEST-000004 +0 -0
- package/dist/tests/commands/auth.test.d.ts +2 -0
- package/dist/tests/commands/auth.test.d.ts.map +1 -0
- package/dist/tests/commands/auth.test.js +304 -0
- package/dist/tests/commands/auth.test.js.map +1 -0
- package/dist/tests/commands/channel.test.d.ts +2 -0
- package/dist/tests/commands/channel.test.d.ts.map +1 -0
- package/dist/tests/commands/channel.test.js +166 -0
- package/dist/tests/commands/channel.test.js.map +1 -0
- package/dist/tests/commands/file.test.d.ts +2 -0
- package/dist/tests/commands/file.test.d.ts.map +1 -0
- package/dist/tests/commands/file.test.js +175 -0
- package/dist/tests/commands/file.test.js.map +1 -0
- package/dist/tests/commands/message.test.d.ts +2 -0
- package/dist/tests/commands/message.test.d.ts.map +1 -0
- package/dist/tests/commands/message.test.js +293 -0
- package/dist/tests/commands/message.test.js.map +1 -0
- package/dist/tests/commands/reaction.test.d.ts +2 -0
- package/dist/tests/commands/reaction.test.d.ts.map +1 -0
- package/dist/tests/commands/reaction.test.js +84 -0
- package/dist/tests/commands/reaction.test.js.map +1 -0
- package/dist/tests/commands/snapshot.test.d.ts +2 -0
- package/dist/tests/commands/snapshot.test.d.ts.map +1 -0
- package/dist/tests/commands/snapshot.test.js +280 -0
- package/dist/tests/commands/snapshot.test.js.map +1 -0
- package/dist/tests/commands/user.test.d.ts +2 -0
- package/dist/tests/commands/user.test.d.ts.map +1 -0
- package/dist/tests/commands/user.test.js +117 -0
- package/dist/tests/commands/user.test.js.map +1 -0
- package/dist/tests/commands/workspace.test.d.ts +2 -0
- package/dist/tests/commands/workspace.test.d.ts.map +1 -0
- package/dist/tests/commands/workspace.test.js +453 -0
- package/dist/tests/commands/workspace.test.js.map +1 -0
- package/dist/tests/credential-manager.test.d.ts +2 -0
- package/dist/tests/credential-manager.test.d.ts.map +1 -0
- package/dist/tests/credential-manager.test.js +199 -0
- package/dist/tests/credential-manager.test.js.map +1 -0
- package/dist/tests/slack-client.test.d.ts +2 -0
- package/dist/tests/slack-client.test.d.ts.map +1 -0
- package/dist/tests/slack-client.test.js +741 -0
- package/dist/tests/slack-client.test.js.map +1 -0
- package/dist/tests/types.test.d.ts +2 -0
- package/dist/tests/types.test.d.ts.map +1 -0
- package/dist/tests/types.test.js +215 -0
- package/dist/tests/types.test.js.map +1 -0
- package/dist/types/index.d.ts +369 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +92 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/error-handler.d.ts +2 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +5 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/output.d.ts +2 -0
- package/dist/utils/output.d.ts.map +1 -0
- package/dist/utils/output.js +4 -0
- package/dist/utils/output.js.map +1 -0
- package/docs/discord.md +182 -0
- package/docs/slack.md +160 -0
- package/package.json +37 -0
- package/skills/agent-discord/SKILL.md +273 -0
- package/skills/agent-discord/references/authentication.md +294 -0
- package/skills/agent-discord/references/common-patterns.md +455 -0
- package/skills/agent-discord/templates/guild-summary.sh +167 -0
- package/skills/agent-discord/templates/monitor-channel.sh +180 -0
- package/skills/agent-discord/templates/post-message.sh +173 -0
- package/skills/agent-slack/SKILL.md +268 -0
- package/skills/agent-slack/references/authentication.md +332 -0
- package/skills/agent-slack/references/common-patterns.md +527 -0
- package/skills/agent-slack/templates/monitor-channel.sh +186 -0
- package/skills/agent-slack/templates/post-message.sh +130 -0
- package/skills/agent-slack/templates/workspace-summary.sh +149 -0
- package/src/cli.ts +29 -0
- package/src/platforms/discord/cli.ts +36 -0
- package/src/platforms/discord/client.test.ts +456 -0
- package/src/platforms/discord/client.ts +281 -0
- package/src/platforms/discord/commands/auth.test.ts +72 -0
- package/src/platforms/discord/commands/auth.ts +206 -0
- package/src/platforms/discord/commands/channel.test.ts +153 -0
- package/src/platforms/discord/commands/channel.ts +127 -0
- package/src/platforms/discord/commands/file.test.ts +98 -0
- package/src/platforms/discord/commands/file.ts +134 -0
- package/src/platforms/discord/commands/guild.test.ts +117 -0
- package/src/platforms/discord/commands/guild.ts +129 -0
- package/src/platforms/discord/commands/index.ts +8 -0
- package/src/platforms/discord/commands/message.test.ts +107 -0
- package/src/platforms/discord/commands/message.ts +182 -0
- package/src/platforms/discord/commands/reaction.test.ts +123 -0
- package/src/platforms/discord/commands/reaction.ts +156 -0
- package/src/platforms/discord/commands/snapshot.test.ts +29 -0
- package/src/platforms/discord/commands/snapshot.ts +104 -0
- package/src/platforms/discord/commands/user.test.ts +115 -0
- package/src/platforms/discord/commands/user.ts +124 -0
- package/src/platforms/discord/credential-manager.test.ts +173 -0
- package/src/platforms/discord/credential-manager.ts +95 -0
- package/src/platforms/discord/token-extractor.test.ts +918 -0
- package/src/platforms/discord/token-extractor.ts +549 -0
- package/src/platforms/discord/types.test.ts +245 -0
- package/src/platforms/discord/types.ts +158 -0
- package/src/platforms/slack/cli.ts +36 -0
- package/src/platforms/slack/client.ts +466 -0
- package/src/platforms/slack/commands/auth.ts +211 -0
- package/src/platforms/slack/commands/channel.ts +158 -0
- package/src/platforms/slack/commands/file.ts +153 -0
- package/src/platforms/slack/commands/index.ts +8 -0
- package/src/platforms/slack/commands/message.ts +369 -0
- package/src/platforms/slack/commands/reaction.ts +166 -0
- package/src/platforms/slack/commands/snapshot.ts +114 -0
- package/src/platforms/slack/commands/user.ts +110 -0
- package/src/platforms/slack/commands/workspace.ts +111 -0
- package/src/platforms/slack/credential-manager.ts +74 -0
- package/src/platforms/slack/index.ts +2 -0
- package/src/platforms/slack/token-extractor.ts +496 -0
- package/src/platforms/slack/types.ts +193 -0
- package/src/shared/utils/concurrency.test.ts +53 -0
- package/src/shared/utils/concurrency.ts +20 -0
- package/src/shared/utils/error-handler.ts +4 -0
- package/src/shared/utils/output.ts +3 -0
- package/tests/cli.test.ts +94 -0
- package/tests/commands/auth.test.ts +383 -0
- package/tests/commands/channel.test.ts +185 -0
- package/tests/commands/file.test.ts +204 -0
- package/tests/commands/message.test.ts +344 -0
- package/tests/commands/reaction.test.ts +101 -0
- package/tests/commands/snapshot.test.ts +308 -0
- package/tests/commands/user.test.ts +138 -0
- package/tests/commands/workspace.test.ts +528 -0
- package/tests/credential-manager.test.ts +241 -0
- package/tests/slack-client.test.ts +916 -0
- package/tests/types.test.ts +241 -0
- package/tsconfig.json +36 -0
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
import { Database } from 'bun:sqlite'
|
|
2
|
+
import { execSync } from 'node:child_process'
|
|
3
|
+
import { createDecipheriv, pbkdf2Sync } from 'node:crypto'
|
|
4
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
5
|
+
import { homedir } from 'node:os'
|
|
6
|
+
import { join } from 'node:path'
|
|
7
|
+
import { ClassicLevel } from 'classic-level'
|
|
8
|
+
|
|
9
|
+
export interface ExtractedWorkspace {
|
|
10
|
+
workspace_id: string
|
|
11
|
+
workspace_name: string
|
|
12
|
+
token: string
|
|
13
|
+
cookie: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface TokenInfo {
|
|
17
|
+
token: string
|
|
18
|
+
teamId: string
|
|
19
|
+
teamName: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class TokenExtractor {
|
|
23
|
+
private platform: NodeJS.Platform
|
|
24
|
+
private slackDir: string
|
|
25
|
+
|
|
26
|
+
constructor(platform?: NodeJS.Platform, slackDir?: string) {
|
|
27
|
+
this.platform = platform ?? process.platform
|
|
28
|
+
|
|
29
|
+
if (!['darwin', 'linux', 'win32'].includes(this.platform)) {
|
|
30
|
+
throw new Error(`Unsupported platform: ${this.platform}`)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
this.slackDir = slackDir ?? this.getSlackDir()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getSlackDir(): string {
|
|
37
|
+
switch (this.platform) {
|
|
38
|
+
case 'darwin': {
|
|
39
|
+
// Check direct download version first
|
|
40
|
+
const directPath = join(homedir(), 'Library', 'Application Support', 'Slack')
|
|
41
|
+
if (existsSync(directPath)) {
|
|
42
|
+
return directPath
|
|
43
|
+
}
|
|
44
|
+
// Check App Store (sandboxed) version
|
|
45
|
+
const sandboxedPath = join(
|
|
46
|
+
homedir(),
|
|
47
|
+
'Library',
|
|
48
|
+
'Containers',
|
|
49
|
+
'com.tinyspeck.slackmacgap',
|
|
50
|
+
'Data',
|
|
51
|
+
'Library',
|
|
52
|
+
'Application Support',
|
|
53
|
+
'Slack'
|
|
54
|
+
)
|
|
55
|
+
if (existsSync(sandboxedPath)) {
|
|
56
|
+
return sandboxedPath
|
|
57
|
+
}
|
|
58
|
+
// Default to direct path for error message
|
|
59
|
+
return directPath
|
|
60
|
+
}
|
|
61
|
+
case 'linux':
|
|
62
|
+
return join(homedir(), '.config', 'Slack')
|
|
63
|
+
case 'win32':
|
|
64
|
+
return join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'Slack')
|
|
65
|
+
default:
|
|
66
|
+
throw new Error(`Unsupported platform: ${this.platform}`)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async extract(): Promise<ExtractedWorkspace[]> {
|
|
71
|
+
if (!existsSync(this.slackDir)) {
|
|
72
|
+
throw new Error(`Slack directory not found: ${this.slackDir}`)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const tokens = await this.extractTokensFromLevelDB()
|
|
76
|
+
if (tokens.length === 0) {
|
|
77
|
+
return []
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const cookie = await this.extractCookieFromSQLite()
|
|
81
|
+
|
|
82
|
+
return tokens.map((t) => ({
|
|
83
|
+
workspace_id: t.teamId,
|
|
84
|
+
workspace_name: t.teamName,
|
|
85
|
+
token: t.token,
|
|
86
|
+
cookie: cookie,
|
|
87
|
+
}))
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private async extractTokensFromLevelDB(): Promise<TokenInfo[]> {
|
|
91
|
+
const possibleDirs = [
|
|
92
|
+
join(this.slackDir, 'storage'),
|
|
93
|
+
join(this.slackDir, 'Local Storage', 'leveldb'),
|
|
94
|
+
join(this.slackDir, 'IndexedDB'),
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
const tokens: TokenInfo[] = []
|
|
98
|
+
|
|
99
|
+
for (const baseDir of possibleDirs) {
|
|
100
|
+
if (!existsSync(baseDir)) {
|
|
101
|
+
continue
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const levelDbDirs = this.findLevelDBDirs(baseDir)
|
|
105
|
+
if (baseDir.endsWith('leveldb') && this.isLevelDBDir(baseDir)) {
|
|
106
|
+
levelDbDirs.push(baseDir)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
for (const dbDir of levelDbDirs) {
|
|
110
|
+
try {
|
|
111
|
+
const extracted = await this.extractFromLevelDB(dbDir)
|
|
112
|
+
tokens.push(...extracted)
|
|
113
|
+
} catch {}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return this.deduplicateTokens(tokens)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private deduplicateTokens(tokens: TokenInfo[]): TokenInfo[] {
|
|
121
|
+
const seen = new Map<string, TokenInfo>()
|
|
122
|
+
for (const token of tokens) {
|
|
123
|
+
if (!seen.has(token.teamId) || token.teamName !== 'unknown') {
|
|
124
|
+
seen.set(token.teamId, token)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return Array.from(seen.values())
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private findLevelDBDirs(baseDir: string): string[] {
|
|
131
|
+
const dirs: string[] = []
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const entries = readdirSync(baseDir, { withFileTypes: true })
|
|
135
|
+
for (const entry of entries) {
|
|
136
|
+
if (entry.isDirectory()) {
|
|
137
|
+
const fullPath = join(baseDir, entry.name)
|
|
138
|
+
if (this.isLevelDBDir(fullPath)) {
|
|
139
|
+
dirs.push(fullPath)
|
|
140
|
+
}
|
|
141
|
+
dirs.push(...this.findLevelDBDirs(fullPath))
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} catch {
|
|
145
|
+
return dirs
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return dirs
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private isLevelDBDir(dir: string): boolean {
|
|
152
|
+
try {
|
|
153
|
+
const files = readdirSync(dir)
|
|
154
|
+
return files.some((f) => f.endsWith('.ldb') || f.endsWith('.log') || f === 'CURRENT')
|
|
155
|
+
} catch {
|
|
156
|
+
return false
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private async extractFromLevelDB(dbPath: string): Promise<TokenInfo[]> {
|
|
161
|
+
const tokens: TokenInfo[] = []
|
|
162
|
+
|
|
163
|
+
// First try reading LDB files directly (more reliable for sandboxed apps)
|
|
164
|
+
const directTokens = this.extractTokensFromLDBFiles(dbPath)
|
|
165
|
+
if (directTokens.length > 0) {
|
|
166
|
+
return directTokens
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Fallback to ClassicLevel for standard installations
|
|
170
|
+
let db: ClassicLevel<string, string> | null = null
|
|
171
|
+
try {
|
|
172
|
+
db = new ClassicLevel(dbPath, { valueEncoding: 'utf8' })
|
|
173
|
+
|
|
174
|
+
for await (const [key, value] of db.iterator()) {
|
|
175
|
+
if (typeof value === 'string' && value.includes('xoxc-')) {
|
|
176
|
+
const extracted = this.parseTokenData(key, value)
|
|
177
|
+
if (extracted) {
|
|
178
|
+
tokens.push(extracted)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
} catch {
|
|
183
|
+
} finally {
|
|
184
|
+
if (db) {
|
|
185
|
+
try {
|
|
186
|
+
await db.close()
|
|
187
|
+
} catch {}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return tokens
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
private extractTokensFromLDBFiles(dbPath: string): TokenInfo[] {
|
|
195
|
+
const tokens: TokenInfo[] = []
|
|
196
|
+
try {
|
|
197
|
+
// Prioritize .log files (not compacted, have clean data)
|
|
198
|
+
// Then fall back to .ldb files
|
|
199
|
+
const logFiles = readdirSync(dbPath).filter((f) => f.endsWith('.log'))
|
|
200
|
+
const ldbFiles = readdirSync(dbPath).filter((f) => f.endsWith('.ldb'))
|
|
201
|
+
const files = [...logFiles, ...ldbFiles]
|
|
202
|
+
|
|
203
|
+
for (const file of files) {
|
|
204
|
+
const filePath = join(dbPath, file)
|
|
205
|
+
const content = readFileSync(filePath)
|
|
206
|
+
const isLogFile = file.endsWith('.log')
|
|
207
|
+
|
|
208
|
+
const xoxcMarker = Buffer.from('xoxc-')
|
|
209
|
+
let idx = content.indexOf(xoxcMarker, 0)
|
|
210
|
+
while (idx !== -1) {
|
|
211
|
+
const tokenData = isLogFile
|
|
212
|
+
? this.extractTokenFromLogFile(content, idx)
|
|
213
|
+
: this.extractTokenFromBuffer(content, idx)
|
|
214
|
+
if (tokenData) {
|
|
215
|
+
tokens.push(tokenData)
|
|
216
|
+
}
|
|
217
|
+
idx = content.indexOf(xoxcMarker, idx + 5)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
} catch {}
|
|
221
|
+
return tokens
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private extractTokenFromLogFile(buffer: Buffer, startIdx: number): TokenInfo | null {
|
|
225
|
+
// LOG files have clean (non-fragmented) JSON data
|
|
226
|
+
const chunk = buffer.subarray(startIdx, startIdx + 300)
|
|
227
|
+
const str = chunk.toString('utf8')
|
|
228
|
+
|
|
229
|
+
// Token ends at quote
|
|
230
|
+
const endQuote = str.indexOf('"')
|
|
231
|
+
if (endQuote === -1) return null
|
|
232
|
+
|
|
233
|
+
const token = str.substring(0, endQuote)
|
|
234
|
+
|
|
235
|
+
// Validate token format
|
|
236
|
+
if (!/^xoxc-\d+-\d+-\d+-[0-9a-f]{64}$/i.test(token)) {
|
|
237
|
+
return null
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
let teamId = 'unknown'
|
|
241
|
+
let teamName = 'unknown'
|
|
242
|
+
|
|
243
|
+
const surroundingChunk = buffer.subarray(Math.max(0, startIdx - 500), startIdx + 500)
|
|
244
|
+
const surroundingStr = surroundingChunk.toString('utf8')
|
|
245
|
+
|
|
246
|
+
const teamIdMatch = surroundingStr.match(/T[A-Z0-9]{8,11}/)
|
|
247
|
+
if (teamIdMatch) {
|
|
248
|
+
teamId = teamIdMatch[0]
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const teamNameMatch = surroundingStr.match(/"name"\s*:\s*"([^"]+)"/)
|
|
252
|
+
if (teamNameMatch) {
|
|
253
|
+
teamName = teamNameMatch[1]
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return { token, teamId, teamName }
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
private extractTokenFromBuffer(buffer: Buffer, startIdx: number): TokenInfo | null {
|
|
260
|
+
const chunk = buffer.subarray(startIdx, startIdx + 200)
|
|
261
|
+
|
|
262
|
+
// LevelDB fragmentation pattern observed:
|
|
263
|
+
// Token bytes: xoxc-455709840052 [19 0d f0 5e] 228-6209589301201-9f47...
|
|
264
|
+
// The 4 garbage bytes (0x19 0x0d 0xf0 0xNN) replace a hyphen between numeric segments
|
|
265
|
+
//
|
|
266
|
+
// Strategy: scan for valid token chars, when we hit a non-valid sequence,
|
|
267
|
+
// check if it's a 4-byte fragmentation marker and insert a hyphen
|
|
268
|
+
|
|
269
|
+
const result: number[] = []
|
|
270
|
+
const validChars = new Set('0123456789abcdefABCDEF-xoc'.split('').map((c) => c.charCodeAt(0)))
|
|
271
|
+
const terminators = new Set([0x22, 0x00, 0x7d, 0x2c]) // " null } ,
|
|
272
|
+
|
|
273
|
+
let i = 0
|
|
274
|
+
while (i < chunk.length) {
|
|
275
|
+
const byte = chunk[i]
|
|
276
|
+
|
|
277
|
+
if (terminators.has(byte)) {
|
|
278
|
+
break
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (validChars.has(byte)) {
|
|
282
|
+
result.push(byte)
|
|
283
|
+
i++
|
|
284
|
+
} else {
|
|
285
|
+
// Check for 4-byte fragmentation marker pattern
|
|
286
|
+
// Pattern: 0x19 0x0d 0xf0 0xNN (where NN varies)
|
|
287
|
+
if (
|
|
288
|
+
i + 3 < chunk.length &&
|
|
289
|
+
chunk[i] === 0x19 &&
|
|
290
|
+
chunk[i + 1] === 0x0d &&
|
|
291
|
+
chunk[i + 2] === 0xf0
|
|
292
|
+
) {
|
|
293
|
+
// Skip the 4 garbage bytes and insert a hyphen
|
|
294
|
+
result.push(0x2d) // hyphen
|
|
295
|
+
i += 4
|
|
296
|
+
} else {
|
|
297
|
+
// Unknown garbage - insert hyphen and skip this byte
|
|
298
|
+
if (result.length > 0 && result[result.length - 1] !== 0x2d) {
|
|
299
|
+
result.push(0x2d) // hyphen
|
|
300
|
+
}
|
|
301
|
+
i++
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const reconstructed = Buffer.from(result).toString('utf8')
|
|
307
|
+
|
|
308
|
+
// Clean up any double hyphens
|
|
309
|
+
const cleaned = reconstructed.replace(/--+/g, '-').replace(/-$/, '')
|
|
310
|
+
|
|
311
|
+
// xoxc tokens: xoxc-NUM-NUM-NUM-64HEX (4 parts after xoxc)
|
|
312
|
+
const tokenPatterns = [/xoxc-\d+-\d+-\d+-[0-9a-f]{64}/i, /xoxc-\d+-\d+-[0-9a-f]{64}/i]
|
|
313
|
+
|
|
314
|
+
let token: string | null = null
|
|
315
|
+
for (const pattern of tokenPatterns) {
|
|
316
|
+
const match = cleaned.match(pattern)
|
|
317
|
+
if (match) {
|
|
318
|
+
token = match[0]
|
|
319
|
+
break
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (!token) {
|
|
324
|
+
return null
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const parts = token.split('-')
|
|
328
|
+
if (parts.length < 4) {
|
|
329
|
+
return null
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const lastPart = parts[parts.length - 1]
|
|
333
|
+
if (!/^[0-9a-f]{64}$/i.test(lastPart)) {
|
|
334
|
+
return null
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
let teamId = 'unknown'
|
|
338
|
+
let teamName = 'unknown'
|
|
339
|
+
|
|
340
|
+
const surroundingChunk = buffer.subarray(Math.max(0, startIdx - 500), startIdx + 500)
|
|
341
|
+
const surroundingStr = surroundingChunk.toString('utf8')
|
|
342
|
+
|
|
343
|
+
const teamIdMatch = surroundingStr.match(/T[A-Z0-9]{8,11}/)
|
|
344
|
+
if (teamIdMatch) {
|
|
345
|
+
teamId = teamIdMatch[0]
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const teamNameMatch = surroundingStr.match(/"team_name"\s*:\s*"([^"]+)"/)
|
|
349
|
+
if (teamNameMatch) {
|
|
350
|
+
teamName = teamNameMatch[1]
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return { token, teamId, teamName }
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
private parseTokenData(_key: string, value: string): TokenInfo | null {
|
|
357
|
+
const tokenMatch = value.match(/xoxc-[a-zA-Z0-9-]+/)
|
|
358
|
+
if (!tokenMatch) {
|
|
359
|
+
return null
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const token = tokenMatch[0]
|
|
363
|
+
|
|
364
|
+
let teamId = 'unknown'
|
|
365
|
+
let teamName = 'unknown'
|
|
366
|
+
|
|
367
|
+
const teamIdMatch = value.match(/"team_id"\s*:\s*"(T[A-Z0-9]+)"/)
|
|
368
|
+
if (teamIdMatch) {
|
|
369
|
+
teamId = teamIdMatch[1]
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const teamNameMatch = value.match(/"team_name"\s*:\s*"([^"]+)"/)
|
|
373
|
+
if (teamNameMatch) {
|
|
374
|
+
teamName = teamNameMatch[1]
|
|
375
|
+
} else {
|
|
376
|
+
const domainMatch = value.match(/"domain"\s*:\s*"([^"]+)"/)
|
|
377
|
+
if (domainMatch) {
|
|
378
|
+
teamName = domainMatch[1]
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return { token, teamId, teamName }
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
private async extractCookieFromSQLite(): Promise<string> {
|
|
386
|
+
const cookiesPath = join(this.slackDir, 'Cookies')
|
|
387
|
+
if (!existsSync(cookiesPath)) {
|
|
388
|
+
const networkCookiesPath = join(this.slackDir, 'Network', 'Cookies')
|
|
389
|
+
if (!existsSync(networkCookiesPath)) {
|
|
390
|
+
return ''
|
|
391
|
+
}
|
|
392
|
+
return this.readCookieFromDB(networkCookiesPath)
|
|
393
|
+
}
|
|
394
|
+
return this.readCookieFromDB(cookiesPath)
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
private readCookieFromDB(dbPath: string): string {
|
|
398
|
+
try {
|
|
399
|
+
const db = new Database(dbPath, { readonly: true })
|
|
400
|
+
|
|
401
|
+
const row = db
|
|
402
|
+
.query(
|
|
403
|
+
`SELECT value, encrypted_value
|
|
404
|
+
FROM cookies
|
|
405
|
+
WHERE name = 'd' AND host_key LIKE '%slack.com%'
|
|
406
|
+
ORDER BY last_access_utc DESC
|
|
407
|
+
LIMIT 1`
|
|
408
|
+
)
|
|
409
|
+
.get() as { value?: string; encrypted_value?: Uint8Array } | null
|
|
410
|
+
|
|
411
|
+
db.close()
|
|
412
|
+
|
|
413
|
+
if (!row) {
|
|
414
|
+
return ''
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (row.value?.startsWith('xoxd-')) {
|
|
418
|
+
return row.value
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (row.encrypted_value && row.encrypted_value.length > 0) {
|
|
422
|
+
const decrypted = this.tryDecryptCookie(Buffer.from(row.encrypted_value))
|
|
423
|
+
if (decrypted) {
|
|
424
|
+
return decrypted
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return ''
|
|
429
|
+
} catch {
|
|
430
|
+
return ''
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
private tryDecryptCookie(encrypted: Buffer): string | null {
|
|
435
|
+
const str = encrypted.toString('utf8')
|
|
436
|
+
if (str.startsWith('xoxd-')) {
|
|
437
|
+
return str
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Check for v10 encryption (macOS Keychain)
|
|
441
|
+
if (encrypted.length > 3 && encrypted.subarray(0, 3).toString() === 'v10') {
|
|
442
|
+
return this.decryptV10Cookie(encrypted)
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return null
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
private decryptV10Cookie(encrypted: Buffer): string | null {
|
|
449
|
+
try {
|
|
450
|
+
const key = this.getDerivedKey()
|
|
451
|
+
if (!key) {
|
|
452
|
+
return null
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// v10 uses AES-128-CBC with 16-space IV (Chrome/Electron pattern)
|
|
456
|
+
const iv = Buffer.alloc(16, ' ')
|
|
457
|
+
const ciphertext = encrypted.subarray(3)
|
|
458
|
+
|
|
459
|
+
const decipher = createDecipheriv('aes-128-cbc', key, iv)
|
|
460
|
+
const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])
|
|
461
|
+
const result = decrypted.toString('utf8')
|
|
462
|
+
|
|
463
|
+
// Extract xoxd- token from decrypted data (may have padding/garbage before it)
|
|
464
|
+
const match = result.match(/xoxd-[A-Za-z0-9%]+/)
|
|
465
|
+
return match ? match[0] : null
|
|
466
|
+
} catch {
|
|
467
|
+
return null
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
private getDerivedKey(): Buffer | null {
|
|
472
|
+
if (this.platform !== 'darwin') {
|
|
473
|
+
return null
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
try {
|
|
477
|
+
let password: string
|
|
478
|
+
try {
|
|
479
|
+
password = execSync(
|
|
480
|
+
'security find-generic-password -ga "Slack App Store Key" -s "Slack Safe Storage" -w 2>/dev/null',
|
|
481
|
+
{ encoding: 'utf8' }
|
|
482
|
+
).trim()
|
|
483
|
+
} catch {
|
|
484
|
+
password = execSync(
|
|
485
|
+
'security find-generic-password -ga "Slack Key" -s "Slack Safe Storage" -w 2>/dev/null',
|
|
486
|
+
{ encoding: 'utf8' }
|
|
487
|
+
).trim()
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// Chrome/Electron uses PBKDF2 with these parameters
|
|
491
|
+
return pbkdf2Sync(password, 'saltysalt', 1003, 16, 'sha1')
|
|
492
|
+
} catch {
|
|
493
|
+
return null
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core type definitions for agent-slack
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from 'zod'
|
|
6
|
+
|
|
7
|
+
export interface SlackChannel {
|
|
8
|
+
id: string
|
|
9
|
+
name: string
|
|
10
|
+
is_private: boolean
|
|
11
|
+
is_archived: boolean
|
|
12
|
+
created: number
|
|
13
|
+
creator: string
|
|
14
|
+
topic?: {
|
|
15
|
+
value: string
|
|
16
|
+
creator: string
|
|
17
|
+
last_set: number
|
|
18
|
+
}
|
|
19
|
+
purpose?: {
|
|
20
|
+
value: string
|
|
21
|
+
creator: string
|
|
22
|
+
last_set: number
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface SlackMessage {
|
|
27
|
+
ts: string
|
|
28
|
+
text: string
|
|
29
|
+
user?: string
|
|
30
|
+
username?: string
|
|
31
|
+
type: string
|
|
32
|
+
thread_ts?: string
|
|
33
|
+
reply_count?: number
|
|
34
|
+
replies?: Array<{ user: string; ts: string }>
|
|
35
|
+
edited?: {
|
|
36
|
+
user: string
|
|
37
|
+
ts: string
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface SlackUser {
|
|
42
|
+
id: string
|
|
43
|
+
name: string
|
|
44
|
+
real_name: string
|
|
45
|
+
is_admin: boolean
|
|
46
|
+
is_owner: boolean
|
|
47
|
+
is_bot: boolean
|
|
48
|
+
is_app_user: boolean
|
|
49
|
+
profile?: {
|
|
50
|
+
email?: string
|
|
51
|
+
phone?: string
|
|
52
|
+
title?: string
|
|
53
|
+
status_text?: string
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface SlackReaction {
|
|
58
|
+
name: string
|
|
59
|
+
count: number
|
|
60
|
+
users: string[]
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface SlackFile {
|
|
64
|
+
id: string
|
|
65
|
+
name: string
|
|
66
|
+
title: string
|
|
67
|
+
mimetype: string
|
|
68
|
+
size: number
|
|
69
|
+
url_private: string
|
|
70
|
+
created: number
|
|
71
|
+
user: string
|
|
72
|
+
channels?: string[]
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface SlackSearchResult {
|
|
76
|
+
ts: string
|
|
77
|
+
text: string
|
|
78
|
+
user?: string
|
|
79
|
+
username?: string
|
|
80
|
+
channel: {
|
|
81
|
+
id: string
|
|
82
|
+
name: string
|
|
83
|
+
}
|
|
84
|
+
permalink: string
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface WorkspaceCredentials {
|
|
88
|
+
workspace_id: string
|
|
89
|
+
workspace_name: string
|
|
90
|
+
token: string
|
|
91
|
+
cookie: string
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface Config {
|
|
95
|
+
current_workspace: string | null
|
|
96
|
+
workspaces: Record<string, WorkspaceCredentials>
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Zod validation schemas
|
|
100
|
+
export const SlackChannelSchema = z.object({
|
|
101
|
+
id: z.string(),
|
|
102
|
+
name: z.string(),
|
|
103
|
+
is_private: z.boolean(),
|
|
104
|
+
is_archived: z.boolean(),
|
|
105
|
+
created: z.number(),
|
|
106
|
+
creator: z.string(),
|
|
107
|
+
topic: z
|
|
108
|
+
.object({
|
|
109
|
+
value: z.string(),
|
|
110
|
+
creator: z.string(),
|
|
111
|
+
last_set: z.number(),
|
|
112
|
+
})
|
|
113
|
+
.optional(),
|
|
114
|
+
purpose: z
|
|
115
|
+
.object({
|
|
116
|
+
value: z.string(),
|
|
117
|
+
creator: z.string(),
|
|
118
|
+
last_set: z.number(),
|
|
119
|
+
})
|
|
120
|
+
.optional(),
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
export const SlackMessageSchema = z.object({
|
|
124
|
+
ts: z.string(),
|
|
125
|
+
text: z.string(),
|
|
126
|
+
user: z.string().optional(),
|
|
127
|
+
username: z.string().optional(),
|
|
128
|
+
type: z.string(),
|
|
129
|
+
thread_ts: z.string().optional(),
|
|
130
|
+
reply_count: z.number().optional(),
|
|
131
|
+
replies: z
|
|
132
|
+
.array(
|
|
133
|
+
z.object({
|
|
134
|
+
user: z.string(),
|
|
135
|
+
ts: z.string(),
|
|
136
|
+
})
|
|
137
|
+
)
|
|
138
|
+
.optional(),
|
|
139
|
+
edited: z
|
|
140
|
+
.object({
|
|
141
|
+
user: z.string(),
|
|
142
|
+
ts: z.string(),
|
|
143
|
+
})
|
|
144
|
+
.optional(),
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
export const SlackUserSchema = z.object({
|
|
148
|
+
id: z.string(),
|
|
149
|
+
name: z.string(),
|
|
150
|
+
real_name: z.string(),
|
|
151
|
+
is_admin: z.boolean(),
|
|
152
|
+
is_owner: z.boolean(),
|
|
153
|
+
is_bot: z.boolean(),
|
|
154
|
+
is_app_user: z.boolean(),
|
|
155
|
+
profile: z
|
|
156
|
+
.object({
|
|
157
|
+
email: z.string().optional(),
|
|
158
|
+
phone: z.string().optional(),
|
|
159
|
+
title: z.string().optional(),
|
|
160
|
+
status_text: z.string().optional(),
|
|
161
|
+
})
|
|
162
|
+
.optional(),
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
export const SlackReactionSchema = z.object({
|
|
166
|
+
name: z.string(),
|
|
167
|
+
count: z.number(),
|
|
168
|
+
users: z.array(z.string()),
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
export const SlackFileSchema = z.object({
|
|
172
|
+
id: z.string(),
|
|
173
|
+
name: z.string(),
|
|
174
|
+
title: z.string(),
|
|
175
|
+
mimetype: z.string(),
|
|
176
|
+
size: z.number(),
|
|
177
|
+
url_private: z.string(),
|
|
178
|
+
created: z.number(),
|
|
179
|
+
user: z.string(),
|
|
180
|
+
channels: z.array(z.string()).optional(),
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
export const WorkspaceCredentialsSchema = z.object({
|
|
184
|
+
workspace_id: z.string(),
|
|
185
|
+
workspace_name: z.string(),
|
|
186
|
+
token: z.string(),
|
|
187
|
+
cookie: z.string(),
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
export const ConfigSchema = z.object({
|
|
191
|
+
current_workspace: z.string().nullable(),
|
|
192
|
+
workspaces: z.record(z.string(), WorkspaceCredentialsSchema),
|
|
193
|
+
})
|