first version

This commit is contained in:
Jay 2017-03-13 22:25:23 +08:00
commit a5d307f435
5 changed files with 213 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
config.json
node_modules

107
app.js Normal file
View File

@ -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);

17
config.sample.json Normal file
View File

@ -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"
]
}]
}

68
libs/storeObject.js Normal file
View File

@ -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;

19
package.json Normal file
View File

@ -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"
}
}