-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
142 lines (113 loc) · 3.25 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"time"
"github.com/gorilla/mux"
"github.com/rdegges/go-ipify"
"github.com/robfig/cron"
"github.com/spf13/viper"
)
var (
version = "dev"
embedUseOS = true
)
// ServerConfig holds server global config values
type ServerConfig struct {
// port the application server will listen on
ListenPort string
// the app version
Version string
// PathPrefix allows the application to be run on a shared domain
PathPrefix string
}
type server struct {
config *ServerConfig
router *mux.Router
}
var jsonFilePath string
// getJSONFilePath gets the jsonFilePath string
func getJSONFilePath() string {
return jsonFilePath
}
// setJSONFilePath sets the jsonFilePath string
func setJSONFilePath(path string) {
jsonFilePath = path
}
// postToGoogleDNS makes a call to GoogleDomains DDNS with provided hostname details
// and the current WAN IP as provided, then attempts to read the response from Google
// and logs the result or error
func postToGoogleDNS(username string, password string, domain string, ip string) {
log.Println("Domain: ", domain)
var endpoint = fmt.Sprintf("https://%s:%s@domains.google.com/nic/update?hostname=%s&myip=%s", username, password, domain, ip)
resp, err := http.Get(endpoint)
if err != nil {
log.Println(err)
}
body, readErr := ioutil.ReadAll(resp.Body)
if readErr != nil {
log.Println(readErr)
}
log.Println(string(body))
}
// attemptIPAddressUpdates gets the hostnames from JSON file
// and loops through calling postToGoogleDNS to attempt
// to update the record on Google Domains DDNS
func attemptIPAddressUpdates() {
var hostnames = getHostnamesFromJSON()
ip, err := ipify.GetIp()
if err != nil {
log.Println(err)
} else {
for _, hostname := range hostnames.Hostnames {
postToGoogleDNS(hostname.Username, hostname.Password, hostname.Domain, ip)
}
}
}
// func respondWithError(w http.ResponseWriter, code int, message string) {
// respondWithJSON(w, code, map[string]string{"error": message})
// }
// respondWithJSON takes a payload and writes the response
func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) {
response, _ := json.Marshal(payload)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
w.Write(response)
}
func main() {
log.Println("Google Domains DDNS Updater version " + version)
embedUseOS = len(os.Args) > 1 && os.Args[1] == "live"
InitConfig()
pathPrefix := viper.GetString("http.path_prefix")
router := mux.NewRouter()
if pathPrefix != "" {
router = router.PathPrefix(pathPrefix).Subrouter()
}
setJSONFilePath(viper.GetString("config.json_path"))
var cadence = viper.GetString("config.cadence")
c := cron.New()
c.AddFunc(cadence, attemptIPAddressUpdates)
c.Start()
s := &server{
config: &ServerConfig{
ListenPort: viper.GetString("http.port"),
Version: version,
PathPrefix: pathPrefix,
},
router: router,
}
s.routes()
srv := &http.Server{
Handler: s.router,
Addr: fmt.Sprintf(":%s", s.config.ListenPort),
// Good practice: enforce timeouts for servers you create!
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
log.Println("Access the WebUI via 127.0.0.1:" + s.config.ListenPort)
log.Fatal(srv.ListenAndServe())
}