From 1b193248ed097fac370d01858856d061d92e6b9d Mon Sep 17 00:00:00 2001 From: adb Date: Tue, 30 Mar 2021 23:40:33 +0200 Subject: [PATCH] add project files --- .eslintrc.js | 31 +++++++++++++++++++++++++ .gitignore | 1 + DynDnsBot.js | 31 +++++++++++++++++++++++++ OvhApi.js | 55 +++++++++++++++++++++++++++++++++++++++++++++ example.config.json | 15 +++++++++++++ index.js | 5 +++++ jsonDataStore.js | 25 +++++++++++++++++++++ package.json | 19 ++++++++++++++++ 8 files changed, 182 insertions(+) create mode 100644 .eslintrc.js create mode 100644 .gitignore create mode 100644 DynDnsBot.js create mode 100644 OvhApi.js create mode 100644 example.config.json create mode 100644 index.js create mode 100644 jsonDataStore.js create mode 100644 package.json diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..3673603 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,31 @@ +module.exports = { + "env": { + "browser": true, + "es6": true + }, + "extends": [ + "eslint:recommended", + ], + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module" + }, + "rules": { + "indent": [ + "warn", + 2 + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "warn", + "single" + ] + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0cffcb3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.json \ No newline at end of file diff --git a/DynDnsBot.js b/DynDnsBot.js new file mode 100644 index 0000000..658a23f --- /dev/null +++ b/DynDnsBot.js @@ -0,0 +1,31 @@ +import {OvhApi} from './OvhApi.js'; +import rest from 'superagent'; + +export class DynDnsBot{ + constructor({config}){ + this.config = config; + this.dns = new OvhApi({credentials: config.ovhCredentials}); + this.lastIp = null; + } + + async update() { + let newIp = await this.getIp(); + if (newIp === this.lastIp) return; + this.lastIp = newIp; + this.config.records.forEach(record => { + record.target = newIp; + this.dns.updateRecord(record); + }); + } + setInterval(seconds = this.config.updateInterval, random = this.config.randomInterval){ + this.interval = setInterval(random + ?setTimeout(this.update, Math.random()*seconds*1000) + :this.update, + seconds*1000); + } + async getIp(){ + return await rest.get(this.config.ipApi).then(newIp => { + return newIp; + }).catch(console.error); + } +} \ No newline at end of file diff --git a/OvhApi.js b/OvhApi.js new file mode 100644 index 0000000..c190f97 --- /dev/null +++ b/OvhApi.js @@ -0,0 +1,55 @@ +import rest from 'superagent'; + +export class OvhApi{ + async constructor({credentials}){ + this.credentials = credentials; + this.baseUrl = credentials.apiUrl; + this.apiToken = await this.getToken({applicationKey: credentials.applicationKey}); + } + + async sendRequest({ + path, + obj={}, + method=rest=>rest.get, + header={accept: 'json'} + }){ + let request = method(rest)(`${this.baseUrl}${path}`); + await Object.keys(header).forEach(key => request.set(key, header[key])); + return await request.send(obj).then(res => { + return JSON.parse(res.text); + }).catch(err => { + console.log(err); + return false; + }); + } + + async getToken({applicationKey}){ + return await this.sendRequest({ + path: '/auth/credential', + method: rest=>rest.post, + header: { + 'X-Ovh-Application': applicationKey, + 'Content-type': 'application/json' + }, + obj: { + accessRules: [ + {method: 'GET', path: '/domain/zone/*'}, + {method: 'POST', path: '/domain/zone/*'}, + {method: 'PUT', path: '/domain/zone/*'} + ] + } + }); + } + + async updateRecord({domain, subDomain, recordId, target, ttl = 3600}){ + return await this.sendRequest({ + path: `/domain/zone/${domain}/record/${recordId}`, + method: rest=>rest.put, + obj: { + subDomain, + target, + ttl + } + }); + } +} \ No newline at end of file diff --git a/example.config.json b/example.config.json new file mode 100644 index 0000000..92a5a7a --- /dev/null +++ b/example.config.json @@ -0,0 +1,15 @@ +{ + "ipApi": "https://api.ipify.org/", + "updateInterval": 300, + "randomInterval": true, + "records": [{ + "domain": "foo.bar", + "subDomain": "foo.foo.bar", + "recordId": 0, + "ttl": 300 + }], + "ovhCredentials": { + "applicationKey": "", + "apiUrl": "https://ca.api.ovh.com/1.0" + } +} \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..1cbcd84 --- /dev/null +++ b/index.js @@ -0,0 +1,5 @@ +import {DynDnsBot} from './DynDnsBot.js'; +import {loadData} from './jsonDataStore.js'; + +let bot = new DynDnsBot({config: loadData('config.json')}); +bot.setInterval(); \ No newline at end of file diff --git a/jsonDataStore.js b/jsonDataStore.js new file mode 100644 index 0000000..0f313f0 --- /dev/null +++ b/jsonDataStore.js @@ -0,0 +1,25 @@ +import fs from "fs"; + +export function storeData(data, path) { + try { + fs.writeFileSync(path, JSON.stringify(data)); + } catch (err) { + console.error(err); + } +} +export function loadData(path) { + try { + return JSON.parse(fs.readFileSync(path, 'utf8')) + } catch (err) { + console.error(err) + return false + } +} +export function getStat(path) { + try { + return fs.existsSync(path) === true; + } catch(err) { + console.error(err) + return false; + } +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..a64519b --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "ovh-api-dyndns", + "version": "1.0.0", + "description": "", + "main": "index.js", + "type": "module", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "adb", + "license": "", + "dependencies": { + "superagent": "^6.1.0" + }, + "devDependencies": { + "eslint": "^6.7.2" + } +}