Skip to content

Commit

Permalink
no-ip-refresher first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Falldog committed Jun 17, 2017
1 parent e81082b commit 383b1bb
Show file tree
Hide file tree
Showing 6 changed files with 266 additions and 0 deletions.
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM selenium/standalone-firefox:3.4.0
LABEL authors=Falldog

RUN sudo mkdir -p /code \
sudo chown seluser /code

COPY requirement.txt /code/requirement.txt
RUN sudo apt-get update -qqy \
&& sudo apt-get install -qqy python3-pip \
&& sudo pip3 install -r /code/requirement.txt

WORKDIR /code
COPY refresher.py refresher.py
COPY refresher.cfg refresher.cfg
COPY entry_point.sh entry_point.sh

CMD ["/code/entry_point.sh"]

44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
no-ip-refresher
=============
automatic refresh your no-ip domain name, without 30 days expiration
use [docker-selenium](https://github.com/SeleniumHQ/docker-selenium) to manipulate no-ip with selenium


Requirement
-------
[docker](https://www.docker.com/)


Installation & Configuration
-------
clone source code
```sh
git clone https://github.com/Falldog/no-ip-refresher.git
```

modify configuration in `refresher.cfg`
Example as below:
```
[Refresher]
username=your-name
password=password
host=your-host.ddns.net
```

Refresh in docker
-------
```sh
cd no-ip-refresher
docker build -t no-ip-refresher .
docker run no-ip-refresher
```


crontab
-------
schedule it in crontab
avoid expiration after 30 days
```sh
0 0 1,15 * * root docker run no-ip-refresher # 1st & 15th day every month
```

31 changes: 31 additions & 0 deletions entry_point.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash
SCREEN_WIDTH=1920
SCREEN_HEIGHT=1080

source /opt/bin/functions.sh

export GEOMETRY="$SCREEN_WIDTH""x""$SCREEN_HEIGHT""x""$SCREEN_DEPTH"

function shutdown {
kill -s SIGTERM $NODE_PID
wait $NODE_PID
}

if [ ! -z "$SE_OPTS" ]; then
echo "appending selenium options: ${SE_OPTS}"
fi

SERVERNUM=$(get_server_num)

rm -f /tmp/.X*lock

xvfb-run -n $SERVERNUM --server-args="-screen 0 $GEOMETRY -ac +extension RANDR" \
java ${JAVA_OPTS} -jar /opt/selenium/selenium-server-standalone.jar \
${SE_OPTS} &
NODE_PID=$!

/code/refresher.py

shutdown SIGTERM SIGINT
wait $NODE_PID

4 changes: 4 additions & 0 deletions refresher.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[Refresher]
username=user
password=password
host=your-host.ddns.net
167 changes: 167 additions & 0 deletions refresher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#!/usr/bin/env python3
import sys
import time
import requests
import subprocess
from os.path import join, exists, dirname, abspath
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait, Select
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

# python2+3
try:
import configparser
except:
import ConfigParser as configparser

CUR_DIR = abspath(dirname(__file__))


class NoIpRefresher(object):
def __init__(self, config):
self.browser = webdriver.Firefox(log_path='/dev/null')
self.wait = WebDriverWait(self.browser, 15)
self.username = config.get('Refresher', 'username')
self.password = config.get('Refresher', 'password')
self.host = config.get('Refresher', 'host')
self.ip = self.get_public_ip()

def get_public_ip(self):
resp = requests.get('http://ipinfo.io/ip')
ip = resp.text.strip()
print('public ip: %s' % ip)
return ip

def process(self):
self.login()
self.remove_exists_host()
self.add_host()
self.browser.quit()

def login(self):
print('try to login')
self.browser.get('https://www.noip.com/login')
time.sleep(2)

elem = self.browser.find_element_by_css_selector('#clogs > input[name=username]')
elem.clear()
elem.send_keys(self.username)

elem = self.browser.find_element_by_css_selector('#clogs > input[name=password]')
elem.clear()
elem.send_keys(self.password)

elem = self.browser.find_element_by_css_selector('#clogs > button').click()

self.wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#main-navbar-collapse a.user-menu > i.fa-user')))
print('login success!')

def remove_exists_host(self):
print('remove_exists_host')
self.browser.get('https://my.noip.com/#!/dynamic-dns')
time.sleep(2)

elem = self.browser.find_element_by_css_selector('#host-panel > table')
tbody = elem.find_element_by_tag_name('tbody')
for tr in tbody.find_elements_by_tag_name('tr'):
try:
host = tr.find_element_by_css_selector('td[data-title="Host"] > a').text
ip = tr.find_element_by_css_selector('td[data-title="IP / Target"]').text
remove_btn = tr.find_element_by_css_selector('td.host-remove-col > div')
except NoSuchElementException:
continue

print('exists host: %s, ip: %s' % (host, ip))

if host == self.host:
remove_btn.click()
time.sleep(1)

ok_btn = self.browser.find_element_by_css_selector('body > div.bootbox-confirm div.modal-footer > button.btn-primary')
ok_btn.click()
break

def add_host(self):
print('add_host')
idx = self.host.index('.')
domain_name = self.host[:idx]
domain_suffix = self.host[idx+1:]

self.browser.get('https://www.noip.com/members/dns/host.php')
time.sleep(2)

# domain name
self.wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#hostname')))
time.sleep(1)
elem = self.browser.find_element_by_css_selector('#hostname')
elem.clear()
elem.send_keys(domain_name)

# IP
elem = self.browser.find_element_by_css_selector('#ip')
elem.clear()
elem.send_keys(self.ip)

# domain suffix
select = Select(self.browser.find_element_by_css_selector('select[name="host[domain]"]'))
select.select_by_visible_text(domain_suffix)

submit = self.browser.find_element_by_css_selector('input[type=submit]')
self.browser.execute_script("arguments[0].scrollIntoView();", submit)
submit.click()

self.wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#right-inner > div.successbox')))
print('add host: %s success' % self.host)

def add_host_new_design(self):
print('add_host')
idx = self.host.index('.')
domain_name = self.host[:idx]
domain_suffix = self.host[idx+1:]

# self.browser.get('https://my.noip.com/#!/dynamic-dns')
# time.sleep(2)

add_host_btn = self.browser.find_element_by_css_selector('#host-panel > div.panel-footer > div > button')
add_host_btn.click()

# domain name
self.wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#name')))
time.sleep(1)
elem = self.browser.find_element_by_css_selector('#name')
elem.clear()
elem.send_keys(domain_name)

# IP
elem = self.browser.find_element_by_css_selector('#host-modal .modal-body input[name=target]')
elem.clear()
elem.send_keys(self.ip)

# domain suffix
elem = self.browser.find_element_by_css_selector('#host-modal .modal-body select[name=domain] + div')
elem.click()
self.wait.until(EC.visibility_of(elem.find_element_by_css_selector('.chosen-search')))
elem.send_keys(domain_suffix)
time.sleep(1)
elem.find_element_by_css_selector('.chosen-results .active-result').click()

self.wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#host-modal div.modal-footer > button.btn-primary')))

elem.send_keys(Keys.ENTER)


if __name__ == '__main__':
config_file = join(CUR_DIR, 'refresher.cfg')
if not exists(config_file):
sys.exit("refresher.cfg doesn't exists")

with open(config_file, 'r') as f:
config = configparser.ConfigParser()
config.readfp(f)
refresher = NoIpRefresher(config)
refresher.process()

2 changes: 2 additions & 0 deletions requirement.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
selenium==3.4.3
requests

0 comments on commit 383b1bb

Please sign in to comment.