├── .gitignore ├── LICENSE ├── README.md ├── example.js ├── lib └── inwx.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | node_modules 15 | npm-debug.log 16 | 17 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Matthias Kadenbach 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | inwx-nodejs 2 | =========== 3 | This is a deprecated project. You can find our current official Node.js client here: [INWX Domrobot Node.js](https://github.com/inwx/nodejs-client) 4 | 5 | 6 | License (MIT) 7 | ------------- 8 | Released under the MIT license. See the LICENSE file for the complete wording. 9 | 10 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | var http = require('http') // or https 2 | var inwx = require('inwx'); 3 | 4 | 5 | /* 6 | * Get my IP address and update 7 | * nameserver records for testtest123.info 8 | */ 9 | 10 | // retrieve my ip ... 11 | http.get("http://echoip.com", function(res) { 12 | res.on("data", function(data){ 13 | var IP_ADDRESS = data + ""; // @todo ip address validation!!!! 14 | 15 | // connect to inwx 16 | inwx({api: "testing", user: "max", password: "pass"}, function(api){ 17 | 18 | // update nameserver 19 | // @todo update on changes only 20 | api.nameserverRecordHelper("testtest123.info", "update", {content: IP_ADDRESS}, {type: "A"}, function(response) { 21 | console.log("IP updated to " + IP_ADDRESS); 22 | }); 23 | 24 | api.close(); 25 | }); 26 | }); 27 | 28 | res.on("error", function(e){ 29 | console.error(e.message); 30 | }); 31 | 32 | }); 33 | 34 | -------------------------------------------------------------------------------- /lib/inwx.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * inwx 1.0.0 3 | * https://github.com/mattes/inwx-nodejs 4 | * 5 | * Copyright 2012 Matthias Kadenbach 6 | * Released under the MIT license 7 | * 8 | * 9 | * INWX XML-RPC API DOC: 10 | * https://www.inwx.de/de/help#key=20 11 | * https://www.inwx.de/de/download/file/api-current.zip (logged in inwx customers only) 12 | */ 13 | 14 | var xmlrpc = require('xmlrpc'); 15 | 16 | /* 17 | * init inwx api and call readyCallback when ready 18 | * @param opts {api: production|testing, user: string, password: string} 19 | * @param readyCallback call when api is ready 20 | * @param errorCallback call on error (optional) 21 | */ 22 | function inwx(opts, readyCallback, errorCallback) { 23 | this.connected = false; 24 | var that = this; 25 | 26 | // Invokes with new if called without 27 | if (false === (this instanceof inwx)) { 28 | return new inwx(opts, readyCallback); 29 | } 30 | 31 | if(!opts.user || !opts.password) throw new Error("missing user and/or password"); 32 | if(!opts.host) opts.host = opts.api == "production" ? "api.domrobot.com" : "api.ote.domrobot.com"; 33 | 34 | this.client = xmlrpc.createSecureClient({ host: opts.host, path: "/xmlrpc/", cookies: true }); 35 | 36 | this.call("account", "login", {user: opts.user, pass: opts.password}, 37 | function(response) { 38 | this.connected = true; 39 | readyCallback.call(this, that); 40 | }, 41 | function (error) { 42 | if(errorCallback) { 43 | errorCallback.call(this, error); 44 | } else { 45 | throw new Error(error.msg); 46 | } 47 | }); 48 | 49 | return that; 50 | } 51 | 52 | /* 53 | * make remote xmlrpc api call 54 | * @param object object to call (see inwx api doc) 55 | * @param method method to call (see inwx api doc) 56 | * @param params {key: value[, ...]} 57 | * @param successCallback call when api call was successful 58 | * @param errorCallback call on error (optional) 59 | */ 60 | inwx.prototype.call = function call(object, method, params, successCallback, errorCallback) { 61 | if(!object) throw new Error("missing object for xmlrpc call"); 62 | if(!method) throw new Error("missing method for xmlrpc call"); 63 | 64 | this.client.methodCall(object + "." + method, [ params ], function(error, response){ 65 | if(error) { 66 | // xmlrpc error 67 | if(errorCallback) { 68 | errorCallback.call(this, error); 69 | } else { 70 | throw new Error(error.message); 71 | } 72 | } else { 73 | if(parseInt(response.code) < 2000) { 74 | // no errors 75 | if(successCallback) successCallback.call(this, response.resData); 76 | } else { 77 | // error from inwx error? 78 | if(errorCallback) { 79 | errorCallback.call(this, response); 80 | } else { 81 | var additionalReason = response.reason ? " + " + response.reason + "(AdditionalCode " + response.reasonCode + ")": ""; 82 | console.error("ERROR: " + object + "." + method + "(" + JSON.stringify(params) + ") returned: " + response.msg + " (Code " + response.code + ")" + (additionalReason ? additionalReason : "")); 83 | throw new Error(response.msg); 84 | } 85 | } 86 | } 87 | }); 88 | }; 89 | 90 | /* 91 | * logout from api 92 | */ 93 | inwx.prototype.close = function close() { 94 | if(this.connected) this.call("account", "logout"); 95 | } 96 | 97 | 98 | 99 | /* 100 | * a helper method for nameserver operations 101 | * @param domain existing domain from your nameserver sets 102 | * @param command create|update|delete 103 | * @param opt1, opt2, opt3, opt4 changes depending on command, see examples below 104 | * 105 | * examples: 106 | * nameserverRecordHelper("example.com", "create", {key: value[, ...]}, successCallback, errorCallback) 107 | * nameserverRecordHelper("example.com", "update", {key: value[, ...]}, {where_key: value[, ...]}, successCallback, errorCallback) 108 | * nameserverRecordHelper("example.com", "delete", {where_key: value[, ...]}, successCallback, errorCallback) 109 | * 110 | * successCallback and errorCallback are optional 111 | * 112 | * SOA revision number is updated automatically by inwx 113 | */ 114 | inwx.prototype.nameserverRecordHelper = function nameserverRecordHelper(domain, command, opt1, opt2, opt3, opt4) { 115 | var that = this; 116 | switch(command) { 117 | 118 | case "create": 119 | var values = opt1, successCallback = opt2, errorCallback = opt3; 120 | if(!values) throw new Error("missing values parameter"); 121 | 122 | values.domain = domain; 123 | this.call("nameserver", "createRecord", values, successCallback, errorCallback); 124 | break; 125 | 126 | case "update": 127 | var values = opt1, where = opt2, successCallback = opt3, errorCallback = opt4; 128 | if(!values) throw new Error("missing values parameter"); 129 | if(!where) throw new Error("missing where parameter"); 130 | 131 | this.call("nameserver", "info", {domain: domain}, function(nameserverRecords) { 132 | if(!nameserverRecords.count > 0) successCallback.call(this, []); 133 | 134 | // find matches in existing nameserver records 135 | var updateRecords = that._findAndReturnMatchesInNameserverRecords(where, nameserverRecords.record); 136 | var updateRecordsLength = updateRecords.length; 137 | if(!updateRecordsLength > 0) successCallback.call(this, []); 138 | 139 | // update found matches 140 | if(updateRecordsLength > 0) { 141 | var updatedRecordIds = []; 142 | var callbackCounter = 0; 143 | updateRecords.forEach(function(record) { 144 | updatedRecordIds.push(record.id); 145 | var updateValues = values; 146 | updateValues.id = record.id; 147 | that.call("nameserver", "updateRecord", updateValues, function(){ 148 | callbackCounter++; 149 | if(callbackCounter == updateRecordsLength) { 150 | // as soon as last record was updated, fetch updated records and return them 151 | // @todo: add timeout, if callbackCounter does not reach updateRecordsLength 152 | 153 | that.call("nameserver", "info", {domain: domain}, function(nameserverRecords) { 154 | if(!nameserverRecords.count > 0) throw new Error("oh, i updated nameserver records and now everything is gone?!"); 155 | 156 | var updatedRecords = []; 157 | nameserverRecords.record.forEach(function(record){ 158 | if(updatedRecordIds.indexOf(record.id) >= 0) updatedRecords.push(record); 159 | }); 160 | successCallback.call(that, updatedRecords); 161 | }); 162 | } 163 | }); 164 | }); 165 | } 166 | }); 167 | break; 168 | 169 | case "delete": 170 | var where = opt1, successCallback = opt2, errorCallback = opt3; 171 | if(!where) throw new Error("missing where parameter"); 172 | 173 | this.call("nameserver", "info", {domain: domain}, function(nameserverRecords) { 174 | if(!nameserverRecords.count > 0) successCallback.call(this, []); 175 | 176 | // find matches in existing nameserver records 177 | var deleteRecords = that._findAndReturnMatchesInNameserverRecords(where, nameserverRecords.record); 178 | var deleteRecordsLength = deleteRecords.length; 179 | if(!deleteRecordsLength > 0) successCallback.call(this, []); 180 | 181 | // delete found matches 182 | if(deleteRecordsLength > 0) { 183 | var callbackCounter = 0; 184 | deleteRecords.forEach(function(record) { 185 | that.call("nameserver", "deleteRecord", {id: record.id}, function(){ 186 | callbackCounter++; 187 | if(callbackCounter == deleteRecordsLength) { 188 | // as soon as last record was deleted, call callback 189 | // @todo: add timeout, if callbackCounter does not reach deleteRecordsLength 190 | successCallback.call(that, deleteRecords); 191 | } 192 | }); 193 | }); 194 | } 195 | }); 196 | break; 197 | } 198 | } 199 | 200 | /* 201 | * internal helper to find matches in nameserver records 202 | * @param where {where_key: value[, ...]} 203 | * @param nameserverRecords [ {record}[, {...}] ] 204 | */ 205 | inwx.prototype._findAndReturnMatchesInNameserverRecords = function _findAndReturnMatchesInNameserverRecords(where, nameserverRecords) { 206 | var foundRecords = []; 207 | var whereKeys = Object.keys(where); 208 | var whereKeysLength = whereKeys.length; 209 | nameserverRecords.forEach(function(record) { 210 | var foundFlag = 0; 211 | whereKeys.forEach(function(key){ 212 | if(record[key] == where[key]) foundFlag++; 213 | }); 214 | if(foundFlag == whereKeysLength) foundRecords.push(record); 215 | }); 216 | return foundRecords; 217 | } 218 | 219 | 220 | 221 | 222 | module.exports = inwx; 223 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { "name" : "inwx" 2 | , "description" : "INWX XML-RPC API Client" 3 | , "keywords" : [ "inwx", "InterNetworX", "nameserver", "dyndns", "dns", "domain", "api", "xml-rpc", "xmlrpc", "xml", "rpc" ] 4 | , "version" : "1.0.0" 5 | , "preferGlobal" : false 6 | , "homepage" : "https://github.com/mattes/inwx-nodejs" 7 | , "author" : "Matthias Kadenbach (https://github.com/mattes)" 8 | , "repository" : { 9 | "type" : "git" 10 | , "url" : "git://github.com/mattes/inwx-nodejs.git" 11 | } 12 | , "bugs" : { 13 | "url" : "https://github.com/mattes/inwx-nodejs/issues" 14 | } 15 | , "directories" : { 16 | "lib" : "./lib" 17 | } 18 | , "main" : "./lib/inwx.js" 19 | , "dependencies" : { 20 | "xmlrpc" : ">=1.1.0" 21 | } 22 | , "engines" : { 23 | "node" : ">=0.8", 24 | "npm" : ">=1.0.0" 25 | } 26 | , "licenses" : [ { 27 | "type" : "MIT" 28 | , "url" : "https://raw.github.com/mattes/inwx-nodejs/master/LICENSE" 29 | } 30 | ] 31 | } 32 | 33 | --------------------------------------------------------------------------------