@hardlydifficult/chat 1.0.1 → 1.0.3
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/README.md +134 -45
- package/dist/Channel.d.ts +24 -13
- package/dist/Channel.d.ts.map +1 -1
- package/dist/Channel.js +99 -46
- package/dist/Channel.js.map +1 -1
- package/dist/ChatClient.d.ts +2 -2
- package/dist/ChatClient.d.ts.map +1 -1
- package/dist/ChatClient.js +5 -1
- package/dist/ChatClient.js.map +1 -1
- package/dist/Message.d.ts +91 -6
- package/dist/Message.d.ts.map +1 -1
- package/dist/Message.js +138 -9
- package/dist/Message.js.map +1 -1
- package/dist/discord/DiscordChatClient.d.ts +19 -3
- package/dist/discord/DiscordChatClient.d.ts.map +1 -1
- package/dist/discord/DiscordChatClient.js +79 -15
- package/dist/discord/DiscordChatClient.js.map +1 -1
- package/dist/discord/index.d.ts +1 -1
- package/dist/discord/index.d.ts.map +1 -1
- package/dist/discord/index.js +5 -1
- package/dist/discord/index.js.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -10
- package/dist/index.js.map +1 -1
- package/dist/outputters/discord.d.ts +19 -0
- package/dist/outputters/discord.d.ts.map +1 -0
- package/dist/outputters/discord.js +64 -0
- package/dist/outputters/discord.js.map +1 -0
- package/dist/outputters/index.d.ts +4 -0
- package/dist/outputters/index.d.ts.map +1 -0
- package/dist/outputters/index.js +8 -0
- package/dist/outputters/index.js.map +1 -0
- package/dist/outputters/slack.d.ts +24 -0
- package/dist/outputters/slack.d.ts.map +1 -0
- package/dist/outputters/slack.js +149 -0
- package/dist/outputters/slack.js.map +1 -0
- package/dist/slack/SlackChatClient.d.ts +12 -2
- package/dist/slack/SlackChatClient.d.ts.map +1 -1
- package/dist/slack/SlackChatClient.js +54 -8
- package/dist/slack/SlackChatClient.js.map +1 -1
- package/dist/slack/index.d.ts +1 -1
- package/dist/slack/index.d.ts.map +1 -1
- package/dist/slack/index.js +5 -1
- package/dist/slack/index.js.map +1 -1
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +7 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +7 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +10 -0
- package/dist/utils.js.map +1 -0
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @hardlydifficult/chat
|
|
2
2
|
|
|
3
|
-
Unified API for
|
|
3
|
+
Unified API for Discord and Slack messaging with rich document support.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -11,93 +11,152 @@ npm install @hardlydifficult/chat
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
import { createChatClient } from
|
|
14
|
+
import { createChatClient } from "@hardlydifficult/chat";
|
|
15
15
|
|
|
16
16
|
// Uses DISCORD_TOKEN and DISCORD_GUILD_ID env vars
|
|
17
|
-
const client = createChatClient({ type:
|
|
17
|
+
const client = createChatClient({ type: "discord" });
|
|
18
18
|
|
|
19
19
|
// Or for Slack: uses SLACK_BOT_TOKEN and SLACK_APP_TOKEN env vars
|
|
20
|
-
const client = createChatClient({ type:
|
|
20
|
+
const client = createChatClient({ type: "slack" });
|
|
21
21
|
|
|
22
22
|
const channel = await client.connect(channelId);
|
|
23
23
|
|
|
24
24
|
await channel
|
|
25
|
-
.postMessage(
|
|
26
|
-
.addReactions([
|
|
25
|
+
.postMessage("Vote: (1) Pizza, (2) Burgers, (3) Salad")
|
|
26
|
+
.addReactions(["1️⃣", "2️⃣", "3️⃣"])
|
|
27
|
+
.onReaction((event) => {
|
|
28
|
+
console.log(`${event.user.username} voted ${event.emoji}`);
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Rich Documents
|
|
33
|
+
|
|
34
|
+
Post rich, formatted messages using the `@hardlydifficult/document-generator` package:
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { doc } from '@hardlydifficult/document-generator';
|
|
38
|
+
import { createChatClient } from '@hardlydifficult/chat';
|
|
39
|
+
|
|
40
|
+
const client = createChatClient({ type: 'slack' });
|
|
41
|
+
const channel = await client.connect(channelId);
|
|
42
|
+
|
|
43
|
+
const report = doc()
|
|
44
|
+
.header("Daily Report")
|
|
45
|
+
.text("Here are today's **highlights**:")
|
|
46
|
+
.list(["Feature A completed", "Bug B fixed", "99.9% uptime"])
|
|
47
|
+
.divider()
|
|
48
|
+
.link("View dashboard", "https://example.com/dashboard")
|
|
49
|
+
.context("Generated automatically");
|
|
50
|
+
|
|
51
|
+
// Automatically converted to Slack Block Kit / Discord Embed
|
|
52
|
+
await channel.postMessage(report);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Message Operations
|
|
56
|
+
|
|
57
|
+
### Update Messages
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
const msg = await channel.postMessage('Initial content');
|
|
61
|
+
await msg.update('Updated content');
|
|
62
|
+
await msg.update(doc().header('New Header').text('New body'));
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Delete Messages
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
const msg = await channel.postMessage('Temporary message');
|
|
69
|
+
await msg.delete();
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Thread Replies
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
const msg = await channel.postMessage('Main message');
|
|
76
|
+
msg.postReply('This is a thread reply');
|
|
77
|
+
msg.postReply(doc().text('Rich reply with **formatting**'));
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Reactions
|
|
27
81
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
82
|
+
```typescript
|
|
83
|
+
// Add reactions and listen for user votes (chainable)
|
|
84
|
+
await channel
|
|
85
|
+
.postMessage("Pick one")
|
|
86
|
+
.addReactions(["👍", "👎", "🤷"])
|
|
87
|
+
.onReaction((event) => {
|
|
88
|
+
console.log(`${event.user.username} reacted with ${event.emoji}`);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Or wait for reactions to be added before continuing
|
|
92
|
+
const msg = await channel.postMessage("Loading...").wait();
|
|
93
|
+
msg.addReactions(["✅"]);
|
|
94
|
+
await msg.waitForReactions();
|
|
31
95
|
```
|
|
32
96
|
|
|
33
|
-
## API
|
|
97
|
+
## API Reference
|
|
34
98
|
|
|
35
99
|
### `createChatClient(config)`
|
|
36
100
|
|
|
37
101
|
```typescript
|
|
38
102
|
// Discord - env vars: DISCORD_TOKEN, DISCORD_GUILD_ID
|
|
39
103
|
createChatClient({ type: 'discord' });
|
|
40
|
-
createChatClient({ type: 'discord', token: '...', guildId: '...' });
|
|
104
|
+
createChatClient({ type: 'discord', token: '...', guildId: '...' });
|
|
41
105
|
|
|
42
106
|
// Slack - env vars: SLACK_BOT_TOKEN, SLACK_APP_TOKEN
|
|
43
107
|
createChatClient({ type: 'slack' });
|
|
44
|
-
createChatClient({ type: 'slack', token: '...', appToken: '...' });
|
|
108
|
+
createChatClient({ type: 'slack', token: '...', appToken: '...' });
|
|
45
109
|
```
|
|
46
110
|
|
|
47
111
|
### `client.connect(channelId): Promise<Channel>`
|
|
48
112
|
|
|
49
113
|
Connect to a channel.
|
|
50
114
|
|
|
51
|
-
### `channel.postMessage(
|
|
115
|
+
### `channel.postMessage(content): Message`
|
|
52
116
|
|
|
53
|
-
Post a message.
|
|
117
|
+
Post a message. Content can be a string or a Document.
|
|
54
118
|
|
|
55
119
|
### `message.addReactions(emojis): Message`
|
|
56
120
|
|
|
57
121
|
Add reactions. Chainable and awaitable.
|
|
58
122
|
|
|
59
|
-
|
|
60
|
-
await channel.postMessage('Pick one').addReactions(['1️⃣', '2️⃣']);
|
|
61
|
-
```
|
|
123
|
+
### `message.postReply(content): Message`
|
|
62
124
|
|
|
63
|
-
|
|
125
|
+
Post a reply in the message's thread.
|
|
64
126
|
|
|
65
|
-
|
|
127
|
+
### `message.update(content): Promise<void>`
|
|
66
128
|
|
|
67
|
-
|
|
68
|
-
const unsubscribe = channel.onReaction((event) => {
|
|
69
|
-
// event.emoji, event.user.id, event.user.username, event.messageId
|
|
70
|
-
});
|
|
71
|
-
```
|
|
129
|
+
Update the message content.
|
|
72
130
|
|
|
73
|
-
### `
|
|
131
|
+
### `message.delete(): Promise<void>`
|
|
74
132
|
|
|
75
|
-
|
|
133
|
+
Delete the message.
|
|
76
134
|
|
|
77
|
-
|
|
135
|
+
### `message.waitForReactions(): Promise<void>`
|
|
78
136
|
|
|
79
|
-
|
|
80
|
-
import { createChatClient } from '@hardlydifficult/chat';
|
|
137
|
+
Wait for all pending reactions to complete.
|
|
81
138
|
|
|
82
|
-
|
|
83
|
-
const channel = await client.connect(process.env.CHANNEL_ID);
|
|
139
|
+
### `message.onReaction(callback): Message`
|
|
84
140
|
|
|
85
|
-
|
|
86
|
-
const emojis = ['1️⃣', '2️⃣', '3️⃣'];
|
|
141
|
+
Listen for reactions on this message. Chainable.
|
|
87
142
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
.
|
|
143
|
+
```typescript
|
|
144
|
+
channel
|
|
145
|
+
.postMessage("Vote!")
|
|
146
|
+
.addReactions(["👍", "👎"])
|
|
147
|
+
.onReaction((event) => {
|
|
148
|
+
// event.emoji, event.user.id, event.user.username,
|
|
149
|
+
// event.messageId, event.channelId, event.timestamp
|
|
150
|
+
});
|
|
151
|
+
```
|
|
91
152
|
|
|
92
|
-
|
|
93
|
-
if (event.messageId !== message.id) return;
|
|
153
|
+
### `message.offReaction(): void`
|
|
94
154
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
```
|
|
155
|
+
Stop listening for reactions on this message.
|
|
156
|
+
|
|
157
|
+
### `client.disconnect(): Promise<void>`
|
|
158
|
+
|
|
159
|
+
Disconnect from the platform.
|
|
101
160
|
|
|
102
161
|
## Platform Setup
|
|
103
162
|
|
|
@@ -112,6 +171,36 @@ channel.onReaction((event) => {
|
|
|
112
171
|
|
|
113
172
|
1. Create app at [Slack API](https://api.slack.com/apps)
|
|
114
173
|
2. Enable Socket Mode, generate App Token
|
|
115
|
-
3. Bot scopes: `chat:write`, `reactions:write`, `reactions:read`
|
|
174
|
+
3. Bot scopes: `chat:write`, `chat:write.public`, `reactions:write`, `reactions:read`
|
|
116
175
|
4. Subscribe to: `reaction_added`
|
|
117
176
|
5. Set `SLACK_BOT_TOKEN` and `SLACK_APP_TOKEN` env vars
|
|
177
|
+
|
|
178
|
+
## Example: Interactive Poll
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
import { createChatClient } from "@hardlydifficult/chat";
|
|
182
|
+
import { doc } from "@hardlydifficult/document-generator";
|
|
183
|
+
|
|
184
|
+
const client = createChatClient({ type: "discord" });
|
|
185
|
+
const channel = await client.connect(process.env.CHANNEL_ID);
|
|
186
|
+
|
|
187
|
+
const options = ["Pizza", "Burgers", "Salad"];
|
|
188
|
+
const emojis = ["1️⃣", "2️⃣", "3️⃣"];
|
|
189
|
+
const votes: Record<string, string> = {};
|
|
190
|
+
|
|
191
|
+
const pollDoc = doc()
|
|
192
|
+
.header("🗳️ Lunch Poll")
|
|
193
|
+
.text("What should we order?")
|
|
194
|
+
.list(options.map((o, i) => `${emojis[i]} ${o}`));
|
|
195
|
+
|
|
196
|
+
await channel
|
|
197
|
+
.postMessage(pollDoc)
|
|
198
|
+
.addReactions(emojis)
|
|
199
|
+
.onReaction((event) => {
|
|
200
|
+
const choice = options[emojis.indexOf(event.emoji)];
|
|
201
|
+
if (choice) {
|
|
202
|
+
votes[event.user.id] = choice;
|
|
203
|
+
console.log(`${event.user.username} voted for ${choice}`);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
```
|
package/dist/Channel.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import type { Platform, ReactionCallback, MessageData } from './types
|
|
2
|
-
import { Message
|
|
1
|
+
import type { Platform, ReactionCallback, MessageData, MessageContent } from './types';
|
|
2
|
+
import { Message } from './Message';
|
|
3
3
|
/**
|
|
4
4
|
* Interface for platform-specific channel operations
|
|
5
5
|
*/
|
|
6
|
-
export interface ChannelOperations
|
|
7
|
-
postMessage(channelId: string,
|
|
6
|
+
export interface ChannelOperations {
|
|
7
|
+
postMessage(channelId: string, content: MessageContent, options?: {
|
|
8
|
+
threadTs?: string;
|
|
9
|
+
}): Promise<MessageData>;
|
|
10
|
+
updateMessage(messageId: string, channelId: string, content: MessageContent): Promise<void>;
|
|
11
|
+
deleteMessage(messageId: string, channelId: string): Promise<void>;
|
|
12
|
+
addReaction(messageId: string, channelId: string, emoji: string): Promise<void>;
|
|
8
13
|
subscribeToReactions(channelId: string, callback: ReactionCallback): () => void;
|
|
9
14
|
}
|
|
10
15
|
/**
|
|
@@ -14,25 +19,31 @@ export declare class Channel {
|
|
|
14
19
|
readonly id: string;
|
|
15
20
|
readonly platform: Platform;
|
|
16
21
|
private operations;
|
|
17
|
-
private
|
|
22
|
+
private messageReactionCallbacks;
|
|
18
23
|
private unsubscribeFromPlatform;
|
|
19
24
|
constructor(id: string, platform: Platform, operations: ChannelOperations);
|
|
20
25
|
/**
|
|
21
26
|
* Post a message to this channel
|
|
22
|
-
* @param
|
|
27
|
+
* @param content - Message content (string or Document)
|
|
28
|
+
* @param options - Optional message options (e.g., threadTs for threading)
|
|
23
29
|
* @returns Message object with chainable reaction methods
|
|
24
30
|
*/
|
|
25
|
-
postMessage(
|
|
31
|
+
postMessage(content: MessageContent, options?: {
|
|
32
|
+
threadTs?: string;
|
|
33
|
+
}): Message;
|
|
26
34
|
/**
|
|
27
|
-
*
|
|
28
|
-
* @param callback - Function called when users add reactions
|
|
29
|
-
* @returns Unsubscribe function
|
|
35
|
+
* Emit a reaction event to registered message-specific callbacks
|
|
30
36
|
*/
|
|
31
|
-
|
|
37
|
+
private emitReaction;
|
|
32
38
|
/**
|
|
33
|
-
*
|
|
39
|
+
* Subscribe to reactions for a specific message
|
|
40
|
+
* @internal Used by Message.onReaction
|
|
34
41
|
*/
|
|
35
|
-
private
|
|
42
|
+
private subscribeToMessageReactions;
|
|
43
|
+
/**
|
|
44
|
+
* Create MessageOperations from ChannelOperations
|
|
45
|
+
*/
|
|
46
|
+
private createMessageOperations;
|
|
36
47
|
/**
|
|
37
48
|
* Disconnect from this channel (cleanup)
|
|
38
49
|
*/
|
package/dist/Channel.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Channel.d.ts","sourceRoot":"","sources":["../src/Channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"Channel.d.ts","sourceRoot":"","sources":["../src/Channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACvF,OAAO,EAAE,OAAO,EAA0B,MAAM,WAAW,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,CACT,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9B,OAAO,CAAC,WAAW,CAAC,CAAC;IACxB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5F,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM,IAAI,CAAC;CACjF;AAED;;GAEG;AACH,qBAAa,OAAO;IAClB,SAAgB,EAAE,EAAE,MAAM,CAAC;IAC3B,SAAgB,QAAQ,EAAE,QAAQ,CAAC;IAEnC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,wBAAwB,CAA4C;IAC5E,OAAO,CAAC,uBAAuB,CAA6B;gBAEhD,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,iBAAiB;IAWzE;;;;;OAKG;IACH,WAAW,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO;IAY9E;;OAEG;YACW,YAAY;IAa1B;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IAgBnC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAe/B;;OAEG;IACH,UAAU,IAAI,IAAI;CAOnB"}
|
package/dist/Channel.js
CHANGED
|
@@ -1,50 +1,77 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Channel = void 0;
|
|
4
|
+
const Message_1 = require("./Message");
|
|
2
5
|
/**
|
|
3
6
|
* Represents a connected channel with messaging capabilities
|
|
4
7
|
*/
|
|
5
|
-
|
|
8
|
+
class Channel {
|
|
6
9
|
id;
|
|
7
10
|
platform;
|
|
8
11
|
operations;
|
|
9
|
-
|
|
12
|
+
messageReactionCallbacks = new Map();
|
|
10
13
|
unsubscribeFromPlatform = null;
|
|
11
14
|
constructor(id, platform, operations) {
|
|
12
15
|
this.id = id;
|
|
13
16
|
this.platform = platform;
|
|
14
17
|
this.operations = operations;
|
|
15
|
-
// Subscribe to platform reactions and forward to
|
|
18
|
+
// Subscribe to platform reactions and forward to message-specific callbacks
|
|
16
19
|
this.unsubscribeFromPlatform = this.operations.subscribeToReactions(id, (event) => this.emitReaction(event));
|
|
17
20
|
}
|
|
18
21
|
/**
|
|
19
22
|
* Post a message to this channel
|
|
20
|
-
* @param
|
|
23
|
+
* @param content - Message content (string or Document)
|
|
24
|
+
* @param options - Optional message options (e.g., threadTs for threading)
|
|
21
25
|
* @returns Message object with chainable reaction methods
|
|
22
26
|
*/
|
|
23
|
-
postMessage(
|
|
24
|
-
const messagePromise = this.operations.postMessage(this.id,
|
|
27
|
+
postMessage(content, options) {
|
|
28
|
+
const messagePromise = this.operations.postMessage(this.id, content, options);
|
|
25
29
|
// Create a Message that will resolve once the post completes
|
|
26
|
-
const pendingMessage = new PendingMessage(messagePromise, this.
|
|
30
|
+
const pendingMessage = new PendingMessage(messagePromise, this.createMessageOperations(), this.platform);
|
|
27
31
|
return pendingMessage;
|
|
28
32
|
}
|
|
29
33
|
/**
|
|
30
|
-
*
|
|
31
|
-
* @param callback - Function called when users add reactions
|
|
32
|
-
* @returns Unsubscribe function
|
|
34
|
+
* Emit a reaction event to registered message-specific callbacks
|
|
33
35
|
*/
|
|
34
|
-
|
|
35
|
-
this.
|
|
36
|
+
async emitReaction(event) {
|
|
37
|
+
const callbacks = this.messageReactionCallbacks.get(event.messageId);
|
|
38
|
+
if (!callbacks) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const promises = Array.from(callbacks).map((cb) => Promise.resolve(cb(event)).catch((err) => {
|
|
42
|
+
console.error('Reaction callback error:', err);
|
|
43
|
+
}));
|
|
44
|
+
await Promise.all(promises);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Subscribe to reactions for a specific message
|
|
48
|
+
* @internal Used by Message.onReaction
|
|
49
|
+
*/
|
|
50
|
+
subscribeToMessageReactions(messageId, callback) {
|
|
51
|
+
let callbacks = this.messageReactionCallbacks.get(messageId);
|
|
52
|
+
if (!callbacks) {
|
|
53
|
+
callbacks = new Set();
|
|
54
|
+
this.messageReactionCallbacks.set(messageId, callbacks);
|
|
55
|
+
}
|
|
56
|
+
callbacks.add(callback);
|
|
36
57
|
return () => {
|
|
37
|
-
|
|
58
|
+
callbacks.delete(callback);
|
|
59
|
+
if (callbacks.size === 0) {
|
|
60
|
+
this.messageReactionCallbacks.delete(messageId);
|
|
61
|
+
}
|
|
38
62
|
};
|
|
39
63
|
}
|
|
40
64
|
/**
|
|
41
|
-
*
|
|
65
|
+
* Create MessageOperations from ChannelOperations
|
|
42
66
|
*/
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
67
|
+
createMessageOperations() {
|
|
68
|
+
return {
|
|
69
|
+
addReaction: (messageId, channelId, emoji) => this.operations.addReaction(messageId, channelId, emoji),
|
|
70
|
+
updateMessage: (messageId, channelId, content) => this.operations.updateMessage(messageId, channelId, content),
|
|
71
|
+
deleteMessage: (messageId, channelId) => this.operations.deleteMessage(messageId, channelId),
|
|
72
|
+
postReply: async (channelId, threadTs, content) => this.operations.postMessage(channelId, content, { threadTs }),
|
|
73
|
+
subscribeToReactions: (messageId, callback) => this.subscribeToMessageReactions(messageId, callback),
|
|
74
|
+
};
|
|
48
75
|
}
|
|
49
76
|
/**
|
|
50
77
|
* Disconnect from this channel (cleanup)
|
|
@@ -54,52 +81,78 @@ export class Channel {
|
|
|
54
81
|
this.unsubscribeFromPlatform();
|
|
55
82
|
this.unsubscribeFromPlatform = null;
|
|
56
83
|
}
|
|
57
|
-
this.
|
|
84
|
+
this.messageReactionCallbacks.clear();
|
|
58
85
|
}
|
|
59
86
|
}
|
|
87
|
+
exports.Channel = Channel;
|
|
60
88
|
/**
|
|
61
|
-
* A Message that is still being posted
|
|
89
|
+
* A Message that is still being posted.
|
|
90
|
+
* Use `.wait()` to await completion and handle errors.
|
|
62
91
|
*/
|
|
63
|
-
class PendingMessage extends Message {
|
|
92
|
+
class PendingMessage extends Message_1.Message {
|
|
64
93
|
postPromise;
|
|
65
|
-
|
|
66
|
-
constructor(postPromise,
|
|
67
|
-
// Initialize with placeholder data
|
|
68
|
-
super({ id: '', channelId: '', platform
|
|
94
|
+
deferredReactionCallbacks = [];
|
|
95
|
+
constructor(postPromise, operations, platform) {
|
|
96
|
+
// Initialize with placeholder data using the correct platform
|
|
97
|
+
super({ id: '', channelId: '', platform }, operations);
|
|
69
98
|
this.postPromise = postPromise;
|
|
70
|
-
// Update our data when the post resolves
|
|
71
|
-
|
|
72
|
-
|
|
99
|
+
// Update our data when the post resolves and subscribe any deferred listeners
|
|
100
|
+
this.postPromise
|
|
101
|
+
.then((data) => {
|
|
73
102
|
// Update the readonly properties via Object.defineProperty
|
|
74
103
|
Object.defineProperty(this, 'id', { value: data.id });
|
|
75
104
|
Object.defineProperty(this, 'channelId', { value: data.channelId });
|
|
76
105
|
Object.defineProperty(this, 'platform', { value: data.platform });
|
|
106
|
+
// Subscribe deferred reaction callbacks now that we have the message ID
|
|
107
|
+
for (const callback of this.deferredReactionCallbacks) {
|
|
108
|
+
const unsubscribe = this.operations.subscribeToReactions(data.id, callback);
|
|
109
|
+
this.reactionUnsubscribers.push(unsubscribe);
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
.catch(() => {
|
|
113
|
+
// Errors handled via wait()
|
|
77
114
|
});
|
|
78
115
|
}
|
|
79
116
|
/**
|
|
80
117
|
* Override addReactions to wait for post to complete first
|
|
81
118
|
*/
|
|
82
119
|
addReactions(emojis) {
|
|
83
|
-
// Chain after the post completes
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
120
|
+
// Chain after the post completes, capturing current pendingReactions
|
|
121
|
+
const currentPendingReactions = this.pendingReactions;
|
|
122
|
+
this.pendingReactions = this.postPromise.then(() => currentPendingReactions);
|
|
123
|
+
for (const emoji of emojis) {
|
|
124
|
+
this.pendingReactions = this.pendingReactions.then(() => this.operations.addReaction(this.id, this.channelId, emoji));
|
|
125
|
+
}
|
|
87
126
|
return this;
|
|
88
127
|
}
|
|
89
128
|
/**
|
|
90
|
-
*
|
|
129
|
+
* Override onReaction to defer subscription until post completes
|
|
91
130
|
*/
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
131
|
+
onReaction(callback) {
|
|
132
|
+
this.deferredReactionCallbacks.push(callback);
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Wait for post to complete.
|
|
137
|
+
* Throws if the post fails - allows callers to handle errors.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* const msg = channel.postMessage('Hello');
|
|
142
|
+
* await msg.wait(); // throws if post fails
|
|
143
|
+
* console.log(msg.id); // now available
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
async wait() {
|
|
147
|
+
await this.postPromise;
|
|
148
|
+
return this;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Wait for post and all pending reactions to complete.
|
|
152
|
+
*/
|
|
153
|
+
async waitForReactions() {
|
|
154
|
+
await this.postPromise;
|
|
155
|
+
await this.pendingReactions;
|
|
103
156
|
}
|
|
104
157
|
}
|
|
105
158
|
//# sourceMappingURL=Channel.js.map
|
package/dist/Channel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Channel.js","sourceRoot":"","sources":["../src/Channel.ts"],"names":[],"mappings":"AACA,
|
|
1
|
+
{"version":3,"file":"Channel.js","sourceRoot":"","sources":["../src/Channel.ts"],"names":[],"mappings":"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"}
|
package/dist/ChatClient.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ChatConfig } from './types
|
|
2
|
-
import type { Channel } from './Channel
|
|
1
|
+
import type { ChatConfig } from './types';
|
|
2
|
+
import type { Channel } from './Channel';
|
|
3
3
|
/**
|
|
4
4
|
* Abstract base class for chat platform clients
|
|
5
5
|
* Provides a unified API for Discord and Slack
|
package/dist/ChatClient.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatClient.d.ts","sourceRoot":"","sources":["../src/ChatClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ChatClient.d.ts","sourceRoot":"","sources":["../src/ChatClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC;;;GAGG;AACH,8BAAsB,UAAU;IAClB,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,UAAU;gBAAlB,MAAM,EAAE,UAAU;IAEjD;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAErD;;OAEG;IACH,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CACrC"}
|
package/dist/ChatClient.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChatClient = void 0;
|
|
1
4
|
/**
|
|
2
5
|
* Abstract base class for chat platform clients
|
|
3
6
|
* Provides a unified API for Discord and Slack
|
|
4
7
|
*/
|
|
5
|
-
|
|
8
|
+
class ChatClient {
|
|
6
9
|
config;
|
|
7
10
|
constructor(config) {
|
|
8
11
|
this.config = config;
|
|
9
12
|
}
|
|
10
13
|
}
|
|
14
|
+
exports.ChatClient = ChatClient;
|
|
11
15
|
//# sourceMappingURL=ChatClient.js.map
|
package/dist/ChatClient.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatClient.js","sourceRoot":"","sources":["../src/ChatClient.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,
|
|
1
|
+
{"version":3,"file":"ChatClient.js","sourceRoot":"","sources":["../src/ChatClient.ts"],"names":[],"mappings":";;;AAGA;;;GAGG;AACH,MAAsB,UAAU;IACC;IAA/B,YAA+B,MAAkB;QAAlB,WAAM,GAAN,MAAM,CAAY;IAAG,CAAC;CAatD;AAdD,gCAcC"}
|