first version
This commit is contained in:
commit
a5d307f435
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
config.json
|
||||||
|
node_modules
|
107
app.js
Normal file
107
app.js
Normal 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
17
config.sample.json
Normal 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
68
libs/storeObject.js
Normal 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
19
package.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user