@urugus/slack-cli 0.1.6 → 0.1.8

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.
Files changed (65) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/commands/channels.d.ts.map +1 -1
  3. package/dist/commands/channels.js +3 -12
  4. package/dist/commands/channels.js.map +1 -1
  5. package/dist/commands/config-subcommands.d.ts +14 -0
  6. package/dist/commands/config-subcommands.d.ts.map +1 -0
  7. package/dist/commands/config-subcommands.js +65 -0
  8. package/dist/commands/config-subcommands.js.map +1 -0
  9. package/dist/commands/config.d.ts.map +1 -1
  10. package/dist/commands/config.js +7 -55
  11. package/dist/commands/config.js.map +1 -1
  12. package/dist/commands/history-display.d.ts +3 -0
  13. package/dist/commands/history-display.d.ts.map +1 -0
  14. package/dist/commands/history-display.js +33 -0
  15. package/dist/commands/history-display.js.map +1 -0
  16. package/dist/commands/history-validators.d.ts +5 -0
  17. package/dist/commands/history-validators.d.ts.map +1 -0
  18. package/dist/commands/history-validators.js +35 -0
  19. package/dist/commands/history-validators.js.map +1 -0
  20. package/dist/commands/history.d.ts.map +1 -1
  21. package/dist/commands/history.js +8 -51
  22. package/dist/commands/history.js.map +1 -1
  23. package/dist/utils/channel-formatter.d.ts +0 -3
  24. package/dist/utils/channel-formatter.d.ts.map +1 -1
  25. package/dist/utils/channel-formatter.js +8 -44
  26. package/dist/utils/channel-formatter.js.map +1 -1
  27. package/dist/utils/formatters/channels-list-formatters.d.ts +13 -0
  28. package/dist/utils/formatters/channels-list-formatters.d.ts.map +1 -0
  29. package/dist/utils/formatters/channels-list-formatters.js +53 -0
  30. package/dist/utils/formatters/channels-list-formatters.js.map +1 -0
  31. package/dist/utils/slack-api-client.d.ts +2 -2
  32. package/dist/utils/slack-api-client.d.ts.map +1 -1
  33. package/dist/utils/slack-api-client.js +9 -140
  34. package/dist/utils/slack-api-client.js.map +1 -1
  35. package/dist/utils/slack-operations/base-client.d.ts +10 -0
  36. package/dist/utils/slack-operations/base-client.d.ts.map +1 -0
  37. package/dist/utils/slack-operations/base-client.js +32 -0
  38. package/dist/utils/slack-operations/base-client.js.map +1 -0
  39. package/dist/utils/slack-operations/channel-operations.d.ts +15 -0
  40. package/dist/utils/slack-operations/channel-operations.d.ts.map +1 -0
  41. package/dist/utils/slack-operations/channel-operations.js +93 -0
  42. package/dist/utils/slack-operations/channel-operations.js.map +1 -0
  43. package/dist/utils/slack-operations/index.d.ts +4 -0
  44. package/dist/utils/slack-operations/index.d.ts.map +1 -0
  45. package/dist/utils/slack-operations/index.js +10 -0
  46. package/dist/utils/slack-operations/index.js.map +1 -0
  47. package/dist/utils/slack-operations/message-operations.d.ts +12 -0
  48. package/dist/utils/slack-operations/message-operations.d.ts.map +1 -0
  49. package/dist/utils/slack-operations/message-operations.js +80 -0
  50. package/dist/utils/slack-operations/message-operations.js.map +1 -0
  51. package/package.json +1 -1
  52. package/src/commands/channels.ts +4 -22
  53. package/src/commands/config-subcommands.ts +63 -0
  54. package/src/commands/config.ts +15 -69
  55. package/src/commands/history-display.ts +36 -0
  56. package/src/commands/history-validators.ts +46 -0
  57. package/src/commands/history.ts +13 -60
  58. package/src/utils/channel-formatter.ts +9 -53
  59. package/src/utils/formatters/channels-list-formatters.ts +59 -0
  60. package/src/utils/slack-api-client.ts +12 -172
  61. package/src/utils/slack-operations/base-client.ts +30 -0
  62. package/src/utils/slack-operations/channel-operations.ts +112 -0
  63. package/src/utils/slack-operations/index.ts +3 -0
  64. package/src/utils/slack-operations/message-operations.ts +94 -0
  65. package/tests/utils/slack-api-client.test.ts +8 -6
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChannelsJsonFormatter = exports.ChannelsSimpleFormatter = exports.ChannelsTableFormatter = void 0;
4
+ exports.createChannelsListFormatter = createChannelsListFormatter;
5
+ const output_formatter_1 = require("./output-formatter");
6
+ class ChannelsTableFormatter extends output_formatter_1.BaseFormatter {
7
+ format(channels) {
8
+ // Print table header
9
+ console.log('Name Type Members Created Description');
10
+ console.log('─'.repeat(65));
11
+ // Print channel rows
12
+ channels.forEach((channel) => {
13
+ const name = channel.name.padEnd(17);
14
+ const type = channel.type.padEnd(9);
15
+ const members = channel.members.toString().padEnd(8);
16
+ const created = channel.created.padEnd(12);
17
+ const purpose = channel.purpose.length > 30 ? channel.purpose.substring(0, 27) + '...' : channel.purpose;
18
+ console.log(`${name} ${type} ${members} ${created} ${purpose}`);
19
+ });
20
+ }
21
+ }
22
+ exports.ChannelsTableFormatter = ChannelsTableFormatter;
23
+ class ChannelsSimpleFormatter extends output_formatter_1.BaseFormatter {
24
+ format(channels) {
25
+ channels.forEach((channel) => console.log(channel.name));
26
+ }
27
+ }
28
+ exports.ChannelsSimpleFormatter = ChannelsSimpleFormatter;
29
+ class ChannelsJsonFormatter extends output_formatter_1.BaseFormatter {
30
+ format(channels) {
31
+ console.log(JSON.stringify(channels.map((channel) => ({
32
+ id: channel.id,
33
+ name: channel.name,
34
+ type: channel.type,
35
+ members: channel.members,
36
+ created: channel.created + 'T00:00:00Z',
37
+ purpose: channel.purpose,
38
+ })), null, 2));
39
+ }
40
+ }
41
+ exports.ChannelsJsonFormatter = ChannelsJsonFormatter;
42
+ function createChannelsListFormatter(format) {
43
+ switch (format) {
44
+ case 'json':
45
+ return new ChannelsJsonFormatter();
46
+ case 'simple':
47
+ return new ChannelsSimpleFormatter();
48
+ case 'table':
49
+ default:
50
+ return new ChannelsTableFormatter();
51
+ }
52
+ }
53
+ //# sourceMappingURL=channels-list-formatters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channels-list-formatters.js","sourceRoot":"","sources":["../../../src/utils/formatters/channels-list-formatters.ts"],"names":[],"mappings":";;;AAgDA,kEAUC;AA1DD,yDAAmD;AAGnD,MAAa,sBAAuB,SAAQ,gCAA0B;IACpE,MAAM,CAAC,QAAuB;QAC5B,qBAAqB;QACrB,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;QAC7E,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAE5B,qBAAqB;QACrB,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC3B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACrC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACpC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC3C,MAAM,OAAO,GACX,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;YAE3F,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAlBD,wDAkBC;AAED,MAAa,uBAAwB,SAAQ,gCAA0B;IACrE,MAAM,CAAC,QAAuB;QAC5B,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3D,CAAC;CACF;AAJD,0DAIC;AAED,MAAa,qBAAsB,SAAQ,gCAA0B;IACnE,MAAM,CAAC,QAAuB;QAC5B,OAAO,CAAC,GAAG,CACT,IAAI,CAAC,SAAS,CACZ,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACzB,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO,GAAG,YAAY;YACvC,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CAAC,EACH,IAAI,EACJ,CAAC,CACF,CACF,CAAC;IACJ,CAAC;CACF;AAjBD,sDAiBC;AAED,SAAgB,2BAA2B,CAAC,MAAc;IACxD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM;YACT,OAAO,IAAI,qBAAqB,EAAE,CAAC;QACrC,KAAK,QAAQ;YACX,OAAO,IAAI,uBAAuB,EAAE,CAAC;QACvC,KAAK,OAAO,CAAC;QACb;YACE,OAAO,IAAI,sBAAsB,EAAE,CAAC;IACxC,CAAC;AACH,CAAC"}
@@ -60,8 +60,8 @@ export interface ChannelUnreadResult {
60
60
  users: Map<string, string>;
61
61
  }
