~singpolyma/sgx-jmp

9db53ccfa22c642548632e4ce7e946d1efc4d26f — Stephen Paul Weber 1 year, 2 months ago c97470e
lnp command
4 files changed, 198 insertions(+), 30 deletions(-)

A forms/lnp.rb
A lib/form_to_h.rb
A lib/port_in_order.rb
M sgx_jmp.rb
A forms/lnp.rb => forms/lnp.rb +83 -0
@@ 0,0 1,83 @@
form!
title "Bring your own number to JMP"
instructions <<~I
	To confirm, you'd like to transfer in a number to your JMP account (your current JMP number will be replaced by the number you are transferring in).

	Once you've submitted the details for the number you'd like to bring to JMP, we will begin the transfer process. This normally takes 1-2 weeks during which both your existing number and your current JMP number will continue to work as they do now.

	Within a day or two of submitting this form, we will know which date the transfer will take place, and we will message your current JMP number with this information. Note that there is normally a period of 15-45 minutes at the time of transfer where incoming calls and messages will not be delivered to the number you are transferring in. After that time, all calls and messages will be handled by your JMP account, and your current JMP number will no longer receive calls or messages.

	If this all seems fine to you, then please enter the information for the number you'd like to transfer into JMP:
I

field(
	var: "BillingTelephoneNumber",
	required: true,
	type: "text-single",
	label: "Phone number"
)

field(
	var: "Subscriber[FirstName]",
	required: true,
	type: "text-single",
	label: "Billing first name"
)

field(
	var: "Subscriber[LastName]",
	required: true,
	type: "text-single",
	label: "Billing last name"
)

field(
	var: "Subscriber[ServiceAddress][HouseNumber]",
	required: true,
	type: "text-single",
	label: "Billing street number"
)

field(
	var: "Subscriber[ServiceAddress][StreetName]",
	required: true,
	type: "text-single",
	label: "Billing street name"
)

field(
	var: "Subscriber[ServiceAddress][City]",
	required: true,
	type: "text-single",
	label: "Billing city"
)

field(
	var: "Subscriber[ServiceAddress][StateCode]",
	required: true,
	type: "text-single",
	label: "Billing state or province"
)

field(
	var: "Subscriber[ServiceAddress][Zip]",
	required: true,
	type: "text-single",
	label: "Billing zip or postal code"
)

field(
	var: "WirelessInfo[AccountNumber]",
	required: false,
	type: "text-single",
	label: "Account number",
	description: "required unless carrier is VoIP"
)

field(
	var: "WirelessInfo[PinNumber]",
	required: false,
	type: "text-single",
	label: "Account PIN",
	description: "required unless your carrier has none"
)

A lib/form_to_h.rb => lib/form_to_h.rb +21 -0
@@ 0,0 1,21 @@
# frozen_string_literal: true

require "blather"
require "rack"

module FormToH
	refine Blather::Stanza::X do
		def to_h
			params = Rack::Utils.default_query_parser.make_params
			fields.each do |field|
				Rack::Utils.default_query_parser.normalize_params(
					params,
					field.var,
					field.value,
					32
				)
			end
			params.to_h
		end
	end
end

A lib/port_in_order.rb => lib/port_in_order.rb +29 -0
@@ 0,0 1,29 @@
# frozen_string_literal: true

class PortInOrder
	def initialize(params)
		@params = params
		@params["SiteId"] = CONFIG[:bandwidth_site]
		@params["PeerId"] = CONFIG[:bandwidth_peer]
		@params["ProcessingStatus"] = "DRAFT"
		@params["Subscriber"]["SubscriberType"] ||= "RESIDENTIAL"
	end

	def loa_authorizing_person
		"%s %s" % [
			@params.dig("Subscriber", "FirstName"),
			@params.dig("Subscriber", "LastName")
		]
	end

	def to_h
		@params.dup.tap do |h|
			h["LoaAuthorizingPerson"] = loa_authorizing_person
			h["BillingTelephoneNumber"].gsub!(/[^\d]/, "")
			h["BillingTelephoneNumber"].gsub!(/\A1(\d{10})\Z/) { $1 }
			h["ListOfPhoneNumbers"] = {
				"PhoneNumber" => params["BillingTelephoneNumber"]
			}
		end
	end
end

