ponder 0.1.1 → 0.2.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.
- data/examples/echo.rb +6 -8
- data/examples/redis_last_seen.rb +23 -17
- data/lib/core_ext/array.rb +9 -0
- data/lib/ponder.rb +12 -3
- data/lib/ponder/async_irc.rb +119 -88
- data/lib/ponder/callback.rb +10 -7
- data/lib/ponder/logger/blind_io.rb +16 -14
- data/lib/ponder/logger/twoflogger.rb +7 -5
- data/lib/ponder/thaum.rb +78 -88
- data/lib/ponder/version.rb +1 -1
- data/ponder.gemspec +3 -3
- data/spec/async_irc_spec.rb +153 -112
- data/spec/callback_spec.rb +3 -4
- data/spec/irc_spec.rb +12 -7
- data/spec/thaum_spec.rb +5 -6
- metadata +9 -9
- data/examples/github_blog.rb +0 -31
data/examples/echo.rb
CHANGED
@@ -3,14 +3,12 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
3
3
|
require 'ponder'
|
4
4
|
|
5
5
|
# This Thaum will parrot all channel messages.
|
6
|
-
@ponder = Ponder::Thaum.new
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
c.verbose = true
|
13
|
-
c.logging = false
|
6
|
+
@ponder = Ponder::Thaum.new do |t|
|
7
|
+
t.server = 'chat.freenode.org'
|
8
|
+
t.port = 6667
|
9
|
+
t.nick = 'Ponder'
|
10
|
+
t.verbose = true
|
11
|
+
t.logging = false
|
14
12
|
end
|
15
13
|
|
16
14
|
@ponder.on :connect do
|
data/examples/redis_last_seen.rb
CHANGED
@@ -32,14 +32,12 @@ def remember(lowercase_nick, nick, user, host, channel, action,
|
|
32
32
|
'updated_at', Time.now.to_i)
|
33
33
|
end
|
34
34
|
|
35
|
-
@ponder = Ponder::Thaum.new
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
c.verbose = true
|
42
|
-
c.logging = false
|
35
|
+
@ponder = Ponder::Thaum.new do |t|
|
36
|
+
t.server = 'chat.freenode.org'
|
37
|
+
t.port = 6667
|
38
|
+
t.nick = 'Ponder'
|
39
|
+
t.verbose = true
|
40
|
+
t.logging = false
|
43
41
|
end
|
44
42
|
|
45
43
|
@ponder.on :connect do
|
@@ -124,16 +122,24 @@ end
|
|
124
122
|
@ponder.message event_data[:channel], "Too many results (#{results})."
|
125
123
|
end
|
126
124
|
# single search
|
127
|
-
elsif @redis.exists nick
|
128
|
-
msg = last_seen(nick)
|
129
|
-
if online_nick = @ponder.whois(nick)
|
130
|
-
msg = "#{online_nick[:nick]} is online. (#{msg})"
|
131
|
-
end
|
132
|
-
@ponder.message event_data[:channel], msg
|
133
|
-
elsif online_nick = @ponder.whois(nick)
|
134
|
-
@ponder.message event_data[:channel], "#{online_nick[:nick]} is online."
|
135
125
|
else
|
136
|
-
@ponder.
|
126
|
+
@ponder.whois(nick).callback do |result|
|
127
|
+
message = if @redis.exists nick
|
128
|
+
if result
|
129
|
+
"#{result[:nick]} is online. (#{last_seen(nick)})"
|
130
|
+
else
|
131
|
+
last_seen(nick)
|
132
|
+
end
|
133
|
+
else
|
134
|
+
if result
|
135
|
+
"#{result[:nick]} is online."
|
136
|
+
else
|
137
|
+
"#{nick} not found."
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
@ponder.message event_data[:channel], message
|
142
|
+
end
|
137
143
|
end
|
138
144
|
end
|
139
145
|
|
data/lib/ponder.rb
CHANGED
@@ -3,9 +3,18 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
3
3
|
module Ponder
|
4
4
|
ROOT = File.dirname($0)
|
5
5
|
|
6
|
-
autoload :
|
6
|
+
autoload :AsyncIRC, 'ponder/async_irc'
|
7
|
+
autoload :Callback, 'ponder/callback'
|
8
|
+
autoload :Connection, 'ponder/connection'
|
9
|
+
autoload :Filter, 'ponder/filter'
|
7
10
|
autoload :Formatting, 'ponder/formatting'
|
8
|
-
autoload :
|
9
|
-
autoload :
|
11
|
+
autoload :IRC, 'ponder/irc'
|
12
|
+
autoload :Thaum, 'ponder/thaum'
|
13
|
+
autoload :VERSION, 'ponder/version'
|
14
|
+
|
15
|
+
module Logger
|
16
|
+
autoload :Twoflogger, 'ponder/logger/twoflogger'
|
17
|
+
autoload :BlindIo, 'ponder/logger/blind_io'
|
18
|
+
end
|
10
19
|
end
|
11
20
|
|
data/lib/ponder/async_irc.rb
CHANGED
@@ -1,120 +1,151 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'timeout'
|
3
|
+
require 'eventmachine'
|
3
4
|
|
4
5
|
module Ponder
|
5
6
|
module AsyncIRC
|
6
|
-
|
7
|
+
class Topic
|
8
|
+
# number of seconds the deferrable will wait for a response before failing
|
9
|
+
TIMEOUT = 15
|
7
10
|
|
8
|
-
|
9
|
-
queue = Queue.new
|
10
|
-
@observer_queues[queue] = [/:\S+ (331|332|403|442) \S+ #{Regexp.escape(channel)} :/i]
|
11
|
-
raw "TOPIC #{channel}"
|
11
|
+
include EventMachine::Deferrable
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
raw_numeric = response.scan(/^:\S+ (\d{3})/)[0][0]
|
13
|
+
def initialize(channel, timeout_after, thaum)
|
14
|
+
@channel = channel
|
15
|
+
@thaum = thaum
|
17
16
|
|
18
|
-
|
17
|
+
self.timeout(timeout_after)
|
18
|
+
self.errback { @thaum.deferrables.delete self }
|
19
|
+
|
20
|
+
@thaum.deferrables.add self
|
21
|
+
@thaum.raw "TOPIC #{@channel}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def try(message)
|
25
|
+
if message =~ /:\S+ (331|332|403|442) \S+ #{Regexp.escape(@channel)} :/i
|
26
|
+
case $1
|
19
27
|
when '331'
|
20
|
-
{:raw_numeric => 331, :message => 'No topic is set'}
|
28
|
+
succeed({:raw_numeric => 331, :message => 'No topic is set'})
|
21
29
|
when '332'
|
22
|
-
{:raw_numeric => 332, :message =>
|
30
|
+
succeed({:raw_numeric => 332, :message => message.scan(/ :(.*)/)[0][0]})
|
23
31
|
when '403'
|
24
|
-
{:raw_numeric => 403, :message => 'No such channel'}
|
32
|
+
succeed({:raw_numeric => 403, :message => 'No such channel'})
|
25
33
|
when '442'
|
26
|
-
{:raw_numeric => 442, :message => "You're not on that channel"}
|
34
|
+
succeed({:raw_numeric => 442, :message => "You're not on that channel"})
|
27
35
|
end
|
28
36
|
end
|
29
|
-
rescue Timeout::Error
|
30
|
-
false
|
31
37
|
end
|
32
38
|
|
33
|
-
|
34
|
-
|
39
|
+
def succeed(*args)
|
40
|
+
@thaum.deferrables.delete self
|
41
|
+
set_deferred_status :succeeded, *args
|
42
|
+
end
|
35
43
|
end
|
36
44
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
45
|
+
class Whois
|
46
|
+
# number of seconds the deferrable will wait for a response before failing
|
47
|
+
TIMEOUT = 15
|
48
|
+
|
49
|
+
include EventMachine::Deferrable
|
50
|
+
|
51
|
+
def initialize(nick, timeout_after, thaum)
|
52
|
+
@nick = nick
|
53
|
+
@thaum = thaum
|
54
|
+
@whois_data = {}
|
55
|
+
|
56
|
+
self.timeout(timeout_after)
|
57
|
+
self.errback { @thaum.deferrables.delete self }
|
58
|
+
|
59
|
+
@thaum.deferrables.add self
|
60
|
+
@thaum.raw "WHOIS #{@nick}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def try(message)
|
64
|
+
if message =~ /^:\S+ (307|311|312|318|319|330|401) \S+ #{Regexp.escape(@nick)}/i
|
65
|
+
case $1
|
66
|
+
when '307', '330'
|
67
|
+
@whois_data[:registered] = true
|
68
|
+
when '311'
|
69
|
+
message = message.scan(/^:\S+ 311 \S+ (\S+) :?(\S+) (\S+) \* :(.*)$/)[0]
|
70
|
+
@whois_data[:nick] = message[0]
|
71
|
+
@whois_data[:username] = message[1]
|
72
|
+
@whois_data[:host] = message[2]
|
73
|
+
@whois_data[:real_name] = message[3]
|
74
|
+
when '312'
|
75
|
+
message = message.scan(/^:\S+ 312 \S+ \S+ (\S+) :(.*)/)[0]
|
76
|
+
@whois_data[:server] = {:address => message[0], :name => message[1]}
|
77
|
+
when '318'
|
78
|
+
succeed @whois_data
|
79
|
+
when '319'
|
80
|
+
channels_with_mode = message.scan(/^:\S+ 319 \S+ \S+ :(.*)/)[0][0].split(' ')
|
81
|
+
@whois_data[:channels] = {}
|
82
|
+
channels_with_mode.each do |c|
|
83
|
+
@whois_data[:channels][c.scan(/(.)?(#\S+)/)[0][1]] = c.scan(/(.)?(#\S+)/)[0][0]
|
61
84
|
end
|
85
|
+
when '401'
|
86
|
+
succeed false
|
62
87
|
end
|
63
88
|
end
|
64
|
-
rescue Timeout::Error
|
65
|
-
information = false
|
66
89
|
end
|
67
90
|
|
68
|
-
|
69
|
-
|
91
|
+
def succeed(*args)
|
92
|
+
@thaum.deferrables.delete self
|
93
|
+
set_deferred_status :succeeded, *args
|
94
|
+
end
|
70
95
|
end
|
71
96
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
channels_with_mode.each do |c|
|
103
|
-
whois[:channels][c.scan(/(.)?(#\S+)/)[0][1]] = c.scan(/(.)?(#\S+)/)[0][0]
|
104
|
-
end
|
105
|
-
when '401'
|
106
|
-
whois = false
|
107
|
-
running = false
|
108
|
-
end
|
97
|
+
class Channel
|
98
|
+
# number of seconds the deferrable will wait for a response before failing
|
99
|
+
TIMEOUT = 15
|
100
|
+
|
101
|
+
include EventMachine::Deferrable
|
102
|
+
|
103
|
+
def initialize(channel, timeout_after, thaum)
|
104
|
+
@channel = channel
|
105
|
+
@thaum = thaum
|
106
|
+
@channel_information = {}
|
107
|
+
|
108
|
+
self.timeout(timeout_after)
|
109
|
+
self.errback { @ponder.deferrables.delete self }
|
110
|
+
|
111
|
+
@thaum.deferrables.add self
|
112
|
+
@thaum.raw "MODE #{@channel}"
|
113
|
+
end
|
114
|
+
|
115
|
+
def try(message)
|
116
|
+
if message =~ /:\S+ (324|329|403|442) \S+ #{Regexp.escape(@channel)}/i
|
117
|
+
case $1
|
118
|
+
when '324'
|
119
|
+
@channel_information[:modes] = message.scan(/^:\S+ 324 \S+ \S+ \+(\w*)/)[0][0].split('')
|
120
|
+
limit = message.scan(/^:\S+ 324 \S+ \S+ \+\w* (\w*)/)[0]
|
121
|
+
@channel_information[:channel_limit] = limit[0].to_i if limit
|
122
|
+
when '329'
|
123
|
+
@channel_information[:created_at] = Time.at(message.scan(/^:\S+ 329 \S+ \S+ (\d+)/)[0][0].to_i)
|
124
|
+
succeed @channel_information
|
125
|
+
when '403', '442'
|
126
|
+
succeed false
|
109
127
|
end
|
110
128
|
end
|
111
|
-
rescue Timeout::Error
|
112
|
-
nil
|
113
129
|
end
|
114
130
|
|
115
|
-
|
116
|
-
|
131
|
+
def succeed(*args)
|
132
|
+
@thaum.deferrables.delete self
|
133
|
+
set_deferred_status :succeeded, *args
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
module Delegate
|
138
|
+
def get_topic(channel, timeout_after = AsyncIRC::Topic::TIMEOUT)
|
139
|
+
AsyncIRC::Topic.new(channel, timeout_after, self)
|
140
|
+
end
|
141
|
+
|
142
|
+
def whois(nick, timeout_after = AsyncIRC::Whois::TIMEOUT)
|
143
|
+
AsyncIRC::Whois.new(nick, timeout_after, self)
|
144
|
+
end
|
145
|
+
|
146
|
+
def channel_info(channel, timeout_after = AsyncIRC::Channel::TIMEOUT)
|
147
|
+
AsyncIRC::Channel.new(channel, timeout_after, self)
|
148
|
+
end
|
117
149
|
end
|
118
150
|
end
|
119
151
|
end
|
120
|
-
|
data/lib/ponder/callback.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
module Ponder
|
2
2
|
class Callback
|
3
3
|
LISTENED_TYPES = [:connect, :channel, :query, :join, :part, :quit, :nickchange, :kick, :topic, :disconnect] # + 3-digit numbers
|
4
|
-
|
5
|
-
|
4
|
+
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
def initialize(event_type = :channel, match = //, options = {}, proc = Proc.new {})
|
6
8
|
unless self.class::LISTENED_TYPES.include?(event_type) || event_type.is_a?(Integer)
|
7
9
|
raise TypeError, "#{event_type} is an unsupported event-type"
|
8
10
|
end
|
9
|
-
|
11
|
+
|
10
12
|
self.match = match
|
11
13
|
self.proc = proc
|
14
|
+
@options = options
|
12
15
|
end
|
13
|
-
|
16
|
+
|
14
17
|
def call(event_type, event_data = {})
|
15
18
|
if (event_type == :channel) || (event_type == :query)
|
16
19
|
@proc.call(event_data) if event_data[:message] =~ @match
|
@@ -20,9 +23,9 @@ module Ponder
|
|
20
23
|
@proc.call(event_data)
|
21
24
|
end
|
22
25
|
end
|
23
|
-
|
26
|
+
|
24
27
|
private
|
25
|
-
|
28
|
+
|
26
29
|
def match=(match)
|
27
30
|
if match.is_a?(Regexp)
|
28
31
|
@match = match
|
@@ -30,7 +33,7 @@ module Ponder
|
|
30
33
|
raise TypeError, "#{match} must be a Regexp"
|
31
34
|
end
|
32
35
|
end
|
33
|
-
|
36
|
+
|
34
37
|
def proc=(proc)
|
35
38
|
if proc.is_a?(Proc)
|
36
39
|
@proc = proc
|
@@ -1,24 +1,26 @@
|
|
1
1
|
module Ponder
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
module Logger
|
3
|
+
class BlindIo
|
4
|
+
def debug(*args, &block)
|
5
|
+
end
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
def info(*args, &block)
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
10
|
+
def warn(*args, &block)
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
13
|
+
def error(*args, &block)
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
16
|
+
def fatal(*args, &block)
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
19
|
+
def unknown(*args, &block)
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
+
def method_missing(*args, &block)
|
23
|
+
end
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
require 'logger'
|
2
2
|
|
3
3
|
module Ponder
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
module Logger
|
5
|
+
class Twoflogger < ::Logger
|
6
|
+
def initialize(*args)
|
7
|
+
super(*args)
|
8
|
+
self.formatter = proc do |severity, datetime, progname, msg|
|
9
|
+
"#{severity} #{datetime.strftime('%Y-%m-%d %H:%M:%S')} #{msg}\n"
|
10
|
+
end
|
9
11
|
end
|
10
12
|
end
|
11
13
|
end
|
data/lib/ponder/thaum.rb
CHANGED
@@ -1,21 +1,25 @@
|
|
1
|
+
require 'core_ext/array'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'ostruct'
|
4
|
+
require 'set'
|
1
5
|
require 'ponder/async_irc'
|
2
6
|
require 'ponder/callback'
|
3
7
|
require 'ponder/connection'
|
8
|
+
require 'ponder/filter'
|
4
9
|
require 'ponder/irc'
|
5
10
|
require 'ponder/logger/twoflogger'
|
6
11
|
require 'ponder/logger/blind_io'
|
7
|
-
require 'ostruct'
|
8
|
-
autoload :FileUtils, 'fileutils'
|
9
12
|
|
10
13
|
module Ponder
|
11
14
|
class Thaum
|
12
15
|
include IRC
|
13
|
-
include AsyncIRC
|
16
|
+
include AsyncIRC::Delegate
|
14
17
|
|
15
18
|
attr_reader :config, :callbacks
|
16
|
-
attr_accessor :connected, :logger, :console_logger
|
19
|
+
attr_accessor :connected, :logger, :console_logger, :deferrables
|
17
20
|
|
18
|
-
def initialize
|
21
|
+
def initialize(&block)
|
22
|
+
# default settings
|
19
23
|
@config = OpenStruct.new(
|
20
24
|
:server => 'localhost',
|
21
25
|
:port => 6667,
|
@@ -28,13 +32,34 @@ module Ponder
|
|
28
32
|
:reconnect_interval => 30
|
29
33
|
)
|
30
34
|
|
31
|
-
|
32
|
-
@
|
35
|
+
# custom settings
|
36
|
+
block.call(@config) if block_given?
|
37
|
+
|
38
|
+
# setting up loggers
|
39
|
+
@console_logger = if @config.verbose
|
40
|
+
Logger::Twoflogger.new($stdout)
|
41
|
+
else
|
42
|
+
Logger::BlindIo.new
|
43
|
+
end
|
44
|
+
|
45
|
+
@logger = if @config.logging
|
46
|
+
if @config.logger
|
47
|
+
@config.logger
|
48
|
+
else
|
49
|
+
log_path = File.join(ROOT, 'logs', 'log.log')
|
50
|
+
log_dir = File.dirname(log_path)
|
51
|
+
FileUtils.mkdir_p(log_dir) unless File.exist?(log_dir)
|
52
|
+
Logger::Twoflogger.new(log_path, File::WRONLY | File::APPEND)
|
53
|
+
end
|
54
|
+
else
|
55
|
+
Logger::BlindIo.new
|
56
|
+
end
|
33
57
|
|
34
|
-
|
58
|
+
# when using methods like #get_topic or #whois, a Deferrable object will wait
|
59
|
+
# for the response and call a callback. these Deferrables are stored in this Set
|
60
|
+
@deferrables = Set.new
|
35
61
|
|
36
62
|
@connected = false
|
37
|
-
@reloading = false
|
38
63
|
|
39
64
|
# user callbacks
|
40
65
|
@callbacks = Hash.new { |hash, key| hash[key] = [] }
|
@@ -58,36 +83,13 @@ module Ponder
|
|
58
83
|
@after_filters = Hash.new { |hash, key| hash[key] = [] }
|
59
84
|
end
|
60
85
|
|
61
|
-
def
|
62
|
-
|
63
|
-
block.call(@config)
|
64
|
-
|
65
|
-
# logger changes (if differing from initialize)
|
66
|
-
if @config.verbose
|
67
|
-
@console_logger = @config.console_logger if @config.console_logger
|
68
|
-
else
|
69
|
-
@console_logger = BlindIo.new
|
70
|
-
end
|
71
|
-
|
72
|
-
if @config.logging
|
73
|
-
log_path = @config.log_path || File.join(ROOT, 'logs', 'log.log')
|
74
|
-
log_dir = File.dirname(log_path)
|
75
|
-
FileUtils.mkdir_p(log_dir) unless File.exist?(log_dir)
|
86
|
+
def on(event_types = [:channel], match = //, *options, &block)
|
87
|
+
options = options.extract_options!
|
76
88
|
|
77
|
-
if @config.logger
|
78
|
-
@logger = @config.logger
|
79
|
-
else
|
80
|
-
@logger = Twoflogger.new(log_path, File::WRONLY | File::APPEND)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def on(event_types = [:channel], match = //, &block)
|
87
89
|
if event_types.is_a?(Array)
|
88
|
-
callbacks = event_types.map { |event_type| Callback.new(event_type, match, block) }
|
90
|
+
callbacks = event_types.map { |event_type| Callback.new(event_type, match, options, block) }
|
89
91
|
else
|
90
|
-
callbacks = [Callback.new(event_types, match, block)]
|
92
|
+
callbacks = [Callback.new(event_types, match, options, block)]
|
91
93
|
event_types = [event_types]
|
92
94
|
end
|
93
95
|
|
@@ -97,27 +99,14 @@ module Ponder
|
|
97
99
|
end
|
98
100
|
|
99
101
|
def connect
|
100
|
-
|
101
|
-
|
102
|
-
@console_logger.info '-- Starting Ponder'
|
102
|
+
@logger.info '-- Starting Ponder'
|
103
|
+
@console_logger.info '-- Starting Ponder'
|
103
104
|
|
104
|
-
|
105
|
-
|
106
|
-
end
|
105
|
+
EventMachine::run do
|
106
|
+
@connection = EventMachine::connect(@config.server, @config.port, Connection, self)
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
-
def reload!
|
111
|
-
@reloading = true
|
112
|
-
@callbacks.clear
|
113
|
-
load $0
|
114
|
-
@reloading = false
|
115
|
-
end
|
116
|
-
|
117
|
-
def reloading?
|
118
|
-
@reloading
|
119
|
-
end
|
120
|
-
|
121
110
|
# parsing incoming traffic
|
122
111
|
def parse(message)
|
123
112
|
message.chomp!
|
@@ -128,7 +117,7 @@ module Ponder
|
|
128
117
|
when /^PING \S+$/
|
129
118
|
raw message.sub(/PING/, 'PONG')
|
130
119
|
|
131
|
-
when
|
120
|
+
when /^(?:\:\S+ )?(\d\d\d) /
|
132
121
|
number = $1.to_i
|
133
122
|
parse_event(number, :type => number, :params => $')
|
134
123
|
|
@@ -157,51 +146,52 @@ module Ponder
|
|
157
146
|
parse_event(:topic, :type => :topic, :nick => $1, :user => $2, :host => $3, :channel => $4, :topic => $')
|
158
147
|
end
|
159
148
|
|
160
|
-
|
161
|
-
|
162
|
-
if message =~ regexp
|
163
|
-
queue << message
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
149
|
+
# if there are pending deferrabels, check if the message suits their matching pattern
|
150
|
+
@deferrables.each { |d| d.try(message) }
|
167
151
|
end
|
168
152
|
|
169
153
|
# process callbacks with its begin; rescue; end
|
170
154
|
def process_callbacks(event_type, event_data)
|
171
155
|
@callbacks[event_type].each do |callback|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
end
|
156
|
+
# process chain of before_filters, callback handling and after_filters
|
157
|
+
process = proc do
|
158
|
+
begin
|
159
|
+
stop_running = false
|
160
|
+
|
161
|
+
# before filters (specific filters first, then :all)
|
162
|
+
(@before_filters[event_type] + @before_filters[:all]).each do |filter|
|
163
|
+
if filter.call(event_type, event_data) == false
|
164
|
+
stop_running = true
|
165
|
+
break
|
183
166
|
end
|
167
|
+
end
|
184
168
|
|
185
|
-
|
186
|
-
|
187
|
-
|
169
|
+
unless stop_running
|
170
|
+
# handling
|
171
|
+
callback.call(event_type, event_data)
|
188
172
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
end
|
193
|
-
end
|
194
|
-
rescue => e
|
195
|
-
[@logger, @console_logger].each do |logger|
|
196
|
-
logger.error("-- #{e.class}: #{e.message}")
|
197
|
-
e.backtrace.each { |line| logger.error("-- #{line}") }
|
173
|
+
# after filters (specific filters first, then :all)
|
174
|
+
(@after_filters[event_type] + @after_filters[:all]).each do |filter|
|
175
|
+
filter.call(event_type, event_data)
|
198
176
|
end
|
199
177
|
end
|
178
|
+
rescue => e
|
179
|
+
[@logger, @console_logger].each do |logger|
|
180
|
+
logger.error("-- #{e.class}: #{e.message}")
|
181
|
+
e.backtrace.each { |line| logger.error("-- #{line}") }
|
182
|
+
end
|
200
183
|
end
|
201
|
-
|
184
|
+
end
|
185
|
+
|
186
|
+
# defer the whole process
|
187
|
+
if callback.options[:defer]
|
188
|
+
EM.defer(process)
|
189
|
+
else
|
190
|
+
process.call
|
191
|
+
end
|
202
192
|
end
|
203
193
|
end
|
204
|
-
|
194
|
+
|
205
195
|
def before_filter(event_types = :all, match = //, &block)
|
206
196
|
filter(@before_filters, event_types, match, block)
|
207
197
|
end
|
@@ -225,10 +215,10 @@ module Ponder
|
|
225
215
|
def filter(filter_type, event_types = :all, match = //, block = Proc.new)
|
226
216
|
if event_types.is_a?(Array)
|
227
217
|
event_types.each do |event_type|
|
228
|
-
filter_type[event_type] << Filter.new(event_type, match, block)
|
218
|
+
filter_type[event_type] << Filter.new(event_type, match, {}, block)
|
229
219
|
end
|
230
220
|
else
|
231
|
-
filter_type[event_types] << Filter.new(event_types, match, block)
|
221
|
+
filter_type[event_types] << Filter.new(event_types, match, {}, block)
|
232
222
|
end
|
233
223
|
end
|
234
224
|
end
|
data/lib/ponder/version.rb
CHANGED
data/ponder.gemspec
CHANGED
@@ -5,13 +5,13 @@ require 'lib/ponder/version'
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = 'ponder'
|
7
7
|
s.version = Ponder::VERSION
|
8
|
-
s.date = '2011-
|
8
|
+
s.date = '2011-08-28'
|
9
9
|
s.summary = 'IRC bot framework'
|
10
10
|
s.description = 'Ponder (Stibbons) is a Domain Specific Language for writing IRC Bots using the EventMachine library.'
|
11
11
|
|
12
12
|
s.author = 'Tobias Bühlmann'
|
13
13
|
s.email = 'tobias.buehlmann@gmx.de'
|
14
|
-
s.homepage = '
|
14
|
+
s.homepage = 'https://github.com/tbuehlmann/ponder'
|
15
15
|
|
16
16
|
s.required_ruby_version = '>= 1.8.6'
|
17
17
|
s.add_dependency('eventmachine', '>= 0.12.10')
|
@@ -21,8 +21,8 @@ Gem::Specification.new do |s|
|
|
21
21
|
README.md
|
22
22
|
Rakefile
|
23
23
|
examples/echo.rb
|
24
|
-
examples/github_blog.rb
|
25
24
|
examples/redis_last_seen.rb
|
25
|
+
lib/core_ext/array.rb
|
26
26
|
lib/ponder.rb
|
27
27
|
lib/ponder/async_irc.rb
|
28
28
|
lib/ponder/callback.rb
|
data/spec/async_irc_spec.rb
CHANGED
@@ -2,144 +2,185 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
require 'ponder/thaum'
|
5
|
+
require 'ponder/async_irc'
|
5
6
|
|
6
7
|
describe Ponder::AsyncIRC do
|
7
|
-
PERIODIC_TIME = 0.01
|
8
|
-
|
9
8
|
before(:each) do
|
10
|
-
@ponder = Ponder::Thaum.new
|
11
|
-
@ponder.configure { |c| c.verbose = false }
|
9
|
+
@ponder = Ponder::Thaum.new { |c| c.verbose = false }
|
12
10
|
end
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
EM.
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
12
|
+
describe Ponder::AsyncIRC::Whois do
|
13
|
+
context 'tries to get whois information when' do
|
14
|
+
it 'there is no such nick' do
|
15
|
+
@ponder.should_receive(:raw).with('WHOIS not_online')
|
16
|
+
EM.run do
|
17
|
+
whois = @ponder.whois('not_online', 1.5)
|
18
|
+
whois.callback do |result|
|
19
|
+
result.should be_false
|
20
|
+
EM.stop
|
21
|
+
end
|
22
|
+
whois.errback do
|
23
|
+
fail 'Wrong Callback called'
|
24
|
+
EM.stop
|
25
|
+
end
|
26
|
+
|
27
|
+
EM.next_tick { @ponder.parse(":server 401 Ponder not_online :No such nick\r\n") }
|
28
|
+
end
|
29
29
|
end
|
30
|
-
@result.should eql({:raw_numeric => 332, :message => 'topic content'})
|
31
|
-
end
|
32
30
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
31
|
+
it 'the user is online' do
|
32
|
+
@ponder.should_receive(:raw).with('WHOIS Ridcully')
|
33
|
+
EM.run do
|
34
|
+
whois = @ponder.whois('Ridcully', 1.5)
|
35
|
+
whois.callback do |result|
|
36
|
+
result.should be_kind_of(Hash)
|
37
|
+
result[:nick].should eql('Ridcully')
|
38
|
+
result[:username].should eql('ridc')
|
39
|
+
result[:host].should eql('host')
|
40
|
+
result[:real_name].should eql('Ridcully the wizard')
|
41
|
+
|
42
|
+
result[:server].should be_kind_of(Hash)
|
43
|
+
result[:server][:address].should eql('foo.host.net')
|
44
|
+
result[:server][:name].should eql('That host thing')
|
45
|
+
|
46
|
+
result[:channels].should be_kind_of(Hash)
|
47
|
+
result[:channels]['#foo'].should be_nil
|
48
|
+
result[:channels]['##bar'].should be_nil
|
49
|
+
result[:channels]['#baz'].should eql('<')
|
50
|
+
result[:channels]['#sushi'].should eql('@')
|
51
|
+
result[:channels]['#ramen'].should eql('+')
|
52
|
+
|
53
|
+
result[:registered].should be_true
|
54
|
+
EM.stop
|
55
|
+
end
|
56
|
+
whois.errback do
|
57
|
+
fail 'Wrong Callback called'
|
58
|
+
EM.stop
|
59
|
+
end
|
60
|
+
|
61
|
+
EM.next_tick do
|
62
|
+
@ponder.parse(":server 311 Ponder Ridcully :ridc host * :Ridcully the wizard\r\n")
|
63
|
+
@ponder.parse(":server 312 Ponder Ridcully foo.host.net :That host thing\r\n")
|
64
|
+
@ponder.parse(":server 319 Ponder Ridcully :#foo ##bar <#baz @#sushi +#ramen\r\n")
|
65
|
+
@ponder.parse(":server 330 Ponder Ridcully rid_ :is logged in as\r\n")
|
66
|
+
@ponder.parse(":server 318 Ponder Ridcully :End of /WHOIS list.\r\n")
|
67
|
+
end
|
68
|
+
end
|
38
69
|
end
|
39
|
-
@result.should eql({:raw_numeric => 403, :message => 'No such channel'})
|
40
70
|
end
|
41
71
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
EM
|
72
|
+
context 'it tries to get channel information when' do
|
73
|
+
it 'there is no such channel' do
|
74
|
+
@ponder.should_receive(:raw).with('MODE #no_channel')
|
75
|
+
|
76
|
+
EM.run do
|
77
|
+
channel_info = @ponder.channel_info('#no_channel')
|
78
|
+
channel_info.callback do |result|
|
79
|
+
result.should be_false
|
80
|
+
EM.stop
|
81
|
+
end
|
82
|
+
channel_info.errback do
|
83
|
+
fail 'Wrong Callback called'
|
84
|
+
EM.stop
|
85
|
+
end
|
86
|
+
|
87
|
+
EM.next_tick { @ponder.parse(":server 403 Ponder #no_channel :No such channel\r\n") }
|
88
|
+
end
|
47
89
|
end
|
48
|
-
@result.should eql({:raw_numeric => 442, :message => "You're not on that channel"})
|
49
90
|
end
|
50
91
|
end
|
51
92
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
EM.
|
57
|
-
|
93
|
+
describe Ponder::AsyncIRC::Topic do
|
94
|
+
context 'tries to get a topic' do
|
95
|
+
it ', adds the Deferrable object to the Set and deletes if afterwards for a success' do
|
96
|
+
@ponder.should_receive(:raw).with('TOPIC #channel')
|
97
|
+
EM.run do
|
98
|
+
@ponder.deferrables.should be_empty
|
99
|
+
topic = @ponder.get_topic('#channel')
|
100
|
+
@ponder.deferrables.should include(topic)
|
101
|
+
topic.callback do |result|
|
102
|
+
@ponder.deferrables.should be_empty
|
103
|
+
EM.stop
|
104
|
+
end
|
105
|
+
topic.errback do
|
106
|
+
fail 'Wrong Callback called'
|
107
|
+
EM.stop
|
108
|
+
end
|
109
|
+
|
110
|
+
EM.next_tick { @ponder.parse(":server 331 Ponder #channel :No topic is set.\r\n") }
|
111
|
+
end
|
58
112
|
end
|
59
|
-
@result.should be_false
|
60
|
-
end
|
61
113
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
@ponder.parse(":server 324 Ponder #channel +cnst\r\n")
|
77
|
-
@ponder.parse(":server 329 Ponder #channel 1233034048\r\n")
|
114
|
+
it ', adds the Deferrable object to the Set and deletes if afterwards for a failure (timeout)' do
|
115
|
+
@ponder.should_receive(:raw).with('TOPIC #channel')
|
116
|
+
EM.run do
|
117
|
+
@ponder.deferrables.should be_empty
|
118
|
+
topic = @ponder.get_topic('#channel', 1.5)
|
119
|
+
@ponder.deferrables.should include(topic)
|
120
|
+
topic.callback do |result|
|
121
|
+
fail 'Wrong Callback called'
|
122
|
+
EM.stop
|
123
|
+
end
|
124
|
+
topic.errback do
|
125
|
+
@ponder.deferrables.should be_empty
|
126
|
+
EM.stop
|
127
|
+
end
|
78
128
|
end
|
79
129
|
end
|
80
|
-
@result.should be_kind_of(Hash)
|
81
|
-
@result[:modes].should include('c', 'n', 's', 't')
|
82
|
-
@result[:created_at].should eql(Time.at(1233034048))
|
83
|
-
end
|
84
130
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
@ponder.
|
91
|
-
|
131
|
+
it 'when there is no topic set' do
|
132
|
+
@ponder.should_receive(:raw).with('TOPIC #channel')
|
133
|
+
EM.run do
|
134
|
+
@ponder.deferrables.should be_empty
|
135
|
+
topic = @ponder.get_topic('#channel', 2)
|
136
|
+
@ponder.deferrables.should include(topic)
|
137
|
+
topic.callback do |result|
|
138
|
+
result.should eql({:raw_numeric => 331, :message => 'No topic is set'})
|
139
|
+
@ponder.deferrables.should be_empty
|
140
|
+
EM.stop
|
141
|
+
end
|
142
|
+
topic.errback do
|
143
|
+
fail 'Wrong Callback called'
|
144
|
+
EM.stop
|
145
|
+
end
|
146
|
+
|
147
|
+
EM.next_tick { @ponder.parse(":server 331 Ponder #channel :No topic is set.\r\n") }
|
92
148
|
end
|
93
149
|
end
|
94
|
-
@result.should be_kind_of(Hash)
|
95
|
-
@result[:modes].should include('c', 'n', 's', 't')
|
96
|
-
@result[:created_at].should eql(Time.at(1233034048))
|
97
|
-
@result[:channel_limit].should equal(8)
|
98
|
-
end
|
99
|
-
end
|
100
150
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
151
|
+
it 'when there is no such channel' do
|
152
|
+
@ponder.should_receive(:raw).with('TOPIC #no_channel')
|
153
|
+
EM.run do
|
154
|
+
topic = @ponder.get_topic('#no_channel')
|
155
|
+
topic.callback do |result|
|
156
|
+
result.should eql({:raw_numeric => 403, :message => 'No such channel'})
|
157
|
+
EM.stop
|
158
|
+
end
|
159
|
+
topic.errback do
|
160
|
+
fail 'Wrong Callback called'
|
161
|
+
EM.stop
|
162
|
+
end
|
163
|
+
|
164
|
+
EM.next_tick { @ponder.parse(":server 403 Ponder #no_channel :No such channel\r\n") }
|
165
|
+
end
|
107
166
|
end
|
108
|
-
@result.should be_false
|
109
|
-
end
|
110
167
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
168
|
+
it "you're not on that channel" do
|
169
|
+
@ponder.should_receive(:raw).with('TOPIC #channel')
|
170
|
+
EM.run do
|
171
|
+
topic = @ponder.get_topic('#channel')
|
172
|
+
topic.callback do |result|
|
173
|
+
result.should eql({:raw_numeric => 442, :message => "You're not on that channel"})
|
174
|
+
EM.stop
|
175
|
+
end
|
176
|
+
topic.errback do
|
177
|
+
fail 'Wrong Callback called'
|
178
|
+
EM.stop
|
179
|
+
end
|
180
|
+
|
181
|
+
EM.next_tick { @ponder.parse(":server 442 Ponder #channel :You're not on that channel\r\n") }
|
121
182
|
end
|
122
183
|
end
|
123
|
-
|
124
|
-
@result.should be_kind_of(Hash)
|
125
|
-
@result[:nick].should eql('Ridcully')
|
126
|
-
@result[:username].should eql('ridc')
|
127
|
-
@result[:host].should eql('host')
|
128
|
-
@result[:real_name].should eql('Ridcully the wizard')
|
129
|
-
|
130
|
-
@result[:server].should be_kind_of(Hash)
|
131
|
-
@result[:server][:address].should eql('foo.host.net')
|
132
|
-
@result[:server][:name].should eql('That host thing')
|
133
|
-
|
134
|
-
@result[:channels].should be_kind_of(Hash)
|
135
|
-
@result[:channels]['#foo'].should be_nil
|
136
|
-
@result[:channels]['##bar'].should be_nil
|
137
|
-
@result[:channels]['#baz'].should eql('<')
|
138
|
-
@result[:channels]['#sushi'].should eql('@')
|
139
|
-
@result[:channels]['#ramen'].should eql('+')
|
140
|
-
|
141
|
-
@result[:registered].should be_true
|
142
184
|
end
|
143
185
|
end
|
144
186
|
end
|
145
|
-
|
data/spec/callback_spec.rb
CHANGED
@@ -7,8 +7,7 @@ describe Ponder::Callback do
|
|
7
7
|
before(:all) { @proc = Proc.new { } }
|
8
8
|
|
9
9
|
before(:each) do
|
10
|
-
@ponder = Ponder::Thaum.new
|
11
|
-
@ponder.configure { |c| c.verbose = true }
|
10
|
+
@ponder = Ponder::Thaum.new { |c| c.verbose = true }
|
12
11
|
end
|
13
12
|
|
14
13
|
context 'tries to create a callback' do
|
@@ -25,12 +24,12 @@ describe Ponder::Callback do
|
|
25
24
|
end
|
26
25
|
|
27
26
|
it 'with an invalid proc' do
|
28
|
-
lambda { Ponder::Callback.new(:channel, /foo/, 8) }.should raise_error(TypeError)
|
27
|
+
lambda { Ponder::Callback.new(:channel, /foo/, {}, 8) }.should raise_error(TypeError)
|
29
28
|
end
|
30
29
|
end
|
31
30
|
|
32
31
|
it "calls the callback's proc on right match" do
|
33
|
-
callback = Ponder::Callback.new(:channel, /wizzard/, Proc.new { 8 })
|
32
|
+
callback = Ponder::Callback.new(:channel, /wizzard/, {}, Proc.new { 8 })
|
34
33
|
callback.call(:channel, {:message => 'I like wizzards'}).should eql(8)
|
35
34
|
end
|
36
35
|
|
data/spec/irc_spec.rb
CHANGED
@@ -5,12 +5,11 @@ require 'ponder/thaum'
|
|
5
5
|
|
6
6
|
describe Ponder::IRC do
|
7
7
|
before(:each) do
|
8
|
-
@ponder = Ponder::Thaum.new
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
c.reconnect = true
|
8
|
+
@ponder = Ponder::Thaum.new do |t|
|
9
|
+
t.nick = 'Ponder'
|
10
|
+
t.username = 'Ponder'
|
11
|
+
t.real_name = 'Ponder Stibbons'
|
12
|
+
t.reconnect = true
|
14
13
|
end
|
15
14
|
end
|
16
15
|
|
@@ -26,10 +25,16 @@ describe Ponder::IRC do
|
|
26
25
|
end
|
27
26
|
|
28
27
|
it 'registers with the server with a password' do
|
28
|
+
@ponder = Ponder::Thaum.new do |t|
|
29
|
+
t.nick = 'Ponder'
|
30
|
+
t.username = 'Ponder'
|
31
|
+
t.real_name = 'Ponder Stibbons'
|
32
|
+
t.reconnect = true
|
33
|
+
t.password = 'secret'
|
34
|
+
end
|
29
35
|
@ponder.should_receive(:raw).with('NICK Ponder').once
|
30
36
|
@ponder.should_receive(:raw).with('USER Ponder * * :Ponder Stibbons').once
|
31
37
|
@ponder.should_receive(:raw).with('PASS secret').once
|
32
|
-
@ponder.configure { |c| c.password = 'secret' }
|
33
38
|
@ponder.register
|
34
39
|
end
|
35
40
|
|
data/spec/thaum_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe Ponder::Thaum do
|
|
8
8
|
@ponder = Ponder::Thaum.new
|
9
9
|
end
|
10
10
|
|
11
|
-
it 'sets a default configuration
|
11
|
+
it 'sets a default configuration' do
|
12
12
|
@ponder.config.server.should eql('localhost')
|
13
13
|
@ponder.config.port.should equal(6667)
|
14
14
|
@ponder.config.nick.should eql('Ponder')
|
@@ -19,14 +19,13 @@ describe Ponder::Thaum do
|
|
19
19
|
@ponder.config.reconnect.should be_true
|
20
20
|
@ponder.config.reconnect_interval.should equal(30)
|
21
21
|
|
22
|
-
@ponder.logger.should be_an_instance_of(Ponder::BlindIo)
|
23
|
-
@ponder.console_logger.should be_an_instance_of(Ponder::Twoflogger)
|
22
|
+
@ponder.logger.should be_an_instance_of(Ponder::Logger::BlindIo)
|
23
|
+
@ponder.console_logger.should be_an_instance_of(Ponder::Logger::Twoflogger)
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'sets the logger correctly' do
|
27
|
-
|
28
|
-
Ponder::
|
29
|
-
@ponder.configure { |c| c.logging = true }
|
27
|
+
Ponder::Logger::Twoflogger.should_receive(:new).twice
|
28
|
+
@ponder = Ponder::Thaum.new { |t| t.logging = true }
|
30
29
|
end
|
31
30
|
|
32
31
|
it 'sets default callbacks' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ponder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-08-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
16
|
-
requirement: &
|
16
|
+
requirement: &21592080 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.12.10
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *21592080
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &21591680 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *21591680
|
36
36
|
description: Ponder (Stibbons) is a Domain Specific Language for writing IRC Bots
|
37
37
|
using the EventMachine library.
|
38
38
|
email: tobias.buehlmann@gmx.de
|
@@ -44,8 +44,8 @@ files:
|
|
44
44
|
- README.md
|
45
45
|
- Rakefile
|
46
46
|
- examples/echo.rb
|
47
|
-
- examples/github_blog.rb
|
48
47
|
- examples/redis_last_seen.rb
|
48
|
+
- lib/core_ext/array.rb
|
49
49
|
- lib/ponder.rb
|
50
50
|
- lib/ponder/async_irc.rb
|
51
51
|
- lib/ponder/callback.rb
|
@@ -63,7 +63,7 @@ files:
|
|
63
63
|
- spec/irc_spec.rb
|
64
64
|
- spec/spec_helper.rb
|
65
65
|
- spec/thaum_spec.rb
|
66
|
-
homepage:
|
66
|
+
homepage: https://github.com/tbuehlmann/ponder
|
67
67
|
licenses: []
|
68
68
|
post_install_message:
|
69
69
|
rdoc_options: []
|
@@ -83,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
83
|
version: '0'
|
84
84
|
requirements: []
|
85
85
|
rubyforge_project:
|
86
|
-
rubygems_version: 1.
|
86
|
+
rubygems_version: 1.8.6
|
87
87
|
signing_key:
|
88
88
|
specification_version: 3
|
89
89
|
summary: IRC bot framework
|
data/examples/github_blog.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'ponder'
|
5
|
-
require 'nokogiri'
|
6
|
-
require 'open-uri'
|
7
|
-
|
8
|
-
# This Thaum answers the channel message "blog?" with the title of the newest github blog entry.
|
9
|
-
@ponder = Ponder::Thaum.new
|
10
|
-
|
11
|
-
@ponder.configure do |c|
|
12
|
-
c.server = 'chat.freenode.org'
|
13
|
-
c.port = 6667
|
14
|
-
c.nick = 'Ponder'
|
15
|
-
c.verbose = true
|
16
|
-
c.logging = false
|
17
|
-
end
|
18
|
-
|
19
|
-
@ponder.on :connect do
|
20
|
-
@ponder.join '#ponder'
|
21
|
-
end
|
22
|
-
|
23
|
-
@ponder.on :channel, /^blog\?$/ do |event_data|
|
24
|
-
doc = Nokogiri::HTML(open('https://github.com/blog'))
|
25
|
-
title = doc.xpath('/html/body/div/div[2]/div/div/ul/li/h2/a')[0].text
|
26
|
-
|
27
|
-
@ponder.message event_data[:channel], "Newest Github Blog Post: #{title}"
|
28
|
-
end
|
29
|
-
|
30
|
-
@ponder.connect
|
31
|
-
|