@urugus/slack-cli 0.2.10 → 0.2.11

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 CHANGED
@@ -143,6 +143,23 @@ slack-cli unread --format json
143
143
  slack-cli unread --format simple
144
144
  ```
145
145
 
146
+ ### List Scheduled Messages
147
+
148
+ ```bash
149
+ # List scheduled messages
150
+ slack-cli scheduled
151
+
152
+ # Filter by channel
153
+ slack-cli scheduled -c general
154
+
155
+ # Limit results
156
+ slack-cli scheduled --limit 20
157
+
158
+ # Output in different formats
159
+ slack-cli scheduled --format json
160
+ slack-cli scheduled --format simple
161
+ ```
162
+
146
163
  ### Other Commands
147
164
 
148
165
  ```bash
@@ -162,44 +179,56 @@ slack-cli config set --token NEW_TOKEN
162
179
  ## Options
163
180
 
164
181
  ### Global Options
165
- | Option | Short | Description |
166
- |--------|-------|-------------|
167
- | --profile | -p | Use specific workspace profile |
182
+
183
+ | Option | Short | Description |
184
+ | --------- | ----- | ------------------------------ |
185
+ | --profile | -p | Use specific workspace profile |
168
186
 
169
187
  ### send command
170
- | Option | Short | Description |
171
- |--------|-------|-------------|
172
- | --channel | -c | Target channel name or ID (required) |
173
- | --message | -m | Message to send |
174
- | --file | -f | File containing message content |
175
- | --thread | -t | Thread timestamp to reply to |
176
- | --at | | Schedule time (Unix seconds or ISO 8601) |
177
- | --after | | Schedule message after N minutes |
188
+
189
+ | Option | Short | Description |
190
+ | --------- | ----- | ---------------------------------------- |
191
+ | --channel | -c | Target channel name or ID (required) |
192
+ | --message | -m | Message to send |
193
+ | --file | -f | File containing message content |
194
+ | --thread | -t | Thread timestamp to reply to |
195
+ | --at | | Schedule time (Unix seconds or ISO 8601) |
196
+ | --after | | Schedule message after N minutes |
178
197
 
179
198
  ### channels command
180
- | Option | Short | Description |
181
- |--------|-------|-------------|
182
- | --type | | Channel type: public, private, im, mpim, all (default: public) |
183
- | --include-archived | | Include archived channels |
184
- | --format | | Output format: table, simple, json (default: table) |
185
- | --limit | | Maximum number of channels to list (default: 100) |
199
+
200
+ | Option | Short | Description |
201
+ | ------------------ | ----- | -------------------------------------------------------------- |
202
+ | --type | | Channel type: public, private, im, mpim, all (default: public) |
203
+ | --include-archived | | Include archived channels |
204
+ | --format | | Output format: table, simple, json (default: table) |
205
+ | --limit | | Maximum number of channels to list (default: 100) |
186
206
 
187
207
  ### history command
188
- | Option | Short | Description |
189
- |--------|-------|-------------|
190
- | --channel | -c | Target channel name or ID (required) |
191
- | --number | -n | Number of messages to retrieve (default: 10) |
192
- | --since | | Get messages since specific date (YYYY-MM-DD HH:MM:SS) |
208
+
209
+ | Option | Short | Description |
210
+ | --------- | ----- | ------------------------------------------------------ |
211
+ | --channel | -c | Target channel name or ID (required) |
212
+ | --number | -n | Number of messages to retrieve (default: 10) |
213
+ | --since | | Get messages since specific date (YYYY-MM-DD HH:MM:SS) |
193
214
 
194
215
  ### unread command
195
- | Option | Short | Description |
196
- |--------|-------|-------------|
197
- | --channel | -c | Get unread for specific channel |
198
- | --format | | Output format: table, simple, json (default: table) |
199
- | --count-only | | Show only unread counts |
200
- | --limit | | Maximum number of channels to display (default: 50) |
201
- | --mark-read | | Mark messages as read after fetching |
202
216
 
217
+ | Option | Short | Description |
218
+ | ------------ | ----- | --------------------------------------------------- |
219
+ | --channel | -c | Get unread for specific channel |
220
+ | --format | | Output format: table, simple, json (default: table) |
221
+ | --count-only | | Show only unread counts |
222
+ | --limit | | Maximum number of channels to display (default: 50) |
223
+ | --mark-read | | Mark messages as read after fetching |
224
+
225
+ ### scheduled command
226
+
227
+ | Option | Short | Description |
228
+ | --------- | ----- | ---------------------------------------------------------- |
229
+ | --channel | -c | Filter by channel name or ID |
230
+ | --limit | | Maximum number of scheduled messages to list (default: 50) |
231
+ | --format | | Output format: table, simple, json (default: table) |
203
232
 
204
233
  ## Required Permissions
205
234
 
@@ -216,19 +245,25 @@ Your Slack API token needs the following scopes:
216
245
  ## Advanced Features
217
246
 
218
247
  ### Rate Limiting
248
+
219
249
  The CLI includes built-in rate limiting to handle Slack API limits:
250
+
220
251
  - Concurrent requests: 3
221
252
  - Automatic retry with exponential backoff (max 3 retries)
222
253
  - Graceful error handling for rate limit errors
223
254
 
224
255
  ### Output Formats
256
+
225
257
  Most commands support multiple output formats:
258
+
226
259
  - `table` (default) - Human-readable table format
227
260
  - `simple` - Simplified text output
228
261
  - `json` - Machine-readable JSON format
229
262
 
230
263
  ### Markdown Support
264
+
231
265
  Messages sent via the `send` command automatically support Slack's mrkdwn formatting:
266
+
232
267
  - `*bold*` for bold text
233
268
  - `_italic_` for italic text
234
269
  - `~strikethrough~` for strikethrough
@@ -240,4 +275,4 @@ Messages sent via the `send` command automatically support Slack's mrkdwn format
240
275
 
241
276
  ## License
242
277
 
