# frozen_string_literal: true
require "blather/client"
require "dhall"
require_relative "em_promise"
CONFIG = Dhall::Coder.load(ARGV[0])
def node(name, parent, ns: nil)
Niceogiri::XML::Node.new(
name,
parent.document,
ns || parent.class.registered_ns
)
end
def escape_jid(localpart)
# TODO: proper XEP-0106 Sec 4.3, ie. pre-escaped
localpart
.to_s
.gsub("\\", "\\\\5c")
.gsub(" ", "\\\\20")
.gsub("\"", "\\\\22")
.gsub("&", "\\\\26")
.gsub("'", "\\\\27")
.gsub("/", "\\\\2f")
.gsub(":", "\\\\3a")
.gsub("<", "\\\\3c")
.gsub(">", "\\\\3e")
.gsub("@", "\\\\40")
end
def unescape_jid(localpart)
localpart
.to_s
.gsub("\\20", " ")
.gsub("\\22", "\"")
.gsub("\\26", "&")
.gsub("\\27", "'")
.gsub("\\2f", "/")
.gsub("\\3a", ":")
.gsub("\\3c", "<")
.gsub("\\3e", ">")
.gsub("\\40", "@")
.gsub("\\5c", "\\")
end
def proxy_jid(jid)
Blather::JID.new(
escape_jid(jid.stripped),
CONFIG["component"]["jid"],
jid.resource
)
end
def unproxy_jid(jid)
parsed = Blather::JID.new(unescape_jid(jid.node))
Blather::JID.new(parsed.node, parsed.domain, jid.resource)
end
class IBR < Blather::Stanza::Iq::Query
register :ibr, nil, "jabber:iq:register"
def registered=(reg)
query.at_xpath("./ns:registered", ns: self.class.registered_ns)&.remove
query << node("registered", self) if reg
end
def registered?
!!query.at_xpath("./ns:registered", ns: self.class.registered_ns)
end
[
"instructions",
"username",
"nick",
"password",
"name",
"first",
"last",
"last",
"email",
"address",
"city",
"state",
"zip",
"phone",
"url",
"date"
].each do |tag|
define_method("#{tag}=") do |v|
query.at_xpath("./ns:#{tag}", ns: self.class.registered_ns)&.remove
query << (i = node(tag, self))
i.content = v
end
define_method(tag) do
query.at_xpath("./ns:#{tag}", ns: self.class.registered_ns)&.content
end
end
end
Blather::DSL.append_features(self.class)
when_ready do
EM.add_periodic_timer(3600) do
ping = Blather::Stanza::Iq::Ping.new(:get, CONFIG["server"]["host"])
ping.from = CONFIG["component"]["jid"]
self << ping
end
end
# workqueue_count MUST be 0 or else Blather uses threads!
setup(
CONFIG["component"]["jid"],
CONFIG["component"]["secret"],
CONFIG["server"]["host"],
CONFIG["server"]["port"],
nil,
nil,
workqueue_count: 0
)
message :error? do |m|
puts "MESSAGE ERROR: #{m.inspect}"
end
ibr :get? do |iq|
fwd = iq.dup
fwd.from = proxy_jid(iq.from)
fwd.to = Blather::JID.new(nil, CONFIG["sgx"], iq.to.resource)
fwd.id = "JMPGET%#{iq.id}"
self << fwd
end
ibr :result? do |iq|
if iq.id.start_with?("JMPGET")
reply = iq.reply
reply.instructions =
"Please enter the phone number you wish to register with JMP.chat"
reply.registered = iq.registered?
reply.phone = iq.phone
else
reply = iq.dup
end
reply.id = iq.id.sub(/JMP[GS]ET%/, "")
reply.from = Blather::JID.new(
nil,
CONFIG["component"]["jid"],
iq.from.resource
)
reply.to = unproxy_jid(iq.to)
self << reply
end
ibr :error? do |iq|
reply = iq.dup
reply.id = iq.id.sub(/JMP[GS]ET%/, "")
reply.from = Blather::JID.new(
nil,
CONFIG["component"]["jid"],
iq.from.resource
)
reply.to = unproxy_jid(iq.to)
self << reply
end
ibr :set? do |iq|
fwd = iq.dup
CONFIG["creds"].each do |k, v|
fwd.public_send("#{k}=", v)
end
fwd.from = proxy_jid(iq.from)
fwd.to = Blather::JID.new(nil, CONFIG["sgx"], iq.to.resource)
fwd.id = "JMPSET%#{iq.id}"
self << fwd
end