safubot 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardoc/checksums +5 -5
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -0
- data/README.md +9 -9
- data/doc/Safubot/Bot.html +334 -218
- data/doc/Safubot/Evented.html +1 -1
- data/doc/Safubot/KnownUser.html +1 -1
- data/doc/Safubot/Log.html +1 -1
- data/doc/Safubot/Problem.html +130 -0
- data/doc/Safubot/Problematic.html +282 -0
- data/doc/Safubot/Query.html +50 -1
- data/doc/Safubot/Request.html +19 -2
- data/doc/Safubot/Response.html +19 -2
- data/doc/Safubot/Test.html +1 -1
- data/doc/Safubot/Twitter/Bot.html +248 -135
- data/doc/Safubot/Twitter/DirectMessage.html +22 -22
- data/doc/Safubot/Twitter/Tweet.html +40 -40
- data/doc/Safubot/Twitter.html +1 -1
- data/doc/Safubot/XMPP/Bot.html +47 -31
- data/doc/Safubot/XMPP/Message.html +1 -1
- data/doc/Safubot/XMPP.html +1 -1
- data/doc/Safubot.html +4 -4
- data/doc/_index.html +26 -4
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +11 -10
- data/doc/index.html +11 -10
- data/doc/method_list.html +103 -79
- data/doc/top-level-namespace.html +1 -1
- data/lib/safubot/bot.rb +100 -26
- data/lib/safubot/test_helper.rb +4 -0
- data/lib/safubot/twitter.rb +6 -7
- data/lib/safubot/version.rb +1 -1
- data/lib/safubot/xmpp.rb +9 -3
- data/safubot.gemspec +1 -0
- metadata +119 -113
data/lib/safubot/bot.rb
CHANGED
@@ -8,19 +8,51 @@ module Safubot
|
|
8
8
|
"#{e.inspect}\n#{e.backtrace.join("\n\t")}"
|
9
9
|
end
|
10
10
|
|
11
|
+
###
|
12
|
+
# An EmbeddedDocument for storing processing/dispatch errors.
|
13
|
+
class Problem
|
14
|
+
include MongoMapper::EmbeddedDocument
|
15
|
+
key :when, Time
|
16
|
+
key :error, String # Exception#to_s
|
17
|
+
key :type, String # Exception class
|
18
|
+
key :backtrace, Array, :default => nil
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# A mixin adding Problem handling.
|
23
|
+
module Problematic
|
24
|
+
##
|
25
|
+
# Adds a timestamped Problem to the list.
|
26
|
+
# @param e Exception from which the Problem is derived.
|
27
|
+
def add_problem(e)
|
28
|
+
problem = Problem.new(:error => e.to_s, :type => e.class.to_s,
|
29
|
+
:when => Time.now, :backtrace => e.backtrace)
|
30
|
+
self.problems.push(problem)
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Fetches the most recent Problem.
|
35
|
+
def last_problem
|
36
|
+
self.problems.sort { |x,y| x.when <=> y.when }.last
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
11
41
|
##
|
12
42
|
# Defines elements of the input queue, agnostic of the transfer medium.
|
13
43
|
# May be extended by service-specific modules.
|
14
44
|
class Request
|
15
45
|
include MongoMapper::Document
|
46
|
+
include Problematic
|
16
47
|
safe
|
17
|
-
key :
|
48
|
+
key :processing, Boolean, :default => false # Currently-processing lock.
|
18
49
|
key :processed, Boolean, :default => false # Have we processed this request?
|
19
50
|
key :success, Boolean, :default => false # Did we *successfully* process this request?
|
20
51
|
key :text, String # The actual content.
|
21
52
|
belongs_to :source, :polymorphic => true # The concrete medium-specific source.
|
22
|
-
belongs_to :user, :
|
53
|
+
belongs_to :user, :class_name => "Safubot::KnownUser"
|
23
54
|
many :responses, :class_name => "Safubot::Response"
|
55
|
+
many :problems # Hopefully not that many ;)
|
24
56
|
timestamps!
|
25
57
|
end
|
26
58
|
|
@@ -29,11 +61,13 @@ module Safubot
|
|
29
61
|
# May be extended by service-specific modules.
|
30
62
|
class Response
|
31
63
|
include MongoMapper::Document
|
64
|
+
include Problematic
|
32
65
|
safe
|
33
|
-
key :
|
66
|
+
key :dispatching, Boolean, :default => false # Dispatch lock.
|
34
67
|
key :dispatched, Boolean, :default => false
|
35
68
|
key :text, String
|
36
|
-
belongs_to :request, :
|
69
|
+
belongs_to :request, :class_name => "Safubot::Request"
|
70
|
+
many :problems
|
37
71
|
timestamps!
|
38
72
|
end
|
39
73
|
|
@@ -47,27 +81,54 @@ module Safubot
|
|
47
81
|
attr_reader :opts, :twitter, :xmpp
|
48
82
|
|
49
83
|
##
|
50
|
-
# Records an error and emits a corresponding :request_error event.
|
84
|
+
# Records an error in processing and emits a corresponding :request_error event.
|
51
85
|
# @param req The Request for which the error was encountered.
|
52
86
|
# @param e The caught Exception.
|
53
87
|
def request_error(req, e)
|
54
|
-
Log.error "Error processing #{req.source.class} '#{req.text}': #{e
|
55
|
-
req.
|
88
|
+
Log.error "Error processing #{req.source.class} '#{req.text}': #{error_report(e)}"
|
89
|
+
req.add_problem(e)
|
56
90
|
req.save
|
57
91
|
emit(:request_error, req, e)
|
58
92
|
end
|
59
93
|
|
94
|
+
##
|
95
|
+
# Records an error in dispatch and emits a corresponding :dispatch_error event.
|
96
|
+
# @param resp The Response for which the error was encountered.
|
97
|
+
# @param e The caught Exception.
|
98
|
+
def dispatch_error(resp, e)
|
99
|
+
Log.error "Error dispatching #{resp.request.source.class} '#{resp.text}': #{error_report(e)}"
|
100
|
+
resp.add_problem(e)
|
101
|
+
resp.save
|
102
|
+
emit(:dispatch_error, resp, e)
|
103
|
+
end
|
104
|
+
|
60
105
|
##
|
61
106
|
# Processes an individual request (synchronously).
|
62
107
|
# @param req An unprocessed Request.
|
63
108
|
def process_request(req)
|
109
|
+
req.reload
|
110
|
+
if req.processed
|
111
|
+
Log.debug "Request '#{req.text}' has already been processed, ignoring."
|
112
|
+
return
|
113
|
+
elsif req.processing
|
114
|
+
Log.debug "Request '#{req.text}' is currently in processing, ignoring."
|
115
|
+
return
|
116
|
+
end
|
117
|
+
|
64
118
|
begin
|
119
|
+
req.processing = true
|
120
|
+
req.save
|
65
121
|
emit(:request, req)
|
66
122
|
rescue Exception => e
|
67
123
|
request_error(req, e)
|
124
|
+
else
|
125
|
+
req.success = true
|
68
126
|
ensure
|
69
|
-
|
70
|
-
|
127
|
+
#if Safubot::mode == :production
|
128
|
+
req.processing = false
|
129
|
+
req.processed = true
|
130
|
+
req.save
|
131
|
+
#end
|
71
132
|
end
|
72
133
|
end
|
73
134
|
|
@@ -75,8 +136,26 @@ module Safubot
|
|
75
136
|
# Performs appropriate dispatch operation for response type.
|
76
137
|
# @param resp An undispatched Response.
|
77
138
|
def dispatch(resp)
|
139
|
+
resp.reload
|
140
|
+
if resp.dispatched
|
141
|
+
Log.debug "Response '#{resp.text}' has already been dispatched, ignoring."
|
142
|
+
return
|
143
|
+
elsif resp.dispatching
|
144
|
+
Log.debug "Response '#{resp.text}' is already in dispatch, ignoring."
|
145
|
+
return
|
146
|
+
elsif resp.problems.length > 10
|
147
|
+
Log.debug "Response '#{resp.text}' encountered more than ten dispatch errors, ignoring."
|
148
|
+
return
|
149
|
+
elsif !resp.problems.empty? && (Time.now - resp.last_problem.when) < 1.minute
|
150
|
+
Log.debug "Response '#{resp.text}' encountered a dispatch error <1 minute ago, ignoring."
|
151
|
+
return
|
152
|
+
end
|
153
|
+
|
78
154
|
begin
|
79
155
|
source = resp.request.source
|
156
|
+
resp.dispatching = true
|
157
|
+
resp.save
|
158
|
+
|
80
159
|
if Safubot::mode != :production
|
81
160
|
Log.info "#{source.class} Response to #{source.username}: #{resp.text}"
|
82
161
|
else
|
@@ -87,15 +166,15 @@ module Safubot
|
|
87
166
|
else
|
88
167
|
raise NotImplementedError, "Don't know how to send response to a #{source.class}!"
|
89
168
|
end
|
90
|
-
end
|
91
169
|
|
92
|
-
|
93
|
-
|
170
|
+
resp.dispatched = true
|
171
|
+
resp.save
|
172
|
+
end
|
94
173
|
rescue Exception => e
|
95
|
-
|
96
|
-
|
174
|
+
dispatch_error(resp, e)
|
175
|
+
ensure
|
176
|
+
resp.dispatching = false
|
97
177
|
resp.save
|
98
|
-
emit(:dispatch_error, resp, e)
|
99
178
|
end
|
100
179
|
end
|
101
180
|
|
@@ -112,18 +191,12 @@ module Safubot
|
|
112
191
|
end
|
113
192
|
|
114
193
|
##
|
115
|
-
# Adds a response to the queue.
|
194
|
+
# Adds a response to the queue and dispatches it.
|
116
195
|
# @param req Request to respond to.
|
117
196
|
# @param text Contents of the response.
|
118
197
|
def respond(req, text)
|
119
198
|
Log.info("#{req.user.name}: #{req.text}\nsafubot: #{text}")
|
120
|
-
Response.create(:request => req, :text => text)
|
121
|
-
end
|
122
|
-
|
123
|
-
# Respond + push
|
124
|
-
def respond_now(req, text)
|
125
|
-
respond(req, text)
|
126
|
-
push
|
199
|
+
dispatch(Response.create(:request => req, :text => text))
|
127
200
|
end
|
128
201
|
|
129
202
|
# Dispatches all undispatched Responses.
|
@@ -142,7 +215,6 @@ module Safubot
|
|
142
215
|
rescue Exception => e
|
143
216
|
request_error(req, e)
|
144
217
|
end
|
145
|
-
|
146
218
|
push
|
147
219
|
end
|
148
220
|
end
|
@@ -174,7 +246,8 @@ module Safubot
|
|
174
246
|
def enable_twitter(opts={})
|
175
247
|
@twitter = Twitter::Bot.new(opts)
|
176
248
|
@twitter.on(:request) do |req|
|
177
|
-
|
249
|
+
process_request(req)
|
250
|
+
req.responses.where(:dispatched => false).map(&method(:dispatch))
|
178
251
|
end
|
179
252
|
end
|
180
253
|
|
@@ -183,7 +256,8 @@ module Safubot
|
|
183
256
|
defaults = { :jid => nil, :password => nil }
|
184
257
|
@xmpp = XMPP::Bot.new(defaults.merge(options))
|
185
258
|
@xmpp.on(:request) do |req|
|
186
|
-
|
259
|
+
process_request(req)
|
260
|
+
req.responses.where(:dispatched => false).map(&method(:dispatch))
|
187
261
|
end
|
188
262
|
end
|
189
263
|
|
data/lib/safubot/test_helper.rb
CHANGED
data/lib/safubot/twitter.rb
CHANGED
@@ -170,7 +170,7 @@ module Safubot
|
|
170
170
|
if source.is_a?(DirectMessage)
|
171
171
|
@client.direct_message_create(source.raw['sender']['screen_name'], resp.text)
|
172
172
|
elsif source.is_a?(Tweet)
|
173
|
-
reply
|
173
|
+
reply source, resp.text
|
174
174
|
else
|
175
175
|
raise NotImplementedError, "Don't know how to send response to a #{req.source.class}!"
|
176
176
|
end
|
@@ -188,7 +188,7 @@ module Safubot
|
|
188
188
|
# @param message A raw JSON-derived direct message.
|
189
189
|
def handle_message(message)
|
190
190
|
return if message.sender.screen_name == @username
|
191
|
-
DirectMessage.from(message).make_request
|
191
|
+
handle_request(DirectMessage.from(message).make_request)
|
192
192
|
end
|
193
193
|
|
194
194
|
##
|
@@ -198,7 +198,7 @@ module Safubot
|
|
198
198
|
def handle_tweet(status)
|
199
199
|
return if status.user.screen_name == @username
|
200
200
|
if status.text.match(/@#{@username}/i)
|
201
|
-
Tweet.from(status).make_request
|
201
|
+
handle_request(Tweet.from(status).make_request)
|
202
202
|
else
|
203
203
|
emit(:timeline, Tweet.from(status))
|
204
204
|
end
|
@@ -239,8 +239,7 @@ module Safubot
|
|
239
239
|
@stream = TweetStream::Client.new(@opts)
|
240
240
|
|
241
241
|
@stream.on_direct_message do |message|
|
242
|
-
|
243
|
-
handle_request(req) if req.is_a? Request
|
242
|
+
handle_message(message)
|
244
243
|
end
|
245
244
|
|
246
245
|
@stream.on_error do |err|
|
@@ -253,6 +252,7 @@ module Safubot
|
|
253
252
|
|
254
253
|
@stream.on_inited do
|
255
254
|
Log.info("TweetStream client is online at @#{@username} :3")
|
255
|
+
emit(:ready)
|
256
256
|
end
|
257
257
|
end
|
258
258
|
|
@@ -260,8 +260,7 @@ module Safubot
|
|
260
260
|
def run_stream
|
261
261
|
begin
|
262
262
|
@stream.userstream do |status|
|
263
|
-
|
264
|
-
handle_request(req) if req.is_a? Request
|
263
|
+
handle_tweet(status)
|
265
264
|
end
|
266
265
|
rescue Exception => e
|
267
266
|
if e.is_a?(Interrupt) || e.is_a?(SignalException)
|
data/lib/safubot/version.rb
CHANGED
data/lib/safubot/xmpp.rb
CHANGED
@@ -113,11 +113,13 @@ module Safubot
|
|
113
113
|
# Runs the Blather client.
|
114
114
|
def run_blather
|
115
115
|
begin
|
116
|
-
EM::run {
|
116
|
+
EM::run {
|
117
|
+
@client.run
|
118
|
+
}
|
117
119
|
rescue Exception => e
|
118
120
|
if e.is_a?(Interrupt) || e.is_a?(SignalException)
|
119
121
|
stop
|
120
|
-
|
122
|
+
elsif @state == :running
|
121
123
|
Log.error "XMPP client exited unexpectedly: #{error_report(e)}"
|
122
124
|
Log.error "Restarting XMPP client in 5 seconds."
|
123
125
|
sleep 5; init_blather; run_blather
|
@@ -155,7 +157,11 @@ module Safubot
|
|
155
157
|
|
156
158
|
# Dispatch a Response via XMPP.
|
157
159
|
def send(resp)
|
158
|
-
|
160
|
+
if @state == :running
|
161
|
+
tell(resp.request.source.from, resp.text)
|
162
|
+
else
|
163
|
+
on(:ready) { send(resp) }
|
164
|
+
end
|
159
165
|
end
|
160
166
|
|
161
167
|
def initialize(opts)
|
data/safubot.gemspec
CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
+
s.add_dependency "activesupport", "= 3.1.0" # mongo_mapper seems to need this without specifying it.
|
22
23
|
s.add_dependency "eventmachine", "~> 0.12.10"
|
23
24
|
s.add_dependency "bson_ext", "~> 1.4.0"
|
24
25
|
s.add_dependency "mongo_mapper", "~> 0.10.1"
|
metadata
CHANGED
@@ -1,144 +1,159 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: safubot
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.3
|
3
|
+
version: !ruby/object:Gem::Version
|
5
4
|
prerelease:
|
5
|
+
version: 0.0.4
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Jaiden Mispy
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
|
13
|
+
date: 2011-12-01 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activesupport
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - "="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 3.1.0
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
15
27
|
name: eventmachine
|
16
|
-
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
17
30
|
none: false
|
18
|
-
requirements:
|
31
|
+
requirements:
|
19
32
|
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
33
|
+
- !ruby/object:Gem::Version
|
21
34
|
version: 0.12.10
|
22
35
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
26
38
|
name: bson_ext
|
27
|
-
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
28
41
|
none: false
|
29
|
-
requirements:
|
42
|
+
requirements:
|
30
43
|
- - ~>
|
31
|
-
- !ruby/object:Gem::Version
|
44
|
+
- !ruby/object:Gem::Version
|
32
45
|
version: 1.4.0
|
33
46
|
type: :runtime
|
34
|
-
|
35
|
-
|
36
|
-
- !ruby/object:Gem::Dependency
|
47
|
+
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
37
49
|
name: mongo_mapper
|
38
|
-
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
39
52
|
none: false
|
40
|
-
requirements:
|
53
|
+
requirements:
|
41
54
|
- - ~>
|
42
|
-
- !ruby/object:Gem::Version
|
55
|
+
- !ruby/object:Gem::Version
|
43
56
|
version: 0.10.1
|
44
57
|
type: :runtime
|
45
|
-
|
46
|
-
|
47
|
-
- !ruby/object:Gem::Dependency
|
58
|
+
version_requirements: *id004
|
59
|
+
- !ruby/object:Gem::Dependency
|
48
60
|
name: twitter
|
49
|
-
|
61
|
+
prerelease: false
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
50
63
|
none: false
|
51
|
-
requirements:
|
64
|
+
requirements:
|
52
65
|
- - ~>
|
53
|
-
- !ruby/object:Gem::Version
|
66
|
+
- !ruby/object:Gem::Version
|
54
67
|
version: 2.0.0
|
55
68
|
type: :runtime
|
56
|
-
|
57
|
-
|
58
|
-
- !ruby/object:Gem::Dependency
|
69
|
+
version_requirements: *id005
|
70
|
+
- !ruby/object:Gem::Dependency
|
59
71
|
name: tweetstream
|
60
|
-
|
72
|
+
prerelease: false
|
73
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
61
74
|
none: false
|
62
|
-
requirements:
|
75
|
+
requirements:
|
63
76
|
- - ~>
|
64
|
-
- !ruby/object:Gem::Version
|
77
|
+
- !ruby/object:Gem::Version
|
65
78
|
version: 1.1.3
|
66
79
|
type: :runtime
|
67
|
-
|
68
|
-
|
69
|
-
- !ruby/object:Gem::Dependency
|
80
|
+
version_requirements: *id006
|
81
|
+
- !ruby/object:Gem::Dependency
|
70
82
|
name: blather
|
71
|
-
|
83
|
+
prerelease: false
|
84
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
72
85
|
none: false
|
73
|
-
requirements:
|
86
|
+
requirements:
|
74
87
|
- - ~>
|
75
|
-
- !ruby/object:Gem::Version
|
88
|
+
- !ruby/object:Gem::Version
|
76
89
|
version: 0.5.8
|
77
90
|
type: :runtime
|
78
|
-
|
79
|
-
|
80
|
-
- !ruby/object:Gem::Dependency
|
91
|
+
version_requirements: *id007
|
92
|
+
- !ruby/object:Gem::Dependency
|
81
93
|
name: rake
|
82
|
-
|
94
|
+
prerelease: false
|
95
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
83
96
|
none: false
|
84
|
-
requirements:
|
85
|
-
- -
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
version:
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: "0"
|
88
101
|
type: :development
|
89
|
-
|
90
|
-
|
91
|
-
- !ruby/object:Gem::Dependency
|
102
|
+
version_requirements: *id008
|
103
|
+
- !ruby/object:Gem::Dependency
|
92
104
|
name: rspec
|
93
|
-
|
105
|
+
prerelease: false
|
106
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
94
107
|
none: false
|
95
|
-
requirements:
|
96
|
-
- -
|
97
|
-
- !ruby/object:Gem::Version
|
98
|
-
version:
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: "0"
|
99
112
|
type: :development
|
100
|
-
|
101
|
-
|
102
|
-
- !ruby/object:Gem::Dependency
|
113
|
+
version_requirements: *id009
|
114
|
+
- !ruby/object:Gem::Dependency
|
103
115
|
name: yard
|
104
|
-
|
116
|
+
prerelease: false
|
117
|
+
requirement: &id010 !ruby/object:Gem::Requirement
|
105
118
|
none: false
|
106
|
-
requirements:
|
107
|
-
- -
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version:
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: "0"
|
110
123
|
type: :development
|
111
|
-
|
112
|
-
|
113
|
-
- !ruby/object:Gem::Dependency
|
124
|
+
version_requirements: *id010
|
125
|
+
- !ruby/object:Gem::Dependency
|
114
126
|
name: bundler
|
115
|
-
|
127
|
+
prerelease: false
|
128
|
+
requirement: &id011 !ruby/object:Gem::Requirement
|
116
129
|
none: false
|
117
|
-
requirements:
|
118
|
-
- -
|
119
|
-
- !ruby/object:Gem::Version
|
120
|
-
version:
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: "0"
|
121
134
|
type: :development
|
122
|
-
|
123
|
-
|
124
|
-
- !ruby/object:Gem::Dependency
|
135
|
+
version_requirements: *id011
|
136
|
+
- !ruby/object:Gem::Dependency
|
125
137
|
name: wirble
|
126
|
-
|
138
|
+
prerelease: false
|
139
|
+
requirement: &id012 !ruby/object:Gem::Requirement
|
127
140
|
none: false
|
128
|
-
requirements:
|
129
|
-
- -
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version:
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: "0"
|
132
145
|
type: :development
|
133
|
-
|
134
|
-
version_requirements: *24331220
|
146
|
+
version_requirements: *id012
|
135
147
|
description: A friendly event-driven chatbot framework. Supports Twitter and XMPP.
|
136
|
-
email:
|
148
|
+
email:
|
137
149
|
- ^_^@mispy.me
|
138
150
|
executables: []
|
151
|
+
|
139
152
|
extensions: []
|
153
|
+
|
140
154
|
extra_rdoc_files: []
|
141
|
-
|
155
|
+
|
156
|
+
files:
|
142
157
|
- .gitignore
|
143
158
|
- .yardoc/checksums
|
144
159
|
- .yardoc/objects/root.dat
|
@@ -152,6 +167,8 @@ files:
|
|
152
167
|
- doc/Safubot/Evented.html
|
153
168
|
- doc/Safubot/KnownUser.html
|
154
169
|
- doc/Safubot/Log.html
|
170
|
+
- doc/Safubot/Problem.html
|
171
|
+
- doc/Safubot/Problematic.html
|
155
172
|
- doc/Safubot/Query.html
|
156
173
|
- doc/Safubot/Request.html
|
157
174
|
- doc/Safubot/Response.html
|
@@ -196,44 +213,33 @@ files:
|
|
196
213
|
- spec/safubot/known_user_spec.rb
|
197
214
|
- spec/safubot/twitter_spec.rb
|
198
215
|
- spec/safubot/xmpp_spec.rb
|
199
|
-
homepage:
|
216
|
+
homepage: ""
|
200
217
|
licenses: []
|
218
|
+
|
201
219
|
post_install_message:
|
202
220
|
rdoc_options: []
|
203
|
-
|
221
|
+
|
222
|
+
require_paths:
|
204
223
|
- lib
|
205
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
224
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
206
225
|
none: false
|
207
|
-
requirements:
|
208
|
-
- -
|
209
|
-
- !ruby/object:Gem::Version
|
210
|
-
version:
|
211
|
-
|
212
|
-
- 0
|
213
|
-
hash: 401033843839902587
|
214
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - ">="
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: "0"
|
230
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
215
231
|
none: false
|
216
|
-
requirements:
|
217
|
-
- -
|
218
|
-
- !ruby/object:Gem::Version
|
219
|
-
version:
|
220
|
-
segments:
|
221
|
-
- 0
|
222
|
-
hash: 401033843839902587
|
232
|
+
requirements:
|
233
|
+
- - ">="
|
234
|
+
- !ruby/object:Gem::Version
|
235
|
+
version: "0"
|
223
236
|
requirements: []
|
237
|
+
|
224
238
|
rubyforge_project: safubot
|
225
|
-
rubygems_version: 1.8.
|
239
|
+
rubygems_version: 1.8.11
|
226
240
|
signing_key:
|
227
241
|
specification_version: 3
|
228
242
|
summary: A friendly event-driven chatbot framework. Supports Twitter and XMPP.
|
229
|
-
test_files:
|
230
|
-
|
231
|
-
- spec/fixtures/twitter/tweet
|
232
|
-
- spec/fixtures/xmpp/message
|
233
|
-
- spec/helper.rb
|
234
|
-
- spec/safubot/bot_spec.rb
|
235
|
-
- spec/safubot/evented_spec.rb
|
236
|
-
- spec/safubot/known_user_spec.rb
|
237
|
-
- spec/safubot/twitter_spec.rb
|
238
|
-
- spec/safubot/xmpp_spec.rb
|
243
|
+
test_files: []
|
244
|
+
|
239
245
|
has_rdoc:
|