opensrs-ruby 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/opensrs/account.rb +16 -0
- data/lib/opensrs/client.rb +174 -0
- data/lib/opensrs/contact.rb +15 -0
- data/lib/opensrs/domain.rb +278 -0
- data/lib/opensrs/errors.rb +20 -0
- data/lib/opensrs.rb +19 -0
- metadata +87 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 6fa12db38773abeaa598352a9c011222163f51fb764d9211011f2e9cdd0bd87f
|
|
4
|
+
data.tar.gz: de281c57faf8f23c228416cf9f3484713581f532d2020e2755e0564e831b3eb4
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c3dd656f403f0d9312cd2531b97c63d431fab45e1839c3c8b3759e84b0da83fdd2ad79a35311392d773e426223d689d05c300af5a156c9697d7ec3e33a849b5d
|
|
7
|
+
data.tar.gz: d915f09dca9694ed8aa54d5f867ffd3db3be858b1036295680f41f9e7d5bdf1a443e6ac1477f672b8ffe45540fd45cfc13d2f3d64b2b250ac6076679cffd12cc
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module OpenSRS
|
|
2
|
+
Balance = Struct.new(:amount, :hold, keyword_init: true)
|
|
3
|
+
|
|
4
|
+
module Account
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
def balance(client: OpenSRS.default_client)
|
|
8
|
+
result = client.call(action: "GET_BALANCE", object: "BALANCE")
|
|
9
|
+
attrs = result["attributes"]
|
|
10
|
+
Balance.new(
|
|
11
|
+
amount: attrs["balance"].to_f,
|
|
12
|
+
hold: attrs["hold_balance"].to_f
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
require "net/http"
|
|
2
|
+
require "uri"
|
|
3
|
+
require "digest/md5"
|
|
4
|
+
require "rexml/document"
|
|
5
|
+
|
|
6
|
+
module OpenSRS
|
|
7
|
+
class Client
|
|
8
|
+
LIVE_URL = "https://rr-n1-tor.opensrs.net:55443"
|
|
9
|
+
TEST_URL = "https://horizon.opensrs.net:55443"
|
|
10
|
+
|
|
11
|
+
attr_reader :username
|
|
12
|
+
|
|
13
|
+
def initialize(username:, api_key:, test: false)
|
|
14
|
+
@username = username
|
|
15
|
+
@api_key = api_key
|
|
16
|
+
@url = test ? TEST_URL : LIVE_URL
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def call(action:, object:, attributes: {}, extra: {})
|
|
20
|
+
xml = build_xml(action, object, attributes, extra)
|
|
21
|
+
response_body = post(xml)
|
|
22
|
+
result = parse_response(response_body)
|
|
23
|
+
check_for_errors!(result)
|
|
24
|
+
result
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def post(xml)
|
|
30
|
+
signature = compute_signature(xml)
|
|
31
|
+
uri = URI(@url)
|
|
32
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
33
|
+
http.use_ssl = true
|
|
34
|
+
http.open_timeout = 15
|
|
35
|
+
http.read_timeout = 30
|
|
36
|
+
|
|
37
|
+
request = Net::HTTP::Post.new("/")
|
|
38
|
+
request["Content-Type"] = "text/xml"
|
|
39
|
+
request["X-Username"] = @username
|
|
40
|
+
request["X-Signature"] = signature
|
|
41
|
+
request.body = xml
|
|
42
|
+
|
|
43
|
+
http.request(request).body
|
|
44
|
+
rescue Net::OpenTimeout, Net::ReadTimeout, Errno::ECONNREFUSED, Errno::ECONNRESET => e
|
|
45
|
+
raise ConnectionError, e.message
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def compute_signature(xml)
|
|
49
|
+
step1 = Digest::MD5.hexdigest(xml + @api_key)
|
|
50
|
+
Digest::MD5.hexdigest(step1 + @api_key)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def check_for_errors!(result)
|
|
54
|
+
return if result["is_success"] == "1"
|
|
55
|
+
|
|
56
|
+
code = result["response_code"]
|
|
57
|
+
message = result["response_text"]
|
|
58
|
+
|
|
59
|
+
case code
|
|
60
|
+
when "415"
|
|
61
|
+
raise AuthenticationError.new(message, code)
|
|
62
|
+
when "485"
|
|
63
|
+
raise InsufficientBalance.new(message, code)
|
|
64
|
+
when "211"
|
|
65
|
+
raise DomainUnavailable.new(message, code)
|
|
66
|
+
when "487"
|
|
67
|
+
raise TransferError.new(message, code)
|
|
68
|
+
when "410"
|
|
69
|
+
raise DomainNotFound.new(message, code)
|
|
70
|
+
else
|
|
71
|
+
raise RequestError.new(message, code)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def build_xml(action, object, attributes, extra)
|
|
76
|
+
items = [
|
|
77
|
+
item("protocol", "XCP"),
|
|
78
|
+
item("action", action),
|
|
79
|
+
item("object", object),
|
|
80
|
+
]
|
|
81
|
+
extra.each { |k, v| items << item(k, v) }
|
|
82
|
+
items << item_assoc("attributes", attributes) unless attributes.empty?
|
|
83
|
+
|
|
84
|
+
<<~XML
|
|
85
|
+
<?xml version='1.0' encoding='UTF-8' standalone='no' ?>
|
|
86
|
+
<!DOCTYPE OPS_envelope SYSTEM 'ops.dtd'>
|
|
87
|
+
<OPS_envelope>
|
|
88
|
+
<header><version>0.9</version></header>
|
|
89
|
+
<body>
|
|
90
|
+
<data_block>
|
|
91
|
+
<dt_assoc>
|
|
92
|
+
#{items.join("\n ")}
|
|
93
|
+
</dt_assoc>
|
|
94
|
+
</data_block>
|
|
95
|
+
</body>
|
|
96
|
+
</OPS_envelope>
|
|
97
|
+
XML
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def item(key, value)
|
|
101
|
+
"<item key=\"#{key}\">#{escape(value)}</item>"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def item_assoc(key, hash)
|
|
105
|
+
inner = hash.map do |k, v|
|
|
106
|
+
if v.is_a?(Hash)
|
|
107
|
+
item_assoc(k, v)
|
|
108
|
+
elsif v.is_a?(Array)
|
|
109
|
+
item_array(k, v)
|
|
110
|
+
else
|
|
111
|
+
item(k, v)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
"<item key=\"#{key}\"><dt_assoc>#{inner.join}</dt_assoc></item>"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def item_array(key, arr)
|
|
118
|
+
inner = arr.each_with_index.map do |v, i|
|
|
119
|
+
if v.is_a?(Hash)
|
|
120
|
+
item_assoc(i.to_s, v)
|
|
121
|
+
else
|
|
122
|
+
item(i.to_s, v)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
"<item key=\"#{key}\"><dt_array>#{inner.join}</dt_array></item>"
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def escape(val)
|
|
129
|
+
val.to_s.gsub("&", "&").gsub("<", "<").gsub(">", ">")
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def parse_response(xml_str)
|
|
133
|
+
doc = REXML::Document.new(xml_str)
|
|
134
|
+
root_assoc = doc.elements["//body/data_block/dt_assoc"]
|
|
135
|
+
parse_assoc(root_assoc)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def parse_assoc(element)
|
|
139
|
+
return {} unless element
|
|
140
|
+
result = {}
|
|
141
|
+
element.elements.each("item") do |el|
|
|
142
|
+
key = el.attributes["key"]
|
|
143
|
+
child_assoc = el.elements["dt_assoc"]
|
|
144
|
+
child_array = el.elements["dt_array"]
|
|
145
|
+
if child_assoc
|
|
146
|
+
result[key] = parse_assoc(child_assoc)
|
|
147
|
+
elsif child_array
|
|
148
|
+
result[key] = parse_array(child_array)
|
|
149
|
+
else
|
|
150
|
+
result[key] = el.text&.strip
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
result
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def parse_array(element)
|
|
157
|
+
return [] unless element
|
|
158
|
+
items = {}
|
|
159
|
+
element.elements.each("item") do |el|
|
|
160
|
+
key = el.attributes["key"].to_i
|
|
161
|
+
child_assoc = el.elements["dt_assoc"]
|
|
162
|
+
child_array = el.elements["dt_array"]
|
|
163
|
+
if child_assoc
|
|
164
|
+
items[key] = parse_assoc(child_assoc)
|
|
165
|
+
elsif child_array
|
|
166
|
+
items[key] = parse_array(child_array)
|
|
167
|
+
else
|
|
168
|
+
items[key] = el.text&.strip
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
items.sort_by(&:first).map(&:last)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module OpenSRS
|
|
2
|
+
Contact = Struct.new(
|
|
3
|
+
:first_name, :last_name, :org_name, :address1, :address2,
|
|
4
|
+
:city, :state, :postal_code, :country, :phone, :email,
|
|
5
|
+
keyword_init: true
|
|
6
|
+
) do
|
|
7
|
+
def self.from_hash(hash)
|
|
8
|
+
new(**hash.transform_keys(&:to_sym).slice(*members))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_api_hash
|
|
12
|
+
to_h.compact.transform_keys(&:to_s)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
require "time"
|
|
2
|
+
require "digest/md5"
|
|
3
|
+
|
|
4
|
+
module OpenSRS
|
|
5
|
+
DomainCheck = Struct.new(:domain, :available, :price, keyword_init: true)
|
|
6
|
+
DomainSuggestion = Struct.new(:name, :available, keyword_init: true)
|
|
7
|
+
|
|
8
|
+
class Domain
|
|
9
|
+
attr_reader :name, :expires_at, :created_at, :updated_at, :nameservers, :contacts
|
|
10
|
+
|
|
11
|
+
def initialize(name:, client: nil, expires_at: nil, created_at: nil,
|
|
12
|
+
updated_at: nil, auto_renew: false, locked: false,
|
|
13
|
+
whois_private: false, nameservers: [], contacts: {})
|
|
14
|
+
@name = name
|
|
15
|
+
@client = client || OpenSRS.default_client
|
|
16
|
+
@expires_at = expires_at
|
|
17
|
+
@created_at = created_at
|
|
18
|
+
@updated_at = updated_at
|
|
19
|
+
@auto_renew = auto_renew
|
|
20
|
+
@locked = locked
|
|
21
|
+
@whois_private = whois_private
|
|
22
|
+
@nameservers = nameservers
|
|
23
|
+
@contacts = contacts
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def auto_renew? = @auto_renew
|
|
27
|
+
def locked? = @locked
|
|
28
|
+
def whois_private? = @whois_private
|
|
29
|
+
|
|
30
|
+
class << self
|
|
31
|
+
def available?(domain_name, client: OpenSRS.default_client)
|
|
32
|
+
result = client.call(action: "LOOKUP", object: "DOMAIN",
|
|
33
|
+
attributes: { "domain" => domain_name })
|
|
34
|
+
result.dig("attributes", "status") == "available"
|
|
35
|
+
rescue OpenSRS::DomainUnavailable
|
|
36
|
+
false
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def check(domain_name, client: OpenSRS.default_client)
|
|
40
|
+
lookup = client.call(action: "LOOKUP", object: "DOMAIN",
|
|
41
|
+
attributes: { "domain" => domain_name })
|
|
42
|
+
available = lookup.dig("attributes", "status") == "available"
|
|
43
|
+
|
|
44
|
+
price = nil
|
|
45
|
+
if available
|
|
46
|
+
price_result = client.call(action: "GET_PRICE", object: "DOMAIN",
|
|
47
|
+
attributes: { "domain" => domain_name, "period" => "1", "reg_type" => "new" })
|
|
48
|
+
price = price_result.dig("attributes", "price")&.to_f
|
|
49
|
+
end
|
|
50
|
+
price ||= lookup.dig("attributes", "price")&.to_f
|
|
51
|
+
|
|
52
|
+
DomainCheck.new(domain: domain_name, available: available, price: price)
|
|
53
|
+
rescue OpenSRS::DomainUnavailable
|
|
54
|
+
DomainCheck.new(domain: domain_name, available: false, price: nil)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def price(domain_name, period: 1, client: OpenSRS.default_client)
|
|
58
|
+
result = client.call(action: "GET_PRICE", object: "DOMAIN",
|
|
59
|
+
attributes: { "domain" => domain_name, "period" => period.to_s, "reg_type" => "new" })
|
|
60
|
+
result.dig("attributes", "price").to_f
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def suggest(search_string, tlds: [".com", ".net", ".org", ".io"], client: OpenSRS.default_client)
|
|
64
|
+
result = client.call(action: "NAME_SUGGEST", object: "DOMAIN",
|
|
65
|
+
attributes: { "searchstring" => search_string, "tlds" => tlds, "max_wait_time" => "5" })
|
|
66
|
+
attrs = result["attributes"] || {}
|
|
67
|
+
|
|
68
|
+
suggestions = []
|
|
69
|
+
%w[lookup suggestion].each do |category|
|
|
70
|
+
items = attrs.dig(category, "items")
|
|
71
|
+
next unless items.is_a?(Array)
|
|
72
|
+
items.each do |item|
|
|
73
|
+
next unless item.is_a?(Hash) && item["domain"]
|
|
74
|
+
suggestions << DomainSuggestion.new(
|
|
75
|
+
name: item["domain"],
|
|
76
|
+
available: item["status"] == "available"
|
|
77
|
+
)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
suggestions
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def find(domain_name, client: OpenSRS.default_client)
|
|
84
|
+
result = client.call(action: "GET", object: "DOMAIN",
|
|
85
|
+
attributes: { "type" => "all_info" },
|
|
86
|
+
extra: { "domain" => domain_name })
|
|
87
|
+
attrs = result["attributes"] || {}
|
|
88
|
+
from_api(domain_name, attrs, client: client)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def all(from: "2020-01-01", to: "2030-12-31", client: OpenSRS.default_client)
|
|
92
|
+
result = client.call(action: "GET_DOMAINS_BY_EXPIREDATE", object: "DOMAIN",
|
|
93
|
+
attributes: { "exp_from" => from, "exp_to" => to, "limit" => "200", "page" => "0" })
|
|
94
|
+
domains = result.dig("attributes", "exp_domains") || []
|
|
95
|
+
domains.map do |d|
|
|
96
|
+
new(
|
|
97
|
+
name: d["name"],
|
|
98
|
+
expires_at: parse_time(d["expiredate"]),
|
|
99
|
+
client: client
|
|
100
|
+
)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def transferable?(domain_name, client: OpenSRS.default_client)
|
|
105
|
+
result = client.call(action: "CHECK_TRANSFER", object: "DOMAIN",
|
|
106
|
+
attributes: { "domain" => domain_name, "check_status" => "1" })
|
|
107
|
+
result.dig("attributes", "transferrable") == "1"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def register!(domain_name, period: 1, contacts:, nameservers:, client: OpenSRS.default_client)
|
|
111
|
+
contact_set = {}
|
|
112
|
+
contacts.each do |role, data|
|
|
113
|
+
c = data.is_a?(Contact) ? data : Contact.new(**data)
|
|
114
|
+
contact_set[role.to_s] = c.to_api_hash
|
|
115
|
+
end
|
|
116
|
+
%w[admin billing].each { |r| contact_set[r] ||= contact_set["owner"] }
|
|
117
|
+
|
|
118
|
+
ns_list = nameservers.each_with_index.map do |ns, i|
|
|
119
|
+
{ "name" => ns, "sortorder" => (i + 1).to_s }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
reg_user = domain_name.gsub(/[^a-z0-9]/i, "")[0, 20]
|
|
123
|
+
reg_pass = Digest::MD5.hexdigest(domain_name + Time.now.to_s)[0, 20]
|
|
124
|
+
|
|
125
|
+
client.call(action: "SW_REGISTER", object: "DOMAIN", attributes: {
|
|
126
|
+
"domain" => domain_name,
|
|
127
|
+
"reg_type" => "new",
|
|
128
|
+
"period" => period.to_s,
|
|
129
|
+
"reg_username" => reg_user,
|
|
130
|
+
"reg_password" => reg_pass,
|
|
131
|
+
"handle" => "process",
|
|
132
|
+
"custom_nameservers" => "1",
|
|
133
|
+
"custom_tech_contact" => "0",
|
|
134
|
+
"auto_renew" => "0",
|
|
135
|
+
"f_whois_privacy" => "1",
|
|
136
|
+
"contact_set" => contact_set,
|
|
137
|
+
"nameserver_list" => ns_list,
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
new(name: domain_name, client: client, nameservers: nameservers)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def transfer!(domain_name, auth_code:, contacts:, nameservers: [], client: OpenSRS.default_client)
|
|
144
|
+
contact_set = {}
|
|
145
|
+
contacts.each do |role, data|
|
|
146
|
+
c = data.is_a?(Contact) ? data : Contact.new(**data)
|
|
147
|
+
contact_set[role.to_s] = c.to_api_hash
|
|
148
|
+
end
|
|
149
|
+
%w[admin billing].each { |r| contact_set[r] ||= contact_set["owner"] }
|
|
150
|
+
|
|
151
|
+
reg_user = domain_name.gsub(/[^a-z0-9]/i, "")[0, 20]
|
|
152
|
+
reg_pass = Digest::MD5.hexdigest(domain_name + Time.now.to_s)[0, 20]
|
|
153
|
+
|
|
154
|
+
attrs = {
|
|
155
|
+
"domain" => domain_name,
|
|
156
|
+
"reg_type" => "transfer",
|
|
157
|
+
"period" => "1",
|
|
158
|
+
"reg_username" => reg_user,
|
|
159
|
+
"reg_password" => reg_pass,
|
|
160
|
+
"handle" => "process",
|
|
161
|
+
"custom_nameservers" => nameservers.any? ? "1" : "0",
|
|
162
|
+
"custom_tech_contact" => "0",
|
|
163
|
+
"auto_renew" => "0",
|
|
164
|
+
"contact_set" => contact_set,
|
|
165
|
+
"auth_info" => auth_code,
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if nameservers.any?
|
|
169
|
+
attrs["nameserver_list"] = nameservers.each_with_index.map { |ns, i|
|
|
170
|
+
{ "name" => ns, "sortorder" => (i + 1).to_s }
|
|
171
|
+
}
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
client.call(action: "SW_REGISTER", object: "DOMAIN", attributes: attrs)
|
|
175
|
+
new(name: domain_name, client: client, nameservers: nameservers)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
private
|
|
179
|
+
|
|
180
|
+
def from_api(domain_name, attrs, client:)
|
|
181
|
+
nameservers = (attrs["nameserver_list"] || []).sort_by { |ns|
|
|
182
|
+
ns["sortorder"].to_i
|
|
183
|
+
}.map { |ns| ns["name"] }
|
|
184
|
+
|
|
185
|
+
contacts = {}
|
|
186
|
+
(attrs["contact_set"] || {}).each do |role, data|
|
|
187
|
+
contacts[role.to_sym] = Contact.from_hash(data) if data.is_a?(Hash)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
new(
|
|
191
|
+
name: domain_name,
|
|
192
|
+
client: client,
|
|
193
|
+
expires_at: parse_time(attrs["registry_expiredate"] || attrs["expiredate"]),
|
|
194
|
+
created_at: parse_time(attrs["registry_createdate"]),
|
|
195
|
+
updated_at: parse_time(attrs["registry_updatedate"]),
|
|
196
|
+
auto_renew: attrs["auto_renew"].to_s == "1",
|
|
197
|
+
locked: attrs["f_lock_domain"].to_s == "1",
|
|
198
|
+
whois_private: attrs["whois_privacy_state"] == "enabled",
|
|
199
|
+
nameservers: nameservers,
|
|
200
|
+
contacts: contacts
|
|
201
|
+
)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def parse_time(str)
|
|
205
|
+
return nil unless str && !str.empty?
|
|
206
|
+
Time.parse(str)
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def renew!(years: 1)
|
|
211
|
+
current = self.class.find(@name, client: @client)
|
|
212
|
+
expiry_year = current.expires_at&.year || Time.now.year
|
|
213
|
+
|
|
214
|
+
@client.call(action: "RENEW", object: "DOMAIN", attributes: {
|
|
215
|
+
"domain" => @name,
|
|
216
|
+
"auto_renew" => "0",
|
|
217
|
+
"handle" => "process",
|
|
218
|
+
"currentexpirationyear" => expiry_year.to_s,
|
|
219
|
+
"period" => years.to_s,
|
|
220
|
+
})
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def lock!
|
|
224
|
+
modify_setting("f_lock_domain", "1")
|
|
225
|
+
@locked = true
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def unlock!
|
|
229
|
+
modify_setting("f_lock_domain", "0")
|
|
230
|
+
@locked = false
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def set_nameservers(nameservers)
|
|
234
|
+
ns_list = nameservers.each_with_index.map { |ns, i|
|
|
235
|
+
{ "name" => ns, "sortorder" => (i + 1).to_s }
|
|
236
|
+
}
|
|
237
|
+
@client.call(action: "MODIFY", object: "DOMAIN",
|
|
238
|
+
attributes: {
|
|
239
|
+
"affect_domains" => "0",
|
|
240
|
+
"data" => "nameserver_list",
|
|
241
|
+
"assign_ns" => nameservers,
|
|
242
|
+
"nameserver_list" => ns_list
|
|
243
|
+
},
|
|
244
|
+
extra: { "domain" => @name })
|
|
245
|
+
@nameservers = nameservers
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def enable_whois_privacy!
|
|
249
|
+
@client.call(action: "SET", object: "DOMAIN",
|
|
250
|
+
attributes: { "affect_domains" => "0", "data" => "whois_privacy_state", "state" => "enable" },
|
|
251
|
+
extra: { "domain" => @name })
|
|
252
|
+
@whois_private = true
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def disable_whois_privacy!
|
|
256
|
+
@client.call(action: "SET", object: "DOMAIN",
|
|
257
|
+
attributes: { "affect_domains" => "0", "data" => "whois_privacy_state", "state" => "disable" },
|
|
258
|
+
extra: { "domain" => @name })
|
|
259
|
+
@whois_private = false
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def set_auto_renew(enabled)
|
|
263
|
+
@client.call(action: "MODIFY", object: "DOMAIN",
|
|
264
|
+
attributes: { "affect_domains" => "0", "data" => "expire_action",
|
|
265
|
+
"auto_renew" => enabled ? "1" : "0", "let_expire" => enabled ? "0" : "1" },
|
|
266
|
+
extra: { "domain" => @name })
|
|
267
|
+
@auto_renew = enabled
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
private
|
|
271
|
+
|
|
272
|
+
def modify_setting(key, value)
|
|
273
|
+
@client.call(action: "MODIFY", object: "DOMAIN",
|
|
274
|
+
attributes: { "affect_domains" => "0", "data" => "status", key => value },
|
|
275
|
+
extra: { "domain" => @name })
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module OpenSRS
|
|
2
|
+
class Error < StandardError; end
|
|
3
|
+
|
|
4
|
+
class ConnectionError < Error; end
|
|
5
|
+
|
|
6
|
+
class RequestError < Error
|
|
7
|
+
attr_reader :response_code
|
|
8
|
+
|
|
9
|
+
def initialize(message = nil, response_code = nil)
|
|
10
|
+
@response_code = response_code
|
|
11
|
+
super(message)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class AuthenticationError < RequestError; end
|
|
16
|
+
class DomainNotFound < RequestError; end
|
|
17
|
+
class DomainUnavailable < RequestError; end
|
|
18
|
+
class TransferError < RequestError; end
|
|
19
|
+
class InsufficientBalance < RequestError; end
|
|
20
|
+
end
|
data/lib/opensrs.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require_relative "opensrs/errors"
|
|
2
|
+
require_relative "opensrs/contact"
|
|
3
|
+
require_relative "opensrs/client"
|
|
4
|
+
require_relative "opensrs/account"
|
|
5
|
+
require_relative "opensrs/domain"
|
|
6
|
+
|
|
7
|
+
module OpenSRS
|
|
8
|
+
class << self
|
|
9
|
+
attr_reader :default_client
|
|
10
|
+
|
|
11
|
+
def configure(username:, api_key:, test: false)
|
|
12
|
+
@default_client = Client.new(username: username, api_key: api_key, test: test)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def reset!
|
|
16
|
+
@default_client = nil
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: opensrs-ruby
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- usiegj00
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: minitest
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '5.0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '5.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rake
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '13.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '13.0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: webmock
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '3.0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '3.0'
|
|
54
|
+
email:
|
|
55
|
+
- 248302+usiegj00@users.noreply.github.com
|
|
56
|
+
executables: []
|
|
57
|
+
extensions: []
|
|
58
|
+
extra_rdoc_files: []
|
|
59
|
+
files:
|
|
60
|
+
- lib/opensrs.rb
|
|
61
|
+
- lib/opensrs/account.rb
|
|
62
|
+
- lib/opensrs/client.rb
|
|
63
|
+
- lib/opensrs/contact.rb
|
|
64
|
+
- lib/opensrs/domain.rb
|
|
65
|
+
- lib/opensrs/errors.rb
|
|
66
|
+
homepage: https://github.com/aluminumio/opensrs-gem
|
|
67
|
+
licenses:
|
|
68
|
+
- MIT
|
|
69
|
+
metadata: {}
|
|
70
|
+
rdoc_options: []
|
|
71
|
+
require_paths:
|
|
72
|
+
- lib
|
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
|
+
requirements:
|
|
75
|
+
- - ">="
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '3.1'
|
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
requirements: []
|
|
84
|
+
rubygems_version: 3.6.9
|
|
85
|
+
specification_version: 4
|
|
86
|
+
summary: Ruby client for the OpenSRS domain registration API
|
|
87
|
+
test_files: []
|