Implementation of 'get_real_ip'.
[gandi_dns_update.git] / src / main.rs
1 /*
2 * API Reference: https://api.gandi.net/docs/livedns/
3 * Some inspiration: https://github.com/rmarchant/gandi-ddns/blob/master/gandi_ddns.py
4 */
5
6 use std::{ thread, time, fs::File, net::{ IpAddr, Ipv4Addr } };
7 use ron::{ de::from_reader, ser::to_writer };
8 use serde::{ Deserialize, Serialize };
9
10 type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
11
12 #[derive(Debug)]
13 struct GetRealIpError;
14
15 impl std::fmt::Display for GetRealIpError {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 write!(f, "SuperErrorSideKick is here!")
18 }
19 }
20
21 impl std::error::Error for GetRealIpError {}
22
23 #[derive(Debug, Deserialize, Serialize)]
24 struct Config {
25 delay_between_check: time::Duration,
26 api_key: String,
27 }
28
29 impl Config {
30 fn default() -> Self {
31 Config { delay_between_check: time::Duration::from_secs(60), api_key: String::from("") }
32 }
33
34 fn read(file_path: &str) -> Result<Config> {
35 match File::open(file_path) {
36 Ok(file) => from_reader(file).map_err(|e| e.into()),
37 // The file doesn't exit -> create it with default values.
38 Err(_) => {
39 let file = File::create(file_path)?;
40 let default_config = Config::default();
41 to_writer(file, &default_config)?;
42 Ok(default_config)
43 }
44 }
45 }
46 }
47
48 const FILE_CONF: &str = "config.ron";
49
50 fn main() -> Result<()> {
51 println!("GANDI DynDNS");
52
53 let config = Config::read(FILE_CONF)?;
54
55 println!("Configuration: {:?}", config);
56
57 loop {
58 let time_beginning_loop = time::Instant::now();
59
60 check_and_update_dns(&config.api_key);
61
62 let elapsed = time::Instant::now() - time_beginning_loop;
63
64 if elapsed < config.delay_between_check {
65 let to_wait = config.delay_between_check - elapsed;
66 thread::sleep(to_wait);
67 }
68
69 }
70 }
71
72 fn check_and_update_dns(api_key: &str) {
73 /*
74 let url = "https://api.gandi.net/v5/livedns/domains";
75 let client = reqwest::blocking::Client::new();
76
77 match client.get(url).header("Authorization", format!("Apikey {}", api_key)).send() {
78 Ok(resp) =>
79 if resp.status().is_success() {
80 let content = resp.text().unwrap();
81 println!("Content:\n{:?}", content);
82 } else {
83 println!("Request unsuccessful:\n{:#?}", resp);
84 },
85 Err(error) =>
86 println!("Error during request: {:?}", error)
87 }
88 */
89 dbg!(get_real_ip());
90 }
91
92 fn get_real_ip() -> Result<Ipv4Addr> {
93
94 let url = "https://api.ipify.org";
95 let client = reqwest::blocking::Client::new();
96
97 match client.get(url).send() {
98 Ok(resp) =>
99 if resp.status().is_success() {
100 let content = resp.text().unwrap();
101 match content.parse::<IpAddr>() {
102 Ok(IpAddr::V4(ip_v4)) => Ok(ip_v4),
103 /*Err(_)*/ _ => Err(Box::new(GetRealIpError))
104 }
105 //println!("Content:\n{:?}", content);
106 } else {
107 println!("Request unsuccessful:\n{:#?}", resp);
108 Err(Box::new(GetRealIpError))
109 },
110
111 Err(error) => {
112 println!("Error during request: {:?}", error);
113 Err(Box::new(GetRealIpError))
114 }
115 }
116 }
117
118 fn get_current_record_ip() {
119
120 }
121
122 fn update_record_ip() {
123
124 }