Compare commits

..

4 Commits

Author SHA1 Message Date
adb
5d966f422a add configProxy and update config.json 2021-03-31 21:42:23 +02:00
adb
1eb45bbe8c fix interval 2021-03-31 21:41:42 +02:00
adb
2a9f5873ff add docker-compose 2021-03-31 21:41:03 +02:00
adb
bb383094f7 add sendSignedRequest, getConsumerKey, getSignature 2021-03-31 21:40:49 +02:00
6 changed files with 105 additions and 31 deletions

View File

@ -18,14 +18,15 @@ export class DynDnsBot{
}); });
} }
setInterval(seconds = this.config.updateInterval, random = this.config.randomInterval){ setInterval(seconds = this.config.updateInterval, random = this.config.randomInterval){
this.interval = setInterval(random let handler = (callback) => random
?setTimeout(this.update, Math.random()*seconds*1000) ?()=>setTimeout(callback, Math.random()*seconds*1000)
:this.update, :callback;
seconds*1000); this.interval = setInterval(handler(this.update), seconds*1000);
this.update();
} }
async getIp(){ async getIp(){
return await rest.get(this.config.ipApi).then(newIp => { return await rest.get(this.config.ipApi).then(res => {
return newIp; return JSON.parse(res.text);
}).catch(console.error); }).catch(console.error);
} }
} }

View File

@ -1,37 +1,73 @@
import rest from 'superagent'; import rest from 'superagent';
import sha1 from 'sha1';
import readline from 'readline';
export class OvhApi{ export class OvhApi{
async constructor({credentials}){ constructor({credentials}){
this.credentials = credentials; this.credentials = credentials;
this.baseUrl = credentials.apiUrl; this.baseUrl = this.credentials.apiUrl;
this.apiToken = await this.getToken({applicationKey: credentials.applicationKey}); this.methods = {get: 'GET', post: 'POST', put: 'PUT', delete: 'DELETE', path: 'PATCH'};
this.rl = readline.createInterface({
input: process.stdin
});
} }
async sendRequest({ async sendRequest({
path, path,
obj={}, body={},
method=rest=>rest.get, getMethod=rest=>rest.get,
header={accept: 'json'} header={accept: 'json'}
}){ }){
let request = method(rest)(`${this.baseUrl}${path}`); console.log(`api request at ${path} =>`);
console.log(header);
console.log(body);
let request = getMethod(rest)(`${this.baseUrl}${path}`);
await Object.keys(header).forEach(key => request.set(key, header[key])); await Object.keys(header).forEach(key => request.set(key, header[key]));
return await request.send(obj).then(res => { return await request.send(body).then(res => {
console.log('api response =>');
console.log(JSON.parse(res.text));
return JSON.parse(res.text); return JSON.parse(res.text);
}).catch(err => { }).catch(err => {
console.log(err); console.error(err);
return false; return false;
}); });
} }
async getToken({applicationKey}){ async sendSignedRequest({
return await this.sendRequest({ path,
body={},
getMethod=rest=>rest.get,
header={accept: 'json'}
}){
if (!this.credentials.consumerKey) await this.getConsumerKey();
let timestamp = await this.getApiTime();
header['X-Ovh-Timestamp'] = timestamp;
header['X-Ovh-Signature'] = await this.getSignature({
method: getMethod(this.methods),
query: this.baseUrl+path,
body, timestamp
});
header['X-Ovh-Consumer'] = this.credentials.consumerKey;
await this.sendRequest({path, body, getMethod, header});
}
async getSignature({method = 'GET', query, body='', timestamp}){
return '$1$' + sha1(
this.credentials.applicationSecret+'+'+
this.credentials.consumerKey+'+'+
method+'+'+query+'+'+body+'+'+timestamp
);
}
async getConsumerKey(){
let res = await this.sendRequest({
path: '/auth/credential', path: '/auth/credential',
method: rest=>rest.post, getMethod: rest=>rest.post,
header: { header: {
'X-Ovh-Application': applicationKey, 'X-Ovh-Application': this.credentials.applicationKey,
'Content-type': 'application/json' 'Content-type': 'application/json'
}, },
obj: { body: {
accessRules: [ accessRules: [
{method: 'GET', path: '/domain/zone/*'}, {method: 'GET', path: '/domain/zone/*'},
{method: 'POST', path: '/domain/zone/*'}, {method: 'POST', path: '/domain/zone/*'},
@ -39,17 +75,28 @@ export class OvhApi{
] ]
} }
}); });
} this.credentials.consumerKey = res.consumerKey;
console.log('please validate on ovh site:');
async updateRecord({domain, subDomain, recordId, target, ttl = 3600}){ console.log(res.validationUrl);
return await this.sendRequest({ await this.rl.question('continue? (Y/n)', () => {
path: `/domain/zone/${domain}/record/${recordId}`, switch (input) {
method: rest=>rest.put, case 'n': process.exit(); break;
obj: { default: return res.consumerKey;
subDomain,
target,
ttl
} }
}); });
} }
async updateRecord({domain, subDomain, recordId, target, ttl = 3600}){
return await this.sendSignedRequest({
path: `/domain/zone/${domain}/record/${recordId}`,
getMethod: rest=>rest.put,
body: {subDomain, target, ttl}
});
}
async getApiTime(){
return await this.sendRequest({
path: '/auth/time'
});
}
} }

13
docker-compose.yml Normal file
View File

@ -0,0 +1,13 @@
version: '3'
services:
node:
image: node:alpine
container_name: ovh-api-dyndns
restart: always
volumes:
- ./:/home/node/app/
- ./node_logs/:/var/log/
working_dir: /home/node/app/
environment:
- NODE_ENV=production
command: sh -c 'npm i && nodejs index.js'

View File

@ -10,6 +10,7 @@
}], }],
"ovhCredentials": { "ovhCredentials": {
"applicationKey": "", "applicationKey": "",
"applicationSecret": "",
"apiUrl": "https://ca.api.ovh.com/1.0" "apiUrl": "https://ca.api.ovh.com/1.0"
} }
} }

View File

@ -1,5 +1,16 @@
import {DynDnsBot} from './DynDnsBot.js'; import {DynDnsBot} from './DynDnsBot.js';
import {loadData} from './jsonDataStore.js'; import {loadData, storeData} from './jsonDataStore.js';
let bot = new DynDnsBot({config: loadData('config.json')}); let configPath = 'config.json';
let config = loadData(configPath);
let configProxy = new Proxy(config, {
set: (target, key, value) => {
console.log(`config changed: ${key} set from ${target[key]} to ${value}`);
target[key] = value;
storeData(config, configPath);
return true;
}
});
let bot = new DynDnsBot({config: configProxy});
bot.setInterval(); bot.setInterval();

View File

@ -11,6 +11,7 @@
"author": "adb", "author": "adb",
"license": "", "license": "",
"dependencies": { "dependencies": {
"sha1": "^1.1.1",
"superagent": "^6.1.0" "superagent": "^6.1.0"
}, },
"devDependencies": { "devDependencies": {