this repo has no description
1
fork

Configure Feed

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

feat: add nick serv support

+58 -4
+2
.env.example
··· 11 11 12 12 # IRC Configuration 13 13 IRC_NICK=slackbridge 14 + NICKSERV_PASSWORD=your-nickserv-password-here 15 + NICKSERV_EMAIL=your-email@example.com 14 16 15 17 # Admin users (comma-separated Slack user IDs) 16 18 ADMINS=U1234567890,U0987654321
+7 -1
README.md
··· 40 40 41 41 # IRC Configuration 42 42 IRC_NICK=slackbridge 43 + NICKSERV_PASSWORD=your-nickserv-password-here 44 + NICKSERV_EMAIL=your-email@example.com 43 45 44 46 # Admin users (comma-separated Slack user IDs) 45 47 ADMINS=U1234567890,U0987654321 ··· 90 92 91 93 The bridge connects to `irc.hackclub.com:6667` (no TLS) and forwards messages bidirectionally based on channel mappings: 92 94 95 + - **NickServ Authentication**: If `NICKSERV_PASSWORD` is configured, the bridge authenticates on connect 96 + - Waits for NickServ confirmation before joining channels 97 + - Auto-registers the nick if not registered (requires `NICKSERV_EMAIL`) 98 + - Prevents "No external channel messages" errors by ensuring proper authentication 93 99 - **IRC → Slack**: Messages from mapped IRC channels appear in their corresponding Slack channels 94 100 - Image URLs are automatically displayed as inline attachments 95 101 - IRC mentions (`@nick` or `nick:`) are converted to Slack mentions for mapped users 96 102 - IRC formatting codes are converted to Slack markdown 97 103 - **Slack → IRC**: Messages from mapped Slack channels are sent to their corresponding IRC channels 98 - - Slack mentions are converted to `@displayName` format using Cachet 104 + - Slack mentions are converted to mapped IRC nicks, or the display name from `<@U123|name>` format 99 105 - Slack markdown is converted to IRC formatting codes 100 106 - File attachments are uploaded to Hack Club CDN and URLs are shared 101 107 - **User mappings** allow custom IRC nicknames for specific Slack users and enable proper mentions both ways
+49 -3
src/index.ts
··· 84 84 // Register slash commands 85 85 registerCommands(); 86 86 87 + // Track NickServ authentication state 88 + let nickServAuthAttempted = false; 89 + let isAuthenticated = false; 90 + 87 91 // Join all mapped IRC channels on connect 88 92 ircClient.addListener("registered", async () => { 89 93 console.log("Connected to IRC server"); 90 - const mappings = channelMappings.getAll(); 91 - for (const mapping of mappings) { 92 - ircClient.join(mapping.irc_channel); 94 + 95 + // Authenticate with NickServ if password is provided 96 + if (process.env.NICKSERV_PASSWORD && !nickServAuthAttempted) { 97 + nickServAuthAttempted = true; 98 + console.log("Authenticating with NickServ..."); 99 + ircClient.say("NickServ", `IDENTIFY ${process.env.NICKSERV_PASSWORD}`); 100 + // Don't join channels yet - wait for NickServ response 101 + } else if (!process.env.NICKSERV_PASSWORD) { 102 + // No auth needed, join immediately 103 + const mappings = channelMappings.getAll(); 104 + for (const mapping of mappings) { 105 + ircClient.join(mapping.irc_channel); 106 + } 93 107 } 94 108 }); 95 109 96 110 ircClient.addListener("join", (channel: string, nick: string) => { 97 111 if (nick === process.env.IRC_NICK) { 98 112 console.log(`Joined IRC channel: ${channel}`); 113 + } 114 + }); 115 + 116 + // Handle NickServ notices 117 + ircClient.addListener("notice", async (nick: string, to: string, text: string) => { 118 + if (nick !== "NickServ") return; 119 + 120 + console.log(`NickServ: ${text}`); 121 + 122 + // Check for successful authentication 123 + if (text.includes("You are now identified") || text.includes("Password accepted")) { 124 + console.log("✓ Successfully authenticated with NickServ"); 125 + isAuthenticated = true; 126 + 127 + // Join channels after successful auth 128 + const mappings = channelMappings.getAll(); 129 + for (const mapping of mappings) { 130 + ircClient.join(mapping.irc_channel); 131 + } 132 + } 133 + // Check if nick is not registered 134 + else if (text.includes("isn't registered") || text.includes("not registered")) { 135 + console.log("Nick not registered, registering with NickServ..."); 136 + if (process.env.NICKSERV_PASSWORD && process.env.NICKSERV_EMAIL) { 137 + ircClient.say("NickServ", `REGISTER ${process.env.NICKSERV_PASSWORD} ${process.env.NICKSERV_EMAIL}`); 138 + } else { 139 + console.error("Cannot register: NICKSERV_EMAIL not configured"); 140 + } 141 + } 142 + // Check for failed authentication 143 + else if (text.includes("Invalid password") || text.includes("Access denied")) { 144 + console.error("✗ NickServ authentication failed: Invalid password"); 99 145 } 100 146 }); 101 147