registration.rb

  1# frozen_string_literal: true
  2
  3require_relative "./oob"
  4
  5class Registration
  6	def self.for(iq, customer, web_register_manager)
  7		raise "TODO" if customer&.active?
  8
  9		EMPromise.resolve(customer&.registered?).then do |registered|
 10			if registered
 11				Registered.new(iq, registered.phone)
 12			else
 13				web_register_manager.choose_tel(iq).then do |(riq, tel)|
 14					Activation.for(riq, customer, tel)
 15				end
 16			end
 17		end
 18	end
 19
 20	class Registered
 21		def initialize(iq, tel)
 22			@reply = iq.reply
 23			@reply.status = :completed
 24			@tel = tel
 25		end
 26
 27		def write
 28			@reply.note_type = :error
 29			@reply.note_text = <<~NOTE
 30				You are already registered with JMP number #{@tel}
 31			NOTE
 32			BLATHER << @reply
 33			nil
 34		end
 35	end
 36
 37	class Activation
 38		def self.for(iq, customer, tel)
 39			return EMPromise.resolve(new(iq, customer, tel)) if customer
 40
 41			# Create customer_id
 42			raise "TODO"
 43		end
 44
 45		def initialize(iq, customer, tel)
 46			@reply = iq.reply
 47			reply.allowed_actions = [:next]
 48
 49			@customer = customer
 50			@tel = tel
 51		end
 52
 53		attr_reader :reply, :customer, :tel
 54
 55		FORM_FIELDS = [
 56			{
 57				var: "activation_method",
 58				type: "list-single",
 59				label: "Activate using",
 60				required: true,
 61				options: [
 62					{
 63						value: "bitcoin",
 64						label: "Bitcoin"
 65					},
 66					{
 67						value: "credit_card",
 68						label: "Credit Card"
 69					},
 70					{
 71						value: "code",
 72						label: "Referral or Activation Code"
 73					}
 74				]
 75			},
 76			{
 77				var: "plan_name",
 78				type: "list-single",
 79				label: "What currency should your account balance be in?",
 80				required: true,
 81				options: [
 82					{
 83						value: "cad_beta_unlimited-v20210223",
 84						label: "Canadian Dollars"
 85					},
 86					{
 87						value: "usd_beta_unlimited-v20210223",
 88						label: "United States Dollars"
 89					}
 90				]
 91			}
 92		].freeze
 93
 94		def write
 95			form = reply.form
 96			form.type = :form
 97			form.title = "Activate JMP"
 98			form.instructions = "Going to activate #{tel} (TODO RATE CTR)"
 99			form.fields = FORM_FIELDS
100
101			COMMAND_MANAGER.write(reply).then { |iq|
102				Payment.for(iq, customer, tel)
103			}.then(&:write)
104		end
105	end
106
107	module Payment
108		def self.kinds
109			@kinds ||= {}
110		end
111
112		def self.for(iq, customer, tel)
113			plan_name = iq.form.field("plan_name").value.to_s
114			customer = customer.with_plan(plan_name)
115			kinds.fetch(iq.form.field("activation_method")&.value&.to_s&.to_sym) {
116				raise "Invalid activation method"
117			}.call(iq, customer, tel)
118		end
119
120		class Bitcoin
121			Payment.kinds[:bitcoin] = method(:new)
122
123			def initialize(iq, customer, tel)
124				@reply = iq.reply
125				reply.note_type = :info
126				reply.status = :completed
127
128				@customer = customer
129				@customer_id = customer.customer_id
130				@tel = tel
131				@addr = ELECTRUM.createnewaddress
132			end
133
134			attr_reader :reply, :customer_id, :tel
135
136			def save
137				EMPromise.all([
138					REDIS.mset(
139						"pending_tel_for-#{customer_id}", tel,
140						"pending_plan_for-#{customer_id}", @customer.plan_name
141					),
142					@addr.then do |addr|
143						REDIS.sadd("jmp_customer_btc_addresses-#{customer_id}", addr)
144					end
145				])
146			end
147
148			def note_text(amount, addr)
149				<<~NOTE
150					Activate your account by sending at least #{'%.6f' % amount} BTC to
151					#{addr}
152
153					You will receive a notification when your payment is complete.
154				NOTE
155			end
156
157			def write
158				EMPromise.all([
159					@addr,
160					save,
161					BTC_SELL_PRICES.public_send(@customer.currency.to_s.downcase)
162				]).then do |(addr, _, rate)|
163					min = CONFIG[:activation_amount] / rate
164					reply.note_text = note_text(min, addr)
165					BLATHER << reply
166					nil
167				end
168			end
169		end
170
171		class CreditCard
172			Payment.kinds[:credit_card] = ->(*args) { self.for(*args) }
173
174			def self.for(iq, customer, tel)
175				customer.payment_methods.then do |payment_methods|
176					if payment_methods.default_payment_method
177						Activate.new(iq, customer, tel)
178					else
179						new(iq, customer, tel)
180					end
181				end
182			end
183
184			def initialize(iq, customer, tel)
185				@customer = customer
186				@tel = tel
187
188				@reply = iq.reply
189				@reply.allowed_actions = [:next]
190				@reply.note_type = :info
191				@reply.note_text = "#{oob.desc}: #{oob.url}"
192			end
193
194			attr_reader :reply
195
196			def oob
197				oob = OOB.find_or_create(@reply.command)
198				oob.url = CONFIG[:credit_card_url].call(
199					@reply.to.stripped.to_s,
200					@customer.customer_id
201				)
202				oob.desc = "Add credit card, then return here and choose next"
203				oob
204			end
205
206			def write
207				COMMAND_MANAGER.write(@reply).then do |riq|
208					CreditCard.for(riq, @customer, @tel)
209				end
210			end
211
212			class Activate
213				def initialize(_iq, _customer, _tel)
214					raise "TODO"
215				end
216			end
217		end
218	end
219end