Skip to content

Commit

Permalink
add irc topic/join/leave hooks
Browse files Browse the repository at this point in the history
Also make the bot run its own messages through the hooks.

This means you can end up in an infinite loop if one of the hooks responds with text that matches itself, so be careful.
  • Loading branch information
aaronpk committed Jun 26, 2016
1 parent a9c8381 commit 13eaf44
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 66 deletions.
7 changes: 7 additions & 0 deletions hooks.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ hooks:
match: ".*"
url: "http://localhost:8000/log.php"
token: xxxxx
- events:
- topic
- join
- leave
channels:
- "@freenode"
url: "http://localhost:8000/log.php"
profile_data:
- channels:
- "#example@freenode"
Expand Down
152 changes: 92 additions & 60 deletions irc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ def self.handle_response(channel, response)
"setting topic for #{channel}"
elsif response['content']
IRCAPI.send_message channel, response['content']
handle_message channel, {nick: $config['irc']['nick'], user: $config['irc']['username'], realname: $config['irc']['username']}, response['content']
"sent"
else
"error"
end
Expand All @@ -74,13 +76,90 @@ def self.handle_response(channel, response)

def chat_author_from_irc_user(user)
Bot::Author.new({
uid: user.nick,
nickname: user.nick,
username: user.data[:user],
name: user.data[:realname],
uid: user[:nick],
nickname: user[:nick],
username: user[:user],
name: user[:realname],
})
end

def user_hash_from_irc_user(user)
{
nick: user.nick,
user: user.data[:user],
realname: user.data[:realname]
}
end

def fetch_user_info(hooks, channel, user)
# Enhance the author info
# TODO: expire the cache
if $nicks[user[:nick]].nil?
user_info = chat_author_from_irc_user user

hooks['profile_data'].each do |hook|
next if !Gateway.channel_match(hook, channel, $config['irc']['server'])
user_info = Gateway.enhance_profile hook, user_info
end

$nicks[user[:nick]] = user_info
end
end

def chat_channel_from_name(channel)
if $channels[channel].nil?
$channels[channel] = Bot::Channel.new({
uid: channel,
name: channel
})
else
$channels[channel]
end
end

def handle_event(event, data, text=nil)
channel = data.channel.name

hooks = Gateway.load_hooks

chat_channel_from_name channel
fetch_user_info hooks, channel, user_hash_from_irc_user(data.user)

hooks['hooks'].each do |hook|
next if !Gateway.channel_match(hook, channel, $config['irc']['server'])

if hook['match'].nil? && !hook['events'].nil? && hook['events'].include?(event)
Gateway.process do
IRCAPI.send_to_hook hook, event, channel, data.user.nick, text, nil
end
end
end
end

def handle_message(channel, user, text)
chat_channel_from_name channel

hooks = Gateway.load_hooks

fetch_user_info hooks, channel, user

command = "message"

hooks['hooks'].each do |hook|
next if !Gateway.channel_match(hook, channel, $config['irc']['server'])

if match=Gateway.text_match(hook, text)
puts "Matched hook: #{hook['match']} Posting to #{hook['url']}"
puts match.captures.inspect

# Post to the hook URL in a separate thread
Gateway.process do
IRCAPI.send_to_hook hook, 'message', channel, user[:nick], text, match
end

end
end
end

$channels = {}
$nicks = {}
Expand All @@ -90,6 +169,9 @@ def chat_author_from_irc_user(user)
c.server = $config['irc']['host']
c.port = $config['irc']['port']
c.password = $config['irc']['password']
if $config['irc']['ssl']
c.ssl.use = true
end
c.nick = $config['irc']['nick']
c.user = $config['irc']['username']
c.channels = $config['irc']['channels']
Expand All @@ -98,80 +180,30 @@ def chat_author_from_irc_user(user)
on :message do |data, nick|
channel = data.channel ? data.channel.name : data.user.nick

if $channels[channel].nil?
$channels[channel] = Bot::Channel.new({
uid: channel,
name: channel
})
end

hooks = Gateway.load_hooks

# Enhance the author info
# TODO: expire the cache
if $nicks[data.user.nick].nil?
user_info = chat_author_from_irc_user data.user

hooks['profile_data'].each do |hook|
next if !Gateway.channel_match(hook, channel, $config['irc']['server'])
user_info = Gateway.enhance_profile hook, user_info
end

$nicks[data.user.nick] = user_info
end

command = "message"

# IRC "/me" lines end up coming through as PRIVMSG "\u0001ACTION waves\u0001"
if match = data.message.match(/\u0001ACTION (.+)\u0001/)
text = "/me #{match[1]}"
else
text = data.message
end

hooks['hooks'].each do |hook|
next if !Gateway.channel_match(hook, channel, $config['irc']['server'])

if match=Gateway.text_match(hook, text)
puts "Matched hook: #{hook['match']} Posting to #{hook['url']}"
puts match.captures.inspect

# Post to the hook URL in a separate thread
if $config['thread']
Thread.new do
IRCAPI.send_to_hook hook, 'message', channel, data.user.nick, text, match
end
else
IRCAPI.send_to_hook hook, 'message', channel, data.user.nick, text, match
end

end
end

handle_message channel, user_hash_from_irc_user(data.user), text
end

on :invite do |data, nick|
$client.join(data.channel)
end

on :topic do |data|
puts "TOPIC:"
puts data.inspect
end

on :connect do |data, user|
puts "CONNECT:"
puts data.inspect
handle_event 'topic', data, data.message
end

on :online do |data, user|
puts "ONLINE:"
puts data.inspect
on :part do |data|
handle_event 'leave', data
end

on :offline do |data, user|
puts "OFFLINE:"
puts data.inspect
on :join do |data|
handle_event 'join', data
end

end
Expand Down
13 changes: 12 additions & 1 deletion lib/gateway.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
class Gateway

def self.process(&block)
if $config['thread']
Thread.new do
block.call
end
else
block.call
end
end

def self.load_hooks
YAML.load_file 'hooks.yml'
end
Expand All @@ -23,6 +33,7 @@ def self.channel_match(hook, channel, server)
end

def self.text_match(hook, text)
return false if hook['match'].nil? || text.nil?
Regexp.new(hook['match']).match(text)
end

Expand All @@ -42,7 +53,7 @@ def self.send_to_hook(hook, timestamp, network, server, channel, author, type, c
channel: channel.to_hash,
author: author.to_hash,
content: content,
match: match.captures,
match: match ? match.captures : nil,
response_url: response_url
}

Expand Down
6 changes: 1 addition & 5 deletions slack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,7 @@ def chat_channel_from_slack_user_id(channel_id)
puts match.captures.inspect

# Post to the hook URL in a separate thread
if $config['thread']
Thread.new do
SlackAPI.send_to_hook hook, 'message', data, text, match
end
else
Gateway.process do
SlackAPI.send_to_hook hook, 'message', data, text, match
end

Expand Down

0 comments on commit 13eaf44

Please sign in to comment.