diff --git a/.gitignore b/.gitignore index f2c1360..279d4a5 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ /test/tmp/ /test/version_tmp/ /tmp/ +vendor/ ## Specific to RubyMotion: .dat* diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..7e2237b --- /dev/null +++ b/Gemfile @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +gem 'json' +gem 'rotp' +gem 'xmlrpc' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..40c29e3 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,21 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) + json (2.2.0) + public_suffix (4.0.1) + rotp (5.1.0) + addressable (~> 2.5) + xmlrpc (0.3.0) + +PLATFORMS + ruby + +DEPENDENCIES + json + rotp + xmlrpc + +BUNDLED WITH + 1.16.1 diff --git a/README.md b/README.md index 129c946..8c4c622 100644 --- a/README.md +++ b/README.md @@ -16,31 +16,43 @@ You can view a detailed description of the API functions in our documentation. Y If you still experience any kind of problems don't hesitate to contact our [support via email](mailto:support@inwx.de). +Installation +------- + +```bash +gem install inwx-domrobot +``` + Example ------- ```ruby -require "inwx/Domrobot" -require "yaml" +require 'inwx-domrobot' +require 'pp' + +user = '' +pass = '' -addr = "api.ote.domrobot.com" -# addr = "api.domrobot.com" -user = "your_username" -pass = "your_password" +domrobot = INWX::Domrobot.new -domrobot = INWX::Domrobot.new(addr) +result = domrobot.set_language('en'). + use_ote. + use_json. + set_debug(true). + login(user, pass) -result = domrobot.login(user,pass) -puts YAML::dump(result) +object = 'domain' +method = 'check' -object = "domain" -method = "check" +params = { domain: 'mydomain.com' } -params = { :domain => "mydomain.com" } +if result['code'] == 1000 + result = domrobot.call(object, method, params) -result = domrobot.call(object, method, params) + domrobot.logout +end -puts YAML::dump(result) +pp result ``` You can also look at the example.rb in the Project. diff --git a/example.rb b/example.rb old mode 100644 new mode 100755 index 4d540c0..0053da1 --- a/example.rb +++ b/example.rb @@ -1,22 +1,38 @@ -#!/usr/bin/env ruby -require "./inwx/Domrobot" -require "yaml" - -addr = "api.ote.domrobot.com" -# addr = "api.domrobot.com" -user = "your_username" -pass = "your_password" - -domrobot = INWX::Domrobot.new(addr) - -result = domrobot.login(user,pass) -puts YAML::dump(result) - -object = "domain" -method = "check" - -params = { :domain => "mydomain.com" } - -result = domrobot.call(object, method, params) - -puts YAML::dump(result) +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'inwx-domrobot' +require 'pp' + +# Get your credentials from a safe place when using in production +user = '' +pass = '' + +domrobot = INWX::Domrobot.new + +result = domrobot.set_language('en'). + # use the OTE endpoint + use_ote. + # or use the LIVE endpoint instead + # use_live. + # use the JSON-RPC API + use_json. + # or use the XML-RPC API instead + # use_xml. + # output everything you're sending and receiving in JSON pretty print + set_debug(true). + # optional 3rd parameter available: shared_secret for 2 factor auth + login(user, pass) + +object = 'domain' +method = 'check' + +params = { domain: 'mydomain.com' } + +if result['code'] == 1000 + result = domrobot.call(object, method, params) + + domrobot.logout +end + +pp result diff --git a/inwx-domrobot.gemspec b/inwx-domrobot.gemspec new file mode 100644 index 0000000..2fdeb1e --- /dev/null +++ b/inwx-domrobot.gemspec @@ -0,0 +1,13 @@ +Gem::Specification.new do |s| + s.name = 'inwx-domrobot' + s.version = '3.0' + s.date = '2019-09-12' + s.summary = "INWX Domrobot" + s.description = "Ruby Client to easily use the Domrobot API of INWX" + s.authors = ["INWX"] + s.email = 'support@inwx.de' + s.files = ["lib/inwx-domrobot.rb"] + s.homepage = + 'https://rubygems.org/gems/inwx-domrobot' + s.license = 'MIT' + end diff --git a/inwx/Domrobot.rb b/inwx/Domrobot.rb deleted file mode 100644 index 64587e8..0000000 --- a/inwx/Domrobot.rb +++ /dev/null @@ -1,52 +0,0 @@ -require "xmlrpc/client" - -module INWX - class Domrobot - attr_accessor :client, :cookie - - def initialize(address) - @cookie = "" - # Create a new client instance - @client = XMLRPC::Client.new(address,"/xmlrpc/","443", nil, nil, nil, nil, true, 100) - end - - def login(username = false, password = false, language = 'en') - params = { :user => username, :pass => password, 'lang' => language } - ret = call("account","login",params) - cookie = client.cookie - unless cookie.nil? || cookie.length <= 2 - setCookie(cookie) - end - return ret - end - - def logout() - call("account","logout") - end - - def setCookie(cookie) - self.cookie = cookie - fp = File.new("domrobot.tmp", "w") - fp.write(cookie) - fp.close - end - - def getCookie() - if self.cookie.length > 2 - return self.cookie - end - if File.exist?("domrobot.tmp") - fp = File.new("domrobot.tmp", "r") - cookie = fp.read() - fp.close - return cookie - end - end - - def call(object, method, params = {}) - client.cookie = getCookie() - # Call the remote method - client.call(object+"."+method, params) - end - end -end diff --git a/lib/inwx-domrobot.rb b/lib/inwx-domrobot.rb new file mode 100644 index 0000000..e01a18c --- /dev/null +++ b/lib/inwx-domrobot.rb @@ -0,0 +1,135 @@ +# frozen_string_literal: true + +require 'xmlrpc/client' +require 'json' +require 'net/http' +require 'net/https' +require 'rotp' + +module INWX + class Domrobot + attr_accessor :client, :cookie, :language, :api_type, :url, :debug + URL_LIVE = 'api.domrobot.com' + URL_OTE = 'api.ote.domrobot.com' + TYPE_JSON = '/jsonrpc/' + TYPE_XML = '/xmlrpc/' + private_constant :TYPE_JSON, :TYPE_XML, :URL_OTE, :URL_LIVE + + def initialize + self.cookie = '' + self.debug = false + self.url = URL_OTE + self.api_type = TYPE_JSON + end + + def set_language(language = 'en') + self.language = language + self + end + + def use_ote + self.url = URL_OTE + self + end + + def use_live + self.url = URL_LIVE + self + end + + def use_json + self.api_type = TYPE_JSON + self + end + + def use_xml + self.api_type = TYPE_XML + self + end + + def set_debug(value) + self.debug = value + self + end + + def create_client + if api_type == TYPE_XML + self.client = XMLRPC::Client.new(url, api_type, '443', nil, nil, nil, nil, true, 100) + else + self.client = Net::HTTP.new(url, 443) + client.use_ssl = true + end + end + + def login(username = false, password = false, shared_secret = nil) + create_client + + params = { user: username, pass: password, lang: language } + ret = call('account', 'login', params) + + unless shared_secret.nil? + secret_code = get_secret_code(shared_secret) + ret = call('account', 'unlock', tan: secret_code) + end + + ret + end + + def logout + call('account', 'logout') + end + + def call(object, method, params = {}) + if api_type == TYPE_XML + call_xml(object, method, params) + else + call_json(object, method, params) + end + end + + def call_xml(object, method, params = {}) + client.cookie = cookie + res = client.call(object + '.' + method, params) + + save_cookie(client.cookie) + debug_sent = { method: object + '.' + method, params: params } + output_debug(debug_sent.to_json, res.to_json) + + res + end + + def call_json(object, method, params = {}) + req = Net::HTTP::Post.new(api_type) + + json_params = { method: object + '.' + method, params: params } + + req.body = json_params.to_json + req['Cookie'] = cookie + res = client.request(req) + + save_cookie(res.response['set-cookie']) + output_debug(req.body, res.body) + + JSON.parse(res.body) + end + + def save_cookie(cookie) + self.cookie = cookie unless cookie.nil? + end + + def output_debug(sent, received) + if debug + puts 'Sent:' + puts JSON.pretty_generate(JSON.parse(sent)) + puts 'Received:' + puts JSON.pretty_generate(JSON.parse(received)) + puts '-------------------------' + end + end + + def get_secret_code(shared_secret) + totp = ROTP::TOTP.new(shared_secret) + totp.now + end + end +end