From b08a181cf34e179b87767cfb3d84fff2ef1a39e7 Mon Sep 17 00:00:00 2001 From: sipp11 Date: Sun, 18 Mar 2018 17:47:46 +0900 Subject: [PATCH] Init --- .gitignore | 4 +++ README.md | 19 ++++++++++++ update.py | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 update.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6a142df --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.vscode +.DS_Store +settings.conf +test.py \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..fccf08f --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# Namesilo updater + +## Prerequisite + +`NAMESILO_API` in environment variable + +`settings.conf` in the same directory + +[default] +domain=example.com +subdomain=dynamic + +### Python3 library + +You probably don't need anything extra from python3. Tested on python 3.5.2 and 3.6.4 + +## What to make this works? + +Adding `python3 update.py` to crontab should do the trick. Once a day should be enough IMHO. diff --git a/update.py b/update.py new file mode 100644 index 0000000..a4e9d76 --- /dev/null +++ b/update.py @@ -0,0 +1,88 @@ +import configparser +import os +import sys + +import xml.etree.ElementTree as ET +from requests import get + +BASE_URL = 'https://www.namesilo.com/api/dnsUpdateRecord?version=1&type=xml&' +UPDATE_URL = '{base}key={key}&domain={domain}&rrid={rrid}&' \ + 'rrhost={host}&rrvalue={new_value}&rrttl=7207' +LIST_URL = '{base}key={key}&domain={domain}' + +EVERYDAY_IP_SERVICE = 'https://tool.everyday.in.th/ip?format=text' + +'''Updater procedure +1. Getch a new public IP +2. Get a namesilo's DNS +3. check if 1 & 2 are different, then Update +''' + + +def get_public_ip(): + '''Get current public IP + + return IP or None + ''' + res = get(EVERYDAY_IP_SERVICE) + if res.status_code != 200: + return None + return res.text.strip() + +def get_namesilo_dns(key, domain, target_host): + res = get(LIST_URL.format(base=BASE_URL, key=key, domain=domain)) + if res.status_code != 200: + return None + tree = ET.fromstring(res.text.strip()) + for i in tree.iter('resource_record'): + host = i.find('./host').text + if host == target_host: + return { + 'rrid': i.find('./host').text, + 'value': i.find('./value').text, + 'host': host, + } + break + return {} + + +def update_namesilo_data(key, domain, rrid, subdomain, new_value): + res = get(UPDATE_URL.format(base=BASE_URL, key=key, domain=domainม + rrid=rrid, host=host, new_value=new_value)) + if res.status_code != 200: + return None + return True + + +def main(): + api_key = os.environ['NAMESILO_API'] + if not api_key: + print('NAMESILO_API in env is not found.') + sys.exit() + print('KEY: {}...'.format(api_key[:3])) + config = configparser.ConfigParser() + config.read('settings.conf') + domain = config['default']['domain'] + subdomain = config['default']['subdomain'] + target = '{}.{}'.format(subdomain, domain) + print('TARGET: {}'.format(target)) + public_ip = get_public_ip() + print('PUBLIC IP: {}..'.format(public_ip[:-5])) + namesilo_data = get_namesilo_dns(api_key, domain, target) + if not namesilo_data: + print('NAMESILO API service is down or target not found') + sys.exit() + + if namesilo_data['value'] == public_ip: + print('Current value is okay. No need to do anything') + sys.exit() + + rrid = namesilo_data['rrid'] + result = update_namesilo_data(api_key, domain, rrid, subdomain, public_ip) + if not result: + print('Updating process failed.') + sys.exit() + print('Updated to a new IP: {}'.format(public_ip)) + +if __name__ == '__main__': + main()