ruben 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
[](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:
|