# frozen_string_literal: true
require_relative "./oob"
class Registration
def self.for(iq, customer, web_register_manager)
raise "TODO" if customer&.active?
EMPromise.resolve(customer&.registered?).then do |registered|
if registered
Registered.new(iq, registered.phone)
else
web_register_manager.choose_tel(iq).then do |(riq, tel)|
Activation.for(riq, customer, tel)
end
end
end
end
class Registered
def initialize(iq, tel)
@reply = iq.reply
@reply.status = :completed
@tel = tel
end
def write
@reply.note_type = :error
@reply.note_text = <<~NOTE
You are already registered with JMP number #{@tel}
NOTE
BLATHER << @reply
nil
end
end
class Activation
def self.for(iq, customer, tel)
return EMPromise.resolve(new(iq, customer, tel)) if customer
# Create customer_id
raise "TODO"
end
def initialize(iq, customer, tel)
@reply = iq.reply
reply.allowed_actions = [:next]
@customer = customer
@tel = tel
end
attr_reader :reply, :customer, :tel
FORM_FIELDS = [
{
var: "activation_method",
type: "list-single",
label: "Activate using",
required: true,
options: [
{
value: "bitcoin",
label: "Bitcoin"
},
{
value: "credit_card",
label: "Credit Card ($#{CONFIG[:activation_amount]})"
},
{
value: "code",
label: "Referral or Activation Code"
}
]
},
{
var: "plan_name",
type: "list-single",
label: "What currency should your account balance be in?",
required: true,
options: [
{
value: "cad_beta_unlimited-v20210223",
label: "Canadian Dollars"
},
{
value: "usd_beta_unlimited-v20210223",
label: "United States Dollars"
}
]
}
].freeze
def write
form = reply.form
form.type = :form
form.title = "Activate JMP"
form.instructions = "Going to activate #{tel} (TODO RATE CTR)"
form.fields = FORM_FIELDS
COMMAND_MANAGER.write(reply).then { |iq|
Payment.for(iq, customer, tel)
}.then(&:write)
end
end
module Payment
def self.kinds
@kinds ||= {}
end
def self.for(iq, customer, tel)
plan_name = iq.form.field("plan_name").value.to_s
customer = customer.with_plan(plan_name)
kinds.fetch(iq.form.field("activation_method")&.value&.to_s&.to_sym) {
raise "Invalid activation method"
}.call(iq, customer, tel)
end
class Bitcoin
Payment.kinds[:bitcoin] = method(:new)
def initialize(iq, customer, tel)
@reply = iq.reply
reply.note_type = :info
reply.status = :completed
@customer = customer
@customer_id = customer.customer_id
@tel = tel
@addr = ELECTRUM.createnewaddress
end
attr_reader :reply, :customer_id, :tel
def save
EMPromise.all([
REDIS.mset(
"pending_tel_for-#{customer_id}", tel,
"pending_plan_for-#{customer_id}", @customer.plan_name
),
@addr.then do |addr|
REDIS.sadd("jmp_customer_btc_addresses-#{customer_id}", addr)
end
])
end
def note_text(amount, addr)
<<~NOTE
Activate your account by sending at least #{'%.6f' % amount} BTC to
#{addr}
You will receive a notification when your payment is complete.
NOTE
end
def write
EMPromise.all([
@addr,
save,
BTC_SELL_PRICES.public_send(@customer.currency.to_s.downcase)
]).then do |(addr, _, rate)|
min = CONFIG[:activation_amount] / rate
reply.note_text = note_text(min, addr)
BLATHER << reply
nil
end
end
end
class CreditCard
Payment.kinds[:credit_card] = ->(*args) { self.for(*args) }
def self.for(iq, customer, tel)
customer.payment_methods.then do |payment_methods|
if (method = payment_methods.default_payment_method)
Activate.new(iq, customer, method, tel)
else
new(iq, customer, tel)
end
end
end
def initialize(iq, customer, tel)
@customer = customer
@tel = tel
@reply = iq.reply
@reply.allowed_actions = [:next]
@reply.note_type = :info
@reply.note_text = "#{oob.desc}: #{oob.url}"
end
attr_reader :reply
def oob
oob = OOB.find_or_create(@reply.command)
oob.url = CONFIG[:credit_card_url].call(
@reply.to.stripped.to_s,
@customer.customer_id
)
oob.desc = "Add credit card, then return here and choose next"
oob
end
def write
COMMAND_MANAGER.write(@reply).then do |riq|
CreditCard.for(riq, @customer, @tel)
end
end
class Activate
def initialize(iq, customer, payment_method, tel)
@iq = iq
@customer = customer
@payment_method = payment_method
@tel = tel
end
def write
Transaction.sale(
@customer.merchant_account,
@payment_method,
CONFIG[:activation_amount]
).then(&:insert).then {
@customer.bill_plan
}.then do
Finish.new(@iq, @customer, @tel).write
end
end
end
end
end
class Finish
def initialize(iq, customer, tel)
@reply = iq.reply
@reply.status = :completed
@reply.note_type = :info
@reply.note_text = "Your JMP account has been activated as #{tel}"
@customer = customer
@tel = tel
end
def write
BandwidthTNOrder.create(@tel).then(&:poll).then(
->(_) { @customer.register!(@tel).then { BLATHER << @reply } },
lambda do |_|
@reply.note_type = :error
@reply.note_text =
"The JMP number #{@tel} is no longer available, " \
"please visit https://jmp.chat and choose another."
BLATHER << @reply
end
)
end
end
end