+30
.env.example
+30
.env.example
···
+5
.gitignore
+5
.gitignore
+147
-1
README.md
+147
-1
README.md
···+Channel and user mappings are stored in a SQLite database (`bridge.db`). You can manage them through:+sqlite> INSERT INTO channel_mappings (slack_channel_id, irc_channel) VALUES ('C1234567890', '#general');+The bridge connects to `irc.hackclub.com:6667` (no TLS) and forwards messages bidirectionally based on channel mappings:+- **NickServ Authentication**: If `NICKSERV_PASSWORD` is configured, the bridge authenticates on connect+- **IRC โ Slack**: Messages from mapped IRC channels appear in their corresponding Slack channels+- **Slack โ IRC**: Messages from mapped Slack channels are sent to their corresponding IRC channels+- User display names: Uses name from Slack event if available, otherwise Cachet API (if `CACHET_ENABLED=true`), then Slack API fallback+- Thread messages are prefixed with `@xxxxx` (5-char thread ID) to show they're part of a thread+- **User mappings** allow custom IRC nicknames for specific Slack users and enable proper mentions both ways+- **Permissions**: Only channel creators, channel managers, or global admins can bridge/unbridge channelsIf you want to report an issue the main repo is [the tangled repo](https://tangled.org/dunkirk.sh/irc-slack-bridge) and the github is just a mirror.
+37
biome.json
+37
biome.json
···
+21
bun.lock
+21
bun.lock
······"@types/bun": ["@types/bun@1.3.3", "", { "dependencies": { "bun-types": "1.3.3" } }, "sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g=="],+"@types/irc": ["@types/irc@0.5.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-73npDB2rOidw5a30tEmbVZg28bzbfamOa1gK4h5h+6bdSrtVvegchmEKdmsBPTHStjQcCbNqlXS4rRbBUuIrJg=="],"@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],"bun-types": ["bun-types@1.3.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="],+"iconv": ["iconv@2.2.3", "", { "dependencies": { "nan": "^2.3.5" } }, "sha512-evIiYeKdt5nEGYKNkQcGPQy781sYgbBKi3gEkt1s4CwteCdOHSjGGRyyp6lP8inYFZwvzG3lgjXEvGUC8nqQ5A=="],+"irc": ["irc@0.5.2", "", { "dependencies": { "irc-colors": "^1.1.0" }, "optionalDependencies": { "iconv": "~2.2.1", "node-icu-charset-detector": "~0.2.0" } }, "sha512-KnrvkV05Y71SWmRWHtnlWEIH7LA/YeDul6l7tncCGLNEw4B6Obtmkatb3ACnSLj0kOJ6UBiuhss9e+eRG3zlxw=="],+"irc-colors": ["irc-colors@1.5.0", "", {}, "sha512-HtszKchBQTcqw1DC09uD7i7vvMayHGM1OCo6AHt5pkgZEyo99ClhHTMJdf+Ezc9ovuNNxcH89QfyclGthjZJOw=="],+"nan": ["nan@2.23.1", "", {}, "sha512-r7bBUGKzlqk8oPBDYxt6Z0aEdF1G1rwlMcLk8LCOMbOzf0mG+JUfUzG4fIMWwHWP0iyaLWEQZJmtB7nOHEm/qw=="],+"node-icu-charset-detector": ["node-icu-charset-detector@0.2.0", "", { "dependencies": { "nan": "^2.3.3" } }, "sha512-DYOFJ3NfKdxEi9hPbmoCss6WydGhJsxpSleUlZfAWEbZt3AU7JuxailgA9tnqQdsHiujfUY9VtDfWD9m0+ThtQ=="],+"slack-edge": ["slack-edge@1.3.12", "", { "dependencies": { "slack-web-api-client": "^1.1.7" } }, "sha512-9+He610rMeEeZawJY2UB4MGqQ4YwqOJXa+g5z0j26JCguFPv3MkByLiYsIf9fJMsCega4863RqzLCQ61AvCPAA=="],+"slack-web-api-client": ["slack-web-api-client@1.1.7", "", {}, "sha512-R36tRp8JcBTHXHMs60sNJTHbUrfj/+5X3ezSNbdoNXTdcRGPM8NZ6ANG3MeZEROxYEOm665Ya7QNfp/xmskQbw=="],"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
-1
index.ts
-1
index.ts
···
+21
-10
package.json
+21
-10
package.json
···
+59
slack-manifest.yaml
+59
slack-manifest.yaml
···
+96
src/commands.test.ts
+96
src/commands.test.ts
···
+528
src/commands.ts
+528
src/commands.ts
···+text: "โ You don't have permission to manage this channel. You must be the channel creator, a channel manager, or an admin.",+text: `โ IRC channel ${ircChannel} is already bridged to <#${existingIrcMapping.slack_channel_id}>`,+text: "โ You don't have permission to manage this channel. You must be the channel creator, a channel manager, or an admin.",+text: `โ IRC nick *${ircNick}* is already linked to <@${existingIrcMapping.slack_user_id}>`,
+460
src/index.ts
+460
src/index.ts
···+`๐ Server Started in ${Bun.nanoseconds() / 1000000} milliseconds on version: ${version}!\n\n----------------------------------\n`,
+44
src/lib/avatars.test.ts
+44
src/lib/avatars.test.ts
···
+19
src/lib/avatars.ts
+19
src/lib/avatars.ts
···+"https://hc-cdn.hel1.your-objectstorage.com/s/v3/4183627c4d26c56c915e104a8a7374f43acd1733_pfp__1_.png",+"https://hc-cdn.hel1.your-objectstorage.com/s/v3/389b1e6bd4248a7e5dd88e14c1adb8eb01267080_pfp__2_.png",+"https://hc-cdn.hel1.your-objectstorage.com/s/v3/03011a5e59548191de058f33ccd1d1cb1d64f2a0_pfp__3_.png",+"https://hc-cdn.hel1.your-objectstorage.com/s/v3/f9c57b88fbd4633114c1864bcc2968db555dbd2a_pfp__4_.png",+"https://hc-cdn.hel1.your-objectstorage.com/s/v3/e61a8cabee5a749588125242747b65122fb94205_pfp.png",
+21
src/lib/cachet.ts
+21
src/lib/cachet.ts
···
+21
src/lib/cdn.ts
+21
src/lib/cdn.ts
···
+160
src/lib/db.test.ts
+160
src/lib/db.test.ts
···
+255
src/lib/db.ts
+255
src/lib/db.ts
···+const hasIrcChannelUnique = channelSchema?.sql?.includes("irc_channel TEXT NOT NULL UNIQUE") ?? false;+"SELECT irc_channel, COUNT(*) as count FROM channel_mappings GROUP BY irc_channel HAVING count > 1",+"Warning: Found duplicate IRC channel mappings. Keeping only the most recent mapping for each IRC channel.",+"Warning: Found duplicate IRC nick mappings. Keeping only the most recent mapping for each IRC nick.",+"INSERT OR REPLACE INTO thread_timestamps (thread_ts, thread_id, slack_channel_id, last_message_time) VALUES (?, ?, ?, ?)",
+56
src/lib/mentions.test.ts
+56
src/lib/mentions.test.ts
···
+79
src/lib/mentions.ts
+79
src/lib/mentions.ts
···
+137
src/lib/parser.test.ts
+137
src/lib/parser.test.ts
···
+88
src/lib/parser.ts
+88
src/lib/parser.ts
···
+99
src/lib/permissions.ts
+99
src/lib/permissions.ts
···
+106
src/lib/threads.test.ts
+106
src/lib/threads.test.ts
···
+51
src/lib/threads.ts
+51
src/lib/threads.ts
···
+168
src/lib/user-cache.test.ts
+168
src/lib/user-cache.test.ts
···
+104
src/lib/user-cache.ts
+104
src/lib/user-cache.ts
···
+16
src/types.ts
+16
src/types.ts
···
+24
-24
tsconfig.json
+24
-24
tsconfig.json
···