From a5d307f435a01a4450330fa37d797750d774b820 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 13 Mar 2017 22:25:23 +0800 Subject: [PATCH] first version --- .gitignore | 2 + app.js | 107 ++++++++++++++++++++++++++++++++++++++++++++ config.sample.json | 17 +++++++ libs/storeObject.js | 68 ++++++++++++++++++++++++++++ package.json | 19 ++++++++ 5 files changed, 213 insertions(+) create mode 100644 .gitignore create mode 100644 app.js create mode 100644 config.sample.json create mode 100644 libs/storeObject.js create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..95b863a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +config.json +node_modules diff --git a/app.js b/app.js new file mode 100644 index 0000000..23ea71e --- /dev/null +++ b/app.js @@ -0,0 +1,107 @@ +const request = require('request'); +const config = require('./config.json'); +const so = require('./libs/storeObject'); + +/** + * @param {string} uri + * @param {string} method + * @param {object} data + */ +async function urlRequest(uri, method = 'GET', data = {}) { + return new Promise((resolve, reject) => { + let token = so.get('token'); + + let headers = { + 'X-Auth-Token': token && token.id ? token.id : '', + 'Accept': 'application/json', + 'Content-Type': 'application/json' + } + let json = { + method, + uri, + headers, + json: data + }; + request(json, (err, res, body) => { + if (err) return reject(err); + if (res.statusCode != 200) return reject(`HTTP Request Fail , URL: ${uri} , StatusCode: ${res.statusCode} , Reponse: ${JSON.stringify(body)}`); + return resolve(body); + }); + }) +} + +const runUpdateDNS = async() => { + try { + let ip = await urlRequest('http://ip.trj.tw/getip.php'); + console.log(`${Date.now()} // get public ip: ${ip}`); + + let t = so.get('token'); + if (t == null || ('etime' in t && t.etime < Date.now() + 30000)) { + + let tokenData = await urlRequest(`${config.api.url.identity}/tokens`, 'POST', { + 'auth': { + 'passwordCredentials': { + 'username': config.api.username, + 'password': config.api.password + }, + 'tenantId': config.api.tenantid + } + }); + let { token } = tokenData.access; + token.etime = new Date(token.expires).getTime(); + so.set('token', token); + console.log(`${Date.now()} - get api token: ${token.id}, expire: ${token.expires}`); + } + + let domainsData = await urlRequest(`${config.api.url.dns}/v1/domains`); + for (let i in domainsData.domains) { + let tmp = domainsData.domains[i]; + for (let j in config.domain) { + if (config.domain[j].name == tmp.name) { + config.domain[j].id = tmp.id; + console.log(`${Date.now()} - get domain ${config.domain[i].name} id: ${tmp.id}`); + } + } + } + + for (let i in config.domain) { + if (!('id' in config.domain[i])) continue; + let data = await urlRequest(`${config.api.url.dns}/v1/domains/${config.domain[i].id}/records`); + for (let j in data.records) { + let tmp = data.records[j]; + if (!/^a$/i.test(tmp.type)) continue; + for (let k in config.domain[i].sub) { + let ctmp = config.domain[i].sub[k]; + if (tmp.name == `${ctmp.name}.${config.domain[i].name}`) { + ctmp.id = tmp.id; + ctmp.changed = ip == tmp.data ? false : true; + console.log(`${Date.now()} - get record ${ctmp.name}.${config.domain[i].name} id: ${tmp.id}`); + } + } + } + } + + for (let i in config.domain) { + if (!('id' in config.domain[i])) continue; + let id = config.domain[i].id; + for (let j in config.domain[i].sub) { + let tmp = config.domain[i].sub[j]; + if (!('id' in tmp) || !('changed' in tmp)) continue; + if (!tmp.changed) { + console.log(`${Date.now()} - dns record ${tmp.name}.${config.domain[i].name} ip not change`); + continue; + } + await urlRequest(`${config.api.url.dns}/v1/domains/${id}/records/${tmp.id}`, 'PUT', { data: ip }); + console.log(`${Date.now()} - dns record ${tmp.name}.${config.domain[i].name} update finish`); + } + } + + } catch (e) { + console.log(`${Date.now()} - ${e}`); + return; + } + +}; + +runUpdateDNS(); +setInterval(() => runUpdateDNS(), 300000); \ No newline at end of file diff --git a/config.sample.json b/config.sample.json new file mode 100644 index 0000000..78bc965 --- /dev/null +++ b/config.sample.json @@ -0,0 +1,17 @@ +{ + "api": { + "username": "", + "password": "", + "tenantid": "", + "url": { + "identity": "https://identity.tyo1.conoha.io/v2.0", + "dns": "https://dns-service.tyo1.conoha.io" + } + }, + "domain": [{ + "name": "example.com", + "sub": [ + "sub1" + ] + }] +} \ No newline at end of file diff --git a/libs/storeObject.js b/libs/storeObject.js new file mode 100644 index 0000000..f6a79f3 --- /dev/null +++ b/libs/storeObject.js @@ -0,0 +1,68 @@ +const StoreObj = (() => { + + let memStore = {}; + let maxAge = 3600000; + + /** + * @param {string} uuid + * @param {object} obj + */ + const set = (uuid, obj) => { + memStore[uuid] = { + obj, + age: Date.now() + maxAge + } + } + + /** + * @param {string} uuid + */ + const get = (uuid) => { + if (uuid in memStore) { + let s = memStore[uuid]; + if (Date.now() < s.age) { + s.age = Date.now() + maxAge; + return s.obj; + } else { + delete memStore[uuid]; + } + } + return null; + } + + /** + * @param {string} uuid + */ + const chkKey = (uuid) => { + if (uuid in memStore) return true; + return false; + } + + /** + * @param {string} uuid + */ + const del = (uuid) => { + if (uuid in memStore) delete memStore[uuid]; + } + + const clear = () => { + let t = Date.now(); + for (var i in memStore) { + let s = memStore[i]; + if (s.age < t) delete memStore[i]; + } + } + + /** + * @param {string} uuid if not input return all + */ + const show = (uuid) => { + if (uuid && uuid in memStore) return memStore[uuid]; + + return memStore; + } + + return {set, get, chkKey, clear, del, show }; +})() + +module.exports = StoreObj; \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..630ddbe --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "node-conoha-ddns", + "version": "1.0.0", + "description": "ConoHa DNS API DDNS腳本", + "main": "app.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://git.trj.tw/nodejs/conoha-ddns.git" + }, + "keywords": [], + "author": "UrWind", + "license": "MIT", + "dependencies": { + "request": "^2.81.0" + } +}