···
1
+
import type { AnyMessageBlock, Block, BlockElement } from "slack-edge";
import { channelMappings, userMappings } from "./db";
import { slackApp, ircClient } from "./index";
export function registerCommands() {
// Link Slack channel to IRC channel
slackApp.command("/irc-bridge-channel", async ({ payload, context }) => {
7
-
const args = payload.text.trim().split(/\s+/);
8
-
const ircChannel = args[0];
9
+
response_type: "ephemeral",
10
+
text: "Bridge channel command received",
14
+
block_id: "irc_channel_input",
16
+
type: "plain_text_input",
17
+
action_id: "irc_channel",
25
+
text: "IRC Channel",
35
+
text: "Bridge Channel",
38
+
action_id: "bridge_channel_submit",
39
+
value: payload.channel_id,
47
+
action_id: "cancel",
52
+
replace_original: true,
10
-
if (!ircChannel || !ircChannel.startsWith("#")) {
12
-
text: "Usage: `/irc-bridge-channel #irc-channel`\nExample: `/irc-bridge-channel #lounge`",
56
+
// Handle bridge channel submission
57
+
slackApp.action("bridge_channel_submit", async ({ payload, context }) => {
58
+
const stateValues = payload.state?.values;
59
+
const ircChannel = stateValues?.irc_channel_input?.irc_channel?.value;
61
+
const slackChannelId = payload.actions?.[0]?.value;
62
+
if (!context.respond) {
16
-
const slackChannelId = payload.channel_id;
66
+
if (!ircChannel || !ircChannel.startsWith("#")) {
68
+
response_type: "ephemeral",
69
+
text: "❌ IRC channel must start with #",
70
+
replace_original: true,
19
-
// Create the mapping
channelMappings.create(slackChannelId, ircChannel);
22
-
// Join the IRC channel
ircClient.join(ircChannel);
25
-
// Join the Slack channel if not already in it
await context.client.conversations.join({
31
-
text: `✅ Successfully bridged this channel to ${ircChannel}`,
84
+
`Created channel mapping: ${slackChannelId} -> ${ircChannel}`,
88
+
response_type: "ephemeral",
89
+
text: `✅ Successfully bridged <#${slackChannelId}> to ${ircChannel}`,
90
+
replace_original: true,
console.error("Error creating channel mapping:", error);
95
+
response_type: "ephemeral",
text: `❌ Failed to bridge channel: ${error}`,
97
+
replace_original: true,
// Unlink Slack channel from IRC
42
-
slackApp.command("/irc-unbridge-channel", async ({ payload }) => {
103
+
slackApp.command("/irc-unbridge-channel", async ({ payload, context }) => {
const slackChannelId = payload.channel_id;
105
+
const mapping = channelMappings.getBySlackChannel(slackChannelId);
109
+
response_type: "ephemeral",
110
+
text: "❌ This channel is not bridged to IRC",
116
+
response_type: "ephemeral",
117
+
text: "Are you sure you want to remove the bridge to *${mapping.irc_channel}*?",
123
+
text: `Are you sure you want to remove the bridge to *${mapping.irc_channel}*?`,
132
+
type: "plain_text",
133
+
text: "Remove Bridge",
136
+
action_id: "unbridge_channel_confirm",
137
+
value: slackChannelId,
142
+
type: "plain_text",
145
+
action_id: "cancel",
150
+
replace_original: true,
154
+
// Handle unbridge confirmation
155
+
slackApp.action("unbridge_channel_confirm", async ({ payload, context }) => {
156
+
// @ts-expect-error
157
+
const slackChannelId = payload.actions?.[0]?.value;
158
+
if (!context.respond) return;
const mapping = channelMappings.getBySlackChannel(slackChannelId);
164
+
response_type: "ephemeral",
text: "❌ This channel is not bridged to IRC",
166
+
replace_original: true,
channelMappings.delete(slackChannelId);
173
+
`Removed channel mapping: ${slackChannelId} -> ${mapping.irc_channel}`,
177
+
response_type: "ephemeral",
text: `✅ Removed bridge to ${mapping.irc_channel}`,
179
+
replace_original: true,
console.error("Error removing channel mapping:", error);
184
+
response_type: "ephemeral",
text: `❌ Failed to remove bridge: ${error}`,
186
+
replace_original: true,
// Link Slack user to IRC nick
67
-
slackApp.command("/irc-bridge-user", async ({ payload }) => {
68
-
const args = payload.text.trim().split(/\s+/);
69
-
const ircNick = args[0];
192
+
slackApp.command("/irc-bridge-user", async ({ payload, context }) => {
194
+
response_type: "ephemeral",
195
+
text: "Enter your IRC nickname",
199
+
block_id: "irc_nick_input",
201
+
type: "plain_text_input",
202
+
action_id: "irc_nick",
204
+
type: "plain_text",
209
+
type: "plain_text",
210
+
text: "IRC Nickname",
219
+
type: "plain_text",
220
+
text: "Link Account",
223
+
action_id: "bridge_user_submit",
224
+
value: payload.user_id,
229
+
type: "plain_text",
232
+
action_id: "cancel",
237
+
replace_original: true,
241
+
// Handle bridge user submission
242
+
slackApp.action("bridge_user_submit", async ({ payload, context }) => {
243
+
const stateValues = payload.state?.values;
244
+
const ircNick = stateValues?.irc_nick_input?.irc_nick?.value;
245
+
// @ts-expect-error
246
+
const slackUserId = payload.actions?.[0]?.value;
247
+
if (!context.respond) {
73
-
text: "Usage: `/irc-bridge-user <irc-nick>`\nExample: `/irc-bridge-user myircnick`",
253
+
response_type: "ephemeral",
254
+
text: "❌ IRC nickname is required",
255
+
replace_original: true,
77
-
const slackUserId = payload.user_id;
userMappings.create(slackUserId, ircNick);
console.log(`Created user mapping: ${slackUserId} -> ${ircNick}`);
84
-
text: `✅ Successfully linked your account to IRC nick: ${ircNick}`,
265
+
response_type: "ephemeral",
266
+
text: `✅ Successfully linked your account to IRC nick: *${ircNick}*`,
267
+
replace_original: true,
console.error("Error creating user mapping:", error);
272
+
response_type: "ephemeral",
text: `❌ Failed to link user: ${error}`,
274
+
replace_original: true,
// Unlink Slack user from IRC
95
-
slackApp.command("/irc-unbridge-user", async ({ payload }) => {
280
+
slackApp.command("/irc-unbridge-user", async ({ payload, context }) => {
const slackUserId = payload.user_id;
282
+
const mapping = userMappings.getBySlackUser(slackUserId);
286
+
response_type: "ephemeral",
287
+
text: "❌ You don't have an IRC nick mapping",
293
+
response_type: "ephemeral",
294
+
text: "Are you sure you want to remove your link to IRC nick *${mapping.irc_nick}*?",
300
+
text: `Are you sure you want to remove your link to IRC nick *${mapping.irc_nick}*?`,
309
+
type: "plain_text",
310
+
text: "Remove Link",
313
+
action_id: "unbridge_user_confirm",
314
+
value: slackUserId,
319
+
type: "plain_text",
322
+
action_id: "cancel",
327
+
replace_original: true,
331
+
// Handle unbridge user confirmation
332
+
slackApp.action("unbridge_user_confirm", async ({ payload, context }) => {
333
+
// @ts-expect-error
334
+
const slackUserId = payload.actions?.[0]?.value;
335
+
if (!context.respond) {
const mapping = userMappings.getBySlackUser(slackUserId);
343
+
response_type: "ephemeral",
text: "❌ You don't have an IRC nick mapping",
345
+
replace_original: true,
userMappings.delete(slackUserId);
352
+
`Removed user mapping: ${slackUserId} -> ${mapping.irc_nick}`,
356
+
response_type: "ephemeral",
text: `✅ Removed link to IRC nick: ${mapping.irc_nick}`,
358
+
replace_original: true,
console.error("Error removing user mapping:", error);
363
+
response_type: "ephemeral",
text: `❌ Failed to remove link: ${error}`,
365
+
replace_original: true,
370
+
// Handle cancel button
371
+
slackApp.action("cancel", async ({ context }) => {
372
+
if (!context.respond) return;
375
+
response_type: "ephemeral",
376
+
delete_original: true,
120
-
slackApp.command("/irc-bridge-list", async ({ payload }) => {
381
+
slackApp.command("/irc-bridge-list", async ({ payload, context }) => {
const channelMaps = channelMappings.getAll();
const userMaps = userMappings.getAll();
124
-
let text = "*Channel Bridges:*\n";
385
+
const blocks: AnyMessageBlock[] = [
389
+
type: "plain_text",
390
+
text: "IRC Bridge Status",
397
+
text: "*Channel Bridges:*",
if (channelMaps.length === 0) {
407
+
text: "_No channel bridges configured_",
for (const map of channelMaps) {
129
-
text += `• <#${map.slack_channel_id}> ↔️ ${map.irc_channel}\n`;
416
+
text: `• <#${map.slack_channel_id}> ↔️ *${map.irc_channel}*`,
133
-
text += "\n*User Mappings:*\n";
430
+
text: "*User Mappings:*",
if (userMaps.length === 0) {
440
+
text: "_No user mappings configured_",
for (const map of userMaps) {
138
-
text += `• <@${map.slack_user_id}> ↔️ ${map.irc_nick}\n`;
449
+
text: `• <@${map.slack_user_id}> ↔️ *${map.irc_nick}*`,
456
+
response_type: "ephemeral",
457
+
text: "IRC mapping list",
459
+
replace_original: true,