this repo has no description
1import { SlackApp } from "slack-edge"; 2import { version } from "./package.json"; 3import * as irc from "irc-framework"; 4 5const missingEnvVars = []; 6if (!process.env.SLACK_BOT_TOKEN) missingEnvVars.push("SLACK_BOT_TOKEN"); 7if (!process.env.SLACK_SIGNING_SECRET) missingEnvVars.push("SLACK_SIGNING_SECRET"); 8if (!process.env.ADMINS) missingEnvVars.push("ADMINS"); 9if (!process.env.IRC_NICK) missingEnvVars.push("IRC_NICK"); 10if (!process.env.IRC_CHANNEL) missingEnvVars.push("IRC_CHANNEL"); 11 12if (missingEnvVars.length > 0) { 13 throw new Error( 14 `Missing required environment variables: ${missingEnvVars.join(", ")}`, 15 ); 16} 17 18const slackApp = new SlackApp({ 19 env: { 20 SLACK_BOT_TOKEN: process.env.SLACK_BOT_TOKEN, 21 SLACK_SIGNING_SECRET: process.env.SLACK_SIGNING_SECRET, 22 SLACK_LOGGING_LEVEL: "INFO", 23 }, 24 startLazyListenerAfterAck: true, 25}); 26const slackClient = slackApp.client; 27 28// IRC client setup 29const ircClient = new irc.Client(); 30ircClient.connect({ 31 host: "irc.hackclub.com", 32 port: 6667, 33 tls: false, 34 nick: process.env.IRC_NICK, 35 username: process.env.IRC_NICK, 36 gecos: "Slack IRC Bridge", 37 auto_reconnect: true, 38 auto_reconnect_wait: 4000, 39 auto_reconnect_max_retries: 0, 40}); 41 42const ircChannel = process.env.IRC_CHANNEL; 43const slackChannel = process.env.SLACK_CHANNEL; 44 45// IRC event handlers 46ircClient.on("registered", () => { 47 console.log("Connected to IRC server"); 48 ircClient.join(ircChannel); 49}); 50 51ircClient.on("join", (event) => { 52 if (event.nick === ircClient.user.nick) { 53 console.log(`Joined IRC channel: ${event.channel}`); 54 } 55}); 56 57ircClient.on("message", async (event) => { 58 if (event.nick === ircClient.user.nick) return; 59 if (event.nick === "****") return; 60 61 if (slackChannel) { 62 try { 63 await slackClient.chat.postMessage({ 64 token: process.env.SLACK_BOT_TOKEN, 65 channel: slackChannel, 66 text: event.message, 67 username: event.nick, 68 unfurl_links: false, 69 unfurl_media: false, 70 }); 71 } catch (error) { 72 console.error("Error posting to Slack:", error); 73 } 74 } 75}); 76 77ircClient.on("close", () => { 78 console.log("Disconnected from IRC server"); 79}); 80 81ircClient.on("error", (error) => { 82 console.error("IRC error:", error); 83}); 84 85// Slack event handlers 86slackApp.event("message", async ({ payload }) => { 87 if (payload.subtype) return; 88 if (payload.bot_id) return; 89 if (!slackChannel || payload.channel !== slackChannel) return; 90 91 try { 92 const userInfo = await slackClient.users.info({ 93 token: process.env.SLACK_BOT_TOKEN, 94 user: payload.user, 95 }); 96 97 const username = userInfo.user?.real_name || userInfo.user?.name || "Unknown"; 98 const message = `<${username}> ${payload.text}`; 99 100 ircClient.say(ircChannel, message); 101 } catch (error) { 102 console.error("Error handling Slack message:", error); 103 } 104}); 105 106export default { 107 port: process.env.PORT || 3000, 108 async fetch(request: Request) { 109 const url = new URL(request.url); 110 const path = url.pathname; 111 112 switch (path) { 113 case "/": 114 return new Response(`Hello World from irc-slack-bridge@${version}`); 115 case "/health": 116 return new Response("OK"); 117 case "/slack": 118 return slackApp.run(request); 119 default: 120 return new Response("404 Not Found", { status: 404 }); 121 } 122 }, 123}; 124 125console.log( 126 `🚀 Server Started in ${Bun.nanoseconds() / 1000000} milliseconds on version: ${version}!\n\n----------------------------------\n`, 127); 128console.log(`Connecting to IRC: irc.hackclub.com:6667 as ${process.env.IRC_NICK}`); 129console.log(`IRC Channel: ${ircChannel}`); 130console.log(`Slack Channel: ${slackChannel || "Not configured (IRC->Slack only)"}`); 131 132export { slackApp, slackClient, ircClient, version }; 133