ruben 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +0 -1
- data/README.md +5 -11
- data/Rakefile +38 -3
- data/bin/ruben +15 -16
- data/lib/robot.rb +23 -13
- data/lib/robot/channel.rb +24 -16
- data/lib/robot/listener.rb +22 -7
- data/lib/robot/scripts/engage.rb +4 -2
- data/lib/robot/scripts/flip_coin.rb +5 -3
- data/lib/robot/scripts/hello.rb +5 -3
- data/lib/robot/scripts/politeness.rb +6 -4
- data/lib/robot/scripts/roll_dice.rb +4 -2
- data/lib/robot/scripts/tell_time.rb +7 -4
- metadata +7 -9
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 09c93b25e4f051e816791d7c6d1f56132c8e916e
|
4
|
+
data.tar.gz: a0e138d4f441de54b04d4a35b3be5f866e76498f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c385cdcbc386cd357aa000a7f75b84a8fbd8bf6d107e5a98f3511cc6a72e605031f1abf7ab11ec505a7c94e15ecf626318963ab2fc80a6957492a49e8ee054cd
|
7
|
+
data.tar.gz: 41131b1132fe46909a129bb2d1495aa0c5a07760f2206d8c46710343a393a4ad66ea63f2bebb38103c2e8779ee19e56c619cd169d189b1b7c57ac65121bc40d7
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -4,32 +4,28 @@ Ruben
|
|
4
4
|
[![Build Status](https://travis-ci.org/ericqweinstein/ruben.png)](https://travis-ci.org/ericqweinstein/ruben)
|
5
5
|
|
6
6
|
###Description
|
7
|
-
|
8
7
|
Ruben is an IRC chat bot written in Ruby. He is inspired, in part, by [Hubot](http://hubot.github.com/), his CoffeeScript brother from another mother.
|
9
8
|
|
10
9
|
###Dependencies
|
11
|
-
|
12
|
-
*
|
13
|
-
*
|
14
|
-
* RSpec 2.12.2 (for running tests)
|
10
|
+
* Ruby 1.9.3+
|
11
|
+
* Rake 10.0.4 (for running tests, if that's your jam)
|
12
|
+
* RSpec 2.13.0 (see above)
|
15
13
|
|
16
14
|
###Installation
|
17
|
-
|
18
|
-
Version 1.0.2 is available from RubyGems; you can get your version of Ruben by typing
|
15
|
+
Version 1.1.0 is available from RubyGems; you can get your version of Ruben by typing
|
19
16
|
|
20
17
|
```bash
|
21
18
|
$ gem install ruben
|
22
19
|
```
|
23
20
|
|
24
21
|
###Getting Started
|
25
|
-
|
26
22
|
Ruben comes with a `bin/ruben` executable, so you can run him with
|
27
23
|
|
28
24
|
```bash
|
29
25
|
$ ruben <server> <port> <channel> <nick>
|
30
26
|
```
|
31
27
|
|
32
|
-
Ruben takes a server name, port number, channel name, and nick as command line arguments. For example, if you type:
|
28
|
+
Ruben takes a server name, port number, channel name, and nick as command line arguments. For example, if you type:
|
33
29
|
|
34
30
|
```bash
|
35
31
|
$ ruben irc.freenode.net 6667 test_chan ruben_
|
@@ -48,7 +44,6 @@ $ >> JOIN #test_chan
|
|
48
44
|
You can get Ruben's usage information by typing `ruben -h` or `ruben --help`.
|
49
45
|
|
50
46
|
###Adding Scripts
|
51
|
-
|
52
47
|
You can extend Ruben's functionality by adding scripts to `/scripts`. Each script should be a `.rb` file that instantiates a new `Listener` object, like so:
|
53
48
|
|
54
49
|
```ruby
|
@@ -60,4 +55,3 @@ Listener.new(/Regexp/, thing_to_do)
|
|
60
55
|
```
|
61
56
|
|
62
57
|
Ruben's listeners hear every incoming IRC message. If a listener's Regexp matches the inbound message, Ruben will call the associated lambda.
|
63
|
-
|
data/Rakefile
CHANGED
@@ -1,6 +1,41 @@
|
|
1
|
-
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
# encoding: UTF-8
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
require 'rubocop/rake_task'
|
6
|
+
require 'yard'
|
7
|
+
|
8
|
+
task default: :help
|
9
|
+
|
10
|
+
desc 'Display help menu'
|
11
|
+
task :help do
|
12
|
+
puts <<-eos
|
13
|
+
Available Rake tasks:
|
14
|
+
|
15
|
+
rake help # Display help menu
|
16
|
+
rake rubocop # Lint
|
17
|
+
rake spec # Run tests
|
18
|
+
rake yard # Generate documentation
|
19
|
+
eos
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'Lint'
|
23
|
+
RuboCop::RakeTask.new(:rubocop) do |t|
|
24
|
+
t.patterns = %w(bin/**/* lib/**/*.rb)
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Run tests'
|
28
|
+
task :spec do
|
29
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
30
|
+
task.rspec_opts = ['--color --format d']
|
31
|
+
task.pattern = './spec/**/*_spec.rb'
|
32
|
+
end
|
5
33
|
end
|
6
34
|
|
35
|
+
desc 'Generate documentation'
|
36
|
+
task :yard do
|
37
|
+
YARD::Rake::YardocTask.new do |t|
|
38
|
+
t.files = %w(bin/* lib/**/*.rb)
|
39
|
+
t.options = ['--protected', '--private']
|
40
|
+
end
|
41
|
+
end
|
data/bin/ruben
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
# @author Eric Weinstein <eric.q.weinstein@gmail.com>
|
2
4
|
|
3
|
-
require
|
4
|
-
require_relative
|
5
|
-
|
6
|
-
options = {}
|
5
|
+
require 'optparse'
|
6
|
+
require_relative '../lib/robot'
|
7
7
|
|
8
8
|
opt_parser = OptionParser.new do |opts|
|
9
|
-
opts.banner =
|
10
|
-
opts.separator
|
11
|
-
opts.separator
|
12
|
-
opts.separator
|
13
|
-
opts.separator
|
14
|
-
opts.separator
|
15
|
-
opts.separator
|
16
|
-
opts.separator
|
17
|
-
|
18
|
-
opts.on(
|
9
|
+
opts.banner = 'Usage: ruben SERVER PORT CHANNEL NICK'
|
10
|
+
opts.separator ''
|
11
|
+
opts.separator 'Running Ruben:'
|
12
|
+
opts.separator ' SERVER is an IRC server (e.g. irc.freenode.net).'
|
13
|
+
opts.separator ' PORT is the IRC port (e.g. 6667).'
|
14
|
+
opts.separator ' CHANNEL is the IRC channel you want to join.'
|
15
|
+
opts.separator ' NICK is the nickname you want Ruben to use.'
|
16
|
+
opts.separator ''
|
17
|
+
|
18
|
+
opts.on('-h', '--help', 'Display this screen') do
|
19
19
|
puts opt_parser
|
20
20
|
exit
|
21
21
|
end
|
@@ -37,7 +37,6 @@ rescue SocketError => e
|
|
37
37
|
end
|
38
38
|
|
39
39
|
# Ensure Ruben leaves politely when ^C-ed
|
40
|
-
trap(
|
40
|
+
trap('INT') { ruben.quit }
|
41
41
|
|
42
42
|
ruben.run
|
43
|
-
|
data/lib/robot.rb
CHANGED
@@ -1,8 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# encoding: UTF-8
|
2
|
+
# @author Eric Weinstein <eric.q.weinstein@gmail.com>
|
3
|
+
require 'socket'
|
4
|
+
require 'singleton'
|
5
|
+
require_relative 'robot/channel'
|
6
|
+
require_relative 'robot/listener'
|
5
7
|
|
8
|
+
# Handles connection to the TCP socket and
|
9
|
+
# sending credentials as per the IRC protocol.
|
10
|
+
# @see http://tools.ietf.org/html/rfc2812
|
11
|
+
# @attr_reader [TCPSocket] socket A TCP socket.
|
12
|
+
# @attr [String] server An IRC server.
|
13
|
+
# @attr [Integer] port The port to connect to.
|
14
|
+
# @attr [String] channel The IRC channel to join.
|
15
|
+
# @attr [String] nick The robot's nickname.
|
16
|
+
# @attr [Array<Listener>] listeners A list
|
17
|
+
# of all registered listeners.
|
6
18
|
class Robot
|
7
19
|
include Singleton
|
8
20
|
include Channel
|
@@ -11,24 +23,22 @@ class Robot
|
|
11
23
|
attr_accessor :server, :port, :channel, :nick, :listeners
|
12
24
|
|
13
25
|
def initialize
|
14
|
-
@listeners = Listener.
|
26
|
+
@listeners = Listener.listeners
|
15
27
|
end
|
16
28
|
|
29
|
+
# The main event loop.
|
17
30
|
def run
|
18
31
|
begin
|
19
32
|
@socket = TCPSocket.open(server, port)
|
20
|
-
rescue
|
21
|
-
puts "An error occurred
|
22
|
-
exit
|
33
|
+
rescue => e
|
34
|
+
puts "An error occurred: #{e.message}"
|
35
|
+
exit 1
|
23
36
|
end
|
24
37
|
|
25
|
-
send
|
38
|
+
send 'USER ruben 0 * :Ruben'
|
26
39
|
send "NICK #{@nick}"
|
27
40
|
send "JOIN ##{@channel}"
|
28
41
|
|
29
|
-
until @socket.eof?
|
30
|
-
listen
|
31
|
-
end
|
42
|
+
listen until @socket.eof?
|
32
43
|
end
|
33
44
|
end
|
34
|
-
|
data/lib/robot/channel.rb
CHANGED
@@ -1,43 +1,51 @@
|
|
1
|
-
|
1
|
+
# encoding: UTF-8
|
2
|
+
# @author Eric Weinstein <eric.q.weinstein@gmail.com>
|
3
|
+
require_relative 'listener'
|
2
4
|
|
3
|
-
# Load scripts
|
4
|
-
Dir[File.dirname(__FILE__) +
|
5
|
+
# Load all our 'bot's scripts.
|
6
|
+
Dir[File.dirname(__FILE__) + '/scripts/*.rb'].each { |script| require script }
|
5
7
|
|
8
|
+
# Handles communcation with IRC.
|
6
9
|
module Channel
|
10
|
+
# Things the robot might say when disconnecting.
|
11
|
+
PARTING_MESSAGES = ['bye', 'peace!', 'later', 'I\'m out']
|
7
12
|
|
8
|
-
|
9
|
-
|
13
|
+
# Sends a message to IRC.
|
14
|
+
# @param [String] msg The message to send.
|
10
15
|
def send(msg)
|
11
16
|
@socket.puts msg
|
12
|
-
puts
|
17
|
+
puts '<< ' << msg
|
13
18
|
end
|
14
19
|
|
20
|
+
# Sends a message to users in the channel.
|
21
|
+
# @param [String] msg The message to say.
|
15
22
|
def say(msg)
|
16
23
|
send "PRIVMSG ##{@channel} :#{msg}"
|
17
24
|
end
|
18
25
|
|
26
|
+
# Continuously listens to the socket
|
27
|
+
# for messages coming from either IRC
|
28
|
+
# or users in the channel.
|
19
29
|
def listen
|
20
30
|
@inbound = @socket.gets
|
21
|
-
puts
|
31
|
+
puts '>> ' << @inbound
|
22
32
|
|
23
|
-
# Stay connected to the server
|
24
|
-
if @inbound.match(/^PING (
|
25
|
-
pong =
|
33
|
+
# Stay connected to the server.
|
34
|
+
if @inbound.match(/^PING (?<msg>.*)$/)
|
35
|
+
pong = Regexp.last_match[:msg]
|
26
36
|
send "PONG #{pong}"
|
27
37
|
end
|
28
38
|
|
29
|
-
# Respond to messages in the channel
|
39
|
+
# Respond to messages in the channel.
|
30
40
|
@listeners.each do |listener|
|
31
|
-
if @inbound.match
|
32
|
-
listener.response.call
|
33
|
-
end
|
41
|
+
listener.response.call if @inbound.match listener.pattern
|
34
42
|
end
|
35
43
|
end
|
36
44
|
|
45
|
+
# Terminates the IRC connection.
|
37
46
|
def quit
|
38
47
|
say "#{PARTING_MESSAGES.sample}"
|
39
48
|
send "PART ##{@channel} :mic drop"
|
40
|
-
send
|
49
|
+
send 'QUIT'
|
41
50
|
end
|
42
51
|
end
|
43
|
-
|
data/lib/robot/listener.rb
CHANGED
@@ -1,16 +1,31 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# @author Eric Weinstein <eric.q.weinstein@gmail.com>
|
3
|
+
|
4
|
+
# Collects and initalizes
|
5
|
+
# listeners from all our scripts.
|
6
|
+
# @attr [RegExp] pattern A pattern against
|
7
|
+
# which to match incoming messages.
|
8
|
+
# @attr [String] response The response to
|
9
|
+
# provide if the RegExp matches.
|
1
10
|
class Listener
|
2
11
|
attr_accessor :pattern, :response
|
3
12
|
|
4
|
-
|
5
|
-
|
13
|
+
@listeners = []
|
14
|
+
|
6
15
|
def initialize(pattern, response)
|
7
|
-
|
8
|
-
@pattern
|
16
|
+
self.class.add_listener(self)
|
17
|
+
@pattern = pattern
|
9
18
|
@response = response
|
10
19
|
end
|
11
20
|
|
12
|
-
|
13
|
-
|
21
|
+
class << self
|
22
|
+
attr_reader :listeners
|
23
|
+
|
24
|
+
# Adds a listener object to the class'
|
25
|
+
# list of listeners.
|
26
|
+
# @param [Listener] listener A listener to add.
|
27
|
+
def add_listener(listener)
|
28
|
+
@listeners << listener
|
29
|
+
end
|
14
30
|
end
|
15
31
|
end
|
16
|
-
|
data/lib/robot/scripts/engage.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
#
|
1
|
+
# encoding: UTF-8
|
2
|
+
# @author Eric Weinstein <eric.q.weinstein@gmail.com>
|
2
3
|
|
4
|
+
# Provides a random warp factor whenever
|
5
|
+
# the robot hears the word 'engage'.
|
3
6
|
warp_factor = lambda do
|
4
7
|
Robot.instance.say "WARP FACTOR #{rand(9) + 1}"
|
5
8
|
end
|
6
9
|
|
7
10
|
Listener.new(/ :\bengage\b/i, warp_factor)
|
8
|
-
|
@@ -1,11 +1,13 @@
|
|
1
|
-
#
|
1
|
+
# encoding: UTF-8
|
2
|
+
# @author Eric Weinstein <eric.q.weinstein@gmail.com>
|
2
3
|
|
4
|
+
# The robot flips a coin when
|
5
|
+
# it hears 'flip a coin'.
|
3
6
|
flip_coin = lambda do
|
4
7
|
coin_flip = rand(2)
|
5
|
-
result = coin_flip == 1 ?
|
8
|
+
result = coin_flip == 1 ? 'heads' : 'tails'
|
6
9
|
|
7
10
|
Robot.instance.say "#{result}!"
|
8
11
|
end
|
9
12
|
|
10
13
|
Listener.new(/ :(?:(?:ruben)?,?\s*flip\s*(?:a)?\s*coin)/i, flip_coin)
|
11
|
-
|
data/lib/robot/scripts/hello.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
#
|
1
|
+
# encoding: UTF-8
|
2
|
+
# @author Eric Weinstein <eric.q.weinstein@gmail.com>
|
2
3
|
|
4
|
+
# The robot says hello when greeted
|
5
|
+
# with any of the greetings.
|
3
6
|
say_hello = lambda do
|
4
|
-
greetings = [
|
7
|
+
greetings = ['sup', 'hey', 'what up', 'sup g']
|
5
8
|
Robot.instance.say "#{greetings.sample}"
|
6
9
|
end
|
7
10
|
|
8
11
|
Listener.new(/ :(?:hi|hello|hey)\s*,?\s*(?:ruben)/i, say_hello)
|
9
|
-
|
@@ -1,9 +1,11 @@
|
|
1
|
-
#
|
1
|
+
# encoding: UTF-8
|
2
|
+
# @author Eric Weinstein <eric.q.weinstein@gmail.com>
|
2
3
|
|
4
|
+
# The robot tells you you're welcome
|
5
|
+
# when it hears 'thanks', 'ty', &c.
|
3
6
|
youre_welcome = lambda do
|
4
|
-
responses = [
|
7
|
+
responses = ['no prob', 'sure thing', 'np boss']
|
5
8
|
Robot.instance.say "#{responses.sample}"
|
6
9
|
end
|
7
|
-
|
8
|
-
Listener.new(/ :(?:thanks|ty|thank\s*you),?\s*(?:ruben)/i, youre_welcome)
|
9
10
|
|
11
|
+
Listener.new(/ :(?:thanks|ty|thank\s*you),?\s*(?:ruben)/i, youre_welcome)
|
@@ -1,5 +1,8 @@
|
|
1
|
-
#
|
1
|
+
# encoding: UTF-8
|
2
|
+
# @author Eric Weinstein <eric.q.weinstein@gmail.com>
|
2
3
|
|
4
|
+
# The robot rolls a D6 whenever
|
5
|
+
# it hears 'roll the dice'.
|
3
6
|
roll_dice = lambda do
|
4
7
|
lucky_number = rand(5) + 1
|
5
8
|
|
@@ -7,4 +10,3 @@ roll_dice = lambda do
|
|
7
10
|
end
|
8
11
|
|
9
12
|
Listener.new(/ :(?:(?:ruben)?,?\s*roll\s*(?:the)?\s*dice)/i, roll_dice)
|
10
|
-
|
@@ -1,11 +1,14 @@
|
|
1
|
-
#
|
1
|
+
# encoding: UTF-8
|
2
|
+
# @author Eric Weinstein <eric.q.weinstein@gmail.com>
|
2
3
|
|
4
|
+
# The robot tells you what time it
|
5
|
+
# is when it hears 'what time'.
|
3
6
|
what_time = lambda do
|
4
|
-
current_hour = Time.now.localtime.strftime(
|
7
|
+
current_hour = Time.now.localtime.strftime('%H').to_i
|
5
8
|
current_hour = current_hour > 12 ? current_hour - 12 : current_hour
|
6
9
|
|
7
|
-
Robot.instance.say "I dunno, around #{Time
|
10
|
+
Robot.instance.say "I dunno, around #{Time
|
11
|
+
.now.localtime.strftime("#{current_hour}:%M %p")}"
|
8
12
|
end
|
9
13
|
|
10
14
|
Listener.new(/ :(?:what\s*time)/i, what_time)
|
11
|
-
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruben
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
5
|
-
prerelease:
|
4
|
+
version: 1.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Eric Weinstein
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-06-23 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
13
|
description: Ruben is an IRC chat bot written in Ruby. He is inspired, in part, by
|
15
14
|
Hubot, his CoffeeScript brother from another mother.
|
@@ -35,27 +34,26 @@ files:
|
|
35
34
|
- Rakefile
|
36
35
|
homepage: http://github.com/ericqweinstein/ruben
|
37
36
|
licenses: []
|
37
|
+
metadata: {}
|
38
38
|
post_install_message:
|
39
39
|
rdoc_options: []
|
40
40
|
require_paths:
|
41
41
|
- lib
|
42
42
|
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
-
none: false
|
44
43
|
requirements:
|
45
|
-
- -
|
44
|
+
- - '>='
|
46
45
|
- !ruby/object:Gem::Version
|
47
46
|
version: '0'
|
48
47
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
48
|
requirements:
|
51
|
-
- -
|
49
|
+
- - '>='
|
52
50
|
- !ruby/object:Gem::Version
|
53
51
|
version: '0'
|
54
52
|
requirements: []
|
55
53
|
rubyforge_project:
|
56
|
-
rubygems_version:
|
54
|
+
rubygems_version: 2.0.14
|
57
55
|
signing_key:
|
58
|
-
specification_version:
|
56
|
+
specification_version: 4
|
59
57
|
summary: An extensible IRC chat bot.
|
60
58
|
test_files: []
|
61
59
|
has_rdoc:
|