@hardlydifficult/chat 1.1.124 → 1.1.126
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 +137 -12
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -404,7 +404,7 @@ import type { Member, Message, Thread, MessageBatch } from "@hardlydifficult/cha
|
|
|
404
404
|
### Streaming Behavior
|
|
405
405
|
|
|
406
406
|
| Feature | Discord | Slack |
|
|
407
|
-
|
|
407
|
+
|---------|:-----:|:-----:|
|
|
408
408
|
| Message editing | ✅ | ✅ |
|
|
409
409
|
| Stream chunking | Automatic, 1000 chars | Automatic, 2000 chars |
|
|
410
410
|
| Truncation | Oldest first | Oldest first |
|
|
@@ -667,18 +667,143 @@ console.log(MESSAGE_LIMITS.SLACK_MAX_MESSAGE_LENGTH); // 4000
|
|
|
667
667
|
|
|
668
668
|
### Platform Differences
|
|
669
669
|
|
|
670
|
-
| Feature
|
|
671
|
-
|
|
672
|
-
| Typing indicators
|
|
673
|
-
| Message length limit
|
|
674
|
-
| Thread creation
|
|
675
|
-
| Bulk delete
|
|
676
|
-
| Emoji format
|
|
677
|
-
| File uploads
|
|
670
|
+
| Feature | Discord | Slack |
|
|
671
|
+
|---------|:-----:|:-----:|
|
|
672
|
+
| Typing indicators | ✅ Supported | ❌ No API support (no-op) |
|
|
673
|
+
| Message length limit | 2000 characters | 4000 characters |
|
|
674
|
+
| Thread creation | Explicit thread channel | Implicit via parent message ts |
|
|
675
|
+
| Bulk delete | ✅ Up to 100 messages at once | ❌ Must delete one-by-one |
|
|
676
|
+
| Emoji format | Plain Unicode or `:name:` | Colon-wrapped `:name:` |
|
|
677
|
+
| File uploads | As attachments | Via `filesUploadV2` API |
|
|
678
678
|
|
|
679
679
|
### Message Limits
|
|
680
680
|
|
|
681
681
|
| Platform | Max Message Length | Notes |
|
|
682
|
-
|
|
683
|
-
| Discord
|
|
684
|
-
| Slack
|
|
682
|
+
|---------|-------------------|-------|
|
|
683
|
+
| Discord | 2000 | Embed-only messages may be larger |
|
|
684
|
+
| Slack | 4000 | Per block element; message may contain many |
|
|
685
|
+
|
|
686
|
+
## Core Components
|
|
687
|
+
|
|
688
|
+
### Chat Clients
|
|
689
|
+
- **`DiscordChatClient`** - Discord implementation using `discord.js`
|
|
690
|
+
- **`SlackChatClient`** - Slack implementation using `@slack/bolt`
|
|
691
|
+
- **`ChatClient`** - Abstract base class shared by both implementations
|
|
692
|
+
|
|
693
|
+
### Channel & Message Abstraction
|
|
694
|
+
- **`Channel`** - Unified channel interface supporting posts, threads, reactions, and message tracking
|
|
695
|
+
- **`Message`** - Represents a message with operations for updates, deletes, and reactions
|
|
696
|
+
- **`PendingMessage`** - A message still being posted, awaitable and chainable
|
|
697
|
+
- **`Thread`** - Thread management with streaming and reply subscription
|
|
698
|
+
- **`MessageBatch`** - Logical group of messages for batch operations
|
|
699
|
+
- **`batchStore`** - In-memory storage for tracking message batches
|
|
700
|
+
|
|
701
|
+
### Streaming & Output
|
|
702
|
+
- **`StreamingReply`** - Buffers and flushes text as multiple messages with auto-chunking
|
|
703
|
+
- **`StreamingThread`** - Extends streaming for thread context with auto-creation and cleanup
|
|
704
|
+
- **`StreamConsumer`** - Converts an async generator into a streaming reply
|
|
705
|
+
|
|
706
|
+
### Command Handling
|
|
707
|
+
- **`CommandParser`** - Parses user input with channel awareness and member lookups
|
|
708
|
+
- **`findBestMemberMatch`** - Fuzzy member matching by ID, mention, name, email, etc.
|
|
709
|
+
- **`MessageContext`** - Contextual info for command execution
|
|
710
|
+
- **`CommandContext`** - Full execution context for commands
|
|
711
|
+
|
|
712
|
+
### Utilities
|
|
713
|
+
- **`channelIdToName`** - Extracts readable channel name from ID
|
|
714
|
+
- **`extractMentionId`** - Extracts user ID from Discord mention format
|
|
715
|
+
- **`isDocument`** - Type guard for Document objects in content
|
|
716
|
+
- **`toDiscordEmbed`** - Converts Document blocks to Discord embed format
|
|
717
|
+
- **`toSlackBlocks`** - Converts Document blocks to Slack Block Kit format
|
|
718
|
+
|
|
719
|
+
### Job Lifecycle
|
|
720
|
+
- **`setupJobLifecycle`** - Manages cancel/dismiss flow for long-running jobs
|
|
721
|
+
- **`EMOJI_CANCEL`** - ❌ Emoji for canceling jobs
|
|
722
|
+
- **`EMOJI_DISMISS`** - 🗑️ Emoji for deleting completed jobs
|
|
723
|
+
|
|
724
|
+
## Usage
|
|
725
|
+
|
|
726
|
+
### Creating a client
|
|
727
|
+
|
|
728
|
+
```ts
|
|
729
|
+
import { DiscordChatClient, SlackChatClient } from "@hardlydifficult/chat";
|
|
730
|
+
|
|
731
|
+
// Discord
|
|
732
|
+
const discordClient = new DiscordChatClient({
|
|
733
|
+
token: process.env.DISCORD_TOKEN!,
|
|
734
|
+
guildId: process.env.DISCORD_GUILD_ID!,
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
// Slack
|
|
738
|
+
const slackClient = new SlackChatClient({
|
|
739
|
+
token: process.env.SLACK_BOT_TOKEN!,
|
|
740
|
+
appToken: process.env.SLACK_APP_TOKEN!,
|
|
741
|
+
});
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
### Subscribing to messages and commands
|
|
745
|
+
|
|
746
|
+
```ts
|
|
747
|
+
const channel = await client.connect(channelId);
|
|
748
|
+
|
|
749
|
+
channel.onMessage(async (event) => {
|
|
750
|
+
if (event.content.startsWith("!")) {
|
|
751
|
+
const { command, args, context } = new CommandParser(channel).parse(event.content);
|
|
752
|
+
if (command === "help") {
|
|
753
|
+
await channel.postMessage("Here's how to use this bot...");
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
});
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
### Posting with formatting
|
|
760
|
+
|
|
761
|
+
```ts
|
|
762
|
+
import { Document, heading, text, list } from "@hardlydifficult/document-generator";
|
|
763
|
+
|
|
764
|
+
const doc = new Document()
|
|
765
|
+
.addBlock(heading("My Title", 1))
|
|
766
|
+
.addBlock(text("This is some **bold** text."))
|
|
767
|
+
.addBlock(list(["Item 1", "Item 2", "Item 3"]));
|
|
768
|
+
|
|
769
|
+
await channel.postMessage(doc);
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
### Streaming replies
|
|
773
|
+
|
|
774
|
+
```ts
|
|
775
|
+
import { StreamingReply, StreamConsumer } from "@hardlydifficult/chat";
|
|
776
|
+
|
|
777
|
+
const stream = new StreamingReply(channel);
|
|
778
|
+
stream.append("Hello ");
|
|
779
|
+
await stream.flush();
|
|
780
|
+
|
|
781
|
+
// Later...
|
|
782
|
+
stream.append("world!");
|
|
783
|
+
await stream.flush();
|
|
784
|
+
|
|
785
|
+
// Or stream from an async generator
|
|
786
|
+
const asyncGenerator = (function* () {
|
|
787
|
+
yield "Part 1\n";
|
|
788
|
+
yield "Part 2\n";
|
|
789
|
+
yield "Part 3\n";
|
|
790
|
+
})();
|
|
791
|
+
|
|
792
|
+
await new StreamConsumer(stream, asyncGenerator()).consume();
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
## Installation
|
|
796
|
+
|
|
797
|
+
```bash
|
|
798
|
+
npm install @hardlydifficult/chat
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
## Dependencies
|
|
802
|
+
|
|
803
|
+
- `discord.js` for Discord integration
|
|
804
|
+
- `@slack/bolt` for Slack integration
|
|
805
|
+
- `@hardlydifficult/document-generator` for structured content
|
|
806
|
+
|
|
807
|
+
## License
|
|
808
|
+
|
|
809
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hardlydifficult/chat",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.126",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
"discord.js": "14.25.1"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@hardlydifficult/document-generator": "1.1.
|
|
22
|
+
"@hardlydifficult/document-generator": "1.1.13",
|
|
23
23
|
"@types/node": "25.3.0",
|
|
24
24
|
"typescript": "5.9.3",
|
|
25
25
|
"vitest": "4.0.18"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@hardlydifficult/document-generator": "1.1.
|
|
28
|
+
"@hardlydifficult/document-generator": "1.1.13"
|
|
29
29
|
},
|
|
30
30
|
"type": "commonjs",
|
|
31
31
|
"engines": {
|