62
62
  export declare class SlackApiClient {
63
- private client;
64
- private rateLimiter;
63
+ private channelOps;
64
+ private messageOps;
65
65
  constructor(token: string);
66
66
  sendMessage(channel: string, text: string): Promise<ChatPostMessageResponse>;
67
67
  listChannels(options: ListChannelsOptions): 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":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAIzD,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,OAAO,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,UAAU,CAAoB;gBAE1B,KAAK,EAAE,MAAM;IAKnB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAI5E,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAI9D,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAI5E,kBAAkB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAIxC,gBAAgB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAG9E;AAED,eAAO,MAAM,cAAc;0BACG,MAAM,WAAW,mBAAmB,KAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAItF,CAAC"}
@@ -1,158 +1,27 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.slackApiClient = exports.SlackApiClient = void 0;
7
- const web_api_1 = require("@slack/web-api");
8
- const p_limit_1 = __importDefault(require("p-limit"));
9
- const channel_resolver_1 = require("./channel-resolver");
10
- const constants_1 = require("./constants");
4
+ const channel_operations_1 = require("./slack-operations/channel-operations");
5
+ const message_operations_1 = require("./slack-operations/message-operations");
11
6
  class SlackApiClient {
12
7
  constructor(token) {
13
- this.client = new web_api_1.WebClient(token, {
14
- retryConfig: constants_1.RATE_LIMIT.RETRY_CONFIG,
15
- });
16
- // Limit concurrent API calls to avoid rate limiting
17
- this.rateLimiter = (0, p_limit_1.default)(constants_1.RATE_LIMIT.CONCURRENT_REQUESTS);
8
+ this.channelOps = new channel_operations_1.ChannelOperations(token);
9
+ this.messageOps = new message_operations_1.MessageOperations(token);
18
10
  }
19
11
  async sendMessage(channel, text) {
20
- return await this.client.chat.postMessage({
21
- channel,
22
- text,
23
- });
12
+ return this.messageOps.sendMessage(channel, text);
24
13
  }
25
14
  async listChannels(options) {
26
- const channels = [];
27
- let cursor;
28
- // Paginate through all channels
29
- do {
30
- const response = await this.client.conversations.list({
31
- types: options.types,
32
- exclude_archived: options.exclude_archived,
33
- limit: options.limit,
34
- cursor,
35
- });
36
- if (response.channels) {
37
- channels.push(...response.channels);
38
- }
39
- cursor = response.response_metadata?.next_cursor;
40
- } while (cursor);
41
- return channels;
15
+ return this.channelOps.listChannels(options);
42
16
  }
43
17
  async getHistory(channel, options) {
44
- // Resolve channel name to ID if needed
45
- const channelId = await channel_resolver_1.channelResolver.resolveChannelId(channel, () => this.listChannels({
46
- types: 'public_channel,private_channel,im,mpim',
47
- exclude_archived: true,
48
- limit: constants_1.DEFAULTS.CHANNELS_LIMIT,
49
- }));
50
- const response = await this.client.conversations.history({
51
- channel: channelId,
52
- limit: options.limit,
53
- oldest: options.oldest,
54
- });
55
- const messages = response.messages;
56
- // Get unique user IDs
57
- const userIds = [...new Set(messages.filter((m) => m.user).map((m) => m.user))];
58
- const users = new Map();
59
- // Fetch user information
60
- if (userIds.length > 0) {
61
- for (const userId of userIds) {
62
- try {
63
- const userInfo = await this.client.users.info({ user: userId });
64
- if (userInfo.user?.name) {
65
- users.set(userId, userInfo.user.name);
66
- }
67
- }
68
- catch (error) {
69
- // If we can't get user info, we'll use the ID
70
- users.set(userId, userId);
71
- }
72
- }
73
- }
74
- return { messages, users };
18
+ return this.messageOps.getHistory(channel, options);
75
19
  }
76
20
  async listUnreadChannels() {
77
- // Get all conversations the user is a member of
78
- const response = await this.client.conversations.list({
79
- types: 'public_channel,private_channel,im,mpim',
80
- exclude_archived: true,
81
- limit: 1000,
82
- });
83
- const channels = response.channels;
84
- // Batch process channels to reduce rate limit issues
85
- const batchSize = constants_1.RATE_LIMIT.BATCH_SIZE;
86
- const batches = [];
87
- for (let i = 0; i < channels.length; i += batchSize) {
88
- batches.push(channels.slice(i, i + batchSize));
89
- }
90
- const channelsWithUnread = [];
91
- // Process batches sequentially with delay
92
- for (const batch of batches) {
93
- const batchResults = await Promise.all(batch.map((channel) => this.rateLimiter(async () => {
94
- try {
95
- const info = await this.client.conversations.info({
96
- channel: channel.id,
97
- include_num_members: false,
98
- });
99
- const channelInfo = info.channel;
100
- return {
101
- ...channel,
102
- unread_count: channelInfo.unread_count || 0,
103
- unread_count_display: channelInfo.unread_count_display || 0,
104
- last_read: channelInfo.last_read,
105
- };
106
- }
107
- catch (error) {
108
- // Log rate limit errors but continue processing
109
- if (error instanceof Error && error.message?.includes('rate limit')) {
110
- console.warn(`Rate limit hit for channel ${channel.name}, skipping...`);
111
- }
112
- return channel;
113
- }
114
- })));
115
- channelsWithUnread.push(...batchResults);
116
- // Add delay between batches to avoid rate limiting
117
- if (batches.indexOf(batch) < batches.length - 1) {
118
- await new Promise((resolve) => setTimeout(resolve, constants_1.RATE_LIMIT.BATCH_DELAY_MS));
119
- }
120
- }
121
- // Filter to only channels with unread messages
122
- return channelsWithUnread.filter((channel) => (channel.unread_count_display || 0) > 0);
21
+ return this.channelOps.listUnreadChannels();
123
22
  }
124
23
  async getChannelUnread(channelNameOrId) {
125
- // Resolve channel name to ID if needed
126
- const channelId = await channel_resolver_1.channelResolver.resolveChannelId(channelNameOrId, () => this.listChannels({
127
- types: 'public_channel,private_channel,im,mpim',
128
- exclude_archived: true,
129
- limit: constants_1.DEFAULTS.CHANNELS_LIMIT,
130
- }));
131
- // Get channel info with unread count
132
- const info = await this.client.conversations.info({
133
- channel: channelId,
134
- });
135
- const channel = info.channel;
136
- // Get unread messages
137
- let messages = [];
138
- let users = new Map();
139
- if (channel.last_read && channel.unread_count > 0) {
140
- const historyResult = await this.getHistory(channelId, {
141
- limit: channel.unread_count,
142
- oldest: channel.last_read,
143
- });
144
- messages = historyResult.messages;
145
- users = historyResult.users;
146
- }
147
- return {
148
- channel: {
149
- ...channel,
150
- unread_count: channel.unread_count || 0,
151
- unread_count_display: channel.unread_count_display || 0,
152
- },
153
- messages,
154
- users,
155
- };
24
+ return this.messageOps.getChannelUnread(channelNameOrId);
156
25
  }
157
26
  }
