agent-messenger 2.2.0 → 2.4.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/README.md +16 -16
- package/.claude-plugin/marketplace.json +29 -29
- package/.claude-plugin/plugin.json +5 -5
- package/CONTRIBUTING.md +1 -1
- package/README.md +9 -6
- package/bun.lock +89 -105
- package/bunfig.toml +3 -0
- package/dist/package.json +13 -3
- package/dist/src/platforms/discordbot/client.js +2 -2
- package/dist/src/platforms/discordbot/client.js.map +1 -1
- package/dist/src/platforms/kakaotalk/cli.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/cli.js +2 -1
- package/dist/src/platforms/kakaotalk/cli.js.map +1 -1
- package/dist/src/platforms/kakaotalk/client.d.ts +2 -1
- package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/client.js +52 -2
- package/dist/src/platforms/kakaotalk/client.js.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/index.d.ts +1 -0
- package/dist/src/platforms/kakaotalk/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/index.js +1 -0
- package/dist/src/platforms/kakaotalk/commands/index.js.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/profile.d.ts +3 -0
- package/dist/src/platforms/kakaotalk/commands/profile.d.ts.map +1 -0
- package/dist/src/platforms/kakaotalk/commands/profile.js +19 -0
- package/dist/src/platforms/kakaotalk/commands/profile.js.map +1 -0
- package/dist/src/platforms/kakaotalk/index.d.ts +2 -2
- package/dist/src/platforms/kakaotalk/index.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/index.js +1 -1
- package/dist/src/platforms/kakaotalk/index.js.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/session.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/session.js +2 -1
- package/dist/src/platforms/kakaotalk/protocol/session.js.map +1 -1
- package/dist/src/platforms/kakaotalk/types.d.ts +16 -0
- package/dist/src/platforms/kakaotalk/types.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/types.js +8 -0
- package/dist/src/platforms/kakaotalk/types.js.map +1 -1
- package/dist/src/platforms/line/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/line/commands/auth.js +32 -20
- package/dist/src/platforms/line/commands/auth.js.map +1 -1
- package/dist/src/platforms/teams/commands/reaction.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/reaction.js +2 -0
- package/dist/src/platforms/teams/commands/reaction.js.map +1 -1
- package/dist/src/platforms/webex/client.d.ts +2 -0
- package/dist/src/platforms/webex/client.d.ts.map +1 -1
- package/dist/src/platforms/webex/client.js +66 -23
- package/dist/src/platforms/webex/client.js.map +1 -1
- package/dist/src/platforms/webex/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/auth.js +4 -0
- package/dist/src/platforms/webex/commands/auth.js.map +1 -1
- package/dist/src/platforms/webex/encryption.d.ts +10 -0
- package/dist/src/platforms/webex/encryption.d.ts.map +1 -0
- package/dist/src/platforms/webex/encryption.js +49 -0
- package/dist/src/platforms/webex/encryption.js.map +1 -0
- package/dist/src/platforms/webex/ensure-auth.d.ts.map +1 -1
- package/dist/src/platforms/webex/ensure-auth.js +4 -0
- package/dist/src/platforms/webex/ensure-auth.js.map +1 -1
- package/dist/src/platforms/webex/token-extractor.d.ts +6 -5
- package/dist/src/platforms/webex/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/webex/token-extractor.js +92 -43
- package/dist/src/platforms/webex/token-extractor.js.map +1 -1
- package/dist/src/platforms/webex/types.d.ts +4 -0
- package/dist/src/platforms/webex/types.d.ts.map +1 -1
- package/dist/src/platforms/webex/types.js +2 -0
- package/dist/src/platforms/webex/types.js.map +1 -1
- package/dist/src/platforms/wechatbot/cli.d.ts +5 -0
- package/dist/src/platforms/wechatbot/cli.d.ts.map +1 -0
- package/dist/src/platforms/wechatbot/cli.js +18 -0
- package/dist/src/platforms/wechatbot/cli.js.map +1 -0
- package/dist/src/platforms/wechatbot/client.d.ts +36 -0
- package/dist/src/platforms/wechatbot/client.d.ts.map +1 -0
- package/dist/src/platforms/wechatbot/client.js +208 -0
- package/dist/src/platforms/wechatbot/client.js.map +1 -0
- package/dist/src/platforms/wechatbot/commands/auth.d.ts +28 -0
- package/dist/src/platforms/wechatbot/commands/auth.d.ts.map +1 -0
- package/dist/src/platforms/wechatbot/commands/auth.js +164 -0
- package/dist/src/platforms/wechatbot/commands/auth.js.map +1 -0
- package/dist/src/platforms/wechatbot/commands/index.d.ts +5 -0
- package/dist/src/platforms/wechatbot/commands/index.d.ts.map +1 -0
- package/dist/src/platforms/wechatbot/commands/index.js +5 -0
- package/dist/src/platforms/wechatbot/commands/index.js.map +1 -0
- package/dist/src/platforms/wechatbot/commands/message.d.ts +18 -0
- package/dist/src/platforms/wechatbot/commands/message.d.ts.map +1 -0
- package/dist/src/platforms/wechatbot/commands/message.js +80 -0
- package/dist/src/platforms/wechatbot/commands/message.js.map +1 -0
- package/dist/src/platforms/wechatbot/commands/shared.d.ts +9 -0
- package/dist/src/platforms/wechatbot/commands/shared.d.ts.map +1 -0
- package/dist/src/platforms/wechatbot/commands/shared.js +13 -0
- package/dist/src/platforms/wechatbot/commands/shared.js.map +1 -0
- package/dist/src/platforms/wechatbot/commands/template.d.ts +19 -0
- package/dist/src/platforms/wechatbot/commands/template.d.ts.map +1 -0
- package/dist/src/platforms/wechatbot/commands/template.js +76 -0
- package/dist/src/platforms/wechatbot/commands/template.js.map +1 -0
- package/dist/src/platforms/wechatbot/commands/user.d.ts +20 -0
- package/dist/src/platforms/wechatbot/commands/user.d.ts.map +1 -0
- package/dist/src/platforms/wechatbot/commands/user.js +53 -0
- package/dist/src/platforms/wechatbot/commands/user.js.map +1 -0
- package/dist/src/platforms/wechatbot/credential-manager.d.ts +17 -0
- package/dist/src/platforms/wechatbot/credential-manager.d.ts.map +1 -0
- package/dist/src/platforms/wechatbot/credential-manager.js +121 -0
- package/dist/src/platforms/wechatbot/credential-manager.js.map +1 -0
- package/dist/src/platforms/wechatbot/index.d.ts +5 -0
- package/dist/src/platforms/wechatbot/index.d.ts.map +1 -0
- package/dist/src/platforms/wechatbot/index.js +4 -0
- package/dist/src/platforms/wechatbot/index.js.map +1 -0
- package/dist/src/platforms/wechatbot/types.d.ts +94 -0
- package/dist/src/platforms/wechatbot/types.d.ts.map +1 -0
- package/dist/src/platforms/wechatbot/types.js +54 -0
- package/dist/src/platforms/wechatbot/types.js.map +1 -0
- package/dist/src/platforms/whatsapp/client.d.ts +1 -0
- package/dist/src/platforms/whatsapp/client.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/client.js +27 -13
- 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 +21 -18
- package/dist/src/platforms/whatsapp/commands/auth.js.map +1 -1
- package/dist/src/platforms/whatsapp/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/credential-manager.js +14 -8
- package/dist/src/platforms/whatsapp/credential-manager.js.map +1 -1
- package/docs/content/docs/agent-skills.mdx +4 -4
- package/docs/content/docs/cli/channeltalk.mdx +1 -1
- package/docs/content/docs/cli/channeltalkbot.mdx +1 -1
- package/docs/content/docs/cli/discord.mdx +1 -1
- package/docs/content/docs/cli/discordbot.mdx +1 -1
- package/docs/content/docs/cli/instagram.mdx +1 -1
- package/docs/content/docs/cli/kakaotalk.mdx +1 -1
- package/docs/content/docs/cli/line.mdx +1 -1
- package/docs/content/docs/cli/meta.json +1 -0
- package/docs/content/docs/cli/slack.mdx +1 -1
- package/docs/content/docs/cli/slackbot.mdx +1 -1
- package/docs/content/docs/cli/teams.mdx +1 -1
- package/docs/content/docs/cli/webex.mdx +5 -3
- package/docs/content/docs/cli/wechatbot.mdx +179 -0
- package/docs/content/docs/cli/whatsapp.mdx +1 -1
- package/docs/content/docs/cli/whatsappbot.mdx +1 -1
- package/docs/content/docs/sdk/meta.json +1 -1
- package/docs/content/docs/sdk/wechatbot.mdx +282 -0
- package/docs/content/docs/tui.mdx +1 -1
- package/docs/src/app/page.tsx +5 -5
- package/package.json +13 -3
- package/skills/agent-channeltalk/SKILL.md +1 -1
- package/skills/agent-channeltalkbot/SKILL.md +1 -1
- package/skills/agent-discord/SKILL.md +1 -1
- package/skills/agent-discordbot/SKILL.md +1 -1
- package/skills/agent-instagram/SKILL.md +1 -1
- package/skills/agent-kakaotalk/SKILL.md +24 -1
- package/skills/agent-line/SKILL.md +7 -11
- package/skills/agent-line/references/authentication.md +13 -4
- package/skills/agent-slack/SKILL.md +1 -1
- package/skills/agent-slackbot/SKILL.md +1 -1
- package/skills/agent-teams/SKILL.md +1 -1
- package/skills/agent-telegram/SKILL.md +1 -1
- package/skills/agent-webex/SKILL.md +1 -1
- package/skills/agent-webex/references/authentication.md +4 -3
- package/skills/agent-webex/references/common-patterns.md +1 -1
- package/skills/agent-wechatbot/SKILL.md +385 -0
- package/skills/agent-whatsapp/SKILL.md +12 -1
- package/skills/agent-whatsappbot/SKILL.md +1 -1
- package/src/platforms/discord/credential-manager.test.ts +18 -1
- package/src/platforms/discordbot/client.ts +2 -2
- package/src/platforms/instagram/commands/auth.test.ts +216 -0
- package/src/platforms/instagram/commands/chat.test.ts +127 -0
- package/src/platforms/instagram/commands/message.test.ts +178 -0
- package/src/platforms/kakaotalk/cli.ts +2 -1
- package/src/platforms/kakaotalk/client.test.ts +157 -0
- package/src/platforms/kakaotalk/client.ts +57 -3
- package/src/platforms/kakaotalk/commands/auth.test.ts +299 -0
- package/src/platforms/kakaotalk/commands/chat.test.ts +97 -0
- package/src/platforms/kakaotalk/commands/index.ts +1 -0
- package/src/platforms/kakaotalk/commands/message.test.ts +113 -0
- package/src/platforms/kakaotalk/commands/profile.test.ts +84 -0
- package/src/platforms/kakaotalk/commands/profile.ts +21 -0
- package/src/platforms/kakaotalk/index.test.ts +5 -0
- package/src/platforms/kakaotalk/index.ts +2 -0
- package/src/platforms/kakaotalk/protocol/session.ts +2 -0
- package/src/platforms/kakaotalk/types.ts +18 -0
- package/src/platforms/line/commands/auth.test.ts +141 -0
- package/src/platforms/line/commands/auth.ts +28 -19
- package/src/platforms/line/commands/chat.test.ts +110 -0
- package/src/platforms/line/commands/friend.test.ts +98 -0
- package/src/platforms/line/commands/message.test.ts +119 -0
- package/src/platforms/line/commands/profile.test.ts +85 -0
- package/src/platforms/slackbot/commands/channel.test.ts +139 -0
- package/src/platforms/slackbot/commands/message.test.ts +226 -0
- package/src/platforms/slackbot/commands/reaction.test.ts +90 -0
- package/src/platforms/slackbot/commands/user.test.ts +143 -0
- package/src/platforms/teams/commands/reaction.test.ts +45 -61
- package/src/platforms/teams/commands/reaction.ts +2 -0
- package/src/platforms/telegram/commands/chat.test.ts +125 -0
- package/src/platforms/telegram/commands/message.test.ts +92 -0
- package/src/platforms/webex/client.ts +98 -26
- package/src/platforms/webex/commands/auth.ts +4 -0
- package/src/platforms/webex/commands/member.test.ts +65 -58
- package/src/platforms/webex/commands/message.test.ts +78 -121
- package/src/platforms/webex/commands/snapshot.test.ts +59 -46
- package/src/platforms/webex/commands/space.test.ts +49 -48
- package/src/platforms/webex/encryption.ts +53 -0
- package/src/platforms/webex/ensure-auth.ts +4 -0
- package/src/platforms/webex/token-extractor.ts +107 -40
- package/src/platforms/webex/types.ts +4 -0
- package/src/platforms/webex/typings/node-jose.d.ts +27 -0
- package/src/platforms/wechatbot/cli.ts +24 -0
- package/src/platforms/wechatbot/client.test.ts +497 -0
- package/src/platforms/wechatbot/client.ts +268 -0
- package/src/platforms/wechatbot/commands/auth.test.ts +211 -0
- package/src/platforms/wechatbot/commands/auth.ts +203 -0
- package/src/platforms/wechatbot/commands/index.ts +4 -0
- package/src/platforms/wechatbot/commands/message.test.ts +155 -0
- package/src/platforms/wechatbot/commands/message.ts +104 -0
- package/src/platforms/wechatbot/commands/shared.ts +22 -0
- package/src/platforms/wechatbot/commands/template.test.ts +199 -0
- package/src/platforms/wechatbot/commands/template.ts +102 -0
- package/src/platforms/wechatbot/commands/user.test.ts +165 -0
- package/src/platforms/wechatbot/commands/user.ts +75 -0
- package/src/platforms/wechatbot/credential-manager.test.ts +255 -0
- package/src/platforms/wechatbot/credential-manager.ts +148 -0
- package/src/platforms/wechatbot/index.test.ts +49 -0
- package/src/platforms/wechatbot/index.ts +19 -0
- package/src/platforms/wechatbot/types.test.ts +223 -0
- package/src/platforms/wechatbot/types.ts +107 -0
- package/src/platforms/whatsapp/client.ts +24 -13
- package/src/platforms/whatsapp/commands/auth.test.ts +311 -0
- package/src/platforms/whatsapp/commands/auth.ts +21 -17
- package/src/platforms/whatsapp/commands/chat.test.ts +198 -0
- package/src/platforms/whatsapp/commands/message.test.ts +231 -0
- package/src/platforms/whatsapp/credential-manager.test.ts +20 -0
- package/src/platforms/whatsapp/credential-manager.ts +17 -8
- package/src/platforms/whatsappbot/commands/auth.test.ts +217 -0
- package/src/platforms/whatsappbot/commands/message.test.ts +198 -0
- package/src/platforms/whatsappbot/commands/template.test.ts +112 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, mock, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
const mockResolveChannel = mock((_channel: string) => Promise.resolve('C123456'))
|
|
4
|
+
const mockListChannels = mock(() =>
|
|
5
|
+
Promise.resolve([
|
|
6
|
+
{
|
|
7
|
+
id: 'C123456',
|
|
8
|
+
name: 'general',
|
|
9
|
+
is_private: false,
|
|
10
|
+
is_archived: false,
|
|
11
|
+
created: 1609459200,
|
|
12
|
+
creator: 'U123',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
id: 'C789012',
|
|
16
|
+
name: 'random',
|
|
17
|
+
is_private: false,
|
|
18
|
+
is_archived: false,
|
|
19
|
+
created: 1609459200,
|
|
20
|
+
creator: 'U123',
|
|
21
|
+
},
|
|
22
|
+
]),
|
|
23
|
+
)
|
|
24
|
+
const mockGetChannelInfo = mock(() =>
|
|
25
|
+
Promise.resolve({
|
|
26
|
+
id: 'C123456',
|
|
27
|
+
name: 'general',
|
|
28
|
+
is_private: false,
|
|
29
|
+
is_archived: false,
|
|
30
|
+
created: 1609459200,
|
|
31
|
+
creator: 'U123',
|
|
32
|
+
topic: { value: 'General discussion', creator: 'U123', last_set: 1609459200 },
|
|
33
|
+
purpose: { value: 'Company-wide announcements', creator: 'U123', last_set: 1609459200 },
|
|
34
|
+
}),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
mock.module('../client', () => ({
|
|
38
|
+
SlackBotClient: class MockSlackBotClient {
|
|
39
|
+
async login(_credentials?: { token: string }) {
|
|
40
|
+
return this
|
|
41
|
+
}
|
|
42
|
+
resolveChannel = mockResolveChannel
|
|
43
|
+
listChannels = mockListChannels
|
|
44
|
+
getChannelInfo = mockGetChannelInfo
|
|
45
|
+
},
|
|
46
|
+
}))
|
|
47
|
+
|
|
48
|
+
import { SlackBotClient } from '../client'
|
|
49
|
+
|
|
50
|
+
describe('channel commands', () => {
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
mockResolveChannel.mockClear()
|
|
53
|
+
mockListChannels.mockClear()
|
|
54
|
+
mockGetChannelInfo.mockClear()
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
describe('listChannels', () => {
|
|
58
|
+
test('returns list of channels', async () => {
|
|
59
|
+
// given
|
|
60
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
61
|
+
|
|
62
|
+
// when
|
|
63
|
+
const channels = await client.listChannels()
|
|
64
|
+
|
|
65
|
+
// then
|
|
66
|
+
expect(channels).toHaveLength(2)
|
|
67
|
+
expect(channels[0].name).toBe('general')
|
|
68
|
+
expect(channels[1].name).toBe('random')
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test('includes channel metadata', async () => {
|
|
72
|
+
// given
|
|
73
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
74
|
+
|
|
75
|
+
// when
|
|
76
|
+
const channels = await client.listChannels()
|
|
77
|
+
const channel = channels[0]
|
|
78
|
+
|
|
79
|
+
// then
|
|
80
|
+
expect(channel.id).toBeDefined()
|
|
81
|
+
expect(channel.name).toBeDefined()
|
|
82
|
+
expect(channel.is_private).toBe(false)
|
|
83
|
+
expect(channel.is_archived).toBe(false)
|
|
84
|
+
expect(channel.created).toBeDefined()
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test('passes limit option', async () => {
|
|
88
|
+
// given
|
|
89
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
90
|
+
|
|
91
|
+
// when
|
|
92
|
+
await client.listChannels({ limit: 50 })
|
|
93
|
+
|
|
94
|
+
// then
|
|
95
|
+
expect(mockListChannels).toHaveBeenCalledWith({ limit: 50 })
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
describe('getChannelInfo', () => {
|
|
100
|
+
test('returns channel details', async () => {
|
|
101
|
+
// given
|
|
102
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
103
|
+
|
|
104
|
+
// when
|
|
105
|
+
const channel = await client.getChannelInfo('C123456')
|
|
106
|
+
|
|
107
|
+
// then
|
|
108
|
+
expect(channel.id).toBe('C123456')
|
|
109
|
+
expect(channel.name).toBe('general')
|
|
110
|
+
expect(channel.is_private).toBe(false)
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
test('includes topic and purpose', async () => {
|
|
114
|
+
// given
|
|
115
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
116
|
+
|
|
117
|
+
// when
|
|
118
|
+
const channel = await client.getChannelInfo('C123456')
|
|
119
|
+
|
|
120
|
+
// then
|
|
121
|
+
expect(channel.topic?.value).toBe('General discussion')
|
|
122
|
+
expect(channel.purpose?.value).toBe('Company-wide announcements')
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
describe('resolveChannel', () => {
|
|
127
|
+
test('resolves channel name to ID', async () => {
|
|
128
|
+
// given
|
|
129
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
130
|
+
|
|
131
|
+
// when
|
|
132
|
+
const channelId = await client.resolveChannel('general')
|
|
133
|
+
|
|
134
|
+
// then
|
|
135
|
+
expect(channelId).toBe('C123456')
|
|
136
|
+
expect(mockResolveChannel).toHaveBeenCalledWith('general')
|
|
137
|
+
})
|
|
138
|
+
})
|
|
139
|
+
})
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, mock, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
const mockResolveChannel = mock((_channel: string) => Promise.resolve('C123456'))
|
|
4
|
+
const mockPostMessage = mock(() =>
|
|
5
|
+
Promise.resolve({
|
|
6
|
+
ts: '1234567890.000100',
|
|
7
|
+
text: 'Hello world',
|
|
8
|
+
type: 'message',
|
|
9
|
+
user: 'U123',
|
|
10
|
+
}),
|
|
11
|
+
)
|
|
12
|
+
const mockGetConversationHistory = mock(() =>
|
|
13
|
+
Promise.resolve([
|
|
14
|
+
{ ts: '1234567890.000100', text: 'Hello', type: 'message', user: 'U123' },
|
|
15
|
+
{ ts: '1234567890.000200', text: 'World', type: 'message', user: 'U456' },
|
|
16
|
+
]),
|
|
17
|
+
)
|
|
18
|
+
const mockGetMessage = mock(() =>
|
|
19
|
+
Promise.resolve({
|
|
20
|
+
ts: '1234567890.000100',
|
|
21
|
+
text: 'Hello world',
|
|
22
|
+
type: 'message',
|
|
23
|
+
user: 'U123',
|
|
24
|
+
}),
|
|
25
|
+
)
|
|
26
|
+
const mockUpdateMessage = mock(() =>
|
|
27
|
+
Promise.resolve({
|
|
28
|
+
ts: '1234567890.000100',
|
|
29
|
+
text: 'Updated text',
|
|
30
|
+
type: 'message',
|
|
31
|
+
user: 'U123',
|
|
32
|
+
}),
|
|
33
|
+
)
|
|
34
|
+
const mockDeleteMessage = mock(() => Promise.resolve())
|
|
35
|
+
const mockGetThreadReplies = mock(() =>
|
|
36
|
+
Promise.resolve([
|
|
37
|
+
{ ts: '1234567890.000100', text: 'Thread reply 1', type: 'message', user: 'U123' },
|
|
38
|
+
{ ts: '1234567890.000200', text: 'Thread reply 2', type: 'message', user: 'U456' },
|
|
39
|
+
]),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
mock.module('../client', () => ({
|
|
43
|
+
SlackBotClient: class MockSlackBotClient {
|
|
44
|
+
async login(_credentials?: { token: string }) {
|
|
45
|
+
return this
|
|
46
|
+
}
|
|
47
|
+
resolveChannel = mockResolveChannel
|
|
48
|
+
postMessage = mockPostMessage
|
|
49
|
+
getConversationHistory = mockGetConversationHistory
|
|
50
|
+
getMessage = mockGetMessage
|
|
51
|
+
updateMessage = mockUpdateMessage
|
|
52
|
+
deleteMessage = mockDeleteMessage
|
|
53
|
+
getThreadReplies = mockGetThreadReplies
|
|
54
|
+
},
|
|
55
|
+
}))
|
|
56
|
+
|
|
57
|
+
import { SlackBotClient } from '../client'
|
|
58
|
+
|
|
59
|
+
describe('message commands', () => {
|
|
60
|
+
beforeEach(() => {
|
|
61
|
+
mockResolveChannel.mockClear()
|
|
62
|
+
mockPostMessage.mockClear()
|
|
63
|
+
mockGetConversationHistory.mockClear()
|
|
64
|
+
mockGetMessage.mockClear()
|
|
65
|
+
mockUpdateMessage.mockClear()
|
|
66
|
+
mockDeleteMessage.mockClear()
|
|
67
|
+
mockGetThreadReplies.mockClear()
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
describe('postMessage', () => {
|
|
71
|
+
test('sends message to channel', async () => {
|
|
72
|
+
// given
|
|
73
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
74
|
+
|
|
75
|
+
// when
|
|
76
|
+
const result = await client.postMessage('C123456', 'Hello world')
|
|
77
|
+
|
|
78
|
+
// then
|
|
79
|
+
expect(result.ts).toBe('1234567890.000100')
|
|
80
|
+
expect(result.text).toBe('Hello world')
|
|
81
|
+
expect(result.type).toBe('message')
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
test('sends message with thread_ts', async () => {
|
|
85
|
+
// given
|
|
86
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
87
|
+
|
|
88
|
+
// when
|
|
89
|
+
await client.postMessage('C123456', 'Thread reply', { thread_ts: '1234567890.000100' })
|
|
90
|
+
|
|
91
|
+
// then
|
|
92
|
+
expect(mockPostMessage).toHaveBeenCalledWith('C123456', 'Thread reply', { thread_ts: '1234567890.000100' })
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
describe('getConversationHistory', () => {
|
|
97
|
+
test('returns messages from channel', async () => {
|
|
98
|
+
// given
|
|
99
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
100
|
+
|
|
101
|
+
// when
|
|
102
|
+
const messages = await client.getConversationHistory('C123456', { limit: 20 })
|
|
103
|
+
|
|
104
|
+
// then
|
|
105
|
+
expect(messages).toHaveLength(2)
|
|
106
|
+
expect(messages[0].text).toBe('Hello')
|
|
107
|
+
expect(messages[1].text).toBe('World')
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test('passes limit option', async () => {
|
|
111
|
+
// given
|
|
112
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
113
|
+
|
|
114
|
+
// when
|
|
115
|
+
await client.getConversationHistory('C123456', { limit: 50 })
|
|
116
|
+
|
|
117
|
+
// then
|
|
118
|
+
expect(mockGetConversationHistory).toHaveBeenCalledWith('C123456', { limit: 50 })
|
|
119
|
+
})
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
describe('getMessage', () => {
|
|
123
|
+
test('returns single message by ts', async () => {
|
|
124
|
+
// given
|
|
125
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
126
|
+
|
|
127
|
+
// when
|
|
128
|
+
const message = await client.getMessage('C123456', '1234567890.000100')
|
|
129
|
+
|
|
130
|
+
// then
|
|
131
|
+
expect(message).not.toBeNull()
|
|
132
|
+
expect(message?.ts).toBe('1234567890.000100')
|
|
133
|
+
expect(message?.text).toBe('Hello world')
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
test('returns null when message not found', async () => {
|
|
137
|
+
// given
|
|
138
|
+
mockGetMessage.mockResolvedValueOnce(null)
|
|
139
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
140
|
+
|
|
141
|
+
// when
|
|
142
|
+
const message = await client.getMessage('C123456', 'nonexistent.ts')
|
|
143
|
+
|
|
144
|
+
// then
|
|
145
|
+
expect(message).toBeNull()
|
|
146
|
+
})
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
describe('updateMessage', () => {
|
|
150
|
+
test('updates message text', async () => {
|
|
151
|
+
// given
|
|
152
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
153
|
+
|
|
154
|
+
// when
|
|
155
|
+
const result = await client.updateMessage('C123456', '1234567890.000100', 'Updated text')
|
|
156
|
+
|
|
157
|
+
// then
|
|
158
|
+
expect(result.ts).toBe('1234567890.000100')
|
|
159
|
+
expect(result.text).toBe('Updated text')
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
test('called with correct arguments', async () => {
|
|
163
|
+
// given
|
|
164
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
165
|
+
|
|
166
|
+
// when
|
|
167
|
+
await client.updateMessage('C123456', '1234567890.000100', 'New text')
|
|
168
|
+
|
|
169
|
+
// then
|
|
170
|
+
expect(mockUpdateMessage).toHaveBeenCalledWith('C123456', '1234567890.000100', 'New text')
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
describe('deleteMessage', () => {
|
|
175
|
+
test('deletes message by ts', async () => {
|
|
176
|
+
// given
|
|
177
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
178
|
+
|
|
179
|
+
// when
|
|
180
|
+
await client.deleteMessage('C123456', '1234567890.000100')
|
|
181
|
+
|
|
182
|
+
// then
|
|
183
|
+
expect(mockDeleteMessage).toHaveBeenCalledWith('C123456', '1234567890.000100')
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
describe('getThreadReplies', () => {
|
|
188
|
+
test('returns thread replies', async () => {
|
|
189
|
+
// given
|
|
190
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
191
|
+
|
|
192
|
+
// when
|
|
193
|
+
const replies = await client.getThreadReplies('C123456', '1234567890.000100', { limit: 100 })
|
|
194
|
+
|
|
195
|
+
// then
|
|
196
|
+
expect(replies).toHaveLength(2)
|
|
197
|
+
expect(replies[0].text).toBe('Thread reply 1')
|
|
198
|
+
expect(replies[1].text).toBe('Thread reply 2')
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
test('passes limit option', async () => {
|
|
202
|
+
// given
|
|
203
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
204
|
+
|
|
205
|
+
// when
|
|
206
|
+
await client.getThreadReplies('C123456', '1234567890.000100', { limit: 50 })
|
|
207
|
+
|
|
208
|
+
// then
|
|
209
|
+
expect(mockGetThreadReplies).toHaveBeenCalledWith('C123456', '1234567890.000100', { limit: 50 })
|
|
210
|
+
})
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
describe('resolveChannel', () => {
|
|
214
|
+
test('resolves channel name to ID', async () => {
|
|
215
|
+
// given
|
|
216
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
217
|
+
|
|
218
|
+
// when
|
|
219
|
+
const channelId = await client.resolveChannel('general')
|
|
220
|
+
|
|
221
|
+
// then
|
|
222
|
+
expect(channelId).toBe('C123456')
|
|
223
|
+
expect(mockResolveChannel).toHaveBeenCalledWith('general')
|
|
224
|
+
})
|
|
225
|
+
})
|
|
226
|
+
})
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, mock, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
const mockResolveChannel = mock((_channel: string) => Promise.resolve('C123456'))
|
|
4
|
+
const mockAddReaction = mock(() => Promise.resolve())
|
|
5
|
+
const mockRemoveReaction = mock(() => Promise.resolve())
|
|
6
|
+
|
|
7
|
+
mock.module('../client', () => ({
|
|
8
|
+
SlackBotClient: class MockSlackBotClient {
|
|
9
|
+
async login(_credentials?: { token: string }) {
|
|
10
|
+
return this
|
|
11
|
+
}
|
|
12
|
+
resolveChannel = mockResolveChannel
|
|
13
|
+
addReaction = mockAddReaction
|
|
14
|
+
removeReaction = mockRemoveReaction
|
|
15
|
+
},
|
|
16
|
+
}))
|
|
17
|
+
|
|
18
|
+
import { SlackBotClient } from '../client'
|
|
19
|
+
|
|
20
|
+
describe('reaction commands', () => {
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
mockResolveChannel.mockClear()
|
|
23
|
+
mockAddReaction.mockClear()
|
|
24
|
+
mockRemoveReaction.mockClear()
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
describe('addReaction', () => {
|
|
28
|
+
test('adds emoji reaction to message', async () => {
|
|
29
|
+
// given
|
|
30
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
31
|
+
|
|
32
|
+
// when
|
|
33
|
+
await client.addReaction('C123456', '1234567890.000100', 'thumbsup')
|
|
34
|
+
|
|
35
|
+
// then
|
|
36
|
+
expect(mockAddReaction).toHaveBeenCalledWith('C123456', '1234567890.000100', 'thumbsup')
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('called with correct arguments', async () => {
|
|
40
|
+
// given
|
|
41
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
42
|
+
|
|
43
|
+
// when
|
|
44
|
+
await client.addReaction('C123456', '1234567890.000200', 'heart')
|
|
45
|
+
|
|
46
|
+
// then
|
|
47
|
+
expect(mockAddReaction).toHaveBeenCalledTimes(1)
|
|
48
|
+
expect(mockAddReaction).toHaveBeenCalledWith('C123456', '1234567890.000200', 'heart')
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe('removeReaction', () => {
|
|
53
|
+
test('removes emoji reaction from message', async () => {
|
|
54
|
+
// given
|
|
55
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
56
|
+
|
|
57
|
+
// when
|
|
58
|
+
await client.removeReaction('C123456', '1234567890.000100', 'thumbsup')
|
|
59
|
+
|
|
60
|
+
// then
|
|
61
|
+
expect(mockRemoveReaction).toHaveBeenCalledWith('C123456', '1234567890.000100', 'thumbsup')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test('called with correct arguments', async () => {
|
|
65
|
+
// given
|
|
66
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
67
|
+
|
|
68
|
+
// when
|
|
69
|
+
await client.removeReaction('C123456', '1234567890.000200', 'wave')
|
|
70
|
+
|
|
71
|
+
// then
|
|
72
|
+
expect(mockRemoveReaction).toHaveBeenCalledTimes(1)
|
|
73
|
+
expect(mockRemoveReaction).toHaveBeenCalledWith('C123456', '1234567890.000200', 'wave')
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
describe('resolveChannel', () => {
|
|
78
|
+
test('resolves channel name before reaction', async () => {
|
|
79
|
+
// given
|
|
80
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
81
|
+
|
|
82
|
+
// when
|
|
83
|
+
const channelId = await client.resolveChannel('general')
|
|
84
|
+
|
|
85
|
+
// then
|
|
86
|
+
expect(channelId).toBe('C123456')
|
|
87
|
+
expect(mockResolveChannel).toHaveBeenCalledWith('general')
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
})
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, mock, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
const mockListUsers = mock(() =>
|
|
4
|
+
Promise.resolve([
|
|
5
|
+
{
|
|
6
|
+
id: 'U123',
|
|
7
|
+
name: 'alice',
|
|
8
|
+
real_name: 'Alice Smith',
|
|
9
|
+
is_admin: false,
|
|
10
|
+
is_owner: false,
|
|
11
|
+
is_bot: false,
|
|
12
|
+
is_app_user: false,
|
|
13
|
+
profile: { email: 'alice@example.com', title: 'Engineer' },
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: 'U456',
|
|
17
|
+
name: 'bob',
|
|
18
|
+
real_name: 'Bob Jones',
|
|
19
|
+
is_admin: true,
|
|
20
|
+
is_owner: false,
|
|
21
|
+
is_bot: false,
|
|
22
|
+
is_app_user: false,
|
|
23
|
+
profile: { email: 'bob@example.com', title: 'Manager' },
|
|
24
|
+
},
|
|
25
|
+
]),
|
|
26
|
+
)
|
|
27
|
+
const mockGetUserInfo = mock(() =>
|
|
28
|
+
Promise.resolve({
|
|
29
|
+
id: 'U123',
|
|
30
|
+
name: 'alice',
|
|
31
|
+
real_name: 'Alice Smith',
|
|
32
|
+
is_admin: false,
|
|
33
|
+
is_owner: false,
|
|
34
|
+
is_bot: false,
|
|
35
|
+
is_app_user: false,
|
|
36
|
+
profile: {
|
|
37
|
+
email: 'alice@example.com',
|
|
38
|
+
phone: '+1-555-0100',
|
|
39
|
+
title: 'Engineer',
|
|
40
|
+
status_text: 'Working from home',
|
|
41
|
+
},
|
|
42
|
+
}),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
mock.module('../client', () => ({
|
|
46
|
+
SlackBotClient: class MockSlackBotClient {
|
|
47
|
+
async login(_credentials?: { token: string }) {
|
|
48
|
+
return this
|
|
49
|
+
}
|
|
50
|
+
listUsers = mockListUsers
|
|
51
|
+
getUserInfo = mockGetUserInfo
|
|
52
|
+
},
|
|
53
|
+
}))
|
|
54
|
+
|
|
55
|
+
import { SlackBotClient } from '../client'
|
|
56
|
+
|
|
57
|
+
describe('user commands', () => {
|
|
58
|
+
beforeEach(() => {
|
|
59
|
+
mockListUsers.mockClear()
|
|
60
|
+
mockGetUserInfo.mockClear()
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
describe('listUsers', () => {
|
|
64
|
+
test('returns list of users', async () => {
|
|
65
|
+
// given
|
|
66
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
67
|
+
|
|
68
|
+
// when
|
|
69
|
+
const users = await client.listUsers()
|
|
70
|
+
|
|
71
|
+
// then
|
|
72
|
+
expect(users).toHaveLength(2)
|
|
73
|
+
expect(users[0].name).toBe('alice')
|
|
74
|
+
expect(users[1].name).toBe('bob')
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('includes user metadata', async () => {
|
|
78
|
+
// given
|
|
79
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
80
|
+
|
|
81
|
+
// when
|
|
82
|
+
const users = await client.listUsers()
|
|
83
|
+
const user = users[0]
|
|
84
|
+
|
|
85
|
+
// then
|
|
86
|
+
expect(user.id).toBeDefined()
|
|
87
|
+
expect(user.name).toBeDefined()
|
|
88
|
+
expect(user.real_name).toBeDefined()
|
|
89
|
+
expect(user.is_bot).toBe(false)
|
|
90
|
+
expect(user.is_admin).toBe(false)
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
test('passes limit option', async () => {
|
|
94
|
+
// given
|
|
95
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
96
|
+
|
|
97
|
+
// when
|
|
98
|
+
await client.listUsers({ limit: 50 })
|
|
99
|
+
|
|
100
|
+
// then
|
|
101
|
+
expect(mockListUsers).toHaveBeenCalledWith({ limit: 50 })
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
describe('getUserInfo', () => {
|
|
106
|
+
test('returns user details by ID', async () => {
|
|
107
|
+
// given
|
|
108
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
109
|
+
|
|
110
|
+
// when
|
|
111
|
+
const user = await client.getUserInfo('U123')
|
|
112
|
+
|
|
113
|
+
// then
|
|
114
|
+
expect(user.id).toBe('U123')
|
|
115
|
+
expect(user.name).toBe('alice')
|
|
116
|
+
expect(user.real_name).toBe('Alice Smith')
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
test('includes profile information', async () => {
|
|
120
|
+
// given
|
|
121
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
122
|
+
|
|
123
|
+
// when
|
|
124
|
+
const user = await client.getUserInfo('U123')
|
|
125
|
+
|
|
126
|
+
// then
|
|
127
|
+
expect(user.profile?.email).toBe('alice@example.com')
|
|
128
|
+
expect(user.profile?.title).toBe('Engineer')
|
|
129
|
+
expect(user.profile?.status_text).toBe('Working from home')
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('called with correct user ID', async () => {
|
|
133
|
+
// given
|
|
134
|
+
const client = await new SlackBotClient().login({ token: 'xoxb-test-token' })
|
|
135
|
+
|
|
136
|
+
// when
|
|
137
|
+
await client.getUserInfo('U456')
|
|
138
|
+
|
|
139
|
+
// then
|
|
140
|
+
expect(mockGetUserInfo).toHaveBeenCalledWith('U456')
|
|
141
|
+
})
|
|
142
|
+
})
|
|
143
|
+
})
|