1# frozen_string_literal: true
2
3require "em-http"
4require "em-synchrony/em-http" # For apost vs post
5require "json"
6require "lazy_object"
7require "value_semantics/monkey_patched"
8
9require_relative "sim"
10
11class SIMRepo
12 value_semantics do
13 db Anything(), default: LazyObject.new { DB }
14 end
15
16 KEEPGO_HEADERS = {
17 "Accept" => "application/json",
18 "apiKey" => CONFIG[:keepgo][:api_key],
19 "accessToken" => CONFIG[:keepgo][:access_token]
20 }.freeze
21
22 def all(start_page=1)
23 req("lines").aget(
24 head: KEEPGO_HEADERS, query: { page: start_page, per_page: 1000 }
25 ).then { |req|
26 result = JSON.parse(req.response)
27 sims = result.dig("sim_cards", "items")&.map(&SIM.method(:extract))
28
29 next sims if result.dig("sim_cards", "last_page") == start_page
30 next [] if !sims || sims.empty?
31
32 all(start_page + 1).then { |next_page| sims + next_page }
33 }
34 end
35
36 def find(iccid)
37 req("line/#{iccid}/get_details").aget(head: KEEPGO_HEADERS).then { |req|
38 SIM.extract(JSON.parse(req.response)&.dig("sim_card"))
39 }
40 end
41
42 def refill(sim, **kwargs)
43 iccid = sim.is_a?(String) ? sim : sim.iccid
44
45 req("line/#{iccid}/refill").apost(
46 head: KEEPGO_HEADERS.merge("Content-Type" => "application/json"),
47 body: kwargs.to_json
48 ).then { |req| JSON.parse(req.response) }
49 end
50
51 def owned_by(customer)
52 customer = customer.customer_id if customer.respond_to?(:customer_id)
53 promise = db.query_defer(<<~SQL, [customer])
54 SELECT iccid, nickname FROM sims WHERE customer_id=$1
55 SQL
56 promise.then { |result|
57 EMPromise.all(result.map { |row|
58 find(row["iccid"]).then { |sim| sim.with(nickname: row["nickname"]) }
59 })
60 }
61 end
62
63 def put_owner(sim, customer, nickname=nil)
64 db.query_defer(<<~SQL, [customer.customer_id, sim.iccid, nickname])
65 UPDATE sims SET customer_id=$1, nickname=COALESCE($3, nickname) WHERE iccid=$2 AND customer_id IS NULL
66 SQL
67 end
68
69 def available
70 db.query_defer(<<~SQL).then { |r| find(r.first["iccid"]) }
71 SELECT iccid FROM sims WHERE customer_id IS NULL LIMIT 1
72 SQL
73 end
74
75protected
76
77 def req(path)
78 EM::HttpRequest.new(
79 "https://myaccount.keepgo.com/api/v2/#{path}",
80 tls: { verify_peer: true }
81 )
82 end
83end