243
- MIT
278
+ MIT
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function setupScheduledCommand(): Command;
3
+ //# sourceMappingURL=scheduled.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduled.d.ts","sourceRoot":"","sources":["../../src/commands/scheduled.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkCpC,wBAAgB,qBAAqB,IAAI,OAAO,CAoC/C"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setupScheduledCommand = setupScheduledCommand;
4
+ const commander_1 = require("commander");
5
+ const command_wrapper_1 = require("../utils/command-wrapper");
6
+ const client_factory_1 = require("../utils/client-factory");
7
+ const option_parsers_1 = require("../utils/option-parsers");
8
+ const validators_1 = require("../utils/validators");
9
+ function formatPostAt(postAt) {
10
+ return new Date(postAt * 1000).toISOString();
11
+ }
12
+ function renderTable(messages) {
13
+ const rows = messages.map((message) => ({
14
+ id: message.id,
15
+ channel: message.channel_id,
16
+ post_at: formatPostAt(message.post_at),
17
+ text: message.text || '',
18
+ }));
19
+ console.table(rows);
20
+ }
21
+ function renderSimple(messages) {
22
+ for (const message of messages) {
23
+ console.log(`${formatPostAt(message.post_at)} ${message.channel_id} ${message.id} ${message.text || ''}`);
24
+ }
25
+ }
26
+ function setupScheduledCommand() {
27
+ const scheduledCommand = new commander_1.Command('scheduled')
28
+ .description('List scheduled messages')
29
+ .option('-c, --channel <channel>', 'Filter by channel name or ID')
30
+ .option('--limit <number>', 'Maximum number of scheduled messages to list', '50')
31
+ .option('--format <format>', 'Output format: table, simple, json', 'table')
32
+ .option('--profile <profile>', 'Use specific workspace profile')
33
+ .hook('preAction', (0, validators_1.createValidationHook)([validators_1.optionValidators.format]))
34
+ .action((0, command_wrapper_1.wrapCommand)(async (options) => {
35
+ const client = await (0, client_factory_1.createSlackClient)(options.profile);
36
+ const limit = (0, option_parsers_1.parseLimit)(options.limit, 50);
37
+ const messages = await client.listScheduledMessages(options.channel, limit);
38
+ if (messages.length === 0) {
39
+ console.log('No scheduled messages found');
40
+ return;
41
+ }
42
+ const format = (0, option_parsers_1.parseFormat)(options.format);
43
+ if (format === 'json') {
44
+ console.log(JSON.stringify(messages, null, 2));
45
+ return;
46
+ }
47
+ if (format === 'simple') {
48
+ renderSimple(messages);
49
+ return;
50
+ }
51
+ renderTable(messages);
52
+ }));
53
+ return scheduledCommand;
54
+ }
55
+ //# sourceMappingURL=scheduled.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduled.js","sourceRoot":"","sources":["../../src/commands/scheduled.ts"],"names":[],"mappings":";;AAkCA,sDAoCC;AAtED,yCAAoC;AACpC,8DAAuD;AACvD,4DAA4D;AAE5D,4DAAkE;AAClE,oDAA6E;AAE7E,SAAS,YAAY,CAAC,MAAc;IAClC,OAAO,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,WAAW,CAClB,QAAmF;IAEnF,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACtC,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,OAAO,EAAE,OAAO,CAAC,UAAU;QAC3B,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC;QACtC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;KACzB,CAAC,CAAC,CAAC;IAEJ,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,YAAY,CACnB,QAAmF;IAEnF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CACT,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,EAAE,IAAI,OAAO,CAAC,IAAI,IAAI,EAAE,EAAE,CAC7F,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAgB,qBAAqB;IACnC,MAAM,gBAAgB,GAAG,IAAI,mBAAO,CAAC,WAAW,CAAC;SAC9C,WAAW,CAAC,yBAAyB,CAAC;SACtC,MAAM,CAAC,yBAAyB,EAAE,8BAA8B,CAAC;SACjE,MAAM,CAAC,kBAAkB,EAAE,8CAA8C,EAAE,IAAI,CAAC;SAChF,MAAM,CAAC,mBAAmB,EAAE,oCAAoC,EAAE,OAAO,CAAC;SAC1E,MAAM,CAAC,qBAAqB,EAAE,gCAAgC,CAAC;SAC/D,IAAI,CAAC,WAAW,EAAE,IAAA,iCAAoB,EAAC,CAAC,6BAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;SAClE,MAAM,CACL,IAAA,6BAAW,EAAC,KAAK,EAAE,OAAyB,EAAE,EAAE;QAC9C,MAAM,MAAM,GAAG,MAAM,IAAA,kCAAiB,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,IAAA,2BAAU,EAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAE5E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;YAC3C,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,IAAA,4BAAW,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAE3C,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/C,OAAO;QACT,CAAC;QAED,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YACxB,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvB,OAAO;QACT,CAAC;QAED,WAAW,CAAC,QAAQ,CAAC,CAAC;IACxB,CAAC,CAAC,CACH,CAAC;IAEJ,OAAO,gBAAgB,CAAC;AAC1B,CAAC"}
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ const send_1 = require("./commands/send");
7
7
  const channels_1 = require("./commands/channels");
8
8
  const history_1 = require("./commands/history");
9
9
  const unread_1 = require("./commands/unread");
10
+ const scheduled_1 = require("./commands/scheduled");
10
11
  const fs_1 = require("fs");
11
12
  const path_1 = require("path");
12
13
  const program = new commander_1.Command();
@@ -19,5 +20,6 @@ program.addCommand((0, send_1.setupSendCommand)());
19
20
  program.addCommand((0, channels_1.setupChannelsCommand)());
20
21
  program.addCommand((0, history_1.setupHistoryCommand)());
21
22
  program.addCommand((0, unread_1.setupUnreadCommand)());
23
+ program.addCommand((0, scheduled_1.setupScheduledCommand)());
22
24
  program.parse();
23
25
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,8CAAuD;AACvD,0CAAmD;AACnD,kDAA2D;AAC3D,gDAAyD;AACzD,8CAAuD;AACvD,2BAAkC;AAClC,+BAA4B;AAE5B,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,iCAAiC;AACjC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAY,EAAC,IAAA,WAAI,EAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAC7F,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;AAEpC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,yCAAyC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAElG,OAAO,CAAC,UAAU,CAAC,IAAA,2BAAkB,GAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,IAAA,uBAAgB,GAAE,CAAC,CAAC;AACvC,OAAO,CAAC,UAAU,CAAC,IAAA,+BAAoB,GAAE,CAAC,CAAC;AAC3C,OAAO,CAAC,UAAU,CAAC,IAAA,6BAAmB,GAAE,CAAC,CAAC;AAC1C,OAAO,CAAC,UAAU,CAAC,IAAA,2BAAkB,GAAE,CAAC,CAAC;AAEzC,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,8CAAuD;AACvD,0CAAmD;AACnD,kDAA2D;AAC3D,gDAAyD;AACzD,8CAAuD;AACvD,oDAA6D;AAC7D,2BAAkC;AAClC,+BAA4B;AAE5B,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,iCAAiC;AACjC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAY,EAAC,IAAA,WAAI,EAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAC7F,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;AAEpC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,yCAAyC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAElG,OAAO,CAAC,UAAU,CAAC,IAAA,2BAAkB,GAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,IAAA,uBAAgB,GAAE,CAAC,CAAC;AACvC,OAAO,CAAC,UAAU,CAAC,IAAA,+BAAoB,GAAE,CAAC,CAAC;AAC3C,OAAO,CAAC,UAAU,CAAC,IAAA,6BAAmB,GAAE,CAAC,CAAC;AAC1C,OAAO,CAAC,UAAU,CAAC,IAAA,2BAAkB,GAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,IAAA,iCAAqB,GAAE,CAAC,CAAC;AAE5C,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -20,6 +20,12 @@ export interface SendOptions {
20
20
  after?: string;
21
21
  profile?: string;
22
22
  }
