palbo-lijab 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/lijab +9 -0
- data/ext/extconf.rb +20 -0
- data/ext/readline_extra.c +172 -0
- data/lib/lijab/commands/contacts.rb +101 -0
- data/lib/lijab/commands/options.rb +49 -0
- data/lib/lijab/commands/simple.rb +132 -0
- data/lib/lijab/commands/status.rb +63 -0
- data/lib/lijab/commands/subscription.rb +78 -0
- data/lib/lijab/commands.rb +139 -0
- data/lib/lijab/config.rb +174 -0
- data/lib/lijab/contacts.rb +318 -0
- data/lib/lijab/history.rb +122 -0
- data/lib/lijab/hooks.rb +109 -0
- data/lib/lijab/input.rb +234 -0
- data/lib/lijab/main.rb +246 -0
- data/lib/lijab/out.rb +173 -0
- data/lib/lijab/term/ansi.rb +20 -0
- data/lib/lijab/version.rb +4 -0
- data/lib/lijab/xmpp4r/message.rb +45 -0
- data/lib/lijab.rb +7 -0
- data/lib/readline/extra.rb +7 -0
- metadata +102 -0
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
class File
|
4
|
+
include File::Tail
|
5
|
+
end
|
6
|
+
|
7
|
+
module Lijab
|
8
|
+
|
9
|
+
module HistoryHandler
|
10
|
+
class DummyHistory
|
11
|
+
def log(*a)
|
12
|
+
end
|
13
|
+
|
14
|
+
def last(*a)
|
15
|
+
Out::put("warning: logs are disabled")
|
16
|
+
[]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class History
|
21
|
+
MEMORY_LOG_LENGTH = 50
|
22
|
+
|
23
|
+
def initialize(path, target=nil, log_to_session=false)
|
24
|
+
@path, @target, @log_to_session = path, target, log_to_session
|
25
|
+
@m = []
|
26
|
+
end
|
27
|
+
|
28
|
+
def init_logfile
|
29
|
+
@w = File.open(@path, 'a')
|
30
|
+
@r = File.open(@path, 'r')
|
31
|
+
@r.return_if_eof = true
|
32
|
+
end
|
33
|
+
|
34
|
+
def log(msg, direction, target=nil)
|
35
|
+
init_logfile() unless @w
|
36
|
+
|
37
|
+
time = Time.now.utc
|
38
|
+
target ||= @target
|
39
|
+
arrow = direction == :from ? "<-" : "->"
|
40
|
+
quoted = [msg].pack("M").gsub(/=?\n/) { |m| m[0] == ?= ? "" : "=0A" }
|
41
|
+
|
42
|
+
@w.puts("#{time.iso8601} #{target} #{arrow} #{quoted}")
|
43
|
+
@w.flush
|
44
|
+
|
45
|
+
@m.push({:time=>time.localtime, :target=>target, :direction=>direction, :msg=>msg})
|
46
|
+
@m.shift if @m.length > MEMORY_LOG_LENGTH
|
47
|
+
|
48
|
+
@m = []
|
49
|
+
|
50
|
+
HistoryHandler::log(msg, direction, target) if @log_to_session
|
51
|
+
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def last(n)
|
56
|
+
return [] if n <= 0
|
57
|
+
|
58
|
+
init_logfile() unless @r
|
59
|
+
|
60
|
+
if n <= @m.length
|
61
|
+
@m[-n..-1]
|
62
|
+
else
|
63
|
+
ret = []
|
64
|
+
@r.seek(0, File::SEEK_END)
|
65
|
+
@r.backward(n)
|
66
|
+
@r.tail(n-@m.length) do |l|
|
67
|
+
time, target, direction, msg = l.split(" ", 4)
|
68
|
+
ret << {:time => Time.parse(time).localtime,
|
69
|
+
:target => target,
|
70
|
+
:direction => direction == "<-" ? :from : :to,
|
71
|
+
:msg => msg.strip.unpack("M").first}
|
72
|
+
end
|
73
|
+
ret += @m
|
74
|
+
if @m.length < MEMORY_LOG_LENGTH
|
75
|
+
@m = (ret[0...n-@m.length] + @m)
|
76
|
+
@m = @m[-MEMORY_LOG_LENGTH..-1] if @m.length > MEMORY_LOG_LENGTH
|
77
|
+
end
|
78
|
+
ret
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
module_function
|
84
|
+
|
85
|
+
@histories = {}
|
86
|
+
|
87
|
+
def get(jid)
|
88
|
+
name = jid.strip.to_s
|
89
|
+
if Config.account[:log]
|
90
|
+
path = File.join(Config.account[:log_dir], "#{name}.log")
|
91
|
+
@histories[name] ||= History.new(path, name, true)
|
92
|
+
else
|
93
|
+
@dummy ||= DummyHistory.new
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def log(msg, direction, target)
|
98
|
+
return unless Config.account[:log]
|
99
|
+
|
100
|
+
init_session_log() unless @session
|
101
|
+
@session.log(msg, direction, target)
|
102
|
+
end
|
103
|
+
|
104
|
+
def last(n)
|
105
|
+
unless Config.account[:log]
|
106
|
+
Out::put("warning: logs are disabled")
|
107
|
+
return []
|
108
|
+
end
|
109
|
+
|
110
|
+
init_session_log() unless @session
|
111
|
+
@session.last(n)
|
112
|
+
end
|
113
|
+
|
114
|
+
def init_session_log
|
115
|
+
return unless Config.account[:log]
|
116
|
+
|
117
|
+
@session = History.new(path = File.join(Config.account[:log_dir], "session.log"))
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
data/lib/lijab/hooks.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
|
2
|
+
module Lijab
|
3
|
+
|
4
|
+
module HooksHandler
|
5
|
+
module_function
|
6
|
+
|
7
|
+
@on_connect = []
|
8
|
+
@on_disconnect = []
|
9
|
+
@on_incoming_message = []
|
10
|
+
@on_presence = []
|
11
|
+
@on_pre_send_message = []
|
12
|
+
@on_post_send_message = []
|
13
|
+
|
14
|
+
def init
|
15
|
+
@on_connect, @on_disconnect, @on_incoming_message, @on_presence = [], [], [], []
|
16
|
+
@on_pre_send_message, @on_post_send_message = [], []
|
17
|
+
|
18
|
+
Dir[File.join(Config.dirs[:hooks], '**', '*.rb')].each { |f| load f }
|
19
|
+
|
20
|
+
Main.client.add_message_callback(&method(:handle_message))
|
21
|
+
Main.contacts.roster.add_presence_callback(&method(:handle_presence))
|
22
|
+
end
|
23
|
+
|
24
|
+
def handle_message(msg)
|
25
|
+
return unless msg.body && !msg.body.empty?
|
26
|
+
|
27
|
+
@on_incoming_message.each do |b|
|
28
|
+
b.call(Main.contacts[msg.from.strip], msg.body)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def handle_presence(roster_item, old_p, new_p)
|
33
|
+
@on_presence.each do |b|
|
34
|
+
b.call(Main.contacts[roster_item.jid.strip], old_p, new_p)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def handle_pre_send_message(contact, msg)
|
39
|
+
return msg if @on_pre_send_message.empty? || !msg.body || msg.body.empty?
|
40
|
+
|
41
|
+
@on_pre_send_message.inject(msg) do |ret_msg, block|
|
42
|
+
args = [contact, ret_msg.body]
|
43
|
+
args.push(msg) if block.arity == 3
|
44
|
+
|
45
|
+
m = block.call(*args)
|
46
|
+
break if !m
|
47
|
+
|
48
|
+
if m.is_a?(Jabber::Message)
|
49
|
+
m
|
50
|
+
else
|
51
|
+
ret_msg.body = m.to_s
|
52
|
+
ret_msg
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def handle_post_send_message(contact, msg)
|
58
|
+
return if !msg.body || msg.body.empty?
|
59
|
+
|
60
|
+
@on_post_send_message.each do |block|
|
61
|
+
args = [contact, msg.body]
|
62
|
+
args.push(msg) if block.arity == 3
|
63
|
+
block.call(*args)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def handle_connect
|
68
|
+
@on_connect.each { |b| b.call }
|
69
|
+
end
|
70
|
+
|
71
|
+
def handle_disconnect
|
72
|
+
@on_disconnect.each { |b| b.call }
|
73
|
+
end
|
74
|
+
|
75
|
+
attr_reader :on_connect, :on_disconnect, :on_incoming_message, :on_presence,
|
76
|
+
:on_pre_send_message, :on_post_send_message
|
77
|
+
module_function :on_connect, :on_disconnect, :on_incoming_message,:on_presence,
|
78
|
+
:on_pre_send_message, :on_post_send_message
|
79
|
+
end
|
80
|
+
|
81
|
+
module Hooks
|
82
|
+
module_function
|
83
|
+
|
84
|
+
def on_incoming_message(&block)
|
85
|
+
HooksHandler::on_incoming_message.push(block)
|
86
|
+
end
|
87
|
+
|
88
|
+
def on_presence(&block)
|
89
|
+
HooksHandler::on_presence.push(block)
|
90
|
+
end
|
91
|
+
|
92
|
+
def on_pre_send_message(&block)
|
93
|
+
HooksHandler::on_pre_send_message.push(block)
|
94
|
+
end
|
95
|
+
|
96
|
+
def on_post_send_message(&block)
|
97
|
+
HooksHandler::on_post_send_message.push(block)
|
98
|
+
end
|
99
|
+
|
100
|
+
def on_connect(&block)
|
101
|
+
HooksHandler::on_connect.push(block)
|
102
|
+
end
|
103
|
+
|
104
|
+
def on_disconnect(&block)
|
105
|
+
HooksHandler::on_disconnect.push(block)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
data/lib/lijab/input.rb
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
require 'readline'
|
2
|
+
require 'readline/extra'
|
3
|
+
|
4
|
+
module Lijab
|
5
|
+
|
6
|
+
module InputHandler
|
7
|
+
|
8
|
+
DEFAULT_PROMPT = "> "
|
9
|
+
|
10
|
+
@prompt = DEFAULT_PROMPT
|
11
|
+
@last_to = ""
|
12
|
+
@last_typed = ""
|
13
|
+
@multiline = false
|
14
|
+
@multilines = []
|
15
|
+
|
16
|
+
module_function
|
17
|
+
|
18
|
+
def init
|
19
|
+
Readline::completer_word_break_characters = ""
|
20
|
+
Readline::completion_append_character = " "
|
21
|
+
Readline::completion_proc = method(:completer).to_proc
|
22
|
+
Readline::pre_input_proc = lambda do
|
23
|
+
print "#{ANSI.cleartoeol}" ; STDOUT.flush
|
24
|
+
unless @last_to.empty?
|
25
|
+
Readline::insert_text("#{@last_to}: ")
|
26
|
+
Readline::redisplay
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
if Config.opts[:ctrl_c_quits]
|
31
|
+
trap("SIGINT") { Main.quit }
|
32
|
+
else
|
33
|
+
trap("SIGINT") do
|
34
|
+
Readline::line_buffer = ""
|
35
|
+
puts
|
36
|
+
Out::make_infoline
|
37
|
+
print "#{@prompt}"
|
38
|
+
STDOUT.flush
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
read_typed_history()
|
43
|
+
|
44
|
+
init_char_input_stuff()
|
45
|
+
|
46
|
+
@input_thread = Thread.new { read_input() }
|
47
|
+
end
|
48
|
+
|
49
|
+
def prompt(p=nil)
|
50
|
+
return @prompt unless p
|
51
|
+
@prompt = p
|
52
|
+
end
|
53
|
+
|
54
|
+
def reset_prompt
|
55
|
+
@prompt = DEFAULT_PROMPT
|
56
|
+
end
|
57
|
+
|
58
|
+
def init_char_input_stuff
|
59
|
+
# i'm surprised this doesn't make typing fucking unbearable
|
60
|
+
|
61
|
+
@on_char_input_blocks = []
|
62
|
+
|
63
|
+
@on_char_input_blocks << lambda do |c|
|
64
|
+
to, msg = Readline::line_buffer.split(":", 2).strip
|
65
|
+
if to && msg && Main.contacts.key?(to)
|
66
|
+
# TODO: try to see if a thread improves things
|
67
|
+
Main.contacts[to].typed_stuff
|
68
|
+
end
|
69
|
+
c
|
70
|
+
end
|
71
|
+
|
72
|
+
Readline::char_input_proc = lambda do |c|
|
73
|
+
ret = c
|
74
|
+
@on_char_input_blocks.each do |block|
|
75
|
+
ret = block.call(c)
|
76
|
+
break if ret != c
|
77
|
+
end
|
78
|
+
ret
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def on_char_input(&block)
|
83
|
+
@on_char_input_blocks << block
|
84
|
+
end
|
85
|
+
|
86
|
+
#def composing_watcher
|
87
|
+
# timer = nil
|
88
|
+
# loop do
|
89
|
+
# sleep(1)
|
90
|
+
|
91
|
+
# buf = Readline::line_buffer
|
92
|
+
# next unless buf != @last_line
|
93
|
+
|
94
|
+
# @last_line = buf
|
95
|
+
# to, msg = buf.split(":", 2).strip
|
96
|
+
|
97
|
+
# next unless to && msg && Main.contacts.key?(to)
|
98
|
+
# end
|
99
|
+
#end
|
100
|
+
|
101
|
+
def read_input
|
102
|
+
loop do
|
103
|
+
Out::make_infoline
|
104
|
+
|
105
|
+
t = Readline::readline(@prompt, true)
|
106
|
+
|
107
|
+
@last_typed = t || ""
|
108
|
+
|
109
|
+
if !t
|
110
|
+
if @multiline
|
111
|
+
@last_typed = @multilines
|
112
|
+
process_input(@multilines.join("\n"))
|
113
|
+
multiline(false)
|
114
|
+
else
|
115
|
+
if Config.opts[:ctrl_c_quits]
|
116
|
+
puts ; next
|
117
|
+
else
|
118
|
+
Main.quit
|
119
|
+
end
|
120
|
+
end
|
121
|
+
elsif !@multiline && t =~ /^\s*$/
|
122
|
+
Readline::HISTORY.pop
|
123
|
+
else
|
124
|
+
Readline::HISTORY.pop if Readline::HISTORY.to_a[-2] == t
|
125
|
+
|
126
|
+
if @multiline
|
127
|
+
@multilines.push(t)
|
128
|
+
@last_typed = @multilines
|
129
|
+
else
|
130
|
+
process_input(t)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def process_input(text)
|
137
|
+
return if text.empty?
|
138
|
+
|
139
|
+
if !Main.connected
|
140
|
+
# FIXME: brute force ftw!
|
141
|
+
Out::error("not connected :-(", false)
|
142
|
+
return
|
143
|
+
end
|
144
|
+
|
145
|
+
if text[0] == ?/
|
146
|
+
Commands::run(*text[1..-1].split(" ", 2))
|
147
|
+
@last_to = ""
|
148
|
+
else
|
149
|
+
to, msg = text.split(":", 2)
|
150
|
+
return unless to && msg && !msg.empty? && Main.contacts.key?(to)
|
151
|
+
msg = msg[1..-1] if msg[0].chr == " " # goddammit, whitespace will be the death of me
|
152
|
+
|
153
|
+
@last_to = to
|
154
|
+
jid = Jabber::JID.new(to)
|
155
|
+
jid = nil unless jid.resource
|
156
|
+
Main.contacts[to].send_message(msg, jid)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def delete_last_typed
|
161
|
+
if @last_typed.is_a?(Array)
|
162
|
+
@last_typed.each do |line|
|
163
|
+
# line length + multiline prompt + \n
|
164
|
+
# FIXME: put the multiline prompt somewhere
|
165
|
+
print "\b" * (line.length + 6)
|
166
|
+
print "#{ANSIMove.up(1)}"
|
167
|
+
end
|
168
|
+
print "#{ANSIMove.down(1)}" if @last_typed.length > 0
|
169
|
+
else
|
170
|
+
print "\b" * @last_typed.length
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def delete_typed
|
175
|
+
if @multiline
|
176
|
+
delete_last_typed()
|
177
|
+
else
|
178
|
+
print "\b" * Readline::line_buffer.length
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def redisplay_input()
|
183
|
+
if @multiline && !@multilines.empty?
|
184
|
+
puts "#{ANSI.clearline}#{DEFAULT_PROMPT}#{@multilines[0]}"
|
185
|
+
@multilines[1..-1].each do |line|
|
186
|
+
puts "#{ANSI.clearline}#{@prompt}#{line}"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
Out::make_infoline()
|
191
|
+
print "#{@prompt}#{Readline::line_buffer}"
|
192
|
+
STDOUT.flush
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
def completer(line)
|
197
|
+
return if !Main.connected
|
198
|
+
|
199
|
+
if line[0] == ?/
|
200
|
+
Commands::completer(line)
|
201
|
+
else
|
202
|
+
Main.contacts.completer(line)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def save_typed_history
|
207
|
+
File.open(Config.account[:typed], 'w') do |f|
|
208
|
+
f.puts(Readline::HISTORY.to_a[-300..-1] || Readline::HISTORY.to_a)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def read_typed_history
|
213
|
+
path = Config.account[:typed]
|
214
|
+
File.read(path).each { |l| Readline::HISTORY.push(l.chomp) } if File.file?(path)
|
215
|
+
end
|
216
|
+
|
217
|
+
def multiline?
|
218
|
+
@multiline
|
219
|
+
end
|
220
|
+
|
221
|
+
def multiline(enable, first_line="")
|
222
|
+
@multiline = enable
|
223
|
+
@multilines = []
|
224
|
+
if enable
|
225
|
+
@multilines.push(first_line) unless first_line.empty?
|
226
|
+
prompt("---> ")
|
227
|
+
else
|
228
|
+
reset_prompt()
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
|
data/lib/lijab/main.rb
ADDED
@@ -0,0 +1,246 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'file/tail'
|
3
|
+
require 'monitor'
|
4
|
+
require 'optparse'
|
5
|
+
require 'term/ansicolor'
|
6
|
+
require 'xmpp4r'
|
7
|
+
require 'xmpp4r/roster'
|
8
|
+
require 'yaml'
|
9
|
+
|
10
|
+
require 'lijab/commands'
|
11
|
+
require 'lijab/config'
|
12
|
+
require 'lijab/contacts'
|
13
|
+
require 'lijab/history'
|
14
|
+
require 'lijab/hooks'
|
15
|
+
require 'lijab/input'
|
16
|
+
require 'lijab/out'
|
17
|
+
require 'lijab/version'
|
18
|
+
require 'lijab/xmpp4r/message'
|
19
|
+
|
20
|
+
include Term
|
21
|
+
|
22
|
+
|
23
|
+
class String
|
24
|
+
include ANSIColor
|
25
|
+
|
26
|
+
def colored(*colors)
|
27
|
+
s = self
|
28
|
+
colors.each { |c| s = s.send(c) }
|
29
|
+
s
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Array
|
34
|
+
def strip
|
35
|
+
self.map { |s| s.strip }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
Thread.abort_on_exception = true
|
40
|
+
|
41
|
+
module Lijab
|
42
|
+
|
43
|
+
module Main
|
44
|
+
module_function
|
45
|
+
|
46
|
+
@monitor = Monitor.new
|
47
|
+
|
48
|
+
def run!
|
49
|
+
args = parse_args()
|
50
|
+
Jabber::debug = args[:debug]
|
51
|
+
|
52
|
+
Config::init(args)
|
53
|
+
read_saved_session()
|
54
|
+
|
55
|
+
@connected = false
|
56
|
+
|
57
|
+
print ANSI.title("lijab -- #{Config.jid.strip}") ; STDOUT.flush
|
58
|
+
|
59
|
+
begin
|
60
|
+
setup_client()
|
61
|
+
rescue SystemCallError, SocketError
|
62
|
+
Out::error("couldn't connect")
|
63
|
+
reconnect()
|
64
|
+
end
|
65
|
+
|
66
|
+
Commands::init
|
67
|
+
InputHandler::init
|
68
|
+
end
|
69
|
+
|
70
|
+
def setup_after_connect
|
71
|
+
HooksHandler::init
|
72
|
+
end
|
73
|
+
|
74
|
+
def setup_client
|
75
|
+
return unless @monitor.try_enter
|
76
|
+
begin
|
77
|
+
@client = Jabber::Client.new(Config.jid)
|
78
|
+
|
79
|
+
@client.on_exception do |e,stream,from|
|
80
|
+
@connected = false
|
81
|
+
|
82
|
+
case from
|
83
|
+
when :disconnected
|
84
|
+
Out::error("disconnected")
|
85
|
+
HooksHandler::handle_disconnect
|
86
|
+
reconnect()
|
87
|
+
else
|
88
|
+
# death before lost messages!
|
89
|
+
raise e || "exception raised from #{from}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
@client.add_message_callback do |msg|
|
94
|
+
if Main.contacts.key?(msg.from)
|
95
|
+
Main.contacts[msg.from].handle_message(msg)
|
96
|
+
else
|
97
|
+
Main.contacts.handle_non_contact_message(msg)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
Out::put("connecting...".yellow, true)
|
102
|
+
|
103
|
+
@client.use_ssl = Config.account[:use_ssl]
|
104
|
+
@client.connect(Config.account[:server], Config.account[:port])
|
105
|
+
|
106
|
+
loop do
|
107
|
+
begin
|
108
|
+
if !Config.account[:password]
|
109
|
+
print "#{Config.account[:name]} account password: "
|
110
|
+
system("stty -echo") # FIXME
|
111
|
+
STDIN.read_nonblock(9999999) rescue nil
|
112
|
+
Config.account[:password] = gets.chomp
|
113
|
+
system("stty echo")
|
114
|
+
puts
|
115
|
+
end
|
116
|
+
|
117
|
+
@client.auth(Config.account[:password])
|
118
|
+
break
|
119
|
+
rescue Jabber::ClientAuthenticationFailure
|
120
|
+
Out::error("couldn't authenticate: wrong password?", false)
|
121
|
+
Config.account[:password] = nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
@contacts = Contacts::Contacts.new(Jabber::Roster::Helper.new(@client))
|
126
|
+
@client.send(@presence)
|
127
|
+
@connected = true
|
128
|
+
|
129
|
+
setup_after_connect()
|
130
|
+
HooksHandler::handle_connect
|
131
|
+
|
132
|
+
Out::put("connected!".green, true)
|
133
|
+
ensure
|
134
|
+
@monitor.exit
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def reconnect
|
139
|
+
do_sleep = 1
|
140
|
+
loop do
|
141
|
+
do_sleep.downto(1) do |i|
|
142
|
+
Out::infoline("trying reconnect in #{i*5} seconds...")
|
143
|
+
sleep(5)
|
144
|
+
end
|
145
|
+
do_sleep = [do_sleep*2, 10].min
|
146
|
+
|
147
|
+
begin
|
148
|
+
setup_client()
|
149
|
+
Out::clear_infoline
|
150
|
+
break
|
151
|
+
rescue SystemCallError, SocketError
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def set_status(status, msg=nil)
|
157
|
+
type = status == :invisible ? :unavailable : nil
|
158
|
+
priority = Config.opts[:status_priorities][status]
|
159
|
+
status = nil if [:available, :invisible].include?(status)
|
160
|
+
|
161
|
+
@presence.set_type(type).set_show(status).set_status(msg).set_priority(priority)
|
162
|
+
|
163
|
+
@client.send(@presence)
|
164
|
+
end
|
165
|
+
|
166
|
+
def clear_status_message
|
167
|
+
set_status(@status)
|
168
|
+
end
|
169
|
+
|
170
|
+
def set_priority(priority)
|
171
|
+
@client.send(@presence.set_priority(priority))
|
172
|
+
end
|
173
|
+
|
174
|
+
def parse_args
|
175
|
+
options = {:debug => false}
|
176
|
+
begin
|
177
|
+
op = OptionParser.new do |opts|
|
178
|
+
opts.banner = "usage: lijab [-h | -V | [-a ACCOUNTNAME] [-d BASEDIR] [-D]]\n\n"
|
179
|
+
opts.on("-D", "--[no-]debug",
|
180
|
+
"output xmpp debug information to stderr") { |v| options[:debug] = v }
|
181
|
+
opts.on("-d", "--basedir BASEDIR",
|
182
|
+
"configs base directory") { |v| options[:basedir] = v }
|
183
|
+
opts.on("-a", "--account ACCOUNTNAME",
|
184
|
+
"the name of the account to connect to") { |v| options[:account] = v }
|
185
|
+
opts.on("-V", "--version", "print version information") do |v|
|
186
|
+
puts "lijab #{Lijab::VERSION}"
|
187
|
+
exit(0)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
begin
|
191
|
+
op.parse!
|
192
|
+
rescue OptionParser::ParseError => e
|
193
|
+
puts "#{e}\n\n#{op.banner.chomp}"
|
194
|
+
exit(1)
|
195
|
+
end
|
196
|
+
rescue OptionParser::MissingArgument
|
197
|
+
puts "lijab: error: #{$!}\n\n#{op}"
|
198
|
+
exit 1
|
199
|
+
end
|
200
|
+
options
|
201
|
+
end
|
202
|
+
|
203
|
+
def save_session
|
204
|
+
return unless @presence
|
205
|
+
|
206
|
+
o = {:status => {:type => @presence.type,
|
207
|
+
:show => @presence.show,
|
208
|
+
:status => @presence.status,
|
209
|
+
:priority => @presence.priority}}
|
210
|
+
File.open(File.join(Config.account[:dir], "session_data.yml"), 'w') do |f|
|
211
|
+
f.puts(YAML.dump(o))
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def read_saved_session
|
216
|
+
path = File.join(Config.account[:dir], "session_data.yml")
|
217
|
+
|
218
|
+
if File.file?(path)
|
219
|
+
o = YAML.load_file(path)
|
220
|
+
else
|
221
|
+
o = {:status => {:type => :available, :priority => 51}}
|
222
|
+
end
|
223
|
+
|
224
|
+
@presence = Jabber::Presence.new.set_type(o[:status][:type]) \
|
225
|
+
.set_show(o[:status][:show]) \
|
226
|
+
.set_status(o[:status][:status]) \
|
227
|
+
.set_priority(o[:status][:priority])
|
228
|
+
end
|
229
|
+
|
230
|
+
def quit
|
231
|
+
begin
|
232
|
+
@client.close if @connected
|
233
|
+
rescue
|
234
|
+
end
|
235
|
+
InputHandler::save_typed_history
|
236
|
+
Config::dump_config_file(false, true)
|
237
|
+
save_session()
|
238
|
+
puts "\nexiting..."
|
239
|
+
exit 0
|
240
|
+
end
|
241
|
+
|
242
|
+
attr_reader :contacts, :client, :connected, :presence
|
243
|
+
module_function :contacts, :client, :connected, :presence
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|