this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

chore: format and ignore slack threads

+325 -315
+21 -21
package.json
··· 1 1 { 2 - "name": "irc-slack-bridge", 3 - "version": "0.0.1", 4 - "module": "src/index.ts", 5 - "type": "module", 6 - "private": true, 7 - "scripts": { 8 - "dev": "bun src/index.ts", 9 - "start": "bun src/index.ts", 10 - "ngrok": "ngrok http 3000 --domain casual-renewing-reptile.ngrok-free.app" 11 - }, 12 - "devDependencies": { 13 - "@types/bun": "latest", 14 - "@types/irc": "^0.5.4" 15 - }, 16 - "peerDependencies": { 17 - "typescript": "^5" 18 - }, 19 - "dependencies": { 20 - "irc": "^0.5.2", 21 - "slack-edge": "^1.3.12" 22 - } 2 + "name": "irc-slack-bridge", 3 + "version": "0.0.1", 4 + "module": "src/index.ts", 5 + "type": "module", 6 + "private": true, 7 + "scripts": { 8 + "dev": "bun src/index.ts", 9 + "start": "bun src/index.ts", 10 + "ngrok": "ngrok http 3000 --domain casual-renewing-reptile.ngrok-free.app" 11 + }, 12 + "devDependencies": { 13 + "@types/bun": "latest", 14 + "@types/irc": "^0.5.4" 15 + }, 16 + "peerDependencies": { 17 + "typescript": "^5" 18 + }, 19 + "dependencies": { 20 + "irc": "^0.5.2", 21 + "slack-edge": "^1.3.12" 22 + } 23 23 }
+118 -118
src/commands.ts
··· 2 2 import { slackApp, ircClient } from "./index"; 3 3 4 4 export function registerCommands() { 5 - // Link Slack channel to IRC channel 6 - slackApp.command("/irc-bridge-channel", async ({ payload, context }) => { 7 - const args = payload.text.trim().split(/\s+/); 8 - const ircChannel = args[0]; 5 + // Link Slack channel to IRC channel 6 + slackApp.command("/irc-bridge-channel", async ({ payload, context }) => { 7 + const args = payload.text.trim().split(/\s+/); 8 + const ircChannel = args[0]; 9 9 10 - if (!ircChannel || !ircChannel.startsWith("#")) { 11 - return { 12 - text: "Usage: `/irc-bridge-channel #irc-channel`\nExample: `/irc-bridge-channel #lounge`", 13 - }; 14 - } 10 + if (!ircChannel || !ircChannel.startsWith("#")) { 11 + return { 12 + text: "Usage: `/irc-bridge-channel #irc-channel`\nExample: `/irc-bridge-channel #lounge`", 13 + }; 14 + } 15 15 16 - const slackChannelId = payload.channel_id; 16 + const slackChannelId = payload.channel_id; 17 17 18 - try { 19 - // Create the mapping 20 - channelMappings.create(slackChannelId, ircChannel); 18 + try { 19 + // Create the mapping 20 + channelMappings.create(slackChannelId, ircChannel); 21 21 22 - // Join the IRC channel 23 - ircClient.join(ircChannel); 22 + // Join the IRC channel 23 + ircClient.join(ircChannel); 24 24 25 - // Join the Slack channel if not already in it 26 - await context.client.conversations.join({ 27 - channel: slackChannelId, 28 - }); 25 + // Join the Slack channel if not already in it 26 + await context.client.conversations.join({ 27 + channel: slackChannelId, 28 + }); 29 29 30 - return { 31 - text: `✅ Successfully bridged this channel to ${ircChannel}`, 32 - }; 33 - } catch (error) { 34 - console.error("Error creating channel mapping:", error); 35 - return { 36 - text: `❌ Failed to bridge channel: ${error}`, 37 - }; 38 - } 39 - }); 30 + return { 31 + text: `✅ Successfully bridged this channel to ${ircChannel}`, 32 + }; 33 + } catch (error) { 34 + console.error("Error creating channel mapping:", error); 35 + return { 36 + text: `❌ Failed to bridge channel: ${error}`, 37 + }; 38 + } 39 + }); 40 40 41 - // Unlink Slack channel from IRC 42 - slackApp.command("/irc-unbridge-channel", async ({ payload }) => { 43 - const slackChannelId = payload.channel_id; 41 + // Unlink Slack channel from IRC 42 + slackApp.command("/irc-unbridge-channel", async ({ payload }) => { 43 + const slackChannelId = payload.channel_id; 44 44 45 - try { 46 - const mapping = channelMappings.getBySlackChannel(slackChannelId); 47 - if (!mapping) { 48 - return { 49 - text: "❌ This channel is not bridged to IRC", 50 - }; 51 - } 45 + try { 46 + const mapping = channelMappings.getBySlackChannel(slackChannelId); 47 + if (!mapping) { 48 + return { 49 + text: "❌ This channel is not bridged to IRC", 50 + }; 51 + } 52 52 53 - channelMappings.delete(slackChannelId); 53 + channelMappings.delete(slackChannelId); 54 54 55 - return { 56 - text: `✅ Removed bridge to ${mapping.irc_channel}`, 57 - }; 58 - } catch (error) { 59 - console.error("Error removing channel mapping:", error); 60 - return { 61 - text: `❌ Failed to remove bridge: ${error}`, 62 - }; 63 - } 64 - }); 55 + return { 56 + text: `✅ Removed bridge to ${mapping.irc_channel}`, 57 + }; 58 + } catch (error) { 59 + console.error("Error removing channel mapping:", error); 60 + return { 61 + text: `❌ Failed to remove bridge: ${error}`, 62 + }; 63 + } 64 + }); 65 65 66 - // 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]; 66 + // 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]; 70 70 71 - if (!ircNick) { 72 - return { 73 - text: "Usage: `/irc-bridge-user <irc-nick>`\nExample: `/irc-bridge-user myircnick`", 74 - }; 75 - } 71 + if (!ircNick) { 72 + return { 73 + text: "Usage: `/irc-bridge-user <irc-nick>`\nExample: `/irc-bridge-user myircnick`", 74 + }; 75 + } 76 76 77 - const slackUserId = payload.user_id; 77 + const slackUserId = payload.user_id; 78 78 79 - try { 80 - userMappings.create(slackUserId, ircNick); 81 - console.log(`Created user mapping: ${slackUserId} -> ${ircNick}`); 79 + try { 80 + userMappings.create(slackUserId, ircNick); 81 + console.log(`Created user mapping: ${slackUserId} -> ${ircNick}`); 82 82 83 - return { 84 - text: `✅ Successfully linked your account to IRC nick: ${ircNick}`, 85 - }; 86 - } catch (error) { 87 - console.error("Error creating user mapping:", error); 88 - return { 89 - text: `❌ Failed to link user: ${error}`, 90 - }; 91 - } 92 - }); 83 + return { 84 + text: `✅ Successfully linked your account to IRC nick: ${ircNick}`, 85 + }; 86 + } catch (error) { 87 + console.error("Error creating user mapping:", error); 88 + return { 89 + text: `❌ Failed to link user: ${error}`, 90 + }; 91 + } 92 + }); 93 93 94 - // Unlink Slack user from IRC 95 - slackApp.command("/irc-unbridge-user", async ({ payload }) => { 96 - const slackUserId = payload.user_id; 94 + // Unlink Slack user from IRC 95 + slackApp.command("/irc-unbridge-user", async ({ payload }) => { 96 + const slackUserId = payload.user_id; 97 97 98 - try { 99 - const mapping = userMappings.getBySlackUser(slackUserId); 100 - if (!mapping) { 101 - return { 102 - text: "❌ You don't have an IRC nick mapping", 103 - }; 104 - } 98 + try { 99 + const mapping = userMappings.getBySlackUser(slackUserId); 100 + if (!mapping) { 101 + return { 102 + text: "❌ You don't have an IRC nick mapping", 103 + }; 104 + } 105 105 106 - userMappings.delete(slackUserId); 106 + userMappings.delete(slackUserId); 107 107 108 - return { 109 - text: `✅ Removed link to IRC nick: ${mapping.irc_nick}`, 110 - }; 111 - } catch (error) { 112 - console.error("Error removing user mapping:", error); 113 - return { 114 - text: `❌ Failed to remove link: ${error}`, 115 - }; 116 - } 117 - }); 108 + return { 109 + text: `✅ Removed link to IRC nick: ${mapping.irc_nick}`, 110 + }; 111 + } catch (error) { 112 + console.error("Error removing user mapping:", error); 113 + return { 114 + text: `❌ Failed to remove link: ${error}`, 115 + }; 116 + } 117 + }); 118 118 119 - // List channel mappings 120 - slackApp.command("/irc-bridge-list", async ({ payload }) => { 121 - const channelMaps = channelMappings.getAll(); 122 - const userMaps = userMappings.getAll(); 119 + // List channel mappings 120 + slackApp.command("/irc-bridge-list", async ({ payload }) => { 121 + const channelMaps = channelMappings.getAll(); 122 + const userMaps = userMappings.getAll(); 123 123 124 - let text = "*Channel Bridges:*\n"; 125 - if (channelMaps.length === 0) { 126 - text += "None\n"; 127 - } else { 128 - for (const map of channelMaps) { 129 - text += `• <#${map.slack_channel_id}> ↔️ ${map.irc_channel}\n`; 130 - } 131 - } 124 + let text = "*Channel Bridges:*\n"; 125 + if (channelMaps.length === 0) { 126 + text += "None\n"; 127 + } else { 128 + for (const map of channelMaps) { 129 + text += `• <#${map.slack_channel_id}> ↔️ ${map.irc_channel}\n`; 130 + } 131 + } 132 132 133 - text += "\n*User Mappings:*\n"; 134 - if (userMaps.length === 0) { 135 - text += "None\n"; 136 - } else { 137 - for (const map of userMaps) { 138 - text += `• <@${map.slack_user_id}> ↔️ ${map.irc_nick}\n`; 139 - } 140 - } 133 + text += "\n*User Mappings:*\n"; 134 + if (userMaps.length === 0) { 135 + text += "None\n"; 136 + } else { 137 + for (const map of userMaps) { 138 + text += `• <@${map.slack_user_id}> ↔️ ${map.irc_nick}\n`; 139 + } 140 + } 141 141 142 - return { 143 - text, 144 - }; 145 - }); 142 + return { 143 + text, 144 + }; 145 + }); 146 146 }
+17 -7
src/db.ts
··· 40 40 }, 41 41 42 42 getBySlackChannel(slackChannelId: string): ChannelMapping | null { 43 - return db.query("SELECT * FROM channel_mappings WHERE slack_channel_id = ?").get(slackChannelId) as ChannelMapping | null; 43 + return db 44 + .query("SELECT * FROM channel_mappings WHERE slack_channel_id = ?") 45 + .get(slackChannelId) as ChannelMapping | null; 44 46 }, 45 47 46 48 getByIrcChannel(ircChannel: string): ChannelMapping | null { 47 - return db.query("SELECT * FROM channel_mappings WHERE irc_channel = ?").get(ircChannel) as ChannelMapping | null; 49 + return db 50 + .query("SELECT * FROM channel_mappings WHERE irc_channel = ?") 51 + .get(ircChannel) as ChannelMapping | null; 48 52 }, 49 53 50 54 create(slackChannelId: string, ircChannel: string): void { 51 55 db.run( 52 56 "INSERT OR REPLACE INTO channel_mappings (slack_channel_id, irc_channel) VALUES (?, ?)", 53 - [slackChannelId, ircChannel] 57 + [slackChannelId, ircChannel], 54 58 ); 55 59 }, 56 60 57 61 delete(slackChannelId: string): void { 58 - db.run("DELETE FROM channel_mappings WHERE slack_channel_id = ?", [slackChannelId]); 62 + db.run("DELETE FROM channel_mappings WHERE slack_channel_id = ?", [ 63 + slackChannelId, 64 + ]); 59 65 }, 60 66 }; 61 67 ··· 65 71 }, 66 72 67 73 getBySlackUser(slackUserId: string): UserMapping | null { 68 - return db.query("SELECT * FROM user_mappings WHERE slack_user_id = ?").get(slackUserId) as UserMapping | null; 74 + return db 75 + .query("SELECT * FROM user_mappings WHERE slack_user_id = ?") 76 + .get(slackUserId) as UserMapping | null; 69 77 }, 70 78 71 79 getByIrcNick(ircNick: string): UserMapping | null { 72 - return db.query("SELECT * FROM user_mappings WHERE irc_nick = ?").get(ircNick) as UserMapping | null; 80 + return db 81 + .query("SELECT * FROM user_mappings WHERE irc_nick = ?") 82 + .get(ircNick) as UserMapping | null; 73 83 }, 74 84 75 85 create(slackUserId: string, ircNick: string): void { 76 86 db.run( 77 87 "INSERT OR REPLACE INTO user_mappings (slack_user_id, irc_nick) VALUES (?, ?)", 78 - [slackUserId, ircNick] 88 + [slackUserId, ircNick], 79 89 ); 80 90 }, 81 91
+145 -144
src/index.ts
··· 9 9 const missingEnvVars = []; 10 10 if (!process.env.SLACK_BOT_TOKEN) missingEnvVars.push("SLACK_BOT_TOKEN"); 11 11 if (!process.env.SLACK_SIGNING_SECRET) 12 - missingEnvVars.push("SLACK_SIGNING_SECRET"); 12 + missingEnvVars.push("SLACK_SIGNING_SECRET"); 13 13 if (!process.env.ADMINS) missingEnvVars.push("ADMINS"); 14 14 if (!process.env.IRC_NICK) missingEnvVars.push("IRC_NICK"); 15 15 16 16 if (missingEnvVars.length > 0) { 17 - throw new Error( 18 - `Missing required environment variables: ${missingEnvVars.join(", ")}`, 19 - ); 17 + throw new Error( 18 + `Missing required environment variables: ${missingEnvVars.join(", ")}`, 19 + ); 20 20 } 21 21 22 22 const slackApp = new SlackApp({ 23 - env: { 24 - SLACK_BOT_TOKEN: process.env.SLACK_BOT_TOKEN as string, 25 - SLACK_SIGNING_SECRET: process.env.SLACK_SIGNING_SECRET as string, 26 - SLACK_LOGGING_LEVEL: "INFO", 27 - }, 28 - startLazyListenerAfterAck: true, 23 + env: { 24 + SLACK_BOT_TOKEN: process.env.SLACK_BOT_TOKEN as string, 25 + SLACK_SIGNING_SECRET: process.env.SLACK_SIGNING_SECRET as string, 26 + SLACK_LOGGING_LEVEL: "INFO", 27 + }, 28 + startLazyListenerAfterAck: true, 29 29 }); 30 30 const slackClient = slackApp.client; 31 31 32 32 // Get bot user ID 33 33 let botUserId: string | undefined; 34 34 slackClient.auth 35 - .test({ 36 - token: process.env.SLACK_BOT_TOKEN, 37 - }) 38 - .then((result) => { 39 - botUserId = result.user_id; 40 - console.log(`Bot user ID: ${botUserId}`); 41 - }); 35 + .test({ 36 + token: process.env.SLACK_BOT_TOKEN, 37 + }) 38 + .then((result) => { 39 + botUserId = result.user_id; 40 + console.log(`Bot user ID: ${botUserId}`); 41 + }); 42 42 43 43 // IRC client setup 44 44 const ircClient = new irc.Client( 45 - "irc.hackclub.com", 46 - process.env.IRC_NICK || "slackbridge", 47 - { 48 - port: 6667, 49 - autoRejoin: true, 50 - autoConnect: true, 51 - channels: [], 52 - secure: false, 53 - userName: process.env.IRC_NICK, 54 - realName: "Slack IRC Bridge", 55 - }, 45 + "irc.hackclub.com", 46 + process.env.IRC_NICK || "slackbridge", 47 + { 48 + port: 6667, 49 + autoRejoin: true, 50 + autoConnect: true, 51 + channels: [], 52 + secure: false, 53 + userName: process.env.IRC_NICK, 54 + realName: "Slack IRC Bridge", 55 + }, 56 56 ); 57 57 58 58 // Clean up IRC connection on hot reload or exit 59 59 process.on("beforeExit", () => { 60 - ircClient.disconnect("Reloading", () => { 61 - console.log("IRC client disconnected"); 62 - }); 60 + ircClient.disconnect("Reloading", () => { 61 + console.log("IRC client disconnected"); 62 + }); 63 63 }); 64 64 65 65 // Register slash commands ··· 67 67 68 68 // Join all mapped IRC channels on connect 69 69 ircClient.addListener("registered", async () => { 70 - console.log("Connected to IRC server"); 71 - const mappings = channelMappings.getAll(); 72 - for (const mapping of mappings) { 73 - ircClient.join(mapping.irc_channel); 74 - } 70 + console.log("Connected to IRC server"); 71 + const mappings = channelMappings.getAll(); 72 + for (const mapping of mappings) { 73 + ircClient.join(mapping.irc_channel); 74 + } 75 75 }); 76 76 77 77 ircClient.addListener("join", (channel: string, nick: string) => { 78 - if (nick === process.env.IRC_NICK) { 79 - console.log(`Joined IRC channel: ${channel}`); 80 - } 78 + if (nick === process.env.IRC_NICK) { 79 + console.log(`Joined IRC channel: ${channel}`); 80 + } 81 81 }); 82 82 83 83 ircClient.addListener( 84 - "message", 85 - async (nick: string, to: string, text: string) => { 86 - // Ignore messages from our own bot (with or without numbers suffix) 87 - const botNickPattern = new RegExp(`^${process.env.IRC_NICK}\\d*$`); 88 - if (botNickPattern.test(nick)) return; 89 - if (nick === "****") return; 84 + "message", 85 + async (nick: string, to: string, text: string) => { 86 + // Ignore messages from our own bot (with or without numbers suffix) 87 + const botNickPattern = new RegExp(`^${process.env.IRC_NICK}\\d*$`); 88 + if (botNickPattern.test(nick)) return; 89 + if (nick === "****") return; 90 90 91 - // Find Slack channel mapping for this IRC channel 92 - const mapping = channelMappings.getByIrcChannel(to); 93 - if (!mapping) return; 91 + // Find Slack channel mapping for this IRC channel 92 + const mapping = channelMappings.getByIrcChannel(to); 93 + if (!mapping) return; 94 94 95 - // Check if this IRC nick is mapped to a Slack user 96 - const userMapping = userMappings.getByIrcNick(nick); 95 + // Check if this IRC nick is mapped to a Slack user 96 + const userMapping = userMappings.getByIrcNick(nick); 97 97 98 - const displayName = `${nick} <irc>`; 99 - let iconUrl: string | undefined; 98 + const displayName = `${nick} <irc>`; 99 + let iconUrl: string | undefined; 100 100 101 - if (userMapping) { 102 - try { 103 - iconUrl = `https://cachet.dunkirk.sh/users/${userMapping.slack_user_id}/r`; 104 - } catch (error) { 105 - console.error("Error fetching user info:", error); 106 - } 107 - } 101 + if (userMapping) { 102 + try { 103 + iconUrl = `https://cachet.dunkirk.sh/users/${userMapping.slack_user_id}/r`; 104 + } catch (error) { 105 + console.error("Error fetching user info:", error); 106 + } 107 + } 108 108 109 - try { 110 - await slackClient.chat.postMessage({ 111 - token: process.env.SLACK_BOT_TOKEN, 112 - channel: mapping.slack_channel_id, 113 - text: parseIRCFormatting(text), 114 - username: displayName, 115 - icon_url: iconUrl, 116 - unfurl_links: false, 117 - unfurl_media: false, 118 - }); 119 - console.log(`IRC → Slack: <${nick}> ${text}`); 120 - } catch (error) { 121 - console.error("Error posting to Slack:", error); 122 - } 123 - }, 109 + try { 110 + await slackClient.chat.postMessage({ 111 + token: process.env.SLACK_BOT_TOKEN, 112 + channel: mapping.slack_channel_id, 113 + text: parseIRCFormatting(text), 114 + username: displayName, 115 + icon_url: iconUrl, 116 + unfurl_links: false, 117 + unfurl_media: false, 118 + }); 119 + console.log(`IRC → Slack: <${nick}> ${text}`); 120 + } catch (error) { 121 + console.error("Error posting to Slack:", error); 122 + } 123 + }, 124 124 ); 125 125 126 126 ircClient.addListener("error", (error: string) => { 127 - console.error("IRC error:", error); 127 + console.error("IRC error:", error); 128 128 }); 129 129 130 130 // Slack event handlers 131 131 slackApp.event("message", async ({ payload }) => { 132 - if (payload.subtype) return; 133 - if (payload.bot_id) return; 134 - if (payload.user === botUserId) return; 132 + if (payload.subtype) return; 133 + if (payload.bot_id) return; 134 + if (payload.user === botUserId) return; 135 + if (payload.thread_ts) return; 135 136 136 - // Find IRC channel mapping for this Slack channel 137 - const mapping = channelMappings.getBySlackChannel(payload.channel); 138 - if (!mapping) { 139 - console.log( 140 - `No IRC channel mapping found for Slack channel ${payload.channel}`, 141 - ); 142 - slackClient.conversations.leave({ 143 - channel: payload.channel, 144 - }); 145 - return; 146 - } 137 + // Find IRC channel mapping for this Slack channel 138 + const mapping = channelMappings.getBySlackChannel(payload.channel); 139 + if (!mapping) { 140 + console.log( 141 + `No IRC channel mapping found for Slack channel ${payload.channel}`, 142 + ); 143 + slackClient.conversations.leave({ 144 + channel: payload.channel, 145 + }); 146 + return; 147 + } 147 148 148 - try { 149 - const userInfo = await slackClient.users.info({ 150 - token: process.env.SLACK_BOT_TOKEN, 151 - user: payload.user, 152 - }); 149 + try { 150 + const userInfo = await slackClient.users.info({ 151 + token: process.env.SLACK_BOT_TOKEN, 152 + user: payload.user, 153 + }); 153 154 154 - // Check for user mapping, otherwise use Slack name 155 - const userMapping = userMappings.getBySlackUser(payload.user); 156 - const username = 157 - userMapping?.irc_nick || 158 - userInfo.user?.real_name || 159 - userInfo.user?.name || 160 - "Unknown"; 155 + // Check for user mapping, otherwise use Slack name 156 + const userMapping = userMappings.getBySlackUser(payload.user); 157 + const username = 158 + userMapping?.irc_nick || 159 + userInfo.user?.real_name || 160 + userInfo.user?.name || 161 + "Unknown"; 161 162 162 - // Parse Slack mentions and replace with display names 163 - let messageText = payload.text; 164 - const mentionRegex = /<@(U[A-Z0-9]+)>/g; 165 - const mentions = Array.from(messageText.matchAll(mentionRegex)); 163 + // Parse Slack mentions and replace with display names 164 + let messageText = payload.text; 165 + const mentionRegex = /<@(U[A-Z0-9]+)>/g; 166 + const mentions = Array.from(messageText.matchAll(mentionRegex)); 166 167 167 - for (const match of mentions) { 168 - const userId = match[1]; 169 - try { 170 - const response = await fetch( 171 - `https://cachet.dunkirk.sh/users/${userId}`, 172 - ); 173 - if (response.ok) { 174 - const data = (await response.json()) as CachetUser; 175 - messageText = messageText.replace(match[0], `@${data.displayName}`); 176 - } 177 - } catch (error) { 178 - console.error(`Error fetching user ${userId} from cachet:`, error); 179 - } 180 - } 168 + for (const match of mentions) { 169 + const userId = match[1]; 170 + try { 171 + const response = await fetch( 172 + `https://cachet.dunkirk.sh/users/${userId}`, 173 + ); 174 + if (response.ok) { 175 + const data = (await response.json()) as CachetUser; 176 + messageText = messageText.replace(match[0], `@${data.displayName}`); 177 + } 178 + } catch (error) { 179 + console.error(`Error fetching user ${userId} from cachet:`, error); 180 + } 181 + } 181 182 182 - // Parse Slack markdown formatting 183 - messageText = parseSlackMarkdown(messageText); 183 + // Parse Slack markdown formatting 184 + messageText = parseSlackMarkdown(messageText); 184 185 185 - const message = `<${username}> ${messageText}`; 186 + const message = `<${username}> ${messageText}`; 186 187 187 - ircClient.say(mapping.irc_channel, message); 188 - console.log(`Slack → IRC: ${message}`); 189 - } catch (error) { 190 - console.error("Error handling Slack message:", error); 191 - } 188 + ircClient.say(mapping.irc_channel, message); 189 + console.log(`Slack → IRC: ${message}`); 190 + } catch (error) { 191 + console.error("Error handling Slack message:", error); 192 + } 192 193 }); 193 194 194 195 export default { 195 - port: process.env.PORT || 3000, 196 - async fetch(request: Request) { 197 - const url = new URL(request.url); 198 - const path = url.pathname; 196 + port: process.env.PORT || 3000, 197 + async fetch(request: Request) { 198 + const url = new URL(request.url); 199 + const path = url.pathname; 199 200 200 - switch (path) { 201 - case "/": 202 - return new Response(`Hello World from irc-slack-bridge@${version}`); 203 - case "/health": 204 - return new Response("OK"); 205 - case "/slack": 206 - return slackApp.run(request); 207 - default: 208 - return new Response("404 Not Found", { status: 404 }); 209 - } 210 - }, 201 + switch (path) { 202 + case "/": 203 + return new Response(`Hello World from irc-slack-bridge@${version}`); 204 + case "/health": 205 + return new Response("OK"); 206 + case "/slack": 207 + return slackApp.run(request); 208 + default: 209 + return new Response("404 Not Found", { status: 404 }); 210 + } 211 + }, 211 212 }; 212 213 213 214 console.log( 214 - `🚀 Server Started in ${Bun.nanoseconds() / 1000000} milliseconds on version: ${version}!\n\n----------------------------------\n`, 215 + `🚀 Server Started in ${Bun.nanoseconds() / 1000000} milliseconds on version: ${version}!\n\n----------------------------------\n`, 215 216 ); 216 217 console.log( 217 - `Connecting to IRC: irc.hackclub.com:6667 as ${process.env.IRC_NICK}`, 218 + `Connecting to IRC: irc.hackclub.com:6667 as ${process.env.IRC_NICK}`, 218 219 ); 219 220 console.log(`Channel mappings: ${channelMappings.getAll().length}`); 220 221 console.log(`User mappings: ${userMappings.getAll().length}`);
-1
src/parser.ts
··· 86 86 87 87 return parsed; 88 88 } 89 -
+24 -24
tsconfig.json
··· 1 1 { 2 - "compilerOptions": { 3 - // Environment setup & latest features 4 - "lib": ["ESNext"], 5 - "target": "ESNext", 6 - "module": "Preserve", 7 - "moduleDetection": "force", 8 - "jsx": "react-jsx", 9 - "allowJs": true, 2 + "compilerOptions": { 3 + // Environment setup & latest features 4 + "lib": ["ESNext"], 5 + "target": "ESNext", 6 + "module": "Preserve", 7 + "moduleDetection": "force", 8 + "jsx": "react-jsx", 9 + "allowJs": true, 10 10 11 - // Bundler mode 12 - "moduleResolution": "bundler", 13 - "allowImportingTsExtensions": true, 14 - "verbatimModuleSyntax": true, 15 - "noEmit": true, 11 + // Bundler mode 12 + "moduleResolution": "bundler", 13 + "allowImportingTsExtensions": true, 14 + "verbatimModuleSyntax": true, 15 + "noEmit": true, 16 16 17 - // Best practices 18 - "strict": true, 19 - "skipLibCheck": true, 20 - "noFallthroughCasesInSwitch": true, 21 - "noUncheckedIndexedAccess": true, 22 - "noImplicitOverride": true, 17 + // Best practices 18 + "strict": true, 19 + "skipLibCheck": true, 20 + "noFallthroughCasesInSwitch": true, 21 + "noUncheckedIndexedAccess": true, 22 + "noImplicitOverride": true, 23 23 24 - // Some stricter flags (disabled by default) 25 - "noUnusedLocals": false, 26 - "noUnusedParameters": false, 27 - "noPropertyAccessFromIndexSignature": false 28 - } 24 + // Some stricter flags (disabled by default) 25 + "noUnusedLocals": false, 26 + "noUnusedParameters": false, 27 + "noPropertyAccessFromIndexSignature": false 28 + } 29 29 }