23
+ export interface ScheduledOptions {
24
+ channel?: string;
25
+ limit?: string;
26
+ format?: 'table' | 'simple' | 'json';
27
+ profile?: string;
28
+ }
23
29
  export interface ChannelsOptions {
24
30
  type: 'public' | 'private' | 'im' | 'mpim' | 'all';
25
31
  includeArchived: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/types/commands.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,KAAK,CAAC;IACnD,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/types/commands.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,KAAK,CAAC;IACnD,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
@@ -1 +1 @@
1
- {"version":3,"file":"channel-resolver.d.ts","sourceRoot":"","sources":["../../src/utils/channel-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,MAAM,MAAM,mBAAmB,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;AAE3D,qBAAa,eAAe;IAC1B;;OAEG;IACH,WAAW,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO;IAQ7C;;OAEG;IACH,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,GAAG,SAAS;IAc1E;;OAEG;IACH,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,KAAK,SAAI,GAAG,MAAM,EAAE;IAOjF;;OAEG;IACH,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,KAAK;IAcpE;;OAEG;IACG,gBAAgB,CACpB,eAAe,EAAE,MAAM,EACvB,WAAW,EAAE,mBAAmB,GAC/B,OAAO,CAAC,MAAM,CAAC;CAgBnB;AAGD,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
1
+ {"version":3,"file":"channel-resolver.d.ts","sourceRoot":"","sources":["../../src/utils/channel-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,MAAM,MAAM,mBAAmB,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;AAE3D,qBAAa,eAAe;IAC1B;;OAEG;IACH,WAAW,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO;IAI7C;;OAEG;IACH,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,GAAG,SAAS;IAc1E;;OAEG;IACH,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,KAAK,SAAI,GAAG,MAAM,EAAE;IAOjF;;OAEG;IACH,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,KAAK;IAcpE;;OAEG;IACG,gBAAgB,CACpB,eAAe,EAAE,MAAM,EACvB,WAAW,EAAE,mBAAmB,GAC/B,OAAO,CAAC,MAAM,CAAC;CAgBnB;AAGD,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
@@ -6,9 +6,7 @@ class ChannelResolver {
6
6
  * Check if the given string is a channel ID
7
7
  */
8
8
  isChannelId(channelNameOrId) {
9
- return (channelNameOrId.startsWith('C') ||
10
- channelNameOrId.startsWith('D') ||
11
- channelNameOrId.startsWith('G'));
9
+ return /^[CDG][A-Z0-9]{8,}$/.test(channelNameOrId);
12
10
  }
13
11
  /**
14
12
  * Find a channel by name from the given list
@@ -1 +1 @@
1
- {"version":3,"file":"channel-resolver.js","sourceRoot":"","sources":["../../src/utils/channel-resolver.ts"],"names":[],"mappings":";;;AAIA,MAAa,eAAe;IAC1B;;OAEG;IACH,WAAW,CAAC,eAAuB;QACjC,OAAO,CACL,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC;YAC/B,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC;YAC/B,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC,CAChC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,WAAmB,EAAE,QAAmB;QAClD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACzB,oBAAoB;YACpB,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW;gBAAE,OAAO,IAAI,CAAC;YACxC,yBAAyB;YACzB,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;gBAAE,OAAO,IAAI,CAAC;YACzD,yBAAyB;YACzB,IAAI,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,WAAW,CAAC,WAAW,EAAE;gBAAE,OAAO,IAAI,CAAC;YACrE,6BAA6B;YAC7B,IAAI,CAAC,CAAC,eAAe,KAAK,WAAW;gBAAE,OAAO,IAAI,CAAC;YACnD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,kBAAkB,CAAC,WAAmB,EAAE,QAAmB,EAAE,KAAK,GAAG,CAAC;QACpE,OAAO,QAAQ;aACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;aACxE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;aACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAc,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,WAAmB,EAAE,QAAmB;QAC1D,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAEvE,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,KAAK,CACd,YAAY,WAAW,2CAA2C,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC/F,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,KAAK,CACd,YAAY,WAAW,0DAA0D,CAClF,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CACpB,eAAuB,EACvB,WAAgC;QAEhC,mCAAmC;QACnC,IAAI,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,EAAE,CAAC;YACtC,OAAO,eAAe,CAAC;QACzB,CAAC;QAED,iDAAiD;QACjD,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAE5D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,mBAAmB,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAC5D,CAAC;QAED,OAAO,OAAO,CAAC,EAAE,CAAC;IACpB,CAAC;CACF;AA9ED,0CA8EC;AAED,8BAA8B;AACjB,QAAA,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"channel-resolver.js","sourceRoot":"","sources":["../../src/utils/channel-resolver.ts"],"names":[],"mappings":";;;AAIA,MAAa,eAAe;IAC1B;;OAEG;IACH,WAAW,CAAC,eAAuB;QACjC,OAAO,qBAAqB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACrD,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,WAAmB,EAAE,QAAmB;QAClD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACzB,oBAAoB;YACpB,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW;gBAAE,OAAO,IAAI,CAAC;YACxC,yBAAyB;YACzB,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;gBAAE,OAAO,IAAI,CAAC;YACzD,yBAAyB;YACzB,IAAI,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,WAAW,CAAC,WAAW,EAAE;gBAAE,OAAO,IAAI,CAAC;YACrE,6BAA6B;YAC7B,IAAI,CAAC,CAAC,eAAe,KAAK,WAAW;gBAAE,OAAO,IAAI,CAAC;YACnD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,kBAAkB,CAAC,WAAmB,EAAE,QAAmB,EAAE,KAAK,GAAG,CAAC;QACpE,OAAO,QAAQ;aACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;aACxE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;aACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAc,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,WAAmB,EAAE,QAAmB;QAC1D,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAEvE,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,KAAK,CACd,YAAY,WAAW,2CAA2C,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC/F,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,KAAK,CACd,YAAY,WAAW,0DAA0D,CAClF,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CACpB,eAAuB,EACvB,WAAgC;QAEhC,mCAAmC;QACnC,IAAI,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,EAAE,CAAC;YACtC,OAAO,eAAe,CAAC;QACzB,CAAC;QAED,iDAAiD;QACjD,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAE5D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,mBAAmB,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAC5D,CAAC;QAED,OAAO,OAAO,CAAC,EAAE,CAAC;IACpB,CAAC;CACF;AA1ED,0CA0EC;AAED,8BAA8B;AACjB,QAAA,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC"}
@@ -50,6 +50,13 @@ export interface Message {
50
50
  attachments?: unknown[];
51
51
  blocks?: unknown[];
52
52
  }
53
+ export interface ScheduledMessage {
54
+ id: string;
55
+ channel_id: string;
56
+ post_at: number;
57
+ date_created: number;
58
+ text?: string;
59
+ }
53
60
  export interface HistoryResult {
54
61
  messages: Message[];
55
62
  users: Map<string, string>;
@@ -65,6 +72,7 @@ export declare class SlackApiClient {
65
72
  constructor(token: string);
66
73
  sendMessage(channel: string, text: string, thread_ts?: string): Promise<ChatPostMessageResponse>;
67
74
  scheduleMessage(channel: string, text: string, post_at: number, thread_ts?: string): Promise<ChatScheduleMessageResponse>;
75
+ listScheduledMessages(channel?: string, limit?: number): Promise<ScheduledMessage[]>;
68
76
  listChannels(options: ListChannelsOptions): Promise<Channel[]>;
69
77
  getHistory(channel: string, options: HistoryOptions): Promise<HistoryResult>;
70
78
  listUnreadChannels(): Promise<Channel[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"slack-api-client.d.ts","sourceRoot":"","sources":["../../src/utils/slack-api-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"slack-api-client.d.ts","sourceRoot":"","sources":["../../src/utils/slack-api-client.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,9 @@ class SlackApiClient {
14
14
  async scheduleMessage(channel, text, post_at, thread_ts) {
15
15
  return this.messageOps.scheduleMessage(channel, text, post_at, thread_ts);
16
16
  }
17
+ async listScheduledMessages(channel, limit = 50) {
18
+ return this.messageOps.listScheduledMessages(channel, limit);
19
+ }
17
20
  async listChannels(options) {
18
21
  return this.channelOps.listChannels(options);
19
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"slack-api-client.js","sourceRoot":"","sources":["../../src/utils/slack-api-client.ts"],"names":[],"mappings":";;;AACA,8EAA0E;AAC1E,8EAA0E;AAoE1E,MAAa,cAAc;IAIzB,YAAY,KAAa;QACvB,IAAI,CAAC,UAAU,GAAG,IAAI,sCAAiB,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,CAAC,UAAU,GAAG,IAAI,sCAAiB,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,WAAW,CACf,OAAe,EACf,IAAY,EACZ,SAAkB;QAElB,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,OAAe,EACf,IAAY,EACZ,OAAe,EACf,SAAkB;QAElB,OAAO,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,OAA4B;QAC7C,OAAO,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAe,EAAE,OAAuB;QACvD,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,OAAO,IAAI,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,eAAuB;QAC5C,OAAO,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB;QAChC,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC/C,CAAC;CACF;AA7CD,wCA6CC;AAEY,QAAA,cAAc,GAAG;IAC5B,YAAY,EAAE,KAAK,EAAE,KAAa,EAAE,OAA4B,EAAsB,EAAE;QACtF,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"slack-api-client.js","sourceRoot":"","sources":["../../src/utils/slack-api-client.ts"],"names":[],"mappings":";;;AACA,8EAA0E;AAC1E,8EAA0E;AA4E1E,MAAa,cAAc;IAIzB,YAAY,KAAa;QACvB,IAAI,CAAC,UAAU,GAAG,IAAI,sCAAiB,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,CAAC,UAAU,GAAG,IAAI,sCAAiB,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,WAAW,CACf,OAAe,EACf,IAAY,EACZ,SAAkB;QAElB,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,OAAe,EACf,IAAY,EACZ,OAAe,EACf,SAAkB;QAElB,OAAO,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,OAAgB,EAAE,KAAK,GAAG,EAAE;QACtD,OAAO,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,OAA4B;QAC7C,OAAO,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAe,EAAE,OAAuB;QACvD,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,OAAO,IAAI,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,eAAuB;QAC5C,OAAO,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB;QAChC,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC/C,CAAC;CACF;AAjDD,wCAiDC;AAEY,QAAA,cAAc,GAAG;IAC5B,YAAY,EAAE,KAAK,EAAE,KAAa,EAAE,OAA4B,EAAsB,EAAE;QACtF,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;CACF,CAAC"}
@@ -1,11 +1,12 @@
1
1
  import { ChatPostMessageResponse, ChatScheduleMessageResponse } from '@slack/web-api';
2
2
  import { BaseSlackClient } from './base-client';
3
- import { HistoryOptions, HistoryResult, ChannelUnreadResult } from '../slack-api-client';
3
+ import { HistoryOptions, HistoryResult, ChannelUnreadResult, ScheduledMessage } from '../slack-api-client';
4
4
  export declare class MessageOperations extends BaseSlackClient {
5
5
  private channelOps;
6
6
  constructor(token: string);
7
7
  sendMessage(channel: string, text: string, thread_ts?: string): Promise<ChatPostMessageResponse>;
8
8
  scheduleMessage(channel: string, text: string, post_at: number, thread_ts?: string): Promise<ChatScheduleMessageResponse>;
9
+ listScheduledMessages(channel?: string, limit?: number): Promise<ScheduledMessage[]>;
9
10
  getHistory(channel: string, options: HistoryOptions): Promise<HistoryResult>;
10
11
  getChannelUnread(channelNameOrId: string): Promise<ChannelUnreadResult>;
11
12
  private fetchUserInfo;
@@ -1 +1 @@
1
- {"version":3,"file":"message-operations.d.ts","sourceRoot":"","sources":["../../../src/utils/slack-operations/message-operations.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EAGvB,2BAA2B,EAC5B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,EAAW,cAAc,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAIlG,qBAAa,iBAAkB,SAAQ,eAAe;IACpD,OAAO,CAAC,UAAU,CAAoB;gBAE1B,KAAK,EAAE,MAAM;IAKnB,WAAW,CACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,uBAAuB,CAAC;IAa7B,eAAe,CACnB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,2BAA2B,CAAC;IAcjC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAyB5E,gBAAgB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;YAsC/D,aAAa;IAoBrB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMnD"}
1
+ {"version":3,"file":"message-operations.d.ts","sourceRoot":"","sources":["../../../src/utils/slack-operations/message-operations.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EAGvB,2BAA2B,EAC5B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,EAEL,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,qBAAqB,CAAC;AAI7B,qBAAa,iBAAkB,SAAQ,eAAe;IACpD,OAAO,CAAC,UAAU,CAAoB;gBAE1B,KAAK,EAAE,MAAM;IAKnB,WAAW,CACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,uBAAuB,CAAC;IAa7B,eAAe,CACnB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,2BAA2B,CAAC;IAcjC,qBAAqB,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAuBhF,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAyB5E,gBAAgB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;YAsC/D,aAAa;IAoBrB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMnD"}
@@ -32,6 +32,23 @@ class MessageOperations extends base_client_1.BaseSlackClient {
32
32
  }
33
33
  return await this.client.chat.scheduleMessage(params);
34
34
  }
35
+ async listScheduledMessages(channel, limit = 50) {
36
+ const channelId = channel
37
+ ? await channel_resolver_1.channelResolver.resolveChannelId(channel, () => this.channelOps.listChannels({
38
+ types: 'public_channel,private_channel,im,mpim',
39
+ exclude_archived: true,
40
+ limit: constants_1.DEFAULTS.CHANNELS_LIMIT,
41
+ }))
42
+ : undefined;
43
+ const params = {
44
+ limit,
45
+ };
46
+ if (channelId) {
47
+ params.channel = channelId;
48
+ }
49
+ const response = await this.client.chat.scheduledMessages.list(params);
50
+ return (response.scheduled_messages || []);
51
+ }
35
52
  async getHistory(channel, options) {
36
53
  // Resolve channel name to ID if needed
37
54
  const channelId = await channel_resolver_1.channelResolver.resolveChannelId(channel, () => this.channelOps.listChannels({
@@ -1 +1 @@
1
- {"version":3,"file":"message-operations.js","sourceRoot":"","sources":["../../../src/utils/slack-operations/message-operations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"message-operations.js","sourceRoot":"","sources":["../../../src/utils/slack-operations/message-operations.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@urugus/slack-cli",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "description": "A command-line tool for sending messages to Slack",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
- "slack-cli": "dist/index.js"
7
+ "slack-cli": "./dist/index.js"
8
8
  },
9
9
  "scripts": {
10
10
  "build": "tsc",
@@ -0,0 +1,71 @@
1
+ import { Command } from 'commander';
2
+ import { wrapCommand } from '../utils/command-wrapper';
3
+ import { createSlackClient } from '../utils/client-factory';
4
+ import { ScheduledOptions } from '../types/commands';
5
+ import { parseFormat, parseLimit } from '../utils/option-parsers';
6
+ import { createValidationHook, optionValidators } from '../utils/validators';
7
+
8
+ function formatPostAt(postAt: number): string {
9
+ return new Date(postAt * 1000).toISOString();
10
+ }
11
+
12
+ function renderTable(
13
+ messages: Array<{ id: string; channel_id: string; post_at: number; text?: string }>
14
+ ) {
15
+ const rows = messages.map((message) => ({
16
+ id: message.id,
17
+ channel: message.channel_id,
18
+ post_at: formatPostAt(message.post_at),
19
+ text: message.text || '',
20
+ }));
21
+
22
+ console.table(rows);
23
+ }
24
+
25
+ function renderSimple(
26
+ messages: Array<{ id: string; channel_id: string; post_at: number; text?: string }>
27
+ ) {
28
+ for (const message of messages) {
29
+ console.log(
30
+ `${formatPostAt(message.post_at)} ${message.channel_id} ${message.id} ${message.text || ''}`
31
+ );
32
+ }
33
+ }
34
+
35
+ export function setupScheduledCommand(): Command {
36
+ const scheduledCommand = new Command('scheduled')
37
+ .description('List scheduled messages')
38
+ .option('-c, --channel <channel>', 'Filter by channel name or ID')
39
+ .option('--limit <number>', 'Maximum number of scheduled messages to list', '50')
40
+ .option('--format <format>', 'Output format: table, simple, json', 'table')
41
+ .option('--profile <profile>', 'Use specific workspace profile')
42
+ .hook('preAction', createValidationHook([optionValidators.format]))
43
+ .action(
44
+ wrapCommand(async (options: ScheduledOptions) => {
45
+ const client = await createSlackClient(options.profile);
46
+ const limit = parseLimit(options.limit, 50);
47
+ const messages = await client.listScheduledMessages(options.channel, limit);
48
+
49
+ if (messages.length === 0) {
50
+ console.log('No scheduled messages found');
51
+ return;
52
+ }
53
+
54
+ const format = parseFormat(options.format);
55
+
56
+ if (format === 'json') {
57
+ console.log(JSON.stringify(messages, null, 2));
58
+ return;
59
+ }
60
+
61
+ if (format === 'simple') {
62
+ renderSimple(messages);
63
+ return;
64
+ }
65
+
66
+ renderTable(messages);
67
+ })
68
+ );
69
+
70
+ return scheduledCommand;
71
+ }
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ import { setupSendCommand } from './commands/send';
5
5
  import { setupChannelsCommand } from './commands/channels';
6
6
  import { setupHistoryCommand } from './commands/history';
7
7
  import { setupUnreadCommand } from './commands/unread';
8
+ import { setupScheduledCommand } from './commands/scheduled';
8
9
  import { readFileSync } from 'fs';
9
10
  import { join } from 'path';
10
11
 
@@ -21,5 +22,6 @@ program.addCommand(setupSendCommand());
21
22
  program.addCommand(setupChannelsCommand());
22
23
  program.addCommand(setupHistoryCommand());
23
24
  program.addCommand(setupUnreadCommand());
25
+ program.addCommand(setupScheduledCommand());
24
26
 
25
27
  program.parse();
@@ -25,6 +25,13 @@ export interface SendOptions {
25
25
  profile?: string;
26
26
  }
27
27
 
28
+ export interface ScheduledOptions {
29
+ channel?: string;
30
+ limit?: string;
31
+ format?: 'table' | 'simple' | 'json';
32
+ profile?: string;
33
+ }
34
+
28
35
  export interface ChannelsOptions {
29
36
  type: 'public' | 'private' | 'im' | 'mpim' | 'all';
30
37
  includeArchived: boolean;
@@ -7,11 +7,7 @@ export class ChannelResolver {
7
7
  * Check if the given string is a channel ID
8
8
  */
9
9
  isChannelId(channelNameOrId: string): boolean {
10
- return (
11
- channelNameOrId.startsWith('C') ||
12
- channelNameOrId.startsWith('D') ||
13
- channelNameOrId.startsWith('G')
14
- );
10
+ return /^[CDG][A-Z0-9]{8,}$/.test(channelNameOrId);
15
11
  }
16
12
 
17
13
  /**
@@ -57,6 +57,14 @@ export interface Message {
57
57
  blocks?: unknown[];
58
58
  }
59
59
 
60
+ export interface ScheduledMessage {
61
+ id: string;
62
+ channel_id: string;
63
+ post_at: number;
64
+ date_created: number;
65
+ text?: string;
66
+ }
67
+
60
68
  export interface HistoryResult {
61
69
  messages: Message[];
62
70
  users: Map<string, string>;
@@ -94,6 +102,10 @@ export class SlackApiClient {
94
102
  return this.messageOps.scheduleMessage(channel, text, post_at, thread_ts);
95
103
  }
96
104
 
105
+ async listScheduledMessages(channel?: string, limit = 50): Promise<ScheduledMessage[]> {
106
+ return this.messageOps.listScheduledMessages(channel, limit);
107
+ }
108
+
97
109
  async listChannels(options: ListChannelsOptions): Promise<Channel[]> {
98
110
  return this.channelOps.listChannels(options);
99
111
  }
@@ -7,7 +7,13 @@ import {
7
7
  import { BaseSlackClient } from './base-client';
8
8
  import { channelResolver } from '../channel-resolver';
9
9
  import { DEFAULTS } from '../constants';
10
- import { Message, HistoryOptions, HistoryResult, ChannelUnreadResult } from '../slack-api-client';
10
+ import {
11
+ Message,
12
+ HistoryOptions,
13
+ HistoryResult,
14
+ ChannelUnreadResult,
15
+ ScheduledMessage,
16
+ } from '../slack-api-client';
11
17
  import { ChannelOperations } from './channel-operations';
12
18
  import { extractAllUserIds } from '../mention-utils';
13
19
 
@@ -55,6 +61,29 @@ export class MessageOperations extends BaseSlackClient {
55
61
  return await this.client.chat.scheduleMessage(params);
56
62
  }
57
63
 
64
+ async listScheduledMessages(channel?: string, limit = 50): Promise<ScheduledMessage[]> {
65
+ const channelId = channel
66
+ ? await channelResolver.resolveChannelId(channel, () =>
67
+ this.channelOps.listChannels({
68
+ types: 'public_channel,private_channel,im,mpim',
69
+ exclude_archived: true,
70
+ limit: DEFAULTS.CHANNELS_LIMIT,
71
+ })
72
+ )
73
+ : undefined;
74
+
75
+ const params: { channel?: string; limit: number } = {
76
+ limit,
77
+ };
78
+
79
+ if (channelId) {
80
+ params.channel = channelId;
81
+ }
82
+
83
+ const response = await this.client.chat.scheduledMessages.list(params as any);
84
+ return (response.scheduled_messages || []) as ScheduledMessage[];
85
+ }
86
+
58
87
  async getHistory(channel: string, options: HistoryOptions): Promise<HistoryResult> {
59
88
  // Resolve channel name to ID if needed
60
89
  const channelId = await channelResolver.resolveChannelId(channel, () =>
@@ -0,0 +1,131 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import { setupScheduledCommand } from '../../src/commands/scheduled';
3
+ import { SlackApiClient } from '../../src/utils/slack-api-client';
4
+ import { ProfileConfigManager } from '../../src/utils/profile-config';
5
+ import { setupMockConsole, createTestProgram, restoreMocks } from '../test-utils';
6
+
7
+ vi.mock('../../src/utils/slack-api-client');
8
+ vi.mock('../../src/utils/profile-config');
9
+
10
+ describe('scheduled command', () => {
11
+ let program: any;
12
+ let mockSlackClient: SlackApiClient;
13
+ let mockConfigManager: ProfileConfigManager;
14
+ let mockConsole: any;
15
+ let tableSpy: any;
16
+
17
+ const mockScheduledMessages = [
18
+ {
19
+ id: 'Q123',
20
+ channel_id: 'C1234567890',
21
+ post_at: 1770855000,
22
+ date_created: 1770854400,
23
+ text: 'Scheduled message 1',
24
+ },
25
+ {
26
+ id: 'Q456',
27
+ channel_id: 'C0987654321',
28
+ post_at: 1770858600,
29
+ date_created: 1770854400,
30
+ text: 'Scheduled message 2',
31
+ },
32
+ ];
33
+
34
+ beforeEach(() => {
35
+ vi.clearAllMocks();
36
+
37
+ mockConfigManager = new ProfileConfigManager();
38
+ vi.mocked(ProfileConfigManager).mockReturnValue(mockConfigManager);
39
+
40
+ mockSlackClient = new SlackApiClient('test-token');
41
+ vi.mocked(SlackApiClient).mockReturnValue(mockSlackClient);
42
+
43
+ mockConsole = setupMockConsole();
44
+ tableSpy = vi.spyOn(console, 'table').mockImplementation(() => {});
45
+
46
+ program = createTestProgram();
47
+ program.addCommand(setupScheduledCommand());
48
+ });
49
+
50
+ afterEach(() => {
51
+ restoreMocks();
52
+ });
53
+
54
+ it('should list scheduled messages in table format by default', async () => {
55
+ vi.mocked(mockConfigManager.getConfig).mockResolvedValue({
56
+ token: 'test-token',
57
+ updatedAt: new Date().toISOString(),
58
+ });
59
+ vi.mocked(mockSlackClient.listScheduledMessages).mockResolvedValue(
60
+ mockScheduledMessages as any
61
+ );
62
+
63
+ await program.parseAsync(['node', 'slack-cli', 'scheduled']);
64
+
65
+ expect(mockSlackClient.listScheduledMessages).toHaveBeenCalledWith(undefined, 50);
66
+ expect(tableSpy).toHaveBeenCalled();
67
+ });
68
+
69
+ it('should filter by channel and limit', async () => {
70
+ vi.mocked(mockConfigManager.getConfig).mockResolvedValue({
71
+ token: 'test-token',
72
+ updatedAt: new Date().toISOString(),
73
+ });
74
+ vi.mocked(mockSlackClient.listScheduledMessages).mockResolvedValue(
75
+ mockScheduledMessages as any
76
+ );
77
+
78
+ await program.parseAsync([
79
+ 'node',
80
+ 'slack-cli',
81
+ 'scheduled',
82
+ '--channel',
83
+ 'general',
84
+ '--limit',
85
+ '10',
86
+ ]);
87
+
88
+ expect(mockSlackClient.listScheduledMessages).toHaveBeenCalledWith('general', 10);
89
+ });
90
+
91
+ it('should output json format', async () => {
92
+ vi.mocked(mockConfigManager.getConfig).mockResolvedValue({
93
+ token: 'test-token',
94
+ updatedAt: new Date().toISOString(),
95
+ });
96
+ vi.mocked(mockSlackClient.listScheduledMessages).mockResolvedValue(
97
+ mockScheduledMessages as any
98
+ );
99
+
100
+ await program.parseAsync(['node', 'slack-cli', 'scheduled', '--format', 'json']);
101
+
102
+ expect(mockConsole.logSpy).toHaveBeenCalledWith(expect.stringContaining('"id": "Q123"'));
103
+ });
104
+
105
+ it('should output simple format', async () => {
106
+ vi.mocked(mockConfigManager.getConfig).mockResolvedValue({
107
+ token: 'test-token',
108
+ updatedAt: new Date().toISOString(),
109
+ });
110
+ vi.mocked(mockSlackClient.listScheduledMessages).mockResolvedValue(
111
+ mockScheduledMessages as any
112
+ );
113
+
114
+ await program.parseAsync(['node', 'slack-cli', 'scheduled', '--format', 'simple']);
115
+
116
+ expect(mockConsole.logSpy).toHaveBeenCalledWith(expect.stringContaining('Q123'));
117
+ expect(mockConsole.logSpy).toHaveBeenCalledWith(expect.stringContaining('Q456'));
118
+ });
119
+
120
+ it('should show empty message when no scheduled messages', async () => {
121
+ vi.mocked(mockConfigManager.getConfig).mockResolvedValue({
122
+ token: 'test-token',
123
+ updatedAt: new Date().toISOString(),
124
+ });
125
+ vi.mocked(mockSlackClient.listScheduledMessages).mockResolvedValue([] as any);
126
+
127
+ await program.parseAsync(['node', 'slack-cli', 'scheduled']);
128
+
129
+ expect(mockConsole.logSpy).toHaveBeenCalledWith('No scheduled messages found');
130
+ });
131
+ });
@@ -10,21 +10,21 @@ describe('ChannelResolver', () => {
10
10
  resolver = new ChannelResolver();
11
11
  mockChannels = [
12
12
  {
13
- id: 'C123',
13
+ id: 'C1234567890',
14
14
  name: 'general',
15
15
  is_private: false,
16
16
  created: 1234567890,
17
17
  is_member: true,
18
18
  },
19
19
  {
20
- id: 'C456',
20
+ id: 'C0987654321',
21
21
  name: 'random',
22
22
  is_private: false,
23
23
  created: 1234567890,
24
24
  is_member: true,
25
25
  },
26
26
  {
27
- id: 'C789',
27
+ id: 'C1111111111',
28
28
  name: 'dev-team',
29
29
  is_private: false,
30
30
  created: 1234567890,
@@ -32,7 +32,7 @@ describe('ChannelResolver', () => {
32
32
  name_normalized: 'dev-team',
33
33
  },
34
34
  {
35
- id: 'G123',
35
+ id: 'G1234567890',
36
36
  name: 'private-channel',
37
37
  is_private: true,
38
38
  created: 1234567890,
@@ -42,21 +42,18 @@ describe('ChannelResolver', () => {
42
42
  });
43
43
 
44
44
  describe('isChannelId', () => {
45
- it('should identify channel IDs starting with C', () => {
46
- expect(resolver.isChannelId('C123456')).toBe(true);
45
+ it('should identify channel IDs with valid format', () => {
46
+ expect(resolver.isChannelId('C1234567890')).toBe(true);
47
+ expect(resolver.isChannelId('D1234567890')).toBe(true);
48
+ expect(resolver.isChannelId('G1234567890')).toBe(true);
47
49
  });
48
50
 
49
- it('should identify DM IDs starting with D', () => {
50
- expect(resolver.isChannelId('D123456')).toBe(true);
51
- });
52
-
53
- it('should identify group IDs starting with G', () => {
54
- expect(resolver.isChannelId('G123456')).toBe(true);
55
- });
56
-
57
- it('should return false for channel names', () => {
51
+ it('should return false for channel names or malformed IDs', () => {
58
52
  expect(resolver.isChannelId('general')).toBe(false);
59
53
  expect(resolver.isChannelId('#general')).toBe(false);
54
+ expect(resolver.isChannelId('General')).toBe(false);
55
+ expect(resolver.isChannelId('Dev')).toBe(false);
56
+ expect(resolver.isChannelId('C123')).toBe(false);
60
57
  });
61
58
  });
62
59
 
@@ -96,8 +93,8 @@ describe('ChannelResolver', () => {
96
93
  it('should limit results to specified count', () => {
97
94
  const manyChannels = [
98
95
  ...mockChannels,
99
- { id: 'C999', name: 'general-2', is_private: false, created: 0 },
100
- { id: 'C888', name: 'general-3', is_private: false, created: 0 },
96
+ { id: 'C9999999999', name: 'general-2', is_private: false, created: 0 },
97
+ { id: 'C8888888888', name: 'general-3', is_private: false, created: 0 },
101
98
  ];
102
99
  const result = resolver.getSimilarChannels('general', manyChannels, 2);
103
100
  expect(result).toHaveLength(2);
@@ -128,15 +125,22 @@ describe('ChannelResolver', () => {
128
125
  describe('resolveChannelId', () => {
129
126
  it('should return ID directly if already an ID', async () => {
130
127
  const getChannelsFn = vi.fn();
131
- const result = await resolver.resolveChannelId('C123456', getChannelsFn);
132
- expect(result).toBe('C123456');
128
+ const result = await resolver.resolveChannelId('C1234567890', getChannelsFn);
129
+ expect(result).toBe('C1234567890');
133
130
  expect(getChannelsFn).not.toHaveBeenCalled();
134
131
  });
135
132
 
136
133
  it('should resolve channel name to ID', async () => {
137
134
  const getChannelsFn = vi.fn().mockResolvedValue(mockChannels);
138
135
  const result = await resolver.resolveChannelId('general', getChannelsFn);
139
- expect(result).toBe('C123');
136
+ expect(result).toBe('C1234567890');
137
+ expect(getChannelsFn).toHaveBeenCalled();
138
+ });
139
+
140
+ it('should resolve mixed-case channel names to ID', async () => {
141
+ const getChannelsFn = vi.fn().mockResolvedValue(mockChannels);
142
+ const result = await resolver.resolveChannelId('General', getChannelsFn);
143
+ expect(result).toBe('C1234567890');
140
144
  expect(getChannelsFn).toHaveBeenCalled();
141
145
  });
142
146
 
@@ -154,4 +158,4 @@ describe('ChannelResolver', () => {
154
158
  );
155
159
  });
156
160
  });
157
- });
161
+ });
@@ -13,15 +13,18 @@ describe('SlackApiClient', () => {
13
13
  mockWebClient = {
14
14
  chat: {
15
15
  postMessage: vi.fn(),
16
- scheduleMessage: vi.fn()
16
+ scheduleMessage: vi.fn(),
17
+ scheduledMessages: {
18
+ list: vi.fn(),
19
+ },
17
20
  },
18
21
  conversations: {
19
22
  list: vi.fn(),
20
- info: vi.fn()
23
+ info: vi.fn(),
21
24
  },
22
25
  users: {
23
- conversations: vi.fn()
24
- }
26
+ conversations: vi.fn(),
27
+ },
25
28
  };
26
29
  vi.mocked(WebClient).mockReturnValue(mockWebClient);
27
30
  client = new SlackApiClient('test-token');
@@ -47,7 +50,7 @@ describe('SlackApiClient', () => {
47
50
 
48
51
  expect(mockWebClient.chat.postMessage).toHaveBeenCalledWith({
49
52
  channel: 'general',
50
- text: 'Hello, World!'
53
+ text: 'Hello, World!',
51
54
  });
52
55
  expect(result).toEqual(mockResponse);
53
56
  });
@@ -60,7 +63,7 @@ describe('SlackApiClient', () => {
60
63
 
61
64
  expect(mockWebClient.chat.postMessage).toHaveBeenCalledWith({
62
65
  channel: 'C1234567890',
63
- text: 'Hello!'
66
+ text: 'Hello!',
64
67
  });
65
68
  });
66
69
 
@@ -73,7 +76,7 @@ describe('SlackApiClient', () => {
73
76
 
74
77
  expect(mockWebClient.chat.postMessage).toHaveBeenCalledWith({
75
78
  channel: 'general',
76
- text: multiLineMessage
79
+ text: multiLineMessage,
77
80
  });
78
81
  });
79
82
 
@@ -95,12 +98,29 @@ describe('SlackApiClient', () => {
95
98
  expect(mockWebClient.chat.scheduleMessage).toHaveBeenCalledWith({
96
99
  channel: 'general',
97
100
  text: 'Hello, future!',
98
- post_at: 1770855000
101
+ post_at: 1770855000,
99
102
  });
100
103
  expect(result).toEqual(mockResponse);
101
104
  });
102
105
  });
103
106
 
107
+ describe('listScheduledMessages', () => {
108
+ it('should list scheduled messages', async () => {
109
+ const mockResponse = {
110
+ ok: true,
111
+ scheduled_messages: [
112
+ { id: 'Q123', channel_id: 'C123', post_at: 1770855000, date_created: 1770854400 },
113
+ ],
114
+ };
115
+ vi.mocked(mockWebClient.chat.scheduledMessages.list).mockResolvedValue(mockResponse as any);
116
+
117
+ const result = await client.listScheduledMessages();
118
+
119
+ expect(mockWebClient.chat.scheduledMessages.list).toHaveBeenCalledWith({ limit: 50 });
120
+ expect(result).toEqual(mockResponse.scheduled_messages);
121
+ });
122
+ });
123
+
104
124
  describe('listChannels', () => {
105
125
  it('should list channels with default options', async () => {
106
126
  const mockChannels = [
@@ -111,24 +131,24 @@ describe('SlackApiClient', () => {
111
131
  is_private: false,
112
132
  num_members: 150,
113
133
  created: 1579075200,
114
- purpose: { value: 'Company announcements' }
115
- }
134
+ purpose: { value: 'Company announcements' },
135
+ },
116
136
  ];
117
137
  vi.mocked(mockWebClient.conversations.list).mockResolvedValue({
118
138
  ok: true,
119
- channels: mockChannels
139
+ channels: mockChannels,
120
140
  } as any);
121
141
 
122
142
  const result = await client.listChannels({
123
143
  types: 'public_channel',
124
144
  exclude_archived: true,
125
- limit: 100
145
+ limit: 100,
126
146
  });
127
147
 
128
148
  expect(mockWebClient.conversations.list).toHaveBeenCalledWith({
129
149
  types: 'public_channel',
130
150
  exclude_archived: true,
131
- limit: 100
151
+ limit: 100,
132
152
  });
133
153
  expect(result).toEqual(mockChannels);
134
154
  });
@@ -142,24 +162,24 @@ describe('SlackApiClient', () => {
142
162
  is_private: true,
143
163
  num_members: 10,
144
164
  created: 1579075200,
145
- purpose: { value: 'Private discussions' }
146
- }
165
+ purpose: { value: 'Private discussions' },
166
+ },
147
167
  ];
148
168
  vi.mocked(mockWebClient.conversations.list).mockResolvedValue({
149
169
  ok: true,
150
- channels: mockChannels
170
+ channels: mockChannels,
151
171
  } as any);
152
172
 
153
173
  const result = await client.listChannels({
154
174
  types: 'private_channel',
155
175
  exclude_archived: true,
156
- limit: 50
176
+ limit: 50,
157
177
  });
158
178
 
159
179
  expect(mockWebClient.conversations.list).toHaveBeenCalledWith({
160
180
  types: 'private_channel',
161
181
  exclude_archived: true,
162
- limit: 50
182
+ limit: 50,
163
183
  });
164
184
  expect(result).toEqual(mockChannels);
165
185
  });
@@ -167,30 +187,32 @@ describe('SlackApiClient', () => {
167
187
  it('should handle multiple channel types', async () => {
168
188
  vi.mocked(mockWebClient.conversations.list).mockResolvedValue({
169
189
  ok: true,
170
- channels: []
190
+ channels: [],
171
191
  } as any);
172
192
 
173
193
  await client.listChannels({
174
194
  types: 'public_channel,private_channel,im',
175
195
  exclude_archived: false,
176
- limit: 200
196
+ limit: 200,
177
197
  });
178
198
 
179
199
  expect(mockWebClient.conversations.list).toHaveBeenCalledWith({
180
200
  types: 'public_channel,private_channel,im',
181
201
  exclude_archived: false,
182
- limit: 200
202
+ limit: 200,
183
203
  });
184
204
  });
185
205
 
186
206
  it('should handle API errors', async () => {
187
207
  vi.mocked(mockWebClient.conversations.list).mockRejectedValue(new Error('invalid_auth'));
188
208
 
189
- await expect(client.listChannels({
190
- types: 'public_channel',
191
- exclude_archived: true,
192
- limit: 100
193
- })).rejects.toThrow('invalid_auth');
209
+ await expect(
210
+ client.listChannels({
211
+ types: 'public_channel',
212
+ exclude_archived: true,
213
+ limit: 100,
214
+ })
215
+ ).rejects.toThrow('invalid_auth');
194
216
  });
195
217
 
196
218
  it('should handle pagination when listing channels', async () => {
@@ -199,11 +221,11 @@ describe('SlackApiClient', () => {
199
221
  ok: true,
200
222
  channels: [
201
223
  { id: 'C001', name: 'channel1', is_private: false },
202
- { id: 'C002', name: 'channel2', is_private: false }
224
+ { id: 'C002', name: 'channel2', is_private: false },
203
225
  ],
204
226
  response_metadata: {
205
- next_cursor: 'cursor123'
206
- }
227
+ next_cursor: 'cursor123',
228
+ },
207
229
  } as any);
208
230
 
209
231
  // Second page
@@ -211,28 +233,26 @@ describe('SlackApiClient', () => {
211
233
  ok: true,
212
234
  channels: [
213
235
  { id: 'C003', name: 'channel3', is_private: false },
214
- { id: 'C004', name: 'channel4', is_private: false }
236
+ { id: 'C004', name: 'channel4', is_private: false },
215
237
  ],
216
238
  response_metadata: {
217
- next_cursor: 'cursor456'
218
- }
239
+ next_cursor: 'cursor456',
240
+ },
219
241
  } as any);
220
242
 
221
243
  // Third page (last page)
222
244
  vi.mocked(mockWebClient.conversations.list).mockResolvedValueOnce({
223
245
  ok: true,
224
- channels: [
225
- { id: 'C005', name: 'channel5', is_private: false }
226
- ],
246
+ channels: [{ id: 'C005', name: 'channel5', is_private: false }],
227
247
  response_metadata: {
228
- next_cursor: ''
229
- }
248
+ next_cursor: '',
249
+ },
230
250
  } as any);
231
251
 
232
252
  const result = await client.listChannels({
233
253
  types: 'public_channel',
234
254
  exclude_archived: true,
235
- limit: 2
255
+ limit: 2,
236
256
  });
237
257
 
238
258
  // Should have called the API 3 times
@@ -243,7 +263,7 @@ describe('SlackApiClient', () => {
243
263
  types: 'public_channel',
244
264
  exclude_archived: true,
245
265
  limit: 2,
246
- cursor: undefined
266
+ cursor: undefined,
247
267
  });
248
268
 
249
269
  // Second call
@@ -251,7 +271,7 @@ describe('SlackApiClient', () => {
251
271
  types: 'public_channel',
252
272
  exclude_archived: true,
253
273
  limit: 2,
254
- cursor: 'cursor123'
274
+ cursor: 'cursor123',
255
275
  });
256
276
 
257
277
  // Third call
@@ -259,7 +279,7 @@ describe('SlackApiClient', () => {
259
279
  types: 'public_channel',
260
280
  exclude_archived: true,
261
281
  limit: 2,
262
- cursor: 'cursor456'
282
+ cursor: 'cursor456',
263
283
  });
264
284
 
265
285
  // Should return all channels
@@ -274,22 +294,20 @@ describe('SlackApiClient', () => {
274
294
  it('should handle empty cursor in pagination', async () => {
275
295
  vi.mocked(mockWebClient.conversations.list).mockResolvedValueOnce({
276
296
  ok: true,
277
- channels: [
278
- { id: 'C001', name: 'channel1', is_private: false }
279
- ],
297
+ channels: [{ id: 'C001', name: 'channel1', is_private: false }],
280
298
  response_metadata: {
281
299
  // No next_cursor field
282
- }
300
+ },
283
301
  } as any);
284
302
 
285
303
  const result = await client.listChannels({
286
304
  types: 'public_channel',
287
305
  exclude_archived: true,
288
- limit: 100
306
+ limit: 100,
289
307
  });
290
308
 
291
309
  expect(mockWebClient.conversations.list).toHaveBeenCalledTimes(1);
292
310
  expect(result).toHaveLength(1);
293
311
  });
294
312
  });
295
- });
313
+ });
@@ -13,6 +13,9 @@ vi.mock('@slack/web-api', () => ({
13
13
  chat: {
14
14
  postMessage: vi.fn(),
15
15
  scheduleMessage: vi.fn(),
16
+ scheduledMessages: {
17
+ list: vi.fn(),
18
+ },
16
19
  },
17
20
  })),
18
21
  LogLevel: {
@@ -49,6 +52,22 @@ describe('MessageOperations', () => {
49
52
  });
50
53
  });
51
54
 
55
+ describe('listScheduledMessages', () => {
56
+ it('should call chat.scheduledMessages.list', async () => {
57
+ mockClient.chat.scheduledMessages.list.mockResolvedValue({
58
+ ok: true,
59
+ scheduled_messages: [
60
+ { id: 'Q123', channel_id: 'C123', post_at: 1770855000, date_created: 1770854400 },
61
+ ],
62
+ });
63
+
64
+ const result = await messageOps.listScheduledMessages(undefined, 20);
65
+
66
+ expect(mockClient.chat.scheduledMessages.list).toHaveBeenCalledWith({ limit: 20 });
67
+ expect(result).toHaveLength(1);
68
+ });
69
+ });
70
+
52
71
  describe('getHistory with mentions', () => {
53
72
  it('should fetch user info for mentioned users in message text', async () => {
54
73
  const mockMessages = [