omnibot 0.0.21 → 0.0.22
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 +4 -4
- data/Rakefile +1 -1
- data/examples/command_mail.rb +2 -2
- data/lib/omnibot.rb +32 -33
- data/lib/omnibot/amqpconsumer.rb +72 -72
- data/lib/omnibot/helpers.rb +64 -64
- data/lib/omnibot/jabberbot.rb +198 -205
- data/lib/omnibot/launcher.rb +58 -69
- data/lib/omnibot/loggedcommand.rb +14 -15
- data/lib/omnibot/mailchecker.rb +106 -114
- data/lib/omnibot/omnisend.rb +19 -21
- data/lib/omnibot/periodiccommand.rb +40 -45
- data/lib/omnibot/version.rb +1 -1
- metadata +20 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 420769502e3d02ff10e46d8f35ebe5d9e58e204e
|
4
|
+
data.tar.gz: c3f3c964d5aeceaa6db8fc4bcd57003d3886c6be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9adb175015c16571bd145838e1a1c743196453f49346e1f00c67ede9d48d99a97f03d0409191d4b517c7e9fa06099ca7d2111139cac562e816e193569c252dd
|
7
|
+
data.tar.gz: bf4820829a12830951f963eb8c9a617a831f711328ad419c7db7a69a1854267da647ede463d5f7d4a00b9be157aefed9ac3a1acdcd5828cb4fac4f5b976e2d67
|
data/Rakefile
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
data/examples/command_mail.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# encoding: utf-8
|
3
3
|
# You can specify this script in ~/.forward for mail forwarding
|
4
|
-
IO.popen('omnisend','w') do |io|
|
5
|
-
|
4
|
+
IO.popen('omnisend', 'w') do |io|
|
5
|
+
IO.new(STDIN.fileno, 'r:UTF-8').each { |s| io.write s }
|
6
6
|
end
|
data/lib/omnibot.rb
CHANGED
@@ -14,48 +14,47 @@ require 'sqlite3'
|
|
14
14
|
require 'socket'
|
15
15
|
require 'date'
|
16
16
|
require 'tmpdir'
|
17
|
+
require 'retryable'
|
17
18
|
|
18
|
-
require
|
19
|
+
require 'xray/thread_dump_signal_handler'
|
19
20
|
|
20
21
|
# patch from https://github.com/ln/xmpp4r/issues/3
|
21
22
|
|
22
|
-
if RUBY_VERSION <
|
23
|
+
if RUBY_VERSION < '1.9'
|
23
24
|
# ...
|
24
25
|
else
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
26
|
+
# Encoding patch
|
27
|
+
require 'socket'
|
28
|
+
class TCPSocket
|
29
|
+
def external_encoding
|
30
|
+
Encoding::BINARY
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'rexml/source'
|
35
|
+
class REXML::IOSource
|
36
|
+
alias_method :encoding_assign, :encoding=
|
37
|
+
def encoding=(value)
|
38
|
+
encoding_assign(value) if value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
begin
|
43
|
+
# OpenSSL is optional and can be missing
|
44
|
+
require 'openssl'
|
45
|
+
class OpenSSL::SSL::SSLSocket
|
46
|
+
def external_encoding
|
47
|
+
Encoding::BINARY
|
48
|
+
end
|
49
|
+
end
|
50
|
+
rescue # rubocop:disable Lint/HandleExceptions
|
51
|
+
end
|
51
52
|
end
|
52
53
|
|
53
54
|
# -----------------
|
54
55
|
|
55
56
|
module OmniBot
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
|
57
|
+
%w( helpers jabberbot amqpconsumer omnisend launcher loggedcommand periodiccommand mailchecker ).each do |file|
|
58
|
+
require "omnibot/#{file}.rb"
|
59
|
+
end
|
61
60
|
end
|
data/lib/omnibot/amqpconsumer.rb
CHANGED
@@ -1,76 +1,76 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module OmniBot
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
4
|
+
# AMQP consumer class
|
5
|
+
class AMQPConsumer
|
6
|
+
attr_accessor :handlers
|
7
|
+
attr_accessor :db
|
8
|
+
|
9
|
+
def send_message(message)
|
10
|
+
@omnibot.add_message [Time.now, message]
|
11
|
+
rescue Object => e
|
12
|
+
OmniLog::error "Sending message error: #{e.message}\ntrace:\n#{Helpers::backtrace e}\nIgnoring..."
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(config)
|
16
|
+
@config = config
|
17
|
+
end
|
18
|
+
|
19
|
+
def amqp_loop
|
20
|
+
AMQP.start do |connection|
|
21
|
+
OmniLog::info "Setup amqp gem #{AMQP::VERSION}, AMQP protocol #{AMQ::Protocol::VERSION}..."
|
22
|
+
|
23
|
+
connection.on_tcp_connection_loss do |conn, _settings|
|
24
|
+
OmniLog::info '[network failure] Trying to reconnect...'
|
25
|
+
conn.reconnect(false, 30)
|
26
|
+
end
|
27
|
+
|
28
|
+
mq = AMQP::Channel.new(connection)
|
29
|
+
exchange = mq.direct(Helpers::amqp_exchange_name)
|
30
|
+
queue = mq.queue('', exclusive: true).bind(exchange, routing_key: Helpers::amqp_routing_key)
|
31
|
+
|
32
|
+
OmniLog::info 'Setup omnibot...'
|
33
|
+
@omnibot = JabberBot.new(Jabber::JID::new(@config['omnibotuser']), @config['omnibotpass'])
|
34
|
+
@omnibot.timer_provider = EM
|
35
|
+
@omnibot.set_subscriber Jabber::JID::new(@config['notifyjid']), @config['notifyresource']
|
36
|
+
@omnibot.connect
|
37
|
+
|
38
|
+
@handlers.each_with_index do |handler, index|
|
39
|
+
OmniLog::info "Setup handler #{handler}..."
|
40
|
+
handler.timer_provider = EM
|
41
|
+
handler.jabber_messenger { |message| send_message message }
|
42
|
+
handler.startup_pause = index * 10
|
43
|
+
handler.start
|
44
|
+
end
|
45
|
+
|
46
|
+
OmniLog::info '==== AMQP is ready ===='
|
47
|
+
|
48
|
+
queue.subscribe do |msg|
|
49
|
+
message = Marshal.load(Base64.decode64(msg)).force_encoding('UTF-8')
|
50
|
+
send_message message
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Main AMQP loop
|
56
|
+
def start
|
57
|
+
# exit hook
|
58
|
+
Signal.trap('INT') do
|
59
|
+
OmniLog::info "It's a trap, should exit..."
|
60
|
+
AMQP.stop { EM.stop }
|
61
|
+
end
|
62
|
+
|
63
|
+
begin
|
64
|
+
exception_cb = proc { |e| OmniLog::error "Cannot connect to AMQP: #{e.message}" }
|
65
|
+
Retryable.retryable(tries: 5, sleep: ->(n) { 3**n }, exception_cb: exception_cb, on: AMQP::TCPConnectionFailed) do
|
66
|
+
amqp_loop
|
67
|
+
end
|
68
|
+
rescue => e
|
69
|
+
OmniLog::error "AMQP/Jabber setup error: #{e.message}\ntrace:\n#{Helpers::backtrace e}\nExiting..."
|
70
|
+
AMQP.stop { EM.stop }
|
71
|
+
end
|
72
|
+
|
73
|
+
OmniLog::info 'Exited'
|
74
|
+
end
|
75
|
+
end
|
75
76
|
end
|
76
|
-
|
data/lib/omnibot/helpers.rb
CHANGED
@@ -1,71 +1,71 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module OmniBot
|
4
|
+
class OmniLog
|
5
|
+
def self.init_log
|
6
|
+
logger = Logger.new('omnibot.log')
|
7
|
+
logger.level = Logger::DEBUG
|
8
|
+
logger
|
9
|
+
end
|
4
10
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
logger = Logger.new('omnibot.log')
|
9
|
-
logger.level = Logger::DEBUG
|
10
|
-
logger
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.log=(value)
|
14
|
-
@logger = value
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.log
|
18
|
-
@logger
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.debug(progname = nil, &block); @logger.debug(progname, &block); end
|
22
|
-
def self.info(progname = nil, &block); @logger.info(progname, &block); end
|
23
|
-
def self.warn(progname = nil, &block); @logger.warn(progname, &block); end
|
24
|
-
def self.error(progname = nil, &block); @logger.error(progname, &block); end
|
25
|
-
def self.fatal(progname = nil, &block); @logger.fatal(progname, &block); end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Helper class for counting reconnect attempts
|
29
|
-
class AttemptCounter
|
30
|
-
def report
|
31
|
-
OmniLog::debug "AttemptCounter: try #{@counter} of #{@max_attempts}"
|
32
|
-
end
|
33
|
-
public
|
34
|
-
def initialize max_attempts
|
35
|
-
@counter = 0
|
36
|
-
@max_attempts = max_attempts
|
37
|
-
OmniLog::debug "AttemptCounter inited"
|
38
|
-
end
|
39
|
-
|
40
|
-
def out_of_attempts?
|
41
|
-
@counter >= @max_attempts
|
42
|
-
end
|
43
|
-
|
44
|
-
def increase
|
45
|
-
@counter += 1
|
46
|
-
report
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
class Helpers
|
51
|
-
def self.backtrace e
|
52
|
-
e.respond_to?(:backtrace) && e.backtrace ? e.backtrace.join("\n\t") : ""
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.same_day? t1, t2
|
56
|
-
t1.year == t2.year && t1.month == t2.month && t1.day == t2.day
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.amqp_exchange_name
|
60
|
-
'omnibot-exchange'
|
61
|
-
end
|
62
|
-
|
63
|
-
def self.amqp_routing_key
|
64
|
-
'omnibot-routing'
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|
11
|
+
def self.log=(value)
|
12
|
+
@logger = value
|
13
|
+
end
|
68
14
|
|
69
|
-
|
15
|
+
def self.log
|
16
|
+
@logger
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.debug(progname = nil, &block); @logger.debug(progname, &block); end
|
20
|
+
|
21
|
+
def self.info(progname = nil, &block); @logger.info(progname, &block); end
|
22
|
+
|
23
|
+
def self.warn(progname = nil, &block); @logger.warn(progname, &block); end
|
24
|
+
|
25
|
+
def self.error(progname = nil, &block); @logger.error(progname, &block); end
|
26
|
+
|
27
|
+
def self.fatal(progname = nil, &block); @logger.fatal(progname, &block); end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Helper class for counting reconnect attempts
|
31
|
+
class AttemptCounter
|
32
|
+
def report
|
33
|
+
OmniLog::debug "AttemptCounter: try #{@counter} of #{@max_attempts}"
|
34
|
+
end
|
70
35
|
|
36
|
+
public
|
71
37
|
|
38
|
+
def initialize(max_attempts)
|
39
|
+
@counter = 0
|
40
|
+
@max_attempts = max_attempts
|
41
|
+
OmniLog::debug 'AttemptCounter inited'
|
42
|
+
end
|
43
|
+
|
44
|
+
def out_of_attempts?
|
45
|
+
@counter >= @max_attempts
|
46
|
+
end
|
47
|
+
|
48
|
+
def increase
|
49
|
+
@counter += 1
|
50
|
+
report
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Helpers
|
55
|
+
def self.backtrace(e)
|
56
|
+
e.respond_to?(:backtrace) && e.backtrace ? e.backtrace.join("\n\t") : ''
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.same_day?(t1, t2)
|
60
|
+
t1.year == t2.year && t1.month == t2.month && t1.day == t2.day
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.amqp_exchange_name
|
64
|
+
'omnibot-exchange'
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.amqp_routing_key
|
68
|
+
'omnibot-routing'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/omnibot/jabberbot.rb
CHANGED
@@ -1,209 +1,202 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module OmniBot
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
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
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
msg = Jabber::Message::new(@subscriber_concrete_jid, body)
|
203
|
-
msg.type = :chat
|
204
|
-
@client.send(msg)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
4
|
+
# Jabber bot with reconnection and dnd-care logic
|
5
|
+
class JabberBot
|
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})" : '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 needed_user?(jid)
|
15
|
+
jid.strip == @subscriber && @subscriber_resource.match((jid.resource || ''))
|
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
|
+
return unless needed_user? old_presence.from
|
21
|
+
@subscriber_online = check_presence? old_presence
|
22
|
+
@subscriber_concrete_jid = old_presence.from
|
23
|
+
OmniLog::debug "Subscriber #{@subscriber} is #{@subscriber_online ? 'ready' : 'not ready'}"
|
24
|
+
pump_messages if @subscriber_online
|
25
|
+
|
26
|
+
unless @greeting_done
|
27
|
+
@greeting_done = true
|
28
|
+
add_message [Time.now, 'Hello, I am online']
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_subscripton_request_callback(item, pres)
|
33
|
+
OmniLog::debug "Subscription request item=#{item} pres=#{dump_presence pres}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_exception_handler(e, stream, sym_where)
|
37
|
+
OmniLog::error "Jabber exception of #{e ? e.class : nil} happens at symbol \"#{sym_where}\": #{e}\nbacktrace\n#{Helpers::backtrace e}"
|
38
|
+
OmniLog::debug "stream is #{stream} vs client #{@client}"
|
39
|
+
on_generic_exception_handler e
|
40
|
+
end
|
41
|
+
|
42
|
+
def safe_reconnect
|
43
|
+
reconnect
|
44
|
+
rescue Jabber::ClientAuthenticationFailure => e
|
45
|
+
OmniLog::error "Authentification error: #{e.class}: #{e}"
|
46
|
+
raise
|
47
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
48
|
+
# needed to handle all errors from xmpp
|
49
|
+
OmniLog::error "Reconnect hard error: #{e.class}: #{e}"
|
50
|
+
on_generic_exception_handler e
|
51
|
+
end
|
52
|
+
|
53
|
+
def on_generic_exception_handler(e)
|
54
|
+
if e && (e.is_a?(Jabber::ServerDisconnected) || e.class.to_s =~ /^Errno::.+/ || e.is_a?(SocketError))
|
55
|
+
OmniLog::warn "Looking to error, ign=#{@ignore_reconnect}, tp=#{@timer_provider}"
|
56
|
+
OmniLog::error 'No timer provider assigned' unless @timer_provider
|
57
|
+
# attempt counter is set when it's needed to connect
|
58
|
+
unless @ignore_reconnect
|
59
|
+
@timer_provider.add_timer(@reconnect_pause) { try_reconnect }
|
60
|
+
end
|
61
|
+
else
|
62
|
+
OmniLog::warn "Ignoring error #{e}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def reconnect
|
67
|
+
OmniLog::debug 'Going to reconnect'
|
68
|
+
@client.connect
|
69
|
+
@client.auth(@password)
|
70
|
+
@client.send(Jabber::Presence.new.set_type(:available))
|
71
|
+
end
|
72
|
+
|
73
|
+
def try_reconnect
|
74
|
+
OmniLog::debug "Called try_reconnect, #{@client.inspect}, #{@client.is_connected?}"
|
75
|
+
return if @client.is_connected?
|
76
|
+
|
77
|
+
OmniLog::debug 'Called try_reconnect'
|
78
|
+
|
79
|
+
@attempt_counter = AttemptCounter.new(5) unless @attempt_counter
|
80
|
+
@attempt_counter.increase
|
81
|
+
|
82
|
+
if @attempt_counter.out_of_attempts?
|
83
|
+
OmniLog::warn "Can't reconect too often, sleep for #{@reconnect_long_pause / 60} minutes..."
|
84
|
+
@attempt_counter = nil
|
85
|
+
@ignore_reconnect = true
|
86
|
+
@timer_provider.add_timer(@reconnect_long_pause) do
|
87
|
+
@ignore_reconnect = false
|
88
|
+
try_reconnect
|
89
|
+
end
|
90
|
+
return
|
91
|
+
end
|
92
|
+
|
93
|
+
safe_reconnect
|
94
|
+
|
95
|
+
if @client.is_connected?
|
96
|
+
@attempt_counter = nil
|
97
|
+
@roster = Jabber::Roster::Helper.new(@client)
|
98
|
+
@roster.add_subscription_request_callback { |item, pres| on_subscripton_request_callback item, pres }
|
99
|
+
end
|
100
|
+
|
101
|
+
OmniLog::debug "Client #{@client.is_connected? ? 'is' : 'isn\'t'} connected"
|
102
|
+
end
|
103
|
+
|
104
|
+
def check_presence?(presence)
|
105
|
+
raise 'No subscriber' unless @subscriber
|
106
|
+
|
107
|
+
if presence.type.nil?
|
108
|
+
OmniLog::debug "Subscriber status #{presence.show ? presence.show : 'online'}"
|
109
|
+
return presence.show.nil? || presence.show == :chat
|
110
|
+
elsif presence.type == :unavailable
|
111
|
+
OmniLog::debug 'Subscriber goes offline'
|
112
|
+
return false
|
113
|
+
else
|
114
|
+
return false
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def say_when_human(orig, now)
|
119
|
+
if Helpers::same_day? now, orig
|
120
|
+
amount = now - orig
|
121
|
+
if amount < 60
|
122
|
+
return 'just now'
|
123
|
+
elsif amount < 60 * 60
|
124
|
+
return 'less than a hour ago'
|
125
|
+
elsif amount < 60 * 60 * 2
|
126
|
+
return ' two hours ago'
|
127
|
+
elsif amount < 60 * 60 * 6
|
128
|
+
return amount.div(3600).to_s + ' hours ago'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
orig.to_s
|
132
|
+
end
|
133
|
+
|
134
|
+
def pump_messages
|
135
|
+
while (msg = @messages.shift)
|
136
|
+
send msg
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
public
|
141
|
+
|
142
|
+
attr_writer :timer_provider
|
143
|
+
|
144
|
+
def initialize(jid, password)
|
145
|
+
@client = Jabber::Client::new(jid)
|
146
|
+
@password = password
|
147
|
+
raise 'No jid set' if jid.empty?
|
148
|
+
raise 'No password set' unless password
|
149
|
+
|
150
|
+
@ignore_reconnect = false
|
151
|
+
@reconnect_pause = 10
|
152
|
+
@reconnect_long_pause = 60 * 15
|
153
|
+
|
154
|
+
@messages = []
|
155
|
+
@subscriber_online = false
|
156
|
+
@subscriber_concrete_jid = nil
|
157
|
+
|
158
|
+
@client.on_exception { |e, stream, sym_where| on_exception_handler(e, stream, sym_where) }
|
159
|
+
@client.add_message_callback { |m| on_message_handler m }
|
160
|
+
@client.add_presence_callback { |from, to| on_presence_callback from, to }
|
161
|
+
end
|
162
|
+
|
163
|
+
def connect
|
164
|
+
try_reconnect
|
165
|
+
end
|
166
|
+
|
167
|
+
def disconnect
|
168
|
+
@client.close
|
169
|
+
end
|
170
|
+
|
171
|
+
def set_subscriber(jid, resource = nil)
|
172
|
+
@subscriber = jid
|
173
|
+
if resource.nil? || resource == ''
|
174
|
+
@subscriber_resource = /.*/
|
175
|
+
else
|
176
|
+
@subscriber_resource = Regexp.new(resource)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def add_message(message)
|
181
|
+
OmniLog::debug 'Register a message, ' + (@subscriber_online ? 'should send immediately' : 'will send later')
|
182
|
+
@messages << message
|
183
|
+
pump_messages if @subscriber_online
|
184
|
+
end
|
185
|
+
|
186
|
+
def send(message)
|
187
|
+
raise 'Not connected' unless @client.is_connected?
|
188
|
+
raise 'No concrete jid' unless @subscriber_concrete_jid
|
189
|
+
|
190
|
+
OmniLog::info 'Sending a message...'
|
191
|
+
orig = message[0]
|
192
|
+
content = message[1]
|
193
|
+
|
194
|
+
body = 'Omnibot reported ' + say_when_human(orig, Time.now) + ":\n" + content.to_s
|
195
|
+
OmniLog::debug body
|
196
|
+
|
197
|
+
msg = Jabber::Message::new(@subscriber_concrete_jid, body)
|
198
|
+
msg.type = :chat
|
199
|
+
@client.send(msg)
|
200
|
+
end
|
201
|
+
end
|
208
202
|
end
|
209
|
-
|