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 EM.add_timer(15) do
46 promise.reject(:timeout)
47 end
48
49 client.write_with_handler(stanza) do |s|
50 if s.error?
51 promise.reject(s)
52 else
53 promise.fulfill(s)
54 end
55 end
56 promise
57 end
58
59 def self.command(node, sessionid=nil, action: :execute, form: nil)
60 Blather::Stanza::Iq::Command.new.tap do |cmd|
61 cmd.to = CONFIG[:sgx_jmp]
62 cmd.node = node
63 cmd.command[:sessionid] = sessionid if sessionid
64 cmd.action = action
65 cmd.command << form if form
66 end
67 end
68
69 def self.execute(command_node, form=nil)
70 write_with_promise(command(command_node)).then do |iq|
71 next iq unless form
72
73 write_with_promise(command(command_node, iq.sessionid, form: form))
74 end
75 end
76end