sgx-catapult.rb

  1#!/usr/bin/env ruby
  2#
  3# Copyright (C) 2017  Denver Gingerich <denver@ossguy.com>
  4#
  5# This file is part of sgx-catapult.
  6#
  7# sgx-catapult is free software: you can redistribute it and/or modify it under
  8# the terms of the GNU Affero General Public License as published by the Free
  9# Software Foundation, either version 3 of the License, or (at your option) any
 10# later version.
 11#
 12# sgx-catapult is distributed in the hope that it will be useful, but WITHOUT
 13# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 14# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
 15# details.
 16#
 17# You should have received a copy of the GNU Affero General Public License along
 18# with sgx-catapult.  If not, see <http://www.gnu.org/licenses/>.
 19
 20require 'blather/client/dsl'
 21
 22if ARGV.size != 4 then
 23	puts "Usage: sgx-catapult.rb <component_jid> <component_password> " +
 24		"<server_hostname> <server_port>"
 25	exit 0
 26end
 27
 28module SGXcatapult
 29	extend Blather::DSL
 30
 31	def self.run
 32		client.run
 33	end
 34
 35	setup ARGV[0], ARGV[1], ARGV[2], ARGV[3]
 36
 37	message :chat?, :body do |m|
 38		begin
 39			puts "#{m.from.to_s} -> #{m.to.to_s} #{m.body}"
 40			msg = Blather::Stanza::Message.new(m.from, 'thx for "' +
 41				m.body + '"')
 42			msg.from = m.to
 43			write_to_stream msg
 44		rescue => e
 45			# TODO: do something better with this info
 46			say m.from, e.inspect
 47		end
 48	end
 49
 50	iq '/iq/ns:query', :ns =>
 51		'http://jabber.org/protocol/disco#items' do |i, xpath_result|
 52
 53		puts "IQ: #{i.inspect}"
 54
 55		msg = Blather::Stanza::Iq::DiscoItems.new
 56		msg.id = i.id
 57		msg.to = i.from
 58		msg.type = 'result'
 59
 60		puts "RESPONSE0: #{msg.inspect}"
 61		write_to_stream msg
 62		puts "SENT"
 63	end
 64
 65	iq '/iq/ns:query', :ns =>
 66		'http://jabber.org/protocol/disco#info' do |i, xpath_result|
 67
 68		puts "IQ: #{i.inspect}"
 69
 70		msg = Blather::Stanza::Iq::DiscoInfo.new
 71		msg.id = i.id
 72		msg.to = i.from
 73		msg.type = 'result'
 74
 75		msg.identities = [{:name =>
 76			'Soprani.ca Gateway to XMPP - Catapult',
 77			:type => 'sms-ctplt', :category => 'gateway'}]
 78		msg.features = ["jabber:iq:register",
 79			"jabber:iq:gateway", "jabber:iq:private",
 80			"http://jabber.org/protocol/disco#info",
 81			"http://jabber.org/protocol/commands",
 82			"http://jabber.org/protocol/muc"]
 83		puts "RESPONSE1: #{msg.inspect}"
 84		write_to_stream msg
 85		puts "SENT"
 86	end
 87
 88	iq '/iq/ns:query', :ns => 'jabber:iq:register' do |i, qn|
 89		puts "IQ: #{i.inspect}"
 90
 91		if i.type == :set
 92			xn = qn.children.find { |v| v.element_name == "x" }
 93
 94			if xn.nil?
 95				puts "id: " + qn.children.find {
 96					|v| v.element_name == "nick" }
 97				puts "token: " + qn.children.find {
 98					|v| v.element_name == "username" }
 99				puts "secret: " + qn.children.find {
100					|v| v.element_name == "password" }
101				puts "phone num: " + qn.children.find {
102					|v| v.element_name == "phone" }
103				next
104			end
105
106			for field in xn.children
107				if field.element_name == "field"
108					val = field.children.find { |v|
109						v.element_name == "value" }
110
111					case field['var']
112					when 'nick'
113						puts "id: " + val.text
114					when 'username'
115						puts "token: " + val.text
116					when 'password'
117						puts "secret: " + val.text
118					when 'phone'
119						puts "phone num: " + val.text
120					when 'FORM_TYPE'
121						puts "FORM_TYPE: " + val.text
122					else
123						# TODO: error
124						puts "weird var: " +field['var']
125					end
126				end
127			end
128
129			# success (for now)
130			msg = Blather::Stanza::Iq.new
131			msg.id = i.id
132			msg.to = i.from
133			msg.type = 'result'
134
135			puts "RESPONSE3: #{msg.inspect}"
136			write_to_stream msg
137			puts "SENT"
138
139		elsif i.type == :get
140			orig = Blather::Stanza::Iq.new
141			orig.id = i.id
142			orig.to = i.from
143			orig.type = 'result'
144
145			msg = Nokogiri::XML::Node.new 'query',orig.document
146			msg['xmlns'] = 'jabber:iq:register'
147			n1 = Nokogiri::XML::Node.new 'instructions',msg.document
148			n1.content= "Enter the information from your Account " +
149				"page as well as the Phone Number\nin your " +
150				"account you want to use (ie. '+12345678901')" +
151				".\nUser Id is nick, API Token is username, " +
152				"API Secret is password, Phone Number is phone"+
153				".\n\nThe source code for this gateway is at " +
154				"https://github.com/ossguy/sgx-catapult ." +
155				"\nCopyright (C) 2017  Denver Gingerich, " +
156				"licensed under AGPLv3+."
157			n2 = Nokogiri::XML::Node.new 'nick',msg.document
158			n3 = Nokogiri::XML::Node.new 'username',msg.document
159			n4 = Nokogiri::XML::Node.new 'password',msg.document
160			n5 = Nokogiri::XML::Node.new 'phone',msg.document
161			msg.add_child(n1)
162			msg.add_child(n2)
163			msg.add_child(n3)
164			msg.add_child(n4)
165			msg.add_child(n5)
166
167			x = Nokogiri::XML::Node.new 'x',orig.document
168			x['xmlns'] = 'jabber:x:data'
169			x['type'] = 'form'
170			msg.add_child(x)
171
172			title = Nokogiri::XML::Node.new 'title',orig.document
173			title.content= 'Register for ' +
174				'Soprani.ca Gateway to XMPP - Catapult'
175			x.add_child(title)
176
177			instr = Nokogiri::XML::Node.new 'instructions',
178				orig.document
179			instr.content= "Enter the details from your Account " +
180				"page as well as the Phone Number\nin your " +
181				"account you want to use (ie. '+12345678901')" +
182				".\n\nThe source code for this gateway is at " +
183				"https://github.com/ossguy/sgx-catapult ." +
184				"\nCopyright (C) 2017  Denver Gingerich, " +
185				"licensed under AGPLv3+."
186			x.add_child(instr)
187
188			f1 = Nokogiri::XML::Node.new 'field',orig.document
189			f1['type'] = 'hidden'
190			f1['var'] = 'FORM_TYPE'
191			v1 = Nokogiri::XML::Node.new 'value',orig.document
192			v1.content= 'jabber:iq:register'
193			f1.add_child(v1)
194			x.add_child(f1)
195
196			f2 = Nokogiri::XML::Node.new 'field',orig.document
197			f2['type'] = 'text-single'
198			f2['label'] = 'User Id'
199			f2['var'] = 'nick'
200			v2 = Nokogiri::XML::Node.new 'required',orig.document
201			f2.add_child(v2)
202			x.add_child(f2)
203
204			f3 = Nokogiri::XML::Node.new 'field',orig.document
205			f3['type'] = 'text-single'
206			f3['label'] = 'API Token'
207			f3['var'] = 'username'
208			v3 = Nokogiri::XML::Node.new 'required',orig.document
209			f3.add_child(v3)
210			x.add_child(f3)
211
212			f4 = Nokogiri::XML::Node.new 'field',orig.document
213			f4['type'] = 'text-private'
214			f4['label'] = 'API Secret'
215			f4['var'] = 'password'
216			v4 = Nokogiri::XML::Node.new 'required',orig.document
217			f4.add_child(v4)
218			x.add_child(f4)
219
220			f5 = Nokogiri::XML::Node.new 'field',orig.document
221			f5['type'] = 'text-single'
222			f5['label'] = 'Phone Number'
223			f5['var'] = 'phone'
224			v5 = Nokogiri::XML::Node.new 'required',orig.document
225			f5.add_child(v5)
226			x.add_child(f5)
227
228			orig.add_child(msg)
229			puts "RESPONSE2: #{orig.inspect}"
230			write_to_stream orig
231			puts "SENT"
232		end
233	end
234
235	subscription(:request?) do |s|
236		# TODO: fix these - they don't actual work; write does not exist
237		#write(s.approve!)
238		#write(s.request!)
239	end
240end
241
242[:INT, :TERM].each do |sig|
243	trap(sig) {
244		puts 'Shutting down gateway...'
245		SGXcatapult.shutdown
246		puts 'Gateway has terminated.'
247
248		EM.stop
249	}
250end
251
252EM.run do
253	SGXcatapult.run
254end