M sgx_jmp.rb => sgx_jmp.rb +65 -30
@@ 79,7 79,9 @@ require_relative "lib/customer_repo"
require_relative "lib/electrum"
require_relative "lib/expiring_lock"
require_relative "lib/em"
require_relative "lib/form_to_h"
require_relative "lib/low_balance"
require_relative "lib/port_in_order"
require_relative "lib/payment_methods"
require_relative "lib/paypal_done"
require_relative "lib/registration"


@@ 537,36 539,6 @@ Command.new(
	end
}.register(self).then(&CommandList.method(:register))

command :execute?, node: "web-register" do |iq|
	StatsD.increment("command", tags: ["node:#{iq.node}"])

	sentry_hub = new_sentry_hub(iq, name: iq.node)

	begin
		jid = iq.form.field("jid")&.value.to_s.strip
		tel = iq.form.field("tel")&.value.to_s.strip
		sentry_hub.current_scope.set_user(jid: jid, tel: tel)
		if iq.from.stripped != CONFIG[:web_register][:from]
			BLATHER << iq.as_error("forbidden", :auth)
		elsif jid == "" || tel !~ /\A\+\d+\Z/
			reply_with_note(iq, "Invalid JID or telephone number.", type: :error)
		else
			IQ_MANAGER.write(Blather::Stanza::Iq::Command.new.tap { |cmd|
				cmd.to = CONFIG[:web_register][:to]
				cmd.node = "push-register"
				cmd.form.fields = [var: "to", value: jid]
				cmd.form.type = "submit"
			}).then { |result|
				TEL_SELECTIONS.set(result.form.field("from")&.value.to_s.strip, tel)
			}.then {
				BLATHER << iq.reply.tap { |reply| reply.status = :completed }
			}.catch { |e| panic(e, sentry_hub) }
		end
	rescue StandardError => e
		sentry_hub.capture_exception(e)
	end
end

Command.new(
	"info",
	"Show Account Info",


@@ 637,6 609,69 @@ Command.new(
	end
}.register(self).then(&CommandList.method(:register))

Command.new(
	"lnp",
	"Port in your number from another carrier",
	list_for: ->(**) { true }
) {
	using FormToH

	EMPromise.all([
		Command.customer,
		Command.reply do |reply|
			reply.allowed_actions = [:next]
			reply.command << FormTemplate.render("lnp")
		end
	]).then do |(customer, iq)|
		order = PortInOrder.new(iq.form.to_h.slice(
			"BillingTelephoneNumber", "Subscriber", "WirelessInfo"
		).merge("CustomerOrderId" => customer.customer_id))
		order_id = BandwidthIris::PortIn.create(order.to_h)[:order_id]
		url = "https://dashboard.bandwidth.com/portal/r/a/" \
		      "#{CONFIG[:creds][:account]}/orders/portIn/#{order_id}"
		BLATHER.join(CONFIG[:notify_admin], "sgx-jmp")
		BLATHER.say(
			CONFIG[:notify_admin],
			"New port-in request for #{customer.customer_id}: #{url}",
			:groupchat
		)
		Command.finish(
			"Your port-in request has been accepted, " \
			"support will contact you with next steps"
		)
	end
}.register(self).then(&CommandList.method(:register))

command :execute?, node: "web-register" do |iq|
	StatsD.increment("command", tags: ["node:#{iq.node}"])

	sentry_hub = new_sentry_hub(iq, name: iq.node)

	begin
		jid = iq.form.field("jid")&.value.to_s.strip
		tel = iq.form.field("tel")&.value.to_s.strip
		sentry_hub.current_scope.set_user(jid: jid, tel: tel)
		if iq.from.stripped != CONFIG[:web_register][:from]
			BLATHER << iq.as_error("forbidden", :auth)
		elsif jid == "" || tel !~ /\A\+\d+\Z/
			reply_with_note(iq, "Invalid JID or telephone number.", type: :error)
		else
			IQ_MANAGER.write(Blather::Stanza::Iq::Command.new.tap { |cmd|
				cmd.to = CONFIG[:web_register][:to]
				cmd.node = "push-register"
				cmd.form.fields = [var: "to", value: jid]
				cmd.form.type = "submit"
			}).then { |result|
				TEL_SELECTIONS.set(result.form.field("from")&.value.to_s.strip, tel)
			}.then {
				BLATHER << iq.reply.tap { |reply| reply.status = :completed }
			}.catch { |e| panic(e, sentry_hub) }
		end
	rescue StandardError => e
		sentry_hub.capture_exception(e)
	end
end

command sessionid: /./ do |iq|
	COMMAND_MANAGER.fulfill(iq)
end