From 20060d11308408d63d9c2471ec961e4f5d770319 Mon Sep 17 00:00:00 2001 From: ~purplebored Date: Sun, 28 Sep 2025 13:53:56 +0200 Subject: [PATCH] add: Bump up the version and add RELLAYMSG for IRC. --- README.md | 10 +-- bot.js | 148 ++++++++++++++++++++++++++++++-------------- example.config.yaml | 4 ++ package-lock.json | 10 +-- package.json | 2 +- 5 files changed, 118 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 8930ef4..72d7fad 100644 --- a/README.md +++ b/README.md @@ -9,24 +9,24 @@ A crappy group chat to a IRC room bridge written in node - logDebug(`Connecting to ${ircConfig.server}:${ircConfig.port} ...`) + logDebug(`Connecting to ${ircConfig.server}:${ircConfig.port} ...`) ); client.on("connected", () => - logDebug(`TCP connection established to ${ircConfig.server}`) + logDebug(`TCP connection established to ${ircConfig.server}`) ); client.on("registered", () => { console.log( `Connected to IRC ${ircConfig.server} as ${ircConfig.nick}, joining ${ircConfig.channel}` ); client.join(ircConfig.channel, () => - logDebug(`Sent JOIN for ${ircConfig.channel}`) + logDebug(`Sent JOIN for ${ircConfig.channel}`) ); }); - client.on("join", (event) => - logDebug(`Joined ${event.channel} as ${event.nick}`) - ); + + client.on("names", (event) => { + const myNick = ircConfig.nick; + const modes = event.users[myNick]; + if (Array.isArray(modes) && modes.includes("@")) { + client.state.hasOp = true; + logDebug(`${myNick} detected as +o from NAMES list`); + } + }); + + client.on("mode", (event) => { + if (event.target === ircConfig.channel) { + for (const m of event.modes) { + if (m.mode === "+o" && m.param === ircConfig.nick) { + client.state.hasOp = true; + logDebug(`${ircConfig.nick} gained +o (channel operator)`); + } else if (m.mode === "-o" && m.param === ircConfig.nick) { + client.state.hasOp = false; + logDebug(`${ircConfig.nick} lost +o (channel operator)`); + } + } + } + }); + client.on("error", (event) => - console.error(`IRC error on ${ircConfig.server}:`, event) + console.error(`IRC error on ${ircConfig.server}:`, event) ); client.on("socket close", () => - logDebug(`Socket closed for ${ircConfig.server}`) + logDebug(`Socket closed for ${ircConfig.server}`) ); client.on("socket error", (err) => - console.error(`Socket error on ${ircConfig.server}:`, err) + console.error(`Socket error on ${ircConfig.server}:`, err) ); - + // Handle IRC → Discord client.on("message", (event) => { - if (event.nick === ircConfig.nick) return; // Skip self + if (event.nick === ircConfig.nick || event.nick.endsWith("/dc")) return; + const ircMessage = `<${event.nick}> ${event.message}`; const discordChannel = discordClient.channels.cache.get(discordChannelId); if (discordChannel) discordChannel.send(ircMessage).catch(console.error); }); - client.on("relaymsg", (event) => { - const discordChannel = discordClient.channels.cache.get(discordChannelId); - if (discordChannel) - discordChannel - .send(`[relay ${event.nick}] ${event.message}`) - .catch(console.error); - }); + client.on("relaymsg", (event) => { + const discordChannel = discordClient.channels.cache.get(discordChannelId); + if (discordChannel) + discordChannel.send(`<${event.nick}> ${event.message}`).catch(console.error); + }); - if (DEBUG) { - client.on("raw", (event) => console.log("RAW:", event.line)); - } + if (DEBUG) { + client.on("raw", (event) => console.log("RAW:", event.line)); + } - return { client, channel: ircConfig.channel, nick: ircConfig.nick, discordChannelId }; + return { + client, + channel: ircConfig.channel, + nick: ircConfig.nick, + discordChannelId, + useRelayMsg, + }; } // Initialize IRC clients for (const bridge of bridges) { - const { client, channel, nick, discordChannelId } = createIRCClient(bridge); - ircClients.set(client, { channel, nick, discordChannelId }); + const { client, channel, nick, discordChannelId, useRelayMsg } = + createIRCClient(bridge); + ircClients.set(client, { channel, nick, discordChannelId, useRelayMsg }); } // Discord ready discordClient.once("ready", () => -console.log(`Logged in as ${discordClient.user.tag}`) + console.log(`Logged in as ${discordClient.user.tag}`) ); // Forward Discord messages → IRC @@ -145,16 +179,14 @@ discordClient.on("messageCreate", async (message) => { const referencedMessage = await message.channel.messages.fetch( message.reference.messageId ); - if (referencedMessage.content) { let refAuthor = referencedMessage.author.username; if (referencedMessage.guild) { const member = await referencedMessage.guild.members - .fetch(referencedMessage.author.id) - .catch(() => null); + .fetch(referencedMessage.author.id) + .catch(() => null); if (member) refAuthor = member.displayName; } - const originalText = referencedMessage.content.replace(/\n/g, " "); quote = `<${refAuthor}> said: ${originalText} | `; } @@ -163,17 +195,35 @@ discordClient.on("messageCreate", async (message) => { } } - // Build message text - let discordMessage = `${quote}<${nickname}> ${message.content}`; - - // Append attachment URLs + // Build message + let baseMessage = message.content; + if (quote) baseMessage = `${quote}${baseMessage}`; if (message.attachments.size > 0) { const urls = message.attachments.map((att) => att.url).join(" "); - discordMessage += ` [Attachments: ${urls}]`; + baseMessage += ` [Attachments: ${urls}]`; } + const privmsgMessage = `<${nickname}> ${baseMessage}`; - logForward(`Forwarding Discord → IRC [${info.channel}]: ${discordMessage}`); - ircClient.say(info.channel, discordMessage); + logForward(`Forwarding Discord → IRC [${info.channel}]: ${privmsgMessage}`); + + // --- RELAYMSG logic --- + if (info.useRelayMsg) { + if (ircClient.state.hasOp) { + const relayNick = `${nickname}/dc`; + ircClient.raw(`RELAYMSG ${info.channel} ${relayNick} :${baseMessage}`); + } else { + if (!ircClient.state.warnedRelayMsg) { + ircClient.say( + info.channel, + `[Bridge] Missing +o, falling back to PRIVMSG (RELAYMSG disabled)` + ); + ircClient.state.warnedRelayMsg = true; + } + ircClient.say(info.channel, privmsgMessage); + } + } else { + ircClient.say(info.channel, privmsgMessage); + } } }); @@ -205,7 +255,15 @@ discordClient.on("messageReactionAdd", async (reaction, user) => { const reactionMessage = `<${nickname}> reacted with ${emoji} to "${originalContent}"`; logForward(`Reaction → IRC [${info.channel}]: ${reactionMessage}`); - ircClient.say(info.channel, reactionMessage); + + if (info.useRelayMsg && ircClient.state.hasOp) { + const relayNick = `${nickname}/dc`; + ircClient.raw( + `RELAYMSG ${info.channel} ${relayNick} :${reactionMessage}` + ); + } else { + ircClient.say(info.channel, reactionMessage); + } } } catch (err) { logDebug("Failed to handle reaction:", err); @@ -214,5 +272,5 @@ discordClient.on("messageReactionAdd", async (reaction, user) => { // Login to Discord discordClient.login(DISCORD_TOKEN).catch((err) => -console.error("Failed to login to Discord:", err) + console.error("Failed to login to Discord:", err) ); diff --git a/example.config.yaml b/example.config.yaml index 59ef9b1..8ff525c 100644 --- a/example.config.yaml +++ b/example.config.yaml @@ -1,3 +1,5 @@ +# WARNING YAML is very sensitive so make sure everything is formatted like in this example configuration file :D + discord: token: "YOUR_DISCORD_TOKEN" # Insert your bot or user token here. @@ -15,6 +17,7 @@ bridges: nick: "MyBot" password: null # or "yourpassword" if required channel: "#test" + useRelayMsg: false # Adding more then one bridge - discordChannelId: "987654321098765432" @@ -25,3 +28,4 @@ bridges: nick: "OtherBot" password: null channel: "#another" + useRelayMsg: true diff --git a/package-lock.json b/package-lock.json index 7ee57b0..361f0c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { - "name": "bridge", - "version": "1.0.0", + "name": "discord-irc-bridge", + "version": "2.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "bridge", - "version": "1.0.0", - "license": "ISC", + "name": "discord-irc-bridge", + "version": "2.0.1", + "license": "Apache-2.0", "dependencies": { "discord.js-selfbot-v13": "^3.4.5", "irc": "^0.5.2", diff --git a/package.json b/package.json index 6f98076..ee08059 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "discord-irc-bridge", - "version": "2.0.0", + "version": "2.0.1", "description": "A Discord <-> IRC bridge using selfbot and irc-framework", "main": "bot.js", "scripts": {