158
27
  exports.SlackApiClient = SlackApiClient;
@@ -1 +1 @@
1
- {"version":3,"file":"slack-api-client.js","sourceRoot":"","sources":["../../src/utils/slack-api-client.ts"],"names":[],"mappings":"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"}
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,CAAC,OAAe,EAAE,IAAY;QAC7C,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACpD,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;CACF;AA5BD,wCA4BC;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"}
@@ -0,0 +1,10 @@
1
+ import { WebClient } from '@slack/web-api';
2
+ import pLimit from 'p-limit';
3
+ export declare class BaseSlackClient {
4
+ protected client: WebClient;
5
+ protected rateLimiter: ReturnType<typeof pLimit>;
6
+ constructor(token: string);
7
+ protected handleRateLimit(error: unknown): Promise<void>;
8
+ protected delay(ms: number): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=base-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-client.d.ts","sourceRoot":"","sources":["../../../src/utils/slack-operations/base-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAY,MAAM,gBAAgB,CAAC;AACrD,OAAO,MAAM,MAAM,SAAS,CAAC;AAG7B,qBAAa,eAAe;IAC1B,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC;IAC5B,SAAS,CAAC,WAAW,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;gBAErC,KAAK,EAAE,MAAM;cAWT,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;cAO9C,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGjD"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BaseSlackClient = void 0;
7
+ const web_api_1 = require("@slack/web-api");
8
+ const p_limit_1 = __importDefault(require("p-limit"));
9
+ const constants_1 = require("../constants");
10
+ class BaseSlackClient {
11
+ constructor(token) {
12
+ this.client = new web_api_1.WebClient(token, {
13
+ retryConfig: {
14
+ retries: 0, // Disable automatic retries to handle rate limits manually
15
+ },
16
+ logLevel: web_api_1.LogLevel.ERROR, // Reduce noise from WebClient logs
17
+ });
18
+ // Limit concurrent API calls to avoid rate limiting
19
+ this.rateLimiter = (0, p_limit_1.default)(constants_1.RATE_LIMIT.CONCURRENT_REQUESTS);
20
+ }
21
+ async handleRateLimit(error) {
22
+ if (error instanceof Error && error.message?.includes('rate limit')) {
23
+ // If we hit rate limit, wait longer
24
+ await new Promise((resolve) => setTimeout(resolve, 5000));
25
+ }
26
+ }
27
+ async delay(ms) {
28
+ await new Promise((resolve) => setTimeout(resolve, ms));
29
+ }
30
+ }
31
+ exports.BaseSlackClient = BaseSlackClient;
32
+ //# sourceMappingURL=base-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-client.js","sourceRoot":"","sources":["../../../src/utils/slack-operations/base-client.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAqD;AACrD,sDAA6B;AAC7B,4CAA0C;AAE1C,MAAa,eAAe;IAI1B,YAAY,KAAa;QACvB,IAAI,CAAC,MAAM,GAAG,IAAI,mBAAS,CAAC,KAAK,EAAE;YACjC,WAAW,EAAE;gBACX,OAAO,EAAE,CAAC,EAAE,2DAA2D;aACxE;YACD,QAAQ,EAAE,kBAAQ,CAAC,KAAK,EAAE,mCAAmC;SAC9D,CAAC,CAAC;QACH,oDAAoD;QACpD,IAAI,CAAC,WAAW,GAAG,IAAA,iBAAM,EAAC,sBAAU,CAAC,mBAAmB,CAAC,CAAC;IAC5D,CAAC;IAES,KAAK,CAAC,eAAe,CAAC,KAAc;QAC5C,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YACpE,oCAAoC;YACpC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAES,KAAK,CAAC,KAAK,CAAC,EAAU;QAC9B,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC;CACF;AAzBD,0CAyBC"}
@@ -0,0 +1,15 @@
1
+ import { BaseSlackClient } from './base-client';
2
+ import { Channel, ListChannelsOptions } from '../slack-api-client';
3
+ interface ChannelWithUnreadInfo extends Channel {
4
+ unread_count: number;
5
+ unread_count_display: number;
6
+ last_read?: string;
7
+ }
8
+ export declare class ChannelOperations extends BaseSlackClient {
9
+ listChannels(options: ListChannelsOptions): Promise<Channel[]>;
10
+ listUnreadChannels(): Promise<Channel[]>;
11
+ private listUnreadChannelsFallback;
12
+ getChannelInfo(channelNameOrId: string): Promise<ChannelWithUnreadInfo>;
13
+ }
14
+ export {};
15
+ //# sourceMappingURL=channel-operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-operations.d.ts","sourceRoot":"","sources":["../../../src/utils/slack-operations/channel-operations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAEnE,UAAU,qBAAsB,SAAQ,OAAO;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,iBAAkB,SAAQ,eAAe;IAC9C,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAuB9D,kBAAkB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YAqBhC,0BAA0B;IAwClC,cAAc,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAe9E"}
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChannelOperations = void 0;
4
+ const base_client_1 = require("./base-client");
5
+ const channel_resolver_1 = require("../channel-resolver");
6
+ const constants_1 = require("../constants");
7
+ class ChannelOperations extends base_client_1.BaseSlackClient {
8
+ async listChannels(options) {
9
+ const channels = [];
10
+ let cursor;
11
+ // Paginate through all channels
12
+ do {
13
+ const response = await this.client.conversations.list({
14
+ types: options.types,
15
+ exclude_archived: options.exclude_archived,
16
+ limit: options.limit,
17
+ cursor,
18
+ });
19
+ if (response.channels) {
20
+ channels.push(...response.channels);
21
+ }
22
+ cursor = response.response_metadata?.next_cursor;
23
+ } while (cursor);
24
+ return channels;
25
+ }
26
+ async listUnreadChannels() {
27
+ try {
28
+ // Use users.conversations to get unread counts in a single API call
29
+ const response = await this.client.users.conversations({
30
+ types: 'public_channel,private_channel,im,mpim',
31
+ exclude_archived: true,
32
+ limit: 1000,
33
+ });
34
+ const channels = response.channels;
35
+ // Filter to only channels with unread messages
36
+ // The users.conversations endpoint includes unread_count_display
37
+ return channels.filter((channel) => (channel.unread_count_display || 0) > 0);
38
+ }
39
+ catch (error) {
40
+ // Fallback to the old method if users.conversations fails
41
+ console.warn('Failed to use users.conversations, falling back to conversations.list');
42
+ return this.listUnreadChannelsFallback();
43
+ }
44
+ }
45
+ async listUnreadChannelsFallback() {
46
+ // Get all conversations the user is a member of
47
+ const response = await this.client.conversations.list({
48
+ types: 'public_channel,private_channel,im,mpim',
49
+ exclude_archived: true,
50
+ limit: 1000,
51
+ });
52
+ const channels = response.channels;
53
+ const channelsWithUnread = [];
54
+ // Process channels one by one with delay to avoid rate limits
55
+ for (const channel of channels) {
56
+ try {
57
+ const info = await this.client.conversations.info({
58
+ channel: channel.id,
59
+ include_num_members: false,
60
+ });
61
+ const channelInfo = info.channel;
62
+ if (channelInfo.unread_count_display && channelInfo.unread_count_display > 0) {
63
+ channelsWithUnread.push({
64
+ ...channel,
65
+ unread_count: channelInfo.unread_count || 0,
66
+ unread_count_display: channelInfo.unread_count_display || 0,
67
+ last_read: channelInfo.last_read,
68
+ });
69
+ }
70
+ // Add delay between API calls to avoid rate limiting
71
+ await this.delay(100);
72
+ }
73
+ catch (error) {
74
+ // Skip channels that fail
75
+ await this.handleRateLimit(error);
76
+ }
77
+ }
78
+ return channelsWithUnread;
79
+ }
80
+ async getChannelInfo(channelNameOrId) {
81
+ const channelId = await channel_resolver_1.channelResolver.resolveChannelId(channelNameOrId, () => this.listChannels({
82
+ types: 'public_channel,private_channel,im,mpim',
83
+ exclude_archived: true,
84
+ limit: constants_1.DEFAULTS.CHANNELS_LIMIT,
85
+ }));
86
+ const info = await this.client.conversations.info({
87
+ channel: channelId,
88
+ });
89
+ return info.channel;
90
+ }
91
+ }
92
+ exports.ChannelOperations = ChannelOperations;
93
+ //# sourceMappingURL=channel-operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-operations.js","sourceRoot":"","sources":["../../../src/utils/slack-operations/channel-operations.ts"],"names":[],"mappings":";;;AAAA,+CAAgD;AAChD,0DAAsD;AACtD,4CAAwC;AASxC,MAAa,iBAAkB,SAAQ,6BAAe;IACpD,KAAK,CAAC,YAAY,CAAC,OAA4B;QAC7C,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,IAAI,MAA0B,CAAC;QAE/B,gCAAgC;QAChC,GAAG,CAAC;YACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;gBACpD,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;gBAC1C,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,MAAM;aACP,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACtB,QAAQ,CAAC,IAAI,CAAC,GAAI,QAAQ,CAAC,QAAsB,CAAC,CAAC;YACrD,CAAC;YAED,MAAM,GAAG,QAAQ,CAAC,iBAAiB,EAAE,WAAW,CAAC;QACnD,CAAC,QAAQ,MAAM,EAAE;QAEjB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,IAAI,CAAC;YACH,oEAAoE;YACpE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC;gBACrD,KAAK,EAAE,wCAAwC;gBAC/C,gBAAgB,EAAE,IAAI;gBACtB,KAAK,EAAE,IAAI;aACZ,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAqB,CAAC;YAEhD,+CAA+C;YAC/C,iEAAiE;YACjE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,oBAAoB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,0DAA0D;YAC1D,OAAO,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;YACtF,OAAO,IAAI,CAAC,0BAA0B,EAAE,CAAC;QAC3C,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,0BAA0B;QACtC,gDAAgD;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;YACpD,KAAK,EAAE,wCAAwC;YAC/C,gBAAgB,EAAE,IAAI;YACtB,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAqB,CAAC;QAChD,MAAM,kBAAkB,GAAc,EAAE,CAAC;QAEzC,8DAA8D;QAC9D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;oBAChD,OAAO,EAAE,OAAO,CAAC,EAAE;oBACnB,mBAAmB,EAAE,KAAK;iBAC3B,CAAC,CAAC;gBACH,MAAM,WAAW,GAAG,IAAI,CAAC,OAAgC,CAAC;gBAE1D,IAAI,WAAW,CAAC,oBAAoB,IAAI,WAAW,CAAC,oBAAoB,GAAG,CAAC,EAAE,CAAC;oBAC7E,kBAAkB,CAAC,IAAI,CAAC;wBACtB,GAAG,OAAO;wBACV,YAAY,EAAE,WAAW,CAAC,YAAY,IAAI,CAAC;wBAC3C,oBAAoB,EAAE,WAAW,CAAC,oBAAoB,IAAI,CAAC;wBAC3D,SAAS,EAAE,WAAW,CAAC,SAAS;qBACjC,CAAC,CAAC;gBACL,CAAC;gBAED,qDAAqD;gBACrD,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,0BAA0B;gBAC1B,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QAED,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,eAAuB;QAC1C,MAAM,SAAS,GAAG,MAAM,kCAAe,CAAC,gBAAgB,CAAC,eAAe,EAAE,GAAG,EAAE,CAC7E,IAAI,CAAC,YAAY,CAAC;YAChB,KAAK,EAAE,wCAAwC;YAC/C,gBAAgB,EAAE,IAAI;YACtB,KAAK,EAAE,oBAAQ,CAAC,cAAc;SAC/B,CAAC,CACH,CAAC;QAEF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;YAChD,OAAO,EAAE,SAAS;SACnB,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,OAAgC,CAAC;IAC/C,CAAC;CACF;AApGD,8CAoGC"}
@@ -0,0 +1,4 @@
1
+ export { BaseSlackClient } from './base-client';
2
+ export { ChannelOperations } from './channel-operations';
3
+ export { MessageOperations } from './message-operations';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/slack-operations/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MessageOperations = exports.ChannelOperations = exports.BaseSlackClient = void 0;
4
+ var base_client_1 = require("./base-client");
5
+ Object.defineProperty(exports, "BaseSlackClient", { enumerable: true, get: function () { return base_client_1.BaseSlackClient; } });
6
+ var channel_operations_1 = require("./channel-operations");
7
+ Object.defineProperty(exports, "ChannelOperations", { enumerable: true, get: function () { return channel_operations_1.ChannelOperations; } });
8
+ var message_operations_1 = require("./message-operations");
9
+ Object.defineProperty(exports, "MessageOperations", { enumerable: true, get: function () { return message_operations_1.MessageOperations; } });
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/slack-operations/index.ts"],"names":[],"mappings":";;;AAAA,6CAAgD;AAAvC,8GAAA,eAAe,OAAA;AACxB,2DAAyD;AAAhD,uHAAA,iBAAiB,OAAA;AAC1B,2DAAyD;AAAhD,uHAAA,iBAAiB,OAAA"}
@@ -0,0 +1,12 @@
1
+ import { ChatPostMessageResponse } from '@slack/web-api';
2
+ import { BaseSlackClient } from './base-client';
3
+ import { HistoryOptions, HistoryResult, ChannelUnreadResult } from '../slack-api-client';
4
+ export declare class MessageOperations extends BaseSlackClient {
5
+ private channelOps;
6
+ constructor(token: string);
7
+ sendMessage(channel: string, text: string): Promise<ChatPostMessageResponse>;
8
+ getHistory(channel: string, options: HistoryOptions): Promise<HistoryResult>;
9
+ getChannelUnread(channelNameOrId: string): Promise<ChannelUnreadResult>;
10
+ private fetchUserInfo;
11
+ }
12
+ //# sourceMappingURL=message-operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-operations.d.ts","sourceRoot":"","sources":["../../../src/utils/slack-operations/message-operations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,EAAW,cAAc,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAGlG,qBAAa,iBAAkB,SAAQ,eAAe;IACpD,OAAO,CAAC,UAAU,CAAoB;gBAE1B,KAAK,EAAE,MAAM;IAKnB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAO5E,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;YA2B/D,aAAa;CAmB5B"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MessageOperations = void 0;
4
+ const base_client_1 = require("./base-client");
5
+ const channel_resolver_1 = require("../channel-resolver");
6
+ const constants_1 = require("../constants");
7
+ const channel_operations_1 = require("./channel-operations");
8
+ class MessageOperations extends base_client_1.BaseSlackClient {
9
+ constructor(token) {
10
+ super(token);
11
+ this.channelOps = new channel_operations_1.ChannelOperations(token);
12
+ }
13
+ async sendMessage(channel, text) {
14
+ return await this.client.chat.postMessage({
15
+ channel,
16
+ text,
17
+ });
18
+ }
19
+ async getHistory(channel, options) {
20
+ // Resolve channel name to ID if needed
21
+ const channelId = await channel_resolver_1.channelResolver.resolveChannelId(channel, () => this.channelOps.listChannels({
22
+ types: 'public_channel,private_channel,im,mpim',
23
+ exclude_archived: true,
24
+ limit: constants_1.DEFAULTS.CHANNELS_LIMIT,
25
+ }));
26
+ const response = await this.client.conversations.history({
27
+ channel: channelId,
28
+ limit: options.limit,
29
+ oldest: options.oldest,
30
+ });
31
+ const messages = response.messages;
32
+ // Get unique user IDs
33
+ const userIds = [...new Set(messages.filter((m) => m.user).map((m) => m.user))];
34
+ const users = await this.fetchUserInfo(userIds);
35
+ return { messages, users };
36
+ }
37
+ async getChannelUnread(channelNameOrId) {
38
+ const channel = await this.channelOps.getChannelInfo(channelNameOrId);
39
+ // Get unread messages
40
+ let messages = [];
41
+ let users = new Map();
42
+ if (channel.last_read && channel.unread_count > 0) {
43
+ const historyResult = await this.getHistory(channel.id, {
44
+ limit: channel.unread_count,
45
+ oldest: channel.last_read,
46
+ });
47
+ messages = historyResult.messages;
48
+ users = historyResult.users;
49
+ }
50
+ return {
51
+ channel: {
52
+ ...channel,
53
+ unread_count: channel.unread_count || 0,
54
+ unread_count_display: channel.unread_count_display || 0,
55
+ },
56
+ messages,
57
+ users,
58
+ };
59
+ }
60
+ async fetchUserInfo(userIds) {
61
+ const users = new Map();
62
+ if (userIds.length > 0) {
63
+ for (const userId of userIds) {
64
+ try {
65
+ const userInfo = await this.client.users.info({ user: userId });
66
+ if (userInfo.user?.name) {
67
+ users.set(userId, userInfo.user.name);
68
+ }
69
+ }
70
+ catch (error) {
71
+ // If we can't get user info, we'll use the ID
72
+ users.set(userId, userId);
73
+ }
74
+ }
75
+ }
76
+ return users;
77
+ }
78
+ }
79
+ exports.MessageOperations = MessageOperations;
80
+ //# sourceMappingURL=message-operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-operations.js","sourceRoot":"","sources":["../../../src/utils/slack-operations/message-operations.ts"],"names":[],"mappings":";;;AACA,+CAAgD;AAChD,0DAAsD;AACtD,4CAAwC;AAExC,6DAAyD;AAEzD,MAAa,iBAAkB,SAAQ,6BAAe;IAGpD,YAAY,KAAa;QACvB,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,UAAU,GAAG,IAAI,sCAAiB,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,IAAY;QAC7C,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;YACxC,OAAO;YACP,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAe,EAAE,OAAuB;QACvD,uCAAuC;QACvC,MAAM,SAAS,GAAG,MAAM,kCAAe,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CACrE,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;YAC3B,KAAK,EAAE,wCAAwC;YAC/C,gBAAgB,EAAE,IAAI;YACtB,KAAK,EAAE,oBAAQ,CAAC,cAAc;SAC/B,CAAC,CACH,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC;YACvD,OAAO,EAAE,SAAS;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAqB,CAAC;QAEhD,sBAAsB;QACtB,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAK,CAAC,CAAC,CAAC,CAAC;QACjF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAEhD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,eAAuB;QAC5C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAEtE,sBAAsB;QACtB,IAAI,QAAQ,GAAc,EAAE,CAAC;QAC7B,IAAI,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;QAEtC,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;YAClD,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,EAAE;gBACtD,KAAK,EAAE,OAAO,CAAC,YAAY;gBAC3B,MAAM,EAAE,OAAO,CAAC,SAAS;aAC1B,CAAC,CAAC;YACH,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;YAClC,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC;QAC9B,CAAC;QAED,OAAO;YACL,OAAO,EAAE;gBACP,GAAG,OAAO;gBACV,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,CAAC;gBACvC,oBAAoB,EAAE,OAAO,CAAC,oBAAoB,IAAI,CAAC;aACxD;YACD,QAAQ;YACR,KAAK;SACN,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,OAAiB;QAC3C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;QAExC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;oBAChE,IAAI,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;wBACxB,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACxC,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,8CAA8C;oBAC9C,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAtFD,8CAsFC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@urugus/slack-cli",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "A command-line tool for sending messages to Slack",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -3,13 +3,8 @@ import { wrapCommand } from '../utils/command-wrapper';
3
3
  import { createSlackClient } from '../utils/client-factory';
4
4
  import { ERROR_MESSAGES } from '../utils/constants';
5
5
  import { ChannelsOptions } from '../types/commands';
6
- import {
7
- mapChannelToInfo,
8
- formatChannelsAsTable,
9
- formatChannelsAsSimple,
10
- formatChannelsAsJson,
11
- getChannelTypes,
12
- } from '../utils/channel-formatter';
6
+ import { mapChannelToInfo, getChannelTypes } from '../utils/channel-formatter';
7
+ import { createChannelsListFormatter } from '../utils/formatters/channels-list-formatters';
13
8
 
14
9
  export function setupChannelsCommand(): Command {
15
10
  const channelsCommand = new Command('channels');
@@ -43,21 +38,8 @@ export function setupChannelsCommand(): Command {
43
38
 
44
39
  // Format and display channels
45
40
  const channelInfos = channels.map(mapChannelToInfo);
46
-
47
- switch (options.format) {
48
- case 'simple':
49
- formatChannelsAsSimple(channelInfos);
50
- break;
51
-
52
- case 'json':
53
- formatChannelsAsJson(channelInfos);
54
- break;
55
-
56
- case 'table':
57
- default:
58
- formatChannelsAsTable(channelInfos);
59
- break;
60
- }
41
+ const formatter = createChannelsListFormatter(options.format);
42
+ formatter.format(channelInfos);
61
43
  })
62
44
  );
63
45