1# frozen_string_literal: true
2
3require "blather/client/dsl"
4require "em_promise"
5require "timeout"
6
7module BlatherNotify
8 extend Blather::DSL
9
10 @ready = Queue.new
11
12 when_ready { @ready << :ready }
13
14 def self.start(jid, password)
15 # workqueue_count MUST be 0 or else Blather uses threads!
16 setup(jid, password, nil, nil, nil, nil, workqueue_count: 0)
17
18 EM.error_handler(&method(:panic))
19
20 @thread = Thread.new {
21 EM.run do
22 client.run
23 end
24 }
25
26 Timeout.timeout(30) { @ready.pop }
27 at_exit { wait_then_exit }
28 end
29
30 def self.panic(e)
31 warn e.message
32 warn e.backtrace
33 exit! 2
34 end
35
36 def self.wait_then_exit
37 disconnected { EM.stop }
38 EM.add_timer(30) { EM.stop }
39 shutdown
40 @thread.join
41 end
42
43 def self.write_with_promise(stanza)
44 promise = EMPromise.new
45 client.write_with_handler(stanza) do |s|
46 if s.error?
47 promise.reject(s)
48 else
49 promise.fulfill(s)
50 end
51 end
52 promise
53 end
54
55 def self.command(node, sessionid=nil, action: :execute, form: nil)
56 Blather::Stanza::Iq::Command.new.tap do |cmd|
57 cmd.to = CONFIG[:sgx_jmp]
58 cmd.node = node
59 cmd.command[:sessionid] = sessionid if sessionid
60 cmd.action = action
61 cmd.command << form if form
62 end
63 end
64
65 def self.execute(command_node, form=nil)
66 write_with_promise(command(command_node)).then do |iq|
67 next iq unless form
68
69 write_with_promise(command(command_node, iq.sessionid, form: form))
70 end
71 end
72end