this repo has no description

chore: format and ignore slack threads

dunkirk.sh 00788028 9c84fca1

verified
+21 -21
package.json
···
{
-
"name": "irc-slack-bridge",
-
"version": "0.0.1",
-
"module": "src/index.ts",
-
"type": "module",
-
"private": true,
-
"scripts": {
-
"dev": "bun src/index.ts",
-
"start": "bun src/index.ts",
-
"ngrok": "ngrok http 3000 --domain casual-renewing-reptile.ngrok-free.app"
-
},
-
"devDependencies": {
-
"@types/bun": "latest",
-
"@types/irc": "^0.5.4"
-
},
-
"peerDependencies": {
-
"typescript": "^5"
-
},
-
"dependencies": {
-
"irc": "^0.5.2",
-
"slack-edge": "^1.3.12"
-
}
}
···
{
+
"name": "irc-slack-bridge",
+
"version": "0.0.1",
+
"module": "src/index.ts",
+
"type": "module",
+
"private": true,
+
"scripts": {
+
"dev": "bun src/index.ts",
+
"start": "bun src/index.ts",
+
"ngrok": "ngrok http 3000 --domain casual-renewing-reptile.ngrok-free.app"
+
},
+
"devDependencies": {
+
"@types/bun": "latest",
+
"@types/irc": "^0.5.4"
+
},
+
"peerDependencies": {
+
"typescript": "^5"
+
},
+
"dependencies": {
+
"irc": "^0.5.2",
+
"slack-edge": "^1.3.12"
+
}
}
+118 -118
src/commands.ts
···
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("#")) {
-
return {
-
text: "Usage: `/irc-bridge-channel #irc-channel`\nExample: `/irc-bridge-channel #lounge`",
-
};
-
}
-
const slackChannelId = payload.channel_id;
-
try {
-
// Create the mapping
-
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({
-
channel: slackChannelId,
-
});
-
return {
-
text: `✅ Successfully bridged this channel to ${ircChannel}`,
-
};
-
} catch (error) {
-
console.error("Error creating channel mapping:", error);
-
return {
-
text: `❌ Failed to bridge channel: ${error}`,
-
};
-
}
-
});
-
// Unlink Slack channel from IRC
-
slackApp.command("/irc-unbridge-channel", async ({ payload }) => {
-
const slackChannelId = payload.channel_id;
-
try {
-
const mapping = channelMappings.getBySlackChannel(slackChannelId);
-
if (!mapping) {
-
return {
-
text: "❌ This channel is not bridged to IRC",
-
};
-
}
-
channelMappings.delete(slackChannelId);
-
return {
-
text: `✅ Removed bridge to ${mapping.irc_channel}`,
-
};
-
} catch (error) {
-
console.error("Error removing channel mapping:", error);
-
return {
-
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];
-
if (!ircNick) {
-
return {
-
text: "Usage: `/irc-bridge-user <irc-nick>`\nExample: `/irc-bridge-user myircnick`",
-
};
-
}
-
const slackUserId = payload.user_id;
-
try {
-
userMappings.create(slackUserId, ircNick);
-
console.log(`Created user mapping: ${slackUserId} -> ${ircNick}`);
-
return {
-
text: `✅ Successfully linked your account to IRC nick: ${ircNick}`,
-
};
-
} catch (error) {
-
console.error("Error creating user mapping:", error);
-
return {
-
text: `❌ Failed to link user: ${error}`,
-
};
-
}
-
});
-
// Unlink Slack user from IRC
-
slackApp.command("/irc-unbridge-user", async ({ payload }) => {
-
const slackUserId = payload.user_id;
-
try {
-
const mapping = userMappings.getBySlackUser(slackUserId);
-
if (!mapping) {
-
return {
-
text: "❌ You don't have an IRC nick mapping",
-
};
-
}
-
userMappings.delete(slackUserId);
-
return {
-
text: `✅ Removed link to IRC nick: ${mapping.irc_nick}`,
-
};
-
} catch (error) {
-
console.error("Error removing user mapping:", error);
-
return {
-
text: `❌ Failed to remove link: ${error}`,
-
};
-
}
-
});
-
// List channel mappings
-
slackApp.command("/irc-bridge-list", async ({ payload }) => {
-
const channelMaps = channelMappings.getAll();
-
const userMaps = userMappings.getAll();
-
let text = "*Channel Bridges:*\n";
-
if (channelMaps.length === 0) {
-
text += "None\n";
-
} else {
-
for (const map of channelMaps) {
-
text += `• <#${map.slack_channel_id}> ↔️ ${map.irc_channel}\n`;
-
}
-
}
-
text += "\n*User Mappings:*\n";
-
if (userMaps.length === 0) {
-
text += "None\n";
-
} else {
-
for (const map of userMaps) {
-
text += `• <@${map.slack_user_id}> ↔️ ${map.irc_nick}\n`;
-
}
-
}
-
return {
-
text,
-
};
-
});
}
···
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("#")) {
+
return {
+
text: "Usage: `/irc-bridge-channel #irc-channel`\nExample: `/irc-bridge-channel #lounge`",
+
};
+
}
+
const slackChannelId = payload.channel_id;
+
try {
+
// Create the mapping
+
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({
+
channel: slackChannelId,
+
});
+
return {
+
text: `✅ Successfully bridged this channel to ${ircChannel}`,
+
};
+
} catch (error) {
+
console.error("Error creating channel mapping:", error);
+
return {
+
text: `❌ Failed to bridge channel: ${error}`,
+
};
+
}
+
});
+
// Unlink Slack channel from IRC
+
slackApp.command("/irc-unbridge-channel", async ({ payload }) => {
+
const slackChannelId = payload.channel_id;
+
try {
+
const mapping = channelMappings.getBySlackChannel(slackChannelId);
+
if (!mapping) {
+
return {
+
text: "❌ This channel is not bridged to IRC",
+
};
+
}
+
channelMappings.delete(slackChannelId);
+
return {
+
text: `✅ Removed bridge to ${mapping.irc_channel}`,
+
};
+
} catch (error) {
+
console.error("Error removing channel mapping:", error);
+
return {
+
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];
+
if (!ircNick) {
+
return {
+
text: "Usage: `/irc-bridge-user <irc-nick>`\nExample: `/irc-bridge-user myircnick`",
+
};
+
}
+
const slackUserId = payload.user_id;
+
try {
+
userMappings.create(slackUserId, ircNick);
+
console.log(`Created user mapping: ${slackUserId} -> ${ircNick}`);
+
return {
+
text: `✅ Successfully linked your account to IRC nick: ${ircNick}`,
+
};
+
} catch (error) {
+
console.error("Error creating user mapping:", error);
+
return {
+
text: `❌ Failed to link user: ${error}`,
+
};
+
}
+
});
+
// Unlink Slack user from IRC
+
slackApp.command("/irc-unbridge-user", async ({ payload }) => {
+
const slackUserId = payload.user_id;
+
try {
+
const mapping = userMappings.getBySlackUser(slackUserId);
+
if (!mapping) {
+
return {
+
text: "❌ You don't have an IRC nick mapping",
+
};
+
}
+
userMappings.delete(slackUserId);
+
return {
+
text: `✅ Removed link to IRC nick: ${mapping.irc_nick}`,
+
};
+
} catch (error) {
+
console.error("Error removing user mapping:", error);
+
return {
+
text: `❌ Failed to remove link: ${error}`,
+
};
+
}
+
});
+
// List channel mappings
+
slackApp.command("/irc-bridge-list", async ({ payload }) => {
+
const channelMaps = channelMappings.getAll();
+
const userMaps = userMappings.getAll();
+
let text = "*Channel Bridges:*\n";
+
if (channelMaps.length === 0) {
+
text += "None\n";
+
} else {
+
for (const map of channelMaps) {
+
text += `• <#${map.slack_channel_id}> ↔️ ${map.irc_channel}\n`;
+
}
+
}
+
text += "\n*User Mappings:*\n";
+
if (userMaps.length === 0) {
+
text += "None\n";
+
} else {
+
for (const map of userMaps) {
+
text += `• <@${map.slack_user_id}> ↔️ ${map.irc_nick}\n`;
+
}
+
}
+
return {
+
text,
+
};
+
});
}
+17 -7
src/db.ts
···
},
getBySlackChannel(slackChannelId: string): ChannelMapping | null {
-
return db.query("SELECT * FROM channel_mappings WHERE slack_channel_id = ?").get(slackChannelId) as ChannelMapping | null;
},
getByIrcChannel(ircChannel: string): ChannelMapping | null {
-
return db.query("SELECT * FROM channel_mappings WHERE irc_channel = ?").get(ircChannel) as ChannelMapping | null;
},
create(slackChannelId: string, ircChannel: string): void {
db.run(
"INSERT OR REPLACE INTO channel_mappings (slack_channel_id, irc_channel) VALUES (?, ?)",
-
[slackChannelId, ircChannel]
);
},
delete(slackChannelId: string): void {
-
db.run("DELETE FROM channel_mappings WHERE slack_channel_id = ?", [slackChannelId]);
},
};
···
},
getBySlackUser(slackUserId: string): UserMapping | null {
-
return db.query("SELECT * FROM user_mappings WHERE slack_user_id = ?").get(slackUserId) as UserMapping | null;
},
getByIrcNick(ircNick: string): UserMapping | null {
-
return db.query("SELECT * FROM user_mappings WHERE irc_nick = ?").get(ircNick) as UserMapping | null;
},
create(slackUserId: string, ircNick: string): void {
db.run(
"INSERT OR REPLACE INTO user_mappings (slack_user_id, irc_nick) VALUES (?, ?)",
-
[slackUserId, ircNick]
);
},
···
},
getBySlackChannel(slackChannelId: string): ChannelMapping | null {
+
return db
+
.query("SELECT * FROM channel_mappings WHERE slack_channel_id = ?")
+
.get(slackChannelId) as ChannelMapping | null;
},
getByIrcChannel(ircChannel: string): ChannelMapping | null {
+
return db
+
.query("SELECT * FROM channel_mappings WHERE irc_channel = ?")
+
.get(ircChannel) as ChannelMapping | null;
},
create(slackChannelId: string, ircChannel: string): void {
db.run(
"INSERT OR REPLACE INTO channel_mappings (slack_channel_id, irc_channel) VALUES (?, ?)",
+
[slackChannelId, ircChannel],
);
},
delete(slackChannelId: string): void {
+
db.run("DELETE FROM channel_mappings WHERE slack_channel_id = ?", [
+
slackChannelId,
+
]);
},
};
···
},
getBySlackUser(slackUserId: string): UserMapping | null {
+
return db
+
.query("SELECT * FROM user_mappings WHERE slack_user_id = ?")
+
.get(slackUserId) as UserMapping | null;
},
getByIrcNick(ircNick: string): UserMapping | null {
+
return db
+
.query("SELECT * FROM user_mappings WHERE irc_nick = ?")
+
.get(ircNick) as UserMapping | null;
},
create(slackUserId: string, ircNick: string): void {
db.run(
"INSERT OR REPLACE INTO user_mappings (slack_user_id, irc_nick) VALUES (?, ?)",
+
[slackUserId, ircNick],
);
},
+145 -144
src/index.ts
···
const missingEnvVars = [];
if (!process.env.SLACK_BOT_TOKEN) missingEnvVars.push("SLACK_BOT_TOKEN");
if (!process.env.SLACK_SIGNING_SECRET)
-
missingEnvVars.push("SLACK_SIGNING_SECRET");
if (!process.env.ADMINS) missingEnvVars.push("ADMINS");
if (!process.env.IRC_NICK) missingEnvVars.push("IRC_NICK");
if (missingEnvVars.length > 0) {
-
throw new Error(
-
`Missing required environment variables: ${missingEnvVars.join(", ")}`,
-
);
}
const slackApp = new SlackApp({
-
env: {
-
SLACK_BOT_TOKEN: process.env.SLACK_BOT_TOKEN as string,
-
SLACK_SIGNING_SECRET: process.env.SLACK_SIGNING_SECRET as string,
-
SLACK_LOGGING_LEVEL: "INFO",
-
},
-
startLazyListenerAfterAck: true,
});
const slackClient = slackApp.client;
// Get bot user ID
let botUserId: string | undefined;
slackClient.auth
-
.test({
-
token: process.env.SLACK_BOT_TOKEN,
-
})
-
.then((result) => {
-
botUserId = result.user_id;
-
console.log(`Bot user ID: ${botUserId}`);
-
});
// IRC client setup
const ircClient = new irc.Client(
-
"irc.hackclub.com",
-
process.env.IRC_NICK || "slackbridge",
-
{
-
port: 6667,
-
autoRejoin: true,
-
autoConnect: true,
-
channels: [],
-
secure: false,
-
userName: process.env.IRC_NICK,
-
realName: "Slack IRC Bridge",
-
},
);
// Clean up IRC connection on hot reload or exit
process.on("beforeExit", () => {
-
ircClient.disconnect("Reloading", () => {
-
console.log("IRC client disconnected");
-
});
});
// Register slash commands
···
// Join all mapped IRC channels on connect
ircClient.addListener("registered", async () => {
-
console.log("Connected to IRC server");
-
const mappings = channelMappings.getAll();
-
for (const mapping of mappings) {
-
ircClient.join(mapping.irc_channel);
-
}
});
ircClient.addListener("join", (channel: string, nick: string) => {
-
if (nick === process.env.IRC_NICK) {
-
console.log(`Joined IRC channel: ${channel}`);
-
}
});
ircClient.addListener(
-
"message",
-
async (nick: string, to: string, text: string) => {
-
// Ignore messages from our own bot (with or without numbers suffix)
-
const botNickPattern = new RegExp(`^${process.env.IRC_NICK}\\d*$`);
-
if (botNickPattern.test(nick)) return;
-
if (nick === "****") return;
-
// Find Slack channel mapping for this IRC channel
-
const mapping = channelMappings.getByIrcChannel(to);
-
if (!mapping) return;
-
// Check if this IRC nick is mapped to a Slack user
-
const userMapping = userMappings.getByIrcNick(nick);
-
const displayName = `${nick} <irc>`;
-
let iconUrl: string | undefined;
-
if (userMapping) {
-
try {
-
iconUrl = `https://cachet.dunkirk.sh/users/${userMapping.slack_user_id}/r`;
-
} catch (error) {
-
console.error("Error fetching user info:", error);
-
}
-
}
-
try {
-
await slackClient.chat.postMessage({
-
token: process.env.SLACK_BOT_TOKEN,
-
channel: mapping.slack_channel_id,
-
text: parseIRCFormatting(text),
-
username: displayName,
-
icon_url: iconUrl,
-
unfurl_links: false,
-
unfurl_media: false,
-
});
-
console.log(`IRC → Slack: <${nick}> ${text}`);
-
} catch (error) {
-
console.error("Error posting to Slack:", error);
-
}
-
},
);
ircClient.addListener("error", (error: string) => {
-
console.error("IRC error:", error);
});
// Slack event handlers
slackApp.event("message", async ({ payload }) => {
-
if (payload.subtype) return;
-
if (payload.bot_id) return;
-
if (payload.user === botUserId) return;
-
// Find IRC channel mapping for this Slack channel
-
const mapping = channelMappings.getBySlackChannel(payload.channel);
-
if (!mapping) {
-
console.log(
-
`No IRC channel mapping found for Slack channel ${payload.channel}`,
-
);
-
slackClient.conversations.leave({
-
channel: payload.channel,
-
});
-
return;
-
}
-
try {
-
const userInfo = await slackClient.users.info({
-
token: process.env.SLACK_BOT_TOKEN,
-
user: payload.user,
-
});
-
// Check for user mapping, otherwise use Slack name
-
const userMapping = userMappings.getBySlackUser(payload.user);
-
const username =
-
userMapping?.irc_nick ||
-
userInfo.user?.real_name ||
-
userInfo.user?.name ||
-
"Unknown";
-
// Parse Slack mentions and replace with display names
-
let messageText = payload.text;
-
const mentionRegex = /<@(U[A-Z0-9]+)>/g;
-
const mentions = Array.from(messageText.matchAll(mentionRegex));
-
for (const match of mentions) {
-
const userId = match[1];
-
try {
-
const response = await fetch(
-
`https://cachet.dunkirk.sh/users/${userId}`,
-
);
-
if (response.ok) {
-
const data = (await response.json()) as CachetUser;
-
messageText = messageText.replace(match[0], `@${data.displayName}`);
-
}
-
} catch (error) {
-
console.error(`Error fetching user ${userId} from cachet:`, error);
-
}
-
}
-
// Parse Slack markdown formatting
-
messageText = parseSlackMarkdown(messageText);
-
const message = `<${username}> ${messageText}`;
-
ircClient.say(mapping.irc_channel, message);
-
console.log(`Slack → IRC: ${message}`);
-
} catch (error) {
-
console.error("Error handling Slack message:", error);
-
}
});
export default {
-
port: process.env.PORT || 3000,
-
async fetch(request: Request) {
-
const url = new URL(request.url);
-
const path = url.pathname;
-
switch (path) {
-
case "/":
-
return new Response(`Hello World from irc-slack-bridge@${version}`);
-
case "/health":
-
return new Response("OK");
-
case "/slack":
-
return slackApp.run(request);
-
default:
-
return new Response("404 Not Found", { status: 404 });
-
}
-
},
};
console.log(
-
`🚀 Server Started in ${Bun.nanoseconds() / 1000000} milliseconds on version: ${version}!\n\n----------------------------------\n`,
);
console.log(
-
`Connecting to IRC: irc.hackclub.com:6667 as ${process.env.IRC_NICK}`,
);
console.log(`Channel mappings: ${channelMappings.getAll().length}`);
console.log(`User mappings: ${userMappings.getAll().length}`);
···
const missingEnvVars = [];
if (!process.env.SLACK_BOT_TOKEN) missingEnvVars.push("SLACK_BOT_TOKEN");
if (!process.env.SLACK_SIGNING_SECRET)
+
missingEnvVars.push("SLACK_SIGNING_SECRET");
if (!process.env.ADMINS) missingEnvVars.push("ADMINS");
if (!process.env.IRC_NICK) missingEnvVars.push("IRC_NICK");
if (missingEnvVars.length > 0) {
+
throw new Error(
+
`Missing required environment variables: ${missingEnvVars.join(", ")}`,
+
);
}
const slackApp = new SlackApp({
+
env: {
+
SLACK_BOT_TOKEN: process.env.SLACK_BOT_TOKEN as string,
+
SLACK_SIGNING_SECRET: process.env.SLACK_SIGNING_SECRET as string,
+
SLACK_LOGGING_LEVEL: "INFO",
+
},
+
startLazyListenerAfterAck: true,
});
const slackClient = slackApp.client;
// Get bot user ID
let botUserId: string | undefined;
slackClient.auth
+
.test({
+
token: process.env.SLACK_BOT_TOKEN,
+
})
+
.then((result) => {
+
botUserId = result.user_id;
+
console.log(`Bot user ID: ${botUserId}`);
+
});
// IRC client setup
const ircClient = new irc.Client(
+
"irc.hackclub.com",
+
process.env.IRC_NICK || "slackbridge",
+
{
+
port: 6667,
+
autoRejoin: true,
+
autoConnect: true,
+
channels: [],
+
secure: false,
+
userName: process.env.IRC_NICK,
+
realName: "Slack IRC Bridge",
+
},
);
// Clean up IRC connection on hot reload or exit
process.on("beforeExit", () => {
+
ircClient.disconnect("Reloading", () => {
+
console.log("IRC client disconnected");
+
});
});
// Register slash commands
···
// Join all mapped IRC channels on connect
ircClient.addListener("registered", async () => {
+
console.log("Connected to IRC server");
+
const mappings = channelMappings.getAll();
+
for (const mapping of mappings) {
+
ircClient.join(mapping.irc_channel);
+
}
});
ircClient.addListener("join", (channel: string, nick: string) => {
+
if (nick === process.env.IRC_NICK) {
+
console.log(`Joined IRC channel: ${channel}`);
+
}
});
ircClient.addListener(
+
"message",
+
async (nick: string, to: string, text: string) => {
+
// Ignore messages from our own bot (with or without numbers suffix)
+
const botNickPattern = new RegExp(`^${process.env.IRC_NICK}\\d*$`);
+
if (botNickPattern.test(nick)) return;
+
if (nick === "****") return;
+
// Find Slack channel mapping for this IRC channel
+
const mapping = channelMappings.getByIrcChannel(to);
+
if (!mapping) return;
+
// Check if this IRC nick is mapped to a Slack user
+
const userMapping = userMappings.getByIrcNick(nick);
+
const displayName = `${nick} <irc>`;
+
let iconUrl: string | undefined;
+
if (userMapping) {
+
try {
+
iconUrl = `https://cachet.dunkirk.sh/users/${userMapping.slack_user_id}/r`;
+
} catch (error) {
+
console.error("Error fetching user info:", error);
+
}
+
}
+
try {
+
await slackClient.chat.postMessage({
+
token: process.env.SLACK_BOT_TOKEN,
+
channel: mapping.slack_channel_id,
+
text: parseIRCFormatting(text),
+
username: displayName,
+
icon_url: iconUrl,
+
unfurl_links: false,
+
unfurl_media: false,
+
});
+
console.log(`IRC → Slack: <${nick}> ${text}`);
+
} catch (error) {
+
console.error("Error posting to Slack:", error);
+
}
+
},
);
ircClient.addListener("error", (error: string) => {
+
console.error("IRC error:", error);
});
// Slack event handlers
slackApp.event("message", async ({ payload }) => {
+
if (payload.subtype) return;
+
if (payload.bot_id) return;
+
if (payload.user === botUserId) return;
+
if (payload.thread_ts) return;
+
// Find IRC channel mapping for this Slack channel
+
const mapping = channelMappings.getBySlackChannel(payload.channel);
+
if (!mapping) {
+
console.log(
+
`No IRC channel mapping found for Slack channel ${payload.channel}`,
+
);
+
slackClient.conversations.leave({
+
channel: payload.channel,
+
});
+
return;
+
}
+
try {
+
const userInfo = await slackClient.users.info({
+
token: process.env.SLACK_BOT_TOKEN,
+
user: payload.user,
+
});
+
// Check for user mapping, otherwise use Slack name
+
const userMapping = userMappings.getBySlackUser(payload.user);
+
const username =
+
userMapping?.irc_nick ||
+
userInfo.user?.real_name ||
+
userInfo.user?.name ||
+
"Unknown";
+
// Parse Slack mentions and replace with display names
+
let messageText = payload.text;
+
const mentionRegex = /<@(U[A-Z0-9]+)>/g;
+
const mentions = Array.from(messageText.matchAll(mentionRegex));
+
for (const match of mentions) {
+
const userId = match[1];
+
try {
+
const response = await fetch(
+
`https://cachet.dunkirk.sh/users/${userId}`,
+
);
+
if (response.ok) {
+
const data = (await response.json()) as CachetUser;
+
messageText = messageText.replace(match[0], `@${data.displayName}`);
+
}
+
} catch (error) {
+
console.error(`Error fetching user ${userId} from cachet:`, error);
+
}
+
}
+
// Parse Slack markdown formatting
+
messageText = parseSlackMarkdown(messageText);
+
const message = `<${username}> ${messageText}`;
+
ircClient.say(mapping.irc_channel, message);
+
console.log(`Slack → IRC: ${message}`);
+
} catch (error) {
+
console.error("Error handling Slack message:", error);
+
}
});
export default {
+
port: process.env.PORT || 3000,
+
async fetch(request: Request) {
+
const url = new URL(request.url);
+
const path = url.pathname;
+
switch (path) {
+
case "/":
+
return new Response(`Hello World from irc-slack-bridge@${version}`);
+
case "/health":
+
return new Response("OK");
+
case "/slack":
+
return slackApp.run(request);
+
default:
+
return new Response("404 Not Found", { status: 404 });
+
}
+
},
};
console.log(
+
`🚀 Server Started in ${Bun.nanoseconds() / 1000000} milliseconds on version: ${version}!\n\n----------------------------------\n`,
);
console.log(
+
`Connecting to IRC: irc.hackclub.com:6667 as ${process.env.IRC_NICK}`,
);
console.log(`Channel mappings: ${channelMappings.getAll().length}`);
console.log(`User mappings: ${userMappings.getAll().length}`);
-1
src/parser.ts
···
return parsed;
}
-
···
return parsed;
}
+24 -24
tsconfig.json
···
{
-
"compilerOptions": {
-
// Environment setup & latest features
-
"lib": ["ESNext"],
-
"target": "ESNext",
-
"module": "Preserve",
-
"moduleDetection": "force",
-
"jsx": "react-jsx",
-
"allowJs": true,
-
// Bundler mode
-
"moduleResolution": "bundler",
-
"allowImportingTsExtensions": true,
-
"verbatimModuleSyntax": true,
-
"noEmit": true,
-
// Best practices
-
"strict": true,
-
"skipLibCheck": true,
-
"noFallthroughCasesInSwitch": true,
-
"noUncheckedIndexedAccess": true,
-
"noImplicitOverride": true,
-
// Some stricter flags (disabled by default)
-
"noUnusedLocals": false,
-
"noUnusedParameters": false,
-
"noPropertyAccessFromIndexSignature": false
-
}
}
···
{
+
"compilerOptions": {
+
// Environment setup & latest features
+
"lib": ["ESNext"],
+
"target": "ESNext",
+
"module": "Preserve",
+
"moduleDetection": "force",
+
"jsx": "react-jsx",
+
"allowJs": true,
+
// Bundler mode
+
"moduleResolution": "bundler",
+
"allowImportingTsExtensions": true,
+
"verbatimModuleSyntax": true,
+
"noEmit": true,
+
// Best practices
+
"strict": true,
+
"skipLibCheck": true,
+
"noFallthroughCasesInSwitch": true,
+
"noUncheckedIndexedAccess": true,
+
"noImplicitOverride": true,
+
// Some stricter flags (disabled by default)
+
"noUnusedLocals": false,
+
"noUnusedParameters": false,
+
"noPropertyAccessFromIndexSignature": false
+
}
}