palbo-lijab 0.1.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/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
|
+
|