-
-
Save chrsan/d59f219cfccc196e4c35 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
// Fetch dependencies: go get golang.org/x/net/html | |
// Run as a shell script: go run joker.go -h | |
// Build as a static binary: go build joker.go && ./joker -h | |
// | |
// '-h' displays the command line flags | |
// | |
// Author: chrsan | |
import ( | |
"flag" | |
"fmt" | |
"io/ioutil" | |
"log" | |
"net/http" | |
"net/url" | |
"os" | |
"strings" | |
"golang.org/x/net/html" | |
) | |
// Walk the node n to find the IP address text. | |
func extractIP(n *html.Node) (string, bool) { | |
if n.Type == html.TextNode && strings.HasPrefix(n.Data, `Current IP Address:`) { | |
return strings.TrimPrefix(n.Data, `Current IP Address: `), true | |
} | |
// Traverse the child nodes. | |
for c := n.FirstChild; c != nil; c = c.NextSibling { | |
if s, found := extractIP(c); found { | |
return strings.TrimSpace(s), true | |
} | |
} | |
return "", false | |
} | |
// Fetch the current IP address. | |
func fetchIP() (string, bool) { | |
res, err := http.Get("https://svc.joker.com/nic/checkip") | |
if err != nil { | |
log.Fatal(err) | |
} | |
defer res.Body.Close() | |
doc, err := html.Parse(res.Body) | |
if err != nil { | |
log.Fatal(err) | |
} | |
return extractIP(doc) | |
} | |
// Struct holding the old IP address and file it was read from. | |
type oldIPFile struct { | |
file *os.File | |
ip string | |
} | |
// Open the file containing the old IP address. | |
func openOldIPFile(path string) *oldIPFile { | |
if f, err := os.OpenFile(path, os.O_RDWR, 0); err != nil { | |
// The file didn't exist, let's create it. | |
f, err := os.Create(path) | |
if err != nil { | |
log.Fatal(err) | |
} | |
return &oldIPFile{file: f} | |
} else { | |
// The file did exist, read its content. | |
b, err := ioutil.ReadAll(f) | |
if err != nil { | |
log.Fatal(err) | |
} | |
return &oldIPFile{file: f, ip: strings.TrimSpace(string(b))} | |
} | |
} | |
// Write the IP address to the file pointed to. | |
func (f *oldIPFile) write() error { | |
if err := f.file.Truncate(0); err != nil { | |
return err | |
} | |
if n, err := f.file.WriteString(f.ip); err != nil { | |
return err | |
} else if n != len(f.ip) { | |
return fmt.Errorf("Could not write %d expected bytes to %s", n, f.file.Name()) | |
} | |
return nil | |
} | |
// Update the DNS | |
func updateDNS(ip, username, password, domain string) { | |
r, err := http.NewRequest("GET", "https://svc.joker.com/nic/update", nil) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// URL parameters | |
v := url.Values{} | |
v.Set("myip", ip) | |
v.Set("username", username) | |
v.Set("password", password) | |
v.Set("hostname", domain) | |
v.Set("wildcard", "NOCHG") | |
v.Set("mx", "NOCHG") | |
v.Set("backmx", "NOCHG") | |
r.Form = v | |
resp, err := http.DefaultClient.Do(r) | |
if err != nil { | |
log.Fatal(err) | |
} | |
if resp.StatusCode != http.StatusOK { | |
log.Fatal("Failed to update DNS provider") | |
} | |
} | |
// Command line flags. | |
var ( | |
oldIpFileFlag = flag.String("f", "", "path to old IP file") | |
usernameFlag = flag.String("u", "", "username") | |
passwordFlag = flag.String("p", "", "password") | |
domainFlag = flag.String("d", "", "domain") | |
) | |
// Check that none of the command line flag values are empty. | |
func checkFlags() bool { | |
for _, f := range []*string{oldIpFileFlag, usernameFlag, passwordFlag, domainFlag} { | |
if *f == "" { | |
return false | |
} | |
} | |
return true | |
} | |
func main() { | |
flag.Parse() | |
// Check the command line flags state. | |
if flag.NFlag() != 4 || flag.NArg() != 0 || !checkFlags() { | |
flag.Usage() | |
os.Exit(1) | |
} | |
ip, ok := fetchIP() | |
if !ok { | |
log.Fatal("Could not determine IP address") | |
} | |
log.Printf("Fetched IP address: %s\n", ip) | |
old := openOldIPFile(*oldIpFileFlag) | |
defer old.file.Close() | |
if ip == old.ip { | |
log.Printf("Same IP address: %s\n", ip) | |
} else { | |
log.Printf("%q != %q, updating DNS\n", ip, old.ip) | |
old.ip = ip | |
if err := old.write(); err != nil { | |
log.Fatal(err) | |
} | |
// TODO: Uncomment the line below to do the real thing | |
// updateDNS(ip, *usernameFlag, *passwordFlag, *domainFlag) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Fetching IP adress from joker.com | |
# Format: <html><head><title>Current IP Check</title></head><body>Current IP Address: 88.80.167.132</body></html> | |
function fetchIP { | |
local _returnParam=$1 | |
local _response=$(curl --silent https://svc.joker.com/nic/checkip) | |
local _exit_code=$? | |
if [ $_exit_code -ne 0 ]; then | |
( | |
logger "Faild to fetch new IP adress" | |
) | |
fi | |
eval $_returnParam="'$_response'" | |
} | |
# Extract IP adress from response | |
function extractIP { | |
local _returnParam=$1 # <html><head><title>Current IP Check</title></head><body>Current IP Address: 88.80.167.132</body></html> | |
local _current_ip=$(echo $2 | sed -n -e 's/.*IP Address: \([0-9\.]*\).*/\1/p') | |
local _exit_code=$? | |
if [ $_exit_code -ne 0 ]; then | |
logger "[WARNING] Faild to match IP number" | |
fi | |
eval $_returnParam="$_current_ip" | |
} | |
# Fetching old IP from file | |
function oldIP { | |
local _returnParam=$1 | |
local _file=$2 | |
if [ ! -f "$_file" ]; then # Check if file exists | |
touch "$_file" # Create file | |
fi | |
eval $_returnParam="`cat $_file`" | |
} | |
# Update DNS Server | |
function updateDNS { | |
local _current_ip=$1 | |
local _updateResponse=$(curl --write-out %{http_code} --silent --output /dev/null $3) | |
local _update_exit_code=$? | |
if [ $_update_exit_code -ne 0 ]; then # Curl could not make the call | |
( | |
logger "[Warning] Failed to update DNS provider, exit code: $_update_exit_code" | |
) | |
else | |
( | |
if [ $_updateResponse -ne 200 ]; then # Response call was not 200 | |
( | |
logger "[Warning] Faild to update DNS provider, response code: $_updateResponse" | |
) | |
else | |
( | |
echo $_current_ip > $2 # Save current IP to file | |
logger "[Info] Old IP: $old_ip, New IP: $_current_ip" | |
) | |
fi | |
) | |
fi | |
} | |
# Main program | |
logger "[Info] DNS update started" | |
file="/usr/local/var/log/myip.file3" # Local storage for IP number | |
fetchIP response # Fetching the IP | |
extractIP currnet_ip "$response" # Extracting IP from response | |
oldIP old_ip "$file" # Read old IP adress from file | |
if [ "$currnet_ip" == "$old_ip" ]; then # Check if old and current IP are same | |
( | |
logger "[Info] Same IP adress: $old_ip" | |
) | |
else # They are not the same | |
( | |
updateDNS $currnet_ip $file "https://svc.joker.com/nic/update?username=<username>&password=<passowrd>&hostname=<domain>&myip=$currnet_ip&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG" | |
) | |
fi | |
logger "[Info] DNS update finished" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment