omnibot 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +31 -0
- data/Rakefile +36 -0
- data/bin/omnibot +5 -0
- data/bin/omnisend +5 -0
- data/examples/config.yaml +7 -0
- data/lib/omnibot.rb +13 -0
- data/lib/omnibot/amqpconsumer.rb +74 -0
- data/lib/omnibot/helpers.rb +65 -0
- data/lib/omnibot/jabberbot.rb +186 -0
- data/lib/omnibot/launcher.rb +37 -0
- data/lib/omnibot/omnisend.rb +23 -0
- data/lib/omnibot/periodiccommand.rb +48 -0
- data/lib/omnibot/version.rb +3 -0
- metadata +122 -0
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
OmniBot
|
2
|
+
===============
|
3
|
+
|
4
|
+
Simple XMPP bot for server monitoring.
|
5
|
+
Works with AMQP for sending messages at server side.
|
6
|
+
Sends notifications to a user via XMPP.
|
7
|
+
|
8
|
+
Dependencies
|
9
|
+
------------
|
10
|
+
|
11
|
+
* RabbitMQ or any other AMQP-compatible server
|
12
|
+
* amqp
|
13
|
+
* xmpp4r
|
14
|
+
* eventmachine
|
15
|
+
|
16
|
+
Installation
|
17
|
+
------------
|
18
|
+
|
19
|
+
Configure omnibot configuration from examples/config.yaml to ~/.omnibot.yaml and adjust it.
|
20
|
+
Then execute command:
|
21
|
+
|
22
|
+
omnibot
|
23
|
+
|
24
|
+
Send messages to omnibot by AMQP by running:
|
25
|
+
|
26
|
+
omnisend 'Hello World!'
|
27
|
+
|
28
|
+
Support
|
29
|
+
-------
|
30
|
+
|
31
|
+
Tested on Mac OS X 10.6 with Ruby 1.8
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
begin
|
2
|
+
require "bundler"
|
3
|
+
Bundler.setup
|
4
|
+
rescue LoadError
|
5
|
+
$stderr.puts "You need to have Bundler installed to be able build this gem."
|
6
|
+
end
|
7
|
+
|
8
|
+
gemspec = eval(File.read(Dir["*.gemspec"].first))
|
9
|
+
|
10
|
+
|
11
|
+
desc "Validate the gemspec"
|
12
|
+
task :gemspec do
|
13
|
+
gemspec.validate
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Build gem locally"
|
17
|
+
task :build => :gemspec do
|
18
|
+
system "gem build #{gemspec.name}.gemspec"
|
19
|
+
FileUtils.mkdir_p "pkg"
|
20
|
+
FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", "pkg"
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "Install gem locally"
|
24
|
+
task :install => :build do
|
25
|
+
system "gem install pkg/#{gemspec.name}-#{gemspec.version}"
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Push gem"
|
29
|
+
task :push => :build do
|
30
|
+
system "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Clean automatically generated files"
|
34
|
+
task :clean do
|
35
|
+
FileUtils.rm_rf "pkg"
|
36
|
+
end
|
data/bin/omnibot
ADDED
data/bin/omnisend
ADDED
data/lib/omnibot.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
require 'amqp'
|
5
|
+
require 'mq'
|
6
|
+
require 'eventmachine'
|
7
|
+
require 'xmpp4r'
|
8
|
+
require 'xmpp4r/client'
|
9
|
+
require 'xmpp4r/roster'
|
10
|
+
|
11
|
+
%w[ helpers jabberbot amqpconsumer omnisend launcher periodiccommand ].each do |file|
|
12
|
+
require "omnibot/#{file}.rb"
|
13
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module OmniBot
|
2
|
+
|
3
|
+
# AMQP consumer class
|
4
|
+
class AMQPConsumer
|
5
|
+
|
6
|
+
def send_message message
|
7
|
+
begin
|
8
|
+
@omnibot.add_message [Time.now, message]
|
9
|
+
rescue Object => e
|
10
|
+
OmniLog::error "Sending message error: #{e.message}\ntrace:\n#{Helpers::backtrace e}\nIgnoring..."
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize config
|
15
|
+
@config = config
|
16
|
+
end
|
17
|
+
|
18
|
+
def amqp_loop
|
19
|
+
# setup amqp
|
20
|
+
mq = MQ.new
|
21
|
+
exchange = mq.direct(Helpers::amqp_exchange_name)
|
22
|
+
queue = mq.queue("omnibot-consumerqueue", :exclusive => true)
|
23
|
+
queue.bind(exchange)
|
24
|
+
|
25
|
+
begin
|
26
|
+
OmniLog::info "Setup omnibot..."
|
27
|
+
@omnibot = JabberBot.new(Jabber::JID::new(@config['omnibotuser']), @config['omnibotpass'])
|
28
|
+
@omnibot.timer_provider = EM
|
29
|
+
@omnibot.set_subscriber Jabber::JID::new(@config['notifyjid']), @config['notifyresource']
|
30
|
+
@omnibot.connect
|
31
|
+
|
32
|
+
pause = 0
|
33
|
+
[@config['periodiccommands']].flatten.each do |command|
|
34
|
+
OmniLog::info "Setup command #{command}..."
|
35
|
+
periodic_command = PeriodicCommand.new command, pause
|
36
|
+
periodic_command.timer_provider = EM
|
37
|
+
periodic_command.set_jabber_messenger { |message| send_message message }
|
38
|
+
periodic_command.start
|
39
|
+
pause += 20
|
40
|
+
end
|
41
|
+
|
42
|
+
rescue Object => e
|
43
|
+
OmniLog::error "Sending message error: #{e.message}\ntrace:\n#{Helpers::backtrace e}\nExiting..."
|
44
|
+
AMQP.stop{ EM.stop }
|
45
|
+
end
|
46
|
+
|
47
|
+
OmniLog::info "==== AMQP is ready ===="
|
48
|
+
|
49
|
+
queue.subscribe do |msg|
|
50
|
+
message = Marshal.load msg
|
51
|
+
send_message message
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Main AMQP loop
|
56
|
+
def start
|
57
|
+
|
58
|
+
# exit hook
|
59
|
+
Signal.trap('INT') do
|
60
|
+
OmniLog::info "It's a trap, should exit..."
|
61
|
+
AMQP.stop{ EM.stop }
|
62
|
+
end
|
63
|
+
|
64
|
+
AMQP.start do
|
65
|
+
amqp_loop
|
66
|
+
end
|
67
|
+
|
68
|
+
OmniLog::info "Exited"
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module OmniBot
|
2
|
+
|
3
|
+
class OmniLog
|
4
|
+
|
5
|
+
def self.init_log
|
6
|
+
logger = Logger.new('omnibot.log')
|
7
|
+
logger.level = Logger::DEBUG
|
8
|
+
logger
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.log=(value)
|
12
|
+
@logger = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.log
|
16
|
+
@logger
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.debug(progname = nil, &block); @logger.debug(progname, &block); end
|
20
|
+
def self.info(progname = nil, &block); @logger.info(progname, &block); end
|
21
|
+
def self.warn(progname = nil, &block); @logger.warn(progname, &block); end
|
22
|
+
def self.error(progname = nil, &block); @logger.error(progname, &block); end
|
23
|
+
def self.fatal(progname = nil, &block); @logger.fatal(progname, &block); end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Helper class for counting reconnect attempts
|
27
|
+
class AttemptCounter
|
28
|
+
def report
|
29
|
+
OmniLog::debug "AttemptCounter: try #{@counter} of #{@max_attempts}"
|
30
|
+
end
|
31
|
+
public
|
32
|
+
def initialize max_attempts
|
33
|
+
@counter = 0
|
34
|
+
@max_attempts = max_attempts
|
35
|
+
OmniLog::debug "AttemptCounter inited"
|
36
|
+
end
|
37
|
+
|
38
|
+
def out_of_attempts?
|
39
|
+
@counter >= @max_attempts
|
40
|
+
end
|
41
|
+
|
42
|
+
def increase
|
43
|
+
@counter += 1
|
44
|
+
report
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Helpers
|
49
|
+
def self.backtrace e
|
50
|
+
e.respond_to?(:backtrace) && e.backtrace ? e.backtrace.join("\n\t") : ""
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.same_day? t1, t2
|
54
|
+
t1.year == t2.year && t1.month == t2.month && t1.day == t2.day
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.amqp_exchange_name
|
58
|
+
'omnibot-exchange'
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
|
@@ -0,0 +1,186 @@
|
|
1
|
+
module OmniBot
|
2
|
+
|
3
|
+
# Jabber bot with reconnection and dnd-care logic
|
4
|
+
class JabberBot
|
5
|
+
|
6
|
+
def dump_presence p
|
7
|
+
p ? "Presence status=#{p.status} type=#{p.type} show=#{p.show} from=#{p.from} to=#{p.to} xml=(#{p.to_s})" : "nil"
|
8
|
+
end
|
9
|
+
|
10
|
+
def on_message_handler m
|
11
|
+
OmniLog::debug "Got jabber message from #{m.from}:\n#{m.body}\n."
|
12
|
+
end
|
13
|
+
|
14
|
+
def is_needed_user? jid
|
15
|
+
jid.strip == @subscriber && @subscriber_resource.match((jid.resource or ''))
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_presence_callback old_presence, new_presence
|
19
|
+
OmniLog::debug "Presence changed:\n...old #{dump_presence old_presence}\n...new #{dump_presence new_presence}"
|
20
|
+
if is_needed_user? old_presence.from
|
21
|
+
@subscriber_online = check_presence? old_presence
|
22
|
+
OmniLog::debug "Subscriber #{@subscriber} is #{@subscriber_online ? "ready" : "not ready"}"
|
23
|
+
pump_messages if @subscriber_online
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def on_subscripton_request_callback item, pres
|
28
|
+
OmniLog::debug "Subscription request item=#{item} pres=#{dump_presence pres}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def on_exception_handler e, stream, sym_where
|
32
|
+
OmniLog::error "Jabber exception happens at symbol \"#{sym_where}\": #{e}\nbacktrace\n#{Helpers::backtrace e}"
|
33
|
+
OmniLog::debug "stream is #{stream} vs client #{@client}"
|
34
|
+
on_generic_exception_handler e
|
35
|
+
end
|
36
|
+
|
37
|
+
def safe_reconnect
|
38
|
+
begin
|
39
|
+
reconnect
|
40
|
+
rescue Jabber::ClientAuthenticationFailure => e
|
41
|
+
OmniLog::error "Authentification error: #{e.class}: #{e}"
|
42
|
+
raise
|
43
|
+
rescue Exception => e
|
44
|
+
OmniLog::error "Reconnect hard error: #{e.class}: #{e}"
|
45
|
+
on_generic_exception_handler e
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def on_generic_exception_handler e
|
50
|
+
if e && (e.kind_of?(Jabber::ServerDisconnected) || e.class.to_s =~ /^Errno::.+/)
|
51
|
+
OmniLog::error "No timer provider assigned" unless @timer_provider
|
52
|
+
# attempt counter is set when it's needed to connect
|
53
|
+
unless @ignore_reconnect
|
54
|
+
@timer_provider.add_timer(@reconnect_pause) { try_reconnect }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def reconnect
|
60
|
+
OmniLog::debug 'Going to reconnect'
|
61
|
+
@client.connect
|
62
|
+
@client.auth(@password)
|
63
|
+
@client.send(Jabber::Presence.new.set_type(:available))
|
64
|
+
end
|
65
|
+
|
66
|
+
def try_reconnect
|
67
|
+
return if @client.is_connected?
|
68
|
+
|
69
|
+
OmniLog::debug 'Called try_reconnect'
|
70
|
+
|
71
|
+
@attempt_counter = AttemptCounter.new(5) unless @attempt_counter
|
72
|
+
@attempt_counter.increase
|
73
|
+
|
74
|
+
if @attempt_counter.out_of_attempts?
|
75
|
+
OmniLog::warn "Can't reconect too often, sleep for #{@reconnect_long_pause/60} minutes..."
|
76
|
+
@attempt_counter = nil
|
77
|
+
@ignore_reconnect = true
|
78
|
+
@timer_provider.add_timer(@reconnect_long_pause) {
|
79
|
+
@ignore_reconnect = false
|
80
|
+
try_reconnect
|
81
|
+
}
|
82
|
+
return
|
83
|
+
end
|
84
|
+
|
85
|
+
safe_reconnect
|
86
|
+
|
87
|
+
if @client.is_connected?
|
88
|
+
@attempt_counter = nil
|
89
|
+
@roster = Jabber::Roster::Helper.new(@client)
|
90
|
+
@roster.add_subscription_request_callback { |item, pres| on_subscripton_request_callback item, pres }
|
91
|
+
end
|
92
|
+
|
93
|
+
OmniLog::debug "Client #{@client.is_connected? ? 'is' : 'isn\'t'} connected"
|
94
|
+
end
|
95
|
+
|
96
|
+
def check_presence? presence
|
97
|
+
raise 'No subscriber' unless @subscriber
|
98
|
+
|
99
|
+
OmniLog::debug "Subscriber #{@subscriber} is #{presence.show ? presence.show : 'online'}"
|
100
|
+
presence.show == nil || presence.show == :chat
|
101
|
+
end
|
102
|
+
|
103
|
+
def say_when_human orig, now
|
104
|
+
if Helpers::same_day? now, orig
|
105
|
+
amount = now - orig
|
106
|
+
if amount < 60
|
107
|
+
return "just now"
|
108
|
+
elsif amount < 60*60
|
109
|
+
return "less than a hour ago"
|
110
|
+
elsif amount < 60*60*6
|
111
|
+
return amount.div(60).to_s + " hours ago"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
return orig.to_s
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
def pump_messages
|
119
|
+
while msg = @messages.shift
|
120
|
+
send msg
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
public
|
125
|
+
|
126
|
+
attr_writer :timer_provider
|
127
|
+
|
128
|
+
def initialize jid, password
|
129
|
+
@client = Jabber::Client::new(jid)
|
130
|
+
@password = password
|
131
|
+
raise 'No jid set' if jid.empty?
|
132
|
+
raise 'No password set' unless password
|
133
|
+
|
134
|
+
@ignore_reconnect = false
|
135
|
+
@reconnect_pause = 10
|
136
|
+
@reconnect_long_pause = 60*15
|
137
|
+
|
138
|
+
@messages = []
|
139
|
+
@subscriber_online = false
|
140
|
+
|
141
|
+
@client.on_exception { |e, stream, sym_where| on_exception_handler(e, stream, sym_where) }
|
142
|
+
@client.add_message_callback { |m| on_message_handler m }
|
143
|
+
@client.add_presence_callback { |from, to| on_presence_callback from, to }
|
144
|
+
end
|
145
|
+
|
146
|
+
def connect
|
147
|
+
try_reconnect
|
148
|
+
end
|
149
|
+
|
150
|
+
def disconnect
|
151
|
+
@client.close
|
152
|
+
end
|
153
|
+
|
154
|
+
def set_subscriber jid, resource=nil
|
155
|
+
@subscriber = jid
|
156
|
+
if resource == nil || resource == ''
|
157
|
+
@subscriber_resource = /.*/
|
158
|
+
else
|
159
|
+
@subscriber_resource = Regexp.new(resource)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def add_message message
|
164
|
+
OmniLog::debug "Register a message, " + (@subscriber_online ? "should send immediately" : "will send later")
|
165
|
+
@messages << message
|
166
|
+
pump_messages if @subscriber_online
|
167
|
+
end
|
168
|
+
|
169
|
+
def send message
|
170
|
+
raise 'Not connected' unless @client.is_connected?
|
171
|
+
|
172
|
+
OmniLog::info "Sending a message..."
|
173
|
+
orig = message[0]
|
174
|
+
content = message[1]
|
175
|
+
|
176
|
+
body = "Omnibot reported " + say_when_human(orig, Time.now) + ":\n" + content.to_s
|
177
|
+
OmniLog::debug body
|
178
|
+
|
179
|
+
msg = Jabber::Message::new(@subscriber, body)
|
180
|
+
msg.type = :chat
|
181
|
+
@client.send(msg)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module OmniBot
|
2
|
+
|
3
|
+
# entry point
|
4
|
+
class Launcher
|
5
|
+
def get_config_path args
|
6
|
+
return args[0] if args[0] && File.file?(args[0])
|
7
|
+
path = File.join(ENV['HOME'],'.omnibot.yaml')
|
8
|
+
return path if ENV['HOME'] && File.file?(path)
|
9
|
+
raise 'No config file found, checked command line and ~/.omnibot.yaml'
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_log_path config
|
13
|
+
return config['logpath'] unless (config['logpath'] or '').empty?
|
14
|
+
return '/var/log/omnibot.log' if File.directory? '/var/log/'
|
15
|
+
return 'omnibot.log'
|
16
|
+
end
|
17
|
+
|
18
|
+
def start args
|
19
|
+
config_path = get_config_path args
|
20
|
+
puts "Using config at #{config_path}"
|
21
|
+
config = YAML.load_file(config_path)["config"]
|
22
|
+
|
23
|
+
log_path = get_log_path config
|
24
|
+
puts "Using log at #{log_path}"
|
25
|
+
OmniLog::log = Logger.new(log_path)
|
26
|
+
OmniLog::log.level = Logger::DEBUG
|
27
|
+
|
28
|
+
consumer = AMQPConsumer.new config
|
29
|
+
consumer.start
|
30
|
+
|
31
|
+
OmniLog::log.close
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module OmniBot
|
2
|
+
|
3
|
+
class OmniSend
|
4
|
+
|
5
|
+
def start args
|
6
|
+
return 1 if args.empty?
|
7
|
+
message = args.join(' ')
|
8
|
+
puts "Sending message #{message}"
|
9
|
+
data = Marshal.dump(message)
|
10
|
+
|
11
|
+
Signal.trap('INT') { AMQP.stop{ EM.stop } }
|
12
|
+
|
13
|
+
AMQP.start do
|
14
|
+
mq = MQ.new
|
15
|
+
exchange = mq.direct(Helpers::amqp_exchange_name)
|
16
|
+
exchange.publish(data)
|
17
|
+
puts 'sent'
|
18
|
+
AMQP.stop{ EM.stop }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module OmniBot
|
2
|
+
|
3
|
+
# Send to jabber user result of a daily command
|
4
|
+
class PeriodicCommand
|
5
|
+
|
6
|
+
def on_first_timer
|
7
|
+
OmniLog::debug "Okay, it's near of midnight"
|
8
|
+
on_periodic_timer
|
9
|
+
@timer_provider.add_periodic_timer(24*3600) { on_periodic_timer }
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_periodic_timer
|
13
|
+
OmniLog::info "Reporting command #{@command}"
|
14
|
+
body = `#{@command}`
|
15
|
+
raise 'Error launching command ' if $? != 0
|
16
|
+
message_body = "Results of daily executed command #{@command}:\n" + body
|
17
|
+
@jabber_messenger.call message_body
|
18
|
+
end
|
19
|
+
|
20
|
+
public
|
21
|
+
attr_writer :timer_provider
|
22
|
+
|
23
|
+
def initialize command, pause
|
24
|
+
@command = command
|
25
|
+
@pause = pause
|
26
|
+
|
27
|
+
raise 'Wrong command' if (command == nil or command == '')
|
28
|
+
end
|
29
|
+
|
30
|
+
def start
|
31
|
+
`command -v #{@command}`
|
32
|
+
if $? != 0
|
33
|
+
OmniLog::warn "Command #{@command} is not available"
|
34
|
+
else
|
35
|
+
now = Time.now
|
36
|
+
next_report_time = Time.local(now.year, now.month, now.day+1, 1, 0, 0)
|
37
|
+
next_report_time = next_report_time + @pause
|
38
|
+
@timer_provider.add_timer(next_report_time - now) { on_first_timer }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_jabber_messenger &block
|
43
|
+
@jabber_messenger = block
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: omnibot
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- theirix
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-01-10 00:00:00 +03:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 3
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
prerelease: false
|
32
|
+
version_requirements: *id001
|
33
|
+
type: :runtime
|
34
|
+
name: xmpp4r
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
hash: 3
|
42
|
+
segments:
|
43
|
+
- 0
|
44
|
+
version: "0"
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *id002
|
47
|
+
type: :runtime
|
48
|
+
name: eventmachine
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
hash: 3
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
version: "0"
|
59
|
+
prerelease: false
|
60
|
+
version_requirements: *id003
|
61
|
+
type: :runtime
|
62
|
+
name: amqp
|
63
|
+
description: Works with AMQP for sending messages at server side.Sends notifications to an user via XMPP.Can monitor system by performing daily commands.
|
64
|
+
email: theirix@gmail.com
|
65
|
+
executables:
|
66
|
+
- omnibot
|
67
|
+
- omnisend
|
68
|
+
extensions: []
|
69
|
+
|
70
|
+
extra_rdoc_files: []
|
71
|
+
|
72
|
+
files:
|
73
|
+
- examples/config.yaml
|
74
|
+
- lib/omnibot/amqpconsumer.rb
|
75
|
+
- lib/omnibot/helpers.rb
|
76
|
+
- lib/omnibot/jabberbot.rb
|
77
|
+
- lib/omnibot/launcher.rb
|
78
|
+
- lib/omnibot/omnisend.rb
|
79
|
+
- lib/omnibot/periodiccommand.rb
|
80
|
+
- lib/omnibot/version.rb
|
81
|
+
- lib/omnibot.rb
|
82
|
+
- Rakefile
|
83
|
+
- README.md
|
84
|
+
- bin/omnibot
|
85
|
+
- bin/omnisend
|
86
|
+
has_rdoc: true
|
87
|
+
homepage: http://github.com/theirix/omnibot
|
88
|
+
licenses: []
|
89
|
+
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 31
|
101
|
+
segments:
|
102
|
+
- 1
|
103
|
+
- 8
|
104
|
+
version: "1.8"
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
hash: 3
|
111
|
+
segments:
|
112
|
+
- 0
|
113
|
+
version: "0"
|
114
|
+
requirements:
|
115
|
+
- AMQP-compatible server (for example, RabbitMQ)
|
116
|
+
rubyforge_project: nowarning
|
117
|
+
rubygems_version: 1.4.2
|
118
|
+
signing_key:
|
119
|
+
specification_version: 3
|
120
|
+
summary: Simple XMPP bot for server monitoring
|
121
|
+
test_files: []
|
122
|
+
|