Permalink
Browse files

add dnspod-ddns 0.1

  • Loading branch information...
0 parents commit 0c09a09ca41fe027898bd85efebc234448894e8a @ohsc ohsc committed Nov 15, 2012
Showing with 327 additions and 0 deletions.
  1. +12 −0 .gitignore
  2. +31 −0 README.md
  3. +44 −0 bin/cli.js
  4. +174 −0 lib/index.js
  5. +20 −0 lib/timeTicker.js
  6. +46 −0 package.json
@@ -0,0 +1,12 @@
+.DS_Store
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.swp
+*.swo
+testing
+node_modules
+.nide
@@ -0,0 +1,31 @@
+# dnspod-ddns
+
+dnspod-ddns is a ddns updating tool of [DNSPod](http://www.dnspod.cn).
+It was originally designed for use with [node.js](http://nodejs.org).
+
+
+## Download
+
+You can install using Node Package Manager (npm):
+
+```sh
+npm install -g dnspod-ddns
+```
+
+## Usage
+
+dnspod-ddns is a command line tool. It will update your dns record after you execute the following. You can add it to crontab for continuously updating.
+
+```sh
+dnspod-ddns --dns-domain yourdomain.com --dns-host yourhost --user youremail --passwd yourpassword
+```
+
+Otherwise, you can run it in daemon mode.
+
+```sh
+dnspod-ddns --dns-domain yourdomain.com --dns-host yourhost --user youremail --passwd yourpassword --daemon
+```
+
+## License
+
+Copyright (c) 2012 Chao Shen. This software is licensed under the BSD License.
@@ -0,0 +1,44 @@
+#!/usr/bin/env node
+
+var fs = require('fs'),
+ program = require('commander'),
+ ddns = require('../'),
+ options;
+
+
+program
+ .version('0.0.1')
+ .usage('[options] [value ...]')
+ .option('-d, --dns-domain <domain>', 'Set domain name(*required)')
+ .option('-H, --dns-host <host>', 'Set host name(*required)')
+ .option('-u, --user <user>', 'Set user name(*required)')
+ .option('-p, --passwd <password>', 'Set password(*required)')
+ .option('-D, --daemon', 'Start as daemon mode')
+ .parse(process.argv);
+
+if (!program.dnsDomain) {
+ console.log('--dns-domain is required.');
+ process.exit(-1);
+} else if (!program.dnsHost) {
+ console.log('--dns-host is required.');
+ process.exit(-1);
+} else if (!program.user) {
+ console.log('--user is required.');
+ process.exit(-1);
+} else if (!program.passwd) {
+ console.log('--passwd is required.');
+ process.exit(-1);
+} else {
+ options = {
+ domain: program.dnsDomain,
+ sub_domain: program.dnsHost,
+ login_email: program.user,
+ login_password: program.passwd,
+ is_daemon: program.daemon
+ };
+ console.log('received args %j', options);
+ ddns.run(options);
+}
+
+
+
@@ -0,0 +1,174 @@
+var async = require('async'),
+ Dnspod = require('dnspod-client'),
+ TimeTicker = require('./timeTicker');
+
+function ctxFilter(paramsArr, extObj) {
+ var subCtx = {},
+ self = this;
+ paramsArr.forEach(function (key) {
+ if (self[key]) {
+ subCtx[key] = self[key];
+ }
+ });
+
+ if (extObj) {
+ Object.keys(extObj).forEach(function (key) {
+ subCtx[key] = extObj[key];
+ });
+ }
+
+ return subCtx;
+}
+
+function updateIp(context, doneFn) {
+ var params = ctxFilter.bind(context),
+ client = new Dnspod(params(['login_email', 'login_password']));
+
+ async.waterfall([
+ function (callback) {
+ client
+ .recordList(params(['domain_id', 'sub_domain'], {length: 5}))
+ .on('recordList', callback);
+ },
+ function (result, callback) {
+ if (result.status.code === "1") {
+ if (result.records.length > 0) {
+ context.record_id = result.records[0].id;
+ context.record_value = result.records[0].value;
+ callback(null);
+ } else {
+ callback(new Error('Can not found any matched host.'));
+ }
+ } else {
+ callback(new Error(result.status.message));
+ }
+ }
+ ], function (err) {
+ if (err) {
+ console.log(err);
+ }
+ if (doneFn) {
+ doneFn(err);
+ }
+ });
+}
+
+function requestIds(context, doneFn) {
+ var params = ctxFilter.bind(context),
+ client = new Dnspod(params(['login_email', 'login_password']));
+ async.waterfall([
+ function (callback) {
+ //request domain id
+ client
+ .domainInfo(params(['domain']))
+ .on('domainInfo', callback);
+ },
+ function (result, callback) {
+ if (result.status.code === "1") {
+ //export to global
+ context.domain_id = result.domain.id;
+ callback(null);
+ } else {
+ callback(new Error(result.status.message));
+ }
+ },
+ function (callback) {
+ updateIp(context, callback);
+ }
+ ], doneFn);
+}
+
+function updateDdns(context, doneFn) {
+ var params = ctxFilter.bind(context),
+ client = new Dnspod(params(['login_email', 'login_password']));
+
+ async.waterfall([
+ function (callback) {
+ client
+ .getHostIp()
+ .on('getHostIp', callback);
+ },
+ function (result, callback) {
+ var oldIp = context.record_value;
+
+ console.log('Old ip address is %j, while new ip address is %j', oldIp, result);
+
+ if (result !== oldIp) {
+ //export to global
+ context.record_value = result;
+ callback(null, true);
+ } else {
+ callback(null, false);
+ }
+ },
+ function (result, callback) {
+ if (result) {
+ client
+ .recordDdns(params([
+ 'domain_id',
+ 'record_id',
+ 'sub_domain',
+ 'record_line'
+ ]))
+ .on('recordDdns', callback);
+ }
+ }
+ ], function (err, result) {
+ if (err) {
+ console.log(err);
+ } else {
+ console.log(result);
+ }
+ if (doneFn) {
+ doneFn(err, result);
+ }
+ });
+}
+
+function runAsDaemon(context) {
+ var ticker = new TimeTicker(60 * 1000, 5 * 60 * 1000);
+ ticker.on('tick', function () {
+ updateDdns(context, function (err, result) {
+ if (err) {
+ process.exit(-1);
+ }
+ });
+ });
+ ticker.on('wideTick', function () {
+ updateIp(context, function (err, result) {
+ if (err) {
+ process.exit(-1);
+ }
+ });
+ });
+}
+
+function run(options) {
+ var context = {
+ domain: options.domain,
+ sub_domain: options.sub_domain,
+ login_email: options.login_email,
+ login_password: options.login_password,
+ domain_id: '',
+ record_id: '',
+ record_value: '',
+ record_line: '默认'
+ };
+ requestIds(context, function (err, result) {
+ if (err) {
+ console.log('request ids failed with error: %j', err.message);
+ } else {
+ if (options.is_daemon) {
+ runAsDaemon(context);
+ } else {
+ updateDdns(context);
+ }
+ }
+ });
+}
+
+module.exports = {
+ requestIds: requestIds,
+ updateDdns: updateDdns,
+ run: run
+};
@@ -0,0 +1,20 @@
+var EventEmitter = require('events').EventEmitter,
+ util = require('util');
+
+function TimeTicker(interval, wideInterval) {
+ var self = this,
+ count = 0,
+ len = wideInterval / interval,
+ nextTick = function () {
+ if (count === 0) {
+ self.emit('wideTick');
+ }
+ self.emit('tick');
+ count = (count + 1) % len;
+ setTimeout(nextTick, interval);
+ };
+ process.nextTick(nextTick);
+}
+util.inherits(TimeTicker, EventEmitter);
+
+module.exports = TimeTicker;
@@ -0,0 +1,46 @@
+{
+ "name": "dnspod-ddns",
+ "description": "A DNSPOD DDNS Client",
+ "version": "0.1.0",
+ "keywords": [
+ "dnspod",
+ "ddns",
+ "update record"
+ ],
+ "homepage": "https://github.com/ohsc/dnspod-ddns",
+ "author": {
+ "name": "Chao Shen",
+ "email": "shen218@gmail.com"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/ohsc/dnspod-ddns.git"
+ },
+ "bugs": {
+ "url": "http://github.com/ohsc/dnspod-ddns/issues"
+ },
+ "licenses": [
+ {
+ "type": "BSD",
+ "url": "http://github.com/ohsc/dnspod-ddns/raw/master/LICENSE.md"
+ }
+ ],
+ "main": "./lib/index.js",
+ "bin": {
+ "dnspod-ddns": "./bin/cli.js"
+ },
+ "dependencies": {
+ "dnspod-client": "0.1.2",
+ "commander": "1.0.5",
+ "async": "0.1.22"
+ },
+ "devDependencies": {
+ "mocha": ">= 1.5.0",
+ "jslint": ">= 0.1.9"
+ },
+ "scripts": {
+ "test": "node_modules/.bin/mocha test/test.js",
+ "lint": "find . -name '*.js' -not -regex './node_modules.*' -print0 | xargs -0 ./node_modules/.bin/jslint --sloppy --stupid --node --color --git"
+ },
+ "readmeFilename": "README.md"
+}

0 comments on commit 0c09a09

Please sign in to comment.