···
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 }) => {
-
const args = payload.text.trim().split(/\s+/);
-
const ircChannel = args[0];
-
if (!ircChannel || !ircChannel.startsWith("#")) {
-
text: "Usage: `/irc-bridge-channel #irc-channel`\nExample: `/irc-bridge-channel #lounge`",
-
const slackChannelId = payload.channel_id;
channelMappings.create(slackChannelId, ircChannel);
-
// Join the IRC channel
ircClient.join(ircChannel);
-
// Join the Slack channel if not already in it
await context.client.conversations.join({
-
text: `✅ Successfully bridged this channel to ${ircChannel}`,
console.error("Error creating channel mapping:", error);
text: `❌ Failed to bridge channel: ${error}`,
// Unlink Slack channel from IRC
-
slackApp.command("/irc-unbridge-channel", async ({ payload }) => {
const slackChannelId = payload.channel_id;
const mapping = channelMappings.getBySlackChannel(slackChannelId);
text: "❌ This channel is not bridged to IRC",
channelMappings.delete(slackChannelId);
text: `✅ Removed bridge to ${mapping.irc_channel}`,
console.error("Error removing channel mapping:", error);
text: `❌ Failed to remove bridge: ${error}`,
// Link Slack user to IRC nick
-
slackApp.command("/irc-bridge-user", async ({ payload }) => {
-
const args = payload.text.trim().split(/\s+/);
-
const ircNick = args[0];
-
text: "Usage: `/irc-bridge-user <irc-nick>`\nExample: `/irc-bridge-user myircnick`",
-
const slackUserId = payload.user_id;
userMappings.create(slackUserId, ircNick);
console.log(`Created user mapping: ${slackUserId} -> ${ircNick}`);
-
text: `✅ Successfully linked your account to IRC nick: ${ircNick}`,
console.error("Error creating user mapping:", error);
text: `❌ Failed to link user: ${error}`,
// Unlink Slack user from IRC
-
slackApp.command("/irc-unbridge-user", async ({ payload }) => {
const slackUserId = payload.user_id;
const mapping = userMappings.getBySlackUser(slackUserId);
text: "❌ You don't have an IRC nick mapping",
userMappings.delete(slackUserId);
text: `✅ Removed link to IRC nick: ${mapping.irc_nick}`,
console.error("Error removing user mapping:", error);
text: `❌ Failed to remove link: ${error}`,
-
slackApp.command("/irc-bridge-list", async ({ payload }) => {
const channelMaps = channelMappings.getAll();
const userMaps = userMappings.getAll();
-
let text = "*Channel Bridges:*\n";
if (channelMaps.length === 0) {
for (const map of channelMaps) {
-
text += `• <#${map.slack_channel_id}> ↔️ ${map.irc_channel}\n`;
-
text += "\n*User Mappings:*\n";
if (userMaps.length === 0) {
for (const map of userMaps) {
-
text += `• <@${map.slack_user_id}> ↔️ ${map.irc_nick}\n`;
···
+
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 }) => {
+
response_type: "ephemeral",
+
text: "Bridge channel command received",
+
block_id: "irc_channel_input",
+
type: "plain_text_input",
+
action_id: "irc_channel",
+
text: "Bridge Channel",
+
action_id: "bridge_channel_submit",
+
value: payload.channel_id,
+
replace_original: true,
+
// Handle bridge channel submission
+
slackApp.action("bridge_channel_submit", async ({ payload, context }) => {
+
const stateValues = payload.state?.values;
+
const ircChannel = stateValues?.irc_channel_input?.irc_channel?.value;
+
const slackChannelId = payload.actions?.[0]?.value;
+
if (!context.respond) {
+
if (!ircChannel || !ircChannel.startsWith("#")) {
+
response_type: "ephemeral",
+
text: "❌ IRC channel must start with #",
+
replace_original: true,
channelMappings.create(slackChannelId, ircChannel);
ircClient.join(ircChannel);
await context.client.conversations.join({
+
`Created channel mapping: ${slackChannelId} -> ${ircChannel}`,
+
response_type: "ephemeral",
+
text: `✅ Successfully bridged <#${slackChannelId}> to ${ircChannel}`,
+
replace_original: true,
console.error("Error creating channel mapping:", error);
+
response_type: "ephemeral",
text: `❌ Failed to bridge channel: ${error}`,
+
replace_original: true,
// Unlink Slack channel from IRC
+
slackApp.command("/irc-unbridge-channel", async ({ payload, context }) => {
const slackChannelId = payload.channel_id;
+
const mapping = channelMappings.getBySlackChannel(slackChannelId);
+
response_type: "ephemeral",
+
text: "❌ This channel is not bridged to IRC",
+
response_type: "ephemeral",
+
text: "Are you sure you want to remove the bridge to *${mapping.irc_channel}*?",
+
text: `Are you sure you want to remove the bridge to *${mapping.irc_channel}*?`,
+
action_id: "unbridge_channel_confirm",
+
replace_original: true,
+
// Handle unbridge confirmation
+
slackApp.action("unbridge_channel_confirm", async ({ payload, context }) => {
+
const slackChannelId = payload.actions?.[0]?.value;
+
if (!context.respond) return;
const mapping = channelMappings.getBySlackChannel(slackChannelId);
+
response_type: "ephemeral",
text: "❌ This channel is not bridged to IRC",
+
replace_original: true,
channelMappings.delete(slackChannelId);
+
`Removed channel mapping: ${slackChannelId} -> ${mapping.irc_channel}`,
+
response_type: "ephemeral",
text: `✅ Removed bridge to ${mapping.irc_channel}`,
+
replace_original: true,
console.error("Error removing channel mapping:", error);
+
response_type: "ephemeral",
text: `❌ Failed to remove bridge: ${error}`,
+
replace_original: true,
// Link Slack user to IRC nick
+
slackApp.command("/irc-bridge-user", async ({ payload, context }) => {
+
response_type: "ephemeral",
+
text: "Enter your IRC nickname",
+
block_id: "irc_nick_input",
+
type: "plain_text_input",
+
action_id: "bridge_user_submit",
+
value: payload.user_id,
+
replace_original: true,
+
// Handle bridge user submission
+
slackApp.action("bridge_user_submit", async ({ payload, context }) => {
+
const stateValues = payload.state?.values;
+
const ircNick = stateValues?.irc_nick_input?.irc_nick?.value;
+
const slackUserId = payload.actions?.[0]?.value;
+
if (!context.respond) {
+
response_type: "ephemeral",
+
text: "❌ IRC nickname is required",
+
replace_original: true,
userMappings.create(slackUserId, ircNick);
console.log(`Created user mapping: ${slackUserId} -> ${ircNick}`);
+
response_type: "ephemeral",
+
text: `✅ Successfully linked your account to IRC nick: *${ircNick}*`,
+
replace_original: true,
console.error("Error creating user mapping:", error);
+
response_type: "ephemeral",
text: `❌ Failed to link user: ${error}`,
+
replace_original: true,
// Unlink Slack user from IRC
+
slackApp.command("/irc-unbridge-user", async ({ payload, context }) => {
const slackUserId = payload.user_id;
+
const mapping = userMappings.getBySlackUser(slackUserId);
+
response_type: "ephemeral",
+
text: "❌ You don't have an IRC nick mapping",
+
response_type: "ephemeral",
+
text: "Are you sure you want to remove your link to IRC nick *${mapping.irc_nick}*?",
+
text: `Are you sure you want to remove your link to IRC nick *${mapping.irc_nick}*?`,
+
action_id: "unbridge_user_confirm",
+
replace_original: true,
+
// Handle unbridge user confirmation
+
slackApp.action("unbridge_user_confirm", async ({ payload, context }) => {
+
const slackUserId = payload.actions?.[0]?.value;
+
if (!context.respond) {
const mapping = userMappings.getBySlackUser(slackUserId);
+
response_type: "ephemeral",
text: "❌ You don't have an IRC nick mapping",
+
replace_original: true,
userMappings.delete(slackUserId);
+
`Removed user mapping: ${slackUserId} -> ${mapping.irc_nick}`,
+
response_type: "ephemeral",
text: `✅ Removed link to IRC nick: ${mapping.irc_nick}`,
+
replace_original: true,
console.error("Error removing user mapping:", error);
+
response_type: "ephemeral",
text: `❌ Failed to remove link: ${error}`,
+
replace_original: true,
+
// Handle cancel button
+
slackApp.action("cancel", async ({ context }) => {
+
if (!context.respond) return;
+
response_type: "ephemeral",
+
slackApp.command("/irc-bridge-list", async ({ payload, context }) => {
const channelMaps = channelMappings.getAll();
const userMaps = userMappings.getAll();
+
const blocks: AnyMessageBlock[] = [
+
text: "IRC Bridge Status",
+
text: "*Channel Bridges:*",
if (channelMaps.length === 0) {
+
text: "_No channel bridges configured_",
for (const map of channelMaps) {
+
text: `• <#${map.slack_channel_id}> ↔️ *${map.irc_channel}*`,
+
text: "*User Mappings:*",
if (userMaps.length === 0) {
+
text: "_No user mappings configured_",
for (const map of userMaps) {
+
text: `• <@${map.slack_user_id}> ↔️ *${map.irc_nick}*`,
+
response_type: "ephemeral",
+
text: "IRC mapping list",
+
replace_original: true,