Created
October 27, 2015 00:42
-
-
Save copygirl/6bd44865e98951b4716c to your computer and use it in GitHub Desktop.
Fiddled-together IRC - Discord bridge bot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Fiddled-together IRC - Discord bridge bot | |
# Currently set up to relay messages to channels of the same name. | |
# Discord APIs are very likely to change, and so this will probably break. | |
require! { | |
irc # npm install node-irc | |
"discord.js": Discord # npm install discord.js | |
"prelude-ls": { find } # npm install prelude-ls | |
"./auth" # Configuration goes in auth.json file | |
# auth.irc contains IRC information, see clientIrc | |
# auth.discord contains "email" and "password" field | |
} | |
messageLimit = 200 | |
String.prototype.limit = (repl) -> | |
if @length > messageLimit | |
then "#{@substr 0, messageLimit - 4} #{repl or '...'}" | |
else @ | |
String.prototype.splice = (index, count, str) -> | |
"#{@slice 0, index}#str#{@slice index + count}" | |
# See here for options that may be contained in auth.irc: | |
# autoConnect MUST be set to false. I've seen strange | |
# things happen if connect is called a second time. | |
# https://node-irc.readthedocs.org/en/latest/API.html#client | |
clientIrc = new irc.Client auth.irc.server, auth.irc.nick, auth.irc | |
clientIrc.on \registered, !-> | |
# IRC client has no "disconnect" event, so we have to make do with this. | |
# (clientIrc.conn is not initialized until clientItc.connect is called.) | |
clientIrc.conn.on \close, !-> | |
console.log "[= IRC =] Sir, they spotted us, I have to kill the connection!" | |
console.log "[= IRC =] We hacked into their mainframes, sir!" | |
# Identify with nickserv. This requires the account to be set up already. | |
clientIrc.say "NickServ", "IDENTIFY #auth.irc.password" if auth.irc.password | |
clientIrc.on \message#, (nick, channel, message) !-> | |
response = "<#nick> #{message.limit!}" | |
console.log "[= IRC =] [#channel] #response" | |
clientDiscord.sendToChannel channel, response | |
clientIrc.on \action, (nick, channel, message) !-> | |
# Ignore actions not sent channel a channel. | |
if !channel.startsWith "#" then return | |
response = "\\* #nick *#{message.limit!}*" | |
clientDiscord.sendToChannel channel, response | |
clientDiscord = new Discord.Client! | |
clientDiscord.sendToChannel = (channelName, message, callback) !-> | |
# Find the Discord channel with a matching name, or don't send it. | |
channel = clientDiscord.channels |> find (ch) -> "##{ch.name}" == channelName | |
clientDiscord.sendMessage channel, message, callback if channel | |
clientDiscord.on \ready, !-> | |
console.log "[Discord] Ready to serve, copy-sensei." | |
clientDiscord.on \disconnected, !-> | |
console.log "[Discord] I have failed you, copy-sensei..." | |
clientDiscord.on \message, (msg) !-> | |
# You receive message events from your own sent messages, so ignore those. | |
if msg.author.id == clientDiscord.user.id then return | |
# Only relay messages to channels that the bot is actually in. | |
if !("##{msg.channel.name}" of clientIrc.chans) then return | |
from = msg.author.username | |
text = msg.content | |
# Replace user mentions (<@long-ass user id>) with actual user name (@username). | |
# TODO: Do the same for #channel "mentions" (currently displays <#long-ass channel id>) | |
for user in msg.mentions | |
text .= replace (new RegExp "<@#{user.id}>", "g"), "@#{user.username}" | |
# Format message differently if it seems to be a message generated by /me: | |
# Needs to start and end with a *, no *'s in the message itself, so | |
# "*this* is *bullshit*" or "*this *is* bullshit* don't count. | |
response = if /^\*[^\*]+\*$/g.test text | |
"* #from #{text.substr 1, text.length - 2 .limit!}" | |
else "<#from> #{text.limit!}" | |
console.log "[Discord] [##{msg.channel.name}] #response" | |
# Insert zero-width space in name to avoid | |
# highlighting IRC users with the same name. | |
# Because lazyness, this only works for 3+ char nicks. | |
response .= splice 3, 0, "\u200B" | |
clientIrc.say "##{msg.channel.name}", response | |
clientIrc.connect 0 # retryCount = 0 | |
clientDiscord.login auth.discord.email, auth.discord.password | |
exitHandler = !-> | |
# Wait for both clients to disconnect. | |
num = 0 | |
onLogout = !-> | |
if ++num >= 2 | |
process.exit! | |
clientIrc.disconnect "I have been terminated T_T", onLogout | |
clientDiscord.logout onLogout | |
process.on \exit, exitHandler | |
process.on \SIGINT, exitHandler # ctrl-c |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment